From e53e7fadc28a10683777bcc66c36aa76c1d3a21b Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Wed, 16 Mar 2011 23:13:54 -0500 Subject: [PATCH 001/397] 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 002/397] 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 003/397] 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 004/397] 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 005/397] 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 006/397] 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 007/397] 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 008/397] 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 009/397] 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 010/397] 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 011/397] 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 012/397] 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 013/397] 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 014/397] 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 015/397] 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 016/397] 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 017/397] 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 018/397] 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 019/397] 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 020/397] 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 021/397] 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 022/397] 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 023/397] 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 024/397] 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 025/397] 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 026/397] 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 027/397] 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 028/397] 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 029/397] 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 030/397] 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 031/397] 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 032/397] 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 033/397] 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 034/397] 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 035/397] 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 036/397] 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 037/397] 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 038/397] 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 039/397] 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 040/397] 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 041/397] 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 042/397] [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 043/397] 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 044/397] 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 045/397] 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 046/397] 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 047/397] 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 048/397] 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 049/397] 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 050/397] 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 051/397] 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 052/397] 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 053/397] 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 054/397] [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 055/397] 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 056/397] 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 057/397] 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 058/397] 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 059/397] 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 060/397] 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 061/397] 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 062/397] 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 063/397] 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 064/397] 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 065/397] 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 066/397] 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 067/397] 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 068/397] 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 069/397] 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 070/397] 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 071/397] 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 072/397] [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 073/397] 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 074/397] 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 075/397] 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 076/397] 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 077/397] [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 078/397] 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 079/397] 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 080/397] 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 081/397] 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 082/397] 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 083/397] 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 084/397] 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 085/397] 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 086/397] 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 087/397] 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 088/397] 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 089/397] 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 090/397] 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 091/397] 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 092/397] 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 093/397] 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 094/397] 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 095/397] 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 58f6f59b9e3f244aa5c825d9ca457649fcf9138a Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 6 Jul 2011 08:35:22 -0400 Subject: [PATCH 096/397] Revert two SCSI/block patches from 2.6.38.6; drop now-unneeded followon patches --- block-export-blk_-get-put-_queue.patch | 39 ----------------- block-queue-refcount.patch | 43 ------------------- kernel.spec | 14 ++++-- revert-fix-oops-in-scsi_run_queue.patch | 21 +++++++++ ...stricter-guards-on-queue-dead-checks.patch | 34 +++++++++++++++ 5 files changed, 65 insertions(+), 86 deletions(-) delete mode 100644 block-export-blk_-get-put-_queue.patch delete mode 100644 block-queue-refcount.patch create mode 100644 revert-fix-oops-in-scsi_run_queue.patch create mode 100644 revert-put-stricter-guards-on-queue-dead-checks.patch 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/kernel.spec b/kernel.spec index 5211df656..5b47d3bbe 100644 --- a/kernel.spec +++ b/kernel.spec @@ -664,8 +664,8 @@ 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 +Patch600: revert-fix-oops-in-scsi_run_queue.patch +Patch601: revert-put-stricter-guards-on-queue-dead-checks.patch Patch602: block-blkdev_get-should-access-bd_disk-only-after.patch Patch603: cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch @@ -1313,8 +1313,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 +# Revert SCSI patches from 2.6.38.6 that cause more problems thatn they solve +ApplyPatch revert-fix-oops-in-scsi_run_queue.patch +ApplyPatch revert-put-stricter-guards-on-queue-dead-checks.patch +# Fix potential NULL deref in 2.6.38.8 ApplyPatch block-blkdev_get-should-access-bd_disk-only-after.patch # rhbz#577968 ApplyPatch cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch @@ -2065,6 +2067,10 @@ fi # and build. %changelog +* Wed Jul 06 2011 Chuck Ebbert +- Revert SCSI/block patches from 2.6.38.6 that caused more problems + than they fixed; drop band-aid patch attempting to fix the fix. + * Mon Jun 27 2011 Dave Jones - Disable CONFIG_CRYPTO_MANAGER_DISABLE_TESTS, as this also disables FIPS (rhbz 716942) diff --git a/revert-fix-oops-in-scsi_run_queue.patch b/revert-fix-oops-in-scsi_run_queue.patch new file mode 100644 index 000000000..3170ed865 --- /dev/null +++ b/revert-fix-oops-in-scsi_run_queue.patch @@ -0,0 +1,21 @@ +revert c055f5b2614b4f758ae6cc86733f31fa4c2c5844 from 2.6.38.6 + +--- b/drivers/scsi/scsi_lib.c ++++ a/drivers/scsi/scsi_lib.c +@@ -400,15 +400,10 @@ + 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); + diff --git a/revert-put-stricter-guards-on-queue-dead-checks.patch b/revert-put-stricter-guards-on-queue-dead-checks.patch new file mode 100644 index 000000000..7acd4127b --- /dev/null +++ b/revert-put-stricter-guards-on-queue-dead-checks.patch @@ -0,0 +1,34 @@ +reverte 86cbfb5607d4b81b1a993ff689bbd2addd5d3a9b from 2.6.38.6 + +--- b/drivers/scsi/scsi_sysfs.c ++++ a/drivers/scsi/scsi_sysfs.c +@@ -322,8 +322,14 @@ + kfree(evt); + } + ++ if (sdev->request_queue) { ++ sdev->request_queue->queuedata = NULL; ++ /* user context needed to free queue */ ++ scsi_free_queue(sdev->request_queue); ++ /* temporary expedient, try to catch use of queue lock ++ * after free of sdev */ ++ sdev->request_queue = NULL; ++ } +- /* NULL queue means the device can't be used */ +- sdev->request_queue = NULL; + + scsi_target_reap(scsi_target(sdev)); + +@@ -931,12 +937,6 @@ + if (sdev->host->hostt->slave_destroy) + sdev->host->hostt->slave_destroy(sdev); + transport_destroy_device(dev); +- +- /* cause the request function to reject all I/O requests */ +- sdev->request_queue->queuedata = NULL; +- +- /* Freeing the queue signals to block that we're done */ +- scsi_free_queue(sdev->request_queue); + put_device(dev); + } + From 10aa0c1bf70fb514608f23a83b8388fff92ea63d Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 6 Jul 2011 09:13:22 -0400 Subject: [PATCH 097/397] CVE-2011-2497: kernel: bluetooth: buffer overflow in l2cap config request --- ...fer-overflow-in-l2cap-config-request.patch | 32 +++++++++++++++++++ kernel.spec | 7 ++-- 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch diff --git a/bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch b/bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch new file mode 100644 index 000000000..5cc80c72f --- /dev/null +++ b/bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch @@ -0,0 +1,32 @@ +From: Dan Rosenberg +Date: Fri, 24 Jun 2011 12:38:05 +0000 (-0400) +Subject: Bluetooth: Prevent buffer overflow in l2cap config request +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fpadovan%2Fbluetooth-2.6.git;a=commitdiff_plain;h=7ac28817536797fd40e9646452183606f9e17f71 + +Bluetooth: Prevent buffer overflow in l2cap config request +[ backport to 2.6.38 ] + +A remote user can provide a small value for the command size field in +the command header of an l2cap configuration request, resulting in an +integer underflow when subtracting the size of the configuration request +header. This results in copying a very large amount of data via +memcpy() and destroying the kernel heap. Check for underflow. + +Signed-off-by: Dan Rosenberg +Cc: stable +Signed-off-by: Gustavo F. Padovan +--- + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 56fdd91..7d8a66b 100644 +--- a/net/bluetooth/l2cap.c ++++ b/net/bluetooth/l2cap.c +@@ -3116,7 +3116,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr + + /* Reject if config buffer is too small. */ + len = cmd_len - sizeof(*req); +- if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) { ++ if (len < 0 || l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) { + l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, + l2cap_build_conf_rsp(sk, rsp, + L2CAP_CONF_REJECT, flags), rsp); diff --git a/kernel.spec b/kernel.spec index 5b47d3bbe..baa589c5d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -773,7 +773,7 @@ Patch12404: x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patc Patch12407: scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch Patch12416: bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch - +Patch12417: bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch Patch12418: ath5k-disable-fast-channel-switching-by-default.patch Patch12419: iwlagn-use-cts-to-self-protection-on-5000-adapters-series.patch @@ -1332,6 +1332,9 @@ ApplyPatch libata-sas-only-set-frozen-flag-if-new-eh-is-supported.patch ApplyPatch hda_intel-prealloc-4mb-dmabuffer.patch # Networking +ApplyPatch bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch +# CVE-2011-2497 +ApplyPatch bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch # Misc fixes # The input layer spews crap no-one cares about. @@ -1448,7 +1451,6 @@ 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 @@ -2070,6 +2072,7 @@ fi * Wed Jul 06 2011 Chuck Ebbert - Revert SCSI/block patches from 2.6.38.6 that caused more problems than they fixed; drop band-aid patch attempting to fix the fix. +- CVE-2011-2497: kernel: bluetooth: buffer overflow in l2cap config request * Mon Jun 27 2011 Dave Jones - Disable CONFIG_CRYPTO_MANAGER_DISABLE_TESTS, as this also disables FIPS (rhbz 716942) From 5d1e28000da6030596adf1806317b830b78e1843 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 6 Jul 2011 09:25:53 -0400 Subject: [PATCH 098/397] CVE-2011-2517: kernel: nl80211: missing check for valid SSID size in scan operations --- kernel.spec | 7 +++ ...r-valid-ssid-size-in-scan-operations.patch | 42 ++++++++++++++++++ nl80211-fix-overflow-in-ssid_len.patch.patch | 44 +++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 nl80211-fix-check-for-valid-ssid-size-in-scan-operations.patch create mode 100644 nl80211-fix-overflow-in-ssid_len.patch.patch diff --git a/kernel.spec b/kernel.spec index baa589c5d..f18675273 100644 --- a/kernel.spec +++ b/kernel.spec @@ -780,6 +780,9 @@ Patch12419: iwlagn-use-cts-to-self-protection-on-5000-adapters-series.patch Patch12420: crypto-aesni_intel-merge-with-fpu_ko.patch +Patch12430: nl80211-fix-check-for-valid-ssid-size-in-scan-operations.patch +Patch12431: nl80211-fix-overflow-in-ssid_len.patch.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1335,6 +1338,9 @@ ApplyPatch hda_intel-prealloc-4mb-dmabuffer.patch ApplyPatch bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch # CVE-2011-2497 ApplyPatch bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch +# CVE-2011-2517 +ApplyPatch nl80211-fix-check-for-valid-ssid-size-in-scan-operations.patch +ApplyPatch nl80211-fix-overflow-in-ssid_len.patch.patch # Misc fixes # The input layer spews crap no-one cares about. @@ -2073,6 +2079,7 @@ fi - Revert SCSI/block patches from 2.6.38.6 that caused more problems than they fixed; drop band-aid patch attempting to fix the fix. - CVE-2011-2497: kernel: bluetooth: buffer overflow in l2cap config request +- CVE-2011-2517: kernel: nl80211: missing check for valid SSID size in scan operations * Mon Jun 27 2011 Dave Jones - Disable CONFIG_CRYPTO_MANAGER_DISABLE_TESTS, as this also disables FIPS (rhbz 716942) diff --git a/nl80211-fix-check-for-valid-ssid-size-in-scan-operations.patch b/nl80211-fix-check-for-valid-ssid-size-in-scan-operations.patch new file mode 100644 index 000000000..f4b166c60 --- /dev/null +++ b/nl80211-fix-check-for-valid-ssid-size-in-scan-operations.patch @@ -0,0 +1,42 @@ +From: Luciano Coelho +Date: Wed, 18 May 2011 21:43:38 +0000 (+0300) +Subject: nl80211: fix check for valid SSID size in scan operations +X-Git-Tag: v3.0-rc2~7^2~16^2~12 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=208c72f4fe44fe09577e7975ba0e7fa0278f3d03 + +nl80211: fix check for valid SSID size in scan operations +[ 2.6.38 backport ] + +In both trigger_scan and sched_scan operations, we were checking for +the SSID length before assigning the value correctly. Since the +memory was just kzalloc'ed, the check was always failing and SSID with +over 32 characters were allowed to go through. + +This was causing a buffer overflow when copying the actual SSID to the +proper place. + +This bug has been there since 2.6.29-rc4. + +Cc: stable@kernel.org +Signed-off-by: Luciano Coelho +Signed-off-by: John W. Linville +--- + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index ec83f41..88a565f 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -3406,12 +3406,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) + i = 0; + if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) { + nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { ++ request->ssids[i].ssid_len = nla_len(attr); + if (request->ssids[i].ssid_len > IEEE80211_MAX_SSID_LEN) { + err = -EINVAL; + goto out_free; + } + memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr)); +- request->ssids[i].ssid_len = nla_len(attr); + i++; + } + } diff --git a/nl80211-fix-overflow-in-ssid_len.patch.patch b/nl80211-fix-overflow-in-ssid_len.patch.patch new file mode 100644 index 000000000..dcbf26b87 --- /dev/null +++ b/nl80211-fix-overflow-in-ssid_len.patch.patch @@ -0,0 +1,44 @@ +From: Luciano Coelho +Date: Tue, 7 Jun 2011 17:42:26 +0000 (+0300) +Subject: nl80211: fix overflow in ssid_len +X-Git-Tag: v3.0-rc4~5^2~13^2~6 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=57a27e1d6a3bb9ad4efeebd3a8c71156d6207536 + +nl80211: fix overflow in ssid_len +[ 2.6.38 backport ] + +When one of the SSID's length passed in a scan or sched_scan request +is larger than 255, there will be an overflow in the u8 that is used +to store the length before checking. This causes the check to fail +and we overrun the buffer when copying the SSID. + +Fix this by checking the nl80211 attribute length before copying it to +the struct. + +This is a follow up for the previous commit +208c72f4fe44fe09577e7975ba0e7fa0278f3d03, which didn't fix the problem +entirely. + +Reported-by: Ido Yariv +Signed-off-by: Luciano Coelho +Signed-off-by: John W. Linville +--- + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 88a565f..98fa8eb 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -3406,11 +3406,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) + i = 0; + if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) { + nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { +- request->ssids[i].ssid_len = nla_len(attr); +- if (request->ssids[i].ssid_len > IEEE80211_MAX_SSID_LEN) { ++ if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) { + err = -EINVAL; + goto out_free; + } ++ request->ssids[i].ssid_len = nla_len(attr); + memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr)); + i++; + } From c2a198def50551bcc15ea08d5710a8a662b76de4 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 6 Jul 2011 09:37:55 -0400 Subject: [PATCH 099/397] Bump version for build --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index f18675273..7bbad73f4 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 34 +%global baserelease 35 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2075,7 +2075,7 @@ fi # and build. %changelog -* Wed Jul 06 2011 Chuck Ebbert +* Wed Jul 06 2011 Chuck Ebbert 2.6.38.8-35 - Revert SCSI/block patches from 2.6.38.6 that caused more problems than they fixed; drop band-aid patch attempting to fix the fix. - CVE-2011-2497: kernel: bluetooth: buffer overflow in l2cap config request From af3abd43a548a42c86c500fd072a9d28889639dc Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 12 Jul 2011 15:17:54 -0400 Subject: [PATCH 100/397] zd1211rw: fix invalid signal values from device (rhbz 720093) --- kernel.spec | 7 ++ ...ix-invalid-signal-values-from-device.patch | 82 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch diff --git a/kernel.spec b/kernel.spec index 7bbad73f4..41d8f486f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -783,6 +783,8 @@ Patch12420: crypto-aesni_intel-merge-with-fpu_ko.patch Patch12430: nl80211-fix-check-for-valid-ssid-size-in-scan-operations.patch Patch12431: nl80211-fix-overflow-in-ssid_len.patch.patch +Patch12440: linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1342,6 +1344,8 @@ ApplyPatch bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch ApplyPatch nl80211-fix-check-for-valid-ssid-size-in-scan-operations.patch ApplyPatch nl80211-fix-overflow-in-ssid_len.patch.patch +ApplyPatch linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch + # Misc fixes # The input layer spews crap no-one cares about. ApplyPatch linux-2.6-input-kill-stupid-messages.patch @@ -2075,6 +2079,9 @@ fi # and build. %changelog +* Tue Jul 12 2011 John W. Linville +- zd1211rw: fix invalid signal values from device (rhbz 720093) + * Wed Jul 06 2011 Chuck Ebbert 2.6.38.8-35 - Revert SCSI/block patches from 2.6.38.6 that caused more problems than they fixed; drop band-aid patch attempting to fix the fix. diff --git a/linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch b/linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch new file mode 100644 index 000000000..f91ceb808 --- /dev/null +++ b/linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch @@ -0,0 +1,82 @@ +commit 7a1d6564a15183cb5994656040966df09af8390f +Author: Jussi Kivilinna +Date: Mon Jun 20 14:42:28 2011 +0300 + + zd1211rw: fix invalid signal values from device + + Driver uses IEEE80211_HW_SIGNAL_UNSPEC and so signal values reported to + mac80211 should be in range 0..100. Sometimes device return out of range + values. These out of range values can then trigger warning in + cfg80211_inform_bss_frame. + + This patch adds checks to enforce range returned from driver to + mac80211 be in 0..100 range. + + Signed-off-by: Jussi Kivilinna + Signed-off-by: John W. Linville + +diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h +index 5463ca9..9a1b013 100644 +--- a/drivers/net/wireless/zd1211rw/zd_def.h ++++ b/drivers/net/wireless/zd1211rw/zd_def.h +@@ -37,9 +37,15 @@ typedef u16 __nocast zd_addr_t; + if (net_ratelimit()) \ + dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \ + } while (0) ++# define dev_dbg_f_cond(dev, cond, fmt, args...) ({ \ ++ bool __cond = !!(cond); \ ++ if (unlikely(__cond)) \ ++ dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \ ++}) + #else + # define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0) + # define dev_dbg_f_limit(dev, fmt, args...) do { (void)(dev); } while (0) ++# define dev_dbg_f_cond(dev, cond, fmt, args...) do { (void)(dev); } while (0) + #endif /* DEBUG */ + + #ifdef DEBUG +diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c +index 5037c8b..5de28bf 100644 +--- a/drivers/net/wireless/zd1211rw/zd_mac.c ++++ b/drivers/net/wireless/zd1211rw/zd_mac.c +@@ -160,6 +160,22 @@ static int zd_reg2alpha2(u8 regdomain, char *alpha2) + return 1; + } + ++static int zd_check_signal(struct ieee80211_hw *hw, int signal) ++{ ++ struct zd_mac *mac = zd_hw_mac(hw); ++ ++ dev_dbg_f_cond(zd_mac_dev(mac), signal < 0 || signal > 100, ++ "%s: signal value from device not in range 0..100, " ++ "but %d.\n", __func__, signal); ++ ++ if (signal < 0) ++ signal = 0; ++ else if (signal > 100) ++ signal = 100; ++ ++ return signal; ++} ++ + int zd_mac_preinit_hw(struct ieee80211_hw *hw) + { + int r; +@@ -461,7 +477,7 @@ static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, + if (istatus.rates[i].idx = -1; /* terminate */ + +- info->status.ack_signal = ackssi; ++ info->status.ack_signal = zd_check_signal(hw, ackssi); + ieee80211_tx_status_irqsafe(hw, skb); + } + +@@ -982,7 +998,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) + + stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq; + stats.band = IEEE80211_BAND_2GHZ; +- stats.signal = status->signal_strength; ++ stats.signal = zd_check_signal(hw, status->signal_strength); + + rate = zd_rx_rate(buffer, status); + From 523da4bf9ab95829b9fad07277eea72ed853f1a5 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 12 Jul 2011 15:30:46 -0400 Subject: [PATCH 101/397] Bump version for build --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 41d8f486f..bd267363f 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 35 +%global baserelease 36 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2079,7 +2079,7 @@ fi # and build. %changelog -* Tue Jul 12 2011 John W. Linville +* Tue Jul 12 2011 John W. Linville - 2.6.38.8-36 - zd1211rw: fix invalid signal values from device (rhbz 720093) * Wed Jul 06 2011 Chuck Ebbert 2.6.38.8-35 From 7f4ef57b34dc9175479754f725bc87620c1bd303 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 28 Jul 2011 16:51:58 -0400 Subject: [PATCH 102/397] Rebase to 3.0 (but all it 2.6.40) --- Makefile | 12 +- TODO | 93 +- acpi_reboot.patch | 106 - add-appleir-usb-driver.patch | 2 +- ahci-add-another-pci-id-for-marvell.patch | 32 - apple_backlight.patch | 688 -- ...le-fast-channel-switching-by-default.patch | 72 - ...get-should-access-bd_disk-only-after.patch | 40 - ...-for-ath3k-on-pegatron-lucid-tablets.patch | 37 - ...fer-overflow-in-l2cap-config-request.patch | 32 - bonding-incorrect-tx-queue-offset.patch | 54 - ...cking-around-ioc-ioc-data-assignment.patch | 44 - config-arm | 12 + config-debug | 1 + config-generic | 229 +- 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 + crypto-aesni_intel-merge-with-fpu_ko.patch | 134 - cx88-Fix-HVR4000-IR-keymap.patch | 55 - ...rkaround-for-bsd-ring-on-sandybridge.patch | 43 - drm-i915-fix-pipelined-fencing.patch | 80 - drm-i915-snb-irq-stalls-fix.patch | 53 - 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-restore-mode.patch | 128 - drm-nouveau-fixes.patch | 1 - drm-nouveau-updates.patch | 6778 +-------------- ...tom-cards-with-hardcoded-EDID-record.patch | 56 - 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 - fix-scsi_dispatch_cmd.patch | 68 + ...uch-add-support-for-elo-touchsystems.patch | 78 - hid-ntrig-deref-unclaimed-input.patch | 46 - ...-completely-disabled-and-default-off.patch | 145 - ...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 | 1049 +-- ...reference-in-scan-get-next-rmap-item.patch | 82 - ...t-frozen-flag-if-new-eh-is-supported.patch | 72 - linux-2.6-32bit-mmap-exec-randomization.patch | 10 + linux-2.6-acpi-debug-infinite-loop.patch | 27 +- linux-2.6-crash-driver.patch | 29 +- linux-2.6-debug-always-inline-kzalloc.patch | 25 - linux-2.6-debug-sizeof-structs.patch | 33 - linux-2.6-defaults-pci_no_msi.patch | 110 - linux-2.6-defaults-pci_use_crs.patch | 29 - linux-2.6-firewire-git-pending.patch | 4 - linux-2.6-firewire-git-update.patch | 3682 -------- linux-2.6-hotfixes.patch | 15 - linux-2.6-i386-nx-emulation.patch | 45 +- linux-2.6-netconsole-deadlock.patch | 56 - linux-2.6-selinux-mprotect-checks.patch | 124 - linux-2.6-silence-noise.patch | 13 +- linux-2.6-sparc-selinux-mprotect-checks.patch | 35 - linux-2.6-tracehook.patch | 129 - linux-2.6-upstream-reverts.patch | 204 +- linux-2.6-utrace-ptrace.patch | 2031 ----- ...-revert-make-ptrace-functions-static.patch | 47 - linux-2.6-utrace.patch | 4166 --------- linux-2.6-v4l-dvb-experimental.patch | 1326 --- linux-2.6-v4l-dvb-update.patch | 7725 ----------------- ...ix-invalid-signal-values-from-device.patch | 82 - ...r-valid-ssid-size-in-scan-operations.patch | 42 - nl80211-fix-overflow-in-ssid_len.patch.patch | 44 - ...-state-clearing-regardless-of-policy.patch | 29 - ...igured-for-aspm-under-powersave-mode.patch | 112 - ...ngle-valid-userspace-syslog-prefixes.patch | 214 - revert-fix-oops-in-scsi_run_queue.patch | 21 - ...ore-ivalid-report-id-while-switching.patch | 43 - ...stricter-guards-on-queue-dead-checks.patch | 34 - ...-caching-printk-from-error-to-notice.patch | 28 - ..._sw-fix-deadlock-in-start_stop_endio.patch | 32 - sources | 4 +- ...info-when-frame-pointer-is-available.patch | 352 - ...ci-bfsort-whitelist-for-dell-systems.patch | 55 - 95 files changed, 628 insertions(+), 39045 deletions(-) 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 ath5k-disable-fast-channel-switching-by-default.patch delete mode 100644 block-blkdev_get-should-access-bd_disk-only-after.patch delete mode 100644 bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch delete mode 100644 bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch delete mode 100644 bonding-incorrect-tx-queue-offset.patch delete mode 100644 cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch delete mode 100644 crypto-aesni_intel-merge-with-fpu_ko.patch delete mode 100644 cx88-Fix-HVR4000-IR-keymap.patch delete mode 100644 drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch delete mode 100644 drm-i915-fix-pipelined-fencing.patch delete mode 100644 drm-i915-snb-irq-stalls-fix.patch 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-restore-mode.patch delete mode 100644 drm-nouveau-fixes.patch delete mode 100644 drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.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 create mode 100644 fix-scsi_dispatch_cmd.patch delete mode 100644 hid-multitouch-add-support-for-elo-touchsystems.patch delete mode 100644 hid-ntrig-deref-unclaimed-input.patch delete mode 100644 ima-allow-it-to-be-completely-disabled-and-default-off.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 ksm-fix-null-pointer-dereference-in-scan-get-next-rmap-item.patch delete mode 100644 libata-sas-only-set-frozen-flag-if-new-eh-is-supported.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-defaults-pci_no_msi.patch delete mode 100644 linux-2.6-defaults-pci_use_crs.patch delete mode 100644 linux-2.6-firewire-git-pending.patch delete mode 100644 linux-2.6-firewire-git-update.patch delete mode 100644 linux-2.6-hotfixes.patch delete mode 100644 linux-2.6-netconsole-deadlock.patch delete mode 100644 linux-2.6-selinux-mprotect-checks.patch delete mode 100644 linux-2.6-sparc-selinux-mprotect-checks.patch delete mode 100644 linux-2.6-tracehook.patch delete mode 100644 linux-2.6-utrace-ptrace.patch delete mode 100644 linux-2.6-utrace-revert-make-ptrace-functions-static.patch delete mode 100644 linux-2.6-utrace.patch delete mode 100644 linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch delete mode 100644 nl80211-fix-check-for-valid-ssid-size-in-scan-operations.patch delete mode 100644 nl80211-fix-overflow-in-ssid_len.patch.patch delete mode 100644 pci-enable-aspm-state-clearing-regardless-of-policy.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 revert-fix-oops-in-scsi_run_queue.patch delete mode 100644 revert-hid-magicmouse-ignore-ivalid-report-id-while-switching.patch delete mode 100644 revert-put-stricter-guards-on-queue-dead-checks.patch delete mode 100644 scsi-sd-downgrade-caching-printk-from-error-to-notice.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 delete mode 100644 x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch diff --git a/Makefile b/Makefile index 7bc3839f8..cffc926c2 100644 --- a/Makefile +++ b/Makefile @@ -55,6 +55,9 @@ debug: @perl -pi -e 's/# CONFIG_DEBUG_OBJECTS is not set/CONFIG_DEBUG_OBJECTS=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_OBJECTS_FREE is not set/CONFIG_DEBUG_OBJECTS_FREE=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_OBJECTS_TIMERS is not set/CONFIG_DEBUG_OBJECTS_TIMERS=y/' config-nodebug + @perl -pi -e 's/# CONFIG_DEBUG_OBJECTS_WORK is not set/CONFIG_DEBUG_OBJECTS_WORK=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_DEBUG_OBJECTS_RCU_HEAD is not set/CONFIG_DEBUG_OBJECTS_RCU_HEAD=y/' config-nodebug @perl -pi -e 's/# CONFIG_X86_PTDUMP is not set/CONFIG_X86_PTDUMP=y/' config-nodebug @perl -pi -e 's/# CONFIG_CAN_DEBUG_DEVICES is not set/CONFIG_CAN_DEBUG_DEVICES=y/' config-nodebug @perl -pi -e 's/# CONFIG_MODULE_FORCE_UNLOAD is not set/CONFIG_MODULE_FORCE_UNLOAD=y/' config-nodebug @@ -79,7 +82,6 @@ debug: @perl -pi -e 's/# CONFIG_ATH_DEBUG is not set/CONFIG_ATH_DEBUG=y/' config-nodebug @perl -pi -e 's/# CONFIG_CARL9170_DEBUGFS is not set/CONFIG_CARL9170_DEBUGFS=y/' config-nodebug @perl -pi -e 's/# CONFIG_IWLWIFI_DEVICE_TRACING is not set/CONFIG_IWLWIFI_DEVICE_TRACING=y/' config-nodebug - @perl -pi -e 's/# CONFIG_DEBUG_OBJECTS_WORK is not set/CONFIG_DEBUG_OBJECTS_WORK=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set/CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y/' config-nodebug @perl -pi -e 's/# CONFIG_DMADEVICES_DEBUG is not set/CONFIG_DMADEVICES_DEBUG=y/' config-nodebug @perl -pi -e 's/# CONFIG_DMADEVICES_VDEBUG is not set/CONFIG_DMADEVICES_VDEBUG=y/' config-nodebug @@ -89,8 +91,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_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 @perl -pi -e 's/# CONFIG_DEBUG_SET_MODULE_RONX is not set/CONFIG_DEBUG_SET_MODULE_RONX=y/' config-nodebug @@ -133,6 +133,9 @@ release: @perl -pi -e 's/CONFIG_DEBUG_OBJECTS=y/# CONFIG_DEBUG_OBJECTS is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_OBJECTS_FREE=y/# CONFIG_DEBUG_OBJECTS_FREE is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_OBJECTS_TIMERS=y/# CONFIG_DEBUG_OBJECTS_TIMERS is not set/' config-nodebug + @perl -pi -e 's/CONFIG_DEBUG_OBJECTS_WORK=y/# CONFIG_DEBUG_OBJECTS_WORK 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_DEBUG_OBJECTS_RCU_HEAD=y/# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set/' config-nodebug @perl -pi -e 's/CONFIG_X86_PTDUMP=y/# CONFIG_X86_PTDUMP is not set/' config-nodebug @perl -pi -e 's/CONFIG_CAN_DEBUG_DEVICES=y/# CONFIG_CAN_DEBUG_DEVICES is not set/' config-nodebug @perl -pi -e 's/CONFIG_MODULE_FORCE_UNLOAD=y/# CONFIG_MODULE_FORCE_UNLOAD is not set/' config-nodebug @@ -157,7 +160,6 @@ release: @perl -pi -e 's/CONFIG_ATH_DEBUG=y/# CONFIG_ATH_DEBUG is not set/' config-nodebug @perl -pi -e 's/CONFIG_CARL9170_DEBUGFS=y/# CONFIG_CARL9170_DEBUGFS is not set/' config-nodebug @perl -pi -e 's/CONFIG_IWLWIFI_DEVICE_TRACING=y/# CONFIG_IWLWIFI_DEVICE_TRACING is not set/' config-nodebug - @perl -pi -e 's/CONFIG_DEBUG_OBJECTS_WORK=y/# CONFIG_DEBUG_OBJECTS_WORK is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y/# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set/' config-nodebug @perl -pi -e 's/CONFIG_DMADEVICES_DEBUG=y/# CONFIG_DMADEVICES_DEBUG is not set/' config-nodebug @perl -pi -e 's/CONFIG_DMADEVICES_VDEBUG=y/# CONFIG_DMADEVICES_VDEBUG is not set/' config-nodebug @@ -167,8 +169,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_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 @perl -pi -e 's/CONFIG_DEBUG_SET_MODULE_RONX=y/# CONFIG_DEBUG_SET_MODULE_RONX is not set/' config-nodebug diff --git a/TODO b/TODO index abaefae05..968324422 100644 --- a/TODO +++ b/TODO @@ -1,57 +1,33 @@ # 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 +* linux-2.6-defaults-aspm.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. +* linux-2.6-makefile-after_link.patch + Rolandware that is used by the debuginfo generation. + Possibly upstreamable ? -* lirc-2.6.33.patch -* hdpvr-ir-enable.patch - jarod working on upstreaming +* linux-2.6.29-sparc-IOC_TYPECHECK.patch + Responsible: Spot/Dennis. -* 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-v4l-dvb-uvcvideo-update.patch + Responsible: Hans. * linux-2.6-serial-460800.patch Probably not upstreamable. @@ -59,3 +35,56 @@ https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=126403 http://lkml.org/lkml/2006/8/2/208 +* linux-2.6-crash-driver.patch + Unlikely to go upstream. + https://bugzilla.redhat.com/show_bug.cgi?id=492803 + +* linux-2.6-32bit-mmap-exec-randomization.patch + One half of the remaining exec-shield diff. + davej bugged Ingo again on Jun 17 2011 about upstreaming. + +* runtime_pm_fixups.patch +* linux-2.6-usb-pci-autosuspend.patch +* linux-2.6-enable-more-pci-autosuspend.patch +* linux-2.6-acpi-debug-infinite-loop.patch +* acpi-ec-add-delay-before-write.patch + Responsible: mjg59 + +* linux-2.6-v4l-dvb-experimental.patch +* linux-2.6-v4l-dvb-fixes.patch +* linux-2.6-v4l-dvb-update.patch + Empty. + +* fix_xen_guest_on_old_EC2.patch + Ugly for upstream. It's a hack to make old HV's work optimally. + Eventually we can drop it, but probably not until fixed HV's + are commonplace. (When?) + Responsible: Justin. + +* linux-2.6-i386-nx-emulation.patch + The ugly segment hack part of exec-shield that Linus hates. + Unlikely to ever go upstream. + +* linux-2.6-e1000-ich9-montevina.patch + Intel hates it. Davej has an SDV that needs it. + Low maintenence, and worth hanging onto until it gets replaced + with something that fails in a different way. + +-------- +currently undocumented: + +add-appleir-usb-driver.patch +die-floppy-die.patch +disable-i8042-check-on-apple-mac.patch +dmar-disable-when-ricoh-multifunction.patch +drm-intel-make-lvds-work.patch +drm-intel-next.patch +drm-nouveau-updates.patch +hda_intel-prealloc-4mb-dmabuffer.patch +linux-2.6.30-no-pcspkr-modalias.patch +linux-2.6-input-kill-stupid-messages.patch +linux-2.6-intel-iommu-igfx.patch +linux-2.6-upstream-reverts.patch +linux-3.0-fix-uts-release.patch +neuter_intel_microcode_load.patch + 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/add-appleir-usb-driver.patch b/add-appleir-usb-driver.patch index af4f968f6..26477ccce 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[] = { - { 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) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, USB_DEVICE_ID_ACTIONSTAR_1011) }, - { 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/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 deleted file mode 100644 index 86ebf8340..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"); - -@@ -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/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/bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch b/bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch deleted file mode 100644 index 767105587..000000000 --- a/bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch +++ /dev/null @@ -1,37 +0,0 @@ -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/bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch b/bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch deleted file mode 100644 index 5cc80c72f..000000000 --- a/bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Dan Rosenberg -Date: Fri, 24 Jun 2011 12:38:05 +0000 (-0400) -Subject: Bluetooth: Prevent buffer overflow in l2cap config request -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fpadovan%2Fbluetooth-2.6.git;a=commitdiff_plain;h=7ac28817536797fd40e9646452183606f9e17f71 - -Bluetooth: Prevent buffer overflow in l2cap config request -[ backport to 2.6.38 ] - -A remote user can provide a small value for the command size field in -the command header of an l2cap configuration request, resulting in an -integer underflow when subtracting the size of the configuration request -header. This results in copying a very large amount of data via -memcpy() and destroying the kernel heap. Check for underflow. - -Signed-off-by: Dan Rosenberg -Cc: stable -Signed-off-by: Gustavo F. Padovan ---- - -diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c -index 56fdd91..7d8a66b 100644 ---- a/net/bluetooth/l2cap.c -+++ b/net/bluetooth/l2cap.c -@@ -3116,7 +3116,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr - - /* Reject if config buffer is too small. */ - len = cmd_len - sizeof(*req); -- if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) { -+ if (len < 0 || l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) { - l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, - l2cap_build_conf_rsp(sk, rsp, - L2CAP_CONF_REJECT, flags), rsp); 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/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/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..e4dab09c1 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 @@ -447,6 +453,7 @@ CONFIG_SCSI_SCAN_ASYNC=y CONFIG_SCSI_SRP=m CONFIG_SCSI_SRP_ATTRS=m CONFIG_SCSI_TGT=m +CONFIG_SCSI_ISCI=m CONFIG_SCSI_DH=y CONFIG_SCSI_DH_RDAC=m @@ -569,6 +576,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 +697,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 +768,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 +816,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 +852,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 +913,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 +941,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 +1032,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 +1106,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 +1454,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 +1515,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 +1550,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 +1583,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 +1647,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 +1707,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 +1741,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 +1933,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 +2014,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 +2050,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 +2099,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 +2172,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 +2280,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 +2319,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 +2423,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 +2485,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 +2509,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 +2560,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 +2572,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 +2592,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 +2664,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 +2693,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 +2770,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 +2841,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 +2859,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 +2976,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 +3034,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 +3046,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 +3055,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 +3091,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 +3113,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 +3179,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 +3190,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 +3253,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 +3281,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 +3310,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 +3335,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 +3401,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 +3446,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 +3485,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 +3610,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 +3673,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 +3696,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 +3951,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 +3984,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 +4196,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 @@ -4078,8 +4208,6 @@ CONFIG_ASYNC_TX_DMA=y CONFIG_UNUSED_SYMBOLS=y -CONFIG_UTRACE=y - CONFIG_FTRACE=y CONFIG_DYNAMIC_FTRACE=y # CONFIG_IRQSOFF_TRACER is not set @@ -4122,13 +4250,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 +4302,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 +4331,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 +4371,6 @@ CONFIG_PHONET=m CONFIG_ICS932S401=m # CONFIG_C2PORT is not set -CONFIG_W1_SLAVE_BQ27000=m CONFIG_IT87_WDT=m @@ -4327,6 +4459,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 +4511,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 +4534,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 +4566,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 +4594,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 +4615,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 +4636,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/crypto-aesni_intel-merge-with-fpu_ko.patch b/crypto-aesni_intel-merge-with-fpu_ko.patch deleted file mode 100644 index afb4bec8b..000000000 --- a/crypto-aesni_intel-merge-with-fpu_ko.patch +++ /dev/null @@ -1,134 +0,0 @@ -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/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-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-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-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/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 index 209deb295..89f4e2d48 100644 --- a/drm-intel-make-lvds-work.patch +++ b/drm-intel-make-lvds-work.patch @@ -1,23 +1,18 @@ - 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) +@@ -5821,7 +5821,6 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, + struct intel_load_detect_pipe *old) { 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); - } +@@ -5832,7 +5831,6 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, - /* Switch crtc and encoder back off if necessary */ + if (old->load_detect_temp) { + connector->encoder = NULL; +- drm_helper_disable_unused_functions(dev); + + if (old->release_fb) + old->release_fb->funcs->destroy(old->release_fb); 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-fixes.patch b/drm-nouveau-fixes.patch deleted file mode 100644 index 8b1378917..000000000 --- a/drm-nouveau-fixes.patch +++ /dev/null @@ -1 +0,0 @@ - diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index 7a703e897..607602cfc 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -1,6777 +1 @@ -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 */ +nil 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 deleted file mode 100644 index 217e29d76..000000000 --- a/drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch +++ /dev/null @@ -1,56 +0,0 @@ -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/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/fix-scsi_dispatch_cmd.patch b/fix-scsi_dispatch_cmd.patch new file mode 100644 index 000000000..3976791ca --- /dev/null +++ b/fix-scsi_dispatch_cmd.patch @@ -0,0 +1,68 @@ +commit bfe159a51203c15d23cb3158fffdc25ec4b4dda1 +Author: James Bottomley +Date: Thu Jul 7 15:45:40 2011 -0500 + + [SCSI] fix crash in scsi_dispatch_cmd() + + USB surprise removal of sr is triggering an oops in + scsi_dispatch_command(). What seems to be happening is that USB is + hanging on to a queue reference until the last close of the upper + device, so the crash is caused by surprise remove of a mounted CD + followed by attempted unmount. + + The problem is that USB doesn't issue its final commands as part of + the SCSI teardown path, but on last close when the block queue is long + gone. The long term fix is probably to make sr do the teardown in the + same way as sd (so remove all the lower bits on ejection, but keep the + upper disk alive until last close of user space). However, the + current oops can be simply fixed by not allowing any commands to be + sent to a dead queue. + + Cc: stable@kernel.org + Signed-off-by: James Bottomley + +diff --git a/block/blk-core.c b/block/blk-core.c +index d2f8f40..1d49e1c 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -839,6 +839,9 @@ struct request *blk_get_request(struct request_queue *q, int rw, gfp_t gfp_mask) + { + struct request *rq; + ++ if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) ++ return NULL; ++ + BUG_ON(rw != READ && rw != WRITE); + + spin_lock_irq(q->queue_lock); +diff --git a/block/blk-exec.c b/block/blk-exec.c +index 8a0e7ec..a1ebceb 100644 +--- a/block/blk-exec.c ++++ b/block/blk-exec.c +@@ -50,6 +50,13 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, + { + int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; + ++ if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) { ++ rq->errors = -ENXIO; ++ if (rq->end_io) ++ rq->end_io(rq, rq->errors); ++ return; ++ } ++ + rq->rq_disk = bd_disk; + rq->end_io = done; + WARN_ON(irqs_disabled()); +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index ec1803a..28d9c9d 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -213,6 +213,8 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, + int ret = DRIVER_ERROR << 24; + + req = blk_get_request(sdev->request_queue, write, __GFP_WAIT); ++ if (!req) ++ return ret; + + if (bufflen && blk_rq_map_kern(sdev->request_queue, req, + buffer, bufflen, __GFP_WAIT)) diff --git a/hid-multitouch-add-support-for-elo-touchsystems.patch b/hid-multitouch-add-support-for-elo-touchsystems.patch deleted file mode 100644 index 1294f4630..000000000 --- a/hid-multitouch-add-support-for-elo-touchsystems.patch +++ /dev/null @@ -1,78 +0,0 @@ -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/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/ima-allow-it-to-be-completely-disabled-and-default-off.patch b/ima-allow-it-to-be-completely-disabled-and-default-off.patch deleted file mode 100644 index 4f8f1f180..000000000 --- a/ima-allow-it-to-be-completely-disabled-and-default-off.patch +++ /dev/null @@ -1,145 +0,0 @@ -From 785465d9cffd65b5a69dd2f465d2f7c917713220 Mon Sep 17 00:00:00 2001 -From: Kyle McMartin -Date: Mon, 18 Oct 2010 13:30:39 -0400 -Subject: [PATCH] ima: provide a toggle to disable it entirely - -Signed-off-by: Kyle McMartin ---- - security/integrity/ima/ima.h | 1 + - security/integrity/ima/ima_iint.c | 9 +++++++++ - security/integrity/ima/ima_main.c | 24 +++++++++++++++++++++--- - 3 files changed, 31 insertions(+), 3 deletions(-) - -diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h -index 3fbcd1d..65c3977 100644 ---- a/security/integrity/ima/ima.h -+++ b/security/integrity/ima/ima.h -@@ -37,6 +37,7 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; - /* set during initialization */ - extern int iint_initialized; - extern int ima_initialized; -+extern int ima_enabled; - extern int ima_used_chip; - extern char *ima_hash; - -diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c -index afba4ae..3d191ef 100644 ---- a/security/integrity/ima/ima_iint.c -+++ b/security/integrity/ima/ima_iint.c -@@ -54,6 +54,9 @@ int ima_inode_alloc(struct inode *inode) - struct ima_iint_cache *iint = NULL; - int rc = 0; - -+ if (!ima_enabled) -+ return 0; -+ - iint = kmem_cache_alloc(iint_cache, GFP_NOFS); - if (!iint) - return -ENOMEM; -@@ -116,6 +119,9 @@ void ima_inode_free(struct inode *inode) - { - struct ima_iint_cache *iint; - -+ if (!ima_enabled) -+ return; -+ - spin_lock(&ima_iint_lock); - iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode); - spin_unlock(&ima_iint_lock); -@@ -139,6 +145,9 @@ static void init_once(void *foo) - - static int __init ima_iintcache_init(void) - { -+ if (!ima_enabled) -+ return 0; -+ - iint_cache = - kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, - SLAB_PANIC, init_once); -diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c -index e662b89..6e91905 100644 ---- a/security/integrity/ima/ima_main.c -+++ b/security/integrity/ima/ima_main.c -@@ -26,6 +26,7 @@ - #include "ima.h" - - int ima_initialized; -+int ima_enabled; - - char *ima_hash = "sha1"; - static int __init hash_setup(char *str) -@@ -36,6 +37,14 @@ static int __init hash_setup(char *str) - } - __setup("ima_hash=", hash_setup); - -+static int __init ima_enable(char *str) -+{ -+ if (strncmp(str, "on", 2) == 0) -+ ima_enabled = 1; -+ return 1; -+} -+__setup("ima=", ima_enable); -+ - struct ima_imbalance { - struct hlist_node node; - unsigned long fsmagic; -@@ -148,7 +157,7 @@ void ima_counts_get(struct file *file) - struct ima_iint_cache *iint; - int rc; - -- if (!iint_initialized || !S_ISREG(inode->i_mode)) -+ if (!ima_enabled || !iint_initialized || !S_ISREG(inode->i_mode)) - return; - iint = ima_iint_find_get(inode); - if (!iint) -@@ -215,7 +224,7 @@ void ima_file_free(struct file *file) - struct inode *inode = file->f_dentry->d_inode; - struct ima_iint_cache *iint; - -- if (!iint_initialized || !S_ISREG(inode->i_mode)) -+ if (!ima_enabled || !iint_initialized || !S_ISREG(inode->i_mode)) - return; - iint = ima_iint_find_get(inode); - if (!iint) -@@ -269,7 +278,7 @@ int ima_file_mmap(struct file *file, unsigned long prot) - { - int rc; - -- if (!file) -+ if (!ima_enabled || !file) - return 0; - if (prot & PROT_EXEC) - rc = process_measurement(file, file->f_dentry->d_name.name, -@@ -294,6 +303,9 @@ int ima_bprm_check(struct linux_binprm *bprm) - { - int rc; - -+ if (!ima_enabled) -+ return 0; -+ - rc = process_measurement(bprm->file, bprm->filename, - MAY_EXEC, BPRM_CHECK); - return 0; -@@ -313,6 +325,9 @@ int ima_file_check(struct file *file, int mask) - { - int rc; - -+ if (!ima_enabled) -+ return 0; -+ - rc = process_measurement(file, file->f_dentry->d_name.name, - mask & (MAY_READ | MAY_WRITE | MAY_EXEC), - FILE_CHECK); -@@ -324,6 +339,9 @@ static int __init init_ima(void) - { - int error; - -+ if (!ima_enabled) -+ return 0; -+ - error = ima_init(); - ima_initialized = 1; - return error; --- -1.7.3.1 - 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 bd267363f..4a6b7d530 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,19 +51,20 @@ 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 36 +%global baserelease 2 %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 +%define fake_sublevel 40 ## 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 0 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -75,18 +76,8 @@ Summary: The Linux kernel %define stable_base %(echo $((%{stable_update} - 1))) %endif %endif -%define rpmversion 2.6.%{base_sublevel}%{?stablerev} +%define rpmversion 2.6.%{fake_sublevel}%{?stablerev} -## The not-released-kernel case ## -%else -# The next upstream release sublevel (base_sublevel+1) -%define upstream_sublevel %(echo $((%{base_sublevel} + 1))) -# The rc snapshot level -%define rcrev 0 -# The git snapshot level -%define gitrev 0 -# Set rpm version accordingly -%define rpmversion 2.6.%{upstream_sublevel} %endif # Nb: The above rcrev and gitrev values automagically define Patch00 and Patch01 below. @@ -184,6 +175,7 @@ Summary: The Linux kernel %endif # The kernel tarball/base version +# % define kversion 3.%{base_sublevel} %define kversion 2.6.%{base_sublevel} %define make_target bzImage @@ -345,7 +337,7 @@ Summary: The Linux kernel %define asmarch sparc %define all_arch_configs kernel-%{version}-sparc64*.config %define make_target image -%define kernel_image vmlinux +%define kernel_image arch/sparc/boot/image %define image_install_path boot %define with_perf 0 %endif @@ -431,7 +423,7 @@ Summary: The Linux kernel # First the general kernel 2.6 required versions as per # Documentation/Changes # -%define kernel_dot_org_conflicts ppp < 2.4.3-3, isdn4k-utils < 3.2-32, nfs-utils < 1.0.7-12, e2fsprogs < 1.37-4, util-linux < 2.12, jfsutils < 1.1.7-2, reiserfs-utils < 3.6.19-2, xfsprogs < 2.6.13-4, procps < 3.2.5-6.3, oprofile < 0.9.1-2 +%define kernel_dot_org_conflicts ppp < 2.4.3-3, isdn4k-utils < 3.2-32, nfs-utils < 1.0.7-12, e2fsprogs < 1.37-4, util-linux < 2.12, jfsutils < 1.1.7-2, reiserfs-utils < 3.6.19-2, xfsprogs < 2.6.13-4, procps < 3.2.5-6.3, oprofile < 0.9.1-2, module-init-tools < 3.13-1 # # Then a series of requirements that are distribution specific, either @@ -529,6 +521,7 @@ BuildRequires: rpm-build >= 4.4.2.1-4 %endif Source0: ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-%{kversion}.tar.bz2 +#Source0: ftp://ftp.kernel.org/pub/linux/kernel/v3.0/linux-3.0-rc5.tar.bz2 Source11: genkey Source14: find-provides @@ -564,15 +557,17 @@ Source1000: config-local # Here should be only the patches up to the upstream canonical Linus tree. +Patch00: patch-3.0.bz2 + # For a stable release kernel %if 0%{?stable_update} %if 0%{?stable_base} -%define stable_patch_00 patch-2.6.%{base_sublevel}.%{stable_base}.bz2 -Patch00: %{stable_patch_00} +%define stable_patch_00 patch-3.%{base_sublevel}.%{stable_base}.bz2 +Patch01: %{stable_patch_00} %endif %if 0%{?stable_rc} -%define stable_patch_01 patch-2.6.%{base_sublevel}.%{stable_update}-rc%{stable_rc}.bz2 -Patch01: %{stable_patch_01} +%define stable_patch_01 patch-3.%{base_sublevel}.%{stable_update}-rc%{stable_rc}.bz2 +Patch02: %{stable_patch_01} %endif # non-released_kernel case @@ -580,14 +575,14 @@ Patch01: %{stable_patch_01} # near the top of this spec file. %else %if 0%{?rcrev} -Patch00: patch-2.6.%{upstream_sublevel}-rc%{rcrev}.bz2 +Patch00: patch-3.0-rc%{rcrev}.bz2 %if 0%{?gitrev} -Patch01: patch-2.6.%{upstream_sublevel}-rc%{rcrev}-git%{gitrev}.bz2 +Patch01: patch-3.0-rc%{rcrev}-git%{gitrev}.bz2 %endif %else # pre-{base_sublevel+1}-rc1 case %if 0%{?gitrev} -Patch00: patch-2.6.%{base_sublevel}-git%{gitrev}.bz2 +Patch00: patch-3.%{base_sublevel}-git%{gitrev}.bz2 %endif %endif %endif @@ -596,7 +591,7 @@ Patch00: patch-2.6.%{base_sublevel}-git%{gitrev}.bz2 ### BRANCH PATCH ### %endif -Patch02: git-linus.diff +Patch03: git-linus.diff # we also need compile fixes for -vanilla Patch04: linux-2.6-compile-fixes.patch @@ -612,35 +607,16 @@ 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 -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 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 Patch390: linux-2.6-defaults-acpi-video.patch Patch391: linux-2.6-acpi-video-dos.patch @@ -649,10 +625,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 @@ -660,20 +632,8 @@ Patch470: die-floppy-die.patch Patch510: linux-2.6-silence-noise.patch 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: revert-fix-oops-in-scsi_run_queue.patch -Patch601: revert-put-stricter-guards-on-queue-dead-checks.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 +Patch610: hda_intel-prealloc-4mb-dmabuffer.patch Patch700: linux-2.6-e1000-ich9-montevina.patch @@ -687,103 +647,43 @@ 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 # 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 -Patch2201: linux-2.6-firewire-git-pending.patch # Quiet boot fixes # silence the ACPI blacklist code 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 +Patch2902: linux-2.6-v4l-dvb-uvcvideo-update.patch # fs fixes # NFSv4 # patches headed upstream - Patch12010: add-appleir-usb-driver.patch 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 +Patch12205: runtime_pm_fixups.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 -Patch12417: bluetooth-prevent-buffer-overflow-in-l2cap-config-request.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 - -Patch12430: nl80211-fix-check-for-valid-ssid-size-in-scan-operations.patch -Patch12431: nl80211-fix-overflow-in-ssid_len.patch.patch - -Patch12440: linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch +Patch13000: fix-scsi_dispatch_cmd.patch %endif @@ -1013,7 +913,7 @@ ApplyPatch() fi %if !%{using_upstream_branch} if ! grep -E "^Patch[0-9]+: $patch\$" %{_specdir}/${RPM_PACKAGE_NAME%%%%%{?variant}}.spec ; then - if [ "${patch:0:10}" != "patch-2.6." ] ; then + if [ "${patch:0:8}" != "patch-3." ] ; then echo "ERROR: Patch $patch not listed as a source patch in specfile" exit 1 fi @@ -1078,7 +978,7 @@ ApplyOptionalPatch() # Build a list of the other top-level kernel tree directories. # This will be used to hardlink identical vanilla subdirs. -sharedirs=$(find "$PWD" -maxdepth 1 -type d -name 'kernel-2.6.*' \ +sharedirs=$(find "$PWD" -maxdepth 1 -type d -name 'kernel-3.*' \ | grep -x -v "$PWD"/kernel-%{kversion}%{?dist}) ||: if [ ! -d kernel-%{kversion}%{?dist}/vanilla-%{vanillaversion} ]; then @@ -1132,14 +1032,14 @@ if [ ! -d kernel-%{kversion}%{?dist}/vanilla-%{vanillaversion} ]; then # Update vanilla to the latest upstream. # (non-released_kernel case only) %if 0%{?rcrev} - ApplyPatch patch-2.6.%{upstream_sublevel}-rc%{rcrev}.bz2 + ApplyPatch patch-3.0-rc%{rcrev}.bz2 %if 0%{?gitrev} - ApplyPatch patch-2.6.%{upstream_sublevel}-rc%{rcrev}-git%{gitrev}.bz2 + ApplyPatch patch-3.0-rc%{rcrev}-git%{gitrev}.bz2 %endif %else # pre-{base_sublevel+1}-rc1 case %if 0%{?gitrev} - ApplyPatch patch-2.6.%{base_sublevel}-git%{gitrev}.bz2 + ApplyPatch patch-3.0-git%{gitrev}.bz2 %endif %endif @@ -1208,6 +1108,9 @@ do done %endif +# Update vanilla to the latest upstream. (2.6.39 -> 3.0) +ApplyPatch patch-3.0.bz2 + ApplyOptionalPatch git-linus.diff ApplyPatch linux-2.6-makefile-after_link.patch @@ -1222,36 +1125,13 @@ 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. -ApplyPatch linux-2.6-utrace-revert-make-ptrace-functions-static.patch -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 -# 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 @@ -1294,42 +1174,18 @@ 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 # -# make default state of PCI MSI a config option -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 - -#ApplyPatch ima-allow-it-to-be-completely-disabled-and-default-off.patch # -# SCSI / block Bits. +# SCSI Bits. # -# Revert SCSI patches from 2.6.38.6 that cause more problems thatn they solve -ApplyPatch revert-fix-oops-in-scsi_run_queue.patch -ApplyPatch revert-put-stricter-guards-on-queue-dead-checks.patch -# Fix potential NULL deref in 2.6.38.8 -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 # ACPI @@ -1337,27 +1193,16 @@ ApplyPatch libata-sas-only-set-frozen-flag-if-new-eh-is-supported.patch ApplyPatch hda_intel-prealloc-4mb-dmabuffer.patch # Networking -ApplyPatch bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch -# CVE-2011-2497 -ApplyPatch bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch -# CVE-2011-2517 -ApplyPatch nl80211-fix-check-for-valid-ssid-size-in-scan-operations.patch -ApplyPatch nl80211-fix-overflow-in-ssid_len.patch.patch - -ApplyPatch linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.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 -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... 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 @@ -1367,12 +1212,6 @@ ApplyPatch linux-2.6-silence-noise.patch # Make fbcon not show the penguins with 'quiet' ApplyPatch linux-2.6-silence-fbcon-logo.patch -# Fix the SELinux mprotect checks on executable mappings -#ApplyPatch linux-2.6-selinux-mprotect-checks.patch -# Fix SELinux for sparc -# FIXME: Can we drop this now? See updated linux-2.6-selinux-mprotect-checks.patch -#ApplyPatch linux-2.6-sparc-selinux-mprotect-checks.patch - # Changes to upstream defaults. @@ -1390,86 +1229,40 @@ 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 # Intel DRM ApplyOptionalPatch drm-intel-next.patch -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 -#ApplyOptionalPatch linux-2.6-firewire-git-pending.patch # silence the ACPI blacklist code 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 +#ApplyPatch linux-2.6-v4l-dvb-uvcvideo-update.patch # Patches headed upstream - ApplyPatch disable-i8042-check-on-apple-mac.patch 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 ###ApplyPatch linux-2.6-enable-more-pci-autosuspend.patch +#ApplyPatch runtime_pm_fixups.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 - - -# 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 +ApplyPatch fix-scsi_dispatch_cmd.patch # END OF PATCH APPLICATIONS @@ -1574,8 +1367,12 @@ BuildKernel() { # make sure EXTRAVERSION says what we want it to say perl -p -i -e "s/^EXTRAVERSION.*/EXTRAVERSION = %{?stablerev}-%{release}.%{_target_cpu}${Flavour:+.${Flavour}}/" Makefile + perl -p -i -e 's/^VERSION.*/VERSION = 2/' Makefile + perl -p -i -e 's/^PATCHLEVEL.*/PATCHLEVEL = 6/' Makefile + perl -p -i -e 's/^SUBLEVEL.*/SUBLEVEL = 40/' Makefile # if pre-rc1 devel kernel, must fix up SUBLEVEL for our versioning scheme + ### XXX this will probably be dead code in 3.0 --kyle %if !0%{?rcrev} %if 0%{?gitrev} perl -p -i -e 's/^SUBLEVEL.*/SUBLEVEL = %{upstream_sublevel}/' Makefile @@ -2079,714 +1876,104 @@ fi # and build. %changelog -* Tue Jul 12 2011 John W. Linville - 2.6.38.8-36 -- zd1211rw: fix invalid signal values from device (rhbz 720093) +* Thu Jul 28 2011 Dave Jones +- fix crash in scsi_dispatch_cmd() -* Wed Jul 06 2011 Chuck Ebbert 2.6.38.8-35 -- Revert SCSI/block patches from 2.6.38.6 that caused more problems - than they fixed; drop band-aid patch attempting to fix the fix. -- CVE-2011-2497: kernel: bluetooth: buffer overflow in l2cap config request -- CVE-2011-2517: kernel: nl80211: missing check for valid SSID size in scan operations +* Thu Jul 28 2011 Dave Jones 2.6.40-1 +- Turn off debugging options. (make release) + +* Tue Jul 26 2011 Dave Jones 2.6.40-0 +- Rebase to final 3.0 (munge to 2.6.40-0) + +* Thu Jun 30 2011 Kyle McMartin 2.6.40-0.rc5.git0.1 +- More than meets the eye, it's Linux 3.0-rc5 in disguise. * 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: - Another fix for Sandybridge stalls +* Thu Jun 23 2011 Kyle McMartin 3.0-0.rc4.git3.1 +- Linux 3.0-rc4-git3 +- Drop linux-3.0-fix-uts-release.patch, and instead just perl the Makefile +- linux-2.6-silence-noise.patch: fix context +- iwlagn-fix-dma-direction.patch: fix DMAR errors (for me at least) -* 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 -- 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 (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) +* Wed Jun 22 2011 Kyle McMartin 3.0-0.rc4.git0.2 +- Re-enable debuginfo generation. Thanks to Richard Jones for noticing... no + wonder builds had been so quick lately. -* Thu Jun 23 2011 Dave Airlie 2.6.38.8-34 -- drm-i915-snb-irq-stalls-fix.patch: fix Sandybridge IRQ stalls +* Tue Jun 21 2011 Kyle McMartin 3.0-0.rc4.git0.1 +- Linux 3.0-rc4 (getting closer...) -* Thu Jun 23 2011 Dave Airlie -- drm-radeon-update3.patch: more radeon fixes backport +* Fri Jun 17 2011 Kyle McMartin 3.0-0.rc3.git6.1 +- Update to 3.0-rc3-git6 -* Tue Jun 21 2011 Dave Jones -- HID: ntrig don't dereference unclaimed hidinput (rhbz#714827) +* Fri Jun 17 2011 Dave Jones +- drop qcserial 'compile fix' that was just duplicating an include. +- drop struct sizeof debug patch. (no real value. not upstreamable) +- drop linux-2.6-debug-always-inline-kzalloc.patch. + Can't recall why this was added. Can easily re-add if deemed necessary. -* Mon Jun 20 2011 Kyle McMartin 2.6.38.8-33 -- [sgruszka@] iwlwifi: fix general 11n instability (rhbz#648732) +* Fri Jun 17 2011 Kyle McMartin +- linux-2.6-defaults-pci_no_msi.patch: drop, haven't toggled the default + in many moons. +- linux-2.6-defaults-pci_use_crs.patch: ditto. +- linux-2.6-selinux-mprotect-checks.patch: upstream a while ago. +- drm-i915-gen4-has-non-power-of-two-strides.patch: drop buggy bugfix +- drop some more unapplied crud. +- We haven't applied firewire patches in a dogs age. + +* Fri Jun 17 2011 Kyle McMartin 3.0-0.rc3.git5.1 +- Try updating to a git snapshot for the first time in 3.0-rc, + update to 3.0-rc3-git5 +- Fix a subtle bug I introduced in 3.0-rc1, "patch-3." is 9 letters, not 10. + +* Thu Jun 16 2011 Kyle McMartin +- Disable mm patches which had been submitted against 2.6.39, as Rik reports + they seem to aggravate a VM_BUG_ON. More investigation is necessary. * Wed Jun 15 2011 Kyle McMartin -- crypto: aesni-intel - Merge with fpu.ko (rhbz#589390) +- Conflict with pre-3.2.1-5 versions of mdadm. (#710646) -* Thu Jun 09 2011 Kyle McMartin 2.6.38.8-32 +* Wed Jun 15 2011 Kyle McMartin +- Build in aesni-intel on i686 for symmetry with 64-bit. + +* Tue Jun 14 2011 Kyle McMartin 3.0-0.rc3.git0.3 +- Fix libdm conflict (whose bright idea was it to give subpackages differing + version numbers?) + +* Tue Jun 14 2011 Kyle McMartin +- Update to 3.0-rc3, add another conflicts to deal with 2 digit + versions (libdm.) +- Simplify linux-3.0-fix-uts-release.patch now that SUBLEVEL is optional. +- revert-ftrace-remove-unnecessary-disabling-of-irqs.patch: drop upstreamed + patch. +- drm-intel-eeebox-eb1007-quirk.patch: ditto. +- ath5k-disable-fast-channel-switching-by-default.patch: ditto. + +* 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. +* Thu Jun 09 2011 Kyle McMartin 3.0-0.rc2.git0.2 +- rhbz#710921: revert-ftrace-remove-unnecessary-disabling-of-irqs.patch -* 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 -- Drop x86-amd-arat-bug-on-sempron-workaround.patch; the proper fix is in 2.6.38.8 +* Wed Jun 08 2011 Kyle McMartin 3.0-0.rc2.git0.1 +- Update to 3.0-rc2, rebase utsname fix. +- Build IPv6 into the kernel for a variety of reasons + (http://lists.fedoraproject.org/pipermail/kernel/2011-June/003105.html) -* Sun May 29 2011 Dave Airlie -- fix oops on pageflipping sometimes (#680651) +* Mon Jun 06 2011 Kyle McMartin 3.0-0.rc1.git0.3 +- Conflict with module-init-tools older than 3.13 to ensure the + 3.0 transition is handled correctly. -* 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 Jun 01 2011 Kyle McMartin 3.0-0.rc1.git0.2 +- Fix utsname for 3.0-rc1 -* Wed May 25 2011 Dave Airlie -- drm-radeon-update2.patch: more radeon updates + cayman accel support +* Mon May 30 2011 Kyle McMartin 3.0-0.rc1.git0.1 +- Linux 3.0-rc1 (won't build until module-init-tools gets an update.) -* 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 - -* 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-27 -- [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) - -* 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: - 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 - -* 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) - -* 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) - -* 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 - -* 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) -- 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 - -* 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) - -* 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 -- nuvoton-cir: improve compatibility with lirc raw IR mode - -* 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) - -* 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) - -* 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. - -* 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 - -* 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 - -* 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) - -* 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) - -* 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 -- 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 - 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) - -* 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. -- 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 -- 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 - -* 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: - 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 -- 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 - 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 - -* 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) - -* 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 - -* Tue Mar 15 2011 Chuck Ebbert 2.6.38-1 -- Linux 2.6.38 - -* Mon Mar 14 2011 Chuck Ebbert 2.6.38-0.rc8.git4.1 -- Linux 2.6.38-rc8-git4 - -* Thu Mar 10 2011 Chuck Ebbert -- Linux 2.6.38-rc8-git3 - -* Thu Mar 10 2011 Chuck Ebbert 2.6.38-0.rc8.git2.1 -- Linux 2.6.38-rc8-git2 - -* Wed Mar 09 2011 Chuck Ebbert -- Linux 2.6.38-rc8-git1 - -* Wed Mar 09 2011 Dennis Gilmore -- apply sparc64 gcc-4.6.0 buildfix patch - -* Wed Mar 09 2011 Ben Skeggs 2.6.38-0.rc8.git0.2 -- nouveau: allow max clients on nv4x (679629), better error reporting - -* Tue Mar 08 2011 Chuck Ebbert 2.6.38-0.rc8.git0.1 -- Linux 2.6.38-rc8 - -* Sat Mar 05 2011 Chuck Ebbert 2.6.38-0.rc7.git4.1 -- Linux 2.6.38-rc7-git4 -- Revert upstream commit e3e89cc535223433a619d0969db3fa05cdd946b8 - for now to fix utrace build. - -* Fri Mar 04 2011 Roland McGrath - 2.6.38-0.rc7.git2.3 -- Split out perf-debuginfo subpackage. - -* Fri Mar 04 2011 Kyle McMartin 2.6.38-0.rc7.git2.2 -- Disable drm-i915-gen4-has-non-power-of-two-strides.patch for now, breaks - my mutter. - -* Fri Mar 04 2011 Kyle McMartin 2.6.38-0.rc7.git2.1 -- Linux 2.6.38-rc7-git2 -- drm-i915-gen4-has-non-power-of-two-strides.patch (#681285) - -* Thu Mar 03 2011 Chuck Ebbert 2.6.38-0.rc7.git1.1 -- Linux 2.6.38-rc7-git1 - -* Tue Mar 01 2011 Kyle McMartin 2.6.38-0.rc7.git0.1 -- Linux 2.6.38-rc7 - -* Fri Feb 25 2011 Chuck Ebbert 2.6.38-0.rc6.git6.1 -- Linux 2.6.38-rc6-git6 -- Build in virtio_pci driver so virtio_console will be built-in (#677713) - -* Thu Feb 24 2011 Chuck Ebbert 2.6.38-0.rc6.git4.1 -- Linux 2.6.38-rc6-git4 - -* Thu Feb 24 2011 Matthew Garrett 2.6.38-0.rc6.git2.2 -- linux-2.6-acpi-fix-implicit-notify.patch: Fix implicit notify when there's - more than one device per GPE - -* Wed Feb 23 2011 Chuck Ebbert 2.6.38-0.rc6.git2.1 -- Linux 2.6.38-rc6-git2 - -* Wed Feb 23 2011 Ben Skeggs 2.6.38-0.rc6.git0.2 -- nouveau: nv4x pciegart fixes, nvc0 accel improvements - -* Tue Feb 22 2011 Kyle McMartin 2.6.38-0.rc6.git0.1 -- Linux 2.6.38-rc6 - -* Tue Feb 22 2011 Chuck Ebbert 2.6.38-0.rc5.git7.1 -- Linux 2.6.38-rc5-git7 - -* Mon Feb 21 2011 Dave Jones 2.6.38-0.rc5.git6.1 -- Linux 2.6.38-rc5-git6 - -* Sat Feb 19 2011 Chuck Ebbert 2.6.38-0.rc5.git5.1 -- Linux 2.6.38-rc5-git5 - -* Wed Feb 16 2011 Chuck Ebbert 2.6.38-0.rc5.git1.1 -- Linux 2.6.38-rc5-git1 -- Add support for Airprime/Sierra USB IP modem (#676860) -- Make virtio_console built-in on x86_64 (#677713) -- Revert check for read-only block device added in .38 (#672265) - -* Tue Feb 15 2011 Kyle McMartin 2.6.38-0.rc5.git0.1 -- Linux 2.6.38-rc5 (81 minutes later...) - -* Sun Feb 13 2011 Chuck Ebbert 2.6.38-0.rc4.git7.1 -- Linux 2.6.38-rc4-git7 - -* Sat Feb 12 2011 Chuck Ebbert 2.6.38-0.rc4.git6.1 -- Linux 2.6.38-rc4-git6 -- Fix memory corruption caused by bug in bridge code. - -* Thu Feb 10 2011 Chuck Ebbert 2.6.38-0.rc4.git3.1 -- Linux 2.6.38-rc4-git3 - -* Mon Feb 07 2011 Fedora Release Engineering - 2.6.38-0.rc4.git0.2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild - -* Mon Feb 07 2011 Kyle McMartin 2.6.38-0.rc4.git0.1 -- Linux 2.6.38-rc4 - -* Fri Feb 04 2011 Chuck Ebbert 2.6.38-0.rc3.git4.1 -- Linux 2.6.38-rc3-git4 - -* Thu Feb 03 2011 Chuck Ebbert -- Linux 2.6.38-rc3-git3 -- Enable Advansys SCSI driver on x86_64 (#589115) - -* Thu Feb 03 2011 Kyle McMartin 2.6.38-0.rc3.git2.1 -- Linux 2.6.38-rc3-git2 snapshot -- [sgruszka] ath5k: fix fast channel change (#672778) - -* Wed Feb 02 2011 Kyle McMartin 2.6.38-0.rc3.git1.1 -- Linux 2.6.38-rc3-git1 snapshot. - -* Wed Feb 02 2011 Chuck Ebbert -- Fix autoload of atl1c driver for latest hardware (#607499) - -* Tue Feb 01 2011 Chuck Ebbert 2.6.38-0.rc3.git0.1 -- Linux 2.6.38-rc3 -- Try to fix some obvious bugs in hfsplus mount failure handling (#673857) - -* Mon Jan 31 2011 Chuck Ebbert 2.6.38-0.rc2.git9.1 -- Linux 2.6.38-rc2-git9 - -* Mon Jan 31 2011 Kyle McMartin -- disable CONFIG_SERIAL_8250_DETECT_IRQ (from mschmidt@redhat.com) - -* Mon Jan 31 2011 Chuck Ebbert -- Linux 2.6.38-rc2-git8 -- Add Trond's NFS bugfixes branch from git.linux-nfs.org - -* Mon Jan 31 2011 Chuck Ebbert 2.6.38-0.rc2.git7.2 -- Fix build failure on s390. - -* Fri Jan 28 2011 Chuck Ebbert 2.6.38-0.rc2.git7.1 -- Linux 2.6.38-rc2-git7 - -* Wed Jan 26 2011 Kyle McMartin 2.6.38-0.rc2.git5.1 -- Linux 2.6.38-rc2-git5 -- [x86] Re-enable TRANSPARENT_HUGEPAGE, should be fixed by cacf061c. - -* Tue Jan 25 2011 Kyle McMartin 2.6.38-0.rc2.git3.2 -- [x86] Disable TRANSPARENT_HUGEPAGE for now, there be dragons there. - -* Tue Jan 25 2011 Kyle McMartin 2.6.38-0.rc2.git3.1 -- Linux 2.6.38-rc2-git3 -- perf-gcc460-build-fixes.patch: fix context from [9486aa38] - -* Mon Jan 24 2011 Kyle McMartin 2.6.38-0.rc2.git1.3 -- Disable usb/pci/acpi autosuspend goo until it can be checked. - -* Mon Jan 24 2011 Kyle McMartin -- debug-tty-print-dev-name.patch: drop, haven't seen any warnings recently. -- runtime_pm_fixups.patch: rebase and re-enable, make acpi_power_transition - in pci_bind actually do the right thing instead of (likely) always - trying to transition to D0. - -* Mon Jan 24 2011 Kyle McMartin 2.6.38-0.rc2.git1.1 -- Linux 2.6.38-rc2-git1 -- [e5cce6c1] tpm: fix panic caused by "tpm: Autodetect itpm devices" - may fix some boot issues people were having. -- tpm-fix-stall-on-boot.patch: upstream. -- perf-gcc460-build-fixes.patch: fix build issues with warn-unused-but-set - in gcc 4.6.0 - -* Sat Jan 22 2011 Kyle McMartin 2.6.38-0.rc2.git0.1 -- Linux 2.6.38-rc2 -- linux-2.6-serial-460800.patch, drivers/serial => drivers/tty/serial - -* Thu Jan 20 2011 Kyle McMartin 2.6.38-0.rc1.git1.1 -- Linux 2.6.38-rc1-git1, should fix boot failure in -rc1. - -* Wed Jan 19 2011 Roland McGrath -- utrace update - -* Wed Jan 19 2011 Kyle McMartin 2.6.38-0.rc1.git0.1 -- Linux 2.6.38-rc1 - -* Tue Jan 18 2011 Kyle McMartin 2.6.38-0.rc0.git18.1 -- Linux 2.6.37-git18 - -* Mon Jan 17 2011 Kyle McMartin 2.6.38-0.rc0.git16.1 -- Linux 2.6.37-git16 -- config changes: - - CONFIG_SQUASHFS_XZ=y [generic] - - CONFIG_SPARSE_IRQ=y [arm] - -* Sat Jan 15 2011 Kyle McMartin 2.6.38-0.rc0.git13.1 -- Linux 2.6.37-git13 -- Drop xen_export-arbitrary_virt_to_machine.patch, upstream. - -* Fri Jan 14 2011 Kyle McMartin -- xen_export-arbitrary_virt_to_machine.patch: pull patch from upstream - to fix build error. - -* Fri Jan 14 2011 Kyle McMartin 2.6.38-0.rc0.git12.1 -- Linux 2.6.37-git12 -- 0001-use-__devexit-not-__exit-in-n2_unregister_algs-fixes.patch: drop - upstream patch. -- acpi-update-battery-information-on-notification-0x81.patch: drop upstream - patch. -- mm-*.patch: drop upstream patches. -- important config changes: - ACPI_IPMI=m - CRYPTO_AES_NI_INTEL=m [i386] - TRANSPARENT_HUGEPAGE=y - -* Wed Jan 12 2011 Kyle McMartin 2.6.38-0.rc0.git9.1 -- Linux 2.6.37-git9 -- Re-enable DEBUG_SET_MODULE_RONX since commit 94462ad3 fixed it. -- Enable some more new random HID and sensor junk as modules. - -* Tue Jan 11 2011 Matthew Garrett -- linux-2.6-ehci-check-port-status.patch - fix USB resume on some AMD systems - -* Mon Jan 10 2011 Jarod Wilson -- Add support for local rebuild config option overrides -- Add missing --with/--without pae build flag support - -* Mon Jan 10 2011 Kyle McMartin 2.6.38-0.rc0.git4.2 -- Disable DEBUG_SET_MODULE_RONX for now, it causes boot-up to fail since - dynamic ftrace is trying to rewrite instructions on module load. - -* Mon Jan 10 2011 Kyle McMartin -- Drop obsolete linux-2.6-debug-nmi-timeout.patch - -* Mon Jan 10 2011 Kyle McMartin 2.6.38-0.rc0.git4.1 -- Branch for 2.6.38 -- Rebase trivial patches. -- Switch debug configs back on. -- config changes: - DEBUG_SET_MODULE_RONX=y - B43_PHY_N=y - RT2800USB_RT33XX=y | - RT2800PCI_RT33XX=y | experimental - WL12XX=m - RTL8192CE=m - CAN_SLCAN=m - SCHED_AUTOGROUP=n - -* Fri Jan 07 2011 Kyle McMartin 2.6.37-2 -- drm_i915-check-eDP-encoder-correctly-when-setting-modes.patch reported to - fix HP/Sony eDP issues by adamw and airlied. - -* Wed Jan 05 2011 Dennis Gilmore -- build sparc headers on sparcv9 - -* Tue Jan 04 2011 Dennis Gilmore -- add patch for sparc build failure - -* Tue Jan 04 2011 Kyle McMartin 2.6.37-1 -- Track release of 2.6.37 - -* Mon Jan 03 2011 Kyle McMartin 2.6.37-0.rc8.git3.1 -- Linux 2.6.37-rc8-git3 -- Merged acpi battery notification patch and -rc8. - -* Thu Dec 23 2010 Kyle McMartin -- Pull in flexcop procfs rename patch since it's still not upstream. (#664852) - -* Tue Dec 21 2010 Kyle McMartin 2.6.37.0.rc7.git0.2 -- Linux 2.6.37-rc7 -- CONFIG_USB_OTG=n (seems unnecessary?) -- Enable release builds until .37 releases in rawhide. - -* Sun Dec 19 2010 Kyle McMartin 2.6.37-0.rc6.git5.1 -- Linux 2.6.37-rc6-git5 -- sched-cure-more-NO_HZ-load-average-woes.patch: upstream. - -* Sat Dec 18 2010 Kyle McMartin -- Patch from nhorman against f13: - Enhance AF_PACKET to allow non-contiguous buffer alloc (#637619) - -* Sat Dec 18 2010 Kyle McMartin -- Fix SELinux issues with NFS/btrfs and/or xfsdump. (#662344) - -* Fri Dec 17 2010 Matthew Garrett 2.6.37-0.rc6.git0.3 -- efi_default_physical.patch: Revert hunk that breaks boot -- linux-next-macbook-air-input.patch: Add input support for new Macbook Airs - -* Thu Dec 16 2010 Matthew Garrett 2.6.37-0.rc6.git0.2 -- applesmc_update.patch: Make the driver more generic. Should help Apples. -- apple_backlight.patch: Make sure that this loads on all hardware. -- efifb_update.patch: Fixes for the 11 inch Macbook Air -- acpi_reboot.patch: Should make reboot work better on most hardware -- efi_default_physical.patch: Some machines dislike EFI virtual mode - -* Wed Dec 15 2010 Kyle McMartin 2.6.37-0.rc6.git0.1 -- Linux 2.6.37-rc6 -- Re-activate acpi patch which rejected on the previous commit. - -* Wed Dec 15 2010 Kyle McMartin 2.6.37-0.rc5.git5.1 -- 2.6.37-rc5-git5 - -* Fri Dec 10 2010 Kyle McMartin -- Another patch from mjg59: Set _OSC supported field correctly (#638912) - -* Fri Dec 10 2010 Kyle McMartin -- pci-disable-aspm-if-bios-asks-us-to.patch: Patch from mjg59 to disable - ASPM if the BIOS has disabled it, but enabled it already on some devices. - -* Thu Dec 09 2010 Kyle McMartin -- Snarf patch from wireless-next to fix mdomsch's orinico wifi. - (orinoco: initialise priv->hw before assigning the interrupt) - [229bd792] (#657864) - -* Wed Dec 08 2010 Kyle McMartin 2.6.37-0.rc5.git2.1 -- Linux 2.6.37-rc5-git2 -- sched-cure-more-NO_HZ-load-average-woes.patch: fix some of the complaints - in 2.6.35+ about load average with dynticks. (rhbz#650934) - -* Tue Dec 07 2010 Kyle McMartin 2.6.37-0.rc5.git0.1 -- Linux 2.6.37-rc5 - -* Sat Dec 04 2010 Kyle McMartin -- Enable C++ symbol demangling with perf by linking against libiberty.a, - which is LGPL2. - -* Fri Dec 03 2010 Kyle McMartin -- Linux 2.6.37-rc4-git3 -- Enable HP ILO on x86_64 for (#571329) -- Drop merged drm-fixes.patch, split out edp-fixes. -- tty-dont-allow-reopen-when-ldisc-is-changing.patch: upstream. -- tty-ldisc-fix-open-flag-handling.patch: upstream. -- Enable CIFS_ACL. - -* Thu Dec 02 2010 Kyle McMartin -- Grab some of Mel's fixes from -mmotm to hopefully sort out #649694. - -* Wed Dec 01 2010 Kyle McMartin 2.6.37-0.rc4.git1.1 -- Linux 2.6.37-rc4-git1 -- Pull in DRM fixes that are queued for -rc5 [3074adc8] - + edp-fixes on top - -* Tue Nov 30 2010 Kyle McMartin 2.6.37-0.rc4.git0.1 -- Linux 2.6.37-rc4 - -* Mon Nov 29 2010 Kyle McMartin -- Update debug-vm-would_have_oomkilled patch. - -* Mon Nov 29 2010 Kyle McMartin 2.6.37-0.rc3.git6.1 -- Linux 2.6.37-rc3-git6 -- TTY: open/hangup race fixup (rhbz#630464) - -* Fri Nov 26 2010 Kyle McMartin 2.6.37-0.rc3.git3.1 -- Linux 2.6.37-rc3-git3 -- Print tty->flags as well in debugging patch... - -* Fri Nov 26 2010 Kyle McMartin -- Copy tty_open WARN_ON debugging patch from rawhide. - -* Fri Nov 26 2010 Kyle McMartin 2.6.37-0.rc3.git2.1 -- Linux 2.6.37-rc3-git2 -- CGROUP_MEM_RES_CTLR_SWAP_ENABLED is not set, so the cgroup memory - resource controller swap accounting is disabled by default. You can - enable it with 'swapaccount' if desired. -- TTY: don't allow reopen when ldisc is changing (rhbz#630464) - -* Wed Nov 24 2010 Kyle McMartin 2.6.37-0.rc3.git1.1 -- Linux 2.6.37-rc3-git1 - -* Mon Nov 22 2010 Kyle McMartin 2.6.37-0.rc3.git0.1 -- Linux 2.6.37-rc3 - -* Sat Nov 20 2010 Kyle McMartin 2.6.37-0.rc2.git7.1 -- Linux 2.6.37-rc2-git7 - -* Fri Nov 19 2010 Kyle McMartin 2.6.37-0.rc2.git5.1 -- Linux 2.6.37-rc2-git5 - -* Thu Nov 18 2010 Kyle McMartin -- Move %{fedora_build} in the un-released (ie: -git/-rc) kernel case for - a variety of reasons, principally so that: - 1: Bumping %baserelease isn't needed if we're just updating snapshots. - 2: %buildid will sort as newer so we don't need to bump baserelease when - building bugzilla fixes. - -* Wed Nov 17 2010 Kyle McMartin 2.6.37-0.1.rc2.git2 -- Linux 2.6.37-rc2-git2 -- enable STRICT_DEVMEM on s390x. - -* Wed Nov 17 2010 Kyle McMartin -- Make vmlinuz/System.map root read-write only by default. You can just - chmod 644 them later if you (unlikely) need them without root. - -* Mon Nov 15 2010 Kyle McMartin 2.6.37-0.1.rc2.git0 -- Linux 2.6.37-rc2 - -* Sat Nov 13 2010 Kyle McMartin 2.6.37-0.1.rc1.git10 -- Linux 2.6.37-rc1-git10 -- SECURITY_DMESG_RESTRICT added, the principle of least surprise dictates - we should probably have it off. If you want to restrict dmesg access - you may use the kernel.dmesg_restrict sysctl. -- linux-2.6-bluetooth-autosuspend.patch: merged upstream. - -* Tue Nov 09 2010 Kyle McMartin 2.6.37-0.1.rc1.git7 -- Linux 2.6.37-rc1-git7 - -* Mon Nov 08 2010 Kyle McMartin 2.6.37-0.1.rc1.git5 -- Linux 2.6.37-rc1-git5 - -* Mon Nov 08 2010 Kyle McMartin -- Cherry-pick utrace-ptrace fixes from mayoung. Thanks! - -* Tue Nov 02 2010 Kyle McMartin 2.6.37-0.1.rc1.git0 -- Linux 2.6.37-rc1 - -* Tue Oct 26 2010 Kyle McMartin 2.6.37-0.1.rc0.git8 -- Linux 2.6.36-git8 - -* Fri Oct 22 2010 Kyle McMartin 2.6.37-0.1.rc0.git2 -- Switch to tracking git snapshots of what will become 2.6.37. -- Fix context rejects in utrace and a few other patches. - -* Wed Oct 20 2010 Chuck Ebbert 2.6.36-1 -- Linux 2.6.36 +* Mon May 30 2011 Kyle McMartin +- Trimmed changelog, see fedpkg git for earlier history. ### # The following Emacs magic makes C-c C-e use UTC dates. 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/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 deleted file mode 100644 index 85016b40a..000000000 --- a/libata-sas-only-set-frozen-flag-if-new-eh-is-supported.patch +++ /dev/null @@ -1,72 +0,0 @@ -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); diff --git a/linux-2.6-32bit-mmap-exec-randomization.patch b/linux-2.6-32bit-mmap-exec-randomization.patch index dd40b60df..6008173b0 100644 --- a/linux-2.6-32bit-mmap-exec-randomization.patch +++ b/linux-2.6-32bit-mmap-exec-randomization.patch @@ -1,3 +1,13 @@ +Before: +Heap randomisation test (PIE) : 16 bits (guessed) +Main executable randomisation (PIE) : 8 bits (guessed) + +after: +Heap randomisation test (PIE) : 19 bits (guessed) +Main executable randomisation (PIE) : 12 bits (guessed) + + + --- b/include/linux/sched.h +++ b/include/linux/sched.h @@ -397,6 +397,10 @@ 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..b8377d321 100644 --- a/linux-2.6-crash-driver.patch +++ b/linux-2.6-crash-driver.patch @@ -220,20 +220,6 @@ 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. - -+config CRASH -+ tristate "Crash Utility memory driver" - - config LEGACY_PTY_COUNT - int "Maximum number of legacy PTY in use" - diff --git a/drivers/char/crash.c b/drivers/char/crash.c new file mode 100644 index 0000000..e5437de @@ -379,3 +365,18 @@ index ba53ec9..6588b33 100644 js-rtc-y = rtc.o + +obj-$(CONFIG_CRASH) += crash.o + +diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig +index 04f8b2d..e8fb997 100644 +--- a/drivers/char/Kconfig ++++ b/drivers/char/Kconfig +@@ -4,6 +4,9 @@ + + menu "Character devices" + ++config CRASH ++ tristate "Crash Utility memory driver" ++ + source "drivers/tty/Kconfig" + + config DEVKMEM 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-defaults-pci_no_msi.patch b/linux-2.6-defaults-pci_no_msi.patch deleted file mode 100644 index 29a84e8d2..000000000 --- a/linux-2.6-defaults-pci_no_msi.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 14bdd0d36f5284108468bb73afd50726b07c7a84 Mon Sep 17 00:00:00 2001 -From: Kyle McMartin -Date: Mon, 29 Mar 2010 23:43:49 -0400 -Subject: linux-2.6-defaults-pci_no_msi - ---- - Documentation/kernel-parameters.txt | 3 +++ - drivers/pci/Kconfig | 12 ++++++++++++ - drivers/pci/msi.c | 9 +++++++++ - drivers/pci/pci.c | 2 ++ - drivers/pci/pci.h | 2 ++ - 5 files changed, 28 insertions(+), 0 deletions(-) - -diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index e4cbca5..8154a0f 100644 ---- a/Documentation/kernel-parameters.txt -+++ b/Documentation/kernel-parameters.txt -@@ -1911,6 +1911,9 @@ and is between 256 and 4096 characters. It is defined in the file - check_enable_amd_mmconf [X86] check for and enable - properly configured MMIO access to PCI - config space on AMD family 10h CPU -+ msi [MSI] If the PCI_MSI kernel config parameter is -+ enabled, this kernel boot option can be used to -+ enable the use of MSI interrupts system-wide. - nomsi [MSI] If the PCI_MSI kernel config parameter is - enabled, this kernel boot option can be used to - disable the use of MSI interrupts system-wide. -diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig -index 7858a11..b12fcad 100644 ---- a/drivers/pci/Kconfig -+++ b/drivers/pci/Kconfig -@@ -21,6 +21,18 @@ config PCI_MSI - - If you don't know what to do here, say Y. - -+config PCI_MSI_DEFAULT_ON -+ def_bool y -+ prompt "Use Message Signaled Interrupts by default" -+ depends on PCI_MSI -+ help -+ Selecting this option will enable use of PCI MSI where applicable -+ by default. Support for MSI can be disabled through the use of the -+ pci=nomsi boot flag. Conversely, if this option is not selected, -+ support for PCI MSI can be enabled by passing the pci=msi flag. -+ -+ If you don't know what to do here, say N. -+ - config PCI_DEBUG - bool "PCI Debugging" - depends on PCI && DEBUG_KERNEL -diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c -index f9cf317..6b0539a 100644 ---- a/drivers/pci/msi.c -+++ b/drivers/pci/msi.c -@@ -22,7 +22,11 @@ - #include "pci.h" - #include "msi.h" - -+#ifdef CONFIG_PCI_MSI_DEFAULT_ON - static int pci_msi_enable = 1; -+#else -+static int pci_msi_enable = 0; -+#endif /*CONFIG_PCI_MSI_DEFAULT_ON*/ - - /* Arch hooks */ - -@@ -836,6 +840,11 @@ int pci_msi_enabled(void) - } - EXPORT_SYMBOL(pci_msi_enabled); - -+void pci_yes_msi(void) -+{ -+ pci_msi_enable = 1; -+} -+ - void pci_msi_init_pci_dev(struct pci_dev *dev) - { - INIT_LIST_HEAD(&dev->msi_list); -diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c -index 1531f3a..3cb332b 100644 ---- a/drivers/pci/pci.c -+++ b/drivers/pci/pci.c -@@ -2983,6 +2983,8 @@ static int __init pci_setup(char *str) - if (*str && (str = pcibios_setup(str)) && *str) { - if (!strcmp(str, "nomsi")) { - pci_no_msi(); -+ } else if (!strcmp(str, "msi")) { -+ pci_yes_msi(); - } else if (!strcmp(str, "noaer")) { - pci_no_aer(); - } else if (!strcmp(str, "nodomains")) { -diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h -index 4eb10f4..caa051e 100644 ---- a/drivers/pci/pci.h -+++ b/drivers/pci/pci.h -@@ -122,9 +122,11 @@ extern unsigned int pci_pm_d3_delay; - - #ifdef CONFIG_PCI_MSI - void pci_no_msi(void); -+void pci_yes_msi(void); - extern void pci_msi_init_pci_dev(struct pci_dev *dev); - #else - static inline void pci_no_msi(void) { } -+static inline void pci_yes_msi(void) { } - static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { } - #endif - --- -1.7.0.1 - diff --git a/linux-2.6-defaults-pci_use_crs.patch b/linux-2.6-defaults-pci_use_crs.patch deleted file mode 100644 index 18acee12d..000000000 --- a/linux-2.6-defaults-pci_use_crs.patch +++ /dev/null @@ -1,29 +0,0 @@ -diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig -index cea0cd9..c326065 100644 ---- a/arch/x86/Kconfig -+++ b/arch/x86/Kconfig -@@ -2142,3 +2142,8 @@ source "crypto/Kconfig" - source "arch/x86/kvm/Kconfig" - - source "lib/Kconfig" -+ -+config PCI_DEFAULT_USE_CRS -+ def_bool y -+ prompt "Use PCI Host Bridge Windows from ACPI by default?" -+ depends on ACPI -diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c -index 15466c0..3099406 100644 ---- a/arch/x86/pci/acpi.c -+++ b/arch/x86/pci/acpi.c -@@ -16,7 +16,11 @@ struct pci_root_info { - int busnum; - }; - -+#ifdef CONFIG_PCI_DEFAULT_USE_CRS - static bool pci_use_crs = true; -+#else -+static bool pci_use_crs = false; -+#endif - - static int __init set_use_crs(const struct dmi_system_id *id) - { diff --git a/linux-2.6-firewire-git-pending.patch b/linux-2.6-firewire-git-pending.patch deleted file mode 100644 index e05471f1b..000000000 --- a/linux-2.6-firewire-git-pending.patch +++ /dev/null @@ -1,4 +0,0 @@ -# -# Patches under review and/or pending inclusion in the linux1394-git -# tree (and/or in by the time your read this), which we want... -# diff --git a/linux-2.6-firewire-git-update.patch b/linux-2.6-firewire-git-update.patch deleted file mode 100644 index 685808133..000000000 --- a/linux-2.6-firewire-git-update.patch +++ /dev/null @@ -1,3682 +0,0 @@ -linux1394-2.6.git tree vs. linus v2.6.29-rc3-git1 on 20090130 by jarod - ---- - firewire-git/drivers/firewire/fw-card.c | 68 - - firewire-git/drivers/firewire/fw-cdev.c | 1014 +++++++++++++++++-------- - firewire-git/drivers/firewire/fw-device.c | 43 - - firewire-git/drivers/firewire/fw-device.h | 7 - firewire-git/drivers/firewire/fw-iso.c | 225 ++++- - firewire-git/drivers/firewire/fw-ohci.c | 236 ++--- - firewire-git/drivers/firewire/fw-sbp2.c | 57 - - firewire-git/drivers/firewire/fw-topology.c | 28 - firewire-git/drivers/firewire/fw-topology.h | 19 - firewire-git/drivers/firewire/fw-transaction.c | 151 +-- - firewire-git/drivers/firewire/fw-transaction.h | 125 --- - include/linux/firewire-cdev.h | 170 +++- - 12 files changed, 1359 insertions(+), 784 deletions(-) - -diff -Naurp linux-2.6-git/drivers/firewire/fw-card.c firewire-git/drivers/firewire/fw-card.c ---- linux-2.6-git/drivers/firewire/fw-card.c 2009-01-30 13:39:02.989651512 -0500 -+++ firewire-git/drivers/firewire/fw-card.c 2009-01-30 13:35:51.859771884 -0500 -@@ -63,8 +63,7 @@ static int descriptor_count; - #define BIB_CMC ((1) << 30) - #define BIB_IMC ((1) << 31) - --static u32 * --generate_config_rom(struct fw_card *card, size_t *config_rom_length) -+static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) - { - struct fw_descriptor *desc; - static u32 config_rom[256]; -@@ -128,8 +127,7 @@ generate_config_rom(struct fw_card *card - return config_rom; - } - --static void --update_config_roms(void) -+static void update_config_roms(void) - { - struct fw_card *card; - u32 *config_rom; -@@ -141,8 +139,7 @@ update_config_roms(void) - } - } - --int --fw_core_add_descriptor(struct fw_descriptor *desc) -+int fw_core_add_descriptor(struct fw_descriptor *desc) - { - size_t i; - -@@ -171,8 +168,7 @@ fw_core_add_descriptor(struct fw_descrip - return 0; - } - --void --fw_core_remove_descriptor(struct fw_descriptor *desc) -+void fw_core_remove_descriptor(struct fw_descriptor *desc) - { - mutex_lock(&card_mutex); - -@@ -189,8 +185,7 @@ static const char gap_count_table[] = { - 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 - }; - --void --fw_schedule_bm_work(struct fw_card *card, unsigned long delay) -+void fw_schedule_bm_work(struct fw_card *card, unsigned long delay) - { - int scheduled; - -@@ -200,8 +195,7 @@ fw_schedule_bm_work(struct fw_card *card - fw_card_put(card); - } - --static void --fw_card_bm_work(struct work_struct *work) -+static void fw_card_bm_work(struct work_struct *work) - { - struct fw_card *card = container_of(work, struct fw_card, work.work); - struct fw_device *root_device; -@@ -371,17 +365,16 @@ fw_card_bm_work(struct work_struct *work - fw_card_put(card); - } - --static void --flush_timer_callback(unsigned long data) -+static void flush_timer_callback(unsigned long data) - { - struct fw_card *card = (struct fw_card *)data; - - fw_flush_transactions(card); - } - --void --fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, -- struct device *device) -+void fw_card_initialize(struct fw_card *card, -+ const struct fw_card_driver *driver, -+ struct device *device) - { - static atomic_t index = ATOMIC_INIT(-1); - -@@ -406,9 +399,8 @@ fw_card_initialize(struct fw_card *card, - } - EXPORT_SYMBOL(fw_card_initialize); - --int --fw_card_add(struct fw_card *card, -- u32 max_receive, u32 link_speed, u64 guid) -+int fw_card_add(struct fw_card *card, -+ u32 max_receive, u32 link_speed, u64 guid) - { - u32 *config_rom; - size_t length; -@@ -435,23 +427,20 @@ EXPORT_SYMBOL(fw_card_add); - * dummy driver just fails all IO. - */ - --static int --dummy_enable(struct fw_card *card, u32 *config_rom, size_t length) -+static int dummy_enable(struct fw_card *card, u32 *config_rom, size_t length) - { - BUG(); - return -1; - } - --static int --dummy_update_phy_reg(struct fw_card *card, int address, -- int clear_bits, int set_bits) -+static int dummy_update_phy_reg(struct fw_card *card, int address, -+ int clear_bits, int set_bits) - { - return -ENODEV; - } - --static int --dummy_set_config_rom(struct fw_card *card, -- u32 *config_rom, size_t length) -+static int dummy_set_config_rom(struct fw_card *card, -+ u32 *config_rom, size_t length) - { - /* - * We take the card out of card_list before setting the dummy -@@ -461,27 +450,23 @@ dummy_set_config_rom(struct fw_card *car - return -1; - } - --static void --dummy_send_request(struct fw_card *card, struct fw_packet *packet) -+static void dummy_send_request(struct fw_card *card, struct fw_packet *packet) - { - packet->callback(packet, card, -ENODEV); - } - --static void --dummy_send_response(struct fw_card *card, struct fw_packet *packet) -+static void dummy_send_response(struct fw_card *card, struct fw_packet *packet) - { - packet->callback(packet, card, -ENODEV); - } - --static int --dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet) -+static int dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet) - { - return -ENOENT; - } - --static int --dummy_enable_phys_dma(struct fw_card *card, -- int node_id, int generation) -+static int dummy_enable_phys_dma(struct fw_card *card, -+ int node_id, int generation) - { - return -ENODEV; - } -@@ -496,16 +481,14 @@ static struct fw_card_driver dummy_drive - .enable_phys_dma = dummy_enable_phys_dma, - }; - --void --fw_card_release(struct kref *kref) -+void fw_card_release(struct kref *kref) - { - struct fw_card *card = container_of(kref, struct fw_card, kref); - - complete(&card->done); - } - --void --fw_core_remove_card(struct fw_card *card) -+void fw_core_remove_card(struct fw_card *card) - { - card->driver->update_phy_reg(card, 4, - PHY_LINK_ACTIVE | PHY_CONTENDER, 0); -@@ -529,8 +512,7 @@ fw_core_remove_card(struct fw_card *card - } - EXPORT_SYMBOL(fw_core_remove_card); - --int --fw_core_initiate_bus_reset(struct fw_card *card, int short_reset) -+int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset) - { - int reg = short_reset ? 5 : 1; - int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET; -diff -Naurp linux-2.6-git/drivers/firewire/fw-cdev.c firewire-git/drivers/firewire/fw-cdev.c ---- linux-2.6-git/drivers/firewire/fw-cdev.c 2008-11-04 11:19:19.000000000 -0500 -+++ firewire-git/drivers/firewire/fw-cdev.c 2009-01-30 13:35:51.860646788 -0500 -@@ -18,87 +18,162 @@ - * 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 - #include -+#include - #include --#include --#include --#include --#include --#include -+#include -+#include -+#include -+ - #include - #include --#include "fw-transaction.h" --#include "fw-topology.h" -+ - #include "fw-device.h" -+#include "fw-topology.h" -+#include "fw-transaction.h" -+ -+struct client { -+ u32 version; -+ struct fw_device *device; -+ -+ spinlock_t lock; -+ bool in_shutdown; -+ struct idr resource_idr; -+ struct list_head event_list; -+ wait_queue_head_t wait; -+ u64 bus_reset_closure; -+ -+ struct fw_iso_context *iso_context; -+ u64 iso_closure; -+ struct fw_iso_buffer buffer; -+ unsigned long vm_start; - --struct client; --struct client_resource { - struct list_head link; -- void (*release)(struct client *client, struct client_resource *r); -- u32 handle; -+ struct kref kref; -+}; -+ -+static inline void client_get(struct client *client) -+{ -+ kref_get(&client->kref); -+} -+ -+static void client_release(struct kref *kref) -+{ -+ struct client *client = container_of(kref, struct client, kref); -+ -+ fw_device_put(client->device); -+ kfree(client); -+} -+ -+static void client_put(struct client *client) -+{ -+ kref_put(&client->kref, client_release); -+} -+ -+struct client_resource; -+typedef void (*client_resource_release_fn_t)(struct client *, -+ struct client_resource *); -+struct client_resource { -+ client_resource_release_fn_t release; -+ int handle; -+}; -+ -+struct address_handler_resource { -+ struct client_resource resource; -+ struct fw_address_handler handler; -+ __u64 closure; -+ struct client *client; -+}; -+ -+struct outbound_transaction_resource { -+ struct client_resource resource; -+ struct fw_transaction transaction; -+}; -+ -+struct inbound_transaction_resource { -+ struct client_resource resource; -+ struct fw_request *request; -+ void *data; -+ size_t length; - }; - -+struct descriptor_resource { -+ struct client_resource resource; -+ struct fw_descriptor descriptor; -+ u32 data[0]; -+}; -+ -+struct iso_resource { -+ struct client_resource resource; -+ struct client *client; -+ /* Schedule work and access todo only with client->lock held. */ -+ struct delayed_work work; -+ enum {ISO_RES_ALLOC, ISO_RES_REALLOC, ISO_RES_DEALLOC, -+ ISO_RES_ALLOC_ONCE, ISO_RES_DEALLOC_ONCE,} todo; -+ int generation; -+ u64 channels; -+ s32 bandwidth; -+ struct iso_resource_event *e_alloc, *e_dealloc; -+}; -+ -+static void schedule_iso_resource(struct iso_resource *); -+static void release_iso_resource(struct client *, struct client_resource *); -+ - /* - * dequeue_event() just kfree()'s the event, so the event has to be -- * the first field in the struct. -+ * the first field in a struct XYZ_event. - */ -- - struct event { - struct { void *data; size_t size; } v[2]; - struct list_head link; - }; - --struct bus_reset { -+struct bus_reset_event { - struct event event; - struct fw_cdev_event_bus_reset reset; - }; - --struct response { -+struct outbound_transaction_event { - struct event event; -- struct fw_transaction transaction; - struct client *client; -- struct client_resource resource; -+ struct outbound_transaction_resource r; - struct fw_cdev_event_response response; - }; - --struct iso_interrupt { -+struct inbound_transaction_event { - struct event event; -- struct fw_cdev_event_iso_interrupt interrupt; -+ struct fw_cdev_event_request request; - }; - --struct client { -- u32 version; -- struct fw_device *device; -- spinlock_t lock; -- u32 resource_handle; -- struct list_head resource_list; -- struct list_head event_list; -- wait_queue_head_t wait; -- u64 bus_reset_closure; -- -- struct fw_iso_context *iso_context; -- u64 iso_closure; -- struct fw_iso_buffer buffer; -- unsigned long vm_start; -+struct iso_interrupt_event { -+ struct event event; -+ struct fw_cdev_event_iso_interrupt interrupt; -+}; - -- struct list_head link; -+struct iso_resource_event { -+ struct event event; -+ struct fw_cdev_event_iso_resource resource; - }; - --static inline void __user * --u64_to_uptr(__u64 value) -+static inline void __user *u64_to_uptr(__u64 value) - { - return (void __user *)(unsigned long)value; - } - --static inline __u64 --uptr_to_u64(void __user *ptr) -+static inline __u64 uptr_to_u64(void __user *ptr) - { - return (__u64)(unsigned long)ptr; - } -@@ -107,7 +182,6 @@ static int fw_device_op_open(struct inod - { - struct fw_device *device; - struct client *client; -- unsigned long flags; - - device = fw_device_get_by_devt(inode->i_rdev); - if (device == NULL) -@@ -125,16 +199,17 @@ static int fw_device_op_open(struct inod - } - - client->device = device; -- INIT_LIST_HEAD(&client->event_list); -- INIT_LIST_HEAD(&client->resource_list); - spin_lock_init(&client->lock); -+ idr_init(&client->resource_idr); -+ INIT_LIST_HEAD(&client->event_list); - init_waitqueue_head(&client->wait); -+ kref_init(&client->kref); - - file->private_data = client; - -- spin_lock_irqsave(&device->card->lock, flags); -+ mutex_lock(&device->client_list_mutex); - list_add_tail(&client->link, &device->client_list); -- spin_unlock_irqrestore(&device->card->lock, flags); -+ mutex_unlock(&device->client_list_mutex); - - return 0; - } -@@ -150,68 +225,69 @@ static void queue_event(struct client *c - event->v[1].size = size1; - - spin_lock_irqsave(&client->lock, flags); -- list_add_tail(&event->link, &client->event_list); -+ if (client->in_shutdown) -+ kfree(event); -+ else -+ list_add_tail(&event->link, &client->event_list); - spin_unlock_irqrestore(&client->lock, flags); - - wake_up_interruptible(&client->wait); - } - --static int --dequeue_event(struct client *client, char __user *buffer, size_t count) -+static int dequeue_event(struct client *client, -+ char __user *buffer, size_t count) - { -- unsigned long flags; - struct event *event; - size_t size, total; -- int i, retval; -+ int i, ret; - -- retval = wait_event_interruptible(client->wait, -- !list_empty(&client->event_list) || -- fw_device_is_shutdown(client->device)); -- if (retval < 0) -- return retval; -+ ret = wait_event_interruptible(client->wait, -+ !list_empty(&client->event_list) || -+ fw_device_is_shutdown(client->device)); -+ if (ret < 0) -+ return ret; - - if (list_empty(&client->event_list) && - fw_device_is_shutdown(client->device)) - return -ENODEV; - -- spin_lock_irqsave(&client->lock, flags); -- event = container_of(client->event_list.next, struct event, link); -+ spin_lock_irq(&client->lock); -+ event = list_first_entry(&client->event_list, struct event, link); - list_del(&event->link); -- spin_unlock_irqrestore(&client->lock, flags); -+ spin_unlock_irq(&client->lock); - - total = 0; - for (i = 0; i < ARRAY_SIZE(event->v) && total < count; i++) { - size = min(event->v[i].size, count - total); - if (copy_to_user(buffer + total, event->v[i].data, size)) { -- retval = -EFAULT; -+ ret = -EFAULT; - goto out; - } - total += size; - } -- retval = total; -+ ret = total; - - out: - kfree(event); - -- return retval; -+ return ret; - } - --static ssize_t --fw_device_op_read(struct file *file, -- char __user *buffer, size_t count, loff_t *offset) -+static ssize_t fw_device_op_read(struct file *file, char __user *buffer, -+ size_t count, loff_t *offset) - { - struct client *client = file->private_data; - - return dequeue_event(client, buffer, count); - } - --/* caller must hold card->lock so that node pointers can be dereferenced here */ --static void --fill_bus_reset_event(struct fw_cdev_event_bus_reset *event, -- struct client *client) -+static void fill_bus_reset_event(struct fw_cdev_event_bus_reset *event, -+ struct client *client) - { - struct fw_card *card = client->device->card; - -+ spin_lock_irq(&card->lock); -+ - event->closure = client->bus_reset_closure; - event->type = FW_CDEV_EVENT_BUS_RESET; - event->generation = client->device->generation; -@@ -220,39 +296,49 @@ fill_bus_reset_event(struct fw_cdev_even - event->bm_node_id = 0; /* FIXME: We don't track the BM. */ - event->irm_node_id = card->irm_node->node_id; - event->root_node_id = card->root_node->node_id; -+ -+ spin_unlock_irq(&card->lock); - } - --static void --for_each_client(struct fw_device *device, -- void (*callback)(struct client *client)) -+static void for_each_client(struct fw_device *device, -+ void (*callback)(struct client *client)) - { -- struct fw_card *card = device->card; - struct client *c; -- unsigned long flags; -- -- spin_lock_irqsave(&card->lock, flags); - -+ mutex_lock(&device->client_list_mutex); - list_for_each_entry(c, &device->client_list, link) - callback(c); -+ mutex_unlock(&device->client_list_mutex); -+} -+ -+static int schedule_reallocations(int id, void *p, void *data) -+{ -+ struct client_resource *r = p; - -- spin_unlock_irqrestore(&card->lock, flags); -+ if (r->release == release_iso_resource) -+ schedule_iso_resource(container_of(r, -+ struct iso_resource, resource)); -+ return 0; - } - --static void --queue_bus_reset_event(struct client *client) -+static void queue_bus_reset_event(struct client *client) - { -- struct bus_reset *bus_reset; -+ struct bus_reset_event *e; - -- bus_reset = kzalloc(sizeof(*bus_reset), GFP_ATOMIC); -- if (bus_reset == NULL) { -+ e = kzalloc(sizeof(*e), GFP_KERNEL); -+ if (e == NULL) { - fw_notify("Out of memory when allocating bus reset event\n"); - return; - } - -- fill_bus_reset_event(&bus_reset->reset, client); -+ fill_bus_reset_event(&e->reset, client); -+ -+ queue_event(client, &e->event, -+ &e->reset, sizeof(e->reset), NULL, 0); - -- queue_event(client, &bus_reset->event, -- &bus_reset->reset, sizeof(bus_reset->reset), NULL, 0); -+ spin_lock_irq(&client->lock); -+ idr_for_each(&client->resource_idr, schedule_reallocations, client); -+ spin_unlock_irq(&client->lock); - } - - void fw_device_cdev_update(struct fw_device *device) -@@ -274,11 +360,11 @@ static int ioctl_get_info(struct client - { - struct fw_cdev_get_info *get_info = buffer; - struct fw_cdev_event_bus_reset bus_reset; -- struct fw_card *card = client->device->card; - unsigned long ret = 0; - - client->version = get_info->version; - get_info->version = FW_CDEV_VERSION; -+ get_info->card = client->device->card->index; - - down_read(&fw_device_rwsem); - -@@ -300,49 +386,61 @@ static int ioctl_get_info(struct client - client->bus_reset_closure = get_info->bus_reset_closure; - if (get_info->bus_reset != 0) { - void __user *uptr = u64_to_uptr(get_info->bus_reset); -- unsigned long flags; - -- spin_lock_irqsave(&card->lock, flags); - fill_bus_reset_event(&bus_reset, client); -- spin_unlock_irqrestore(&card->lock, flags); -- - if (copy_to_user(uptr, &bus_reset, sizeof(bus_reset))) - return -EFAULT; - } - -- get_info->card = card->index; -- - return 0; - } - --static void --add_client_resource(struct client *client, struct client_resource *resource) -+static int add_client_resource(struct client *client, -+ struct client_resource *resource, gfp_t gfp_mask) - { - unsigned long flags; -+ int ret; -+ -+ retry: -+ if (idr_pre_get(&client->resource_idr, gfp_mask | __GFP_ZERO) == 0) -+ return -ENOMEM; - - spin_lock_irqsave(&client->lock, flags); -- list_add_tail(&resource->link, &client->resource_list); -- resource->handle = client->resource_handle++; -+ if (client->in_shutdown) -+ ret = -ECANCELED; -+ else -+ ret = idr_get_new(&client->resource_idr, resource, -+ &resource->handle); -+ if (ret >= 0) { -+ client_get(client); -+ if (resource->release == release_iso_resource) -+ schedule_iso_resource(container_of(resource, -+ struct iso_resource, resource)); -+ } - spin_unlock_irqrestore(&client->lock, flags); -+ -+ if (ret == -EAGAIN) -+ goto retry; -+ -+ return ret < 0 ? ret : 0; - } - --static int --release_client_resource(struct client *client, u32 handle, -- struct client_resource **resource) -+static int release_client_resource(struct client *client, u32 handle, -+ client_resource_release_fn_t release, -+ struct client_resource **resource) - { - struct client_resource *r; -- unsigned long flags; - -- spin_lock_irqsave(&client->lock, flags); -- list_for_each_entry(r, &client->resource_list, link) { -- if (r->handle == handle) { -- list_del(&r->link); -- break; -- } -- } -- spin_unlock_irqrestore(&client->lock, flags); -+ spin_lock_irq(&client->lock); -+ if (client->in_shutdown) -+ r = NULL; -+ else -+ r = idr_find(&client->resource_idr, handle); -+ if (r && r->release == release) -+ idr_remove(&client->resource_idr, handle); -+ spin_unlock_irq(&client->lock); - -- if (&r->link == &client->resource_list) -+ if (!(r && r->release == release)) - return -EINVAL; - - if (resource) -@@ -350,203 +448,242 @@ release_client_resource(struct client *c - else - r->release(client, r); - -+ client_put(client); -+ - return 0; - } - --static void --release_transaction(struct client *client, struct client_resource *resource) -+static void release_transaction(struct client *client, -+ struct client_resource *resource) - { -- struct response *response = -- container_of(resource, struct response, resource); -+ struct outbound_transaction_resource *r = container_of(resource, -+ struct outbound_transaction_resource, resource); - -- fw_cancel_transaction(client->device->card, &response->transaction); -+ fw_cancel_transaction(client->device->card, &r->transaction); - } - --static void --complete_transaction(struct fw_card *card, int rcode, -- void *payload, size_t length, void *data) -+static void complete_transaction(struct fw_card *card, int rcode, -+ void *payload, size_t length, void *data) - { -- struct response *response = data; -- struct client *client = response->client; -+ struct outbound_transaction_event *e = data; -+ struct fw_cdev_event_response *rsp = &e->response; -+ struct client *client = e->client; - unsigned long flags; -- struct fw_cdev_event_response *r = &response->response; - -- if (length < r->length) -- r->length = length; -+ if (length < rsp->length) -+ rsp->length = length; - if (rcode == RCODE_COMPLETE) -- memcpy(r->data, payload, r->length); -+ memcpy(rsp->data, payload, rsp->length); - - spin_lock_irqsave(&client->lock, flags); -- list_del(&response->resource.link); -+ /* -+ * 1. If called while in shutdown, the idr tree must be left untouched. -+ * The idr handle will be removed and the client reference will be -+ * dropped later. -+ * 2. If the call chain was release_client_resource -> -+ * release_transaction -> complete_transaction (instead of a normal -+ * conclusion of the transaction), i.e. if this resource was already -+ * unregistered from the idr, the client reference will be dropped -+ * by release_client_resource and we must not drop it here. -+ */ -+ if (!client->in_shutdown && -+ idr_find(&client->resource_idr, e->r.resource.handle)) { -+ idr_remove(&client->resource_idr, e->r.resource.handle); -+ /* Drop the idr's reference */ -+ client_put(client); -+ } - spin_unlock_irqrestore(&client->lock, flags); - -- r->type = FW_CDEV_EVENT_RESPONSE; -- r->rcode = rcode; -+ rsp->type = FW_CDEV_EVENT_RESPONSE; -+ rsp->rcode = rcode; - - /* -- * In the case that sizeof(*r) doesn't align with the position of the -+ * In the case that sizeof(*rsp) doesn't align with the position of the - * data, and the read is short, preserve an extra copy of the data - * to stay compatible with a pre-2.6.27 bug. Since the bug is harmless - * for short reads and some apps depended on it, this is both safe - * and prudent for compatibility. - */ -- if (r->length <= sizeof(*r) - offsetof(typeof(*r), data)) -- queue_event(client, &response->event, r, sizeof(*r), -- r->data, r->length); -+ if (rsp->length <= sizeof(*rsp) - offsetof(typeof(*rsp), data)) -+ queue_event(client, &e->event, rsp, sizeof(*rsp), -+ rsp->data, rsp->length); - else -- queue_event(client, &response->event, r, sizeof(*r) + r->length, -+ queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length, - NULL, 0); -+ -+ /* Drop the transaction callback's reference */ -+ client_put(client); - } - --static int ioctl_send_request(struct client *client, void *buffer) -+static int init_request(struct client *client, -+ struct fw_cdev_send_request *request, -+ int destination_id, int speed) - { -- struct fw_device *device = client->device; -- struct fw_cdev_send_request *request = buffer; -- struct response *response; -+ struct outbound_transaction_event *e; -+ int ret; - -- /* What is the biggest size we'll accept, really? */ -- if (request->length > 4096) -- return -EINVAL; -+ if (request->length > 4096 || request->length > 512 << speed) -+ return -EIO; - -- response = kmalloc(sizeof(*response) + request->length, GFP_KERNEL); -- if (response == NULL) -+ e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL); -+ if (e == NULL) - return -ENOMEM; - -- response->client = client; -- response->response.length = request->length; -- response->response.closure = request->closure; -+ e->client = client; -+ e->response.length = request->length; -+ e->response.closure = request->closure; - - if (request->data && -- copy_from_user(response->response.data, -+ copy_from_user(e->response.data, - u64_to_uptr(request->data), request->length)) { -- kfree(response); -- return -EFAULT; -+ ret = -EFAULT; -+ goto failed; - } - -- response->resource.release = release_transaction; -- add_client_resource(client, &response->resource); -- -- fw_send_request(device->card, &response->transaction, -- request->tcode & 0x1f, -- device->node->node_id, -- request->generation, -- device->max_speed, -- request->offset, -- response->response.data, request->length, -- complete_transaction, response); -+ e->r.resource.release = release_transaction; -+ ret = add_client_resource(client, &e->r.resource, GFP_KERNEL); -+ if (ret < 0) -+ goto failed; -+ -+ /* Get a reference for the transaction callback */ -+ client_get(client); -+ -+ fw_send_request(client->device->card, &e->r.transaction, -+ request->tcode & 0x1f, destination_id, -+ request->generation, speed, request->offset, -+ e->response.data, request->length, -+ complete_transaction, e); - - if (request->data) - return sizeof(request) + request->length; - else - return sizeof(request); -+ failed: -+ kfree(e); -+ -+ return ret; - } - --struct address_handler { -- struct fw_address_handler handler; -- __u64 closure; -- struct client *client; -- struct client_resource resource; --}; -+static int ioctl_send_request(struct client *client, void *buffer) -+{ -+ struct fw_cdev_send_request *request = buffer; - --struct request { -- struct fw_request *request; -- void *data; -- size_t length; -- struct client_resource resource; --}; -+ switch (request->tcode) { -+ case TCODE_WRITE_QUADLET_REQUEST: -+ case TCODE_WRITE_BLOCK_REQUEST: -+ case TCODE_READ_QUADLET_REQUEST: -+ case TCODE_READ_BLOCK_REQUEST: -+ case TCODE_LOCK_MASK_SWAP: -+ case TCODE_LOCK_COMPARE_SWAP: -+ case TCODE_LOCK_FETCH_ADD: -+ case TCODE_LOCK_LITTLE_ADD: -+ case TCODE_LOCK_BOUNDED_ADD: -+ case TCODE_LOCK_WRAP_ADD: -+ case TCODE_LOCK_VENDOR_DEPENDENT: -+ break; -+ default: -+ return -EINVAL; -+ } - --struct request_event { -- struct event event; -- struct fw_cdev_event_request request; --}; -+ return init_request(client, request, client->device->node->node_id, -+ client->device->max_speed); -+} - --static void --release_request(struct client *client, struct client_resource *resource) -+static void release_request(struct client *client, -+ struct client_resource *resource) - { -- struct request *request = -- container_of(resource, struct request, resource); -+ struct inbound_transaction_resource *r = container_of(resource, -+ struct inbound_transaction_resource, resource); - -- fw_send_response(client->device->card, request->request, -+ fw_send_response(client->device->card, r->request, - RCODE_CONFLICT_ERROR); -- kfree(request); -+ kfree(r); - } - --static void --handle_request(struct fw_card *card, struct fw_request *r, -- int tcode, int destination, int source, -- int generation, int speed, -- unsigned long long offset, -- void *payload, size_t length, void *callback_data) --{ -- struct address_handler *handler = callback_data; -- struct request *request; -- struct request_event *e; -- struct client *client = handler->client; -+static void handle_request(struct fw_card *card, struct fw_request *request, -+ int tcode, int destination, int source, -+ int generation, int speed, -+ unsigned long long offset, -+ void *payload, size_t length, void *callback_data) -+{ -+ struct address_handler_resource *handler = callback_data; -+ struct inbound_transaction_resource *r; -+ struct inbound_transaction_event *e; -+ int ret; - -- request = kmalloc(sizeof(*request), GFP_ATOMIC); -+ r = kmalloc(sizeof(*r), GFP_ATOMIC); - e = kmalloc(sizeof(*e), GFP_ATOMIC); -- if (request == NULL || e == NULL) { -- kfree(request); -- kfree(e); -- fw_send_response(card, r, RCODE_CONFLICT_ERROR); -- return; -- } -- -- request->request = r; -- request->data = payload; -- request->length = length; -+ if (r == NULL || e == NULL) -+ goto failed; - -- request->resource.release = release_request; -- add_client_resource(client, &request->resource); -+ r->request = request; -+ r->data = payload; -+ r->length = length; -+ -+ r->resource.release = release_request; -+ ret = add_client_resource(handler->client, &r->resource, GFP_ATOMIC); -+ if (ret < 0) -+ goto failed; - - e->request.type = FW_CDEV_EVENT_REQUEST; - e->request.tcode = tcode; - e->request.offset = offset; - e->request.length = length; -- e->request.handle = request->resource.handle; -+ e->request.handle = r->resource.handle; - e->request.closure = handler->closure; - -- queue_event(client, &e->event, -+ queue_event(handler->client, &e->event, - &e->request, sizeof(e->request), payload, length); -+ return; -+ -+ failed: -+ kfree(r); -+ kfree(e); -+ fw_send_response(card, request, RCODE_CONFLICT_ERROR); - } - --static void --release_address_handler(struct client *client, -- struct client_resource *resource) -+static void release_address_handler(struct client *client, -+ struct client_resource *resource) - { -- struct address_handler *handler = -- container_of(resource, struct address_handler, resource); -+ struct address_handler_resource *r = -+ container_of(resource, struct address_handler_resource, resource); - -- fw_core_remove_address_handler(&handler->handler); -- kfree(handler); -+ fw_core_remove_address_handler(&r->handler); -+ kfree(r); - } - - static int ioctl_allocate(struct client *client, void *buffer) - { - struct fw_cdev_allocate *request = buffer; -- struct address_handler *handler; -+ struct address_handler_resource *r; - struct fw_address_region region; -+ int ret; - -- handler = kmalloc(sizeof(*handler), GFP_KERNEL); -- if (handler == NULL) -+ r = kmalloc(sizeof(*r), GFP_KERNEL); -+ if (r == NULL) - return -ENOMEM; - - region.start = request->offset; - region.end = request->offset + request->length; -- handler->handler.length = request->length; -- handler->handler.address_callback = handle_request; -- handler->handler.callback_data = handler; -- handler->closure = request->closure; -- handler->client = client; -- -- if (fw_core_add_address_handler(&handler->handler, ®ion) < 0) { -- kfree(handler); -- return -EBUSY; -+ r->handler.length = request->length; -+ r->handler.address_callback = handle_request; -+ r->handler.callback_data = r; -+ r->closure = request->closure; -+ r->client = client; -+ -+ ret = fw_core_add_address_handler(&r->handler, ®ion); -+ if (ret < 0) { -+ kfree(r); -+ return ret; - } - -- handler->resource.release = release_address_handler; -- add_client_resource(client, &handler->resource); -- request->handle = handler->resource.handle; -+ r->resource.release = release_address_handler; -+ ret = add_client_resource(client, &r->resource, GFP_KERNEL); -+ if (ret < 0) { -+ release_address_handler(client, &r->resource); -+ return ret; -+ } -+ request->handle = r->resource.handle; - - return 0; - } -@@ -555,18 +692,22 @@ static int ioctl_deallocate(struct clien - { - struct fw_cdev_deallocate *request = buffer; - -- return release_client_resource(client, request->handle, NULL); -+ return release_client_resource(client, request->handle, -+ release_address_handler, NULL); - } - - static int ioctl_send_response(struct client *client, void *buffer) - { - struct fw_cdev_send_response *request = buffer; - struct client_resource *resource; -- struct request *r; -+ struct inbound_transaction_resource *r; - -- if (release_client_resource(client, request->handle, &resource) < 0) -+ if (release_client_resource(client, request->handle, -+ release_request, &resource) < 0) - return -EINVAL; -- r = container_of(resource, struct request, resource); -+ -+ r = container_of(resource, struct inbound_transaction_resource, -+ resource); - if (request->length < r->length) - r->length = request->length; - if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) -@@ -588,85 +729,84 @@ static int ioctl_initiate_bus_reset(stru - return fw_core_initiate_bus_reset(client->device->card, short_reset); - } - --struct descriptor { -- struct fw_descriptor d; -- struct client_resource resource; -- u32 data[0]; --}; -- - static void release_descriptor(struct client *client, - struct client_resource *resource) - { -- struct descriptor *descriptor = -- container_of(resource, struct descriptor, resource); -+ struct descriptor_resource *r = -+ container_of(resource, struct descriptor_resource, resource); - -- fw_core_remove_descriptor(&descriptor->d); -- kfree(descriptor); -+ fw_core_remove_descriptor(&r->descriptor); -+ kfree(r); - } - - static int ioctl_add_descriptor(struct client *client, void *buffer) - { - struct fw_cdev_add_descriptor *request = buffer; -- struct descriptor *descriptor; -- int retval; -+ struct descriptor_resource *r; -+ int ret; - - if (request->length > 256) - return -EINVAL; - -- descriptor = -- kmalloc(sizeof(*descriptor) + request->length * 4, GFP_KERNEL); -- if (descriptor == NULL) -+ r = kmalloc(sizeof(*r) + request->length * 4, GFP_KERNEL); -+ if (r == NULL) - return -ENOMEM; - -- if (copy_from_user(descriptor->data, -+ if (copy_from_user(r->data, - u64_to_uptr(request->data), request->length * 4)) { -- kfree(descriptor); -- return -EFAULT; -+ ret = -EFAULT; -+ goto failed; - } - -- descriptor->d.length = request->length; -- descriptor->d.immediate = request->immediate; -- descriptor->d.key = request->key; -- descriptor->d.data = descriptor->data; -- -- retval = fw_core_add_descriptor(&descriptor->d); -- if (retval < 0) { -- kfree(descriptor); -- return retval; -+ r->descriptor.length = request->length; -+ r->descriptor.immediate = request->immediate; -+ r->descriptor.key = request->key; -+ r->descriptor.data = r->data; -+ -+ ret = fw_core_add_descriptor(&r->descriptor); -+ if (ret < 0) -+ goto failed; -+ -+ r->resource.release = release_descriptor; -+ ret = add_client_resource(client, &r->resource, GFP_KERNEL); -+ if (ret < 0) { -+ fw_core_remove_descriptor(&r->descriptor); -+ goto failed; - } -- -- descriptor->resource.release = release_descriptor; -- add_client_resource(client, &descriptor->resource); -- request->handle = descriptor->resource.handle; -+ request->handle = r->resource.handle; - - return 0; -+ failed: -+ kfree(r); -+ -+ return ret; - } - - static int ioctl_remove_descriptor(struct client *client, void *buffer) - { - struct fw_cdev_remove_descriptor *request = buffer; - -- return release_client_resource(client, request->handle, NULL); -+ return release_client_resource(client, request->handle, -+ release_descriptor, NULL); - } - --static void --iso_callback(struct fw_iso_context *context, u32 cycle, -- size_t header_length, void *header, void *data) -+static void iso_callback(struct fw_iso_context *context, u32 cycle, -+ size_t header_length, void *header, void *data) - { - struct client *client = data; -- struct iso_interrupt *irq; -+ struct iso_interrupt_event *e; - -- irq = kzalloc(sizeof(*irq) + header_length, GFP_ATOMIC); -- if (irq == NULL) -+ e = kzalloc(sizeof(*e) + header_length, GFP_ATOMIC); -+ if (e == NULL) - return; - -- irq->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT; -- irq->interrupt.closure = client->iso_closure; -- irq->interrupt.cycle = cycle; -- irq->interrupt.header_length = header_length; -- memcpy(irq->interrupt.header, header, header_length); -- queue_event(client, &irq->event, &irq->interrupt, -- sizeof(irq->interrupt) + header_length, NULL, 0); -+ e->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT; -+ e->interrupt.closure = client->iso_closure; -+ e->interrupt.cycle = cycle; -+ e->interrupt.header_length = header_length; -+ memcpy(e->interrupt.header, header, header_length); -+ queue_event(client, &e->event, &e->interrupt, -+ sizeof(e->interrupt) + header_length, NULL, 0); - } - - static int ioctl_create_iso_context(struct client *client, void *buffer) -@@ -871,6 +1011,237 @@ static int ioctl_get_cycle_timer(struct - return 0; - } - -+static void iso_resource_work(struct work_struct *work) -+{ -+ struct iso_resource_event *e; -+ struct iso_resource *r = -+ container_of(work, struct iso_resource, work.work); -+ struct client *client = r->client; -+ int generation, channel, bandwidth, todo; -+ bool skip, free, success; -+ -+ spin_lock_irq(&client->lock); -+ generation = client->device->generation; -+ todo = r->todo; -+ /* Allow 1000ms grace period for other reallocations. */ -+ if (todo == ISO_RES_ALLOC && -+ time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) { -+ if (schedule_delayed_work(&r->work, DIV_ROUND_UP(HZ, 3))) -+ client_get(client); -+ skip = true; -+ } else { -+ /* We could be called twice within the same generation. */ -+ skip = todo == ISO_RES_REALLOC && -+ r->generation == generation; -+ } -+ free = todo == ISO_RES_DEALLOC || -+ todo == ISO_RES_ALLOC_ONCE || -+ todo == ISO_RES_DEALLOC_ONCE; -+ r->generation = generation; -+ spin_unlock_irq(&client->lock); -+ -+ if (skip) -+ goto out; -+ -+ bandwidth = r->bandwidth; -+ -+ fw_iso_resource_manage(client->device->card, generation, -+ r->channels, &channel, &bandwidth, -+ todo == ISO_RES_ALLOC || -+ todo == ISO_RES_REALLOC || -+ todo == ISO_RES_ALLOC_ONCE); -+ /* -+ * Is this generation outdated already? As long as this resource sticks -+ * in the idr, it will be scheduled again for a newer generation or at -+ * shutdown. -+ */ -+ if (channel == -EAGAIN && -+ (todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC)) -+ goto out; -+ -+ success = channel >= 0 || bandwidth > 0; -+ -+ spin_lock_irq(&client->lock); -+ /* -+ * Transit from allocation to reallocation, except if the client -+ * requested deallocation in the meantime. -+ */ -+ if (r->todo == ISO_RES_ALLOC) -+ r->todo = ISO_RES_REALLOC; -+ /* -+ * Allocation or reallocation failure? Pull this resource out of the -+ * idr and prepare for deletion, unless the client is shutting down. -+ */ -+ if (r->todo == ISO_RES_REALLOC && !success && -+ !client->in_shutdown && -+ idr_find(&client->resource_idr, r->resource.handle)) { -+ idr_remove(&client->resource_idr, r->resource.handle); -+ client_put(client); -+ free = true; -+ } -+ spin_unlock_irq(&client->lock); -+ -+ if (todo == ISO_RES_ALLOC && channel >= 0) -+ r->channels = 1ULL << channel; -+ -+ if (todo == ISO_RES_REALLOC && success) -+ goto out; -+ -+ if (todo == ISO_RES_ALLOC || todo == ISO_RES_ALLOC_ONCE) { -+ e = r->e_alloc; -+ r->e_alloc = NULL; -+ } else { -+ e = r->e_dealloc; -+ r->e_dealloc = NULL; -+ } -+ e->resource.handle = r->resource.handle; -+ e->resource.channel = channel; -+ e->resource.bandwidth = bandwidth; -+ -+ queue_event(client, &e->event, -+ &e->resource, sizeof(e->resource), NULL, 0); -+ -+ if (free) { -+ cancel_delayed_work(&r->work); -+ kfree(r->e_alloc); -+ kfree(r->e_dealloc); -+ kfree(r); -+ } -+ out: -+ client_put(client); -+} -+ -+static void schedule_iso_resource(struct iso_resource *r) -+{ -+ client_get(r->client); -+ if (!schedule_delayed_work(&r->work, 0)) -+ client_put(r->client); -+} -+ -+static void release_iso_resource(struct client *client, -+ struct client_resource *resource) -+{ -+ struct iso_resource *r = -+ container_of(resource, struct iso_resource, resource); -+ -+ spin_lock_irq(&client->lock); -+ r->todo = ISO_RES_DEALLOC; -+ schedule_iso_resource(r); -+ spin_unlock_irq(&client->lock); -+} -+ -+static int init_iso_resource(struct client *client, -+ struct fw_cdev_allocate_iso_resource *request, int todo) -+{ -+ struct iso_resource_event *e1, *e2; -+ struct iso_resource *r; -+ int ret; -+ -+ if ((request->channels == 0 && request->bandwidth == 0) || -+ request->bandwidth > BANDWIDTH_AVAILABLE_INITIAL || -+ request->bandwidth < 0) -+ return -EINVAL; -+ -+ r = kmalloc(sizeof(*r), GFP_KERNEL); -+ e1 = kmalloc(sizeof(*e1), GFP_KERNEL); -+ e2 = kmalloc(sizeof(*e2), GFP_KERNEL); -+ if (r == NULL || e1 == NULL || e2 == NULL) { -+ ret = -ENOMEM; -+ goto fail; -+ } -+ -+ INIT_DELAYED_WORK(&r->work, iso_resource_work); -+ r->client = client; -+ r->todo = todo; -+ r->generation = -1; -+ r->channels = request->channels; -+ r->bandwidth = request->bandwidth; -+ r->e_alloc = e1; -+ r->e_dealloc = e2; -+ -+ e1->resource.closure = request->closure; -+ e1->resource.type = FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED; -+ e2->resource.closure = request->closure; -+ e2->resource.type = FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED; -+ -+ if (todo == ISO_RES_ALLOC) { -+ r->resource.release = release_iso_resource; -+ ret = add_client_resource(client, &r->resource, GFP_KERNEL); -+ if (ret < 0) -+ goto fail; -+ } else { -+ r->resource.release = NULL; -+ r->resource.handle = -1; -+ schedule_iso_resource(r); -+ } -+ request->handle = r->resource.handle; -+ -+ return 0; -+ fail: -+ kfree(r); -+ kfree(e1); -+ kfree(e2); -+ -+ return ret; -+} -+ -+static int ioctl_allocate_iso_resource(struct client *client, void *buffer) -+{ -+ struct fw_cdev_allocate_iso_resource *request = buffer; -+ -+ return init_iso_resource(client, request, ISO_RES_ALLOC); -+} -+ -+static int ioctl_deallocate_iso_resource(struct client *client, void *buffer) -+{ -+ struct fw_cdev_deallocate *request = buffer; -+ -+ return release_client_resource(client, request->handle, -+ release_iso_resource, NULL); -+} -+ -+static int ioctl_allocate_iso_resource_once(struct client *client, void *buffer) -+{ -+ struct fw_cdev_allocate_iso_resource *request = buffer; -+ -+ return init_iso_resource(client, request, ISO_RES_ALLOC_ONCE); -+} -+ -+static int ioctl_deallocate_iso_resource_once(struct client *client, void *buffer) -+{ -+ struct fw_cdev_allocate_iso_resource *request = buffer; -+ -+ return init_iso_resource(client, request, ISO_RES_DEALLOC_ONCE); -+} -+ -+static int ioctl_get_speed(struct client *client, void *buffer) -+{ -+ struct fw_cdev_get_speed *request = buffer; -+ -+ request->max_speed = client->device->max_speed; -+ -+ return 0; -+} -+ -+static int ioctl_send_broadcast_request(struct client *client, void *buffer) -+{ -+ struct fw_cdev_send_request *request = buffer; -+ -+ switch (request->tcode) { -+ case TCODE_WRITE_QUADLET_REQUEST: -+ case TCODE_WRITE_BLOCK_REQUEST: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* Security policy: Only allow accesses to Units Space. */ -+ if (request->offset < CSR_REGISTER_BASE + CSR_CONFIG_ROM_END) -+ return -EACCES; -+ -+ return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100); -+} -+ - static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { - ioctl_get_info, - ioctl_send_request, -@@ -885,13 +1256,19 @@ static int (* const ioctl_handlers[])(st - ioctl_start_iso, - ioctl_stop_iso, - ioctl_get_cycle_timer, -+ ioctl_allocate_iso_resource, -+ ioctl_deallocate_iso_resource, -+ ioctl_allocate_iso_resource_once, -+ ioctl_deallocate_iso_resource_once, -+ ioctl_get_speed, -+ ioctl_send_broadcast_request, - }; - --static int --dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) -+static int dispatch_ioctl(struct client *client, -+ unsigned int cmd, void __user *arg) - { - char buffer[256]; -- int retval; -+ int ret; - - if (_IOC_TYPE(cmd) != '#' || - _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers)) -@@ -903,9 +1280,9 @@ dispatch_ioctl(struct client *client, un - return -EFAULT; - } - -- retval = ioctl_handlers[_IOC_NR(cmd)](client, buffer); -- if (retval < 0) -- return retval; -+ ret = ioctl_handlers[_IOC_NR(cmd)](client, buffer); -+ if (ret < 0) -+ return ret; - - if (_IOC_DIR(cmd) & _IOC_READ) { - if (_IOC_SIZE(cmd) > sizeof(buffer) || -@@ -913,12 +1290,11 @@ dispatch_ioctl(struct client *client, un - return -EFAULT; - } - -- return retval; -+ return ret; - } - --static long --fw_device_op_ioctl(struct file *file, -- unsigned int cmd, unsigned long arg) -+static long fw_device_op_ioctl(struct file *file, -+ unsigned int cmd, unsigned long arg) - { - struct client *client = file->private_data; - -@@ -929,9 +1305,8 @@ fw_device_op_ioctl(struct file *file, - } - - #ifdef CONFIG_COMPAT --static long --fw_device_op_compat_ioctl(struct file *file, -- unsigned int cmd, unsigned long arg) -+static long fw_device_op_compat_ioctl(struct file *file, -+ unsigned int cmd, unsigned long arg) - { - struct client *client = file->private_data; - -@@ -947,7 +1322,7 @@ static int fw_device_op_mmap(struct file - struct client *client = file->private_data; - enum dma_data_direction direction; - unsigned long size; -- int page_count, retval; -+ int page_count, ret; - - if (fw_device_is_shutdown(client->device)) - return -ENODEV; -@@ -973,48 +1348,57 @@ static int fw_device_op_mmap(struct file - else - direction = DMA_FROM_DEVICE; - -- retval = fw_iso_buffer_init(&client->buffer, client->device->card, -- page_count, direction); -- if (retval < 0) -- return retval; -+ ret = fw_iso_buffer_init(&client->buffer, client->device->card, -+ page_count, direction); -+ if (ret < 0) -+ return ret; - -- retval = fw_iso_buffer_map(&client->buffer, vma); -- if (retval < 0) -+ ret = fw_iso_buffer_map(&client->buffer, vma); -+ if (ret < 0) - fw_iso_buffer_destroy(&client->buffer, client->device->card); - -- return retval; -+ return ret; -+} -+ -+static int shutdown_resource(int id, void *p, void *data) -+{ -+ struct client_resource *r = p; -+ struct client *client = data; -+ -+ r->release(client, r); -+ client_put(client); -+ -+ return 0; - } - - static int fw_device_op_release(struct inode *inode, struct file *file) - { - struct client *client = file->private_data; - struct event *e, *next_e; -- struct client_resource *r, *next_r; -- unsigned long flags; - -- if (client->buffer.pages) -- fw_iso_buffer_destroy(&client->buffer, client->device->card); -+ mutex_lock(&client->device->client_list_mutex); -+ list_del(&client->link); -+ mutex_unlock(&client->device->client_list_mutex); - - if (client->iso_context) - fw_iso_context_destroy(client->iso_context); - -- list_for_each_entry_safe(r, next_r, &client->resource_list, link) -- r->release(client, r); -+ if (client->buffer.pages) -+ fw_iso_buffer_destroy(&client->buffer, client->device->card); - -- /* -- * FIXME: We should wait for the async tasklets to stop -- * running before freeing the memory. -- */ -+ /* Freeze client->resource_idr and client->event_list */ -+ spin_lock_irq(&client->lock); -+ client->in_shutdown = true; -+ spin_unlock_irq(&client->lock); -+ -+ idr_for_each(&client->resource_idr, shutdown_resource, client); -+ idr_remove_all(&client->resource_idr); -+ idr_destroy(&client->resource_idr); - - list_for_each_entry_safe(e, next_e, &client->event_list, link) - kfree(e); - -- spin_lock_irqsave(&client->device->card->lock, flags); -- list_del(&client->link); -- spin_unlock_irqrestore(&client->device->card->lock, flags); -- -- fw_device_put(client->device); -- kfree(client); -+ client_put(client); - - return 0; - } -diff -Naurp linux-2.6-git/drivers/firewire/fw-device.c firewire-git/drivers/firewire/fw-device.c ---- linux-2.6-git/drivers/firewire/fw-device.c 2009-01-30 13:39:02.989651512 -0500 -+++ firewire-git/drivers/firewire/fw-device.c 2009-01-30 13:35:51.860646788 -0500 -@@ -27,8 +27,10 @@ - #include - #include - #include -+#include - #include - #include -+#include - #include - #include - #include "fw-transaction.h" -@@ -132,8 +134,7 @@ static int get_modalias(struct fw_unit * - vendor, model, specifier_id, version); - } - --static int --fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env) -+static int fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env) - { - struct fw_unit *unit = fw_unit(dev); - char modalias[64]; -@@ -191,8 +192,8 @@ struct config_rom_attribute { - u32 key; - }; - --static ssize_t --show_immediate(struct device *dev, struct device_attribute *dattr, char *buf) -+static ssize_t show_immediate(struct device *dev, -+ struct device_attribute *dattr, char *buf) - { - struct config_rom_attribute *attr = - container_of(dattr, struct config_rom_attribute, attr); -@@ -223,8 +224,8 @@ show_immediate(struct device *dev, struc - #define IMMEDIATE_ATTR(name, key) \ - { __ATTR(name, S_IRUGO, show_immediate, NULL), key } - --static ssize_t --show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf) -+static ssize_t show_text_leaf(struct device *dev, -+ struct device_attribute *dattr, char *buf) - { - struct config_rom_attribute *attr = - container_of(dattr, struct config_rom_attribute, attr); -@@ -293,10 +294,9 @@ static struct config_rom_attribute confi - TEXT_LEAF_ATTR(hardware_version_name, CSR_HARDWARE_VERSION), - }; - --static void --init_fw_attribute_group(struct device *dev, -- struct device_attribute *attrs, -- struct fw_attribute_group *group) -+static void init_fw_attribute_group(struct device *dev, -+ struct device_attribute *attrs, -+ struct fw_attribute_group *group) - { - struct device_attribute *attr; - int i, j; -@@ -319,9 +319,8 @@ init_fw_attribute_group(struct device *d - dev->groups = group->groups; - } - --static ssize_t --modalias_show(struct device *dev, -- struct device_attribute *attr, char *buf) -+static ssize_t modalias_show(struct device *dev, -+ struct device_attribute *attr, char *buf) - { - struct fw_unit *unit = fw_unit(dev); - int length; -@@ -332,9 +331,8 @@ modalias_show(struct device *dev, - return length + 1; - } - --static ssize_t --rom_index_show(struct device *dev, -- struct device_attribute *attr, char *buf) -+static ssize_t rom_index_show(struct device *dev, -+ struct device_attribute *attr, char *buf) - { - struct fw_device *device = fw_device(dev->parent); - struct fw_unit *unit = fw_unit(dev); -@@ -349,8 +347,8 @@ static struct device_attribute fw_unit_a - __ATTR_NULL, - }; - --static ssize_t --config_rom_show(struct device *dev, struct device_attribute *attr, char *buf) -+static ssize_t config_rom_show(struct device *dev, -+ struct device_attribute *attr, char *buf) - { - struct fw_device *device = fw_device(dev); - size_t length; -@@ -363,8 +361,8 @@ config_rom_show(struct device *dev, stru - return length; - } - --static ssize_t --guid_show(struct device *dev, struct device_attribute *attr, char *buf) -+static ssize_t guid_show(struct device *dev, -+ struct device_attribute *attr, char *buf) - { - struct fw_device *device = fw_device(dev); - int ret; -@@ -383,8 +381,8 @@ static struct device_attribute fw_device - __ATTR_NULL, - }; - --static int --read_rom(struct fw_device *device, int generation, int index, u32 *data) -+static int read_rom(struct fw_device *device, -+ int generation, int index, u32 *data) - { - int rcode; - -@@ -1004,6 +1002,7 @@ void fw_node_event(struct fw_card *card, - device->node = fw_node_get(node); - device->node_id = node->node_id; - device->generation = card->generation; -+ mutex_init(&device->client_list_mutex); - INIT_LIST_HEAD(&device->client_list); - - /* -diff -Naurp linux-2.6-git/drivers/firewire/fw-device.h firewire-git/drivers/firewire/fw-device.h ---- linux-2.6-git/drivers/firewire/fw-device.h 2009-01-30 13:39:02.989651512 -0500 -+++ firewire-git/drivers/firewire/fw-device.h 2009-01-30 13:35:51.860646788 -0500 -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - #include - - enum fw_device_state { -@@ -64,7 +65,10 @@ struct fw_device { - bool cmc; - struct fw_card *card; - struct device device; -+ -+ struct mutex client_list_mutex; - struct list_head client_list; -+ - u32 *config_rom; - size_t config_rom_length; - int config_rom_retries; -@@ -176,8 +180,7 @@ struct fw_driver { - const struct fw_device_id *id_table; - }; - --static inline struct fw_driver * --fw_driver(struct device_driver *drv) -+static inline struct fw_driver *fw_driver(struct device_driver *drv) - { - return container_of(drv, struct fw_driver, driver); - } -diff -Naurp linux-2.6-git/drivers/firewire/fw-iso.c firewire-git/drivers/firewire/fw-iso.c ---- linux-2.6-git/drivers/firewire/fw-iso.c 2008-11-04 11:18:33.000000000 -0500 -+++ firewire-git/drivers/firewire/fw-iso.c 2009-01-30 13:35:51.860646788 -0500 -@@ -1,5 +1,7 @@ - /* -- * Isochronous IO functionality -+ * Isochronous I/O functionality: -+ * - Isochronous DMA context management -+ * - Isochronous bus resource management (channels, bandwidth), client side - * - * Copyright (C) 2006 Kristian Hoegsberg - * -@@ -18,21 +20,25 @@ - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - --#include --#include - #include --#include -+#include -+#include -+#include - #include -+#include -+#include - --#include "fw-transaction.h" - #include "fw-topology.h" --#include "fw-device.h" -+#include "fw-transaction.h" - --int --fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, -- int page_count, enum dma_data_direction direction) -+/* -+ * Isochronous DMA context management -+ */ -+ -+int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, -+ int page_count, enum dma_data_direction direction) - { -- int i, j, retval = -ENOMEM; -+ int i, j; - dma_addr_t address; - - buffer->page_count = page_count; -@@ -69,19 +75,19 @@ fw_iso_buffer_init(struct fw_iso_buffer - kfree(buffer->pages); - out: - buffer->pages = NULL; -- return retval; -+ return -ENOMEM; - } - - int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma) - { - unsigned long uaddr; -- int i, retval; -+ int i, ret; - - uaddr = vma->vm_start; - for (i = 0; i < buffer->page_count; i++) { -- retval = vm_insert_page(vma, uaddr, buffer->pages[i]); -- if (retval) -- return retval; -+ ret = vm_insert_page(vma, uaddr, buffer->pages[i]); -+ if (ret) -+ return ret; - uaddr += PAGE_SIZE; - } - -@@ -105,14 +111,14 @@ void fw_iso_buffer_destroy(struct fw_iso - buffer->pages = NULL; - } - --struct fw_iso_context * --fw_iso_context_create(struct fw_card *card, int type, -- int channel, int speed, size_t header_size, -- fw_iso_callback_t callback, void *callback_data) -+struct fw_iso_context *fw_iso_context_create(struct fw_card *card, -+ int type, int channel, int speed, size_t header_size, -+ fw_iso_callback_t callback, void *callback_data) - { - struct fw_iso_context *ctx; - -- ctx = card->driver->allocate_iso_context(card, type, header_size); -+ ctx = card->driver->allocate_iso_context(card, -+ type, channel, header_size); - if (IS_ERR(ctx)) - return ctx; - -@@ -134,25 +140,186 @@ void fw_iso_context_destroy(struct fw_is - card->driver->free_iso_context(ctx); - } - --int --fw_iso_context_start(struct fw_iso_context *ctx, int cycle, int sync, int tags) -+int fw_iso_context_start(struct fw_iso_context *ctx, -+ int cycle, int sync, int tags) - { - return ctx->card->driver->start_iso(ctx, cycle, sync, tags); - } - --int --fw_iso_context_queue(struct fw_iso_context *ctx, -- struct fw_iso_packet *packet, -- struct fw_iso_buffer *buffer, -- unsigned long payload) -+int fw_iso_context_queue(struct fw_iso_context *ctx, -+ struct fw_iso_packet *packet, -+ struct fw_iso_buffer *buffer, -+ unsigned long payload) - { - struct fw_card *card = ctx->card; - - return card->driver->queue_iso(ctx, packet, buffer, payload); - } - --int --fw_iso_context_stop(struct fw_iso_context *ctx) -+int fw_iso_context_stop(struct fw_iso_context *ctx) - { - return ctx->card->driver->stop_iso(ctx); - } -+ -+/* -+ * Isochronous bus resource management (channels, bandwidth), client side -+ */ -+ -+static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, -+ int bandwidth, bool allocate) -+{ -+ __be32 data[2]; -+ int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; -+ -+ /* -+ * On a 1394a IRM with low contention, try < 1 is enough. -+ * On a 1394-1995 IRM, we need at least try < 2. -+ * Let's just do try < 5. -+ */ -+ for (try = 0; try < 5; try++) { -+ new = allocate ? old - bandwidth : old + bandwidth; -+ if (new < 0 || new > BANDWIDTH_AVAILABLE_INITIAL) -+ break; -+ -+ data[0] = cpu_to_be32(old); -+ data[1] = cpu_to_be32(new); -+ switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, -+ irm_id, generation, SCODE_100, -+ CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE, -+ data, sizeof(data))) { -+ case RCODE_GENERATION: -+ /* A generation change frees all bandwidth. */ -+ return allocate ? -EAGAIN : bandwidth; -+ -+ case RCODE_COMPLETE: -+ if (be32_to_cpup(data) == old) -+ return bandwidth; -+ -+ old = be32_to_cpup(data); -+ /* Fall through. */ -+ } -+ } -+ -+ return -EIO; -+} -+ -+static int manage_channel(struct fw_card *card, int irm_id, int generation, -+ u32 channels_mask, u64 offset, bool allocate) -+{ -+ __be32 data[2], c, all, old; -+ int i, retry = 5; -+ -+ old = all = allocate ? cpu_to_be32(~0) : 0; -+ -+ for (i = 0; i < 32; i++) { -+ if (!(channels_mask & 1 << i)) -+ continue; -+ -+ c = cpu_to_be32(1 << (31 - i)); -+ if ((old & c) != (all & c)) -+ continue; -+ -+ data[0] = old; -+ data[1] = old ^ c; -+ switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, -+ irm_id, generation, SCODE_100, -+ offset, data, sizeof(data))) { -+ case RCODE_GENERATION: -+ /* A generation change frees all channels. */ -+ return allocate ? -EAGAIN : i; -+ -+ case RCODE_COMPLETE: -+ if (data[0] == old) -+ return i; -+ -+ old = data[0]; -+ -+ /* Is the IRM 1394a-2000 compliant? */ -+ if ((data[0] & c) == (data[1] & c)) -+ continue; -+ -+ /* 1394-1995 IRM, fall through to retry. */ -+ default: -+ if (retry--) -+ i--; -+ } -+ } -+ -+ return -EIO; -+} -+ -+static void deallocate_channel(struct fw_card *card, int irm_id, -+ int generation, int channel) -+{ -+ u32 mask; -+ u64 offset; -+ -+ mask = channel < 32 ? 1 << channel : 1 << (channel - 32); -+ offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : -+ CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; -+ -+ manage_channel(card, irm_id, generation, mask, offset, false); -+} -+ -+/** -+ * fw_iso_resource_manage - Allocate or deallocate a channel and/or bandwidth -+ * -+ * In parameters: card, generation, channels_mask, bandwidth, allocate -+ * Out parameters: channel, bandwidth -+ * This function blocks (sleeps) during communication with the IRM. -+ * -+ * Allocates or deallocates at most one channel out of channels_mask. -+ * channels_mask is a bitfield with MSB for channel 63 and LSB for channel 0. -+ * (Note, the IRM's CHANNELS_AVAILABLE is a big-endian bitfield with MSB for -+ * channel 0 and LSB for channel 63.) -+ * Allocates or deallocates as many bandwidth allocation units as specified. -+ * -+ * Returns channel < 0 if no channel was allocated or deallocated. -+ * Returns bandwidth = 0 if no bandwidth was allocated or deallocated. -+ * -+ * If generation is stale, deallocations succeed but allocations fail with -+ * channel = -EAGAIN. -+ * -+ * If channel allocation fails, no bandwidth will be allocated either. -+ * If bandwidth allocation fails, no channel will be allocated either. -+ * But deallocations of channel and bandwidth are tried independently -+ * of each other's success. -+ */ -+void fw_iso_resource_manage(struct fw_card *card, int generation, -+ u64 channels_mask, int *channel, int *bandwidth, -+ bool allocate) -+{ -+ u32 channels_hi = channels_mask; /* channels 31...0 */ -+ u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ -+ int irm_id, ret, c = -EINVAL; -+ -+ spin_lock_irq(&card->lock); -+ irm_id = card->irm_node->node_id; -+ spin_unlock_irq(&card->lock); -+ -+ if (channels_hi) -+ c = manage_channel(card, irm_id, generation, channels_hi, -+ CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, allocate); -+ if (channels_lo && c < 0) { -+ c = manage_channel(card, irm_id, generation, channels_lo, -+ CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, allocate); -+ if (c >= 0) -+ c += 32; -+ } -+ *channel = c; -+ -+ if (allocate && channels_mask != 0 && c < 0) -+ *bandwidth = 0; -+ -+ if (*bandwidth == 0) -+ return; -+ -+ ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate); -+ if (ret < 0) -+ *bandwidth = 0; -+ -+ if (allocate && ret < 0 && c >= 0) { -+ deallocate_channel(card, irm_id, generation, c); -+ *channel = ret; -+ } -+} -diff -Naurp linux-2.6-git/drivers/firewire/fw-ohci.c firewire-git/drivers/firewire/fw-ohci.c ---- linux-2.6-git/drivers/firewire/fw-ohci.c 2009-01-30 13:39:02.990772025 -0500 -+++ firewire-git/drivers/firewire/fw-ohci.c 2009-01-30 13:35:51.861646907 -0500 -@@ -205,6 +205,7 @@ struct fw_ohci { - - u32 it_context_mask; - struct iso_context *it_context_list; -+ u64 ir_context_channels; - u32 ir_context_mask; - struct iso_context *ir_context_list; - }; -@@ -441,9 +442,8 @@ static inline void flush_writes(const st - reg_read(ohci, OHCI1394_Version); - } - --static int --ohci_update_phy_reg(struct fw_card *card, int addr, -- int clear_bits, int set_bits) -+static int ohci_update_phy_reg(struct fw_card *card, int addr, -+ int clear_bits, int set_bits) - { - struct fw_ohci *ohci = fw_ohci(card); - u32 val, old; -@@ -658,8 +658,8 @@ static void ar_context_tasklet(unsigned - } - } - --static int --ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci, u32 regs) -+static int ar_context_init(struct ar_context *ctx, -+ struct fw_ohci *ohci, u32 regs) - { - struct ar_buffer ab; - -@@ -690,8 +690,7 @@ static void ar_context_run(struct ar_con - flush_writes(ctx->ohci); - } - --static struct descriptor * --find_branch_descriptor(struct descriptor *d, int z) -+static struct descriptor *find_branch_descriptor(struct descriptor *d, int z) - { - int b, key; - -@@ -751,8 +750,7 @@ static void context_tasklet(unsigned lon - * Allocate a new buffer and add it to the list of free buffers for this - * context. Must be called with ohci->lock held. - */ --static int --context_add_buffer(struct context *ctx) -+static int context_add_buffer(struct context *ctx) - { - struct descriptor_buffer *desc; - dma_addr_t uninitialized_var(bus_addr); -@@ -781,9 +779,8 @@ context_add_buffer(struct context *ctx) - return 0; - } - --static int --context_init(struct context *ctx, struct fw_ohci *ohci, -- u32 regs, descriptor_callback_t callback) -+static int context_init(struct context *ctx, struct fw_ohci *ohci, -+ u32 regs, descriptor_callback_t callback) - { - ctx->ohci = ohci; - ctx->regs = regs; -@@ -814,8 +811,7 @@ context_init(struct context *ctx, struct - return 0; - } - --static void --context_release(struct context *ctx) -+static void context_release(struct context *ctx) - { - struct fw_card *card = &ctx->ohci->card; - struct descriptor_buffer *desc, *tmp; -@@ -827,8 +823,8 @@ context_release(struct context *ctx) - } - - /* Must be called with ohci->lock held */ --static struct descriptor * --context_get_descriptors(struct context *ctx, int z, dma_addr_t *d_bus) -+static struct descriptor *context_get_descriptors(struct context *ctx, -+ int z, dma_addr_t *d_bus) - { - struct descriptor *d = NULL; - struct descriptor_buffer *desc = ctx->buffer_tail; -@@ -912,8 +908,8 @@ struct driver_data { - * Must always be called with the ochi->lock held to ensure proper - * generation handling and locking around packet queue manipulation. - */ --static int --at_context_queue_packet(struct context *ctx, struct fw_packet *packet) -+static int at_context_queue_packet(struct context *ctx, -+ struct fw_packet *packet) - { - struct fw_ohci *ohci = ctx->ohci; - dma_addr_t d_bus, uninitialized_var(payload_bus); -@@ -1095,8 +1091,8 @@ static int handle_at_packet(struct conte - #define HEADER_GET_DATA_LENGTH(q) (((q) >> 16) & 0xffff) - #define HEADER_GET_EXTENDED_TCODE(q) (((q) >> 0) & 0xffff) - --static void --handle_local_rom(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) -+static void handle_local_rom(struct fw_ohci *ohci, -+ struct fw_packet *packet, u32 csr) - { - struct fw_packet response; - int tcode, length, i; -@@ -1122,8 +1118,8 @@ handle_local_rom(struct fw_ohci *ohci, s - fw_core_handle_response(&ohci->card, &response); - } - --static void --handle_local_lock(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) -+static void handle_local_lock(struct fw_ohci *ohci, -+ struct fw_packet *packet, u32 csr) - { - struct fw_packet response; - int tcode, length, ext_tcode, sel; -@@ -1164,8 +1160,7 @@ handle_local_lock(struct fw_ohci *ohci, - fw_core_handle_response(&ohci->card, &response); - } - --static void --handle_local_request(struct context *ctx, struct fw_packet *packet) -+static void handle_local_request(struct context *ctx, struct fw_packet *packet) - { - u64 offset; - u32 csr; -@@ -1205,11 +1200,10 @@ handle_local_request(struct context *ctx - } - } - --static void --at_context_transmit(struct context *ctx, struct fw_packet *packet) -+static void at_context_transmit(struct context *ctx, struct fw_packet *packet) - { - unsigned long flags; -- int retval; -+ int ret; - - spin_lock_irqsave(&ctx->ohci->lock, flags); - -@@ -1220,10 +1214,10 @@ at_context_transmit(struct context *ctx, - return; - } - -- retval = at_context_queue_packet(ctx, packet); -+ ret = at_context_queue_packet(ctx, packet); - spin_unlock_irqrestore(&ctx->ohci->lock, flags); - -- if (retval < 0) -+ if (ret < 0) - packet->callback(packet, &ctx->ohci->card, packet->ack); - - } -@@ -1590,12 +1584,12 @@ static int ohci_enable(struct fw_card *c - return 0; - } - --static int --ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length) -+static int ohci_set_config_rom(struct fw_card *card, -+ u32 *config_rom, size_t length) - { - struct fw_ohci *ohci; - unsigned long flags; -- int retval = -EBUSY; -+ int ret = -EBUSY; - __be32 *next_config_rom; - dma_addr_t uninitialized_var(next_config_rom_bus); - -@@ -1649,7 +1643,7 @@ ohci_set_config_rom(struct fw_card *card - - reg_write(ohci, OHCI1394_ConfigROMmap, - ohci->next_config_rom_bus); -- retval = 0; -+ ret = 0; - } - - spin_unlock_irqrestore(&ohci->lock, flags); -@@ -1661,13 +1655,13 @@ ohci_set_config_rom(struct fw_card *card - * controller could need to access it before the bus reset - * takes effect. - */ -- if (retval == 0) -+ if (ret == 0) - fw_core_initiate_bus_reset(&ohci->card, 1); - else - dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, - next_config_rom, next_config_rom_bus); - -- return retval; -+ return ret; - } - - static void ohci_send_request(struct fw_card *card, struct fw_packet *packet) -@@ -1689,7 +1683,7 @@ static int ohci_cancel_packet(struct fw_ - struct fw_ohci *ohci = fw_ohci(card); - struct context *ctx = &ohci->at_request_ctx; - struct driver_data *driver_data = packet->driver_data; -- int retval = -ENOENT; -+ int ret = -ENOENT; - - tasklet_disable(&ctx->tasklet); - -@@ -1704,23 +1698,22 @@ static int ohci_cancel_packet(struct fw_ - driver_data->packet = NULL; - packet->ack = RCODE_CANCELLED; - packet->callback(packet, &ohci->card, packet->ack); -- retval = 0; -- -+ ret = 0; - out: - tasklet_enable(&ctx->tasklet); - -- return retval; -+ return ret; - } - --static int --ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) -+static int ohci_enable_phys_dma(struct fw_card *card, -+ int node_id, int generation) - { - #ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA - return 0; - #else - struct fw_ohci *ohci = fw_ohci(card); - unsigned long flags; -- int n, retval = 0; -+ int n, ret = 0; - - /* - * FIXME: Make sure this bitmask is cleared when we clear the busReset -@@ -1730,7 +1723,7 @@ ohci_enable_phys_dma(struct fw_card *car - spin_lock_irqsave(&ohci->lock, flags); - - if (ohci->generation != generation) { -- retval = -ESTALE; -+ ret = -ESTALE; - goto out; - } - -@@ -1748,12 +1741,12 @@ ohci_enable_phys_dma(struct fw_card *car - flush_writes(ohci); - out: - spin_unlock_irqrestore(&ohci->lock, flags); -- return retval; -+ -+ return ret; - #endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */ - } - --static u64 --ohci_get_bus_time(struct fw_card *card) -+static u64 ohci_get_bus_time(struct fw_card *card) - { - struct fw_ohci *ohci = fw_ohci(card); - u32 cycle_time; -@@ -1765,6 +1758,28 @@ ohci_get_bus_time(struct fw_card *card) - return bus_time; - } - -+static void copy_iso_headers(struct iso_context *ctx, void *p) -+{ -+ int i = ctx->header_length; -+ -+ if (i + ctx->base.header_size > PAGE_SIZE) -+ return; -+ -+ /* -+ * The iso header is byteswapped to little endian by -+ * the controller, but the remaining header quadlets -+ * are big endian. We want to present all the headers -+ * as big endian, so we have to swap the first quadlet. -+ */ -+ if (ctx->base.header_size > 0) -+ *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); -+ if (ctx->base.header_size > 4) -+ *(u32 *) (ctx->header + i + 4) = __swab32(*(u32 *) p); -+ if (ctx->base.header_size > 8) -+ memcpy(ctx->header + i + 8, p + 8, ctx->base.header_size - 8); -+ ctx->header_length += ctx->base.header_size; -+} -+ - static int handle_ir_dualbuffer_packet(struct context *context, - struct descriptor *d, - struct descriptor *last) -@@ -1775,7 +1790,6 @@ static int handle_ir_dualbuffer_packet(s - __le32 *ir_header; - size_t header_length; - void *p, *end; -- int i; - - if (db->first_res_count != 0 && db->second_res_count != 0) { - if (ctx->excess_bytes <= le16_to_cpu(db->second_req_count)) { -@@ -1788,25 +1802,14 @@ static int handle_ir_dualbuffer_packet(s - header_length = le16_to_cpu(db->first_req_count) - - le16_to_cpu(db->first_res_count); - -- i = ctx->header_length; - p = db + 1; - end = p + header_length; -- while (p < end && i + ctx->base.header_size <= PAGE_SIZE) { -- /* -- * The iso header is byteswapped to little endian by -- * the controller, but the remaining header quadlets -- * are big endian. We want to present all the headers -- * as big endian, so we have to swap the first -- * quadlet. -- */ -- *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); -- memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4); -- i += ctx->base.header_size; -+ while (p < end) { -+ copy_iso_headers(ctx, p); - ctx->excess_bytes += - (le32_to_cpu(*(__le32 *)(p + 4)) >> 16) & 0xffff; -- p += ctx->base.header_size + 4; -+ p += max(ctx->base.header_size, (size_t)8); - } -- ctx->header_length = i; - - ctx->excess_bytes -= le16_to_cpu(db->second_req_count) - - le16_to_cpu(db->second_res_count); -@@ -1832,7 +1835,6 @@ static int handle_ir_packet_per_buffer(s - struct descriptor *pd; - __le32 *ir_header; - void *p; -- int i; - - for (pd = d; pd <= last; pd++) { - if (pd->transfer_status) -@@ -1842,21 +1844,8 @@ static int handle_ir_packet_per_buffer(s - /* Descriptor(s) not done yet, stop iteration */ - return 0; - -- i = ctx->header_length; -- p = last + 1; -- -- if (ctx->base.header_size > 0 && -- i + ctx->base.header_size <= PAGE_SIZE) { -- /* -- * The iso header is byteswapped to little endian by -- * the controller, but the remaining header quadlets -- * are big endian. We want to present all the headers -- * as big endian, so we have to swap the first quadlet. -- */ -- *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); -- memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4); -- ctx->header_length += ctx->base.header_size; -- } -+ p = last + 1; -+ copy_iso_headers(ctx, p); - - if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) { - ir_header = (__le32 *) p; -@@ -1888,21 +1877,24 @@ static int handle_it_packet(struct conte - return 1; - } - --static struct fw_iso_context * --ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) -+static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card, -+ int type, int channel, size_t header_size) - { - struct fw_ohci *ohci = fw_ohci(card); - struct iso_context *ctx, *list; - descriptor_callback_t callback; -+ u64 *channels, dont_care = ~0ULL; - u32 *mask, regs; - unsigned long flags; -- int index, retval = -ENOMEM; -+ int index, ret = -ENOMEM; - - if (type == FW_ISO_CONTEXT_TRANSMIT) { -+ channels = &dont_care; - mask = &ohci->it_context_mask; - list = ohci->it_context_list; - callback = handle_it_packet; - } else { -+ channels = &ohci->ir_context_channels; - mask = &ohci->ir_context_mask; - list = ohci->ir_context_list; - if (ohci->use_dualbuffer) -@@ -1912,9 +1904,11 @@ ohci_allocate_iso_context(struct fw_card - } - - spin_lock_irqsave(&ohci->lock, flags); -- index = ffs(*mask) - 1; -- if (index >= 0) -+ index = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1; -+ if (index >= 0) { -+ *channels &= ~(1ULL << channel); - *mask &= ~(1 << index); -+ } - spin_unlock_irqrestore(&ohci->lock, flags); - - if (index < 0) -@@ -1932,8 +1926,8 @@ ohci_allocate_iso_context(struct fw_card - if (ctx->header == NULL) - goto out; - -- retval = context_init(&ctx->context, ohci, regs, callback); -- if (retval < 0) -+ ret = context_init(&ctx->context, ohci, regs, callback); -+ if (ret < 0) - goto out_with_header; - - return &ctx->base; -@@ -1945,7 +1939,7 @@ ohci_allocate_iso_context(struct fw_card - *mask |= 1 << index; - spin_unlock_irqrestore(&ohci->lock, flags); - -- return ERR_PTR(retval); -+ return ERR_PTR(ret); - } - - static int ohci_start_iso(struct fw_iso_context *base, -@@ -2024,16 +2018,16 @@ static void ohci_free_iso_context(struct - } else { - index = ctx - ohci->ir_context_list; - ohci->ir_context_mask |= 1 << index; -+ ohci->ir_context_channels |= 1ULL << base->channel; - } - - spin_unlock_irqrestore(&ohci->lock, flags); - } - --static int --ohci_queue_iso_transmit(struct fw_iso_context *base, -- struct fw_iso_packet *packet, -- struct fw_iso_buffer *buffer, -- unsigned long payload) -+static int ohci_queue_iso_transmit(struct fw_iso_context *base, -+ struct fw_iso_packet *packet, -+ struct fw_iso_buffer *buffer, -+ unsigned long payload) - { - struct iso_context *ctx = container_of(base, struct iso_context, base); - struct descriptor *d, *last, *pd; -@@ -2128,11 +2122,10 @@ ohci_queue_iso_transmit(struct fw_iso_co - return 0; - } - --static int --ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, -- struct fw_iso_packet *packet, -- struct fw_iso_buffer *buffer, -- unsigned long payload) -+static int ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, -+ struct fw_iso_packet *packet, -+ struct fw_iso_buffer *buffer, -+ unsigned long payload) - { - struct iso_context *ctx = container_of(base, struct iso_context, base); - struct db_descriptor *db = NULL; -@@ -2151,11 +2144,11 @@ ohci_queue_iso_receive_dualbuffer(struct - z = 2; - - /* -- * The OHCI controller puts the status word in the header -- * buffer too, so we need 4 extra bytes per packet. -+ * The OHCI controller puts the isochronous header and trailer in the -+ * buffer, so we need at least 8 bytes. - */ - packet_count = p->header_length / ctx->base.header_size; -- header_size = packet_count * (ctx->base.header_size + 4); -+ header_size = packet_count * max(ctx->base.header_size, (size_t)8); - - /* Get header size in number of descriptors. */ - header_z = DIV_ROUND_UP(header_size, sizeof(*d)); -@@ -2173,7 +2166,8 @@ ohci_queue_iso_receive_dualbuffer(struct - db = (struct db_descriptor *) d; - db->control = cpu_to_le16(DESCRIPTOR_STATUS | - DESCRIPTOR_BRANCH_ALWAYS); -- db->first_size = cpu_to_le16(ctx->base.header_size + 4); -+ db->first_size = -+ cpu_to_le16(max(ctx->base.header_size, (size_t)8)); - if (p->skip && rest == p->payload_length) { - db->control |= cpu_to_le16(DESCRIPTOR_WAIT); - db->first_req_count = db->first_size; -@@ -2208,11 +2202,10 @@ ohci_queue_iso_receive_dualbuffer(struct - return 0; - } - --static int --ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, -- struct fw_iso_packet *packet, -- struct fw_iso_buffer *buffer, -- unsigned long payload) -+static int ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, -+ struct fw_iso_packet *packet, -+ struct fw_iso_buffer *buffer, -+ unsigned long payload) - { - struct iso_context *ctx = container_of(base, struct iso_context, base); - struct descriptor *d = NULL, *pd = NULL; -@@ -2223,11 +2216,11 @@ ohci_queue_iso_receive_packet_per_buffer - int page, offset, packet_count, header_size, payload_per_buffer; - - /* -- * The OHCI controller puts the status word in the -- * buffer too, so we need 4 extra bytes per packet. -+ * The OHCI controller puts the isochronous header and trailer in the -+ * buffer, so we need at least 8 bytes. - */ - packet_count = p->header_length / ctx->base.header_size; -- header_size = ctx->base.header_size + 4; -+ header_size = max(ctx->base.header_size, (size_t)8); - - /* Get header size in number of descriptors. */ - header_z = DIV_ROUND_UP(header_size, sizeof(*d)); -@@ -2286,29 +2279,27 @@ ohci_queue_iso_receive_packet_per_buffer - return 0; - } - --static int --ohci_queue_iso(struct fw_iso_context *base, -- struct fw_iso_packet *packet, -- struct fw_iso_buffer *buffer, -- unsigned long payload) -+static int ohci_queue_iso(struct fw_iso_context *base, -+ struct fw_iso_packet *packet, -+ struct fw_iso_buffer *buffer, -+ unsigned long payload) - { - struct iso_context *ctx = container_of(base, struct iso_context, base); - unsigned long flags; -- int retval; -+ int ret; - - spin_lock_irqsave(&ctx->context.ohci->lock, flags); - if (base->type == FW_ISO_CONTEXT_TRANSMIT) -- retval = ohci_queue_iso_transmit(base, packet, buffer, payload); -+ ret = ohci_queue_iso_transmit(base, packet, buffer, payload); - else if (ctx->context.ohci->use_dualbuffer) -- retval = ohci_queue_iso_receive_dualbuffer(base, packet, -- buffer, payload); -+ ret = ohci_queue_iso_receive_dualbuffer(base, packet, -+ buffer, payload); - else -- retval = ohci_queue_iso_receive_packet_per_buffer(base, packet, -- buffer, -- payload); -+ ret = ohci_queue_iso_receive_packet_per_buffer(base, packet, -+ buffer, payload); - spin_unlock_irqrestore(&ctx->context.ohci->lock, flags); - -- return retval; -+ return ret; - } - - static const struct fw_card_driver ohci_driver = { -@@ -2357,8 +2348,8 @@ static void ohci_pmac_off(struct pci_dev - #define ohci_pmac_off(dev) - #endif /* CONFIG_PPC_PMAC */ - --static int __devinit --pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) -+static int __devinit pci_probe(struct pci_dev *dev, -+ const struct pci_device_id *ent) - { - struct fw_ohci *ohci; - u32 bus_options, max_receive, link_speed, version; -@@ -2440,6 +2431,7 @@ pci_probe(struct pci_dev *dev, const str - ohci->it_context_list = kzalloc(size, GFP_KERNEL); - - reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0); -+ ohci->ir_context_channels = ~0ULL; - ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet); - reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0); - size = sizeof(struct iso_context) * hweight32(ohci->ir_context_mask); -diff -Naurp linux-2.6-git/drivers/firewire/fw-sbp2.c firewire-git/drivers/firewire/fw-sbp2.c ---- linux-2.6-git/drivers/firewire/fw-sbp2.c 2009-01-30 13:39:02.991771976 -0500 -+++ firewire-git/drivers/firewire/fw-sbp2.c 2009-01-30 13:35:51.861646907 -0500 -@@ -392,20 +392,18 @@ static const struct { - } - }; - --static void --free_orb(struct kref *kref) -+static void free_orb(struct kref *kref) - { - struct sbp2_orb *orb = container_of(kref, struct sbp2_orb, kref); - - kfree(orb); - } - --static void --sbp2_status_write(struct fw_card *card, struct fw_request *request, -- int tcode, int destination, int source, -- int generation, int speed, -- unsigned long long offset, -- void *payload, size_t length, void *callback_data) -+static void sbp2_status_write(struct fw_card *card, struct fw_request *request, -+ int tcode, int destination, int source, -+ int generation, int speed, -+ unsigned long long offset, -+ void *payload, size_t length, void *callback_data) - { - struct sbp2_logical_unit *lu = callback_data; - struct sbp2_orb *orb; -@@ -451,9 +449,8 @@ sbp2_status_write(struct fw_card *card, - fw_send_response(card, request, RCODE_COMPLETE); - } - --static void --complete_transaction(struct fw_card *card, int rcode, -- void *payload, size_t length, void *data) -+static void complete_transaction(struct fw_card *card, int rcode, -+ void *payload, size_t length, void *data) - { - struct sbp2_orb *orb = data; - unsigned long flags; -@@ -482,9 +479,8 @@ complete_transaction(struct fw_card *car - kref_put(&orb->kref, free_orb); - } - --static void --sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, -- int node_id, int generation, u64 offset) -+static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, -+ int node_id, int generation, u64 offset) - { - struct fw_device *device = fw_device(lu->tgt->unit->device.parent); - unsigned long flags; -@@ -531,8 +527,8 @@ static int sbp2_cancel_orbs(struct sbp2_ - return retval; - } - --static void --complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) -+static void complete_management_orb(struct sbp2_orb *base_orb, -+ struct sbp2_status *status) - { - struct sbp2_management_orb *orb = - container_of(base_orb, struct sbp2_management_orb, base); -@@ -542,10 +538,9 @@ complete_management_orb(struct sbp2_orb - complete(&orb->done); - } - --static int --sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, -- int generation, int function, int lun_or_login_id, -- void *response) -+static int sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, -+ int generation, int function, -+ int lun_or_login_id, void *response) - { - struct fw_device *device = fw_device(lu->tgt->unit->device.parent); - struct sbp2_management_orb *orb; -@@ -652,9 +647,8 @@ static void sbp2_agent_reset(struct sbp2 - &d, sizeof(d)); - } - --static void --complete_agent_reset_write_no_wait(struct fw_card *card, int rcode, -- void *payload, size_t length, void *data) -+static void complete_agent_reset_write_no_wait(struct fw_card *card, -+ int rcode, void *payload, size_t length, void *data) - { - kfree(data); - } -@@ -1299,8 +1293,7 @@ static void sbp2_unmap_scatterlist(struc - sizeof(orb->page_table), DMA_TO_DEVICE); - } - --static unsigned int --sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data) -+static unsigned int sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data) - { - int sam_status; - -@@ -1337,8 +1330,8 @@ sbp2_status_to_sense_data(u8 *sbp2_statu - } - } - --static void --complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) -+static void complete_command_orb(struct sbp2_orb *base_orb, -+ struct sbp2_status *status) - { - struct sbp2_command_orb *orb = - container_of(base_orb, struct sbp2_command_orb, base); -@@ -1384,9 +1377,8 @@ complete_command_orb(struct sbp2_orb *ba - orb->done(orb->cmd); - } - --static int --sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device, -- struct sbp2_logical_unit *lu) -+static int sbp2_map_scatterlist(struct sbp2_command_orb *orb, -+ struct fw_device *device, struct sbp2_logical_unit *lu) - { - struct scatterlist *sg = scsi_sglist(orb->cmd); - int i, n; -@@ -1584,9 +1576,8 @@ static int sbp2_scsi_abort(struct scsi_c - * This is the concatenation of target port identifier and logical unit - * identifier as per SAM-2...SAM-4 annex A. - */ --static ssize_t --sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr, -- char *buf) -+static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, -+ struct device_attribute *attr, char *buf) - { - struct scsi_device *sdev = to_scsi_device(dev); - struct sbp2_logical_unit *lu; -diff -Naurp linux-2.6-git/drivers/firewire/fw-topology.c firewire-git/drivers/firewire/fw-topology.c ---- linux-2.6-git/drivers/firewire/fw-topology.c 2009-01-30 13:39:02.991771976 -0500 -+++ firewire-git/drivers/firewire/fw-topology.c 2009-01-30 13:35:51.862647087 -0500 -@@ -314,9 +314,8 @@ typedef void (*fw_node_callback_t)(struc - struct fw_node * node, - struct fw_node * parent); - --static void --for_each_fw_node(struct fw_card *card, struct fw_node *root, -- fw_node_callback_t callback) -+static void for_each_fw_node(struct fw_card *card, struct fw_node *root, -+ fw_node_callback_t callback) - { - struct list_head list; - struct fw_node *node, *next, *child, *parent; -@@ -349,9 +348,8 @@ for_each_fw_node(struct fw_card *card, s - fw_node_put(node); - } - --static void --report_lost_node(struct fw_card *card, -- struct fw_node *node, struct fw_node *parent) -+static void report_lost_node(struct fw_card *card, -+ struct fw_node *node, struct fw_node *parent) - { - fw_node_event(card, node, FW_NODE_DESTROYED); - fw_node_put(node); -@@ -360,9 +358,8 @@ report_lost_node(struct fw_card *card, - card->bm_retries = 0; - } - --static void --report_found_node(struct fw_card *card, -- struct fw_node *node, struct fw_node *parent) -+static void report_found_node(struct fw_card *card, -+ struct fw_node *node, struct fw_node *parent) - { - int b_path = (node->phy_speed == SCODE_BETA); - -@@ -415,8 +412,7 @@ static void move_tree(struct fw_node *no - * found, lost or updated. Update the nodes in the card topology tree - * as we go. - */ --static void --update_tree(struct fw_card *card, struct fw_node *root) -+static void update_tree(struct fw_card *card, struct fw_node *root) - { - struct list_head list0, list1; - struct fw_node *node0, *node1, *next1; -@@ -497,8 +493,8 @@ update_tree(struct fw_card *card, struct - } - } - --static void --update_topology_map(struct fw_card *card, u32 *self_ids, int self_id_count) -+static void update_topology_map(struct fw_card *card, -+ u32 *self_ids, int self_id_count) - { - int node_count; - -@@ -510,10 +506,8 @@ update_topology_map(struct fw_card *card - fw_compute_block_crc(card->topology_map); - } - --void --fw_core_handle_bus_reset(struct fw_card *card, -- int node_id, int generation, -- int self_id_count, u32 * self_ids) -+void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, -+ int self_id_count, u32 *self_ids) - { - struct fw_node *local_node; - unsigned long flags; -diff -Naurp linux-2.6-git/drivers/firewire/fw-topology.h firewire-git/drivers/firewire/fw-topology.h ---- linux-2.6-git/drivers/firewire/fw-topology.h 2008-11-04 11:18:33.000000000 -0500 -+++ firewire-git/drivers/firewire/fw-topology.h 2009-01-30 13:35:51.862647087 -0500 -@@ -19,6 +19,11 @@ - #ifndef __fw_topology_h - #define __fw_topology_h - -+#include -+#include -+ -+#include -+ - enum { - FW_NODE_CREATED, - FW_NODE_UPDATED, -@@ -51,26 +56,22 @@ struct fw_node { - struct fw_node *ports[0]; - }; - --static inline struct fw_node * --fw_node_get(struct fw_node *node) -+static inline struct fw_node *fw_node_get(struct fw_node *node) - { - atomic_inc(&node->ref_count); - - return node; - } - --static inline void --fw_node_put(struct fw_node *node) -+static inline void fw_node_put(struct fw_node *node) - { - if (atomic_dec_and_test(&node->ref_count)) - kfree(node); - } - --void --fw_destroy_nodes(struct fw_card *card); -- --int --fw_compute_block_crc(u32 *block); -+struct fw_card; -+void fw_destroy_nodes(struct fw_card *card); - -+int fw_compute_block_crc(u32 *block); - - #endif /* __fw_topology_h */ -diff -Naurp linux-2.6-git/drivers/firewire/fw-transaction.c firewire-git/drivers/firewire/fw-transaction.c ---- linux-2.6-git/drivers/firewire/fw-transaction.c 2009-01-30 13:39:02.991771976 -0500 -+++ firewire-git/drivers/firewire/fw-transaction.c 2009-01-30 13:35:51.862647087 -0500 -@@ -64,10 +64,9 @@ - #define PHY_CONFIG_ROOT_ID(node_id) ((((node_id) & 0x3f) << 24) | (1 << 23)) - #define PHY_IDENTIFIER(id) ((id) << 30) - --static int --close_transaction(struct fw_transaction *transaction, -- struct fw_card *card, int rcode, -- u32 *payload, size_t length) -+static int close_transaction(struct fw_transaction *transaction, -+ struct fw_card *card, int rcode, -+ u32 *payload, size_t length) - { - struct fw_transaction *t; - unsigned long flags; -@@ -94,9 +93,8 @@ close_transaction(struct fw_transaction - * Only valid for transactions that are potentially pending (ie have - * been sent). - */ --int --fw_cancel_transaction(struct fw_card *card, -- struct fw_transaction *transaction) -+int fw_cancel_transaction(struct fw_card *card, -+ struct fw_transaction *transaction) - { - /* - * Cancel the packet transmission if it's still queued. That -@@ -116,9 +114,8 @@ fw_cancel_transaction(struct fw_card *ca - } - EXPORT_SYMBOL(fw_cancel_transaction); - --static void --transmit_complete_callback(struct fw_packet *packet, -- struct fw_card *card, int status) -+static void transmit_complete_callback(struct fw_packet *packet, -+ struct fw_card *card, int status) - { - struct fw_transaction *t = - container_of(packet, struct fw_transaction, packet); -@@ -151,8 +148,7 @@ transmit_complete_callback(struct fw_pac - } - } - --static void --fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, -+static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, - int destination_id, int source_id, int generation, int speed, - unsigned long long offset, void *payload, size_t length) - { -@@ -247,12 +243,10 @@ fw_fill_request(struct fw_packet *packet - * @param callback_data pointer to arbitrary data, which will be - * passed to the callback - */ --void --fw_send_request(struct fw_card *card, struct fw_transaction *t, -- int tcode, int destination_id, int generation, int speed, -- unsigned long long offset, -- void *payload, size_t length, -- fw_transaction_callback_t callback, void *callback_data) -+void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, -+ int destination_id, int generation, int speed, -+ unsigned long long offset, void *payload, size_t length, -+ fw_transaction_callback_t callback, void *callback_data) - { - unsigned long flags; - int tlabel; -@@ -322,8 +316,8 @@ static void transaction_callback(struct - * Returns the RCODE. - */ - int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, -- int generation, int speed, unsigned long long offset, -- void *data, size_t length) -+ int generation, int speed, unsigned long long offset, -+ void *data, size_t length) - { - struct transaction_callback_data d; - struct fw_transaction t; -@@ -399,9 +393,8 @@ void fw_flush_transactions(struct fw_car - } - } - --static struct fw_address_handler * --lookup_overlapping_address_handler(struct list_head *list, -- unsigned long long offset, size_t length) -+static struct fw_address_handler *lookup_overlapping_address_handler( -+ struct list_head *list, unsigned long long offset, size_t length) - { - struct fw_address_handler *handler; - -@@ -414,9 +407,8 @@ lookup_overlapping_address_handler(struc - return NULL; - } - --static struct fw_address_handler * --lookup_enclosing_address_handler(struct list_head *list, -- unsigned long long offset, size_t length) -+static struct fw_address_handler *lookup_enclosing_address_handler( -+ struct list_head *list, unsigned long long offset, size_t length) - { - struct fw_address_handler *handler; - -@@ -449,36 +441,44 @@ const struct fw_address_region fw_unit_s - #endif /* 0 */ - - /** -- * Allocate a range of addresses in the node space of the OHCI -- * controller. When a request is received that falls within the -- * specified address range, the specified callback is invoked. The -- * parameters passed to the callback give the details of the -- * particular request. -+ * fw_core_add_address_handler - register for incoming requests -+ * @handler: callback -+ * @region: region in the IEEE 1212 node space address range -+ * -+ * region->start, ->end, and handler->length have to be quadlet-aligned. -+ * -+ * When a request is received that falls within the specified address range, -+ * the specified callback is invoked. The parameters passed to the callback -+ * give the details of the particular request. - * - * Return value: 0 on success, non-zero otherwise. - * The start offset of the handler's address region is determined by - * fw_core_add_address_handler() and is returned in handler->offset. -- * The offset is quadlet-aligned. - */ --int --fw_core_add_address_handler(struct fw_address_handler *handler, -- const struct fw_address_region *region) -+int fw_core_add_address_handler(struct fw_address_handler *handler, -+ const struct fw_address_region *region) - { - struct fw_address_handler *other; - unsigned long flags; - int ret = -EBUSY; - -+ if (region->start & 0xffff000000000003ULL || -+ region->end & 0xffff000000000003ULL || -+ region->start >= region->end || -+ handler->length & 3 || -+ handler->length == 0) -+ return -EINVAL; -+ - spin_lock_irqsave(&address_handler_lock, flags); - -- handler->offset = roundup(region->start, 4); -+ handler->offset = region->start; - while (handler->offset + handler->length <= region->end) { - other = - lookup_overlapping_address_handler(&address_handler_list, - handler->offset, - handler->length); - if (other != NULL) { -- handler->offset = -- roundup(other->offset + other->length, 4); -+ handler->offset += other->length; - } else { - list_add_tail(&handler->link, &address_handler_list); - ret = 0; -@@ -493,12 +493,7 @@ fw_core_add_address_handler(struct fw_ad - EXPORT_SYMBOL(fw_core_add_address_handler); - - /** -- * Deallocate a range of addresses allocated with fw_allocate. This -- * will call the associated callback one last time with a the special -- * tcode TCODE_DEALLOCATE, to let the client destroy the registered -- * callback data. For convenience, the callback parameters offset and -- * length are set to the start and the length respectively for the -- * deallocated region, payload is set to NULL. -+ * fw_core_remove_address_handler - unregister an address handler - */ - void fw_core_remove_address_handler(struct fw_address_handler *handler) - { -@@ -518,9 +513,8 @@ struct fw_request { - u32 data[0]; - }; - --static void --free_response_callback(struct fw_packet *packet, -- struct fw_card *card, int status) -+static void free_response_callback(struct fw_packet *packet, -+ struct fw_card *card, int status) - { - struct fw_request *request; - -@@ -528,9 +522,8 @@ free_response_callback(struct fw_packet - kfree(request); - } - --void --fw_fill_response(struct fw_packet *response, u32 *request_header, -- int rcode, void *payload, size_t length) -+void fw_fill_response(struct fw_packet *response, u32 *request_header, -+ int rcode, void *payload, size_t length) - { - int tcode, tlabel, extended_tcode, source, destination; - -@@ -588,8 +581,7 @@ fw_fill_response(struct fw_packet *respo - } - EXPORT_SYMBOL(fw_fill_response); - --static struct fw_request * --allocate_request(struct fw_packet *p) -+static struct fw_request *allocate_request(struct fw_packet *p) - { - struct fw_request *request; - u32 *data, length; -@@ -649,8 +641,8 @@ allocate_request(struct fw_packet *p) - return request; - } - --void --fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) -+void fw_send_response(struct fw_card *card, -+ struct fw_request *request, int rcode) - { - /* unified transaction or broadcast transaction: don't respond */ - if (request->ack != ACK_PENDING || -@@ -670,8 +662,7 @@ fw_send_response(struct fw_card *card, s - } - EXPORT_SYMBOL(fw_send_response); - --void --fw_core_handle_request(struct fw_card *card, struct fw_packet *p) -+void fw_core_handle_request(struct fw_card *card, struct fw_packet *p) - { - struct fw_address_handler *handler; - struct fw_request *request; -@@ -719,8 +710,7 @@ fw_core_handle_request(struct fw_card *c - } - EXPORT_SYMBOL(fw_core_handle_request); - --void --fw_core_handle_response(struct fw_card *card, struct fw_packet *p) -+void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) - { - struct fw_transaction *t; - unsigned long flags; -@@ -793,12 +783,10 @@ static const struct fw_address_region to - { .start = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP, - .end = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP_END, }; - --static void --handle_topology_map(struct fw_card *card, struct fw_request *request, -- int tcode, int destination, int source, -- int generation, int speed, -- unsigned long long offset, -- void *payload, size_t length, void *callback_data) -+static void handle_topology_map(struct fw_card *card, struct fw_request *request, -+ int tcode, int destination, int source, int generation, -+ int speed, unsigned long long offset, -+ void *payload, size_t length, void *callback_data) - { - int i, start, end; - __be32 *map; -@@ -832,12 +820,10 @@ static const struct fw_address_region re - { .start = CSR_REGISTER_BASE, - .end = CSR_REGISTER_BASE | CSR_CONFIG_ROM, }; - --static void --handle_registers(struct fw_card *card, struct fw_request *request, -- int tcode, int destination, int source, -- int generation, int speed, -- unsigned long long offset, -- void *payload, size_t length, void *callback_data) -+static void handle_registers(struct fw_card *card, struct fw_request *request, -+ int tcode, int destination, int source, int generation, -+ int speed, unsigned long long offset, -+ void *payload, size_t length, void *callback_data) - { - int reg = offset & ~CSR_REGISTER_BASE; - unsigned long long bus_time; -@@ -939,11 +925,11 @@ static struct fw_descriptor model_id_des - - static int __init fw_core_init(void) - { -- int retval; -+ int ret; - -- retval = bus_register(&fw_bus_type); -- if (retval < 0) -- return retval; -+ ret = bus_register(&fw_bus_type); -+ if (ret < 0) -+ return ret; - - fw_cdev_major = register_chrdev(0, "firewire", &fw_device_ops); - if (fw_cdev_major < 0) { -@@ -951,19 +937,10 @@ static int __init fw_core_init(void) - return fw_cdev_major; - } - -- retval = fw_core_add_address_handler(&topology_map, -- &topology_map_region); -- BUG_ON(retval < 0); -- -- retval = fw_core_add_address_handler(®isters, -- ®isters_region); -- BUG_ON(retval < 0); -- -- /* Add the vendor textual descriptor. */ -- retval = fw_core_add_descriptor(&vendor_id_descriptor); -- BUG_ON(retval < 0); -- retval = fw_core_add_descriptor(&model_id_descriptor); -- BUG_ON(retval < 0); -+ fw_core_add_address_handler(&topology_map, &topology_map_region); -+ fw_core_add_address_handler(®isters, ®isters_region); -+ fw_core_add_descriptor(&vendor_id_descriptor); -+ fw_core_add_descriptor(&model_id_descriptor); - - return 0; - } -diff -Naurp linux-2.6-git/drivers/firewire/fw-transaction.h firewire-git/drivers/firewire/fw-transaction.h ---- linux-2.6-git/drivers/firewire/fw-transaction.h 2009-01-30 13:39:02.992772636 -0500 -+++ firewire-git/drivers/firewire/fw-transaction.h 2009-01-30 13:35:51.862647087 -0500 -@@ -82,14 +82,14 @@ - #define CSR_SPEED_MAP 0x2000 - #define CSR_SPEED_MAP_END 0x3000 - -+#define BANDWIDTH_AVAILABLE_INITIAL 4915 - #define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31) - #define BROADCAST_CHANNEL_VALID (1 << 30) - - #define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args) - #define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args) - --static inline void --fw_memcpy_from_be32(void *_dst, void *_src, size_t size) -+static inline void fw_memcpy_from_be32(void *_dst, void *_src, size_t size) - { - u32 *dst = _dst; - __be32 *src = _src; -@@ -99,8 +99,7 @@ fw_memcpy_from_be32(void *_dst, void *_s - dst[i] = be32_to_cpu(src[i]); - } - --static inline void --fw_memcpy_to_be32(void *_dst, void *_src, size_t size) -+static inline void fw_memcpy_to_be32(void *_dst, void *_src, size_t size) - { - fw_memcpy_from_be32(_dst, _src, size); - } -@@ -125,8 +124,7 @@ typedef void (*fw_packet_callback_t)(str - struct fw_card *card, int status); - - typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode, -- void *data, -- size_t length, -+ void *data, size_t length, - void *callback_data); - - /* -@@ -141,12 +139,6 @@ typedef void (*fw_address_callback_t)(st - void *data, size_t length, - void *callback_data); - --typedef void (*fw_bus_reset_callback_t)(struct fw_card *handle, -- int node_id, int generation, -- u32 *self_ids, -- int self_id_count, -- void *callback_data); -- - struct fw_packet { - int speed; - int generation; -@@ -187,12 +179,6 @@ struct fw_transaction { - void *callback_data; - }; - --static inline struct fw_packet * --fw_packet(struct list_head *l) --{ -- return list_entry(l, struct fw_packet, link); --} -- - struct fw_address_handler { - u64 offset; - size_t length; -@@ -201,7 +187,6 @@ struct fw_address_handler { - struct list_head link; - }; - -- - struct fw_address_region { - u64 start; - u64 end; -@@ -315,10 +300,8 @@ struct fw_iso_packet { - struct fw_iso_context; - - typedef void (*fw_iso_callback_t)(struct fw_iso_context *context, -- u32 cycle, -- size_t header_length, -- void *header, -- void *data); -+ u32 cycle, size_t header_length, -+ void *header, void *data); - - /* - * An iso buffer is just a set of pages mapped for DMA in the -@@ -344,36 +327,25 @@ struct fw_iso_context { - void *callback_data; - }; - --int --fw_iso_buffer_init(struct fw_iso_buffer *buffer, -- struct fw_card *card, -- int page_count, -- enum dma_data_direction direction); --int --fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); --void --fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); -- --struct fw_iso_context * --fw_iso_context_create(struct fw_card *card, int type, -- int channel, int speed, size_t header_size, -- fw_iso_callback_t callback, void *callback_data); -- --void --fw_iso_context_destroy(struct fw_iso_context *ctx); -- --int --fw_iso_context_queue(struct fw_iso_context *ctx, -- struct fw_iso_packet *packet, -- struct fw_iso_buffer *buffer, -- unsigned long payload); -- --int --fw_iso_context_start(struct fw_iso_context *ctx, -- int cycle, int sync, int tags); -+int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, -+ int page_count, enum dma_data_direction direction); -+int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); -+void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); -+ -+struct fw_iso_context *fw_iso_context_create(struct fw_card *card, -+ int type, int channel, int speed, size_t header_size, -+ fw_iso_callback_t callback, void *callback_data); -+int fw_iso_context_queue(struct fw_iso_context *ctx, -+ struct fw_iso_packet *packet, -+ struct fw_iso_buffer *buffer, -+ unsigned long payload); -+int fw_iso_context_start(struct fw_iso_context *ctx, -+ int cycle, int sync, int tags); -+int fw_iso_context_stop(struct fw_iso_context *ctx); -+void fw_iso_context_destroy(struct fw_iso_context *ctx); - --int --fw_iso_context_stop(struct fw_iso_context *ctx); -+void fw_iso_resource_manage(struct fw_card *card, int generation, -+ u64 channels_mask, int *channel, int *bandwidth, bool allocate); - - struct fw_card_driver { - /* -@@ -415,7 +387,7 @@ struct fw_card_driver { - - struct fw_iso_context * - (*allocate_iso_context)(struct fw_card *card, -- int type, size_t header_size); -+ int type, int channel, size_t header_size); - void (*free_iso_context)(struct fw_iso_context *ctx); - - int (*start_iso)(struct fw_iso_context *ctx, -@@ -429,24 +401,18 @@ struct fw_card_driver { - int (*stop_iso)(struct fw_iso_context *ctx); - }; - --int --fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); -+int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); - --void --fw_send_request(struct fw_card *card, struct fw_transaction *t, -+void fw_send_request(struct fw_card *card, struct fw_transaction *t, - int tcode, int destination_id, int generation, int speed, - unsigned long long offset, void *data, size_t length, - fw_transaction_callback_t callback, void *callback_data); -- --int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, -- int generation, int speed, unsigned long long offset, -- void *data, size_t length); -- - int fw_cancel_transaction(struct fw_card *card, - struct fw_transaction *transaction); -- - void fw_flush_transactions(struct fw_card *card); -- -+int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, -+ int generation, int speed, unsigned long long offset, -+ void *data, size_t length); - void fw_send_phy_config(struct fw_card *card, - int node_id, int generation, int gap_count); - -@@ -454,29 +420,18 @@ void fw_send_phy_config(struct fw_card * - * Called by the topology code to inform the device code of node - * activity; found, lost, or updated nodes. - */ --void --fw_node_event(struct fw_card *card, struct fw_node *node, int event); -+void fw_node_event(struct fw_card *card, struct fw_node *node, int event); - - /* API used by card level drivers */ - --void --fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, -- struct device *device); --int --fw_card_add(struct fw_card *card, -- u32 max_receive, u32 link_speed, u64 guid); -- --void --fw_core_remove_card(struct fw_card *card); -- --void --fw_core_handle_bus_reset(struct fw_card *card, -- int node_id, int generation, -- int self_id_count, u32 *self_ids); --void --fw_core_handle_request(struct fw_card *card, struct fw_packet *request); -- --void --fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); -+void fw_card_initialize(struct fw_card *card, -+ const struct fw_card_driver *driver, struct device *device); -+int fw_card_add(struct fw_card *card, -+ u32 max_receive, u32 link_speed, u64 guid); -+void fw_core_remove_card(struct fw_card *card); -+void fw_core_handle_bus_reset(struct fw_card *card, int node_id, -+ int generation, int self_id_count, u32 *self_ids); -+void fw_core_handle_request(struct fw_card *card, struct fw_packet *request); -+void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); - - #endif /* __fw_transaction_h */ ---- linux-2.6-git/include/linux/firewire-cdev.h 2008-11-04 11:19:21.000000000 -0500 -+++ firewire-git/include/linux/firewire-cdev.h 2009-01-30 13:35:54.327647015 -0500 -@@ -25,10 +25,12 @@ - #include - #include - --#define FW_CDEV_EVENT_BUS_RESET 0x00 --#define FW_CDEV_EVENT_RESPONSE 0x01 --#define FW_CDEV_EVENT_REQUEST 0x02 --#define FW_CDEV_EVENT_ISO_INTERRUPT 0x03 -+#define FW_CDEV_EVENT_BUS_RESET 0x00 -+#define FW_CDEV_EVENT_RESPONSE 0x01 -+#define FW_CDEV_EVENT_REQUEST 0x02 -+#define FW_CDEV_EVENT_ISO_INTERRUPT 0x03 -+#define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED 0x04 -+#define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 0x05 - - /** - * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types -@@ -136,7 +138,24 @@ struct fw_cdev_event_request { - * This event is sent when the controller has completed an &fw_cdev_iso_packet - * with the %FW_CDEV_ISO_INTERRUPT bit set. In the receive case, the headers - * stripped of all packets up until and including the interrupt packet are -- * returned in the @header field. -+ * returned in the @header field. The amount of header data per packet is as -+ * specified at iso context creation by &fw_cdev_create_iso_context.header_size. -+ * -+ * In version 1 of this ABI, header data consisted of the 1394 isochronous -+ * packet header, followed by quadlets from the packet payload if -+ * &fw_cdev_create_iso_context.header_size > 4. -+ * -+ * In version 2 of this ABI, header data consist of the 1394 isochronous -+ * packet header, followed by a timestamp quadlet if -+ * &fw_cdev_create_iso_context.header_size > 4, followed by quadlets from the -+ * packet payload if &fw_cdev_create_iso_context.header_size > 8. -+ * -+ * Behaviour of ver. 1 of this ABI is no longer available since ABI ver. 2. -+ * -+ * Format of 1394 iso packet header: 16 bits len, 2 bits tag, 6 bits channel, -+ * 4 bits tcode, 4 bits sy, in big endian byte order. Format of timestamp: -+ * 16 bits invalid, 3 bits cycleSeconds, 13 bits cycleCount, in big endian byte -+ * order. - */ - struct fw_cdev_event_iso_interrupt { - __u64 closure; -@@ -147,12 +166,44 @@ struct fw_cdev_event_iso_interrupt { - }; - - /** -+ * struct fw_cdev_event_iso_resource - Iso resources were allocated or freed -+ * @closure: See &fw_cdev_event_common; -+ * set by %FW_CDEV_IOC_(DE)ALLOCATE_ISO_RESOURCE(_ONCE) ioctl -+ * @type: %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or -+ * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED -+ * @handle: Reference by which an allocated resource can be deallocated -+ * @channel: Isochronous channel which was (de)allocated, if any -+ * @bandwidth: Bandwidth allocation units which were (de)allocated, if any -+ * -+ * An %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED event is sent after an isochronous -+ * resource was allocated at the IRM. The client has to check @channel and -+ * @bandwidth for whether the allocation actually succeeded. -+ * -+ * An %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event is sent after an isochronous -+ * resource was deallocated at the IRM. It is also sent when automatic -+ * reallocation after a bus reset failed. -+ * -+ * @channel is <0 if no channel was (de)allocated or if reallocation failed. -+ * @bandwidth is 0 if no bandwidth was (de)allocated or if reallocation failed. -+ */ -+struct fw_cdev_event_iso_resource { -+ __u64 closure; -+ __u32 type; -+ __u32 handle; -+ __s32 channel; -+ __s32 bandwidth; -+}; -+ -+/** - * union fw_cdev_event - Convenience union of fw_cdev_event_ types - * @common: Valid for all types - * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET - * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE - * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST - * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT -+ * @iso_resource: Valid if @common.type == -+ * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or -+ * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED - * - * Convenience union for userspace use. Events could be read(2) into an - * appropriately aligned char buffer and then cast to this union for further -@@ -163,13 +214,15 @@ struct fw_cdev_event_iso_interrupt { - * not fit will be discarded so that the next read(2) will return a new event. - */ - union fw_cdev_event { -- struct fw_cdev_event_common common; -- struct fw_cdev_event_bus_reset bus_reset; -- struct fw_cdev_event_response response; -- struct fw_cdev_event_request request; -- struct fw_cdev_event_iso_interrupt iso_interrupt; -+ struct fw_cdev_event_common common; -+ struct fw_cdev_event_bus_reset bus_reset; -+ struct fw_cdev_event_response response; -+ struct fw_cdev_event_request request; -+ struct fw_cdev_event_iso_interrupt iso_interrupt; -+ struct fw_cdev_event_iso_resource iso_resource; - }; - -+/* available since kernel version 2.6.22 */ - #define FW_CDEV_IOC_GET_INFO _IOWR('#', 0x00, struct fw_cdev_get_info) - #define FW_CDEV_IOC_SEND_REQUEST _IOW('#', 0x01, struct fw_cdev_send_request) - #define FW_CDEV_IOC_ALLOCATE _IOWR('#', 0x02, struct fw_cdev_allocate) -@@ -178,18 +231,29 @@ union fw_cdev_event { - #define FW_CDEV_IOC_INITIATE_BUS_RESET _IOW('#', 0x05, struct fw_cdev_initiate_bus_reset) - #define FW_CDEV_IOC_ADD_DESCRIPTOR _IOWR('#', 0x06, struct fw_cdev_add_descriptor) - #define FW_CDEV_IOC_REMOVE_DESCRIPTOR _IOW('#', 0x07, struct fw_cdev_remove_descriptor) -- - #define FW_CDEV_IOC_CREATE_ISO_CONTEXT _IOWR('#', 0x08, struct fw_cdev_create_iso_context) - #define FW_CDEV_IOC_QUEUE_ISO _IOWR('#', 0x09, struct fw_cdev_queue_iso) - #define FW_CDEV_IOC_START_ISO _IOW('#', 0x0a, struct fw_cdev_start_iso) - #define FW_CDEV_IOC_STOP_ISO _IOW('#', 0x0b, struct fw_cdev_stop_iso) -+ -+/* available since kernel version 2.6.24 */ - #define FW_CDEV_IOC_GET_CYCLE_TIMER _IOR('#', 0x0c, struct fw_cdev_get_cycle_timer) - --/* FW_CDEV_VERSION History -- * -- * 1 Feb 18, 2007: Initial version. -+/* available since kernel version 2.6.30 */ -+#define FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE _IOWR('#', 0x0d, struct fw_cdev_allocate_iso_resource) -+#define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE _IOW('#', 0x0e, struct fw_cdev_deallocate) -+#define FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE _IOW('#', 0x0f, struct fw_cdev_allocate_iso_resource) -+#define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE_ONCE _IOW('#', 0x10, struct fw_cdev_allocate_iso_resource) -+#define FW_CDEV_IOC_GET_SPEED _IOR('#', 0x11, struct fw_cdev_get_speed) -+#define FW_CDEV_IOC_SEND_BROADCAST_REQUEST _IOW('#', 0x12, struct fw_cdev_send_request) -+ -+/* -+ * FW_CDEV_VERSION History -+ * 1 (2.6.22) - initial version -+ * 2 (2.6.30) - changed &fw_cdev_event_iso_interrupt.header if -+ * &fw_cdev_create_iso_context.header_size is 8 or more - */ --#define FW_CDEV_VERSION 1 -+#define FW_CDEV_VERSION 2 - - /** - * struct fw_cdev_get_info - General purpose information ioctl -@@ -201,7 +265,7 @@ union fw_cdev_event { - * case, @rom_length is updated with the actual length of the - * configuration ROM. - * @rom: If non-zero, address of a buffer to be filled by a copy of the -- * local node's configuration ROM -+ * device's configuration ROM - * @bus_reset: If non-zero, address of a buffer to be filled by a - * &struct fw_cdev_event_bus_reset with the current state - * of the bus. This does not cause a bus reset to happen. -@@ -229,7 +293,7 @@ struct fw_cdev_get_info { - * Send a request to the device. This ioctl implements all outgoing requests. - * Both quadlet and block request specify the payload as a pointer to the data - * in the @data field. Once the transaction completes, the kernel writes an -- * &fw_cdev_event_request event back. The @closure field is passed back to -+ * &fw_cdev_event_response event back. The @closure field is passed back to - * user space in the response event. - */ - struct fw_cdev_send_request { -@@ -284,9 +348,9 @@ struct fw_cdev_allocate { - }; - - /** -- * struct fw_cdev_deallocate - Free an address range allocation -- * @handle: Handle to the address range, as returned by the kernel when the -- * range was allocated -+ * struct fw_cdev_deallocate - Free a CSR address range or isochronous resource -+ * @handle: Handle to the address range or iso resource, as returned by the -+ * kernel when the range or resource was allocated - */ - struct fw_cdev_deallocate { - __u32 handle; -@@ -370,6 +434,9 @@ struct fw_cdev_remove_descriptor { - * - * If a context was successfully created, the kernel writes back a handle to the - * context, which must be passed in for subsequent operations on that context. -+ * -+ * Note that the effect of a @header_size > 4 depends on -+ * &fw_cdev_get_info.version, as documented at &fw_cdev_event_iso_interrupt. - */ - struct fw_cdev_create_iso_context { - __u32 type; -@@ -473,10 +540,73 @@ struct fw_cdev_stop_iso { - * The %FW_CDEV_IOC_GET_CYCLE_TIMER ioctl reads the isochronous cycle timer - * and also the system clock. This allows to express the receive time of an - * isochronous packet as a system time with microsecond accuracy. -+ * -+ * @cycle_timer consists of 7 bits cycleSeconds, 13 bits cycleCount, and -+ * 12 bits cycleOffset, in host byte order. - */ - struct fw_cdev_get_cycle_timer { - __u64 local_time; - __u32 cycle_timer; - }; - -+/** -+ * struct fw_cdev_allocate_iso_resource - (De)allocate a channel or bandwidth -+ * @closure: Passed back to userspace in correponding iso resource events -+ * @channels: Isochronous channels of which one is to be (de)allocated -+ * @bandwidth: Isochronous bandwidth units to be (de)allocated -+ * @handle: Handle to the allocation, written by the kernel (only valid in -+ * case of %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE ioctls) -+ * -+ * The %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE ioctl initiates allocation of an -+ * isochronous channel and/or of isochronous bandwidth at the isochronous -+ * resource manager (IRM). Only one of the channels specified in @channels is -+ * allocated. An %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED is sent after -+ * communication with the IRM, indicating success or failure in the event data. -+ * The kernel will automatically reallocate the resources after bus resets. -+ * Should a reallocation fail, an %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event -+ * will be sent. The kernel will also automatically deallocate the resources -+ * when the file descriptor is closed. -+ * -+ * The %FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE ioctl can be used to initiate -+ * deallocation of resources which were allocated as described above. -+ * An %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event concludes this operation. -+ * -+ * The %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE ioctl is a variant of allocation -+ * without automatic re- or deallocation. -+ * An %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED event concludes this operation, -+ * indicating success or failure in its data. -+ * -+ * The %FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE_ONCE ioctl works like -+ * %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE except that resources are freed -+ * instead of allocated. -+ * An %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED event concludes this operation. -+ * -+ * To summarize, %FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE allocates iso resources -+ * for the lifetime of the fd or handle. -+ * In contrast, %FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE allocates iso resources -+ * for the duration of a bus generation. -+ * -+ * @channels is a host-endian bitfield with the least significant bit -+ * representing channel 0 and the most significant bit representing channel 63: -+ * 1ULL << c for each channel c that is a candidate for (de)allocation. -+ * -+ * @bandwidth is expressed in bandwidth allocation units, i.e. the time to send -+ * one quadlet of data (payload or header data) at speed S1600. -+ */ -+struct fw_cdev_allocate_iso_resource { -+ __u64 closure; -+ __u64 channels; -+ __u32 bandwidth; -+ __u32 handle; -+}; -+ -+/** -+ * struct fw_cdev_get_speed - Query maximum speed to or from this device -+ * @max_speed: Speed code; minimum of the device's link speed, the local node's -+ * link speed, and all PHY port speeds between the two links -+ */ -+struct fw_cdev_get_speed { -+ __u32 max_speed; -+}; -+ - #endif /* _LINUX_FIREWIRE_CDEV_H */ 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..856b9b95a 100644 --- a/linux-2.6-i386-nx-emulation.patch +++ b/linux-2.6-i386-nx-emulation.patch @@ -3,21 +3,21 @@ @@ -5,6 +5,7 @@ #include #include - #include + +#include + #include - static inline void fill_ldt(struct desc_struct *desc, - const struct user_desc *info) -@@ -93,6 +94,9 @@ static inline int desc_empty(const void *ptr) + static inline void fill_ldt(struct desc_struct *desc, const struct user_desc *info) +@@ -97,6 +98,9 @@ static inline int desc_empty(const void *ptr) - #define load_TLS(t, cpu) native_load_tls(t, cpu) - #define set_ldt native_set_ldt + #define load_TLS(t, cpu) native_load_tls(t, cpu) + #define set_ldt native_set_ldt +#ifdef CONFIG_X86_32 -+#define load_user_cs_desc native_load_user_cs_desc ++#define load_user_cs_desc native_load_user_cs_desc +#endif /*CONFIG_X86_32*/ - #define write_ldt_entry(dt, entry, desc) \ - native_write_ldt_entry(dt, entry, desc) + #define write_ldt_entry(dt, entry, desc) native_write_ldt_entry(dt, entry, desc) + #define write_gdt_entry(dt, entry, desc, type) native_write_gdt_entry(dt, entry, desc, type) @@ -392,4 +396,25 @@ static inline void set_system_intr_gate_ist(int n, void *addr, unsigned ist) _set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS); } @@ -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,6 +7,9 @@ /* * The x86 doesn't have a mmu context, but * we put the segment information here. @@ -56,9 +56,11 @@ */ typedef struct { void *ldt; - int size; +@@ -19,6 +22,11 @@ typedef struct { + struct mutex lock; void *vdso; ++ +#ifdef CONFIG_X86_32 + struct desc_struct user_cs; + unsigned long exec_limit; @@ -141,8 +143,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 +474,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; @@ -502,16 +504,15 @@ static void unmap_region(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev, unsigned long start, unsigned long end); -@@ -388,6 +401,9 @@ +@@ -432,6 +432,8 @@ __vma_link(struct mm_struct *mm, struct vm_area_struct *vma, + struct vm_area_struct *prev, struct rb_node **rb_link, + struct rb_node *rb_parent) { - struct vm_area_struct *next; - + if (vma->vm_flags & VM_EXEC) + arch_add_exec_range(mm, vma->vm_end); -+ - vma->vm_prev = prev; - if (prev) { - next = prev->vm_next; + __vma_link_list(mm, vma, prev, rb_parent); + __vma_link_rb(mm, vma, rb_link, rb_parent); + } @@ -489,6 +504,8 @@ rb_erase(&vma->vm_rb, &mm->mm_rb); if (mm->mmap_cache == vma) @@ -549,8 +550,8 @@ /* Success. */ @@ -2254,6 +2367,7 @@ - free_pgtables(tlb, vma, FIRST_USER_ADDRESS, 0); - tlb_finish_mmu(tlb, 0, end); + free_pgtables(&tlb, vma, FIRST_USER_ADDRESS, 0); + tlb_finish_mmu(&tlb, 0, end); + arch_flush_exec_range(mm); /* 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-selinux-mprotect-checks.patch b/linux-2.6-selinux-mprotect-checks.patch deleted file mode 100644 index 010a63c43..000000000 --- a/linux-2.6-selinux-mprotect-checks.patch +++ /dev/null @@ -1,124 +0,0 @@ -This needs a fixed toolchain, and a userspace rebuild to work. -For these reasons, it's had difficulty getting upstream. - -ie, Fedora has a new enough toolchain, and has been rebuilt, so we don't need -the ifdefs. Other distros don't/haven't, and this patch would break them -if pushed upstream. - - -Subject: [Fwd: Re: [PATCH] Disable execmem for sparc] -From: Stephen Smalley -To: Dave Jones -Date: Wed, 28 Apr 2010 16:04:56 -0400 -Message-Id: <1272485096.6013.326.camel@moss-pluto.epoch.ncsc.mil> - --------- Forwarded Message -------- -From: Stephen Smalley -To: David Miller -Cc: tcallawa@redhat.com, dennis@ausil.us, sparclinux@vger.kernel.org, dgilmore@redhat.com, jmorris@namei.org, eparis@parisplace.org -Subject: Re: [PATCH] Disable execmem for sparc -Date: Wed, 28 Apr 2010 15:57:57 -0400 - -On Tue, 2010-04-27 at 11:47 -0700, David Miller wrote: -> From: "Tom \"spot\" Callaway" -> Date: Tue, 27 Apr 2010 14:20:21 -0400 -> -> > [root@apollo ~]$ cat /proc/2174/maps -> > 00010000-00014000 r-xp 00000000 fd:00 15466577 -> > /sbin/mingetty -> > 00022000-00024000 rwxp 00002000 fd:00 15466577 -> > /sbin/mingetty -> > 00024000-00046000 rwxp 00000000 00:00 0 -> > [heap] -> -> SELINUX probably barfs on the executable heap, the PLT is in the HEAP -> just like powerpc32 and that's why VM_DATA_DEFAULT_FLAGS has to set -> both executable and writable. -> -> You also can't remove the CONFIG_PPC32 ifdefs in selinux, since -> because of the VM_DATA_DEFAULT_FLAGS setting used still in that arch, -> the heap will always have executable permission, just like sparc does. -> You have to support those binaries forever, whether you like it or not. -> -> Let's just replace the CONFIG_PPC32 ifdef in SELINUX with CONFIG_PPC32 -> || CONFIG_SPARC as in Tom's original patch and let's be done with -> this. -> -> In fact I would go through all the arch/ header files and check the -> VM_DATA_DEFAULT_FLAGS settings and add the necessary new ifdefs to the -> SELINUX code so that other platforms don't have the pain of having to -> go through this process too. - -To avoid maintaining per-arch ifdefs, it seems that we could just -directly use (VM_DATA_DEFAULT_FLAGS & VM_EXEC) as the basis for deciding -whether to enable or disable these checks. VM_DATA_DEFAULT_FLAGS isn't -constant on some architectures but instead depends on -current->personality, but we want this applied uniformly. So we'll just -use the initial task state to determine whether or not to enable these -checks. - -Signed-off-by: Stephen Smalley - -diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c -index ebee467..a03fd74 100644 ---- a/security/selinux/hooks.c -+++ b/security/selinux/hooks.c -@@ -2999,13 +2999,15 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, - return file_has_perm(cred, file, av); - } - -+static int default_noexec; -+ - static int file_map_prot_check(struct file *file, unsigned long prot, int shared) - { - const struct cred *cred = current_cred(); - int rc = 0; - --#ifndef CONFIG_PPC32 -- if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { -+ if (default_noexec && -+ (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { - /* - * We are making executable an anonymous mapping or a - * private file mapping that will also be writable. -@@ -3015,7 +3017,6 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared - if (rc) - goto error; - } --#endif - - if (file) { - /* read access is always possible with a mapping */ -@@ -3076,8 +3077,8 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, - if (selinux_checkreqprot) - prot = reqprot; - --#ifndef CONFIG_PPC32 -- if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { -+ if (default_noexec && -+ (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { - int rc = 0; - if (vma->vm_start >= vma->vm_mm->start_brk && - vma->vm_end <= vma->vm_mm->brk) { -@@ -3099,7 +3100,6 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, - if (rc) - return rc; - } --#endif - - return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); - } -@@ -5662,6 +5662,8 @@ static __init int selinux_init(void) - /* Set the security state for the initial task. */ - cred_init_security(); - -+ default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC); -+ - sel_inode_cache = kmem_cache_create("selinux_inode_security", - sizeof(struct inode_security_struct), - 0, SLAB_PANIC, NULL); - --- -Stephen Smalley -National Security Agency - diff --git a/linux-2.6-silence-noise.patch b/linux-2.6-silence-noise.patch index 32c678b1f..8aba3cdab 100644 --- a/linux-2.6-silence-noise.patch +++ b/linux-2.6-silence-noise.patch @@ -34,23 +34,24 @@ ratelimited. It isn't particularly useful, so just remove it. Signed-off-by: Dave Jones ---- linux-2.6.27.noarch/net/can/af_can.c~ 2008-12-11 16:53:48.000000000 -0500 -+++ linux-2.6.27.noarch/net/can/af_can.c 2008-12-11 16:54:42.000000000 -0500 -@@ -134,13 +134,9 @@ static int can_create(struct net *net, s +--- a/net/can/af_can.c ++++ b/net/can/af_can.c +@@ -157,13 +157,9 @@ static int can_create(struct net *net, struct socket *sock, int protocol, err = request_module("can-proto-%d", protocol); /* - * In case of error we only print a message but don't - * return the error code immediately. Below we will - * return -EPROTONOSUPPORT -+ * In case of error we don't return the error code immediately. ++ * In case of error we but don't return the error code immediately. + * Below we will return -EPROTONOSUPPORT */ - if (err && printk_ratelimit()) - printk(KERN_ERR "can: request_module " - "(can-proto-%d) failed.\n", protocol); + + cp = can_get_proto(protocol); } - #endif This was removed in revision 1.6 of linux-2.6-silence-noise.patch in ye olde CVS tree. I have no idea why. Originally the pr_debug in @@ -68,5 +69,5 @@ index 2a52270..bacbdd2 100644 - 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/linux-2.6-sparc-selinux-mprotect-checks.patch b/linux-2.6-sparc-selinux-mprotect-checks.patch deleted file mode 100644 index cc821e323..000000000 --- a/linux-2.6-sparc-selinux-mprotect-checks.patch +++ /dev/null @@ -1,35 +0,0 @@ -diff -up linux-2.6.24.sparc64/security/selinux/hooks.c.BAD linux-2.6.24.sparc64/security/selinux/hooks.c ---- linux-2.6.24.sparc64/security/selinux/hooks.c.BAD 2008-03-21 14:28:06.000000000 -0400 -+++ linux-2.6.24.sparc64/security/selinux/hooks.c 2008-03-21 14:29:10.000000000 -0400 -@@ -3018,6 +3018,7 @@ static int file_map_prot_check(struct fi - const struct cred *cred = current_cred(); - int rc = 0; - -+#ifndef CONFIG_SPARC - if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { - /* - * We are making executable an anonymous mapping or a -@@ -3028,6 +3029,7 @@ static int file_map_prot_check(struct fi - if (rc) - goto error; - } -+#endif - - if (file) { - /* read access is always possible with a mapping */ -@@ -3081,6 +3081,7 @@ static int selinux_file_mprotect(struct - if (selinux_checkreqprot) - prot = reqprot; - -+#ifndef CONFIG_SPARC - if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { - rc = 0; - if (vma->vm_start >= vma->vm_mm->start_brk && -@@ -3103,6 +3103,7 @@ static int selinux_file_mprotect(struct - if (rc) - return rc; - } -+#endif - - return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); - } diff --git a/linux-2.6-tracehook.patch b/linux-2.6-tracehook.patch deleted file mode 100644 index 027c6d533..000000000 --- a/linux-2.6-tracehook.patch +++ /dev/null @@ -1,129 +0,0 @@ -From: Oleg Nesterov - -[PATCH] signals: check ->group_stop_count after tracehook_get_signal() - -Move the call to do_signal_stop() down, after tracehook call. -This makes ->group_stop_count condition visible to tracers before -do_signal_stop() will participate in this group-stop. - -Currently the patch has no effect, tracehook_get_signal() always -returns 0. - -Signed-off-by: Oleg Nesterov -Signed-off-by: Roland McGrath ---- - include/linux/ptrace.h | 1 + - include/linux/sched.h | 1 + - include/linux/tracehook.h | 10 +++++----- - kernel/ptrace.c | 2 +- - kernel/signal.c | 4 ++-- - 5 files changed, 10 insertions(+), 8 deletions(-) - -diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h -index 092a04f..619cdf0 100644 ---- a/include/linux/ptrace.h -+++ b/include/linux/ptrace.h -@@ -106,6 +106,7 @@ extern int ptrace_traceme(void); - extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); - extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); - extern int ptrace_attach(struct task_struct *tsk); -+extern bool __ptrace_detach(struct task_struct *tracer, struct task_struct *tracee); - extern int ptrace_detach(struct task_struct *, unsigned int); - extern void ptrace_disable(struct task_struct *); - extern int ptrace_check_attach(struct task_struct *task, int kill); -diff --git a/include/linux/sched.h b/include/linux/sched.h -index 2238745..09f26df 100644 ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -2061,6 +2061,7 @@ extern int kill_pgrp(struct pid *pid, in - extern int kill_pid(struct pid *pid, int sig, int priv); - extern int kill_proc_info(int, struct siginfo *, pid_t); - extern int do_notify_parent(struct task_struct *, int); -+extern void do_notify_parent_cldstop(struct task_struct *, int); - extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent); - extern void force_sig(int, struct task_struct *); - extern int send_sig(int, struct task_struct *, int); -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 3a2e66d..98917e9 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -134,7 +134,7 @@ static inline __must_check int tracehook - */ - static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) - { -- if (step) { -+ if (step && (task_ptrace(current) & PT_PTRACED)) { - siginfo_t info; - user_single_step_siginfo(current, regs, &info); - force_sig_info(SIGTRAP, &info, current); -@@ -156,7 +156,7 @@ static inline int tracehook_unsafe_exec( - { - int unsafe = 0; - int ptrace = task_ptrace(task); -- if (ptrace & PT_PTRACED) { -+ if (ptrace) { - if (ptrace & PT_PTRACE_CAP) - unsafe |= LSM_UNSAFE_PTRACE_CAP; - else -@@ -178,7 +178,7 @@ static inline int tracehook_unsafe_exec( - */ - static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk) - { -- if (task_ptrace(tsk) & PT_PTRACED) -+ if (task_ptrace(tsk)) - return rcu_dereference(tsk->parent); - return NULL; - } -@@ -386,7 +386,7 @@ static inline void tracehook_signal_hand - const struct k_sigaction *ka, - struct pt_regs *regs, int stepping) - { -- if (stepping) -+ if (stepping && (task_ptrace(current) & PT_PTRACED)) - ptrace_notify(SIGTRAP); - } - -@@ -492,7 +492,7 @@ static inline int tracehook_get_signal(s - */ - static inline int tracehook_notify_jctl(int notify, int why) - { -- return notify ?: (current->ptrace & PT_PTRACED) ? why : 0; -+ return notify ?: task_ptrace(current) ? why : 0; - } - - /** -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 99bbaa3..84d9f8f 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -270,7 +270,7 @@ static int ignoring_children(struct sigh - * reap it now, in that case we must also wake up sub-threads sleeping in - * do_wait(). - */ --static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) -+bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) - { - __ptrace_unlink(p); - -diff --git a/kernel/signal.c b/kernel/signal.c -index 4e3cff1..b74324d 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -1522,7 +1522,7 @@ int do_notify_parent(struct task_struct - return ret; - } - --static void do_notify_parent_cldstop(struct task_struct *tsk, int why) -+void do_notify_parent_cldstop(struct task_struct *tsk, int why) - { - struct siginfo info; - unsigned long flags; -@@ -1794,7 +1794,7 @@ static int do_signal_stop(int signr) - static int ptrace_signal(int signr, siginfo_t *info, - struct pt_regs *regs, void *cookie) - { -- if (!task_ptrace(current)) -+ if (!(task_ptrace(current) & PT_PTRACED)) - return signr; - - ptrace_signal_deliver(regs, cookie); diff --git a/linux-2.6-upstream-reverts.patch b/linux-2.6-upstream-reverts.patch index 157205fb2..607602cfc 100644 --- a/linux-2.6-upstream-reverts.patch +++ b/linux-2.6-upstream-reverts.patch @@ -1,203 +1 @@ -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; +nil diff --git a/linux-2.6-utrace-ptrace.patch b/linux-2.6-utrace-ptrace.patch deleted file mode 100644 index 367deb966..000000000 --- a/linux-2.6-utrace-ptrace.patch +++ /dev/null @@ -1,2031 +0,0 @@ -implement utrace-ptrace - -The patch adds the new file, kernel/ptrace-utrace.c, which contains -the new implementation of ptrace over utrace. - -This file is not compiled until we have CONFIG_UTRACE option, will be -added by the next "utrace core" patch. - -It's supposed to be an invisible implementation change, nothing should -change to userland when CONFIG_UTRACE is enabled. - -Signed-off-by: Roland McGrath -Signed-off-by: Oleg Nesterov ---- - include/linux/ptrace.h | 1 + - kernel/Makefile | 1 + - kernel/ptrace-utrace.c | 1187 ++++++++++++++++++++++++++++++++++++++++++++++++ - kernel/ptrace.c | 690 ++++++++++++++-------------- - kernel/utrace.c | 16 + - 5 files changed, 1544 insertions(+), 351 deletions(-) - -diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h -index 619cdf0..e391bdb 100644 ---- a/include/linux/ptrace.h -+++ b/include/linux/ptrace.h -@@ -100,6 +100,7 @@ - #include /* For struct task_struct. */ - - -+extern void ptrace_notify_stop(struct task_struct *tracee); - extern long arch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data); - extern int ptrace_traceme(void); -diff --git a/kernel/Makefile b/kernel/Makefile -index 1172528..9a815a5 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -71,6 +71,7 @@ obj-$(CONFIG_RESOURCE_COUNTERS) += res_c - obj-$(CONFIG_SMP) += stop_machine.o - obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o - obj-$(CONFIG_UTRACE) += utrace.o -+obj-$(CONFIG_UTRACE) += ptrace-utrace.o - obj-$(CONFIG_AUDIT) += audit.o auditfilter.o - obj-$(CONFIG_AUDITSYSCALL) += auditsc.o - obj-$(CONFIG_AUDIT_WATCH) += audit_watch.o -diff --git a/kernel/ptrace-utrace.c b/kernel/ptrace-utrace.c -new file mode 100644 -index ...a5bcb9e 100644 ---- /dev/null -+++ b/kernel/ptrace-utrace.c -@@ -0,0 +1,1187 @@ -+/* -+ * linux/kernel/ptrace.c -+ * -+ * (C) Copyright 1999 Linus Torvalds -+ * -+ * Common interfaces for "ptrace()" which we do not want -+ * to continually duplicate across every architecture. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * ptrace a task: make the debugger its new parent and -+ * move it to the ptrace list. -+ * -+ * Must be called with the tasklist lock write-held. -+ */ -+void __ptrace_link(struct task_struct *child, struct task_struct *new_parent) -+{ -+ BUG_ON(!list_empty(&child->ptrace_entry)); -+ list_add(&child->ptrace_entry, &new_parent->ptraced); -+ child->parent = new_parent; -+} -+ -+/* -+ * unptrace a task: move it back to its original parent and -+ * remove it from the ptrace list. -+ * -+ * Must be called with the tasklist lock write-held. -+ */ -+void __ptrace_unlink(struct task_struct *child) -+{ -+ BUG_ON(!child->ptrace); -+ -+ child->ptrace = 0; -+ child->parent = child->real_parent; -+ list_del_init(&child->ptrace_entry); -+} -+ -+struct ptrace_context { -+ int options; -+ -+ int signr; -+ siginfo_t *siginfo; -+ -+ int stop_code; -+ unsigned long eventmsg; -+ -+ enum utrace_resume_action resume; -+}; -+ -+#define PT_UTRACED 0x00001000 -+ -+#define PTRACE_O_SYSEMU 0x100 -+#define PTRACE_O_DETACHED 0x200 -+ -+#define PTRACE_EVENT_SYSCALL (1 << 16) -+#define PTRACE_EVENT_SIGTRAP (2 << 16) -+#define PTRACE_EVENT_SIGNAL (3 << 16) -+/* events visible to user-space */ -+#define PTRACE_EVENT_MASK 0xFFFF -+ -+static inline bool ptrace_event_pending(struct ptrace_context *ctx) -+{ -+ return ctx->stop_code != 0; -+} -+ -+static inline int get_stop_event(struct ptrace_context *ctx) -+{ -+ return ctx->stop_code >> 8; -+} -+ -+static inline void set_stop_code(struct ptrace_context *ctx, int event) -+{ -+ ctx->stop_code = (event << 8) | SIGTRAP; -+} -+ -+static inline struct ptrace_context * -+ptrace_context(struct utrace_engine *engine) -+{ -+ return engine->data; -+} -+ -+static const struct utrace_engine_ops ptrace_utrace_ops; /* forward decl */ -+ -+static struct utrace_engine *ptrace_lookup_engine(struct task_struct *tracee) -+{ -+ return utrace_attach_task(tracee, UTRACE_ATTACH_MATCH_OPS, -+ &ptrace_utrace_ops, NULL); -+} -+ -+static int utrace_barrier_uninterruptible(struct task_struct *target, -+ struct utrace_engine *engine) -+{ -+ for (;;) { -+ int err = utrace_barrier(target, engine); -+ -+ if (err != -ERESTARTSYS) -+ return err; -+ -+ schedule_timeout_uninterruptible(1); -+ } -+} -+ -+static struct utrace_engine * -+ptrace_reuse_engine(struct task_struct *tracee) -+{ -+ struct utrace_engine *engine; -+ struct ptrace_context *ctx; -+ int err = -EPERM; -+ -+ engine = ptrace_lookup_engine(tracee); -+ if (IS_ERR(engine)) -+ return engine; -+ -+ ctx = ptrace_context(engine); -+ if (unlikely(ctx->options == PTRACE_O_DETACHED)) { -+ /* -+ * Try to reuse this self-detaching engine. -+ * The only caller which can hit this case is ptrace_attach(), -+ * it holds ->cred_guard_mutex. -+ */ -+ ctx->options = 0; -+ ctx->eventmsg = 0; -+ -+ /* make sure we don't get unwanted reports */ -+ err = utrace_set_events(tracee, engine, UTRACE_EVENT(QUIESCE)); -+ if (!err || err == -EINPROGRESS) { -+ ctx->resume = UTRACE_RESUME; -+ /* synchronize with ptrace_report_signal() */ -+ err = utrace_barrier_uninterruptible(tracee, engine); -+ } -+ -+ if (!err) { -+ WARN_ON(engine->ops != &ptrace_utrace_ops && -+ !tracee->exit_state); -+ return engine; -+ } -+ -+ WARN_ON(engine->ops == &ptrace_utrace_ops); -+ } -+ -+ utrace_engine_put(engine); -+ return ERR_PTR(err); -+} -+ -+static struct utrace_engine * -+ptrace_attach_engine(struct task_struct *tracee) -+{ -+ struct utrace_engine *engine; -+ struct ptrace_context *ctx; -+ -+ if (unlikely(task_utrace_flags(tracee))) { -+ engine = ptrace_reuse_engine(tracee); -+ if (!IS_ERR(engine) || IS_ERR(engine) == -EPERM) -+ return engine; -+ } -+ -+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); -+ if (unlikely(!ctx)) -+ return ERR_PTR(-ENOMEM); -+ -+ ctx->resume = UTRACE_RESUME; -+ -+ engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | -+ UTRACE_ATTACH_EXCLUSIVE | -+ UTRACE_ATTACH_MATCH_OPS, -+ &ptrace_utrace_ops, ctx); -+ if (unlikely(IS_ERR(engine))) { -+ if (engine != ERR_PTR(-ESRCH) && -+ engine != ERR_PTR(-ERESTARTNOINTR)) -+ engine = ERR_PTR(-EPERM); -+ kfree(ctx); -+ } -+ -+ return engine; -+} -+ -+static inline int ptrace_set_events(struct task_struct *target, -+ struct utrace_engine *engine, -+ unsigned long options) -+{ -+ struct ptrace_context *ctx = ptrace_context(engine); -+ /* -+ * We need QUIESCE for resume handling, CLONE to check -+ * for CLONE_PTRACE, other events are always reported. -+ */ -+ unsigned long events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | -+ UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; -+ -+ ctx->options = options; -+ if (options & PTRACE_O_TRACEEXIT) -+ events |= UTRACE_EVENT(EXIT); -+ -+ return utrace_set_events(target, engine, events); -+} -+ -+/* -+ * Attach a utrace engine for ptrace and set up its event mask. -+ * Returns error code or 0 on success. -+ */ -+static int ptrace_attach_task(struct task_struct *tracee, int options) -+{ -+ struct utrace_engine *engine; -+ int err; -+ -+ engine = ptrace_attach_engine(tracee); -+ if (IS_ERR(engine)) -+ return PTR_ERR(engine); -+ /* -+ * It can fail only if the tracee is dead, the caller -+ * must notice this before setting PT_UTRACED. -+ */ -+ err = ptrace_set_events(tracee, engine, options); -+ WARN_ON(err && !tracee->exit_state); -+ utrace_engine_put(engine); -+ return 0; -+} -+ -+static int ptrace_wake_up(struct task_struct *tracee, -+ struct utrace_engine *engine, -+ enum utrace_resume_action action, -+ bool force_wakeup) -+{ -+ if (force_wakeup) { -+ unsigned long flags; -+ /* -+ * Preserve the compatibility bug. Historically ptrace -+ * wakes up the tracee even if it should not. Clear -+ * SIGNAL_STOP_STOPPED for utrace_wakeup(). -+ */ -+ if (lock_task_sighand(tracee, &flags)) { -+ tracee->signal->flags &= ~SIGNAL_STOP_STOPPED; -+ unlock_task_sighand(tracee, &flags); -+ } -+ } -+ -+ if (action != UTRACE_REPORT) -+ ptrace_context(engine)->stop_code = 0; -+ -+ return utrace_control(tracee, engine, action); -+} -+ -+static void ptrace_detach_task(struct task_struct *tracee, int sig) -+{ -+ /* -+ * If true, the caller is PTRACE_DETACH, otherwise -+ * the tracer detaches implicitly during exit. -+ */ -+ bool explicit = (sig >= 0); -+ struct utrace_engine *engine = ptrace_lookup_engine(tracee); -+ enum utrace_resume_action action = UTRACE_DETACH; -+ struct ptrace_context *ctx; -+ -+ if (unlikely(IS_ERR(engine))) -+ return; -+ -+ ctx = ptrace_context(engine); -+ -+ if (!explicit) { -+ int err; -+ -+ /* -+ * We are going to detach, the tracee can be running. -+ * Ensure ptrace_report_signal() won't report a signal. -+ */ -+ ctx->resume = UTRACE_DETACH; -+ err = utrace_barrier_uninterruptible(tracee, engine); -+ -+ if (!err && ctx->siginfo) { -+ /* -+ * The tracee has already reported a signal -+ * before utrace_barrier(). -+ * -+ * Resume it like we do in PTRACE_EVENT_SIGNAL -+ * case below. The difference is that we can race -+ * with ptrace_report_signal() if the tracee is -+ * running but this doesn't matter. In any case -+ * UTRACE_SIGNAL_REPORT must be pending and it -+ * can return nothing but UTRACE_DETACH. -+ */ -+ action = UTRACE_RESUME; -+ } -+ -+ } else if (sig) { -+ switch (get_stop_event(ctx)) { -+ case PTRACE_EVENT_SYSCALL: -+ send_sig_info(sig, SEND_SIG_PRIV, tracee); -+ break; -+ -+ case PTRACE_EVENT_SIGNAL: -+ ctx->signr = sig; -+ ctx->resume = UTRACE_DETACH; -+ action = UTRACE_RESUME; -+ break; -+ } -+ } -+ -+ ptrace_wake_up(tracee, engine, action, explicit); -+ -+ if (action != UTRACE_DETACH) -+ ctx->options = PTRACE_O_DETACHED; -+ -+ utrace_engine_put(engine); -+} -+ -+static void ptrace_abort_attach(struct task_struct *tracee) -+{ -+ ptrace_detach_task(tracee, 0); -+} -+ -+static u32 ptrace_report_exit(u32 action, struct utrace_engine *engine, -+ long orig_code, long *code) -+{ -+ struct ptrace_context *ctx = ptrace_context(engine); -+ -+ WARN_ON(ptrace_event_pending(ctx) && -+ !signal_group_exit(current->signal)); -+ -+ set_stop_code(ctx, PTRACE_EVENT_EXIT); -+ ctx->eventmsg = *code; -+ -+ return UTRACE_STOP; -+} -+ -+static void ptrace_clone_attach(struct task_struct *child, -+ int options) -+{ -+ struct task_struct *parent = current; -+ struct task_struct *tracer; -+ bool abort = true; -+ -+ if (unlikely(ptrace_attach_task(child, options))) { -+ WARN_ON(1); -+ return; -+ } -+ -+ write_lock_irq(&tasklist_lock); -+ tracer = parent->parent; -+ if (!(tracer->flags & PF_EXITING) && parent->ptrace) { -+ child->ptrace = parent->ptrace; -+ __ptrace_link(child, tracer); -+ abort = false; -+ } -+ write_unlock_irq(&tasklist_lock); -+ if (unlikely(abort)) { -+ ptrace_abort_attach(child); -+ return; -+ } -+ -+ sigaddset(&child->pending.signal, SIGSTOP); -+ set_tsk_thread_flag(child, TIF_SIGPENDING); -+} -+ -+static u32 ptrace_report_clone(u32 action, struct utrace_engine *engine, -+ unsigned long clone_flags, -+ struct task_struct *child) -+{ -+ struct ptrace_context *ctx = ptrace_context(engine); -+ int event = 0; -+ -+ WARN_ON(ptrace_event_pending(ctx)); -+ -+ if (clone_flags & CLONE_UNTRACED) { -+ /* no events reported */ -+ } else if (clone_flags & CLONE_VFORK) { -+ if (ctx->options & PTRACE_O_TRACEVFORK) -+ event = PTRACE_EVENT_VFORK; -+ else if (ctx->options & PTRACE_O_TRACEVFORKDONE) -+ event = PTRACE_EVENT_VFORK_DONE; -+ } else if ((clone_flags & CSIGNAL) != SIGCHLD) { -+ if (ctx->options & PTRACE_O_TRACECLONE) -+ event = PTRACE_EVENT_CLONE; -+ } else if (ctx->options & PTRACE_O_TRACEFORK) { -+ event = PTRACE_EVENT_FORK; -+ } -+ /* -+ * Any of these reports implies auto-attaching the new child. -+ * So does CLONE_PTRACE, even with no event to report. -+ */ -+ if ((event && event != PTRACE_EVENT_VFORK_DONE) || -+ (clone_flags & CLONE_PTRACE)) -+ ptrace_clone_attach(child, ctx->options); -+ -+ if (!event) -+ return UTRACE_RESUME; -+ -+ set_stop_code(ctx, event); -+ ctx->eventmsg = child->pid; -+ /* -+ * We shouldn't stop now, inside the do_fork() path. -+ * We will stop later, before return to user-mode. -+ */ -+ if (event == PTRACE_EVENT_VFORK_DONE) -+ return UTRACE_REPORT; -+ else -+ return UTRACE_STOP; -+} -+ -+static inline void set_syscall_code(struct ptrace_context *ctx) -+{ -+ set_stop_code(ctx, PTRACE_EVENT_SYSCALL); -+ if (ctx->options & PTRACE_O_TRACESYSGOOD) -+ ctx->stop_code |= 0x80; -+} -+ -+static u32 ptrace_report_syscall_entry(u32 action, struct utrace_engine *engine, -+ struct pt_regs *regs) -+{ -+ struct ptrace_context *ctx = ptrace_context(engine); -+ -+ if (action & UTRACE_SYSCALL_RESUMED) { -+ /* -+ * We already reported the first time. -+ * Nothing more to do now. -+ */ -+ if (unlikely(ctx->options & PTRACE_O_SYSEMU)) -+ return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; -+ return utrace_syscall_action(action) | UTRACE_RESUME; -+ } -+ -+ WARN_ON(ptrace_event_pending(ctx)); -+ -+ set_syscall_code(ctx); -+ -+ if (unlikely(ctx->options & PTRACE_O_SYSEMU)) -+ return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; -+ /* -+ * Stop now to report. We will get another callback after -+ * we resume, with the UTRACE_SYSCALL_RESUMED flag set. -+ */ -+ return UTRACE_SYSCALL_RUN | UTRACE_STOP; -+} -+ -+static inline bool is_step_resume(enum utrace_resume_action resume) -+{ -+ return resume == UTRACE_BLOCKSTEP || resume == UTRACE_SINGLESTEP; -+} -+ -+static u32 ptrace_report_syscall_exit(u32 action, struct utrace_engine *engine, -+ struct pt_regs *regs) -+{ -+ struct ptrace_context *ctx = ptrace_context(engine); -+ -+ if (ptrace_event_pending(ctx)) -+ return UTRACE_STOP; -+ -+ if (is_step_resume(ctx->resume)) { -+ ctx->signr = SIGTRAP; -+ return UTRACE_INTERRUPT; -+ } -+ -+ set_syscall_code(ctx); -+ return UTRACE_STOP; -+} -+ -+static u32 ptrace_report_exec(u32 action, struct utrace_engine *engine, -+ const struct linux_binfmt *fmt, -+ const struct linux_binprm *bprm, -+ struct pt_regs *regs) -+{ -+ struct ptrace_context *ctx = ptrace_context(engine); -+ -+ WARN_ON(ptrace_event_pending(ctx)); -+ -+ if (!(ctx->options & PTRACE_O_TRACEEXEC)) { -+ /* -+ * Old-fashioned ptrace'd exec just posts a plain signal. -+ */ -+ send_sig(SIGTRAP, current, 0); -+ return UTRACE_RESUME; -+ } -+ -+ set_stop_code(ctx, PTRACE_EVENT_EXEC); -+ return UTRACE_STOP; -+} -+ -+static enum utrace_signal_action resume_signal(struct ptrace_context *ctx, -+ struct k_sigaction *return_ka) -+{ -+ siginfo_t *info = ctx->siginfo; -+ int signr = ctx->signr; -+ -+ ctx->siginfo = NULL; -+ ctx->signr = 0; -+ -+ /* Did the debugger cancel the sig? */ -+ if (!signr) -+ return UTRACE_SIGNAL_IGN; -+ /* -+ * Update the siginfo structure if the signal has changed. -+ * If the debugger wanted something specific in the siginfo -+ * then it should have updated *info via PTRACE_SETSIGINFO. -+ */ -+ if (info->si_signo != signr) { -+ info->si_signo = signr; -+ info->si_errno = 0; -+ info->si_code = SI_USER; -+ info->si_pid = task_pid_vnr(current->parent); -+ info->si_uid = task_uid(current->parent); -+ } -+ -+ /* If the (new) signal is now blocked, requeue it. */ -+ if (sigismember(¤t->blocked, signr)) { -+ send_sig_info(signr, info, current); -+ return UTRACE_SIGNAL_IGN; -+ } -+ -+ spin_lock_irq(¤t->sighand->siglock); -+ *return_ka = current->sighand->action[signr - 1]; -+ spin_unlock_irq(¤t->sighand->siglock); -+ -+ return UTRACE_SIGNAL_DELIVER; -+} -+ -+static u32 ptrace_report_signal(u32 action, struct utrace_engine *engine, -+ struct pt_regs *regs, -+ siginfo_t *info, -+ const struct k_sigaction *orig_ka, -+ struct k_sigaction *return_ka) -+{ -+ struct ptrace_context *ctx = ptrace_context(engine); -+ enum utrace_resume_action resume = ctx->resume; -+ -+ if (ptrace_event_pending(ctx)) { -+ action = utrace_signal_action(action); -+ WARN_ON(action != UTRACE_SIGNAL_REPORT); -+ return action | UTRACE_STOP; -+ } -+ -+ switch (utrace_signal_action(action)) { -+ case UTRACE_SIGNAL_HANDLER: -+ if (WARN_ON(ctx->siginfo)) -+ ctx->siginfo = NULL; -+ -+ if (is_step_resume(resume)) { -+ set_stop_code(ctx, PTRACE_EVENT_SIGTRAP); -+ return UTRACE_STOP | UTRACE_SIGNAL_IGN; -+ } -+ -+ case UTRACE_SIGNAL_REPORT: -+ if (!ctx->siginfo) { -+ if (ctx->signr) { -+ /* set by ptrace_resume(SYSCALL_EXIT) */ -+ WARN_ON(ctx->signr != SIGTRAP); -+ user_single_step_siginfo(current, regs, info); -+ force_sig_info(SIGTRAP, info, current); -+ } -+ -+ return resume | UTRACE_SIGNAL_IGN; -+ } -+ -+ if (WARN_ON(ctx->siginfo != info)) -+ return resume | UTRACE_SIGNAL_IGN; -+ -+ return resume | resume_signal(ctx, return_ka); -+ -+ default: -+ break; -+ } -+ -+ WARN_ON(ctx->siginfo); -+ -+ /* Raced with the exiting tracer ? */ -+ if (resume == UTRACE_DETACH) -+ return action; -+ -+ ctx->siginfo = info; -+ /* -+ * ctx->siginfo points to the caller's stack. -+ * Make sure the subsequent UTRACE_SIGNAL_REPORT clears -+ * ->siginfo before return from get_signal_to_deliver(). -+ */ -+ if (utrace_control(current, engine, UTRACE_INTERRUPT)) -+ WARN_ON(1); -+ -+ ctx->signr = info->si_signo; -+ ctx->stop_code = (PTRACE_EVENT_SIGNAL << 8) | ctx->signr; -+ -+ return UTRACE_STOP | UTRACE_SIGNAL_IGN; -+} -+ -+static u32 ptrace_report_quiesce(u32 action, struct utrace_engine *engine, -+ unsigned long event) -+{ -+ struct ptrace_context *ctx = ptrace_context(engine); -+ -+ if (ptrace_event_pending(ctx)) -+ return UTRACE_STOP; -+ -+ return event ? UTRACE_RESUME : ctx->resume; -+} -+ -+static void ptrace_release(void *data) -+{ -+ kfree(data); -+} -+ -+static const struct utrace_engine_ops ptrace_utrace_ops = { -+ .report_signal = ptrace_report_signal, -+ .report_quiesce = ptrace_report_quiesce, -+ .report_exec = ptrace_report_exec, -+ .report_exit = ptrace_report_exit, -+ .report_clone = ptrace_report_clone, -+ .report_syscall_entry = ptrace_report_syscall_entry, -+ .report_syscall_exit = ptrace_report_syscall_exit, -+ .release = ptrace_release, -+}; -+ -+int ptrace_check_attach(struct task_struct *child, int kill) -+{ -+ struct utrace_engine *engine; -+ struct utrace_examiner exam; -+ int ret = -ESRCH; -+ -+ engine = ptrace_lookup_engine(child); -+ if (IS_ERR(engine)) -+ return ret; -+ -+ if (child->parent != current) -+ goto out; -+ -+ if (unlikely(kill)) -+ ret = 0; -+ -+ if (!task_is_stopped_or_traced(child)) -+ goto out; -+ /* -+ * Make sure our engine has already stopped the child. -+ * Then wait for it to be off the CPU. -+ */ -+ if (!utrace_control(child, engine, UTRACE_STOP) && -+ !utrace_prepare_examine(child, engine, &exam)) -+ ret = 0; -+out: -+ utrace_engine_put(engine); -+ return ret; -+} -+ -+int ptrace_attach(struct task_struct *task) -+{ -+ int retval; -+ -+ audit_ptrace(task); -+ -+ retval = -EPERM; -+ if (unlikely(task->flags & PF_KTHREAD)) -+ goto out; -+ if (same_thread_group(task, current)) -+ goto out; -+ -+ /* -+ * Protect exec's credential calculations against our interference; -+ * interference; SUID, SGID and LSM creds get determined differently -+ * under ptrace. -+ */ -+ retval = -ERESTARTNOINTR; -+ if (mutex_lock_interruptible(&task->signal->cred_guard_mutex)) -+ goto out; -+ -+ task_lock(task); -+ retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); -+ task_unlock(task); -+ if (retval) -+ goto unlock_creds; -+ -+ retval = ptrace_attach_task(task, 0); -+ if (unlikely(retval)) -+ goto unlock_creds; -+ -+ write_lock_irq(&tasklist_lock); -+ retval = -EPERM; -+ if (unlikely(task->exit_state)) -+ goto unlock_tasklist; -+ -+ BUG_ON(task->ptrace); -+ task->ptrace = PT_UTRACED; -+ if (capable(CAP_SYS_PTRACE)) -+ task->ptrace |= PT_PTRACE_CAP; -+ -+ __ptrace_link(task, current); -+ send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); -+ -+ retval = 0; -+unlock_tasklist: -+ write_unlock_irq(&tasklist_lock); -+unlock_creds: -+ mutex_unlock(&task->signal->cred_guard_mutex); -+out: -+ return retval; -+} -+ -+/* -+ * Performs checks and sets PT_UTRACED. -+ * Should be used by all ptrace implementations for PTRACE_TRACEME. -+ */ -+int ptrace_traceme(void) -+{ -+ bool detach = true; -+ int ret = ptrace_attach_task(current, 0); -+ -+ if (unlikely(ret)) -+ return ret; -+ -+ ret = -EPERM; -+ write_lock_irq(&tasklist_lock); -+ BUG_ON(current->ptrace); -+ ret = security_ptrace_traceme(current->parent); -+ /* -+ * Check PF_EXITING to ensure ->real_parent has not passed -+ * exit_ptrace(). Otherwise we don't report the error but -+ * pretend ->real_parent untraces us right after return. -+ */ -+ if (!ret && !(current->real_parent->flags & PF_EXITING)) { -+ current->ptrace = PT_UTRACED; -+ __ptrace_link(current, current->real_parent); -+ detach = false; -+ } -+ write_unlock_irq(&tasklist_lock); -+ -+ if (detach) -+ ptrace_abort_attach(current); -+ return ret; -+} -+ -+static void ptrace_do_detach(struct task_struct *tracee, unsigned int data) -+{ -+ bool detach, release; -+ -+ write_lock_irq(&tasklist_lock); -+ /* -+ * This tracee can be already killed. Make sure de_thread() or -+ * our sub-thread doing do_wait() didn't do release_task() yet. -+ */ -+ detach = tracee->ptrace != 0; -+ release = false; -+ if (likely(detach)) -+ release = __ptrace_detach(current, tracee); -+ write_unlock_irq(&tasklist_lock); -+ -+ if (unlikely(release)) -+ release_task(tracee); -+ else if (likely(detach)) -+ ptrace_detach_task(tracee, data); -+} -+ -+int ptrace_detach(struct task_struct *child, unsigned int data) -+{ -+ if (!valid_signal(data)) -+ return -EIO; -+ -+ ptrace_do_detach(child, data); -+ -+ return 0; -+} -+ -+/* -+ * Detach all tasks we were using ptrace on. Called with tasklist held -+ * for writing, and returns with it held too. But note it can release -+ * and reacquire the lock. -+ */ -+void exit_ptrace(struct task_struct *tracer) -+{ -+ bool locked = true; -+ -+ for (;;) { -+ struct task_struct *tracee = NULL; -+ -+ if (!locked) -+ read_lock(&tasklist_lock); -+ if (!list_empty(&tracer->ptraced)) { -+ tracee = list_first_entry(&tracer->ptraced, -+ struct task_struct, ptrace_entry); -+ get_task_struct(tracee); -+ } -+ if (!locked) -+ read_unlock(&tasklist_lock); -+ if (!tracee) -+ break; -+ -+ if (locked) { -+ write_unlock_irq(&tasklist_lock); -+ locked = false; -+ } -+ ptrace_do_detach(tracee, -1); -+ put_task_struct(tracee); -+ } -+ -+ if (!locked) -+ write_lock_irq(&tasklist_lock); -+} -+ -+static int ptrace_set_options(struct task_struct *tracee, -+ struct utrace_engine *engine, long data) -+{ -+ BUILD_BUG_ON(PTRACE_O_MASK & (PTRACE_O_SYSEMU | PTRACE_O_DETACHED)); -+ -+ ptrace_set_events(tracee, engine, data & PTRACE_O_MASK); -+ return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; -+} -+ -+static int ptrace_rw_siginfo(struct task_struct *tracee, -+ struct ptrace_context *ctx, -+ siginfo_t *info, bool write) -+{ -+ unsigned long flags; -+ int err; -+ -+ switch (get_stop_event(ctx)) { -+ case 0: /* jctl stop */ -+ return -EINVAL; -+ -+ case PTRACE_EVENT_SIGNAL: -+ err = -ESRCH; -+ if (lock_task_sighand(tracee, &flags)) { -+ if (likely(task_is_traced(tracee))) { -+ if (write) -+ *ctx->siginfo = *info; -+ else -+ *info = *ctx->siginfo; -+ err = 0; -+ } -+ unlock_task_sighand(tracee, &flags); -+ } -+ -+ return err; -+ -+ default: -+ if (!write) { -+ memset(info, 0, sizeof(*info)); -+ info->si_signo = SIGTRAP; -+ info->si_code = ctx->stop_code & PTRACE_EVENT_MASK; -+ info->si_pid = task_pid_vnr(tracee); -+ info->si_uid = task_uid(tracee); -+ } -+ -+ return 0; -+ } -+} -+ -+static void do_ptrace_notify_stop(struct ptrace_context *ctx, -+ struct task_struct *tracee) -+{ -+ /* -+ * This can race with SIGKILL, but we borrow this race from -+ * the old ptrace implementation. ->exit_code is only needed -+ * for wait_task_stopped()->task_stopped_code(), we should -+ * change it to use ptrace_context. -+ */ -+ tracee->exit_code = ctx->stop_code & PTRACE_EVENT_MASK; -+ WARN_ON(!tracee->exit_code); -+ -+ read_lock(&tasklist_lock); -+ /* -+ * Don't want to allow preemption here, because -+ * sys_ptrace() needs this task to be inactive. -+ */ -+ preempt_disable(); -+ /* -+ * It can be killed and then released by our subthread, -+ * or ptrace_attach() has not completed yet. -+ */ -+ if (task_ptrace(tracee)) -+ do_notify_parent_cldstop(tracee, CLD_TRAPPED); -+ read_unlock(&tasklist_lock); -+ preempt_enable_no_resched(); -+} -+ -+void ptrace_notify_stop(struct task_struct *tracee) -+{ -+ struct utrace_engine *engine = ptrace_lookup_engine(tracee); -+ -+ if (IS_ERR(engine)) -+ return; -+ -+ do_ptrace_notify_stop(ptrace_context(engine), tracee); -+ utrace_engine_put(engine); -+} -+ -+static int ptrace_resume_action(struct task_struct *tracee, -+ struct utrace_engine *engine, long request) -+{ -+ struct ptrace_context *ctx = ptrace_context(engine); -+ unsigned long events; -+ int action; -+ -+ ctx->options &= ~PTRACE_O_SYSEMU; -+ events = engine->flags & ~UTRACE_EVENT_SYSCALL; -+ action = UTRACE_RESUME; -+ -+ switch (request) { -+#ifdef PTRACE_SINGLEBLOCK -+ case PTRACE_SINGLEBLOCK: -+ if (unlikely(!arch_has_block_step())) -+ return -EIO; -+ action = UTRACE_BLOCKSTEP; -+ events |= UTRACE_EVENT(SYSCALL_EXIT); -+ break; -+#endif -+ -+#ifdef PTRACE_SINGLESTEP -+ case PTRACE_SINGLESTEP: -+ if (unlikely(!arch_has_single_step())) -+ return -EIO; -+ action = UTRACE_SINGLESTEP; -+ events |= UTRACE_EVENT(SYSCALL_EXIT); -+ break; -+#endif -+ -+#ifdef PTRACE_SYSEMU -+ case PTRACE_SYSEMU_SINGLESTEP: -+ if (unlikely(!arch_has_single_step())) -+ return -EIO; -+ action = UTRACE_SINGLESTEP; -+ case PTRACE_SYSEMU: -+ ctx->options |= PTRACE_O_SYSEMU; -+ events |= UTRACE_EVENT(SYSCALL_ENTRY); -+ break; -+#endif -+ -+ case PTRACE_SYSCALL: -+ events |= UTRACE_EVENT_SYSCALL; -+ break; -+ -+ case PTRACE_CONT: -+ break; -+ default: -+ return -EIO; -+ } -+ -+ if (events != engine->flags && -+ utrace_set_events(tracee, engine, events)) -+ return -ESRCH; -+ -+ return action; -+} -+ -+static int ptrace_resume(struct task_struct *tracee, -+ struct utrace_engine *engine, -+ long request, long data) -+{ -+ struct ptrace_context *ctx = ptrace_context(engine); -+ int action; -+ -+ if (!valid_signal(data)) -+ return -EIO; -+ -+ action = ptrace_resume_action(tracee, engine, request); -+ if (action < 0) -+ return action; -+ -+ switch (get_stop_event(ctx)) { -+ case PTRACE_EVENT_VFORK: -+ if (ctx->options & PTRACE_O_TRACEVFORKDONE) { -+ set_stop_code(ctx, PTRACE_EVENT_VFORK_DONE); -+ action = UTRACE_REPORT; -+ } -+ break; -+ -+ case PTRACE_EVENT_EXEC: -+ case PTRACE_EVENT_FORK: -+ case PTRACE_EVENT_CLONE: -+ case PTRACE_EVENT_VFORK_DONE: -+ if (request == PTRACE_SYSCALL) { -+ set_syscall_code(ctx); -+ do_ptrace_notify_stop(ctx, tracee); -+ return 0; -+ } -+ -+ if (action != UTRACE_RESUME) { -+ /* -+ * single-stepping. UTRACE_SIGNAL_REPORT will -+ * synthesize a trap to follow the syscall insn. -+ */ -+ ctx->signr = SIGTRAP; -+ action = UTRACE_INTERRUPT; -+ } -+ break; -+ -+ case PTRACE_EVENT_SYSCALL: -+ if (data) -+ send_sig_info(data, SEND_SIG_PRIV, tracee); -+ break; -+ -+ case PTRACE_EVENT_SIGNAL: -+ ctx->signr = data; -+ break; -+ } -+ -+ ctx->resume = action; -+ ptrace_wake_up(tracee, engine, action, true); -+ return 0; -+} -+ -+extern int ptrace_regset(struct task_struct *task, int req, unsigned int type, -+ struct iovec *kiov); -+ -+int ptrace_request(struct task_struct *child, long request, -+ unsigned long addr, unsigned long data) -+{ -+ struct utrace_engine *engine = ptrace_lookup_engine(child); -+ siginfo_t siginfo; -+ int ret; -+ -+ if (unlikely(IS_ERR(engine))) -+ return -ESRCH; -+ -+ switch (request) { -+ case PTRACE_PEEKTEXT: -+ case PTRACE_PEEKDATA: -+ ret = generic_ptrace_peekdata(child, addr, data); -+ break; -+ case PTRACE_POKETEXT: -+ case PTRACE_POKEDATA: -+ ret = generic_ptrace_pokedata(child, addr, data); -+ break; -+ -+#ifdef PTRACE_OLDSETOPTIONS -+ case PTRACE_OLDSETOPTIONS: -+#endif -+ case PTRACE_SETOPTIONS: -+ ret = ptrace_set_options(child, engine, data); -+ break; -+ case PTRACE_GETEVENTMSG: -+ ret = put_user(ptrace_context(engine)->eventmsg, -+ (unsigned long __user *) data); -+ break; -+ -+ case PTRACE_GETSIGINFO: -+ ret = ptrace_rw_siginfo(child, ptrace_context(engine), -+ &siginfo, false); -+ if (!ret) -+ ret = copy_siginfo_to_user((siginfo_t __user *) data, -+ &siginfo); -+ break; -+ -+ case PTRACE_SETSIGINFO: -+ if (copy_from_user(&siginfo, (siginfo_t __user *) data, -+ sizeof siginfo)) -+ ret = -EFAULT; -+ else -+ ret = ptrace_rw_siginfo(child, ptrace_context(engine), -+ &siginfo, true); -+ break; -+ -+ case PTRACE_DETACH: /* detach a process that was attached. */ -+ ret = ptrace_detach(child, data); -+ break; -+ -+ case PTRACE_KILL: -+ /* Ugly historical behaviour. */ -+ if (task_is_traced(child)) -+ ptrace_resume(child, engine, PTRACE_CONT, SIGKILL); -+ ret = 0; -+ break; -+ -+ case PTRACE_GETREGSET: -+ case PTRACE_SETREGSET: -+ { -+ struct iovec kiov; -+ struct iovec __user *uiov = (struct iovec __user *) data; -+ -+ if (!access_ok(VERIFY_WRITE, uiov, sizeof(*uiov))) -+ return -EFAULT; -+ -+ if (__get_user(kiov.iov_base, &uiov->iov_base) || -+ __get_user(kiov.iov_len, &uiov->iov_len)) -+ return -EFAULT; -+ -+ ret = ptrace_regset(child, request, addr, &kiov); -+ if (!ret) -+ ret = __put_user(kiov.iov_len, &uiov->iov_len); -+ break; -+ } -+ -+ default: -+ ret = ptrace_resume(child, engine, request, data); -+ break; -+ } -+ -+ utrace_engine_put(engine); -+ return ret; -+} -+ -+#if defined CONFIG_COMPAT -+#include -+ -+int compat_ptrace_request(struct task_struct *child, compat_long_t request, -+ compat_ulong_t addr, compat_ulong_t data) -+{ -+ struct utrace_engine *engine = ptrace_lookup_engine(child); -+ compat_ulong_t __user *datap = compat_ptr(data); -+ compat_ulong_t word; -+ siginfo_t siginfo; -+ int ret; -+ -+ if (unlikely(IS_ERR(engine))) -+ return -ESRCH; -+ -+ switch (request) { -+ case PTRACE_PEEKTEXT: -+ case PTRACE_PEEKDATA: -+ ret = access_process_vm(child, addr, &word, sizeof(word), 0); -+ if (ret != sizeof(word)) -+ ret = -EIO; -+ else -+ ret = put_user(word, datap); -+ break; -+ -+ case PTRACE_POKETEXT: -+ case PTRACE_POKEDATA: -+ ret = access_process_vm(child, addr, &data, sizeof(data), 1); -+ ret = (ret != sizeof(data) ? -EIO : 0); -+ break; -+ -+ case PTRACE_GETEVENTMSG: -+ ret = put_user((compat_ulong_t)ptrace_context(engine)->eventmsg, -+ datap); -+ break; -+ -+ case PTRACE_GETSIGINFO: -+ ret = ptrace_rw_siginfo(child, ptrace_context(engine), -+ &siginfo, false); -+ if (!ret) -+ ret = copy_siginfo_to_user32( -+ (struct compat_siginfo __user *) datap, -+ &siginfo); -+ break; -+ -+ case PTRACE_SETSIGINFO: -+ memset(&siginfo, 0, sizeof siginfo); -+ if (copy_siginfo_from_user32( -+ &siginfo, (struct compat_siginfo __user *) datap)) -+ ret = -EFAULT; -+ else -+ ret = ptrace_rw_siginfo(child, ptrace_context(engine), -+ &siginfo, true); -+ break; -+ -+ case PTRACE_GETREGSET: -+ case PTRACE_SETREGSET: -+ { -+ struct iovec kiov; -+ struct compat_iovec __user *uiov = -+ (struct compat_iovec __user *) datap; -+ compat_uptr_t ptr; -+ compat_size_t len; -+ -+ if (!access_ok(VERIFY_WRITE, uiov, sizeof(*uiov))) -+ return -EFAULT; -+ -+ if (__get_user(ptr, &uiov->iov_base) || -+ __get_user(len, &uiov->iov_len)) -+ return -EFAULT; -+ -+ kiov.iov_base = compat_ptr(ptr); -+ kiov.iov_len = len; -+ -+ ret = ptrace_regset(child, request, addr, &kiov); -+ if (!ret) -+ ret = __put_user(kiov.iov_len, &uiov->iov_len); -+ break; -+ } -+ -+ default: -+ ret = ptrace_request(child, request, addr, data); -+ } -+ -+ utrace_engine_put(engine); -+ return ret; -+} -+#endif /* CONFIG_COMPAT */ -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index e275608..72ea65c 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -15,7 +15,6 @@ - #include - #include - #include --#include - #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); - retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); -- if (!retval && exclude_ptrace(task)) -- retval = -EBUSY; - task_unlock(task); - if (retval) - goto unlock_creds; -@@ -220,91 +475,37 @@ unlock_tasklist: - write_unlock_irq(&tasklist_lock); - unlock_creds: - mutex_unlock(&task->signal->cred_guard_mutex); --out: -- return retval; --} -- --/** -- * ptrace_traceme -- helper for PTRACE_TRACEME -- * -- * Performs checks and sets PT_PTRACED. -- * Should be used by all ptrace implementations for PTRACE_TRACEME. -- */ --int ptrace_traceme(void) --{ -- int ret = -EPERM; -- -- if (exclude_ptrace(current)) /* XXX locking */ -- return -EBUSY; -- -- write_lock_irq(&tasklist_lock); -- /* Are we already being traced? */ -- if (!current->ptrace) { -- ret = security_ptrace_traceme(current->parent); -- /* -- * Check PF_EXITING to ensure ->real_parent has not passed -- * exit_ptrace(). Otherwise we don't report the error but -- * pretend ->real_parent untraces us right after return. -- */ -- if (!ret && !(current->real_parent->flags & PF_EXITING)) { -- current->ptrace = PT_PTRACED; -- __ptrace_link(current, current->real_parent); -- } -- } -- write_unlock_irq(&tasklist_lock); -- -- return ret; --} -- --/* -- * 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. -+out: -+ return retval; -+} -+ -+/** -+ * ptrace_traceme -- helper for PTRACE_TRACEME - * -- * 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(). -+ * Performs checks and sets PT_PTRACED. -+ * Should be used by all ptrace implementations for PTRACE_TRACEME. - */ --bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) -+int ptrace_traceme(void) - { -- __ptrace_unlink(p); -+ int ret = -EPERM; - -- 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; -+ write_lock_irq(&tasklist_lock); -+ /* Are we already being traced? */ -+ if (!current->ptrace) { -+ ret = security_ptrace_traceme(current->parent); -+ /* -+ * Check PF_EXITING to ensure ->real_parent has not passed -+ * exit_ptrace(). Otherwise we don't report the error but -+ * pretend ->real_parent untraces us right after return. -+ */ -+ if (!ret && !(current->real_parent->flags & PF_EXITING)) { -+ current->ptrace = PT_PTRACED; -+ __ptrace_link(current, current->real_parent); - } - } -+ write_unlock_irq(&tasklist_lock); - -- return false; -+ return ret; - } - - int ptrace_detach(struct task_struct *child, unsigned int data) -@@ -368,57 +569,7 @@ void exit_ptrace(struct task_struct *tra - write_lock_irq(&tasklist_lock); - } - --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; --} -- --static int ptrace_setoptions(struct task_struct *child, unsigned long data) -+static int ptrace_setoptions(struct task_struct *child, long data) - { - child->ptrace &= ~PT_TRACE_MASK; - -@@ -533,47 +683,6 @@ static int ptrace_resume(struct task_str - return 0; - } - --#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; --} -- --static 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 -- - int ptrace_request(struct task_struct *child, long request, - unsigned long addr, unsigned long data) - { -@@ -689,91 +798,7 @@ int ptrace_request(struct task_struct *c - return ret; - } - --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 -- - 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 - - return ret; - } -- --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 */ -+#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 -+++ b/kernel/utrace.c -@@ -816,6 +816,22 @@ relock: - spin_unlock_irq(&task->sighand->siglock); - spin_unlock(&utrace->lock); - -+ /* -+ * If ptrace is among the reasons for this stop, do its -+ * notification now. This could not just be done in -+ * ptrace's own event report callbacks because it has to -+ * be done after we are in TASK_TRACED. This makes the -+ * synchronization with ptrace_do_wait() work right. -+ * -+ * It's only because of the bad old overloading of the do_wait() -+ * logic for handling ptrace stops that we need this special case -+ * here. One day we will clean up ptrace so it does not need to -+ * work this way. New things that are designed sensibly don't need -+ * a wakeup that synchronizes with tasklist_lock and ->state, so -+ * the proper utrace API does not try to support this weirdness. -+ */ -+ ptrace_notify_stop(task); -+ - schedule(); - - utrace_finish_stop(); diff --git a/linux-2.6-utrace-revert-make-ptrace-functions-static.patch b/linux-2.6-utrace-revert-make-ptrace-functions-static.patch deleted file mode 100644 index 5e3dcc21d..000000000 --- a/linux-2.6-utrace-revert-make-ptrace-functions-static.patch +++ /dev/null @@ -1,47 +0,0 @@ -Revert: -commit e3e89cc535223433a619d0969db3fa05cdd946b8 -("Mark ptrace_{traceme,attach,detach} static") - ---- b/include/linux/ptrace.h -+++ a/include/linux/ptrace.h -@@ -102,8 +102,11 @@ - - extern long arch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data); -+extern int ptrace_traceme(void); - extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); - extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); -+extern int ptrace_attach(struct task_struct *tsk); -+extern int ptrace_detach(struct task_struct *, unsigned int); - extern void ptrace_disable(struct task_struct *); - extern int ptrace_check_attach(struct task_struct *task, int kill); - extern int ptrace_request(struct task_struct *child, long request, ---- b/kernel/ptrace.c -+++ a/kernel/ptrace.c -@@ -163,7 +163,7 @@ - return !err; - } - -+int ptrace_attach(struct task_struct *task) --static int ptrace_attach(struct task_struct *task) - { - int retval; - -@@ -219,7 +219,7 @@ - * Performs checks and sets PT_PTRACED. - * Should be used by all ptrace implementations for PTRACE_TRACEME. - */ -+int ptrace_traceme(void) --static int ptrace_traceme(void) - { - int ret = -EPERM; - -@@ -293,7 +293,7 @@ - return false; - } - -+int ptrace_detach(struct task_struct *child, unsigned int data) --static int ptrace_detach(struct task_struct *child, unsigned int data) - { - bool dead = false; - diff --git a/linux-2.6-utrace.patch b/linux-2.6-utrace.patch deleted file mode 100644 index 366b8a176..000000000 --- a/linux-2.6-utrace.patch +++ /dev/null @@ -1,4166 +0,0 @@ -utrace core - -This adds the utrace facility, a new modular interface in the kernel for -implementing user thread tracing and debugging. This fits on top of the -tracehook_* layer, so the new code is well-isolated. - -The new interface is in and the DocBook utrace book -describes it. It allows for multiple separate tracing engines to work in -parallel without interfering with each other. Higher-level tracing -facilities can be implemented as loadable kernel modules using this layer. - -The new facility is made optional under CONFIG_UTRACE. -When this is not enabled, no new code is added. -It can only be enabled on machines that have all the -prerequisites and select CONFIG_HAVE_ARCH_TRACEHOOK. - -In this initial version, utrace and ptrace do not play together at all. -If ptrace is attached to a thread, the attach calls in the utrace kernel -API return -EBUSY. If utrace is attached to a thread, the PTRACE_ATTACH -or PTRACE_TRACEME request will return EBUSY to userland. The old ptrace -code is otherwise unchanged and nothing using ptrace should be affected -by this patch as long as utrace is not used at the same time. In the -future we can clean up the ptrace implementation and rework it to use -the utrace API. - -Signed-off-by: Roland McGrath ---- - Documentation/DocBook/Makefile | 2 +- - Documentation/DocBook/utrace.tmpl | 589 +++++++++ - fs/proc/array.c | 3 + - include/linux/sched.h | 5 + - include/linux/tracehook.h | 87 ++- - include/linux/utrace.h | 692 +++++++++++ - init/Kconfig | 9 + - kernel/Makefile | 1 + - kernel/fork.c | 3 + - kernel/ptrace.c | 14 + - kernel/utrace.c | 2440 +++++++++++++++++++++++++++++++++++++ - 11 files changed, 3843 insertions(+), 2 deletions(-) - -diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile -index 8b6e00a..2740633 100644 ---- a/Documentation/DocBook/Makefile -+++ b/Documentation/DocBook/Makefile -@@ -14,7 +14,7 @@ DOCBOOKS := z8530book.xml mcabook.xml de - genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ - 80211.xml debugobjects.xml sh.xml regulator.xml \ - alsa-driver-api.xml writing-an-alsa-driver.xml \ -- tracepoint.xml media.xml drm.xml -+ tracepoint.xml utrace.xml media.xml drm.xml - - ### - # The build process is as follows (targets): -diff --git a/Documentation/DocBook/utrace.tmpl b/Documentation/DocBook/utrace.tmpl -new file mode 100644 -index ...0c40add 100644 ---- /dev/null -+++ b/Documentation/DocBook/utrace.tmpl -@@ -0,0 +1,589 @@ -+ -+ -+ -+ -+ -+ The utrace User Debugging Infrastructure -+ -+ -+ -+ -+ utrace concepts -+ -+ Introduction -+ -+ -+ utrace is infrastructure code for tracing -+ and controlling user threads. This is the foundation for writing -+ tracing engines, which can be loadable kernel modules. -+ -+ -+ -+ The basic actors in utrace are the thread -+ and the tracing engine. A tracing engine is some body of code that -+ calls into the <linux/utrace.h> -+ interfaces, represented by a struct -+ utrace_engine_ops. (Usually it's a kernel module, -+ though the legacy ptrace support is a tracing -+ engine that is not in a kernel module.) The interface operates on -+ individual threads (struct task_struct). -+ If an engine wants to treat several threads as a group, that is up -+ to its higher-level code. -+ -+ -+ -+ Tracing begins by attaching an engine to a thread, using -+ utrace_attach_task or -+ utrace_attach_pid. If successful, it returns a -+ pointer that is the handle used in all other calls. -+ -+ -+ -+ -+ Events and Callbacks -+ -+ -+ An attached engine does nothing by default. An engine makes something -+ happen by requesting callbacks via utrace_set_events -+ and poking the thread with utrace_control. -+ The synchronization issues related to these two calls -+ are discussed further below in . -+ -+ -+ -+ Events are specified using the macro -+ UTRACE_EVENT(type). -+ Each event type is associated with a callback in struct -+ utrace_engine_ops. A tracing engine can leave unused -+ callbacks NULL. The only callbacks required -+ are those used by the event flags it sets. -+ -+ -+ -+ Many engines can be attached to each thread. When a thread has an -+ event, each engine gets a callback if it has set the event flag for -+ that event type. For most events, engines are called in the order they -+ attached. Engines that attach after the event has occurred do not get -+ callbacks for that event. This includes any new engines just attached -+ by an existing engine's callback function. Once the sequence of -+ callbacks for that one event has completed, such new engines are then -+ eligible in the next sequence that starts when there is another event. -+ -+ -+ -+ Event reporting callbacks have details particular to the event type, -+ but are all called in similar environments and have the same -+ constraints. Callbacks are made from safe points, where no locks -+ are held, no special resources are pinned (usually), and the -+ user-mode state of the thread is accessible. So, callback code has -+ a pretty free hand. But to be a good citizen, callback code should -+ never block for long periods. It is fine to block in -+ kmalloc and the like, but never wait for i/o or -+ for user mode to do something. If you need the thread to wait, use -+ UTRACE_STOP and return from the callback -+ quickly. When your i/o finishes or whatever, you can use -+ utrace_control to resume the thread. -+ -+ -+ -+ The UTRACE_EVENT(SYSCALL_ENTRY) event is a special -+ case. While other events happen in the kernel when it will return to -+ user mode soon, this event happens when entering the kernel before it -+ will proceed with the work requested from user mode. Because of this -+ difference, the report_syscall_entry callback is -+ special in two ways. For this event, engines are called in reverse of -+ the normal order (this includes the report_quiesce -+ call that precedes a report_syscall_entry call). -+ This preserves the semantics that the last engine to attach is called -+ "closest to user mode"--the engine that is first to see a thread's user -+ state when it enters the kernel is also the last to see that state when -+ the thread returns to user mode. For the same reason, if these -+ callbacks use UTRACE_STOP (see the next section), -+ the thread stops immediately after callbacks rather than only when it's -+ ready to return to user mode; when allowed to resume, it will actually -+ attempt the system call indicated by the register values at that time. -+ -+ -+ -+ -+ Stopping Safely -+ -+ Writing well-behaved callbacks -+ -+ -+ Well-behaved callbacks are important to maintain two essential -+ properties of the interface. The first of these is that unrelated -+ tracing engines should not interfere with each other. If your engine's -+ event callback does not return quickly, then another engine won't get -+ the event notification in a timely manner. The second important -+ property is that tracing should be as noninvasive as possible to the -+ normal operation of the system overall and of the traced thread in -+ particular. That is, attached tracing engines should not perturb a -+ thread's behavior, except to the extent that changing its user-visible -+ state is explicitly what you want to do. (Obviously some perturbation -+ is unavoidable, primarily timing changes, ranging from small delays due -+ to the overhead of tracing, to arbitrary pauses in user code execution -+ when a user stops a thread with a debugger for examination.) Even when -+ you explicitly want the perturbation of making the traced thread block, -+ just blocking directly in your callback has more unwanted effects. For -+ example, the CLONE event callbacks are called when -+ the new child thread has been created but not yet started running; the -+ child can never be scheduled until the CLONE -+ tracing callbacks return. (This allows engines tracing the parent to -+ attach to the child.) If a CLONE event callback -+ blocks the parent thread, it also prevents the child thread from -+ running (even to process a SIGKILL). If what you -+ want is to make both the parent and child block, then use -+ utrace_attach_task on the child and then use -+ UTRACE_STOP on both threads. A more crucial -+ problem with blocking in callbacks is that it can prevent -+ SIGKILL from working. A thread that is blocking -+ due to UTRACE_STOP will still wake up and die -+ immediately when sent a SIGKILL, as all threads -+ should. Relying on the utrace -+ infrastructure rather than on private synchronization calls in event -+ callbacks is an important way to help keep tracing robustly -+ noninvasive. -+ -+ -+ -+ -+ Using <constant>UTRACE_STOP</constant> -+ -+ -+ To control another thread and access its state, it must be stopped -+ with UTRACE_STOP. This means that it is -+ stopped and won't start running again while we access it. When a -+ thread is not already stopped, utrace_control -+ returns -EINPROGRESS and an engine must wait -+ for an event callback when the thread is ready to stop. The thread -+ may be running on another CPU or may be blocked. When it is ready -+ to be examined, it will make callbacks to engines that set the -+ UTRACE_EVENT(QUIESCE) event bit. To wake up an -+ interruptible wait, use UTRACE_INTERRUPT. -+ -+ -+ -+ As long as some engine has used UTRACE_STOP and -+ not called utrace_control to resume the thread, -+ then the thread will remain stopped. SIGKILL -+ will wake it up, but it will not run user code. When the stop is -+ cleared with utrace_control or a callback -+ return value, the thread starts running again. -+ (See also .) -+ -+ -+ -+ -+ -+ -+ Tear-down Races -+ -+ Primacy of <constant>SIGKILL</constant> -+ -+ Ordinarily synchronization issues for tracing engines are kept fairly -+ straightforward by using UTRACE_STOP. You ask a -+ thread to stop, and then once it makes the -+ report_quiesce callback it cannot do anything else -+ that would result in another callback, until you let it with a -+ utrace_control call. This simple arrangement -+ avoids complex and error-prone code in each one of a tracing engine's -+ event callbacks to keep them serialized with the engine's other -+ operations done on that thread from another thread of control. -+ However, giving tracing engines complete power to keep a traced thread -+ stuck in place runs afoul of a more important kind of simplicity that -+ the kernel overall guarantees: nothing can prevent or delay -+ SIGKILL from making a thread die and release its -+ resources. To preserve this important property of -+ SIGKILL, it as a special case can break -+ UTRACE_STOP like nothing else normally can. This -+ includes both explicit SIGKILL signals and the -+ implicit SIGKILL sent to each other thread in the -+ same thread group by a thread doing an exec, or processing a fatal -+ signal, or making an exit_group system call. A -+ tracing engine can prevent a thread from beginning the exit or exec or -+ dying by signal (other than SIGKILL) if it is -+ attached to that thread, but once the operation begins, no tracing -+ engine can prevent or delay all other threads in the same thread group -+ dying. -+ -+ -+ -+ Final callbacks -+ -+ The report_reap callback is always the final event -+ in the life cycle of a traced thread. Tracing engines can use this as -+ the trigger to clean up their own data structures. The -+ report_death callback is always the penultimate -+ event a tracing engine might see; it's seen unless the thread was -+ already in the midst of dying when the engine attached. Many tracing -+ engines will have no interest in when a parent reaps a dead process, -+ and nothing they want to do with a zombie thread once it dies; for -+ them, the report_death callback is the natural -+ place to clean up data structures and detach. To facilitate writing -+ such engines robustly, given the asynchrony of -+ SIGKILL, and without error-prone manual -+ implementation of synchronization schemes, the -+ utrace infrastructure provides some special -+ guarantees about the report_death and -+ report_reap callbacks. It still takes some care -+ to be sure your tracing engine is robust to tear-down races, but these -+ rules make it reasonably straightforward and concise to handle a lot of -+ corner cases correctly. -+ -+ -+ -+ Engine and task pointers -+ -+ The first sort of guarantee concerns the core data structures -+ themselves. struct utrace_engine is -+ a reference-counted data structure. While you hold a reference, an -+ engine pointer will always stay valid so that you can safely pass it to -+ any utrace call. Each call to -+ utrace_attach_task or -+ utrace_attach_pid returns an engine pointer with a -+ reference belonging to the caller. You own that reference until you -+ drop it using utrace_engine_put. There is an -+ implicit reference on the engine while it is attached. So if you drop -+ your only reference, and then use -+ utrace_attach_task without -+ UTRACE_ATTACH_CREATE to look up that same engine, -+ you will get the same pointer with a new reference to replace the one -+ you dropped, just like calling utrace_engine_get. -+ When an engine has been detached, either explicitly with -+ UTRACE_DETACH or implicitly after -+ report_reap, then any references you hold are all -+ that keep the old engine pointer alive. -+ -+ -+ -+ There is nothing a kernel module can do to keep a struct -+ task_struct alive outside of -+ rcu_read_lock. When the task dies and is reaped -+ by its parent (or itself), that structure can be freed so that any -+ dangling pointers you have stored become invalid. -+ utrace will not prevent this, but it can -+ help you detect it safely. By definition, a task that has been reaped -+ has had all its engines detached. All -+ utrace calls can be safely called on a -+ detached engine if the caller holds a reference on that engine pointer, -+ even if the task pointer passed in the call is invalid. All calls -+ return -ESRCH for a detached engine, which tells -+ you that the task pointer you passed could be invalid now. Since -+ utrace_control and -+ utrace_set_events do not block, you can call those -+ inside a rcu_read_lock section and be sure after -+ they don't return -ESRCH that the task pointer is -+ still valid until rcu_read_unlock. The -+ infrastructure never holds task references of its own. Though neither -+ rcu_read_lock nor any other lock is held while -+ making a callback, it's always guaranteed that the struct -+ task_struct and the struct -+ utrace_engine passed as arguments remain valid -+ until the callback function returns. -+ -+ -+ -+ The common means for safely holding task pointers that is available to -+ kernel modules is to use struct pid, which -+ permits put_pid from kernel modules. When using -+ that, the calls utrace_attach_pid, -+ utrace_control_pid, -+ utrace_set_events_pid, and -+ utrace_barrier_pid are available. -+ -+ -+ -+ -+ -+ Serialization of <constant>DEATH</constant> and <constant>REAP</constant> -+ -+ -+ The second guarantee is the serialization of -+ DEATH and REAP event -+ callbacks for a given thread. The actual reaping by the parent -+ (release_task call) can occur simultaneously -+ while the thread is still doing the final steps of dying, including -+ the report_death callback. If a tracing engine -+ has requested both DEATH and -+ REAP event reports, it's guaranteed that the -+ report_reap callback will not be made until -+ after the report_death callback has returned. -+ If the report_death callback itself detaches -+ from the thread, then the report_reap callback -+ will never be made. Thus it is safe for a -+ report_death callback to clean up data -+ structures and detach. -+ -+ -+ -+ Interlock with final callbacks -+ -+ The final sort of guarantee is that a tracing engine will know for sure -+ whether or not the report_death and/or -+ report_reap callbacks will be made for a certain -+ thread. These tear-down races are disambiguated by the error return -+ values of utrace_set_events and -+ utrace_control. Normally -+ utrace_control called with -+ UTRACE_DETACH returns zero, and this means that no -+ more callbacks will be made. If the thread is in the midst of dying, -+ it returns -EALREADY to indicate that the -+ report_death callback may already be in progress; -+ when you get this error, you know that any cleanup your -+ report_death callback does is about to happen or -+ has just happened--note that if the report_death -+ callback does not detach, the engine remains attached until the thread -+ gets reaped. If the thread is in the midst of being reaped, -+ utrace_control returns -ESRCH -+ to indicate that the report_reap callback may -+ already be in progress; this means the engine is implicitly detached -+ when the callback completes. This makes it possible for a tracing -+ engine that has decided asynchronously to detach from a thread to -+ safely clean up its data structures, knowing that no -+ report_death or report_reap -+ callback will try to do the same. utrace_detach -+ returns -ESRCH when the struct -+ utrace_engine has already been detached, but is -+ still a valid pointer because of its reference count. A tracing engine -+ can use this to safely synchronize its own independent multiple threads -+ of control with each other and with its event callbacks that detach. -+ -+ -+ -+ In the same vein, utrace_set_events normally -+ returns zero; if the target thread was stopped before the call, then -+ after a successful call, no event callbacks not requested in the new -+ flags will be made. It fails with -EALREADY if -+ you try to clear UTRACE_EVENT(DEATH) when the -+ report_death callback may already have begun, or if -+ you try to newly set UTRACE_EVENT(DEATH) or -+ UTRACE_EVENT(QUIESCE) when the target is already -+ dead or dying. Like utrace_control, it returns -+ -ESRCH when the report_reap -+ callback may already have begun, or the thread has already been detached -+ (including forcible detach on reaping). This lets the tracing engine -+ know for sure which event callbacks it will or won't see after -+ utrace_set_events has returned. By checking for -+ errors, it can know whether to clean up its data structures immediately -+ or to let its callbacks do the work. -+ -+ -+ -+ Using <function>utrace_barrier</function> -+ -+ When a thread is safely stopped, calling -+ utrace_control with UTRACE_DETACH -+ or calling utrace_set_events to disable some events -+ ensures synchronously that your engine won't get any more of the callbacks -+ that have been disabled (none at all when detaching). But these can also -+ be used while the thread is not stopped, when it might be simultaneously -+ making a callback to your engine. For this situation, these calls return -+ -EINPROGRESS when it's possible a callback is in -+ progress. If you are not prepared to have your old callbacks still run, -+ then you can synchronize to be sure all the old callbacks are finished, -+ using utrace_barrier. This is necessary if the -+ kernel module containing your callback code is going to be unloaded. -+ -+ -+ After using UTRACE_DETACH once, further calls to -+ utrace_control with the same engine pointer will -+ return -ESRCH. In contrast, after getting -+ -EINPROGRESS from -+ utrace_set_events, you can call -+ utrace_set_events again later and if it returns zero -+ then know the old callbacks have finished. -+ -+ -+ Unlike all other calls, utrace_barrier (and -+ utrace_barrier_pid) will accept any engine pointer you -+ hold a reference on, even if UTRACE_DETACH has already -+ been used. After any utrace_control or -+ utrace_set_events call (these do not block), you can -+ call utrace_barrier to block until callbacks have -+ finished. This returns -ESRCH only if the engine is -+ completely detached (finished all callbacks). Otherwise it waits -+ until the thread is definitely not in the midst of a callback to this -+ engine and then returns zero, but can return -+ -ERESTARTSYS if its wait is interrupted. -+ -+ -+ -+ -+ -+ -+ -+utrace core API -+ -+ -+ The utrace API is declared in <linux/utrace.h>. -+ -+ -+!Iinclude/linux/utrace.h -+!Ekernel/utrace.c -+ -+ -+ -+Machine State -+ -+ -+ The task_current_syscall function can be used on any -+ valid struct task_struct at any time, and does -+ not even require that utrace_attach_task was used at all. -+ -+ -+ -+ The other ways to access the registers and other machine-dependent state of -+ a task can only be used on a task that is at a known safe point. The safe -+ points are all the places where utrace_set_events can -+ request callbacks (except for the DEATH and -+ REAP events). So at any event callback, it is safe to -+ examine current. -+ -+ -+ -+ One task can examine another only after a callback in the target task that -+ returns UTRACE_STOP so that task will not return to user -+ mode after the safe point. This guarantees that the task will not resume -+ until the same engine uses utrace_control, unless the -+ task dies suddenly. To examine safely, one must use a pair of calls to -+ utrace_prepare_examine and -+ utrace_finish_examine surrounding the calls to -+ struct user_regset functions or direct examination -+ of task data structures. utrace_prepare_examine returns -+ an error if the task is not properly stopped, or is dead. After a -+ successful examination, the paired utrace_finish_examine -+ call returns an error if the task ever woke up during the examination. If -+ so, any data gathered may be scrambled and should be discarded. This means -+ there was a spurious wake-up (which should not happen), or a sudden death. -+ -+ -+<structname>struct user_regset</structname> -+ -+ -+ The struct user_regset API -+ is declared in <linux/regset.h>. -+ -+ -+!Finclude/linux/regset.h -+ -+ -+ -+ -+ <filename>System Call Information</filename> -+ -+ -+ This function is declared in <linux/ptrace.h>. -+ -+ -+!Elib/syscall.c -+ -+ -+ -+<filename>System Call Tracing</filename> -+ -+ -+ The arch API for system call information is declared in -+ <asm/syscall.h>. -+ Each of these calls can be used only at system call entry tracing, -+ or can be used only at system call exit and the subsequent safe points -+ before returning to user mode. -+ At system call entry tracing means either during a -+ report_syscall_entry callback, -+ or any time after that callback has returned UTRACE_STOP. -+ -+ -+!Finclude/asm-generic/syscall.h -+ -+ -+ -+ -+ -+Kernel Internals -+ -+ -+ This chapter covers the interface to the tracing infrastructure -+ from the core of the kernel and the architecture-specific code. -+ This is for maintainers of the kernel and arch code, and not relevant -+ to using the tracing facilities described in preceding chapters. -+ -+ -+Core Calls In -+ -+ -+ These calls are declared in <linux/tracehook.h>. -+ The core kernel calls these functions at various important places. -+ -+ -+!Finclude/linux/tracehook.h -+ -+ -+ -+Architecture Calls Out -+ -+ -+ An arch that has done all these things sets -+ CONFIG_HAVE_ARCH_TRACEHOOK. -+ This is required to enable the utrace code. -+ -+ -+<filename><asm/ptrace.h></filename> -+ -+ -+ An arch defines these in <asm/ptrace.h> -+ if it supports hardware single-step or block-step features. -+ -+ -+!Finclude/linux/ptrace.h arch_has_single_step arch_has_block_step -+!Finclude/linux/ptrace.h user_enable_single_step user_enable_block_step -+!Finclude/linux/ptrace.h user_disable_single_step -+ -+ -+ -+ -+ <filename><asm/syscall.h></filename> -+ -+ -+ An arch provides <asm/syscall.h> that -+ defines these as inlines, or declares them as exported functions. -+ These interfaces are described in . -+ -+ -+ -+ -+ -+ <filename><linux/tracehook.h></filename> -+ -+ -+ An arch must define TIF_NOTIFY_RESUME -+ and TIF_SYSCALL_TRACE -+ in its <asm/thread_info.h>. -+ The arch code must call the following functions, all declared -+ in <linux/tracehook.h> and -+ described in : -+ -+ -+ -+ tracehook_notify_resume -+ -+ -+ tracehook_report_syscall_entry -+ -+ -+ tracehook_report_syscall_exit -+ -+ -+ tracehook_signal_handler -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/fs/proc/array.c b/fs/proc/array.c -index fff6572..a67bd83 100644 ---- a/fs/proc/array.c -+++ b/fs/proc/array.c -@@ -81,6 +81,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -192,6 +193,8 @@ static inline void task_state(struct seq - cred->uid, cred->euid, cred->suid, cred->fsuid, - cred->gid, cred->egid, cred->sgid, cred->fsgid); - -+ task_utrace_proc_status(m, p); -+ - task_lock(p); - if (p->files) - fdt = files_fdtable(p->files); -diff --git a/include/linux/sched.h b/include/linux/sched.h -index 09f26df..e6fa5e9 100644 ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -1357,6 +1357,11 @@ struct task_struct { - #endif - seccomp_t seccomp; - -+#ifdef CONFIG_UTRACE -+ struct utrace *utrace; -+ unsigned long utrace_flags; -+#endif -+ - /* Thread group tracking */ - u32 parent_exec_id; - u32 self_exec_id; -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 98917e9..afba8f8 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -49,6 +49,7 @@ - #include - #include - #include -+#include - struct linux_binprm; - - /** -@@ -63,6 +64,8 @@ struct linux_binprm; - */ - static inline int tracehook_expect_breakpoints(struct task_struct *task) - { -+ if (unlikely(task_utrace_flags(task) & UTRACE_EVENT(SIGNAL_CORE))) -+ return 1; - return (task_ptrace(task) & PT_PTRACED) != 0; - } - -@@ -111,6 +114,9 @@ static inline void ptrace_report_syscall - static inline __must_check int tracehook_report_syscall_entry( - struct pt_regs *regs) - { -+ if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && -+ utrace_report_syscall_entry(regs)) -+ return 1; - ptrace_report_syscall(regs); - return 0; - } -@@ -134,6 +140,9 @@ static inline __must_check int tracehook - */ - static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) - { -+ if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) -+ utrace_report_syscall_exit(regs); -+ - if (step && (task_ptrace(current) & PT_PTRACED)) { - siginfo_t info; - user_single_step_siginfo(current, regs, &info); -@@ -201,6 +210,8 @@ static inline void tracehook_report_exec - struct linux_binprm *bprm, - struct pt_regs *regs) - { -+ if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXEC))) -+ utrace_report_exec(fmt, bprm, regs); - if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) && - unlikely(task_ptrace(current) & PT_PTRACED)) - send_sig(SIGTRAP, current, 0); -@@ -218,10 +229,37 @@ static inline void tracehook_report_exec - */ - static inline void tracehook_report_exit(long *exit_code) - { -+ if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXIT))) -+ utrace_report_exit(exit_code); - ptrace_event(PT_TRACE_EXIT, PTRACE_EVENT_EXIT, *exit_code); - } - - /** -+ * tracehook_init_task - task_struct has just been copied -+ * @task: new &struct task_struct just copied from parent -+ * -+ * Called from do_fork() when @task has just been duplicated. -+ * After this, @task will be passed to tracehook_free_task() -+ * even if the rest of its setup fails before it is fully created. -+ */ -+static inline void tracehook_init_task(struct task_struct *task) -+{ -+ utrace_init_task(task); -+} -+ -+/** -+ * tracehook_free_task - task_struct is being freed -+ * @task: dead &struct task_struct being freed -+ * -+ * Called from free_task() when @task is no longer in use. -+ */ -+static inline void tracehook_free_task(struct task_struct *task) -+{ -+ if (task_utrace_struct(task)) -+ utrace_free_task(task); -+} -+ -+/** - * tracehook_prepare_clone - prepare for new child to be cloned - * @clone_flags: %CLONE_* flags from clone/fork/vfork system call - * -@@ -285,6 +323,8 @@ static inline void tracehook_report_clon - unsigned long clone_flags, - pid_t pid, struct task_struct *child) - { -+ if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE))) -+ utrace_report_clone(clone_flags, child); - if (unlikely(task_ptrace(child))) { - /* - * It doesn't matter who attached/attaching to this -@@ -317,6 +357,9 @@ static inline void tracehook_report_clon - pid_t pid, - struct task_struct *child) - { -+ if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE)) && -+ (clone_flags & CLONE_VFORK)) -+ utrace_finish_vfork(current); - if (unlikely(trace)) - ptrace_event(0, trace, pid); - } -@@ -351,6 +394,10 @@ static inline void tracehook_report_vfor - */ - static inline void tracehook_prepare_release_task(struct task_struct *task) - { -+ /* see utrace_add_engine() about this barrier */ -+ smp_mb(); -+ if (task_utrace_flags(task)) -+ utrace_maybe_reap(task, task_utrace_struct(task), true); - } - - /** -@@ -365,6 +412,7 @@ static inline void tracehook_prepare_rel - static inline void tracehook_finish_release_task(struct task_struct *task) - { - ptrace_release_task(task); -+ BUG_ON(task->exit_state != EXIT_DEAD); - } - - /** -@@ -386,6 +434,8 @@ static inline void tracehook_signal_hand - const struct k_sigaction *ka, - struct pt_regs *regs, int stepping) - { -+ if (task_utrace_flags(current)) -+ utrace_signal_handler(current, stepping); - if (stepping && (task_ptrace(current) & PT_PTRACED)) - ptrace_notify(SIGTRAP); - } -@@ -403,6 +453,8 @@ static inline void tracehook_signal_hand - static inline int tracehook_consider_ignored_signal(struct task_struct *task, - int sig) - { -+ if (unlikely(task_utrace_flags(task) & UTRACE_EVENT(SIGNAL_IGN))) -+ return 1; - return (task_ptrace(task) & PT_PTRACED) != 0; - } - -@@ -422,6 +474,9 @@ static inline int tracehook_consider_ign - static inline int tracehook_consider_fatal_signal(struct task_struct *task, - int sig) - { -+ if (unlikely(task_utrace_flags(task) & (UTRACE_EVENT(SIGNAL_TERM) | -+ UTRACE_EVENT(SIGNAL_CORE)))) -+ return 1; - return (task_ptrace(task) & PT_PTRACED) != 0; - } - -@@ -436,6 +491,8 @@ static inline int tracehook_consider_fat - */ - static inline int tracehook_force_sigpending(void) - { -+ if (unlikely(task_utrace_flags(current))) -+ return utrace_interrupt_pending(); - return 0; - } - -@@ -465,6 +522,8 @@ static inline int tracehook_get_signal(s - siginfo_t *info, - struct k_sigaction *return_ka) - { -+ if (unlikely(task_utrace_flags(task))) -+ return utrace_get_signal(task, regs, info, return_ka); - return 0; - } - -@@ -492,6 +551,8 @@ static inline int tracehook_get_signal(s - */ - static inline int tracehook_notify_jctl(int notify, int why) - { -+ if (task_utrace_flags(current) & UTRACE_EVENT(JCTL)) -+ utrace_report_jctl(notify, why); - return notify ?: task_ptrace(current) ? why : 0; - } - -@@ -502,6 +563,8 @@ static inline int tracehook_notify_jctl( - */ - static inline void tracehook_finish_jctl(void) - { -+ if (task_utrace_flags(current)) -+ utrace_finish_stop(); - } - - #define DEATH_REAP -1 -@@ -524,6 +587,8 @@ static inline void tracehook_finish_jctl - static inline int tracehook_notify_death(struct task_struct *task, - void **death_cookie, int group_dead) - { -+ *death_cookie = task_utrace_struct(task); -+ - if (task_detached(task)) - return task->ptrace ? SIGCHLD : DEATH_REAP; - -@@ -560,6 +625,15 @@ static inline void tracehook_report_deat - int signal, void *death_cookie, - int group_dead) - { -+ /* -+ * If utrace_set_events() was just called to enable -+ * UTRACE_EVENT(DEATH), then we are obliged to call -+ * utrace_report_death() and not miss it. utrace_set_events() -+ * checks @task->exit_state under tasklist_lock to synchronize -+ * with exit_notify(), the caller. -+ */ -+ if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) -+ utrace_report_death(task, death_cookie, group_dead, signal); - } - - #ifdef TIF_NOTIFY_RESUME -@@ -589,10 +663,21 @@ static inline void set_notify_resume(str - * asynchronously, this will be called again before we return to - * user mode. - * -- * Called without locks. -+ * Called without locks. However, on some machines this may be -+ * called with interrupts disabled. - */ - static inline void tracehook_notify_resume(struct pt_regs *regs) - { -+ struct task_struct *task = current; -+ /* -+ * Prevent the following store/load from getting ahead of the -+ * caller which clears TIF_NOTIFY_RESUME. This pairs with the -+ * implicit mb() before setting TIF_NOTIFY_RESUME in -+ * set_notify_resume(). -+ */ -+ smp_mb(); -+ if (task_utrace_flags(task)) -+ utrace_resume(task, regs); - } - #endif /* TIF_NOTIFY_RESUME */ - -diff --git a/include/linux/utrace.h b/include/linux/utrace.h -new file mode 100644 -index ...f251efe 100644 ---- /dev/null -+++ b/include/linux/utrace.h -@@ -0,0 +1,692 @@ -+/* -+ * utrace infrastructure interface for debugging user processes -+ * -+ * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved. -+ * -+ * This copyrighted material is made available to anyone wishing to use, -+ * modify, copy, or redistribute it subject to the terms and conditions -+ * of the GNU General Public License v.2. -+ * -+ * Red Hat Author: Roland McGrath. -+ * -+ * This interface allows for notification of interesting events in a -+ * thread. It also mediates access to thread state such as registers. -+ * Multiple unrelated users can be associated with a single thread. -+ * We call each of these a tracing engine. -+ * -+ * A tracing engine starts by calling utrace_attach_task() or -+ * utrace_attach_pid() on the chosen thread, passing in a set of hooks -+ * (&struct utrace_engine_ops), and some associated data. This produces a -+ * &struct utrace_engine, which is the handle used for all other -+ * operations. An attached engine has its ops vector, its data, and an -+ * event mask controlled by utrace_set_events(). -+ * -+ * For each event bit that is set, that engine will get the -+ * appropriate ops->report_*() callback when the event occurs. The -+ * &struct utrace_engine_ops need not provide callbacks for an event -+ * unless the engine sets one of the associated event bits. -+ */ -+ -+#ifndef _LINUX_UTRACE_H -+#define _LINUX_UTRACE_H 1 -+ -+#include -+#include -+#include -+#include -+ -+struct linux_binprm; -+struct pt_regs; -+struct utrace; -+struct user_regset; -+struct user_regset_view; -+ -+/* -+ * Event bits passed to utrace_set_events(). -+ * These appear in &struct task_struct.@utrace_flags -+ * and &struct utrace_engine.@flags. -+ */ -+enum utrace_events { -+ _UTRACE_EVENT_QUIESCE, /* Thread is available for examination. */ -+ _UTRACE_EVENT_REAP, /* Zombie reaped, no more tracing possible. */ -+ _UTRACE_EVENT_CLONE, /* Successful clone/fork/vfork just done. */ -+ _UTRACE_EVENT_EXEC, /* Successful execve just completed. */ -+ _UTRACE_EVENT_EXIT, /* Thread exit in progress. */ -+ _UTRACE_EVENT_DEATH, /* Thread has died. */ -+ _UTRACE_EVENT_SYSCALL_ENTRY, /* User entered kernel for system call. */ -+ _UTRACE_EVENT_SYSCALL_EXIT, /* Returning to user after system call. */ -+ _UTRACE_EVENT_SIGNAL, /* Signal delivery will run a user handler. */ -+ _UTRACE_EVENT_SIGNAL_IGN, /* No-op signal to be delivered. */ -+ _UTRACE_EVENT_SIGNAL_STOP, /* Signal delivery will suspend. */ -+ _UTRACE_EVENT_SIGNAL_TERM, /* Signal delivery will terminate. */ -+ _UTRACE_EVENT_SIGNAL_CORE, /* Signal delivery will dump core. */ -+ _UTRACE_EVENT_JCTL, /* Job control stop or continue completed. */ -+ _UTRACE_NEVENTS -+}; -+#define UTRACE_EVENT(type) (1UL << _UTRACE_EVENT_##type) -+ -+/* -+ * All the kinds of signal events. -+ * These all use the @report_signal() callback. -+ */ -+#define UTRACE_EVENT_SIGNAL_ALL (UTRACE_EVENT(SIGNAL) \ -+ | UTRACE_EVENT(SIGNAL_IGN) \ -+ | UTRACE_EVENT(SIGNAL_STOP) \ -+ | UTRACE_EVENT(SIGNAL_TERM) \ -+ | UTRACE_EVENT(SIGNAL_CORE)) -+/* -+ * Both kinds of syscall events; these call the @report_syscall_entry() -+ * and @report_syscall_exit() callbacks, respectively. -+ */ -+#define UTRACE_EVENT_SYSCALL \ -+ (UTRACE_EVENT(SYSCALL_ENTRY) | UTRACE_EVENT(SYSCALL_EXIT)) -+ -+/* -+ * The event reports triggered synchronously by task death. -+ */ -+#define _UTRACE_DEATH_EVENTS (UTRACE_EVENT(DEATH) | UTRACE_EVENT(QUIESCE)) -+ -+/* -+ * Hooks in call these entry points to the utrace dispatch. -+ */ -+void utrace_free_task(struct task_struct *); -+bool utrace_interrupt_pending(void); -+void utrace_resume(struct task_struct *, struct pt_regs *); -+void utrace_finish_stop(void); -+void utrace_maybe_reap(struct task_struct *, struct utrace *, bool); -+int utrace_get_signal(struct task_struct *, struct pt_regs *, -+ siginfo_t *, struct k_sigaction *); -+void utrace_report_clone(unsigned long, struct task_struct *); -+void utrace_finish_vfork(struct task_struct *); -+void utrace_report_exit(long *exit_code); -+void utrace_report_death(struct task_struct *, struct utrace *, bool, int); -+void utrace_report_jctl(int notify, int type); -+void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *, -+ struct pt_regs *regs); -+bool utrace_report_syscall_entry(struct pt_regs *); -+void utrace_report_syscall_exit(struct pt_regs *); -+void utrace_signal_handler(struct task_struct *, int); -+ -+#ifndef CONFIG_UTRACE -+ -+/* -+ * uses these accessors to avoid #ifdef CONFIG_UTRACE. -+ */ -+static inline unsigned long task_utrace_flags(struct task_struct *task) -+{ -+ return 0; -+} -+static inline struct utrace *task_utrace_struct(struct task_struct *task) -+{ -+ return NULL; -+} -+static inline void utrace_init_task(struct task_struct *child) -+{ -+} -+ -+static inline void task_utrace_proc_status(struct seq_file *m, -+ struct task_struct *p) -+{ -+} -+ -+#else /* CONFIG_UTRACE */ -+ -+static inline unsigned long task_utrace_flags(struct task_struct *task) -+{ -+ return task->utrace_flags; -+} -+ -+static inline struct utrace *task_utrace_struct(struct task_struct *task) -+{ -+ struct utrace *utrace; -+ -+ /* -+ * This barrier ensures that any prior load of task->utrace_flags -+ * is ordered before this load of task->utrace. We use those -+ * utrace_flags checks in the hot path to decide to call into -+ * the utrace code. The first attach installs task->utrace before -+ * setting task->utrace_flags nonzero with implicit barrier in -+ * between, see utrace_add_engine(). -+ */ -+ smp_rmb(); -+ utrace = task->utrace; -+ -+ smp_read_barrier_depends(); /* See utrace_task_alloc(). */ -+ return utrace; -+} -+ -+static inline void utrace_init_task(struct task_struct *task) -+{ -+ task->utrace_flags = 0; -+ task->utrace = NULL; -+} -+ -+void task_utrace_proc_status(struct seq_file *m, struct task_struct *p); -+ -+ -+/* -+ * Version number of the API defined in this file. This will change -+ * whenever a tracing engine's code would need some updates to keep -+ * working. We maintain this here for the benefit of tracing engine code -+ * that is developed concurrently with utrace API improvements before they -+ * are merged into the kernel, making LINUX_VERSION_CODE checks unwieldy. -+ */ -+#define UTRACE_API_VERSION 20091216 -+ -+/** -+ * enum utrace_resume_action - engine's choice of action for a traced task -+ * @UTRACE_STOP: Stay quiescent after callbacks. -+ * @UTRACE_INTERRUPT: Make @report_signal() callback soon. -+ * @UTRACE_REPORT: Make some callback soon. -+ * @UTRACE_SINGLESTEP: Resume in user mode for one instruction. -+ * @UTRACE_BLOCKSTEP: Resume in user mode until next branch. -+ * @UTRACE_RESUME: Resume normally in user mode. -+ * @UTRACE_DETACH: Detach my engine (implies %UTRACE_RESUME). -+ * -+ * See utrace_control() for detailed descriptions of each action. This is -+ * encoded in the @action argument and the return value for every callback -+ * with a &u32 return value. -+ * -+ * The order of these is important. When there is more than one engine, -+ * each supplies its choice and the smallest value prevails. -+ */ -+enum utrace_resume_action { -+ UTRACE_STOP, -+ UTRACE_INTERRUPT, -+ UTRACE_REPORT, -+ UTRACE_SINGLESTEP, -+ UTRACE_BLOCKSTEP, -+ UTRACE_RESUME, -+ UTRACE_DETACH, -+ UTRACE_RESUME_MAX -+}; -+#define UTRACE_RESUME_BITS (ilog2(UTRACE_RESUME_MAX) + 1) -+#define UTRACE_RESUME_MASK ((1 << UTRACE_RESUME_BITS) - 1) -+ -+/** -+ * utrace_resume_action - &enum utrace_resume_action from callback action -+ * @action: &u32 callback @action argument or return value -+ * -+ * This extracts the &enum utrace_resume_action from @action, -+ * which is the @action argument to a &struct utrace_engine_ops -+ * callback or the return value from one. -+ */ -+static inline enum utrace_resume_action utrace_resume_action(u32 action) -+{ -+ return action & UTRACE_RESUME_MASK; -+} -+ -+/** -+ * enum utrace_signal_action - disposition of signal -+ * @UTRACE_SIGNAL_DELIVER: Deliver according to sigaction. -+ * @UTRACE_SIGNAL_IGN: Ignore the signal. -+ * @UTRACE_SIGNAL_TERM: Terminate the process. -+ * @UTRACE_SIGNAL_CORE: Terminate with core dump. -+ * @UTRACE_SIGNAL_STOP: Deliver as absolute stop. -+ * @UTRACE_SIGNAL_TSTP: Deliver as job control stop. -+ * @UTRACE_SIGNAL_REPORT: Reporting before pending signals. -+ * @UTRACE_SIGNAL_HANDLER: Reporting after signal handler setup. -+ * -+ * This is encoded in the @action argument and the return value for -+ * a @report_signal() callback. It says what will happen to the -+ * signal described by the &siginfo_t parameter to the callback. -+ * -+ * The %UTRACE_SIGNAL_REPORT value is used in an @action argument when -+ * a tracing report is being made before dequeuing any pending signal. -+ * If this is immediately after a signal handler has been set up, then -+ * %UTRACE_SIGNAL_HANDLER is used instead. A @report_signal callback -+ * that uses %UTRACE_SIGNAL_DELIVER|%UTRACE_SINGLESTEP will ensure -+ * it sees a %UTRACE_SIGNAL_HANDLER report. -+ */ -+enum utrace_signal_action { -+ UTRACE_SIGNAL_DELIVER = 0x00, -+ UTRACE_SIGNAL_IGN = 0x10, -+ UTRACE_SIGNAL_TERM = 0x20, -+ UTRACE_SIGNAL_CORE = 0x30, -+ UTRACE_SIGNAL_STOP = 0x40, -+ UTRACE_SIGNAL_TSTP = 0x50, -+ UTRACE_SIGNAL_REPORT = 0x60, -+ UTRACE_SIGNAL_HANDLER = 0x70 -+}; -+#define UTRACE_SIGNAL_MASK 0xf0 -+#define UTRACE_SIGNAL_HOLD 0x100 /* Flag, push signal back on queue. */ -+ -+/** -+ * utrace_signal_action - &enum utrace_signal_action from callback action -+ * @action: @report_signal callback @action argument or return value -+ * -+ * This extracts the &enum utrace_signal_action from @action, which -+ * is the @action argument to a @report_signal callback or the -+ * return value from one. -+ */ -+static inline enum utrace_signal_action utrace_signal_action(u32 action) -+{ -+ return action & UTRACE_SIGNAL_MASK; -+} -+ -+/** -+ * enum utrace_syscall_action - disposition of system call attempt -+ * @UTRACE_SYSCALL_RUN: Run the system call. -+ * @UTRACE_SYSCALL_ABORT: Don't run the system call. -+ * -+ * This is encoded in the @action argument and the return value for -+ * a @report_syscall_entry callback. -+ */ -+enum utrace_syscall_action { -+ UTRACE_SYSCALL_RUN = 0x00, -+ UTRACE_SYSCALL_ABORT = 0x10 -+}; -+#define UTRACE_SYSCALL_MASK 0xf0 -+#define UTRACE_SYSCALL_RESUMED 0x100 /* Flag, report_syscall_entry() repeats */ -+ -+/** -+ * utrace_syscall_action - &enum utrace_syscall_action from callback action -+ * @action: @report_syscall_entry callback @action or return value -+ * -+ * This extracts the &enum utrace_syscall_action from @action, which -+ * is the @action argument to a @report_syscall_entry callback or the -+ * return value from one. -+ */ -+static inline enum utrace_syscall_action utrace_syscall_action(u32 action) -+{ -+ return action & UTRACE_SYSCALL_MASK; -+} -+ -+/* -+ * Flags for utrace_attach_task() and utrace_attach_pid(). -+ */ -+#define UTRACE_ATTACH_MATCH_OPS 0x0001 /* Match engines on ops. */ -+#define UTRACE_ATTACH_MATCH_DATA 0x0002 /* Match engines on data. */ -+#define UTRACE_ATTACH_MATCH_MASK 0x000f -+#define UTRACE_ATTACH_CREATE 0x0010 /* Attach a new engine. */ -+#define UTRACE_ATTACH_EXCLUSIVE 0x0020 /* Refuse if existing match. */ -+ -+/** -+ * struct utrace_engine - per-engine structure -+ * @ops: &struct utrace_engine_ops pointer passed to utrace_attach_task() -+ * @data: engine-private &void * passed to utrace_attach_task() -+ * @flags: event mask set by utrace_set_events() plus internal flag bits -+ * -+ * The task itself never has to worry about engines detaching while -+ * it's doing event callbacks. These structures are removed from the -+ * task's active list only when it's stopped, or by the task itself. -+ * -+ * utrace_engine_get() and utrace_engine_put() maintain a reference count. -+ * When it drops to zero, the structure is freed. One reference is held -+ * implicitly while the engine is attached to its task. -+ */ -+struct utrace_engine { -+/* private: */ -+ struct kref kref; -+ void (*release)(void *); -+ struct list_head entry; -+ -+/* public: */ -+ const struct utrace_engine_ops *ops; -+ void *data; -+ -+ unsigned long flags; -+}; -+ -+/** -+ * utrace_engine_get - acquire a reference on a &struct utrace_engine -+ * @engine: &struct utrace_engine pointer -+ * -+ * You must hold a reference on @engine, and you get another. -+ */ -+static inline void utrace_engine_get(struct utrace_engine *engine) -+{ -+ kref_get(&engine->kref); -+} -+ -+void __utrace_engine_release(struct kref *); -+ -+/** -+ * utrace_engine_put - release a reference on a &struct utrace_engine -+ * @engine: &struct utrace_engine pointer -+ * -+ * You must hold a reference on @engine, and you lose that reference. -+ * If it was the last one, @engine becomes an invalid pointer. -+ */ -+static inline void utrace_engine_put(struct utrace_engine *engine) -+{ -+ kref_put(&engine->kref, __utrace_engine_release); -+} -+ -+/** -+ * struct utrace_engine_ops - tracing engine callbacks -+ * -+ * Each @report_*() callback corresponds to an %UTRACE_EVENT(*) bit. -+ * utrace_set_events() calls on @engine choose which callbacks will -+ * be made to @engine from @task. -+ * -+ * Most callbacks take an @action argument, giving the resume action -+ * chosen by other tracing engines. All callbacks take an @engine -+ * argument. The @report_reap callback takes a @task argument that -+ * might or might not be @current. All other @report_* callbacks -+ * report an event in the @current task. -+ * -+ * For some calls, @action also includes bits specific to that event -+ * and utrace_resume_action() is used to extract the resume action. -+ * This shows what would happen if @engine wasn't there, or will if -+ * the callback's return value uses %UTRACE_RESUME. This always -+ * starts as %UTRACE_RESUME when no other tracing is being done on -+ * this task. -+ * -+ * All return values contain &enum utrace_resume_action bits. For -+ * some calls, other bits specific to that kind of event are added to -+ * the resume action bits with OR. These are the same bits used in -+ * the @action argument. The resume action returned by a callback -+ * does not override previous engines' choices, it only says what -+ * @engine wants done. What @current actually does is the action that's -+ * most constrained among the choices made by all attached engines. -+ * See utrace_control() for more information on the actions. -+ * -+ * When %UTRACE_STOP is used in @report_syscall_entry, then @current -+ * stops before attempting the system call. In this case, another -+ * @report_syscall_entry callback will follow after @current resumes if -+ * %UTRACE_REPORT or %UTRACE_INTERRUPT was returned by some callback -+ * or passed to utrace_control(). In a second or later callback, -+ * %UTRACE_SYSCALL_RESUMED is set in the @action argument to indicate -+ * a repeat callback still waiting to attempt the same system call -+ * invocation. This repeat callback gives each engine an opportunity -+ * to reexamine registers another engine might have changed while -+ * @current was held in %UTRACE_STOP. -+ * -+ * In other cases, the resume action does not take effect until @current -+ * is ready to check for signals and return to user mode. If there -+ * are more callbacks to be made, the last round of calls determines -+ * the final action. A @report_quiesce callback with @event zero, or -+ * a @report_signal callback, will always be the last one made before -+ * @current resumes. Only %UTRACE_STOP is "sticky"--if @engine returned -+ * %UTRACE_STOP then @current stays stopped unless @engine returns -+ * different from a following callback. -+ * -+ * The report_death() and report_reap() callbacks do not take @action -+ * arguments, and only %UTRACE_DETACH is meaningful in the return value -+ * from a report_death() callback. None of the resume actions applies -+ * to a dead thread. -+ * -+ * All @report_*() hooks are called with no locks held, in a generally -+ * safe environment when we will be returning to user mode soon (or just -+ * entered the kernel). It is fine to block for memory allocation and -+ * the like, but all hooks are asynchronous and must not block on -+ * external events! If you want the thread to block, use %UTRACE_STOP -+ * in your hook's return value; then later wake it up with utrace_control(). -+ * -+ * @report_quiesce: -+ * Requested by %UTRACE_EVENT(%QUIESCE). -+ * This does not indicate any event, but just that @current is in a -+ * safe place for examination. This call is made before each specific -+ * event callback, except for @report_reap. The @event argument gives -+ * the %UTRACE_EVENT(@which) value for the event occurring. This -+ * callback might be made for events @engine has not requested, if -+ * some other engine is tracing the event; calling utrace_set_events() -+ * call here can request the immediate callback for this occurrence of -+ * @event. @event is zero when there is no other event, @current is -+ * now ready to check for signals and return to user mode, and some -+ * engine has used %UTRACE_REPORT or %UTRACE_INTERRUPT to request this -+ * callback. For this case, if @report_signal is not %NULL, the -+ * @report_quiesce callback may be replaced with a @report_signal -+ * callback passing %UTRACE_SIGNAL_REPORT in its @action argument, -+ * whenever @current is entering the signal-check path anyway. -+ * -+ * @report_signal: -+ * Requested by %UTRACE_EVENT(%SIGNAL_*) or %UTRACE_EVENT(%QUIESCE). -+ * Use utrace_signal_action() and utrace_resume_action() on @action. -+ * The signal action is %UTRACE_SIGNAL_REPORT when some engine has -+ * used %UTRACE_REPORT or %UTRACE_INTERRUPT; the callback can choose -+ * to stop or to deliver an artificial signal, before pending signals. -+ * It's %UTRACE_SIGNAL_HANDLER instead when signal handler setup just -+ * finished (after a previous %UTRACE_SIGNAL_DELIVER return); this -+ * serves in lieu of any %UTRACE_SIGNAL_REPORT callback requested by -+ * %UTRACE_REPORT or %UTRACE_INTERRUPT, and is also implicitly -+ * requested by %UTRACE_SINGLESTEP or %UTRACE_BLOCKSTEP into the -+ * signal delivery. The other signal actions indicate a signal about -+ * to be delivered; the previous engine's return value sets the signal -+ * action seen by the the following engine's callback. The @info data -+ * can be changed at will, including @info->si_signo. The settings in -+ * @return_ka determines what %UTRACE_SIGNAL_DELIVER does. @orig_ka -+ * is what was in force before other tracing engines intervened, and -+ * it's %NULL when this report began as %UTRACE_SIGNAL_REPORT or -+ * %UTRACE_SIGNAL_HANDLER. For a report without a new signal, @info -+ * is left uninitialized and must be set completely by an engine that -+ * chooses to deliver a signal; if there was a previous @report_signal -+ * callback ending in %UTRACE_STOP and it was just resumed using -+ * %UTRACE_REPORT or %UTRACE_INTERRUPT, then @info is left unchanged -+ * from the previous callback. In this way, the original signal can -+ * be left in @info while returning %UTRACE_STOP|%UTRACE_SIGNAL_IGN -+ * and then found again when resuming with %UTRACE_INTERRUPT. -+ * The %UTRACE_SIGNAL_HOLD flag bit can be OR'd into the return value, -+ * and might be in @action if the previous engine returned it. This -+ * flag asks that the signal in @info be pushed back on @current's queue -+ * so that it will be seen again after whatever action is taken now. -+ * -+ * @report_clone: -+ * Requested by %UTRACE_EVENT(%CLONE). -+ * Event reported for parent, before the new task @child might run. -+ * @clone_flags gives the flags used in the clone system call, or -+ * equivalent flags for a fork() or vfork() system call. This -+ * function can use utrace_attach_task() on @child. Then passing -+ * %UTRACE_STOP to utrace_control() on @child here keeps the child -+ * stopped before it ever runs in user mode, %UTRACE_REPORT or -+ * %UTRACE_INTERRUPT ensures a callback from @child before it -+ * starts in user mode. -+ * -+ * @report_jctl: -+ * Requested by %UTRACE_EVENT(%JCTL). -+ * Job control event; @type is %CLD_STOPPED or %CLD_CONTINUED, -+ * indicating whether we are stopping or resuming now. If @notify -+ * is nonzero, @current is the last thread to stop and so will send -+ * %SIGCHLD to its parent after this callback; @notify reflects -+ * what the parent's %SIGCHLD has in @si_code, which can sometimes -+ * be %CLD_STOPPED even when @type is %CLD_CONTINUED. -+ * -+ * @report_exec: -+ * Requested by %UTRACE_EVENT(%EXEC). -+ * An execve system call has succeeded and the new program is about to -+ * start running. The initial user register state is handy to be tweaked -+ * directly in @regs. @fmt and @bprm gives the details of this exec. -+ * -+ * @report_syscall_entry: -+ * Requested by %UTRACE_EVENT(%SYSCALL_ENTRY). -+ * Thread has entered the kernel to request a system call. -+ * The user register state is handy to be tweaked directly in @regs. -+ * The @action argument contains an &enum utrace_syscall_action, -+ * use utrace_syscall_action() to extract it. The return value -+ * overrides the last engine's action for the system call. -+ * If the final action is %UTRACE_SYSCALL_ABORT, no system call -+ * is made. The details of the system call being attempted can -+ * be fetched here with syscall_get_nr() and syscall_get_arguments(). -+ * The parameter registers can be changed with syscall_set_arguments(). -+ * See above about the %UTRACE_SYSCALL_RESUMED flag in @action. -+ * Use %UTRACE_REPORT in the return value to guarantee you get -+ * another callback (with %UTRACE_SYSCALL_RESUMED flag) in case -+ * @current stops with %UTRACE_STOP before attempting the system call. -+ * -+ * @report_syscall_exit: -+ * Requested by %UTRACE_EVENT(%SYSCALL_EXIT). -+ * Thread is about to leave the kernel after a system call request. -+ * The user register state is handy to be tweaked directly in @regs. -+ * The results of the system call attempt can be examined here using -+ * syscall_get_error() and syscall_get_return_value(). It is safe -+ * here to call syscall_set_return_value() or syscall_rollback(). -+ * -+ * @report_exit: -+ * Requested by %UTRACE_EVENT(%EXIT). -+ * Thread is exiting and cannot be prevented from doing so, -+ * but all its state is still live. The @code value will be -+ * the wait result seen by the parent, and can be changed by -+ * this engine or others. The @orig_code value is the real -+ * status, not changed by any tracing engine. Returning %UTRACE_STOP -+ * here keeps @current stopped before it cleans up its state and dies, -+ * so it can be examined by other processes. When @current is allowed -+ * to run, it will die and get to the @report_death callback. -+ * -+ * @report_death: -+ * Requested by %UTRACE_EVENT(%DEATH). -+ * Thread is really dead now. It might be reaped by its parent at -+ * any time, or self-reap immediately. Though the actual reaping -+ * may happen in parallel, a report_reap() callback will always be -+ * ordered after a report_death() callback. -+ * -+ * @report_reap: -+ * Requested by %UTRACE_EVENT(%REAP). -+ * Called when someone reaps the dead task (parent, init, or self). -+ * This means the parent called wait, or else this was a detached -+ * thread or a process whose parent ignores SIGCHLD. -+ * No more callbacks are made after this one. -+ * The engine is always detached. -+ * There is nothing more a tracing engine can do about this thread. -+ * After this callback, the @engine pointer will become invalid. -+ * The @task pointer may become invalid if get_task_struct() hasn't -+ * been used to keep it alive. -+ * An engine should always request this callback if it stores the -+ * @engine pointer or stores any pointer in @engine->data, so it -+ * can clean up its data structures. -+ * Unlike other callbacks, this can be called from the parent's context -+ * rather than from the traced thread itself--it must not delay the -+ * parent by blocking. -+ * -+ * @release: -+ * If not %NULL, this is called after the last utrace_engine_put() -+ * call for a &struct utrace_engine, which could be implicit after -+ * a %UTRACE_DETACH return from another callback. Its argument is -+ * the engine's @data member. -+ */ -+struct utrace_engine_ops { -+ u32 (*report_quiesce)(u32 action, struct utrace_engine *engine, -+ unsigned long event); -+ u32 (*report_signal)(u32 action, struct utrace_engine *engine, -+ struct pt_regs *regs, -+ siginfo_t *info, -+ const struct k_sigaction *orig_ka, -+ struct k_sigaction *return_ka); -+ u32 (*report_clone)(u32 action, struct utrace_engine *engine, -+ unsigned long clone_flags, -+ struct task_struct *child); -+ u32 (*report_jctl)(u32 action, struct utrace_engine *engine, -+ int type, int notify); -+ u32 (*report_exec)(u32 action, struct utrace_engine *engine, -+ const struct linux_binfmt *fmt, -+ const struct linux_binprm *bprm, -+ struct pt_regs *regs); -+ u32 (*report_syscall_entry)(u32 action, struct utrace_engine *engine, -+ struct pt_regs *regs); -+ u32 (*report_syscall_exit)(u32 action, struct utrace_engine *engine, -+ struct pt_regs *regs); -+ u32 (*report_exit)(u32 action, struct utrace_engine *engine, -+ long orig_code, long *code); -+ u32 (*report_death)(struct utrace_engine *engine, -+ bool group_dead, int signal); -+ void (*report_reap)(struct utrace_engine *engine, -+ struct task_struct *task); -+ void (*release)(void *data); -+}; -+ -+/** -+ * struct utrace_examiner - private state for using utrace_prepare_examine() -+ * -+ * The members of &struct utrace_examiner are private to the implementation. -+ * This data type holds the state from a call to utrace_prepare_examine() -+ * to be used by a call to utrace_finish_examine(). -+ */ -+struct utrace_examiner { -+/* private: */ -+ long state; -+ unsigned long ncsw; -+}; -+ -+/* -+ * These are the exported entry points for tracing engines to use. -+ * See kernel/utrace.c for their kerneldoc comments with interface details. -+ */ -+struct utrace_engine *utrace_attach_task(struct task_struct *, int, -+ const struct utrace_engine_ops *, -+ void *); -+struct utrace_engine *utrace_attach_pid(struct pid *, int, -+ const struct utrace_engine_ops *, -+ void *); -+int __must_check utrace_control(struct task_struct *, -+ struct utrace_engine *, -+ enum utrace_resume_action); -+int __must_check utrace_set_events(struct task_struct *, -+ struct utrace_engine *, -+ unsigned long eventmask); -+int __must_check utrace_barrier(struct task_struct *, -+ struct utrace_engine *); -+int __must_check utrace_prepare_examine(struct task_struct *, -+ struct utrace_engine *, -+ struct utrace_examiner *); -+int __must_check utrace_finish_examine(struct task_struct *, -+ struct utrace_engine *, -+ struct utrace_examiner *); -+ -+/** -+ * utrace_control_pid - control a thread being traced by a tracing engine -+ * @pid: thread to affect -+ * @engine: attached engine to affect -+ * @action: &enum utrace_resume_action for thread to do -+ * -+ * This is the same as utrace_control(), but takes a &struct pid -+ * pointer rather than a &struct task_struct pointer. The caller must -+ * hold a ref on @pid, but does not need to worry about the task -+ * staying valid. If it's been reaped so that @pid points nowhere, -+ * then this call returns -%ESRCH. -+ */ -+static inline __must_check int utrace_control_pid( -+ struct pid *pid, struct utrace_engine *engine, -+ enum utrace_resume_action action) -+{ -+ /* -+ * We don't bother with rcu_read_lock() here to protect the -+ * task_struct pointer, because utrace_control will return -+ * -ESRCH without looking at that pointer if the engine is -+ * already detached. A task_struct pointer can't die before -+ * all the engines are detached in release_task() first. -+ */ -+ struct task_struct *task = pid_task(pid, PIDTYPE_PID); -+ return unlikely(!task) ? -ESRCH : utrace_control(task, engine, action); -+} -+ -+/** -+ * utrace_set_events_pid - choose which event reports a tracing engine gets -+ * @pid: thread to affect -+ * @engine: attached engine to affect -+ * @eventmask: new event mask -+ * -+ * This is the same as utrace_set_events(), but takes a &struct pid -+ * pointer rather than a &struct task_struct pointer. The caller must -+ * hold a ref on @pid, but does not need to worry about the task -+ * staying valid. If it's been reaped so that @pid points nowhere, -+ * then this call returns -%ESRCH. -+ */ -+static inline __must_check int utrace_set_events_pid( -+ struct pid *pid, struct utrace_engine *engine, unsigned long eventmask) -+{ -+ struct task_struct *task = pid_task(pid, PIDTYPE_PID); -+ return unlikely(!task) ? -ESRCH : -+ utrace_set_events(task, engine, eventmask); -+} -+ -+/** -+ * utrace_barrier_pid - synchronize with simultaneous tracing callbacks -+ * @pid: thread to affect -+ * @engine: engine to affect (can be detached) -+ * -+ * This is the same as utrace_barrier(), but takes a &struct pid -+ * pointer rather than a &struct task_struct pointer. The caller must -+ * hold a ref on @pid, but does not need to worry about the task -+ * staying valid. If it's been reaped so that @pid points nowhere, -+ * then this call returns -%ESRCH. -+ */ -+static inline __must_check int utrace_barrier_pid(struct pid *pid, -+ struct utrace_engine *engine) -+{ -+ struct task_struct *task = pid_task(pid, PIDTYPE_PID); -+ return unlikely(!task) ? -ESRCH : utrace_barrier(task, engine); -+} -+ -+#endif /* CONFIG_UTRACE */ -+ -+#endif /* linux/utrace.h */ -diff --git a/init/Kconfig b/init/Kconfig -index c972899..17483b7 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -339,6 +339,15 @@ config AUDIT_TREE - depends on AUDITSYSCALL - select FSNOTIFY - -+config UTRACE -+ bool "Infrastructure for tracing and debugging user processes" -+ depends on EXPERIMENTAL -+ depends on HAVE_ARCH_TRACEHOOK -+ help -+ Enable the utrace process tracing interface. This is an internal -+ kernel interface exported to kernel modules, to track events in -+ user threads, extract and change user thread state. -+ - source "kernel/irq/Kconfig" - - menu "RCU Subsystem" -diff --git a/kernel/Makefile b/kernel/Makefile -index 0b5ff08..1172528 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -70,6 +70,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o - obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o - obj-$(CONFIG_SMP) += stop_machine.o - obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o -+obj-$(CONFIG_UTRACE) += utrace.o - obj-$(CONFIG_AUDIT) += audit.o auditfilter.o - obj-$(CONFIG_AUDITSYSCALL) += auditsc.o - obj-$(CONFIG_AUDIT_WATCH) += audit_watch.o -diff --git a/kernel/fork.c b/kernel/fork.c -index 5447dc7..10a39fe 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -162,6 +162,7 @@ void free_task(struct task_struct *tsk) - free_thread_info(tsk->stack); - rt_mutex_debug_task_free(tsk); - ftrace_graph_exit_task(tsk); -+ tracehook_free_task(tsk); - free_task_struct(tsk); - } - EXPORT_SYMBOL(free_task); -@@ -1018,6 +1019,8 @@ static struct task_struct *copy_process( - if (!p) - goto fork_out; - -+ tracehook_init_task(p); -+ - ftrace_graph_init_task(p); - - rt_mutex_init_task(p); -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 84d9f8f..e275608 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -163,6 +164,14 @@ bool ptrace_may_access(struct task_struc - 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; -@@ -186,6 +195,8 @@ int ptrace_attach(struct task_struct *ta - - task_lock(task); - retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); -+ if (!retval && exclude_ptrace(task)) -+ retval = -EBUSY; - task_unlock(task); - if (retval) - goto unlock_creds; -@@ -223,6 +234,9 @@ int ptrace_traceme(void) - { - int ret = -EPERM; - -+ if (exclude_ptrace(current)) /* XXX locking */ -+ return -EBUSY; -+ - write_lock_irq(&tasklist_lock); - /* Are we already being traced? */ - if (!current->ptrace) { -diff --git a/kernel/utrace.c b/kernel/utrace.c -new file mode 100644 -index ...26d6faf 100644 ---- /dev/null -+++ b/kernel/utrace.c -@@ -0,0 +1,2440 @@ -+/* -+ * utrace infrastructure interface for debugging user processes -+ * -+ * Copyright (C) 2006-2010 Red Hat, Inc. All rights reserved. -+ * -+ * This copyrighted material is made available to anyone wishing to use, -+ * modify, copy, or redistribute it subject to the terms and conditions -+ * of the GNU General Public License v.2. -+ * -+ * Red Hat Author: Roland McGrath. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+/* -+ * Per-thread structure private to utrace implementation. -+ * If task_struct.utrace_flags is nonzero, task_struct.utrace -+ * has always been allocated first. Once allocated, it is -+ * never freed until free_task(). -+ * -+ * The common event reporting loops are done by the task making the -+ * report without ever taking any locks. To facilitate this, the two -+ * lists @attached and @attaching work together for smooth asynchronous -+ * attaching with low overhead. Modifying either list requires @lock. -+ * The @attaching list can be modified any time while holding @lock. -+ * New engines being attached always go on this list. -+ * -+ * The @attached list is what the task itself uses for its reporting -+ * loops. When the task itself is not quiescent, it can use the -+ * @attached list without taking any lock. Nobody may modify the list -+ * when the task is not quiescent. When it is quiescent, that means -+ * that it won't run again without taking @lock itself before using -+ * the list. -+ * -+ * At each place where we know the task is quiescent (or it's current), -+ * while holding @lock, we call splice_attaching(), below. This moves -+ * the @attaching list members on to the end of the @attached list. -+ * Since this happens at the start of any reporting pass, any new -+ * engines attached asynchronously go on the stable @attached list -+ * in time to have their callbacks seen. -+ */ -+struct utrace { -+ spinlock_t lock; -+ struct list_head attached, attaching; -+ -+ struct task_struct *cloning; -+ -+ struct utrace_engine *reporting; -+ -+ enum utrace_resume_action resume:UTRACE_RESUME_BITS; -+ unsigned int signal_handler:1; -+ unsigned int vfork_stop:1; /* need utrace_stop() before vfork wait */ -+ unsigned int death:1; /* in utrace_report_death() now */ -+ unsigned int reap:1; /* release_task() has run */ -+ unsigned int pending_attach:1; /* need splice_attaching() */ -+}; -+ -+static struct kmem_cache *utrace_cachep; -+static struct kmem_cache *utrace_engine_cachep; -+static const struct utrace_engine_ops utrace_detached_ops; /* forward decl */ -+ -+static int __init utrace_init(void) -+{ -+ utrace_cachep = KMEM_CACHE(utrace, SLAB_PANIC); -+ utrace_engine_cachep = KMEM_CACHE(utrace_engine, SLAB_PANIC); -+ return 0; -+} -+module_init(utrace_init); -+ -+/* -+ * Set up @task.utrace for the first time. We can have races -+ * between two utrace_attach_task() calls here. The task_lock() -+ * governs installing the new pointer. If another one got in first, -+ * we just punt the new one we allocated. -+ * -+ * This returns false only in case of a memory allocation failure. -+ */ -+static bool utrace_task_alloc(struct task_struct *task) -+{ -+ struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, GFP_KERNEL); -+ if (unlikely(!utrace)) -+ return false; -+ spin_lock_init(&utrace->lock); -+ INIT_LIST_HEAD(&utrace->attached); -+ INIT_LIST_HEAD(&utrace->attaching); -+ utrace->resume = UTRACE_RESUME; -+ task_lock(task); -+ if (likely(!task->utrace)) { -+ /* -+ * This barrier makes sure the initialization of the struct -+ * precedes the installation of the pointer. This pairs -+ * with smp_read_barrier_depends() in task_utrace_struct(). -+ */ -+ smp_wmb(); -+ task->utrace = utrace; -+ } -+ task_unlock(task); -+ -+ if (unlikely(task->utrace != utrace)) -+ kmem_cache_free(utrace_cachep, utrace); -+ return true; -+} -+ -+/* -+ * This is called via tracehook_free_task() from free_task() -+ * when @task is being deallocated. -+ */ -+void utrace_free_task(struct task_struct *task) -+{ -+ kmem_cache_free(utrace_cachep, task->utrace); -+} -+ -+/* -+ * This is calledwhen the task is safely quiescent, i.e. it won't consult -+ * utrace->attached without the lock. Move any engines attached -+ * asynchronously from @utrace->attaching onto the @utrace->attached list. -+ */ -+static void splice_attaching(struct utrace *utrace) -+{ -+ lockdep_assert_held(&utrace->lock); -+ list_splice_tail_init(&utrace->attaching, &utrace->attached); -+ utrace->pending_attach = 0; -+} -+ -+/* -+ * This is the exported function used by the utrace_engine_put() inline. -+ */ -+void __utrace_engine_release(struct kref *kref) -+{ -+ struct utrace_engine *engine = container_of(kref, struct utrace_engine, -+ kref); -+ BUG_ON(!list_empty(&engine->entry)); -+ if (engine->release) -+ (*engine->release)(engine->data); -+ kmem_cache_free(utrace_engine_cachep, engine); -+} -+EXPORT_SYMBOL_GPL(__utrace_engine_release); -+ -+static bool engine_matches(struct utrace_engine *engine, int flags, -+ const struct utrace_engine_ops *ops, void *data) -+{ -+ if ((flags & UTRACE_ATTACH_MATCH_OPS) && engine->ops != ops) -+ return false; -+ if ((flags & UTRACE_ATTACH_MATCH_DATA) && engine->data != data) -+ return false; -+ return engine->ops && engine->ops != &utrace_detached_ops; -+} -+ -+static struct utrace_engine *find_matching_engine( -+ struct utrace *utrace, int flags, -+ const struct utrace_engine_ops *ops, void *data) -+{ -+ struct utrace_engine *engine; -+ list_for_each_entry(engine, &utrace->attached, entry) -+ if (engine_matches(engine, flags, ops, data)) -+ return engine; -+ list_for_each_entry(engine, &utrace->attaching, entry) -+ if (engine_matches(engine, flags, ops, data)) -+ return engine; -+ return NULL; -+} -+ -+/* -+ * Enqueue @engine, or maybe don't if UTRACE_ATTACH_EXCLUSIVE. -+ */ -+static int utrace_add_engine(struct task_struct *target, -+ struct utrace *utrace, -+ struct utrace_engine *engine, -+ int flags, -+ const struct utrace_engine_ops *ops, -+ void *data) -+{ -+ int ret; -+ -+ spin_lock(&utrace->lock); -+ -+ ret = -EEXIST; -+ if ((flags & UTRACE_ATTACH_EXCLUSIVE) && -+ unlikely(find_matching_engine(utrace, flags, ops, data))) -+ goto unlock; -+ -+ /* -+ * In case we had no engines before, make sure that -+ * utrace_flags is not zero. Since we did unlock+lock -+ * at least once after utrace_task_alloc() installed -+ * ->utrace, we have the necessary barrier which pairs -+ * with rmb() in task_utrace_struct(). -+ */ -+ ret = -ESRCH; -+ if (!target->utrace_flags) { -+ target->utrace_flags = UTRACE_EVENT(REAP); -+ /* -+ * If we race with tracehook_prepare_release_task() -+ * make sure that either it sees utrace_flags != 0 -+ * or we see exit_state == EXIT_DEAD. -+ */ -+ smp_mb(); -+ if (unlikely(target->exit_state == EXIT_DEAD)) { -+ target->utrace_flags = 0; -+ goto unlock; -+ } -+ } -+ -+ /* -+ * Put the new engine on the pending ->attaching list. -+ * Make sure it gets onto the ->attached list by the next -+ * time it's examined. Setting ->pending_attach ensures -+ * that start_report() takes the lock and splices the lists -+ * before the next new reporting pass. -+ * -+ * When target == current, it would be safe just to call -+ * splice_attaching() right here. But if we're inside a -+ * callback, that would mean the new engine also gets -+ * notified about the event that precipitated its own -+ * creation. This is not what the user wants. -+ */ -+ list_add_tail(&engine->entry, &utrace->attaching); -+ utrace->pending_attach = 1; -+ utrace_engine_get(engine); -+ ret = 0; -+unlock: -+ spin_unlock(&utrace->lock); -+ -+ return ret; -+} -+ -+/** -+ * utrace_attach_task - attach new engine, or look up an attached engine -+ * @target: thread to attach to -+ * @flags: flag bits combined with OR, see below -+ * @ops: callback table for new engine -+ * @data: engine private data pointer -+ * -+ * The caller must ensure that the @target thread does not get freed, -+ * i.e. hold a ref or be its parent. It is always safe to call this -+ * on @current, or on the @child pointer in a @report_clone callback. -+ * For most other cases, it's easier to use utrace_attach_pid() instead. -+ * -+ * UTRACE_ATTACH_CREATE: -+ * Create a new engine. If %UTRACE_ATTACH_CREATE is not specified, you -+ * only look up an existing engine already attached to the thread. -+ * -+ * UTRACE_ATTACH_EXCLUSIVE: -+ * Attempting to attach a second (matching) engine fails with -%EEXIST. -+ * -+ * UTRACE_ATTACH_MATCH_OPS: Only consider engines matching @ops. -+ * UTRACE_ATTACH_MATCH_DATA: Only consider engines matching @data. -+ * -+ * Calls with neither %UTRACE_ATTACH_MATCH_OPS nor %UTRACE_ATTACH_MATCH_DATA -+ * match the first among any engines attached to @target. That means that -+ * %UTRACE_ATTACH_EXCLUSIVE in such a call fails with -%EEXIST if there -+ * are any engines on @target at all. -+ */ -+struct utrace_engine *utrace_attach_task( -+ struct task_struct *target, int flags, -+ const struct utrace_engine_ops *ops, void *data) -+{ -+ struct utrace *utrace = task_utrace_struct(target); -+ struct utrace_engine *engine; -+ int ret; -+ -+ if (!(flags & UTRACE_ATTACH_CREATE)) { -+ if (unlikely(!utrace)) -+ return ERR_PTR(-ENOENT); -+ spin_lock(&utrace->lock); -+ engine = find_matching_engine(utrace, flags, ops, data); -+ if (engine) -+ utrace_engine_get(engine); -+ spin_unlock(&utrace->lock); -+ return engine ?: ERR_PTR(-ENOENT); -+ } -+ -+ if (unlikely(!ops) || unlikely(ops == &utrace_detached_ops)) -+ return ERR_PTR(-EINVAL); -+ -+ if (unlikely(target->flags & PF_KTHREAD)) -+ /* -+ * Silly kernel, utrace is for users! -+ */ -+ return ERR_PTR(-EPERM); -+ -+ if (!utrace) { -+ if (unlikely(!utrace_task_alloc(target))) -+ return ERR_PTR(-ENOMEM); -+ utrace = task_utrace_struct(target); -+ } -+ -+ engine = kmem_cache_alloc(utrace_engine_cachep, GFP_KERNEL); -+ if (unlikely(!engine)) -+ return ERR_PTR(-ENOMEM); -+ -+ /* -+ * Initialize the new engine structure. It starts out with one ref -+ * to return. utrace_add_engine() adds another for being attached. -+ */ -+ kref_init(&engine->kref); -+ engine->flags = 0; -+ engine->ops = ops; -+ engine->data = data; -+ engine->release = ops->release; -+ -+ ret = utrace_add_engine(target, utrace, engine, flags, ops, data); -+ -+ if (unlikely(ret)) { -+ kmem_cache_free(utrace_engine_cachep, engine); -+ engine = ERR_PTR(ret); -+ } -+ -+ -+ return engine; -+} -+EXPORT_SYMBOL_GPL(utrace_attach_task); -+ -+/** -+ * utrace_attach_pid - attach new engine, or look up an attached engine -+ * @pid: &struct pid pointer representing thread to attach to -+ * @flags: flag bits combined with OR, see utrace_attach_task() -+ * @ops: callback table for new engine -+ * @data: engine private data pointer -+ * -+ * This is the same as utrace_attach_task(), but takes a &struct pid -+ * pointer rather than a &struct task_struct pointer. The caller must -+ * hold a ref on @pid, but does not need to worry about the task -+ * staying valid. If it's been reaped so that @pid points nowhere, -+ * then this call returns -%ESRCH. -+ */ -+struct utrace_engine *utrace_attach_pid( -+ struct pid *pid, int flags, -+ const struct utrace_engine_ops *ops, void *data) -+{ -+ struct utrace_engine *engine = ERR_PTR(-ESRCH); -+ struct task_struct *task = get_pid_task(pid, PIDTYPE_PID); -+ if (task) { -+ engine = utrace_attach_task(task, flags, ops, data); -+ put_task_struct(task); -+ } -+ return engine; -+} -+EXPORT_SYMBOL_GPL(utrace_attach_pid); -+ -+/* -+ * When an engine is detached, the target thread may still see it and -+ * make callbacks until it quiesces. We install a special ops vector -+ * with these two callbacks. When the target thread quiesces, it can -+ * safely free the engine itself. For any event we will always get -+ * the report_quiesce() callback first, so we only need this one -+ * pointer to be set. The only exception is report_reap(), so we -+ * supply that callback too. -+ */ -+static u32 utrace_detached_quiesce(u32 action, struct utrace_engine *engine, -+ unsigned long event) -+{ -+ return UTRACE_DETACH; -+} -+ -+static void utrace_detached_reap(struct utrace_engine *engine, -+ struct task_struct *task) -+{ -+} -+ -+static const struct utrace_engine_ops utrace_detached_ops = { -+ .report_quiesce = &utrace_detached_quiesce, -+ .report_reap = &utrace_detached_reap -+}; -+ -+/* -+ * The caller has to hold a ref on the engine. If the attached flag is -+ * true (all but utrace_barrier() calls), the engine is supposed to be -+ * attached. If the attached flag is false (utrace_barrier() only), -+ * then return -ERESTARTSYS for an engine marked for detach but not yet -+ * fully detached. The task pointer can be invalid if the engine is -+ * detached. -+ * -+ * Get the utrace lock for the target task. -+ * Returns the struct if locked, or ERR_PTR(-errno). -+ * -+ * This has to be robust against races with: -+ * utrace_control(target, UTRACE_DETACH) calls -+ * UTRACE_DETACH after reports -+ * utrace_report_death -+ * utrace_release_task -+ */ -+static struct utrace *get_utrace_lock(struct task_struct *target, -+ struct utrace_engine *engine, -+ bool attached) -+ __acquires(utrace->lock) -+{ -+ struct utrace *utrace; -+ -+ rcu_read_lock(); -+ -+ /* -+ * If this engine was already detached, bail out before we look at -+ * the task_struct pointer at all. If it's detached after this -+ * check, then RCU is still keeping this task_struct pointer valid. -+ * -+ * The ops pointer is NULL when the engine is fully detached. -+ * It's &utrace_detached_ops when it's marked detached but still -+ * on the list. In the latter case, utrace_barrier() still works, -+ * since the target might be in the middle of an old callback. -+ */ -+ if (unlikely(!engine->ops)) { -+ rcu_read_unlock(); -+ return ERR_PTR(-ESRCH); -+ } -+ -+ if (unlikely(engine->ops == &utrace_detached_ops)) { -+ rcu_read_unlock(); -+ return attached ? ERR_PTR(-ESRCH) : ERR_PTR(-ERESTARTSYS); -+ } -+ -+ utrace = task_utrace_struct(target); -+ spin_lock(&utrace->lock); -+ if (unlikely(utrace->reap) || unlikely(!engine->ops) || -+ unlikely(engine->ops == &utrace_detached_ops)) { -+ /* -+ * By the time we got the utrace lock, -+ * it had been reaped or detached already. -+ */ -+ spin_unlock(&utrace->lock); -+ utrace = ERR_PTR(-ESRCH); -+ if (!attached && engine->ops == &utrace_detached_ops) -+ utrace = ERR_PTR(-ERESTARTSYS); -+ } -+ rcu_read_unlock(); -+ -+ return utrace; -+} -+ -+/* -+ * Now that we don't hold any locks, run through any -+ * detached engines and free their references. Each -+ * engine had one implicit ref while it was attached. -+ */ -+static void put_detached_list(struct list_head *list) -+{ -+ struct utrace_engine *engine, *next; -+ list_for_each_entry_safe(engine, next, list, entry) { -+ list_del_init(&engine->entry); -+ utrace_engine_put(engine); -+ } -+} -+ -+/* -+ * We use an extra bit in utrace_engine.flags past the event bits, -+ * to record whether the engine is keeping the target thread stopped. -+ * -+ * This bit is set in task_struct.utrace_flags whenever it is set in any -+ * engine's flags. Only utrace_reset() resets it in utrace_flags. -+ */ -+#define ENGINE_STOP (1UL << _UTRACE_NEVENTS) -+ -+static void mark_engine_wants_stop(struct task_struct *task, -+ struct utrace_engine *engine) -+{ -+ engine->flags |= ENGINE_STOP; -+ task->utrace_flags |= ENGINE_STOP; -+} -+ -+static void clear_engine_wants_stop(struct utrace_engine *engine) -+{ -+ engine->flags &= ~ENGINE_STOP; -+} -+ -+static bool engine_wants_stop(struct utrace_engine *engine) -+{ -+ return (engine->flags & ENGINE_STOP) != 0; -+} -+ -+/** -+ * utrace_set_events - choose which event reports a tracing engine gets -+ * @target: thread to affect -+ * @engine: attached engine to affect -+ * @events: new event mask -+ * -+ * This changes the set of events for which @engine wants callbacks made. -+ * -+ * This fails with -%EALREADY and does nothing if you try to clear -+ * %UTRACE_EVENT(%DEATH) when the @report_death callback may already have -+ * begun, or if you try to newly set %UTRACE_EVENT(%DEATH) or -+ * %UTRACE_EVENT(%QUIESCE) when @target is already dead or dying. -+ * -+ * This fails with -%ESRCH if you try to clear %UTRACE_EVENT(%REAP) when -+ * the @report_reap callback may already have begun, or when @target has -+ * already been detached, including forcible detach on reaping. -+ * -+ * If @target was stopped before the call, then after a successful call, -+ * no event callbacks not requested in @events will be made; if -+ * %UTRACE_EVENT(%QUIESCE) is included in @events, then a -+ * @report_quiesce callback will be made when @target resumes. -+ * -+ * If @target was not stopped and @events excludes some bits that were -+ * set before, this can return -%EINPROGRESS to indicate that @target -+ * may have been making some callback to @engine. When this returns -+ * zero, you can be sure that no event callbacks you've disabled in -+ * @events can be made. If @events only sets new bits that were not set -+ * before on @engine, then -%EINPROGRESS will never be returned. -+ * -+ * To synchronize after an -%EINPROGRESS return, see utrace_barrier(). -+ * -+ * When @target is @current, -%EINPROGRESS is not returned. But note -+ * that a newly-created engine will not receive any callbacks related to -+ * an event notification already in progress. This call enables @events -+ * callbacks to be made as soon as @engine becomes eligible for any -+ * callbacks, see utrace_attach_task(). -+ * -+ * These rules provide for coherent synchronization based on %UTRACE_STOP, -+ * even when %SIGKILL is breaking its normal simple rules. -+ */ -+int utrace_set_events(struct task_struct *target, -+ struct utrace_engine *engine, -+ unsigned long events) -+{ -+ struct utrace *utrace; -+ unsigned long old_flags, old_utrace_flags; -+ int ret = -EALREADY; -+ -+ /* -+ * We just ignore the internal bit, so callers can use -+ * engine->flags to seed bitwise ops for our argument. -+ */ -+ events &= ~ENGINE_STOP; -+ -+ utrace = get_utrace_lock(target, engine, true); -+ if (unlikely(IS_ERR(utrace))) -+ return PTR_ERR(utrace); -+ -+ old_utrace_flags = target->utrace_flags; -+ old_flags = engine->flags & ~ENGINE_STOP; -+ -+ /* -+ * If utrace_report_death() is already progress now, -+ * it's too late to clear the death event bits. -+ */ -+ if (((old_flags & ~events) & _UTRACE_DEATH_EVENTS) && utrace->death) -+ goto unlock; -+ -+ /* -+ * When setting these flags, it's essential that we really -+ * synchronize with exit_notify(). They cannot be set after -+ * exit_notify() takes the tasklist_lock. By holding the read -+ * lock here while setting the flags, we ensure that the calls -+ * to tracehook_notify_death() and tracehook_report_death() will -+ * see the new flags. This ensures that utrace_release_task() -+ * knows positively that utrace_report_death() will be called or -+ * that it won't. -+ */ -+ if ((events & ~old_flags) & _UTRACE_DEATH_EVENTS) { -+ read_lock(&tasklist_lock); -+ if (unlikely(target->exit_state)) { -+ read_unlock(&tasklist_lock); -+ goto unlock; -+ } -+ target->utrace_flags |= events; -+ read_unlock(&tasklist_lock); -+ } -+ -+ engine->flags = events | (engine->flags & ENGINE_STOP); -+ target->utrace_flags |= events; -+ -+ if ((events & UTRACE_EVENT_SYSCALL) && -+ !(old_utrace_flags & UTRACE_EVENT_SYSCALL)) -+ set_tsk_thread_flag(target, TIF_SYSCALL_TRACE); -+ -+ ret = 0; -+ if ((old_flags & ~events) && target != current && -+ !task_is_stopped_or_traced(target) && !target->exit_state) { -+ /* -+ * This barrier ensures that our engine->flags changes -+ * have hit before we examine utrace->reporting, -+ * pairing with the barrier in start_callback(). If -+ * @target has not yet hit finish_callback() to clear -+ * utrace->reporting, we might be in the middle of a -+ * callback to @engine. -+ */ -+ smp_mb(); -+ if (utrace->reporting == engine) -+ ret = -EINPROGRESS; -+ } -+unlock: -+ spin_unlock(&utrace->lock); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(utrace_set_events); -+ -+/* -+ * Asynchronously mark an engine as being detached. -+ * -+ * This must work while the target thread races with us doing -+ * start_callback(), defined below. It uses smp_rmb() between checking -+ * @engine->flags and using @engine->ops. Here we change @engine->ops -+ * first, then use smp_wmb() before changing @engine->flags. This ensures -+ * it can check the old flags before using the old ops, or check the old -+ * flags before using the new ops, or check the new flags before using the -+ * new ops, but can never check the new flags before using the old ops. -+ * Hence, utrace_detached_ops might be used with any old flags in place. -+ * It has report_quiesce() and report_reap() callbacks to handle all cases. -+ */ -+static void mark_engine_detached(struct utrace_engine *engine) -+{ -+ engine->ops = &utrace_detached_ops; -+ smp_wmb(); -+ engine->flags = UTRACE_EVENT(QUIESCE); -+} -+ -+/* -+ * Get @target to stop and return true if it is already stopped now. -+ * If we return false, it will make some event callback soonish. -+ * Called with @utrace locked. -+ */ -+static bool utrace_do_stop(struct task_struct *target, struct utrace *utrace) -+{ -+ if (task_is_stopped(target)) { -+ /* -+ * Stopped is considered quiescent; when it wakes up, it will -+ * go through utrace_finish_stop() before doing anything else. -+ */ -+ spin_lock_irq(&target->sighand->siglock); -+ if (likely(task_is_stopped(target))) -+ __set_task_state(target, TASK_TRACED); -+ spin_unlock_irq(&target->sighand->siglock); -+ } else if (utrace->resume > UTRACE_REPORT) { -+ utrace->resume = UTRACE_REPORT; -+ set_notify_resume(target); -+ } -+ -+ return task_is_traced(target); -+} -+ -+/* -+ * If the target is not dead it should not be in tracing -+ * stop any more. Wake it unless it's in job control stop. -+ */ -+static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) -+{ -+ lockdep_assert_held(&utrace->lock); -+ spin_lock_irq(&target->sighand->siglock); -+ if (target->signal->flags & SIGNAL_STOP_STOPPED || -+ target->signal->group_stop_count) -+ target->state = TASK_STOPPED; -+ else -+ wake_up_state(target, __TASK_TRACED); -+ spin_unlock_irq(&target->sighand->siglock); -+} -+ -+/* -+ * This is called when there might be some detached engines on the list or -+ * some stale bits in @task->utrace_flags. Clean them up and recompute the -+ * flags. Returns true if we're now fully detached. -+ * -+ * Called with @utrace->lock held, returns with it released. -+ * After this returns, @utrace might be freed if everything detached. -+ */ -+static bool utrace_reset(struct task_struct *task, struct utrace *utrace) -+ __releases(utrace->lock) -+{ -+ struct utrace_engine *engine, *next; -+ unsigned long flags = 0; -+ LIST_HEAD(detached); -+ -+ splice_attaching(utrace); -+ -+ /* -+ * Update the set of events of interest from the union -+ * of the interests of the remaining tracing engines. -+ * For any engine marked detached, remove it from the list. -+ * We'll collect them on the detached list. -+ */ -+ list_for_each_entry_safe(engine, next, &utrace->attached, entry) { -+ if (engine->ops == &utrace_detached_ops) { -+ engine->ops = NULL; -+ list_move(&engine->entry, &detached); -+ } else { -+ flags |= engine->flags | UTRACE_EVENT(REAP); -+ } -+ } -+ -+ if (task->exit_state) { -+ /* -+ * Once it's already dead, we never install any flags -+ * except REAP. When ->exit_state is set and events -+ * like DEATH are not set, then they never can be set. -+ * This ensures that utrace_release_task() knows -+ * positively that utrace_report_death() can never run. -+ */ -+ BUG_ON(utrace->death); -+ flags &= UTRACE_EVENT(REAP); -+ } else if (!(flags & UTRACE_EVENT_SYSCALL) && -+ test_tsk_thread_flag(task, TIF_SYSCALL_TRACE)) { -+ clear_tsk_thread_flag(task, TIF_SYSCALL_TRACE); -+ } -+ -+ if (!flags) { -+ /* -+ * No more engines, cleared out the utrace. -+ */ -+ utrace->resume = UTRACE_RESUME; -+ utrace->signal_handler = 0; -+ } -+ -+ /* -+ * If no more engines want it stopped, wake it up. -+ */ -+ if (task_is_traced(task) && !(flags & ENGINE_STOP)) { -+ /* -+ * It just resumes, so make sure single-step -+ * is not left set. -+ */ -+ if (utrace->resume == UTRACE_RESUME) -+ user_disable_single_step(task); -+ utrace_wakeup(task, utrace); -+ } -+ -+ /* -+ * In theory spin_lock() doesn't imply rcu_read_lock(). -+ * Once we clear ->utrace_flags this task_struct can go away -+ * because tracehook_prepare_release_task() path does not take -+ * utrace->lock when ->utrace_flags == 0. -+ */ -+ rcu_read_lock(); -+ task->utrace_flags = flags; -+ spin_unlock(&utrace->lock); -+ rcu_read_unlock(); -+ -+ put_detached_list(&detached); -+ -+ return !flags; -+} -+ -+void utrace_finish_stop(void) -+{ -+ /* -+ * If we were task_is_traced() and then SIGKILL'ed, make -+ * sure we do nothing until the tracer drops utrace->lock. -+ */ -+ if (unlikely(__fatal_signal_pending(current))) { -+ struct utrace *utrace = task_utrace_struct(current); -+ spin_unlock_wait(&utrace->lock); -+ } -+} -+ -+/* -+ * Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up. -+ * @task == current, @utrace == current->utrace, which is not locked. -+ * Return true if we were woken up by SIGKILL even though some utrace -+ * engine may still want us to stay stopped. -+ */ -+static void utrace_stop(struct task_struct *task, struct utrace *utrace, -+ enum utrace_resume_action action) -+{ -+relock: -+ spin_lock(&utrace->lock); -+ -+ if (action < utrace->resume) { -+ /* -+ * Ensure a reporting pass when we're resumed. -+ */ -+ utrace->resume = action; -+ if (action == UTRACE_INTERRUPT) -+ set_thread_flag(TIF_SIGPENDING); -+ else -+ set_thread_flag(TIF_NOTIFY_RESUME); -+ } -+ -+ /* -+ * If the ENGINE_STOP bit is clear in utrace_flags, that means -+ * utrace_reset() ran after we processed some UTRACE_STOP return -+ * values from callbacks to get here. If all engines have detached -+ * or resumed us, we don't stop. This check doesn't require -+ * siglock, but it should follow the interrupt/report bookkeeping -+ * steps (this can matter for UTRACE_RESUME but not UTRACE_DETACH). -+ */ -+ if (unlikely(!(task->utrace_flags & ENGINE_STOP))) { -+ utrace_reset(task, utrace); -+ if (task->utrace_flags & ENGINE_STOP) -+ goto relock; -+ return; -+ } -+ -+ /* -+ * The siglock protects us against signals. As well as SIGKILL -+ * waking us up, we must synchronize with the signal bookkeeping -+ * for stop signals and SIGCONT. -+ */ -+ spin_lock_irq(&task->sighand->siglock); -+ -+ if (unlikely(__fatal_signal_pending(task))) { -+ spin_unlock_irq(&task->sighand->siglock); -+ spin_unlock(&utrace->lock); -+ return; -+ } -+ -+ __set_current_state(TASK_TRACED); -+ -+ /* -+ * If there is a group stop in progress, -+ * we must participate in the bookkeeping. -+ */ -+ if (unlikely(task->signal->group_stop_count) && -+ !--task->signal->group_stop_count) -+ task->signal->flags = SIGNAL_STOP_STOPPED; -+ -+ spin_unlock_irq(&task->sighand->siglock); -+ spin_unlock(&utrace->lock); -+ -+ schedule(); -+ -+ utrace_finish_stop(); -+ -+ /* -+ * While in TASK_TRACED, we were considered "frozen enough". -+ * Now that we woke up, it's crucial if we're supposed to be -+ * frozen that we freeze now before running anything substantial. -+ */ -+ try_to_freeze(); -+ -+ /* -+ * While we were in TASK_TRACED, complete_signal() considered -+ * us "uninterested" in signal wakeups. Now make sure our -+ * TIF_SIGPENDING state is correct for normal running. -+ */ -+ spin_lock_irq(&task->sighand->siglock); -+ recalc_sigpending(); -+ spin_unlock_irq(&task->sighand->siglock); -+} -+ -+/* -+ * Called by release_task() with @reap set to true. -+ * Called by utrace_report_death() with @reap set to false. -+ * On reap, make report_reap callbacks and clean out @utrace -+ * unless still making callbacks. On death, update bookkeeping -+ * and handle the reap work if release_task() came in first. -+ */ -+void utrace_maybe_reap(struct task_struct *target, struct utrace *utrace, -+ bool reap) -+{ -+ struct utrace_engine *engine, *next; -+ struct list_head attached; -+ -+ spin_lock(&utrace->lock); -+ -+ if (reap) { -+ /* -+ * If the target will do some final callbacks but hasn't -+ * finished them yet, we know because it clears these event -+ * bits after it's done. Instead of cleaning up here and -+ * requiring utrace_report_death() to cope with it, we -+ * delay the REAP report and the teardown until after the -+ * target finishes its death reports. -+ */ -+ utrace->reap = 1; -+ -+ if (target->utrace_flags & _UTRACE_DEATH_EVENTS) { -+ spin_unlock(&utrace->lock); -+ return; -+ } -+ } else { -+ /* -+ * After we unlock with this flag clear, any competing -+ * utrace_control/utrace_set_events calls know that we've -+ * finished our callbacks and any detach bookkeeping. -+ */ -+ utrace->death = 0; -+ -+ if (!utrace->reap) { -+ /* -+ * We're just dead, not reaped yet. This will -+ * reset @target->utrace_flags so the later call -+ * with @reap set won't hit the check above. -+ */ -+ utrace_reset(target, utrace); -+ return; -+ } -+ } -+ -+ /* -+ * utrace_add_engine() checks ->utrace_flags != 0. Since -+ * @utrace->reap is set, nobody can set or clear UTRACE_EVENT(REAP) -+ * in @engine->flags or change @engine->ops and nobody can change -+ * @utrace->attached after we drop the lock. -+ */ -+ target->utrace_flags = 0; -+ -+ /* -+ * We clear out @utrace->attached before we drop the lock so -+ * that find_matching_engine() can't come across any old engine -+ * while we are busy tearing it down. -+ */ -+ list_replace_init(&utrace->attached, &attached); -+ list_splice_tail_init(&utrace->attaching, &attached); -+ -+ spin_unlock(&utrace->lock); -+ -+ list_for_each_entry_safe(engine, next, &attached, entry) { -+ if (engine->flags & UTRACE_EVENT(REAP)) -+ engine->ops->report_reap(engine, target); -+ -+ engine->ops = NULL; -+ engine->flags = 0; -+ list_del_init(&engine->entry); -+ -+ utrace_engine_put(engine); -+ } -+} -+ -+/* -+ * You can't do anything to a dead task but detach it. -+ * If release_task() has been called, you can't do that. -+ * -+ * On the exit path, DEATH and QUIESCE event bits are set only -+ * before utrace_report_death() has taken the lock. At that point, -+ * the death report will come soon, so disallow detach until it's -+ * done. This prevents us from racing with it detaching itself. -+ * -+ * Called only when @target->exit_state is nonzero. -+ */ -+static inline int utrace_control_dead(struct task_struct *target, -+ struct utrace *utrace, -+ enum utrace_resume_action action) -+{ -+ lockdep_assert_held(&utrace->lock); -+ -+ if (action != UTRACE_DETACH || unlikely(utrace->reap)) -+ return -ESRCH; -+ -+ if (unlikely(utrace->death)) -+ /* -+ * We have already started the death report. We can't -+ * prevent the report_death and report_reap callbacks, -+ * so tell the caller they will happen. -+ */ -+ return -EALREADY; -+ -+ return 0; -+} -+ -+/** -+ * utrace_control - control a thread being traced by a tracing engine -+ * @target: thread to affect -+ * @engine: attached engine to affect -+ * @action: &enum utrace_resume_action for thread to do -+ * -+ * This is how a tracing engine asks a traced thread to do something. -+ * This call is controlled by the @action argument, which has the -+ * same meaning as the &enum utrace_resume_action value returned by -+ * event reporting callbacks. -+ * -+ * If @target is already dead (@target->exit_state nonzero), -+ * all actions except %UTRACE_DETACH fail with -%ESRCH. -+ * -+ * The following sections describe each option for the @action argument. -+ * -+ * UTRACE_DETACH: -+ * -+ * After this, the @engine data structure is no longer accessible, -+ * and the thread might be reaped. The thread will start running -+ * again if it was stopped and no longer has any attached engines -+ * that want it stopped. -+ * -+ * If the @report_reap callback may already have begun, this fails -+ * with -%ESRCH. If the @report_death callback may already have -+ * begun, this fails with -%EALREADY. -+ * -+ * If @target is not already stopped, then a callback to this engine -+ * might be in progress or about to start on another CPU. If so, -+ * then this returns -%EINPROGRESS; the detach happens as soon as -+ * the pending callback is finished. To synchronize after an -+ * -%EINPROGRESS return, see utrace_barrier(). -+ * -+ * If @target is properly stopped before utrace_control() is called, -+ * then after successful return it's guaranteed that no more callbacks -+ * to the @engine->ops vector will be made. -+ * -+ * The only exception is %SIGKILL (and exec or group-exit by another -+ * thread in the group), which can cause asynchronous @report_death -+ * and/or @report_reap callbacks even when %UTRACE_STOP was used. -+ * (In that event, this fails with -%ESRCH or -%EALREADY, see above.) -+ * -+ * UTRACE_STOP: -+ * -+ * This asks that @target stop running. This returns 0 only if -+ * @target is already stopped, either for tracing or for job -+ * control. Then @target will remain stopped until another -+ * utrace_control() call is made on @engine; @target can be woken -+ * only by %SIGKILL (or equivalent, such as exec or termination by -+ * another thread in the same thread group). -+ * -+ * This returns -%EINPROGRESS if @target is not already stopped. -+ * Then the effect is like %UTRACE_REPORT. A @report_quiesce or -+ * @report_signal callback will be made soon. Your callback can -+ * then return %UTRACE_STOP to keep @target stopped. -+ * -+ * This does not interrupt system calls in progress, including ones -+ * that sleep for a long time. For that, use %UTRACE_INTERRUPT. -+ * To interrupt system calls and then keep @target stopped, your -+ * @report_signal callback can return %UTRACE_STOP. -+ * -+ * UTRACE_RESUME: -+ * -+ * Just let @target continue running normally, reversing the effect -+ * of a previous %UTRACE_STOP. If another engine is keeping @target -+ * stopped, then it remains stopped until all engines let it resume. -+ * If @target was not stopped, this has no effect. -+ * -+ * UTRACE_REPORT: -+ * -+ * This is like %UTRACE_RESUME, but also ensures that there will be -+ * a @report_quiesce or @report_signal callback made soon. If -+ * @target had been stopped, then there will be a callback before it -+ * resumes running normally. If another engine is keeping @target -+ * stopped, then there might be no callbacks until all engines let -+ * it resume. -+ * -+ * Since this is meaningless unless @report_quiesce callbacks will -+ * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). -+ * -+ * UTRACE_INTERRUPT: -+ * -+ * This is like %UTRACE_REPORT, but ensures that @target will make a -+ * @report_signal callback before it resumes or delivers signals. -+ * If @target was in a system call or about to enter one, work in -+ * progress will be interrupted as if by %SIGSTOP. If another -+ * engine is keeping @target stopped, then there might be no -+ * callbacks until all engines let it resume. -+ * -+ * This gives @engine an opportunity to introduce a forced signal -+ * disposition via its @report_signal callback. -+ * -+ * UTRACE_SINGLESTEP: -+ * -+ * It's invalid to use this unless arch_has_single_step() returned true. -+ * This is like %UTRACE_RESUME, but resumes for one user instruction only. -+ * -+ * Note that passing %UTRACE_SINGLESTEP or %UTRACE_BLOCKSTEP to -+ * utrace_control() or returning it from an event callback alone does -+ * not necessarily ensure that stepping will be enabled. If there are -+ * more callbacks made to any engine before returning to user mode, -+ * then the resume action is chosen only by the last set of callbacks. -+ * To be sure, enable %UTRACE_EVENT(%QUIESCE) and look for the -+ * @report_quiesce callback with a zero event mask, or the -+ * @report_signal callback with %UTRACE_SIGNAL_REPORT. -+ * -+ * Since this is not robust unless @report_quiesce callbacks will -+ * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). -+ * -+ * UTRACE_BLOCKSTEP: -+ * -+ * It's invalid to use this unless arch_has_block_step() returned true. -+ * This is like %UTRACE_SINGLESTEP, but resumes for one whole basic -+ * block of user instructions. -+ * -+ * Since this is not robust unless @report_quiesce callbacks will -+ * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). -+ * -+ * %UTRACE_BLOCKSTEP devolves to %UTRACE_SINGLESTEP when another -+ * tracing engine is using %UTRACE_SINGLESTEP at the same time. -+ */ -+int utrace_control(struct task_struct *target, -+ struct utrace_engine *engine, -+ enum utrace_resume_action action) -+{ -+ struct utrace *utrace; -+ bool reset; -+ int ret; -+ -+ if (unlikely(action >= UTRACE_RESUME_MAX)) { -+ WARN(1, "invalid action argument to utrace_control()!"); -+ return -EINVAL; -+ } -+ -+ /* -+ * This is a sanity check for a programming error in the caller. -+ * Their request can only work properly in all cases by relying on -+ * a follow-up callback, but they didn't set one up! This check -+ * doesn't do locking, but it shouldn't matter. The caller has to -+ * be synchronously sure the callback is set up to be operating the -+ * interface properly. -+ */ -+ if (action >= UTRACE_REPORT && action < UTRACE_RESUME && -+ unlikely(!(engine->flags & UTRACE_EVENT(QUIESCE)))) { -+ WARN(1, "utrace_control() with no QUIESCE callback in place!"); -+ return -EINVAL; -+ } -+ -+ utrace = get_utrace_lock(target, engine, true); -+ if (unlikely(IS_ERR(utrace))) -+ return PTR_ERR(utrace); -+ -+ reset = task_is_traced(target); -+ ret = 0; -+ -+ /* -+ * ->exit_state can change under us, this doesn't matter. -+ * We do not care about ->exit_state in fact, but we do -+ * care about ->reap and ->death. If either flag is set, -+ * we must also see ->exit_state != 0. -+ */ -+ if (unlikely(target->exit_state)) { -+ ret = utrace_control_dead(target, utrace, action); -+ if (ret) { -+ spin_unlock(&utrace->lock); -+ return ret; -+ } -+ reset = true; -+ } -+ -+ switch (action) { -+ case UTRACE_STOP: -+ mark_engine_wants_stop(target, engine); -+ if (!reset && !utrace_do_stop(target, utrace)) -+ ret = -EINPROGRESS; -+ reset = false; -+ break; -+ -+ case UTRACE_DETACH: -+ if (engine_wants_stop(engine)) -+ target->utrace_flags &= ~ENGINE_STOP; -+ mark_engine_detached(engine); -+ reset = reset || utrace_do_stop(target, utrace); -+ if (!reset) { -+ /* -+ * As in utrace_set_events(), this barrier ensures -+ * that our engine->flags changes have hit before we -+ * examine utrace->reporting, pairing with the barrier -+ * in start_callback(). If @target has not yet hit -+ * finish_callback() to clear utrace->reporting, we -+ * might be in the middle of a callback to @engine. -+ */ -+ smp_mb(); -+ if (utrace->reporting == engine) -+ ret = -EINPROGRESS; -+ } -+ break; -+ -+ case UTRACE_RESUME: -+ clear_engine_wants_stop(engine); -+ break; -+ -+ case UTRACE_BLOCKSTEP: -+ /* -+ * Resume from stopped, step one block. -+ * We fall through to treat it like UTRACE_SINGLESTEP. -+ */ -+ if (unlikely(!arch_has_block_step())) { -+ WARN(1, "UTRACE_BLOCKSTEP when !arch_has_block_step()"); -+ action = UTRACE_SINGLESTEP; -+ } -+ -+ case UTRACE_SINGLESTEP: -+ /* -+ * Resume from stopped, step one instruction. -+ * We fall through to the UTRACE_REPORT case. -+ */ -+ if (unlikely(!arch_has_single_step())) { -+ WARN(1, -+ "UTRACE_SINGLESTEP when !arch_has_single_step()"); -+ reset = false; -+ ret = -EOPNOTSUPP; -+ break; -+ } -+ -+ case UTRACE_REPORT: -+ /* -+ * Make the thread call tracehook_notify_resume() soon. -+ * But don't bother if it's already been interrupted. -+ * In that case, utrace_get_signal() will be reporting soon. -+ */ -+ clear_engine_wants_stop(engine); -+ if (action < utrace->resume) { -+ utrace->resume = action; -+ set_notify_resume(target); -+ } -+ break; -+ -+ case UTRACE_INTERRUPT: -+ /* -+ * Make the thread call tracehook_get_signal() soon. -+ */ -+ clear_engine_wants_stop(engine); -+ if (utrace->resume == UTRACE_INTERRUPT) -+ break; -+ utrace->resume = UTRACE_INTERRUPT; -+ -+ /* -+ * If it's not already stopped, interrupt it now. We need -+ * the siglock here in case it calls recalc_sigpending() -+ * and clears its own TIF_SIGPENDING. By taking the lock, -+ * we've serialized any later recalc_sigpending() after our -+ * setting of utrace->resume to force it on. -+ */ -+ if (reset) { -+ /* -+ * This is really just to keep the invariant that -+ * TIF_SIGPENDING is set with UTRACE_INTERRUPT. -+ * When it's stopped, we know it's always going -+ * through utrace_get_signal() and will recalculate. -+ */ -+ set_tsk_thread_flag(target, TIF_SIGPENDING); -+ } else { -+ struct sighand_struct *sighand; -+ unsigned long irqflags; -+ sighand = lock_task_sighand(target, &irqflags); -+ if (likely(sighand)) { -+ signal_wake_up(target, 0); -+ unlock_task_sighand(target, &irqflags); -+ } -+ } -+ break; -+ -+ default: -+ BUG(); /* We checked it on entry. */ -+ } -+ -+ /* -+ * Let the thread resume running. If it's not stopped now, -+ * there is nothing more we need to do. -+ */ -+ if (reset) -+ utrace_reset(target, utrace); -+ else -+ spin_unlock(&utrace->lock); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(utrace_control); -+ -+/** -+ * utrace_barrier - synchronize with simultaneous tracing callbacks -+ * @target: thread to affect -+ * @engine: engine to affect (can be detached) -+ * -+ * This blocks while @target might be in the midst of making a callback to -+ * @engine. It can be interrupted by signals and will return -%ERESTARTSYS. -+ * A return value of zero means no callback from @target to @engine was -+ * in progress. Any effect of its return value (such as %UTRACE_STOP) has -+ * already been applied to @engine. -+ * -+ * It's not necessary to keep the @target pointer alive for this call. -+ * It's only necessary to hold a ref on @engine. This will return -+ * safely even if @target has been reaped and has no task refs. -+ * -+ * A successful return from utrace_barrier() guarantees its ordering -+ * with respect to utrace_set_events() and utrace_control() calls. If -+ * @target was not properly stopped, event callbacks just disabled might -+ * still be in progress; utrace_barrier() waits until there is no chance -+ * an unwanted callback can be in progress. -+ */ -+int utrace_barrier(struct task_struct *target, struct utrace_engine *engine) -+{ -+ struct utrace *utrace; -+ int ret = -ERESTARTSYS; -+ -+ if (unlikely(target == current)) -+ return 0; -+ -+ do { -+ utrace = get_utrace_lock(target, engine, false); -+ if (unlikely(IS_ERR(utrace))) { -+ ret = PTR_ERR(utrace); -+ if (ret != -ERESTARTSYS) -+ break; -+ } else { -+ /* -+ * All engine state changes are done while -+ * holding the lock, i.e. before we get here. -+ * Since we have the lock, we only need to -+ * worry about @target making a callback. -+ * When it has entered start_callback() but -+ * not yet gotten to finish_callback(), we -+ * will see utrace->reporting == @engine. -+ * When @target doesn't take the lock, it uses -+ * barriers to order setting utrace->reporting -+ * before it examines the engine state. -+ */ -+ if (utrace->reporting != engine) -+ ret = 0; -+ spin_unlock(&utrace->lock); -+ if (!ret) -+ break; -+ } -+ schedule_timeout_interruptible(1); -+ } while (!signal_pending(current)); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(utrace_barrier); -+ -+/* -+ * This is local state used for reporting loops, perhaps optimized away. -+ */ -+struct utrace_report { -+ u32 result; -+ enum utrace_resume_action action; -+ enum utrace_resume_action resume_action; -+ bool detaches; -+ bool spurious; -+}; -+ -+#define INIT_REPORT(var) \ -+ struct utrace_report var = { \ -+ .action = UTRACE_RESUME, \ -+ .resume_action = UTRACE_RESUME, \ -+ .spurious = true \ -+ } -+ -+/* -+ * We are now making the report, so clear the flag saying we need one. -+ * When there is a new attach, ->pending_attach is set just so we will -+ * know to do splice_attaching() here before the callback loop. -+ */ -+static enum utrace_resume_action start_report(struct utrace *utrace) -+{ -+ enum utrace_resume_action resume = utrace->resume; -+ if (utrace->pending_attach || -+ (resume > UTRACE_INTERRUPT && resume < UTRACE_RESUME)) { -+ spin_lock(&utrace->lock); -+ splice_attaching(utrace); -+ resume = utrace->resume; -+ if (resume > UTRACE_INTERRUPT) -+ utrace->resume = UTRACE_RESUME; -+ spin_unlock(&utrace->lock); -+ } -+ return resume; -+} -+ -+static inline void finish_report_reset(struct task_struct *task, -+ struct utrace *utrace, -+ struct utrace_report *report) -+{ -+ if (unlikely(report->spurious || report->detaches)) { -+ spin_lock(&utrace->lock); -+ if (utrace_reset(task, utrace)) -+ report->action = UTRACE_RESUME; -+ } -+} -+ -+/* -+ * Complete a normal reporting pass, pairing with a start_report() call. -+ * This handles any UTRACE_DETACH or UTRACE_REPORT or UTRACE_INTERRUPT -+ * returns from engine callbacks. If @will_not_stop is true and any -+ * engine's last callback used UTRACE_STOP, we do UTRACE_REPORT here to -+ * ensure we stop before user mode. If there were no callbacks made, it -+ * will recompute @task->utrace_flags to avoid another false-positive. -+ */ -+static void finish_report(struct task_struct *task, struct utrace *utrace, -+ struct utrace_report *report, bool will_not_stop) -+{ -+ enum utrace_resume_action resume = report->action; -+ -+ if (resume == UTRACE_STOP) -+ resume = will_not_stop ? UTRACE_REPORT : UTRACE_RESUME; -+ -+ if (resume < utrace->resume) { -+ spin_lock(&utrace->lock); -+ utrace->resume = resume; -+ if (resume == UTRACE_INTERRUPT) -+ set_tsk_thread_flag(task, TIF_SIGPENDING); -+ else -+ set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); -+ spin_unlock(&utrace->lock); -+ } -+ -+ finish_report_reset(task, utrace, report); -+} -+ -+static void finish_callback_report(struct task_struct *task, -+ struct utrace *utrace, -+ struct utrace_report *report, -+ struct utrace_engine *engine, -+ enum utrace_resume_action action) -+{ -+ if (action == UTRACE_DETACH) { -+ /* -+ * By holding the lock here, we make sure that -+ * utrace_barrier() (really get_utrace_lock()) sees the -+ * effect of this detach. Otherwise utrace_barrier() could -+ * return 0 after this callback had returned UTRACE_DETACH. -+ * This way, a 0 return is an unambiguous indicator that any -+ * callback returning UTRACE_DETACH has indeed caused detach. -+ */ -+ spin_lock(&utrace->lock); -+ engine->ops = &utrace_detached_ops; -+ spin_unlock(&utrace->lock); -+ } -+ -+ /* -+ * If utrace_control() was used, treat that like UTRACE_DETACH here. -+ */ -+ if (engine->ops == &utrace_detached_ops) { -+ report->detaches = true; -+ return; -+ } -+ -+ if (action < report->action) -+ report->action = action; -+ -+ if (action != UTRACE_STOP) { -+ if (action < report->resume_action) -+ report->resume_action = action; -+ -+ if (engine_wants_stop(engine)) { -+ spin_lock(&utrace->lock); -+ clear_engine_wants_stop(engine); -+ spin_unlock(&utrace->lock); -+ } -+ -+ return; -+ } -+ -+ if (!engine_wants_stop(engine)) { -+ spin_lock(&utrace->lock); -+ /* -+ * If utrace_control() came in and detached us -+ * before we got the lock, we must not stop now. -+ */ -+ if (unlikely(engine->ops == &utrace_detached_ops)) -+ report->detaches = true; -+ else -+ mark_engine_wants_stop(task, engine); -+ spin_unlock(&utrace->lock); -+ } -+} -+ -+/* -+ * Apply the return value of one engine callback to @report. -+ * Returns true if @engine detached and should not get any more callbacks. -+ */ -+static bool finish_callback(struct task_struct *task, struct utrace *utrace, -+ struct utrace_report *report, -+ struct utrace_engine *engine, -+ u32 ret) -+{ -+ report->result = ret & ~UTRACE_RESUME_MASK; -+ finish_callback_report(task, utrace, report, engine, -+ utrace_resume_action(ret)); -+ -+ /* -+ * Now that we have applied the effect of the return value, -+ * clear this so that utrace_barrier() can stop waiting. -+ * A subsequent utrace_control() can stop or resume @engine -+ * and know this was ordered after its callback's action. -+ * -+ * We don't need any barriers here because utrace_barrier() -+ * takes utrace->lock. If we touched engine->flags above, -+ * the lock guaranteed this change was before utrace_barrier() -+ * examined utrace->reporting. -+ */ -+ utrace->reporting = NULL; -+ -+ /* -+ * We've just done an engine callback. These are allowed to sleep, -+ * though all well-behaved ones restrict that to blocking kalloc() -+ * or quickly-acquired mutex_lock() and the like. This is a good -+ * place to make sure tracing engines don't introduce too much -+ * latency under voluntary preemption. -+ */ -+ might_sleep(); -+ -+ return engine->ops == &utrace_detached_ops; -+} -+ -+/* -+ * Start the callbacks for @engine to consider @event (a bit mask). -+ * This makes the report_quiesce() callback first. If @engine wants -+ * a specific callback for @event, we return the ops vector to use. -+ * If not, we return NULL. The return value from the ops->callback -+ * function called should be passed to finish_callback(). -+ */ -+static const struct utrace_engine_ops *start_callback( -+ struct utrace *utrace, struct utrace_report *report, -+ struct utrace_engine *engine, struct task_struct *task, -+ unsigned long event) -+{ -+ const struct utrace_engine_ops *ops; -+ unsigned long want; -+ -+ /* -+ * This barrier ensures that we've set utrace->reporting before -+ * we examine engine->flags or engine->ops. utrace_barrier() -+ * relies on this ordering to indicate that the effect of any -+ * utrace_control() and utrace_set_events() calls is in place -+ * by the time utrace->reporting can be seen to be NULL. -+ */ -+ utrace->reporting = engine; -+ smp_mb(); -+ -+ /* -+ * This pairs with the barrier in mark_engine_detached(). -+ * It makes sure that we never see the old ops vector with -+ * the new flags, in case the original vector had no report_quiesce. -+ */ -+ want = engine->flags; -+ smp_rmb(); -+ ops = engine->ops; -+ -+ if ((want & UTRACE_EVENT(QUIESCE)) || ops == &utrace_detached_ops) { -+ if (finish_callback(task, utrace, report, engine, -+ (*ops->report_quiesce)(report->action, -+ engine, event))) -+ return NULL; -+ -+ if (!event) { -+ /* We only got here to report QUIESCE */ -+ report->spurious = false; -+ return NULL; -+ } -+ -+ /* -+ * finish_callback() reset utrace->reporting after the -+ * quiesce callback. Now we set it again (as above) -+ * before re-examining engine->flags, which could have -+ * been changed synchronously by ->report_quiesce or -+ * asynchronously by utrace_control() or utrace_set_events(). -+ */ -+ utrace->reporting = engine; -+ smp_mb(); -+ want = engine->flags; -+ } -+ -+ if (want & ENGINE_STOP) -+ report->action = UTRACE_STOP; -+ -+ if (want & event) { -+ report->spurious = false; -+ return ops; -+ } -+ -+ utrace->reporting = NULL; -+ return NULL; -+} -+ -+/* -+ * Do a normal reporting pass for engines interested in @event. -+ * @callback is the name of the member in the ops vector, and remaining -+ * args are the extras it takes after the standard three args. -+ */ -+#define REPORT_CALLBACKS(rev, task, utrace, report, event, callback, ...) \ -+ do { \ -+ struct utrace_engine *engine; \ -+ const struct utrace_engine_ops *ops; \ -+ list_for_each_entry##rev(engine, &utrace->attached, entry) { \ -+ ops = start_callback(utrace, report, engine, task, \ -+ event); \ -+ if (!ops) \ -+ continue; \ -+ finish_callback(task, utrace, report, engine, \ -+ (*ops->callback)(__VA_ARGS__)); \ -+ } \ -+ } while (0) -+#define REPORT(task, utrace, report, event, callback, ...) \ -+ do { \ -+ start_report(utrace); \ -+ REPORT_CALLBACKS(, task, utrace, report, event, callback, \ -+ (report)->action, engine, ## __VA_ARGS__); \ -+ finish_report(task, utrace, report, true); \ -+ } while (0) -+ -+/* -+ * Called iff UTRACE_EVENT(EXEC) flag is set. -+ */ -+void utrace_report_exec(struct linux_binfmt *fmt, struct linux_binprm *bprm, -+ struct pt_regs *regs) -+{ -+ struct task_struct *task = current; -+ struct utrace *utrace = task_utrace_struct(task); -+ INIT_REPORT(report); -+ -+ REPORT(task, utrace, &report, UTRACE_EVENT(EXEC), -+ report_exec, fmt, bprm, regs); -+} -+ -+static u32 do_report_syscall_entry(struct pt_regs *regs, -+ struct task_struct *task, -+ struct utrace *utrace, -+ struct utrace_report *report, -+ u32 resume_report) -+{ -+ start_report(utrace); -+ REPORT_CALLBACKS(_reverse, task, utrace, report, -+ UTRACE_EVENT(SYSCALL_ENTRY), report_syscall_entry, -+ resume_report | report->result | report->action, -+ engine, regs); -+ finish_report(task, utrace, report, false); -+ -+ if (report->action != UTRACE_STOP) -+ return 0; -+ -+ utrace_stop(task, utrace, report->resume_action); -+ -+ if (fatal_signal_pending(task)) { -+ /* -+ * We are continuing despite UTRACE_STOP because of a -+ * SIGKILL. Don't let the system call actually proceed. -+ */ -+ report->result = UTRACE_SYSCALL_ABORT; -+ } else if (utrace->resume <= UTRACE_REPORT) { -+ /* -+ * If we've been asked for another report after our stop, -+ * go back to report (and maybe stop) again before we run -+ * the system call. The second (and later) reports are -+ * marked with the UTRACE_SYSCALL_RESUMED flag so that -+ * engines know this is a second report at the same -+ * entry. This gives them the chance to examine the -+ * registers anew after they might have been changed -+ * while we were stopped. -+ */ -+ report->detaches = false; -+ report->spurious = true; -+ report->action = report->resume_action = UTRACE_RESUME; -+ return UTRACE_SYSCALL_RESUMED; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Called iff UTRACE_EVENT(SYSCALL_ENTRY) flag is set. -+ * Return true to prevent the system call. -+ */ -+bool utrace_report_syscall_entry(struct pt_regs *regs) -+{ -+ struct task_struct *task = current; -+ struct utrace *utrace = task_utrace_struct(task); -+ INIT_REPORT(report); -+ u32 resume_report = 0; -+ -+ do { -+ resume_report = do_report_syscall_entry(regs, task, utrace, -+ &report, resume_report); -+ } while (resume_report); -+ -+ return utrace_syscall_action(report.result) == UTRACE_SYSCALL_ABORT; -+} -+ -+/* -+ * Called iff UTRACE_EVENT(SYSCALL_EXIT) flag is set. -+ */ -+void utrace_report_syscall_exit(struct pt_regs *regs) -+{ -+ struct task_struct *task = current; -+ struct utrace *utrace = task_utrace_struct(task); -+ INIT_REPORT(report); -+ -+ REPORT(task, utrace, &report, UTRACE_EVENT(SYSCALL_EXIT), -+ report_syscall_exit, regs); -+} -+ -+/* -+ * Called iff UTRACE_EVENT(CLONE) flag is set. -+ * This notification call blocks the wake_up_new_task call on the child. -+ * So we must not quiesce here. tracehook_report_clone_complete will do -+ * a quiescence check momentarily. -+ */ -+void utrace_report_clone(unsigned long clone_flags, struct task_struct *child) -+{ -+ struct task_struct *task = current; -+ struct utrace *utrace = task_utrace_struct(task); -+ INIT_REPORT(report); -+ -+ /* -+ * We don't use the REPORT() macro here, because we need -+ * to clear utrace->cloning before finish_report(). -+ * After finish_report(), utrace can be a stale pointer -+ * in cases when report.action is still UTRACE_RESUME. -+ */ -+ start_report(utrace); -+ utrace->cloning = child; -+ -+ REPORT_CALLBACKS(, task, utrace, &report, -+ UTRACE_EVENT(CLONE), report_clone, -+ report.action, engine, clone_flags, child); -+ -+ utrace->cloning = NULL; -+ finish_report(task, utrace, &report, !(clone_flags & CLONE_VFORK)); -+ -+ /* -+ * For a vfork, we will go into an uninterruptible block waiting -+ * for the child. We need UTRACE_STOP to happen before this, not -+ * after. For CLONE_VFORK, utrace_finish_vfork() will be called. -+ */ -+ if (report.action == UTRACE_STOP && (clone_flags & CLONE_VFORK)) { -+ spin_lock(&utrace->lock); -+ utrace->vfork_stop = 1; -+ spin_unlock(&utrace->lock); -+ } -+} -+ -+/* -+ * We're called after utrace_report_clone() for a CLONE_VFORK. -+ * If UTRACE_STOP was left from the clone report, we stop here. -+ * After this, we'll enter the uninterruptible wait_for_completion() -+ * waiting for the child. -+ */ -+void utrace_finish_vfork(struct task_struct *task) -+{ -+ struct utrace *utrace = task_utrace_struct(task); -+ -+ if (utrace->vfork_stop) { -+ spin_lock(&utrace->lock); -+ utrace->vfork_stop = 0; -+ spin_unlock(&utrace->lock); -+ utrace_stop(task, utrace, UTRACE_RESUME); /* XXX */ -+ } -+} -+ -+/* -+ * Called iff UTRACE_EVENT(JCTL) flag is set. -+ * -+ * Called with siglock held. -+ */ -+void utrace_report_jctl(int notify, int what) -+{ -+ struct task_struct *task = current; -+ struct utrace *utrace = task_utrace_struct(task); -+ INIT_REPORT(report); -+ -+ spin_unlock_irq(&task->sighand->siglock); -+ -+ REPORT(task, utrace, &report, UTRACE_EVENT(JCTL), -+ report_jctl, what, notify); -+ -+ spin_lock_irq(&task->sighand->siglock); -+} -+ -+/* -+ * Called iff UTRACE_EVENT(EXIT) flag is set. -+ */ -+void utrace_report_exit(long *exit_code) -+{ -+ struct task_struct *task = current; -+ struct utrace *utrace = task_utrace_struct(task); -+ INIT_REPORT(report); -+ long orig_code = *exit_code; -+ -+ REPORT(task, utrace, &report, UTRACE_EVENT(EXIT), -+ report_exit, orig_code, exit_code); -+ -+ if (report.action == UTRACE_STOP) -+ utrace_stop(task, utrace, report.resume_action); -+} -+ -+/* -+ * Called iff UTRACE_EVENT(DEATH) or UTRACE_EVENT(QUIESCE) flag is set. -+ * -+ * It is always possible that we are racing with utrace_release_task here. -+ * For this reason, utrace_release_task checks for the event bits that get -+ * us here, and delays its cleanup for us to do. -+ */ -+void utrace_report_death(struct task_struct *task, struct utrace *utrace, -+ bool group_dead, int signal) -+{ -+ INIT_REPORT(report); -+ -+ BUG_ON(!task->exit_state); -+ -+ /* -+ * We are presently considered "quiescent"--which is accurate -+ * inasmuch as we won't run any more user instructions ever again. -+ * But for utrace_control and utrace_set_events to be robust, they -+ * must be sure whether or not we will run any more callbacks. If -+ * a call comes in before we do, taking the lock here synchronizes -+ * us so we don't run any callbacks just disabled. Calls that come -+ * in while we're running the callbacks will see the exit.death -+ * flag and know that we are not yet fully quiescent for purposes -+ * of detach bookkeeping. -+ */ -+ spin_lock(&utrace->lock); -+ BUG_ON(utrace->death); -+ utrace->death = 1; -+ utrace->resume = UTRACE_RESUME; -+ splice_attaching(utrace); -+ spin_unlock(&utrace->lock); -+ -+ REPORT_CALLBACKS(, task, utrace, &report, UTRACE_EVENT(DEATH), -+ report_death, engine, group_dead, signal); -+ -+ utrace_maybe_reap(task, utrace, false); -+} -+ -+/* -+ * Finish the last reporting pass before returning to user mode. -+ */ -+static void finish_resume_report(struct task_struct *task, -+ struct utrace *utrace, -+ struct utrace_report *report) -+{ -+ finish_report_reset(task, utrace, report); -+ -+ switch (report->action) { -+ case UTRACE_STOP: -+ utrace_stop(task, utrace, report->resume_action); -+ break; -+ -+ case UTRACE_INTERRUPT: -+ if (!signal_pending(task)) -+ set_tsk_thread_flag(task, TIF_SIGPENDING); -+ break; -+ -+ case UTRACE_BLOCKSTEP: -+ if (likely(arch_has_block_step())) { -+ user_enable_block_step(task); -+ break; -+ } -+ -+ /* -+ * This means some callback is to blame for failing -+ * to check arch_has_block_step() itself. Warn and -+ * then fall through to treat it as SINGLESTEP. -+ */ -+ WARN(1, "UTRACE_BLOCKSTEP when !arch_has_block_step()"); -+ -+ case UTRACE_SINGLESTEP: -+ if (likely(arch_has_single_step())) { -+ user_enable_single_step(task); -+ } else { -+ /* -+ * This means some callback is to blame for failing -+ * to check arch_has_single_step() itself. Spew -+ * about it so the loser will fix his module. -+ */ -+ WARN(1, -+ "UTRACE_SINGLESTEP when !arch_has_single_step()"); -+ } -+ break; -+ -+ case UTRACE_REPORT: -+ case UTRACE_RESUME: -+ default: -+ user_disable_single_step(task); -+ break; -+ } -+} -+ -+/* -+ * This is called when TIF_NOTIFY_RESUME had been set (and is now clear). -+ * We are close to user mode, and this is the place to report or stop. -+ * When we return, we're going to user mode or into the signals code. -+ */ -+void utrace_resume(struct task_struct *task, struct pt_regs *regs) -+{ -+ struct utrace *utrace = task_utrace_struct(task); -+ INIT_REPORT(report); -+ struct utrace_engine *engine; -+ -+ /* -+ * Some machines get here with interrupts disabled. The same arch -+ * code path leads to calling into get_signal_to_deliver(), which -+ * implicitly reenables them by virtue of spin_unlock_irq. -+ */ -+ local_irq_enable(); -+ -+ /* -+ * If this flag is still set it's because there was a signal -+ * handler setup done but no report_signal following it. Clear -+ * the flag before we get to user so it doesn't confuse us later. -+ */ -+ if (unlikely(utrace->signal_handler)) { -+ spin_lock(&utrace->lock); -+ utrace->signal_handler = 0; -+ spin_unlock(&utrace->lock); -+ } -+ -+ /* -+ * Update our bookkeeping even if there are no callbacks made here. -+ */ -+ report.action = start_report(utrace); -+ -+ switch (report.action) { -+ case UTRACE_RESUME: -+ /* -+ * Anything we might have done was already handled by -+ * utrace_get_signal(), or this is an entirely spurious -+ * call. (The arch might use TIF_NOTIFY_RESUME for other -+ * purposes as well as calling us.) -+ */ -+ return; -+ case UTRACE_REPORT: -+ if (unlikely(!(task->utrace_flags & UTRACE_EVENT(QUIESCE)))) -+ break; -+ /* -+ * Do a simple reporting pass, with no specific -+ * callback after report_quiesce. -+ */ -+ report.action = UTRACE_RESUME; -+ list_for_each_entry(engine, &utrace->attached, entry) -+ start_callback(utrace, &report, engine, task, 0); -+ break; -+ default: -+ /* -+ * Even if this report was truly spurious, there is no need -+ * for utrace_reset() now. TIF_NOTIFY_RESUME was already -+ * cleared--it doesn't stay spuriously set. -+ */ -+ report.spurious = false; -+ break; -+ } -+ -+ /* -+ * Finish the report and either stop or get ready to resume. -+ * If utrace->resume was not UTRACE_REPORT, this applies its -+ * effect now (i.e. step or interrupt). -+ */ -+ finish_resume_report(task, utrace, &report); -+} -+ -+/* -+ * Return true if current has forced signal_pending(). -+ * -+ * This is called only when current->utrace_flags is nonzero, so we know -+ * that current->utrace must be set. It's not inlined in tracehook.h -+ * just so that struct utrace can stay opaque outside this file. -+ */ -+bool utrace_interrupt_pending(void) -+{ -+ return task_utrace_struct(current)->resume == UTRACE_INTERRUPT; -+} -+ -+/* -+ * Take the siglock and push @info back on our queue. -+ * Returns with @task->sighand->siglock held. -+ */ -+static void push_back_signal(struct task_struct *task, siginfo_t *info) -+ __acquires(task->sighand->siglock) -+{ -+ struct sigqueue *q; -+ -+ if (unlikely(!info->si_signo)) { /* Oh, a wise guy! */ -+ spin_lock_irq(&task->sighand->siglock); -+ return; -+ } -+ -+ q = sigqueue_alloc(); -+ if (likely(q)) { -+ q->flags = 0; -+ copy_siginfo(&q->info, info); -+ } -+ -+ spin_lock_irq(&task->sighand->siglock); -+ -+ sigaddset(&task->pending.signal, info->si_signo); -+ if (likely(q)) -+ list_add(&q->list, &task->pending.list); -+ -+ set_tsk_thread_flag(task, TIF_SIGPENDING); -+} -+ -+/* -+ * This is the hook from the signals code, called with the siglock held. -+ * Here is the ideal place to stop. We also dequeue and intercept signals. -+ */ -+int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, -+ siginfo_t *info, struct k_sigaction *return_ka) -+ __releases(task->sighand->siglock) -+ __acquires(task->sighand->siglock) -+{ -+ struct utrace *utrace; -+ struct k_sigaction *ka; -+ INIT_REPORT(report); -+ struct utrace_engine *engine; -+ const struct utrace_engine_ops *ops; -+ unsigned long event, want; -+ u32 ret; -+ int signr; -+ -+ utrace = task_utrace_struct(task); -+ if (utrace->resume < UTRACE_RESUME || -+ utrace->pending_attach || utrace->signal_handler) { -+ enum utrace_resume_action resume; -+ -+ /* -+ * We've been asked for an explicit report before we -+ * even check for pending signals. -+ */ -+ -+ spin_unlock_irq(&task->sighand->siglock); -+ -+ spin_lock(&utrace->lock); -+ -+ splice_attaching(utrace); -+ -+ report.result = utrace->signal_handler ? -+ UTRACE_SIGNAL_HANDLER : UTRACE_SIGNAL_REPORT; -+ utrace->signal_handler = 0; -+ -+ resume = utrace->resume; -+ utrace->resume = UTRACE_RESUME; -+ -+ spin_unlock(&utrace->lock); -+ -+ /* -+ * Make sure signal_pending() only returns true -+ * if there are real signals pending. -+ */ -+ if (signal_pending(task)) { -+ spin_lock_irq(&task->sighand->siglock); -+ recalc_sigpending(); -+ spin_unlock_irq(&task->sighand->siglock); -+ } -+ -+ if (resume > UTRACE_REPORT) { -+ /* -+ * We only got here to process utrace->resume. -+ * Despite no callbacks, this report is not spurious. -+ */ -+ report.action = resume; -+ report.spurious = false; -+ finish_resume_report(task, utrace, &report); -+ return -1; -+ } else if (!(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { -+ /* -+ * We only got here to clear utrace->signal_handler. -+ */ -+ return -1; -+ } -+ -+ /* -+ * Do a reporting pass for no signal, just for EVENT(QUIESCE). -+ * The engine callbacks can fill in *info and *return_ka. -+ * We'll pass NULL for the @orig_ka argument to indicate -+ * that there was no original signal. -+ */ -+ event = 0; -+ ka = NULL; -+ memset(return_ka, 0, sizeof *return_ka); -+ } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || -+ unlikely(task->signal->group_stop_count)) { -+ /* -+ * If no engine is interested in intercepting signals or -+ * we must stop, let the caller just dequeue them normally -+ * or participate in group-stop. -+ */ -+ return 0; -+ } else { -+ /* -+ * Steal the next signal so we can let tracing engines -+ * examine it. From the signal number and sigaction, -+ * determine what normal delivery would do. If no -+ * engine perturbs it, we'll do that by returning the -+ * signal number after setting *return_ka. -+ */ -+ signr = dequeue_signal(task, &task->blocked, info); -+ if (signr == 0) -+ return signr; -+ BUG_ON(signr != info->si_signo); -+ -+ ka = &task->sighand->action[signr - 1]; -+ *return_ka = *ka; -+ -+ /* -+ * We are never allowed to interfere with SIGKILL. -+ * Just punt after filling in *return_ka for our caller. -+ */ -+ if (signr == SIGKILL) -+ return signr; -+ -+ if (ka->sa.sa_handler == SIG_IGN) { -+ event = UTRACE_EVENT(SIGNAL_IGN); -+ report.result = UTRACE_SIGNAL_IGN; -+ } else if (ka->sa.sa_handler != SIG_DFL) { -+ event = UTRACE_EVENT(SIGNAL); -+ report.result = UTRACE_SIGNAL_DELIVER; -+ } else if (sig_kernel_coredump(signr)) { -+ event = UTRACE_EVENT(SIGNAL_CORE); -+ report.result = UTRACE_SIGNAL_CORE; -+ } else if (sig_kernel_ignore(signr)) { -+ event = UTRACE_EVENT(SIGNAL_IGN); -+ report.result = UTRACE_SIGNAL_IGN; -+ } else if (signr == SIGSTOP) { -+ event = UTRACE_EVENT(SIGNAL_STOP); -+ report.result = UTRACE_SIGNAL_STOP; -+ } else if (sig_kernel_stop(signr)) { -+ event = UTRACE_EVENT(SIGNAL_STOP); -+ report.result = UTRACE_SIGNAL_TSTP; -+ } else { -+ event = UTRACE_EVENT(SIGNAL_TERM); -+ report.result = UTRACE_SIGNAL_TERM; -+ } -+ -+ /* -+ * Now that we know what event type this signal is, we -+ * can short-circuit if no engines care about those. -+ */ -+ if ((task->utrace_flags & (event | UTRACE_EVENT(QUIESCE))) == 0) -+ return signr; -+ -+ /* -+ * We have some interested engines, so tell them about -+ * the signal and let them change its disposition. -+ */ -+ spin_unlock_irq(&task->sighand->siglock); -+ } -+ -+ /* -+ * This reporting pass chooses what signal disposition we'll act on. -+ */ -+ list_for_each_entry(engine, &utrace->attached, entry) { -+ /* -+ * See start_callback() comment about this barrier. -+ */ -+ utrace->reporting = engine; -+ smp_mb(); -+ -+ /* -+ * This pairs with the barrier in mark_engine_detached(), -+ * see start_callback() comments. -+ */ -+ want = engine->flags; -+ smp_rmb(); -+ ops = engine->ops; -+ -+ if ((want & (event | UTRACE_EVENT(QUIESCE))) == 0) { -+ utrace->reporting = NULL; -+ continue; -+ } -+ -+ if (ops->report_signal) -+ ret = (*ops->report_signal)( -+ report.result | report.action, engine, -+ regs, info, ka, return_ka); -+ else -+ ret = (report.result | (*ops->report_quiesce)( -+ report.action, engine, event)); -+ -+ /* -+ * Avoid a tight loop reporting again and again if some -+ * engine is too stupid. -+ */ -+ switch (utrace_resume_action(ret)) { -+ default: -+ break; -+ case UTRACE_INTERRUPT: -+ case UTRACE_REPORT: -+ ret = (ret & ~UTRACE_RESUME_MASK) | UTRACE_RESUME; -+ break; -+ } -+ -+ finish_callback(task, utrace, &report, engine, ret); -+ } -+ -+ /* -+ * We express the chosen action to the signals code in terms -+ * of a representative signal whose default action does it. -+ * Our caller uses our return value (signr) to decide what to -+ * do, but uses info->si_signo as the signal number to report. -+ */ -+ switch (utrace_signal_action(report.result)) { -+ case UTRACE_SIGNAL_TERM: -+ signr = SIGTERM; -+ break; -+ -+ case UTRACE_SIGNAL_CORE: -+ signr = SIGQUIT; -+ break; -+ -+ case UTRACE_SIGNAL_STOP: -+ signr = SIGSTOP; -+ break; -+ -+ case UTRACE_SIGNAL_TSTP: -+ signr = SIGTSTP; -+ break; -+ -+ case UTRACE_SIGNAL_DELIVER: -+ signr = info->si_signo; -+ -+ if (return_ka->sa.sa_handler == SIG_DFL) { -+ /* -+ * We'll do signr's normal default action. -+ * For ignore, we'll fall through below. -+ * For stop/death, break locks and returns it. -+ */ -+ if (likely(signr) && !sig_kernel_ignore(signr)) -+ break; -+ } else if (return_ka->sa.sa_handler != SIG_IGN && -+ likely(signr)) { -+ /* -+ * Complete the bookkeeping after the report. -+ * The handler will run. If an engine wanted to -+ * stop or step, then make sure we do another -+ * report after signal handler setup. -+ */ -+ if (report.action != UTRACE_RESUME) -+ report.action = UTRACE_INTERRUPT; -+ finish_report(task, utrace, &report, true); -+ -+ if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) -+ push_back_signal(task, info); -+ else -+ spin_lock_irq(&task->sighand->siglock); -+ -+ /* -+ * We do the SA_ONESHOT work here since the -+ * normal path will only touch *return_ka now. -+ */ -+ if (unlikely(return_ka->sa.sa_flags & SA_ONESHOT)) { -+ return_ka->sa.sa_flags &= ~SA_ONESHOT; -+ if (likely(valid_signal(signr))) { -+ ka = &task->sighand->action[signr - 1]; -+ ka->sa.sa_handler = SIG_DFL; -+ } -+ } -+ -+ return signr; -+ } -+ -+ /* Fall through for an ignored signal. */ -+ -+ case UTRACE_SIGNAL_IGN: -+ case UTRACE_SIGNAL_REPORT: -+ default: -+ /* -+ * If the signal is being ignored, then we are on the way -+ * directly back to user mode. We can stop here, or step, -+ * as in utrace_resume(), above. After we've dealt with that, -+ * our caller will relock and come back through here. -+ */ -+ finish_resume_report(task, utrace, &report); -+ -+ if (unlikely(fatal_signal_pending(task))) { -+ /* -+ * The only reason we woke up now was because of a -+ * SIGKILL. Don't do normal dequeuing in case it -+ * might get a signal other than SIGKILL. That would -+ * perturb the death state so it might differ from -+ * what the debugger would have allowed to happen. -+ * Instead, pluck out just the SIGKILL to be sure -+ * we'll die immediately with nothing else different -+ * from the quiescent state the debugger wanted us in. -+ */ -+ sigset_t sigkill_only; -+ siginitsetinv(&sigkill_only, sigmask(SIGKILL)); -+ spin_lock_irq(&task->sighand->siglock); -+ signr = dequeue_signal(task, &sigkill_only, info); -+ BUG_ON(signr != SIGKILL); -+ *return_ka = task->sighand->action[SIGKILL - 1]; -+ return signr; -+ } -+ -+ if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) { -+ push_back_signal(task, info); -+ spin_unlock_irq(&task->sighand->siglock); -+ } -+ -+ return -1; -+ } -+ -+ /* -+ * Complete the bookkeeping after the report. -+ * This sets utrace->resume if UTRACE_STOP was used. -+ */ -+ finish_report(task, utrace, &report, true); -+ -+ return_ka->sa.sa_handler = SIG_DFL; -+ -+ /* -+ * If this signal is fatal, si_signo gets through as exit_code. -+ * We can't allow a completely bogus value there or else core -+ * kernel code can freak out. (If an engine wants to control -+ * the exit_code value exactly, it can do so in report_exit.) -+ * We'll produce a big complaint in dmesg, but won't crash. -+ * That's nicer for debugging your utrace engine. -+ */ -+ if (unlikely(info->si_signo & 0x80)) { -+ WARN(1, "utrace engine left bogus si_signo value!"); -+ info->si_signo = SIGTRAP; -+ } -+ -+ if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) -+ push_back_signal(task, info); -+ else -+ spin_lock_irq(&task->sighand->siglock); -+ -+ if (sig_kernel_stop(signr)) -+ task->signal->flags |= SIGNAL_STOP_DEQUEUED; -+ -+ return signr; -+} -+ -+/* -+ * This gets called after a signal handler has been set up. -+ * We set a flag so the next report knows it happened. -+ * If we're already stepping, make sure we do a report_signal. -+ * If not, make sure we get into utrace_resume() where we can -+ * clear the signal_handler flag before resuming. -+ */ -+void utrace_signal_handler(struct task_struct *task, int stepping) -+{ -+ struct utrace *utrace = task_utrace_struct(task); -+ -+ spin_lock(&utrace->lock); -+ -+ utrace->signal_handler = 1; -+ if (utrace->resume > UTRACE_INTERRUPT) { -+ if (stepping) { -+ utrace->resume = UTRACE_INTERRUPT; -+ set_tsk_thread_flag(task, TIF_SIGPENDING); -+ } else if (utrace->resume == UTRACE_RESUME) { -+ set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); -+ } -+ } -+ -+ spin_unlock(&utrace->lock); -+} -+ -+/** -+ * utrace_prepare_examine - prepare to examine thread state -+ * @target: thread of interest, a &struct task_struct pointer -+ * @engine: engine pointer returned by utrace_attach_task() -+ * @exam: temporary state, a &struct utrace_examiner pointer -+ * -+ * This call prepares to safely examine the thread @target using -+ * &struct user_regset calls, or direct access to thread-synchronous fields. -+ * -+ * When @target is current, this call is superfluous. When @target is -+ * another thread, it must be held stopped via %UTRACE_STOP by @engine. -+ * -+ * This call may block the caller until @target stays stopped, so it must -+ * be called only after the caller is sure @target is about to unschedule. -+ * This means a zero return from a utrace_control() call on @engine giving -+ * %UTRACE_STOP, or a report_quiesce() or report_signal() callback to -+ * @engine that used %UTRACE_STOP in its return value. -+ * -+ * Returns -%ESRCH if @target is dead or -%EINVAL if %UTRACE_STOP was -+ * not used. If @target has started running again despite %UTRACE_STOP -+ * (for %SIGKILL or a spurious wakeup), this call returns -%EAGAIN. -+ * -+ * When this call returns zero, it's safe to use &struct user_regset -+ * calls and task_user_regset_view() on @target and to examine some of -+ * its fields directly. When the examination is complete, a -+ * utrace_finish_examine() call must follow to check whether it was -+ * completed safely. -+ */ -+int utrace_prepare_examine(struct task_struct *target, -+ struct utrace_engine *engine, -+ struct utrace_examiner *exam) -+{ -+ int ret = 0; -+ -+ if (unlikely(target == current)) -+ return 0; -+ -+ rcu_read_lock(); -+ if (unlikely(!engine_wants_stop(engine))) -+ ret = -EINVAL; -+ else if (unlikely(target->exit_state)) -+ ret = -ESRCH; -+ else { -+ exam->state = target->state; -+ if (unlikely(exam->state == TASK_RUNNING)) -+ ret = -EAGAIN; -+ else -+ get_task_struct(target); -+ } -+ rcu_read_unlock(); -+ -+ if (likely(!ret)) { -+ exam->ncsw = wait_task_inactive(target, exam->state); -+ put_task_struct(target); -+ if (unlikely(!exam->ncsw)) -+ ret = -EAGAIN; -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(utrace_prepare_examine); -+ -+/** -+ * utrace_finish_examine - complete an examination of thread state -+ * @target: thread of interest, a &struct task_struct pointer -+ * @engine: engine pointer returned by utrace_attach_task() -+ * @exam: pointer passed to utrace_prepare_examine() call -+ * -+ * This call completes an examination on the thread @target begun by a -+ * paired utrace_prepare_examine() call with the same arguments that -+ * returned success (zero). -+ * -+ * When @target is current, this call is superfluous. When @target is -+ * another thread, this returns zero if @target has remained unscheduled -+ * since the paired utrace_prepare_examine() call returned zero. -+ * -+ * When this returns an error, any examination done since the paired -+ * utrace_prepare_examine() call is unreliable and the data extracted -+ * should be discarded. The error is -%EINVAL if @engine is not -+ * keeping @target stopped, or -%EAGAIN if @target woke up unexpectedly. -+ */ -+int utrace_finish_examine(struct task_struct *target, -+ struct utrace_engine *engine, -+ struct utrace_examiner *exam) -+{ -+ int ret = 0; -+ -+ if (unlikely(target == current)) -+ return 0; -+ -+ rcu_read_lock(); -+ if (unlikely(!engine_wants_stop(engine))) -+ ret = -EINVAL; -+ else if (unlikely(target->state != exam->state)) -+ ret = -EAGAIN; -+ else -+ get_task_struct(target); -+ rcu_read_unlock(); -+ -+ if (likely(!ret)) { -+ unsigned long ncsw = wait_task_inactive(target, exam->state); -+ if (unlikely(ncsw != exam->ncsw)) -+ ret = -EAGAIN; -+ put_task_struct(target); -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(utrace_finish_examine); -+ -+/* -+ * This is declared in linux/regset.h and defined in machine-dependent -+ * code. We put the export here to ensure no machine forgets it. -+ */ -+EXPORT_SYMBOL_GPL(task_user_regset_view); -+ -+/* -+ * Called with rcu_read_lock() held. -+ */ -+void task_utrace_proc_status(struct seq_file *m, struct task_struct *p) -+{ -+ seq_printf(m, "Utrace:\t%lx\n", p->utrace_flags); -+} 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/linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch b/linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch deleted file mode 100644 index f91ceb808..000000000 --- a/linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch +++ /dev/null @@ -1,82 +0,0 @@ -commit 7a1d6564a15183cb5994656040966df09af8390f -Author: Jussi Kivilinna -Date: Mon Jun 20 14:42:28 2011 +0300 - - zd1211rw: fix invalid signal values from device - - Driver uses IEEE80211_HW_SIGNAL_UNSPEC and so signal values reported to - mac80211 should be in range 0..100. Sometimes device return out of range - values. These out of range values can then trigger warning in - cfg80211_inform_bss_frame. - - This patch adds checks to enforce range returned from driver to - mac80211 be in 0..100 range. - - Signed-off-by: Jussi Kivilinna - Signed-off-by: John W. Linville - -diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h -index 5463ca9..9a1b013 100644 ---- a/drivers/net/wireless/zd1211rw/zd_def.h -+++ b/drivers/net/wireless/zd1211rw/zd_def.h -@@ -37,9 +37,15 @@ typedef u16 __nocast zd_addr_t; - if (net_ratelimit()) \ - dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \ - } while (0) -+# define dev_dbg_f_cond(dev, cond, fmt, args...) ({ \ -+ bool __cond = !!(cond); \ -+ if (unlikely(__cond)) \ -+ dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \ -+}) - #else - # define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0) - # define dev_dbg_f_limit(dev, fmt, args...) do { (void)(dev); } while (0) -+# define dev_dbg_f_cond(dev, cond, fmt, args...) do { (void)(dev); } while (0) - #endif /* DEBUG */ - - #ifdef DEBUG -diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c -index 5037c8b..5de28bf 100644 ---- a/drivers/net/wireless/zd1211rw/zd_mac.c -+++ b/drivers/net/wireless/zd1211rw/zd_mac.c -@@ -160,6 +160,22 @@ static int zd_reg2alpha2(u8 regdomain, char *alpha2) - return 1; - } - -+static int zd_check_signal(struct ieee80211_hw *hw, int signal) -+{ -+ struct zd_mac *mac = zd_hw_mac(hw); -+ -+ dev_dbg_f_cond(zd_mac_dev(mac), signal < 0 || signal > 100, -+ "%s: signal value from device not in range 0..100, " -+ "but %d.\n", __func__, signal); -+ -+ if (signal < 0) -+ signal = 0; -+ else if (signal > 100) -+ signal = 100; -+ -+ return signal; -+} -+ - int zd_mac_preinit_hw(struct ieee80211_hw *hw) - { - int r; -@@ -461,7 +477,7 @@ static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, - if (istatus.rates[i].idx = -1; /* terminate */ - -- info->status.ack_signal = ackssi; -+ info->status.ack_signal = zd_check_signal(hw, ackssi); - ieee80211_tx_status_irqsafe(hw, skb); - } - -@@ -982,7 +998,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) - - stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq; - stats.band = IEEE80211_BAND_2GHZ; -- stats.signal = status->signal_strength; -+ stats.signal = zd_check_signal(hw, status->signal_strength); - - rate = zd_rx_rate(buffer, status); - diff --git a/nl80211-fix-check-for-valid-ssid-size-in-scan-operations.patch b/nl80211-fix-check-for-valid-ssid-size-in-scan-operations.patch deleted file mode 100644 index f4b166c60..000000000 --- a/nl80211-fix-check-for-valid-ssid-size-in-scan-operations.patch +++ /dev/null @@ -1,42 +0,0 @@ -From: Luciano Coelho -Date: Wed, 18 May 2011 21:43:38 +0000 (+0300) -Subject: nl80211: fix check for valid SSID size in scan operations -X-Git-Tag: v3.0-rc2~7^2~16^2~12 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=208c72f4fe44fe09577e7975ba0e7fa0278f3d03 - -nl80211: fix check for valid SSID size in scan operations -[ 2.6.38 backport ] - -In both trigger_scan and sched_scan operations, we were checking for -the SSID length before assigning the value correctly. Since the -memory was just kzalloc'ed, the check was always failing and SSID with -over 32 characters were allowed to go through. - -This was causing a buffer overflow when copying the actual SSID to the -proper place. - -This bug has been there since 2.6.29-rc4. - -Cc: stable@kernel.org -Signed-off-by: Luciano Coelho -Signed-off-by: John W. Linville ---- - -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index ec83f41..88a565f 100644 ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -3406,12 +3406,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) - i = 0; - if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) { - nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { -+ request->ssids[i].ssid_len = nla_len(attr); - if (request->ssids[i].ssid_len > IEEE80211_MAX_SSID_LEN) { - err = -EINVAL; - goto out_free; - } - memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr)); -- request->ssids[i].ssid_len = nla_len(attr); - i++; - } - } diff --git a/nl80211-fix-overflow-in-ssid_len.patch.patch b/nl80211-fix-overflow-in-ssid_len.patch.patch deleted file mode 100644 index dcbf26b87..000000000 --- a/nl80211-fix-overflow-in-ssid_len.patch.patch +++ /dev/null @@ -1,44 +0,0 @@ -From: Luciano Coelho -Date: Tue, 7 Jun 2011 17:42:26 +0000 (+0300) -Subject: nl80211: fix overflow in ssid_len -X-Git-Tag: v3.0-rc4~5^2~13^2~6 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=57a27e1d6a3bb9ad4efeebd3a8c71156d6207536 - -nl80211: fix overflow in ssid_len -[ 2.6.38 backport ] - -When one of the SSID's length passed in a scan or sched_scan request -is larger than 255, there will be an overflow in the u8 that is used -to store the length before checking. This causes the check to fail -and we overrun the buffer when copying the SSID. - -Fix this by checking the nl80211 attribute length before copying it to -the struct. - -This is a follow up for the previous commit -208c72f4fe44fe09577e7975ba0e7fa0278f3d03, which didn't fix the problem -entirely. - -Reported-by: Ido Yariv -Signed-off-by: Luciano Coelho -Signed-off-by: John W. Linville ---- - -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index 88a565f..98fa8eb 100644 ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -3406,11 +3406,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) - i = 0; - if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) { - nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { -- request->ssids[i].ssid_len = nla_len(attr); -- if (request->ssids[i].ssid_len > IEEE80211_MAX_SSID_LEN) { -+ if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) { - err = -EINVAL; - goto out_free; - } -+ request->ssids[i].ssid_len = nla_len(attr); - memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr)); - i++; - } diff --git a/pci-enable-aspm-state-clearing-regardless-of-policy.patch b/pci-enable-aspm-state-clearing-regardless-of-policy.patch deleted file mode 100644 index afc977623..000000000 --- a/pci-enable-aspm-state-clearing-regardless-of-policy.patch +++ /dev/null @@ -1,29 +0,0 @@ -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)); - } 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/revert-fix-oops-in-scsi_run_queue.patch b/revert-fix-oops-in-scsi_run_queue.patch deleted file mode 100644 index 3170ed865..000000000 --- a/revert-fix-oops-in-scsi_run_queue.patch +++ /dev/null @@ -1,21 +0,0 @@ -revert c055f5b2614b4f758ae6cc86733f31fa4c2c5844 from 2.6.38.6 - ---- b/drivers/scsi/scsi_lib.c -+++ a/drivers/scsi/scsi_lib.c -@@ -400,15 +400,10 @@ - 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); - diff --git a/revert-hid-magicmouse-ignore-ivalid-report-id-while-switching.patch b/revert-hid-magicmouse-ignore-ivalid-report-id-while-switching.patch deleted file mode 100644 index 96be7fdd8..000000000 --- a/revert-hid-magicmouse-ignore-ivalid-report-id-while-switching.patch +++ /dev/null @@ -1,43 +0,0 @@ -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; - } diff --git a/revert-put-stricter-guards-on-queue-dead-checks.patch b/revert-put-stricter-guards-on-queue-dead-checks.patch deleted file mode 100644 index 7acd4127b..000000000 --- a/revert-put-stricter-guards-on-queue-dead-checks.patch +++ /dev/null @@ -1,34 +0,0 @@ -reverte 86cbfb5607d4b81b1a993ff689bbd2addd5d3a9b from 2.6.38.6 - ---- b/drivers/scsi/scsi_sysfs.c -+++ a/drivers/scsi/scsi_sysfs.c -@@ -322,8 +322,14 @@ - kfree(evt); - } - -+ if (sdev->request_queue) { -+ sdev->request_queue->queuedata = NULL; -+ /* user context needed to free queue */ -+ scsi_free_queue(sdev->request_queue); -+ /* temporary expedient, try to catch use of queue lock -+ * after free of sdev */ -+ sdev->request_queue = NULL; -+ } -- /* NULL queue means the device can't be used */ -- sdev->request_queue = NULL; - - scsi_target_reap(scsi_target(sdev)); - -@@ -931,12 +937,6 @@ - if (sdev->host->hostt->slave_destroy) - sdev->host->hostt->slave_destroy(sdev); - transport_destroy_device(dev); -- -- /* cause the request function to reject all I/O requests */ -- sdev->request_queue->queuedata = NULL; -- -- /* Freeing the queue signals to block that we're done */ -- scsi_free_queue(sdev->request_queue); - put_device(dev); - } - diff --git a/scsi-sd-downgrade-caching-printk-from-error-to-notice.patch b/scsi-sd-downgrade-caching-printk-from-error-to-notice.patch deleted file mode 100644 index c082fe05f..000000000 --- a/scsi-sd-downgrade-caching-printk-from-error-to-notice.patch +++ /dev/null @@ -1,28 +0,0 @@ -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 -@@ -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 ((buffer[offset] & 0x3f) != modepage) { -- sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); -+ sd_printk(KERN_NOTICE, sdkp, "Got wrong page\n"); - goto defaults; - } - -@@ -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; 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..ab481e125 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2 -c0f416f6a2e916633f697287cc7cb914 patch-2.6.38.8.bz2 +1aab7a741abe08d42e8eccf20de61e05 linux-2.6.39.tar.bz2 +df5790b51f218fc5e5463162b26afbfc patch-3.0.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; - } 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 deleted file mode 100644 index 9cedbadf9..000000000 --- a/x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch +++ /dev/null @@ -1,55 +0,0 @@ -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 89cbb5520283ff0c82228e8e242dbb1b4a1da9b4 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 28 Jul 2011 17:07:32 -0400 Subject: [PATCH 103/397] remove refs to unapplied patches --- kernel.spec | 9 --------- 1 file changed, 9 deletions(-) diff --git a/kernel.spec b/kernel.spec index 4a6b7d530..dc098588e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -663,7 +663,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 # fs fixes @@ -679,7 +678,6 @@ Patch12018: neuter_intel_microcode_load.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 Patch12303: dmar-disable-when-ricoh-multifunction.patch @@ -1244,7 +1242,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 # Patches headed upstream ApplyPatch disable-i8042-check-on-apple-mac.patch @@ -1253,12 +1250,6 @@ ApplyPatch add-appleir-usb-driver.patch ApplyPatch neuter_intel_microcode_load.patch -# Runtime PM -#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 From 3530e8957478fd5c1ca1d29f1643b5f26add6d73 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 28 Jul 2011 21:25:17 -0400 Subject: [PATCH 104/397] module-init-tools needs to be a prereq, not a conflict. --- kernel.spec | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/kernel.spec b/kernel.spec index dc098588e..944300658 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 @@ -423,7 +423,7 @@ Summary: The Linux kernel # First the general kernel 2.6 required versions as per # Documentation/Changes # -%define kernel_dot_org_conflicts ppp < 2.4.3-3, isdn4k-utils < 3.2-32, nfs-utils < 1.0.7-12, e2fsprogs < 1.37-4, util-linux < 2.12, jfsutils < 1.1.7-2, reiserfs-utils < 3.6.19-2, xfsprogs < 2.6.13-4, procps < 3.2.5-6.3, oprofile < 0.9.1-2, module-init-tools < 3.13-1 +%define kernel_dot_org_conflicts ppp < 2.4.3-3, isdn4k-utils < 3.2-32, nfs-utils < 1.0.7-12, e2fsprogs < 1.37-4, util-linux < 2.12, jfsutils < 1.1.7-2, reiserfs-utils < 3.6.19-2, xfsprogs < 2.6.13-4, procps < 3.2.5-6.3, oprofile < 0.9.1-2 # # Then a series of requirements that are distribution specific, either @@ -441,7 +441,7 @@ Summary: The Linux kernel # Packages that need to be installed before the kernel is, because the %%post # scripts use them. # -%define kernel_prereq fileutils, module-init-tools, initscripts >= 8.11.1-1, grubby >= 7.0.10-1 +%define kernel_prereq fileutils, module-init-tools >= 3.16-2, initscripts >= 8.11.1-1, grubby >= 7.0.10-1 %define initrd_prereq dracut >= 001-7 # @@ -1867,7 +1867,10 @@ fi # and build. %changelog -* Thu Jul 28 2011 Dave Jones +* Thu Jul 28 2011 Dave Jones 2.6.40-3 +- Fix module-init-tools conflict: + +* Thu Jul 28 2011 Dave Jones 2.6.40-2 - fix crash in scsi_dispatch_cmd() * Thu Jul 28 2011 Dave Jones 2.6.40-1 From 725a196dd65d1ffaeb38f3b6ade6cf70831401db Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 29 Jul 2011 14:20:23 -0400 Subject: [PATCH 105/397] Re-add utrace. --- config-generic | 2 + kernel.spec | 9 +- utrace.patch | 6166 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 6176 insertions(+), 1 deletion(-) create mode 100644 utrace.patch diff --git a/config-generic b/config-generic index e4dab09c1..dc11ce9ac 100644 --- a/config-generic +++ b/config-generic @@ -4208,6 +4208,8 @@ CONFIG_ASYNC_TX_DMA=y CONFIG_UNUSED_SYMBOLS=y +CONFIG_UTRACE=y + CONFIG_FTRACE=y CONFIG_DYNAMIC_FTRACE=y # CONFIG_IRQSOFF_TRACER is not set diff --git a/kernel.spec b/kernel.spec index 944300658..5ca1921c4 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 @@ -683,6 +683,8 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13000: fix-scsi_dispatch_cmd.patch +Patch20000: utrace.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1255,6 +1257,8 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch fix-scsi_dispatch_cmd.patch +ApplyPatch utrace.patch + # END OF PATCH APPLICATIONS %endif @@ -1867,6 +1871,9 @@ fi # and build. %changelog +* Fri Jul 29 2011 Dave Jones 2.6.40-4 +- Re-add utrace, which got accidentally dropped during the rebase. + * Thu Jul 28 2011 Dave Jones 2.6.40-3 - Fix module-init-tools conflict: diff --git a/utrace.patch b/utrace.patch new file mode 100644 index 000000000..55d0b3c1b --- /dev/null +++ b/utrace.patch @@ -0,0 +1,6166 @@ +From davej Thu Jun 30 20:27:03 2011 +Return-Path: oleg@redhat.com +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:03 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:00 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 10DAED812A; + Thu, 30 Jun 2011 20:23:00 -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 fiwBBweCuo8A; Thu, 30 Jun 2011 20:22:59 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E7CA2D810F; + Thu, 30 Jun 2011 20:22:59 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610MpCP015143; + Thu, 30 Jun 2011 20:22:52 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:20:59 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:20:57 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 01/19] utrace core +Message-ID: <20110701002057.GA25776@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Status: RO +Content-Length: 148213 +Lines: 4119 + +From: Roland McGrath + +This adds the utrace facility, a new modular interface in the kernel for +implementing user thread tracing and debugging. This fits on top of the +tracehook_* layer, so the new code is well-isolated. + +The new interface is in and the DocBook utrace book +describes it. It allows for multiple separate tracing engines to work in +parallel without interfering with each other. Higher-level tracing +facilities can be implemented as loadable kernel modules using this layer. + +The new facility is made optional under CONFIG_UTRACE. +When this is not enabled, no new code is added. +It can only be enabled on machines that have all the +prerequisites and select CONFIG_HAVE_ARCH_TRACEHOOK. + +In this initial version, utrace and ptrace do not play together at all, +the next patches try to fix this. + +This is is same/old utrace-core patch except: + + - use group_stop/GROUP_STOP_DEQUEUED instead of removed + signal->flags/SIGNAL_STOP_DEQUEUED in utrace_get_signal() + + - rediff the changes in tracehook.h against the current code + without PT_PTRACED tweaks which were needed for ptrace-utrace + +Signed-off-by: Roland McGrath +Signed-off-by: Oleg Nesterov +--- + Documentation/DocBook/Makefile | 2 +- + Documentation/DocBook/utrace.tmpl | 589 +++++++++ + fs/proc/array.c | 3 + + include/linux/sched.h | 5 + + include/linux/tracehook.h | 85 ++- + include/linux/utrace.h | 692 +++++++++++ + init/Kconfig | 9 + + kernel/Makefile | 1 + + kernel/fork.c | 3 + + kernel/utrace.c | 2440 +++++++++++++++++++++++++++++++++++++ + 10 files changed, 3827 insertions(+), 2 deletions(-) + create mode 100644 Documentation/DocBook/utrace.tmpl + create mode 100644 include/linux/utrace.h + create mode 100644 kernel/utrace.c + +diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile +index 3cebfa0..86c288b 100644 +--- a/Documentation/DocBook/Makefile ++++ b/Documentation/DocBook/Makefile +@@ -14,7 +14,7 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ + genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ + 80211.xml debugobjects.xml sh.xml regulator.xml \ + alsa-driver-api.xml writing-an-alsa-driver.xml \ +- tracepoint.xml media.xml drm.xml ++ tracepoint.xml utrace.xml media.xml drm.xml + + ### + # The build process is as follows (targets): +diff --git a/Documentation/DocBook/utrace.tmpl b/Documentation/DocBook/utrace.tmpl +new file mode 100644 +index 0000000..0c40add +--- /dev/null ++++ b/Documentation/DocBook/utrace.tmpl +@@ -0,0 +1,589 @@ ++ ++ ++ ++ ++ ++ The utrace User Debugging Infrastructure ++ ++ ++ ++ ++ utrace concepts ++ ++ Introduction ++ ++ ++ utrace is infrastructure code for tracing ++ and controlling user threads. This is the foundation for writing ++ tracing engines, which can be loadable kernel modules. ++ ++ ++ ++ The basic actors in utrace are the thread ++ and the tracing engine. A tracing engine is some body of code that ++ calls into the <linux/utrace.h> ++ interfaces, represented by a struct ++ utrace_engine_ops. (Usually it's a kernel module, ++ though the legacy ptrace support is a tracing ++ engine that is not in a kernel module.) The interface operates on ++ individual threads (struct task_struct). ++ If an engine wants to treat several threads as a group, that is up ++ to its higher-level code. ++ ++ ++ ++ Tracing begins by attaching an engine to a thread, using ++ utrace_attach_task or ++ utrace_attach_pid. If successful, it returns a ++ pointer that is the handle used in all other calls. ++ ++ ++ ++ ++ Events and Callbacks ++ ++ ++ An attached engine does nothing by default. An engine makes something ++ happen by requesting callbacks via utrace_set_events ++ and poking the thread with utrace_control. ++ The synchronization issues related to these two calls ++ are discussed further below in . ++ ++ ++ ++ Events are specified using the macro ++ UTRACE_EVENT(type). ++ Each event type is associated with a callback in struct ++ utrace_engine_ops. A tracing engine can leave unused ++ callbacks NULL. The only callbacks required ++ are those used by the event flags it sets. ++ ++ ++ ++ Many engines can be attached to each thread. When a thread has an ++ event, each engine gets a callback if it has set the event flag for ++ that event type. For most events, engines are called in the order they ++ attached. Engines that attach after the event has occurred do not get ++ callbacks for that event. This includes any new engines just attached ++ by an existing engine's callback function. Once the sequence of ++ callbacks for that one event has completed, such new engines are then ++ eligible in the next sequence that starts when there is another event. ++ ++ ++ ++ Event reporting callbacks have details particular to the event type, ++ but are all called in similar environments and have the same ++ constraints. Callbacks are made from safe points, where no locks ++ are held, no special resources are pinned (usually), and the ++ user-mode state of the thread is accessible. So, callback code has ++ a pretty free hand. But to be a good citizen, callback code should ++ never block for long periods. It is fine to block in ++ kmalloc and the like, but never wait for i/o or ++ for user mode to do something. If you need the thread to wait, use ++ UTRACE_STOP and return from the callback ++ quickly. When your i/o finishes or whatever, you can use ++ utrace_control to resume the thread. ++ ++ ++ ++ The UTRACE_EVENT(SYSCALL_ENTRY) event is a special ++ case. While other events happen in the kernel when it will return to ++ user mode soon, this event happens when entering the kernel before it ++ will proceed with the work requested from user mode. Because of this ++ difference, the report_syscall_entry callback is ++ special in two ways. For this event, engines are called in reverse of ++ the normal order (this includes the report_quiesce ++ call that precedes a report_syscall_entry call). ++ This preserves the semantics that the last engine to attach is called ++ "closest to user mode"--the engine that is first to see a thread's user ++ state when it enters the kernel is also the last to see that state when ++ the thread returns to user mode. For the same reason, if these ++ callbacks use UTRACE_STOP (see the next section), ++ the thread stops immediately after callbacks rather than only when it's ++ ready to return to user mode; when allowed to resume, it will actually ++ attempt the system call indicated by the register values at that time. ++ ++ ++ ++ ++ Stopping Safely ++ ++ Writing well-behaved callbacks ++ ++ ++ Well-behaved callbacks are important to maintain two essential ++ properties of the interface. The first of these is that unrelated ++ tracing engines should not interfere with each other. If your engine's ++ event callback does not return quickly, then another engine won't get ++ the event notification in a timely manner. The second important ++ property is that tracing should be as noninvasive as possible to the ++ normal operation of the system overall and of the traced thread in ++ particular. That is, attached tracing engines should not perturb a ++ thread's behavior, except to the extent that changing its user-visible ++ state is explicitly what you want to do. (Obviously some perturbation ++ is unavoidable, primarily timing changes, ranging from small delays due ++ to the overhead of tracing, to arbitrary pauses in user code execution ++ when a user stops a thread with a debugger for examination.) Even when ++ you explicitly want the perturbation of making the traced thread block, ++ just blocking directly in your callback has more unwanted effects. For ++ example, the CLONE event callbacks are called when ++ the new child thread has been created but not yet started running; the ++ child can never be scheduled until the CLONE ++ tracing callbacks return. (This allows engines tracing the parent to ++ attach to the child.) If a CLONE event callback ++ blocks the parent thread, it also prevents the child thread from ++ running (even to process a SIGKILL). If what you ++ want is to make both the parent and child block, then use ++ utrace_attach_task on the child and then use ++ UTRACE_STOP on both threads. A more crucial ++ problem with blocking in callbacks is that it can prevent ++ SIGKILL from working. A thread that is blocking ++ due to UTRACE_STOP will still wake up and die ++ immediately when sent a SIGKILL, as all threads ++ should. Relying on the utrace ++ infrastructure rather than on private synchronization calls in event ++ callbacks is an important way to help keep tracing robustly ++ noninvasive. ++ ++ ++ ++ ++ Using <constant>UTRACE_STOP</constant> ++ ++ ++ To control another thread and access its state, it must be stopped ++ with UTRACE_STOP. This means that it is ++ stopped and won't start running again while we access it. When a ++ thread is not already stopped, utrace_control ++ returns -EINPROGRESS and an engine must wait ++ for an event callback when the thread is ready to stop. The thread ++ may be running on another CPU or may be blocked. When it is ready ++ to be examined, it will make callbacks to engines that set the ++ UTRACE_EVENT(QUIESCE) event bit. To wake up an ++ interruptible wait, use UTRACE_INTERRUPT. ++ ++ ++ ++ As long as some engine has used UTRACE_STOP and ++ not called utrace_control to resume the thread, ++ then the thread will remain stopped. SIGKILL ++ will wake it up, but it will not run user code. When the stop is ++ cleared with utrace_control or a callback ++ return value, the thread starts running again. ++ (See also .) ++ ++ ++ ++ ++ ++ ++ Tear-down Races ++ ++ Primacy of <constant>SIGKILL</constant> ++ ++ Ordinarily synchronization issues for tracing engines are kept fairly ++ straightforward by using UTRACE_STOP. You ask a ++ thread to stop, and then once it makes the ++ report_quiesce callback it cannot do anything else ++ that would result in another callback, until you let it with a ++ utrace_control call. This simple arrangement ++ avoids complex and error-prone code in each one of a tracing engine's ++ event callbacks to keep them serialized with the engine's other ++ operations done on that thread from another thread of control. ++ However, giving tracing engines complete power to keep a traced thread ++ stuck in place runs afoul of a more important kind of simplicity that ++ the kernel overall guarantees: nothing can prevent or delay ++ SIGKILL from making a thread die and release its ++ resources. To preserve this important property of ++ SIGKILL, it as a special case can break ++ UTRACE_STOP like nothing else normally can. This ++ includes both explicit SIGKILL signals and the ++ implicit SIGKILL sent to each other thread in the ++ same thread group by a thread doing an exec, or processing a fatal ++ signal, or making an exit_group system call. A ++ tracing engine can prevent a thread from beginning the exit or exec or ++ dying by signal (other than SIGKILL) if it is ++ attached to that thread, but once the operation begins, no tracing ++ engine can prevent or delay all other threads in the same thread group ++ dying. ++ ++ ++ ++ Final callbacks ++ ++ The report_reap callback is always the final event ++ in the life cycle of a traced thread. Tracing engines can use this as ++ the trigger to clean up their own data structures. The ++ report_death callback is always the penultimate ++ event a tracing engine might see; it's seen unless the thread was ++ already in the midst of dying when the engine attached. Many tracing ++ engines will have no interest in when a parent reaps a dead process, ++ and nothing they want to do with a zombie thread once it dies; for ++ them, the report_death callback is the natural ++ place to clean up data structures and detach. To facilitate writing ++ such engines robustly, given the asynchrony of ++ SIGKILL, and without error-prone manual ++ implementation of synchronization schemes, the ++ utrace infrastructure provides some special ++ guarantees about the report_death and ++ report_reap callbacks. It still takes some care ++ to be sure your tracing engine is robust to tear-down races, but these ++ rules make it reasonably straightforward and concise to handle a lot of ++ corner cases correctly. ++ ++ ++ ++ Engine and task pointers ++ ++ The first sort of guarantee concerns the core data structures ++ themselves. struct utrace_engine is ++ a reference-counted data structure. While you hold a reference, an ++ engine pointer will always stay valid so that you can safely pass it to ++ any utrace call. Each call to ++ utrace_attach_task or ++ utrace_attach_pid returns an engine pointer with a ++ reference belonging to the caller. You own that reference until you ++ drop it using utrace_engine_put. There is an ++ implicit reference on the engine while it is attached. So if you drop ++ your only reference, and then use ++ utrace_attach_task without ++ UTRACE_ATTACH_CREATE to look up that same engine, ++ you will get the same pointer with a new reference to replace the one ++ you dropped, just like calling utrace_engine_get. ++ When an engine has been detached, either explicitly with ++ UTRACE_DETACH or implicitly after ++ report_reap, then any references you hold are all ++ that keep the old engine pointer alive. ++ ++ ++ ++ There is nothing a kernel module can do to keep a struct ++ task_struct alive outside of ++ rcu_read_lock. When the task dies and is reaped ++ by its parent (or itself), that structure can be freed so that any ++ dangling pointers you have stored become invalid. ++ utrace will not prevent this, but it can ++ help you detect it safely. By definition, a task that has been reaped ++ has had all its engines detached. All ++ utrace calls can be safely called on a ++ detached engine if the caller holds a reference on that engine pointer, ++ even if the task pointer passed in the call is invalid. All calls ++ return -ESRCH for a detached engine, which tells ++ you that the task pointer you passed could be invalid now. Since ++ utrace_control and ++ utrace_set_events do not block, you can call those ++ inside a rcu_read_lock section and be sure after ++ they don't return -ESRCH that the task pointer is ++ still valid until rcu_read_unlock. The ++ infrastructure never holds task references of its own. Though neither ++ rcu_read_lock nor any other lock is held while ++ making a callback, it's always guaranteed that the struct ++ task_struct and the struct ++ utrace_engine passed as arguments remain valid ++ until the callback function returns. ++ ++ ++ ++ The common means for safely holding task pointers that is available to ++ kernel modules is to use struct pid, which ++ permits put_pid from kernel modules. When using ++ that, the calls utrace_attach_pid, ++ utrace_control_pid, ++ utrace_set_events_pid, and ++ utrace_barrier_pid are available. ++ ++ ++ ++ ++ ++ Serialization of <constant>DEATH</constant> and <constant>REAP</constant> ++ ++ ++ The second guarantee is the serialization of ++ DEATH and REAP event ++ callbacks for a given thread. The actual reaping by the parent ++ (release_task call) can occur simultaneously ++ while the thread is still doing the final steps of dying, including ++ the report_death callback. If a tracing engine ++ has requested both DEATH and ++ REAP event reports, it's guaranteed that the ++ report_reap callback will not be made until ++ after the report_death callback has returned. ++ If the report_death callback itself detaches ++ from the thread, then the report_reap callback ++ will never be made. Thus it is safe for a ++ report_death callback to clean up data ++ structures and detach. ++ ++ ++ ++ Interlock with final callbacks ++ ++ The final sort of guarantee is that a tracing engine will know for sure ++ whether or not the report_death and/or ++ report_reap callbacks will be made for a certain ++ thread. These tear-down races are disambiguated by the error return ++ values of utrace_set_events and ++ utrace_control. Normally ++ utrace_control called with ++ UTRACE_DETACH returns zero, and this means that no ++ more callbacks will be made. If the thread is in the midst of dying, ++ it returns -EALREADY to indicate that the ++ report_death callback may already be in progress; ++ when you get this error, you know that any cleanup your ++ report_death callback does is about to happen or ++ has just happened--note that if the report_death ++ callback does not detach, the engine remains attached until the thread ++ gets reaped. If the thread is in the midst of being reaped, ++ utrace_control returns -ESRCH ++ to indicate that the report_reap callback may ++ already be in progress; this means the engine is implicitly detached ++ when the callback completes. This makes it possible for a tracing ++ engine that has decided asynchronously to detach from a thread to ++ safely clean up its data structures, knowing that no ++ report_death or report_reap ++ callback will try to do the same. utrace_detach ++ returns -ESRCH when the struct ++ utrace_engine has already been detached, but is ++ still a valid pointer because of its reference count. A tracing engine ++ can use this to safely synchronize its own independent multiple threads ++ of control with each other and with its event callbacks that detach. ++ ++ ++ ++ In the same vein, utrace_set_events normally ++ returns zero; if the target thread was stopped before the call, then ++ after a successful call, no event callbacks not requested in the new ++ flags will be made. It fails with -EALREADY if ++ you try to clear UTRACE_EVENT(DEATH) when the ++ report_death callback may already have begun, or if ++ you try to newly set UTRACE_EVENT(DEATH) or ++ UTRACE_EVENT(QUIESCE) when the target is already ++ dead or dying. Like utrace_control, it returns ++ -ESRCH when the report_reap ++ callback may already have begun, or the thread has already been detached ++ (including forcible detach on reaping). This lets the tracing engine ++ know for sure which event callbacks it will or won't see after ++ utrace_set_events has returned. By checking for ++ errors, it can know whether to clean up its data structures immediately ++ or to let its callbacks do the work. ++ ++ ++ ++ Using <function>utrace_barrier</function> ++ ++ When a thread is safely stopped, calling ++ utrace_control with UTRACE_DETACH ++ or calling utrace_set_events to disable some events ++ ensures synchronously that your engine won't get any more of the callbacks ++ that have been disabled (none at all when detaching). But these can also ++ be used while the thread is not stopped, when it might be simultaneously ++ making a callback to your engine. For this situation, these calls return ++ -EINPROGRESS when it's possible a callback is in ++ progress. If you are not prepared to have your old callbacks still run, ++ then you can synchronize to be sure all the old callbacks are finished, ++ using utrace_barrier. This is necessary if the ++ kernel module containing your callback code is going to be unloaded. ++ ++ ++ After using UTRACE_DETACH once, further calls to ++ utrace_control with the same engine pointer will ++ return -ESRCH. In contrast, after getting ++ -EINPROGRESS from ++ utrace_set_events, you can call ++ utrace_set_events again later and if it returns zero ++ then know the old callbacks have finished. ++ ++ ++ Unlike all other calls, utrace_barrier (and ++ utrace_barrier_pid) will accept any engine pointer you ++ hold a reference on, even if UTRACE_DETACH has already ++ been used. After any utrace_control or ++ utrace_set_events call (these do not block), you can ++ call utrace_barrier to block until callbacks have ++ finished. This returns -ESRCH only if the engine is ++ completely detached (finished all callbacks). Otherwise it waits ++ until the thread is definitely not in the midst of a callback to this ++ engine and then returns zero, but can return ++ -ERESTARTSYS if its wait is interrupted. ++ ++ ++ ++ ++ ++ ++ ++utrace core API ++ ++ ++ The utrace API is declared in <linux/utrace.h>. ++ ++ ++!Iinclude/linux/utrace.h ++!Ekernel/utrace.c ++ ++ ++ ++Machine State ++ ++ ++ The task_current_syscall function can be used on any ++ valid struct task_struct at any time, and does ++ not even require that utrace_attach_task was used at all. ++ ++ ++ ++ The other ways to access the registers and other machine-dependent state of ++ a task can only be used on a task that is at a known safe point. The safe ++ points are all the places where utrace_set_events can ++ request callbacks (except for the DEATH and ++ REAP events). So at any event callback, it is safe to ++ examine current. ++ ++ ++ ++ One task can examine another only after a callback in the target task that ++ returns UTRACE_STOP so that task will not return to user ++ mode after the safe point. This guarantees that the task will not resume ++ until the same engine uses utrace_control, unless the ++ task dies suddenly. To examine safely, one must use a pair of calls to ++ utrace_prepare_examine and ++ utrace_finish_examine surrounding the calls to ++ struct user_regset functions or direct examination ++ of task data structures. utrace_prepare_examine returns ++ an error if the task is not properly stopped, or is dead. After a ++ successful examination, the paired utrace_finish_examine ++ call returns an error if the task ever woke up during the examination. If ++ so, any data gathered may be scrambled and should be discarded. This means ++ there was a spurious wake-up (which should not happen), or a sudden death. ++ ++ ++<structname>struct user_regset</structname> ++ ++ ++ The struct user_regset API ++ is declared in <linux/regset.h>. ++ ++ ++!Finclude/linux/regset.h ++ ++ ++ ++ ++ <filename>System Call Information</filename> ++ ++ ++ This function is declared in <linux/ptrace.h>. ++ ++ ++!Elib/syscall.c ++ ++ ++ ++<filename>System Call Tracing</filename> ++ ++ ++ The arch API for system call information is declared in ++ <asm/syscall.h>. ++ Each of these calls can be used only at system call entry tracing, ++ or can be used only at system call exit and the subsequent safe points ++ before returning to user mode. ++ At system call entry tracing means either during a ++ report_syscall_entry callback, ++ or any time after that callback has returned UTRACE_STOP. ++ ++ ++!Finclude/asm-generic/syscall.h ++ ++ ++ ++ ++ ++Kernel Internals ++ ++ ++ This chapter covers the interface to the tracing infrastructure ++ from the core of the kernel and the architecture-specific code. ++ This is for maintainers of the kernel and arch code, and not relevant ++ to using the tracing facilities described in preceding chapters. ++ ++ ++Core Calls In ++ ++ ++ These calls are declared in <linux/tracehook.h>. ++ The core kernel calls these functions at various important places. ++ ++ ++!Finclude/linux/tracehook.h ++ ++ ++ ++Architecture Calls Out ++ ++ ++ An arch that has done all these things sets ++ CONFIG_HAVE_ARCH_TRACEHOOK. ++ This is required to enable the utrace code. ++ ++ ++<filename><asm/ptrace.h></filename> ++ ++ ++ An arch defines these in <asm/ptrace.h> ++ if it supports hardware single-step or block-step features. ++ ++ ++!Finclude/linux/ptrace.h arch_has_single_step arch_has_block_step ++!Finclude/linux/ptrace.h user_enable_single_step user_enable_block_step ++!Finclude/linux/ptrace.h user_disable_single_step ++ ++ ++ ++ ++ <filename><asm/syscall.h></filename> ++ ++ ++ An arch provides <asm/syscall.h> that ++ defines these as inlines, or declares them as exported functions. ++ These interfaces are described in . ++ ++ ++ ++ ++ ++ <filename><linux/tracehook.h></filename> ++ ++ ++ An arch must define TIF_NOTIFY_RESUME ++ and TIF_SYSCALL_TRACE ++ in its <asm/thread_info.h>. ++ The arch code must call the following functions, all declared ++ in <linux/tracehook.h> and ++ described in : ++ ++ ++ ++ tracehook_notify_resume ++ ++ ++ tracehook_report_syscall_entry ++ ++ ++ tracehook_report_syscall_exit ++ ++ ++ tracehook_signal_handler ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/fs/proc/array.c b/fs/proc/array.c +index 9b45ee8..496fef3 100644 +--- a/fs/proc/array.c ++++ b/fs/proc/array.c +@@ -81,6 +81,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -192,6 +193,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, + cred->uid, cred->euid, cred->suid, cred->fsuid, + cred->gid, cred->egid, cred->sgid, cred->fsgid); + ++ task_utrace_proc_status(m, p); ++ + task_lock(p); + if (p->files) + fdt = files_fdtable(p->files); +diff --git a/include/linux/sched.h b/include/linux/sched.h +index a837b20..b87de83 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -1397,6 +1397,11 @@ struct task_struct { + #endif + seccomp_t seccomp; + ++#ifdef CONFIG_UTRACE ++ struct utrace *utrace; ++ unsigned long utrace_flags; ++#endif ++ + /* Thread group tracking */ + u32 parent_exec_id; + u32 self_exec_id; +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index e95f523..7d7bdde 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + struct linux_binprm; + + /** +@@ -63,6 +64,8 @@ struct linux_binprm; + */ + static inline int tracehook_expect_breakpoints(struct task_struct *task) + { ++ if (unlikely(task_utrace_flags(task) & UTRACE_EVENT(SIGNAL_CORE))) ++ return 1; + return (task_ptrace(task) & PT_PTRACED) != 0; + } + +@@ -111,6 +114,9 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) + static inline __must_check int tracehook_report_syscall_entry( + struct pt_regs *regs) + { ++ if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && ++ utrace_report_syscall_entry(regs)) ++ return 1; + ptrace_report_syscall(regs); + return 0; + } +@@ -134,6 +140,9 @@ static inline __must_check int tracehook_report_syscall_entry( + */ + static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) + { ++ if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) ++ utrace_report_syscall_exit(regs); ++ + if (step) { + siginfo_t info; + user_single_step_siginfo(current, regs, &info); +@@ -201,6 +210,8 @@ static inline void tracehook_report_exec(struct linux_binfmt *fmt, + struct linux_binprm *bprm, + struct pt_regs *regs) + { ++ if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXEC))) ++ utrace_report_exec(fmt, bprm, regs); + if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) && + unlikely(task_ptrace(current) & PT_PTRACED)) + send_sig(SIGTRAP, current, 0); +@@ -218,10 +229,37 @@ static inline void tracehook_report_exec(struct linux_binfmt *fmt, + */ + static inline void tracehook_report_exit(long *exit_code) + { ++ if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXIT))) ++ utrace_report_exit(exit_code); + ptrace_event(PT_TRACE_EXIT, PTRACE_EVENT_EXIT, *exit_code); + } + + /** ++ * tracehook_init_task - task_struct has just been copied ++ * @task: new &struct task_struct just copied from parent ++ * ++ * Called from do_fork() when @task has just been duplicated. ++ * After this, @task will be passed to tracehook_free_task() ++ * even if the rest of its setup fails before it is fully created. ++ */ ++static inline void tracehook_init_task(struct task_struct *task) ++{ ++ utrace_init_task(task); ++} ++ ++/** ++ * tracehook_free_task - task_struct is being freed ++ * @task: dead &struct task_struct being freed ++ * ++ * Called from free_task() when @task is no longer in use. ++ */ ++static inline void tracehook_free_task(struct task_struct *task) ++{ ++ if (task_utrace_struct(task)) ++ utrace_free_task(task); ++} ++ ++/** + * tracehook_prepare_clone - prepare for new child to be cloned + * @clone_flags: %CLONE_* flags from clone/fork/vfork system call + * +@@ -285,6 +323,8 @@ static inline void tracehook_report_clone(struct pt_regs *regs, + unsigned long clone_flags, + pid_t pid, struct task_struct *child) + { ++ if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE))) ++ utrace_report_clone(clone_flags, child); + if (unlikely(task_ptrace(child))) { + /* + * It doesn't matter who attached/attaching to this +@@ -317,6 +357,9 @@ static inline void tracehook_report_clone_complete(int trace, + pid_t pid, + struct task_struct *child) + { ++ if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE)) && ++ (clone_flags & CLONE_VFORK)) ++ utrace_finish_vfork(current); + if (unlikely(trace)) + ptrace_event(0, trace, pid); + } +@@ -351,6 +394,10 @@ static inline void tracehook_report_vfork_done(struct task_struct *child, + */ + static inline void tracehook_prepare_release_task(struct task_struct *task) + { ++ /* see utrace_add_engine() about this barrier */ ++ smp_mb(); ++ if (task_utrace_flags(task)) ++ utrace_maybe_reap(task, task_utrace_struct(task), true); + } + + /** +@@ -365,6 +412,7 @@ static inline void tracehook_prepare_release_task(struct task_struct *task) + static inline void tracehook_finish_release_task(struct task_struct *task) + { + ptrace_release_task(task); ++ BUG_ON(task->exit_state != EXIT_DEAD); + } + + /** +@@ -386,6 +434,8 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, + const struct k_sigaction *ka, + struct pt_regs *regs, int stepping) + { ++ if (task_utrace_flags(current)) ++ utrace_signal_handler(current, stepping); + if (stepping) + ptrace_notify(SIGTRAP); + } +@@ -403,6 +453,8 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, + static inline int tracehook_consider_ignored_signal(struct task_struct *task, + int sig) + { ++ if (unlikely(task_utrace_flags(task) & UTRACE_EVENT(SIGNAL_IGN))) ++ return 1; + return (task_ptrace(task) & PT_PTRACED) != 0; + } + +@@ -422,6 +474,9 @@ static inline int tracehook_consider_ignored_signal(struct task_struct *task, + static inline int tracehook_consider_fatal_signal(struct task_struct *task, + int sig) + { ++ if (unlikely(task_utrace_flags(task) & (UTRACE_EVENT(SIGNAL_TERM) | ++ UTRACE_EVENT(SIGNAL_CORE)))) ++ return 1; + return (task_ptrace(task) & PT_PTRACED) != 0; + } + +@@ -436,6 +491,8 @@ static inline int tracehook_consider_fatal_signal(struct task_struct *task, + */ + static inline int tracehook_force_sigpending(void) + { ++ if (unlikely(task_utrace_flags(current))) ++ return utrace_interrupt_pending(); + return 0; + } + +@@ -465,6 +522,8 @@ static inline int tracehook_get_signal(struct task_struct *task, + siginfo_t *info, + struct k_sigaction *return_ka) + { ++ if (unlikely(task_utrace_flags(task))) ++ return utrace_get_signal(task, regs, info, return_ka); + return 0; + } + +@@ -475,6 +534,8 @@ static inline int tracehook_get_signal(struct task_struct *task, + */ + static inline void tracehook_finish_jctl(void) + { ++ if (task_utrace_flags(current)) ++ utrace_finish_stop(); + } + + #define DEATH_REAP -1 +@@ -497,6 +558,8 @@ static inline void tracehook_finish_jctl(void) + static inline int tracehook_notify_death(struct task_struct *task, + void **death_cookie, int group_dead) + { ++ *death_cookie = task_utrace_struct(task); ++ + if (task_detached(task)) + return task->ptrace ? SIGCHLD : DEATH_REAP; + +@@ -533,6 +596,15 @@ static inline void tracehook_report_death(struct task_struct *task, + int signal, void *death_cookie, + int group_dead) + { ++ /* ++ * If utrace_set_events() was just called to enable ++ * UTRACE_EVENT(DEATH), then we are obliged to call ++ * utrace_report_death() and not miss it. utrace_set_events() ++ * checks @task->exit_state under tasklist_lock to synchronize ++ * with exit_notify(), the caller. ++ */ ++ if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) ++ utrace_report_death(task, death_cookie, group_dead, signal); + } + + #ifdef TIF_NOTIFY_RESUME +@@ -562,10 +634,21 @@ static inline void set_notify_resume(struct task_struct *task) + * asynchronously, this will be called again before we return to + * user mode. + * +- * Called without locks. ++ * Called without locks. However, on some machines this may be ++ * called with interrupts disabled. + */ + static inline void tracehook_notify_resume(struct pt_regs *regs) + { ++ struct task_struct *task = current; ++ /* ++ * Prevent the following store/load from getting ahead of the ++ * caller which clears TIF_NOTIFY_RESUME. This pairs with the ++ * implicit mb() before setting TIF_NOTIFY_RESUME in ++ * set_notify_resume(). ++ */ ++ smp_mb(); ++ if (task_utrace_flags(task)) ++ utrace_resume(task, regs); + } + #endif /* TIF_NOTIFY_RESUME */ + +diff --git a/include/linux/utrace.h b/include/linux/utrace.h +new file mode 100644 +index 0000000..f251efe +--- /dev/null ++++ b/include/linux/utrace.h +@@ -0,0 +1,692 @@ ++/* ++ * utrace infrastructure interface for debugging user processes ++ * ++ * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved. ++ * ++ * This copyrighted material is made available to anyone wishing to use, ++ * modify, copy, or redistribute it subject to the terms and conditions ++ * of the GNU General Public License v.2. ++ * ++ * Red Hat Author: Roland McGrath. ++ * ++ * This interface allows for notification of interesting events in a ++ * thread. It also mediates access to thread state such as registers. ++ * Multiple unrelated users can be associated with a single thread. ++ * We call each of these a tracing engine. ++ * ++ * A tracing engine starts by calling utrace_attach_task() or ++ * utrace_attach_pid() on the chosen thread, passing in a set of hooks ++ * (&struct utrace_engine_ops), and some associated data. This produces a ++ * &struct utrace_engine, which is the handle used for all other ++ * operations. An attached engine has its ops vector, its data, and an ++ * event mask controlled by utrace_set_events(). ++ * ++ * For each event bit that is set, that engine will get the ++ * appropriate ops->report_*() callback when the event occurs. The ++ * &struct utrace_engine_ops need not provide callbacks for an event ++ * unless the engine sets one of the associated event bits. ++ */ ++ ++#ifndef _LINUX_UTRACE_H ++#define _LINUX_UTRACE_H 1 ++ ++#include ++#include ++#include ++#include ++ ++struct linux_binprm; ++struct pt_regs; ++struct utrace; ++struct user_regset; ++struct user_regset_view; ++ ++/* ++ * Event bits passed to utrace_set_events(). ++ * These appear in &struct task_struct.@utrace_flags ++ * and &struct utrace_engine.@flags. ++ */ ++enum utrace_events { ++ _UTRACE_EVENT_QUIESCE, /* Thread is available for examination. */ ++ _UTRACE_EVENT_REAP, /* Zombie reaped, no more tracing possible. */ ++ _UTRACE_EVENT_CLONE, /* Successful clone/fork/vfork just done. */ ++ _UTRACE_EVENT_EXEC, /* Successful execve just completed. */ ++ _UTRACE_EVENT_EXIT, /* Thread exit in progress. */ ++ _UTRACE_EVENT_DEATH, /* Thread has died. */ ++ _UTRACE_EVENT_SYSCALL_ENTRY, /* User entered kernel for system call. */ ++ _UTRACE_EVENT_SYSCALL_EXIT, /* Returning to user after system call. */ ++ _UTRACE_EVENT_SIGNAL, /* Signal delivery will run a user handler. */ ++ _UTRACE_EVENT_SIGNAL_IGN, /* No-op signal to be delivered. */ ++ _UTRACE_EVENT_SIGNAL_STOP, /* Signal delivery will suspend. */ ++ _UTRACE_EVENT_SIGNAL_TERM, /* Signal delivery will terminate. */ ++ _UTRACE_EVENT_SIGNAL_CORE, /* Signal delivery will dump core. */ ++ _UTRACE_EVENT_JCTL, /* Job control stop or continue completed. */ ++ _UTRACE_NEVENTS ++}; ++#define UTRACE_EVENT(type) (1UL << _UTRACE_EVENT_##type) ++ ++/* ++ * All the kinds of signal events. ++ * These all use the @report_signal() callback. ++ */ ++#define UTRACE_EVENT_SIGNAL_ALL (UTRACE_EVENT(SIGNAL) \ ++ | UTRACE_EVENT(SIGNAL_IGN) \ ++ | UTRACE_EVENT(SIGNAL_STOP) \ ++ | UTRACE_EVENT(SIGNAL_TERM) \ ++ | UTRACE_EVENT(SIGNAL_CORE)) ++/* ++ * Both kinds of syscall events; these call the @report_syscall_entry() ++ * and @report_syscall_exit() callbacks, respectively. ++ */ ++#define UTRACE_EVENT_SYSCALL \ ++ (UTRACE_EVENT(SYSCALL_ENTRY) | UTRACE_EVENT(SYSCALL_EXIT)) ++ ++/* ++ * The event reports triggered synchronously by task death. ++ */ ++#define _UTRACE_DEATH_EVENTS (UTRACE_EVENT(DEATH) | UTRACE_EVENT(QUIESCE)) ++ ++/* ++ * Hooks in call these entry points to the utrace dispatch. ++ */ ++void utrace_free_task(struct task_struct *); ++bool utrace_interrupt_pending(void); ++void utrace_resume(struct task_struct *, struct pt_regs *); ++void utrace_finish_stop(void); ++void utrace_maybe_reap(struct task_struct *, struct utrace *, bool); ++int utrace_get_signal(struct task_struct *, struct pt_regs *, ++ siginfo_t *, struct k_sigaction *); ++void utrace_report_clone(unsigned long, struct task_struct *); ++void utrace_finish_vfork(struct task_struct *); ++void utrace_report_exit(long *exit_code); ++void utrace_report_death(struct task_struct *, struct utrace *, bool, int); ++void utrace_report_jctl(int notify, int type); ++void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *, ++ struct pt_regs *regs); ++bool utrace_report_syscall_entry(struct pt_regs *); ++void utrace_report_syscall_exit(struct pt_regs *); ++void utrace_signal_handler(struct task_struct *, int); ++ ++#ifndef CONFIG_UTRACE ++ ++/* ++ * uses these accessors to avoid #ifdef CONFIG_UTRACE. ++ */ ++static inline unsigned long task_utrace_flags(struct task_struct *task) ++{ ++ return 0; ++} ++static inline struct utrace *task_utrace_struct(struct task_struct *task) ++{ ++ return NULL; ++} ++static inline void utrace_init_task(struct task_struct *child) ++{ ++} ++ ++static inline void task_utrace_proc_status(struct seq_file *m, ++ struct task_struct *p) ++{ ++} ++ ++#else /* CONFIG_UTRACE */ ++ ++static inline unsigned long task_utrace_flags(struct task_struct *task) ++{ ++ return task->utrace_flags; ++} ++ ++static inline struct utrace *task_utrace_struct(struct task_struct *task) ++{ ++ struct utrace *utrace; ++ ++ /* ++ * This barrier ensures that any prior load of task->utrace_flags ++ * is ordered before this load of task->utrace. We use those ++ * utrace_flags checks in the hot path to decide to call into ++ * the utrace code. The first attach installs task->utrace before ++ * setting task->utrace_flags nonzero with implicit barrier in ++ * between, see utrace_add_engine(). ++ */ ++ smp_rmb(); ++ utrace = task->utrace; ++ ++ smp_read_barrier_depends(); /* See utrace_task_alloc(). */ ++ return utrace; ++} ++ ++static inline void utrace_init_task(struct task_struct *task) ++{ ++ task->utrace_flags = 0; ++ task->utrace = NULL; ++} ++ ++void task_utrace_proc_status(struct seq_file *m, struct task_struct *p); ++ ++ ++/* ++ * Version number of the API defined in this file. This will change ++ * whenever a tracing engine's code would need some updates to keep ++ * working. We maintain this here for the benefit of tracing engine code ++ * that is developed concurrently with utrace API improvements before they ++ * are merged into the kernel, making LINUX_VERSION_CODE checks unwieldy. ++ */ ++#define UTRACE_API_VERSION 20091216 ++ ++/** ++ * enum utrace_resume_action - engine's choice of action for a traced task ++ * @UTRACE_STOP: Stay quiescent after callbacks. ++ * @UTRACE_INTERRUPT: Make @report_signal() callback soon. ++ * @UTRACE_REPORT: Make some callback soon. ++ * @UTRACE_SINGLESTEP: Resume in user mode for one instruction. ++ * @UTRACE_BLOCKSTEP: Resume in user mode until next branch. ++ * @UTRACE_RESUME: Resume normally in user mode. ++ * @UTRACE_DETACH: Detach my engine (implies %UTRACE_RESUME). ++ * ++ * See utrace_control() for detailed descriptions of each action. This is ++ * encoded in the @action argument and the return value for every callback ++ * with a &u32 return value. ++ * ++ * The order of these is important. When there is more than one engine, ++ * each supplies its choice and the smallest value prevails. ++ */ ++enum utrace_resume_action { ++ UTRACE_STOP, ++ UTRACE_INTERRUPT, ++ UTRACE_REPORT, ++ UTRACE_SINGLESTEP, ++ UTRACE_BLOCKSTEP, ++ UTRACE_RESUME, ++ UTRACE_DETACH, ++ UTRACE_RESUME_MAX ++}; ++#define UTRACE_RESUME_BITS (ilog2(UTRACE_RESUME_MAX) + 1) ++#define UTRACE_RESUME_MASK ((1 << UTRACE_RESUME_BITS) - 1) ++ ++/** ++ * utrace_resume_action - &enum utrace_resume_action from callback action ++ * @action: &u32 callback @action argument or return value ++ * ++ * This extracts the &enum utrace_resume_action from @action, ++ * which is the @action argument to a &struct utrace_engine_ops ++ * callback or the return value from one. ++ */ ++static inline enum utrace_resume_action utrace_resume_action(u32 action) ++{ ++ return action & UTRACE_RESUME_MASK; ++} ++ ++/** ++ * enum utrace_signal_action - disposition of signal ++ * @UTRACE_SIGNAL_DELIVER: Deliver according to sigaction. ++ * @UTRACE_SIGNAL_IGN: Ignore the signal. ++ * @UTRACE_SIGNAL_TERM: Terminate the process. ++ * @UTRACE_SIGNAL_CORE: Terminate with core dump. ++ * @UTRACE_SIGNAL_STOP: Deliver as absolute stop. ++ * @UTRACE_SIGNAL_TSTP: Deliver as job control stop. ++ * @UTRACE_SIGNAL_REPORT: Reporting before pending signals. ++ * @UTRACE_SIGNAL_HANDLER: Reporting after signal handler setup. ++ * ++ * This is encoded in the @action argument and the return value for ++ * a @report_signal() callback. It says what will happen to the ++ * signal described by the &siginfo_t parameter to the callback. ++ * ++ * The %UTRACE_SIGNAL_REPORT value is used in an @action argument when ++ * a tracing report is being made before dequeuing any pending signal. ++ * If this is immediately after a signal handler has been set up, then ++ * %UTRACE_SIGNAL_HANDLER is used instead. A @report_signal callback ++ * that uses %UTRACE_SIGNAL_DELIVER|%UTRACE_SINGLESTEP will ensure ++ * it sees a %UTRACE_SIGNAL_HANDLER report. ++ */ ++enum utrace_signal_action { ++ UTRACE_SIGNAL_DELIVER = 0x00, ++ UTRACE_SIGNAL_IGN = 0x10, ++ UTRACE_SIGNAL_TERM = 0x20, ++ UTRACE_SIGNAL_CORE = 0x30, ++ UTRACE_SIGNAL_STOP = 0x40, ++ UTRACE_SIGNAL_TSTP = 0x50, ++ UTRACE_SIGNAL_REPORT = 0x60, ++ UTRACE_SIGNAL_HANDLER = 0x70 ++}; ++#define UTRACE_SIGNAL_MASK 0xf0 ++#define UTRACE_SIGNAL_HOLD 0x100 /* Flag, push signal back on queue. */ ++ ++/** ++ * utrace_signal_action - &enum utrace_signal_action from callback action ++ * @action: @report_signal callback @action argument or return value ++ * ++ * This extracts the &enum utrace_signal_action from @action, which ++ * is the @action argument to a @report_signal callback or the ++ * return value from one. ++ */ ++static inline enum utrace_signal_action utrace_signal_action(u32 action) ++{ ++ return action & UTRACE_SIGNAL_MASK; ++} ++ ++/** ++ * enum utrace_syscall_action - disposition of system call attempt ++ * @UTRACE_SYSCALL_RUN: Run the system call. ++ * @UTRACE_SYSCALL_ABORT: Don't run the system call. ++ * ++ * This is encoded in the @action argument and the return value for ++ * a @report_syscall_entry callback. ++ */ ++enum utrace_syscall_action { ++ UTRACE_SYSCALL_RUN = 0x00, ++ UTRACE_SYSCALL_ABORT = 0x10 ++}; ++#define UTRACE_SYSCALL_MASK 0xf0 ++#define UTRACE_SYSCALL_RESUMED 0x100 /* Flag, report_syscall_entry() repeats */ ++ ++/** ++ * utrace_syscall_action - &enum utrace_syscall_action from callback action ++ * @action: @report_syscall_entry callback @action or return value ++ * ++ * This extracts the &enum utrace_syscall_action from @action, which ++ * is the @action argument to a @report_syscall_entry callback or the ++ * return value from one. ++ */ ++static inline enum utrace_syscall_action utrace_syscall_action(u32 action) ++{ ++ return action & UTRACE_SYSCALL_MASK; ++} ++ ++/* ++ * Flags for utrace_attach_task() and utrace_attach_pid(). ++ */ ++#define UTRACE_ATTACH_MATCH_OPS 0x0001 /* Match engines on ops. */ ++#define UTRACE_ATTACH_MATCH_DATA 0x0002 /* Match engines on data. */ ++#define UTRACE_ATTACH_MATCH_MASK 0x000f ++#define UTRACE_ATTACH_CREATE 0x0010 /* Attach a new engine. */ ++#define UTRACE_ATTACH_EXCLUSIVE 0x0020 /* Refuse if existing match. */ ++ ++/** ++ * struct utrace_engine - per-engine structure ++ * @ops: &struct utrace_engine_ops pointer passed to utrace_attach_task() ++ * @data: engine-private &void * passed to utrace_attach_task() ++ * @flags: event mask set by utrace_set_events() plus internal flag bits ++ * ++ * The task itself never has to worry about engines detaching while ++ * it's doing event callbacks. These structures are removed from the ++ * task's active list only when it's stopped, or by the task itself. ++ * ++ * utrace_engine_get() and utrace_engine_put() maintain a reference count. ++ * When it drops to zero, the structure is freed. One reference is held ++ * implicitly while the engine is attached to its task. ++ */ ++struct utrace_engine { ++/* private: */ ++ struct kref kref; ++ void (*release)(void *); ++ struct list_head entry; ++ ++/* public: */ ++ const struct utrace_engine_ops *ops; ++ void *data; ++ ++ unsigned long flags; ++}; ++ ++/** ++ * utrace_engine_get - acquire a reference on a &struct utrace_engine ++ * @engine: &struct utrace_engine pointer ++ * ++ * You must hold a reference on @engine, and you get another. ++ */ ++static inline void utrace_engine_get(struct utrace_engine *engine) ++{ ++ kref_get(&engine->kref); ++} ++ ++void __utrace_engine_release(struct kref *); ++ ++/** ++ * utrace_engine_put - release a reference on a &struct utrace_engine ++ * @engine: &struct utrace_engine pointer ++ * ++ * You must hold a reference on @engine, and you lose that reference. ++ * If it was the last one, @engine becomes an invalid pointer. ++ */ ++static inline void utrace_engine_put(struct utrace_engine *engine) ++{ ++ kref_put(&engine->kref, __utrace_engine_release); ++} ++ ++/** ++ * struct utrace_engine_ops - tracing engine callbacks ++ * ++ * Each @report_*() callback corresponds to an %UTRACE_EVENT(*) bit. ++ * utrace_set_events() calls on @engine choose which callbacks will ++ * be made to @engine from @task. ++ * ++ * Most callbacks take an @action argument, giving the resume action ++ * chosen by other tracing engines. All callbacks take an @engine ++ * argument. The @report_reap callback takes a @task argument that ++ * might or might not be @current. All other @report_* callbacks ++ * report an event in the @current task. ++ * ++ * For some calls, @action also includes bits specific to that event ++ * and utrace_resume_action() is used to extract the resume action. ++ * This shows what would happen if @engine wasn't there, or will if ++ * the callback's return value uses %UTRACE_RESUME. This always ++ * starts as %UTRACE_RESUME when no other tracing is being done on ++ * this task. ++ * ++ * All return values contain &enum utrace_resume_action bits. For ++ * some calls, other bits specific to that kind of event are added to ++ * the resume action bits with OR. These are the same bits used in ++ * the @action argument. The resume action returned by a callback ++ * does not override previous engines' choices, it only says what ++ * @engine wants done. What @current actually does is the action that's ++ * most constrained among the choices made by all attached engines. ++ * See utrace_control() for more information on the actions. ++ * ++ * When %UTRACE_STOP is used in @report_syscall_entry, then @current ++ * stops before attempting the system call. In this case, another ++ * @report_syscall_entry callback will follow after @current resumes if ++ * %UTRACE_REPORT or %UTRACE_INTERRUPT was returned by some callback ++ * or passed to utrace_control(). In a second or later callback, ++ * %UTRACE_SYSCALL_RESUMED is set in the @action argument to indicate ++ * a repeat callback still waiting to attempt the same system call ++ * invocation. This repeat callback gives each engine an opportunity ++ * to reexamine registers another engine might have changed while ++ * @current was held in %UTRACE_STOP. ++ * ++ * In other cases, the resume action does not take effect until @current ++ * is ready to check for signals and return to user mode. If there ++ * are more callbacks to be made, the last round of calls determines ++ * the final action. A @report_quiesce callback with @event zero, or ++ * a @report_signal callback, will always be the last one made before ++ * @current resumes. Only %UTRACE_STOP is "sticky"--if @engine returned ++ * %UTRACE_STOP then @current stays stopped unless @engine returns ++ * different from a following callback. ++ * ++ * The report_death() and report_reap() callbacks do not take @action ++ * arguments, and only %UTRACE_DETACH is meaningful in the return value ++ * from a report_death() callback. None of the resume actions applies ++ * to a dead thread. ++ * ++ * All @report_*() hooks are called with no locks held, in a generally ++ * safe environment when we will be returning to user mode soon (or just ++ * entered the kernel). It is fine to block for memory allocation and ++ * the like, but all hooks are asynchronous and must not block on ++ * external events! If you want the thread to block, use %UTRACE_STOP ++ * in your hook's return value; then later wake it up with utrace_control(). ++ * ++ * @report_quiesce: ++ * Requested by %UTRACE_EVENT(%QUIESCE). ++ * This does not indicate any event, but just that @current is in a ++ * safe place for examination. This call is made before each specific ++ * event callback, except for @report_reap. The @event argument gives ++ * the %UTRACE_EVENT(@which) value for the event occurring. This ++ * callback might be made for events @engine has not requested, if ++ * some other engine is tracing the event; calling utrace_set_events() ++ * call here can request the immediate callback for this occurrence of ++ * @event. @event is zero when there is no other event, @current is ++ * now ready to check for signals and return to user mode, and some ++ * engine has used %UTRACE_REPORT or %UTRACE_INTERRUPT to request this ++ * callback. For this case, if @report_signal is not %NULL, the ++ * @report_quiesce callback may be replaced with a @report_signal ++ * callback passing %UTRACE_SIGNAL_REPORT in its @action argument, ++ * whenever @current is entering the signal-check path anyway. ++ * ++ * @report_signal: ++ * Requested by %UTRACE_EVENT(%SIGNAL_*) or %UTRACE_EVENT(%QUIESCE). ++ * Use utrace_signal_action() and utrace_resume_action() on @action. ++ * The signal action is %UTRACE_SIGNAL_REPORT when some engine has ++ * used %UTRACE_REPORT or %UTRACE_INTERRUPT; the callback can choose ++ * to stop or to deliver an artificial signal, before pending signals. ++ * It's %UTRACE_SIGNAL_HANDLER instead when signal handler setup just ++ * finished (after a previous %UTRACE_SIGNAL_DELIVER return); this ++ * serves in lieu of any %UTRACE_SIGNAL_REPORT callback requested by ++ * %UTRACE_REPORT or %UTRACE_INTERRUPT, and is also implicitly ++ * requested by %UTRACE_SINGLESTEP or %UTRACE_BLOCKSTEP into the ++ * signal delivery. The other signal actions indicate a signal about ++ * to be delivered; the previous engine's return value sets the signal ++ * action seen by the the following engine's callback. The @info data ++ * can be changed at will, including @info->si_signo. The settings in ++ * @return_ka determines what %UTRACE_SIGNAL_DELIVER does. @orig_ka ++ * is what was in force before other tracing engines intervened, and ++ * it's %NULL when this report began as %UTRACE_SIGNAL_REPORT or ++ * %UTRACE_SIGNAL_HANDLER. For a report without a new signal, @info ++ * is left uninitialized and must be set completely by an engine that ++ * chooses to deliver a signal; if there was a previous @report_signal ++ * callback ending in %UTRACE_STOP and it was just resumed using ++ * %UTRACE_REPORT or %UTRACE_INTERRUPT, then @info is left unchanged ++ * from the previous callback. In this way, the original signal can ++ * be left in @info while returning %UTRACE_STOP|%UTRACE_SIGNAL_IGN ++ * and then found again when resuming with %UTRACE_INTERRUPT. ++ * The %UTRACE_SIGNAL_HOLD flag bit can be OR'd into the return value, ++ * and might be in @action if the previous engine returned it. This ++ * flag asks that the signal in @info be pushed back on @current's queue ++ * so that it will be seen again after whatever action is taken now. ++ * ++ * @report_clone: ++ * Requested by %UTRACE_EVENT(%CLONE). ++ * Event reported for parent, before the new task @child might run. ++ * @clone_flags gives the flags used in the clone system call, or ++ * equivalent flags for a fork() or vfork() system call. This ++ * function can use utrace_attach_task() on @child. Then passing ++ * %UTRACE_STOP to utrace_control() on @child here keeps the child ++ * stopped before it ever runs in user mode, %UTRACE_REPORT or ++ * %UTRACE_INTERRUPT ensures a callback from @child before it ++ * starts in user mode. ++ * ++ * @report_jctl: ++ * Requested by %UTRACE_EVENT(%JCTL). ++ * Job control event; @type is %CLD_STOPPED or %CLD_CONTINUED, ++ * indicating whether we are stopping or resuming now. If @notify ++ * is nonzero, @current is the last thread to stop and so will send ++ * %SIGCHLD to its parent after this callback; @notify reflects ++ * what the parent's %SIGCHLD has in @si_code, which can sometimes ++ * be %CLD_STOPPED even when @type is %CLD_CONTINUED. ++ * ++ * @report_exec: ++ * Requested by %UTRACE_EVENT(%EXEC). ++ * An execve system call has succeeded and the new program is about to ++ * start running. The initial user register state is handy to be tweaked ++ * directly in @regs. @fmt and @bprm gives the details of this exec. ++ * ++ * @report_syscall_entry: ++ * Requested by %UTRACE_EVENT(%SYSCALL_ENTRY). ++ * Thread has entered the kernel to request a system call. ++ * The user register state is handy to be tweaked directly in @regs. ++ * The @action argument contains an &enum utrace_syscall_action, ++ * use utrace_syscall_action() to extract it. The return value ++ * overrides the last engine's action for the system call. ++ * If the final action is %UTRACE_SYSCALL_ABORT, no system call ++ * is made. The details of the system call being attempted can ++ * be fetched here with syscall_get_nr() and syscall_get_arguments(). ++ * The parameter registers can be changed with syscall_set_arguments(). ++ * See above about the %UTRACE_SYSCALL_RESUMED flag in @action. ++ * Use %UTRACE_REPORT in the return value to guarantee you get ++ * another callback (with %UTRACE_SYSCALL_RESUMED flag) in case ++ * @current stops with %UTRACE_STOP before attempting the system call. ++ * ++ * @report_syscall_exit: ++ * Requested by %UTRACE_EVENT(%SYSCALL_EXIT). ++ * Thread is about to leave the kernel after a system call request. ++ * The user register state is handy to be tweaked directly in @regs. ++ * The results of the system call attempt can be examined here using ++ * syscall_get_error() and syscall_get_return_value(). It is safe ++ * here to call syscall_set_return_value() or syscall_rollback(). ++ * ++ * @report_exit: ++ * Requested by %UTRACE_EVENT(%EXIT). ++ * Thread is exiting and cannot be prevented from doing so, ++ * but all its state is still live. The @code value will be ++ * the wait result seen by the parent, and can be changed by ++ * this engine or others. The @orig_code value is the real ++ * status, not changed by any tracing engine. Returning %UTRACE_STOP ++ * here keeps @current stopped before it cleans up its state and dies, ++ * so it can be examined by other processes. When @current is allowed ++ * to run, it will die and get to the @report_death callback. ++ * ++ * @report_death: ++ * Requested by %UTRACE_EVENT(%DEATH). ++ * Thread is really dead now. It might be reaped by its parent at ++ * any time, or self-reap immediately. Though the actual reaping ++ * may happen in parallel, a report_reap() callback will always be ++ * ordered after a report_death() callback. ++ * ++ * @report_reap: ++ * Requested by %UTRACE_EVENT(%REAP). ++ * Called when someone reaps the dead task (parent, init, or self). ++ * This means the parent called wait, or else this was a detached ++ * thread or a process whose parent ignores SIGCHLD. ++ * No more callbacks are made after this one. ++ * The engine is always detached. ++ * There is nothing more a tracing engine can do about this thread. ++ * After this callback, the @engine pointer will become invalid. ++ * The @task pointer may become invalid if get_task_struct() hasn't ++ * been used to keep it alive. ++ * An engine should always request this callback if it stores the ++ * @engine pointer or stores any pointer in @engine->data, so it ++ * can clean up its data structures. ++ * Unlike other callbacks, this can be called from the parent's context ++ * rather than from the traced thread itself--it must not delay the ++ * parent by blocking. ++ * ++ * @release: ++ * If not %NULL, this is called after the last utrace_engine_put() ++ * call for a &struct utrace_engine, which could be implicit after ++ * a %UTRACE_DETACH return from another callback. Its argument is ++ * the engine's @data member. ++ */ ++struct utrace_engine_ops { ++ u32 (*report_quiesce)(u32 action, struct utrace_engine *engine, ++ unsigned long event); ++ u32 (*report_signal)(u32 action, struct utrace_engine *engine, ++ struct pt_regs *regs, ++ siginfo_t *info, ++ const struct k_sigaction *orig_ka, ++ struct k_sigaction *return_ka); ++ u32 (*report_clone)(u32 action, struct utrace_engine *engine, ++ unsigned long clone_flags, ++ struct task_struct *child); ++ u32 (*report_jctl)(u32 action, struct utrace_engine *engine, ++ int type, int notify); ++ u32 (*report_exec)(u32 action, struct utrace_engine *engine, ++ const struct linux_binfmt *fmt, ++ const struct linux_binprm *bprm, ++ struct pt_regs *regs); ++ u32 (*report_syscall_entry)(u32 action, struct utrace_engine *engine, ++ struct pt_regs *regs); ++ u32 (*report_syscall_exit)(u32 action, struct utrace_engine *engine, ++ struct pt_regs *regs); ++ u32 (*report_exit)(u32 action, struct utrace_engine *engine, ++ long orig_code, long *code); ++ u32 (*report_death)(struct utrace_engine *engine, ++ bool group_dead, int signal); ++ void (*report_reap)(struct utrace_engine *engine, ++ struct task_struct *task); ++ void (*release)(void *data); ++}; ++ ++/** ++ * struct utrace_examiner - private state for using utrace_prepare_examine() ++ * ++ * The members of &struct utrace_examiner are private to the implementation. ++ * This data type holds the state from a call to utrace_prepare_examine() ++ * to be used by a call to utrace_finish_examine(). ++ */ ++struct utrace_examiner { ++/* private: */ ++ long state; ++ unsigned long ncsw; ++}; ++ ++/* ++ * These are the exported entry points for tracing engines to use. ++ * See kernel/utrace.c for their kerneldoc comments with interface details. ++ */ ++struct utrace_engine *utrace_attach_task(struct task_struct *, int, ++ const struct utrace_engine_ops *, ++ void *); ++struct utrace_engine *utrace_attach_pid(struct pid *, int, ++ const struct utrace_engine_ops *, ++ void *); ++int __must_check utrace_control(struct task_struct *, ++ struct utrace_engine *, ++ enum utrace_resume_action); ++int __must_check utrace_set_events(struct task_struct *, ++ struct utrace_engine *, ++ unsigned long eventmask); ++int __must_check utrace_barrier(struct task_struct *, ++ struct utrace_engine *); ++int __must_check utrace_prepare_examine(struct task_struct *, ++ struct utrace_engine *, ++ struct utrace_examiner *); ++int __must_check utrace_finish_examine(struct task_struct *, ++ struct utrace_engine *, ++ struct utrace_examiner *); ++ ++/** ++ * utrace_control_pid - control a thread being traced by a tracing engine ++ * @pid: thread to affect ++ * @engine: attached engine to affect ++ * @action: &enum utrace_resume_action for thread to do ++ * ++ * This is the same as utrace_control(), but takes a &struct pid ++ * pointer rather than a &struct task_struct pointer. The caller must ++ * hold a ref on @pid, but does not need to worry about the task ++ * staying valid. If it's been reaped so that @pid points nowhere, ++ * then this call returns -%ESRCH. ++ */ ++static inline __must_check int utrace_control_pid( ++ struct pid *pid, struct utrace_engine *engine, ++ enum utrace_resume_action action) ++{ ++ /* ++ * We don't bother with rcu_read_lock() here to protect the ++ * task_struct pointer, because utrace_control will return ++ * -ESRCH without looking at that pointer if the engine is ++ * already detached. A task_struct pointer can't die before ++ * all the engines are detached in release_task() first. ++ */ ++ struct task_struct *task = pid_task(pid, PIDTYPE_PID); ++ return unlikely(!task) ? -ESRCH : utrace_control(task, engine, action); ++} ++ ++/** ++ * utrace_set_events_pid - choose which event reports a tracing engine gets ++ * @pid: thread to affect ++ * @engine: attached engine to affect ++ * @eventmask: new event mask ++ * ++ * This is the same as utrace_set_events(), but takes a &struct pid ++ * pointer rather than a &struct task_struct pointer. The caller must ++ * hold a ref on @pid, but does not need to worry about the task ++ * staying valid. If it's been reaped so that @pid points nowhere, ++ * then this call returns -%ESRCH. ++ */ ++static inline __must_check int utrace_set_events_pid( ++ struct pid *pid, struct utrace_engine *engine, unsigned long eventmask) ++{ ++ struct task_struct *task = pid_task(pid, PIDTYPE_PID); ++ return unlikely(!task) ? -ESRCH : ++ utrace_set_events(task, engine, eventmask); ++} ++ ++/** ++ * utrace_barrier_pid - synchronize with simultaneous tracing callbacks ++ * @pid: thread to affect ++ * @engine: engine to affect (can be detached) ++ * ++ * This is the same as utrace_barrier(), but takes a &struct pid ++ * pointer rather than a &struct task_struct pointer. The caller must ++ * hold a ref on @pid, but does not need to worry about the task ++ * staying valid. If it's been reaped so that @pid points nowhere, ++ * then this call returns -%ESRCH. ++ */ ++static inline __must_check int utrace_barrier_pid(struct pid *pid, ++ struct utrace_engine *engine) ++{ ++ struct task_struct *task = pid_task(pid, PIDTYPE_PID); ++ return unlikely(!task) ? -ESRCH : utrace_barrier(task, engine); ++} ++ ++#endif /* CONFIG_UTRACE */ ++ ++#endif /* linux/utrace.h */ +diff --git a/init/Kconfig b/init/Kconfig +index 412c21b..a03ae51 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -372,6 +372,15 @@ config AUDIT_TREE + depends on AUDITSYSCALL + select FSNOTIFY + ++config UTRACE ++ bool "Infrastructure for tracing and debugging user processes" ++ depends on EXPERIMENTAL ++ depends on HAVE_ARCH_TRACEHOOK ++ help ++ Enable the utrace process tracing interface. This is an internal ++ kernel interface exported to kernel modules, to track events in ++ user threads, extract and change user thread state. ++ + source "kernel/irq/Kconfig" + + menu "RCU Subsystem" +diff --git a/kernel/Makefile b/kernel/Makefile +index 2d64cfc..4a22e81 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -68,6 +68,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o + obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o + obj-$(CONFIG_SMP) += stop_machine.o + obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o ++obj-$(CONFIG_UTRACE) += utrace.o + obj-$(CONFIG_AUDIT) += audit.o auditfilter.o + obj-$(CONFIG_AUDITSYSCALL) += auditsc.o + obj-$(CONFIG_AUDIT_WATCH) += audit_watch.o +diff --git a/kernel/fork.c b/kernel/fork.c +index 0276c30..62caf3d 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -168,6 +168,7 @@ void free_task(struct task_struct *tsk) + free_thread_info(tsk->stack); + rt_mutex_debug_task_free(tsk); + ftrace_graph_exit_task(tsk); ++ tracehook_free_task(tsk); + free_task_struct(tsk); + } + EXPORT_SYMBOL(free_task); +@@ -1095,6 +1096,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, + if (!p) + goto fork_out; + ++ tracehook_init_task(p); ++ + ftrace_graph_init_task(p); + + rt_mutex_init_task(p); +diff --git a/kernel/utrace.c b/kernel/utrace.c +new file mode 100644 +index 0000000..f332d65 +--- /dev/null ++++ b/kernel/utrace.c +@@ -0,0 +1,2440 @@ ++/* ++ * utrace infrastructure interface for debugging user processes ++ * ++ * Copyright (C) 2006-2010 Red Hat, Inc. All rights reserved. ++ * ++ * This copyrighted material is made available to anyone wishing to use, ++ * modify, copy, or redistribute it subject to the terms and conditions ++ * of the GNU General Public License v.2. ++ * ++ * Red Hat Author: Roland McGrath. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++/* ++ * Per-thread structure private to utrace implementation. ++ * If task_struct.utrace_flags is nonzero, task_struct.utrace ++ * has always been allocated first. Once allocated, it is ++ * never freed until free_task(). ++ * ++ * The common event reporting loops are done by the task making the ++ * report without ever taking any locks. To facilitate this, the two ++ * lists @attached and @attaching work together for smooth asynchronous ++ * attaching with low overhead. Modifying either list requires @lock. ++ * The @attaching list can be modified any time while holding @lock. ++ * New engines being attached always go on this list. ++ * ++ * The @attached list is what the task itself uses for its reporting ++ * loops. When the task itself is not quiescent, it can use the ++ * @attached list without taking any lock. Nobody may modify the list ++ * when the task is not quiescent. When it is quiescent, that means ++ * that it won't run again without taking @lock itself before using ++ * the list. ++ * ++ * At each place where we know the task is quiescent (or it's current), ++ * while holding @lock, we call splice_attaching(), below. This moves ++ * the @attaching list members on to the end of the @attached list. ++ * Since this happens at the start of any reporting pass, any new ++ * engines attached asynchronously go on the stable @attached list ++ * in time to have their callbacks seen. ++ */ ++struct utrace { ++ spinlock_t lock; ++ struct list_head attached, attaching; ++ ++ struct task_struct *cloning; ++ ++ struct utrace_engine *reporting; ++ ++ enum utrace_resume_action resume:UTRACE_RESUME_BITS; ++ unsigned int signal_handler:1; ++ unsigned int vfork_stop:1; /* need utrace_stop() before vfork wait */ ++ unsigned int death:1; /* in utrace_report_death() now */ ++ unsigned int reap:1; /* release_task() has run */ ++ unsigned int pending_attach:1; /* need splice_attaching() */ ++}; ++ ++static struct kmem_cache *utrace_cachep; ++static struct kmem_cache *utrace_engine_cachep; ++static const struct utrace_engine_ops utrace_detached_ops; /* forward decl */ ++ ++static int __init utrace_init(void) ++{ ++ utrace_cachep = KMEM_CACHE(utrace, SLAB_PANIC); ++ utrace_engine_cachep = KMEM_CACHE(utrace_engine, SLAB_PANIC); ++ return 0; ++} ++module_init(utrace_init); ++ ++/* ++ * Set up @task.utrace for the first time. We can have races ++ * between two utrace_attach_task() calls here. The task_lock() ++ * governs installing the new pointer. If another one got in first, ++ * we just punt the new one we allocated. ++ * ++ * This returns false only in case of a memory allocation failure. ++ */ ++static bool utrace_task_alloc(struct task_struct *task) ++{ ++ struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, GFP_KERNEL); ++ if (unlikely(!utrace)) ++ return false; ++ spin_lock_init(&utrace->lock); ++ INIT_LIST_HEAD(&utrace->attached); ++ INIT_LIST_HEAD(&utrace->attaching); ++ utrace->resume = UTRACE_RESUME; ++ task_lock(task); ++ if (likely(!task->utrace)) { ++ /* ++ * This barrier makes sure the initialization of the struct ++ * precedes the installation of the pointer. This pairs ++ * with smp_read_barrier_depends() in task_utrace_struct(). ++ */ ++ smp_wmb(); ++ task->utrace = utrace; ++ } ++ task_unlock(task); ++ ++ if (unlikely(task->utrace != utrace)) ++ kmem_cache_free(utrace_cachep, utrace); ++ return true; ++} ++ ++/* ++ * This is called via tracehook_free_task() from free_task() ++ * when @task is being deallocated. ++ */ ++void utrace_free_task(struct task_struct *task) ++{ ++ kmem_cache_free(utrace_cachep, task->utrace); ++} ++ ++/* ++ * This is calledwhen the task is safely quiescent, i.e. it won't consult ++ * utrace->attached without the lock. Move any engines attached ++ * asynchronously from @utrace->attaching onto the @utrace->attached list. ++ */ ++static void splice_attaching(struct utrace *utrace) ++{ ++ lockdep_assert_held(&utrace->lock); ++ list_splice_tail_init(&utrace->attaching, &utrace->attached); ++ utrace->pending_attach = 0; ++} ++ ++/* ++ * This is the exported function used by the utrace_engine_put() inline. ++ */ ++void __utrace_engine_release(struct kref *kref) ++{ ++ struct utrace_engine *engine = container_of(kref, struct utrace_engine, ++ kref); ++ BUG_ON(!list_empty(&engine->entry)); ++ if (engine->release) ++ (*engine->release)(engine->data); ++ kmem_cache_free(utrace_engine_cachep, engine); ++} ++EXPORT_SYMBOL_GPL(__utrace_engine_release); ++ ++static bool engine_matches(struct utrace_engine *engine, int flags, ++ const struct utrace_engine_ops *ops, void *data) ++{ ++ if ((flags & UTRACE_ATTACH_MATCH_OPS) && engine->ops != ops) ++ return false; ++ if ((flags & UTRACE_ATTACH_MATCH_DATA) && engine->data != data) ++ return false; ++ return engine->ops && engine->ops != &utrace_detached_ops; ++} ++ ++static struct utrace_engine *find_matching_engine( ++ struct utrace *utrace, int flags, ++ const struct utrace_engine_ops *ops, void *data) ++{ ++ struct utrace_engine *engine; ++ list_for_each_entry(engine, &utrace->attached, entry) ++ if (engine_matches(engine, flags, ops, data)) ++ return engine; ++ list_for_each_entry(engine, &utrace->attaching, entry) ++ if (engine_matches(engine, flags, ops, data)) ++ return engine; ++ return NULL; ++} ++ ++/* ++ * Enqueue @engine, or maybe don't if UTRACE_ATTACH_EXCLUSIVE. ++ */ ++static int utrace_add_engine(struct task_struct *target, ++ struct utrace *utrace, ++ struct utrace_engine *engine, ++ int flags, ++ const struct utrace_engine_ops *ops, ++ void *data) ++{ ++ int ret; ++ ++ spin_lock(&utrace->lock); ++ ++ ret = -EEXIST; ++ if ((flags & UTRACE_ATTACH_EXCLUSIVE) && ++ unlikely(find_matching_engine(utrace, flags, ops, data))) ++ goto unlock; ++ ++ /* ++ * In case we had no engines before, make sure that ++ * utrace_flags is not zero. Since we did unlock+lock ++ * at least once after utrace_task_alloc() installed ++ * ->utrace, we have the necessary barrier which pairs ++ * with rmb() in task_utrace_struct(). ++ */ ++ ret = -ESRCH; ++ if (!target->utrace_flags) { ++ target->utrace_flags = UTRACE_EVENT(REAP); ++ /* ++ * If we race with tracehook_prepare_release_task() ++ * make sure that either it sees utrace_flags != 0 ++ * or we see exit_state == EXIT_DEAD. ++ */ ++ smp_mb(); ++ if (unlikely(target->exit_state == EXIT_DEAD)) { ++ target->utrace_flags = 0; ++ goto unlock; ++ } ++ } ++ ++ /* ++ * Put the new engine on the pending ->attaching list. ++ * Make sure it gets onto the ->attached list by the next ++ * time it's examined. Setting ->pending_attach ensures ++ * that start_report() takes the lock and splices the lists ++ * before the next new reporting pass. ++ * ++ * When target == current, it would be safe just to call ++ * splice_attaching() right here. But if we're inside a ++ * callback, that would mean the new engine also gets ++ * notified about the event that precipitated its own ++ * creation. This is not what the user wants. ++ */ ++ list_add_tail(&engine->entry, &utrace->attaching); ++ utrace->pending_attach = 1; ++ utrace_engine_get(engine); ++ ret = 0; ++unlock: ++ spin_unlock(&utrace->lock); ++ ++ return ret; ++} ++ ++/** ++ * utrace_attach_task - attach new engine, or look up an attached engine ++ * @target: thread to attach to ++ * @flags: flag bits combined with OR, see below ++ * @ops: callback table for new engine ++ * @data: engine private data pointer ++ * ++ * The caller must ensure that the @target thread does not get freed, ++ * i.e. hold a ref or be its parent. It is always safe to call this ++ * on @current, or on the @child pointer in a @report_clone callback. ++ * For most other cases, it's easier to use utrace_attach_pid() instead. ++ * ++ * UTRACE_ATTACH_CREATE: ++ * Create a new engine. If %UTRACE_ATTACH_CREATE is not specified, you ++ * only look up an existing engine already attached to the thread. ++ * ++ * UTRACE_ATTACH_EXCLUSIVE: ++ * Attempting to attach a second (matching) engine fails with -%EEXIST. ++ * ++ * UTRACE_ATTACH_MATCH_OPS: Only consider engines matching @ops. ++ * UTRACE_ATTACH_MATCH_DATA: Only consider engines matching @data. ++ * ++ * Calls with neither %UTRACE_ATTACH_MATCH_OPS nor %UTRACE_ATTACH_MATCH_DATA ++ * match the first among any engines attached to @target. That means that ++ * %UTRACE_ATTACH_EXCLUSIVE in such a call fails with -%EEXIST if there ++ * are any engines on @target at all. ++ */ ++struct utrace_engine *utrace_attach_task( ++ struct task_struct *target, int flags, ++ const struct utrace_engine_ops *ops, void *data) ++{ ++ struct utrace *utrace = task_utrace_struct(target); ++ struct utrace_engine *engine; ++ int ret; ++ ++ if (!(flags & UTRACE_ATTACH_CREATE)) { ++ if (unlikely(!utrace)) ++ return ERR_PTR(-ENOENT); ++ spin_lock(&utrace->lock); ++ engine = find_matching_engine(utrace, flags, ops, data); ++ if (engine) ++ utrace_engine_get(engine); ++ spin_unlock(&utrace->lock); ++ return engine ?: ERR_PTR(-ENOENT); ++ } ++ ++ if (unlikely(!ops) || unlikely(ops == &utrace_detached_ops)) ++ return ERR_PTR(-EINVAL); ++ ++ if (unlikely(target->flags & PF_KTHREAD)) ++ /* ++ * Silly kernel, utrace is for users! ++ */ ++ return ERR_PTR(-EPERM); ++ ++ if (!utrace) { ++ if (unlikely(!utrace_task_alloc(target))) ++ return ERR_PTR(-ENOMEM); ++ utrace = task_utrace_struct(target); ++ } ++ ++ engine = kmem_cache_alloc(utrace_engine_cachep, GFP_KERNEL); ++ if (unlikely(!engine)) ++ return ERR_PTR(-ENOMEM); ++ ++ /* ++ * Initialize the new engine structure. It starts out with one ref ++ * to return. utrace_add_engine() adds another for being attached. ++ */ ++ kref_init(&engine->kref); ++ engine->flags = 0; ++ engine->ops = ops; ++ engine->data = data; ++ engine->release = ops->release; ++ ++ ret = utrace_add_engine(target, utrace, engine, flags, ops, data); ++ ++ if (unlikely(ret)) { ++ kmem_cache_free(utrace_engine_cachep, engine); ++ engine = ERR_PTR(ret); ++ } ++ ++ ++ return engine; ++} ++EXPORT_SYMBOL_GPL(utrace_attach_task); ++ ++/** ++ * utrace_attach_pid - attach new engine, or look up an attached engine ++ * @pid: &struct pid pointer representing thread to attach to ++ * @flags: flag bits combined with OR, see utrace_attach_task() ++ * @ops: callback table for new engine ++ * @data: engine private data pointer ++ * ++ * This is the same as utrace_attach_task(), but takes a &struct pid ++ * pointer rather than a &struct task_struct pointer. The caller must ++ * hold a ref on @pid, but does not need to worry about the task ++ * staying valid. If it's been reaped so that @pid points nowhere, ++ * then this call returns -%ESRCH. ++ */ ++struct utrace_engine *utrace_attach_pid( ++ struct pid *pid, int flags, ++ const struct utrace_engine_ops *ops, void *data) ++{ ++ struct utrace_engine *engine = ERR_PTR(-ESRCH); ++ struct task_struct *task = get_pid_task(pid, PIDTYPE_PID); ++ if (task) { ++ engine = utrace_attach_task(task, flags, ops, data); ++ put_task_struct(task); ++ } ++ return engine; ++} ++EXPORT_SYMBOL_GPL(utrace_attach_pid); ++ ++/* ++ * When an engine is detached, the target thread may still see it and ++ * make callbacks until it quiesces. We install a special ops vector ++ * with these two callbacks. When the target thread quiesces, it can ++ * safely free the engine itself. For any event we will always get ++ * the report_quiesce() callback first, so we only need this one ++ * pointer to be set. The only exception is report_reap(), so we ++ * supply that callback too. ++ */ ++static u32 utrace_detached_quiesce(u32 action, struct utrace_engine *engine, ++ unsigned long event) ++{ ++ return UTRACE_DETACH; ++} ++ ++static void utrace_detached_reap(struct utrace_engine *engine, ++ struct task_struct *task) ++{ ++} ++ ++static const struct utrace_engine_ops utrace_detached_ops = { ++ .report_quiesce = &utrace_detached_quiesce, ++ .report_reap = &utrace_detached_reap ++}; ++ ++/* ++ * The caller has to hold a ref on the engine. If the attached flag is ++ * true (all but utrace_barrier() calls), the engine is supposed to be ++ * attached. If the attached flag is false (utrace_barrier() only), ++ * then return -ERESTARTSYS for an engine marked for detach but not yet ++ * fully detached. The task pointer can be invalid if the engine is ++ * detached. ++ * ++ * Get the utrace lock for the target task. ++ * Returns the struct if locked, or ERR_PTR(-errno). ++ * ++ * This has to be robust against races with: ++ * utrace_control(target, UTRACE_DETACH) calls ++ * UTRACE_DETACH after reports ++ * utrace_report_death ++ * utrace_release_task ++ */ ++static struct utrace *get_utrace_lock(struct task_struct *target, ++ struct utrace_engine *engine, ++ bool attached) ++ __acquires(utrace->lock) ++{ ++ struct utrace *utrace; ++ ++ rcu_read_lock(); ++ ++ /* ++ * If this engine was already detached, bail out before we look at ++ * the task_struct pointer at all. If it's detached after this ++ * check, then RCU is still keeping this task_struct pointer valid. ++ * ++ * The ops pointer is NULL when the engine is fully detached. ++ * It's &utrace_detached_ops when it's marked detached but still ++ * on the list. In the latter case, utrace_barrier() still works, ++ * since the target might be in the middle of an old callback. ++ */ ++ if (unlikely(!engine->ops)) { ++ rcu_read_unlock(); ++ return ERR_PTR(-ESRCH); ++ } ++ ++ if (unlikely(engine->ops == &utrace_detached_ops)) { ++ rcu_read_unlock(); ++ return attached ? ERR_PTR(-ESRCH) : ERR_PTR(-ERESTARTSYS); ++ } ++ ++ utrace = task_utrace_struct(target); ++ spin_lock(&utrace->lock); ++ if (unlikely(utrace->reap) || unlikely(!engine->ops) || ++ unlikely(engine->ops == &utrace_detached_ops)) { ++ /* ++ * By the time we got the utrace lock, ++ * it had been reaped or detached already. ++ */ ++ spin_unlock(&utrace->lock); ++ utrace = ERR_PTR(-ESRCH); ++ if (!attached && engine->ops == &utrace_detached_ops) ++ utrace = ERR_PTR(-ERESTARTSYS); ++ } ++ rcu_read_unlock(); ++ ++ return utrace; ++} ++ ++/* ++ * Now that we don't hold any locks, run through any ++ * detached engines and free their references. Each ++ * engine had one implicit ref while it was attached. ++ */ ++static void put_detached_list(struct list_head *list) ++{ ++ struct utrace_engine *engine, *next; ++ list_for_each_entry_safe(engine, next, list, entry) { ++ list_del_init(&engine->entry); ++ utrace_engine_put(engine); ++ } ++} ++ ++/* ++ * We use an extra bit in utrace_engine.flags past the event bits, ++ * to record whether the engine is keeping the target thread stopped. ++ * ++ * This bit is set in task_struct.utrace_flags whenever it is set in any ++ * engine's flags. Only utrace_reset() resets it in utrace_flags. ++ */ ++#define ENGINE_STOP (1UL << _UTRACE_NEVENTS) ++ ++static void mark_engine_wants_stop(struct task_struct *task, ++ struct utrace_engine *engine) ++{ ++ engine->flags |= ENGINE_STOP; ++ task->utrace_flags |= ENGINE_STOP; ++} ++ ++static void clear_engine_wants_stop(struct utrace_engine *engine) ++{ ++ engine->flags &= ~ENGINE_STOP; ++} ++ ++static bool engine_wants_stop(struct utrace_engine *engine) ++{ ++ return (engine->flags & ENGINE_STOP) != 0; ++} ++ ++/** ++ * utrace_set_events - choose which event reports a tracing engine gets ++ * @target: thread to affect ++ * @engine: attached engine to affect ++ * @events: new event mask ++ * ++ * This changes the set of events for which @engine wants callbacks made. ++ * ++ * This fails with -%EALREADY and does nothing if you try to clear ++ * %UTRACE_EVENT(%DEATH) when the @report_death callback may already have ++ * begun, or if you try to newly set %UTRACE_EVENT(%DEATH) or ++ * %UTRACE_EVENT(%QUIESCE) when @target is already dead or dying. ++ * ++ * This fails with -%ESRCH if you try to clear %UTRACE_EVENT(%REAP) when ++ * the @report_reap callback may already have begun, or when @target has ++ * already been detached, including forcible detach on reaping. ++ * ++ * If @target was stopped before the call, then after a successful call, ++ * no event callbacks not requested in @events will be made; if ++ * %UTRACE_EVENT(%QUIESCE) is included in @events, then a ++ * @report_quiesce callback will be made when @target resumes. ++ * ++ * If @target was not stopped and @events excludes some bits that were ++ * set before, this can return -%EINPROGRESS to indicate that @target ++ * may have been making some callback to @engine. When this returns ++ * zero, you can be sure that no event callbacks you've disabled in ++ * @events can be made. If @events only sets new bits that were not set ++ * before on @engine, then -%EINPROGRESS will never be returned. ++ * ++ * To synchronize after an -%EINPROGRESS return, see utrace_barrier(). ++ * ++ * When @target is @current, -%EINPROGRESS is not returned. But note ++ * that a newly-created engine will not receive any callbacks related to ++ * an event notification already in progress. This call enables @events ++ * callbacks to be made as soon as @engine becomes eligible for any ++ * callbacks, see utrace_attach_task(). ++ * ++ * These rules provide for coherent synchronization based on %UTRACE_STOP, ++ * even when %SIGKILL is breaking its normal simple rules. ++ */ ++int utrace_set_events(struct task_struct *target, ++ struct utrace_engine *engine, ++ unsigned long events) ++{ ++ struct utrace *utrace; ++ unsigned long old_flags, old_utrace_flags; ++ int ret = -EALREADY; ++ ++ /* ++ * We just ignore the internal bit, so callers can use ++ * engine->flags to seed bitwise ops for our argument. ++ */ ++ events &= ~ENGINE_STOP; ++ ++ utrace = get_utrace_lock(target, engine, true); ++ if (unlikely(IS_ERR(utrace))) ++ return PTR_ERR(utrace); ++ ++ old_utrace_flags = target->utrace_flags; ++ old_flags = engine->flags & ~ENGINE_STOP; ++ ++ /* ++ * If utrace_report_death() is already progress now, ++ * it's too late to clear the death event bits. ++ */ ++ if (((old_flags & ~events) & _UTRACE_DEATH_EVENTS) && utrace->death) ++ goto unlock; ++ ++ /* ++ * When setting these flags, it's essential that we really ++ * synchronize with exit_notify(). They cannot be set after ++ * exit_notify() takes the tasklist_lock. By holding the read ++ * lock here while setting the flags, we ensure that the calls ++ * to tracehook_notify_death() and tracehook_report_death() will ++ * see the new flags. This ensures that utrace_release_task() ++ * knows positively that utrace_report_death() will be called or ++ * that it won't. ++ */ ++ if ((events & ~old_flags) & _UTRACE_DEATH_EVENTS) { ++ read_lock(&tasklist_lock); ++ if (unlikely(target->exit_state)) { ++ read_unlock(&tasklist_lock); ++ goto unlock; ++ } ++ target->utrace_flags |= events; ++ read_unlock(&tasklist_lock); ++ } ++ ++ engine->flags = events | (engine->flags & ENGINE_STOP); ++ target->utrace_flags |= events; ++ ++ if ((events & UTRACE_EVENT_SYSCALL) && ++ !(old_utrace_flags & UTRACE_EVENT_SYSCALL)) ++ set_tsk_thread_flag(target, TIF_SYSCALL_TRACE); ++ ++ ret = 0; ++ if ((old_flags & ~events) && target != current && ++ !task_is_stopped_or_traced(target) && !target->exit_state) { ++ /* ++ * This barrier ensures that our engine->flags changes ++ * have hit before we examine utrace->reporting, ++ * pairing with the barrier in start_callback(). If ++ * @target has not yet hit finish_callback() to clear ++ * utrace->reporting, we might be in the middle of a ++ * callback to @engine. ++ */ ++ smp_mb(); ++ if (utrace->reporting == engine) ++ ret = -EINPROGRESS; ++ } ++unlock: ++ spin_unlock(&utrace->lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(utrace_set_events); ++ ++/* ++ * Asynchronously mark an engine as being detached. ++ * ++ * This must work while the target thread races with us doing ++ * start_callback(), defined below. It uses smp_rmb() between checking ++ * @engine->flags and using @engine->ops. Here we change @engine->ops ++ * first, then use smp_wmb() before changing @engine->flags. This ensures ++ * it can check the old flags before using the old ops, or check the old ++ * flags before using the new ops, or check the new flags before using the ++ * new ops, but can never check the new flags before using the old ops. ++ * Hence, utrace_detached_ops might be used with any old flags in place. ++ * It has report_quiesce() and report_reap() callbacks to handle all cases. ++ */ ++static void mark_engine_detached(struct utrace_engine *engine) ++{ ++ engine->ops = &utrace_detached_ops; ++ smp_wmb(); ++ engine->flags = UTRACE_EVENT(QUIESCE); ++} ++ ++/* ++ * Get @target to stop and return true if it is already stopped now. ++ * If we return false, it will make some event callback soonish. ++ * Called with @utrace locked. ++ */ ++static bool utrace_do_stop(struct task_struct *target, struct utrace *utrace) ++{ ++ if (task_is_stopped(target)) { ++ /* ++ * Stopped is considered quiescent; when it wakes up, it will ++ * go through utrace_finish_stop() before doing anything else. ++ */ ++ spin_lock_irq(&target->sighand->siglock); ++ if (likely(task_is_stopped(target))) ++ __set_task_state(target, TASK_TRACED); ++ spin_unlock_irq(&target->sighand->siglock); ++ } else if (utrace->resume > UTRACE_REPORT) { ++ utrace->resume = UTRACE_REPORT; ++ set_notify_resume(target); ++ } ++ ++ return task_is_traced(target); ++} ++ ++/* ++ * If the target is not dead it should not be in tracing ++ * stop any more. Wake it unless it's in job control stop. ++ */ ++static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) ++{ ++ lockdep_assert_held(&utrace->lock); ++ spin_lock_irq(&target->sighand->siglock); ++ if (target->signal->flags & SIGNAL_STOP_STOPPED || ++ target->signal->group_stop_count) ++ target->state = TASK_STOPPED; ++ else ++ wake_up_state(target, __TASK_TRACED); ++ spin_unlock_irq(&target->sighand->siglock); ++} ++ ++/* ++ * This is called when there might be some detached engines on the list or ++ * some stale bits in @task->utrace_flags. Clean them up and recompute the ++ * flags. Returns true if we're now fully detached. ++ * ++ * Called with @utrace->lock held, returns with it released. ++ * After this returns, @utrace might be freed if everything detached. ++ */ ++static bool utrace_reset(struct task_struct *task, struct utrace *utrace) ++ __releases(utrace->lock) ++{ ++ struct utrace_engine *engine, *next; ++ unsigned long flags = 0; ++ LIST_HEAD(detached); ++ ++ splice_attaching(utrace); ++ ++ /* ++ * Update the set of events of interest from the union ++ * of the interests of the remaining tracing engines. ++ * For any engine marked detached, remove it from the list. ++ * We'll collect them on the detached list. ++ */ ++ list_for_each_entry_safe(engine, next, &utrace->attached, entry) { ++ if (engine->ops == &utrace_detached_ops) { ++ engine->ops = NULL; ++ list_move(&engine->entry, &detached); ++ } else { ++ flags |= engine->flags | UTRACE_EVENT(REAP); ++ } ++ } ++ ++ if (task->exit_state) { ++ /* ++ * Once it's already dead, we never install any flags ++ * except REAP. When ->exit_state is set and events ++ * like DEATH are not set, then they never can be set. ++ * This ensures that utrace_release_task() knows ++ * positively that utrace_report_death() can never run. ++ */ ++ BUG_ON(utrace->death); ++ flags &= UTRACE_EVENT(REAP); ++ } else if (!(flags & UTRACE_EVENT_SYSCALL) && ++ test_tsk_thread_flag(task, TIF_SYSCALL_TRACE)) { ++ clear_tsk_thread_flag(task, TIF_SYSCALL_TRACE); ++ } ++ ++ if (!flags) { ++ /* ++ * No more engines, cleared out the utrace. ++ */ ++ utrace->resume = UTRACE_RESUME; ++ utrace->signal_handler = 0; ++ } ++ ++ /* ++ * If no more engines want it stopped, wake it up. ++ */ ++ if (task_is_traced(task) && !(flags & ENGINE_STOP)) { ++ /* ++ * It just resumes, so make sure single-step ++ * is not left set. ++ */ ++ if (utrace->resume == UTRACE_RESUME) ++ user_disable_single_step(task); ++ utrace_wakeup(task, utrace); ++ } ++ ++ /* ++ * In theory spin_lock() doesn't imply rcu_read_lock(). ++ * Once we clear ->utrace_flags this task_struct can go away ++ * because tracehook_prepare_release_task() path does not take ++ * utrace->lock when ->utrace_flags == 0. ++ */ ++ rcu_read_lock(); ++ task->utrace_flags = flags; ++ spin_unlock(&utrace->lock); ++ rcu_read_unlock(); ++ ++ put_detached_list(&detached); ++ ++ return !flags; ++} ++ ++void utrace_finish_stop(void) ++{ ++ /* ++ * If we were task_is_traced() and then SIGKILL'ed, make ++ * sure we do nothing until the tracer drops utrace->lock. ++ */ ++ if (unlikely(__fatal_signal_pending(current))) { ++ struct utrace *utrace = task_utrace_struct(current); ++ spin_unlock_wait(&utrace->lock); ++ } ++} ++ ++/* ++ * Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up. ++ * @task == current, @utrace == current->utrace, which is not locked. ++ * Return true if we were woken up by SIGKILL even though some utrace ++ * engine may still want us to stay stopped. ++ */ ++static void utrace_stop(struct task_struct *task, struct utrace *utrace, ++ enum utrace_resume_action action) ++{ ++relock: ++ spin_lock(&utrace->lock); ++ ++ if (action < utrace->resume) { ++ /* ++ * Ensure a reporting pass when we're resumed. ++ */ ++ utrace->resume = action; ++ if (action == UTRACE_INTERRUPT) ++ set_thread_flag(TIF_SIGPENDING); ++ else ++ set_thread_flag(TIF_NOTIFY_RESUME); ++ } ++ ++ /* ++ * If the ENGINE_STOP bit is clear in utrace_flags, that means ++ * utrace_reset() ran after we processed some UTRACE_STOP return ++ * values from callbacks to get here. If all engines have detached ++ * or resumed us, we don't stop. This check doesn't require ++ * siglock, but it should follow the interrupt/report bookkeeping ++ * steps (this can matter for UTRACE_RESUME but not UTRACE_DETACH). ++ */ ++ if (unlikely(!(task->utrace_flags & ENGINE_STOP))) { ++ utrace_reset(task, utrace); ++ if (task->utrace_flags & ENGINE_STOP) ++ goto relock; ++ return; ++ } ++ ++ /* ++ * The siglock protects us against signals. As well as SIGKILL ++ * waking us up, we must synchronize with the signal bookkeeping ++ * for stop signals and SIGCONT. ++ */ ++ spin_lock_irq(&task->sighand->siglock); ++ ++ if (unlikely(__fatal_signal_pending(task))) { ++ spin_unlock_irq(&task->sighand->siglock); ++ spin_unlock(&utrace->lock); ++ return; ++ } ++ ++ __set_current_state(TASK_TRACED); ++ ++ /* ++ * If there is a group stop in progress, ++ * we must participate in the bookkeeping. ++ */ ++ if (unlikely(task->signal->group_stop_count) && ++ !--task->signal->group_stop_count) ++ task->signal->flags = SIGNAL_STOP_STOPPED; ++ ++ spin_unlock_irq(&task->sighand->siglock); ++ spin_unlock(&utrace->lock); ++ ++ schedule(); ++ ++ utrace_finish_stop(); ++ ++ /* ++ * While in TASK_TRACED, we were considered "frozen enough". ++ * Now that we woke up, it's crucial if we're supposed to be ++ * frozen that we freeze now before running anything substantial. ++ */ ++ try_to_freeze(); ++ ++ /* ++ * While we were in TASK_TRACED, complete_signal() considered ++ * us "uninterested" in signal wakeups. Now make sure our ++ * TIF_SIGPENDING state is correct for normal running. ++ */ ++ spin_lock_irq(&task->sighand->siglock); ++ recalc_sigpending(); ++ spin_unlock_irq(&task->sighand->siglock); ++} ++ ++/* ++ * Called by release_task() with @reap set to true. ++ * Called by utrace_report_death() with @reap set to false. ++ * On reap, make report_reap callbacks and clean out @utrace ++ * unless still making callbacks. On death, update bookkeeping ++ * and handle the reap work if release_task() came in first. ++ */ ++void utrace_maybe_reap(struct task_struct *target, struct utrace *utrace, ++ bool reap) ++{ ++ struct utrace_engine *engine, *next; ++ struct list_head attached; ++ ++ spin_lock(&utrace->lock); ++ ++ if (reap) { ++ /* ++ * If the target will do some final callbacks but hasn't ++ * finished them yet, we know because it clears these event ++ * bits after it's done. Instead of cleaning up here and ++ * requiring utrace_report_death() to cope with it, we ++ * delay the REAP report and the teardown until after the ++ * target finishes its death reports. ++ */ ++ utrace->reap = 1; ++ ++ if (target->utrace_flags & _UTRACE_DEATH_EVENTS) { ++ spin_unlock(&utrace->lock); ++ return; ++ } ++ } else { ++ /* ++ * After we unlock with this flag clear, any competing ++ * utrace_control/utrace_set_events calls know that we've ++ * finished our callbacks and any detach bookkeeping. ++ */ ++ utrace->death = 0; ++ ++ if (!utrace->reap) { ++ /* ++ * We're just dead, not reaped yet. This will ++ * reset @target->utrace_flags so the later call ++ * with @reap set won't hit the check above. ++ */ ++ utrace_reset(target, utrace); ++ return; ++ } ++ } ++ ++ /* ++ * utrace_add_engine() checks ->utrace_flags != 0. Since ++ * @utrace->reap is set, nobody can set or clear UTRACE_EVENT(REAP) ++ * in @engine->flags or change @engine->ops and nobody can change ++ * @utrace->attached after we drop the lock. ++ */ ++ target->utrace_flags = 0; ++ ++ /* ++ * We clear out @utrace->attached before we drop the lock so ++ * that find_matching_engine() can't come across any old engine ++ * while we are busy tearing it down. ++ */ ++ list_replace_init(&utrace->attached, &attached); ++ list_splice_tail_init(&utrace->attaching, &attached); ++ ++ spin_unlock(&utrace->lock); ++ ++ list_for_each_entry_safe(engine, next, &attached, entry) { ++ if (engine->flags & UTRACE_EVENT(REAP)) ++ engine->ops->report_reap(engine, target); ++ ++ engine->ops = NULL; ++ engine->flags = 0; ++ list_del_init(&engine->entry); ++ ++ utrace_engine_put(engine); ++ } ++} ++ ++/* ++ * You can't do anything to a dead task but detach it. ++ * If release_task() has been called, you can't do that. ++ * ++ * On the exit path, DEATH and QUIESCE event bits are set only ++ * before utrace_report_death() has taken the lock. At that point, ++ * the death report will come soon, so disallow detach until it's ++ * done. This prevents us from racing with it detaching itself. ++ * ++ * Called only when @target->exit_state is nonzero. ++ */ ++static inline int utrace_control_dead(struct task_struct *target, ++ struct utrace *utrace, ++ enum utrace_resume_action action) ++{ ++ lockdep_assert_held(&utrace->lock); ++ ++ if (action != UTRACE_DETACH || unlikely(utrace->reap)) ++ return -ESRCH; ++ ++ if (unlikely(utrace->death)) ++ /* ++ * We have already started the death report. We can't ++ * prevent the report_death and report_reap callbacks, ++ * so tell the caller they will happen. ++ */ ++ return -EALREADY; ++ ++ return 0; ++} ++ ++/** ++ * utrace_control - control a thread being traced by a tracing engine ++ * @target: thread to affect ++ * @engine: attached engine to affect ++ * @action: &enum utrace_resume_action for thread to do ++ * ++ * This is how a tracing engine asks a traced thread to do something. ++ * This call is controlled by the @action argument, which has the ++ * same meaning as the &enum utrace_resume_action value returned by ++ * event reporting callbacks. ++ * ++ * If @target is already dead (@target->exit_state nonzero), ++ * all actions except %UTRACE_DETACH fail with -%ESRCH. ++ * ++ * The following sections describe each option for the @action argument. ++ * ++ * UTRACE_DETACH: ++ * ++ * After this, the @engine data structure is no longer accessible, ++ * and the thread might be reaped. The thread will start running ++ * again if it was stopped and no longer has any attached engines ++ * that want it stopped. ++ * ++ * If the @report_reap callback may already have begun, this fails ++ * with -%ESRCH. If the @report_death callback may already have ++ * begun, this fails with -%EALREADY. ++ * ++ * If @target is not already stopped, then a callback to this engine ++ * might be in progress or about to start on another CPU. If so, ++ * then this returns -%EINPROGRESS; the detach happens as soon as ++ * the pending callback is finished. To synchronize after an ++ * -%EINPROGRESS return, see utrace_barrier(). ++ * ++ * If @target is properly stopped before utrace_control() is called, ++ * then after successful return it's guaranteed that no more callbacks ++ * to the @engine->ops vector will be made. ++ * ++ * The only exception is %SIGKILL (and exec or group-exit by another ++ * thread in the group), which can cause asynchronous @report_death ++ * and/or @report_reap callbacks even when %UTRACE_STOP was used. ++ * (In that event, this fails with -%ESRCH or -%EALREADY, see above.) ++ * ++ * UTRACE_STOP: ++ * ++ * This asks that @target stop running. This returns 0 only if ++ * @target is already stopped, either for tracing or for job ++ * control. Then @target will remain stopped until another ++ * utrace_control() call is made on @engine; @target can be woken ++ * only by %SIGKILL (or equivalent, such as exec or termination by ++ * another thread in the same thread group). ++ * ++ * This returns -%EINPROGRESS if @target is not already stopped. ++ * Then the effect is like %UTRACE_REPORT. A @report_quiesce or ++ * @report_signal callback will be made soon. Your callback can ++ * then return %UTRACE_STOP to keep @target stopped. ++ * ++ * This does not interrupt system calls in progress, including ones ++ * that sleep for a long time. For that, use %UTRACE_INTERRUPT. ++ * To interrupt system calls and then keep @target stopped, your ++ * @report_signal callback can return %UTRACE_STOP. ++ * ++ * UTRACE_RESUME: ++ * ++ * Just let @target continue running normally, reversing the effect ++ * of a previous %UTRACE_STOP. If another engine is keeping @target ++ * stopped, then it remains stopped until all engines let it resume. ++ * If @target was not stopped, this has no effect. ++ * ++ * UTRACE_REPORT: ++ * ++ * This is like %UTRACE_RESUME, but also ensures that there will be ++ * a @report_quiesce or @report_signal callback made soon. If ++ * @target had been stopped, then there will be a callback before it ++ * resumes running normally. If another engine is keeping @target ++ * stopped, then there might be no callbacks until all engines let ++ * it resume. ++ * ++ * Since this is meaningless unless @report_quiesce callbacks will ++ * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). ++ * ++ * UTRACE_INTERRUPT: ++ * ++ * This is like %UTRACE_REPORT, but ensures that @target will make a ++ * @report_signal callback before it resumes or delivers signals. ++ * If @target was in a system call or about to enter one, work in ++ * progress will be interrupted as if by %SIGSTOP. If another ++ * engine is keeping @target stopped, then there might be no ++ * callbacks until all engines let it resume. ++ * ++ * This gives @engine an opportunity to introduce a forced signal ++ * disposition via its @report_signal callback. ++ * ++ * UTRACE_SINGLESTEP: ++ * ++ * It's invalid to use this unless arch_has_single_step() returned true. ++ * This is like %UTRACE_RESUME, but resumes for one user instruction only. ++ * ++ * Note that passing %UTRACE_SINGLESTEP or %UTRACE_BLOCKSTEP to ++ * utrace_control() or returning it from an event callback alone does ++ * not necessarily ensure that stepping will be enabled. If there are ++ * more callbacks made to any engine before returning to user mode, ++ * then the resume action is chosen only by the last set of callbacks. ++ * To be sure, enable %UTRACE_EVENT(%QUIESCE) and look for the ++ * @report_quiesce callback with a zero event mask, or the ++ * @report_signal callback with %UTRACE_SIGNAL_REPORT. ++ * ++ * Since this is not robust unless @report_quiesce callbacks will ++ * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). ++ * ++ * UTRACE_BLOCKSTEP: ++ * ++ * It's invalid to use this unless arch_has_block_step() returned true. ++ * This is like %UTRACE_SINGLESTEP, but resumes for one whole basic ++ * block of user instructions. ++ * ++ * Since this is not robust unless @report_quiesce callbacks will ++ * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). ++ * ++ * %UTRACE_BLOCKSTEP devolves to %UTRACE_SINGLESTEP when another ++ * tracing engine is using %UTRACE_SINGLESTEP at the same time. ++ */ ++int utrace_control(struct task_struct *target, ++ struct utrace_engine *engine, ++ enum utrace_resume_action action) ++{ ++ struct utrace *utrace; ++ bool reset; ++ int ret; ++ ++ if (unlikely(action >= UTRACE_RESUME_MAX)) { ++ WARN(1, "invalid action argument to utrace_control()!"); ++ return -EINVAL; ++ } ++ ++ /* ++ * This is a sanity check for a programming error in the caller. ++ * Their request can only work properly in all cases by relying on ++ * a follow-up callback, but they didn't set one up! This check ++ * doesn't do locking, but it shouldn't matter. The caller has to ++ * be synchronously sure the callback is set up to be operating the ++ * interface properly. ++ */ ++ if (action >= UTRACE_REPORT && action < UTRACE_RESUME && ++ unlikely(!(engine->flags & UTRACE_EVENT(QUIESCE)))) { ++ WARN(1, "utrace_control() with no QUIESCE callback in place!"); ++ return -EINVAL; ++ } ++ ++ utrace = get_utrace_lock(target, engine, true); ++ if (unlikely(IS_ERR(utrace))) ++ return PTR_ERR(utrace); ++ ++ reset = task_is_traced(target); ++ ret = 0; ++ ++ /* ++ * ->exit_state can change under us, this doesn't matter. ++ * We do not care about ->exit_state in fact, but we do ++ * care about ->reap and ->death. If either flag is set, ++ * we must also see ->exit_state != 0. ++ */ ++ if (unlikely(target->exit_state)) { ++ ret = utrace_control_dead(target, utrace, action); ++ if (ret) { ++ spin_unlock(&utrace->lock); ++ return ret; ++ } ++ reset = true; ++ } ++ ++ switch (action) { ++ case UTRACE_STOP: ++ mark_engine_wants_stop(target, engine); ++ if (!reset && !utrace_do_stop(target, utrace)) ++ ret = -EINPROGRESS; ++ reset = false; ++ break; ++ ++ case UTRACE_DETACH: ++ if (engine_wants_stop(engine)) ++ target->utrace_flags &= ~ENGINE_STOP; ++ mark_engine_detached(engine); ++ reset = reset || utrace_do_stop(target, utrace); ++ if (!reset) { ++ /* ++ * As in utrace_set_events(), this barrier ensures ++ * that our engine->flags changes have hit before we ++ * examine utrace->reporting, pairing with the barrier ++ * in start_callback(). If @target has not yet hit ++ * finish_callback() to clear utrace->reporting, we ++ * might be in the middle of a callback to @engine. ++ */ ++ smp_mb(); ++ if (utrace->reporting == engine) ++ ret = -EINPROGRESS; ++ } ++ break; ++ ++ case UTRACE_RESUME: ++ clear_engine_wants_stop(engine); ++ break; ++ ++ case UTRACE_BLOCKSTEP: ++ /* ++ * Resume from stopped, step one block. ++ * We fall through to treat it like UTRACE_SINGLESTEP. ++ */ ++ if (unlikely(!arch_has_block_step())) { ++ WARN(1, "UTRACE_BLOCKSTEP when !arch_has_block_step()"); ++ action = UTRACE_SINGLESTEP; ++ } ++ ++ case UTRACE_SINGLESTEP: ++ /* ++ * Resume from stopped, step one instruction. ++ * We fall through to the UTRACE_REPORT case. ++ */ ++ if (unlikely(!arch_has_single_step())) { ++ WARN(1, ++ "UTRACE_SINGLESTEP when !arch_has_single_step()"); ++ reset = false; ++ ret = -EOPNOTSUPP; ++ break; ++ } ++ ++ case UTRACE_REPORT: ++ /* ++ * Make the thread call tracehook_notify_resume() soon. ++ * But don't bother if it's already been interrupted. ++ * In that case, utrace_get_signal() will be reporting soon. ++ */ ++ clear_engine_wants_stop(engine); ++ if (action < utrace->resume) { ++ utrace->resume = action; ++ set_notify_resume(target); ++ } ++ break; ++ ++ case UTRACE_INTERRUPT: ++ /* ++ * Make the thread call tracehook_get_signal() soon. ++ */ ++ clear_engine_wants_stop(engine); ++ if (utrace->resume == UTRACE_INTERRUPT) ++ break; ++ utrace->resume = UTRACE_INTERRUPT; ++ ++ /* ++ * If it's not already stopped, interrupt it now. We need ++ * the siglock here in case it calls recalc_sigpending() ++ * and clears its own TIF_SIGPENDING. By taking the lock, ++ * we've serialized any later recalc_sigpending() after our ++ * setting of utrace->resume to force it on. ++ */ ++ if (reset) { ++ /* ++ * This is really just to keep the invariant that ++ * TIF_SIGPENDING is set with UTRACE_INTERRUPT. ++ * When it's stopped, we know it's always going ++ * through utrace_get_signal() and will recalculate. ++ */ ++ set_tsk_thread_flag(target, TIF_SIGPENDING); ++ } else { ++ struct sighand_struct *sighand; ++ unsigned long irqflags; ++ sighand = lock_task_sighand(target, &irqflags); ++ if (likely(sighand)) { ++ signal_wake_up(target, 0); ++ unlock_task_sighand(target, &irqflags); ++ } ++ } ++ break; ++ ++ default: ++ BUG(); /* We checked it on entry. */ ++ } ++ ++ /* ++ * Let the thread resume running. If it's not stopped now, ++ * there is nothing more we need to do. ++ */ ++ if (reset) ++ utrace_reset(target, utrace); ++ else ++ spin_unlock(&utrace->lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(utrace_control); ++ ++/** ++ * utrace_barrier - synchronize with simultaneous tracing callbacks ++ * @target: thread to affect ++ * @engine: engine to affect (can be detached) ++ * ++ * This blocks while @target might be in the midst of making a callback to ++ * @engine. It can be interrupted by signals and will return -%ERESTARTSYS. ++ * A return value of zero means no callback from @target to @engine was ++ * in progress. Any effect of its return value (such as %UTRACE_STOP) has ++ * already been applied to @engine. ++ * ++ * It's not necessary to keep the @target pointer alive for this call. ++ * It's only necessary to hold a ref on @engine. This will return ++ * safely even if @target has been reaped and has no task refs. ++ * ++ * A successful return from utrace_barrier() guarantees its ordering ++ * with respect to utrace_set_events() and utrace_control() calls. If ++ * @target was not properly stopped, event callbacks just disabled might ++ * still be in progress; utrace_barrier() waits until there is no chance ++ * an unwanted callback can be in progress. ++ */ ++int utrace_barrier(struct task_struct *target, struct utrace_engine *engine) ++{ ++ struct utrace *utrace; ++ int ret = -ERESTARTSYS; ++ ++ if (unlikely(target == current)) ++ return 0; ++ ++ do { ++ utrace = get_utrace_lock(target, engine, false); ++ if (unlikely(IS_ERR(utrace))) { ++ ret = PTR_ERR(utrace); ++ if (ret != -ERESTARTSYS) ++ break; ++ } else { ++ /* ++ * All engine state changes are done while ++ * holding the lock, i.e. before we get here. ++ * Since we have the lock, we only need to ++ * worry about @target making a callback. ++ * When it has entered start_callback() but ++ * not yet gotten to finish_callback(), we ++ * will see utrace->reporting == @engine. ++ * When @target doesn't take the lock, it uses ++ * barriers to order setting utrace->reporting ++ * before it examines the engine state. ++ */ ++ if (utrace->reporting != engine) ++ ret = 0; ++ spin_unlock(&utrace->lock); ++ if (!ret) ++ break; ++ } ++ schedule_timeout_interruptible(1); ++ } while (!signal_pending(current)); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(utrace_barrier); ++ ++/* ++ * This is local state used for reporting loops, perhaps optimized away. ++ */ ++struct utrace_report { ++ u32 result; ++ enum utrace_resume_action action; ++ enum utrace_resume_action resume_action; ++ bool detaches; ++ bool spurious; ++}; ++ ++#define INIT_REPORT(var) \ ++ struct utrace_report var = { \ ++ .action = UTRACE_RESUME, \ ++ .resume_action = UTRACE_RESUME, \ ++ .spurious = true \ ++ } ++ ++/* ++ * We are now making the report, so clear the flag saying we need one. ++ * When there is a new attach, ->pending_attach is set just so we will ++ * know to do splice_attaching() here before the callback loop. ++ */ ++static enum utrace_resume_action start_report(struct utrace *utrace) ++{ ++ enum utrace_resume_action resume = utrace->resume; ++ if (utrace->pending_attach || ++ (resume > UTRACE_INTERRUPT && resume < UTRACE_RESUME)) { ++ spin_lock(&utrace->lock); ++ splice_attaching(utrace); ++ resume = utrace->resume; ++ if (resume > UTRACE_INTERRUPT) ++ utrace->resume = UTRACE_RESUME; ++ spin_unlock(&utrace->lock); ++ } ++ return resume; ++} ++ ++static inline void finish_report_reset(struct task_struct *task, ++ struct utrace *utrace, ++ struct utrace_report *report) ++{ ++ if (unlikely(report->spurious || report->detaches)) { ++ spin_lock(&utrace->lock); ++ if (utrace_reset(task, utrace)) ++ report->action = UTRACE_RESUME; ++ } ++} ++ ++/* ++ * Complete a normal reporting pass, pairing with a start_report() call. ++ * This handles any UTRACE_DETACH or UTRACE_REPORT or UTRACE_INTERRUPT ++ * returns from engine callbacks. If @will_not_stop is true and any ++ * engine's last callback used UTRACE_STOP, we do UTRACE_REPORT here to ++ * ensure we stop before user mode. If there were no callbacks made, it ++ * will recompute @task->utrace_flags to avoid another false-positive. ++ */ ++static void finish_report(struct task_struct *task, struct utrace *utrace, ++ struct utrace_report *report, bool will_not_stop) ++{ ++ enum utrace_resume_action resume = report->action; ++ ++ if (resume == UTRACE_STOP) ++ resume = will_not_stop ? UTRACE_REPORT : UTRACE_RESUME; ++ ++ if (resume < utrace->resume) { ++ spin_lock(&utrace->lock); ++ utrace->resume = resume; ++ if (resume == UTRACE_INTERRUPT) ++ set_tsk_thread_flag(task, TIF_SIGPENDING); ++ else ++ set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); ++ spin_unlock(&utrace->lock); ++ } ++ ++ finish_report_reset(task, utrace, report); ++} ++ ++static void finish_callback_report(struct task_struct *task, ++ struct utrace *utrace, ++ struct utrace_report *report, ++ struct utrace_engine *engine, ++ enum utrace_resume_action action) ++{ ++ if (action == UTRACE_DETACH) { ++ /* ++ * By holding the lock here, we make sure that ++ * utrace_barrier() (really get_utrace_lock()) sees the ++ * effect of this detach. Otherwise utrace_barrier() could ++ * return 0 after this callback had returned UTRACE_DETACH. ++ * This way, a 0 return is an unambiguous indicator that any ++ * callback returning UTRACE_DETACH has indeed caused detach. ++ */ ++ spin_lock(&utrace->lock); ++ engine->ops = &utrace_detached_ops; ++ spin_unlock(&utrace->lock); ++ } ++ ++ /* ++ * If utrace_control() was used, treat that like UTRACE_DETACH here. ++ */ ++ if (engine->ops == &utrace_detached_ops) { ++ report->detaches = true; ++ return; ++ } ++ ++ if (action < report->action) ++ report->action = action; ++ ++ if (action != UTRACE_STOP) { ++ if (action < report->resume_action) ++ report->resume_action = action; ++ ++ if (engine_wants_stop(engine)) { ++ spin_lock(&utrace->lock); ++ clear_engine_wants_stop(engine); ++ spin_unlock(&utrace->lock); ++ } ++ ++ return; ++ } ++ ++ if (!engine_wants_stop(engine)) { ++ spin_lock(&utrace->lock); ++ /* ++ * If utrace_control() came in and detached us ++ * before we got the lock, we must not stop now. ++ */ ++ if (unlikely(engine->ops == &utrace_detached_ops)) ++ report->detaches = true; ++ else ++ mark_engine_wants_stop(task, engine); ++ spin_unlock(&utrace->lock); ++ } ++} ++ ++/* ++ * Apply the return value of one engine callback to @report. ++ * Returns true if @engine detached and should not get any more callbacks. ++ */ ++static bool finish_callback(struct task_struct *task, struct utrace *utrace, ++ struct utrace_report *report, ++ struct utrace_engine *engine, ++ u32 ret) ++{ ++ report->result = ret & ~UTRACE_RESUME_MASK; ++ finish_callback_report(task, utrace, report, engine, ++ utrace_resume_action(ret)); ++ ++ /* ++ * Now that we have applied the effect of the return value, ++ * clear this so that utrace_barrier() can stop waiting. ++ * A subsequent utrace_control() can stop or resume @engine ++ * and know this was ordered after its callback's action. ++ * ++ * We don't need any barriers here because utrace_barrier() ++ * takes utrace->lock. If we touched engine->flags above, ++ * the lock guaranteed this change was before utrace_barrier() ++ * examined utrace->reporting. ++ */ ++ utrace->reporting = NULL; ++ ++ /* ++ * We've just done an engine callback. These are allowed to sleep, ++ * though all well-behaved ones restrict that to blocking kalloc() ++ * or quickly-acquired mutex_lock() and the like. This is a good ++ * place to make sure tracing engines don't introduce too much ++ * latency under voluntary preemption. ++ */ ++ might_sleep(); ++ ++ return engine->ops == &utrace_detached_ops; ++} ++ ++/* ++ * Start the callbacks for @engine to consider @event (a bit mask). ++ * This makes the report_quiesce() callback first. If @engine wants ++ * a specific callback for @event, we return the ops vector to use. ++ * If not, we return NULL. The return value from the ops->callback ++ * function called should be passed to finish_callback(). ++ */ ++static const struct utrace_engine_ops *start_callback( ++ struct utrace *utrace, struct utrace_report *report, ++ struct utrace_engine *engine, struct task_struct *task, ++ unsigned long event) ++{ ++ const struct utrace_engine_ops *ops; ++ unsigned long want; ++ ++ /* ++ * This barrier ensures that we've set utrace->reporting before ++ * we examine engine->flags or engine->ops. utrace_barrier() ++ * relies on this ordering to indicate that the effect of any ++ * utrace_control() and utrace_set_events() calls is in place ++ * by the time utrace->reporting can be seen to be NULL. ++ */ ++ utrace->reporting = engine; ++ smp_mb(); ++ ++ /* ++ * This pairs with the barrier in mark_engine_detached(). ++ * It makes sure that we never see the old ops vector with ++ * the new flags, in case the original vector had no report_quiesce. ++ */ ++ want = engine->flags; ++ smp_rmb(); ++ ops = engine->ops; ++ ++ if ((want & UTRACE_EVENT(QUIESCE)) || ops == &utrace_detached_ops) { ++ if (finish_callback(task, utrace, report, engine, ++ (*ops->report_quiesce)(report->action, ++ engine, event))) ++ return NULL; ++ ++ if (!event) { ++ /* We only got here to report QUIESCE */ ++ report->spurious = false; ++ return NULL; ++ } ++ ++ /* ++ * finish_callback() reset utrace->reporting after the ++ * quiesce callback. Now we set it again (as above) ++ * before re-examining engine->flags, which could have ++ * been changed synchronously by ->report_quiesce or ++ * asynchronously by utrace_control() or utrace_set_events(). ++ */ ++ utrace->reporting = engine; ++ smp_mb(); ++ want = engine->flags; ++ } ++ ++ if (want & ENGINE_STOP) ++ report->action = UTRACE_STOP; ++ ++ if (want & event) { ++ report->spurious = false; ++ return ops; ++ } ++ ++ utrace->reporting = NULL; ++ return NULL; ++} ++ ++/* ++ * Do a normal reporting pass for engines interested in @event. ++ * @callback is the name of the member in the ops vector, and remaining ++ * args are the extras it takes after the standard three args. ++ */ ++#define REPORT_CALLBACKS(rev, task, utrace, report, event, callback, ...) \ ++ do { \ ++ struct utrace_engine *engine; \ ++ const struct utrace_engine_ops *ops; \ ++ list_for_each_entry##rev(engine, &utrace->attached, entry) { \ ++ ops = start_callback(utrace, report, engine, task, \ ++ event); \ ++ if (!ops) \ ++ continue; \ ++ finish_callback(task, utrace, report, engine, \ ++ (*ops->callback)(__VA_ARGS__)); \ ++ } \ ++ } while (0) ++#define REPORT(task, utrace, report, event, callback, ...) \ ++ do { \ ++ start_report(utrace); \ ++ REPORT_CALLBACKS(, task, utrace, report, event, callback, \ ++ (report)->action, engine, ## __VA_ARGS__); \ ++ finish_report(task, utrace, report, true); \ ++ } while (0) ++ ++/* ++ * Called iff UTRACE_EVENT(EXEC) flag is set. ++ */ ++void utrace_report_exec(struct linux_binfmt *fmt, struct linux_binprm *bprm, ++ struct pt_regs *regs) ++{ ++ struct task_struct *task = current; ++ struct utrace *utrace = task_utrace_struct(task); ++ INIT_REPORT(report); ++ ++ REPORT(task, utrace, &report, UTRACE_EVENT(EXEC), ++ report_exec, fmt, bprm, regs); ++} ++ ++static u32 do_report_syscall_entry(struct pt_regs *regs, ++ struct task_struct *task, ++ struct utrace *utrace, ++ struct utrace_report *report, ++ u32 resume_report) ++{ ++ start_report(utrace); ++ REPORT_CALLBACKS(_reverse, task, utrace, report, ++ UTRACE_EVENT(SYSCALL_ENTRY), report_syscall_entry, ++ resume_report | report->result | report->action, ++ engine, regs); ++ finish_report(task, utrace, report, false); ++ ++ if (report->action != UTRACE_STOP) ++ return 0; ++ ++ utrace_stop(task, utrace, report->resume_action); ++ ++ if (fatal_signal_pending(task)) { ++ /* ++ * We are continuing despite UTRACE_STOP because of a ++ * SIGKILL. Don't let the system call actually proceed. ++ */ ++ report->result = UTRACE_SYSCALL_ABORT; ++ } else if (utrace->resume <= UTRACE_REPORT) { ++ /* ++ * If we've been asked for another report after our stop, ++ * go back to report (and maybe stop) again before we run ++ * the system call. The second (and later) reports are ++ * marked with the UTRACE_SYSCALL_RESUMED flag so that ++ * engines know this is a second report at the same ++ * entry. This gives them the chance to examine the ++ * registers anew after they might have been changed ++ * while we were stopped. ++ */ ++ report->detaches = false; ++ report->spurious = true; ++ report->action = report->resume_action = UTRACE_RESUME; ++ return UTRACE_SYSCALL_RESUMED; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Called iff UTRACE_EVENT(SYSCALL_ENTRY) flag is set. ++ * Return true to prevent the system call. ++ */ ++bool utrace_report_syscall_entry(struct pt_regs *regs) ++{ ++ struct task_struct *task = current; ++ struct utrace *utrace = task_utrace_struct(task); ++ INIT_REPORT(report); ++ u32 resume_report = 0; ++ ++ do { ++ resume_report = do_report_syscall_entry(regs, task, utrace, ++ &report, resume_report); ++ } while (resume_report); ++ ++ return utrace_syscall_action(report.result) == UTRACE_SYSCALL_ABORT; ++} ++ ++/* ++ * Called iff UTRACE_EVENT(SYSCALL_EXIT) flag is set. ++ */ ++void utrace_report_syscall_exit(struct pt_regs *regs) ++{ ++ struct task_struct *task = current; ++ struct utrace *utrace = task_utrace_struct(task); ++ INIT_REPORT(report); ++ ++ REPORT(task, utrace, &report, UTRACE_EVENT(SYSCALL_EXIT), ++ report_syscall_exit, regs); ++} ++ ++/* ++ * Called iff UTRACE_EVENT(CLONE) flag is set. ++ * This notification call blocks the wake_up_new_task call on the child. ++ * So we must not quiesce here. tracehook_report_clone_complete will do ++ * a quiescence check momentarily. ++ */ ++void utrace_report_clone(unsigned long clone_flags, struct task_struct *child) ++{ ++ struct task_struct *task = current; ++ struct utrace *utrace = task_utrace_struct(task); ++ INIT_REPORT(report); ++ ++ /* ++ * We don't use the REPORT() macro here, because we need ++ * to clear utrace->cloning before finish_report(). ++ * After finish_report(), utrace can be a stale pointer ++ * in cases when report.action is still UTRACE_RESUME. ++ */ ++ start_report(utrace); ++ utrace->cloning = child; ++ ++ REPORT_CALLBACKS(, task, utrace, &report, ++ UTRACE_EVENT(CLONE), report_clone, ++ report.action, engine, clone_flags, child); ++ ++ utrace->cloning = NULL; ++ finish_report(task, utrace, &report, !(clone_flags & CLONE_VFORK)); ++ ++ /* ++ * For a vfork, we will go into an uninterruptible block waiting ++ * for the child. We need UTRACE_STOP to happen before this, not ++ * after. For CLONE_VFORK, utrace_finish_vfork() will be called. ++ */ ++ if (report.action == UTRACE_STOP && (clone_flags & CLONE_VFORK)) { ++ spin_lock(&utrace->lock); ++ utrace->vfork_stop = 1; ++ spin_unlock(&utrace->lock); ++ } ++} ++ ++/* ++ * We're called after utrace_report_clone() for a CLONE_VFORK. ++ * If UTRACE_STOP was left from the clone report, we stop here. ++ * After this, we'll enter the uninterruptible wait_for_completion() ++ * waiting for the child. ++ */ ++void utrace_finish_vfork(struct task_struct *task) ++{ ++ struct utrace *utrace = task_utrace_struct(task); ++ ++ if (utrace->vfork_stop) { ++ spin_lock(&utrace->lock); ++ utrace->vfork_stop = 0; ++ spin_unlock(&utrace->lock); ++ utrace_stop(task, utrace, UTRACE_RESUME); /* XXX */ ++ } ++} ++ ++/* ++ * Called iff UTRACE_EVENT(JCTL) flag is set. ++ * ++ * Called with siglock held. ++ */ ++void utrace_report_jctl(int notify, int what) ++{ ++ struct task_struct *task = current; ++ struct utrace *utrace = task_utrace_struct(task); ++ INIT_REPORT(report); ++ ++ spin_unlock_irq(&task->sighand->siglock); ++ ++ REPORT(task, utrace, &report, UTRACE_EVENT(JCTL), ++ report_jctl, what, notify); ++ ++ spin_lock_irq(&task->sighand->siglock); ++} ++ ++/* ++ * Called iff UTRACE_EVENT(EXIT) flag is set. ++ */ ++void utrace_report_exit(long *exit_code) ++{ ++ struct task_struct *task = current; ++ struct utrace *utrace = task_utrace_struct(task); ++ INIT_REPORT(report); ++ long orig_code = *exit_code; ++ ++ REPORT(task, utrace, &report, UTRACE_EVENT(EXIT), ++ report_exit, orig_code, exit_code); ++ ++ if (report.action == UTRACE_STOP) ++ utrace_stop(task, utrace, report.resume_action); ++} ++ ++/* ++ * Called iff UTRACE_EVENT(DEATH) or UTRACE_EVENT(QUIESCE) flag is set. ++ * ++ * It is always possible that we are racing with utrace_release_task here. ++ * For this reason, utrace_release_task checks for the event bits that get ++ * us here, and delays its cleanup for us to do. ++ */ ++void utrace_report_death(struct task_struct *task, struct utrace *utrace, ++ bool group_dead, int signal) ++{ ++ INIT_REPORT(report); ++ ++ BUG_ON(!task->exit_state); ++ ++ /* ++ * We are presently considered "quiescent"--which is accurate ++ * inasmuch as we won't run any more user instructions ever again. ++ * But for utrace_control and utrace_set_events to be robust, they ++ * must be sure whether or not we will run any more callbacks. If ++ * a call comes in before we do, taking the lock here synchronizes ++ * us so we don't run any callbacks just disabled. Calls that come ++ * in while we're running the callbacks will see the exit.death ++ * flag and know that we are not yet fully quiescent for purposes ++ * of detach bookkeeping. ++ */ ++ spin_lock(&utrace->lock); ++ BUG_ON(utrace->death); ++ utrace->death = 1; ++ utrace->resume = UTRACE_RESUME; ++ splice_attaching(utrace); ++ spin_unlock(&utrace->lock); ++ ++ REPORT_CALLBACKS(, task, utrace, &report, UTRACE_EVENT(DEATH), ++ report_death, engine, group_dead, signal); ++ ++ utrace_maybe_reap(task, utrace, false); ++} ++ ++/* ++ * Finish the last reporting pass before returning to user mode. ++ */ ++static void finish_resume_report(struct task_struct *task, ++ struct utrace *utrace, ++ struct utrace_report *report) ++{ ++ finish_report_reset(task, utrace, report); ++ ++ switch (report->action) { ++ case UTRACE_STOP: ++ utrace_stop(task, utrace, report->resume_action); ++ break; ++ ++ case UTRACE_INTERRUPT: ++ if (!signal_pending(task)) ++ set_tsk_thread_flag(task, TIF_SIGPENDING); ++ break; ++ ++ case UTRACE_BLOCKSTEP: ++ if (likely(arch_has_block_step())) { ++ user_enable_block_step(task); ++ break; ++ } ++ ++ /* ++ * This means some callback is to blame for failing ++ * to check arch_has_block_step() itself. Warn and ++ * then fall through to treat it as SINGLESTEP. ++ */ ++ WARN(1, "UTRACE_BLOCKSTEP when !arch_has_block_step()"); ++ ++ case UTRACE_SINGLESTEP: ++ if (likely(arch_has_single_step())) { ++ user_enable_single_step(task); ++ } else { ++ /* ++ * This means some callback is to blame for failing ++ * to check arch_has_single_step() itself. Spew ++ * about it so the loser will fix his module. ++ */ ++ WARN(1, ++ "UTRACE_SINGLESTEP when !arch_has_single_step()"); ++ } ++ break; ++ ++ case UTRACE_REPORT: ++ case UTRACE_RESUME: ++ default: ++ user_disable_single_step(task); ++ break; ++ } ++} ++ ++/* ++ * This is called when TIF_NOTIFY_RESUME had been set (and is now clear). ++ * We are close to user mode, and this is the place to report or stop. ++ * When we return, we're going to user mode or into the signals code. ++ */ ++void utrace_resume(struct task_struct *task, struct pt_regs *regs) ++{ ++ struct utrace *utrace = task_utrace_struct(task); ++ INIT_REPORT(report); ++ struct utrace_engine *engine; ++ ++ /* ++ * Some machines get here with interrupts disabled. The same arch ++ * code path leads to calling into get_signal_to_deliver(), which ++ * implicitly reenables them by virtue of spin_unlock_irq. ++ */ ++ local_irq_enable(); ++ ++ /* ++ * If this flag is still set it's because there was a signal ++ * handler setup done but no report_signal following it. Clear ++ * the flag before we get to user so it doesn't confuse us later. ++ */ ++ if (unlikely(utrace->signal_handler)) { ++ spin_lock(&utrace->lock); ++ utrace->signal_handler = 0; ++ spin_unlock(&utrace->lock); ++ } ++ ++ /* ++ * Update our bookkeeping even if there are no callbacks made here. ++ */ ++ report.action = start_report(utrace); ++ ++ switch (report.action) { ++ case UTRACE_RESUME: ++ /* ++ * Anything we might have done was already handled by ++ * utrace_get_signal(), or this is an entirely spurious ++ * call. (The arch might use TIF_NOTIFY_RESUME for other ++ * purposes as well as calling us.) ++ */ ++ return; ++ case UTRACE_REPORT: ++ if (unlikely(!(task->utrace_flags & UTRACE_EVENT(QUIESCE)))) ++ break; ++ /* ++ * Do a simple reporting pass, with no specific ++ * callback after report_quiesce. ++ */ ++ report.action = UTRACE_RESUME; ++ list_for_each_entry(engine, &utrace->attached, entry) ++ start_callback(utrace, &report, engine, task, 0); ++ break; ++ default: ++ /* ++ * Even if this report was truly spurious, there is no need ++ * for utrace_reset() now. TIF_NOTIFY_RESUME was already ++ * cleared--it doesn't stay spuriously set. ++ */ ++ report.spurious = false; ++ break; ++ } ++ ++ /* ++ * Finish the report and either stop or get ready to resume. ++ * If utrace->resume was not UTRACE_REPORT, this applies its ++ * effect now (i.e. step or interrupt). ++ */ ++ finish_resume_report(task, utrace, &report); ++} ++ ++/* ++ * Return true if current has forced signal_pending(). ++ * ++ * This is called only when current->utrace_flags is nonzero, so we know ++ * that current->utrace must be set. It's not inlined in tracehook.h ++ * just so that struct utrace can stay opaque outside this file. ++ */ ++bool utrace_interrupt_pending(void) ++{ ++ return task_utrace_struct(current)->resume == UTRACE_INTERRUPT; ++} ++ ++/* ++ * Take the siglock and push @info back on our queue. ++ * Returns with @task->sighand->siglock held. ++ */ ++static void push_back_signal(struct task_struct *task, siginfo_t *info) ++ __acquires(task->sighand->siglock) ++{ ++ struct sigqueue *q; ++ ++ if (unlikely(!info->si_signo)) { /* Oh, a wise guy! */ ++ spin_lock_irq(&task->sighand->siglock); ++ return; ++ } ++ ++ q = sigqueue_alloc(); ++ if (likely(q)) { ++ q->flags = 0; ++ copy_siginfo(&q->info, info); ++ } ++ ++ spin_lock_irq(&task->sighand->siglock); ++ ++ sigaddset(&task->pending.signal, info->si_signo); ++ if (likely(q)) ++ list_add(&q->list, &task->pending.list); ++ ++ set_tsk_thread_flag(task, TIF_SIGPENDING); ++} ++ ++/* ++ * This is the hook from the signals code, called with the siglock held. ++ * Here is the ideal place to stop. We also dequeue and intercept signals. ++ */ ++int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, ++ siginfo_t *info, struct k_sigaction *return_ka) ++ __releases(task->sighand->siglock) ++ __acquires(task->sighand->siglock) ++{ ++ struct utrace *utrace; ++ struct k_sigaction *ka; ++ INIT_REPORT(report); ++ struct utrace_engine *engine; ++ const struct utrace_engine_ops *ops; ++ unsigned long event, want; ++ u32 ret; ++ int signr; ++ ++ utrace = task_utrace_struct(task); ++ if (utrace->resume < UTRACE_RESUME || ++ utrace->pending_attach || utrace->signal_handler) { ++ enum utrace_resume_action resume; ++ ++ /* ++ * We've been asked for an explicit report before we ++ * even check for pending signals. ++ */ ++ ++ spin_unlock_irq(&task->sighand->siglock); ++ ++ spin_lock(&utrace->lock); ++ ++ splice_attaching(utrace); ++ ++ report.result = utrace->signal_handler ? ++ UTRACE_SIGNAL_HANDLER : UTRACE_SIGNAL_REPORT; ++ utrace->signal_handler = 0; ++ ++ resume = utrace->resume; ++ utrace->resume = UTRACE_RESUME; ++ ++ spin_unlock(&utrace->lock); ++ ++ /* ++ * Make sure signal_pending() only returns true ++ * if there are real signals pending. ++ */ ++ if (signal_pending(task)) { ++ spin_lock_irq(&task->sighand->siglock); ++ recalc_sigpending(); ++ spin_unlock_irq(&task->sighand->siglock); ++ } ++ ++ if (resume > UTRACE_REPORT) { ++ /* ++ * We only got here to process utrace->resume. ++ * Despite no callbacks, this report is not spurious. ++ */ ++ report.action = resume; ++ report.spurious = false; ++ finish_resume_report(task, utrace, &report); ++ return -1; ++ } else if (!(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { ++ /* ++ * We only got here to clear utrace->signal_handler. ++ */ ++ return -1; ++ } ++ ++ /* ++ * Do a reporting pass for no signal, just for EVENT(QUIESCE). ++ * The engine callbacks can fill in *info and *return_ka. ++ * We'll pass NULL for the @orig_ka argument to indicate ++ * that there was no original signal. ++ */ ++ event = 0; ++ ka = NULL; ++ memset(return_ka, 0, sizeof *return_ka); ++ } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || ++ unlikely(task->signal->group_stop_count)) { ++ /* ++ * If no engine is interested in intercepting signals or ++ * we must stop, let the caller just dequeue them normally ++ * or participate in group-stop. ++ */ ++ return 0; ++ } else { ++ /* ++ * Steal the next signal so we can let tracing engines ++ * examine it. From the signal number and sigaction, ++ * determine what normal delivery would do. If no ++ * engine perturbs it, we'll do that by returning the ++ * signal number after setting *return_ka. ++ */ ++ signr = dequeue_signal(task, &task->blocked, info); ++ if (signr == 0) ++ return signr; ++ BUG_ON(signr != info->si_signo); ++ ++ ka = &task->sighand->action[signr - 1]; ++ *return_ka = *ka; ++ ++ /* ++ * We are never allowed to interfere with SIGKILL. ++ * Just punt after filling in *return_ka for our caller. ++ */ ++ if (signr == SIGKILL) ++ return signr; ++ ++ if (ka->sa.sa_handler == SIG_IGN) { ++ event = UTRACE_EVENT(SIGNAL_IGN); ++ report.result = UTRACE_SIGNAL_IGN; ++ } else if (ka->sa.sa_handler != SIG_DFL) { ++ event = UTRACE_EVENT(SIGNAL); ++ report.result = UTRACE_SIGNAL_DELIVER; ++ } else if (sig_kernel_coredump(signr)) { ++ event = UTRACE_EVENT(SIGNAL_CORE); ++ report.result = UTRACE_SIGNAL_CORE; ++ } else if (sig_kernel_ignore(signr)) { ++ event = UTRACE_EVENT(SIGNAL_IGN); ++ report.result = UTRACE_SIGNAL_IGN; ++ } else if (signr == SIGSTOP) { ++ event = UTRACE_EVENT(SIGNAL_STOP); ++ report.result = UTRACE_SIGNAL_STOP; ++ } else if (sig_kernel_stop(signr)) { ++ event = UTRACE_EVENT(SIGNAL_STOP); ++ report.result = UTRACE_SIGNAL_TSTP; ++ } else { ++ event = UTRACE_EVENT(SIGNAL_TERM); ++ report.result = UTRACE_SIGNAL_TERM; ++ } ++ ++ /* ++ * Now that we know what event type this signal is, we ++ * can short-circuit if no engines care about those. ++ */ ++ if ((task->utrace_flags & (event | UTRACE_EVENT(QUIESCE))) == 0) ++ return signr; ++ ++ /* ++ * We have some interested engines, so tell them about ++ * the signal and let them change its disposition. ++ */ ++ spin_unlock_irq(&task->sighand->siglock); ++ } ++ ++ /* ++ * This reporting pass chooses what signal disposition we'll act on. ++ */ ++ list_for_each_entry(engine, &utrace->attached, entry) { ++ /* ++ * See start_callback() comment about this barrier. ++ */ ++ utrace->reporting = engine; ++ smp_mb(); ++ ++ /* ++ * This pairs with the barrier in mark_engine_detached(), ++ * see start_callback() comments. ++ */ ++ want = engine->flags; ++ smp_rmb(); ++ ops = engine->ops; ++ ++ if ((want & (event | UTRACE_EVENT(QUIESCE))) == 0) { ++ utrace->reporting = NULL; ++ continue; ++ } ++ ++ if (ops->report_signal) ++ ret = (*ops->report_signal)( ++ report.result | report.action, engine, ++ regs, info, ka, return_ka); ++ else ++ ret = (report.result | (*ops->report_quiesce)( ++ report.action, engine, event)); ++ ++ /* ++ * Avoid a tight loop reporting again and again if some ++ * engine is too stupid. ++ */ ++ switch (utrace_resume_action(ret)) { ++ default: ++ break; ++ case UTRACE_INTERRUPT: ++ case UTRACE_REPORT: ++ ret = (ret & ~UTRACE_RESUME_MASK) | UTRACE_RESUME; ++ break; ++ } ++ ++ finish_callback(task, utrace, &report, engine, ret); ++ } ++ ++ /* ++ * We express the chosen action to the signals code in terms ++ * of a representative signal whose default action does it. ++ * Our caller uses our return value (signr) to decide what to ++ * do, but uses info->si_signo as the signal number to report. ++ */ ++ switch (utrace_signal_action(report.result)) { ++ case UTRACE_SIGNAL_TERM: ++ signr = SIGTERM; ++ break; ++ ++ case UTRACE_SIGNAL_CORE: ++ signr = SIGQUIT; ++ break; ++ ++ case UTRACE_SIGNAL_STOP: ++ signr = SIGSTOP; ++ break; ++ ++ case UTRACE_SIGNAL_TSTP: ++ signr = SIGTSTP; ++ break; ++ ++ case UTRACE_SIGNAL_DELIVER: ++ signr = info->si_signo; ++ ++ if (return_ka->sa.sa_handler == SIG_DFL) { ++ /* ++ * We'll do signr's normal default action. ++ * For ignore, we'll fall through below. ++ * For stop/death, break locks and returns it. ++ */ ++ if (likely(signr) && !sig_kernel_ignore(signr)) ++ break; ++ } else if (return_ka->sa.sa_handler != SIG_IGN && ++ likely(signr)) { ++ /* ++ * Complete the bookkeeping after the report. ++ * The handler will run. If an engine wanted to ++ * stop or step, then make sure we do another ++ * report after signal handler setup. ++ */ ++ if (report.action != UTRACE_RESUME) ++ report.action = UTRACE_INTERRUPT; ++ finish_report(task, utrace, &report, true); ++ ++ if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) ++ push_back_signal(task, info); ++ else ++ spin_lock_irq(&task->sighand->siglock); ++ ++ /* ++ * We do the SA_ONESHOT work here since the ++ * normal path will only touch *return_ka now. ++ */ ++ if (unlikely(return_ka->sa.sa_flags & SA_ONESHOT)) { ++ return_ka->sa.sa_flags &= ~SA_ONESHOT; ++ if (likely(valid_signal(signr))) { ++ ka = &task->sighand->action[signr - 1]; ++ ka->sa.sa_handler = SIG_DFL; ++ } ++ } ++ ++ return signr; ++ } ++ ++ /* Fall through for an ignored signal. */ ++ ++ case UTRACE_SIGNAL_IGN: ++ case UTRACE_SIGNAL_REPORT: ++ default: ++ /* ++ * If the signal is being ignored, then we are on the way ++ * directly back to user mode. We can stop here, or step, ++ * as in utrace_resume(), above. After we've dealt with that, ++ * our caller will relock and come back through here. ++ */ ++ finish_resume_report(task, utrace, &report); ++ ++ if (unlikely(fatal_signal_pending(task))) { ++ /* ++ * The only reason we woke up now was because of a ++ * SIGKILL. Don't do normal dequeuing in case it ++ * might get a signal other than SIGKILL. That would ++ * perturb the death state so it might differ from ++ * what the debugger would have allowed to happen. ++ * Instead, pluck out just the SIGKILL to be sure ++ * we'll die immediately with nothing else different ++ * from the quiescent state the debugger wanted us in. ++ */ ++ sigset_t sigkill_only; ++ siginitsetinv(&sigkill_only, sigmask(SIGKILL)); ++ spin_lock_irq(&task->sighand->siglock); ++ signr = dequeue_signal(task, &sigkill_only, info); ++ BUG_ON(signr != SIGKILL); ++ *return_ka = task->sighand->action[SIGKILL - 1]; ++ return signr; ++ } ++ ++ if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) { ++ push_back_signal(task, info); ++ spin_unlock_irq(&task->sighand->siglock); ++ } ++ ++ return -1; ++ } ++ ++ /* ++ * Complete the bookkeeping after the report. ++ * This sets utrace->resume if UTRACE_STOP was used. ++ */ ++ finish_report(task, utrace, &report, true); ++ ++ return_ka->sa.sa_handler = SIG_DFL; ++ ++ /* ++ * If this signal is fatal, si_signo gets through as exit_code. ++ * We can't allow a completely bogus value there or else core ++ * kernel code can freak out. (If an engine wants to control ++ * the exit_code value exactly, it can do so in report_exit.) ++ * We'll produce a big complaint in dmesg, but won't crash. ++ * That's nicer for debugging your utrace engine. ++ */ ++ if (unlikely(info->si_signo & 0x80)) { ++ WARN(1, "utrace engine left bogus si_signo value!"); ++ info->si_signo = SIGTRAP; ++ } ++ ++ if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) ++ push_back_signal(task, info); ++ else ++ spin_lock_irq(&task->sighand->siglock); ++ ++ if (sig_kernel_stop(signr)) ++ task->group_stop |= GROUP_STOP_DEQUEUED; ++ ++ return signr; ++} ++ ++/* ++ * This gets called after a signal handler has been set up. ++ * We set a flag so the next report knows it happened. ++ * If we're already stepping, make sure we do a report_signal. ++ * If not, make sure we get into utrace_resume() where we can ++ * clear the signal_handler flag before resuming. ++ */ ++void utrace_signal_handler(struct task_struct *task, int stepping) ++{ ++ struct utrace *utrace = task_utrace_struct(task); ++ ++ spin_lock(&utrace->lock); ++ ++ utrace->signal_handler = 1; ++ if (utrace->resume > UTRACE_INTERRUPT) { ++ if (stepping) { ++ utrace->resume = UTRACE_INTERRUPT; ++ set_tsk_thread_flag(task, TIF_SIGPENDING); ++ } else if (utrace->resume == UTRACE_RESUME) { ++ set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); ++ } ++ } ++ ++ spin_unlock(&utrace->lock); ++} ++ ++/** ++ * utrace_prepare_examine - prepare to examine thread state ++ * @target: thread of interest, a &struct task_struct pointer ++ * @engine: engine pointer returned by utrace_attach_task() ++ * @exam: temporary state, a &struct utrace_examiner pointer ++ * ++ * This call prepares to safely examine the thread @target using ++ * &struct user_regset calls, or direct access to thread-synchronous fields. ++ * ++ * When @target is current, this call is superfluous. When @target is ++ * another thread, it must be held stopped via %UTRACE_STOP by @engine. ++ * ++ * This call may block the caller until @target stays stopped, so it must ++ * be called only after the caller is sure @target is about to unschedule. ++ * This means a zero return from a utrace_control() call on @engine giving ++ * %UTRACE_STOP, or a report_quiesce() or report_signal() callback to ++ * @engine that used %UTRACE_STOP in its return value. ++ * ++ * Returns -%ESRCH if @target is dead or -%EINVAL if %UTRACE_STOP was ++ * not used. If @target has started running again despite %UTRACE_STOP ++ * (for %SIGKILL or a spurious wakeup), this call returns -%EAGAIN. ++ * ++ * When this call returns zero, it's safe to use &struct user_regset ++ * calls and task_user_regset_view() on @target and to examine some of ++ * its fields directly. When the examination is complete, a ++ * utrace_finish_examine() call must follow to check whether it was ++ * completed safely. ++ */ ++int utrace_prepare_examine(struct task_struct *target, ++ struct utrace_engine *engine, ++ struct utrace_examiner *exam) ++{ ++ int ret = 0; ++ ++ if (unlikely(target == current)) ++ return 0; ++ ++ rcu_read_lock(); ++ if (unlikely(!engine_wants_stop(engine))) ++ ret = -EINVAL; ++ else if (unlikely(target->exit_state)) ++ ret = -ESRCH; ++ else { ++ exam->state = target->state; ++ if (unlikely(exam->state == TASK_RUNNING)) ++ ret = -EAGAIN; ++ else ++ get_task_struct(target); ++ } ++ rcu_read_unlock(); ++ ++ if (likely(!ret)) { ++ exam->ncsw = wait_task_inactive(target, exam->state); ++ put_task_struct(target); ++ if (unlikely(!exam->ncsw)) ++ ret = -EAGAIN; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(utrace_prepare_examine); ++ ++/** ++ * utrace_finish_examine - complete an examination of thread state ++ * @target: thread of interest, a &struct task_struct pointer ++ * @engine: engine pointer returned by utrace_attach_task() ++ * @exam: pointer passed to utrace_prepare_examine() call ++ * ++ * This call completes an examination on the thread @target begun by a ++ * paired utrace_prepare_examine() call with the same arguments that ++ * returned success (zero). ++ * ++ * When @target is current, this call is superfluous. When @target is ++ * another thread, this returns zero if @target has remained unscheduled ++ * since the paired utrace_prepare_examine() call returned zero. ++ * ++ * When this returns an error, any examination done since the paired ++ * utrace_prepare_examine() call is unreliable and the data extracted ++ * should be discarded. The error is -%EINVAL if @engine is not ++ * keeping @target stopped, or -%EAGAIN if @target woke up unexpectedly. ++ */ ++int utrace_finish_examine(struct task_struct *target, ++ struct utrace_engine *engine, ++ struct utrace_examiner *exam) ++{ ++ int ret = 0; ++ ++ if (unlikely(target == current)) ++ return 0; ++ ++ rcu_read_lock(); ++ if (unlikely(!engine_wants_stop(engine))) ++ ret = -EINVAL; ++ else if (unlikely(target->state != exam->state)) ++ ret = -EAGAIN; ++ else ++ get_task_struct(target); ++ rcu_read_unlock(); ++ ++ if (likely(!ret)) { ++ unsigned long ncsw = wait_task_inactive(target, exam->state); ++ if (unlikely(ncsw != exam->ncsw)) ++ ret = -EAGAIN; ++ put_task_struct(target); ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(utrace_finish_examine); ++ ++/* ++ * This is declared in linux/regset.h and defined in machine-dependent ++ * code. We put the export here to ensure no machine forgets it. ++ */ ++EXPORT_SYMBOL_GPL(task_user_regset_view); ++ ++/* ++ * Called with rcu_read_lock() held. ++ */ ++void task_utrace_proc_status(struct seq_file *m, struct task_struct *p) ++{ ++ seq_printf(m, "Utrace:\t%lx\n", p->utrace_flags); ++} +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:04 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:04 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:03 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2259ED812A; + Thu, 30 Jun 2011 20:23:03 -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 Ex9fFDzwy1Zb; Thu, 30 Jun 2011 20:23:03 -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 0EF28D810F; + Thu, 30 Jun 2011 20:23:03 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610Mt6X021086; + Thu, 30 Jun 2011 20:22:56 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:03 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:01 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 02/19] utrace: remove jobctl bits +Message-ID: <20110701002101.GA25779@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +Status: RO +Content-Length: 1890 +Lines: 56 + +- change utrace_get_signal() to check GROUP_STOP_PENDING instead of + signal->group_stop_count. With the recent changes group_stop_count + doesn't necessarily mean this task should participate in group stop. + +- remove the "participate in group stop" code from utrace_wakeup() and + utrace_stop(), this is no longer needed and wrong. + +Signed-off-by: Oleg Nesterov +--- + kernel/utrace.c | 16 ++-------------- + 1 files changed, 2 insertions(+), 14 deletions(-) + +diff --git a/kernel/utrace.c b/kernel/utrace.c +index f332d65..6e7fafb 100644 +--- a/kernel/utrace.c ++++ b/kernel/utrace.c +@@ -648,11 +648,7 @@ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) + { + lockdep_assert_held(&utrace->lock); + spin_lock_irq(&target->sighand->siglock); +- if (target->signal->flags & SIGNAL_STOP_STOPPED || +- target->signal->group_stop_count) +- target->state = TASK_STOPPED; +- else +- wake_up_state(target, __TASK_TRACED); ++ wake_up_state(target, __TASK_TRACED); + spin_unlock_irq(&target->sighand->siglock); + } + +@@ -805,14 +801,6 @@ relock: + + __set_current_state(TASK_TRACED); + +- /* +- * If there is a group stop in progress, +- * we must participate in the bookkeeping. +- */ +- if (unlikely(task->signal->group_stop_count) && +- !--task->signal->group_stop_count) +- task->signal->flags = SIGNAL_STOP_STOPPED; +- + spin_unlock_irq(&task->sighand->siglock); + spin_unlock(&utrace->lock); + +@@ -2036,7 +2024,7 @@ int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, + ka = NULL; + memset(return_ka, 0, sizeof *return_ka); + } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || +- unlikely(task->signal->group_stop_count)) { ++ unlikely(task->group_stop & GROUP_STOP_PENDING)) { + /* + * If no engine is interested in intercepting signals or + * we must stop, let the caller just dequeue them normally +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:05 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:05 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:06 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6B38AD812A; + Thu, 30 Jun 2011 20:23:06 -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 f4153Z6E7KGl; Thu, 30 Jun 2011 20:23:06 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 55D4AD810F; + Thu, 30 Jun 2011 20:23:06 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610Mwi2015168; + Thu, 30 Jun 2011 20:22:59 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:06 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:04 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 03/19] ptrace: take ->siglock around s/TRACED/RUNNING/ +Message-ID: <20110701002104.GA25787@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Status: RO +Content-Length: 1624 +Lines: 56 + +change ptrace_resume() and ptrace_stop() to take ->siglock around changing +task->state from TRACED to RUNNING. + +With this patch __TASK_TRACED/STOPPED bits are fully protected by ->siglock, +nobody can set or clear these bits without ->siglock held. + +Signed-off-by: Oleg Nesterov +--- + kernel/ptrace.c | 8 +++++++- + kernel/signal.c | 3 +++ + 2 files changed, 10 insertions(+), 1 deletions(-) + +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index 2df1157..9988b13 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -534,6 +534,8 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info) + static int ptrace_resume(struct task_struct *child, long request, + unsigned long data) + { ++ unsigned long flags; ++ + if (!valid_signal(data)) + return -EIO; + +@@ -562,7 +564,11 @@ static int ptrace_resume(struct task_struct *child, long request, + } + + child->exit_code = data; +- wake_up_state(child, __TASK_TRACED); ++ ++ if (lock_task_sighand(child, &flags)) { ++ wake_up_state(child, __TASK_TRACED); ++ unlock_task_sighand(child, &flags); ++ } + + return 0; + } +diff --git a/kernel/signal.c b/kernel/signal.c +index ff76786..2138cee 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -1799,7 +1799,10 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) + if (gstop_done) + do_notify_parent_cldstop(current, false, why); + ++ spin_lock_irq(¤t->sighand->siglock); + __set_current_state(TASK_RUNNING); ++ spin_unlock_irq(¤t->sighand->siglock); ++ + if (clear_code) + current->exit_code = 0; + read_unlock(&tasklist_lock); +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:06 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:06 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:09 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E1AB7D812A; + Thu, 30 Jun 2011 20:23:09 -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 QhOnA49nS3Vp; Thu, 30 Jun 2011 20:23:09 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C5E15D810F; + Thu, 30 Jun 2011 20:23:09 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610N2Kd007635; + Thu, 30 Jun 2011 20:23:02 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:10 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:07 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 04/19] introduce wake_up_quiescent() +Message-ID: <20110701002107.GA25790@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +Status: RO +Content-Length: 3104 +Lines: 93 + +No functional changes. Add the new helper, wake_up_quiescent(task, state), +which simply returns wake_up_state(task, state). Change all callers which +do wake_up_state(STOPPED/TRACED) to use the new helper. ptrace_stop() is +a bit special, it does __set_current_state(RUNNING) in the very unlikely +case, change it as well. + +Signed-off-by: Oleg Nesterov +--- + include/linux/signal.h | 2 ++ + kernel/ptrace.c | 2 +- + kernel/signal.c | 12 ++++++++++-- + kernel/utrace.c | 2 +- + 4 files changed, 14 insertions(+), 4 deletions(-) + +diff --git a/include/linux/signal.h b/include/linux/signal.h +index a822300..2be3712 100644 +--- a/include/linux/signal.h ++++ b/include/linux/signal.h +@@ -239,6 +239,8 @@ static inline int valid_signal(unsigned long sig) + struct timespec; + struct pt_regs; + ++extern int wake_up_quiescent(struct task_struct *p, unsigned int state); ++ + extern int next_signal(struct sigpending *pending, sigset_t *mask); + extern int do_send_sig_info(int sig, struct siginfo *info, + struct task_struct *p, bool group); +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index 9988b13..26ae214 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -566,7 +566,7 @@ static int ptrace_resume(struct task_struct *child, long request, + child->exit_code = data; + + if (lock_task_sighand(child, &flags)) { +- wake_up_state(child, __TASK_TRACED); ++ wake_up_quiescent(child, __TASK_TRACED); + unlock_task_sighand(child, &flags); + } + +diff --git a/kernel/signal.c b/kernel/signal.c +index 2138cee..4fcf1c7 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -652,6 +652,14 @@ void signal_wake_up(struct task_struct *t, int resume) + } + + /* ++ * wakes up the STOPPED/TRACED task, must be called with ->siglock held. ++ */ ++int wake_up_quiescent(struct task_struct *p, unsigned int state) ++{ ++ return wake_up_state(p, state); ++} ++ ++/* + * Remove signals in mask from the pending set and queue. + * Returns 1 if any signals were found. + * +@@ -811,7 +819,7 @@ static int prepare_signal(int sig, struct task_struct *p, int from_ancestor_ns) + do { + task_clear_group_stop_pending(t); + rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending); +- wake_up_state(t, __TASK_STOPPED); ++ wake_up_quiescent(t, __TASK_STOPPED); + } while_each_thread(p, t); + + /* +@@ -1800,7 +1808,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) + do_notify_parent_cldstop(current, false, why); + + spin_lock_irq(¤t->sighand->siglock); +- __set_current_state(TASK_RUNNING); ++ wake_up_quiescent(current, __TASK_TRACED); + spin_unlock_irq(¤t->sighand->siglock); + + if (clear_code) +diff --git a/kernel/utrace.c b/kernel/utrace.c +index 6e7fafb..d7c547c 100644 +--- a/kernel/utrace.c ++++ b/kernel/utrace.c +@@ -648,7 +648,7 @@ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) + { + lockdep_assert_held(&utrace->lock); + spin_lock_irq(&target->sighand->siglock); +- wake_up_state(target, __TASK_TRACED); ++ wake_up_quiescent(target, __TASK_TRACED); + spin_unlock_irq(&target->sighand->siglock); + } + +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:07 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:07 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:13 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2CF811287F3; + Thu, 30 Jun 2011 20:23:13 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id dNPA3WxO-7pp; Thu, 30 Jun 2011 20:23:13 -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 zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 154D61287DD; + Thu, 30 Jun 2011 20:23:13 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610N5nY021107; + Thu, 30 Jun 2011 20:23:06 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:13 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:11 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 05/19] introduce ptrace_signal_wake_up() +Message-ID: <20110701002111.GA25797@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +Status: RO +Content-Length: 1975 +Lines: 68 + +Add the new helper, ptrace_signal_wake_up(), change ptrace.c to use +it instead of signal_wake_up(). + +The new helper does almost the same, except: + + - it doesn't use the TASK_WAKEKILL bit to wake up the TRACED + or STOPPED task, it uses __TASK_STOPPED | __TASK_TRACED + explicitly. This is what ptrace actually wants, it should + never wake up a TASK_KILLABLE task. + + This should be cleanuped upatream, signal_wake_up() should + take the state as an argument, not a boolean. Until then + we add a new static helper. + + - it uses wake_up_quiescent() instead of wake_up_state(). + +Thereafter every change from STOPPED/TRACED to RUNNING is done via +wake_up_quiescent(). + +Signed-off-by: Oleg Nesterov +--- + kernel/ptrace.c | 16 ++++++++++++++-- + 1 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index 26ae214..0b2aba5 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -24,6 +24,18 @@ + #include + #include + ++static void ptrace_signal_wake_up(struct task_struct *p, int quiescent) ++{ ++ unsigned int state; ++ ++ set_tsk_thread_flag(p, TIF_SIGPENDING); ++ ++ state = TASK_INTERRUPTIBLE; ++ if (quiescent) ++ state |= (__TASK_STOPPED | __TASK_TRACED); ++ if (!wake_up_quiescent(p, state)) ++ kick_process(p); ++} + + /* + * ptrace a task: make the debugger its new parent and +@@ -92,7 +104,7 @@ void __ptrace_unlink(struct task_struct *child) + * TASK_KILLABLE sleeps. + */ + if (child->group_stop & GROUP_STOP_PENDING || task_is_traced(child)) +- signal_wake_up(child, task_is_traced(child)); ++ ptrace_signal_wake_up(child, task_is_traced(child)); + + spin_unlock(&child->sighand->siglock); + } +@@ -245,7 +257,7 @@ static int ptrace_attach(struct task_struct *task) + */ + if (task_is_stopped(task)) { + task->group_stop |= GROUP_STOP_PENDING | GROUP_STOP_TRAPPING; +- signal_wake_up(task, 1); ++ ptrace_signal_wake_up(task, 1); + wait_trap = true; + } + +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:08 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:08 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:16 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6FB379C0CB; + Thu, 30 Jun 2011 20:23:16 -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 IYB64KKErOyI; Thu, 30 Jun 2011 20:23:16 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 597119C0C5; + Thu, 30 Jun 2011 20:23:16 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610N8bE032569; + Thu, 30 Jun 2011 20:23:09 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:16 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:14 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 06/19] wait_task_inactive: treat task->state and + match_state as bitmasks +Message-ID: <20110701002114.GA25804@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Status: RO +Content-Length: 1558 +Lines: 39 + +Change wait_task_inactive() to check "state & match_state" instead of +"state == match_state". This should not make any difference, but this +allows us to add more "stopped" bits which can be set or cleared +independently. + +IOW. wait_task_inactive() assumes that if task->state != 0, it can +only be changed to TASK_RUNNING. Currently this is true, and in this +case "state & match_state" continues to work. But, unlike the current +check, it also works if task->state has other bits set while the caller +is only interested in, say, __TASK_TRACED. + +Note: I think wait_task_inactive() should be cleanuped upstrean anyway, +nowadays we have TASK_WAKING and task->state != 0 doesn't necessarily +mean it is TASK_RUNNING. It also makes sense to exclude the !TASK_REPORT +bits during the check. Finally, probably this patch makes sense anyway +even without utrace. For example, a stopped _and_ traced thread could +have task->state = TASK_STOPPED | TASK_TRACED, this can be useful. + +Signed-off-by: Oleg Nesterov +--- + kernel/sched.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/kernel/sched.c b/kernel/sched.c +index 3f2e502..ade7997 100644 +--- a/kernel/sched.c ++++ b/kernel/sched.c +@@ -2277,7 +2277,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) + * is actually now running somewhere else! + */ + while (task_running(rq, p)) { +- if (match_state && unlikely(p->state != match_state)) ++ if (match_state && !likely(p->state & match_state)) + return 0; + cpu_relax(); + } +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:09 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:09 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:19 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A6BD4D810F; + Thu, 30 Jun 2011 20:23:19 -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 2ovLSk6W1SGg; Thu, 30 Jun 2011 20:23:19 -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 zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8DBABD812A; + Thu, 30 Jun 2011 20:23:19 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610NCUq026299; + Thu, 30 Jun 2011 20:23:12 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:19 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:17 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 07/19] introduce TASK_UTRACED state +Message-ID: <20110701002117.GA25807@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +Status: RO +Content-Length: 2913 +Lines: 84 + +Introduce TASK_UTRACED state, will be used by utrace instead of TASK_TRACED. + +Note: this state is reported as "t (tracing stop)" to the user-space to +avoid the confusion. IOW, it looks like TASK_TRACED in /proc/pid/status. + +Signed-off-by: Oleg Nesterov +--- + fs/proc/array.c | 11 ++++++----- + include/linux/sched.h | 20 +++++++++++--------- + 2 files changed, 17 insertions(+), 14 deletions(-) + +diff --git a/fs/proc/array.c b/fs/proc/array.c +index 496fef3..bfaa998 100644 +--- a/fs/proc/array.c ++++ b/fs/proc/array.c +@@ -138,11 +138,12 @@ static const char * const task_state_array[] = { + "D (disk sleep)", /* 2 */ + "T (stopped)", /* 4 */ + "t (tracing stop)", /* 8 */ +- "Z (zombie)", /* 16 */ +- "X (dead)", /* 32 */ +- "x (dead)", /* 64 */ +- "K (wakekill)", /* 128 */ +- "W (waking)", /* 256 */ ++ "t (tracing stop)", /* 16 (stopped by utrace) */ ++ "Z (zombie)", /* 32 */ ++ "X (dead)", /* 64 */ ++ "x (dead)", /* 128 */ ++ "K (wakekill)", /* 256 */ ++ "W (waking)", /* 512 */ + }; + + static inline const char *get_task_state(struct task_struct *tsk) +diff --git a/include/linux/sched.h b/include/linux/sched.h +index b87de83..7a0008c 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -184,16 +184,17 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) + #define TASK_UNINTERRUPTIBLE 2 + #define __TASK_STOPPED 4 + #define __TASK_TRACED 8 ++#define __TASK_UTRACED 16 + /* in tsk->exit_state */ +-#define EXIT_ZOMBIE 16 +-#define EXIT_DEAD 32 ++#define EXIT_ZOMBIE 32 ++#define EXIT_DEAD 64 + /* in tsk->state again */ +-#define TASK_DEAD 64 +-#define TASK_WAKEKILL 128 +-#define TASK_WAKING 256 +-#define TASK_STATE_MAX 512 ++#define TASK_DEAD 128 ++#define TASK_WAKEKILL 256 ++#define TASK_WAKING 512 ++#define TASK_STATE_MAX 1024 + +-#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKW" ++#define TASK_STATE_TO_CHAR_STR "RSDTtUZXxKW" + + extern char ___assert_task_state[1 - 2*!!( + sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1)]; +@@ -202,15 +203,16 @@ extern char ___assert_task_state[1 - 2*!!( + #define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE) + #define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED) + #define TASK_TRACED (TASK_WAKEKILL | __TASK_TRACED) ++#define TASK_UTRACED (TASK_WAKEKILL | __TASK_UTRACED) + + /* Convenience macros for the sake of wake_up */ + #define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE) +-#define TASK_ALL (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED) ++#define TASK_ALL (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED | __TASK_UTRACED) + + /* get_task_state() */ + #define TASK_REPORT (TASK_RUNNING | TASK_INTERRUPTIBLE | \ + TASK_UNINTERRUPTIBLE | __TASK_STOPPED | \ +- __TASK_TRACED) ++ __TASK_TRACED | __TASK_UTRACED) + + #define task_is_traced(task) ((task->state & __TASK_TRACED) != 0) + #define task_is_stopped(task) ((task->state & __TASK_STOPPED) != 0) +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:10 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:10 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:23 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1A66AD812A; + Thu, 30 Jun 2011 20:23:23 -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 fctUcQ+-lYpk; Thu, 30 Jun 2011 20:23:23 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F2D35D810F; + Thu, 30 Jun 2011 20:23:22 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NF1u015200; + Thu, 30 Jun 2011 20:23:15 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:23 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:20 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 08/19] utrace: use TASK_UTRACED instead of TASK_TRACED +Message-ID: <20110701002120.GA25814@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Status: RO +Content-Length: 4316 +Lines: 130 + +Change utrace.c to use TASK_UTRACED instead of TASK_TRACED. + +- utrace_stop/utrace_wakeup: simply use the new state + +- utrace_do_stop: do not clear STOPPED/TRACED, but add the new + __TASK_UTRACED bit to state the fact that both ptrace and utrace + want this task to be stopped + +- naturally, do not use task_is_traced() to check if this task was + stopped by utrace, use the new task_is_utraced() helper which + checks __TASK_UTRACED. + +Signed-off-by: Oleg Nesterov +--- + kernel/utrace.c | 26 ++++++++++++++------------ + 1 files changed, 14 insertions(+), 12 deletions(-) + +diff --git a/kernel/utrace.c b/kernel/utrace.c +index d7c547c..be98607 100644 +--- a/kernel/utrace.c ++++ b/kernel/utrace.c +@@ -462,6 +462,8 @@ static void put_detached_list(struct list_head *list) + */ + #define ENGINE_STOP (1UL << _UTRACE_NEVENTS) + ++#define task_is_utraced(task) ((task->state & __TASK_UTRACED) != 0) ++ + static void mark_engine_wants_stop(struct task_struct *task, + struct utrace_engine *engine) + { +@@ -576,7 +578,7 @@ int utrace_set_events(struct task_struct *target, + + ret = 0; + if ((old_flags & ~events) && target != current && +- !task_is_stopped_or_traced(target) && !target->exit_state) { ++ !task_is_utraced(target) && !target->exit_state) { + /* + * This barrier ensures that our engine->flags changes + * have hit before we examine utrace->reporting, +@@ -623,21 +625,21 @@ static void mark_engine_detached(struct utrace_engine *engine) + */ + static bool utrace_do_stop(struct task_struct *target, struct utrace *utrace) + { +- if (task_is_stopped(target)) { ++ if (task_is_stopped_or_traced(target)) { + /* + * Stopped is considered quiescent; when it wakes up, it will + * go through utrace_finish_stop() before doing anything else. + */ + spin_lock_irq(&target->sighand->siglock); +- if (likely(task_is_stopped(target))) +- __set_task_state(target, TASK_TRACED); ++ if (likely(task_is_stopped_or_traced(target))) ++ target->state |= TASK_UTRACED; + spin_unlock_irq(&target->sighand->siglock); + } else if (utrace->resume > UTRACE_REPORT) { + utrace->resume = UTRACE_REPORT; + set_notify_resume(target); + } + +- return task_is_traced(target); ++ return task_is_utraced(target); + } + + /* +@@ -648,7 +650,7 @@ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) + { + lockdep_assert_held(&utrace->lock); + spin_lock_irq(&target->sighand->siglock); +- wake_up_quiescent(target, __TASK_TRACED); ++ wake_up_quiescent(target, __TASK_UTRACED); + spin_unlock_irq(&target->sighand->siglock); + } + +@@ -710,7 +712,7 @@ static bool utrace_reset(struct task_struct *task, struct utrace *utrace) + /* + * If no more engines want it stopped, wake it up. + */ +- if (task_is_traced(task) && !(flags & ENGINE_STOP)) { ++ if (task_is_utraced(task) && !(flags & ENGINE_STOP)) { + /* + * It just resumes, so make sure single-step + * is not left set. +@@ -749,7 +751,7 @@ void utrace_finish_stop(void) + } + + /* +- * Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up. ++ * Perform %UTRACE_STOP, i.e. block in TASK_UTRACED until woken up. + * @task == current, @utrace == current->utrace, which is not locked. + * Return true if we were woken up by SIGKILL even though some utrace + * engine may still want us to stay stopped. +@@ -799,7 +801,7 @@ relock: + return; + } + +- __set_current_state(TASK_TRACED); ++ __set_current_state(TASK_UTRACED); + + spin_unlock_irq(&task->sighand->siglock); + spin_unlock(&utrace->lock); +@@ -809,14 +811,14 @@ relock: + utrace_finish_stop(); + + /* +- * While in TASK_TRACED, we were considered "frozen enough". ++ * While in TASK_UTRACED, we were considered "frozen enough". + * Now that we woke up, it's crucial if we're supposed to be + * frozen that we freeze now before running anything substantial. + */ + try_to_freeze(); + + /* +- * While we were in TASK_TRACED, complete_signal() considered ++ * While we were in TASK_UTRACED, complete_signal() considered + * us "uninterested" in signal wakeups. Now make sure our + * TIF_SIGPENDING state is correct for normal running. + */ +@@ -1087,7 +1089,7 @@ int utrace_control(struct task_struct *target, + if (unlikely(IS_ERR(utrace))) + return PTR_ERR(utrace); + +- reset = task_is_traced(target); ++ reset = task_is_utraced(target); + ret = 0; + + /* +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:12 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:12 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:26 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 289969C0C5; + Thu, 30 Jun 2011 20:23:26 -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 q99JSaVz2X1O; Thu, 30 Jun 2011 20:23:26 -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 zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 143F89C0C3; + Thu, 30 Jun 2011 20:23:26 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610NI9T021133; + Thu, 30 Jun 2011 20:23:19 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:26 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:24 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 09/19] tracehooks: kill tracehook_finish_jctl(), add + tracehook_finish_stop() +Message-ID: <20110701002124.GA25817@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +Status: RO +Content-Length: 2782 +Lines: 86 + +tracehook_finish_jctl() is needed to avoid the races with SIGKILL +which wakes up UTRACED task, and thus it should be called every time +after the STOPPED/TRACED/UTRACED returns from schedule(), remember +that TASK_UTRACED can be added while the task is STOPPED/UTRACED. + +- rename it to tracehook_finish_stop(),jctl no longer matches the + reality. + +- change do_signal_state() to call this helper right after schedule(), + otherwise this logic is broken by the upstream changes + +- now that utrace doesn't control TASK_TRACED bit, ptrace_stop() must + call this helper too. + +Signed-off-by: Oleg Nesterov +--- + include/linux/tracehook.h | 6 +++--- + kernel/signal.c | 5 +++-- + kernel/utrace.c | 2 +- + 3 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index 7d7bdde..3c7b6b3 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -528,11 +528,11 @@ static inline int tracehook_get_signal(struct task_struct *task, + } + + /** +- * tracehook_finish_jctl - report about return from job control stop ++ * tracehook_finish_stop - report about return from STOPPED/TRACED + * +- * This is called by do_signal_stop() after wakeup. ++ * This is called by do_signal_stop() and ptrace_stop after wakeup. + */ +-static inline void tracehook_finish_jctl(void) ++static inline void tracehook_finish_stop(void) + { + if (task_utrace_flags(current)) + utrace_finish_stop(); +diff --git a/kernel/signal.c b/kernel/signal.c +index 4fcf1c7..a7979ad 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -1816,6 +1816,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) + read_unlock(&tasklist_lock); + } + ++ tracehook_finish_stop(); + /* + * While in TASK_TRACED, we were considered "frozen enough". + * Now that we woke up, it's crucial if we're supposed to be +@@ -1952,6 +1953,8 @@ retry: + /* Now we don't run again until woken by SIGCONT or SIGKILL */ + schedule(); + ++ tracehook_finish_stop(); ++ + spin_lock_irq(¤t->sighand->siglock); + } else { + ptrace_stop(current->group_stop & GROUP_STOP_SIGMASK, +@@ -1974,8 +1977,6 @@ retry: + + spin_unlock_irq(¤t->sighand->siglock); + +- tracehook_finish_jctl(); +- + return 1; + } + +diff --git a/kernel/utrace.c b/kernel/utrace.c +index be98607..daa96b9 100644 +--- a/kernel/utrace.c ++++ b/kernel/utrace.c +@@ -741,7 +741,7 @@ static bool utrace_reset(struct task_struct *task, struct utrace *utrace) + void utrace_finish_stop(void) + { + /* +- * If we were task_is_traced() and then SIGKILL'ed, make ++ * If we were task_is_utraced() and then SIGKILL'ed, make + * sure we do nothing until the tracer drops utrace->lock. + */ + if (unlikely(__fatal_signal_pending(current))) { +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:13 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:13 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:29 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A748FD813B; + Thu, 30 Jun 2011 20:23:29 -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 EwbxGxAU7ASi; Thu, 30 Jun 2011 20:23:29 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 72761D810F; + Thu, 30 Jun 2011 20:23:29 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NMAW015213; + Thu, 30 Jun 2011 20:23:22 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:29 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:27 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 10/19] teach wake_up_quiescent() to do "selective" wake_up +Message-ID: <20110701002127.GA25824@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Status: RO +Content-Length: 1335 +Lines: 46 + +Both utrace and ptrace can want the same thread to be quiescent, in this +case its state is TASK_TRACED | TASK_UTRACED. And this also means that +this task must not run unless both utrace and ptrace resume it. + +Change wake_up_quiescent(p, state) to do "p->state &= ~state" and return +false unless there is no more "quiescent" bits in task->state. + +Signed-off-by: Oleg Nesterov +--- + kernel/signal.c | 15 +++++++++++++++ + 1 files changed, 15 insertions(+), 0 deletions(-) + +diff --git a/kernel/signal.c b/kernel/signal.c +index a7979ad..57552e6 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -651,11 +651,26 @@ void signal_wake_up(struct task_struct *t, int resume) + kick_process(t); + } + ++#define STATE_QUIESCENT (__TASK_STOPPED | __TASK_TRACED | __TASK_UTRACED) + /* + * wakes up the STOPPED/TRACED task, must be called with ->siglock held. + */ + int wake_up_quiescent(struct task_struct *p, unsigned int state) + { ++ unsigned int quiescent = (p->state & STATE_QUIESCENT); ++ ++ WARN_ON(state & ~(STATE_QUIESCENT | TASK_INTERRUPTIBLE)); ++ ++ if (quiescent) { ++ state &= ~TASK_INTERRUPTIBLE; ++ if ((quiescent & ~state) != 0) { ++ p->state &= ~state; ++ WARN_ON(!(p->state & STATE_QUIESCENT)); ++ WARN_ON(!(p->state & TASK_WAKEKILL)); ++ return 0; ++ } ++ } ++ + return wake_up_state(p, state); + } + +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:14 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:14 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:32 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C94CF9C0C5; + Thu, 30 Jun 2011 20:23:32 -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 9R-z4gQXQITf; Thu, 30 Jun 2011 20:23:32 -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 zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B55759C0C3; + Thu, 30 Jun 2011 20:23:32 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610NPe5021144; + Thu, 30 Jun 2011 20:23:25 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:33 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:30 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 11/19] ptrace_stop: do not assume the task is running after + wake_up_quiescent() +Message-ID: <20110701002130.GA25827@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +Status: RO +Content-Length: 962 +Lines: 31 + +If ptrace_stop() sets TASK_TRACED and then detects we should not stop, +it can race with utrace_do_stop() which can see TASK_TRACED and add +TASK_UTRACED. In this case we should stop for utrace needs. + +Signed-off-by: Oleg Nesterov +--- + kernel/signal.c | 8 ++++++++ + 1 files changed, 8 insertions(+), 0 deletions(-) + +diff --git a/kernel/signal.c b/kernel/signal.c +index 57552e6..89e691d 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -1829,6 +1829,14 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) + if (clear_code) + current->exit_code = 0; + read_unlock(&tasklist_lock); ++ ++ /* ++ * It is possible that __TASK_UTRACED was added by utrace ++ * while we were __TASK_TRACED and before we take ->siglock ++ * for wake_up_quiescent(), we need to block in this case. ++ * Otherwise this is unnecessary but absolutely harmless. ++ */ ++ schedule(); + } + + tracehook_finish_stop(); +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:17 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:17 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:36 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4390F1287F3; + Thu, 30 Jun 2011 20:23:36 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id v5mzxCjpefBI; Thu, 30 Jun 2011 20:23:36 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 283B21287DD; + Thu, 30 Jun 2011 20:23:36 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NSc9032626; + Thu, 30 Jun 2011 20:23:29 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:36 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:34 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 12/19] get_signal_to_deliver: restructure utrace/ptrace + signal reporting +Message-ID: <20110701002134.GA25834@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Status: RO +Content-Length: 2012 +Lines: 73 + +get_signal_to_deliver() assumes that either tracehook_get_signal() does +nothing (without CONFIG_UTRACE), or it also reports the signal to ptrace +engine implemented on top of utrace. Now that ptrace works independently +this doesn't work. + +Change the code to call ptrace_signal() after tracehook_get_signal(). + +Move ->ptrace check from ptrace_signal() to get_signal_to_deliver(), +we do not want to change *return_ka if it was initialized by utrace +and the task is not traced. + +IOW, roughly, ptrace acts as if it is the last attached engine, it +takes the final decision about the signal. + +Signed-off-by: Oleg Nesterov +--- + kernel/signal.c | 24 +++++++++++------------- + 1 files changed, 11 insertions(+), 13 deletions(-) + +diff --git a/kernel/signal.c b/kernel/signal.c +index 89e691d..d0e0c67 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -2006,9 +2006,6 @@ retry: + static int ptrace_signal(int signr, siginfo_t *info, + struct pt_regs *regs, void *cookie) + { +- if (!task_ptrace(current)) +- return signr; +- + ptrace_signal_deliver(regs, cookie); + + /* Let the debugger run. */ +@@ -2110,6 +2107,7 @@ relock: + signr = tracehook_get_signal(current, regs, info, return_ka); + if (unlikely(signr < 0)) + goto relock; ++ + if (unlikely(signr != 0)) + ka = return_ka; + else { +@@ -2117,18 +2115,18 @@ relock: + GROUP_STOP_PENDING) && do_signal_stop(0)) + goto relock; + +- signr = dequeue_signal(current, ¤t->blocked, +- info); ++ signr = dequeue_signal(current, ¤t->blocked, info); + +- if (!signr) +- break; /* will return 0 */ ++ ka = &sighand->action[signr-1]; ++ } + +- if (signr != SIGKILL) { +- signr = ptrace_signal(signr, info, +- regs, cookie); +- if (!signr) +- continue; +- } ++ if (!signr) ++ break; /* will return 0 */ ++ ++ if (signr != SIGKILL && current->ptrace) { ++ signr = ptrace_signal(signr, info, regs, cookie); ++ if (!signr) ++ continue; + + ka = &sighand->action[signr-1]; + } +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:18 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:18 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:39 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 74BDFD813B; + Thu, 30 Jun 2011 20:23:39 -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 tAGkG+GCPdeN; Thu, 30 Jun 2011 20:23:39 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5B728D812A; + Thu, 30 Jun 2011 20:23:39 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NWY1032629; + Thu, 30 Jun 2011 20:23:32 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:39 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:37 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 13/19] introduce ptrace_set_syscall_trace() +Message-ID: <20110701002137.GA25837@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Status: RO +Content-Length: 1581 +Lines: 52 + +No functional changes. Add the new helper, ptrace_set_syscall_trace(), +which should be used to set/clear TIF_SYSCALL_TRACE in ptrace code. +Currently it does nothing more. + +Signed-off-by: Oleg Nesterov +--- + kernel/ptrace.c | 15 ++++++++++----- + 1 files changed, 10 insertions(+), 5 deletions(-) + +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index 0b2aba5..b6fd922 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -37,6 +37,14 @@ static void ptrace_signal_wake_up(struct task_struct *p, int quiescent) + kick_process(p); + } + ++static void ptrace_set_syscall_trace(struct task_struct *p, bool on) ++{ ++ if (on) ++ set_tsk_thread_flag(p, TIF_SYSCALL_TRACE); ++ else ++ clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); ++} ++ + /* + * ptrace a task: make the debugger its new parent and + * move it to the ptrace list. +@@ -364,7 +372,7 @@ static int ptrace_detach(struct task_struct *child, unsigned int data) + + /* Architecture-specific hardware disable .. */ + ptrace_disable(child); +- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); ++ ptrace_set_syscall_trace(child, false); + + write_lock_irq(&tasklist_lock); + /* +@@ -551,10 +559,7 @@ static int ptrace_resume(struct task_struct *child, long request, + if (!valid_signal(data)) + return -EIO; + +- if (request == PTRACE_SYSCALL) +- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); +- else +- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); ++ ptrace_set_syscall_trace(child, request == PTRACE_SYSCALL); + + #ifdef TIF_SYSCALL_EMU + if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP) +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:20 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:20 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:42 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id CFC3F9C0C5; + Thu, 30 Jun 2011 20:23:42 -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 vS4KlM5ek+bt; Thu, 30 Jun 2011 20:23:42 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B28CA9C0C3; + Thu, 30 Jun 2011 20:23:42 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NZvo015255; + Thu, 30 Jun 2011 20:23:35 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:43 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:40 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 14/19] introduce PT_SYSCALL_TRACE flag +Message-ID: <20110701002140.GA25844@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Status: RO +Content-Length: 2236 +Lines: 73 + +Currently tracehooks assume that if the ptraced task has +TIF_SYSCALL_TRACE set, the tracee should report the syscall. +This is not true, this thread flag can be set by utrace. + +Add the new internal ptrace flag, PT_SYSCALL_TRACE. Change +ptrace_set_syscall_trace() to set/clear this bit along with +TIF_SYSCALL_TRACE, change ptrace_report_syscall() to check +this flag instead of PT_PTRACED. + +Signed-off-by: Oleg Nesterov +--- + include/linux/ptrace.h | 3 +++ + include/linux/tracehook.h | 2 +- + kernel/ptrace.c | 7 +++++-- + 3 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h +index 9178d5c..98d995d 100644 +--- a/include/linux/ptrace.h ++++ b/include/linux/ptrace.h +@@ -90,6 +90,8 @@ + + #define PT_TRACE_MASK 0x000003f4 + ++#define PT_SYSCALL_TRACE 0x00010000 ++ + /* single stepping state bits (used on ARM and PA-RISC) */ + #define PT_SINGLESTEP_BIT 31 + #define PT_SINGLESTEP (1<ptrace = 0; + if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) { + child->ptrace = current->ptrace; ++ child->ptrace &= ~PT_SYSCALL_TRACE; + __ptrace_link(child, current->parent); + } + +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index 3c7b6b3..6ce7a37 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -76,7 +76,7 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) + { + int ptrace = task_ptrace(current); + +- if (!(ptrace & PT_PTRACED)) ++ if (!(ptrace & PT_SYSCALL_TRACE)) + return; + + ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index b6fd922..0825a01 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -39,10 +39,13 @@ static void ptrace_signal_wake_up(struct task_struct *p, int quiescent) + + static void ptrace_set_syscall_trace(struct task_struct *p, bool on) + { +- if (on) ++ if (on) { ++ p->ptrace |= PT_SYSCALL_TRACE; + set_tsk_thread_flag(p, TIF_SYSCALL_TRACE); +- else ++ } else { ++ p->ptrace &= ~PT_SYSCALL_TRACE; + clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); ++ } + } + + /* +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:21 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:21 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:46 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 35A70D812A; + Thu, 30 Jun 2011 20:23: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 L06hkGLA8FQs; Thu, 30 Jun 2011 20:23:46 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 21C2BD810F; + Thu, 30 Jun 2011 20:23:46 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610Nc7k007721; + Thu, 30 Jun 2011 20:23:39 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:46 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:44 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 15/19] utrace: don't clear TIF_SYSCALL_TRACE if it is + needed by ptrace +Message-ID: <20110701002144.GA25847@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +Status: RO +Content-Length: 797 +Lines: 24 + +TIF_SYSCALL_TRACE should be cleared only if both ptrace and utrace do +not want it, change utrace_reset() to check PT_SYSCALL_TRACE before +clear_tsk_thread_flag(TIF_SYSCALL_TRACE). + +Signed-off-by: Oleg Nesterov +--- + kernel/utrace.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/kernel/utrace.c b/kernel/utrace.c +index daa96b9..a824ac3 100644 +--- a/kernel/utrace.c ++++ b/kernel/utrace.c +@@ -697,6 +697,7 @@ static bool utrace_reset(struct task_struct *task, struct utrace *utrace) + BUG_ON(utrace->death); + flags &= UTRACE_EVENT(REAP); + } else if (!(flags & UTRACE_EVENT_SYSCALL) && ++ !(task->ptrace & PT_SYSCALL_TRACE) && + test_tsk_thread_flag(task, TIF_SYSCALL_TRACE)) { + clear_tsk_thread_flag(task, TIF_SYSCALL_TRACE); + } +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:22 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:22 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:49 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 72E0C9C0C3; + Thu, 30 Jun 2011 20:23: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 o3ezwgloxuCS; Thu, 30 Jun 2011 20:23: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 5DD6A9C0C5; + Thu, 30 Jun 2011 20:23:49 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610NglX026379; + Thu, 30 Jun 2011 20:23:42 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:49 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:47 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 16/19] introduce task_utrace_lock/task_utrace_unlock +Message-ID: <20110701002147.GA25854@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +Status: RO +Content-Length: 2190 +Lines: 81 + +- Add task_utrace_lock(task). It simply takes task->utrace->lock if + this task was ever utraced. Otherwise it takes task_lock(), this + serializes with utrace_attach_task()->utrace_task_alloc(). In both + case the caller can be sure it can't race with anything which needs + utrace->lock. + +- Add task_utrace_unlock(task), it releases the corresponding lock. + +Signed-off-by: Oleg Nesterov +--- + include/linux/utrace.h | 9 +++++++++ + kernel/utrace.c | 26 ++++++++++++++++++++++++++ + 2 files changed, 35 insertions(+), 0 deletions(-) + +diff --git a/include/linux/utrace.h b/include/linux/utrace.h +index f251efe..5176f5f 100644 +--- a/include/linux/utrace.h ++++ b/include/linux/utrace.h +@@ -109,6 +109,12 @@ void utrace_signal_handler(struct task_struct *, int); + + #ifndef CONFIG_UTRACE + ++static inline void task_utrace_lock(struct task_struct *task) ++{ ++} ++static inline void task_utrace_unlock(struct task_struct *task) ++{ ++} + /* + * uses these accessors to avoid #ifdef CONFIG_UTRACE. + */ +@@ -131,6 +137,9 @@ static inline void task_utrace_proc_status(struct seq_file *m, + + #else /* CONFIG_UTRACE */ + ++extern void task_utrace_lock(struct task_struct *task); ++extern void task_utrace_unlock(struct task_struct *task); ++ + static inline unsigned long task_utrace_flags(struct task_struct *task) + { + return task->utrace_flags; +diff --git a/kernel/utrace.c b/kernel/utrace.c +index a824ac3..508c13c 100644 +--- a/kernel/utrace.c ++++ b/kernel/utrace.c +@@ -79,6 +79,32 @@ static int __init utrace_init(void) + } + module_init(utrace_init); + ++void task_utrace_lock(struct task_struct *task) ++{ ++ struct utrace *utrace = task_utrace_struct(task); ++ ++ if (!utrace) { ++ task_lock(task); ++ utrace = task_utrace_struct(task); ++ if (!utrace) ++ return; ++ ++ task_unlock(task); ++ } ++ ++ spin_lock(&utrace->lock); ++} ++ ++void task_utrace_unlock(struct task_struct *task) ++{ ++ struct utrace *utrace = task_utrace_struct(task); ++ ++ if (utrace) ++ spin_unlock(&utrace->lock); ++ else ++ task_unlock(task); ++} ++ + /* + * Set up @task.utrace for the first time. We can have races + * between two utrace_attach_task() calls here. The task_lock() +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:24 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:24 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:52 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id DB8D8D812A; + Thu, 30 Jun 2011 20:23:52 -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 74TDLZXBCl6s; Thu, 30 Jun 2011 20:23:52 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C6776D810F; + Thu, 30 Jun 2011 20:23:52 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NjAl015271; + Thu, 30 Jun 2011 20:23:45 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:53 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:50 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 17/19] teach ptrace_set_syscall_trace() to play well with + utrace +Message-ID: <20110701002150.GA25861@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Status: RO +Content-Length: 1513 +Lines: 49 + +1. ptrace_set_syscall_trace(true)->set_tsk_thread_flag(TIF_SYSCALL_TRACE) + can race with utrace_control()->utrace_reset() path which can miss + PT_SYSCALL_TRACE and clear TIF_SYSCALL_TRACE after it was already set. + +2. ptrace_set_syscall_trace(false) clears TIF_SYSCALL_TRACE and this is + not utrace-friendly, it can need this flag. + +Change ptrace_set_syscall_trace() to take task_utrace_lock(), this is +enough to fix the 1st problem. Check task_utrace_flags() before clearing +TIF_SYSCALL_TRACE, this fixes 2. + +Signed-off-by: Oleg Nesterov +--- + kernel/ptrace.c | 6 +++++- + 1 files changed, 5 insertions(+), 1 deletions(-) + +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index 0825a01..209ea2d 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + static void ptrace_signal_wake_up(struct task_struct *p, int quiescent) + { +@@ -39,13 +40,16 @@ static void ptrace_signal_wake_up(struct task_struct *p, int quiescent) + + static void ptrace_set_syscall_trace(struct task_struct *p, bool on) + { ++ task_utrace_lock(p); + if (on) { + p->ptrace |= PT_SYSCALL_TRACE; + set_tsk_thread_flag(p, TIF_SYSCALL_TRACE); + } else { + p->ptrace &= ~PT_SYSCALL_TRACE; +- clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); ++ if (!(task_utrace_flags(p) & UTRACE_EVENT_SYSCALL)) ++ clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); + } ++ task_utrace_unlock(p); + } + + /* +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:24 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:24 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:56 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6CD231287F3; + Thu, 30 Jun 2011 20:23:56 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id XX9YNcTcP1Ny; Thu, 30 Jun 2011 20:23:56 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 504BF1287DD; + Thu, 30 Jun 2011 20:23:56 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NmjB032686; + Thu, 30 Jun 2011 20:23:49 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:56 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:54 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 18/19] introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK +Message-ID: <20110701002154.GA25864@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Status: RO +Content-Length: 3725 +Lines: 108 + +Add the new internal ptrace flags, PT_SINGLE_STEP and PT_SINGLE_BLOCK. + +Like PT_SYSCALL_TRACE, this is needed to avoid the unnecessary ptrace +reports when TIF_SINGLESTEP was set by another engine, not by ptrace. +Also, we need these bits to coordinate the user_*_single_step() calls +from ptrace and utrace. + +TODO: update the !x86 ptrace code which does user_disable_single_step(). + +Signed-off-by: Oleg Nesterov +--- + arch/x86/kernel/ptrace.c | 1 + + include/linux/ptrace.h | 5 ++++- + include/linux/tracehook.h | 7 +++++-- + kernel/ptrace.c | 3 +++ + 4 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c +index 807c2a2..7ab475f 100644 +--- a/arch/x86/kernel/ptrace.c ++++ b/arch/x86/kernel/ptrace.c +@@ -807,6 +807,7 @@ static int ioperm_get(struct task_struct *target, + */ + void ptrace_disable(struct task_struct *child) + { ++ child->ptrace &= ~(PT_SINGLE_STEP | PT_SINGLE_BLOCK); + user_disable_single_step(child); + #ifdef TIF_SYSCALL_EMU + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); +diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h +index 98d995d..65b1e4f 100644 +--- a/include/linux/ptrace.h ++++ b/include/linux/ptrace.h +@@ -91,6 +91,8 @@ + #define PT_TRACE_MASK 0x000003f4 + + #define PT_SYSCALL_TRACE 0x00010000 ++#define PT_SINGLE_STEP 0x00020000 ++#define PT_SINGLE_BLOCK 0x00040000 + + /* single stepping state bits (used on ARM and PA-RISC) */ + #define PT_SINGLESTEP_BIT 31 +@@ -189,7 +191,8 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) + child->ptrace = 0; + if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) { + child->ptrace = current->ptrace; +- child->ptrace &= ~PT_SYSCALL_TRACE; ++ child->ptrace &= ++ ~(PT_SYSCALL_TRACE | PT_SINGLE_STEP | PT_SINGLE_BLOCK); + __ptrace_link(child, current->parent); + } + +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index 6ce7a37..06edb52 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -121,6 +121,9 @@ static inline __must_check int tracehook_report_syscall_entry( + return 0; + } + ++#define ptrace_wants_step() \ ++ (current->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK)) ++ + /** + * tracehook_report_syscall_exit - task has just finished a system call + * @regs: user register state of current task +@@ -143,7 +146,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) + if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) + utrace_report_syscall_exit(regs); + +- if (step) { ++ if (step && ptrace_wants_step()) { + siginfo_t info; + user_single_step_siginfo(current, regs, &info); + force_sig_info(SIGTRAP, &info, current); +@@ -436,7 +439,7 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, + { + if (task_utrace_flags(current)) + utrace_signal_handler(current, stepping); +- if (stepping) ++ if (stepping && ptrace_wants_step()) + ptrace_notify(SIGTRAP); + } + +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index 209ea2d..44908d0 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -575,13 +575,16 @@ static int ptrace_resume(struct task_struct *child, long request, + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); + #endif + ++ child->ptrace &= ~(PT_SINGLE_STEP | PT_SINGLE_BLOCK); + if (is_singleblock(request)) { + if (unlikely(!arch_has_block_step())) + return -EIO; ++ child->ptrace |= PT_SINGLE_BLOCK; + user_enable_block_step(child); + } else if (is_singlestep(request) || is_sysemu_singlestep(request)) { + if (unlikely(!arch_has_single_step())) + return -EIO; ++ child->ptrace |= PT_SINGLE_STEP; + user_enable_single_step(child); + } else { + user_disable_single_step(child); +-- +1.5.5.1 + + +From davej Thu Jun 30 20:27:26 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 30 Jun 2011 20:27:26 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:59 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8FF6B9C0C5; + Thu, 30 Jun 2011 20:23:59 -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 pNFtYrppMjXf; Thu, 30 Jun 2011 20:23:59 -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 7C2B89C0C3; + Thu, 30 Jun 2011 20:23:59 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610Nqpd026408; + Thu, 30 Jun 2011 20:23:52 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Fri, 1 Jul 2011 02:21:59 +0200 (CEST) +Date: Fri, 1 Jul 2011 02:21:57 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 19/19] utrace: consult PT_SINGLE_STEP/PT_SINGLE_BLOCK + before user_disable_single_step() +Message-ID: <20110701002157.GA25871@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +Status: RO +Content-Length: 1150 +Lines: 41 + +- do not do user_enable_block_step() if PT_SINGLE_STEP is set, in this + case ptrace has already called user_enable_single_step() + +- do not do user_disable_single_step() if PT_*_STEP is set, ptrace needs + the stepping + +Unless the tracee is killed this can't race with ptrace, this is called +by the tracee itself. + +Signed-off-by: Oleg Nesterov +--- + kernel/utrace.c | 6 ++++-- + 1 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/kernel/utrace.c b/kernel/utrace.c +index 508c13c..d6607cb 100644 +--- a/kernel/utrace.c ++++ b/kernel/utrace.c +@@ -1828,7 +1828,8 @@ static void finish_resume_report(struct task_struct *task, + + case UTRACE_BLOCKSTEP: + if (likely(arch_has_block_step())) { +- user_enable_block_step(task); ++ if (!(current->ptrace & PT_SINGLE_STEP)) ++ user_enable_block_step(task); + break; + } + +@@ -1856,7 +1857,8 @@ static void finish_resume_report(struct task_struct *task, + case UTRACE_REPORT: + case UTRACE_RESUME: + default: +- user_disable_single_step(task); ++ if (!(current->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK))) ++ user_disable_single_step(task); + break; + } + } +-- +1.5.5.1 + + From 2d60cadcce1ab36ae6578bcfee73b64cea4accb9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 2 Aug 2011 12:56:27 -0400 Subject: [PATCH 106/397] Add change to include the rt2x00 drivers in modules.networking --- kernel.spec | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 5ca1921c4..4a28e04d9 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 @@ -1504,7 +1504,7 @@ BuildKernel() { } collect_modules_list networking \ - 'register_netdev|ieee80211_register_hw|usbnet_probe|phy_driver_register' + 'register_netdev|ieee80211_register_hw|usbnet_probe|phy_driver_register|rt2x00(pci|usb)_probe' collect_modules_list block \ 'ata_scsi_ioctl|scsi_add_host|scsi_add_host_with_dma|blk_init_queue|register_mtd_blktrans|scsi_esp_register|scsi_register_device_handler' collect_modules_list drm \ @@ -1871,6 +1871,10 @@ fi # and build. %changelog +* Tue Aug 02 2011 Josh Boyer 2.6.40-5 +- Add change from Yanko Kaneti to get the rt2x00 drivers in modules.networking + (rhbz 708314) + * Fri Jul 29 2011 Dave Jones 2.6.40-4 - Re-add utrace, which got accidentally dropped during the rebase. From d988a172b0e2bf061e5a846dc76ff7acf887f247 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 2 Aug 2011 18:18:17 -0400 Subject: [PATCH 107/397] Change USB_SERIAL_OPTION back to modular. (rhbz 727680) --- config-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index dc11ce9ac..6919e5b47 100644 --- a/config-generic +++ b/config-generic @@ -3381,7 +3381,7 @@ CONFIG_USB_SERIAL_MOS7715_PARPORT=y CONFIG_USB_SERIAL_MOS7840=m CONFIG_USB_SERIAL_MOTOROLA=m CONFIG_USB_SERIAL_NAVMAN=m -CONFIG_USB_SERIAL_OPTION=y +CONFIG_USB_SERIAL_OPTION=m CONFIG_USB_SERIAL_OTI6858=m CONFIG_USB_SERIAL_OPTICON=m CONFIG_USB_SERIAL_OMNINET=m diff --git a/kernel.spec b/kernel.spec index 4a28e04d9..4713d12ac 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1871,6 +1871,9 @@ fi # and build. %changelog +* Tue Aug 02 2011 Dave Jones +- Change USB_SERIAL_OPTION back to modular. (rhbz 727680) + * Tue Aug 02 2011 Josh Boyer 2.6.40-5 - Add change from Yanko Kaneti to get the rt2x00 drivers in modules.networking (rhbz 708314) From c309d3128d8df3ee65a2a0a0d3f731ce7e67dc5c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 2 Aug 2011 19:23:10 -0400 Subject: [PATCH 108/397] Add fix from 3.1 for mounting HFSPlus filesystems --- ...io-requests-are-not-smaller-than-the.patch | 315 ++++++++++++++++++ kernel.spec | 8 +- 2 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch diff --git a/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch b/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch new file mode 100644 index 000000000..c81bf91d1 --- /dev/null +++ b/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch @@ -0,0 +1,315 @@ +From 6596528e391ad978a6a120142cba97a1d7324cb6 Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Mon, 18 Jul 2011 08:06:23 -0700 +Subject: [PATCH] hfsplus: ensure bio requests are not smaller than the + hardware sectors + +Currently all bio requests are 512 bytes, which may fail for media +whose physical sector size is larger than this. Ensure these +requests are not smaller than the block device logical block size. + +BugLink: http://bugs.launchpad.net/bugs/734883 +Signed-off-by: Seth Forshee +Signed-off-by: Christoph Hellwig +--- + fs/hfsplus/hfsplus_fs.h | 16 ++++++++- + fs/hfsplus/part_tbl.c | 32 ++++++++++-------- + fs/hfsplus/super.c | 12 +++--- + fs/hfsplus/wrapper.c | 83 +++++++++++++++++++++++++++++++++++----------- + 4 files changed, 101 insertions(+), 42 deletions(-) + +diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h +index 0bebf74..81dfd1e 100644 +--- a/fs/hfsplus/hfsplus_fs.h ++++ b/fs/hfsplus/hfsplus_fs.h +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include "hfsplus_raw.h" + + #define DBG_BNODE_REFS 0x00000001 +@@ -110,7 +111,9 @@ struct hfsplus_vh; + struct hfs_btree; + + struct hfsplus_sb_info { ++ void *s_vhdr_buf; + struct hfsplus_vh *s_vhdr; ++ void *s_backup_vhdr_buf; + struct hfsplus_vh *s_backup_vhdr; + struct hfs_btree *ext_tree; + struct hfs_btree *cat_tree; +@@ -258,6 +261,15 @@ struct hfsplus_readdir_data { + struct hfsplus_cat_key key; + }; + ++/* ++ * Find minimum acceptible I/O size for an hfsplus sb. ++ */ ++static inline unsigned short hfsplus_min_io_size(struct super_block *sb) ++{ ++ return max_t(unsigned short, bdev_logical_block_size(sb->s_bdev), ++ HFSPLUS_SECTOR_SIZE); ++} ++ + #define hfs_btree_open hfsplus_btree_open + #define hfs_btree_close hfsplus_btree_close + #define hfs_btree_write hfsplus_btree_write +@@ -436,8 +448,8 @@ int hfsplus_compare_dentry(const struct dentry *parent, + /* wrapper.c */ + int hfsplus_read_wrapper(struct super_block *); + int hfs_part_find(struct super_block *, sector_t *, sector_t *); +-int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, +- void *data, int rw); ++int hfsplus_submit_bio(struct super_block *sb, sector_t sector, ++ void *buf, void **data, int rw); + + /* time macros */ + #define __hfsp_mt2ut(t) (be32_to_cpu(t) - 2082844800U) +diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c +index 40ad88c..eb355d8 100644 +--- a/fs/hfsplus/part_tbl.c ++++ b/fs/hfsplus/part_tbl.c +@@ -88,11 +88,12 @@ static int hfs_parse_old_pmap(struct super_block *sb, struct old_pmap *pm, + return -ENOENT; + } + +-static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm, +- sector_t *part_start, sector_t *part_size) ++static int hfs_parse_new_pmap(struct super_block *sb, void *buf, ++ struct new_pmap *pm, sector_t *part_start, sector_t *part_size) + { + struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); + int size = be32_to_cpu(pm->pmMapBlkCnt); ++ int buf_size = hfsplus_min_io_size(sb); + int res; + int i = 0; + +@@ -107,11 +108,14 @@ static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm, + if (++i >= size) + return -ENOENT; + +- res = hfsplus_submit_bio(sb->s_bdev, +- *part_start + HFS_PMAP_BLK + i, +- pm, READ); +- if (res) +- return res; ++ pm = (struct new_pmap *)((u8 *)pm + HFSPLUS_SECTOR_SIZE); ++ if ((u8 *)pm - (u8 *)buf >= buf_size) { ++ res = hfsplus_submit_bio(sb, ++ *part_start + HFS_PMAP_BLK + i, ++ buf, (void **)&pm, READ); ++ if (res) ++ return res; ++ } + } while (pm->pmSig == cpu_to_be16(HFS_NEW_PMAP_MAGIC)); + + return -ENOENT; +@@ -124,15 +128,15 @@ static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm, + int hfs_part_find(struct super_block *sb, + sector_t *part_start, sector_t *part_size) + { +- void *data; ++ void *buf, *data; + int res; + +- data = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL); +- if (!data) ++ buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); ++ if (!buf) + return -ENOMEM; + +- res = hfsplus_submit_bio(sb->s_bdev, *part_start + HFS_PMAP_BLK, +- data, READ); ++ res = hfsplus_submit_bio(sb, *part_start + HFS_PMAP_BLK, ++ buf, &data, READ); + if (res) + goto out; + +@@ -141,13 +145,13 @@ int hfs_part_find(struct super_block *sb, + res = hfs_parse_old_pmap(sb, data, part_start, part_size); + break; + case HFS_NEW_PMAP_MAGIC: +- res = hfs_parse_new_pmap(sb, data, part_start, part_size); ++ res = hfs_parse_new_pmap(sb, buf, data, part_start, part_size); + break; + default: + res = -ENOENT; + break; + } + out: +- kfree(data); ++ kfree(buf); + return res; + } +diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c +index 84f56e1..c106ca2 100644 +--- a/fs/hfsplus/super.c ++++ b/fs/hfsplus/super.c +@@ -203,17 +203,17 @@ int hfsplus_sync_fs(struct super_block *sb, int wait) + write_backup = 1; + } + +- error2 = hfsplus_submit_bio(sb->s_bdev, ++ error2 = hfsplus_submit_bio(sb, + sbi->part_start + HFSPLUS_VOLHEAD_SECTOR, +- sbi->s_vhdr, WRITE_SYNC); ++ sbi->s_vhdr_buf, NULL, WRITE_SYNC); + if (!error) + error = error2; + if (!write_backup) + goto out; + +- error2 = hfsplus_submit_bio(sb->s_bdev, ++ error2 = hfsplus_submit_bio(sb, + sbi->part_start + sbi->sect_count - 2, +- sbi->s_backup_vhdr, WRITE_SYNC); ++ sbi->s_backup_vhdr_buf, NULL, WRITE_SYNC); + if (!error) + error2 = error; + out: +@@ -257,8 +257,8 @@ static void hfsplus_put_super(struct super_block *sb) + hfs_btree_close(sbi->ext_tree); + iput(sbi->alloc_file); + iput(sbi->hidden_dir); +- kfree(sbi->s_vhdr); +- kfree(sbi->s_backup_vhdr); ++ kfree(sbi->s_vhdr_buf); ++ kfree(sbi->s_backup_vhdr_buf); + unload_nls(sbi->nls); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; +diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c +index 2f933e8..10e515a 100644 +--- a/fs/hfsplus/wrapper.c ++++ b/fs/hfsplus/wrapper.c +@@ -31,25 +31,67 @@ static void hfsplus_end_io_sync(struct bio *bio, int err) + complete(bio->bi_private); + } + +-int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, +- void *data, int rw) ++/* ++ * hfsplus_submit_bio - Perfrom block I/O ++ * @sb: super block of volume for I/O ++ * @sector: block to read or write, for blocks of HFSPLUS_SECTOR_SIZE bytes ++ * @buf: buffer for I/O ++ * @data: output pointer for location of requested data ++ * @rw: direction of I/O ++ * ++ * The unit of I/O is hfsplus_min_io_size(sb), which may be bigger than ++ * HFSPLUS_SECTOR_SIZE, and @buf must be sized accordingly. On reads ++ * @data will return a pointer to the start of the requested sector, ++ * which may not be the same location as @buf. ++ * ++ * If @sector is not aligned to the bdev logical block size it will ++ * be rounded down. For writes this means that @buf should contain data ++ * that starts at the rounded-down address. As long as the data was ++ * read using hfsplus_submit_bio() and the same buffer is used things ++ * will work correctly. ++ */ ++int hfsplus_submit_bio(struct super_block *sb, sector_t sector, ++ void *buf, void **data, int rw) + { + DECLARE_COMPLETION_ONSTACK(wait); + struct bio *bio; + int ret = 0; ++ unsigned int io_size; ++ loff_t start; ++ int offset; ++ ++ /* ++ * Align sector to hardware sector size and find offset. We ++ * assume that io_size is a power of two, which _should_ ++ * be true. ++ */ ++ io_size = hfsplus_min_io_size(sb); ++ start = (loff_t)sector << HFSPLUS_SECTOR_SHIFT; ++ offset = start & (io_size - 1); ++ sector &= ~((io_size >> HFSPLUS_SECTOR_SHIFT) - 1); + + bio = bio_alloc(GFP_NOIO, 1); + bio->bi_sector = sector; +- bio->bi_bdev = bdev; ++ bio->bi_bdev = sb->s_bdev; + bio->bi_end_io = hfsplus_end_io_sync; + bio->bi_private = &wait; + +- /* +- * We always submit one sector at a time, so bio_add_page must not fail. +- */ +- if (bio_add_page(bio, virt_to_page(data), HFSPLUS_SECTOR_SIZE, +- offset_in_page(data)) != HFSPLUS_SECTOR_SIZE) +- BUG(); ++ if (!(rw & WRITE) && data) ++ *data = (u8 *)buf + offset; ++ ++ while (io_size > 0) { ++ unsigned int page_offset = offset_in_page(buf); ++ unsigned int len = min_t(unsigned int, PAGE_SIZE - page_offset, ++ io_size); ++ ++ ret = bio_add_page(bio, virt_to_page(buf), len, page_offset); ++ if (ret != len) { ++ ret = -EIO; ++ goto out; ++ } ++ io_size -= len; ++ buf = (u8 *)buf + len; ++ } + + submit_bio(rw, bio); + wait_for_completion(&wait); +@@ -57,8 +99,9 @@ int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, + if (!bio_flagged(bio, BIO_UPTODATE)) + ret = -EIO; + ++out: + bio_put(bio); +- return ret; ++ return ret < 0 ? ret : 0; + } + + static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd) +@@ -143,17 +186,17 @@ int hfsplus_read_wrapper(struct super_block *sb) + goto out; + + error = -ENOMEM; +- sbi->s_vhdr = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL); +- if (!sbi->s_vhdr) ++ sbi->s_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); ++ if (!sbi->s_vhdr_buf) + goto out; +- sbi->s_backup_vhdr = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL); +- if (!sbi->s_backup_vhdr) ++ sbi->s_backup_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); ++ if (!sbi->s_backup_vhdr_buf) + goto out_free_vhdr; + + reread: +- error = hfsplus_submit_bio(sb->s_bdev, +- part_start + HFSPLUS_VOLHEAD_SECTOR, +- sbi->s_vhdr, READ); ++ error = hfsplus_submit_bio(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, ++ sbi->s_vhdr_buf, (void **)&sbi->s_vhdr, ++ READ); + if (error) + goto out_free_backup_vhdr; + +@@ -183,9 +226,9 @@ reread: + goto reread; + } + +- error = hfsplus_submit_bio(sb->s_bdev, +- part_start + part_size - 2, +- sbi->s_backup_vhdr, READ); ++ error = hfsplus_submit_bio(sb, part_start + part_size - 2, ++ sbi->s_backup_vhdr_buf, ++ (void **)&sbi->s_backup_vhdr, READ); + if (error) + goto out_free_backup_vhdr; + +-- +1.7.6 + diff --git a/kernel.spec b/kernel.spec index 4713d12ac..6fa0dcf10 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 @@ -682,6 +682,7 @@ Patch12204: linux-2.6-enable-more-pci-autosuspend.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13000: fix-scsi_dispatch_cmd.patch +Patch13001: hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch Patch20000: utrace.patch @@ -1257,6 +1258,8 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch fix-scsi_dispatch_cmd.patch +ApplyPatch hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch + ApplyPatch utrace.patch # END OF PATCH APPLICATIONS @@ -1871,6 +1874,9 @@ fi # and build. %changelog +* Tue Aug 02 2011 Josh Boyer +- Add patch to fix HFSPlus filesystem mounting (rhbz 720771) + * Tue Aug 02 2011 Dave Jones - Change USB_SERIAL_OPTION back to modular. (rhbz 727680) From 52aef13a2d375a7abc1d806db3bed90612d10ab4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 2 Aug 2011 14:33:26 -0400 Subject: [PATCH 109/397] Add patch to fix epoll lockdep warnings --- epoll-fix-spurious-lockdep-warnings.patch | 116 ++++++++++++++++++++++ kernel.spec | 7 +- 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 epoll-fix-spurious-lockdep-warnings.patch diff --git a/epoll-fix-spurious-lockdep-warnings.patch b/epoll-fix-spurious-lockdep-warnings.patch new file mode 100644 index 000000000..131796af8 --- /dev/null +++ b/epoll-fix-spurious-lockdep-warnings.patch @@ -0,0 +1,116 @@ +epoll can acquire multiple ep->mutex on multiple "struct eventpoll"s +at once in the case where one epoll fd is monitoring another epoll +fd. This is perfectly OK, since we're careful about the lock ordering, +but causes spurious lockdep warnings. Annotate the recursion using +mutex_lock_nested, and add a comment explaining the nesting rules for +good measure. + +Reported-by: Paul Bolle +Signed-off-by: Nelson Elhage +--- + I've tested this on a synthetic epoll test case, that just adds e1 to + e2 and then does an epoll_wait(). I verified that it caused lockdep + problems on 3.0 and that this patch fixed it, but I haven't done more + extensive testing. Paul, are you able to test systemd against this? + + fs/eventpoll.c | 25 ++++++++++++++++++------- + 1 files changed, 18 insertions(+), 7 deletions(-) + +diff --git a/fs/eventpoll.c b/fs/eventpoll.c +index f9cfd16..0cb7bc6 100644 +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -76,6 +76,15 @@ + * Events that require holding "epmutex" are very rare, while for + * normal operations the epoll private "ep->mtx" will guarantee + * a better scalability. ++ * It is possible to acquire multiple "ep->mtx"es at once in the case ++ * when one epoll fd is added to another. In this case, we always ++ * acquire the locks in the order of nesting (i.e. after epoll_ctl(e1, ++ * EPOLL_CTL_ADD, e2), e1->mtx will always be acquired before ++ * e2->mtx). Since we disallow cycles of epoll file descriptors, this ++ * ensures that the mutexes are well-ordered. In order to communicate ++ * this nesting to lockdep, when walking a tree of epoll file ++ * descriptors, we use the current recursion depth as the lockdep ++ * subkey. + */ + + /* Epoll private bits inside the event mask */ +@@ -464,13 +473,15 @@ static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi) + * @ep: Pointer to the epoll private data structure. + * @sproc: Pointer to the scan callback. + * @priv: Private opaque data passed to the @sproc callback. ++ * @depth: The current depth of recursive f_op->poll calls. + * + * Returns: The same integer error code returned by the @sproc callback. + */ + static int ep_scan_ready_list(struct eventpoll *ep, + int (*sproc)(struct eventpoll *, + struct list_head *, void *), +- void *priv) ++ void *priv, ++ int depth) + { + int error, pwake = 0; + unsigned long flags; +@@ -481,7 +492,7 @@ static int ep_scan_ready_list(struct eventpoll *ep, + * We need to lock this because we could be hit by + * eventpoll_release_file() and epoll_ctl(). + */ +- mutex_lock(&ep->mtx); ++ mutex_lock_nested(&ep->mtx, depth); + + /* + * Steal the ready list, and re-init the original one to the +@@ -670,7 +681,7 @@ static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head, + + static int ep_poll_readyevents_proc(void *priv, void *cookie, int call_nests) + { +- return ep_scan_ready_list(priv, ep_read_events_proc, NULL); ++ return ep_scan_ready_list(priv, ep_read_events_proc, NULL, call_nests + 1); + } + + static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait) +@@ -737,7 +748,7 @@ void eventpoll_release_file(struct file *file) + + ep = epi->ep; + list_del_init(&epi->fllink); +- mutex_lock(&ep->mtx); ++ mutex_lock_nested(&ep->mtx, 0); + ep_remove(ep, epi); + mutex_unlock(&ep->mtx); + } +@@ -1134,7 +1145,7 @@ static int ep_send_events(struct eventpoll *ep, + esed.maxevents = maxevents; + esed.events = events; + +- return ep_scan_ready_list(ep, ep_send_events_proc, &esed); ++ return ep_scan_ready_list(ep, ep_send_events_proc, &esed, 0); + } + + static inline struct timespec ep_set_mstimeout(long ms) +@@ -1267,7 +1278,7 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests) + struct rb_node *rbp; + struct epitem *epi; + +- mutex_lock(&ep->mtx); ++ mutex_lock_nested(&ep->mtx, call_nests + 1); + for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) { + epi = rb_entry(rbp, struct epitem, rbn); + if (unlikely(is_file_epoll(epi->ffd.file))) { +@@ -1409,7 +1420,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, + } + + +- mutex_lock(&ep->mtx); ++ mutex_lock_nested(&ep->mtx, 0); + + /* + * Try to lookup the file inside our RB tree, Since we grabbed "mtx" +-- +1.7.4.1 + +-- +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 \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index 6fa0dcf10..b8b21e2c8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -682,7 +682,8 @@ Patch12204: linux-2.6-enable-more-pci-autosuspend.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13000: fix-scsi_dispatch_cmd.patch -Patch13001: hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch +Patch13001: epoll-fix-spurious-lockdep-warnings.patch +Patch13002: hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch Patch20000: utrace.patch @@ -1257,6 +1258,7 @@ ApplyPatch neuter_intel_microcode_load.patch ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch fix-scsi_dispatch_cmd.patch +ApplyPatch epoll-fix-spurious-lockdep-warnings.patch ApplyPatch hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch @@ -1874,6 +1876,9 @@ fi # and build. %changelog +* Tue Aug 02 2011 Josh Boyer +- Fix epoll recursive lockdep warnings (rhbz 722472) + * Tue Aug 02 2011 Josh Boyer - Add patch to fix HFSPlus filesystem mounting (rhbz 720771) From a9cca766eb649fe0cb02dc714fa364ca5bb517c3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 3 Aug 2011 08:24:49 -0400 Subject: [PATCH 110/397] Add patches to fix rhbz 720594,720128,720054. This syncs up f15 with f16 for the most part now. --- fix-cdc-ncm-dma-stack-vars.patch | 114 ++++++++++++++++++ kernel.spec | 15 +++ ...2x00-Add-device-ID-for-RT539F-device.patch | 23 ++++ ...tek-driver-uses-stack-memory-for-DMA.patch | 96 +++++++++++++++ 4 files changed, 248 insertions(+) create mode 100644 fix-cdc-ncm-dma-stack-vars.patch create mode 100644 linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch create mode 100644 ums-realtek-driver-uses-stack-memory-for-DMA.patch diff --git a/fix-cdc-ncm-dma-stack-vars.patch b/fix-cdc-ncm-dma-stack-vars.patch new file mode 100644 index 000000000..7f46a00fe --- /dev/null +++ b/fix-cdc-ncm-dma-stack-vars.patch @@ -0,0 +1,114 @@ +commit d072ef23b8ee6bcabc00beff0b5702e704a473cb +Author: Josh Boyer +Date: Tue Aug 2 08:09:56 2011 -0400 + + usbnet/cdc_ncm: Don't use stack variables for DMA buffers + + The cdc_ncm driver still has a few places where stack variables are passed + to the cdc_ncm_do_request function. This triggers a stack trace in + lib/dma-debug.c if the CONFIG_DEBUG_DMA_API option is set. + + Adjust these calls to pass parameters that have been allocated with kzalloc. + + Signed-off-by: Josh Boyer + +diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c +index fd622a6..96dd386 100644 +--- a/drivers/net/usb/cdc_ncm.c ++++ b/drivers/net/usb/cdc_ncm.c +@@ -260,23 +260,38 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) + req.wIndex = cpu_to_le16(iface_no); + + if (flags & USB_CDC_NCM_NCAP_NTB_INPUT_SIZE) { +- struct usb_cdc_ncm_ndp_input_size ndp_in_sz; ++ struct usb_cdc_ncm_ndp_input_size *ndp_in_sz; ++ ++ ndp_in_sz = kzalloc(sizeof(*ndp_in_sz), GFP_KERNEL); ++ if (!ndp_in_sz) { ++ err = -ENOMEM; ++ goto size_err; ++ } + + req.wLength = 8; +- ndp_in_sz.dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); +- ndp_in_sz.wNtbInMaxDatagrams = ++ ndp_in_sz->dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); ++ ndp_in_sz->wNtbInMaxDatagrams = + cpu_to_le16(CDC_NCM_DPT_DATAGRAMS_MAX); +- ndp_in_sz.wReserved = 0; +- err = cdc_ncm_do_request(ctx, &req, &ndp_in_sz, 0, NULL, ++ ndp_in_sz->wReserved = 0; ++ err = cdc_ncm_do_request(ctx, &req, ndp_in_sz, 0, NULL, + 1000); ++ kfree(ndp_in_sz); + } else { +- __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); ++ __le32 *dwNtbInMaxSize; ++ dwNtbInMaxSize = kzalloc(sizeof(*dwNtbInMaxSize), GFP_KERNEL); ++ if (!dwNtbInMaxSize) { ++ err = -ENOMEM; ++ goto size_err; ++ } ++ *dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); + + req.wLength = 4; +- err = cdc_ncm_do_request(ctx, &req, &dwNtbInMaxSize, 0, ++ err = cdc_ncm_do_request(ctx, &req, dwNtbInMaxSize, 0, + NULL, 1000); ++ kfree(dwNtbInMaxSize); + } + ++size_err: + if (err) + pr_debug("Setting NTB Input Size failed\n"); + } +@@ -362,9 +377,15 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) + + /* set Max Datagram Size (MTU) */ + if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) { +- __le16 max_datagram_size; ++ __le16 *max_datagram_size; + u16 eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize); + ++ max_datagram_size = kzalloc(sizeof(*max_datagram_size), GFP_KERNEL); ++ if (!max_datagram_size) { ++ err = -ENOMEM; ++ goto max_dgram_err; ++ } ++ + req.bmRequestType = USB_TYPE_CLASS | USB_DIR_IN | + USB_RECIP_INTERFACE; + req.bNotificationType = USB_CDC_GET_MAX_DATAGRAM_SIZE; +@@ -372,13 +393,15 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) + req.wIndex = cpu_to_le16(iface_no); + req.wLength = cpu_to_le16(2); + +- err = cdc_ncm_do_request(ctx, &req, &max_datagram_size, 0, NULL, ++ err = cdc_ncm_do_request(ctx, &req, max_datagram_size, 0, NULL, + 1000); ++ + if (err) { + pr_debug("GET_MAX_DATAGRAM_SIZE failed, use size=%u\n", + CDC_NCM_MIN_DATAGRAM_SIZE); ++ kfree(max_datagram_size); + } else { +- ctx->max_datagram_size = le16_to_cpu(max_datagram_size); ++ ctx->max_datagram_size = le16_to_cpu(*max_datagram_size); + /* Check Eth descriptor value */ + if (eth_max_sz < CDC_NCM_MAX_DATAGRAM_SIZE) { + if (ctx->max_datagram_size > eth_max_sz) +@@ -401,10 +424,12 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) + req.wValue = 0; + req.wIndex = cpu_to_le16(iface_no); + req.wLength = 2; +- max_datagram_size = cpu_to_le16(ctx->max_datagram_size); ++ *max_datagram_size = cpu_to_le16(ctx->max_datagram_size); + +- err = cdc_ncm_do_request(ctx, &req, &max_datagram_size, ++ err = cdc_ncm_do_request(ctx, &req, max_datagram_size, + 0, NULL, 1000); ++ kfree(max_datagram_size); ++max_dgram_err: + if (err) + pr_debug("SET_MAX_DATAGRAM_SIZE failed\n"); + } diff --git a/kernel.spec b/kernel.spec index b8b21e2c8..aa20c703b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -675,6 +675,11 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12018: neuter_intel_microcode_load.patch +Patch12019: linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch + +Patch12022: fix-cdc-ncm-dma-stack-vars.patch +Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch + # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch Patch12204: linux-2.6-enable-more-pci-autosuspend.patch @@ -1254,6 +1259,11 @@ ApplyPatch add-appleir-usb-driver.patch ApplyPatch neuter_intel_microcode_load.patch +ApplyPatch linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch + +ApplyPatch fix-cdc-ncm-dma-stack-vars.patch +ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch + # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -1876,6 +1886,11 @@ fi # and build. %changelog +* Wed Aug 03 2011 Josh Boyer +- rt2x00: Add device ID for RT539F device. (rhbz 720594) +- Add patch to fix backtrace in cdc_ncm driver (rhbz 720128) +- Add patch to fix backtrace in usm-realtek driver (rhbz 720054) + * Tue Aug 02 2011 Josh Boyer - Fix epoll recursive lockdep warnings (rhbz 722472) diff --git a/linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch b/linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch new file mode 100644 index 000000000..abf01cfe4 --- /dev/null +++ b/linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch @@ -0,0 +1,23 @@ +commit 71e0b38c2914018b01f3f08b43ee9e3328197699 +Author: Gertjan van Wingerde +Date: Wed Jul 6 22:58:55 2011 +0200 + + rt2x00: Add device ID for RT539F device. + + Reported-by: Wim Vander Schelden + Signed-off-by: Gertjan van Wingerde + Signed-off-by: Ivo van Doorn + Signed-off-by: John W. Linville + +diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c +index 5513edf..fd99449 100644 +--- a/drivers/net/wireless/rt2x00/rt2800pci.c ++++ b/drivers/net/wireless/rt2x00/rt2800pci.c +@@ -1160,6 +1160,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { + #endif + #ifdef CONFIG_RT2800PCI_RT53XX + { PCI_DEVICE(0x1814, 0x5390) }, ++ { PCI_DEVICE(0x1814, 0x539f) }, + #endif + { 0, } + }; diff --git a/ums-realtek-driver-uses-stack-memory-for-DMA.patch b/ums-realtek-driver-uses-stack-memory-for-DMA.patch new file mode 100644 index 000000000..2564fdbf2 --- /dev/null +++ b/ums-realtek-driver-uses-stack-memory-for-DMA.patch @@ -0,0 +1,96 @@ +commit 82e632009bb7d6b97f8cabe9918c82703f4e5cd2 +Author: Josh Boyer +Date: Tue Aug 2 08:37:53 2011 -0400 + + This patch changed rts51x_read_mem, rts51x_write_mem, and rts51x_read_status to + allocate temporary buffers with kmalloc. This way stack addresses are not used + for DMA when these functions call rts51x_bulk_transport. + + Signed-off-by: Adam Cozzette + Backported-by: Josh Boyer + +diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c +index d509a4a..69a1bd3 100644 +--- a/drivers/usb/storage/realtek_cr.c ++++ b/drivers/usb/storage/realtek_cr.c +@@ -285,6 +285,11 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) + { + int retval; + u8 cmnd[12] = {0}; ++ u8 *buf; ++ ++ buf = kmalloc(len, GFP_NOIO); ++ if (buf == NULL) ++ return USB_STOR_TRANSPORT_ERROR; + + US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); + +@@ -296,10 +301,14 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) + cmnd[5] = (u8)len; + + retval = rts51x_bulk_transport(us, 0, cmnd, 12, +- data, len, DMA_FROM_DEVICE, NULL); +- if (retval != USB_STOR_TRANSPORT_GOOD) ++ buf, len, DMA_FROM_DEVICE, NULL); ++ if (retval != USB_STOR_TRANSPORT_GOOD) { ++ kfree(buf); + return -EIO; ++ } + ++ memcpy(data, buf, len); ++ kfree(buf); + return 0; + } + +@@ -307,6 +316,12 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) + { + int retval; + u8 cmnd[12] = {0}; ++ u8 *buf; ++ ++ buf = kmalloc(len, GFP_NOIO); ++ if (buf == NULL) ++ return USB_STOR_TRANSPORT_ERROR; ++ memcpy(buf, data, len); + + US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); + +@@ -318,7 +333,8 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) + cmnd[5] = (u8)len; + + retval = rts51x_bulk_transport(us, 0, cmnd, 12, +- data, len, DMA_TO_DEVICE, NULL); ++ buf, len, DMA_TO_DEVICE, NULL); ++ kfree(buf); + if (retval != USB_STOR_TRANSPORT_GOOD) + return -EIO; + +@@ -330,6 +346,11 @@ static int rts51x_read_status(struct us_data *us, + { + int retval; + u8 cmnd[12] = {0}; ++ u8 *buf; ++ ++ buf = kmalloc(len, GFP_NOIO); ++ if (buf == NULL) ++ return USB_STOR_TRANSPORT_ERROR; + + US_DEBUGP("%s, lun = %d\n", __func__, lun); + +@@ -337,10 +358,14 @@ static int rts51x_read_status(struct us_data *us, + cmnd[1] = 0x09; + + retval = rts51x_bulk_transport(us, lun, cmnd, 12, +- status, len, DMA_FROM_DEVICE, actlen); +- if (retval != USB_STOR_TRANSPORT_GOOD) ++ buf, len, DMA_FROM_DEVICE, actlen); ++ if (retval != USB_STOR_TRANSPORT_GOOD) { ++ kfree(buf); + return -EIO; ++ } + ++ memcpy(status, buf, len); ++ kfree(buf); + return 0; + } + From bdcd61e44a117ce16e9dc0691dcd97328c617fef Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 3 Aug 2011 13:40:30 -0400 Subject: [PATCH 111/397] Disable CONFIG_BCMA since no driver currently uses it (rhbz 727796) --- config-generic | 4 +--- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/config-generic b/config-generic index 6919e5b47..0c1304053 100644 --- a/config-generic +++ b/config-generic @@ -4657,9 +4657,7 @@ CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 CONFIG_TEST_KSTRTOX=m -CONFIG_BCMA=m -CONFIG_BCMA_HOST_PCI=y -# CONFIG_BCMA_DEBUG is not set +# CONFIG_BCMA is not set # CONFIG_GOOGLE_FIRMWARE is not set CONFIG_INTEL_MID_PTI=m diff --git a/kernel.spec b/kernel.spec index aa20c703b..4a4549bf1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1886,6 +1886,9 @@ fi # and build. %changelog +* Wed Aug 03 2011 John W. Linville +- Disable CONFIG_BCMA since no driver currently uses it (rhbz 727796) + * Wed Aug 03 2011 Josh Boyer - rt2x00: Add device ID for RT539F device. (rhbz 720594) - Add patch to fix backtrace in cdc_ncm driver (rhbz 720128) From 3082e89bfa17db28473381d1ff7dea8d470f1f23 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Aug 2011 19:09:58 -0400 Subject: [PATCH 112/397] Apply patches from 3.0.1rc It's easier to just delete all the generic -stable macro stuff and do it by hand than it is to make it work with our munged 3.0->2.6.40.x This is only going to live until f16 is out anyway, so lets not waste effort. --- fix-scsi_dispatch_cmd.patch | 68 ----------------- kernel.spec | 76 ++----------------- ...2x00-Add-device-ID-for-RT539F-device.patch | 23 ------ 3 files changed, 7 insertions(+), 160 deletions(-) delete mode 100644 fix-scsi_dispatch_cmd.patch delete mode 100644 linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch diff --git a/fix-scsi_dispatch_cmd.patch b/fix-scsi_dispatch_cmd.patch deleted file mode 100644 index 3976791ca..000000000 --- a/fix-scsi_dispatch_cmd.patch +++ /dev/null @@ -1,68 +0,0 @@ -commit bfe159a51203c15d23cb3158fffdc25ec4b4dda1 -Author: James Bottomley -Date: Thu Jul 7 15:45:40 2011 -0500 - - [SCSI] fix crash in scsi_dispatch_cmd() - - USB surprise removal of sr is triggering an oops in - scsi_dispatch_command(). What seems to be happening is that USB is - hanging on to a queue reference until the last close of the upper - device, so the crash is caused by surprise remove of a mounted CD - followed by attempted unmount. - - The problem is that USB doesn't issue its final commands as part of - the SCSI teardown path, but on last close when the block queue is long - gone. The long term fix is probably to make sr do the teardown in the - same way as sd (so remove all the lower bits on ejection, but keep the - upper disk alive until last close of user space). However, the - current oops can be simply fixed by not allowing any commands to be - sent to a dead queue. - - Cc: stable@kernel.org - Signed-off-by: James Bottomley - -diff --git a/block/blk-core.c b/block/blk-core.c -index d2f8f40..1d49e1c 100644 ---- a/block/blk-core.c -+++ b/block/blk-core.c -@@ -839,6 +839,9 @@ struct request *blk_get_request(struct request_queue *q, int rw, gfp_t gfp_mask) - { - struct request *rq; - -+ if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) -+ return NULL; -+ - BUG_ON(rw != READ && rw != WRITE); - - spin_lock_irq(q->queue_lock); -diff --git a/block/blk-exec.c b/block/blk-exec.c -index 8a0e7ec..a1ebceb 100644 ---- a/block/blk-exec.c -+++ b/block/blk-exec.c -@@ -50,6 +50,13 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, - { - int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; - -+ if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) { -+ rq->errors = -ENXIO; -+ if (rq->end_io) -+ rq->end_io(rq, rq->errors); -+ return; -+ } -+ - rq->rq_disk = bd_disk; - rq->end_io = done; - WARN_ON(irqs_disabled()); -diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c -index ec1803a..28d9c9d 100644 ---- a/drivers/scsi/scsi_lib.c -+++ b/drivers/scsi/scsi_lib.c -@@ -213,6 +213,8 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, - int ret = DRIVER_ERROR << 24; - - req = blk_get_request(sdev->request_queue, write, __GFP_WAIT); -+ if (!req) -+ return ret; - - if (bufflen && blk_rq_map_kern(sdev->request_queue, req, - buffer, bufflen, __GFP_WAIT)) diff --git a/kernel.spec b/kernel.spec index 4a4549bf1..6d4019aa9 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 0 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -64,7 +64,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 @@ -558,40 +558,8 @@ Source1000: config-local # Here should be only the patches up to the upstream canonical Linus tree. Patch00: patch-3.0.bz2 +Patch01: patch-3.0.1-rc1.bz2 -# For a stable release kernel -%if 0%{?stable_update} -%if 0%{?stable_base} -%define stable_patch_00 patch-3.%{base_sublevel}.%{stable_base}.bz2 -Patch01: %{stable_patch_00} -%endif -%if 0%{?stable_rc} -%define stable_patch_01 patch-3.%{base_sublevel}.%{stable_update}-rc%{stable_rc}.bz2 -Patch02: %{stable_patch_01} -%endif - -# non-released_kernel case -# These are automagically defined by the rcrev and gitrev values set up -# near the top of this spec file. -%else -%if 0%{?rcrev} -Patch00: patch-3.0-rc%{rcrev}.bz2 -%if 0%{?gitrev} -Patch01: patch-3.0-rc%{rcrev}-git%{gitrev}.bz2 -%endif -%else -# pre-{base_sublevel+1}-rc1 case -%if 0%{?gitrev} -Patch00: patch-3.%{base_sublevel}-git%{gitrev}.bz2 -%endif -%endif -%endif - -%if %{using_upstream_branch} -### BRANCH PATCH ### -%endif - -Patch03: git-linus.diff # we also need compile fixes for -vanilla Patch04: linux-2.6-compile-fixes.patch @@ -675,8 +643,6 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12018: neuter_intel_microcode_load.patch -Patch12019: linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch - Patch12022: fix-cdc-ncm-dma-stack-vars.patch Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch @@ -686,7 +652,6 @@ Patch12204: linux-2.6-enable-more-pci-autosuspend.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch -Patch13000: fix-scsi_dispatch_cmd.patch Patch13001: epoll-fix-spurious-lockdep-warnings.patch Patch13002: hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch @@ -1034,24 +999,6 @@ if [ ! -d kernel-%{kversion}%{?dist}/vanilla-%{vanillaversion} ]; then # Need to apply patches to the base vanilla version. cp -rl vanilla-%{kversion} vanilla-%{vanillaversion} - cd vanilla-%{vanillaversion} - -# Update vanilla to the latest upstream. -# (non-released_kernel case only) -%if 0%{?rcrev} - ApplyPatch patch-3.0-rc%{rcrev}.bz2 -%if 0%{?gitrev} - ApplyPatch patch-3.0-rc%{rcrev}-git%{gitrev}.bz2 -%endif -%else -# pre-{base_sublevel+1}-rc1 case -%if 0%{?gitrev} - ApplyPatch patch-3.0-git%{gitrev}.bz2 -%endif -%endif - - cd .. - fi %endif @@ -1076,14 +1023,6 @@ cp -rl vanilla-%{vanillaversion} linux-%{kversion}.%{_target_cpu} cd linux-%{kversion}.%{_target_cpu} -# released_kernel with possible stable updates -%if 0%{?stable_base} -ApplyPatch %{stable_patch_00} -%endif -%if 0%{?stable_rc} -ApplyPatch %{stable_patch_01} -%endif - %if %{using_upstream_branch} ### BRANCH APPLY ### %endif @@ -1117,8 +1056,7 @@ done # Update vanilla to the latest upstream. (2.6.39 -> 3.0) ApplyPatch patch-3.0.bz2 - -ApplyOptionalPatch git-linus.diff +ApplyPatch patch-3.0.1-rc1.bz2 ApplyPatch linux-2.6-makefile-after_link.patch @@ -1259,15 +1197,12 @@ ApplyPatch add-appleir-usb-driver.patch ApplyPatch neuter_intel_microcode_load.patch -ApplyPatch linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch - ApplyPatch fix-cdc-ncm-dma-stack-vars.patch ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch -ApplyPatch fix-scsi_dispatch_cmd.patch ApplyPatch epoll-fix-spurious-lockdep-warnings.patch ApplyPatch hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch @@ -1886,6 +1821,9 @@ fi # and build. %changelog +* Wed Aug 03 2011 Dave Jones +- Apply patches from patch-3.0.1-rc1 + * Wed Aug 03 2011 John W. Linville - Disable CONFIG_BCMA since no driver currently uses it (rhbz 727796) diff --git a/linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch b/linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch deleted file mode 100644 index abf01cfe4..000000000 --- a/linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch +++ /dev/null @@ -1,23 +0,0 @@ -commit 71e0b38c2914018b01f3f08b43ee9e3328197699 -Author: Gertjan van Wingerde -Date: Wed Jul 6 22:58:55 2011 +0200 - - rt2x00: Add device ID for RT539F device. - - Reported-by: Wim Vander Schelden - Signed-off-by: Gertjan van Wingerde - Signed-off-by: Ivo van Doorn - Signed-off-by: John W. Linville - -diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c -index 5513edf..fd99449 100644 ---- a/drivers/net/wireless/rt2x00/rt2800pci.c -+++ b/drivers/net/wireless/rt2x00/rt2800pci.c -@@ -1160,6 +1160,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { - #endif - #ifdef CONFIG_RT2800PCI_RT53XX - { PCI_DEVICE(0x1814, 0x5390) }, -+ { PCI_DEVICE(0x1814, 0x539f) }, - #endif - { 0, } - }; From 2a94216ed5b3b8e1c8843adc1ea5577f3dd3b5f7 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Aug 2011 19:36:09 -0400 Subject: [PATCH 113/397] upload --- sources | 1 + 1 file changed, 1 insertion(+) diff --git a/sources b/sources index ab481e125..cd8d69080 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 1aab7a741abe08d42e8eccf20de61e05 linux-2.6.39.tar.bz2 df5790b51f218fc5e5463162b26afbfc patch-3.0.bz2 +a8d352fb8ed2da9b67f5032200f41ad9 patch-3.0.1-rc1.bz2 From 320507088097cfdefc2952bfd206b9cb9a10fdac Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 3 Aug 2011 21:51:30 -0400 Subject: [PATCH 114/397] iwlagn: check for !priv->txq in iwlagn_wait_tx_queue_empty (rhbz 728044) --- ...r-priv--txq-in-iwlagn_wait_tx_queue_empty.patch | 14 ++++++++++++++ kernel.spec | 7 +++++++ 2 files changed, 21 insertions(+) create mode 100644 iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch diff --git a/iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch b/iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch new file mode 100644 index 000000000..855a30da7 --- /dev/null +++ b/iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch @@ -0,0 +1,14 @@ +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +index f803fb6..d6ae444 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +@@ -1487,6 +1487,9 @@ int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv) + unsigned long now = jiffies; + int ret = 0; + ++ if (!priv->txq) ++ return 0; ++ + /* waiting for all the tx frames complete might take a while */ + for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { + if (cnt == priv->cmd_queue) diff --git a/kernel.spec b/kernel.spec index 6d4019aa9..b2fd2acb5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -655,6 +655,8 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13001: epoll-fix-spurious-lockdep-warnings.patch Patch13002: hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch +Patch13010: iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch + Patch20000: utrace.patch %endif @@ -1207,6 +1209,8 @@ ApplyPatch epoll-fix-spurious-lockdep-warnings.patch ApplyPatch hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch +ApplyPatch iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch + ApplyPatch utrace.patch # END OF PATCH APPLICATIONS @@ -1821,6 +1825,9 @@ fi # and build. %changelog +* Wed Aug 03 2011 Dave Jones +- iwlagn: check for !priv->txq in iwlagn_wait_tx_queue_empty (rhbz 728044) + * Wed Aug 03 2011 Dave Jones - Apply patches from patch-3.0.1-rc1 From 85b3aab0f02676d835c8eb8badc1d0d006c1d424 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 4 Aug 2011 13:19:26 -0400 Subject: [PATCH 115/397] Drop neuter_intel_microcode_load.patch (rhbz 690930) --- kernel.spec | 7 +++---- neuter_intel_microcode_load.patch | 24 ------------------------ 2 files changed, 3 insertions(+), 28 deletions(-) delete mode 100644 neuter_intel_microcode_load.patch diff --git a/kernel.spec b/kernel.spec index b2fd2acb5..20bed7d41 100644 --- a/kernel.spec +++ b/kernel.spec @@ -641,8 +641,6 @@ Patch12010: add-appleir-usb-driver.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch12018: neuter_intel_microcode_load.patch - Patch12022: fix-cdc-ncm-dma-stack-vars.patch Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch @@ -1197,8 +1195,6 @@ ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch add-appleir-usb-driver.patch -ApplyPatch neuter_intel_microcode_load.patch - ApplyPatch fix-cdc-ncm-dma-stack-vars.patch ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch @@ -1825,6 +1821,9 @@ fi # and build. %changelog +* Thu Aug 04 2011 Dave Jones +- Drop neuter_intel_microcode_load.patch (rhbz 690930) + * Wed Aug 03 2011 Dave Jones - iwlagn: check for !priv->txq in iwlagn_wait_tx_queue_empty (rhbz 728044) diff --git a/neuter_intel_microcode_load.patch b/neuter_intel_microcode_load.patch deleted file mode 100644 index 2766e439d..000000000 --- a/neuter_intel_microcode_load.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c -index ebd193e..c57024a 100644 ---- a/arch/x86/kernel/microcode_intel.c -+++ b/arch/x86/kernel/microcode_intel.c -@@ -453,9 +453,18 @@ static void microcode_fini_cpu(int cpu) - uci->mc = NULL; - } - -+/* we don't ship the broken out files... -+ * instead, we'll just fail here, and load it with microcode_ctl -+ */ -+static enum ucode_state noop_request_microcode_fw(int cpu, -+ struct device *device) -+{ -+ return UCODE_NFOUND; -+} -+ - static struct microcode_ops microcode_intel_ops = { - .request_microcode_user = request_microcode_user, -- .request_microcode_fw = request_microcode_fw, -+ .request_microcode_fw = noop_request_microcode_fw, - .collect_cpu_info = collect_cpu_info, - .apply_microcode = apply_microcode, - .microcode_fini_cpu = microcode_fini_cpu, From a40673ffda4677ffa2bfe222ac27acb94d230dc9 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 5 Aug 2011 11:35:36 -0400 Subject: [PATCH 116/397] Final 3.0.1 diff. --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 20bed7d41..41908fa98 100644 --- a/kernel.spec +++ b/kernel.spec @@ -558,7 +558,7 @@ Source1000: config-local # Here should be only the patches up to the upstream canonical Linus tree. Patch00: patch-3.0.bz2 -Patch01: patch-3.0.1-rc1.bz2 +Patch01: patch-3.0.1.bz2 # we also need compile fixes for -vanilla @@ -1056,7 +1056,7 @@ done # Update vanilla to the latest upstream. (2.6.39 -> 3.0) ApplyPatch patch-3.0.bz2 -ApplyPatch patch-3.0.1-rc1.bz2 +ApplyPatch patch-3.0.1.bz2 ApplyPatch linux-2.6-makefile-after_link.patch @@ -1821,6 +1821,9 @@ fi # and build. %changelog +* Fri Aug 05 2011 Dave Jones +- Final 3.0.1 diff. + * Thu Aug 04 2011 Dave Jones - Drop neuter_intel_microcode_load.patch (rhbz 690930) diff --git a/sources b/sources index cd8d69080..97f423af5 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 1aab7a741abe08d42e8eccf20de61e05 linux-2.6.39.tar.bz2 df5790b51f218fc5e5463162b26afbfc patch-3.0.bz2 -a8d352fb8ed2da9b67f5032200f41ad9 patch-3.0.1-rc1.bz2 +ac49f7907f1fc85fbab92d0f1aa1552a patch-3.0.1.bz2 From e447dfbbddc5ca1aa8ae96198e20590a7ad2a996 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 5 Aug 2011 14:33:01 -0400 Subject: [PATCH 117/397] Revert f16-only change that made IPV6 built-in. --- config-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 0c1304053..0a6785bce 100644 --- a/config-generic +++ b/config-generic @@ -816,7 +816,7 @@ CONFIG_IP_VS_NQ=m CONFIG_IP_VS_FTP=m CONFIG_IP_VS_PE_SIP=m -CONFIG_IPV6=y +CONFIG_IPV6=m CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y diff --git a/kernel.spec b/kernel.spec index 41908fa98..09eb2e953 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1821,6 +1821,9 @@ fi # and build. %changelog +* Fri Aug 05 2011 Dave Jones +- Revert f16-only change that made IPV6 built-in. + * Fri Aug 05 2011 Dave Jones - Final 3.0.1 diff. From 13393fc3c2d1bbc2334640844553581f6e91e4ae Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sat, 6 Aug 2011 01:14:10 -0400 Subject: [PATCH 118/397] bump for build --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 09eb2e953..2eb3e5ac7 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 0 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1821,7 +1821,7 @@ fi # and build. %changelog -* Fri Aug 05 2011 Dave Jones +* Fri Aug 05 2011 Dave Jones 2.6.40.1-1 - Revert f16-only change that made IPV6 built-in. * Fri Aug 05 2011 Dave Jones From 8b853530614598b4a49d0033380e6df77b0d5cb5 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 7 Aug 2011 16:02:41 -0400 Subject: [PATCH 119/397] utrace fixes. --- kernel.spec | 3 + utrace.patch | 1169 +++++++++++++++++++++++++++++++------------------- 2 files changed, 741 insertions(+), 431 deletions(-) diff --git a/kernel.spec b/kernel.spec index 2eb3e5ac7..8bf5f0159 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1821,6 +1821,9 @@ fi # and build. %changelog +* Sun Aug 07 2011 Dave Jones +- Utrace fixes. + * Fri Aug 05 2011 Dave Jones 2.6.40.1-1 - Revert f16-only change that made IPV6 built-in. diff --git a/utrace.patch b/utrace.patch index 55d0b3c1b..f5515e3ed 100644 --- a/utrace.patch +++ b/utrace.patch @@ -1,41 +1,42 @@ -From davej Thu Jun 30 20:27:03 2011 +From davej Sun Aug 7 15:19:08 2011 Return-Path: oleg@redhat.com Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:03 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:00 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:08 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:17:59 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 10DAED812A; - Thu, 30 Jun 2011 20:23:00 -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 fiwBBweCuo8A; Thu, 30 Jun 2011 20:22:59 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E7CA2D810F; - Thu, 30 Jun 2011 20:22:59 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F09A8A5D58; + Sun, 7 Aug 2011 15:17:58 -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 6mY7uBb0+l7B; Sun, 7 Aug 2011 15:17:58 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D1DFE9C7FA; + Sun, 7 Aug 2011 15:17:58 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610MpCP015143; - Thu, 30 Jun 2011 20:22:52 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JHtc4027719; + Sun, 7 Aug 2011 15:17:56 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:20:59 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:20:57 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:19 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:17 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 01/19] utrace core -Message-ID: <20110701002057.GA25776@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 01/22] utrace core +Message-ID: <20110807191517.GA14365@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 148213 -Lines: 4119 +Content-Length: 148212 +Lines: 4118 From: Roland McGrath @@ -4156,8 +4157,7 @@ index 0000000..f332d65 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:04 2011 +From davej Sun Aug 7 15:19:09 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -4166,40 +4166,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:04 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:09 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:03 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:01 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2259ED812A; - Thu, 30 Jun 2011 20:23:03 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A1FB8D89A7; + Sun, 7 Aug 2011 15:18:01 -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 Ex9fFDzwy1Zb; Thu, 30 Jun 2011 20:23:03 -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 0EF28D810F; - Thu, 30 Jun 2011 20:23:03 -0400 (EDT) + with ESMTP id JtiDMxvrW-Di; Sun, 7 Aug 2011 15:18:01 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7F0E6D8988; + Sun, 7 Aug 2011 15:18:01 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610Mt6X021086; - Thu, 30 Jun 2011 20:22:56 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JHxlJ027726; + Sun, 7 Aug 2011 15:17:59 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:03 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:01 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:23 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:21 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 02/19] utrace: remove jobctl bits -Message-ID: <20110701002101.GA25779@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 02/22] utrace: remove jobctl bits +Message-ID: <20110807191521.GA14373@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 1890 -Lines: 56 +Content-Length: 1889 +Lines: 55 - change utrace_get_signal() to check GROUP_STOP_PENDING instead of signal->group_stop_count. With the recent changes group_stop_count @@ -4257,8 +4258,7 @@ index f332d65..6e7fafb 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:05 2011 +From davej Sun Aug 7 15:19:10 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -4267,40 +4267,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:05 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:10 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:06 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:04 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6B38AD812A; - Thu, 30 Jun 2011 20:23:06 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 473EDD89A7; + Sun, 7 Aug 2011 15:18:04 -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 f4153Z6E7KGl; Thu, 30 Jun 2011 20:23:06 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 55D4AD810F; - Thu, 30 Jun 2011 20:23:06 -0400 (EDT) + with ESMTP id uA3eVmUnKFQu; Sun, 7 Aug 2011 15:18:04 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 29079D8988; + Sun, 7 Aug 2011 15:18:04 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610Mwi2015168; - Thu, 30 Jun 2011 20:22:59 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JI1LH027738; + Sun, 7 Aug 2011 15:18:02 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:06 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:04 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:25 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:23 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 03/19] ptrace: take ->siglock around s/TRACED/RUNNING/ -Message-ID: <20110701002104.GA25787@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 03/22] ptrace: take ->siglock around s/TRACED/RUNNING/ +Message-ID: <20110807191523.GA14376@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 1624 -Lines: 56 +Content-Length: 1623 +Lines: 55 change ptrace_resume() and ptrace_stop() to take ->siglock around changing task->state from TRACED to RUNNING. @@ -4358,8 +4359,7 @@ index ff76786..2138cee 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:06 2011 +From davej Sun Aug 7 15:19:11 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -4368,40 +4368,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:06 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:09 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:11 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:06 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E1AB7D812A; - Thu, 30 Jun 2011 20:23:09 -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 QhOnA49nS3Vp; Thu, 30 Jun 2011 20:23:09 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C5E15D810F; - Thu, 30 Jun 2011 20:23:09 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D76B6A5D58; + Sun, 7 Aug 2011 15:18:06 -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 xyKeY-zzvTgR; Sun, 7 Aug 2011 15:18:06 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BB0E49C7FA; + Sun, 7 Aug 2011 15:18:06 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610N2Kd007635; - Thu, 30 Jun 2011 20:23:02 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JI4PF028668; + Sun, 7 Aug 2011 15:18:05 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:10 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:07 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:28 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:26 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 04/19] introduce wake_up_quiescent() -Message-ID: <20110701002107.GA25790@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 04/22] introduce wake_up_quiescent() +Message-ID: <20110807191526.GA14383@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 3104 -Lines: 93 +Content-Length: 3103 +Lines: 92 No functional changes. Add the new helper, wake_up_quiescent(task, state), which simply returns wake_up_state(task, state). Change all callers which @@ -4496,8 +4497,7 @@ index 6e7fafb..d7c547c 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:07 2011 +From davej Sun Aug 7 15:19:13 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -4506,40 +4506,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:07 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:13 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:13 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:09 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2CF811287F3; - Thu, 30 Jun 2011 20:23:13 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C8DCF1322A2; + Sun, 7 Aug 2011 15:18:09 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id dNPA3WxO-7pp; Thu, 30 Jun 2011 20:23:13 -0400 (EDT) + with ESMTP id ZQXZL5xrzV21; Sun, 7 Aug 2011 15:18:09 -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 zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 154D61287DD; - Thu, 30 Jun 2011 20:23:13 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B3D6D128FDA; + Sun, 7 Aug 2011 15:18:09 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610N5nY021107; - Thu, 30 Jun 2011 20:23:06 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JI7P5029847; + Sun, 7 Aug 2011 15:18:07 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:13 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:11 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:31 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:28 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 05/19] introduce ptrace_signal_wake_up() -Message-ID: <20110701002111.GA25797@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 05/22] introduce ptrace_signal_wake_up() +Message-ID: <20110807191528.GA14386@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO -Content-Length: 1975 -Lines: 68 +Content-Length: 1974 +Lines: 67 Add the new helper, ptrace_signal_wake_up(), change ptrace.c to use it instead of signal_wake_up(). @@ -4609,8 +4610,7 @@ index 26ae214..0b2aba5 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:08 2011 +From davej Sun Aug 7 15:19:14 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -4619,41 +4619,42 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:08 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:14 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:16 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:12 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6FB379C0CB; - Thu, 30 Jun 2011 20:23:16 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 72BBDA5D58; + Sun, 7 Aug 2011 15:18:12 -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 IYB64KKErOyI; Thu, 30 Jun 2011 20:23:16 -0400 (EDT) + with ESMTP id k8I1SMuU0ydh; Sun, 7 Aug 2011 15:18:12 -0400 (EDT) Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 597119C0C5; - Thu, 30 Jun 2011 20:23:16 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5DFAB9C7FA; + Sun, 7 Aug 2011 15:18:12 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610N8bE032569; - Thu, 30 Jun 2011 20:23:09 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIAjF028676; + Sun, 7 Aug 2011 15:18:10 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:16 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:14 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:34 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:31 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 06/19] wait_task_inactive: treat task->state and +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 06/22] wait_task_inactive: treat task->state and match_state as bitmasks -Message-ID: <20110701002114.GA25804@redhat.com> +Message-ID: <20110807191531.GA14393@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 1558 -Lines: 39 +Content-Length: 1557 +Lines: 38 Change wait_task_inactive() to check "state & match_state" instead of "state == match_state". This should not make any difference, but this @@ -4694,8 +4695,7 @@ index 3f2e502..ade7997 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:09 2011 +From davej Sun Aug 7 15:19:15 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -4704,40 +4704,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:09 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:19 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:15 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:15 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A6BD4D810F; - Thu, 30 Jun 2011 20:23:19 -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 2ovLSk6W1SGg; Thu, 30 Jun 2011 20:23:19 -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 zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8DBABD812A; - Thu, 30 Jun 2011 20:23:19 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1FD1B1322A2; + Sun, 7 Aug 2011 15:18:15 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id gfct30463vGS; Sun, 7 Aug 2011 15:18:15 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 01C04128FDA; + Sun, 7 Aug 2011 15:18:15 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610NCUq026299; - Thu, 30 Jun 2011 20:23:12 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JICKL027777; + Sun, 7 Aug 2011 15:18:13 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:19 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:17 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:36 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:34 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 07/19] introduce TASK_UTRACED state -Message-ID: <20110701002117.GA25807@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 07/22] introduce TASK_UTRACED state +Message-ID: <20110807191534.GA14396@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 2913 -Lines: 84 +Content-Length: 2912 +Lines: 83 Introduce TASK_UTRACED state, will be used by utrace instead of TASK_TRACED. @@ -4823,8 +4824,7 @@ index b87de83..7a0008c 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:10 2011 +From davej Sun Aug 7 15:19:17 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -4833,40 +4833,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:10 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:23 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:17 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:17 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1A66AD812A; - Thu, 30 Jun 2011 20:23:23 -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 fctUcQ+-lYpk; Thu, 30 Jun 2011 20:23:23 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F2D35D810F; - Thu, 30 Jun 2011 20:23:22 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B634FA5D5A; + Sun, 7 Aug 2011 15:18:17 -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 3vEyYZtZ8hD5; Sun, 7 Aug 2011 15:18:17 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9921A9C7FA; + Sun, 7 Aug 2011 15:18:17 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NF1u015200; - Thu, 30 Jun 2011 20:23:15 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIFH8028686; + Sun, 7 Aug 2011 15:18:16 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:23 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:20 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:39 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:37 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 08/19] utrace: use TASK_UTRACED instead of TASK_TRACED -Message-ID: <20110701002120.GA25814@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 08/22] utrace: use TASK_UTRACED instead of TASK_TRACED +Message-ID: <20110807191537.GA14403@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 4316 -Lines: 130 +Content-Length: 4315 +Lines: 129 Change utrace.c to use TASK_UTRACED instead of TASK_TRACED. @@ -4998,8 +4999,7 @@ index d7c547c..be98607 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:12 2011 +From davej Sun Aug 7 15:19:19 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5008,41 +5008,42 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:12 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:26 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:19 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:24 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 289969C0C5; - Thu, 30 Jun 2011 20:23:26 -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 q99JSaVz2X1O; Thu, 30 Jun 2011 20:23:26 -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 zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 143F89C0C3; - Thu, 30 Jun 2011 20:23:26 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 53AC0D89A9; + Sun, 7 Aug 2011 15:18:20 -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 CGhyA84rXAKN; Sun, 7 Aug 2011 15:18:20 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 36B2CD8988; + Sun, 7 Aug 2011 15:18:20 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610NI9T021133; - Thu, 30 Jun 2011 20:23:19 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIIFB028696; + Sun, 7 Aug 2011 15:18:18 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:26 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:24 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:41 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:39 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 09/19] tracehooks: kill tracehook_finish_jctl(), add +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 09/22] tracehooks: kill tracehook_finish_jctl(), add tracehook_finish_stop() -Message-ID: <20110701002124.GA25817@redhat.com> +Message-ID: <20110807191539.GA14406@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 2782 -Lines: 86 +Content-Length: 2781 +Lines: 85 tracehook_finish_jctl() is needed to avoid the races with SIGKILL which wakes up UTRACED task, and thus it should be called every time @@ -5130,8 +5131,7 @@ index be98607..daa96b9 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:13 2011 +From davej Sun Aug 7 15:19:18 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5140,40 +5140,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:13 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:29 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:18 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:22 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A748FD813B; - Thu, 30 Jun 2011 20:23:29 -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 EwbxGxAU7ASi; Thu, 30 Jun 2011 20:23:29 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 72761D810F; - Thu, 30 Jun 2011 20:23:29 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id DD6839C7FA; + Sun, 7 Aug 2011 15:18:22 -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 hZs6VyadcD7K; Sun, 7 Aug 2011 15:18:22 -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 C7B129C7DE; + Sun, 7 Aug 2011 15:18:22 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NMAW015213; - Thu, 30 Jun 2011 20:23:22 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIKMe020605; + Sun, 7 Aug 2011 15:18:21 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:29 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:27 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:44 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:42 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 10/19] teach wake_up_quiescent() to do "selective" wake_up -Message-ID: <20110701002127.GA25824@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 10/22] teach wake_up_quiescent() to do "selective" wake_up +Message-ID: <20110807191542.GA14409@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO -Content-Length: 1335 -Lines: 46 +Content-Length: 1334 +Lines: 45 Both utrace and ptrace can want the same thread to be quiescent, in this case its state is TASK_TRACED | TASK_UTRACED. And this also means that @@ -5221,8 +5222,7 @@ index a7979ad..57552e6 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:14 2011 +From davej Sun Aug 7 15:19:20 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5231,41 +5231,42 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:14 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:32 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:20 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:25 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C94CF9C0C5; - Thu, 30 Jun 2011 20:23:32 -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 9R-z4gQXQITf; Thu, 30 Jun 2011 20:23:32 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7C2991322AA; + Sun, 7 Aug 2011 15:18:25 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id rHOxOwY4bOdr; Sun, 7 Aug 2011 15:18:25 -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 zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B55759C0C3; - Thu, 30 Jun 2011 20:23:32 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 67ABD128FDA; + Sun, 7 Aug 2011 15:18:25 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610NPe5021144; - Thu, 30 Jun 2011 20:23:25 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JINVP029911; + Sun, 7 Aug 2011 15:18:23 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:33 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:30 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:47 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:45 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 11/19] ptrace_stop: do not assume the task is running after +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 11/22] ptrace_stop: do not assume the task is running after wake_up_quiescent() -Message-ID: <20110701002130.GA25827@redhat.com> +Message-ID: <20110807191545.GA14416@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO -Content-Length: 962 -Lines: 31 +Content-Length: 961 +Lines: 30 If ptrace_stop() sets TASK_TRACED and then detects we should not stop, it can race with utrace_do_stop() which can see TASK_TRACED and add @@ -5298,8 +5299,7 @@ index 57552e6..89e691d 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:17 2011 +From davej Sun Aug 7 15:19:21 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5308,41 +5308,42 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:17 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:21 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:36 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:28 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4390F1287F3; - Thu, 30 Jun 2011 20:23:36 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1B4B91322AE; + Sun, 7 Aug 2011 15:18:28 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id v5mzxCjpefBI; Thu, 30 Jun 2011 20:23:36 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 283B21287DD; - Thu, 30 Jun 2011 20:23:36 -0400 (EDT) + with ESMTP id q5tv0cJeZqLD; Sun, 7 Aug 2011 15:18:28 -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 zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 071461322A9; + Sun, 7 Aug 2011 15:18:28 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NSc9032626; - Thu, 30 Jun 2011 20:23:29 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIPFB020635; + Sun, 7 Aug 2011 15:18:26 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:36 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:34 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:49 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:47 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 12/19] get_signal_to_deliver: restructure utrace/ptrace +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 12/22] get_signal_to_deliver: restructure utrace/ptrace signal reporting -Message-ID: <20110701002134.GA25834@redhat.com> +Message-ID: <20110807191547.GA14419@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO -Content-Length: 2012 -Lines: 73 +Content-Length: 2011 +Lines: 72 get_signal_to_deliver() assumes that either tracehook_get_signal() does nothing (without CONFIG_UTRACE), or it also reports the signal to ptrace @@ -5417,8 +5418,7 @@ index 89e691d..d0e0c67 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:18 2011 +From davej Sun Aug 7 15:19:22 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5427,40 +5427,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:18 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:39 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:22 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:30 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 74BDFD813B; - Thu, 30 Jun 2011 20:23:39 -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 tAGkG+GCPdeN; Thu, 30 Jun 2011 20:23:39 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5B728D812A; - Thu, 30 Jun 2011 20:23:39 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BFD8F1322A2; + Sun, 7 Aug 2011 15:18:30 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id JczS8HsLYY6X; Sun, 7 Aug 2011 15:18:30 -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 zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A8F91128FDA; + Sun, 7 Aug 2011 15:18:30 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NWY1032629; - Thu, 30 Jun 2011 20:23:32 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIS1m029940; + Sun, 7 Aug 2011 15:18:29 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:39 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:37 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:52 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:50 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 13/19] introduce ptrace_set_syscall_trace() -Message-ID: <20110701002137.GA25837@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 13/22] introduce ptrace_set_syscall_trace() +Message-ID: <20110807191550.GA14426@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO -Content-Length: 1581 -Lines: 52 +Content-Length: 1580 +Lines: 51 No functional changes. Add the new helper, ptrace_set_syscall_trace(), which should be used to set/clear TIF_SYSCALL_TRACE in ptrace code. @@ -5514,8 +5515,7 @@ index 0b2aba5..b6fd922 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:20 2011 +From davej Sun Aug 7 15:19:23 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5524,40 +5524,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:20 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:23 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:42 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:33 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id CFC3F9C0C5; - Thu, 30 Jun 2011 20:23:42 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 585699C7DE; + Sun, 7 Aug 2011 15:18:33 -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 vS4KlM5ek+bt; Thu, 30 Jun 2011 20:23:42 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B28CA9C0C3; - Thu, 30 Jun 2011 20:23:42 -0400 (EDT) + with ESMTP id Zp+5oAzhYq2W; Sun, 7 Aug 2011 15:18:33 -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 44532909E4; + Sun, 7 Aug 2011 15:18:33 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NZvo015255; - Thu, 30 Jun 2011 20:23:35 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIV6n020657; + Sun, 7 Aug 2011 15:18:31 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:43 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:40 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:54 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:52 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 14/19] introduce PT_SYSCALL_TRACE flag -Message-ID: <20110701002140.GA25844@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 14/22] introduce PT_SYSCALL_TRACE flag +Message-ID: <20110807191552.GA14429@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO -Content-Length: 2236 -Lines: 73 +Content-Length: 2235 +Lines: 72 Currently tracehooks assume that if the ptraced task has TIF_SYSCALL_TRACE set, the tracee should report the syscall. @@ -5632,8 +5633,7 @@ index b6fd922..0825a01 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:21 2011 +From davej Sun Aug 7 15:19:24 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5642,41 +5642,42 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:21 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:24 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:46 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:35 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 35A70D812A; - Thu, 30 Jun 2011 20:23:46 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F0377D89A9; + Sun, 7 Aug 2011 15:18:35 -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 L06hkGLA8FQs; Thu, 30 Jun 2011 20:23:46 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 21C2BD810F; - Thu, 30 Jun 2011 20:23:46 -0400 (EDT) + with ESMTP id cBLqfABIHZ6h; Sun, 7 Aug 2011 15:18:35 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id DC799D8988; + Sun, 7 Aug 2011 15:18:35 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610Nc7k007721; - Thu, 30 Jun 2011 20:23:39 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIXU3007727; + Sun, 7 Aug 2011 15:18:34 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:46 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:44 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:57 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:55 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 15/19] utrace: don't clear TIF_SYSCALL_TRACE if it is +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 15/22] utrace: don't clear TIF_SYSCALL_TRACE if it is needed by ptrace -Message-ID: <20110701002144.GA25847@redhat.com> +Message-ID: <20110807191555.GA14436@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO -Content-Length: 797 -Lines: 24 +Content-Length: 796 +Lines: 23 TIF_SYSCALL_TRACE should be cleared only if both ptrace and utrace do not want it, change utrace_reset() to check PT_SYSCALL_TRACE before @@ -5702,8 +5703,7 @@ index daa96b9..a824ac3 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:22 2011 +From davej Sun Aug 7 15:19:25 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5712,40 +5712,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:22 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:25 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:49 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:38 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 72E0C9C0C3; - Thu, 30 Jun 2011 20:23:49 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A6B3C9C7DE; + Sun, 7 Aug 2011 15:18:38 -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 o3ezwgloxuCS; Thu, 30 Jun 2011 20:23: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 5DD6A9C0C5; - Thu, 30 Jun 2011 20:23:49 -0400 (EDT) + with ESMTP id ln+MaW5alQl7; Sun, 7 Aug 2011 15:18:38 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8A6D2909E4; + Sun, 7 Aug 2011 15:18:38 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610NglX026379; - Thu, 30 Jun 2011 20:23:42 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIaYf007737; + Sun, 7 Aug 2011 15:18:36 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:49 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:47 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:16:00 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:58 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 16/19] introduce task_utrace_lock/task_utrace_unlock -Message-ID: <20110701002147.GA25854@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 16/22] introduce task_utrace_lock/task_utrace_unlock +Message-ID: <20110807191558.GA14440@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO -Content-Length: 2190 -Lines: 81 +Content-Length: 2189 +Lines: 80 - Add task_utrace_lock(task). It simply takes task->utrace->lock if this task was ever utraced. Otherwise it takes task_lock(), this @@ -5828,8 +5829,7 @@ index a824ac3..508c13c 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:24 2011 +From davej Sun Aug 7 15:19:27 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5838,41 +5838,42 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:24 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:52 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:27 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:41 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id DB8D8D812A; - Thu, 30 Jun 2011 20:23:52 -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 74TDLZXBCl6s; Thu, 30 Jun 2011 20:23:52 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C6776D810F; - Thu, 30 Jun 2011 20:23:52 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 41B111322A2; + Sun, 7 Aug 2011 15:18:41 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id ypKNrfgt9t+i; Sun, 7 Aug 2011 15:18:41 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2D805128FDA; + Sun, 7 Aug 2011 15:18:41 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NjAl015271; - Thu, 30 Jun 2011 20:23:45 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIdnm028810; + Sun, 7 Aug 2011 15:18:39 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:53 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:50 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:16:02 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:16:00 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 17/19] teach ptrace_set_syscall_trace() to play well with +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 17/22] teach ptrace_set_syscall_trace() to play well with utrace -Message-ID: <20110701002150.GA25861@redhat.com> +Message-ID: <20110807191600.GA14443@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 1513 -Lines: 49 +Content-Length: 1512 +Lines: 48 1. ptrace_set_syscall_trace(true)->set_tsk_thread_flag(TIF_SYSCALL_TRACE) can race with utrace_control()->utrace_reset() path which can miss @@ -5923,8 +5924,7 @@ index 0825a01..209ea2d 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:24 2011 +From davej Sun Aug 7 15:19:27 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5933,40 +5933,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:24 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:56 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:27 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:43 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6CD231287F3; - Thu, 30 Jun 2011 20:23:56 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id XX9YNcTcP1Ny; Thu, 30 Jun 2011 20:23:56 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 504BF1287DD; - Thu, 30 Jun 2011 20:23:56 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E37B59C7DE; + Sun, 7 Aug 2011 15:18:43 -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 NRVgSzxr7avy; Sun, 7 Aug 2011 15:18:43 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C6D6E909E4; + Sun, 7 Aug 2011 15:18:43 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NmjB032686; - Thu, 30 Jun 2011 20:23:49 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIfAM007754; + Sun, 7 Aug 2011 15:18:42 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:56 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:54 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:16:05 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:16:03 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 18/19] introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK -Message-ID: <20110701002154.GA25864@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 18/22] introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK +Message-ID: <20110807191603.GA14450@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO -Content-Length: 3725 -Lines: 108 +Content-Length: 3724 +Lines: 107 Add the new internal ptrace flags, PT_SINGLE_STEP and PT_SINGLE_BLOCK. @@ -6076,8 +6077,7 @@ index 209ea2d..44908d0 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:26 2011 +From davej Sun Aug 7 15:19:29 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -6086,58 +6086,92 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:26 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:59 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:29 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:46 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8FF6B9C0C5; - Thu, 30 Jun 2011 20:23:59 -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 pNFtYrppMjXf; Thu, 30 Jun 2011 20:23:59 -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 7C2B89C0C3; - Thu, 30 Jun 2011 20:23:59 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 810E31322A2; + Sun, 7 Aug 2011 15:18:46 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id ptiIThWTq2a6; Sun, 7 Aug 2011 15:18:46 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6B665128FDA; + Sun, 7 Aug 2011 15:18:46 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610Nqpd026408; - Thu, 30 Jun 2011 20:23:52 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIiI8007757; + Sun, 7 Aug 2011 15:18:44 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:59 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:57 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:16:08 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:16:06 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 19/19] utrace: consult PT_SINGLE_STEP/PT_SINGLE_BLOCK - before user_disable_single_step() -Message-ID: <20110701002157.GA25871@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 19/22] utrace: finish_resume_report: don't do + user_xxx_step() if ptrace_wants_step() +Message-ID: <20110807191606.GA14453@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO -Content-Length: 1150 -Lines: 41 +Content-Length: 2740 +Lines: 83 -- do not do user_enable_block_step() if PT_SINGLE_STEP is set, in this - case ptrace has already called user_enable_single_step() +finish_resume_report() should not enable/disable the stepping if +ptrace_wants_step() == T. If ptrace wants block_step while utrace +wants single_step we could "promote" the stepping, but I do not +think this really makes sense. -- do not do user_disable_single_step() if PT_*_STEP is set, ptrace needs - the stepping - -Unless the tracee is killed this can't race with ptrace, this is called -by the tracee itself. +Unless the tracee is killed this can't race with ptrace, this is +called by the tracee itself. If it is killed we do not care. Signed-off-by: Oleg Nesterov --- - kernel/utrace.c | 6 ++++-- - 1 files changed, 4 insertions(+), 2 deletions(-) + include/linux/tracehook.h | 8 ++++---- + kernel/utrace.c | 9 ++++++--- + 2 files changed, 10 insertions(+), 7 deletions(-) +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index 06edb52..5612d2d 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -121,8 +121,8 @@ static inline __must_check int tracehook_report_syscall_entry( + return 0; + } + +-#define ptrace_wants_step() \ +- (current->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK)) ++#define ptrace_wants_step(task) \ ++ ((task)->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK)) + + /** + * tracehook_report_syscall_exit - task has just finished a system call +@@ -146,7 +146,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) + if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) + utrace_report_syscall_exit(regs); + +- if (step && ptrace_wants_step()) { ++ if (step && ptrace_wants_step(current)) { + siginfo_t info; + user_single_step_siginfo(current, regs, &info); + force_sig_info(SIGTRAP, &info, current); +@@ -439,7 +439,7 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, + { + if (task_utrace_flags(current)) + utrace_signal_handler(current, stepping); +- if (stepping && ptrace_wants_step()) ++ if (stepping && ptrace_wants_step(current)) + ptrace_notify(SIGTRAP); + } + diff --git a/kernel/utrace.c b/kernel/utrace.c -index 508c13c..d6607cb 100644 +index 508c13c..fbabb81 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -1828,7 +1828,8 @@ static void finish_resume_report(struct task_struct *task, @@ -6145,17 +6179,27 @@ index 508c13c..d6607cb 100644 case UTRACE_BLOCKSTEP: if (likely(arch_has_block_step())) { - user_enable_block_step(task); -+ if (!(current->ptrace & PT_SINGLE_STEP)) ++ if (!ptrace_wants_step(task)) + user_enable_block_step(task); break; } -@@ -1856,7 +1857,8 @@ static void finish_resume_report(struct task_struct *task, +@@ -1841,7 +1842,8 @@ static void finish_resume_report(struct task_struct *task, + + case UTRACE_SINGLESTEP: + if (likely(arch_has_single_step())) { +- user_enable_single_step(task); ++ if (!ptrace_wants_step(task)) ++ user_enable_single_step(task); + } else { + /* + * This means some callback is to blame for failing +@@ -1856,7 +1858,8 @@ static void finish_resume_report(struct task_struct *task, case UTRACE_REPORT: case UTRACE_RESUME: default: - user_disable_single_step(task); -+ if (!(current->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK))) ++ if (!ptrace_wants_step(task)) + user_disable_single_step(task); break; } @@ -6163,4 +6207,267 @@ index 508c13c..d6607cb 100644 -- 1.5.5.1 +From davej Sun Aug 7 15:19:30 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Sun, 07 Aug 2011 15:19:30 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:49 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1C4A79C7DE; + Sun, 7 Aug 2011 15:18: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 GxHOzMqYQY8N; Sun, 7 Aug 2011 15:18:49 -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 zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 066D2909E4; + Sun, 7 Aug 2011 15:18:49 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIkkD030034; + Sun, 7 Aug 2011 15:18:47 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Sun, 7 Aug 2011 21:16:10 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:16:08 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 20/22] ptrace: shift user_*_step() from ptrace_resume() to + ptrace_stop() +Message-ID: <20110807191608.GA14460@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +Status: RO +Content-Length: 2384 +Lines: 70 + +1. ptrace_resume() plays with the stopped task which can be also + task_is_utraced(). In this case user_enable_xxx_step() can race + with utrace_reset()->user_disable_single_step(). + + We could change utrace_reset() to check ptrace_wants_step() and + add the task_utrace_lock + unlock barrier after ptrace_resume() + sets PT_SINGLE_STEP. + + But it is better to reassign enable/desable from the tracer to + the tracee, it can check its PT_SINGLE_ bits after wakeup. This + also makes sense because enable_step(task) can be faster if + task == current. + +2. ptrace can do user_disable_single_step() while utrace needs the + stepping. + + Set TIF_NOTIFY_RESUME after user_disable_single_step() to ensure + the tracee can't return to the user-space without utrace_resume(). + Any correct engine which wants the stepping should reassert it. + +Signed-off-by: Oleg Nesterov +--- + kernel/ptrace.c | 4 ---- + kernel/signal.c | 12 ++++++++++++ + 2 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index 44908d0..d37b30d 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -580,14 +580,10 @@ static int ptrace_resume(struct task_struct *child, long request, + if (unlikely(!arch_has_block_step())) + return -EIO; + child->ptrace |= PT_SINGLE_BLOCK; +- user_enable_block_step(child); + } else if (is_singlestep(request) || is_sysemu_singlestep(request)) { + if (unlikely(!arch_has_single_step())) + return -EIO; + child->ptrace |= PT_SINGLE_STEP; +- user_enable_single_step(child); +- } else { +- user_disable_single_step(child); + } + + child->exit_code = data; +diff --git a/kernel/signal.c b/kernel/signal.c +index d0e0c67..bc40bd7 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -1840,6 +1840,18 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) + } + + tracehook_finish_stop(); ++ ++ if (current->ptrace & PT_SINGLE_BLOCK) ++ user_enable_block_step(current); ++ else if (current->ptrace & PT_SINGLE_STEP) ++ user_enable_single_step(current); ++ else { ++ user_disable_single_step(current); ++ /* if utrace needs the stepping it should reassert */ ++ if (task_utrace_flags(current)) ++ set_thread_flag(TIF_NOTIFY_RESUME); ++ } ++ + /* + * While in TASK_TRACED, we were considered "frozen enough". + * Now that we woke up, it's crucial if we're supposed to be +-- +1.5.5.1 + +From davej Sun Aug 7 15:19:31 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Sun, 07 Aug 2011 15:19:31 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:51 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id AD8D0D89A9; + Sun, 7 Aug 2011 15:18:51 -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 LHAT6DyOymTI; Sun, 7 Aug 2011 15:18:51 -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 99798D8988; + Sun, 7 Aug 2011 15:18:51 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIn3U030041; + Sun, 7 Aug 2011 15:18:50 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Sun, 7 Aug 2011 21:16:13 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:16:11 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 21/22] ptrace_disable: no need to disable stepping +Message-ID: <20110807191611.GA14463@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +Status: RO +Content-Length: 944 +Lines: 28 + +ptrace_disable() is called when the tracee is quiescent and we +are going to untrace. This means we are going to clear ->ptrace +and wake up the tracee. Now that ptrace_stop() checks PT_ bits +and does user_disable_single_step() we can remove this code from +ptrace_disable(), it is unneeded and not utrace-friendly. + +TODO: change !x86 code. + +Signed-off-by: Oleg Nesterov +--- + arch/x86/kernel/ptrace.c | 2 -- + 1 files changed, 0 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c +index 7ab475f..f1cdc7d 100644 +--- a/arch/x86/kernel/ptrace.c ++++ b/arch/x86/kernel/ptrace.c +@@ -807,8 +807,6 @@ static int ioperm_get(struct task_struct *target, + */ + void ptrace_disable(struct task_struct *child) + { +- child->ptrace &= ~(PT_SINGLE_STEP | PT_SINGLE_BLOCK); +- user_disable_single_step(child); + #ifdef TIF_SYSCALL_EMU + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); + #endif +-- +1.5.5.1 + +From davej Sun Aug 7 15:19:32 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Sun, 07 Aug 2011 15:19:32 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:54 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 57405D89A9; + Sun, 7 Aug 2011 15:18:54 -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 XgEdPuPz9LNX; Sun, 7 Aug 2011 15:18:54 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 42E6BD8988; + Sun, 7 Aug 2011 15:18:54 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIqEO027919; + Sun, 7 Aug 2011 15:18:52 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Sun, 7 Aug 2011 21:16:15 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:16:13 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 22/22] ptrace_report_syscall: check TIF_SYSCALL_EMU +Message-ID: <20110807191613.GA14470@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +Status: RO +Content-Length: 862 +Lines: 27 + +4d16a64 "introduce PT_SYSCALL_TRACE flag" breaks PTRACE_SYSEMU +which doesn't set PT_SYSCALL_TRACE. + +Change ptrace_report_syscall() to check TIF_SYSCALL_EMU as well. +This can't conflict with utrace, this flag can only be set by +ptrace. + +Signed-off-by: Oleg Nesterov +--- + include/linux/tracehook.h | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index 5612d2d..ac833de 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -76,7 +76,7 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) + { + int ptrace = task_ptrace(current); + +- if (!(ptrace & PT_SYSCALL_TRACE)) ++ if (!(ptrace & PT_SYSCALL_TRACE) && !test_thread_flag(TIF_SYSCALL_EMU)) + return; + + ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); +-- +1.5.5.1 From a75a12cf597fb2edb69dc5ded1ae2fbed09e8357 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 7 Aug 2011 16:03:28 -0400 Subject: [PATCH 120/397] ref the utrace bz --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 8bf5f0159..b0e948304 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1822,7 +1822,7 @@ fi %changelog * Sun Aug 07 2011 Dave Jones -- Utrace fixes. +- Utrace fixes. (rhbz 728379) * Fri Aug 05 2011 Dave Jones 2.6.40.1-1 - Revert f16-only change that made IPV6 built-in. From d2714557b2b6255de092f55dadc4bbe1e9784b7e Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 9 Aug 2011 10:11:03 -0400 Subject: [PATCH 121/397] James' suggested fix for 728872 --- block-stray-block-put-after-teardown.patch | 11 +++++++++++ kernel.spec | 9 ++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 block-stray-block-put-after-teardown.patch diff --git a/block-stray-block-put-after-teardown.patch b/block-stray-block-put-after-teardown.patch new file mode 100644 index 000000000..f4bf9c40c --- /dev/null +++ b/block-stray-block-put-after-teardown.patch @@ -0,0 +1,11 @@ +--- linux-2.6.39.noarch/block/elevator.c~ 2011-08-09 10:07:41.532774872 -0400 ++++ linux-2.6.39.noarch/block/elevator.c 2011-08-09 10:07:56.131724173 -0400 +@@ -815,7 +815,7 @@ void elv_completed_request(struct reques + */ + if (blk_account_rq(rq)) { + q->in_flight[rq_is_sync(rq)]--; +- if ((rq->cmd_flags & REQ_SORTED) && ++ if ((rq->cmd_flags & REQ_SORTED) && e->ops && + e->ops->elevator_completed_req_fn) + e->ops->elevator_completed_req_fn(q, rq); + } diff --git a/kernel.spec b/kernel.spec index b0e948304..bf5ea6f0f 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 @@ -623,6 +623,8 @@ Patch1825: drm-intel-make-lvds-work.patch Patch1900: linux-2.6-intel-iommu-igfx.patch +Patch2000: block-stray-block-put-after-teardown.patch + # Quiet boot fixes # silence the ACPI blacklist code Patch2802: linux-2.6-silence-acpi-blacklist.patch @@ -1181,6 +1183,8 @@ ApplyOptionalPatch drm-intel-next.patch ApplyPatch drm-intel-make-lvds-work.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch +ApplyPatch block-stray-block-put-after-teardown.patch + # silence the ACPI blacklist code ApplyPatch linux-2.6-silence-acpi-blacklist.patch @@ -1821,6 +1825,9 @@ fi # and build. %changelog +* Tue Aug 09 2011 Dave Jones 2.6.40.1-2 +- Fix stray block put after queue teardown (rhbz 728872) + * Sun Aug 07 2011 Dave Jones - Utrace fixes. (rhbz 728379) From ad04a02c6934b8b666cc26f4396c8c7a3beb4f0f Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 9 Aug 2011 13:27:57 -0400 Subject: [PATCH 122/397] Enable CONFIG_SAMSUNG_LAPTOP (rhbz 729363) --- config-x86-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-x86-generic b/config-x86-generic index 79a63a880..f12458388 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -517,7 +517,7 @@ CONFIG_X86_DECODER_SELFTEST=y CONFIG_ACPI_CMPC=m CONFIG_MSI_WMI=m CONFIG_TOSHIBA_BT_RFKILL=m -# CONFIG_SAMSUNG_LAPTOP is not set +CONFIG_SAMSUNG_LAPTOP=m CONFIG_VGA_SWITCHEROO=y CONFIG_LPC_SCH=m diff --git a/kernel.spec b/kernel.spec index bf5ea6f0f..f8a8415fb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1825,6 +1825,9 @@ fi # and build. %changelog +* Tue Aug 09 2011 Dave Jones +- Enable CONFIG_SAMSUNG_LAPTOP (rhbz 729363) + * Tue Aug 09 2011 Dave Jones 2.6.40.1-2 - Fix stray block put after queue teardown (rhbz 728872) From a9f639a8c2070c9f964a8b8a868f9e73e0d6c14f Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 9 Aug 2011 14:09:59 -0400 Subject: [PATCH 123/397] ptrace_report_syscall: check if TIF_SYSCALL_EMU is defined --- kernel.spec | 3 ++ utrace.patch | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/kernel.spec b/kernel.spec index f8a8415fb..13eed3c06 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1825,6 +1825,9 @@ fi # and build. %changelog +* Tue Aug 09 2011 Dave Jones +- ptrace_report_syscall: check if TIF_SYSCALL_EMU is defined + * Tue Aug 09 2011 Dave Jones - Enable CONFIG_SAMSUNG_LAPTOP (rhbz 729363) diff --git a/utrace.patch b/utrace.patch index f5515e3ed..f70d0b1fb 100644 --- a/utrace.patch +++ b/utrace.patch @@ -6471,3 +6471,82 @@ index 5612d2d..ac833de 100644 -- 1.5.5.1 +From davej Tue Aug 9 13:34:35 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Tue, 09 Aug 2011 13:34:35 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Tue, 9 Aug 2011 13:33:16 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 16B6E9EBAD; + Tue, 9 Aug 2011 13:33:16 -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 T2mXXk1FjIIy; Tue, 9 Aug 2011 13:33:16 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 025259EBA5; + Tue, 9 Aug 2011 13:33:16 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p79HXDVF004054; + Tue, 9 Aug 2011 13:33:13 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Tue, 9 Aug 2011 19:30:35 +0200 (CEST) +Date: Tue, 9 Aug 2011 19:30:33 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, Tony Breeds +Subject: [PATCH utrace-3.0 23/22] ptrace_report_syscall: check if + TIF_SYSCALL_EMU is defined +Message-ID: <20110809173033.GA26443@redhat.com> +References: <20110701002053.GA25767@redhat.com> <20110807191434.GA13184@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Status: RO +Content-Length: 844 +Lines: 31 + +From: Tony Breeds + +TIF_SYSCALL_EMU is x86 only, add ifdef into ptrace_report_syscall(). + +Signed-off-by: Oleg Nesterov +--- + include/linux/tracehook.h | 8 ++++++-- + 1 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index ac833de..d5baf86 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -76,8 +76,12 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) + { + int ptrace = task_ptrace(current); + +- if (!(ptrace & PT_SYSCALL_TRACE) && !test_thread_flag(TIF_SYSCALL_EMU)) +- return; ++ if (!(ptrace & PT_SYSCALL_TRACE)) { ++#ifdef TIF_SYSCALL_EMU ++ if (!test_thread_flag(TIF_SYSCALL_EMU)) ++#endif ++ return; ++ } + + ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); + +-- +1.5.5.1 + + From 1c75faa7b208fb4f05bafa8afc26e2949aa392f7 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 9 Aug 2011 16:45:14 -0400 Subject: [PATCH 124/397] enable for 64bit too --- config-x86_64-generic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-x86_64-generic b/config-x86_64-generic index d4a9a5f4e..306410cf7 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -421,7 +421,7 @@ CONFIG_FUNCTION_GRAPH_TRACER=y CONFIG_ACPI_CMPC=m CONFIG_MSI_WMI=m CONFIG_TOSHIBA_BT_RFKILL=m -# CONFIG_SAMSUNG_LAPTOP is not set +CONFIG_SAMSUNG_LAPTOP=m CONFIG_CS5535_MFGPT=m CONFIG_GEODE_WDT=m From 408089c858ed5068f49590891fa4da716feee643 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 1 Jul 2011 15:33:00 -0500 Subject: [PATCH 125/397] From: David Marlin Modify to split the ARM config files to work more like other archs. Rename: config-arm -> config-arm-generic Add: config-arm-omap-generic --- Makefile.config | 14 +- config-arm => config-arm-generic | 2 + config-arm-omap-generic | 1090 ++++++++++++++++++++++++++++++ kernel.spec | 9 +- 4 files changed, 1111 insertions(+), 4 deletions(-) rename config-arm => config-arm-generic (98%) create mode 100644 config-arm-omap-generic diff --git a/Makefile.config b/Makefile.config index 53812fa9b..35060e32f 100644 --- a/Makefile.config +++ b/Makefile.config @@ -8,7 +8,8 @@ CONFIGFILES = \ $(CFG)-i686.config $(CFG)-i686-debug.config \ $(CFG)-i686-PAE.config $(CFG)-i686-PAEdebug.config \ $(CFG)-x86_64.config $(CFG)-x86_64-debug.config \ - $(CFG)-s390x.config $(CFG)-arm.config \ + $(CFG)-s390x.config \ + $(CFG)-arm.config $(CFG)-armv7l-omap.config \ $(CFG)-ppc.config $(CFG)-ppc-smp.config \ $(CFG)-sparc64.config \ $(CFG)-ppc64.config $(CFG)-ppc64-debug.config \ @@ -32,6 +33,12 @@ temp-generic: config-generic temp-debug-generic: config-generic cat config-generic config-debug > temp-debug-generic +temp-arm-generic: config-arm-generic temp-generic + perl merge.pl $^ > $@ + +temp-armv7l-omap-generic: config-arm-omap-generic temp-arm-generic + perl merge.pl $^ > $@ + temp-x86-generic: config-x86-generic temp-generic perl merge.pl $^ > $@ @@ -92,7 +99,10 @@ kernel-$(VERSION)-ppc64-debug.config: config-powerpc64 temp-powerpc-debug-generi kernel-$(VERSION)-s390x.config: config-s390x temp-s390-generic perl merge.pl $^ s390 > $@ -kernel-$(VERSION)-arm.config: config-arm temp-generic +kernel-$(VERSION)-arm.config: /dev/null temp-arm-generic + perl merge.pl $^ arm > $@ + +kernel-$(VERSION)-armv7l-omap.config: /dev/null temp-armv7l-omap-generic perl merge.pl $^ arm > $@ kernel-$(VERSION)-ppc.config: /dev/null temp-powerpc32-generic diff --git a/config-arm b/config-arm-generic similarity index 98% rename from config-arm rename to config-arm-generic index dd6f90ad6..5b79fe23d 100644 --- a/config-arm +++ b/config-arm-generic @@ -146,4 +146,6 @@ CONFIG_USE_OF=y CONFIG_PROC_DEVICETREE=y CONFIG_MTD_PHYSMAP_OF=m CONFIG_SERIAL_OF_PLATFORM=m +# CONFIG_LEDS_GPIO_OF is not set CONFIG_MMC_SDHCI_OF=m + diff --git a/config-arm-omap-generic b/config-arm-omap-generic new file mode 100644 index 000000000..34b5389d6 --- /dev/null +++ b/config-arm-omap-generic @@ -0,0 +1,1090 @@ +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_LOCKBREAK=y +CONFIG_ARCH_HAS_CPUFREQ=y +# CONFIG_SPARSE_IRQ is not set +CONFIG_TREE_PREEMPT_RCU=y +CONFIG_PREEMPT_RCU=y +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_RCU_BOOST is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_BLK_CGROUP is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_STOP_MACHINE=y +# CONFIG_INLINE_SPIN_UNLOCK is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set +# CONFIG_INLINE_READ_UNLOCK is not set +# CONFIG_INLINE_READ_UNLOCK_IRQ is not set +# CONFIG_INLINE_WRITE_UNLOCK is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_OMAP=y +# CONFIG_GPIO_PCA953X is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# TI OMAP Common Features +CONFIG_ARCH_OMAP_OTG=y +# CONFIG_ARCH_OMAP1 is not set +CONFIG_ARCH_OMAP2PLUS=y + +# +# OMAP Feature Selections +# +CONFIG_OMAP_SMARTREFLEX=y +CONFIG_OMAP_SMARTREFLEX_CLASS3=y +CONFIG_OMAP_RESET_CLOCKS=y +CONFIG_OMAP_MUX=y +# CONFIG_OMAP_MUX_DEBUG is not set +CONFIG_OMAP_MUX_WARNINGS=y +CONFIG_OMAP_MCBSP=y +CONFIG_OMAP_MBOX_FWK=m +CONFIG_OMAP_MBOX_KFIFO_SIZE=256 +CONFIG_OMAP_32K_TIMER=y +# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set +CONFIG_OMAP_32K_TIMER_HZ=128 +CONFIG_OMAP_DM_TIMER=y +# CONFIG_OMAP_PM_NONE is not set +CONFIG_OMAP_PM_NOOP=y + +# +# TI OMAP2/3/4 Specific Features +# +CONFIG_ARCH_OMAP2PLUS_TYPICAL=y +# CONFIG_ARCH_OMAP2 is not set +CONFIG_ARCH_OMAP3=y +CONFIG_ARCH_OMAP4=y +CONFIG_SOC_OMAP3430=y +# CONFIG_SOC_OMAPTI816X is not set +CONFIG_OMAP_PACKAGE_CBB=y +CONFIG_OMAP_PACKAGE_CBL=y +CONFIG_OMAP_PACKAGE_CBS=y + +# +# OMAP Board Type +# +CONFIG_MACH_OMAP3_BEAGLE=y +CONFIG_MACH_DEVKIT8000=y +CONFIG_MACH_OMAP_LDP=y +CONFIG_MACH_OMAP3530_LV_SOM=y +CONFIG_MACH_OMAP3_TORPEDO=y +CONFIG_MACH_OVERO=y +CONFIG_MACH_OMAP3EVM=y +CONFIG_MACH_OMAP3517EVM=y +CONFIG_MACH_CRANEBOARD=y +CONFIG_MACH_OMAP3_PANDORA=y +CONFIG_MACH_OMAP3_TOUCHBOOK=y +CONFIG_MACH_OMAP_3430SDP=y +CONFIG_MACH_NOKIA_RM680=y +CONFIG_MACH_NOKIA_RX51=y +CONFIG_MACH_OMAP_ZOOM2=y +CONFIG_MACH_OMAP_ZOOM3=y +CONFIG_MACH_CM_T35=y +CONFIG_MACH_CM_T3517=y +CONFIG_MACH_IGEP0020=y +CONFIG_MACH_IGEP0030=y +CONFIG_MACH_SBC3530=y +CONFIG_MACH_OMAP_3630SDP=y +CONFIG_MACH_OMAP_4430SDP=y +CONFIG_MACH_OMAP4_PANDA=y +CONFIG_MACH_TI8168EVM=y +CONFIG_OMAP3_EMU=y +# CONFIG_OMAP3_SDRC_AC_TIMING is not set +# System MMU +CONFIG_CPU_32v6K=y +CONFIG_CPU_V7=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_ARM_THUMBEE=y +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_CPU_HAS_PMU=y +CONFIG_ARM_ERRATA_430973=y +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_742230 is not set +# CONFIG_ARM_ERRATA_742231 is not set +CONFIG_PL310_ERRATA_588369=y +CONFIG_ARM_ERRATA_720789=y +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_ARM_ERRATA_753970 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_754327 is not set +CONFIG_ARM_GIC=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_PCCARD is not set +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_HAVE_ARM_SCU=y +CONFIG_HAVE_ARM_TWD=y +CONFIG_NR_CPUS=2 +CONFIG_HOTPLUG_CPU=y +CONFIG_LOCAL_TIMERS=y +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_HZ=128 +# CONFIG_THUMB2_KERNEL is not set +# CONFIG_OABI_COMPAT is not set +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +CONFIG_HW_PERF_EVENTS=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +# CONFIG_CC_STACKPROTECTOR is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_AUTO_ZRELADDR is not set +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_VFPv3=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_BINFMT_MISC=m +CONFIG_PM_DEBUG=y +# CONFIG_PM_ADVANCED_DEBUG is not set +# CONFIG_PM_VERBOSE is not set +CONFIG_CAN_PM_TRACE=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_APM_EMULATION is not set +CONFIG_ARCH_HAS_OPP=y +CONFIG_PM_OPP=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set +# CONFIG_ARPD is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +CONFIG_IPV6=y +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_IPV6_SUBTREES is not set +# CONFIG_IPV6_MROUTE is not set +CONFIG_NF_DEFRAG_IPV4=m +# CONFIG_NET_DCCPPROBE is not set +# CONFIG_L2TP_V3 is not set +# CONFIG_DECNET_ROUTER is not set +# CONFIG_NET_SCH_INGRESS is not set +# CONFIG_NET_CLS_U32 is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_ACT_CSUM is not set +# CONFIG_NET_CLS_IND is not set +CONFIG_RPS=y +CONFIG_XPS=y +# CONFIG_CAN_SLCAN is not set +# CONFIG_CAN_DEV is not set +CONFIG_RXKAD=m +CONFIG_FIRMWARE_IN_KERNEL=y +# CONFIG_DEBUG_DEVRES is not set +CONFIG_MTD=y +CONFIG_MTD_TESTS=m +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +CONFIG_SM_FTL=m +CONFIG_MTD_PHYSMAP=m +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_GPIO_ADDR is not set +CONFIG_MTD_PLATRAM=m +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=m +CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_MTD_SST25L is not set +CONFIG_MTD_SLRAM=m +CONFIG_MTD_PHRAM=m +CONFIG_MTD_DOC2000=m +CONFIG_MTD_DOC2001=m +CONFIG_MTD_DOC2001PLUS=m +CONFIG_MTD_DOCPROBE=m +CONFIG_MTD_DOCECC=m +# CONFIG_MTD_DOCPROBE_ADVANCED is not set +CONFIG_MTD_DOCPROBE_ADDRESS=0 +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_OMAP2=y +CONFIG_MTD_NAND_OMAP_PREFETCH=y +CONFIG_MTD_NAND_OMAP_PREFETCH_DMA=y +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_PLATFORM=y +# CONFIG_MTD_ALAUDA is not set +CONFIG_MTD_ONENAND=y +# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set +# CONFIG_MTD_ONENAND_GENERIC is not set +CONFIG_MTD_ONENAND_OMAP2=y +# CONFIG_MTD_ONENAND_OTP is not set +CONFIG_MTD_ONENAND_2X_PROGRAM=y +CONFIG_MTD_ONENAND_SIM=m +CONFIG_MTD_UBI_GLUEBI=m +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV_RAM_SIZE=65536 +CONFIG_MG_DISK=m +CONFIG_MG_DISK_RES=0 +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +CONFIG_HMC6352=m +CONFIG_DS1682=m +CONFIG_TI_DAC7512=m +CONFIG_BMP085=m +CONFIG_C2PORT=m +CONFIG_EEPROM_AT25=m +# CONFIG_IWMC3200TOP_DEBUGFS is not set +# CONFIG_SCSI_PROC_FS is not set +# CONFIG_BLK_DEV_SR_VENDOR is not set +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_SATA_AHCI_PLATFORM is not set +# CONFIG_DM_DEBUG is not set +# CONFIG_DM_RAID is not set +# CONFIG_DM_LOG_USERSPACE is not set +CONFIG_DM_MULTIPATH=y +# CONFIG_TARGET_CORE is not set +# CONFIG_MACVTAP is not set +CONFIG_MII=y +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM63XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_TI_DAVINCI_EMAC is not set +# CONFIG_TI_DAVINCI_MDIO is not set +# CONFIG_TI_DAVINCI_CPDMA is not set +CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y +CONFIG_ENC28J60=m +# CONFIG_ENC28J60_WRITEVERIFY is not set +# CONFIG_ETHOC is not set +CONFIG_SMC911X=y +CONFIG_SMSC911X=y +# CONFIG_DNET is not set +# CONFIG_B44 is not set +CONFIG_KS8851=m +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_ATH9K_HTC is not set +# CONFIG_AR9170_USB is not set +# CONFIG_B43_SDIO is not set +# CONFIG_B43_PHY_N is not set +# CONFIG_HOSTAP is not set +# CONFIG_IWM is not set +CONFIG_LIBERTAS_SPI=m +# CONFIG_LIBERTAS_MESH is not set +CONFIG_P54_SPI=m +# CONFIG_P54_SPI_DEFAULT_EEPROM is not set +# CONFIG_RT2800USB_RT33XX is not set +# CONFIG_RTL8192CE is not set +CONFIG_WL1251_SPI=m +CONFIG_WL12XX_SPI=m +CONFIG_WL12XX_SDIO_TEST=m +# CONFIG_WIMAX_IWMC3200_SDIO is not set +CONFIG_USB_USBNET=y +CONFIG_USB_NET_CDCETHER=y +CONFIG_USB_NET_CDC_NCM=y +CONFIG_USB_NET_RNDIS_HOST=y +# CONFIG_ATM_TCP is not set +# CONFIG_IEEE802154_FAKEHARD is not set +# CONFIG_CAIF_TTY is not set +# CONFIG_CAIF_SPI_SLAVE is not set +CONFIG_PPP_BSDCOMP=m +# CONFIG_PPPOL2TP is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +CONFIG_INPUT_POLLDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_EVBUG=m +# CONFIG_KEYBOARD_QT2160 is not set +CONFIG_KEYBOARD_LKKBD=m +CONFIG_KEYBOARD_GPIO=m +CONFIG_KEYBOARD_TCA6416=m +CONFIG_KEYBOARD_MATRIX=m +CONFIG_KEYBOARD_LM8323=m +CONFIG_KEYBOARD_MCS=m +CONFIG_KEYBOARD_NEWTON=m +CONFIG_KEYBOARD_STOWAWAY=m +CONFIG_KEYBOARD_SUNKBD=m +# CONFIG_KEYBOARD_OMAP4 is not set +CONFIG_KEYBOARD_TWL4030=m +CONFIG_KEYBOARD_XTKBD=m +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_GPIO=m +CONFIG_JOYSTICK_AS5011=m +# CONFIG_TABLET_USB_HANWANG is not set +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_AD7877=m +CONFIG_TOUCHSCREEN_AD7879=m +CONFIG_TOUCHSCREEN_AD7879_I2C=m +# CONFIG_TOUCHSCREEN_AD7879_SPI is not set +CONFIG_TOUCHSCREEN_CY8CTMG110=m +CONFIG_TOUCHSCREEN_HAMPSHIRE=m +CONFIG_TOUCHSCREEN_QT602240=m +CONFIG_TOUCHSCREEN_TPS6507X=m +# CONFIG_TOUCHSCREEN_TSC2005 is not set +CONFIG_INPUT_AD714X=m +CONFIG_INPUT_AD714X_I2C=m +CONFIG_INPUT_AD714X_SPI=m +# CONFIG_INPUT_APPLEIR is not set +CONFIG_INPUT_TWL4030_PWRBUTTON=y +CONFIG_INPUT_TWL4030_VIBRA=y +CONFIG_INPUT_UINPUT=y +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +CONFIG_INPUT_ADXL34X=m +CONFIG_INPUT_ADXL34X_I2C=m +CONFIG_INPUT_ADXL34X_SPI=m +# CONFIG_INPUT_CMA3000_I2C is not set +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_GAMEPORT_NS558 is not set +# CONFIG_GAMEPORT_L4 is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +CONFIG_SERIAL_8250_DETECT_IRQ=y +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_OMAP=y +CONFIG_SERIAL_OMAP_CONSOLE=y +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_GPIO is not set +CONFIG_I2C_OMAP=y +# CONFIG_I2C_SIMTEC is not set +CONFIG_I2C_TAOS_EVM=m +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y +# SPI Master Controller Drivers +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +CONFIG_SPI_OMAP24XX=y +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set +# SPI Protocol Masters +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# +# CONFIG_GPIO_BASIC_MMIO is not set +# CONFIG_GPIO_IT8761E is not set +# CONFIG_GPIO_PL061 is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +CONFIG_GPIO_TWL4030=y +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_CHARGER_TWL4030 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set +CONFIG_WATCHDOG_NOWAYOUT=y +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_MPCORE_WATCHDOG is not set +CONFIG_OMAP_WATCHDOG=y +# CONFIG_TWL4030_WATCHDOG is not set +CONFIG_SSB=y +# CONFIG_SSB_SDIOHOST is not set +CONFIG_MFD_CORE=y +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS65010 is not set +CONFIG_TWL4030_CORE=y +# CONFIG_TWL4030_MADC is not set +CONFIG_TWL4030_POWER=y +CONFIG_TWL4030_CODEC=y +# CONFIG_TWL6030_PWM is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_EZX_PCAP is not set +CONFIG_MFD_OMAP_USB_HOST=y +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_WL1273_CORE is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_DUMMY is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +CONFIG_REGULATOR_TWL4030=y +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_MEDIA_SUPPORT=y +CONFIG_RC_CORE=y +CONFIG_LIRC=y +CONFIG_IR_RC5_SZ_DECODER=y +CONFIG_IR_LIRC_CODEC=y +# CONFIG_RC_LOOPBACK is not set +CONFIG_VIDEOBUF_DMA_CONTIG=m +CONFIG_V4L2_MEM2MEM_DEV=m +# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set +# Encoders/decoders and other helper chips +# + +# +CONFIG_VIDEO_IR_I2C=m +CONFIG_VIDEO_CS5345=m +CONFIG_VIDEO_M52790=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_VP27SMPX=m +CONFIG_VIDEO_OV7670=m +CONFIG_VIDEO_SAA717X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m +# +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_SAA6588 is not set +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_MT9V032 is not set +# CONFIG_VIDEO_TCM825X is not set +# CONFIG_VIDEO_SAA7110 is not set +# CONFIG_VIDEO_SAA7191 is not set +# CONFIG_VIDEO_TVP514X is not set +# CONFIG_VIDEO_TVP5150 is not set +CONFIG_VIDEO_TVP7002=m +# CONFIG_VIDEO_VPX3220 is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_ADV7343 is not set +CONFIG_VIDEO_AK881X=m +# CONFIG_VIDEO_VPFE_CAPTURE is not set +CONFIG_VIDEO_OMAP2_VOUT=m +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_VIDEO_AU0828 is not set +# CONFIG_VIDEO_SR030PC30 is not set +# CONFIG_VIDEO_OMAP3 is not set +# CONFIG_SOC_CAMERA is not set +CONFIG_USB_ET61X251=m +CONFIG_USB_SN9C102=m +CONFIG_VIDEO_MEM2MEM_TESTDEV=m +CONFIG_RADIO_TEA5764=m +CONFIG_RADIO_SAA7706H=m +CONFIG_RADIO_TEF6862=m +# CONFIG_TTPCI_EEPROM is not set +# CONFIG_SMS_SDIO_DRV is not set +# CONFIG_DVB_DUMMY_FE is not set +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_PLL=m +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB_DDC is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set +# CONFIG_FB_OMAP_LCD_VGA is not set +CONFIG_OMAP2_VRAM=y +CONFIG_OMAP2_VRFB=y +CONFIG_OMAP2_DSS=y +CONFIG_OMAP2_VRAM_SIZE=12 +CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y +# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set +CONFIG_OMAP2_DSS_DPI=y +# CONFIG_OMAP2_DSS_RFBI is not set +CONFIG_OMAP2_DSS_VENC=y +CONFIG_OMAP4_DSS_HDMI=y +# CONFIG_OMAP2_DSS_SDI is not set +# CONFIG_OMAP2_DSS_DSI is not set +# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set +CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1 +CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET=y +CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y +CONFIG_FB_OMAP2=y +CONFIG_FB_OMAP2_DEBUG_SUPPORT=y +CONFIG_FB_OMAP2_NUM_FBS=3 + +# +# OMAP2/3 Display Device Drivers +# +CONFIG_PANEL_GENERIC_DPI=y +CONFIG_PANEL_SHARP_LS037V7DW01=y +CONFIG_PANEL_NEC_NL8048HL11_01B=y +CONFIG_PANEL_TPO_TD043MTEA1=y +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LCD_PLATFORM is not set +# CONFIG_LCD_S6E63M0 is not set +CONFIG_BACKLIGHT_GENERIC=m +CONFIG_DISPLAY_SUPPORT=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_JACK=y +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=m +CONFIG_SND_SEQ_HRTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_RAWMIDI_SEQ=m +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_SOC=y +# CONFIG_SND_SOC_CACHE_LZO is not set +CONFIG_SND_OMAP_SOC=y +CONFIG_SND_OMAP_SOC_MCBSP=y +CONFIG_SND_OMAP_SOC_MCPDM=y +CONFIG_SND_OMAP_SOC_RX51=y +CONFIG_SND_OMAP_SOC_OVERO=y +CONFIG_SND_OMAP_SOC_OMAP3EVM=y +CONFIG_SND_OMAP_SOC_AM3517EVM=y +CONFIG_SND_OMAP_SOC_SDP3430=y +CONFIG_SND_OMAP_SOC_SDP4430=y +CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=y +CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y +CONFIG_SND_OMAP_SOC_ZOOM2=y +CONFIG_SND_OMAP_SOC_IGEP0020=y +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +CONFIG_SND_SOC_TLV320AIC23=y +CONFIG_SND_SOC_TLV320AIC3X=y +CONFIG_SND_SOC_TWL4030=y +CONFIG_SND_SOC_TWL6040=y +# CONFIG_SOUND_PRIME is not set +CONFIG_HID=y +CONFIG_HID_3M_PCT=m +CONFIG_HID_A4TECH=m +# CONFIG_HID_ACRUX is not set +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_EZKEY=m +CONFIG_HID_KYE=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LOGITECH=m +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MOSART=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_NTRIG=m +CONFIG_HID_QUANTA=m +CONFIG_HID_STANTUM=m +# CONFIG_HID_TIVO_SLIDE is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_EHCI_HCD_OMAP=y +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_U132_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_TUSB6010 is not set +CONFIG_USB_MUSB_OMAP2PLUS=y +# CONFIG_USB_MUSB_AM35X is not set +# CONFIG_USB_MUSB_HOST is not set +# CONFIG_USB_MUSB_PERIPHERAL is not set +CONFIG_USB_MUSB_OTG=y +CONFIG_USB_GADGET_MUSB_HDRC=y +CONFIG_USB_INVENTRA_DMA=y +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=m +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_USBAT=m +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_JUMPSHOT=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +# CONFIG_USB_UAS is not set +# CONFIG_USB_LIBUSUAL is not set +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +CONFIG_USB_SERIAL_KEYSPAN_USA28=y +CONFIG_USB_SERIAL_KEYSPAN_USA28X=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y +CONFIG_USB_SERIAL_KEYSPAN_USA19=y +CONFIG_USB_SERIAL_KEYSPAN_USA18X=y +CONFIG_USB_SERIAL_KEYSPAN_USA19W=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y +CONFIG_USB_SERIAL_KEYSPAN_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +# CONFIG_USB_SERIAL_SAFE_PADDED is not set +# CONFIG_USB_SERIAL_SAMBA is not set +CONFIG_USB_SERIAL_ZIO=m +CONFIG_USB_RIO500=m +CONFIG_USB_CYPRESS_CY7C63=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_TEST=m +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_R8A66597 is not set +# CONFIG_USB_GADGET_PXA_U2O is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +CONFIG_USB_ETH=y +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_ETH_EEM=y +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_NOKIA is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set +CONFIG_USB_GPIO_VBUS=y +# CONFIG_ISP1301_OMAP is not set +CONFIG_TWL4030_USB=y +CONFIG_TWL6030_USB=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_OMAP=m +CONFIG_MMC_OMAP_HS=y +CONFIG_MMC_SPI=m +# CONFIG_MMC_DW is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MEMSTICK is not set +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_GPIO_PLATFORM=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_LT3593 is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_GPIO is not set +# CONFIG_NFC_DEVICES is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_TWL4030=m +CONFIG_RTC_DRV_S35390A=m +CONFIG_RTC_DRV_M41T94=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_MAX6902=m +CONFIG_RTC_DRV_R9701=m +CONFIG_RTC_DRV_RS5C348=m +CONFIG_RTC_DRV_DS3234=m +CONFIG_RTC_DRV_PCF2123=m +CONFIG_RTC_DRV_CMOS=m +CONFIG_RTC_DRV_M48T86=m +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_USB_SE401 is not set +# CONFIG_USB_VICAM is not set +CONFIG_PRISM2_USB=m +CONFIG_BRCM80211=y +CONFIG_BRCMFMAC=y +CONFIG_RT2870=m +CONFIG_R8712U=m +CONFIG_R8712_AP=y +CONFIG_ZRAM=m +# CONFIG_ZRAM_DEBUG is not set +# CONFIG_LIRC_STAGING is not set +CONFIG_TIDSPBRIDGE=m +CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE=0x600000 +# CONFIG_TIDSPBRIDGE_DEBUG is not set +CONFIG_TIDSPBRIDGE_RECOVERY=y +# CONFIG_TIDSPBRIDGE_CACHE_LINE_CHECK is not set +CONFIG_TIDSPBRIDGE_WDT3=y +CONFIG_TIDSPBRIDGE_WDT_TIMEOUT=5 +# CONFIG_TIDSPBRIDGE_NTFY_PWRERR is not set +# CONFIG_TIDSPBRIDGE_BACKTRACE is not set +# CONFIG_WESTBRIDGE is not set +CONFIG_WESTBRIDGE_HAL_SELECTED=y +CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL=y +# CONFIG_MACH_NO_WESTBRIDGE is not set +# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_JFS_STATISTICS=y +CONFIG_XFS_RT=y +CONFIG_OCFS2_FS_STATS=y +CONFIG_OCFS2_DEBUG_MASKLOG=y +# CONFIG_BTRFS_FS is not set +CONFIG_PRINT_QUOTA_WARNING=y +CONFIG_QUOTA_TREE=m +CONFIG_QFMT_V1=m +CONFIG_QFMT_V2=m +CONFIG_AUTOFS4_FS=m +CONFIG_ISO9660_FS=m +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_LZO=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +# CONFIG_JFFS2_CMODE_PRIORITY is not set +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_JFFS2_CMODE_FAVOURLZO=y +# CONFIG_LOGFS is not set +CONFIG_NFS_FS=m +# CONFIG_NFS_V4_1 is not set +CONFIG_ROOT_NFS=y +CONFIG_NFSD_DEPRECATED=y +CONFIG_LOCKD=y +CONFIG_NFS_ACL_SUPPORT=y +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_FSCACHE is not set +# CONFIG_CIFS_ACL is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_9P_FSCACHE is not set +# CONFIG_9P_FS_POSIX_ACL is not set +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=y +# CONFIG_DLM_DEBUG is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_DEBUG_PREEMPT=y +# CONFIG_BKL is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_RCU_CPU_STALL_VERBOSE=y +# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_RING_BUFFER_BENCHMARK is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_KGDB_TESTS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +CONFIG_EARLY_PRINTK=y +# CONFIG_DEBUG_ICEDCC is not set +CONFIG_OC_ETM=y +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_LSM_MMAP_MIN_ADDR=0 +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0 +# CONFIG_IMA is not set +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_RNG=m +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_SEQIV=m +CONFIG_CRYPTO_CTR=m +# CONFIG_CRYPTO_VMAC is not set +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_USER_API=m +CONFIG_CRYPTO_USER_API_HASH=m +CONFIG_CRYPTO_USER_API_SKCIPHER=m +CONFIG_CRYPTO_DEV_OMAP_SHAM=m +CONFIG_CRYPTO_DEV_OMAP_AES=m +CONFIG_LIBCRC32C=y +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_CGROUP_PERF is not set +# CONFIG_OPROFILE is not set +# CONFIG_OPROFILE is not set +# CONFIG_PATA_ARASAN_CF is not set +# CONFIG_BT_ATH3K is not set +# CONFIG_BT_WILINK is not set +# CONFIG_USB_HSO is not set diff --git a/kernel.spec b/kernel.spec index 13eed3c06..88066cd14 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 @@ -373,6 +373,7 @@ Summary: The Linux kernel %ifarch %{arm} %define all_arch_configs kernel-%{version}-arm*.config %define image_install_path boot +%define asmarch arm %define hdrarch arm %define make_target vmlinux %define kernel_image vmlinux @@ -549,7 +550,8 @@ Source70: config-s390x Source90: config-sparc64-generic -Source100: config-arm +Source100: config-arm-generic +Source110: config-arm-omap-generic # This file is intentionally left empty in the stock kernel. Its a nicety # added for those wanting to do custom rebuilds with altered config opts. @@ -1825,6 +1827,9 @@ fi # and build. %changelog +* Tue Aug 09 2011 Josh Boyer +- Add Makefile.config and ARM config changes from David Marlin + * Tue Aug 09 2011 Dave Jones - ptrace_report_syscall: check if TIF_SYSCALL_EMU is defined From d1998c6a8ab80de310adcd985cf0d137d0ee277c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 11 Aug 2011 12:00:03 -0400 Subject: [PATCH 126/397] Fix Xen blk device naming (rhbz 729340) --- kernel.spec | 7 ++++++- xen-blkfront-name-adjust.patch | 30 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 xen-blkfront-name-adjust.patch diff --git a/kernel.spec b/kernel.spec index 88066cd14..6b0e6c774 100644 --- a/kernel.spec +++ b/kernel.spec @@ -612,7 +612,8 @@ Patch800: linux-2.6-crash-driver.patch # crypto/ # virt + ksm patches -Patch1555: fix_xen_guest_on_old_EC2.patch +Patch1500: fix_xen_guest_on_old_EC2.patch +Patch1501: xen-blkfront-name-adjust.patch # DRM @@ -1174,6 +1175,7 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch # Assorted Virt Fixes ApplyPatch fix_xen_guest_on_old_EC2.patch +ApplyPatch xen-blkfront-name-adjust.patch # DRM core @@ -1827,6 +1829,9 @@ fi # and build. %changelog +* Thu Aug 11 2011 Dave Jones +- Fix Xen blk device naming (rhbz 729340) + * Tue Aug 09 2011 Josh Boyer - Add Makefile.config and ARM config changes from David Marlin diff --git a/xen-blkfront-name-adjust.patch b/xen-blkfront-name-adjust.patch new file mode 100644 index 000000000..9573c7bf5 --- /dev/null +++ b/xen-blkfront-name-adjust.patch @@ -0,0 +1,30 @@ +commit 196cfe2ae8fcdc03b3c7d627e7dfe8c0ce7229f9 +Author: Stefan Bader +Date: Thu Jul 14 15:30:22 2011 +0200 + + xen-blkfront: Drop name and minor adjustments for emulated scsi devices + + These were intended to avoid the namespace clash when representing + emulated IDE and SCSI devices. However that seems to confuse users + more than expected (a disk defined as sda becomes xvde). + So for now go back to the scheme which does no adjustments. This + will break when mixing IDE and SCSI names in the configuration of + guests but should be by now expected. + + Acked-by: Stefano Stabellini + Signed-off-by: Stefan Bader + Signed-off-by: Konrad Rzeszutek Wilk + +--- linux-2.6.39.noarch/drivers/block/xen-blkfront.c~ 2011-08-11 11:54:25.656150889 -0400 ++++ linux-2.6.39.noarch/drivers/block/xen-blkfront.c 2011-08-11 11:54:54.573046334 -0400 +@@ -123,8 +123,8 @@ static DEFINE_SPINLOCK(minor_lock); + #define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED)) + #define EMULATED_HD_DISK_MINOR_OFFSET (0) + #define EMULATED_HD_DISK_NAME_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET / 256) +-#define EMULATED_SD_DISK_MINOR_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET + (4 * 16)) +-#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_HD_DISK_NAME_OFFSET + 4) ++#define EMULATED_SD_DISK_MINOR_OFFSET (0) ++#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_SD_DISK_MINOR_OFFSET / 256) + + #define DEV_NAME "xvd" /* name in /dev */ + From c1dc3d8679be63d656014b2655aeb3e266d72b9c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 11 Aug 2011 15:05:26 -0400 Subject: [PATCH 127/397] Add quirk patch for logitech webcams (rhbz 729269) --- kernel.spec | 5 ++++ usb-add-quirk-for-logitech-webcams.patch | 30 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 usb-add-quirk-for-logitech-webcams.patch diff --git a/kernel.spec b/kernel.spec index 6b0e6c774..09a34c67c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -648,6 +648,7 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12022: fix-cdc-ncm-dma-stack-vars.patch Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch +Patch12024: usb-add-quirk-for-logitech-webcams.patch # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch @@ -1205,6 +1206,7 @@ ApplyPatch add-appleir-usb-driver.patch ApplyPatch fix-cdc-ncm-dma-stack-vars.patch ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch +ApplyPatch usb-add-quirk-for-logitech-webcams.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -1829,6 +1831,9 @@ fi # and build. %changelog +* Thu Aug 11 2011 Josh Boyer +- Add munged together patch for rhbz 729269 + * Thu Aug 11 2011 Dave Jones - Fix Xen blk device naming (rhbz 729340) diff --git a/usb-add-quirk-for-logitech-webcams.patch b/usb-add-quirk-for-logitech-webcams.patch new file mode 100644 index 000000000..fa32f34f9 --- /dev/null +++ b/usb-add-quirk-for-logitech-webcams.patch @@ -0,0 +1,30 @@ +commit a218e3649310bd2ee0e8b7ec6353ab029d020289 +Author: Oliver Neukum +Date: Tue Aug 9 08:12:37 2011 -0400 + + USB: quirk for Logitech C250, C270, and C310 webcams + + This need for this was shown by the new PM code + + Signed-off-by: Oliver Neukum + +diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c +index 81ce6a8..5114281 100644 +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -41,6 +41,15 @@ static const struct usb_device_id usb_quirk_list[] = { + /* Logitech Harmony 700-series */ + { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, + ++ /* Logitech Webcam C250 */ ++ { USB_DEVICE(0x046d, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, ++ ++ /* Logitech Webcam C310 */ ++ { USB_DEVICE(0x046d, 0x081b), .driver_info = USB_QUIRK_RESET_RESUME }, ++ ++ /* Logitech Webcam C270 */ ++ { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + /* Philips PSC805 audio device */ + { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME }, + From bfb05f22a77b318e7db68b1eb0e31988de7236a8 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Wed, 10 Aug 2011 14:27:06 -0500 Subject: [PATCH 128/397] setup config for tegra based arm boards, add device tree patches for arm build tegra and omap kernel on arm --- Makefile.config | 8 +- arm-omap-dt-compat.patch | 42 +++++++++ ...reading-mac-address-from-device-tree.patch | 92 +++++++++++++++++++ config-arm-tegra | 71 ++++++++++++++ kernel.spec | 63 ++++++++++++- 5 files changed, 272 insertions(+), 4 deletions(-) create mode 100644 arm-omap-dt-compat.patch create mode 100644 arm-smsc-support-reading-mac-address-from-device-tree.patch create mode 100644 config-arm-tegra diff --git a/Makefile.config b/Makefile.config index 35060e32f..f23293e83 100644 --- a/Makefile.config +++ b/Makefile.config @@ -9,7 +9,7 @@ CONFIGFILES = \ $(CFG)-i686-PAE.config $(CFG)-i686-PAEdebug.config \ $(CFG)-x86_64.config $(CFG)-x86_64-debug.config \ $(CFG)-s390x.config \ - $(CFG)-arm.config $(CFG)-armv7l-omap.config \ + $(CFG)-arm.config $(CFG)-armv7l-omap.config $(CFG)-armv7l-tegra.config \ $(CFG)-ppc.config $(CFG)-ppc-smp.config \ $(CFG)-sparc64.config \ $(CFG)-ppc64.config $(CFG)-ppc64-debug.config \ @@ -39,6 +39,9 @@ temp-arm-generic: config-arm-generic temp-generic temp-armv7l-omap-generic: config-arm-omap-generic temp-arm-generic perl merge.pl $^ > $@ +temp-armv7l-tegra: config-arm-tegra temp-arm-generic + perl merge.pl $^ > $@ + temp-x86-generic: config-x86-generic temp-generic perl merge.pl $^ > $@ @@ -105,6 +108,9 @@ kernel-$(VERSION)-arm.config: /dev/null temp-arm-generic kernel-$(VERSION)-armv7l-omap.config: /dev/null temp-armv7l-omap-generic perl merge.pl $^ arm > $@ +kernel-$(VERSION)-armv7l-tegra.config: /dev/null temp-armv7l-tegra + perl merge.pl $^ arm > $@ + kernel-$(VERSION)-ppc.config: /dev/null temp-powerpc32-generic perl merge.pl $^ powerpc > $@ diff --git a/arm-omap-dt-compat.patch b/arm-omap-dt-compat.patch new file mode 100644 index 000000000..ab7cd0a4d --- /dev/null +++ b/arm-omap-dt-compat.patch @@ -0,0 +1,42 @@ +diff -up linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap3beagle.c.fdt linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap3beagle.c +--- linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap3beagle.c.fdt 2011-08-04 16:51:12.034188064 -0500 ++++ linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap3beagle.c 2011-08-04 22:13:52.801156923 -0500 +@@ -591,6 +591,11 @@ static void __init omap3_beagle_init(voi + beagle_opp_init(); + } + ++static const char *omap3_beagle_dt_match[] __initdata = { ++ "ti,omap3-beagle", ++ NULL ++}; ++ + MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board") + /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */ + .boot_params = 0x80000100, +@@ -600,4 +605,5 @@ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagl + .init_irq = omap3_beagle_init_irq, + .init_machine = omap3_beagle_init, + .timer = &omap_timer, ++ .dt_compat = omap3_beagle_dt_match, + MACHINE_END +diff -up linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c.fdt linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c +--- linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c.fdt 2011-08-04 16:51:12.092169023 -0500 ++++ linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c 2011-08-04 22:15:29.200157437 -0500 +@@ -708,6 +708,11 @@ static void __init omap4_panda_map_io(vo + omap44xx_map_common_io(); + } + ++static const char *omap4_panda_match[] __initdata = { ++ "ti,omap4-panda", ++ NULL, ++}; ++ + MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board") + /* Maintainer: David Anders - Texas Instruments Inc */ + .boot_params = 0x80000100, +@@ -717,4 +722,5 @@ MACHINE_START(OMAP4_PANDA, "OMAP4 Panda + .init_irq = gic_init_irq, + .init_machine = omap4_panda_init, + .timer = &omap_timer, ++ .dt_compat = omap4_panda_match, + MACHINE_END diff --git a/arm-smsc-support-reading-mac-address-from-device-tree.patch b/arm-smsc-support-reading-mac-address-from-device-tree.patch new file mode 100644 index 000000000..a36c68369 --- /dev/null +++ b/arm-smsc-support-reading-mac-address-from-device-tree.patch @@ -0,0 +1,92 @@ +From 0b608345e114681f66ca0a3cf9d9434728da62ce Mon Sep 17 00:00:00 2001 +From: Ken Cox +Date: Thu, 23 Jun 2011 10:36:43 -0500 +Subject: [PATCH] Support reading mac address from device tree. + +If CONFIG_OF is enabled, we will try to read the mac address from the device tree. This enables us the ability to have a "static" mac address on arm boards such as the pandaboard and beagleboard which generate random mac addresses. +--- + drivers/net/usb/smsc75xx.c | 17 +++++++++++++++++ + drivers/net/usb/smsc95xx.c | 18 +++++++++++++++++- + 2 files changed, 34 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c +index 753ee6e..ac0a200 100644 +--- a/drivers/net/usb/smsc75xx.c ++++ b/drivers/net/usb/smsc75xx.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include "smsc75xx.h" + + #define SMSC_CHIPNAME "smsc75xx" +@@ -658,6 +659,22 @@ static int smsc75xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) + + static void smsc75xx_init_mac_address(struct usbnet *dev) + { ++ void *address; ++#ifdef CONFIG_OF ++ struct device_node *np; ++ ++ /* try the device tree */ ++ np = of_find_node_by_name(NULL, "smsc75xx"); ++ if (np) { ++ address = of_get_property(np, "local-mac-address", NULL); ++ if (address) { ++ memcpy(dev->net->dev_addr, address, ETH_ALEN); ++ netif_dbg(dev, ifup, dev->net, "MAC address read from device tree\n"); ++ return; ++ } ++ } ++#endif ++ + /* try reading mac address from EEPROM */ + if (smsc75xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, + dev->net->dev_addr) == 0) { +diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c +index bc86f4b..c83942d 100644 +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include "smsc95xx.h" + + #define SMSC_CHIPNAME "smsc95xx" +@@ -639,6 +640,22 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) + + static void smsc95xx_init_mac_address(struct usbnet *dev) + { ++ void *address; ++#ifdef CONFIG_OF ++ struct device_node *np; ++ ++ /* try the device tree */ ++ np = of_find_node_by_name(NULL, "smsc95xx"); ++ if (np) { ++ address = of_get_property(np, "local-mac-address", NULL); ++ if (address) { ++ memcpy(dev->net->dev_addr, address, ETH_ALEN); ++ netif_dbg(dev, ifup, dev->net, "MAC address read from device tree\n"); ++ return; ++ } ++ } ++#endif ++ + /* try reading mac address from EEPROM */ + if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, + dev->net->dev_addr) == 0) { +@@ -648,7 +665,6 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) + return; + } + } +- + /* no eeprom, or eeprom values are invalid. generate random MAC */ + random_ether_addr(dev->net->dev_addr); + netif_dbg(dev, ifup, dev->net, "MAC address set to random_ether_addr\n"); +-- +1.7.2.3 + diff --git a/config-arm-tegra b/config-arm-tegra new file mode 100644 index 000000000..31d89b3b2 --- /dev/null +++ b/config-arm-tegra @@ -0,0 +1,71 @@ +CONFIG_ARCH_TEGRA=y +CONFIG_MACH_HARMONY=y +CONFIG_MACH_KAEN=y +CONFIG_MACH_PAZ00=y +CONFIG_MACH_TRIMSLICE=y +CONFIG_MACH_WARIO=y +CONFIG_TEGRA_DEBUG_UARTD=y +CONFIG_ARM_ERRATA_742230=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_SMP=y +CONFIG_NR_CPUS=2 +CONFIG_PREEMPT=y +CONFIG_AEABI=y + +CONFIG_I2C_TEGRA=y + +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_TEGRA=y + +# CONFIG_RCU_BOOST is not set +CONFIG_TEGRA_SYSTEM_DMA=y +CONFIG_TEGRA_EMC_SCALING_ENABLE=y +CONFIG_ARM_THUMBEE=y +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_CACHE_L2X0=y +CONFIG_ARM_ERRATA_430973=y +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_742231 is not set +CONFIG_PL310_ERRATA_588369=y +CONFIG_ARM_ERRATA_720789=y +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_ARM_ERRATA_753970 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_754327 is not set +CONFIG_SMP_ON_UP=y +CONFIG_LOCAL_TIMERS=y +# CONFIG_THUMB2_KERNEL is not set +CONFIG_HW_PERF_EVENTS=y +# CONFIG_NEON is not set +# CONFIG_RFKILL_GPIO is not set +CONFIG_KEYBOARD_TEGRA=y +# CONFIG_MPCORE_WATCHDOG is not set +CONFIG_USB_EHCI_TEGRA=y +CONFIG_RTC_DRV_TEGRA=m +CONFIG_MFD_NVEC=y +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_RCU_CPU_STALL_VERBOSE is not set +# CONFIG_PREEMPT_TRACER is not set +CONFIG_KEYBOARD_NVEC=y +CONFIG_SERIO_NVEC_PS2=y +CONFIG_NVEC_POWER=y + +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEBUG=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y diff --git a/kernel.spec b/kernel.spec index 09a34c67c..544d4bba8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -112,6 +112,10 @@ Summary: The Linux kernel %define with_bootwrapper %{?_without_bootwrapper: 0} %{?!_without_bootwrapper: 1} # Want to build a the vsdo directories installed %define with_vdso_install %{?_without_vdso_install: 0} %{?!_without_vdso_install: 1} +# ARM OMAP (Beagle/Panda Board) +%define with_omap %{?_without_omap: 0} %{?!_without_omap: 1} +# kernel-tegra (only valid for arm) +%define with_tegra %{?_without_tegra: 0} %{?!_without_tegra: 1} # Build the kernel-doc package, but don't fail the build if it botches. # Here "true" means "continue" and "false" means "fail the build". @@ -221,6 +225,12 @@ Summary: The Linux kernel %define with_pae 0 %endif +# kernel-tegra and omap is only built on arm +%ifnarch %{arm} +%define with_tegra 0 +%define with_omap 0 +%endif + # if requested, only build base kernel %if %{with_baseonly} %define with_smp 0 @@ -375,8 +385,10 @@ Summary: The Linux kernel %define image_install_path boot %define asmarch arm %define hdrarch arm -%define make_target vmlinux -%define kernel_image vmlinux +%define make_target bzImage +%define kernel_image arch/arm/boot/zImage +%define with_up 0 +%define with_perf 0 %endif %if %{nopatches} @@ -399,7 +411,7 @@ Summary: The Linux kernel # Which is a BadThing(tm). # We only build kernel-headers on the following... -%define nobuildarches i386 s390 sparc sparcv9 %{arm} +%define nobuildarches i386 s390 sparc sparcv9 %ifarch %nobuildarches %define with_up 0 @@ -552,6 +564,7 @@ Source90: config-sparc64-generic Source100: config-arm-generic Source110: config-arm-omap-generic +Source111: config-arm-tegra # This file is intentionally left empty in the stock kernel. Its a nicety # added for those wanting to do custom rebuilds with altered config opts. @@ -663,6 +676,9 @@ Patch13010: iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch Patch20000: utrace.patch +# Flattened devicetree support +Patch21000: arm-omap-dt-compat.patch +Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -855,6 +871,19 @@ It should only be installed when trying to gather additional information on kernel bugs, as some of these options impact performance noticably. +%define variant_summary The Linux kernel compiled for TI-OMAP boards +%kernel_variant_package omap +%description omap +This package includes a version of the Linux kernel with support for +TI-OMAP based systems, i.e., BeagleBoard-xM. + +%define variant_summary The Linux kernel compiled for tegra boards +%kernel_variant_package tegra +%description tegra +This package includes a version of the Linux kernel with support for +nvidia tegra based systems, i.e., trimslice, ac-100. + + %prep # do a few sanity-checks for --with *only builds %if %{with_baseonly} @@ -1093,6 +1122,12 @@ ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R # ApplyPatch linux-2.6.29-sparc-IOC_TYPECHECK.patch +# +# ARM +# +ApplyPatch arm-omap-dt-compat.patch +ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch + # # Exec shield # @@ -1524,6 +1559,14 @@ BuildKernel %make_target %kernel_image PAEdebug BuildKernel %make_target %kernel_image PAE %endif +%if %{with_omap} +BuildKernel %make_target %kernel_image omap +%endif + +%if %{with_tegra} +BuildKernel %make_target %kernel_image tegra +%endif + %if %{with_up} BuildKernel %make_target %kernel_image %endif @@ -1716,6 +1759,12 @@ fi}\ %kernel_variant_post -v PAEdebug -r (kernel|kernel-smp) %kernel_variant_preun PAEdebug +%kernel_variant_preun omap +%kernel_variant_post -v omap + +%kernel_variant_preun tegra +%kernel_variant_post -v tegra + if [ -x /sbin/ldconfig ] then /sbin/ldconfig -X || exit $? @@ -1826,11 +1875,19 @@ fi %kernel_variant_files %{with_debug} debug %kernel_variant_files %{with_pae} PAE %kernel_variant_files %{with_pae_debug} PAEdebug +%kernel_variant_files %{with_omap} omap +%kernel_variant_files %{with_tegra} tegra # plz don't put in a version string unless you're going to tag # and build. %changelog +* Thu Aug 11 2011 Dennis Gilmore +- add config for arm tegra devices +- setup kernel to build omap image (patch from David Marlin) +- setup kernel to build tegra image based on omap work +- add arm device tree patches + * Thu Aug 11 2011 Josh Boyer - Add munged together patch for rhbz 729269 From 92be6ab41b66dbd012e0e59cceab13cf7e30842f Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Wed, 10 Aug 2011 14:50:02 -0500 Subject: [PATCH 129/397] only build kernel headers on the base arm arches --- kernel.spec | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel.spec b/kernel.spec index 544d4bba8..a874c7b08 100644 --- a/kernel.spec +++ b/kernel.spec @@ -388,6 +388,11 @@ Summary: The Linux kernel %define make_target bzImage %define kernel_image arch/arm/boot/zImage %define with_up 0 +# we only build headers on the base arm arches +# just like we used to only build them on i386 for x86 +%ifnarch armv5tel armv7hl +%define with_headers 0 +%endif %define with_perf 0 %endif From 7c90685c8f9206a4c9f13072d25c4a1f30ed86d9 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Wed, 10 Aug 2011 15:06:10 -0500 Subject: [PATCH 130/397] only build the omap and tegra variants on armv7 builds --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index a874c7b08..04acaf5a1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -225,8 +225,8 @@ Summary: The Linux kernel %define with_pae 0 %endif -# kernel-tegra and omap is only built on arm -%ifnarch %{arm} +# kernel-tegra and omap is only built on armv7 hard and softfp +%ifnarch armv7hl armv7l %define with_tegra 0 %define with_omap 0 %endif From 82a003a4a45656bd13c9cf2a237f662f4b6525e4 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Fri, 12 Aug 2011 00:37:40 -0500 Subject: [PATCH 131/397] tweak the arm configs a little build a up image on armv5tel its a basic qemu image. setup to make configs for building kernels on hardware floating point arm arches --- Makefile.config | 13 ++++++++++++- config-arm-generic | 5 ++++- config-arm-tegra | 18 +++++++++++++++++- kernel.spec | 3 +++ 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/Makefile.config b/Makefile.config index f23293e83..75be683ab 100644 --- a/Makefile.config +++ b/Makefile.config @@ -9,7 +9,9 @@ CONFIGFILES = \ $(CFG)-i686-PAE.config $(CFG)-i686-PAEdebug.config \ $(CFG)-x86_64.config $(CFG)-x86_64-debug.config \ $(CFG)-s390x.config \ - $(CFG)-arm.config $(CFG)-armv7l-omap.config $(CFG)-armv7l-tegra.config \ + $(CFG)-arm.config $(CFG)-armv5tel.config \ + $(CFG)-armv7l-omap.config $(CFG)-armv7l-tegra.config \ + $(CFG)-armv7hl-omap.config $(CFG)-armv7hl-tegra.config \ $(CFG)-ppc.config $(CFG)-ppc-smp.config \ $(CFG)-sparc64.config \ $(CFG)-ppc64.config $(CFG)-ppc64-debug.config \ @@ -105,12 +107,21 @@ kernel-$(VERSION)-s390x.config: config-s390x temp-s390-generic kernel-$(VERSION)-arm.config: /dev/null temp-arm-generic perl merge.pl $^ arm > $@ +kernel-$(VERSION)-armv5tel.config: /dev/null temp-arm-generic + perl merge.pl $^ arm > $@ + kernel-$(VERSION)-armv7l-omap.config: /dev/null temp-armv7l-omap-generic perl merge.pl $^ arm > $@ kernel-$(VERSION)-armv7l-tegra.config: /dev/null temp-armv7l-tegra perl merge.pl $^ arm > $@ +kernel-$(VERSION)-armv7hl-omap.config: /dev/null temp-armv7l-omap-generic + perl merge.pl $^ arm > $@ + +kernel-$(VERSION)-armv7hl-tegra.config: /dev/null temp-armv7l-tegra + perl merge.pl $^ arm > $@ + kernel-$(VERSION)-ppc.config: /dev/null temp-powerpc32-generic perl merge.pl $^ powerpc > $@ diff --git a/config-arm-generic b/config-arm-generic index 5b79fe23d..4a0897152 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -82,9 +82,12 @@ CONFIG_FB_ARMCLCD=m CONFIG_SND_ARM=y CONFIG_SND_ARMAACI=m +CONFIG_SND_SOC=m +# CONFIG_SND_SOC_CACHE_LZO is not set +# CONFIG_SND_SOC_ALL_CODECS is not set CONFIG_USB_MUSB_HDRC=y -# CONFIG_MUSB_PIO_ONLY is not set +CONFIG_MUSB_PIO_ONLY=y CONFIG_USB_TUSB6010=y # CONFIG_USB_MUSB_DEBUG is not set diff --git a/config-arm-tegra b/config-arm-tegra index 31d89b3b2..15e9ed720 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -49,6 +49,11 @@ CONFIG_KEYBOARD_TEGRA=y # CONFIG_MPCORE_WATCHDOG is not set CONFIG_USB_EHCI_TEGRA=y CONFIG_RTC_DRV_TEGRA=m + +CONFIG_SND_SOC_TEGRA=m +CONFIG_SND_SOC_TEGRA_WM8903=m +CONFIG_SND_SOC_TEGRA_TRIMSLICE=m + CONFIG_MFD_NVEC=y # CONFIG_DEBUG_PREEMPT is not set # CONFIG_RCU_CPU_STALL_VERBOSE is not set @@ -56,6 +61,7 @@ CONFIG_MFD_NVEC=y CONFIG_KEYBOARD_NVEC=y CONFIG_SERIO_NVEC_PS2=y CONFIG_NVEC_POWER=y +CONFIG_POWER_SUPPLY=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_DEBUG=y @@ -67,5 +73,15 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=m CONFIG_CPU_FREQ_GOV_ONDEMAND=m CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m CONFIG_CPU_FREQ_TABLE=y -CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y + + +# these modules all fail with missing __bad_udelay +# http://www.spinics.net/lists/arm/msg15615.html provides some background +# CONFIG_SUNGEM is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_RADEON is not set +# CONFIG_DRM_RADEON is not set +# CONFIG_ATM_HE is not set +# CONFIG_SCSI_ACARD is not set diff --git a/kernel.spec b/kernel.spec index 04acaf5a1..a393d559e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -387,7 +387,10 @@ Summary: The Linux kernel %define hdrarch arm %define make_target bzImage %define kernel_image arch/arm/boot/zImage +# we build a up kernel on armv5tel. its used for qemu. +%ifnarch armv5tel %define with_up 0 +%endif # we only build headers on the base arm arches # just like we used to only build them on i386 for x86 %ifnarch armv5tel armv7hl From 31e0bc8c16acfe12a112eaf80e8cdba0653f695f Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Fri, 12 Aug 2011 09:11:15 -0500 Subject: [PATCH 132/397] the modules effected by __bad_udelay need to be excluded on all arm arches not just the tegra boards disable them in config-arm-generic --- config-arm-generic | 8 ++++++++ config-arm-tegra | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/config-arm-generic b/config-arm-generic index 4a0897152..5db311f9d 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -152,3 +152,11 @@ CONFIG_SERIAL_OF_PLATFORM=m # CONFIG_LEDS_GPIO_OF is not set CONFIG_MMC_SDHCI_OF=m +# these modules all fail with missing __bad_udelay +# http://www.spinics.net/lists/arm/msg15615.html provides some background +# CONFIG_SUNGEM is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_RADEON is not set +# CONFIG_DRM_RADEON is not set +# CONFIG_ATM_HE is not set +# CONFIG_SCSI_ACARD is not set diff --git a/config-arm-tegra b/config-arm-tegra index 15e9ed720..b3e0592a5 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -77,11 +77,3 @@ CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y -# these modules all fail with missing __bad_udelay -# http://www.spinics.net/lists/arm/msg15615.html provides some background -# CONFIG_SUNGEM is not set -# CONFIG_FB_SAVAGE is not set -# CONFIG_FB_RADEON is not set -# CONFIG_DRM_RADEON is not set -# CONFIG_ATM_HE is not set -# CONFIG_SCSI_ACARD is not set From a81be4733d73502aadd3166a7300ebbec746a249 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sat, 13 Aug 2011 20:29:55 -0400 Subject: [PATCH 133/397] Apply patches from 3.0.2rc1 --- .gitignore | 1 + kernel.spec | 9 +++++++-- sources | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 8043b138c..6652babd2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ clog *.rpm kernel-2.6.*/ kernel-3.*/ +/patch-3.0.2-rc1.gz diff --git a/kernel.spec b/kernel.spec index a393d559e..653d0ace8 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 0 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -64,7 +64,7 @@ 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 # Set rpm version accordingly @@ -582,6 +582,7 @@ Source1000: config-local Patch00: patch-3.0.bz2 Patch01: patch-3.0.1.bz2 +Patch02: patch-3.0.2-rc1.gz # we also need compile fixes for -vanilla @@ -1100,6 +1101,7 @@ done # Update vanilla to the latest upstream. (2.6.39 -> 3.0) ApplyPatch patch-3.0.bz2 ApplyPatch patch-3.0.1.bz2 +ApplyPatch patch-3.0.2-rc1.gz ApplyPatch linux-2.6-makefile-after_link.patch @@ -1890,6 +1892,9 @@ fi # and build. %changelog +* Sat Aug 13 2011 Dave Jones +- Apply patches from 3.0.2rc1 + * Thu Aug 11 2011 Dennis Gilmore - add config for arm tegra devices - setup kernel to build omap image (patch from David Marlin) diff --git a/sources b/sources index 97f423af5..16e338fb9 100644 --- a/sources +++ b/sources @@ -1,3 +1,4 @@ 1aab7a741abe08d42e8eccf20de61e05 linux-2.6.39.tar.bz2 df5790b51f218fc5e5463162b26afbfc patch-3.0.bz2 ac49f7907f1fc85fbab92d0f1aa1552a patch-3.0.1.bz2 +67faca534354c2f9dcc3536153acf0fb patch-3.0.2-rc1.gz From a0b4a6a9a921b081eea0dab8bca477b9dc87ad0e Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Mon, 15 Aug 2011 11:22:49 -0500 Subject: [PATCH 134/397] disable crystalhd module on the generic arm qemu build but enable it on the others disable tpm on arm build in mmc_block on tegra build --- config-arm-generic | 6 ++++++ config-arm-omap-generic | 3 ++- config-arm-tegra | 3 ++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/config-arm-generic b/config-arm-generic index 5db311f9d..3886c6d8d 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -152,6 +152,12 @@ CONFIG_SERIAL_OF_PLATFORM=m # CONFIG_LEDS_GPIO_OF is not set CONFIG_MMC_SDHCI_OF=m +# CONFIG_TCG_TPM is not set +# CONFIG_IMA is not set + +# ERROR: "__bswapsi2" [drivers/staging/crystalhd/crystalhd.ko] undefined! +# CONFIG_CRYSTALHD is not set + # these modules all fail with missing __bad_udelay # http://www.spinics.net/lists/arm/msg15615.html provides some background # CONFIG_SUNGEM is not set diff --git a/config-arm-omap-generic b/config-arm-omap-generic index 34b5389d6..8c9fc9c3b 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -413,7 +413,6 @@ CONFIG_SERIAL_OMAP_CONSOLE=y # CONFIG_HW_RANDOM_TIMERIOMEM is not set # CONFIG_R3964 is not set # CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set CONFIG_I2C=y CONFIG_I2C_CHARDEV=y # CONFIG_I2C_GPIO is not set @@ -1088,3 +1087,5 @@ CONFIG_LIBCRC32C=y # CONFIG_BT_ATH3K is not set # CONFIG_BT_WILINK is not set # CONFIG_USB_HSO is not set + +CONFIG_CRYSTALHD=m diff --git a/config-arm-tegra b/config-arm-tegra index b3e0592a5..c79efcf5b 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -16,6 +16,7 @@ CONFIG_AEABI=y CONFIG_I2C_TEGRA=y CONFIG_MMC=y +CONFIG_MMC_BLOCK=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_TEGRA=y @@ -76,4 +77,4 @@ CONFIG_CPU_FREQ_TABLE=y CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y - +CONFIG_CRYSTALHD=m From 5d9335e883fd6c159d353057691fe0d72b4c9866 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 15 Aug 2011 12:42:45 -0400 Subject: [PATCH 135/397] CVE-2011-2905 perf tools may parse user-controlled config file. (rhbz 729809) --- kernel.spec | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 653d0ace8..989762147 100644 --- a/kernel.spec +++ b/kernel.spec @@ -584,7 +584,6 @@ Patch00: patch-3.0.bz2 Patch01: patch-3.0.1.bz2 Patch02: patch-3.0.2-rc1.gz - # we also need compile fixes for -vanilla Patch04: linux-2.6-compile-fixes.patch @@ -593,10 +592,10 @@ Patch05: linux-2.6-makefile-after_link.patch %if !%{nopatches} - # revert upstream patches we get via other methods Patch09: linux-2.6-upstream-reverts.patch -# Git trees. + +Patch10: CVE-2011-2905.patch # Standalone patches @@ -1115,6 +1114,9 @@ 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 +# CVE fixes +ApplyPatch CVE-2011-2905.patch + # Architecture patches # x86(-64) @@ -1892,6 +1894,9 @@ fi # and build. %changelog +* Mon Aug 15 2011 Dave Jones +- CVE-2011-2905 perf tools may parse user-controlled config file. (rhbz 729809) + * Sat Aug 13 2011 Dave Jones - Apply patches from 3.0.2rc1 From 6c34be7b202ba315ae57a0753b4084e67f684f16 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 15 Aug 2011 12:43:15 -0400 Subject: [PATCH 136/397] CVE-2011-2905 perf tools may parse user-controlled config file. (rhbz 729809) --- CVE-2011-2905.patch | 116 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 CVE-2011-2905.patch diff --git a/CVE-2011-2905.patch b/CVE-2011-2905.patch new file mode 100644 index 000000000..0c7c28892 --- /dev/null +++ b/CVE-2011-2905.patch @@ -0,0 +1,116 @@ +commit aba8d056078e47350d85b06a9cabd5afcc4b72ea +Author: Jonathan Nieder +Date: Fri Aug 5 18:58:38 2011 +0200 + + perf tools: do not look at ./config for configuration + + In addition to /etc/perfconfig and $HOME/.perfconfig, perf looks for + configuration in the file ./config, imitating git which looks at + $GIT_DIR/config. If ./config is not a perf configuration file, it + fails, or worse, treats it as a configuration file and changes behavior + in some unexpected way. + + "config" is not an unusual name for a file to be lying around and perf + does not have a private directory dedicated for its own use, so let's + just stop looking for configuration in the cwd. Callers needing + context-sensitive configuration can use the PERF_CONFIG environment + variable. + + Requested-by: Christian Ohm + Cc: 632923@bugs.debian.org + Cc: Ben Hutchings + Cc: Christian Ohm + Cc: Ingo Molnar + Cc: Paul Mackerras + Cc: Peter Zijlstra + Link: http://lkml.kernel.org/r/20110805165838.GA7237@elie.gateway.2wire.net + Signed-off-by: Jonathan Nieder + Signed-off-by: Arnaldo Carvalho de Melo + +diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c +index e02d78c..6c86eca 100644 +--- a/tools/perf/util/config.c ++++ b/tools/perf/util/config.c +@@ -399,7 +399,6 @@ static int perf_config_global(void) + int perf_config(config_fn_t fn, void *data) + { + int ret = 0, found = 0; +- char *repo_config = NULL; + const char *home = NULL; + + /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ +@@ -421,12 +420,6 @@ int perf_config(config_fn_t fn, void *data) + free(user_config); + } + +- repo_config = perf_pathdup("config"); +- if (!access(repo_config, R_OK)) { +- ret += perf_config_from_file(fn, repo_config, data); +- found += 1; +- } +- free(repo_config); + if (found == 0) + return -1; + return ret; +commit 069e3725dd9be3b759a98e8c80ac5fc38b392b23 +Author: Arnaldo Carvalho de Melo +Date: Tue Aug 9 12:42:13 2011 -0300 + + perf tools: Check $HOME/.perfconfig ownership + + Just like we do already for perf.data files. + + Requested-by: Ingo Molnar + Cc: Ben Hutchings + Cc: Christian Ohm + Cc: David Ahern + Cc: Frederic Weisbecker + Cc: Jonathan Nieder + Cc: Mike Galbraith + Cc: Paul Mackerras + Cc: Peter Zijlstra + Cc: Stephane Eranian + Link: http://lkml.kernel.org/n/tip-qgokmxsmvppwpc5404qhyk7e@git.kernel.org + Signed-off-by: Arnaldo Carvalho de Melo + +diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c +index 6c86eca..fe02903 100644 +--- a/tools/perf/util/config.c ++++ b/tools/perf/util/config.c +@@ -413,13 +413,32 @@ int perf_config(config_fn_t fn, void *data) + home = getenv("HOME"); + if (perf_config_global() && home) { + char *user_config = strdup(mkpath("%s/.perfconfig", home)); +- if (!access(user_config, R_OK)) { +- ret += perf_config_from_file(fn, user_config, data); +- found += 1; ++ struct stat st; ++ ++ if (user_config == NULL) { ++ warning("Not enough memory to process %s/.perfconfig, " ++ "ignoring it.", home); ++ goto out; ++ } ++ ++ if (stat(user_config, &st) < 0) ++ goto out_free; ++ ++ if (st.st_uid && (st.st_uid != geteuid())) { ++ warning("File %s not owned by current user or root, " ++ "ignoring it.", user_config); ++ goto out_free; + } ++ ++ if (!st.st_size) ++ goto out_free; ++ ++ ret += perf_config_from_file(fn, user_config, data); ++ found += 1; ++out_free: + free(user_config); + } +- ++out: + if (found == 0) + return -1; + return ret; From 8f238d3c7303a4765b0c6ce8e9d7d5e421488e34 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 15 Aug 2011 22:56:42 -0400 Subject: [PATCH 137/397] 3.0.2 --- kernel.spec | 11 ++++++----- sources | 3 +-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/kernel.spec b/kernel.spec index 989762147..78e624d54 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 0 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -581,8 +581,7 @@ Source1000: config-local # Here should be only the patches up to the upstream canonical Linus tree. Patch00: patch-3.0.bz2 -Patch01: patch-3.0.1.bz2 -Patch02: patch-3.0.2-rc1.gz +Patch01: patch-3.0.2.bz2 # we also need compile fixes for -vanilla Patch04: linux-2.6-compile-fixes.patch @@ -1099,8 +1098,7 @@ done # Update vanilla to the latest upstream. (2.6.39 -> 3.0) ApplyPatch patch-3.0.bz2 -ApplyPatch patch-3.0.1.bz2 -ApplyPatch patch-3.0.2-rc1.gz +ApplyPatch patch-3.0.2.bz2 ApplyPatch linux-2.6-makefile-after_link.patch @@ -1894,6 +1892,9 @@ fi # and build. %changelog +* Mon Aug 15 2011 Dave Jones 2.6.40.2-1 +- 3.0.2 + * Mon Aug 15 2011 Dave Jones - CVE-2011-2905 perf tools may parse user-controlled config file. (rhbz 729809) diff --git a/sources b/sources index 16e338fb9..95e1e2493 100644 --- a/sources +++ b/sources @@ -1,4 +1,3 @@ 1aab7a741abe08d42e8eccf20de61e05 linux-2.6.39.tar.bz2 df5790b51f218fc5e5463162b26afbfc patch-3.0.bz2 -ac49f7907f1fc85fbab92d0f1aa1552a patch-3.0.1.bz2 -67faca534354c2f9dcc3536153acf0fb patch-3.0.2-rc1.gz +f5743283e6075282cebfbde62e65240b patch-3.0.2.bz2 From 9fe2f4befc252efd51e9b3e8b3e99e77485bbe25 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 15 Aug 2011 23:55:31 -0400 Subject: [PATCH 138/397] merge 3.0.3rc1 patches. (contains fix for CVE-2011-2905) --- .gitignore | 1 + CVE-2011-2905.patch | 116 ------------------------------------- kernel.spec | 31 ++++------ perf-check-ownership.patch | 62 ++++++++++++++++++++ sources | 1 + 5 files changed, 76 insertions(+), 135 deletions(-) delete mode 100644 CVE-2011-2905.patch create mode 100644 perf-check-ownership.patch diff --git a/.gitignore b/.gitignore index 6652babd2..03eb9bf77 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ clog kernel-2.6.*/ kernel-3.*/ /patch-3.0.2-rc1.gz +/patch-3.0.3-rc1.gz diff --git a/CVE-2011-2905.patch b/CVE-2011-2905.patch deleted file mode 100644 index 0c7c28892..000000000 --- a/CVE-2011-2905.patch +++ /dev/null @@ -1,116 +0,0 @@ -commit aba8d056078e47350d85b06a9cabd5afcc4b72ea -Author: Jonathan Nieder -Date: Fri Aug 5 18:58:38 2011 +0200 - - perf tools: do not look at ./config for configuration - - In addition to /etc/perfconfig and $HOME/.perfconfig, perf looks for - configuration in the file ./config, imitating git which looks at - $GIT_DIR/config. If ./config is not a perf configuration file, it - fails, or worse, treats it as a configuration file and changes behavior - in some unexpected way. - - "config" is not an unusual name for a file to be lying around and perf - does not have a private directory dedicated for its own use, so let's - just stop looking for configuration in the cwd. Callers needing - context-sensitive configuration can use the PERF_CONFIG environment - variable. - - Requested-by: Christian Ohm - Cc: 632923@bugs.debian.org - Cc: Ben Hutchings - Cc: Christian Ohm - Cc: Ingo Molnar - Cc: Paul Mackerras - Cc: Peter Zijlstra - Link: http://lkml.kernel.org/r/20110805165838.GA7237@elie.gateway.2wire.net - Signed-off-by: Jonathan Nieder - Signed-off-by: Arnaldo Carvalho de Melo - -diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c -index e02d78c..6c86eca 100644 ---- a/tools/perf/util/config.c -+++ b/tools/perf/util/config.c -@@ -399,7 +399,6 @@ static int perf_config_global(void) - int perf_config(config_fn_t fn, void *data) - { - int ret = 0, found = 0; -- char *repo_config = NULL; - const char *home = NULL; - - /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ -@@ -421,12 +420,6 @@ int perf_config(config_fn_t fn, void *data) - free(user_config); - } - -- repo_config = perf_pathdup("config"); -- if (!access(repo_config, R_OK)) { -- ret += perf_config_from_file(fn, repo_config, data); -- found += 1; -- } -- free(repo_config); - if (found == 0) - return -1; - return ret; -commit 069e3725dd9be3b759a98e8c80ac5fc38b392b23 -Author: Arnaldo Carvalho de Melo -Date: Tue Aug 9 12:42:13 2011 -0300 - - perf tools: Check $HOME/.perfconfig ownership - - Just like we do already for perf.data files. - - Requested-by: Ingo Molnar - Cc: Ben Hutchings - Cc: Christian Ohm - Cc: David Ahern - Cc: Frederic Weisbecker - Cc: Jonathan Nieder - Cc: Mike Galbraith - Cc: Paul Mackerras - Cc: Peter Zijlstra - Cc: Stephane Eranian - Link: http://lkml.kernel.org/n/tip-qgokmxsmvppwpc5404qhyk7e@git.kernel.org - Signed-off-by: Arnaldo Carvalho de Melo - -diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c -index 6c86eca..fe02903 100644 ---- a/tools/perf/util/config.c -+++ b/tools/perf/util/config.c -@@ -413,13 +413,32 @@ int perf_config(config_fn_t fn, void *data) - home = getenv("HOME"); - if (perf_config_global() && home) { - char *user_config = strdup(mkpath("%s/.perfconfig", home)); -- if (!access(user_config, R_OK)) { -- ret += perf_config_from_file(fn, user_config, data); -- found += 1; -+ struct stat st; -+ -+ if (user_config == NULL) { -+ warning("Not enough memory to process %s/.perfconfig, " -+ "ignoring it.", home); -+ goto out; -+ } -+ -+ if (stat(user_config, &st) < 0) -+ goto out_free; -+ -+ if (st.st_uid && (st.st_uid != geteuid())) { -+ warning("File %s not owned by current user or root, " -+ "ignoring it.", user_config); -+ goto out_free; - } -+ -+ if (!st.st_size) -+ goto out_free; -+ -+ ret += perf_config_from_file(fn, user_config, data); -+ found += 1; -+out_free: - free(user_config); - } -- -+out: - if (found == 0) - return -1; - return ret; diff --git a/kernel.spec b/kernel.spec index 78e624d54..859eeb971 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 0 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -64,7 +64,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 @@ -582,6 +582,7 @@ Source1000: config-local Patch00: patch-3.0.bz2 Patch01: patch-3.0.2.bz2 +Patch02: patch-3.0.3-rc1.gz # we also need compile fixes for -vanilla Patch04: linux-2.6-compile-fixes.patch @@ -594,10 +595,10 @@ Patch05: linux-2.6-makefile-after_link.patch # revert upstream patches we get via other methods Patch09: linux-2.6-upstream-reverts.patch -Patch10: CVE-2011-2905.patch - # Standalone patches +Patch100: perf-check-ownership.patch + Patch150: linux-2.6.29-sparc-IOC_TYPECHECK.patch Patch160: linux-2.6-32bit-mmap-exec-randomization.patch @@ -1099,6 +1100,7 @@ done # Update vanilla to the latest upstream. (2.6.39 -> 3.0) ApplyPatch patch-3.0.bz2 ApplyPatch patch-3.0.2.bz2 +ApplyPatch patch-3.0.3-rc1.gz ApplyPatch linux-2.6-makefile-after_link.patch @@ -1112,20 +1114,8 @@ 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 -# CVE fixes -ApplyPatch CVE-2011-2905.patch - -# Architecture patches -# x86(-64) - -# -# Intel IOMMU -# - -# -# PowerPC -# +ApplyPatch perf-check-ownership.patch # # SPARC64 @@ -1892,8 +1882,11 @@ fi # and build. %changelog -* Mon Aug 15 2011 Dave Jones 2.6.40.2-1 -- 3.0.2 +* Mon Aug 15 2011 Dave Jones 2.6.40.3-0 +- Apply patches from 3.0.3-rc1 + +* Mon Aug 15 2011 Dave Jones +- Apply patches from 3.0.2 * Mon Aug 15 2011 Dave Jones - CVE-2011-2905 perf tools may parse user-controlled config file. (rhbz 729809) diff --git a/perf-check-ownership.patch b/perf-check-ownership.patch new file mode 100644 index 000000000..93ed66085 --- /dev/null +++ b/perf-check-ownership.patch @@ -0,0 +1,62 @@ +commit 069e3725dd9be3b759a98e8c80ac5fc38b392b23 +Author: Arnaldo Carvalho de Melo +Date: Tue Aug 9 12:42:13 2011 -0300 + + perf tools: Check $HOME/.perfconfig ownership + + Just like we do already for perf.data files. + + Requested-by: Ingo Molnar + Cc: Ben Hutchings + Cc: Christian Ohm + Cc: David Ahern + Cc: Frederic Weisbecker + Cc: Jonathan Nieder + Cc: Mike Galbraith + Cc: Paul Mackerras + Cc: Peter Zijlstra + Cc: Stephane Eranian + Link: http://lkml.kernel.org/n/tip-qgokmxsmvppwpc5404qhyk7e@git.kernel.org + Signed-off-by: Arnaldo Carvalho de Melo + +diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c +index 6c86eca..fe02903 100644 +--- a/tools/perf/util/config.c ++++ b/tools/perf/util/config.c +@@ -413,13 +413,32 @@ int perf_config(config_fn_t fn, void *data) + home = getenv("HOME"); + if (perf_config_global() && home) { + char *user_config = strdup(mkpath("%s/.perfconfig", home)); +- if (!access(user_config, R_OK)) { +- ret += perf_config_from_file(fn, user_config, data); +- found += 1; ++ struct stat st; ++ ++ if (user_config == NULL) { ++ warning("Not enough memory to process %s/.perfconfig, " ++ "ignoring it.", home); ++ goto out; ++ } ++ ++ if (stat(user_config, &st) < 0) ++ goto out_free; ++ ++ if (st.st_uid && (st.st_uid != geteuid())) { ++ warning("File %s not owned by current user or root, " ++ "ignoring it.", user_config); ++ goto out_free; + } ++ ++ if (!st.st_size) ++ goto out_free; ++ ++ ret += perf_config_from_file(fn, user_config, data); ++ found += 1; ++out_free: + free(user_config); + } +- ++out: + if (found == 0) + return -1; + return ret; diff --git a/sources b/sources index 95e1e2493..4ed2072c0 100644 --- a/sources +++ b/sources @@ -1,3 +1,4 @@ 1aab7a741abe08d42e8eccf20de61e05 linux-2.6.39.tar.bz2 df5790b51f218fc5e5463162b26afbfc patch-3.0.bz2 f5743283e6075282cebfbde62e65240b patch-3.0.2.bz2 +23b4aad2d34ea209f62b199e67a88240 patch-3.0.3-rc1.gz From fc919d08c49f2f94566b8cb2e8f37a3e667214f7 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Tue, 16 Aug 2011 13:42:11 -0500 Subject: [PATCH 139/397] * Tue Aug 16 2011 Dennis Gilmore - add patch to work around gcc bug on arm --- arm-readl.patch | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 11 +++++++++++ 2 files changed, 60 insertions(+) create mode 100644 arm-readl.patch diff --git a/arm-readl.patch b/arm-readl.patch new file mode 100644 index 000000000..4cbd5af73 --- /dev/null +++ b/arm-readl.patch @@ -0,0 +1,49 @@ +--- arch/arm/include/asm/io.h.orig 2011-07-26 00:44:15.000000000 -0400 ++++ arch/arm/include/asm/io.h 2011-07-26 00:40:41.000000000 -0400 +@@ -55,6 +55,46 @@ + #define __raw_readw(a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a)) + #define __raw_readl(a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a)) + ++#undef __raw_writew ++#define __raw_writew(v,a) __dj_writew(v,a) ++static inline void ++__dj_writew(unsigned short v, unsigned short *a) ++{ ++ __chk_io_ptr(a); ++ asm volatile ("strh %0,[%1,#0]" :: "r" (v), "r" (a)); ++} ++ ++#undef __raw_writel ++#define __raw_writel(v,a) __dj_writel(v,a) ++static inline void ++__dj_writel(unsigned int v, unsigned int *a) ++{ ++ __chk_io_ptr(a); ++ asm volatile ("str %0,[%1,#0]" :: "r" (v), "r" (a)); ++} ++ ++#undef __raw_readw ++#define __raw_readw(a) __dj_readw(a) ++static inline unsigned short ++__dj_readw(unsigned short *a) ++{ ++ unsigned short rv; ++ __chk_io_ptr(a); ++ asm volatile ("ldrh %0,[%1,#0]" : "=r" (rv) : "r" (a)); ++ return rv; ++} ++ ++#undef __raw_readl ++#define __raw_readl(a) __dj_readl(a) ++static inline unsigned int ++__dj_readl(unsigned int *a) ++{ ++ unsigned long rv; ++ __chk_io_ptr(a); ++ asm volatile ("ldr %0,[%1,#0]" : "=r" (rv) : "r" (a)); ++ return rv; ++} ++ + /* + * Architecture ioremap implementation. + */ diff --git a/kernel.spec b/kernel.spec index 859eeb971..81e2aa523 100644 --- a/kernel.spec +++ b/kernel.spec @@ -687,6 +687,13 @@ Patch20000: utrace.patch # Flattened devicetree support Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch + +# workaround for issue with gcc-4.6.x +# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45819 +# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45704 +# patch from http://www.delorie.com/tmp/arm-readl.patch +Patch21002: arm-readl.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1127,6 +1134,7 @@ ApplyPatch linux-2.6.29-sparc-IOC_TYPECHECK.patch # ApplyPatch arm-omap-dt-compat.patch ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch +ApplyPatch arm-readl.patch # # Exec shield @@ -1882,6 +1890,9 @@ fi # and build. %changelog +* Tue Aug 16 2011 Dennis Gilmore +- add patch to work around gcc bug on arm + * Mon Aug 15 2011 Dave Jones 2.6.40.3-0 - Apply patches from 3.0.3-rc1 From 51219927a8b8a82d5c455548838544d62e542d37 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Tue, 16 Aug 2011 14:36:08 -0500 Subject: [PATCH 140/397] add a kernel/ to the start of the path so the arm-readl patch applies --- arm-readl.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arm-readl.patch b/arm-readl.patch index 4cbd5af73..5179396f6 100644 --- a/arm-readl.patch +++ b/arm-readl.patch @@ -1,5 +1,5 @@ ---- arch/arm/include/asm/io.h.orig 2011-07-26 00:44:15.000000000 -0400 -+++ arch/arm/include/asm/io.h 2011-07-26 00:40:41.000000000 -0400 +--- kernel/arch/arm/include/asm/io.h.orig 2011-07-26 00:44:15.000000000 -0400 ++++ kernel/arch/arm/include/asm/io.h 2011-07-26 00:40:41.000000000 -0400 @@ -55,6 +55,46 @@ #define __raw_readw(a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a)) #define __raw_readl(a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a)) From 24d01a89348ca52dd123c1ccb04cede1450fdb22 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Thu, 18 Aug 2011 10:34:21 -0500 Subject: [PATCH 141/397] add patch to have usb on tegra boards initialise correctly build in usb-storage on tegra systems --- TEGRA-2.6.40.2-enable-USB-ports.patch | 111 ++++++++++++++++++++++++++ config-arm-tegra | 1 + kernel.spec | 7 ++ 3 files changed, 119 insertions(+) create mode 100644 TEGRA-2.6.40.2-enable-USB-ports.patch diff --git a/TEGRA-2.6.40.2-enable-USB-ports.patch b/TEGRA-2.6.40.2-enable-USB-ports.patch new file mode 100644 index 000000000..1fef5fec2 --- /dev/null +++ b/TEGRA-2.6.40.2-enable-USB-ports.patch @@ -0,0 +1,111 @@ +--- linux-2.6.39.armv7l/arch/arm/mach-tegra/board-trimslice-pinmux.c.TEGRA 2011-05-19 00:06:34.000000000 -0400 ++++ linux-2.6.39.armv7l/arch/arm/mach-tegra/board-trimslice-pinmux.c 2011-08-16 01:16:35.194157025 -0400 +@@ -126,7 +126,7 @@ + {TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, +- {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, ++ {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_UAD, TEGRA_MUX_IRDA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_UCA, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_UCB, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, +--- linux-2.6.39.armv7l/arch/arm/mach-tegra/board-trimslice.c.TEGRA 2011-05-19 00:06:34.000000000 -0400 ++++ linux-2.6.39.armv7l/arch/arm/mach-tegra/board-trimslice.c 2011-08-16 01:25:44.679159239 -0400 +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -30,6 +31,8 @@ + + #include + #include ++#include ++#include + + #include "board.h" + #include "clock.h" +@@ -102,6 +105,68 @@ + } + subsys_initcall(tegra_trimslice_pci_init); + ++static struct tegra_utmip_config utmi_phy_config[] = { ++ [0] = { ++ .hssync_start_delay = 0, ++ .idle_wait_delay = 17, ++ .elastic_limit = 16, ++ .term_range_adj = 6, ++ .xcvr_setup = 15, ++ .xcvr_lsfslew = 2, ++ .xcvr_lsrslew = 2, ++ }, ++ [1] = { ++ .hssync_start_delay = 0, ++ .idle_wait_delay = 17, ++ .elastic_limit = 16, ++ .term_range_adj = 6, ++ .xcvr_setup = 8, ++ .xcvr_lsfslew = 2, ++ .xcvr_lsrslew = 2, ++ }, ++}; ++ ++static struct tegra_ehci_platform_data ehci1_data = { ++ .phy_config = &utmi_phy_config[0], ++ .operating_mode = TEGRA_USB_HOST, ++ .power_down_on_bus_suspend = 0, ++}; ++ ++struct tegra_ulpi_config ehci2_phy_config = { ++ .reset_gpio = TEGRA_GPIO_PV0, ++ .clk = "pll_m", ++}; ++ ++static struct tegra_ehci_platform_data ehci2_data = { ++ .operating_mode = TEGRA_USB_HOST, ++ .phy_config = &ehci2_phy_config, ++ .power_down_on_bus_suspend = 0, ++}; ++ ++static struct tegra_ehci_platform_data ehci3_data = { ++ .phy_config = &utmi_phy_config[1], ++ .operating_mode = TEGRA_USB_HOST, ++ .power_down_on_bus_suspend = 0, ++}; ++ ++static void trimslice_usb_init(void) ++{ ++ tegra_ehci3_device.dev.platform_data = &ehci3_data; ++ platform_device_register(&tegra_ehci3_device); ++ ++ tegra_gpio_enable(TEGRA_GPIO_PV0); ++ tegra_ehci2_device.dev.platform_data = &ehci2_data; ++ platform_device_register(&tegra_ehci2_device); ++ ++ tegra_gpio_enable(TEGRA_GPIO_PV2); ++ gpio_request(TEGRA_GPIO_PV2, "usb1 mode"); ++ gpio_direction_output(TEGRA_GPIO_PV2, 1); ++ ++ tegra_ehci1_device.dev.platform_data = &ehci1_data; ++ platform_device_register(&tegra_ehci1_device); ++} ++ ++ + static void __init tegra_trimslice_init(void) + { + tegra_clk_init_from_table(trimslice_clk_init_table); +@@ -112,8 +177,11 @@ + tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4; + + platform_add_devices(trimslice_devices, ARRAY_SIZE(trimslice_devices)); ++ ++ trimslice_usb_init(); + } + ++ + MACHINE_START(TRIMSLICE, "trimslice") + .boot_params = 0x00000100, + .fixup = tegra_trimslice_fixup, diff --git a/config-arm-tegra b/config-arm-tegra index c79efcf5b..67f1e3839 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -49,6 +49,7 @@ CONFIG_HW_PERF_EVENTS=y CONFIG_KEYBOARD_TEGRA=y # CONFIG_MPCORE_WATCHDOG is not set CONFIG_USB_EHCI_TEGRA=y +CONFIG_USB_STORAGE=y CONFIG_RTC_DRV_TEGRA=m CONFIG_SND_SOC_TEGRA=m diff --git a/kernel.spec b/kernel.spec index 81e2aa523..a6a04d8d7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -694,6 +694,8 @@ Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch # patch from http://www.delorie.com/tmp/arm-readl.patch Patch21002: arm-readl.patch +Patch21003: TEGRA-2.6.40.2-enable-USB-ports.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1135,6 +1137,7 @@ ApplyPatch linux-2.6.29-sparc-IOC_TYPECHECK.patch ApplyPatch arm-omap-dt-compat.patch ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch ApplyPatch arm-readl.patch +ApplyPatch TEGRA-2.6.40.2-enable-USB-ports.patch # # Exec shield @@ -1890,6 +1893,10 @@ fi # and build. %changelog +* Wed Aug 17 2011 Dennis Gilmore +- add patch to correctly initialise usb on trimslice systems +- build in usb-storage on tegra, internal ssd on trimslice is connected to usb + * Tue Aug 16 2011 Dennis Gilmore - add patch to work around gcc bug on arm From 449d91f7c4d661f77dfef54f2f40c9364dd20ff7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 19 Aug 2011 08:48:45 -0400 Subject: [PATCH 142/397] Add patch to fix race between cryptd and aesni (rhbz 721002) --- crypto-register-cryptd-first.patch | 26 ++++++++++++++++++++++++++ kernel.spec | 7 ++++++- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 crypto-register-cryptd-first.patch diff --git a/crypto-register-cryptd-first.patch b/crypto-register-cryptd-first.patch new file mode 100644 index 000000000..0cd55d6fc --- /dev/null +++ b/crypto-register-cryptd-first.patch @@ -0,0 +1,26 @@ +commit 9d4c522a113f6caa8b792ae829a25490fa87b1a2 +Author: Herbert Xu +Date: Fri Aug 19 16:11:23 2011 +0800 + + crypto: cryptd - Use subsys_initcall to prevent races with aesni + + As cryptd is depeneded on by other algorithms such as aesni-intel, + it needs to be registered before them. When everything is built + as modules, this occurs naturally. However, for this to work when + they are built-in, we need to use subsys_initcall in cryptd. + + Signed-off-by: Herbert Xu + +diff --git a/crypto/cryptd.c b/crypto/cryptd.c +index e46d21a..671d4d6 100644 +--- a/crypto/cryptd.c ++++ b/crypto/cryptd.c +@@ -945,7 +945,7 @@ static void __exit cryptd_exit(void) + crypto_unregister_template(&cryptd_tmpl); + } + +-module_init(cryptd_init); ++subsys_initcall(cryptd_init); + module_exit(cryptd_exit); + + MODULE_LICENSE("GPL"); diff --git a/kernel.spec b/kernel.spec index a6a04d8d7..20ae80c80 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 0 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -670,6 +670,7 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12022: fix-cdc-ncm-dma-stack-vars.patch Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch Patch12024: usb-add-quirk-for-logitech-webcams.patch +Patch12025: crypto-register-cryptd-first.patch # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch @@ -1253,6 +1254,7 @@ ApplyPatch add-appleir-usb-driver.patch ApplyPatch fix-cdc-ncm-dma-stack-vars.patch ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch +ApplyPatch crypto-register-cryptd-first.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -1893,6 +1895,9 @@ fi # and build. %changelog +* Fri Aug 19 2011 Josh Boyer +- Add patch to fix race between cryptd and aesni (rhbz 721002) + * Wed Aug 17 2011 Dennis Gilmore - add patch to correctly initialise usb on trimslice systems - build in usb-storage on tegra, internal ssd on trimslice is connected to usb From 2b8c61a6bf1fb98f1332d96b194440760b57f7b8 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 22 Aug 2011 10:23:01 -0400 Subject: [PATCH 143/397] Avoid false quiescent states in rcutree with CONFIG_RCU_FAST_NO_HZ. (rhbz 577968) --- kernel.spec | 8 +++ rcutree-avoid-false-quiescent-states.patch | 67 ++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 rcutree-avoid-false-quiescent-states.patch diff --git a/kernel.spec b/kernel.spec index 20ae80c80..f47298f10 100644 --- a/kernel.spec +++ b/kernel.spec @@ -658,6 +658,8 @@ Patch2899: linux-2.6-v4l-dvb-fixes.patch Patch2900: linux-2.6-v4l-dvb-update.patch Patch2901: linux-2.6-v4l-dvb-experimental.patch +Patch3000: rcutree-avoid-false-quiescent-states.patch + # fs fixes # NFSv4 @@ -1246,6 +1248,9 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-fixes.patch ApplyOptionalPatch linux-2.6-v4l-dvb-update.patch ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch +# Avoid false quiescent states in rcu. +ApplyPatch rcutree-avoid-false-quiescent-states.patch + # Patches headed upstream ApplyPatch disable-i8042-check-on-apple-mac.patch @@ -1895,6 +1900,9 @@ fi # and build. %changelog +* Mon Aug 22 2011 Dave Jones +- Avoid false quiescent states in rcutree with CONFIG_RCU_FAST_NO_HZ. (rhbz 577968) + * Fri Aug 19 2011 Josh Boyer - Add patch to fix race between cryptd and aesni (rhbz 721002) diff --git a/rcutree-avoid-false-quiescent-states.patch b/rcutree-avoid-false-quiescent-states.patch new file mode 100644 index 000000000..9c7ffea34 --- /dev/null +++ b/rcutree-avoid-false-quiescent-states.patch @@ -0,0 +1,67 @@ +diff --git a/kernel/rcutree.c b/kernel/rcutree.c +index ba06207..c38a882 100644 +--- a/kernel/rcutree.c ++++ b/kernel/rcutree.c +@@ -1476,9 +1476,6 @@ static void rcu_process_callbacks(struct softirq_action *unused) + &__get_cpu_var(rcu_sched_data)); + __rcu_process_callbacks(&rcu_bh_state, &__get_cpu_var(rcu_bh_data)); + rcu_preempt_process_callbacks(); +- +- /* If we are last CPU on way to dyntick-idle mode, accelerate it. */ +- rcu_needs_cpu_flush(); + } + + /* +diff --git a/kernel/rcutree.h b/kernel/rcutree.h +index 01b2ccd..795f7fc 100644 +--- a/kernel/rcutree.h ++++ b/kernel/rcutree.h +@@ -450,7 +450,6 @@ static int rcu_preempt_needs_cpu(int cpu); + static void __cpuinit rcu_preempt_init_percpu_data(int cpu); + static void rcu_preempt_send_cbs_to_online(void); + static void __init __rcu_init_preempt(void); +-static void rcu_needs_cpu_flush(void); + static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags); + static void rcu_preempt_boost_start_gp(struct rcu_node *rnp); + static void invoke_rcu_callbacks_kthread(void); +diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h +index 8aafbb8..b0254de 100644 +--- a/kernel/rcutree_plugin.h ++++ b/kernel/rcutree_plugin.h +@@ -1907,15 +1907,6 @@ int rcu_needs_cpu(int cpu) + return rcu_needs_cpu_quick_check(cpu); + } + +-/* +- * Check to see if we need to continue a callback-flush operations to +- * allow the last CPU to enter dyntick-idle mode. But fast dyntick-idle +- * entry is not configured, so we never do need to. +- */ +-static void rcu_needs_cpu_flush(void) +-{ +-} +- + #else /* #if !defined(CONFIG_RCU_FAST_NO_HZ) */ + + #define RCU_NEEDS_CPU_FLUSHES 5 +@@ -1991,20 +1982,4 @@ int rcu_needs_cpu(int cpu) + return c; + } + +-/* +- * Check to see if we need to continue a callback-flush operations to +- * allow the last CPU to enter dyntick-idle mode. +- */ +-static void rcu_needs_cpu_flush(void) +-{ +- int cpu = smp_processor_id(); +- unsigned long flags; +- +- if (per_cpu(rcu_dyntick_drain, cpu) <= 0) +- return; +- local_irq_save(flags); +- (void)rcu_needs_cpu(cpu); +- local_irq_restore(flags); +-} +- + #endif /* #else #if !defined(CONFIG_RCU_FAST_NO_HZ) */ From a6590c7efed36d7e43b7623ff01088ce5d7d570f Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 22 Aug 2011 14:15:03 -0400 Subject: [PATCH 144/397] Update to 3.0.3-final --- kernel.spec | 9 +++++---- sources | 3 +-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel.spec b/kernel.spec index f47298f10..6b90d3c45 100644 --- a/kernel.spec +++ b/kernel.spec @@ -581,8 +581,7 @@ Source1000: config-local # Here should be only the patches up to the upstream canonical Linus tree. Patch00: patch-3.0.bz2 -Patch01: patch-3.0.2.bz2 -Patch02: patch-3.0.3-rc1.gz +Patch01: patch-3.0.3.bz2 # we also need compile fixes for -vanilla Patch04: linux-2.6-compile-fixes.patch @@ -1111,8 +1110,7 @@ done # Update vanilla to the latest upstream. (2.6.39 -> 3.0) ApplyPatch patch-3.0.bz2 -ApplyPatch patch-3.0.2.bz2 -ApplyPatch patch-3.0.3-rc1.gz +ApplyPatch patch-3.0.3.bz2 ApplyPatch linux-2.6-makefile-after_link.patch @@ -1900,6 +1898,9 @@ fi # and build. %changelog +* Mon Aug 22 2011 Chuck Ebbert +- Update to 3.0.3-final + * Mon Aug 22 2011 Dave Jones - Avoid false quiescent states in rcutree with CONFIG_RCU_FAST_NO_HZ. (rhbz 577968) diff --git a/sources b/sources index 4ed2072c0..2bb7b1b7c 100644 --- a/sources +++ b/sources @@ -1,4 +1,3 @@ 1aab7a741abe08d42e8eccf20de61e05 linux-2.6.39.tar.bz2 df5790b51f218fc5e5463162b26afbfc patch-3.0.bz2 -f5743283e6075282cebfbde62e65240b patch-3.0.2.bz2 -23b4aad2d34ea209f62b199e67a88240 patch-3.0.3-rc1.gz +1757786b9a9ffbd48ad9642199ff5bd7 patch-3.0.3.bz2 From 3f743de566ab5bc0ba6126cfa9466faad4f40543 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 22 Aug 2011 17:09:03 -0400 Subject: [PATCH 145/397] Revert 'iwlwifi: advertise max aggregate size'. (rhbz 708747) --- iwlagn-revert-max-aggregate-size.patch | 13 +++++++++++++ kernel.spec | 5 +++++ 2 files changed, 18 insertions(+) create mode 100644 iwlagn-revert-max-aggregate-size.patch diff --git a/iwlagn-revert-max-aggregate-size.patch b/iwlagn-revert-max-aggregate-size.patch new file mode 100644 index 000000000..d9e9a8db4 --- /dev/null +++ b/iwlagn-revert-max-aggregate-size.patch @@ -0,0 +1,13 @@ +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c +index b0ae4de..afa00ec 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn.c +@@ -2140,8 +2140,6 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, + IEEE80211_HW_SPECTRUM_MGMT | + IEEE80211_HW_REPORTS_TX_ACK_STATUS; + +- hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF; +- + hw->flags |= IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_SUPPORTS_DYNAMIC_PS; + diff --git a/kernel.spec b/kernel.spec index 6b90d3c45..80480a331 100644 --- a/kernel.spec +++ b/kernel.spec @@ -683,6 +683,7 @@ Patch13001: epoll-fix-spurious-lockdep-warnings.patch Patch13002: hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch Patch13010: iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch +Patch13011: iwlagn-revert-max-aggregate-size.patch Patch20000: utrace.patch @@ -1267,6 +1268,7 @@ ApplyPatch epoll-fix-spurious-lockdep-warnings.patch ApplyPatch hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch ApplyPatch iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch +ApplyPatch iwlagn-revert-max-aggregate-size.patch ApplyPatch utrace.patch @@ -1898,6 +1900,9 @@ fi # and build. %changelog +* Mon Aug 22 2011 Dave Jones +- Revert 'iwlwifi: advertise max aggregate size'. (rhbz 708747) + * Mon Aug 22 2011 Chuck Ebbert - Update to 3.0.3-final From 98ae7131a4a22a1da7777a9da887121b82b77d29 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 23 Aug 2011 14:16:32 +1000 Subject: [PATCH 146/397] nouveau: pull some patches from 3.1 to fix some hibernate/suspend issues --- drm-nouveau-updates.patch | 461 +++++++++++++++++++++++++++++++++++++- 1 file changed, 460 insertions(+), 1 deletion(-) diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index 607602cfc..651cc4ac3 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -1 +1,460 @@ -nil + drivers/gpu/drm/nouveau/nouveau_drv.c | 11 ++- + drivers/gpu/drm/nouveau/nouveau_drv.h | 3 +- + drivers/gpu/drm/nouveau/nouveau_state.c | 4 +- + drivers/gpu/drm/nouveau/nv04_graph.c | 22 ++---- + drivers/gpu/drm/nouveau/nv10_graph.c | 15 +++-- + drivers/gpu/drm/nouveau/nv20_graph.c | 11 ++- + drivers/gpu/drm/nouveau/nv40_graph.c | 112 ++++++------------------------- + drivers/gpu/drm/nouveau/nv40_mpeg.c | 2 +- + drivers/gpu/drm/nouveau/nv50_graph.c | 9 ++- + drivers/gpu/drm/nouveau/nv50_mpeg.c | 2 +- + drivers/gpu/drm/nouveau/nv84_crypt.c | 2 +- + drivers/gpu/drm/nouveau/nva3_copy.c | 2 +- + drivers/gpu/drm/nouveau/nvc0_copy.c | 2 +- + drivers/gpu/drm/nouveau/nvc0_graph.c | 2 +- + 14 files changed, 68 insertions(+), 131 deletions(-) + +diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c +index 02c6f37..4e1a360 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_drv.c ++++ b/drivers/gpu/drm/nouveau/nouveau_drv.c +@@ -210,10 +210,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) + pfifo->unload_context(dev); + + for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) { +- if (dev_priv->eng[e]) { +- ret = dev_priv->eng[e]->fini(dev, e); +- if (ret) +- goto out_abort; ++ if (!dev_priv->eng[e]) ++ continue; ++ ++ ret = dev_priv->eng[e]->fini(dev, e, true); ++ if (ret) { ++ NV_ERROR(dev, "... engine %d failed: %d\n", i, ret); ++ goto out_abort; + } + } + +diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h +index 9c56331..82d6295 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_drv.h ++++ b/drivers/gpu/drm/nouveau/nouveau_drv.h +@@ -297,7 +297,7 @@ struct nouveau_channel { + struct nouveau_exec_engine { + void (*destroy)(struct drm_device *, int engine); + int (*init)(struct drm_device *, int engine); +- int (*fini)(struct drm_device *, int engine); ++ int (*fini)(struct drm_device *, int engine, bool suspend); + int (*context_new)(struct nouveau_channel *, int engine); + void (*context_del)(struct nouveau_channel *, int engine); + int (*object_new)(struct nouveau_channel *, int engine, +@@ -1120,7 +1120,6 @@ extern int nvc0_fifo_unload_context(struct drm_device *); + + /* nv04_graph.c */ + extern int nv04_graph_create(struct drm_device *); +-extern void nv04_graph_fifo_access(struct drm_device *, bool); + extern int nv04_graph_object_new(struct nouveau_channel *, int, u32, u16); + extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data); +diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c +index 731acea..e65e71b 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_state.c ++++ b/drivers/gpu/drm/nouveau/nouveau_state.c +@@ -682,7 +682,7 @@ out_engine: + for (e = e - 1; e >= 0; e--) { + if (!dev_priv->eng[e]) + continue; +- dev_priv->eng[e]->fini(dev, e); ++ dev_priv->eng[e]->fini(dev, e, false); + dev_priv->eng[e]->destroy(dev,e ); + } + } +@@ -727,7 +727,7 @@ static void nouveau_card_takedown(struct drm_device *dev) + engine->fifo.takedown(dev); + for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) { + if (dev_priv->eng[e]) { +- dev_priv->eng[e]->fini(dev, e); ++ dev_priv->eng[e]->fini(dev, e, false); + dev_priv->eng[e]->destroy(dev,e ); + } + } +diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c +index 3626ee7..dbdea8e 100644 +--- a/drivers/gpu/drm/nouveau/nv04_graph.c ++++ b/drivers/gpu/drm/nouveau/nv04_graph.c +@@ -450,13 +450,13 @@ nv04_graph_context_del(struct nouveau_channel *chan, int engine) + unsigned long flags; + + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); +- nv04_graph_fifo_access(dev, false); ++ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); + + /* Unload the context if it's the currently active one */ + if (nv04_graph_channel(dev) == chan) + nv04_graph_unload_context(dev); + +- nv04_graph_fifo_access(dev, true); ++ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + /* Free the context resources */ +@@ -538,24 +538,18 @@ nv04_graph_init(struct drm_device *dev, int engine) + } + + static int +-nv04_graph_fini(struct drm_device *dev, int engine) ++nv04_graph_fini(struct drm_device *dev, int engine, bool suspend) + { ++ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); ++ if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { ++ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); ++ return -EBUSY; ++ } + nv04_graph_unload_context(dev); + nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); + return 0; + } + +-void +-nv04_graph_fifo_access(struct drm_device *dev, bool enabled) +-{ +- if (enabled) +- nv_wr32(dev, NV04_PGRAPH_FIFO, +- nv_rd32(dev, NV04_PGRAPH_FIFO) | 1); +- else +- nv_wr32(dev, NV04_PGRAPH_FIFO, +- nv_rd32(dev, NV04_PGRAPH_FIFO) & ~1); +-} +- + static int + nv04_graph_mthd_set_ref(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c +index 0930c6c..7255e4a 100644 +--- a/drivers/gpu/drm/nouveau/nv10_graph.c ++++ b/drivers/gpu/drm/nouveau/nv10_graph.c +@@ -708,8 +708,8 @@ static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan, + 0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c); + nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst); + nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); +- nv04_graph_fifo_access(dev, true); +- nv04_graph_fifo_access(dev, false); ++ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); ++ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); + + /* Restore the FIFO state */ + for (i = 0; i < ARRAY_SIZE(fifo); i++) +@@ -879,13 +879,13 @@ nv10_graph_context_del(struct nouveau_channel *chan, int engine) + unsigned long flags; + + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); +- nv04_graph_fifo_access(dev, false); ++ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); + + /* Unload the context if it's the currently active one */ + if (nv10_graph_channel(dev) == chan) + nv10_graph_unload_context(dev); + +- nv04_graph_fifo_access(dev, true); ++ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + /* Free the context resources */ +@@ -957,8 +957,13 @@ nv10_graph_init(struct drm_device *dev, int engine) + } + + static int +-nv10_graph_fini(struct drm_device *dev, int engine) ++nv10_graph_fini(struct drm_device *dev, int engine, bool suspend) + { ++ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); ++ if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { ++ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); ++ return -EBUSY; ++ } + nv10_graph_unload_context(dev); + nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); + return 0; +diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c +index affc7d7..b6cf157 100644 +--- a/drivers/gpu/drm/nouveau/nv20_graph.c ++++ b/drivers/gpu/drm/nouveau/nv20_graph.c +@@ -454,13 +454,13 @@ nv20_graph_context_del(struct nouveau_channel *chan, int engine) + unsigned long flags; + + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); +- nv04_graph_fifo_access(dev, false); ++ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); + + /* Unload the context if it's the currently active one */ + if (nv10_graph_channel(dev) == chan) + nv20_graph_unload_context(dev); + +- nv04_graph_fifo_access(dev, true); ++ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + /* Free the context resources */ +@@ -654,8 +654,13 @@ nv30_graph_init(struct drm_device *dev, int engine) + } + + int +-nv20_graph_fini(struct drm_device *dev, int engine) ++nv20_graph_fini(struct drm_device *dev, int engine, bool suspend) + { ++ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); ++ if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { ++ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); ++ return -EBUSY; ++ } + nv20_graph_unload_context(dev); + nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); + return 0; +diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c +index 5beb01b..ba14a93 100644 +--- a/drivers/gpu/drm/nouveau/nv40_graph.c ++++ b/drivers/gpu/drm/nouveau/nv40_graph.c +@@ -35,89 +35,6 @@ struct nv40_graph_engine { + u32 grctx_size; + }; + +-static struct nouveau_channel * +-nv40_graph_channel(struct drm_device *dev) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpuobj *grctx; +- uint32_t inst; +- int i; +- +- inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); +- if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) +- return NULL; +- inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4; +- +- for (i = 0; i < dev_priv->engine.fifo.channels; i++) { +- if (!dev_priv->channels.ptr[i]) +- continue; +- +- grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR]; +- if (grctx && grctx->pinst == inst) +- return dev_priv->channels.ptr[i]; +- } +- +- return NULL; +-} +- +-static int +-nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) +-{ +- uint32_t old_cp, tv = 1000, tmp; +- int i; +- +- old_cp = nv_rd32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER); +- nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); +- +- tmp = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0310); +- tmp |= save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE : +- NV40_PGRAPH_CTXCTL_0310_XFER_LOAD; +- nv_wr32(dev, NV40_PGRAPH_CTXCTL_0310, tmp); +- +- tmp = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0304); +- tmp |= NV40_PGRAPH_CTXCTL_0304_XFER_CTX; +- nv_wr32(dev, NV40_PGRAPH_CTXCTL_0304, tmp); +- +- nouveau_wait_for_idle(dev); +- +- for (i = 0; i < tv; i++) { +- if (nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C) == 0) +- break; +- } +- +- nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp); +- +- if (i == tv) { +- uint32_t ucstat = nv_rd32(dev, NV40_PGRAPH_CTXCTL_UCODE_STAT); +- NV_ERROR(dev, "Failed: Instance=0x%08x Save=%d\n", inst, save); +- NV_ERROR(dev, "IP: 0x%02x, Opcode: 0x%08x\n", +- ucstat >> NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT, +- ucstat & NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK); +- NV_ERROR(dev, "0x40030C = 0x%08x\n", +- nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C)); +- return -EBUSY; +- } +- +- return 0; +-} +- +-static int +-nv40_graph_unload_context(struct drm_device *dev) +-{ +- uint32_t inst; +- int ret; +- +- inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); +- if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) +- return 0; +- inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE; +- +- ret = nv40_graph_transfer_context(dev, inst, 1); +- +- nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst); +- return ret; +-} +- + static int + nv40_graph_context_new(struct nouveau_channel *chan, int engine) + { +@@ -163,16 +80,16 @@ nv40_graph_context_del(struct nouveau_channel *chan, int engine) + struct nouveau_gpuobj *grctx = chan->engctx[engine]; + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 inst = 0x01000000 | (grctx->pinst >> 4); + unsigned long flags; + + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); +- nv04_graph_fifo_access(dev, false); +- +- /* Unload the context if it's the currently active one */ +- if (nv40_graph_channel(dev) == chan) +- nv40_graph_unload_context(dev); +- +- nv04_graph_fifo_access(dev, true); ++ nv_mask(dev, 0x400720, 0x00000000, 0x00000001); ++ if (nv_rd32(dev, 0x40032c) == inst) ++ nv_mask(dev, 0x40032c, 0x01000000, 0x00000000); ++ if (nv_rd32(dev, 0x400330) == inst) ++ nv_mask(dev, 0x400330, 0x01000000, 0x00000000); ++ nv_mask(dev, 0x400720, 0x00000001, 0x00000001); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + /* Free the context resources */ +@@ -429,9 +346,20 @@ nv40_graph_init(struct drm_device *dev, int engine) + } + + static int +-nv40_graph_fini(struct drm_device *dev, int engine) ++nv40_graph_fini(struct drm_device *dev, int engine, bool suspend) + { +- nv40_graph_unload_context(dev); ++ u32 inst = nv_rd32(dev, 0x40032c); ++ if (inst & 0x01000000) { ++ nv_wr32(dev, 0x400720, 0x00000000); ++ nv_wr32(dev, 0x400784, inst); ++ nv_mask(dev, 0x400310, 0x00000020, 0x00000020); ++ nv_mask(dev, 0x400304, 0x00000001, 0x00000001); ++ if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000)) { ++ u32 insn = nv_rd32(dev, 0x400308); ++ NV_ERROR(dev, "PGRAPH: ctxprog timeout 0x%08x\n", insn); ++ } ++ nv_mask(dev, 0x40032c, 0x01000000, 0x00000000); ++ } + return 0; + } + +diff --git a/drivers/gpu/drm/nouveau/nv40_mpeg.c b/drivers/gpu/drm/nouveau/nv40_mpeg.c +index 6d2af29..ad03a0e 100644 +--- a/drivers/gpu/drm/nouveau/nv40_mpeg.c ++++ b/drivers/gpu/drm/nouveau/nv40_mpeg.c +@@ -137,7 +137,7 @@ nv40_mpeg_init(struct drm_device *dev, int engine) + } + + static int +-nv40_mpeg_fini(struct drm_device *dev, int engine) ++nv40_mpeg_fini(struct drm_device *dev, int engine, bool suspend) + { + /*XXX: context save? */ + nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); +diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c +index e25cbb4..d27dcf0 100644 +--- a/drivers/gpu/drm/nouveau/nv50_graph.c ++++ b/drivers/gpu/drm/nouveau/nv50_graph.c +@@ -125,7 +125,6 @@ static void + nv50_graph_init_reset(struct drm_device *dev) + { + uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21); +- + NV_DEBUG(dev, "\n"); + + nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e); +@@ -255,9 +254,13 @@ nv50_graph_init(struct drm_device *dev, int engine) + } + + static int +-nv50_graph_fini(struct drm_device *dev, int engine) ++nv50_graph_fini(struct drm_device *dev, int engine, bool suspend) + { +- NV_DEBUG(dev, "\n"); ++ nv_mask(dev, 0x400500, 0x00010001, 0x00000000); ++ if (!nv_wait(dev, 0x400700, ~0, 0) && suspend) { ++ nv_mask(dev, 0x400500, 0x00010001, 0x00010001); ++ return -EBUSY; ++ } + nv50_graph_unload_context(dev); + nv_wr32(dev, 0x40013c, 0x00000000); + return 0; +diff --git a/drivers/gpu/drm/nouveau/nv50_mpeg.c b/drivers/gpu/drm/nouveau/nv50_mpeg.c +index 1dc5913..b57a2d1 100644 +--- a/drivers/gpu/drm/nouveau/nv50_mpeg.c ++++ b/drivers/gpu/drm/nouveau/nv50_mpeg.c +@@ -160,7 +160,7 @@ nv50_mpeg_init(struct drm_device *dev, int engine) + } + + static int +-nv50_mpeg_fini(struct drm_device *dev, int engine) ++nv50_mpeg_fini(struct drm_device *dev, int engine, bool suspend) + { + /*XXX: context save for s/r */ + nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); +diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c +index 75b809a..edece9c 100644 +--- a/drivers/gpu/drm/nouveau/nv84_crypt.c ++++ b/drivers/gpu/drm/nouveau/nv84_crypt.c +@@ -138,7 +138,7 @@ nv84_crypt_isr(struct drm_device *dev) + } + + static int +-nv84_crypt_fini(struct drm_device *dev, int engine) ++nv84_crypt_fini(struct drm_device *dev, int engine, bool suspend) + { + nv_wr32(dev, 0x102140, 0x00000000); + return 0; +diff --git a/drivers/gpu/drm/nouveau/nva3_copy.c b/drivers/gpu/drm/nouveau/nva3_copy.c +index b86820a..8f356d5 100644 +--- a/drivers/gpu/drm/nouveau/nva3_copy.c ++++ b/drivers/gpu/drm/nouveau/nva3_copy.c +@@ -140,7 +140,7 @@ nva3_copy_init(struct drm_device *dev, int engine) + } + + static int +-nva3_copy_fini(struct drm_device *dev, int engine) ++nva3_copy_fini(struct drm_device *dev, int engine, bool suspend) + { + nv_mask(dev, 0x104048, 0x00000003, 0x00000000); + +diff --git a/drivers/gpu/drm/nouveau/nvc0_copy.c b/drivers/gpu/drm/nouveau/nvc0_copy.c +index 208fa7a..4d58c33 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_copy.c ++++ b/drivers/gpu/drm/nouveau/nvc0_copy.c +@@ -127,7 +127,7 @@ nvc0_copy_init(struct drm_device *dev, int engine) + } + + static int +-nvc0_copy_fini(struct drm_device *dev, int engine) ++nvc0_copy_fini(struct drm_device *dev, int engine, bool suspend) + { + struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); + +diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c +index ca6db20..69c6522 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_graph.c ++++ b/drivers/gpu/drm/nouveau/nvc0_graph.c +@@ -248,7 +248,7 @@ nvc0_graph_object_new(struct nouveau_channel *chan, int engine, + } + + static int +-nvc0_graph_fini(struct drm_device *dev, int engine) ++nvc0_graph_fini(struct drm_device *dev, int engine, bool suspend) + { + return 0; + } From 7acacb7383940633b80988b30578ff5d9e2244e4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 23 Aug 2011 14:17:55 +1000 Subject: [PATCH 147/397] oops, add the spec file.. --- kernel.spec | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel.spec b/kernel.spec index 80480a331..88dc05654 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1900,6 +1900,9 @@ fi # and build. %changelog +* Tue Aug 23 2011 Ben Skeggs +- nouveau: pull patches from 3.1 to fix some suspend/hibernate problems (rhbz#730582) + * Mon Aug 22 2011 Dave Jones - Revert 'iwlwifi: advertise max aggregate size'. (rhbz 708747) From 8728f9c48f2cd17126ec2906ab6b3cb007d7d14f Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 24 Aug 2011 16:07:37 -0400 Subject: [PATCH 148/397] Automate the kernel version faking. --- kernel.spec | 177 ++++++++++++++++------------------------------------ 1 file changed, 53 insertions(+), 124 deletions(-) diff --git a/kernel.spec b/kernel.spec index 88dc05654..419093b33 100644 --- a/kernel.spec +++ b/kernel.spec @@ -3,11 +3,6 @@ Summary: The Linux kernel -# For a stable, released kernel, released_kernel should be 1. For rawhide -# and/or a kernel built from an rc or git snapshot, released_kernel should -# be 0. -%global released_kernel 1 - # Save original buildid for later if it's defined %if 0%{?buildid:1} %global orig_buildid %{buildid} @@ -44,24 +39,16 @@ Summary: The Linux kernel # # We used to have some extra magic weirdness to bump this automatically, # but now we don't. Just use: rpmdev-bumpspec -c 'comment for changelog' -# When changing base_sublevel below or going from rc to a final kernel, -# reset this by hand to 1 (or to 0 and then use rpmdev-bumpspec). -# scripts/rebase.sh should be made to do that for you, actually. -# -# For non-released -rc kernels, this will be prepended with "0.", so -# for example a 3 here will become 0.3 +# When changing real_sublevel below, reset this by hand to 1 +# (or to 0 and then use rpmdev-bumpspec). # %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 39 -%define fake_sublevel 40 - -## If this is a released kernel ## -%if 0%{?released_kernel} +# real_sublevel is the 3.x kernel version we're starting with +%define real_sublevel 0 +# fake_sublevel is the 2.6.x version we're faking +%define fake_sublevel %(echo $((40 + %{real_sublevel}))) # Do we have a -stable update to apply? %define stable_update 3 @@ -78,9 +65,6 @@ Summary: The Linux kernel %endif %define rpmversion 2.6.%{fake_sublevel}%{?stablerev} -%endif -# Nb: The above rcrev and gitrev values automagically define Patch00 and Patch01 below. - # What parts do we want to build? We must build at least one kernel. # These are the kernels that are built IF the architecture allows it. # All should default to 1 (enabled) and be flipped to 0 (disabled) @@ -119,11 +103,7 @@ Summary: The Linux kernel # Build the kernel-doc package, but don't fail the build if it botches. # Here "true" means "continue" and "false" means "fail the build". -%if 0%{?released_kernel} %define doc_build_fail false -%else -%define doc_build_fail true -%endif %define rawhide_skip_docs 0 %if 0%{?rawhide_skip_docs} @@ -154,33 +134,15 @@ Summary: The Linux kernel %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} # pkg_release is what we'll fill in for the rpm Release: field -%if 0%{?released_kernel} %if 0%{?stable_rc} %define stable_rctag .rc%{stable_rc} %endif %define pkg_release %{fedora_build}%{?stable_rctag}%{?buildid}%{?dist} -%else - -# non-released_kernel -%if 0%{?rcrev} -%define rctag .rc%rcrev -%else -%define rctag .rc0 -%endif -%if 0%{?gitrev} -%define gittag .git%gitrev -%else -%define gittag .git0 -%endif -%define pkg_release 0%{?rctag}%{?gittag}.%{fedora_build}%{?buildid}%{?dist} - -%endif - # The kernel tarball/base version -# % define kversion 3.%{base_sublevel} -%define kversion 2.6.%{base_sublevel} +%define realversion 3.%{real_sublevel} +%define fakeversion 2.6.%{fake_sublevel} %define make_target bzImage @@ -541,8 +503,7 @@ BuildRequires: rpm-build >= 4.4.2.1-4 %define debuginfo_args --strict-build-id %endif -Source0: ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-%{kversion}.tar.bz2 -#Source0: ftp://ftp.kernel.org/pub/linux/kernel/v3.0/linux-3.0-rc5.tar.bz2 +Source0: ftp://ftp.kernel.org/pub/linux/kernel/v3.x/linux-%{realversion}.tar.bz2 Source11: genkey Source14: find-provides @@ -580,8 +541,17 @@ Source1000: config-local # Here should be only the patches up to the upstream canonical Linus tree. -Patch00: patch-3.0.bz2 -Patch01: patch-3.0.3.bz2 +# For a stable release kernel +%if 0%{?stable_update} +%if 0%{?stable_base} +%define stable_patch_00 patch-3.%{real_sublevel}.%{stable_base}.bz2 +Patch00: %{stable_patch_00} +%endif +%if 0%{?stable_rc} +%define stable_patch_01 patch-3.%{real_sublevel}.%{stable_update}-rc%{stable_rc}.bz2 +Patch01: %{stable_patch_01} +%endif +%endif # we also need compile fixes for -vanilla Patch04: linux-2.6-compile-fixes.patch @@ -819,7 +789,8 @@ AutoReqProv: no\ Requires(pre): /usr/bin/find\ Requires: perl\ %description -n kernel%{?variant}%{?1:-%{1}}-devel\ -This package provides kernel headers and makefiles sufficient to build modules\ +This package provides kernel headers and +makefiles sufficient to build modules\ against the %{?2:%{2} }kernel package.\ %{nil} @@ -978,46 +949,24 @@ ApplyOptionalPatch() # which speeds things up quite a bit. # Update to latest upstream. -%if 0%{?released_kernel} -%define vanillaversion 2.6.%{base_sublevel} -# non-released_kernel case -%else -%if 0%{?rcrev} -%define vanillaversion 2.6.%{upstream_sublevel}-rc%{rcrev} -%if 0%{?gitrev} -%define vanillaversion 2.6.%{upstream_sublevel}-rc%{rcrev}-git%{gitrev} -%endif -%else -# pre-{base_sublevel+1}-rc1 case -%if 0%{?gitrev} -%define vanillaversion 2.6.%{base_sublevel}-git%{gitrev} -%else -%define vanillaversion 2.6.%{base_sublevel} -%endif -%endif -%endif - -# %%{vanillaversion} : the full version name, e.g. 2.6.35-rc6-git3 -# %%{kversion} : the base version, e.g. 2.6.34 - -# Use kernel-%%{kversion}%%{?dist} as the top-level directory name +# Use kernel-%%{fakeversion}%%{?dist} as the top-level directory name # so we can prep different trees within a single git directory. # Build a list of the other top-level kernel tree directories. # This will be used to hardlink identical vanilla subdirs. sharedirs=$(find "$PWD" -maxdepth 1 -type d -name 'kernel-3.*' \ - | grep -x -v "$PWD"/kernel-%{kversion}%{?dist}) ||: + | grep -x -v "$PWD"/kernel-%{fakeversion}%{?dist}) ||: -if [ ! -d kernel-%{kversion}%{?dist}/vanilla-%{vanillaversion} ]; then +if [ ! -d kernel-%{fakeversion}%{?dist}/vanilla-%{realversion} ]; then - if [ -d kernel-%{kversion}%{?dist}/vanilla-%{kversion} ]; then + if [ -d kernel-%{fakeversion}%{?dist}/vanilla-%{realversion} ]; then # The base vanilla version already exists. - cd kernel-%{kversion}%{?dist} + cd kernel-%{fakeversion}%{?dist} # Any vanilla-* directories other than the base one are stale. for dir in vanilla-*; do - [ "$dir" = vanilla-%{kversion} ] || rm -rf $dir & + [ "$dir" = vanilla-%{realversion} ] || rm -rf $dir & done else @@ -1025,58 +974,39 @@ if [ ! -d kernel-%{kversion}%{?dist}/vanilla-%{vanillaversion} ]; then rm -f pax_global_header # Look for an identical base vanilla dir that can be hardlinked. for sharedir in $sharedirs ; do - if [[ ! -z $sharedir && -d $sharedir/vanilla-%{kversion} ]] ; then + if [[ ! -z $sharedir && -d $sharedir/vanilla-%{realversion} ]] ; then break fi done - if [[ ! -z $sharedir && -d $sharedir/vanilla-%{kversion} ]] ; then -%setup -q -n kernel-%{kversion}%{?dist} -c -T - cp -rl $sharedir/vanilla-%{kversion} . + if [[ ! -z $sharedir && -d $sharedir/vanilla-%{realversion} ]] ; then +%setup -q -n kernel-%{fakeversion}%{?dist} -c -T + cp -rl $sharedir/vanilla-%{realversion} . else -%setup -q -n kernel-%{kversion}%{?dist} -c - mv linux-%{kversion} vanilla-%{kversion} +%setup -q -n kernel-%{fakeversion}%{?dist} -c + mv linux-%{realversion} vanilla-%{realversion} fi fi -%if "%{kversion}" != "%{vanillaversion}" - - for sharedir in $sharedirs ; do - if [[ ! -z $sharedir && -d $sharedir/vanilla-%{vanillaversion} ]] ; then - break - fi - done - if [[ ! -z $sharedir && -d $sharedir/vanilla-%{vanillaversion} ]] ; then - - cp -rl $sharedir/vanilla-%{vanillaversion} . - - else - - # Need to apply patches to the base vanilla version. - cp -rl vanilla-%{kversion} vanilla-%{vanillaversion} - fi - -%endif - else # We already have all vanilla dirs, just change to the top-level directory. - cd kernel-%{kversion}%{?dist} + cd kernel-%{fakeversion}%{?dist} fi # Now build the fedora kernel tree. -if [ -d linux-%{kversion}.%{_target_cpu} ]; then +if [ -d linux-%{fakeversion}.%{_target_cpu} ]; then # Just in case we ctrl-c'd a prep already rm -rf deleteme.%{_target_cpu} # Move away the stale away, and delete in background. - mv linux-%{kversion}.%{_target_cpu} deleteme.%{_target_cpu} + mv linux-%{fakeversion}.%{_target_cpu} deleteme.%{_target_cpu} rm -rf deleteme.%{_target_cpu} & fi -cp -rl vanilla-%{vanillaversion} linux-%{kversion}.%{_target_cpu} +cp -rl vanilla-%{realversion} linux-%{fakeversion}.%{_target_cpu} -cd linux-%{kversion}.%{_target_cpu} +cd linux-%{fakeversion}.%{_target_cpu} %if %{using_upstream_branch} ### BRANCH APPLY ### @@ -1109,9 +1039,13 @@ do done %endif -# Update vanilla to the latest upstream. (2.6.39 -> 3.0) -ApplyPatch patch-3.0.bz2 -ApplyPatch patch-3.0.3.bz2 +# released_kernel with possible stable updates +%if 0%{?stable_base} +ApplyPatch %{stable_patch_00} +%endif +%if 0%{?stable_rc} +ApplyPatch %{stable_patch_01} +%endif ApplyPatch linux-2.6-makefile-after_link.patch @@ -1377,15 +1311,7 @@ BuildKernel() { perl -p -i -e "s/^EXTRAVERSION.*/EXTRAVERSION = %{?stablerev}-%{release}.%{_target_cpu}${Flavour:+.${Flavour}}/" Makefile perl -p -i -e 's/^VERSION.*/VERSION = 2/' Makefile perl -p -i -e 's/^PATCHLEVEL.*/PATCHLEVEL = 6/' Makefile - perl -p -i -e 's/^SUBLEVEL.*/SUBLEVEL = 40/' Makefile - - # if pre-rc1 devel kernel, must fix up SUBLEVEL for our versioning scheme - ### XXX this will probably be dead code in 3.0 --kyle - %if !0%{?rcrev} - %if 0%{?gitrev} - perl -p -i -e 's/^SUBLEVEL.*/SUBLEVEL = %{upstream_sublevel}/' Makefile - %endif - %endif + perl -p -i -e 's/^SUBLEVEL.*/SUBLEVEL = %{fake_sublevel}/' Makefile # and now to start the build process @@ -1563,7 +1489,7 @@ rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT/boot mkdir -p $RPM_BUILD_ROOT%{_libexecdir} -cd linux-%{kversion}.%{_target_cpu} +cd linux-%{fakeversion}.%{_target_cpu} %if %{with_debug} BuildKernel %make_target %kernel_image debug @@ -1636,7 +1562,7 @@ find Documentation -type d | xargs chmod u+w %install -cd linux-%{kversion}.%{_target_cpu} +cd linux-%{fakeversion}.%{_target_cpu} %if %{with_doc} docdir=$RPM_BUILD_ROOT%{_datadir}/doc/kernel-doc-%{rpmversion} @@ -1802,7 +1728,7 @@ fi %files firmware %defattr(-,root,root) /lib/firmware/* -%doc linux-%{kversion}.%{_target_cpu}/firmware/WHENCE +%doc linux-%{fakeversion}.%{_target_cpu}/firmware/WHENCE %endif %if %{with_bootwrapper} @@ -1900,6 +1826,9 @@ fi # and build. %changelog +* Wed Aug 24 2011 Chuck Ebbert +- Automate the kernel version faking. + * Tue Aug 23 2011 Ben Skeggs - nouveau: pull patches from 3.1 to fix some suspend/hibernate problems (rhbz#730582) From a22cd81f847ce028bda2bdcc0259925ba4d252d9 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 25 Aug 2011 09:02:16 +1000 Subject: [PATCH 149/397] nouveau: ttm fixes for rhbz#699551 --- drm-ttm-nouveau-oops-fix.patch | 40 ++++++++++++++++++++++++++++++++++ kernel.spec | 4 ++++ 2 files changed, 44 insertions(+) create mode 100644 drm-ttm-nouveau-oops-fix.patch diff --git a/drm-ttm-nouveau-oops-fix.patch b/drm-ttm-nouveau-oops-fix.patch new file mode 100644 index 000000000..e65259e50 --- /dev/null +++ b/drm-ttm-nouveau-oops-fix.patch @@ -0,0 +1,40 @@ +diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c +index 2e618b5..9095b5b 100644 +--- a/drivers/gpu/drm/ttm/ttm_bo.c ++++ b/drivers/gpu/drm/ttm/ttm_bo.c +@@ -390,10 +390,12 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, + * Create and bind a ttm if required. + */ + +- if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED) && (bo->ttm == NULL)) { +- ret = ttm_bo_add_ttm(bo, false); +- if (ret) +- goto out_err; ++ if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) { ++ if (bo->ttm == NULL) { ++ ret = ttm_bo_add_ttm(bo, false); ++ if (ret) ++ goto out_err; ++ } + + ret = ttm_tt_set_placement_caching(bo->ttm, mem->placement); + if (ret) +diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c +index 77dbf40..ae3c6f5 100644 +--- a/drivers/gpu/drm/ttm/ttm_bo_util.c ++++ b/drivers/gpu/drm/ttm/ttm_bo_util.c +@@ -635,13 +635,13 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, + if (ret) + return ret; + +- ttm_bo_free_old_node(bo); + if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && + (bo->ttm != NULL)) { + ttm_tt_unbind(bo->ttm); + ttm_tt_destroy(bo->ttm); + bo->ttm = NULL; + } ++ ttm_bo_free_old_node(bo); + } else { + /** + * This should help pipeline ordinary buffer moves. diff --git a/kernel.spec b/kernel.spec index 419093b33..4010266fe 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1161,6 +1161,7 @@ ApplyPatch fix_xen_guest_on_old_EC2.patch ApplyPatch xen-blkfront-name-adjust.patch # DRM core +ApplyPatch drm-ttm-nouveau-oops-fix.patch # Nouveau DRM ApplyOptionalPatch drm-nouveau-updates.patch @@ -1826,6 +1827,9 @@ fi # and build. %changelog +* Thu Aug 25 2011 Ben Skeggs +- nouveau: add patch fixing ttm issues that lead to oopses/corruption (rhbz#699551) + * Wed Aug 24 2011 Chuck Ebbert - Automate the kernel version faking. From 8b2df4baf084f8f01bd1d067279e6c69999cbe7b Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 25 Aug 2011 01:09:30 -0400 Subject: [PATCH 150/397] VFS: Fix automount for negative autofs dentries (rhbz#719607) --- kernel.spec | 10 ++++ ...tomount-for-negative-autofs-dentries.patch | 56 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 vfs-fix-automount-for-negative-autofs-dentries.patch diff --git a/kernel.spec b/kernel.spec index 4010266fe..8997b345e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -609,6 +609,7 @@ Patch1501: xen-blkfront-name-adjust.patch # nouveau + drm fixes Patch1810: drm-nouveau-updates.patch +Patch1811: drm-ttm-nouveau-oops-fix.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch # make sure the lvds comes back on lid open @@ -669,6 +670,9 @@ Patch21002: arm-readl.patch Patch21003: TEGRA-2.6.40.2-enable-USB-ports.patch +# rhbz#719607 +Patch21004: vfs-fix-automount-for-negative-autofs-dentries.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1207,6 +1211,9 @@ ApplyPatch iwlagn-revert-max-aggregate-size.patch ApplyPatch utrace.patch +# rhbz#719607 +ApplyPatch vfs-fix-automount-for-negative-autofs-dentries.patch + # END OF PATCH APPLICATIONS %endif @@ -1827,6 +1834,9 @@ fi # and build. %changelog +* Thu Aug 25 2011 Chuck Ebbert +- VFS: Fix automount for negative autofs dentries (rhbz#719607) + * Thu Aug 25 2011 Ben Skeggs - nouveau: add patch fixing ttm issues that lead to oopses/corruption (rhbz#699551) diff --git a/vfs-fix-automount-for-negative-autofs-dentries.patch b/vfs-fix-automount-for-negative-autofs-dentries.patch new file mode 100644 index 000000000..7759ea6ae --- /dev/null +++ b/vfs-fix-automount-for-negative-autofs-dentries.patch @@ -0,0 +1,56 @@ +From: David Howells +Date: Mon, 11 Jul 2011 13:20:57 +0000 (+0100) +Subject: VFS: Fix automount for negative autofs dentries +X-Git-Tag: v3.1-rc1~91^2~12 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=5a30d8a2b8ddd5102c440c7e5a7c8e1fd729c818 + +VFS: Fix automount for negative autofs dentries +[ backport for 3.0.x: LOOKUP_PARENT => LOOKUP_CONTINUE ] + +Autofs may set the DCACHE_NEED_AUTOMOUNT flag on negative dentries. These +need attention from the automounter daemon regardless of the LOOKUP_FOLLOW flag. + +Signed-off-by: David Howells +Acked-by: Ian Kent +Signed-off-by: Al Viro +--- + +diff --git a/fs/namei.c b/fs/namei.c +index f8c69d3..445fd5d 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -716,19 +716,25 @@ static int follow_automount(struct path *path, unsigned flags, + if ((flags & LOOKUP_NO_AUTOMOUNT) && !(flags & LOOKUP_CONTINUE)) + return -EISDIR; /* we actually want to stop here */ + +- /* We want to mount if someone is trying to open/create a file of any +- * type under the mountpoint, wants to traverse through the mountpoint +- * or wants to open the mounted directory. +- * ++ /* + * We don't want to mount if someone's just doing a stat and they've + * set AT_SYMLINK_NOFOLLOW - unless they're stat'ing a directory and + * appended a '/' to the name. + */ +- if (!(flags & LOOKUP_FOLLOW) && +- !(flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY | +- LOOKUP_OPEN | LOOKUP_CREATE))) +- return -EISDIR; +- ++ if (!(flags & LOOKUP_FOLLOW)) { ++ /* We do, however, want to mount if someone wants to open or ++ * create a file of any type under the mountpoint, wants to ++ * traverse through the mountpoint or wants to open the mounted ++ * directory. ++ * Also, autofs may mark negative dentries as being automount ++ * points. These will need the attentions of the daemon to ++ * instantiate them before they can be used. ++ */ ++ if (!(flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY | ++ LOOKUP_OPEN | LOOKUP_CREATE)) && ++ path->dentry->d_inode) ++ return -EISDIR; ++ } + current->total_link_count++; + if (current->total_link_count >= 40) + return -ELOOP; From 51b4bd866618e270be70144c6f227fcd0b924768 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 25 Aug 2011 01:32:58 -0400 Subject: [PATCH 151/397] Add patches queued for 3.0.4 --- kernel.spec | 13 +- stable-queue.patch | 1083 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1094 insertions(+), 2 deletions(-) create mode 100644 stable-queue.patch diff --git a/kernel.spec b/kernel.spec index 8997b345e..0e11262f8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -553,6 +553,9 @@ Patch01: %{stable_patch_01} %endif %endif +# Patches from git://git.kernel.org/pub/scm/linux/kernel/git/stable/stable-queue.git +Patch02: stable-queue.patch + # we also need compile fixes for -vanilla Patch04: linux-2.6-compile-fixes.patch @@ -1051,6 +1054,8 @@ ApplyPatch %{stable_patch_00} ApplyPatch %{stable_patch_01} %endif +ApplyOptionalPatch stable-queue.patch + ApplyPatch linux-2.6-makefile-after_link.patch # @@ -1162,7 +1167,7 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch # Assorted Virt Fixes ApplyPatch fix_xen_guest_on_old_EC2.patch -ApplyPatch xen-blkfront-name-adjust.patch +#ApplyPatch xen-blkfront-name-adjust.patch # DRM core ApplyPatch drm-ttm-nouveau-oops-fix.patch @@ -1834,6 +1839,10 @@ fi # and build. %changelog +* Thu Aug 25 2011 Chuck Ebbert 2.6.40.3-2 +- Add patches queued for 3.0.4 +- Comment out xen-blkfront-name-adjust.patch, now queued for -stable + * Thu Aug 25 2011 Chuck Ebbert - VFS: Fix automount for negative autofs dentries (rhbz#719607) diff --git a/stable-queue.patch b/stable-queue.patch new file mode 100644 index 000000000..e3c1d5e5f --- /dev/null +++ b/stable-queue.patch @@ -0,0 +1,1083 @@ +--- vanilla-3.0.3.orig/kernel/irq/generic-chip.c ++++ vanilla-3.0.3/kernel/irq/generic-chip.c +@@ -246,7 +246,7 @@ void irq_setup_generic_chip(struct irq_c + gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask); + + for (i = gc->irq_base; msk; msk >>= 1, i++) { +- if (!msk & 0x01) ++ if (!(msk & 0x01)) + continue; + + if (flags & IRQ_GC_INIT_NESTED_LOCK) +@@ -301,7 +301,7 @@ void irq_remove_generic_chip(struct irq_ + raw_spin_unlock(&gc_lock); + + for (; msk; msk >>= 1, i++) { +- if (!msk & 0x01) ++ if (!(msk & 0x01)) + continue; + + /* Remove handler first. That will mask the irq line */ +--- vanilla-3.0.3.orig/fs/cifs/dir.c ++++ vanilla-3.0.3/fs/cifs/dir.c +@@ -110,8 +110,8 @@ cifs_bp_rename_retry: + } + rcu_read_unlock(); + if (namelen != dfsplen || read_seqretry(&rename_lock, seq)) { +- cERROR(1, "did not end path lookup where expected namelen is %d", +- namelen); ++ cFYI(1, "did not end path lookup where expected. namelen=%d " ++ "dfsplen=%d", namelen, dfsplen); + /* presumably this is only possible if racing with a rename + of one of the parent directories (we can not lock the dentries + above us to prevent this, but retrying should be harmless) */ +--- vanilla-3.0.3.orig/fs/befs/linuxvfs.c ++++ vanilla-3.0.3/fs/befs/linuxvfs.c +@@ -474,17 +474,22 @@ befs_follow_link(struct dentry *dentry, + befs_data_stream *data = &befs_ino->i_data.ds; + befs_off_t len = data->size; + +- befs_debug(sb, "Follow long symlink"); +- +- link = kmalloc(len, GFP_NOFS); +- if (!link) { +- link = ERR_PTR(-ENOMEM); +- } else if (befs_read_lsymlink(sb, data, link, len) != len) { +- kfree(link); +- befs_error(sb, "Failed to read entire long symlink"); ++ if (len == 0) { ++ befs_error(sb, "Long symlink with illegal length"); + link = ERR_PTR(-EIO); + } else { +- link[len - 1] = '\0'; ++ befs_debug(sb, "Follow long symlink"); ++ ++ link = kmalloc(len, GFP_NOFS); ++ if (!link) { ++ link = ERR_PTR(-ENOMEM); ++ } else if (befs_read_lsymlink(sb, data, link, len) != len) { ++ kfree(link); ++ befs_error(sb, "Failed to read entire long symlink"); ++ link = ERR_PTR(-EIO); ++ } else { ++ link[len - 1] = '\0'; ++ } + } + } else { + link = befs_ino->i_data.symlink; +--- vanilla-3.0.3.orig/drivers/edac/i7core_edac.c ++++ vanilla-3.0.3/drivers/edac/i7core_edac.c +@@ -1670,7 +1670,7 @@ static void i7core_mce_output_error(stru + char *type, *optype, *err, *msg; + unsigned long error = m->status & 0x1ff0000l; + u32 optypenum = (m->status >> 4) & 0x07; +- u32 core_err_cnt = (m->status >> 38) && 0x7fff; ++ u32 core_err_cnt = (m->status >> 38) & 0x7fff; + u32 dimm = (m->misc >> 16) & 0x3; + u32 channel = (m->misc >> 18) & 0x3; + u32 syndrome = m->misc >> 32; +--- vanilla-3.0.3.orig/fs/cifs/connect.c ++++ vanilla-3.0.3/fs/cifs/connect.c +@@ -2838,7 +2838,8 @@ cleanup_volume_info_contents(struct smb_ + kfree(volume_info->username); + kzfree(volume_info->password); + kfree(volume_info->UNC); +- kfree(volume_info->UNCip); ++ if (volume_info->UNCip != volume_info->UNC + 2) ++ kfree(volume_info->UNCip); + kfree(volume_info->domainname); + kfree(volume_info->iocharset); + kfree(volume_info->prepath); +--- vanilla-3.0.3.orig/arch/x86/kernel/cpu/intel.c ++++ vanilla-3.0.3/arch/x86/kernel/cpu/intel.c +@@ -465,11 +465,11 @@ static void __cpuinit init_intel(struct + u64 epb; + + rdmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb); +- if ((epb & 0xF) == 0) { +- printk_once(KERN_WARNING, "x86: updated energy_perf_bias" +- " to 'normal' from 'performance'\n" +- "You can view and update epb via utility," +- " such as x86_energy_perf_policy(8)\n"); ++ if ((epb & 0xF) == ENERGY_PERF_BIAS_PERFORMANCE) { ++ printk_once(KERN_WARNING "ENERGY_PERF_BIAS:" ++ " Set to 'normal', was 'performance'\n" ++ "ENERGY_PERF_BIAS: View and update with" ++ " x86_energy_perf_policy(8)\n"); + epb = (epb & ~0xF) | ENERGY_PERF_BIAS_NORMAL; + wrmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb); + } +--- vanilla-3.0.3.orig/fs/nfs/objlayout/objio_osd.c ++++ vanilla-3.0.3/fs/nfs/objlayout/objio_osd.c +@@ -479,7 +479,6 @@ static int _io_check(struct objio_state + for (i = 0; i < ios->numdevs; i++) { + struct osd_sense_info osi; + struct osd_request *or = ios->per_dev[i].or; +- unsigned dev; + int ret; + + if (!or) +@@ -500,9 +499,8 @@ static int _io_check(struct objio_state + + continue; /* we recovered */ + } +- dev = ios->per_dev[i].dev; +- objlayout_io_set_result(&ios->ol_state, dev, +- &ios->layout->comps[dev].oc_object_id, ++ objlayout_io_set_result(&ios->ol_state, i, ++ &ios->layout->comps[i].oc_object_id, + osd_pri_2_pnfs_err(osi.osd_err_pri), + ios->per_dev[i].offset, + ios->per_dev[i].length, +@@ -589,22 +587,19 @@ static void _calc_stripe_info(struct obj + } + + static int _add_stripe_unit(struct objio_state *ios, unsigned *cur_pg, +- unsigned pgbase, struct _objio_per_comp *per_dev, int cur_len, ++ unsigned pgbase, struct _objio_per_comp *per_dev, int len, + gfp_t gfp_flags) + { + unsigned pg = *cur_pg; ++ int cur_len = len; + struct request_queue *q = + osd_request_queue(_io_od(ios, per_dev->dev)); + +- per_dev->length += cur_len; +- + if (per_dev->bio == NULL) { +- unsigned stripes = ios->layout->num_comps / +- ios->layout->mirrors_p1; +- unsigned pages_in_stripe = stripes * ++ unsigned pages_in_stripe = ios->layout->group_width * + (ios->layout->stripe_unit / PAGE_SIZE); + unsigned bio_size = (ios->ol_state.nr_pages + pages_in_stripe) / +- stripes; ++ ios->layout->group_width; + + if (BIO_MAX_PAGES_KMALLOC < bio_size) + bio_size = BIO_MAX_PAGES_KMALLOC; +@@ -632,6 +627,7 @@ static int _add_stripe_unit(struct objio + } + BUG_ON(cur_len); + ++ per_dev->length += len; + *cur_pg = pg; + return 0; + } +@@ -650,7 +646,7 @@ static int _prepare_one_group(struct obj + int ret = 0; + + while (length) { +- struct _objio_per_comp *per_dev = &ios->per_dev[dev]; ++ struct _objio_per_comp *per_dev = &ios->per_dev[dev - first_dev]; + unsigned cur_len, page_off = 0; + + if (!per_dev->length) { +@@ -670,8 +666,8 @@ static int _prepare_one_group(struct obj + cur_len = stripe_unit; + } + +- if (max_comp < dev) +- max_comp = dev; ++ if (max_comp < dev - first_dev) ++ max_comp = dev - first_dev; + } else { + cur_len = stripe_unit; + } +@@ -806,7 +802,7 @@ static int _read_mirrors(struct objio_st + struct _objio_per_comp *per_dev = &ios->per_dev[cur_comp]; + unsigned dev = per_dev->dev; + struct pnfs_osd_object_cred *cred = +- &ios->layout->comps[dev]; ++ &ios->layout->comps[cur_comp]; + struct osd_obj_id obj = { + .partition = cred->oc_object_id.oid_partition_id, + .id = cred->oc_object_id.oid_object_id, +@@ -904,7 +900,7 @@ static int _write_mirrors(struct objio_s + for (; cur_comp < last_comp; ++cur_comp, ++dev) { + struct osd_request *or = NULL; + struct pnfs_osd_object_cred *cred = +- &ios->layout->comps[dev]; ++ &ios->layout->comps[cur_comp]; + struct osd_obj_id obj = { + .partition = cred->oc_object_id.oid_partition_id, + .id = cred->oc_object_id.oid_object_id, +--- vanilla-3.0.3.orig/fs/nfs/objlayout/pnfs_osd_xdr_cli.c ++++ vanilla-3.0.3/fs/nfs/objlayout/pnfs_osd_xdr_cli.c +@@ -170,6 +170,9 @@ int pnfs_osd_xdr_decode_layout_map(struc + p = _osd_xdr_decode_data_map(p, &layout->olo_map); + layout->olo_comps_index = be32_to_cpup(p++); + layout->olo_num_comps = be32_to_cpup(p++); ++ dprintk("%s: olo_comps_index=%d olo_num_comps=%d\n", __func__, ++ layout->olo_comps_index, layout->olo_num_comps); ++ + iter->total_comps = layout->olo_num_comps; + return 0; + } +--- vanilla-3.0.3.orig/fs/nfs/callback.h ++++ vanilla-3.0.3/fs/nfs/callback.h +@@ -38,6 +38,7 @@ enum nfs4_callback_opnum { + struct cb_process_state { + __be32 drc_status; + struct nfs_client *clp; ++ int slotid; + }; + + struct cb_compound_hdr_arg { +@@ -166,7 +167,6 @@ extern unsigned nfs4_callback_layoutreca + void *dummy, struct cb_process_state *cps); + + extern void nfs4_check_drain_bc_complete(struct nfs4_session *ses); +-extern void nfs4_cb_take_slot(struct nfs_client *clp); + + struct cb_devicenotifyitem { + uint32_t cbd_notify_type; +--- vanilla-3.0.3.orig/fs/nfs/callback_proc.c ++++ vanilla-3.0.3/fs/nfs/callback_proc.c +@@ -333,7 +333,7 @@ validate_seqid(struct nfs4_slot_table *t + /* Normal */ + if (likely(args->csa_sequenceid == slot->seq_nr + 1)) { + slot->seq_nr++; +- return htonl(NFS4_OK); ++ goto out_ok; + } + + /* Replay */ +@@ -352,11 +352,14 @@ validate_seqid(struct nfs4_slot_table *t + /* Wraparound */ + if (args->csa_sequenceid == 1 && (slot->seq_nr + 1) == 0) { + slot->seq_nr = 1; +- return htonl(NFS4_OK); ++ goto out_ok; + } + + /* Misordered request */ + return htonl(NFS4ERR_SEQ_MISORDERED); ++out_ok: ++ tbl->highest_used_slotid = args->csa_slotid; ++ return htonl(NFS4_OK); + } + + /* +@@ -418,26 +421,37 @@ __be32 nfs4_callback_sequence(struct cb_ + struct cb_sequenceres *res, + struct cb_process_state *cps) + { ++ struct nfs4_slot_table *tbl; + struct nfs_client *clp; + int i; + __be32 status = htonl(NFS4ERR_BADSESSION); + +- cps->clp = NULL; +- + clp = nfs4_find_client_sessionid(args->csa_addr, &args->csa_sessionid); + if (clp == NULL) + goto out; + ++ tbl = &clp->cl_session->bc_slot_table; ++ ++ spin_lock(&tbl->slot_tbl_lock); + /* state manager is resetting the session */ + if (test_bit(NFS4_SESSION_DRAINING, &clp->cl_session->session_state)) { +- status = NFS4ERR_DELAY; ++ spin_unlock(&tbl->slot_tbl_lock); ++ status = htonl(NFS4ERR_DELAY); ++ /* Return NFS4ERR_BADSESSION if we're draining the session ++ * in order to reset it. ++ */ ++ if (test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) ++ status = htonl(NFS4ERR_BADSESSION); + goto out; + } + + status = validate_seqid(&clp->cl_session->bc_slot_table, args); ++ spin_unlock(&tbl->slot_tbl_lock); + if (status) + goto out; + ++ cps->slotid = args->csa_slotid; ++ + /* + * Check for pending referring calls. If a match is found, a + * related callback was received before the response to the original +@@ -454,7 +468,6 @@ __be32 nfs4_callback_sequence(struct cb_ + res->csr_slotid = args->csa_slotid; + res->csr_highestslotid = NFS41_BC_MAX_CALLBACKS - 1; + res->csr_target_highestslotid = NFS41_BC_MAX_CALLBACKS - 1; +- nfs4_cb_take_slot(clp); + + out: + cps->clp = clp; /* put in nfs4_callback_compound */ +--- vanilla-3.0.3.orig/fs/nfs/callback_xdr.c ++++ vanilla-3.0.3/fs/nfs/callback_xdr.c +@@ -754,26 +754,15 @@ static void nfs4_callback_free_slot(stru + * Let the state manager know callback processing done. + * A single slot, so highest used slotid is either 0 or -1 + */ +- tbl->highest_used_slotid--; ++ tbl->highest_used_slotid = -1; + nfs4_check_drain_bc_complete(session); + spin_unlock(&tbl->slot_tbl_lock); + } + +-static void nfs4_cb_free_slot(struct nfs_client *clp) ++static void nfs4_cb_free_slot(struct cb_process_state *cps) + { +- if (clp && clp->cl_session) +- nfs4_callback_free_slot(clp->cl_session); +-} +- +-/* A single slot, so highest used slotid is either 0 or -1 */ +-void nfs4_cb_take_slot(struct nfs_client *clp) +-{ +- struct nfs4_slot_table *tbl = &clp->cl_session->bc_slot_table; +- +- spin_lock(&tbl->slot_tbl_lock); +- tbl->highest_used_slotid++; +- BUG_ON(tbl->highest_used_slotid != 0); +- spin_unlock(&tbl->slot_tbl_lock); ++ if (cps->slotid != -1) ++ nfs4_callback_free_slot(cps->clp->cl_session); + } + + #else /* CONFIG_NFS_V4_1 */ +@@ -784,7 +773,7 @@ preprocess_nfs41_op(int nop, unsigned in + return htonl(NFS4ERR_MINOR_VERS_MISMATCH); + } + +-static void nfs4_cb_free_slot(struct nfs_client *clp) ++static void nfs4_cb_free_slot(struct cb_process_state *cps) + { + } + #endif /* CONFIG_NFS_V4_1 */ +@@ -866,6 +855,7 @@ static __be32 nfs4_callback_compound(str + struct cb_process_state cps = { + .drc_status = 0, + .clp = NULL, ++ .slotid = -1, + }; + unsigned int nops = 0; + +@@ -906,7 +896,7 @@ static __be32 nfs4_callback_compound(str + + *hdr_res.status = status; + *hdr_res.nops = htonl(nops); +- nfs4_cb_free_slot(cps.clp); ++ nfs4_cb_free_slot(&cps); + nfs_put_client(cps.clp); + dprintk("%s: done, status = %u\n", __func__, ntohl(status)); + return rpc_success; +--- vanilla-3.0.3.orig/arch/x86/kernel/cpu/mtrr/main.c ++++ vanilla-3.0.3/arch/x86/kernel/cpu/mtrr/main.c +@@ -248,6 +248,25 @@ set_mtrr(unsigned int reg, unsigned long + unsigned long flags; + int cpu; + ++#ifdef CONFIG_SMP ++ /* ++ * If this cpu is not yet active, we are in the cpu online path. There ++ * can be no stop_machine() in parallel, as stop machine ensures this ++ * by using get_online_cpus(). We can skip taking the stop_cpus_mutex, ++ * as we don't need it and also we can't afford to block while waiting ++ * for the mutex. ++ * ++ * If this cpu is active, we need to prevent stop_machine() happening ++ * in parallel by taking the stop cpus mutex. ++ * ++ * Also, this is called in the context of cpu online path or in the ++ * context where cpu hotplug is prevented. So checking the active status ++ * of the raw_smp_processor_id() is safe. ++ */ ++ if (cpu_active(raw_smp_processor_id())) ++ mutex_lock(&stop_cpus_mutex); ++#endif ++ + preempt_disable(); + + data.smp_reg = reg; +@@ -330,6 +349,10 @@ set_mtrr(unsigned int reg, unsigned long + + local_irq_restore(flags); + preempt_enable(); ++#ifdef CONFIG_SMP ++ if (cpu_active(raw_smp_processor_id())) ++ mutex_unlock(&stop_cpus_mutex); ++#endif + } + + /** +--- vanilla-3.0.3.orig/include/linux/stop_machine.h ++++ vanilla-3.0.3/include/linux/stop_machine.h +@@ -27,6 +27,8 @@ struct cpu_stop_work { + struct cpu_stop_done *done; + }; + ++extern struct mutex stop_cpus_mutex; ++ + int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg); + void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg, + struct cpu_stop_work *work_buf); +--- vanilla-3.0.3.orig/kernel/stop_machine.c ++++ vanilla-3.0.3/kernel/stop_machine.c +@@ -132,8 +132,8 @@ void stop_one_cpu_nowait(unsigned int cp + cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu), work_buf); + } + ++DEFINE_MUTEX(stop_cpus_mutex); + /* static data for stop_cpus */ +-static DEFINE_MUTEX(stop_cpus_mutex); + static DEFINE_PER_CPU(struct cpu_stop_work, stop_cpus_work); + + int __stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg) +--- vanilla-3.0.3.orig/fs/btrfs/extent-tree.c ++++ vanilla-3.0.3/fs/btrfs/extent-tree.c +@@ -1784,6 +1784,9 @@ static int btrfs_discard_extent(struct b + + + for (i = 0; i < multi->num_stripes; i++, stripe++) { ++ if (!stripe->dev->can_discard) ++ continue; ++ + ret = btrfs_issue_discard(stripe->dev->bdev, + stripe->physical, + stripe->length); +@@ -1791,11 +1794,16 @@ static int btrfs_discard_extent(struct b + discarded_bytes += stripe->length; + else if (ret != -EOPNOTSUPP) + break; ++ ++ /* ++ * Just in case we get back EOPNOTSUPP for some reason, ++ * just ignore the return value so we don't screw up ++ * people calling discard_extent. ++ */ ++ ret = 0; + } + kfree(multi); + } +- if (discarded_bytes && ret == -EOPNOTSUPP) +- ret = 0; + + if (actual_bytes) + *actual_bytes = discarded_bytes; +--- vanilla-3.0.3.orig/fs/btrfs/volumes.c ++++ vanilla-3.0.3/fs/btrfs/volumes.c +@@ -500,6 +500,9 @@ static int __btrfs_close_devices(struct + fs_devices->rw_devices--; + } + ++ if (device->can_discard) ++ fs_devices->num_can_discard--; ++ + new_device = kmalloc(sizeof(*new_device), GFP_NOFS); + BUG_ON(!new_device); + memcpy(new_device, device, sizeof(*new_device)); +@@ -508,6 +511,7 @@ static int __btrfs_close_devices(struct + new_device->bdev = NULL; + new_device->writeable = 0; + new_device->in_fs_metadata = 0; ++ new_device->can_discard = 0; + list_replace_rcu(&device->dev_list, &new_device->dev_list); + + call_rcu(&device->rcu, free_device); +@@ -547,6 +551,7 @@ int btrfs_close_devices(struct btrfs_fs_ + static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, + fmode_t flags, void *holder) + { ++ struct request_queue *q; + struct block_device *bdev; + struct list_head *head = &fs_devices->devices; + struct btrfs_device *device; +@@ -603,6 +608,12 @@ static int __btrfs_open_devices(struct b + seeding = 0; + } + ++ q = bdev_get_queue(bdev); ++ if (blk_queue_discard(q)) { ++ device->can_discard = 1; ++ fs_devices->num_can_discard++; ++ } ++ + device->bdev = bdev; + device->in_fs_metadata = 0; + device->mode = flags; +@@ -1542,6 +1553,7 @@ error: + + int btrfs_init_new_device(struct btrfs_root *root, char *device_path) + { ++ struct request_queue *q; + struct btrfs_trans_handle *trans; + struct btrfs_device *device; + struct block_device *bdev; +@@ -1611,6 +1623,9 @@ int btrfs_init_new_device(struct btrfs_r + + lock_chunks(root); + ++ q = bdev_get_queue(bdev); ++ if (blk_queue_discard(q)) ++ device->can_discard = 1; + device->writeable = 1; + device->work.func = pending_bios_fn; + generate_random_uuid(device->uuid); +@@ -1646,6 +1661,8 @@ int btrfs_init_new_device(struct btrfs_r + root->fs_info->fs_devices->num_devices++; + root->fs_info->fs_devices->open_devices++; + root->fs_info->fs_devices->rw_devices++; ++ if (device->can_discard) ++ root->fs_info->fs_devices->num_can_discard++; + root->fs_info->fs_devices->total_rw_bytes += device->total_bytes; + + if (!blk_queue_nonrot(bdev_get_queue(bdev))) +--- vanilla-3.0.3.orig/fs/btrfs/volumes.h ++++ vanilla-3.0.3/fs/btrfs/volumes.h +@@ -48,6 +48,7 @@ struct btrfs_device { + int writeable; + int in_fs_metadata; + int missing; ++ int can_discard; + + spinlock_t io_lock; + +@@ -104,6 +105,7 @@ struct btrfs_fs_devices { + u64 rw_devices; + u64 missing_devices; + u64 total_rw_bytes; ++ u64 num_can_discard; + struct block_device *latest_bdev; + + /* all of the devices in the FS, protected by a mutex +--- vanilla-3.0.3.orig/drivers/block/loop.c ++++ vanilla-3.0.3/drivers/block/loop.c +@@ -750,10 +750,10 @@ static ssize_t loop_attr_backing_file_sh + ssize_t ret; + char *p = NULL; + +- mutex_lock(&lo->lo_ctl_mutex); ++ spin_lock_irq(&lo->lo_lock); + if (lo->lo_backing_file) + p = d_path(&lo->lo_backing_file->f_path, buf, PAGE_SIZE - 1); +- mutex_unlock(&lo->lo_ctl_mutex); ++ spin_unlock_irq(&lo->lo_lock); + + if (IS_ERR_OR_NULL(p)) + ret = PTR_ERR(p); +@@ -1007,7 +1007,9 @@ static int loop_clr_fd(struct loop_devic + + kthread_stop(lo->lo_thread); + ++ spin_lock_irq(&lo->lo_lock); + lo->lo_backing_file = NULL; ++ spin_unlock_irq(&lo->lo_lock); + + loop_release_xfer(lo); + lo->transfer = NULL; +--- vanilla-3.0.3.orig/fs/btrfs/tree-log.c ++++ vanilla-3.0.3/fs/btrfs/tree-log.c +@@ -799,14 +799,15 @@ static noinline int add_inode_ref(struct + struct extent_buffer *eb, int slot, + struct btrfs_key *key) + { +- struct inode *dir; +- int ret; + struct btrfs_inode_ref *ref; ++ struct btrfs_dir_item *di; ++ struct inode *dir; + struct inode *inode; +- char *name; +- int namelen; + unsigned long ref_ptr; + unsigned long ref_end; ++ char *name; ++ int namelen; ++ int ret; + int search_done = 0; + + /* +@@ -909,6 +910,25 @@ again: + } + btrfs_release_path(path); + ++ /* look for a conflicting sequence number */ ++ di = btrfs_lookup_dir_index_item(trans, root, path, btrfs_ino(dir), ++ btrfs_inode_ref_index(eb, ref), ++ name, namelen, 0); ++ if (di && !IS_ERR(di)) { ++ ret = drop_one_dir_item(trans, root, path, dir, di); ++ BUG_ON(ret); ++ } ++ btrfs_release_path(path); ++ ++ /* look for a conflicing name */ ++ di = btrfs_lookup_dir_item(trans, root, path, btrfs_ino(dir), ++ name, namelen, 0); ++ if (di && !IS_ERR(di)) { ++ ret = drop_one_dir_item(trans, root, path, dir, di); ++ BUG_ON(ret); ++ } ++ btrfs_release_path(path); ++ + insert: + /* insert our name */ + ret = btrfs_add_link(trans, dir, inode, name, namelen, 0, +--- vanilla-3.0.3.orig/sound/usb/mixer.c ++++ vanilla-3.0.3/sound/usb/mixer.c +@@ -152,6 +152,7 @@ static inline void check_mapped_dB(const + if (p && p->dB) { + cval->dBmin = p->dB->min; + cval->dBmax = p->dB->max; ++ cval->initialized = 1; + } + } + +@@ -1092,7 +1093,7 @@ static void build_feature_ctl(struct mix + " Switch" : " Volume"); + if (control == UAC_FU_VOLUME) { + check_mapped_dB(map, cval); +- if (cval->dBmin < cval->dBmax) { ++ if (cval->dBmin < cval->dBmax || !cval->initialized) { + kctl->tlv.c = mixer_vol_tlv; + kctl->vd[0].access |= + SNDRV_CTL_ELEM_ACCESS_TLV_READ | +--- vanilla-3.0.3.orig/sound/usb/caiaq/audio.c ++++ vanilla-3.0.3/sound/usb/caiaq/audio.c +@@ -139,8 +139,12 @@ static void stream_stop(struct snd_usb_c + + for (i = 0; i < N_URBS; i++) { + usb_kill_urb(dev->data_urbs_in[i]); +- usb_kill_urb(dev->data_urbs_out[i]); ++ ++ if (test_bit(i, &dev->outurb_active_mask)) ++ usb_kill_urb(dev->data_urbs_out[i]); + } ++ ++ dev->outurb_active_mask = 0; + } + + static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream) +@@ -612,8 +616,8 @@ static void read_completed(struct urb *u + { + struct snd_usb_caiaq_cb_info *info = urb->context; + struct snd_usb_caiaqdev *dev; +- struct urb *out; +- int frame, len, send_it = 0, outframe = 0; ++ struct urb *out = NULL; ++ int i, frame, len, send_it = 0, outframe = 0; + size_t offset = 0; + + if (urb->status || !info) +@@ -624,7 +628,17 @@ static void read_completed(struct urb *u + if (!dev->streaming) + return; + +- out = dev->data_urbs_out[info->index]; ++ /* find an unused output urb that is unused */ ++ for (i = 0; i < N_URBS; i++) ++ if (test_and_set_bit(i, &dev->outurb_active_mask) == 0) { ++ out = dev->data_urbs_out[i]; ++ break; ++ } ++ ++ if (!out) { ++ log("Unable to find an output urb to use\n"); ++ goto requeue; ++ } + + /* read the recently received packet and send back one which has + * the same layout */ +@@ -655,8 +669,12 @@ static void read_completed(struct urb *u + out->number_of_packets = outframe; + out->transfer_flags = URB_ISO_ASAP; + usb_submit_urb(out, GFP_ATOMIC); ++ } else { ++ struct snd_usb_caiaq_cb_info *oinfo = out->context; ++ clear_bit(oinfo->index, &dev->outurb_active_mask); + } + ++requeue: + /* re-submit inbound urb */ + for (frame = 0; frame < FRAMES_PER_URB; frame++) { + urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame; +@@ -678,6 +696,8 @@ static void write_completed(struct urb * + dev->output_running = 1; + wake_up(&dev->prepare_wait_queue); + } ++ ++ clear_bit(info->index, &dev->outurb_active_mask); + } + + static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret) +@@ -829,6 +849,9 @@ int snd_usb_caiaq_audio_init(struct snd_ + if (!dev->data_cb_info) + return -ENOMEM; + ++ dev->outurb_active_mask = 0; ++ BUILD_BUG_ON(N_URBS > (sizeof(dev->outurb_active_mask) * 8)); ++ + for (i = 0; i < N_URBS; i++) { + dev->data_cb_info[i].dev = dev; + dev->data_cb_info[i].index = i; +--- vanilla-3.0.3.orig/sound/usb/caiaq/device.h ++++ vanilla-3.0.3/sound/usb/caiaq/device.h +@@ -96,6 +96,7 @@ struct snd_usb_caiaqdev { + int input_panic, output_panic, warned; + char *audio_in_buf, *audio_out_buf; + unsigned int samplerates, bpp; ++ unsigned long outurb_active_mask; + + struct snd_pcm_substream *sub_playback[MAX_STREAMS]; + struct snd_pcm_substream *sub_capture[MAX_STREAMS]; +--- vanilla-3.0.3.orig/sound/pci/ac97/ac97_patch.c ++++ vanilla-3.0.3/sound/pci/ac97/ac97_patch.c +@@ -1909,6 +1909,7 @@ static unsigned int ad1981_jacks_whiteli + 0x103c0944, /* HP nc6220 */ + 0x103c0934, /* HP nc8220 */ + 0x103c006d, /* HP nx9105 */ ++ 0x103c300d, /* HP Compaq dc5100 SFF(PT003AW) */ + 0x17340088, /* FSC Scenic-W */ + 0 /* end */ + }; +--- vanilla-3.0.3.orig/fs/ext4/ext4_jbd2.h ++++ vanilla-3.0.3/fs/ext4/ext4_jbd2.h +@@ -289,10 +289,10 @@ static inline int ext4_should_order_data + + static inline int ext4_should_writeback_data(struct inode *inode) + { +- if (!S_ISREG(inode->i_mode)) +- return 0; + if (EXT4_JOURNAL(inode) == NULL) + return 1; ++ if (!S_ISREG(inode->i_mode)) ++ return 0; + if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA)) + return 0; + if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) +--- vanilla-3.0.3.orig/fs/ext4/inode.c ++++ vanilla-3.0.3/fs/ext4/inode.c +@@ -189,6 +189,12 @@ void ext4_evict_inode(struct inode *inod + int err; + + trace_ext4_evict_inode(inode); ++ ++ mutex_lock(&inode->i_mutex); ++ ext4_flush_completed_IO(inode); ++ mutex_unlock(&inode->i_mutex); ++ ext4_ioend_wait(inode); ++ + if (inode->i_nlink) { + truncate_inode_pages(&inode->i_data, 0); + goto no_delete; +@@ -1849,6 +1855,8 @@ static int ext4_journalled_write_end(str + from = pos & (PAGE_CACHE_SIZE - 1); + to = from + len; + ++ BUG_ON(!ext4_handle_valid(handle)); ++ + if (copied < len) { + if (!PageUptodate(page)) + copied = 0; +@@ -2148,7 +2156,12 @@ static int mpage_da_submit_io(struct mpa + else if (test_opt(inode->i_sb, MBLK_IO_SUBMIT)) + err = ext4_bio_write_page(&io_submit, page, + len, mpd->wbc); +- else ++ else if (buffer_uninit(page_bufs)) { ++ ext4_set_bh_endio(page_bufs, inode); ++ err = block_write_full_page_endio(page, ++ noalloc_get_block_write, ++ mpd->wbc, ext4_end_io_buffer_write); ++ } else + err = block_write_full_page(page, + noalloc_get_block_write, mpd->wbc); + +@@ -2564,6 +2577,8 @@ static int __ext4_journalled_writepage(s + goto out; + } + ++ BUG_ON(!ext4_handle_valid(handle)); ++ + ret = walk_page_buffers(handle, page_bufs, 0, len, NULL, + do_journal_get_write_access); + +@@ -3635,8 +3650,15 @@ static void ext4_end_io_buffer_write(str + goto out; + } + +- io_end->flag = EXT4_IO_END_UNWRITTEN; ++ /* ++ * It may be over-defensive here to check EXT4_IO_END_UNWRITTEN now, ++ * but being more careful is always safe for the future change. ++ */ + inode = io_end->inode; ++ if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { ++ io_end->flag |= EXT4_IO_END_UNWRITTEN; ++ atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); ++ } + + /* Add the io_end to per-inode completed io list*/ + spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); +--- vanilla-3.0.3.orig/fs/ext4/super.c ++++ vanilla-3.0.3/fs/ext4/super.c +@@ -892,7 +892,6 @@ static void ext4_i_callback(struct rcu_h + + static void ext4_destroy_inode(struct inode *inode) + { +- ext4_ioend_wait(inode); + if (!list_empty(&(EXT4_I(inode)->i_orphan))) { + ext4_msg(inode->i_sb, KERN_ERR, + "Inode %lu (%p): orphan list check failed!", +--- vanilla-3.0.3.orig/fs/ext4/page-io.c ++++ vanilla-3.0.3/fs/ext4/page-io.c +@@ -338,8 +338,10 @@ submit_and_retry: + if ((io_end->num_io_pages >= MAX_IO_PAGES) && + (io_end->pages[io_end->num_io_pages-1] != io_page)) + goto submit_and_retry; +- if (buffer_uninit(bh)) +- io->io_end->flag |= EXT4_IO_END_UNWRITTEN; ++ if (buffer_uninit(bh) && !(io_end->flag & EXT4_IO_END_UNWRITTEN)) { ++ io_end->flag |= EXT4_IO_END_UNWRITTEN; ++ atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); ++ } + io->io_end->size += bh->b_size; + io->io_next_block++; + ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh)); +--- vanilla-3.0.3.orig/drivers/block/xen-blkfront.c ++++ vanilla-3.0.3/drivers/block/xen-blkfront.c +@@ -123,8 +123,8 @@ static DEFINE_SPINLOCK(minor_lock); + #define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED)) + #define EMULATED_HD_DISK_MINOR_OFFSET (0) + #define EMULATED_HD_DISK_NAME_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET / 256) +-#define EMULATED_SD_DISK_MINOR_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET + (4 * 16)) +-#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_HD_DISK_NAME_OFFSET + 4) ++#define EMULATED_SD_DISK_MINOR_OFFSET (0) ++#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_SD_DISK_MINOR_OFFSET / 256) + + #define DEV_NAME "xvd" /* name in /dev */ + +@@ -529,7 +529,7 @@ static int xlvbd_alloc_gendisk(blkif_sec + minor = BLKIF_MINOR_EXT(info->vdevice); + nr_parts = PARTS_PER_EXT_DISK; + offset = minor / nr_parts; +- if (xen_hvm_domain() && offset <= EMULATED_HD_DISK_NAME_OFFSET + 4) ++ if (xen_hvm_domain() && offset < EMULATED_HD_DISK_NAME_OFFSET + 4) + printk(KERN_WARNING "blkfront: vdevice 0x%x might conflict with " + "emulated IDE disks,\n\t choose an xvd device name" + "from xvde on\n", info->vdevice); +--- vanilla-3.0.3.orig/arch/x86/include/asm/xen/page.h ++++ vanilla-3.0.3/arch/x86/include/asm/xen/page.h +@@ -39,7 +39,7 @@ typedef struct xpaddr { + ((unsigned long)((u64)CONFIG_XEN_MAX_DOMAIN_MEMORY * 1024 * 1024 * 1024 / PAGE_SIZE)) + + extern unsigned long *machine_to_phys_mapping; +-extern unsigned int machine_to_phys_order; ++extern unsigned long machine_to_phys_nr; + + extern unsigned long get_phys_to_machine(unsigned long pfn); + extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn); +@@ -87,7 +87,7 @@ static inline unsigned long mfn_to_pfn(u + if (xen_feature(XENFEAT_auto_translated_physmap)) + return mfn; + +- if (unlikely((mfn >> machine_to_phys_order) != 0)) { ++ if (unlikely(mfn >= machine_to_phys_nr)) { + pfn = ~0; + goto try_override; + } +--- vanilla-3.0.3.orig/arch/x86/xen/enlighten.c ++++ vanilla-3.0.3/arch/x86/xen/enlighten.c +@@ -77,8 +77,8 @@ EXPORT_SYMBOL_GPL(xen_domain_type); + + unsigned long *machine_to_phys_mapping = (void *)MACH2PHYS_VIRT_START; + EXPORT_SYMBOL(machine_to_phys_mapping); +-unsigned int machine_to_phys_order; +-EXPORT_SYMBOL(machine_to_phys_order); ++unsigned long machine_to_phys_nr; ++EXPORT_SYMBOL(machine_to_phys_nr); + + struct start_info *xen_start_info; + EXPORT_SYMBOL_GPL(xen_start_info); +--- vanilla-3.0.3.orig/arch/x86/xen/mmu.c ++++ vanilla-3.0.3/arch/x86/xen/mmu.c +@@ -1626,15 +1626,19 @@ static void __init xen_map_identity_earl + void __init xen_setup_machphys_mapping(void) + { + struct xen_machphys_mapping mapping; +- unsigned long machine_to_phys_nr_ents; + + if (HYPERVISOR_memory_op(XENMEM_machphys_mapping, &mapping) == 0) { + machine_to_phys_mapping = (unsigned long *)mapping.v_start; +- machine_to_phys_nr_ents = mapping.max_mfn + 1; ++ machine_to_phys_nr = mapping.max_mfn + 1; + } else { +- machine_to_phys_nr_ents = MACH2PHYS_NR_ENTRIES; ++ machine_to_phys_nr = MACH2PHYS_NR_ENTRIES; + } +- machine_to_phys_order = fls(machine_to_phys_nr_ents - 1); ++#ifdef CONFIG_X86_32 ++ if ((machine_to_phys_mapping + machine_to_phys_nr) ++ < machine_to_phys_mapping) ++ machine_to_phys_nr = (unsigned long *)NULL ++ - machine_to_phys_mapping; ++#endif + } + + #ifdef CONFIG_X86_64 +--- vanilla-3.0.3.orig/arch/x86/xen/smp.c ++++ vanilla-3.0.3/arch/x86/xen/smp.c +@@ -521,8 +521,6 @@ static void __init xen_hvm_smp_prepare_c + native_smp_prepare_cpus(max_cpus); + WARN_ON(xen_smp_intr_init(0)); + +- if (!xen_have_vector_callback) +- return; + xen_init_lock_cpu(0); + xen_init_spinlocks(); + } +@@ -546,6 +544,8 @@ static void xen_hvm_cpu_die(unsigned int + + void __init xen_hvm_smp_init(void) + { ++ if (!xen_have_vector_callback) ++ return; + smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus; + smp_ops.smp_send_reschedule = xen_smp_send_reschedule; + smp_ops.cpu_up = xen_hvm_cpu_up; +--- vanilla-3.0.3.orig/arch/x86/platform/olpc/olpc.c ++++ vanilla-3.0.3/arch/x86/platform/olpc/olpc.c +@@ -157,13 +157,13 @@ restart: + if (inbuf && inlen) { + /* write data to EC */ + for (i = 0; i < inlen; i++) { ++ pr_devel("olpc-ec: sending cmd arg 0x%x\n", inbuf[i]); ++ outb(inbuf[i], 0x68); + if (wait_on_ibf(0x6c, 0)) { + printk(KERN_ERR "olpc-ec: timeout waiting for" + " EC accept data!\n"); + goto err; + } +- pr_devel("olpc-ec: sending cmd arg 0x%x\n", inbuf[i]); +- outb(inbuf[i], 0x68); + } + } + if (outbuf && outlen) { +--- vanilla-3.0.3.orig/arch/x86/vdso/vdso32/sysenter.S ++++ vanilla-3.0.3/arch/x86/vdso/vdso32/sysenter.S +@@ -43,7 +43,7 @@ __kernel_vsyscall: + .space 7,0x90 + + /* 14: System call restart point is here! (SYSENTER_RETURN-2) */ +- jmp .Lenter_kernel ++ int $0x80 + /* 16: System call normal return point is here! */ + VDSO32_SYSENTER_RETURN: /* Symbol used by sysenter.c via vdso32-syms.h */ + pop %ebp +--- vanilla-3.0.3.orig/arch/x86/kernel/apic/x2apic_uv_x.c ++++ vanilla-3.0.3/arch/x86/kernel/apic/x2apic_uv_x.c +@@ -207,7 +207,6 @@ static int __cpuinit uv_wakeup_secondary + ((start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) | + APIC_DM_INIT; + uv_write_global_mmr64(pnode, UVH_IPI_INT, val); +- mdelay(10); + + val = (1UL << UVH_IPI_INT_SEND_SHFT) | + (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) | +--- vanilla-3.0.3.orig/drivers/gpu/drm/ttm/ttm_bo.c ++++ vanilla-3.0.3/drivers/gpu/drm/ttm/ttm_bo.c +@@ -353,8 +353,10 @@ static int ttm_bo_add_ttm(struct ttm_buf + + ret = ttm_tt_set_user(bo->ttm, current, + bo->buffer_start, bo->num_pages); +- if (unlikely(ret != 0)) ++ if (unlikely(ret != 0)) { + ttm_tt_destroy(bo->ttm); ++ bo->ttm = NULL; ++ } + break; + default: + printk(KERN_ERR TTM_PFX "Illegal buffer object type\n"); +--- vanilla-3.0.3.orig/drivers/gpu/drm/radeon/radeon_connectors.c ++++ vanilla-3.0.3/drivers/gpu/drm/radeon/radeon_connectors.c +@@ -466,6 +466,16 @@ static bool radeon_connector_needs_exten + (supported_device == ATOM_DEVICE_DFP2_SUPPORT)) + return true; + } ++ /* TOSHIBA Satellite L300D with ATI Mobility Radeon x1100 ++ * (RS690M) sends data to i2c bus for a HDMI connector that ++ * is not implemented */ ++ if ((dev->pdev->device == 0x791f) && ++ (dev->pdev->subsystem_vendor == 0x1179) && ++ (dev->pdev->subsystem_device == 0xff68)) { ++ if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) && ++ (supported_device == ATOM_DEVICE_DFP2_SUPPORT)) ++ return true; ++ } + + /* Default: no EDID header probe required for DDC probing */ + return false; +--- vanilla-3.0.3.orig/fs/fuse/dev.c ++++ vanilla-3.0.3/fs/fuse/dev.c +@@ -1358,6 +1358,10 @@ static int fuse_notify_inval_entry(struc + if (outarg.namelen > FUSE_NAME_MAX) + goto err; + ++ err = -EINVAL; ++ if (size != sizeof(outarg) + outarg.namelen + 1) ++ goto err; ++ + name.name = buf; + name.len = outarg.namelen; + err = fuse_copy_one(cs, buf, outarg.namelen + 1); +--- vanilla-3.0.3.orig/drivers/net/wireless/rt2x00/rt2x00usb.c ++++ vanilla-3.0.3/drivers/net/wireless/rt2x00/rt2x00usb.c +@@ -262,23 +262,20 @@ static void rt2x00usb_interrupt_txdone(s + struct queue_entry *entry = (struct queue_entry *)urb->context; + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + +- if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) ++ if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + return; +- +- if (rt2x00dev->ops->lib->tx_dma_done) +- rt2x00dev->ops->lib->tx_dma_done(entry); +- +- /* +- * Report the frame as DMA done +- */ +- rt2x00lib_dmadone(entry); +- + /* + * Check if the frame was correctly uploaded + */ + if (urb->status) + set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); ++ /* ++ * Report the frame as DMA done ++ */ ++ rt2x00lib_dmadone(entry); + ++ if (rt2x00dev->ops->lib->tx_dma_done) ++ rt2x00dev->ops->lib->tx_dma_done(entry); + /* + * Schedule the delayed work for reading the TX status + * from the device. +--- vanilla-3.0.3.orig/drivers/mmc/host/sdhci.c ++++ vanilla-3.0.3/drivers/mmc/host/sdhci.c +@@ -1863,9 +1863,6 @@ static void sdhci_tasklet_finish(unsigne + + del_timer(&host->timer); + +- if (host->version >= SDHCI_SPEC_300) +- del_timer(&host->tuning_timer); +- + mrq = host->mrq; + + /* +--- vanilla-3.0.3.orig/drivers/net/igb/e1000_82575.c ++++ vanilla-3.0.3/drivers/net/igb/e1000_82575.c +@@ -1735,6 +1735,7 @@ static s32 igb_reset_hw_82580(struct e10 + ctrl |= E1000_CTRL_RST; + + wr32(E1000_CTRL, ctrl); ++ wrfl(); + + /* Add delay to insure DEV_RST has time to complete */ + if (global_device_reset) From 802d512561c5fda01e132b1e0b99c185ae622283 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 25 Aug 2011 01:47:24 -0400 Subject: [PATCH 152/397] Add linux-3.0.tar.bz2 to the sources file --- sources | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sources b/sources index 2bb7b1b7c..6d922d0b6 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ -1aab7a741abe08d42e8eccf20de61e05 linux-2.6.39.tar.bz2 -df5790b51f218fc5e5463162b26afbfc patch-3.0.bz2 +398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 1757786b9a9ffbd48ad9642199ff5bd7 patch-3.0.3.bz2 From fbbfcd6a2793155d395a6cfe86084b1f1b9bbf8b Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 25 Aug 2011 20:08:39 -0400 Subject: [PATCH 153/397] Reduce severity of host bridge window conflict warnings (rhbz#729652) --- kernel.spec | 8 ++++ ...host-bridge-window-conflict-warnings.patch | 40 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 x86-pci-reduce-severity-of-host-bridge-window-conflict-warnings.patch diff --git a/kernel.spec b/kernel.spec index 0e11262f8..0c46c89ef 100644 --- a/kernel.spec +++ b/kernel.spec @@ -595,6 +595,8 @@ Patch470: die-floppy-die.patch Patch510: linux-2.6-silence-noise.patch Patch530: linux-2.6-silence-fbcon-logo.patch +# from 3.1 +Patch540: x86-pci-reduce-severity-of-host-bridge-window-conflict-warnings.patch Patch610: hda_intel-prealloc-4mb-dmabuffer.patch @@ -1154,6 +1156,9 @@ ApplyPatch linux-2.6-silence-noise.patch # Make fbcon not show the penguins with 'quiet' ApplyPatch linux-2.6-silence-fbcon-logo.patch +# Get rid of useless bridge window conflict warnings +ApplyPatch x86-pci-reduce-severity-of-host-bridge-window-conflict-warnings.patch + # Changes to upstream defaults. @@ -1839,6 +1844,9 @@ fi # and build. %changelog +* Thu Aug 25 2011 Chuck Ebbert +- Reduce severity of host bridge window conflict warnings (rhbz#729652) + * Thu Aug 25 2011 Chuck Ebbert 2.6.40.3-2 - Add patches queued for 3.0.4 - Comment out xen-blkfront-name-adjust.patch, now queued for -stable diff --git a/x86-pci-reduce-severity-of-host-bridge-window-conflict-warnings.patch b/x86-pci-reduce-severity-of-host-bridge-window-conflict-warnings.patch new file mode 100644 index 000000000..5db2f0051 --- /dev/null +++ b/x86-pci-reduce-severity-of-host-bridge-window-conflict-warnings.patch @@ -0,0 +1,40 @@ +From: Bjorn Helgaas +Date: Sat, 2 Jul 2011 16:47:12 +0000 (-0600) +Subject: x86/PCI: reduce severity of host bridge window conflict warnings +X-Git-Tag: v3.1-rc1~122^2~13 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=43d786ed4df4c54cb8802a523748a7d78130a2cb + +x86/PCI: reduce severity of host bridge window conflict warnings + +Host bridge windows are top-level resources, so if we find a host bridge +window conflict, it's probably with a hard-coded legacy reservation. +Moving host bridge windows is theoretically possible, but we don't support +it; we just ignore windows with conflicts, and it's not worth making this +a user-visible error. + +Reported-and-tested-by: Jools Wills +References: https://bugzilla.kernel.org/show_bug.cgi?id=38522 +Reported-by: Das +References: https://bugzilla.kernel.org/show_bug.cgi?id=16497 +Signed-off-by: Bjorn Helgaas +Signed-off-by: Jesse Barnes +--- + +diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c +index 68c3c13..ae3cb23 100644 +--- a/arch/x86/pci/acpi.c ++++ b/arch/x86/pci/acpi.c +@@ -246,10 +246,9 @@ static void add_resources(struct pci_root_info *info) + + conflict = insert_resource_conflict(root, res); + if (conflict) +- dev_err(&info->bridge->dev, +- "address space collision: host bridge window %pR " +- "conflicts with %s %pR\n", +- res, conflict->name, conflict); ++ dev_info(&info->bridge->dev, ++ "ignoring host bridge window %pR (conflicts with %s %pR)\n", ++ res, conflict->name, conflict); + else + pci_bus_add_resource(info->bus, res, 0); + } From bd7673d363fc7da8aa6b8b6d38ac4dbf22e76d17 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 26 Aug 2011 13:15:24 -0400 Subject: [PATCH 154/397] Add fixes for cifs mount oopses (rhbz#727927 rhbz#731278 rhbz#732934) --- ...ERR_PTR-dereference-in-cifs_get_root.patch | 120 ++++++++++++++++++ kernel.spec | 10 ++ 2 files changed, 130 insertions(+) create mode 100644 cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch diff --git a/cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch b/cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch new file mode 100644 index 000000000..f15a0e952 --- /dev/null +++ b/cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch @@ -0,0 +1,120 @@ +Return-Path: kernel-bounces@lists.fedoraproject.org +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail02.corp.redhat.com with LMTP; Thu, 25 Aug 2011 10:45:29 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D94C212A429; + Thu, 25 Aug 2011 10:40:08 -0400 (EDT) +X-Quarantine-ID: +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id C-k2lztK9Aht; Thu, 25 Aug 2011 10:40:08 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 99EEE12A424; + Thu, 25 Aug 2011 10:40:08 -0400 (EDT) +Received: from mx1.redhat.com (ext-mx12.extmail.prod.ext.phx2.redhat.com [10.5.110.17]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p7PEe7jY023291; + Thu, 25 Aug 2011 10:40:08 -0400 +Received: from bastion.fedoraproject.org (bastion02.phx2.fedoraproject.org [10.5.126.11]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p7PEe54S022197; + Thu, 25 Aug 2011 10:40:05 -0400 +Received: from lists.fedoraproject.org (collab1.vpn.fedoraproject.org [192.168.1.21]) + by bastion02.phx2.fedoraproject.org (Postfix) with ESMTP id E3F1D1108EB; + Thu, 25 Aug 2011 14:40:04 +0000 (UTC) +Received: from collab1.fedoraproject.org (localhost.localdomain [127.0.0.1]) + by lists.fedoraproject.org (Postfix) with ESMTP id 52AA23267A7; + Thu, 25 Aug 2011 14:40:04 +0000 (UTC) +X-Original-To: kernel@lists.fedoraproject.org +Delivered-To: kernel@lists.fedoraproject.org +Received: from smtp-mm02.fedoraproject.org (smtp-mm02.fedoraproject.org + [66.35.62.164]) + by lists.fedoraproject.org (Postfix) with ESMTP id 8FD8232679C + for ; + Thu, 25 Aug 2011 14:40:01 +0000 (UTC) +Received: from mail-gx0-f173.google.com (mail-gx0-f173.google.com + [209.85.161.173]) + by smtp-mm02.fedoraproject.org (Postfix) with ESMTP id 42F73E721F + for ; + Thu, 25 Aug 2011 14:40:01 +0000 (UTC) +Received: by gxk26 with SMTP id 26so2067938gxk.32 + for ; + Thu, 25 Aug 2011 07:40:00 -0700 (PDT) +Received: by 10.91.21.4 with SMTP id y4mr6531700agi.115.1314283200592; + Thu, 25 Aug 2011 07:40:00 -0700 (PDT) +Received: from salusa.poochiereds.net (cpe-075-177-182-191.nc.res.rr.com + [75.177.182.191]) + by mx.google.com with ESMTPS id l13sm579931anj.16.2011.08.25.07.39.59 + (version=SSLv3 cipher=OTHER); Thu, 25 Aug 2011 07:40:00 -0700 (PDT) +From: Jeff Layton +To: kernel@lists.fedoraproject.org +Subject: [PATCH 2/2] CIFS: Fix ERR_PTR dereference in cifs_get_root +Date: Thu, 25 Aug 2011 10:39:54 -0400 +Message-Id: <1314283194-26086-3-git-send-email-jlayton@redhat.com> +In-Reply-To: <1314283194-26086-1-git-send-email-jlayton@redhat.com> +References: <1314283194-26086-1-git-send-email-jlayton@redhat.com> +X-BeenThere: kernel@lists.fedoraproject.org +X-Mailman-Version: 2.1.9 +Precedence: list +List-Id: "Fedora kernel development." +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: kernel-bounces@lists.fedoraproject.org +Errors-To: kernel-bounces@lists.fedoraproject.org +X-RedHat-Spam-Score: -0.502 (RP_MATCHES_RCVD) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.110.17 + +From: Pavel Shilovsky + +move it to the beginning of the loop. + +Cc: +Signed-off-by: Pavel Shilovsky +Reviewed-by: Jeff Layton +--- + fs/cifs/cifsfs.c | 10 ++++++---- + 1 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c +index fc7e57b..53e7d72 100644 +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -566,6 +566,12 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) + struct inode *dir = dentry->d_inode; + struct dentry *child; + ++ if (!dir) { ++ dput(dentry); ++ dentry = ERR_PTR(-ENOENT); ++ break; ++ } ++ + /* skip separators */ + while (*s == sep) + s++; +@@ -581,10 +587,6 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) + mutex_unlock(&dir->i_mutex); + dput(dentry); + dentry = child; +- if (!dentry->d_inode) { +- dput(dentry); +- dentry = ERR_PTR(-ENOENT); +- } + } while (!IS_ERR(dentry)); + _FreeXid(xid); + kfree(full_path); +-- +1.7.6 + +_______________________________________________ +kernel mailing list +kernel@lists.fedoraproject.org +https://admin.fedoraproject.org/mailman/listinfo/kernel diff --git a/kernel.spec b/kernel.spec index 0c46c89ef..f6e396b4a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -678,6 +678,9 @@ Patch21003: TEGRA-2.6.40.2-enable-USB-ports.patch # rhbz#719607 Patch21004: vfs-fix-automount-for-negative-autofs-dentries.patch +# rhbz#727927 rhbz#731278 rhbz#732934 +Patch21005: cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1224,6 +1227,10 @@ ApplyPatch utrace.patch # rhbz#719607 ApplyPatch vfs-fix-automount-for-negative-autofs-dentries.patch +# rhbz#727927 rhbz#731278 rhbz#732934 +# cifs-possible-memory-corruption-on-mount.patch is already queued for 3.0.4 +ApplyPatch cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch + # END OF PATCH APPLICATIONS %endif @@ -1844,6 +1851,9 @@ fi # and build. %changelog +* Fri Aug 26 2011 Chuck Ebbert +- Add fixes for cifs mount oopses (rhbz#727927 rhbz#731278 rhbz#732934) + * Thu Aug 25 2011 Chuck Ebbert - Reduce severity of host bridge window conflict warnings (rhbz#729652) From 333fe2ae43e0d64f7a732af5f5d5ffa0ec84318f Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sat, 27 Aug 2011 13:24:53 -0400 Subject: [PATCH 155/397] Fix get_gate_vma usage in 32bit NX emulation. --- kernel.spec | 3 +++ linux-2.6-i386-nx-emulation.patch | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index f6e396b4a..ad9e50c90 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1851,6 +1851,9 @@ fi # and build. %changelog +* Sat Aug 27 2011 Dave Jones +- Fix get_gate_vma usage in 32bit NX emulation. + * Fri Aug 26 2011 Chuck Ebbert - Add fixes for cifs mount oopses (rhbz#727927 rhbz#731278 rhbz#732934) diff --git a/linux-2.6-i386-nx-emulation.patch b/linux-2.6-i386-nx-emulation.patch index 856b9b95a..fb58c612e 100644 --- a/linux-2.6-i386-nx-emulation.patch +++ b/linux-2.6-i386-nx-emulation.patch @@ -249,7 +249,7 @@ + for (vma = current->mm->mmap; vma; vma = vma->vm_next) + if ((vma->vm_flags & VM_EXEC) && (vma->vm_end > limit)) + limit = vma->vm_end; -+ vma = get_gate_vma(current); ++ vma = get_gate_vma(current->mm); + if (vma && (vma->vm_flags & VM_EXEC) && (vma->vm_end > limit)) + limit = vma->vm_end; + spin_unlock(¤t->mm->page_table_lock); From 9c11a5058e73f86a4990d41aef1d227e0fc06feb Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 29 Aug 2011 17:33:31 -0400 Subject: [PATCH 156/397] Linux 3.0.4 --- kernel.spec | 9 +- sources | 2 +- stable-queue.patch | 1084 +------------------------------- xen-blkfront-name-adjust.patch | 30 - 4 files changed, 7 insertions(+), 1118 deletions(-) delete mode 100644 xen-blkfront-name-adjust.patch diff --git a/kernel.spec b/kernel.spec index ad9e50c90..345b79516 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 @@ -608,7 +608,6 @@ Patch800: linux-2.6-crash-driver.patch # virt + ksm patches Patch1500: fix_xen_guest_on_old_EC2.patch -Patch1501: xen-blkfront-name-adjust.patch # DRM @@ -1175,7 +1174,6 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch # Assorted Virt Fixes ApplyPatch fix_xen_guest_on_old_EC2.patch -#ApplyPatch xen-blkfront-name-adjust.patch # DRM core ApplyPatch drm-ttm-nouveau-oops-fix.patch @@ -1851,6 +1849,9 @@ fi # and build. %changelog +* Mon Aug 29 2011 Chuck Ebbert 2.6.40.4-3 +- Linux 3.0.4 + * Sat Aug 27 2011 Dave Jones - Fix get_gate_vma usage in 32bit NX emulation. diff --git a/sources b/sources index 6d922d0b6..1ae01ff4f 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 -1757786b9a9ffbd48ad9642199ff5bd7 patch-3.0.3.bz2 +62ca5f3caed233617127b2b3b7a87d15 patch-3.0.4.bz2 diff --git a/stable-queue.patch b/stable-queue.patch index e3c1d5e5f..607602cfc 100644 --- a/stable-queue.patch +++ b/stable-queue.patch @@ -1,1083 +1 @@ ---- vanilla-3.0.3.orig/kernel/irq/generic-chip.c -+++ vanilla-3.0.3/kernel/irq/generic-chip.c -@@ -246,7 +246,7 @@ void irq_setup_generic_chip(struct irq_c - gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask); - - for (i = gc->irq_base; msk; msk >>= 1, i++) { -- if (!msk & 0x01) -+ if (!(msk & 0x01)) - continue; - - if (flags & IRQ_GC_INIT_NESTED_LOCK) -@@ -301,7 +301,7 @@ void irq_remove_generic_chip(struct irq_ - raw_spin_unlock(&gc_lock); - - for (; msk; msk >>= 1, i++) { -- if (!msk & 0x01) -+ if (!(msk & 0x01)) - continue; - - /* Remove handler first. That will mask the irq line */ ---- vanilla-3.0.3.orig/fs/cifs/dir.c -+++ vanilla-3.0.3/fs/cifs/dir.c -@@ -110,8 +110,8 @@ cifs_bp_rename_retry: - } - rcu_read_unlock(); - if (namelen != dfsplen || read_seqretry(&rename_lock, seq)) { -- cERROR(1, "did not end path lookup where expected namelen is %d", -- namelen); -+ cFYI(1, "did not end path lookup where expected. namelen=%d " -+ "dfsplen=%d", namelen, dfsplen); - /* presumably this is only possible if racing with a rename - of one of the parent directories (we can not lock the dentries - above us to prevent this, but retrying should be harmless) */ ---- vanilla-3.0.3.orig/fs/befs/linuxvfs.c -+++ vanilla-3.0.3/fs/befs/linuxvfs.c -@@ -474,17 +474,22 @@ befs_follow_link(struct dentry *dentry, - befs_data_stream *data = &befs_ino->i_data.ds; - befs_off_t len = data->size; - -- befs_debug(sb, "Follow long symlink"); -- -- link = kmalloc(len, GFP_NOFS); -- if (!link) { -- link = ERR_PTR(-ENOMEM); -- } else if (befs_read_lsymlink(sb, data, link, len) != len) { -- kfree(link); -- befs_error(sb, "Failed to read entire long symlink"); -+ if (len == 0) { -+ befs_error(sb, "Long symlink with illegal length"); - link = ERR_PTR(-EIO); - } else { -- link[len - 1] = '\0'; -+ befs_debug(sb, "Follow long symlink"); -+ -+ link = kmalloc(len, GFP_NOFS); -+ if (!link) { -+ link = ERR_PTR(-ENOMEM); -+ } else if (befs_read_lsymlink(sb, data, link, len) != len) { -+ kfree(link); -+ befs_error(sb, "Failed to read entire long symlink"); -+ link = ERR_PTR(-EIO); -+ } else { -+ link[len - 1] = '\0'; -+ } - } - } else { - link = befs_ino->i_data.symlink; ---- vanilla-3.0.3.orig/drivers/edac/i7core_edac.c -+++ vanilla-3.0.3/drivers/edac/i7core_edac.c -@@ -1670,7 +1670,7 @@ static void i7core_mce_output_error(stru - char *type, *optype, *err, *msg; - unsigned long error = m->status & 0x1ff0000l; - u32 optypenum = (m->status >> 4) & 0x07; -- u32 core_err_cnt = (m->status >> 38) && 0x7fff; -+ u32 core_err_cnt = (m->status >> 38) & 0x7fff; - u32 dimm = (m->misc >> 16) & 0x3; - u32 channel = (m->misc >> 18) & 0x3; - u32 syndrome = m->misc >> 32; ---- vanilla-3.0.3.orig/fs/cifs/connect.c -+++ vanilla-3.0.3/fs/cifs/connect.c -@@ -2838,7 +2838,8 @@ cleanup_volume_info_contents(struct smb_ - kfree(volume_info->username); - kzfree(volume_info->password); - kfree(volume_info->UNC); -- kfree(volume_info->UNCip); -+ if (volume_info->UNCip != volume_info->UNC + 2) -+ kfree(volume_info->UNCip); - kfree(volume_info->domainname); - kfree(volume_info->iocharset); - kfree(volume_info->prepath); ---- vanilla-3.0.3.orig/arch/x86/kernel/cpu/intel.c -+++ vanilla-3.0.3/arch/x86/kernel/cpu/intel.c -@@ -465,11 +465,11 @@ static void __cpuinit init_intel(struct - u64 epb; - - rdmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb); -- if ((epb & 0xF) == 0) { -- printk_once(KERN_WARNING, "x86: updated energy_perf_bias" -- " to 'normal' from 'performance'\n" -- "You can view and update epb via utility," -- " such as x86_energy_perf_policy(8)\n"); -+ if ((epb & 0xF) == ENERGY_PERF_BIAS_PERFORMANCE) { -+ printk_once(KERN_WARNING "ENERGY_PERF_BIAS:" -+ " Set to 'normal', was 'performance'\n" -+ "ENERGY_PERF_BIAS: View and update with" -+ " x86_energy_perf_policy(8)\n"); - epb = (epb & ~0xF) | ENERGY_PERF_BIAS_NORMAL; - wrmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb); - } ---- vanilla-3.0.3.orig/fs/nfs/objlayout/objio_osd.c -+++ vanilla-3.0.3/fs/nfs/objlayout/objio_osd.c -@@ -479,7 +479,6 @@ static int _io_check(struct objio_state - for (i = 0; i < ios->numdevs; i++) { - struct osd_sense_info osi; - struct osd_request *or = ios->per_dev[i].or; -- unsigned dev; - int ret; - - if (!or) -@@ -500,9 +499,8 @@ static int _io_check(struct objio_state - - continue; /* we recovered */ - } -- dev = ios->per_dev[i].dev; -- objlayout_io_set_result(&ios->ol_state, dev, -- &ios->layout->comps[dev].oc_object_id, -+ objlayout_io_set_result(&ios->ol_state, i, -+ &ios->layout->comps[i].oc_object_id, - osd_pri_2_pnfs_err(osi.osd_err_pri), - ios->per_dev[i].offset, - ios->per_dev[i].length, -@@ -589,22 +587,19 @@ static void _calc_stripe_info(struct obj - } - - static int _add_stripe_unit(struct objio_state *ios, unsigned *cur_pg, -- unsigned pgbase, struct _objio_per_comp *per_dev, int cur_len, -+ unsigned pgbase, struct _objio_per_comp *per_dev, int len, - gfp_t gfp_flags) - { - unsigned pg = *cur_pg; -+ int cur_len = len; - struct request_queue *q = - osd_request_queue(_io_od(ios, per_dev->dev)); - -- per_dev->length += cur_len; -- - if (per_dev->bio == NULL) { -- unsigned stripes = ios->layout->num_comps / -- ios->layout->mirrors_p1; -- unsigned pages_in_stripe = stripes * -+ unsigned pages_in_stripe = ios->layout->group_width * - (ios->layout->stripe_unit / PAGE_SIZE); - unsigned bio_size = (ios->ol_state.nr_pages + pages_in_stripe) / -- stripes; -+ ios->layout->group_width; - - if (BIO_MAX_PAGES_KMALLOC < bio_size) - bio_size = BIO_MAX_PAGES_KMALLOC; -@@ -632,6 +627,7 @@ static int _add_stripe_unit(struct objio - } - BUG_ON(cur_len); - -+ per_dev->length += len; - *cur_pg = pg; - return 0; - } -@@ -650,7 +646,7 @@ static int _prepare_one_group(struct obj - int ret = 0; - - while (length) { -- struct _objio_per_comp *per_dev = &ios->per_dev[dev]; -+ struct _objio_per_comp *per_dev = &ios->per_dev[dev - first_dev]; - unsigned cur_len, page_off = 0; - - if (!per_dev->length) { -@@ -670,8 +666,8 @@ static int _prepare_one_group(struct obj - cur_len = stripe_unit; - } - -- if (max_comp < dev) -- max_comp = dev; -+ if (max_comp < dev - first_dev) -+ max_comp = dev - first_dev; - } else { - cur_len = stripe_unit; - } -@@ -806,7 +802,7 @@ static int _read_mirrors(struct objio_st - struct _objio_per_comp *per_dev = &ios->per_dev[cur_comp]; - unsigned dev = per_dev->dev; - struct pnfs_osd_object_cred *cred = -- &ios->layout->comps[dev]; -+ &ios->layout->comps[cur_comp]; - struct osd_obj_id obj = { - .partition = cred->oc_object_id.oid_partition_id, - .id = cred->oc_object_id.oid_object_id, -@@ -904,7 +900,7 @@ static int _write_mirrors(struct objio_s - for (; cur_comp < last_comp; ++cur_comp, ++dev) { - struct osd_request *or = NULL; - struct pnfs_osd_object_cred *cred = -- &ios->layout->comps[dev]; -+ &ios->layout->comps[cur_comp]; - struct osd_obj_id obj = { - .partition = cred->oc_object_id.oid_partition_id, - .id = cred->oc_object_id.oid_object_id, ---- vanilla-3.0.3.orig/fs/nfs/objlayout/pnfs_osd_xdr_cli.c -+++ vanilla-3.0.3/fs/nfs/objlayout/pnfs_osd_xdr_cli.c -@@ -170,6 +170,9 @@ int pnfs_osd_xdr_decode_layout_map(struc - p = _osd_xdr_decode_data_map(p, &layout->olo_map); - layout->olo_comps_index = be32_to_cpup(p++); - layout->olo_num_comps = be32_to_cpup(p++); -+ dprintk("%s: olo_comps_index=%d olo_num_comps=%d\n", __func__, -+ layout->olo_comps_index, layout->olo_num_comps); -+ - iter->total_comps = layout->olo_num_comps; - return 0; - } ---- vanilla-3.0.3.orig/fs/nfs/callback.h -+++ vanilla-3.0.3/fs/nfs/callback.h -@@ -38,6 +38,7 @@ enum nfs4_callback_opnum { - struct cb_process_state { - __be32 drc_status; - struct nfs_client *clp; -+ int slotid; - }; - - struct cb_compound_hdr_arg { -@@ -166,7 +167,6 @@ extern unsigned nfs4_callback_layoutreca - void *dummy, struct cb_process_state *cps); - - extern void nfs4_check_drain_bc_complete(struct nfs4_session *ses); --extern void nfs4_cb_take_slot(struct nfs_client *clp); - - struct cb_devicenotifyitem { - uint32_t cbd_notify_type; ---- vanilla-3.0.3.orig/fs/nfs/callback_proc.c -+++ vanilla-3.0.3/fs/nfs/callback_proc.c -@@ -333,7 +333,7 @@ validate_seqid(struct nfs4_slot_table *t - /* Normal */ - if (likely(args->csa_sequenceid == slot->seq_nr + 1)) { - slot->seq_nr++; -- return htonl(NFS4_OK); -+ goto out_ok; - } - - /* Replay */ -@@ -352,11 +352,14 @@ validate_seqid(struct nfs4_slot_table *t - /* Wraparound */ - if (args->csa_sequenceid == 1 && (slot->seq_nr + 1) == 0) { - slot->seq_nr = 1; -- return htonl(NFS4_OK); -+ goto out_ok; - } - - /* Misordered request */ - return htonl(NFS4ERR_SEQ_MISORDERED); -+out_ok: -+ tbl->highest_used_slotid = args->csa_slotid; -+ return htonl(NFS4_OK); - } - - /* -@@ -418,26 +421,37 @@ __be32 nfs4_callback_sequence(struct cb_ - struct cb_sequenceres *res, - struct cb_process_state *cps) - { -+ struct nfs4_slot_table *tbl; - struct nfs_client *clp; - int i; - __be32 status = htonl(NFS4ERR_BADSESSION); - -- cps->clp = NULL; -- - clp = nfs4_find_client_sessionid(args->csa_addr, &args->csa_sessionid); - if (clp == NULL) - goto out; - -+ tbl = &clp->cl_session->bc_slot_table; -+ -+ spin_lock(&tbl->slot_tbl_lock); - /* state manager is resetting the session */ - if (test_bit(NFS4_SESSION_DRAINING, &clp->cl_session->session_state)) { -- status = NFS4ERR_DELAY; -+ spin_unlock(&tbl->slot_tbl_lock); -+ status = htonl(NFS4ERR_DELAY); -+ /* Return NFS4ERR_BADSESSION if we're draining the session -+ * in order to reset it. -+ */ -+ if (test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) -+ status = htonl(NFS4ERR_BADSESSION); - goto out; - } - - status = validate_seqid(&clp->cl_session->bc_slot_table, args); -+ spin_unlock(&tbl->slot_tbl_lock); - if (status) - goto out; - -+ cps->slotid = args->csa_slotid; -+ - /* - * Check for pending referring calls. If a match is found, a - * related callback was received before the response to the original -@@ -454,7 +468,6 @@ __be32 nfs4_callback_sequence(struct cb_ - res->csr_slotid = args->csa_slotid; - res->csr_highestslotid = NFS41_BC_MAX_CALLBACKS - 1; - res->csr_target_highestslotid = NFS41_BC_MAX_CALLBACKS - 1; -- nfs4_cb_take_slot(clp); - - out: - cps->clp = clp; /* put in nfs4_callback_compound */ ---- vanilla-3.0.3.orig/fs/nfs/callback_xdr.c -+++ vanilla-3.0.3/fs/nfs/callback_xdr.c -@@ -754,26 +754,15 @@ static void nfs4_callback_free_slot(stru - * Let the state manager know callback processing done. - * A single slot, so highest used slotid is either 0 or -1 - */ -- tbl->highest_used_slotid--; -+ tbl->highest_used_slotid = -1; - nfs4_check_drain_bc_complete(session); - spin_unlock(&tbl->slot_tbl_lock); - } - --static void nfs4_cb_free_slot(struct nfs_client *clp) -+static void nfs4_cb_free_slot(struct cb_process_state *cps) - { -- if (clp && clp->cl_session) -- nfs4_callback_free_slot(clp->cl_session); --} -- --/* A single slot, so highest used slotid is either 0 or -1 */ --void nfs4_cb_take_slot(struct nfs_client *clp) --{ -- struct nfs4_slot_table *tbl = &clp->cl_session->bc_slot_table; -- -- spin_lock(&tbl->slot_tbl_lock); -- tbl->highest_used_slotid++; -- BUG_ON(tbl->highest_used_slotid != 0); -- spin_unlock(&tbl->slot_tbl_lock); -+ if (cps->slotid != -1) -+ nfs4_callback_free_slot(cps->clp->cl_session); - } - - #else /* CONFIG_NFS_V4_1 */ -@@ -784,7 +773,7 @@ preprocess_nfs41_op(int nop, unsigned in - return htonl(NFS4ERR_MINOR_VERS_MISMATCH); - } - --static void nfs4_cb_free_slot(struct nfs_client *clp) -+static void nfs4_cb_free_slot(struct cb_process_state *cps) - { - } - #endif /* CONFIG_NFS_V4_1 */ -@@ -866,6 +855,7 @@ static __be32 nfs4_callback_compound(str - struct cb_process_state cps = { - .drc_status = 0, - .clp = NULL, -+ .slotid = -1, - }; - unsigned int nops = 0; - -@@ -906,7 +896,7 @@ static __be32 nfs4_callback_compound(str - - *hdr_res.status = status; - *hdr_res.nops = htonl(nops); -- nfs4_cb_free_slot(cps.clp); -+ nfs4_cb_free_slot(&cps); - nfs_put_client(cps.clp); - dprintk("%s: done, status = %u\n", __func__, ntohl(status)); - return rpc_success; ---- vanilla-3.0.3.orig/arch/x86/kernel/cpu/mtrr/main.c -+++ vanilla-3.0.3/arch/x86/kernel/cpu/mtrr/main.c -@@ -248,6 +248,25 @@ set_mtrr(unsigned int reg, unsigned long - unsigned long flags; - int cpu; - -+#ifdef CONFIG_SMP -+ /* -+ * If this cpu is not yet active, we are in the cpu online path. There -+ * can be no stop_machine() in parallel, as stop machine ensures this -+ * by using get_online_cpus(). We can skip taking the stop_cpus_mutex, -+ * as we don't need it and also we can't afford to block while waiting -+ * for the mutex. -+ * -+ * If this cpu is active, we need to prevent stop_machine() happening -+ * in parallel by taking the stop cpus mutex. -+ * -+ * Also, this is called in the context of cpu online path or in the -+ * context where cpu hotplug is prevented. So checking the active status -+ * of the raw_smp_processor_id() is safe. -+ */ -+ if (cpu_active(raw_smp_processor_id())) -+ mutex_lock(&stop_cpus_mutex); -+#endif -+ - preempt_disable(); - - data.smp_reg = reg; -@@ -330,6 +349,10 @@ set_mtrr(unsigned int reg, unsigned long - - local_irq_restore(flags); - preempt_enable(); -+#ifdef CONFIG_SMP -+ if (cpu_active(raw_smp_processor_id())) -+ mutex_unlock(&stop_cpus_mutex); -+#endif - } - - /** ---- vanilla-3.0.3.orig/include/linux/stop_machine.h -+++ vanilla-3.0.3/include/linux/stop_machine.h -@@ -27,6 +27,8 @@ struct cpu_stop_work { - struct cpu_stop_done *done; - }; - -+extern struct mutex stop_cpus_mutex; -+ - int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg); - void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg, - struct cpu_stop_work *work_buf); ---- vanilla-3.0.3.orig/kernel/stop_machine.c -+++ vanilla-3.0.3/kernel/stop_machine.c -@@ -132,8 +132,8 @@ void stop_one_cpu_nowait(unsigned int cp - cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu), work_buf); - } - -+DEFINE_MUTEX(stop_cpus_mutex); - /* static data for stop_cpus */ --static DEFINE_MUTEX(stop_cpus_mutex); - static DEFINE_PER_CPU(struct cpu_stop_work, stop_cpus_work); - - int __stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg) ---- vanilla-3.0.3.orig/fs/btrfs/extent-tree.c -+++ vanilla-3.0.3/fs/btrfs/extent-tree.c -@@ -1784,6 +1784,9 @@ static int btrfs_discard_extent(struct b - - - for (i = 0; i < multi->num_stripes; i++, stripe++) { -+ if (!stripe->dev->can_discard) -+ continue; -+ - ret = btrfs_issue_discard(stripe->dev->bdev, - stripe->physical, - stripe->length); -@@ -1791,11 +1794,16 @@ static int btrfs_discard_extent(struct b - discarded_bytes += stripe->length; - else if (ret != -EOPNOTSUPP) - break; -+ -+ /* -+ * Just in case we get back EOPNOTSUPP for some reason, -+ * just ignore the return value so we don't screw up -+ * people calling discard_extent. -+ */ -+ ret = 0; - } - kfree(multi); - } -- if (discarded_bytes && ret == -EOPNOTSUPP) -- ret = 0; - - if (actual_bytes) - *actual_bytes = discarded_bytes; ---- vanilla-3.0.3.orig/fs/btrfs/volumes.c -+++ vanilla-3.0.3/fs/btrfs/volumes.c -@@ -500,6 +500,9 @@ static int __btrfs_close_devices(struct - fs_devices->rw_devices--; - } - -+ if (device->can_discard) -+ fs_devices->num_can_discard--; -+ - new_device = kmalloc(sizeof(*new_device), GFP_NOFS); - BUG_ON(!new_device); - memcpy(new_device, device, sizeof(*new_device)); -@@ -508,6 +511,7 @@ static int __btrfs_close_devices(struct - new_device->bdev = NULL; - new_device->writeable = 0; - new_device->in_fs_metadata = 0; -+ new_device->can_discard = 0; - list_replace_rcu(&device->dev_list, &new_device->dev_list); - - call_rcu(&device->rcu, free_device); -@@ -547,6 +551,7 @@ int btrfs_close_devices(struct btrfs_fs_ - static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, - fmode_t flags, void *holder) - { -+ struct request_queue *q; - struct block_device *bdev; - struct list_head *head = &fs_devices->devices; - struct btrfs_device *device; -@@ -603,6 +608,12 @@ static int __btrfs_open_devices(struct b - seeding = 0; - } - -+ q = bdev_get_queue(bdev); -+ if (blk_queue_discard(q)) { -+ device->can_discard = 1; -+ fs_devices->num_can_discard++; -+ } -+ - device->bdev = bdev; - device->in_fs_metadata = 0; - device->mode = flags; -@@ -1542,6 +1553,7 @@ error: - - int btrfs_init_new_device(struct btrfs_root *root, char *device_path) - { -+ struct request_queue *q; - struct btrfs_trans_handle *trans; - struct btrfs_device *device; - struct block_device *bdev; -@@ -1611,6 +1623,9 @@ int btrfs_init_new_device(struct btrfs_r - - lock_chunks(root); - -+ q = bdev_get_queue(bdev); -+ if (blk_queue_discard(q)) -+ device->can_discard = 1; - device->writeable = 1; - device->work.func = pending_bios_fn; - generate_random_uuid(device->uuid); -@@ -1646,6 +1661,8 @@ int btrfs_init_new_device(struct btrfs_r - root->fs_info->fs_devices->num_devices++; - root->fs_info->fs_devices->open_devices++; - root->fs_info->fs_devices->rw_devices++; -+ if (device->can_discard) -+ root->fs_info->fs_devices->num_can_discard++; - root->fs_info->fs_devices->total_rw_bytes += device->total_bytes; - - if (!blk_queue_nonrot(bdev_get_queue(bdev))) ---- vanilla-3.0.3.orig/fs/btrfs/volumes.h -+++ vanilla-3.0.3/fs/btrfs/volumes.h -@@ -48,6 +48,7 @@ struct btrfs_device { - int writeable; - int in_fs_metadata; - int missing; -+ int can_discard; - - spinlock_t io_lock; - -@@ -104,6 +105,7 @@ struct btrfs_fs_devices { - u64 rw_devices; - u64 missing_devices; - u64 total_rw_bytes; -+ u64 num_can_discard; - struct block_device *latest_bdev; - - /* all of the devices in the FS, protected by a mutex ---- vanilla-3.0.3.orig/drivers/block/loop.c -+++ vanilla-3.0.3/drivers/block/loop.c -@@ -750,10 +750,10 @@ static ssize_t loop_attr_backing_file_sh - ssize_t ret; - char *p = NULL; - -- mutex_lock(&lo->lo_ctl_mutex); -+ spin_lock_irq(&lo->lo_lock); - if (lo->lo_backing_file) - p = d_path(&lo->lo_backing_file->f_path, buf, PAGE_SIZE - 1); -- mutex_unlock(&lo->lo_ctl_mutex); -+ spin_unlock_irq(&lo->lo_lock); - - if (IS_ERR_OR_NULL(p)) - ret = PTR_ERR(p); -@@ -1007,7 +1007,9 @@ static int loop_clr_fd(struct loop_devic - - kthread_stop(lo->lo_thread); - -+ spin_lock_irq(&lo->lo_lock); - lo->lo_backing_file = NULL; -+ spin_unlock_irq(&lo->lo_lock); - - loop_release_xfer(lo); - lo->transfer = NULL; ---- vanilla-3.0.3.orig/fs/btrfs/tree-log.c -+++ vanilla-3.0.3/fs/btrfs/tree-log.c -@@ -799,14 +799,15 @@ static noinline int add_inode_ref(struct - struct extent_buffer *eb, int slot, - struct btrfs_key *key) - { -- struct inode *dir; -- int ret; - struct btrfs_inode_ref *ref; -+ struct btrfs_dir_item *di; -+ struct inode *dir; - struct inode *inode; -- char *name; -- int namelen; - unsigned long ref_ptr; - unsigned long ref_end; -+ char *name; -+ int namelen; -+ int ret; - int search_done = 0; - - /* -@@ -909,6 +910,25 @@ again: - } - btrfs_release_path(path); - -+ /* look for a conflicting sequence number */ -+ di = btrfs_lookup_dir_index_item(trans, root, path, btrfs_ino(dir), -+ btrfs_inode_ref_index(eb, ref), -+ name, namelen, 0); -+ if (di && !IS_ERR(di)) { -+ ret = drop_one_dir_item(trans, root, path, dir, di); -+ BUG_ON(ret); -+ } -+ btrfs_release_path(path); -+ -+ /* look for a conflicing name */ -+ di = btrfs_lookup_dir_item(trans, root, path, btrfs_ino(dir), -+ name, namelen, 0); -+ if (di && !IS_ERR(di)) { -+ ret = drop_one_dir_item(trans, root, path, dir, di); -+ BUG_ON(ret); -+ } -+ btrfs_release_path(path); -+ - insert: - /* insert our name */ - ret = btrfs_add_link(trans, dir, inode, name, namelen, 0, ---- vanilla-3.0.3.orig/sound/usb/mixer.c -+++ vanilla-3.0.3/sound/usb/mixer.c -@@ -152,6 +152,7 @@ static inline void check_mapped_dB(const - if (p && p->dB) { - cval->dBmin = p->dB->min; - cval->dBmax = p->dB->max; -+ cval->initialized = 1; - } - } - -@@ -1092,7 +1093,7 @@ static void build_feature_ctl(struct mix - " Switch" : " Volume"); - if (control == UAC_FU_VOLUME) { - check_mapped_dB(map, cval); -- if (cval->dBmin < cval->dBmax) { -+ if (cval->dBmin < cval->dBmax || !cval->initialized) { - kctl->tlv.c = mixer_vol_tlv; - kctl->vd[0].access |= - SNDRV_CTL_ELEM_ACCESS_TLV_READ | ---- vanilla-3.0.3.orig/sound/usb/caiaq/audio.c -+++ vanilla-3.0.3/sound/usb/caiaq/audio.c -@@ -139,8 +139,12 @@ static void stream_stop(struct snd_usb_c - - for (i = 0; i < N_URBS; i++) { - usb_kill_urb(dev->data_urbs_in[i]); -- usb_kill_urb(dev->data_urbs_out[i]); -+ -+ if (test_bit(i, &dev->outurb_active_mask)) -+ usb_kill_urb(dev->data_urbs_out[i]); - } -+ -+ dev->outurb_active_mask = 0; - } - - static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream) -@@ -612,8 +616,8 @@ static void read_completed(struct urb *u - { - struct snd_usb_caiaq_cb_info *info = urb->context; - struct snd_usb_caiaqdev *dev; -- struct urb *out; -- int frame, len, send_it = 0, outframe = 0; -+ struct urb *out = NULL; -+ int i, frame, len, send_it = 0, outframe = 0; - size_t offset = 0; - - if (urb->status || !info) -@@ -624,7 +628,17 @@ static void read_completed(struct urb *u - if (!dev->streaming) - return; - -- out = dev->data_urbs_out[info->index]; -+ /* find an unused output urb that is unused */ -+ for (i = 0; i < N_URBS; i++) -+ if (test_and_set_bit(i, &dev->outurb_active_mask) == 0) { -+ out = dev->data_urbs_out[i]; -+ break; -+ } -+ -+ if (!out) { -+ log("Unable to find an output urb to use\n"); -+ goto requeue; -+ } - - /* read the recently received packet and send back one which has - * the same layout */ -@@ -655,8 +669,12 @@ static void read_completed(struct urb *u - out->number_of_packets = outframe; - out->transfer_flags = URB_ISO_ASAP; - usb_submit_urb(out, GFP_ATOMIC); -+ } else { -+ struct snd_usb_caiaq_cb_info *oinfo = out->context; -+ clear_bit(oinfo->index, &dev->outurb_active_mask); - } - -+requeue: - /* re-submit inbound urb */ - for (frame = 0; frame < FRAMES_PER_URB; frame++) { - urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame; -@@ -678,6 +696,8 @@ static void write_completed(struct urb * - dev->output_running = 1; - wake_up(&dev->prepare_wait_queue); - } -+ -+ clear_bit(info->index, &dev->outurb_active_mask); - } - - static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret) -@@ -829,6 +849,9 @@ int snd_usb_caiaq_audio_init(struct snd_ - if (!dev->data_cb_info) - return -ENOMEM; - -+ dev->outurb_active_mask = 0; -+ BUILD_BUG_ON(N_URBS > (sizeof(dev->outurb_active_mask) * 8)); -+ - for (i = 0; i < N_URBS; i++) { - dev->data_cb_info[i].dev = dev; - dev->data_cb_info[i].index = i; ---- vanilla-3.0.3.orig/sound/usb/caiaq/device.h -+++ vanilla-3.0.3/sound/usb/caiaq/device.h -@@ -96,6 +96,7 @@ struct snd_usb_caiaqdev { - int input_panic, output_panic, warned; - char *audio_in_buf, *audio_out_buf; - unsigned int samplerates, bpp; -+ unsigned long outurb_active_mask; - - struct snd_pcm_substream *sub_playback[MAX_STREAMS]; - struct snd_pcm_substream *sub_capture[MAX_STREAMS]; ---- vanilla-3.0.3.orig/sound/pci/ac97/ac97_patch.c -+++ vanilla-3.0.3/sound/pci/ac97/ac97_patch.c -@@ -1909,6 +1909,7 @@ static unsigned int ad1981_jacks_whiteli - 0x103c0944, /* HP nc6220 */ - 0x103c0934, /* HP nc8220 */ - 0x103c006d, /* HP nx9105 */ -+ 0x103c300d, /* HP Compaq dc5100 SFF(PT003AW) */ - 0x17340088, /* FSC Scenic-W */ - 0 /* end */ - }; ---- vanilla-3.0.3.orig/fs/ext4/ext4_jbd2.h -+++ vanilla-3.0.3/fs/ext4/ext4_jbd2.h -@@ -289,10 +289,10 @@ static inline int ext4_should_order_data - - static inline int ext4_should_writeback_data(struct inode *inode) - { -- if (!S_ISREG(inode->i_mode)) -- return 0; - if (EXT4_JOURNAL(inode) == NULL) - return 1; -+ if (!S_ISREG(inode->i_mode)) -+ return 0; - if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA)) - return 0; - if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) ---- vanilla-3.0.3.orig/fs/ext4/inode.c -+++ vanilla-3.0.3/fs/ext4/inode.c -@@ -189,6 +189,12 @@ void ext4_evict_inode(struct inode *inod - int err; - - trace_ext4_evict_inode(inode); -+ -+ mutex_lock(&inode->i_mutex); -+ ext4_flush_completed_IO(inode); -+ mutex_unlock(&inode->i_mutex); -+ ext4_ioend_wait(inode); -+ - if (inode->i_nlink) { - truncate_inode_pages(&inode->i_data, 0); - goto no_delete; -@@ -1849,6 +1855,8 @@ static int ext4_journalled_write_end(str - from = pos & (PAGE_CACHE_SIZE - 1); - to = from + len; - -+ BUG_ON(!ext4_handle_valid(handle)); -+ - if (copied < len) { - if (!PageUptodate(page)) - copied = 0; -@@ -2148,7 +2156,12 @@ static int mpage_da_submit_io(struct mpa - else if (test_opt(inode->i_sb, MBLK_IO_SUBMIT)) - err = ext4_bio_write_page(&io_submit, page, - len, mpd->wbc); -- else -+ else if (buffer_uninit(page_bufs)) { -+ ext4_set_bh_endio(page_bufs, inode); -+ err = block_write_full_page_endio(page, -+ noalloc_get_block_write, -+ mpd->wbc, ext4_end_io_buffer_write); -+ } else - err = block_write_full_page(page, - noalloc_get_block_write, mpd->wbc); - -@@ -2564,6 +2577,8 @@ static int __ext4_journalled_writepage(s - goto out; - } - -+ BUG_ON(!ext4_handle_valid(handle)); -+ - ret = walk_page_buffers(handle, page_bufs, 0, len, NULL, - do_journal_get_write_access); - -@@ -3635,8 +3650,15 @@ static void ext4_end_io_buffer_write(str - goto out; - } - -- io_end->flag = EXT4_IO_END_UNWRITTEN; -+ /* -+ * It may be over-defensive here to check EXT4_IO_END_UNWRITTEN now, -+ * but being more careful is always safe for the future change. -+ */ - inode = io_end->inode; -+ if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { -+ io_end->flag |= EXT4_IO_END_UNWRITTEN; -+ atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); -+ } - - /* Add the io_end to per-inode completed io list*/ - spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); ---- vanilla-3.0.3.orig/fs/ext4/super.c -+++ vanilla-3.0.3/fs/ext4/super.c -@@ -892,7 +892,6 @@ static void ext4_i_callback(struct rcu_h - - static void ext4_destroy_inode(struct inode *inode) - { -- ext4_ioend_wait(inode); - if (!list_empty(&(EXT4_I(inode)->i_orphan))) { - ext4_msg(inode->i_sb, KERN_ERR, - "Inode %lu (%p): orphan list check failed!", ---- vanilla-3.0.3.orig/fs/ext4/page-io.c -+++ vanilla-3.0.3/fs/ext4/page-io.c -@@ -338,8 +338,10 @@ submit_and_retry: - if ((io_end->num_io_pages >= MAX_IO_PAGES) && - (io_end->pages[io_end->num_io_pages-1] != io_page)) - goto submit_and_retry; -- if (buffer_uninit(bh)) -- io->io_end->flag |= EXT4_IO_END_UNWRITTEN; -+ if (buffer_uninit(bh) && !(io_end->flag & EXT4_IO_END_UNWRITTEN)) { -+ io_end->flag |= EXT4_IO_END_UNWRITTEN; -+ atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); -+ } - io->io_end->size += bh->b_size; - io->io_next_block++; - ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh)); ---- vanilla-3.0.3.orig/drivers/block/xen-blkfront.c -+++ vanilla-3.0.3/drivers/block/xen-blkfront.c -@@ -123,8 +123,8 @@ static DEFINE_SPINLOCK(minor_lock); - #define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED)) - #define EMULATED_HD_DISK_MINOR_OFFSET (0) - #define EMULATED_HD_DISK_NAME_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET / 256) --#define EMULATED_SD_DISK_MINOR_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET + (4 * 16)) --#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_HD_DISK_NAME_OFFSET + 4) -+#define EMULATED_SD_DISK_MINOR_OFFSET (0) -+#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_SD_DISK_MINOR_OFFSET / 256) - - #define DEV_NAME "xvd" /* name in /dev */ - -@@ -529,7 +529,7 @@ static int xlvbd_alloc_gendisk(blkif_sec - minor = BLKIF_MINOR_EXT(info->vdevice); - nr_parts = PARTS_PER_EXT_DISK; - offset = minor / nr_parts; -- if (xen_hvm_domain() && offset <= EMULATED_HD_DISK_NAME_OFFSET + 4) -+ if (xen_hvm_domain() && offset < EMULATED_HD_DISK_NAME_OFFSET + 4) - printk(KERN_WARNING "blkfront: vdevice 0x%x might conflict with " - "emulated IDE disks,\n\t choose an xvd device name" - "from xvde on\n", info->vdevice); ---- vanilla-3.0.3.orig/arch/x86/include/asm/xen/page.h -+++ vanilla-3.0.3/arch/x86/include/asm/xen/page.h -@@ -39,7 +39,7 @@ typedef struct xpaddr { - ((unsigned long)((u64)CONFIG_XEN_MAX_DOMAIN_MEMORY * 1024 * 1024 * 1024 / PAGE_SIZE)) - - extern unsigned long *machine_to_phys_mapping; --extern unsigned int machine_to_phys_order; -+extern unsigned long machine_to_phys_nr; - - extern unsigned long get_phys_to_machine(unsigned long pfn); - extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn); -@@ -87,7 +87,7 @@ static inline unsigned long mfn_to_pfn(u - if (xen_feature(XENFEAT_auto_translated_physmap)) - return mfn; - -- if (unlikely((mfn >> machine_to_phys_order) != 0)) { -+ if (unlikely(mfn >= machine_to_phys_nr)) { - pfn = ~0; - goto try_override; - } ---- vanilla-3.0.3.orig/arch/x86/xen/enlighten.c -+++ vanilla-3.0.3/arch/x86/xen/enlighten.c -@@ -77,8 +77,8 @@ EXPORT_SYMBOL_GPL(xen_domain_type); - - unsigned long *machine_to_phys_mapping = (void *)MACH2PHYS_VIRT_START; - EXPORT_SYMBOL(machine_to_phys_mapping); --unsigned int machine_to_phys_order; --EXPORT_SYMBOL(machine_to_phys_order); -+unsigned long machine_to_phys_nr; -+EXPORT_SYMBOL(machine_to_phys_nr); - - struct start_info *xen_start_info; - EXPORT_SYMBOL_GPL(xen_start_info); ---- vanilla-3.0.3.orig/arch/x86/xen/mmu.c -+++ vanilla-3.0.3/arch/x86/xen/mmu.c -@@ -1626,15 +1626,19 @@ static void __init xen_map_identity_earl - void __init xen_setup_machphys_mapping(void) - { - struct xen_machphys_mapping mapping; -- unsigned long machine_to_phys_nr_ents; - - if (HYPERVISOR_memory_op(XENMEM_machphys_mapping, &mapping) == 0) { - machine_to_phys_mapping = (unsigned long *)mapping.v_start; -- machine_to_phys_nr_ents = mapping.max_mfn + 1; -+ machine_to_phys_nr = mapping.max_mfn + 1; - } else { -- machine_to_phys_nr_ents = MACH2PHYS_NR_ENTRIES; -+ machine_to_phys_nr = MACH2PHYS_NR_ENTRIES; - } -- machine_to_phys_order = fls(machine_to_phys_nr_ents - 1); -+#ifdef CONFIG_X86_32 -+ if ((machine_to_phys_mapping + machine_to_phys_nr) -+ < machine_to_phys_mapping) -+ machine_to_phys_nr = (unsigned long *)NULL -+ - machine_to_phys_mapping; -+#endif - } - - #ifdef CONFIG_X86_64 ---- vanilla-3.0.3.orig/arch/x86/xen/smp.c -+++ vanilla-3.0.3/arch/x86/xen/smp.c -@@ -521,8 +521,6 @@ static void __init xen_hvm_smp_prepare_c - native_smp_prepare_cpus(max_cpus); - WARN_ON(xen_smp_intr_init(0)); - -- if (!xen_have_vector_callback) -- return; - xen_init_lock_cpu(0); - xen_init_spinlocks(); - } -@@ -546,6 +544,8 @@ static void xen_hvm_cpu_die(unsigned int - - void __init xen_hvm_smp_init(void) - { -+ if (!xen_have_vector_callback) -+ return; - smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus; - smp_ops.smp_send_reschedule = xen_smp_send_reschedule; - smp_ops.cpu_up = xen_hvm_cpu_up; ---- vanilla-3.0.3.orig/arch/x86/platform/olpc/olpc.c -+++ vanilla-3.0.3/arch/x86/platform/olpc/olpc.c -@@ -157,13 +157,13 @@ restart: - if (inbuf && inlen) { - /* write data to EC */ - for (i = 0; i < inlen; i++) { -+ pr_devel("olpc-ec: sending cmd arg 0x%x\n", inbuf[i]); -+ outb(inbuf[i], 0x68); - if (wait_on_ibf(0x6c, 0)) { - printk(KERN_ERR "olpc-ec: timeout waiting for" - " EC accept data!\n"); - goto err; - } -- pr_devel("olpc-ec: sending cmd arg 0x%x\n", inbuf[i]); -- outb(inbuf[i], 0x68); - } - } - if (outbuf && outlen) { ---- vanilla-3.0.3.orig/arch/x86/vdso/vdso32/sysenter.S -+++ vanilla-3.0.3/arch/x86/vdso/vdso32/sysenter.S -@@ -43,7 +43,7 @@ __kernel_vsyscall: - .space 7,0x90 - - /* 14: System call restart point is here! (SYSENTER_RETURN-2) */ -- jmp .Lenter_kernel -+ int $0x80 - /* 16: System call normal return point is here! */ - VDSO32_SYSENTER_RETURN: /* Symbol used by sysenter.c via vdso32-syms.h */ - pop %ebp ---- vanilla-3.0.3.orig/arch/x86/kernel/apic/x2apic_uv_x.c -+++ vanilla-3.0.3/arch/x86/kernel/apic/x2apic_uv_x.c -@@ -207,7 +207,6 @@ static int __cpuinit uv_wakeup_secondary - ((start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) | - APIC_DM_INIT; - uv_write_global_mmr64(pnode, UVH_IPI_INT, val); -- mdelay(10); - - val = (1UL << UVH_IPI_INT_SEND_SHFT) | - (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) | ---- vanilla-3.0.3.orig/drivers/gpu/drm/ttm/ttm_bo.c -+++ vanilla-3.0.3/drivers/gpu/drm/ttm/ttm_bo.c -@@ -353,8 +353,10 @@ static int ttm_bo_add_ttm(struct ttm_buf - - ret = ttm_tt_set_user(bo->ttm, current, - bo->buffer_start, bo->num_pages); -- if (unlikely(ret != 0)) -+ if (unlikely(ret != 0)) { - ttm_tt_destroy(bo->ttm); -+ bo->ttm = NULL; -+ } - break; - default: - printk(KERN_ERR TTM_PFX "Illegal buffer object type\n"); ---- vanilla-3.0.3.orig/drivers/gpu/drm/radeon/radeon_connectors.c -+++ vanilla-3.0.3/drivers/gpu/drm/radeon/radeon_connectors.c -@@ -466,6 +466,16 @@ static bool radeon_connector_needs_exten - (supported_device == ATOM_DEVICE_DFP2_SUPPORT)) - return true; - } -+ /* TOSHIBA Satellite L300D with ATI Mobility Radeon x1100 -+ * (RS690M) sends data to i2c bus for a HDMI connector that -+ * is not implemented */ -+ if ((dev->pdev->device == 0x791f) && -+ (dev->pdev->subsystem_vendor == 0x1179) && -+ (dev->pdev->subsystem_device == 0xff68)) { -+ if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) && -+ (supported_device == ATOM_DEVICE_DFP2_SUPPORT)) -+ return true; -+ } - - /* Default: no EDID header probe required for DDC probing */ - return false; ---- vanilla-3.0.3.orig/fs/fuse/dev.c -+++ vanilla-3.0.3/fs/fuse/dev.c -@@ -1358,6 +1358,10 @@ static int fuse_notify_inval_entry(struc - if (outarg.namelen > FUSE_NAME_MAX) - goto err; - -+ err = -EINVAL; -+ if (size != sizeof(outarg) + outarg.namelen + 1) -+ goto err; -+ - name.name = buf; - name.len = outarg.namelen; - err = fuse_copy_one(cs, buf, outarg.namelen + 1); ---- vanilla-3.0.3.orig/drivers/net/wireless/rt2x00/rt2x00usb.c -+++ vanilla-3.0.3/drivers/net/wireless/rt2x00/rt2x00usb.c -@@ -262,23 +262,20 @@ static void rt2x00usb_interrupt_txdone(s - struct queue_entry *entry = (struct queue_entry *)urb->context; - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - -- if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) -+ if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) - return; -- -- if (rt2x00dev->ops->lib->tx_dma_done) -- rt2x00dev->ops->lib->tx_dma_done(entry); -- -- /* -- * Report the frame as DMA done -- */ -- rt2x00lib_dmadone(entry); -- - /* - * Check if the frame was correctly uploaded - */ - if (urb->status) - set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); -+ /* -+ * Report the frame as DMA done -+ */ -+ rt2x00lib_dmadone(entry); - -+ if (rt2x00dev->ops->lib->tx_dma_done) -+ rt2x00dev->ops->lib->tx_dma_done(entry); - /* - * Schedule the delayed work for reading the TX status - * from the device. ---- vanilla-3.0.3.orig/drivers/mmc/host/sdhci.c -+++ vanilla-3.0.3/drivers/mmc/host/sdhci.c -@@ -1863,9 +1863,6 @@ static void sdhci_tasklet_finish(unsigne - - del_timer(&host->timer); - -- if (host->version >= SDHCI_SPEC_300) -- del_timer(&host->tuning_timer); -- - mrq = host->mrq; - - /* ---- vanilla-3.0.3.orig/drivers/net/igb/e1000_82575.c -+++ vanilla-3.0.3/drivers/net/igb/e1000_82575.c -@@ -1735,6 +1735,7 @@ static s32 igb_reset_hw_82580(struct e10 - ctrl |= E1000_CTRL_RST; - - wr32(E1000_CTRL, ctrl); -+ wrfl(); - - /* Add delay to insure DEV_RST has time to complete */ - if (global_device_reset) +nil diff --git a/xen-blkfront-name-adjust.patch b/xen-blkfront-name-adjust.patch deleted file mode 100644 index 9573c7bf5..000000000 --- a/xen-blkfront-name-adjust.patch +++ /dev/null @@ -1,30 +0,0 @@ -commit 196cfe2ae8fcdc03b3c7d627e7dfe8c0ce7229f9 -Author: Stefan Bader -Date: Thu Jul 14 15:30:22 2011 +0200 - - xen-blkfront: Drop name and minor adjustments for emulated scsi devices - - These were intended to avoid the namespace clash when representing - emulated IDE and SCSI devices. However that seems to confuse users - more than expected (a disk defined as sda becomes xvde). - So for now go back to the scheme which does no adjustments. This - will break when mixing IDE and SCSI names in the configuration of - guests but should be by now expected. - - Acked-by: Stefano Stabellini - Signed-off-by: Stefan Bader - Signed-off-by: Konrad Rzeszutek Wilk - ---- linux-2.6.39.noarch/drivers/block/xen-blkfront.c~ 2011-08-11 11:54:25.656150889 -0400 -+++ linux-2.6.39.noarch/drivers/block/xen-blkfront.c 2011-08-11 11:54:54.573046334 -0400 -@@ -123,8 +123,8 @@ static DEFINE_SPINLOCK(minor_lock); - #define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED)) - #define EMULATED_HD_DISK_MINOR_OFFSET (0) - #define EMULATED_HD_DISK_NAME_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET / 256) --#define EMULATED_SD_DISK_MINOR_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET + (4 * 16)) --#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_HD_DISK_NAME_OFFSET + 4) -+#define EMULATED_SD_DISK_MINOR_OFFSET (0) -+#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_SD_DISK_MINOR_OFFSET / 256) - - #define DEV_NAME "xvd" /* name in /dev */ - From f2b0200bfa3021f9d5ac225e08f65e340bc70471 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 30 Aug 2011 08:58:14 -0400 Subject: [PATCH 157/397] Add patch to fix rhbz 606017 --- ...ensure-thermal-limits-match-cpu-freq.patch | 128 ++++++++++++++++++ kernel.spec | 7 +- 2 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 acpi-ensure-thermal-limits-match-cpu-freq.patch diff --git a/acpi-ensure-thermal-limits-match-cpu-freq.patch b/acpi-ensure-thermal-limits-match-cpu-freq.patch new file mode 100644 index 000000000..3945af197 --- /dev/null +++ b/acpi-ensure-thermal-limits-match-cpu-freq.patch @@ -0,0 +1,128 @@ +The ACPI thermal management code supports slowing down a CPU when it's +overheating. Right now that's done by choosing to run it at 100%, 75%, 50% +or 25% of full speed. However, most CPUs do not allow an arbitrary +frequency to be set and so will run at the first frequency below that value. +This doesn't match the intent of the specification, which is to drop the +frequency state by state until the temperature stabalises. Fix this up +so it uses actual frequencies rather than percentages. + +Reported by: Gene Snider +Signed-off-by: Matthew Garrett +--- + drivers/acpi/processor_thermal.c | 45 +++++++++++++++++++++---------------- + 1 files changed, 25 insertions(+), 20 deletions(-) + +diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c +index 870550d..1c4eb60 100644 +--- a/drivers/acpi/processor_thermal.c ++++ b/drivers/acpi/processor_thermal.c +@@ -52,10 +52,8 @@ ACPI_MODULE_NAME("processor_thermal"); + * _any_ cpufreq driver and not only the acpi-cpufreq driver. + */ + +-#define CPUFREQ_THERMAL_MIN_STEP 0 +-#define CPUFREQ_THERMAL_MAX_STEP 3 + +-static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg); ++static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_limit_state); + static unsigned int acpi_thermal_cpufreq_is_init = 0; + + static int cpu_has_cpufreq(unsigned int cpu) +@@ -70,19 +68,19 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, + unsigned long event, void *data) + { + struct cpufreq_policy *policy = data; +- unsigned long max_freq = 0; ++ int state = per_cpu(cpufreq_thermal_limit_state, policy->cpu); ++ struct cpufreq_frequency_table *table; + + if (event != CPUFREQ_ADJUST) +- goto out; ++ return 0; ++ ++ table = cpufreq_frequency_get_table(policy->cpu); + +- max_freq = ( +- policy->cpuinfo.max_freq * +- (100 - per_cpu(cpufreq_thermal_reduction_pctg, policy->cpu) * 20) +- ) / 100; ++ if (!table) ++ return 0; + +- cpufreq_verify_within_limits(policy, 0, max_freq); ++ cpufreq_verify_within_limits(policy, 0, table[state].frequency); + +- out: + return 0; + } + +@@ -92,10 +90,21 @@ static struct notifier_block acpi_thermal_cpufreq_notifier_block = { + + static int cpufreq_get_max_state(unsigned int cpu) + { ++ int count = 0; ++ struct cpufreq_frequency_table *table; ++ + if (!cpu_has_cpufreq(cpu)) + return 0; + +- return CPUFREQ_THERMAL_MAX_STEP; ++ table = cpufreq_frequency_get_table(cpu); ++ ++ if (!table) ++ return 0; ++ ++ while (table[count].frequency != CPUFREQ_TABLE_END) ++ count++; ++ ++ return count; + } + + static int cpufreq_get_cur_state(unsigned int cpu) +@@ -103,7 +112,7 @@ static int cpufreq_get_cur_state(unsigned int cpu) + if (!cpu_has_cpufreq(cpu)) + return 0; + +- return per_cpu(cpufreq_thermal_reduction_pctg, cpu); ++ return per_cpu(cpufreq_thermal_limit_state, cpu); + } + + static int cpufreq_set_cur_state(unsigned int cpu, int state) +@@ -111,7 +120,7 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state) + if (!cpu_has_cpufreq(cpu)) + return 0; + +- per_cpu(cpufreq_thermal_reduction_pctg, cpu) = state; ++ per_cpu(cpufreq_thermal_limit_state, cpu) = state; + cpufreq_update_policy(cpu); + return 0; + } +@@ -122,7 +131,7 @@ void acpi_thermal_cpufreq_init(void) + + for (i = 0; i < nr_cpu_ids; i++) + if (cpu_present(i)) +- per_cpu(cpufreq_thermal_reduction_pctg, i) = 0; ++ per_cpu(cpufreq_thermal_limit_state, i) = 0; + + i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block, + CPUFREQ_POLICY_NOTIFIER); +@@ -170,15 +179,11 @@ int acpi_processor_get_limit_info(struct acpi_processor *pr) + return 0; + } + +-/* thermal coolign device callbacks */ ++/* thermal cooling device callbacks */ + static int acpi_processor_max_state(struct acpi_processor *pr) + { + int max_state = 0; + +- /* +- * There exists four states according to +- * cpufreq_thermal_reduction_ptg. 0, 1, 2, 3 +- */ + max_state += cpufreq_get_max_state(pr->id); + if (pr->flags.throttling) + max_state += (pr->throttling.state_count -1); +-- +1.7.6.1 + diff --git a/kernel.spec b/kernel.spec index 345b79516..857686901 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -585,6 +585,7 @@ Patch390: linux-2.6-defaults-acpi-video.patch 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 +Patch395: acpi-ensure-thermal-limits-match-cpu-freq.patch Patch450: linux-2.6-input-kill-stupid-messages.patch Patch452: linux-2.6.30-no-pcspkr-modalias.patch @@ -1118,6 +1119,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-ensure-thermal-limits-match-cpu-freq.patch # Various low-impact patches to aid debugging. ApplyPatch linux-2.6-debug-taint-vm.patch @@ -1849,6 +1851,9 @@ fi # and build. %changelog +* Tue Aug 30 2011 Josh Boyer +- Add patch to fix rhbz 606017 + * Mon Aug 29 2011 Chuck Ebbert 2.6.40.4-3 - Linux 3.0.4 From d6189c7ffdde4b405bc3f07b5ca801bcb8b8051d Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Tue, 30 Aug 2011 09:18:58 -0400 Subject: [PATCH 158/397] Fix unsafe pointer access in sendmsg/sendmmsg --- kernel.spec | 11 +++- ...ndmsg-fix-unsafe-user-pointer-access.patch | 60 +++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 sendmmsg-sendmsg-fix-unsafe-user-pointer-access.patch diff --git a/kernel.spec b/kernel.spec index 345b79516..a4d9e5f22 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -680,6 +680,9 @@ Patch21004: vfs-fix-automount-for-negative-autofs-dentries.patch # rhbz#727927 rhbz#731278 rhbz#732934 Patch21005: cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch +# from 3.0.5 patch queue +Patch21006: sendmmsg-sendmsg-fix-unsafe-user-pointer-access.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1229,6 +1232,9 @@ ApplyPatch vfs-fix-automount-for-negative-autofs-dentries.patch # cifs-possible-memory-corruption-on-mount.patch is already queued for 3.0.4 ApplyPatch cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch +# from 3.0.5 patch queue +ApplyPatch sendmmsg-sendmsg-fix-unsafe-user-pointer-access.patch + # END OF PATCH APPLICATIONS %endif @@ -1849,6 +1855,9 @@ fi # and build. %changelog +* Tue Aug 30 2011 Chuck Ebbert 2.6.40.4-4 +- Fix unsafe pointer access in sendmsg/sendmmsg + * Mon Aug 29 2011 Chuck Ebbert 2.6.40.4-3 - Linux 3.0.4 diff --git a/sendmmsg-sendmsg-fix-unsafe-user-pointer-access.patch b/sendmmsg-sendmsg-fix-unsafe-user-pointer-access.patch new file mode 100644 index 000000000..0f85bd910 --- /dev/null +++ b/sendmmsg-sendmsg-fix-unsafe-user-pointer-access.patch @@ -0,0 +1,60 @@ +From bc909d9ddbf7778371e36a651d6e4194b1cc7d4c Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers +Date: Wed, 24 Aug 2011 19:45:03 -0700 +Subject: sendmmsg/sendmsg: fix unsafe user pointer access + +From: Mathieu Desnoyers + +commit bc909d9ddbf7778371e36a651d6e4194b1cc7d4c upstream. + +Dereferencing a user pointer directly from kernel-space without going +through the copy_from_user family of functions is a bad idea. Two of +such usages can be found in the sendmsg code path called from sendmmsg, +added by + +commit c71d8ebe7a4496fb7231151cb70a6baa0cb56f9a upstream. +commit 5b47b8038f183b44d2d8ff1c7d11a5c1be706b34 in the 3.0-stable tree. + +Usages are performed through memcmp() and memcpy() directly. Fix those +by using the already copied msg_sys structure instead of the __user *msg +structure. Note that msg_sys can be set to NULL by verify_compat_iovec() +or verify_iovec(), which requires additional NULL pointer checks. + +Signed-off-by: Mathieu Desnoyers +Signed-off-by: David Goulet +CC: Tetsuo Handa +CC: Anton Blanchard +CC: David S. Miller +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + net/socket.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/net/socket.c ++++ b/net/socket.c +@@ -1965,8 +1965,9 @@ static int __sys_sendmsg(struct socket * + * used_address->name_len is initialized to UINT_MAX so that the first + * destination address never matches. + */ +- if (used_address && used_address->name_len == msg_sys->msg_namelen && +- !memcmp(&used_address->name, msg->msg_name, ++ if (used_address && msg_sys->msg_name && ++ used_address->name_len == msg_sys->msg_namelen && ++ !memcmp(&used_address->name, msg_sys->msg_name, + used_address->name_len)) { + err = sock_sendmsg_nosec(sock, msg_sys, total_len); + goto out_freectl; +@@ -1978,8 +1979,9 @@ static int __sys_sendmsg(struct socket * + */ + if (used_address && err >= 0) { + used_address->name_len = msg_sys->msg_namelen; +- memcpy(&used_address->name, msg->msg_name, +- used_address->name_len); ++ if (msg_sys->msg_name) ++ memcpy(&used_address->name, msg_sys->msg_name, ++ used_address->name_len); + } + + out_freectl: From 1c814032e0c813db3a0d705d2890c51aaef15168 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 30 Aug 2011 10:18:01 -0400 Subject: [PATCH 159/397] Fixup acpi patch to select CPU_FREQ_TABLE so we don't get an undefined link error --- ...ensure-thermal-limits-match-cpu-freq.patch | 22 +++++++++++++++++-- kernel.spec | 5 ++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/acpi-ensure-thermal-limits-match-cpu-freq.patch b/acpi-ensure-thermal-limits-match-cpu-freq.patch index 3945af197..9d97b6024 100644 --- a/acpi-ensure-thermal-limits-match-cpu-freq.patch +++ b/acpi-ensure-thermal-limits-match-cpu-freq.patch @@ -1,3 +1,8 @@ +From 9a056a5843ff83db987d6e18625f4a2ee64b5450 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Tue, 30 Aug 2011 10:07:24 -0400 +Subject: [PATCH] ACPI: Ensure thermal limits match CPU frequencies + The ACPI thermal management code supports slowing down a CPU when it's overheating. Right now that's done by choosing to run it at 100%, 75%, 50% or 25% of full speed. However, most CPUs do not allow an arbitrary @@ -9,9 +14,22 @@ so it uses actual frequencies rather than percentages. Reported by: Gene Snider Signed-off-by: Matthew Garrett --- + drivers/acpi/Kconfig | 1 + drivers/acpi/processor_thermal.c | 45 +++++++++++++++++++++---------------- - 1 files changed, 25 insertions(+), 20 deletions(-) + 2 files changed, 26 insertions(+), 20 deletions(-) +diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig +index de0e3df..7d1bdb5 100644 +--- a/drivers/acpi/Kconfig ++++ b/drivers/acpi/Kconfig +@@ -185,6 +185,7 @@ config ACPI_PROCESSOR + tristate "Processor" + select THERMAL + select CPU_IDLE ++ select CPU_FREQ_TABLE + default y + help + This driver installs ACPI as the idle handler for Linux and uses diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 870550d..1c4eb60 100644 --- a/drivers/acpi/processor_thermal.c @@ -124,5 +142,5 @@ index 870550d..1c4eb60 100644 if (pr->flags.throttling) max_state += (pr->throttling.state_count -1); -- -1.7.6.1 +1.7.6 diff --git a/kernel.spec b/kernel.spec index c1a0e152e..2ec686e95 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -1857,6 +1857,9 @@ fi # and build. %changelog +* Tue Aug 30 2011 Josh Boyer 2.6.40.4-5 +- Fix kconfig error in patch for rhbz 606017 + * Tue Aug 30 2011 Chuck Ebbert 2.6.40.4-4 - Fix unsafe pointer access in sendmsg/sendmmsg From 144f5a9a826508c3c5b991bcc61015344318529b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 31 Aug 2011 12:05:50 -0400 Subject: [PATCH 160/397] Reinstate some conflicts: that disappeared during the rebase (rhbz 710646) --- kernel.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 2ec686e95..b45b59955 100644 --- a/kernel.spec +++ b/kernel.spec @@ -406,7 +406,7 @@ Summary: The Linux kernel # First the general kernel 2.6 required versions as per # Documentation/Changes # -%define kernel_dot_org_conflicts ppp < 2.4.3-3, isdn4k-utils < 3.2-32, nfs-utils < 1.0.7-12, e2fsprogs < 1.37-4, util-linux < 2.12, jfsutils < 1.1.7-2, reiserfs-utils < 3.6.19-2, xfsprogs < 2.6.13-4, procps < 3.2.5-6.3, oprofile < 0.9.1-2 +%define kernel_dot_org_conflicts ppp < 2.4.3-3, isdn4k-utils < 3.2-32, nfs-utils < 1.0.7-12, e2fsprogs < 1.37-4, util-linux < 2.12, jfsutils < 1.1.7-2, reiserfs-utils < 3.6.19-2, xfsprogs < 2.6.13-4, procps < 3.2.5-6.3, oprofile < 0.9.1-2, device-mapper-libs < 1.02.63-2, mdadm < 3.2.1-5 # # Then a series of requirements that are distribution specific, either @@ -1857,6 +1857,9 @@ fi # and build. %changelog +* Wed Aug 31 2011 Dave Jones +- Reinstate some conflicts: that disappeared during the rebase (rhbz 710646) + * Tue Aug 30 2011 Josh Boyer 2.6.40.4-5 - Fix kconfig error in patch for rhbz 606017 From 13db1541cba4f77affe151f736cb56baaa7b1a96 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 7 Sep 2011 12:23:33 -0400 Subject: [PATCH 161/397] Fix for rhbz 735437 --- kernel.spec | 11 +++++- ucvideo-fix-crash-when-linking-entities.patch | 34 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 ucvideo-fix-crash-when-linking-entities.patch diff --git a/kernel.spec b/kernel.spec index b45b59955..6e1b549bb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 5 +%global baserelease 6 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -684,6 +684,9 @@ Patch21005: cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch # from 3.0.5 patch queue Patch21006: sendmmsg-sendmsg-fix-unsafe-user-pointer-access.patch +# rhbz #735437 +Patch21007: ucvideo-fix-crash-when-linking-entities.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1237,6 +1240,9 @@ ApplyPatch cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch # from 3.0.5 patch queue ApplyPatch sendmmsg-sendmsg-fix-unsafe-user-pointer-access.patch +#rhbz 735437 +ApplyPatch ucvideo-fix-crash-when-linking-entities.patch + # END OF PATCH APPLICATIONS %endif @@ -1857,6 +1863,9 @@ fi # and build. %changelog +* Wed Sep 07 2011 Josh Boyer +- Add patch to fix oops when linking entities in ucvideo (rhbz 735437) + * Wed Aug 31 2011 Dave Jones - Reinstate some conflicts: that disappeared during the rebase (rhbz 710646) diff --git a/ucvideo-fix-crash-when-linking-entities.patch b/ucvideo-fix-crash-when-linking-entities.patch new file mode 100644 index 000000000..69f86d64c --- /dev/null +++ b/ucvideo-fix-crash-when-linking-entities.patch @@ -0,0 +1,34 @@ +The uvc_mc_register_entity() function wrongfully selects the +media_entity associated with a UVC entity when creating links. This +results in access to uninitialized media_entity structures and can hit a +BUG_ON statement in media_entity_create_link(). Fix it. + +Signed-off-by: Laurent Pinchart +--- + drivers/media/video/uvc/uvc_entity.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +This patch should fix a v3.0 regression that results in a kernel crash as +reported in http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=637740 and +https://bugzilla.redhat.com/show_bug.cgi?id=735437. + +Test results will be welcome. + +diff --git a/drivers/media/video/uvc/uvc_entity.c b/drivers/media/video/uvc/uvc_entity.c +index 48fea37..29e2399 100644 +--- a/drivers/media/video/uvc/uvc_entity.c ++++ b/drivers/media/video/uvc/uvc_entity.c +@@ -49,7 +49,7 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain, + if (remote == NULL) + return -EINVAL; + +- source = (UVC_ENTITY_TYPE(remote) != UVC_TT_STREAMING) ++ source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING) + ? (remote->vdev ? &remote->vdev->entity : NULL) + : &remote->subdev.entity; + if (source == NULL) +-- +Regards, + +Laurent Pinchart + From 8aa7f7a64727577fae7697501e22c91583cae704 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 15 Sep 2011 10:12:52 -0400 Subject: [PATCH 162/397] Fix CVE-2011-3191 --- ...le-memory-corruption-in-CIFSFindNext.patch | 82 +++++++++++++++++++ kernel.spec | 9 ++ 2 files changed, 91 insertions(+) create mode 100644 cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch diff --git a/cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch b/cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch new file mode 100644 index 000000000..06fc5c74a --- /dev/null +++ b/cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch @@ -0,0 +1,82 @@ +Path: news.gmane.org!not-for-mail +From: Jeff Layton +Newsgroups: gmane.linux.kernel.cifs +Subject: [PATCH] cifs: fix possible memory corruption in CIFSFindNext +Date: Tue, 23 Aug 2011 07:21:28 -0400 +Lines: 37 +Approved: news@gmane.org +Message-ID: <1314098488-1547-1-git-send-email-jlayton@redhat.com> +NNTP-Posting-Host: lo.gmane.org +X-Trace: dough.gmane.org 1314098501 27164 80.91.229.12 (23 Aug 2011 11:21:41 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Tue, 23 Aug 2011 11:21:41 +0000 (UTC) +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, dcl-HN4QTLPn1qTvY7RNz7mR4EEOCMrvLtNR@public.gmane.org +To: smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org +Original-X-From: linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Tue Aug 23 13:21:37 2011 +Return-path: +Envelope-to: glkc-linux-cifs-1dZseelyfdZg9hUCZPvPmw@public.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1Qvp33-0003JC-05 + for glkc-linux-cifs-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Tue, 23 Aug 2011 13:21:37 +0200 +Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand + id S1752435Ab1HWLVg (ORCPT ); + Tue, 23 Aug 2011 07:21:36 -0400 +Original-Received: from mail-gy0-f174.google.com ([209.85.160.174]:43114 "EHLO + mail-gy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1751065Ab1HWLVf (ORCPT + ); Tue, 23 Aug 2011 07:21:35 -0400 +Original-Received: by gya6 with SMTP id 6so4228912gya.19 + for ; Tue, 23 Aug 2011 04:21:35 -0700 (PDT) +Original-Received: by 10.101.144.18 with SMTP id w18mr3505731ann.133.1314098494691; + Tue, 23 Aug 2011 04:21:34 -0700 (PDT) +Original-Received: from salusa.poochiereds.net (cpe-075-177-182-191.nc.res.rr.com [75.177.182.191]) + by mx.google.com with ESMTPS id d33sm48355ano.35.2011.08.23.04.21.32 + (version=SSLv3 cipher=OTHER); + Tue, 23 Aug 2011 04:21:33 -0700 (PDT) +X-Mailer: git-send-email 1.7.6 +Original-Sender: linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Xref: news.gmane.org gmane.linux.kernel.cifs:4006 +Archived-At: + +The name_len variable in CIFSFindNext is a signed int that gets set to +the resume_name_len in the cifs_search_info. The resume_name_len however +is unsigned and for some infolevels is populated directly from a 32 bit +value sent by the server. + +If the server sends a very large value for this, then that value could +look negative when converted to a signed int. That would make that +value pass the PATH_MAX check later in CIFSFindNext. The name_len would +then be used as a length value for a memcpy. It would then be treated +as unsigned again, and the memcpy scribbles over a ton of memory. + +Fix this by making the name_len an unsigned value in CIFSFindNext. + +Cc: +Reported-by: Darren Lavender +Signed-off-by: Jeff Layton +--- + fs/cifs/cifssmb.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c +index f4d0988..950464d 100644 +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -4089,7 +4089,8 @@ int CIFSFindNext(const int xid, struct cifs_tcon *tcon, + T2_FNEXT_RSP_PARMS *parms; + char *response_data; + int rc = 0; +- int bytes_returned, name_len; ++ int bytes_returned; ++ unsigned int name_len; + __u16 params, byte_count; + + cFYI(1, "In FindNext"); +-- +1.7.6 + diff --git a/kernel.spec b/kernel.spec index 6e1b549bb..f5e468fb0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -687,6 +687,9 @@ Patch21006: sendmmsg-sendmsg-fix-unsafe-user-pointer-access.patch # rhbz #735437 Patch21007: ucvideo-fix-crash-when-linking-entities.patch +# CVE-2011-3192 +Patch21008: cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1243,6 +1246,9 @@ ApplyPatch sendmmsg-sendmsg-fix-unsafe-user-pointer-access.patch #rhbz 735437 ApplyPatch ucvideo-fix-crash-when-linking-entities.patch +# CVE-2011-3191 +ApplyPatch cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch + # END OF PATCH APPLICATIONS %endif @@ -1863,6 +1869,9 @@ fi # and build. %changelog +* Thu Sep 15 2011 Josh Boyer +- CVE-2011-3191: cifs: fix possible memory corruption in CIFSFindNext + * Wed Sep 07 2011 Josh Boyer - Add patch to fix oops when linking entities in ucvideo (rhbz 735437) From eae267fb0472df2ba9d7ad76f099f591656a5def Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Thu, 22 Sep 2011 16:35:46 -0500 Subject: [PATCH 163/397] * Thu Sep 22 2011 Dennis Gilmore - build a vmlinux image on sparc64 --- kernel.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index f5e468fb0..fb60811d4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -308,8 +308,8 @@ Summary: The Linux kernel %ifarch sparc64 %define asmarch sparc %define all_arch_configs kernel-%{version}-sparc64*.config -%define make_target image -%define kernel_image arch/sparc/boot/image +%define make_target vmlinux +%define kernel_image vmlinux %define image_install_path boot %define with_perf 0 %endif @@ -1869,6 +1869,9 @@ fi # and build. %changelog +* Thu Sep 22 2011 Dennis Gilmore +- build a vmlinux image on sparc64 + * Thu Sep 15 2011 Josh Boyer - CVE-2011-3191: cifs: fix possible memory corruption in CIFSFindNext From bbc0f03b3029a3cb8eacdadc0a1d83d425e47769 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 23 Sep 2011 10:44:18 -0400 Subject: [PATCH 164/397] Fix CVE-2011-1161 CVE-2011-1162 --- TPM-Call-tpm_transmit-with-correct-size.patch | 43 ++++++++++++++++++ ...ro-buffer-after-copying-to-userspace.patch | 45 +++++++++++++++++++ kernel.spec | 11 +++++ 3 files changed, 99 insertions(+) create mode 100644 TPM-Call-tpm_transmit-with-correct-size.patch create mode 100644 TPM-Zero-buffer-after-copying-to-userspace.patch diff --git a/TPM-Call-tpm_transmit-with-correct-size.patch b/TPM-Call-tpm_transmit-with-correct-size.patch new file mode 100644 index 000000000..64f776f13 --- /dev/null +++ b/TPM-Call-tpm_transmit-with-correct-size.patch @@ -0,0 +1,43 @@ +From 6b07d30aca7e52f2881b8c8c20c8a2cd28e8b3d3 Mon Sep 17 00:00:00 2001 +From: Peter Huewe +Date: Thu, 15 Sep 2011 14:37:43 -0300 +Subject: [PATCH] TPM: Call tpm_transmit with correct size + +This patch changes the call of tpm_transmit by supplying the size of the +userspace buffer instead of TPM_BUFSIZE. + +This got assigned CVE-2011-1161. + +[The first hunk didn't make sense given one could expect + way less data than TPM_BUFSIZE, so added tpm_transmit boundary + check over bufsiz instead + The last parameter of tpm_transmit() reflects the amount + of data expected from the device, and not the buffer size + being supplied to it. It isn't ideal to parse it directly, + so we just set it to the maximum the input buffer can handle + and let the userspace API to do such job.] + +Signed-off-by: Rajiv Andrade +Cc: Stable Kernel +Signed-off-by: James Morris +--- + drivers/char/tpm/tpm.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c +index caf8012..1fe9793 100644 +--- a/drivers/char/tpm/tpm.c ++++ b/drivers/char/tpm/tpm.c +@@ -383,6 +383,9 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, + u32 count, ordinal; + unsigned long stop; + ++ if (bufsiz > TPM_BUFSIZE) ++ bufsiz = TPM_BUFSIZE; ++ + count = be32_to_cpu(*((__be32 *) (buf + 2))); + ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); + if (count == 0) +-- +1.7.6 + diff --git a/TPM-Zero-buffer-after-copying-to-userspace.patch b/TPM-Zero-buffer-after-copying-to-userspace.patch new file mode 100644 index 000000000..1b3d9ac48 --- /dev/null +++ b/TPM-Zero-buffer-after-copying-to-userspace.patch @@ -0,0 +1,45 @@ +From 3321c07ae5068568cd61ac9f4ba749006a7185c9 Mon Sep 17 00:00:00 2001 +From: Peter Huewe +Date: Thu, 15 Sep 2011 14:47:42 -0300 +Subject: [PATCH] TPM: Zero buffer after copying to userspace + +Since the buffer might contain security related data it might be a good idea to +zero the buffer after we have copied it to userspace. + +This got assigned CVE-2011-1162. + +Signed-off-by: Rajiv Andrade +Cc: Stable Kernel +Signed-off-by: James Morris +--- + drivers/char/tpm/tpm.c | 6 +++++- + 1 files changed, 5 insertions(+), 1 deletions(-) + +diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c +index 1fe9793..9ca5c02 100644 +--- a/drivers/char/tpm/tpm.c ++++ b/drivers/char/tpm/tpm.c +@@ -1105,6 +1105,7 @@ ssize_t tpm_read(struct file *file, char __user *buf, + { + struct tpm_chip *chip = file->private_data; + ssize_t ret_size; ++ int rc; + + del_singleshot_timer_sync(&chip->user_read_timer); + flush_work_sync(&chip->work); +@@ -1115,8 +1116,11 @@ ssize_t tpm_read(struct file *file, char __user *buf, + ret_size = size; + + mutex_lock(&chip->buffer_mutex); +- if (copy_to_user(buf, chip->data_buffer, ret_size)) ++ rc = copy_to_user(buf, chip->data_buffer, ret_size); ++ memset(chip->data_buffer, 0, ret_size); ++ if (rc) + ret_size = -EFAULT; ++ + mutex_unlock(&chip->buffer_mutex); + } + +-- +1.7.6 + diff --git a/kernel.spec b/kernel.spec index fb60811d4..df0b98483 100644 --- a/kernel.spec +++ b/kernel.spec @@ -690,6 +690,10 @@ Patch21007: ucvideo-fix-crash-when-linking-entities.patch # CVE-2011-3192 Patch21008: cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch +# CVE-2011-1161 CVE-2011-1162 +Patch21009: TPM-Call-tpm_transmit-with-correct-size.patch +Patch21010: TPM-Zero-buffer-after-copying-to-userspace.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1249,6 +1253,10 @@ ApplyPatch ucvideo-fix-crash-when-linking-entities.patch # CVE-2011-3191 ApplyPatch cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch +# CVE-2011-1161 CVE-2011-1162 +ApplyPatch TPM-Call-tpm_transmit-with-correct-size.patch +ApplyPatch TPM-Zero-buffer-after-copying-to-userspace.patch + # END OF PATCH APPLICATIONS %endif @@ -1869,6 +1877,9 @@ fi # and build. %changelog +* Fri Sep 23 2011 Josh Boyer +- CVE-2011-1161 CVE-2011-1162: tpm: infoleaks + * Thu Sep 22 2011 Dennis Gilmore - build a vmlinux image on sparc64 From a949670cf06e4496cafdbf3a61fedaaea4087417 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 23 Sep 2011 11:44:36 -0400 Subject: [PATCH 165/397] Add patch to fix 1 second delay from MD driver during shutdown (rhbz 740645) --- kernel.spec | 7 ++ ...-reboot-by-1-second-if-no-MD-devices.patch | 110 ++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 md-dont-delay-reboot-by-1-second-if-no-MD-devices.patch diff --git a/kernel.spec b/kernel.spec index df0b98483..344d33202 100644 --- a/kernel.spec +++ b/kernel.spec @@ -694,6 +694,9 @@ Patch21008: cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch Patch21009: TPM-Call-tpm_transmit-with-correct-size.patch Patch21010: TPM-Zero-buffer-after-copying-to-userspace.patch +# rhbz #740645 +Patch21011: md-dont-delay-reboot-by-1-second-if-no-MD-devices.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1257,6 +1260,9 @@ ApplyPatch cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch ApplyPatch TPM-Call-tpm_transmit-with-correct-size.patch ApplyPatch TPM-Zero-buffer-after-copying-to-userspace.patch +#rhbz 740645 +ApplyPatch md-dont-delay-reboot-by-1-second-if-no-MD-devices.patch + # END OF PATCH APPLICATIONS %endif @@ -1878,6 +1884,7 @@ fi %changelog * Fri Sep 23 2011 Josh Boyer +- Add patch to fix 1 second delay from MD driver during shutdown (rhbz 740645) - CVE-2011-1161 CVE-2011-1162: tpm: infoleaks * Thu Sep 22 2011 Dennis Gilmore diff --git a/md-dont-delay-reboot-by-1-second-if-no-MD-devices.patch b/md-dont-delay-reboot-by-1-second-if-no-MD-devices.patch new file mode 100644 index 000000000..0ce4896de --- /dev/null +++ b/md-dont-delay-reboot-by-1-second-if-no-MD-devices.patch @@ -0,0 +1,110 @@ +Path: news.gmane.org!not-for-mail +From: "Daniel P. Berrange" +Newsgroups: gmane.linux.raid,gmane.linux.kernel +Subject: [PATCH] md: don't delay reboot by 1 second if no MD devices exist +Date: Fri, 23 Sep 2011 10:40:45 +0100 +Lines: 65 +Approved: news@gmane.org +Message-ID: <1316770845-18171-1-git-send-email-berrange@redhat.com> +NNTP-Posting-Host: lo.gmane.org +X-Trace: dough.gmane.org 1316770900 21954 80.91.229.12 (23 Sep 2011 09:41:40 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Fri, 23 Sep 2011 09:41:40 +0000 (UTC) +Cc: linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org, + "Daniel P. Berrange" +To: Neil Brown +Original-X-From: linux-raid-owner@vger.kernel.org Fri Sep 23 11:41:35 2011 +Return-path: +Envelope-to: linux-raid@lo.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1R72GD-0001vh-7L + for linux-raid@lo.gmane.org; Fri, 23 Sep 2011 11:41:33 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1752806Ab1IWJlT (ORCPT ); + Fri, 23 Sep 2011 05:41:19 -0400 +Original-Received: from mx1.redhat.com ([209.132.183.28]:18969 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1752669Ab1IWJlS (ORCPT ); + Fri, 23 Sep 2011 05:41:18 -0400 +Original-Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p8N9fGuK005549 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Fri, 23 Sep 2011 05:41:16 -0400 +Original-Received: from t500wlan.home.berrange.com.com (vpn1-7-26.ams2.redhat.com [10.36.7.26]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p8N9fDFC018631; + Fri, 23 Sep 2011 05:41:14 -0400 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +Original-Sender: linux-raid-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-raid@vger.kernel.org +Xref: news.gmane.org gmane.linux.raid:35508 gmane.linux.kernel:1194566 +Archived-At: + +From: "Daniel P. Berrange" + +The md_notify_reboot() method includes a call to mdelay(1000), +to deal with "exotic SCSI devices" which are too volatile on +reboot. The delay is unconditional. Even if the machine does +not have any block devices, let alone MD devices, the kernel +shutdown sequence is slowed down. + +1 second does not matter much with physical hardware, but with +certain virtualization use cases any wasted time in the bootup +& shutdown sequence counts for alot. + +* drivers/md/md.c: md_notify_reboot() - only impose a delay if + there was at least one MD device to be stopped during reboot + +Signed-off-by: Daniel P. Berrange +--- + drivers/md/md.c | 8 ++++++-- + 1 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 5404b22..ef7ad8d 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -8059,12 +8059,13 @@ static int md_notify_reboot(struct notifier_block *this, + { + struct list_head *tmp; + mddev_t *mddev; ++ int need_delay = 0; + + if ((code == SYS_DOWN) || (code == SYS_HALT) || (code == SYS_POWER_OFF)) { + + printk(KERN_INFO "md: stopping all md devices.\n"); + +- for_each_mddev(mddev, tmp) ++ for_each_mddev(mddev, tmp) { + if (mddev_trylock(mddev)) { + /* Force a switch to readonly even array + * appears to still be in use. Hence +@@ -8073,13 +8074,16 @@ static int md_notify_reboot(struct notifier_block *this, + md_set_readonly(mddev, 100); + mddev_unlock(mddev); + } ++ need_delay = 1; ++ } + /* + * certain more exotic SCSI devices are known to be + * volatile wrt too early system reboots. While the + * right place to handle this issue is the given + * driver, we do want to have a safe RAID driver ... + */ +- mdelay(1000*1); ++ if (need_delay) ++ mdelay(1000*1); + } + return NOTIFY_DONE; + } +-- +1.7.6.2 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-raid" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + From a2573a13a2c6a024d97577e062d2b89df2ec4d90 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 26 Sep 2011 09:39:04 -0400 Subject: [PATCH 166/397] Fix breakage of Apple MagicMouse/Trackpad (rhbz #714381) --- ...d-report-id-while-switching-modes-v2.patch | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patch diff --git a/hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patch b/hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patch new file mode 100644 index 000000000..cf87d2ad3 --- /dev/null +++ b/hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patch @@ -0,0 +1,62 @@ +From 35d851df23b093ee027f827fed2213ae5e88fc7a Mon Sep 17 00:00:00 2001 +From: Jiri Kosina +Date: Thu, 25 Aug 2011 14:21:37 +0200 +Subject: [PATCH] HID: magicmouse: ignore 'ivalid report id' while switching + modes, v2 + +This is basically a more generic respin of 23746a6 ("HID: magicmouse: ignore +'ivalid report id' while switching modes") which got reverted later by +c3a492. + +It turns out that on some configurations, this is actually still the case +and we are not able to detect in runtime. + +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 + +Reported-by: Chase Douglas +Reported-by: Jaikumar Ganesh +Tested-by: Chase Douglas +Tested-by: Jaikumar Ganesh +Signed-off-by: Jiri Kosina +--- + drivers/hid/hid-magicmouse.c | 10 +++++++++- + 1 files changed, 9 insertions(+), 1 deletions(-) + +diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c +index b5bdab3..f0fbd7b 100644 +--- a/drivers/hid/hid-magicmouse.c ++++ b/drivers/hid/hid-magicmouse.c +@@ -537,9 +537,17 @@ static int magicmouse_probe(struct hid_device *hdev, + } + report->size = 6; + ++ /* ++ * Some devices repond 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 && ret != sizeof(feature)) { + hid_err(hdev, "unable to request touch data (%d)\n", ret); + goto err_stop_hw; + } +-- +1.7.5.4 + From 41645d50203afbff2f0605b8b5a2180396a967e4 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Tue, 27 Sep 2011 09:25:51 -0400 Subject: [PATCH 167/397] Actually add the specfile change --- kernel.spec | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel.spec b/kernel.spec index 344d33202..2c53c9b7c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -697,6 +697,9 @@ Patch21010: TPM-Zero-buffer-after-copying-to-userspace.patch # rhbz #740645 Patch21011: md-dont-delay-reboot-by-1-second-if-no-MD-devices.patch +# rhbz #714381 +Patch21012: hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1263,6 +1266,9 @@ ApplyPatch TPM-Zero-buffer-after-copying-to-userspace.patch #rhbz 740645 ApplyPatch md-dont-delay-reboot-by-1-second-if-no-MD-devices.patch +# rhbz #714381 +ApplyPatch hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patch + # END OF PATCH APPLICATIONS %endif @@ -1883,6 +1889,9 @@ fi # and build. %changelog +* Mon Sep 26 2011 Chuck Ebbert +- Fix breakage of Apple MagicMouse/Trackpad (rhbz #714381) + * Fri Sep 23 2011 Josh Boyer - Add patch to fix 1 second delay from MD driver during shutdown (rhbz 740645) - CVE-2011-1161 CVE-2011-1162: tpm: infoleaks From e1bdb5078cf5195cd1b158d9c488ba485f0bf71a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 28 Sep 2011 16:09:56 -0400 Subject: [PATCH 168/397] Backport backlight support for Samsung n150/NC10 class machines (rhbz 496975) --- ...sung-laptop-DMI-identification-for-N.patch | 44 +++++++++++++++++++ kernel.spec | 9 ++++ 2 files changed, 53 insertions(+) create mode 100644 Platform-fix-samsung-laptop-DMI-identification-for-N.patch diff --git a/Platform-fix-samsung-laptop-DMI-identification-for-N.patch b/Platform-fix-samsung-laptop-DMI-identification-for-N.patch new file mode 100644 index 000000000..c36935d6b --- /dev/null +++ b/Platform-fix-samsung-laptop-DMI-identification-for-N.patch @@ -0,0 +1,44 @@ +From 350268c1de71490d5e803a81e609191034a55560 Mon Sep 17 00:00:00 2001 +From: Thomas Courbon +Date: Wed, 20 Jul 2011 22:57:44 +0200 +Subject: [PATCH] Platform: fix samsung-laptop DMI identification for + N150/N210/220/N230 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some samsung latop of the N150/N2{10,20,30} serie are badly detected by the samsung-laptop platform driver, see bug # 36082. +It appears that N230 identifies itself as N150/N210/N220/N230 whereas the other identify themselves as N150/N210/220. +This patch attemtp fix #36082 allowing correct identification for all the said netbook model. + +Reported-by: Daniel Eklöf +Signed-off-by: Thomas Courbon +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/samsung-laptop.c | 10 ++++++++++ + 1 files changed, 10 insertions(+), 0 deletions(-) + +diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c +index d347116..1658575 100644 +--- a/drivers/platform/x86/samsung-laptop.c ++++ b/drivers/platform/x86/samsung-laptop.c +@@ -601,6 +601,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { + .callback = dmi_check_cb, + }, + { ++ .ident = "N150/N210/N220", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, ++ "SAMSUNG ELECTRONICS CO., LTD."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"), ++ DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"), ++ }, ++ .callback = dmi_check_cb, ++ }, ++ { + .ident = "N150/N210/N220/N230", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, +-- +1.7.6 + diff --git a/kernel.spec b/kernel.spec index 2c53c9b7c..35dd29681 100644 --- a/kernel.spec +++ b/kernel.spec @@ -700,6 +700,9 @@ Patch21011: md-dont-delay-reboot-by-1-second-if-no-MD-devices.patch # rhbz #714381 Patch21012: hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patch +# rhbz #496975 +Patch21013: Platform-fix-samsung-laptop-DMI-identification-for-N.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1269,6 +1272,9 @@ ApplyPatch md-dont-delay-reboot-by-1-second-if-no-MD-devices.patch # rhbz #714381 ApplyPatch hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patch +# rhbz #496675 +ApplyPatch Platform-fix-samsung-laptop-DMI-identification-for-N.patch + # END OF PATCH APPLICATIONS %endif @@ -1889,6 +1895,9 @@ fi # and build. %changelog +* Tue Sep 27 2011 Josh Boyer +- Backport support for Samsung n150 class machines (rhbz 496975) + * Mon Sep 26 2011 Chuck Ebbert - Fix breakage of Apple MagicMouse/Trackpad (rhbz #714381) From 74f5c02455677fd4be38440c472e546b87ec399f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 28 Sep 2011 19:07:14 -0400 Subject: [PATCH 169/397] Add patch from upstream to ix the USB drive removal oopses we've been seeing --- ...queue-resources-at-blk_release_queue.patch | 71 +++++++++++++++++++ kernel.spec | 8 +++ 2 files changed, 79 insertions(+) create mode 100644 block-Free-queue-resources-at-blk_release_queue.patch diff --git a/block-Free-queue-resources-at-blk_release_queue.patch b/block-Free-queue-resources-at-blk_release_queue.patch new file mode 100644 index 000000000..9c3049778 --- /dev/null +++ b/block-Free-queue-resources-at-blk_release_queue.patch @@ -0,0 +1,71 @@ +From 3a527bb7e00bb9650f28d273f56c872db03452c5 Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Wed, 28 Sep 2011 08:07:01 -0600 +Subject: [PATCH] block: Free queue resources at blk_release_queue() + +A kernel crash is observed when a mounted ext3/ext4 filesystem is +physically removed. The problem is that blk_cleanup_queue() frees up +some resources eg by calling elevator_exit(), which are not checked for +in normal operation. So we should rather move these calls to the +destructor function blk_release_queue() as at that point all remaining +references are gone. However, in doing so we have to ensure that any +externally supplied queue_lock is disconnected as the driver might free +up the lock after the call of blk_cleanup_queue(), + +Signed-off-by: Hannes Reinecke +Signed-off-by: Jens Axboe +--- + block/blk-core.c | 13 ++++++------- + block/blk-sysfs.c | 5 +++++ + 2 files changed, 11 insertions(+), 7 deletions(-) + +diff --git a/block/blk-core.c b/block/blk-core.c +index 1d49e1c..847d04e 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -348,9 +348,10 @@ void blk_put_queue(struct request_queue *q) + EXPORT_SYMBOL(blk_put_queue); + + /* +- * Note: If a driver supplied the queue lock, it should not zap that lock +- * unexpectedly as some queue cleanup components like elevator_exit() and +- * blk_throtl_exit() need queue lock. ++ * Note: If a driver supplied the queue lock, it is disconnected ++ * by this function. The actual state of the lock doesn't matter ++ * here as the request_queue isn't accessible after this point ++ * (QUEUE_FLAG_DEAD is set) and no other requests will be queued. + */ + void blk_cleanup_queue(struct request_queue *q) + { +@@ -367,10 +368,8 @@ void blk_cleanup_queue(struct request_queue *q) + queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q); + mutex_unlock(&q->sysfs_lock); + +- if (q->elevator) +- elevator_exit(q->elevator); +- +- blk_throtl_exit(q); ++ if (q->queue_lock != &q->__queue_lock) ++ q->queue_lock = &q->__queue_lock; + + blk_put_queue(q); + } +diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c +index d935bd8..45c56d8 100644 +--- a/block/blk-sysfs.c ++++ b/block/blk-sysfs.c +@@ -472,6 +472,11 @@ static void blk_release_queue(struct kobject *kobj) + + blk_sync_queue(q); + ++ if (q->elevator) ++ elevator_exit(q->elevator); ++ ++ blk_throtl_exit(q); ++ + if (rl->rq_pool) + mempool_destroy(rl->rq_pool); + +-- +1.7.6 + diff --git a/kernel.spec b/kernel.spec index 35dd29681..7b92f4f8d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -703,6 +703,8 @@ Patch21012: hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patc # rhbz #496975 Patch21013: Platform-fix-samsung-laptop-DMI-identification-for-N.patch +Patch21014: block-Free-queue-resources-at-blk_release_queue.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1275,6 +1277,8 @@ ApplyPatch hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patch # rhbz #496675 ApplyPatch Platform-fix-samsung-laptop-DMI-identification-for-N.patch +ApplyPatch block-Free-queue-resources-at-blk_release_queue.patch + # END OF PATCH APPLICATIONS %endif @@ -1895,6 +1899,10 @@ fi # and build. %changelog +* Wed Sep 28 2011 Josh Boyer +- Backport upstream block patch to try and fix a number of oopses we're seeing + with USB drive removals + * Tue Sep 27 2011 Josh Boyer - Backport support for Samsung n150 class machines (rhbz 496975) From cd7408621ed346269d69fa371cf81a9ad4379e1f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 29 Sep 2011 10:52:45 -0400 Subject: [PATCH 170/397] Update logitech quirk patch --- kernel.spec | 3 +- usb-add-quirk-for-logitech-webcams.patch | 69 +++++++++++++++++++----- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/kernel.spec b/kernel.spec index 7b92f4f8d..8d4aca75f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1899,9 +1899,10 @@ fi # and build. %changelog -* Wed Sep 28 2011 Josh Boyer +* Wed Sep 28 2011 Josh Boyer 2.6.40.4-6 - Backport upstream block patch to try and fix a number of oopses we're seeing with USB drive removals +- Update usb-add-quirk-for-logitech-webcams.patch (rhbz 742010) * Tue Sep 27 2011 Josh Boyer - Backport support for Samsung n150 class machines (rhbz 496975) diff --git a/usb-add-quirk-for-logitech-webcams.patch b/usb-add-quirk-for-logitech-webcams.patch index fa32f34f9..9a932ca57 100644 --- a/usb-add-quirk-for-logitech-webcams.patch +++ b/usb-add-quirk-for-logitech-webcams.patch @@ -1,30 +1,71 @@ -commit a218e3649310bd2ee0e8b7ec6353ab029d020289 -Author: Oliver Neukum -Date: Tue Aug 9 08:12:37 2011 -0400 +From 48ff94510ecf6b36c793c40ae3d15ce39a331e17 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Tue, 13 Sep 2011 08:42:21 +0200 +Subject: [PATCH] USB:add RESET_RESUME for webcams shown to be quirky - USB: quirk for Logitech C250, C270, and C310 webcams - - This need for this was shown by the new PM code - - Signed-off-by: Oliver Neukum +From 6f673c5ef819548b2cbaf7bb607779af6fdbe731 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Tue, 30 Aug 2011 15:34:32 +0200 +Subject: [PATCH] USB:add RESET_RESUME for webcams shown to be quirky + +The new runtime PM code has shown that many webcams suffer +from a race condition that may crash them upon resume. +Runtime PM is especially prone to show the problem because +it retains power to the cameras at all times. However +system suspension may also crash the devices and retain +power to the devices. +The only way to solve this problem without races is in +usbcore with the RESET_RESUME quirk. + +Signed-off-by: Oliver Neukum + +Add C300 ID from patch in rhbz #742010 +--- + drivers/usb/core/quirks.c | 24 ++++++++++++++++++++++++ + 1 files changed, 24 insertions(+), 0 deletions(-) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c -index 81ce6a8..5114281 100644 +index 81ce6a8..d6a8d82 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c -@@ -41,6 +41,15 @@ static const struct usb_device_id usb_quirk_list[] = { - /* Logitech Harmony 700-series */ - { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, +@@ -38,6 +38,27 @@ static const struct usb_device_id usb_quirk_list[] = { + /* Creative SB Audigy 2 NX */ + { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, ++ /* Logitech Webcam C200 */ ++ { USB_DEVICE(0x046d, 0x0802), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + /* Logitech Webcam C250 */ + { USB_DEVICE(0x046d, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, + ++ /* Logitech Webcam C300 */ ++ { USB_DEVICE(0x046d, 0x0805), .driver_info = USB_QUIRK_RESET_RESUME }, ++ ++ /* Logitech Webcam B/C500 */ ++ { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME }, ++ ++ /* Logitech Webcam Pro 9000 */ ++ { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + /* Logitech Webcam C310 */ + { USB_DEVICE(0x046d, 0x081b), .driver_info = USB_QUIRK_RESET_RESUME }, + + /* Logitech Webcam C270 */ + { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME }, + - /* Philips PSC805 audio device */ - { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Logitech Harmony 700-series */ + { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, +@@ -69,6 +90,9 @@ static const struct usb_device_id usb_quirk_list[] = { + { USB_DEVICE(0x06a3, 0x0006), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, + ++ /* Guillemot Webcam Hercules Dualpix Exchange*/ ++ { USB_DEVICE(0x06f8, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + /* M-Systems Flash Disk Pioneers */ + { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, + +-- +1.7.6 + From ea166942be9f175b7ebd356fc64f67f36e03ff97 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 29 Sep 2011 11:00:15 -0400 Subject: [PATCH 171/397] Backport two upstream patches to fix rhbz 700718 --- kernel.spec | 13 ++- ...from-regs-when-possible-in-dump_trac.patch | 86 +++++++++++++++++++ ...ck-pointer-in-perf-live-regs-savings.patch | 38 ++++++++ 3 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch create mode 100644 x86-Save-stack-pointer-in-perf-live-regs-savings.patch diff --git a/kernel.spec b/kernel.spec index 8d4aca75f..57843e0f9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -705,6 +705,10 @@ Patch21013: Platform-fix-samsung-laptop-DMI-identification-for-N.patch Patch21014: block-Free-queue-resources-at-blk_release_queue.patch +# rhbz #700718 +Patch21015: x86-Save-stack-pointer-in-perf-live-regs-savings.patch +Patch21016: x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1279,6 +1283,10 @@ ApplyPatch Platform-fix-samsung-laptop-DMI-identification-for-N.patch ApplyPatch block-Free-queue-resources-at-blk_release_queue.patch +# rhbz #700718 +ApplyPatch x86-Save-stack-pointer-in-perf-live-regs-savings.patch +ApplyPatch x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch + # END OF PATCH APPLICATIONS %endif @@ -1899,7 +1907,10 @@ fi # and build. %changelog -* Wed Sep 28 2011 Josh Boyer 2.6.40.4-6 +* Thu Sep 29 2011 Josh Boyer +- Backport two upstream patches to fix rhbz 700718 + +* Wed Sep 28 2011 Josh Boyer - Backport upstream block patch to try and fix a number of oopses we're seeing with USB drive removals - Update usb-add-quirk-for-logitech-webcams.patch (rhbz 742010) diff --git a/x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch b/x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch new file mode 100644 index 000000000..bda767af8 --- /dev/null +++ b/x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch @@ -0,0 +1,86 @@ +From 47ce11a2b6519f9c7843223ea8e561eb71ea5896 Mon Sep 17 00:00:00 2001 +From: Frederic Weisbecker +Date: Thu, 30 Jun 2011 19:04:56 +0200 +Subject: [PATCH 2/2] x86: Fetch stack from regs when possible in dump_trace() + +When regs are passed to dump_stack(), we fetch the frame +pointer from the regs but the stack pointer is taken from +the current frame. + +Thus the frame and stack pointers may not come from the same +context. For example this can result in the unwinder to +think the context is in irq, due to the current value of +the stack, but the frame pointer coming from the regs points +to a frame from another place. It then tries to fix up +the irq link but ends up dereferencing a random frame +pointer that doesn't belong to the irq stack: + +[ 9131.706906] ------------[ cut here ]------------ +[ 9131.707003] WARNING: at arch/x86/kernel/dumpstack_64.c:129 dump_trace+0x2aa/0x330() +[ 9131.707003] Hardware name: AMD690VM-FMH +[ 9131.707003] Perf: bad frame pointer = 0000000000000005 in callchain +[ 9131.707003] Modules linked in: +[ 9131.707003] Pid: 1050, comm: perf Not tainted 3.0.0-rc3+ #181 +[ 9131.707003] Call Trace: +[ 9131.707003] [] warn_slowpath_common+0x7a/0xb0 +[ 9131.707003] [] warn_slowpath_fmt+0x41/0x50 +[ 9131.707003] [] ? bad_to_user+0x6d/0x10be +[ 9131.707003] [] dump_trace+0x2aa/0x330 +[ 9131.707003] [] ? native_sched_clock+0x13/0x50 +[ 9131.707003] [] perf_callchain_kernel+0x54/0x70 +[ 9131.707003] [] perf_prepare_sample+0x19f/0x2a0 +[ 9131.707003] [] __perf_event_overflow+0x16c/0x290 +[ 9131.707003] [] ? __perf_event_overflow+0x130/0x290 +[ 9131.707003] [] ? native_sched_clock+0x13/0x50 +[ 9131.707003] [] ? sched_clock+0x9/0x10 +[ 9131.707003] [] ? T.375+0x15/0x90 +[ 9131.707003] [] ? trace_hardirqs_on_caller+0x64/0x180 +[ 9131.707003] [] ? trace_hardirqs_off+0xd/0x10 +[ 9131.707003] [] perf_event_overflow+0x14/0x20 +[ 9131.707003] [] perf_swevent_hrtimer+0x11c/0x130 +[ 9131.707003] [] ? error_exit+0x51/0xb0 +[ 9131.707003] [] __run_hrtimer+0x83/0x1e0 +[ 9131.707003] [] ? perf_event_overflow+0x20/0x20 +[ 9131.707003] [] hrtimer_interrupt+0x106/0x250 +[ 9131.707003] [] ? trace_hardirqs_off_thunk+0x3a/0x3c +[ 9131.707003] [] smp_apic_timer_interrupt+0x53/0x90 +[ 9131.707003] [] apic_timer_interrupt+0x13/0x20 +[ 9131.707003] [] ? error_exit+0x51/0xb0 +[ 9131.707003] [] ? error_exit+0x4c/0xb0 +[ 9131.707003] ---[ end trace b2560d4876709347 ]--- + +Fix this by simply taking the stack pointer from regs->sp +when regs are provided. + +Signed-off-by: Frederic Weisbecker +Cc: Ingo Molnar +Cc: Thomas Gleixner +Cc: H. Peter Anvin +Cc: Peter Zijlstra +Cc: Arnaldo Carvalho de Melo +--- + arch/x86/kernel/dumpstack_64.c | 7 +++++-- + 1 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c +index e71c98d..788295c 100644 +--- a/arch/x86/kernel/dumpstack_64.c ++++ b/arch/x86/kernel/dumpstack_64.c +@@ -155,9 +155,12 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, + task = current; + + if (!stack) { +- stack = &dummy; +- if (task && task != current) ++ if (regs) ++ stack = (unsigned long *)regs->sp; ++ else if (task && task != current) + stack = (unsigned long *)task->thread.sp; ++ else ++ stack = &dummy; + } + + if (!bp) +-- +1.7.6 + diff --git a/x86-Save-stack-pointer-in-perf-live-regs-savings.patch b/x86-Save-stack-pointer-in-perf-live-regs-savings.patch new file mode 100644 index 000000000..3964f10e9 --- /dev/null +++ b/x86-Save-stack-pointer-in-perf-live-regs-savings.patch @@ -0,0 +1,38 @@ +From 9e46294dadedc0c04adcb8ce760bd2cd74f7332d Mon Sep 17 00:00:00 2001 +From: Frederic Weisbecker +Date: Sat, 2 Jul 2011 15:00:52 +0200 +Subject: [PATCH 1/2] x86: Save stack pointer in perf live regs savings + +In order to prepare for fetching the stack pointer from the +regs when possible in dump_trace() instead of taking the +local one, save the current stack pointer in perf live regs saving. + +Signed-off-by: Frederic Weisbecker +Cc: Ingo Molnar +Cc: Thomas Gleixner +Cc: H. Peter Anvin +Cc: Peter Zijlstra +Cc: Arnaldo Carvalho de Melo +--- + arch/x86/include/asm/perf_event.h | 5 +++++ + 1 files changed, 5 insertions(+), 0 deletions(-) + +diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h +index d9d4dae..094fb30 100644 +--- a/arch/x86/include/asm/perf_event.h ++++ b/arch/x86/include/asm/perf_event.h +@@ -152,6 +152,11 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs); + (regs)->bp = caller_frame_pointer(); \ + (regs)->cs = __KERNEL_CS; \ + regs->flags = 0; \ ++ asm volatile( \ ++ _ASM_MOV "%%"_ASM_SP ", %0\n" \ ++ : "=m" ((regs)->sp) \ ++ :: "memory" \ ++ ); \ + } + + #else +-- +1.7.6 + From e0adc28e6310d1393f535777d3930b885d03698e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 3 Oct 2011 14:46:45 -0400 Subject: [PATCH 172/397] Add patch to fix PIE execution with ASLR disabled (rhbz 708563) --- ...x-PIE-execution-with-random-disabled.patch | 87 +++++++++++++++++++ kernel.spec | 9 ++ 2 files changed, 96 insertions(+) create mode 100644 binfmt_elf-fix-PIE-execution-with-random-disabled.patch diff --git a/binfmt_elf-fix-PIE-execution-with-random-disabled.patch b/binfmt_elf-fix-PIE-execution-with-random-disabled.patch new file mode 100644 index 000000000..b376c88a9 --- /dev/null +++ b/binfmt_elf-fix-PIE-execution-with-random-disabled.patch @@ -0,0 +1,87 @@ +On Mon, 3 Oct 2011, Josh Boyer wrote: + +> > > Perhaps another check here for randomize? Something like: +> > > +> > > #if defined(CONFIG_X86) || defined(CONFIG_ARM) +> > > if (current->flags & PF_RANDOMIZE) +> > > load_bias = 0; +> > > else if (vaddr) +> > > load_bias = 0; +> > > else +> > > load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE); +> > > #else +> > > load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); +> > > #endif +> > > +> > > If that's stupid, then feel free to tell me. I won't pretend like I +> > > understand what is going on here yet, but based on the explanation you +> > > provided that might work. +> > +> > I have just verified my hunch that the original patch from H.J. / Josh +> > breaks ASLR completely, so Andrew, please drop it for now. +> +> Yes, please drop the original. + +Thanks. + +> > I am now looking into how to fix things properly. +> > +> > Josh, looking at what you are proposing -- do you see any reason to make +> > the behavior different in #else branch and in !(current->flags & +> > PF_RANDOMIZE) case? +> +> I was mostly just trying to adapt H.J.'s patch to account for the +> PF_RANDOMIZE case. Looking at it a bit more, I'm not sure why they +> would need to be different. H.J., do you recall why you made that +> change originally? + +How about the patch below instead? It survives my testing, and I believe +it handles both cases properly. + +Confirmation from the original bug reporter would obviously be a nice +bonus too :) + + + + +From: Jiri Kosina +Subject: [PATCH] binfmt_elf: fix PIE execution with randomization disabled + +The case of address space randomization being disabled in runtime through +randomize_va_space sysctl is not treated properly in load_elf_binary(), +resulting in SIGKILL coming at exec() time for certain PIE-linked binaries +in case the randomization has been disabled at runtime prior to calling +exec(). + +Handle the randomize_va_space == 0 case the same way as if we were not +supporting .text randomization at all. + +Based on original patch by H.J. Lu and +Josh Boyer + +Cc: Ingo Molnar +Cc: Jiri Kosina +Cc: Nicolas Pitre +Cc: Russell King +Signed-off-by: Jiri Kosina +--- + fs/binfmt_elf.c | 5 ++++- + 1 files changed, 4 insertions(+), 1 deletions(-) + +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index dd0fdfc..bb11fe4 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -795,7 +795,10 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) + * might try to exec. This is because the brk will + * follow the loader, and is not movable. */ + #if defined(CONFIG_X86) || defined(CONFIG_ARM) +- load_bias = 0; ++ if (current->flags & PF_RANDOMIZE) ++ load_bias = 0; ++ else ++ load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); + #else + load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); + #endif + diff --git a/kernel.spec b/kernel.spec index 57843e0f9..2ba7d58bf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -709,6 +709,9 @@ Patch21014: block-Free-queue-resources-at-blk_release_queue.patch Patch21015: x86-Save-stack-pointer-in-perf-live-regs-savings.patch Patch21016: x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch +#rhbz #708563 +Patch21017: binfmt_elf-fix-PIE-execution-with-random-disabled.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1287,6 +1290,9 @@ ApplyPatch block-Free-queue-resources-at-blk_release_queue.patch ApplyPatch x86-Save-stack-pointer-in-perf-live-regs-savings.patch ApplyPatch x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch +#rhbz #708563 +ApplyPatch binfmt_elf-fix-PIE-execution-with-random-disabled.patch + # END OF PATCH APPLICATIONS %endif @@ -1907,6 +1913,9 @@ fi # and build. %changelog +* Mon Oct 04 2011 Josh Boyer 2.6.40.4-6 +- Add patch to fix PIE execution when ASLR is disabled at runtime (rhbz 708563) + * Thu Sep 29 2011 Josh Boyer - Backport two upstream patches to fix rhbz 700718 From 9788e320b34123dd78fdcf1d72e53d9ff0976627 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 3 Oct 2011 20:14:47 -0400 Subject: [PATCH 173/397] Update to the 3.0.6 stable release (2.6.40.6) patch-3.0.6.bz2 was generated from git as previously done with some of the 3.1 rc patches. Hopefully kernel.org will have a generated and signed copy for the next stable release. --- TPM-Call-tpm_transmit-with-correct-size.patch | 43 ------- ...ro-buffer-after-copying-to-userspace.patch | 45 ------- ...queue-resources-at-blk_release_queue.patch | 71 ----------- ...le-memory-corruption-in-CIFSFindNext.patch | 82 ------------- config-arm-omap-generic | 1 + config-arm-tegra | 1 + fix-cdc-ncm-dma-stack-vars.patch | 114 ------------------ iwlagn-revert-max-aggregate-size.patch | 13 -- kernel.spec | 37 +----- ...ndmsg-fix-unsafe-user-pointer-access.patch | 60 --------- sources | 2 +- 11 files changed, 9 insertions(+), 460 deletions(-) delete mode 100644 TPM-Call-tpm_transmit-with-correct-size.patch delete mode 100644 TPM-Zero-buffer-after-copying-to-userspace.patch delete mode 100644 block-Free-queue-resources-at-blk_release_queue.patch delete mode 100644 cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch delete mode 100644 fix-cdc-ncm-dma-stack-vars.patch delete mode 100644 iwlagn-revert-max-aggregate-size.patch delete mode 100644 sendmmsg-sendmsg-fix-unsafe-user-pointer-access.patch diff --git a/TPM-Call-tpm_transmit-with-correct-size.patch b/TPM-Call-tpm_transmit-with-correct-size.patch deleted file mode 100644 index 64f776f13..000000000 --- a/TPM-Call-tpm_transmit-with-correct-size.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 6b07d30aca7e52f2881b8c8c20c8a2cd28e8b3d3 Mon Sep 17 00:00:00 2001 -From: Peter Huewe -Date: Thu, 15 Sep 2011 14:37:43 -0300 -Subject: [PATCH] TPM: Call tpm_transmit with correct size - -This patch changes the call of tpm_transmit by supplying the size of the -userspace buffer instead of TPM_BUFSIZE. - -This got assigned CVE-2011-1161. - -[The first hunk didn't make sense given one could expect - way less data than TPM_BUFSIZE, so added tpm_transmit boundary - check over bufsiz instead - The last parameter of tpm_transmit() reflects the amount - of data expected from the device, and not the buffer size - being supplied to it. It isn't ideal to parse it directly, - so we just set it to the maximum the input buffer can handle - and let the userspace API to do such job.] - -Signed-off-by: Rajiv Andrade -Cc: Stable Kernel -Signed-off-by: James Morris ---- - drivers/char/tpm/tpm.c | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) - -diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c -index caf8012..1fe9793 100644 ---- a/drivers/char/tpm/tpm.c -+++ b/drivers/char/tpm/tpm.c -@@ -383,6 +383,9 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, - u32 count, ordinal; - unsigned long stop; - -+ if (bufsiz > TPM_BUFSIZE) -+ bufsiz = TPM_BUFSIZE; -+ - count = be32_to_cpu(*((__be32 *) (buf + 2))); - ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); - if (count == 0) --- -1.7.6 - diff --git a/TPM-Zero-buffer-after-copying-to-userspace.patch b/TPM-Zero-buffer-after-copying-to-userspace.patch deleted file mode 100644 index 1b3d9ac48..000000000 --- a/TPM-Zero-buffer-after-copying-to-userspace.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 3321c07ae5068568cd61ac9f4ba749006a7185c9 Mon Sep 17 00:00:00 2001 -From: Peter Huewe -Date: Thu, 15 Sep 2011 14:47:42 -0300 -Subject: [PATCH] TPM: Zero buffer after copying to userspace - -Since the buffer might contain security related data it might be a good idea to -zero the buffer after we have copied it to userspace. - -This got assigned CVE-2011-1162. - -Signed-off-by: Rajiv Andrade -Cc: Stable Kernel -Signed-off-by: James Morris ---- - drivers/char/tpm/tpm.c | 6 +++++- - 1 files changed, 5 insertions(+), 1 deletions(-) - -diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c -index 1fe9793..9ca5c02 100644 ---- a/drivers/char/tpm/tpm.c -+++ b/drivers/char/tpm/tpm.c -@@ -1105,6 +1105,7 @@ ssize_t tpm_read(struct file *file, char __user *buf, - { - struct tpm_chip *chip = file->private_data; - ssize_t ret_size; -+ int rc; - - del_singleshot_timer_sync(&chip->user_read_timer); - flush_work_sync(&chip->work); -@@ -1115,8 +1116,11 @@ ssize_t tpm_read(struct file *file, char __user *buf, - ret_size = size; - - mutex_lock(&chip->buffer_mutex); -- if (copy_to_user(buf, chip->data_buffer, ret_size)) -+ rc = copy_to_user(buf, chip->data_buffer, ret_size); -+ memset(chip->data_buffer, 0, ret_size); -+ if (rc) - ret_size = -EFAULT; -+ - mutex_unlock(&chip->buffer_mutex); - } - --- -1.7.6 - diff --git a/block-Free-queue-resources-at-blk_release_queue.patch b/block-Free-queue-resources-at-blk_release_queue.patch deleted file mode 100644 index 9c3049778..000000000 --- a/block-Free-queue-resources-at-blk_release_queue.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 3a527bb7e00bb9650f28d273f56c872db03452c5 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Wed, 28 Sep 2011 08:07:01 -0600 -Subject: [PATCH] block: Free queue resources at blk_release_queue() - -A kernel crash is observed when a mounted ext3/ext4 filesystem is -physically removed. The problem is that blk_cleanup_queue() frees up -some resources eg by calling elevator_exit(), which are not checked for -in normal operation. So we should rather move these calls to the -destructor function blk_release_queue() as at that point all remaining -references are gone. However, in doing so we have to ensure that any -externally supplied queue_lock is disconnected as the driver might free -up the lock after the call of blk_cleanup_queue(), - -Signed-off-by: Hannes Reinecke -Signed-off-by: Jens Axboe ---- - block/blk-core.c | 13 ++++++------- - block/blk-sysfs.c | 5 +++++ - 2 files changed, 11 insertions(+), 7 deletions(-) - -diff --git a/block/blk-core.c b/block/blk-core.c -index 1d49e1c..847d04e 100644 ---- a/block/blk-core.c -+++ b/block/blk-core.c -@@ -348,9 +348,10 @@ void blk_put_queue(struct request_queue *q) - EXPORT_SYMBOL(blk_put_queue); - - /* -- * Note: If a driver supplied the queue lock, it should not zap that lock -- * unexpectedly as some queue cleanup components like elevator_exit() and -- * blk_throtl_exit() need queue lock. -+ * Note: If a driver supplied the queue lock, it is disconnected -+ * by this function. The actual state of the lock doesn't matter -+ * here as the request_queue isn't accessible after this point -+ * (QUEUE_FLAG_DEAD is set) and no other requests will be queued. - */ - void blk_cleanup_queue(struct request_queue *q) - { -@@ -367,10 +368,8 @@ void blk_cleanup_queue(struct request_queue *q) - queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q); - mutex_unlock(&q->sysfs_lock); - -- if (q->elevator) -- elevator_exit(q->elevator); -- -- blk_throtl_exit(q); -+ if (q->queue_lock != &q->__queue_lock) -+ q->queue_lock = &q->__queue_lock; - - blk_put_queue(q); - } -diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c -index d935bd8..45c56d8 100644 ---- a/block/blk-sysfs.c -+++ b/block/blk-sysfs.c -@@ -472,6 +472,11 @@ static void blk_release_queue(struct kobject *kobj) - - blk_sync_queue(q); - -+ if (q->elevator) -+ elevator_exit(q->elevator); -+ -+ blk_throtl_exit(q); -+ - if (rl->rq_pool) - mempool_destroy(rl->rq_pool); - --- -1.7.6 - diff --git a/cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch b/cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch deleted file mode 100644 index 06fc5c74a..000000000 --- a/cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch +++ /dev/null @@ -1,82 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Jeff Layton -Newsgroups: gmane.linux.kernel.cifs -Subject: [PATCH] cifs: fix possible memory corruption in CIFSFindNext -Date: Tue, 23 Aug 2011 07:21:28 -0400 -Lines: 37 -Approved: news@gmane.org -Message-ID: <1314098488-1547-1-git-send-email-jlayton@redhat.com> -NNTP-Posting-Host: lo.gmane.org -X-Trace: dough.gmane.org 1314098501 27164 80.91.229.12 (23 Aug 2011 11:21:41 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Tue, 23 Aug 2011 11:21:41 +0000 (UTC) -Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, dcl-HN4QTLPn1qTvY7RNz7mR4EEOCMrvLtNR@public.gmane.org -To: smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org -Original-X-From: linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Tue Aug 23 13:21:37 2011 -Return-path: -Envelope-to: glkc-linux-cifs-1dZseelyfdZg9hUCZPvPmw@public.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1Qvp33-0003JC-05 - for glkc-linux-cifs-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Tue, 23 Aug 2011 13:21:37 +0200 -Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand - id S1752435Ab1HWLVg (ORCPT ); - Tue, 23 Aug 2011 07:21:36 -0400 -Original-Received: from mail-gy0-f174.google.com ([209.85.160.174]:43114 "EHLO - mail-gy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1751065Ab1HWLVf (ORCPT - ); Tue, 23 Aug 2011 07:21:35 -0400 -Original-Received: by gya6 with SMTP id 6so4228912gya.19 - for ; Tue, 23 Aug 2011 04:21:35 -0700 (PDT) -Original-Received: by 10.101.144.18 with SMTP id w18mr3505731ann.133.1314098494691; - Tue, 23 Aug 2011 04:21:34 -0700 (PDT) -Original-Received: from salusa.poochiereds.net (cpe-075-177-182-191.nc.res.rr.com [75.177.182.191]) - by mx.google.com with ESMTPS id d33sm48355ano.35.2011.08.23.04.21.32 - (version=SSLv3 cipher=OTHER); - Tue, 23 Aug 2011 04:21:33 -0700 (PDT) -X-Mailer: git-send-email 1.7.6 -Original-Sender: linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Xref: news.gmane.org gmane.linux.kernel.cifs:4006 -Archived-At: - -The name_len variable in CIFSFindNext is a signed int that gets set to -the resume_name_len in the cifs_search_info. The resume_name_len however -is unsigned and for some infolevels is populated directly from a 32 bit -value sent by the server. - -If the server sends a very large value for this, then that value could -look negative when converted to a signed int. That would make that -value pass the PATH_MAX check later in CIFSFindNext. The name_len would -then be used as a length value for a memcpy. It would then be treated -as unsigned again, and the memcpy scribbles over a ton of memory. - -Fix this by making the name_len an unsigned value in CIFSFindNext. - -Cc: -Reported-by: Darren Lavender -Signed-off-by: Jeff Layton ---- - fs/cifs/cifssmb.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c -index f4d0988..950464d 100644 ---- a/fs/cifs/cifssmb.c -+++ b/fs/cifs/cifssmb.c -@@ -4089,7 +4089,8 @@ int CIFSFindNext(const int xid, struct cifs_tcon *tcon, - T2_FNEXT_RSP_PARMS *parms; - char *response_data; - int rc = 0; -- int bytes_returned, name_len; -+ int bytes_returned; -+ unsigned int name_len; - __u16 params, byte_count; - - cFYI(1, "In FindNext"); --- -1.7.6 - diff --git a/config-arm-omap-generic b/config-arm-omap-generic index 8c9fc9c3b..560dfe649 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -127,6 +127,7 @@ CONFIG_ARM_ERRATA_720789=y # CONFIG_ARM_ERRATA_753970 is not set # CONFIG_ARM_ERRATA_754322 is not set # CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_764369 is not set CONFIG_ARM_GIC=y # CONFIG_PCI_SYSCALL is not set # CONFIG_PCCARD is not set diff --git a/config-arm-tegra b/config-arm-tegra index 67f1e3839..c8f1eec24 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -40,6 +40,7 @@ CONFIG_ARM_ERRATA_720789=y # CONFIG_ARM_ERRATA_753970 is not set # CONFIG_ARM_ERRATA_754322 is not set # CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_764369 is not set CONFIG_SMP_ON_UP=y CONFIG_LOCAL_TIMERS=y # CONFIG_THUMB2_KERNEL is not set diff --git a/fix-cdc-ncm-dma-stack-vars.patch b/fix-cdc-ncm-dma-stack-vars.patch deleted file mode 100644 index 7f46a00fe..000000000 --- a/fix-cdc-ncm-dma-stack-vars.patch +++ /dev/null @@ -1,114 +0,0 @@ -commit d072ef23b8ee6bcabc00beff0b5702e704a473cb -Author: Josh Boyer -Date: Tue Aug 2 08:09:56 2011 -0400 - - usbnet/cdc_ncm: Don't use stack variables for DMA buffers - - The cdc_ncm driver still has a few places where stack variables are passed - to the cdc_ncm_do_request function. This triggers a stack trace in - lib/dma-debug.c if the CONFIG_DEBUG_DMA_API option is set. - - Adjust these calls to pass parameters that have been allocated with kzalloc. - - Signed-off-by: Josh Boyer - -diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c -index fd622a6..96dd386 100644 ---- a/drivers/net/usb/cdc_ncm.c -+++ b/drivers/net/usb/cdc_ncm.c -@@ -260,23 +260,38 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) - req.wIndex = cpu_to_le16(iface_no); - - if (flags & USB_CDC_NCM_NCAP_NTB_INPUT_SIZE) { -- struct usb_cdc_ncm_ndp_input_size ndp_in_sz; -+ struct usb_cdc_ncm_ndp_input_size *ndp_in_sz; -+ -+ ndp_in_sz = kzalloc(sizeof(*ndp_in_sz), GFP_KERNEL); -+ if (!ndp_in_sz) { -+ err = -ENOMEM; -+ goto size_err; -+ } - - req.wLength = 8; -- ndp_in_sz.dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); -- ndp_in_sz.wNtbInMaxDatagrams = -+ ndp_in_sz->dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); -+ ndp_in_sz->wNtbInMaxDatagrams = - cpu_to_le16(CDC_NCM_DPT_DATAGRAMS_MAX); -- ndp_in_sz.wReserved = 0; -- err = cdc_ncm_do_request(ctx, &req, &ndp_in_sz, 0, NULL, -+ ndp_in_sz->wReserved = 0; -+ err = cdc_ncm_do_request(ctx, &req, ndp_in_sz, 0, NULL, - 1000); -+ kfree(ndp_in_sz); - } else { -- __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); -+ __le32 *dwNtbInMaxSize; -+ dwNtbInMaxSize = kzalloc(sizeof(*dwNtbInMaxSize), GFP_KERNEL); -+ if (!dwNtbInMaxSize) { -+ err = -ENOMEM; -+ goto size_err; -+ } -+ *dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); - - req.wLength = 4; -- err = cdc_ncm_do_request(ctx, &req, &dwNtbInMaxSize, 0, -+ err = cdc_ncm_do_request(ctx, &req, dwNtbInMaxSize, 0, - NULL, 1000); -+ kfree(dwNtbInMaxSize); - } - -+size_err: - if (err) - pr_debug("Setting NTB Input Size failed\n"); - } -@@ -362,9 +377,15 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) - - /* set Max Datagram Size (MTU) */ - if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) { -- __le16 max_datagram_size; -+ __le16 *max_datagram_size; - u16 eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize); - -+ max_datagram_size = kzalloc(sizeof(*max_datagram_size), GFP_KERNEL); -+ if (!max_datagram_size) { -+ err = -ENOMEM; -+ goto max_dgram_err; -+ } -+ - req.bmRequestType = USB_TYPE_CLASS | USB_DIR_IN | - USB_RECIP_INTERFACE; - req.bNotificationType = USB_CDC_GET_MAX_DATAGRAM_SIZE; -@@ -372,13 +393,15 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) - req.wIndex = cpu_to_le16(iface_no); - req.wLength = cpu_to_le16(2); - -- err = cdc_ncm_do_request(ctx, &req, &max_datagram_size, 0, NULL, -+ err = cdc_ncm_do_request(ctx, &req, max_datagram_size, 0, NULL, - 1000); -+ - if (err) { - pr_debug("GET_MAX_DATAGRAM_SIZE failed, use size=%u\n", - CDC_NCM_MIN_DATAGRAM_SIZE); -+ kfree(max_datagram_size); - } else { -- ctx->max_datagram_size = le16_to_cpu(max_datagram_size); -+ ctx->max_datagram_size = le16_to_cpu(*max_datagram_size); - /* Check Eth descriptor value */ - if (eth_max_sz < CDC_NCM_MAX_DATAGRAM_SIZE) { - if (ctx->max_datagram_size > eth_max_sz) -@@ -401,10 +424,12 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) - req.wValue = 0; - req.wIndex = cpu_to_le16(iface_no); - req.wLength = 2; -- max_datagram_size = cpu_to_le16(ctx->max_datagram_size); -+ *max_datagram_size = cpu_to_le16(ctx->max_datagram_size); - -- err = cdc_ncm_do_request(ctx, &req, &max_datagram_size, -+ err = cdc_ncm_do_request(ctx, &req, max_datagram_size, - 0, NULL, 1000); -+ kfree(max_datagram_size); -+max_dgram_err: - if (err) - pr_debug("SET_MAX_DATAGRAM_SIZE failed\n"); - } diff --git a/iwlagn-revert-max-aggregate-size.patch b/iwlagn-revert-max-aggregate-size.patch deleted file mode 100644 index d9e9a8db4..000000000 --- a/iwlagn-revert-max-aggregate-size.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c -index b0ae4de..afa00ec 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c -@@ -2140,8 +2140,6 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, - IEEE80211_HW_SPECTRUM_MGMT | - IEEE80211_HW_REPORTS_TX_ACK_STATUS; - -- hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF; -- - hw->flags |= IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_SUPPORTS_DYNAMIC_PS; - diff --git a/kernel.spec b/kernel.spec index 2ba7d58bf..7848784f0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 6 +%global baserelease 0 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # Do we have a -stable update to apply? -%define stable_update 4 +%define stable_update 6 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -644,7 +644,6 @@ Patch12010: add-appleir-usb-driver.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch12022: fix-cdc-ncm-dma-stack-vars.patch Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch Patch12024: usb-add-quirk-for-logitech-webcams.patch Patch12025: crypto-register-cryptd-first.patch @@ -659,7 +658,6 @@ Patch13001: epoll-fix-spurious-lockdep-warnings.patch Patch13002: hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch Patch13010: iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch -Patch13011: iwlagn-revert-max-aggregate-size.patch Patch20000: utrace.patch @@ -681,19 +679,9 @@ Patch21004: vfs-fix-automount-for-negative-autofs-dentries.patch # rhbz#727927 rhbz#731278 rhbz#732934 Patch21005: cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch -# from 3.0.5 patch queue -Patch21006: sendmmsg-sendmsg-fix-unsafe-user-pointer-access.patch - # rhbz #735437 Patch21007: ucvideo-fix-crash-when-linking-entities.patch -# CVE-2011-3192 -Patch21008: cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch - -# CVE-2011-1161 CVE-2011-1162 -Patch21009: TPM-Call-tpm_transmit-with-correct-size.patch -Patch21010: TPM-Zero-buffer-after-copying-to-userspace.patch - # rhbz #740645 Patch21011: md-dont-delay-reboot-by-1-second-if-no-MD-devices.patch @@ -703,8 +691,6 @@ Patch21012: hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patc # rhbz #496975 Patch21013: Platform-fix-samsung-laptop-DMI-identification-for-N.patch -Patch21014: block-Free-queue-resources-at-blk_release_queue.patch - # rhbz #700718 Patch21015: x86-Save-stack-pointer-in-perf-live-regs-savings.patch Patch21016: x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch @@ -1238,7 +1224,6 @@ ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch add-appleir-usb-driver.patch -ApplyPatch fix-cdc-ncm-dma-stack-vars.patch ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch ApplyPatch crypto-register-cryptd-first.patch @@ -1251,7 +1236,6 @@ ApplyPatch epoll-fix-spurious-lockdep-warnings.patch ApplyPatch hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch ApplyPatch iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch -ApplyPatch iwlagn-revert-max-aggregate-size.patch ApplyPatch utrace.patch @@ -1262,19 +1246,9 @@ ApplyPatch vfs-fix-automount-for-negative-autofs-dentries.patch # cifs-possible-memory-corruption-on-mount.patch is already queued for 3.0.4 ApplyPatch cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch -# from 3.0.5 patch queue -ApplyPatch sendmmsg-sendmsg-fix-unsafe-user-pointer-access.patch - #rhbz 735437 ApplyPatch ucvideo-fix-crash-when-linking-entities.patch -# CVE-2011-3191 -ApplyPatch cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch - -# CVE-2011-1161 CVE-2011-1162 -ApplyPatch TPM-Call-tpm_transmit-with-correct-size.patch -ApplyPatch TPM-Zero-buffer-after-copying-to-userspace.patch - #rhbz 740645 ApplyPatch md-dont-delay-reboot-by-1-second-if-no-MD-devices.patch @@ -1284,8 +1258,6 @@ ApplyPatch hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patch # rhbz #496675 ApplyPatch Platform-fix-samsung-laptop-DMI-identification-for-N.patch -ApplyPatch block-Free-queue-resources-at-blk_release_queue.patch - # rhbz #700718 ApplyPatch x86-Save-stack-pointer-in-perf-live-regs-savings.patch ApplyPatch x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch @@ -1913,7 +1885,10 @@ fi # and build. %changelog -* Mon Oct 04 2011 Josh Boyer 2.6.40.4-6 +* Mon Oct 03 2011 Josh Boyer 2.6.40.6-0 +- Linux 3.0.6 stable release + +* Mon Oct 03 2011 Josh Boyer 2.6.40.4-6 - Add patch to fix PIE execution when ASLR is disabled at runtime (rhbz 708563) * Thu Sep 29 2011 Josh Boyer diff --git a/sendmmsg-sendmsg-fix-unsafe-user-pointer-access.patch b/sendmmsg-sendmsg-fix-unsafe-user-pointer-access.patch deleted file mode 100644 index 0f85bd910..000000000 --- a/sendmmsg-sendmsg-fix-unsafe-user-pointer-access.patch +++ /dev/null @@ -1,60 +0,0 @@ -From bc909d9ddbf7778371e36a651d6e4194b1cc7d4c Mon Sep 17 00:00:00 2001 -From: Mathieu Desnoyers -Date: Wed, 24 Aug 2011 19:45:03 -0700 -Subject: sendmmsg/sendmsg: fix unsafe user pointer access - -From: Mathieu Desnoyers - -commit bc909d9ddbf7778371e36a651d6e4194b1cc7d4c upstream. - -Dereferencing a user pointer directly from kernel-space without going -through the copy_from_user family of functions is a bad idea. Two of -such usages can be found in the sendmsg code path called from sendmmsg, -added by - -commit c71d8ebe7a4496fb7231151cb70a6baa0cb56f9a upstream. -commit 5b47b8038f183b44d2d8ff1c7d11a5c1be706b34 in the 3.0-stable tree. - -Usages are performed through memcmp() and memcpy() directly. Fix those -by using the already copied msg_sys structure instead of the __user *msg -structure. Note that msg_sys can be set to NULL by verify_compat_iovec() -or verify_iovec(), which requires additional NULL pointer checks. - -Signed-off-by: Mathieu Desnoyers -Signed-off-by: David Goulet -CC: Tetsuo Handa -CC: Anton Blanchard -CC: David S. Miller -Signed-off-by: David S. Miller -Signed-off-by: Greg Kroah-Hartman - ---- - net/socket.c | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - ---- a/net/socket.c -+++ b/net/socket.c -@@ -1965,8 +1965,9 @@ static int __sys_sendmsg(struct socket * - * used_address->name_len is initialized to UINT_MAX so that the first - * destination address never matches. - */ -- if (used_address && used_address->name_len == msg_sys->msg_namelen && -- !memcmp(&used_address->name, msg->msg_name, -+ if (used_address && msg_sys->msg_name && -+ used_address->name_len == msg_sys->msg_namelen && -+ !memcmp(&used_address->name, msg_sys->msg_name, - used_address->name_len)) { - err = sock_sendmsg_nosec(sock, msg_sys, total_len); - goto out_freectl; -@@ -1978,8 +1979,9 @@ static int __sys_sendmsg(struct socket * - */ - if (used_address && err >= 0) { - used_address->name_len = msg_sys->msg_namelen; -- memcpy(&used_address->name, msg->msg_name, -- used_address->name_len); -+ if (msg_sys->msg_name) -+ memcpy(&used_address->name, msg_sys->msg_name, -+ used_address->name_len); - } - - out_freectl: diff --git a/sources b/sources index 1ae01ff4f..296c54af1 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 -62ca5f3caed233617127b2b3b7a87d15 patch-3.0.4.bz2 +4751b440e1c840229468e16617d5b539 patch-3.0.6.bz2 From 71ac22df477b9266777c561e5fa0956d4fb44601 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 6 Oct 2011 14:31:40 -0400 Subject: [PATCH 174/397] Add patch to fix Ricoh e823 SD card readers (rhbz 722509) --- kernel.spec | 11 ++- ...-for-lower-base-frequency-quirk-for-.patch | 73 +++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 mmc-Always-check-for-lower-base-frequency-quirk-for-.patch diff --git a/kernel.spec b/kernel.spec index 7848784f0..bbd1b3554 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 0 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -698,6 +698,9 @@ Patch21016: x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch #rhbz #708563 Patch21017: binfmt_elf-fix-PIE-execution-with-random-disabled.patch +#rhbz #722509 +Patch21018: mmc-Always-check-for-lower-base-frequency-quirk-for-.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1265,6 +1268,9 @@ ApplyPatch x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch #rhbz #708563 ApplyPatch binfmt_elf-fix-PIE-execution-with-random-disabled.patch +#rhbz #722509 +ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch + # END OF PATCH APPLICATIONS %endif @@ -1885,6 +1891,9 @@ fi # and build. %changelog +* Thu Oct 06 2011 Josh Boyer +- Add patch to fix base frequency check for Ricoh e823 devices (rhbz 722509) + * Mon Oct 03 2011 Josh Boyer 2.6.40.6-0 - Linux 3.0.6 stable release diff --git a/mmc-Always-check-for-lower-base-frequency-quirk-for-.patch b/mmc-Always-check-for-lower-base-frequency-quirk-for-.patch new file mode 100644 index 000000000..2d7caad83 --- /dev/null +++ b/mmc-Always-check-for-lower-base-frequency-quirk-for-.patch @@ -0,0 +1,73 @@ +From 65ff02dff67bf26a9c27d9aa11a30eaf3d28469e Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Wed, 5 Oct 2011 11:29:57 -0400 +Subject: [PATCH] mmc: Always check for lower base frequency quirk for Ricoh + 1180:e823 + +Commit 15bed0f2f added a quirk for the e823 Ricoh card reader to lower the +base frequency. However, the quirk first checks to see if the proprietary +MMC controller is disabled, and returns if so. On some devices, such as the +Lenovo X220, the MMC controller is already disabled by firmware it seems, +but the frequency change is still needed so sdhci-pci can talk to the cards. +Since the MMC controller is disabled, the frequency fixup was never being run +on these machines. + +This moves the e823 check above the MMC controller check so that it always +gets run. + +This fixes https://bugzilla.redhat.com/show_bug.cgi?id=722509 + +Signed-off-by: Josh Boyer +--- + drivers/pci/quirks.c | 28 ++++++++++++++-------------- + 1 files changed, 14 insertions(+), 14 deletions(-) + +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index 1196f61..cec4629 100644 +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -2745,20 +2745,6 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) + /* disable must be done via function #0 */ + if (PCI_FUNC(dev->devfn)) + return; +- +- pci_read_config_byte(dev, 0xCB, &disable); +- +- if (disable & 0x02) +- return; +- +- pci_read_config_byte(dev, 0xCA, &write_enable); +- pci_write_config_byte(dev, 0xCA, 0x57); +- pci_write_config_byte(dev, 0xCB, disable | 0x02); +- pci_write_config_byte(dev, 0xCA, write_enable); +- +- dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n"); +- dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n"); +- + /* + * RICOH 0xe823 SD/MMC card reader fails to recognize + * certain types of SD/MMC cards. Lowering the SD base +@@ -2781,6 +2767,20 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) + + dev_notice(&dev->dev, "MMC controller base frequency changed to 50Mhz.\n"); + } ++ ++ pci_read_config_byte(dev, 0xCB, &disable); ++ ++ if (disable & 0x02) ++ return; ++ ++ pci_read_config_byte(dev, 0xCA, &write_enable); ++ pci_write_config_byte(dev, 0xCA, 0x57); ++ pci_write_config_byte(dev, 0xCB, disable | 0x02); ++ pci_write_config_byte(dev, 0xCA, write_enable); ++ ++ dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n"); ++ dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n"); ++ + } + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); + DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); +-- +1.7.6.4 + From 7ba24c33e7095b1f4c4aa04686dbe4c5621d3444 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 11 Oct 2011 11:12:15 -0400 Subject: [PATCH 175/397] add e1000e workaround for packet drop on 82579 at 100Mbps (rhbz 713315) --- kernel.spec | 5 ++ ...-for-packet-drop-on-82579-at-100Mbps.patch | 63 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 net-3-4-e1000e-workaround-for-packet-drop-on-82579-at-100Mbps.patch diff --git a/kernel.spec b/kernel.spec index bbd1b3554..724990cf7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -602,6 +602,7 @@ Patch540: x86-pci-reduce-severity-of-host-bridge-window-conflict-warnings.patch Patch610: hda_intel-prealloc-4mb-dmabuffer.patch Patch700: linux-2.6-e1000-ich9-montevina.patch +Patch701: net-3-4-e1000e-workaround-for-packet-drop-on-82579-at-100Mbps.patch Patch800: linux-2.6-crash-driver.patch @@ -1191,6 +1192,7 @@ ApplyPatch linux-2.6-crash-driver.patch # Hack e1000e to work on Montevina SDV ApplyPatch linux-2.6-e1000-ich9-montevina.patch +ApplyPatch net-3-4-e1000e-workaround-for-packet-drop-on-82579-at-100Mbps.patch # crypto/ @@ -1891,6 +1893,9 @@ fi # and build. %changelog +* Tue Oct 11 2011 Dave Jones +- add e1000e workaround for packet drop on 82579 at 100Mbps (rhbz 713315) + * Thu Oct 06 2011 Josh Boyer - Add patch to fix base frequency check for Ricoh e823 devices (rhbz 722509) diff --git a/net-3-4-e1000e-workaround-for-packet-drop-on-82579-at-100Mbps.patch b/net-3-4-e1000e-workaround-for-packet-drop-on-82579-at-100Mbps.patch new file mode 100644 index 000000000..626362416 --- /dev/null +++ b/net-3-4-e1000e-workaround-for-packet-drop-on-82579-at-100Mbps.patch @@ -0,0 +1,63 @@ +http://patchwork.ozlabs.org/patch/109926/ + +From: Bruce Allan + +The MAC can drop short packets when the PHY detects noise on the line at +100Mbps due to a timing issue. Workaround the issue by increasing the PLL +counter so the PHY properly recognizes the synchronization pattern from the +MAC. + +Signed-off-by: Bruce Allan +Tested-by: Jeff Pieper +Signed-off-by: Jeff Kirsher +--- + drivers/net/e1000e/ich8lan.c | 19 ++++++++++++++----- + 1 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c +index 7525e37..46a5277 100644 +--- a/drivers/net/e1000e/ich8lan.c ++++ b/drivers/net/e1000e/ich8lan.c +@@ -137,8 +137,9 @@ + #define HV_PM_CTRL PHY_REG(770, 17) + + /* PHY Low Power Idle Control */ +-#define I82579_LPI_CTRL PHY_REG(772, 20) +-#define I82579_LPI_CTRL_ENABLE_MASK 0x6000 ++#define I82579_LPI_CTRL PHY_REG(772, 20) ++#define I82579_LPI_CTRL_ENABLE_MASK 0x6000 ++#define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT 0x80 + + /* EMI Registers */ + #define I82579_EMI_ADDR 0x10 +@@ -1670,6 +1671,7 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) + s32 ret_val = 0; + u16 status_reg = 0; + u32 mac_reg; ++ u16 phy_reg; + + if (hw->mac.type != e1000_pch2lan) + goto out; +@@ -1684,12 +1686,19 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) + mac_reg = er32(FEXTNVM4); + mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; + +- if (status_reg & HV_M_STATUS_SPEED_1000) ++ ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg); ++ if (ret_val) ++ goto out; ++ ++ if (status_reg & HV_M_STATUS_SPEED_1000) { + mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC; +- else ++ phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; ++ } else { + mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC; +- ++ phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; ++ } + ew32(FEXTNVM4, mac_reg); ++ ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg); + } + + out: From 38f975149b16c38977058be7c59401701a7b2b8e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 11 Oct 2011 15:04:39 -0400 Subject: [PATCH 176/397] Add patch to fix fuse memory leak (rhbz 745241) --- fuse-fix-memory-leak.patch | 70 ++++++++++++++++++++++++++++++++++++++ kernel.spec | 11 +++++- 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 fuse-fix-memory-leak.patch diff --git a/fuse-fix-memory-leak.patch b/fuse-fix-memory-leak.patch new file mode 100644 index 000000000..c52069bee --- /dev/null +++ b/fuse-fix-memory-leak.patch @@ -0,0 +1,70 @@ +From 4078129ec09990936702ab5274e05d139d7f7dcd Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Mon, 12 Sep 2011 09:38:03 +0200 +Subject: [PATCH] fuse: fix memory leak + +kmemleak is reporting that 32 bytes are being leaked by FUSE: + + unreferenced object 0xe373b270 (size 32): + comm "fusermount", pid 1207, jiffies 4294707026 (age 2675.187s) + hex dump (first 32 bytes): + 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ................ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + backtrace: + [] kmemleak_alloc+0x27/0x50 + [] kmem_cache_alloc+0xc5/0x180 + [] fuse_alloc_forget+0x1e/0x20 + [] fuse_alloc_inode+0xb0/0xd0 + [] alloc_inode+0x1c/0x80 + [] iget5_locked+0x8f/0x1a0 + [] fuse_iget+0x72/0x1a0 + [] fuse_get_root_inode+0x8a/0x90 + [] fuse_fill_super+0x3ef/0x590 + [] mount_nodev+0x3f/0x90 + [] fuse_mount+0x15/0x20 + [] mount_fs+0x1c/0xc0 + [] vfs_kern_mount+0x41/0x90 + [] do_kern_mount+0x39/0xd0 + [] do_mount+0x2e5/0x660 + [] sys_mount+0x66/0xa0 + +This leak report is consistent and happens once per boot on +3.1.0-rc5-dirty. + +This happens if a FORGET request is queued after the fuse device was +released. + +Reported-by: Sitsofe Wheeler +Signed-off-by: Miklos Szeredi +Tested-by: Sitsofe Wheeler +Signed-off-by: Linus Torvalds +--- + fs/fuse/dev.c | 12 ++++++++---- + 1 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c +index 168a80f..5cb8614 100644 +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -258,10 +258,14 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget, + forget->forget_one.nlookup = nlookup; + + spin_lock(&fc->lock); +- fc->forget_list_tail->next = forget; +- fc->forget_list_tail = forget; +- wake_up(&fc->waitq); +- kill_fasync(&fc->fasync, SIGIO, POLL_IN); ++ if (fc->connected) { ++ fc->forget_list_tail->next = forget; ++ fc->forget_list_tail = forget; ++ wake_up(&fc->waitq); ++ kill_fasync(&fc->fasync, SIGIO, POLL_IN); ++ } else { ++ kfree(forget); ++ } + spin_unlock(&fc->lock); + } + +-- +1.7.6.4 + diff --git a/kernel.spec b/kernel.spec index 724990cf7..0c20733e9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -702,6 +702,9 @@ Patch21017: binfmt_elf-fix-PIE-execution-with-random-disabled.patch #rhbz #722509 Patch21018: mmc-Always-check-for-lower-base-frequency-quirk-for-.patch +#rhbz #745241 +Patch21019: fuse-fix-memory-leak.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1273,6 +1276,9 @@ ApplyPatch binfmt_elf-fix-PIE-execution-with-random-disabled.patch #rhbz #722509 ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch +#rhbz #745241 +ApplyPatch fuse-fix-memory-leak.patch + # END OF PATCH APPLICATIONS %endif @@ -1893,6 +1899,9 @@ fi # and build. %changelog +* Tue Oct 11 2011 Josh Boyer +- fix memory leak in fuse (rhbz 745241) + * Tue Oct 11 2011 Dave Jones - add e1000e workaround for packet drop on 82579 at 100Mbps (rhbz 713315) From 4b7f4d32b3c6ff58ef316b7a825dc1ca568f5b94 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Thu, 13 Oct 2011 10:49:31 -0400 Subject: [PATCH 177/397] drm/i915: Treat SDVO LVDS as digital when parsing EDID (#729882) --- drm-i915-sdvo-lvds-is-digital.patch | 83 +++++++++++++++++++++++++++++ kernel.spec | 6 +++ 2 files changed, 89 insertions(+) create mode 100644 drm-i915-sdvo-lvds-is-digital.patch diff --git a/drm-i915-sdvo-lvds-is-digital.patch b/drm-i915-sdvo-lvds-is-digital.patch new file mode 100644 index 000000000..68d0c4b31 --- /dev/null +++ b/drm-i915-sdvo-lvds-is-digital.patch @@ -0,0 +1,83 @@ +From 64015d6d16d7ed5b6ffcec95dc13e8694bd2a4d6 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Mon, 20 Jun 2011 22:35:24 +0100 +Subject: [PATCH] drm/i915/sdvo: Include LVDS panels for the IS_DIGITAL check + +We were checking whether the supplied edid matched the connector it was +read from. We do this in case a DDC read returns an EDID for another +device on a multifunction or otherwise interesting card. However, we +failed to include LVDS as a digital device and so rejecting an otherwise +valid EDID. + +Fixes the detection of the secondary SDVO LVDS panel on the Libretto +W105. + +Signed-off-by: Chris Wilson +--- + drivers/gpu/drm/i915/intel_sdvo.c | 28 ++++++++++++++++++++-------- + 1 files changed, 20 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c +index f96975c..26eff9f 100644 +--- a/drivers/gpu/drm/i915/intel_sdvo.c ++++ b/drivers/gpu/drm/i915/intel_sdvo.c +@@ -49,6 +49,7 @@ + #define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK) + #define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK) + #define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK)) ++#define IS_DIGITAL(c) (c->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK)) + + + static const char *tv_format_names[] = { +@@ -1363,6 +1364,18 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) + return status; + } + ++static bool ++intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo, ++ struct edid *edid) ++{ ++ bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); ++ bool connector_is_digital = !!IS_DIGITAL(sdvo); ++ ++ DRM_DEBUG_KMS("connector_is_digital? %d, monitor_is_digital? %d\n", ++ connector_is_digital, monitor_is_digital); ++ return connector_is_digital == monitor_is_digital; ++} ++ + static enum drm_connector_status + intel_sdvo_detect(struct drm_connector *connector, bool force) + { +@@ -1407,10 +1420,12 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) + if (edid == NULL) + edid = intel_sdvo_get_analog_edid(connector); + if (edid != NULL) { +- if (edid->input & DRM_EDID_INPUT_DIGITAL) +- ret = connector_status_disconnected; +- else ++ if (intel_sdvo_connector_matches_edid(intel_sdvo_connector, ++ edid)) + ret = connector_status_connected; ++ else ++ ret = connector_status_disconnected; ++ + connector->display_info.raw_edid = NULL; + kfree(edid); + } else +@@ -1451,11 +1466,8 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) + edid = intel_sdvo_get_analog_edid(connector); + + if (edid != NULL) { +- struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); +- bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); +- bool connector_is_digital = !!IS_TMDS(intel_sdvo_connector); +- +- if (connector_is_digital == monitor_is_digital) { ++ if (intel_sdvo_connector_matches_edid(to_intel_sdvo_connector(connector), ++ edid)) { + drm_mode_connector_update_edid_property(connector, edid); + drm_add_edid_modes(connector, edid); + } +-- +1.7.5.4 + diff --git a/kernel.spec b/kernel.spec index 0c20733e9..9b87f7ab2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -620,6 +620,8 @@ Patch1811: drm-ttm-nouveau-oops-fix.patch Patch1824: drm-intel-next.patch # make sure the lvds comes back on lid open Patch1825: drm-intel-make-lvds-work.patch +# rhbz#729882, https://bugs.freedesktop.org/attachment.cgi?id=49069 +Patch1827: drm-i915-sdvo-lvds-is-digital.patch Patch1900: linux-2.6-intel-iommu-igfx.patch @@ -1211,6 +1213,7 @@ ApplyOptionalPatch drm-nouveau-updates.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch ApplyPatch drm-intel-make-lvds-work.patch +ApplyPatch drm-i915-sdvo-lvds-is-digital.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch ApplyPatch block-stray-block-put-after-teardown.patch @@ -1899,6 +1902,9 @@ fi # and build. %changelog +* Thu Oct 13 2011 Adam Jackson +- drm/i915: Treat SDVO LVDS as digital when parsing EDID (#729882) + * Tue Oct 11 2011 Josh Boyer - fix memory leak in fuse (rhbz 745241) From ab000f377f6e7f64df9b3093c0d7fdade11570d1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 13 Oct 2011 15:51:57 -0400 Subject: [PATCH 178/397] Add C600 ID to the Logitech USB patch --- kernel.spec | 3 +++ usb-add-quirk-for-logitech-webcams.patch | 18 +++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/kernel.spec b/kernel.spec index 9b87f7ab2..35a2613e1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1902,6 +1902,9 @@ fi # and build. %changelog +* Thu Oct 13 2011 Josh Boyer +- Update usb-add-quirk-for-logitech-webcams.patch with C600 ID (rhbz 742010) + * Thu Oct 13 2011 Adam Jackson - drm/i915: Treat SDVO LVDS as digital when parsing EDID (#729882) diff --git a/usb-add-quirk-for-logitech-webcams.patch b/usb-add-quirk-for-logitech-webcams.patch index 9a932ca57..052a27e73 100644 --- a/usb-add-quirk-for-logitech-webcams.patch +++ b/usb-add-quirk-for-logitech-webcams.patch @@ -1,4 +1,4 @@ -From 48ff94510ecf6b36c793c40ae3d15ce39a331e17 Mon Sep 17 00:00:00 2001 +From d5446509abd85b6845d91a319a033c5bd17e494d Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 13 Sep 2011 08:42:21 +0200 Subject: [PATCH] USB:add RESET_RESUME for webcams shown to be quirky @@ -20,15 +20,16 @@ usbcore with the RESET_RESUME quirk. Signed-off-by: Oliver Neukum Add C300 ID from patch in rhbz #742010 +Add C600 ID from rhbz #742010 --- - drivers/usb/core/quirks.c | 24 ++++++++++++++++++++++++ - 1 files changed, 24 insertions(+), 0 deletions(-) + drivers/usb/core/quirks.c | 27 +++++++++++++++++++++++++++ + 1 files changed, 27 insertions(+), 0 deletions(-) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c -index 81ce6a8..d6a8d82 100644 +index 81ce6a8..caa1991 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c -@@ -38,6 +38,27 @@ static const struct usb_device_id usb_quirk_list[] = { +@@ -38,6 +38,30 @@ static const struct usb_device_id usb_quirk_list[] = { /* Creative SB Audigy 2 NX */ { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, @@ -44,6 +45,9 @@ index 81ce6a8..d6a8d82 100644 + /* Logitech Webcam B/C500 */ + { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME }, + ++ /* Logitech Webcam C600 */ ++ { USB_DEVICE(0x046d, 0x0808), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + /* Logitech Webcam Pro 9000 */ + { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME }, + @@ -56,7 +60,7 @@ index 81ce6a8..d6a8d82 100644 /* Logitech Harmony 700-series */ { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, -@@ -69,6 +90,9 @@ static const struct usb_device_id usb_quirk_list[] = { +@@ -69,6 +93,9 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x06a3, 0x0006), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, @@ -67,5 +71,5 @@ index 81ce6a8..d6a8d82 100644 { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, -- -1.7.6 +1.7.6.4 From bcd1989f6e355541f238eb281e3c8d0b12d2d028 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 17 Oct 2011 13:24:14 -0400 Subject: [PATCH 179/397] Add two patches to fix stalls in khugepaged (rhbz 735946) --- ...direct-reclaim-for-higher-order-allo.patch | 54 +++++++++++++ ...-compaction-if-compaction-can-procee.patch | 81 +++++++++++++++++++ kernel.spec | 13 ++- 3 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch create mode 100644 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch diff --git a/0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch b/0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch new file mode 100644 index 000000000..77777f012 --- /dev/null +++ b/0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch @@ -0,0 +1,54 @@ +From 6b7025ea927d290a59d2772828435c1893f0267f Mon Sep 17 00:00:00 2001 +From: Rik van Riel +Date: Fri, 7 Oct 2011 16:17:22 +0100 +Subject: [PATCH 1/2] mm: vmscan: Limit direct reclaim for higher order + allocations + +When suffering from memory fragmentation due to unfreeable pages, +THP page faults will repeatedly try to compact memory. Due to the +unfreeable pages, compaction fails. + +Needless to say, at that point page reclaim also fails to create +free contiguous 2MB areas. However, that doesn't stop the current +code from trying, over and over again, and freeing a minimum of 4MB +(2UL << sc->order pages) at every single invocation. + +This resulted in my 12GB system having 2-3GB free memory, a +corresponding amount of used swap and very sluggish response times. + +This can be avoided by having the direct reclaim code not reclaim from +zones that already have plenty of free memory available for compaction. + +If compaction still fails due to unmovable memory, doing additional +reclaim will only hurt the system, not help. + +Signed-off-by: Rik van Riel +Signed-off-by: Mel Gorman +--- + mm/vmscan.c | 10 ++++++++++ + 1 files changed, 10 insertions(+), 0 deletions(-) + +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 6072d74..8c03534 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -2022,6 +2022,16 @@ static void shrink_zones(int priority, struct zonelist *zonelist, + continue; + if (zone->all_unreclaimable && priority != DEF_PRIORITY) + continue; /* Let kswapd poll it */ ++ if (COMPACTION_BUILD) { ++ /* ++ * If we already have plenty of memory free ++ * for compaction, don't free any more. ++ */ ++ if (sc->order > PAGE_ALLOC_COSTLY_ORDER && ++ (compaction_suitable(zone, sc->order) || ++ compaction_deferred(zone))) ++ continue; ++ } + /* + * This steals pages from memory cgroups over softlimit + * and returns the number of reclaimed pages and +-- +1.7.6.4 + diff --git a/0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch b/0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch new file mode 100644 index 000000000..e74b64d91 --- /dev/null +++ b/0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch @@ -0,0 +1,81 @@ +From c01043c9aa51a63bd01c60e53494ca4a7e994542 Mon Sep 17 00:00:00 2001 +From: Mel Gorman +Date: Fri, 7 Oct 2011 16:17:23 +0100 +Subject: [PATCH 2/2] mm: Abort reclaim/compaction if compaction can proceed + +If compaction can proceed, shrink_zones() stops doing any work but +the callers still shrink_slab(), raises the priority and potentially +sleeps. This patch aborts direct reclaim/compaction entirely if +compaction can proceed. + +Signed-off-by: Mel Gorman +--- + mm/vmscan.c | 20 ++++++++++++++++---- + 1 files changed, 16 insertions(+), 4 deletions(-) + +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 8c03534..b295a38 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -2000,14 +2000,19 @@ restart: + * + * If a zone is deemed to be full of pinned pages then just give it a light + * scan then give up on it. ++ * ++ * This function returns true if a zone is being reclaimed for a costly ++ * high-order allocation and compaction is either ready to begin or deferred. ++ * This indicates to the caller that it should retry the allocation or fail. + */ +-static void shrink_zones(int priority, struct zonelist *zonelist, ++static bool shrink_zones(int priority, struct zonelist *zonelist, + struct scan_control *sc) + { + struct zoneref *z; + struct zone *zone; + unsigned long nr_soft_reclaimed; + unsigned long nr_soft_scanned; ++ bool should_abort_reclaim = false; + + for_each_zone_zonelist_nodemask(zone, z, zonelist, + gfp_zone(sc->gfp_mask), sc->nodemask) { +@@ -2025,12 +2030,15 @@ static void shrink_zones(int priority, struct zonelist *zonelist, + if (COMPACTION_BUILD) { + /* + * If we already have plenty of memory free +- * for compaction, don't free any more. ++ * for compaction in this zone , don't free any ++ * more. + */ + if (sc->order > PAGE_ALLOC_COSTLY_ORDER && + (compaction_suitable(zone, sc->order) || +- compaction_deferred(zone))) ++ compaction_deferred(zone))) { ++ should_abort_reclaim = true; + continue; ++ } + } + /* + * This steals pages from memory cgroups over softlimit +@@ -2049,6 +2057,8 @@ static void shrink_zones(int priority, struct zonelist *zonelist, + + shrink_zone(priority, zone, sc); + } ++ ++ return should_abort_reclaim; + } + + static bool zone_reclaimable(struct zone *zone) +@@ -2113,7 +2123,9 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, + sc->nr_scanned = 0; + if (!priority) + disable_swap_token(sc->mem_cgroup); +- shrink_zones(priority, zonelist, sc); ++ if (shrink_zones(priority, zonelist, sc)) ++ break; ++ + /* + * Don't shrink slabs when reclaiming memory from + * over limit cgroups +-- +1.7.6.4 + diff --git a/kernel.spec b/kernel.spec index 35a2613e1..9bedf761d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -707,6 +707,10 @@ Patch21018: mmc-Always-check-for-lower-base-frequency-quirk-for-.patch #rhbz #745241 Patch21019: fuse-fix-memory-leak.patch +#rhbz #735946 +Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch +Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1282,6 +1286,10 @@ ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch #rhbz #745241 ApplyPatch fuse-fix-memory-leak.patch +#rhbz #735946 +ApplyPatch 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch +ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch + # END OF PATCH APPLICATIONS %endif @@ -1902,6 +1910,9 @@ fi # and build. %changelog +* Mon Oct 17 2011 Josh Boyer +- Add two patches to fix stalls in khugepaged (rhbz 735946) + * Thu Oct 13 2011 Josh Boyer - Update usb-add-quirk-for-logitech-webcams.patch with C600 ID (rhbz 742010) From 7be21bba8949bc7d26f4d9dbdf80c1b812505b3e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 17 Oct 2011 14:07:35 -0400 Subject: [PATCH 180/397] Linux 3.0.7 stable release --- kernel.spec | 9 ++- ...-for-packet-drop-on-82579-at-100Mbps.patch | 63 ------------------- sources | 2 +- 3 files changed, 5 insertions(+), 69 deletions(-) delete mode 100644 net-3-4-e1000e-workaround-for-packet-drop-on-82579-at-100Mbps.patch diff --git a/kernel.spec b/kernel.spec index 9bedf761d..176dbfcde 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 0 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 # Set rpm version accordingly @@ -602,7 +602,6 @@ Patch540: x86-pci-reduce-severity-of-host-bridge-window-conflict-warnings.patch Patch610: hda_intel-prealloc-4mb-dmabuffer.patch Patch700: linux-2.6-e1000-ich9-montevina.patch -Patch701: net-3-4-e1000e-workaround-for-packet-drop-on-82579-at-100Mbps.patch Patch800: linux-2.6-crash-driver.patch @@ -1201,7 +1200,6 @@ ApplyPatch linux-2.6-crash-driver.patch # Hack e1000e to work on Montevina SDV ApplyPatch linux-2.6-e1000-ich9-montevina.patch -ApplyPatch net-3-4-e1000e-workaround-for-packet-drop-on-82579-at-100Mbps.patch # crypto/ @@ -1910,7 +1908,8 @@ fi # and build. %changelog -* Mon Oct 17 2011 Josh Boyer +* Mon Oct 17 2011 Josh Boyer 2.6.40.7-0 +- Linux 3.0.7 stable release - Add two patches to fix stalls in khugepaged (rhbz 735946) * Thu Oct 13 2011 Josh Boyer diff --git a/net-3-4-e1000e-workaround-for-packet-drop-on-82579-at-100Mbps.patch b/net-3-4-e1000e-workaround-for-packet-drop-on-82579-at-100Mbps.patch deleted file mode 100644 index 626362416..000000000 --- a/net-3-4-e1000e-workaround-for-packet-drop-on-82579-at-100Mbps.patch +++ /dev/null @@ -1,63 +0,0 @@ -http://patchwork.ozlabs.org/patch/109926/ - -From: Bruce Allan - -The MAC can drop short packets when the PHY detects noise on the line at -100Mbps due to a timing issue. Workaround the issue by increasing the PLL -counter so the PHY properly recognizes the synchronization pattern from the -MAC. - -Signed-off-by: Bruce Allan -Tested-by: Jeff Pieper -Signed-off-by: Jeff Kirsher ---- - drivers/net/e1000e/ich8lan.c | 19 ++++++++++++++----- - 1 files changed, 14 insertions(+), 5 deletions(-) - -diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c -index 7525e37..46a5277 100644 ---- a/drivers/net/e1000e/ich8lan.c -+++ b/drivers/net/e1000e/ich8lan.c -@@ -137,8 +137,9 @@ - #define HV_PM_CTRL PHY_REG(770, 17) - - /* PHY Low Power Idle Control */ --#define I82579_LPI_CTRL PHY_REG(772, 20) --#define I82579_LPI_CTRL_ENABLE_MASK 0x6000 -+#define I82579_LPI_CTRL PHY_REG(772, 20) -+#define I82579_LPI_CTRL_ENABLE_MASK 0x6000 -+#define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT 0x80 - - /* EMI Registers */ - #define I82579_EMI_ADDR 0x10 -@@ -1670,6 +1671,7 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) - s32 ret_val = 0; - u16 status_reg = 0; - u32 mac_reg; -+ u16 phy_reg; - - if (hw->mac.type != e1000_pch2lan) - goto out; -@@ -1684,12 +1686,19 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) - mac_reg = er32(FEXTNVM4); - mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; - -- if (status_reg & HV_M_STATUS_SPEED_1000) -+ ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg); -+ if (ret_val) -+ goto out; -+ -+ if (status_reg & HV_M_STATUS_SPEED_1000) { - mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC; -- else -+ phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; -+ } else { - mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC; -- -+ phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; -+ } - ew32(FEXTNVM4, mac_reg); -+ ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg); - } - - out: diff --git a/sources b/sources index 296c54af1..882a51334 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 -4751b440e1c840229468e16617d5b539 patch-3.0.6.bz2 +34c883ae9b6f112029879c8672b590ad patch-3.0.7.bz2 From a7fc75d2d8730c28c312c3283d40a962dd9404ba Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 18 Oct 2011 15:47:52 -0400 Subject: [PATCH 181/397] Add patch to fix lock inversion introduced in 3.0.7 --- cputimer-Cure-lock-inversion.patch | 148 +++++++++++++++++++++++++++++ kernel.spec | 7 +- 2 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 cputimer-Cure-lock-inversion.patch diff --git a/cputimer-Cure-lock-inversion.patch b/cputimer-Cure-lock-inversion.patch new file mode 100644 index 000000000..23759ad8b --- /dev/null +++ b/cputimer-Cure-lock-inversion.patch @@ -0,0 +1,148 @@ +Path: news.gmane.org!not-for-mail +From: Peter Zijlstra +Newsgroups: gmane.linux.kernel +Subject: Re: Linux 3.1-rc9 +Date: Tue, 18 Oct 2011 11:05:13 +0200 +Lines: 84 +Approved: news@gmane.org +Message-ID: <1318928713.21167.4.camel@twins> +References: + <20111007070842.GA27555@hostway.ca> <20111007174848.GA11011@hostway.ca> + <1318010515.398.8.camel@twins> <20111008005035.GC22843@hostway.ca> + <1318060551.8395.0.camel@twins> <20111012213555.GC24461@hostway.ca> + <20111013232521.GA5654@hostway.ca> + + <1318847658.6594.40.camel@twins> + + <1318874090.4172.84.camel@twins> + + <1318879396.4172.92.camel@twins> + +NNTP-Posting-Host: lo.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8BIT +X-Trace: dough.gmane.org 1318928749 2484 80.91.229.12 (18 Oct 2011 09:05:49 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Tue, 18 Oct 2011 09:05:49 +0000 (UTC) +Cc: Linus Torvalds , + Simon Kirby , + Linux Kernel Mailing List , + Dave Jones , + Martin Schwidefsky , + Ingo Molnar +To: Thomas Gleixner +Original-X-From: linux-kernel-owner@vger.kernel.org Tue Oct 18 11:05:43 2011 +Return-path: +Envelope-to: glk-linux-kernel-3@lo.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1RG5cB-0003K9-2n + for glk-linux-kernel-3@lo.gmane.org; Tue, 18 Oct 2011 11:05:39 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1757183Ab1JRJFc (ORCPT ); + Tue, 18 Oct 2011 05:05:32 -0400 +Original-Received: from casper.infradead.org ([85.118.1.10]:40399 "EHLO + casper.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1753880Ab1JRJFa convert rfc822-to-8bit (ORCPT + ); + Tue, 18 Oct 2011 05:05:30 -0400 +Original-Received: from j77219.upc-j.chello.nl ([24.132.77.219] helo=twins) + by casper.infradead.org with esmtpsa (Exim 4.76 #1 (Red Hat Linux)) + id 1RG5bu-0008Qu-O5; Tue, 18 Oct 2011 09:05:22 +0000 +Original-Received: by twins (Postfix, from userid 1000) + id 69952813C82C; Tue, 18 Oct 2011 11:05:13 +0200 (CEST) +In-Reply-To: +X-Mailer: Evolution 3.0.3- +Original-Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel:1204676 +Archived-At: + +On Tue, 2011-10-18 at 10:39 +0200, Thomas Gleixner wrote: +> On Mon, 17 Oct 2011, Thomas Gleixner wrote: +> > That said, I really need some sleep before I can make a final +> > judgement on that horror. The call paths are such an intermingled mess +> > that it's not funny anymore. I do that tomorrow morning first thing. +> +> The patch is safe and the exit race just existed in my confused tired +> brain. Peter, can you please provide a changelog. That wants a cc +> stable as well, because that deadlock causing commit hit 3.0.7 :( + +--- +Subject: cputimer: Cure lock inversion +From: Peter Zijlstra +Date: Mon Oct 17 11:50:30 CEST 2011 + +There's a lock inversion between the cputimer->lock and rq->lock; notably +the two callchains involved are: + + update_rlimit_cpu() + sighand->siglock + set_process_cpu_timer() + cpu_timer_sample_group() + thread_group_cputimer() + cputimer->lock + thread_group_cputime() + task_sched_runtime() + ->pi_lock + rq->lock + + scheduler_tick() + rq->lock + task_tick_fair() + update_curr() + account_group_exec() + cputimer->lock + +Where the first one is enabling a CLOCK_PROCESS_CPUTIME_ID timer, and +the second one is keeping up-to-date. + +This problem was introduced by e8abccb7193 ("posix-cpu-timers: Cure +SMP accounting oddities"). + +Cure the problem by removing the cputimer->lock and rq->lock nesting, +this leaves concurrent enablers doing duplicate work, but the time +wasted should be on the same order otherwise wasted spinning on the +lock and the greater-than assignment filter should ensure we preserve +monotonicity. + +Reported-by: Dave Jones +Reported-by: Simon Kirby +Cc: stable@kernel.org +Cc: Thomas Gleixner +Signed-off-by: Peter Zijlstra +--- + kernel/posix-cpu-timers.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) +Index: linux-2.6/kernel/posix-cpu-timers.c +=================================================================== +--- linux-2.6.orig/kernel/posix-cpu-timers.c ++++ linux-2.6/kernel/posix-cpu-timers.c +@@ -274,9 +274,7 @@ void thread_group_cputimer(struct task_s + struct task_cputime sum; + unsigned long flags; + +- spin_lock_irqsave(&cputimer->lock, flags); + if (!cputimer->running) { +- cputimer->running = 1; + /* + * The POSIX timer interface allows for absolute time expiry + * values through the TIMER_ABSTIME flag, therefore we have +@@ -284,8 +282,11 @@ void thread_group_cputimer(struct task_s + * it. + */ + thread_group_cputime(tsk, &sum); ++ spin_lock_irqsave(&cputimer->lock, flags); ++ cputimer->running = 1; + update_gt_cputime(&cputimer->cputime, &sum); +- } ++ } else ++ spin_lock_irqsave(&cputimer->lock, flags); + *times = cputimer->cputime; + spin_unlock_irqrestore(&cputimer->lock, flags); + } + diff --git a/kernel.spec b/kernel.spec index 176dbfcde..6a5d38ed0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 0 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -649,6 +649,7 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch Patch12024: usb-add-quirk-for-logitech-webcams.patch Patch12025: crypto-register-cryptd-first.patch +Patch12026: cputimer-Cure-lock-inversion.patch # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch @@ -1240,6 +1241,7 @@ ApplyPatch add-appleir-usb-driver.patch ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch ApplyPatch crypto-register-cryptd-first.patch +ApplyPatch cputimer-Cure-lock-inversion.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -1908,6 +1910,9 @@ fi # and build. %changelog +* Tue Oct 18 2011 Josh Boyer +- Add patch to fix lock inversion introduced in 3.0.7 + * Mon Oct 17 2011 Josh Boyer 2.6.40.7-0 - Linux 3.0.7 stable release - Add two patches to fix stalls in khugepaged (rhbz 735946) From f6d62efb23225a63c162368b07ff4f8df8a5597d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 18 Oct 2011 16:04:40 -0400 Subject: [PATCH 182/397] Add patch to fix invalid EFI remap calls from Matt Fleming --- kernel.spec | 3 + ...a-with-an-ioremap-address-is-invalid.patch | 211 ++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch diff --git a/kernel.spec b/kernel.spec index 6a5d38ed0..b785e133a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -650,6 +650,7 @@ Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch Patch12024: usb-add-quirk-for-logitech-webcams.patch Patch12025: crypto-register-cryptd-first.patch Patch12026: cputimer-Cure-lock-inversion.patch +Patch12027: x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch @@ -1242,6 +1243,7 @@ ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch ApplyPatch crypto-register-cryptd-first.patch ApplyPatch cputimer-Cure-lock-inversion.patch +ApplyPatch x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -1911,6 +1913,7 @@ fi %changelog * Tue Oct 18 2011 Josh Boyer +- Add patch to fix invalid EFI remap calls from Matt Fleming - Add patch to fix lock inversion introduced in 3.0.7 * Mon Oct 17 2011 Josh Boyer 2.6.40.7-0 diff --git a/x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch b/x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch new file mode 100644 index 000000000..f05567fe3 --- /dev/null +++ b/x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch @@ -0,0 +1,211 @@ +Path: news.gmane.org!not-for-mail +From: Matt Fleming +Newsgroups: gmane.linux.kernel +Subject: [PATCH v2] x86, efi: Calling __pa() with an ioremap'd address is invalid +Date: Fri, 14 Oct 2011 12:36:45 +0100 +Lines: 160 +Approved: news@gmane.org +Message-ID: <1318592205-11193-1-git-send-email-matt@console-pimps.org> +NNTP-Posting-Host: lo.gmane.org +X-Trace: dough.gmane.org 1318592224 30879 80.91.229.12 (14 Oct 2011 11:37:04 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Fri, 14 Oct 2011 11:37:04 +0000 (UTC) +Cc: Thomas Gleixner , Ingo Molnar , + "H. Peter Anvin" , Zhang Rui , + Huang Ying , + linux-kernel@vger.kernel.org +To: Matthew Garrett +Original-X-From: linux-kernel-owner@vger.kernel.org Fri Oct 14 13:36:59 2011 +Return-path: +Envelope-to: glk-linux-kernel-3@lo.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1REg4Q-0001UQ-SA + for glk-linux-kernel-3@lo.gmane.org; Fri, 14 Oct 2011 13:36:59 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1755420Ab1JNLgv (ORCPT ); + Fri, 14 Oct 2011 07:36:51 -0400 +Original-Received: from arkanian.console-pimps.org ([212.110.184.194]:46859 "EHLO + arkanian.console-pimps.org" rhost-flags-OK-OK-OK-OK) + by vger.kernel.org with ESMTP id S1751315Ab1JNLgu (ORCPT + ); + Fri, 14 Oct 2011 07:36:50 -0400 +Original-Received: by arkanian.console-pimps.org (Postfix, from userid 1002) + id 443C1C0009; Fri, 14 Oct 2011 12:36:49 +0100 (BST) +X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on + arkanian.vm.bytemark.co.uk +X-Spam-Level: +X-Spam-Status: No, score=-5.3 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00 + autolearn=ham version=3.2.5 +Original-Received: from localhost (02ddb86b.bb.sky.com [2.221.184.107]) + by arkanian.console-pimps.org (Postfix) with ESMTPSA id F0D40C0008; + Fri, 14 Oct 2011 12:36:47 +0100 (BST) +X-Mailer: git-send-email 1.7.4.4 +Original-Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel:1203294 +Archived-At: + +From: Matt Fleming + +If we encounter an efi_memory_desc_t without EFI_MEMORY_WB set in +->attribute we currently call set_memory_uc(), which in turn calls +__pa() on a potentially ioremap'd address. On CONFIG_X86_32 this is +invalid, resulting in the following oops, + + BUG: unable to handle kernel paging request at f7f22280 + IP: [] reserve_ram_pages_type+0x89/0x210 + *pdpt = 0000000001978001 *pde = 0000000001ffb067 *pte = 0000000000000000 + Oops: 0000 [#1] PREEMPT SMP + Modules linked in: + + Pid: 0, comm: swapper Not tainted 3.0.0-acpi-efi-0805 #3 + EIP: 0060:[] EFLAGS: 00010202 CPU: 0 + EIP is at reserve_ram_pages_type+0x89/0x210 + EAX: 0070e280 EBX: 38714000 ECX: f7814000 EDX: 00000000 + ESI: 00000000 EDI: 38715000 EBP: c189fef0 ESP: c189fea8 + DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 + Process swapper (pid: 0, ti=c189e000 task=c18bbe60 task.ti=c189e000) + Stack: + 80000200 ff108000 00000000 c189ff00 00038714 00000000 00000000 c189fed0 + c104f8ca 00038714 00000000 00038715 00000000 00000000 00038715 00000000 + 00000010 38715000 c189ff48 c1025aff 38715000 00000000 00000010 00000000 + Call Trace: + [] ? page_is_ram+0x1a/0x40 + [] reserve_memtype+0xdf/0x2f0 + [] set_memory_uc+0x49/0xa0 + [] efi_enter_virtual_mode+0x1c2/0x3aa + [] start_kernel+0x291/0x2f2 + [] ? loglevel+0x1b/0x1b + [] i386_start_kernel+0xbf/0xc8 + +So, if we're ioremap'ing an address range let's setup the mapping with +the correct caching attribute instead of modifying it after the fact. + +Also, take this opportunity to unify the 32/64-bit efi_ioremap() +implementations because they can both be implemented with +ioremap_{cache,nocache}. When asked about the original reason behind +using init_memory_mapping() for the 64-bit version Huang Ying said, + + "The intention of init_memory_mapping() usage is to make EFI virtual + address unchanged after kexec. But in fact, init_memory_mapping() + can not handle some memory range, so ioremap_xxx() is introduced as + a fix. Now we decide to use ioremap_xxx() anyway and use some other + scheme for kexec support, so init_memory_mapping() here is + unnecessary. IMHO, init_memory_mapping() is not as good as + ioremap_xxx() here." + +And because efi_ioremap() now consists of 4 lines, let's just inline +it directly into the one callsite in efi_enter_virtual_mode(). + +Cc: Thomas Gleixner +Cc: Ingo Molnar +Cc: H. Peter Anvin +Cc: Matthew Garrett +Cc: Zhang Rui +Cc: Huang Ying +Cc: stable@kernel.org +Signed-off-by: Matt Fleming +--- + arch/x86/include/asm/efi.h | 5 ----- + arch/x86/platform/efi/efi.c | 24 ++++++++++++++---------- + arch/x86/platform/efi/efi_64.c | 17 ----------------- + 3 files changed, 14 insertions(+), 32 deletions(-) + +diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h +index 7093e4a..b8d8bfc 100644 +--- a/arch/x86/include/asm/efi.h ++++ b/arch/x86/include/asm/efi.h +@@ -33,8 +33,6 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...); + #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \ + efi_call_virt(f, a1, a2, a3, a4, a5, a6) + +-#define efi_ioremap(addr, size, type) ioremap_cache(addr, size) +- + #else /* !CONFIG_X86_32 */ + + extern u64 efi_call0(void *fp); +@@ -84,9 +82,6 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3, + efi_call6((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ + (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6)) + +-extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, +- u32 type); +- + #endif /* CONFIG_X86_32 */ + + extern int add_efi_memmap; +diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c +index 3ae4128..6ea011c 100644 +--- a/arch/x86/platform/efi/efi.c ++++ b/arch/x86/platform/efi/efi.c +@@ -670,10 +670,21 @@ void __init efi_enter_virtual_mode(void) + end_pfn = PFN_UP(end); + if (end_pfn <= max_low_pfn_mapped + || (end_pfn > (1UL << (32 - PAGE_SHIFT)) +- && end_pfn <= max_pfn_mapped)) ++ && end_pfn <= max_pfn_mapped)) { + va = __va(md->phys_addr); +- else +- va = efi_ioremap(md->phys_addr, size, md->type); ++ ++ if (!(md->attribute & EFI_MEMORY_WB)) { ++ addr = (u64) (unsigned long)va; ++ npages = md->num_pages; ++ memrange_efi_to_native(&addr, &npages); ++ set_memory_uc(addr, npages); ++ } ++ } else { ++ if (!(md->attribute & EFI_MEMORY_WB)) ++ va = ioremap_nocache(md->phys_addr, size); ++ else ++ va = ioremap_cache(md->phys_addr, size); ++ } + + md->virt_addr = (u64) (unsigned long) va; + +@@ -683,13 +694,6 @@ void __init efi_enter_virtual_mode(void) + continue; + } + +- if (!(md->attribute & EFI_MEMORY_WB)) { +- addr = md->virt_addr; +- npages = md->num_pages; +- memrange_efi_to_native(&addr, &npages); +- set_memory_uc(addr, npages); +- } +- + systab = (u64) (unsigned long) efi_phys.systab; + if (md->phys_addr <= systab && systab < end) { + systab += md->virt_addr - md->phys_addr; +diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c +index ac3aa54..312250c 100644 +--- a/arch/x86/platform/efi/efi_64.c ++++ b/arch/x86/platform/efi/efi_64.c +@@ -80,20 +80,3 @@ void __init efi_call_phys_epilog(void) + local_irq_restore(efi_flags); + early_code_mapping_set_exec(0); + } +- +-void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, +- u32 type) +-{ +- unsigned long last_map_pfn; +- +- if (type == EFI_MEMORY_MAPPED_IO) +- return ioremap(phys_addr, size); +- +- last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size); +- if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) { +- unsigned long top = last_map_pfn << PAGE_SHIFT; +- efi_ioremap(top, size - (top - phys_addr), type); +- } +- +- return (void __iomem *)__va(phys_addr); +-} +-- +1.7.4.4 + From e8a2ce7b99b490fe43b0072b197a6fcffea11898 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 19 Oct 2011 13:17:37 -0400 Subject: [PATCH 183/397] Add Sony VGN-FW21E to nonvs blacklist. (rhbz 641789) --- acpi-sony-nonvs-blacklist.patch | 19 +++++++++++++++++++ kernel.spec | 5 +++++ 2 files changed, 24 insertions(+) create mode 100644 acpi-sony-nonvs-blacklist.patch diff --git a/acpi-sony-nonvs-blacklist.patch b/acpi-sony-nonvs-blacklist.patch new file mode 100644 index 000000000..f332c6443 --- /dev/null +++ b/acpi-sony-nonvs-blacklist.patch @@ -0,0 +1,19 @@ +diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c +index 3ed80b2..17fc718 100644 +--- a/drivers/acpi/sleep.c ++++ b/drivers/acpi/sleep.c +@@ -390,6 +390,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { + }, + { + .callback = init_nvs_nosave, ++ .ident = "Sony Vaio VGN-FW21E", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"), ++ }, ++ }, ++ { ++ .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-SR11M", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), diff --git a/kernel.spec b/kernel.spec index b785e133a..86dca2aea 100644 --- a/kernel.spec +++ b/kernel.spec @@ -586,6 +586,7 @@ 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 Patch395: acpi-ensure-thermal-limits-match-cpu-freq.patch +Patch396: acpi-sony-nonvs-blacklist.patch Patch450: linux-2.6-input-kill-stupid-messages.patch Patch452: linux-2.6.30-no-pcspkr-modalias.patch @@ -1151,6 +1152,7 @@ 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-ensure-thermal-limits-match-cpu-freq.patch +ApplyPatch acpi-sony-nonvs-blacklist.patch # Various low-impact patches to aid debugging. ApplyPatch linux-2.6-debug-taint-vm.patch @@ -1912,6 +1914,9 @@ fi # and build. %changelog +* Wed Oct 19 2011 Dave Jones +- Add Sony VGN-FW21E to nonvs blacklist. (rhbz 641789) + * Tue Oct 18 2011 Josh Boyer - Add patch to fix invalid EFI remap calls from Matt Fleming - Add patch to fix lock inversion introduced in 3.0.7 From 73fbe46367cf6b567a26be06c1cd719e8d49c779 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 20 Oct 2011 08:59:15 -0400 Subject: [PATCH 184/397] Add backport for P4 watchdog and perf support from Don Zickus (rhbz 713675) --- kernel.spec | 7 +- ...make-watchdog-and-perf-work-together.patch | 267 ++++++++++++++++++ 2 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 x86-p4-make-watchdog-and-perf-work-together.patch diff --git a/kernel.spec b/kernel.spec index 86dca2aea..5216e0ef2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -652,6 +652,7 @@ Patch12024: usb-add-quirk-for-logitech-webcams.patch Patch12025: crypto-register-cryptd-first.patch Patch12026: cputimer-Cure-lock-inversion.patch Patch12027: x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch +Patch12028: x86-p4-make-watchdog-and-perf-work-together.patch # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch @@ -1246,6 +1247,7 @@ ApplyPatch usb-add-quirk-for-logitech-webcams.patch ApplyPatch crypto-register-cryptd-first.patch ApplyPatch cputimer-Cure-lock-inversion.patch ApplyPatch x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch +ApplyPatch x86-p4-make-watchdog-and-perf-work-together.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -1914,6 +1916,9 @@ fi # and build. %changelog +* Thu Oct 20 2011 Josh Boyer +- Add backport for P4 watchdog and perf support from Don Zickus (rhbz 713675) + * Wed Oct 19 2011 Dave Jones - Add Sony VGN-FW21E to nonvs blacklist. (rhbz 641789) diff --git a/x86-p4-make-watchdog-and-perf-work-together.patch b/x86-p4-make-watchdog-and-perf-work-together.patch new file mode 100644 index 000000000..9ef049b96 --- /dev/null +++ b/x86-p4-make-watchdog-and-perf-work-together.patch @@ -0,0 +1,267 @@ +BZ https://bugzilla.redhat.com/show_bug.cgi?id=713675 + +Let nmi watchdog and perf work together on a P4. Combination of the following 3.1 +upstream commits (the second commit reverts the first one). + +commit 1880c4ae182afb5650c5678949ecfe7ff66a724e +Author: Cyrill Gorcunov +Date: Thu Jun 23 16:49:18 2011 +0400 + + perf, x86: Add hw_watchdog_set_attr() in a sake of nmi-watchdog on P4 + + Due to restriction and specifics of Netburst PMU we need a separated + event for NMI watchdog. In particular every Netburst event + consumes not just a counter and a config register, but also an + additional ESCR register. + + Since ESCR registers are grouped upon counters (i.e. if ESCR is occupied + for some event there is no room for another event to enter until its + released) we need to pick up the "least" used ESCR (or the most available + one) for nmi-watchdog purposes -- so MSR_P4_CRU_ESCR2/3 was chosen. + + With this patch nmi-watchdog and perf top should be able to run simultaneously. + + Signed-off-by: Cyrill Gorcunov + CC: Lin Ming + CC: Arnaldo Carvalho de Melo + CC: Frederic Weisbecker + Tested-and-reviewed-by: Don Zickus + Tested-and-reviewed-by: Stephane Eranian + Signed-off-by: Peter Zijlstra + Link: http://lkml.kernel.org/r/20110623124918.GC13050@sun + Signed-off-by: Ingo Molnar + +commit f91298709790b9a483752ca3c967845537df2af3 +Author: Cyrill Gorcunov +Date: Sat Jul 9 00:17:12 2011 +0400 + + perf, x86: P4 PMU - Introduce event alias feature + + Instead of hw_nmi_watchdog_set_attr() weak function + and appropriate x86_pmu::hw_watchdog_set_attr() call + we introduce even alias mechanism which allow us + to drop this routines completely and isolate quirks + of Netburst architecture inside P4 PMU code only. + + The main idea remains the same though -- to allow + nmi-watchdog and perf top run simultaneously. + + Note the aliasing mechanism applies to generic + PERF_COUNT_HW_CPU_CYCLES event only because arbitrary + event (say passed as RAW initially) might have some + additional bits set inside ESCR register changing + the behaviour of event and we can't guarantee anymore + that alias event will give the same result. + + P.S. Thanks a huge to Don and Steven for for testing + and early review. + + Acked-by: Don Zickus + Tested-by: Steven Rostedt + Signed-off-by: Cyrill Gorcunov + CC: Ingo Molnar + CC: Peter Zijlstra + CC: Stephane Eranian + CC: Lin Ming + CC: Arnaldo Carvalho de Melo + CC: Frederic Weisbecker + Link: http://lkml.kernel.org/r/20110708201712.GS23657@sun + Signed-off-by: Steven Rostedt + + +diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h +index 56fd9e3..4d86c86 100644 +--- a/arch/x86/include/asm/perf_event_p4.h ++++ b/arch/x86/include/asm/perf_event_p4.h +@@ -102,6 +102,14 @@ + #define P4_CONFIG_HT (1ULL << P4_CONFIG_HT_SHIFT) + + /* ++ * If an event has alias it should be marked ++ * with a special bit. (Don't forget to check ++ * P4_PEBS_CONFIG_MASK and related bits on ++ * modification.) ++ */ ++#define P4_CONFIG_ALIASABLE (1 << 9) ++ ++/* + * The bits we allow to pass for RAW events + */ + #define P4_CONFIG_MASK_ESCR \ +@@ -123,6 +131,31 @@ + (p4_config_pack_escr(P4_CONFIG_MASK_ESCR)) | \ + (p4_config_pack_cccr(P4_CONFIG_MASK_CCCR)) + ++/* ++ * In case of event aliasing we need to preserve some ++ * caller bits otherwise the mapping won't be complete. ++ */ ++#define P4_CONFIG_EVENT_ALIAS_MASK \ ++ (p4_config_pack_escr(P4_CONFIG_MASK_ESCR) | \ ++ p4_config_pack_cccr(P4_CCCR_EDGE | \ ++ P4_CCCR_THRESHOLD_MASK | \ ++ P4_CCCR_COMPLEMENT | \ ++ P4_CCCR_COMPARE)) ++ ++#define P4_CONFIG_EVENT_ALIAS_IMMUTABLE_BITS \ ++ ((P4_CONFIG_HT) | \ ++ p4_config_pack_escr(P4_ESCR_T0_OS | \ ++ P4_ESCR_T0_USR | \ ++ P4_ESCR_T1_OS | \ ++ P4_ESCR_T1_USR) | \ ++ p4_config_pack_cccr(P4_CCCR_OVF | \ ++ P4_CCCR_CASCADE | \ ++ P4_CCCR_FORCE_OVF | \ ++ P4_CCCR_THREAD_ANY | \ ++ P4_CCCR_OVF_PMI_T0 | \ ++ P4_CCCR_OVF_PMI_T1 | \ ++ P4_CONFIG_ALIASABLE)) ++ + static inline bool p4_is_event_cascaded(u64 config) + { + u32 cccr = p4_config_unpack_cccr(config); +diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c +index ead584f..0c4071a 100644 +--- a/arch/x86/kernel/cpu/perf_event_p4.c ++++ b/arch/x86/kernel/cpu/perf_event_p4.c +@@ -556,11 +556,92 @@ static __initconst const u64 p4_hw_cache_event_ids + }, + }; + ++/* ++ * Because of Netburst being quite restricted in now ++ * many same events can run simultaneously, we use ++ * event aliases, ie different events which have the ++ * same functionallity but use non-intersected resources ++ * (ESCR/CCCR/couter registers). This allow us to run ++ * two or more semi-same events together. It is done ++ * transparently to a user space. ++ * ++ * Never set any cusom internal bits such as P4_CONFIG_HT, ++ * P4_CONFIG_ALIASABLE or bits for P4_PEBS_METRIC, they are ++ * either up-to-dated automatically either not appliable ++ * at all. ++ * ++ * And be really carefull choosing aliases! ++ */ ++struct p4_event_alias { ++ u64 orig; ++ u64 alter; ++} p4_event_aliases[] = { ++ { ++ /* ++ * Non-halted cycles can be substituted with ++ * non-sleeping cycles (see Intel SDM Vol3b for ++ * details). ++ */ ++ .orig = ++ p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_GLOBAL_POWER_EVENTS) | ++ P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)), ++ .alter = ++ p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_EXECUTION_EVENT) | ++ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS0)| ++ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS1)| ++ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS2)| ++ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS3)| ++ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS0) | ++ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS1) | ++ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS2) | ++ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS3))| ++ p4_config_pack_cccr(P4_CCCR_THRESHOLD(15) | P4_CCCR_COMPLEMENT | ++ P4_CCCR_COMPARE), ++ }, ++}; ++ ++static u64 p4_get_alias_event(u64 config) ++{ ++ u64 config_match; ++ int i; ++ ++ /* ++ * Probably we're lucky and don't have to do ++ * matching over all config bits. ++ */ ++ if (!(config & P4_CONFIG_ALIASABLE)) ++ return 0; ++ ++ config_match = config & P4_CONFIG_EVENT_ALIAS_MASK; ++ ++ /* ++ * If an event was previously swapped to the alter config ++ * we should swap it back otherwise contnention on registers ++ * will return back. ++ */ ++ for (i = 0; i < ARRAY_SIZE(p4_event_aliases); i++) { ++ if (config_match == p4_event_aliases[i].orig) { ++ config_match = p4_event_aliases[i].alter; ++ break; ++ } else if (config_match == p4_event_aliases[i].alter) { ++ config_match = p4_event_aliases[i].orig; ++ break; ++ } ++ } ++ ++ if (i >= ARRAY_SIZE(p4_event_aliases)) ++ return 0; ++ ++ return config_match | ++ (config & P4_CONFIG_EVENT_ALIAS_IMMUTABLE_BITS); ++} ++ + static u64 p4_general_events[PERF_COUNT_HW_MAX] = { + /* non-halted CPU clocks */ + [PERF_COUNT_HW_CPU_CYCLES] = + p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_GLOBAL_POWER_EVENTS) | +- P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)), ++ P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)) | ++ P4_CONFIG_ALIASABLE, + + /* + * retired instructions +@@ -1120,6 +1201,8 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign + struct p4_event_bind *bind; + unsigned int i, thread, num; + int cntr_idx, escr_idx; ++ u64 config_alias; ++ int pass; + + bitmap_zero(used_mask, X86_PMC_IDX_MAX); + bitmap_zero(escr_mask, P4_ESCR_MSR_TABLE_SIZE); +@@ -1128,6 +1211,17 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign + + hwc = &cpuc->event_list[i]->hw; + thread = p4_ht_thread(cpu); ++ pass = 0; ++ ++again: ++ /* ++ * Aliases are swappable so we may hit circular ++ * lock if both original config and alias need ++ * resources (MSR registers) which already busy. ++ */ ++ if (pass > 2) ++ goto done; ++ + bind = p4_config_get_bind(hwc->config); + escr_idx = p4_get_escr_idx(bind->escr_msr[thread]); + if (unlikely(escr_idx == -1)) +@@ -1141,8 +1235,17 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign + } + + cntr_idx = p4_next_cntr(thread, used_mask, bind); +- if (cntr_idx == -1 || test_bit(escr_idx, escr_mask)) +- goto done; ++ if (cntr_idx == -1 || test_bit(escr_idx, escr_mask)) { ++ /* ++ * Probably an event alias is still available. ++ */ ++ config_alias = p4_get_alias_event(hwc->config); ++ if (!config_alias) ++ goto done; ++ hwc->config = config_alias; ++ pass++; ++ goto again; ++ } + + p4_pmu_swap_config_ts(hwc, cpu); + if (assign) From 70cad0483df92cfcd57b07de973f1b099b076d6b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 21 Oct 2011 12:58:17 -0400 Subject: [PATCH 185/397] Lower severity of Radeon lockup messages. --- drm-lower-severity-radeon-lockup.diff | 13 +++++++++++++ kernel.spec | 8 ++++++++ 2 files changed, 21 insertions(+) create mode 100644 drm-lower-severity-radeon-lockup.diff diff --git a/drm-lower-severity-radeon-lockup.diff b/drm-lower-severity-radeon-lockup.diff new file mode 100644 index 000000000..1302c92ea --- /dev/null +++ b/drm-lower-severity-radeon-lockup.diff @@ -0,0 +1,13 @@ +diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c +index 7fd4e3e..a488b50 100644 +--- a/drivers/gpu/drm/radeon/radeon_fence.c ++++ b/drivers/gpu/drm/radeon/radeon_fence.c +@@ -263,7 +263,7 @@ retry: + */ + if (seq == rdev->fence_drv.last_seq && radeon_gpu_is_lockup(rdev)) { + /* good news we believe it's a lockup */ +- WARN(1, "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n", ++ printk(KERN_WARNING "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n", + fence->seq, seq); + /* FIXME: what should we do ? marking everyone + * as signaled for now diff --git a/kernel.spec b/kernel.spec index 5216e0ef2..8a61edeee 100644 --- a/kernel.spec +++ b/kernel.spec @@ -623,6 +623,8 @@ Patch1825: drm-intel-make-lvds-work.patch # rhbz#729882, https://bugs.freedesktop.org/attachment.cgi?id=49069 Patch1827: drm-i915-sdvo-lvds-is-digital.patch +Patch1850: drm-lower-severity-radeon-lockup.diff + Patch1900: linux-2.6-intel-iommu-igfx.patch Patch2000: block-stray-block-put-after-teardown.patch @@ -1221,6 +1223,9 @@ ApplyOptionalPatch drm-nouveau-updates.patch ApplyOptionalPatch drm-intel-next.patch ApplyPatch drm-intel-make-lvds-work.patch ApplyPatch drm-i915-sdvo-lvds-is-digital.patch + +ApplyPatch drm-lower-severity-radeon-lockup.diff + ApplyPatch linux-2.6-intel-iommu-igfx.patch ApplyPatch block-stray-block-put-after-teardown.patch @@ -1916,6 +1921,9 @@ fi # and build. %changelog +* Fri Oct 21 2011 Dave Jones +- Lower severity of Radeon lockup messages. + * Thu Oct 20 2011 Josh Boyer - Add backport for P4 watchdog and perf support from Don Zickus (rhbz 713675) From 4ab6a85e89d5ad3a0f1e751c6bffbdb22d8073ec Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 24 Oct 2011 09:01:53 -0400 Subject: [PATCH 186/397] Backport 3 fixed from linux-next to fix dib0700 playback (rhbz 733827) --- kernel.spec | 13 +- ...-DiBcom-protect-the-I2C-bufer-access.patch | 1159 +++++++++++++++++ media-dib0700-correct-error-message.patch | 105 ++ ...00-protect-the-dib0700-buffer-access.patch | 250 ++++ 4 files changed, 1526 insertions(+), 1 deletion(-) create mode 100644 media-DiBcom-protect-the-I2C-bufer-access.patch create mode 100644 media-dib0700-correct-error-message.patch create mode 100644 media-dib0700-protect-the-dib0700-buffer-access.patch diff --git a/kernel.spec b/kernel.spec index 8a61edeee..0838191bd 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -638,6 +638,10 @@ 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: media-DiBcom-protect-the-I2C-bufer-access.patch +Patch2903: media-dib0700-protect-the-dib0700-buffer-access.patch +Patch2904: media-dib0700-correct-error-message.patch + Patch3000: rcutree-avoid-false-quiescent-states.patch # fs fixes @@ -1239,6 +1243,10 @@ 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 media-DiBcom-protect-the-I2C-bufer-access.patch +ApplyPatch media-dib0700-protect-the-dib0700-buffer-access.patch +ApplyPatch media-dib0700-correct-error-message.patch + # Avoid false quiescent states in rcu. ApplyPatch rcutree-avoid-false-quiescent-states.patch @@ -1921,6 +1929,9 @@ fi # and build. %changelog +* Mon Oct 24 2011 Josh Boyer +- Backport 3 fixed from linux-next to fix dib0700 playback (rhbz 733827) + * Fri Oct 21 2011 Dave Jones - Lower severity of Radeon lockup messages. diff --git a/media-DiBcom-protect-the-I2C-bufer-access.patch b/media-DiBcom-protect-the-I2C-bufer-access.patch new file mode 100644 index 000000000..dc988bb18 --- /dev/null +++ b/media-DiBcom-protect-the-I2C-bufer-access.patch @@ -0,0 +1,1159 @@ +From 4aa9d354534c2fcbb06170f5968f762aa9bdd0f6 Mon Sep 17 00:00:00 2001 +From: Patrick Boettcher +Date: Wed, 3 Aug 2011 15:08:21 -0300 +Subject: [PATCH 1/3] [media] DiBcom: protect the I2C bufer access + +This patch protects the I2C buffer access in order to manage concurrent +access. This protection is done using mutex. +Furthermore, for the dib9000, if a pid filtering command is +received during the tuning, this pid filtering command is delayed to +avoid any concurrent access issue. + +Cc: Mauro Carvalho Chehab +Cc: Florian Mickler +Cc: stable@kernel.org +Signed-off-by: Olivier Grenie +Signed-off-by: Patrick Boettcher +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/dvb/frontends/dib0070.c | 37 +++++- + drivers/media/dvb/frontends/dib0090.c | 70 +++++++++-- + drivers/media/dvb/frontends/dib7000m.c | 27 ++++- + drivers/media/dvb/frontends/dib7000p.c | 32 +++++- + drivers/media/dvb/frontends/dib8000.c | 72 ++++++++++-- + drivers/media/dvb/frontends/dib9000.c | 164 +++++++++++++++++++++++--- + drivers/media/dvb/frontends/dibx000_common.c | 76 ++++++++++-- + drivers/media/dvb/frontends/dibx000_common.h | 1 + + 8 files changed, 412 insertions(+), 67 deletions(-) + +diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c +index 1d47d4d..dc1cb17 100644 +--- a/drivers/media/dvb/frontends/dib0070.c ++++ b/drivers/media/dvb/frontends/dib0070.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include "dvb_frontend.h" + +@@ -78,10 +79,18 @@ struct dib0070_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[3]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + +-static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) ++static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = reg; + + memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); +@@ -96,13 +105,23 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) + + if (i2c_transfer(state->i2c, state->msg, 2) != 2) { + printk(KERN_WARNING "DiB0070 I2C read failed\n"); +- return 0; +- } +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ ret = 0; ++ } else ++ ret = (state->i2c_read_buffer[0] << 8) ++ | state->i2c_read_buffer[1]; ++ ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } + state->i2c_write_buffer[0] = reg; + state->i2c_write_buffer[1] = val >> 8; + state->i2c_write_buffer[2] = val & 0xff; +@@ -115,9 +134,12 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) + + if (i2c_transfer(state->i2c, state->msg, 1) != 1) { + printk(KERN_WARNING "DiB0070 I2C write failed\n"); +- return -EREMOTEIO; +- } +- return 0; ++ ret = -EREMOTEIO; ++ } else ++ ret = 0; ++ ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + #define HARD_RESET(state) do { \ +@@ -734,6 +756,7 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter + state->cfg = cfg; + state->i2c = i2c; + state->fe = fe; ++ mutex_init(&state->i2c_buffer_lock); + fe->tuner_priv = state; + + if (dib0070_reset(fe) != 0) +diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c +index c9c935a..b174d1c 100644 +--- a/drivers/media/dvb/frontends/dib0090.c ++++ b/drivers/media/dvb/frontends/dib0090.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include "dvb_frontend.h" + +@@ -196,6 +197,7 @@ struct dib0090_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[3]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + struct dib0090_fw_state { +@@ -208,10 +210,18 @@ struct dib0090_fw_state { + struct i2c_msg msg; + u8 i2c_write_buffer[2]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = reg; + + memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); +@@ -226,14 +236,24 @@ static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) + + if (i2c_transfer(state->i2c, state->msg, 2) != 2) { + printk(KERN_WARNING "DiB0090 I2C read failed\n"); +- return 0; +- } ++ ret = 0; ++ } else ++ ret = (state->i2c_read_buffer[0] << 8) ++ | state->i2c_read_buffer[1]; + +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + state->i2c_write_buffer[0] = reg & 0xff; + state->i2c_write_buffer[1] = val >> 8; + state->i2c_write_buffer[2] = val & 0xff; +@@ -246,13 +266,23 @@ static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) + + if (i2c_transfer(state->i2c, state->msg, 1) != 1) { + printk(KERN_WARNING "DiB0090 I2C write failed\n"); +- return -EREMOTEIO; +- } +- return 0; ++ ret = -EREMOTEIO; ++ } else ++ ret = 0; ++ ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = reg; + + memset(&state->msg, 0, sizeof(struct i2c_msg)); +@@ -262,13 +292,24 @@ static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg) + state->msg.len = 2; + if (i2c_transfer(state->i2c, &state->msg, 1) != 1) { + printk(KERN_WARNING "DiB0090 I2C read failed\n"); +- return 0; +- } +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ ret = 0; ++ } else ++ ret = (state->i2c_read_buffer[0] << 8) ++ | state->i2c_read_buffer[1]; ++ ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + state->i2c_write_buffer[0] = val >> 8; + state->i2c_write_buffer[1] = val & 0xff; + +@@ -279,9 +320,12 @@ static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val) + state->msg.len = 2; + if (i2c_transfer(state->i2c, &state->msg, 1) != 1) { + printk(KERN_WARNING "DiB0090 I2C write failed\n"); +- return -EREMOTEIO; +- } +- return 0; ++ ret = -EREMOTEIO; ++ } else ++ ret = 0; ++ ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + #define HARD_RESET(state) do { if (cfg->reset) { if (cfg->sleep) cfg->sleep(fe, 0); msleep(10); cfg->reset(fe, 1); msleep(10); cfg->reset(fe, 0); msleep(10); } } while (0) +@@ -2440,6 +2484,7 @@ struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapte + st->config = config; + st->i2c = i2c; + st->fe = fe; ++ mutex_init(&st->i2c_buffer_lock); + fe->tuner_priv = st; + + if (config->wbd == NULL) +@@ -2471,6 +2516,7 @@ struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_ada + st->config = config; + st->i2c = i2c; + st->fe = fe; ++ mutex_init(&st->i2c_buffer_lock); + fe->tuner_priv = st; + + if (dib0090_fw_reset_digital(fe, st->config) != 0) +diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c +index 79cb1c2..dbb76d7 100644 +--- a/drivers/media/dvb/frontends/dib7000m.c ++++ b/drivers/media/dvb/frontends/dib7000m.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + #include "dvb_frontend.h" + +@@ -55,6 +56,7 @@ struct dib7000m_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[4]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + enum dib7000m_power_mode { +@@ -69,6 +71,13 @@ enum dib7000m_power_mode { + + static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = (reg >> 8) | 0x80; + state->i2c_write_buffer[1] = reg & 0xff; + +@@ -85,11 +94,21 @@ static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) + if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2) + dprintk("i2c read error on %d",reg); + +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ mutex_unlock(&state->i2c_buffer_lock); ++ ++ return ret; + } + + static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + state->i2c_write_buffer[0] = (reg >> 8) & 0xff; + state->i2c_write_buffer[1] = reg & 0xff; + state->i2c_write_buffer[2] = (val >> 8) & 0xff; +@@ -101,7 +120,10 @@ static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) + state->msg[0].buf = state->i2c_write_buffer; + state->msg[0].len = 4; + +- return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; ++ ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? ++ -EREMOTEIO : 0); ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf) + { +@@ -1385,6 +1407,7 @@ struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, + demod = &st->demod; + demod->demodulator_priv = st; + memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops)); ++ mutex_init(&st->i2c_buffer_lock); + + st->timf_default = cfg->bw->timf; + +diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c +index 0c9f40c..292bc19 100644 +--- a/drivers/media/dvb/frontends/dib7000p.c ++++ b/drivers/media/dvb/frontends/dib7000p.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + #include "dvb_math.h" + #include "dvb_frontend.h" +@@ -68,6 +69,7 @@ struct dib7000p_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[4]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + enum dib7000p_power_mode { +@@ -81,6 +83,13 @@ static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff); + + static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = reg >> 8; + state->i2c_write_buffer[1] = reg & 0xff; + +@@ -97,11 +106,20 @@ static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) + if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2) + dprintk("i2c read error on %d", reg); + +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + state->i2c_write_buffer[0] = (reg >> 8) & 0xff; + state->i2c_write_buffer[1] = reg & 0xff; + state->i2c_write_buffer[2] = (val >> 8) & 0xff; +@@ -113,7 +131,10 @@ static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) + state->msg[0].buf = state->i2c_write_buffer; + state->msg[0].len = 4; + +- return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; ++ ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? ++ -EREMOTEIO : 0); ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf) +@@ -1646,6 +1667,7 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau + return -ENOMEM; + + dpst->i2c_adap = i2c; ++ mutex_init(&dpst->i2c_buffer_lock); + + for (k = no_of_demods - 1; k >= 0; k--) { + dpst->cfg = cfg[k]; +@@ -2324,6 +2346,7 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, + demod = &st->demod; + demod->demodulator_priv = st; + memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops)); ++ mutex_init(&st->i2c_buffer_lock); + + dib7000p_write_word(st, 1287, 0x0003); /* sram lead in, rdy */ + +@@ -2333,8 +2356,9 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, + st->version = dib7000p_read_word(st, 897); + + /* FIXME: make sure the dev.parent field is initialized, or else +- request_firmware() will hit an OOPS (this should be moved somewhere +- more common) */ ++ request_firmware() will hit an OOPS (this should be moved somewhere ++ more common) */ ++ st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent; + + dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr); + +diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c +index 7d2ea11..fe284d5 100644 +--- a/drivers/media/dvb/frontends/dib8000.c ++++ b/drivers/media/dvb/frontends/dib8000.c +@@ -10,6 +10,8 @@ + #include + #include + #include ++#include ++ + #include "dvb_math.h" + + #include "dvb_frontend.h" +@@ -37,6 +39,7 @@ struct i2c_device { + u8 addr; + u8 *i2c_write_buffer; + u8 *i2c_read_buffer; ++ struct mutex *i2c_buffer_lock; + }; + + struct dib8000_state { +@@ -77,6 +80,7 @@ struct dib8000_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[4]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + enum dib8000_power_mode { +@@ -86,24 +90,39 @@ enum dib8000_power_mode { + + static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg) + { ++ u16 ret; + struct i2c_msg msg[2] = { +- {.addr = i2c->addr >> 1, .flags = 0, +- .buf = i2c->i2c_write_buffer, .len = 2}, +- {.addr = i2c->addr >> 1, .flags = I2C_M_RD, +- .buf = i2c->i2c_read_buffer, .len = 2}, ++ {.addr = i2c->addr >> 1, .flags = 0, .len = 2}, ++ {.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2}, + }; + ++ if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ ++ msg[0].buf = i2c->i2c_write_buffer; + msg[0].buf[0] = reg >> 8; + msg[0].buf[1] = reg & 0xff; ++ msg[1].buf = i2c->i2c_read_buffer; + + if (i2c_transfer(i2c->adap, msg, 2) != 2) + dprintk("i2c read error on %d", reg); + +- return (msg[1].buf[0] << 8) | msg[1].buf[1]; ++ ret = (msg[1].buf[0] << 8) | msg[1].buf[1]; ++ mutex_unlock(i2c->i2c_buffer_lock); ++ return ret; + } + + static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = reg >> 8; + state->i2c_write_buffer[1] = reg & 0xff; + +@@ -120,7 +139,10 @@ static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) + if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2) + dprintk("i2c read error on %d", reg); + +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ mutex_unlock(&state->i2c_buffer_lock); ++ ++ return ret; + } + + static u32 dib8000_read32(struct dib8000_state *state, u16 reg) +@@ -135,22 +157,35 @@ static u32 dib8000_read32(struct dib8000_state *state, u16 reg) + + static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val) + { +- struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, +- .buf = i2c->i2c_write_buffer, .len = 4}; ++ struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4}; + int ret = 0; + ++ if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ ++ msg.buf = i2c->i2c_write_buffer; + msg.buf[0] = (reg >> 8) & 0xff; + msg.buf[1] = reg & 0xff; + msg.buf[2] = (val >> 8) & 0xff; + msg.buf[3] = val & 0xff; + + ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0; ++ mutex_unlock(i2c->i2c_buffer_lock); + + return ret; + } + + static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + state->i2c_write_buffer[0] = (reg >> 8) & 0xff; + state->i2c_write_buffer[1] = reg & 0xff; + state->i2c_write_buffer[2] = (val >> 8) & 0xff; +@@ -162,7 +197,11 @@ static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) + state->msg[0].buf = state->i2c_write_buffer; + state->msg[0].len = 4; + +- return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; ++ ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? ++ -EREMOTEIO : 0); ++ mutex_unlock(&state->i2c_buffer_lock); ++ ++ return ret; + } + + static const s16 coeff_2k_sb_1seg_dqpsk[8] = { +@@ -2434,8 +2473,15 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau + if (!client.i2c_read_buffer) { + dprintk("%s: not enough memory", __func__); + ret = -ENOMEM; +- goto error_memory; ++ goto error_memory_read; ++ } ++ client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL); ++ if (!client.i2c_buffer_lock) { ++ dprintk("%s: not enough memory", __func__); ++ ret = -ENOMEM; ++ goto error_memory_lock; + } ++ mutex_init(client.i2c_buffer_lock); + + for (k = no_of_demods - 1; k >= 0; k--) { + /* designated i2c address */ +@@ -2476,8 +2522,10 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau + } + + error: ++ kfree(client.i2c_buffer_lock); ++error_memory_lock: + kfree(client.i2c_read_buffer); +-error_memory: ++error_memory_read: + kfree(client.i2c_write_buffer); + + return ret; +@@ -2581,6 +2629,8 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s + state->i2c.addr = i2c_addr; + state->i2c.i2c_write_buffer = state->i2c_write_buffer; + state->i2c.i2c_read_buffer = state->i2c_read_buffer; ++ mutex_init(&state->i2c_buffer_lock); ++ state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock; + state->gpio_val = cfg->gpio_val; + state->gpio_dir = cfg->gpio_dir; + +diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb/frontends/dib9000.c +index a085588..b931074 100644 +--- a/drivers/media/dvb/frontends/dib9000.c ++++ b/drivers/media/dvb/frontends/dib9000.c +@@ -38,6 +38,15 @@ struct i2c_device { + #define DibInitLock(lock) mutex_init(lock) + #define DibFreeLock(lock) + ++struct dib9000_pid_ctrl { ++#define DIB9000_PID_FILTER_CTRL 0 ++#define DIB9000_PID_FILTER 1 ++ u8 cmd; ++ u8 id; ++ u16 pid; ++ u8 onoff; ++}; ++ + struct dib9000_state { + struct i2c_device i2c; + +@@ -99,6 +108,10 @@ struct dib9000_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[255]; + u8 i2c_read_buffer[255]; ++ DIB_LOCK demod_lock; ++ u8 get_frontend_internal; ++ struct dib9000_pid_ctrl pid_ctrl[10]; ++ s8 pid_ctrl_index; /* -1: empty list; -2: do not use the list */ + }; + + static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +@@ -1743,19 +1756,56 @@ EXPORT_SYMBOL(dib9000_set_gpio); + int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) + { + struct dib9000_state *state = fe->demodulator_priv; +- u16 val = dib9000_read_word(state, 294 + 1) & 0xffef; ++ u16 val; ++ int ret; ++ ++ if ((state->pid_ctrl_index != -2) && (state->pid_ctrl_index < 9)) { ++ /* postpone the pid filtering cmd */ ++ dprintk("pid filter cmd postpone"); ++ state->pid_ctrl_index++; ++ state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER_CTRL; ++ state->pid_ctrl[state->pid_ctrl_index].onoff = onoff; ++ return 0; ++ } ++ ++ DibAcquireLock(&state->demod_lock); ++ ++ val = dib9000_read_word(state, 294 + 1) & 0xffef; + val |= (onoff & 0x1) << 4; + + dprintk("PID filter enabled %d", onoff); +- return dib9000_write_word(state, 294 + 1, val); ++ ret = dib9000_write_word(state, 294 + 1, val); ++ DibReleaseLock(&state->demod_lock); ++ return ret; ++ + } + EXPORT_SYMBOL(dib9000_fw_pid_filter_ctrl); + + int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) + { + struct dib9000_state *state = fe->demodulator_priv; ++ int ret; ++ ++ if (state->pid_ctrl_index != -2) { ++ /* postpone the pid filtering cmd */ ++ dprintk("pid filter postpone"); ++ if (state->pid_ctrl_index < 9) { ++ state->pid_ctrl_index++; ++ state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER; ++ state->pid_ctrl[state->pid_ctrl_index].id = id; ++ state->pid_ctrl[state->pid_ctrl_index].pid = pid; ++ state->pid_ctrl[state->pid_ctrl_index].onoff = onoff; ++ } else ++ dprintk("can not add any more pid ctrl cmd"); ++ return 0; ++ } ++ ++ DibAcquireLock(&state->demod_lock); + dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff); +- return dib9000_write_word(state, 300 + 1 + id, onoff ? (1 << 13) | pid : 0); ++ ret = dib9000_write_word(state, 300 + 1 + id, ++ onoff ? (1 << 13) | pid : 0); ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + EXPORT_SYMBOL(dib9000_fw_pid_filter); + +@@ -1778,6 +1828,7 @@ static void dib9000_release(struct dvb_frontend *demod) + DibFreeLock(&state->platform.risc.mbx_lock); + DibFreeLock(&state->platform.risc.mem_lock); + DibFreeLock(&state->platform.risc.mem_mbx_lock); ++ DibFreeLock(&state->demod_lock); + dibx000_exit_i2c_master(&st->i2c_master); + + i2c_del_adapter(&st->tuner_adap); +@@ -1795,14 +1846,19 @@ static int dib9000_sleep(struct dvb_frontend *fe) + { + struct dib9000_state *state = fe->demodulator_priv; + u8 index_frontend; +- int ret; ++ int ret = 0; + ++ DibAcquireLock(&state->demod_lock); + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { + ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]); + if (ret < 0) +- return ret; ++ goto error; + } +- return dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0); ++ ret = dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0); ++ ++error: ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + + static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune) +@@ -1816,7 +1872,10 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + struct dib9000_state *state = fe->demodulator_priv; + u8 index_frontend, sub_index_frontend; + fe_status_t stat; +- int ret; ++ int ret = 0; ++ ++ if (state->get_frontend_internal == 0) ++ DibAcquireLock(&state->demod_lock); + + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { + state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat); +@@ -1846,14 +1905,15 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + state->fe[index_frontend]->dtv_property_cache.rolloff; + } + } +- return 0; ++ ret = 0; ++ goto return_value; + } + } + + /* get the channel from master chip */ + ret = dib9000_fw_get_channel(fe, fep); + if (ret != 0) +- return ret; ++ goto return_value; + + /* synchronize the cache with the other frontends */ + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { +@@ -1866,8 +1926,12 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP; + state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff; + } ++ ret = 0; + +- return 0; ++return_value: ++ if (state->get_frontend_internal == 0) ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + + static int dib9000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) +@@ -1912,6 +1976,10 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + dprintk("dib9000: must specify bandwidth "); + return 0; + } ++ ++ state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */ ++ DibAcquireLock(&state->demod_lock); ++ + fe->dtv_property_cache.delivery_system = SYS_DVBT; + + /* set the master status */ +@@ -1974,13 +2042,18 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + /* check the tune result */ + if (exit_condition == 1) { /* tune failed */ + dprintk("tune failed"); ++ DibReleaseLock(&state->demod_lock); ++ /* tune failed; put all the pid filtering cmd to junk */ ++ state->pid_ctrl_index = -1; + return 0; + } + + dprintk("tune success on frontend%i", index_frontend_success); + + /* synchronize all the channel cache */ ++ state->get_frontend_internal = 1; + dib9000_get_frontend(state->fe[0], fep); ++ state->get_frontend_internal = 0; + + /* retune the other frontends with the found channel */ + channel_status.status = CHANNEL_STATUS_PARAMETERS_SET; +@@ -2025,6 +2098,28 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + /* turn off the diversity for the last frontend */ + dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0); + ++ DibReleaseLock(&state->demod_lock); ++ if (state->pid_ctrl_index >= 0) { ++ u8 index_pid_filter_cmd; ++ u8 pid_ctrl_index = state->pid_ctrl_index; ++ ++ state->pid_ctrl_index = -2; ++ for (index_pid_filter_cmd = 0; ++ index_pid_filter_cmd <= pid_ctrl_index; ++ index_pid_filter_cmd++) { ++ if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER_CTRL) ++ dib9000_fw_pid_filter_ctrl(state->fe[0], ++ state->pid_ctrl[index_pid_filter_cmd].onoff); ++ else if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER) ++ dib9000_fw_pid_filter(state->fe[0], ++ state->pid_ctrl[index_pid_filter_cmd].id, ++ state->pid_ctrl[index_pid_filter_cmd].pid, ++ state->pid_ctrl[index_pid_filter_cmd].onoff); ++ } ++ } ++ /* do not postpone any more the pid filtering */ ++ state->pid_ctrl_index = -2; ++ + return 0; + } + +@@ -2041,6 +2136,7 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat) + u8 index_frontend; + u16 lock = 0, lock_slave = 0; + ++ DibAcquireLock(&state->demod_lock); + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) + lock_slave |= dib9000_read_lock(state->fe[index_frontend]); + +@@ -2059,6 +2155,8 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat) + if ((lock & 0x0008) || (lock_slave & 0x0008)) + *stat |= FE_HAS_LOCK; + ++ DibReleaseLock(&state->demod_lock); ++ + return 0; + } + +@@ -2066,10 +2164,14 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber) + { + struct dib9000_state *state = fe->demodulator_priv; + u16 *c; ++ int ret = 0; + ++ DibAcquireLock(&state->demod_lock); + DibAcquireLock(&state->platform.risc.mem_mbx_lock); +- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) +- return -EIO; ++ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { ++ ret = -EIO; ++ goto error; ++ } + dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, + state->i2c_read_buffer, 16 * 2); + DibReleaseLock(&state->platform.risc.mem_mbx_lock); +@@ -2077,7 +2179,10 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber) + c = (u16 *)state->i2c_read_buffer; + + *ber = c[10] << 16 | c[11]; +- return 0; ++ ++error: ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + + static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) +@@ -2086,7 +2191,9 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) + u8 index_frontend; + u16 *c = (u16 *)state->i2c_read_buffer; + u16 val; ++ int ret = 0; + ++ DibAcquireLock(&state->demod_lock); + *strength = 0; + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { + state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val); +@@ -2097,8 +2204,10 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) + } + + DibAcquireLock(&state->platform.risc.mem_mbx_lock); +- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) +- return -EIO; ++ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { ++ ret = -EIO; ++ goto error; ++ } + dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); + DibReleaseLock(&state->platform.risc.mem_mbx_lock); + +@@ -2107,7 +2216,10 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) + *strength = 65535; + else + *strength += val; +- return 0; ++ ++error: ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + + static u32 dib9000_get_snr(struct dvb_frontend *fe) +@@ -2151,6 +2263,7 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr) + u8 index_frontend; + u32 snr_master; + ++ DibAcquireLock(&state->demod_lock); + snr_master = dib9000_get_snr(fe); + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) + snr_master += dib9000_get_snr(state->fe[index_frontend]); +@@ -2161,6 +2274,8 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr) + } else + *snr = 0; + ++ DibReleaseLock(&state->demod_lock); ++ + return 0; + } + +@@ -2168,15 +2283,22 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) + { + struct dib9000_state *state = fe->demodulator_priv; + u16 *c = (u16 *)state->i2c_read_buffer; ++ int ret = 0; + ++ DibAcquireLock(&state->demod_lock); + DibAcquireLock(&state->platform.risc.mem_mbx_lock); +- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) +- return -EIO; ++ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { ++ ret = -EIO; ++ goto error; ++ } + dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); + DibReleaseLock(&state->platform.risc.mem_mbx_lock); + + *unc = c[12]; +- return 0; ++ ++error: ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + + int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr) +@@ -2322,6 +2444,10 @@ struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, c + DibInitLock(&st->platform.risc.mbx_lock); + DibInitLock(&st->platform.risc.mem_lock); + DibInitLock(&st->platform.risc.mem_mbx_lock); ++ DibInitLock(&st->demod_lock); ++ st->get_frontend_internal = 0; ++ ++ st->pid_ctrl_index = -2; + + st->fe[0] = fe; + fe->demodulator_priv = st; +diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c +index dc5d17a..774d507 100644 +--- a/drivers/media/dvb/frontends/dibx000_common.c ++++ b/drivers/media/dvb/frontends/dibx000_common.c +@@ -1,4 +1,5 @@ + #include ++#include + + #include "dibx000_common.h" + +@@ -10,6 +11,13 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); + + static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + mst->i2c_write_buffer[0] = (reg >> 8) & 0xff; + mst->i2c_write_buffer[1] = reg & 0xff; + mst->i2c_write_buffer[2] = (val >> 8) & 0xff; +@@ -21,11 +29,21 @@ static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) + mst->msg[0].buf = mst->i2c_write_buffer; + mst->msg[0].len = 4; + +- return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0; ++ ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0; ++ mutex_unlock(&mst->i2c_buffer_lock); ++ ++ return ret; + } + + static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + mst->i2c_write_buffer[0] = reg >> 8; + mst->i2c_write_buffer[1] = reg & 0xff; + +@@ -42,7 +60,10 @@ static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg) + if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2) + dprintk("i2c read error on %d", reg); + +- return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1]; ++ ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1]; ++ mutex_unlock(&mst->i2c_buffer_lock); ++ ++ return ret; + } + + static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst) +@@ -257,6 +278,7 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msg[], int num) + { + struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); ++ int ret; + + if (num > 32) { + dprintk("%s: too much I2C message to be transmitted (%i).\ +@@ -264,10 +286,15 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, + return -ENOMEM; + } + +- memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); +- + dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7); + ++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ ++ memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); ++ + /* open the gate */ + dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); + mst->msg[0].addr = mst->i2c_addr; +@@ -282,7 +309,11 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, + mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; + mst->msg[num + 1].len = 4; + +- return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO; ++ ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? ++ num : -EIO); ++ ++ mutex_unlock(&mst->i2c_buffer_lock); ++ return ret; + } + + static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = { +@@ -294,6 +325,7 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msg[], int num) + { + struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); ++ int ret; + + if (num > 32) { + dprintk("%s: too much I2C message to be transmitted (%i).\ +@@ -301,10 +333,14 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, + return -ENOMEM; + } + +- memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); +- + dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); + ++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); ++ + /* open the gate */ + dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); + mst->msg[0].addr = mst->i2c_addr; +@@ -319,7 +355,10 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, + mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; + mst->msg[num + 1].len = 4; + +- return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO; ++ ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? ++ num : -EIO); ++ mutex_unlock(&mst->i2c_buffer_lock); ++ return ret; + } + + static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = { +@@ -390,8 +429,18 @@ static int i2c_adapter_init(struct i2c_adapter *i2c_adap, + int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, + struct i2c_adapter *i2c_adap, u8 i2c_addr) + { +- u8 tx[4]; +- struct i2c_msg m = {.addr = i2c_addr >> 1,.buf = tx,.len = 4 }; ++ int ret; ++ ++ mutex_init(&mst->i2c_buffer_lock); ++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ memset(mst->msg, 0, sizeof(struct i2c_msg)); ++ mst->msg[0].addr = i2c_addr >> 1; ++ mst->msg[0].flags = 0; ++ mst->msg[0].buf = mst->i2c_write_buffer; ++ mst->msg[0].len = 4; + + mst->device_rev = device_rev; + mst->i2c_adap = i2c_adap; +@@ -431,9 +480,12 @@ int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, + "DiBX000: could not initialize the master i2c_adapter\n"); + + /* initialize the i2c-master by closing the gate */ +- dibx000_i2c_gate_ctrl(mst, tx, 0, 0); ++ dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0); ++ ++ ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1); ++ mutex_unlock(&mst->i2c_buffer_lock); + +- return i2c_transfer(i2c_adap, &m, 1) == 1; ++ return ret; + } + + EXPORT_SYMBOL(dibx000_init_i2c_master); +diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h +index f031165..5e01147 100644 +--- a/drivers/media/dvb/frontends/dibx000_common.h ++++ b/drivers/media/dvb/frontends/dibx000_common.h +@@ -33,6 +33,7 @@ struct dibx000_i2c_master { + struct i2c_msg msg[34]; + u8 i2c_write_buffer[8]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, +-- +1.7.6.4 + diff --git a/media-dib0700-correct-error-message.patch b/media-dib0700-correct-error-message.patch new file mode 100644 index 000000000..f40a4fa12 --- /dev/null +++ b/media-dib0700-correct-error-message.patch @@ -0,0 +1,105 @@ +From e4f0158142e4b23939d9444d8af80ff20692f7a5 Mon Sep 17 00:00:00 2001 +From: Olivier Grenie +Date: Thu, 4 Aug 2011 16:10:03 -0300 +Subject: [PATCH 3/3] [media] dib0700: correct error message + +The goal of this patch is to correct a previous patch. In case of error, +the err() function should be used instead of dprintk() function. + +[mchehab@redhat.com: as I've replaced dprintk by deb_info, on the the + previous patch, to avoid breaking bisect, I had to fix a merge conflict + on this one] +Signed-off-by: Olivier Grenie +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/dvb/dvb-usb/dib0700_core.c | 18 +++++++++--------- + 1 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c +index a224e94..b693ed1 100644 +--- a/drivers/media/dvb/dvb-usb/dib0700_core.c ++++ b/drivers/media/dvb/dvb-usb/dib0700_core.c +@@ -31,7 +31,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, + int ret; + + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -117,7 +117,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ + int ret; + + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -138,7 +138,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) + + if (st->fw_version >= 0x10201) { + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -227,7 +227,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, + } else { + /* Write request */ + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + st->buf[0] = REQUEST_NEW_I2C_WRITE; +@@ -273,7 +273,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -368,7 +368,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, + int ret; + + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -400,7 +400,7 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) + return -EINVAL; + + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -560,7 +560,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) + } + + if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -610,7 +610,7 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) + int new_proto, ret; + + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +-- +1.7.6.4 + diff --git a/media-dib0700-protect-the-dib0700-buffer-access.patch b/media-dib0700-protect-the-dib0700-buffer-access.patch new file mode 100644 index 000000000..e63f58c75 --- /dev/null +++ b/media-dib0700-protect-the-dib0700-buffer-access.patch @@ -0,0 +1,250 @@ +From 9e3419029b4c660298928a6f03002daae6c055a6 Mon Sep 17 00:00:00 2001 +From: Olivier Grenie +Date: Mon, 1 Aug 2011 15:45:58 -0300 +Subject: [PATCH 2/3] [media] dib0700: protect the dib0700 buffer access + +This patch protects the common buffer access inside the dib0700 in order +to manage concurrent access. This protection is done using mutex. + +Cc: Mauro Carvalho Chehab +Cc: Florian Mickler +Cc: stable@kernel.org +Signed-off-by: Javier Marcet +Signed-off-by: Olivier Grenie +Signed-off-by: Patrick Boettcher +[mchehab@redhat.com: dprint requires 3 arguments. Replaced by dib_info] +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/dvb/dvb-usb/dib0700_core.c | 81 ++++++++++++++++++++++++++--- + 1 files changed, 72 insertions(+), 9 deletions(-) + +diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c +index 5eb91b4..a224e94 100644 +--- a/drivers/media/dvb/dvb-usb/dib0700_core.c ++++ b/drivers/media/dvb/dvb-usb/dib0700_core.c +@@ -30,6 +30,11 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, + struct dib0700_state *st = d->priv; + int ret; + ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } ++ + ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), + REQUEST_GET_VERSION, + USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, +@@ -46,6 +51,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, + if (fwtype != NULL) + *fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) | + (st->buf[14] << 8) | st->buf[15]; ++ mutex_unlock(&d->usb_mutex); + return ret; + } + +@@ -108,7 +114,12 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen + int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val) + { + struct dib0700_state *st = d->priv; +- s16 ret; ++ int ret; ++ ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } + + st->buf[0] = REQUEST_SET_GPIO; + st->buf[1] = gpio; +@@ -116,6 +127,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ + + ret = dib0700_ctrl_wr(d, st->buf, 3); + ++ mutex_unlock(&d->usb_mutex); + return ret; + } + +@@ -125,6 +137,11 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) + int ret; + + if (st->fw_version >= 0x10201) { ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } ++ + st->buf[0] = REQUEST_SET_USB_XFER_LEN; + st->buf[1] = (nb_ts_packets >> 8) & 0xff; + st->buf[2] = nb_ts_packets & 0xff; +@@ -132,6 +149,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) + deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets); + + ret = dib0700_ctrl_wr(d, st->buf, 3); ++ mutex_unlock(&d->usb_mutex); + } else { + deb_info("this firmware does not allow to change the USB xfer len\n"); + ret = -EIO; +@@ -208,6 +226,10 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, + + } else { + /* Write request */ ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } + st->buf[0] = REQUEST_NEW_I2C_WRITE; + st->buf[1] = msg[i].addr << 1; + st->buf[2] = (en_start << 7) | (en_stop << 6) | +@@ -227,6 +249,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, + USB_TYPE_VENDOR | USB_DIR_OUT, + 0, 0, st->buf, msg[i].len + 4, + USB_CTRL_GET_TIMEOUT); ++ mutex_unlock(&d->usb_mutex); + if (result < 0) { + deb_info("i2c write error (status = %d)\n", result); + break; +@@ -249,6 +272,10 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } + + for (i = 0; i < num; i++) { + /* fill in the address */ +@@ -279,6 +306,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, + break; + } + } ++ mutex_unlock(&d->usb_mutex); + mutex_unlock(&d->i2c_mutex); + + return i; +@@ -337,7 +365,12 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, + u16 pll_loopdiv, u16 free_div, u16 dsuScaler) + { + struct dib0700_state *st = d->priv; +- s16 ret; ++ int ret; ++ ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } + + st->buf[0] = REQUEST_SET_CLOCK; + st->buf[1] = (en_pll << 7) | (pll_src << 6) | +@@ -352,6 +385,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, + st->buf[9] = dsuScaler & 0xff; /* LSB */ + + ret = dib0700_ctrl_wr(d, st->buf, 10); ++ mutex_unlock(&d->usb_mutex); + + return ret; + } +@@ -360,10 +394,16 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) + { + struct dib0700_state *st = d->priv; + u16 divider; ++ int ret; + + if (scl_kHz == 0) + return -EINVAL; + ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } ++ + st->buf[0] = REQUEST_SET_I2C_PARAM; + divider = (u16) (30000 / scl_kHz); + st->buf[1] = 0; +@@ -379,7 +419,11 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) + deb_info("setting I2C speed: %04x %04x %04x (%d kHz).", + (st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) | + st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz); +- return dib0700_ctrl_wr(d, st->buf, 8); ++ ++ ret = dib0700_ctrl_wr(d, st->buf, 8); ++ mutex_unlock(&d->usb_mutex); ++ ++ return ret; + } + + +@@ -515,6 +559,11 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) + } + } + ++ if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } ++ + st->buf[0] = REQUEST_ENABLE_VIDEO; + /* this bit gives a kind of command, + * rather than enabling something or not */ +@@ -548,7 +597,10 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) + + deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]); + +- return dib0700_ctrl_wr(adap->dev, st->buf, 4); ++ ret = dib0700_ctrl_wr(adap->dev, st->buf, 4); ++ mutex_unlock(&adap->dev->usb_mutex); ++ ++ return ret; + } + + int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) +@@ -557,6 +609,11 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) + struct dib0700_state *st = d->priv; + int new_proto, ret; + ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } ++ + st->buf[0] = REQUEST_SET_RC; + st->buf[1] = 0; + st->buf[2] = 0; +@@ -567,23 +624,29 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) + else if (rc_type == RC_TYPE_NEC) + new_proto = 0; + else if (rc_type == RC_TYPE_RC6) { +- if (st->fw_version < 0x10200) +- return -EINVAL; ++ if (st->fw_version < 0x10200) { ++ ret = -EINVAL; ++ goto out; ++ } + + new_proto = 2; +- } else +- return -EINVAL; ++ } else { ++ ret = -EINVAL; ++ goto out; ++ } + + st->buf[1] = new_proto; + + ret = dib0700_ctrl_wr(d, st->buf, 3); + if (ret < 0) { + err("ir protocol setup failed"); +- return ret; ++ goto out; + } + + d->props.rc.core.protocol = rc_type; + ++out: ++ mutex_unlock(&d->usb_mutex); + return ret; + } + +-- +1.7.6.4 + From 7eb4ded0217ce9ac297a93365d14d90d7fa82f54 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 24 Oct 2011 09:18:41 -0400 Subject: [PATCH 187/397] Add version number to changelog --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 0838191bd..391035661 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1929,7 +1929,7 @@ fi # and build. %changelog -* Mon Oct 24 2011 Josh Boyer +* Mon Oct 24 2011 Josh Boyer 2.6.40.7-3 - Backport 3 fixed from linux-next to fix dib0700 playback (rhbz 733827) * Fri Oct 21 2011 Dave Jones From a38747fb2ee092b52fb45deb31c7623adfa75344 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 24 Oct 2011 15:35:03 -0400 Subject: [PATCH 188/397] sync linux-2.6-debug-taint-vm.patch with f16 print modules when in bad_page() --- kernel.spec | 3 +++ linux-2.6-debug-taint-vm.patch | 46 ++++++++++++---------------------- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/kernel.spec b/kernel.spec index 391035661..48efc6aaa 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1929,6 +1929,9 @@ fi # and build. %changelog +* Mon Oct 24 2011 Dave Jones +- Print modules list from bad_page() + * Mon Oct 24 2011 Josh Boyer 2.6.40.7-3 - Backport 3 fixed from linux-next to fix dib0700 playback (rhbz 733827) diff --git a/linux-2.6-debug-taint-vm.patch b/linux-2.6-debug-taint-vm.patch index ee367d45a..672509db2 100644 --- a/linux-2.6-debug-taint-vm.patch +++ b/linux-2.6-debug-taint-vm.patch @@ -1,31 +1,20 @@ -From b04c57d9dc889462951312be2ac81ff6c702e954 Mon Sep 17 00:00:00 2001 -From: Kyle McMartin -Date: Wed, 8 Jul 2009 13:05:09 -0400 -Subject: [PATCH 3/6] fedora: linux-2.6-debug-taint-vm.patch - ---- - kernel/panic.c | 4 +++- - mm/slab.c | 8 ++++---- - mm/slub.c | 2 +- - 4 files changed, 11 insertions(+), 8 deletions(-) - -diff --git a/kernel/panic.c b/kernel/panic.c -index 984b3ec..6d1c3be 100644 ---- a/kernel/panic.c -+++ b/kernel/panic.c -@@ -199,6 +199,7 @@ const char *print_tainted(void) +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 4e8985a..70d0853 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -318,6 +318,7 @@ static void bad_page(struct page *page) + current->comm, page_to_pfn(page)); + dump_page(page); - return buf; - } -+EXPORT_SYMBOL(print_tainted); - - int test_taint(unsigned flag) - { ++ print_modules(); + dump_stack(); + out: + /* Leave bad fields for debug, except PageBuddy could make trouble */ diff --git a/mm/slab.c b/mm/slab.c -index e74a16e..7bc287e 100644 +index d96e223..6f8905b 100644 --- a/mm/slab.c +++ b/mm/slab.c -@@ -1803,8 +1803,8 @@ static void check_poison_obj(struct kmem_cache *cachep, void *objp) +@@ -1886,8 +1886,8 @@ static void check_poison_obj(struct kmem_cache *cachep, void *objp) /* Print header */ if (lines == 0) { printk(KERN_ERR @@ -36,7 +25,7 @@ index e74a16e..7bc287e 100644 print_objinfo(cachep, objp, 0); } /* Hexdump the affected line */ -@@ -2902,8 +2902,8 @@ static void check_slabp(struct kmem_cache *cachep, struct slab *slabp) +@@ -2985,8 +2985,8 @@ static void check_slabp(struct kmem_cache *cachep, struct slab *slabp) if (entries != cachep->num - slabp->inuse) { bad: printk(KERN_ERR "slab: Internal list corruption detected in " @@ -48,10 +37,10 @@ index e74a16e..7bc287e 100644 i < sizeof(*slabp) + cachep->num * sizeof(kmem_bufctl_t); i++) { diff --git a/mm/slub.c b/mm/slub.c -index 819f056..8eff0f4 100644 +index 35f351f..e7ccb39 100644 --- a/mm/slub.c +++ b/mm/slub.c -@@ -433,7 +433,7 @@ static void slab_bug(struct kmem_cache *s, char *fmt, ...) +@@ -472,7 +472,7 @@ static void slab_bug(struct kmem_cache *s, char *fmt, ...) va_end(args); printk(KERN_ERR "========================================" "=====================================\n"); @@ -60,6 +49,3 @@ index 819f056..8eff0f4 100644 printk(KERN_ERR "----------------------------------------" "-------------------------------------\n\n"); } --- -1.6.2.5 - From 5d467e53f1ec1ebb822dcc62583b82524745b187 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 24 Oct 2011 22:40:46 -0400 Subject: [PATCH 189/397] Add patch from LKML to fix Samsung notebook brightness flicker (rhbz 737108) --- kernel.spec | 9 +++ ...sung-brightness-min-max-calculations.patch | 56 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 platform-fix-samsung-brightness-min-max-calculations.patch diff --git a/kernel.spec b/kernel.spec index 48efc6aaa..589acc35b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -720,6 +720,9 @@ Patch21019: fuse-fix-memory-leak.patch Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch +#rhbz 737108 +Patch21030: platform-fix-samsung-brightness-min-max-calculations.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1309,6 +1312,9 @@ ApplyPatch fuse-fix-memory-leak.patch ApplyPatch 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch +#rhbz 737108 +ApplyPatch platform-fix-samsung-brightness-min-max-calculations.patch + # END OF PATCH APPLICATIONS %endif @@ -1929,6 +1935,9 @@ fi # and build. %changelog +* Mon Oct 24 2011 Chuck Ebbert +- Add patch from LKML to fix Samsung notebook brightness flicker (rhbz 737108) + * Mon Oct 24 2011 Dave Jones - Print modules list from bad_page() diff --git a/platform-fix-samsung-brightness-min-max-calculations.patch b/platform-fix-samsung-brightness-min-max-calculations.patch new file mode 100644 index 000000000..6a2c3b8cc --- /dev/null +++ b/platform-fix-samsung-brightness-min-max-calculations.patch @@ -0,0 +1,56 @@ +From: Jason Stubbs +Subject: [PATCH] platform: fix samsung brightness min/max calculations + +For one of the SABI configs, the valid brightness levels are 1 through 8 with +0 being reserved for the BIOS. To make the range 0-based, the driver is meant +to offset values to/from userspace by 1 giving valid levels of 0 through 7. + +Currently, the driver is reporting a max brightness of 8 and doing the offset +the wrong way such that setting a brightness of 8 will set as 7 in hardware +while setting a brightness of 0 will attempt (and fail) to set as -1 in +hardware. + +This patch fixes these calculations as well as a potential miscalculation due +to an assumption of min_brightness being either 0 or 1. + +Signed-off-by: Jason Stubbs +Signed-off-by: Chuck Ebbert + +--- +Originally posted here, context fixed to apply to 3.0/3.1: +[ https://lkml.org/lkml/2011/5/11/548 ] + +diff a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c +--- a/drivers/platform/x86/samsung-laptop.c ++++ b/drivers/platform/x86/samsung-laptop.c +@@ -370,15 +370,17 @@ static u8 read_brightness(void) + &sretval); + if (!retval) { + user_brightness = sretval.retval[0]; +- if (user_brightness != 0) ++ if (user_brightness > sabi_config->min_brightness) + user_brightness -= sabi_config->min_brightness; ++ else ++ user_brightness = 0; + } + return user_brightness; + } + + static void set_brightness(u8 user_brightness) + { +- u8 user_level = user_brightness - sabi_config->min_brightness; ++ u8 user_level = user_brightness + sabi_config->min_brightness; + + sabi_set_command(sabi_config->commands.set_brightness, user_level); + } +@@ -802,7 +804,8 @@ static int __init samsung_init(void) + /* create a backlight device to talk to this one */ + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; +- props.max_brightness = sabi_config->max_brightness; ++ props.max_brightness = sabi_config->max_brightness - ++ sabi_config->min_brightness; + backlight_device = backlight_device_register("samsung", &sdev->dev, + NULL, &backlight_ops, + &props); +_ From 1c1043840bc1f9d6d93381fd21c8ec4009f12b7e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 25 Oct 2011 11:31:15 -0400 Subject: [PATCH 190/397] Update to the Linux 3.0.8 stable release --- ...ERR_PTR-dereference-in-cifs_get_root.patch | 120 ------- cputimer-Cure-lock-inversion.patch | 148 -------- drm-ttm-nouveau-oops-fix.patch | 40 --- fuse-fix-memory-leak.patch | 70 ---- ...io-requests-are-not-smaller-than-the.patch | 315 ------------------ ...d-report-id-while-switching-modes-v2.patch | 62 ---- kernel.spec | 39 +-- sources | 2 +- ucvideo-fix-crash-when-linking-entities.patch | 34 -- 9 files changed, 6 insertions(+), 824 deletions(-) delete mode 100644 cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch delete mode 100644 cputimer-Cure-lock-inversion.patch delete mode 100644 drm-ttm-nouveau-oops-fix.patch delete mode 100644 fuse-fix-memory-leak.patch delete mode 100644 hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch delete mode 100644 hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patch delete mode 100644 ucvideo-fix-crash-when-linking-entities.patch diff --git a/cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch b/cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch deleted file mode 100644 index f15a0e952..000000000 --- a/cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch +++ /dev/null @@ -1,120 +0,0 @@ -Return-Path: kernel-bounces@lists.fedoraproject.org -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail02.corp.redhat.com with LMTP; Thu, 25 Aug 2011 10:45:29 -0400 (EDT) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D94C212A429; - Thu, 25 Aug 2011 10:40:08 -0400 (EDT) -X-Quarantine-ID: -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id C-k2lztK9Aht; Thu, 25 Aug 2011 10:40:08 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 99EEE12A424; - Thu, 25 Aug 2011 10:40:08 -0400 (EDT) -Received: from mx1.redhat.com (ext-mx12.extmail.prod.ext.phx2.redhat.com [10.5.110.17]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p7PEe7jY023291; - Thu, 25 Aug 2011 10:40:08 -0400 -Received: from bastion.fedoraproject.org (bastion02.phx2.fedoraproject.org [10.5.126.11]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p7PEe54S022197; - Thu, 25 Aug 2011 10:40:05 -0400 -Received: from lists.fedoraproject.org (collab1.vpn.fedoraproject.org [192.168.1.21]) - by bastion02.phx2.fedoraproject.org (Postfix) with ESMTP id E3F1D1108EB; - Thu, 25 Aug 2011 14:40:04 +0000 (UTC) -Received: from collab1.fedoraproject.org (localhost.localdomain [127.0.0.1]) - by lists.fedoraproject.org (Postfix) with ESMTP id 52AA23267A7; - Thu, 25 Aug 2011 14:40:04 +0000 (UTC) -X-Original-To: kernel@lists.fedoraproject.org -Delivered-To: kernel@lists.fedoraproject.org -Received: from smtp-mm02.fedoraproject.org (smtp-mm02.fedoraproject.org - [66.35.62.164]) - by lists.fedoraproject.org (Postfix) with ESMTP id 8FD8232679C - for ; - Thu, 25 Aug 2011 14:40:01 +0000 (UTC) -Received: from mail-gx0-f173.google.com (mail-gx0-f173.google.com - [209.85.161.173]) - by smtp-mm02.fedoraproject.org (Postfix) with ESMTP id 42F73E721F - for ; - Thu, 25 Aug 2011 14:40:01 +0000 (UTC) -Received: by gxk26 with SMTP id 26so2067938gxk.32 - for ; - Thu, 25 Aug 2011 07:40:00 -0700 (PDT) -Received: by 10.91.21.4 with SMTP id y4mr6531700agi.115.1314283200592; - Thu, 25 Aug 2011 07:40:00 -0700 (PDT) -Received: from salusa.poochiereds.net (cpe-075-177-182-191.nc.res.rr.com - [75.177.182.191]) - by mx.google.com with ESMTPS id l13sm579931anj.16.2011.08.25.07.39.59 - (version=SSLv3 cipher=OTHER); Thu, 25 Aug 2011 07:40:00 -0700 (PDT) -From: Jeff Layton -To: kernel@lists.fedoraproject.org -Subject: [PATCH 2/2] CIFS: Fix ERR_PTR dereference in cifs_get_root -Date: Thu, 25 Aug 2011 10:39:54 -0400 -Message-Id: <1314283194-26086-3-git-send-email-jlayton@redhat.com> -In-Reply-To: <1314283194-26086-1-git-send-email-jlayton@redhat.com> -References: <1314283194-26086-1-git-send-email-jlayton@redhat.com> -X-BeenThere: kernel@lists.fedoraproject.org -X-Mailman-Version: 2.1.9 -Precedence: list -List-Id: "Fedora kernel development." -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: kernel-bounces@lists.fedoraproject.org -Errors-To: kernel-bounces@lists.fedoraproject.org -X-RedHat-Spam-Score: -0.502 (RP_MATCHES_RCVD) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -X-Scanned-By: MIMEDefang 2.68 on 10.5.110.17 - -From: Pavel Shilovsky - -move it to the beginning of the loop. - -Cc: -Signed-off-by: Pavel Shilovsky -Reviewed-by: Jeff Layton ---- - fs/cifs/cifsfs.c | 10 ++++++---- - 1 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c -index fc7e57b..53e7d72 100644 ---- a/fs/cifs/cifsfs.c -+++ b/fs/cifs/cifsfs.c -@@ -566,6 +566,12 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) - struct inode *dir = dentry->d_inode; - struct dentry *child; - -+ if (!dir) { -+ dput(dentry); -+ dentry = ERR_PTR(-ENOENT); -+ break; -+ } -+ - /* skip separators */ - while (*s == sep) - s++; -@@ -581,10 +587,6 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) - mutex_unlock(&dir->i_mutex); - dput(dentry); - dentry = child; -- if (!dentry->d_inode) { -- dput(dentry); -- dentry = ERR_PTR(-ENOENT); -- } - } while (!IS_ERR(dentry)); - _FreeXid(xid); - kfree(full_path); --- -1.7.6 - -_______________________________________________ -kernel mailing list -kernel@lists.fedoraproject.org -https://admin.fedoraproject.org/mailman/listinfo/kernel diff --git a/cputimer-Cure-lock-inversion.patch b/cputimer-Cure-lock-inversion.patch deleted file mode 100644 index 23759ad8b..000000000 --- a/cputimer-Cure-lock-inversion.patch +++ /dev/null @@ -1,148 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Peter Zijlstra -Newsgroups: gmane.linux.kernel -Subject: Re: Linux 3.1-rc9 -Date: Tue, 18 Oct 2011 11:05:13 +0200 -Lines: 84 -Approved: news@gmane.org -Message-ID: <1318928713.21167.4.camel@twins> -References: - <20111007070842.GA27555@hostway.ca> <20111007174848.GA11011@hostway.ca> - <1318010515.398.8.camel@twins> <20111008005035.GC22843@hostway.ca> - <1318060551.8395.0.camel@twins> <20111012213555.GC24461@hostway.ca> - <20111013232521.GA5654@hostway.ca> - - <1318847658.6594.40.camel@twins> - - <1318874090.4172.84.camel@twins> - - <1318879396.4172.92.camel@twins> - -NNTP-Posting-Host: lo.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset="UTF-8" -Content-Transfer-Encoding: 8BIT -X-Trace: dough.gmane.org 1318928749 2484 80.91.229.12 (18 Oct 2011 09:05:49 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Tue, 18 Oct 2011 09:05:49 +0000 (UTC) -Cc: Linus Torvalds , - Simon Kirby , - Linux Kernel Mailing List , - Dave Jones , - Martin Schwidefsky , - Ingo Molnar -To: Thomas Gleixner -Original-X-From: linux-kernel-owner@vger.kernel.org Tue Oct 18 11:05:43 2011 -Return-path: -Envelope-to: glk-linux-kernel-3@lo.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1RG5cB-0003K9-2n - for glk-linux-kernel-3@lo.gmane.org; Tue, 18 Oct 2011 11:05:39 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1757183Ab1JRJFc (ORCPT ); - Tue, 18 Oct 2011 05:05:32 -0400 -Original-Received: from casper.infradead.org ([85.118.1.10]:40399 "EHLO - casper.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1753880Ab1JRJFa convert rfc822-to-8bit (ORCPT - ); - Tue, 18 Oct 2011 05:05:30 -0400 -Original-Received: from j77219.upc-j.chello.nl ([24.132.77.219] helo=twins) - by casper.infradead.org with esmtpsa (Exim 4.76 #1 (Red Hat Linux)) - id 1RG5bu-0008Qu-O5; Tue, 18 Oct 2011 09:05:22 +0000 -Original-Received: by twins (Postfix, from userid 1000) - id 69952813C82C; Tue, 18 Oct 2011 11:05:13 +0200 (CEST) -In-Reply-To: -X-Mailer: Evolution 3.0.3- -Original-Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel:1204676 -Archived-At: - -On Tue, 2011-10-18 at 10:39 +0200, Thomas Gleixner wrote: -> On Mon, 17 Oct 2011, Thomas Gleixner wrote: -> > That said, I really need some sleep before I can make a final -> > judgement on that horror. The call paths are such an intermingled mess -> > that it's not funny anymore. I do that tomorrow morning first thing. -> -> The patch is safe and the exit race just existed in my confused tired -> brain. Peter, can you please provide a changelog. That wants a cc -> stable as well, because that deadlock causing commit hit 3.0.7 :( - ---- -Subject: cputimer: Cure lock inversion -From: Peter Zijlstra -Date: Mon Oct 17 11:50:30 CEST 2011 - -There's a lock inversion between the cputimer->lock and rq->lock; notably -the two callchains involved are: - - update_rlimit_cpu() - sighand->siglock - set_process_cpu_timer() - cpu_timer_sample_group() - thread_group_cputimer() - cputimer->lock - thread_group_cputime() - task_sched_runtime() - ->pi_lock - rq->lock - - scheduler_tick() - rq->lock - task_tick_fair() - update_curr() - account_group_exec() - cputimer->lock - -Where the first one is enabling a CLOCK_PROCESS_CPUTIME_ID timer, and -the second one is keeping up-to-date. - -This problem was introduced by e8abccb7193 ("posix-cpu-timers: Cure -SMP accounting oddities"). - -Cure the problem by removing the cputimer->lock and rq->lock nesting, -this leaves concurrent enablers doing duplicate work, but the time -wasted should be on the same order otherwise wasted spinning on the -lock and the greater-than assignment filter should ensure we preserve -monotonicity. - -Reported-by: Dave Jones -Reported-by: Simon Kirby -Cc: stable@kernel.org -Cc: Thomas Gleixner -Signed-off-by: Peter Zijlstra ---- - kernel/posix-cpu-timers.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) -Index: linux-2.6/kernel/posix-cpu-timers.c -=================================================================== ---- linux-2.6.orig/kernel/posix-cpu-timers.c -+++ linux-2.6/kernel/posix-cpu-timers.c -@@ -274,9 +274,7 @@ void thread_group_cputimer(struct task_s - struct task_cputime sum; - unsigned long flags; - -- spin_lock_irqsave(&cputimer->lock, flags); - if (!cputimer->running) { -- cputimer->running = 1; - /* - * The POSIX timer interface allows for absolute time expiry - * values through the TIMER_ABSTIME flag, therefore we have -@@ -284,8 +282,11 @@ void thread_group_cputimer(struct task_s - * it. - */ - thread_group_cputime(tsk, &sum); -+ spin_lock_irqsave(&cputimer->lock, flags); -+ cputimer->running = 1; - update_gt_cputime(&cputimer->cputime, &sum); -- } -+ } else -+ spin_lock_irqsave(&cputimer->lock, flags); - *times = cputimer->cputime; - spin_unlock_irqrestore(&cputimer->lock, flags); - } - diff --git a/drm-ttm-nouveau-oops-fix.patch b/drm-ttm-nouveau-oops-fix.patch deleted file mode 100644 index e65259e50..000000000 --- a/drm-ttm-nouveau-oops-fix.patch +++ /dev/null @@ -1,40 +0,0 @@ -diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c -index 2e618b5..9095b5b 100644 ---- a/drivers/gpu/drm/ttm/ttm_bo.c -+++ b/drivers/gpu/drm/ttm/ttm_bo.c -@@ -390,10 +390,12 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, - * Create and bind a ttm if required. - */ - -- if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED) && (bo->ttm == NULL)) { -- ret = ttm_bo_add_ttm(bo, false); -- if (ret) -- goto out_err; -+ if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) { -+ if (bo->ttm == NULL) { -+ ret = ttm_bo_add_ttm(bo, false); -+ if (ret) -+ goto out_err; -+ } - - ret = ttm_tt_set_placement_caching(bo->ttm, mem->placement); - if (ret) -diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c -index 77dbf40..ae3c6f5 100644 ---- a/drivers/gpu/drm/ttm/ttm_bo_util.c -+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c -@@ -635,13 +635,13 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, - if (ret) - return ret; - -- ttm_bo_free_old_node(bo); - if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && - (bo->ttm != NULL)) { - ttm_tt_unbind(bo->ttm); - ttm_tt_destroy(bo->ttm); - bo->ttm = NULL; - } -+ ttm_bo_free_old_node(bo); - } else { - /** - * This should help pipeline ordinary buffer moves. diff --git a/fuse-fix-memory-leak.patch b/fuse-fix-memory-leak.patch deleted file mode 100644 index c52069bee..000000000 --- a/fuse-fix-memory-leak.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 4078129ec09990936702ab5274e05d139d7f7dcd Mon Sep 17 00:00:00 2001 -From: Miklos Szeredi -Date: Mon, 12 Sep 2011 09:38:03 +0200 -Subject: [PATCH] fuse: fix memory leak - -kmemleak is reporting that 32 bytes are being leaked by FUSE: - - unreferenced object 0xe373b270 (size 32): - comm "fusermount", pid 1207, jiffies 4294707026 (age 2675.187s) - hex dump (first 32 bytes): - 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ................ - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - backtrace: - [] kmemleak_alloc+0x27/0x50 - [] kmem_cache_alloc+0xc5/0x180 - [] fuse_alloc_forget+0x1e/0x20 - [] fuse_alloc_inode+0xb0/0xd0 - [] alloc_inode+0x1c/0x80 - [] iget5_locked+0x8f/0x1a0 - [] fuse_iget+0x72/0x1a0 - [] fuse_get_root_inode+0x8a/0x90 - [] fuse_fill_super+0x3ef/0x590 - [] mount_nodev+0x3f/0x90 - [] fuse_mount+0x15/0x20 - [] mount_fs+0x1c/0xc0 - [] vfs_kern_mount+0x41/0x90 - [] do_kern_mount+0x39/0xd0 - [] do_mount+0x2e5/0x660 - [] sys_mount+0x66/0xa0 - -This leak report is consistent and happens once per boot on -3.1.0-rc5-dirty. - -This happens if a FORGET request is queued after the fuse device was -released. - -Reported-by: Sitsofe Wheeler -Signed-off-by: Miklos Szeredi -Tested-by: Sitsofe Wheeler -Signed-off-by: Linus Torvalds ---- - fs/fuse/dev.c | 12 ++++++++---- - 1 files changed, 8 insertions(+), 4 deletions(-) - -diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c -index 168a80f..5cb8614 100644 ---- a/fs/fuse/dev.c -+++ b/fs/fuse/dev.c -@@ -258,10 +258,14 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget, - forget->forget_one.nlookup = nlookup; - - spin_lock(&fc->lock); -- fc->forget_list_tail->next = forget; -- fc->forget_list_tail = forget; -- wake_up(&fc->waitq); -- kill_fasync(&fc->fasync, SIGIO, POLL_IN); -+ if (fc->connected) { -+ fc->forget_list_tail->next = forget; -+ fc->forget_list_tail = forget; -+ wake_up(&fc->waitq); -+ kill_fasync(&fc->fasync, SIGIO, POLL_IN); -+ } else { -+ kfree(forget); -+ } - spin_unlock(&fc->lock); - } - --- -1.7.6.4 - diff --git a/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch b/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch deleted file mode 100644 index c81bf91d1..000000000 --- a/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch +++ /dev/null @@ -1,315 +0,0 @@ -From 6596528e391ad978a6a120142cba97a1d7324cb6 Mon Sep 17 00:00:00 2001 -From: Seth Forshee -Date: Mon, 18 Jul 2011 08:06:23 -0700 -Subject: [PATCH] hfsplus: ensure bio requests are not smaller than the - hardware sectors - -Currently all bio requests are 512 bytes, which may fail for media -whose physical sector size is larger than this. Ensure these -requests are not smaller than the block device logical block size. - -BugLink: http://bugs.launchpad.net/bugs/734883 -Signed-off-by: Seth Forshee -Signed-off-by: Christoph Hellwig ---- - fs/hfsplus/hfsplus_fs.h | 16 ++++++++- - fs/hfsplus/part_tbl.c | 32 ++++++++++-------- - fs/hfsplus/super.c | 12 +++--- - fs/hfsplus/wrapper.c | 83 +++++++++++++++++++++++++++++++++++----------- - 4 files changed, 101 insertions(+), 42 deletions(-) - -diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h -index 0bebf74..81dfd1e 100644 ---- a/fs/hfsplus/hfsplus_fs.h -+++ b/fs/hfsplus/hfsplus_fs.h -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include "hfsplus_raw.h" - - #define DBG_BNODE_REFS 0x00000001 -@@ -110,7 +111,9 @@ struct hfsplus_vh; - struct hfs_btree; - - struct hfsplus_sb_info { -+ void *s_vhdr_buf; - struct hfsplus_vh *s_vhdr; -+ void *s_backup_vhdr_buf; - struct hfsplus_vh *s_backup_vhdr; - struct hfs_btree *ext_tree; - struct hfs_btree *cat_tree; -@@ -258,6 +261,15 @@ struct hfsplus_readdir_data { - struct hfsplus_cat_key key; - }; - -+/* -+ * Find minimum acceptible I/O size for an hfsplus sb. -+ */ -+static inline unsigned short hfsplus_min_io_size(struct super_block *sb) -+{ -+ return max_t(unsigned short, bdev_logical_block_size(sb->s_bdev), -+ HFSPLUS_SECTOR_SIZE); -+} -+ - #define hfs_btree_open hfsplus_btree_open - #define hfs_btree_close hfsplus_btree_close - #define hfs_btree_write hfsplus_btree_write -@@ -436,8 +448,8 @@ int hfsplus_compare_dentry(const struct dentry *parent, - /* wrapper.c */ - int hfsplus_read_wrapper(struct super_block *); - int hfs_part_find(struct super_block *, sector_t *, sector_t *); --int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, -- void *data, int rw); -+int hfsplus_submit_bio(struct super_block *sb, sector_t sector, -+ void *buf, void **data, int rw); - - /* time macros */ - #define __hfsp_mt2ut(t) (be32_to_cpu(t) - 2082844800U) -diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c -index 40ad88c..eb355d8 100644 ---- a/fs/hfsplus/part_tbl.c -+++ b/fs/hfsplus/part_tbl.c -@@ -88,11 +88,12 @@ static int hfs_parse_old_pmap(struct super_block *sb, struct old_pmap *pm, - return -ENOENT; - } - --static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm, -- sector_t *part_start, sector_t *part_size) -+static int hfs_parse_new_pmap(struct super_block *sb, void *buf, -+ struct new_pmap *pm, sector_t *part_start, sector_t *part_size) - { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); - int size = be32_to_cpu(pm->pmMapBlkCnt); -+ int buf_size = hfsplus_min_io_size(sb); - int res; - int i = 0; - -@@ -107,11 +108,14 @@ static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm, - if (++i >= size) - return -ENOENT; - -- res = hfsplus_submit_bio(sb->s_bdev, -- *part_start + HFS_PMAP_BLK + i, -- pm, READ); -- if (res) -- return res; -+ pm = (struct new_pmap *)((u8 *)pm + HFSPLUS_SECTOR_SIZE); -+ if ((u8 *)pm - (u8 *)buf >= buf_size) { -+ res = hfsplus_submit_bio(sb, -+ *part_start + HFS_PMAP_BLK + i, -+ buf, (void **)&pm, READ); -+ if (res) -+ return res; -+ } - } while (pm->pmSig == cpu_to_be16(HFS_NEW_PMAP_MAGIC)); - - return -ENOENT; -@@ -124,15 +128,15 @@ static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm, - int hfs_part_find(struct super_block *sb, - sector_t *part_start, sector_t *part_size) - { -- void *data; -+ void *buf, *data; - int res; - -- data = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL); -- if (!data) -+ buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); -+ if (!buf) - return -ENOMEM; - -- res = hfsplus_submit_bio(sb->s_bdev, *part_start + HFS_PMAP_BLK, -- data, READ); -+ res = hfsplus_submit_bio(sb, *part_start + HFS_PMAP_BLK, -+ buf, &data, READ); - if (res) - goto out; - -@@ -141,13 +145,13 @@ int hfs_part_find(struct super_block *sb, - res = hfs_parse_old_pmap(sb, data, part_start, part_size); - break; - case HFS_NEW_PMAP_MAGIC: -- res = hfs_parse_new_pmap(sb, data, part_start, part_size); -+ res = hfs_parse_new_pmap(sb, buf, data, part_start, part_size); - break; - default: - res = -ENOENT; - break; - } - out: -- kfree(data); -+ kfree(buf); - return res; - } -diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c -index 84f56e1..c106ca2 100644 ---- a/fs/hfsplus/super.c -+++ b/fs/hfsplus/super.c -@@ -203,17 +203,17 @@ int hfsplus_sync_fs(struct super_block *sb, int wait) - write_backup = 1; - } - -- error2 = hfsplus_submit_bio(sb->s_bdev, -+ error2 = hfsplus_submit_bio(sb, - sbi->part_start + HFSPLUS_VOLHEAD_SECTOR, -- sbi->s_vhdr, WRITE_SYNC); -+ sbi->s_vhdr_buf, NULL, WRITE_SYNC); - if (!error) - error = error2; - if (!write_backup) - goto out; - -- error2 = hfsplus_submit_bio(sb->s_bdev, -+ error2 = hfsplus_submit_bio(sb, - sbi->part_start + sbi->sect_count - 2, -- sbi->s_backup_vhdr, WRITE_SYNC); -+ sbi->s_backup_vhdr_buf, NULL, WRITE_SYNC); - if (!error) - error2 = error; - out: -@@ -257,8 +257,8 @@ static void hfsplus_put_super(struct super_block *sb) - hfs_btree_close(sbi->ext_tree); - iput(sbi->alloc_file); - iput(sbi->hidden_dir); -- kfree(sbi->s_vhdr); -- kfree(sbi->s_backup_vhdr); -+ kfree(sbi->s_vhdr_buf); -+ kfree(sbi->s_backup_vhdr_buf); - unload_nls(sbi->nls); - kfree(sb->s_fs_info); - sb->s_fs_info = NULL; -diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c -index 2f933e8..10e515a 100644 ---- a/fs/hfsplus/wrapper.c -+++ b/fs/hfsplus/wrapper.c -@@ -31,25 +31,67 @@ static void hfsplus_end_io_sync(struct bio *bio, int err) - complete(bio->bi_private); - } - --int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, -- void *data, int rw) -+/* -+ * hfsplus_submit_bio - Perfrom block I/O -+ * @sb: super block of volume for I/O -+ * @sector: block to read or write, for blocks of HFSPLUS_SECTOR_SIZE bytes -+ * @buf: buffer for I/O -+ * @data: output pointer for location of requested data -+ * @rw: direction of I/O -+ * -+ * The unit of I/O is hfsplus_min_io_size(sb), which may be bigger than -+ * HFSPLUS_SECTOR_SIZE, and @buf must be sized accordingly. On reads -+ * @data will return a pointer to the start of the requested sector, -+ * which may not be the same location as @buf. -+ * -+ * If @sector is not aligned to the bdev logical block size it will -+ * be rounded down. For writes this means that @buf should contain data -+ * that starts at the rounded-down address. As long as the data was -+ * read using hfsplus_submit_bio() and the same buffer is used things -+ * will work correctly. -+ */ -+int hfsplus_submit_bio(struct super_block *sb, sector_t sector, -+ void *buf, void **data, int rw) - { - DECLARE_COMPLETION_ONSTACK(wait); - struct bio *bio; - int ret = 0; -+ unsigned int io_size; -+ loff_t start; -+ int offset; -+ -+ /* -+ * Align sector to hardware sector size and find offset. We -+ * assume that io_size is a power of two, which _should_ -+ * be true. -+ */ -+ io_size = hfsplus_min_io_size(sb); -+ start = (loff_t)sector << HFSPLUS_SECTOR_SHIFT; -+ offset = start & (io_size - 1); -+ sector &= ~((io_size >> HFSPLUS_SECTOR_SHIFT) - 1); - - bio = bio_alloc(GFP_NOIO, 1); - bio->bi_sector = sector; -- bio->bi_bdev = bdev; -+ bio->bi_bdev = sb->s_bdev; - bio->bi_end_io = hfsplus_end_io_sync; - bio->bi_private = &wait; - -- /* -- * We always submit one sector at a time, so bio_add_page must not fail. -- */ -- if (bio_add_page(bio, virt_to_page(data), HFSPLUS_SECTOR_SIZE, -- offset_in_page(data)) != HFSPLUS_SECTOR_SIZE) -- BUG(); -+ if (!(rw & WRITE) && data) -+ *data = (u8 *)buf + offset; -+ -+ while (io_size > 0) { -+ unsigned int page_offset = offset_in_page(buf); -+ unsigned int len = min_t(unsigned int, PAGE_SIZE - page_offset, -+ io_size); -+ -+ ret = bio_add_page(bio, virt_to_page(buf), len, page_offset); -+ if (ret != len) { -+ ret = -EIO; -+ goto out; -+ } -+ io_size -= len; -+ buf = (u8 *)buf + len; -+ } - - submit_bio(rw, bio); - wait_for_completion(&wait); -@@ -57,8 +99,9 @@ int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, - if (!bio_flagged(bio, BIO_UPTODATE)) - ret = -EIO; - -+out: - bio_put(bio); -- return ret; -+ return ret < 0 ? ret : 0; - } - - static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd) -@@ -143,17 +186,17 @@ int hfsplus_read_wrapper(struct super_block *sb) - goto out; - - error = -ENOMEM; -- sbi->s_vhdr = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL); -- if (!sbi->s_vhdr) -+ sbi->s_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); -+ if (!sbi->s_vhdr_buf) - goto out; -- sbi->s_backup_vhdr = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL); -- if (!sbi->s_backup_vhdr) -+ sbi->s_backup_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); -+ if (!sbi->s_backup_vhdr_buf) - goto out_free_vhdr; - - reread: -- error = hfsplus_submit_bio(sb->s_bdev, -- part_start + HFSPLUS_VOLHEAD_SECTOR, -- sbi->s_vhdr, READ); -+ error = hfsplus_submit_bio(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, -+ sbi->s_vhdr_buf, (void **)&sbi->s_vhdr, -+ READ); - if (error) - goto out_free_backup_vhdr; - -@@ -183,9 +226,9 @@ reread: - goto reread; - } - -- error = hfsplus_submit_bio(sb->s_bdev, -- part_start + part_size - 2, -- sbi->s_backup_vhdr, READ); -+ error = hfsplus_submit_bio(sb, part_start + part_size - 2, -+ sbi->s_backup_vhdr_buf, -+ (void **)&sbi->s_backup_vhdr, READ); - if (error) - goto out_free_backup_vhdr; - --- -1.7.6 - diff --git a/hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patch b/hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patch deleted file mode 100644 index cf87d2ad3..000000000 --- a/hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 35d851df23b093ee027f827fed2213ae5e88fc7a Mon Sep 17 00:00:00 2001 -From: Jiri Kosina -Date: Thu, 25 Aug 2011 14:21:37 +0200 -Subject: [PATCH] HID: magicmouse: ignore 'ivalid report id' while switching - modes, v2 - -This is basically a more generic respin of 23746a6 ("HID: magicmouse: ignore -'ivalid report id' while switching modes") which got reverted later by -c3a492. - -It turns out that on some configurations, this is actually still the case -and we are not able to detect in runtime. - -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 - -Reported-by: Chase Douglas -Reported-by: Jaikumar Ganesh -Tested-by: Chase Douglas -Tested-by: Jaikumar Ganesh -Signed-off-by: Jiri Kosina ---- - drivers/hid/hid-magicmouse.c | 10 +++++++++- - 1 files changed, 9 insertions(+), 1 deletions(-) - -diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c -index b5bdab3..f0fbd7b 100644 ---- a/drivers/hid/hid-magicmouse.c -+++ b/drivers/hid/hid-magicmouse.c -@@ -537,9 +537,17 @@ static int magicmouse_probe(struct hid_device *hdev, - } - report->size = 6; - -+ /* -+ * Some devices repond 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 && ret != sizeof(feature)) { - hid_err(hdev, "unable to request touch data (%d)\n", ret); - goto err_stop_hw; - } --- -1.7.5.4 - diff --git a/kernel.spec b/kernel.spec index 589acc35b..5719e125f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 0 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 @@ -615,7 +615,6 @@ Patch1500: fix_xen_guest_on_old_EC2.patch # nouveau + drm fixes Patch1810: drm-nouveau-updates.patch -Patch1811: drm-ttm-nouveau-oops-fix.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch # make sure the lvds comes back on lid open @@ -656,7 +655,6 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch Patch12024: usb-add-quirk-for-logitech-webcams.patch Patch12025: crypto-register-cryptd-first.patch -Patch12026: cputimer-Cure-lock-inversion.patch Patch12027: x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch Patch12028: x86-p4-make-watchdog-and-perf-work-together.patch @@ -667,7 +665,6 @@ Patch12204: linux-2.6-enable-more-pci-autosuspend.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13001: epoll-fix-spurious-lockdep-warnings.patch -Patch13002: hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch Patch13010: iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch @@ -688,18 +685,9 @@ Patch21003: TEGRA-2.6.40.2-enable-USB-ports.patch # rhbz#719607 Patch21004: vfs-fix-automount-for-negative-autofs-dentries.patch -# rhbz#727927 rhbz#731278 rhbz#732934 -Patch21005: cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch - -# rhbz #735437 -Patch21007: ucvideo-fix-crash-when-linking-entities.patch - # rhbz #740645 Patch21011: md-dont-delay-reboot-by-1-second-if-no-MD-devices.patch -# rhbz #714381 -Patch21012: hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patch - # rhbz #496975 Patch21013: Platform-fix-samsung-laptop-DMI-identification-for-N.patch @@ -713,9 +701,6 @@ Patch21017: binfmt_elf-fix-PIE-execution-with-random-disabled.patch #rhbz #722509 Patch21018: mmc-Always-check-for-lower-base-frequency-quirk-for-.patch -#rhbz #745241 -Patch21019: fuse-fix-memory-leak.patch - #rhbz #735946 Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch @@ -1221,7 +1206,6 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch ApplyPatch fix_xen_guest_on_old_EC2.patch # DRM core -ApplyPatch drm-ttm-nouveau-oops-fix.patch # Nouveau DRM ApplyOptionalPatch drm-nouveau-updates.patch @@ -1261,7 +1245,6 @@ ApplyPatch add-appleir-usb-driver.patch ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch ApplyPatch crypto-register-cryptd-first.patch -ApplyPatch cputimer-Cure-lock-inversion.patch ApplyPatch x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch ApplyPatch x86-p4-make-watchdog-and-perf-work-together.patch @@ -1270,8 +1253,6 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch epoll-fix-spurious-lockdep-warnings.patch -ApplyPatch hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch - ApplyPatch iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch ApplyPatch utrace.patch @@ -1279,19 +1260,9 @@ ApplyPatch utrace.patch # rhbz#719607 ApplyPatch vfs-fix-automount-for-negative-autofs-dentries.patch -# rhbz#727927 rhbz#731278 rhbz#732934 -# cifs-possible-memory-corruption-on-mount.patch is already queued for 3.0.4 -ApplyPatch cifs-fix-ERR_PTR-dereference-in-cifs_get_root.patch - -#rhbz 735437 -ApplyPatch ucvideo-fix-crash-when-linking-entities.patch - #rhbz 740645 ApplyPatch md-dont-delay-reboot-by-1-second-if-no-MD-devices.patch -# rhbz #714381 -ApplyPatch hid-magicmouse-ignore-ivalid-report-id-while-switching-modes-v2.patch - # rhbz #496675 ApplyPatch Platform-fix-samsung-laptop-DMI-identification-for-N.patch @@ -1305,9 +1276,6 @@ ApplyPatch binfmt_elf-fix-PIE-execution-with-random-disabled.patch #rhbz #722509 ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch -#rhbz #745241 -ApplyPatch fuse-fix-memory-leak.patch - #rhbz #735946 ApplyPatch 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch @@ -1935,6 +1903,9 @@ fi # and build. %changelog +* Tue Oct 25 2011 Josh Boyer +- Linux 3.0.8 stable release + * Mon Oct 24 2011 Chuck Ebbert - Add patch from LKML to fix Samsung notebook brightness flicker (rhbz 737108) diff --git a/sources b/sources index 882a51334..6dcaf1f12 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 -34c883ae9b6f112029879c8672b590ad patch-3.0.7.bz2 +49618d8c7a71549c8870eb709c7d3f81 patch-3.0.8.bz2 diff --git a/ucvideo-fix-crash-when-linking-entities.patch b/ucvideo-fix-crash-when-linking-entities.patch deleted file mode 100644 index 69f86d64c..000000000 --- a/ucvideo-fix-crash-when-linking-entities.patch +++ /dev/null @@ -1,34 +0,0 @@ -The uvc_mc_register_entity() function wrongfully selects the -media_entity associated with a UVC entity when creating links. This -results in access to uninitialized media_entity structures and can hit a -BUG_ON statement in media_entity_create_link(). Fix it. - -Signed-off-by: Laurent Pinchart ---- - drivers/media/video/uvc/uvc_entity.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -This patch should fix a v3.0 regression that results in a kernel crash as -reported in http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=637740 and -https://bugzilla.redhat.com/show_bug.cgi?id=735437. - -Test results will be welcome. - -diff --git a/drivers/media/video/uvc/uvc_entity.c b/drivers/media/video/uvc/uvc_entity.c -index 48fea37..29e2399 100644 ---- a/drivers/media/video/uvc/uvc_entity.c -+++ b/drivers/media/video/uvc/uvc_entity.c -@@ -49,7 +49,7 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain, - if (remote == NULL) - return -EINVAL; - -- source = (UVC_ENTITY_TYPE(remote) != UVC_TT_STREAMING) -+ source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING) - ? (remote->vdev ? &remote->vdev->entity : NULL) - : &remote->subdev.entity; - if (source == NULL) --- -Regards, - -Laurent Pinchart - From 45fb06294afc11b167b6fc591484e14c782fd05d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 25 Oct 2011 11:42:22 -0400 Subject: [PATCH 191/397] CVE-2011-1083: excessive in kernel CPU consumption when creating large nested epoll structures (rhbz 748668) --- epoll-limit-paths.patch | 465 ++++++++++++++++++++++++++++++++++++++++ kernel.spec | 7 +- 2 files changed, 471 insertions(+), 1 deletion(-) create mode 100644 epoll-limit-paths.patch diff --git a/epoll-limit-paths.patch b/epoll-limit-paths.patch new file mode 100644 index 000000000..440db27b9 --- /dev/null +++ b/epoll-limit-paths.patch @@ -0,0 +1,465 @@ +From 6a4ca79652219cf22da800d990e5b46feaea1ad9 Mon Sep 17 00:00:00 2001 +From: Jason Baron +Date: Mon, 24 Oct 2011 14:59:02 +1100 +Subject: [PATCH] epoll: limit paths + +epoll: limit paths + +The current epoll code can be tickled to run basically indefinitely in +both loop detection path check (on ep_insert()), and in the wakeup paths. +The programs that tickle this behavior set up deeply linked networks of +epoll file descriptors that cause the epoll algorithms to traverse them +indefinitely. A couple of these sample programs have been previously +posted in this thread: https://lkml.org/lkml/2011/2/25/297. + +To fix the loop detection path check algorithms, I simply keep track of +the epoll nodes that have been already visited. Thus, the loop detection +becomes proportional to the number of epoll file descriptor and links. +This dramatically decreases the run-time of the loop check algorithm. In +one diabolical case I tried it reduced the run-time from 15 mintues (all +in kernel time) to .3 seconds. + +Fixing the wakeup paths could be done at wakeup time in a similar manner +by keeping track of nodes that have already been visited, but the +complexity is harder, since there can be multiple wakeups on different +cpus...Thus, I've opted to limit the number of possible wakeup paths when +the paths are created. + +This is accomplished, by noting that the end file descriptor points that +are found during the loop detection pass (from the newly added link), are +actually the sources for wakeup events. I keep a list of these file +descriptors and limit the number and length of these paths that emanate +from these 'source file descriptors'. In the current implemetation I +allow 1000 paths of length 1, 500 of length 2, 100 of length 3, 50 of +length 4 and 10 of length 5. Note that it is sufficient to check the +'source file descriptors' reachable from the newly added link, since no +other 'source file descriptors' will have newly added links. This allows +us to check only the wakeup paths that may have gotten too long, and not +re-check all possible wakeup paths on the system. + +In terms of the path limit selection, I think its first worth noting that +the most common case for epoll, is probably the model where you have 1 +epoll file descriptor that is monitoring n number of 'source file +descriptors'. In this case, each 'source file descriptor' has a 1 path of +length 1. Thus, I believe that the limits I'm proposing are quite +reasonable and in fact may be too generous. Thus, I'm hoping that the +proposed limits will not prevent any workloads that currently work to +fail. + +In terms of locking, I have extended the use of the 'epmutex' to all +epoll_ctl add and remove operations. Currently its only used in a subset +of the add paths. I need to hold the epmutex, so that we can correctly +traverse a coherent graph, to check the number of paths. I believe that +this additional locking is probably ok, since its in the setup/teardown +paths, and doesn't affect the running paths, but it certainly is going to +add some extra overhead. Also, worth noting is that the epmuex was +recently added to the ep_ctl add operations in the initial path loop +detection code using the argument that it was not on a critical path. + +Another thing to note here, is the length of epoll chains that is allowed. +Currently, eventpoll.c defines: + +/* Maximum number of nesting allowed inside epoll sets */ +#define EP_MAX_NESTS 4 + +This basically means that I am limited to a graph depth of 5 (EP_MAX_NESTS ++ 1). However, this limit is currently only enforced during the loop +check detection code, and only when the epoll file descriptors are added +in a certain order. Thus, this limit is currently easily bypassed. The +newly added check for wakeup paths, stricly limits the wakeup paths to a +length of 5, regardless of the order in which ep's are linked together. +Thus, a side-effect of the new code is a more consistent enforcement of +the graph depth. + +Thus far, I've tested this, using the sample programs previously +mentioned, which now either return quickly or return -EINVAL. I've also +testing using the piptest.c epoll tester, which showed no difference in +performance. I've also created a number of different epoll networks and +tested that they behave as expectded. + +I believe this solves the original diabolical test cases, while still +preserving the sane epoll nesting. + +Signed-off-by: Jason Baron +Cc: Nelson Elhage +Cc: Davide Libenzi +Signed-off-by: Andrew Morton +--- + fs/eventpoll.c | 226 ++++++++++++++++++++++++++++++++++++++++----- + include/linux/eventpoll.h | 1 + + include/linux/fs.h | 1 + + 3 files changed, 203 insertions(+), 25 deletions(-) + +diff --git a/fs/eventpoll.c b/fs/eventpoll.c +index 4a53743..414ac74 100644 +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -197,6 +197,12 @@ struct eventpoll { + + /* The user that created the eventpoll descriptor */ + struct user_struct *user; ++ ++ struct file *file; ++ ++ /* used to optimize loop detection check */ ++ int visited; ++ struct list_head visitedllink; + }; + + /* Wait structure used by the poll hooks */ +@@ -255,6 +261,12 @@ static struct kmem_cache *epi_cache __read_mostly; + /* Slab cache used to allocate "struct eppoll_entry" */ + static struct kmem_cache *pwq_cache __read_mostly; + ++/* Visited nodes during ep_loop_check(), so we can unset them when we finish */ ++LIST_HEAD(visited_list); ++ ++/* Files with newly added links, which need a limit on emanating paths */ ++LIST_HEAD(tfile_check_list); ++ + #ifdef CONFIG_SYSCTL + + #include +@@ -276,6 +288,12 @@ ctl_table epoll_table[] = { + }; + #endif /* CONFIG_SYSCTL */ + ++static const struct file_operations eventpoll_fops; ++ ++static inline int is_file_epoll(struct file *f) ++{ ++ return f->f_op == &eventpoll_fops; ++} + + /* Setup the structure that is used as key for the RB tree */ + static inline void ep_set_ffd(struct epoll_filefd *ffd, +@@ -711,12 +729,6 @@ static const struct file_operations eventpoll_fops = { + .llseek = noop_llseek, + }; + +-/* Fast test to see if the file is an evenpoll file */ +-static inline int is_file_epoll(struct file *f) +-{ +- return f->f_op == &eventpoll_fops; +-} +- + /* + * This is called from eventpoll_release() to unlink files from the eventpoll + * interface. We need to have this facility to cleanup correctly files that are +@@ -926,6 +938,96 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi) + rb_insert_color(&epi->rbn, &ep->rbr); + } + ++ ++ ++#define PATH_ARR_SIZE 5 ++/* These are the number paths of length 1 to 5, that we are allowing to emanate ++ * from a single file of interest. For example, we allow 1000 paths of length ++ * 1, to emanate from each file of interest. This essentially represents the ++ * potential wakeup paths, which need to be limited in order to avoid massive ++ * uncontrolled wakeup storms. The common use case should be a single ep which ++ * is connected to n file sources. In this case each file source has 1 path ++ * of length 1. Thus, the numbers below should be more than sufficient. ++ */ ++int path_limits[PATH_ARR_SIZE] = { 1000, 500, 100, 50, 10 }; ++int path_count[PATH_ARR_SIZE]; ++ ++static int path_count_inc(int nests) ++{ ++ if (++path_count[nests] > path_limits[nests]) ++ return -1; ++ return 0; ++} ++ ++static void path_count_init(void) ++{ ++ int i; ++ ++ for (i = 0; i < PATH_ARR_SIZE; i++) ++ path_count[i] = 0; ++} ++ ++static int reverse_path_check_proc(void *priv, void *cookie, int call_nests) ++{ ++ int error = 0; ++ struct file *file = priv; ++ struct file *child_file; ++ struct epitem *epi; ++ ++ list_for_each_entry(epi, &file->f_ep_links, fllink) { ++ child_file = epi->ep->file; ++ if (is_file_epoll(child_file)) { ++ if (list_empty(&child_file->f_ep_links)) { ++ if (path_count_inc(call_nests)) { ++ error = -1; ++ break; ++ } ++ } else { ++ error = ep_call_nested(&poll_loop_ncalls, ++ EP_MAX_NESTS, ++ reverse_path_check_proc, ++ child_file, child_file, ++ current); ++ } ++ if (error != 0) ++ break; ++ } else { ++ printk(KERN_ERR "reverse_path_check_proc: " ++ "file is not an ep!\n"); ++ } ++ } ++ return error; ++} ++ ++/** ++ * reverse_path_check - The tfile_check_list is list of file *, which have ++ * links that are proposed to be newly added. We need to ++ * make sure that those added links don't add too many ++ * paths such that we will spend all our time waking up ++ * eventpoll objects. ++ * ++ * Returns: Returns zero if the proposed links don't create too many paths, ++ * -1 otherwise. ++ */ ++static int reverse_path_check(void) ++{ ++ int length = 0; ++ int error = 0; ++ struct file *current_file; ++ ++ /* let's call this for all tfiles */ ++ list_for_each_entry(current_file, &tfile_check_list, f_tfile_llink) { ++ length++; ++ path_count_init(); ++ error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, ++ reverse_path_check_proc, current_file, ++ current_file, current); ++ if (error) ++ break; ++ } ++ return error; ++} ++ + /* + * Must be called with "mtx" held. + */ +@@ -987,6 +1089,11 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, + */ + ep_rbtree_insert(ep, epi); + ++ /* now check if we've created too many backpaths */ ++ error = -EINVAL; ++ if (reverse_path_check()) ++ goto error_remove_epi; ++ + /* We have to drop the new item inside our item list to keep track of it */ + spin_lock_irqsave(&ep->lock, flags); + +@@ -1011,6 +1118,14 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, + + return 0; + ++error_remove_epi: ++ spin_lock(&tfile->f_lock); ++ if (ep_is_linked(&epi->fllink)) ++ list_del_init(&epi->fllink); ++ spin_unlock(&tfile->f_lock); ++ ++ rb_erase(&epi->rbn, &ep->rbr); ++ + error_unregister: + ep_unregister_pollwait(ep, epi); + +@@ -1275,18 +1390,35 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests) + int error = 0; + struct file *file = priv; + struct eventpoll *ep = file->private_data; ++ struct eventpoll *ep_tovisit; + struct rb_node *rbp; + struct epitem *epi; + + mutex_lock_nested(&ep->mtx, call_nests + 1); ++ ep->visited = 1; ++ list_add(&ep->visitedllink, &visited_list); + for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) { + epi = rb_entry(rbp, struct epitem, rbn); + if (unlikely(is_file_epoll(epi->ffd.file))) { ++ ep_tovisit = epi->ffd.file->private_data; ++ if (ep_tovisit->visited) ++ continue; + error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, +- ep_loop_check_proc, epi->ffd.file, +- epi->ffd.file->private_data, current); ++ ep_loop_check_proc, epi->ffd.file, ++ ep_tovisit, current); + if (error != 0) + break; ++ } else { ++ /* if we've reached a file that is not associated with ++ * an ep, then then we need to check if the newly added ++ * links are going to add too many wakeup paths. We do ++ * this by adding it to the tfile_check_list, if it's ++ * not already there, and calling reverse_path_check() ++ * during ep_insert() ++ */ ++ if (list_empty(&epi->ffd.file->f_tfile_llink)) ++ list_add(&epi->ffd.file->f_tfile_llink, ++ &tfile_check_list); + } + } + mutex_unlock(&ep->mtx); +@@ -1307,8 +1439,30 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests) + */ + static int ep_loop_check(struct eventpoll *ep, struct file *file) + { +- return ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, ++ int ret; ++ struct eventpoll *ep_cur, *ep_next; ++ ++ ret = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, + ep_loop_check_proc, file, ep, current); ++ /* clear visited list */ ++ list_for_each_entry_safe(ep_cur, ep_next, &visited_list, visitedllink) { ++ ep_cur->visited = 0; ++ list_del(&ep_cur->visitedllink); ++ } ++ return ret; ++} ++ ++static void clear_tfile_check_list(void) ++{ ++ struct file *file; ++ ++ /* first clear the tfile_check_list */ ++ while (!list_empty(&tfile_check_list)) { ++ file = list_first_entry(&tfile_check_list, struct file, ++ f_tfile_llink); ++ list_del_init(&file->f_tfile_llink); ++ } ++ INIT_LIST_HEAD(&tfile_check_list); + } + + /* +@@ -1316,8 +1470,9 @@ static int ep_loop_check(struct eventpoll *ep, struct file *file) + */ + SYSCALL_DEFINE1(epoll_create1, int, flags) + { +- int error; ++ int error, fd; + struct eventpoll *ep = NULL; ++ struct file *file; + + /* Check the EPOLL_* constant for consistency. */ + BUILD_BUG_ON(EPOLL_CLOEXEC != O_CLOEXEC); +@@ -1334,11 +1489,25 @@ SYSCALL_DEFINE1(epoll_create1, int, flags) + * Creates all the items needed to setup an eventpoll file. That is, + * a file structure and a free file descriptor. + */ +- error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep, ++ fd = get_unused_fd_flags(O_RDWR | (flags & O_CLOEXEC)); ++ if (fd < 0) { ++ error = fd; ++ goto out_free_ep; ++ } ++ file = anon_inode_getfile("[eventpoll]", &eventpoll_fops, ep, + O_RDWR | (flags & O_CLOEXEC)); +- if (error < 0) +- ep_free(ep); +- ++ if (IS_ERR(file)) { ++ error = PTR_ERR(file); ++ goto out_free_fd; ++ } ++ fd_install(fd, file); ++ ep->file = file; ++ return fd; ++ ++out_free_fd: ++ put_unused_fd(fd); ++out_free_ep: ++ ep_free(ep); + return error; + } + +@@ -1404,21 +1573,27 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, + /* + * When we insert an epoll file descriptor, inside another epoll file + * descriptor, there is the change of creating closed loops, which are +- * better be handled here, than in more critical paths. ++ * better be handled here, than in more critical paths. While we are ++ * checking for loops we also determine the list of files reachable ++ * and hang them on the tfile_check_list, so we can check that we ++ * haven't created too many possible wakeup paths. + * +- * We hold epmutex across the loop check and the insert in this case, in +- * order to prevent two separate inserts from racing and each doing the +- * insert "at the same time" such that ep_loop_check passes on both +- * before either one does the insert, thereby creating a cycle. ++ * We need to hold the epmutex across both ep_insert and ep_remove ++ * b/c we want to make sure we are looking at a coherent view of ++ * epoll network. + */ +- if (unlikely(is_file_epoll(tfile) && op == EPOLL_CTL_ADD)) { ++ if (op == EPOLL_CTL_ADD || op == EPOLL_CTL_DEL) { + mutex_lock(&epmutex); + did_lock_epmutex = 1; +- error = -ELOOP; +- if (ep_loop_check(ep, tfile) != 0) +- goto error_tgt_fput; + } +- ++ if (op == EPOLL_CTL_ADD) { ++ if (is_file_epoll(tfile)) { ++ error = -ELOOP; ++ if (ep_loop_check(ep, tfile) != 0) ++ goto error_tgt_fput; ++ } else ++ list_add(&tfile->f_tfile_llink, &tfile_check_list); ++ } + + mutex_lock_nested(&ep->mtx, 0); + +@@ -1437,6 +1612,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, + error = ep_insert(ep, &epds, tfile, fd); + } else + error = -EEXIST; ++ clear_tfile_check_list(); + break; + case EPOLL_CTL_DEL: + if (epi) +@@ -1455,7 +1631,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, + mutex_unlock(&ep->mtx); + + error_tgt_fput: +- if (unlikely(did_lock_epmutex)) ++ if (did_lock_epmutex) + mutex_unlock(&epmutex); + + fput(tfile); +diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h +index f362733..657ab55 100644 +--- a/include/linux/eventpoll.h ++++ b/include/linux/eventpoll.h +@@ -61,6 +61,7 @@ struct file; + static inline void eventpoll_init_file(struct file *file) + { + INIT_LIST_HEAD(&file->f_ep_links); ++ INIT_LIST_HEAD(&file->f_tfile_llink); + } + + +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 277f497..93778e0 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -985,6 +985,7 @@ struct file { + #ifdef CONFIG_EPOLL + /* Used by fs/eventpoll.c to link all the hooks to this file */ + struct list_head f_ep_links; ++ struct list_head f_tfile_llink; + #endif /* #ifdef CONFIG_EPOLL */ + struct address_space *f_mapping; + #ifdef CONFIG_DEBUG_WRITECOUNT +-- +1.7.6.4 + diff --git a/kernel.spec b/kernel.spec index 5719e125f..e100c2026 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 0 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -665,6 +665,7 @@ Patch12204: linux-2.6-enable-more-pci-autosuspend.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13001: epoll-fix-spurious-lockdep-warnings.patch +Patch13002: epoll-limit-paths.patch Patch13010: iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch @@ -1252,6 +1253,7 @@ ApplyPatch x86-p4-make-watchdog-and-perf-work-together.patch ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch epoll-fix-spurious-lockdep-warnings.patch +ApplyPatch epoll-limit-paths.patch ApplyPatch iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch @@ -1903,6 +1905,9 @@ fi # and build. %changelog +* Tue Oct 25 2011 Josh Boyer +- CVE-2011-1083: excessive in kernel CPU consumption when creating large nested epoll structures (rhbz 748668) + * Tue Oct 25 2011 Josh Boyer - Linux 3.0.8 stable release From 8cbfe5c222a243530b41a5dc411aae818f425e38 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 25 Oct 2011 13:52:02 -0400 Subject: [PATCH 192/397] CVE-2011-3347: be2net: promiscuous mode and non-member VLAN packets DoS (rhbz 748691) --- be2net-move-to-new-vlan-model.patch | 107 ++++++++++++++++++ ...r-vlan-pkts-not-received-in-promisco.patch | 63 +++++++++++ ...-remove-bogus-unlikely-on-vlan-check.patch | 39 +++++++ kernel.spec | 11 ++ 4 files changed, 220 insertions(+) create mode 100644 be2net-move-to-new-vlan-model.patch create mode 100644 be2net-non-member-vlan-pkts-not-received-in-promisco.patch create mode 100644 benet-remove-bogus-unlikely-on-vlan-check.patch diff --git a/be2net-move-to-new-vlan-model.patch b/be2net-move-to-new-vlan-model.patch new file mode 100644 index 000000000..781297144 --- /dev/null +++ b/be2net-move-to-new-vlan-model.patch @@ -0,0 +1,107 @@ +From 1447378e3da1b56bb5c7fb1b1bc9b85e061447e7 Mon Sep 17 00:00:00 2001 +From: Ajit Khaparde +Date: Tue, 12 Jul 2011 22:10:01 -0700 +Subject: [PATCH 1/3] be2net: move to new vlan model + +Signed-off-by: Ajit Khaparde +Signed-off-by: David S. Miller +--- + drivers/net/benet/be.h | 1 - + drivers/net/benet/be_main.c | 34 +++++++++------------------------- + 2 files changed, 9 insertions(+), 26 deletions(-) + +diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h +index a7db870..5112000 100644 +--- a/drivers/net/benet/be.h ++++ b/drivers/net/benet/be.h +@@ -332,7 +332,6 @@ struct be_adapter { + u8 eq_next_idx; + struct be_drv_stats drv_stats; + +- struct vlan_group *vlan_grp; + u16 vlans_added; + u16 max_vlans; /* Number of vlans supported */ + u8 vlan_tag[VLAN_N_VID]; +diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c +index a485f7f..146e420 100644 +--- a/drivers/net/benet/be_main.c ++++ b/drivers/net/benet/be_main.c +@@ -648,7 +648,7 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, + AMAP_SET_BITS(struct amap_eth_hdr_wrb, udpcs, hdr, 1); + } + +- if (adapter->vlan_grp && vlan_tx_tag_present(skb)) { ++ if (vlan_tx_tag_present(skb)) { + AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1); + vlan_tag = vlan_tx_tag_get(skb); + vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; +@@ -842,13 +842,6 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num) + return status; + } + +-static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp) +-{ +- struct be_adapter *adapter = netdev_priv(netdev); +- +- adapter->vlan_grp = grp; +-} +- + static void be_vlan_add_vid(struct net_device *netdev, u16 vid) + { + struct be_adapter *adapter = netdev_priv(netdev); +@@ -867,7 +860,6 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) + struct be_adapter *adapter = netdev_priv(netdev); + + adapter->vlans_added--; +- vlan_group_set_device(adapter->vlan_grp, vid, NULL); + + if (!be_physfn(adapter)) + return; +@@ -1196,16 +1188,10 @@ static void be_rx_compl_process(struct be_adapter *adapter, + skb->rxhash = rxcp->rss_hash; + + +- if (unlikely(rxcp->vlanf)) { +- if (!adapter->vlan_grp || adapter->vlans_added == 0) { +- kfree_skb(skb); +- return; +- } +- vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, +- rxcp->vlan_tag); +- } else { +- netif_receive_skb(skb); +- } ++ if (unlikely(rxcp->vlanf)) ++ __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag); ++ ++ netif_receive_skb(skb); + } + + /* Process the RX completion indicated by rxcp when GRO is enabled */ +@@ -1259,11 +1245,10 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, + if (adapter->netdev->features & NETIF_F_RXHASH) + skb->rxhash = rxcp->rss_hash; + +- if (likely(!rxcp->vlanf)) +- napi_gro_frags(&eq_obj->napi); +- else +- vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, +- rxcp->vlan_tag); ++ if (unlikely(rxcp->vlanf)) ++ __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag); ++ ++ napi_gro_frags(&eq_obj->napi); + } + + static void be_parse_rx_compl_v1(struct be_adapter *adapter, +@@ -2901,7 +2886,6 @@ static struct net_device_ops be_netdev_ops = { + .ndo_set_mac_address = be_mac_addr_set, + .ndo_change_mtu = be_change_mtu, + .ndo_validate_addr = eth_validate_addr, +- .ndo_vlan_rx_register = be_vlan_register, + .ndo_vlan_rx_add_vid = be_vlan_add_vid, + .ndo_vlan_rx_kill_vid = be_vlan_rem_vid, + .ndo_set_vf_mac = be_set_vf_mac, +-- +1.7.6.4 + diff --git a/be2net-non-member-vlan-pkts-not-received-in-promisco.patch b/be2net-non-member-vlan-pkts-not-received-in-promisco.patch new file mode 100644 index 000000000..866473efd --- /dev/null +++ b/be2net-non-member-vlan-pkts-not-received-in-promisco.patch @@ -0,0 +1,63 @@ +From c0e64ef4899df4cedc872871e54e2c069d29e519 Mon Sep 17 00:00:00 2001 +From: Sathya Perla +Date: Tue, 2 Aug 2011 19:57:43 +0000 +Subject: [PATCH] be2net: non-member vlan pkts not received in promiscous mode + +While configuring promiscous mode, explicitly set the +VLAN_PROMISCOUS bit to make this happen. When switching off +promiscous mode, re-program the vids. + +Signed-off-by: Xavier Selvin +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/benet/be_cmds.c | 6 ++++-- + drivers/net/benet/be_main.c | 7 +++++++ + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c +index 1c25dbd..73fd949 100644 +--- a/drivers/net/benet/be_cmds.c ++++ b/drivers/net/benet/be_cmds.c +@@ -1586,9 +1586,11 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, bool en) + OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req)); + + req->if_id = cpu_to_le32(adapter->if_handle); +- req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS); ++ req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS ++ | BE_IF_FLAGS_VLAN_PROMISCUOUS); + if (en) +- req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS); ++ req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS ++ | BE_IF_FLAGS_VLAN_PROMISCUOUS); + + sge->pa_hi = cpu_to_le32(upper_32_bits(promiscous_cmd.dma)); + sge->pa_lo = cpu_to_le32(promiscous_cmd.dma & 0xFFFFFFFF); +diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c +index 3b2c5e6..32a5b11 100644 +--- a/drivers/net/benet/be_main.c ++++ b/drivers/net/benet/be_main.c +@@ -728,6 +728,10 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num) + status = be_cmd_vlan_config(adapter, if_handle, vtag, 1, 1, 0); + } + ++ /* No need to further configure vids if in promiscuous mode */ ++ if (adapter->promiscuous) ++ return 0; ++ + if (adapter->vlans_added <= adapter->max_vlans) { + /* Construct VLAN Table to give to HW */ + for (i = 0; i < VLAN_N_VID; i++) { +@@ -787,6 +791,9 @@ static void be_set_multicast_list(struct net_device *netdev) + if (adapter->promiscuous) { + adapter->promiscuous = false; + be_cmd_promiscuous_config(adapter, false); ++ ++ if (adapter->vlans_added) ++ be_vid_config(adapter, false, 0); + } + + /* Enable multicast promisc if num configured exceeds what we support */ +-- +1.7.6.4 + diff --git a/benet-remove-bogus-unlikely-on-vlan-check.patch b/benet-remove-bogus-unlikely-on-vlan-check.patch new file mode 100644 index 000000000..08c00817e --- /dev/null +++ b/benet-remove-bogus-unlikely-on-vlan-check.patch @@ -0,0 +1,39 @@ +From 82f15998fafe683add83f7a11b2e25f919b3cd2d Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Tue, 25 Oct 2011 13:47:16 -0400 +Subject: [PATCH] benet: remove bogus "unlikely" on vlan check + +Use of unlikely in this place is wrong. Remove it. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +Backported-by: Josh Boyer +--- + drivers/net/benet/be_main.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c +index c411bb1..6df0c7e 100644 +--- a/drivers/net/benet/be_main.c ++++ b/drivers/net/benet/be_main.c +@@ -1192,7 +1192,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, + skb->rxhash = rxcp->rss_hash; + + +- if (unlikely(rxcp->vlanf)) ++ if (rxcp->vlanf) + __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag); + + netif_receive_skb(skb); +@@ -1249,7 +1249,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, + if (adapter->netdev->features & NETIF_F_RXHASH) + skb->rxhash = rxcp->rss_hash; + +- if (unlikely(rxcp->vlanf)) ++ if (rxcp->vlanf) + __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag); + + napi_gro_frags(&eq_obj->napi); +-- +1.7.6.4 + diff --git a/kernel.spec b/kernel.spec index e100c2026..4a1f3181a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -709,6 +709,11 @@ Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch #rhbz 737108 Patch21030: platform-fix-samsung-brightness-min-max-calculations.patch +#rhbz 748691 +Patch21040: be2net-move-to-new-vlan-model.patch +Patch21041: be2net-non-member-vlan-pkts-not-received-in-promisco.patch +Patch21042: benet-remove-bogus-unlikely-on-vlan-check.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1285,6 +1290,11 @@ ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch #rhbz 737108 ApplyPatch platform-fix-samsung-brightness-min-max-calculations.patch +#rhbz 748691 +ApplyPatch be2net-move-to-new-vlan-model.patch +ApplyPatch be2net-non-member-vlan-pkts-not-received-in-promisco.patch +ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch + # END OF PATCH APPLICATIONS %endif @@ -1906,6 +1916,7 @@ fi %changelog * Tue Oct 25 2011 Josh Boyer +- CVE-2011-3347: be2net: promiscuous mode and non-member VLAN packets DoS (rhbz 748691) - CVE-2011-1083: excessive in kernel CPU consumption when creating large nested epoll structures (rhbz 748668) * Tue Oct 25 2011 Josh Boyer From 2725a26b33a74905f063f961ced90d64589f342a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 26 Oct 2011 09:18:09 -0400 Subject: [PATCH 193/397] Add patch to fix XFS memory corruption (rhbz 749166) --- kernel.spec | 9 +++- ...le-memory-corruption-in-xfs_readlink.patch | 43 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch diff --git a/kernel.spec b/kernel.spec index 4a1f3181a..811d0f59a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -714,6 +714,9 @@ Patch21040: be2net-move-to-new-vlan-model.patch Patch21041: be2net-non-member-vlan-pkts-not-received-in-promisco.patch Patch21042: benet-remove-bogus-unlikely-on-vlan-check.patch +#rhbz 749166 +Patch21050: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1135,6 +1138,7 @@ ApplyPatch linux-2.6-32bit-mmap-exec-randomization.patch # ext4 # xfs +ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch # btrfs @@ -1915,6 +1919,9 @@ fi # and build. %changelog +* Wed Oct 26 2011 Josh Boyer +- Add patch to fix XFS memory corruption (rhbz 749166) + * Tue Oct 25 2011 Josh Boyer - CVE-2011-3347: be2net: promiscuous mode and non-member VLAN packets DoS (rhbz 748691) - CVE-2011-1083: excessive in kernel CPU consumption when creating large nested epoll structures (rhbz 748668) diff --git a/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch b/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch new file mode 100644 index 000000000..319f80dc5 --- /dev/null +++ b/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch @@ -0,0 +1,43 @@ +From cbee73333a2d05c274240dff5de1b4bb74bfb497 Mon Sep 17 00:00:00 2001 +From: Carlos Maiolino +Date: Tue, 18 Oct 2011 02:18:58 -0200 +Subject: [PATCH] Fix possible memory corruption in xfs_readlink + +Fixes a possible memory corruption when the link is larger than +MAXPATHLEN and XFS_DEBUG is not enabled. This also remove the +S_ISLNK assert, since the inode mode is checked previously in +xfs_readlink_by_handle() and via VFS. + +Signed-off-by: Carlos Maiolino +--- + fs/xfs/xfs_vnodeops.c | 10 +++++++--- + 1 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c +index 6197207..111870b 100644 +--- a/fs/xfs/xfs_vnodeops.c ++++ b/fs/xfs/xfs_vnodeops.c +@@ -545,13 +545,17 @@ xfs_readlink( + + xfs_ilock(ip, XFS_ILOCK_SHARED); + +- ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK); +- ASSERT(ip->i_d.di_size <= MAXPATHLEN); +- + pathlen = ip->i_d.di_size; + if (!pathlen) + goto out; + ++ if (pathlen > MAXPATHLEN) { ++ xfs_alert(mp, "%s: inode (%llu) symlink length (%d) too long", ++ __func__, (unsigned long long)ip->i_ino, pathlen); ++ ASSERT(0); ++ return XFS_ERROR(EFSCORRUPTED); ++ } ++ + if (ip->i_df.if_flags & XFS_IFINLINE) { + memcpy(link, ip->i_df.if_u1.if_data, pathlen); + link[pathlen] = '\0'; +-- +1.7.6.4 + From ae6e0e8643bb47a1f68c9d65020a7644dc3beb4f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 26 Oct 2011 12:22:48 -0400 Subject: [PATCH 194/397] Edit changelog to reflect CVE-2011-4077 --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 811d0f59a..986dbdede 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1920,7 +1920,7 @@ fi %changelog * Wed Oct 26 2011 Josh Boyer -- Add patch to fix XFS memory corruption (rhbz 749166) +- CVE-2011-4077: xfs: potential buffer overflow in xfs_readlink() (rhbz 749166) * Tue Oct 25 2011 Josh Boyer - CVE-2011-3347: be2net: promiscuous mode and non-member VLAN packets DoS (rhbz 748691) From d40de0083f32fe2edc2f57fbd3d2ab9d26fcb824 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 26 Oct 2011 12:25:25 -0400 Subject: [PATCH 195/397] Add verrel to changelog --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 986dbdede..baa44dd66 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1919,7 +1919,7 @@ fi # and build. %changelog -* Wed Oct 26 2011 Josh Boyer +* Wed Oct 26 2011 Josh Boyer 2.6.40.8-2 - CVE-2011-4077: xfs: potential buffer overflow in xfs_readlink() (rhbz 749166) * Tue Oct 25 2011 Josh Boyer From 08e5f6190949d3dc32c6e83c8e2acab7e49ab925 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 28 Oct 2011 15:53:11 -0400 Subject: [PATCH 196/397] Shutup floppy.c. Abrt files enough bugs as it is (rhbz 749887) --- floppy-drop-disable_hlt-warning.patch | 13 +++++++++++++ kernel.spec | 7 ++++++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 floppy-drop-disable_hlt-warning.patch diff --git a/floppy-drop-disable_hlt-warning.patch b/floppy-drop-disable_hlt-warning.patch new file mode 100644 index 000000000..8f0849e1e --- /dev/null +++ b/floppy-drop-disable_hlt-warning.patch @@ -0,0 +1,13 @@ +diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c +index 9955a53..aef66d1 100644 +--- a/drivers/block/floppy.c ++++ b/drivers/block/floppy.c +@@ -1038,7 +1038,7 @@ static void floppy_disable_hlt(void) + { + unsigned long flags; + +- WARN_ONCE(1, "floppy_disable_hlt() scheduled for removal in 2012"); ++ printk(KERN_INFO "floppy_disable_hlt() scheduled for removal in 2012"); + spin_lock_irqsave(&floppy_hlt_lock, flags); + if (!hlt_disabled) { + hlt_disabled = 1; diff --git a/kernel.spec b/kernel.spec index baa44dd66..4e0718b1a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -594,6 +594,7 @@ Patch452: linux-2.6.30-no-pcspkr-modalias.patch Patch460: linux-2.6-serial-460800.patch Patch470: die-floppy-die.patch +Patch471: floppy-drop-disable_hlt-warning.patch Patch510: linux-2.6-silence-noise.patch Patch530: linux-2.6-silence-fbcon-logo.patch @@ -1186,6 +1187,7 @@ ApplyPatch linux-2.6-input-kill-stupid-messages.patch # stop floppy.ko from autoloading during udev... ApplyPatch die-floppy-die.patch +ApplyPatch floppy-drop-disable_hlt-warning.patch ApplyPatch linux-2.6.30-no-pcspkr-modalias.patch @@ -1919,6 +1921,9 @@ fi # and build. %changelog +* Fri Oct 28 2011 Josh Boyer +- Add patch to prevent tracebacks on a warning in floppy.c (rhbz 749887) + * Wed Oct 26 2011 Josh Boyer 2.6.40.8-2 - CVE-2011-4077: xfs: potential buffer overflow in xfs_readlink() (rhbz 749166) From 38450608c90a1a98ff72f4a6a9d1bdca12402421 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 31 Oct 2011 21:01:48 -0400 Subject: [PATCH 197/397] Add patch to fix integer overflow of points in oom_badness (rhbz 750402) --- kernel.spec | 8 ++ oom-fix-integer-overflow-of-points.patch | 100 +++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 oom-fix-integer-overflow-of-points.patch diff --git a/kernel.spec b/kernel.spec index 4e0718b1a..5625d80f3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -718,6 +718,8 @@ Patch21042: benet-remove-bogus-unlikely-on-vlan-check.patch #rhbz 749166 Patch21050: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch +Patch21070: oom-fix-integer-overflow-of-points.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1301,6 +1303,9 @@ ApplyPatch be2net-move-to-new-vlan-model.patch ApplyPatch be2net-non-member-vlan-pkts-not-received-in-promisco.patch ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch +#rhbz 750402 +ApplyPatch oom-fix-integer-overflow-of-points.patch + # END OF PATCH APPLICATIONS %endif @@ -1921,6 +1926,9 @@ fi # and build. %changelog +* Mon Oct 31 2011 Josh Boyer +- Add patch to fix integer overflow of points in oom_badness (rhbz 750402) + * Fri Oct 28 2011 Josh Boyer - Add patch to prevent tracebacks on a warning in floppy.c (rhbz 749887) diff --git a/oom-fix-integer-overflow-of-points.patch b/oom-fix-integer-overflow-of-points.patch new file mode 100644 index 000000000..02f6a8f72 --- /dev/null +++ b/oom-fix-integer-overflow-of-points.patch @@ -0,0 +1,100 @@ + +Delivered-To: jwboyer@gmail.com +Received: by 10.220.45.11 with SMTP id c11cs62970vcf; + Mon, 31 Oct 2011 08:56:49 -0700 (PDT) +Received: by 10.101.15.19 with SMTP id s19mr2706064ani.103.1320076596057; + Mon, 31 Oct 2011 08:56:36 -0700 (PDT) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id x8si7676575ani.27.2011.10.31.08.56.32; + Mon, 31 Oct 2011 08:56:36 -0700 (PDT) +Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=linux-kernel-owner@vger.kernel.org +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S934545Ab1JaP4X (ORCPT + 99 others); + Mon, 31 Oct 2011 11:56:23 -0400 +Received: from mx1.redhat.com ([209.132.183.28]:23653 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S934538Ab1JaP4X (ORCPT ); + Mon, 31 Oct 2011 11:56:23 -0400 +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p9VFuHOO027543 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Mon, 31 Oct 2011 11:56:18 -0400 +Received: from dhcp-26-164.brq.redhat.com (dhcp-26-164.brq.redhat.com [10.34.26.164]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p9VFuEK3018476; + Mon, 31 Oct 2011 11:56:15 -0400 +From: Frantisek Hrbata +To: rientjes@google.com +Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, + akpm@linux-foundation.org, kosaki.motohiro@jp.fujitsu.com, + oleg@redhat.com, minchan.kim@gmail.com, stable@kernel.org, + eteo@redhat.com, pmatouse@redhat.com +Subject: [PATCH v2] oom: fix integer overflow of points in oom_badness +Date: Mon, 31 Oct 2011 16:56:09 +0100 +Message-Id: <1320076569-23872-1-git-send-email-fhrbata@redhat.com> +In-Reply-To: <1320048865-13175-1-git-send-email-fhrbata@redhat.com> +References: <1320048865-13175-1-git-send-email-fhrbata@redhat.com> +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org + +An integer overflow will happen on 64bit archs if task's sum of rss, swapents +and nr_ptes exceeds (2^31)/1000 value. This was introduced by commit + +f755a04 oom: use pte pages in OOM score + +where the oom score computation was divided into several steps and it's no +longer computed as one expression in unsigned long(rss, swapents, nr_pte are +unsigned long), where the result value assigned to points(int) is in +range(1..1000). So there could be an int overflow while computing + +176 points *= 1000; + +and points may have negative value. Meaning the oom score for a mem hog task +will be one. + +196 if (points <= 0) +197 return 1; + +For example: +[ 3366] 0 3366 35390480 24303939 5 0 0 oom01 +Out of memory: Kill process 3366 (oom01) score 1 or sacrifice child + +Here the oom1 process consumes more than 24303939(rss)*4096~=92GB physical +memory, but it's oom score is one. + +In this situation the mem hog task is skipped and oom killer kills another and +most probably innocent task with oom score greater than one. + +The points variable should be of type long instead of int to prevent the int +overflow. + +Signed-off-by: Frantisek Hrbata +--- + mm/oom_kill.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/mm/oom_kill.c b/mm/oom_kill.c +index 626303b..e9a1785 100644 +--- a/mm/oom_kill.c ++++ b/mm/oom_kill.c +@@ -162,7 +162,7 @@ static bool oom_unkillable_task(struct task_struct *p, + unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem, + const nodemask_t *nodemask, unsigned long totalpages) + { +- int points; ++ long points; + + if (oom_unkillable_task(p, mem, nodemask)) + return 0; +-- +1.7.6.4 + +-- +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/ From 2c7438bdcc753eed29f54c0eebc3d1b36768a07e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 31 Oct 2011 21:10:19 -0400 Subject: [PATCH 198/397] Add CVE number in changelog (rhbz 750402) --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 5625d80f3..2208c584b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1927,7 +1927,7 @@ fi %changelog * Mon Oct 31 2011 Josh Boyer -- Add patch to fix integer overflow of points in oom_badness (rhbz 750402) +-CVE-2011-4097: oom_badness() integer overflow (rhbz 750402) * Fri Oct 28 2011 Josh Boyer - Add patch to prevent tracebacks on a warning in floppy.c (rhbz 749887) From 158235aeb97dc1a7814a6e47523ea6dfe8128f35 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 1 Nov 2011 12:55:56 -0400 Subject: [PATCH 199/397] Add another Sony laptop to the nonvs blacklist. (rhbz 641789) --- acpi-sony-nonvs-blacklist.patch | 19 +++++++++++++++++++ kernel.spec | 5 ++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/acpi-sony-nonvs-blacklist.patch b/acpi-sony-nonvs-blacklist.patch index f332c6443..db500e8bf 100644 --- a/acpi-sony-nonvs-blacklist.patch +++ b/acpi-sony-nonvs-blacklist.patch @@ -17,3 +17,22 @@ index 3ed80b2..17fc718 100644 .ident = "Sony Vaio VGN-SR11M", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), +diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c +index 0e46fae..6d9a3ab 100644 +--- a/drivers/acpi/sleep.c ++++ b/drivers/acpi/sleep.c +@@ -398,6 +398,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { + }, + { + .callback = init_nvs_nosave, ++ .ident = "Sony Vaio VPCEB17FX", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"), ++ }, ++ }, ++ { ++ .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-SR11M", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), diff --git a/kernel.spec b/kernel.spec index 2208c584b..0f45da3de 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1926,8 +1926,11 @@ fi # and build. %changelog +* Tue Nov 01 2011 Dave Jones 2.6.40.8-4 +- Add another Sony laptop to the nonvs blacklist. (rhbz 641789) + * Mon Oct 31 2011 Josh Boyer --CVE-2011-4097: oom_badness() integer overflow (rhbz 750402) +- CVE-2011-4097: oom_badness() integer overflow (rhbz 750402) * Fri Oct 28 2011 Josh Boyer - Add patch to prevent tracebacks on a warning in floppy.c (rhbz 749887) From e517e6666bf4ab3ea30ce96a5df4ad879f82a5a8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 1 Nov 2011 11:09:01 -0400 Subject: [PATCH 200/397] Drop x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid (rhbz 748516) Discussed this with Matt Fleming and Matthew Garrett. The patch was added to fix an oops case on 32-bit EFI machines, but we don't support 32-bit EFI and it is causing regressions on 64-bit EFI Macs. Drop the patch for now. --- kernel.spec | 9 +- ...a-with-an-ioremap-address-is-invalid.patch | 211 ------------------ 2 files changed, 5 insertions(+), 215 deletions(-) delete mode 100644 x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch diff --git a/kernel.spec b/kernel.spec index 0f45da3de..66ba36fe4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -656,7 +656,6 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch Patch12024: usb-add-quirk-for-logitech-webcams.patch Patch12025: crypto-register-cryptd-first.patch -Patch12027: x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch Patch12028: x86-p4-make-watchdog-and-perf-work-together.patch # Runtime power management @@ -1259,7 +1258,6 @@ ApplyPatch add-appleir-usb-driver.patch ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch ApplyPatch crypto-register-cryptd-first.patch -ApplyPatch x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch ApplyPatch x86-p4-make-watchdog-and-perf-work-together.patch # rhbz#605888 @@ -1926,7 +1924,10 @@ fi # and build. %changelog -* Tue Nov 01 2011 Dave Jones 2.6.40.8-4 +* Tue Nov 01 2011 Josh Boyer 2.6.40.8-4 +- Drop x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid (rhbz 748516) + +* Tue Nov 01 2011 Dave Jones - Add another Sony laptop to the nonvs blacklist. (rhbz 641789) * Mon Oct 31 2011 Josh Boyer diff --git a/x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch b/x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch deleted file mode 100644 index f05567fe3..000000000 --- a/x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch +++ /dev/null @@ -1,211 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Matt Fleming -Newsgroups: gmane.linux.kernel -Subject: [PATCH v2] x86, efi: Calling __pa() with an ioremap'd address is invalid -Date: Fri, 14 Oct 2011 12:36:45 +0100 -Lines: 160 -Approved: news@gmane.org -Message-ID: <1318592205-11193-1-git-send-email-matt@console-pimps.org> -NNTP-Posting-Host: lo.gmane.org -X-Trace: dough.gmane.org 1318592224 30879 80.91.229.12 (14 Oct 2011 11:37:04 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Fri, 14 Oct 2011 11:37:04 +0000 (UTC) -Cc: Thomas Gleixner , Ingo Molnar , - "H. Peter Anvin" , Zhang Rui , - Huang Ying , - linux-kernel@vger.kernel.org -To: Matthew Garrett -Original-X-From: linux-kernel-owner@vger.kernel.org Fri Oct 14 13:36:59 2011 -Return-path: -Envelope-to: glk-linux-kernel-3@lo.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1REg4Q-0001UQ-SA - for glk-linux-kernel-3@lo.gmane.org; Fri, 14 Oct 2011 13:36:59 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1755420Ab1JNLgv (ORCPT ); - Fri, 14 Oct 2011 07:36:51 -0400 -Original-Received: from arkanian.console-pimps.org ([212.110.184.194]:46859 "EHLO - arkanian.console-pimps.org" rhost-flags-OK-OK-OK-OK) - by vger.kernel.org with ESMTP id S1751315Ab1JNLgu (ORCPT - ); - Fri, 14 Oct 2011 07:36:50 -0400 -Original-Received: by arkanian.console-pimps.org (Postfix, from userid 1002) - id 443C1C0009; Fri, 14 Oct 2011 12:36:49 +0100 (BST) -X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on - arkanian.vm.bytemark.co.uk -X-Spam-Level: -X-Spam-Status: No, score=-5.3 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00 - autolearn=ham version=3.2.5 -Original-Received: from localhost (02ddb86b.bb.sky.com [2.221.184.107]) - by arkanian.console-pimps.org (Postfix) with ESMTPSA id F0D40C0008; - Fri, 14 Oct 2011 12:36:47 +0100 (BST) -X-Mailer: git-send-email 1.7.4.4 -Original-Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel:1203294 -Archived-At: - -From: Matt Fleming - -If we encounter an efi_memory_desc_t without EFI_MEMORY_WB set in -->attribute we currently call set_memory_uc(), which in turn calls -__pa() on a potentially ioremap'd address. On CONFIG_X86_32 this is -invalid, resulting in the following oops, - - BUG: unable to handle kernel paging request at f7f22280 - IP: [] reserve_ram_pages_type+0x89/0x210 - *pdpt = 0000000001978001 *pde = 0000000001ffb067 *pte = 0000000000000000 - Oops: 0000 [#1] PREEMPT SMP - Modules linked in: - - Pid: 0, comm: swapper Not tainted 3.0.0-acpi-efi-0805 #3 - EIP: 0060:[] EFLAGS: 00010202 CPU: 0 - EIP is at reserve_ram_pages_type+0x89/0x210 - EAX: 0070e280 EBX: 38714000 ECX: f7814000 EDX: 00000000 - ESI: 00000000 EDI: 38715000 EBP: c189fef0 ESP: c189fea8 - DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 - Process swapper (pid: 0, ti=c189e000 task=c18bbe60 task.ti=c189e000) - Stack: - 80000200 ff108000 00000000 c189ff00 00038714 00000000 00000000 c189fed0 - c104f8ca 00038714 00000000 00038715 00000000 00000000 00038715 00000000 - 00000010 38715000 c189ff48 c1025aff 38715000 00000000 00000010 00000000 - Call Trace: - [] ? page_is_ram+0x1a/0x40 - [] reserve_memtype+0xdf/0x2f0 - [] set_memory_uc+0x49/0xa0 - [] efi_enter_virtual_mode+0x1c2/0x3aa - [] start_kernel+0x291/0x2f2 - [] ? loglevel+0x1b/0x1b - [] i386_start_kernel+0xbf/0xc8 - -So, if we're ioremap'ing an address range let's setup the mapping with -the correct caching attribute instead of modifying it after the fact. - -Also, take this opportunity to unify the 32/64-bit efi_ioremap() -implementations because they can both be implemented with -ioremap_{cache,nocache}. When asked about the original reason behind -using init_memory_mapping() for the 64-bit version Huang Ying said, - - "The intention of init_memory_mapping() usage is to make EFI virtual - address unchanged after kexec. But in fact, init_memory_mapping() - can not handle some memory range, so ioremap_xxx() is introduced as - a fix. Now we decide to use ioremap_xxx() anyway and use some other - scheme for kexec support, so init_memory_mapping() here is - unnecessary. IMHO, init_memory_mapping() is not as good as - ioremap_xxx() here." - -And because efi_ioremap() now consists of 4 lines, let's just inline -it directly into the one callsite in efi_enter_virtual_mode(). - -Cc: Thomas Gleixner -Cc: Ingo Molnar -Cc: H. Peter Anvin -Cc: Matthew Garrett -Cc: Zhang Rui -Cc: Huang Ying -Cc: stable@kernel.org -Signed-off-by: Matt Fleming ---- - arch/x86/include/asm/efi.h | 5 ----- - arch/x86/platform/efi/efi.c | 24 ++++++++++++++---------- - arch/x86/platform/efi/efi_64.c | 17 ----------------- - 3 files changed, 14 insertions(+), 32 deletions(-) - -diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h -index 7093e4a..b8d8bfc 100644 ---- a/arch/x86/include/asm/efi.h -+++ b/arch/x86/include/asm/efi.h -@@ -33,8 +33,6 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...); - #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \ - efi_call_virt(f, a1, a2, a3, a4, a5, a6) - --#define efi_ioremap(addr, size, type) ioremap_cache(addr, size) -- - #else /* !CONFIG_X86_32 */ - - extern u64 efi_call0(void *fp); -@@ -84,9 +82,6 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3, - efi_call6((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ - (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6)) - --extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, -- u32 type); -- - #endif /* CONFIG_X86_32 */ - - extern int add_efi_memmap; -diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c -index 3ae4128..6ea011c 100644 ---- a/arch/x86/platform/efi/efi.c -+++ b/arch/x86/platform/efi/efi.c -@@ -670,10 +670,21 @@ void __init efi_enter_virtual_mode(void) - end_pfn = PFN_UP(end); - if (end_pfn <= max_low_pfn_mapped - || (end_pfn > (1UL << (32 - PAGE_SHIFT)) -- && end_pfn <= max_pfn_mapped)) -+ && end_pfn <= max_pfn_mapped)) { - va = __va(md->phys_addr); -- else -- va = efi_ioremap(md->phys_addr, size, md->type); -+ -+ if (!(md->attribute & EFI_MEMORY_WB)) { -+ addr = (u64) (unsigned long)va; -+ npages = md->num_pages; -+ memrange_efi_to_native(&addr, &npages); -+ set_memory_uc(addr, npages); -+ } -+ } else { -+ if (!(md->attribute & EFI_MEMORY_WB)) -+ va = ioremap_nocache(md->phys_addr, size); -+ else -+ va = ioremap_cache(md->phys_addr, size); -+ } - - md->virt_addr = (u64) (unsigned long) va; - -@@ -683,13 +694,6 @@ void __init efi_enter_virtual_mode(void) - continue; - } - -- if (!(md->attribute & EFI_MEMORY_WB)) { -- addr = md->virt_addr; -- npages = md->num_pages; -- memrange_efi_to_native(&addr, &npages); -- set_memory_uc(addr, npages); -- } -- - systab = (u64) (unsigned long) efi_phys.systab; - if (md->phys_addr <= systab && systab < end) { - systab += md->virt_addr - md->phys_addr; -diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c -index ac3aa54..312250c 100644 ---- a/arch/x86/platform/efi/efi_64.c -+++ b/arch/x86/platform/efi/efi_64.c -@@ -80,20 +80,3 @@ void __init efi_call_phys_epilog(void) - local_irq_restore(efi_flags); - early_code_mapping_set_exec(0); - } -- --void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, -- u32 type) --{ -- unsigned long last_map_pfn; -- -- if (type == EFI_MEMORY_MAPPED_IO) -- return ioremap(phys_addr, size); -- -- last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size); -- if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) { -- unsigned long top = last_map_pfn << PAGE_SHIFT; -- efi_ioremap(top, size - (top - phys_addr), type); -- } -- -- return (void __iomem *)__va(phys_addr); --} --- -1.7.4.4 - From 5937336acbfdb7cceffa18a189ef3a963ef4b296 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 1 Nov 2011 14:09:58 -0400 Subject: [PATCH 201/397] allow building the perf rpm for ARM (rhbz 741325) --- kernel.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 66ba36fe4..6bdada864 100644 --- a/kernel.spec +++ b/kernel.spec @@ -352,13 +352,13 @@ Summary: The Linux kernel # we build a up kernel on armv5tel. its used for qemu. %ifnarch armv5tel %define with_up 0 +%define with_perf 0 %endif # we only build headers on the base arm arches # just like we used to only build them on i386 for x86 %ifnarch armv5tel armv7hl %define with_headers 0 %endif -%define with_perf 0 %endif %if %{nopatches} @@ -1924,6 +1924,9 @@ fi # and build. %changelog +* Tue Nov 01 2011 Dave Jones 2.6.40.8-5 +- allow building the perf rpm for ARM (rhbz 741325) + * Tue Nov 01 2011 Josh Boyer 2.6.40.8-4 - Drop x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid (rhbz 748516) From 6bb8ae898aae45c0a1c24d0a3c9087082abd3b8f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 2 Nov 2011 09:55:36 -0400 Subject: [PATCH 202/397] Add patch to fix oops when removing wmi module (rhbz 706574) --- ...rly-cleanup-devices-to-avoid-crashes.patch | 41 +++++++++++++++++++ kernel.spec | 11 ++++- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 WMI-properly-cleanup-devices-to-avoid-crashes.patch diff --git a/WMI-properly-cleanup-devices-to-avoid-crashes.patch b/WMI-properly-cleanup-devices-to-avoid-crashes.patch new file mode 100644 index 000000000..1119d25f5 --- /dev/null +++ b/WMI-properly-cleanup-devices-to-avoid-crashes.patch @@ -0,0 +1,41 @@ +From 023b9565972a4a5e0f01b9aa32680af6e9b5c388 Mon Sep 17 00:00:00 2001 +From: Dmitry Torokhov +Date: Wed, 7 Sep 2011 15:00:02 -0700 +Subject: [PATCH] WMI: properly cleanup devices to avoid crashes + +We need to remove devices that we destroy from the list, otherwise +we'll crash if there are more than one "_WDG" methods in DSDT. + +This fixes https://bugzilla.kernel.org/show_bug.cgi?id=32052 + +Tested-by: Ilya Tumaykin +Cc: stable@kernel.org +Signed-off-by: Dmitry Torokhov +Acked-by: Carlos Corbacho +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/wmi.c | 6 +++++- + 1 files changed, 5 insertions(+), 1 deletions(-) + +diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c +index f23d5a8..9b88be4 100644 +--- a/drivers/platform/x86/wmi.c ++++ b/drivers/platform/x86/wmi.c +@@ -754,9 +754,13 @@ static void wmi_free_devices(void) + struct wmi_block *wblock, *next; + + /* Delete devices for all the GUIDs */ +- list_for_each_entry_safe(wblock, next, &wmi_block_list, list) ++ list_for_each_entry_safe(wblock, next, &wmi_block_list, list) { ++ list_del(&wblock->list); + if (wblock->dev.class) + device_unregister(&wblock->dev); ++ else ++ kfree(wblock); ++ } + } + + static bool guid_already_parsed(const char *guid_string) +-- +1.7.6.4 + diff --git a/kernel.spec b/kernel.spec index 6bdada864..87fc89abd 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -719,6 +719,9 @@ Patch21050: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch Patch21070: oom-fix-integer-overflow-of-points.patch +#rhbz 706574 +Patch21071: WMI-properly-cleanup-devices-to-avoid-crashes.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1304,6 +1307,9 @@ ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch #rhbz 750402 ApplyPatch oom-fix-integer-overflow-of-points.patch +#rhbz 706574 +ApplyPatch WMI-properly-cleanup-devices-to-avoid-crashes.patch + # END OF PATCH APPLICATIONS %endif @@ -1924,6 +1930,9 @@ fi # and build. %changelog +* Wed Nov 02 2011 Josh Boyer +- Add patch to fix oops when removing wmi module (rhbz 706574) + * Tue Nov 01 2011 Dave Jones 2.6.40.8-5 - allow building the perf rpm for ARM (rhbz 741325) From c7fa63c78c25bda3ac1af342dd45c96f6e148980 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 3 Nov 2011 09:35:03 -0400 Subject: [PATCH 203/397] Add patches queued for 3.2 for elantech driver (rhbz 728607) --- elantech.patch | 2116 ++++++++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 11 +- 2 files changed, 2126 insertions(+), 1 deletion(-) create mode 100644 elantech.patch diff --git a/elantech.patch b/elantech.patch new file mode 100644 index 000000000..255efd2b6 --- /dev/null +++ b/elantech.patch @@ -0,0 +1,2116 @@ +From 13ac768d9a8731c8b3bab7d6c86520f290272fe7 Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Fri, 9 Sep 2011 10:22:19 -0700 +Subject: Input: elantech - correct x, y value range for v2 hardware +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +x, y values are actually 12-bit long. Also update protocol document to +reflect the change. + +Signed-off-by: JJ Ding +Acked-by: Daniel Kurtz +Acked-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + Documentation/input/elantech.txt | 8 ++++---- + drivers/input/mouse/elantech.c | 8 ++++---- + 2 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt +index db798af..bce9941 100644 +--- a/Documentation/input/elantech.txt ++++ b/Documentation/input/elantech.txt +@@ -389,14 +389,14 @@ byte 0: + byte 1: + + bit 7 6 5 4 3 2 1 0 +- p7 p6 p5 p4 . x10 x9 x8 ++ p7 p6 p5 p4 x11 x10 x9 x8 + + byte 2: + + bit 7 6 5 4 3 2 1 0 + x7 x6 x5 x4 x3 x2 x1 x0 + +- x10..x0 = absolute x value (horizontal) ++ x11..x0 = absolute x value (horizontal) + + byte 3: + +@@ -420,7 +420,7 @@ byte 3: + byte 4: + + bit 7 6 5 4 3 2 1 0 +- p3 p1 p2 p0 . . y9 y8 ++ p3 p1 p2 p0 y11 y10 y9 y8 + + p7..p0 = pressure (not EF113) + +@@ -429,7 +429,7 @@ byte 5: + bit 7 6 5 4 3 2 1 0 + y7 y6 y5 y4 y3 y2 y1 y0 + +- y9..y0 = absolute y value (vertical) ++ y11..y0 = absolute y value (vertical) + + + 4.2.2 Two finger touch +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 3250356..da161da 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -290,15 +290,15 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + /* pass through... */ + case 1: + /* +- * byte 1: . . . . . x10 x9 x8 ++ * byte 1: . . . . x11 x10 x9 x8 + * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 + */ +- x1 = ((packet[1] & 0x07) << 8) | packet[2]; ++ x1 = ((packet[1] & 0x0f) << 8) | packet[2]; + /* +- * byte 4: . . . . . . y9 y8 ++ * byte 4: . . . . y11 y10 y9 y8 + * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 + */ +- y1 = ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5]); ++ y1 = ETP_YMAX_V2 - (((packet[4] & 0x0f) << 8) | packet[5]); + + input_report_abs(dev, ABS_X, x1); + input_report_abs(dev, ABS_Y, y1); +-- +1.7.6.4 + + +From c47c9334b4ebb6ecb565d9bf834df170fcd09484 Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Fri, 9 Sep 2011 10:22:58 -0700 +Subject: Input: elantech - get rid of ETP_2FT_* in elantech.h +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For two finger touches the coordinate of each finger gets reported +separately but with reduced resolution. + +With this change, we now have the same range for ST and MT data and +scale MT data because it has lower resolution to match ST. + +Suggested-by: Dmitry Torokhov +Signed-off-by: JJ Ding +Acked-by: Daniel Kurtz +Acked-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.c | 28 +++++++++++++--------------- + drivers/input/mouse/elantech.h | 11 ----------- + 2 files changed, 13 insertions(+), 26 deletions(-) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index da161da..cd8e2e5 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -273,11 +273,11 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + struct elantech_data *etd = psmouse->private; + struct input_dev *dev = psmouse->dev; + unsigned char *packet = psmouse->packet; +- unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0, width = 0, pres = 0; ++ unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0; ++ unsigned int width = 0, pres = 0; + + /* byte 0: n1 n0 . . . . R L */ + fingers = (packet[0] & 0xc0) >> 6; +- input_report_key(dev, BTN_TOUCH, fingers != 0); + + switch (fingers) { + case 3: +@@ -300,9 +300,6 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + */ + y1 = ETP_YMAX_V2 - (((packet[4] & 0x0f) << 8) | packet[5]); + +- input_report_abs(dev, ABS_X, x1); +- input_report_abs(dev, ABS_Y, y1); +- + pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); + width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); + break; +@@ -314,22 +311,18 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + * byte 0: . . ay8 ax8 . . . . + * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 + */ +- x1 = ((packet[0] & 0x10) << 4) | packet[1]; ++ x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2; + /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ +- y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); ++ y1 = ETP_YMAX_V2 - ++ ((((packet[0] & 0x20) << 3) | packet[2]) << 2); + /* + * byte 3: . . by8 bx8 . . . . + * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 + */ +- x2 = ((packet[3] & 0x10) << 4) | packet[4]; ++ x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2; + /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ +- y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); +- /* +- * For compatibility with the X Synaptics driver scale up +- * one coordinate and report as ordinary mouse movent +- */ +- input_report_abs(dev, ABS_X, x1 << 2); +- input_report_abs(dev, ABS_Y, y1 << 2); ++ y2 = ETP_YMAX_V2 - ++ ((((packet[3] & 0x20) << 3) | packet[5]) << 2); + + /* Unknown so just report sensible values */ + pres = 127; +@@ -337,6 +330,11 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + break; + } + ++ input_report_key(dev, BTN_TOUCH, fingers != 0); ++ if (fingers != 0) { ++ input_report_abs(dev, ABS_X, x1); ++ input_report_abs(dev, ABS_Y, y1); ++ } + elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); + input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); + input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); +diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h +index fabb2b9..1c5894e 100644 +--- a/drivers/input/mouse/elantech.h ++++ b/drivers/input/mouse/elantech.h +@@ -82,17 +82,6 @@ + #define ETP_WMIN_V2 0 + #define ETP_WMAX_V2 15 + +-/* +- * For two finger touches the coordinate of each finger gets reported +- * separately but with reduced resolution. +- */ +-#define ETP_2FT_FUZZ 4 +- +-#define ETP_2FT_XMIN ( 0 + ETP_2FT_FUZZ) +-#define ETP_2FT_XMAX (288 - ETP_2FT_FUZZ) +-#define ETP_2FT_YMIN ( 0 + ETP_2FT_FUZZ) +-#define ETP_2FT_YMAX (192 - ETP_2FT_FUZZ) +- + struct elantech_data { + unsigned char reg_10; + unsigned char reg_11; +-- +1.7.6.4 + + +From aa719e391c1769c93ec42a30daffa4ffa2a8503c Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Fri, 9 Sep 2011 10:26:16 -0700 +Subject: Input: elantech - use firmware provided x, y ranges +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +With newer hardware, the touchpad provides range info. +Let's use it. + +Signed-off-by: JJ Ding +Acked-by: Daniel Kurtz +Acked-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.c | 71 +++++++++++++++++++++++++++++++-------- + drivers/input/mouse/elantech.h | 3 +- + 2 files changed, 58 insertions(+), 16 deletions(-) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index cd8e2e5..296b6a6 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -223,7 +223,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) + input_report_abs(dev, ABS_X, + ((packet[1] & 0x0c) << 6) | packet[2]); + input_report_abs(dev, ABS_Y, +- ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3])); ++ etd->y_max - (((packet[1] & 0x03) << 8) | packet[3])); + } + + input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); +@@ -233,7 +233,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) + input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); + + if (etd->fw_version < 0x020000 && +- (etd->capabilities & ETP_CAP_HAS_ROCKER)) { ++ (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { + /* rocker up */ + input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); + /* rocker down */ +@@ -298,7 +298,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + * byte 4: . . . . y11 y10 y9 y8 + * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 + */ +- y1 = ETP_YMAX_V2 - (((packet[4] & 0x0f) << 8) | packet[5]); ++ y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); + + pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); + width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); +@@ -313,7 +313,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + */ + x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2; + /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ +- y1 = ETP_YMAX_V2 - ++ y1 = etd->y_max - + ((((packet[0] & 0x20) << 3) | packet[2]) << 2); + /* + * byte 3: . . by8 bx8 . . . . +@@ -321,7 +321,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + */ + x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2; + /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ +- y2 = ETP_YMAX_V2 - ++ y2 = etd->y_max - + ((((packet[3] & 0x20) << 3) | packet[5]) << 2); + + /* Unknown so just report sensible values */ +@@ -468,6 +468,41 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) + return rc; + } + ++static void elantech_set_range(struct psmouse *psmouse, ++ unsigned int *x_min, unsigned int *y_min, ++ unsigned int *x_max, unsigned int *y_max) ++{ ++ struct elantech_data *etd = psmouse->private; ++ int i; ++ ++ switch (etd->hw_version) { ++ case 1: ++ *x_min = ETP_XMIN_V1; ++ *y_min = ETP_YMIN_V1; ++ *x_max = ETP_XMAX_V1; ++ *y_max = ETP_YMAX_V1; ++ break; ++ ++ case 2: ++ if (etd->fw_version == 0x020800 || ++ etd->fw_version == 0x020b00 || ++ etd->fw_version == 0x020030) { ++ *x_min = ETP_XMIN_V2; ++ *y_min = ETP_YMIN_V2; ++ *x_max = ETP_XMAX_V2; ++ *y_max = ETP_YMAX_V2; ++ } else { ++ i = (etd->fw_version > 0x020800 && ++ etd->fw_version < 0x020900) ? 1 : 2; ++ *x_min = 0; ++ *y_min = 0; ++ *x_max = (etd->capabilities[1] - i) * 64; ++ *y_max = (etd->capabilities[2] - i) * 64; ++ } ++ break; ++ } ++} ++ + /* + * Set the appropriate event bits for the input subsystem + */ +@@ -475,6 +510,9 @@ static void elantech_set_input_params(struct psmouse *psmouse) + { + struct input_dev *dev = psmouse->dev; + struct elantech_data *etd = psmouse->private; ++ unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0; ++ ++ elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max); + + __set_bit(EV_KEY, dev->evbit); + __set_bit(EV_ABS, dev->evbit); +@@ -492,18 +530,18 @@ static void elantech_set_input_params(struct psmouse *psmouse) + case 1: + /* Rocker button */ + if (etd->fw_version < 0x020000 && +- (etd->capabilities & ETP_CAP_HAS_ROCKER)) { ++ (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { + __set_bit(BTN_FORWARD, dev->keybit); + __set_bit(BTN_BACK, dev->keybit); + } +- input_set_abs_params(dev, ABS_X, ETP_XMIN_V1, ETP_XMAX_V1, 0, 0); +- input_set_abs_params(dev, ABS_Y, ETP_YMIN_V1, ETP_YMAX_V1, 0, 0); ++ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); ++ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); + break; + + case 2: + __set_bit(BTN_TOOL_QUADTAP, dev->keybit); +- input_set_abs_params(dev, ABS_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); +- input_set_abs_params(dev, ABS_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); ++ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); ++ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); + if (etd->reports_pressure) { + input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, + ETP_PMAX_V2, 0, 0); +@@ -512,10 +550,12 @@ static void elantech_set_input_params(struct psmouse *psmouse) + } + __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); + input_mt_init_slots(dev, 2); +- input_set_abs_params(dev, ABS_MT_POSITION_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); +- input_set_abs_params(dev, ABS_MT_POSITION_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); ++ input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); ++ input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); + break; + } ++ ++ etd->y_max = y_max; + } + + struct elantech_attr_data { +@@ -769,13 +809,14 @@ int elantech_init(struct psmouse *psmouse) + pr_info("assuming hardware version %d, firmware version %d.%d.%d\n", + etd->hw_version, param[0], param[1], param[2]); + +- if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) { ++ if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, ++ etd->capabilities)) { + pr_err("failed to query capabilities.\n"); + goto init_fail; + } + pr_info("Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n", +- param[0], param[1], param[2]); +- etd->capabilities = param[0]; ++ etd->capabilities[0], etd->capabilities[1], ++ etd->capabilities[2]); + + /* + * This firmware suffers from misreporting coordinates when +diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h +index 1c5894e..b54ea27 100644 +--- a/drivers/input/mouse/elantech.h ++++ b/drivers/input/mouse/elantech.h +@@ -93,13 +93,14 @@ struct elantech_data { + unsigned char reg_25; + unsigned char reg_26; + unsigned char debug; +- unsigned char capabilities; ++ unsigned char capabilities[3]; + bool paritycheck; + bool jumpy_cursor; + bool reports_pressure; + unsigned char hw_version; + unsigned int fw_version; + unsigned int single_finger_reports; ++ unsigned int y_max; + unsigned char parity[256]; + }; + +-- +1.7.6.4 + + +From 91f395e84dc83707b01c69e297894dbf992a566e Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Fri, 9 Sep 2011 10:27:42 -0700 +Subject: Input: elantech - remove ETP_EDGE_FUZZ_V2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Don't try to be too clever and remove ETP_EDGE_FUZZ_V2. X, Y ranges +should be just the raw resolution of the device. Otherwise, they can +cause underflow on the Y axis. + +Suggested-by: Éric Piel +Signed-off-by: JJ Ding +Acked-by: Daniel Kurtz +Acked-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.h | 15 ++++++--------- + 1 files changed, 6 insertions(+), 9 deletions(-) + +diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h +index b54ea27..d9e6144 100644 +--- a/drivers/input/mouse/elantech.h ++++ b/drivers/input/mouse/elantech.h +@@ -66,16 +66,13 @@ + #define ETP_YMAX_V1 (384 - ETP_EDGE_FUZZ_V1) + + /* +- * It seems the resolution for hardware version 2 doubled. +- * Hence the X and Y ranges are doubled too. +- * The bezel around the pad also appears to be smaller ++ * The resolution for older v2 hardware doubled. ++ * (newer v2's firmware provides command so we can query) + */ +-#define ETP_EDGE_FUZZ_V2 8 +- +-#define ETP_XMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2) +-#define ETP_XMAX_V2 (1152 - ETP_EDGE_FUZZ_V2) +-#define ETP_YMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2) +-#define ETP_YMAX_V2 ( 768 - ETP_EDGE_FUZZ_V2) ++#define ETP_XMIN_V2 0 ++#define ETP_XMAX_V2 1152 ++#define ETP_YMIN_V2 0 ++#define ETP_YMAX_V2 768 + + #define ETP_PMIN_V2 0 + #define ETP_PMAX_V2 255 +-- +1.7.6.4 + + +From cc66bde05d267cce5a6f64d877e63036505cc31e Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Fri, 9 Sep 2011 10:28:04 -0700 +Subject: Input: elantech - packet checking for v2 hardware +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For v2 hardware, there is no real parity check, but we can still check +some constant bits for data integrity. + +Also rename elantech_check_parity_v1 to elantech_packet_check_v1 to make +these packet checking function names consistent. + +Signed-off-by: JJ Ding +Acked-by: Daniel Kurtz +Acked-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.c | 39 ++++++++++++++++++++++++++++++++++----- + 1 files changed, 34 insertions(+), 5 deletions(-) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 296b6a6..f2e3a2b 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -350,7 +350,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + input_sync(dev); + } + +-static int elantech_check_parity_v1(struct psmouse *psmouse) ++static int elantech_packet_check_v1(struct psmouse *psmouse) + { + struct elantech_data *etd = psmouse->private; + unsigned char *packet = psmouse->packet; +@@ -374,6 +374,34 @@ static int elantech_check_parity_v1(struct psmouse *psmouse) + etd->parity[packet[3]] == p3; + } + ++static int elantech_packet_check_v2(struct psmouse *psmouse) ++{ ++ struct elantech_data *etd = psmouse->private; ++ unsigned char *packet = psmouse->packet; ++ ++ /* ++ * V2 hardware has two flavors. Older ones that do not report pressure, ++ * and newer ones that reports pressure and width. With newer ones, all ++ * packets (1, 2, 3 finger touch) have the same constant bits. With ++ * older ones, 1/3 finger touch packets and 2 finger touch packets ++ * have different constant bits. ++ * With all three cases, if the constant bits are not exactly what I ++ * expected, I consider them invalid. ++ */ ++ if (etd->reports_pressure) ++ return (packet[0] & 0x0c) == 0x04 && ++ (packet[3] & 0x0f) == 0x02; ++ ++ if ((packet[0] & 0xc0) == 0x80) ++ return (packet[0] & 0x0c) == 0x0c && ++ (packet[3] & 0x0e) == 0x08; ++ ++ return (packet[0] & 0x3c) == 0x3c && ++ (packet[1] & 0xf0) == 0x00 && ++ (packet[3] & 0x3e) == 0x38 && ++ (packet[4] & 0xf0) == 0x00; ++} ++ + /* + * Process byte stream from mouse and handle complete packets + */ +@@ -389,14 +417,16 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) + + switch (etd->hw_version) { + case 1: +- if (etd->paritycheck && !elantech_check_parity_v1(psmouse)) ++ if (etd->paritycheck && !elantech_packet_check_v1(psmouse)) + return PSMOUSE_BAD_DATA; + + elantech_report_absolute_v1(psmouse); + break; + + case 2: +- /* We don't know how to check parity in protocol v2 */ ++ if (etd->paritycheck && !elantech_packet_check_v2(psmouse)) ++ return PSMOUSE_BAD_DATA; ++ + elantech_report_absolute_v2(psmouse); + break; + } +@@ -795,8 +825,7 @@ int elantech_init(struct psmouse *psmouse) + etd->hw_version = 2; + /* For now show extra debug information */ + etd->debug = 1; +- /* Don't know how to do parity checking for version 2 */ +- etd->paritycheck = 0; ++ etd->paritycheck = 1; + + if (etd->fw_version >= 0x020800) + etd->reports_pressure = true; +-- +1.7.6.4 + + +From 7e1abba14d70426b251ee58451ab1671af425409 Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Fri, 9 Sep 2011 10:28:19 -0700 +Subject: Input: elantech - clean up elantech_init +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Group property setting code into elantech_set_properties. + +Signed-off-by: JJ Ding +Acked-by: Daniel Kurtz +Acked-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.c | 69 ++++++++++++++++++++++----------------- + 1 files changed, 39 insertions(+), 30 deletions(-) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index f2e3a2b..1ab1c14 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -791,6 +791,42 @@ static int elantech_reconnect(struct psmouse *psmouse) + } + + /* ++ * determine hardware version and set some properties according to it. ++ */ ++static void elantech_set_properties(struct elantech_data *etd) ++{ ++ /* ++ * Assume every version greater than 0x020030 is new EeePC style ++ * hardware with 6 byte packets, except 0x020600 ++ */ ++ if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) ++ etd->hw_version = 1; ++ else ++ etd->hw_version = 2; ++ ++ /* ++ * Turn on packet checking by default. ++ */ ++ etd->paritycheck = 1; ++ ++ /* ++ * This firmware suffers from misreporting coordinates when ++ * a touch action starts causing the mouse cursor or scrolled page ++ * to jump. Enable a workaround. ++ */ ++ etd->jumpy_cursor = ++ (etd->fw_version == 0x020022 || etd->fw_version == 0x020600); ++ ++ if (etd->hw_version == 2) { ++ /* For now show extra debug information */ ++ etd->debug = 1; ++ ++ if (etd->fw_version >= 0x020800) ++ etd->reports_pressure = true; ++ } ++} ++ ++/* + * Initialize the touchpad and create sysfs entries + */ + int elantech_init(struct psmouse *psmouse) +@@ -816,26 +852,9 @@ int elantech_init(struct psmouse *psmouse) + } + + etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; +- +- /* +- * Assume every version greater than this is new EeePC style +- * hardware with 6 byte packets +- */ +- if (etd->fw_version >= 0x020030) { +- etd->hw_version = 2; +- /* For now show extra debug information */ +- etd->debug = 1; +- etd->paritycheck = 1; +- +- if (etd->fw_version >= 0x020800) +- etd->reports_pressure = true; +- +- } else { +- etd->hw_version = 1; +- etd->paritycheck = 1; +- } +- +- pr_info("assuming hardware version %d, firmware version %d.%d.%d\n", ++ elantech_set_properties(etd); ++ pr_info("assuming hardware version %d " ++ "(with firmware version 0x%02x%02x%02x)\n", + etd->hw_version, param[0], param[1], param[2]); + + if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, +@@ -847,16 +866,6 @@ int elantech_init(struct psmouse *psmouse) + etd->capabilities[0], etd->capabilities[1], + etd->capabilities[2]); + +- /* +- * This firmware suffers from misreporting coordinates when +- * a touch action starts causing the mouse cursor or scrolled page +- * to jump. Enable a workaround. +- */ +- if (etd->fw_version == 0x020022 || etd->fw_version == 0x020600) { +- pr_info("firmware version 2.0.34/2.6.0 detected, enabling jumpy cursor workaround\n"); +- etd->jumpy_cursor = true; +- } +- + if (elantech_set_absolute_mode(psmouse)) { + pr_err("failed to put touchpad into absolute mode.\n"); + goto init_fail; +-- +1.7.6.4 + + +From 709d9ebd2853032df0599c30d5ac61c8397679f3 Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Fri, 9 Sep 2011 10:30:31 -0700 +Subject: Input: elantech - add v3 hardware support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +v3 hardware's packet format is almost identical to v2 (one/three finger touch), +except when sensing two finger touch, the hardware sends 12 bytes of data. + +Signed-off-by: JJ Ding +Acked-by: Daniel Kurtz +Acked-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + Documentation/input/elantech.txt | 117 +++++++++++++++++++-- + drivers/input/mouse/elantech.c | 208 ++++++++++++++++++++++++++++++++++---- + drivers/input/mouse/elantech.h | 12 ++ + 3 files changed, 306 insertions(+), 31 deletions(-) + +diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt +index bce9941..cee08ee 100644 +--- a/Documentation/input/elantech.txt ++++ b/Documentation/input/elantech.txt +@@ -16,15 +16,22 @@ Contents + + 1. Introduction + 2. Extra knobs +- 3. Hardware version 1 +- 3.1 Registers +- 3.2 Native relative mode 4 byte packet format +- 3.3 Native absolute mode 4 byte packet format +- 4. Hardware version 2 ++ 3. Differentiating hardware versions ++ 4. Hardware version 1 + 4.1 Registers +- 4.2 Native absolute mode 6 byte packet format +- 4.2.1 One finger touch +- 4.2.2 Two finger touch ++ 4.2 Native relative mode 4 byte packet format ++ 4.3 Native absolute mode 4 byte packet format ++ 5. Hardware version 2 ++ 5.1 Registers ++ 5.2 Native absolute mode 6 byte packet format ++ 5.2.1 Parity checking and packet re-synchronization ++ 5.2.2 One/Three finger touch ++ 5.2.3 Two finger touch ++ 6. Hardware version 3 ++ 6.1 Registers ++ 6.2 Native absolute mode 6 byte packet format ++ 6.2.1 One/Three finger touch ++ 6.2.2 Two finger touch + + + +@@ -375,7 +382,7 @@ For all the other ones, there are just a few constant bits: + + In case an error is detected, all the packets are shifted by one (and packet[0] is discarded). + +-5.2.1 One/Three finger touch ++5.2.2 One/Three finger touch + ~~~~~~~~~~~~~~~~ + + byte 0: +@@ -384,7 +391,7 @@ byte 0: + n1 n0 w3 w2 . . R L + + L, R = 1 when Left, Right mouse button pressed +- n1..n0 = numbers of fingers on touchpad ++ n1..n0 = number of fingers on touchpad + + byte 1: + +@@ -432,7 +439,7 @@ byte 5: + y11..y0 = absolute y value (vertical) + + +-4.2.2 Two finger touch ++5.2.3 Two finger touch + ~~~~~~~~~~~~~~~~ + + Note that the two pairs of coordinates are not exactly the coordinates of the +@@ -446,7 +453,7 @@ byte 0: + n1 n0 ay8 ax8 . . R L + + L, R = 1 when Left, Right mouse button pressed +- n1..n0 = numbers of fingers on touchpad ++ n1..n0 = number of fingers on touchpad + + byte 1: + +@@ -480,3 +487,89 @@ byte 5: + by7 by8 by5 by4 by3 by2 by1 by0 + + by8..by0 = upper-right finger absolute y value ++ ++///////////////////////////////////////////////////////////////////////////// ++ ++6. Hardware version 3 ++ ================== ++ ++6.1 Registers ++ ~~~~~~~~~ ++* reg_10 ++ ++ bit 7 6 5 4 3 2 1 0 ++ 0 0 0 0 0 0 0 A ++ ++ A: 1 = enable absolute tracking ++ ++6.2 Native absolute mode 6 byte packet format ++ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++1 and 3 finger touch shares the same 6-byte packet format, except that ++3 finger touch only reports the position of the center of all three fingers. ++ ++Firmware would send 12 bytes of data for 2 finger touch. ++ ++Note on debounce: ++In case the box has unstable power supply or other electricity issues, or ++when number of finger changes, F/W would send "debounce packet" to inform ++driver that the hardware is in debounce status. ++The debouce packet has the following signature: ++ byte 0: 0xc4 ++ byte 1: 0xff ++ byte 2: 0xff ++ byte 3: 0x02 ++ byte 4: 0xff ++ byte 5: 0xff ++When we encounter this kind of packet, we just ignore it. ++ ++6.2.1 One/Three finger touch ++ ~~~~~~~~~~~~~~~~~~~~~~ ++ ++byte 0: ++ ++ bit 7 6 5 4 3 2 1 0 ++ n1 n0 w3 w2 0 1 R L ++ ++ L, R = 1 when Left, Right mouse button pressed ++ n1..n0 = number of fingers on touchpad ++ ++byte 1: ++ ++ bit 7 6 5 4 3 2 1 0 ++ p7 p6 p5 p4 x11 x10 x9 x8 ++ ++byte 2: ++ ++ bit 7 6 5 4 3 2 1 0 ++ x7 x6 x5 x4 x3 x2 x1 x0 ++ ++ x11..x0 = absolute x value (horizontal) ++ ++byte 3: ++ ++ bit 7 6 5 4 3 2 1 0 ++ 0 0 w1 w0 0 0 1 0 ++ ++ w3..w0 = width of the finger touch ++ ++byte 4: ++ ++ bit 7 6 5 4 3 2 1 0 ++ p3 p1 p2 p0 y11 y10 y9 y8 ++ ++ p7..p0 = pressure ++ ++byte 5: ++ ++ bit 7 6 5 4 3 2 1 0 ++ y7 y6 y5 y4 y3 y2 y1 y0 ++ ++ y11..y0 = absolute y value (vertical) ++ ++6.2.2 Two finger touch ++ ~~~~~~~~~~~~~~~~ ++ ++The packet format is exactly the same for two finger touch, except the hardware ++sends two 6 byte packets. The first packet contains data for the first finger, ++the second packet has data for the second finger. So for two finger touch a ++total of 12 bytes are sent. +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 1ab1c14..9cfc70a 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -108,6 +108,16 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, + rc = -1; + } + break; ++ ++ case 3: ++ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || ++ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, reg) || ++ elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) { ++ rc = -1; ++ } ++ break; + } + + if (rc) +@@ -154,6 +164,18 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, + rc = -1; + } + break; ++ ++ case 3: ++ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || ++ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, reg) || ++ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, val) || ++ elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { ++ rc = -1; ++ } ++ break; + } + + if (rc) +@@ -350,6 +372,84 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + input_sync(dev); + } + ++/* ++ * Interpret complete data packets and report absolute mode input events for ++ * hardware version 3. (12 byte packets for two fingers) ++ */ ++static void elantech_report_absolute_v3(struct psmouse *psmouse, ++ int packet_type) ++{ ++ struct input_dev *dev = psmouse->dev; ++ struct elantech_data *etd = psmouse->private; ++ unsigned char *packet = psmouse->packet; ++ unsigned int fingers = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0; ++ unsigned int width = 0, pres = 0; ++ ++ /* byte 0: n1 n0 . . . . R L */ ++ fingers = (packet[0] & 0xc0) >> 6; ++ ++ switch (fingers) { ++ case 3: ++ case 1: ++ /* ++ * byte 1: . . . . x11 x10 x9 x8 ++ * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 ++ */ ++ x1 = ((packet[1] & 0x0f) << 8) | packet[2]; ++ /* ++ * byte 4: . . . . y11 y10 y9 y8 ++ * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 ++ */ ++ y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); ++ break; ++ ++ case 2: ++ if (packet_type == PACKET_V3_HEAD) { ++ /* ++ * byte 1: . . . . ax11 ax10 ax9 ax8 ++ * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 ++ */ ++ etd->prev_x = ((packet[1] & 0x0f) << 8) | packet[2]; ++ /* ++ * byte 4: . . . . ay11 ay10 ay9 ay8 ++ * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 ++ */ ++ etd->prev_y = etd->y_max - ++ (((packet[4] & 0x0f) << 8) | packet[5]); ++ /* ++ * wait for next packet ++ */ ++ return; ++ } ++ ++ /* packet_type == PACKET_V3_TAIL */ ++ x1 = etd->prev_x; ++ y1 = etd->prev_y; ++ x2 = ((packet[1] & 0x0f) << 8) | packet[2]; ++ y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); ++ break; ++ } ++ ++ pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); ++ width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); ++ ++ input_report_key(dev, BTN_TOUCH, fingers != 0); ++ if (fingers != 0) { ++ input_report_abs(dev, ABS_X, x1); ++ input_report_abs(dev, ABS_Y, y1); ++ } ++ elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); ++ input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); ++ input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); ++ input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); ++ input_report_key(dev, BTN_LEFT, packet[0] & 0x01); ++ input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); ++ input_report_abs(dev, ABS_PRESSURE, pres); ++ input_report_abs(dev, ABS_TOOL_WIDTH, width); ++ ++ input_sync(dev); ++} ++ + static int elantech_packet_check_v1(struct psmouse *psmouse) + { + struct elantech_data *etd = psmouse->private; +@@ -403,11 +503,37 @@ static int elantech_packet_check_v2(struct psmouse *psmouse) + } + + /* ++ * We check the constant bits to determine what packet type we get, ++ * so packet checking is mandatory for v3 hardware. ++ */ ++static int elantech_packet_check_v3(struct psmouse *psmouse) ++{ ++ const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff }; ++ unsigned char *packet = psmouse->packet; ++ ++ /* ++ * check debounce first, it has the same signature in byte 0 ++ * and byte 3 as PACKET_V3_HEAD. ++ */ ++ if (!memcmp(packet, debounce_packet, sizeof(debounce_packet))) ++ return PACKET_DEBOUNCE; ++ ++ if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02) ++ return PACKET_V3_HEAD; ++ ++ if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) ++ return PACKET_V3_TAIL; ++ ++ return PACKET_UNKNOWN; ++} ++ ++/* + * Process byte stream from mouse and handle complete packets + */ + static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) + { + struct elantech_data *etd = psmouse->private; ++ int packet_type; + + if (psmouse->pktcnt < psmouse->pktsize) + return PSMOUSE_GOOD_DATA; +@@ -429,6 +555,18 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) + + elantech_report_absolute_v2(psmouse); + break; ++ ++ case 3: ++ packet_type = elantech_packet_check_v3(psmouse); ++ /* ignore debounce */ ++ if (packet_type == PACKET_DEBOUNCE) ++ return PSMOUSE_FULL_PACKET; ++ ++ if (packet_type == PACKET_UNKNOWN) ++ return PSMOUSE_BAD_DATA; ++ ++ elantech_report_absolute_v3(psmouse, packet_type); ++ break; + } + + return PSMOUSE_FULL_PACKET; +@@ -463,8 +601,15 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) + elantech_write_reg(psmouse, 0x11, etd->reg_11) || + elantech_write_reg(psmouse, 0x21, etd->reg_21)) { + rc = -1; +- break; + } ++ break; ++ ++ case 3: ++ etd->reg_10 = 0x0b; ++ if (elantech_write_reg(psmouse, 0x10, etd->reg_10)) ++ rc = -1; ++ ++ break; + } + + if (rc == 0) { +@@ -498,11 +643,12 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) + return rc; + } + +-static void elantech_set_range(struct psmouse *psmouse, +- unsigned int *x_min, unsigned int *y_min, +- unsigned int *x_max, unsigned int *y_max) ++static int elantech_set_range(struct psmouse *psmouse, ++ unsigned int *x_min, unsigned int *y_min, ++ unsigned int *x_max, unsigned int *y_max) + { + struct elantech_data *etd = psmouse->private; ++ unsigned char param[3]; + int i; + + switch (etd->hw_version) { +@@ -530,19 +676,30 @@ static void elantech_set_range(struct psmouse *psmouse, + *y_max = (etd->capabilities[2] - i) * 64; + } + break; ++ ++ case 3: ++ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) ++ return -1; ++ ++ *x_max = (0x0f & param[0]) << 8 | param[1]; ++ *y_max = (0xf0 & param[0]) << 4 | param[2]; ++ break; + } ++ ++ return 0; + } + + /* + * Set the appropriate event bits for the input subsystem + */ +-static void elantech_set_input_params(struct psmouse *psmouse) ++static int elantech_set_input_params(struct psmouse *psmouse) + { + struct input_dev *dev = psmouse->dev; + struct elantech_data *etd = psmouse->private; + unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0; + +- elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max); ++ if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max)) ++ return -1; + + __set_bit(EV_KEY, dev->evbit); + __set_bit(EV_ABS, dev->evbit); +@@ -570,6 +727,9 @@ static void elantech_set_input_params(struct psmouse *psmouse) + + case 2: + __set_bit(BTN_TOOL_QUADTAP, dev->keybit); ++ __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); ++ /* fall through */ ++ case 3: + input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); + input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); + if (etd->reports_pressure) { +@@ -578,7 +738,6 @@ static void elantech_set_input_params(struct psmouse *psmouse) + input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, + ETP_WMAX_V2, 0, 0); + } +- __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); + input_mt_init_slots(dev, 2); + input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); + input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); +@@ -586,6 +745,8 @@ static void elantech_set_input_params(struct psmouse *psmouse) + } + + etd->y_max = y_max; ++ ++ return 0; + } + + struct elantech_attr_data { +@@ -727,7 +888,8 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) + * Report this in case there are Elantech models that use a different + * set of magic numbers + */ +- if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) { ++ if (param[0] != 0x3c || param[1] != 0x03 || ++ (param[2] != 0xc8 && param[2] != 0x00)) { + pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", + param[0], param[1], param[2]); + return -1; +@@ -793,16 +955,16 @@ static int elantech_reconnect(struct psmouse *psmouse) + /* + * determine hardware version and set some properties according to it. + */ +-static void elantech_set_properties(struct elantech_data *etd) ++static int elantech_set_properties(struct elantech_data *etd) + { +- /* +- * Assume every version greater than 0x020030 is new EeePC style +- * hardware with 6 byte packets, except 0x020600 +- */ + if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) + etd->hw_version = 1; +- else ++ else if (etd->fw_version < 0x150600) + etd->hw_version = 2; ++ else if ((etd->fw_version & 0x0f0000) >> 16 == 5) ++ etd->hw_version = 3; ++ else ++ return -1; + + /* + * Turn on packet checking by default. +@@ -817,13 +979,15 @@ static void elantech_set_properties(struct elantech_data *etd) + etd->jumpy_cursor = + (etd->fw_version == 0x020022 || etd->fw_version == 0x020600); + +- if (etd->hw_version == 2) { ++ if (etd->hw_version > 1) { + /* For now show extra debug information */ + etd->debug = 1; + + if (etd->fw_version >= 0x020800) + etd->reports_pressure = true; + } ++ ++ return 0; + } + + /* +@@ -850,9 +1014,12 @@ int elantech_init(struct psmouse *psmouse) + pr_err("failed to query firmware version.\n"); + goto init_fail; + } +- + etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; +- elantech_set_properties(etd); ++ ++ if (elantech_set_properties(etd)) { ++ pr_err("unknown hardware version, aborting...\n"); ++ goto init_fail; ++ } + pr_info("assuming hardware version %d " + "(with firmware version 0x%02x%02x%02x)\n", + etd->hw_version, param[0], param[1], param[2]); +@@ -871,7 +1038,10 @@ int elantech_init(struct psmouse *psmouse) + goto init_fail; + } + +- elantech_set_input_params(psmouse); ++ if (elantech_set_input_params(psmouse)) { ++ pr_err("failed to query touchpad range.\n"); ++ goto init_fail; ++ } + + error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, + &elantech_attr_group); +@@ -883,7 +1053,7 @@ int elantech_init(struct psmouse *psmouse) + psmouse->protocol_handler = elantech_process_byte; + psmouse->disconnect = elantech_disconnect; + psmouse->reconnect = elantech_reconnect; +- psmouse->pktsize = etd->hw_version == 2 ? 6 : 4; ++ psmouse->pktsize = etd->hw_version > 1 ? 6 : 4; + + return 0; + +diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h +index d9e6144..236c33c 100644 +--- a/drivers/input/mouse/elantech.h ++++ b/drivers/input/mouse/elantech.h +@@ -16,6 +16,7 @@ + /* + * Command values for Synaptics style queries + */ ++#define ETP_FW_ID_QUERY 0x00 + #define ETP_FW_VERSION_QUERY 0x01 + #define ETP_CAPABILITIES_QUERY 0x02 + +@@ -24,6 +25,7 @@ + */ + #define ETP_REGISTER_READ 0x10 + #define ETP_REGISTER_WRITE 0x11 ++#define ETP_REGISTER_READWRITE 0x00 + + /* + * Hardware version 2 custom PS/2 command value +@@ -79,6 +81,14 @@ + #define ETP_WMIN_V2 0 + #define ETP_WMAX_V2 15 + ++/* ++ * v3 hardware has 2 kinds of packet types. ++ */ ++#define PACKET_UNKNOWN 0x01 ++#define PACKET_DEBOUNCE 0x02 ++#define PACKET_V3_HEAD 0x03 ++#define PACKET_V3_TAIL 0x04 ++ + struct elantech_data { + unsigned char reg_10; + unsigned char reg_11; +@@ -98,6 +108,8 @@ struct elantech_data { + unsigned int fw_version; + unsigned int single_finger_reports; + unsigned int y_max; ++ unsigned int prev_x; ++ unsigned int prev_y; + unsigned char parity[256]; + }; + +-- +1.7.6.4 + + +From 5936f37c68ab27b24d6f2faf23268a9aefd3092e Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Fri, 9 Sep 2011 10:31:58 -0700 +Subject: Input: elantech - add v4 hardware support + +v4 hardware is a true multitouch capable touchpad (up to 5 fingers). +The packet format is quite complex, please see protocol document for +reference. + +Signed-off-by: JJ Ding +Signed-off-by: Dmitry Torokhov +--- + Documentation/input/elantech.txt | 170 ++++++++++++++++++++++++++ + drivers/input/mouse/elantech.c | 249 ++++++++++++++++++++++++++++++++++++-- + drivers/input/mouse/elantech.h | 29 ++++- + 3 files changed, 432 insertions(+), 16 deletions(-) + +diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt +index cee08ee..5602eb7 100644 +--- a/Documentation/input/elantech.txt ++++ b/Documentation/input/elantech.txt +@@ -32,6 +32,12 @@ Contents + 6.2 Native absolute mode 6 byte packet format + 6.2.1 One/Three finger touch + 6.2.2 Two finger touch ++ 7. Hardware version 4 ++ 7.1 Registers ++ 7.2 Native absolute mode 6 byte packet format ++ 7.2.1 Status packet ++ 7.2.2 Head packet ++ 7.2.3 Motion packet + + + +@@ -573,3 +579,167 @@ The packet format is exactly the same for two finger touch, except the hardware + sends two 6 byte packets. The first packet contains data for the first finger, + the second packet has data for the second finger. So for two finger touch a + total of 12 bytes are sent. ++ ++///////////////////////////////////////////////////////////////////////////// ++ ++7. Hardware version 4 ++ ================== ++ ++7.1 Registers ++ ~~~~~~~~~ ++* reg_07 ++ ++ bit 7 6 5 4 3 2 1 0 ++ 0 0 0 0 0 0 0 A ++ ++ A: 1 = enable absolute tracking ++ ++7.2 Native absolute mode 6 byte packet format ++ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers. ++Unfortunately, due to PS/2's limited bandwidth, its packet format is rather ++complex. ++ ++Whenever the numbers or identities of the fingers changes, the hardware sends a ++status packet to indicate how many and which fingers is on touchpad, followed by ++head packets or motion packets. A head packet contains data of finger id, finger ++position (absolute x, y values), width, and pressure. A motion packet contains ++two fingers' position delta. ++ ++For example, when status packet tells there are 2 fingers on touchpad, then we ++can expect two following head packets. If the finger status doesn't change, ++the following packets would be motion packets, only sending delta of finger ++position, until we receive a status packet. ++ ++One exception is one finger touch. when a status packet tells us there is only ++one finger, the hardware would just send head packets afterwards. ++ ++7.2.1 Status packet ++ ~~~~~~~~~~~~~ ++ ++byte 0: ++ ++ bit 7 6 5 4 3 2 1 0 ++ . . . . 0 1 R L ++ ++ L, R = 1 when Left, Right mouse button pressed ++ ++byte 1: ++ ++ bit 7 6 5 4 3 2 1 0 ++ . . . ft4 ft3 ft2 ft1 ft0 ++ ++ ft4 ft3 ft2 ft1 ft0 ftn = 1 when finger n is on touchpad ++ ++byte 2: not used ++ ++byte 3: ++ ++ bit 7 6 5 4 3 2 1 0 ++ . . . 1 0 0 0 0 ++ ++ constant bits ++ ++byte 4: ++ ++ bit 7 6 5 4 3 2 1 0 ++ p . . . . . . . ++ ++ p = 1 for palm ++ ++byte 5: not used ++ ++7.2.2 Head packet ++ ~~~~~~~~~~~ ++ ++byte 0: ++ ++ bit 7 6 5 4 3 2 1 0 ++ w3 w2 w1 w0 0 1 R L ++ ++ L, R = 1 when Left, Right mouse button pressed ++ w3..w0 = finger width (spans how many trace lines) ++ ++byte 1: ++ ++ bit 7 6 5 4 3 2 1 0 ++ p7 p6 p5 p4 x11 x10 x9 x8 ++ ++byte 2: ++ ++ bit 7 6 5 4 3 2 1 0 ++ x7 x6 x5 x4 x3 x2 x1 x0 ++ ++ x11..x0 = absolute x value (horizontal) ++ ++byte 3: ++ ++ bit 7 6 5 4 3 2 1 0 ++ id2 id1 id0 1 0 0 0 1 ++ ++ id2..id0 = finger id ++ ++byte 4: ++ ++ bit 7 6 5 4 3 2 1 0 ++ p3 p1 p2 p0 y11 y10 y9 y8 ++ ++ p7..p0 = pressure ++ ++byte 5: ++ ++ bit 7 6 5 4 3 2 1 0 ++ y7 y6 y5 y4 y3 y2 y1 y0 ++ ++ y11..y0 = absolute y value (vertical) ++ ++7.2.3 Motion packet ++ ~~~~~~~~~~~~~ ++ ++byte 0: ++ ++ bit 7 6 5 4 3 2 1 0 ++ id2 id1 id0 w 0 1 R L ++ ++ L, R = 1 when Left, Right mouse button pressed ++ id2..id0 = finger id ++ w = 1 when delta overflows (> 127 or < -128), in this case ++ firmware sends us (delta x / 5) and (delta y / 5) ++ ++byte 1: ++ ++ bit 7 6 5 4 3 2 1 0 ++ x7 x6 x5 x4 x3 x2 x1 x0 ++ ++ x7..x0 = delta x (two's complement) ++ ++byte 2: ++ ++ bit 7 6 5 4 3 2 1 0 ++ y7 y6 y5 y4 y3 y2 y1 y0 ++ ++ y7..y0 = delta y (two's complement) ++ ++byte 3: ++ ++ bit 7 6 5 4 3 2 1 0 ++ id2 id1 id0 1 0 0 1 0 ++ ++ id2..id0 = finger id ++ ++byte 4: ++ ++ bit 7 6 5 4 3 2 1 0 ++ x7 x6 x5 x4 x3 x2 x1 x0 ++ ++ x7..x0 = delta x (two's complement) ++ ++byte 5: ++ ++ bit 7 6 5 4 3 2 1 0 ++ y7 y6 y5 y4 y3 y2 y1 y0 ++ ++ y7..y0 = delta y (two's complement) ++ ++ byte 0 ~ 2 for one finger ++ byte 3 ~ 5 for another +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 9cfc70a..b8733b3 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -84,7 +84,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, + unsigned char param[3]; + int rc = 0; + +- if (reg < 0x10 || reg > 0x26) ++ if (reg < 0x07 || reg > 0x26) + return -1; + + if (reg > 0x11 && reg < 0x20) +@@ -109,7 +109,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, + } + break; + +- case 3: ++ case 3 ... 4: + if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || + elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || + elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || +@@ -122,8 +122,10 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, + + if (rc) + pr_err("failed to read register 0x%02x.\n", reg); +- else ++ else if (etd->hw_version != 4) + *val = param[0]; ++ else ++ *val = param[1]; + + return rc; + } +@@ -137,7 +139,7 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, + struct elantech_data *etd = psmouse->private; + int rc = 0; + +- if (reg < 0x10 || reg > 0x26) ++ if (reg < 0x07 || reg > 0x26) + return -1; + + if (reg > 0x11 && reg < 0x20) +@@ -176,6 +178,20 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, + rc = -1; + } + break; ++ ++ case 4: ++ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || ++ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, reg) || ++ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || ++ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, val) || ++ elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { ++ rc = -1; ++ } ++ break; + } + + if (rc) +@@ -409,12 +425,12 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, + * byte 1: . . . . ax11 ax10 ax9 ax8 + * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 + */ +- etd->prev_x = ((packet[1] & 0x0f) << 8) | packet[2]; ++ etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2]; + /* + * byte 4: . . . . ay11 ay10 ay9 ay8 + * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 + */ +- etd->prev_y = etd->y_max - ++ etd->mt[0].y = etd->y_max - + (((packet[4] & 0x0f) << 8) | packet[5]); + /* + * wait for next packet +@@ -423,8 +439,8 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, + } + + /* packet_type == PACKET_V3_TAIL */ +- x1 = etd->prev_x; +- y1 = etd->prev_y; ++ x1 = etd->mt[0].x; ++ y1 = etd->mt[0].y; + x2 = ((packet[1] & 0x0f) << 8) | packet[2]; + y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); + break; +@@ -450,6 +466,129 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, + input_sync(dev); + } + ++static void elantech_input_sync_v4(struct psmouse *psmouse) ++{ ++ struct input_dev *dev = psmouse->dev; ++ unsigned char *packet = psmouse->packet; ++ ++ input_report_key(dev, BTN_LEFT, packet[0] & 0x01); ++ input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); ++ input_mt_report_pointer_emulation(dev, true); ++ input_sync(dev); ++} ++ ++static void process_packet_status_v4(struct psmouse *psmouse) ++{ ++ struct input_dev *dev = psmouse->dev; ++ unsigned char *packet = psmouse->packet; ++ unsigned fingers; ++ int i; ++ ++ /* notify finger state change */ ++ fingers = packet[1] & 0x1f; ++ for (i = 0; i < ETP_MAX_FINGERS; i++) { ++ if ((fingers & (1 << i)) == 0) { ++ input_mt_slot(dev, i); ++ input_mt_report_slot_state(dev, MT_TOOL_FINGER, false); ++ } ++ } ++ ++ elantech_input_sync_v4(psmouse); ++} ++ ++static void process_packet_head_v4(struct psmouse *psmouse) ++{ ++ struct input_dev *dev = psmouse->dev; ++ struct elantech_data *etd = psmouse->private; ++ unsigned char *packet = psmouse->packet; ++ int id = ((packet[3] & 0xe0) >> 5) - 1; ++ int pres, traces; ++ ++ if (id < 0) ++ return; ++ ++ etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2]; ++ etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); ++ pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); ++ traces = (packet[0] & 0xf0) >> 4; ++ ++ input_mt_slot(dev, id); ++ input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); ++ ++ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); ++ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); ++ input_report_abs(dev, ABS_MT_PRESSURE, pres); ++ input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width); ++ /* report this for backwards compatibility */ ++ input_report_abs(dev, ABS_TOOL_WIDTH, traces); ++ ++ elantech_input_sync_v4(psmouse); ++} ++ ++static void process_packet_motion_v4(struct psmouse *psmouse) ++{ ++ struct input_dev *dev = psmouse->dev; ++ struct elantech_data *etd = psmouse->private; ++ unsigned char *packet = psmouse->packet; ++ int weight, delta_x1 = 0, delta_y1 = 0, delta_x2 = 0, delta_y2 = 0; ++ int id, sid; ++ ++ id = ((packet[0] & 0xe0) >> 5) - 1; ++ if (id < 0) ++ return; ++ ++ sid = ((packet[3] & 0xe0) >> 5) - 1; ++ weight = (packet[0] & 0x10) ? ETP_WEIGHT_VALUE : 1; ++ /* ++ * Motion packets give us the delta of x, y values of specific fingers, ++ * but in two's complement. Let the compiler do the conversion for us. ++ * Also _enlarge_ the numbers to int, in case of overflow. ++ */ ++ delta_x1 = (signed char)packet[1]; ++ delta_y1 = (signed char)packet[2]; ++ delta_x2 = (signed char)packet[4]; ++ delta_y2 = (signed char)packet[5]; ++ ++ etd->mt[id].x += delta_x1 * weight; ++ etd->mt[id].y -= delta_y1 * weight; ++ input_mt_slot(dev, id); ++ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); ++ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); ++ ++ if (sid >= 0) { ++ etd->mt[sid].x += delta_x2 * weight; ++ etd->mt[sid].y -= delta_y2 * weight; ++ input_mt_slot(dev, sid); ++ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[sid].x); ++ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[sid].y); ++ } ++ ++ elantech_input_sync_v4(psmouse); ++} ++ ++static void elantech_report_absolute_v4(struct psmouse *psmouse, ++ int packet_type) ++{ ++ switch (packet_type) { ++ case PACKET_V4_STATUS: ++ process_packet_status_v4(psmouse); ++ break; ++ ++ case PACKET_V4_HEAD: ++ process_packet_head_v4(psmouse); ++ break; ++ ++ case PACKET_V4_MOTION: ++ process_packet_motion_v4(psmouse); ++ break; ++ ++ case PACKET_UNKNOWN: ++ default: ++ /* impossible to get here */ ++ break; ++ } ++} ++ + static int elantech_packet_check_v1(struct psmouse *psmouse) + { + struct elantech_data *etd = psmouse->private; +@@ -504,7 +643,7 @@ static int elantech_packet_check_v2(struct psmouse *psmouse) + + /* + * We check the constant bits to determine what packet type we get, +- * so packet checking is mandatory for v3 hardware. ++ * so packet checking is mandatory for v3 and later hardware. + */ + static int elantech_packet_check_v3(struct psmouse *psmouse) + { +@@ -527,6 +666,25 @@ static int elantech_packet_check_v3(struct psmouse *psmouse) + return PACKET_UNKNOWN; + } + ++static int elantech_packet_check_v4(struct psmouse *psmouse) ++{ ++ unsigned char *packet = psmouse->packet; ++ ++ if ((packet[0] & 0x0c) == 0x04 && ++ (packet[3] & 0x1f) == 0x11) ++ return PACKET_V4_HEAD; ++ ++ if ((packet[0] & 0x0c) == 0x04 && ++ (packet[3] & 0x1f) == 0x12) ++ return PACKET_V4_MOTION; ++ ++ if ((packet[0] & 0x0c) == 0x04 && ++ (packet[3] & 0x1f) == 0x10) ++ return PACKET_V4_STATUS; ++ ++ return PACKET_UNKNOWN; ++} ++ + /* + * Process byte stream from mouse and handle complete packets + */ +@@ -567,6 +725,14 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) + + elantech_report_absolute_v3(psmouse, packet_type); + break; ++ ++ case 4: ++ packet_type = elantech_packet_check_v4(psmouse); ++ if (packet_type == PACKET_UNKNOWN) ++ return PSMOUSE_BAD_DATA; ++ ++ elantech_report_absolute_v4(psmouse, packet_type); ++ break; + } + + return PSMOUSE_FULL_PACKET; +@@ -610,6 +776,13 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) + rc = -1; + + break; ++ ++ case 4: ++ etd->reg_07 = 0x01; ++ if (elantech_write_reg(psmouse, 0x07, etd->reg_07)) ++ rc = -1; ++ ++ goto skip_readback_reg_10; /* v4 has no reg 0x10 to read */ + } + + if (rc == 0) { +@@ -637,6 +810,7 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) + } + } + ++ skip_readback_reg_10: + if (rc) + pr_err("failed to initialise registers.\n"); + +@@ -645,10 +819,12 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) + + static int elantech_set_range(struct psmouse *psmouse, + unsigned int *x_min, unsigned int *y_min, +- unsigned int *x_max, unsigned int *y_max) ++ unsigned int *x_max, unsigned int *y_max, ++ unsigned int *width) + { + struct elantech_data *etd = psmouse->private; + unsigned char param[3]; ++ unsigned char traces; + int i; + + switch (etd->hw_version) { +@@ -684,6 +860,19 @@ static int elantech_set_range(struct psmouse *psmouse, + *x_max = (0x0f & param[0]) << 8 | param[1]; + *y_max = (0xf0 & param[0]) << 4 | param[2]; + break; ++ ++ case 4: ++ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) ++ return -1; ++ ++ *x_max = (0x0f & param[0]) << 8 | param[1]; ++ *y_max = (0xf0 & param[0]) << 4 | param[2]; ++ traces = etd->capabilities[1]; ++ if ((traces < 2) || (traces > *x_max)) ++ return -1; ++ ++ *width = *x_max / (traces - 1); ++ break; + } + + return 0; +@@ -696,9 +885,9 @@ static int elantech_set_input_params(struct psmouse *psmouse) + { + struct input_dev *dev = psmouse->dev; + struct elantech_data *etd = psmouse->private; +- unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0; ++ unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0; + +- if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max)) ++ if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width)) + return -1; + + __set_bit(EV_KEY, dev->evbit); +@@ -742,9 +931,37 @@ static int elantech_set_input_params(struct psmouse *psmouse) + input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); + input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); + break; ++ ++ case 4: ++ __set_bit(BTN_TOOL_QUADTAP, dev->keybit); ++ /* For X to recognize me as touchpad. */ ++ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); ++ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); ++ /* ++ * range of pressure and width is the same as v2, ++ * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility. ++ */ ++ input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, ++ ETP_PMAX_V2, 0, 0); ++ input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, ++ ETP_WMAX_V2, 0, 0); ++ /* Multitouch capable pad, up to 5 fingers. */ ++ input_mt_init_slots(dev, ETP_MAX_FINGERS); ++ input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); ++ input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); ++ input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2, ++ ETP_PMAX_V2, 0, 0); ++ /* ++ * The firmware reports how many trace lines the finger spans, ++ * convert to surface unit as Protocol-B requires. ++ */ ++ input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0, ++ ETP_WMAX_V2 * width, 0, 0); ++ break; + } + + etd->y_max = y_max; ++ etd->width = width; + + return 0; + } +@@ -816,6 +1033,7 @@ static ssize_t elantech_set_int_attr(struct psmouse *psmouse, + elantech_show_int_attr, \ + elantech_set_int_attr) + ++ELANTECH_INT_ATTR(reg_07, 0x07); + ELANTECH_INT_ATTR(reg_10, 0x10); + ELANTECH_INT_ATTR(reg_11, 0x11); + ELANTECH_INT_ATTR(reg_20, 0x20); +@@ -829,6 +1047,7 @@ ELANTECH_INT_ATTR(debug, 0); + ELANTECH_INT_ATTR(paritycheck, 0); + + static struct attribute *elantech_attrs[] = { ++ &psmouse_attr_reg_07.dattr.attr, + &psmouse_attr_reg_10.dattr.attr, + &psmouse_attr_reg_11.dattr.attr, + &psmouse_attr_reg_20.dattr.attr, +@@ -957,12 +1176,16 @@ static int elantech_reconnect(struct psmouse *psmouse) + */ + static int elantech_set_properties(struct elantech_data *etd) + { ++ int ver = (etd->fw_version & 0x0f0000) >> 16; ++ + if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) + etd->hw_version = 1; + else if (etd->fw_version < 0x150600) + etd->hw_version = 2; +- else if ((etd->fw_version & 0x0f0000) >> 16 == 5) ++ else if (ver == 5) + etd->hw_version = 3; ++ else if (ver == 6) ++ etd->hw_version = 4; + else + return -1; + +diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h +index 236c33c..7ecaef0 100644 +--- a/drivers/input/mouse/elantech.h ++++ b/drivers/input/mouse/elantech.h +@@ -82,14 +82,37 @@ + #define ETP_WMAX_V2 15 + + /* +- * v3 hardware has 2 kinds of packet types. ++ * v3 hardware has 2 kinds of packet types, ++ * v4 hardware has 3. + */ + #define PACKET_UNKNOWN 0x01 + #define PACKET_DEBOUNCE 0x02 + #define PACKET_V3_HEAD 0x03 + #define PACKET_V3_TAIL 0x04 ++#define PACKET_V4_HEAD 0x05 ++#define PACKET_V4_MOTION 0x06 ++#define PACKET_V4_STATUS 0x07 ++ ++/* ++ * track up to 5 fingers for v4 hardware ++ */ ++#define ETP_MAX_FINGERS 5 ++ ++/* ++ * weight value for v4 hardware ++ */ ++#define ETP_WEIGHT_VALUE 5 ++ ++/* ++ * The base position for one finger, v4 hardware ++ */ ++struct finger_pos { ++ unsigned int x; ++ unsigned int y; ++}; + + struct elantech_data { ++ unsigned char reg_07; + unsigned char reg_10; + unsigned char reg_11; + unsigned char reg_20; +@@ -108,8 +131,8 @@ struct elantech_data { + unsigned int fw_version; + unsigned int single_finger_reports; + unsigned int y_max; +- unsigned int prev_x; +- unsigned int prev_y; ++ unsigned int width; ++ struct finger_pos mt[ETP_MAX_FINGERS]; + unsigned char parity[256]; + }; + +-- +1.7.6.4 + + +From 3c09085f371a68f09147abb59b35db928fe3950f Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Tue, 20 Sep 2011 22:42:51 -0700 +Subject: Input: elantech - better support all those v2 variants +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +V2 hardware has many variants. This patch adddresses two issues: + + - some model also has debounce packets, but with a different signature + than v3. Now we just check debounce for all v2 hardware. + + - due to different scanning methods the hardware uses, x and y ranges have + to be calculated differently. And for some specific versions, we can just + see them as custom-made, so set {x, y} the same values as Windows driver + does. + +Signed-off-by: JJ Ding +Tested-by: Richard Schütz +Reviewed-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.c | 46 +++++++++++++++++++++++++++++++++++---- + drivers/input/mouse/elantech.h | 1 + + 2 files changed, 42 insertions(+), 5 deletions(-) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index b8733b3..c2d91eb 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -613,6 +613,18 @@ static int elantech_packet_check_v1(struct psmouse *psmouse) + etd->parity[packet[3]] == p3; + } + ++static int elantech_debounce_check_v2(struct psmouse *psmouse) ++{ ++ /* ++ * When we encounter packet that matches this exactly, it means the ++ * hardware is in debounce status. Just ignore the whole packet. ++ */ ++ const u8 debounce_packet[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff }; ++ unsigned char *packet = psmouse->packet; ++ ++ return !memcmp(packet, debounce_packet, sizeof(debounce_packet)); ++} ++ + static int elantech_packet_check_v2(struct psmouse *psmouse) + { + struct elantech_data *etd = psmouse->private; +@@ -708,6 +720,10 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) + break; + + case 2: ++ /* ignore debounce */ ++ if (elantech_debounce_check_v2(psmouse)) ++ return PSMOUSE_FULL_PACKET; ++ + if (etd->paritycheck && !elantech_packet_check_v2(psmouse)) + return PSMOUSE_BAD_DATA; + +@@ -825,7 +841,6 @@ static int elantech_set_range(struct psmouse *psmouse, + struct elantech_data *etd = psmouse->private; + unsigned char param[3]; + unsigned char traces; +- int i; + + switch (etd->hw_version) { + case 1: +@@ -844,12 +859,33 @@ static int elantech_set_range(struct psmouse *psmouse, + *x_max = ETP_XMAX_V2; + *y_max = ETP_YMAX_V2; + } else { ++ int i; ++ int fixed_dpi; ++ + i = (etd->fw_version > 0x020800 && + etd->fw_version < 0x020900) ? 1 : 2; +- *x_min = 0; +- *y_min = 0; +- *x_max = (etd->capabilities[1] - i) * 64; +- *y_max = (etd->capabilities[2] - i) * 64; ++ ++ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) ++ return -1; ++ ++ fixed_dpi = param[1] & 0x10; ++ ++ if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) { ++ if (synaptics_send_cmd(psmouse, ETP_SAMPLE_QUERY, param)) ++ return -1; ++ ++ *x_max = (etd->capabilities[1] - i) * param[1] / 2; ++ *y_max = (etd->capabilities[2] - i) * param[2] / 2; ++ } else if (etd->fw_version == 0x040216) { ++ *x_max = 819; ++ *y_max = 405; ++ } else if (etd->fw_version == 0x040219 || etd->fw_version == 0x040215) { ++ *x_max = 900; ++ *y_max = 500; ++ } else { ++ *x_max = (etd->capabilities[1] - i) * 64; ++ *y_max = (etd->capabilities[2] - i) * 64; ++ } + } + break; + +diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h +index 7ecaef0..9e5f1aa 100644 +--- a/drivers/input/mouse/elantech.h ++++ b/drivers/input/mouse/elantech.h +@@ -19,6 +19,7 @@ + #define ETP_FW_ID_QUERY 0x00 + #define ETP_FW_VERSION_QUERY 0x01 + #define ETP_CAPABILITIES_QUERY 0x02 ++#define ETP_SAMPLE_QUERY 0x03 + + /* + * Command values for register reading or writing +-- +1.7.6.4 + + +From 6c0ec284648f0346e96b0079999cb7af055f58ab Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Tue, 20 Sep 2011 22:42:51 -0700 +Subject: Input: elantech - remove module parameter force_elantech +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This essentially reverts commit f81bc788ff91d4efd4baf88b2c29713838caa8e5. + +With recent work on elantech driver, I believe we now have complete support +for all elantech touchpads. So remove this hack. + +Signed-off-by: JJ Ding +Reviewed-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.c | 12 ++---------- + 1 files changed, 2 insertions(+), 10 deletions(-) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index c2d91eb..25290b3 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -28,10 +28,6 @@ + printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \ + } while (0) + +-static bool force_elantech; +-module_param_named(force_elantech, force_elantech, bool, 0644); +-MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default)."); +- + /* + * Send a Synaptics style sliced query command + */ +@@ -1164,12 +1160,8 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) + param[0], param[1], param[2]); + + if (!elantech_is_signature_valid(param)) { +- if (!force_elantech) { +- pr_debug("Probably not a real Elantech touchpad. Aborting.\n"); +- return -1; +- } +- +- pr_debug("Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n"); ++ pr_debug("Probably not a real Elantech touchpad. Aborting.\n"); ++ return -1; + } + + if (set_properties) { +-- +1.7.6.4 + diff --git a/kernel.spec b/kernel.spec index 87fc89abd..3b1cd23a5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 5 +%global baserelease 6 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -722,6 +722,9 @@ Patch21070: oom-fix-integer-overflow-of-points.patch #rhbz 706574 Patch21071: WMI-properly-cleanup-devices-to-avoid-crashes.patch +#rhbz 728607 +Patch21060: elantech.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1310,6 +1313,9 @@ ApplyPatch oom-fix-integer-overflow-of-points.patch #rhbz 706574 ApplyPatch WMI-properly-cleanup-devices-to-avoid-crashes.patch +#rhbz 728607 +ApplyPatch elantech.patch + # END OF PATCH APPLICATIONS %endif @@ -1930,6 +1936,9 @@ fi # and build. %changelog +* Thu Nov 03 2011 Josh Boyer +- Add patches queued for 3.2 for elantech driver (rhbz 728607) + * Wed Nov 02 2011 Josh Boyer - Add patch to fix oops when removing wmi module (rhbz 706574) From 1f93f04e2352a8390a591837af111fcaa8619e31 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 7 Nov 2011 14:52:27 -0500 Subject: [PATCH 204/397] rebase to 3.1.0 --- .gitignore | 5 +- Makefile | 18 +- Makefile.config | 29 +- TEGRA-2.6.40.2-enable-USB-ports.patch | 111 - acpi-ec-add-delay-before-write.patch | 51 - add-appleir-usb-driver.patch | 5 +- add-macbookair41-keyboard.patch | 119 + arm-omap-dt-compat.patch | 4 +- be2net-move-to-new-vlan-model.patch | 107 - config-arm-generic | 7 +- config-arm-omap-generic | 12 +- config-arm-tegra | 6 +- config-debug | 9 +- config-generic | 207 +- config-ia64-generic | 213 - config-nodebug | 9 +- config-powerpc-generic | 15 + config-powerpc64 | 23 +- config-s390x | 1 - config-sparc64-generic | 2 - config-x86-32-generic | 206 + config-x86-generic | 302 +- config-x86_64-generic | 389 +- dmar-disable-when-ricoh-multifunction.patch | 4 +- drm-i915-fbc-stfu.patch | 102 + drm-nouveau-updates.patch | 8886 ++++++++++++++++- efi-dont-map-boot-services-on-32bit.patch | 22 + epoll-fix-spurious-lockdep-warnings.patch | 2 +- hda_intel-prealloc-4mb-dmabuffer.patch | 47 - hvcs_pi_buf_alloc.patch | 43 + ...eck-if-acpi-already-handle-backlight.patch | 31 + ...x-ht_params-NULL-pointer-dereference.patch | 43 + kernel.spec | 197 +- linux-2.6-crash-driver.patch | 61 +- linux-2.6-debug-vm-would-have-oomkilled.patch | 69 - linux-2.6-intel-iommu-igfx.patch | 4 +- linux-2.6-silence-noise.patch | 4 +- linux-2.6.29-sparc-IOC_TYPECHECK.patch | 21 - linux-2.6.30-no-pcspkr-modalias.patch | 13 +- ...-DiBcom-protect-the-I2C-bufer-access.patch | 27 +- media-dib0700-correct-error-message.patch | 14 +- ...00-protect-the-dib0700-buffer-access.patch | 14 +- perf-check-ownership.patch | 62 - powerpc-Fix-deadlock-in-icswx-code.patch | 74 + rcu-avoid-just-onlined-cpu-resched.patch | 47 + revert-efi-rtclock.patch | 76 + scripts/grab-logs.sh | 2 +- sources | 3 +- taint-vbox.patch | 15 + udlfb-bind-framebuffer-to-interface.patch | 33 + ...tek-driver-uses-stack-memory-for-DMA.patch | 89 +- utrace.patch | 3034 ++++-- ...tomount-for-negative-autofs-dentries.patch | 56 - ...from-regs-when-possible-in-dump_trac.patch | 86 - ...ck-pointer-in-perf-live-regs-savings.patch | 38 - ...make-watchdog-and-perf-work-together.patch | 267 - ...host-bridge-window-conflict-warnings.patch | 40 - ...le-memory-corruption-in-xfs_readlink.patch | 50 +- 58 files changed, 11724 insertions(+), 3702 deletions(-) delete mode 100644 TEGRA-2.6.40.2-enable-USB-ports.patch delete mode 100644 acpi-ec-add-delay-before-write.patch create mode 100644 add-macbookair41-keyboard.patch delete mode 100644 be2net-move-to-new-vlan-model.patch delete mode 100644 config-ia64-generic create mode 100644 config-x86-32-generic create mode 100644 drm-i915-fbc-stfu.patch create mode 100644 efi-dont-map-boot-services-on-32bit.patch delete mode 100644 hda_intel-prealloc-4mb-dmabuffer.patch create mode 100644 hvcs_pi_buf_alloc.patch create mode 100644 ideapad-Check-if-acpi-already-handle-backlight.patch create mode 100644 iwlagn-fix-ht_params-NULL-pointer-dereference.patch delete mode 100644 linux-2.6-debug-vm-would-have-oomkilled.patch delete mode 100644 linux-2.6.29-sparc-IOC_TYPECHECK.patch delete mode 100644 perf-check-ownership.patch create mode 100644 powerpc-Fix-deadlock-in-icswx-code.patch create mode 100644 rcu-avoid-just-onlined-cpu-resched.patch create mode 100644 revert-efi-rtclock.patch create mode 100644 taint-vbox.patch create mode 100644 udlfb-bind-framebuffer-to-interface.patch delete mode 100644 vfs-fix-automount-for-negative-autofs-dentries.patch delete mode 100644 x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch delete mode 100644 x86-Save-stack-pointer-in-perf-live-regs-savings.patch delete mode 100644 x86-p4-make-watchdog-and-perf-work-together.patch delete mode 100644 x86-pci-reduce-severity-of-host-bridge-window-conflict-warnings.patch diff --git a/.gitignore b/.gitignore index 03eb9bf77..2a459583a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,4 @@ linux-*.tar.bz2 patch-*.bz2 clog *.rpm -kernel-2.6.*/ -kernel-3.*/ -/patch-3.0.2-rc1.gz -/patch-3.0.3-rc1.gz +kernel-[23].*/ diff --git a/Makefile b/Makefile index cffc926c2..3e9e3a8fa 100644 --- a/Makefile +++ b/Makefile @@ -36,13 +36,11 @@ debug: @perl -pi -e 's/# CONFIG_DEBUG_SLAB is not set/CONFIG_DEBUG_SLAB=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_MUTEXES is not set/CONFIG_DEBUG_MUTEXES=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_RT_MUTEXES is not set/CONFIG_DEBUG_RT_MUTEXES=y/' config-nodebug - @perl -pi -e 's/# CONFIG_DEBUG_RWSEMS is not set/CONFIG_DEBUG_RWSEMS=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_LOCK_ALLOC is not set/CONFIG_DEBUG_LOCK_ALLOC=y/' config-nodebug @perl -pi -e 's/# CONFIG_PROVE_LOCKING is not set/CONFIG_PROVE_LOCKING=y/' config-nodebug @perl -pi -e 's/# CONFIG_PROVE_RCU is not set/CONFIG_PROVE_RCU=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_SPINLOCK is not set/CONFIG_DEBUG_SPINLOCK=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_VM is not set/CONFIG_DEBUG_VM=y/' config-nodebug - @perl -pi -e 's/# CONFIG_DEBUG_SLEEP_IN_IRQ is not set/CONFIG_DEBUG_SLEEP_IN_IRQ=y/' config-nodebug @perl -pi -e 's/# CONFIG_FAULT_INJECTION is not set/CONFIG_FAULT_INJECTION=y/' config-nodebug @perl -pi -e 's/# CONFIG_FAILSLAB is not set/CONFIG_FAILSLAB=y/' config-nodebug @perl -pi -e 's/# CONFIG_FAIL_PAGE_ALLOC is not set/CONFIG_FAIL_PAGE_ALLOC=y/' config-nodebug @@ -66,7 +64,6 @@ debug: @perl -pi -e 's/# CONFIG_DMA_API_DEBUG is not set/CONFIG_DMA_API_DEBUG=y/' config-nodebug @perl -pi -e 's/# CONFIG_PM_TEST_SUSPEND is not set/CONFIG_PM_TEST_SUSPEND=y/' config-generic @perl -pi -e 's/# CONFIG_PM_ADVANCED_DEBUG is not set/CONFIG_PM_ADVANCED_DEBUG=y/' config-generic - @perl -pi -e 's/# CONFIG_BOOT_TRACER is not set/CONFIG_BOOT_TRACER=y/' config-generic @perl -pi -e 's/# CONFIG_B43_DEBUG is not set/CONFIG_B43_DEBUG=y/' config-generic @perl -pi -e 's/# CONFIG_B43LEGACY_DEBUG is not set/CONFIG_B43LEGACY_DEBUG=y/' config-generic @perl -pi -e 's/# CONFIG_MMIOTRACE is not set/CONFIG_MMIOTRACE=y/' config-nodebug @@ -77,7 +74,7 @@ debug: @perl -pi -e 's/# CONFIG_EXT4_DEBUG is not set/CONFIG_EXT4_DEBUG=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_PERF_USE_VMALLOC is not set/CONFIG_DEBUG_PERF_USE_VMALLOC=y/' config-nodebug @perl -pi -e 's/# CONFIG_JBD2_DEBUG is not set/CONFIG_JBD2_DEBUG=y/' config-nodebug - @perl -pi -e 's/# CONFIG_DEBUG_CFQ_IOSCHED is not set/CONFIG_DEBUG_CFQ_IOSCHED=y/' config-nodebug + @perl -pi -e 's/# CONFIG_DEBUG_BLK_CGROUP is not set/CONFIG_DEBUG_BLK_CGROUP=y/' config-nodebug @perl -pi -e 's/# CONFIG_DRBD_FAULT_INJECTION is not set/CONFIG_DRBD_FAULT_INJECTION=y/' config-nodebug @perl -pi -e 's/# CONFIG_ATH_DEBUG is not set/CONFIG_ATH_DEBUG=y/' config-nodebug @perl -pi -e 's/# CONFIG_CARL9170_DEBUGFS is not set/CONFIG_CARL9170_DEBUGFS=y/' config-nodebug @@ -92,6 +89,8 @@ debug: @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_TEST_LIST_SORT is not set/CONFIG_TEST_LIST_SORT=y/' config-nodebug + @perl -pi -e 's/# CONFIG_DEBUG_ATOMIC_SLEEP is not set/CONFIG_DEBUG_ATOMIC_SLEEP=y/' config-nodebug + @perl -pi -e 's/# CONFIG_DETECT_HUNG_TASK is not set/CONFIG_DETECT_HUNG_TASK=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_SET_MODULE_RONX is not set/CONFIG_DEBUG_SET_MODULE_RONX=y/' config-nodebug @@ -114,13 +113,11 @@ release: @perl -pi -e 's/CONFIG_DEBUG_SLAB=y/# CONFIG_DEBUG_SLAB is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_MUTEXES=y/# CONFIG_DEBUG_MUTEXES is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_RT_MUTEXES=y/# CONFIG_DEBUG_RT_MUTEXES is not set/' config-nodebug - @perl -pi -e 's/CONFIG_DEBUG_RWSEMS=y/# CONFIG_DEBUG_RWSEMS is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_LOCK_ALLOC=y/# CONFIG_DEBUG_LOCK_ALLOC is not set/' config-nodebug @perl -pi -e 's/CONFIG_PROVE_LOCKING=y/# CONFIG_PROVE_LOCKING is not set/' config-nodebug @perl -pi -e 's/CONFIG_PROVE_RCU=y/# CONFIG_PROVE_RCU is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_SPINLOCK=y/# CONFIG_DEBUG_SPINLOCK is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_VM=y/# CONFIG_DEBUG_VM is not set/' config-nodebug - @perl -pi -e 's/CONFIG_DEBUG_SLEEP_IN_IRQ=y/# CONFIG_DEBUG_SLEEP_IN_IRQ is not set/' config-nodebug @perl -pi -e 's/CONFIG_FAULT_INJECTION=y/# CONFIG_FAULT_INJECTION is not set/' config-nodebug @perl -pi -e 's/CONFIG_FAILSLAB=y/# CONFIG_FAILSLAB is not set/' config-nodebug @perl -pi -e 's/CONFIG_FAIL_PAGE_ALLOC=y/# CONFIG_FAIL_PAGE_ALLOC is not set/' config-nodebug @@ -142,9 +139,8 @@ release: @perl -pi -e 's/CONFIG_SYSCTL_SYSCALL_CHECK=y/# CONFIG_SYSCTL_SYSCALL_CHECK is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_NOTIFIERS=y/# CONFIG_DEBUG_NOTIFIERS is not set/' config-nodebug @perl -pi -e 's/CONFIG_DMA_API_DEBUG=y/# CONFIG_DMA_API_DEBUG is not set/' config-nodebug - @perl -pi -e 's/CONFIG_PM_TEST_SUSPEND=y/#\ CONFIG_PM_TEST_SUSPEND\ is\ not\ set/' config-generic - @perl -pi -e 's/CONFIG_PM_ADVANCED_DEBUG=y/#\ CONFIG_PM_ADVANCED_DEBUG\ is\ not\ set/' config-generic - @perl -pi -e 's/CONFIG_BOOT_TRACER=y/#\ CONFIG_BOOT_TRACER\ is\ not\ set/' config-generic + @perl -pi -e 's/CONFIG_PM_TEST_SUSPEND=y/# CONFIG_PM_TEST_SUSPEND is not set/' config-generic + @perl -pi -e 's/CONFIG_PM_ADVANCED_DEBUG=y/# CONFIG_PM_ADVANCED_DEBUG is not set/' config-generic @perl -pi -e 's/CONFIG_B43_DEBUG=y/# CONFIG_B43_DEBUG is not set/' config-generic @perl -pi -e 's/CONFIG_B43LEGACY_DEBUG=y/# CONFIG_B43LEGACY_DEBUG is not set/' config-generic @perl -pi -e 's/CONFIG_MMIOTRACE=y/# CONFIG_MMIOTRACE is not set/' config-nodebug @@ -155,7 +151,7 @@ release: @perl -pi -e 's/CONFIG_EXT4_DEBUG=y/# CONFIG_EXT4_DEBUG is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_PERF_USE_VMALLOC=y/# CONFIG_DEBUG_PERF_USE_VMALLOC is not set/' config-nodebug @perl -pi -e 's/CONFIG_JBD2_DEBUG=y/# CONFIG_JBD2_DEBUG is not set/' config-nodebug - @perl -pi -e 's/CONFIG_DEBUG_CFQ_IOSCHED=y/# CONFIG_DEBUG_CFQ_IOSCHED is not set/' config-nodebug + @perl -pi -e 's/CONFIG_DEBUG_BLK_CGROUP=y/# CONFIG_DEBUG_BLK_CGROUP is not set/' config-nodebug @perl -pi -e 's/CONFIG_DRBD_FAULT_INJECTION=y/# CONFIG_DRBD_FAULT_INJECTION is not set/' config-nodebug @perl -pi -e 's/CONFIG_ATH_DEBUG=y/# CONFIG_ATH_DEBUG is not set/' config-nodebug @perl -pi -e 's/CONFIG_CARL9170_DEBUGFS=y/# CONFIG_CARL9170_DEBUGFS is not set/' config-nodebug @@ -170,6 +166,8 @@ release: #@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_TEST_LIST_SORT=y/# CONFIG_TEST_LIST_SORT is not set/' config-nodebug + @perl -pi -e 's/CONFIG_DEBUG_ATOMIC_SLEEP=y/# CONFIG_DEBUG_ATOMIC_SLEEP is not set/' config-nodebug + @perl -pi -e 's/CONFIG_DETECT_HUNG_TASK=y/# CONFIG_DETECT_HUNG_TASK is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_SET_MODULE_RONX=y/# CONFIG_DEBUG_SET_MODULE_RONX is not set/' config-nodebug diff --git a/Makefile.config b/Makefile.config index 75be683ab..d56185c15 100644 --- a/Makefile.config +++ b/Makefile.config @@ -14,10 +14,9 @@ CONFIGFILES = \ $(CFG)-armv7hl-omap.config $(CFG)-armv7hl-tegra.config \ $(CFG)-ppc.config $(CFG)-ppc-smp.config \ $(CFG)-sparc64.config \ - $(CFG)-ppc64.config $(CFG)-ppc64-debug.config \ - $(CFG)-ia64.config + $(CFG)-ppc64.config $(CFG)-ppc64-debug.config -PLATFORMS = x86 x86_64 powerpc powerpc32 powerpc64 s390x ia64 sparc64 +PLATFORMS = x86 x86_64 powerpc powerpc32 powerpc64 s390x sparc64 TEMPFILES = $(addprefix temp-, $(addsuffix -generic, $(PLATFORMS))) configs: $(CONFIGFILES) @@ -44,16 +43,22 @@ temp-armv7l-omap-generic: config-arm-omap-generic temp-arm-generic temp-armv7l-tegra: config-arm-tegra temp-arm-generic perl merge.pl $^ > $@ -temp-x86-generic: config-x86-generic temp-generic +temp-x86-32: config-x86-32-generic config-x86-generic perl merge.pl $^ > $@ -temp-x86-debug-generic: config-x86-generic temp-debug-generic +temp-x86-32-generic: temp-x86-32 temp-generic perl merge.pl $^ > $@ -temp-x86_64-generic: config-x86_64-generic temp-generic +temp-x86-debug-generic: temp-x86-32 temp-debug-generic perl merge.pl $^ > $@ -temp-x86_64-debug-generic: config-x86_64-generic temp-debug-generic +temp-x86-64: config-x86_64-generic config-x86-generic + perl merge.pl $^ > $@ + +temp-x86_64-generic: temp-x86-64 temp-generic + perl merge.pl $^ > $@ + +temp-x86_64-debug-generic: temp-x86-64 temp-debug-generic perl merge.pl $^ > $@ temp-sparc64-generic: config-sparc64-generic temp-generic @@ -71,16 +76,13 @@ temp-powerpc32-generic: config-powerpc32-generic temp-powerpc-generic temp-s390-generic: config-s390x temp-generic perl merge.pl $^ > $@ -temp-ia64-generic: config-ia64-generic temp-generic - perl merge.pl $^ > $@ - -kernel-$(VERSION)-i686-PAE.config: config-i686-PAE temp-x86-generic +kernel-$(VERSION)-i686-PAE.config: config-i686-PAE temp-x86-32-generic perl merge.pl $^ i386 > $@ kernel-$(VERSION)-i686-PAEdebug.config: config-i686-PAE temp-x86-debug-generic perl merge.pl $^ i386 > $@ -kernel-$(VERSION)-i686.config: /dev/null temp-x86-generic +kernel-$(VERSION)-i686.config: /dev/null temp-x86-32-generic perl merge.pl $^ i386 > $@ kernel-$(VERSION)-i686-debug.config: /dev/null temp-x86-debug-generic @@ -127,6 +129,3 @@ kernel-$(VERSION)-ppc.config: /dev/null temp-powerpc32-generic kernel-$(VERSION)-ppc-smp.config: config-powerpc32-smp temp-powerpc32-generic perl merge.pl $^ powerpc > $@ - -kernel-$(VERSION)-ia64.config: /dev/null temp-ia64-generic - perl merge.pl $^ ia64 > $@ diff --git a/TEGRA-2.6.40.2-enable-USB-ports.patch b/TEGRA-2.6.40.2-enable-USB-ports.patch deleted file mode 100644 index 1fef5fec2..000000000 --- a/TEGRA-2.6.40.2-enable-USB-ports.patch +++ /dev/null @@ -1,111 +0,0 @@ ---- linux-2.6.39.armv7l/arch/arm/mach-tegra/board-trimslice-pinmux.c.TEGRA 2011-05-19 00:06:34.000000000 -0400 -+++ linux-2.6.39.armv7l/arch/arm/mach-tegra/board-trimslice-pinmux.c 2011-08-16 01:16:35.194157025 -0400 -@@ -126,7 +126,7 @@ - {TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, - {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, - {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, -- {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, -+ {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, - {TEGRA_PINGROUP_UAD, TEGRA_MUX_IRDA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, - {TEGRA_PINGROUP_UCA, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, - {TEGRA_PINGROUP_UCB, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, ---- linux-2.6.39.armv7l/arch/arm/mach-tegra/board-trimslice.c.TEGRA 2011-05-19 00:06:34.000000000 -0400 -+++ linux-2.6.39.armv7l/arch/arm/mach-tegra/board-trimslice.c 2011-08-16 01:25:44.679159239 -0400 -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -30,6 +31,8 @@ - - #include - #include -+#include -+#include - - #include "board.h" - #include "clock.h" -@@ -102,6 +105,68 @@ - } - subsys_initcall(tegra_trimslice_pci_init); - -+static struct tegra_utmip_config utmi_phy_config[] = { -+ [0] = { -+ .hssync_start_delay = 0, -+ .idle_wait_delay = 17, -+ .elastic_limit = 16, -+ .term_range_adj = 6, -+ .xcvr_setup = 15, -+ .xcvr_lsfslew = 2, -+ .xcvr_lsrslew = 2, -+ }, -+ [1] = { -+ .hssync_start_delay = 0, -+ .idle_wait_delay = 17, -+ .elastic_limit = 16, -+ .term_range_adj = 6, -+ .xcvr_setup = 8, -+ .xcvr_lsfslew = 2, -+ .xcvr_lsrslew = 2, -+ }, -+}; -+ -+static struct tegra_ehci_platform_data ehci1_data = { -+ .phy_config = &utmi_phy_config[0], -+ .operating_mode = TEGRA_USB_HOST, -+ .power_down_on_bus_suspend = 0, -+}; -+ -+struct tegra_ulpi_config ehci2_phy_config = { -+ .reset_gpio = TEGRA_GPIO_PV0, -+ .clk = "pll_m", -+}; -+ -+static struct tegra_ehci_platform_data ehci2_data = { -+ .operating_mode = TEGRA_USB_HOST, -+ .phy_config = &ehci2_phy_config, -+ .power_down_on_bus_suspend = 0, -+}; -+ -+static struct tegra_ehci_platform_data ehci3_data = { -+ .phy_config = &utmi_phy_config[1], -+ .operating_mode = TEGRA_USB_HOST, -+ .power_down_on_bus_suspend = 0, -+}; -+ -+static void trimslice_usb_init(void) -+{ -+ tegra_ehci3_device.dev.platform_data = &ehci3_data; -+ platform_device_register(&tegra_ehci3_device); -+ -+ tegra_gpio_enable(TEGRA_GPIO_PV0); -+ tegra_ehci2_device.dev.platform_data = &ehci2_data; -+ platform_device_register(&tegra_ehci2_device); -+ -+ tegra_gpio_enable(TEGRA_GPIO_PV2); -+ gpio_request(TEGRA_GPIO_PV2, "usb1 mode"); -+ gpio_direction_output(TEGRA_GPIO_PV2, 1); -+ -+ tegra_ehci1_device.dev.platform_data = &ehci1_data; -+ platform_device_register(&tegra_ehci1_device); -+} -+ -+ - static void __init tegra_trimslice_init(void) - { - tegra_clk_init_from_table(trimslice_clk_init_table); -@@ -112,8 +177,11 @@ - tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4; - - platform_add_devices(trimslice_devices, ARRAY_SIZE(trimslice_devices)); -+ -+ trimslice_usb_init(); - } - -+ - MACHINE_START(TRIMSLICE, "trimslice") - .boot_params = 0x00000100, - .fixup = tegra_trimslice_fixup, diff --git a/acpi-ec-add-delay-before-write.patch b/acpi-ec-add-delay-before-write.patch deleted file mode 100644 index f1cb50817..000000000 --- a/acpi-ec-add-delay-before-write.patch +++ /dev/null @@ -1,51 +0,0 @@ -https://bugzilla.kernel.org/show_bug.cgi?id=14733#c41 - -diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c -index 27e0b92..09fbb69 100644 ---- a/drivers/acpi/ec.c -+++ b/drivers/acpi/ec.c -@@ -226,6 +226,7 @@ static int ec_poll(struct acpi_ec *ec) - if (ec_transaction_done(ec)) - return 0; - } else { -+ msleep(1); - if (wait_event_timeout(ec->wait, - ec_transaction_done(ec), - msecs_to_jiffies(1))) -@@ -233,8 +234,8 @@ static int ec_poll(struct acpi_ec *ec) - } - advance_transaction(ec, acpi_ec_read_status(ec)); - } while (time_before(jiffies, delay)); -- if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) -- break; -+// if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) -+// break; - pr_debug(PREFIX "controller reset, restart transaction\n"); - spin_lock_irqsave(&ec->curr_lock, flags); - start_transaction(ec); -@@ -271,15 +272,24 @@ static int ec_check_ibf0(struct acpi_ec *ec) - return (status & ACPI_EC_FLAG_IBF) == 0; - } - -+/* try to clean input buffer with burst_disable transaction */ -+static int acpi_ec_clean_buffer(struct acpi_ec *ec) -+{ -+ struct transaction t = {.command = ACPI_EC_BURST_DISABLE, -+ .wdata = NULL, .rdata = NULL, -+ .wlen = 0, .rlen = 0}; -+ return acpi_ec_transaction_unlocked(ec, &t); -+} -+ - static int ec_wait_ibf0(struct acpi_ec *ec) - { - unsigned long delay = jiffies + msecs_to_jiffies(ec_delay); - /* interrupt wait manually if GPE mode is not active */ - while (time_before(jiffies, delay)) - if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), - msecs_to_jiffies(1))) - return 0; -- return -ETIME; -+ return acpi_ec_clean_buffer(ec); - } - - static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) diff --git a/add-appleir-usb-driver.patch b/add-appleir-usb-driver.patch index 26477ccce..0ab0ed6f4 100644 --- a/add-appleir-usb-driver.patch +++ b/add-appleir-usb-driver.patch @@ -140,9 +140,8 @@ diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 60de906..2f2f2e7 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig -@@ -209,6 +209,19 @@ config INPUT_KEYSPAN_REMOTE - To compile this driver as a module, choose M here: the module will - be called keyspan_remote. + help + Say Y here if you need accelerometer to work in polling mode. +config INPUT_APPLEIR + tristate "Apple infrared receiver (built in)" diff --git a/add-macbookair41-keyboard.patch b/add-macbookair41-keyboard.patch new file mode 100644 index 000000000..bd5afdafe --- /dev/null +++ b/add-macbookair41-keyboard.patch @@ -0,0 +1,119 @@ +Path: news.gmane.org!not-for-mail +From: Pieter-Augustijn Van Malleghem +Newsgroups: gmane.linux.kernel.input +Subject: [PATCH] Add MacBookAir4,1 keyboard support +Date: Wed, 7 Sep 2011 16:15:52 -0400 +Lines: 72 +Approved: news@gmane.org +Message-ID: <20110907201552.GA1962@Caligula> +NNTP-Posting-Host: lo.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +X-Trace: dough.gmane.org 1315426570 11003 80.91.229.12 (7 Sep 2011 20:16:10 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Wed, 7 Sep 2011 20:16:10 +0000 (UTC) +To: linux-input@vger.kernel.org +Original-X-From: linux-input-owner@vger.kernel.org Wed Sep 07 22:16:06 2011 +Return-path: +Envelope-to: glki-linux-input-2@lo.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1R1OXV-0007QX-Ll + for glki-linux-input-2@lo.gmane.org; Wed, 07 Sep 2011 22:16:06 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1751419Ab1IGUQE (ORCPT ); + Wed, 7 Sep 2011 16:16:04 -0400 +Original-Received: from mail-vx0-f174.google.com ([209.85.220.174]:57168 "EHLO + mail-vx0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1751237Ab1IGUQC (ORCPT + ); Wed, 7 Sep 2011 16:16:02 -0400 +Original-Received: by vxj15 with SMTP id 15so31147vxj.19 + for ; Wed, 07 Sep 2011 13:16:02 -0700 (PDT) +Original-Received: by 10.52.69.210 with SMTP id g18mr64348vdu.133.1315426562281; + Wed, 07 Sep 2011 13:16:02 -0700 (PDT) +Original-Received: from Caligula ([140.247.246.50]) + by mx.google.com with ESMTPS id ch2sm944169vdc.19.2011.09.07.13.16.01 + (version=TLSv1/SSLv3 cipher=OTHER); + Wed, 07 Sep 2011 13:16:01 -0700 (PDT) +Content-Disposition: inline +User-Agent: Mutt/1.5.21 (2010-09-15) +Original-Sender: linux-input-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-input@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel.input:21462 +Archived-At: + +This patch adds support for the Apple MacBookAir4,1 released in July +2011. It was inspired by Joshua Dillon's patch for the MacBookAir4,2 +posted on http://www.almostsure.com/mba42/hid-apple-dkms.patch. + +Signed-off-by: Pieter-Augustijn Van Malleghem +diff -uNr linux/drivers/hid/hid-apple.c patched/drivers/hid/hid-apple.c +--- linux/drivers/hid/hid-apple.c 2011-09-06 23:41:58.000000000 -0400 ++++ patched/drivers/hid/hid-apple.c 2011-09-06 23:53:05.000000000 -0400 +@@ -183,6 +183,9 @@ + if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && + hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) + table = macbookair_fn_keys; ++ else if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI && ++ hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) ++ table = apple_fn_keys; + else if (hid->product < 0x21d || hid->product >= 0x300) + table = powerbook_fn_keys; + else +@@ -493,6 +499,12 @@ + .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_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI), ++ .driver_data = APPLE_HAS_FN }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO), ++ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_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), +diff -uNr linux/drivers/hid/hid-core.c patched/drivers/hid/hid-core.c +--- linux/drivers/hid/hid-core.c 2011-09-06 23:41:58.000000000 -0400 ++++ patched/drivers/hid/hid-core.c 2011-09-06 23:56:22.000000000 -0400 +@@ -1340,6 +1340,9 @@ + { 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_WELLSPRING6A_ANSI) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) }, +@@ -1892,6 +1895,9 @@ + { 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_WELLSPRING6A_ANSI) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_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) }, + { } +diff -uNr linux/drivers/hid/hid-ids.h patched/drivers/hid/hid-ids.h +--- linux/drivers/hid/hid-ids.h 2011-09-06 23:41:58.000000000 -0400 ++++ patched/drivers/hid/hid-ids.h 2011-09-06 23:57:39.000000000 -0400 +@@ -109,6 +109,9 @@ + #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_WELLSPRING6A_ANSI 0x0249 ++#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a ++#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b + #define USB_DEVICE_ID_APPLE_ALU_REVB_ANSI 0x024f + #define USB_DEVICE_ID_APPLE_ALU_REVB_ISO 0x0250 + #define USB_DEVICE_ID_APPLE_ALU_REVB_JIS 0x0251 +-- +To unsubscribe from this list: send the line "unsubscribe linux-input" 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/arm-omap-dt-compat.patch b/arm-omap-dt-compat.patch index ab7cd0a4d..4046e938f 100644 --- a/arm-omap-dt-compat.patch +++ b/arm-omap-dt-compat.patch @@ -16,7 +16,7 @@ diff -up linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap3beagle.c.fdt linux-2 @@ -600,4 +605,5 @@ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagl .init_irq = omap3_beagle_init_irq, .init_machine = omap3_beagle_init, - .timer = &omap_timer, + .timer = &omap3_secure_timer, + .dt_compat = omap3_beagle_dt_match, MACHINE_END diff -up linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c.fdt linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c @@ -37,6 +37,6 @@ diff -up linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c.fdt linux-2. @@ -717,4 +722,5 @@ MACHINE_START(OMAP4_PANDA, "OMAP4 Panda .init_irq = gic_init_irq, .init_machine = omap4_panda_init, - .timer = &omap_timer, + .timer = &omap4_timer, + .dt_compat = omap4_panda_match, MACHINE_END diff --git a/be2net-move-to-new-vlan-model.patch b/be2net-move-to-new-vlan-model.patch deleted file mode 100644 index 781297144..000000000 --- a/be2net-move-to-new-vlan-model.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 1447378e3da1b56bb5c7fb1b1bc9b85e061447e7 Mon Sep 17 00:00:00 2001 -From: Ajit Khaparde -Date: Tue, 12 Jul 2011 22:10:01 -0700 -Subject: [PATCH 1/3] be2net: move to new vlan model - -Signed-off-by: Ajit Khaparde -Signed-off-by: David S. Miller ---- - drivers/net/benet/be.h | 1 - - drivers/net/benet/be_main.c | 34 +++++++++------------------------- - 2 files changed, 9 insertions(+), 26 deletions(-) - -diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h -index a7db870..5112000 100644 ---- a/drivers/net/benet/be.h -+++ b/drivers/net/benet/be.h -@@ -332,7 +332,6 @@ struct be_adapter { - u8 eq_next_idx; - struct be_drv_stats drv_stats; - -- struct vlan_group *vlan_grp; - u16 vlans_added; - u16 max_vlans; /* Number of vlans supported */ - u8 vlan_tag[VLAN_N_VID]; -diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c -index a485f7f..146e420 100644 ---- a/drivers/net/benet/be_main.c -+++ b/drivers/net/benet/be_main.c -@@ -648,7 +648,7 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, - AMAP_SET_BITS(struct amap_eth_hdr_wrb, udpcs, hdr, 1); - } - -- if (adapter->vlan_grp && vlan_tx_tag_present(skb)) { -+ if (vlan_tx_tag_present(skb)) { - AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1); - vlan_tag = vlan_tx_tag_get(skb); - vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; -@@ -842,13 +842,6 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num) - return status; - } - --static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp) --{ -- struct be_adapter *adapter = netdev_priv(netdev); -- -- adapter->vlan_grp = grp; --} -- - static void be_vlan_add_vid(struct net_device *netdev, u16 vid) - { - struct be_adapter *adapter = netdev_priv(netdev); -@@ -867,7 +860,6 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) - struct be_adapter *adapter = netdev_priv(netdev); - - adapter->vlans_added--; -- vlan_group_set_device(adapter->vlan_grp, vid, NULL); - - if (!be_physfn(adapter)) - return; -@@ -1196,16 +1188,10 @@ static void be_rx_compl_process(struct be_adapter *adapter, - skb->rxhash = rxcp->rss_hash; - - -- if (unlikely(rxcp->vlanf)) { -- if (!adapter->vlan_grp || adapter->vlans_added == 0) { -- kfree_skb(skb); -- return; -- } -- vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, -- rxcp->vlan_tag); -- } else { -- netif_receive_skb(skb); -- } -+ if (unlikely(rxcp->vlanf)) -+ __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag); -+ -+ netif_receive_skb(skb); - } - - /* Process the RX completion indicated by rxcp when GRO is enabled */ -@@ -1259,11 +1245,10 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, - if (adapter->netdev->features & NETIF_F_RXHASH) - skb->rxhash = rxcp->rss_hash; - -- if (likely(!rxcp->vlanf)) -- napi_gro_frags(&eq_obj->napi); -- else -- vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, -- rxcp->vlan_tag); -+ if (unlikely(rxcp->vlanf)) -+ __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag); -+ -+ napi_gro_frags(&eq_obj->napi); - } - - static void be_parse_rx_compl_v1(struct be_adapter *adapter, -@@ -2901,7 +2886,6 @@ static struct net_device_ops be_netdev_ops = { - .ndo_set_mac_address = be_mac_addr_set, - .ndo_change_mtu = be_change_mtu, - .ndo_validate_addr = eth_validate_addr, -- .ndo_vlan_rx_register = be_vlan_register, - .ndo_vlan_rx_add_vid = be_vlan_add_vid, - .ndo_vlan_rx_kill_vid = be_vlan_rem_vid, - .ndo_set_vf_mac = be_set_vf_mac, --- -1.7.6.4 - diff --git a/config-arm-generic b/config-arm-generic index 3886c6d8d..307c66d68 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -9,6 +9,7 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_ARCH_VERSATILE=y CONFIG_ARCH_VERSATILE_PB=y CONFIG_MACH_VERSATILE_AB=y +CONFIG_MACH_VERSATILE_DT=y CONFIG_HIGHMEM=y # CONFIG_HIGHPTE is not set @@ -149,9 +150,13 @@ CONFIG_USE_OF=y CONFIG_PROC_DEVICETREE=y CONFIG_MTD_PHYSMAP_OF=m CONFIG_SERIAL_OF_PLATFORM=m -# CONFIG_LEDS_GPIO_OF is not set CONFIG_MMC_SDHCI_OF=m +CONFIG_MMC_SDHCI_PXAV3=m +CONFIG_MMC_SDHCI_PXAV2=m +CONFIG_FTGMAC100=m + +# disable TPM on arm at least on the trimslices it causes havoc # CONFIG_TCG_TPM is not set # CONFIG_IMA is not set diff --git a/config-arm-omap-generic b/config-arm-omap-generic index 560dfe649..8c3ae6a24 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -276,6 +276,7 @@ CONFIG_TI_DAC7512=m CONFIG_BMP085=m CONFIG_C2PORT=m CONFIG_EEPROM_AT25=m +CONFIG_EEPROM_93XX46=m # CONFIG_IWMC3200TOP_DEBUGFS is not set # CONFIG_SCSI_PROC_FS is not set # CONFIG_BLK_DEV_SR_VENDOR is not set @@ -388,6 +389,7 @@ CONFIG_INPUT_AD714X_SPI=m # CONFIG_INPUT_APPLEIR is not set CONFIG_INPUT_TWL4030_PWRBUTTON=y CONFIG_INPUT_TWL4030_VIBRA=y +CONFIG_INPUT_TWL6040_VIBRA=y CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set CONFIG_INPUT_ADXL34X=m @@ -445,6 +447,7 @@ CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y # CONFIG_DEBUG_GPIO is not set CONFIG_GPIO_SYSFS=y +# CONFIG_GPIO_GENERIC_PLATFORM is not set # # Memory mapped GPIO expanders: @@ -568,6 +571,7 @@ CONFIG_OMAP_WATCHDOG=y CONFIG_SSB=y # CONFIG_SSB_SDIOHOST is not set CONFIG_MFD_CORE=y +# CONFIG_MFD_AAT2870_CORE is not set # CONFIG_MFD_88PM860X is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_ASIC3 is not set @@ -597,6 +601,8 @@ CONFIG_TWL4030_CODEC=y CONFIG_MFD_OMAP_USB_HOST=y # CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set # CONFIG_MFD_WL1273_CORE is not set CONFIG_REGULATOR=y # CONFIG_REGULATOR_DEBUG is not set @@ -640,6 +646,7 @@ CONFIG_VIDEO_SAA717X=m CONFIG_VIDEO_SAA7127=m CONFIG_VIDEO_UPD64031A=m CONFIG_VIDEO_UPD64083=m +CONFIG_VIDEO_ADP1653=m # # CONFIG_VIDEO_TVAUDIO is not set # CONFIG_VIDEO_TDA7432 is not set @@ -699,7 +706,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_ARMCLCD is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set -# CONFIG_FB_MB862XX is not set # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set # CONFIG_FB_OMAP_LCD_VGA is not set CONFIG_OMAP2_VRAM=y @@ -736,6 +742,7 @@ CONFIG_PANEL_TPO_TD043MTEA1=y # CONFIG_LCD_VGG2432A4 is not set # CONFIG_LCD_PLATFORM is not set # CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_AMS369FG06 is not set CONFIG_BACKLIGHT_GENERIC=m CONFIG_DISPLAY_SUPPORT=y # CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set @@ -790,6 +797,7 @@ CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=y CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y CONFIG_SND_OMAP_SOC_ZOOM2=y CONFIG_SND_OMAP_SOC_IGEP0020=y +CONFIG_SND_OMAP_SOC_OMAP4_HDMI=y CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_SND_SOC_ALL_CODECS is not set CONFIG_SND_SOC_TLV320AIC23=y @@ -920,6 +928,7 @@ CONFIG_MMC_SPI=m # CONFIG_MEMSTICK is not set CONFIG_LEDS_GPIO=y CONFIG_LEDS_GPIO_PLATFORM=y +CONFIG_LEDS_GPIO_OF=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set @@ -1028,7 +1037,6 @@ CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 CONFIG_DEBUG_PREEMPT=y # CONFIG_BKL is not set # CONFIG_SPARSE_RCU_POINTER is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_HIGHMEM is not set # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_LIST is not set diff --git a/config-arm-tegra b/config-arm-tegra index c8f1eec24..910b39f81 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -4,8 +4,8 @@ CONFIG_MACH_KAEN=y CONFIG_MACH_PAZ00=y CONFIG_MACH_TRIMSLICE=y CONFIG_MACH_WARIO=y +CONFIG_MACH_TEGRA_DT=y CONFIG_TEGRA_DEBUG_UARTD=y -CONFIG_ARM_ERRATA_742230=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y @@ -31,6 +31,7 @@ CONFIG_CACHE_L2X0=y CONFIG_ARM_ERRATA_430973=y # CONFIG_ARM_ERRATA_458693 is not set # CONFIG_ARM_ERRATA_460075 is not set +CONFIG_ARM_ERRATA_742230=y # CONFIG_ARM_ERRATA_742231 is not set CONFIG_PL310_ERRATA_588369=y CONFIG_ARM_ERRATA_720789=y @@ -47,10 +48,11 @@ CONFIG_LOCAL_TIMERS=y CONFIG_HW_PERF_EVENTS=y # CONFIG_NEON is not set # CONFIG_RFKILL_GPIO is not set +CONFIG_GPIO_GENERIC_PLATFORM=y +# CONFIG_GPIO_MCP23S08 is not set CONFIG_KEYBOARD_TEGRA=y # CONFIG_MPCORE_WATCHDOG is not set CONFIG_USB_EHCI_TEGRA=y -CONFIG_USB_STORAGE=y CONFIG_RTC_DRV_TEGRA=m CONFIG_SND_SOC_TEGRA=m diff --git a/config-debug b/config-debug index 7bbaa0b59..a25239038 100644 --- a/config-debug +++ b/config-debug @@ -2,6 +2,8 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y +CONFIG_DEBUG_ATOMIC_SLEEP=y + CONFIG_DEBUG_MUTEXES=y CONFIG_DEBUG_RT_MUTEXES=y CONFIG_DEBUG_LOCK_ALLOC=y @@ -70,7 +72,7 @@ CONFIG_DEBUG_PERF_USE_VMALLOC=y CONFIG_JBD2_DEBUG=y -CONFIG_DEBUG_CFQ_IOSCHED=y +CONFIG_DEBUG_BLK_CGROUP=y CONFIG_DRBD_FAULT_INJECTION=y @@ -98,3 +100,8 @@ CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y CONFIG_TEST_LIST_SORT=y CONFIG_DEBUG_SET_MODULE_RONX=y + +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set + diff --git a/config-generic b/config-generic index 0a6785bce..39851a235 100644 --- a/config-generic +++ b/config-generic @@ -45,7 +45,6 @@ CONFIG_LOG_BUF_SHIFT=17 # CONFIG_EXPERT is not set CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y -CONFIG_KALLSYMS_EXTRA_PASS=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y @@ -92,7 +91,6 @@ CONFIG_PCI_STUB=y CONFIG_PCI_IOV=y CONFIG_HT_IRQ=y CONFIG_PCI_MSI=y -CONFIG_PCI_MSI_DEFAULT_ON=y CONFIG_PCIEPORTBUS=y CONFIG_PCIEAER=y CONFIG_PCIEASPM=y @@ -101,7 +99,6 @@ CONFIG_PCIE_ECRC=y CONFIG_PCIEAER_INJECT=m CONFIG_HOTPLUG_PCI_PCIE=y CONFIG_HOTPLUG_PCI_FAKE=m -CONFIG_PCI_LEGACY=y CONFIG_ISA=y # CONFIG_EISA is not set @@ -118,7 +115,6 @@ CONFIG_YENTA=m CONFIG_CARDBUS=y CONFIG_I82092=m CONFIG_PD6729=m -CONFIG_PCMCIA_IOCTL=y CONFIG_PCCARD=y CONFIG_MMC=m @@ -195,9 +191,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 CONFIG_MTD_CMDLINE_PARTS=y # # User Modules And Translation Layers @@ -359,6 +353,7 @@ CONFIG_CISS_SCSI_TAPE=y CONFIG_BLK_DEV_DAC960=m CONFIG_BLK_DEV_UMEM=m CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_OSD=m @@ -375,6 +370,7 @@ CONFIG_BLK_DEV_DELKIN=m # CONFIG_BLK_DEV_TC86C001 is not set CONFIG_LBDAF=y CONFIG_BLK_DEV_BSG=y +CONFIG_BLK_DEV_BSGLIB=y CONFIG_BLK_DEV_INTEGRITY=y CONFIG_BLK_DEV_THROTTLING=y @@ -486,7 +482,6 @@ CONFIG_SCSI_SAS_ATTRS=m CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SAS_ATA=y -# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set CONFIG_SCSI_SAS_HOST_SMP=y CONFIG_RAID_ATTRS=m @@ -528,6 +523,7 @@ CONFIG_MEGARAID_LEGACY=m CONFIG_MEGARAID_SAS=m CONFIG_SCSI_MVSAS=m # CONFIG_SCSI_MVSAS_DEBUG is not set +CONFIG_SCSI_MVSAS_TASKLET=y CONFIG_SCSI_MPT2SAS=m CONFIG_SCSI_MPT2SAS_MAX_SGE=128 CONFIG_SCSI_MPT2SAS_LOGGING=y @@ -725,7 +721,6 @@ CONFIG_FIREWIRE_NOSY=m # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -734,6 +729,10 @@ CONFIG_FIREWIRE_NOSY=m # CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set # +# Virtualization support drivers +# +# CONFIG_VIRT_DRIVERS is not set + # Networking support # CONFIG_NET=y @@ -758,7 +757,6 @@ CONFIG_TCP_MD5SIG=y # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_NET_KEY=m CONFIG_NET_KEY_MIGRATE=y @@ -844,9 +842,7 @@ CONFIG_NET_9P_VIRTIO=m # CONFIG_NET_9P_DEBUG is not set CONFIG_NET_9P_RDMA=m -CONFIG_DECNET=m -CONFIG_DECNET_ROUTER=y -# CONFIG_DECNET_NF_GRABULATOR is not set +# CONFIG_DECNET is not set CONFIG_BRIDGE=m CONFIG_BRIDGE_IGMP_SNOOPING=y # CONFIG_NETWORK_PHY_TIMESTAMPING is not set @@ -924,7 +920,6 @@ CONFIG_BRIDGE_NETFILTER=y # IP: Netfilter Configuration # -CONFIG_NF_CT_ACCT=y CONFIG_NF_CONNTRACK_MARK=y CONFIG_NF_CONNTRACK_SECMARK=y CONFIG_NF_CONNTRACK_EVENTS=y @@ -950,7 +945,6 @@ CONFIG_NF_CT_PROTO_SCTP=m CONFIG_NF_CT_NETLINK=m CONFIG_NF_CT_PROTO_UDPLITE=m -CONFIG_IP_NF_MATCH_ADDRTYPE=m CONFIG_IP_NF_MATCH_AH=m CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_TTL=m @@ -1043,6 +1037,7 @@ 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_HASH_NETIFACE=m CONFIG_IP_SET_LIST_SET=m # @@ -1076,7 +1071,6 @@ CONFIG_IP_DCCP_CCID2=m # CONFIG_IP_DCCP_CCID2_DEBUG is not set CONFIG_IP_DCCP_CCID3=y # CONFIG_IP_DCCP_CCID3_DEBUG is not set -CONFIG_IP_DCCP_CCID3_RTO=100 # CONFIG_IP_DCCP_DEBUG is not set CONFIG_NET_DCCPPROBE=m @@ -1300,7 +1294,6 @@ CONFIG_ATL1E=m CONFIG_E100=m CONFIG_FEALNX=m CONFIG_FORCEDETH=m -CONFIG_FORCEDETH_NAPI=y CONFIG_NATSEMI=m CONFIG_NE2K_PCI=m CONFIG_8139CP=m @@ -1344,9 +1337,9 @@ CONFIG_NS83820=m CONFIG_HAMACHI=m CONFIG_YELLOWFIN=m CONFIG_R8169=m -CONFIG_R8169_VLAN=y CONFIG_SKGE=m # CONFIG_SKGE_DEBUG is not set +CONFIG_SKGE_GENESIS=y CONFIG_TIGON3=m CONFIG_SKY2=m # CONFIG_SKY2_DEBUG is not set @@ -1410,9 +1403,6 @@ CONFIG_SLIP_SMART=y # CONFIG_WLAN=y # CONFIG_STRIP is not set -# CONFIG_ARLAN is not set -CONFIG_PCMCIA_WAVELAN=m -CONFIG_PCMCIA_NETWAVE=m # CONFIG_PCMCIA_RAYCS is not set CONFIG_WIRELESS=y @@ -1424,7 +1414,6 @@ CONFIG_CFG80211_DEBUGFS=y CONFIG_CFG80211_DEFAULT_PS=y CONFIG_NL80211=y # CONFIG_NL80211_TESTMODE is not set -# CONFIG_WIRELESS_OLD_REGULATORY is not set CONFIG_WIRELESS_EXT=y CONFIG_WIRELESS_EXT_SYSFS=y CONFIG_LIB80211=m @@ -1472,6 +1461,7 @@ CONFIG_ATMEL=m CONFIG_B43=m CONFIG_B43_PCMCIA=y CONFIG_B43_SDIO=y +CONFIG_B43_BCMA=y # CONFIG_B43_DEBUG is not set CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y @@ -1514,7 +1504,6 @@ CONFIG_LIBERTAS_MESH=y 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 @@ -1523,9 +1512,7 @@ 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 -CONFIG_IWL3945_SPECTRUM_MEASUREMENT=y # CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE is not set CONFIG_IWM=m # CONFIG_IWM_DEBUG is not set @@ -1566,7 +1553,6 @@ CONFIG_USB_NET_KALMIA=m CONFIG_USB_NET_SMSC75XX=m CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set -CONFIG_AR9170_USB=m CONFIG_WL12XX_MENU=m CONFIG_WL12XX=m @@ -1578,13 +1564,11 @@ CONFIG_WL12XX_SDIO=m CONFIG_WL1251=m CONFIG_WL1251_SPI=m CONFIG_WL1251_SDIO=m -CONFIG_WL1271=m -CONFIG_WL1271_SDIO=m -CONFIG_WL1271_SPI=m CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192CU=m +CONFIG_RTL8192DE=m CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m @@ -1665,6 +1649,8 @@ CONFIG_BAYCOM_PAR=m CONFIG_BAYCOM_EPP=m CONFIG_YAM=m +CONFIG_NFC=m + # # IrDA (infrared) support # @@ -1708,7 +1694,6 @@ CONFIG_WINBOND_FIR=m # CONFIG_BT=m CONFIG_BT_L2CAP=y -CONFIG_BT_L2CAP_EXT_FEATURES=y CONFIG_BT_SCO=y CONFIG_BT_CMTP=m CONFIG_BT_RFCOMM=m @@ -1833,8 +1818,6 @@ CONFIG_ISDN_CAPI=m CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y CONFIG_ISDN_CAPI_MIDDLEWARE=y CONFIG_ISDN_CAPI_CAPI20=m -CONFIG_ISDN_CAPI_CAPIFS_BOOL=y -CONFIG_ISDN_CAPI_CAPIFS=m # # CAPI hardware drivers @@ -1999,7 +1982,6 @@ CONFIG_TOUCHSCREEN_INEXIO=m CONFIG_TOUCHSCREEN_MTOUCH=m CONFIG_TOUCHSCREEN_MCS5000=m CONFIG_TOUCHSCREEN_MK712=m -# CONFIG_TOUCHSCREEN_QT602240 is not set CONFIG_TOUCHSCREEN_PENMOUNT=m # CONFIG_TOUCHSCREEN_TPS6507X is not set CONFIG_TOUCHSCREEN_TSC2007=m @@ -2031,10 +2013,13 @@ CONFIG_MAC_EMUMOUSEBTN=y CONFIG_INPUT_WM831X_ON=m -CONFIG_INPUT_APPLEIR=m # CONFIG_INPUT_AD714X is not set # CONFIG_INPUT_PCF8574 is not set +CONFIG_INPUT_MMA8450=m +CONFIG_INPUT_MPU3050=m +CONFIG_INPUT_KXTJ9=m +# CONFIG_INPUT_KXTJ9_POLLED_MODE is not set # # Character devices @@ -2075,19 +2060,12 @@ CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_SHARE_IRQ=y # CONFIG_SERIAL_8250_DETECT_IRQ is not set CONFIG_SERIAL_8250_RSA=y -# CONFIG_COMPUTONE is not set CONFIG_CYCLADES=m # CONFIG_CYZ_INTR is not set -# CONFIG_DIGIEPCA is not set # CONFIG_MOXA_INTELLIO is not set # CONFIG_MOXA_SMARTIO is not set # CONFIG_ISI is not set -# CONFIG_RISCOM8 is not set -# CONFIG_SPECIALIX is not set -# CONFIG_SX is not set # CONFIG_RIO is not set -# CONFIG_STALLION is not set -# CONFIG_ISTALLION is not set CONFIG_SERIAL_JSM=m # CONFIG_SERIAL_MFD_HSU is not set @@ -2138,7 +2116,6 @@ CONFIG_I2C_ALGOPCA=m # CONFIG_I2C_AMD8111 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_I2C_ELEKTOR is not set # CONFIG_I2C_I801 is not set # CONFIG_I2C_ISCH is not set @@ -2191,7 +2168,6 @@ CONFIG_SENSORS_ADM9240=m CONFIG_SENSORS_ADS7828=m CONFIG_SENSORS_ADT7462=m CONFIG_SENSORS_ADT7470=m -CONFIG_SENSORS_ADT7473=m CONFIG_SENSORS_ADT7475=m CONFIG_SENSORS_APPLESMC=m CONFIG_SENSORS_ASB100=m @@ -2231,6 +2207,7 @@ CONFIG_SENSORS_LM93=m CONFIG_SENSORS_LTC4245=m CONFIG_SENSORS_MAX1619=m CONFIG_SENSORS_MAX6650=m +CONFIG_SENSORS_NTC_THERMISTOR=m CONFIG_SENSORS_PC87360=m CONFIG_SENSORS_PC87427=m CONFIG_SENSORS_PCF8591=m @@ -2261,6 +2238,7 @@ CONFIG_SENSORS_W83792D=m CONFIG_SENSORS_W83793=m CONFIG_SENSORS_LTC4215=m CONFIG_SENSORS_LM95241=m +CONFIG_SENSORS_LM95245=m CONFIG_SENSORS_TMP421=m CONFIG_SENSORS_WM8350=m CONFIG_SENSORS_WM831X=m @@ -2284,6 +2262,7 @@ CONFIG_SENSORS_LINEAGE=m CONFIG_SENSORS_LTC4151=m CONFIG_SENSORS_MAX6639=m CONFIG_SENSORS_SCH5627=m +CONFIG_SENSORS_SCH5636=m CONFIG_SENSORS_ADS1015=m CONFIG_SENSORS_MAX16065=m CONFIG_SENSORS_MAX6642=m @@ -2295,13 +2274,16 @@ CONFIG_SENSORS_EMC6W201=m CONFIG_PMBUS=m CONFIG_SENSORS_PMBUS=m CONFIG_SENSORS_MAX16064=m +CONFIG_SENSORS_LM25066=m CONFIG_SENSORS_MAX34440=m CONFIG_SENSORS_MAX8688=m +CONFIG_SENSORS_MAX1668=m # CONFIG_HMC6352 is not set # CONFIG_BMP085 is not set # CONFIG_PCH_PHUB is not set # CONFIG_SERIAL_PCH_UART is not set +# CONFIG_USB_SWITCH_FSA9480 is not set CONFIG_W1=m CONFIG_W1_CON=y @@ -2341,6 +2323,7 @@ CONFIG_IPMI_POWEROFF=m # Watchdog Cards # CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_CORE=y # CONFIG_WATCHDOG_NOWAYOUT is not set CONFIG_SOFT_WATCHDOG=m CONFIG_WDTPCI=m @@ -2375,6 +2358,7 @@ CONFIG_USBPCWATCHDOG=m CONFIG_WM8350_WATCHDOG=m CONFIG_WM831X_WATCHDOG=m # CONFIG_MAX63XX_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_TIMERIOMEM=m @@ -2454,7 +2438,6 @@ CONFIG_DRM_R128=m CONFIG_DRM_RADEON=m CONFIG_DRM_RADEON_KMS=y CONFIG_DRM_I810=m -# CONFIG_DRM_I830 is not set CONFIG_DRM_MGA=m CONFIG_DRM_SIS=m CONFIG_DRM_SAVAGE=m @@ -2489,8 +2472,6 @@ 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 @@ -2526,6 +2507,7 @@ CONFIG_VIDEO_CX88_VP3054=m CONFIG_VIDEO_EM28XX=m CONFIG_VIDEO_EM28XX_ALSA=m CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_VIDEO_EM28XX_RC=y CONFIG_VIDEO_CX231XX=m CONFIG_VIDEO_CX231XX_ALSA=m CONFIG_VIDEO_CX231XX_DVB=m @@ -2535,17 +2517,13 @@ CONFIG_VIDEO_HEXIUM_GEMINI=m CONFIG_VIDEO_IVTV=m CONFIG_VIDEO_MEYE=m CONFIG_VIDEO_MXB=m -# CONFIG_VIDEO_OVCAMCHIP is not set CONFIG_VIDEO_PVRUSB2_DVB=y CONFIG_VIDEO_HDPVR=m -CONFIG_VIDEO_SAA5246A=m -CONFIG_VIDEO_SAA5249=m CONFIG_VIDEO_SAA6588=m CONFIG_VIDEO_SAA7134=m CONFIG_VIDEO_SAA7134_ALSA=m CONFIG_VIDEO_SAA7134_DVB=m CONFIG_VIDEO_SAA7134_RC=y -CONFIG_VIDEO_STRADIS=m CONFIG_VIDEO_USBVISION=m CONFIG_VIDEO_W9966=m CONFIG_VIDEO_ZORAN=m @@ -2568,9 +2546,7 @@ CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y # # Radio Adapters # -CONFIG_RADIO_GEMTEK_PCI=m CONFIG_RADIO_MAXIRADIO=m -CONFIG_RADIO_MAESTRO=m CONFIG_RADIO_WL1273=m CONFIG_RADIO_WL128X=m @@ -2587,6 +2563,7 @@ CONFIG_MEDIA_TUNER_MT2131=m CONFIG_MEDIA_TUNER_QT1010=m CONFIG_MEDIA_TUNER_XC2028=m CONFIG_MEDIA_TUNER_XC5000=m +CONFIG_MEDIA_TUNER_XC4000=m CONFIG_MEDIA_TUNER_MXL5005S=m CONFIG_MEDIA_TUNER_MXL5007T=m CONFIG_MEDIA_TUNER_MC44S803=m @@ -2599,6 +2576,7 @@ CONFIG_MEDIA_TUNER_TDA18212=m # CONFIG_DVB_CAPTURE_DRIVERS=y CONFIG_DVB_CORE=m +CONFIG_DVB_NET=y CONFIG_DVB_MAX_ADAPTERS=8 CONFIG_DVB_DYNAMIC_MINORS=y @@ -2607,6 +2585,8 @@ CONFIG_DVB_STB0899=m CONFIG_DVB_STB6100=m CONFIG_DVB_STV090x=m CONFIG_DVB_STV6110x=m +CONFIG_DVB_DRXK=m +CONFIG_DVB_TDA18271C2DD=m CONFIG_DVB_CX24110=m CONFIG_DVB_CX24123=m CONFIG_DVB_MT312=m @@ -2684,14 +2664,13 @@ CONFIG_DVB_USB_DW2102=m CONFIG_DVB_USB_FRIIO=m CONFIG_DVB_USB_EC168=m CONFIG_DVB_DM1105=m -CONFIG_DVB_DRX397XD=m -CONFIG_DVB_LGDT3304=m CONFIG_DVB_S921=m CONFIG_DVB_ISL6405=m CONFIG_DVB_LGS8GL5=m CONFIG_DVB_DUMMY_FE=m CONFIG_DVB_FIREDTV=m CONFIG_DVB_NGENE=m +CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_MB86A20S=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_DIB9000=m @@ -2769,6 +2748,7 @@ CONFIG_IR_RC6_DECODER=m CONFIG_IR_JVC_DECODER=m CONFIG_IR_SONY_DECODER=m CONFIG_IR_RC5_SZ_DECODER=m +CONFIG_IR_MCE_KBD_DECODER=m CONFIG_IR_LIRC_CODEC=m CONFIG_IR_IMON=m CONFIG_IR_MCEUSB=m @@ -2862,10 +2842,7 @@ 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_MB862XX is not set # CONFIG_FB_PRE_INIT_FB is not set # CONFIG_FB_TMIO is not set # CONFIG_FB_BROADSHEET is not set @@ -2988,24 +2965,23 @@ CONFIG_SND_HDA_INPUT_JACK=y CONFIG_SND_HDA_PATCH_LOADER=y CONFIG_SND_HDA_HWDEP=y CONFIG_SND_HDA_CODEC_REALTEK=y +CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS=y CONFIG_SND_HDA_CODEC_CA0110=y CONFIG_SND_HDA_CODEC_ANALOG=y CONFIG_SND_HDA_CODEC_SIGMATEL=y CONFIG_SND_HDA_CODEC_VIA=y -CONFIG_SND_HDA_CODEC_ATIHDMI=y CONFIG_SND_HDA_CODEC_CIRRUS=y CONFIG_SND_HDA_CODEC_CONEXANT=y CONFIG_SND_HDA_CODEC_CMEDIA=y -CONFIG_SND_HDA_CODEC_INTELHDMI=y CONFIG_SND_HDA_CODEC_SI3054=y -CONFIG_SND_HDA_CODEC_NVHDMI=y CONFIG_SND_HDA_CODEC_HDMI=y +CONFIG_SND_HDA_CODEC_CA0132=y CONFIG_SND_HDA_GENERIC=y CONFIG_SND_HDA_POWER_SAVE=y CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 CONFIG_SND_HDA_RECONFIG=y +CONFIG_SND_HDA_PREALLOC_SIZE=4096 CONFIG_SND_HDSPM=m -CONFIG_SND_HIFIER=m CONFIG_SND_ICE1712=m CONFIG_SND_ICE1724=m CONFIG_SND_INTEL8X0=y @@ -3154,18 +3130,13 @@ CONFIG_USB_IDMOUSE=m CONFIG_DRAGONRISE_FF=y CONFIG_GREENASIA_FF=y CONFIG_SMARTJOYPLUS_FF=y -CONFIG_HID_3M_PCT=y CONFIG_LOGIG940_FF=y CONFIG_HID_MAGICMOUSE=y -CONFIG_HID_MOSART=y CONFIG_HID_MULTITOUCH=m CONFIG_HID_NTRIG=y CONFIG_HID_QUANTA=y -CONFIG_HID_STANTUM=y -CONFIG_HID_CANDO=m CONFIG_HID_PRODIKEYS=m CONFIG_HID_DRAGONRISE=m -CONFIG_HID_EGALAX=m CONFIG_HID_GYRATION=m CONFIG_HID_TWINHAN=m CONFIG_HID_ORTEK=m @@ -3195,6 +3166,10 @@ CONFIG_HID_KEYTOUCH=m CONFIG_HID_LCPOWER=m CONFIG_HID_ROCCAT_ARVO=m CONFIG_HID_ROCCAT_KOVAPLUS=m +CONFIG_HID_HOLTEK=m +CONFIG_HOLTEK_FF=y +CONFIG_HID_SPEEDLINK=m +CONFIG_HID_WIIMOTE=m # # USB Imaging devices @@ -3205,10 +3180,7 @@ CONFIG_USB_MICROTEK=m # # USB Multimedia devices # -CONFIG_DAB=y -CONFIG_USB_DABUSB=m -CONFIG_USB_VICAM=m CONFIG_USB_DSBR=m # CONFIG_USB_ET61X251 is not set CONFIG_USB_M5602=m @@ -3228,7 +3200,6 @@ CONFIG_USB_GSPCA_PAC207=m CONFIG_USB_GSPCA_PAC7311=m CONFIG_USB_GSPCA_SN9C2028=m CONFIG_USB_GSPCA_SN9C20X=m -CONFIG_USB_GSPCA_SN9C20X_EVDEV=y CONFIG_USB_GSPCA_SONIXB=m CONFIG_USB_GSPCA_SONIXJ=m CONFIG_USB_GSPCA_SPCA500=m @@ -3256,15 +3227,11 @@ CONFIG_USB_GSPCA_SQ930X=m CONFIG_USB_GSPCA_NW80X=m CONFIG_USB_GSPCA_VICAM=m CONFIG_USB_GSPCA_KINECT=m +CONFIG_USB_GSPCA_SE401=m -CONFIG_USB_IBMCAM=m -CONFIG_USB_KONICAWC=m -# CONFIG_USB_OV511 is not set CONFIG_USB_S2255=m -CONFIG_USB_SE401=m # CONFIG_VIDEO_SH_MOBILE_CEU is not set # CONFIG_VIDEO_SH_MOBILE_CSI2 is not set -# CONFIG_USB_STV680 is not set # CONFIG_USB_SN9C102 is not set CONFIG_USB_ZR364XX=m CONFIG_SOC_CAMERA=m @@ -3279,6 +3246,7 @@ CONFIG_SOC_CAMERA_MT9T112=m CONFIG_SOC_CAMERA_RJ54N1=m CONFIG_SOC_CAMERA_OV9640=m CONFIG_SOC_CAMERA_OV6650=m +CONFIG_SOC_CAMERA_OV5642=m CONFIG_SOC_CAMERA_IMX074=m CONFIG_SOC_CAMERA_OV2640=m CONFIG_SOC_CAMERA_OV9740=m @@ -3399,7 +3367,6 @@ CONFIG_USB_SERIAL_QCAUX=m CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m CONFIG_USB_SERIAL_DEBUG=m CONFIG_USB_SERIAL_SSU100=m -CONFIG_USB_SERIAL_SAMBA=m CONFIG_USB_SERIAL_CONSOLE=y @@ -3418,7 +3385,6 @@ CONFIG_USB_SEVSEG=m CONFIG_USB_ALI_M5632=y CONFIG_USB_APPLEDISPLAY=m CONFIG_USB_ATM=m -CONFIG_USB_BERRY_CHARGE=m CONFIG_USB_CXACRU=m # CONFIG_USB_C67X00_HCD is not set # CONFIG_USB_CYTHERM is not set @@ -3428,7 +3394,6 @@ CONFIG_USB_FTDI_ELAN=m CONFIG_USB_FILE_STORAGE=m # CONFIG_USB_FILE_STORAGE_TEST is not set # CONFIG_USB_GADGET is not set -# CONFIG_USB_GADGET_GOKU is not set # CONFIG_USB_GADGETFS is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set @@ -3436,7 +3401,6 @@ CONFIG_USB_FILE_STORAGE=m CONFIG_USB_IOWARRIOR=m CONFIG_USB_ISIGHTFW=m CONFIG_USB_YUREX=m -CONFIG_USB_VST=m CONFIG_USB_LCD=m CONFIG_USB_LD=m CONFIG_USB_LEGOTOWER=m @@ -3445,7 +3409,6 @@ CONFIG_USB_PWC=m 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_SISUSBVGA=m CONFIG_USB_SISUSBVGA_CON=y CONFIG_RADIO_SI470X=y @@ -3460,7 +3423,6 @@ CONFIG_USB_TRANCEVIBRATOR=m CONFIG_USB_U132_HCD=m CONFIG_USB_UEAGLEATM=m CONFIG_USB_XUSBATM=m -# CONFIG_USB_ZC0301 is not set CONFIG_USB_ZERO=m CONFIG_USB_ANNOUNCE_NEW_DEVICES=y @@ -3512,7 +3474,7 @@ CONFIG_MFD_WM8400=m # CONFIG_MFD_RDC321X is not set # CONFIG_MFD_JANZ_CMODIO is not set # CONFIG_MFD_WM831X_I2C is not set -CONFIG_MFD_CS5535=m +# CONFIG_MFD_CS5535 is not set # # File systems @@ -3563,7 +3525,6 @@ CONFIG_QFMT_V2=y CONFIG_QUOTACTL=y CONFIG_DNOTIFY=y # Autofsv3 is obsolete. -# CONFIG_AUTOFS_FS is not set # systemd is dependant upon AUTOFS, so build it in. CONFIG_AUTOFS4_FS=y CONFIG_EXOFS_FS=m @@ -3641,6 +3602,7 @@ CONFIG_SQUASHFS=m CONFIG_SQUASHFS_XATTR=y CONFIG_SQUASHFS_LZO=y CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_ZLIB=y # CONFIG_SQUASHFS_EMBEDDED is not set CONFIG_VXFS_FS=m # CONFIG_HPFS_FS is not set @@ -3672,8 +3634,8 @@ CONFIG_NFSD_V4=y 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_PNFS_BLOCK=m CONFIG_LOCKD=m CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y @@ -3681,13 +3643,9 @@ CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m CONFIG_SUNRPC_XPRT_RDMA=m CONFIG_RPCSEC_GSS_KRB5=m -CONFIG_RPCSEC_GSS_SPKM3=m -# CONFIG_SMB_FS is not set -# CONFIG_SMB_NLS_DEFAULT is not set CONFIG_CIFS=m CONFIG_CIFS_STATS=y # CONFIG_CIFS_STATS2 is not set -CONFIG_CIFS_EXPERIMENTAL=y CONFIG_CIFS_UPCALL=y CONFIG_CIFS_XATTR=y CONFIG_CIFS_POSIX=y @@ -3931,6 +3889,8 @@ CONFIG_CRC32=m CONFIG_CRC_CCITT=m CONFIG_CRC_ITU_T=m CONFIG_CRC_T10DIF=m +CONFIG_CRC8=m +CONFIG_CORDIC=m CONFIG_CRYPTO_ZLIB=m CONFIG_ZLIB_INFLATE=y @@ -3967,7 +3927,6 @@ CONFIG_SCHEDSTATS=y CONFIG_SCHED_DEBUG=y CONFIG_FAIR_GROUP_SCHED=y CONFIG_SCHED_OMIT_FRAME_POINTER=y -CONFIG_GROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_SCHED_AUTOGROUP=y @@ -3976,14 +3935,13 @@ CONFIG_PROC_PID_CPUSET=y CONFIG_CGROUPS=y # CONFIG_CGROUP_DEBUG is not set -CONFIG_CGROUP_NS=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_FREEZER=y 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_MEM_RES_CTLR_SWAP_ENABLED is not set CONFIG_CGROUP_PERF=y CONFIG_BLK_CGROUP=y # CONFIG_DEBUG_BLK_CGROUP is not set @@ -4015,6 +3973,19 @@ CONFIG_PM_TRACE=y # CONFIG_PM_TEST_SUSPEND is not set CONFIG_PM_RUNTIME=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEBUG=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y + ## BEGIN ISA Junk. CONFIG_I82365=m @@ -4074,7 +4045,6 @@ CONFIG_EWRK3=m # CONFIG_SKISA is not set # CONFIG_PROTEON is not set # CONFIG_SMCTR is not set -# CONFIG_WAVELAN is not set # CONFIG_HISAX_16_0 is not set # CONFIG_HISAX_AVM_A1 is not set # CONFIG_HISAX_IX1MICROR2 is not set @@ -4127,7 +4097,6 @@ CONFIG_RADIO_ADAPTERS=y # CONFIG_SND_AD1848 is not set # CONFIG_SND_CS4231 is not set CONFIG_SND_CS4236=m -# CONFIG_SND_ES968 is not set # CONFIG_SND_ES1688 is not set # CONFIG_SND_ES18XX is not set # CONFIG_SND_GUSCLASSIC is not set @@ -4146,9 +4115,7 @@ CONFIG_SND_SBAWE=m # CONFIG_SND_ALS100 is not set # CONFIG_SND_AZT2320 is not set # CONFIG_SND_CMI8330 is not set -# CONFIG_SND_DT019X is not set CONFIG_SND_OPL3SA2=m -# CONFIG_SND_SGALAXY is not set # CONFIG_SND_SSCAPE is not set CONFIG_SND_DARLA20=m CONFIG_SND_GINA20=m @@ -4175,6 +4142,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_AMS_DELTA is not set # CONFIG_LEDS_LOCOMO is not set # CONFIG_LEDS_NET48XX is not set +# CONFIG_LEDS_NET5501 is not set # CONFIG_LEDS_PCA9532 is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_BD2802 is not set @@ -4215,9 +4183,7 @@ CONFIG_DYNAMIC_FTRACE=y # CONFIG_IRQSOFF_TRACER is not set CONFIG_SCHED_TRACER=y CONFIG_CONTEXT_SWITCH_TRACER=y -CONFIG_WORKQUEUE_TRACER=y CONFIG_FTRACE_SYSCALLS=y -CONFIG_KMEMTRACE=y CONFIG_FTRACE_MCOUNT_RECORD=y # CONFIG_FTRACE_STARTUP_TEST is not set # CONFIG_TRACE_BRANCH_PROFILING is not set @@ -4227,6 +4193,7 @@ CONFIG_FUNCTION_TRACER=y CONFIG_STACK_TRACER=y CONFIG_KPROBES=y +CONFIG_JUMP_LABEL=y CONFIG_OPTPROBES=y # CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set @@ -4266,7 +4233,6 @@ CONFIG_AUXDISPLAY=y CONFIG_UIO=m CONFIG_UIO_CIF=m -CONFIG_UIO_SMX=m # CONFIG_UIO_PDRV is not set # CONFIG_UIO_PDRV_GENIRQ is not set CONFIG_UIO_AEC=m @@ -4280,20 +4246,14 @@ CONFIG_UIO_PCI_GENERIC=m # LIRC CONFIG_LIRC_STAGING=y CONFIG_LIRC_BT829=m -CONFIG_LIRC_ENE0100=m -CONFIG_LIRC_I2C=m CONFIG_LIRC_IGORPLUGUSB=m CONFIG_LIRC_IMON=m -CONFIG_LIRC_IT87=m -CONFIG_LIRC_ITE8709=m -CONFIG_LIRC_MCEUSB=m CONFIG_LIRC_ZILOG=m CONFIG_LIRC_PARALLEL=m CONFIG_LIRC_SERIAL=m CONFIG_LIRC_SERIAL_TRANSMITTER=y CONFIG_LIRC_SASEM=m CONFIG_LIRC_SIR=m -CONFIG_LIRC_STREAMZAP=m CONFIG_LIRC_TTUSBIR=m # CONFIG_SAMPLES is not set @@ -4318,7 +4278,6 @@ CONFIG_RESOURCE_COUNTERS=y #FIXME: x86 generic? CONFIG_LEDS_CLEVO_MAIL=m -CONFIG_I8K=m CONFIG_INPUT_APANEL=m # CONFIG_INTEL_MENLOW is not set @@ -4369,7 +4328,6 @@ CONFIG_NET_SCH_MULTIQ=m CONFIG_NET_ACT_SKBEDIT=m CONFIG_PHONET=m -# CONFIG_PHONET_PIPECTRLR is not set CONFIG_ICS932S401=m # CONFIG_C2PORT is not set @@ -4394,12 +4352,9 @@ CONFIG_USB_HWA_HCD=m CONFIG_UWB=m CONFIG_UWB_HWA=m CONFIG_UWB_WHCI=m -CONFIG_UWB_WLP=m CONFIG_UWB_I1480U=m -CONFIG_UWB_I1480U_WLP=m CONFIG_STAGING=y -# CONFIG_STAGING_EXCLUDE_BUILD is not set # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set # CONFIG_VIDEO_TM6000 is not set @@ -4407,31 +4362,20 @@ CONFIG_STAGING=y # CONFIG_WLAGS49_H25 is not set # CONFIG_VIDEO_DT3155 is not set # CONFIG_TI_ST is not set -# CONFIG_ST_BT is not set # CONFIG_FB_XGI is not set # CONFIG_VIDEO_GO7007 is not set -# CONFIG_USB_IP_COMMON is not set # CONFIG_DT3155 is not set # CONFIG_W35UND is not set # CONFIG_PRISM2_USB is not set # CONFIG_ECHO is not set CONFIG_USB_ATMEL=m -# CONFIG_POCH is not set -# CONFIG_OTUS is not set -# CONFIG_RT2860 is not set -# CONFIG_RT2870 is not set # CONFIG_COMEDI is not set # CONFIG_ASUS_OLED is not set # CONFIG_PANEL is not set -# CONFIG_ALTERA_PCIE_CHDMA is not set -# CONFIG_INPUT_MIMIO is not set # CONFIG_TRANZPORT is not set # CONFIG_POHMELFS is not set -# CONFIG_B3DFG is not set # CONFIG_IDE_PHISON is not set -# CONFIG_PLAN9AUTH is not set # CONFIG_LINE6_USB is not set -# CONFIG_RTL8192SU is not set # CONFIG_IIO is not set # CONFIG_VME_BUS is not set # CONFIG_RAR_REGISTER is not set @@ -4443,7 +4387,6 @@ CONFIG_USB_ATMEL=m # CONFIG_HYPERV is not set # CONFIG_R8187SE is not set # CONFIG_RTL8192U is not set -# CONFIG_RAMZSWAP is not set # CONFIG_BATMAN_ADV is not set # CONFIG_FB_SM7XX is not set # CONFIG_SPECTRA is not set @@ -4451,7 +4394,6 @@ CONFIG_USB_ATMEL=m # CONFIG_EASYCAP is not set # CONFIG_SOLO6X10 is not set # CONFIG_ACPI_QUICKSTART is not set -# CONFIG_BRCM80211 is not set # CONFIG_R8712U is not set # CONFIG_ATH6K_LEGACY is not set # CONFIG_USB_ENESTORAGE is not set @@ -4476,10 +4418,8 @@ CONFIG_USB_ATMEL=m # # CONFIG_DEBUG_VIRTUAL is not set -# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FUNCTION_GRAPH_TRACER is not set -# CONFIG_BOOT_TRACER is not set CONFIG_EARLY_PRINTK_DBGP=y CONFIG_SECURITYFS=y @@ -4502,8 +4442,6 @@ CONFIG_LSM_MMAP_MIN_ADDR=65536 # CONFIG_PAGE_POISONING is not set -CONFIG_SLOW_WORK=y -CONFIG_SLOW_WORK_DEBUG=y # CONFIG_CRASH_DUMP is not set # CONFIG_CRASH is not set @@ -4512,7 +4450,6 @@ 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 @@ -4556,7 +4493,6 @@ CONFIG_FB_UDL=m # from getting useful bug-reports makes it worth leaving them on. CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_HIGHMEM=y -CONFIG_DEBUG_SPINLOCK_SLEEP=y CONFIG_BOOT_PRINTK_DELAY=y CONFIG_DEBUG_LIST=y CONFIG_DEBUG_SHIRQ=y @@ -4564,13 +4500,10 @@ CONFIG_DEBUG_DEVRES=y CONFIG_DEBUG_RODATA_TEST=y CONFIG_DEBUG_NX_TEST=m CONFIG_DEBUG_BOOT_PARAMS=y -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 @@ -4602,18 +4535,14 @@ CONFIG_GPIO_SYSFS=y # CONFIG_GPIO_SCH is not set # CONFIG_GPIO_LANGWELL is not set # CONFIG_GPIO_RDC321X is not set -# CONFIG_GPIO_BASIC_MMIO is not set # CONFIG_GPIO_VX855 is not set # CONFIG_GPIO_PCH is not set # CONFIG_GPIO_ML_IOH is not set -CONFIG_KSYM_TRACER=y -CONFIG_PROFILE_KSYM_TRACER=y CONFIG_KPROBE_EVENT=y # CONFIG_RAMOOPS is not set -CONFIG_IR_CORE=m CONFIG_IR_ENE=m CONFIG_IR_STREAMZAP=m CONFIG_IR_WINBOND_CIR=m @@ -4628,18 +4557,17 @@ CONFIG_SPARSE_RCU_POINTER=y # CONFIG_PM_OPP is not set -CONFIG_BKL=y CONFIG_EVENT_POWER_TRACING_DEPRECATED=y # CONFIG_XZ_DEC_TEST is not set -CONFIG_NFC_DEVICES=y CONFIG_PN544_NFC=m +CONFIG_NFC_PN533=m CONFIG_TARGET_CORE=m +CONFIG_ISCSI_TARGET=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 @@ -4661,3 +4589,6 @@ CONFIG_TEST_KSTRTOX=m # CONFIG_GOOGLE_FIRMWARE is not set CONFIG_INTEL_MID_PTI=m + +CONFIG_IOMMU_SUPPORT=y + diff --git a/config-ia64-generic b/config-ia64-generic deleted file mode 100644 index 704c704aa..000000000 --- a/config-ia64-generic +++ /dev/null @@ -1,213 +0,0 @@ -# -# Automatically generated make config: don't edit -# - -# -# Processor type and features -# -CONFIG_IA64=y -CONFIG_64BIT=y -# CONFIG_XEN is not set -CONFIG_MMU=y -CONFIG_EFI=y -# CONFIG_ITANIUM is not set -CONFIG_MCKINLEY=y -CONFIG_IA64_GENERIC=y -# CONFIG_IA64_DIG is not set -# CONFIG_IA64_HP_ZX1 is not set -# CONFIG_IA64_SGI_SN2 is not set -CONFIG_IA64_ESI=y -CONFIG_IA64_HP_AML_NFW=y -CONFIG_MSPEC=y -# CONFIG_IA64_HP_SIM is not set -# CONFIG_IA64_PAGE_SIZE_4KB is not set -# CONFIG_IA64_PAGE_SIZE_8KB is not set -CONFIG_IA64_PAGE_SIZE_16KB=y -# CONFIG_IA64_PAGE_SIZE_64KB is not set -CONFIG_IA64_L1_CACHE_SHIFT=7 -CONFIG_NUMA=y -# CONFIG_VIRTUAL_MEM_MAP is not set -CONFIG_SPARSEMEM_MANUAL=y -CONFIG_SPARSEMEM=y -CONFIG_MEMORY_HOTPLUG=y -CONFIG_MEMORY_HOTREMOVE=y -CONFIG_IA64_MCA_RECOVERY=m -CONFIG_IA64_CYCLONE=y -CONFIG_MMTIMER=y -CONFIG_IOSAPIC=y -CONFIG_FORCE_MAX_ZONEORDER=18 -CONFIG_NR_CPUS=1024 -# CONFIG_IA32_SUPPORT is not set -# CONFIG_COMPAT is not set -CONFIG_PERFMON=y -CONFIG_IA64_PALINFO=y -CONFIG_EFI_VARS=y -CONFIG_SERIAL_8250_RUNTIME_UARTS=16 -CONFIG_EFI_PCDP=y -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_BLK_DEV_SGIIOC4=y - -# -# Character devices -# -CONFIG_TCG_INFINEON=m - -# -# Watchdog Cards -# -# CONFIG_HW_RANDOM is not set -# CONFIG_GEN_RTC is not set -CONFIG_EFI_RTC=y -CONFIG_RTC_DRV_EFI=y - - -# -# AGP -# -CONFIG_AGP_I460=y -CONFIG_AGP_HP_ZX1=y -CONFIG_AGP_SGI_TIOCA=y - -# -# HP Simulator drivers -# -# CONFIG_HP_SIMETH is not set -# CONFIG_HP_SIMSERIAL is not set -# CONFIG_HP_SIMSCSI is not set - -# -# Kernel hacking -# -# CONFIG_IA64_PRINT_HAZARDS is not set -# CONFIG_DISABLE_VHPT is not set -# CONFIG_IA64_DEBUG_CMPXCHG is not set -# CONFIG_IA64_DEBUG_IRQ is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# SGI -# -CONFIG_SGI_SNSC=y -CONFIG_SGI_TIOCX=y -CONFIG_SGI_MBCS=m -CONFIG_SGI_IOC3=m -CONFIG_SGI_IOC4=y -CONFIG_SGI_XP=m -CONFIG_SGI_GRU=m -# CONFIG_SGI_GRU_DEBUG is not set -CONFIG_SERIAL_SGI_L1_CONSOLE=y -CONFIG_SERIAL_SGI_IOC3=m -CONFIG_SERIAL_SGI_IOC4=m - - -# -# SCSI low-level drivers -# -# CONFIG_SCSI_BUSLOGIC is not set - -# -CONFIG_ACPI=y -CONFIG_ACPI_AC=y -# CONFIG_ACPI_ASUS is not set -CONFIG_ACPI_PROCFS_POWER=y -CONFIG_ACPI_SYSFS_POWER=y -# CONFIG_ACPI_BATTERY is not set -CONFIG_ACPI_BLACKLIST_YEAR=0 -CONFIG_ACPI_BUTTON=y -# CONFIG_ACPI_DOCK is not set -CONFIG_ACPI_FAN=y -CONFIG_ACPI_HOTPLUG_MEMORY=y -CONFIG_ACPI_NUMA=y -CONFIG_ACPI_POWER=y -CONFIG_ACPI_PROCESSOR=y -CONFIG_ACPI_PROCFS=y -CONFIG_ACPI_SLEEP=y -CONFIG_ACPI_THERMAL=y -# CONFIG_ACPI_TOSHIBA is not set -CONFIG_ACPI_VIDEO=m -# CONFIG_ACPI_PROC_EVENT is not set -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 -# CONFIG_HPET is not set -# CONFIG_HOTPLUG_PCI_CPCI is not set -CONFIG_HOTPLUG_PCI_SHPC=m -CONFIG_HOTPLUG_PCI_SGI=m -CONFIG_PNPACPI=y - -CONFIG_SCHED_SMT=y - -CONFIG_ARCH_DISCONTIGMEM_ENABLE=y - -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_DEBUG=y -CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=m -CONFIG_CPU_FREQ_GOV_USERSPACE=m -CONFIG_CPU_FREQ_GOV_ONDEMAND=m -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m -CONFIG_CPU_FREQ_STAT=m -CONFIG_CPU_FREQ_STAT_DETAILS=y - -CONFIG_IA64_ACPI_CPUFREQ=m - -# CONFIG_PERMIT_BSP_REMOVE is not set -# CONFIG_FORCE_CPEI_RETARGET is not set - -CONFIG_NODES_SHIFT=10 - - -CONFIG_HW_RANDOM_INTEL=m - -CONFIG_CRASH_DUMP=y -CONFIG_PROC_VMCORE=y - -# drivers/media/video/usbvision/usbvision-i2c.c:64:39: error: macro "outb" passed 4 arguments, but takes just 2 -# CONFIG_VIDEO_USBVISION is not set - -# CONFIG_IA64_MC_ERR_INJECT is not set - -CONFIG_DMIID=y -CONFIG_DMI_SYSFS=y - -CONFIG_SENSORS_I5K_AMB=m - -CONFIG_SPARSEMEM_VMEMMAP=y - -CONFIG_FRAME_WARN=2048 - -CONFIG_VIRT_CPU_ACCOUNTING=y -CONFIG_VIRTUALIZATION=y -CONFIG_KVM=m -CONFIG_KVM_INTEL=m - -CONFIG_HP_ILO=m - -CONFIG_PARAVIRT_GUEST=y -CONFIG_PARAVIRT=y - -CONFIG_DMAR_DEFAULT_ON=y - -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 62650aa3a..084f88e2e 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,6 +2,8 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y +# CONFIG_DEBUG_ATOMIC_SLEEP is not set + # CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_DEBUG_LOCK_ALLOC is not set @@ -70,7 +72,7 @@ CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 # CONFIG_JBD2_DEBUG is not set -# CONFIG_DEBUG_CFQ_IOSCHED is not set +# CONFIG_DEBUG_BLK_CGROUP is not set # CONFIG_DRBD_FAULT_INJECTION is not set @@ -98,3 +100,8 @@ CONFIG_KDB_KEYBOARD=y # CONFIG_TEST_LIST_SORT is not set # CONFIG_DEBUG_SET_MODULE_RONX is not set + +# CONFIG_DETECT_HUNG_TASK is not set +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set + diff --git a/config-powerpc-generic b/config-powerpc-generic index e47c31588..186aa540a 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -60,6 +60,12 @@ CONFIG_FB_ATY_BACKLIGHT=y CONFIG_FB_RADEON_BACKLIGHT=y CONFIG_FB_RIVA_BACKLIGHT=y CONFIG_FB_NVIDIA_BACKLIGHT=y +# FIXME: Do we care about this hardware ? +CONFIG_FB_MB862XX=m +CONFIG_FB_MB862XX_PCI_GDC=y +CONFIG_FB_MB862XX_LIME=y +CONFIG_FB_MB862XX_I2C=y + CONFIG_SND_POWERMAC=m CONFIG_SND_POWERMAC_AUTO_DRC=y @@ -327,16 +333,19 @@ CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m # CONFIG_MFD_88PM8607 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C 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 # CONFIG_MFD_TC35892 is not set +# CONFIG_MFD_AAT2870_CORE is not set # CONFIG_GPIO_SCH is not set # CONFIG_PPC_MPC512x is not set +# CONFIG_RTC_DRV_MPC5121 is not set CONFIG_MPC512X_DMA=m @@ -355,3 +364,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 + +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_MCP23S08 is not set + +# Disable btrfs until it is shown to work with 64k pages (rhbz 747079) +# CONFIG_BTRFS_FS is not set diff --git a/config-powerpc64 b/config-powerpc64 index 8866a5320..ad3edf171 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -44,6 +44,7 @@ CONFIG_LPARCFG=y CONFIG_SERIAL_ICOM=m CONFIG_HVCS=m CONFIG_HVC_CONSOLE=y +# CONFIG_HVC_OLD_HVSI is not set CONFIG_HOTPLUG_PCI=y CONFIG_THERM_PM72=y CONFIG_IBMVETH=m @@ -107,9 +108,16 @@ CONFIG_NR_CPUS=128 CONFIG_RTAS_PROC=y CONFIG_IOMMU_VMERGE=y CONFIG_NUMA=y -# CONFIG_PPC_64K_PAGES is not set +CONFIG_PPC_64K_PAGES=y +CONFIG_PPC_SUBPAGE_PROT=y CONFIG_SCHED_SMT=y +CONFIG_HZ=100 +CONFIG_HZ_100=y +# CONFIG_HZ_1000 is not set + +CONFIG_MEMORY_HOTREMOVE=y + # CONFIG_MV643XX_ETH is not set CONFIG_IRQSTACKS=y CONFIG_DEBUG_STACKOVERFLOW=y @@ -118,7 +126,7 @@ CONFIG_DEBUG_STACKOVERFLOW=y CONFIG_EHEA=m CONFIG_INFINIBAND_EHCA=m -CONFIG_HCALL_STATS=y +# CONFIG_HCALL_STATS is not set CONFIG_XMON_DISASSEMBLY=y @@ -147,7 +155,7 @@ CONFIG_EDAC_CPC925=m CONFIG_FRAME_WARN=2048 CONFIG_PHYP_DUMP=y -CONFIG_FORCE_MAX_ZONEORDER=13 +CONFIG_FORCE_MAX_ZONEORDER=9 CONFIG_VIRTUALIZATION=y CONFIG_VSX=y @@ -174,6 +182,8 @@ CONFIG_PERF_EVENTS=y CONFIG_EVENT_PROFILE=y CONFIG_KVM_BOOK3S_64=m +#-- Enable _HV once publicly available POWER7 hardware can use it +# CONFIG_KVM_BOOK3S_64_HV is not set # CONFIG_KVM_EXIT_TIMING is not set #-- bz#607175 @@ -181,10 +191,15 @@ CONFIG_KVM_BOOK3S_64=m CONFIG_PPC_SMLPAR=y CONFIG_CMM=y #-- DLPAR memory remove -# CONFIG_SPARSEMEM_VMEMMAP is not set +CONFIG_SPARSEMEM_VMEMMAP=y + +# CONFIG_COMPACTION is not set CONFIG_PSERIES_ENERGY=m CONFIG_PPC_ICSWX=y CONFIG_IO_EVENT_IRQ=y CONFIG_HW_RANDOM_AMD=m + +CONFIG_BPF_JIT=y +CONFIG_CPU_FREQ_MAPLE=y diff --git a/config-s390x b/config-s390x index da9db13c1..5251b5b32 100644 --- a/config-s390x +++ b/config-s390x @@ -236,5 +236,4 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_WARN_DYNAMIC_STACK is not set -CONFIG_JUMP_LABEL=y CONFIG_CRYPTO_GHASH_S390=m diff --git a/config-sparc64-generic b/config-sparc64-generic index dac8a644f..d95a9b1ed 100644 --- a/config-sparc64-generic +++ b/config-sparc64-generic @@ -202,8 +202,6 @@ CONFIG_FB_XVR1000=y CONFIG_CRYPTO_DEV_NIAGARA2=y -CONFIG_JUMP_LABEL=y - # CONFIG_MTD_OF_PARTS is not set # CONFIG_MTD_PHYSMAP_OF is not set # CONFIG_MMC_SDHCI_OF is not set diff --git a/config-x86-32-generic b/config-x86-32-generic new file mode 100644 index 000000000..caeae9398 --- /dev/null +++ b/config-x86-32-generic @@ -0,0 +1,206 @@ +# CONFIG_64BIT is not set + +CONFIG_X86_32_NON_STANDARD=y + +# CONFIG_X86_ELAN is not set +# CONFIG_X86_NUMAQ is not set +# CONFIG_X86_SUMMIT is not set +CONFIG_X86_BIGSMP=y +# CONFIG_X86_VISWS is not set +# CONFIG_X86_RDC321X is not set +# CONFIG_X86_ES7000 is not set +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +CONFIG_M686=y +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MVIAC3_2 is not set + +CONFIG_NR_CPUS=32 +CONFIG_X86_GENERIC=y +# CONFIG_X86_PPRO_FENCE is not set + +CONFIG_TOSHIBA=m + +CONFIG_SONYPI=m +CONFIG_SONYPI_COMPAT=y + +# CONFIG_NUMA is not set + +# CONFIG_NOHIGHMEM is not set +CONFIG_HIGHMEM4G=y +# CONFIG_HIGHMEM64G is not set +CONFIG_HIGHMEM=y +CONFIG_HIGHPTE=y + +# CONFIG_MATH_EMULATION is not set + +CONFIG_FB_GEODE=y +CONFIG_FB_GEODE_LX=y +CONFIG_FB_GEODE_GX=y +# CONFIG_FB_GEODE_GX1 is not set + +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOMMCONFIG is not set +CONFIG_PCI_GOANY=y + +# FIXME: wtf? "x86 specific drivers" +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_IBM_ASM=m + +# +# APM (Advanced Power Management) BIOS Support +# +CONFIG_APM=y +# CONFIG_APM_IGNORE_USER_SUSPEND is not set +# CONFIG_APM_DO_ENABLE is not set +CONFIG_APM_CPU_IDLE=y +# CONFIG_APM_DISPLAY_BLANK is not set +# CONFIG_APM_ALLOW_INTS is not set + +CONFIG_ACPI_BLACKLIST_YEAR=1999 + + +# CONFIG_X86_POWERNOW_K6 is not set +CONFIG_X86_POWERNOW_K7=y +# CONFIG_X86_GX_SUSPMOD is not set +CONFIG_X86_SPEEDSTEP_ICH=y +CONFIG_X86_SPEEDSTEP_SMI=y +CONFIG_X86_SPEEDSTEP_LIB=y +# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set +CONFIG_X86_LONGRUN=y +# CONFIG_X86_LONGHAUL is not set +# CONFIG_X86_CPUFREQ_NFORCE2 is not set +# e_powersaver is dangerous +# CONFIG_X86_E_POWERSAVER is not set + +CONFIG_X86_HT=y +CONFIG_X86_TRAMPOLINE=y + + +# CONFIG_4KSTACKS is not set + +CONFIG_PCI_DIRECT=y + +# SHPC has half-arsed PCI probing, which makes it load on too many systems +# CONFIG_HOTPLUG_PCI_SHPC is not set + +CONFIG_BLK_DEV_AMD74XX=y + +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_ALI1563=m +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m + +CONFIG_SCx200_ACB=m + +# CONFIG_X86_REBOOTFIXUPS is not set + +CONFIG_PC8736x_GPIO=m +# CONFIG_NSC_GPIO is not set +CONFIG_CS5535_GPIO=m +CONFIG_GPIO_SCH=m + +CONFIG_SND_ISA=y +CONFIG_SND_ES18XX=m + +CONFIG_HW_RANDOM_GEODE=m + +# CONFIG_SGI_IOC4 is not set + +CONFIG_TC1100_WMI=m + +CONFIG_IB700_WDT=m + +CONFIG_PHYSICAL_ALIGN=0x400000 +CONFIG_PHYSICAL_START=0x400000 + +# CONFIG_KEXEC_JUMP is not set + +CONFIG_CRYPTO_AES_586=y +CONFIG_CRYPTO_DEV_GEODE=m +CONFIG_CRYPTO_TWOFISH_586=m + +CONFIG_VIDEO_CAFE_CCIC=m + +CONFIG_VMI=y + +CONFIG_XEN_MAX_DOMAIN_MEMORY=8 + +CONFIG_MTD_NAND_CAFE=m + +# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set + + +CONFIG_OLPC=y +CONFIG_OLPC_OPENFIRMWARE=y +CONFIG_BATTERY_OLPC=y +CONFIG_MOUSE_PS2_OLPC=y +CONFIG_OLPC_XO1_PM=y +CONFIG_OLPC_XO15_SCI=y +CONFIG_OLPC_XO1_RTC=y +CONFIG_OLPC_XO1_SCI=y +# staging +# CONFIG_FB_OLPC_DCON is not set + +# CONFIG_SPARSE_IRQ is not set + +CONFIG_RCU_FANOUT=32 + +# CONFIG_X86_ANCIENT_MCE is not set + +# CONFIG_X86_MRST is not set + +CONFIG_I2C_PXA=m +# CONFIG_GPIO_LANGWELL is not set + +# CONFIG_INTEL_TXT is not set + +CONFIG_GEODE_WDT=m +CONFIG_CS5535_MFGPT=m +CONFIG_CS5535_CLOCK_EVENT_SRC=m + +CONFIG_LEDS_INTEL_SS4200=m + +CONFIG_OLPC_XO1=m +CONFIG_XO1_RFKILL=m + +CONFIG_X86_32_IRIS=m + + +CONFIG_MTD_OF_PARTS=y +CONFIG_MTD_PHYSMAP_OF=m +CONFIG_PROC_DEVICETREE=y +CONFIG_SERIAL_OF_PLATFORM=m +CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m +# CONFIG_MMC_SDHCI_OF is not set + +# CONFIG_X86_INTEL_MID is not set + +CONFIG_MFD_CS5535=m + +# I2O enabled only for 32-bit x86, disabled for PAE kernel +CONFIG_I2O=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m +CONFIG_I2O_CONFIG=y +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m + diff --git a/config-x86-generic b/config-x86-generic index f12458388..4252062dc 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -1,68 +1,30 @@ CONFIG_UID16=y -# CONFIG_64BIT is not set -# CONFIG_KERNEL_LZMA is not set -# -# Processor type and features -# -# -# Enable summit and co via the generic arch -# CONFIG_X86_EXTENDED_PLATFORM=y -CONFIG_X86_32_NON_STANDARD=y -# CONFIG_X86_ELAN is not set -# CONFIG_X86_NUMAQ is not set -# CONFIG_X86_SUMMIT is not set -CONFIG_X86_BIGSMP=y -# CONFIG_X86_VISWS is not set -# CONFIG_X86_RDC321X is not set -# CONFIG_X86_ES7000 is not set -# CONFIG_M386 is not set -# CONFIG_M486 is not set -# CONFIG_M586 is not set -# CONFIG_M586TSC is not set -# CONFIG_M586MMX is not set -CONFIG_M686=y -# CONFIG_MPENTIUMII is not set -# CONFIG_MPENTIUMIII is not set -# CONFIG_MPENTIUMM is not set -# CONFIG_MPENTIUM4 is not set -# CONFIG_MK6 is not set -# CONFIG_MK7 is not set -# CONFIG_MK8 is not set -# CONFIG_MCRUSOE is not set -# CONFIG_MWINCHIPC6 is not set -# CONFIG_MWINCHIP3D is not set -# CONFIG_MCYRIXIII is not set -# CONFIG_MVIAC3_2 is not set CONFIG_SMP=y -CONFIG_NR_CPUS=64 + CONFIG_X86_GENERIC=y -# CONFIG_X86_PPRO_FENCE is not set + CONFIG_HPET=y CONFIG_HPET_TIMER=y # CONFIG_HPET_MMAP is not set -CONFIG_X86_MCE=y -CONFIG_TOSHIBA=m + CONFIG_I8K=m -CONFIG_SONYPI=m CONFIG_SONYPI_COMPAT=y CONFIG_MICROCODE=m +CONFIG_MICROCODE_INTEL=y +CONFIG_MICROCODE_AMD=y + CONFIG_X86_MSR=y CONFIG_X86_CPUID=y CONFIG_EDD=m # CONFIG_EDD_OFF is not set -# CONFIG_NUMA is not set -# CONFIG_NOHIGHMEM is not set -CONFIG_HIGHMEM4G=y -# CONFIG_HIGHMEM64G is not set -CONFIG_HIGHMEM=y -CONFIG_HIGHPTE=y - -# CONFIG_MATH_EMULATION is not set CONFIG_MTRR=y +CONFIG_MTRR_SANITIZER=y +CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=1 +CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1 CONFIG_X86_PAT=y CONFIG_X86_PM_TIMER=y @@ -70,153 +32,79 @@ CONFIG_EFI=y CONFIG_EFI_VARS=y CONFIG_EFI_PCDP=y CONFIG_FB_EFI=y + +# FIXME: 32bit only? # CONFIG_FB_N411 is not set CONFIG_DMAR=y CONFIG_DMAR_BROKEN_GFX_WA=y CONFIG_DMAR_FLOPPY_WA=y CONFIG_DMAR_DEFAULT_ON=y - -CONFIG_FB_GEODE=y -CONFIG_FB_GEODE_LX=y -CONFIG_FB_GEODE_GX=y -# CONFIG_FB_GEODE_GX1 is not set - -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GODIRECT is not set -# CONFIG_PCI_GOMMCONFIG is not set -CONFIG_PCI_GOANY=y - -# -# x86 specific drivers -# -CONFIG_PCMCIA_FDOMAIN=m -CONFIG_SCSI_FUTURE_DOMAIN=m CONFIG_SCSI_ADVANSYS=m -CONFIG_CC_STACKPROTECTOR=y - CONFIG_SECCOMP=y CONFIG_CAPI_EICON=y -# I2O enabled only for 32-bit x86, disabled for PAE kernel -CONFIG_I2O=m -CONFIG_I2O_BLOCK=m -CONFIG_I2O_SCSI=m -CONFIG_I2O_PROC=m -CONFIG_I2O_CONFIG=y -CONFIG_I2O_EXT_ADAPTEC=y -CONFIG_I2O_CONFIG_OLD_IOCTL=y -CONFIG_I2O_BUS=m - -# -# APM (Advanced Power Management) BIOS Support -# -CONFIG_APM=y -# CONFIG_APM_IGNORE_USER_SUSPEND is not set -# CONFIG_APM_DO_ENABLE is not set -CONFIG_APM_CPU_IDLE=y -# CONFIG_APM_DISPLAY_BLANK is not set -# CONFIG_APM_ALLOW_INTS is not set - # # Kernel debugging # CONFIG_X86_MPPARSE=y +# CONFIG_X86_VERBOSE_BOOTUP is not set +# CONFIG_MMIOTRACE_TEST is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_DEBUG_RODATA=y +CONFIG_DEBUG_STACKOVERFLOW=y CONFIG_ACPI=y CONFIG_ACPI_AC=y # CONFIG_ACPI_ASUS is not set CONFIG_ACPI_PROCFS_POWER=y -CONFIG_ACPI_SYSFS_POWER=y CONFIG_ACPI_BATTERY=y -CONFIG_ACPI_BLACKLIST_YEAR=1999 CONFIG_ACPI_BUTTON=y CONFIG_ACPI_CONTAINER=m CONFIG_ACPI_DOCK=y CONFIG_ACPI_FAN=y CONFIG_ACPI_NUMA=y CONFIG_ACPI_PROCESSOR=y -CONFIG_ACPI_POWER=y CONFIG_ACPI_PROCFS=y CONFIG_ACPI_SBS=m CONFIG_ACPI_SLEEP=y CONFIG_ACPI_THERMAL=y -CONFIG_TOPSTAR_LAPTOP=m CONFIG_ACPI_TOSHIBA=m CONFIG_ACPI_VIDEO=m # CONFIG_ACPI_PROC_EVENT is not set CONFIG_PNPACPI=y -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_GHES=y +CONFIG_ACPI_APEI_MEMORY_FAILURE=y # CONFIG_ACPI_APEI_EINJ is not set CONFIG_ACPI_IPMI=m CONFIG_ACPI_CUSTOM_METHOD=m -# -# CPUFreq processor drivers -# -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_DEBUG=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=m -CONFIG_CPU_FREQ_GOV_USERSPACE=m -CONFIG_CPU_FREQ_GOV_ONDEMAND=m -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m -CONFIG_CPU_FREQ_TABLE=y -CONFIG_CPU_FREQ_STAT=m -CONFIG_CPU_FREQ_STAT_DETAILS=y - CONFIG_X86_ACPI_CPUFREQ=m CONFIG_X86_PCC_CPUFREQ=m -# CONFIG_X86_POWERNOW_K6 is not set -CONFIG_X86_POWERNOW_K7=y CONFIG_X86_POWERNOW_K8=m -# CONFIG_X86_GX_SUSPMOD is not set -# CONFIG_X86_SPEEDSTEP_CENTRINO is not set -CONFIG_X86_SPEEDSTEP_ICH=y -CONFIG_X86_SPEEDSTEP_SMI=y -CONFIG_X86_SPEEDSTEP_LIB=y -# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set CONFIG_X86_P4_CLOCKMOD=m -CONFIG_X86_LONGRUN=y -# CONFIG_X86_LONGHAUL is not set -# CONFIG_X86_CPUFREQ_NFORCE2 is not set -# e_powersaver is dangerous -# CONFIG_X86_E_POWERSAVER is not set - -CONFIG_X86_HT=y -CONFIG_X86_TRAMPOLINE=y +# CONFIG_X86_SPEEDSTEP_CENTRINO is not set # # various x86 specific drivers # CONFIG_NVRAM=y -CONFIG_IBM_ASM=m -CONFIG_CRYPTO_TWOFISH_586=m CONFIG_CRYPTO_DEV_PADLOCK=m CONFIG_CRYPTO_DEV_PADLOCK_AES=m CONFIG_CRYPTO_DEV_PADLOCK_SHA=m CONFIG_GENERIC_ISA_DMA=y -CONFIG_SCHED_SMT=y + CONFIG_SUSPEND=y CONFIG_HIBERNATION=y CONFIG_PM_STD_PARTITION="" -CONFIG_DEBUG_RODATA=y -CONFIG_DEBUG_STACKOVERFLOW=y -# CONFIG_4KSTACKS is not set -CONFIG_DEBUG_NMI_TIMEOUT=5 - -CONFIG_PCI_DIRECT=y CONFIG_PCI_MMCONFIG=y CONFIG_PCI_BIOS=y @@ -225,8 +113,7 @@ CONFIG_HOTPLUG_PCI_COMPAQ=m # CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set CONFIG_HOTPLUG_PCI_IBM=m # CONFIG_HOTPLUG_PCI_CPCI is not set -# SHPC has half-arsed PCI probing, which makes it load on too many systems -# CONFIG_HOTPLUG_PCI_SHPC is not set + CONFIG_PM=y CONFIG_IPW2100=m @@ -239,9 +126,6 @@ CONFIG_IPW2200_QOS=y CONFIG_BLK_DEV_AMD74XX=y -CONFIG_I2C_ALI1535=m -CONFIG_I2C_ALI15X3=m -CONFIG_I2C_ALI1563=m CONFIG_I2C_AMD756=m CONFIG_I2C_AMD756_S4882=m CONFIG_I2C_AMD8111=m @@ -250,45 +134,35 @@ CONFIG_I2C_ISCH=m CONFIG_I2C_NFORCE2=m CONFIG_I2C_NFORCE2_S4985=m CONFIG_I2C_PIIX4=m -CONFIG_I2C_SIS5595=m -CONFIG_I2C_SIS630=m CONFIG_I2C_SIS96X=m - CONFIG_I2C_VIA=m CONFIG_I2C_VIAPRO=m -CONFIG_SCx200_ACB=m - -# CONFIG_X86_REBOOTFIXUPS is not set - CONFIG_DELL_RBU=m CONFIG_DCDBAS=m -CONFIG_GPIO_SCH=m -CONFIG_PC8736x_GPIO=m -# CONFIG_NSC_GPIO is not set -CONFIG_CS5535_GPIO=m - CONFIG_EDAC=y # CONFIG_EDAC_DEBUG is not set CONFIG_EDAC_MM_EDAC=m CONFIG_EDAC_AMD76X=m +CONFIG_EDAC_AMD8111=m +CONFIG_EDAC_AMD8131=m CONFIG_EDAC_E7XXX=m CONFIG_EDAC_E752X=m CONFIG_EDAC_I82860=m CONFIG_EDAC_I82875P=m CONFIG_EDAC_I82975X=m CONFIG_EDAC_I3000=m +CONFIG_EDAC_I3200=m CONFIG_EDAC_I5000=m CONFIG_EDAC_I5100=m CONFIG_EDAC_I5400=m -CONFIG_EDAC_R82600=m -CONFIG_EDAC_AMD8131=m -CONFIG_EDAC_AMD8111=m -CONFIG_EDAC_I7CORE=m -CONFIG_EDAC_I3000=m CONFIG_EDAC_I7300=m +CONFIG_EDAC_I7CORE=m +CONFIG_EDAC_R82600=m CONFIG_EDAC_X38=m +CONFIG_EDAC_MCE_INJ=m +CONFIG_EDAC_DECODE_MCE=m CONFIG_SCHED_MC=y @@ -299,83 +173,75 @@ CONFIG_TCG_INFINEON=m CONFIG_HW_RANDOM_INTEL=m CONFIG_HW_RANDOM_AMD=m -CONFIG_HW_RANDOM_GEODE=m CONFIG_HW_RANDOM_VIA=m - # CONFIG_COMPAT_VDSO is not set -# CONFIG_SGI_IOC4 is not set - CONFIG_X86_PLATFORM_DEVICES=y + CONFIG_ASUS_LAPTOP=m CONFIG_COMPAL_LAPTOP=m +CONFIG_DELL_LAPTOP=m CONFIG_EEEPC_LAPTOP=m -CONFIG_EEEPC_WMI=m CONFIG_FUJITSU_LAPTOP=m # CONFIG_FUJITSU_LAPTOP_DEBUG is not set CONFIG_IDEAPAD_LAPTOP=m CONFIG_MSI_LAPTOP=m +CONFIG_PANASONIC_LAPTOP=m +CONFIG_SAMSUNG_LAPTOP=m CONFIG_SONY_LAPTOP=m -CONFIG_DELL_LAPTOP=m +CONFIG_TOPSTAR_LAPTOP=m + CONFIG_ACPI_WMI=m CONFIG_ACER_WMI=m CONFIG_ACERHDF=m -CONFIG_TC1100_WMI=m +CONFIG_ASUS_WMI=m +CONFIG_ASUS_NB_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_EEEPC_WMI=m CONFIG_INTEL_OAKTRAIL=m +CONFIG_SAMSUNG_Q10=m +CONFIG_XO15_EBOOK=m # CONFIG_TOUCHSCREEN_INTEL_MID is not set # CONFIG_SMSC37B787_WDT is not set CONFIG_W83697HF_WDT=m -CONFIG_IB700_WDT=m -CONFIG_RELOCATABLE=y -CONFIG_PHYSICAL_ALIGN=0x400000 -CONFIG_PHYSICAL_START=0x400000 CONFIG_CRASH_DUMP=y -# CONFIG_KEXEC_JUMP is not set CONFIG_PROC_VMCORE=y CONFIG_CRASH=m -CONFIG_CRYPTO_DEV_GEODE=m - -CONFIG_VIDEO_CAFE_CCIC=m - CONFIG_VIRTUALIZATION=y CONFIG_KVM=m CONFIG_KVM_INTEL=m CONFIG_KVM_AMD=m CONFIG_LGUEST=m +CONFIG_LGUEST_GUEST=y CONFIG_PARAVIRT_GUEST=y CONFIG_PARAVIRT=y +CONFIG_PARAVIRT_TIME_ACCOUNTING=y # CONFIG_PARAVIRT_DEBUG is not set # PARAVIRT_SPINLOCKS has a 5% perf hit +# FIXME: Still true ? References? # CONFIG_PARAVIRT_SPINLOCKS is not set + CONFIG_KVM_CLOCK=y CONFIG_KVM_GUEST=y CONFIG_KVM_MMU_AUDIT=y # default $x would be nice... -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 CONFIG_XEN_SAVE_RESTORE=y CONFIG_HVC_XEN=y 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 @@ -387,13 +253,14 @@ 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_PLATFORM_PCI=y CONFIG_XEN_GNTDEV=m CONFIG_INPUT_XEN_KBDDEV_FRONTEND=m +CONFIG_XEN_SELFBALLOONING=y +CONFIG_XEN_PCIDEV_BACKEND=m CONFIG_MTD_ESB2ROM=m CONFIG_MTD_CK804XROM=m -CONFIG_MTD_NAND_CAFE=m CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -425,99 +292,52 @@ CONFIG_SENSORS_FAM15H_POWER=m CONFIG_SENSORS_ACPI_POWER=m # CONFIG_CPA_DEBUG is not set -# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set CONFIG_HP_WATCHDOG=m CONFIG_NV_TCO=m CONFIG_SP5100_TCO=m -CONFIG_OLPC=y -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 # CONFIG_MEMTEST is not set # CONFIG_MAXSMP is not set -CONFIG_MTRR_SANITIZER=y -CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=1 -CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1 -CONFIG_SYSPROF_TRACER=y -# CONFIG_X86_VERBOSE_BOOTUP is not set -# CONFIG_MMIOTRACE_TEST is not set - -# CONFIG_DEBUG_PER_CPU_MAPS is not set CONFIG_HP_ILO=m CONFIG_BACKLIGHT_APPLE=m -CONFIG_OPROFILE_IBS=y -CONFIG_MICROCODE_INTEL=y -CONFIG_MICROCODE_AMD=y # CONFIG_X86_CHECK_BIOS_CORRUPTION is not set -CONFIG_X86_RESERVE_LOW_64K=y # CONFIG_CMDLINE_BOOL is not set -CONFIG_PANASONIC_LAPTOP=m - -CONFIG_X86_PTRACE_BTS=y CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y -CONFIG_POWER_TRACER=y -CONFIG_HW_BRANCH_TRACER=y - -# CONFIG_SPARSE_IRQ is not set - -CONFIG_RCU_FANOUT=32 # CONFIG_IOMMU_STRESS is not set CONFIG_PERF_COUNTERS=y CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y +CONFIG_X86_MCE=y CONFIG_X86_MCE_INTEL=y CONFIG_X86_MCE_AMD=y -# CONFIG_X86_ANCIENT_MCE is not set # CONFIG_X86_MCE_INJECT is not set -# CONFIG_X86_MRST is not set 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 - -# CONFIG_GPIO_LANGWELL is not set - -# CONFIG_INTEL_TXT is not set - -CONFIG_CS5535_MFGPT=m -CONFIG_GEODE_WDT=m -CONFIG_CS5535_CLOCK_EVENT_SRC=m - -CONFIG_LEDS_INTEL_SS4200=m CONFIG_X86_DECODER_SELFTEST=y CONFIG_ACPI_CMPC=m CONFIG_MSI_WMI=m CONFIG_TOSHIBA_BT_RFKILL=m -CONFIG_SAMSUNG_LAPTOP=m CONFIG_VGA_SWITCHEROO=y CONFIG_LPC_SCH=m @@ -526,46 +346,38 @@ CONFIG_PCI_CNB20LE_QUIRK=y CONFIG_ACPI_EC_DEBUGFS=m # CONFIG_ACPI_APEI_ERST_DEBUG is not set +# CONFIG_ACPI_QUICKSTART is not set + CONFIG_INTEL_IDLE=y + # CONFIG_TOUCHSCREEN_CY8CTMG110 is not set -CONFIG_SENSORS_PKGTEMP=m CONFIG_F71808E_WDT=m CONFIG_HPWDT_NMI_DECODING=y # CONFIG_MFD_TPS6586X is not set # CONFIG_INTEL_MID_DMAC is not set CONFIG_PCH_DMA=m -# CONFIG_ACPI_QUICKSTART is not set -CONFIG_IDEAPAD_ACPI=m CONFIG_INTEL_IPS=m # CONFIG_IBM_RTL is not set -CONFIG_OLPC_XO1=m -CONFIG_XO1_RFKILL=m CONFIG_VIDEO_VIA_CAMERA=m -CONFIG_EDAC_MCE_INJ=m CONFIG_IRQ_TIME_ACCOUNTING=y CONFIG_X86_RESERVE_LOW=64 CONFIG_PCH_GBE=m CONFIG_PCH_PHUB=m -CONFIG_JUMP_LABEL=y - -CONFIG_X86_32_IRIS=m - CONFIG_TRANSPARENT_HUGEPAGE=y CONFIG_CRYPTO_AES_NI_INTEL=y -CONFIG_CRYPTO_AES_586=y - -CONFIG_MTD_OF_PARTS=m -CONFIG_MTD_PHYSMAP_OF=m -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 + +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_MCP23S08 is not set + +CONFIG_SCHED_SMT=y +CONFIG_CC_STACKPROTECTOR=y +CONFIG_RELOCATABLE=y diff --git a/config-x86_64-generic b/config-x86_64-generic index 306410cf7..693c3a8b6 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -1,241 +1,59 @@ CONFIG_64BIT=y -CONFIG_UID16=y -# CONFIG_KERNEL_LZMA is not set # CONFIG_MK8 is not set # CONFIG_MPSC is not set CONFIG_GENERIC_CPU=y -CONFIG_X86_EXTENDED_PLATFORM=y + # CONFIG_X86_VSMP is not set # CONFIG_X86_UV is not set -CONFIG_X86_MSR=y -CONFIG_X86_CPUID=y -CONFIG_MTRR=y CONFIG_NUMA=y CONFIG_K8_NUMA=y CONFIG_AMD_NUMA=y CONFIG_X86_64_ACPI_NUMA=y # CONFIG_NUMA_EMU is not set + CONFIG_NR_CPUS=256 -CONFIG_X86_POWERNOW_K8=m -CONFIG_X86_P4_CLOCKMOD=m +CONFIG_PHYSICAL_START=0x1000000 + CONFIG_IA32_EMULATION=y # CONFIG_IA32_AOUT is not set + +CONFIG_AMD_IOMMU=y +CONFIG_AMD_IOMMU_STATS=y # CONFIG_IOMMU_DEBUG is not set -CONFIG_DEBUG_RODATA=y -CONFIG_MICROCODE=m CONFIG_SWIOTLB=y CONFIG_CALGARY_IOMMU=y CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y -CONFIG_X86_PM_TIMER=y -CONFIG_EDD=m -# CONFIG_EDD_OFF is not set -CONFIG_PCI_BIOS=y -CONFIG_PCI_MMCONFIG=y -CONFIG_DMAR=y -CONFIG_DMAR_BROKEN_GFX_WA=y -CONFIG_DMAR_FLOPPY_WA=y -CONFIG_DMAR_DEFAULT_ON=y CONFIG_KEXEC_JUMP=y -CONFIG_EFI=y -CONFIG_EFI_VARS=y -CONFIG_EFI_PCDP=y -CONFIG_FB_EFI=y - -CONFIG_SCSI_ADVANSYS=m - -CONFIG_SECCOMP=y - -CONFIG_CAPI_EICON=y - -CONFIG_GENERIC_ISA_DMA=y -CONFIG_SCHED_SMT=y -CONFIG_SUSPEND=y -CONFIG_HIBERNATION=y -CONFIG_PM_STD_PARTITION="" - -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=m -CONFIG_CPU_FREQ_GOV_USERSPACE=m -CONFIG_CPU_FREQ_GOV_ONDEMAND=m -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m -CONFIG_CPU_FREQ_TABLE=y -CONFIG_CPU_FREQ_DEBUG=y -# CONFIG_X86_SPEEDSTEP_CENTRINO is not set -CONFIG_X86_PCC_CPUFREQ=m -CONFIG_X86_ACPI_CPUFREQ=m -CONFIG_CPU_FREQ_STAT=m -CONFIG_CPU_FREQ_STAT_DETAILS=y - -CONFIG_ACPI=y -CONFIG_ACPI_AC=y -# CONFIG_ACPI_ASUS is not set -CONFIG_ACPI_PROCFS_POWER=y -CONFIG_ACPI_SYSFS_POWER=y -CONFIG_ACPI_BATTERY=y CONFIG_ACPI_BLACKLIST_YEAR=0 -CONFIG_ACPI_BUTTON=y -CONFIG_ACPI_CONTAINER=m -CONFIG_ACPI_DOCK=y -CONFIG_ACPI_FAN=y CONFIG_ACPI_HOTPLUG_MEMORY=m -CONFIG_ACPI_NUMA=y -CONFIG_ACPI_PROCESSOR=y -CONFIG_ACPI_PROCFS=y -CONFIG_ACPI_SBS=m -CONFIG_ACPI_SLEEP=y -CONFIG_ACPI_THERMAL=y -CONFIG_ACPI_TOSHIBA=m -CONFIG_ACPI_POWER=y -CONFIG_ACPI_VIDEO=m -# CONFIG_ACPI_PROC_EVENT is not set -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 -CONFIG_COMPAL_LAPTOP=m -CONFIG_FUJITSU_LAPTOP=m -# CONFIG_FUJITSU_LAPTOP_DEBUG is not set -CONFIG_MSI_LAPTOP=m -CONFIG_SONY_LAPTOP=m -CONFIG_SONYPI_COMPAT=y -CONFIG_EEEPC_LAPTOP=m -CONFIG_EEEPC_WMI=m -CONFIG_DELL_LAPTOP=m -CONFIG_ACPI_WMI=m -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 - -CONFIG_THINKPAD_ACPI=m -# CONFIG_THINKPAD_ACPI_DEBUG is not set -# CONFIG_THINKPAD_ACPI_DEBUGFACILITIES is not set -CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y -CONFIG_THINKPAD_ACPI_VIDEO=y -CONFIG_THINKPAD_ACPI_ALSA_SUPPORT=y -# CONFIG_THINKPAD_ACPI_UNSAFE_LEDS is not set - -CONFIG_HOTPLUG_PCI=y -CONFIG_HOTPLUG_PCI_COMPAQ=m -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -CONFIG_HOTPLUG_PCI_IBM=m -# CONFIG_HOTPLUG_PCI_CPCI is not set # SHPC has half-arsed PCI probing, which makes it load on too many systems CONFIG_HOTPLUG_PCI_SHPC=m -CONFIG_HPET=y -# CONFIG_HPET_MMAP is not set -CONFIG_PM=y - -CONFIG_IPW2100=m -CONFIG_IPW2100_MONITOR=y -CONFIG_IPW2200=m -CONFIG_IPW2200_MONITOR=y -CONFIG_IPW2200_RADIOTAP=y -CONFIG_IPW2200_PROMISCUOUS=y -CONFIG_IPW2200_QOS=y - CONFIG_PNP=y -CONFIG_PNPACPI=y +# Really ? not 32bit only ? CONFIG_BLK_DEV_AMD74XX=y -CONFIG_CRYPTO_DEV_PADLOCK=m -CONFIG_CRYPTO_DEV_PADLOCK_AES=m -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 - -CONFIG_X86_MCE=y -CONFIG_X86_MCE_INTEL=y -CONFIG_X86_MCE_AMD=y +CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m # CONFIG_I2C_ALI1535 is not set # CONFIG_I2C_ALI1563 is not set # CONFIG_I2C_ALI15X3 is not set -CONFIG_I2C_AMD756=m -CONFIG_I2C_AMD756_S4882=m -CONFIG_I2C_AMD8111=m -CONFIG_I2C_I801=m -CONFIG_I2C_ISCH=m -CONFIG_I2C_NFORCE2_S4985=m -CONFIG_I2C_PIIX4=m # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set -CONFIG_I2C_SIS96X=m -CONFIG_I2C_VIA=m -CONFIG_I2C_VIAPRO=m - -CONFIG_DELL_RBU=m -CONFIG_DCDBAS=m - -CONFIG_NVRAM=y - -CONFIG_EDAC=y -# CONFIG_EDAC_DEBUG is not set -CONFIG_EDAC_MM_EDAC=m -CONFIG_EDAC_AMD76X=m -CONFIG_EDAC_E7XXX=m -CONFIG_EDAC_E752X=m -CONFIG_EDAC_I5000=m -CONFIG_EDAC_I5100=m -CONFIG_EDAC_I5400=m -CONFIG_EDAC_I82875P=m -CONFIG_EDAC_I82860=m -CONFIG_EDAC_I82975X=m -CONFIG_EDAC_R82600=m -CONFIG_EDAC_AMD8131=m -CONFIG_EDAC_AMD8111=m CONFIG_EDAC_AMD64=m # CONFIG_EDAC_AMD64_ERROR_INJECTION is not set -CONFIG_EDAC_DECODE_MCE=m -CONFIG_EDAC_I7CORE=m -CONFIG_EDAC_I3000=m -CONFIG_EDAC_I7300=m -CONFIG_EDAC_X38=m -CONFIG_SCHED_MC=y - -CONFIG_TCG_INFINEON=m - -CONFIG_HW_RANDOM_INTEL=m -CONFIG_HW_RANDOM_AMD=m -CONFIG_HW_RANDOM_VIA=m - -# CONFIG_HW_RANDOM_GEODE is not set - - -CONFIG_DEBUG_STACKOVERFLOW=y -CONFIG_DEBUG_NMI_TIMEOUT=5 - -CONFIG_GPIO_SCH=m # CONFIG_PC8736x_GPIO is not set # CONFIG_DISCONTIGMEM_MANUAL is not set @@ -254,223 +72,46 @@ CONFIG_MEMORY_HOTREMOVE=y # CONFIG_BLK_DEV_CS5530 is not set # CONFIG_BLK_DEV_CS5535 is not set -CONFIG_CC_STACKPROTECTOR=y - CONFIG_SGI_IOC4=m CONFIG_SGI_XP=m CONFIG_SGI_GRU=m # CONFIG_SGI_GRU_DEBUG is not set -# CONFIG_SMSC37B787_WDT is not set -CONFIG_W83697HF_WDT=m - # CONFIG_VIDEO_CAFE_CCIC is not set -CONFIG_MTD_ESB2ROM=m -CONFIG_MTD_CK804XROM=m - -CONFIG_RELOCATABLE=y -CONFIG_MACINTOSH_DRIVERS=y - -CONFIG_CRASH_DUMP=y -CONFIG_PHYSICAL_START=0x1000000 -CONFIG_PROC_VMCORE=y -CONFIG_CRASH=m - -CONFIG_DMIID=y -CONFIG_DMI_SYSFS=y - -CONFIG_ISCSI_IBFT_FIND=y -CONFIG_ISCSI_IBFT=m - - -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_CPU_IDLE=y -# CONFIG_CPU_IDLE_GOV_LADDER is not set -CONFIG_CPU_IDLE_GOV_MENU=y - -CONFIG_VIRTUALIZATION=y -CONFIG_KVM=m -CONFIG_KVM_INTEL=m -CONFIG_KVM_AMD=m - -CONFIG_PARAVIRT_GUEST=y -CONFIG_PARAVIRT=y -# CONFIG_PARAVIRT_DEBUG is not set -# PARAVIRT_SPINLOCKS has a 5% perf hit -# CONFIG_PARAVIRT_SPINLOCKS is not set -CONFIG_KVM_CLOCK=y -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 -CONFIG_XEN_SAVE_RESTORE=y -CONFIG_HVC_XEN=y -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_BALLOON_MEMORY_HOTPLUG is not set 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 -# CONFIG_DEBUG_PER_CPU_MAPS is not set -# CONFIG_CPA_DEBUG is not set - -CONFIG_HP_WATCHDOG=m -CONFIG_NV_TCO=m -CONFIG_SP5100_TCO=m CONFIG_FRAME_WARN=2048 CONFIG_NODES_SHIFT=9 -CONFIG_X86_PAT=y -# FIXME: These should be 32bit only -# CONFIG_FB_N411 is not set -CONFIG_STRICT_DEVMEM=y CONFIG_DIRECT_GBPAGES=y -# CONFIG_NO_BOOTMEM is not set - -# CONFIG_MEMTEST is not set -CONFIG_AMD_IOMMU=y -CONFIG_AMD_IOMMU_STATS=y -# CONFIG_MAXSMP is not set -CONFIG_MTRR_SANITIZER=y -CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=1 -CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1 -CONFIG_SYSPROF_TRACER=y -# CONFIG_X86_VERBOSE_BOOTUP is not set -# CONFIG_MMIOTRACE_TEST is not set - CONFIG_X86_MPPARSE=y -CONFIG_BACKLIGHT_APPLE=m - -CONFIG_OPROFILE_IBS=y -CONFIG_MICROCODE_INTEL=y -CONFIG_MICROCODE_AMD=y - -# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set -CONFIG_X86_RESERVE_LOW_64K=y - -# CONFIG_CMDLINE_BOOL is not set - -CONFIG_PANASONIC_LAPTOP=m - -CONFIG_X86_PTRACE_BTS=y - CONFIG_I7300_IDLE=m CONFIG_INTR_REMAP=y -CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y - -CONFIG_POWER_TRACER=y -CONFIG_HW_BRANCH_TRACER=y - CONFIG_X86_X2APIC=y CONFIG_SPARSE_IRQ=y CONFIG_RCU_FANOUT=64 -# CONFIG_IOMMU_STRESS is not set - -CONFIG_PERF_COUNTERS=y -CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y - -# CONFIG_X86_MCE_INJECT is not set - -CONFIG_SFI=y -CONFIG_INPUT_WINBOND_CIR=m -CONFIG_I2C_SCMI=m -CONFIG_SBC_FITPC2_WATCHDOG=m -CONFIG_EDAC_I3200=m -CONFIG_TOPSTAR_LAPTOP=m CONFIG_INTEL_TXT=y + CONFIG_GPIO_LANGWELL=y CONFIG_FUNCTION_GRAPH_TRACER=y -CONFIG_ACPI_CMPC=m -CONFIG_MSI_WMI=m -CONFIG_TOSHIBA_BT_RFKILL=m -CONFIG_SAMSUNG_LAPTOP=m - -CONFIG_CS5535_MFGPT=m -CONFIG_GEODE_WDT=m -CONFIG_CS5535_CLOCK_EVENT_SRC=m - -CONFIG_X86_DECODER_SELFTEST=y - -CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m - -CONFIG_VGA_SWITCHEROO=y -CONFIG_LPC_SCH=m - CONFIG_I7300_IDLE=m -CONFIG_PCI_CNB20LE_QUIRK=y - -CONFIG_ACPI_EC_DEBUGFS=m -# CONFIG_ACPI_APEI_ERST_DEBUG is not set -CONFIG_INTEL_IDLE=y -# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set -CONFIG_SENSORS_PKGTEMP=m -CONFIG_F71808E_WDT=m -CONFIG_HPWDT_NMI_DECODING=y -# CONFIG_MFD_TPS6586X is not set -# CONFIG_INTEL_MID_DMAC is not set -CONFIG_PCH_DMA=m -# CONFIG_ACPI_QUICKSTART is not set -CONFIG_IDEAPAD_ACPI=m -CONFIG_INTEL_IPS=m -CONFIG_IDEAPAD_LAPTOP=m -# CONFIG_IBM_RTL is not set - -CONFIG_EDAC_MCE_INJ=m -CONFIG_IRQ_TIME_ACCOUNTING=y -CONFIG_X86_RESERVE_LOW=64 - -CONFIG_PCH_GBE=m -CONFIG_PCH_PHUB=m - -CONFIG_VIDEO_VIA_CAMERA=m - -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 + +# Should be 32bit only, but lacks KConfig depends +# CONFIG_XO15_EBOOK is not set + diff --git a/dmar-disable-when-ricoh-multifunction.patch b/dmar-disable-when-ricoh-multifunction.patch index 120730f9e..a4528617e 100644 --- a/dmar-disable-when-ricoh-multifunction.patch +++ b/dmar-disable-when-ricoh-multifunction.patch @@ -9,8 +9,8 @@ Subject: [PATCH] dmar: disable if ricoh multifunction detected diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 4789f8e..5923914 100644 ---- a/drivers/pci/intel-iommu.c -+++ b/drivers/pci/intel-iommu.c +--- a/drivers/iommu/intel-iommu.c ++++ b/drivers/iommu/intel-iommu.c @@ -3784,6 +3784,16 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_g DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt); diff --git a/drm-i915-fbc-stfu.patch b/drm-i915-fbc-stfu.patch new file mode 100644 index 000000000..9240387ee --- /dev/null +++ b/drm-i915-fbc-stfu.patch @@ -0,0 +1,102 @@ +From c5d1455d9340c63e5c5d987e2d816e77538caa90 Mon Sep 17 00:00:00 2001 +From: Adam Jackson +Date: Tue, 13 Sep 2011 12:07:37 -0400 +Subject: [PATCH] drm/i915: Shut the fbc messages up + +FB compression enable/disable fires on pretty much every pageflip now, +which is just uncredibly excessive. Hush that noise. + +Signed-off-by: Adam Jackson +--- + drivers/gpu/drm/i915/intel_display.c | 19 ------------------- + 1 files changed, 0 insertions(+), 19 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index 56a8554..a6d14eb 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -1474,8 +1474,6 @@ static void i8xx_disable_fbc(struct drm_device *dev) + DRM_DEBUG_KMS("FBC idle timed out\n"); + return; + } +- +- DRM_DEBUG_KMS("disabled FBC\n"); + } + + static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) +@@ -1516,9 +1514,6 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) + fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT; + fbc_ctl |= obj->fence_reg; + I915_WRITE(FBC_CONTROL, fbc_ctl); +- +- DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %d, ", +- cfb_pitch, crtc->y, intel_crtc->plane); + } + + static bool i8xx_fbc_enabled(struct drm_device *dev) +@@ -1551,8 +1546,6 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) + + /* enable it... */ + I915_WRITE(DPFC_CONTROL, I915_READ(DPFC_CONTROL) | DPFC_CTL_EN); +- +- DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); + } + + static void g4x_disable_fbc(struct drm_device *dev) +@@ -1565,8 +1558,6 @@ static void g4x_disable_fbc(struct drm_device *dev) + if (dpfc_ctl & DPFC_CTL_EN) { + dpfc_ctl &= ~DPFC_CTL_EN; + I915_WRITE(DPFC_CONTROL, dpfc_ctl); +- +- DRM_DEBUG_KMS("disabled FBC\n"); + } + } + +@@ -1631,8 +1622,6 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) + I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y); + sandybridge_blit_fbc_update(dev); + } +- +- DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); + } + + static void ironlake_disable_fbc(struct drm_device *dev) +@@ -1645,8 +1634,6 @@ static void ironlake_disable_fbc(struct drm_device *dev) + if (dpfc_ctl & DPFC_CTL_EN) { + dpfc_ctl &= ~DPFC_CTL_EN; + I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); +- +- DRM_DEBUG_KMS("disabled FBC\n"); + } + } + +@@ -1701,8 +1688,6 @@ static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv) + if (dev_priv->fbc_work == NULL) + return; + +- DRM_DEBUG_KMS("cancelling pending FBC enable\n"); +- + /* Synchronisation is provided by struct_mutex and checking of + * dev_priv->fbc_work, so we can perform the cancellation + * entirely asynchronously. +@@ -1743,8 +1728,6 @@ static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval) + + dev_priv->fbc_work = work; + +- DRM_DEBUG_KMS("scheduling delayed FBC enable\n"); +- + /* Delay the actual enabling to let pageflipping cease and the + * display to settle before starting the compression. Note that + * this delay also serves a second purpose: it allows for a +@@ -1800,8 +1783,6 @@ static void intel_update_fbc(struct drm_device *dev) + struct drm_i915_gem_object *obj; + int enable_fbc; + +- DRM_DEBUG_KMS("\n"); +- + if (!i915_powersave) + return; + +-- +1.7.6 + diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index 651cc4ac3..1e7c9279e 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -1,284 +1,4970 @@ - drivers/gpu/drm/nouveau/nouveau_drv.c | 11 ++- - drivers/gpu/drm/nouveau/nouveau_drv.h | 3 +- - drivers/gpu/drm/nouveau/nouveau_state.c | 4 +- - drivers/gpu/drm/nouveau/nv04_graph.c | 22 ++---- - drivers/gpu/drm/nouveau/nv10_graph.c | 15 +++-- - drivers/gpu/drm/nouveau/nv20_graph.c | 11 ++- - drivers/gpu/drm/nouveau/nv40_graph.c | 112 ++++++------------------------- - drivers/gpu/drm/nouveau/nv40_mpeg.c | 2 +- - drivers/gpu/drm/nouveau/nv50_graph.c | 9 ++- - drivers/gpu/drm/nouveau/nv50_mpeg.c | 2 +- - drivers/gpu/drm/nouveau/nv84_crypt.c | 2 +- - drivers/gpu/drm/nouveau/nva3_copy.c | 2 +- - drivers/gpu/drm/nouveau/nvc0_copy.c | 2 +- - drivers/gpu/drm/nouveau/nvc0_graph.c | 2 +- - 14 files changed, 68 insertions(+), 131 deletions(-) - -diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c -index 02c6f37..4e1a360 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_drv.c -+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c -@@ -210,10 +210,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) - pfifo->unload_context(dev); +diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile +index 0583677..35ef5b1 100644 +--- a/drivers/gpu/drm/nouveau/Makefile ++++ b/drivers/gpu/drm/nouveau/Makefile +@@ -21,16 +21,17 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ + nv40_grctx.o nv50_grctx.o nvc0_grctx.o \ + nv84_crypt.o \ + nva3_copy.o nvc0_copy.o \ +- nv40_mpeg.o nv50_mpeg.o \ ++ nv31_mpeg.o nv50_mpeg.o \ + nv04_instmem.o nv50_instmem.o nvc0_instmem.o \ +- nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \ +- nv50_cursor.o nv50_display.o \ + nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ + nv04_crtc.o nv04_display.o nv04_cursor.o \ ++ nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \ ++ nv50_cursor.o nv50_display.o \ ++ nvd0_display.o \ + nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o \ + nv10_gpio.o nv50_gpio.o \ + nv50_calc.o \ +- nv04_pm.o nv50_pm.o nva3_pm.o \ ++ nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \ + nv50_vram.o nvc0_vram.o \ + nv50_vm.o nvc0_vm.o - for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) { -- if (dev_priv->eng[e]) { -- ret = dev_priv->eng[e]->fini(dev, e); -- if (ret) -- goto out_abort; -+ if (!dev_priv->eng[e]) -+ continue; -+ -+ ret = dev_priv->eng[e]->fini(dev, e, true); -+ if (ret) { -+ NV_ERROR(dev, "... engine %d failed: %d\n", i, ret); -+ goto out_abort; - } - } +diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c +index 00a55df..fa22b28 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c ++++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c +@@ -37,8 +37,10 @@ + #include "nouveau_drv.h" + #include "nouveau_drm.h" + #include "nouveau_reg.h" ++#include "nouveau_encoder.h" -diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h -index 9c56331..82d6295 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_drv.h -+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h -@@ -297,7 +297,7 @@ struct nouveau_channel { - struct nouveau_exec_engine { - void (*destroy)(struct drm_device *, int engine); - int (*init)(struct drm_device *, int engine); -- int (*fini)(struct drm_device *, int engine); -+ int (*fini)(struct drm_device *, int engine, bool suspend); - int (*context_new)(struct nouveau_channel *, int engine); - void (*context_del)(struct nouveau_channel *, int engine); - int (*object_new)(struct nouveau_channel *, int engine, -@@ -1120,7 +1120,6 @@ extern int nvc0_fifo_unload_context(struct drm_device *); - - /* nv04_graph.c */ - extern int nv04_graph_create(struct drm_device *); --extern void nv04_graph_fifo_access(struct drm_device *, bool); - extern int nv04_graph_object_new(struct nouveau_channel *, int, u32, u16); - extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data); -diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c -index 731acea..e65e71b 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_state.c -+++ b/drivers/gpu/drm/nouveau/nouveau_state.c -@@ -682,7 +682,7 @@ out_engine: - for (e = e - 1; e >= 0; e--) { - if (!dev_priv->eng[e]) - continue; -- dev_priv->eng[e]->fini(dev, e); -+ dev_priv->eng[e]->fini(dev, e, false); - dev_priv->eng[e]->destroy(dev,e ); - } - } -@@ -727,7 +727,7 @@ static void nouveau_card_takedown(struct drm_device *dev) - engine->fifo.takedown(dev); - for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) { - if (dev_priv->eng[e]) { -- dev_priv->eng[e]->fini(dev, e); -+ dev_priv->eng[e]->fini(dev, e, false); - dev_priv->eng[e]->destroy(dev,e ); - } - } -diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c -index 3626ee7..dbdea8e 100644 ---- a/drivers/gpu/drm/nouveau/nv04_graph.c -+++ b/drivers/gpu/drm/nouveau/nv04_graph.c -@@ -450,13 +450,13 @@ nv04_graph_context_del(struct nouveau_channel *chan, int engine) - unsigned long flags; - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -- nv04_graph_fifo_access(dev, false); -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - - /* Unload the context if it's the currently active one */ - if (nv04_graph_channel(dev) == chan) - nv04_graph_unload_context(dev); - -- nv04_graph_fifo_access(dev, true); -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* Free the context resources */ -@@ -538,24 +538,18 @@ nv04_graph_init(struct drm_device *dev, int engine) - } - - static int --nv04_graph_fini(struct drm_device *dev, int engine) -+nv04_graph_fini(struct drm_device *dev, int engine, bool suspend) +-static int nv40_get_intensity(struct backlight_device *bd) ++static int ++nv40_get_intensity(struct backlight_device *bd) { -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); -+ if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); -+ return -EBUSY; -+ } - nv04_graph_unload_context(dev); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); - return 0; + struct drm_device *dev = bl_get_data(bd); + int val = (nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK) +@@ -47,7 +49,8 @@ static int nv40_get_intensity(struct backlight_device *bd) + return val; } --void --nv04_graph_fifo_access(struct drm_device *dev, bool enabled) --{ -- if (enabled) -- nv_wr32(dev, NV04_PGRAPH_FIFO, -- nv_rd32(dev, NV04_PGRAPH_FIFO) | 1); -- else -- nv_wr32(dev, NV04_PGRAPH_FIFO, -- nv_rd32(dev, NV04_PGRAPH_FIFO) & ~1); --} -- - static int - nv04_graph_mthd_set_ref(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) -diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c -index 0930c6c..7255e4a 100644 ---- a/drivers/gpu/drm/nouveau/nv10_graph.c -+++ b/drivers/gpu/drm/nouveau/nv10_graph.c -@@ -708,8 +708,8 @@ static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan, - 0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst); - nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); -- nv04_graph_fifo_access(dev, true); -- nv04_graph_fifo_access(dev, false); -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - - /* Restore the FIFO state */ - for (i = 0; i < ARRAY_SIZE(fifo); i++) -@@ -879,13 +879,13 @@ nv10_graph_context_del(struct nouveau_channel *chan, int engine) - unsigned long flags; - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -- nv04_graph_fifo_access(dev, false); -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - - /* Unload the context if it's the currently active one */ - if (nv10_graph_channel(dev) == chan) - nv10_graph_unload_context(dev); - -- nv04_graph_fifo_access(dev, true); -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* Free the context resources */ -@@ -957,8 +957,13 @@ nv10_graph_init(struct drm_device *dev, int engine) - } - - static int --nv10_graph_fini(struct drm_device *dev, int engine) -+nv10_graph_fini(struct drm_device *dev, int engine, bool suspend) +-static int nv40_set_intensity(struct backlight_device *bd) ++static int ++nv40_set_intensity(struct backlight_device *bd) { -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); -+ if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); -+ return -EBUSY; -+ } - nv10_graph_unload_context(dev); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); - return 0; -diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c -index affc7d7..b6cf157 100644 ---- a/drivers/gpu/drm/nouveau/nv20_graph.c -+++ b/drivers/gpu/drm/nouveau/nv20_graph.c -@@ -454,13 +454,13 @@ nv20_graph_context_del(struct nouveau_channel *chan, int engine) - unsigned long flags; - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -- nv04_graph_fifo_access(dev, false); -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - - /* Unload the context if it's the currently active one */ - if (nv10_graph_channel(dev) == chan) - nv20_graph_unload_context(dev); - -- nv04_graph_fifo_access(dev, true); -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* Free the context resources */ -@@ -654,8 +654,13 @@ nv30_graph_init(struct drm_device *dev, int engine) - } - - int --nv20_graph_fini(struct drm_device *dev, int engine) -+nv20_graph_fini(struct drm_device *dev, int engine, bool suspend) - { -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); -+ if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); -+ return -EBUSY; -+ } - nv20_graph_unload_context(dev); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); - return 0; -diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c -index 5beb01b..ba14a93 100644 ---- a/drivers/gpu/drm/nouveau/nv40_graph.c -+++ b/drivers/gpu/drm/nouveau/nv40_graph.c -@@ -35,89 +35,6 @@ struct nv40_graph_engine { - u32 grctx_size; + struct drm_device *dev = bl_get_data(bd); + int val = bd->props.brightness; +@@ -65,30 +68,8 @@ static const struct backlight_ops nv40_bl_ops = { + .update_status = nv40_set_intensity, }; --static struct nouveau_channel * --nv40_graph_channel(struct drm_device *dev) +-static int nv50_get_intensity(struct backlight_device *bd) -{ +- struct drm_device *dev = bl_get_data(bd); +- +- return nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT); +-} +- +-static int nv50_set_intensity(struct backlight_device *bd) +-{ +- struct drm_device *dev = bl_get_data(bd); +- int val = bd->props.brightness; +- +- nv_wr32(dev, NV50_PDISPLAY_SOR_BACKLIGHT, +- val | NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE); +- return 0; +-} +- +-static const struct backlight_ops nv50_bl_ops = { +- .options = BL_CORE_SUSPENDRESUME, +- .get_brightness = nv50_get_intensity, +- .update_status = nv50_set_intensity, +-}; +- +-static int nouveau_nv40_backlight_init(struct drm_connector *connector) ++static int ++nv40_backlight_init(struct drm_connector *connector) + { + struct drm_device *dev = connector->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; +@@ -113,34 +94,129 @@ static int nouveau_nv40_backlight_init(struct drm_connector *connector) + return 0; + } + +-static int nouveau_nv50_backlight_init(struct drm_connector *connector) ++static int ++nv50_get_intensity(struct backlight_device *bd) ++{ ++ struct nouveau_encoder *nv_encoder = bl_get_data(bd); ++ struct drm_device *dev = nv_encoder->base.base.dev; ++ int or = nv_encoder->or; ++ u32 div = 1025; ++ u32 val; ++ ++ val = nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(or)); ++ val &= NV50_PDISP_SOR_PWM_CTL_VAL; ++ return ((val * 100) + (div / 2)) / div; ++} ++ ++static int ++nv50_set_intensity(struct backlight_device *bd) ++{ ++ struct nouveau_encoder *nv_encoder = bl_get_data(bd); ++ struct drm_device *dev = nv_encoder->base.base.dev; ++ int or = nv_encoder->or; ++ u32 div = 1025; ++ u32 val = (bd->props.brightness * div) / 100; ++ ++ nv_wr32(dev, NV50_PDISP_SOR_PWM_CTL(or), ++ NV50_PDISP_SOR_PWM_CTL_NEW | val); ++ return 0; ++} ++ ++static const struct backlight_ops nv50_bl_ops = { ++ .options = BL_CORE_SUSPENDRESUME, ++ .get_brightness = nv50_get_intensity, ++ .update_status = nv50_set_intensity, ++}; ++ ++static int ++nva3_get_intensity(struct backlight_device *bd) ++{ ++ struct nouveau_encoder *nv_encoder = bl_get_data(bd); ++ struct drm_device *dev = nv_encoder->base.base.dev; ++ int or = nv_encoder->or; ++ u32 div, val; ++ ++ div = nv_rd32(dev, NV50_PDISP_SOR_PWM_DIV(or)); ++ val = nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(or)); ++ val &= NVA3_PDISP_SOR_PWM_CTL_VAL; ++ if (div && div >= val) ++ return ((val * 100) + (div / 2)) / div; ++ ++ return 100; ++} ++ ++static int ++nva3_set_intensity(struct backlight_device *bd) ++{ ++ struct nouveau_encoder *nv_encoder = bl_get_data(bd); ++ struct drm_device *dev = nv_encoder->base.base.dev; ++ int or = nv_encoder->or; ++ u32 div, val; ++ ++ div = nv_rd32(dev, NV50_PDISP_SOR_PWM_DIV(or)); ++ val = (bd->props.brightness * div) / 100; ++ if (div) { ++ nv_wr32(dev, NV50_PDISP_SOR_PWM_CTL(or), val | ++ NV50_PDISP_SOR_PWM_CTL_NEW | ++ NVA3_PDISP_SOR_PWM_CTL_UNK); ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static const struct backlight_ops nva3_bl_ops = { ++ .options = BL_CORE_SUSPENDRESUME, ++ .get_brightness = nva3_get_intensity, ++ .update_status = nva3_set_intensity, ++}; ++ ++static int ++nv50_backlight_init(struct drm_connector *connector) + { + struct drm_device *dev = connector->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_encoder *nv_encoder; + struct backlight_properties props; + struct backlight_device *bd; ++ const struct backlight_ops *ops; ++ ++ nv_encoder = find_encoder(connector, OUTPUT_LVDS); ++ if (!nv_encoder) { ++ nv_encoder = find_encoder(connector, OUTPUT_DP); ++ if (!nv_encoder) ++ return -ENODEV; ++ } + +- if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT)) ++ if (!nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(nv_encoder->or))) + return 0; + ++ if (dev_priv->chipset <= 0xa0 || ++ dev_priv->chipset == 0xaa || ++ dev_priv->chipset == 0xac) ++ ops = &nv50_bl_ops; ++ else ++ ops = &nva3_bl_ops; ++ + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; +- props.max_brightness = 1025; +- bd = backlight_device_register("nv_backlight", &connector->kdev, dev, +- &nv50_bl_ops, &props); ++ props.max_brightness = 100; ++ bd = backlight_device_register("nv_backlight", &connector->kdev, ++ nv_encoder, ops, &props); + if (IS_ERR(bd)) + return PTR_ERR(bd); + + dev_priv->backlight = bd; +- bd->props.brightness = nv50_get_intensity(bd); ++ bd->props.brightness = bd->ops->get_brightness(bd); + backlight_update_status(bd); + return 0; + } + +-int nouveau_backlight_init(struct drm_connector *connector) ++int ++nouveau_backlight_init(struct drm_device *dev) + { +- struct drm_device *dev = connector->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct drm_connector *connector; + + #ifdef CONFIG_ACPI + if (acpi_video_backlight_support()) { +@@ -150,21 +226,28 @@ int nouveau_backlight_init(struct drm_connector *connector) + } + #endif + +- switch (dev_priv->card_type) { +- case NV_40: +- return nouveau_nv40_backlight_init(connector); +- case NV_50: +- return nouveau_nv50_backlight_init(connector); +- default: +- break; ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { ++ if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && ++ connector->connector_type != DRM_MODE_CONNECTOR_eDP) ++ continue; ++ ++ switch (dev_priv->card_type) { ++ case NV_40: ++ return nv40_backlight_init(connector); ++ case NV_50: ++ return nv50_backlight_init(connector); ++ default: ++ break; ++ } + } + ++ + return 0; + } + +-void nouveau_backlight_exit(struct drm_connector *connector) ++void ++nouveau_backlight_exit(struct drm_device *dev) + { +- struct drm_device *dev = connector->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->backlight) { +diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c +index b311fab..032a820 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_bios.c ++++ b/drivers/gpu/drm/nouveau/nouveau_bios.c +@@ -296,6 +296,11 @@ munge_reg(struct nvbios *bios, uint32_t reg) + if (dev_priv->card_type < NV_50) + return reg; + ++ if (reg & 0x80000000) { ++ BUG_ON(bios->display.crtc < 0); ++ reg += bios->display.crtc * 0x800; ++ } ++ + if (reg & 0x40000000) { + BUG_ON(!dcbent); + +@@ -304,7 +309,7 @@ munge_reg(struct nvbios *bios, uint32_t reg) + reg += 0x00000080; + } + +- reg &= ~0x60000000; ++ reg &= ~0xe0000000; + return reg; + } + +@@ -1174,22 +1179,19 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + * + */ + +- struct bit_displayport_encoder_table *dpe = NULL; + struct dcb_entry *dcb = bios->display.output; + struct drm_device *dev = bios->dev; + uint8_t cond = bios->data[offset + 1]; +- int dummy; ++ uint8_t *table, *entry; + + BIOSLOG(bios, "0x%04X: subop 0x%02X\n", offset, cond); + + if (!iexec->execute) + return 3; + +- dpe = nouveau_bios_dp_table(dev, dcb, &dummy); +- if (!dpe) { +- NV_ERROR(dev, "0x%04X: INIT_3A: no encoder table!!\n", offset); ++ table = nouveau_dp_bios_data(dev, dcb, &entry); ++ if (!table) + return 3; +- } + + switch (cond) { + case 0: +@@ -1203,7 +1205,7 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + break; + case 1: + case 2: +- if (!(dpe->unknown & cond)) ++ if (!(entry[5] & cond)) + iexec->execute = false; + break; + case 5: +@@ -3221,6 +3223,49 @@ init_8d(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + return 1; + } + ++static void ++init_gpio_unknv50(struct nvbios *bios, struct dcb_gpio_entry *gpio) ++{ ++ const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; ++ u32 r, s, v; ++ ++ /* Not a clue, needs de-magicing */ ++ r = nv50_gpio_ctl[gpio->line >> 4]; ++ s = (gpio->line & 0x0f); ++ v = bios_rd32(bios, r) & ~(0x00010001 << s); ++ switch ((gpio->entry & 0x06000000) >> 25) { ++ case 1: ++ v |= (0x00000001 << s); ++ break; ++ case 2: ++ v |= (0x00010000 << s); ++ break; ++ default: ++ break; ++ } ++ ++ bios_wr32(bios, r, v); ++} ++ ++static void ++init_gpio_unknvd0(struct nvbios *bios, struct dcb_gpio_entry *gpio) ++{ ++ u32 v, i; ++ ++ v = bios_rd32(bios, 0x00d610 + (gpio->line * 4)); ++ v &= 0xffffff00; ++ v |= (gpio->entry & 0x00ff0000) >> 16; ++ bios_wr32(bios, 0x00d610 + (gpio->line * 4), v); ++ ++ i = (gpio->entry & 0x1f000000) >> 24; ++ if (i) { ++ v = bios_rd32(bios, 0x00d640 + ((i - 1) * 4)); ++ v &= 0xffffff00; ++ v |= gpio->line; ++ bios_wr32(bios, 0x00d640 + ((i - 1) * 4), v); ++ } ++} ++ + static int + init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + { +@@ -3235,7 +3280,6 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + + struct drm_nouveau_private *dev_priv = bios->dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; +- const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; + int i; + + if (dev_priv->card_type < NV_50) { +@@ -3248,33 +3292,20 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + + for (i = 0; i < bios->dcb.gpio.entries; i++) { + struct dcb_gpio_entry *gpio = &bios->dcb.gpio.entry[i]; +- uint32_t r, s, v; + + BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry); + + BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n", + offset, gpio->tag, gpio->state_default); +- if (bios->execute) +- pgpio->set(bios->dev, gpio->tag, gpio->state_default); + +- /* The NVIDIA binary driver doesn't appear to actually do +- * any of this, my VBIOS does however. +- */ +- /* Not a clue, needs de-magicing */ +- r = nv50_gpio_ctl[gpio->line >> 4]; +- s = (gpio->line & 0x0f); +- v = bios_rd32(bios, r) & ~(0x00010001 << s); +- switch ((gpio->entry & 0x06000000) >> 25) { +- case 1: +- v |= (0x00000001 << s); +- break; +- case 2: +- v |= (0x00010000 << s); +- break; +- default: +- break; +- } +- bios_wr32(bios, r, v); ++ if (!bios->execute) ++ continue; ++ ++ pgpio->set(bios->dev, gpio->tag, gpio->state_default); ++ if (dev_priv->card_type < NV_D0) ++ init_gpio_unknv50(bios, gpio); ++ else ++ init_gpio_unknvd0(bios, gpio); + } + + return 1; +@@ -3737,6 +3768,10 @@ parse_init_table(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + int count = 0, i, ret; + uint8_t id; + ++ /* catch NULL script pointers */ ++ if (offset == 0) ++ return 0; ++ + /* + * Loop until INIT_DONE causes us to break out of the loop + * (or until offset > bios length just in case... ) +@@ -4389,86 +4424,37 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b + return 0; + } + +-static uint8_t * +-bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent, +- uint16_t record, int record_len, int record_nr, +- bool match_link) ++/* BIT 'U'/'d' table encoder subtables have hashes matching them to ++ * a particular set of encoders. ++ * ++ * This function returns true if a particular DCB entry matches. ++ */ ++bool ++bios_encoder_match(struct dcb_entry *dcb, u32 hash) + { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *grctx; -- uint32_t inst; -- int i; +- struct nvbios *bios = &dev_priv->vbios; +- uint32_t entry; +- uint16_t table; +- int i, v; ++ if ((hash & 0x000000f0) != (dcb->location << 4)) ++ return false; ++ if ((hash & 0x0000000f) != dcb->type) ++ return false; ++ if (!(hash & (dcb->or << 16))) ++ return false; + +- switch (dcbent->type) { ++ switch (dcb->type) { + case OUTPUT_TMDS: + case OUTPUT_LVDS: + case OUTPUT_DP: +- break; +- default: +- match_link = false; +- break; +- } - -- inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); -- if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) -- return NULL; -- inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4; +- for (i = 0; i < record_nr; i++, record += record_len) { +- table = ROM16(bios->data[record]); +- if (!table) +- continue; +- entry = ROM32(bios->data[table]); - -- for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- if (!dev_priv->channels.ptr[i]) +- if (match_link) { +- v = (entry & 0x00c00000) >> 22; +- if (!(v & dcbent->sorconf.link)) +- continue; ++ if (hash & 0x00c00000) { ++ if (!(hash & (dcb->sorconf.link << 22))) ++ return false; + } +- +- v = (entry & 0x000f0000) >> 16; +- if (!(v & dcbent->or)) - continue; - -- grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR]; -- if (grctx && grctx->pinst == inst) -- return dev_priv->channels.ptr[i]; +- v = (entry & 0x000000f0) >> 4; +- if (v != dcbent->location) +- continue; +- +- v = (entry & 0x0000000f); +- if (v != dcbent->type) +- continue; +- +- return &bios->data[table]; - } - - return NULL; -} - --static int --nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) +-void * +-nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent, +- int *length) -{ -- uint32_t old_cp, tv = 1000, tmp; -- int i; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nvbios *bios = &dev_priv->vbios; +- uint8_t *table; - -- old_cp = nv_rd32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER); -- nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); +- if (!bios->display.dp_table_ptr) { +- NV_ERROR(dev, "No pointer to DisplayPort table\n"); +- return NULL; +- } +- table = &bios->data[bios->display.dp_table_ptr]; - -- tmp = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0310); -- tmp |= save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE : -- NV40_PGRAPH_CTXCTL_0310_XFER_LOAD; -- nv_wr32(dev, NV40_PGRAPH_CTXCTL_0310, tmp); +- if (table[0] != 0x20 && table[0] != 0x21) { +- NV_ERROR(dev, "DisplayPort table version 0x%02x unknown\n", +- table[0]); +- return NULL; ++ default: ++ return true; + } - -- tmp = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0304); -- tmp |= NV40_PGRAPH_CTXCTL_0304_XFER_CTX; -- nv_wr32(dev, NV40_PGRAPH_CTXCTL_0304, tmp); +- *length = table[4]; +- return bios_output_config_match(dev, dcbent, +- bios->display.dp_table_ptr + table[1], +- table[2], table[3], table[0] >= 0x21); + } + + int +-nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, +- uint32_t sub, int pxclk) ++nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, ++ struct dcb_entry *dcbent, int crtc) + { + /* + * The display script table is located by the BIT 'U' table. +@@ -4498,7 +4484,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, + uint8_t *table = &bios->data[bios->display.script_table_ptr]; + uint8_t *otable = NULL; + uint16_t script; +- int i = 0; ++ int i; + + if (!bios->display.script_table_ptr) { + NV_ERROR(dev, "No pointer to output script table\n"); +@@ -4550,30 +4536,33 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, + + NV_DEBUG_KMS(dev, "Searching for output entry for %d %d %d\n", + dcbent->type, dcbent->location, dcbent->or); +- otable = bios_output_config_match(dev, dcbent, table[1] + +- bios->display.script_table_ptr, +- table[2], table[3], table[0] >= 0x21); ++ for (i = 0; i < table[3]; i++) { ++ otable = ROMPTR(bios, table[table[1] + (i * table[2])]); ++ if (otable && bios_encoder_match(dcbent, ROM32(otable[0]))) ++ break; ++ } ++ + if (!otable) { + NV_DEBUG_KMS(dev, "failed to match any output table\n"); + return 1; + } + +- if (pxclk < -2 || pxclk > 0) { ++ if (pclk < -2 || pclk > 0) { + /* Try to find matching script table entry */ + for (i = 0; i < otable[5]; i++) { +- if (ROM16(otable[table[4] + i*6]) == sub) ++ if (ROM16(otable[table[4] + i*6]) == type) + break; + } + + if (i == otable[5]) { + NV_ERROR(dev, "Table 0x%04x not found for %d/%d, " + "using first\n", +- sub, dcbent->type, dcbent->or); ++ type, dcbent->type, dcbent->or); + i = 0; + } + } + +- if (pxclk == 0) { ++ if (pclk == 0) { + script = ROM16(otable[6]); + if (!script) { + NV_DEBUG_KMS(dev, "output script 0 not found\n"); +@@ -4581,9 +4570,9 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, + } + + NV_DEBUG_KMS(dev, "0x%04X: parsing output script 0\n", script); +- nouveau_bios_run_init_table(dev, script, dcbent); ++ nouveau_bios_run_init_table(dev, script, dcbent, crtc); + } else +- if (pxclk == -1) { ++ if (pclk == -1) { + script = ROM16(otable[8]); + if (!script) { + NV_DEBUG_KMS(dev, "output script 1 not found\n"); +@@ -4591,9 +4580,9 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, + } + + NV_DEBUG_KMS(dev, "0x%04X: parsing output script 1\n", script); +- nouveau_bios_run_init_table(dev, script, dcbent); ++ nouveau_bios_run_init_table(dev, script, dcbent, crtc); + } else +- if (pxclk == -2) { ++ if (pclk == -2) { + if (table[4] >= 12) + script = ROM16(otable[10]); + else +@@ -4604,31 +4593,31 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, + } + + NV_DEBUG_KMS(dev, "0x%04X: parsing output script 2\n", script); +- nouveau_bios_run_init_table(dev, script, dcbent); ++ nouveau_bios_run_init_table(dev, script, dcbent, crtc); + } else +- if (pxclk > 0) { ++ if (pclk > 0) { + script = ROM16(otable[table[4] + i*6 + 2]); + if (script) +- script = clkcmptable(bios, script, pxclk); ++ script = clkcmptable(bios, script, pclk); + if (!script) { + NV_DEBUG_KMS(dev, "clock script 0 not found\n"); + return 1; + } + + NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 0\n", script); +- nouveau_bios_run_init_table(dev, script, dcbent); ++ nouveau_bios_run_init_table(dev, script, dcbent, crtc); + } else +- if (pxclk < 0) { ++ if (pclk < 0) { + script = ROM16(otable[table[4] + i*6 + 4]); + if (script) +- script = clkcmptable(bios, script, -pxclk); ++ script = clkcmptable(bios, script, -pclk); + if (!script) { + NV_DEBUG_KMS(dev, "clock script 1 not found\n"); + return 1; + } + + NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 1\n", script); +- nouveau_bios_run_init_table(dev, script, dcbent); ++ nouveau_bios_run_init_table(dev, script, dcbent, crtc); + } + + return 0; +@@ -5478,14 +5467,6 @@ parse_bit_U_tbl_entry(struct drm_device *dev, struct nvbios *bios, + return 0; + } + +-static int +-parse_bit_displayport_tbl_entry(struct drm_device *dev, struct nvbios *bios, +- struct bit_entry *bitentry) +-{ +- bios->display.dp_table_ptr = ROM16(bios->data[bitentry->offset]); +- return 0; +-} - -- nouveau_wait_for_idle(dev); + struct bit_table { + const char id; + int (* const parse_fn)(struct drm_device *, struct nvbios *, struct bit_entry *); +@@ -5559,7 +5540,6 @@ parse_bit_structure(struct nvbios *bios, const uint16_t bitoffset) + parse_bit_table(bios, bitoffset, &BIT_TABLE('L', lvds)); + parse_bit_table(bios, bitoffset, &BIT_TABLE('T', tmds)); + parse_bit_table(bios, bitoffset, &BIT_TABLE('U', U)); +- parse_bit_table(bios, bitoffset, &BIT_TABLE('d', displayport)); + + return 0; + } +@@ -5884,9 +5864,15 @@ parse_dcb_gpio_table(struct nvbios *bios) + } + + e->line = (e->entry & 0x0000001f) >> 0; +- e->state_default = (e->entry & 0x01000000) >> 24; +- e->state[0] = (e->entry & 0x18000000) >> 27; +- e->state[1] = (e->entry & 0x60000000) >> 29; ++ if (gpio[0] == 0x40) { ++ e->state_default = (e->entry & 0x01000000) >> 24; ++ e->state[0] = (e->entry & 0x18000000) >> 27; ++ e->state[1] = (e->entry & 0x60000000) >> 29; ++ } else { ++ e->state_default = (e->entry & 0x00000080) >> 7; ++ e->state[0] = (entry[4] >> 4) & 3; ++ e->state[1] = (entry[4] >> 6) & 3; ++ } + } + } + +@@ -6156,7 +6142,14 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, + } + case OUTPUT_DP: + entry->dpconf.sor.link = (conf & 0x00000030) >> 4; +- entry->dpconf.link_bw = (conf & 0x00e00000) >> 21; ++ switch ((conf & 0x00e00000) >> 21) { ++ case 0: ++ entry->dpconf.link_bw = 162000; ++ break; ++ default: ++ entry->dpconf.link_bw = 270000; ++ break; ++ } + switch ((conf & 0x0f000000) >> 24) { + case 0xf: + entry->dpconf.link_nr = 4; +@@ -6769,7 +6762,7 @@ uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev) + + void + nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, +- struct dcb_entry *dcbent) ++ struct dcb_entry *dcbent, int crtc) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->vbios; +@@ -6777,11 +6770,22 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, + + spin_lock_bh(&bios->lock); + bios->display.output = dcbent; ++ bios->display.crtc = crtc; + parse_init_table(bios, table, &iexec); + bios->display.output = NULL; + spin_unlock_bh(&bios->lock); + } + ++void ++nouveau_bios_init_exec(struct drm_device *dev, uint16_t table) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvbios *bios = &dev_priv->vbios; ++ struct init_exec iexec = { true, false }; ++ ++ parse_init_table(bios, table, &iexec); ++} ++ + static bool NVInitVBIOS(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +@@ -6863,9 +6867,8 @@ nouveau_run_vbios_init(struct drm_device *dev) + + if (dev_priv->card_type >= NV_50) { + for (i = 0; i < bios->dcb.entries; i++) { +- nouveau_bios_run_display_table(dev, +- &bios->dcb.entry[i], +- 0, 0); ++ nouveau_bios_run_display_table(dev, 0, 0, ++ &bios->dcb.entry[i], -1); + } + } + +diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h +index 050c314..8adb69e 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_bios.h ++++ b/drivers/gpu/drm/nouveau/nouveau_bios.h +@@ -289,8 +289,8 @@ struct nvbios { + + struct { + struct dcb_entry *output; ++ int crtc; + uint16_t script_table_ptr; +- uint16_t dp_table_ptr; + } display; + + struct { +diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c +index 890d50e..7226f41 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_bo.c ++++ b/drivers/gpu/drm/nouveau/nouveau_bo.c +@@ -956,7 +956,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) + break; + } + +- if (dev_priv->card_type == NV_C0) ++ if (dev_priv->card_type >= NV_C0) + page_shift = node->page_shift; + else + page_shift = 12; +diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c +index b0d753f..a319d56 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_channel.c ++++ b/drivers/gpu/drm/nouveau/nouveau_channel.c +@@ -411,13 +411,17 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, + return ret; + init->channel = chan->id; + +- if (chan->dma.ib_max) +- init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM | +- NOUVEAU_GEM_DOMAIN_GART; +- else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM) ++ if (nouveau_vram_pushbuf == 0) { ++ if (chan->dma.ib_max) ++ init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM | ++ NOUVEAU_GEM_DOMAIN_GART; ++ else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM) ++ init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM; ++ else ++ init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART; ++ } else { + init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM; +- else +- init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART; ++ } + + if (dev_priv->card_type < NV_C0) { + init->subchan[0].handle = NvM2MF; +diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c +index 939d4df..e0d275e 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_connector.c ++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c +@@ -39,7 +39,7 @@ + + static void nouveau_connector_hotplug(void *, int); + +-static struct nouveau_encoder * ++struct nouveau_encoder * + find_encoder(struct drm_connector *connector, int type) + { + struct drm_device *dev = connector->dev; +@@ -116,10 +116,6 @@ nouveau_connector_destroy(struct drm_connector *connector) + nouveau_connector_hotplug, connector); + } + +- if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS || +- connector->connector_type == DRM_MODE_CONNECTOR_eDP) +- nouveau_backlight_exit(connector); - -- for (i = 0; i < tv; i++) { -- if (nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C) == 0) + kfree(nv_connector->edid); + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); +@@ -712,11 +708,8 @@ nouveau_connector_mode_valid(struct drm_connector *connector, + case OUTPUT_TV: + return get_slave_funcs(encoder)->mode_valid(encoder, mode); + case OUTPUT_DP: +- if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7) +- max_clock = nv_encoder->dp.link_nr * 270000; +- else +- max_clock = nv_encoder->dp.link_nr * 162000; +- ++ max_clock = nv_encoder->dp.link_nr; ++ max_clock *= nv_encoder->dp.link_bw; + clock = clock * nouveau_connector_bpp(connector) / 8; + break; + default: +@@ -871,7 +864,6 @@ nouveau_connector_create(struct drm_device *dev, int index) + dev->mode_config.scaling_mode_property, + nv_connector->scaling_mode); + } +- connector->polled = DRM_CONNECTOR_POLL_CONNECT; + /* fall-through */ + case DCB_CONNECTOR_TV_0: + case DCB_CONNECTOR_TV_1: +@@ -888,27 +880,20 @@ nouveau_connector_create(struct drm_device *dev, int index) + dev->mode_config.dithering_mode_property, + nv_connector->use_dithering ? + DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF); +- +- if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS) { +- if (dev_priv->card_type >= NV_50) +- connector->polled = DRM_CONNECTOR_POLL_HPD; +- else +- connector->polled = DRM_CONNECTOR_POLL_CONNECT; +- } + break; + } + +- if (pgpio->irq_register) { ++ if (nv_connector->dcb->gpio_tag != 0xff && pgpio->irq_register) { + pgpio->irq_register(dev, nv_connector->dcb->gpio_tag, + nouveau_connector_hotplug, connector); ++ ++ connector->polled = DRM_CONNECTOR_POLL_HPD; ++ } else { ++ connector->polled = DRM_CONNECTOR_POLL_CONNECT; + } + + drm_sysfs_connector_add(connector); + +- if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS || +- connector->connector_type == DRM_MODE_CONNECTOR_eDP) +- nouveau_backlight_init(connector); +- + dcb->drm = connector; + return dcb->drm; + +@@ -925,22 +910,13 @@ nouveau_connector_hotplug(void *data, int plugged) + struct drm_connector *connector = data; + struct drm_device *dev = connector->dev; + +- NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un", +- drm_get_connector_name(connector)); +- +- if (connector->encoder && connector->encoder->crtc && +- connector->encoder->crtc->enabled) { +- struct nouveau_encoder *nv_encoder = nouveau_encoder(connector->encoder); +- struct drm_encoder_helper_funcs *helper = +- connector->encoder->helper_private; ++ NV_DEBUG(dev, "%splugged %s\n", plugged ? "" : "un", ++ drm_get_connector_name(connector)); + +- if (nv_encoder->dcb->type == OUTPUT_DP) { +- if (plugged) +- helper->dpms(connector->encoder, DRM_MODE_DPMS_ON); +- else +- helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF); +- } +- } ++ if (plugged) ++ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); ++ else ++ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + + drm_helper_hpd_irq_event(dev); + } +diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h +index cb1ce2a..bf8e128 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_crtc.h ++++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h +@@ -82,14 +82,13 @@ static inline struct drm_crtc *to_drm_crtc(struct nouveau_crtc *crtc) + } + + int nv50_crtc_create(struct drm_device *dev, int index); +-int nv50_cursor_init(struct nouveau_crtc *); +-void nv50_cursor_fini(struct nouveau_crtc *); + int nv50_crtc_cursor_set(struct drm_crtc *drm_crtc, struct drm_file *file_priv, + uint32_t buffer_handle, uint32_t width, + uint32_t height); + int nv50_crtc_cursor_move(struct drm_crtc *drm_crtc, int x, int y); + + int nv04_cursor_init(struct nouveau_crtc *); ++int nv50_cursor_init(struct nouveau_crtc *); + + struct nouveau_connector * + nouveau_crtc_connector_get(struct nouveau_crtc *crtc); +diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c +index eb514ea..ddbabef 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_display.c ++++ b/drivers/gpu/drm/nouveau/nouveau_display.c +@@ -105,9 +105,12 @@ nouveau_framebuffer_init(struct drm_device *dev, + if (dev_priv->chipset == 0x50) + nv_fb->r_format |= (tile_flags << 8); + +- if (!tile_flags) +- nv_fb->r_pitch = 0x00100000 | fb->pitch; +- else { ++ if (!tile_flags) { ++ if (dev_priv->card_type < NV_D0) ++ nv_fb->r_pitch = 0x00100000 | fb->pitch; ++ else ++ nv_fb->r_pitch = 0x01000000 | fb->pitch; ++ } else { + u32 mode = nvbo->tile_mode; + if (dev_priv->card_type >= NV_C0) + mode >>= 4; +diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c +index 7beb82a..de5efe7 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_dp.c ++++ b/drivers/gpu/drm/nouveau/nouveau_dp.c +@@ -28,418 +28,619 @@ + #include "nouveau_i2c.h" + #include "nouveau_connector.h" + #include "nouveau_encoder.h" ++#include "nouveau_crtc.h" ++ ++/****************************************************************************** ++ * aux channel util functions ++ *****************************************************************************/ ++#define AUX_DBG(fmt, args...) do { \ ++ if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_AUXCH) { \ ++ NV_PRINTK(KERN_DEBUG, dev, "AUXCH(%d): " fmt, ch, ##args); \ ++ } \ ++} while (0) ++#define AUX_ERR(fmt, args...) NV_ERROR(dev, "AUXCH(%d): " fmt, ch, ##args) ++ ++static void ++auxch_fini(struct drm_device *dev, int ch) ++{ ++ nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); ++} + + static int +-auxch_rd(struct drm_encoder *encoder, int address, uint8_t *buf, int size) ++auxch_init(struct drm_device *dev, int ch) + { +- struct drm_device *dev = encoder->dev; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct nouveau_i2c_chan *auxch; +- int ret; +- +- auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); +- if (!auxch) +- return -ENODEV; +- +- ret = nouveau_dp_auxch(auxch, 9, address, buf, size); +- if (ret) +- return ret; ++ const u32 unksel = 1; /* nfi which to use, or if it matters.. */ ++ const u32 ureq = unksel ? 0x00100000 : 0x00200000; ++ const u32 urep = unksel ? 0x01000000 : 0x02000000; ++ u32 ctrl, timeout; ++ ++ /* wait up to 1ms for any previous transaction to be done... */ ++ timeout = 1000; ++ do { ++ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); ++ udelay(1); ++ if (!timeout--) { ++ AUX_ERR("begin idle timeout 0x%08x", ctrl); ++ return -EBUSY; ++ } ++ } while (ctrl & 0x03010000); ++ ++ /* set some magic, and wait up to 1ms for it to appear */ ++ nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq); ++ timeout = 1000; ++ do { ++ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); ++ udelay(1); ++ if (!timeout--) { ++ AUX_ERR("magic wait 0x%08x\n", ctrl); ++ auxch_fini(dev, ch); ++ return -EBUSY; ++ } ++ } while ((ctrl & 0x03000000) != urep); + + return 0; + } + + static int +-auxch_wr(struct drm_encoder *encoder, int address, uint8_t *buf, int size) ++auxch_tx(struct drm_device *dev, int ch, u8 type, u32 addr, u8 *data, u8 size) + { +- struct drm_device *dev = encoder->dev; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct nouveau_i2c_chan *auxch; +- int ret; ++ u32 ctrl, stat, timeout, retries; ++ u32 xbuf[4] = {}; ++ int ret, i; + +- auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); +- if (!auxch) +- return -ENODEV; ++ AUX_DBG("%d: 0x%08x %d\n", type, addr, size); + +- ret = nouveau_dp_auxch(auxch, 8, address, buf, size); +- return ret; +-} ++ ret = auxch_init(dev, ch); ++ if (ret) ++ goto out; + +-static int +-nouveau_dp_lane_count_set(struct drm_encoder *encoder, uint8_t cmd) +-{ +- struct drm_device *dev = encoder->dev; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- uint32_t tmp; +- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); +- +- tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); +- tmp &= ~(NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED | +- NV50_SOR_DP_CTRL_LANE_MASK); +- tmp |= ((1 << (cmd & DP_LANE_COUNT_MASK)) - 1) << 16; +- if (cmd & DP_LANE_COUNT_ENHANCED_FRAME_EN) +- tmp |= NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED; +- nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); +- +- return auxch_wr(encoder, DP_LANE_COUNT_SET, &cmd, 1); +-} ++ stat = nv_rd32(dev, 0x00e4e8 + (ch * 0x50)); ++ if (!(stat & 0x10000000)) { ++ AUX_DBG("sink not detected\n"); ++ ret = -ENXIO; ++ goto out; ++ } + +-static int +-nouveau_dp_link_bw_set(struct drm_encoder *encoder, uint8_t cmd) +-{ +- struct drm_device *dev = encoder->dev; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- uint32_t tmp; +- int reg = 0x614300 + (nv_encoder->or * 0x800); ++ if (!(type & 1)) { ++ memcpy(xbuf, data, size); ++ for (i = 0; i < 16; i += 4) { ++ AUX_DBG("wr 0x%08x\n", xbuf[i / 4]); ++ nv_wr32(dev, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]); ++ } ++ } + +- tmp = nv_rd32(dev, reg); +- tmp &= 0xfff3ffff; +- if (cmd == DP_LINK_BW_2_7) +- tmp |= 0x00040000; +- nv_wr32(dev, reg, tmp); ++ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); ++ ctrl &= ~0x0001f0ff; ++ ctrl |= type << 12; ++ ctrl |= size - 1; ++ nv_wr32(dev, 0x00e4e0 + (ch * 0x50), addr); ++ ++ /* retry transaction a number of times on failure... */ ++ ret = -EREMOTEIO; ++ for (retries = 0; retries < 32; retries++) { ++ /* reset, and delay a while if this is a retry */ ++ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); ++ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); ++ if (retries) ++ udelay(400); ++ ++ /* transaction request, wait up to 1ms for it to complete */ ++ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); ++ ++ timeout = 1000; ++ do { ++ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); ++ udelay(1); ++ if (!timeout--) { ++ AUX_ERR("tx req timeout 0x%08x\n", ctrl); ++ goto out; ++ } ++ } while (ctrl & 0x00010000); + +- return auxch_wr(encoder, DP_LINK_BW_SET, &cmd, 1); +-} ++ /* read status, and check if transaction completed ok */ ++ stat = nv_mask(dev, 0x00e4e8 + (ch * 0x50), 0, 0); ++ if (!(stat & 0x000f0f00)) { ++ ret = 0; ++ break; ++ } + +-static int +-nouveau_dp_link_train_set(struct drm_encoder *encoder, int pattern) +-{ +- struct drm_device *dev = encoder->dev; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- uint32_t tmp; +- uint8_t cmd; +- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); +- int ret; ++ AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); ++ } + +- tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); +- tmp &= ~NV50_SOR_DP_CTRL_TRAINING_PATTERN; +- tmp |= (pattern << 24); +- nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); ++ if (type & 1) { ++ for (i = 0; i < 16; i += 4) { ++ xbuf[i / 4] = nv_rd32(dev, 0x00e4d0 + (ch * 0x50) + i); ++ AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); ++ } ++ memcpy(data, xbuf, size); ++ } + +- ret = auxch_rd(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1); +- if (ret) +- return ret; +- cmd &= ~DP_TRAINING_PATTERN_MASK; +- cmd |= (pattern & DP_TRAINING_PATTERN_MASK); +- return auxch_wr(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1); ++out: ++ auxch_fini(dev, ch); ++ return ret; + } + +-static int +-nouveau_dp_max_voltage_swing(struct drm_encoder *encoder) ++static u32 ++dp_link_bw_get(struct drm_device *dev, int or, int link) + { +- 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 i, dpe_headerlen, max_vs = 0; +- +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) +- return false; +- dpse = (void *)((char *)dpe + dpe_headerlen); ++ u32 ctrl = nv_rd32(dev, 0x614300 + (or * 0x800)); ++ if (!(ctrl & 0x000c0000)) ++ return 162000; ++ return 270000; ++} + +- for (i = 0; i < dpe_headerlen; i++, dpse++) { +- if (dpse->vs_level > max_vs) +- max_vs = dpse->vs_level; ++static int ++dp_lane_count_get(struct drm_device *dev, int or, int link) ++{ ++ u32 ctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); ++ switch (ctrl & 0x000f0000) { ++ case 0x00010000: return 1; ++ case 0x00030000: return 2; ++ default: ++ return 4; + } +- +- return max_vs; + } + +-static int +-nouveau_dp_max_pre_emphasis(struct drm_encoder *encoder, int vs) ++void ++nouveau_dp_tu_update(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) + { +- 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 i, dpe_headerlen, max_pre = 0; ++ const u32 symbol = 100000; ++ int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0; ++ int TU, VTUi, VTUf, VTUa; ++ u64 link_data_rate, link_ratio, unk; ++ u32 best_diff = 64 * symbol; ++ u32 link_nr, link_bw, r; ++ ++ /* calculate packed data rate for each lane */ ++ link_nr = dp_lane_count_get(dev, or, link); ++ link_data_rate = (clk * bpp / 8) / link_nr; ++ ++ /* calculate ratio of packed data rate to link symbol rate */ ++ link_bw = dp_link_bw_get(dev, or, link); ++ link_ratio = link_data_rate * symbol; ++ r = do_div(link_ratio, link_bw); ++ ++ for (TU = 64; TU >= 32; TU--) { ++ /* calculate average number of valid symbols in each TU */ ++ u32 tu_valid = link_ratio * TU; ++ u32 calc, diff; ++ ++ /* find a hw representation for the fraction.. */ ++ VTUi = tu_valid / symbol; ++ calc = VTUi * symbol; ++ diff = tu_valid - calc; ++ if (diff) { ++ if (diff >= (symbol / 2)) { ++ VTUf = symbol / (symbol - diff); ++ if (symbol - (VTUf * diff)) ++ VTUf++; ++ ++ if (VTUf <= 15) { ++ VTUa = 1; ++ calc += symbol - (symbol / VTUf); ++ } else { ++ VTUa = 0; ++ VTUf = 1; ++ calc += symbol; ++ } ++ } else { ++ VTUa = 0; ++ VTUf = min((int)(symbol / diff), 15); ++ calc += symbol / VTUf; ++ } + +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) +- return false; +- dpse = (void *)((char *)dpe + dpe_headerlen); ++ diff = calc - tu_valid; ++ } else { ++ /* no remainder, but the hw doesn't like the fractional ++ * part to be zero. decrement the integer part and ++ * have the fraction add a whole symbol back ++ */ ++ VTUa = 0; ++ VTUf = 1; ++ VTUi--; ++ } + +- for (i = 0; i < dpe_headerlen; i++, dpse++) { +- if (dpse->vs_level != vs) +- continue; ++ if (diff < best_diff) { ++ best_diff = diff; ++ bestTU = TU; ++ bestVTUa = VTUa; ++ bestVTUf = VTUf; ++ bestVTUi = VTUi; ++ if (diff == 0) ++ break; ++ } ++ } + +- if (dpse->pre_level > max_pre) +- max_pre = dpse->pre_level; ++ if (!bestTU) { ++ NV_ERROR(dev, "DP: unable to find suitable config\n"); ++ return; + } + +- return max_pre; ++ /* XXX close to vbios numbers, but not right */ ++ unk = (symbol - link_ratio) * bestTU; ++ unk *= link_ratio; ++ r = do_div(unk, symbol); ++ r = do_div(unk, symbol); ++ unk += 6; ++ ++ nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2); ++ nv_mask(dev, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 | ++ bestVTUf << 16 | ++ bestVTUi << 8 | ++ unk); + } + +-static bool +-nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config) ++u8 * ++nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) + { +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct drm_device *dev = encoder->dev; +- struct bit_displayport_encoder_table *dpe; +- int ret, i, dpe_headerlen, vs = 0, pre = 0; +- uint8_t request[2]; +- +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) +- return false; +- +- ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2); +- if (ret) +- return false; +- +- NV_DEBUG_KMS(dev, "\t\tadjust 0x%02x 0x%02x\n", request[0], request[1]); +- +- /* Keep all lanes at the same level.. */ +- for (i = 0; i < nv_encoder->dp.link_nr; i++) { +- int lane_req = (request[i >> 1] >> ((i & 1) << 2)) & 0xf; +- int lane_vs = lane_req & 3; +- int lane_pre = (lane_req >> 2) & 3; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvbios *bios = &dev_priv->vbios; ++ struct bit_entry d; ++ u8 *table; ++ int i; ++ ++ if (bit_table(dev, 'd', &d)) { ++ NV_ERROR(dev, "BIT 'd' table not found\n"); ++ return NULL; ++ } + +- if (lane_vs > vs) +- vs = lane_vs; +- if (lane_pre > pre) +- pre = lane_pre; ++ if (d.version != 1) { ++ NV_ERROR(dev, "BIT 'd' table version %d unknown\n", d.version); ++ return NULL; + } + +- if (vs >= nouveau_dp_max_voltage_swing(encoder)) { +- vs = nouveau_dp_max_voltage_swing(encoder); +- vs |= 4; ++ table = ROMPTR(bios, d.data[0]); ++ if (!table) { ++ NV_ERROR(dev, "displayport table pointer invalid\n"); ++ return NULL; + } + +- if (pre >= nouveau_dp_max_pre_emphasis(encoder, vs & 3)) { +- pre = nouveau_dp_max_pre_emphasis(encoder, vs & 3); +- pre |= 4; ++ switch (table[0]) { ++ case 0x20: ++ case 0x21: ++ case 0x30: ++ break; ++ default: ++ NV_ERROR(dev, "displayport table 0x%02x unknown\n", table[0]); ++ return NULL; + } + +- /* Update the configuration for all lanes.. */ +- for (i = 0; i < nv_encoder->dp.link_nr; i++) +- config[i] = (pre << 3) | vs; ++ for (i = 0; i < table[3]; i++) { ++ *entry = ROMPTR(bios, table[table[1] + (i * table[2])]); ++ if (*entry && bios_encoder_match(dcb, ROM32((*entry)[0]))) ++ return table; ++ } + +- return true; ++ NV_ERROR(dev, "displayport encoder table not found\n"); ++ return NULL; + } + +-static bool +-nouveau_dp_link_train_commit(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 or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); +- int dpe_headerlen, ret, i; ++/****************************************************************************** ++ * link training ++ *****************************************************************************/ ++struct dp_state { ++ struct dcb_entry *dcb; ++ u8 *table; ++ u8 *entry; ++ int auxch; ++ int crtc; ++ int or; ++ int link; ++ u8 *dpcd; ++ int link_nr; ++ u32 link_bw; ++ u8 stat[6]; ++ u8 conf[4]; ++}; + +- NV_DEBUG_KMS(dev, "\t\tconfig 0x%02x 0x%02x 0x%02x 0x%02x\n", +- config[0], config[1], config[2], config[3]); ++static void ++dp_set_link_config(struct drm_device *dev, struct dp_state *dp) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ int or = dp->or, link = dp->link; ++ u8 *entry, sink[2]; ++ u32 dp_ctrl; ++ u16 script; ++ ++ NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); ++ ++ /* set selected link rate on source */ ++ switch (dp->link_bw) { ++ case 270000: ++ nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00040000); ++ sink[0] = DP_LINK_BW_2_7; ++ break; ++ default: ++ nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00000000); ++ sink[0] = DP_LINK_BW_1_62; ++ break; ++ } + +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) +- return false; +- dpse = (void *)((char *)dpe + dpe_headerlen); ++ /* offset +0x0a of each dp encoder table entry is a pointer to another ++ * table, that has (among other things) pointers to more scripts that ++ * need to be executed, this time depending on link speed. ++ */ ++ entry = ROMPTR(&dev_priv->vbios, dp->entry[10]); ++ if (entry) { ++ if (dp->table[0] < 0x30) { ++ while (dp->link_bw < (ROM16(entry[0]) * 10)) ++ entry += 4; ++ script = ROM16(entry[2]); ++ } else { ++ while (dp->link_bw < (entry[0] * 27000)) ++ entry += 3; ++ script = ROM16(entry[1]); ++ } + +- for (i = 0; i < dpe->record_nr; i++, dpse++) { +- if (dpse->vs_level == (config[0] & 3) && +- dpse->pre_level == ((config[0] >> 3) & 3)) +- break; ++ nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc); + } +- BUG_ON(i == dpe->record_nr); +- +- for (i = 0; i < nv_encoder->dp.link_nr; i++) { +- const int shift[4] = { 16, 8, 0, 24 }; +- uint32_t mask = 0xff << shift[i]; +- uint32_t reg0, reg1, reg2; +- +- reg0 = nv_rd32(dev, NV50_SOR_DP_UNK118(or, link)) & ~mask; +- reg0 |= (dpse->reg0 << shift[i]); +- reg1 = nv_rd32(dev, NV50_SOR_DP_UNK120(or, link)) & ~mask; +- reg1 |= (dpse->reg1 << shift[i]); +- reg2 = nv_rd32(dev, NV50_SOR_DP_UNK130(or, link)) & 0xffff00ff; +- reg2 |= (dpse->reg2 << 8); +- nv_wr32(dev, NV50_SOR_DP_UNK118(or, link), reg0); +- nv_wr32(dev, NV50_SOR_DP_UNK120(or, link), reg1); +- nv_wr32(dev, NV50_SOR_DP_UNK130(or, link), reg2); ++ ++ /* configure lane count on the source */ ++ dp_ctrl = ((1 << dp->link_nr) - 1) << 16; ++ sink[1] = dp->link_nr; ++ if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) { ++ dp_ctrl |= 0x00004000; ++ sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + } + +- ret = auxch_wr(encoder, DP_TRAINING_LANE0_SET, config, 4); +- if (ret) +- return false; ++ nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x001f4000, dp_ctrl); + +- return true; ++ /* inform the sink of the new configuration */ ++ auxch_tx(dev, dp->auxch, 8, DP_LINK_BW_SET, sink, 2); + } + +-bool +-nouveau_dp_link_train(struct drm_encoder *encoder) ++static void ++dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 tp) + { +- struct drm_device *dev = encoder->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct nouveau_connector *nv_connector; +- struct bit_displayport_encoder_table *dpe; +- int dpe_headerlen; +- uint8_t config[4], status[3]; +- bool cr_done, cr_max_vs, eq_done, hpd_state; +- int ret = 0, i, tries, voltage; ++ u8 sink_tp; + +- NV_DEBUG_KMS(dev, "link training!!\n"); ++ NV_DEBUG_KMS(dev, "training pattern %d\n", tp); + +- nv_connector = nouveau_encoder_connector_get(nv_encoder); +- if (!nv_connector) +- return false; ++ nv_mask(dev, NV50_SOR_DP_CTRL(dp->or, dp->link), 0x0f000000, tp << 24); + +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) { +- NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or); +- return false; +- } ++ auxch_tx(dev, dp->auxch, 9, DP_TRAINING_PATTERN_SET, &sink_tp, 1); ++ sink_tp &= ~DP_TRAINING_PATTERN_MASK; ++ sink_tp |= tp; ++ auxch_tx(dev, dp->auxch, 8, DP_TRAINING_PATTERN_SET, &sink_tp, 1); ++} + +- /* disable hotplug detect, this flips around on some panels during +- * link training. +- */ +- hpd_state = pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); ++static const u8 nv50_lane_map[] = { 16, 8, 0, 24 }; ++static const u8 nvaf_lane_map[] = { 24, 16, 8, 0 }; ++ ++static int ++dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 mask = 0, drv = 0, pre = 0, unk = 0; ++ const u8 *shifts; ++ int link = dp->link; ++ int or = dp->or; ++ int i; ++ ++ if (dev_priv->chipset != 0xaf) ++ shifts = nv50_lane_map; ++ else ++ shifts = nvaf_lane_map; ++ ++ for (i = 0; i < dp->link_nr; i++) { ++ u8 *conf = dp->entry + dp->table[4]; ++ u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; ++ u8 lpre = (lane & 0x0c) >> 2; ++ u8 lvsw = (lane & 0x03) >> 0; ++ ++ mask |= 0xff << shifts[i]; ++ unk |= 1 << (shifts[i] >> 3); ++ ++ dp->conf[i] = (lpre << 3) | lvsw; ++ if (lvsw == DP_TRAIN_VOLTAGE_SWING_1200) ++ dp->conf[i] |= DP_TRAIN_MAX_SWING_REACHED; ++ if (lpre == DP_TRAIN_PRE_EMPHASIS_9_5) ++ dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; ++ ++ NV_DEBUG_KMS(dev, "config lane %d %02x\n", i, dp->conf[i]); ++ ++ if (dp->table[0] < 0x30) { ++ u8 *last = conf + (dp->entry[4] * dp->table[5]); ++ while (lvsw != conf[0] || lpre != conf[1]) { ++ conf += dp->table[5]; ++ if (conf >= last) ++ return -EINVAL; ++ } ++ ++ conf += 2; ++ } else { ++ /* no lookup table anymore, set entries for each ++ * combination of voltage swing and pre-emphasis ++ * level allowed by the DP spec. ++ */ ++ switch (lvsw) { ++ case 0: lpre += 0; break; ++ case 1: lpre += 4; break; ++ case 2: lpre += 7; break; ++ case 3: lpre += 9; break; ++ } ++ ++ conf = conf + (lpre * dp->table[5]); ++ conf++; ++ } + +- if (dpe->script0) { +- NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); +- nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0), +- nv_encoder->dcb); ++ drv |= conf[0] << shifts[i]; ++ pre |= conf[1] << shifts[i]; ++ unk = (unk & ~0x0000ff00) | (conf[2] << 8); + } + +-train: +- cr_done = eq_done = false; ++ nv_mask(dev, NV50_SOR_DP_UNK118(or, link), mask, drv); ++ nv_mask(dev, NV50_SOR_DP_UNK120(or, link), mask, pre); ++ nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000ff0f, unk); + +- /* set link configuration */ +- NV_DEBUG_KMS(dev, "\tbegin train: bw %d, lanes %d\n", +- nv_encoder->dp.link_bw, nv_encoder->dp.link_nr); ++ return auxch_tx(dev, dp->auxch, 8, DP_TRAINING_LANE0_SET, dp->conf, 4); ++} + +- ret = nouveau_dp_link_bw_set(encoder, nv_encoder->dp.link_bw); +- if (ret) +- return false; ++static int ++dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay) ++{ ++ int ret; + +- config[0] = nv_encoder->dp.link_nr; +- if (nv_encoder->dp.dpcd_version >= 0x11 && +- nv_encoder->dp.enhanced_frame) +- config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; ++ udelay(delay); + +- ret = nouveau_dp_lane_count_set(encoder, config[0]); ++ ret = auxch_tx(dev, dp->auxch, 9, DP_LANE0_1_STATUS, dp->stat, 6); + if (ret) +- return false; ++ return ret; + +- /* clock recovery */ +- NV_DEBUG_KMS(dev, "\tbegin cr\n"); +- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_1); +- if (ret) +- goto stop; ++ NV_DEBUG_KMS(dev, "status %02x %02x %02x %02x %02x %02x\n", ++ dp->stat[0], dp->stat[1], dp->stat[2], dp->stat[3], ++ dp->stat[4], dp->stat[5]); ++ return 0; ++} + +- tries = 0; +- voltage = -1; +- memset(config, 0x00, sizeof(config)); +- for (;;) { +- if (!nouveau_dp_link_train_commit(encoder, config)) +- break; ++static int ++dp_link_train_cr(struct drm_device *dev, struct dp_state *dp) ++{ ++ bool cr_done = false, abort = false; ++ int voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK; ++ int tries = 0, i; + +- udelay(100); ++ dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_1); + +- ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 2); +- if (ret) ++ do { ++ if (dp_link_train_commit(dev, dp) || ++ dp_link_train_update(dev, dp, 100)) + break; +- NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n", +- status[0], status[1]); + + cr_done = true; +- cr_max_vs = false; +- for (i = 0; i < nv_encoder->dp.link_nr; i++) { +- int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf; +- ++ for (i = 0; i < dp->link_nr; i++) { ++ u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; + if (!(lane & DP_LANE_CR_DONE)) { + cr_done = false; +- if (config[i] & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED) +- cr_max_vs = true; ++ if (dp->conf[i] & DP_TRAIN_MAX_SWING_REACHED) ++ abort = true; + break; + } + } + +- if ((config[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { +- voltage = config[0] & DP_TRAIN_VOLTAGE_SWING_MASK; ++ if ((dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { ++ voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK; + tries = 0; + } ++ } while (!cr_done && !abort && ++tries < 5); + +- if (cr_done || cr_max_vs || (++tries == 5)) +- break; +- +- if (!nouveau_dp_link_train_adjust(encoder, config)) - break; - } - -- nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp); +- if (!cr_done) +- goto stop; ++ return cr_done ? 0 : -1; ++} + +- /* channel equalisation */ +- NV_DEBUG_KMS(dev, "\tbegin eq\n"); +- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_2); +- if (ret) +- goto stop; ++static int ++dp_link_train_eq(struct drm_device *dev, struct dp_state *dp) ++{ ++ bool eq_done, cr_done = true; ++ int tries = 0, i; + +- for (tries = 0; tries <= 5; tries++) { +- udelay(400); ++ dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_2); + +- ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 3); +- if (ret) ++ do { ++ if (dp_link_train_update(dev, dp, 400)) + break; +- NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n", +- status[0], status[1]); + +- eq_done = true; +- if (!(status[2] & DP_INTERLANE_ALIGN_DONE)) +- eq_done = false; - -- if (i == tv) { -- uint32_t ucstat = nv_rd32(dev, NV40_PGRAPH_CTXCTL_UCODE_STAT); -- NV_ERROR(dev, "Failed: Instance=0x%08x Save=%d\n", inst, save); -- NV_ERROR(dev, "IP: 0x%02x, Opcode: 0x%08x\n", -- ucstat >> NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT, -- ucstat & NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK); -- NV_ERROR(dev, "0x40030C = 0x%08x\n", -- nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C)); +- for (i = 0; eq_done && i < nv_encoder->dp.link_nr; i++) { +- int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf; +- +- if (!(lane & DP_LANE_CR_DONE)) { ++ eq_done = !!(dp->stat[2] & DP_INTERLANE_ALIGN_DONE); ++ for (i = 0; i < dp->link_nr && eq_done; i++) { ++ u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; ++ if (!(lane & DP_LANE_CR_DONE)) + cr_done = false; +- break; +- } +- + if (!(lane & DP_LANE_CHANNEL_EQ_DONE) || +- !(lane & DP_LANE_SYMBOL_LOCKED)) { ++ !(lane & DP_LANE_SYMBOL_LOCKED)) + eq_done = false; +- break; +- } + } + +- if (eq_done || !cr_done) ++ if (dp_link_train_commit(dev, dp)) + break; ++ } while (!eq_done && cr_done && ++tries <= 5); + +- if (!nouveau_dp_link_train_adjust(encoder, config) || +- !nouveau_dp_link_train_commit(encoder, config)) +- break; +- } ++ return eq_done ? 0 : -1; ++} + +-stop: +- /* end link training */ +- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_DISABLE); +- if (ret) ++bool ++nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) ++{ ++ struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; ++ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); ++ struct nouveau_connector *nv_connector = ++ nouveau_encoder_connector_get(nv_encoder); ++ struct drm_device *dev = encoder->dev; ++ struct nouveau_i2c_chan *auxch; ++ const u32 bw_list[] = { 270000, 162000, 0 }; ++ const u32 *link_bw = bw_list; ++ struct dp_state dp; ++ ++ auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); ++ if (!auxch) + return false; + +- /* retry at a lower setting, if possible */ +- if (!ret && !(eq_done && cr_done)) { +- NV_DEBUG_KMS(dev, "\twe failed\n"); +- if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62) { +- NV_DEBUG_KMS(dev, "retry link training at low rate\n"); +- nv_encoder->dp.link_bw = DP_LINK_BW_1_62; +- goto train; +- } ++ dp.table = nouveau_dp_bios_data(dev, nv_encoder->dcb, &dp.entry); ++ if (!dp.table) ++ return -EINVAL; ++ ++ dp.dcb = nv_encoder->dcb; ++ dp.crtc = nv_crtc->index; ++ dp.auxch = auxch->rd; ++ dp.or = nv_encoder->or; ++ dp.link = !(nv_encoder->dcb->sorconf.link & 1); ++ dp.dpcd = nv_encoder->dp.dpcd; ++ ++ /* some sinks toggle hotplug in response to some of the actions ++ * we take during link training (DP_SET_POWER is one), we need ++ * to ignore them for the moment to avoid races. ++ */ ++ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); ++ ++ /* enable down-spreading, if possible */ ++ if (dp.table[1] >= 16) { ++ u16 script = ROM16(dp.entry[14]); ++ if (nv_encoder->dp.dpcd[3] & 1) ++ script = ROM16(dp.entry[12]); ++ ++ nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc); + } + +- if (dpe->script1) { +- NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or); +- nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1), +- nv_encoder->dcb); ++ /* execute pre-train script from vbios */ ++ nouveau_bios_run_init_table(dev, ROM16(dp.entry[6]), dp.dcb, dp.crtc); ++ ++ /* start off at highest link rate supported by encoder and display */ ++ while (*link_bw > nv_encoder->dp.link_bw) ++ link_bw++; ++ ++ while (link_bw[0]) { ++ /* find minimum required lane count at this link rate */ ++ dp.link_nr = nv_encoder->dp.link_nr; ++ while ((dp.link_nr >> 1) * link_bw[0] > datarate) ++ dp.link_nr >>= 1; ++ ++ /* drop link rate to minimum with this lane count */ ++ while ((link_bw[1] * dp.link_nr) > datarate) ++ link_bw++; ++ dp.link_bw = link_bw[0]; ++ ++ /* program selected link configuration */ ++ dp_set_link_config(dev, &dp); ++ ++ /* attempt to train the link at this configuration */ ++ memset(dp.stat, 0x00, sizeof(dp.stat)); ++ if (!dp_link_train_cr(dev, &dp) && ++ !dp_link_train_eq(dev, &dp)) ++ break; ++ ++ /* retry at lower rate */ ++ link_bw++; + } + +- /* re-enable hotplug detect */ +- pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, hpd_state); ++ /* finish link training */ ++ dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE); + +- return eq_done; ++ /* execute post-train script from vbios */ ++ nouveau_bios_run_init_table(dev, ROM16(dp.entry[8]), dp.dcb, dp.crtc); ++ ++ /* re-enable hotplug detect */ ++ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true); ++ return true; + } + + bool +@@ -447,31 +648,34 @@ nouveau_dp_detect(struct drm_encoder *encoder) + { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; +- uint8_t dpcd[4]; ++ struct nouveau_i2c_chan *auxch; ++ u8 *dpcd = nv_encoder->dp.dpcd; + int ret; + +- ret = auxch_rd(encoder, 0x0000, dpcd, 4); +- if (ret) ++ auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); ++ if (!auxch) + return false; + +- NV_DEBUG_KMS(dev, "encoder: link_bw %d, link_nr %d\n" +- "display: link_bw %d, link_nr %d version 0x%02x\n", +- nv_encoder->dcb->dpconf.link_bw, +- nv_encoder->dcb->dpconf.link_nr, +- dpcd[1], dpcd[2] & 0x0f, dpcd[0]); ++ ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8); ++ if (ret) ++ return false; + +- nv_encoder->dp.dpcd_version = dpcd[0]; ++ nv_encoder->dp.link_bw = 27000 * dpcd[1]; ++ nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; + +- nv_encoder->dp.link_bw = dpcd[1]; +- if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62 && +- !nv_encoder->dcb->dpconf.link_bw) +- nv_encoder->dp.link_bw = DP_LINK_BW_1_62; ++ NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n", ++ nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); ++ NV_DEBUG_KMS(dev, "encoder: %dx%d\n", ++ nv_encoder->dcb->dpconf.link_nr, ++ nv_encoder->dcb->dpconf.link_bw); + +- nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; +- if (nv_encoder->dp.link_nr > nv_encoder->dcb->dpconf.link_nr) ++ if (nv_encoder->dcb->dpconf.link_nr < nv_encoder->dp.link_nr) + nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; ++ if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw) ++ nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw; + +- nv_encoder->dp.enhanced_frame = (dpcd[2] & DP_ENHANCED_FRAME_CAP); ++ NV_DEBUG_KMS(dev, "maximum: %dx%d\n", ++ nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); + + return true; + } +@@ -480,105 +684,13 @@ int + nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, + uint8_t *data, int data_nr) + { +- struct drm_device *dev = auxch->dev; +- uint32_t tmp, ctrl, stat = 0, data32[4] = {}; +- int ret = 0, i, index = auxch->rd; +- +- NV_DEBUG_KMS(dev, "ch %d cmd %d addr 0x%x len %d\n", index, cmd, addr, data_nr); +- +- tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); +- nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp | 0x00100000); +- tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); +- if (!(tmp & 0x01000000)) { +- NV_ERROR(dev, "expected bit 24 == 1, got 0x%08x\n", tmp); +- ret = -EIO; +- goto out; +- } +- +- for (i = 0; i < 3; i++) { +- tmp = nv_rd32(dev, NV50_AUXCH_STAT(auxch->rd)); +- if (tmp & NV50_AUXCH_STAT_STATE_READY) +- break; +- udelay(100); +- } +- +- if (i == 3) { +- ret = -EBUSY; +- goto out; +- } +- +- if (!(cmd & 1)) { +- memcpy(data32, data, data_nr); +- for (i = 0; i < 4; i++) { +- NV_DEBUG_KMS(dev, "wr %d: 0x%08x\n", i, data32[i]); +- nv_wr32(dev, NV50_AUXCH_DATA_OUT(index, i), data32[i]); +- } +- } +- +- nv_wr32(dev, NV50_AUXCH_ADDR(index), addr); +- ctrl = nv_rd32(dev, NV50_AUXCH_CTRL(index)); +- ctrl &= ~(NV50_AUXCH_CTRL_CMD | NV50_AUXCH_CTRL_LEN); +- ctrl |= (cmd << NV50_AUXCH_CTRL_CMD_SHIFT); +- ctrl |= ((data_nr - 1) << NV50_AUXCH_CTRL_LEN_SHIFT); +- +- for (i = 0; i < 16; i++) { +- nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000); +- nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl); +- nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x00010000); +- if (!nv_wait(dev, NV50_AUXCH_CTRL(index), +- 0x00010000, 0x00000000)) { +- NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n", +- nv_rd32(dev, NV50_AUXCH_CTRL(index))); +- ret = -EBUSY; +- goto out; +- } +- +- udelay(400); +- +- stat = nv_rd32(dev, NV50_AUXCH_STAT(index)); +- if ((stat & NV50_AUXCH_STAT_REPLY_AUX) != +- NV50_AUXCH_STAT_REPLY_AUX_DEFER) +- break; +- } +- +- if (i == 16) { +- NV_ERROR(dev, "auxch DEFER too many times, bailing\n"); +- ret = -EREMOTEIO; +- goto out; +- } +- +- if (cmd & 1) { +- if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) { +- ret = -EREMOTEIO; +- goto out; +- } +- +- for (i = 0; i < 4; i++) { +- data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i)); +- NV_DEBUG_KMS(dev, "rd %d: 0x%08x\n", i, data32[i]); +- } +- memcpy(data, data32, data_nr); +- } +- +-out: +- tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); +- nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp & ~0x00100000); +- tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); +- if (tmp & 0x01000000) { +- NV_ERROR(dev, "expected bit 24 == 0, got 0x%08x\n", tmp); +- ret = -EIO; +- } +- +- udelay(400); +- +- return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY); ++ return auxch_tx(auxch->dev, auxch->rd, cmd, addr, data, data_nr); + } + + static int + nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) + { + struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adap; +- struct drm_device *dev = auxch->dev; + struct i2c_msg *msg = msgs; + int ret, mcnt = num; + +@@ -602,19 +714,6 @@ nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) + if (ret < 0) + return ret; + +- switch (ret & NV50_AUXCH_STAT_REPLY_I2C) { +- case NV50_AUXCH_STAT_REPLY_I2C_ACK: +- break; +- case NV50_AUXCH_STAT_REPLY_I2C_NACK: +- return -EREMOTEIO; +- case NV50_AUXCH_STAT_REPLY_I2C_DEFER: +- udelay(100); +- continue; +- default: +- NV_ERROR(dev, "bad auxch reply: 0x%08x\n", ret); +- return -EREMOTEIO; +- } +- + ptr += cnt; + remaining -= cnt; + } +diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c +index b30ddd8..c1e01f3 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_drv.c ++++ b/drivers/gpu/drm/nouveau/nouveau_drv.c +@@ -41,7 +41,7 @@ int nouveau_agpmode = -1; + module_param_named(agpmode, nouveau_agpmode, int, 0400); + + MODULE_PARM_DESC(modeset, "Enable kernel modesetting"); +-static int nouveau_modeset = -1; /* kms */ ++int nouveau_modeset = -1; + module_param_named(modeset, nouveau_modeset, int, 0400); + + MODULE_PARM_DESC(vbios, "Override default VBIOS location"); +diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h +index d7d51de..29837da 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_drv.h ++++ b/drivers/gpu/drm/nouveau/nouveau_drv.h +@@ -414,12 +414,13 @@ struct nouveau_gpio_engine { + }; + + struct nouveau_pm_voltage_level { +- u8 voltage; +- u8 vid; ++ u32 voltage; /* microvolts */ ++ u8 vid; + }; + + struct nouveau_pm_voltage { + bool supported; ++ u8 version; + u8 vid_mask; + + struct nouveau_pm_voltage_level *level; +@@ -428,17 +429,48 @@ struct nouveau_pm_voltage { + + struct nouveau_pm_memtiming { + int id; +- u32 reg_100220; +- u32 reg_100224; +- u32 reg_100228; +- u32 reg_10022c; +- u32 reg_100230; +- u32 reg_100234; +- u32 reg_100238; +- u32 reg_10023c; +- u32 reg_100240; ++ u32 reg_0; /* 0x10f290 on Fermi, 0x100220 for older */ ++ u32 reg_1; ++ u32 reg_2; ++ u32 reg_3; ++ u32 reg_4; ++ u32 reg_5; ++ u32 reg_6; ++ u32 reg_7; ++ u32 reg_8; ++ /* To be written to 0x1002c0 */ ++ u8 CL; ++ u8 WR; + }; + ++struct nouveau_pm_tbl_header{ ++ u8 version; ++ u8 header_len; ++ u8 entry_cnt; ++ u8 entry_len; ++}; ++ ++struct nouveau_pm_tbl_entry{ ++ u8 tWR; ++ u8 tUNK_1; ++ u8 tCL; ++ u8 tRP; /* Byte 3 */ ++ u8 empty_4; ++ u8 tRAS; /* Byte 5 */ ++ u8 empty_6; ++ u8 tRFC; /* Byte 7 */ ++ u8 empty_8; ++ u8 tRC; /* Byte 9 */ ++ u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14; ++ u8 empty_15,empty_16,empty_17; ++ u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21; ++}; ++ ++/* nouveau_mem.c */ ++void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, ++ struct nouveau_pm_tbl_entry *e, uint8_t magic_number, ++ struct nouveau_pm_memtiming *timing); ++ + #define NOUVEAU_PM_MAX_LEVEL 8 + struct nouveau_pm_level { + struct device_attribute dev_attr; +@@ -448,11 +480,19 @@ struct nouveau_pm_level { + u32 core; + u32 memory; + u32 shader; +- u32 unk05; +- u32 unk0a; +- +- u8 voltage; +- u8 fanspeed; ++ u32 rop; ++ u32 copy; ++ u32 daemon; ++ u32 vdec; ++ u32 unk05; /* nv50:nva3, roughly.. */ ++ u32 unka0; /* nva3:nvc0 */ ++ u32 hub01; /* nvc0- */ ++ u32 hub06; /* nvc0- */ ++ u32 hub07; /* nvc0- */ ++ ++ u32 volt_min; /* microvolts */ ++ u32 volt_max; ++ u8 fanspeed; + + u16 memscript; + struct nouveau_pm_memtiming *timing; +@@ -496,6 +536,11 @@ struct nouveau_pm_engine { + void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *, + u32 id, int khz); + void (*clock_set)(struct drm_device *, void *); ++ ++ int (*clocks_get)(struct drm_device *, struct nouveau_pm_level *); ++ void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *); ++ void (*clocks_set)(struct drm_device *, void *); ++ + int (*voltage_get)(struct drm_device *); + int (*voltage_set)(struct drm_device *, int voltage); + int (*fanspeed_get)(struct drm_device *); +@@ -504,7 +549,7 @@ struct nouveau_pm_engine { + }; + + struct nouveau_vram_engine { +- struct nouveau_mm *mm; ++ struct nouveau_mm mm; + + int (*init)(struct drm_device *); + void (*takedown)(struct drm_device *dev); +@@ -623,6 +668,7 @@ enum nouveau_card_type { + NV_40 = 0x40, + NV_50 = 0x50, + NV_C0 = 0xc0, ++ NV_D0 = 0xd0 + }; + + struct drm_nouveau_private { +@@ -633,8 +679,8 @@ struct drm_nouveau_private { + enum nouveau_card_type card_type; + /* exact chipset, derived from NV_PMC_BOOT_0 */ + int chipset; +- int stepping; + int flags; ++ u32 crystal; + + void __iomem *mmio; + +@@ -721,7 +767,6 @@ struct drm_nouveau_private { + uint64_t vram_size; + uint64_t vram_sys_base; + +- uint64_t fb_phys; + uint64_t fb_available_size; + uint64_t fb_mappable_pages; + uint64_t fb_aper_free; +@@ -784,6 +829,7 @@ nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo) + } + + /* nouveau_drv.c */ ++extern int nouveau_modeset; + extern int nouveau_agpmode; + extern int nouveau_duallink; + extern int nouveau_uscript_lvds; +@@ -824,6 +870,8 @@ extern bool nouveau_wait_eq(struct drm_device *, uint64_t timeout, + uint32_t reg, uint32_t mask, uint32_t val); + extern bool nouveau_wait_ne(struct drm_device *, uint64_t timeout, + uint32_t reg, uint32_t mask, uint32_t val); ++extern bool nouveau_wait_cb(struct drm_device *, u64 timeout, ++ bool (*cond)(void *), void *); + extern bool nouveau_wait_for_idle(struct drm_device *); + extern int nouveau_card_init(struct drm_device *); + +@@ -1006,15 +1054,15 @@ static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector + + /* nouveau_backlight.c */ + #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT +-extern int nouveau_backlight_init(struct drm_connector *); +-extern void nouveau_backlight_exit(struct drm_connector *); ++extern int nouveau_backlight_init(struct drm_device *); ++extern void nouveau_backlight_exit(struct drm_device *); + #else +-static inline int nouveau_backlight_init(struct drm_connector *dev) ++static inline int nouveau_backlight_init(struct drm_device *dev) + { + return 0; + } + +-static inline void nouveau_backlight_exit(struct drm_connector *dev) { } ++static inline void nouveau_backlight_exit(struct drm_device *dev) { } + #endif + + /* nouveau_bios.c */ +@@ -1022,7 +1070,8 @@ extern int nouveau_bios_init(struct drm_device *); + extern void nouveau_bios_takedown(struct drm_device *dev); + extern int nouveau_run_vbios_init(struct drm_device *); + extern void nouveau_bios_run_init_table(struct drm_device *, uint16_t table, +- struct dcb_entry *); ++ struct dcb_entry *, int crtc); ++extern void nouveau_bios_init_exec(struct drm_device *, uint16_t table); + extern struct dcb_gpio_entry *nouveau_bios_gpio_entry(struct drm_device *, + enum dcb_gpio_tag); + extern struct dcb_connector_table_entry * +@@ -1030,11 +1079,8 @@ nouveau_bios_connector_entry(struct drm_device *, int index); + extern u32 get_pll_register(struct drm_device *, enum pll_types); + extern int get_pll_limits(struct drm_device *, uint32_t limit_match, + struct pll_lims *); +-extern int nouveau_bios_run_display_table(struct drm_device *, +- struct dcb_entry *, +- uint32_t script, int pxclk); +-extern void *nouveau_bios_dp_table(struct drm_device *, struct dcb_entry *, +- int *length); ++extern int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, ++ struct dcb_entry *, int crtc); + extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); + extern uint8_t *nouveau_bios_embedded_edid(struct drm_device *); + extern int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk, +@@ -1043,6 +1089,7 @@ extern int run_tmds_table(struct drm_device *, struct dcb_entry *, + int head, int pxclk); + extern int call_lvds_script(struct drm_device *, struct dcb_entry *, int head, + enum LVDS_script, int pxclk); ++bool bios_encoder_match(struct dcb_entry *, u32 hash); + + /* nouveau_ttm.c */ + int nouveau_ttm_global_init(struct drm_nouveau_private *); +@@ -1053,7 +1100,9 @@ int nouveau_ttm_mmap(struct file *, struct vm_area_struct *); + int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, + uint8_t *data, int data_nr); + bool nouveau_dp_detect(struct drm_encoder *); +-bool nouveau_dp_link_train(struct drm_encoder *); ++bool nouveau_dp_link_train(struct drm_encoder *, u32 datarate); ++void nouveau_dp_tu_update(struct drm_device *, int, int, u32, u32); ++u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **); + + /* nv04_fb.c */ + extern int nv04_fb_init(struct drm_device *); +@@ -1179,8 +1228,8 @@ extern int nva3_copy_create(struct drm_device *dev); + /* nvc0_copy.c */ + extern int nvc0_copy_create(struct drm_device *dev, int engine); + +-/* nv40_mpeg.c */ +-extern int nv40_mpeg_create(struct drm_device *dev); ++/* nv31_mpeg.c */ ++extern int nv31_mpeg_create(struct drm_device *dev); + + /* nv50_mpeg.c */ + extern int nv50_mpeg_create(struct drm_device *dev); +@@ -1265,6 +1314,11 @@ extern int nv04_display_create(struct drm_device *); + extern int nv04_display_init(struct drm_device *); + extern void nv04_display_destroy(struct drm_device *); + ++/* nvd0_display.c */ ++extern int nvd0_display_create(struct drm_device *); ++extern int nvd0_display_init(struct drm_device *); ++extern void nvd0_display_destroy(struct drm_device *); ++ + /* nv04_crtc.c */ + extern int nv04_crtc_create(struct drm_device *, int index); + +@@ -1374,6 +1428,8 @@ int nv50_gpio_init(struct drm_device *dev); + void nv50_gpio_fini(struct drm_device *dev); + int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); + int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); ++int nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); ++int nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); + int nv50_gpio_irq_register(struct drm_device *, enum dcb_gpio_tag, + void (*)(void *, int), void *); + void nv50_gpio_irq_unregister(struct drm_device *, enum dcb_gpio_tag, +@@ -1448,6 +1504,8 @@ static inline void nv_wr08(struct drm_device *dev, unsigned reg, u8 val) + nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val)) + #define nv_wait_ne(dev, reg, mask, val) \ + nouveau_wait_ne(dev, 2000000000ULL, (reg), (mask), (val)) ++#define nv_wait_cb(dev, func, data) \ ++ nouveau_wait_cb(dev, 2000000000ULL, (func), (data)) + + /* PRAMIN access */ + static inline u32 nv_ri32(struct drm_device *dev, unsigned offset) +@@ -1514,6 +1572,7 @@ enum { + NOUVEAU_REG_DEBUG_RMVIO = 0x80, + NOUVEAU_REG_DEBUG_VGAATTR = 0x100, + NOUVEAU_REG_DEBUG_EVO = 0x200, ++ NOUVEAU_REG_DEBUG_AUXCH = 0x400 + }; + + #define NV_REG_DEBUG(type, dev, fmt, arg...) do { \ +diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h +index ae69b61..e5d6e3f 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h ++++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h +@@ -49,17 +49,17 @@ struct nouveau_encoder { + + union { + struct { +- int mc_unknown; +- uint32_t unk0; +- uint32_t unk1; +- int dpcd_version; ++ u8 dpcd[8]; + int link_nr; + int link_bw; +- bool enhanced_frame; ++ u32 datarate; + } dp; + }; + }; + ++struct nouveau_encoder * ++find_encoder(struct drm_connector *connector, int type); ++ + static inline struct nouveau_encoder *nouveau_encoder(struct drm_encoder *enc) + { + struct drm_encoder_slave *slave = to_encoder_slave(enc); +@@ -83,21 +83,4 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder); + int nv50_sor_create(struct drm_connector *, struct dcb_entry *); + int nv50_dac_create(struct drm_connector *, struct dcb_entry *); + +-struct bit_displayport_encoder_table { +- uint32_t match; +- uint8_t record_nr; +- uint8_t unknown; +- uint16_t script0; +- uint16_t script1; +- uint16_t unknown_table; +-} __attribute__ ((packed)); +- +-struct bit_displayport_encoder_table_entry { +- uint8_t vs_level; +- uint8_t pre_level; +- uint8_t reg0; +- uint8_t reg1; +- uint8_t reg2; +-} __attribute__ ((packed)); +- + #endif /* __NOUVEAU_ENCODER_H__ */ +diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c +index c919cfc..81116cf 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_fence.c ++++ b/drivers/gpu/drm/nouveau/nouveau_fence.c +@@ -519,7 +519,7 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) + 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, ++ ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_FROM_MEMORY, + mem->start << PAGE_SHIFT, + mem->size, NV_MEM_ACCESS_RW, + NV_MEM_TARGET_VRAM, &obj); +diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c +index cb389d0..f6a27fa 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_i2c.c ++++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c +@@ -107,6 +107,13 @@ nv4e_i2c_getsda(void *data) + return !!((nv_rd32(dev, i2c->rd) >> 16) & 8); + } + ++static const uint32_t nv50_i2c_port[] = { ++ 0x00e138, 0x00e150, 0x00e168, 0x00e180, ++ 0x00e254, 0x00e274, 0x00e764, 0x00e780, ++ 0x00e79c, 0x00e7b8 ++}; ++#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port) ++ + static int + nv50_i2c_getscl(void *data) + { +@@ -130,28 +137,32 @@ static void + nv50_i2c_setscl(void *data, int state) + { + struct nouveau_i2c_chan *i2c = data; +- struct drm_device *dev = i2c->dev; + +- nv_wr32(dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0)); ++ nv_wr32(i2c->dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0)); + } + + static void + nv50_i2c_setsda(void *data, int state) + { + struct nouveau_i2c_chan *i2c = data; +- struct drm_device *dev = i2c->dev; + +- nv_wr32(dev, i2c->wr, +- (nv_rd32(dev, i2c->rd) & 1) | 4 | (state ? 2 : 0)); ++ nv_mask(i2c->dev, i2c->wr, 0x00000006, 4 | (state ? 2 : 0)); + i2c->data = state; + } + +-static const uint32_t nv50_i2c_port[] = { +- 0x00e138, 0x00e150, 0x00e168, 0x00e180, +- 0x00e254, 0x00e274, 0x00e764, 0x00e780, +- 0x00e79c, 0x00e7b8 +-}; +-#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port) ++static int ++nvd0_i2c_getscl(void *data) ++{ ++ struct nouveau_i2c_chan *i2c = data; ++ return !!(nv_rd32(i2c->dev, i2c->rd) & 0x10); ++} ++ ++static int ++nvd0_i2c_getsda(void *data) ++{ ++ struct nouveau_i2c_chan *i2c = data; ++ return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20); ++} + + int + nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) +@@ -163,7 +174,8 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) + if (entry->chan) + return -EEXIST; + +- if (dev_priv->card_type >= NV_50 && entry->read >= NV50_I2C_PORTS) { ++ if (dev_priv->card_type >= NV_50 && ++ dev_priv->card_type <= NV_C0 && entry->read >= NV50_I2C_PORTS) { + NV_ERROR(dev, "unknown i2c port %d\n", entry->read); + return -EINVAL; + } +@@ -192,10 +204,17 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) + case 5: + i2c->bit.setsda = nv50_i2c_setsda; + i2c->bit.setscl = nv50_i2c_setscl; +- i2c->bit.getsda = nv50_i2c_getsda; +- i2c->bit.getscl = nv50_i2c_getscl; +- i2c->rd = nv50_i2c_port[entry->read]; +- i2c->wr = i2c->rd; ++ if (dev_priv->card_type < NV_D0) { ++ i2c->bit.getsda = nv50_i2c_getsda; ++ i2c->bit.getscl = nv50_i2c_getscl; ++ i2c->rd = nv50_i2c_port[entry->read]; ++ i2c->wr = i2c->rd; ++ } else { ++ i2c->bit.getsda = nvd0_i2c_getsda; ++ i2c->bit.getscl = nvd0_i2c_getscl; ++ i2c->rd = 0x00d014 + (entry->read * 0x20); ++ i2c->wr = i2c->rd; ++ } + break; + case 6: + i2c->rd = entry->read; +@@ -267,7 +286,10 @@ nouveau_i2c_find(struct drm_device *dev, int index) + val = 0xe001; + } + +- nv_wr32(dev, reg, (nv_rd32(dev, reg) & ~0xf003) | val); ++ /* nfi, but neither auxch or i2c work if it's 1 */ ++ nv_mask(dev, reg + 0x0c, 0x00000001, 0x00000000); ++ /* nfi, but switches auxch vs normal i2c */ ++ nv_mask(dev, reg + 0x00, 0x0000f003, val); + } + + if (!i2c->chan && nouveau_i2c_init(dev, i2c, index)) +diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c +index f9ae2fc..36bec48 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_mem.c ++++ b/drivers/gpu/drm/nouveau/nouveau_mem.c +@@ -408,8 +408,6 @@ nouveau_mem_vram_init(struct drm_device *dev) + if (ret) + return ret; + +- dev_priv->fb_phys = pci_resource_start(dev->pdev, 1); +- + ret = nouveau_ttm_global_init(dev_priv); + if (ret) + return ret; +@@ -504,35 +502,146 @@ nouveau_mem_gart_init(struct drm_device *dev) + return 0; + } + ++/* XXX: For now a dummy. More samples required, possibly even a card ++ * Called from nouveau_perf.c */ ++void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, ++ struct nouveau_pm_tbl_entry *e, uint8_t magic_number, ++ struct nouveau_pm_memtiming *timing) { ++ ++ NV_DEBUG(dev,"Timing entry format unknown, please contact nouveau developers"); ++} ++ ++void nv40_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, ++ struct nouveau_pm_tbl_entry *e, uint8_t magic_number, ++ struct nouveau_pm_memtiming *timing) { ++ ++ timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP); ++ ++ /* XXX: I don't trust the -1's and +1's... they must come ++ * from somewhere! */ ++ timing->reg_1 = (e->tWR + 2 + magic_number) << 24 | ++ 1 << 16 | ++ (e->tUNK_1 + 2 + magic_number) << 8 | ++ (e->tCL + 2 - magic_number); ++ timing->reg_2 = (magic_number << 24 | e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10); ++ timing->reg_2 |= 0x20200000; ++ ++ NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x\n", timing->id, ++ timing->reg_0, timing->reg_1,timing->reg_2); ++} ++ ++void nv50_mem_timing_entry(struct drm_device *dev, struct bit_entry *P, struct nouveau_pm_tbl_header *hdr, ++ struct nouveau_pm_tbl_entry *e, uint8_t magic_number,struct nouveau_pm_memtiming *timing) { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ uint8_t unk18 = 1, ++ unk19 = 1, ++ unk20 = 0, ++ unk21 = 0; ++ ++ switch (min(hdr->entry_len, (u8) 22)) { ++ case 22: ++ unk21 = e->tUNK_21; ++ case 21: ++ unk20 = e->tUNK_20; ++ case 20: ++ unk19 = e->tUNK_19; ++ case 19: ++ unk18 = e->tUNK_18; ++ break; ++ } ++ ++ timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP); ++ ++ /* XXX: I don't trust the -1's and +1's... they must come ++ * from somewhere! */ ++ timing->reg_1 = (e->tWR + unk19 + 1 + magic_number) << 24 | ++ max(unk18, (u8) 1) << 16 | ++ (e->tUNK_1 + unk19 + 1 + magic_number) << 8; ++ if (dev_priv->chipset == 0xa8) { ++ timing->reg_1 |= (e->tCL - 1); ++ } else { ++ timing->reg_1 |= (e->tCL + 2 - magic_number); ++ } ++ timing->reg_2 = (e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10); ++ ++ timing->reg_5 = (e->tRAS << 24 | e->tRC); ++ timing->reg_5 += max(e->tUNK_10, e->tUNK_11) << 16; ++ ++ if (P->version == 1) { ++ timing->reg_2 |= magic_number << 24; ++ timing->reg_3 = (0x14 + e->tCL) << 24 | ++ 0x16 << 16 | ++ (e->tCL - 1) << 8 | ++ (e->tCL - 1); ++ timing->reg_4 = (nv_rd32(dev,0x10022c) & 0xffff0000) | e->tUNK_13 << 8 | e->tUNK_13; ++ timing->reg_5 |= (e->tCL + 2) << 8; ++ timing->reg_7 = 0x4000202 | (e->tCL - 1) << 16; ++ } else { ++ timing->reg_2 |= (unk19 - 1) << 24; ++ /* XXX: reg_10022c for recentish cards pretty much unknown*/ ++ timing->reg_3 = e->tCL - 1; ++ timing->reg_4 = (unk20 << 24 | unk21 << 16 | ++ e->tUNK_13 << 8 | e->tUNK_13); ++ /* XXX: +6? */ ++ timing->reg_5 |= (unk19 + 6) << 8; ++ ++ /* XXX: reg_10023c currently unknown ++ * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */ ++ timing->reg_7 = 0x202; ++ } ++ ++ NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", timing->id, ++ timing->reg_0, timing->reg_1, ++ timing->reg_2, timing->reg_3); ++ NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n", ++ timing->reg_4, timing->reg_5, ++ timing->reg_6, timing->reg_7); ++ NV_DEBUG(dev, " 240: %08x\n", timing->reg_8); ++} ++ ++void nvc0_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, ++ struct nouveau_pm_tbl_entry *e, struct nouveau_pm_memtiming *timing) { ++ timing->reg_0 = (e->tRC << 24 | (e->tRFC & 0x7f) << 17 | e->tRAS << 8 | e->tRP); ++ timing->reg_1 = (nv_rd32(dev,0x10f294) & 0xff000000) | (e->tUNK_11&0x0f) << 20 | (e->tUNK_19 << 7) | (e->tCL & 0x0f); ++ timing->reg_2 = (nv_rd32(dev,0x10f298) & 0xff0000ff) | e->tWR << 16 | e->tUNK_1 << 8; ++ timing->reg_3 = e->tUNK_20 << 9 | e->tUNK_13; ++ timing->reg_4 = (nv_rd32(dev,0x10f2a0) & 0xfff000ff) | e->tUNK_12 << 15; ++ NV_DEBUG(dev, "Entry %d: 290: %08x %08x %08x %08x\n", timing->id, ++ timing->reg_0, timing->reg_1, ++ timing->reg_2, timing->reg_3); ++ NV_DEBUG(dev, " 2a0: %08x %08x %08x %08x\n", ++ timing->reg_4, timing->reg_5, ++ timing->reg_6, timing->reg_7); ++} ++ ++/** ++ * Processes the Memory Timing BIOS table, stores generated ++ * register values ++ * @pre init scripts were run, memtiming regs are initialized ++ */ + void + nouveau_mem_timing_init(struct drm_device *dev) + { +- /* cards < NVC0 only */ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm_memtimings *memtimings = &pm->memtimings; + struct nvbios *bios = &dev_priv->vbios; + struct bit_entry P; +- u8 tUNK_0, tUNK_1, tUNK_2; +- u8 tRP; /* Byte 3 */ +- u8 tRAS; /* Byte 5 */ +- u8 tRFC; /* Byte 7 */ +- 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; ++ struct nouveau_pm_tbl_header *hdr = NULL; ++ uint8_t magic_number; ++ u8 *entry; ++ int i; + + if (bios->type == NVBIOS_BIT) { + if (bit_table(dev, 'P', &P)) + return; + + if (P.version == 1) +- mem = ROMPTR(bios, P.data[4]); ++ hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[4]); + else + if (P.version == 2) +- mem = ROMPTR(bios, P.data[8]); ++ hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[8]); + else { + NV_WARN(dev, "unknown mem for BIT P %d\n", P.version); + } +@@ -541,150 +650,56 @@ nouveau_mem_timing_init(struct drm_device *dev) + return; + } + +- if (!mem) { ++ if (!hdr) { + NV_DEBUG(dev, "memory timing table pointer invalid\n"); + return; + } + +- if (mem[0] != 0x10) { +- NV_WARN(dev, "memory timing table 0x%02x unknown\n", mem[0]); ++ if (hdr->version != 0x10) { ++ NV_WARN(dev, "memory timing table 0x%02x unknown\n", hdr->version); + return; + } + + /* validate record length */ +- entries = mem[2]; +- recordlen = mem[3]; +- if (recordlen < 15) { +- NV_ERROR(dev, "mem timing table length unknown: %d\n", mem[3]); ++ if (hdr->entry_len < 15) { ++ NV_ERROR(dev, "mem timing table length unknown: %d\n", hdr->entry_len); + return; + } + + /* parse vbios entries into common format */ + memtimings->timing = +- kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL); ++ kcalloc(hdr->entry_cnt, sizeof(*memtimings->timing), GFP_KERNEL); + 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) { ++ * Used in calculations later... source unknown */ ++ magic_number = 0; ++ if (P.version == 1) { + magic_number = (nv_rd32(dev, 0x100228) & 0x0f000000) >> 24; + } + +- entry = mem + mem[1]; +- for (i = 0; i < entries; i++, entry += recordlen) { ++ entry = (u8*) hdr + hdr->header_len; ++ for (i = 0; i < hdr->entry_cnt; i++, entry += hdr->entry_len) { + struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i]; + if (entry[0] == 0) + continue; + +- tUNK_18 = 1; +- tUNK_19 = 1; +- tUNK_20 = 0; +- tUNK_21 = 0; +- switch (min(recordlen, 22)) { +- case 22: +- tUNK_21 = entry[21]; +- case 21: +- tUNK_20 = entry[20]; +- case 20: +- tUNK_19 = entry[19]; +- case 19: +- tUNK_18 = entry[18]; +- default: +- tUNK_0 = entry[0]; +- tUNK_1 = entry[1]; +- tUNK_2 = entry[2]; +- tRP = entry[3]; +- tRAS = entry[5]; +- tRFC = entry[7]; +- tRC = entry[9]; +- tUNK_10 = entry[10]; +- tUNK_11 = entry[11]; +- tUNK_12 = entry[12]; +- tUNK_13 = entry[13]; +- tUNK_14 = entry[14]; +- break; +- } +- +- timing->reg_100220 = (tRC << 24 | tRFC << 16 | tRAS << 8 | tRP); +- +- /* XXX: I don't trust the -1's and +1's... they must come +- * from somewhere! */ +- 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 (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? */ +- } + timing->id = i; +- +- NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, +- timing->reg_100220, timing->reg_100224, +- timing->reg_100228, timing->reg_10022c); +- 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); ++ timing->WR = entry[0]; ++ timing->CL = entry[2]; ++ ++ if(dev_priv->card_type <= NV_40) { ++ nv40_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]); ++ } else if(dev_priv->card_type == NV_50){ ++ nv50_mem_timing_entry(dev,&P,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]); ++ } else if(dev_priv->card_type == NV_C0) { ++ nvc0_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,&pm->memtimings.timing[i]); ++ } + } + +- memtimings->nr_timing = entries; +- memtimings->supported = (dev_priv->chipset <= 0x98); ++ memtimings->nr_timing = hdr->entry_cnt; ++ memtimings->supported = P.version == 1; + } + + void +@@ -693,7 +708,10 @@ nouveau_mem_timing_fini(struct drm_device *dev) + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_memtimings *mem = &dev_priv->engine.pm.memtimings; + +- kfree(mem->timing); ++ if(mem->timing) { ++ kfree(mem->timing); ++ mem->timing = NULL; ++ } + } + + static int +diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.c b/drivers/gpu/drm/nouveau/nouveau_mm.c +index 1640dec..b29ffb3 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_mm.c ++++ b/drivers/gpu/drm/nouveau/nouveau_mm.c +@@ -27,7 +27,7 @@ + #include "nouveau_mm.h" + + static inline void +-region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a) ++region_put(struct nouveau_mm *mm, struct nouveau_mm_node *a) + { + list_del(&a->nl_entry); + list_del(&a->fl_entry); +@@ -35,7 +35,7 @@ region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a) + } + + static struct nouveau_mm_node * +-region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size) ++region_split(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) + { + struct nouveau_mm_node *b; + +@@ -57,33 +57,33 @@ region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size) + return b; + } + +-#define node(root, dir) ((root)->nl_entry.dir == &rmm->nodes) ? NULL : \ ++#define node(root, dir) ((root)->nl_entry.dir == &mm->nodes) ? NULL : \ + list_entry((root)->nl_entry.dir, struct nouveau_mm_node, nl_entry) + + void +-nouveau_mm_put(struct nouveau_mm *rmm, struct nouveau_mm_node *this) ++nouveau_mm_put(struct nouveau_mm *mm, struct nouveau_mm_node *this) + { + struct nouveau_mm_node *prev = node(this, prev); + struct nouveau_mm_node *next = node(this, next); + +- list_add(&this->fl_entry, &rmm->free); ++ list_add(&this->fl_entry, &mm->free); + this->type = 0; + + if (prev && prev->type == 0) { + prev->length += this->length; +- region_put(rmm, this); ++ region_put(mm, this); + this = prev; + } + + if (next && next->type == 0) { + next->offset = this->offset; + next->length += this->length; +- region_put(rmm, this); ++ region_put(mm, this); + } + } + + int +-nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, ++nouveau_mm_get(struct nouveau_mm *mm, int type, u32 size, u32 size_nc, + u32 align, struct nouveau_mm_node **pnode) + { + struct nouveau_mm_node *prev, *this, *next; +@@ -92,17 +92,17 @@ nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, + u32 splitoff; + u32 s, e; + +- list_for_each_entry(this, &rmm->free, fl_entry) { ++ list_for_each_entry(this, &mm->free, fl_entry) { + e = this->offset + this->length; + s = this->offset; + + prev = node(this, prev); + if (prev && prev->type != type) +- s = roundup(s, rmm->block_size); ++ s = roundup(s, mm->block_size); + + next = node(this, next); + if (next && next->type != type) +- e = rounddown(e, rmm->block_size); ++ e = rounddown(e, mm->block_size); + + s = (s + align_mask) & ~align_mask; + e &= ~align_mask; +@@ -110,10 +110,10 @@ nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, + continue; + + splitoff = s - this->offset; +- if (splitoff && !region_split(rmm, this, splitoff)) ++ if (splitoff && !region_split(mm, this, splitoff)) + return -ENOMEM; + +- this = region_split(rmm, this, min(size, e - s)); ++ this = region_split(mm, this, min(size, e - s)); + if (!this) + return -ENOMEM; + +@@ -127,52 +127,49 @@ nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, + } + + int +-nouveau_mm_init(struct nouveau_mm **prmm, u32 offset, u32 length, u32 block) ++nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block) + { +- struct nouveau_mm *rmm; +- struct nouveau_mm_node *heap; ++ struct nouveau_mm_node *node; ++ ++ if (block) { ++ mutex_init(&mm->mutex); ++ INIT_LIST_HEAD(&mm->nodes); ++ INIT_LIST_HEAD(&mm->free); ++ mm->block_size = block; ++ mm->heap_nodes = 0; ++ } + +- heap = kzalloc(sizeof(*heap), GFP_KERNEL); +- if (!heap) ++ node = kzalloc(sizeof(*node), GFP_KERNEL); ++ if (!node) + return -ENOMEM; +- heap->offset = roundup(offset, block); +- heap->length = rounddown(offset + length, block) - heap->offset; ++ node->offset = roundup(offset, mm->block_size); ++ node->length = rounddown(offset + length, mm->block_size) - node->offset; + +- rmm = kzalloc(sizeof(*rmm), GFP_KERNEL); +- if (!rmm) { +- kfree(heap); +- return -ENOMEM; +- } +- rmm->block_size = block; +- mutex_init(&rmm->mutex); +- INIT_LIST_HEAD(&rmm->nodes); +- INIT_LIST_HEAD(&rmm->free); +- list_add(&heap->nl_entry, &rmm->nodes); +- list_add(&heap->fl_entry, &rmm->free); +- +- *prmm = rmm; ++ list_add_tail(&node->nl_entry, &mm->nodes); ++ list_add_tail(&node->fl_entry, &mm->free); ++ mm->heap_nodes++; + return 0; + } + + int +-nouveau_mm_fini(struct nouveau_mm **prmm) ++nouveau_mm_fini(struct nouveau_mm *mm) + { +- struct nouveau_mm *rmm = *prmm; + struct nouveau_mm_node *node, *heap = +- list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry); +- +- if (!list_is_singular(&rmm->nodes)) { +- printk(KERN_ERR "nouveau_mm not empty at destroy time!\n"); +- list_for_each_entry(node, &rmm->nodes, nl_entry) { +- printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n", +- node->type, node->offset, node->length); ++ list_first_entry(&mm->nodes, struct nouveau_mm_node, nl_entry); ++ int nodes = 0; ++ ++ list_for_each_entry(node, &mm->nodes, nl_entry) { ++ if (nodes++ == mm->heap_nodes) { ++ printk(KERN_ERR "nouveau_mm in use at destroy time!\n"); ++ list_for_each_entry(node, &mm->nodes, nl_entry) { ++ printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n", ++ node->type, node->offset, node->length); ++ } ++ WARN_ON(1); ++ return -EBUSY; + } +- WARN_ON(1); +- return -EBUSY; + } + + kfree(heap); +- kfree(rmm); +- *prmm = NULL; + return 0; + } +diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.h b/drivers/gpu/drm/nouveau/nouveau_mm.h +index b9c016d..57a600c 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_mm.h ++++ b/drivers/gpu/drm/nouveau/nouveau_mm.h +@@ -42,10 +42,11 @@ struct nouveau_mm { + struct mutex mutex; + + u32 block_size; ++ int heap_nodes; + }; + +-int nouveau_mm_init(struct nouveau_mm **, u32 offset, u32 length, u32 block); +-int nouveau_mm_fini(struct nouveau_mm **); ++int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block); ++int nouveau_mm_fini(struct nouveau_mm *); + int nouveau_mm_pre(struct nouveau_mm *); + int nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc, + u32 align, struct nouveau_mm_node **); +diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c +index 159b7c4..02222c5 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_object.c ++++ b/drivers/gpu/drm/nouveau/nouveau_object.c +@@ -693,6 +693,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) + static int + nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm) + { ++ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct drm_device *dev = chan->dev; + struct nouveau_gpuobj *pgd = NULL; + struct nouveau_vm_pgd *vpgd; +@@ -722,6 +723,9 @@ nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm) + nv_wo32(chan->ramin, 0x020c, 0x000000ff); + + /* map display semaphore buffers into channel's vm */ ++ if (dev_priv->card_type >= NV_D0) ++ return 0; ++ + for (i = 0; i < 2; i++) { + struct nv50_display_crtc *dispc = &nv50_display(dev)->crtc[i]; + +@@ -746,7 +750,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, + int ret, i; + + NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); +- if (dev_priv->card_type == NV_C0) ++ if (dev_priv->card_type >= NV_C0) + return nvc0_gpuobj_channel_init(chan, vm); + + /* Allocate a chunk of memory for per-channel object storage */ +@@ -793,7 +797,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, + return ret; + + /* dma objects for display sync channel semaphore blocks */ +- for (i = 0; i < 2; i++) { ++ for (i = 0; i < dev->mode_config.num_crtc; i++) { + struct nouveau_gpuobj *sem = NULL; + struct nv50_display_crtc *dispc = + &nv50_display(dev)->crtc[i]; +@@ -875,18 +879,18 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) + + NV_DEBUG(dev, "ch%d\n", chan->id); + +- if (dev_priv->card_type >= NV_50) { ++ if (dev_priv->card_type >= NV_50 && dev_priv->card_type <= NV_C0) { + struct nv50_display *disp = nv50_display(dev); + +- for (i = 0; i < 2; i++) { ++ for (i = 0; i < dev->mode_config.num_crtc; i++) { + struct nv50_display_crtc *dispc = &disp->crtc[i]; + nouveau_bo_vma_del(dispc->sem.bo, &chan->dispc_vma[i]); + } +- +- nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); +- nouveau_gpuobj_ref(NULL, &chan->vm_pd); + } + ++ nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); ++ nouveau_gpuobj_ref(NULL, &chan->vm_pd); ++ + if (drm_mm_initialized(&chan->ramin_heap)) + drm_mm_takedown(&chan->ramin_heap); + nouveau_gpuobj_ref(NULL, &chan->ramin); +diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c +index ef9dec0..9f178aa 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_perf.c ++++ b/drivers/gpu/drm/nouveau/nouveau_perf.c +@@ -127,13 +127,57 @@ nouveau_perf_timing(struct drm_device *dev, struct bit_entry *P, + + entry += ramcfg * recordlen; + if (entry[1] >= pm->memtimings.nr_timing) { +- NV_WARN(dev, "timingset %d does not exist\n", entry[1]); ++ if (entry[1] != 0xff) ++ NV_WARN(dev, "timingset %d does not exist\n", entry[1]); + return NULL; + } + + return &pm->memtimings.timing[entry[1]]; + } + ++static void ++nouveau_perf_voltage(struct drm_device *dev, struct bit_entry *P, ++ struct nouveau_pm_level *perflvl) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvbios *bios = &dev_priv->vbios; ++ u8 *vmap; ++ int id; ++ ++ id = perflvl->volt_min; ++ perflvl->volt_min = 0; ++ ++ /* boards using voltage table version <0x40 store the voltage ++ * level directly in the perflvl entry as a multiple of 10mV ++ */ ++ if (dev_priv->engine.pm.voltage.version < 0x40) { ++ perflvl->volt_min = id * 10000; ++ perflvl->volt_max = perflvl->volt_min; ++ return; ++ } ++ ++ /* on newer ones, the perflvl stores an index into yet another ++ * vbios table containing a min/max voltage value for the perflvl ++ */ ++ if (P->version != 2 || P->length < 34) { ++ NV_DEBUG(dev, "where's our volt map table ptr? %d %d\n", ++ P->version, P->length); ++ return; ++ } ++ ++ vmap = ROMPTR(bios, P->data[32]); ++ if (!vmap) { ++ NV_DEBUG(dev, "volt map table pointer invalid\n"); ++ return; ++ } ++ ++ if (id < vmap[3]) { ++ vmap += vmap[1] + (vmap[2] * id); ++ perflvl->volt_min = ROM32(vmap[0]); ++ perflvl->volt_max = ROM32(vmap[4]); ++ } ++} ++ + void + nouveau_perf_init(struct drm_device *dev) + { +@@ -141,6 +185,8 @@ nouveau_perf_init(struct drm_device *dev) + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nvbios *bios = &dev_priv->vbios; + struct bit_entry P; ++ struct nouveau_pm_memtimings *memtimings = &pm->memtimings; ++ struct nouveau_pm_tbl_header mt_hdr; + u8 version, headerlen, recordlen, entries; + u8 *perf, *entry; + int vid, i; +@@ -188,6 +234,22 @@ nouveau_perf_init(struct drm_device *dev) + } + + entry = perf + headerlen; ++ ++ /* For version 0x15, initialize memtiming table */ ++ if(version == 0x15) { ++ memtimings->timing = ++ kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL); ++ if(!memtimings) { ++ NV_WARN(dev,"Could not allocate memtiming table\n"); ++ return; ++ } ++ ++ mt_hdr.entry_cnt = entries; ++ mt_hdr.entry_len = 14; ++ mt_hdr.version = version; ++ mt_hdr.header_len = 4; ++ } ++ + for (i = 0; i < entries; i++) { + struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; + +@@ -203,7 +265,8 @@ nouveau_perf_init(struct drm_device *dev) + case 0x13: + case 0x15: + perflvl->fanspeed = entry[55]; +- perflvl->voltage = (recordlen > 56) ? entry[56] : 0; ++ if (recordlen > 56) ++ perflvl->volt_min = entry[56]; + perflvl->core = ROM32(entry[1]) * 10; + perflvl->memory = ROM32(entry[5]) * 20; + break; +@@ -211,9 +274,10 @@ nouveau_perf_init(struct drm_device *dev) + case 0x23: + case 0x24: + perflvl->fanspeed = entry[4]; +- perflvl->voltage = entry[5]; +- perflvl->core = ROM16(entry[6]) * 1000; +- ++ perflvl->volt_min = entry[5]; ++ perflvl->shader = ROM16(entry[6]) * 1000; ++ perflvl->core = perflvl->shader; ++ perflvl->core += (signed char)entry[8] * 1000; + if (dev_priv->chipset == 0x49 || + dev_priv->chipset == 0x4b) + perflvl->memory = ROM16(entry[11]) * 1000; +@@ -223,7 +287,7 @@ nouveau_perf_init(struct drm_device *dev) + break; + case 0x25: + perflvl->fanspeed = entry[4]; +- perflvl->voltage = entry[5]; ++ perflvl->volt_min = entry[5]; + perflvl->core = ROM16(entry[6]) * 1000; + perflvl->shader = ROM16(entry[10]) * 1000; + perflvl->memory = ROM16(entry[12]) * 1000; +@@ -232,7 +296,7 @@ nouveau_perf_init(struct drm_device *dev) + perflvl->memscript = ROM16(entry[2]); + case 0x35: + perflvl->fanspeed = entry[6]; +- perflvl->voltage = entry[7]; ++ perflvl->volt_min = entry[7]; + perflvl->core = ROM16(entry[8]) * 1000; + perflvl->shader = ROM16(entry[10]) * 1000; + perflvl->memory = ROM16(entry[12]) * 1000; +@@ -240,30 +304,34 @@ nouveau_perf_init(struct drm_device *dev) + perflvl->unk05 = ROM16(entry[16]) * 1000; + break; + case 0x40: +-#define subent(n) entry[perf[2] + ((n) * perf[3])] ++#define subent(n) (ROM16(entry[perf[2] + ((n) * perf[3])]) & 0xfff) * 1000 + perflvl->fanspeed = 0; /*XXX*/ +- perflvl->voltage = entry[2]; ++ perflvl->volt_min = entry[2]; + 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; ++ perflvl->core = subent(0); ++ perflvl->shader = subent(1); ++ perflvl->memory = subent(2); ++ perflvl->vdec = subent(3); ++ perflvl->unka0 = subent(4); + } else { +- perflvl->shader = ROM16(subent(3)) & 0xfff; ++ perflvl->hub06 = subent(0); ++ perflvl->hub01 = subent(1); ++ perflvl->copy = subent(2); ++ perflvl->shader = subent(3); ++ perflvl->rop = subent(4); ++ perflvl->memory = subent(5); ++ perflvl->vdec = subent(6); ++ perflvl->daemon = subent(10); ++ perflvl->hub07 = subent(11); + 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; + } + + /* make sure vid is valid */ +- if (pm->voltage.supported && perflvl->voltage) { +- vid = nouveau_volt_vid_lookup(dev, perflvl->voltage); ++ nouveau_perf_voltage(dev, &P, perflvl); ++ if (pm->voltage.supported && perflvl->volt_min) { ++ vid = nouveau_volt_vid_lookup(dev, perflvl->volt_min); + if (vid < 0) { + NV_DEBUG(dev, "drop perflvl %d, bad vid\n", i); + entry += recordlen; +@@ -272,7 +340,11 @@ nouveau_perf_init(struct drm_device *dev) + } + + /* get the corresponding memory timings */ +- if (version > 0x15) { ++ if (version == 0x15) { ++ memtimings->timing[i].id = i; ++ nv30_mem_timing_entry(dev,&mt_hdr,(struct nouveau_pm_tbl_entry*) &entry[41],0,&memtimings->timing[i]); ++ perflvl->timing = &memtimings->timing[i]; ++ } else if (version > 0x15) { + /* last 3 args are for < 0x40, ignored for >= 0x40 */ + perflvl->timing = + nouveau_perf_timing(dev, &P, +diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c +index da8d994..a539fd2 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_pm.c ++++ b/drivers/gpu/drm/nouveau/nouveau_pm.c +@@ -64,18 +64,26 @@ nouveau_pm_perflvl_set(struct drm_device *dev, struct nouveau_pm_level *perflvl) + if (perflvl == pm->cur) + return 0; + +- if (pm->voltage.supported && pm->voltage_set && perflvl->voltage) { +- ret = pm->voltage_set(dev, perflvl->voltage); ++ if (pm->voltage.supported && pm->voltage_set && perflvl->volt_min) { ++ ret = pm->voltage_set(dev, perflvl->volt_min); + if (ret) { + NV_ERROR(dev, "voltage_set %d failed: %d\n", +- perflvl->voltage, ret); ++ perflvl->volt_min, ret); + } + } + +- nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core); +- nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader); +- nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory); +- nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05); ++ if (pm->clocks_pre) { ++ void *state = pm->clocks_pre(dev, perflvl); ++ if (IS_ERR(state)) ++ return PTR_ERR(state); ++ pm->clocks_set(dev, state); ++ } else ++ if (pm->clock_set) { ++ nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core); ++ nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader); ++ nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory); ++ nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05); ++ } + + pm->cur = perflvl; + return 0; +@@ -92,9 +100,6 @@ nouveau_pm_profile_set(struct drm_device *dev, const char *profile) + if (nouveau_perflvl_wr != 7777) + return -EPERM; + +- if (!pm->clock_set) +- return -EINVAL; +- + if (!strncmp(profile, "boot", 4)) + perflvl = &pm->boot; + else { +@@ -123,31 +128,37 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + int ret; + +- if (!pm->clock_get) +- return -EINVAL; +- + memset(perflvl, 0, sizeof(*perflvl)); + +- ret = pm->clock_get(dev, PLL_CORE); +- if (ret > 0) +- perflvl->core = ret; ++ if (pm->clocks_get) { ++ ret = pm->clocks_get(dev, perflvl); ++ if (ret) ++ return ret; ++ } else ++ if (pm->clock_get) { ++ ret = pm->clock_get(dev, PLL_CORE); ++ if (ret > 0) ++ perflvl->core = ret; + +- ret = pm->clock_get(dev, PLL_MEMORY); +- if (ret > 0) +- perflvl->memory = ret; ++ ret = pm->clock_get(dev, PLL_MEMORY); ++ if (ret > 0) ++ perflvl->memory = ret; + +- ret = pm->clock_get(dev, PLL_SHADER); +- if (ret > 0) +- perflvl->shader = ret; ++ ret = pm->clock_get(dev, PLL_SHADER); ++ if (ret > 0) ++ perflvl->shader = ret; + +- ret = pm->clock_get(dev, PLL_UNK05); +- if (ret > 0) +- perflvl->unk05 = ret; ++ ret = pm->clock_get(dev, PLL_UNK05); ++ if (ret > 0) ++ perflvl->unk05 = ret; ++ } + + if (pm->voltage.supported && pm->voltage_get) { + ret = pm->voltage_get(dev); +- if (ret > 0) +- perflvl->voltage = ret; ++ if (ret > 0) { ++ perflvl->volt_min = ret; ++ perflvl->volt_max = ret; ++ } + } + + return 0; +@@ -156,7 +167,7 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) + static void + nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) + { +- char c[16], s[16], v[16], f[16], t[16]; ++ char c[16], s[16], v[32], f[16], t[16], m[16]; + + c[0] = '\0'; + if (perflvl->core) +@@ -166,9 +177,19 @@ nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) + if (perflvl->shader) + snprintf(s, sizeof(s), " shader %dMHz", perflvl->shader / 1000); + ++ m[0] = '\0'; ++ if (perflvl->memory) ++ snprintf(m, sizeof(m), " memory %dMHz", perflvl->memory / 1000); ++ + v[0] = '\0'; +- if (perflvl->voltage) +- snprintf(v, sizeof(v), " voltage %dmV", perflvl->voltage * 10); ++ if (perflvl->volt_min && perflvl->volt_min != perflvl->volt_max) { ++ snprintf(v, sizeof(v), " voltage %dmV-%dmV", ++ perflvl->volt_min / 1000, perflvl->volt_max / 1000); ++ } else ++ if (perflvl->volt_min) { ++ snprintf(v, sizeof(v), " voltage %dmV", ++ perflvl->volt_min / 1000); ++ } + + f[0] = '\0'; + if (perflvl->fanspeed) +@@ -178,8 +199,7 @@ nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) + if (perflvl->timing) + snprintf(t, sizeof(t), " timing %d", perflvl->timing->id); + +- snprintf(ptr, len, "memory %dMHz%s%s%s%s%s\n", perflvl->memory / 1000, +- c, s, v, f, t); ++ snprintf(ptr, len, "%s%s%s%s%s%s\n", c, s, m, t, v, f); + } + + static ssize_t +@@ -190,7 +210,7 @@ nouveau_pm_get_perflvl_info(struct device *d, + char *ptr = buf; + int len = PAGE_SIZE; + +- snprintf(ptr, len, "%d: ", perflvl->id); ++ snprintf(ptr, len, "%d:", perflvl->id); + ptr += strlen(buf); + len -= strlen(buf); + +@@ -211,9 +231,9 @@ nouveau_pm_get_perflvl(struct device *d, struct device_attribute *a, char *buf) + if (!pm->cur) + snprintf(ptr, len, "setting: boot\n"); + else if (pm->cur == &pm->boot) +- snprintf(ptr, len, "setting: boot\nc: "); ++ snprintf(ptr, len, "setting: boot\nc:"); + else +- snprintf(ptr, len, "setting: static %d\nc: ", pm->cur->id); ++ snprintf(ptr, len, "setting: static %d\nc:", pm->cur->id); + ptr += strlen(buf); + len -= strlen(buf); + +@@ -292,7 +312,7 @@ nouveau_sysfs_fini(struct drm_device *dev) + } + } + +-#ifdef CONFIG_HWMON ++#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) + static ssize_t + nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) + { +@@ -409,7 +429,7 @@ static const struct attribute_group hwmon_attrgroup = { + static int + nouveau_hwmon_init(struct drm_device *dev) + { +-#ifdef CONFIG_HWMON ++#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct device *hwmon_dev; +@@ -442,7 +462,7 @@ nouveau_hwmon_init(struct drm_device *dev) + static void + nouveau_hwmon_fini(struct drm_device *dev) + { +-#ifdef CONFIG_HWMON ++#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + +@@ -488,7 +508,7 @@ nouveau_pm_init(struct drm_device *dev) + NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl); + for (i = 0; i < pm->nr_perflvl; i++) { + nouveau_pm_perflvl_info(&pm->perflvl[i], info, sizeof(info)); +- NV_INFO(dev, "%d: %s", pm->perflvl[i].id, info); ++ NV_INFO(dev, "%d:%s", pm->perflvl[i].id, info); + } + + /* determine current ("boot") performance level */ +@@ -498,7 +518,7 @@ nouveau_pm_init(struct drm_device *dev) + pm->cur = &pm->boot; + + nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info)); +- NV_INFO(dev, "c: %s", info); ++ NV_INFO(dev, "c:%s", info); + } + + /* switch performance levels now if requested */ +diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.h b/drivers/gpu/drm/nouveau/nouveau_pm.h +index 4a9838dd..8ac02cd 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_pm.h ++++ b/drivers/gpu/drm/nouveau/nouveau_pm.h +@@ -52,6 +52,11 @@ void *nv04_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, + u32 id, int khz); + void nv04_pm_clock_set(struct drm_device *, void *); + ++/* nv40_pm.c */ ++int nv40_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); ++void *nv40_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); ++void nv40_pm_clocks_set(struct drm_device *, void *); ++ + /* nv50_pm.c */ + int nv50_pm_clock_get(struct drm_device *, u32 id); + void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, +@@ -59,10 +64,12 @@ void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, + void nv50_pm_clock_set(struct drm_device *, void *); + + /* nva3_pm.c */ +-int nva3_pm_clock_get(struct drm_device *, u32 id); +-void *nva3_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, +- u32 id, int khz); +-void nva3_pm_clock_set(struct drm_device *, void *); ++int nva3_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); ++void *nva3_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); ++void nva3_pm_clocks_set(struct drm_device *, void *); ++ ++/* nvc0_pm.c */ ++int nvc0_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); + + /* nouveau_temp.c */ + void nouveau_temp_init(struct drm_device *dev); +diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h +index f18cdfc..43a96b9 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_reg.h ++++ b/drivers/gpu/drm/nouveau/nouveau_reg.h +@@ -826,9 +826,12 @@ + #define NV50_PDISPLAY_SOR_DPMS_STATE_ACTIVE 0x00030000 + #define NV50_PDISPLAY_SOR_DPMS_STATE_BLANKED 0x00080000 + #define NV50_PDISPLAY_SOR_DPMS_STATE_WAIT 0x10000000 +-#define NV50_PDISPLAY_SOR_BACKLIGHT 0x0061c084 +-#define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000 +-#define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff ++#define NV50_PDISP_SOR_PWM_DIV(i) (0x0061c080 + (i) * 0x800) ++#define NV50_PDISP_SOR_PWM_CTL(i) (0x0061c084 + (i) * 0x800) ++#define NV50_PDISP_SOR_PWM_CTL_NEW 0x80000000 ++#define NVA3_PDISP_SOR_PWM_CTL_UNK 0x40000000 ++#define NV50_PDISP_SOR_PWM_CTL_VAL 0x000007ff ++#define NVA3_PDISP_SOR_PWM_CTL_VAL 0x00ffffff + #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 +@@ -843,7 +846,7 @@ + #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_SCFG(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) +diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c +index 2706cb3..b75258a 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c ++++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c +@@ -12,8 +12,8 @@ struct nouveau_sgdma_be { + struct drm_device *dev; + + dma_addr_t *pages; +- bool *ttm_alloced; + unsigned nr_pages; ++ bool unmap_pages; + + u64 offset; + bool bound; +@@ -26,43 +26,28 @@ nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages, + { + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + struct drm_device *dev = nvbe->dev; ++ int i; + + NV_DEBUG(nvbe->dev, "num_pages = %ld\n", num_pages); + +- if (nvbe->pages) +- return -EINVAL; +- +- nvbe->pages = kmalloc(sizeof(dma_addr_t) * num_pages, GFP_KERNEL); +- if (!nvbe->pages) +- return -ENOMEM; ++ nvbe->pages = dma_addrs; ++ nvbe->nr_pages = num_pages; ++ nvbe->unmap_pages = true; + +- nvbe->ttm_alloced = kmalloc(sizeof(bool) * num_pages, GFP_KERNEL); +- if (!nvbe->ttm_alloced) { +- kfree(nvbe->pages); +- nvbe->pages = NULL; +- return -ENOMEM; ++ /* this code path isn't called and is incorrect anyways */ ++ if (0) { /* dma_addrs[0] != DMA_ERROR_CODE) { */ ++ nvbe->unmap_pages = false; ++ return 0; + } + +- nvbe->nr_pages = 0; +- while (num_pages--) { +- /* this code path isn't called and is incorrect anyways */ +- if (0) { /*dma_addrs[nvbe->nr_pages] != DMA_ERROR_CODE)*/ +- nvbe->pages[nvbe->nr_pages] = +- dma_addrs[nvbe->nr_pages]; +- nvbe->ttm_alloced[nvbe->nr_pages] = true; +- } else { +- nvbe->pages[nvbe->nr_pages] = +- pci_map_page(dev->pdev, pages[nvbe->nr_pages], 0, +- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); +- if (pci_dma_mapping_error(dev->pdev, +- nvbe->pages[nvbe->nr_pages])) { +- be->func->clear(be); +- return -EFAULT; +- } +- nvbe->ttm_alloced[nvbe->nr_pages] = false; ++ for (i = 0; i < num_pages; i++) { ++ nvbe->pages[i] = pci_map_page(dev->pdev, pages[i], 0, ++ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); ++ if (pci_dma_mapping_error(dev->pdev, nvbe->pages[i])) { ++ nvbe->nr_pages = --i; ++ be->func->clear(be); ++ return -EFAULT; + } +- +- nvbe->nr_pages++; + } + + return 0; +@@ -72,25 +57,16 @@ static void + nouveau_sgdma_clear(struct ttm_backend *be) + { + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; +- struct drm_device *dev; +- +- if (nvbe && nvbe->pages) { +- dev = nvbe->dev; +- NV_DEBUG(dev, "\n"); ++ struct drm_device *dev = nvbe->dev; + +- if (nvbe->bound) +- be->func->unbind(be); ++ if (nvbe->bound) ++ be->func->unbind(be); + ++ if (nvbe->unmap_pages) { + while (nvbe->nr_pages--) { +- if (!nvbe->ttm_alloced[nvbe->nr_pages]) +- pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages], ++ pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages], + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + } +- kfree(nvbe->pages); +- kfree(nvbe->ttm_alloced); +- nvbe->pages = NULL; +- nvbe->ttm_alloced = NULL; +- nvbe->nr_pages = 0; + } + } + +diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c +index 10656e4..82478e0 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_state.c ++++ b/drivers/gpu/drm/nouveau/nouveau_state.c +@@ -286,9 +286,9 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->gpio.get = nv10_gpio_get; + engine->gpio.set = nv10_gpio_set; + engine->gpio.irq_enable = NULL; +- engine->pm.clock_get = nv04_pm_clock_get; +- engine->pm.clock_pre = nv04_pm_clock_pre; +- engine->pm.clock_set = nv04_pm_clock_set; ++ engine->pm.clocks_get = nv40_pm_clocks_get; ++ engine->pm.clocks_pre = nv40_pm_clocks_pre; ++ engine->pm.clocks_set = nv40_pm_clocks_set; + engine->pm.voltage_get = nouveau_voltage_gpio_get; + engine->pm.voltage_set = nouveau_voltage_gpio_set; + engine->pm.temp_get = nv40_temp_get; +@@ -299,7 +299,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + case 0x50: + case 0x80: /* gotta love NVIDIA's consistency.. */ + case 0x90: +- case 0xA0: ++ case 0xa0: + engine->instmem.init = nv50_instmem_init; + engine->instmem.takedown = nv50_instmem_takedown; + engine->instmem.suspend = nv50_instmem_suspend; +@@ -359,9 +359,9 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->pm.clock_set = nv50_pm_clock_set; + break; + default: +- engine->pm.clock_get = nva3_pm_clock_get; +- engine->pm.clock_pre = nva3_pm_clock_pre; +- engine->pm.clock_set = nva3_pm_clock_set; ++ engine->pm.clocks_get = nva3_pm_clocks_get; ++ engine->pm.clocks_pre = nva3_pm_clocks_pre; ++ engine->pm.clocks_set = nva3_pm_clocks_set; + break; + } + engine->pm.voltage_get = nouveau_voltage_gpio_get; +@@ -376,7 +376,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->vram.put = nv50_vram_del; + engine->vram.flags_valid = nv50_vram_flags_valid; + break; +- case 0xC0: ++ case 0xc0: + engine->instmem.init = nvc0_instmem_init; + engine->instmem.takedown = nvc0_instmem_takedown; + engine->instmem.suspend = nvc0_instmem_suspend; +@@ -422,12 +422,73 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->vram.put = nv50_vram_del; + engine->vram.flags_valid = nvc0_vram_flags_valid; + engine->pm.temp_get = nv84_temp_get; ++ engine->pm.clocks_get = nvc0_pm_clocks_get; ++ engine->pm.voltage_get = nouveau_voltage_gpio_get; ++ engine->pm.voltage_set = nouveau_voltage_gpio_set; ++ break; ++ case 0xd0: ++ engine->instmem.init = nvc0_instmem_init; ++ engine->instmem.takedown = nvc0_instmem_takedown; ++ engine->instmem.suspend = nvc0_instmem_suspend; ++ engine->instmem.resume = nvc0_instmem_resume; ++ engine->instmem.get = nv50_instmem_get; ++ engine->instmem.put = nv50_instmem_put; ++ engine->instmem.map = nv50_instmem_map; ++ engine->instmem.unmap = nv50_instmem_unmap; ++ engine->instmem.flush = nv84_instmem_flush; ++ engine->mc.init = nv50_mc_init; ++ engine->mc.takedown = nv50_mc_takedown; ++ engine->timer.init = nv04_timer_init; ++ engine->timer.read = nv04_timer_read; ++ engine->timer.takedown = nv04_timer_takedown; ++ engine->fb.init = nvc0_fb_init; ++ engine->fb.takedown = nvc0_fb_takedown; ++ engine->fifo.channels = 128; ++ engine->fifo.init = nvc0_fifo_init; ++ engine->fifo.takedown = nvc0_fifo_takedown; ++ engine->fifo.disable = nvc0_fifo_disable; ++ engine->fifo.enable = nvc0_fifo_enable; ++ engine->fifo.reassign = nvc0_fifo_reassign; ++ engine->fifo.channel_id = nvc0_fifo_channel_id; ++ engine->fifo.create_context = nvc0_fifo_create_context; ++ engine->fifo.destroy_context = nvc0_fifo_destroy_context; ++ engine->fifo.load_context = nvc0_fifo_load_context; ++ engine->fifo.unload_context = nvc0_fifo_unload_context; ++ engine->display.early_init = nouveau_stub_init; ++ engine->display.late_takedown = nouveau_stub_takedown; ++ engine->display.create = nvd0_display_create; ++ engine->display.init = nvd0_display_init; ++ engine->display.destroy = nvd0_display_destroy; ++ engine->gpio.init = nv50_gpio_init; ++ engine->gpio.takedown = nouveau_stub_takedown; ++ engine->gpio.get = nvd0_gpio_get; ++ engine->gpio.set = nvd0_gpio_set; ++ engine->gpio.irq_register = nv50_gpio_irq_register; ++ engine->gpio.irq_unregister = nv50_gpio_irq_unregister; ++ engine->gpio.irq_enable = nv50_gpio_irq_enable; ++ engine->vram.init = nvc0_vram_init; ++ engine->vram.takedown = nv50_vram_fini; ++ engine->vram.get = nvc0_vram_new; ++ engine->vram.put = nv50_vram_del; ++ engine->vram.flags_valid = nvc0_vram_flags_valid; ++ engine->pm.clocks_get = nvc0_pm_clocks_get; ++ engine->pm.voltage_get = nouveau_voltage_gpio_get; ++ engine->pm.voltage_set = nouveau_voltage_gpio_set; + break; + default: + NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); + return 1; + } + ++ /* headless mode */ ++ if (nouveau_modeset == 2) { ++ engine->display.early_init = nouveau_stub_init; ++ engine->display.late_takedown = nouveau_stub_takedown; ++ engine->display.create = nouveau_stub_init; ++ engine->display.init = nouveau_stub_init; ++ engine->display.destroy = nouveau_stub_takedown; ++ } ++ + return 0; + } + +@@ -449,21 +510,6 @@ nouveau_vga_set_decode(void *priv, bool state) + return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; + } + +-static int +-nouveau_card_init_channel(struct drm_device *dev) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- int ret; +- +- ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL, +- NvDmaFB, NvDmaTT); +- if (ret) +- return ret; +- +- mutex_unlock(&dev_priv->channel->mutex); +- return 0; +-} +- + static void nouveau_switcheroo_set_state(struct pci_dev *pdev, + enum vga_switcheroo_state state) + { +@@ -630,8 +676,11 @@ nouveau_card_init(struct drm_device *dev) + break; + } + +- if (dev_priv->card_type == NV_40) +- nv40_mpeg_create(dev); ++ if (dev_priv->card_type == NV_40 || ++ dev_priv->chipset == 0x31 || ++ dev_priv->chipset == 0x34 || ++ dev_priv->chipset == 0x36) ++ nv31_mpeg_create(dev); + else + if (dev_priv->card_type == NV_50 && + (dev_priv->chipset < 0x98 || dev_priv->chipset == 0xa0)) +@@ -651,41 +700,69 @@ nouveau_card_init(struct drm_device *dev) + goto out_engine; + } + +- ret = engine->display.create(dev); ++ ret = nouveau_irq_init(dev); + if (ret) + goto out_fifo; + +- ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1); +- if (ret) +- goto out_vblank; ++ /* initialise general modesetting */ ++ drm_mode_config_init(dev); ++ drm_mode_create_scaling_mode_property(dev); ++ drm_mode_create_dithering_property(dev); ++ dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; ++ dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1); ++ dev->mode_config.min_width = 0; ++ dev->mode_config.min_height = 0; ++ if (dev_priv->card_type < NV_10) { ++ dev->mode_config.max_width = 2048; ++ dev->mode_config.max_height = 2048; ++ } else ++ if (dev_priv->card_type < NV_50) { ++ dev->mode_config.max_width = 4096; ++ dev->mode_config.max_height = 4096; ++ } else { ++ dev->mode_config.max_width = 8192; ++ dev->mode_config.max_height = 8192; ++ } + +- ret = nouveau_irq_init(dev); ++ ret = engine->display.create(dev); + if (ret) +- goto out_vblank; ++ goto out_irq; + +- /* what about PVIDEO/PCRTC/PRAMDAC etc? */ ++ nouveau_backlight_init(dev); + + if (dev_priv->eng[NVOBJ_ENGINE_GR]) { + ret = nouveau_fence_init(dev); + if (ret) +- goto out_irq; ++ goto out_disp; + +- ret = nouveau_card_init_channel(dev); ++ ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL, ++ NvDmaFB, NvDmaTT); + if (ret) + goto out_fence; ++ ++ mutex_unlock(&dev_priv->channel->mutex); ++ } ++ ++ if (dev->mode_config.num_crtc) { ++ ret = drm_vblank_init(dev, dev->mode_config.num_crtc); ++ if (ret) ++ goto out_chan; ++ ++ nouveau_fbcon_init(dev); ++ drm_kms_helper_poll_init(dev); + } + +- nouveau_fbcon_init(dev); +- drm_kms_helper_poll_init(dev); + return 0; + ++out_chan: ++ nouveau_channel_put_unlocked(&dev_priv->channel); + out_fence: + nouveau_fence_fini(dev); ++out_disp: ++ nouveau_backlight_exit(dev); ++ engine->display.destroy(dev); + out_irq: + nouveau_irq_fini(dev); +-out_vblank: +- drm_vblank_cleanup(dev); +- engine->display.destroy(dev); + out_fifo: + if (!dev_priv->noaccel) + engine->fifo.takedown(dev); +@@ -732,15 +809,20 @@ static void nouveau_card_takedown(struct drm_device *dev) + struct nouveau_engine *engine = &dev_priv->engine; + int e; + +- drm_kms_helper_poll_fini(dev); +- nouveau_fbcon_fini(dev); ++ if (dev->mode_config.num_crtc) { ++ drm_kms_helper_poll_fini(dev); ++ nouveau_fbcon_fini(dev); ++ drm_vblank_cleanup(dev); ++ } + + if (dev_priv->channel) { + nouveau_channel_put_unlocked(&dev_priv->channel); + nouveau_fence_fini(dev); + } + ++ nouveau_backlight_exit(dev); + engine->display.destroy(dev); ++ drm_mode_config_cleanup(dev); + + if (!dev_priv->noaccel) { + engine->fifo.takedown(dev); +@@ -774,7 +856,6 @@ static void nouveau_card_takedown(struct drm_device *dev) + engine->vram.takedown(dev); + + nouveau_irq_fini(dev); +- drm_vblank_cleanup(dev); + + nouveau_pm_fini(dev); + nouveau_bios_takedown(dev); +@@ -907,7 +988,7 @@ static int nouveau_remove_conflicting_drivers(struct drm_device *dev) + int nouveau_load(struct drm_device *dev, unsigned long flags) + { + struct drm_nouveau_private *dev_priv; +- uint32_t reg0; ++ uint32_t reg0, strap; + resource_size_t mmio_start_offs; + int ret; + +@@ -951,13 +1032,11 @@ 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) +@@ -987,6 +1066,9 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) + case 0xc0: + dev_priv->card_type = NV_C0; + break; ++ case 0xd0: ++ dev_priv->card_type = NV_D0; ++ break; + default: + NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0); + ret = -EINVAL; +@@ -996,6 +1078,23 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) + NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", + dev_priv->card_type, reg0); + ++ /* determine frequency of timing crystal */ ++ strap = nv_rd32(dev, 0x101000); ++ if ( dev_priv->chipset < 0x17 || ++ (dev_priv->chipset >= 0x20 && dev_priv->chipset <= 0x25)) ++ strap &= 0x00000040; ++ else ++ strap &= 0x00400040; ++ ++ switch (strap) { ++ case 0x00000000: dev_priv->crystal = 13500; break; ++ case 0x00000040: dev_priv->crystal = 14318; break; ++ case 0x00400000: dev_priv->crystal = 27000; break; ++ case 0x00400040: dev_priv->crystal = 25000; break; ++ } ++ ++ NV_DEBUG(dev, "crystal freq: %dKHz\n", dev_priv->crystal); ++ + /* Determine whether we'll attempt acceleration or not, some + * cards are disabled by default here due to them being known + * non-functional, or never been tested due to lack of hw. +@@ -1030,7 +1129,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) + ioremap(pci_resource_start(dev->pdev, ramin_bar), + dev_priv->ramin_size); + if (!dev_priv->ramin) { +- NV_ERROR(dev, "Failed to PRAMIN BAR"); ++ NV_ERROR(dev, "Failed to map PRAMIN BAR\n"); + ret = -ENOMEM; + goto err_mmio; + } +@@ -1130,7 +1229,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, + getparam->value = 1; + break; + case NOUVEAU_GETPARAM_HAS_PAGEFLIP: +- getparam->value = 1; ++ getparam->value = dev_priv->card_type < NV_D0; + break; + case NOUVEAU_GETPARAM_GRAPH_UNITS: + /* NV40 and NV50 versions are quite different, but register +@@ -1198,6 +1297,23 @@ nouveau_wait_ne(struct drm_device *dev, uint64_t timeout, + return false; + } + ++/* Wait until cond(data) == true, up until timeout has hit */ ++bool ++nouveau_wait_cb(struct drm_device *dev, u64 timeout, ++ bool (*cond)(void *), void *data) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; ++ u64 start = ptimer->read(dev); ++ ++ do { ++ if (cond(data) == true) ++ return true; ++ } while (ptimer->read(dev) - start < timeout); ++ ++ return false; ++} ++ + /* Waits for PGRAPH to go completely idle */ + bool nouveau_wait_for_idle(struct drm_device *dev) + { +diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c +index 244fd38..ef0832b 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_vm.c ++++ b/drivers/gpu/drm/nouveau/nouveau_vm.c +@@ -172,9 +172,9 @@ nouveau_vm_unmap_pgt(struct nouveau_vm *vm, int big, u32 fpde, u32 lpde) + vm->map_pgt(vpgd->obj, pde, vpgt->obj); + } + +- mutex_unlock(&vm->mm->mutex); ++ mutex_unlock(&vm->mm.mutex); + nouveau_gpuobj_ref(NULL, &pgt); +- mutex_lock(&vm->mm->mutex); ++ mutex_lock(&vm->mm.mutex); + } + } + +@@ -191,18 +191,18 @@ nouveau_vm_map_pgt(struct nouveau_vm *vm, u32 pde, u32 type) + pgt_size = (1 << (vm->pgt_bits + 12)) >> type; + pgt_size *= 8; + +- mutex_unlock(&vm->mm->mutex); ++ mutex_unlock(&vm->mm.mutex); + ret = nouveau_gpuobj_new(vm->dev, NULL, pgt_size, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &pgt); +- mutex_lock(&vm->mm->mutex); ++ mutex_lock(&vm->mm.mutex); + if (unlikely(ret)) + return ret; + + /* someone beat us to filling the PDE while we didn't have the lock */ + if (unlikely(vpgt->refcount[big]++)) { +- mutex_unlock(&vm->mm->mutex); ++ mutex_unlock(&vm->mm.mutex); + nouveau_gpuobj_ref(NULL, &pgt); +- mutex_lock(&vm->mm->mutex); ++ mutex_lock(&vm->mm.mutex); + return 0; + } + +@@ -223,10 +223,10 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, + u32 fpde, lpde, pde; + int ret; + +- mutex_lock(&vm->mm->mutex); +- ret = nouveau_mm_get(vm->mm, page_shift, msize, 0, align, &vma->node); ++ mutex_lock(&vm->mm.mutex); ++ ret = nouveau_mm_get(&vm->mm, page_shift, msize, 0, align, &vma->node); + if (unlikely(ret != 0)) { +- mutex_unlock(&vm->mm->mutex); ++ mutex_unlock(&vm->mm.mutex); + return ret; + } + +@@ -245,13 +245,13 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, + if (ret) { + if (pde != fpde) + nouveau_vm_unmap_pgt(vm, big, fpde, pde - 1); +- nouveau_mm_put(vm->mm, vma->node); +- mutex_unlock(&vm->mm->mutex); ++ nouveau_mm_put(&vm->mm, vma->node); ++ mutex_unlock(&vm->mm.mutex); + vma->node = NULL; + return ret; + } + } +- mutex_unlock(&vm->mm->mutex); ++ mutex_unlock(&vm->mm.mutex); + + vma->vm = vm; + vma->offset = (u64)vma->node->offset << 12; +@@ -270,11 +270,11 @@ nouveau_vm_put(struct nouveau_vma *vma) + fpde = (vma->node->offset >> vm->pgt_bits); + lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits; + +- mutex_lock(&vm->mm->mutex); ++ mutex_lock(&vm->mm.mutex); + nouveau_vm_unmap_pgt(vm, vma->node->type != vm->spg_shift, fpde, lpde); +- nouveau_mm_put(vm->mm, vma->node); ++ nouveau_mm_put(&vm->mm, vma->node); + vma->node = NULL; +- mutex_unlock(&vm->mm->mutex); ++ mutex_unlock(&vm->mm.mutex); + } + + int +@@ -306,7 +306,7 @@ nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset, + block = length; + + } else +- if (dev_priv->card_type == NV_C0) { ++ if (dev_priv->card_type >= NV_C0) { + vm->map_pgt = nvc0_vm_map_pgt; + vm->map = nvc0_vm_map; + vm->map_sg = nvc0_vm_map_sg; +@@ -360,11 +360,11 @@ nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd) + + nouveau_gpuobj_ref(pgd, &vpgd->obj); + +- mutex_lock(&vm->mm->mutex); ++ mutex_lock(&vm->mm.mutex); + for (i = vm->fpde; i <= vm->lpde; i++) + vm->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj); + list_add(&vpgd->head, &vm->pgd_list); +- mutex_unlock(&vm->mm->mutex); ++ mutex_unlock(&vm->mm.mutex); + return 0; + } + +@@ -377,7 +377,7 @@ nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd) + if (!mpgd) + return; + +- mutex_lock(&vm->mm->mutex); ++ mutex_lock(&vm->mm.mutex); + list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { + if (vpgd->obj == mpgd) { + pgd = vpgd->obj; +@@ -386,7 +386,7 @@ nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd) + break; + } + } +- mutex_unlock(&vm->mm->mutex); ++ mutex_unlock(&vm->mm.mutex); + + nouveau_gpuobj_ref(NULL, &pgd); + } +diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h +index 579ca8c..6ce995f 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_vm.h ++++ b/drivers/gpu/drm/nouveau/nouveau_vm.h +@@ -51,7 +51,7 @@ struct nouveau_vma { + + struct nouveau_vm { + struct drm_device *dev; +- struct nouveau_mm *mm; ++ struct nouveau_mm mm; + int refcount; + + struct list_head pgd_list; +diff --git a/drivers/gpu/drm/nouveau/nouveau_volt.c b/drivers/gpu/drm/nouveau/nouveau_volt.c +index 75e87274..86d03e1 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_volt.c ++++ b/drivers/gpu/drm/nouveau/nouveau_volt.c +@@ -27,7 +27,7 @@ + #include "nouveau_drv.h" + #include "nouveau_pm.h" + +-static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a }; ++static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 }; + static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]); + + int +@@ -170,6 +170,13 @@ nouveau_volt_init(struct drm_device *dev) + */ + vidshift = 2; + break; ++ case 0x40: ++ headerlen = volt[1]; ++ recordlen = volt[2]; ++ entries = volt[3]; /* not a clue what the entries are for.. */ ++ vidmask = volt[11]; /* guess.. */ ++ vidshift = 0; ++ break; + default: + NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]); + return; +@@ -197,16 +204,37 @@ nouveau_volt_init(struct drm_device *dev) + } + + /* parse vbios entries into common format */ +- voltage->level = kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL); +- if (!voltage->level) +- return; ++ voltage->version = volt[0]; ++ if (voltage->version < 0x40) { ++ voltage->nr_level = entries; ++ voltage->level = ++ kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL); ++ if (!voltage->level) ++ return; + +- entry = volt + headerlen; +- for (i = 0; i < entries; i++, entry += recordlen) { +- voltage->level[i].voltage = entry[0]; +- voltage->level[i].vid = entry[1] >> vidshift; ++ entry = volt + headerlen; ++ for (i = 0; i < entries; i++, entry += recordlen) { ++ voltage->level[i].voltage = entry[0] * 10000; ++ voltage->level[i].vid = entry[1] >> vidshift; ++ } ++ } else { ++ u32 volt_uv = ROM32(volt[4]); ++ s16 step_uv = ROM16(volt[8]); ++ u8 vid; ++ ++ voltage->nr_level = voltage->vid_mask + 1; ++ voltage->level = kcalloc(voltage->nr_level, ++ sizeof(*voltage->level), GFP_KERNEL); ++ if (!voltage->level) ++ return; ++ ++ for (vid = 0; vid <= voltage->vid_mask; vid++) { ++ voltage->level[vid].voltage = volt_uv; ++ voltage->level[vid].vid = vid; ++ volt_uv += step_uv; ++ } + } +- voltage->nr_level = entries; ++ + voltage->supported = true; + } + +diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c +index 1715e14..6bd8518 100644 +--- a/drivers/gpu/drm/nouveau/nv04_display.c ++++ b/drivers/gpu/drm/nouveau/nv04_display.c +@@ -126,27 +126,6 @@ nv04_display_create(struct drm_device *dev) + + nouveau_hw_save_vga_fonts(dev, 1); + +- drm_mode_config_init(dev); +- drm_mode_create_scaling_mode_property(dev); +- drm_mode_create_dithering_property(dev); +- +- dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; +- +- dev->mode_config.min_width = 0; +- dev->mode_config.min_height = 0; +- switch (dev_priv->card_type) { +- case NV_04: +- dev->mode_config.max_width = 2048; +- dev->mode_config.max_height = 2048; +- break; +- default: +- dev->mode_config.max_width = 4096; +- dev->mode_config.max_height = 4096; +- break; +- } +- +- dev->mode_config.fb_base = dev_priv->fb_phys; +- + nv04_crtc_create(dev, 0); + if (nv_two_heads(dev)) + nv04_crtc_create(dev, 1); +@@ -235,8 +214,6 @@ nv04_display_destroy(struct drm_device *dev) + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + crtc->funcs->restore(crtc); + +- drm_mode_config_cleanup(dev); +- + nouveau_hw_save_vga_fonts(dev, 0); + } + +diff --git a/drivers/gpu/drm/nouveau/nv04_pm.c b/drivers/gpu/drm/nouveau/nv04_pm.c +index eb1c70d..9ae92a8 100644 +--- a/drivers/gpu/drm/nouveau/nv04_pm.c ++++ b/drivers/gpu/drm/nouveau/nv04_pm.c +@@ -68,6 +68,7 @@ void + nv04_pm_clock_set(struct drm_device *dev, void *pre_state) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; + struct nv04_pm_state *state = pre_state; + u32 reg = state->pll.reg; + +@@ -85,6 +86,9 @@ nv04_pm_clock_set(struct drm_device *dev, void *pre_state) + nv_mask(dev, 0x1002c0, 0, 1 << 8); + } + ++ if (reg == NV_PRAMDAC_NVPLL_COEFF) ++ ptimer->init(dev); ++ + kfree(state); + } + +diff --git a/drivers/gpu/drm/nouveau/nv04_timer.c b/drivers/gpu/drm/nouveau/nv04_timer.c +index 1d09ddd..263301b 100644 +--- a/drivers/gpu/drm/nouveau/nv04_timer.c ++++ b/drivers/gpu/drm/nouveau/nv04_timer.c +@@ -6,43 +6,75 @@ + int + nv04_timer_init(struct drm_device *dev) + { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 m, n, d; ++ + nv_wr32(dev, NV04_PTIMER_INTR_EN_0, 0x00000000); + nv_wr32(dev, NV04_PTIMER_INTR_0, 0xFFFFFFFF); + +- /* Just use the pre-existing values when possible for now; these regs +- * are not written in nv (driver writer missed a /4 on the address), and +- * writing 8 and 3 to the correct regs breaks the timings on the LVDS +- * hardware sequencing microcode. +- * A correct solution (involving calculations with the GPU PLL) can +- * be done when kernel modesetting lands +- */ +- if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) || +- !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) { +- nv_wr32(dev, NV04_PTIMER_NUMERATOR, 0x00000008); +- nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 0x00000003); ++ /* aim for 31.25MHz, which gives us nanosecond timestamps */ ++ d = 1000000 / 32; ++ ++ /* determine base clock for timer source */ ++ if (dev_priv->chipset < 0x40) { ++ n = dev_priv->engine.pm.clock_get(dev, PLL_CORE); ++ } else ++ if (dev_priv->chipset == 0x40) { ++ /*XXX: figure this out */ ++ n = 0; ++ } else { ++ n = dev_priv->crystal; ++ m = 1; ++ while (n < (d * 2)) { ++ n += (n / m); ++ m++; ++ } ++ ++ nv_wr32(dev, 0x009220, m - 1); ++ } ++ ++ if (!n) { ++ NV_WARN(dev, "PTIMER: unknown input clock freq\n"); ++ if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) || ++ !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) { ++ nv_wr32(dev, NV04_PTIMER_NUMERATOR, 1); ++ nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 1); ++ } ++ return 0; ++ } ++ ++ /* reduce ratio to acceptable values */ ++ while (((n % 5) == 0) && ((d % 5) == 0)) { ++ n /= 5; ++ d /= 5; + } + ++ while (((n % 2) == 0) && ((d % 2) == 0)) { ++ n /= 2; ++ d /= 2; ++ } ++ ++ while (n > 0xffff || d > 0xffff) { ++ n >>= 1; ++ d >>= 1; ++ } ++ ++ nv_wr32(dev, NV04_PTIMER_NUMERATOR, n); ++ nv_wr32(dev, NV04_PTIMER_DENOMINATOR, d); + return 0; + } + +-uint64_t ++u64 + nv04_timer_read(struct drm_device *dev) + { +- uint32_t low; +- /* From kmmio dumps on nv28 this looks like how the blob does this. +- * It reads the high dword twice, before and after. +- * The only explanation seems to be that the 64-bit timer counter +- * advances between high and low dword reads and may corrupt the +- * result. Not confirmed. +- */ +- uint32_t high2 = nv_rd32(dev, NV04_PTIMER_TIME_1); +- uint32_t high1; ++ u32 hi, lo; ++ + do { +- high1 = high2; +- low = nv_rd32(dev, NV04_PTIMER_TIME_0); +- high2 = nv_rd32(dev, NV04_PTIMER_TIME_1); +- } while (high1 != high2); +- return (((uint64_t)high2) << 32) | (uint64_t)low; ++ hi = nv_rd32(dev, NV04_PTIMER_TIME_1); ++ lo = nv_rd32(dev, NV04_PTIMER_TIME_0); ++ } while (hi != nv_rd32(dev, NV04_PTIMER_TIME_1)); ++ ++ return ((u64)hi << 32 | lo); + } + + void +diff --git a/drivers/gpu/drm/nouveau/nv31_mpeg.c b/drivers/gpu/drm/nouveau/nv31_mpeg.c +new file mode 100644 +index 0000000..6f06a07 +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nv31_mpeg.c +@@ -0,0 +1,344 @@ ++/* ++ * 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"), ++ * 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 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) OR AUTHOR(S) 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: Ben Skeggs ++ */ ++ ++#include "drmP.h" ++#include "nouveau_drv.h" ++#include "nouveau_ramht.h" ++ ++struct nv31_mpeg_engine { ++ struct nouveau_exec_engine base; ++ atomic_t refcount; ++}; ++ ++ ++static int ++nv31_mpeg_context_new(struct nouveau_channel *chan, int engine) ++{ ++ struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); ++ ++ if (!atomic_add_unless(&pmpeg->refcount, 1, 1)) ++ return -EBUSY; ++ ++ chan->engctx[engine] = (void *)0xdeadcafe; ++ return 0; ++} ++ ++static void ++nv31_mpeg_context_del(struct nouveau_channel *chan, int engine) ++{ ++ struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); ++ atomic_dec(&pmpeg->refcount); ++ chan->engctx[engine] = NULL; ++} ++ ++static int ++nv40_mpeg_context_new(struct nouveau_channel *chan, int engine) ++{ ++ struct drm_device *dev = chan->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpuobj *ctx = NULL; ++ unsigned long flags; ++ int ret; ++ ++ NV_DEBUG(dev, "ch%d\n", chan->id); ++ ++ ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC | ++ NVOBJ_FLAG_ZERO_FREE, &ctx); ++ if (ret) ++ return ret; ++ ++ nv_wo32(ctx, 0x78, 0x02001ec1); ++ ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ nv_mask(dev, 0x002500, 0x00000001, 0x00000000); ++ if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id) ++ nv_wr32(dev, 0x00330c, ctx->pinst >> 4); ++ nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4); ++ nv_mask(dev, 0x002500, 0x00000001, 0x00000001); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); ++ ++ chan->engctx[engine] = ctx; ++ return 0; ++} ++ ++static void ++nv40_mpeg_context_del(struct nouveau_channel *chan, int engine) ++{ ++ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; ++ struct nouveau_gpuobj *ctx = chan->engctx[engine]; ++ struct drm_device *dev = chan->dev; ++ unsigned long flags; ++ u32 inst = 0x80000000 | (ctx->pinst >> 4); ++ ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); ++ if (nv_rd32(dev, 0x00b318) == inst) ++ nv_mask(dev, 0x00b318, 0x80000000, 0x00000000); ++ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); ++ ++ nouveau_gpuobj_ref(NULL, &ctx); ++ chan->engctx[engine] = NULL; ++} ++ ++static int ++nv31_mpeg_object_new(struct nouveau_channel *chan, int engine, ++ u32 handle, u16 class) ++{ ++ struct drm_device *dev = chan->dev; ++ struct nouveau_gpuobj *obj = NULL; ++ int ret; ++ ++ ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC | ++ NVOBJ_FLAG_ZERO_FREE, &obj); ++ if (ret) ++ return ret; ++ obj->engine = 2; ++ obj->class = class; ++ ++ nv_wo32(obj, 0x00, class); ++ ++ ret = nouveau_ramht_insert(chan, handle, obj); ++ nouveau_gpuobj_ref(NULL, &obj); ++ return ret; ++} ++ ++static int ++nv31_mpeg_init(struct drm_device *dev, int engine) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); ++ int i; ++ ++ /* VPE init */ ++ nv_mask(dev, 0x000200, 0x00000002, 0x00000000); ++ nv_mask(dev, 0x000200, 0x00000002, 0x00000002); ++ nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ ++ nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ ++ ++ for (i = 0; i < dev_priv->engine.fb.num_tiles; i++) ++ pmpeg->base.set_tile_region(dev, i); ++ ++ /* PMPEG init */ ++ nv_wr32(dev, 0x00b32c, 0x00000000); ++ nv_wr32(dev, 0x00b314, 0x00000100); ++ nv_wr32(dev, 0x00b220, nv44_graph_class(dev) ? 0x00000044 : 0x00000031); ++ nv_wr32(dev, 0x00b300, 0x02001ec1); ++ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); ++ ++ nv_wr32(dev, 0x00b100, 0xffffffff); ++ nv_wr32(dev, 0x00b140, 0xffffffff); ++ ++ if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) { ++ NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200)); ++ return -EBUSY; ++ } ++ ++ return 0; ++} ++ ++static int ++nv31_mpeg_fini(struct drm_device *dev, int engine, bool suspend) ++{ ++ /*XXX: context save? */ ++ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); ++ nv_wr32(dev, 0x00b140, 0x00000000); ++ return 0; ++} ++ ++static int ++nv31_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) ++{ ++ struct drm_device *dev = chan->dev; ++ u32 inst = data << 4; ++ u32 dma0 = nv_ri32(dev, inst + 0); ++ u32 dma1 = nv_ri32(dev, inst + 4); ++ u32 dma2 = nv_ri32(dev, inst + 8); ++ u32 base = (dma2 & 0xfffff000) | (dma0 >> 20); ++ u32 size = dma1 + 1; ++ ++ /* only allow linear DMA objects */ ++ if (!(dma0 & 0x00002000)) ++ return -EINVAL; ++ ++ if (mthd == 0x0190) { ++ /* DMA_CMD */ ++ nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000)); ++ nv_wr32(dev, 0x00b334, base); ++ nv_wr32(dev, 0x00b324, size); ++ } else ++ if (mthd == 0x01a0) { ++ /* DMA_DATA */ ++ nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); ++ nv_wr32(dev, 0x00b360, base); ++ nv_wr32(dev, 0x00b364, size); ++ } else { ++ /* DMA_IMAGE, VRAM only */ ++ if (dma0 & 0x000c0000) ++ return -EINVAL; ++ ++ nv_wr32(dev, 0x00b370, base); ++ nv_wr32(dev, 0x00b374, size); ++ } ++ ++ return 0; ++} ++ ++static int ++nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpuobj *ctx; ++ unsigned long flags; ++ int i; ++ ++ /* hardcode drm channel id on nv3x, so swmthd lookup works */ ++ if (dev_priv->card_type < NV_40) ++ return 0; ++ ++ spin_lock_irqsave(&dev_priv->channels.lock, flags); ++ for (i = 0; i < dev_priv->engine.fifo.channels; i++) { ++ if (!dev_priv->channels.ptr[i]) ++ continue; ++ ++ ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG]; ++ if (ctx && ctx->pinst == inst) ++ break; ++ } ++ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); ++ return i; ++} ++ ++static void ++nv31_vpe_set_tile_region(struct drm_device *dev, int i) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; ++ ++ nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch); ++ nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit); ++ nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr); ++} ++ ++static void ++nv31_mpeg_isr(struct drm_device *dev) ++{ ++ u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4; ++ u32 chid = nv31_mpeg_isr_chid(dev, inst); ++ u32 stat = nv_rd32(dev, 0x00b100); ++ u32 type = nv_rd32(dev, 0x00b230); ++ u32 mthd = nv_rd32(dev, 0x00b234); ++ u32 data = nv_rd32(dev, 0x00b238); ++ u32 show = stat; ++ ++ if (stat & 0x01000000) { ++ /* happens on initial binding of the object */ ++ if (type == 0x00000020 && mthd == 0x0000) { ++ nv_mask(dev, 0x00b308, 0x00000000, 0x00000000); ++ show &= ~0x01000000; ++ } ++ ++ if (type == 0x00000010) { ++ if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data)) ++ show &= ~0x01000000; ++ } ++ } ++ ++ nv_wr32(dev, 0x00b100, stat); ++ nv_wr32(dev, 0x00b230, 0x00000001); ++ ++ if (show && nouveau_ratelimit()) { ++ NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", ++ chid, inst, stat, type, mthd, data); ++ } ++} ++ ++static void ++nv31_vpe_isr(struct drm_device *dev) ++{ ++ if (nv_rd32(dev, 0x00b100)) ++ nv31_mpeg_isr(dev); ++ ++ if (nv_rd32(dev, 0x00b800)) { ++ u32 stat = nv_rd32(dev, 0x00b800); ++ NV_INFO(dev, "PMSRCH: 0x%08x\n", stat); ++ nv_wr32(dev, 0xb800, stat); ++ } ++} ++ ++static void ++nv31_mpeg_destroy(struct drm_device *dev, int engine) ++{ ++ struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); ++ ++ nouveau_irq_unregister(dev, 0); ++ ++ NVOBJ_ENGINE_DEL(dev, MPEG); ++ kfree(pmpeg); ++} ++ ++int ++nv31_mpeg_create(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv31_mpeg_engine *pmpeg; ++ ++ pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); ++ if (!pmpeg) ++ return -ENOMEM; ++ atomic_set(&pmpeg->refcount, 0); ++ ++ pmpeg->base.destroy = nv31_mpeg_destroy; ++ pmpeg->base.init = nv31_mpeg_init; ++ pmpeg->base.fini = nv31_mpeg_fini; ++ if (dev_priv->card_type < NV_40) { ++ pmpeg->base.context_new = nv31_mpeg_context_new; ++ pmpeg->base.context_del = nv31_mpeg_context_del; ++ } else { ++ pmpeg->base.context_new = nv40_mpeg_context_new; ++ pmpeg->base.context_del = nv40_mpeg_context_del; ++ } ++ pmpeg->base.object_new = nv31_mpeg_object_new; ++ ++ /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between ++ * all VPE engines, for this driver's purposes the PMPEG engine ++ * will be treated as the "master" and handle the global VPE ++ * bits too ++ */ ++ pmpeg->base.set_tile_region = nv31_vpe_set_tile_region; ++ nouveau_irq_register(dev, 0, nv31_vpe_isr); ++ ++ NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); ++ NVOBJ_CLASS(dev, 0x3174, MPEG); ++ NVOBJ_MTHD (dev, 0x3174, 0x0190, nv31_mpeg_mthd_dma); ++ NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv31_mpeg_mthd_dma); ++ NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv31_mpeg_mthd_dma); ++ ++#if 0 ++ NVOBJ_ENGINE_ADD(dev, ME, &pme->base); ++ NVOBJ_CLASS(dev, 0x4075, ME); ++#endif ++ return 0; ++ ++} +diff --git a/drivers/gpu/drm/nouveau/nv40_mpeg.c b/drivers/gpu/drm/nouveau/nv40_mpeg.c +deleted file mode 100644 +index ad03a0e..0000000 +--- a/drivers/gpu/drm/nouveau/nv40_mpeg.c ++++ /dev/null +@@ -1,311 +0,0 @@ +-/* +- * 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"), +- * 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 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) OR AUTHOR(S) 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: Ben Skeggs +- */ +- +-#include "drmP.h" +-#include "nouveau_drv.h" +-#include "nouveau_ramht.h" +- +-struct nv40_mpeg_engine { +- struct nouveau_exec_engine base; +-}; +- +-static int +-nv40_mpeg_context_new(struct nouveau_channel *chan, int engine) +-{ +- struct drm_device *dev = chan->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpuobj *ctx = NULL; +- unsigned long flags; +- int ret; +- +- NV_DEBUG(dev, "ch%d\n", chan->id); +- +- ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC | +- NVOBJ_FLAG_ZERO_FREE, &ctx); +- if (ret) +- return ret; +- +- nv_wo32(ctx, 0x78, 0x02001ec1); +- +- spin_lock_irqsave(&dev_priv->context_switch_lock, flags); +- nv_mask(dev, 0x002500, 0x00000001, 0x00000000); +- if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id) +- nv_wr32(dev, 0x00330c, ctx->pinst >> 4); +- nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4); +- nv_mask(dev, 0x002500, 0x00000001, 0x00000001); +- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +- +- chan->engctx[engine] = ctx; +- return 0; +-} +- +-static void +-nv40_mpeg_context_del(struct nouveau_channel *chan, int engine) +-{ +- struct drm_nouveau_private *dev_priv = chan->dev->dev_private; +- struct nouveau_gpuobj *ctx = chan->engctx[engine]; +- struct drm_device *dev = chan->dev; +- unsigned long flags; +- u32 inst = 0x80000000 | (ctx->pinst >> 4); +- +- spin_lock_irqsave(&dev_priv->context_switch_lock, flags); +- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); +- if (nv_rd32(dev, 0x00b318) == inst) +- nv_mask(dev, 0x00b318, 0x80000000, 0x00000000); +- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); +- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +- +- nouveau_gpuobj_ref(NULL, &ctx); +- chan->engctx[engine] = NULL; +-} +- +-static int +-nv40_mpeg_object_new(struct nouveau_channel *chan, int engine, +- u32 handle, u16 class) +-{ +- struct drm_device *dev = chan->dev; +- struct nouveau_gpuobj *obj = NULL; +- int ret; +- +- ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC | +- NVOBJ_FLAG_ZERO_FREE, &obj); +- if (ret) +- return ret; +- obj->engine = 2; +- obj->class = class; +- +- nv_wo32(obj, 0x00, class); +- +- ret = nouveau_ramht_insert(chan, handle, obj); +- nouveau_gpuobj_ref(NULL, &obj); +- return ret; +-} +- +-static int +-nv40_mpeg_init(struct drm_device *dev, int engine) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine); +- int i; +- +- /* VPE init */ +- nv_mask(dev, 0x000200, 0x00000002, 0x00000000); +- nv_mask(dev, 0x000200, 0x00000002, 0x00000002); +- nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ +- nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ +- +- for (i = 0; i < dev_priv->engine.fb.num_tiles; i++) +- pmpeg->base.set_tile_region(dev, i); +- +- /* PMPEG init */ +- nv_wr32(dev, 0x00b32c, 0x00000000); +- nv_wr32(dev, 0x00b314, 0x00000100); +- nv_wr32(dev, 0x00b220, 0x00000044); +- nv_wr32(dev, 0x00b300, 0x02001ec1); +- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); +- +- nv_wr32(dev, 0x00b100, 0xffffffff); +- nv_wr32(dev, 0x00b140, 0xffffffff); +- +- if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) { +- NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200)); - return -EBUSY; - } - @@ -286,175 +4972,3565 @@ index 5beb01b..ba14a93 100644 -} - -static int --nv40_graph_unload_context(struct drm_device *dev) +-nv40_mpeg_fini(struct drm_device *dev, int engine, bool suspend) +-{ +- /*XXX: context save? */ +- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); +- nv_wr32(dev, 0x00b140, 0x00000000); +- return 0; +-} +- +-static int +-nv40_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) +-{ +- struct drm_device *dev = chan->dev; +- u32 inst = data << 4; +- u32 dma0 = nv_ri32(dev, inst + 0); +- u32 dma1 = nv_ri32(dev, inst + 4); +- u32 dma2 = nv_ri32(dev, inst + 8); +- u32 base = (dma2 & 0xfffff000) | (dma0 >> 20); +- u32 size = dma1 + 1; +- +- /* only allow linear DMA objects */ +- if (!(dma0 & 0x00002000)) +- return -EINVAL; +- +- if (mthd == 0x0190) { +- /* DMA_CMD */ +- nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000)); +- nv_wr32(dev, 0x00b334, base); +- nv_wr32(dev, 0x00b324, size); +- } else +- if (mthd == 0x01a0) { +- /* DMA_DATA */ +- nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); +- nv_wr32(dev, 0x00b360, base); +- nv_wr32(dev, 0x00b364, size); +- } else { +- /* DMA_IMAGE, VRAM only */ +- if (dma0 & 0x000c0000) +- return -EINVAL; +- +- nv_wr32(dev, 0x00b370, base); +- nv_wr32(dev, 0x00b374, size); +- } +- +- return 0; +-} +- +-static int +-nv40_mpeg_isr_chid(struct drm_device *dev, u32 inst) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpuobj *ctx; +- unsigned long flags; +- int i; +- +- spin_lock_irqsave(&dev_priv->channels.lock, flags); +- for (i = 0; i < dev_priv->engine.fifo.channels; i++) { +- if (!dev_priv->channels.ptr[i]) +- continue; +- +- ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG]; +- if (ctx && ctx->pinst == inst) +- break; +- } +- spin_unlock_irqrestore(&dev_priv->channels.lock, flags); +- return i; +-} +- +-static void +-nv40_vpe_set_tile_region(struct drm_device *dev, int i) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; +- +- nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch); +- nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit); +- nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr); +-} +- +-static void +-nv40_mpeg_isr(struct drm_device *dev) +-{ +- u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4; +- u32 chid = nv40_mpeg_isr_chid(dev, inst); +- u32 stat = nv_rd32(dev, 0x00b100); +- u32 type = nv_rd32(dev, 0x00b230); +- u32 mthd = nv_rd32(dev, 0x00b234); +- u32 data = nv_rd32(dev, 0x00b238); +- u32 show = stat; +- +- if (stat & 0x01000000) { +- /* happens on initial binding of the object */ +- if (type == 0x00000020 && mthd == 0x0000) { +- nv_mask(dev, 0x00b308, 0x00000000, 0x00000000); +- show &= ~0x01000000; +- } +- +- if (type == 0x00000010) { +- if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data)) +- show &= ~0x01000000; +- } +- } +- +- nv_wr32(dev, 0x00b100, stat); +- nv_wr32(dev, 0x00b230, 0x00000001); +- +- if (show && nouveau_ratelimit()) { +- NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", +- chid, inst, stat, type, mthd, data); +- } +-} +- +-static void +-nv40_vpe_isr(struct drm_device *dev) +-{ +- if (nv_rd32(dev, 0x00b100)) +- nv40_mpeg_isr(dev); +- +- if (nv_rd32(dev, 0x00b800)) { +- u32 stat = nv_rd32(dev, 0x00b800); +- NV_INFO(dev, "PMSRCH: 0x%08x\n", stat); +- nv_wr32(dev, 0xb800, stat); +- } +-} +- +-static void +-nv40_mpeg_destroy(struct drm_device *dev, int engine) +-{ +- struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine); +- +- nouveau_irq_unregister(dev, 0); +- +- NVOBJ_ENGINE_DEL(dev, MPEG); +- kfree(pmpeg); +-} +- +-int +-nv40_mpeg_create(struct drm_device *dev) +-{ +- struct nv40_mpeg_engine *pmpeg; +- +- pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); +- if (!pmpeg) +- return -ENOMEM; +- +- pmpeg->base.destroy = nv40_mpeg_destroy; +- pmpeg->base.init = nv40_mpeg_init; +- pmpeg->base.fini = nv40_mpeg_fini; +- pmpeg->base.context_new = nv40_mpeg_context_new; +- pmpeg->base.context_del = nv40_mpeg_context_del; +- pmpeg->base.object_new = nv40_mpeg_object_new; +- +- /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between +- * all VPE engines, for this driver's purposes the PMPEG engine +- * will be treated as the "master" and handle the global VPE +- * bits too +- */ +- pmpeg->base.set_tile_region = nv40_vpe_set_tile_region; +- nouveau_irq_register(dev, 0, nv40_vpe_isr); +- +- NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); +- NVOBJ_CLASS(dev, 0x3174, MPEG); +- NVOBJ_MTHD (dev, 0x3174, 0x0190, nv40_mpeg_mthd_dma); +- NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv40_mpeg_mthd_dma); +- NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv40_mpeg_mthd_dma); +- +-#if 0 +- NVOBJ_ENGINE_ADD(dev, ME, &pme->base); +- NVOBJ_CLASS(dev, 0x4075, ME); +-#endif +- return 0; +- +-} +diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c +new file mode 100644 +index 0000000..e676b0d +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nv40_pm.c +@@ -0,0 +1,348 @@ ++/* ++ * 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"), ++ * 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 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) OR AUTHOR(S) 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: Ben Skeggs ++ */ ++ ++#include "drmP.h" ++#include "nouveau_drv.h" ++#include "nouveau_bios.h" ++#include "nouveau_pm.h" ++#include "nouveau_hw.h" ++ ++#define min2(a,b) ((a) < (b) ? (a) : (b)) ++ ++static u32 ++read_pll_1(struct drm_device *dev, u32 reg) ++{ ++ u32 ctrl = nv_rd32(dev, reg + 0x00); ++ int P = (ctrl & 0x00070000) >> 16; ++ int N = (ctrl & 0x0000ff00) >> 8; ++ int M = (ctrl & 0x000000ff) >> 0; ++ u32 ref = 27000, clk = 0; ++ ++ if (ctrl & 0x80000000) ++ clk = ref * N / M; ++ ++ return clk >> P; ++} ++ ++static u32 ++read_pll_2(struct drm_device *dev, u32 reg) ++{ ++ u32 ctrl = nv_rd32(dev, reg + 0x00); ++ u32 coef = nv_rd32(dev, reg + 0x04); ++ int N2 = (coef & 0xff000000) >> 24; ++ int M2 = (coef & 0x00ff0000) >> 16; ++ int N1 = (coef & 0x0000ff00) >> 8; ++ int M1 = (coef & 0x000000ff) >> 0; ++ int P = (ctrl & 0x00070000) >> 16; ++ u32 ref = 27000, clk = 0; ++ ++ if ((ctrl & 0x80000000) && M1) { ++ clk = ref * N1 / M1; ++ if ((ctrl & 0x40000100) == 0x40000000) { ++ if (M2) ++ clk = clk * N2 / M2; ++ else ++ clk = 0; ++ } ++ } ++ ++ return clk >> P; ++} ++ ++static u32 ++read_clk(struct drm_device *dev, u32 src) ++{ ++ switch (src) { ++ case 3: ++ return read_pll_2(dev, 0x004000); ++ case 2: ++ return read_pll_1(dev, 0x004008); ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++int ++nv40_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) ++{ ++ u32 ctrl = nv_rd32(dev, 0x00c040); ++ ++ perflvl->core = read_clk(dev, (ctrl & 0x00000003) >> 0); ++ perflvl->shader = read_clk(dev, (ctrl & 0x00000030) >> 4); ++ perflvl->memory = read_pll_2(dev, 0x4020); ++ return 0; ++} ++ ++struct nv40_pm_state { ++ u32 ctrl; ++ u32 npll_ctrl; ++ u32 npll_coef; ++ u32 spll; ++ u32 mpll_ctrl; ++ u32 mpll_coef; ++}; ++ ++static int ++nv40_calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll, ++ u32 clk, int *N1, int *M1, int *N2, int *M2, int *log2P) ++{ ++ struct nouveau_pll_vals coef; ++ int ret; ++ ++ ret = get_pll_limits(dev, reg, pll); ++ if (ret) ++ return ret; ++ ++ if (clk < pll->vco1.maxfreq) ++ pll->vco2.maxfreq = 0; ++ ++ ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef); ++ if (ret == 0) ++ return -ERANGE; ++ ++ *N1 = coef.N1; ++ *M1 = coef.M1; ++ if (N2 && M2) { ++ if (pll->vco2.maxfreq) { ++ *N2 = coef.N2; ++ *M2 = coef.M2; ++ } else { ++ *N2 = 1; ++ *M2 = 1; ++ } ++ } ++ *log2P = coef.log2P; ++ return 0; ++} ++ ++void * ++nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) ++{ ++ struct nv40_pm_state *info; ++ struct pll_lims pll; ++ int N1, N2, M1, M2, log2P; ++ int ret; ++ ++ info = kmalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return ERR_PTR(-ENOMEM); ++ ++ /* core/geometric clock */ ++ ret = nv40_calc_pll(dev, 0x004000, &pll, perflvl->core, ++ &N1, &M1, &N2, &M2, &log2P); ++ if (ret < 0) ++ goto out; ++ ++ if (N2 == M2) { ++ info->npll_ctrl = 0x80000100 | (log2P << 16); ++ info->npll_coef = (N1 << 8) | M1; ++ } else { ++ info->npll_ctrl = 0xc0000000 | (log2P << 16); ++ info->npll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1; ++ } ++ ++ /* use the second PLL for shader/rop clock, if it differs from core */ ++ if (perflvl->shader && perflvl->shader != perflvl->core) { ++ ret = nv40_calc_pll(dev, 0x004008, &pll, perflvl->shader, ++ &N1, &M1, NULL, NULL, &log2P); ++ if (ret < 0) ++ goto out; ++ ++ info->spll = 0xc0000000 | (log2P << 16) | (N1 << 8) | M1; ++ info->ctrl = 0x00000223; ++ } else { ++ info->spll = 0x00000000; ++ info->ctrl = 0x00000333; ++ } ++ ++ /* memory clock */ ++ if (!perflvl->memory) { ++ info->mpll_ctrl = 0x00000000; ++ goto out; ++ } ++ ++ ret = nv40_calc_pll(dev, 0x004020, &pll, perflvl->memory, ++ &N1, &M1, &N2, &M2, &log2P); ++ if (ret < 0) ++ goto out; ++ ++ info->mpll_ctrl = 0x80000000 | (log2P << 16); ++ info->mpll_ctrl |= min2(pll.log2p_bias + log2P, pll.max_log2p) << 20; ++ if (N2 == M2) { ++ info->mpll_ctrl |= 0x00000100; ++ info->mpll_coef = (N1 << 8) | M1; ++ } else { ++ info->mpll_ctrl |= 0x40000000; ++ info->mpll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1; ++ } ++ ++out: ++ if (ret < 0) { ++ kfree(info); ++ info = ERR_PTR(ret); ++ } ++ return info; ++} ++ ++static bool ++nv40_pm_gr_idle(void *data) ++{ ++ struct drm_device *dev = data; ++ ++ if ((nv_rd32(dev, 0x400760) & 0x000000f0) >> 4 != ++ (nv_rd32(dev, 0x400760) & 0x0000000f)) ++ return false; ++ ++ if (nv_rd32(dev, 0x400700)) ++ return false; ++ ++ return true; ++} ++ ++void ++nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv40_pm_state *info = pre_state; ++ unsigned long flags; ++ struct bit_entry M; ++ u32 crtc_mask = 0; ++ u8 sr1[2]; ++ int i; ++ ++ /* determine which CRTCs are active, fetch VGA_SR1 for each */ ++ for (i = 0; i < 2; i++) { ++ u32 vbl = nv_rd32(dev, 0x600808 + (i * 0x2000)); ++ u32 cnt = 0; ++ do { ++ if (vbl != nv_rd32(dev, 0x600808 + (i * 0x2000))) { ++ nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01); ++ sr1[i] = nv_rd08(dev, 0x0c03c5 + (i * 0x2000)); ++ if (!(sr1[i] & 0x20)) ++ crtc_mask |= (1 << i); ++ break; ++ } ++ udelay(1); ++ } while (cnt++ < 32); ++ } ++ ++ /* halt and idle engines */ ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ nv_mask(dev, 0x002500, 0x00000001, 0x00000000); ++ if (!nv_wait(dev, 0x002500, 0x00000010, 0x00000000)) ++ goto resume; ++ nv_mask(dev, 0x003220, 0x00000001, 0x00000000); ++ if (!nv_wait(dev, 0x003220, 0x00000010, 0x00000000)) ++ goto resume; ++ nv_mask(dev, 0x003200, 0x00000001, 0x00000000); ++ nv04_fifo_cache_pull(dev, false); ++ ++ if (!nv_wait_cb(dev, nv40_pm_gr_idle, dev)) ++ goto resume; ++ ++ /* set engine clocks */ ++ nv_mask(dev, 0x00c040, 0x00000333, 0x00000000); ++ nv_wr32(dev, 0x004004, info->npll_coef); ++ nv_mask(dev, 0x004000, 0xc0070100, info->npll_ctrl); ++ nv_mask(dev, 0x004008, 0xc007ffff, info->spll); ++ mdelay(5); ++ nv_mask(dev, 0x00c040, 0x00000333, info->ctrl); ++ ++ if (!info->mpll_ctrl) ++ goto resume; ++ ++ /* wait for vblank start on active crtcs, disable memory access */ ++ for (i = 0; i < 2; i++) { ++ if (!(crtc_mask & (1 << i))) ++ continue; ++ nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00000000); ++ nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); ++ nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01); ++ nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i] | 0x20); ++ } ++ ++ /* prepare ram for reclocking */ ++ nv_wr32(dev, 0x1002d4, 0x00000001); /* precharge */ ++ nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */ ++ nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */ ++ nv_mask(dev, 0x100210, 0x80000000, 0x00000000); /* no auto refresh */ ++ nv_wr32(dev, 0x1002dc, 0x00000001); /* enable self-refresh */ ++ ++ /* change the PLL of each memory partition */ ++ nv_mask(dev, 0x00c040, 0x0000c000, 0x00000000); ++ switch (dev_priv->chipset) { ++ case 0x40: ++ case 0x45: ++ case 0x41: ++ case 0x42: ++ case 0x47: ++ nv_mask(dev, 0x004044, 0xc0771100, info->mpll_ctrl); ++ nv_mask(dev, 0x00402c, 0xc0771100, info->mpll_ctrl); ++ nv_wr32(dev, 0x004048, info->mpll_coef); ++ nv_wr32(dev, 0x004030, info->mpll_coef); ++ case 0x43: ++ case 0x49: ++ case 0x4b: ++ nv_mask(dev, 0x004038, 0xc0771100, info->mpll_ctrl); ++ nv_wr32(dev, 0x00403c, info->mpll_coef); ++ default: ++ nv_mask(dev, 0x004020, 0xc0771100, info->mpll_ctrl); ++ nv_wr32(dev, 0x004024, info->mpll_coef); ++ break; ++ } ++ udelay(100); ++ nv_mask(dev, 0x00c040, 0x0000c000, 0x0000c000); ++ ++ /* re-enable normal operation of memory controller */ ++ nv_wr32(dev, 0x1002dc, 0x00000000); ++ nv_mask(dev, 0x100210, 0x80000000, 0x80000000); ++ udelay(100); ++ ++ /* execute memory reset script from vbios */ ++ if (!bit_table(dev, 'M', &M)) ++ nouveau_bios_init_exec(dev, ROM16(M.data[0])); ++ ++ /* make sure we're in vblank (hopefully the same one as before), and ++ * then re-enable crtc memory access ++ */ ++ for (i = 0; i < 2; i++) { ++ if (!(crtc_mask & (1 << i))) ++ continue; ++ nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); ++ nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01); ++ nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i]); ++ } ++ ++ /* resume engines */ ++resume: ++ nv_wr32(dev, 0x003250, 0x00000001); ++ nv_mask(dev, 0x003220, 0x00000001, 0x00000001); ++ nv_wr32(dev, 0x003200, 0x00000001); ++ nv_wr32(dev, 0x002500, 0x00000001); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); ++ ++ kfree(info); ++} +diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c +index 5d98907..882080e 100644 +--- a/drivers/gpu/drm/nouveau/nv50_crtc.c ++++ b/drivers/gpu/drm/nouveau/nv50_crtc.c +@@ -329,8 +329,6 @@ nv50_crtc_destroy(struct drm_crtc *crtc) + + drm_crtc_cleanup(&nv_crtc->base); + +- nv50_cursor_fini(nv_crtc); +- + nouveau_bo_unmap(nv_crtc->lut.nvbo); + nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); + nouveau_bo_unmap(nv_crtc->cursor.nvbo); +diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c +index 9752c35..adfc9b6 100644 +--- a/drivers/gpu/drm/nouveau/nv50_cursor.c ++++ b/drivers/gpu/drm/nouveau/nv50_cursor.c +@@ -137,21 +137,3 @@ nv50_cursor_init(struct nouveau_crtc *nv_crtc) + nv_crtc->cursor.show = nv50_cursor_show; + return 0; + } +- +-void +-nv50_cursor_fini(struct nouveau_crtc *nv_crtc) +-{ +- struct drm_device *dev = nv_crtc->base.dev; +- int idx = nv_crtc->index; +- +- NV_DEBUG_KMS(dev, "\n"); +- +- nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0); +- if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), +- NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { +- NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); +- NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", +- nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx))); +- } +-} +- +diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c +index db1a5f4..d23ca00 100644 +--- a/drivers/gpu/drm/nouveau/nv50_display.c ++++ b/drivers/gpu/drm/nouveau/nv50_display.c +@@ -247,6 +247,16 @@ static int nv50_display_disable(struct drm_device *dev) + } + } + ++ for (i = 0; i < 2; i++) { ++ nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0); ++ if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), ++ NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { ++ NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); ++ NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", ++ nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); ++ } ++ } ++ + nv50_evo_fini(dev); + + for (i = 0; i < 3; i++) { +@@ -286,23 +296,6 @@ int nv50_display_create(struct drm_device *dev) + return -ENOMEM; + dev_priv->engine.display.priv = priv; + +- /* init basic kernel modesetting */ +- drm_mode_config_init(dev); +- +- /* Initialise some optional connector properties. */ +- drm_mode_create_scaling_mode_property(dev); +- drm_mode_create_dithering_property(dev); +- +- dev->mode_config.min_width = 0; +- dev->mode_config.min_height = 0; +- +- dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; +- +- dev->mode_config.max_width = 8192; +- dev->mode_config.max_height = 8192; +- +- dev->mode_config.fb_base = dev_priv->fb_phys; +- + /* Create CRTC objects */ + for (i = 0; i < 2; i++) + nv50_crtc_create(dev, i); +@@ -364,8 +357,6 @@ nv50_display_destroy(struct drm_device *dev) + + NV_DEBUG_KMS(dev, "\n"); + +- drm_mode_config_cleanup(dev); +- + nv50_display_disable(dev); + nouveau_irq_unregister(dev, 26); + kfree(disp); +@@ -698,7 +689,7 @@ nv50_display_unk10_handler(struct drm_device *dev) + struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i]; + + if (dcb->type == type && (dcb->or & (1 << or))) { +- nouveau_bios_run_display_table(dev, dcb, 0, -1); ++ nouveau_bios_run_display_table(dev, 0, -1, dcb, -1); + disp->irq.dcb = dcb; + goto ack; + } +@@ -711,37 +702,6 @@ ack: + } + + static void +-nv50_display_unk20_dp_hack(struct drm_device *dev, struct dcb_entry *dcb) +-{ +- int or = ffs(dcb->or) - 1, link = !(dcb->dpconf.sor.link & 1); +- struct drm_encoder *encoder; +- uint32_t tmp, unk0 = 0, unk1 = 0; +- +- if (dcb->type != OUTPUT_DP) +- return; +- +- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- +- if (nv_encoder->dcb == dcb) { +- unk0 = nv_encoder->dp.unk0; +- unk1 = nv_encoder->dp.unk1; +- break; +- } +- } +- +- if (unk0 || unk1) { +- tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); +- tmp &= 0xfffffe03; +- nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp | unk0); +- +- tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link)); +- tmp &= 0xfef080c0; +- nv_wr32(dev, NV50_SOR_DP_UNK128(or, link), tmp | unk1); +- } +-} +- +-static void + nv50_display_unk20_handler(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +@@ -753,7 +713,7 @@ nv50_display_unk20_handler(struct drm_device *dev) + NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); + dcb = disp->irq.dcb; + if (dcb) { +- nouveau_bios_run_display_table(dev, dcb, 0, -2); ++ nouveau_bios_run_display_table(dev, 0, -2, dcb, -1); + disp->irq.dcb = NULL; + } + +@@ -837,9 +797,15 @@ nv50_display_unk20_handler(struct drm_device *dev) + } + + script = nv50_display_script_select(dev, dcb, mc, pclk); +- nouveau_bios_run_display_table(dev, dcb, script, pclk); ++ nouveau_bios_run_display_table(dev, script, pclk, dcb, -1); + +- nv50_display_unk20_dp_hack(dev, dcb); ++ if (type == OUTPUT_DP) { ++ int link = !(dcb->dpconf.sor.link & 1); ++ if ((mc & 0x000f0000) == 0x00020000) ++ nouveau_dp_tu_update(dev, or, link, pclk, 18); ++ else ++ nouveau_dp_tu_update(dev, or, link, pclk, 24); ++ } + + if (dcb->type != OUTPUT_ANALOG) { + tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or)); +@@ -904,7 +870,7 @@ nv50_display_unk40_handler(struct drm_device *dev) + if (!dcb) + goto ack; + +- nouveau_bios_run_display_table(dev, dcb, script, -pclk); ++ nouveau_bios_run_display_table(dev, script, -pclk, dcb, -1); + nv50_display_unk40_dp_set_tmds(dev, dcb); + + ack: +diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c +index d4f4206..793a5cc 100644 +--- a/drivers/gpu/drm/nouveau/nv50_gpio.c ++++ b/drivers/gpu/drm/nouveau/nv50_gpio.c +@@ -98,6 +98,37 @@ nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) + } + + int ++nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) ++{ ++ struct dcb_gpio_entry *gpio; ++ u32 v; ++ ++ gpio = nouveau_bios_gpio_entry(dev, tag); ++ if (!gpio) ++ return -ENOENT; ++ ++ v = nv_rd32(dev, 0x00d610 + (gpio->line * 4)); ++ v &= 0x00004000; ++ return (!!v == (gpio->state[1] & 1)); ++} ++ ++int ++nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) ++{ ++ struct dcb_gpio_entry *gpio; ++ u32 v; ++ ++ gpio = nouveau_bios_gpio_entry(dev, tag); ++ if (!gpio) ++ return -ENOENT; ++ ++ v = gpio->state[state] ^ 2; ++ ++ nv_mask(dev, 0x00d610 + (gpio->line * 4), 0x00003000, v << 12); ++ return 0; ++} ++ ++int + nv50_gpio_irq_register(struct drm_device *dev, enum dcb_gpio_tag tag, + void (*handler)(void *, int), void *data) + { +diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c +index d43c46c..8c979b3 100644 +--- a/drivers/gpu/drm/nouveau/nv50_graph.c ++++ b/drivers/gpu/drm/nouveau/nv50_graph.c +@@ -120,70 +120,62 @@ nv50_graph_unload_context(struct drm_device *dev) + return 0; + } + +-static void +-nv50_graph_init_reset(struct drm_device *dev) +-{ +- uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21); +- NV_DEBUG(dev, "\n"); +- +- nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e); +- nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | pmc_e); +-} +- +-static void +-nv50_graph_init_intr(struct drm_device *dev) +-{ +- NV_DEBUG(dev, "\n"); +- +- nv_wr32(dev, NV03_PGRAPH_INTR, 0xffffffff); +- nv_wr32(dev, 0x400138, 0xffffffff); +- nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xffffffff); +-} +- +-static void +-nv50_graph_init_regs__nv(struct drm_device *dev) ++static int ++nv50_graph_init(struct drm_device *dev, int engine) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- uint32_t units = nv_rd32(dev, 0x1540); ++ struct nv50_graph_engine *pgraph = nv_engine(dev, engine); ++ u32 units = nv_rd32(dev, 0x001540); + int i; + + NV_DEBUG(dev, "\n"); + ++ /* master reset */ ++ nv_mask(dev, 0x000200, 0x00200100, 0x00000000); ++ nv_mask(dev, 0x000200, 0x00200100, 0x00200100); ++ nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */ ++ ++ /* reset/enable traps and interrupts */ + nv_wr32(dev, 0x400804, 0xc0000000); + nv_wr32(dev, 0x406800, 0xc0000000); + nv_wr32(dev, 0x400c04, 0xc0000000); + nv_wr32(dev, 0x401800, 0xc0000000); + nv_wr32(dev, 0x405018, 0xc0000000); + nv_wr32(dev, 0x402000, 0xc0000000); +- + for (i = 0; i < 16; i++) { +- if (units & 1 << i) { +- if (dev_priv->chipset < 0xa0) { +- nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000); +- nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000); +- nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000); +- } else { +- nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000); +- nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000); +- nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000); +- } ++ if (!(units & (1 << i))) ++ continue; ++ ++ if (dev_priv->chipset < 0xa0) { ++ nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000); ++ nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000); ++ nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000); ++ } else { ++ nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000); ++ nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000); ++ nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000); + } + } + + nv_wr32(dev, 0x400108, 0xffffffff); +- +- nv_wr32(dev, 0x400824, 0x00004000); ++ nv_wr32(dev, 0x400138, 0xffffffff); ++ nv_wr32(dev, 0x400100, 0xffffffff); ++ nv_wr32(dev, 0x40013c, 0xffffffff); + nv_wr32(dev, 0x400500, 0x00010001); +-} +- +-static void +-nv50_graph_init_zcull(struct drm_device *dev) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- int i; +- +- NV_DEBUG(dev, "\n"); + ++ /* upload context program, initialise ctxctl defaults */ ++ nv_wr32(dev, 0x400324, 0x00000000); ++ for (i = 0; i < pgraph->ctxprog_size; i++) ++ nv_wr32(dev, 0x400328, pgraph->ctxprog[i]); ++ nv_wr32(dev, 0x400824, 0x00000000); ++ nv_wr32(dev, 0x400828, 0x00000000); ++ nv_wr32(dev, 0x40082c, 0x00000000); ++ nv_wr32(dev, 0x400830, 0x00000000); ++ nv_wr32(dev, 0x400724, 0x00000000); ++ nv_wr32(dev, 0x40032c, 0x00000000); ++ nv_wr32(dev, 0x400320, 4); /* CTXCTL_CMD = NEWCTXDMA */ ++ ++ /* some unknown zcull magic */ + switch (dev_priv->chipset & 0xf0) { + case 0x50: + case 0x80: +@@ -212,43 +204,7 @@ nv50_graph_init_zcull(struct drm_device *dev) + nv_wr32(dev, 0x402c28 + (i * 8), 0x00000000); + nv_wr32(dev, 0x402c2c + (i * 8), 0x00000000); + } +-} +- +-static int +-nv50_graph_init_ctxctl(struct drm_device *dev) +-{ +- struct nv50_graph_engine *pgraph = nv_engine(dev, NVOBJ_ENGINE_GR); +- int i; +- +- NV_DEBUG(dev, "\n"); +- +- nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); +- for (i = 0; i < pgraph->ctxprog_size; i++) +- nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, pgraph->ctxprog[i]); +- +- 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); +- return 0; +-} +- +-static int +-nv50_graph_init(struct drm_device *dev, int engine) -{ -- uint32_t inst; - int ret; - -- inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); -- if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) -- return 0; -- inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE; +- NV_DEBUG(dev, "\n"); - -- ret = nv40_graph_transfer_context(dev, inst, 1); +- nv50_graph_init_reset(dev); +- nv50_graph_init_regs__nv(dev); +- nv50_graph_init_zcull(dev); - -- nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst); -- return ret; +- ret = nv50_graph_init_ctxctl(dev); +- if (ret) +- return ret; + +- nv50_graph_init_intr(dev); + return 0; + } + +diff --git a/drivers/gpu/drm/nouveau/nv50_grctx.c b/drivers/gpu/drm/nouveau/nv50_grctx.c +index de9abff..d05c2c3 100644 +--- a/drivers/gpu/drm/nouveau/nv50_grctx.c ++++ b/drivers/gpu/drm/nouveau/nv50_grctx.c +@@ -40,6 +40,12 @@ + #define CP_FLAG_UNK0B ((0 * 32) + 0xb) + #define CP_FLAG_UNK0B_CLEAR 0 + #define CP_FLAG_UNK0B_SET 1 ++#define CP_FLAG_XFER_SWITCH ((0 * 32) + 0xe) ++#define CP_FLAG_XFER_SWITCH_DISABLE 0 ++#define CP_FLAG_XFER_SWITCH_ENABLE 1 ++#define CP_FLAG_STATE ((0 * 32) + 0x1c) ++#define CP_FLAG_STATE_STOPPED 0 ++#define CP_FLAG_STATE_RUNNING 1 + #define CP_FLAG_UNK1D ((0 * 32) + 0x1d) + #define CP_FLAG_UNK1D_CLEAR 0 + #define CP_FLAG_UNK1D_SET 1 +@@ -194,6 +200,9 @@ nv50_grctx_init(struct nouveau_grctx *ctx) + "the devs.\n"); + return -ENOSYS; + } ++ ++ cp_set (ctx, STATE, RUNNING); ++ cp_set (ctx, XFER_SWITCH, ENABLE); + /* decide whether we're loading/unloading the context */ + cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save); + cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save); +@@ -260,6 +269,8 @@ nv50_grctx_init(struct nouveau_grctx *ctx) + cp_name(ctx, cp_exit); + cp_set (ctx, USER_SAVE, NOT_PENDING); + cp_set (ctx, USER_LOAD, NOT_PENDING); ++ cp_set (ctx, XFER_SWITCH, DISABLE); ++ cp_set (ctx, STATE, STOPPED); + cp_out (ctx, CP_END); + ctx->ctxvals_pos += 0x400; /* padding... no idea why you need it */ + +diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c +index 8a28100..3d5a86b 100644 +--- a/drivers/gpu/drm/nouveau/nv50_pm.c ++++ b/drivers/gpu/drm/nouveau/nv50_pm.c +@@ -115,15 +115,15 @@ nv50_pm_clock_set(struct drm_device *dev, void *pre_state) + BIT_M.version == 1 && BIT_M.length >= 0x0b) { + script = ROM16(BIT_M.data[0x05]); + if (script) +- nouveau_bios_run_init_table(dev, script, NULL); ++ nouveau_bios_run_init_table(dev, script, NULL, -1); + script = ROM16(BIT_M.data[0x07]); + if (script) +- nouveau_bios_run_init_table(dev, script, NULL); ++ nouveau_bios_run_init_table(dev, script, NULL, -1); + script = ROM16(BIT_M.data[0x09]); + if (script) +- nouveau_bios_run_init_table(dev, script, NULL); ++ nouveau_bios_run_init_table(dev, script, NULL, -1); + +- nouveau_bios_run_init_table(dev, perflvl->memscript, NULL); ++ nouveau_bios_run_init_table(dev, perflvl->memscript, NULL, -1); + } + + if (state->type == PLL_MEMORY) { +diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c +index ffe8b48..2633aa8 100644 +--- a/drivers/gpu/drm/nouveau/nv50_sor.c ++++ b/drivers/gpu/drm/nouveau/nv50_sor.c +@@ -124,7 +124,7 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) + if (mode == DRM_MODE_DPMS_ON) { + u8 status = DP_SET_POWER_D0; + nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); +- nouveau_dp_link_train(encoder); ++ nouveau_dp_link_train(encoder, nv_encoder->dp.datarate); + } else { + u8 status = DP_SET_POWER_D3; + nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); +@@ -187,14 +187,13 @@ nv50_sor_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 nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); ++ struct nouveau_connector *nv_connector; + uint32_t mode_ctl = 0; + int ret; + + NV_DEBUG_KMS(dev, "or %d type %d -> crtc %d\n", + nv_encoder->or, nv_encoder->dcb->type, crtc->index); + +- nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); +- + switch (nv_encoder->dcb->type) { + case OUTPUT_TMDS: + if (nv_encoder->dcb->sorconf.link & 1) { +@@ -206,7 +205,15 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + mode_ctl = 0x0200; + break; + case OUTPUT_DP: +- mode_ctl |= (nv_encoder->dp.mc_unknown << 16); ++ nv_connector = nouveau_encoder_connector_get(nv_encoder); ++ if (nv_connector && nv_connector->base.display_info.bpc == 6) { ++ nv_encoder->dp.datarate = crtc->mode->clock * 18 / 8; ++ mode_ctl |= 0x00020000; ++ } else { ++ nv_encoder->dp.datarate = crtc->mode->clock * 24 / 8; ++ mode_ctl |= 0x00050000; ++ } ++ + if (nv_encoder->dcb->sorconf.link & 1) + mode_ctl |= 0x00000800; + else +@@ -227,6 +234,8 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) + mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NVSYNC; + ++ nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); ++ + ret = RING_SPACE(evo, 2); + if (ret) { + NV_ERROR(dev, "no space while connecting SOR\n"); +@@ -313,31 +322,6 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry) + encoder->possible_crtcs = entry->heads; + encoder->possible_clones = 0; + +- if (nv_encoder->dcb->type == OUTPUT_DP) { +- int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1); +- uint32_t tmp; +- +- tmp = nv_rd32(dev, 0x61c700 + (or * 0x800)); +- if (!tmp) +- tmp = nv_rd32(dev, 0x610798 + (or * 8)); +- +- switch ((tmp & 0x00000f00) >> 8) { +- case 8: +- case 9: +- nv_encoder->dp.mc_unknown = (tmp & 0x000f0000) >> 16; +- tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); +- nv_encoder->dp.unk0 = tmp & 0x000001fc; +- tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link)); +- nv_encoder->dp.unk1 = tmp & 0x010f7f3f; +- break; +- default: +- break; +- } +- +- if (!nv_encoder->dp.mc_unknown) +- nv_encoder->dp.mc_unknown = 5; +- } +- + drm_mode_connector_attach_encoder(connector, encoder); + return 0; + } +diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c +index af32dae..9da2383 100644 +--- a/drivers/gpu/drm/nouveau/nv50_vram.c ++++ b/drivers/gpu/drm/nouveau/nv50_vram.c +@@ -51,7 +51,7 @@ void + nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_mm *mm = dev_priv->engine.vram.mm; ++ struct nouveau_mm *mm = &dev_priv->engine.vram.mm; + struct nouveau_mm_node *this; + struct nouveau_mem *mem; + +@@ -82,7 +82,7 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, + u32 memtype, struct nouveau_mem **pmem) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_mm *mm = dev_priv->engine.vram.mm; ++ struct nouveau_mm *mm = &dev_priv->engine.vram.mm; + struct nouveau_mm_node *r; + struct nouveau_mem *mem; + int comp = (memtype & 0x300) >> 8; +diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c +index e4b2b9e..618c144 100644 +--- a/drivers/gpu/drm/nouveau/nva3_pm.c ++++ b/drivers/gpu/drm/nouveau/nva3_pm.c +@@ -27,178 +27,316 @@ + #include "nouveau_bios.h" + #include "nouveau_pm.h" + +-/* 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. +- */ ++static u32 read_clk(struct drm_device *, int, bool); ++static u32 read_pll(struct drm_device *, int, u32); + +-struct nva3_pm_state { +- enum pll_types type; +- u32 src0; +- u32 src1; +- u32 ctrl; +- u32 coef; +- u32 old_pnm; +- u32 new_pnm; +- u32 new_div; +-}; ++static u32 ++read_vco(struct drm_device *dev, int clk) ++{ ++ u32 sctl = nv_rd32(dev, 0x4120 + (clk * 4)); ++ if ((sctl & 0x00000030) != 0x00000030) ++ return read_pll(dev, 0x41, 0x00e820); ++ return read_pll(dev, 0x42, 0x00e8a0); ++} + +-static int +-nva3_pm_pll_offset(u32 id) ++static u32 ++read_clk(struct drm_device *dev, int clk, bool ignore_en) + { +- 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; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 sctl, sdiv, sclk; ++ ++ /* refclk for the 0xe8xx plls is a fixed frequency */ ++ if (clk >= 0x40) { ++ if (dev_priv->chipset == 0xaf) { ++ /* no joke.. seriously.. sigh.. */ ++ return nv_rd32(dev, 0x00471c) * 1000; ++ } ++ ++ return dev_priv->crystal; + } + +- return -ENOENT; ++ sctl = nv_rd32(dev, 0x4120 + (clk * 4)); ++ if (!ignore_en && !(sctl & 0x00000100)) ++ return 0; ++ ++ switch (sctl & 0x00003000) { ++ case 0x00000000: ++ return dev_priv->crystal; ++ case 0x00002000: ++ if (sctl & 0x00000040) ++ return 108000; ++ return 100000; ++ case 0x00003000: ++ sclk = read_vco(dev, clk); ++ sdiv = ((sctl & 0x003f0000) >> 16) + 2; ++ return (sclk * 2) / sdiv; ++ default: ++ return 0; ++ } + } + +-int +-nva3_pm_clock_get(struct drm_device *dev, u32 id) ++static u32 ++read_pll(struct drm_device *dev, int clk, u32 pll) ++{ ++ u32 ctrl = nv_rd32(dev, pll + 0); ++ u32 sclk = 0, P = 1, N = 1, M = 1; ++ ++ if (!(ctrl & 0x00000008)) { ++ if (ctrl & 0x00000001) { ++ u32 coef = nv_rd32(dev, pll + 4); ++ M = (coef & 0x000000ff) >> 0; ++ N = (coef & 0x0000ff00) >> 8; ++ P = (coef & 0x003f0000) >> 16; ++ ++ /* no post-divider on these.. */ ++ if ((pll & 0x00ff00) == 0x00e800) ++ P = 1; ++ ++ sclk = read_clk(dev, 0x00 + clk, false); ++ } ++ } else { ++ sclk = read_clk(dev, 0x10 + clk, false); ++ } ++ ++ return sclk * N / (M * P); ++} ++ ++struct creg { ++ u32 clk; ++ u32 pll; ++}; ++ ++static int ++calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) + { +- u32 src0, src1, ctrl, coef; +- struct pll_lims pll; +- int ret, off; +- int P, N, M; ++ struct pll_lims limits; ++ u32 oclk, sclk, sdiv; ++ int P, N, M, diff; ++ int ret; ++ ++ reg->pll = 0; ++ reg->clk = 0; ++ if (!khz) { ++ NV_DEBUG(dev, "no clock for 0x%04x/0x%02x\n", pll, clk); ++ return 0; ++ } + +- ret = get_pll_limits(dev, id, &pll); ++ switch (khz) { ++ case 27000: ++ reg->clk = 0x00000100; ++ return khz; ++ case 100000: ++ reg->clk = 0x00002100; ++ return khz; ++ case 108000: ++ reg->clk = 0x00002140; ++ return khz; ++ default: ++ sclk = read_vco(dev, clk); ++ sdiv = min((sclk * 2) / (khz - 2999), (u32)65); ++ /* if the clock has a PLL attached, and we can get a within ++ * [-2, 3) MHz of a divider, we'll disable the PLL and use ++ * the divider instead. ++ * ++ * divider can go as low as 2, limited here because NVIDIA ++ * and the VBIOS on my NVA8 seem to prefer using the PLL ++ * for 810MHz - is there a good reason? ++ */ ++ if (sdiv > 4) { ++ oclk = (sclk * 2) / sdiv; ++ diff = khz - oclk; ++ if (!pll || (diff >= -2000 && diff < 3000)) { ++ reg->clk = (((sdiv - 2) << 16) | 0x00003100); ++ return oclk; ++ } ++ } ++ ++ if (!pll) { ++ NV_ERROR(dev, "bad freq %02x: %d %d\n", clk, khz, sclk); ++ return -ERANGE; ++ } ++ ++ break; ++ } ++ ++ ret = get_pll_limits(dev, pll, &limits); + if (ret) + return ret; + +- off = nva3_pm_pll_offset(id); +- if (off < 0) +- return off; ++ limits.refclk = read_clk(dev, clk - 0x10, true); ++ if (!limits.refclk) ++ return -EINVAL; ++ ++ ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P); ++ if (ret >= 0) { ++ reg->clk = nv_rd32(dev, 0x4120 + (clk * 4)); ++ reg->pll = (P << 16) | (N << 8) | M; ++ } ++ return ret; ++} ++ ++static void ++prog_pll(struct drm_device *dev, int clk, u32 pll, struct creg *reg) ++{ ++ const u32 src0 = 0x004120 + (clk * 4); ++ const u32 src1 = 0x004160 + (clk * 4); ++ const u32 ctrl = pll + 0; ++ const u32 coef = pll + 4; ++ u32 cntl; ++ ++ if (!reg->clk && !reg->pll) { ++ NV_DEBUG(dev, "no clock for %02x\n", clk); ++ return; ++ } + +- 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); ++ cntl = nv_rd32(dev, ctrl) & 0xfffffff2; ++ if (reg->pll) { ++ nv_mask(dev, src0, 0x00000101, 0x00000101); ++ nv_wr32(dev, coef, reg->pll); ++ nv_wr32(dev, ctrl, cntl | 0x00000015); ++ nv_mask(dev, src1, 0x00000100, 0x00000000); ++ nv_mask(dev, src1, 0x00000001, 0x00000000); ++ } else { ++ nv_mask(dev, src1, 0x003f3141, 0x00000101 | reg->clk); ++ nv_wr32(dev, ctrl, cntl | 0x0000001d); ++ nv_mask(dev, ctrl, 0x00000001, 0x00000000); ++ nv_mask(dev, src0, 0x00000100, 0x00000000); ++ nv_mask(dev, src0, 0x00000001, 0x00000000); ++ } ++} + +- if (ctrl & 0x00000008) { +- u32 div = ((src1 & 0x003c0000) >> 18) + 1; +- return (pll.refclk * 2) / div; ++static void ++prog_clk(struct drm_device *dev, int clk, struct creg *reg) ++{ ++ if (!reg->clk) { ++ NV_DEBUG(dev, "no clock for %02x\n", clk); ++ return; + } + +- P = (coef & 0x003f0000) >> 16; +- N = (coef & 0x0000ff00) >> 8; +- M = (coef & 0x000000ff); +- return pll.refclk * N / M / P; ++ nv_mask(dev, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | reg->clk); ++} ++ ++int ++nva3_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) ++{ ++ perflvl->core = read_pll(dev, 0x00, 0x4200); ++ perflvl->shader = read_pll(dev, 0x01, 0x4220); ++ perflvl->memory = read_pll(dev, 0x02, 0x4000); ++ perflvl->unka0 = read_clk(dev, 0x20, false); ++ perflvl->vdec = read_clk(dev, 0x21, false); ++ perflvl->daemon = read_clk(dev, 0x25, false); ++ perflvl->copy = perflvl->core; ++ return 0; + } + ++struct nva3_pm_state { ++ struct creg nclk; ++ struct creg sclk; ++ struct creg mclk; ++ struct creg vdec; ++ struct creg unka0; ++}; ++ + void * +-nva3_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, +- u32 id, int khz) ++nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) + { +- struct nva3_pm_state *pll; +- struct pll_lims limits; +- int N, M, P, diff; +- int ret, off; ++ struct nva3_pm_state *info; ++ int ret; + +- ret = get_pll_limits(dev, id, &limits); ++ info = kzalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return ERR_PTR(-ENOMEM); ++ ++ ret = calc_clk(dev, 0x10, 0x4200, perflvl->core, &info->nclk); + if (ret < 0) +- return (ret == -ENOENT) ? NULL : ERR_PTR(ret); ++ goto out; + +- off = nva3_pm_pll_offset(id); +- if (id < 0) +- return ERR_PTR(-EINVAL); ++ ret = calc_clk(dev, 0x11, 0x4220, perflvl->shader, &info->sclk); ++ if (ret < 0) ++ goto out; + ++ ret = calc_clk(dev, 0x12, 0x4000, perflvl->memory, &info->mclk); ++ if (ret < 0) ++ goto out; + +- 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; +- +- /* 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 = calc_clk(dev, 0x20, 0x0000, perflvl->unka0, &info->unka0); ++ if (ret < 0) ++ goto out; + +- if (!pll->new_div) { +- ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P); +- if (ret < 0) +- return ERR_PTR(ret); ++ ret = calc_clk(dev, 0x21, 0x0000, perflvl->vdec, &info->vdec); ++ if (ret < 0) ++ goto out; + +- pll->new_pnm = (P << 16) | (N << 8) | M; +- pll->new_div = 2 - 1; +- } else { +- pll->new_pnm = 0; +- pll->new_div--; ++out: ++ if (ret < 0) { ++ kfree(info); ++ info = ERR_PTR(ret); + } ++ return info; ++} ++ ++static bool ++nva3_pm_grcp_idle(void *data) ++{ ++ struct drm_device *dev = data; + +- if ((nv_rd32(dev, pll->src1) & 0x00000101) != 0x00000101) +- pll->old_pnm = nv_rd32(dev, pll->coef); +- return pll; ++ if (!(nv_rd32(dev, 0x400304) & 0x00000001)) ++ return true; ++ if (nv_rd32(dev, 0x400308) == 0x0050001c) ++ return true; ++ return false; + } + + void +-nva3_pm_clock_set(struct drm_device *dev, void *pre_state) ++nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) + { +- struct nva3_pm_state *pll = pre_state; +- u32 ctrl = 0; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nva3_pm_state *info = pre_state; ++ unsigned long flags; + +- /* 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; ++ /* prevent any new grctx switches from starting */ ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ nv_wr32(dev, 0x400324, 0x00000000); ++ nv_wr32(dev, 0x400328, 0x0050001c); /* wait flag 0x1c */ ++ /* wait for any pending grctx switches to complete */ ++ if (!nv_wait_cb(dev, nva3_pm_grcp_idle, dev)) { ++ NV_ERROR(dev, "pm: ctxprog didn't go idle\n"); ++ goto cleanup; + } +- +- 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); ++ /* freeze PFIFO */ ++ nv_mask(dev, 0x002504, 0x00000001, 0x00000001); ++ if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) { ++ NV_ERROR(dev, "pm: fifo didn't go idle\n"); ++ goto cleanup; + } + +- 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); +- } ++ prog_pll(dev, 0x00, 0x004200, &info->nclk); ++ prog_pll(dev, 0x01, 0x004220, &info->sclk); ++ prog_clk(dev, 0x20, &info->unka0); ++ prog_clk(dev, 0x21, &info->vdec); + +- if (pll->type == PLL_MEMORY) { ++ if (info->mclk.clk || info->mclk.pll) { ++ nv_wr32(dev, 0x100210, 0); ++ nv_wr32(dev, 0x1002dc, 1); ++ nv_wr32(dev, 0x004018, 0x00001000); ++ prog_pll(dev, 0x02, 0x004000, &info->mclk); ++ if (nv_rd32(dev, 0x4000) & 0x00000008) ++ nv_wr32(dev, 0x004018, 0x1000d000); ++ else ++ nv_wr32(dev, 0x004018, 0x10005000); + nv_wr32(dev, 0x1002dc, 0); + nv_wr32(dev, 0x100210, 0x80000000); + } + +- kfree(pll); ++cleanup: ++ /* unfreeze PFIFO */ ++ nv_mask(dev, 0x002504, 0x00000001, 0x00000000); ++ /* restore ctxprog to normal */ ++ nv_wr32(dev, 0x400324, 0x00000000); ++ nv_wr32(dev, 0x400328, 0x0070009c); /* set flag 0x1c */ ++ /* unblock it if necessary */ ++ if (nv_rd32(dev, 0x400308) == 0x0050001c) ++ nv_mask(dev, 0x400824, 0x10000000, 0x10000000); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); ++ kfree(info); + } +- +diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c +index 08e6b11..5bf5503 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_fb.c ++++ b/drivers/gpu/drm/nouveau/nvc0_fb.c +@@ -32,6 +32,30 @@ struct nvc0_fb_priv { + dma_addr_t r100c10; + }; + ++static inline void ++nvc0_mfb_subp_isr(struct drm_device *dev, int unit, int subp) ++{ ++ u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400); ++ u32 stat = nv_rd32(dev, subp_base + 0x020); ++ ++ if (stat) { ++ NV_INFO(dev, "PMFB%d_SUBP%d: 0x%08x\n", unit, subp, stat); ++ nv_wr32(dev, subp_base + 0x020, stat); ++ } ++} ++ ++static void ++nvc0_mfb_isr(struct drm_device *dev) ++{ ++ u32 units = nv_rd32(dev, 0x00017c); ++ while (units) { ++ u32 subp, unit = ffs(units) - 1; ++ for (subp = 0; subp < 2; subp++) ++ nvc0_mfb_subp_isr(dev, unit, subp); ++ units &= ~(1 << unit); ++ } ++} ++ + static void + nvc0_fb_destroy(struct drm_device *dev) + { +@@ -39,6 +63,8 @@ nvc0_fb_destroy(struct drm_device *dev) + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + struct nvc0_fb_priv *priv = pfb->priv; + ++ nouveau_irq_unregister(dev, 25); ++ + if (priv->r100c10_page) { + pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); +@@ -74,6 +100,7 @@ nvc0_fb_create(struct drm_device *dev) + return -EFAULT; + } + ++ nouveau_irq_register(dev, 25, nvc0_mfb_isr); + return 0; + } + +diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c +index 6f9f341..dcbe0d5 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_fifo.c ++++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c +@@ -322,7 +322,7 @@ nvc0_fifo_init(struct drm_device *dev) + } + + /* PSUBFIFO[n] */ +- for (i = 0; i < 3; i++) { ++ for (i = 0; i < priv->spoon_nr; i++) { + nv_mask(dev, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); + nv_wr32(dev, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ + nv_wr32(dev, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTR_EN */ +diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c +index 5b2f6f4..4b8d0b3 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_graph.c ++++ b/drivers/gpu/drm/nouveau/nvc0_graph.c +@@ -390,7 +390,7 @@ nvc0_graph_init_gpc_0(struct drm_device *dev) + } + + nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918); +- nv_wr32(dev, GPC_BCAST(0x08ac), priv->rop_nr); ++ nv_wr32(dev, GPC_BCAST(0x08ac), nv_rd32(dev, 0x100800)); + } + + static void +@@ -700,22 +700,6 @@ nvc0_graph_isr(struct drm_device *dev) + nv_wr32(dev, 0x400500, 0x00010001); + } + +-static void +-nvc0_runk140_isr(struct drm_device *dev) +-{ +- u32 units = nv_rd32(dev, 0x00017c) & 0x1f; +- +- while (units) { +- u32 unit = ffs(units) - 1; +- u32 reg = 0x140000 + unit * 0x2000; +- u32 st0 = nv_mask(dev, reg + 0x1020, 0, 0); +- u32 st1 = nv_mask(dev, reg + 0x1420, 0, 0); +- +- NV_DEBUG(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1); +- units &= ~(1 << unit); +- } -} - static int - nv40_graph_context_new(struct nouveau_channel *chan, int engine) - { -@@ -163,16 +80,16 @@ nv40_graph_context_del(struct nouveau_channel *chan, int engine) - struct nouveau_gpuobj *grctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ u32 inst = 0x01000000 | (grctx->pinst >> 4); - unsigned long flags; + nvc0_graph_create_fw(struct drm_device *dev, const char *fwname, + struct nvc0_graph_fuc *fuc) +@@ -764,7 +748,6 @@ nvc0_graph_destroy(struct drm_device *dev, int engine) + } - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -- nv04_graph_fifo_access(dev, false); -- -- /* Unload the context if it's the currently active one */ -- if (nv40_graph_channel(dev) == chan) -- nv40_graph_unload_context(dev); -- -- nv04_graph_fifo_access(dev, true); -+ nv_mask(dev, 0x400720, 0x00000000, 0x00000001); -+ if (nv_rd32(dev, 0x40032c) == inst) -+ nv_mask(dev, 0x40032c, 0x01000000, 0x00000000); -+ if (nv_rd32(dev, 0x400330) == inst) -+ nv_mask(dev, 0x400330, 0x01000000, 0x00000000); -+ nv_mask(dev, 0x400720, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + nouveau_irq_unregister(dev, 12); +- nouveau_irq_unregister(dev, 25); - /* Free the context resources */ -@@ -429,9 +346,20 @@ nv40_graph_init(struct drm_device *dev, int engine) + nouveau_gpuobj_ref(NULL, &priv->unk4188b8); + nouveau_gpuobj_ref(NULL, &priv->unk4188b4); +@@ -803,7 +786,6 @@ nvc0_graph_create(struct drm_device *dev) + + NVOBJ_ENGINE_ADD(dev, GR, &priv->base); + nouveau_irq_register(dev, 12, nvc0_graph_isr); +- nouveau_irq_register(dev, 25, nvc0_runk140_isr); + + if (nouveau_ctxfw) { + NV_INFO(dev, "PGRAPH: using external firmware\n"); +@@ -864,6 +846,9 @@ nvc0_graph_create(struct drm_device *dev) + case 0xce: /* 4/4/0/0, 4 */ + priv->magic_not_rop_nr = 0x03; + break; ++ case 0xcf: /* 4/0/0/0, 3 */ ++ priv->magic_not_rop_nr = 0x03; ++ break; + } + + if (!priv->magic_not_rop_nr) { +@@ -889,20 +874,3 @@ error: + nvc0_graph_destroy(dev, NVOBJ_ENGINE_GR); + return ret; } +- +-MODULE_FIRMWARE("nouveau/nvc0_fuc409c"); +-MODULE_FIRMWARE("nouveau/nvc0_fuc409d"); +-MODULE_FIRMWARE("nouveau/nvc0_fuc41ac"); +-MODULE_FIRMWARE("nouveau/nvc0_fuc41ad"); +-MODULE_FIRMWARE("nouveau/nvc3_fuc409c"); +-MODULE_FIRMWARE("nouveau/nvc3_fuc409d"); +-MODULE_FIRMWARE("nouveau/nvc3_fuc41ac"); +-MODULE_FIRMWARE("nouveau/nvc3_fuc41ad"); +-MODULE_FIRMWARE("nouveau/nvc4_fuc409c"); +-MODULE_FIRMWARE("nouveau/nvc4_fuc409d"); +-MODULE_FIRMWARE("nouveau/nvc4_fuc41ac"); +-MODULE_FIRMWARE("nouveau/nvc4_fuc41ad"); +-MODULE_FIRMWARE("nouveau/fuc409c"); +-MODULE_FIRMWARE("nouveau/fuc409d"); +-MODULE_FIRMWARE("nouveau/fuc41ac"); +-MODULE_FIRMWARE("nouveau/fuc41ad"); +diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.h b/drivers/gpu/drm/nouveau/nvc0_graph.h +index 55689e9..636fe98 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_graph.h ++++ b/drivers/gpu/drm/nouveau/nvc0_graph.h +@@ -82,6 +82,7 @@ nvc0_graph_class(struct drm_device *dev) + case 0xc3: + case 0xc4: + case 0xce: /* guess, mmio trace shows only 0x9097 state */ ++ case 0xcf: /* guess, mmio trace shows only 0x9097 state */ + return 0x9097; + case 0xc1: + return 0x9197; +diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c +index 31018ea..dd0e6a7 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grctx.c ++++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c +@@ -1678,7 +1678,10 @@ nvc0_grctx_generate_tp(struct drm_device *dev) + nv_wr32(dev, 0x419c04, 0x00000006); + nv_wr32(dev, 0x419c08, 0x00000002); + nv_wr32(dev, 0x419c20, 0x00000000); +- nv_wr32(dev, 0x419cb0, 0x00060048); //XXX: 0xce 0x00020048 ++ if (chipset == 0xce || chipset == 0xcf) ++ nv_wr32(dev, 0x419cb0, 0x00020048); ++ else ++ nv_wr32(dev, 0x419cb0, 0x00060048); + nv_wr32(dev, 0x419ce8, 0x00000000); + nv_wr32(dev, 0x419cf4, 0x00000183); + nv_wr32(dev, 0x419d20, chipset != 0xc1 ? 0x02180000 : 0x12180000); +@@ -1783,11 +1786,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) + nv_wr32(dev, 0x40587c, 0x00000000); - static int --nv40_graph_fini(struct drm_device *dev, int engine) -+nv40_graph_fini(struct drm_device *dev, int engine, bool suspend) - { -- nv40_graph_unload_context(dev); -+ u32 inst = nv_rd32(dev, 0x40032c); -+ if (inst & 0x01000000) { -+ nv_wr32(dev, 0x400720, 0x00000000); -+ nv_wr32(dev, 0x400784, inst); -+ nv_mask(dev, 0x400310, 0x00000020, 0x00000020); -+ nv_mask(dev, 0x400304, 0x00000001, 0x00000001); -+ if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000)) { -+ u32 insn = nv_rd32(dev, 0x400308); -+ NV_ERROR(dev, "PGRAPH: ctxprog timeout 0x%08x\n", insn); + if (1) { +- const u8 chipset_tp_max[] = { 16, 4, 0, 4, 8, 0, 0, 0, +- 16, 0, 0, 0, 0, 0, 8, 0 }; +- u8 max = chipset_tp_max[dev_priv->chipset & 0x0f]; +- u8 tpnr[GPC_MAX]; +- u8 data[TP_MAX]; ++ u8 tpnr[GPC_MAX], data[TP_MAX]; + + memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); + memset(data, 0x1f, sizeof(data)); +@@ -1801,7 +1800,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) + data[tp] = gpc; + } + +- for (i = 0; i < max / 4; i++) ++ for (i = 0; i < 4; i++) + nv_wr32(dev, 0x4060a8 + (i * 4), ((u32 *)data)[i]); + } + +diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc +index 0ec2add..06f5e26 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc ++++ b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc +@@ -77,6 +77,11 @@ chipsets: + .b16 nvc0_gpc_mmio_tail + .b16 nvc0_tpc_mmio_head + .b16 nvc3_tpc_mmio_tail ++.b8 0xcf 0 0 0 ++.b16 nvc0_gpc_mmio_head ++.b16 nvc0_gpc_mmio_tail ++.b16 nvc0_tpc_mmio_head ++.b16 nvcf_tpc_mmio_tail + .b8 0 0 0 0 + + // GPC mmio lists +@@ -134,8 +139,9 @@ mmctx_data(0x000750, 2) + nvc0_tpc_mmio_tail: + mmctx_data(0x000758, 1) + mmctx_data(0x0002c4, 1) +-mmctx_data(0x0004bc, 1) + mmctx_data(0x0006e0, 1) ++nvcf_tpc_mmio_tail: ++mmctx_data(0x0004bc, 1) + nvc3_tpc_mmio_tail: + mmctx_data(0x000544, 1) + nvc1_tpc_mmio_tail: +diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h +index 1896c89..6f82032 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h ++++ b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h +@@ -25,23 +25,26 @@ uint32_t nvc0_grgpc_data[] = { + 0x00000000, + 0x00000000, + 0x000000c0, +- 0x011000b0, +- 0x01640114, ++ 0x011c00bc, ++ 0x01700120, + 0x000000c1, +- 0x011400b0, +- 0x01780114, ++ 0x012000bc, ++ 0x01840120, + 0x000000c3, +- 0x011000b0, +- 0x01740114, ++ 0x011c00bc, ++ 0x01800120, + 0x000000c4, +- 0x011000b0, +- 0x01740114, ++ 0x011c00bc, ++ 0x01800120, + 0x000000c8, +- 0x011000b0, +- 0x01640114, ++ 0x011c00bc, ++ 0x01700120, + 0x000000ce, +- 0x011000b0, +- 0x01740114, ++ 0x011c00bc, ++ 0x01800120, ++ 0x000000cf, ++ 0x011c00bc, ++ 0x017c0120, + 0x00000000, + 0x00000380, + 0x14000400, +@@ -90,8 +93,8 @@ uint32_t nvc0_grgpc_data[] = { + 0x04000750, + 0x00000758, + 0x000002c4, +- 0x000004bc, + 0x000006e0, ++ 0x000004bc, + 0x00000544, + }; + +diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc +index a1a5991..e4f8c7e 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc ++++ b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc +@@ -56,6 +56,9 @@ chipsets: + .b8 0xce 0 0 0 + .b16 nvc0_hub_mmio_head + .b16 nvc0_hub_mmio_tail ++.b8 0xcf 0 0 0 ++.b16 nvc0_hub_mmio_head ++.b16 nvc0_hub_mmio_tail + .b8 0 0 0 0 + + nvc0_hub_mmio_head: +diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h +index b3b541b..241d326 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h ++++ b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h +@@ -23,17 +23,19 @@ uint32_t nvc0_grhub_data[] = { + 0x00000000, + 0x00000000, + 0x000000c0, +- 0x012c0090, ++ 0x01340098, + 0x000000c1, +- 0x01300090, ++ 0x01380098, + 0x000000c3, +- 0x012c0090, ++ 0x01340098, + 0x000000c4, +- 0x012c0090, ++ 0x01340098, + 0x000000c8, +- 0x012c0090, ++ 0x01340098, + 0x000000ce, +- 0x012c0090, ++ 0x01340098, ++ 0x000000cf, ++ 0x01340098, + 0x00000000, + 0x0417e91c, + 0x04400204, +@@ -190,8 +192,6 @@ uint32_t nvc0_grhub_data[] = { + 0x00000000, + 0x00000000, + 0x00000000, +- 0x00000000, +- 0x00000000, + }; + + uint32_t nvc0_grhub_code[] = { +diff --git a/drivers/gpu/drm/nouveau/nvc0_pm.c b/drivers/gpu/drm/nouveau/nvc0_pm.c +new file mode 100644 +index 0000000..929aded +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nvc0_pm.c +@@ -0,0 +1,155 @@ ++/* ++ * 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"), ++ * 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 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) OR AUTHOR(S) 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: Ben Skeggs ++ */ ++ ++#include "drmP.h" ++#include "nouveau_drv.h" ++#include "nouveau_bios.h" ++#include "nouveau_pm.h" ++ ++static u32 read_div(struct drm_device *, int, u32, u32); ++static u32 read_pll(struct drm_device *, u32); ++ ++static u32 ++read_vco(struct drm_device *dev, u32 dsrc) ++{ ++ u32 ssrc = nv_rd32(dev, dsrc); ++ if (!(ssrc & 0x00000100)) ++ return read_pll(dev, 0x00e800); ++ return read_pll(dev, 0x00e820); ++} ++ ++static u32 ++read_pll(struct drm_device *dev, u32 pll) ++{ ++ u32 ctrl = nv_rd32(dev, pll + 0); ++ u32 coef = nv_rd32(dev, pll + 4); ++ u32 P = (coef & 0x003f0000) >> 16; ++ u32 N = (coef & 0x0000ff00) >> 8; ++ u32 M = (coef & 0x000000ff) >> 0; ++ u32 sclk, doff; ++ ++ if (!(ctrl & 0x00000001)) ++ return 0; ++ ++ switch (pll & 0xfff000) { ++ case 0x00e000: ++ sclk = 27000; ++ P = 1; ++ break; ++ case 0x137000: ++ doff = (pll - 0x137000) / 0x20; ++ sclk = read_div(dev, doff, 0x137120, 0x137140); ++ break; ++ case 0x132000: ++ switch (pll) { ++ case 0x132000: ++ sclk = read_pll(dev, 0x132020); ++ break; ++ case 0x132020: ++ sclk = read_div(dev, 0, 0x137320, 0x137330); ++ break; ++ default: ++ return 0; + } -+ nv_mask(dev, 0x40032c, 0x01000000, 0x00000000); ++ break; ++ default: ++ return 0; + } - return 0; - } - -diff --git a/drivers/gpu/drm/nouveau/nv40_mpeg.c b/drivers/gpu/drm/nouveau/nv40_mpeg.c -index 6d2af29..ad03a0e 100644 ---- a/drivers/gpu/drm/nouveau/nv40_mpeg.c -+++ b/drivers/gpu/drm/nouveau/nv40_mpeg.c -@@ -137,7 +137,7 @@ nv40_mpeg_init(struct drm_device *dev, int engine) - } - - static int --nv40_mpeg_fini(struct drm_device *dev, int engine) -+nv40_mpeg_fini(struct drm_device *dev, int engine, bool suspend) ++ ++ return sclk * N / M / P; ++} ++ ++static u32 ++read_div(struct drm_device *dev, int doff, u32 dsrc, u32 dctl) ++{ ++ u32 ssrc = nv_rd32(dev, dsrc + (doff * 4)); ++ u32 sctl = nv_rd32(dev, dctl + (doff * 4)); ++ ++ switch (ssrc & 0x00000003) { ++ case 0: ++ if ((ssrc & 0x00030000) != 0x00030000) ++ return 27000; ++ return 108000; ++ case 2: ++ return 100000; ++ case 3: ++ if (sctl & 0x80000000) { ++ u32 sclk = read_vco(dev, dsrc + (doff * 4)); ++ u32 sdiv = (sctl & 0x0000003f) + 2; ++ return (sclk * 2) / sdiv; ++ } ++ ++ return read_vco(dev, dsrc + (doff * 4)); ++ default: ++ return 0; ++ } ++} ++ ++static u32 ++read_mem(struct drm_device *dev) ++{ ++ u32 ssel = nv_rd32(dev, 0x1373f0); ++ if (ssel & 0x00000001) ++ return read_div(dev, 0, 0x137300, 0x137310); ++ return read_pll(dev, 0x132000); ++} ++ ++static u32 ++read_clk(struct drm_device *dev, int clk) ++{ ++ u32 sctl = nv_rd32(dev, 0x137250 + (clk * 4)); ++ u32 ssel = nv_rd32(dev, 0x137100); ++ u32 sclk, sdiv; ++ ++ if (ssel & (1 << clk)) { ++ if (clk < 7) ++ sclk = read_pll(dev, 0x137000 + (clk * 0x20)); ++ else ++ sclk = read_pll(dev, 0x1370e0); ++ sdiv = ((sctl & 0x00003f00) >> 8) + 2; ++ } else { ++ sclk = read_div(dev, clk, 0x137160, 0x1371d0); ++ sdiv = ((sctl & 0x0000003f) >> 0) + 2; ++ } ++ ++ if (sctl & 0x80000000) ++ return (sclk * 2) / sdiv; ++ return sclk; ++} ++ ++int ++nvc0_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) ++{ ++ perflvl->shader = read_clk(dev, 0x00); ++ perflvl->core = perflvl->shader / 2; ++ perflvl->memory = read_mem(dev); ++ perflvl->rop = read_clk(dev, 0x01); ++ perflvl->hub07 = read_clk(dev, 0x02); ++ perflvl->hub06 = read_clk(dev, 0x07); ++ perflvl->hub01 = read_clk(dev, 0x08); ++ perflvl->copy = read_clk(dev, 0x09); ++ perflvl->daemon = read_clk(dev, 0x0c); ++ perflvl->vdec = read_clk(dev, 0x0e); ++ return 0; ++} +diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c +index e45a24d..edbfe93 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_vram.c ++++ b/drivers/gpu/drm/nouveau/nvc0_vram.c +@@ -61,7 +61,7 @@ nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, + u32 type, struct nouveau_mem **pmem) { - /*XXX: context save? */ - nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); -diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c -index e25cbb4..d27dcf0 100644 ---- a/drivers/gpu/drm/nouveau/nv50_graph.c -+++ b/drivers/gpu/drm/nouveau/nv50_graph.c -@@ -125,7 +125,6 @@ static void - nv50_graph_init_reset(struct drm_device *dev) - { - uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21); -- - NV_DEBUG(dev, "\n"); + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_mm *mm = dev_priv->engine.vram.mm; ++ struct nouveau_mm *mm = &dev_priv->engine.vram.mm; + struct nouveau_mm_node *r; + struct nouveau_mem *mem; + int ret; +@@ -106,12 +106,50 @@ nvc0_vram_init(struct drm_device *dev) + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; + const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ + const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ +- u32 length; ++ u32 parts = nv_rd32(dev, 0x121c74); ++ u32 bsize = nv_rd32(dev, 0x10f20c); ++ u32 offset, length; ++ bool uniform = true; ++ int ret, i; - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e); -@@ -255,9 +254,13 @@ nv50_graph_init(struct drm_device *dev, int engine) +- dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; +- dev_priv->vram_size *= nv_rd32(dev, 0x121c74); ++ NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800)); ++ NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize); + +- length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; ++ /* read amount of vram attached to each memory controller */ ++ for (i = 0; i < parts; i++) { ++ u32 psize = nv_rd32(dev, 0x11020c + (i * 0x1000)); ++ if (psize != bsize) { ++ if (psize < bsize) ++ bsize = psize; ++ uniform = false; ++ } ++ ++ NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", i, psize); ++ ++ dev_priv->vram_size += (u64)psize << 20; ++ } ++ ++ /* if all controllers have the same amount attached, there's no holes */ ++ if (uniform) { ++ offset = rsvd_head; ++ length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; ++ return nouveau_mm_init(&vram->mm, offset, length, 1); ++ } + +- return nouveau_mm_init(&vram->mm, rsvd_head, length, 1); ++ /* otherwise, address lowest common amount from 0GiB */ ++ ret = nouveau_mm_init(&vram->mm, rsvd_head, (bsize << 8) * parts, 1); ++ if (ret) ++ return ret; ++ ++ /* and the rest starting from (8GiB + common_size) */ ++ offset = (0x0200000000ULL >> 12) + (bsize << 8); ++ length = (dev_priv->vram_size >> 12) - (bsize << 8) - rsvd_tail; ++ ++ ret = nouveau_mm_init(&vram->mm, offset, length, 0); ++ if (ret) { ++ nouveau_mm_fini(&vram->mm); ++ return ret; ++ } ++ ++ return 0; } - - static int --nv50_graph_fini(struct drm_device *dev, int engine) -+nv50_graph_fini(struct drm_device *dev, int engine, bool suspend) - { -- NV_DEBUG(dev, "\n"); -+ nv_mask(dev, 0x400500, 0x00010001, 0x00000000); -+ if (!nv_wait(dev, 0x400700, ~0, 0) && suspend) { -+ nv_mask(dev, 0x400500, 0x00010001, 0x00010001); +diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c +new file mode 100644 +index 0000000..23d63b4 +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nvd0_display.c +@@ -0,0 +1,1473 @@ ++/* ++ * 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"), ++ * 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 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) OR AUTHOR(S) 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: Ben Skeggs ++ */ ++ ++#include ++ ++#include "drmP.h" ++#include "drm_crtc_helper.h" ++ ++#include "nouveau_drv.h" ++#include "nouveau_connector.h" ++#include "nouveau_encoder.h" ++#include "nouveau_crtc.h" ++#include "nouveau_dma.h" ++#include "nouveau_fb.h" ++#include "nv50_display.h" ++ ++struct nvd0_display { ++ struct nouveau_gpuobj *mem; ++ struct { ++ dma_addr_t handle; ++ u32 *ptr; ++ } evo[1]; ++ ++ struct tasklet_struct tasklet; ++ u32 modeset; ++}; ++ ++static struct nvd0_display * ++nvd0_display(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ return dev_priv->engine.display.priv; ++} ++ ++static inline int ++evo_icmd(struct drm_device *dev, int id, u32 mthd, u32 data) ++{ ++ int ret = 0; ++ nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000001); ++ nv_wr32(dev, 0x610704 + (id * 0x10), data); ++ nv_mask(dev, 0x610704 + (id * 0x10), 0x80000ffc, 0x80000000 | mthd); ++ if (!nv_wait(dev, 0x610704 + (id * 0x10), 0x80000000, 0x00000000)) ++ ret = -EBUSY; ++ nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000000); ++ return ret; ++} ++ ++static u32 * ++evo_wait(struct drm_device *dev, int id, int nr) ++{ ++ struct nvd0_display *disp = nvd0_display(dev); ++ u32 put = nv_rd32(dev, 0x640000 + (id * 0x1000)) / 4; ++ ++ if (put + nr >= (PAGE_SIZE / 4)) { ++ disp->evo[id].ptr[put] = 0x20000000; ++ ++ nv_wr32(dev, 0x640000 + (id * 0x1000), 0x00000000); ++ if (!nv_wait(dev, 0x640004 + (id * 0x1000), ~0, 0x00000000)) { ++ NV_ERROR(dev, "evo %d dma stalled\n", id); ++ return NULL; ++ } ++ ++ put = 0; ++ } ++ ++ return disp->evo[id].ptr + put; ++} ++ ++static void ++evo_kick(u32 *push, struct drm_device *dev, int id) ++{ ++ struct nvd0_display *disp = nvd0_display(dev); ++ nv_wr32(dev, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2); ++} ++ ++#define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m)) ++#define evo_data(p,d) *((p)++) = (d) ++ ++static struct drm_crtc * ++nvd0_display_crtc_get(struct drm_encoder *encoder) ++{ ++ return nouveau_encoder(encoder)->crtc; ++} ++ ++/****************************************************************************** ++ * CRTC ++ *****************************************************************************/ ++static int ++nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update) ++{ ++ struct drm_device *dev = nv_crtc->base.dev; ++ u32 *push, mode; ++ ++ mode = 0x00000000; ++ if (on) { ++ /* 0x11: 6bpc dynamic 2x2 ++ * 0x13: 8bpc dynamic 2x2 ++ * 0x19: 6bpc static 2x2 ++ * 0x1b: 8bpc static 2x2 ++ * 0x21: 6bpc temporal ++ * 0x23: 8bpc temporal ++ */ ++ mode = 0x00000011; ++ } ++ ++ push = evo_wait(dev, 0, 4); ++ if (push) { ++ evo_mthd(push, 0x0490 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, mode); ++ if (update) { ++ evo_mthd(push, 0x0080, 1); ++ evo_data(push, 0x00000000); ++ } ++ evo_kick(push, dev, 0); ++ } ++ ++ return 0; ++} ++ ++static int ++nvd0_crtc_set_scale(struct nouveau_crtc *nv_crtc, int type, bool update) ++{ ++ struct drm_display_mode *mode = &nv_crtc->base.mode; ++ struct drm_device *dev = nv_crtc->base.dev; ++ struct nouveau_connector *nv_connector; ++ u32 *push, outX, outY; ++ ++ outX = mode->hdisplay; ++ outY = mode->vdisplay; ++ ++ nv_connector = nouveau_crtc_connector_get(nv_crtc); ++ if (nv_connector && nv_connector->native_mode) { ++ struct drm_display_mode *native = nv_connector->native_mode; ++ u32 xratio = (native->hdisplay << 19) / mode->hdisplay; ++ u32 yratio = (native->vdisplay << 19) / mode->vdisplay; ++ ++ switch (type) { ++ case DRM_MODE_SCALE_ASPECT: ++ if (xratio > yratio) { ++ outX = (mode->hdisplay * yratio) >> 19; ++ outY = (mode->vdisplay * yratio) >> 19; ++ } else { ++ outX = (mode->hdisplay * xratio) >> 19; ++ outY = (mode->vdisplay * xratio) >> 19; ++ } ++ break; ++ case DRM_MODE_SCALE_FULLSCREEN: ++ outX = native->hdisplay; ++ outY = native->vdisplay; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ push = evo_wait(dev, 0, 16); ++ if (push) { ++ evo_mthd(push, 0x04c0 + (nv_crtc->index * 0x300), 3); ++ evo_data(push, (outY << 16) | outX); ++ evo_data(push, (outY << 16) | outX); ++ evo_data(push, (outY << 16) | outX); ++ evo_mthd(push, 0x0494 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x04b8 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, (mode->vdisplay << 16) | mode->hdisplay); ++ if (update) { ++ evo_mthd(push, 0x0080, 1); ++ evo_data(push, 0x00000000); ++ } ++ evo_kick(push, dev, 0); ++ } ++ ++ return 0; ++} ++ ++static int ++nvd0_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb, ++ int x, int y, bool update) ++{ ++ struct nouveau_framebuffer *nvfb = nouveau_framebuffer(fb); ++ u32 *push; ++ ++ push = evo_wait(fb->dev, 0, 16); ++ if (push) { ++ evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, nvfb->nvbo->bo.offset >> 8); ++ evo_mthd(push, 0x0468 + (nv_crtc->index * 0x300), 4); ++ evo_data(push, (fb->height << 16) | fb->width); ++ evo_data(push, nvfb->r_pitch); ++ evo_data(push, nvfb->r_format); ++ evo_data(push, nvfb->r_dma); ++ evo_mthd(push, 0x04b0 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, (y << 16) | x); ++ if (update) { ++ evo_mthd(push, 0x0080, 1); ++ evo_data(push, 0x00000000); ++ } ++ evo_kick(push, fb->dev, 0); ++ } ++ ++ nv_crtc->fb.tile_flags = nvfb->r_dma; ++ return 0; ++} ++ ++static void ++nvd0_crtc_cursor_show(struct nouveau_crtc *nv_crtc, bool show, bool update) ++{ ++ struct drm_device *dev = nv_crtc->base.dev; ++ u32 *push = evo_wait(dev, 0, 16); ++ if (push) { ++ if (show) { ++ evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2); ++ evo_data(push, 0x85000000); ++ evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8); ++ evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1); ++ evo_data(push, NvEvoVRAM); ++ } else { ++ evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, 0x05000000); ++ evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1); ++ evo_data(push, 0x00000000); ++ } ++ ++ if (update) { ++ evo_mthd(push, 0x0080, 1); ++ evo_data(push, 0x00000000); ++ } ++ ++ evo_kick(push, dev, 0); ++ } ++} ++ ++static void ++nvd0_crtc_dpms(struct drm_crtc *crtc, int mode) ++{ ++} ++ ++static void ++nvd0_crtc_prepare(struct drm_crtc *crtc) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ u32 *push; ++ ++ push = evo_wait(crtc->dev, 0, 2); ++ if (push) { ++ evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, 0x03000000); ++ evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1); ++ evo_data(push, 0x00000000); ++ evo_kick(push, crtc->dev, 0); ++ } ++ ++ nvd0_crtc_cursor_show(nv_crtc, false, false); ++} ++ ++static void ++nvd0_crtc_commit(struct drm_crtc *crtc) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ u32 *push; ++ ++ push = evo_wait(crtc->dev, 0, 32); ++ if (push) { ++ evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, nv_crtc->fb.tile_flags); ++ evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4); ++ evo_data(push, 0x83000000); ++ evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8); ++ evo_data(push, 0x00000000); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1); ++ evo_data(push, NvEvoVRAM); ++ evo_mthd(push, 0x0430 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, 0xffffff00); ++ evo_kick(push, crtc->dev, 0); ++ } ++ ++ nvd0_crtc_cursor_show(nv_crtc, nv_crtc->cursor.visible, true); ++} ++ ++static bool ++nvd0_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ return true; ++} ++ ++static int ++nvd0_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) ++{ ++ struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb); ++ int ret; ++ ++ ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM); ++ if (ret) ++ return ret; ++ ++ if (old_fb) { ++ nvfb = nouveau_framebuffer(old_fb); ++ nouveau_bo_unpin(nvfb->nvbo); ++ } ++ ++ return 0; ++} ++ ++static int ++nvd0_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode, ++ struct drm_display_mode *mode, int x, int y, ++ struct drm_framebuffer *old_fb) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ struct nouveau_connector *nv_connector; ++ u32 htotal = mode->htotal; ++ u32 vtotal = mode->vtotal; ++ u32 hsyncw = mode->hsync_end - mode->hsync_start - 1; ++ u32 vsyncw = mode->vsync_end - mode->vsync_start - 1; ++ u32 hfrntp = mode->hsync_start - mode->hdisplay; ++ u32 vfrntp = mode->vsync_start - mode->vdisplay; ++ u32 hbackp = mode->htotal - mode->hsync_end; ++ u32 vbackp = mode->vtotal - mode->vsync_end; ++ u32 hss2be = hsyncw + hbackp; ++ u32 vss2be = vsyncw + vbackp; ++ u32 hss2de = htotal - hfrntp; ++ u32 vss2de = vtotal - vfrntp; ++ u32 syncs, *push; ++ int ret; ++ ++ syncs = 0x00000001; ++ if (mode->flags & DRM_MODE_FLAG_NHSYNC) ++ syncs |= 0x00000008; ++ if (mode->flags & DRM_MODE_FLAG_NVSYNC) ++ syncs |= 0x00000010; ++ ++ ret = nvd0_crtc_swap_fbs(crtc, old_fb); ++ if (ret) ++ return ret; ++ ++ push = evo_wait(crtc->dev, 0, 64); ++ if (push) { ++ evo_mthd(push, 0x0410 + (nv_crtc->index * 0x300), 5); ++ evo_data(push, 0x00000000); ++ evo_data(push, (vtotal << 16) | htotal); ++ evo_data(push, (vsyncw << 16) | hsyncw); ++ evo_data(push, (vss2be << 16) | hss2be); ++ evo_data(push, (vss2de << 16) | hss2de); ++ evo_mthd(push, 0x042c + (nv_crtc->index * 0x300), 1); ++ evo_data(push, 0x00000000); /* ??? */ ++ evo_mthd(push, 0x0450 + (nv_crtc->index * 0x300), 3); ++ evo_data(push, mode->clock * 1000); ++ evo_data(push, 0x00200000); /* ??? */ ++ evo_data(push, mode->clock * 1000); ++ evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, syncs); ++ evo_kick(push, crtc->dev, 0); ++ } ++ ++ nv_connector = nouveau_crtc_connector_get(nv_crtc); ++ nvd0_crtc_set_dither(nv_crtc, nv_connector->use_dithering, false); ++ nvd0_crtc_set_scale(nv_crtc, nv_connector->scaling_mode, false); ++ nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, false); ++ return 0; ++} ++ ++static int ++nvd0_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, ++ struct drm_framebuffer *old_fb) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ int ret; ++ ++ if (!crtc->fb) { ++ NV_DEBUG_KMS(crtc->dev, "No FB bound\n"); ++ return 0; ++ } ++ ++ ret = nvd0_crtc_swap_fbs(crtc, old_fb); ++ if (ret) ++ return ret; ++ ++ nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, true); ++ return 0; ++} ++ ++static int ++nvd0_crtc_mode_set_base_atomic(struct drm_crtc *crtc, ++ struct drm_framebuffer *fb, int x, int y, ++ enum mode_set_atomic state) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ nvd0_crtc_set_image(nv_crtc, fb, x, y, true); ++ return 0; ++} ++ ++static void ++nvd0_crtc_lut_load(struct drm_crtc *crtc) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo); ++ int i; ++ ++ for (i = 0; i < 256; i++) { ++ writew(0x6000 + (nv_crtc->lut.r[i] >> 2), lut + (i * 0x20) + 0); ++ writew(0x6000 + (nv_crtc->lut.g[i] >> 2), lut + (i * 0x20) + 2); ++ writew(0x6000 + (nv_crtc->lut.b[i] >> 2), lut + (i * 0x20) + 4); ++ } ++} ++ ++static int ++nvd0_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, ++ uint32_t handle, uint32_t width, uint32_t height) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ struct drm_device *dev = crtc->dev; ++ struct drm_gem_object *gem; ++ struct nouveau_bo *nvbo; ++ bool visible = (handle != 0); ++ int i, ret = 0; ++ ++ if (visible) { ++ if (width != 64 || height != 64) ++ return -EINVAL; ++ ++ gem = drm_gem_object_lookup(dev, file_priv, handle); ++ if (unlikely(!gem)) ++ return -ENOENT; ++ nvbo = nouveau_gem_object(gem); ++ ++ ret = nouveau_bo_map(nvbo); ++ if (ret == 0) { ++ for (i = 0; i < 64 * 64; i++) { ++ u32 v = nouveau_bo_rd32(nvbo, i); ++ nouveau_bo_wr32(nv_crtc->cursor.nvbo, i, v); ++ } ++ nouveau_bo_unmap(nvbo); ++ } ++ ++ drm_gem_object_unreference_unlocked(gem); ++ } ++ ++ if (visible != nv_crtc->cursor.visible) { ++ nvd0_crtc_cursor_show(nv_crtc, visible, true); ++ nv_crtc->cursor.visible = visible; ++ } ++ ++ return ret; ++} ++ ++static int ++nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ const u32 data = (y << 16) | x; ++ ++ nv_wr32(crtc->dev, 0x64d084 + (nv_crtc->index * 0x1000), data); ++ nv_wr32(crtc->dev, 0x64d080 + (nv_crtc->index * 0x1000), 0x00000000); ++ return 0; ++} ++ ++static void ++nvd0_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, ++ uint32_t start, uint32_t size) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ u32 end = max(start + size, (u32)256); ++ u32 i; ++ ++ for (i = start; i < end; i++) { ++ nv_crtc->lut.r[i] = r[i]; ++ nv_crtc->lut.g[i] = g[i]; ++ nv_crtc->lut.b[i] = b[i]; ++ } ++ ++ nvd0_crtc_lut_load(crtc); ++} ++ ++static void ++nvd0_crtc_destroy(struct drm_crtc *crtc) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ nouveau_bo_unmap(nv_crtc->cursor.nvbo); ++ nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); ++ nouveau_bo_unmap(nv_crtc->lut.nvbo); ++ nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); ++ drm_crtc_cleanup(crtc); ++ kfree(crtc); ++} ++ ++static const struct drm_crtc_helper_funcs nvd0_crtc_hfunc = { ++ .dpms = nvd0_crtc_dpms, ++ .prepare = nvd0_crtc_prepare, ++ .commit = nvd0_crtc_commit, ++ .mode_fixup = nvd0_crtc_mode_fixup, ++ .mode_set = nvd0_crtc_mode_set, ++ .mode_set_base = nvd0_crtc_mode_set_base, ++ .mode_set_base_atomic = nvd0_crtc_mode_set_base_atomic, ++ .load_lut = nvd0_crtc_lut_load, ++}; ++ ++static const struct drm_crtc_funcs nvd0_crtc_func = { ++ .cursor_set = nvd0_crtc_cursor_set, ++ .cursor_move = nvd0_crtc_cursor_move, ++ .gamma_set = nvd0_crtc_gamma_set, ++ .set_config = drm_crtc_helper_set_config, ++ .destroy = nvd0_crtc_destroy, ++}; ++ ++static void ++nvd0_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y) ++{ ++} ++ ++static void ++nvd0_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset) ++{ ++} ++ ++static int ++nvd0_crtc_create(struct drm_device *dev, int index) ++{ ++ struct nouveau_crtc *nv_crtc; ++ struct drm_crtc *crtc; ++ int ret, i; ++ ++ nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL); ++ if (!nv_crtc) ++ return -ENOMEM; ++ ++ nv_crtc->index = index; ++ nv_crtc->set_dither = nvd0_crtc_set_dither; ++ nv_crtc->set_scale = nvd0_crtc_set_scale; ++ nv_crtc->cursor.set_offset = nvd0_cursor_set_offset; ++ nv_crtc->cursor.set_pos = nvd0_cursor_set_pos; ++ for (i = 0; i < 256; i++) { ++ nv_crtc->lut.r[i] = i << 8; ++ nv_crtc->lut.g[i] = i << 8; ++ nv_crtc->lut.b[i] = i << 8; ++ } ++ ++ crtc = &nv_crtc->base; ++ drm_crtc_init(dev, crtc, &nvd0_crtc_func); ++ drm_crtc_helper_add(crtc, &nvd0_crtc_hfunc); ++ drm_mode_crtc_set_gamma_size(crtc, 256); ++ ++ ret = nouveau_bo_new(dev, 64 * 64 * 4, 0x100, TTM_PL_FLAG_VRAM, ++ 0, 0x0000, &nv_crtc->cursor.nvbo); ++ if (!ret) { ++ ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); ++ if (!ret) ++ ret = nouveau_bo_map(nv_crtc->cursor.nvbo); ++ if (ret) ++ nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); ++ } ++ ++ if (ret) ++ goto out; ++ ++ ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM, ++ 0, 0x0000, &nv_crtc->lut.nvbo); ++ if (!ret) { ++ ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); ++ if (!ret) ++ ret = nouveau_bo_map(nv_crtc->lut.nvbo); ++ if (ret) ++ nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); ++ } ++ ++ if (ret) ++ goto out; ++ ++ nvd0_crtc_lut_load(crtc); ++ ++out: ++ if (ret) ++ nvd0_crtc_destroy(crtc); ++ return ret; ++} ++ ++/****************************************************************************** ++ * DAC ++ *****************************************************************************/ ++static void ++nvd0_dac_dpms(struct drm_encoder *encoder, int mode) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct drm_device *dev = encoder->dev; ++ int or = nv_encoder->or; ++ u32 dpms_ctrl; ++ ++ dpms_ctrl = 0x80000000; ++ if (mode == DRM_MODE_DPMS_STANDBY || mode == DRM_MODE_DPMS_OFF) ++ dpms_ctrl |= 0x00000001; ++ if (mode == DRM_MODE_DPMS_SUSPEND || mode == DRM_MODE_DPMS_OFF) ++ dpms_ctrl |= 0x00000004; ++ ++ nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000); ++ nv_mask(dev, 0x61a004 + (or * 0x0800), 0xc000007f, dpms_ctrl); ++ nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000); ++} ++ ++static bool ++nvd0_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_connector *nv_connector; ++ ++ nv_connector = nouveau_encoder_connector_get(nv_encoder); ++ if (nv_connector && nv_connector->native_mode) { ++ if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) { ++ int id = adjusted_mode->base.id; ++ *adjusted_mode = *nv_connector->native_mode; ++ adjusted_mode->base.id = id; ++ } ++ } ++ ++ return true; ++} ++ ++static void ++nvd0_dac_prepare(struct drm_encoder *encoder) ++{ ++} ++ ++static void ++nvd0_dac_commit(struct drm_encoder *encoder) ++{ ++} ++ ++static void ++nvd0_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); ++ u32 *push; ++ ++ nvd0_dac_dpms(encoder, DRM_MODE_DPMS_ON); ++ ++ push = evo_wait(encoder->dev, 0, 4); ++ if (push) { ++ evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 2); ++ evo_data(push, 1 << nv_crtc->index); ++ evo_data(push, 0x00ff); ++ evo_kick(push, encoder->dev, 0); ++ } ++ ++ nv_encoder->crtc = encoder->crtc; ++} ++ ++static void ++nvd0_dac_disconnect(struct drm_encoder *encoder) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct drm_device *dev = encoder->dev; ++ u32 *push; ++ ++ if (nv_encoder->crtc) { ++ nvd0_crtc_prepare(nv_encoder->crtc); ++ ++ push = evo_wait(dev, 0, 4); ++ if (push) { ++ evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 1); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x0080, 1); ++ evo_data(push, 0x00000000); ++ evo_kick(push, dev, 0); ++ } ++ ++ nv_encoder->crtc = NULL; ++ } ++} ++ ++static enum drm_connector_status ++nvd0_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) ++{ ++ enum drm_connector_status status = connector_status_disconnected; ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct drm_device *dev = encoder->dev; ++ int or = nv_encoder->or; ++ u32 load; ++ ++ nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00100000); ++ udelay(9500); ++ nv_wr32(dev, 0x61a00c + (or * 0x800), 0x80000000); ++ ++ load = nv_rd32(dev, 0x61a00c + (or * 0x800)); ++ if ((load & 0x38000000) == 0x38000000) ++ status = connector_status_connected; ++ ++ nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00000000); ++ return status; ++} ++ ++static void ++nvd0_dac_destroy(struct drm_encoder *encoder) ++{ ++ drm_encoder_cleanup(encoder); ++ kfree(encoder); ++} ++ ++static const struct drm_encoder_helper_funcs nvd0_dac_hfunc = { ++ .dpms = nvd0_dac_dpms, ++ .mode_fixup = nvd0_dac_mode_fixup, ++ .prepare = nvd0_dac_prepare, ++ .commit = nvd0_dac_commit, ++ .mode_set = nvd0_dac_mode_set, ++ .disable = nvd0_dac_disconnect, ++ .get_crtc = nvd0_display_crtc_get, ++ .detect = nvd0_dac_detect ++}; ++ ++static const struct drm_encoder_funcs nvd0_dac_func = { ++ .destroy = nvd0_dac_destroy, ++}; ++ ++static int ++nvd0_dac_create(struct drm_connector *connector, struct dcb_entry *dcbe) ++{ ++ struct drm_device *dev = connector->dev; ++ struct nouveau_encoder *nv_encoder; ++ struct drm_encoder *encoder; ++ ++ nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); ++ if (!nv_encoder) ++ return -ENOMEM; ++ nv_encoder->dcb = dcbe; ++ nv_encoder->or = ffs(dcbe->or) - 1; ++ ++ encoder = to_drm_encoder(nv_encoder); ++ encoder->possible_crtcs = dcbe->heads; ++ encoder->possible_clones = 0; ++ drm_encoder_init(dev, encoder, &nvd0_dac_func, DRM_MODE_ENCODER_DAC); ++ drm_encoder_helper_add(encoder, &nvd0_dac_hfunc); ++ ++ drm_mode_connector_attach_encoder(connector, encoder); ++ return 0; ++} ++ ++/****************************************************************************** ++ * SOR ++ *****************************************************************************/ ++static void ++nvd0_sor_dpms(struct drm_encoder *encoder, int mode) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct drm_device *dev = encoder->dev; ++ struct drm_encoder *partner; ++ int or = nv_encoder->or; ++ u32 dpms_ctrl; ++ ++ nv_encoder->last_dpms = mode; ++ ++ list_for_each_entry(partner, &dev->mode_config.encoder_list, head) { ++ struct nouveau_encoder *nv_partner = nouveau_encoder(partner); ++ ++ if (partner->encoder_type != DRM_MODE_ENCODER_TMDS) ++ continue; ++ ++ if (nv_partner != nv_encoder && ++ nv_partner->dcb->or == nv_encoder->or) { ++ if (nv_partner->last_dpms == DRM_MODE_DPMS_ON) ++ return; ++ break; ++ } ++ } ++ ++ dpms_ctrl = (mode == DRM_MODE_DPMS_ON); ++ dpms_ctrl |= 0x80000000; ++ ++ nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); ++ nv_mask(dev, 0x61c004 + (or * 0x0800), 0x80000001, dpms_ctrl); ++ nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); ++ nv_wait(dev, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000); ++} ++ ++static bool ++nvd0_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_connector *nv_connector; ++ ++ nv_connector = nouveau_encoder_connector_get(nv_encoder); ++ if (nv_connector && nv_connector->native_mode) { ++ if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) { ++ int id = adjusted_mode->base.id; ++ *adjusted_mode = *nv_connector->native_mode; ++ adjusted_mode->base.id = id; ++ } ++ } ++ ++ return true; ++} ++ ++static void ++nvd0_sor_prepare(struct drm_encoder *encoder) ++{ ++} ++ ++static void ++nvd0_sor_commit(struct drm_encoder *encoder) ++{ ++} ++ ++static void ++nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, ++ struct drm_display_mode *mode) ++{ ++ struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); ++ struct nouveau_connector *nv_connector; ++ struct nvbios *bios = &dev_priv->vbios; ++ u32 mode_ctrl = (1 << nv_crtc->index); ++ u32 *push, or_config; ++ ++ nv_connector = nouveau_encoder_connector_get(nv_encoder); ++ switch (nv_encoder->dcb->type) { ++ case OUTPUT_TMDS: ++ if (nv_encoder->dcb->sorconf.link & 1) { ++ if (mode->clock < 165000) ++ mode_ctrl |= 0x00000100; ++ else ++ mode_ctrl |= 0x00000500; ++ } else { ++ mode_ctrl |= 0x00000200; ++ } ++ ++ or_config = (mode_ctrl & 0x00000f00) >> 8; ++ if (mode->clock >= 165000) ++ or_config |= 0x0100; ++ break; ++ case OUTPUT_LVDS: ++ or_config = (mode_ctrl & 0x00000f00) >> 8; ++ if (bios->fp_no_ddc) { ++ if (bios->fp.dual_link) ++ or_config |= 0x0100; ++ if (bios->fp.if_is_24bit) ++ or_config |= 0x0200; ++ } else { ++ if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) { ++ if (((u8 *)nv_connector->edid)[121] == 2) ++ or_config |= 0x0100; ++ } else ++ if (mode->clock >= bios->fp.duallink_transition_clk) { ++ or_config |= 0x0100; ++ } ++ ++ if (or_config & 0x0100) { ++ if (bios->fp.strapless_is_24bit & 2) ++ or_config |= 0x0200; ++ } else { ++ if (bios->fp.strapless_is_24bit & 1) ++ or_config |= 0x0200; ++ } ++ ++ if (nv_connector->base.display_info.bpc == 8) ++ or_config |= 0x0200; ++ ++ } ++ break; ++ default: ++ BUG_ON(1); ++ break; ++ } ++ ++ nvd0_sor_dpms(encoder, DRM_MODE_DPMS_ON); ++ ++ push = evo_wait(encoder->dev, 0, 4); ++ if (push) { ++ evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 2); ++ evo_data(push, mode_ctrl); ++ evo_data(push, or_config); ++ evo_kick(push, encoder->dev, 0); ++ } ++ ++ nv_encoder->crtc = encoder->crtc; ++} ++ ++static void ++nvd0_sor_disconnect(struct drm_encoder *encoder) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct drm_device *dev = encoder->dev; ++ u32 *push; ++ ++ if (nv_encoder->crtc) { ++ nvd0_crtc_prepare(nv_encoder->crtc); ++ ++ push = evo_wait(dev, 0, 4); ++ if (push) { ++ evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x0080, 1); ++ evo_data(push, 0x00000000); ++ evo_kick(push, dev, 0); ++ } ++ ++ nv_encoder->crtc = NULL; ++ nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; ++ } ++} ++ ++static void ++nvd0_sor_destroy(struct drm_encoder *encoder) ++{ ++ drm_encoder_cleanup(encoder); ++ kfree(encoder); ++} ++ ++static const struct drm_encoder_helper_funcs nvd0_sor_hfunc = { ++ .dpms = nvd0_sor_dpms, ++ .mode_fixup = nvd0_sor_mode_fixup, ++ .prepare = nvd0_sor_prepare, ++ .commit = nvd0_sor_commit, ++ .mode_set = nvd0_sor_mode_set, ++ .disable = nvd0_sor_disconnect, ++ .get_crtc = nvd0_display_crtc_get, ++}; ++ ++static const struct drm_encoder_funcs nvd0_sor_func = { ++ .destroy = nvd0_sor_destroy, ++}; ++ ++static int ++nvd0_sor_create(struct drm_connector *connector, struct dcb_entry *dcbe) ++{ ++ struct drm_device *dev = connector->dev; ++ struct nouveau_encoder *nv_encoder; ++ struct drm_encoder *encoder; ++ ++ nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); ++ if (!nv_encoder) ++ return -ENOMEM; ++ nv_encoder->dcb = dcbe; ++ nv_encoder->or = ffs(dcbe->or) - 1; ++ nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; ++ ++ encoder = to_drm_encoder(nv_encoder); ++ encoder->possible_crtcs = dcbe->heads; ++ encoder->possible_clones = 0; ++ drm_encoder_init(dev, encoder, &nvd0_sor_func, DRM_MODE_ENCODER_TMDS); ++ drm_encoder_helper_add(encoder, &nvd0_sor_hfunc); ++ ++ drm_mode_connector_attach_encoder(connector, encoder); ++ return 0; ++} ++ ++/****************************************************************************** ++ * IRQ ++ *****************************************************************************/ ++static struct dcb_entry * ++lookup_dcb(struct drm_device *dev, int id, u32 mc) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ int type, or, i; ++ ++ if (id < 4) { ++ type = OUTPUT_ANALOG; ++ or = id; ++ } else { ++ switch (mc & 0x00000f00) { ++ case 0x00000000: type = OUTPUT_LVDS; break; ++ case 0x00000100: type = OUTPUT_TMDS; break; ++ case 0x00000200: type = OUTPUT_TMDS; break; ++ case 0x00000500: type = OUTPUT_TMDS; break; ++ default: ++ NV_ERROR(dev, "PDISP: unknown SOR mc 0x%08x\n", mc); ++ return NULL; ++ } ++ ++ or = id - 4; ++ } ++ ++ for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { ++ struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i]; ++ if (dcb->type == type && (dcb->or & (1 << or))) ++ return dcb; ++ } ++ ++ NV_ERROR(dev, "PDISP: DCB for %d/0x%08x not found\n", id, mc); ++ return NULL; ++} ++ ++static void ++nvd0_display_unk1_handler(struct drm_device *dev, u32 crtc, u32 mask) ++{ ++ struct dcb_entry *dcb; ++ int i; ++ ++ for (i = 0; mask && i < 8; i++) { ++ u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20)); ++ if (!(mcc & (1 << crtc))) ++ continue; ++ ++ dcb = lookup_dcb(dev, i, mcc); ++ if (!dcb) ++ continue; ++ ++ nouveau_bios_run_display_table(dev, 0x0000, -1, dcb, crtc); ++ } ++ ++ nv_wr32(dev, 0x6101d4, 0x00000000); ++ nv_wr32(dev, 0x6109d4, 0x00000000); ++ nv_wr32(dev, 0x6101d0, 0x80000000); ++} ++ ++static void ++nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) ++{ ++ struct dcb_entry *dcb; ++ u32 or, tmp, pclk; ++ int i; ++ ++ for (i = 0; mask && i < 8; i++) { ++ u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20)); ++ if (!(mcc & (1 << crtc))) ++ continue; ++ ++ dcb = lookup_dcb(dev, i, mcc); ++ if (!dcb) ++ continue; ++ ++ nouveau_bios_run_display_table(dev, 0x0000, -2, dcb, crtc); ++ } ++ ++ pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000; ++ if (mask & 0x00010000) { ++ nv50_crtc_set_clock(dev, crtc, pclk); ++ } ++ ++ for (i = 0; mask && i < 8; i++) { ++ u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20)); ++ u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20)); ++ if (!(mcp & (1 << crtc))) ++ continue; ++ ++ dcb = lookup_dcb(dev, i, mcp); ++ if (!dcb) ++ continue; ++ or = ffs(dcb->or) - 1; ++ ++ nouveau_bios_run_display_table(dev, cfg, pclk, dcb, crtc); ++ ++ nv_wr32(dev, 0x612200 + (crtc * 0x800), 0x00000000); ++ switch (dcb->type) { ++ case OUTPUT_ANALOG: ++ nv_wr32(dev, 0x612280 + (or * 0x800), 0x00000000); ++ break; ++ case OUTPUT_TMDS: ++ case OUTPUT_LVDS: ++ if (cfg & 0x00000100) ++ tmp = 0x00000101; ++ else ++ tmp = 0x00000000; ++ ++ nv_mask(dev, 0x612300 + (or * 0x800), 0x00000707, tmp); ++ break; ++ default: ++ break; ++ } ++ ++ break; ++ } ++ ++ nv_wr32(dev, 0x6101d4, 0x00000000); ++ nv_wr32(dev, 0x6109d4, 0x00000000); ++ nv_wr32(dev, 0x6101d0, 0x80000000); ++} ++ ++static void ++nvd0_display_unk4_handler(struct drm_device *dev, u32 crtc, u32 mask) ++{ ++ struct dcb_entry *dcb; ++ int pclk, i; ++ ++ pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000; ++ ++ for (i = 0; mask && i < 8; i++) { ++ u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20)); ++ u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20)); ++ if (!(mcp & (1 << crtc))) ++ continue; ++ ++ dcb = lookup_dcb(dev, i, mcp); ++ if (!dcb) ++ continue; ++ ++ nouveau_bios_run_display_table(dev, cfg, -pclk, dcb, crtc); ++ } ++ ++ nv_wr32(dev, 0x6101d4, 0x00000000); ++ nv_wr32(dev, 0x6109d4, 0x00000000); ++ nv_wr32(dev, 0x6101d0, 0x80000000); ++} ++ ++static void ++nvd0_display_bh(unsigned long data) ++{ ++ struct drm_device *dev = (struct drm_device *)data; ++ struct nvd0_display *disp = nvd0_display(dev); ++ u32 mask, crtc; ++ int i; ++ ++ if (drm_debug & (DRM_UT_DRIVER | DRM_UT_KMS)) { ++ NV_INFO(dev, "PDISP: modeset req %d\n", disp->modeset); ++ NV_INFO(dev, " STAT: 0x%08x 0x%08x 0x%08x\n", ++ nv_rd32(dev, 0x6101d0), ++ nv_rd32(dev, 0x6101d4), nv_rd32(dev, 0x6109d4)); ++ for (i = 0; i < 8; i++) { ++ NV_INFO(dev, " %s%d: 0x%08x 0x%08x\n", ++ i < 4 ? "DAC" : "SOR", i, ++ nv_rd32(dev, 0x640180 + (i * 0x20)), ++ nv_rd32(dev, 0x660180 + (i * 0x20))); ++ } ++ } ++ ++ mask = nv_rd32(dev, 0x6101d4); ++ crtc = 0; ++ if (!mask) { ++ mask = nv_rd32(dev, 0x6109d4); ++ crtc = 1; ++ } ++ ++ if (disp->modeset & 0x00000001) ++ nvd0_display_unk1_handler(dev, crtc, mask); ++ if (disp->modeset & 0x00000002) ++ nvd0_display_unk2_handler(dev, crtc, mask); ++ if (disp->modeset & 0x00000004) ++ nvd0_display_unk4_handler(dev, crtc, mask); ++} ++ ++static void ++nvd0_display_intr(struct drm_device *dev) ++{ ++ struct nvd0_display *disp = nvd0_display(dev); ++ u32 intr = nv_rd32(dev, 0x610088); ++ ++ if (intr & 0x00000002) { ++ u32 stat = nv_rd32(dev, 0x61009c); ++ int chid = ffs(stat) - 1; ++ if (chid >= 0) { ++ u32 mthd = nv_rd32(dev, 0x6101f0 + (chid * 12)); ++ u32 data = nv_rd32(dev, 0x6101f4 + (chid * 12)); ++ u32 unkn = nv_rd32(dev, 0x6101f8 + (chid * 12)); ++ ++ NV_INFO(dev, "EvoCh: chid %d mthd 0x%04x data 0x%08x " ++ "0x%08x 0x%08x\n", ++ chid, (mthd & 0x0000ffc), data, mthd, unkn); ++ nv_wr32(dev, 0x61009c, (1 << chid)); ++ nv_wr32(dev, 0x6101f0 + (chid * 12), 0x90000000); ++ } ++ ++ intr &= ~0x00000002; ++ } ++ ++ if (intr & 0x00100000) { ++ u32 stat = nv_rd32(dev, 0x6100ac); ++ ++ if (stat & 0x00000007) { ++ disp->modeset = stat; ++ tasklet_schedule(&disp->tasklet); ++ ++ nv_wr32(dev, 0x6100ac, (stat & 0x00000007)); ++ stat &= ~0x00000007; ++ } ++ ++ if (stat) { ++ NV_INFO(dev, "PDISP: unknown intr24 0x%08x\n", stat); ++ nv_wr32(dev, 0x6100ac, stat); ++ } ++ ++ intr &= ~0x00100000; ++ } ++ ++ if (intr & 0x01000000) { ++ u32 stat = nv_rd32(dev, 0x6100bc); ++ nv_wr32(dev, 0x6100bc, stat); ++ intr &= ~0x01000000; ++ } ++ ++ if (intr & 0x02000000) { ++ u32 stat = nv_rd32(dev, 0x6108bc); ++ nv_wr32(dev, 0x6108bc, stat); ++ intr &= ~0x02000000; ++ } ++ ++ if (intr) ++ NV_INFO(dev, "PDISP: unknown intr 0x%08x\n", intr); ++} ++ ++/****************************************************************************** ++ * Init ++ *****************************************************************************/ ++static void ++nvd0_display_fini(struct drm_device *dev) ++{ ++ int i; ++ ++ /* fini cursors */ ++ for (i = 14; i >= 13; i--) { ++ if (!(nv_rd32(dev, 0x610490 + (i * 0x10)) & 0x00000001)) ++ continue; ++ ++ nv_mask(dev, 0x610490 + (i * 0x10), 0x00000001, 0x00000000); ++ nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00000000); ++ nv_mask(dev, 0x610090, 1 << i, 0x00000000); ++ nv_mask(dev, 0x6100a0, 1 << i, 0x00000000); ++ } ++ ++ /* fini master */ ++ if (nv_rd32(dev, 0x610490) & 0x00000010) { ++ nv_mask(dev, 0x610490, 0x00000010, 0x00000000); ++ nv_mask(dev, 0x610490, 0x00000003, 0x00000000); ++ nv_wait(dev, 0x610490, 0x80000000, 0x00000000); ++ nv_mask(dev, 0x610090, 0x00000001, 0x00000000); ++ nv_mask(dev, 0x6100a0, 0x00000001, 0x00000000); ++ } ++} ++ ++int ++nvd0_display_init(struct drm_device *dev) ++{ ++ struct nvd0_display *disp = nvd0_display(dev); ++ u32 *push; ++ int i; ++ ++ if (nv_rd32(dev, 0x6100ac) & 0x00000100) { ++ nv_wr32(dev, 0x6100ac, 0x00000100); ++ nv_mask(dev, 0x6194e8, 0x00000001, 0x00000000); ++ if (!nv_wait(dev, 0x6194e8, 0x00000002, 0x00000000)) { ++ NV_ERROR(dev, "PDISP: 0x6194e8 0x%08x\n", ++ nv_rd32(dev, 0x6194e8)); ++ return -EBUSY; ++ } ++ } ++ ++ /* nfi what these are exactly, i do know that SOR_MODE_CTRL won't ++ * work at all unless you do the SOR part below. ++ */ ++ for (i = 0; i < 3; i++) { ++ u32 dac = nv_rd32(dev, 0x61a000 + (i * 0x800)); ++ nv_wr32(dev, 0x6101c0 + (i * 0x800), dac); ++ } ++ ++ for (i = 0; i < 4; i++) { ++ u32 sor = nv_rd32(dev, 0x61c000 + (i * 0x800)); ++ nv_wr32(dev, 0x6301c4 + (i * 0x800), sor); ++ } ++ ++ for (i = 0; i < 2; i++) { ++ u32 crtc0 = nv_rd32(dev, 0x616104 + (i * 0x800)); ++ u32 crtc1 = nv_rd32(dev, 0x616108 + (i * 0x800)); ++ u32 crtc2 = nv_rd32(dev, 0x61610c + (i * 0x800)); ++ nv_wr32(dev, 0x6101b4 + (i * 0x800), crtc0); ++ nv_wr32(dev, 0x6101b8 + (i * 0x800), crtc1); ++ nv_wr32(dev, 0x6101bc + (i * 0x800), crtc2); ++ } ++ ++ /* point at our hash table / objects, enable interrupts */ ++ nv_wr32(dev, 0x610010, (disp->mem->vinst >> 8) | 9); ++ nv_mask(dev, 0x6100b0, 0x00000307, 0x00000307); ++ ++ /* init master */ ++ nv_wr32(dev, 0x610494, (disp->evo[0].handle >> 8) | 3); ++ nv_wr32(dev, 0x610498, 0x00010000); ++ nv_wr32(dev, 0x61049c, 0x00000001); ++ nv_mask(dev, 0x610490, 0x00000010, 0x00000010); ++ nv_wr32(dev, 0x640000, 0x00000000); ++ nv_wr32(dev, 0x610490, 0x01000013); ++ if (!nv_wait(dev, 0x610490, 0x80000000, 0x00000000)) { ++ NV_ERROR(dev, "PDISP: master 0x%08x\n", ++ nv_rd32(dev, 0x610490)); + return -EBUSY; + } - nv50_graph_unload_context(dev); - nv_wr32(dev, 0x40013c, 0x00000000); - return 0; -diff --git a/drivers/gpu/drm/nouveau/nv50_mpeg.c b/drivers/gpu/drm/nouveau/nv50_mpeg.c -index 1dc5913..b57a2d1 100644 ---- a/drivers/gpu/drm/nouveau/nv50_mpeg.c -+++ b/drivers/gpu/drm/nouveau/nv50_mpeg.c -@@ -160,7 +160,7 @@ nv50_mpeg_init(struct drm_device *dev, int engine) - } - - static int --nv50_mpeg_fini(struct drm_device *dev, int engine) -+nv50_mpeg_fini(struct drm_device *dev, int engine, bool suspend) - { - /*XXX: context save for s/r */ - nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); -diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c -index 75b809a..edece9c 100644 ---- a/drivers/gpu/drm/nouveau/nv84_crypt.c -+++ b/drivers/gpu/drm/nouveau/nv84_crypt.c -@@ -138,7 +138,7 @@ nv84_crypt_isr(struct drm_device *dev) - } - - static int --nv84_crypt_fini(struct drm_device *dev, int engine) -+nv84_crypt_fini(struct drm_device *dev, int engine, bool suspend) - { - nv_wr32(dev, 0x102140, 0x00000000); - return 0; -diff --git a/drivers/gpu/drm/nouveau/nva3_copy.c b/drivers/gpu/drm/nouveau/nva3_copy.c -index b86820a..8f356d5 100644 ---- a/drivers/gpu/drm/nouveau/nva3_copy.c -+++ b/drivers/gpu/drm/nouveau/nva3_copy.c -@@ -140,7 +140,7 @@ nva3_copy_init(struct drm_device *dev, int engine) - } - - static int --nva3_copy_fini(struct drm_device *dev, int engine) -+nva3_copy_fini(struct drm_device *dev, int engine, bool suspend) - { - nv_mask(dev, 0x104048, 0x00000003, 0x00000000); - -diff --git a/drivers/gpu/drm/nouveau/nvc0_copy.c b/drivers/gpu/drm/nouveau/nvc0_copy.c -index 208fa7a..4d58c33 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_copy.c -+++ b/drivers/gpu/drm/nouveau/nvc0_copy.c -@@ -127,7 +127,7 @@ nvc0_copy_init(struct drm_device *dev, int engine) - } - - static int --nvc0_copy_fini(struct drm_device *dev, int engine) -+nvc0_copy_fini(struct drm_device *dev, int engine, bool suspend) - { - struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); - -diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c -index ca6db20..69c6522 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_graph.c -+++ b/drivers/gpu/drm/nouveau/nvc0_graph.c -@@ -248,7 +248,7 @@ nvc0_graph_object_new(struct nouveau_channel *chan, int engine, - } - - static int --nvc0_graph_fini(struct drm_device *dev, int engine) -+nvc0_graph_fini(struct drm_device *dev, int engine, bool suspend) - { - return 0; - } ++ nv_mask(dev, 0x610090, 0x00000001, 0x00000001); ++ nv_mask(dev, 0x6100a0, 0x00000001, 0x00000001); ++ ++ /* init cursors */ ++ for (i = 13; i <= 14; i++) { ++ nv_wr32(dev, 0x610490 + (i * 0x10), 0x00000001); ++ if (!nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00010000)) { ++ NV_ERROR(dev, "PDISP: curs%d 0x%08x\n", i, ++ nv_rd32(dev, 0x610490 + (i * 0x10))); ++ return -EBUSY; ++ } ++ ++ nv_mask(dev, 0x610090, 1 << i, 1 << i); ++ nv_mask(dev, 0x6100a0, 1 << i, 1 << i); ++ } ++ ++ push = evo_wait(dev, 0, 32); ++ if (!push) ++ return -EBUSY; ++ evo_mthd(push, 0x0088, 1); ++ evo_data(push, NvEvoSync); ++ evo_mthd(push, 0x0084, 1); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x0084, 1); ++ evo_data(push, 0x80000000); ++ evo_mthd(push, 0x008c, 1); ++ evo_data(push, 0x00000000); ++ evo_kick(push, dev, 0); ++ ++ return 0; ++} ++ ++void ++nvd0_display_destroy(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvd0_display *disp = nvd0_display(dev); ++ struct pci_dev *pdev = dev->pdev; ++ ++ nvd0_display_fini(dev); ++ ++ pci_free_consistent(pdev, PAGE_SIZE, disp->evo[0].ptr, disp->evo[0].handle); ++ nouveau_gpuobj_ref(NULL, &disp->mem); ++ nouveau_irq_unregister(dev, 26); ++ ++ dev_priv->engine.display.priv = NULL; ++ kfree(disp); ++} ++ ++int ++nvd0_display_create(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; ++ struct dcb_table *dcb = &dev_priv->vbios.dcb; ++ struct drm_connector *connector, *tmp; ++ struct pci_dev *pdev = dev->pdev; ++ struct nvd0_display *disp; ++ struct dcb_entry *dcbe; ++ int ret, i; ++ ++ disp = kzalloc(sizeof(*disp), GFP_KERNEL); ++ if (!disp) ++ return -ENOMEM; ++ dev_priv->engine.display.priv = disp; ++ ++ /* create crtc objects to represent the hw heads */ ++ for (i = 0; i < 2; i++) { ++ ret = nvd0_crtc_create(dev, i); ++ if (ret) ++ goto out; ++ } ++ ++ /* create encoder/connector objects based on VBIOS DCB table */ ++ for (i = 0, dcbe = &dcb->entry[0]; i < dcb->entries; i++, dcbe++) { ++ connector = nouveau_connector_create(dev, dcbe->connector); ++ if (IS_ERR(connector)) ++ continue; ++ ++ if (dcbe->location != DCB_LOC_ON_CHIP) { ++ NV_WARN(dev, "skipping off-chip encoder %d/%d\n", ++ dcbe->type, ffs(dcbe->or) - 1); ++ continue; ++ } ++ ++ switch (dcbe->type) { ++ case OUTPUT_TMDS: ++ case OUTPUT_LVDS: ++ nvd0_sor_create(connector, dcbe); ++ break; ++ case OUTPUT_ANALOG: ++ nvd0_dac_create(connector, dcbe); ++ break; ++ default: ++ NV_WARN(dev, "skipping unsupported encoder %d/%d\n", ++ dcbe->type, ffs(dcbe->or) - 1); ++ continue; ++ } ++ } ++ ++ /* cull any connectors we created that don't have an encoder */ ++ list_for_each_entry_safe(connector, tmp, &dev->mode_config.connector_list, head) { ++ if (connector->encoder_ids[0]) ++ continue; ++ ++ NV_WARN(dev, "%s has no encoders, removing\n", ++ drm_get_connector_name(connector)); ++ connector->funcs->destroy(connector); ++ } ++ ++ /* setup interrupt handling */ ++ tasklet_init(&disp->tasklet, nvd0_display_bh, (unsigned long)dev); ++ nouveau_irq_register(dev, 26, nvd0_display_intr); ++ ++ /* hash table and dma objects for the memory areas we care about */ ++ ret = nouveau_gpuobj_new(dev, NULL, 0x4000, 0x10000, ++ NVOBJ_FLAG_ZERO_ALLOC, &disp->mem); ++ if (ret) ++ goto out; ++ ++ nv_wo32(disp->mem, 0x1000, 0x00000049); ++ nv_wo32(disp->mem, 0x1004, (disp->mem->vinst + 0x2000) >> 8); ++ nv_wo32(disp->mem, 0x1008, (disp->mem->vinst + 0x2fff) >> 8); ++ nv_wo32(disp->mem, 0x100c, 0x00000000); ++ nv_wo32(disp->mem, 0x1010, 0x00000000); ++ nv_wo32(disp->mem, 0x1014, 0x00000000); ++ nv_wo32(disp->mem, 0x0000, NvEvoSync); ++ nv_wo32(disp->mem, 0x0004, (0x1000 << 9) | 0x00000001); ++ ++ nv_wo32(disp->mem, 0x1020, 0x00000049); ++ nv_wo32(disp->mem, 0x1024, 0x00000000); ++ nv_wo32(disp->mem, 0x1028, (dev_priv->vram_size - 1) >> 8); ++ nv_wo32(disp->mem, 0x102c, 0x00000000); ++ nv_wo32(disp->mem, 0x1030, 0x00000000); ++ nv_wo32(disp->mem, 0x1034, 0x00000000); ++ nv_wo32(disp->mem, 0x0008, NvEvoVRAM); ++ nv_wo32(disp->mem, 0x000c, (0x1020 << 9) | 0x00000001); ++ ++ nv_wo32(disp->mem, 0x1040, 0x00000009); ++ nv_wo32(disp->mem, 0x1044, 0x00000000); ++ nv_wo32(disp->mem, 0x1048, (dev_priv->vram_size - 1) >> 8); ++ nv_wo32(disp->mem, 0x104c, 0x00000000); ++ nv_wo32(disp->mem, 0x1050, 0x00000000); ++ nv_wo32(disp->mem, 0x1054, 0x00000000); ++ nv_wo32(disp->mem, 0x0010, NvEvoVRAM_LP); ++ nv_wo32(disp->mem, 0x0014, (0x1040 << 9) | 0x00000001); ++ ++ nv_wo32(disp->mem, 0x1060, 0x0fe00009); ++ nv_wo32(disp->mem, 0x1064, 0x00000000); ++ nv_wo32(disp->mem, 0x1068, (dev_priv->vram_size - 1) >> 8); ++ nv_wo32(disp->mem, 0x106c, 0x00000000); ++ nv_wo32(disp->mem, 0x1070, 0x00000000); ++ nv_wo32(disp->mem, 0x1074, 0x00000000); ++ nv_wo32(disp->mem, 0x0018, NvEvoFB32); ++ nv_wo32(disp->mem, 0x001c, (0x1060 << 9) | 0x00000001); ++ ++ pinstmem->flush(dev); ++ ++ /* push buffers for evo channels */ ++ disp->evo[0].ptr = ++ pci_alloc_consistent(pdev, PAGE_SIZE, &disp->evo[0].handle); ++ if (!disp->evo[0].ptr) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ ret = nvd0_display_init(dev); ++ if (ret) ++ goto out; ++ ++out: ++ if (ret) ++ nvd0_display_destroy(dev); ++ return ret; ++} diff --git a/efi-dont-map-boot-services-on-32bit.patch b/efi-dont-map-boot-services-on-32bit.patch new file mode 100644 index 000000000..7cc614992 --- /dev/null +++ b/efi-dont-map-boot-services-on-32bit.patch @@ -0,0 +1,22 @@ +diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c +index 3ae4128..ff7dc70 100644 +--- a/arch/x86/platform/efi/efi.c ++++ b/arch/x86/platform/efi/efi.c +@@ -659,10 +659,13 @@ void __init efi_enter_virtual_mode(void) + + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { + md = p; +- if (!(md->attribute & EFI_MEMORY_RUNTIME) && +- md->type != EFI_BOOT_SERVICES_CODE && +- md->type != EFI_BOOT_SERVICES_DATA) +- continue; ++ if (!(md->attribute & EFI_MEMORY_RUNTIME)) { ++#ifdef CONFIG_X86_64 ++ if (md->type != EFI_BOOT_SERVICES_CODE && ++ md->type != EFI_BOOT_SERVICES_DATA) ++#endif ++ continue; ++ } + + size = md->num_pages << EFI_PAGE_SHIFT; + end = md->phys_addr + size; diff --git a/epoll-fix-spurious-lockdep-warnings.patch b/epoll-fix-spurious-lockdep-warnings.patch index 131796af8..c163a86d7 100644 --- a/epoll-fix-spurious-lockdep-warnings.patch +++ b/epoll-fix-spurious-lockdep-warnings.patch @@ -113,4 +113,4 @@ index f9cfd16..0cb7bc6 100644 -- 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 \ No newline at end of file +More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/hda_intel-prealloc-4mb-dmabuffer.patch b/hda_intel-prealloc-4mb-dmabuffer.patch deleted file mode 100644 index 36e6aca4f..000000000 --- a/hda_intel-prealloc-4mb-dmabuffer.patch +++ /dev/null @@ -1,47 +0,0 @@ -From c69fcbd1f60b0842f7c1ad2c95692ffd19c4932b Mon Sep 17 00:00:00 2001 -From: Kyle McMartin -Date: Mon, 29 Mar 2010 23:56:08 -0400 -Subject: hda_intel-prealloc-4mb-dmabuffer - ---- - sound/pci/hda/hda_intel.c | 14 +++++++++++++- - 1 files changed, 13 insertions(+), 1 deletions(-) - -diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c -index 4bb9067..37db515 100644 ---- a/sound/pci/hda/hda_intel.c -+++ b/sound/pci/hda/hda_intel.c -@@ -1986,6 +1986,7 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, - struct azx_pcm *apcm; - int pcm_dev = cpcm->device; - int s, err; -+ size_t prealloc_min = 64*1024; /* 64KB */ - - if (pcm_dev >= HDA_MAX_PCMS) { - snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", -@@ -2019,10 +2020,21 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, - if (cpcm->stream[s].substreams) - snd_pcm_set_ops(pcm, s, &azx_pcm_ops); - } -+ - /* buffer pre-allocation */ -+ -+ /* subtle, don't allocate a big buffer for modems... -+ * also, don't just test 32BIT_MASK, since azx supports -+ * 64-bit DMA in some cases. -+ */ -+ /* lennart wants a 2.2MB buffer for 2sec of 48khz */ -+ if (pcm->dev_class == SNDRV_PCM_CLASS_GENERIC && -+ chip->pci->dma_mask >= DMA_32BIT_MASK) -+ prealloc_min = 4 * 1024 * 1024; /* 4MB */ -+ - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), -- 1024 * 64, 32 * 1024 * 1024); -+ prealloc_min, 32 * 1024 * 1024); - return 0; - } - --- -1.7.0.1 - diff --git a/hvcs_pi_buf_alloc.patch b/hvcs_pi_buf_alloc.patch new file mode 100644 index 000000000..ecabe49b1 --- /dev/null +++ b/hvcs_pi_buf_alloc.patch @@ -0,0 +1,43 @@ + +The Power platform requires the partner info buffer to be page aligned +otherwise it will fail the partner info hcall with H_PARAMETER. Switch +from using kmalloc to allocate this buffer to __get_free_page to ensure +page alignment. + +Signed-off-by: Brian King +--- + + drivers/tty/hvc/hvcs.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff -puN drivers/tty/hvc/hvcs.c~hvcs_pi_buf_alloc drivers/tty/hvc/hvcs.c +--- linux-2.6/drivers/tty/hvc/hvcs.c~hvcs_pi_buf_alloc 2011-09-09 16:00:25.000000000 -0500 ++++ linux-2.6-bjking1/drivers/tty/hvc/hvcs.c 2011-09-09 16:07:08.000000000 -0500 +@@ -1532,7 +1532,7 @@ static int __devinit hvcs_initialize(voi + goto register_fail; + } + +- hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL); ++ hvcs_pi_buff = (unsigned long *) __get_free_page(GFP_KERNEL); + if (!hvcs_pi_buff) { + rc = -ENOMEM; + goto buff_alloc_fail; +@@ -1548,7 +1548,7 @@ static int __devinit hvcs_initialize(voi + return 0; + + kthread_fail: +- kfree(hvcs_pi_buff); ++ free_page((unsigned long)hvcs_pi_buff); + buff_alloc_fail: + tty_unregister_driver(hvcs_tty_driver); + register_fail: +@@ -1597,7 +1597,7 @@ static void __exit hvcs_module_exit(void + kthread_stop(hvcs_task); + + spin_lock(&hvcs_pi_lock); +- kfree(hvcs_pi_buff); ++ free_page((unsigned long)hvcs_pi_buff); + hvcs_pi_buff = NULL; + spin_unlock(&hvcs_pi_lock); + +_ diff --git a/ideapad-Check-if-acpi-already-handle-backlight.patch b/ideapad-Check-if-acpi-already-handle-backlight.patch new file mode 100644 index 000000000..713e005d8 --- /dev/null +++ b/ideapad-Check-if-acpi-already-handle-backlight.patch @@ -0,0 +1,31 @@ +From d4afc7754a60b885b63ef23fd194984e2d53a4e6 Mon Sep 17 00:00:00 2001 +From: Rene Bollford +Date: Sun, 23 Oct 2011 09:56:42 +0200 +Subject: [PATCH] [PATCH] ideapad: Check if acpi already handle backlight + power to avoid a page fault + +This patch avoid a page fault in the ideapad-laptop extras when +turning the backlight power on or off. + +Signed-off-by: Rene Bolldorf +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/ideapad-laptop.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c +index 0c59541..0d94eec 100644 +--- a/drivers/platform/x86/ideapad-laptop.c ++++ b/drivers/platform/x86/ideapad-laptop.c +@@ -493,6 +493,8 @@ static void ideapad_backlight_notify_power(struct ideapad_private *priv) + unsigned long power; + struct backlight_device *blightdev = priv->blightdev; + ++ if (!blightdev) ++ return; + if (read_ec_data(ideapad_handle, 0x18, &power)) + return; + blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; +-- +1.7.6.4 + diff --git a/iwlagn-fix-ht_params-NULL-pointer-dereference.patch b/iwlagn-fix-ht_params-NULL-pointer-dereference.patch new file mode 100644 index 000000000..4dcf490bb --- /dev/null +++ b/iwlagn-fix-ht_params-NULL-pointer-dereference.patch @@ -0,0 +1,43 @@ +This fix regression introduced by commit: + +commit 15b3f3b006b42a678523cad989bfd60b76bf4403 +Author: Wey-Yi Guy +Date: Fri Jun 3 07:54:13 2011 -0700 + + iwlagn: set smps mode after assoc for 1000 device + +Also remove unneeded brackets on the way. + +Address: +https://bugzilla.redhat.com/show_bug.cgi?id=744155 + +If fix will not get 3.1 release, it should be applied in 3.1 stable. + +Cc: stable@kernel.org # 3.1+ +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +index ca632f9..5004342 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +@@ -296,8 +296,8 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv, + return ret; + } + +- if ((ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION) && +- priv->cfg->ht_params->smps_mode) ++ if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION && ++ priv->cfg->ht_params && priv->cfg->ht_params->smps_mode) + ieee80211_request_smps(ctx->vif, + priv->cfg->ht_params->smps_mode); + +-- +1.7.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index 3b1cd23a5..a96c36874 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,16 +42,16 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 6 +%global baserelease 0 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with -%define real_sublevel 0 +%define real_sublevel 1 # fake_sublevel is the 2.6.x version we're faking %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # Do we have a -stable update to apply? -%define stable_update 8 +%define stable_update 0 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -328,20 +328,6 @@ Summary: The Linux kernel %define kernel_image_elf 1 %endif -%ifarch ia64 -%define all_arch_configs kernel-%{version}-ia64*.config -%define image_install_path boot/efi/EFI/redhat -%define make_target compressed -%define kernel_image vmlinux.gz -%endif - -%ifarch alpha alphaev56 -%define all_arch_configs kernel-%{version}-alpha*.config -%define image_install_path boot -%define make_target vmlinux -%define kernel_image vmlinux -%endif - %ifarch %{arm} %define all_arch_configs kernel-%{version}-arm*.config %define image_install_path boot @@ -424,7 +410,7 @@ Summary: The Linux kernel # Packages that need to be installed before the kernel is, because the %%post # scripts use them. # -%define kernel_prereq fileutils, module-init-tools >= 3.16-2, initscripts >= 8.11.1-1, grubby >= 7.0.10-1 +%define kernel_prereq fileutils, module-init-tools >= 3.16-2, initscripts >= 8.11.1-1, grubby >= 7.0.16-5 %define initrd_prereq dracut >= 001-7 # @@ -517,6 +503,7 @@ Source24: config-rhel-generic Source30: config-x86-generic Source31: config-i686-PAE +Source32: config-x86-32-generic Source40: config-x86_64-generic @@ -525,8 +512,6 @@ Source51: config-powerpc32-generic Source52: config-powerpc32-smp Source53: config-powerpc64 -Source60: config-ia64-generic - Source70: config-s390x Source90: config-sparc64-generic @@ -564,26 +549,23 @@ Patch05: linux-2.6-makefile-after_link.patch %if !%{nopatches} + # revert upstream patches we get via other methods Patch09: linux-2.6-upstream-reverts.patch +# Git trees. # Standalone patches -Patch100: perf-check-ownership.patch - -Patch150: linux-2.6.29-sparc-IOC_TYPECHECK.patch - +Patch100: taint-vbox.patch Patch160: linux-2.6-32bit-mmap-exec-randomization.patch Patch161: linux-2.6-i386-nx-emulation.patch Patch202: linux-2.6-debug-taint-vm.patch -Patch203: linux-2.6-debug-vm-would-have-oomkilled.patch Patch383: linux-2.6-defaults-aspm.patch Patch390: linux-2.6-defaults-acpi-video.patch 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 Patch395: acpi-ensure-thermal-limits-match-cpu-freq.patch Patch396: acpi-sony-nonvs-blacklist.patch @@ -598,10 +580,6 @@ Patch471: floppy-drop-disable_hlt-warning.patch Patch510: linux-2.6-silence-noise.patch Patch530: linux-2.6-silence-fbcon-logo.patch -# from 3.1 -Patch540: x86-pci-reduce-severity-of-host-bridge-window-conflict-warnings.patch - -Patch610: hda_intel-prealloc-4mb-dmabuffer.patch Patch700: linux-2.6-e1000-ich9-montevina.patch @@ -620,6 +598,8 @@ Patch1810: drm-nouveau-updates.patch Patch1824: drm-intel-next.patch # make sure the lvds comes back on lid open Patch1825: drm-intel-make-lvds-work.patch +# hush the i915 fbc noise +Patch1826: drm-i915-fbc-stfu.patch # rhbz#729882, https://bugs.freedesktop.org/attachment.cgi?id=49069 Patch1827: drm-i915-sdvo-lvds-is-digital.patch @@ -627,8 +607,6 @@ Patch1850: drm-lower-severity-radeon-lockup.diff Patch1900: linux-2.6-intel-iommu-igfx.patch -Patch2000: block-stray-block-put-after-teardown.patch - # Quiet boot fixes # silence the ACPI blacklist code Patch2802: linux-2.6-silence-acpi-blacklist.patch @@ -638,9 +616,9 @@ 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: media-DiBcom-protect-the-I2C-bufer-access.patch -Patch2903: media-dib0700-protect-the-dib0700-buffer-access.patch -Patch2904: media-dib0700-correct-error-message.patch +Patch2903: media-DiBcom-protect-the-I2C-bufer-access.patch +Patch2904: media-dib0700-protect-the-dib0700-buffer-access.patch +Patch2905: media-dib0700-correct-error-message.patch Patch3000: rcutree-avoid-false-quiescent-states.patch @@ -653,21 +631,28 @@ Patch12010: add-appleir-usb-driver.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch -Patch12024: usb-add-quirk-for-logitech-webcams.patch -Patch12025: crypto-register-cryptd-first.patch -Patch12028: x86-p4-make-watchdog-and-perf-work-together.patch +Patch12021: udlfb-bind-framebuffer-to-interface.patch -# Runtime power management -Patch12203: linux-2.6-usb-pci-autosuspend.patch -Patch12204: linux-2.6-enable-more-pci-autosuspend.patch +Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch +Patch12024: epoll-fix-spurious-lockdep-warnings.patch +Patch12025: rcu-avoid-just-onlined-cpu-resched.patch +Patch12026: block-stray-block-put-after-teardown.patch +Patch12027: usb-add-quirk-for-logitech-webcams.patch +Patch12029: crypto-register-cryptd-first.patch +Patch12030: epoll-limit-paths.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch -Patch13001: epoll-fix-spurious-lockdep-warnings.patch -Patch13002: epoll-limit-paths.patch +Patch13002: revert-efi-rtclock.patch +Patch13003: efi-dont-map-boot-services-on-32bit.patch -Patch13010: iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch +Patch13007: add-macbookair41-keyboard.patch + +Patch13009: hvcs_pi_buf_alloc.patch + +Patch13013: powerpc-Fix-deadlock-in-icswx-code.patch + +Patch13014: iwlagn-fix-ht_params-NULL-pointer-dereference.patch Patch20000: utrace.patch @@ -675,44 +660,16 @@ Patch20000: utrace.patch Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch -# workaround for issue with gcc-4.6.x -# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45819 -# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45704 -# patch from http://www.delorie.com/tmp/arm-readl.patch -Patch21002: arm-readl.patch - -Patch21003: TEGRA-2.6.40.2-enable-USB-ports.patch - -# rhbz#719607 -Patch21004: vfs-fix-automount-for-negative-autofs-dentries.patch - -# rhbz #740645 -Patch21011: md-dont-delay-reboot-by-1-second-if-no-MD-devices.patch - -# rhbz #496975 -Patch21013: Platform-fix-samsung-laptop-DMI-identification-for-N.patch - -# rhbz #700718 -Patch21015: x86-Save-stack-pointer-in-perf-live-regs-savings.patch -Patch21016: x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch - -#rhbz #708563 -Patch21017: binfmt_elf-fix-PIE-execution-with-random-disabled.patch - #rhbz #722509 -Patch21018: mmc-Always-check-for-lower-base-frequency-quirk-for-.patch +Patch21002: mmc-Always-check-for-lower-base-frequency-quirk-for-.patch #rhbz #735946 Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch -#rhbz 737108 -Patch21030: platform-fix-samsung-brightness-min-max-calculations.patch - #rhbz 748691 -Patch21040: be2net-move-to-new-vlan-model.patch -Patch21041: be2net-non-member-vlan-pkts-not-received-in-promisco.patch -Patch21042: benet-remove-bogus-unlikely-on-vlan-check.patch +Patch21030: be2net-non-member-vlan-pkts-not-received-in-promisco.patch +Patch21031: benet-remove-bogus-unlikely-on-vlan-check.patch #rhbz 749166 Patch21050: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch @@ -725,6 +682,9 @@ Patch21071: WMI-properly-cleanup-devices-to-avoid-crashes.patch #rhbz 728607 Patch21060: elantech.patch +#rhbz 748210 +Patch21061: ideapad-Check-if-acpi-already-handle-backlight.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -776,7 +736,7 @@ operate. %package bootwrapper Summary: Boot wrapper files for generating combined kernel + initrd images Group: Development/System -Requires: gzip +Requires: gzip binutils %description bootwrapper Kernel-bootwrapper contains the wrapper code which makes bootable "zImage" files combining both kernel and initial ramdisk. @@ -845,8 +805,7 @@ AutoReqProv: no\ Requires(pre): /usr/bin/find\ Requires: perl\ %description -n kernel%{?variant}%{?1:-%{1}}-devel\ -This package provides kernel headers and -makefiles sufficient to build modules\ +This package provides kernel headers and makefiles sufficient to build modules\ against the %{?2:%{2} }kernel package.\ %{nil} @@ -1118,26 +1077,21 @@ ApplyOptionalPatch linux-2.6-compile-fixes.patch ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R -ApplyPatch perf-check-ownership.patch - -# -# SPARC64 -# -ApplyPatch linux-2.6.29-sparc-IOC_TYPECHECK.patch +# Architecture patches +# x86(-64) # # ARM # ApplyPatch arm-omap-dt-compat.patch ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch -ApplyPatch arm-readl.patch -ApplyPatch TEGRA-2.6.40.2-enable-USB-ports.patch +ApplyPatch taint-vbox.patch # -# Exec shield +# NX Emulation # -ApplyPatch linux-2.6-i386-nx-emulation.patch ApplyPatch linux-2.6-32bit-mmap-exec-randomization.patch +ApplyPatch linux-2.6-i386-nx-emulation.patch # # bugfixes to drivers and filesystems @@ -1162,14 +1116,12 @@ ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch # ACPI 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-ensure-thermal-limits-match-cpu-freq.patch ApplyPatch acpi-sony-nonvs-blacklist.patch # Various low-impact patches to aid debugging. ApplyPatch linux-2.6-debug-taint-vm.patch -ApplyPatch linux-2.6-debug-vm-would-have-oomkilled.patch # # PCI @@ -1184,10 +1136,10 @@ ApplyPatch linux-2.6-defaults-aspm.patch # ACPI # ALSA -ApplyPatch hda_intel-prealloc-4mb-dmabuffer.patch # Networking + # Misc fixes # The input layer spews crap no-one cares about. ApplyPatch linux-2.6-input-kill-stupid-messages.patch @@ -1207,9 +1159,6 @@ ApplyPatch linux-2.6-silence-noise.patch # Make fbcon not show the penguins with 'quiet' ApplyPatch linux-2.6-silence-fbcon-logo.patch -# Get rid of useless bridge window conflict warnings -ApplyPatch x86-pci-reduce-severity-of-host-bridge-window-conflict-warnings.patch - # Changes to upstream defaults. @@ -1232,14 +1181,13 @@ ApplyOptionalPatch drm-nouveau-updates.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch ApplyPatch drm-intel-make-lvds-work.patch +ApplyPatch drm-i915-fbc-stfu.patch ApplyPatch drm-i915-sdvo-lvds-is-digital.patch ApplyPatch drm-lower-severity-radeon-lockup.diff ApplyPatch linux-2.6-intel-iommu-igfx.patch -ApplyPatch block-stray-block-put-after-teardown.patch - # silence the ACPI blacklist code ApplyPatch linux-2.6-silence-acpi-blacklist.patch @@ -1249,61 +1197,52 @@ 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 media-DiBcom-protect-the-I2C-bufer-access.patch -ApplyPatch media-dib0700-protect-the-dib0700-buffer-access.patch -ApplyPatch media-dib0700-correct-error-message.patch - -# Avoid false quiescent states in rcu. +# Patches headed upstream ApplyPatch rcutree-avoid-false-quiescent-states.patch -# Patches headed upstream ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch add-appleir-usb-driver.patch +ApplyPatch udlfb-bind-framebuffer-to-interface.patch ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch +ApplyPatch epoll-fix-spurious-lockdep-warnings.patch +ApplyPatch epoll-limit-paths.patch +ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch +ApplyPatch block-stray-block-put-after-teardown.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch + ApplyPatch crypto-register-cryptd-first.patch -ApplyPatch x86-p4-make-watchdog-and-perf-work-together.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch -ApplyPatch epoll-fix-spurious-lockdep-warnings.patch -ApplyPatch epoll-limit-paths.patch +ApplyPatch revert-efi-rtclock.patch +ApplyPatch efi-dont-map-boot-services-on-32bit.patch -ApplyPatch iwlagn-check-for-priv--txq-in-iwlagn_wait_tx_queue_empty.patch +ApplyPatch add-macbookair41-keyboard.patch -ApplyPatch utrace.patch +ApplyPatch hvcs_pi_buf_alloc.patch -# rhbz#719607 -ApplyPatch vfs-fix-automount-for-negative-autofs-dentries.patch +ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch -#rhbz 740645 -ApplyPatch md-dont-delay-reboot-by-1-second-if-no-MD-devices.patch - -# rhbz #496675 -ApplyPatch Platform-fix-samsung-laptop-DMI-identification-for-N.patch - -# rhbz #700718 -ApplyPatch x86-Save-stack-pointer-in-perf-live-regs-savings.patch -ApplyPatch x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch - -#rhbz #708563 -ApplyPatch binfmt_elf-fix-PIE-execution-with-random-disabled.patch +ApplyPatch iwlagn-fix-ht_params-NULL-pointer-dereference.patch #rhbz #722509 ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch +ApplyPatch media-DiBcom-protect-the-I2C-bufer-access.patch +ApplyPatch media-dib0700-protect-the-dib0700-buffer-access.patch +ApplyPatch media-dib0700-correct-error-message.patch + +# utrace. +ApplyPatch utrace.patch + #rhbz #735946 ApplyPatch 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch -#rhbz 737108 -ApplyPatch platform-fix-samsung-brightness-min-max-calculations.patch - #rhbz 748691 -ApplyPatch be2net-move-to-new-vlan-model.patch ApplyPatch be2net-non-member-vlan-pkts-not-received-in-promisco.patch ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch @@ -1316,6 +1255,9 @@ ApplyPatch WMI-properly-cleanup-devices-to-avoid-crashes.patch #rhbz 728607 ApplyPatch elantech.patch +#rhbz 748210 +ApplyPatch ideapad-Check-if-acpi-already-handle-backlight.patch + # END OF PATCH APPLICATIONS %endif @@ -1936,6 +1878,9 @@ fi # and build. %changelog +* Mon Nov 07 2011 Dave Jones +- Rebase to 3.1.0 + * Thu Nov 03 2011 Josh Boyer - Add patches queued for 3.2 for elantech driver (rhbz 728607) diff --git a/linux-2.6-crash-driver.patch b/linux-2.6-crash-driver.patch index b8377d321..239f0f6a0 100644 --- a/linux-2.6-crash-driver.patch +++ b/linux-2.6-crash-driver.patch @@ -1,17 +1,17 @@ -From df42d15cd28f468ecd4c30465b98a53cce90617c Mon Sep 17 00:00:00 2001 +From f72d640713d01b3b704c6e84ab49b62f19fc9c22 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Tue, 30 Mar 2010 00:16:25 -0400 -Subject: dev-crash-driver.patch +Subject: [PATCH] dev-crash-driver.patch --- arch/ia64/include/asm/crash.h | 90 +++++++++++++++++++++++++++++ arch/ia64/kernel/ia64_ksyms.c | 3 + arch/x86/include/asm/crash.h | 75 ++++++++++++++++++++++++ arch/x86/mm/ioremap.c | 2 + - drivers/char/Kconfig | 2 + + drivers/char/Kconfig | 3 + drivers/char/Makefile | 2 + drivers/char/crash.c | 128 +++++++++++++++++++++++++++++++++++++++++ - 7 files changed, 302 insertions(+), 0 deletions(-) + 7 files changed, 303 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/include/asm/crash.h create mode 100644 arch/x86/include/asm/crash.h create mode 100644 drivers/char/crash.c @@ -208,7 +208,7 @@ index 0000000..dfcc006 + +#endif /* _ASM_I386_CRASH_H */ diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c -index 5eb1ba7..3e525d2 100644 +index be1ef57..ac659f7 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -24,6 +24,8 @@ @@ -220,6 +220,30 @@ 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 423fd56..e04a561 100644 +--- a/drivers/char/Kconfig ++++ b/drivers/char/Kconfig +@@ -4,6 +4,9 @@ + + menu "Character devices" + ++config CRASH ++ tristate "Crash Utility memory driver" ++ + source "drivers/tty/Kconfig" + + config DEVKMEM +diff --git a/drivers/char/Makefile b/drivers/char/Makefile +index 32762ba..3d5d525 100644 +--- a/drivers/char/Makefile ++++ b/drivers/char/Makefile +@@ -65,3 +65,5 @@ obj-$(CONFIG_JS_RTC) += js-rtc.o + js-rtc-y = rtc.o + + obj-$(CONFIG_TILE_SROM) += tile-srom.o ++ ++obj-$(CONFIG_CRASH) += crash.o diff --git a/drivers/char/crash.c b/drivers/char/crash.c new file mode 100644 index 0000000..e5437de @@ -354,29 +378,6 @@ index 0000000..e5437de +module_exit(crash_cleanup_module); + +MODULE_LICENSE("GPL"); +-- +1.7.6 -diff --git a/drivers/char/Makefile b/drivers/char/Makefile -index ba53ec9..6588b33 100644 ---- a/drivers/char/Makefile -+++ b/drivers/char/Makefile -@@ -98,3 +98,5 @@ obj-$(CONFIG_RAMOOPS) += ramoops.o - - obj-$(CONFIG_JS_RTC) += js-rtc.o - js-rtc-y = rtc.o -+ -+obj-$(CONFIG_CRASH) += crash.o - -diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig -index 04f8b2d..e8fb997 100644 ---- a/drivers/char/Kconfig -+++ b/drivers/char/Kconfig -@@ -4,6 +4,9 @@ - - menu "Character devices" - -+config CRASH -+ tristate "Crash Utility memory driver" -+ - source "drivers/tty/Kconfig" - - config DEVKMEM diff --git a/linux-2.6-debug-vm-would-have-oomkilled.patch b/linux-2.6-debug-vm-would-have-oomkilled.patch deleted file mode 100644 index 8bd05ab06..000000000 --- a/linux-2.6-debug-vm-would-have-oomkilled.patch +++ /dev/null @@ -1,69 +0,0 @@ -From beb764ac03e52eba1a654afb4273fab1f9de3cff Mon Sep 17 00:00:00 2001 -From: Kyle McMartin -Date: Mon, 29 Nov 2010 20:59:14 -0500 -Subject: [PATCH] linux-2.6-debug-vm-would_have_oomkilled - ---- - include/linux/oom.h | 1 + - kernel/sysctl.c | 7 +++++++ - mm/oom_kill.c | 8 ++++++++ - 3 files changed, 16 insertions(+), 0 deletions(-) - -diff --git a/include/linux/oom.h b/include/linux/oom.h -index 5e3aa83..79a27b4 100644 ---- a/include/linux/oom.h -+++ b/include/linux/oom.h -@@ -72,5 +72,6 @@ extern struct task_struct *find_lock_task_mm(struct task_struct *p); - extern int sysctl_oom_dump_tasks; - extern int sysctl_oom_kill_allocating_task; - extern int sysctl_panic_on_oom; -+extern int sysctl_would_have_oomkilled; - #endif /* __KERNEL__*/ - #endif /* _INCLUDE_LINUX_OOM_H */ -diff --git a/kernel/sysctl.c b/kernel/sysctl.c -index 5abfa15..a0fed6d 100644 ---- a/kernel/sysctl.c -+++ b/kernel/sysctl.c -@@ -1000,6 +1000,13 @@ static struct ctl_table vm_table[] = { - .proc_handler = proc_dointvec, - }, - { -+ .procname = "would_have_oomkilled", -+ .data = &sysctl_would_have_oomkilled, -+ .maxlen = sizeof(sysctl_would_have_oomkilled), -+ .mode = 0644, -+ .proc_handler = proc_dointvec, -+ }, -+ { - .procname = "overcommit_ratio", - .data = &sysctl_overcommit_ratio, - .maxlen = sizeof(sysctl_overcommit_ratio), -diff --git a/mm/oom_kill.c b/mm/oom_kill.c -index 7dcca55..281ac39 100644 ---- a/mm/oom_kill.c -+++ b/mm/oom_kill.c -@@ -35,6 +35,7 @@ - int sysctl_panic_on_oom; - int sysctl_oom_kill_allocating_task; - int sysctl_oom_dump_tasks = 1; -+int sysctl_would_have_oomkilled; - static DEFINE_SPINLOCK(zone_scan_lock); - - #ifdef CONFIG_NUMA -@@ -477,6 +478,13 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, - } - - task_lock(p); -+ if (sysctl_would_have_oomkilled) { -+ printk(KERN_ERR "%s: would have killed process %d (%s), but continuing instead...\n", -+ __func__, task_pid_nr(p), p->comm); -+ task_unlock(p); -+ return 0; -+ } -+ - pr_err("%s: Kill process %d (%s) score %d or sacrifice child\n", - message, task_pid_nr(p), p->comm, points); - task_unlock(p); --- -1.7.3.2 - diff --git a/linux-2.6-intel-iommu-igfx.patch b/linux-2.6-intel-iommu-igfx.patch index 44fd14186..b2f8f19e3 100644 --- a/linux-2.6-intel-iommu-igfx.patch +++ b/linux-2.6-intel-iommu-igfx.patch @@ -43,8 +43,8 @@ index e7848a0..9914485 100644 for io virtual address below 32 bit forcing dual diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 4173125..8f36786 100644 ---- a/drivers/pci/intel-iommu.c -+++ b/drivers/pci/intel-iommu.c +--- a/drivers/iommu/intel-iommu.c ++++ b/drivers/iommu/intel-iommu.c @@ -340,7 +340,8 @@ int dmar_disabled = 0; int dmar_disabled = 1; #endif /*CONFIG_DMAR_DEFAULT_ON*/ diff --git a/linux-2.6-silence-noise.patch b/linux-2.6-silence-noise.patch index 8aba3cdab..1e4d7c57f 100644 --- a/linux-2.6-silence-noise.patch +++ b/linux-2.6-silence-noise.patch @@ -46,8 +46,8 @@ Signed-off-by: Dave Jones + * In case of error we but don't return the error code immediately. + * Below we will return -EPROTONOSUPPORT */ -- if (err && printk_ratelimit()) -- printk(KERN_ERR "can: request_module " +- if (err) +- printk_ratelimited(KERN_ERR "can: request_module " - "(can-proto-%d) failed.\n", protocol); cp = can_get_proto(protocol); diff --git a/linux-2.6.29-sparc-IOC_TYPECHECK.patch b/linux-2.6.29-sparc-IOC_TYPECHECK.patch deleted file mode 100644 index d73c30adc..000000000 --- a/linux-2.6.29-sparc-IOC_TYPECHECK.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -up vanilla-2.6.29-rc7-git2/arch/sparc/include/asm/ioctl.h.BAD vanilla-2.6.29-rc7-git2/arch/sparc/include/asm/ioctl.h ---- vanilla-2.6.29-rc7-git2/arch/sparc/include/asm/ioctl.h.BAD 2009-03-09 17:01:32.000000000 -0400 -+++ vanilla-2.6.29-rc7-git2/arch/sparc/include/asm/ioctl.h 2009-03-09 16:52:27.000000000 -0400 -@@ -41,6 +41,17 @@ - ((nr) << _IOC_NRSHIFT) | \ - ((size) << _IOC_SIZESHIFT)) - -+#ifdef __KERNEL__ -+/* provoke compile error for invalid uses of size argument */ -+extern unsigned int __invalid_size_argument_for_IOC; -+#define _IOC_TYPECHECK(t) \ -+ ((sizeof(t) == sizeof(t[1]) && \ -+ sizeof(t) < (1 << _IOC_SIZEBITS)) ? \ -+ sizeof(t) : __invalid_size_argument_for_IOC) -+#else -+#define _IOC_TYPECHECK(t) (sizeof(t)) -+#endif -+ - #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) - #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) - #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) diff --git a/linux-2.6.30-no-pcspkr-modalias.patch b/linux-2.6.30-no-pcspkr-modalias.patch index c703b8844..439269cef 100644 --- a/linux-2.6.30-no-pcspkr-modalias.patch +++ b/linux-2.6.30-no-pcspkr-modalias.patch @@ -1,11 +1,12 @@ -diff -up linux-2.6.30.noarch/drivers/input/misc/pcspkr.c.jx linux-2.6.30.noarch/drivers/input/misc/pcspkr.c ---- linux-2.6.30.noarch/drivers/input/misc/pcspkr.c.jx 2009-07-28 16:54:44.000000000 -0400 -+++ linux-2.6.30.noarch/drivers/input/misc/pcspkr.c 2009-07-28 16:59:36.000000000 -0400 -@@ -23,7 +23,6 @@ +diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c +index 34f4d2e..3e40c70 100644 +--- a/drivers/input/misc/pcspkr.c ++++ b/drivers/input/misc/pcspkr.c +@@ -24,7 +24,6 @@ MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("PC Speaker beeper driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:pcspkr"); - #if defined(CONFIG_MIPS) || defined(CONFIG_X86) - /* Use the global PIT lock ! */ + static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) + { diff --git a/media-DiBcom-protect-the-I2C-bufer-access.patch b/media-DiBcom-protect-the-I2C-bufer-access.patch index dc988bb18..1b2a54b86 100644 --- a/media-DiBcom-protect-the-I2C-bufer-access.patch +++ b/media-DiBcom-protect-the-I2C-bufer-access.patch @@ -1,7 +1,10 @@ -From 4aa9d354534c2fcbb06170f5968f762aa9bdd0f6 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher -Date: Wed, 3 Aug 2011 15:08:21 -0300 -Subject: [PATCH 1/3] [media] DiBcom: protect the I2C bufer access +Date: Wed, 3 Aug 2011 15:08:21 +0000 (-0300) +Subject: [media] DiBcom: protect the I2C bufer access +X-Git-Tag: next-20110927~67^2~4^2~225 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=79fcce3230b140f7675f8529ee53fe2f9644f902 + +[media] DiBcom: protect the I2C bufer access This patch protects the I2C buffer access in order to manage concurrent access. This protection is done using mutex. @@ -16,15 +19,6 @@ Signed-off-by: Olivier Grenie Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- - drivers/media/dvb/frontends/dib0070.c | 37 +++++- - drivers/media/dvb/frontends/dib0090.c | 70 +++++++++-- - drivers/media/dvb/frontends/dib7000m.c | 27 ++++- - drivers/media/dvb/frontends/dib7000p.c | 32 +++++- - drivers/media/dvb/frontends/dib8000.c | 72 ++++++++++-- - drivers/media/dvb/frontends/dib9000.c | 164 +++++++++++++++++++++++--- - drivers/media/dvb/frontends/dibx000_common.c | 76 ++++++++++-- - drivers/media/dvb/frontends/dibx000_common.h | 1 + - 8 files changed, 412 insertions(+), 67 deletions(-) diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c index 1d47d4d..dc1cb17 100644 @@ -341,7 +335,7 @@ index 79cb1c2..dbb76d7 100644 st->timf_default = cfg->bw->timf; diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c -index 0c9f40c..292bc19 100644 +index a64a538..4eb9c2b 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -10,6 +10,7 @@ @@ -434,8 +428,8 @@ index 0c9f40c..292bc19 100644 + more common) */ + st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent; - dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr); - + /* FIXME: make sure the dev.parent field is initialized, or else + request_firmware() will hit an OOPS (this should be moved somewhere diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c index 7d2ea11..fe284d5 100644 --- a/drivers/media/dvb/frontends/dib8000.c @@ -1154,6 +1148,3 @@ index f031165..5e01147 100644 }; extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, --- -1.7.6.4 - diff --git a/media-dib0700-correct-error-message.patch b/media-dib0700-correct-error-message.patch index f40a4fa12..5e5d3bfa2 100644 --- a/media-dib0700-correct-error-message.patch +++ b/media-dib0700-correct-error-message.patch @@ -1,7 +1,10 @@ -From e4f0158142e4b23939d9444d8af80ff20692f7a5 Mon Sep 17 00:00:00 2001 From: Olivier Grenie -Date: Thu, 4 Aug 2011 16:10:03 -0300 -Subject: [PATCH 3/3] [media] dib0700: correct error message +Date: Thu, 4 Aug 2011 16:10:03 +0000 (-0300) +Subject: [media] dib0700: correct error message +X-Git-Tag: next-20110927~67^2~4^2~223 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=680417bb318adc5f1f8f392730776176fbcdedd8 + +[media] dib0700: correct error message The goal of this patch is to correct a previous patch. In case of error, the err() function should be used instead of dprintk() function. @@ -12,8 +15,6 @@ the err() function should be used instead of dprintk() function. Signed-off-by: Olivier Grenie Signed-off-by: Mauro Carvalho Chehab --- - drivers/media/dvb/dvb-usb/dib0700_core.c | 18 +++++++++--------- - 1 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index a224e94..b693ed1 100644 @@ -100,6 +101,3 @@ index a224e94..b693ed1 100644 return 0; } --- -1.7.6.4 - diff --git a/media-dib0700-protect-the-dib0700-buffer-access.patch b/media-dib0700-protect-the-dib0700-buffer-access.patch index e63f58c75..109cab8ec 100644 --- a/media-dib0700-protect-the-dib0700-buffer-access.patch +++ b/media-dib0700-protect-the-dib0700-buffer-access.patch @@ -1,7 +1,10 @@ -From 9e3419029b4c660298928a6f03002daae6c055a6 Mon Sep 17 00:00:00 2001 From: Olivier Grenie -Date: Mon, 1 Aug 2011 15:45:58 -0300 -Subject: [PATCH 2/3] [media] dib0700: protect the dib0700 buffer access +Date: Mon, 1 Aug 2011 15:45:58 +0000 (-0300) +Subject: [media] dib0700: protect the dib0700 buffer access +X-Git-Tag: next-20110927~67^2~4^2~224 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=bff469f4167fdabfe15294f375577d7eadbaa1bb + +[media] dib0700: protect the dib0700 buffer access This patch protects the common buffer access inside the dib0700 in order to manage concurrent access. This protection is done using mutex. @@ -15,8 +18,6 @@ Signed-off-by: Patrick Boettcher [mchehab@redhat.com: dprint requires 3 arguments. Replaced by dib_info] Signed-off-by: Mauro Carvalho Chehab --- - drivers/media/dvb/dvb-usb/dib0700_core.c | 81 ++++++++++++++++++++++++++--- - 1 files changed, 72 insertions(+), 9 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index 5eb91b4..a224e94 100644 @@ -245,6 +246,3 @@ index 5eb91b4..a224e94 100644 return ret; } --- -1.7.6.4 - diff --git a/perf-check-ownership.patch b/perf-check-ownership.patch deleted file mode 100644 index 93ed66085..000000000 --- a/perf-check-ownership.patch +++ /dev/null @@ -1,62 +0,0 @@ -commit 069e3725dd9be3b759a98e8c80ac5fc38b392b23 -Author: Arnaldo Carvalho de Melo -Date: Tue Aug 9 12:42:13 2011 -0300 - - perf tools: Check $HOME/.perfconfig ownership - - Just like we do already for perf.data files. - - Requested-by: Ingo Molnar - Cc: Ben Hutchings - Cc: Christian Ohm - Cc: David Ahern - Cc: Frederic Weisbecker - Cc: Jonathan Nieder - Cc: Mike Galbraith - Cc: Paul Mackerras - Cc: Peter Zijlstra - Cc: Stephane Eranian - Link: http://lkml.kernel.org/n/tip-qgokmxsmvppwpc5404qhyk7e@git.kernel.org - Signed-off-by: Arnaldo Carvalho de Melo - -diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c -index 6c86eca..fe02903 100644 ---- a/tools/perf/util/config.c -+++ b/tools/perf/util/config.c -@@ -413,13 +413,32 @@ int perf_config(config_fn_t fn, void *data) - home = getenv("HOME"); - if (perf_config_global() && home) { - char *user_config = strdup(mkpath("%s/.perfconfig", home)); -- if (!access(user_config, R_OK)) { -- ret += perf_config_from_file(fn, user_config, data); -- found += 1; -+ struct stat st; -+ -+ if (user_config == NULL) { -+ warning("Not enough memory to process %s/.perfconfig, " -+ "ignoring it.", home); -+ goto out; -+ } -+ -+ if (stat(user_config, &st) < 0) -+ goto out_free; -+ -+ if (st.st_uid && (st.st_uid != geteuid())) { -+ warning("File %s not owned by current user or root, " -+ "ignoring it.", user_config); -+ goto out_free; - } -+ -+ if (!st.st_size) -+ goto out_free; -+ -+ ret += perf_config_from_file(fn, user_config, data); -+ found += 1; -+out_free: - free(user_config); - } -- -+out: - if (found == 0) - return -1; - return ret; diff --git a/powerpc-Fix-deadlock-in-icswx-code.patch b/powerpc-Fix-deadlock-in-icswx-code.patch new file mode 100644 index 000000000..a2ce3cf76 --- /dev/null +++ b/powerpc-Fix-deadlock-in-icswx-code.patch @@ -0,0 +1,74 @@ +From patchwork Wed Sep 14 19:43:15 2011 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: powerpc: Fix deadlock in icswx code +Date: Wed, 14 Sep 2011 09:43:15 -0000 +From: Anton Blanchard +X-Patchwork-Id: 114701 +Message-Id: <20110915054315.5e5ae062@kryten> +To: benh@kernel.crashing.org, paulus@samba.org +Cc: linuxppc-dev@lists.ozlabs.org + +The icswx code introduced an A-B B-A deadlock: + + CPU0 CPU1 + ---- ---- +lock(&anon_vma->mutex); + lock(&mm->mmap_sem); + lock(&anon_vma->mutex); +lock(&mm->mmap_sem); + +Instead of using the mmap_sem to keep mm_users constant, take the +page table spinlock. + +Signed-off-by: Anton Blanchard +Cc: + +--- + + +diff --git a/arch/powerpc/mm/mmu_context_hash64.c b/arch/powerpc/mm/mmu_context_hash64.c +index 3bafc3d..4ff587e 100644 +--- a/arch/powerpc/mm/mmu_context_hash64.c ++++ b/arch/powerpc/mm/mmu_context_hash64.c +@@ -136,8 +136,8 @@ int use_cop(unsigned long acop, struct mm_struct *mm) + if (!mm || !acop) + return -EINVAL; + +- /* We need to make sure mm_users doesn't change */ +- down_read(&mm->mmap_sem); ++ /* The page_table_lock ensures mm_users won't change under us */ ++ spin_lock(&mm->page_table_lock); + spin_lock(mm->context.cop_lockp); + + if (mm->context.cop_pid == COP_PID_NONE) { +@@ -164,7 +164,7 @@ int use_cop(unsigned long acop, struct mm_struct *mm) + + out: + spin_unlock(mm->context.cop_lockp); +- up_read(&mm->mmap_sem); ++ spin_unlock(&mm->page_table_lock); + + return ret; + } +@@ -185,8 +185,8 @@ void drop_cop(unsigned long acop, struct mm_struct *mm) + if (WARN_ON_ONCE(!mm)) + return; + +- /* We need to make sure mm_users doesn't change */ +- down_read(&mm->mmap_sem); ++ /* The page_table_lock ensures mm_users won't change under us */ ++ spin_lock(&mm->page_table_lock); + spin_lock(mm->context.cop_lockp); + + mm->context.acop &= ~acop; +@@ -213,7 +213,7 @@ void drop_cop(unsigned long acop, struct mm_struct *mm) + } + + spin_unlock(mm->context.cop_lockp); +- up_read(&mm->mmap_sem); ++ spin_unlock(&mm->page_table_lock); + } + EXPORT_SYMBOL_GPL(drop_cop); + diff --git a/rcu-avoid-just-onlined-cpu-resched.patch b/rcu-avoid-just-onlined-cpu-resched.patch new file mode 100644 index 000000000..517f37591 --- /dev/null +++ b/rcu-avoid-just-onlined-cpu-resched.patch @@ -0,0 +1,47 @@ +rcu: Avoid having just-onlined CPU resched itself when RCU is idle + +CPUs set rdp->qs_pending when coming online to resolve races with +grace-period start. However, this means that if RCU is idle, the +just-onlined CPU might needlessly send itself resched IPIs. Adjust +the online-CPU initialization to avoid this, and also to correctly +cause the CPU to respond to the current grace period if needed. + +Signed-off-by: Paul E. McKenney +--- + kernel/rcutree.c | 13 +++++++++---- + 1 files changed, 9 insertions(+), 4 deletions(-) + +diff --git a/kernel/rcutree.c b/kernel/rcutree.c +index ba06207..472d6b2 100644 +--- a/kernel/rcutree.c ++++ b/kernel/rcutree.c +@@ -1865,8 +1865,6 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible) + + /* Set up local state, ensuring consistent view of global state. */ + raw_spin_lock_irqsave(&rnp->lock, flags); +- rdp->passed_quiesc = 0; /* We could be racing with new GP, */ +- rdp->qs_pending = 1; /* so set up to respond to current GP. */ + rdp->beenonline = 1; /* We have now been online. */ + rdp->preemptible = preemptible; + rdp->qlen_last_fqs_check = 0; +@@ -1891,8 +1889,15 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible) + rnp->qsmaskinit |= mask; + mask = rnp->grpmask; + if (rnp == rdp->mynode) { +- rdp->gpnum = rnp->completed; /* if GP in progress... */ +- rdp->completed = rnp->completed; ++ /* ++ * If there is a grace period in progress, we will ++ * set up to wait for it next time we run the ++ * RCU core code. ++ */ ++ rdp->gpnum = rnp->completed; ++ rdp->completed = rnp->completed; ++ rdp->passed_quiesc = 0; ++ rdp->qs_pending = 0; + rdp->passed_quiesc_completed = rnp->completed - 1; + } + raw_spin_unlock(&rnp->lock); /* irqs already disabled. */ +-- +1.7.6 + diff --git a/revert-efi-rtclock.patch b/revert-efi-rtclock.patch new file mode 100644 index 000000000..87ecaa11a --- /dev/null +++ b/revert-efi-rtclock.patch @@ -0,0 +1,76 @@ +diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c +index 3ae4128..e17c6d2 100644 +--- a/arch/x86/platform/efi/efi.c ++++ b/arch/x86/platform/efi/efi.c +@@ -89,50 +89,26 @@ early_param("add_efi_memmap", setup_add_efi_memmap); + + static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) + { +- unsigned long flags; +- efi_status_t status; +- +- spin_lock_irqsave(&rtc_lock, flags); +- status = efi_call_virt2(get_time, tm, tc); +- spin_unlock_irqrestore(&rtc_lock, flags); +- return status; ++ return efi_call_virt2(get_time, tm, tc); + } + + static efi_status_t virt_efi_set_time(efi_time_t *tm) + { +- unsigned long flags; +- efi_status_t status; +- +- spin_lock_irqsave(&rtc_lock, flags); +- status = efi_call_virt1(set_time, tm); +- spin_unlock_irqrestore(&rtc_lock, flags); +- return status; ++ return efi_call_virt1(set_time, tm); + } + + static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled, + efi_bool_t *pending, + efi_time_t *tm) + { +- unsigned long flags; +- efi_status_t status; +- +- spin_lock_irqsave(&rtc_lock, flags); +- status = efi_call_virt3(get_wakeup_time, +- enabled, pending, tm); +- spin_unlock_irqrestore(&rtc_lock, flags); +- return status; ++ return efi_call_virt3(get_wakeup_time, ++ enabled, pending, tm); + } + + static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) + { +- unsigned long flags; +- efi_status_t status; +- +- spin_lock_irqsave(&rtc_lock, flags); +- status = efi_call_virt2(set_wakeup_time, +- enabled, tm); +- spin_unlock_irqrestore(&rtc_lock, flags); +- return status; ++ return efi_call_virt2(set_wakeup_time, ++ enabled, tm); + } + + static efi_status_t virt_efi_get_variable(efi_char16_t *name, +@@ -232,14 +208,11 @@ static efi_status_t __init phys_efi_set_virtual_address_map( + static efi_status_t __init phys_efi_get_time(efi_time_t *tm, + efi_time_cap_t *tc) + { +- unsigned long flags; + efi_status_t status; + +- spin_lock_irqsave(&rtc_lock, flags); + efi_call_phys_prelog(); + status = efi_call_phys2(efi_phys.get_time, tm, tc); + efi_call_phys_epilog(); +- spin_unlock_irqrestore(&rtc_lock, flags); + return status; + } + diff --git a/scripts/grab-logs.sh b/scripts/grab-logs.sh index 8a445ec99..5df573571 100755 --- a/scripts/grab-logs.sh +++ b/scripts/grab-logs.sh @@ -1,6 +1,6 @@ #!/bin/sh -VER=$(make verrel) +VER=$(fedpkg verrel) ver=$(echo $VER | sed -e 's/-/ /g' | awk '{print $2}') rev=$(echo $VER | sed -e 's/-/ /g' | awk '{print $3}') diff --git a/sources b/sources index 6dcaf1f12..9529d7a05 100644 --- a/sources +++ b/sources @@ -1,2 +1 @@ -398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 -49618d8c7a71549c8870eb709c7d3f81 patch-3.0.8.bz2 +8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 diff --git a/taint-vbox.patch b/taint-vbox.patch new file mode 100644 index 000000000..5cb3e47c9 --- /dev/null +++ b/taint-vbox.patch @@ -0,0 +1,15 @@ +diff --git a/kernel/module.c b/kernel/module.c +index 04379f92..d26c9a3 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -2653,6 +2653,10 @@ static int check_module_license_and_versions(struct module *mod) + if (strcmp(mod->name, "ndiswrapper") == 0) + add_taint(TAINT_PROPRIETARY_MODULE); + ++ /* vbox is garbage. */ ++ if (strcmp(mod->name, "vboxdrv") == 0) ++ add_taint(TAINT_CRAP); ++ + /* driverloader was caught wrongly pretending to be under GPL */ + if (strcmp(mod->name, "driverloader") == 0) + add_taint_module(mod, TAINT_PROPRIETARY_MODULE); diff --git a/udlfb-bind-framebuffer-to-interface.patch b/udlfb-bind-framebuffer-to-interface.patch new file mode 100644 index 000000000..1c5c6df9b --- /dev/null +++ b/udlfb-bind-framebuffer-to-interface.patch @@ -0,0 +1,33 @@ +From c91a793f66d5b06292aa431ae3a36c8aca991fa3 Mon Sep 17 00:00:00 2001 +From: Kay Sievers +Date: Tue, 5 Jul 2011 17:04:11 -0700 +Subject: [PATCH] drivers/video/udlfb bind framebuffer to interface. + +Udlfb has been binding the framebuffer device to its parent, which +isn't correct and causes confusion with operations like udev remove. + +Coming plug and play multiseat support is dependent on this fix. + +Signed-off-by: Kay Sievers +Signed-off-by: Bernie Thompson +Signed-off-by: Paul Mundt +--- + drivers/video/udlfb.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c +index 816a4fd..c6584c9 100644 +--- a/drivers/video/udlfb.c ++++ b/drivers/video/udlfb.c +@@ -1549,7 +1549,7 @@ static int dlfb_usb_probe(struct usb_interface *interface, + /* We don't register a new USB class. Our client interface is fbdev */ + + /* allocates framebuffer driver structure, not framebuffer memory */ +- info = framebuffer_alloc(0, &usbdev->dev); ++ info = framebuffer_alloc(0, &interface->dev); + if (!info) { + retval = -ENOMEM; + pr_err("framebuffer_alloc failed\n"); +-- +1.7.4.4 + diff --git a/ums-realtek-driver-uses-stack-memory-for-DMA.patch b/ums-realtek-driver-uses-stack-memory-for-DMA.patch index 2564fdbf2..98c8b0cf9 100644 --- a/ums-realtek-driver-uses-stack-memory-for-DMA.patch +++ b/ums-realtek-driver-uses-stack-memory-for-DMA.patch @@ -1,22 +1,69 @@ -commit 82e632009bb7d6b97f8cabe9918c82703f4e5cd2 -Author: Josh Boyer -Date: Tue Aug 2 08:37:53 2011 -0400 +From patchwork Tue Aug 2 05:04:11 2011 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +Subject: ums-realtek driver uses stack memory for DMA +Date: Tue, 02 Aug 2011 05:04:11 -0000 +From: Adam Cozzette +X-Patchwork-Id: 1028062 +Message-Id: <20110802050411.GC3857@[192.168.0.12]> +To: Josh Boyer +Cc: edwin_rong , wwang , + Greg Kroah-Hartman , linux-usb@vger.kernel.org, + linux-kernel@vger.kernel.org - This patch changed rts51x_read_mem, rts51x_write_mem, and rts51x_read_status to - allocate temporary buffers with kmalloc. This way stack addresses are not used - for DMA when these functions call rts51x_bulk_transport. - - Signed-off-by: Adam Cozzette - Backported-by: Josh Boyer +On Mon, Aug 01, 2011 at 05:09:06PM -0400, Josh Boyer wrote: +> Hello, +> +> We have a report that the ums-realtek driver is generating a backtrace +> due to using stack variables for DMA buffers. The backtrace is below +> and you can view the bug report here: +> https://bugzilla.redhat.com/show_bug.cgi?id=720054 +> +> Looking through the code, it seems that every call to rts51x_read_mem, +> rts51x_write_mem, and rts51x_read_status passes a stack variable to +> rts51x_bulk_transport, which then calls usb_stor_bulk_transfer_buf with +> this and generates the backtrace. It is my understanding that the +> driver should be passing variables that are not on the stack and have +> been allocated with memory that will be suitable for the DMA api (e.g. +> kmalloc). +> +> Was this missed during the initial review and is anyone working on +> adapting the driver to be compliant? + +Could you try out this patch if it looks ok to you? I have not tested it because +unfortunately I don't have the hardware. Right now it generates some compile +warnings like this one: + +drivers/usb/storage/realtek_cr.c:419:40: warning: ‘buf[0]’ may be used uninitialized in this function [-Wuninitialized] + +It think they are harmless but I didn't see an obvious way to get rid of them, +so if you have any suggestions I would be glad to hear them. + +This patch changed rts51x_read_mem, rts51x_write_mem, and rts51x_read_status to +allocate temporary buffers with kmalloc. This way stack addresses are not used +for DMA when these functions call rts51x_bulk_transport. + +Signed-off-by: Adam Cozzette + +--- +realtek_cr.c | 35 ++++++++++++++++++++++++++++++----- + 1 file changed, 30 insertions(+), 5 deletions(-) + +-- +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/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c -index d509a4a..69a1bd3 100644 +index 34adc4b..232167a 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c -@@ -285,6 +285,11 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) +@@ -320,6 +320,11 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) { int retval; - u8 cmnd[12] = {0}; + u8 cmnd[12] = { 0 }; + u8 *buf; + + buf = kmalloc(len, GFP_NOIO); @@ -25,8 +72,8 @@ index d509a4a..69a1bd3 100644 US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); -@@ -296,10 +301,14 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) - cmnd[5] = (u8)len; +@@ -331,10 +336,14 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) + cmnd[5] = (u8) len; retval = rts51x_bulk_transport(us, 0, cmnd, 12, - data, len, DMA_FROM_DEVICE, NULL); @@ -42,10 +89,10 @@ index d509a4a..69a1bd3 100644 return 0; } -@@ -307,6 +316,12 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) +@@ -342,6 +351,12 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) { int retval; - u8 cmnd[12] = {0}; + u8 cmnd[12] = { 0 }; + u8 *buf; + + buf = kmalloc(len, GFP_NOIO); @@ -55,8 +102,8 @@ index d509a4a..69a1bd3 100644 US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); -@@ -318,7 +333,8 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) - cmnd[5] = (u8)len; +@@ -353,7 +368,8 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) + cmnd[5] = (u8) len; retval = rts51x_bulk_transport(us, 0, cmnd, 12, - data, len, DMA_TO_DEVICE, NULL); @@ -65,10 +112,10 @@ index d509a4a..69a1bd3 100644 if (retval != USB_STOR_TRANSPORT_GOOD) return -EIO; -@@ -330,6 +346,11 @@ static int rts51x_read_status(struct us_data *us, +@@ -365,6 +381,11 @@ static int rts51x_read_status(struct us_data *us, { int retval; - u8 cmnd[12] = {0}; + u8 cmnd[12] = { 0 }; + u8 *buf; + + buf = kmalloc(len, GFP_NOIO); @@ -77,7 +124,7 @@ index d509a4a..69a1bd3 100644 US_DEBUGP("%s, lun = %d\n", __func__, lun); -@@ -337,10 +358,14 @@ static int rts51x_read_status(struct us_data *us, +@@ -372,10 +393,14 @@ static int rts51x_read_status(struct us_data *us, cmnd[1] = 0x09; retval = rts51x_bulk_transport(us, lun, cmnd, 12, diff --git a/utrace.patch b/utrace.patch index f70d0b1fb..576c737f3 100644 --- a/utrace.patch +++ b/utrace.patch @@ -1,42 +1,42 @@ -From davej Sun Aug 7 15:19:08 2011 +From davej Wed Aug 3 15:16:11 2011 Return-Path: oleg@redhat.com -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:08 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:17:59 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:11 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:37 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F09A8A5D58; - Sun, 7 Aug 2011 15:17:58 -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 6mY7uBb0+l7B; Sun, 7 Aug 2011 15:17:58 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 92D6F9D8C5; + Wed, 3 Aug 2011 15:12:08 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id RRq2PiCBdMzK; Wed, 3 Aug 2011 15:12:08 -0400 (EDT) Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D1DFE9C7FA; - Sun, 7 Aug 2011 15:17:58 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 75C149D898; + Wed, 3 Aug 2011 15:12:08 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JHtc4027719; - Sun, 7 Aug 2011 15:17:56 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JC01d029136; + Wed, 3 Aug 2011 15:12:01 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:19 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:17 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:28 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:26 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 01/22] utrace core -Message-ID: <20110807191517.GA14365@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 01/31] utrace core +Message-ID: <20110803190926.GA30903@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 148212 -Lines: 4118 +Content-Length: 139951 +Lines: 3867 From: Roland McGrath @@ -59,11 +59,11 @@ the next patches try to fix this. This is is same/old utrace-core patch except: - - use group_stop/GROUP_STOP_DEQUEUED instead of removed + - use task->jobctl/JOBCTL_STOP_DEQUEUED instead of removed signal->flags/SIGNAL_STOP_DEQUEUED in utrace_get_signal() - - rediff the changes in tracehook.h against the current code - without PT_PTRACED tweaks which were needed for ptrace-utrace + - do not include the tracehook changes, this comes with the + next patches Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov @@ -72,30 +72,28 @@ Signed-off-by: Oleg Nesterov Documentation/DocBook/utrace.tmpl | 589 +++++++++ fs/proc/array.c | 3 + include/linux/sched.h | 5 + - include/linux/tracehook.h | 85 ++- include/linux/utrace.h | 692 +++++++++++ init/Kconfig | 9 + kernel/Makefile | 1 + - kernel/fork.c | 3 + kernel/utrace.c | 2440 +++++++++++++++++++++++++++++++++++++ - 10 files changed, 3827 insertions(+), 2 deletions(-) + 8 files changed, 3740 insertions(+), 1 deletions(-) create mode 100644 Documentation/DocBook/utrace.tmpl create mode 100644 include/linux/utrace.h create mode 100644 kernel/utrace.c diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile -index 3cebfa0..86c288b 100644 +index 66725a3..08ed954 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -14,7 +14,7 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ 80211.xml debugobjects.xml sh.xml regulator.xml \ alsa-driver-api.xml writing-an-alsa-driver.xml \ -- tracepoint.xml media.xml drm.xml -+ tracepoint.xml utrace.xml media.xml drm.xml +- tracepoint.xml drm.xml media_api.xml ++ tracepoint.xml utrace.xml drm.xml media_api.xml + + include $(srctree)/Documentation/DocBook/media/Makefile - ### - # The build process is as follows (targets): diff --git a/Documentation/DocBook/utrace.tmpl b/Documentation/DocBook/utrace.tmpl new file mode 100644 index 0000000..0c40add @@ -692,7 +690,7 @@ index 0000000..0c40add + + diff --git a/fs/proc/array.c b/fs/proc/array.c -index 9b45ee8..496fef3 100644 +index 3a1dafd..f0c0ea2 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -81,6 +81,7 @@ @@ -713,10 +711,10 @@ index 9b45ee8..496fef3 100644 if (p->files) fdt = files_fdtable(p->files); diff --git a/include/linux/sched.h b/include/linux/sched.h -index a837b20..b87de83 100644 +index 20b03bf..c6d79af 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h -@@ -1397,6 +1397,11 @@ struct task_struct { +@@ -1406,6 +1406,11 @@ struct task_struct { #endif seccomp_t seccomp; @@ -728,235 +726,6 @@ index a837b20..b87de83 100644 /* Thread group tracking */ u32 parent_exec_id; u32 self_exec_id; -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index e95f523..7d7bdde 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -49,6 +49,7 @@ - #include - #include - #include -+#include - struct linux_binprm; - - /** -@@ -63,6 +64,8 @@ struct linux_binprm; - */ - static inline int tracehook_expect_breakpoints(struct task_struct *task) - { -+ if (unlikely(task_utrace_flags(task) & UTRACE_EVENT(SIGNAL_CORE))) -+ return 1; - return (task_ptrace(task) & PT_PTRACED) != 0; - } - -@@ -111,6 +114,9 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) - static inline __must_check int tracehook_report_syscall_entry( - struct pt_regs *regs) - { -+ if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && -+ utrace_report_syscall_entry(regs)) -+ return 1; - ptrace_report_syscall(regs); - return 0; - } -@@ -134,6 +140,9 @@ static inline __must_check int tracehook_report_syscall_entry( - */ - static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) - { -+ if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) -+ utrace_report_syscall_exit(regs); -+ - if (step) { - siginfo_t info; - user_single_step_siginfo(current, regs, &info); -@@ -201,6 +210,8 @@ static inline void tracehook_report_exec(struct linux_binfmt *fmt, - struct linux_binprm *bprm, - struct pt_regs *regs) - { -+ if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXEC))) -+ utrace_report_exec(fmt, bprm, regs); - if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) && - unlikely(task_ptrace(current) & PT_PTRACED)) - send_sig(SIGTRAP, current, 0); -@@ -218,10 +229,37 @@ static inline void tracehook_report_exec(struct linux_binfmt *fmt, - */ - static inline void tracehook_report_exit(long *exit_code) - { -+ if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXIT))) -+ utrace_report_exit(exit_code); - ptrace_event(PT_TRACE_EXIT, PTRACE_EVENT_EXIT, *exit_code); - } - - /** -+ * tracehook_init_task - task_struct has just been copied -+ * @task: new &struct task_struct just copied from parent -+ * -+ * Called from do_fork() when @task has just been duplicated. -+ * After this, @task will be passed to tracehook_free_task() -+ * even if the rest of its setup fails before it is fully created. -+ */ -+static inline void tracehook_init_task(struct task_struct *task) -+{ -+ utrace_init_task(task); -+} -+ -+/** -+ * tracehook_free_task - task_struct is being freed -+ * @task: dead &struct task_struct being freed -+ * -+ * Called from free_task() when @task is no longer in use. -+ */ -+static inline void tracehook_free_task(struct task_struct *task) -+{ -+ if (task_utrace_struct(task)) -+ utrace_free_task(task); -+} -+ -+/** - * tracehook_prepare_clone - prepare for new child to be cloned - * @clone_flags: %CLONE_* flags from clone/fork/vfork system call - * -@@ -285,6 +323,8 @@ static inline void tracehook_report_clone(struct pt_regs *regs, - unsigned long clone_flags, - pid_t pid, struct task_struct *child) - { -+ if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE))) -+ utrace_report_clone(clone_flags, child); - if (unlikely(task_ptrace(child))) { - /* - * It doesn't matter who attached/attaching to this -@@ -317,6 +357,9 @@ static inline void tracehook_report_clone_complete(int trace, - pid_t pid, - struct task_struct *child) - { -+ if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE)) && -+ (clone_flags & CLONE_VFORK)) -+ utrace_finish_vfork(current); - if (unlikely(trace)) - ptrace_event(0, trace, pid); - } -@@ -351,6 +394,10 @@ static inline void tracehook_report_vfork_done(struct task_struct *child, - */ - static inline void tracehook_prepare_release_task(struct task_struct *task) - { -+ /* see utrace_add_engine() about this barrier */ -+ smp_mb(); -+ if (task_utrace_flags(task)) -+ utrace_maybe_reap(task, task_utrace_struct(task), true); - } - - /** -@@ -365,6 +412,7 @@ static inline void tracehook_prepare_release_task(struct task_struct *task) - static inline void tracehook_finish_release_task(struct task_struct *task) - { - ptrace_release_task(task); -+ BUG_ON(task->exit_state != EXIT_DEAD); - } - - /** -@@ -386,6 +434,8 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, - const struct k_sigaction *ka, - struct pt_regs *regs, int stepping) - { -+ if (task_utrace_flags(current)) -+ utrace_signal_handler(current, stepping); - if (stepping) - ptrace_notify(SIGTRAP); - } -@@ -403,6 +453,8 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, - static inline int tracehook_consider_ignored_signal(struct task_struct *task, - int sig) - { -+ if (unlikely(task_utrace_flags(task) & UTRACE_EVENT(SIGNAL_IGN))) -+ return 1; - return (task_ptrace(task) & PT_PTRACED) != 0; - } - -@@ -422,6 +474,9 @@ static inline int tracehook_consider_ignored_signal(struct task_struct *task, - static inline int tracehook_consider_fatal_signal(struct task_struct *task, - int sig) - { -+ if (unlikely(task_utrace_flags(task) & (UTRACE_EVENT(SIGNAL_TERM) | -+ UTRACE_EVENT(SIGNAL_CORE)))) -+ return 1; - return (task_ptrace(task) & PT_PTRACED) != 0; - } - -@@ -436,6 +491,8 @@ static inline int tracehook_consider_fatal_signal(struct task_struct *task, - */ - static inline int tracehook_force_sigpending(void) - { -+ if (unlikely(task_utrace_flags(current))) -+ return utrace_interrupt_pending(); - return 0; - } - -@@ -465,6 +522,8 @@ static inline int tracehook_get_signal(struct task_struct *task, - siginfo_t *info, - struct k_sigaction *return_ka) - { -+ if (unlikely(task_utrace_flags(task))) -+ return utrace_get_signal(task, regs, info, return_ka); - return 0; - } - -@@ -475,6 +534,8 @@ static inline int tracehook_get_signal(struct task_struct *task, - */ - static inline void tracehook_finish_jctl(void) - { -+ if (task_utrace_flags(current)) -+ utrace_finish_stop(); - } - - #define DEATH_REAP -1 -@@ -497,6 +558,8 @@ static inline void tracehook_finish_jctl(void) - static inline int tracehook_notify_death(struct task_struct *task, - void **death_cookie, int group_dead) - { -+ *death_cookie = task_utrace_struct(task); -+ - if (task_detached(task)) - return task->ptrace ? SIGCHLD : DEATH_REAP; - -@@ -533,6 +596,15 @@ static inline void tracehook_report_death(struct task_struct *task, - int signal, void *death_cookie, - int group_dead) - { -+ /* -+ * If utrace_set_events() was just called to enable -+ * UTRACE_EVENT(DEATH), then we are obliged to call -+ * utrace_report_death() and not miss it. utrace_set_events() -+ * checks @task->exit_state under tasklist_lock to synchronize -+ * with exit_notify(), the caller. -+ */ -+ if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) -+ utrace_report_death(task, death_cookie, group_dead, signal); - } - - #ifdef TIF_NOTIFY_RESUME -@@ -562,10 +634,21 @@ static inline void set_notify_resume(struct task_struct *task) - * asynchronously, this will be called again before we return to - * user mode. - * -- * Called without locks. -+ * Called without locks. However, on some machines this may be -+ * called with interrupts disabled. - */ - static inline void tracehook_notify_resume(struct pt_regs *regs) - { -+ struct task_struct *task = current; -+ /* -+ * Prevent the following store/load from getting ahead of the -+ * caller which clears TIF_NOTIFY_RESUME. This pairs with the -+ * implicit mb() before setting TIF_NOTIFY_RESUME in -+ * set_notify_resume(). -+ */ -+ smp_mb(); -+ if (task_utrace_flags(task)) -+ utrace_resume(task, regs); - } - #endif /* TIF_NOTIFY_RESUME */ - diff --git a/include/linux/utrace.h b/include/linux/utrace.h new file mode 100644 index 0000000..f251efe @@ -1656,7 +1425,7 @@ index 0000000..f251efe + +#endif /* linux/utrace.h */ diff --git a/init/Kconfig b/init/Kconfig -index 412c21b..a03ae51 100644 +index d627783..7afce1f 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -372,6 +372,15 @@ config AUDIT_TREE @@ -1676,7 +1445,7 @@ index 412c21b..a03ae51 100644 menu "RCU Subsystem" diff --git a/kernel/Makefile b/kernel/Makefile -index 2d64cfc..4a22e81 100644 +index d06467f..85828da 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o @@ -1687,30 +1456,9 @@ index 2d64cfc..4a22e81 100644 obj-$(CONFIG_AUDIT) += audit.o auditfilter.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o obj-$(CONFIG_AUDIT_WATCH) += audit_watch.o -diff --git a/kernel/fork.c b/kernel/fork.c -index 0276c30..62caf3d 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -168,6 +168,7 @@ void free_task(struct task_struct *tsk) - free_thread_info(tsk->stack); - rt_mutex_debug_task_free(tsk); - ftrace_graph_exit_task(tsk); -+ tracehook_free_task(tsk); - free_task_struct(tsk); - } - EXPORT_SYMBOL(free_task); -@@ -1095,6 +1096,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, - if (!p) - goto fork_out; - -+ tracehook_init_task(p); -+ - ftrace_graph_init_task(p); - - rt_mutex_init_task(p); diff --git a/kernel/utrace.c b/kernel/utrace.c new file mode 100644 -index 0000000..f332d65 +index 0000000..ef856c9 --- /dev/null +++ b/kernel/utrace.c @@ -0,0 +1,2440 @@ @@ -4000,7 +3748,7 @@ index 0000000..f332d65 + spin_lock_irq(&task->sighand->siglock); + + if (sig_kernel_stop(signr)) -+ task->group_stop |= GROUP_STOP_DEQUEUED; ++ task->jobctl |= JOBCTL_STOP_DEQUEUED; + + return signr; +} @@ -4157,52 +3905,838 @@ index 0000000..f332d65 -- 1.5.5.1 -From davej Sun Aug 7 15:19:09 2011 + +From davej Wed Aug 3 15:16:13 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:09 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:01 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:13 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:37 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A1FB8D89A7; - Sun, 7 Aug 2011 15:18:01 -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 JtiDMxvrW-Di; Sun, 7 Aug 2011 15:18:01 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7F0E6D8988; - Sun, 7 Aug 2011 15:18:01 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 419B39D8CF; + Wed, 3 Aug 2011 15:12:11 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id AmaThyCcp1K4; Wed, 3 Aug 2011 15:12:11 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2A0B29CE59; + Wed, 3 Aug 2011 15:12:11 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JHxlJ027726; - Sun, 7 Aug 2011 15:17:59 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JC3DW023262; + Wed, 3 Aug 2011 15:12:04 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:23 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:21 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:31 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:29 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 02/22] utrace: remove jobctl bits -Message-ID: <20110807191521.GA14373@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 02/31] utrace: add utrace_init_task/utrace_free_task calls +Message-ID: <20110803190929.GA30907@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 1889 -Lines: 55 +Content-Length: 1295 +Lines: 47 -- change utrace_get_signal() to check GROUP_STOP_PENDING instead of +Add the necessary copy_process()->utrace_init_task() and +free_task()->utrace_free_task() calls. + +Originally this was the part of "utrace core" patch, but since +tracehooks are dying it doesn't make sense to reintroduce them. +Instead, just call the utrace_ helpers directly. This is fine +even without CONFIG_UTRACE, gcc is smart enough to optimize out +the code in free_task(). + +Signed-off-by: Oleg Nesterov +--- + kernel/fork.c | 5 +++++ + 1 files changed, 5 insertions(+), 0 deletions(-) + +diff --git a/kernel/fork.c b/kernel/fork.c +index e7ceaca..a9891da 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -66,6 +66,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -167,6 +168,8 @@ void free_task(struct task_struct *tsk) + free_thread_info(tsk->stack); + rt_mutex_debug_task_free(tsk); + ftrace_graph_exit_task(tsk); ++ if (task_utrace_struct(tsk)) ++ utrace_free_task(tsk); + free_task_struct(tsk); + } + EXPORT_SYMBOL(free_task); +@@ -1096,6 +1099,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, + if (!p) + goto fork_out; + ++ utrace_init_task(p); ++ + ftrace_graph_init_task(p); + + rt_mutex_init_task(p); +-- +1.5.5.1 + + +From davej Wed Aug 3 15:16:18 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:16:18 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:07 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F28379DE70; + Wed, 3 Aug 2011 15:12:13 -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 p92IDp0LZ5jX; Wed, 3 Aug 2011 15:12:13 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D4E339DE68; + Wed, 3 Aug 2011 15:12:13 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JC6IA023283; + Wed, 3 Aug 2011 15:12:07 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:34 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:32 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 03/31] tracehooks: add utrace hooks +Message-ID: <20110803190932.GA30915@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Status: RO +Content-Length: 2310 +Lines: 75 + +Add the necessary utrace hooks in the tracehooks which were not +removed yet. + +Signed-off-by: Oleg Nesterov +--- + include/linux/tracehook.h | 22 +++++++++++++++++++++- + 1 files changed, 21 insertions(+), 1 deletions(-) + +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index a71a292..8cc28bc 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + struct linux_binprm; + + /* +@@ -96,6 +97,9 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) + static inline __must_check int tracehook_report_syscall_entry( + struct pt_regs *regs) + { ++ if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && ++ utrace_report_syscall_entry(regs)) ++ return 1; + ptrace_report_syscall(regs); + return 0; + } +@@ -119,6 +123,9 @@ static inline __must_check int tracehook_report_syscall_entry( + */ + static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) + { ++ if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) ++ utrace_report_syscall_exit(regs); ++ + if (step) { + siginfo_t info; + user_single_step_siginfo(current, regs, &info); +@@ -148,6 +155,8 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, + const struct k_sigaction *ka, + struct pt_regs *regs, int stepping) + { ++ if (task_utrace_flags(current)) ++ utrace_signal_handler(current, stepping); + if (stepping) + ptrace_notify(SIGTRAP); + } +@@ -179,10 +188,21 @@ static inline void set_notify_resume(struct task_struct *task) + * asynchronously, this will be called again before we return to + * user mode. + * +- * Called without locks. ++ * Called without locks. However, on some machines this may be ++ * called with interrupts disabled. + */ + static inline void tracehook_notify_resume(struct pt_regs *regs) + { ++ struct task_struct *task = current; ++ /* ++ * Prevent the following store/load from getting ahead of the ++ * caller which clears TIF_NOTIFY_RESUME. This pairs with the ++ * implicit mb() before setting TIF_NOTIFY_RESUME in ++ * set_notify_resume(). ++ */ ++ smp_mb(); ++ if (task_utrace_flags(task)) ++ utrace_resume(task, regs); + } + #endif /* TIF_NOTIFY_RESUME */ + +-- +1.5.5.1 + + +From davej Wed Aug 3 15:16:14 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:16:14 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:37 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 92FCA9D8FA; + Wed, 3 Aug 2011 15:12:16 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id lQaZCHUpw8DT; Wed, 3 Aug 2011 15:12:16 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7479B9D8C9; + Wed, 3 Aug 2011 15:12:16 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JC91G023308; + Wed, 3 Aug 2011 15:12:09 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:37 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:35 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 04/31] tracehooks: reintroduce + tracehook_consider_fatal_signal() +Message-ID: <20110803190935.GA30918@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Status: RO +Content-Length: 3257 +Lines: 90 + +Add the killed tracehook_consider_fatal_signal() back. It has multiple +callers and it is not easy add the necessary checks inline. + +Signed-off-by: Oleg Nesterov +--- + arch/s390/kernel/traps.c | 4 ++-- + include/linux/tracehook.h | 22 ++++++++++++++++++++++ + kernel/signal.c | 4 ++-- + 3 files changed, 26 insertions(+), 4 deletions(-) + +diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c +index ffabcd9..1018ab6 100644 +--- a/arch/s390/kernel/traps.c ++++ b/arch/s390/kernel/traps.c +@@ -329,7 +329,7 @@ void __kprobes do_per_trap(struct pt_regs *regs) + + if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) + return; +- if (!current->ptrace) ++ if (!tracehook_consider_fatal_signal(current, SIGTRAP)) + return; + info.si_signo = SIGTRAP; + info.si_errno = 0; +@@ -428,7 +428,7 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code, + if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) + return; + if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) { +- if (current->ptrace) { ++ if (tracehook_consider_fatal_signal(current, SIGTRAP)) { + info.si_signo = SIGTRAP; + info.si_errno = 0; + info.si_code = TRAP_BRKPT; +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index 8cc28bc..ec2af67 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -161,6 +161,28 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, + ptrace_notify(SIGTRAP); + } + ++/** ++ * tracehook_consider_fatal_signal - suppress special handling of fatal signal ++ * @task: task receiving the signal ++ * @sig: signal number being sent ++ * ++ * Return nonzero to prevent special handling of this termination signal. ++ * Normally handler for signal is %SIG_DFL. It can be %SIG_IGN if @sig is ++ * ignored, in which case force_sig() is about to reset it to %SIG_DFL. ++ * When this returns zero, this signal might cause a quick termination ++ * that does not give the debugger a chance to intercept the signal. ++ * ++ * Called with or without @task->sighand->siglock held. ++ */ ++static inline int tracehook_consider_fatal_signal(struct task_struct *task, ++ int sig) ++{ ++ if (unlikely(task_utrace_flags(task) & (UTRACE_EVENT(SIGNAL_TERM) | ++ UTRACE_EVENT(SIGNAL_CORE)))) ++ return 1; ++ return task->ptrace != 0; ++} ++ + #ifdef TIF_NOTIFY_RESUME + /** + * set_notify_resume - cause tracehook_notify_resume() to be called +diff --git a/kernel/signal.c b/kernel/signal.c +index 291c970..d7ef0da 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -494,7 +494,7 @@ int unhandled_signal(struct task_struct *tsk, int sig) + if (handler != SIG_IGN && handler != SIG_DFL) + return 0; + /* if ptraced, let the tracer determine */ +- return !tsk->ptrace; ++ return !tracehook_consider_fatal_signal(tsk, sig); + } + + /* +@@ -982,7 +982,7 @@ static void complete_signal(int sig, struct task_struct *p, int group) + if (sig_fatal(p, sig) && + !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) && + !sigismember(&t->real_blocked, sig) && +- (sig == SIGKILL || !t->ptrace)) { ++ (sig == SIGKILL || !tracehook_consider_fatal_signal(t, sig))) { + /* + * This signal will be fatal to the whole group. + */ +-- +1.5.5.1 + + +From davej Wed Aug 3 15:16:20 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:16:20 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:08 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 374FE9DE74; + Wed, 3 Aug 2011 15:12:19 -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 Sun0Twp72xGV; Wed, 3 Aug 2011 15:12:19 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 223E39DD25; + Wed, 3 Aug 2011 15:12:19 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCBgK008326; + Wed, 3 Aug 2011 15:12:12 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:39 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:37 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 05/31] add utrace hooks into sig_ignored() and + recalc_sigpending() +Message-ID: <20110803190937.GA30926@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Status: RO +Content-Length: 1508 +Lines: 51 + +Add the necessary and somewhat "special" hooks into sig_ignored() and +recalc_sigpending(). Basically this restores _force_sigpending() and +_consider_ignored_signal() tracehook logic. + +Signed-off-by: Oleg Nesterov +--- + include/linux/utrace.h | 2 ++ + kernel/signal.c | 7 ++++++- + 2 files changed, 8 insertions(+), 1 deletions(-) + +diff --git a/include/linux/utrace.h b/include/linux/utrace.h +index f251efe..1b8da1c 100644 +--- a/include/linux/utrace.h ++++ b/include/linux/utrace.h +@@ -107,6 +107,8 @@ bool utrace_report_syscall_entry(struct pt_regs *); + void utrace_report_syscall_exit(struct pt_regs *); + void utrace_signal_handler(struct task_struct *, int); + ++#define UTRACE_FLAG(task, ev) (task_utrace_flags(task) & UTRACE_EVENT(ev)) ++ + #ifndef CONFIG_UTRACE + + /* +diff --git a/kernel/signal.c b/kernel/signal.c +index d7ef0da..0f9af0b 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -87,7 +87,7 @@ static int sig_ignored(struct task_struct *t, int sig, int from_ancestor_ns) + /* + * Tracers may want to know about even ignored signals. + */ +- return !t->ptrace; ++ return !t->ptrace && !UTRACE_FLAG(t, SIGNAL_IGN); + } + + /* +@@ -150,6 +150,11 @@ void recalc_sigpending_and_wake(struct task_struct *t) + + void recalc_sigpending(void) + { ++ if (task_utrace_flags(current) && utrace_interrupt_pending()) { ++ set_thread_flag(TIF_SIGPENDING); ++ return; ++ } ++ + if (!recalc_sigpending_tsk(current) && !freezing(current)) + clear_thread_flag(TIF_SIGPENDING); + +-- +1.5.5.1 + + +From davej Wed Aug 3 15:16:21 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:16:21 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:09 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 054279DE7D; + Wed, 3 Aug 2011 15:12:22 -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 1BosZIzYSIW0; Wed, 3 Aug 2011 15:12:21 -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 zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E41DC9DE7B; + Wed, 3 Aug 2011 15:12:21 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JCEgD022264; + Wed, 3 Aug 2011 15:12:15 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:42 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:40 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 06/31] restore the EXEC/EXIT/CLONE utrace hooks +Message-ID: <20110803190940.GA30929@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +Status: RO +Content-Length: 2383 +Lines: 83 + +Restore the "trivial" EXEC/EXIT/CLONE utrace hooks. Add the +simple helper, UTRACE_HOOK(), to minimize the changes. + +Signed-off-by: Oleg Nesterov +--- + fs/exec.c | 5 ++++- + include/linux/utrace.h | 6 ++++++ + kernel/exit.c | 1 + + kernel/fork.c | 4 ++++ + 4 files changed, 15 insertions(+), 1 deletions(-) + +diff --git a/fs/exec.c b/fs/exec.c +index da80612..a0814cd 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1401,9 +1401,12 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) + */ + bprm->recursion_depth = depth; + if (retval >= 0) { +- if (depth == 0) ++ if (depth == 0) { ++ UTRACE_HOOK(current, EXEC, ++ report_exec(fmt, bprm, regs)); + ptrace_event(PTRACE_EVENT_EXEC, + old_pid); ++ } + put_binfmt(fmt); + allow_write_access(bprm->file); + if (bprm->file) +diff --git a/include/linux/utrace.h b/include/linux/utrace.h +index 1b8da1c..9ac0b1b 100644 +--- a/include/linux/utrace.h ++++ b/include/linux/utrace.h +@@ -109,6 +109,12 @@ void utrace_signal_handler(struct task_struct *, int); + + #define UTRACE_FLAG(task, ev) (task_utrace_flags(task) & UTRACE_EVENT(ev)) + ++#define UTRACE_HOOK(task, ev, callback) \ ++ do { \ ++ if (UTRACE_FLAG(task, ev)) \ ++ utrace_ ## callback; \ ++ } while (0) ++ + #ifndef CONFIG_UTRACE + + /* +diff --git a/kernel/exit.c b/kernel/exit.c +index 2913b35..c1b0ab6 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -913,6 +913,7 @@ NORET_TYPE void do_exit(long code) + */ + set_fs(USER_DS); + ++ UTRACE_HOOK(current, EXIT, report_exit(&code)); + ptrace_event(PTRACE_EVENT_EXIT, code); + + validate_creds_for_do_exit(tsk); +diff --git a/kernel/fork.c b/kernel/fork.c +index a9891da..37f4a07 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -1539,6 +1539,8 @@ long do_fork(unsigned long clone_flags, + + audit_finish_fork(p); + ++ UTRACE_HOOK(current, CLONE, report_clone(clone_flags, p)); ++ + /* + * We set PF_STARTING at creation in case tracing wants to + * use this to distinguish a fully live task from one that +@@ -1550,6 +1552,8 @@ long do_fork(unsigned long clone_flags, + wake_up_new_task(p); + + /* forking complete and child started to run, tell ptracer */ ++ if (clone_flags & CLONE_VFORK) ++ UTRACE_HOOK(current, CLONE, finish_vfork(current)); + if (unlikely(trace)) + ptrace_event(trace, nr); + +-- +1.5.5.1 + + +From davej Wed Aug 3 15:16:23 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:16:23 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:13 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B36EC9DE82; + Wed, 3 Aug 2011 15:12:24 -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 7Qqv+lXfqHw6; Wed, 3 Aug 2011 15:12:24 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9F8AF9DD25; + Wed, 3 Aug 2011 15:12:24 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCH0U023349; + Wed, 3 Aug 2011 15:12:17 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:45 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:43 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 07/31] utrace: utrace_report_death() can use + task_utrace_struct() +Message-ID: <20110803190943.GA30936@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Status: RO +Content-Length: 1692 +Lines: 44 + +utrace_report_death() assumes that the caller (exit_notify) should +pass task->utrace as an argument. This is no longer needed, it can +safely do task_utrace_struct(). This way we avoid the nasty changes +in exit_notify(). + +Signed-off-by: Oleg Nesterov +--- + include/linux/utrace.h | 2 +- + kernel/utrace.c | 5 +++-- + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/include/linux/utrace.h b/include/linux/utrace.h +index 9ac0b1b..9a2e2f4 100644 +--- a/include/linux/utrace.h ++++ b/include/linux/utrace.h +@@ -99,7 +99,7 @@ int utrace_get_signal(struct task_struct *, struct pt_regs *, + void utrace_report_clone(unsigned long, struct task_struct *); + void utrace_finish_vfork(struct task_struct *); + void utrace_report_exit(long *exit_code); +-void utrace_report_death(struct task_struct *, struct utrace *, bool, int); ++void utrace_report_death(struct task_struct *, bool, int); + void utrace_report_jctl(int notify, int type); + void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *, + struct pt_regs *regs); +diff --git a/kernel/utrace.c b/kernel/utrace.c +index ef856c9..1e750ad 100644 +--- a/kernel/utrace.c ++++ b/kernel/utrace.c +@@ -1759,9 +1759,10 @@ void utrace_report_exit(long *exit_code) + * For this reason, utrace_release_task checks for the event bits that get + * us here, and delays its cleanup for us to do. + */ +-void utrace_report_death(struct task_struct *task, struct utrace *utrace, +- bool group_dead, int signal) ++void utrace_report_death(struct task_struct *task, bool group_dead, int signal) + { ++ struct utrace *utrace = task_utrace_struct(task); ++ + INIT_REPORT(report); + + BUG_ON(!task->exit_state); +-- +1.5.5.1 + + +From davej Wed Aug 3 15:16:15 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:16:15 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:39 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 76DA49D9C7; + Wed, 3 Aug 2011 15:12:27 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 25xHJjCTouA4; Wed, 3 Aug 2011 15:12:27 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 490E79D9AB; + Wed, 3 Aug 2011 15:12:27 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCKXo023360; + Wed, 3 Aug 2011 15:12:20 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:47 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:45 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 08/31] restore the DEATH/REAP utrace hooks +Message-ID: <20110803190945.GA30939@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Status: RO +Content-Length: 2346 +Lines: 70 + +Restore the necessary hooks in release_task() and exit_notify(), +add the corresponding helpers into utrace.h. + +Note: the @signal argument passed to ->report_death() does not +match the previous behaviour. I think this shouldn't affect the +current users, and I bet nobody can really understand what this +magic argument should actually mean anyway. + +Signed-off-by: Oleg Nesterov +--- + include/linux/utrace.h | 22 ++++++++++++++++++++++ + kernel/exit.c | 4 ++++ + 2 files changed, 26 insertions(+), 0 deletions(-) + +diff --git a/include/linux/utrace.h b/include/linux/utrace.h +index 9a2e2f4..cf13839 100644 +--- a/include/linux/utrace.h ++++ b/include/linux/utrace.h +@@ -697,4 +697,26 @@ static inline __must_check int utrace_barrier_pid(struct pid *pid, + + #endif /* CONFIG_UTRACE */ + ++static inline void utrace_release_task(struct task_struct *task) ++{ ++ /* see utrace_add_engine() about this barrier */ ++ smp_mb(); ++ if (task_utrace_flags(task)) ++ utrace_maybe_reap(task, task_utrace_struct(task), true); ++} ++ ++static inline void utrace_exit_notify(struct task_struct *task, ++ int signal, int group_dead) ++{ ++ /* ++ * If utrace_set_events() was just called to enable ++ * UTRACE_EVENT(DEATH), then we are obliged to call ++ * utrace_report_death() and not miss it. utrace_set_events() ++ * checks @task->exit_state under tasklist_lock to synchronize ++ * with exit_notify(), the caller. ++ */ ++ if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) ++ utrace_report_death(task, group_dead, signal); ++} ++ + #endif /* linux/utrace.h */ +diff --git a/kernel/exit.c b/kernel/exit.c +index c1b0ab6..ba5ba22 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -168,6 +168,8 @@ void release_task(struct task_struct * p) + struct task_struct *leader; + int zap_leader; + repeat: ++ utrace_release_task(p); ++ + /* don't need to get the RCU readlock here - the process is dead and + * can't be modifying its own credentials. But shut RCU-lockdep up */ + rcu_read_lock(); +@@ -860,6 +862,8 @@ static void exit_notify(struct task_struct *tsk, int group_dead) + wake_up_process(tsk->signal->group_exit_task); + write_unlock_irq(&tasklist_lock); + ++ utrace_exit_notify(tsk, autoreap ? -1 : SIGCHLD, group_dead); ++ + /* If the process is dead, release it - nobody will wait for it */ + if (autoreap) + release_task(tsk); +-- +1.5.5.1 + + +From davej Wed Aug 3 15:22:02 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:22:02 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:17:16 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 26DB69DE8C; + Wed, 3 Aug 2011 15:12:30 -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 DbxGfmFvtTiR; Wed, 3 Aug 2011 15:12:30 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 0A30A9DE91; + Wed, 3 Aug 2011 15:12:30 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCMDQ008389; + Wed, 3 Aug 2011 15:12:23 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:50 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:48 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 09/31] utrace: remove jobctl bits +Message-ID: <20110803190948.GA30942@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Status: RO +Content-Length: 1888 +Lines: 56 + +- change utrace_get_signal() to check JOBCTL_STOP_PENDING instead of signal->group_stop_count. With the recent changes group_stop_count doesn't necessarily mean this task should participate in group stop. @@ -4215,7 +4749,7 @@ Signed-off-by: Oleg Nesterov 1 files changed, 2 insertions(+), 14 deletions(-) diff --git a/kernel/utrace.c b/kernel/utrace.c -index f332d65..6e7fafb 100644 +index 1e750ad..5d3974e 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -648,11 +648,7 @@ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) @@ -4246,62 +4780,63 @@ index f332d65..6e7fafb 100644 spin_unlock_irq(&task->sighand->siglock); spin_unlock(&utrace->lock); -@@ -2036,7 +2024,7 @@ int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, +@@ -2037,7 +2025,7 @@ int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, ka = NULL; memset(return_ka, 0, sizeof *return_ka); } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || - unlikely(task->signal->group_stop_count)) { -+ unlikely(task->group_stop & GROUP_STOP_PENDING)) { ++ unlikely(task->jobctl & JOBCTL_STOP_PENDING)) { /* * If no engine is interested in intercepting signals or * we must stop, let the caller just dequeue them normally -- 1.5.5.1 -From davej Sun Aug 7 15:19:10 2011 + +From davej Wed Aug 3 15:16:17 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:10 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:04 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:17 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:52 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 473EDD89A7; - Sun, 7 Aug 2011 15:18:04 -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 uA3eVmUnKFQu; Sun, 7 Aug 2011 15:18:04 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 29079D8988; - Sun, 7 Aug 2011 15:18:04 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id AB6E39DA46; + Wed, 3 Aug 2011 15:12:32 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id LkzmRGslEelr; Wed, 3 Aug 2011 15:12:32 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 959659DA60; + Wed, 3 Aug 2011 15:12:32 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JI1LH027738; - Sun, 7 Aug 2011 15:18:02 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCPx7023400; + Wed, 3 Aug 2011 15:12:25 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:25 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:23 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:53 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:51 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 03/22] ptrace: take ->siglock around s/TRACED/RUNNING/ -Message-ID: <20110807191523.GA14376@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 10/31] ptrace: take ->siglock around s/TRACED/RUNNING/ +Message-ID: <20110803190951.GA30949@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 1623 -Lines: 55 +Content-Length: 1624 +Lines: 56 change ptrace_resume() and ptrace_stop() to take ->siglock around changing task->state from TRACED to RUNNING. @@ -4316,10 +4851,10 @@ Signed-off-by: Oleg Nesterov 2 files changed, 10 insertions(+), 1 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 2df1157..9988b13 100644 +index 9de3ecf..56b8fc1 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c -@@ -534,6 +534,8 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info) +@@ -589,6 +589,8 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info) static int ptrace_resume(struct task_struct *child, long request, unsigned long data) { @@ -4328,7 +4863,7 @@ index 2df1157..9988b13 100644 if (!valid_signal(data)) return -EIO; -@@ -562,7 +564,11 @@ static int ptrace_resume(struct task_struct *child, long request, +@@ -617,7 +619,11 @@ static int ptrace_resume(struct task_struct *child, long request, } child->exit_code = data; @@ -4342,10 +4877,10 @@ index 2df1157..9988b13 100644 return 0; } diff --git a/kernel/signal.c b/kernel/signal.c -index ff76786..2138cee 100644 +index 0f9af0b..71f5cca 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -1799,7 +1799,10 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1878,7 +1878,10 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) if (gstop_done) do_notify_parent_cldstop(current, false, why); @@ -4359,50 +4894,51 @@ index ff76786..2138cee 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:11 2011 + +From davej Wed Aug 3 15:16:37 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:11 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:37 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:06 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:29 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D76B6A5D58; - Sun, 7 Aug 2011 15:18:06 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5034E9DEA4; + Wed, 3 Aug 2011 15:12:35 -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 xyKeY-zzvTgR; Sun, 7 Aug 2011 15:18:06 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BB0E49C7FA; - Sun, 7 Aug 2011 15:18:06 -0400 (EDT) + with ESMTP id 8BhFlmqmXy8l; Wed, 3 Aug 2011 15:12:35 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 31AEE9DEAB; + Wed, 3 Aug 2011 15:12:35 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JI4PF028668; - Sun, 7 Aug 2011 15:18:05 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCRCZ008434; + Wed, 3 Aug 2011 15:12:28 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:28 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:26 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:55 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:53 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 04/22] introduce wake_up_quiescent() -Message-ID: <20110807191526.GA14383@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 11/31] introduce wake_up_quiescent() +Message-ID: <20110803190953.GA30952@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO -Content-Length: 3103 -Lines: 92 +Content-Length: 3186 +Lines: 93 No functional changes. Add the new helper, wake_up_quiescent(task, state), which simply returns wake_up_state(task, state). Change all callers which @@ -4432,10 +4968,10 @@ index a822300..2be3712 100644 extern int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p, bool group); diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 9988b13..26ae214 100644 +index 56b8fc1..4194664 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c -@@ -566,7 +566,7 @@ static int ptrace_resume(struct task_struct *child, long request, +@@ -621,7 +621,7 @@ static int ptrace_resume(struct task_struct *child, long request, child->exit_code = data; if (lock_task_sighand(child, &flags)) { @@ -4445,10 +4981,10 @@ index 9988b13..26ae214 100644 } diff --git a/kernel/signal.c b/kernel/signal.c -index 2138cee..4fcf1c7 100644 +index 71f5cca..3e8e0b1 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -652,6 +652,14 @@ void signal_wake_up(struct task_struct *t, int resume) +@@ -702,6 +702,14 @@ void signal_wake_up(struct task_struct *t, int resume) } /* @@ -4463,16 +4999,16 @@ index 2138cee..4fcf1c7 100644 * Remove signals in mask from the pending set and queue. * Returns 1 if any signals were found. * -@@ -811,7 +819,7 @@ static int prepare_signal(int sig, struct task_struct *p, int from_ancestor_ns) - do { - task_clear_group_stop_pending(t); +@@ -888,7 +896,7 @@ static int prepare_signal(int sig, struct task_struct *p, int from_ancestor_ns) + task_clear_jobctl_pending(t, JOBCTL_STOP_PENDING); rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending); -- wake_up_state(t, __TASK_STOPPED); -+ wake_up_quiescent(t, __TASK_STOPPED); + if (likely(!(t->ptrace & PT_SEIZED))) +- wake_up_state(t, __TASK_STOPPED); ++ wake_up_quiescent(t, __TASK_STOPPED); + else + ptrace_trap_notify(t); } while_each_thread(p, t); - - /* -@@ -1800,7 +1808,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1879,7 +1887,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) do_notify_parent_cldstop(current, false, why); spin_lock_irq(¤t->sighand->siglock); @@ -4482,7 +5018,7 @@ index 2138cee..4fcf1c7 100644 if (clear_code) diff --git a/kernel/utrace.c b/kernel/utrace.c -index 6e7fafb..d7c547c 100644 +index 5d3974e..cebc390 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -648,7 +648,7 @@ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) @@ -4497,53 +5033,54 @@ index 6e7fafb..d7c547c 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:13 2011 + +From davej Wed Aug 3 15:22:01 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:13 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:22:01 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:09 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:17:15 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C8DCF1322A2; - Sun, 7 Aug 2011 15:18:09 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F2DE19DC07; + Wed, 3 Aug 2011 15:12:37 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id ZQXZL5xrzV21; Sun, 7 Aug 2011 15:18:09 -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 zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B3D6D128FDA; - Sun, 7 Aug 2011 15:18:09 -0400 (EDT) + with ESMTP id IYfqfx8GhNWc; Wed, 3 Aug 2011 15:12:37 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D645E9DAF7; + Wed, 3 Aug 2011 15:12:37 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JI7P5029847; - Sun, 7 Aug 2011 15:18:07 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCUNh008446; + Wed, 3 Aug 2011 15:12:31 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:31 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:28 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:58 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:56 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 05/22] introduce ptrace_signal_wake_up() -Message-ID: <20110807191528.GA14386@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 12/31] introduce ptrace_signal_wake_up() +Message-ID: <20110803190956.GA30959@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO -Content-Length: 1974 -Lines: 67 +Content-Length: 3667 +Lines: 113 -Add the new helper, ptrace_signal_wake_up(), change ptrace.c to use -it instead of signal_wake_up(). +Add the new helper, ptrace_signal_wake_up(), change ptrace.c/signal.c +to use it instead of signal_wake_up() to wake up a STOPPED/TRACED task. The new helper does almost the same, except: @@ -4563,18 +5100,32 @@ wake_up_quiescent(). Signed-off-by: Oleg Nesterov --- - kernel/ptrace.c | 16 ++++++++++++++-- - 1 files changed, 14 insertions(+), 2 deletions(-) + include/linux/ptrace.h | 1 + + kernel/ptrace.c | 20 ++++++++++++++++---- + kernel/signal.c | 2 +- + 3 files changed, 18 insertions(+), 5 deletions(-) +diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h +index 800f113..6d9282a 100644 +--- a/include/linux/ptrace.h ++++ b/include/linux/ptrace.h +@@ -113,6 +113,7 @@ + #include /* For unlikely. */ + #include /* For struct task_struct. */ + ++extern void ptrace_signal_wake_up(struct task_struct *p, int quiescent); + + extern long arch_ptrace(struct task_struct *child, long request, + unsigned long addr, unsigned long data); diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 26ae214..0b2aba5 100644 +index 4194664..1a50090 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c -@@ -24,6 +24,18 @@ - #include +@@ -25,6 +25,18 @@ #include + #include -+static void ptrace_signal_wake_up(struct task_struct *p, int quiescent) ++void ptrace_signal_wake_up(struct task_struct *p, int quiescent) +{ + unsigned int state; + @@ -4587,74 +5138,106 @@ index 26ae214..0b2aba5 100644 + kick_process(p); +} - /* - * ptrace a task: make the debugger its new parent and -@@ -92,7 +104,7 @@ void __ptrace_unlink(struct task_struct *child) + static int ptrace_trapping_sleep_fn(void *flags) + { +@@ -106,7 +118,7 @@ void __ptrace_unlink(struct task_struct *child) * TASK_KILLABLE sleeps. */ - if (child->group_stop & GROUP_STOP_PENDING || task_is_traced(child)) + if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child)) - signal_wake_up(child, task_is_traced(child)); + ptrace_signal_wake_up(child, task_is_traced(child)); spin_unlock(&child->sighand->siglock); } -@@ -245,7 +257,7 @@ static int ptrace_attach(struct task_struct *task) +@@ -296,7 +308,7 @@ static int ptrace_attach(struct task_struct *task, long request, */ - if (task_is_stopped(task)) { - task->group_stop |= GROUP_STOP_PENDING | GROUP_STOP_TRAPPING; + if (task_is_stopped(task) && + task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING)) - signal_wake_up(task, 1); + ptrace_signal_wake_up(task, 1); - wait_trap = true; - } + spin_unlock(&task->sighand->siglock); + +@@ -731,7 +743,7 @@ int ptrace_request(struct task_struct *child, long request, + * tracee into STOP. + */ + if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP))) +- signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); ++ ptrace_signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); + + unlock_task_sighand(child, &flags); + ret = 0; +@@ -760,7 +772,7 @@ int ptrace_request(struct task_struct *child, long request, + * start of this trap and now. Trigger re-trap. + */ + if (child->jobctl & JOBCTL_TRAP_NOTIFY) +- signal_wake_up(child, true); ++ ptrace_signal_wake_up(child, true); + ret = 0; + } + unlock_task_sighand(child, &flags); +diff --git a/kernel/signal.c b/kernel/signal.c +index 3e8e0b1..0dc6abb 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -854,7 +854,7 @@ static void ptrace_trap_notify(struct task_struct *t) + assert_spin_locked(&t->sighand->siglock); + + task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY); +- signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); ++ ptrace_signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); + } + + /* -- 1.5.5.1 -From davej Sun Aug 7 15:19:14 2011 + +From davej Wed Aug 3 15:15:58 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:14 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:12 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:15:58 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:13:17 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 72BBDA5D58; - Sun, 7 Aug 2011 15:18:12 -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 k8I1SMuU0ydh; Sun, 7 Aug 2011 15:18:12 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8FF88DA558; + Wed, 3 Aug 2011 15:12:40 -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 1cOfIyuaRoO3; Wed, 3 Aug 2011 15:12:40 -0400 (EDT) Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5DFAB9C7FA; - Sun, 7 Aug 2011 15:18:12 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7B6E8DA4A9; + Wed, 3 Aug 2011 15:12:40 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIAjF028676; - Sun, 7 Aug 2011 15:18:10 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCXpn023459; + Wed, 3 Aug 2011 15:12:33 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:34 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:31 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:01 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:59 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 06/22] wait_task_inactive: treat task->state and +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 13/31] wait_task_inactive: treat task->state and match_state as bitmasks -Message-ID: <20110807191531.GA14393@redhat.com> +Message-ID: <20110803190959.GA30962@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 1557 -Lines: 38 +Content-Length: 1558 +Lines: 39 Change wait_task_inactive() to check "state & match_state" instead of "state == match_state". This should not make any difference, but this @@ -4680,10 +5263,10 @@ Signed-off-by: Oleg Nesterov 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c -index 3f2e502..ade7997 100644 +index ccacdbd..66ef2fb 100644 --- a/kernel/sched.c +++ b/kernel/sched.c -@@ -2277,7 +2277,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) +@@ -2289,7 +2289,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) * is actually now running somewhere else! */ while (task_running(rq, p)) { @@ -4695,50 +5278,51 @@ index 3f2e502..ade7997 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:15 2011 + +From davej Wed Aug 3 15:16:24 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:15 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:24 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:15 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:21 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1FD1B1322A2; - Sun, 7 Aug 2011 15:18:15 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 34C189DC30; + Wed, 3 Aug 2011 15:12:43 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id gfct30463vGS; Sun, 7 Aug 2011 15:18:15 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 01C04128FDA; - Sun, 7 Aug 2011 15:18:15 -0400 (EDT) + with ESMTP id RHggq6bqo+Q9; Wed, 3 Aug 2011 15:12:43 -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 zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 210D59DC14; + Wed, 3 Aug 2011 15:12:43 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JICKL027777; - Sun, 7 Aug 2011 15:18:13 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JCZsD022395; + Wed, 3 Aug 2011 15:12:36 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:36 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:34 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:03 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:01 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 07/22] introduce TASK_UTRACED state -Message-ID: <20110807191534.GA14396@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 14/31] introduce TASK_UTRACED state +Message-ID: <20110803191001.GA30969@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO -Content-Length: 2912 -Lines: 83 +Content-Length: 2913 +Lines: 84 Introduce TASK_UTRACED state, will be used by utrace instead of TASK_TRACED. @@ -4752,7 +5336,7 @@ Signed-off-by: Oleg Nesterov 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/fs/proc/array.c b/fs/proc/array.c -index 496fef3..bfaa998 100644 +index f0c0ea2..e0daec4 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -138,11 +138,12 @@ static const char * const task_state_array[] = { @@ -4774,7 +5358,7 @@ index 496fef3..bfaa998 100644 static inline const char *get_task_state(struct task_struct *tsk) diff --git a/include/linux/sched.h b/include/linux/sched.h -index b87de83..7a0008c 100644 +index c6d79af..f3f0a77 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -184,16 +184,17 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) @@ -4824,50 +5408,51 @@ index b87de83..7a0008c 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:17 2011 + +From davej Wed Aug 3 15:16:02 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:17 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:17 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:02 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:13:18 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B634FA5D5A; - Sun, 7 Aug 2011 15:18:17 -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 3vEyYZtZ8hD5; Sun, 7 Aug 2011 15:18:17 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9921A9C7FA; - Sun, 7 Aug 2011 15:18:17 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D7FFADA44E; + Wed, 3 Aug 2011 15:12:45 -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 LFGdvSMswLJT; Wed, 3 Aug 2011 15:12:45 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BA46CDA441; + Wed, 3 Aug 2011 15:12:45 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIFH8028686; - Sun, 7 Aug 2011 15:18:16 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCcpZ029424; + Wed, 3 Aug 2011 15:12:39 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:39 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:37 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:06 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:04 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 08/22] utrace: use TASK_UTRACED instead of TASK_TRACED -Message-ID: <20110807191537.GA14403@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 15/31] utrace: use TASK_UTRACED instead of TASK_TRACED +Message-ID: <20110803191004.GA30972@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 4315 -Lines: 129 +Content-Length: 4316 +Lines: 130 Change utrace.c to use TASK_UTRACED instead of TASK_TRACED. @@ -4887,7 +5472,7 @@ Signed-off-by: Oleg Nesterov 1 files changed, 14 insertions(+), 12 deletions(-) diff --git a/kernel/utrace.c b/kernel/utrace.c -index d7c547c..be98607 100644 +index cebc390..2097103 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -462,6 +462,8 @@ static void put_detached_list(struct list_head *list) @@ -4999,59 +5584,57 @@ index d7c547c..be98607 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:19 2011 + +From davej Wed Aug 3 15:21:40 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:19 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:24 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:21:40 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:42 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 53AC0D89A9; - Sun, 7 Aug 2011 15:18:20 -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 CGhyA84rXAKN; Sun, 7 Aug 2011 15:18:20 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 36B2CD8988; - Sun, 7 Aug 2011 15:18:20 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7035E9DECC; + Wed, 3 Aug 2011 15:12:48 -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 rmRalMQFlNua; Wed, 3 Aug 2011 15:12:48 -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 5CC809DEC9; + Wed, 3 Aug 2011 15:12:48 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIIFB028696; - Sun, 7 Aug 2011 15:18:18 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JCfwv010344; + Wed, 3 Aug 2011 15:12:41 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:41 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:39 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:09 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:07 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 09/22] tracehooks: kill tracehook_finish_jctl(), add - tracehook_finish_stop() -Message-ID: <20110807191539.GA14406@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 16/31] reintroduce tracehook_finish_jctl() as + utrace_end_stop() +Message-ID: <20110803191007.GA30979@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO -Content-Length: 2781 -Lines: 85 +Content-Length: 2401 +Lines: 77 -tracehook_finish_jctl() is needed to avoid the races with SIGKILL -which wakes up UTRACED task, and thus it should be called every time -after the STOPPED/TRACED/UTRACED returns from schedule(), remember -that TASK_UTRACED can be added while the task is STOPPED/UTRACED. - -- rename it to tracehook_finish_stop(),jctl no longer matches the - reality. +utrace_finish_stop() is needed to avoid the races with SIGKILL which +wakes up UTRACED task, and thus it should be called every time after +the STOPPED/TRACED/UTRACED returns from schedule(), remember that +TASK_UTRACED can be added while the task is STOPPED/UTRACED. - change do_signal_state() to call this helper right after schedule(), otherwise this logic is broken by the upstream changes @@ -5061,62 +5644,56 @@ that TASK_UTRACED can be added while the task is STOPPED/UTRACED. Signed-off-by: Oleg Nesterov --- - include/linux/tracehook.h | 6 +++--- - kernel/signal.c | 5 +++-- - kernel/utrace.c | 2 +- - 3 files changed, 7 insertions(+), 6 deletions(-) + include/linux/utrace.h | 11 +++++++++++ + kernel/signal.c | 5 +++++ + kernel/utrace.c | 2 +- + 3 files changed, 17 insertions(+), 1 deletions(-) -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 7d7bdde..3c7b6b3 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -528,11 +528,11 @@ static inline int tracehook_get_signal(struct task_struct *task, +diff --git a/include/linux/utrace.h b/include/linux/utrace.h +index cf13839..0279c74 100644 +--- a/include/linux/utrace.h ++++ b/include/linux/utrace.h +@@ -719,4 +719,15 @@ static inline void utrace_exit_notify(struct task_struct *task, + utrace_report_death(task, group_dead, signal); } - /** -- * tracehook_finish_jctl - report about return from job control stop -+ * tracehook_finish_stop - report about return from STOPPED/TRACED - * -- * This is called by do_signal_stop() after wakeup. ++/** ++ * utrace_end_stop - report about return from STOPPED/TRACED ++ * + * This is called by do_signal_stop() and ptrace_stop after wakeup. - */ --static inline void tracehook_finish_jctl(void) -+static inline void tracehook_finish_stop(void) - { - if (task_utrace_flags(current)) - utrace_finish_stop(); ++ */ ++static inline void utrace_end_stop(void) ++{ ++ if (task_utrace_flags(current)) ++ utrace_finish_stop(); ++} ++ + #endif /* linux/utrace.h */ diff --git a/kernel/signal.c b/kernel/signal.c -index 4fcf1c7..a7979ad 100644 +index 0dc6abb..a625309 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -1816,6 +1816,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1895,6 +1895,8 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) read_unlock(&tasklist_lock); } -+ tracehook_finish_stop(); ++ utrace_end_stop(); ++ /* * While in TASK_TRACED, we were considered "frozen enough". * Now that we woke up, it's crucial if we're supposed to be -@@ -1952,6 +1953,8 @@ retry: +@@ -2059,6 +2061,9 @@ static bool do_signal_stop(int signr) + /* Now we don't run again until woken by SIGCONT or SIGKILL */ schedule(); - -+ tracehook_finish_stop(); + - spin_lock_irq(¤t->sighand->siglock); ++ utrace_end_stop(); ++ + return true; } else { - ptrace_stop(current->group_stop & GROUP_STOP_SIGMASK, -@@ -1974,8 +1977,6 @@ retry: - - spin_unlock_irq(¤t->sighand->siglock); - -- tracehook_finish_jctl(); -- - return 1; - } - + /* diff --git a/kernel/utrace.c b/kernel/utrace.c -index be98607..daa96b9 100644 +index 2097103..d41b982 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -741,7 +741,7 @@ static bool utrace_reset(struct task_struct *task, struct utrace *utrace) @@ -5131,50 +5708,51 @@ index be98607..daa96b9 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:18 2011 + +From davej Wed Aug 3 15:21:41 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:18 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:21:41 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:22 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:42 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id DD6839C7FA; - Sun, 7 Aug 2011 15:18:22 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 153719DD18; + Wed, 3 Aug 2011 15:12:51 -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 hZs6VyadcD7K; Sun, 7 Aug 2011 15:18:22 -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 C7B129C7DE; - Sun, 7 Aug 2011 15:18:22 -0400 (EDT) + with ESMTP id ffM0oM8RRtgL; Wed, 3 Aug 2011 15:12:51 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 0253E9DEC9; + Wed, 3 Aug 2011 15:12:51 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIKMe020605; - Sun, 7 Aug 2011 15:18:21 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCh9Z023559; + Wed, 3 Aug 2011 15:12:44 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:44 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:42 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:11 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:09 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 10/22] teach wake_up_quiescent() to do "selective" wake_up -Message-ID: <20110807191542.GA14409@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 17/31] teach wake_up_quiescent() to do "selective" wake_up +Message-ID: <20110803191009.GA30982@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 1334 -Lines: 45 +Content-Length: 1335 +Lines: 46 Both utrace and ptrace can want the same thread to be quiescent, in this case its state is TASK_TRACED | TASK_UTRACED. And this also means that @@ -5189,10 +5767,10 @@ Signed-off-by: Oleg Nesterov 1 files changed, 15 insertions(+), 0 deletions(-) diff --git a/kernel/signal.c b/kernel/signal.c -index a7979ad..57552e6 100644 +index a625309..0d1675a 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -651,11 +651,26 @@ void signal_wake_up(struct task_struct *t, int resume) +@@ -701,11 +701,26 @@ void signal_wake_up(struct task_struct *t, int resume) kick_process(t); } @@ -5222,51 +5800,52 @@ index a7979ad..57552e6 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:20 2011 + +From davej Wed Aug 3 15:21:43 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:20 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:25 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:21:43 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:43 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7C2991322AA; - Sun, 7 Aug 2011 15:18:25 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id rHOxOwY4bOdr; Sun, 7 Aug 2011 15:18:25 -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 zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 67ABD128FDA; - Sun, 7 Aug 2011 15:18:25 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B0E899DECF; + Wed, 3 Aug 2011 15:12:53 -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 s0bDFhAmsQWN; Wed, 3 Aug 2011 15:12:53 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9DC6E9DEC9; + Wed, 3 Aug 2011 15:12:53 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JINVP029911; - Sun, 7 Aug 2011 15:18:23 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCkUr029453; + Wed, 3 Aug 2011 15:12:46 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:47 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:45 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:14 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:12 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 11/22] ptrace_stop: do not assume the task is running after +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 18/31] ptrace_stop: do not assume the task is running after wake_up_quiescent() -Message-ID: <20110807191545.GA14416@redhat.com> +Message-ID: <20110803191012.GA30985@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 961 -Lines: 30 +Content-Length: 956 +Lines: 31 If ptrace_stop() sets TASK_TRACED and then detects we should not stop, it can race with utrace_do_stop() which can see TASK_TRACED and add @@ -5278,10 +5857,10 @@ Signed-off-by: Oleg Nesterov 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/kernel/signal.c b/kernel/signal.c -index 57552e6..89e691d 100644 +index 0d1675a..249760f 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -1829,6 +1829,14 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1908,6 +1908,14 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) if (clear_code) current->exit_code = 0; read_unlock(&tasklist_lock); @@ -5295,173 +5874,297 @@ index 57552e6..89e691d 100644 + schedule(); } - tracehook_finish_stop(); + utrace_end_stop(); -- 1.5.5.1 -From davej Sun Aug 7 15:19:21 2011 + +From davej Wed Aug 3 15:16:26 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:21 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:26 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:28 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:22 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1B4B91322AE; - Sun, 7 Aug 2011 15:18:28 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 69B489DC62; + Wed, 3 Aug 2011 15:12:56 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id q5tv0cJeZqLD; Sun, 7 Aug 2011 15:18:28 -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 zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 071461322A9; - Sun, 7 Aug 2011 15:18:28 -0400 (EDT) + with ESMTP id 4BNNeoYSdCTc; Wed, 3 Aug 2011 15:12:56 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4A9899DC14; + Wed, 3 Aug 2011 15:12:56 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIPFB020635; - Sun, 7 Aug 2011 15:18:26 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCnRf023575; + Wed, 3 Aug 2011 15:12:49 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:49 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:47 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:16 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:14 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 12/22] get_signal_to_deliver: restructure utrace/ptrace - signal reporting -Message-ID: <20110807191547.GA14419@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 19/31] get_signal_to_deliver: restore/restructure + utrace/ptrace signal reporting +Message-ID: <20110803191014.GA30992@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 2011 -Lines: 72 +Content-Length: 3556 +Lines: 115 -get_signal_to_deliver() assumes that either tracehook_get_signal() does -nothing (without CONFIG_UTRACE), or it also reports the signal to ptrace -engine implemented on top of utrace. Now that ptrace works independently -this doesn't work. +- Reintroduce tracehook_get_signal() as utrace_hook_signal(). -Change the code to call ptrace_signal() after tracehook_get_signal(). +- Change get_signal_to_deliver() to call utrace_hook_signal() first, + before dequeue_signal() -Move ->ptrace check from ptrace_signal() to get_signal_to_deliver(), -we do not want to change *return_ka if it was initialized by utrace -and the task is not traced. +- Always call ptrace_signal() if signal != SIGKILL, no matter whether + this signal comes from utrace or not. + + Since this can change signr again, update "struct k_sigaction *ka" + in this case. IOW, roughly, ptrace acts as if it is the last attached engine, it takes the final decision about the signal. Signed-off-by: Oleg Nesterov --- - kernel/signal.c | 24 +++++++++++------------- - 1 files changed, 11 insertions(+), 13 deletions(-) + include/linux/utrace.h | 31 +++++++++++++++++++++++++++++++ + kernel/signal.c | 30 ++++++++++++++++++++---------- + 2 files changed, 51 insertions(+), 10 deletions(-) +diff --git a/include/linux/utrace.h b/include/linux/utrace.h +index 0279c74..63103e2 100644 +--- a/include/linux/utrace.h ++++ b/include/linux/utrace.h +@@ -730,4 +730,35 @@ static inline void utrace_end_stop(void) + utrace_finish_stop(); + } + ++/** ++ * utrace_hook_signal - deliver synthetic signal to traced task ++ * @task: @current ++ * @regs: task_pt_regs(@current) ++ * @info: details of synthetic signal ++ * @return_ka: sigaction for synthetic signal ++ * ++ * Return zero to check for a real pending signal normally. ++ * Return -1 after releasing the siglock to repeat the check. ++ * Return a signal number to induce an artificial signal delivery, ++ * setting *@info and *@return_ka to specify its details and behavior. ++ * ++ * The @return_ka->sa_handler value controls the disposition of the ++ * signal, no matter the signal number. For %SIG_DFL, the return value ++ * is a representative signal to indicate the behavior (e.g. %SIGTERM ++ * for death, %SIGQUIT for core dump, %SIGSTOP for job control stop, ++ * %SIGTSTP for stop unless in an orphaned pgrp), but the signal number ++ * reported will be @info->si_signo instead. ++ * ++ * Called with @task->sighand->siglock held, before dequeuing pending signals. ++ */ ++static inline int utrace_hook_signal(struct task_struct *task, ++ struct pt_regs *regs, ++ siginfo_t *info, ++ struct k_sigaction *return_ka) ++{ ++ if (unlikely(task_utrace_flags(task))) ++ return utrace_get_signal(task, regs, info, return_ka); ++ return 0; ++} ++ + #endif /* linux/utrace.h */ diff --git a/kernel/signal.c b/kernel/signal.c -index 89e691d..d0e0c67 100644 +index 249760f..3c783d3 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -2006,9 +2006,6 @@ retry: - static int ptrace_signal(int signr, siginfo_t *info, - struct pt_regs *regs, void *cookie) - { -- if (!task_ptrace(current)) -- return signr; -- - ptrace_signal_deliver(regs, cookie); +@@ -2234,17 +2234,27 @@ relock: + for (;;) { + struct k_sigaction *ka; - /* Let the debugger run. */ -@@ -2110,6 +2107,7 @@ relock: - signr = tracehook_get_signal(current, regs, info, return_ka); - if (unlikely(signr < 0)) +- if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) && +- do_signal_stop(0)) ++ signr = utrace_hook_signal(current, regs, info, return_ka); ++ if (unlikely(signr < 0)) goto relock; + +- if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) { +- do_jobctl_trap(); +- spin_unlock_irq(&sighand->siglock); +- goto relock; +- } ++ if (unlikely(signr != 0)) ++ ka = return_ka; ++ else { ++ if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) && ++ do_signal_stop(0)) ++ goto relock; + +- signr = dequeue_signal(current, ¤t->blocked, info); ++ if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) { ++ do_jobctl_trap(); ++ spin_unlock_irq(&sighand->siglock); ++ goto relock; ++ } + - if (unlikely(signr != 0)) - ka = return_ka; - else { -@@ -2117,18 +2115,18 @@ relock: - GROUP_STOP_PENDING) && do_signal_stop(0)) - goto relock; - -- signr = dequeue_signal(current, ¤t->blocked, -- info); + signr = dequeue_signal(current, ¤t->blocked, info); - -- if (!signr) -- break; /* will return 0 */ ++ + ka = &sighand->action[signr-1]; + } -- if (signr != SIGKILL) { -- signr = ptrace_signal(signr, info, -- regs, cookie); -- if (!signr) -- continue; -- } -+ if (!signr) -+ break; /* will return 0 */ -+ -+ if (signr != SIGKILL && current->ptrace) { -+ signr = ptrace_signal(signr, info, regs, cookie); -+ if (!signr) -+ continue; + if (!signr) + break; /* will return 0 */ +@@ -2254,9 +2264,9 @@ relock: + regs, cookie); + if (!signr) + continue; +- } - ka = &sighand->action[signr-1]; - } +- ka = &sighand->action[signr-1]; ++ ka = &sighand->action[signr-1]; ++ } + + /* Trace actually delivered signals. */ + trace_signal_deliver(signr, info, ka); -- 1.5.5.1 -From davej Sun Aug 7 15:19:22 2011 + +From davej Wed Aug 3 15:16:27 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:22 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:27 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:30 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:22 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BFD8F1322A2; - Sun, 7 Aug 2011 15:18:30 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 119589DC72; + Wed, 3 Aug 2011 15:12:59 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id JczS8HsLYY6X; Sun, 7 Aug 2011 15:18:30 -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 zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A8F91128FDA; - Sun, 7 Aug 2011 15:18:30 -0400 (EDT) + with ESMTP id Vxp8fnt8hEcf; Wed, 3 Aug 2011 15:12:59 -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 zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F22049DCAE; + Wed, 3 Aug 2011 15:12:58 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIS1m029940; - Sun, 7 Aug 2011 15:18:29 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JCpO4010401; + Wed, 3 Aug 2011 15:12:52 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:52 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:50 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:19 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:17 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 13/22] introduce ptrace_set_syscall_trace() -Message-ID: <20110807191550.GA14426@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 20/31] utrace_get_signal: + s/JOBCTL_STOP_PENDING/JOBCTL_PENDING_MASK/ +Message-ID: <20110803191017.GA30995@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO -Content-Length: 1580 -Lines: 51 +Content-Length: 1204 +Lines: 33 + +utrace_get_signal() checks JOBCTL_STOP_PENDING to detect the +case when we should not try to dequeue the signal but should +try to participate in the group-stop. + +With the recent changes this is not enough, everything which +contrbutes to recalc_sigpending_tsk() should be respected. + +Check JOBCTL_PENDING_MASK instead. This matches the +JOBCTL_STOP_PENDING | JOBCTL_TRAP_MASK code in the caller, +get_signal_to_deliver(). Note that this code won't run if +utrace_get_signal() returns signr > 0. + +Signed-off-by: Oleg Nesterov +--- + kernel/utrace.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/kernel/utrace.c b/kernel/utrace.c +index d41b982..0bb0a06 100644 +--- a/kernel/utrace.c ++++ b/kernel/utrace.c +@@ -2027,7 +2027,7 @@ int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, + ka = NULL; + memset(return_ka, 0, sizeof *return_ka); + } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || +- unlikely(task->jobctl & JOBCTL_STOP_PENDING)) { ++ unlikely(task->jobctl & JOBCTL_PENDING_MASK)) { + /* + * If no engine is interested in intercepting signals or + * we must stop, let the caller just dequeue them normally +-- +1.5.5.1 + + +From davej Wed Aug 3 15:16:03 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:16:03 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:13:19 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A9253DA3CB; + Wed, 3 Aug 2011 15:13:01 -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 HLlRhTJ2MbYS; Wed, 3 Aug 2011 15:13:01 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9582C4C43B; + Wed, 3 Aug 2011 15:13:01 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCsFX008586; + Wed, 3 Aug 2011 15:12:54 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:22 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:20 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 21/31] introduce ptrace_set_syscall_trace() +Message-ID: <20110803191020.GA31002@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Status: RO +Content-Length: 1549 +Lines: 52 No functional changes. Add the new helper, ptrace_set_syscall_trace(), which should be used to set/clear TIF_SYSCALL_TRACE in ptrace code. @@ -5473,10 +6176,10 @@ Signed-off-by: Oleg Nesterov 1 files changed, 10 insertions(+), 5 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 0b2aba5..b6fd922 100644 +index 1a50090..dc2ad34 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c -@@ -37,6 +37,14 @@ static void ptrace_signal_wake_up(struct task_struct *p, int quiescent) +@@ -38,6 +38,14 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent) kick_process(p); } @@ -5488,10 +6191,10 @@ index 0b2aba5..b6fd922 100644 + clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); +} + - /* - * ptrace a task: make the debugger its new parent and - * move it to the ptrace list. -@@ -364,7 +372,7 @@ static int ptrace_detach(struct task_struct *child, unsigned int data) + static int ptrace_trapping_sleep_fn(void *flags) + { + schedule(); +@@ -418,7 +426,7 @@ static int ptrace_detach(struct task_struct *child, unsigned int data) /* Architecture-specific hardware disable .. */ ptrace_disable(child); @@ -5500,7 +6203,7 @@ index 0b2aba5..b6fd922 100644 write_lock_irq(&tasklist_lock); /* -@@ -551,10 +559,7 @@ static int ptrace_resume(struct task_struct *child, long request, +@@ -606,10 +614,7 @@ static int ptrace_resume(struct task_struct *child, long request, if (!valid_signal(data)) return -EIO; @@ -5515,50 +6218,51 @@ index 0b2aba5..b6fd922 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:23 2011 + +From davej Wed Aug 3 15:21:45 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:23 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:21:45 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:33 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:43 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 585699C7DE; - Sun, 7 Aug 2011 15:18:33 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5C4889DEE6; + Wed, 3 Aug 2011 15:13:04 -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 Zp+5oAzhYq2W; Sun, 7 Aug 2011 15:18:33 -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 44532909E4; - Sun, 7 Aug 2011 15:18:33 -0400 (EDT) + with ESMTP id eXIPU4nVv+7Z; Wed, 3 Aug 2011 15:13:04 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 3F82C9DED6; + Wed, 3 Aug 2011 15:13:04 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIV6n020657; - Sun, 7 Aug 2011 15:18:31 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCueo029507; + Wed, 3 Aug 2011 15:12:57 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:54 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:52 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:24 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:22 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 14/22] introduce PT_SYSCALL_TRACE flag -Message-ID: <20110807191552.GA14429@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 22/31] introduce PT_SYSCALL_TRACE flag +Message-ID: <20110803191022.GA31005@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 2235 -Lines: 72 +Content-Length: 2268 +Lines: 73 Currently tracehooks assume that if the ptraced task has TIF_SYSCALL_TRACE set, the tracee should report the syscall. @@ -5577,33 +6281,33 @@ Signed-off-by: Oleg Nesterov 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h -index 9178d5c..98d995d 100644 +index 6d9282a..c10f610 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h -@@ -90,6 +90,8 @@ +@@ -104,6 +104,8 @@ #define PT_TRACE_MASK 0x000003f4 -+#define PT_SYSCALL_TRACE 0x00010000 ++#define PT_SYSCALL_TRACE 0x00020000 + /* single stepping state bits (used on ARM and PA-RISC) */ #define PT_SINGLESTEP_BIT 31 #define PT_SINGLESTEP (1<ptrace = 0; - if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) { +@@ -227,6 +229,7 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) + + if (unlikely(ptrace) && current->ptrace) { child->ptrace = current->ptrace; + child->ptrace &= ~PT_SYSCALL_TRACE; __ptrace_link(child, current->parent); - } + if (child->ptrace & PT_SEIZED) diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 3c7b6b3..6ce7a37 100644 +index ec2af67..eb9fe30 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h -@@ -76,7 +76,7 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) +@@ -59,7 +59,7 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) { - int ptrace = task_ptrace(current); + int ptrace = current->ptrace; - if (!(ptrace & PT_PTRACED)) + if (!(ptrace & PT_SYSCALL_TRACE)) @@ -5611,10 +6315,10 @@ index 3c7b6b3..6ce7a37 100644 ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index b6fd922..0825a01 100644 +index dc2ad34..7deb292 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c -@@ -39,10 +39,13 @@ static void ptrace_signal_wake_up(struct task_struct *p, int quiescent) +@@ -40,10 +40,13 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent) static void ptrace_set_syscall_trace(struct task_struct *p, bool on) { @@ -5629,55 +6333,56 @@ index b6fd922..0825a01 100644 + } } - /* + static int ptrace_trapping_sleep_fn(void *flags) -- 1.5.5.1 -From davej Sun Aug 7 15:19:24 2011 + +From davej Wed Aug 3 15:16:05 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:24 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:05 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:35 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:13:20 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F0377D89A9; - Sun, 7 Aug 2011 15:18:35 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E516ADA488; + Wed, 3 Aug 2011 15:13:06 -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 cBLqfABIHZ6h; Sun, 7 Aug 2011 15:18:35 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id DC799D8988; - Sun, 7 Aug 2011 15:18:35 -0400 (EDT) + with ESMTP id rP7Um8DZjclX; Wed, 3 Aug 2011 15:13:06 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D155EDA3F8; + Wed, 3 Aug 2011 15:13:06 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIXU3007727; - Sun, 7 Aug 2011 15:18:34 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCxfF029532; + Wed, 3 Aug 2011 15:13:00 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:57 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:55 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:27 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:25 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 15/22] utrace: don't clear TIF_SYSCALL_TRACE if it is +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 23/31] utrace: don't clear TIF_SYSCALL_TRACE if it is needed by ptrace -Message-ID: <20110807191555.GA14436@redhat.com> +Message-ID: <20110803191025.GA31012@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 796 -Lines: 23 +Content-Length: 797 +Lines: 24 TIF_SYSCALL_TRACE should be cleared only if both ptrace and utrace do not want it, change utrace_reset() to check PT_SYSCALL_TRACE before @@ -5689,7 +6394,7 @@ Signed-off-by: Oleg Nesterov 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/kernel/utrace.c b/kernel/utrace.c -index daa96b9..a824ac3 100644 +index 0bb0a06..bebf6de 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -697,6 +697,7 @@ static bool utrace_reset(struct task_struct *task, struct utrace *utrace) @@ -5703,50 +6408,51 @@ index daa96b9..a824ac3 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:25 2011 + +From davej Wed Aug 3 15:16:08 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:25 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:38 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:08 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:29 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A6B3C9C7DE; - Sun, 7 Aug 2011 15:18:38 -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 ln+MaW5alQl7; Sun, 7 Aug 2011 15:18:38 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8A6D2909E4; - Sun, 7 Aug 2011 15:18:38 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 80872DA4B2; + Wed, 3 Aug 2011 15:13:09 -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 AbpC0Wk1ZhtT; Wed, 3 Aug 2011 15:13:09 -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 6D97DDA3F8; + Wed, 3 Aug 2011 15:13:09 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIaYf007737; - Sun, 7 Aug 2011 15:18:36 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JD2RU022591; + Wed, 3 Aug 2011 15:13:02 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:16:00 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:58 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:30 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:28 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 16/22] introduce task_utrace_lock/task_utrace_unlock -Message-ID: <20110807191558.GA14440@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 24/31] introduce task_utrace_lock/task_utrace_unlock +Message-ID: <20110803191028.GA31015@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO -Content-Length: 2189 -Lines: 80 +Content-Length: 2190 +Lines: 81 - Add task_utrace_lock(task). It simply takes task->utrace->lock if this task was ever utraced. Otherwise it takes task_lock(), this @@ -5763,10 +6469,10 @@ Signed-off-by: Oleg Nesterov 2 files changed, 35 insertions(+), 0 deletions(-) diff --git a/include/linux/utrace.h b/include/linux/utrace.h -index f251efe..5176f5f 100644 +index 63103e2..f37373b 100644 --- a/include/linux/utrace.h +++ b/include/linux/utrace.h -@@ -109,6 +109,12 @@ void utrace_signal_handler(struct task_struct *, int); +@@ -117,6 +117,12 @@ void utrace_signal_handler(struct task_struct *, int); #ifndef CONFIG_UTRACE @@ -5779,7 +6485,7 @@ index f251efe..5176f5f 100644 /* * uses these accessors to avoid #ifdef CONFIG_UTRACE. */ -@@ -131,6 +137,9 @@ static inline void task_utrace_proc_status(struct seq_file *m, +@@ -139,6 +145,9 @@ static inline void task_utrace_proc_status(struct seq_file *m, #else /* CONFIG_UTRACE */ @@ -5790,7 +6496,7 @@ index f251efe..5176f5f 100644 { return task->utrace_flags; diff --git a/kernel/utrace.c b/kernel/utrace.c -index a824ac3..508c13c 100644 +index bebf6de..960dd9e 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -79,6 +79,32 @@ static int __init utrace_init(void) @@ -5829,51 +6535,52 @@ index a824ac3..508c13c 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:27 2011 + +From davej Wed Aug 3 15:21:46 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:27 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:41 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:21:46 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:43 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 41B111322A2; - Sun, 7 Aug 2011 15:18:41 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id ypKNrfgt9t+i; Sun, 7 Aug 2011 15:18:41 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2D805128FDA; - Sun, 7 Aug 2011 15:18:41 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 24B3E9DEF6; + Wed, 3 Aug 2011 15:13:12 -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 2jg9j3-p4bHL; Wed, 3 Aug 2011 15:13:12 -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 zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 119759DEF9; + Wed, 3 Aug 2011 15:13:12 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIdnm028810; - Sun, 7 Aug 2011 15:18:39 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JD485022603; + Wed, 3 Aug 2011 15:13:05 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:16:02 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:16:00 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:32 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:30 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 17/22] teach ptrace_set_syscall_trace() to play well with +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 25/31] teach ptrace_set_syscall_trace() to play well with utrace -Message-ID: <20110807191600.GA14443@redhat.com> +Message-ID: <20110803191030.GA31018@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO -Content-Length: 1512 -Lines: 48 +Content-Length: 1545 +Lines: 49 1. ptrace_set_syscall_trace(true)->set_tsk_thread_flag(TIF_SYSCALL_TRACE) can race with utrace_control()->utrace_reset() path which can miss @@ -5892,18 +6599,18 @@ Signed-off-by: Oleg Nesterov 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 0825a01..209ea2d 100644 +index 7deb292..69850e9 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c -@@ -23,6 +23,7 @@ - #include +@@ -24,6 +24,7 @@ #include #include + #include +#include - static void ptrace_signal_wake_up(struct task_struct *p, int quiescent) + void ptrace_signal_wake_up(struct task_struct *p, int quiescent) { -@@ -39,13 +40,16 @@ static void ptrace_signal_wake_up(struct task_struct *p, int quiescent) +@@ -40,13 +41,16 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent) static void ptrace_set_syscall_trace(struct task_struct *p, bool on) { @@ -5920,54 +6627,55 @@ index 0825a01..209ea2d 100644 + task_utrace_unlock(p); } - /* + static int ptrace_trapping_sleep_fn(void *flags) -- 1.5.5.1 -From davej Sun Aug 7 15:19:27 2011 + +From davej Wed Aug 3 15:16:29 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:27 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:43 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:28 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:24 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E37B59C7DE; - Sun, 7 Aug 2011 15:18:43 -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 NRVgSzxr7avy; Sun, 7 Aug 2011 15:18:43 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C6D6E909E4; - Sun, 7 Aug 2011 15:18:43 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 062709DE55; + Wed, 3 Aug 2011 15:13:15 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id lhwVoEywGaPJ; Wed, 3 Aug 2011 15:13:14 -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 zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E4C139DE11; + Wed, 3 Aug 2011 15:13:14 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIfAM007754; - Sun, 7 Aug 2011 15:18:42 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JD7Go010523; + Wed, 3 Aug 2011 15:13:08 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:16:05 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:16:03 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:35 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:33 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 18/22] introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK -Message-ID: <20110807191603.GA14450@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 26/31] introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK +Message-ID: <20110803191033.GA31025@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO -Content-Length: 3724 -Lines: 107 +Content-Length: 3723 +Lines: 108 Add the new internal ptrace flags, PT_SINGLE_STEP and PT_SINGLE_BLOCK. @@ -5987,10 +6695,10 @@ Signed-off-by: Oleg Nesterov 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c -index 807c2a2..7ab475f 100644 +index 8252879..d1557dc 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c -@@ -807,6 +807,7 @@ static int ioperm_get(struct task_struct *target, +@@ -808,6 +808,7 @@ static int ioperm_get(struct task_struct *target, */ void ptrace_disable(struct task_struct *child) { @@ -5999,33 +6707,33 @@ index 807c2a2..7ab475f 100644 #ifdef TIF_SYSCALL_EMU clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h -index 98d995d..65b1e4f 100644 +index c10f610..2743315 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h -@@ -91,6 +91,8 @@ +@@ -105,6 +105,8 @@ #define PT_TRACE_MASK 0x000003f4 - #define PT_SYSCALL_TRACE 0x00010000 -+#define PT_SINGLE_STEP 0x00020000 -+#define PT_SINGLE_BLOCK 0x00040000 + #define PT_SYSCALL_TRACE 0x00020000 ++#define PT_SINGLE_STEP 0x00040000 ++#define PT_SINGLE_BLOCK 0x00080000 /* single stepping state bits (used on ARM and PA-RISC) */ #define PT_SINGLESTEP_BIT 31 -@@ -189,7 +191,8 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) - child->ptrace = 0; - if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) { +@@ -229,7 +231,8 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) + + if (unlikely(ptrace) && current->ptrace) { child->ptrace = current->ptrace; - child->ptrace &= ~PT_SYSCALL_TRACE; + child->ptrace &= + ~(PT_SYSCALL_TRACE | PT_SINGLE_STEP | PT_SINGLE_BLOCK); __ptrace_link(child, current->parent); - } + if (child->ptrace & PT_SEIZED) diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 6ce7a37..06edb52 100644 +index eb9fe30..21c8ca2 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h -@@ -121,6 +121,9 @@ static inline __must_check int tracehook_report_syscall_entry( +@@ -104,6 +104,9 @@ static inline __must_check int tracehook_report_syscall_entry( return 0; } @@ -6035,7 +6743,7 @@ index 6ce7a37..06edb52 100644 /** * tracehook_report_syscall_exit - task has just finished a system call * @regs: user register state of current task -@@ -143,7 +146,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) +@@ -126,7 +129,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) utrace_report_syscall_exit(regs); @@ -6044,7 +6752,7 @@ index 6ce7a37..06edb52 100644 siginfo_t info; user_single_step_siginfo(current, regs, &info); force_sig_info(SIGTRAP, &info, current); -@@ -436,7 +439,7 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, +@@ -157,7 +160,7 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, { if (task_utrace_flags(current)) utrace_signal_handler(current, stepping); @@ -6054,10 +6762,10 @@ index 6ce7a37..06edb52 100644 } diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 209ea2d..44908d0 100644 +index 69850e9..d250a71 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c -@@ -575,13 +575,16 @@ static int ptrace_resume(struct task_struct *child, long request, +@@ -630,13 +630,16 @@ static int ptrace_resume(struct task_struct *child, long request, clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); #endif @@ -6077,51 +6785,52 @@ index 209ea2d..44908d0 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:29 2011 + +From davej Wed Aug 3 15:16:30 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:29 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:30 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:46 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:25 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 810E31322A2; - Sun, 7 Aug 2011 15:18:46 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B3BF49DE11; + Wed, 3 Aug 2011 15:13:17 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id ptiIThWTq2a6; Sun, 7 Aug 2011 15:18:46 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6B665128FDA; - Sun, 7 Aug 2011 15:18:46 -0400 (EDT) + with ESMTP id zC72ecV9Jz07; Wed, 3 Aug 2011 15:13:17 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 98ACE9DE59; + Wed, 3 Aug 2011 15:13:17 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIiI8007757; - Sun, 7 Aug 2011 15:18:44 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JDATh023726; + Wed, 3 Aug 2011 15:13:10 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:16:08 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:16:06 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:38 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:36 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 19/22] utrace: finish_resume_report: don't do +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 27/31] utrace: finish_resume_report: don't do user_xxx_step() if ptrace_wants_step() -Message-ID: <20110807191606.GA14453@redhat.com> +Message-ID: <20110803191036.GA31028@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 2740 -Lines: 83 +Content-Length: 2741 +Lines: 84 finish_resume_report() should not enable/disable the stepping if ptrace_wants_step() == T. If ptrace wants block_step while utrace @@ -6138,10 +6847,10 @@ Signed-off-by: Oleg Nesterov 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 06edb52..5612d2d 100644 +index 21c8ca2..b6812d4 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h -@@ -121,8 +121,8 @@ static inline __must_check int tracehook_report_syscall_entry( +@@ -104,8 +104,8 @@ static inline __must_check int tracehook_report_syscall_entry( return 0; } @@ -6152,7 +6861,7 @@ index 06edb52..5612d2d 100644 /** * tracehook_report_syscall_exit - task has just finished a system call -@@ -146,7 +146,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) +@@ -129,7 +129,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) utrace_report_syscall_exit(regs); @@ -6161,7 +6870,7 @@ index 06edb52..5612d2d 100644 siginfo_t info; user_single_step_siginfo(current, regs, &info); force_sig_info(SIGTRAP, &info, current); -@@ -439,7 +439,7 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, +@@ -160,7 +160,7 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, { if (task_utrace_flags(current)) utrace_signal_handler(current, stepping); @@ -6171,10 +6880,10 @@ index 06edb52..5612d2d 100644 } diff --git a/kernel/utrace.c b/kernel/utrace.c -index 508c13c..fbabb81 100644 +index 960dd9e..05e8532 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c -@@ -1828,7 +1828,8 @@ static void finish_resume_report(struct task_struct *task, +@@ -1829,7 +1829,8 @@ static void finish_resume_report(struct task_struct *task, case UTRACE_BLOCKSTEP: if (likely(arch_has_block_step())) { @@ -6184,7 +6893,7 @@ index 508c13c..fbabb81 100644 break; } -@@ -1841,7 +1842,8 @@ static void finish_resume_report(struct task_struct *task, +@@ -1842,7 +1843,8 @@ static void finish_resume_report(struct task_struct *task, case UTRACE_SINGLESTEP: if (likely(arch_has_single_step())) { @@ -6194,7 +6903,7 @@ index 508c13c..fbabb81 100644 } else { /* * This means some callback is to blame for failing -@@ -1856,7 +1858,8 @@ static void finish_resume_report(struct task_struct *task, +@@ -1857,7 +1859,8 @@ static void finish_resume_report(struct task_struct *task, case UTRACE_REPORT: case UTRACE_RESUME: default: @@ -6207,50 +6916,51 @@ index 508c13c..fbabb81 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:30 2011 + +From davej Wed Aug 3 15:16:32 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:30 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:49 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:32 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:25 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1C4A79C7DE; - Sun, 7 Aug 2011 15:18: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 GxHOzMqYQY8N; Sun, 7 Aug 2011 15:18:49 -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 zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 066D2909E4; - Sun, 7 Aug 2011 15:18:49 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 614CD9DE73; + Wed, 3 Aug 2011 15:13:20 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id jcWOXzUaaIYu; Wed, 3 Aug 2011 15:13:20 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 438889DE59; + Wed, 3 Aug 2011 15:13:20 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIkkD030034; - Sun, 7 Aug 2011 15:18:47 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JDDZ7029595; + Wed, 3 Aug 2011 15:13:13 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:16:10 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:16:08 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:40 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:38 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 20/22] ptrace: shift user_*_step() from ptrace_resume() to +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 28/31] ptrace: shift user_*_step() from ptrace_resume() to ptrace_stop() -Message-ID: <20110807191608.GA14460@redhat.com> +Message-ID: <20110803191038.GA31035@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 2384 +Content-Length: 2374 Lines: 70 1. ptrace_resume() plays with the stopped task which can be also @@ -6276,14 +6986,14 @@ Lines: 70 Signed-off-by: Oleg Nesterov --- kernel/ptrace.c | 4 ---- - kernel/signal.c | 12 ++++++++++++ - 2 files changed, 12 insertions(+), 4 deletions(-) + kernel/signal.c | 11 +++++++++++ + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 44908d0..d37b30d 100644 +index d250a71..d1ef124 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c -@@ -580,14 +580,10 @@ static int ptrace_resume(struct task_struct *child, long request, +@@ -635,14 +635,10 @@ static int ptrace_resume(struct task_struct *child, long request, if (unlikely(!arch_has_block_step())) return -EIO; child->ptrace |= PT_SINGLE_BLOCK; @@ -6299,14 +7009,13 @@ index 44908d0..d37b30d 100644 child->exit_code = data; diff --git a/kernel/signal.c b/kernel/signal.c -index d0e0c67..bc40bd7 100644 +index 3c783d3..43a3e77 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -1840,6 +1840,18 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) - } +@@ -1920,6 +1920,17 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) + + utrace_end_stop(); - tracehook_finish_stop(); -+ + if (current->ptrace & PT_SINGLE_BLOCK) + user_enable_block_step(current); + else if (current->ptrace & PT_SINGLE_STEP) @@ -6324,50 +7033,51 @@ index d0e0c67..bc40bd7 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:31 2011 + +From davej Wed Aug 3 15:16:34 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:31 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:51 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:34 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:25 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id AD8D0D89A9; - Sun, 7 Aug 2011 15:18:51 -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 LHAT6DyOymTI; Sun, 7 Aug 2011 15:18:51 -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 99798D8988; - Sun, 7 Aug 2011 15:18:51 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1A6019DE59; + Wed, 3 Aug 2011 15:13:23 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id db2hhAqFwsPu; Wed, 3 Aug 2011 15:13:23 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 034739DE83; + Wed, 3 Aug 2011 15:13:23 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIn3U030041; - Sun, 7 Aug 2011 15:18:50 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JDFNp008715; + Wed, 3 Aug 2011 15:13:16 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:16:13 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:16:11 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:43 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:41 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 21/22] ptrace_disable: no need to disable stepping -Message-ID: <20110807191611.GA14463@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 29/31] ptrace_disable: no need to disable stepping +Message-ID: <20110803191041.GA31039@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO -Content-Length: 944 -Lines: 28 +Content-Length: 945 +Lines: 29 ptrace_disable() is called when the tracee is quiescent and we are going to untrace. This means we are going to clear ->ptrace @@ -6383,10 +7093,10 @@ Signed-off-by: Oleg Nesterov 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c -index 7ab475f..f1cdc7d 100644 +index d1557dc..96d315a 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c -@@ -807,8 +807,6 @@ static int ioperm_get(struct task_struct *target, +@@ -808,8 +808,6 @@ static int ioperm_get(struct task_struct *target, */ void ptrace_disable(struct task_struct *child) { @@ -6398,50 +7108,51 @@ index 7ab475f..f1cdc7d 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:32 2011 + +From davej Wed Aug 3 15:21:48 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:32 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:54 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:21:48 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:52 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 57405D89A9; - Sun, 7 Aug 2011 15:18:54 -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 XgEdPuPz9LNX; Sun, 7 Aug 2011 15:18:54 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 42E6BD8988; - Sun, 7 Aug 2011 15:18:54 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 95706917AF; + Wed, 3 Aug 2011 15:13:25 -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 ctq4DF3wXncJ; Wed, 3 Aug 2011 15:13:25 -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 7FD14914AF; + Wed, 3 Aug 2011 15:13:25 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIqEO027919; - Sun, 7 Aug 2011 15:18:52 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JDIRO010579; + Wed, 3 Aug 2011 15:13:18 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:16:15 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:16:13 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:46 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:44 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 22/22] ptrace_report_syscall: check TIF_SYSCALL_EMU -Message-ID: <20110807191613.GA14470@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 30/31] ptrace_report_syscall: check TIF_SYSCALL_EMU +Message-ID: <20110803191044.GA31046@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO -Content-Length: 862 -Lines: 27 +Content-Length: 858 +Lines: 28 4d16a64 "introduce PT_SYSCALL_TRACE flag" breaks PTRACE_SYSEMU which doesn't set PT_SYSCALL_TRACE. @@ -6456,12 +7167,12 @@ Signed-off-by: Oleg Nesterov 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 5612d2d..ac833de 100644 +index b6812d4..90ca578 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h -@@ -76,7 +76,7 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) +@@ -59,7 +59,7 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) { - int ptrace = task_ptrace(current); + int ptrace = current->ptrace; - if (!(ptrace & PT_SYSCALL_TRACE)) + if (!(ptrace & PT_SYSCALL_TRACE) && !test_thread_flag(TIF_SYSCALL_EMU)) @@ -6471,7 +7182,81 @@ index 5612d2d..ac833de 100644 -- 1.5.5.1 -From davej Tue Aug 9 13:34:35 2011 + +From davej Wed Aug 3 15:21:49 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:21:49 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:52 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 400F49191F; + Wed, 3 Aug 2011 15:13:28 -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 UeLOLM29JRc7; Wed, 3 Aug 2011 15:13:28 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2D05C903F6; + Wed, 3 Aug 2011 15:13:28 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JDKCA023784; + Wed, 3 Aug 2011 15:13:21 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:48 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:46 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 31/31] utrace_resume: check irqs_disabled() to shut up + lockdep +Message-ID: <20110803191046.GA31049@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Status: RO +Content-Length: 823 +Lines: 26 + +utrace_resume() enables irqs unconditionally. With the recent changes +in lockdep.c this triggers the warning. Check irqs_disabled() before +local_irq_enable(). + +Signed-off-by: Oleg Nesterov +--- + kernel/utrace.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/kernel/utrace.c b/kernel/utrace.c +index 05e8532..c817a46 100644 +--- a/kernel/utrace.c ++++ b/kernel/utrace.c +@@ -1881,7 +1881,8 @@ void utrace_resume(struct task_struct *task, struct pt_regs *regs) + * code path leads to calling into get_signal_to_deliver(), which + * implicitly reenables them by virtue of spin_unlock_irq. + */ +- local_irq_enable(); ++ if (irqs_disabled()) /* make trace_hardirqs_on() happy */ ++ local_irq_enable(); + + /* + * If this flag is still set it's because there was a signal +-- +1.5.5.1 + + +From davej Tue Aug 9 13:39:54 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -6480,42 +7265,42 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Tue, 09 Aug 2011 13:34:35 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Tue, 9 Aug 2011 13:33:16 -0400 (EDT) + for (single-drop); Tue, 09 Aug 2011 13:39:54 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Tue, 9 Aug 2011 13:39:44 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 16B6E9EBAD; - Tue, 9 Aug 2011 13:33:16 -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 T2mXXk1FjIIy; Tue, 9 Aug 2011 13:33:16 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 025259EBA5; - Tue, 9 Aug 2011 13:33:16 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5FCAC12983C; + Tue, 9 Aug 2011 13:39:44 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id nDWbqog6fbHK; Tue, 9 Aug 2011 13:39:44 -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 zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4BEF712983B; + Tue, 9 Aug 2011 13:39:44 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p79HXDVF004054; - Tue, 9 Aug 2011 13:33:13 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p79HdahY022801; + Tue, 9 Aug 2011 13:39:37 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Tue, 9 Aug 2011 19:30:35 +0200 (CEST) -Date: Tue, 9 Aug 2011 19:30:33 +0200 + oleg@redhat.com; Tue, 9 Aug 2011 19:36:58 +0200 (CEST) +Date: Tue, 9 Aug 2011 19:36:56 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, Tony Breeds -Subject: [PATCH utrace-3.0 23/22] ptrace_report_syscall: check if +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH utrace-3.1 32/31] ptrace_report_syscall: check if TIF_SYSCALL_EMU is defined -Message-ID: <20110809173033.GA26443@redhat.com> -References: <20110701002053.GA25767@redhat.com> <20110807191434.GA13184@redhat.com> +Message-ID: <20110809173656.GC26443@redhat.com> +References: <20110802174514.GA23073@redhat.com> <20110803190806.GA30619@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO -Content-Length: 844 +Content-Length: 839 Lines: 31 From: Tony Breeds @@ -6528,12 +7313,12 @@ Signed-off-by: Oleg Nesterov 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index ac833de..d5baf86 100644 +index 90ca578..a1bac95 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h -@@ -76,8 +76,12 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) +@@ -59,8 +59,12 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) { - int ptrace = task_ptrace(current); + int ptrace = current->ptrace; - if (!(ptrace & PT_SYSCALL_TRACE) && !test_thread_flag(TIF_SYSCALL_EMU)) - return; @@ -6550,3 +7335,74 @@ index ac833de..d5baf86 100644 1.5.5.1 +From davej Thu Sep 1 14:14:49 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 01 Sep 2011 14:14:49 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Thu, 1 Sep 2011 14:13:55 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1BA199C63F; + Thu, 1 Sep 2011 14:13:55 -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 0vQx9zlcQB36; Thu, 1 Sep 2011 14:13:55 -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 zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 009959C63D; + Thu, 1 Sep 2011 14:13:55 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p81IDrDX015389; + Thu, 1 Sep 2011 14:13:54 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Thu, 1 Sep 2011 20:10:54 +0200 (CEST) +Date: Thu, 1 Sep 2011 20:10:53 +0200 +From: Oleg Nesterov +To: Dave Jones +Cc: kernel@lists.fedoraproject.org, cebbert@redhat.com +Subject: [PATCH F-16] bz735118: utrace: s390: fix the compile problem with + traps.c +Message-ID: <20110901181053.GA24990@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +Status: RO +Content-Length: 777 +Lines: 27 + +https://bugzilla.redhat.com/show_bug.cgi?id=735118 + +d99e60e5 "tracehooks: reintroduce tracehook_consider_fatal_signal()" +breaks the compilation of arch/s390/kernel/traps.c. Restore the +necessary include removed by upstream 73b7d40f commit. + +Signed-off-by: Oleg Nesterov +--- + arch/s390/kernel/traps.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c +index 1018ab6..50e975d 100644 +--- a/arch/s390/kernel/traps.c ++++ b/arch/s390/kernel/traps.c +@@ -18,7 +18,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +-- +1.5.5.1 + + diff --git a/vfs-fix-automount-for-negative-autofs-dentries.patch b/vfs-fix-automount-for-negative-autofs-dentries.patch deleted file mode 100644 index 7759ea6ae..000000000 --- a/vfs-fix-automount-for-negative-autofs-dentries.patch +++ /dev/null @@ -1,56 +0,0 @@ -From: David Howells -Date: Mon, 11 Jul 2011 13:20:57 +0000 (+0100) -Subject: VFS: Fix automount for negative autofs dentries -X-Git-Tag: v3.1-rc1~91^2~12 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=5a30d8a2b8ddd5102c440c7e5a7c8e1fd729c818 - -VFS: Fix automount for negative autofs dentries -[ backport for 3.0.x: LOOKUP_PARENT => LOOKUP_CONTINUE ] - -Autofs may set the DCACHE_NEED_AUTOMOUNT flag on negative dentries. These -need attention from the automounter daemon regardless of the LOOKUP_FOLLOW flag. - -Signed-off-by: David Howells -Acked-by: Ian Kent -Signed-off-by: Al Viro ---- - -diff --git a/fs/namei.c b/fs/namei.c -index f8c69d3..445fd5d 100644 ---- a/fs/namei.c -+++ b/fs/namei.c -@@ -716,19 +716,25 @@ static int follow_automount(struct path *path, unsigned flags, - if ((flags & LOOKUP_NO_AUTOMOUNT) && !(flags & LOOKUP_CONTINUE)) - return -EISDIR; /* we actually want to stop here */ - -- /* We want to mount if someone is trying to open/create a file of any -- * type under the mountpoint, wants to traverse through the mountpoint -- * or wants to open the mounted directory. -- * -+ /* - * We don't want to mount if someone's just doing a stat and they've - * set AT_SYMLINK_NOFOLLOW - unless they're stat'ing a directory and - * appended a '/' to the name. - */ -- if (!(flags & LOOKUP_FOLLOW) && -- !(flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY | -- LOOKUP_OPEN | LOOKUP_CREATE))) -- return -EISDIR; -- -+ if (!(flags & LOOKUP_FOLLOW)) { -+ /* We do, however, want to mount if someone wants to open or -+ * create a file of any type under the mountpoint, wants to -+ * traverse through the mountpoint or wants to open the mounted -+ * directory. -+ * Also, autofs may mark negative dentries as being automount -+ * points. These will need the attentions of the daemon to -+ * instantiate them before they can be used. -+ */ -+ if (!(flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY | -+ LOOKUP_OPEN | LOOKUP_CREATE)) && -+ path->dentry->d_inode) -+ return -EISDIR; -+ } - current->total_link_count++; - if (current->total_link_count >= 40) - return -ELOOP; diff --git a/x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch b/x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch deleted file mode 100644 index bda767af8..000000000 --- a/x86-Fetch-stack-from-regs-when-possible-in-dump_trac.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 47ce11a2b6519f9c7843223ea8e561eb71ea5896 Mon Sep 17 00:00:00 2001 -From: Frederic Weisbecker -Date: Thu, 30 Jun 2011 19:04:56 +0200 -Subject: [PATCH 2/2] x86: Fetch stack from regs when possible in dump_trace() - -When regs are passed to dump_stack(), we fetch the frame -pointer from the regs but the stack pointer is taken from -the current frame. - -Thus the frame and stack pointers may not come from the same -context. For example this can result in the unwinder to -think the context is in irq, due to the current value of -the stack, but the frame pointer coming from the regs points -to a frame from another place. It then tries to fix up -the irq link but ends up dereferencing a random frame -pointer that doesn't belong to the irq stack: - -[ 9131.706906] ------------[ cut here ]------------ -[ 9131.707003] WARNING: at arch/x86/kernel/dumpstack_64.c:129 dump_trace+0x2aa/0x330() -[ 9131.707003] Hardware name: AMD690VM-FMH -[ 9131.707003] Perf: bad frame pointer = 0000000000000005 in callchain -[ 9131.707003] Modules linked in: -[ 9131.707003] Pid: 1050, comm: perf Not tainted 3.0.0-rc3+ #181 -[ 9131.707003] Call Trace: -[ 9131.707003] [] warn_slowpath_common+0x7a/0xb0 -[ 9131.707003] [] warn_slowpath_fmt+0x41/0x50 -[ 9131.707003] [] ? bad_to_user+0x6d/0x10be -[ 9131.707003] [] dump_trace+0x2aa/0x330 -[ 9131.707003] [] ? native_sched_clock+0x13/0x50 -[ 9131.707003] [] perf_callchain_kernel+0x54/0x70 -[ 9131.707003] [] perf_prepare_sample+0x19f/0x2a0 -[ 9131.707003] [] __perf_event_overflow+0x16c/0x290 -[ 9131.707003] [] ? __perf_event_overflow+0x130/0x290 -[ 9131.707003] [] ? native_sched_clock+0x13/0x50 -[ 9131.707003] [] ? sched_clock+0x9/0x10 -[ 9131.707003] [] ? T.375+0x15/0x90 -[ 9131.707003] [] ? trace_hardirqs_on_caller+0x64/0x180 -[ 9131.707003] [] ? trace_hardirqs_off+0xd/0x10 -[ 9131.707003] [] perf_event_overflow+0x14/0x20 -[ 9131.707003] [] perf_swevent_hrtimer+0x11c/0x130 -[ 9131.707003] [] ? error_exit+0x51/0xb0 -[ 9131.707003] [] __run_hrtimer+0x83/0x1e0 -[ 9131.707003] [] ? perf_event_overflow+0x20/0x20 -[ 9131.707003] [] hrtimer_interrupt+0x106/0x250 -[ 9131.707003] [] ? trace_hardirqs_off_thunk+0x3a/0x3c -[ 9131.707003] [] smp_apic_timer_interrupt+0x53/0x90 -[ 9131.707003] [] apic_timer_interrupt+0x13/0x20 -[ 9131.707003] [] ? error_exit+0x51/0xb0 -[ 9131.707003] [] ? error_exit+0x4c/0xb0 -[ 9131.707003] ---[ end trace b2560d4876709347 ]--- - -Fix this by simply taking the stack pointer from regs->sp -when regs are provided. - -Signed-off-by: Frederic Weisbecker -Cc: Ingo Molnar -Cc: Thomas Gleixner -Cc: H. Peter Anvin -Cc: Peter Zijlstra -Cc: Arnaldo Carvalho de Melo ---- - arch/x86/kernel/dumpstack_64.c | 7 +++++-- - 1 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c -index e71c98d..788295c 100644 ---- a/arch/x86/kernel/dumpstack_64.c -+++ b/arch/x86/kernel/dumpstack_64.c -@@ -155,9 +155,12 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, - task = current; - - if (!stack) { -- stack = &dummy; -- if (task && task != current) -+ if (regs) -+ stack = (unsigned long *)regs->sp; -+ else if (task && task != current) - stack = (unsigned long *)task->thread.sp; -+ else -+ stack = &dummy; - } - - if (!bp) --- -1.7.6 - diff --git a/x86-Save-stack-pointer-in-perf-live-regs-savings.patch b/x86-Save-stack-pointer-in-perf-live-regs-savings.patch deleted file mode 100644 index 3964f10e9..000000000 --- a/x86-Save-stack-pointer-in-perf-live-regs-savings.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 9e46294dadedc0c04adcb8ce760bd2cd74f7332d Mon Sep 17 00:00:00 2001 -From: Frederic Weisbecker -Date: Sat, 2 Jul 2011 15:00:52 +0200 -Subject: [PATCH 1/2] x86: Save stack pointer in perf live regs savings - -In order to prepare for fetching the stack pointer from the -regs when possible in dump_trace() instead of taking the -local one, save the current stack pointer in perf live regs saving. - -Signed-off-by: Frederic Weisbecker -Cc: Ingo Molnar -Cc: Thomas Gleixner -Cc: H. Peter Anvin -Cc: Peter Zijlstra -Cc: Arnaldo Carvalho de Melo ---- - arch/x86/include/asm/perf_event.h | 5 +++++ - 1 files changed, 5 insertions(+), 0 deletions(-) - -diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h -index d9d4dae..094fb30 100644 ---- a/arch/x86/include/asm/perf_event.h -+++ b/arch/x86/include/asm/perf_event.h -@@ -152,6 +152,11 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs); - (regs)->bp = caller_frame_pointer(); \ - (regs)->cs = __KERNEL_CS; \ - regs->flags = 0; \ -+ asm volatile( \ -+ _ASM_MOV "%%"_ASM_SP ", %0\n" \ -+ : "=m" ((regs)->sp) \ -+ :: "memory" \ -+ ); \ - } - - #else --- -1.7.6 - diff --git a/x86-p4-make-watchdog-and-perf-work-together.patch b/x86-p4-make-watchdog-and-perf-work-together.patch deleted file mode 100644 index 9ef049b96..000000000 --- a/x86-p4-make-watchdog-and-perf-work-together.patch +++ /dev/null @@ -1,267 +0,0 @@ -BZ https://bugzilla.redhat.com/show_bug.cgi?id=713675 - -Let nmi watchdog and perf work together on a P4. Combination of the following 3.1 -upstream commits (the second commit reverts the first one). - -commit 1880c4ae182afb5650c5678949ecfe7ff66a724e -Author: Cyrill Gorcunov -Date: Thu Jun 23 16:49:18 2011 +0400 - - perf, x86: Add hw_watchdog_set_attr() in a sake of nmi-watchdog on P4 - - Due to restriction and specifics of Netburst PMU we need a separated - event for NMI watchdog. In particular every Netburst event - consumes not just a counter and a config register, but also an - additional ESCR register. - - Since ESCR registers are grouped upon counters (i.e. if ESCR is occupied - for some event there is no room for another event to enter until its - released) we need to pick up the "least" used ESCR (or the most available - one) for nmi-watchdog purposes -- so MSR_P4_CRU_ESCR2/3 was chosen. - - With this patch nmi-watchdog and perf top should be able to run simultaneously. - - Signed-off-by: Cyrill Gorcunov - CC: Lin Ming - CC: Arnaldo Carvalho de Melo - CC: Frederic Weisbecker - Tested-and-reviewed-by: Don Zickus - Tested-and-reviewed-by: Stephane Eranian - Signed-off-by: Peter Zijlstra - Link: http://lkml.kernel.org/r/20110623124918.GC13050@sun - Signed-off-by: Ingo Molnar - -commit f91298709790b9a483752ca3c967845537df2af3 -Author: Cyrill Gorcunov -Date: Sat Jul 9 00:17:12 2011 +0400 - - perf, x86: P4 PMU - Introduce event alias feature - - Instead of hw_nmi_watchdog_set_attr() weak function - and appropriate x86_pmu::hw_watchdog_set_attr() call - we introduce even alias mechanism which allow us - to drop this routines completely and isolate quirks - of Netburst architecture inside P4 PMU code only. - - The main idea remains the same though -- to allow - nmi-watchdog and perf top run simultaneously. - - Note the aliasing mechanism applies to generic - PERF_COUNT_HW_CPU_CYCLES event only because arbitrary - event (say passed as RAW initially) might have some - additional bits set inside ESCR register changing - the behaviour of event and we can't guarantee anymore - that alias event will give the same result. - - P.S. Thanks a huge to Don and Steven for for testing - and early review. - - Acked-by: Don Zickus - Tested-by: Steven Rostedt - Signed-off-by: Cyrill Gorcunov - CC: Ingo Molnar - CC: Peter Zijlstra - CC: Stephane Eranian - CC: Lin Ming - CC: Arnaldo Carvalho de Melo - CC: Frederic Weisbecker - Link: http://lkml.kernel.org/r/20110708201712.GS23657@sun - Signed-off-by: Steven Rostedt - - -diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h -index 56fd9e3..4d86c86 100644 ---- a/arch/x86/include/asm/perf_event_p4.h -+++ b/arch/x86/include/asm/perf_event_p4.h -@@ -102,6 +102,14 @@ - #define P4_CONFIG_HT (1ULL << P4_CONFIG_HT_SHIFT) - - /* -+ * If an event has alias it should be marked -+ * with a special bit. (Don't forget to check -+ * P4_PEBS_CONFIG_MASK and related bits on -+ * modification.) -+ */ -+#define P4_CONFIG_ALIASABLE (1 << 9) -+ -+/* - * The bits we allow to pass for RAW events - */ - #define P4_CONFIG_MASK_ESCR \ -@@ -123,6 +131,31 @@ - (p4_config_pack_escr(P4_CONFIG_MASK_ESCR)) | \ - (p4_config_pack_cccr(P4_CONFIG_MASK_CCCR)) - -+/* -+ * In case of event aliasing we need to preserve some -+ * caller bits otherwise the mapping won't be complete. -+ */ -+#define P4_CONFIG_EVENT_ALIAS_MASK \ -+ (p4_config_pack_escr(P4_CONFIG_MASK_ESCR) | \ -+ p4_config_pack_cccr(P4_CCCR_EDGE | \ -+ P4_CCCR_THRESHOLD_MASK | \ -+ P4_CCCR_COMPLEMENT | \ -+ P4_CCCR_COMPARE)) -+ -+#define P4_CONFIG_EVENT_ALIAS_IMMUTABLE_BITS \ -+ ((P4_CONFIG_HT) | \ -+ p4_config_pack_escr(P4_ESCR_T0_OS | \ -+ P4_ESCR_T0_USR | \ -+ P4_ESCR_T1_OS | \ -+ P4_ESCR_T1_USR) | \ -+ p4_config_pack_cccr(P4_CCCR_OVF | \ -+ P4_CCCR_CASCADE | \ -+ P4_CCCR_FORCE_OVF | \ -+ P4_CCCR_THREAD_ANY | \ -+ P4_CCCR_OVF_PMI_T0 | \ -+ P4_CCCR_OVF_PMI_T1 | \ -+ P4_CONFIG_ALIASABLE)) -+ - static inline bool p4_is_event_cascaded(u64 config) - { - u32 cccr = p4_config_unpack_cccr(config); -diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c -index ead584f..0c4071a 100644 ---- a/arch/x86/kernel/cpu/perf_event_p4.c -+++ b/arch/x86/kernel/cpu/perf_event_p4.c -@@ -556,11 +556,92 @@ static __initconst const u64 p4_hw_cache_event_ids - }, - }; - -+/* -+ * Because of Netburst being quite restricted in now -+ * many same events can run simultaneously, we use -+ * event aliases, ie different events which have the -+ * same functionallity but use non-intersected resources -+ * (ESCR/CCCR/couter registers). This allow us to run -+ * two or more semi-same events together. It is done -+ * transparently to a user space. -+ * -+ * Never set any cusom internal bits such as P4_CONFIG_HT, -+ * P4_CONFIG_ALIASABLE or bits for P4_PEBS_METRIC, they are -+ * either up-to-dated automatically either not appliable -+ * at all. -+ * -+ * And be really carefull choosing aliases! -+ */ -+struct p4_event_alias { -+ u64 orig; -+ u64 alter; -+} p4_event_aliases[] = { -+ { -+ /* -+ * Non-halted cycles can be substituted with -+ * non-sleeping cycles (see Intel SDM Vol3b for -+ * details). -+ */ -+ .orig = -+ p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_GLOBAL_POWER_EVENTS) | -+ P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)), -+ .alter = -+ p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_EXECUTION_EVENT) | -+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS0)| -+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS1)| -+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS2)| -+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS3)| -+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS0) | -+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS1) | -+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS2) | -+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS3))| -+ p4_config_pack_cccr(P4_CCCR_THRESHOLD(15) | P4_CCCR_COMPLEMENT | -+ P4_CCCR_COMPARE), -+ }, -+}; -+ -+static u64 p4_get_alias_event(u64 config) -+{ -+ u64 config_match; -+ int i; -+ -+ /* -+ * Probably we're lucky and don't have to do -+ * matching over all config bits. -+ */ -+ if (!(config & P4_CONFIG_ALIASABLE)) -+ return 0; -+ -+ config_match = config & P4_CONFIG_EVENT_ALIAS_MASK; -+ -+ /* -+ * If an event was previously swapped to the alter config -+ * we should swap it back otherwise contnention on registers -+ * will return back. -+ */ -+ for (i = 0; i < ARRAY_SIZE(p4_event_aliases); i++) { -+ if (config_match == p4_event_aliases[i].orig) { -+ config_match = p4_event_aliases[i].alter; -+ break; -+ } else if (config_match == p4_event_aliases[i].alter) { -+ config_match = p4_event_aliases[i].orig; -+ break; -+ } -+ } -+ -+ if (i >= ARRAY_SIZE(p4_event_aliases)) -+ return 0; -+ -+ return config_match | -+ (config & P4_CONFIG_EVENT_ALIAS_IMMUTABLE_BITS); -+} -+ - static u64 p4_general_events[PERF_COUNT_HW_MAX] = { - /* non-halted CPU clocks */ - [PERF_COUNT_HW_CPU_CYCLES] = - p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_GLOBAL_POWER_EVENTS) | -- P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)), -+ P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)) | -+ P4_CONFIG_ALIASABLE, - - /* - * retired instructions -@@ -1120,6 +1201,8 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign - struct p4_event_bind *bind; - unsigned int i, thread, num; - int cntr_idx, escr_idx; -+ u64 config_alias; -+ int pass; - - bitmap_zero(used_mask, X86_PMC_IDX_MAX); - bitmap_zero(escr_mask, P4_ESCR_MSR_TABLE_SIZE); -@@ -1128,6 +1211,17 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign - - hwc = &cpuc->event_list[i]->hw; - thread = p4_ht_thread(cpu); -+ pass = 0; -+ -+again: -+ /* -+ * Aliases are swappable so we may hit circular -+ * lock if both original config and alias need -+ * resources (MSR registers) which already busy. -+ */ -+ if (pass > 2) -+ goto done; -+ - bind = p4_config_get_bind(hwc->config); - escr_idx = p4_get_escr_idx(bind->escr_msr[thread]); - if (unlikely(escr_idx == -1)) -@@ -1141,8 +1235,17 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign - } - - cntr_idx = p4_next_cntr(thread, used_mask, bind); -- if (cntr_idx == -1 || test_bit(escr_idx, escr_mask)) -- goto done; -+ if (cntr_idx == -1 || test_bit(escr_idx, escr_mask)) { -+ /* -+ * Probably an event alias is still available. -+ */ -+ config_alias = p4_get_alias_event(hwc->config); -+ if (!config_alias) -+ goto done; -+ hwc->config = config_alias; -+ pass++; -+ goto again; -+ } - - p4_pmu_swap_config_ts(hwc, cpu); - if (assign) diff --git a/x86-pci-reduce-severity-of-host-bridge-window-conflict-warnings.patch b/x86-pci-reduce-severity-of-host-bridge-window-conflict-warnings.patch deleted file mode 100644 index 5db2f0051..000000000 --- a/x86-pci-reduce-severity-of-host-bridge-window-conflict-warnings.patch +++ /dev/null @@ -1,40 +0,0 @@ -From: Bjorn Helgaas -Date: Sat, 2 Jul 2011 16:47:12 +0000 (-0600) -Subject: x86/PCI: reduce severity of host bridge window conflict warnings -X-Git-Tag: v3.1-rc1~122^2~13 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=43d786ed4df4c54cb8802a523748a7d78130a2cb - -x86/PCI: reduce severity of host bridge window conflict warnings - -Host bridge windows are top-level resources, so if we find a host bridge -window conflict, it's probably with a hard-coded legacy reservation. -Moving host bridge windows is theoretically possible, but we don't support -it; we just ignore windows with conflicts, and it's not worth making this -a user-visible error. - -Reported-and-tested-by: Jools Wills -References: https://bugzilla.kernel.org/show_bug.cgi?id=38522 -Reported-by: Das -References: https://bugzilla.kernel.org/show_bug.cgi?id=16497 -Signed-off-by: Bjorn Helgaas -Signed-off-by: Jesse Barnes ---- - -diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c -index 68c3c13..ae3cb23 100644 ---- a/arch/x86/pci/acpi.c -+++ b/arch/x86/pci/acpi.c -@@ -246,10 +246,9 @@ static void add_resources(struct pci_root_info *info) - - conflict = insert_resource_conflict(root, res); - if (conflict) -- dev_err(&info->bridge->dev, -- "address space collision: host bridge window %pR " -- "conflicts with %s %pR\n", -- res, conflict->name, conflict); -+ dev_info(&info->bridge->dev, -+ "ignoring host bridge window %pR (conflicts with %s %pR)\n", -+ res, conflict->name, conflict); - else - pci_bus_add_resource(info->bus, res, 0); - } diff --git a/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch b/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch index 319f80dc5..9e810dba8 100644 --- a/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch +++ b/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch @@ -1,7 +1,40 @@ -From cbee73333a2d05c274240dff5de1b4bb74bfb497 Mon Sep 17 00:00:00 2001 +X-Spam-Checker-Version: SpamAssassin 3.4.0-r929098 (2010-03-30) on oss.sgi.com +X-Spam-Level: +X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,J_CHICKENPOX_64 + autolearn=no version=3.4.0-r929098 +Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) + by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id p9I1KBVD036341 + for ; Mon, 17 Oct 2011 20:20:11 -0500 +X-ASG-Debug-ID: 1318901280-3911029d0000-NocioJ +X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi +Received: from hades.usersys.redhat.com (localhost [127.0.0.1]) + by cuda.sgi.com (Spam Firewall) with ESMTP id B9D1DF75F0A + for ; Mon, 17 Oct 2011 18:28:01 -0700 (PDT) +Received: from hades.usersys.redhat.com ([187.60.101.4]) by cuda.sgi.com with ESMTP id 81CuyNdYBqrtvtnD for ; Mon, 17 Oct 2011 18:28:01 -0700 (PDT) +Received: by hades.usersys.redhat.com (Postfix, from userid 500) + id 5B763E089B; Tue, 18 Oct 2011 02:18:59 -0200 (BRST) From: Carlos Maiolino -Date: Tue, 18 Oct 2011 02:18:58 -0200 +To: xfs@oss.sgi.com +Cc: Carlos Maiolino +X-ASG-Orig-Subj: [PATCH] Fix possible memory corruption in xfs_readlink Subject: [PATCH] Fix possible memory corruption in xfs_readlink +Date: Tue, 18 Oct 2011 02:18:58 -0200 +Message-Id: <1318911538-9174-1-git-send-email-cmaiolino@redhat.com> +X-Mailer: git-send-email 1.7.6.2 +X-Barracuda-Connect: UNKNOWN[187.60.101.4] +X-Barracuda-Start-Time: 1318901282 +X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 +X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com +X-Barracuda-Spam-Score: -1.42 +X-Barracuda-Spam-Status: No, SCORE=-1.42 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=BSF_SC5_MJ1963, RDNS_NONE +X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.2.77645 + Rule breakdown below + pts rule name description + ---- ---------------------- -------------------------------------------------- + 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS + 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 +X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com +X-Virus-Status: Clean Fixes a possible memory corruption when the link is larger than MAXPATHLEN and XFS_DEBUG is not enabled. This also remove the @@ -10,18 +43,18 @@ xfs_readlink_by_handle() and via VFS. Signed-off-by: Carlos Maiolino --- - fs/xfs/xfs_vnodeops.c | 10 +++++++--- - 1 files changed, 7 insertions(+), 3 deletions(-) + fs/xfs/xfs_vnodeops.c | 11 ++++++++--- + 1 files changed, 8 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c -index 6197207..111870b 100644 +index 51fc429..c3288be 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c -@@ -545,13 +545,17 @@ xfs_readlink( +@@ -123,13 +123,18 @@ xfs_readlink( xfs_ilock(ip, XFS_ILOCK_SHARED); -- ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK); +- ASSERT(S_ISLNK(ip->i_d.di_mode)); - ASSERT(ip->i_d.di_size <= MAXPATHLEN); - pathlen = ip->i_d.di_size; @@ -34,10 +67,11 @@ index 6197207..111870b 100644 + ASSERT(0); + return XFS_ERROR(EFSCORRUPTED); + } ++ + if (ip->i_df.if_flags & XFS_IFINLINE) { memcpy(link, ip->i_df.if_u1.if_data, pathlen); link[pathlen] = '\0'; -- -1.7.6.4 +1.7.6.2 From d836bc7c953a5fd46dd6c971eeae91c67156a464 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 9 Nov 2011 14:09:53 -0500 Subject: [PATCH 205/397] Backport brcm80211 from 3.2-rc1 --- brcm80211.patch | 96991 ++++++++++++++++++++++++++++++++++++++++++++++ config-generic | 6 +- kernel.spec | 8 + 3 files changed, 97003 insertions(+), 2 deletions(-) create mode 100644 brcm80211.patch diff --git a/brcm80211.patch b/brcm80211.patch new file mode 100644 index 000000000..73c577f6d --- /dev/null +++ b/brcm80211.patch @@ -0,0 +1,96991 @@ +This patch represents the state of the brcm80211 driver as of 3.2-rc2, +plus a couple of one-line changes required to make it build on a 3.1 +base kernel. + +Obviously, this patch should be dropped completely when rebasing to the +final 3.2 kernel from upstream. + +-- John W. Linville + +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h.orig 2011-11-09 13:46:58.225800883 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h 2011-11-09 13:47:16.977566455 -0500 +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2011 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _bcmchip_h_ ++#define _bcmchip_h_ ++ ++/* bcm4329 */ ++/* SDIO device core, ID 0x829 */ ++#define BCM4329_CORE_BUS_BASE 0x18011000 ++/* internal memory core, ID 0x80e */ ++#define BCM4329_CORE_SOCRAM_BASE 0x18003000 ++/* ARM Cortex M3 core, ID 0x82a */ ++#define BCM4329_CORE_ARM_BASE 0x18002000 ++#define BCM4329_RAMSIZE 0x48000 ++/* firmware name */ ++#define BCM4329_FW_NAME "brcm/bcm4329-fullmac-4.bin" ++#define BCM4329_NV_NAME "brcm/bcm4329-fullmac-4.txt" ++ ++#endif /* _bcmchip_h_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c.orig 2011-11-09 13:46:58.226800871 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c 2011-11-09 13:47:16.978566442 -0500 +@@ -0,0 +1,371 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/* ****************** SDIO CARD Interface Functions **************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include "dhd.h" ++#include "dhd_bus.h" ++#include "dhd_dbg.h" ++#include "sdio_host.h" ++ ++#define SDIOH_API_ACCESS_RETRY_LIMIT 2 ++ ++static void brcmf_sdioh_irqhandler(struct sdio_func *func) ++{ ++ struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev); ++ ++ brcmf_dbg(TRACE, "***IRQHandler\n"); ++ ++ sdio_release_host(func); ++ ++ brcmf_sdbrcm_isr(sdiodev->bus); ++ ++ sdio_claim_host(func); ++} ++ ++int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev) ++{ ++ brcmf_dbg(TRACE, "Entering\n"); ++ ++ sdio_claim_host(sdiodev->func[1]); ++ sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler); ++ sdio_release_host(sdiodev->func[1]); ++ ++ return 0; ++} ++ ++int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev) ++{ ++ brcmf_dbg(TRACE, "Entering\n"); ++ ++ sdio_claim_host(sdiodev->func[1]); ++ sdio_release_irq(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func[1]); ++ ++ return 0; ++} ++ ++u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr, ++ int *err) ++{ ++ int status; ++ s32 retry = 0; ++ u8 data = 0; ++ ++ do { ++ if (retry) /* wait for 1 ms till bus get settled down */ ++ udelay(1000); ++ status = brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, fnc_num, ++ addr, (u8 *) &data); ++ } while (status != 0 ++ && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); ++ if (err) ++ *err = status; ++ ++ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n", ++ fnc_num, addr, data); ++ ++ return data; ++} ++ ++void ++brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr, ++ u8 data, int *err) ++{ ++ int status; ++ s32 retry = 0; ++ ++ do { ++ if (retry) /* wait for 1 ms till bus get settled down */ ++ udelay(1000); ++ status = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, fnc_num, ++ addr, (u8 *) &data); ++ } while (status != 0 ++ && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); ++ if (err) ++ *err = status; ++ ++ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n", ++ fnc_num, addr, data); ++} ++ ++int ++brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) ++{ ++ int err = 0; ++ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, ++ (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err); ++ if (!err) ++ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_SBADDRMID, ++ (address >> 16) & SBSDIO_SBADDRMID_MASK, ++ &err); ++ if (!err) ++ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_SBADDRHIGH, ++ (address >> 24) & SBSDIO_SBADDRHIGH_MASK, ++ &err); ++ ++ return err; ++} ++ ++u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size) ++{ ++ int status; ++ u32 word = 0; ++ uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; ++ ++ brcmf_dbg(INFO, "fun = 1, addr = 0x%x\n", addr); ++ ++ if (bar0 != sdiodev->sbwad) { ++ if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0)) ++ return 0xFFFFFFFF; ++ ++ sdiodev->sbwad = bar0; ++ } ++ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ if (size == 4) ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ ++ status = brcmf_sdioh_request_word(sdiodev, SDIOH_READ, SDIO_FUNC_1, ++ addr, &word, size); ++ ++ sdiodev->regfail = (status != 0); ++ ++ brcmf_dbg(INFO, "u32data = 0x%x\n", word); ++ ++ /* if ok, return appropriately masked word */ ++ if (status == 0) { ++ switch (size) { ++ case sizeof(u8): ++ return word & 0xff; ++ case sizeof(u16): ++ return word & 0xffff; ++ case sizeof(u32): ++ return word; ++ default: ++ sdiodev->regfail = true; ++ ++ } ++ } ++ ++ /* otherwise, bad sdio access or invalid size */ ++ brcmf_dbg(ERROR, "error reading addr 0x%04x size %d\n", addr, size); ++ return 0xFFFFFFFF; ++} ++ ++u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size, ++ u32 data) ++{ ++ int status; ++ uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; ++ int err = 0; ++ ++ brcmf_dbg(INFO, "fun = 1, addr = 0x%x, uint%ddata = 0x%x\n", ++ addr, size * 8, data); ++ ++ if (bar0 != sdiodev->sbwad) { ++ err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); ++ if (err) ++ return err; ++ ++ sdiodev->sbwad = bar0; ++ } ++ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ if (size == 4) ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ status = ++ brcmf_sdioh_request_word(sdiodev, SDIOH_WRITE, SDIO_FUNC_1, ++ addr, &data, size); ++ sdiodev->regfail = (status != 0); ++ ++ if (status == 0) ++ return 0; ++ ++ brcmf_dbg(ERROR, "error writing 0x%08x to addr 0x%04x size %d\n", ++ data, addr, size); ++ return 0xFFFFFFFF; ++} ++ ++bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev) ++{ ++ return sdiodev->regfail; ++} ++ ++int ++brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ++ uint flags, ++ u8 *buf, uint nbytes, struct sk_buff *pkt) ++{ ++ int status; ++ uint incr_fix; ++ uint width; ++ uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; ++ int err = 0; ++ ++ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes); ++ ++ /* Async not implemented yet */ ++ if (flags & SDIO_REQ_ASYNC) ++ return -ENOTSUPP; ++ ++ if (bar0 != sdiodev->sbwad) { ++ err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); ++ if (err) ++ return err; ++ ++ sdiodev->sbwad = bar0; ++ } ++ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ ++ incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; ++ width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; ++ if (width == 4) ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ ++ status = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ, ++ fn, addr, width, nbytes, buf, pkt); ++ ++ return status; ++} ++ ++int ++brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ++ uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt) ++{ ++ uint incr_fix; ++ uint width; ++ uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; ++ int err = 0; ++ ++ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes); ++ ++ /* Async not implemented yet */ ++ if (flags & SDIO_REQ_ASYNC) ++ return -ENOTSUPP; ++ ++ if (bar0 != sdiodev->sbwad) { ++ err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); ++ if (err) ++ return err; ++ ++ sdiodev->sbwad = bar0; ++ } ++ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ ++ incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; ++ width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; ++ if (width == 4) ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ ++ return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn, ++ addr, width, nbytes, buf, pkt); ++} ++ ++int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr, ++ u8 *buf, uint nbytes) ++{ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ ++ return brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC, ++ (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1, ++ addr, 4, nbytes, buf, NULL); ++} ++ ++int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn) ++{ ++ char t_func = (char)fn; ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* issue abort cmd52 command through F0 */ ++ brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0, ++ SDIO_CCCR_ABORT, &t_func); ++ ++ brcmf_dbg(TRACE, "Exit\n"); ++ return 0; ++} ++ ++int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) ++{ ++ u32 regs = 0; ++ int ret = 0; ++ ++ ret = brcmf_sdioh_attach(sdiodev); ++ if (ret) ++ goto out; ++ ++ regs = SI_ENUM_BASE; ++ ++ /* Report the BAR, to fix if needed */ ++ sdiodev->sbwad = SI_ENUM_BASE; ++ ++ /* try to attach to the target device */ ++ sdiodev->bus = brcmf_sdbrcm_probe(0, 0, 0, 0, regs, sdiodev); ++ if (!sdiodev->bus) { ++ brcmf_dbg(ERROR, "device attach failed\n"); ++ ret = -ENODEV; ++ goto out; ++ } ++ ++out: ++ if (ret) ++ brcmf_sdio_remove(sdiodev); ++ ++ return ret; ++} ++EXPORT_SYMBOL(brcmf_sdio_probe); ++ ++int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev) ++{ ++ if (sdiodev->bus) { ++ brcmf_sdbrcm_disconnect(sdiodev->bus); ++ sdiodev->bus = NULL; ++ } ++ ++ brcmf_sdioh_detach(sdiodev); ++ ++ sdiodev->sbwad = 0; ++ ++ return 0; ++} ++EXPORT_SYMBOL(brcmf_sdio_remove); ++ ++void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable) ++{ ++ if (enable) ++ brcmf_sdbrcm_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS); ++ else ++ brcmf_sdbrcm_wd_timer(sdiodev->bus, 0); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c.orig 2011-11-09 13:46:58.228800847 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c 2011-11-09 13:47:16.980566416 -0500 +@@ -0,0 +1,626 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* request_irq() */ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include "sdio_host.h" ++#include "dhd.h" ++#include "dhd_dbg.h" ++#include "wl_cfg80211.h" ++ ++#define SDIO_VENDOR_ID_BROADCOM 0x02d0 ++ ++#define DMA_ALIGN_MASK 0x03 ++ ++#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 ++ ++#define SDIO_FUNC1_BLOCKSIZE 64 ++#define SDIO_FUNC2_BLOCKSIZE 512 ++ ++/* devices we support, null terminated */ ++static const struct sdio_device_id brcmf_sdmmc_ids[] = { ++ {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, ++ { /* end: all zeroes */ }, ++}; ++MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); ++ ++static bool ++brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev) ++{ ++ bool is_err = false; ++#ifdef CONFIG_PM_SLEEP ++ is_err = atomic_read(&sdiodev->suspend); ++#endif ++ return is_err; ++} ++ ++static void ++brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, wait_queue_head_t *wq) ++{ ++#ifdef CONFIG_PM_SLEEP ++ int retry = 0; ++ while (atomic_read(&sdiodev->suspend) && retry++ != 30) ++ wait_event_timeout(*wq, false, HZ/100); ++#endif ++} ++ ++static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, ++ uint regaddr, u8 *byte) ++{ ++ struct sdio_func *sdfunc = sdiodev->func[0]; ++ int err_ret; ++ ++ /* ++ * Can only directly write to some F0 registers. ++ * Handle F2 enable/disable and Abort command ++ * as a special case. ++ */ ++ if (regaddr == SDIO_CCCR_IOEx) { ++ sdfunc = sdiodev->func[2]; ++ if (sdfunc) { ++ sdio_claim_host(sdfunc); ++ if (*byte & SDIO_FUNC_ENABLE_2) { ++ /* Enable Function 2 */ ++ err_ret = sdio_enable_func(sdfunc); ++ if (err_ret) ++ brcmf_dbg(ERROR, ++ "enable F2 failed:%d\n", ++ err_ret); ++ } else { ++ /* Disable Function 2 */ ++ err_ret = sdio_disable_func(sdfunc); ++ if (err_ret) ++ brcmf_dbg(ERROR, ++ "Disable F2 failed:%d\n", ++ err_ret); ++ } ++ sdio_release_host(sdfunc); ++ } ++ } else if (regaddr == SDIO_CCCR_ABORT) { ++ sdio_claim_host(sdfunc); ++ sdio_writeb(sdfunc, *byte, regaddr, &err_ret); ++ sdio_release_host(sdfunc); ++ } else if (regaddr < 0xF0) { ++ brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr); ++ err_ret = -EPERM; ++ } else { ++ sdio_claim_host(sdfunc); ++ sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret); ++ sdio_release_host(sdfunc); ++ } ++ ++ return err_ret; ++} ++ ++int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, ++ uint regaddr, u8 *byte) ++{ ++ int err_ret; ++ ++ brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr); ++ ++ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait); ++ if (brcmf_pm_resume_error(sdiodev)) ++ return -EIO; ++ ++ if (rw && func == 0) { ++ /* handle F0 separately */ ++ err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte); ++ } else { ++ sdio_claim_host(sdiodev->func[func]); ++ if (rw) /* CMD52 Write */ ++ sdio_writeb(sdiodev->func[func], *byte, regaddr, ++ &err_ret); ++ else if (func == 0) { ++ *byte = sdio_f0_readb(sdiodev->func[func], regaddr, ++ &err_ret); ++ } else { ++ *byte = sdio_readb(sdiodev->func[func], regaddr, ++ &err_ret); ++ } ++ sdio_release_host(sdiodev->func[func]); ++ } ++ ++ if (err_ret) ++ brcmf_dbg(ERROR, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", ++ rw ? "write" : "read", func, regaddr, *byte, err_ret); ++ ++ return err_ret; ++} ++ ++int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, ++ uint rw, uint func, uint addr, u32 *word, ++ uint nbytes) ++{ ++ int err_ret = -EIO; ++ ++ if (func == 0) { ++ brcmf_dbg(ERROR, "Only CMD52 allowed to F0\n"); ++ return -EINVAL; ++ } ++ ++ brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", ++ rw, func, addr, nbytes); ++ ++ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); ++ if (brcmf_pm_resume_error(sdiodev)) ++ return -EIO; ++ /* Claim host controller */ ++ sdio_claim_host(sdiodev->func[func]); ++ ++ if (rw) { /* CMD52 Write */ ++ if (nbytes == 4) ++ sdio_writel(sdiodev->func[func], *word, addr, ++ &err_ret); ++ else if (nbytes == 2) ++ sdio_writew(sdiodev->func[func], (*word & 0xFFFF), ++ addr, &err_ret); ++ else ++ brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes); ++ } else { /* CMD52 Read */ ++ if (nbytes == 4) ++ *word = sdio_readl(sdiodev->func[func], addr, &err_ret); ++ else if (nbytes == 2) ++ *word = sdio_readw(sdiodev->func[func], addr, ++ &err_ret) & 0xFFFF; ++ else ++ brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes); ++ } ++ ++ /* Release host controller */ ++ sdio_release_host(sdiodev->func[func]); ++ ++ if (err_ret) ++ brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n", ++ rw ? "write" : "read", err_ret); ++ ++ return err_ret; ++} ++ ++static int ++brcmf_sdioh_request_packet(struct brcmf_sdio_dev *sdiodev, uint fix_inc, ++ uint write, uint func, uint addr, ++ struct sk_buff *pkt) ++{ ++ bool fifo = (fix_inc == SDIOH_DATA_FIX); ++ u32 SGCount = 0; ++ int err_ret = 0; ++ ++ struct sk_buff *pnext; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_packet_wait); ++ if (brcmf_pm_resume_error(sdiodev)) ++ return -EIO; ++ ++ /* Claim host controller */ ++ sdio_claim_host(sdiodev->func[func]); ++ for (pnext = pkt; pnext; pnext = pnext->next) { ++ uint pkt_len = pnext->len; ++ pkt_len += 3; ++ pkt_len &= 0xFFFFFFFC; ++ ++ if ((write) && (!fifo)) { ++ err_ret = sdio_memcpy_toio(sdiodev->func[func], addr, ++ ((u8 *) (pnext->data)), ++ pkt_len); ++ } else if (write) { ++ err_ret = sdio_memcpy_toio(sdiodev->func[func], addr, ++ ((u8 *) (pnext->data)), ++ pkt_len); ++ } else if (fifo) { ++ err_ret = sdio_readsb(sdiodev->func[func], ++ ((u8 *) (pnext->data)), ++ addr, pkt_len); ++ } else { ++ err_ret = sdio_memcpy_fromio(sdiodev->func[func], ++ ((u8 *) (pnext->data)), ++ addr, pkt_len); ++ } ++ ++ if (err_ret) { ++ brcmf_dbg(ERROR, "%s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n", ++ write ? "TX" : "RX", pnext, SGCount, addr, ++ pkt_len, err_ret); ++ } else { ++ brcmf_dbg(TRACE, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n", ++ write ? "TX" : "RX", pnext, SGCount, addr, ++ pkt_len); ++ } ++ ++ if (!fifo) ++ addr += pkt_len; ++ SGCount++; ++ ++ } ++ ++ /* Release host controller */ ++ sdio_release_host(sdiodev->func[func]); ++ ++ brcmf_dbg(TRACE, "Exit\n"); ++ return err_ret; ++} ++ ++/* ++ * This function takes a buffer or packet, and fixes everything up ++ * so that in the end, a DMA-able packet is created. ++ * ++ * A buffer does not have an associated packet pointer, ++ * and may or may not be aligned. ++ * A packet may consist of a single packet, or a packet chain. ++ * If it is a packet chain, then all the packets in the chain ++ * must be properly aligned. ++ * ++ * If the packet data is not aligned, then there may only be ++ * one packet, and in this case, it is copied to a new ++ * aligned packet. ++ * ++ */ ++int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, ++ uint fix_inc, uint write, uint func, uint addr, ++ uint reg_width, uint buflen_u, u8 *buffer, ++ struct sk_buff *pkt) ++{ ++ int Status; ++ struct sk_buff *mypkt = NULL; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); ++ if (brcmf_pm_resume_error(sdiodev)) ++ return -EIO; ++ /* Case 1: we don't have a packet. */ ++ if (pkt == NULL) { ++ brcmf_dbg(DATA, "Creating new %s Packet, len=%d\n", ++ write ? "TX" : "RX", buflen_u); ++ mypkt = brcmu_pkt_buf_get_skb(buflen_u); ++ if (!mypkt) { ++ brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n", ++ buflen_u); ++ return -EIO; ++ } ++ ++ /* For a write, copy the buffer data into the packet. */ ++ if (write) ++ memcpy(mypkt->data, buffer, buflen_u); ++ ++ Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write, ++ func, addr, mypkt); ++ ++ /* For a read, copy the packet data back to the buffer. */ ++ if (!write) ++ memcpy(buffer, mypkt->data, buflen_u); ++ ++ brcmu_pkt_buf_free_skb(mypkt); ++ } else if (((ulong) (pkt->data) & DMA_ALIGN_MASK) != 0) { ++ /* ++ * Case 2: We have a packet, but it is unaligned. ++ * In this case, we cannot have a chain (pkt->next == NULL) ++ */ ++ brcmf_dbg(DATA, "Creating aligned %s Packet, len=%d\n", ++ write ? "TX" : "RX", pkt->len); ++ mypkt = brcmu_pkt_buf_get_skb(pkt->len); ++ if (!mypkt) { ++ brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n", ++ pkt->len); ++ return -EIO; ++ } ++ ++ /* For a write, copy the buffer data into the packet. */ ++ if (write) ++ memcpy(mypkt->data, pkt->data, pkt->len); ++ ++ Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write, ++ func, addr, mypkt); ++ ++ /* For a read, copy the packet data back to the buffer. */ ++ if (!write) ++ memcpy(pkt->data, mypkt->data, mypkt->len); ++ ++ brcmu_pkt_buf_free_skb(mypkt); ++ } else { /* case 3: We have a packet and ++ it is aligned. */ ++ brcmf_dbg(DATA, "Aligned %s Packet, direct DMA\n", ++ write ? "Tx" : "Rx"); ++ Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write, ++ func, addr, pkt); ++ } ++ ++ return Status; ++} ++ ++/* Read client card reg */ ++static int ++brcmf_sdioh_card_regread(struct brcmf_sdio_dev *sdiodev, int func, u32 regaddr, ++ int regsize, u32 *data) ++{ ++ ++ if ((func == 0) || (regsize == 1)) { ++ u8 temp = 0; ++ ++ brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, func, regaddr, ++ &temp); ++ *data = temp; ++ *data &= 0xff; ++ brcmf_dbg(DATA, "byte read data=0x%02x\n", *data); ++ } else { ++ brcmf_sdioh_request_word(sdiodev, SDIOH_READ, func, regaddr, ++ data, regsize); ++ if (regsize == 2) ++ *data &= 0xffff; ++ ++ brcmf_dbg(DATA, "word read data=0x%08x\n", *data); ++ } ++ ++ return SUCCESS; ++} ++ ++static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr) ++{ ++ /* read 24 bits and return valid 17 bit addr */ ++ int i; ++ u32 scratch, regdata; ++ __le32 scratch_le; ++ u8 *ptr = (u8 *)&scratch_le; ++ ++ for (i = 0; i < 3; i++) { ++ if ((brcmf_sdioh_card_regread(sdiodev, 0, regaddr, 1, ++ ®data)) != SUCCESS) ++ brcmf_dbg(ERROR, "Can't read!\n"); ++ ++ *ptr++ = (u8) regdata; ++ regaddr++; ++ } ++ ++ /* Only the lower 17-bits are valid */ ++ scratch = le32_to_cpu(scratch_le); ++ scratch &= 0x0001FFFF; ++ return scratch; ++} ++ ++static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev) ++{ ++ int err_ret; ++ u32 fbraddr; ++ u8 func; ++ ++ brcmf_dbg(TRACE, "\n"); ++ ++ /* Get the Card's common CIS address */ ++ sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev, ++ SDIO_CCCR_CIS); ++ brcmf_dbg(INFO, "Card's Common CIS Ptr = 0x%x\n", ++ sdiodev->func_cis_ptr[0]); ++ ++ /* Get the Card's function CIS (for each function) */ ++ for (fbraddr = SDIO_FBR_BASE(1), func = 1; ++ func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { ++ sdiodev->func_cis_ptr[func] = ++ brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr); ++ brcmf_dbg(INFO, "Function %d CIS Ptr = 0x%x\n", ++ func, sdiodev->func_cis_ptr[func]); ++ } ++ ++ /* Enable Function 1 */ ++ sdio_claim_host(sdiodev->func[1]); ++ err_ret = sdio_enable_func(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func[1]); ++ if (err_ret) ++ brcmf_dbg(ERROR, "Failed to enable F1 Err: 0x%08x\n", err_ret); ++ ++ return false; ++} ++ ++/* ++ * Public entry points & extern's ++ */ ++int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev) ++{ ++ int err_ret = 0; ++ ++ brcmf_dbg(TRACE, "\n"); ++ ++ sdiodev->num_funcs = 2; ++ ++ sdio_claim_host(sdiodev->func[1]); ++ err_ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE); ++ sdio_release_host(sdiodev->func[1]); ++ if (err_ret) { ++ brcmf_dbg(ERROR, "Failed to set F1 blocksize\n"); ++ goto out; ++ } ++ ++ sdio_claim_host(sdiodev->func[2]); ++ err_ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE); ++ sdio_release_host(sdiodev->func[2]); ++ if (err_ret) { ++ brcmf_dbg(ERROR, "Failed to set F2 blocksize\n"); ++ goto out; ++ } ++ ++ brcmf_sdioh_enablefuncs(sdiodev); ++ ++out: ++ brcmf_dbg(TRACE, "Done\n"); ++ return err_ret; ++} ++ ++void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev) ++{ ++ brcmf_dbg(TRACE, "\n"); ++ ++ /* Disable Function 2 */ ++ sdio_claim_host(sdiodev->func[2]); ++ sdio_disable_func(sdiodev->func[2]); ++ sdio_release_host(sdiodev->func[2]); ++ ++ /* Disable Function 1 */ ++ sdio_claim_host(sdiodev->func[1]); ++ sdio_disable_func(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func[1]); ++ ++} ++ ++static int brcmf_ops_sdio_probe(struct sdio_func *func, ++ const struct sdio_device_id *id) ++{ ++ int ret = 0; ++ struct brcmf_sdio_dev *sdiodev; ++ brcmf_dbg(TRACE, "Enter\n"); ++ brcmf_dbg(TRACE, "func->class=%x\n", func->class); ++ brcmf_dbg(TRACE, "sdio_vendor: 0x%04x\n", func->vendor); ++ brcmf_dbg(TRACE, "sdio_device: 0x%04x\n", func->device); ++ brcmf_dbg(TRACE, "Function#: 0x%04x\n", func->num); ++ ++ if (func->num == 1) { ++ if (dev_get_drvdata(&func->card->dev)) { ++ brcmf_dbg(ERROR, "card private drvdata occupied\n"); ++ return -ENXIO; ++ } ++ sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL); ++ if (!sdiodev) ++ return -ENOMEM; ++ sdiodev->func[0] = func->card->sdio_func[0]; ++ sdiodev->func[1] = func; ++ dev_set_drvdata(&func->card->dev, sdiodev); ++ ++ atomic_set(&sdiodev->suspend, false); ++ init_waitqueue_head(&sdiodev->request_byte_wait); ++ init_waitqueue_head(&sdiodev->request_word_wait); ++ init_waitqueue_head(&sdiodev->request_packet_wait); ++ init_waitqueue_head(&sdiodev->request_buffer_wait); ++ } ++ ++ if (func->num == 2) { ++ sdiodev = dev_get_drvdata(&func->card->dev); ++ if ((!sdiodev) || (sdiodev->func[1]->card != func->card)) ++ return -ENODEV; ++ sdiodev->func[2] = func; ++ ++ brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n"); ++ ret = brcmf_sdio_probe(sdiodev); ++ } ++ ++ return ret; ++} ++ ++static void brcmf_ops_sdio_remove(struct sdio_func *func) ++{ ++ struct brcmf_sdio_dev *sdiodev; ++ brcmf_dbg(TRACE, "Enter\n"); ++ brcmf_dbg(INFO, "func->class=%x\n", func->class); ++ brcmf_dbg(INFO, "sdio_vendor: 0x%04x\n", func->vendor); ++ brcmf_dbg(INFO, "sdio_device: 0x%04x\n", func->device); ++ brcmf_dbg(INFO, "Function#: 0x%04x\n", func->num); ++ ++ if (func->num == 2) { ++ sdiodev = dev_get_drvdata(&func->card->dev); ++ brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n"); ++ brcmf_sdio_remove(sdiodev); ++ dev_set_drvdata(&func->card->dev, NULL); ++ kfree(sdiodev); ++ } ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int brcmf_sdio_suspend(struct device *dev) ++{ ++ mmc_pm_flag_t sdio_flags; ++ struct brcmf_sdio_dev *sdiodev; ++ struct sdio_func *func = dev_to_sdio_func(dev); ++ int ret = 0; ++ ++ brcmf_dbg(TRACE, "\n"); ++ ++ sdiodev = dev_get_drvdata(&func->card->dev); ++ ++ atomic_set(&sdiodev->suspend, true); ++ ++ sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]); ++ if (!(sdio_flags & MMC_PM_KEEP_POWER)) { ++ brcmf_dbg(ERROR, "Host can't keep power while suspended\n"); ++ return -EINVAL; ++ } ++ ++ ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER); ++ if (ret) { ++ brcmf_dbg(ERROR, "Failed to set pm_flags\n"); ++ return ret; ++ } ++ ++ brcmf_sdio_wdtmr_enable(sdiodev, false); ++ ++ return ret; ++} ++ ++static int brcmf_sdio_resume(struct device *dev) ++{ ++ struct brcmf_sdio_dev *sdiodev; ++ struct sdio_func *func = dev_to_sdio_func(dev); ++ ++ sdiodev = dev_get_drvdata(&func->card->dev); ++ brcmf_sdio_wdtmr_enable(sdiodev, true); ++ atomic_set(&sdiodev->suspend, false); ++ return 0; ++} ++ ++static const struct dev_pm_ops brcmf_sdio_pm_ops = { ++ .suspend = brcmf_sdio_suspend, ++ .resume = brcmf_sdio_resume, ++}; ++#endif /* CONFIG_PM_SLEEP */ ++ ++static struct sdio_driver brcmf_sdmmc_driver = { ++ .probe = brcmf_ops_sdio_probe, ++ .remove = brcmf_ops_sdio_remove, ++ .name = "brcmfmac", ++ .id_table = brcmf_sdmmc_ids, ++#ifdef CONFIG_PM_SLEEP ++ .drv = { ++ .pm = &brcmf_sdio_pm_ops, ++ }, ++#endif /* CONFIG_PM_SLEEP */ ++}; ++ ++/* bus register interface */ ++int brcmf_bus_register(void) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ return sdio_register_driver(&brcmf_sdmmc_driver); ++} ++ ++void brcmf_bus_unregister(void) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ sdio_unregister_driver(&brcmf_sdmmc_driver); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h.orig 2011-11-09 13:46:58.229800834 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h 2011-11-09 13:47:16.980566416 -0500 +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCMF_BUS_H_ ++#define _BRCMF_BUS_H_ ++ ++/* Packet alignment for most efficient SDIO (can change based on platform) */ ++#define BRCMF_SDALIGN (1 << 6) ++ ++/* watchdog polling interval in ms */ ++#define BRCMF_WD_POLL_MS 10 ++ ++/* ++ * Exported from brcmf bus module (brcmf_usb, brcmf_sdio) ++ */ ++ ++/* Indicate (dis)interest in finding dongles. */ ++extern int brcmf_bus_register(void); ++extern void brcmf_bus_unregister(void); ++ ++/* obtain linux device object providing bus function */ ++extern struct device *brcmf_bus_get_device(struct brcmf_bus *bus); ++ ++/* Stop bus module: clear pending frames, disable data flow */ ++extern void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus); ++ ++/* Initialize bus module: prepare for communication w/dongle */ ++extern int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr); ++ ++/* Send a data frame to the dongle. Callee disposes of txp. */ ++extern int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *txp); ++ ++/* Send/receive a control message to/from the dongle. ++ * Expects caller to enforce a single outstanding transaction. ++ */ ++extern int ++brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen); ++ ++extern int ++brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen); ++ ++extern void brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick); ++ ++#endif /* _BRCMF_BUS_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c.orig 2011-11-09 13:46:58.230800821 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c 2011-11-09 13:47:16.981566403 -0500 +@@ -0,0 +1,498 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/******************************************************************************* ++ * Communicates with the dongle by using dcmd codes. ++ * For certain dcmd codes, the dongle interprets string data from the host. ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "dhd.h" ++#include "dhd_proto.h" ++#include "dhd_bus.h" ++#include "dhd_dbg.h" ++ ++struct brcmf_proto_cdc_dcmd { ++ __le32 cmd; /* dongle command value */ ++ __le32 len; /* lower 16: output buflen; ++ * upper 16: input buflen (excludes header) */ ++ __le32 flags; /* flag defns given below */ ++ __le32 status; /* status code returned from the device */ ++}; ++ ++/* Max valid buffer size that can be sent to the dongle */ ++#define CDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN) ++ ++/* CDC flag definitions */ ++#define CDC_DCMD_ERROR 0x01 /* 1=cmd failed */ ++#define CDC_DCMD_SET 0x02 /* 0=get, 1=set cmd */ ++#define CDC_DCMD_IF_MASK 0xF000 /* I/F index */ ++#define CDC_DCMD_IF_SHIFT 12 ++#define CDC_DCMD_ID_MASK 0xFFFF0000 /* id an cmd pairing */ ++#define CDC_DCMD_ID_SHIFT 16 /* ID Mask shift bits */ ++#define CDC_DCMD_ID(flags) \ ++ (((flags) & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT) ++ ++/* ++ * BDC header - Broadcom specific extension of CDC. ++ * Used on data packets to convey priority across USB. ++ */ ++#define BDC_HEADER_LEN 4 ++#define BDC_PROTO_VER 1 /* Protocol version */ ++#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ ++#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ ++#define BDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */ ++#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */ ++#define BDC_PRIORITY_MASK 0x7 ++#define BDC_FLAG2_IF_MASK 0x0f /* packet rx interface in APSTA */ ++#define BDC_FLAG2_IF_SHIFT 0 ++ ++#define BDC_GET_IF_IDX(hdr) \ ++ ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT)) ++#define BDC_SET_IF_IDX(hdr, idx) \ ++ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \ ++ ((idx) << BDC_FLAG2_IF_SHIFT))) ++ ++struct brcmf_proto_bdc_header { ++ u8 flags; ++ u8 priority; /* 802.1d Priority, 4:7 flow control info for usb */ ++ u8 flags2; ++ u8 rssi; ++}; ++ ++ ++#define RETRIES 2 /* # of retries to retrieve matching dcmd response */ ++#define BUS_HEADER_LEN (16+BRCMF_SDALIGN) /* Must be atleast SDPCM_RESERVE ++ * (amount of header tha might be added) ++ * plus any space that might be needed ++ * for alignment padding. ++ */ ++#define ROUND_UP_MARGIN 2048 /* Biggest SDIO block size possible for ++ * round off at the end of buffer ++ */ ++ ++struct brcmf_proto { ++ u16 reqid; ++ u8 pending; ++ u32 lastcmd; ++ u8 bus_header[BUS_HEADER_LEN]; ++ struct brcmf_proto_cdc_dcmd msg; ++ unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN]; ++}; ++ ++static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr) ++{ ++ struct brcmf_proto *prot = drvr->prot; ++ int len = le32_to_cpu(prot->msg.len) + ++ sizeof(struct brcmf_proto_cdc_dcmd); ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* NOTE : cdc->msg.len holds the desired length of the buffer to be ++ * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area ++ * is actually sent to the dongle ++ */ ++ if (len > CDC_MAX_MSG_SIZE) ++ len = CDC_MAX_MSG_SIZE; ++ ++ /* Send request */ ++ return brcmf_sdbrcm_bus_txctl(drvr->bus, (unsigned char *)&prot->msg, ++ len); ++} ++ ++static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) ++{ ++ int ret; ++ struct brcmf_proto *prot = drvr->prot; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ do { ++ ret = brcmf_sdbrcm_bus_rxctl(drvr->bus, ++ (unsigned char *)&prot->msg, ++ len + sizeof(struct brcmf_proto_cdc_dcmd)); ++ if (ret < 0) ++ break; ++ } while (CDC_DCMD_ID(le32_to_cpu(prot->msg.flags)) != id); ++ ++ return ret; ++} ++ ++int ++brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, ++ void *buf, uint len) ++{ ++ struct brcmf_proto *prot = drvr->prot; ++ struct brcmf_proto_cdc_dcmd *msg = &prot->msg; ++ void *info; ++ int ret = 0, retries = 0; ++ u32 id, flags; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ brcmf_dbg(CTL, "cmd %d len %d\n", cmd, len); ++ ++ /* Respond "bcmerror" and "bcmerrorstr" with local cache */ ++ if (cmd == BRCMF_C_GET_VAR && buf) { ++ if (!strcmp((char *)buf, "bcmerrorstr")) { ++ strncpy((char *)buf, "bcm_error", ++ BCME_STRLEN); ++ goto done; ++ } else if (!strcmp((char *)buf, "bcmerror")) { ++ *(int *)buf = drvr->dongle_error; ++ goto done; ++ } ++ } ++ ++ memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); ++ ++ msg->cmd = cpu_to_le32(cmd); ++ msg->len = cpu_to_le32(len); ++ flags = (++prot->reqid << CDC_DCMD_ID_SHIFT); ++ flags = (flags & ~CDC_DCMD_IF_MASK) | ++ (ifidx << CDC_DCMD_IF_SHIFT); ++ msg->flags = cpu_to_le32(flags); ++ ++ if (buf) ++ memcpy(prot->buf, buf, len); ++ ++ ret = brcmf_proto_cdc_msg(drvr); ++ if (ret < 0) { ++ brcmf_dbg(ERROR, "brcmf_proto_cdc_msg failed w/status %d\n", ++ ret); ++ goto done; ++ } ++ ++retry: ++ /* wait for interrupt and get first fragment */ ++ ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len); ++ if (ret < 0) ++ goto done; ++ ++ flags = le32_to_cpu(msg->flags); ++ id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT; ++ ++ if ((id < prot->reqid) && (++retries < RETRIES)) ++ goto retry; ++ if (id != prot->reqid) { ++ brcmf_dbg(ERROR, "%s: unexpected request id %d (expected %d)\n", ++ brcmf_ifname(drvr, ifidx), id, prot->reqid); ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ /* Check info buffer */ ++ info = (void *)&msg[1]; ++ ++ /* Copy info buffer */ ++ if (buf) { ++ if (ret < (int)len) ++ len = ret; ++ memcpy(buf, info, len); ++ } ++ ++ /* Check the ERROR flag */ ++ if (flags & CDC_DCMD_ERROR) { ++ ret = le32_to_cpu(msg->status); ++ /* Cache error from dongle */ ++ drvr->dongle_error = ret; ++ } ++ ++done: ++ return ret; ++} ++ ++int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, ++ void *buf, uint len) ++{ ++ struct brcmf_proto *prot = drvr->prot; ++ struct brcmf_proto_cdc_dcmd *msg = &prot->msg; ++ int ret = 0; ++ u32 flags, id; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ brcmf_dbg(CTL, "cmd %d len %d\n", cmd, len); ++ ++ memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); ++ ++ msg->cmd = cpu_to_le32(cmd); ++ msg->len = cpu_to_le32(len); ++ flags = (++prot->reqid << CDC_DCMD_ID_SHIFT) | CDC_DCMD_SET; ++ flags = (flags & ~CDC_DCMD_IF_MASK) | ++ (ifidx << CDC_DCMD_IF_SHIFT); ++ msg->flags = cpu_to_le32(flags); ++ ++ if (buf) ++ memcpy(prot->buf, buf, len); ++ ++ ret = brcmf_proto_cdc_msg(drvr); ++ if (ret < 0) ++ goto done; ++ ++ ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len); ++ if (ret < 0) ++ goto done; ++ ++ flags = le32_to_cpu(msg->flags); ++ id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT; ++ ++ if (id != prot->reqid) { ++ brcmf_dbg(ERROR, "%s: unexpected request id %d (expected %d)\n", ++ brcmf_ifname(drvr, ifidx), id, prot->reqid); ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ /* Check the ERROR flag */ ++ if (flags & CDC_DCMD_ERROR) { ++ ret = le32_to_cpu(msg->status); ++ /* Cache error from dongle */ ++ drvr->dongle_error = ret; ++ } ++ ++done: ++ return ret; ++} ++ ++int ++brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, struct brcmf_dcmd *dcmd, ++ int len) ++{ ++ struct brcmf_proto *prot = drvr->prot; ++ int ret = -1; ++ ++ if (drvr->busstate == BRCMF_BUS_DOWN) { ++ brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n"); ++ return ret; ++ } ++ brcmf_os_proto_block(drvr); ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (len > BRCMF_DCMD_MAXLEN) ++ goto done; ++ ++ if (prot->pending == true) { ++ brcmf_dbg(TRACE, "CDC packet is pending!!!! cmd=0x%x (%lu) lastcmd=0x%x (%lu)\n", ++ dcmd->cmd, (unsigned long)dcmd->cmd, prot->lastcmd, ++ (unsigned long)prot->lastcmd); ++ if (dcmd->cmd == BRCMF_C_SET_VAR || ++ dcmd->cmd == BRCMF_C_GET_VAR) ++ brcmf_dbg(TRACE, "iovar cmd=%s\n", (char *)dcmd->buf); ++ ++ goto done; ++ } ++ ++ prot->pending = true; ++ prot->lastcmd = dcmd->cmd; ++ if (dcmd->set) ++ ret = brcmf_proto_cdc_set_dcmd(drvr, ifidx, dcmd->cmd, ++ dcmd->buf, len); ++ else { ++ ret = brcmf_proto_cdc_query_dcmd(drvr, ifidx, dcmd->cmd, ++ dcmd->buf, len); ++ if (ret > 0) ++ dcmd->used = ret - ++ sizeof(struct brcmf_proto_cdc_dcmd); ++ } ++ ++ if (ret >= 0) ++ ret = 0; ++ else { ++ struct brcmf_proto_cdc_dcmd *msg = &prot->msg; ++ /* len == needed when set/query fails from dongle */ ++ dcmd->needed = le32_to_cpu(msg->len); ++ } ++ ++ /* Intercept the wme_dp dongle cmd here */ ++ if (!ret && dcmd->cmd == BRCMF_C_SET_VAR && ++ !strcmp(dcmd->buf, "wme_dp")) { ++ int slen; ++ __le32 val = 0; ++ ++ slen = strlen("wme_dp") + 1; ++ if (len >= (int)(slen + sizeof(int))) ++ memcpy(&val, (char *)dcmd->buf + slen, sizeof(int)); ++ drvr->wme_dp = (u8) le32_to_cpu(val); ++ } ++ ++ prot->pending = false; ++ ++done: ++ brcmf_os_proto_unblock(drvr); ++ ++ return ret; ++} ++ ++static bool pkt_sum_needed(struct sk_buff *skb) ++{ ++ return skb->ip_summed == CHECKSUM_PARTIAL; ++} ++ ++static void pkt_set_sum_good(struct sk_buff *skb, bool x) ++{ ++ skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE); ++} ++ ++void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, ++ struct sk_buff *pktbuf) ++{ ++ struct brcmf_proto_bdc_header *h; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Push BDC header used to convey priority for buses that don't */ ++ ++ skb_push(pktbuf, BDC_HEADER_LEN); ++ ++ h = (struct brcmf_proto_bdc_header *)(pktbuf->data); ++ ++ h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); ++ if (pkt_sum_needed(pktbuf)) ++ h->flags |= BDC_FLAG_SUM_NEEDED; ++ ++ h->priority = (pktbuf->priority & BDC_PRIORITY_MASK); ++ h->flags2 = 0; ++ h->rssi = 0; ++ BDC_SET_IF_IDX(h, ifidx); ++} ++ ++int brcmf_proto_hdrpull(struct brcmf_pub *drvr, int *ifidx, ++ struct sk_buff *pktbuf) ++{ ++ struct brcmf_proto_bdc_header *h; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Pop BDC header used to convey priority for buses that don't */ ++ ++ if (pktbuf->len < BDC_HEADER_LEN) { ++ brcmf_dbg(ERROR, "rx data too short (%d < %d)\n", ++ pktbuf->len, BDC_HEADER_LEN); ++ return -EBADE; ++ } ++ ++ h = (struct brcmf_proto_bdc_header *)(pktbuf->data); ++ ++ *ifidx = BDC_GET_IF_IDX(h); ++ if (*ifidx >= BRCMF_MAX_IFS) { ++ brcmf_dbg(ERROR, "rx data ifnum out of range (%d)\n", *ifidx); ++ return -EBADE; ++ } ++ ++ if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) != ++ BDC_PROTO_VER) { ++ brcmf_dbg(ERROR, "%s: non-BDC packet received, flags 0x%x\n", ++ brcmf_ifname(drvr, *ifidx), h->flags); ++ return -EBADE; ++ } ++ ++ if (h->flags & BDC_FLAG_SUM_GOOD) { ++ brcmf_dbg(INFO, "%s: BDC packet received with good rx-csum, flags 0x%x\n", ++ brcmf_ifname(drvr, *ifidx), h->flags); ++ pkt_set_sum_good(pktbuf, true); ++ } ++ ++ pktbuf->priority = h->priority & BDC_PRIORITY_MASK; ++ ++ skb_pull(pktbuf, BDC_HEADER_LEN); ++ ++ return 0; ++} ++ ++int brcmf_proto_attach(struct brcmf_pub *drvr) ++{ ++ struct brcmf_proto *cdc; ++ ++ cdc = kzalloc(sizeof(struct brcmf_proto), GFP_ATOMIC); ++ if (!cdc) ++ goto fail; ++ ++ /* ensure that the msg buf directly follows the cdc msg struct */ ++ if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) { ++ brcmf_dbg(ERROR, "struct brcmf_proto is not correctly defined\n"); ++ goto fail; ++ } ++ ++ drvr->prot = cdc; ++ drvr->hdrlen += BDC_HEADER_LEN; ++ drvr->maxctl = BRCMF_DCMD_MAXLEN + ++ sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN; ++ return 0; ++ ++fail: ++ kfree(cdc); ++ return -ENOMEM; ++} ++ ++/* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */ ++void brcmf_proto_detach(struct brcmf_pub *drvr) ++{ ++ kfree(drvr->prot); ++ drvr->prot = NULL; ++} ++ ++void brcmf_proto_dstats(struct brcmf_pub *drvr) ++{ ++ /* No stats from dongle added yet, copy bus stats */ ++ drvr->dstats.tx_packets = drvr->tx_packets; ++ drvr->dstats.tx_errors = drvr->tx_errors; ++ drvr->dstats.rx_packets = drvr->rx_packets; ++ drvr->dstats.rx_errors = drvr->rx_errors; ++ drvr->dstats.rx_dropped = drvr->rx_dropped; ++ drvr->dstats.multicast = drvr->rx_multicast; ++ return; ++} ++ ++int brcmf_proto_init(struct brcmf_pub *drvr) ++{ ++ int ret = 0; ++ char buf[128]; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ brcmf_os_proto_block(drvr); ++ ++ /* Get the device MAC address */ ++ strcpy(buf, "cur_etheraddr"); ++ ret = brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, ++ buf, sizeof(buf)); ++ if (ret < 0) { ++ brcmf_os_proto_unblock(drvr); ++ return ret; ++ } ++ memcpy(drvr->mac, buf, ETH_ALEN); ++ ++ brcmf_os_proto_unblock(drvr); ++ ++ ret = brcmf_c_preinit_dcmds(drvr); ++ ++ /* Always assumes wl for now */ ++ drvr->iswl = true; ++ ++ return ret; ++} ++ ++void brcmf_proto_stop(struct brcmf_pub *drvr) ++{ ++ /* Nothing to do for CDC */ ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c.orig 2011-11-09 13:46:58.230800821 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c 2011-11-09 13:47:16.981566403 -0500 +@@ -0,0 +1,895 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "dhd.h" ++#include "dhd_bus.h" ++#include "dhd_proto.h" ++#include "dhd_dbg.h" ++ ++#define BRCM_OUI "\x00\x10\x18" ++#define DOT11_OUI_LEN 3 ++#define BCMILCP_BCM_SUBTYPE_EVENT 1 ++#define PKTFILTER_BUF_SIZE 2048 ++#define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */ ++ ++int brcmf_msg_level; ++ ++#define MSGTRACE_VERSION 1 ++ ++#define BRCMF_PKT_FILTER_FIXED_LEN offsetof(struct brcmf_pkt_filter_le, u) ++#define BRCMF_PKT_FILTER_PATTERN_FIXED_LEN \ ++ offsetof(struct brcmf_pkt_filter_pattern_le, mask_and_pattern) ++ ++#ifdef BCMDBG ++static const char brcmf_version[] = ++ "Dongle Host Driver, version " BRCMF_VERSION_STR "\nCompiled on " ++ __DATE__ " at " __TIME__; ++#else ++static const char brcmf_version[] = ++ "Dongle Host Driver, version " BRCMF_VERSION_STR; ++#endif ++ ++/* Message trace header */ ++struct msgtrace_hdr { ++ u8 version; ++ u8 spare; ++ __be16 len; /* Len of the trace */ ++ __be32 seqnum; /* Sequence number of message. Useful ++ * if the messsage has been lost ++ * because of DMA error or a bus reset ++ * (ex: SDIO Func2) ++ */ ++ __be32 discarded_bytes; /* Number of discarded bytes because of ++ trace overflow */ ++ __be32 discarded_printf; /* Number of discarded printf ++ because of trace overflow */ ++} __packed; ++ ++ ++uint ++brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) ++{ ++ uint len; ++ ++ len = strlen(name) + 1; ++ ++ if ((len + datalen) > buflen) ++ return 0; ++ ++ strncpy(buf, name, buflen); ++ ++ /* append data onto the end of the name string */ ++ memcpy(&buf[len], data, datalen); ++ len += datalen; ++ ++ return len; ++} ++ ++void brcmf_c_init(void) ++{ ++ /* Init global variables at run-time, not as part of the declaration. ++ * This is required to support init/de-init of the driver. ++ * Initialization ++ * of globals as part of the declaration results in non-deterministic ++ * behaviour since the value of the globals may be different on the ++ * first time that the driver is initialized vs subsequent ++ * initializations. ++ */ ++ brcmf_msg_level = BRCMF_ERROR_VAL; ++} ++ ++bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q, ++ struct sk_buff *pkt, int prec) ++{ ++ struct sk_buff *p; ++ int eprec = -1; /* precedence to evict from */ ++ bool discard_oldest; ++ ++ /* Fast case, precedence queue is not full and we are also not ++ * exceeding total queue length ++ */ ++ if (!pktq_pfull(q, prec) && !pktq_full(q)) { ++ brcmu_pktq_penq(q, prec, pkt); ++ return true; ++ } ++ ++ /* Determine precedence from which to evict packet, if any */ ++ if (pktq_pfull(q, prec)) ++ eprec = prec; ++ else if (pktq_full(q)) { ++ p = brcmu_pktq_peek_tail(q, &eprec); ++ if (eprec > prec) ++ return false; ++ } ++ ++ /* Evict if needed */ ++ if (eprec >= 0) { ++ /* Detect queueing to unconfigured precedence */ ++ discard_oldest = ac_bitmap_tst(drvr->wme_dp, eprec); ++ if (eprec == prec && !discard_oldest) ++ return false; /* refuse newer (incoming) packet */ ++ /* Evict packet according to discard policy */ ++ p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) : ++ brcmu_pktq_pdeq_tail(q, eprec); ++ if (p == NULL) ++ brcmf_dbg(ERROR, "brcmu_pktq_penq() failed, oldest %d\n", ++ discard_oldest); ++ ++ brcmu_pkt_buf_free_skb(p); ++ } ++ ++ /* Enqueue */ ++ p = brcmu_pktq_penq(q, prec, pkt); ++ if (p == NULL) ++ brcmf_dbg(ERROR, "brcmu_pktq_penq() failed\n"); ++ ++ return p != NULL; ++} ++ ++#ifdef BCMDBG ++static void ++brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data) ++{ ++ uint i, status, reason; ++ bool group = false, flush_txq = false, link = false; ++ char *auth_str, *event_name; ++ unsigned char *buf; ++ char err_msg[256], eabuf[ETHER_ADDR_STR_LEN]; ++ static struct { ++ uint event; ++ char *event_name; ++ } event_names[] = { ++ { ++ BRCMF_E_SET_SSID, "SET_SSID"}, { ++ BRCMF_E_JOIN, "JOIN"}, { ++ BRCMF_E_START, "START"}, { ++ BRCMF_E_AUTH, "AUTH"}, { ++ BRCMF_E_AUTH_IND, "AUTH_IND"}, { ++ BRCMF_E_DEAUTH, "DEAUTH"}, { ++ BRCMF_E_DEAUTH_IND, "DEAUTH_IND"}, { ++ BRCMF_E_ASSOC, "ASSOC"}, { ++ BRCMF_E_ASSOC_IND, "ASSOC_IND"}, { ++ BRCMF_E_REASSOC, "REASSOC"}, { ++ BRCMF_E_REASSOC_IND, "REASSOC_IND"}, { ++ BRCMF_E_DISASSOC, "DISASSOC"}, { ++ BRCMF_E_DISASSOC_IND, "DISASSOC_IND"}, { ++ BRCMF_E_QUIET_START, "START_QUIET"}, { ++ BRCMF_E_QUIET_END, "END_QUIET"}, { ++ BRCMF_E_BEACON_RX, "BEACON_RX"}, { ++ BRCMF_E_LINK, "LINK"}, { ++ BRCMF_E_MIC_ERROR, "MIC_ERROR"}, { ++ BRCMF_E_NDIS_LINK, "NDIS_LINK"}, { ++ BRCMF_E_ROAM, "ROAM"}, { ++ BRCMF_E_TXFAIL, "TXFAIL"}, { ++ BRCMF_E_PMKID_CACHE, "PMKID_CACHE"}, { ++ BRCMF_E_RETROGRADE_TSF, "RETROGRADE_TSF"}, { ++ BRCMF_E_PRUNE, "PRUNE"}, { ++ BRCMF_E_AUTOAUTH, "AUTOAUTH"}, { ++ BRCMF_E_EAPOL_MSG, "EAPOL_MSG"}, { ++ BRCMF_E_SCAN_COMPLETE, "SCAN_COMPLETE"}, { ++ BRCMF_E_ADDTS_IND, "ADDTS_IND"}, { ++ BRCMF_E_DELTS_IND, "DELTS_IND"}, { ++ BRCMF_E_BCNSENT_IND, "BCNSENT_IND"}, { ++ BRCMF_E_BCNRX_MSG, "BCNRX_MSG"}, { ++ BRCMF_E_BCNLOST_MSG, "BCNLOST_MSG"}, { ++ BRCMF_E_ROAM_PREP, "ROAM_PREP"}, { ++ BRCMF_E_PFN_NET_FOUND, "PNO_NET_FOUND"}, { ++ BRCMF_E_PFN_NET_LOST, "PNO_NET_LOST"}, { ++ BRCMF_E_RESET_COMPLETE, "RESET_COMPLETE"}, { ++ BRCMF_E_JOIN_START, "JOIN_START"}, { ++ BRCMF_E_ROAM_START, "ROAM_START"}, { ++ BRCMF_E_ASSOC_START, "ASSOC_START"}, { ++ BRCMF_E_IBSS_ASSOC, "IBSS_ASSOC"}, { ++ BRCMF_E_RADIO, "RADIO"}, { ++ BRCMF_E_PSM_WATCHDOG, "PSM_WATCHDOG"}, { ++ BRCMF_E_PROBREQ_MSG, "PROBREQ_MSG"}, { ++ BRCMF_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND"}, { ++ BRCMF_E_PSK_SUP, "PSK_SUP"}, { ++ BRCMF_E_COUNTRY_CODE_CHANGED, "COUNTRY_CODE_CHANGED"}, { ++ BRCMF_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME"}, { ++ BRCMF_E_ICV_ERROR, "ICV_ERROR"}, { ++ BRCMF_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR"}, { ++ BRCMF_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR"}, { ++ BRCMF_E_TRACE, "TRACE"}, { ++ BRCMF_E_ACTION_FRAME, "ACTION FRAME"}, { ++ BRCMF_E_ACTION_FRAME_COMPLETE, "ACTION FRAME TX COMPLETE"}, { ++ BRCMF_E_IF, "IF"}, { ++ BRCMF_E_RSSI, "RSSI"}, { ++ BRCMF_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"} ++ }; ++ uint event_type, flags, auth_type, datalen; ++ static u32 seqnum_prev; ++ struct msgtrace_hdr hdr; ++ u32 nblost; ++ char *s, *p; ++ ++ event_type = be32_to_cpu(event->event_type); ++ flags = be16_to_cpu(event->flags); ++ status = be32_to_cpu(event->status); ++ reason = be32_to_cpu(event->reason); ++ auth_type = be32_to_cpu(event->auth_type); ++ datalen = be32_to_cpu(event->datalen); ++ /* debug dump of event messages */ ++ sprintf(eabuf, "%pM", event->addr); ++ ++ event_name = "UNKNOWN"; ++ for (i = 0; i < ARRAY_SIZE(event_names); i++) { ++ if (event_names[i].event == event_type) ++ event_name = event_names[i].event_name; ++ } ++ ++ brcmf_dbg(EVENT, "EVENT: %s, event ID = %d\n", event_name, event_type); ++ brcmf_dbg(EVENT, "flags 0x%04x, status %d, reason %d, auth_type %d MAC %s\n", ++ flags, status, reason, auth_type, eabuf); ++ ++ if (flags & BRCMF_EVENT_MSG_LINK) ++ link = true; ++ if (flags & BRCMF_EVENT_MSG_GROUP) ++ group = true; ++ if (flags & BRCMF_EVENT_MSG_FLUSHTXQ) ++ flush_txq = true; ++ ++ switch (event_type) { ++ case BRCMF_E_START: ++ case BRCMF_E_DEAUTH: ++ case BRCMF_E_DISASSOC: ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf); ++ break; ++ ++ case BRCMF_E_ASSOC_IND: ++ case BRCMF_E_REASSOC_IND: ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf); ++ break; ++ ++ case BRCMF_E_ASSOC: ++ case BRCMF_E_REASSOC: ++ if (status == BRCMF_E_STATUS_SUCCESS) ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, SUCCESS\n", ++ event_name, eabuf); ++ else if (status == BRCMF_E_STATUS_TIMEOUT) ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, TIMEOUT\n", ++ event_name, eabuf); ++ else if (status == BRCMF_E_STATUS_FAIL) ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, FAILURE, reason %d\n", ++ event_name, eabuf, (int)reason); ++ else ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, unexpected status %d\n", ++ event_name, eabuf, (int)status); ++ break; ++ ++ case BRCMF_E_DEAUTH_IND: ++ case BRCMF_E_DISASSOC_IND: ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, reason %d\n", ++ event_name, eabuf, (int)reason); ++ break; ++ ++ case BRCMF_E_AUTH: ++ case BRCMF_E_AUTH_IND: ++ if (auth_type == WLAN_AUTH_OPEN) ++ auth_str = "Open System"; ++ else if (auth_type == WLAN_AUTH_SHARED_KEY) ++ auth_str = "Shared Key"; ++ else { ++ sprintf(err_msg, "AUTH unknown: %d", (int)auth_type); ++ auth_str = err_msg; ++ } ++ if (event_type == BRCMF_E_AUTH_IND) ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s\n", ++ event_name, eabuf, auth_str); ++ else if (status == BRCMF_E_STATUS_SUCCESS) ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, SUCCESS\n", ++ event_name, eabuf, auth_str); ++ else if (status == BRCMF_E_STATUS_TIMEOUT) ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, TIMEOUT\n", ++ event_name, eabuf, auth_str); ++ else if (status == BRCMF_E_STATUS_FAIL) { ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, FAILURE, reason %d\n", ++ event_name, eabuf, auth_str, (int)reason); ++ } ++ ++ break; ++ ++ case BRCMF_E_JOIN: ++ case BRCMF_E_ROAM: ++ case BRCMF_E_SET_SSID: ++ if (status == BRCMF_E_STATUS_SUCCESS) ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", ++ event_name, eabuf); ++ else if (status == BRCMF_E_STATUS_FAIL) ++ brcmf_dbg(EVENT, "MACEVENT: %s, failed\n", event_name); ++ else if (status == BRCMF_E_STATUS_NO_NETWORKS) ++ brcmf_dbg(EVENT, "MACEVENT: %s, no networks found\n", ++ event_name); ++ else ++ brcmf_dbg(EVENT, "MACEVENT: %s, unexpected status %d\n", ++ event_name, (int)status); ++ break; ++ ++ case BRCMF_E_BEACON_RX: ++ if (status == BRCMF_E_STATUS_SUCCESS) ++ brcmf_dbg(EVENT, "MACEVENT: %s, SUCCESS\n", event_name); ++ else if (status == BRCMF_E_STATUS_FAIL) ++ brcmf_dbg(EVENT, "MACEVENT: %s, FAIL\n", event_name); ++ else ++ brcmf_dbg(EVENT, "MACEVENT: %s, status %d\n", ++ event_name, status); ++ break; ++ ++ case BRCMF_E_LINK: ++ brcmf_dbg(EVENT, "MACEVENT: %s %s\n", ++ event_name, link ? "UP" : "DOWN"); ++ break; ++ ++ case BRCMF_E_MIC_ERROR: ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, Group %d, Flush %d\n", ++ event_name, eabuf, group, flush_txq); ++ break; ++ ++ case BRCMF_E_ICV_ERROR: ++ case BRCMF_E_UNICAST_DECODE_ERROR: ++ case BRCMF_E_MULTICAST_DECODE_ERROR: ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf); ++ break; ++ ++ case BRCMF_E_TXFAIL: ++ brcmf_dbg(EVENT, "MACEVENT: %s, RA %s\n", event_name, eabuf); ++ break; ++ ++ case BRCMF_E_SCAN_COMPLETE: ++ case BRCMF_E_PMKID_CACHE: ++ brcmf_dbg(EVENT, "MACEVENT: %s\n", event_name); ++ break; ++ ++ case BRCMF_E_PFN_NET_FOUND: ++ case BRCMF_E_PFN_NET_LOST: ++ case BRCMF_E_PFN_SCAN_COMPLETE: ++ brcmf_dbg(EVENT, "PNOEVENT: %s\n", event_name); ++ break; ++ ++ case BRCMF_E_PSK_SUP: ++ case BRCMF_E_PRUNE: ++ brcmf_dbg(EVENT, "MACEVENT: %s, status %d, reason %d\n", ++ event_name, (int)status, (int)reason); ++ break; ++ ++ case BRCMF_E_TRACE: ++ buf = (unsigned char *) event_data; ++ memcpy(&hdr, buf, sizeof(struct msgtrace_hdr)); ++ ++ if (hdr.version != MSGTRACE_VERSION) { ++ brcmf_dbg(ERROR, ++ "MACEVENT: %s [unsupported version --> brcmf" ++ " version:%d dongle version:%d]\n", ++ event_name, MSGTRACE_VERSION, hdr.version); ++ /* Reset datalen to avoid display below */ ++ datalen = 0; ++ break; ++ } ++ ++ /* There are 2 bytes available at the end of data */ ++ *(buf + sizeof(struct msgtrace_hdr) ++ + be16_to_cpu(hdr.len)) = '\0'; ++ ++ if (be32_to_cpu(hdr.discarded_bytes) ++ || be32_to_cpu(hdr.discarded_printf)) ++ brcmf_dbg(ERROR, ++ "WLC_E_TRACE: [Discarded traces in dongle -->" ++ " discarded_bytes %d discarded_printf %d]\n", ++ be32_to_cpu(hdr.discarded_bytes), ++ be32_to_cpu(hdr.discarded_printf)); ++ ++ nblost = be32_to_cpu(hdr.seqnum) - seqnum_prev - 1; ++ if (nblost > 0) ++ brcmf_dbg(ERROR, "WLC_E_TRACE: [Event lost --> seqnum " ++ " %d nblost %d\n", be32_to_cpu(hdr.seqnum), ++ nblost); ++ seqnum_prev = be32_to_cpu(hdr.seqnum); ++ ++ /* Display the trace buffer. Advance from \n to \n to ++ * avoid display big ++ * printf (issue with Linux printk ) ++ */ ++ p = (char *)&buf[sizeof(struct msgtrace_hdr)]; ++ while ((s = strstr(p, "\n")) != NULL) { ++ *s = '\0'; ++ printk(KERN_DEBUG"%s\n", p); ++ p = s + 1; ++ } ++ printk(KERN_DEBUG "%s\n", p); ++ ++ /* Reset datalen to avoid display below */ ++ datalen = 0; ++ break; ++ ++ case BRCMF_E_RSSI: ++ brcmf_dbg(EVENT, "MACEVENT: %s %d\n", ++ event_name, be32_to_cpu(*((__be32 *)event_data))); ++ break; ++ ++ default: ++ brcmf_dbg(EVENT, ++ "MACEVENT: %s %d, MAC %s, status %d, reason %d, " ++ "auth %d\n", event_name, event_type, eabuf, ++ (int)status, (int)reason, (int)auth_type); ++ break; ++ } ++ ++ /* show any appended data */ ++ if (datalen) { ++ buf = (unsigned char *) event_data; ++ brcmf_dbg(EVENT, " data (%d) : ", datalen); ++ for (i = 0; i < datalen; i++) ++ brcmf_dbg(EVENT, " 0x%02x ", *buf++); ++ brcmf_dbg(EVENT, "\n"); ++ } ++} ++#endif /* BCMDBG */ ++ ++int ++brcmf_c_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata, ++ struct brcmf_event_msg *event, void **data_ptr) ++{ ++ /* check whether packet is a BRCM event pkt */ ++ struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata; ++ struct brcmf_if_event *ifevent; ++ char *event_data; ++ u32 type, status; ++ u16 flags; ++ int evlen; ++ ++ if (memcmp(BRCM_OUI, &pvt_data->hdr.oui[0], DOT11_OUI_LEN)) { ++ brcmf_dbg(ERROR, "mismatched OUI, bailing\n"); ++ return -EBADE; ++ } ++ ++ /* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */ ++ if (get_unaligned_be16(&pvt_data->hdr.usr_subtype) != ++ BCMILCP_BCM_SUBTYPE_EVENT) { ++ brcmf_dbg(ERROR, "mismatched subtype, bailing\n"); ++ return -EBADE; ++ } ++ ++ *data_ptr = &pvt_data[1]; ++ event_data = *data_ptr; ++ ++ /* memcpy since BRCM event pkt may be unaligned. */ ++ memcpy(event, &pvt_data->msg, sizeof(struct brcmf_event_msg)); ++ ++ type = get_unaligned_be32(&event->event_type); ++ flags = get_unaligned_be16(&event->flags); ++ status = get_unaligned_be32(&event->status); ++ evlen = get_unaligned_be32(&event->datalen) + ++ sizeof(struct brcmf_event); ++ ++ switch (type) { ++ case BRCMF_E_IF: ++ ifevent = (struct brcmf_if_event *) event_data; ++ brcmf_dbg(TRACE, "if event\n"); ++ ++ if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) { ++ if (ifevent->action == BRCMF_E_IF_ADD) ++ brcmf_add_if(drvr_priv, ifevent->ifidx, NULL, ++ event->ifname, ++ pvt_data->eth.h_dest, ++ ifevent->flags, ifevent->bssidx); ++ else ++ brcmf_del_if(drvr_priv, ifevent->ifidx); ++ } else { ++ brcmf_dbg(ERROR, "Invalid ifidx %d for %s\n", ++ ifevent->ifidx, event->ifname); ++ } ++ ++ /* send up the if event: btamp user needs it */ ++ *ifidx = brcmf_ifname2idx(drvr_priv, event->ifname); ++ break; ++ ++ /* These are what external supplicant/authenticator wants */ ++ case BRCMF_E_LINK: ++ case BRCMF_E_ASSOC_IND: ++ case BRCMF_E_REASSOC_IND: ++ case BRCMF_E_DISASSOC_IND: ++ case BRCMF_E_MIC_ERROR: ++ default: ++ /* Fall through: this should get _everything_ */ ++ ++ *ifidx = brcmf_ifname2idx(drvr_priv, event->ifname); ++ brcmf_dbg(TRACE, "MAC event %d, flags %x, status %x\n", ++ type, flags, status); ++ ++ /* put it back to BRCMF_E_NDIS_LINK */ ++ if (type == BRCMF_E_NDIS_LINK) { ++ u32 temp1; ++ __be32 temp2; ++ ++ temp1 = get_unaligned_be32(&event->event_type); ++ brcmf_dbg(TRACE, "Converted to WLC_E_LINK type %d\n", ++ temp1); ++ ++ temp2 = cpu_to_be32(BRCMF_E_NDIS_LINK); ++ memcpy((void *)(&pvt_data->msg.event_type), &temp2, ++ sizeof(pvt_data->msg.event_type)); ++ } ++ break; ++ } ++ ++#ifdef BCMDBG ++ brcmf_c_show_host_event(event, event_data); ++#endif /* BCMDBG */ ++ ++ return 0; ++} ++ ++/* Convert user's input in hex pattern to byte-size mask */ ++static int brcmf_c_pattern_atoh(char *src, char *dst) ++{ ++ int i; ++ if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) { ++ brcmf_dbg(ERROR, "Mask invalid format. Needs to start with 0x\n"); ++ return -EINVAL; ++ } ++ src = src + 2; /* Skip past 0x */ ++ if (strlen(src) % 2 != 0) { ++ brcmf_dbg(ERROR, "Mask invalid format. Length must be even.\n"); ++ return -EINVAL; ++ } ++ for (i = 0; *src != '\0'; i++) { ++ unsigned long res; ++ char num[3]; ++ strncpy(num, src, 2); ++ num[2] = '\0'; ++ if (kstrtoul(num, 16, &res)) ++ return -EINVAL; ++ dst[i] = (u8)res; ++ src += 2; ++ } ++ return i; ++} ++ ++void ++brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable, ++ int master_mode) ++{ ++ unsigned long res; ++ char *argv[8]; ++ int i = 0; ++ const char *str; ++ int buf_len; ++ int str_len; ++ char *arg_save = NULL, *arg_org = NULL; ++ int rc; ++ char buf[128]; ++ struct brcmf_pkt_filter_enable_le enable_parm; ++ struct brcmf_pkt_filter_enable_le *pkt_filterp; ++ __le32 mmode_le; ++ ++ arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC); ++ if (!arg_save) ++ goto fail; ++ ++ arg_org = arg_save; ++ memcpy(arg_save, arg, strlen(arg) + 1); ++ ++ argv[i] = strsep(&arg_save, " "); ++ ++ i = 0; ++ if (NULL == argv[i]) { ++ brcmf_dbg(ERROR, "No args provided\n"); ++ goto fail; ++ } ++ ++ str = "pkt_filter_enable"; ++ str_len = strlen(str); ++ strncpy(buf, str, str_len); ++ buf[str_len] = '\0'; ++ buf_len = str_len + 1; ++ ++ pkt_filterp = (struct brcmf_pkt_filter_enable_le *) (buf + str_len + 1); ++ ++ /* Parse packet filter id. */ ++ enable_parm.id = 0; ++ if (!kstrtoul(argv[i], 0, &res)) ++ enable_parm.id = cpu_to_le32((u32)res); ++ ++ /* Parse enable/disable value. */ ++ enable_parm.enable = cpu_to_le32(enable); ++ ++ buf_len += sizeof(enable_parm); ++ memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm)); ++ ++ /* Enable/disable the specified filter. */ ++ rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len); ++ rc = rc >= 0 ? 0 : rc; ++ if (rc) ++ brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n", ++ arg, rc); ++ else ++ brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg); ++ ++ /* Contorl the master mode */ ++ mmode_le = cpu_to_le32(master_mode); ++ brcmf_c_mkiovar("pkt_filter_mode", (char *)&mmode_le, 4, buf, ++ sizeof(buf)); ++ rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, ++ sizeof(buf)); ++ rc = rc >= 0 ? 0 : rc; ++ if (rc) ++ brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n", ++ arg, rc); ++ ++fail: ++ kfree(arg_org); ++} ++ ++void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg) ++{ ++ const char *str; ++ struct brcmf_pkt_filter_le pkt_filter; ++ struct brcmf_pkt_filter_le *pkt_filterp; ++ unsigned long res; ++ int buf_len; ++ int str_len; ++ int rc; ++ u32 mask_size; ++ u32 pattern_size; ++ char *argv[8], *buf = NULL; ++ int i = 0; ++ char *arg_save = NULL, *arg_org = NULL; ++ ++ arg_save = kstrdup(arg, GFP_ATOMIC); ++ if (!arg_save) ++ goto fail; ++ ++ arg_org = arg_save; ++ ++ buf = kmalloc(PKTFILTER_BUF_SIZE, GFP_ATOMIC); ++ if (!buf) ++ goto fail; ++ ++ argv[i] = strsep(&arg_save, " "); ++ while (argv[i++]) ++ argv[i] = strsep(&arg_save, " "); ++ ++ i = 0; ++ if (NULL == argv[i]) { ++ brcmf_dbg(ERROR, "No args provided\n"); ++ goto fail; ++ } ++ ++ str = "pkt_filter_add"; ++ strcpy(buf, str); ++ str_len = strlen(str); ++ buf_len = str_len + 1; ++ ++ pkt_filterp = (struct brcmf_pkt_filter_le *) (buf + str_len + 1); ++ ++ /* Parse packet filter id. */ ++ pkt_filter.id = 0; ++ if (!kstrtoul(argv[i], 0, &res)) ++ pkt_filter.id = cpu_to_le32((u32)res); ++ ++ if (NULL == argv[++i]) { ++ brcmf_dbg(ERROR, "Polarity not provided\n"); ++ goto fail; ++ } ++ ++ /* Parse filter polarity. */ ++ pkt_filter.negate_match = 0; ++ if (!kstrtoul(argv[i], 0, &res)) ++ pkt_filter.negate_match = cpu_to_le32((u32)res); ++ ++ if (NULL == argv[++i]) { ++ brcmf_dbg(ERROR, "Filter type not provided\n"); ++ goto fail; ++ } ++ ++ /* Parse filter type. */ ++ pkt_filter.type = 0; ++ if (!kstrtoul(argv[i], 0, &res)) ++ pkt_filter.type = cpu_to_le32((u32)res); ++ ++ if (NULL == argv[++i]) { ++ brcmf_dbg(ERROR, "Offset not provided\n"); ++ goto fail; ++ } ++ ++ /* Parse pattern filter offset. */ ++ pkt_filter.u.pattern.offset = 0; ++ if (!kstrtoul(argv[i], 0, &res)) ++ pkt_filter.u.pattern.offset = cpu_to_le32((u32)res); ++ ++ if (NULL == argv[++i]) { ++ brcmf_dbg(ERROR, "Bitmask not provided\n"); ++ goto fail; ++ } ++ ++ /* Parse pattern filter mask. */ ++ mask_size = ++ brcmf_c_pattern_atoh ++ (argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern); ++ ++ if (NULL == argv[++i]) { ++ brcmf_dbg(ERROR, "Pattern not provided\n"); ++ goto fail; ++ } ++ ++ /* Parse pattern filter pattern. */ ++ pattern_size = ++ brcmf_c_pattern_atoh(argv[i], ++ (char *)&pkt_filterp->u.pattern. ++ mask_and_pattern[mask_size]); ++ ++ if (mask_size != pattern_size) { ++ brcmf_dbg(ERROR, "Mask and pattern not the same size\n"); ++ goto fail; ++ } ++ ++ pkt_filter.u.pattern.size_bytes = cpu_to_le32(mask_size); ++ buf_len += BRCMF_PKT_FILTER_FIXED_LEN; ++ buf_len += (BRCMF_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size); ++ ++ /* Keep-alive attributes are set in local ++ * variable (keep_alive_pkt), and ++ ** then memcpy'ed into buffer (keep_alive_pktp) since there is no ++ ** guarantee that the buffer is properly aligned. ++ */ ++ memcpy((char *)pkt_filterp, ++ &pkt_filter, ++ BRCMF_PKT_FILTER_FIXED_LEN + BRCMF_PKT_FILTER_PATTERN_FIXED_LEN); ++ ++ rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len); ++ rc = rc >= 0 ? 0 : rc; ++ ++ if (rc) ++ brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n", ++ arg, rc); ++ else ++ brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg); ++ ++fail: ++ kfree(arg_org); ++ ++ kfree(buf); ++} ++ ++static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode) ++{ ++ char iovbuf[32]; ++ int retcode; ++ ++ brcmf_c_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf)); ++ retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, ++ iovbuf, sizeof(iovbuf)); ++ retcode = retcode >= 0 ? 0 : retcode; ++ if (retcode) ++ brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, retcode = %d\n", ++ arp_mode, retcode); ++ else ++ brcmf_dbg(TRACE, "successfully set ARP offload mode to 0x%x\n", ++ arp_mode); ++} ++ ++static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable) ++{ ++ char iovbuf[32]; ++ int retcode; ++ ++ brcmf_c_mkiovar("arpoe", (char *)&arp_enable, 4, ++ iovbuf, sizeof(iovbuf)); ++ retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, ++ iovbuf, sizeof(iovbuf)); ++ retcode = retcode >= 0 ? 0 : retcode; ++ if (retcode) ++ brcmf_dbg(TRACE, "failed to enable ARP offload to %d, retcode = %d\n", ++ arp_enable, retcode); ++ else ++ brcmf_dbg(TRACE, "successfully enabled ARP offload to %d\n", ++ arp_enable); ++} ++ ++int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) ++{ ++ char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for ++ "event_msgs" + '\0' + bitvec */ ++ uint up = 0; ++ char buf[128], *ptr; ++ u32 dongle_align = BRCMF_SDALIGN; ++ u32 glom = 0; ++ u32 roaming = 1; ++ uint bcn_timeout = 3; ++ int scan_assoc_time = 40; ++ int scan_unassoc_time = 40; ++ int i; ++ ++ brcmf_os_proto_block(drvr); ++ ++ /* Set Country code */ ++ if (drvr->country_code[0] != 0) { ++ if (brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_COUNTRY, ++ drvr->country_code, ++ sizeof(drvr->country_code)) < 0) ++ brcmf_dbg(ERROR, "country code setting failed\n"); ++ } ++ ++ /* query for 'ver' to get version info from firmware */ ++ memset(buf, 0, sizeof(buf)); ++ ptr = buf; ++ brcmf_c_mkiovar("ver", NULL, 0, buf, sizeof(buf)); ++ brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, buf, sizeof(buf)); ++ strsep(&ptr, "\n"); ++ /* Print fw version info */ ++ brcmf_dbg(ERROR, "Firmware version = %s\n", buf); ++ ++ /* Match Host and Dongle rx alignment */ ++ brcmf_c_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, ++ sizeof(iovbuf)); ++ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, ++ sizeof(iovbuf)); ++ ++ /* disable glom option per default */ ++ brcmf_c_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); ++ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, ++ sizeof(iovbuf)); ++ ++ /* Setup timeout if Beacons are lost and roam is off to report ++ link down */ ++ brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, ++ sizeof(iovbuf)); ++ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, ++ sizeof(iovbuf)); ++ ++ /* Enable/Disable build-in roaming to allowed ext supplicant to take ++ of romaing */ ++ brcmf_c_mkiovar("roam_off", (char *)&roaming, 4, ++ iovbuf, sizeof(iovbuf)); ++ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, ++ sizeof(iovbuf)); ++ ++ /* Force STA UP */ ++ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_UP, (char *)&up, sizeof(up)); ++ ++ /* Setup event_msgs */ ++ brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN, ++ iovbuf, sizeof(iovbuf)); ++ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, ++ sizeof(iovbuf)); ++ ++ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME, ++ (char *)&scan_assoc_time, sizeof(scan_assoc_time)); ++ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME, ++ (char *)&scan_unassoc_time, sizeof(scan_unassoc_time)); ++ ++ /* Set and enable ARP offload feature */ ++ brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE); ++ brcmf_c_arp_offload_enable(drvr, true); ++ ++ /* Set up pkt filter */ ++ for (i = 0; i < drvr->pktfilter_count; i++) { ++ brcmf_c_pktfilter_offload_set(drvr, drvr->pktfilter[i]); ++ brcmf_c_pktfilter_offload_enable(drvr, drvr->pktfilter[i], ++ 0, true); ++ } ++ ++ brcmf_os_proto_unblock(drvr); ++ ++ return 0; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h.orig 2011-11-09 13:46:58.231800808 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h 2011-11-09 13:47:16.981566403 -0500 +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCMF_DBG_H_ ++#define _BRCMF_DBG_H_ ++ ++#if defined(BCMDBG) ++ ++#define brcmf_dbg(level, fmt, ...) \ ++do { \ ++ if (BRCMF_ERROR_VAL == BRCMF_##level##_VAL) { \ ++ if (brcmf_msg_level & BRCMF_##level##_VAL) { \ ++ if (net_ratelimit()) \ ++ printk(KERN_DEBUG "%s: " fmt, \ ++ __func__, ##__VA_ARGS__); \ ++ } \ ++ } else { \ ++ if (brcmf_msg_level & BRCMF_##level##_VAL) { \ ++ printk(KERN_DEBUG "%s: " fmt, \ ++ __func__, ##__VA_ARGS__); \ ++ } \ ++ } \ ++} while (0) ++ ++#define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL) ++#define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL) ++#define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL) ++#define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL) ++#define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL) ++ ++#else /* (defined BCMDBG) || (defined BCMDBG) */ ++ ++#define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__) ++ ++#define BRCMF_DATA_ON() 0 ++#define BRCMF_CTL_ON() 0 ++#define BRCMF_HDRS_ON() 0 ++#define BRCMF_BYTES_ON() 0 ++#define BRCMF_GLOM_ON() 0 ++ ++#endif /* defined(BCMDBG) */ ++ ++extern int brcmf_msg_level; ++ ++#endif /* _BRCMF_DBG_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd.h.orig 2011-11-09 13:46:58.231800808 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd.h 2011-11-09 13:47:16.982566390 -0500 +@@ -0,0 +1,776 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/**************** ++ * Common types * ++ */ ++ ++#ifndef _BRCMF_H_ ++#define _BRCMF_H_ ++ ++#define BRCMF_VERSION_STR "4.218.248.5" ++ ++/******************************************************************************* ++ * IO codes that are interpreted by dongle firmware ++ ******************************************************************************/ ++#define BRCMF_C_UP 2 ++#define BRCMF_C_SET_PROMISC 10 ++#define BRCMF_C_GET_RATE 12 ++#define BRCMF_C_GET_INFRA 19 ++#define BRCMF_C_SET_INFRA 20 ++#define BRCMF_C_GET_AUTH 21 ++#define BRCMF_C_SET_AUTH 22 ++#define BRCMF_C_GET_BSSID 23 ++#define BRCMF_C_GET_SSID 25 ++#define BRCMF_C_SET_SSID 26 ++#define BRCMF_C_GET_CHANNEL 29 ++#define BRCMF_C_GET_SRL 31 ++#define BRCMF_C_GET_LRL 33 ++#define BRCMF_C_GET_RADIO 37 ++#define BRCMF_C_SET_RADIO 38 ++#define BRCMF_C_GET_PHYTYPE 39 ++#define BRCMF_C_SET_KEY 45 ++#define BRCMF_C_SET_PASSIVE_SCAN 49 ++#define BRCMF_C_SCAN 50 ++#define BRCMF_C_SCAN_RESULTS 51 ++#define BRCMF_C_DISASSOC 52 ++#define BRCMF_C_REASSOC 53 ++#define BRCMF_C_SET_ROAM_TRIGGER 55 ++#define BRCMF_C_SET_ROAM_DELTA 57 ++#define BRCMF_C_GET_DTIMPRD 77 ++#define BRCMF_C_SET_COUNTRY 84 ++#define BRCMF_C_GET_PM 85 ++#define BRCMF_C_SET_PM 86 ++#define BRCMF_C_GET_AP 117 ++#define BRCMF_C_SET_AP 118 ++#define BRCMF_C_GET_RSSI 127 ++#define BRCMF_C_GET_WSEC 133 ++#define BRCMF_C_SET_WSEC 134 ++#define BRCMF_C_GET_PHY_NOISE 135 ++#define BRCMF_C_GET_BSS_INFO 136 ++#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 ++#define BRCMF_C_SET_SCAN_UNASSOC_TIME 187 ++#define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201 ++#define BRCMF_C_GET_VALID_CHANNELS 217 ++#define BRCMF_C_GET_KEY_PRIMARY 235 ++#define BRCMF_C_SET_KEY_PRIMARY 236 ++#define BRCMF_C_SET_SCAN_PASSIVE_TIME 258 ++#define BRCMF_C_GET_VAR 262 ++#define BRCMF_C_SET_VAR 263 ++ ++/* phy types (returned by WLC_GET_PHYTPE) */ ++#define WLC_PHY_TYPE_A 0 ++#define WLC_PHY_TYPE_B 1 ++#define WLC_PHY_TYPE_G 2 ++#define WLC_PHY_TYPE_N 4 ++#define WLC_PHY_TYPE_LP 5 ++#define WLC_PHY_TYPE_SSN 6 ++#define WLC_PHY_TYPE_HT 7 ++#define WLC_PHY_TYPE_LCN 8 ++#define WLC_PHY_TYPE_NULL 0xf ++ ++#define BRCMF_EVENTING_MASK_LEN 16 ++ ++#define TOE_TX_CSUM_OL 0x00000001 ++#define TOE_RX_CSUM_OL 0x00000002 ++ ++#define BRCMF_BSS_INFO_VERSION 108 /* current ver of brcmf_bss_info struct */ ++ ++/* size of brcmf_scan_params not including variable length array */ ++#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64 ++ ++/* masks for channel and ssid count */ ++#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff ++#define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16 ++ ++#define BRCMF_SCAN_ACTION_START 1 ++#define BRCMF_SCAN_ACTION_CONTINUE 2 ++#define WL_SCAN_ACTION_ABORT 3 ++ ++#define BRCMF_ISCAN_REQ_VERSION 1 ++ ++/* brcmf_iscan_results status values */ ++#define BRCMF_SCAN_RESULTS_SUCCESS 0 ++#define BRCMF_SCAN_RESULTS_PARTIAL 1 ++#define BRCMF_SCAN_RESULTS_PENDING 2 ++#define BRCMF_SCAN_RESULTS_ABORTED 3 ++#define BRCMF_SCAN_RESULTS_NO_MEM 4 ++ ++/* Indicates this key is using soft encrypt */ ++#define WL_SOFT_KEY (1 << 0) ++/* primary (ie tx) key */ ++#define BRCMF_PRIMARY_KEY (1 << 1) ++/* Reserved for backward compat */ ++#define WL_KF_RES_4 (1 << 4) ++/* Reserved for backward compat */ ++#define WL_KF_RES_5 (1 << 5) ++/* Indicates a group key for a IBSS PEER */ ++#define WL_IBSS_PEER_GROUP_KEY (1 << 6) ++ ++/* For supporting multiple interfaces */ ++#define BRCMF_MAX_IFS 16 ++#define BRCMF_DEL_IF -0xe ++#define BRCMF_BAD_IF -0xf ++ ++#define DOT11_BSSTYPE_ANY 2 ++#define DOT11_MAX_DEFAULT_KEYS 4 ++ ++#define BRCMF_EVENT_MSG_LINK 0x01 ++#define BRCMF_EVENT_MSG_FLUSHTXQ 0x02 ++#define BRCMF_EVENT_MSG_GROUP 0x04 ++ ++struct brcmf_event_msg { ++ __be16 version; ++ __be16 flags; ++ __be32 event_type; ++ __be32 status; ++ __be32 reason; ++ __be32 auth_type; ++ __be32 datalen; ++ u8 addr[ETH_ALEN]; ++ char ifname[IFNAMSIZ]; ++} __packed; ++ ++struct brcm_ethhdr { ++ u16 subtype; ++ u16 length; ++ u8 version; ++ u8 oui[3]; ++ u16 usr_subtype; ++} __packed; ++ ++struct brcmf_event { ++ struct ethhdr eth; ++ struct brcm_ethhdr hdr; ++ struct brcmf_event_msg msg; ++} __packed; ++ ++struct dngl_stats { ++ unsigned long rx_packets; /* total packets received */ ++ unsigned long tx_packets; /* total packets transmitted */ ++ unsigned long rx_bytes; /* total bytes received */ ++ unsigned long tx_bytes; /* total bytes transmitted */ ++ unsigned long rx_errors; /* bad packets received */ ++ unsigned long tx_errors; /* packet transmit problems */ ++ unsigned long rx_dropped; /* packets dropped by dongle */ ++ unsigned long tx_dropped; /* packets dropped by dongle */ ++ unsigned long multicast; /* multicast packets received */ ++}; ++ ++/* event codes sent by the dongle to this driver */ ++#define BRCMF_E_SET_SSID 0 ++#define BRCMF_E_JOIN 1 ++#define BRCMF_E_START 2 ++#define BRCMF_E_AUTH 3 ++#define BRCMF_E_AUTH_IND 4 ++#define BRCMF_E_DEAUTH 5 ++#define BRCMF_E_DEAUTH_IND 6 ++#define BRCMF_E_ASSOC 7 ++#define BRCMF_E_ASSOC_IND 8 ++#define BRCMF_E_REASSOC 9 ++#define BRCMF_E_REASSOC_IND 10 ++#define BRCMF_E_DISASSOC 11 ++#define BRCMF_E_DISASSOC_IND 12 ++#define BRCMF_E_QUIET_START 13 ++#define BRCMF_E_QUIET_END 14 ++#define BRCMF_E_BEACON_RX 15 ++#define BRCMF_E_LINK 16 ++#define BRCMF_E_MIC_ERROR 17 ++#define BRCMF_E_NDIS_LINK 18 ++#define BRCMF_E_ROAM 19 ++#define BRCMF_E_TXFAIL 20 ++#define BRCMF_E_PMKID_CACHE 21 ++#define BRCMF_E_RETROGRADE_TSF 22 ++#define BRCMF_E_PRUNE 23 ++#define BRCMF_E_AUTOAUTH 24 ++#define BRCMF_E_EAPOL_MSG 25 ++#define BRCMF_E_SCAN_COMPLETE 26 ++#define BRCMF_E_ADDTS_IND 27 ++#define BRCMF_E_DELTS_IND 28 ++#define BRCMF_E_BCNSENT_IND 29 ++#define BRCMF_E_BCNRX_MSG 30 ++#define BRCMF_E_BCNLOST_MSG 31 ++#define BRCMF_E_ROAM_PREP 32 ++#define BRCMF_E_PFN_NET_FOUND 33 ++#define BRCMF_E_PFN_NET_LOST 34 ++#define BRCMF_E_RESET_COMPLETE 35 ++#define BRCMF_E_JOIN_START 36 ++#define BRCMF_E_ROAM_START 37 ++#define BRCMF_E_ASSOC_START 38 ++#define BRCMF_E_IBSS_ASSOC 39 ++#define BRCMF_E_RADIO 40 ++#define BRCMF_E_PSM_WATCHDOG 41 ++#define BRCMF_E_PROBREQ_MSG 44 ++#define BRCMF_E_SCAN_CONFIRM_IND 45 ++#define BRCMF_E_PSK_SUP 46 ++#define BRCMF_E_COUNTRY_CODE_CHANGED 47 ++#define BRCMF_E_EXCEEDED_MEDIUM_TIME 48 ++#define BRCMF_E_ICV_ERROR 49 ++#define BRCMF_E_UNICAST_DECODE_ERROR 50 ++#define BRCMF_E_MULTICAST_DECODE_ERROR 51 ++#define BRCMF_E_TRACE 52 ++#define BRCMF_E_IF 54 ++#define BRCMF_E_RSSI 56 ++#define BRCMF_E_PFN_SCAN_COMPLETE 57 ++#define BRCMF_E_EXTLOG_MSG 58 ++#define BRCMF_E_ACTION_FRAME 59 ++#define BRCMF_E_ACTION_FRAME_COMPLETE 60 ++#define BRCMF_E_PRE_ASSOC_IND 61 ++#define BRCMF_E_PRE_REASSOC_IND 62 ++#define BRCMF_E_CHANNEL_ADOPTED 63 ++#define BRCMF_E_AP_STARTED 64 ++#define BRCMF_E_DFS_AP_STOP 65 ++#define BRCMF_E_DFS_AP_RESUME 66 ++#define BRCMF_E_RESERVED1 67 ++#define BRCMF_E_RESERVED2 68 ++#define BRCMF_E_ESCAN_RESULT 69 ++#define BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70 ++#define BRCMF_E_DCS_REQUEST 73 ++ ++#define BRCMF_E_FIFO_CREDIT_MAP 74 ++ ++#define BRCMF_E_LAST 75 ++ ++#define BRCMF_E_STATUS_SUCCESS 0 ++#define BRCMF_E_STATUS_FAIL 1 ++#define BRCMF_E_STATUS_TIMEOUT 2 ++#define BRCMF_E_STATUS_NO_NETWORKS 3 ++#define BRCMF_E_STATUS_ABORT 4 ++#define BRCMF_E_STATUS_NO_ACK 5 ++#define BRCMF_E_STATUS_UNSOLICITED 6 ++#define BRCMF_E_STATUS_ATTEMPT 7 ++#define BRCMF_E_STATUS_PARTIAL 8 ++#define BRCMF_E_STATUS_NEWSCAN 9 ++#define BRCMF_E_STATUS_NEWASSOC 10 ++#define BRCMF_E_STATUS_11HQUIET 11 ++#define BRCMF_E_STATUS_SUPPRESS 12 ++#define BRCMF_E_STATUS_NOCHANS 13 ++#define BRCMF_E_STATUS_CS_ABORT 15 ++#define BRCMF_E_STATUS_ERROR 16 ++ ++#define BRCMF_E_REASON_INITIAL_ASSOC 0 ++#define BRCMF_E_REASON_LOW_RSSI 1 ++#define BRCMF_E_REASON_DEAUTH 2 ++#define BRCMF_E_REASON_DISASSOC 3 ++#define BRCMF_E_REASON_BCNS_LOST 4 ++#define BRCMF_E_REASON_MINTXRATE 9 ++#define BRCMF_E_REASON_TXFAIL 10 ++ ++#define BRCMF_E_REASON_FAST_ROAM_FAILED 5 ++#define BRCMF_E_REASON_DIRECTED_ROAM 6 ++#define BRCMF_E_REASON_TSPEC_REJECTED 7 ++#define BRCMF_E_REASON_BETTER_AP 8 ++ ++#define BRCMF_E_PRUNE_ENCR_MISMATCH 1 ++#define BRCMF_E_PRUNE_BCAST_BSSID 2 ++#define BRCMF_E_PRUNE_MAC_DENY 3 ++#define BRCMF_E_PRUNE_MAC_NA 4 ++#define BRCMF_E_PRUNE_REG_PASSV 5 ++#define BRCMF_E_PRUNE_SPCT_MGMT 6 ++#define BRCMF_E_PRUNE_RADAR 7 ++#define BRCMF_E_RSN_MISMATCH 8 ++#define BRCMF_E_PRUNE_NO_COMMON_RATES 9 ++#define BRCMF_E_PRUNE_BASIC_RATES 10 ++#define BRCMF_E_PRUNE_CIPHER_NA 12 ++#define BRCMF_E_PRUNE_KNOWN_STA 13 ++#define BRCMF_E_PRUNE_WDS_PEER 15 ++#define BRCMF_E_PRUNE_QBSS_LOAD 16 ++#define BRCMF_E_PRUNE_HOME_AP 17 ++ ++#define BRCMF_E_SUP_OTHER 0 ++#define BRCMF_E_SUP_DECRYPT_KEY_DATA 1 ++#define BRCMF_E_SUP_BAD_UCAST_WEP128 2 ++#define BRCMF_E_SUP_BAD_UCAST_WEP40 3 ++#define BRCMF_E_SUP_UNSUP_KEY_LEN 4 ++#define BRCMF_E_SUP_PW_KEY_CIPHER 5 ++#define BRCMF_E_SUP_MSG3_TOO_MANY_IE 6 ++#define BRCMF_E_SUP_MSG3_IE_MISMATCH 7 ++#define BRCMF_E_SUP_NO_INSTALL_FLAG 8 ++#define BRCMF_E_SUP_MSG3_NO_GTK 9 ++#define BRCMF_E_SUP_GRP_KEY_CIPHER 10 ++#define BRCMF_E_SUP_GRP_MSG1_NO_GTK 11 ++#define BRCMF_E_SUP_GTK_DECRYPT_FAIL 12 ++#define BRCMF_E_SUP_SEND_FAIL 13 ++#define BRCMF_E_SUP_DEAUTH 14 ++ ++#define BRCMF_E_IF_ADD 1 ++#define BRCMF_E_IF_DEL 2 ++#define BRCMF_E_IF_CHANGE 3 ++ ++#define BRCMF_E_IF_ROLE_STA 0 ++#define BRCMF_E_IF_ROLE_AP 1 ++#define BRCMF_E_IF_ROLE_WDS 2 ++ ++#define BRCMF_E_LINK_BCN_LOSS 1 ++#define BRCMF_E_LINK_DISASSOC 2 ++#define BRCMF_E_LINK_ASSOC_REC 3 ++#define BRCMF_E_LINK_BSSCFG_DIS 4 ++ ++/* The level of bus communication with the dongle */ ++enum brcmf_bus_state { ++ BRCMF_BUS_DOWN, /* Not ready for frame transfers */ ++ BRCMF_BUS_LOAD, /* Download access only (CPU reset) */ ++ BRCMF_BUS_DATA /* Ready for frame transfers */ ++}; ++ ++/* Pattern matching filter. Specifies an offset within received packets to ++ * start matching, the pattern to match, the size of the pattern, and a bitmask ++ * that indicates which bits within the pattern should be matched. ++ */ ++struct brcmf_pkt_filter_pattern_le { ++ /* ++ * Offset within received packet to start pattern matching. ++ * Offset '0' is the first byte of the ethernet header. ++ */ ++ __le32 offset; ++ /* Size of the pattern. Bitmask must be the same size.*/ ++ __le32 size_bytes; ++ /* ++ * Variable length mask and pattern data. mask starts at offset 0. ++ * Pattern immediately follows mask. ++ */ ++ u8 mask_and_pattern[1]; ++}; ++ ++/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */ ++struct brcmf_pkt_filter_le { ++ __le32 id; /* Unique filter id, specified by app. */ ++ __le32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */ ++ __le32 negate_match; /* Negate the result of filter matches */ ++ union { /* Filter definitions */ ++ struct brcmf_pkt_filter_pattern_le pattern; /* Filter pattern */ ++ } u; ++}; ++ ++/* IOVAR "pkt_filter_enable" parameter. */ ++struct brcmf_pkt_filter_enable_le { ++ __le32 id; /* Unique filter id */ ++ __le32 enable; /* Enable/disable bool */ ++}; ++ ++/* BSS info structure ++ * Applications MUST CHECK ie_offset field and length field to access IEs and ++ * next bss_info structure in a vector (in struct brcmf_scan_results) ++ */ ++struct brcmf_bss_info { ++ __le32 version; /* version field */ ++ __le32 length; /* byte length of data in this record, ++ * starting at version and including IEs ++ */ ++ u8 BSSID[ETH_ALEN]; ++ __le16 beacon_period; /* units are Kusec */ ++ __le16 capability; /* Capability information */ ++ u8 SSID_len; ++ u8 SSID[32]; ++ struct { ++ __le32 count; /* # rates in this set */ ++ u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ ++ } rateset; /* supported rates */ ++ __le16 chanspec; /* chanspec for bss */ ++ __le16 atim_window; /* units are Kusec */ ++ u8 dtim_period; /* DTIM period */ ++ __le16 RSSI; /* receive signal strength (in dBm) */ ++ s8 phy_noise; /* noise (in dBm) */ ++ ++ u8 n_cap; /* BSS is 802.11N Capable */ ++ /* 802.11N BSS Capabilities (based on HT_CAP_*): */ ++ __le32 nbss_cap; ++ u8 ctl_ch; /* 802.11N BSS control channel number */ ++ __le32 reserved32[1]; /* Reserved for expansion of BSS properties */ ++ u8 flags; /* flags */ ++ u8 reserved[3]; /* Reserved for expansion of BSS properties */ ++ u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ ++ ++ __le16 ie_offset; /* offset at which IEs start, from beginning */ ++ __le32 ie_length; /* byte length of Information Elements */ ++ __le16 SNR; /* average SNR of during frame reception */ ++ /* Add new fields here */ ++ /* variable length Information Elements */ ++}; ++ ++struct brcm_rateset_le { ++ /* # rates in this set */ ++ __le32 count; ++ /* rates in 500kbps units w/hi bit set if basic */ ++ u8 rates[WL_NUMRATES]; ++}; ++ ++struct brcmf_ssid { ++ u32 SSID_len; ++ unsigned char SSID[32]; ++}; ++ ++struct brcmf_ssid_le { ++ __le32 SSID_len; ++ unsigned char SSID[32]; ++}; ++ ++struct brcmf_scan_params_le { ++ struct brcmf_ssid_le ssid_le; /* default: {0, ""} */ ++ u8 bssid[ETH_ALEN]; /* default: bcast */ ++ s8 bss_type; /* default: any, ++ * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT ++ */ ++ u8 scan_type; /* flags, 0 use default */ ++ __le32 nprobes; /* -1 use default, number of probes per channel */ ++ __le32 active_time; /* -1 use default, dwell time per channel for ++ * active scanning ++ */ ++ __le32 passive_time; /* -1 use default, dwell time per channel ++ * for passive scanning ++ */ ++ __le32 home_time; /* -1 use default, dwell time for the ++ * home channel between channel scans ++ */ ++ __le32 channel_num; /* count of channels and ssids that follow ++ * ++ * low half is count of channels in ++ * channel_list, 0 means default (use all ++ * available channels) ++ * ++ * high half is entries in struct brcmf_ssid ++ * array that follows channel_list, aligned for ++ * s32 (4 bytes) meaning an odd channel count ++ * implies a 2-byte pad between end of ++ * channel_list and first ssid ++ * ++ * if ssid count is zero, single ssid in the ++ * fixed parameter portion is assumed, otherwise ++ * ssid in the fixed portion is ignored ++ */ ++ __le16 channel_list[1]; /* list of chanspecs */ ++}; ++ ++/* incremental scan struct */ ++struct brcmf_iscan_params_le { ++ __le32 version; ++ __le16 action; ++ __le16 scan_duration; ++ struct brcmf_scan_params_le params_le; ++}; ++ ++struct brcmf_scan_results { ++ u32 buflen; ++ u32 version; ++ u32 count; ++ struct brcmf_bss_info bss_info[1]; ++}; ++ ++struct brcmf_scan_results_le { ++ __le32 buflen; ++ __le32 version; ++ __le32 count; ++ struct brcmf_bss_info bss_info[1]; ++}; ++ ++/* used for association with a specific BSSID and chanspec list */ ++struct brcmf_assoc_params_le { ++ /* 00:00:00:00:00:00: broadcast scan */ ++ u8 bssid[ETH_ALEN]; ++ /* 0: all available channels, otherwise count of chanspecs in ++ * chanspec_list */ ++ __le32 chanspec_num; ++ /* list of chanspecs */ ++ __le16 chanspec_list[1]; ++}; ++ ++/* used for join with or without a specific bssid and channel list */ ++struct brcmf_join_params { ++ struct brcmf_ssid_le ssid_le; ++ struct brcmf_assoc_params_le params_le; ++}; ++ ++/* size of brcmf_scan_results not including variable length array */ ++#define BRCMF_SCAN_RESULTS_FIXED_SIZE \ ++ (sizeof(struct brcmf_scan_results) - sizeof(struct brcmf_bss_info)) ++ ++/* incremental scan results struct */ ++struct brcmf_iscan_results { ++ union { ++ u32 status; ++ __le32 status_le; ++ }; ++ union { ++ struct brcmf_scan_results results; ++ struct brcmf_scan_results_le results_le; ++ }; ++}; ++ ++/* size of brcmf_iscan_results not including variable length array */ ++#define BRCMF_ISCAN_RESULTS_FIXED_SIZE \ ++ (BRCMF_SCAN_RESULTS_FIXED_SIZE + \ ++ offsetof(struct brcmf_iscan_results, results)) ++ ++struct brcmf_wsec_key { ++ u32 index; /* key index */ ++ u32 len; /* key length */ ++ u8 data[WLAN_MAX_KEY_LEN]; /* key data */ ++ u32 pad_1[18]; ++ u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ ++ u32 flags; /* misc flags */ ++ u32 pad_2[3]; ++ u32 iv_initialized; /* has IV been initialized already? */ ++ u32 pad_3; ++ /* Rx IV */ ++ struct { ++ u32 hi; /* upper 32 bits of IV */ ++ u16 lo; /* lower 16 bits of IV */ ++ } rxiv; ++ u32 pad_4[2]; ++ u8 ea[ETH_ALEN]; /* per station */ ++}; ++ ++/* ++ * dongle requires same struct as above but with fields in little endian order ++ */ ++struct brcmf_wsec_key_le { ++ __le32 index; /* key index */ ++ __le32 len; /* key length */ ++ u8 data[WLAN_MAX_KEY_LEN]; /* key data */ ++ __le32 pad_1[18]; ++ __le32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ ++ __le32 flags; /* misc flags */ ++ __le32 pad_2[3]; ++ __le32 iv_initialized; /* has IV been initialized already? */ ++ __le32 pad_3; ++ /* Rx IV */ ++ struct { ++ __le32 hi; /* upper 32 bits of IV */ ++ __le16 lo; /* lower 16 bits of IV */ ++ } rxiv; ++ __le32 pad_4[2]; ++ u8 ea[ETH_ALEN]; /* per station */ ++}; ++ ++/* Used to get specific STA parameters */ ++struct brcmf_scb_val_le { ++ __le32 val; ++ u8 ea[ETH_ALEN]; ++}; ++ ++/* channel encoding */ ++struct brcmf_channel_info_le { ++ __le32 hw_channel; ++ __le32 target_channel; ++ __le32 scan_channel; ++}; ++ ++/* Bus independent dongle command */ ++struct brcmf_dcmd { ++ uint cmd; /* common dongle cmd definition */ ++ void *buf; /* pointer to user buffer */ ++ uint len; /* length of user buffer */ ++ u8 set; /* get or set request (optional) */ ++ uint used; /* bytes read or written (optional) */ ++ uint needed; /* bytes needed (optional) */ ++}; ++ ++/* Forward decls for struct brcmf_pub (see below) */ ++struct brcmf_bus; /* device bus info */ ++struct brcmf_proto; /* device communication protocol info */ ++struct brcmf_info; /* device driver info */ ++struct brcmf_cfg80211_dev; /* cfg80211 device info */ ++ ++/* Common structure for module and instance linkage */ ++struct brcmf_pub { ++ /* Linkage ponters */ ++ struct brcmf_bus *bus; ++ struct brcmf_proto *prot; ++ struct brcmf_info *info; ++ struct brcmf_cfg80211_dev *config; ++ ++ /* Internal brcmf items */ ++ bool up; /* Driver up/down (to OS) */ ++ bool txoff; /* Transmit flow-controlled */ ++ enum brcmf_bus_state busstate; ++ uint hdrlen; /* Total BRCMF header length (proto + bus) */ ++ uint maxctl; /* Max size rxctl request from proto to bus */ ++ uint rxsz; /* Rx buffer size bus module should use */ ++ u8 wme_dp; /* wme discard priority */ ++ ++ /* Dongle media info */ ++ bool iswl; /* Dongle-resident driver is wl */ ++ unsigned long drv_version; /* Version of dongle-resident driver */ ++ u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */ ++ struct dngl_stats dstats; /* Stats for dongle-based data */ ++ ++ /* Additional stats for the bus level */ ++ ++ /* Data packets sent to dongle */ ++ unsigned long tx_packets; ++ /* Multicast data packets sent to dongle */ ++ unsigned long tx_multicast; ++ /* Errors in sending data to dongle */ ++ unsigned long tx_errors; ++ /* Control packets sent to dongle */ ++ unsigned long tx_ctlpkts; ++ /* Errors sending control frames to dongle */ ++ unsigned long tx_ctlerrs; ++ /* Packets sent up the network interface */ ++ unsigned long rx_packets; ++ /* Multicast packets sent up the network interface */ ++ unsigned long rx_multicast; ++ /* Errors processing rx data packets */ ++ unsigned long rx_errors; ++ /* Control frames processed from dongle */ ++ unsigned long rx_ctlpkts; ++ ++ /* Errors in processing rx control frames */ ++ unsigned long rx_ctlerrs; ++ /* Packets dropped locally (no memory) */ ++ unsigned long rx_dropped; ++ /* Packets flushed due to unscheduled sendup thread */ ++ unsigned long rx_flushed; ++ /* Number of times dpc scheduled by watchdog timer */ ++ unsigned long wd_dpc_sched; ++ ++ /* Number of packets where header read-ahead was used. */ ++ unsigned long rx_readahead_cnt; ++ /* Number of tx packets we had to realloc for headroom */ ++ unsigned long tx_realloc; ++ /* Number of flow control pkts recvd */ ++ unsigned long fc_packets; ++ ++ /* Last error return */ ++ int bcmerror; ++ uint tickcnt; ++ ++ /* Last error from dongle */ ++ int dongle_error; ++ ++ /* Suspend disable flag flag */ ++ int suspend_disable_flag; /* "1" to disable all extra powersaving ++ during suspend */ ++ int in_suspend; /* flag set to 1 when early suspend called */ ++ int dtim_skip; /* dtim skip , default 0 means wake each dtim */ ++ ++ /* Pkt filter defination */ ++ char *pktfilter[100]; ++ int pktfilter_count; ++ ++ u8 country_code[BRCM_CNTRY_BUF_SZ]; ++ char eventmask[BRCMF_EVENTING_MASK_LEN]; ++ ++}; ++ ++struct brcmf_if_event { ++ u8 ifidx; ++ u8 action; ++ u8 flags; ++ u8 bssidx; ++}; ++ ++struct bcmevent_name { ++ uint event; ++ const char *name; ++}; ++ ++extern const struct bcmevent_name bcmevent_names[]; ++ ++extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen, ++ char *buf, uint len); ++ ++/* Indication from bus module regarding presence/insertion of dongle. ++ * Return struct brcmf_pub pointer, used as handle to OS module in later calls. ++ * Returned structure should have bus and prot pointers filled in. ++ * bus_hdrlen specifies required headroom for bus module header. ++ */ ++extern struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, ++ uint bus_hdrlen); ++extern int brcmf_net_attach(struct brcmf_pub *drvr, int idx); ++extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev); ++ ++extern s32 brcmf_exec_dcmd(struct net_device *dev, u32 cmd, void *arg, u32 len); ++ ++/* Indication from bus module regarding removal/absence of dongle */ ++extern void brcmf_detach(struct brcmf_pub *drvr); ++ ++/* Indication from bus module to change flow-control state */ ++extern void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool on); ++ ++extern bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q, ++ struct sk_buff *pkt, int prec); ++ ++/* Receive frame for delivery to OS. Callee disposes of rxp. */ ++extern void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, ++ struct sk_buff *rxp, int numpkt); ++ ++/* Return pointer to interface name */ ++extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx); ++ ++/* Notify tx completion */ ++extern void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, ++ bool success); ++ ++/* Query dongle */ ++extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, ++ uint cmd, void *buf, uint len); ++ ++/* OS independent layer functions */ ++extern int brcmf_os_proto_block(struct brcmf_pub *drvr); ++extern int brcmf_os_proto_unblock(struct brcmf_pub *drvr); ++#ifdef BCMDBG ++extern int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size); ++#endif /* BCMDBG */ ++ ++extern int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name); ++extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx, ++ void *pktdata, struct brcmf_event_msg *, ++ void **data_ptr); ++ ++extern void brcmf_c_init(void); ++ ++extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, ++ struct net_device *ndev, char *name, u8 *mac_addr, ++ u32 flags, u8 bssidx); ++extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx); ++ ++/* Send packet to dongle via data channel */ ++extern int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx,\ ++ struct sk_buff *pkt); ++ ++extern int brcmf_bus_start(struct brcmf_pub *drvr); ++ ++extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg); ++extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, ++ int enable, int master_mode); ++ ++#define BRCMF_DCMD_SMLEN 256 /* "small" cmd buffer required */ ++#define BRCMF_DCMD_MEDLEN 1536 /* "med" cmd buffer required */ ++#define BRCMF_DCMD_MAXLEN 8192 /* max length cmd buffer required */ ++ ++/* message levels */ ++#define BRCMF_ERROR_VAL 0x0001 ++#define BRCMF_TRACE_VAL 0x0002 ++#define BRCMF_INFO_VAL 0x0004 ++#define BRCMF_DATA_VAL 0x0008 ++#define BRCMF_CTL_VAL 0x0010 ++#define BRCMF_TIMER_VAL 0x0020 ++#define BRCMF_HDRS_VAL 0x0040 ++#define BRCMF_BYTES_VAL 0x0080 ++#define BRCMF_INTR_VAL 0x0100 ++#define BRCMF_GLOM_VAL 0x0400 ++#define BRCMF_EVENT_VAL 0x0800 ++#define BRCMF_BTA_VAL 0x1000 ++#define BRCMF_ISCAN_VAL 0x2000 ++ ++/* Enter idle immediately (no timeout) */ ++#define BRCMF_IDLE_IMMEDIATE (-1) ++#define BRCMF_IDLE_ACTIVE 0 /* Do not request any SD clock change ++ when idle */ ++#define BRCMF_IDLE_INTERVAL 1 ++ ++#endif /* _BRCMF_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c.orig 2011-11-09 13:46:58.232800795 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c 2011-11-09 13:47:16.983566378 -0500 +@@ -0,0 +1,1356 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dhd.h" ++#include "dhd_bus.h" ++#include "dhd_proto.h" ++#include "dhd_dbg.h" ++#include "wl_cfg80211.h" ++#include "bcmchip.h" ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac driver."); ++MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards"); ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++ ++/* Interface control information */ ++struct brcmf_if { ++ struct brcmf_info *info; /* back pointer to brcmf_info */ ++ /* OS/stack specifics */ ++ struct net_device *ndev; ++ struct net_device_stats stats; ++ int idx; /* iface idx in dongle */ ++ int state; /* interface state */ ++ u8 mac_addr[ETH_ALEN]; /* assigned MAC address */ ++}; ++ ++/* Local private structure (extension of pub) */ ++struct brcmf_info { ++ struct brcmf_pub pub; ++ ++ /* OS/stack specifics */ ++ struct brcmf_if *iflist[BRCMF_MAX_IFS]; ++ ++ struct mutex proto_block; ++ ++ struct work_struct setmacaddr_work; ++ struct work_struct multicast_work; ++ u8 macvalue[ETH_ALEN]; ++ atomic_t pend_8021x_cnt; ++}; ++ ++/* Error bits */ ++module_param(brcmf_msg_level, int, 0); ++ ++ ++static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *ndev) ++{ ++ int i = 0; ++ ++ while (i < BRCMF_MAX_IFS) { ++ if (drvr_priv->iflist[i] && drvr_priv->iflist[i]->ndev == ndev) ++ return i; ++ i++; ++ } ++ ++ return BRCMF_BAD_IF; ++} ++ ++int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name) ++{ ++ int i = BRCMF_MAX_IFS; ++ struct brcmf_if *ifp; ++ ++ if (name == NULL || *name == '\0') ++ return 0; ++ ++ while (--i > 0) { ++ ifp = drvr_priv->iflist[i]; ++ if (ifp && !strncmp(ifp->ndev->name, name, IFNAMSIZ)) ++ break; ++ } ++ ++ brcmf_dbg(TRACE, "return idx %d for \"%s\"\n", i, name); ++ ++ return i; /* default - the primary interface */ ++} ++ ++char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx) ++{ ++ struct brcmf_info *drvr_priv = drvr->info; ++ ++ if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { ++ brcmf_dbg(ERROR, "ifidx %d out of range\n", ifidx); ++ return ""; ++ } ++ ++ if (drvr_priv->iflist[ifidx] == NULL) { ++ brcmf_dbg(ERROR, "null i/f %d\n", ifidx); ++ return ""; ++ } ++ ++ if (drvr_priv->iflist[ifidx]->ndev) ++ return drvr_priv->iflist[ifidx]->ndev->name; ++ ++ return ""; ++} ++ ++static void _brcmf_set_multicast_list(struct work_struct *work) ++{ ++ struct net_device *ndev; ++ struct netdev_hw_addr *ha; ++ u32 dcmd_value, cnt; ++ __le32 cnt_le; ++ __le32 dcmd_le_value; ++ ++ struct brcmf_dcmd dcmd; ++ char *buf, *bufp; ++ uint buflen; ++ int ret; ++ ++ struct brcmf_info *drvr_priv = container_of(work, struct brcmf_info, ++ multicast_work); ++ ++ ndev = drvr_priv->iflist[0]->ndev; ++ cnt = netdev_mc_count(ndev); ++ ++ /* Determine initial value of allmulti flag */ ++ dcmd_value = (ndev->flags & IFF_ALLMULTI) ? true : false; ++ ++ /* Send down the multicast list first. */ ++ ++ buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETH_ALEN); ++ bufp = buf = kmalloc(buflen, GFP_ATOMIC); ++ if (!bufp) ++ return; ++ ++ strcpy(bufp, "mcast_list"); ++ bufp += strlen("mcast_list") + 1; ++ ++ cnt_le = cpu_to_le32(cnt); ++ memcpy(bufp, &cnt_le, sizeof(cnt)); ++ bufp += sizeof(cnt_le); ++ ++ netdev_for_each_mc_addr(ha, ndev) { ++ if (!cnt) ++ break; ++ memcpy(bufp, ha->addr, ETH_ALEN); ++ bufp += ETH_ALEN; ++ cnt--; ++ } ++ ++ memset(&dcmd, 0, sizeof(dcmd)); ++ dcmd.cmd = BRCMF_C_SET_VAR; ++ dcmd.buf = buf; ++ dcmd.len = buflen; ++ dcmd.set = true; ++ ++ ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len); ++ if (ret < 0) { ++ brcmf_dbg(ERROR, "%s: set mcast_list failed, cnt %d\n", ++ brcmf_ifname(&drvr_priv->pub, 0), cnt); ++ dcmd_value = cnt ? true : dcmd_value; ++ } ++ ++ kfree(buf); ++ ++ /* Now send the allmulti setting. This is based on the setting in the ++ * net_device flags, but might be modified above to be turned on if we ++ * were trying to set some addresses and dongle rejected it... ++ */ ++ ++ buflen = sizeof("allmulti") + sizeof(dcmd_value); ++ buf = kmalloc(buflen, GFP_ATOMIC); ++ if (!buf) ++ return; ++ ++ dcmd_le_value = cpu_to_le32(dcmd_value); ++ ++ if (!brcmf_c_mkiovar ++ ("allmulti", (void *)&dcmd_le_value, ++ sizeof(dcmd_le_value), buf, buflen)) { ++ brcmf_dbg(ERROR, "%s: mkiovar failed for allmulti, datalen %d buflen %u\n", ++ brcmf_ifname(&drvr_priv->pub, 0), ++ (int)sizeof(dcmd_value), buflen); ++ kfree(buf); ++ return; ++ } ++ ++ memset(&dcmd, 0, sizeof(dcmd)); ++ dcmd.cmd = BRCMF_C_SET_VAR; ++ dcmd.buf = buf; ++ dcmd.len = buflen; ++ dcmd.set = true; ++ ++ ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len); ++ if (ret < 0) { ++ brcmf_dbg(ERROR, "%s: set allmulti %d failed\n", ++ brcmf_ifname(&drvr_priv->pub, 0), ++ le32_to_cpu(dcmd_le_value)); ++ } ++ ++ kfree(buf); ++ ++ /* Finally, pick up the PROMISC flag as well, like the NIC ++ driver does */ ++ ++ dcmd_value = (ndev->flags & IFF_PROMISC) ? true : false; ++ dcmd_le_value = cpu_to_le32(dcmd_value); ++ ++ memset(&dcmd, 0, sizeof(dcmd)); ++ dcmd.cmd = BRCMF_C_SET_PROMISC; ++ dcmd.buf = &dcmd_le_value; ++ dcmd.len = sizeof(dcmd_le_value); ++ dcmd.set = true; ++ ++ ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len); ++ if (ret < 0) { ++ brcmf_dbg(ERROR, "%s: set promisc %d failed\n", ++ brcmf_ifname(&drvr_priv->pub, 0), ++ le32_to_cpu(dcmd_le_value)); ++ } ++} ++ ++static void ++_brcmf_set_mac_address(struct work_struct *work) ++{ ++ char buf[32]; ++ struct brcmf_dcmd dcmd; ++ int ret; ++ ++ struct brcmf_info *drvr_priv = container_of(work, struct brcmf_info, ++ setmacaddr_work); ++ ++ brcmf_dbg(TRACE, "enter\n"); ++ if (!brcmf_c_mkiovar("cur_etheraddr", (char *)drvr_priv->macvalue, ++ ETH_ALEN, buf, 32)) { ++ brcmf_dbg(ERROR, "%s: mkiovar failed for cur_etheraddr\n", ++ brcmf_ifname(&drvr_priv->pub, 0)); ++ return; ++ } ++ memset(&dcmd, 0, sizeof(dcmd)); ++ dcmd.cmd = BRCMF_C_SET_VAR; ++ dcmd.buf = buf; ++ dcmd.len = 32; ++ dcmd.set = true; ++ ++ ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len); ++ if (ret < 0) ++ brcmf_dbg(ERROR, "%s: set cur_etheraddr failed\n", ++ brcmf_ifname(&drvr_priv->pub, 0)); ++ else ++ memcpy(drvr_priv->iflist[0]->ndev->dev_addr, ++ drvr_priv->macvalue, ETH_ALEN); ++ ++ return; ++} ++ ++static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr) ++{ ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **) ++ netdev_priv(ndev); ++ struct sockaddr *sa = (struct sockaddr *)addr; ++ int ifidx; ++ ++ ifidx = brcmf_net2idx(drvr_priv, ndev); ++ if (ifidx == BRCMF_BAD_IF) ++ return -1; ++ ++ memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN); ++ schedule_work(&drvr_priv->setmacaddr_work); ++ return 0; ++} ++ ++static void brcmf_netdev_set_multicast_list(struct net_device *ndev) ++{ ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **) ++ netdev_priv(ndev); ++ int ifidx; ++ ++ ifidx = brcmf_net2idx(drvr_priv, ndev); ++ if (ifidx == BRCMF_BAD_IF) ++ return; ++ ++ schedule_work(&drvr_priv->multicast_work); ++} ++ ++int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf) ++{ ++ struct brcmf_info *drvr_priv = drvr->info; ++ ++ /* Reject if down */ ++ if (!drvr->up || (drvr->busstate == BRCMF_BUS_DOWN)) ++ return -ENODEV; ++ ++ /* Update multicast statistic */ ++ if (pktbuf->len >= ETH_ALEN) { ++ u8 *pktdata = (u8 *) (pktbuf->data); ++ struct ethhdr *eh = (struct ethhdr *)pktdata; ++ ++ if (is_multicast_ether_addr(eh->h_dest)) ++ drvr->tx_multicast++; ++ if (ntohs(eh->h_proto) == ETH_P_PAE) ++ atomic_inc(&drvr_priv->pend_8021x_cnt); ++ } ++ ++ /* If the protocol uses a data header, apply it */ ++ brcmf_proto_hdrpush(drvr, ifidx, pktbuf); ++ ++ /* Use bus module to send data frame */ ++ return brcmf_sdbrcm_bus_txdata(drvr->bus, pktbuf); ++} ++ ++static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) ++{ ++ int ret; ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **) ++ netdev_priv(ndev); ++ int ifidx; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Reject if down */ ++ if (!drvr_priv->pub.up || (drvr_priv->pub.busstate == BRCMF_BUS_DOWN)) { ++ brcmf_dbg(ERROR, "xmit rejected pub.up=%d busstate=%d\n", ++ drvr_priv->pub.up, drvr_priv->pub.busstate); ++ netif_stop_queue(ndev); ++ return -ENODEV; ++ } ++ ++ ifidx = brcmf_net2idx(drvr_priv, ndev); ++ if (ifidx == BRCMF_BAD_IF) { ++ brcmf_dbg(ERROR, "bad ifidx %d\n", ifidx); ++ netif_stop_queue(ndev); ++ return -ENODEV; ++ } ++ ++ /* Make sure there's enough room for any header */ ++ if (skb_headroom(skb) < drvr_priv->pub.hdrlen) { ++ struct sk_buff *skb2; ++ ++ brcmf_dbg(INFO, "%s: insufficient headroom\n", ++ brcmf_ifname(&drvr_priv->pub, ifidx)); ++ drvr_priv->pub.tx_realloc++; ++ skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen); ++ dev_kfree_skb(skb); ++ skb = skb2; ++ if (skb == NULL) { ++ brcmf_dbg(ERROR, "%s: skb_realloc_headroom failed\n", ++ brcmf_ifname(&drvr_priv->pub, ifidx)); ++ ret = -ENOMEM; ++ goto done; ++ } ++ } ++ ++ ret = brcmf_sendpkt(&drvr_priv->pub, ifidx, skb); ++ ++done: ++ if (ret) ++ drvr_priv->pub.dstats.tx_dropped++; ++ else ++ drvr_priv->pub.tx_packets++; ++ ++ /* Return ok: we always eat the packet */ ++ return 0; ++} ++ ++void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool state) ++{ ++ struct net_device *ndev; ++ struct brcmf_info *drvr_priv = drvr->info; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ drvr->txoff = state; ++ ndev = drvr_priv->iflist[ifidx]->ndev; ++ if (state == ON) ++ netif_stop_queue(ndev); ++ else ++ netif_wake_queue(ndev); ++} ++ ++static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, ++ void *pktdata, struct brcmf_event_msg *event, ++ void **data) ++{ ++ int bcmerror = 0; ++ ++ bcmerror = brcmf_c_host_event(drvr_priv, ifidx, pktdata, event, data); ++ if (bcmerror != 0) ++ return bcmerror; ++ ++ if (drvr_priv->iflist[*ifidx]->ndev) ++ brcmf_cfg80211_event(drvr_priv->iflist[*ifidx]->ndev, ++ event, *data); ++ ++ return bcmerror; ++} ++ ++void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb, ++ int numpkt) ++{ ++ struct brcmf_info *drvr_priv = drvr->info; ++ unsigned char *eth; ++ uint len; ++ void *data; ++ struct sk_buff *pnext, *save_pktbuf; ++ int i; ++ struct brcmf_if *ifp; ++ struct brcmf_event_msg event; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ save_pktbuf = skb; ++ ++ for (i = 0; skb && i < numpkt; i++, skb = pnext) { ++ ++ pnext = skb->next; ++ skb->next = NULL; ++ ++ /* Get the protocol, maintain skb around eth_type_trans() ++ * The main reason for this hack is for the limitation of ++ * Linux 2.4 where 'eth_type_trans' uses the ++ * 'net->hard_header_len' ++ * to perform skb_pull inside vs ETH_HLEN. Since to avoid ++ * coping of the packet coming from the network stack to add ++ * BDC, Hardware header etc, during network interface ++ * registration ++ * we set the 'net->hard_header_len' to ETH_HLEN + extra space ++ * required ++ * for BDC, Hardware header etc. and not just the ETH_HLEN ++ */ ++ eth = skb->data; ++ len = skb->len; ++ ++ ifp = drvr_priv->iflist[ifidx]; ++ if (ifp == NULL) ++ ifp = drvr_priv->iflist[0]; ++ ++ skb->dev = ifp->ndev; ++ skb->protocol = eth_type_trans(skb, skb->dev); ++ ++ if (skb->pkt_type == PACKET_MULTICAST) ++ drvr_priv->pub.rx_multicast++; ++ ++ skb->data = eth; ++ skb->len = len; ++ ++ /* Strip header, count, deliver upward */ ++ skb_pull(skb, ETH_HLEN); ++ ++ /* Process special event packets and then discard them */ ++ if (ntohs(skb->protocol) == ETH_P_LINK_CTL) ++ brcmf_host_event(drvr_priv, &ifidx, ++ skb_mac_header(skb), ++ &event, &data); ++ ++ if (drvr_priv->iflist[ifidx] && ++ !drvr_priv->iflist[ifidx]->state) ++ ifp = drvr_priv->iflist[ifidx]; ++ ++ if (ifp->ndev) ++ ifp->ndev->last_rx = jiffies; ++ ++ drvr->dstats.rx_bytes += skb->len; ++ drvr->rx_packets++; /* Local count */ ++ ++ if (in_interrupt()) ++ netif_rx(skb); ++ else ++ /* If the receive is not processed inside an ISR, ++ * the softirqd must be woken explicitly to service ++ * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled ++ * by netif_rx_ni(), but in earlier kernels, we need ++ * to do it manually. ++ */ ++ netif_rx_ni(skb); ++ } ++} ++ ++void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, bool success) ++{ ++ uint ifidx; ++ struct brcmf_info *drvr_priv = drvr->info; ++ struct ethhdr *eh; ++ u16 type; ++ ++ brcmf_proto_hdrpull(drvr, &ifidx, txp); ++ ++ eh = (struct ethhdr *)(txp->data); ++ type = ntohs(eh->h_proto); ++ ++ if (type == ETH_P_PAE) ++ atomic_dec(&drvr_priv->pend_8021x_cnt); ++ ++} ++ ++static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) ++{ ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **) ++ netdev_priv(ndev); ++ struct brcmf_if *ifp; ++ int ifidx; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ ifidx = brcmf_net2idx(drvr_priv, ndev); ++ if (ifidx == BRCMF_BAD_IF) ++ return NULL; ++ ++ ifp = drvr_priv->iflist[ifidx]; ++ ++ if (drvr_priv->pub.up) ++ /* Use the protocol to get dongle stats */ ++ brcmf_proto_dstats(&drvr_priv->pub); ++ ++ /* Copy dongle stats to net device stats */ ++ ifp->stats.rx_packets = drvr_priv->pub.dstats.rx_packets; ++ ifp->stats.tx_packets = drvr_priv->pub.dstats.tx_packets; ++ ifp->stats.rx_bytes = drvr_priv->pub.dstats.rx_bytes; ++ ifp->stats.tx_bytes = drvr_priv->pub.dstats.tx_bytes; ++ ifp->stats.rx_errors = drvr_priv->pub.dstats.rx_errors; ++ ifp->stats.tx_errors = drvr_priv->pub.dstats.tx_errors; ++ ifp->stats.rx_dropped = drvr_priv->pub.dstats.rx_dropped; ++ ifp->stats.tx_dropped = drvr_priv->pub.dstats.tx_dropped; ++ ifp->stats.multicast = drvr_priv->pub.dstats.multicast; ++ ++ return &ifp->stats; ++} ++ ++/* Retrieve current toe component enables, which are kept ++ as a bitmap in toe_ol iovar */ ++static int brcmf_toe_get(struct brcmf_info *drvr_priv, int ifidx, u32 *toe_ol) ++{ ++ struct brcmf_dcmd dcmd; ++ __le32 toe_le; ++ char buf[32]; ++ int ret; ++ ++ memset(&dcmd, 0, sizeof(dcmd)); ++ ++ dcmd.cmd = BRCMF_C_GET_VAR; ++ dcmd.buf = buf; ++ dcmd.len = (uint) sizeof(buf); ++ dcmd.set = false; ++ ++ strcpy(buf, "toe_ol"); ++ ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len); ++ if (ret < 0) { ++ /* Check for older dongle image that doesn't support toe_ol */ ++ if (ret == -EIO) { ++ brcmf_dbg(ERROR, "%s: toe not supported by device\n", ++ brcmf_ifname(&drvr_priv->pub, ifidx)); ++ return -EOPNOTSUPP; ++ } ++ ++ brcmf_dbg(INFO, "%s: could not get toe_ol: ret=%d\n", ++ brcmf_ifname(&drvr_priv->pub, ifidx), ret); ++ return ret; ++ } ++ ++ memcpy(&toe_le, buf, sizeof(u32)); ++ *toe_ol = le32_to_cpu(toe_le); ++ return 0; ++} ++ ++/* Set current toe component enables in toe_ol iovar, ++ and set toe global enable iovar */ ++static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol) ++{ ++ struct brcmf_dcmd dcmd; ++ char buf[32]; ++ int ret; ++ __le32 toe_le = cpu_to_le32(toe_ol); ++ ++ memset(&dcmd, 0, sizeof(dcmd)); ++ ++ dcmd.cmd = BRCMF_C_SET_VAR; ++ dcmd.buf = buf; ++ dcmd.len = (uint) sizeof(buf); ++ dcmd.set = true; ++ ++ /* Set toe_ol as requested */ ++ strcpy(buf, "toe_ol"); ++ memcpy(&buf[sizeof("toe_ol")], &toe_le, sizeof(u32)); ++ ++ ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len); ++ if (ret < 0) { ++ brcmf_dbg(ERROR, "%s: could not set toe_ol: ret=%d\n", ++ brcmf_ifname(&drvr_priv->pub, ifidx), ret); ++ return ret; ++ } ++ ++ /* Enable toe globally only if any components are enabled. */ ++ toe_le = cpu_to_le32(toe_ol != 0); ++ ++ strcpy(buf, "toe"); ++ memcpy(&buf[sizeof("toe")], &toe_le, sizeof(u32)); ++ ++ ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len); ++ if (ret < 0) { ++ brcmf_dbg(ERROR, "%s: could not set toe: ret=%d\n", ++ brcmf_ifname(&drvr_priv->pub, ifidx), ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void brcmf_ethtool_get_drvinfo(struct net_device *ndev, ++ struct ethtool_drvinfo *info) ++{ ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **) ++ netdev_priv(ndev); ++ ++ sprintf(info->driver, KBUILD_MODNAME); ++ sprintf(info->version, "%lu", drvr_priv->pub.drv_version); ++ sprintf(info->fw_version, "%s", BCM4329_FW_NAME); ++ sprintf(info->bus_info, "%s", ++ dev_name(brcmf_bus_get_device(drvr_priv->pub.bus))); ++} ++ ++static struct ethtool_ops brcmf_ethtool_ops = { ++ .get_drvinfo = brcmf_ethtool_get_drvinfo ++}; ++ ++static int brcmf_ethtool(struct brcmf_info *drvr_priv, void __user *uaddr) ++{ ++ struct ethtool_drvinfo info; ++ char drvname[sizeof(info.driver)]; ++ u32 cmd; ++ struct ethtool_value edata; ++ u32 toe_cmpnt, csum_dir; ++ int ret; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* all ethtool calls start with a cmd word */ ++ if (copy_from_user(&cmd, uaddr, sizeof(u32))) ++ return -EFAULT; ++ ++ switch (cmd) { ++ case ETHTOOL_GDRVINFO: ++ /* Copy out any request driver name */ ++ if (copy_from_user(&info, uaddr, sizeof(info))) ++ return -EFAULT; ++ strncpy(drvname, info.driver, sizeof(info.driver)); ++ drvname[sizeof(info.driver) - 1] = '\0'; ++ ++ /* clear struct for return */ ++ memset(&info, 0, sizeof(info)); ++ info.cmd = cmd; ++ ++ /* if requested, identify ourselves */ ++ if (strcmp(drvname, "?dhd") == 0) { ++ sprintf(info.driver, "dhd"); ++ strcpy(info.version, BRCMF_VERSION_STR); ++ } ++ ++ /* otherwise, require dongle to be up */ ++ else if (!drvr_priv->pub.up) { ++ brcmf_dbg(ERROR, "dongle is not up\n"); ++ return -ENODEV; ++ } ++ ++ /* finally, report dongle driver type */ ++ else if (drvr_priv->pub.iswl) ++ sprintf(info.driver, "wl"); ++ else ++ sprintf(info.driver, "xx"); ++ ++ sprintf(info.version, "%lu", drvr_priv->pub.drv_version); ++ if (copy_to_user(uaddr, &info, sizeof(info))) ++ return -EFAULT; ++ brcmf_dbg(CTL, "given %*s, returning %s\n", ++ (int)sizeof(drvname), drvname, info.driver); ++ break; ++ ++ /* Get toe offload components from dongle */ ++ case ETHTOOL_GRXCSUM: ++ case ETHTOOL_GTXCSUM: ++ ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt); ++ if (ret < 0) ++ return ret; ++ ++ csum_dir = ++ (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL; ++ ++ edata.cmd = cmd; ++ edata.data = (toe_cmpnt & csum_dir) ? 1 : 0; ++ ++ if (copy_to_user(uaddr, &edata, sizeof(edata))) ++ return -EFAULT; ++ break; ++ ++ /* Set toe offload components in dongle */ ++ case ETHTOOL_SRXCSUM: ++ case ETHTOOL_STXCSUM: ++ if (copy_from_user(&edata, uaddr, sizeof(edata))) ++ return -EFAULT; ++ ++ /* Read the current settings, update and write back */ ++ ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt); ++ if (ret < 0) ++ return ret; ++ ++ csum_dir = ++ (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL; ++ ++ if (edata.data != 0) ++ toe_cmpnt |= csum_dir; ++ else ++ toe_cmpnt &= ~csum_dir; ++ ++ ret = brcmf_toe_set(drvr_priv, 0, toe_cmpnt); ++ if (ret < 0) ++ return ret; ++ ++ /* If setting TX checksum mode, tell Linux the new mode */ ++ if (cmd == ETHTOOL_STXCSUM) { ++ if (edata.data) ++ drvr_priv->iflist[0]->ndev->features |= ++ NETIF_F_IP_CSUM; ++ else ++ drvr_priv->iflist[0]->ndev->features &= ++ ~NETIF_F_IP_CSUM; ++ } ++ ++ break; ++ ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++ ++static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr, ++ int cmd) ++{ ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **) ++ netdev_priv(ndev); ++ int ifidx; ++ ++ ifidx = brcmf_net2idx(drvr_priv, ndev); ++ brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifidx, cmd); ++ ++ if (ifidx == BRCMF_BAD_IF) ++ return -1; ++ ++ if (cmd == SIOCETHTOOL) ++ return brcmf_ethtool(drvr_priv, ifr->ifr_data); ++ ++ return -EOPNOTSUPP; ++} ++ ++/* called only from within this driver. Sends a command to the dongle. */ ++s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len) ++{ ++ struct brcmf_dcmd dcmd; ++ s32 err = 0; ++ int buflen = 0; ++ bool is_set_key_cmd; ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **) ++ netdev_priv(ndev); ++ int ifidx; ++ ++ memset(&dcmd, 0, sizeof(dcmd)); ++ dcmd.cmd = cmd; ++ dcmd.buf = arg; ++ dcmd.len = len; ++ ++ ifidx = brcmf_net2idx(drvr_priv, ndev); ++ ++ if (dcmd.buf != NULL) ++ buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN); ++ ++ /* send to dongle (must be up, and wl) */ ++ if ((drvr_priv->pub.busstate != BRCMF_BUS_DATA)) { ++ brcmf_dbg(ERROR, "DONGLE_DOWN\n"); ++ err = -EIO; ++ goto done; ++ } ++ ++ if (!drvr_priv->pub.iswl) { ++ err = -EIO; ++ goto done; ++ } ++ ++ /* ++ * Intercept BRCMF_C_SET_KEY CMD - serialize M4 send and ++ * set key CMD to prevent M4 encryption. ++ */ ++ is_set_key_cmd = ((dcmd.cmd == BRCMF_C_SET_KEY) || ++ ((dcmd.cmd == BRCMF_C_SET_VAR) && ++ !(strncmp("wsec_key", dcmd.buf, 9))) || ++ ((dcmd.cmd == BRCMF_C_SET_VAR) && ++ !(strncmp("bsscfg:wsec_key", dcmd.buf, 15)))); ++ if (is_set_key_cmd) ++ brcmf_netdev_wait_pend8021x(ndev); ++ ++ err = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, buflen); ++ ++done: ++ if (err > 0) ++ err = 0; ++ ++ return err; ++} ++ ++static int brcmf_netdev_stop(struct net_device *ndev) ++{ ++ struct brcmf_pub *drvr = *(struct brcmf_pub **) netdev_priv(ndev); ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ brcmf_cfg80211_down(drvr->config); ++ if (drvr->up == 0) ++ return 0; ++ ++ /* Set state and stop OS transmissions */ ++ drvr->up = 0; ++ netif_stop_queue(ndev); ++ ++ return 0; ++} ++ ++static int brcmf_netdev_open(struct net_device *ndev) ++{ ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **) ++ netdev_priv(ndev); ++ u32 toe_ol; ++ int ifidx = brcmf_net2idx(drvr_priv, ndev); ++ s32 ret = 0; ++ ++ brcmf_dbg(TRACE, "ifidx %d\n", ifidx); ++ ++ if (ifidx == 0) { /* do it only for primary eth0 */ ++ ++ /* try to bring up bus */ ++ ret = brcmf_bus_start(&drvr_priv->pub); ++ if (ret != 0) { ++ brcmf_dbg(ERROR, "failed with code %d\n", ret); ++ return -1; ++ } ++ atomic_set(&drvr_priv->pend_8021x_cnt, 0); ++ ++ memcpy(ndev->dev_addr, drvr_priv->pub.mac, ETH_ALEN); ++ ++ /* Get current TOE mode from dongle */ ++ if (brcmf_toe_get(drvr_priv, ifidx, &toe_ol) >= 0 ++ && (toe_ol & TOE_TX_CSUM_OL) != 0) ++ drvr_priv->iflist[ifidx]->ndev->features |= ++ NETIF_F_IP_CSUM; ++ else ++ drvr_priv->iflist[ifidx]->ndev->features &= ++ ~NETIF_F_IP_CSUM; ++ } ++ /* Allow transmit calls */ ++ netif_start_queue(ndev); ++ drvr_priv->pub.up = 1; ++ if (brcmf_cfg80211_up(drvr_priv->pub.config)) { ++ brcmf_dbg(ERROR, "failed to bring up cfg80211\n"); ++ return -1; ++ } ++ ++ return ret; ++} ++ ++int ++brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, struct net_device *ndev, ++ char *name, u8 *mac_addr, u32 flags, u8 bssidx) ++{ ++ struct brcmf_if *ifp; ++ int ret = 0, err = 0; ++ ++ brcmf_dbg(TRACE, "idx %d, handle->%p\n", ifidx, ndev); ++ ++ ifp = drvr_priv->iflist[ifidx]; ++ if (!ifp) { ++ ifp = kmalloc(sizeof(struct brcmf_if), GFP_ATOMIC); ++ if (!ifp) ++ return -ENOMEM; ++ } ++ ++ memset(ifp, 0, sizeof(struct brcmf_if)); ++ ifp->info = drvr_priv; ++ drvr_priv->iflist[ifidx] = ifp; ++ if (mac_addr != NULL) ++ memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN); ++ ++ if (ndev == NULL) { ++ ifp->state = BRCMF_E_IF_ADD; ++ ifp->idx = ifidx; ++ /* ++ * Delete the existing interface before overwriting it ++ * in case we missed the BRCMF_E_IF_DEL event. ++ */ ++ if (ifp->ndev != NULL) { ++ brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n", ++ ifp->ndev->name); ++ netif_stop_queue(ifp->ndev); ++ unregister_netdev(ifp->ndev); ++ free_netdev(ifp->ndev); ++ } ++ ++ /* Allocate netdev, including space for private structure */ ++ ifp->ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d", ++ ether_setup); ++ if (!ifp->ndev) { ++ brcmf_dbg(ERROR, "OOM - alloc_netdev\n"); ++ ret = -ENOMEM; ++ } ++ ++ if (ret == 0) { ++ memcpy(netdev_priv(ifp->ndev), &drvr_priv, ++ sizeof(drvr_priv)); ++ err = brcmf_net_attach(&drvr_priv->pub, ifp->idx); ++ if (err != 0) { ++ brcmf_dbg(ERROR, "brcmf_net_attach failed, err %d\n", ++ err); ++ ret = -EOPNOTSUPP; ++ } else { ++ brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n", ++ current->pid, ifp->ndev->name); ++ ifp->state = 0; ++ } ++ } ++ ++ if (ret < 0) { ++ if (ifp->ndev) ++ free_netdev(ifp->ndev); ++ ++ drvr_priv->iflist[ifp->idx] = NULL; ++ kfree(ifp); ++ } ++ } else ++ ifp->ndev = ndev; ++ ++ return 0; ++} ++ ++void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx) ++{ ++ struct brcmf_if *ifp; ++ ++ brcmf_dbg(TRACE, "idx %d\n", ifidx); ++ ++ ifp = drvr_priv->iflist[ifidx]; ++ if (!ifp) { ++ brcmf_dbg(ERROR, "Null interface\n"); ++ return; ++ } ++ ++ ifp->state = BRCMF_E_IF_DEL; ++ ifp->idx = ifidx; ++ if (ifp->ndev != NULL) { ++ netif_stop_queue(ifp->ndev); ++ unregister_netdev(ifp->ndev); ++ free_netdev(ifp->ndev); ++ drvr_priv->iflist[ifidx] = NULL; ++ kfree(ifp); ++ } ++} ++ ++struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen) ++{ ++ struct brcmf_info *drvr_priv = NULL; ++ struct net_device *ndev; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Allocate netdev, including space for private structure */ ++ ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d", ether_setup); ++ if (!ndev) { ++ brcmf_dbg(ERROR, "OOM - alloc_netdev\n"); ++ goto fail; ++ } ++ ++ /* Allocate primary brcmf_info */ ++ drvr_priv = kzalloc(sizeof(struct brcmf_info), GFP_ATOMIC); ++ if (!drvr_priv) ++ goto fail; ++ ++ /* ++ * Save the brcmf_info into the priv ++ */ ++ memcpy(netdev_priv(ndev), &drvr_priv, sizeof(drvr_priv)); ++ ++ if (brcmf_add_if(drvr_priv, 0, ndev, ndev->name, NULL, 0, 0) == ++ BRCMF_BAD_IF) ++ goto fail; ++ ++ ndev->netdev_ops = NULL; ++ mutex_init(&drvr_priv->proto_block); ++ ++ /* Link to info module */ ++ drvr_priv->pub.info = drvr_priv; ++ ++ /* Link to bus module */ ++ drvr_priv->pub.bus = bus; ++ drvr_priv->pub.hdrlen = bus_hdrlen; ++ ++ /* Attach and link in the protocol */ ++ if (brcmf_proto_attach(&drvr_priv->pub) != 0) { ++ brcmf_dbg(ERROR, "brcmf_prot_attach failed\n"); ++ goto fail; ++ } ++ ++ /* Attach and link in the cfg80211 */ ++ drvr_priv->pub.config = ++ brcmf_cfg80211_attach(ndev, ++ brcmf_bus_get_device(bus), ++ &drvr_priv->pub); ++ if (drvr_priv->pub.config == NULL) { ++ brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n"); ++ goto fail; ++ } ++ ++ INIT_WORK(&drvr_priv->setmacaddr_work, _brcmf_set_mac_address); ++ INIT_WORK(&drvr_priv->multicast_work, _brcmf_set_multicast_list); ++ ++ /* ++ * Save the brcmf_info into the priv ++ */ ++ memcpy(netdev_priv(ndev), &drvr_priv, sizeof(drvr_priv)); ++ ++ return &drvr_priv->pub; ++ ++fail: ++ if (ndev) ++ free_netdev(ndev); ++ if (drvr_priv) ++ brcmf_detach(&drvr_priv->pub); ++ ++ return NULL; ++} ++ ++int brcmf_bus_start(struct brcmf_pub *drvr) ++{ ++ int ret = -1; ++ struct brcmf_info *drvr_priv = drvr->info; ++ /* Room for "event_msgs" + '\0' + bitvec */ ++ char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; ++ ++ brcmf_dbg(TRACE, "\n"); ++ ++ /* Bring up the bus */ ++ ret = brcmf_sdbrcm_bus_init(&drvr_priv->pub); ++ if (ret != 0) { ++ brcmf_dbg(ERROR, "brcmf_sdbrcm_bus_init failed %d\n", ret); ++ return ret; ++ } ++ ++ /* If bus is not ready, can't come up */ ++ if (drvr_priv->pub.busstate != BRCMF_BUS_DATA) { ++ brcmf_dbg(ERROR, "failed bus is not ready\n"); ++ return -ENODEV; ++ } ++ ++ brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN, ++ iovbuf, sizeof(iovbuf)); ++ brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, iovbuf, ++ sizeof(iovbuf)); ++ memcpy(drvr->eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN); ++ ++ setbit(drvr->eventmask, BRCMF_E_SET_SSID); ++ setbit(drvr->eventmask, BRCMF_E_PRUNE); ++ setbit(drvr->eventmask, BRCMF_E_AUTH); ++ setbit(drvr->eventmask, BRCMF_E_REASSOC); ++ setbit(drvr->eventmask, BRCMF_E_REASSOC_IND); ++ setbit(drvr->eventmask, BRCMF_E_DEAUTH_IND); ++ setbit(drvr->eventmask, BRCMF_E_DISASSOC_IND); ++ setbit(drvr->eventmask, BRCMF_E_DISASSOC); ++ setbit(drvr->eventmask, BRCMF_E_JOIN); ++ setbit(drvr->eventmask, BRCMF_E_ASSOC_IND); ++ setbit(drvr->eventmask, BRCMF_E_PSK_SUP); ++ setbit(drvr->eventmask, BRCMF_E_LINK); ++ setbit(drvr->eventmask, BRCMF_E_NDIS_LINK); ++ setbit(drvr->eventmask, BRCMF_E_MIC_ERROR); ++ setbit(drvr->eventmask, BRCMF_E_PMKID_CACHE); ++ setbit(drvr->eventmask, BRCMF_E_TXFAIL); ++ setbit(drvr->eventmask, BRCMF_E_JOIN_START); ++ setbit(drvr->eventmask, BRCMF_E_SCAN_COMPLETE); ++ ++/* enable dongle roaming event */ ++ ++ drvr->pktfilter_count = 1; ++ /* Setup filter to allow only unicast */ ++ drvr->pktfilter[0] = "100 0 0 0 0x01 0x00"; ++ ++ /* Bus is ready, do any protocol initialization */ ++ ret = brcmf_proto_init(&drvr_priv->pub); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static struct net_device_ops brcmf_netdev_ops_pri = { ++ .ndo_open = brcmf_netdev_open, ++ .ndo_stop = brcmf_netdev_stop, ++ .ndo_get_stats = brcmf_netdev_get_stats, ++ .ndo_do_ioctl = brcmf_netdev_ioctl_entry, ++ .ndo_start_xmit = brcmf_netdev_start_xmit, ++ .ndo_set_mac_address = brcmf_netdev_set_mac_address, ++ .ndo_set_rx_mode = brcmf_netdev_set_multicast_list ++}; ++ ++int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx) ++{ ++ struct brcmf_info *drvr_priv = drvr->info; ++ struct net_device *ndev; ++ u8 temp_addr[ETH_ALEN] = { ++ 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33}; ++ ++ brcmf_dbg(TRACE, "ifidx %d\n", ifidx); ++ ++ ndev = drvr_priv->iflist[ifidx]->ndev; ++ ndev->netdev_ops = &brcmf_netdev_ops_pri; ++ ++ /* ++ * We have to use the primary MAC for virtual interfaces ++ */ ++ if (ifidx != 0) { ++ /* for virtual interfaces use the primary MAC */ ++ memcpy(temp_addr, drvr_priv->pub.mac, ETH_ALEN); ++ ++ } ++ ++ if (ifidx == 1) { ++ brcmf_dbg(TRACE, "ACCESS POINT MAC:\n"); ++ /* ACCESSPOINT INTERFACE CASE */ ++ temp_addr[0] |= 0X02; /* set bit 2 , ++ - Locally Administered address */ ++ ++ } ++ ndev->hard_header_len = ETH_HLEN + drvr_priv->pub.hdrlen; ++ ndev->ethtool_ops = &brcmf_ethtool_ops; ++ ++ drvr_priv->pub.rxsz = ndev->mtu + ndev->hard_header_len + ++ drvr_priv->pub.hdrlen; ++ ++ memcpy(ndev->dev_addr, temp_addr, ETH_ALEN); ++ ++ if (register_netdev(ndev) != 0) { ++ brcmf_dbg(ERROR, "couldn't register the net device\n"); ++ goto fail; ++ } ++ ++ brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); ++ ++ return 0; ++ ++fail: ++ ndev->netdev_ops = NULL; ++ return -EBADE; ++} ++ ++static void brcmf_bus_detach(struct brcmf_pub *drvr) ++{ ++ struct brcmf_info *drvr_priv; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (drvr) { ++ drvr_priv = drvr->info; ++ if (drvr_priv) { ++ /* Stop the protocol module */ ++ brcmf_proto_stop(&drvr_priv->pub); ++ ++ /* Stop the bus module */ ++ brcmf_sdbrcm_bus_stop(drvr_priv->pub.bus); ++ } ++ } ++} ++ ++void brcmf_detach(struct brcmf_pub *drvr) ++{ ++ struct brcmf_info *drvr_priv; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (drvr) { ++ drvr_priv = drvr->info; ++ if (drvr_priv) { ++ struct brcmf_if *ifp; ++ int i; ++ ++ for (i = 1; i < BRCMF_MAX_IFS; i++) ++ if (drvr_priv->iflist[i]) ++ brcmf_del_if(drvr_priv, i); ++ ++ ifp = drvr_priv->iflist[0]; ++ if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) { ++ rtnl_lock(); ++ brcmf_netdev_stop(ifp->ndev); ++ rtnl_unlock(); ++ unregister_netdev(ifp->ndev); ++ } ++ ++ cancel_work_sync(&drvr_priv->setmacaddr_work); ++ cancel_work_sync(&drvr_priv->multicast_work); ++ ++ brcmf_bus_detach(drvr); ++ ++ if (drvr->prot) ++ brcmf_proto_detach(drvr); ++ ++ brcmf_cfg80211_detach(drvr->config); ++ ++ free_netdev(ifp->ndev); ++ kfree(ifp); ++ kfree(drvr_priv); ++ } ++ } ++} ++ ++static void __exit brcmf_module_cleanup(void) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ brcmf_bus_unregister(); ++} ++ ++static int __init brcmf_module_init(void) ++{ ++ int error; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ error = brcmf_bus_register(); ++ ++ if (error) { ++ brcmf_dbg(ERROR, "brcmf_bus_register failed\n"); ++ goto failed; ++ } ++ return 0; ++ ++failed: ++ return -EINVAL; ++} ++ ++module_init(brcmf_module_init); ++module_exit(brcmf_module_cleanup); ++ ++int brcmf_os_proto_block(struct brcmf_pub *drvr) ++{ ++ struct brcmf_info *drvr_priv = drvr->info; ++ ++ if (drvr_priv) { ++ mutex_lock(&drvr_priv->proto_block); ++ return 1; ++ } ++ return 0; ++} ++ ++int brcmf_os_proto_unblock(struct brcmf_pub *drvr) ++{ ++ struct brcmf_info *drvr_priv = drvr->info; ++ ++ if (drvr_priv) { ++ mutex_unlock(&drvr_priv->proto_block); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv) ++{ ++ return atomic_read(&drvr_priv->pend_8021x_cnt); ++} ++ ++#define MAX_WAIT_FOR_8021X_TX 10 ++ ++int brcmf_netdev_wait_pend8021x(struct net_device *ndev) ++{ ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(ndev); ++ int timeout = 10 * HZ / 1000; ++ int ntimes = MAX_WAIT_FOR_8021X_TX; ++ int pend = brcmf_get_pend_8021x_cnt(drvr_priv); ++ ++ while (ntimes && pend) { ++ if (pend) { ++ set_current_state(TASK_INTERRUPTIBLE); ++ schedule_timeout(timeout); ++ set_current_state(TASK_RUNNING); ++ ntimes--; ++ } ++ pend = brcmf_get_pend_8021x_cnt(drvr_priv); ++ } ++ return pend; ++} ++ ++#ifdef BCMDBG ++int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size) ++{ ++ int ret = 0; ++ struct file *fp; ++ mm_segment_t old_fs; ++ loff_t pos = 0; ++ ++ /* change to KERNEL_DS address limit */ ++ old_fs = get_fs(); ++ set_fs(KERNEL_DS); ++ ++ /* open file to write */ ++ fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640); ++ if (!fp) { ++ brcmf_dbg(ERROR, "open file error\n"); ++ ret = -1; ++ goto exit; ++ } ++ ++ /* Write buf to file */ ++ fp->f_op->write(fp, (char __user *)buf, size, &pos); ++ ++exit: ++ /* free buf before return */ ++ kfree(buf); ++ /* close file before return */ ++ if (fp) ++ filp_close(fp, current->files); ++ /* restore previous address limit */ ++ set_fs(old_fs); ++ ++ return ret; ++} ++#endif /* BCMDBG */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h.orig 2011-11-09 13:46:58.232800795 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h 2011-11-09 13:47:16.983566378 -0500 +@@ -0,0 +1,60 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCMF_PROTO_H_ ++#define _BRCMF_PROTO_H_ ++ ++/* ++ * Exported from the brcmf protocol module (brcmf_cdc) ++ */ ++ ++/* Linkage, sets prot link and updates hdrlen in pub */ ++extern int brcmf_proto_attach(struct brcmf_pub *drvr); ++ ++/* Unlink, frees allocated protocol memory (including brcmf_proto) */ ++extern void brcmf_proto_detach(struct brcmf_pub *drvr); ++ ++/* Initialize protocol: sync w/dongle state. ++ * Sets dongle media info (iswl, drv_version, mac address). ++ */ ++extern int brcmf_proto_init(struct brcmf_pub *drvr); ++ ++/* Stop protocol: sync w/dongle state. */ ++extern void brcmf_proto_stop(struct brcmf_pub *drvr); ++ ++/* Add any protocol-specific data header. ++ * Caller must reserve prot_hdrlen prepend space. ++ */ ++extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, ++ struct sk_buff *txp); ++ ++/* Remove any protocol-specific data header. */ ++extern int brcmf_proto_hdrpull(struct brcmf_pub *, int *ifidx, ++ struct sk_buff *rxp); ++ ++/* Use protocol to issue command to dongle */ ++extern int brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, ++ struct brcmf_dcmd *dcmd, int len); ++ ++/* Update local copy of dongle statistics */ ++extern void brcmf_proto_dstats(struct brcmf_pub *drvr); ++ ++extern int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr); ++ ++extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, ++ uint cmd, void *buf, uint len); ++ ++#endif /* _BRCMF_PROTO_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c.orig 2011-11-09 13:46:58.235800758 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c 2011-11-09 13:47:16.986566342 -0500 +@@ -0,0 +1,4591 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "sdio_host.h" ++ ++#define DCMD_RESP_TIMEOUT 2000 /* In milli second */ ++ ++#ifdef BCMDBG ++ ++#define BRCMF_TRAP_INFO_SIZE 80 ++ ++#define CBUF_LEN (128) ++ ++struct rte_log_le { ++ __le32 buf; /* Can't be pointer on (64-bit) hosts */ ++ __le32 buf_size; ++ __le32 idx; ++ char *_buf_compat; /* Redundant pointer for backward compat. */ ++}; ++ ++struct rte_console { ++ /* Virtual UART ++ * When there is no UART (e.g. Quickturn), ++ * the host should write a complete ++ * input line directly into cbuf and then write ++ * the length into vcons_in. ++ * This may also be used when there is a real UART ++ * (at risk of conflicting with ++ * the real UART). vcons_out is currently unused. ++ */ ++ uint vcons_in; ++ uint vcons_out; ++ ++ /* Output (logging) buffer ++ * Console output is written to a ring buffer log_buf at index log_idx. ++ * The host may read the output when it sees log_idx advance. ++ * Output will be lost if the output wraps around faster than the host ++ * polls. ++ */ ++ struct rte_log_le log_le; ++ ++ /* Console input line buffer ++ * Characters are read one at a time into cbuf ++ * until is received, then ++ * the buffer is processed as a command line. ++ * Also used for virtual UART. ++ */ ++ uint cbuf_idx; ++ char cbuf[CBUF_LEN]; ++}; ++ ++#endif /* BCMDBG */ ++#include ++ ++#include "dhd.h" ++#include "dhd_bus.h" ++#include "dhd_proto.h" ++#include "dhd_dbg.h" ++#include ++ ++#define TXQLEN 2048 /* bulk tx queue length */ ++#define TXHI (TXQLEN - 256) /* turn on flow control above TXHI */ ++#define TXLOW (TXHI - 256) /* turn off flow control below TXLOW */ ++#define PRIOMASK 7 ++ ++#define TXRETRIES 2 /* # of retries for tx frames */ ++ ++#define BRCMF_RXBOUND 50 /* Default for max rx frames in ++ one scheduling */ ++ ++#define BRCMF_TXBOUND 20 /* Default for max tx frames in ++ one scheduling */ ++ ++#define BRCMF_TXMINMAX 1 /* Max tx frames if rx still pending */ ++ ++#define MEMBLOCK 2048 /* Block size used for downloading ++ of dongle image */ ++#define MAX_DATA_BUF (32 * 1024) /* Must be large enough to hold ++ biggest possible glom */ ++ ++#define BRCMF_FIRSTREAD (1 << 6) ++ ++ ++/* SBSDIO_DEVICE_CTL */ ++ ++/* 1: device will assert busy signal when receiving CMD53 */ ++#define SBSDIO_DEVCTL_SETBUSY 0x01 ++/* 1: assertion of sdio interrupt is synchronous to the sdio clock */ ++#define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02 ++/* 1: mask all interrupts to host except the chipActive (rev 8) */ ++#define SBSDIO_DEVCTL_CA_INT_ONLY 0x04 ++/* 1: isolate internal sdio signals, put external pads in tri-state; requires ++ * sdio bus power cycle to clear (rev 9) */ ++#define SBSDIO_DEVCTL_PADS_ISO 0x08 ++/* Force SD->SB reset mapping (rev 11) */ ++#define SBSDIO_DEVCTL_SB_RST_CTL 0x30 ++/* Determined by CoreControl bit */ ++#define SBSDIO_DEVCTL_RST_CORECTL 0x00 ++/* Force backplane reset */ ++#define SBSDIO_DEVCTL_RST_BPRESET 0x10 ++/* Force no backplane reset */ ++#define SBSDIO_DEVCTL_RST_NOBPRESET 0x20 ++ ++/* SBSDIO_FUNC1_CHIPCLKCSR */ ++ ++/* Force ALP request to backplane */ ++#define SBSDIO_FORCE_ALP 0x01 ++/* Force HT request to backplane */ ++#define SBSDIO_FORCE_HT 0x02 ++/* Force ILP request to backplane */ ++#define SBSDIO_FORCE_ILP 0x04 ++/* Make ALP ready (power up xtal) */ ++#define SBSDIO_ALP_AVAIL_REQ 0x08 ++/* Make HT ready (power up PLL) */ ++#define SBSDIO_HT_AVAIL_REQ 0x10 ++/* Squelch clock requests from HW */ ++#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20 ++/* Status: ALP is ready */ ++#define SBSDIO_ALP_AVAIL 0x40 ++/* Status: HT is ready */ ++#define SBSDIO_HT_AVAIL 0x80 ++ ++#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL) ++#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS) ++#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS) ++#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval)) ++ ++#define SBSDIO_CLKAV(regval, alponly) \ ++ (SBSDIO_ALPAV(regval) && (alponly ? 1 : SBSDIO_HTAV(regval))) ++ ++/* direct(mapped) cis space */ ++ ++/* MAPPED common CIS address */ ++#define SBSDIO_CIS_BASE_COMMON 0x1000 ++/* maximum bytes in one CIS */ ++#define SBSDIO_CIS_SIZE_LIMIT 0x200 ++/* cis offset addr is < 17 bits */ ++#define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF ++ ++/* manfid tuple length, include tuple, link bytes */ ++#define SBSDIO_CIS_MANFID_TUPLE_LEN 6 ++ ++/* intstatus */ ++#define I_SMB_SW0 (1 << 0) /* To SB Mail S/W interrupt 0 */ ++#define I_SMB_SW1 (1 << 1) /* To SB Mail S/W interrupt 1 */ ++#define I_SMB_SW2 (1 << 2) /* To SB Mail S/W interrupt 2 */ ++#define I_SMB_SW3 (1 << 3) /* To SB Mail S/W interrupt 3 */ ++#define I_SMB_SW_MASK 0x0000000f /* To SB Mail S/W interrupts mask */ ++#define I_SMB_SW_SHIFT 0 /* To SB Mail S/W interrupts shift */ ++#define I_HMB_SW0 (1 << 4) /* To Host Mail S/W interrupt 0 */ ++#define I_HMB_SW1 (1 << 5) /* To Host Mail S/W interrupt 1 */ ++#define I_HMB_SW2 (1 << 6) /* To Host Mail S/W interrupt 2 */ ++#define I_HMB_SW3 (1 << 7) /* To Host Mail S/W interrupt 3 */ ++#define I_HMB_SW_MASK 0x000000f0 /* To Host Mail S/W interrupts mask */ ++#define I_HMB_SW_SHIFT 4 /* To Host Mail S/W interrupts shift */ ++#define I_WR_OOSYNC (1 << 8) /* Write Frame Out Of Sync */ ++#define I_RD_OOSYNC (1 << 9) /* Read Frame Out Of Sync */ ++#define I_PC (1 << 10) /* descriptor error */ ++#define I_PD (1 << 11) /* data error */ ++#define I_DE (1 << 12) /* Descriptor protocol Error */ ++#define I_RU (1 << 13) /* Receive descriptor Underflow */ ++#define I_RO (1 << 14) /* Receive fifo Overflow */ ++#define I_XU (1 << 15) /* Transmit fifo Underflow */ ++#define I_RI (1 << 16) /* Receive Interrupt */ ++#define I_BUSPWR (1 << 17) /* SDIO Bus Power Change (rev 9) */ ++#define I_XMTDATA_AVAIL (1 << 23) /* bits in fifo */ ++#define I_XI (1 << 24) /* Transmit Interrupt */ ++#define I_RF_TERM (1 << 25) /* Read Frame Terminate */ ++#define I_WF_TERM (1 << 26) /* Write Frame Terminate */ ++#define I_PCMCIA_XU (1 << 27) /* PCMCIA Transmit FIFO Underflow */ ++#define I_SBINT (1 << 28) /* sbintstatus Interrupt */ ++#define I_CHIPACTIVE (1 << 29) /* chip from doze to active state */ ++#define I_SRESET (1 << 30) /* CCCR RES interrupt */ ++#define I_IOE2 (1U << 31) /* CCCR IOE2 Bit Changed */ ++#define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU) ++#define I_DMA (I_RI | I_XI | I_ERRORS) ++ ++/* corecontrol */ ++#define CC_CISRDY (1 << 0) /* CIS Ready */ ++#define CC_BPRESEN (1 << 1) /* CCCR RES signal */ ++#define CC_F2RDY (1 << 2) /* set CCCR IOR2 bit */ ++#define CC_CLRPADSISO (1 << 3) /* clear SDIO pads isolation */ ++#define CC_XMTDATAAVAIL_MODE (1 << 4) ++#define CC_XMTDATAAVAIL_CTRL (1 << 5) ++ ++/* SDA_FRAMECTRL */ ++#define SFC_RF_TERM (1 << 0) /* Read Frame Terminate */ ++#define SFC_WF_TERM (1 << 1) /* Write Frame Terminate */ ++#define SFC_CRC4WOOS (1 << 2) /* CRC error for write out of sync */ ++#define SFC_ABORTALL (1 << 3) /* Abort all in-progress frames */ ++ ++/* HW frame tag */ ++#define SDPCM_FRAMETAG_LEN 4 /* 2 bytes len, 2 bytes check val */ ++ ++/* Total length of frame header for dongle protocol */ ++#define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN) ++#define SDPCM_RESERVE (SDPCM_HDRLEN + BRCMF_SDALIGN) ++ ++/* ++ * Software allocation of To SB Mailbox resources ++ */ ++ ++/* tosbmailbox bits corresponding to intstatus bits */ ++#define SMB_NAK (1 << 0) /* Frame NAK */ ++#define SMB_INT_ACK (1 << 1) /* Host Interrupt ACK */ ++#define SMB_USE_OOB (1 << 2) /* Use OOB Wakeup */ ++#define SMB_DEV_INT (1 << 3) /* Miscellaneous Interrupt */ ++ ++/* tosbmailboxdata */ ++#define SMB_DATA_VERSION_SHIFT 16 /* host protocol version */ ++ ++/* ++ * Software allocation of To Host Mailbox resources ++ */ ++ ++/* intstatus bits */ ++#define I_HMB_FC_STATE I_HMB_SW0 /* Flow Control State */ ++#define I_HMB_FC_CHANGE I_HMB_SW1 /* Flow Control State Changed */ ++#define I_HMB_FRAME_IND I_HMB_SW2 /* Frame Indication */ ++#define I_HMB_HOST_INT I_HMB_SW3 /* Miscellaneous Interrupt */ ++ ++/* tohostmailboxdata */ ++#define HMB_DATA_NAKHANDLED 1 /* retransmit NAK'd frame */ ++#define HMB_DATA_DEVREADY 2 /* talk to host after enable */ ++#define HMB_DATA_FC 4 /* per prio flowcontrol update flag */ ++#define HMB_DATA_FWREADY 8 /* fw ready for protocol activity */ ++ ++#define HMB_DATA_FCDATA_MASK 0xff000000 ++#define HMB_DATA_FCDATA_SHIFT 24 ++ ++#define HMB_DATA_VERSION_MASK 0x00ff0000 ++#define HMB_DATA_VERSION_SHIFT 16 ++ ++/* ++ * Software-defined protocol header ++ */ ++ ++/* Current protocol version */ ++#define SDPCM_PROT_VERSION 4 ++ ++/* SW frame header */ ++#define SDPCM_PACKET_SEQUENCE(p) (((u8 *)p)[0] & 0xff) ++ ++#define SDPCM_CHANNEL_MASK 0x00000f00 ++#define SDPCM_CHANNEL_SHIFT 8 ++#define SDPCM_PACKET_CHANNEL(p) (((u8 *)p)[1] & 0x0f) ++ ++#define SDPCM_NEXTLEN_OFFSET 2 ++ ++/* Data Offset from SOF (HW Tag, SW Tag, Pad) */ ++#define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */ ++#define SDPCM_DOFFSET_VALUE(p) (((u8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff) ++#define SDPCM_DOFFSET_MASK 0xff000000 ++#define SDPCM_DOFFSET_SHIFT 24 ++#define SDPCM_FCMASK_OFFSET 4 /* Flow control */ ++#define SDPCM_FCMASK_VALUE(p) (((u8 *)p)[SDPCM_FCMASK_OFFSET] & 0xff) ++#define SDPCM_WINDOW_OFFSET 5 /* Credit based fc */ ++#define SDPCM_WINDOW_VALUE(p) (((u8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff) ++ ++#define SDPCM_SWHEADER_LEN 8 /* SW header is 64 bits */ ++ ++/* logical channel numbers */ ++#define SDPCM_CONTROL_CHANNEL 0 /* Control channel Id */ ++#define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication Channel Id */ ++#define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv Channel Id */ ++#define SDPCM_GLOM_CHANNEL 3 /* For coalesced packets */ ++#define SDPCM_TEST_CHANNEL 15 /* Reserved for test/debug packets */ ++ ++#define SDPCM_SEQUENCE_WRAP 256 /* wrap-around val for 8bit frame seq */ ++ ++#define SDPCM_GLOMDESC(p) (((u8 *)p)[1] & 0x80) ++ ++/* ++ * Shared structure between dongle and the host. ++ * The structure contains pointers to trap or assert information. ++ */ ++#define SDPCM_SHARED_VERSION 0x0002 ++#define SDPCM_SHARED_VERSION_MASK 0x00FF ++#define SDPCM_SHARED_ASSERT_BUILT 0x0100 ++#define SDPCM_SHARED_ASSERT 0x0200 ++#define SDPCM_SHARED_TRAP 0x0400 ++ ++/* Space for header read, limit for data packets */ ++#define MAX_HDR_READ (1 << 6) ++#define MAX_RX_DATASZ 2048 ++ ++/* Maximum milliseconds to wait for F2 to come up */ ++#define BRCMF_WAIT_F2RDY 3000 ++ ++/* Bump up limit on waiting for HT to account for first startup; ++ * if the image is doing a CRC calculation before programming the PMU ++ * for HT availability, it could take a couple hundred ms more, so ++ * max out at a 1 second (1000000us). ++ */ ++#undef PMU_MAX_TRANSITION_DLY ++#define PMU_MAX_TRANSITION_DLY 1000000 ++ ++/* Value for ChipClockCSR during initial setup */ ++#define BRCMF_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | \ ++ SBSDIO_ALP_AVAIL_REQ) ++ ++/* Flags for SDH calls */ ++#define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED) ++ ++/* sbimstate */ ++#define SBIM_IBE 0x20000 /* inbanderror */ ++#define SBIM_TO 0x40000 /* timeout */ ++#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */ ++#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */ ++ ++/* sbtmstatelow */ ++ ++/* reset */ ++#define SBTML_RESET 0x0001 ++/* reject field */ ++#define SBTML_REJ_MASK 0x0006 ++/* reject */ ++#define SBTML_REJ 0x0002 ++/* temporary reject, for error recovery */ ++#define SBTML_TMPREJ 0x0004 ++ ++/* Shift to locate the SI control flags in sbtml */ ++#define SBTML_SICF_SHIFT 16 ++ ++/* sbtmstatehigh */ ++#define SBTMH_SERR 0x0001 /* serror */ ++#define SBTMH_INT 0x0002 /* interrupt */ ++#define SBTMH_BUSY 0x0004 /* busy */ ++#define SBTMH_TO 0x0020 /* timeout (sonics >= 2.3) */ ++ ++/* Shift to locate the SI status flags in sbtmh */ ++#define SBTMH_SISF_SHIFT 16 ++ ++/* sbidlow */ ++#define SBIDL_INIT 0x80 /* initiator */ ++ ++/* sbidhigh */ ++#define SBIDH_RC_MASK 0x000f /* revision code */ ++#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */ ++#define SBIDH_RCE_SHIFT 8 ++#define SBCOREREV(sbidh) \ ++ ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | \ ++ ((sbidh) & SBIDH_RC_MASK)) ++#define SBIDH_CC_MASK 0x8ff0 /* core code */ ++#define SBIDH_CC_SHIFT 4 ++#define SBIDH_VC_MASK 0xffff0000 /* vendor code */ ++#define SBIDH_VC_SHIFT 16 ++ ++/* ++ * Conversion of 802.1D priority to precedence level ++ */ ++static uint prio2prec(u32 prio) ++{ ++ return (prio == PRIO_8021D_NONE || prio == PRIO_8021D_BE) ? ++ (prio^2) : prio; ++} ++ ++/* ++ * Core reg address translation. ++ * Both macro's returns a 32 bits byte address on the backplane bus. ++ */ ++#define CORE_CC_REG(base, field) \ ++ (base + offsetof(struct chipcregs, field)) ++#define CORE_BUS_REG(base, field) \ ++ (base + offsetof(struct sdpcmd_regs, field)) ++#define CORE_SB(base, field) \ ++ (base + SBCONFIGOFF + offsetof(struct sbconfig, field)) ++ ++/* core registers */ ++struct sdpcmd_regs { ++ u32 corecontrol; /* 0x00, rev8 */ ++ u32 corestatus; /* rev8 */ ++ u32 PAD[1]; ++ u32 biststatus; /* rev8 */ ++ ++ /* PCMCIA access */ ++ u16 pcmciamesportaladdr; /* 0x010, rev8 */ ++ u16 PAD[1]; ++ u16 pcmciamesportalmask; /* rev8 */ ++ u16 PAD[1]; ++ u16 pcmciawrframebc; /* rev8 */ ++ u16 PAD[1]; ++ u16 pcmciaunderflowtimer; /* rev8 */ ++ u16 PAD[1]; ++ ++ /* interrupt */ ++ u32 intstatus; /* 0x020, rev8 */ ++ u32 hostintmask; /* rev8 */ ++ u32 intmask; /* rev8 */ ++ u32 sbintstatus; /* rev8 */ ++ u32 sbintmask; /* rev8 */ ++ u32 funcintmask; /* rev4 */ ++ u32 PAD[2]; ++ u32 tosbmailbox; /* 0x040, rev8 */ ++ u32 tohostmailbox; /* rev8 */ ++ u32 tosbmailboxdata; /* rev8 */ ++ u32 tohostmailboxdata; /* rev8 */ ++ ++ /* synchronized access to registers in SDIO clock domain */ ++ u32 sdioaccess; /* 0x050, rev8 */ ++ u32 PAD[3]; ++ ++ /* PCMCIA frame control */ ++ u8 pcmciaframectrl; /* 0x060, rev8 */ ++ u8 PAD[3]; ++ u8 pcmciawatermark; /* rev8 */ ++ u8 PAD[155]; ++ ++ /* interrupt batching control */ ++ u32 intrcvlazy; /* 0x100, rev8 */ ++ u32 PAD[3]; ++ ++ /* counters */ ++ u32 cmd52rd; /* 0x110, rev8 */ ++ u32 cmd52wr; /* rev8 */ ++ u32 cmd53rd; /* rev8 */ ++ u32 cmd53wr; /* rev8 */ ++ u32 abort; /* rev8 */ ++ u32 datacrcerror; /* rev8 */ ++ u32 rdoutofsync; /* rev8 */ ++ u32 wroutofsync; /* rev8 */ ++ u32 writebusy; /* rev8 */ ++ u32 readwait; /* rev8 */ ++ u32 readterm; /* rev8 */ ++ u32 writeterm; /* rev8 */ ++ u32 PAD[40]; ++ u32 clockctlstatus; /* rev8 */ ++ u32 PAD[7]; ++ ++ u32 PAD[128]; /* DMA engines */ ++ ++ /* SDIO/PCMCIA CIS region */ ++ char cis[512]; /* 0x400-0x5ff, rev6 */ ++ ++ /* PCMCIA function control registers */ ++ char pcmciafcr[256]; /* 0x600-6ff, rev6 */ ++ u16 PAD[55]; ++ ++ /* PCMCIA backplane access */ ++ u16 backplanecsr; /* 0x76E, rev6 */ ++ u16 backplaneaddr0; /* rev6 */ ++ u16 backplaneaddr1; /* rev6 */ ++ u16 backplaneaddr2; /* rev6 */ ++ u16 backplaneaddr3; /* rev6 */ ++ u16 backplanedata0; /* rev6 */ ++ u16 backplanedata1; /* rev6 */ ++ u16 backplanedata2; /* rev6 */ ++ u16 backplanedata3; /* rev6 */ ++ u16 PAD[31]; ++ ++ /* sprom "size" & "blank" info */ ++ u16 spromstatus; /* 0x7BE, rev2 */ ++ u32 PAD[464]; ++ ++ u16 PAD[0x80]; ++}; ++ ++#ifdef BCMDBG ++/* Device console log buffer state */ ++struct brcmf_console { ++ uint count; /* Poll interval msec counter */ ++ uint log_addr; /* Log struct address (fixed) */ ++ struct rte_log_le log_le; /* Log struct (host copy) */ ++ uint bufsize; /* Size of log buffer */ ++ u8 *buf; /* Log buffer (host copy) */ ++ uint last; /* Last buffer read index */ ++}; ++#endif /* BCMDBG */ ++ ++struct sdpcm_shared { ++ u32 flags; ++ u32 trap_addr; ++ u32 assert_exp_addr; ++ u32 assert_file_addr; ++ u32 assert_line; ++ u32 console_addr; /* Address of struct rte_console */ ++ u32 msgtrace_addr; ++ u8 tag[32]; ++}; ++ ++struct sdpcm_shared_le { ++ __le32 flags; ++ __le32 trap_addr; ++ __le32 assert_exp_addr; ++ __le32 assert_file_addr; ++ __le32 assert_line; ++ __le32 console_addr; /* Address of struct rte_console */ ++ __le32 msgtrace_addr; ++ u8 tag[32]; ++}; ++ ++ ++/* misc chip info needed by some of the routines */ ++struct chip_info { ++ u32 chip; ++ u32 chiprev; ++ u32 cccorebase; ++ u32 ccrev; ++ u32 cccaps; ++ u32 buscorebase; /* 32 bits backplane bus address */ ++ u32 buscorerev; ++ u32 buscoretype; ++ u32 ramcorebase; ++ u32 armcorebase; ++ u32 pmurev; ++ u32 ramsize; ++}; ++ ++/* Private data for SDIO bus interaction */ ++struct brcmf_bus { ++ struct brcmf_pub *drvr; ++ ++ struct brcmf_sdio_dev *sdiodev; /* sdio device handler */ ++ struct chip_info *ci; /* Chip info struct */ ++ char *vars; /* Variables (from CIS and/or other) */ ++ uint varsz; /* Size of variables buffer */ ++ ++ u32 ramsize; /* Size of RAM in SOCRAM (bytes) */ ++ ++ u32 hostintmask; /* Copy of Host Interrupt Mask */ ++ u32 intstatus; /* Intstatus bits (events) pending */ ++ bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */ ++ bool fcstate; /* State of dongle flow-control */ ++ ++ uint blocksize; /* Block size of SDIO transfers */ ++ uint roundup; /* Max roundup limit */ ++ ++ struct pktq txq; /* Queue length used for flow-control */ ++ u8 flowcontrol; /* per prio flow control bitmask */ ++ u8 tx_seq; /* Transmit sequence number (next) */ ++ u8 tx_max; /* Maximum transmit sequence allowed */ ++ ++ u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN]; ++ u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ ++ u16 nextlen; /* Next Read Len from last header */ ++ u8 rx_seq; /* Receive sequence number (expected) */ ++ bool rxskip; /* Skip receive (awaiting NAK ACK) */ ++ ++ uint rxbound; /* Rx frames to read before resched */ ++ uint txbound; /* Tx frames to send before resched */ ++ uint txminmax; ++ ++ struct sk_buff *glomd; /* Packet containing glomming descriptor */ ++ struct sk_buff *glom; /* Packet chain for glommed superframe */ ++ uint glomerr; /* Glom packet read errors */ ++ ++ u8 *rxbuf; /* Buffer for receiving control packets */ ++ uint rxblen; /* Allocated length of rxbuf */ ++ u8 *rxctl; /* Aligned pointer into rxbuf */ ++ u8 *databuf; /* Buffer for receiving big glom packet */ ++ u8 *dataptr; /* Aligned pointer into databuf */ ++ uint rxlen; /* Length of valid data in buffer */ ++ ++ u8 sdpcm_ver; /* Bus protocol reported by dongle */ ++ ++ bool intr; /* Use interrupts */ ++ bool poll; /* Use polling */ ++ bool ipend; /* Device interrupt is pending */ ++ uint intrcount; /* Count of device interrupt callbacks */ ++ uint lastintrs; /* Count as of last watchdog timer */ ++ uint spurious; /* Count of spurious interrupts */ ++ uint pollrate; /* Ticks between device polls */ ++ uint polltick; /* Tick counter */ ++ uint pollcnt; /* Count of active polls */ ++ ++#ifdef BCMDBG ++ uint console_interval; ++ struct brcmf_console console; /* Console output polling support */ ++ uint console_addr; /* Console address from shared struct */ ++#endif /* BCMDBG */ ++ ++ uint regfails; /* Count of R_REG failures */ ++ ++ uint clkstate; /* State of sd and backplane clock(s) */ ++ bool activity; /* Activity flag for clock down */ ++ s32 idletime; /* Control for activity timeout */ ++ s32 idlecount; /* Activity timeout counter */ ++ s32 idleclock; /* How to set bus driver when idle */ ++ s32 sd_rxchain; ++ bool use_rxchain; /* If brcmf should use PKT chains */ ++ bool sleeping; /* Is SDIO bus sleeping? */ ++ bool rxflow_mode; /* Rx flow control mode */ ++ bool rxflow; /* Is rx flow control on */ ++ bool alp_only; /* Don't use HT clock (ALP only) */ ++/* Field to decide if rx of control frames happen in rxbuf or lb-pool */ ++ bool usebufpool; ++ ++ /* Some additional counters */ ++ uint tx_sderrs; /* Count of tx attempts with sd errors */ ++ uint fcqueued; /* Tx packets that got queued */ ++ uint rxrtx; /* Count of rtx requests (NAK to dongle) */ ++ uint rx_toolong; /* Receive frames too long to receive */ ++ uint rxc_errors; /* SDIO errors when reading control frames */ ++ uint rx_hdrfail; /* SDIO errors on header reads */ ++ uint rx_badhdr; /* Bad received headers (roosync?) */ ++ uint rx_badseq; /* Mismatched rx sequence number */ ++ uint fc_rcvd; /* Number of flow-control events received */ ++ uint fc_xoff; /* Number which turned on flow-control */ ++ uint fc_xon; /* Number which turned off flow-control */ ++ uint rxglomfail; /* Failed deglom attempts */ ++ uint rxglomframes; /* Number of glom frames (superframes) */ ++ uint rxglompkts; /* Number of packets from glom frames */ ++ uint f2rxhdrs; /* Number of header reads */ ++ uint f2rxdata; /* Number of frame data reads */ ++ uint f2txdata; /* Number of f2 frame writes */ ++ uint f1regdata; /* Number of f1 register accesses */ ++ ++ u8 *ctrl_frame_buf; ++ u32 ctrl_frame_len; ++ bool ctrl_frame_stat; ++ ++ spinlock_t txqlock; ++ wait_queue_head_t ctrl_wait; ++ wait_queue_head_t dcmd_resp_wait; ++ ++ struct timer_list timer; ++ struct completion watchdog_wait; ++ struct task_struct *watchdog_tsk; ++ bool wd_timer_valid; ++ uint save_ms; ++ ++ struct task_struct *dpc_tsk; ++ struct completion dpc_wait; ++ ++ struct semaphore sdsem; ++ ++ const char *fw_name; ++ const struct firmware *firmware; ++ const char *nv_name; ++ u32 fw_ptr; ++}; ++ ++struct sbconfig { ++ u32 PAD[2]; ++ u32 sbipsflag; /* initiator port ocp slave flag */ ++ u32 PAD[3]; ++ u32 sbtpsflag; /* target port ocp slave flag */ ++ u32 PAD[11]; ++ u32 sbtmerrloga; /* (sonics >= 2.3) */ ++ u32 PAD; ++ u32 sbtmerrlog; /* (sonics >= 2.3) */ ++ u32 PAD[3]; ++ u32 sbadmatch3; /* address match3 */ ++ u32 PAD; ++ u32 sbadmatch2; /* address match2 */ ++ u32 PAD; ++ u32 sbadmatch1; /* address match1 */ ++ u32 PAD[7]; ++ u32 sbimstate; /* initiator agent state */ ++ u32 sbintvec; /* interrupt mask */ ++ u32 sbtmstatelow; /* target state */ ++ u32 sbtmstatehigh; /* target state */ ++ u32 sbbwa0; /* bandwidth allocation table0 */ ++ u32 PAD; ++ u32 sbimconfiglow; /* initiator configuration */ ++ u32 sbimconfighigh; /* initiator configuration */ ++ u32 sbadmatch0; /* address match0 */ ++ u32 PAD; ++ u32 sbtmconfiglow; /* target configuration */ ++ u32 sbtmconfighigh; /* target configuration */ ++ u32 sbbconfig; /* broadcast configuration */ ++ u32 PAD; ++ u32 sbbstate; /* broadcast state */ ++ u32 PAD[3]; ++ u32 sbactcnfg; /* activate configuration */ ++ u32 PAD[3]; ++ u32 sbflagst; /* current sbflags */ ++ u32 PAD[3]; ++ u32 sbidlow; /* identification */ ++ u32 sbidhigh; /* identification */ ++}; ++ ++/* clkstate */ ++#define CLK_NONE 0 ++#define CLK_SDONLY 1 ++#define CLK_PENDING 2 /* Not used yet */ ++#define CLK_AVAIL 3 ++ ++#ifdef BCMDBG ++static int qcount[NUMPRIO]; ++static int tx_packets[NUMPRIO]; ++#endif /* BCMDBG */ ++ ++#define SDIO_DRIVE_STRENGTH 6 /* in milliamps */ ++ ++#define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL) ++ ++/* Retry count for register access failures */ ++static const uint retry_limit = 2; ++ ++/* Limit on rounding up frames */ ++static const uint max_roundup = 512; ++ ++#define ALIGNMENT 4 ++ ++static void pkt_align(struct sk_buff *p, int len, int align) ++{ ++ uint datalign; ++ datalign = (unsigned long)(p->data); ++ datalign = roundup(datalign, (align)) - datalign; ++ if (datalign) ++ skb_pull(p, datalign); ++ __skb_trim(p, len); ++} ++ ++/* To check if there's window offered */ ++static bool data_ok(struct brcmf_bus *bus) ++{ ++ return (u8)(bus->tx_max - bus->tx_seq) != 0 && ++ ((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0; ++} ++ ++/* ++ * Reads a register in the SDIO hardware block. This block occupies a series of ++ * adresses on the 32 bit backplane bus. ++ */ ++static void ++r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar) ++{ ++ *retryvar = 0; ++ do { ++ *regvar = brcmf_sdcard_reg_read(bus->sdiodev, ++ bus->ci->buscorebase + reg_offset, sizeof(u32)); ++ } while (brcmf_sdcard_regfail(bus->sdiodev) && ++ (++(*retryvar) <= retry_limit)); ++ if (*retryvar) { ++ bus->regfails += (*retryvar-1); ++ if (*retryvar > retry_limit) { ++ brcmf_dbg(ERROR, "FAILED READ %Xh\n", reg_offset); ++ *regvar = 0; ++ } ++ } ++} ++ ++static void ++w_sdreg32(struct brcmf_bus *bus, u32 regval, u32 reg_offset, u32 *retryvar) ++{ ++ *retryvar = 0; ++ do { ++ brcmf_sdcard_reg_write(bus->sdiodev, ++ bus->ci->buscorebase + reg_offset, ++ sizeof(u32), regval); ++ } while (brcmf_sdcard_regfail(bus->sdiodev) && ++ (++(*retryvar) <= retry_limit)); ++ if (*retryvar) { ++ bus->regfails += (*retryvar-1); ++ if (*retryvar > retry_limit) ++ brcmf_dbg(ERROR, "FAILED REGISTER WRITE %Xh\n", ++ reg_offset); ++ } ++} ++ ++#define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND) ++ ++#define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) ++ ++/* Packet free applicable unconditionally for sdio and sdspi. ++ * Conditional if bufpool was present for gspi bus. ++ */ ++static void brcmf_sdbrcm_pktfree2(struct brcmf_bus *bus, struct sk_buff *pkt) ++{ ++ if (bus->usebufpool) ++ brcmu_pkt_buf_free_skb(pkt); ++} ++ ++/* Turn backplane clock on or off */ ++static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok) ++{ ++ int err; ++ u8 clkctl, clkreq, devctl; ++ unsigned long timeout; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ clkctl = 0; ++ ++ if (on) { ++ /* Request HT Avail */ ++ clkreq = ++ bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; ++ ++ if ((bus->ci->chip == BCM4329_CHIP_ID) ++ && (bus->ci->chiprev == 0)) ++ clkreq |= SBSDIO_FORCE_ALP; ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); ++ if (err) { ++ brcmf_dbg(ERROR, "HT Avail request error: %d\n", err); ++ return -EBADE; ++ } ++ ++ if (pendok && ((bus->ci->buscoretype == PCMCIA_CORE_ID) ++ && (bus->ci->buscorerev == 9))) { ++ u32 dummy, retries; ++ r_sdreg32(bus, &dummy, ++ offsetof(struct sdpcmd_regs, clockctlstatus), ++ &retries); ++ } ++ ++ /* Check current status */ ++ clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ if (err) { ++ brcmf_dbg(ERROR, "HT Avail read error: %d\n", err); ++ return -EBADE; ++ } ++ ++ /* Go to pending and await interrupt if appropriate */ ++ if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { ++ /* Allow only clock-available interrupt */ ++ devctl = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, &err); ++ if (err) { ++ brcmf_dbg(ERROR, "Devctl error setting CA: %d\n", ++ err); ++ return -EBADE; ++ } ++ ++ devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, devctl, &err); ++ brcmf_dbg(INFO, "CLKCTL: set PENDING\n"); ++ bus->clkstate = CLK_PENDING; ++ ++ return 0; ++ } else if (bus->clkstate == CLK_PENDING) { ++ /* Cancel CA-only interrupt filter */ ++ devctl = ++ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, &err); ++ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, devctl, &err); ++ } ++ ++ /* Otherwise, wait here (polling) for HT Avail */ ++ timeout = jiffies + ++ msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000); ++ while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { ++ clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, ++ &err); ++ if (time_after(jiffies, timeout)) ++ break; ++ else ++ usleep_range(5000, 10000); ++ } ++ if (err) { ++ brcmf_dbg(ERROR, "HT Avail request error: %d\n", err); ++ return -EBADE; ++ } ++ if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { ++ brcmf_dbg(ERROR, "HT Avail timeout (%d): clkctl 0x%02x\n", ++ PMU_MAX_TRANSITION_DLY, clkctl); ++ return -EBADE; ++ } ++ ++ /* Mark clock available */ ++ bus->clkstate = CLK_AVAIL; ++ brcmf_dbg(INFO, "CLKCTL: turned ON\n"); ++ ++#if defined(BCMDBG) ++ if (bus->alp_only != true) { ++ if (SBSDIO_ALPONLY(clkctl)) ++ brcmf_dbg(ERROR, "HT Clock should be on\n"); ++ } ++#endif /* defined (BCMDBG) */ ++ ++ bus->activity = true; ++ } else { ++ clkreq = 0; ++ ++ if (bus->clkstate == CLK_PENDING) { ++ /* Cancel CA-only interrupt filter */ ++ devctl = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, &err); ++ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, devctl, &err); ++ } ++ ++ bus->clkstate = CLK_SDONLY; ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); ++ brcmf_dbg(INFO, "CLKCTL: turned OFF\n"); ++ if (err) { ++ brcmf_dbg(ERROR, "Failed access turning clock off: %d\n", ++ err); ++ return -EBADE; ++ } ++ } ++ return 0; ++} ++ ++/* Change idle/active SD state */ ++static int brcmf_sdbrcm_sdclk(struct brcmf_bus *bus, bool on) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (on) ++ bus->clkstate = CLK_SDONLY; ++ else ++ bus->clkstate = CLK_NONE; ++ ++ return 0; ++} ++ ++/* Transition SD and backplane clock readiness */ ++static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok) ++{ ++#ifdef BCMDBG ++ uint oldstate = bus->clkstate; ++#endif /* BCMDBG */ ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Early exit if we're already there */ ++ if (bus->clkstate == target) { ++ if (target == CLK_AVAIL) { ++ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); ++ bus->activity = true; ++ } ++ return 0; ++ } ++ ++ switch (target) { ++ case CLK_AVAIL: ++ /* Make sure SD clock is available */ ++ if (bus->clkstate == CLK_NONE) ++ brcmf_sdbrcm_sdclk(bus, true); ++ /* Now request HT Avail on the backplane */ ++ brcmf_sdbrcm_htclk(bus, true, pendok); ++ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); ++ bus->activity = true; ++ break; ++ ++ case CLK_SDONLY: ++ /* Remove HT request, or bring up SD clock */ ++ if (bus->clkstate == CLK_NONE) ++ brcmf_sdbrcm_sdclk(bus, true); ++ else if (bus->clkstate == CLK_AVAIL) ++ brcmf_sdbrcm_htclk(bus, false, false); ++ else ++ brcmf_dbg(ERROR, "request for %d -> %d\n", ++ bus->clkstate, target); ++ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); ++ break; ++ ++ case CLK_NONE: ++ /* Make sure to remove HT request */ ++ if (bus->clkstate == CLK_AVAIL) ++ brcmf_sdbrcm_htclk(bus, false, false); ++ /* Now remove the SD clock */ ++ brcmf_sdbrcm_sdclk(bus, false); ++ brcmf_sdbrcm_wd_timer(bus, 0); ++ break; ++ } ++#ifdef BCMDBG ++ brcmf_dbg(INFO, "%d -> %d\n", oldstate, bus->clkstate); ++#endif /* BCMDBG */ ++ ++ return 0; ++} ++ ++static int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep) ++{ ++ uint retries = 0; ++ ++ brcmf_dbg(INFO, "request %s (currently %s)\n", ++ sleep ? "SLEEP" : "WAKE", ++ bus->sleeping ? "SLEEP" : "WAKE"); ++ ++ /* Done if we're already in the requested state */ ++ if (sleep == bus->sleeping) ++ return 0; ++ ++ /* Going to sleep: set the alarm and turn off the lights... */ ++ if (sleep) { ++ /* Don't sleep if something is pending */ ++ if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq)) ++ return -EBUSY; ++ ++ /* Make sure the controller has the bus up */ ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); ++ ++ /* Tell device to start using OOB wakeup */ ++ w_sdreg32(bus, SMB_USE_OOB, ++ offsetof(struct sdpcmd_regs, tosbmailbox), &retries); ++ if (retries > retry_limit) ++ brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"); ++ ++ /* Turn off our contribution to the HT clock request */ ++ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, ++ SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); ++ ++ /* Isolate the bus */ ++ if (bus->ci->chip != BCM4329_CHIP_ID) { ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, ++ SBSDIO_DEVCTL_PADS_ISO, NULL); ++ } ++ ++ /* Change state */ ++ bus->sleeping = true; ++ ++ } else { ++ /* Waking up: bus power up is ok, set local state */ ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); ++ ++ /* Force pad isolation off if possible ++ (in case power never toggled) */ ++ if ((bus->ci->buscoretype == PCMCIA_CORE_ID) ++ && (bus->ci->buscorerev >= 10)) ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, 0, NULL); ++ ++ /* Make sure the controller has the bus up */ ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); ++ ++ /* Send misc interrupt to indicate OOB not needed */ ++ w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, tosbmailboxdata), ++ &retries); ++ if (retries <= retry_limit) ++ w_sdreg32(bus, SMB_DEV_INT, ++ offsetof(struct sdpcmd_regs, tosbmailbox), ++ &retries); ++ ++ if (retries > retry_limit) ++ brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"); ++ ++ /* Make sure we have SD bus access */ ++ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); ++ ++ /* Change state */ ++ bus->sleeping = false; ++ } ++ ++ return 0; ++} ++ ++static void bus_wake(struct brcmf_bus *bus) ++{ ++ if (bus->sleeping) ++ brcmf_sdbrcm_bussleep(bus, false); ++} ++ ++static u32 brcmf_sdbrcm_hostmail(struct brcmf_bus *bus) ++{ ++ u32 intstatus = 0; ++ u32 hmb_data; ++ u8 fcbits; ++ uint retries = 0; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Read mailbox data and ack that we did so */ ++ r_sdreg32(bus, &hmb_data, ++ offsetof(struct sdpcmd_regs, tohostmailboxdata), &retries); ++ ++ if (retries <= retry_limit) ++ w_sdreg32(bus, SMB_INT_ACK, ++ offsetof(struct sdpcmd_regs, tosbmailbox), &retries); ++ bus->f1regdata += 2; ++ ++ /* Dongle recomposed rx frames, accept them again */ ++ if (hmb_data & HMB_DATA_NAKHANDLED) { ++ brcmf_dbg(INFO, "Dongle reports NAK handled, expect rtx of %d\n", ++ bus->rx_seq); ++ if (!bus->rxskip) ++ brcmf_dbg(ERROR, "unexpected NAKHANDLED!\n"); ++ ++ bus->rxskip = false; ++ intstatus |= I_HMB_FRAME_IND; ++ } ++ ++ /* ++ * DEVREADY does not occur with gSPI. ++ */ ++ if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) { ++ bus->sdpcm_ver = ++ (hmb_data & HMB_DATA_VERSION_MASK) >> ++ HMB_DATA_VERSION_SHIFT; ++ if (bus->sdpcm_ver != SDPCM_PROT_VERSION) ++ brcmf_dbg(ERROR, "Version mismatch, dongle reports %d, " ++ "expecting %d\n", ++ bus->sdpcm_ver, SDPCM_PROT_VERSION); ++ else ++ brcmf_dbg(INFO, "Dongle ready, protocol version %d\n", ++ bus->sdpcm_ver); ++ } ++ ++ /* ++ * Flow Control has been moved into the RX headers and this out of band ++ * method isn't used any more. ++ * remaining backward compatible with older dongles. ++ */ ++ if (hmb_data & HMB_DATA_FC) { ++ fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >> ++ HMB_DATA_FCDATA_SHIFT; ++ ++ if (fcbits & ~bus->flowcontrol) ++ bus->fc_xoff++; ++ ++ if (bus->flowcontrol & ~fcbits) ++ bus->fc_xon++; ++ ++ bus->fc_rcvd++; ++ bus->flowcontrol = fcbits; ++ } ++ ++ /* Shouldn't be any others */ ++ if (hmb_data & ~(HMB_DATA_DEVREADY | ++ HMB_DATA_NAKHANDLED | ++ HMB_DATA_FC | ++ HMB_DATA_FWREADY | ++ HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK)) ++ brcmf_dbg(ERROR, "Unknown mailbox data content: 0x%02x\n", ++ hmb_data); ++ ++ return intstatus; ++} ++ ++static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx) ++{ ++ uint retries = 0; ++ u16 lastrbc; ++ u8 hi, lo; ++ int err; ++ ++ brcmf_dbg(ERROR, "%sterminate frame%s\n", ++ abort ? "abort command, " : "", ++ rtx ? ", send NAK" : ""); ++ ++ if (abort) ++ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_FRAMECTRL, ++ SFC_RF_TERM, &err); ++ bus->f1regdata++; ++ ++ /* Wait until the packet has been flushed (device/FIFO stable) */ ++ for (lastrbc = retries = 0xffff; retries > 0; retries--) { ++ hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_RFRAMEBCHI, NULL); ++ lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_RFRAMEBCLO, NULL); ++ bus->f1regdata += 2; ++ ++ if ((hi == 0) && (lo == 0)) ++ break; ++ ++ if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) { ++ brcmf_dbg(ERROR, "count growing: last 0x%04x now 0x%04x\n", ++ lastrbc, (hi << 8) + lo); ++ } ++ lastrbc = (hi << 8) + lo; ++ } ++ ++ if (!retries) ++ brcmf_dbg(ERROR, "count never zeroed: last 0x%04x\n", lastrbc); ++ else ++ brcmf_dbg(INFO, "flush took %d iterations\n", 0xffff - retries); ++ ++ if (rtx) { ++ bus->rxrtx++; ++ w_sdreg32(bus, SMB_NAK, ++ offsetof(struct sdpcmd_regs, tosbmailbox), &retries); ++ ++ bus->f1regdata++; ++ if (retries <= retry_limit) ++ bus->rxskip = true; ++ } ++ ++ /* Clear partial in any case */ ++ bus->nextlen = 0; ++ ++ /* If we can't reach the device, signal failure */ ++ if (err || brcmf_sdcard_regfail(bus->sdiodev)) ++ bus->drvr->busstate = BRCMF_BUS_DOWN; ++} ++ ++static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq) ++{ ++ u16 dlen, totlen; ++ u8 *dptr, num = 0; ++ ++ u16 sublen, check; ++ struct sk_buff *pfirst, *plast, *pnext, *save_pfirst; ++ ++ int errcode; ++ u8 chan, seq, doff, sfdoff; ++ u8 txmax; ++ ++ int ifidx = 0; ++ bool usechain = bus->use_rxchain; ++ ++ /* If packets, issue read(s) and send up packet chain */ ++ /* Return sequence numbers consumed? */ ++ ++ brcmf_dbg(TRACE, "start: glomd %p glom %p\n", bus->glomd, bus->glom); ++ ++ /* If there's a descriptor, generate the packet chain */ ++ if (bus->glomd) { ++ pfirst = plast = pnext = NULL; ++ dlen = (u16) (bus->glomd->len); ++ dptr = bus->glomd->data; ++ if (!dlen || (dlen & 1)) { ++ brcmf_dbg(ERROR, "bad glomd len(%d), ignore descriptor\n", ++ dlen); ++ dlen = 0; ++ } ++ ++ for (totlen = num = 0; dlen; num++) { ++ /* Get (and move past) next length */ ++ sublen = get_unaligned_le16(dptr); ++ dlen -= sizeof(u16); ++ dptr += sizeof(u16); ++ if ((sublen < SDPCM_HDRLEN) || ++ ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) { ++ brcmf_dbg(ERROR, "descriptor len %d bad: %d\n", ++ num, sublen); ++ pnext = NULL; ++ break; ++ } ++ if (sublen % BRCMF_SDALIGN) { ++ brcmf_dbg(ERROR, "sublen %d not multiple of %d\n", ++ sublen, BRCMF_SDALIGN); ++ usechain = false; ++ } ++ totlen += sublen; ++ ++ /* For last frame, adjust read len so total ++ is a block multiple */ ++ if (!dlen) { ++ sublen += ++ (roundup(totlen, bus->blocksize) - totlen); ++ totlen = roundup(totlen, bus->blocksize); ++ } ++ ++ /* Allocate/chain packet for next subframe */ ++ pnext = brcmu_pkt_buf_get_skb(sublen + BRCMF_SDALIGN); ++ if (pnext == NULL) { ++ brcmf_dbg(ERROR, "bcm_pkt_buf_get_skb failed, num %d len %d\n", ++ num, sublen); ++ break; ++ } ++ if (!pfirst) { ++ pfirst = plast = pnext; ++ } else { ++ plast->next = pnext; ++ plast = pnext; ++ } ++ ++ /* Adhere to start alignment requirements */ ++ pkt_align(pnext, sublen, BRCMF_SDALIGN); ++ } ++ ++ /* If all allocations succeeded, save packet chain ++ in bus structure */ ++ if (pnext) { ++ brcmf_dbg(GLOM, "allocated %d-byte packet chain for %d subframes\n", ++ totlen, num); ++ if (BRCMF_GLOM_ON() && bus->nextlen && ++ totlen != bus->nextlen) { ++ brcmf_dbg(GLOM, "glomdesc mismatch: nextlen %d glomdesc %d rxseq %d\n", ++ bus->nextlen, totlen, rxseq); ++ } ++ bus->glom = pfirst; ++ pfirst = pnext = NULL; ++ } else { ++ if (pfirst) ++ brcmu_pkt_buf_free_skb(pfirst); ++ bus->glom = NULL; ++ num = 0; ++ } ++ ++ /* Done with descriptor packet */ ++ brcmu_pkt_buf_free_skb(bus->glomd); ++ bus->glomd = NULL; ++ bus->nextlen = 0; ++ } ++ ++ /* Ok -- either we just generated a packet chain, ++ or had one from before */ ++ if (bus->glom) { ++ if (BRCMF_GLOM_ON()) { ++ brcmf_dbg(GLOM, "try superframe read, packet chain:\n"); ++ for (pnext = bus->glom; pnext; pnext = pnext->next) { ++ brcmf_dbg(GLOM, " %p: %p len 0x%04x (%d)\n", ++ pnext, (u8 *) (pnext->data), ++ pnext->len, pnext->len); ++ } ++ } ++ ++ pfirst = bus->glom; ++ dlen = (u16) brcmu_pkttotlen(pfirst); ++ ++ /* Do an SDIO read for the superframe. Configurable iovar to ++ * read directly into the chained packet, or allocate a large ++ * packet and and copy into the chain. ++ */ ++ if (usechain) { ++ errcode = brcmf_sdcard_recv_buf(bus->sdiodev, ++ bus->sdiodev->sbwad, ++ SDIO_FUNC_2, ++ F2SYNC, (u8 *) pfirst->data, dlen, ++ pfirst); ++ } else if (bus->dataptr) { ++ errcode = brcmf_sdcard_recv_buf(bus->sdiodev, ++ bus->sdiodev->sbwad, ++ SDIO_FUNC_2, ++ F2SYNC, bus->dataptr, dlen, ++ NULL); ++ sublen = (u16) brcmu_pktfrombuf(pfirst, 0, dlen, ++ bus->dataptr); ++ if (sublen != dlen) { ++ brcmf_dbg(ERROR, "FAILED TO COPY, dlen %d sublen %d\n", ++ dlen, sublen); ++ errcode = -1; ++ } ++ pnext = NULL; ++ } else { ++ brcmf_dbg(ERROR, "COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", ++ dlen); ++ errcode = -1; ++ } ++ bus->f2rxdata++; ++ ++ /* On failure, kill the superframe, allow a couple retries */ ++ if (errcode < 0) { ++ brcmf_dbg(ERROR, "glom read of %d bytes failed: %d\n", ++ dlen, errcode); ++ bus->drvr->rx_errors++; ++ ++ if (bus->glomerr++ < 3) { ++ brcmf_sdbrcm_rxfail(bus, true, true); ++ } else { ++ bus->glomerr = 0; ++ brcmf_sdbrcm_rxfail(bus, true, false); ++ brcmu_pkt_buf_free_skb(bus->glom); ++ bus->rxglomfail++; ++ bus->glom = NULL; ++ } ++ return 0; ++ } ++#ifdef BCMDBG ++ if (BRCMF_GLOM_ON()) { ++ printk(KERN_DEBUG "SUPERFRAME:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ pfirst->data, min_t(int, pfirst->len, 48)); ++ } ++#endif ++ ++ /* Validate the superframe header */ ++ dptr = (u8 *) (pfirst->data); ++ sublen = get_unaligned_le16(dptr); ++ check = get_unaligned_le16(dptr + sizeof(u16)); ++ ++ chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); ++ seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); ++ bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; ++ if ((bus->nextlen << 4) > MAX_RX_DATASZ) { ++ brcmf_dbg(INFO, "nextlen too large (%d) seq %d\n", ++ bus->nextlen, seq); ++ bus->nextlen = 0; ++ } ++ doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); ++ txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); ++ ++ errcode = 0; ++ if ((u16)~(sublen ^ check)) { ++ brcmf_dbg(ERROR, "(superframe): HW hdr error: len/check 0x%04x/0x%04x\n", ++ sublen, check); ++ errcode = -1; ++ } else if (roundup(sublen, bus->blocksize) != dlen) { ++ brcmf_dbg(ERROR, "(superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n", ++ sublen, roundup(sublen, bus->blocksize), ++ dlen); ++ errcode = -1; ++ } else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) != ++ SDPCM_GLOM_CHANNEL) { ++ brcmf_dbg(ERROR, "(superframe): bad channel %d\n", ++ SDPCM_PACKET_CHANNEL( ++ &dptr[SDPCM_FRAMETAG_LEN])); ++ errcode = -1; ++ } else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) { ++ brcmf_dbg(ERROR, "(superframe): got 2nd descriptor?\n"); ++ errcode = -1; ++ } else if ((doff < SDPCM_HDRLEN) || ++ (doff > (pfirst->len - SDPCM_HDRLEN))) { ++ brcmf_dbg(ERROR, "(superframe): Bad data offset %d: HW %d pkt %d min %d\n", ++ doff, sublen, pfirst->len, SDPCM_HDRLEN); ++ errcode = -1; ++ } ++ ++ /* Check sequence number of superframe SW header */ ++ if (rxseq != seq) { ++ brcmf_dbg(INFO, "(superframe) rx_seq %d, expected %d\n", ++ seq, rxseq); ++ bus->rx_badseq++; ++ rxseq = seq; ++ } ++ ++ /* Check window for sanity */ ++ if ((u8) (txmax - bus->tx_seq) > 0x40) { ++ brcmf_dbg(ERROR, "unlikely tx max %d with tx_seq %d\n", ++ txmax, bus->tx_seq); ++ txmax = bus->tx_seq + 2; ++ } ++ bus->tx_max = txmax; ++ ++ /* Remove superframe header, remember offset */ ++ skb_pull(pfirst, doff); ++ sfdoff = doff; ++ ++ /* Validate all the subframe headers */ ++ for (num = 0, pnext = pfirst; pnext && !errcode; ++ num++, pnext = pnext->next) { ++ dptr = (u8 *) (pnext->data); ++ dlen = (u16) (pnext->len); ++ sublen = get_unaligned_le16(dptr); ++ check = get_unaligned_le16(dptr + sizeof(u16)); ++ chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); ++ doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); ++#ifdef BCMDBG ++ if (BRCMF_GLOM_ON()) { ++ printk(KERN_DEBUG "subframe:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ dptr, 32); ++ } ++#endif ++ ++ if ((u16)~(sublen ^ check)) { ++ brcmf_dbg(ERROR, "(subframe %d): HW hdr error: len/check 0x%04x/0x%04x\n", ++ num, sublen, check); ++ errcode = -1; ++ } else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) { ++ brcmf_dbg(ERROR, "(subframe %d): length mismatch: len 0x%04x, expect 0x%04x\n", ++ num, sublen, dlen); ++ errcode = -1; ++ } else if ((chan != SDPCM_DATA_CHANNEL) && ++ (chan != SDPCM_EVENT_CHANNEL)) { ++ brcmf_dbg(ERROR, "(subframe %d): bad channel %d\n", ++ num, chan); ++ errcode = -1; ++ } else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) { ++ brcmf_dbg(ERROR, "(subframe %d): Bad data offset %d: HW %d min %d\n", ++ num, doff, sublen, SDPCM_HDRLEN); ++ errcode = -1; ++ } ++ } ++ ++ if (errcode) { ++ /* Terminate frame on error, request ++ a couple retries */ ++ if (bus->glomerr++ < 3) { ++ /* Restore superframe header space */ ++ skb_push(pfirst, sfdoff); ++ brcmf_sdbrcm_rxfail(bus, true, true); ++ } else { ++ bus->glomerr = 0; ++ brcmf_sdbrcm_rxfail(bus, true, false); ++ brcmu_pkt_buf_free_skb(bus->glom); ++ bus->rxglomfail++; ++ bus->glom = NULL; ++ } ++ bus->nextlen = 0; ++ return 0; ++ } ++ ++ /* Basic SD framing looks ok - process each packet (header) */ ++ save_pfirst = pfirst; ++ bus->glom = NULL; ++ plast = NULL; ++ ++ for (num = 0; pfirst; rxseq++, pfirst = pnext) { ++ pnext = pfirst->next; ++ pfirst->next = NULL; ++ ++ dptr = (u8 *) (pfirst->data); ++ sublen = get_unaligned_le16(dptr); ++ chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); ++ seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); ++ doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); ++ ++ brcmf_dbg(GLOM, "Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n", ++ num, pfirst, pfirst->data, ++ pfirst->len, sublen, chan, seq); ++ ++ /* precondition: chan == SDPCM_DATA_CHANNEL || ++ chan == SDPCM_EVENT_CHANNEL */ ++ ++ if (rxseq != seq) { ++ brcmf_dbg(GLOM, "rx_seq %d, expected %d\n", ++ seq, rxseq); ++ bus->rx_badseq++; ++ rxseq = seq; ++ } ++#ifdef BCMDBG ++ if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) { ++ printk(KERN_DEBUG "Rx Subframe Data:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ dptr, dlen); ++ } ++#endif ++ ++ __skb_trim(pfirst, sublen); ++ skb_pull(pfirst, doff); ++ ++ if (pfirst->len == 0) { ++ brcmu_pkt_buf_free_skb(pfirst); ++ if (plast) ++ plast->next = pnext; ++ else ++ save_pfirst = pnext; ++ ++ continue; ++ } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, ++ pfirst) != 0) { ++ brcmf_dbg(ERROR, "rx protocol error\n"); ++ bus->drvr->rx_errors++; ++ brcmu_pkt_buf_free_skb(pfirst); ++ if (plast) ++ plast->next = pnext; ++ else ++ save_pfirst = pnext; ++ ++ continue; ++ } ++ ++ /* this packet will go up, link back into ++ chain and count it */ ++ pfirst->next = pnext; ++ plast = pfirst; ++ num++; ++ ++#ifdef BCMDBG ++ if (BRCMF_GLOM_ON()) { ++ brcmf_dbg(GLOM, "subframe %d to stack, %p (%p/%d) nxt/lnk %p/%p\n", ++ num, pfirst, pfirst->data, ++ pfirst->len, pfirst->next, ++ pfirst->prev); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ pfirst->data, ++ min_t(int, pfirst->len, 32)); ++ } ++#endif /* BCMDBG */ ++ } ++ if (num) { ++ up(&bus->sdsem); ++ brcmf_rx_frame(bus->drvr, ifidx, save_pfirst, num); ++ down(&bus->sdsem); ++ } ++ ++ bus->rxglomframes++; ++ bus->rxglompkts += num; ++ } ++ return num; ++} ++ ++static int brcmf_sdbrcm_dcmd_resp_wait(struct brcmf_bus *bus, uint *condition, ++ bool *pending) ++{ ++ DECLARE_WAITQUEUE(wait, current); ++ int timeout = msecs_to_jiffies(DCMD_RESP_TIMEOUT); ++ ++ /* Wait until control frame is available */ ++ add_wait_queue(&bus->dcmd_resp_wait, &wait); ++ set_current_state(TASK_INTERRUPTIBLE); ++ ++ while (!(*condition) && (!signal_pending(current) && timeout)) ++ timeout = schedule_timeout(timeout); ++ ++ if (signal_pending(current)) ++ *pending = true; ++ ++ set_current_state(TASK_RUNNING); ++ remove_wait_queue(&bus->dcmd_resp_wait, &wait); ++ ++ return timeout; ++} ++ ++static int brcmf_sdbrcm_dcmd_resp_wake(struct brcmf_bus *bus) ++{ ++ if (waitqueue_active(&bus->dcmd_resp_wait)) ++ wake_up_interruptible(&bus->dcmd_resp_wait); ++ ++ return 0; ++} ++static void ++brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff) ++{ ++ uint rdlen, pad; ++ ++ int sdret; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Set rxctl for frame (w/optional alignment) */ ++ bus->rxctl = bus->rxbuf; ++ bus->rxctl += BRCMF_FIRSTREAD; ++ pad = ((unsigned long)bus->rxctl % BRCMF_SDALIGN); ++ if (pad) ++ bus->rxctl += (BRCMF_SDALIGN - pad); ++ bus->rxctl -= BRCMF_FIRSTREAD; ++ ++ /* Copy the already-read portion over */ ++ memcpy(bus->rxctl, hdr, BRCMF_FIRSTREAD); ++ if (len <= BRCMF_FIRSTREAD) ++ goto gotpkt; ++ ++ /* Raise rdlen to next SDIO block to avoid tail command */ ++ rdlen = len - BRCMF_FIRSTREAD; ++ if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) { ++ pad = bus->blocksize - (rdlen % bus->blocksize); ++ if ((pad <= bus->roundup) && (pad < bus->blocksize) && ++ ((len + pad) < bus->drvr->maxctl)) ++ rdlen += pad; ++ } else if (rdlen % BRCMF_SDALIGN) { ++ rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN); ++ } ++ ++ /* Satisfy length-alignment requirements */ ++ if (rdlen & (ALIGNMENT - 1)) ++ rdlen = roundup(rdlen, ALIGNMENT); ++ ++ /* Drop if the read is too big or it exceeds our maximum */ ++ if ((rdlen + BRCMF_FIRSTREAD) > bus->drvr->maxctl) { ++ brcmf_dbg(ERROR, "%d-byte control read exceeds %d-byte buffer\n", ++ rdlen, bus->drvr->maxctl); ++ bus->drvr->rx_errors++; ++ brcmf_sdbrcm_rxfail(bus, false, false); ++ goto done; ++ } ++ ++ if ((len - doff) > bus->drvr->maxctl) { ++ brcmf_dbg(ERROR, "%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n", ++ len, len - doff, bus->drvr->maxctl); ++ bus->drvr->rx_errors++; ++ bus->rx_toolong++; ++ brcmf_sdbrcm_rxfail(bus, false, false); ++ goto done; ++ } ++ ++ /* Read remainder of frame body into the rxctl buffer */ ++ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, ++ bus->sdiodev->sbwad, ++ SDIO_FUNC_2, ++ F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen, ++ NULL); ++ bus->f2rxdata++; ++ ++ /* Control frame failures need retransmission */ ++ if (sdret < 0) { ++ brcmf_dbg(ERROR, "read %d control bytes failed: %d\n", ++ rdlen, sdret); ++ bus->rxc_errors++; ++ brcmf_sdbrcm_rxfail(bus, true, true); ++ goto done; ++ } ++ ++gotpkt: ++ ++#ifdef BCMDBG ++ if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) { ++ printk(KERN_DEBUG "RxCtrl:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, bus->rxctl, len); ++ } ++#endif ++ ++ /* Point to valid data and indicate its length */ ++ bus->rxctl += doff; ++ bus->rxlen = len - doff; ++ ++done: ++ /* Awake any waiters */ ++ brcmf_sdbrcm_dcmd_resp_wake(bus); ++} ++ ++/* Pad read to blocksize for efficiency */ ++static void brcmf_pad(struct brcmf_bus *bus, u16 *pad, u16 *rdlen) ++{ ++ if (bus->roundup && bus->blocksize && *rdlen > bus->blocksize) { ++ *pad = bus->blocksize - (*rdlen % bus->blocksize); ++ if (*pad <= bus->roundup && *pad < bus->blocksize && ++ *rdlen + *pad + BRCMF_FIRSTREAD < MAX_RX_DATASZ) ++ *rdlen += *pad; ++ } else if (*rdlen % BRCMF_SDALIGN) { ++ *rdlen += BRCMF_SDALIGN - (*rdlen % BRCMF_SDALIGN); ++ } ++} ++ ++static void ++brcmf_alloc_pkt_and_read(struct brcmf_bus *bus, u16 rdlen, ++ struct sk_buff **pkt, u8 **rxbuf) ++{ ++ int sdret; /* Return code from calls */ ++ ++ *pkt = brcmu_pkt_buf_get_skb(rdlen + BRCMF_SDALIGN); ++ if (*pkt == NULL) ++ return; ++ ++ pkt_align(*pkt, rdlen, BRCMF_SDALIGN); ++ *rxbuf = (u8 *) ((*pkt)->data); ++ /* Read the entire frame */ ++ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, ++ SDIO_FUNC_2, F2SYNC, ++ *rxbuf, rdlen, *pkt); ++ bus->f2rxdata++; ++ ++ if (sdret < 0) { ++ brcmf_dbg(ERROR, "(nextlen): read %d bytes failed: %d\n", ++ rdlen, sdret); ++ brcmu_pkt_buf_free_skb(*pkt); ++ bus->drvr->rx_errors++; ++ /* Force retry w/normal header read. ++ * Don't attempt NAK for ++ * gSPI ++ */ ++ brcmf_sdbrcm_rxfail(bus, true, true); ++ *pkt = NULL; ++ } ++} ++ ++/* Checks the header */ ++static int ++brcmf_check_rxbuf(struct brcmf_bus *bus, struct sk_buff *pkt, u8 *rxbuf, ++ u8 rxseq, u16 nextlen, u16 *len) ++{ ++ u16 check; ++ bool len_consistent; /* Result of comparing readahead len and ++ len from hw-hdr */ ++ ++ memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN); ++ ++ /* Extract hardware header fields */ ++ *len = get_unaligned_le16(bus->rxhdr); ++ check = get_unaligned_le16(bus->rxhdr + sizeof(u16)); ++ ++ /* All zeros means readahead info was bad */ ++ if (!(*len | check)) { ++ brcmf_dbg(INFO, "(nextlen): read zeros in HW header???\n"); ++ goto fail; ++ } ++ ++ /* Validate check bytes */ ++ if ((u16)~(*len ^ check)) { ++ brcmf_dbg(ERROR, "(nextlen): HW hdr error: nextlen/len/check 0x%04x/0x%04x/0x%04x\n", ++ nextlen, *len, check); ++ bus->rx_badhdr++; ++ brcmf_sdbrcm_rxfail(bus, false, false); ++ goto fail; ++ } ++ ++ /* Validate frame length */ ++ if (*len < SDPCM_HDRLEN) { ++ brcmf_dbg(ERROR, "(nextlen): HW hdr length invalid: %d\n", ++ *len); ++ goto fail; ++ } ++ ++ /* Check for consistency with readahead info */ ++ len_consistent = (nextlen != (roundup(*len, 16) >> 4)); ++ if (len_consistent) { ++ /* Mismatch, force retry w/normal ++ header (may be >4K) */ ++ brcmf_dbg(ERROR, "(nextlen): mismatch, nextlen %d len %d rnd %d; expected rxseq %d\n", ++ nextlen, *len, roundup(*len, 16), ++ rxseq); ++ brcmf_sdbrcm_rxfail(bus, true, true); ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ brcmf_sdbrcm_pktfree2(bus, pkt); ++ return -EINVAL; ++} ++ ++/* Return true if there may be more frames to read */ ++static uint ++brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished) ++{ ++ u16 len, check; /* Extracted hardware header fields */ ++ u8 chan, seq, doff; /* Extracted software header fields */ ++ u8 fcbits; /* Extracted fcbits from software header */ ++ ++ struct sk_buff *pkt; /* Packet for event or data frames */ ++ u16 pad; /* Number of pad bytes to read */ ++ u16 rdlen; /* Total number of bytes to read */ ++ u8 rxseq; /* Next sequence number to expect */ ++ uint rxleft = 0; /* Remaining number of frames allowed */ ++ int sdret; /* Return code from calls */ ++ u8 txmax; /* Maximum tx sequence offered */ ++ u8 *rxbuf; ++ int ifidx = 0; ++ uint rxcount = 0; /* Total frames read */ ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Not finished unless we encounter no more frames indication */ ++ *finished = false; ++ ++ for (rxseq = bus->rx_seq, rxleft = maxframes; ++ !bus->rxskip && rxleft && bus->drvr->busstate != BRCMF_BUS_DOWN; ++ rxseq++, rxleft--) { ++ ++ /* Handle glomming separately */ ++ if (bus->glom || bus->glomd) { ++ u8 cnt; ++ brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n", ++ bus->glomd, bus->glom); ++ cnt = brcmf_sdbrcm_rxglom(bus, rxseq); ++ brcmf_dbg(GLOM, "rxglom returned %d\n", cnt); ++ rxseq += cnt - 1; ++ rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1; ++ continue; ++ } ++ ++ /* Try doing single read if we can */ ++ if (bus->nextlen) { ++ u16 nextlen = bus->nextlen; ++ bus->nextlen = 0; ++ ++ rdlen = len = nextlen << 4; ++ brcmf_pad(bus, &pad, &rdlen); ++ ++ /* ++ * After the frame is received we have to ++ * distinguish whether it is data ++ * or non-data frame. ++ */ ++ brcmf_alloc_pkt_and_read(bus, rdlen, &pkt, &rxbuf); ++ if (pkt == NULL) { ++ /* Give up on data, request rtx of events */ ++ brcmf_dbg(ERROR, "(nextlen): brcmf_alloc_pkt_and_read failed: len %d rdlen %d expected rxseq %d\n", ++ len, rdlen, rxseq); ++ continue; ++ } ++ ++ if (brcmf_check_rxbuf(bus, pkt, rxbuf, rxseq, nextlen, ++ &len) < 0) ++ continue; ++ ++ /* Extract software header fields */ ++ chan = SDPCM_PACKET_CHANNEL( ++ &bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ seq = SDPCM_PACKET_SEQUENCE( ++ &bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ doff = SDPCM_DOFFSET_VALUE( ++ &bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ txmax = SDPCM_WINDOW_VALUE( ++ &bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ ++ bus->nextlen = ++ bus->rxhdr[SDPCM_FRAMETAG_LEN + ++ SDPCM_NEXTLEN_OFFSET]; ++ if ((bus->nextlen << 4) > MAX_RX_DATASZ) { ++ brcmf_dbg(INFO, "(nextlen): got frame w/nextlen too large (%d), seq %d\n", ++ bus->nextlen, seq); ++ bus->nextlen = 0; ++ } ++ ++ bus->drvr->rx_readahead_cnt++; ++ ++ /* Handle Flow Control */ ++ fcbits = SDPCM_FCMASK_VALUE( ++ &bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ ++ if (bus->flowcontrol != fcbits) { ++ if (~bus->flowcontrol & fcbits) ++ bus->fc_xoff++; ++ ++ if (bus->flowcontrol & ~fcbits) ++ bus->fc_xon++; ++ ++ bus->fc_rcvd++; ++ bus->flowcontrol = fcbits; ++ } ++ ++ /* Check and update sequence number */ ++ if (rxseq != seq) { ++ brcmf_dbg(INFO, "(nextlen): rx_seq %d, expected %d\n", ++ seq, rxseq); ++ bus->rx_badseq++; ++ rxseq = seq; ++ } ++ ++ /* Check window for sanity */ ++ if ((u8) (txmax - bus->tx_seq) > 0x40) { ++ brcmf_dbg(ERROR, "got unlikely tx max %d with tx_seq %d\n", ++ txmax, bus->tx_seq); ++ txmax = bus->tx_seq + 2; ++ } ++ bus->tx_max = txmax; ++ ++#ifdef BCMDBG ++ if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) { ++ printk(KERN_DEBUG "Rx Data:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ rxbuf, len); ++ } else if (BRCMF_HDRS_ON()) { ++ printk(KERN_DEBUG "RxHdr:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ bus->rxhdr, SDPCM_HDRLEN); ++ } ++#endif ++ ++ if (chan == SDPCM_CONTROL_CHANNEL) { ++ brcmf_dbg(ERROR, "(nextlen): readahead on control packet %d?\n", ++ seq); ++ /* Force retry w/normal header read */ ++ bus->nextlen = 0; ++ brcmf_sdbrcm_rxfail(bus, false, true); ++ brcmf_sdbrcm_pktfree2(bus, pkt); ++ continue; ++ } ++ ++ /* Validate data offset */ ++ if ((doff < SDPCM_HDRLEN) || (doff > len)) { ++ brcmf_dbg(ERROR, "(nextlen): bad data offset %d: HW len %d min %d\n", ++ doff, len, SDPCM_HDRLEN); ++ brcmf_sdbrcm_rxfail(bus, false, false); ++ brcmf_sdbrcm_pktfree2(bus, pkt); ++ continue; ++ } ++ ++ /* All done with this one -- now deliver the packet */ ++ goto deliver; ++ } ++ ++ /* Read frame header (hardware and software) */ ++ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, ++ SDIO_FUNC_2, F2SYNC, bus->rxhdr, ++ BRCMF_FIRSTREAD, NULL); ++ bus->f2rxhdrs++; ++ ++ if (sdret < 0) { ++ brcmf_dbg(ERROR, "RXHEADER FAILED: %d\n", sdret); ++ bus->rx_hdrfail++; ++ brcmf_sdbrcm_rxfail(bus, true, true); ++ continue; ++ } ++#ifdef BCMDBG ++ if (BRCMF_BYTES_ON() || BRCMF_HDRS_ON()) { ++ printk(KERN_DEBUG "RxHdr:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ bus->rxhdr, SDPCM_HDRLEN); ++ } ++#endif ++ ++ /* Extract hardware header fields */ ++ len = get_unaligned_le16(bus->rxhdr); ++ check = get_unaligned_le16(bus->rxhdr + sizeof(u16)); ++ ++ /* All zeros means no more frames */ ++ if (!(len | check)) { ++ *finished = true; ++ break; ++ } ++ ++ /* Validate check bytes */ ++ if ((u16) ~(len ^ check)) { ++ brcmf_dbg(ERROR, "HW hdr err: len/check 0x%04x/0x%04x\n", ++ len, check); ++ bus->rx_badhdr++; ++ brcmf_sdbrcm_rxfail(bus, false, false); ++ continue; ++ } ++ ++ /* Validate frame length */ ++ if (len < SDPCM_HDRLEN) { ++ brcmf_dbg(ERROR, "HW hdr length invalid: %d\n", len); ++ continue; ++ } ++ ++ /* Extract software header fields */ ++ chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ ++ /* Validate data offset */ ++ if ((doff < SDPCM_HDRLEN) || (doff > len)) { ++ brcmf_dbg(ERROR, "Bad data offset %d: HW len %d, min %d seq %d\n", ++ doff, len, SDPCM_HDRLEN, seq); ++ bus->rx_badhdr++; ++ brcmf_sdbrcm_rxfail(bus, false, false); ++ continue; ++ } ++ ++ /* Save the readahead length if there is one */ ++ bus->nextlen = ++ bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; ++ if ((bus->nextlen << 4) > MAX_RX_DATASZ) { ++ brcmf_dbg(INFO, "(nextlen): got frame w/nextlen too large (%d), seq %d\n", ++ bus->nextlen, seq); ++ bus->nextlen = 0; ++ } ++ ++ /* Handle Flow Control */ ++ fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ ++ if (bus->flowcontrol != fcbits) { ++ if (~bus->flowcontrol & fcbits) ++ bus->fc_xoff++; ++ ++ if (bus->flowcontrol & ~fcbits) ++ bus->fc_xon++; ++ ++ bus->fc_rcvd++; ++ bus->flowcontrol = fcbits; ++ } ++ ++ /* Check and update sequence number */ ++ if (rxseq != seq) { ++ brcmf_dbg(INFO, "rx_seq %d, expected %d\n", seq, rxseq); ++ bus->rx_badseq++; ++ rxseq = seq; ++ } ++ ++ /* Check window for sanity */ ++ if ((u8) (txmax - bus->tx_seq) > 0x40) { ++ brcmf_dbg(ERROR, "unlikely tx max %d with tx_seq %d\n", ++ txmax, bus->tx_seq); ++ txmax = bus->tx_seq + 2; ++ } ++ bus->tx_max = txmax; ++ ++ /* Call a separate function for control frames */ ++ if (chan == SDPCM_CONTROL_CHANNEL) { ++ brcmf_sdbrcm_read_control(bus, bus->rxhdr, len, doff); ++ continue; ++ } ++ ++ /* precondition: chan is either SDPCM_DATA_CHANNEL, ++ SDPCM_EVENT_CHANNEL, SDPCM_TEST_CHANNEL or ++ SDPCM_GLOM_CHANNEL */ ++ ++ /* Length to read */ ++ rdlen = (len > BRCMF_FIRSTREAD) ? (len - BRCMF_FIRSTREAD) : 0; ++ ++ /* May pad read to blocksize for efficiency */ ++ if (bus->roundup && bus->blocksize && ++ (rdlen > bus->blocksize)) { ++ pad = bus->blocksize - (rdlen % bus->blocksize); ++ if ((pad <= bus->roundup) && (pad < bus->blocksize) && ++ ((rdlen + pad + BRCMF_FIRSTREAD) < MAX_RX_DATASZ)) ++ rdlen += pad; ++ } else if (rdlen % BRCMF_SDALIGN) { ++ rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN); ++ } ++ ++ /* Satisfy length-alignment requirements */ ++ if (rdlen & (ALIGNMENT - 1)) ++ rdlen = roundup(rdlen, ALIGNMENT); ++ ++ if ((rdlen + BRCMF_FIRSTREAD) > MAX_RX_DATASZ) { ++ /* Too long -- skip this frame */ ++ brcmf_dbg(ERROR, "too long: len %d rdlen %d\n", ++ len, rdlen); ++ bus->drvr->rx_errors++; ++ bus->rx_toolong++; ++ brcmf_sdbrcm_rxfail(bus, false, false); ++ continue; ++ } ++ ++ pkt = brcmu_pkt_buf_get_skb(rdlen + ++ BRCMF_FIRSTREAD + BRCMF_SDALIGN); ++ if (!pkt) { ++ /* Give up on data, request rtx of events */ ++ brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: rdlen %d chan %d\n", ++ rdlen, chan); ++ bus->drvr->rx_dropped++; ++ brcmf_sdbrcm_rxfail(bus, false, RETRYCHAN(chan)); ++ continue; ++ } ++ ++ /* Leave room for what we already read, and align remainder */ ++ skb_pull(pkt, BRCMF_FIRSTREAD); ++ pkt_align(pkt, rdlen, BRCMF_SDALIGN); ++ ++ /* Read the remaining frame data */ ++ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, ++ SDIO_FUNC_2, F2SYNC, ((u8 *) (pkt->data)), ++ rdlen, pkt); ++ bus->f2rxdata++; ++ ++ if (sdret < 0) { ++ brcmf_dbg(ERROR, "read %d %s bytes failed: %d\n", rdlen, ++ ((chan == SDPCM_EVENT_CHANNEL) ? "event" ++ : ((chan == SDPCM_DATA_CHANNEL) ? "data" ++ : "test")), sdret); ++ brcmu_pkt_buf_free_skb(pkt); ++ bus->drvr->rx_errors++; ++ brcmf_sdbrcm_rxfail(bus, true, RETRYCHAN(chan)); ++ continue; ++ } ++ ++ /* Copy the already-read portion */ ++ skb_push(pkt, BRCMF_FIRSTREAD); ++ memcpy(pkt->data, bus->rxhdr, BRCMF_FIRSTREAD); ++ ++#ifdef BCMDBG ++ if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) { ++ printk(KERN_DEBUG "Rx Data:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ pkt->data, len); ++ } ++#endif ++ ++deliver: ++ /* Save superframe descriptor and allocate packet frame */ ++ if (chan == SDPCM_GLOM_CHANNEL) { ++ if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) { ++ brcmf_dbg(GLOM, "glom descriptor, %d bytes:\n", ++ len); ++#ifdef BCMDBG ++ if (BRCMF_GLOM_ON()) { ++ printk(KERN_DEBUG "Glom Data:\n"); ++ print_hex_dump_bytes("", ++ DUMP_PREFIX_OFFSET, ++ pkt->data, len); ++ } ++#endif ++ __skb_trim(pkt, len); ++ skb_pull(pkt, SDPCM_HDRLEN); ++ bus->glomd = pkt; ++ } else { ++ brcmf_dbg(ERROR, "%s: glom superframe w/o " ++ "descriptor!\n", __func__); ++ brcmf_sdbrcm_rxfail(bus, false, false); ++ } ++ continue; ++ } ++ ++ /* Fill in packet len and prio, deliver upward */ ++ __skb_trim(pkt, len); ++ skb_pull(pkt, doff); ++ ++ if (pkt->len == 0) { ++ brcmu_pkt_buf_free_skb(pkt); ++ continue; ++ } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, pkt) != 0) { ++ brcmf_dbg(ERROR, "rx protocol error\n"); ++ brcmu_pkt_buf_free_skb(pkt); ++ bus->drvr->rx_errors++; ++ continue; ++ } ++ ++ /* Unlock during rx call */ ++ up(&bus->sdsem); ++ brcmf_rx_frame(bus->drvr, ifidx, pkt, 1); ++ down(&bus->sdsem); ++ } ++ rxcount = maxframes - rxleft; ++#ifdef BCMDBG ++ /* Message if we hit the limit */ ++ if (!rxleft) ++ brcmf_dbg(DATA, "hit rx limit of %d frames\n", ++ maxframes); ++ else ++#endif /* BCMDBG */ ++ brcmf_dbg(DATA, "processed %d frames\n", rxcount); ++ /* Back off rxseq if awaiting rtx, update rx_seq */ ++ if (bus->rxskip) ++ rxseq--; ++ bus->rx_seq = rxseq; ++ ++ return rxcount; ++} ++ ++static int ++brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn, uint flags, ++ u8 *buf, uint nbytes, struct sk_buff *pkt) ++{ ++ return brcmf_sdcard_send_buf ++ (bus->sdiodev, addr, fn, flags, buf, nbytes, pkt); ++} ++ ++static void ++brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar) ++{ ++ up(&bus->sdsem); ++ wait_event_interruptible_timeout(bus->ctrl_wait, ++ (*lockvar == false), HZ * 2); ++ down(&bus->sdsem); ++ return; ++} ++ ++static void ++brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus) ++{ ++ if (waitqueue_active(&bus->ctrl_wait)) ++ wake_up_interruptible(&bus->ctrl_wait); ++ return; ++} ++ ++/* Writes a HW/SW header into the packet and sends it. */ ++/* Assumes: (a) header space already there, (b) caller holds lock */ ++static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt, ++ uint chan, bool free_pkt) ++{ ++ int ret; ++ u8 *frame; ++ u16 len, pad = 0; ++ u32 swheader; ++ struct sk_buff *new; ++ int i; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ frame = (u8 *) (pkt->data); ++ ++ /* Add alignment padding, allocate new packet if needed */ ++ pad = ((unsigned long)frame % BRCMF_SDALIGN); ++ if (pad) { ++ if (skb_headroom(pkt) < pad) { ++ brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n", ++ skb_headroom(pkt), pad); ++ bus->drvr->tx_realloc++; ++ new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN); ++ if (!new) { ++ brcmf_dbg(ERROR, "couldn't allocate new %d-byte packet\n", ++ pkt->len + BRCMF_SDALIGN); ++ ret = -ENOMEM; ++ goto done; ++ } ++ ++ pkt_align(new, pkt->len, BRCMF_SDALIGN); ++ memcpy(new->data, pkt->data, pkt->len); ++ if (free_pkt) ++ brcmu_pkt_buf_free_skb(pkt); ++ /* free the pkt if canned one is not used */ ++ free_pkt = true; ++ pkt = new; ++ frame = (u8 *) (pkt->data); ++ /* precondition: (frame % BRCMF_SDALIGN) == 0) */ ++ pad = 0; ++ } else { ++ skb_push(pkt, pad); ++ frame = (u8 *) (pkt->data); ++ /* precondition: pad + SDPCM_HDRLEN <= pkt->len */ ++ memset(frame, 0, pad + SDPCM_HDRLEN); ++ } ++ } ++ /* precondition: pad < BRCMF_SDALIGN */ ++ ++ /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ ++ len = (u16) (pkt->len); ++ *(__le16 *) frame = cpu_to_le16(len); ++ *(((__le16 *) frame) + 1) = cpu_to_le16(~len); ++ ++ /* Software tag: channel, sequence number, data offset */ ++ swheader = ++ ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq | ++ (((pad + ++ SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); ++ ++ put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN); ++ put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); ++ ++#ifdef BCMDBG ++ tx_packets[pkt->priority]++; ++ if (BRCMF_BYTES_ON() && ++ (((BRCMF_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) || ++ (BRCMF_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) { ++ printk(KERN_DEBUG "Tx Frame:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, frame, len); ++ } else if (BRCMF_HDRS_ON()) { ++ printk(KERN_DEBUG "TxHdr:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ frame, min_t(u16, len, 16)); ++ } ++#endif ++ ++ /* Raise len to next SDIO block to eliminate tail command */ ++ if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { ++ u16 pad = bus->blocksize - (len % bus->blocksize); ++ if ((pad <= bus->roundup) && (pad < bus->blocksize)) ++ len += pad; ++ } else if (len % BRCMF_SDALIGN) { ++ len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN); ++ } ++ ++ /* Some controllers have trouble with odd bytes -- round to even */ ++ if (len & (ALIGNMENT - 1)) ++ len = roundup(len, ALIGNMENT); ++ ++ ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad, ++ SDIO_FUNC_2, F2SYNC, frame, ++ len, pkt); ++ bus->f2txdata++; ++ ++ if (ret < 0) { ++ /* On failure, abort the command and terminate the frame */ ++ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", ++ ret); ++ bus->tx_sderrs++; ++ ++ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, ++ NULL); ++ bus->f1regdata++; ++ ++ for (i = 0; i < 3; i++) { ++ u8 hi, lo; ++ hi = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCHI, ++ NULL); ++ lo = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCLO, ++ NULL); ++ bus->f1regdata += 2; ++ if ((hi == 0) && (lo == 0)) ++ break; ++ } ++ ++ } ++ if (ret == 0) ++ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; ++ ++done: ++ /* restore pkt buffer pointer before calling tx complete routine */ ++ skb_pull(pkt, SDPCM_HDRLEN + pad); ++ up(&bus->sdsem); ++ brcmf_txcomplete(bus->drvr, pkt, ret != 0); ++ down(&bus->sdsem); ++ ++ if (free_pkt) ++ brcmu_pkt_buf_free_skb(pkt); ++ ++ return ret; ++} ++ ++static uint brcmf_sdbrcm_sendfromq(struct brcmf_bus *bus, uint maxframes) ++{ ++ struct sk_buff *pkt; ++ u32 intstatus = 0; ++ uint retries = 0; ++ int ret = 0, prec_out; ++ uint cnt = 0; ++ uint datalen; ++ u8 tx_prec_map; ++ ++ struct brcmf_pub *drvr = bus->drvr; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ tx_prec_map = ~bus->flowcontrol; ++ ++ /* Send frames until the limit or some other event */ ++ for (cnt = 0; (cnt < maxframes) && data_ok(bus); cnt++) { ++ spin_lock_bh(&bus->txqlock); ++ pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out); ++ if (pkt == NULL) { ++ spin_unlock_bh(&bus->txqlock); ++ break; ++ } ++ spin_unlock_bh(&bus->txqlock); ++ datalen = pkt->len - SDPCM_HDRLEN; ++ ++ ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true); ++ if (ret) ++ bus->drvr->tx_errors++; ++ else ++ bus->drvr->dstats.tx_bytes += datalen; ++ ++ /* In poll mode, need to check for other events */ ++ if (!bus->intr && cnt) { ++ /* Check device status, signal pending interrupt */ ++ r_sdreg32(bus, &intstatus, ++ offsetof(struct sdpcmd_regs, intstatus), ++ &retries); ++ bus->f2txdata++; ++ if (brcmf_sdcard_regfail(bus->sdiodev)) ++ break; ++ if (intstatus & bus->hostintmask) ++ bus->ipend = true; ++ } ++ } ++ ++ /* Deflow-control stack if needed */ ++ if (drvr->up && (drvr->busstate == BRCMF_BUS_DATA) && ++ drvr->txoff && (pktq_len(&bus->txq) < TXLOW)) ++ brcmf_txflowcontrol(drvr, 0, OFF); ++ ++ return cnt; ++} ++ ++static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus) ++{ ++ u32 intstatus, newstatus = 0; ++ uint retries = 0; ++ uint rxlimit = bus->rxbound; /* Rx frames to read before resched */ ++ uint txlimit = bus->txbound; /* Tx frames to send before resched */ ++ uint framecnt = 0; /* Temporary counter of tx/rx frames */ ++ bool rxdone = true; /* Flag for no more read data */ ++ bool resched = false; /* Flag indicating resched wanted */ ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Start with leftover status bits */ ++ intstatus = bus->intstatus; ++ ++ down(&bus->sdsem); ++ ++ /* If waiting for HTAVAIL, check status */ ++ if (bus->clkstate == CLK_PENDING) { ++ int err; ++ u8 clkctl, devctl = 0; ++ ++#ifdef BCMDBG ++ /* Check for inconsistent device control */ ++ devctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, &err); ++ if (err) { ++ brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", err); ++ bus->drvr->busstate = BRCMF_BUS_DOWN; ++ } ++#endif /* BCMDBG */ ++ ++ /* Read CSR, if clock on switch to AVAIL, else ignore */ ++ clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ if (err) { ++ brcmf_dbg(ERROR, "error reading CSR: %d\n", ++ err); ++ bus->drvr->busstate = BRCMF_BUS_DOWN; ++ } ++ ++ brcmf_dbg(INFO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", ++ devctl, clkctl); ++ ++ if (SBSDIO_HTAV(clkctl)) { ++ devctl = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, &err); ++ if (err) { ++ brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", ++ err); ++ bus->drvr->busstate = BRCMF_BUS_DOWN; ++ } ++ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, devctl, &err); ++ if (err) { ++ brcmf_dbg(ERROR, "error writing DEVCTL: %d\n", ++ err); ++ bus->drvr->busstate = BRCMF_BUS_DOWN; ++ } ++ bus->clkstate = CLK_AVAIL; ++ } else { ++ goto clkwait; ++ } ++ } ++ ++ bus_wake(bus); ++ ++ /* Make sure backplane clock is on */ ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true); ++ if (bus->clkstate == CLK_PENDING) ++ goto clkwait; ++ ++ /* Pending interrupt indicates new device status */ ++ if (bus->ipend) { ++ bus->ipend = false; ++ r_sdreg32(bus, &newstatus, ++ offsetof(struct sdpcmd_regs, intstatus), &retries); ++ bus->f1regdata++; ++ if (brcmf_sdcard_regfail(bus->sdiodev)) ++ newstatus = 0; ++ newstatus &= bus->hostintmask; ++ bus->fcstate = !!(newstatus & I_HMB_FC_STATE); ++ if (newstatus) { ++ w_sdreg32(bus, newstatus, ++ offsetof(struct sdpcmd_regs, intstatus), ++ &retries); ++ bus->f1regdata++; ++ } ++ } ++ ++ /* Merge new bits with previous */ ++ intstatus |= newstatus; ++ bus->intstatus = 0; ++ ++ /* Handle flow-control change: read new state in case our ack ++ * crossed another change interrupt. If change still set, assume ++ * FC ON for safety, let next loop through do the debounce. ++ */ ++ if (intstatus & I_HMB_FC_CHANGE) { ++ intstatus &= ~I_HMB_FC_CHANGE; ++ w_sdreg32(bus, I_HMB_FC_CHANGE, ++ offsetof(struct sdpcmd_regs, intstatus), &retries); ++ ++ r_sdreg32(bus, &newstatus, ++ offsetof(struct sdpcmd_regs, intstatus), &retries); ++ bus->f1regdata += 2; ++ bus->fcstate = ++ !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)); ++ intstatus |= (newstatus & bus->hostintmask); ++ } ++ ++ /* Handle host mailbox indication */ ++ if (intstatus & I_HMB_HOST_INT) { ++ intstatus &= ~I_HMB_HOST_INT; ++ intstatus |= brcmf_sdbrcm_hostmail(bus); ++ } ++ ++ /* Generally don't ask for these, can get CRC errors... */ ++ if (intstatus & I_WR_OOSYNC) { ++ brcmf_dbg(ERROR, "Dongle reports WR_OOSYNC\n"); ++ intstatus &= ~I_WR_OOSYNC; ++ } ++ ++ if (intstatus & I_RD_OOSYNC) { ++ brcmf_dbg(ERROR, "Dongle reports RD_OOSYNC\n"); ++ intstatus &= ~I_RD_OOSYNC; ++ } ++ ++ if (intstatus & I_SBINT) { ++ brcmf_dbg(ERROR, "Dongle reports SBINT\n"); ++ intstatus &= ~I_SBINT; ++ } ++ ++ /* Would be active due to wake-wlan in gSPI */ ++ if (intstatus & I_CHIPACTIVE) { ++ brcmf_dbg(INFO, "Dongle reports CHIPACTIVE\n"); ++ intstatus &= ~I_CHIPACTIVE; ++ } ++ ++ /* Ignore frame indications if rxskip is set */ ++ if (bus->rxskip) ++ intstatus &= ~I_HMB_FRAME_IND; ++ ++ /* On frame indication, read available frames */ ++ if (PKT_AVAILABLE()) { ++ framecnt = brcmf_sdbrcm_readframes(bus, rxlimit, &rxdone); ++ if (rxdone || bus->rxskip) ++ intstatus &= ~I_HMB_FRAME_IND; ++ rxlimit -= min(framecnt, rxlimit); ++ } ++ ++ /* Keep still-pending events for next scheduling */ ++ bus->intstatus = intstatus; ++ ++clkwait: ++ if (data_ok(bus) && bus->ctrl_frame_stat && ++ (bus->clkstate == CLK_AVAIL)) { ++ int ret, i; ++ ++ ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad, ++ SDIO_FUNC_2, F2SYNC, (u8 *) bus->ctrl_frame_buf, ++ (u32) bus->ctrl_frame_len, NULL); ++ ++ if (ret < 0) { ++ /* On failure, abort the command and ++ terminate the frame */ ++ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", ++ ret); ++ bus->tx_sderrs++; ++ ++ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, ++ NULL); ++ bus->f1regdata++; ++ ++ for (i = 0; i < 3; i++) { ++ u8 hi, lo; ++ hi = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCHI, ++ NULL); ++ lo = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCLO, ++ NULL); ++ bus->f1regdata += 2; ++ if ((hi == 0) && (lo == 0)) ++ break; ++ } ++ ++ } ++ if (ret == 0) ++ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; ++ ++ brcmf_dbg(INFO, "Return_dpc value is : %d\n", ret); ++ bus->ctrl_frame_stat = false; ++ brcmf_sdbrcm_wait_event_wakeup(bus); ++ } ++ /* Send queued frames (limit 1 if rx may still be pending) */ ++ else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate && ++ brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit ++ && data_ok(bus)) { ++ framecnt = rxdone ? txlimit : min(txlimit, bus->txminmax); ++ framecnt = brcmf_sdbrcm_sendfromq(bus, framecnt); ++ txlimit -= framecnt; ++ } ++ ++ /* Resched if events or tx frames are pending, ++ else await next interrupt */ ++ /* On failed register access, all bets are off: ++ no resched or interrupts */ ++ if ((bus->drvr->busstate == BRCMF_BUS_DOWN) || ++ brcmf_sdcard_regfail(bus->sdiodev)) { ++ brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation %d\n", ++ brcmf_sdcard_regfail(bus->sdiodev)); ++ bus->drvr->busstate = BRCMF_BUS_DOWN; ++ bus->intstatus = 0; ++ } else if (bus->clkstate == CLK_PENDING) { ++ brcmf_dbg(INFO, "rescheduled due to CLK_PENDING awaiting I_CHIPACTIVE interrupt\n"); ++ resched = true; ++ } else if (bus->intstatus || bus->ipend || ++ (!bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) ++ && data_ok(bus)) || PKT_AVAILABLE()) { ++ resched = true; ++ } ++ ++ bus->dpc_sched = resched; ++ ++ /* If we're done for now, turn off clock request. */ ++ if ((bus->clkstate != CLK_PENDING) ++ && bus->idletime == BRCMF_IDLE_IMMEDIATE) { ++ bus->activity = false; ++ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); ++ } ++ ++ up(&bus->sdsem); ++ ++ return resched; ++} ++ ++static int brcmf_sdbrcm_dpc_thread(void *data) ++{ ++ struct brcmf_bus *bus = (struct brcmf_bus *) data; ++ ++ allow_signal(SIGTERM); ++ /* Run until signal received */ ++ while (1) { ++ if (kthread_should_stop()) ++ break; ++ if (!wait_for_completion_interruptible(&bus->dpc_wait)) { ++ /* Call bus dpc unless it indicated down ++ (then clean stop) */ ++ if (bus->drvr->busstate != BRCMF_BUS_DOWN) { ++ if (brcmf_sdbrcm_dpc(bus)) ++ complete(&bus->dpc_wait); ++ } else { ++ /* after stopping the bus, exit thread */ ++ brcmf_sdbrcm_bus_stop(bus); ++ bus->dpc_tsk = NULL; ++ break; ++ } ++ } else ++ break; ++ } ++ return 0; ++} ++ ++int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt) ++{ ++ int ret = -EBADE; ++ uint datalen, prec; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ datalen = pkt->len; ++ ++ /* Add space for the header */ ++ skb_push(pkt, SDPCM_HDRLEN); ++ /* precondition: IS_ALIGNED((unsigned long)(pkt->data), 2) */ ++ ++ prec = prio2prec((pkt->priority & PRIOMASK)); ++ ++ /* Check for existing queue, current flow-control, ++ pending event, or pending clock */ ++ brcmf_dbg(TRACE, "deferring pktq len %d\n", pktq_len(&bus->txq)); ++ bus->fcqueued++; ++ ++ /* Priority based enq */ ++ spin_lock_bh(&bus->txqlock); ++ if (brcmf_c_prec_enq(bus->drvr, &bus->txq, pkt, prec) == false) { ++ skb_pull(pkt, SDPCM_HDRLEN); ++ brcmf_txcomplete(bus->drvr, pkt, false); ++ brcmu_pkt_buf_free_skb(pkt); ++ brcmf_dbg(ERROR, "out of bus->txq !!!\n"); ++ ret = -ENOSR; ++ } else { ++ ret = 0; ++ } ++ spin_unlock_bh(&bus->txqlock); ++ ++ if (pktq_len(&bus->txq) >= TXHI) ++ brcmf_txflowcontrol(bus->drvr, 0, ON); ++ ++#ifdef BCMDBG ++ if (pktq_plen(&bus->txq, prec) > qcount[prec]) ++ qcount[prec] = pktq_plen(&bus->txq, prec); ++#endif ++ /* Schedule DPC if needed to send queued packet(s) */ ++ if (!bus->dpc_sched) { ++ bus->dpc_sched = true; ++ if (bus->dpc_tsk) ++ complete(&bus->dpc_wait); ++ } ++ ++ return ret; ++} ++ ++static int ++brcmf_sdbrcm_membytes(struct brcmf_bus *bus, bool write, u32 address, u8 *data, ++ uint size) ++{ ++ int bcmerror = 0; ++ u32 sdaddr; ++ uint dsize; ++ ++ /* Determine initial transfer parameters */ ++ sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK; ++ if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK) ++ dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr); ++ else ++ dsize = size; ++ ++ /* Set the backplane window to include the start address */ ++ bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address); ++ if (bcmerror) { ++ brcmf_dbg(ERROR, "window change failed\n"); ++ goto xfer_done; ++ } ++ ++ /* Do the transfer(s) */ ++ while (size) { ++ brcmf_dbg(INFO, "%s %d bytes at offset 0x%08x in window 0x%08x\n", ++ write ? "write" : "read", dsize, ++ sdaddr, address & SBSDIO_SBWINDOW_MASK); ++ bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write, ++ sdaddr, data, dsize); ++ if (bcmerror) { ++ brcmf_dbg(ERROR, "membytes transfer failed\n"); ++ break; ++ } ++ ++ /* Adjust for next transfer (if any) */ ++ size -= dsize; ++ if (size) { ++ data += dsize; ++ address += dsize; ++ bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, ++ address); ++ if (bcmerror) { ++ brcmf_dbg(ERROR, "window change failed\n"); ++ break; ++ } ++ sdaddr = 0; ++ dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size); ++ } ++ } ++ ++xfer_done: ++ /* Return the window to backplane enumeration space for core access */ ++ if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, bus->sdiodev->sbwad)) ++ brcmf_dbg(ERROR, "FAILED to set window back to 0x%x\n", ++ bus->sdiodev->sbwad); ++ ++ return bcmerror; ++} ++ ++#ifdef BCMDBG ++#define CONSOLE_LINE_MAX 192 ++ ++static int brcmf_sdbrcm_readconsole(struct brcmf_bus *bus) ++{ ++ struct brcmf_console *c = &bus->console; ++ u8 line[CONSOLE_LINE_MAX], ch; ++ u32 n, idx, addr; ++ int rv; ++ ++ /* Don't do anything until FWREADY updates console address */ ++ if (bus->console_addr == 0) ++ return 0; ++ ++ /* Read console log struct */ ++ addr = bus->console_addr + offsetof(struct rte_console, log_le); ++ rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&c->log_le, ++ sizeof(c->log_le)); ++ if (rv < 0) ++ return rv; ++ ++ /* Allocate console buffer (one time only) */ ++ if (c->buf == NULL) { ++ c->bufsize = le32_to_cpu(c->log_le.buf_size); ++ c->buf = kmalloc(c->bufsize, GFP_ATOMIC); ++ if (c->buf == NULL) ++ return -ENOMEM; ++ } ++ ++ idx = le32_to_cpu(c->log_le.idx); ++ ++ /* Protect against corrupt value */ ++ if (idx > c->bufsize) ++ return -EBADE; ++ ++ /* Skip reading the console buffer if the index pointer ++ has not moved */ ++ if (idx == c->last) ++ return 0; ++ ++ /* Read the console buffer */ ++ addr = le32_to_cpu(c->log_le.buf); ++ rv = brcmf_sdbrcm_membytes(bus, false, addr, c->buf, c->bufsize); ++ if (rv < 0) ++ return rv; ++ ++ while (c->last != idx) { ++ for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) { ++ if (c->last == idx) { ++ /* This would output a partial line. ++ * Instead, back up ++ * the buffer pointer and output this ++ * line next time around. ++ */ ++ if (c->last >= n) ++ c->last -= n; ++ else ++ c->last = c->bufsize - n; ++ goto break2; ++ } ++ ch = c->buf[c->last]; ++ c->last = (c->last + 1) % c->bufsize; ++ if (ch == '\n') ++ break; ++ line[n] = ch; ++ } ++ ++ if (n > 0) { ++ if (line[n - 1] == '\r') ++ n--; ++ line[n] = 0; ++ printk(KERN_DEBUG "CONSOLE: %s\n", line); ++ } ++ } ++break2: ++ ++ return 0; ++} ++#endif /* BCMDBG */ ++ ++static int brcmf_tx_frame(struct brcmf_bus *bus, u8 *frame, u16 len) ++{ ++ int i; ++ int ret; ++ ++ bus->ctrl_frame_stat = false; ++ ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad, ++ SDIO_FUNC_2, F2SYNC, frame, len, NULL); ++ ++ if (ret < 0) { ++ /* On failure, abort the command and terminate the frame */ ++ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", ++ ret); ++ bus->tx_sderrs++; ++ ++ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_FRAMECTRL, ++ SFC_WF_TERM, NULL); ++ bus->f1regdata++; ++ ++ for (i = 0; i < 3; i++) { ++ u8 hi, lo; ++ hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCHI, ++ NULL); ++ lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCLO, ++ NULL); ++ bus->f1regdata += 2; ++ if (hi == 0 && lo == 0) ++ break; ++ } ++ return ret; ++ } ++ ++ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; ++ ++ return ret; ++} ++ ++int ++brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) ++{ ++ u8 *frame; ++ u16 len; ++ u32 swheader; ++ uint retries = 0; ++ u8 doff = 0; ++ int ret = -1; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Back the pointer to make a room for bus header */ ++ frame = msg - SDPCM_HDRLEN; ++ len = (msglen += SDPCM_HDRLEN); ++ ++ /* Add alignment padding (optional for ctl frames) */ ++ doff = ((unsigned long)frame % BRCMF_SDALIGN); ++ if (doff) { ++ frame -= doff; ++ len += doff; ++ msglen += doff; ++ memset(frame, 0, doff + SDPCM_HDRLEN); ++ } ++ /* precondition: doff < BRCMF_SDALIGN */ ++ doff += SDPCM_HDRLEN; ++ ++ /* Round send length to next SDIO block */ ++ if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { ++ u16 pad = bus->blocksize - (len % bus->blocksize); ++ if ((pad <= bus->roundup) && (pad < bus->blocksize)) ++ len += pad; ++ } else if (len % BRCMF_SDALIGN) { ++ len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN); ++ } ++ ++ /* Satisfy length-alignment requirements */ ++ if (len & (ALIGNMENT - 1)) ++ len = roundup(len, ALIGNMENT); ++ ++ /* precondition: IS_ALIGNED((unsigned long)frame, 2) */ ++ ++ /* Need to lock here to protect txseq and SDIO tx calls */ ++ down(&bus->sdsem); ++ ++ bus_wake(bus); ++ ++ /* Make sure backplane clock is on */ ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); ++ ++ /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ ++ *(__le16 *) frame = cpu_to_le16((u16) msglen); ++ *(((__le16 *) frame) + 1) = cpu_to_le16(~msglen); ++ ++ /* Software tag: channel, sequence number, data offset */ ++ swheader = ++ ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & ++ SDPCM_CHANNEL_MASK) ++ | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) & ++ SDPCM_DOFFSET_MASK); ++ put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN); ++ put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); ++ ++ if (!data_ok(bus)) { ++ brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n", ++ bus->tx_max, bus->tx_seq); ++ bus->ctrl_frame_stat = true; ++ /* Send from dpc */ ++ bus->ctrl_frame_buf = frame; ++ bus->ctrl_frame_len = len; ++ ++ brcmf_sdbrcm_wait_for_event(bus, &bus->ctrl_frame_stat); ++ ++ if (bus->ctrl_frame_stat == false) { ++ brcmf_dbg(INFO, "ctrl_frame_stat == false\n"); ++ ret = 0; ++ } else { ++ brcmf_dbg(INFO, "ctrl_frame_stat == true\n"); ++ ret = -1; ++ } ++ } ++ ++ if (ret == -1) { ++#ifdef BCMDBG ++ if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) { ++ printk(KERN_DEBUG "Tx Frame:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ frame, len); ++ } else if (BRCMF_HDRS_ON()) { ++ printk(KERN_DEBUG "TxHdr:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ frame, min_t(u16, len, 16)); ++ } ++#endif ++ ++ do { ++ ret = brcmf_tx_frame(bus, frame, len); ++ } while (ret < 0 && retries++ < TXRETRIES); ++ } ++ ++ if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) { ++ bus->activity = false; ++ brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); ++ } ++ ++ up(&bus->sdsem); ++ ++ if (ret) ++ bus->drvr->tx_ctlerrs++; ++ else ++ bus->drvr->tx_ctlpkts++; ++ ++ return ret ? -EIO : 0; ++} ++ ++int ++brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) ++{ ++ int timeleft; ++ uint rxlen = 0; ++ bool pending; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Wait until control frame is available */ ++ timeleft = brcmf_sdbrcm_dcmd_resp_wait(bus, &bus->rxlen, &pending); ++ ++ down(&bus->sdsem); ++ rxlen = bus->rxlen; ++ memcpy(msg, bus->rxctl, min(msglen, rxlen)); ++ bus->rxlen = 0; ++ up(&bus->sdsem); ++ ++ if (rxlen) { ++ brcmf_dbg(CTL, "resumed on rxctl frame, got %d expected %d\n", ++ rxlen, msglen); ++ } else if (timeleft == 0) { ++ brcmf_dbg(ERROR, "resumed on timeout\n"); ++ } else if (pending == true) { ++ brcmf_dbg(CTL, "cancelled\n"); ++ return -ERESTARTSYS; ++ } else { ++ brcmf_dbg(CTL, "resumed for unknown reason?\n"); ++ } ++ ++ if (rxlen) ++ bus->drvr->rx_ctlpkts++; ++ else ++ bus->drvr->rx_ctlerrs++; ++ ++ return rxlen ? (int)rxlen : -ETIMEDOUT; ++} ++ ++static int brcmf_sdbrcm_downloadvars(struct brcmf_bus *bus, void *arg, int len) ++{ ++ int bcmerror = 0; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Basic sanity checks */ ++ if (bus->drvr->up) { ++ bcmerror = -EISCONN; ++ goto err; ++ } ++ if (!len) { ++ bcmerror = -EOVERFLOW; ++ goto err; ++ } ++ ++ /* Free the old ones and replace with passed variables */ ++ kfree(bus->vars); ++ ++ bus->vars = kmalloc(len, GFP_ATOMIC); ++ bus->varsz = bus->vars ? len : 0; ++ if (bus->vars == NULL) { ++ bcmerror = -ENOMEM; ++ goto err; ++ } ++ ++ /* Copy the passed variables, which should include the ++ terminating double-null */ ++ memcpy(bus->vars, arg, bus->varsz); ++err: ++ return bcmerror; ++} ++ ++static int brcmf_sdbrcm_write_vars(struct brcmf_bus *bus) ++{ ++ int bcmerror = 0; ++ u32 varsize; ++ u32 varaddr; ++ u8 *vbuffer; ++ u32 varsizew; ++ __le32 varsizew_le; ++#ifdef BCMDBG ++ char *nvram_ularray; ++#endif /* BCMDBG */ ++ ++ /* Even if there are no vars are to be written, we still ++ need to set the ramsize. */ ++ varsize = bus->varsz ? roundup(bus->varsz, 4) : 0; ++ varaddr = (bus->ramsize - 4) - varsize; ++ ++ if (bus->vars) { ++ vbuffer = kzalloc(varsize, GFP_ATOMIC); ++ if (!vbuffer) ++ return -ENOMEM; ++ ++ memcpy(vbuffer, bus->vars, bus->varsz); ++ ++ /* Write the vars list */ ++ bcmerror = ++ brcmf_sdbrcm_membytes(bus, true, varaddr, vbuffer, varsize); ++#ifdef BCMDBG ++ /* Verify NVRAM bytes */ ++ brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n", varsize); ++ nvram_ularray = kmalloc(varsize, GFP_ATOMIC); ++ if (!nvram_ularray) ++ return -ENOMEM; ++ ++ /* Upload image to verify downloaded contents. */ ++ memset(nvram_ularray, 0xaa, varsize); ++ ++ /* Read the vars list to temp buffer for comparison */ ++ bcmerror = ++ brcmf_sdbrcm_membytes(bus, false, varaddr, nvram_ularray, ++ varsize); ++ if (bcmerror) { ++ brcmf_dbg(ERROR, "error %d on reading %d nvram bytes at 0x%08x\n", ++ bcmerror, varsize, varaddr); ++ } ++ /* Compare the org NVRAM with the one read from RAM */ ++ if (memcmp(vbuffer, nvram_ularray, varsize)) ++ brcmf_dbg(ERROR, "Downloaded NVRAM image is corrupted\n"); ++ else ++ brcmf_dbg(ERROR, "Download/Upload/Compare of NVRAM ok\n"); ++ ++ kfree(nvram_ularray); ++#endif /* BCMDBG */ ++ ++ kfree(vbuffer); ++ } ++ ++ /* adjust to the user specified RAM */ ++ brcmf_dbg(INFO, "Physical memory size: %d\n", bus->ramsize); ++ brcmf_dbg(INFO, "Vars are at %d, orig varsize is %d\n", ++ varaddr, varsize); ++ varsize = ((bus->ramsize - 4) - varaddr); ++ ++ /* ++ * Determine the length token: ++ * Varsize, converted to words, in lower 16-bits, checksum ++ * in upper 16-bits. ++ */ ++ if (bcmerror) { ++ varsizew = 0; ++ varsizew_le = cpu_to_le32(0); ++ } else { ++ varsizew = varsize / 4; ++ varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF); ++ varsizew_le = cpu_to_le32(varsizew); ++ } ++ ++ brcmf_dbg(INFO, "New varsize is %d, length token=0x%08x\n", ++ varsize, varsizew); ++ ++ /* Write the length token to the last word */ ++ bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->ramsize - 4), ++ (u8 *)&varsizew_le, 4); ++ ++ return bcmerror; ++} ++ ++static void ++brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_dev *sdiodev, u32 corebase) ++{ ++ u32 regdata; ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbtmstatelow), 4); ++ if (regdata & SBTML_RESET) ++ return; ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbtmstatelow), 4); ++ if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) { ++ /* ++ * set target reject and spin until busy is clear ++ * (preserve core-specific bits) ++ */ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbtmstatelow), 4); ++ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), ++ 4, regdata | SBTML_REJ); ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbtmstatelow), 4); ++ udelay(1); ++ SPINWAIT((brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbtmstatehigh), 4) & ++ SBTMH_BUSY), 100000); ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbtmstatehigh), 4); ++ if (regdata & SBTMH_BUSY) ++ brcmf_dbg(ERROR, "ARM core still busy\n"); ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbidlow), 4); ++ if (regdata & SBIDL_INIT) { ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbimstate), 4) | ++ SBIM_RJ; ++ brcmf_sdcard_reg_write(sdiodev, ++ CORE_SB(corebase, sbimstate), 4, ++ regdata); ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbimstate), 4); ++ udelay(1); ++ SPINWAIT((brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbimstate), 4) & ++ SBIM_BY), 100000); ++ } ++ ++ /* set reset and reject while enabling the clocks */ ++ brcmf_sdcard_reg_write(sdiodev, ++ CORE_SB(corebase, sbtmstatelow), 4, ++ (((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | ++ SBTML_REJ | SBTML_RESET)); ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbtmstatelow), 4); ++ udelay(10); ++ ++ /* clear the initiator reject bit */ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbidlow), 4); ++ if (regdata & SBIDL_INIT) { ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbimstate), 4) & ++ ~SBIM_RJ; ++ brcmf_sdcard_reg_write(sdiodev, ++ CORE_SB(corebase, sbimstate), 4, ++ regdata); ++ } ++ } ++ ++ /* leave reset and reject asserted */ ++ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4, ++ (SBTML_REJ | SBTML_RESET)); ++ udelay(1); ++} ++ ++static void ++brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_dev *sdiodev, u32 corebase) ++{ ++ u32 regdata; ++ ++ /* ++ * Must do the disable sequence first to work for ++ * arbitrary current core state. ++ */ ++ brcmf_sdbrcm_chip_disablecore(sdiodev, corebase); ++ ++ /* ++ * Now do the initialization sequence. ++ * set reset while enabling the clock and ++ * forcing them on throughout the core ++ */ ++ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4, ++ ((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | ++ SBTML_RESET); ++ udelay(1); ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbtmstatehigh), 4); ++ if (regdata & SBTMH_SERR) ++ brcmf_sdcard_reg_write(sdiodev, ++ CORE_SB(corebase, sbtmstatehigh), 4, 0); ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbimstate), 4); ++ if (regdata & (SBIM_IBE | SBIM_TO)) ++ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbimstate), 4, ++ regdata & ~(SBIM_IBE | SBIM_TO)); ++ ++ /* clear reset and allow it to propagate throughout the core */ ++ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4, ++ (SICF_FGC << SBTML_SICF_SHIFT) | ++ (SICF_CLOCK_EN << SBTML_SICF_SHIFT)); ++ udelay(1); ++ ++ /* leave clock enabled */ ++ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4, ++ (SICF_CLOCK_EN << SBTML_SICF_SHIFT)); ++ udelay(1); ++} ++ ++static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter) ++{ ++ uint retries; ++ u32 regdata; ++ int bcmerror = 0; ++ ++ /* To enter download state, disable ARM and reset SOCRAM. ++ * To exit download state, simply reset ARM (default is RAM boot). ++ */ ++ if (enter) { ++ bus->alp_only = true; ++ ++ brcmf_sdbrcm_chip_disablecore(bus->sdiodev, ++ bus->ci->armcorebase); ++ ++ brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->ramcorebase); ++ ++ /* Clear the top bit of memory */ ++ if (bus->ramsize) { ++ u32 zeros = 0; ++ brcmf_sdbrcm_membytes(bus, true, bus->ramsize - 4, ++ (u8 *)&zeros, 4); ++ } ++ } else { ++ regdata = brcmf_sdcard_reg_read(bus->sdiodev, ++ CORE_SB(bus->ci->ramcorebase, sbtmstatelow), 4); ++ regdata &= (SBTML_RESET | SBTML_REJ_MASK | ++ (SICF_CLOCK_EN << SBTML_SICF_SHIFT)); ++ if ((SICF_CLOCK_EN << SBTML_SICF_SHIFT) != regdata) { ++ brcmf_dbg(ERROR, "SOCRAM core is down after reset?\n"); ++ bcmerror = -EBADE; ++ goto fail; ++ } ++ ++ bcmerror = brcmf_sdbrcm_write_vars(bus); ++ if (bcmerror) { ++ brcmf_dbg(ERROR, "no vars written to RAM\n"); ++ bcmerror = 0; ++ } ++ ++ w_sdreg32(bus, 0xFFFFFFFF, ++ offsetof(struct sdpcmd_regs, intstatus), &retries); ++ ++ brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->armcorebase); ++ ++ /* Allow HT Clock now that the ARM is running. */ ++ bus->alp_only = false; ++ ++ bus->drvr->busstate = BRCMF_BUS_LOAD; ++ } ++fail: ++ return bcmerror; ++} ++ ++static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus) ++{ ++ if (bus->firmware->size < bus->fw_ptr + len) ++ len = bus->firmware->size - bus->fw_ptr; ++ ++ memcpy(buf, &bus->firmware->data[bus->fw_ptr], len); ++ bus->fw_ptr += len; ++ return len; ++} ++ ++MODULE_FIRMWARE(BCM4329_FW_NAME); ++MODULE_FIRMWARE(BCM4329_NV_NAME); ++ ++static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus) ++{ ++ int offset = 0; ++ uint len; ++ u8 *memblock = NULL, *memptr; ++ int ret; ++ ++ brcmf_dbg(INFO, "Enter\n"); ++ ++ bus->fw_name = BCM4329_FW_NAME; ++ ret = request_firmware(&bus->firmware, bus->fw_name, ++ &bus->sdiodev->func[2]->dev); ++ if (ret) { ++ brcmf_dbg(ERROR, "Fail to request firmware %d\n", ret); ++ return ret; ++ } ++ bus->fw_ptr = 0; ++ ++ memptr = memblock = kmalloc(MEMBLOCK + BRCMF_SDALIGN, GFP_ATOMIC); ++ if (memblock == NULL) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ if ((u32)(unsigned long)memblock % BRCMF_SDALIGN) ++ memptr += (BRCMF_SDALIGN - ++ ((u32)(unsigned long)memblock % BRCMF_SDALIGN)); ++ ++ /* Download image */ ++ while ((len = ++ brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus))) { ++ ret = brcmf_sdbrcm_membytes(bus, true, offset, memptr, len); ++ if (ret) { ++ brcmf_dbg(ERROR, "error %d on writing %d membytes at 0x%08x\n", ++ ret, MEMBLOCK, offset); ++ goto err; ++ } ++ ++ offset += MEMBLOCK; ++ } ++ ++err: ++ kfree(memblock); ++ ++ release_firmware(bus->firmware); ++ bus->fw_ptr = 0; ++ ++ return ret; ++} ++ ++/* ++ * ProcessVars:Takes a buffer of "=\n" lines read from a file ++ * and ending in a NUL. ++ * Removes carriage returns, empty lines, comment lines, and converts ++ * newlines to NULs. ++ * Shortens buffer as needed and pads with NULs. End of buffer is marked ++ * by two NULs. ++*/ ++ ++static uint brcmf_process_nvram_vars(char *varbuf, uint len) ++{ ++ char *dp; ++ bool findNewline; ++ int column; ++ uint buf_len, n; ++ ++ dp = varbuf; ++ ++ findNewline = false; ++ column = 0; ++ ++ for (n = 0; n < len; n++) { ++ if (varbuf[n] == 0) ++ break; ++ if (varbuf[n] == '\r') ++ continue; ++ if (findNewline && varbuf[n] != '\n') ++ continue; ++ findNewline = false; ++ if (varbuf[n] == '#') { ++ findNewline = true; ++ continue; ++ } ++ if (varbuf[n] == '\n') { ++ if (column == 0) ++ continue; ++ *dp++ = 0; ++ column = 0; ++ continue; ++ } ++ *dp++ = varbuf[n]; ++ column++; ++ } ++ buf_len = dp - varbuf; ++ ++ while (dp < varbuf + n) ++ *dp++ = 0; ++ ++ return buf_len; ++} ++ ++static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus) ++{ ++ uint len; ++ char *memblock = NULL; ++ char *bufp; ++ int ret; ++ ++ bus->nv_name = BCM4329_NV_NAME; ++ ret = request_firmware(&bus->firmware, bus->nv_name, ++ &bus->sdiodev->func[2]->dev); ++ if (ret) { ++ brcmf_dbg(ERROR, "Fail to request nvram %d\n", ret); ++ return ret; ++ } ++ bus->fw_ptr = 0; ++ ++ memblock = kmalloc(MEMBLOCK, GFP_ATOMIC); ++ if (memblock == NULL) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ len = brcmf_sdbrcm_get_image(memblock, MEMBLOCK, bus); ++ ++ if (len > 0 && len < MEMBLOCK) { ++ bufp = (char *)memblock; ++ bufp[len] = 0; ++ len = brcmf_process_nvram_vars(bufp, len); ++ bufp += len; ++ *bufp++ = 0; ++ if (len) ++ ret = brcmf_sdbrcm_downloadvars(bus, memblock, len + 1); ++ if (ret) ++ brcmf_dbg(ERROR, "error downloading vars: %d\n", ret); ++ } else { ++ brcmf_dbg(ERROR, "error reading nvram file: %d\n", len); ++ ret = -EIO; ++ } ++ ++err: ++ kfree(memblock); ++ ++ release_firmware(bus->firmware); ++ bus->fw_ptr = 0; ++ ++ return ret; ++} ++ ++static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus) ++{ ++ int bcmerror = -1; ++ ++ /* Keep arm in reset */ ++ if (brcmf_sdbrcm_download_state(bus, true)) { ++ brcmf_dbg(ERROR, "error placing ARM core in reset\n"); ++ goto err; ++ } ++ ++ /* External image takes precedence if specified */ ++ if (brcmf_sdbrcm_download_code_file(bus)) { ++ brcmf_dbg(ERROR, "dongle image file download failed\n"); ++ goto err; ++ } ++ ++ /* External nvram takes precedence if specified */ ++ if (brcmf_sdbrcm_download_nvram(bus)) ++ brcmf_dbg(ERROR, "dongle nvram file download failed\n"); ++ ++ /* Take arm out of reset */ ++ if (brcmf_sdbrcm_download_state(bus, false)) { ++ brcmf_dbg(ERROR, "error getting out of ARM core reset\n"); ++ goto err; ++ } ++ ++ bcmerror = 0; ++ ++err: ++ return bcmerror; ++} ++ ++static bool ++brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus) ++{ ++ bool ret; ++ ++ /* Download the firmware */ ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); ++ ++ ret = _brcmf_sdbrcm_download_firmware(bus) == 0; ++ ++ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); ++ ++ return ret; ++} ++ ++void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus) ++{ ++ u32 local_hostintmask; ++ u8 saveclk; ++ uint retries; ++ int err; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (bus->watchdog_tsk) { ++ send_sig(SIGTERM, bus->watchdog_tsk, 1); ++ kthread_stop(bus->watchdog_tsk); ++ bus->watchdog_tsk = NULL; ++ } ++ ++ if (bus->dpc_tsk && bus->dpc_tsk != current) { ++ send_sig(SIGTERM, bus->dpc_tsk, 1); ++ kthread_stop(bus->dpc_tsk); ++ bus->dpc_tsk = NULL; ++ } ++ ++ down(&bus->sdsem); ++ ++ bus_wake(bus); ++ ++ /* Enable clock for device interrupts */ ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); ++ ++ /* Disable and clear interrupts at the chip level also */ ++ w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask), &retries); ++ local_hostintmask = bus->hostintmask; ++ bus->hostintmask = 0; ++ ++ /* Change our idea of bus state */ ++ bus->drvr->busstate = BRCMF_BUS_DOWN; ++ ++ /* Force clocks on backplane to be sure F2 interrupt propagates */ ++ saveclk = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ if (!err) { ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, ++ (saveclk | SBSDIO_FORCE_HT), &err); ++ } ++ if (err) ++ brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err); ++ ++ /* Turn off the bus (F2), free any pending packets */ ++ brcmf_dbg(INTR, "disable SDIO interrupts\n"); ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, ++ SDIO_FUNC_ENABLE_1, NULL); ++ ++ /* Clear any pending interrupts now that F2 is disabled */ ++ w_sdreg32(bus, local_hostintmask, ++ offsetof(struct sdpcmd_regs, intstatus), &retries); ++ ++ /* Turn off the backplane clock (only) */ ++ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); ++ ++ /* Clear the data packet queues */ ++ brcmu_pktq_flush(&bus->txq, true, NULL, NULL); ++ ++ /* Clear any held glomming stuff */ ++ if (bus->glomd) ++ brcmu_pkt_buf_free_skb(bus->glomd); ++ ++ if (bus->glom) ++ brcmu_pkt_buf_free_skb(bus->glom); ++ ++ bus->glom = bus->glomd = NULL; ++ ++ /* Clear rx control and wake any waiters */ ++ bus->rxlen = 0; ++ brcmf_sdbrcm_dcmd_resp_wake(bus); ++ ++ /* Reset some F2 state stuff */ ++ bus->rxskip = false; ++ bus->tx_seq = bus->rx_seq = 0; ++ ++ up(&bus->sdsem); ++} ++ ++int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr) ++{ ++ struct brcmf_bus *bus = drvr->bus; ++ unsigned long timeout; ++ uint retries = 0; ++ u8 ready, enable; ++ int err, ret = 0; ++ u8 saveclk; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* try to download image and nvram to the dongle */ ++ if (drvr->busstate == BRCMF_BUS_DOWN) { ++ if (!(brcmf_sdbrcm_download_firmware(bus))) ++ return -1; ++ } ++ ++ if (!bus->drvr) ++ return 0; ++ ++ /* Start the watchdog timer */ ++ bus->drvr->tickcnt = 0; ++ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); ++ ++ down(&bus->sdsem); ++ ++ /* Make sure backplane clock is on, needed to generate F2 interrupt */ ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); ++ if (bus->clkstate != CLK_AVAIL) ++ goto exit; ++ ++ /* Force clocks on backplane to be sure F2 interrupt propagates */ ++ saveclk = ++ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ if (!err) { ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, ++ (saveclk | SBSDIO_FORCE_HT), &err); ++ } ++ if (err) { ++ brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err); ++ goto exit; ++ } ++ ++ /* Enable function 2 (frame transfers) */ ++ w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, ++ offsetof(struct sdpcmd_regs, tosbmailboxdata), &retries); ++ enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2); ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, ++ enable, NULL); ++ ++ timeout = jiffies + msecs_to_jiffies(BRCMF_WAIT_F2RDY); ++ ready = 0; ++ while (enable != ready) { ++ ready = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_0, ++ SDIO_CCCR_IORx, NULL); ++ if (time_after(jiffies, timeout)) ++ break; ++ else if (time_after(jiffies, timeout - BRCMF_WAIT_F2RDY + 50)) ++ /* prevent busy waiting if it takes too long */ ++ msleep_interruptible(20); ++ } ++ ++ brcmf_dbg(INFO, "enable 0x%02x, ready 0x%02x\n", enable, ready); ++ ++ /* If F2 successfully enabled, set core and enable interrupts */ ++ if (ready == enable) { ++ /* Set up the interrupt mask and enable interrupts */ ++ bus->hostintmask = HOSTINTMASK; ++ w_sdreg32(bus, bus->hostintmask, ++ offsetof(struct sdpcmd_regs, hostintmask), &retries); ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_WATERMARK, 8, &err); ++ ++ /* Set bus state according to enable result */ ++ drvr->busstate = BRCMF_BUS_DATA; ++ } ++ ++ else { ++ /* Disable F2 again */ ++ enable = SDIO_FUNC_ENABLE_1; ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, ++ SDIO_CCCR_IOEx, enable, NULL); ++ } ++ ++ /* Restore previous clock setting */ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); ++ ++ /* If we didn't come up, turn off backplane clock */ ++ if (drvr->busstate != BRCMF_BUS_DATA) ++ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); ++ ++exit: ++ up(&bus->sdsem); ++ ++ return ret; ++} ++ ++void brcmf_sdbrcm_isr(void *arg) ++{ ++ struct brcmf_bus *bus = (struct brcmf_bus *) arg; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (!bus) { ++ brcmf_dbg(ERROR, "bus is null pointer, exiting\n"); ++ return; ++ } ++ ++ if (bus->drvr->busstate == BRCMF_BUS_DOWN) { ++ brcmf_dbg(ERROR, "bus is down. we have nothing to do\n"); ++ return; ++ } ++ /* Count the interrupt call */ ++ bus->intrcount++; ++ bus->ipend = true; ++ ++ /* Shouldn't get this interrupt if we're sleeping? */ ++ if (bus->sleeping) { ++ brcmf_dbg(ERROR, "INTERRUPT WHILE SLEEPING??\n"); ++ return; ++ } ++ ++ /* Disable additional interrupts (is this needed now)? */ ++ if (!bus->intr) ++ brcmf_dbg(ERROR, "isr w/o interrupt configured!\n"); ++ ++ bus->dpc_sched = true; ++ if (bus->dpc_tsk) ++ complete(&bus->dpc_wait); ++} ++ ++static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr) ++{ ++ struct brcmf_bus *bus; ++ ++ brcmf_dbg(TIMER, "Enter\n"); ++ ++ bus = drvr->bus; ++ ++ /* Ignore the timer if simulating bus down */ ++ if (bus->sleeping) ++ return false; ++ ++ down(&bus->sdsem); ++ ++ /* Poll period: check device if appropriate. */ ++ if (bus->poll && (++bus->polltick >= bus->pollrate)) { ++ u32 intstatus = 0; ++ ++ /* Reset poll tick */ ++ bus->polltick = 0; ++ ++ /* Check device if no interrupts */ ++ if (!bus->intr || (bus->intrcount == bus->lastintrs)) { ++ ++ if (!bus->dpc_sched) { ++ u8 devpend; ++ devpend = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_0, SDIO_CCCR_INTx, ++ NULL); ++ intstatus = ++ devpend & (INTR_STATUS_FUNC1 | ++ INTR_STATUS_FUNC2); ++ } ++ ++ /* If there is something, make like the ISR and ++ schedule the DPC */ ++ if (intstatus) { ++ bus->pollcnt++; ++ bus->ipend = true; ++ ++ bus->dpc_sched = true; ++ if (bus->dpc_tsk) ++ complete(&bus->dpc_wait); ++ } ++ } ++ ++ /* Update interrupt tracking */ ++ bus->lastintrs = bus->intrcount; ++ } ++#ifdef BCMDBG ++ /* Poll for console output periodically */ ++ if (drvr->busstate == BRCMF_BUS_DATA && bus->console_interval != 0) { ++ bus->console.count += BRCMF_WD_POLL_MS; ++ if (bus->console.count >= bus->console_interval) { ++ bus->console.count -= bus->console_interval; ++ /* Make sure backplane clock is on */ ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); ++ if (brcmf_sdbrcm_readconsole(bus) < 0) ++ /* stop on error */ ++ bus->console_interval = 0; ++ } ++ } ++#endif /* BCMDBG */ ++ ++ /* On idle timeout clear activity flag and/or turn off clock */ ++ if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { ++ if (++bus->idlecount >= bus->idletime) { ++ bus->idlecount = 0; ++ if (bus->activity) { ++ bus->activity = false; ++ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); ++ } else { ++ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); ++ } ++ } ++ } ++ ++ up(&bus->sdsem); ++ ++ return bus->ipend; ++} ++ ++static bool brcmf_sdbrcm_chipmatch(u16 chipid) ++{ ++ if (chipid == BCM4329_CHIP_ID) ++ return true; ++ return false; ++} ++ ++static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ kfree(bus->rxbuf); ++ bus->rxctl = bus->rxbuf = NULL; ++ bus->rxlen = 0; ++ ++ kfree(bus->databuf); ++ bus->databuf = NULL; ++} ++ ++static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (bus->drvr->maxctl) { ++ bus->rxblen = ++ roundup((bus->drvr->maxctl + SDPCM_HDRLEN), ++ ALIGNMENT) + BRCMF_SDALIGN; ++ bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC); ++ if (!(bus->rxbuf)) ++ goto fail; ++ } ++ ++ /* Allocate buffer to receive glomed packet */ ++ bus->databuf = kmalloc(MAX_DATA_BUF, GFP_ATOMIC); ++ if (!(bus->databuf)) { ++ /* release rxbuf which was already located as above */ ++ if (!bus->rxblen) ++ kfree(bus->rxbuf); ++ goto fail; ++ } ++ ++ /* Align the buffer */ ++ if ((unsigned long)bus->databuf % BRCMF_SDALIGN) ++ bus->dataptr = bus->databuf + (BRCMF_SDALIGN - ++ ((unsigned long)bus->databuf % BRCMF_SDALIGN)); ++ else ++ bus->dataptr = bus->databuf; ++ ++ return true; ++ ++fail: ++ return false; ++} ++ ++/* SDIO Pad drive strength to select value mappings */ ++struct sdiod_drive_str { ++ u8 strength; /* Pad Drive Strength in mA */ ++ u8 sel; /* Chip-specific select value */ ++}; ++ ++/* SDIO Drive Strength to sel value table for PMU Rev 1 */ ++static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = { ++ { ++ 4, 0x2}, { ++ 2, 0x3}, { ++ 1, 0x0}, { ++ 0, 0x0} ++ }; ++ ++/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */ ++static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = { ++ { ++ 12, 0x7}, { ++ 10, 0x6}, { ++ 8, 0x5}, { ++ 6, 0x4}, { ++ 4, 0x2}, { ++ 2, 0x1}, { ++ 0, 0x0} ++ }; ++ ++/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */ ++static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = { ++ { ++ 32, 0x7}, { ++ 26, 0x6}, { ++ 22, 0x5}, { ++ 16, 0x4}, { ++ 12, 0x3}, { ++ 8, 0x2}, { ++ 4, 0x1}, { ++ 0, 0x0} ++ }; ++ ++#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) ++ ++static char *brcmf_chipname(uint chipid, char *buf, uint len) ++{ ++ const char *fmt; ++ ++ fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x"; ++ snprintf(buf, len, fmt, chipid); ++ return buf; ++} ++ ++static void brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus, ++ u32 drivestrength) { ++ struct sdiod_drive_str *str_tab = NULL; ++ u32 str_mask = 0; ++ u32 str_shift = 0; ++ char chn[8]; ++ ++ if (!(bus->ci->cccaps & CC_CAP_PMU)) ++ return; ++ ++ switch (SDIOD_DRVSTR_KEY(bus->ci->chip, bus->ci->pmurev)) { ++ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1): ++ str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1; ++ str_mask = 0x30000000; ++ str_shift = 28; ++ break; ++ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2): ++ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3): ++ str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2; ++ str_mask = 0x00003800; ++ str_shift = 11; ++ break; ++ case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8): ++ str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3; ++ str_mask = 0x00003800; ++ str_shift = 11; ++ break; ++ default: ++ brcmf_dbg(ERROR, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", ++ brcmf_chipname(bus->ci->chip, chn, 8), ++ bus->ci->chiprev, bus->ci->pmurev); ++ break; ++ } ++ ++ if (str_tab != NULL) { ++ u32 drivestrength_sel = 0; ++ u32 cc_data_temp; ++ int i; ++ ++ for (i = 0; str_tab[i].strength != 0; i++) { ++ if (drivestrength >= str_tab[i].strength) { ++ drivestrength_sel = str_tab[i].sel; ++ break; ++ } ++ } ++ ++ brcmf_sdcard_reg_write(bus->sdiodev, ++ CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), ++ 4, 1); ++ cc_data_temp = brcmf_sdcard_reg_read(bus->sdiodev, ++ CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), 4); ++ cc_data_temp &= ~str_mask; ++ drivestrength_sel <<= str_shift; ++ cc_data_temp |= drivestrength_sel; ++ brcmf_sdcard_reg_write(bus->sdiodev, ++ CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), ++ 4, cc_data_temp); ++ ++ brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n", ++ drivestrength, cc_data_temp); ++ } ++} ++ ++static int ++brcmf_sdbrcm_chip_recognition(struct brcmf_sdio_dev *sdiodev, ++ struct chip_info *ci, u32 regs) ++{ ++ u32 regdata; ++ ++ /* ++ * Get CC core rev ++ * Chipid is assume to be at offset 0 from regs arg ++ * For different chiptypes or old sdio hosts w/o chipcommon, ++ * other ways of recognition should be added here. ++ */ ++ ci->cccorebase = regs; ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_CC_REG(ci->cccorebase, chipid), 4); ++ ci->chip = regdata & CID_ID_MASK; ++ ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; ++ ++ brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev); ++ ++ /* Address of cores for new chips should be added here */ ++ switch (ci->chip) { ++ case BCM4329_CHIP_ID: ++ ci->buscorebase = BCM4329_CORE_BUS_BASE; ++ ci->ramcorebase = BCM4329_CORE_SOCRAM_BASE; ++ ci->armcorebase = BCM4329_CORE_ARM_BASE; ++ ci->ramsize = BCM4329_RAMSIZE; ++ break; ++ default: ++ brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip); ++ return -ENODEV; ++ } ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(ci->cccorebase, sbidhigh), 4); ++ ci->ccrev = SBCOREREV(regdata); ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_CC_REG(ci->cccorebase, pmucapabilities), 4); ++ ci->pmurev = regdata & PCAP_REV_MASK; ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(ci->buscorebase, sbidhigh), 4); ++ ci->buscorerev = SBCOREREV(regdata); ++ ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT; ++ ++ brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n", ++ ci->ccrev, ci->pmurev, ci->buscorerev, ci->buscoretype); ++ ++ /* get chipcommon capabilites */ ++ ci->cccaps = brcmf_sdcard_reg_read(sdiodev, ++ CORE_CC_REG(ci->cccorebase, capabilities), 4); ++ ++ return 0; ++} ++ ++static int ++brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs) ++{ ++ struct chip_info *ci; ++ int err; ++ u8 clkval, clkset; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* alloc chip_info_t */ ++ ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC); ++ if (NULL == ci) ++ return -ENOMEM; ++ ++ /* bus/core/clk setup for register access */ ++ /* Try forcing SDIO core to do ALPAvail request only */ ++ clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); ++ if (err) { ++ brcmf_dbg(ERROR, "error writing for HT off\n"); ++ goto fail; ++ } ++ ++ /* If register supported, wait for ALPAvail and then force ALP */ ++ /* This may take up to 15 milliseconds */ ++ clkval = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, NULL); ++ if ((clkval & ~SBSDIO_AVBITS) == clkset) { ++ SPINWAIT(((clkval = ++ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, ++ NULL)), ++ !SBSDIO_ALPAV(clkval)), ++ PMU_MAX_TRANSITION_DLY); ++ if (!SBSDIO_ALPAV(clkval)) { ++ brcmf_dbg(ERROR, "timeout on ALPAV wait, clkval 0x%02x\n", ++ clkval); ++ err = -EBUSY; ++ goto fail; ++ } ++ clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | ++ SBSDIO_FORCE_ALP; ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, ++ clkset, &err); ++ udelay(65); ++ } else { ++ brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n", ++ clkset, clkval); ++ err = -EACCES; ++ goto fail; ++ } ++ ++ /* Also, disable the extra SDIO pull-ups */ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); ++ ++ err = brcmf_sdbrcm_chip_recognition(bus->sdiodev, ci, regs); ++ if (err) ++ goto fail; ++ ++ /* ++ * Make sure any on-chip ARM is off (in case strapping is wrong), ++ * or downloaded code was already running. ++ */ ++ brcmf_sdbrcm_chip_disablecore(bus->sdiodev, ci->armcorebase); ++ ++ brcmf_sdcard_reg_write(bus->sdiodev, ++ CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0); ++ brcmf_sdcard_reg_write(bus->sdiodev, ++ CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0); ++ ++ /* Disable F2 to clear any intermediate frame state on the dongle */ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, ++ SDIO_FUNC_ENABLE_1, NULL); ++ ++ /* WAR: cmd52 backplane read so core HW will drop ALPReq */ ++ clkval = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ 0, NULL); ++ ++ /* Done with backplane-dependent accesses, can drop clock... */ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); ++ ++ bus->ci = ci; ++ return 0; ++fail: ++ bus->ci = NULL; ++ kfree(ci); ++ return err; ++} ++ ++static bool ++brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva) ++{ ++ u8 clkctl = 0; ++ int err = 0; ++ int reg_addr; ++ u32 reg_val; ++ ++ bus->alp_only = true; ++ ++ /* Return the window to backplane enumeration space for core access */ ++ if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, SI_ENUM_BASE)) ++ brcmf_dbg(ERROR, "FAILED to return to SI_ENUM_BASE\n"); ++ ++#ifdef BCMDBG ++ printk(KERN_DEBUG "F1 signature read @0x18000000=0x%4x\n", ++ brcmf_sdcard_reg_read(bus->sdiodev, SI_ENUM_BASE, 4)); ++ ++#endif /* BCMDBG */ ++ ++ /* ++ * Force PLL off until brcmf_sdbrcm_chip_attach() ++ * programs PLL control regs ++ */ ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, ++ BRCMF_INIT_CLKCTL1, &err); ++ if (!err) ++ clkctl = ++ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ ++ if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) { ++ brcmf_dbg(ERROR, "ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n", ++ err, BRCMF_INIT_CLKCTL1, clkctl); ++ goto fail; ++ } ++ ++ if (brcmf_sdbrcm_chip_attach(bus, regsva)) { ++ brcmf_dbg(ERROR, "brcmf_sdbrcm_chip_attach failed!\n"); ++ goto fail; ++ } ++ ++ if (!brcmf_sdbrcm_chipmatch((u16) bus->ci->chip)) { ++ brcmf_dbg(ERROR, "unsupported chip: 0x%04x\n", bus->ci->chip); ++ goto fail; ++ } ++ ++ brcmf_sdbrcm_sdiod_drive_strength_init(bus, SDIO_DRIVE_STRENGTH); ++ ++ /* Get info on the ARM and SOCRAM cores... */ ++ brcmf_sdcard_reg_read(bus->sdiodev, ++ CORE_SB(bus->ci->armcorebase, sbidhigh), 4); ++ bus->ramsize = bus->ci->ramsize; ++ if (!(bus->ramsize)) { ++ brcmf_dbg(ERROR, "failed to find SOCRAM memory!\n"); ++ goto fail; ++ } ++ ++ /* Set core control so an SDIO reset does a backplane reset */ ++ reg_addr = bus->ci->buscorebase + ++ offsetof(struct sdpcmd_regs, corecontrol); ++ reg_val = brcmf_sdcard_reg_read(bus->sdiodev, reg_addr, sizeof(u32)); ++ brcmf_sdcard_reg_write(bus->sdiodev, reg_addr, sizeof(u32), ++ reg_val | CC_BPRESEN); ++ ++ brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN); ++ ++ /* Locate an appropriately-aligned portion of hdrbuf */ ++ bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0], ++ BRCMF_SDALIGN); ++ ++ /* Set the poll and/or interrupt flags */ ++ bus->intr = true; ++ bus->poll = false; ++ if (bus->poll) ++ bus->pollrate = 1; ++ ++ return true; ++ ++fail: ++ return false; ++} ++ ++static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Disable F2 to clear any intermediate frame state on the dongle */ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, ++ SDIO_FUNC_ENABLE_1, NULL); ++ ++ bus->drvr->busstate = BRCMF_BUS_DOWN; ++ bus->sleeping = false; ++ bus->rxflow = false; ++ ++ /* Done with backplane-dependent accesses, can drop clock... */ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); ++ ++ /* ...and initialize clock/power states */ ++ bus->clkstate = CLK_SDONLY; ++ bus->idletime = BRCMF_IDLE_INTERVAL; ++ bus->idleclock = BRCMF_IDLE_ACTIVE; ++ ++ /* Query the F2 block size, set roundup accordingly */ ++ bus->blocksize = bus->sdiodev->func[2]->cur_blksize; ++ bus->roundup = min(max_roundup, bus->blocksize); ++ ++ /* bus module does not support packet chaining */ ++ bus->use_rxchain = false; ++ bus->sd_rxchain = false; ++ ++ return true; ++} ++ ++static int ++brcmf_sdbrcm_watchdog_thread(void *data) ++{ ++ struct brcmf_bus *bus = (struct brcmf_bus *)data; ++ ++ allow_signal(SIGTERM); ++ /* Run until signal received */ ++ while (1) { ++ if (kthread_should_stop()) ++ break; ++ if (!wait_for_completion_interruptible(&bus->watchdog_wait)) { ++ brcmf_sdbrcm_bus_watchdog(bus->drvr); ++ /* Count the tick for reference */ ++ bus->drvr->tickcnt++; ++ } else ++ break; ++ } ++ return 0; ++} ++ ++static void ++brcmf_sdbrcm_watchdog(unsigned long data) ++{ ++ struct brcmf_bus *bus = (struct brcmf_bus *)data; ++ ++ if (bus->watchdog_tsk) { ++ complete(&bus->watchdog_wait); ++ /* Reschedule the watchdog */ ++ if (bus->wd_timer_valid) ++ mod_timer(&bus->timer, ++ jiffies + BRCMF_WD_POLL_MS * HZ / 1000); ++ } ++} ++ ++static void ++brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ kfree(bus->ci); ++ bus->ci = NULL; ++} ++ ++static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (bus->ci) { ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); ++ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); ++ brcmf_sdbrcm_chip_detach(bus); ++ if (bus->vars && bus->varsz) ++ kfree(bus->vars); ++ bus->vars = NULL; ++ } ++ ++ brcmf_dbg(TRACE, "Disconnected\n"); ++} ++ ++/* Detach and free everything */ ++static void brcmf_sdbrcm_release(struct brcmf_bus *bus) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (bus) { ++ /* De-register interrupt handler */ ++ brcmf_sdcard_intr_dereg(bus->sdiodev); ++ ++ if (bus->drvr) { ++ brcmf_detach(bus->drvr); ++ brcmf_sdbrcm_release_dongle(bus); ++ bus->drvr = NULL; ++ } ++ ++ brcmf_sdbrcm_release_malloc(bus); ++ ++ kfree(bus); ++ } ++ ++ brcmf_dbg(TRACE, "Disconnected\n"); ++} ++ ++void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype, ++ u32 regsva, struct brcmf_sdio_dev *sdiodev) ++{ ++ int ret; ++ struct brcmf_bus *bus; ++ ++ /* Init global variables at run-time, not as part of the declaration. ++ * This is required to support init/de-init of the driver. ++ * Initialization ++ * of globals as part of the declaration results in non-deterministic ++ * behavior since the value of the globals may be different on the ++ * first time that the driver is initialized vs subsequent ++ * initializations. ++ */ ++ brcmf_c_init(); ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* We make an assumption about address window mappings: ++ * regsva == SI_ENUM_BASE*/ ++ ++ /* Allocate private bus interface state */ ++ bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC); ++ if (!bus) ++ goto fail; ++ ++ bus->sdiodev = sdiodev; ++ sdiodev->bus = bus; ++ bus->txbound = BRCMF_TXBOUND; ++ bus->rxbound = BRCMF_RXBOUND; ++ bus->txminmax = BRCMF_TXMINMAX; ++ bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1; ++ bus->usebufpool = false; /* Use bufpool if allocated, ++ else use locally malloced rxbuf */ ++ ++ /* attempt to attach to the dongle */ ++ if (!(brcmf_sdbrcm_probe_attach(bus, regsva))) { ++ brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_attach failed\n"); ++ goto fail; ++ } ++ ++ spin_lock_init(&bus->txqlock); ++ init_waitqueue_head(&bus->ctrl_wait); ++ init_waitqueue_head(&bus->dcmd_resp_wait); ++ ++ /* Set up the watchdog timer */ ++ init_timer(&bus->timer); ++ bus->timer.data = (unsigned long)bus; ++ bus->timer.function = brcmf_sdbrcm_watchdog; ++ ++ /* Initialize thread based operation and lock */ ++ sema_init(&bus->sdsem, 1); ++ ++ /* Initialize watchdog thread */ ++ init_completion(&bus->watchdog_wait); ++ bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread, ++ bus, "brcmf_watchdog"); ++ if (IS_ERR(bus->watchdog_tsk)) { ++ printk(KERN_WARNING ++ "brcmf_watchdog thread failed to start\n"); ++ bus->watchdog_tsk = NULL; ++ } ++ /* Initialize DPC thread */ ++ init_completion(&bus->dpc_wait); ++ bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread, ++ bus, "brcmf_dpc"); ++ if (IS_ERR(bus->dpc_tsk)) { ++ printk(KERN_WARNING ++ "brcmf_dpc thread failed to start\n"); ++ bus->dpc_tsk = NULL; ++ } ++ ++ /* Attach to the brcmf/OS/network interface */ ++ bus->drvr = brcmf_attach(bus, SDPCM_RESERVE); ++ if (!bus->drvr) { ++ brcmf_dbg(ERROR, "brcmf_attach failed\n"); ++ goto fail; ++ } ++ ++ /* Allocate buffers */ ++ if (!(brcmf_sdbrcm_probe_malloc(bus))) { ++ brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_malloc failed\n"); ++ goto fail; ++ } ++ ++ if (!(brcmf_sdbrcm_probe_init(bus))) { ++ brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_init failed\n"); ++ goto fail; ++ } ++ ++ /* Register interrupt callback, but mask it (not operational yet). */ ++ brcmf_dbg(INTR, "disable SDIO interrupts (not interested yet)\n"); ++ ret = brcmf_sdcard_intr_reg(bus->sdiodev); ++ if (ret != 0) { ++ brcmf_dbg(ERROR, "FAILED: sdcard_intr_reg returned %d\n", ret); ++ goto fail; ++ } ++ brcmf_dbg(INTR, "registered SDIO interrupt function ok\n"); ++ ++ brcmf_dbg(INFO, "completed!!\n"); ++ ++ /* if firmware path present try to download and bring up bus */ ++ ret = brcmf_bus_start(bus->drvr); ++ if (ret != 0) { ++ if (ret == -ENOLINK) { ++ brcmf_dbg(ERROR, "dongle is not responding\n"); ++ goto fail; ++ } ++ } ++ /* Ok, have the per-port tell the stack we're open for business */ ++ if (brcmf_net_attach(bus->drvr, 0) != 0) { ++ brcmf_dbg(ERROR, "Net attach failed!!\n"); ++ goto fail; ++ } ++ ++ return bus; ++ ++fail: ++ brcmf_sdbrcm_release(bus); ++ return NULL; ++} ++ ++void brcmf_sdbrcm_disconnect(void *ptr) ++{ ++ struct brcmf_bus *bus = (struct brcmf_bus *)ptr; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (bus) ++ brcmf_sdbrcm_release(bus); ++ ++ brcmf_dbg(TRACE, "Disconnected\n"); ++} ++ ++struct device *brcmf_bus_get_device(struct brcmf_bus *bus) ++{ ++ return &bus->sdiodev->func[2]->dev; ++} ++ ++void ++brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick) ++{ ++ /* don't start the wd until fw is loaded */ ++ if (bus->drvr->busstate == BRCMF_BUS_DOWN) ++ return; ++ ++ /* Totally stop the timer */ ++ if (!wdtick && bus->wd_timer_valid == true) { ++ del_timer_sync(&bus->timer); ++ bus->wd_timer_valid = false; ++ bus->save_ms = wdtick; ++ return; ++ } ++ ++ if (wdtick) { ++ if (bus->save_ms != BRCMF_WD_POLL_MS) { ++ if (bus->wd_timer_valid == true) ++ /* Stop timer and restart at new value */ ++ del_timer_sync(&bus->timer); ++ ++ /* Create timer again when watchdog period is ++ dynamically changed or in the first instance ++ */ ++ bus->timer.expires = ++ jiffies + BRCMF_WD_POLL_MS * HZ / 1000; ++ add_timer(&bus->timer); ++ ++ } else { ++ /* Re arm the timer, at last watchdog period */ ++ mod_timer(&bus->timer, ++ jiffies + BRCMF_WD_POLL_MS * HZ / 1000); ++ } ++ ++ bus->wd_timer_valid = true; ++ bus->save_ms = wdtick; ++ } ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/Makefile.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/Makefile +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/Makefile.orig 2011-11-09 13:46:58.235800758 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/Makefile 2011-11-09 13:47:16.986566342 -0500 +@@ -0,0 +1,33 @@ ++# ++# Makefile fragment for Broadcom 802.11n Networking Device Driver ++# ++# Copyright (c) 2010 Broadcom Corporation ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ccflags-y += \ ++ -Idrivers/net/wireless/brcm80211/brcmfmac \ ++ -Idrivers/net/wireless/brcm80211/include ++ ++DHDOFILES = \ ++ wl_cfg80211.o \ ++ dhd_cdc.o \ ++ dhd_common.o \ ++ dhd_sdio.o \ ++ dhd_linux.o \ ++ bcmsdh.o \ ++ bcmsdh_sdmmc.o ++ ++obj-$(CONFIG_BRCMFMAC) += brcmfmac.o ++brcmfmac-objs += $(DHDOFILES) ++ccflags-y += -D__CHECK_ENDIAN__ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h.orig 2011-11-09 13:46:58.235800758 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h 2011-11-09 13:47:16.987566330 -0500 +@@ -0,0 +1,252 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_SDH_H_ ++#define _BRCM_SDH_H_ ++ ++#include ++ ++#define SDIO_FUNC_0 0 ++#define SDIO_FUNC_1 1 ++#define SDIO_FUNC_2 2 ++ ++#define SDIOD_FBR_SIZE 0x100 ++ ++/* io_en */ ++#define SDIO_FUNC_ENABLE_1 0x02 ++#define SDIO_FUNC_ENABLE_2 0x04 ++ ++/* io_rdys */ ++#define SDIO_FUNC_READY_1 0x02 ++#define SDIO_FUNC_READY_2 0x04 ++ ++/* intr_status */ ++#define INTR_STATUS_FUNC1 0x2 ++#define INTR_STATUS_FUNC2 0x4 ++ ++/* Maximum number of I/O funcs */ ++#define SDIOD_MAX_IOFUNCS 7 ++ ++/* as of sdiod rev 0, supports 3 functions */ ++#define SBSDIO_NUM_FUNCTION 3 ++ ++/* function 1 miscellaneous registers */ ++ ++/* sprom command and status */ ++#define SBSDIO_SPROM_CS 0x10000 ++/* sprom info register */ ++#define SBSDIO_SPROM_INFO 0x10001 ++/* sprom indirect access data byte 0 */ ++#define SBSDIO_SPROM_DATA_LOW 0x10002 ++/* sprom indirect access data byte 1 */ ++#define SBSDIO_SPROM_DATA_HIGH 0x10003 ++/* sprom indirect access addr byte 0 */ ++#define SBSDIO_SPROM_ADDR_LOW 0x10004 ++/* sprom indirect access addr byte 0 */ ++#define SBSDIO_SPROM_ADDR_HIGH 0x10005 ++/* xtal_pu (gpio) output */ ++#define SBSDIO_CHIP_CTRL_DATA 0x10006 ++/* xtal_pu (gpio) enable */ ++#define SBSDIO_CHIP_CTRL_EN 0x10007 ++/* rev < 7, watermark for sdio device */ ++#define SBSDIO_WATERMARK 0x10008 ++/* control busy signal generation */ ++#define SBSDIO_DEVICE_CTL 0x10009 ++ ++/* SB Address Window Low (b15) */ ++#define SBSDIO_FUNC1_SBADDRLOW 0x1000A ++/* SB Address Window Mid (b23:b16) */ ++#define SBSDIO_FUNC1_SBADDRMID 0x1000B ++/* SB Address Window High (b31:b24) */ ++#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C ++/* Frame Control (frame term/abort) */ ++#define SBSDIO_FUNC1_FRAMECTRL 0x1000D ++/* ChipClockCSR (ALP/HT ctl/status) */ ++#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E ++/* SdioPullUp (on cmd, d0-d2) */ ++#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F ++/* Write Frame Byte Count Low */ ++#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019 ++/* Write Frame Byte Count High */ ++#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A ++/* Read Frame Byte Count Low */ ++#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B ++/* Read Frame Byte Count High */ ++#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C ++ ++#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */ ++#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */ ++ ++/* function 1 OCP space */ ++ ++/* sb offset addr is <= 15 bits, 32k */ ++#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF ++#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000 ++/* with b15, maps to 32-bit SB access */ ++#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 ++ ++/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */ ++ ++#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */ ++#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */ ++#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */ ++/* Address bits from SBADDR regs */ ++#define SBSDIO_SBWINDOW_MASK 0xffff8000 ++ ++#define SDIOH_READ 0 /* Read request */ ++#define SDIOH_WRITE 1 /* Write request */ ++ ++#define SDIOH_DATA_FIX 0 /* Fixed addressing */ ++#define SDIOH_DATA_INC 1 /* Incremental addressing */ ++ ++/* internal return code */ ++#define SUCCESS 0 ++#define ERROR 1 ++ ++struct brcmf_sdreg { ++ int func; ++ int offset; ++ int value; ++}; ++ ++struct brcmf_sdio_dev { ++ struct sdio_func *func[SDIO_MAX_FUNCS]; ++ u8 num_funcs; /* Supported funcs on client */ ++ u32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; ++ u32 sbwad; /* Save backplane window address */ ++ bool regfail; /* status of last reg_r/w call */ ++ void *bus; ++ atomic_t suspend; /* suspend flag */ ++ wait_queue_head_t request_byte_wait; ++ wait_queue_head_t request_word_wait; ++ wait_queue_head_t request_packet_wait; ++ wait_queue_head_t request_buffer_wait; ++ ++}; ++ ++/* Register/deregister device interrupt handler. */ ++extern int ++brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev); ++ ++extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev); ++ ++/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface). ++ * fn: function number ++ * addr: unmodified SDIO-space address ++ * data: data byte to write ++ * err: pointer to error code (or NULL) ++ */ ++extern u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint func, ++ u32 addr, int *err); ++extern void brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint func, ++ u32 addr, u8 data, int *err); ++ ++/* Synchronous access to device (client) core registers via CMD53 to F1. ++ * addr: backplane address (i.e. >= regsva from attach) ++ * size: register width in bytes (2 or 4) ++ * data: data for register write ++ */ ++extern u32 ++brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size); ++ ++extern u32 ++brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size, ++ u32 data); ++ ++/* Indicate if last reg read/write failed */ ++extern bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev); ++ ++/* Buffer transfer to/from device (client) core via cmd53. ++ * fn: function number ++ * addr: backplane address (i.e. >= regsva from attach) ++ * flags: backplane width, address increment, sync/async ++ * buf: pointer to memory data buffer ++ * nbytes: number of bytes to transfer to/from buf ++ * pkt: pointer to packet associated with buf (if any) ++ * complete: callback function for command completion (async only) ++ * handle: handle for completion callback (first arg in callback) ++ * Returns 0 or error code. ++ * NOTE: Async operation is not currently supported. ++ */ ++extern int ++brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ++ uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt); ++extern int ++brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ++ uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt); ++ ++/* Flags bits */ ++ ++/* Four-byte target (backplane) width (vs. two-byte) */ ++#define SDIO_REQ_4BYTE 0x1 ++/* Fixed address (FIFO) (vs. incrementing address) */ ++#define SDIO_REQ_FIXED 0x2 ++/* Async request (vs. sync request) */ ++#define SDIO_REQ_ASYNC 0x4 ++ ++/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only). ++ * rw: read or write (0/1) ++ * addr: direct SDIO address ++ * buf: pointer to memory data buffer ++ * nbytes: number of bytes to transfer to/from buf ++ * Returns 0 or error code. ++ */ ++extern int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, ++ u32 addr, u8 *buf, uint nbytes); ++ ++/* Issue an abort to the specified function */ ++extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn); ++ ++/* platform specific/high level functions */ ++extern int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev); ++extern int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev); ++ ++extern int brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, ++ u32 address); ++ ++/* attach, return handler on success, NULL if failed. ++ * The handler shall be provided by all subsequent calls. No local cache ++ * cfghdl points to the starting address of pci device mapped memory ++ */ ++extern int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev); ++extern void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev); ++ ++/* read or write one byte using cmd52 */ ++extern int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, ++ uint fnc, uint addr, u8 *byte); ++ ++/* read or write 2/4 bytes using cmd53 */ ++extern int ++brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, ++ uint rw, uint fnc, uint addr, ++ u32 *word, uint nbyte); ++ ++/* read or write any buffer using cmd53 */ ++extern int ++brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, ++ uint fix_inc, uint rw, uint fnc_num, ++ u32 addr, uint regwidth, ++ u32 buflen, u8 *buffer, struct sk_buff *pkt); ++ ++/* Watchdog timer interface for pm ops */ ++extern void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, ++ bool enable); ++ ++extern void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype, ++ u32 regsva, struct brcmf_sdio_dev *sdiodev); ++extern void brcmf_sdbrcm_disconnect(void *ptr); ++extern void brcmf_sdbrcm_isr(void *arg); ++#endif /* _BRCM_SDH_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c.orig 2011-11-09 13:46:58.237800734 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c 2011-11-09 13:47:16.989566304 -0500 +@@ -0,0 +1,3868 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include "dhd.h" ++#include "wl_cfg80211.h" ++ ++#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \ ++ (sizeof(struct brcmf_assoc_params_le) - sizeof(u16)) ++ ++static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255}; ++ ++static u32 brcmf_dbg_level = WL_DBG_ERR; ++ ++static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data) ++{ ++ dev->driver_data = data; ++} ++ ++static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev) ++{ ++ void *data = NULL; ++ ++ if (dev) ++ data = dev->driver_data; ++ return data; ++} ++ ++static ++struct brcmf_cfg80211_priv *brcmf_priv_get(struct brcmf_cfg80211_dev *cfg_dev) ++{ ++ struct brcmf_cfg80211_iface *ci = brcmf_get_drvdata(cfg_dev); ++ return ci->cfg_priv; ++} ++ ++static bool check_sys_up(struct wiphy *wiphy) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) { ++ WL_INFO("device is not ready : status (%d)\n", ++ (int)cfg_priv->status); ++ return false; ++ } ++ return true; ++} ++ ++#define CHAN2G(_channel, _freq, _flags) { \ ++ .band = IEEE80211_BAND_2GHZ, \ ++ .center_freq = (_freq), \ ++ .hw_value = (_channel), \ ++ .flags = (_flags), \ ++ .max_antenna_gain = 0, \ ++ .max_power = 30, \ ++} ++ ++#define CHAN5G(_channel, _flags) { \ ++ .band = IEEE80211_BAND_5GHZ, \ ++ .center_freq = 5000 + (5 * (_channel)), \ ++ .hw_value = (_channel), \ ++ .flags = (_flags), \ ++ .max_antenna_gain = 0, \ ++ .max_power = 30, \ ++} ++ ++#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2) ++#define RATETAB_ENT(_rateid, _flags) \ ++ { \ ++ .bitrate = RATE_TO_BASE100KBPS(_rateid), \ ++ .hw_value = (_rateid), \ ++ .flags = (_flags), \ ++ } ++ ++static struct ieee80211_rate __wl_rates[] = { ++ RATETAB_ENT(BRCM_RATE_1M, 0), ++ RATETAB_ENT(BRCM_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATETAB_ENT(BRCM_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATETAB_ENT(BRCM_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATETAB_ENT(BRCM_RATE_6M, 0), ++ RATETAB_ENT(BRCM_RATE_9M, 0), ++ RATETAB_ENT(BRCM_RATE_12M, 0), ++ RATETAB_ENT(BRCM_RATE_18M, 0), ++ RATETAB_ENT(BRCM_RATE_24M, 0), ++ RATETAB_ENT(BRCM_RATE_36M, 0), ++ RATETAB_ENT(BRCM_RATE_48M, 0), ++ RATETAB_ENT(BRCM_RATE_54M, 0), ++}; ++ ++#define wl_a_rates (__wl_rates + 4) ++#define wl_a_rates_size 8 ++#define wl_g_rates (__wl_rates + 0) ++#define wl_g_rates_size 12 ++ ++static struct ieee80211_channel __wl_2ghz_channels[] = { ++ CHAN2G(1, 2412, 0), ++ CHAN2G(2, 2417, 0), ++ CHAN2G(3, 2422, 0), ++ CHAN2G(4, 2427, 0), ++ CHAN2G(5, 2432, 0), ++ CHAN2G(6, 2437, 0), ++ CHAN2G(7, 2442, 0), ++ CHAN2G(8, 2447, 0), ++ CHAN2G(9, 2452, 0), ++ CHAN2G(10, 2457, 0), ++ CHAN2G(11, 2462, 0), ++ CHAN2G(12, 2467, 0), ++ CHAN2G(13, 2472, 0), ++ CHAN2G(14, 2484, 0), ++}; ++ ++static struct ieee80211_channel __wl_5ghz_a_channels[] = { ++ CHAN5G(34, 0), CHAN5G(36, 0), ++ CHAN5G(38, 0), CHAN5G(40, 0), ++ CHAN5G(42, 0), CHAN5G(44, 0), ++ CHAN5G(46, 0), CHAN5G(48, 0), ++ CHAN5G(52, 0), CHAN5G(56, 0), ++ CHAN5G(60, 0), CHAN5G(64, 0), ++ CHAN5G(100, 0), CHAN5G(104, 0), ++ CHAN5G(108, 0), CHAN5G(112, 0), ++ CHAN5G(116, 0), CHAN5G(120, 0), ++ CHAN5G(124, 0), CHAN5G(128, 0), ++ CHAN5G(132, 0), CHAN5G(136, 0), ++ CHAN5G(140, 0), CHAN5G(149, 0), ++ CHAN5G(153, 0), CHAN5G(157, 0), ++ CHAN5G(161, 0), CHAN5G(165, 0), ++ CHAN5G(184, 0), CHAN5G(188, 0), ++ CHAN5G(192, 0), CHAN5G(196, 0), ++ CHAN5G(200, 0), CHAN5G(204, 0), ++ CHAN5G(208, 0), CHAN5G(212, 0), ++ CHAN5G(216, 0), ++}; ++ ++static struct ieee80211_channel __wl_5ghz_n_channels[] = { ++ CHAN5G(32, 0), CHAN5G(34, 0), ++ CHAN5G(36, 0), CHAN5G(38, 0), ++ CHAN5G(40, 0), CHAN5G(42, 0), ++ CHAN5G(44, 0), CHAN5G(46, 0), ++ CHAN5G(48, 0), CHAN5G(50, 0), ++ CHAN5G(52, 0), CHAN5G(54, 0), ++ CHAN5G(56, 0), CHAN5G(58, 0), ++ CHAN5G(60, 0), CHAN5G(62, 0), ++ CHAN5G(64, 0), CHAN5G(66, 0), ++ CHAN5G(68, 0), CHAN5G(70, 0), ++ CHAN5G(72, 0), CHAN5G(74, 0), ++ CHAN5G(76, 0), CHAN5G(78, 0), ++ CHAN5G(80, 0), CHAN5G(82, 0), ++ CHAN5G(84, 0), CHAN5G(86, 0), ++ CHAN5G(88, 0), CHAN5G(90, 0), ++ CHAN5G(92, 0), CHAN5G(94, 0), ++ CHAN5G(96, 0), CHAN5G(98, 0), ++ CHAN5G(100, 0), CHAN5G(102, 0), ++ CHAN5G(104, 0), CHAN5G(106, 0), ++ CHAN5G(108, 0), CHAN5G(110, 0), ++ CHAN5G(112, 0), CHAN5G(114, 0), ++ CHAN5G(116, 0), CHAN5G(118, 0), ++ CHAN5G(120, 0), CHAN5G(122, 0), ++ CHAN5G(124, 0), CHAN5G(126, 0), ++ CHAN5G(128, 0), CHAN5G(130, 0), ++ CHAN5G(132, 0), CHAN5G(134, 0), ++ CHAN5G(136, 0), CHAN5G(138, 0), ++ CHAN5G(140, 0), CHAN5G(142, 0), ++ CHAN5G(144, 0), CHAN5G(145, 0), ++ CHAN5G(146, 0), CHAN5G(147, 0), ++ CHAN5G(148, 0), CHAN5G(149, 0), ++ CHAN5G(150, 0), CHAN5G(151, 0), ++ CHAN5G(152, 0), CHAN5G(153, 0), ++ CHAN5G(154, 0), CHAN5G(155, 0), ++ CHAN5G(156, 0), CHAN5G(157, 0), ++ CHAN5G(158, 0), CHAN5G(159, 0), ++ CHAN5G(160, 0), CHAN5G(161, 0), ++ CHAN5G(162, 0), CHAN5G(163, 0), ++ CHAN5G(164, 0), CHAN5G(165, 0), ++ CHAN5G(166, 0), CHAN5G(168, 0), ++ CHAN5G(170, 0), CHAN5G(172, 0), ++ CHAN5G(174, 0), CHAN5G(176, 0), ++ CHAN5G(178, 0), CHAN5G(180, 0), ++ CHAN5G(182, 0), CHAN5G(184, 0), ++ CHAN5G(186, 0), CHAN5G(188, 0), ++ CHAN5G(190, 0), CHAN5G(192, 0), ++ CHAN5G(194, 0), CHAN5G(196, 0), ++ CHAN5G(198, 0), CHAN5G(200, 0), ++ CHAN5G(202, 0), CHAN5G(204, 0), ++ CHAN5G(206, 0), CHAN5G(208, 0), ++ CHAN5G(210, 0), CHAN5G(212, 0), ++ CHAN5G(214, 0), CHAN5G(216, 0), ++ CHAN5G(218, 0), CHAN5G(220, 0), ++ CHAN5G(222, 0), CHAN5G(224, 0), ++ CHAN5G(226, 0), CHAN5G(228, 0), ++}; ++ ++static struct ieee80211_supported_band __wl_band_2ghz = { ++ .band = IEEE80211_BAND_2GHZ, ++ .channels = __wl_2ghz_channels, ++ .n_channels = ARRAY_SIZE(__wl_2ghz_channels), ++ .bitrates = wl_g_rates, ++ .n_bitrates = wl_g_rates_size, ++}; ++ ++static struct ieee80211_supported_band __wl_band_5ghz_a = { ++ .band = IEEE80211_BAND_5GHZ, ++ .channels = __wl_5ghz_a_channels, ++ .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels), ++ .bitrates = wl_a_rates, ++ .n_bitrates = wl_a_rates_size, ++}; ++ ++static struct ieee80211_supported_band __wl_band_5ghz_n = { ++ .band = IEEE80211_BAND_5GHZ, ++ .channels = __wl_5ghz_n_channels, ++ .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels), ++ .bitrates = wl_a_rates, ++ .n_bitrates = wl_a_rates_size, ++}; ++ ++static const u32 __wl_cipher_suites[] = { ++ WLAN_CIPHER_SUITE_WEP40, ++ WLAN_CIPHER_SUITE_WEP104, ++ WLAN_CIPHER_SUITE_TKIP, ++ WLAN_CIPHER_SUITE_CCMP, ++ WLAN_CIPHER_SUITE_AES_CMAC, ++}; ++ ++/* tag_ID/length/value_buffer tuple */ ++struct brcmf_tlv { ++ u8 id; ++ u8 len; ++ u8 data[1]; ++}; ++ ++/* Quarter dBm units to mW ++ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 ++ * Table is offset so the last entry is largest mW value that fits in ++ * a u16. ++ */ ++ ++#define QDBM_OFFSET 153 /* Offset for first entry */ ++#define QDBM_TABLE_LEN 40 /* Table size */ ++ ++/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. ++ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 ++ */ ++#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */ ++ ++/* Largest mW value that will round down to the last table entry, ++ * QDBM_OFFSET + QDBM_TABLE_LEN-1. ++ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + ++ * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. ++ */ ++#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ ++ ++static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = { ++/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ ++/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, ++/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, ++/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, ++/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, ++/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 ++}; ++ ++static u16 brcmf_qdbm_to_mw(u8 qdbm) ++{ ++ uint factor = 1; ++ int idx = qdbm - QDBM_OFFSET; ++ ++ if (idx >= QDBM_TABLE_LEN) ++ /* clamp to max u16 mW value */ ++ return 0xFFFF; ++ ++ /* scale the qdBm index up to the range of the table 0-40 ++ * where an offset of 40 qdBm equals a factor of 10 mW. ++ */ ++ while (idx < 0) { ++ idx += 40; ++ factor *= 10; ++ } ++ ++ /* return the mW value scaled down to the correct factor of 10, ++ * adding in factor/2 to get proper rounding. ++ */ ++ return (nqdBm_to_mW_map[idx] + factor / 2) / factor; ++} ++ ++static u8 brcmf_mw_to_qdbm(u16 mw) ++{ ++ u8 qdbm; ++ int offset; ++ uint mw_uint = mw; ++ uint boundary; ++ ++ /* handle boundary case */ ++ if (mw_uint <= 1) ++ return 0; ++ ++ offset = QDBM_OFFSET; ++ ++ /* move mw into the range of the table */ ++ while (mw_uint < QDBM_TABLE_LOW_BOUND) { ++ mw_uint *= 10; ++ offset -= 40; ++ } ++ ++ for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) { ++ boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] - ++ nqdBm_to_mW_map[qdbm]) / 2; ++ if (mw_uint < boundary) ++ break; ++ } ++ ++ qdbm += (u8) offset; ++ ++ return qdbm; ++} ++ ++/* function for reading/writing a single u32 from/to the dongle */ ++static int ++brcmf_exec_dcmd_u32(struct net_device *ndev, u32 cmd, u32 *par) ++{ ++ int err; ++ __le32 par_le = cpu_to_le32(*par); ++ ++ err = brcmf_exec_dcmd(ndev, cmd, &par_le, sizeof(__le32)); ++ *par = le32_to_cpu(par_le); ++ ++ return err; ++} ++ ++static void convert_key_from_CPU(struct brcmf_wsec_key *key, ++ struct brcmf_wsec_key_le *key_le) ++{ ++ key_le->index = cpu_to_le32(key->index); ++ key_le->len = cpu_to_le32(key->len); ++ key_le->algo = cpu_to_le32(key->algo); ++ key_le->flags = cpu_to_le32(key->flags); ++ key_le->rxiv.hi = cpu_to_le32(key->rxiv.hi); ++ key_le->rxiv.lo = cpu_to_le16(key->rxiv.lo); ++ key_le->iv_initialized = cpu_to_le32(key->iv_initialized); ++ memcpy(key_le->data, key->data, sizeof(key->data)); ++ memcpy(key_le->ea, key->ea, sizeof(key->ea)); ++} ++ ++static int send_key_to_dongle(struct net_device *ndev, ++ struct brcmf_wsec_key *key) ++{ ++ int err; ++ struct brcmf_wsec_key_le key_le; ++ ++ convert_key_from_CPU(key, &key_le); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le, sizeof(key_le)); ++ if (err) ++ WL_ERR("WLC_SET_KEY error (%d)\n", err); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, ++ enum nl80211_iftype type, u32 *flags, ++ struct vif_params *params) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct wireless_dev *wdev; ++ s32 infra = 0; ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ switch (type) { ++ case NL80211_IFTYPE_MONITOR: ++ case NL80211_IFTYPE_WDS: ++ WL_ERR("type (%d) : currently we do not support this type\n", ++ type); ++ return -EOPNOTSUPP; ++ case NL80211_IFTYPE_ADHOC: ++ cfg_priv->conf->mode = WL_MODE_IBSS; ++ infra = 0; ++ break; ++ case NL80211_IFTYPE_STATION: ++ cfg_priv->conf->mode = WL_MODE_BSS; ++ infra = 1; ++ break; ++ default: ++ err = -EINVAL; ++ goto done; ++ } ++ ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); ++ if (err) { ++ WL_ERR("WLC_SET_INFRA error (%d)\n", err); ++ err = -EAGAIN; ++ } else { ++ wdev = ndev->ieee80211_ptr; ++ wdev->iftype = type; ++ } ++ ++ WL_INFO("IF Type = %s\n", ++ (cfg_priv->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra"); ++ ++done: ++ WL_TRACE("Exit\n"); ++ ++ return err; ++} ++ ++static s32 brcmf_dev_intvar_set(struct net_device *ndev, s8 *name, s32 val) ++{ ++ s8 buf[BRCMF_DCMD_SMLEN]; ++ u32 len; ++ s32 err = 0; ++ __le32 val_le; ++ ++ val_le = cpu_to_le32(val); ++ len = brcmf_c_mkiovar(name, (char *)(&val_le), sizeof(val_le), buf, ++ sizeof(buf)); ++ BUG_ON(!len); ++ ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len); ++ if (err) ++ WL_ERR("error (%d)\n", err); ++ ++ return err; ++} ++ ++static s32 ++brcmf_dev_intvar_get(struct net_device *ndev, s8 *name, s32 *retval) ++{ ++ union { ++ s8 buf[BRCMF_DCMD_SMLEN]; ++ __le32 val; ++ } var; ++ u32 len; ++ u32 data_null; ++ s32 err = 0; ++ ++ len = ++ brcmf_c_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), ++ sizeof(var.buf)); ++ BUG_ON(!len); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, &var, len); ++ if (err) ++ WL_ERR("error (%d)\n", err); ++ ++ *retval = le32_to_cpu(var.val); ++ ++ return err; ++} ++ ++static void brcmf_set_mpc(struct net_device *ndev, int mpc) ++{ ++ s32 err = 0; ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ ++ if (test_bit(WL_STATUS_READY, &cfg_priv->status)) { ++ err = brcmf_dev_intvar_set(ndev, "mpc", mpc); ++ if (err) { ++ WL_ERR("fail to set mpc\n"); ++ return; ++ } ++ WL_INFO("MPC : %d\n", mpc); ++ } ++} ++ ++static void wl_iscan_prep(struct brcmf_scan_params_le *params_le, ++ struct brcmf_ssid *ssid) ++{ ++ memcpy(params_le->bssid, ether_bcast, ETH_ALEN); ++ params_le->bss_type = DOT11_BSSTYPE_ANY; ++ params_le->scan_type = 0; ++ params_le->channel_num = 0; ++ params_le->nprobes = cpu_to_le32(-1); ++ params_le->active_time = cpu_to_le32(-1); ++ params_le->passive_time = cpu_to_le32(-1); ++ params_le->home_time = cpu_to_le32(-1); ++ if (ssid && ssid->SSID_len) ++ memcpy(¶ms_le->ssid_le, ssid, sizeof(struct brcmf_ssid)); ++} ++ ++static s32 ++brcmf_dev_iovar_setbuf(struct net_device *ndev, s8 * iovar, void *param, ++ s32 paramlen, void *bufptr, s32 buflen) ++{ ++ s32 iolen; ++ ++ iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen); ++ BUG_ON(!iolen); ++ ++ return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, bufptr, iolen); ++} ++ ++static s32 ++brcmf_dev_iovar_getbuf(struct net_device *ndev, s8 * iovar, void *param, ++ s32 paramlen, void *bufptr, s32 buflen) ++{ ++ s32 iolen; ++ ++ iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen); ++ BUG_ON(!iolen); ++ ++ return brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, bufptr, buflen); ++} ++ ++static s32 ++brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan, ++ struct brcmf_ssid *ssid, u16 action) ++{ ++ s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE + ++ offsetof(struct brcmf_iscan_params_le, params_le); ++ struct brcmf_iscan_params_le *params; ++ s32 err = 0; ++ ++ if (ssid && ssid->SSID_len) ++ params_size += sizeof(struct brcmf_ssid); ++ params = kzalloc(params_size, GFP_KERNEL); ++ if (!params) ++ return -ENOMEM; ++ BUG_ON(params_size >= BRCMF_DCMD_SMLEN); ++ ++ wl_iscan_prep(¶ms->params_le, ssid); ++ ++ params->version = cpu_to_le32(BRCMF_ISCAN_REQ_VERSION); ++ params->action = cpu_to_le16(action); ++ params->scan_duration = cpu_to_le16(0); ++ ++ err = brcmf_dev_iovar_setbuf(iscan->ndev, "iscan", params, params_size, ++ iscan->dcmd_buf, BRCMF_DCMD_SMLEN); ++ if (err) { ++ if (err == -EBUSY) ++ WL_INFO("system busy : iscan canceled\n"); ++ else ++ WL_ERR("error (%d)\n", err); ++ } ++ ++ kfree(params); ++ return err; ++} ++ ++static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); ++ struct net_device *ndev = cfg_to_ndev(cfg_priv); ++ struct brcmf_ssid ssid; ++ __le32 passive_scan; ++ s32 err = 0; ++ ++ /* Broadcast scan by default */ ++ memset(&ssid, 0, sizeof(ssid)); ++ ++ iscan->state = WL_ISCAN_STATE_SCANING; ++ ++ passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1); ++ err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN, ++ &passive_scan, sizeof(passive_scan)); ++ if (err) { ++ WL_ERR("error (%d)\n", err); ++ return err; ++ } ++ brcmf_set_mpc(ndev, 0); ++ cfg_priv->iscan_kickstart = true; ++ err = brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START); ++ if (err) { ++ brcmf_set_mpc(ndev, 1); ++ cfg_priv->iscan_kickstart = false; ++ return err; ++ } ++ mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); ++ iscan->timer_on = 1; ++ return err; ++} ++ ++static s32 ++__brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_scan_request *request, ++ struct cfg80211_ssid *this_ssid) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ struct cfg80211_ssid *ssids; ++ struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int; ++ __le32 passive_scan; ++ bool iscan_req; ++ bool spec_scan; ++ s32 err = 0; ++ u32 SSID_len; ++ ++ if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { ++ WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status); ++ return -EAGAIN; ++ } ++ if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) { ++ WL_ERR("Scanning being aborted : status (%lu)\n", ++ cfg_priv->status); ++ return -EAGAIN; ++ } ++ if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) { ++ WL_ERR("Connecting : status (%lu)\n", ++ cfg_priv->status); ++ return -EAGAIN; ++ } ++ ++ iscan_req = false; ++ spec_scan = false; ++ if (request) { ++ /* scan bss */ ++ ssids = request->ssids; ++ if (cfg_priv->iscan_on && (!ssids || !ssids->ssid_len)) ++ iscan_req = true; ++ } else { ++ /* scan in ibss */ ++ /* we don't do iscan in ibss */ ++ ssids = this_ssid; ++ } ++ ++ cfg_priv->scan_request = request; ++ set_bit(WL_STATUS_SCANNING, &cfg_priv->status); ++ if (iscan_req) { ++ err = brcmf_do_iscan(cfg_priv); ++ if (!err) ++ return err; ++ else ++ goto scan_out; ++ } else { ++ WL_SCAN("ssid \"%s\", ssid_len (%d)\n", ++ ssids->ssid, ssids->ssid_len); ++ memset(&sr->ssid_le, 0, sizeof(sr->ssid_le)); ++ SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len); ++ sr->ssid_le.SSID_len = cpu_to_le32(0); ++ if (SSID_len) { ++ memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len); ++ sr->ssid_le.SSID_len = cpu_to_le32(SSID_len); ++ spec_scan = true; ++ } else { ++ WL_SCAN("Broadcast scan\n"); ++ } ++ ++ passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN, ++ &passive_scan, sizeof(passive_scan)); ++ if (err) { ++ WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err); ++ goto scan_out; ++ } ++ brcmf_set_mpc(ndev, 0); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le, ++ sizeof(sr->ssid_le)); ++ if (err) { ++ if (err == -EBUSY) ++ WL_INFO("system busy : scan for \"%s\" " ++ "canceled\n", sr->ssid_le.SSID); ++ else ++ WL_ERR("WLC_SCAN error (%d)\n", err); ++ ++ brcmf_set_mpc(ndev, 1); ++ goto scan_out; ++ } ++ } ++ ++ return 0; ++ ++scan_out: ++ clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); ++ cfg_priv->scan_request = NULL; ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_scan_request *request) ++{ ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ err = __brcmf_cfg80211_scan(wiphy, ndev, request, NULL); ++ if (err) ++ WL_ERR("scan error (%d)\n", err); ++ ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold) ++{ ++ s32 err = 0; ++ ++ err = brcmf_dev_intvar_set(ndev, "rtsthresh", rts_threshold); ++ if (err) ++ WL_ERR("Error (%d)\n", err); ++ ++ return err; ++} ++ ++static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold) ++{ ++ s32 err = 0; ++ ++ err = brcmf_dev_intvar_set(ndev, "fragthresh", frag_threshold); ++ if (err) ++ WL_ERR("Error (%d)\n", err); ++ ++ return err; ++} ++ ++static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l) ++{ ++ s32 err = 0; ++ u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL); ++ ++ err = brcmf_exec_dcmd_u32(ndev, cmd, &retry); ++ if (err) { ++ WL_ERR("cmd (%d) , error (%d)\n", cmd, err); ++ return err; ++ } ++ return err; ++} ++ ++static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct net_device *ndev = cfg_to_ndev(cfg_priv); ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ if (changed & WIPHY_PARAM_RTS_THRESHOLD && ++ (cfg_priv->conf->rts_threshold != wiphy->rts_threshold)) { ++ cfg_priv->conf->rts_threshold = wiphy->rts_threshold; ++ err = brcmf_set_rts(ndev, cfg_priv->conf->rts_threshold); ++ if (!err) ++ goto done; ++ } ++ if (changed & WIPHY_PARAM_FRAG_THRESHOLD && ++ (cfg_priv->conf->frag_threshold != wiphy->frag_threshold)) { ++ cfg_priv->conf->frag_threshold = wiphy->frag_threshold; ++ err = brcmf_set_frag(ndev, cfg_priv->conf->frag_threshold); ++ if (!err) ++ goto done; ++ } ++ if (changed & WIPHY_PARAM_RETRY_LONG ++ && (cfg_priv->conf->retry_long != wiphy->retry_long)) { ++ cfg_priv->conf->retry_long = wiphy->retry_long; ++ err = brcmf_set_retry(ndev, cfg_priv->conf->retry_long, true); ++ if (!err) ++ goto done; ++ } ++ if (changed & WIPHY_PARAM_RETRY_SHORT ++ && (cfg_priv->conf->retry_short != wiphy->retry_short)) { ++ cfg_priv->conf->retry_short = wiphy->retry_short; ++ err = brcmf_set_retry(ndev, cfg_priv->conf->retry_short, false); ++ if (!err) ++ goto done; ++ } ++ ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item) ++{ ++ switch (item) { ++ case WL_PROF_SEC: ++ return &cfg_priv->profile->sec; ++ case WL_PROF_BSSID: ++ return &cfg_priv->profile->bssid; ++ case WL_PROF_SSID: ++ return &cfg_priv->profile->ssid; ++ } ++ WL_ERR("invalid item (%d)\n", item); ++ return NULL; ++} ++ ++static s32 ++brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv, ++ const struct brcmf_event_msg *e, void *data, s32 item) ++{ ++ s32 err = 0; ++ struct brcmf_ssid *ssid; ++ ++ switch (item) { ++ case WL_PROF_SSID: ++ ssid = (struct brcmf_ssid *) data; ++ memset(cfg_priv->profile->ssid.SSID, 0, ++ sizeof(cfg_priv->profile->ssid.SSID)); ++ memcpy(cfg_priv->profile->ssid.SSID, ++ ssid->SSID, ssid->SSID_len); ++ cfg_priv->profile->ssid.SSID_len = ssid->SSID_len; ++ break; ++ case WL_PROF_BSSID: ++ if (data) ++ memcpy(cfg_priv->profile->bssid, data, ETH_ALEN); ++ else ++ memset(cfg_priv->profile->bssid, 0, ETH_ALEN); ++ break; ++ case WL_PROF_SEC: ++ memcpy(&cfg_priv->profile->sec, data, ++ sizeof(cfg_priv->profile->sec)); ++ break; ++ case WL_PROF_BEACONINT: ++ cfg_priv->profile->beacon_interval = *(u16 *)data; ++ break; ++ case WL_PROF_DTIMPERIOD: ++ cfg_priv->profile->dtim_period = *(u8 *)data; ++ break; ++ default: ++ WL_ERR("unsupported item (%d)\n", item); ++ err = -EOPNOTSUPP; ++ break; ++ } ++ ++ return err; ++} ++ ++static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof) ++{ ++ memset(prof, 0, sizeof(*prof)); ++} ++ ++static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params, ++ size_t *join_params_size) ++{ ++ u16 chanspec = 0; ++ ++ if (ch != 0) { ++ if (ch <= CH_MAX_2G_CHANNEL) ++ chanspec |= WL_CHANSPEC_BAND_2G; ++ else ++ chanspec |= WL_CHANSPEC_BAND_5G; ++ ++ chanspec |= WL_CHANSPEC_BW_20; ++ chanspec |= WL_CHANSPEC_CTL_SB_NONE; ++ ++ *join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE + ++ sizeof(u16); ++ ++ chanspec |= (ch & WL_CHANSPEC_CHAN_MASK); ++ join_params->params_le.chanspec_list[0] = cpu_to_le16(chanspec); ++ join_params->params_le.chanspec_num = cpu_to_le32(1); ++ ++ WL_CONN("join_params->params.chanspec_list[0]= %#X," ++ "channel %d, chanspec %#X\n", ++ chanspec, ch, chanspec); ++ } ++} ++ ++static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct net_device *ndev = NULL; ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ ++ if (cfg_priv->link_up) { ++ ndev = cfg_to_ndev(cfg_priv); ++ WL_INFO("Call WLC_DISASSOC to stop excess roaming\n "); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, NULL, 0); ++ if (err) ++ WL_ERR("WLC_DISASSOC failed (%d)\n", err); ++ cfg_priv->link_up = false; ++ } ++ WL_TRACE("Exit\n"); ++} ++ ++static s32 ++brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_ibss_params *params) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct brcmf_join_params join_params; ++ size_t join_params_size = 0; ++ s32 err = 0; ++ s32 wsec = 0; ++ s32 bcnprd; ++ struct brcmf_ssid ssid; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ if (params->ssid) ++ WL_CONN("SSID: %s\n", params->ssid); ++ else { ++ WL_CONN("SSID: NULL, Not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ set_bit(WL_STATUS_CONNECTING, &cfg_priv->status); ++ ++ if (params->bssid) ++ WL_CONN("BSSID: %02X %02X %02X %02X %02X %02X\n", ++ params->bssid[0], params->bssid[1], params->bssid[2], ++ params->bssid[3], params->bssid[4], params->bssid[5]); ++ else ++ WL_CONN("No BSSID specified\n"); ++ ++ if (params->channel) ++ WL_CONN("channel: %d\n", params->channel->center_freq); ++ else ++ WL_CONN("no channel specified\n"); ++ ++ if (params->channel_fixed) ++ WL_CONN("fixed channel required\n"); ++ else ++ WL_CONN("no fixed channel required\n"); ++ ++ if (params->ie && params->ie_len) ++ WL_CONN("ie len: %d\n", params->ie_len); ++ else ++ WL_CONN("no ie specified\n"); ++ ++ if (params->beacon_interval) ++ WL_CONN("beacon interval: %d\n", params->beacon_interval); ++ else ++ WL_CONN("no beacon interval specified\n"); ++ ++ if (params->basic_rates) ++ WL_CONN("basic rates: %08X\n", params->basic_rates); ++ else ++ WL_CONN("no basic rates specified\n"); ++ ++ if (params->privacy) ++ WL_CONN("privacy required\n"); ++ else ++ WL_CONN("no privacy required\n"); ++ ++ /* Configure Privacy for starter */ ++ if (params->privacy) ++ wsec |= WEP_ENABLED; ++ ++ err = brcmf_dev_intvar_set(ndev, "wsec", wsec); ++ if (err) { ++ WL_ERR("wsec failed (%d)\n", err); ++ goto done; ++ } ++ ++ /* Configure Beacon Interval for starter */ ++ if (params->beacon_interval) ++ bcnprd = params->beacon_interval; ++ else ++ bcnprd = 100; ++ ++ err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_BCNPRD, &bcnprd); ++ if (err) { ++ WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err); ++ goto done; ++ } ++ ++ /* Configure required join parameter */ ++ memset(&join_params, 0, sizeof(struct brcmf_join_params)); ++ ++ /* SSID */ ++ ssid.SSID_len = min_t(u32, params->ssid_len, 32); ++ memcpy(ssid.SSID, params->ssid, ssid.SSID_len); ++ memcpy(join_params.ssid_le.SSID, params->ssid, ssid.SSID_len); ++ join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len); ++ join_params_size = sizeof(join_params.ssid_le); ++ brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID); ++ ++ /* BSSID */ ++ if (params->bssid) { ++ memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN); ++ join_params_size = sizeof(join_params.ssid_le) + ++ BRCMF_ASSOC_PARAMS_FIXED_SIZE; ++ } else { ++ memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN); ++ } ++ ++ brcmf_update_prof(cfg_priv, NULL, ++ &join_params.params_le.bssid, WL_PROF_BSSID); ++ ++ /* Channel */ ++ if (params->channel) { ++ u32 target_channel; ++ ++ cfg_priv->channel = ++ ieee80211_frequency_to_channel( ++ params->channel->center_freq); ++ if (params->channel_fixed) { ++ /* adding chanspec */ ++ brcmf_ch_to_chanspec(cfg_priv->channel, ++ &join_params, &join_params_size); ++ } ++ ++ /* set channel for starter */ ++ target_channel = cfg_priv->channel; ++ err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_CHANNEL, ++ &target_channel); ++ if (err) { ++ WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err); ++ goto done; ++ } ++ } else ++ cfg_priv->channel = 0; ++ ++ cfg_priv->ibss_starter = false; ++ ++ ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, ++ &join_params, join_params_size); ++ if (err) { ++ WL_ERR("WLC_SET_SSID failed (%d)\n", err); ++ goto done; ++ } ++ ++done: ++ if (err) ++ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ brcmf_link_down(cfg_priv); ++ ++ WL_TRACE("Exit\n"); ++ ++ return err; ++} ++ ++static s32 brcmf_set_wpa_version(struct net_device *ndev, ++ struct cfg80211_connect_params *sme) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ struct brcmf_cfg80211_security *sec; ++ s32 val = 0; ++ s32 err = 0; ++ ++ if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) ++ val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED; ++ else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) ++ val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; ++ else ++ val = WPA_AUTH_DISABLED; ++ WL_CONN("setting wpa_auth to 0x%0x\n", val); ++ err = brcmf_dev_intvar_set(ndev, "wpa_auth", val); ++ if (err) { ++ WL_ERR("set wpa_auth failed (%d)\n", err); ++ return err; ++ } ++ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); ++ sec->wpa_versions = sme->crypto.wpa_versions; ++ return err; ++} ++ ++static s32 brcmf_set_auth_type(struct net_device *ndev, ++ struct cfg80211_connect_params *sme) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ struct brcmf_cfg80211_security *sec; ++ s32 val = 0; ++ s32 err = 0; ++ ++ switch (sme->auth_type) { ++ case NL80211_AUTHTYPE_OPEN_SYSTEM: ++ val = 0; ++ WL_CONN("open system\n"); ++ break; ++ case NL80211_AUTHTYPE_SHARED_KEY: ++ val = 1; ++ WL_CONN("shared key\n"); ++ break; ++ case NL80211_AUTHTYPE_AUTOMATIC: ++ val = 2; ++ WL_CONN("automatic\n"); ++ break; ++ case NL80211_AUTHTYPE_NETWORK_EAP: ++ WL_CONN("network eap\n"); ++ default: ++ val = 2; ++ WL_ERR("invalid auth type (%d)\n", sme->auth_type); ++ break; ++ } ++ ++ err = brcmf_dev_intvar_set(ndev, "auth", val); ++ if (err) { ++ WL_ERR("set auth failed (%d)\n", err); ++ return err; ++ } ++ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); ++ sec->auth_type = sme->auth_type; ++ return err; ++} ++ ++static s32 ++brcmf_set_set_cipher(struct net_device *ndev, ++ struct cfg80211_connect_params *sme) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ struct brcmf_cfg80211_security *sec; ++ s32 pval = 0; ++ s32 gval = 0; ++ s32 err = 0; ++ ++ if (sme->crypto.n_ciphers_pairwise) { ++ switch (sme->crypto.ciphers_pairwise[0]) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ case WLAN_CIPHER_SUITE_WEP104: ++ pval = WEP_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ pval = TKIP_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ pval = AES_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ pval = AES_ENABLED; ++ break; ++ default: ++ WL_ERR("invalid cipher pairwise (%d)\n", ++ sme->crypto.ciphers_pairwise[0]); ++ return -EINVAL; ++ } ++ } ++ if (sme->crypto.cipher_group) { ++ switch (sme->crypto.cipher_group) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ case WLAN_CIPHER_SUITE_WEP104: ++ gval = WEP_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ gval = TKIP_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ gval = AES_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ gval = AES_ENABLED; ++ break; ++ default: ++ WL_ERR("invalid cipher group (%d)\n", ++ sme->crypto.cipher_group); ++ return -EINVAL; ++ } ++ } ++ ++ WL_CONN("pval (%d) gval (%d)\n", pval, gval); ++ err = brcmf_dev_intvar_set(ndev, "wsec", pval | gval); ++ if (err) { ++ WL_ERR("error (%d)\n", err); ++ return err; ++ } ++ ++ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); ++ sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0]; ++ sec->cipher_group = sme->crypto.cipher_group; ++ ++ return err; ++} ++ ++static s32 ++brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ struct brcmf_cfg80211_security *sec; ++ s32 val = 0; ++ s32 err = 0; ++ ++ if (sme->crypto.n_akm_suites) { ++ err = brcmf_dev_intvar_get(ndev, "wpa_auth", &val); ++ if (err) { ++ WL_ERR("could not get wpa_auth (%d)\n", err); ++ return err; ++ } ++ if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { ++ switch (sme->crypto.akm_suites[0]) { ++ case WLAN_AKM_SUITE_8021X: ++ val = WPA_AUTH_UNSPECIFIED; ++ break; ++ case WLAN_AKM_SUITE_PSK: ++ val = WPA_AUTH_PSK; ++ break; ++ default: ++ WL_ERR("invalid cipher group (%d)\n", ++ sme->crypto.cipher_group); ++ return -EINVAL; ++ } ++ } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { ++ switch (sme->crypto.akm_suites[0]) { ++ case WLAN_AKM_SUITE_8021X: ++ val = WPA2_AUTH_UNSPECIFIED; ++ break; ++ case WLAN_AKM_SUITE_PSK: ++ val = WPA2_AUTH_PSK; ++ break; ++ default: ++ WL_ERR("invalid cipher group (%d)\n", ++ sme->crypto.cipher_group); ++ return -EINVAL; ++ } ++ } ++ ++ WL_CONN("setting wpa_auth to %d\n", val); ++ err = brcmf_dev_intvar_set(ndev, "wpa_auth", val); ++ if (err) { ++ WL_ERR("could not set wpa_auth (%d)\n", err); ++ return err; ++ } ++ } ++ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); ++ sec->wpa_auth = sme->crypto.akm_suites[0]; ++ ++ return err; ++} ++ ++static s32 ++brcmf_set_wep_sharedkey(struct net_device *ndev, ++ struct cfg80211_connect_params *sme) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ struct brcmf_cfg80211_security *sec; ++ struct brcmf_wsec_key key; ++ s32 val; ++ s32 err = 0; ++ ++ WL_CONN("key len (%d)\n", sme->key_len); ++ ++ if (sme->key_len == 0) ++ return 0; ++ ++ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); ++ WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n", ++ sec->wpa_versions, sec->cipher_pairwise); ++ ++ if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) ++ return 0; ++ ++ if (sec->cipher_pairwise & ++ (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104)) { ++ memset(&key, 0, sizeof(key)); ++ key.len = (u32) sme->key_len; ++ key.index = (u32) sme->key_idx; ++ if (key.len > sizeof(key.data)) { ++ WL_ERR("Too long key length (%u)\n", key.len); ++ return -EINVAL; ++ } ++ memcpy(key.data, sme->key, key.len); ++ key.flags = BRCMF_PRIMARY_KEY; ++ switch (sec->cipher_pairwise) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ key.algo = CRYPTO_ALGO_WEP1; ++ break; ++ case WLAN_CIPHER_SUITE_WEP104: ++ key.algo = CRYPTO_ALGO_WEP128; ++ break; ++ default: ++ WL_ERR("Invalid algorithm (%d)\n", ++ sme->crypto.ciphers_pairwise[0]); ++ return -EINVAL; ++ } ++ /* Set the new key/index */ ++ WL_CONN("key length (%d) key index (%d) algo (%d)\n", ++ key.len, key.index, key.algo); ++ WL_CONN("key \"%s\"\n", key.data); ++ err = send_key_to_dongle(ndev, &key); ++ if (err) ++ return err; ++ ++ if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) { ++ WL_CONN("set auth_type to shared key\n"); ++ val = 1; /* shared key */ ++ err = brcmf_dev_intvar_set(ndev, "auth", val); ++ if (err) { ++ WL_ERR("set auth failed (%d)\n", err); ++ return err; ++ } ++ } ++ } ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_connect_params *sme) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct ieee80211_channel *chan = sme->channel; ++ struct brcmf_join_params join_params; ++ size_t join_params_size; ++ struct brcmf_ssid ssid; ++ ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ if (!sme->ssid) { ++ WL_ERR("Invalid ssid\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ set_bit(WL_STATUS_CONNECTING, &cfg_priv->status); ++ ++ if (chan) { ++ cfg_priv->channel = ++ ieee80211_frequency_to_channel(chan->center_freq); ++ WL_CONN("channel (%d), center_req (%d)\n", ++ cfg_priv->channel, chan->center_freq); ++ } else ++ cfg_priv->channel = 0; ++ ++ WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len); ++ ++ err = brcmf_set_wpa_version(ndev, sme); ++ if (err) { ++ WL_ERR("wl_set_wpa_version failed (%d)\n", err); ++ goto done; ++ } ++ ++ err = brcmf_set_auth_type(ndev, sme); ++ if (err) { ++ WL_ERR("wl_set_auth_type failed (%d)\n", err); ++ goto done; ++ } ++ ++ err = brcmf_set_set_cipher(ndev, sme); ++ if (err) { ++ WL_ERR("wl_set_set_cipher failed (%d)\n", err); ++ goto done; ++ } ++ ++ err = brcmf_set_key_mgmt(ndev, sme); ++ if (err) { ++ WL_ERR("wl_set_key_mgmt failed (%d)\n", err); ++ goto done; ++ } ++ ++ err = brcmf_set_wep_sharedkey(ndev, sme); ++ if (err) { ++ WL_ERR("brcmf_set_wep_sharedkey failed (%d)\n", err); ++ goto done; ++ } ++ ++ memset(&join_params, 0, sizeof(join_params)); ++ join_params_size = sizeof(join_params.ssid_le); ++ ++ ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), sme->ssid_len); ++ memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid.SSID_len); ++ memcpy(&ssid.SSID, sme->ssid, ssid.SSID_len); ++ join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len); ++ brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID); ++ ++ memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN); ++ ++ if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN) ++ WL_CONN("ssid \"%s\", len (%d)\n", ++ ssid.SSID, ssid.SSID_len); ++ ++ brcmf_ch_to_chanspec(cfg_priv->channel, ++ &join_params, &join_params_size); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, ++ &join_params, join_params_size); ++ if (err) ++ WL_ERR("WLC_SET_SSID failed (%d)\n", err); ++ ++done: ++ if (err) ++ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, ++ u16 reason_code) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct brcmf_scb_val_le scbval; ++ s32 err = 0; ++ ++ WL_TRACE("Enter. Reason code = %d\n", reason_code); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ clear_bit(WL_STATUS_CONNECTED, &cfg_priv->status); ++ ++ memcpy(&scbval.ea, brcmf_read_prof(cfg_priv, WL_PROF_BSSID), ETH_ALEN); ++ scbval.val = cpu_to_le32(reason_code); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, &scbval, ++ sizeof(struct brcmf_scb_val_le)); ++ if (err) ++ WL_ERR("error (%d)\n", err); ++ ++ cfg_priv->link_up = false; ++ ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, ++ enum nl80211_tx_power_setting type, s32 dbm) ++{ ++ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct net_device *ndev = cfg_to_ndev(cfg_priv); ++ u16 txpwrmw; ++ s32 err = 0; ++ s32 disable = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ switch (type) { ++ case NL80211_TX_POWER_AUTOMATIC: ++ break; ++ case NL80211_TX_POWER_LIMITED: ++ if (dbm < 0) { ++ WL_ERR("TX_POWER_LIMITED - dbm is negative\n"); ++ err = -EINVAL; ++ goto done; ++ } ++ break; ++ case NL80211_TX_POWER_FIXED: ++ if (dbm < 0) { ++ WL_ERR("TX_POWER_FIXED - dbm is negative\n"); ++ err = -EINVAL; ++ goto done; ++ } ++ break; ++ } ++ /* Make sure radio is off or on as far as software is concerned */ ++ disable = WL_RADIO_SW_DISABLE << 16; ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_RADIO, &disable); ++ if (err) ++ WL_ERR("WLC_SET_RADIO error (%d)\n", err); ++ ++ if (dbm > 0xffff) ++ txpwrmw = 0xffff; ++ else ++ txpwrmw = (u16) dbm; ++ err = brcmf_dev_intvar_set(ndev, "qtxpower", ++ (s32) (brcmf_mw_to_qdbm(txpwrmw))); ++ if (err) ++ WL_ERR("qtxpower error (%d)\n", err); ++ cfg_priv->conf->tx_power = dbm; ++ ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct net_device *ndev = cfg_to_ndev(cfg_priv); ++ s32 txpwrdbm; ++ u8 result; ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ err = brcmf_dev_intvar_get(ndev, "qtxpower", &txpwrdbm); ++ if (err) { ++ WL_ERR("error (%d)\n", err); ++ goto done; ++ } ++ ++ result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE); ++ *dbm = (s32) brcmf_qdbm_to_mw(result); ++ ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, ++ u8 key_idx, bool unicast, bool multicast) ++{ ++ u32 index; ++ u32 wsec; ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ WL_CONN("key index (%d)\n", key_idx); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec); ++ if (err) { ++ WL_ERR("WLC_GET_WSEC error (%d)\n", err); ++ goto done; ++ } ++ ++ if (wsec & WEP_ENABLED) { ++ /* Just select a new current key */ ++ index = key_idx; ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_KEY_PRIMARY, ++ &index); ++ if (err) ++ WL_ERR("error (%d)\n", err); ++ } ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, ++ u8 key_idx, const u8 *mac_addr, struct key_params *params) ++{ ++ struct brcmf_wsec_key key; ++ struct brcmf_wsec_key_le key_le; ++ s32 err = 0; ++ ++ memset(&key, 0, sizeof(key)); ++ key.index = (u32) key_idx; ++ /* Instead of bcast for ea address for default wep keys, ++ driver needs it to be Null */ ++ if (!is_multicast_ether_addr(mac_addr)) ++ memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN); ++ key.len = (u32) params->key_len; ++ /* check for key index change */ ++ if (key.len == 0) { ++ /* key delete */ ++ err = send_key_to_dongle(ndev, &key); ++ if (err) ++ return err; ++ } else { ++ if (key.len > sizeof(key.data)) { ++ WL_ERR("Invalid key length (%d)\n", key.len); ++ return -EINVAL; ++ } ++ ++ WL_CONN("Setting the key index %d\n", key.index); ++ memcpy(key.data, params->key, key.len); ++ ++ if (params->cipher == WLAN_CIPHER_SUITE_TKIP) { ++ u8 keybuf[8]; ++ memcpy(keybuf, &key.data[24], sizeof(keybuf)); ++ memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); ++ memcpy(&key.data[16], keybuf, sizeof(keybuf)); ++ } ++ ++ /* if IW_ENCODE_EXT_RX_SEQ_VALID set */ ++ if (params->seq && params->seq_len == 6) { ++ /* rx iv */ ++ u8 *ivptr; ++ ivptr = (u8 *) params->seq; ++ key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) | ++ (ivptr[3] << 8) | ivptr[2]; ++ key.rxiv.lo = (ivptr[1] << 8) | ivptr[0]; ++ key.iv_initialized = true; ++ } ++ ++ switch (params->cipher) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ key.algo = CRYPTO_ALGO_WEP1; ++ WL_CONN("WLAN_CIPHER_SUITE_WEP40\n"); ++ break; ++ case WLAN_CIPHER_SUITE_WEP104: ++ key.algo = CRYPTO_ALGO_WEP128; ++ WL_CONN("WLAN_CIPHER_SUITE_WEP104\n"); ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ key.algo = CRYPTO_ALGO_TKIP; ++ WL_CONN("WLAN_CIPHER_SUITE_TKIP\n"); ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ key.algo = CRYPTO_ALGO_AES_CCM; ++ WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n"); ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ key.algo = CRYPTO_ALGO_AES_CCM; ++ WL_CONN("WLAN_CIPHER_SUITE_CCMP\n"); ++ break; ++ default: ++ WL_ERR("Invalid cipher (0x%x)\n", params->cipher); ++ return -EINVAL; ++ } ++ convert_key_from_CPU(&key, &key_le); ++ ++ brcmf_netdev_wait_pend8021x(ndev); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le, ++ sizeof(key_le)); ++ if (err) { ++ WL_ERR("WLC_SET_KEY error (%d)\n", err); ++ return err; ++ } ++ } ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, ++ u8 key_idx, bool pairwise, const u8 *mac_addr, ++ struct key_params *params) ++{ ++ struct brcmf_wsec_key key; ++ s32 val; ++ s32 wsec; ++ s32 err = 0; ++ u8 keybuf[8]; ++ ++ WL_TRACE("Enter\n"); ++ WL_CONN("key index (%d)\n", key_idx); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ if (mac_addr) { ++ WL_TRACE("Exit"); ++ return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params); ++ } ++ memset(&key, 0, sizeof(key)); ++ ++ key.len = (u32) params->key_len; ++ key.index = (u32) key_idx; ++ ++ if (key.len > sizeof(key.data)) { ++ WL_ERR("Too long key length (%u)\n", key.len); ++ err = -EINVAL; ++ goto done; ++ } ++ memcpy(key.data, params->key, key.len); ++ ++ key.flags = BRCMF_PRIMARY_KEY; ++ switch (params->cipher) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ key.algo = CRYPTO_ALGO_WEP1; ++ WL_CONN("WLAN_CIPHER_SUITE_WEP40\n"); ++ break; ++ case WLAN_CIPHER_SUITE_WEP104: ++ key.algo = CRYPTO_ALGO_WEP128; ++ WL_CONN("WLAN_CIPHER_SUITE_WEP104\n"); ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ memcpy(keybuf, &key.data[24], sizeof(keybuf)); ++ memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); ++ memcpy(&key.data[16], keybuf, sizeof(keybuf)); ++ key.algo = CRYPTO_ALGO_TKIP; ++ WL_CONN("WLAN_CIPHER_SUITE_TKIP\n"); ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ key.algo = CRYPTO_ALGO_AES_CCM; ++ WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n"); ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ key.algo = CRYPTO_ALGO_AES_CCM; ++ WL_CONN("WLAN_CIPHER_SUITE_CCMP\n"); ++ break; ++ default: ++ WL_ERR("Invalid cipher (0x%x)\n", params->cipher); ++ err = -EINVAL; ++ goto done; ++ } ++ ++ err = send_key_to_dongle(ndev, &key); /* Set the new key/index */ ++ if (err) ++ goto done; ++ ++ val = WEP_ENABLED; ++ err = brcmf_dev_intvar_get(ndev, "wsec", &wsec); ++ if (err) { ++ WL_ERR("get wsec error (%d)\n", err); ++ goto done; ++ } ++ wsec &= ~(WEP_ENABLED); ++ wsec |= val; ++ err = brcmf_dev_intvar_set(ndev, "wsec", wsec); ++ if (err) { ++ WL_ERR("set wsec error (%d)\n", err); ++ goto done; ++ } ++ ++ val = 1; /* assume shared key. otherwise 0 */ ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val); ++ if (err) ++ WL_ERR("WLC_SET_AUTH error (%d)\n", err); ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, ++ u8 key_idx, bool pairwise, const u8 *mac_addr) ++{ ++ struct brcmf_wsec_key key; ++ s32 err = 0; ++ s32 val; ++ s32 wsec; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ memset(&key, 0, sizeof(key)); ++ ++ key.index = (u32) key_idx; ++ key.flags = BRCMF_PRIMARY_KEY; ++ key.algo = CRYPTO_ALGO_OFF; ++ ++ WL_CONN("key index (%d)\n", key_idx); ++ ++ /* Set the new key/index */ ++ err = send_key_to_dongle(ndev, &key); ++ if (err) { ++ if (err == -EINVAL) { ++ if (key.index >= DOT11_MAX_DEFAULT_KEYS) ++ /* we ignore this key index in this case */ ++ WL_ERR("invalid key index (%d)\n", key_idx); ++ } ++ /* Ignore this error, may happen during DISASSOC */ ++ err = -EAGAIN; ++ goto done; ++ } ++ ++ val = 0; ++ err = brcmf_dev_intvar_get(ndev, "wsec", &wsec); ++ if (err) { ++ WL_ERR("get wsec error (%d)\n", err); ++ /* Ignore this error, may happen during DISASSOC */ ++ err = -EAGAIN; ++ goto done; ++ } ++ wsec &= ~(WEP_ENABLED); ++ wsec |= val; ++ err = brcmf_dev_intvar_set(ndev, "wsec", wsec); ++ if (err) { ++ WL_ERR("set wsec error (%d)\n", err); ++ /* Ignore this error, may happen during DISASSOC */ ++ err = -EAGAIN; ++ goto done; ++ } ++ ++ val = 0; /* assume open key. otherwise 1 */ ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val); ++ if (err) { ++ WL_ERR("WLC_SET_AUTH error (%d)\n", err); ++ /* Ignore this error, may happen during DISASSOC */ ++ err = -EAGAIN; ++ } ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, ++ u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie, ++ void (*callback) (void *cookie, struct key_params * params)) ++{ ++ struct key_params params; ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct brcmf_cfg80211_security *sec; ++ s32 wsec; ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ WL_CONN("key index (%d)\n", key_idx); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ memset(¶ms, 0, sizeof(params)); ++ ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec); ++ if (err) { ++ WL_ERR("WLC_GET_WSEC error (%d)\n", err); ++ /* Ignore this error, may happen during DISASSOC */ ++ err = -EAGAIN; ++ goto done; ++ } ++ switch (wsec) { ++ case WEP_ENABLED: ++ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); ++ if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) { ++ params.cipher = WLAN_CIPHER_SUITE_WEP40; ++ WL_CONN("WLAN_CIPHER_SUITE_WEP40\n"); ++ } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) { ++ params.cipher = WLAN_CIPHER_SUITE_WEP104; ++ WL_CONN("WLAN_CIPHER_SUITE_WEP104\n"); ++ } ++ break; ++ case TKIP_ENABLED: ++ params.cipher = WLAN_CIPHER_SUITE_TKIP; ++ WL_CONN("WLAN_CIPHER_SUITE_TKIP\n"); ++ break; ++ case AES_ENABLED: ++ params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; ++ WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n"); ++ break; ++ default: ++ WL_ERR("Invalid algo (0x%x)\n", wsec); ++ err = -EINVAL; ++ goto done; ++ } ++ callback(cookie, ¶ms); ++ ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, ++ struct net_device *ndev, u8 key_idx) ++{ ++ WL_INFO("Not supported\n"); ++ ++ return -EOPNOTSUPP; ++} ++ ++static s32 ++brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, ++ u8 *mac, struct station_info *sinfo) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct brcmf_scb_val_le scb_val; ++ int rssi; ++ s32 rate; ++ s32 err = 0; ++ u8 *bssid = brcmf_read_prof(cfg_priv, WL_PROF_BSSID); ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ if (memcmp(mac, bssid, ETH_ALEN)) { ++ WL_ERR("Wrong Mac address cfg_mac-%X:%X:%X:%X:%X:%X" ++ "wl_bssid-%X:%X:%X:%X:%X:%X\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ bssid[0], bssid[1], bssid[2], bssid[3], ++ bssid[4], bssid[5]); ++ err = -ENOENT; ++ goto done; ++ } ++ ++ /* Report the current tx rate */ ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate); ++ if (err) { ++ WL_ERR("Could not get rate (%d)\n", err); ++ } else { ++ sinfo->filled |= STATION_INFO_TX_BITRATE; ++ sinfo->txrate.legacy = rate * 5; ++ WL_CONN("Rate %d Mbps\n", rate / 2); ++ } ++ ++ if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) { ++ scb_val.val = cpu_to_le32(0); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val, ++ sizeof(struct brcmf_scb_val_le)); ++ if (err) ++ WL_ERR("Could not get rssi (%d)\n", err); ++ ++ rssi = le32_to_cpu(scb_val.val); ++ sinfo->filled |= STATION_INFO_SIGNAL; ++ sinfo->signal = rssi; ++ WL_CONN("RSSI %d dBm\n", rssi); ++ } ++ ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, ++ bool enabled, s32 timeout) ++{ ++ s32 pm; ++ s32 err = 0; ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ ++ WL_TRACE("Enter\n"); ++ ++ /* ++ * Powersave enable/disable request is coming from the ++ * cfg80211 even before the interface is up. In that ++ * scenario, driver will be storing the power save ++ * preference in cfg_priv struct to apply this to ++ * FW later while initializing the dongle ++ */ ++ cfg_priv->pwr_save = enabled; ++ if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) { ++ ++ WL_INFO("Device is not ready," ++ "storing the value in cfg_priv struct\n"); ++ goto done; ++ } ++ ++ pm = enabled ? PM_FAST : PM_OFF; ++ WL_INFO("power save %s\n", (pm ? "enabled" : "disabled")); ++ ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &pm); ++ if (err) { ++ if (err == -ENODEV) ++ WL_ERR("net_device is not ready yet\n"); ++ else ++ WL_ERR("error (%d)\n", err); ++ } ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev, ++ const u8 *addr, ++ const struct cfg80211_bitrate_mask *mask) ++{ ++ struct brcm_rateset_le rateset_le; ++ s32 rate; ++ s32 val; ++ s32 err_bg; ++ s32 err_a; ++ u32 legacy; ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ /* addr param is always NULL. ignore it */ ++ /* Get current rateset */ ++ err = brcmf_exec_dcmd(ndev, BRCM_GET_CURR_RATESET, &rateset_le, ++ sizeof(rateset_le)); ++ if (err) { ++ WL_ERR("could not get current rateset (%d)\n", err); ++ goto done; ++ } ++ ++ legacy = ffs(mask->control[IEEE80211_BAND_2GHZ].legacy & 0xFFFF); ++ if (!legacy) ++ legacy = ffs(mask->control[IEEE80211_BAND_5GHZ].legacy & ++ 0xFFFF); ++ ++ val = wl_g_rates[legacy - 1].bitrate * 100000; ++ ++ if (val < le32_to_cpu(rateset_le.count)) ++ /* Select rate by rateset index */ ++ rate = rateset_le.rates[val] & 0x7f; ++ else ++ /* Specified rate in bps */ ++ rate = val / 500000; ++ ++ WL_CONN("rate %d mbps\n", rate / 2); ++ ++ /* ++ * ++ * Set rate override, ++ * Since the is a/b/g-blind, both a/bg_rate are enforced. ++ */ ++ err_bg = brcmf_dev_intvar_set(ndev, "bg_rate", rate); ++ err_a = brcmf_dev_intvar_set(ndev, "a_rate", rate); ++ if (err_bg && err_a) { ++ WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a); ++ err = err_bg | err_a; ++ } ++ ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv, ++ struct brcmf_bss_info *bi) ++{ ++ struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); ++ struct ieee80211_channel *notify_channel; ++ struct cfg80211_bss *bss; ++ struct ieee80211_supported_band *band; ++ s32 err = 0; ++ u16 channel; ++ u32 freq; ++ u64 notify_timestamp; ++ u16 notify_capability; ++ u16 notify_interval; ++ u8 *notify_ie; ++ size_t notify_ielen; ++ s32 notify_signal; ++ ++ if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) { ++ WL_ERR("Bss info is larger than buffer. Discarding\n"); ++ return 0; ++ } ++ ++ channel = bi->ctl_ch ? bi->ctl_ch : ++ CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); ++ ++ if (channel <= CH_MAX_2G_CHANNEL) ++ band = wiphy->bands[IEEE80211_BAND_2GHZ]; ++ else ++ band = wiphy->bands[IEEE80211_BAND_5GHZ]; ++ ++ freq = ieee80211_channel_to_frequency(channel, band->band); ++ notify_channel = ieee80211_get_channel(wiphy, freq); ++ ++ notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */ ++ notify_capability = le16_to_cpu(bi->capability); ++ notify_interval = le16_to_cpu(bi->beacon_period); ++ notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset); ++ notify_ielen = le32_to_cpu(bi->ie_length); ++ notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100; ++ ++ WL_CONN("bssid: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", ++ bi->BSSID[0], bi->BSSID[1], bi->BSSID[2], ++ bi->BSSID[3], bi->BSSID[4], bi->BSSID[5]); ++ WL_CONN("Channel: %d(%d)\n", channel, freq); ++ WL_CONN("Capability: %X\n", notify_capability); ++ WL_CONN("Beacon interval: %d\n", notify_interval); ++ WL_CONN("Signal: %d\n", notify_signal); ++ WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp); ++ ++ bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID, ++ notify_timestamp, notify_capability, notify_interval, notify_ie, ++ notify_ielen, notify_signal, GFP_KERNEL); ++ ++ if (!bss) { ++ WL_ERR("cfg80211_inform_bss_frame error\n"); ++ return -EINVAL; ++ } ++ ++ return err; ++} ++ ++static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_scan_results *bss_list; ++ struct brcmf_bss_info *bi = NULL; /* must be initialized */ ++ s32 err = 0; ++ int i; ++ ++ bss_list = cfg_priv->bss_list; ++ if (bss_list->version != BRCMF_BSS_INFO_VERSION) { ++ WL_ERR("Version %d != WL_BSS_INFO_VERSION\n", ++ bss_list->version); ++ return -EOPNOTSUPP; ++ } ++ WL_SCAN("scanned AP count (%d)\n", bss_list->count); ++ for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) { ++ bi = next_bss(bss_list, bi); ++ err = brcmf_inform_single_bss(cfg_priv, bi); ++ if (err) ++ break; ++ } ++ return err; ++} ++ ++static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv, ++ struct net_device *ndev, const u8 *bssid) ++{ ++ struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); ++ struct ieee80211_channel *notify_channel; ++ struct brcmf_bss_info *bi = NULL; ++ struct ieee80211_supported_band *band; ++ u8 *buf = NULL; ++ s32 err = 0; ++ u16 channel; ++ u32 freq; ++ u64 notify_timestamp; ++ u16 notify_capability; ++ u16 notify_interval; ++ u8 *notify_ie; ++ size_t notify_ielen; ++ s32 notify_signal; ++ ++ WL_TRACE("Enter\n"); ++ ++ buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); ++ if (buf == NULL) { ++ err = -ENOMEM; ++ goto CleanUp; ++ } ++ ++ *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX); ++ ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX); ++ if (err) { ++ WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err); ++ goto CleanUp; ++ } ++ ++ bi = (struct brcmf_bss_info *)(buf + 4); ++ ++ channel = bi->ctl_ch ? bi->ctl_ch : ++ CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); ++ ++ if (channel <= CH_MAX_2G_CHANNEL) ++ band = wiphy->bands[IEEE80211_BAND_2GHZ]; ++ else ++ band = wiphy->bands[IEEE80211_BAND_5GHZ]; ++ ++ freq = ieee80211_channel_to_frequency(channel, band->band); ++ notify_channel = ieee80211_get_channel(wiphy, freq); ++ ++ notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */ ++ notify_capability = le16_to_cpu(bi->capability); ++ notify_interval = le16_to_cpu(bi->beacon_period); ++ notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset); ++ notify_ielen = le32_to_cpu(bi->ie_length); ++ notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100; ++ ++ WL_CONN("channel: %d(%d)\n", channel, freq); ++ WL_CONN("capability: %X\n", notify_capability); ++ WL_CONN("beacon interval: %d\n", notify_interval); ++ WL_CONN("signal: %d\n", notify_signal); ++ WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp); ++ ++ cfg80211_inform_bss(wiphy, notify_channel, bssid, ++ notify_timestamp, notify_capability, notify_interval, ++ notify_ie, notify_ielen, notify_signal, GFP_KERNEL); ++ ++CleanUp: ++ ++ kfree(buf); ++ ++ WL_TRACE("Exit\n"); ++ ++ return err; ++} ++ ++static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ return cfg_priv->conf->mode == WL_MODE_IBSS; ++} ++ ++/* ++ * Traverse a string of 1-byte tag/1-byte length/variable-length value ++ * triples, returning a pointer to the substring whose first element ++ * matches tag ++ */ ++static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key) ++{ ++ struct brcmf_tlv *elt; ++ int totlen; ++ ++ elt = (struct brcmf_tlv *) buf; ++ totlen = buflen; ++ ++ /* find tagged parameter */ ++ while (totlen >= 2) { ++ int len = elt->len; ++ ++ /* validate remaining totlen */ ++ if ((elt->id == key) && (totlen >= (len + 2))) ++ return elt; ++ ++ elt = (struct brcmf_tlv *) ((u8 *) elt + (len + 2)); ++ totlen -= (len + 2); ++ } ++ ++ return NULL; ++} ++ ++static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_bss_info *bi; ++ struct brcmf_ssid *ssid; ++ struct brcmf_tlv *tim; ++ u16 beacon_interval; ++ u8 dtim_period; ++ size_t ie_len; ++ u8 *ie; ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (brcmf_is_ibssmode(cfg_priv)) ++ return err; ++ ++ ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg_priv, WL_PROF_SSID); ++ ++ *(__le32 *)cfg_priv->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX); ++ err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_GET_BSS_INFO, ++ cfg_priv->extra_buf, WL_EXTRA_BUF_MAX); ++ if (err) { ++ WL_ERR("Could not get bss info %d\n", err); ++ goto update_bss_info_out; ++ } ++ ++ bi = (struct brcmf_bss_info *)(cfg_priv->extra_buf + 4); ++ err = brcmf_inform_single_bss(cfg_priv, bi); ++ if (err) ++ goto update_bss_info_out; ++ ++ ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset); ++ ie_len = le32_to_cpu(bi->ie_length); ++ beacon_interval = le16_to_cpu(bi->beacon_period); ++ ++ tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM); ++ if (tim) ++ dtim_period = tim->data[1]; ++ else { ++ /* ++ * active scan was done so we could not get dtim ++ * information out of probe response. ++ * so we speficially query dtim information to dongle. ++ */ ++ u32 var; ++ err = brcmf_dev_intvar_get(cfg_to_ndev(cfg_priv), ++ "dtim_assoc", &var); ++ if (err) { ++ WL_ERR("wl dtim_assoc failed (%d)\n", err); ++ goto update_bss_info_out; ++ } ++ dtim_period = (u8)var; ++ } ++ ++ brcmf_update_prof(cfg_priv, NULL, &beacon_interval, WL_PROF_BEACONINT); ++ brcmf_update_prof(cfg_priv, NULL, &dtim_period, WL_PROF_DTIMPERIOD); ++ ++update_bss_info_out: ++ WL_TRACE("Exit"); ++ return err; ++} ++ ++static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); ++ struct brcmf_ssid ssid; ++ ++ if (cfg_priv->iscan_on) { ++ iscan->state = WL_ISCAN_STATE_IDLE; ++ ++ if (iscan->timer_on) { ++ del_timer_sync(&iscan->timer); ++ iscan->timer_on = 0; ++ } ++ ++ cancel_work_sync(&iscan->work); ++ ++ /* Abort iscan running in FW */ ++ memset(&ssid, 0, sizeof(ssid)); ++ brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT); ++ } ++} ++ ++static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan, ++ bool aborted) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan); ++ struct net_device *ndev = cfg_to_ndev(cfg_priv); ++ ++ if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { ++ WL_ERR("Scan complete while device not scanning\n"); ++ return; ++ } ++ if (cfg_priv->scan_request) { ++ WL_SCAN("ISCAN Completed scan: %s\n", ++ aborted ? "Aborted" : "Done"); ++ cfg80211_scan_done(cfg_priv->scan_request, aborted); ++ brcmf_set_mpc(ndev, 1); ++ cfg_priv->scan_request = NULL; ++ } ++ cfg_priv->iscan_kickstart = false; ++} ++ ++static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan) ++{ ++ if (iscan->state != WL_ISCAN_STATE_IDLE) { ++ WL_SCAN("wake up iscan\n"); ++ schedule_work(&iscan->work); ++ return 0; ++ } ++ ++ return -EIO; ++} ++ ++static s32 ++brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status, ++ struct brcmf_scan_results **bss_list) ++{ ++ struct brcmf_iscan_results list; ++ struct brcmf_scan_results *results; ++ struct brcmf_scan_results_le *results_le; ++ struct brcmf_iscan_results *list_buf; ++ s32 err = 0; ++ ++ memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX); ++ list_buf = (struct brcmf_iscan_results *)iscan->scan_buf; ++ results = &list_buf->results; ++ results_le = &list_buf->results_le; ++ results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE; ++ results->version = 0; ++ results->count = 0; ++ ++ memset(&list, 0, sizeof(list)); ++ list.results_le.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX); ++ err = brcmf_dev_iovar_getbuf(iscan->ndev, "iscanresults", &list, ++ BRCMF_ISCAN_RESULTS_FIXED_SIZE, ++ iscan->scan_buf, WL_ISCAN_BUF_MAX); ++ if (err) { ++ WL_ERR("error (%d)\n", err); ++ return err; ++ } ++ results->buflen = le32_to_cpu(results_le->buflen); ++ results->version = le32_to_cpu(results_le->version); ++ results->count = le32_to_cpu(results_le->count); ++ WL_SCAN("results->count = %d\n", results_le->count); ++ WL_SCAN("results->buflen = %d\n", results_le->buflen); ++ *status = le32_to_cpu(list_buf->status_le); ++ WL_SCAN("status = %d\n", *status); ++ *bss_list = results; ++ ++ return err; ++} ++ ++static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; ++ s32 err = 0; ++ ++ iscan->state = WL_ISCAN_STATE_IDLE; ++ brcmf_inform_bss(cfg_priv); ++ brcmf_notify_iscan_complete(iscan, false); ++ ++ return err; ++} ++ ++static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; ++ s32 err = 0; ++ ++ /* Reschedule the timer */ ++ mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); ++ iscan->timer_on = 1; ++ ++ return err; ++} ++ ++static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; ++ s32 err = 0; ++ ++ brcmf_inform_bss(cfg_priv); ++ brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE); ++ /* Reschedule the timer */ ++ mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); ++ iscan->timer_on = 1; ++ ++ return err; ++} ++ ++static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; ++ s32 err = 0; ++ ++ iscan->state = WL_ISCAN_STATE_IDLE; ++ brcmf_notify_iscan_complete(iscan, true); ++ ++ return err; ++} ++ ++static void brcmf_cfg80211_iscan_handler(struct work_struct *work) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = ++ container_of(work, struct brcmf_cfg80211_iscan_ctrl, ++ work); ++ struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan); ++ struct brcmf_cfg80211_iscan_eloop *el = &iscan->el; ++ u32 status = BRCMF_SCAN_RESULTS_PARTIAL; ++ ++ if (iscan->timer_on) { ++ del_timer_sync(&iscan->timer); ++ iscan->timer_on = 0; ++ } ++ ++ if (brcmf_get_iscan_results(iscan, &status, &cfg_priv->bss_list)) { ++ status = BRCMF_SCAN_RESULTS_ABORTED; ++ WL_ERR("Abort iscan\n"); ++ } ++ ++ el->handler[status](cfg_priv); ++} ++ ++static void brcmf_iscan_timer(unsigned long data) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = ++ (struct brcmf_cfg80211_iscan_ctrl *)data; ++ ++ if (iscan) { ++ iscan->timer_on = 0; ++ WL_SCAN("timer expired\n"); ++ brcmf_wakeup_iscan(iscan); ++ } ++} ++ ++static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); ++ ++ if (cfg_priv->iscan_on) { ++ iscan->state = WL_ISCAN_STATE_IDLE; ++ INIT_WORK(&iscan->work, brcmf_cfg80211_iscan_handler); ++ } ++ ++ return 0; ++} ++ ++static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el) ++{ ++ memset(el, 0, sizeof(*el)); ++ el->handler[BRCMF_SCAN_RESULTS_SUCCESS] = brcmf_iscan_done; ++ el->handler[BRCMF_SCAN_RESULTS_PARTIAL] = brcmf_iscan_inprogress; ++ el->handler[BRCMF_SCAN_RESULTS_PENDING] = brcmf_iscan_pending; ++ el->handler[BRCMF_SCAN_RESULTS_ABORTED] = brcmf_iscan_aborted; ++ el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted; ++} ++ ++static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); ++ int err = 0; ++ ++ if (cfg_priv->iscan_on) { ++ iscan->ndev = cfg_to_ndev(cfg_priv); ++ brcmf_init_iscan_eloop(&iscan->el); ++ iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS; ++ init_timer(&iscan->timer); ++ iscan->timer.data = (unsigned long) iscan; ++ iscan->timer.function = brcmf_iscan_timer; ++ err = brcmf_invoke_iscan(cfg_priv); ++ if (!err) ++ iscan->data = cfg_priv; ++ } ++ ++ return err; ++} ++ ++static void brcmf_delay(u32 ms) ++{ ++ if (ms < 1000 / HZ) { ++ cond_resched(); ++ mdelay(ms); ++ } else { ++ msleep(ms); ++ } ++} ++ ++static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ ++ /* ++ * Check for WL_STATUS_READY before any function call which ++ * could result is bus access. Don't block the resume for ++ * any driver error conditions ++ */ ++ WL_TRACE("Enter\n"); ++ ++ if (test_bit(WL_STATUS_READY, &cfg_priv->status)) ++ brcmf_invoke_iscan(wiphy_to_cfg(wiphy)); ++ ++ WL_TRACE("Exit\n"); ++ return 0; ++} ++ ++static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, ++ struct cfg80211_wowlan *wow) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct net_device *ndev = cfg_to_ndev(cfg_priv); ++ ++ WL_TRACE("Enter\n"); ++ ++ /* ++ * Check for WL_STATUS_READY before any function call which ++ * could result is bus access. Don't block the suspend for ++ * any driver error conditions ++ */ ++ ++ /* ++ * While going to suspend if associated with AP disassociate ++ * from AP to save power while system is in suspended state ++ */ ++ if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) || ++ test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) && ++ test_bit(WL_STATUS_READY, &cfg_priv->status)) { ++ WL_INFO("Disassociating from AP" ++ " while entering suspend state\n"); ++ brcmf_link_down(cfg_priv); ++ ++ /* ++ * Make sure WPA_Supplicant receives all the event ++ * generated due to DISASSOC call to the fw to keep ++ * the state fw and WPA_Supplicant state consistent ++ */ ++ brcmf_delay(500); ++ } ++ ++ set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); ++ if (test_bit(WL_STATUS_READY, &cfg_priv->status)) ++ brcmf_term_iscan(cfg_priv); ++ ++ if (cfg_priv->scan_request) { ++ /* Indidate scan abort to cfg80211 layer */ ++ WL_INFO("Terminating scan in progress\n"); ++ cfg80211_scan_done(cfg_priv->scan_request, true); ++ cfg_priv->scan_request = NULL; ++ } ++ clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); ++ clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); ++ ++ /* Turn off watchdog timer */ ++ if (test_bit(WL_STATUS_READY, &cfg_priv->status)) { ++ WL_INFO("Enable MPC\n"); ++ brcmf_set_mpc(ndev, 1); ++ } ++ ++ WL_TRACE("Exit\n"); ++ ++ return 0; ++} ++ ++static __used s32 ++brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ u32 buflen; ++ ++ buflen = brcmf_c_mkiovar(name, buf, len, cfg_priv->dcmd_buf, ++ WL_DCMD_LEN_MAX); ++ BUG_ON(!buflen); ++ ++ return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg_priv->dcmd_buf, ++ buflen); ++} ++ ++static s32 ++brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf, ++ s32 buf_len) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ u32 len; ++ s32 err = 0; ++ ++ len = brcmf_c_mkiovar(name, NULL, 0, cfg_priv->dcmd_buf, ++ WL_DCMD_LEN_MAX); ++ BUG_ON(!len); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg_priv->dcmd_buf, ++ WL_DCMD_LEN_MAX); ++ if (err) { ++ WL_ERR("error (%d)\n", err); ++ return err; ++ } ++ memcpy(buf, cfg_priv->dcmd_buf, buf_len); ++ ++ return err; ++} ++ ++static __used s32 ++brcmf_update_pmklist(struct net_device *ndev, ++ struct brcmf_cfg80211_pmk_list *pmk_list, s32 err) ++{ ++ int i, j; ++ int pmkid_len; ++ ++ pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid); ++ ++ WL_CONN("No of elements %d\n", pmkid_len); ++ for (i = 0; i < pmkid_len; i++) { ++ WL_CONN("PMKID[%d]: %pM =\n", i, ++ &pmk_list->pmkids.pmkid[i].BSSID); ++ for (j = 0; j < WLAN_PMKID_LEN; j++) ++ WL_CONN("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]); ++ } ++ ++ if (!err) ++ brcmf_dev_bufvar_set(ndev, "pmkid_info", (char *)pmk_list, ++ sizeof(*pmk_list)); ++ ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_pmksa *pmksa) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids; ++ s32 err = 0; ++ int i; ++ int pmkid_len; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ pmkid_len = le32_to_cpu(pmkids->npmkid); ++ for (i = 0; i < pmkid_len; i++) ++ if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN)) ++ break; ++ if (i < WL_NUM_PMKIDS_MAX) { ++ memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN); ++ memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN); ++ if (i == pmkid_len) { ++ pmkid_len++; ++ pmkids->npmkid = cpu_to_le32(pmkid_len); ++ } ++ } else ++ err = -EINVAL; ++ ++ WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n", ++ pmkids->pmkid[pmkid_len].BSSID); ++ for (i = 0; i < WLAN_PMKID_LEN; i++) ++ WL_CONN("%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]); ++ ++ err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err); ++ ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_pmksa *pmksa) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct pmkid_list pmkid; ++ s32 err = 0; ++ int i, pmkid_len; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN); ++ memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN); ++ ++ WL_CONN("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n", ++ &pmkid.pmkid[0].BSSID); ++ for (i = 0; i < WLAN_PMKID_LEN; i++) ++ WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]); ++ ++ pmkid_len = le32_to_cpu(cfg_priv->pmk_list->pmkids.npmkid); ++ for (i = 0; i < pmkid_len; i++) ++ if (!memcmp ++ (pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID, ++ ETH_ALEN)) ++ break; ++ ++ if ((pmkid_len > 0) ++ && (i < pmkid_len)) { ++ memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0, ++ sizeof(struct pmkid)); ++ for (; i < (pmkid_len - 1); i++) { ++ memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID, ++ &cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID, ++ ETH_ALEN); ++ memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].PMKID, ++ &cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID, ++ WLAN_PMKID_LEN); ++ } ++ cfg_priv->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1); ++ } else ++ err = -EINVAL; ++ ++ err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err); ++ ++ WL_TRACE("Exit\n"); ++ return err; ++ ++} ++ ++static s32 ++brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list)); ++ err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err); ++ ++ WL_TRACE("Exit\n"); ++ return err; ++ ++} ++ ++static struct cfg80211_ops wl_cfg80211_ops = { ++ .change_virtual_intf = brcmf_cfg80211_change_iface, ++ .scan = brcmf_cfg80211_scan, ++ .set_wiphy_params = brcmf_cfg80211_set_wiphy_params, ++ .join_ibss = brcmf_cfg80211_join_ibss, ++ .leave_ibss = brcmf_cfg80211_leave_ibss, ++ .get_station = brcmf_cfg80211_get_station, ++ .set_tx_power = brcmf_cfg80211_set_tx_power, ++ .get_tx_power = brcmf_cfg80211_get_tx_power, ++ .add_key = brcmf_cfg80211_add_key, ++ .del_key = brcmf_cfg80211_del_key, ++ .get_key = brcmf_cfg80211_get_key, ++ .set_default_key = brcmf_cfg80211_config_default_key, ++ .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key, ++ .set_power_mgmt = brcmf_cfg80211_set_power_mgmt, ++ .set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask, ++ .connect = brcmf_cfg80211_connect, ++ .disconnect = brcmf_cfg80211_disconnect, ++ .suspend = brcmf_cfg80211_suspend, ++ .resume = brcmf_cfg80211_resume, ++ .set_pmksa = brcmf_cfg80211_set_pmksa, ++ .del_pmksa = brcmf_cfg80211_del_pmksa, ++ .flush_pmksa = brcmf_cfg80211_flush_pmksa ++}; ++ ++static s32 brcmf_mode_to_nl80211_iftype(s32 mode) ++{ ++ s32 err = 0; ++ ++ switch (mode) { ++ case WL_MODE_BSS: ++ return NL80211_IFTYPE_STATION; ++ case WL_MODE_IBSS: ++ return NL80211_IFTYPE_ADHOC; ++ default: ++ return NL80211_IFTYPE_UNSPECIFIED; ++ } ++ ++ return err; ++} ++ ++static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface, ++ struct device *ndev) ++{ ++ struct wireless_dev *wdev; ++ s32 err = 0; ++ ++ wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); ++ if (!wdev) ++ return ERR_PTR(-ENOMEM); ++ ++ wdev->wiphy = ++ wiphy_new(&wl_cfg80211_ops, ++ sizeof(struct brcmf_cfg80211_priv) + sizeof_iface); ++ if (!wdev->wiphy) { ++ WL_ERR("Couldn not allocate wiphy device\n"); ++ err = -ENOMEM; ++ goto wiphy_new_out; ++ } ++ set_wiphy_dev(wdev->wiphy, ndev); ++ wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; ++ wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; ++ wdev->wiphy->interface_modes = ++ BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); ++ wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; ++ wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set ++ * it as 11a by default. ++ * This will be updated with ++ * 11n phy tables in ++ * "ifconfig up" ++ * if phy has 11n capability ++ */ ++ wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; ++ wdev->wiphy->cipher_suites = __wl_cipher_suites; ++ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); ++ wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power ++ * save mode ++ * by default ++ */ ++ err = wiphy_register(wdev->wiphy); ++ if (err < 0) { ++ WL_ERR("Couldn not register wiphy device (%d)\n", err); ++ goto wiphy_register_out; ++ } ++ return wdev; ++ ++wiphy_register_out: ++ wiphy_free(wdev->wiphy); ++ ++wiphy_new_out: ++ kfree(wdev); ++ ++ return ERR_PTR(err); ++} ++ ++static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct wireless_dev *wdev = cfg_priv->wdev; ++ ++ if (!wdev) { ++ WL_ERR("wdev is invalid\n"); ++ return; ++ } ++ wiphy_unregister(wdev->wiphy); ++ wiphy_free(wdev->wiphy); ++ kfree(wdev); ++ cfg_priv->wdev = NULL; ++} ++ ++static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv, ++ const struct brcmf_event_msg *e) ++{ ++ u32 event = be32_to_cpu(e->event_type); ++ u32 status = be32_to_cpu(e->status); ++ ++ if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) { ++ WL_CONN("Processing set ssid\n"); ++ cfg_priv->link_up = true; ++ return true; ++ } ++ ++ return false; ++} ++ ++static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv, ++ const struct brcmf_event_msg *e) ++{ ++ u32 event = be32_to_cpu(e->event_type); ++ u16 flags = be16_to_cpu(e->flags); ++ ++ if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) { ++ WL_CONN("Processing link down\n"); ++ return true; ++ } ++ return false; ++} ++ ++static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv, ++ const struct brcmf_event_msg *e) ++{ ++ u32 event = be32_to_cpu(e->event_type); ++ u32 status = be32_to_cpu(e->status); ++ ++ if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) { ++ WL_CONN("Processing Link %s & no network found\n", ++ be16_to_cpu(e->flags) & BRCMF_EVENT_MSG_LINK ? ++ "up" : "down"); ++ return true; ++ } ++ ++ if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) { ++ WL_CONN("Processing connecting & no network found\n"); ++ return true; ++ } ++ ++ return false; ++} ++ ++static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); ++ ++ kfree(conn_info->req_ie); ++ conn_info->req_ie = NULL; ++ conn_info->req_ie_len = 0; ++ kfree(conn_info->resp_ie); ++ conn_info->resp_ie = NULL; ++ conn_info->resp_ie_len = 0; ++} ++ ++static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct net_device *ndev = cfg_to_ndev(cfg_priv); ++ struct brcmf_cfg80211_assoc_ielen_le *assoc_info; ++ struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); ++ u32 req_len; ++ u32 resp_len; ++ s32 err = 0; ++ ++ brcmf_clear_assoc_ies(cfg_priv); ++ ++ err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg_priv->extra_buf, ++ WL_ASSOC_INFO_MAX); ++ if (err) { ++ WL_ERR("could not get assoc info (%d)\n", err); ++ return err; ++ } ++ assoc_info = ++ (struct brcmf_cfg80211_assoc_ielen_le *)cfg_priv->extra_buf; ++ req_len = le32_to_cpu(assoc_info->req_len); ++ resp_len = le32_to_cpu(assoc_info->resp_len); ++ if (req_len) { ++ err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies", ++ cfg_priv->extra_buf, ++ WL_ASSOC_INFO_MAX); ++ if (err) { ++ WL_ERR("could not get assoc req (%d)\n", err); ++ return err; ++ } ++ conn_info->req_ie_len = req_len; ++ conn_info->req_ie = ++ kmemdup(cfg_priv->extra_buf, conn_info->req_ie_len, ++ GFP_KERNEL); ++ } else { ++ conn_info->req_ie_len = 0; ++ conn_info->req_ie = NULL; ++ } ++ if (resp_len) { ++ err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies", ++ cfg_priv->extra_buf, ++ WL_ASSOC_INFO_MAX); ++ if (err) { ++ WL_ERR("could not get assoc resp (%d)\n", err); ++ return err; ++ } ++ conn_info->resp_ie_len = resp_len; ++ conn_info->resp_ie = ++ kmemdup(cfg_priv->extra_buf, conn_info->resp_ie_len, ++ GFP_KERNEL); ++ } else { ++ conn_info->resp_ie_len = 0; ++ conn_info->resp_ie = NULL; ++ } ++ WL_CONN("req len (%d) resp len (%d)\n", ++ conn_info->req_ie_len, conn_info->resp_ie_len); ++ ++ return err; ++} ++ ++static s32 ++brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv, ++ struct net_device *ndev, ++ const struct brcmf_event_msg *e) ++{ ++ struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); ++ struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); ++ struct brcmf_channel_info_le channel_le; ++ struct ieee80211_channel *notify_channel; ++ struct ieee80211_supported_band *band; ++ u32 freq; ++ s32 err = 0; ++ u32 target_channel; ++ ++ WL_TRACE("Enter\n"); ++ ++ brcmf_get_assoc_ies(cfg_priv); ++ brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID); ++ brcmf_update_bss_info(cfg_priv); ++ ++ brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le, ++ sizeof(channel_le)); ++ ++ target_channel = le32_to_cpu(channel_le.target_channel); ++ WL_CONN("Roamed to channel %d\n", target_channel); ++ ++ if (target_channel <= CH_MAX_2G_CHANNEL) ++ band = wiphy->bands[IEEE80211_BAND_2GHZ]; ++ else ++ band = wiphy->bands[IEEE80211_BAND_5GHZ]; ++ ++ freq = ieee80211_channel_to_frequency(target_channel, band->band); ++ notify_channel = ieee80211_get_channel(wiphy, freq); ++ ++ cfg80211_roamed(ndev, notify_channel, ++ (u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID), ++ conn_info->req_ie, conn_info->req_ie_len, ++ conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); ++ WL_CONN("Report roaming result\n"); ++ ++ set_bit(WL_STATUS_CONNECTED, &cfg_priv->status); ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv, ++ struct net_device *ndev, const struct brcmf_event_msg *e, ++ bool completed) ++{ ++ struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ ++ if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) { ++ if (completed) { ++ brcmf_get_assoc_ies(cfg_priv); ++ brcmf_update_prof(cfg_priv, NULL, &e->addr, ++ WL_PROF_BSSID); ++ brcmf_update_bss_info(cfg_priv); ++ } ++ cfg80211_connect_result(ndev, ++ (u8 *)brcmf_read_prof(cfg_priv, ++ WL_PROF_BSSID), ++ conn_info->req_ie, ++ conn_info->req_ie_len, ++ conn_info->resp_ie, ++ conn_info->resp_ie_len, ++ completed ? WLAN_STATUS_SUCCESS : ++ WLAN_STATUS_AUTH_TIMEOUT, ++ GFP_KERNEL); ++ if (completed) ++ set_bit(WL_STATUS_CONNECTED, &cfg_priv->status); ++ WL_CONN("Report connect result - connection %s\n", ++ completed ? "succeeded" : "failed"); ++ } ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv, ++ struct net_device *ndev, ++ const struct brcmf_event_msg *e, void *data) ++{ ++ s32 err = 0; ++ ++ if (brcmf_is_linkup(cfg_priv, e)) { ++ WL_CONN("Linkup\n"); ++ if (brcmf_is_ibssmode(cfg_priv)) { ++ brcmf_update_prof(cfg_priv, NULL, (void *)e->addr, ++ WL_PROF_BSSID); ++ wl_inform_ibss(cfg_priv, ndev, e->addr); ++ cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL); ++ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); ++ set_bit(WL_STATUS_CONNECTED, &cfg_priv->status); ++ } else ++ brcmf_bss_connect_done(cfg_priv, ndev, e, true); ++ } else if (brcmf_is_linkdown(cfg_priv, e)) { ++ WL_CONN("Linkdown\n"); ++ if (brcmf_is_ibssmode(cfg_priv)) { ++ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); ++ if (test_and_clear_bit(WL_STATUS_CONNECTED, ++ &cfg_priv->status)) ++ brcmf_link_down(cfg_priv); ++ } else { ++ brcmf_bss_connect_done(cfg_priv, ndev, e, false); ++ if (test_and_clear_bit(WL_STATUS_CONNECTED, ++ &cfg_priv->status)) { ++ cfg80211_disconnected(ndev, 0, NULL, 0, ++ GFP_KERNEL); ++ brcmf_link_down(cfg_priv); ++ } ++ } ++ brcmf_init_prof(cfg_priv->profile); ++ } else if (brcmf_is_nonetwork(cfg_priv, e)) { ++ if (brcmf_is_ibssmode(cfg_priv)) ++ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); ++ else ++ brcmf_bss_connect_done(cfg_priv, ndev, e, false); ++ } ++ ++ return err; ++} ++ ++static s32 ++brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv, ++ struct net_device *ndev, ++ const struct brcmf_event_msg *e, void *data) ++{ ++ s32 err = 0; ++ u32 event = be32_to_cpu(e->event_type); ++ u32 status = be32_to_cpu(e->status); ++ ++ if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) { ++ if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) ++ brcmf_bss_roaming_done(cfg_priv, ndev, e); ++ else ++ brcmf_bss_connect_done(cfg_priv, ndev, e, true); ++ } ++ ++ return err; ++} ++ ++static s32 ++brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv, ++ struct net_device *ndev, ++ const struct brcmf_event_msg *e, void *data) ++{ ++ u16 flags = be16_to_cpu(e->flags); ++ enum nl80211_key_type key_type; ++ ++ if (flags & BRCMF_EVENT_MSG_GROUP) ++ key_type = NL80211_KEYTYPE_GROUP; ++ else ++ key_type = NL80211_KEYTYPE_PAIRWISE; ++ ++ cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1, ++ NULL, GFP_KERNEL); ++ ++ return 0; ++} ++ ++static s32 ++brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv, ++ struct net_device *ndev, ++ const struct brcmf_event_msg *e, void *data) ++{ ++ struct brcmf_channel_info_le channel_inform_le; ++ struct brcmf_scan_results_le *bss_list_le; ++ u32 len = WL_SCAN_BUF_MAX; ++ s32 err = 0; ++ bool scan_abort = false; ++ u32 scan_channel; ++ ++ WL_TRACE("Enter\n"); ++ ++ if (cfg_priv->iscan_on && cfg_priv->iscan_kickstart) { ++ WL_TRACE("Exit\n"); ++ return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv)); ++ } ++ ++ if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { ++ WL_ERR("Scan complete while device not scanning\n"); ++ scan_abort = true; ++ err = -EINVAL; ++ goto scan_done_out; ++ } ++ ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_inform_le, ++ sizeof(channel_inform_le)); ++ if (err) { ++ WL_ERR("scan busy (%d)\n", err); ++ scan_abort = true; ++ goto scan_done_out; ++ } ++ scan_channel = le32_to_cpu(channel_inform_le.scan_channel); ++ if (scan_channel) ++ WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel); ++ cfg_priv->bss_list = cfg_priv->scan_results; ++ bss_list_le = (struct brcmf_scan_results_le *) cfg_priv->bss_list; ++ ++ memset(cfg_priv->scan_results, 0, len); ++ bss_list_le->buflen = cpu_to_le32(len); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS, ++ cfg_priv->scan_results, len); ++ if (err) { ++ WL_ERR("%s Scan_results error (%d)\n", ndev->name, err); ++ err = -EINVAL; ++ scan_abort = true; ++ goto scan_done_out; ++ } ++ cfg_priv->scan_results->buflen = le32_to_cpu(bss_list_le->buflen); ++ cfg_priv->scan_results->version = le32_to_cpu(bss_list_le->version); ++ cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count); ++ ++ err = brcmf_inform_bss(cfg_priv); ++ if (err) { ++ scan_abort = true; ++ goto scan_done_out; ++ } ++ ++scan_done_out: ++ if (cfg_priv->scan_request) { ++ WL_SCAN("calling cfg80211_scan_done\n"); ++ cfg80211_scan_done(cfg_priv->scan_request, scan_abort); ++ brcmf_set_mpc(ndev, 1); ++ cfg_priv->scan_request = NULL; ++ } ++ ++ WL_TRACE("Exit\n"); ++ ++ return err; ++} ++ ++static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf) ++{ ++ conf->mode = (u32)-1; ++ conf->frag_threshold = (u32)-1; ++ conf->rts_threshold = (u32)-1; ++ conf->retry_short = (u32)-1; ++ conf->retry_long = (u32)-1; ++ conf->tx_power = -1; ++} ++ ++static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el) ++{ ++ memset(el, 0, sizeof(*el)); ++ el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status; ++ el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status; ++ el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status; ++ el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status; ++ el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status; ++} ++ ++static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ kfree(cfg_priv->scan_results); ++ cfg_priv->scan_results = NULL; ++ kfree(cfg_priv->bss_info); ++ cfg_priv->bss_info = NULL; ++ kfree(cfg_priv->conf); ++ cfg_priv->conf = NULL; ++ kfree(cfg_priv->profile); ++ cfg_priv->profile = NULL; ++ kfree(cfg_priv->scan_req_int); ++ cfg_priv->scan_req_int = NULL; ++ kfree(cfg_priv->dcmd_buf); ++ cfg_priv->dcmd_buf = NULL; ++ kfree(cfg_priv->extra_buf); ++ cfg_priv->extra_buf = NULL; ++ kfree(cfg_priv->iscan); ++ cfg_priv->iscan = NULL; ++ kfree(cfg_priv->pmk_list); ++ cfg_priv->pmk_list = NULL; ++} ++ ++static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL); ++ if (!cfg_priv->scan_results) ++ goto init_priv_mem_out; ++ cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL); ++ if (!cfg_priv->conf) ++ goto init_priv_mem_out; ++ cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL); ++ if (!cfg_priv->profile) ++ goto init_priv_mem_out; ++ cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); ++ if (!cfg_priv->bss_info) ++ goto init_priv_mem_out; ++ cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int), ++ GFP_KERNEL); ++ if (!cfg_priv->scan_req_int) ++ goto init_priv_mem_out; ++ cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL); ++ if (!cfg_priv->dcmd_buf) ++ goto init_priv_mem_out; ++ cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); ++ if (!cfg_priv->extra_buf) ++ goto init_priv_mem_out; ++ cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL); ++ if (!cfg_priv->iscan) ++ goto init_priv_mem_out; ++ cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL); ++ if (!cfg_priv->pmk_list) ++ goto init_priv_mem_out; ++ ++ return 0; ++ ++init_priv_mem_out: ++ brcmf_deinit_priv_mem(cfg_priv); ++ ++ return -ENOMEM; ++} ++ ++/* ++* retrieve first queued event from head ++*/ ++ ++static struct brcmf_cfg80211_event_q *brcmf_deq_event( ++ struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_event_q *e = NULL; ++ ++ spin_lock_irq(&cfg_priv->evt_q_lock); ++ if (!list_empty(&cfg_priv->evt_q_list)) { ++ e = list_first_entry(&cfg_priv->evt_q_list, ++ struct brcmf_cfg80211_event_q, evt_q_list); ++ list_del(&e->evt_q_list); ++ } ++ spin_unlock_irq(&cfg_priv->evt_q_lock); ++ ++ return e; ++} ++ ++/* ++** push event to tail of the queue ++*/ ++ ++static s32 ++brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event, ++ const struct brcmf_event_msg *msg) ++{ ++ struct brcmf_cfg80211_event_q *e; ++ s32 err = 0; ++ ++ e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_KERNEL); ++ if (!e) ++ return -ENOMEM; ++ ++ e->etype = event; ++ memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg)); ++ ++ spin_lock_irq(&cfg_priv->evt_q_lock); ++ list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list); ++ spin_unlock_irq(&cfg_priv->evt_q_lock); ++ ++ return err; ++} ++ ++static void brcmf_put_event(struct brcmf_cfg80211_event_q *e) ++{ ++ kfree(e); ++} ++ ++static void brcmf_cfg80211_event_handler(struct work_struct *work) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ++ container_of(work, struct brcmf_cfg80211_priv, ++ event_work); ++ struct brcmf_cfg80211_event_q *e; ++ ++ e = brcmf_deq_event(cfg_priv); ++ if (unlikely(!e)) { ++ WL_ERR("event queue empty...\n"); ++ return; ++ } ++ ++ do { ++ WL_INFO("event type (%d)\n", e->etype); ++ if (cfg_priv->el.handler[e->etype]) ++ cfg_priv->el.handler[e->etype](cfg_priv, ++ cfg_to_ndev(cfg_priv), ++ &e->emsg, e->edata); ++ else ++ WL_INFO("Unknown Event (%d): ignoring\n", e->etype); ++ brcmf_put_event(e); ++ } while ((e = brcmf_deq_event(cfg_priv))); ++ ++} ++ ++static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ spin_lock_init(&cfg_priv->evt_q_lock); ++ INIT_LIST_HEAD(&cfg_priv->evt_q_list); ++} ++ ++static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_event_q *e; ++ ++ spin_lock_irq(&cfg_priv->evt_q_lock); ++ while (!list_empty(&cfg_priv->evt_q_list)) { ++ e = list_first_entry(&cfg_priv->evt_q_list, ++ struct brcmf_cfg80211_event_q, evt_q_list); ++ list_del(&e->evt_q_list); ++ kfree(e); ++ } ++ spin_unlock_irq(&cfg_priv->evt_q_lock); ++} ++ ++static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ s32 err = 0; ++ ++ cfg_priv->scan_request = NULL; ++ cfg_priv->pwr_save = true; ++ cfg_priv->iscan_on = true; /* iscan on & off switch. ++ we enable iscan per default */ ++ cfg_priv->roam_on = true; /* roam on & off switch. ++ we enable roam per default */ ++ ++ cfg_priv->iscan_kickstart = false; ++ cfg_priv->active_scan = true; /* we do active scan for ++ specific scan per default */ ++ cfg_priv->dongle_up = false; /* dongle is not up yet */ ++ brcmf_init_eq(cfg_priv); ++ err = brcmf_init_priv_mem(cfg_priv); ++ if (err) ++ return err; ++ INIT_WORK(&cfg_priv->event_work, brcmf_cfg80211_event_handler); ++ brcmf_init_eloop_handler(&cfg_priv->el); ++ mutex_init(&cfg_priv->usr_sync); ++ err = brcmf_init_iscan(cfg_priv); ++ if (err) ++ return err; ++ brcmf_init_conf(cfg_priv->conf); ++ brcmf_init_prof(cfg_priv->profile); ++ brcmf_link_down(cfg_priv); ++ ++ return err; ++} ++ ++static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ cancel_work_sync(&cfg_priv->event_work); ++ cfg_priv->dongle_up = false; /* dongle down */ ++ brcmf_flush_eq(cfg_priv); ++ brcmf_link_down(cfg_priv); ++ brcmf_term_iscan(cfg_priv); ++ brcmf_deinit_priv_mem(cfg_priv); ++} ++ ++struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, ++ struct device *busdev, ++ void *data) ++{ ++ struct wireless_dev *wdev; ++ struct brcmf_cfg80211_priv *cfg_priv; ++ struct brcmf_cfg80211_iface *ci; ++ struct brcmf_cfg80211_dev *cfg_dev; ++ s32 err = 0; ++ ++ if (!ndev) { ++ WL_ERR("ndev is invalid\n"); ++ return NULL; ++ } ++ cfg_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL); ++ if (!cfg_dev) ++ return NULL; ++ ++ wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface), busdev); ++ if (IS_ERR(wdev)) { ++ kfree(cfg_dev); ++ return NULL; ++ } ++ ++ wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS); ++ cfg_priv = wdev_to_cfg(wdev); ++ cfg_priv->wdev = wdev; ++ cfg_priv->pub = data; ++ ci = (struct brcmf_cfg80211_iface *)&cfg_priv->ci; ++ ci->cfg_priv = cfg_priv; ++ ndev->ieee80211_ptr = wdev; ++ SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); ++ wdev->netdev = ndev; ++ err = wl_init_priv(cfg_priv); ++ if (err) { ++ WL_ERR("Failed to init iwm_priv (%d)\n", err); ++ goto cfg80211_attach_out; ++ } ++ brcmf_set_drvdata(cfg_dev, ci); ++ ++ return cfg_dev; ++ ++cfg80211_attach_out: ++ brcmf_free_wdev(cfg_priv); ++ kfree(cfg_dev); ++ return NULL; ++} ++ ++void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg_dev) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv; ++ ++ cfg_priv = brcmf_priv_get(cfg_dev); ++ ++ wl_deinit_priv(cfg_priv); ++ brcmf_free_wdev(cfg_priv); ++ brcmf_set_drvdata(cfg_dev, NULL); ++ kfree(cfg_dev); ++} ++ ++void ++brcmf_cfg80211_event(struct net_device *ndev, ++ const struct brcmf_event_msg *e, void *data) ++{ ++ u32 event_type = be32_to_cpu(e->event_type); ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ ++ if (!brcmf_enq_event(cfg_priv, event_type, e)) ++ schedule_work(&cfg_priv->event_work); ++} ++ ++static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype) ++{ ++ s32 infra = 0; ++ s32 err = 0; ++ ++ switch (iftype) { ++ case NL80211_IFTYPE_MONITOR: ++ case NL80211_IFTYPE_WDS: ++ WL_ERR("type (%d) : currently we do not support this mode\n", ++ iftype); ++ err = -EINVAL; ++ return err; ++ case NL80211_IFTYPE_ADHOC: ++ infra = 0; ++ break; ++ case NL80211_IFTYPE_STATION: ++ infra = 1; ++ break; ++ default: ++ err = -EINVAL; ++ WL_ERR("invalid type (%d)\n", iftype); ++ return err; ++ } ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); ++ if (err) { ++ WL_ERR("WLC_SET_INFRA error (%d)\n", err); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static s32 brcmf_dongle_eventmsg(struct net_device *ndev) ++{ ++ /* Room for "event_msgs" + '\0' + bitvec */ ++ s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; ++ s8 eventmask[BRCMF_EVENTING_MASK_LEN]; ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ ++ /* Setup event_msgs */ ++ brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, ++ iovbuf, sizeof(iovbuf)); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf)); ++ if (err) { ++ WL_ERR("Get event_msgs error (%d)\n", err); ++ goto dongle_eventmsg_out; ++ } ++ memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN); ++ ++ setbit(eventmask, BRCMF_E_SET_SSID); ++ setbit(eventmask, BRCMF_E_ROAM); ++ setbit(eventmask, BRCMF_E_PRUNE); ++ setbit(eventmask, BRCMF_E_AUTH); ++ setbit(eventmask, BRCMF_E_REASSOC); ++ setbit(eventmask, BRCMF_E_REASSOC_IND); ++ setbit(eventmask, BRCMF_E_DEAUTH_IND); ++ setbit(eventmask, BRCMF_E_DISASSOC_IND); ++ setbit(eventmask, BRCMF_E_DISASSOC); ++ setbit(eventmask, BRCMF_E_JOIN); ++ setbit(eventmask, BRCMF_E_ASSOC_IND); ++ setbit(eventmask, BRCMF_E_PSK_SUP); ++ setbit(eventmask, BRCMF_E_LINK); ++ setbit(eventmask, BRCMF_E_NDIS_LINK); ++ setbit(eventmask, BRCMF_E_MIC_ERROR); ++ setbit(eventmask, BRCMF_E_PMKID_CACHE); ++ setbit(eventmask, BRCMF_E_TXFAIL); ++ setbit(eventmask, BRCMF_E_JOIN_START); ++ setbit(eventmask, BRCMF_E_SCAN_COMPLETE); ++ ++ brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, ++ iovbuf, sizeof(iovbuf)); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); ++ if (err) { ++ WL_ERR("Set event_msgs error (%d)\n", err); ++ goto dongle_eventmsg_out; ++ } ++ ++dongle_eventmsg_out: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) ++{ ++ s8 iovbuf[32]; ++ s32 err = 0; ++ __le32 roamtrigger[2]; ++ __le32 roam_delta[2]; ++ __le32 bcn_to_le; ++ __le32 roamvar_le; ++ ++ /* ++ * Setup timeout if Beacons are lost and roam is ++ * off to report link down ++ */ ++ if (roamvar) { ++ bcn_to_le = cpu_to_le32(bcn_timeout); ++ brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_to_le, ++ sizeof(bcn_to_le), iovbuf, sizeof(iovbuf)); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, ++ iovbuf, sizeof(iovbuf)); ++ if (err) { ++ WL_ERR("bcn_timeout error (%d)\n", err); ++ goto dongle_rom_out; ++ } ++ } ++ ++ /* ++ * Enable/Disable built-in roaming to allow supplicant ++ * to take care of roaming ++ */ ++ WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On"); ++ roamvar_le = cpu_to_le32(roamvar); ++ brcmf_c_mkiovar("roam_off", (char *)&roamvar_le, ++ sizeof(roamvar_le), iovbuf, sizeof(iovbuf)); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); ++ if (err) { ++ WL_ERR("roam_off error (%d)\n", err); ++ goto dongle_rom_out; ++ } ++ ++ roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL); ++ roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_TRIGGER, ++ (void *)roamtrigger, sizeof(roamtrigger)); ++ if (err) { ++ WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err); ++ goto dongle_rom_out; ++ } ++ ++ roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA); ++ roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_DELTA, ++ (void *)roam_delta, sizeof(roam_delta)); ++ if (err) { ++ WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err); ++ goto dongle_rom_out; ++ } ++ ++dongle_rom_out: ++ return err; ++} ++ ++static s32 ++brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, ++ s32 scan_unassoc_time, s32 scan_passive_time) ++{ ++ s32 err = 0; ++ __le32 scan_assoc_tm_le = cpu_to_le32(scan_assoc_time); ++ __le32 scan_unassoc_tm_le = cpu_to_le32(scan_unassoc_time); ++ __le32 scan_passive_tm_le = cpu_to_le32(scan_passive_time); ++ ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME, ++ &scan_assoc_tm_le, sizeof(scan_assoc_tm_le)); ++ if (err) { ++ if (err == -EOPNOTSUPP) ++ WL_INFO("Scan assoc time is not supported\n"); ++ else ++ WL_ERR("Scan assoc time error (%d)\n", err); ++ goto dongle_scantime_out; ++ } ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME, ++ &scan_unassoc_tm_le, sizeof(scan_unassoc_tm_le)); ++ if (err) { ++ if (err == -EOPNOTSUPP) ++ WL_INFO("Scan unassoc time is not supported\n"); ++ else ++ WL_ERR("Scan unassoc time error (%d)\n", err); ++ goto dongle_scantime_out; ++ } ++ ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME, ++ &scan_passive_tm_le, sizeof(scan_passive_tm_le)); ++ if (err) { ++ if (err == -EOPNOTSUPP) ++ WL_INFO("Scan passive time is not supported\n"); ++ else ++ WL_ERR("Scan passive time error (%d)\n", err); ++ goto dongle_scantime_out; ++ } ++ ++dongle_scantime_out: ++ return err; ++} ++ ++static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct wiphy *wiphy; ++ s32 phy_list; ++ s8 phy; ++ s32 err = 0; ++ ++ err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST, ++ &phy_list, sizeof(phy_list)); ++ if (err) { ++ WL_ERR("error (%d)\n", err); ++ return err; ++ } ++ ++ phy = ((char *)&phy_list)[1]; ++ WL_INFO("%c phy\n", phy); ++ if (phy == 'n' || phy == 'a') { ++ wiphy = cfg_to_wiphy(cfg_priv); ++ wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n; ++ } ++ ++ return err; ++} ++ ++static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ return wl_update_wiphybands(cfg_priv); ++} ++ ++static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct net_device *ndev; ++ struct wireless_dev *wdev; ++ s32 power_mode; ++ s32 err = 0; ++ ++ if (cfg_priv->dongle_up) ++ return err; ++ ++ ndev = cfg_to_ndev(cfg_priv); ++ wdev = ndev->ieee80211_ptr; ++ ++ brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME, ++ WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME); ++ ++ err = brcmf_dongle_eventmsg(ndev); ++ if (err) ++ goto default_conf_out; ++ ++ power_mode = cfg_priv->pwr_save ? PM_FAST : PM_OFF; ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode); ++ if (err) ++ goto default_conf_out; ++ WL_INFO("power save set to %s\n", ++ (power_mode ? "enabled" : "disabled")); ++ ++ err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1), ++ WL_BEACON_TIMEOUT); ++ if (err) ++ goto default_conf_out; ++ err = brcmf_dongle_mode(ndev, wdev->iftype); ++ if (err && err != -EINPROGRESS) ++ goto default_conf_out; ++ err = brcmf_dongle_probecap(cfg_priv); ++ if (err) ++ goto default_conf_out; ++ ++ /* -EINPROGRESS: Call commit handler */ ++ ++default_conf_out: ++ ++ cfg_priv->dongle_up = true; ++ ++ return err; ++ ++} ++ ++static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ char buf[10+IFNAMSIZ]; ++ struct dentry *fd; ++ s32 err = 0; ++ ++ sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name); ++ cfg_priv->debugfsdir = debugfs_create_dir(buf, ++ cfg_to_wiphy(cfg_priv)->debugfsdir); ++ ++ fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir, ++ (u16 *)&cfg_priv->profile->beacon_interval); ++ if (!fd) { ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++ fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir, ++ (u8 *)&cfg_priv->profile->dtim_period); ++ if (!fd) { ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++err_out: ++ return err; ++} ++ ++static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ debugfs_remove_recursive(cfg_priv->debugfsdir); ++ cfg_priv->debugfsdir = NULL; ++} ++ ++static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ s32 err = 0; ++ ++ set_bit(WL_STATUS_READY, &cfg_priv->status); ++ ++ brcmf_debugfs_add_netdev_params(cfg_priv); ++ ++ err = brcmf_config_dongle(cfg_priv); ++ if (err) ++ return err; ++ ++ brcmf_invoke_iscan(cfg_priv); ++ ++ return err; ++} ++ ++static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ /* ++ * While going down, if associated with AP disassociate ++ * from AP to save power ++ */ ++ if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) || ++ test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) && ++ test_bit(WL_STATUS_READY, &cfg_priv->status)) { ++ WL_INFO("Disassociating from AP"); ++ brcmf_link_down(cfg_priv); ++ ++ /* Make sure WPA_Supplicant receives all the event ++ generated due to DISASSOC call to the fw to keep ++ the state fw and WPA_Supplicant state consistent ++ */ ++ brcmf_delay(500); ++ } ++ ++ set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); ++ brcmf_term_iscan(cfg_priv); ++ if (cfg_priv->scan_request) { ++ cfg80211_scan_done(cfg_priv->scan_request, true); ++ /* May need to perform this to cover rmmod */ ++ /* wl_set_mpc(cfg_to_ndev(wl), 1); */ ++ cfg_priv->scan_request = NULL; ++ } ++ clear_bit(WL_STATUS_READY, &cfg_priv->status); ++ clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); ++ clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); ++ ++ brcmf_debugfs_remove_netdev(cfg_priv); ++ ++ return 0; ++} ++ ++s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv; ++ s32 err = 0; ++ ++ cfg_priv = brcmf_priv_get(cfg_dev); ++ mutex_lock(&cfg_priv->usr_sync); ++ err = __brcmf_cfg80211_up(cfg_priv); ++ mutex_unlock(&cfg_priv->usr_sync); ++ ++ return err; ++} ++ ++s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv; ++ s32 err = 0; ++ ++ cfg_priv = brcmf_priv_get(cfg_dev); ++ mutex_lock(&cfg_priv->usr_sync); ++ err = __brcmf_cfg80211_down(cfg_priv); ++ mutex_unlock(&cfg_priv->usr_sync); ++ ++ return err; ++} ++ ++static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv, ++ u8 t, u8 l, u8 *v) ++{ ++ struct brcmf_cfg80211_ie *ie = &cfg_priv->ie; ++ s32 err = 0; ++ ++ if (ie->offset + l + 2 > WL_TLV_INFO_MAX) { ++ WL_ERR("ei crosses buffer boundary\n"); ++ return -ENOSPC; ++ } ++ ie->buf[ie->offset] = t; ++ ie->buf[ie->offset + 1] = l; ++ memcpy(&ie->buf[ie->offset + 2], v, l); ++ ie->offset += l + 2; ++ ++ return err; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h.orig 2011-11-09 13:46:58.238800722 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h 2011-11-09 13:47:16.989566304 -0500 +@@ -0,0 +1,375 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _wl_cfg80211_h_ ++#define _wl_cfg80211_h_ ++ ++struct brcmf_cfg80211_conf; ++struct brcmf_cfg80211_iface; ++struct brcmf_cfg80211_priv; ++struct brcmf_cfg80211_security; ++struct brcmf_cfg80211_ibss; ++ ++#define WL_DBG_NONE 0 ++#define WL_DBG_CONN (1 << 5) ++#define WL_DBG_SCAN (1 << 4) ++#define WL_DBG_TRACE (1 << 3) ++#define WL_DBG_INFO (1 << 1) ++#define WL_DBG_ERR (1 << 0) ++#define WL_DBG_MASK ((WL_DBG_INFO | WL_DBG_ERR | WL_DBG_TRACE) | \ ++ (WL_DBG_SCAN) | (WL_DBG_CONN)) ++ ++#define WL_ERR(fmt, args...) \ ++do { \ ++ if (brcmf_dbg_level & WL_DBG_ERR) { \ ++ if (net_ratelimit()) { \ ++ printk(KERN_ERR "ERROR @%s : " fmt, \ ++ __func__, ##args); \ ++ } \ ++ } \ ++} while (0) ++ ++#if (defined BCMDBG) ++#define WL_INFO(fmt, args...) \ ++do { \ ++ if (brcmf_dbg_level & WL_DBG_INFO) { \ ++ if (net_ratelimit()) { \ ++ printk(KERN_ERR "INFO @%s : " fmt, \ ++ __func__, ##args); \ ++ } \ ++ } \ ++} while (0) ++ ++#define WL_TRACE(fmt, args...) \ ++do { \ ++ if (brcmf_dbg_level & WL_DBG_TRACE) { \ ++ if (net_ratelimit()) { \ ++ printk(KERN_ERR "TRACE @%s : " fmt, \ ++ __func__, ##args); \ ++ } \ ++ } \ ++} while (0) ++ ++#define WL_SCAN(fmt, args...) \ ++do { \ ++ if (brcmf_dbg_level & WL_DBG_SCAN) { \ ++ if (net_ratelimit()) { \ ++ printk(KERN_ERR "SCAN @%s : " fmt, \ ++ __func__, ##args); \ ++ } \ ++ } \ ++} while (0) ++ ++#define WL_CONN(fmt, args...) \ ++do { \ ++ if (brcmf_dbg_level & WL_DBG_CONN) { \ ++ if (net_ratelimit()) { \ ++ printk(KERN_ERR "CONN @%s : " fmt, \ ++ __func__, ##args); \ ++ } \ ++ } \ ++} while (0) ++ ++#else /* (defined BCMDBG) */ ++#define WL_INFO(fmt, args...) ++#define WL_TRACE(fmt, args...) ++#define WL_SCAN(fmt, args...) ++#define WL_CONN(fmt, args...) ++#endif /* (defined BCMDBG) */ ++ ++#define WL_NUM_SCAN_MAX 1 ++#define WL_NUM_PMKIDS_MAX MAXPMKID /* will be used ++ * for 2.6.33 kernel ++ * or later ++ */ ++#define WL_SCAN_BUF_MAX (1024 * 8) ++#define WL_TLV_INFO_MAX 1024 ++#define WL_BSS_INFO_MAX 2048 ++#define WL_ASSOC_INFO_MAX 512 /* ++ * needs to grab assoc info from dongle to ++ * report it to cfg80211 through "connect" ++ * event ++ */ ++#define WL_DCMD_LEN_MAX 1024 ++#define WL_EXTRA_BUF_MAX 2048 ++#define WL_ISCAN_BUF_MAX 2048 /* ++ * the buf length can be BRCMF_DCMD_MAXLEN ++ * to reduce iteration ++ */ ++#define WL_ISCAN_TIMER_INTERVAL_MS 3000 ++#define WL_SCAN_ERSULTS_LAST (BRCMF_SCAN_RESULTS_NO_MEM+1) ++#define WL_AP_MAX 256 /* virtually unlimitted as long ++ * as kernel memory allows ++ */ ++ ++#define WL_ROAM_TRIGGER_LEVEL -75 ++#define WL_ROAM_DELTA 20 ++#define WL_BEACON_TIMEOUT 3 ++ ++#define WL_SCAN_CHANNEL_TIME 40 ++#define WL_SCAN_UNASSOC_TIME 40 ++#define WL_SCAN_PASSIVE_TIME 120 ++ ++/* dongle status */ ++enum wl_status { ++ WL_STATUS_READY, ++ WL_STATUS_SCANNING, ++ WL_STATUS_SCAN_ABORTING, ++ WL_STATUS_CONNECTING, ++ WL_STATUS_CONNECTED ++}; ++ ++/* wi-fi mode */ ++enum wl_mode { ++ WL_MODE_BSS, ++ WL_MODE_IBSS, ++ WL_MODE_AP ++}; ++ ++/* dongle profile list */ ++enum wl_prof_list { ++ WL_PROF_MODE, ++ WL_PROF_SSID, ++ WL_PROF_SEC, ++ WL_PROF_IBSS, ++ WL_PROF_BAND, ++ WL_PROF_BSSID, ++ WL_PROF_ACT, ++ WL_PROF_BEACONINT, ++ WL_PROF_DTIMPERIOD ++}; ++ ++/* dongle iscan state */ ++enum wl_iscan_state { ++ WL_ISCAN_STATE_IDLE, ++ WL_ISCAN_STATE_SCANING ++}; ++ ++/* dongle configuration */ ++struct brcmf_cfg80211_conf { ++ u32 mode; /* adhoc , infrastructure or ap */ ++ u32 frag_threshold; ++ u32 rts_threshold; ++ u32 retry_short; ++ u32 retry_long; ++ s32 tx_power; ++ struct ieee80211_channel channel; ++}; ++ ++/* cfg80211 main event loop */ ++struct brcmf_cfg80211_event_loop { ++ s32(*handler[BRCMF_E_LAST]) (struct brcmf_cfg80211_priv *cfg_priv, ++ struct net_device *ndev, ++ const struct brcmf_event_msg *e, ++ void *data); ++}; ++ ++/* representing interface of cfg80211 plane */ ++struct brcmf_cfg80211_iface { ++ struct brcmf_cfg80211_priv *cfg_priv; ++}; ++ ++struct brcmf_cfg80211_dev { ++ void *driver_data; /* to store cfg80211 object information */ ++}; ++ ++/* basic structure of scan request */ ++struct brcmf_cfg80211_scan_req { ++ struct brcmf_ssid_le ssid_le; ++}; ++ ++/* basic structure of information element */ ++struct brcmf_cfg80211_ie { ++ u16 offset; ++ u8 buf[WL_TLV_INFO_MAX]; ++}; ++ ++/* event queue for cfg80211 main event */ ++struct brcmf_cfg80211_event_q { ++ struct list_head evt_q_list; ++ u32 etype; ++ struct brcmf_event_msg emsg; ++ s8 edata[1]; ++}; ++ ++/* security information with currently associated ap */ ++struct brcmf_cfg80211_security { ++ u32 wpa_versions; ++ u32 auth_type; ++ u32 cipher_pairwise; ++ u32 cipher_group; ++ u32 wpa_auth; ++}; ++ ++/* ibss information for currently joined ibss network */ ++struct brcmf_cfg80211_ibss { ++ u8 beacon_interval; /* in millisecond */ ++ u8 atim; /* in millisecond */ ++ s8 join_only; ++ u8 band; ++ u8 channel; ++}; ++ ++/* dongle profile */ ++struct brcmf_cfg80211_profile { ++ u32 mode; ++ struct brcmf_ssid ssid; ++ u8 bssid[ETH_ALEN]; ++ u16 beacon_interval; ++ u8 dtim_period; ++ struct brcmf_cfg80211_security sec; ++ struct brcmf_cfg80211_ibss ibss; ++ s32 band; ++}; ++ ++/* dongle iscan event loop */ ++struct brcmf_cfg80211_iscan_eloop { ++ s32 (*handler[WL_SCAN_ERSULTS_LAST]) ++ (struct brcmf_cfg80211_priv *cfg_priv); ++}; ++ ++/* dongle iscan controller */ ++struct brcmf_cfg80211_iscan_ctrl { ++ struct net_device *ndev; ++ struct timer_list timer; ++ u32 timer_ms; ++ u32 timer_on; ++ s32 state; ++ struct work_struct work; ++ struct brcmf_cfg80211_iscan_eloop el; ++ void *data; ++ s8 dcmd_buf[BRCMF_DCMD_SMLEN]; ++ s8 scan_buf[WL_ISCAN_BUF_MAX]; ++}; ++ ++/* association inform */ ++struct brcmf_cfg80211_connect_info { ++ u8 *req_ie; ++ s32 req_ie_len; ++ u8 *resp_ie; ++ s32 resp_ie_len; ++}; ++ ++/* assoc ie length */ ++struct brcmf_cfg80211_assoc_ielen_le { ++ __le32 req_len; ++ __le32 resp_len; ++}; ++ ++/* wpa2 pmk list */ ++struct brcmf_cfg80211_pmk_list { ++ struct pmkid_list pmkids; ++ struct pmkid foo[MAXPMKID - 1]; ++}; ++ ++/* dongle private data of cfg80211 interface */ ++struct brcmf_cfg80211_priv { ++ struct wireless_dev *wdev; /* representing wl cfg80211 device */ ++ struct brcmf_cfg80211_conf *conf; /* dongle configuration */ ++ struct cfg80211_scan_request *scan_request; /* scan request ++ object */ ++ struct brcmf_cfg80211_event_loop el; /* main event loop */ ++ struct list_head evt_q_list; /* used for event queue */ ++ spinlock_t evt_q_lock; /* for event queue synchronization */ ++ struct mutex usr_sync; /* maily for dongle up/down synchronization */ ++ struct brcmf_scan_results *bss_list; /* bss_list holding scanned ++ ap information */ ++ struct brcmf_scan_results *scan_results; ++ struct brcmf_cfg80211_scan_req *scan_req_int; /* scan request object ++ for internal purpose */ ++ struct wl_cfg80211_bss_info *bss_info; /* bss information for ++ cfg80211 layer */ ++ struct brcmf_cfg80211_ie ie; /* information element object for ++ internal purpose */ ++ struct brcmf_cfg80211_profile *profile; /* holding dongle profile */ ++ struct brcmf_cfg80211_iscan_ctrl *iscan; /* iscan controller */ ++ struct brcmf_cfg80211_connect_info conn_info; /* association info */ ++ struct brcmf_cfg80211_pmk_list *pmk_list; /* wpa2 pmk list */ ++ struct work_struct event_work; /* event handler work struct */ ++ unsigned long status; /* current dongle status */ ++ void *pub; ++ u32 channel; /* current channel */ ++ bool iscan_on; /* iscan on/off switch */ ++ bool iscan_kickstart; /* indicate iscan already started */ ++ bool active_scan; /* current scan mode */ ++ bool ibss_starter; /* indicates this sta is ibss starter */ ++ bool link_up; /* link/connection up flag */ ++ bool pwr_save; /* indicate whether dongle to support ++ power save mode */ ++ bool dongle_up; /* indicate whether dongle up or not */ ++ bool roam_on; /* on/off switch for dongle self-roaming */ ++ bool scan_tried; /* indicates if first scan attempted */ ++ u8 *dcmd_buf; /* dcmd buffer */ ++ u8 *extra_buf; /* maily to grab assoc information */ ++ struct dentry *debugfsdir; ++ u8 ci[0] __aligned(NETDEV_ALIGN); ++}; ++ ++static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_priv *w) ++{ ++ return w->wdev->wiphy; ++} ++ ++static inline struct brcmf_cfg80211_priv *wiphy_to_cfg(struct wiphy *w) ++{ ++ return (struct brcmf_cfg80211_priv *)(wiphy_priv(w)); ++} ++ ++static inline struct brcmf_cfg80211_priv *wdev_to_cfg(struct wireless_dev *wd) ++{ ++ return (struct brcmf_cfg80211_priv *)(wdev_priv(wd)); ++} ++ ++static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_priv *cfg) ++{ ++ return cfg->wdev->netdev; ++} ++ ++static inline struct brcmf_cfg80211_priv *ndev_to_cfg(struct net_device *ndev) ++{ ++ return wdev_to_cfg(ndev->ieee80211_ptr); ++} ++ ++#define iscan_to_cfg(i) ((struct brcmf_cfg80211_priv *)(i->data)) ++#define cfg_to_iscan(w) (w->iscan) ++ ++static inline struct ++brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_priv *cfg) ++{ ++ return &cfg->conn_info; ++} ++ ++static inline struct brcmf_bss_info *next_bss(struct brcmf_scan_results *list, ++ struct brcmf_bss_info *bss) ++{ ++ return bss = bss ? ++ (struct brcmf_bss_info *)((unsigned long)bss + ++ le32_to_cpu(bss->length)) : ++ list->bss_info; ++} ++ ++extern struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, ++ struct device *busdev, ++ void *data); ++extern void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg); ++ ++/* event handler from dongle */ ++extern void brcmf_cfg80211_event(struct net_device *ndev, ++ const struct brcmf_event_msg *e, void *data); ++extern s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev); ++extern s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev); ++ ++#endif /* _wl_cfg80211_h_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c.orig 2011-11-09 13:46:58.239800709 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c 2011-11-09 13:47:16.991566278 -0500 +@@ -0,0 +1,2079 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * File contents: support functions for PCI/PCIe ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include "types.h" ++#include "pub.h" ++#include "pmu.h" ++#include "srom.h" ++#include "nicpci.h" ++#include "aiutils.h" ++ ++/* slow_clk_ctl */ ++ /* slow clock source mask */ ++#define SCC_SS_MASK 0x00000007 ++ /* source of slow clock is LPO */ ++#define SCC_SS_LPO 0x00000000 ++ /* source of slow clock is crystal */ ++#define SCC_SS_XTAL 0x00000001 ++ /* source of slow clock is PCI */ ++#define SCC_SS_PCI 0x00000002 ++ /* LPOFreqSel, 1: 160Khz, 0: 32KHz */ ++#define SCC_LF 0x00000200 ++ /* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */ ++#define SCC_LP 0x00000400 ++ /* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */ ++#define SCC_FS 0x00000800 ++ /* IgnorePllOffReq, 1/0: ++ * power logic ignores/honors PLL clock disable requests from core ++ */ ++#define SCC_IP 0x00001000 ++ /* XtalControlEn, 1/0: ++ * power logic does/doesn't disable crystal when appropriate ++ */ ++#define SCC_XC 0x00002000 ++ /* XtalPU (RO), 1/0: crystal running/disabled */ ++#define SCC_XP 0x00004000 ++ /* ClockDivider (SlowClk = 1/(4+divisor)) */ ++#define SCC_CD_MASK 0xffff0000 ++#define SCC_CD_SHIFT 16 ++ ++/* system_clk_ctl */ ++ /* ILPen: Enable Idle Low Power */ ++#define SYCC_IE 0x00000001 ++ /* ALPen: Enable Active Low Power */ ++#define SYCC_AE 0x00000002 ++ /* ForcePLLOn */ ++#define SYCC_FP 0x00000004 ++ /* Force ALP (or HT if ALPen is not set */ ++#define SYCC_AR 0x00000008 ++ /* Force HT */ ++#define SYCC_HR 0x00000010 ++ /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */ ++#define SYCC_CD_MASK 0xffff0000 ++#define SYCC_CD_SHIFT 16 ++ ++#define CST4329_SPROM_OTP_SEL_MASK 0x00000003 ++ /* OTP is powered up, use def. CIS, no SPROM */ ++#define CST4329_DEFCIS_SEL 0 ++ /* OTP is powered up, SPROM is present */ ++#define CST4329_SPROM_SEL 1 ++ /* OTP is powered up, no SPROM */ ++#define CST4329_OTP_SEL 2 ++ /* OTP is powered down, SPROM is present */ ++#define CST4329_OTP_PWRDN 3 ++ ++#define CST4329_SPI_SDIO_MODE_MASK 0x00000004 ++#define CST4329_SPI_SDIO_MODE_SHIFT 2 ++ ++/* 43224 chip-specific ChipControl register bits */ ++#define CCTRL43224_GPIO_TOGGLE 0x8000 ++ /* 12 mA drive strength */ ++#define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 ++ /* 12 mA drive strength for later 43224s */ ++#define CCTRL_43224B0_12MA_LED_DRIVE 0xF0 ++ ++/* 43236 Chip specific ChipStatus register bits */ ++#define CST43236_SFLASH_MASK 0x00000040 ++#define CST43236_OTP_MASK 0x00000080 ++#define CST43236_HSIC_MASK 0x00000100 /* USB/HSIC */ ++#define CST43236_BP_CLK 0x00000200 /* 120/96Mbps */ ++#define CST43236_BOOT_MASK 0x00001800 ++#define CST43236_BOOT_SHIFT 11 ++#define CST43236_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ ++#define CST43236_BOOT_FROM_ROM 1 /* boot from ROM */ ++#define CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */ ++#define CST43236_BOOT_FROM_INVALID 3 ++ ++/* 4331 chip-specific ChipControl register bits */ ++ /* 0 disable */ ++#define CCTRL4331_BT_COEXIST (1<<0) ++ /* 0 SECI is disabled (JTAG functional) */ ++#define CCTRL4331_SECI (1<<1) ++ /* 0 disable */ ++#define CCTRL4331_EXT_LNA (1<<2) ++ /* sprom/gpio13-15 mux */ ++#define CCTRL4331_SPROM_GPIO13_15 (1<<3) ++ /* 0 ext pa disable, 1 ext pa enabled */ ++#define CCTRL4331_EXTPA_EN (1<<4) ++ /* set drive out GPIO_CLK on sprom_cs pin */ ++#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) ++ /* use sprom_cs pin as PCIE mdio interface */ ++#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) ++ /* aband extpa will be at gpio2/5 and sprom_dout */ ++#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) ++ /* override core control on pipe_AuxClkEnable */ ++#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) ++ /* override core control on pipe_AuxPowerDown */ ++#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) ++ /* pcie_auxclkenable */ ++#define CCTRL4331_PCIE_AUXCLKEN (1<<10) ++ /* pcie_pipe_pllpowerdown */ ++#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) ++ /* enable bt_shd0 at gpio4 */ ++#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) ++ /* enable bt_shd1 at gpio5 */ ++#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) ++ ++/* 4331 Chip specific ChipStatus register bits */ ++ /* crystal frequency 20/40Mhz */ ++#define CST4331_XTAL_FREQ 0x00000001 ++#define CST4331_SPROM_PRESENT 0x00000002 ++#define CST4331_OTP_PRESENT 0x00000004 ++#define CST4331_LDO_RF 0x00000008 ++#define CST4331_LDO_PAR 0x00000010 ++ ++/* 4319 chip-specific ChipStatus register bits */ ++#define CST4319_SPI_CPULESSUSB 0x00000001 ++#define CST4319_SPI_CLK_POL 0x00000002 ++#define CST4319_SPI_CLK_PH 0x00000008 ++ /* gpio [7:6], SDIO CIS selection */ ++#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0 ++#define CST4319_SPROM_OTP_SEL_SHIFT 6 ++ /* use default CIS, OTP is powered up */ ++#define CST4319_DEFCIS_SEL 0x00000000 ++ /* use SPROM, OTP is powered up */ ++#define CST4319_SPROM_SEL 0x00000040 ++ /* use OTP, OTP is powered up */ ++#define CST4319_OTP_SEL 0x00000080 ++ /* use SPROM, OTP is powered down */ ++#define CST4319_OTP_PWRDN 0x000000c0 ++ /* gpio [8], sdio/usb mode */ ++#define CST4319_SDIO_USB_MODE 0x00000100 ++#define CST4319_REMAP_SEL_MASK 0x00000600 ++#define CST4319_ILPDIV_EN 0x00000800 ++#define CST4319_XTAL_PD_POL 0x00001000 ++#define CST4319_LPO_SEL 0x00002000 ++#define CST4319_RES_INIT_MODE 0x0000c000 ++ /* PALDO is configured with external PNP */ ++#define CST4319_PALDO_EXTPNP 0x00010000 ++#define CST4319_CBUCK_MODE_MASK 0x00060000 ++#define CST4319_CBUCK_MODE_BURST 0x00020000 ++#define CST4319_CBUCK_MODE_LPBURST 0x00060000 ++#define CST4319_RCAL_VALID 0x01000000 ++#define CST4319_RCAL_VALUE_MASK 0x3e000000 ++#define CST4319_RCAL_VALUE_SHIFT 25 ++ ++/* 4336 chip-specific ChipStatus register bits */ ++#define CST4336_SPI_MODE_MASK 0x00000001 ++#define CST4336_SPROM_PRESENT 0x00000002 ++#define CST4336_OTP_PRESENT 0x00000004 ++#define CST4336_ARMREMAP_0 0x00000008 ++#define CST4336_ILPDIV_EN_MASK 0x00000010 ++#define CST4336_ILPDIV_EN_SHIFT 4 ++#define CST4336_XTAL_PD_POL_MASK 0x00000020 ++#define CST4336_XTAL_PD_POL_SHIFT 5 ++#define CST4336_LPO_SEL_MASK 0x00000040 ++#define CST4336_LPO_SEL_SHIFT 6 ++#define CST4336_RES_INIT_MODE_MASK 0x00000180 ++#define CST4336_RES_INIT_MODE_SHIFT 7 ++#define CST4336_CBUCK_MODE_MASK 0x00000600 ++#define CST4336_CBUCK_MODE_SHIFT 9 ++ ++/* 4313 chip-specific ChipStatus register bits */ ++#define CST4313_SPROM_PRESENT 1 ++#define CST4313_OTP_PRESENT 2 ++#define CST4313_SPROM_OTP_SEL_MASK 0x00000002 ++#define CST4313_SPROM_OTP_SEL_SHIFT 0 ++ ++/* 4313 Chip specific ChipControl register bits */ ++ /* 12 mA drive strengh for later 4313 */ ++#define CCTRL_4313_12MA_LED_DRIVE 0x00000007 ++ ++/* Manufacturer Ids */ ++#define MFGID_ARM 0x43b ++#define MFGID_BRCM 0x4bf ++#define MFGID_MIPS 0x4a7 ++ ++/* Enumeration ROM registers */ ++#define ER_EROMENTRY 0x000 ++#define ER_REMAPCONTROL 0xe00 ++#define ER_REMAPSELECT 0xe04 ++#define ER_MASTERSELECT 0xe10 ++#define ER_ITCR 0xf00 ++#define ER_ITIP 0xf04 ++ ++/* Erom entries */ ++#define ER_TAG 0xe ++#define ER_TAG1 0x6 ++#define ER_VALID 1 ++#define ER_CI 0 ++#define ER_MP 2 ++#define ER_ADD 4 ++#define ER_END 0xe ++#define ER_BAD 0xffffffff ++ ++/* EROM CompIdentA */ ++#define CIA_MFG_MASK 0xfff00000 ++#define CIA_MFG_SHIFT 20 ++#define CIA_CID_MASK 0x000fff00 ++#define CIA_CID_SHIFT 8 ++#define CIA_CCL_MASK 0x000000f0 ++#define CIA_CCL_SHIFT 4 ++ ++/* EROM CompIdentB */ ++#define CIB_REV_MASK 0xff000000 ++#define CIB_REV_SHIFT 24 ++#define CIB_NSW_MASK 0x00f80000 ++#define CIB_NSW_SHIFT 19 ++#define CIB_NMW_MASK 0x0007c000 ++#define CIB_NMW_SHIFT 14 ++#define CIB_NSP_MASK 0x00003e00 ++#define CIB_NSP_SHIFT 9 ++#define CIB_NMP_MASK 0x000001f0 ++#define CIB_NMP_SHIFT 4 ++ ++/* EROM AddrDesc */ ++#define AD_ADDR_MASK 0xfffff000 ++#define AD_SP_MASK 0x00000f00 ++#define AD_SP_SHIFT 8 ++#define AD_ST_MASK 0x000000c0 ++#define AD_ST_SHIFT 6 ++#define AD_ST_SLAVE 0x00000000 ++#define AD_ST_BRIDGE 0x00000040 ++#define AD_ST_SWRAP 0x00000080 ++#define AD_ST_MWRAP 0x000000c0 ++#define AD_SZ_MASK 0x00000030 ++#define AD_SZ_SHIFT 4 ++#define AD_SZ_4K 0x00000000 ++#define AD_SZ_8K 0x00000010 ++#define AD_SZ_16K 0x00000020 ++#define AD_SZ_SZD 0x00000030 ++#define AD_AG32 0x00000008 ++#define AD_ADDR_ALIGN 0x00000fff ++#define AD_SZ_BASE 0x00001000 /* 4KB */ ++ ++/* EROM SizeDesc */ ++#define SD_SZ_MASK 0xfffff000 ++#define SD_SG32 0x00000008 ++#define SD_SZ_ALIGN 0x00000fff ++ ++/* PCI config space bit 4 for 4306c0 slow clock source */ ++#define PCI_CFG_GPIO_SCS 0x10 ++/* PCI config space GPIO 14 for Xtal power-up */ ++#define PCI_CFG_GPIO_XTAL 0x40 ++/* PCI config space GPIO 15 for PLL power-down */ ++#define PCI_CFG_GPIO_PLL 0x80 ++ ++/* power control defines */ ++#define PLL_DELAY 150 /* us pll on delay */ ++#define FREF_DELAY 200 /* us fref change delay */ ++#define XTAL_ON_DELAY 1000 /* us crystal power-on delay */ ++ ++/* resetctrl */ ++#define AIRC_RESET 1 ++ ++#define NOREV -1 /* Invalid rev */ ++ ++/* GPIO Based LED powersave defines */ ++#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */ ++#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */ ++ ++/* When Srom support present, fields in sromcontrol */ ++#define SRC_START 0x80000000 ++#define SRC_BUSY 0x80000000 ++#define SRC_OPCODE 0x60000000 ++#define SRC_OP_READ 0x00000000 ++#define SRC_OP_WRITE 0x20000000 ++#define SRC_OP_WRDIS 0x40000000 ++#define SRC_OP_WREN 0x60000000 ++#define SRC_OTPSEL 0x00000010 ++#define SRC_LOCK 0x00000008 ++#define SRC_SIZE_MASK 0x00000006 ++#define SRC_SIZE_1K 0x00000000 ++#define SRC_SIZE_4K 0x00000002 ++#define SRC_SIZE_16K 0x00000004 ++#define SRC_SIZE_SHIFT 1 ++#define SRC_PRESENT 0x00000001 ++ ++/* External PA enable mask */ ++#define GPIO_CTRL_EPA_EN_MASK 0x40 ++ ++#define DEFAULT_GPIOTIMERVAL \ ++ ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME) ++ ++#define BADIDX (SI_MAXCORES + 1) ++ ++/* Newer chips can access PCI/PCIE and CC core without requiring to change ++ * PCI BAR0 WIN ++ */ ++#define SI_FAST(si) (((si)->pub.buscoretype == PCIE_CORE_ID) || \ ++ (((si)->pub.buscoretype == PCI_CORE_ID) && \ ++ (si)->pub.buscorerev >= 13)) ++ ++#define CCREGS_FAST(si) (((char __iomem *)((si)->curmap) + \ ++ PCI_16KB0_CCREGS_OFFSET)) ++ ++#define IS_SIM(chippkg) \ ++ ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) ++ ++/* ++ * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts ++ * before after core switching to avoid invalid register accesss inside ISR. ++ */ ++#define INTR_OFF(si, intr_val) \ ++ if ((si)->intrsoff_fn && \ ++ (si)->coreid[(si)->curidx] == (si)->dev_coreid) \ ++ intr_val = (*(si)->intrsoff_fn)((si)->intr_arg) ++ ++#define INTR_RESTORE(si, intr_val) \ ++ if ((si)->intrsrestore_fn && \ ++ (si)->coreid[(si)->curidx] == (si)->dev_coreid) \ ++ (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val) ++ ++#define PCI(si) ((si)->pub.buscoretype == PCI_CORE_ID) ++#define PCIE(si) ((si)->pub.buscoretype == PCIE_CORE_ID) ++ ++#define PCI_FORCEHT(si) (PCIE(si) && (si->pub.chip == BCM4716_CHIP_ID)) ++ ++#ifdef BCMDBG ++#define SI_MSG(args) printk args ++#else ++#define SI_MSG(args) ++#endif /* BCMDBG */ ++ ++#define GOODCOREADDR(x, b) \ ++ (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ ++ IS_ALIGNED((x), SI_CORE_SIZE)) ++ ++#define PCIEREGS(si) ((__iomem char *)((si)->curmap) + \ ++ PCI_16KB0_PCIREGS_OFFSET) ++ ++struct aidmp { ++ u32 oobselina30; /* 0x000 */ ++ u32 oobselina74; /* 0x004 */ ++ u32 PAD[6]; ++ u32 oobselinb30; /* 0x020 */ ++ u32 oobselinb74; /* 0x024 */ ++ u32 PAD[6]; ++ u32 oobselinc30; /* 0x040 */ ++ u32 oobselinc74; /* 0x044 */ ++ u32 PAD[6]; ++ u32 oobselind30; /* 0x060 */ ++ u32 oobselind74; /* 0x064 */ ++ u32 PAD[38]; ++ u32 oobselouta30; /* 0x100 */ ++ u32 oobselouta74; /* 0x104 */ ++ u32 PAD[6]; ++ u32 oobseloutb30; /* 0x120 */ ++ u32 oobseloutb74; /* 0x124 */ ++ u32 PAD[6]; ++ u32 oobseloutc30; /* 0x140 */ ++ u32 oobseloutc74; /* 0x144 */ ++ u32 PAD[6]; ++ u32 oobseloutd30; /* 0x160 */ ++ u32 oobseloutd74; /* 0x164 */ ++ u32 PAD[38]; ++ u32 oobsynca; /* 0x200 */ ++ u32 oobseloutaen; /* 0x204 */ ++ u32 PAD[6]; ++ u32 oobsyncb; /* 0x220 */ ++ u32 oobseloutben; /* 0x224 */ ++ u32 PAD[6]; ++ u32 oobsyncc; /* 0x240 */ ++ u32 oobseloutcen; /* 0x244 */ ++ u32 PAD[6]; ++ u32 oobsyncd; /* 0x260 */ ++ u32 oobseloutden; /* 0x264 */ ++ u32 PAD[38]; ++ u32 oobaextwidth; /* 0x300 */ ++ u32 oobainwidth; /* 0x304 */ ++ u32 oobaoutwidth; /* 0x308 */ ++ u32 PAD[5]; ++ u32 oobbextwidth; /* 0x320 */ ++ u32 oobbinwidth; /* 0x324 */ ++ u32 oobboutwidth; /* 0x328 */ ++ u32 PAD[5]; ++ u32 oobcextwidth; /* 0x340 */ ++ u32 oobcinwidth; /* 0x344 */ ++ u32 oobcoutwidth; /* 0x348 */ ++ u32 PAD[5]; ++ u32 oobdextwidth; /* 0x360 */ ++ u32 oobdinwidth; /* 0x364 */ ++ u32 oobdoutwidth; /* 0x368 */ ++ u32 PAD[37]; ++ u32 ioctrlset; /* 0x400 */ ++ u32 ioctrlclear; /* 0x404 */ ++ u32 ioctrl; /* 0x408 */ ++ u32 PAD[61]; ++ u32 iostatus; /* 0x500 */ ++ u32 PAD[127]; ++ u32 ioctrlwidth; /* 0x700 */ ++ u32 iostatuswidth; /* 0x704 */ ++ u32 PAD[62]; ++ u32 resetctrl; /* 0x800 */ ++ u32 resetstatus; /* 0x804 */ ++ u32 resetreadid; /* 0x808 */ ++ u32 resetwriteid; /* 0x80c */ ++ u32 PAD[60]; ++ u32 errlogctrl; /* 0x900 */ ++ u32 errlogdone; /* 0x904 */ ++ u32 errlogstatus; /* 0x908 */ ++ u32 errlogaddrlo; /* 0x90c */ ++ u32 errlogaddrhi; /* 0x910 */ ++ u32 errlogid; /* 0x914 */ ++ u32 errloguser; /* 0x918 */ ++ u32 errlogflags; /* 0x91c */ ++ u32 PAD[56]; ++ u32 intstatus; /* 0xa00 */ ++ u32 PAD[127]; ++ u32 config; /* 0xe00 */ ++ u32 PAD[63]; ++ u32 itcr; /* 0xf00 */ ++ u32 PAD[3]; ++ u32 itipooba; /* 0xf10 */ ++ u32 itipoobb; /* 0xf14 */ ++ u32 itipoobc; /* 0xf18 */ ++ u32 itipoobd; /* 0xf1c */ ++ u32 PAD[4]; ++ u32 itipoobaout; /* 0xf30 */ ++ u32 itipoobbout; /* 0xf34 */ ++ u32 itipoobcout; /* 0xf38 */ ++ u32 itipoobdout; /* 0xf3c */ ++ u32 PAD[4]; ++ u32 itopooba; /* 0xf50 */ ++ u32 itopoobb; /* 0xf54 */ ++ u32 itopoobc; /* 0xf58 */ ++ u32 itopoobd; /* 0xf5c */ ++ u32 PAD[4]; ++ u32 itopoobain; /* 0xf70 */ ++ u32 itopoobbin; /* 0xf74 */ ++ u32 itopoobcin; /* 0xf78 */ ++ u32 itopoobdin; /* 0xf7c */ ++ u32 PAD[4]; ++ u32 itopreset; /* 0xf90 */ ++ u32 PAD[15]; ++ u32 peripherialid4; /* 0xfd0 */ ++ u32 peripherialid5; /* 0xfd4 */ ++ u32 peripherialid6; /* 0xfd8 */ ++ u32 peripherialid7; /* 0xfdc */ ++ u32 peripherialid0; /* 0xfe0 */ ++ u32 peripherialid1; /* 0xfe4 */ ++ u32 peripherialid2; /* 0xfe8 */ ++ u32 peripherialid3; /* 0xfec */ ++ u32 componentid0; /* 0xff0 */ ++ u32 componentid1; /* 0xff4 */ ++ u32 componentid2; /* 0xff8 */ ++ u32 componentid3; /* 0xffc */ ++}; ++ ++/* EROM parsing */ ++ ++static u32 ++get_erom_ent(struct si_pub *sih, u32 __iomem **eromptr, u32 mask, u32 match) ++{ ++ u32 ent; ++ uint inv = 0, nom = 0; ++ ++ while (true) { ++ ent = R_REG(*eromptr); ++ (*eromptr)++; ++ ++ if (mask == 0) ++ break; ++ ++ if ((ent & ER_VALID) == 0) { ++ inv++; ++ continue; ++ } ++ ++ if (ent == (ER_END | ER_VALID)) ++ break; ++ ++ if ((ent & mask) == match) ++ break; ++ ++ nom++; ++ } ++ ++ return ent; ++} ++ ++static u32 ++get_asd(struct si_pub *sih, u32 __iomem **eromptr, uint sp, uint ad, uint st, ++ u32 *addrl, u32 *addrh, u32 *sizel, u32 *sizeh) ++{ ++ u32 asd, sz, szd; ++ ++ asd = get_erom_ent(sih, eromptr, ER_VALID, ER_VALID); ++ if (((asd & ER_TAG1) != ER_ADD) || ++ (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) || ++ ((asd & AD_ST_MASK) != st)) { ++ /* This is not what we want, "push" it back */ ++ (*eromptr)--; ++ return 0; ++ } ++ *addrl = asd & AD_ADDR_MASK; ++ if (asd & AD_AG32) ++ *addrh = get_erom_ent(sih, eromptr, 0, 0); ++ else ++ *addrh = 0; ++ *sizeh = 0; ++ sz = asd & AD_SZ_MASK; ++ if (sz == AD_SZ_SZD) { ++ szd = get_erom_ent(sih, eromptr, 0, 0); ++ *sizel = szd & SD_SZ_MASK; ++ if (szd & SD_SG32) ++ *sizeh = get_erom_ent(sih, eromptr, 0, 0); ++ } else ++ *sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT); ++ ++ return asd; ++} ++ ++static void ai_hwfixup(struct si_info *sii) ++{ ++} ++ ++/* parse the enumeration rom to identify all cores */ ++static void ai_scan(struct si_pub *sih, struct chipcregs __iomem *cc) ++{ ++ struct si_info *sii = (struct si_info *)sih; ++ ++ u32 erombase; ++ u32 __iomem *eromptr, *eromlim; ++ void __iomem *regs = cc; ++ ++ erombase = R_REG(&cc->eromptr); ++ ++ /* Set wrappers address */ ++ sii->curwrap = (void *)((unsigned long)cc + SI_CORE_SIZE); ++ ++ /* Now point the window at the erom */ ++ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, erombase); ++ eromptr = regs; ++ eromlim = eromptr + (ER_REMAPCONTROL / sizeof(u32)); ++ ++ while (eromptr < eromlim) { ++ u32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp; ++ u32 mpd, asd, addrl, addrh, sizel, sizeh; ++ u32 __iomem *base; ++ uint i, j, idx; ++ bool br; ++ ++ br = false; ++ ++ /* Grok a component */ ++ cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI); ++ if (cia == (ER_END | ER_VALID)) { ++ /* Found END of erom */ ++ ai_hwfixup(sii); ++ return; ++ } ++ base = eromptr - 1; ++ cib = get_erom_ent(sih, &eromptr, 0, 0); ++ ++ if ((cib & ER_TAG) != ER_CI) { ++ /* CIA not followed by CIB */ ++ goto error; ++ } ++ ++ cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT; ++ mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT; ++ crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT; ++ nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT; ++ nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT; ++ nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; ++ nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; ++ ++ if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0)) ++ continue; ++ if ((nmw + nsw == 0)) { ++ /* A component which is not a core */ ++ if (cid == OOB_ROUTER_CORE_ID) { ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, ++ &addrl, &addrh, &sizel, &sizeh); ++ if (asd != 0) ++ sii->oob_router = addrl; ++ } ++ continue; ++ } ++ ++ idx = sii->numcores; ++/* sii->eromptr[idx] = base; */ ++ sii->cia[idx] = cia; ++ sii->cib[idx] = cib; ++ sii->coreid[idx] = cid; ++ ++ for (i = 0; i < nmp; i++) { ++ mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); ++ if ((mpd & ER_TAG) != ER_MP) { ++ /* Not enough MP entries for component */ ++ goto error; ++ } ++ } ++ ++ /* First Slave Address Descriptor should be port 0: ++ * the main register space for the core ++ */ ++ asd = ++ get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd == 0) { ++ /* Try again to see if it is a bridge */ ++ asd = ++ get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, ++ &addrh, &sizel, &sizeh); ++ if (asd != 0) ++ br = true; ++ else if ((addrh != 0) || (sizeh != 0) ++ || (sizel != SI_CORE_SIZE)) { ++ /* First Slave ASD for core malformed */ ++ goto error; ++ } ++ } ++ sii->coresba[idx] = addrl; ++ sii->coresba_size[idx] = sizel; ++ /* Get any more ASDs in port 0 */ ++ j = 1; ++ do { ++ asd = ++ get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, ++ &addrh, &sizel, &sizeh); ++ if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE)) { ++ sii->coresba2[idx] = addrl; ++ sii->coresba2_size[idx] = sizel; ++ } ++ j++; ++ } while (asd != 0); ++ ++ /* Go through the ASDs for other slave ports */ ++ for (i = 1; i < nsp; i++) { ++ j = 0; ++ do { ++ asd = ++ get_asd(sih, &eromptr, i, j++, AD_ST_SLAVE, ++ &addrl, &addrh, &sizel, &sizeh); ++ } while (asd != 0); ++ if (j == 0) { ++ /* SP has no address descriptors */ ++ goto error; ++ } ++ } ++ ++ /* Now get master wrappers */ ++ for (i = 0; i < nmw; i++) { ++ asd = ++ get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, ++ &addrh, &sizel, &sizeh); ++ if (asd == 0) { ++ /* Missing descriptor for MW */ ++ goto error; ++ } ++ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { ++ /* Master wrapper %d is not 4KB */ ++ goto error; ++ } ++ if (i == 0) ++ sii->wrapba[idx] = addrl; ++ } ++ ++ /* And finally slave wrappers */ ++ for (i = 0; i < nsw; i++) { ++ uint fwp = (nsp == 1) ? 0 : 1; ++ asd = ++ get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP, ++ &addrl, &addrh, &sizel, &sizeh); ++ if (asd == 0) { ++ /* Missing descriptor for SW */ ++ goto error; ++ } ++ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { ++ /* Slave wrapper is not 4KB */ ++ goto error; ++ } ++ if ((nmw == 0) && (i == 0)) ++ sii->wrapba[idx] = addrl; ++ } ++ ++ /* Don't record bridges */ ++ if (br) ++ continue; ++ ++ /* Done with core */ ++ sii->numcores++; ++ } ++ ++ error: ++ /* Reached end of erom without finding END */ ++ sii->numcores = 0; ++ return; ++} ++ ++/* ++ * This function changes the logical "focus" to the indicated core. ++ * Return the current core's virtual address. Since each core starts with the ++ * same set of registers (BIST, clock control, etc), the returned address ++ * contains the first register of this 'common' register block (not to be ++ * confused with 'common core'). ++ */ ++void __iomem *ai_setcoreidx(struct si_pub *sih, uint coreidx) ++{ ++ struct si_info *sii = (struct si_info *)sih; ++ u32 addr = sii->coresba[coreidx]; ++ u32 wrap = sii->wrapba[coreidx]; ++ ++ if (coreidx >= sii->numcores) ++ return NULL; ++ ++ /* point bar0 window */ ++ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, addr); ++ /* point bar0 2nd 4KB window */ ++ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN2, wrap); ++ sii->curidx = coreidx; ++ ++ return sii->curmap; ++} ++ ++/* Return the number of address spaces in current core */ ++int ai_numaddrspaces(struct si_pub *sih) ++{ ++ return 2; ++} ++ ++/* Return the address of the nth address space in the current core */ ++u32 ai_addrspace(struct si_pub *sih, uint asidx) ++{ ++ struct si_info *sii; ++ uint cidx; ++ ++ sii = (struct si_info *)sih; ++ cidx = sii->curidx; ++ ++ if (asidx == 0) ++ return sii->coresba[cidx]; ++ else if (asidx == 1) ++ return sii->coresba2[cidx]; ++ else { ++ /* Need to parse the erom again to find addr space */ ++ return 0; ++ } ++} ++ ++/* Return the size of the nth address space in the current core */ ++u32 ai_addrspacesize(struct si_pub *sih, uint asidx) ++{ ++ struct si_info *sii; ++ uint cidx; ++ ++ sii = (struct si_info *)sih; ++ cidx = sii->curidx; ++ ++ if (asidx == 0) ++ return sii->coresba_size[cidx]; ++ else if (asidx == 1) ++ return sii->coresba2_size[cidx]; ++ else { ++ /* Need to parse the erom again to find addr */ ++ return 0; ++ } ++} ++ ++uint ai_flag(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ struct aidmp *ai; ++ ++ sii = (struct si_info *)sih; ++ ai = sii->curwrap; ++ ++ return R_REG(&ai->oobselouta30) & 0x1f; ++} ++ ++void ai_setint(struct si_pub *sih, int siflag) ++{ ++} ++ ++uint ai_corevendor(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ u32 cia; ++ ++ sii = (struct si_info *)sih; ++ cia = sii->cia[sii->curidx]; ++ return (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT; ++} ++ ++uint ai_corerev(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ u32 cib; ++ ++ sii = (struct si_info *)sih; ++ cib = sii->cib[sii->curidx]; ++ return (cib & CIB_REV_MASK) >> CIB_REV_SHIFT; ++} ++ ++bool ai_iscoreup(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ struct aidmp *ai; ++ ++ sii = (struct si_info *)sih; ++ ai = sii->curwrap; ++ ++ return (((R_REG(&ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) == ++ SICF_CLOCK_EN) ++ && ((R_REG(&ai->resetctrl) & AIRC_RESET) == 0)); ++} ++ ++void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val) ++{ ++ struct si_info *sii; ++ struct aidmp *ai; ++ u32 w; ++ ++ sii = (struct si_info *)sih; ++ ++ ai = sii->curwrap; ++ ++ if (mask || val) { ++ w = ((R_REG(&ai->ioctrl) & ~mask) | val); ++ W_REG(&ai->ioctrl, w); ++ } ++} ++ ++u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val) ++{ ++ struct si_info *sii; ++ struct aidmp *ai; ++ u32 w; ++ ++ sii = (struct si_info *)sih; ++ ai = sii->curwrap; ++ ++ if (mask || val) { ++ w = ((R_REG(&ai->ioctrl) & ~mask) | val); ++ W_REG(&ai->ioctrl, w); ++ } ++ ++ return R_REG(&ai->ioctrl); ++} ++ ++/* return true if PCIE capability exists in the pci config space */ ++static bool ai_ispcie(struct si_info *sii) ++{ ++ u8 cap_ptr; ++ ++ cap_ptr = ++ pcicore_find_pci_capability(sii->pbus, PCI_CAP_ID_EXP, NULL, ++ NULL); ++ if (!cap_ptr) ++ return false; ++ ++ return true; ++} ++ ++static bool ai_buscore_prep(struct si_info *sii) ++{ ++ /* kludge to enable the clock on the 4306 which lacks a slowclock */ ++ if (!ai_ispcie(sii)) ++ ai_clkctl_xtal(&sii->pub, XTAL | PLL, ON); ++ return true; ++} ++ ++u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val) ++{ ++ struct si_info *sii; ++ struct aidmp *ai; ++ u32 w; ++ ++ sii = (struct si_info *)sih; ++ ai = sii->curwrap; ++ ++ if (mask || val) { ++ w = ((R_REG(&ai->iostatus) & ~mask) | val); ++ W_REG(&ai->iostatus, w); ++ } ++ ++ return R_REG(&ai->iostatus); ++} ++ ++static bool ++ai_buscore_setup(struct si_info *sii, u32 savewin, uint *origidx) ++{ ++ bool pci, pcie; ++ uint i; ++ uint pciidx, pcieidx, pcirev, pcierev; ++ struct chipcregs __iomem *cc; ++ ++ cc = ai_setcoreidx(&sii->pub, SI_CC_IDX); ++ ++ /* get chipcommon rev */ ++ sii->pub.ccrev = (int)ai_corerev(&sii->pub); ++ ++ /* get chipcommon chipstatus */ ++ if (sii->pub.ccrev >= 11) ++ sii->pub.chipst = R_REG(&cc->chipstatus); ++ ++ /* get chipcommon capabilites */ ++ sii->pub.cccaps = R_REG(&cc->capabilities); ++ /* get chipcommon extended capabilities */ ++ ++ if (sii->pub.ccrev >= 35) ++ sii->pub.cccaps_ext = R_REG(&cc->capabilities_ext); ++ ++ /* get pmu rev and caps */ ++ if (sii->pub.cccaps & CC_CAP_PMU) { ++ sii->pub.pmucaps = R_REG(&cc->pmucapabilities); ++ sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; ++ } ++ ++ /* figure out bus/orignal core idx */ ++ sii->pub.buscoretype = NODEV_CORE_ID; ++ sii->pub.buscorerev = NOREV; ++ sii->pub.buscoreidx = BADIDX; ++ ++ pci = pcie = false; ++ pcirev = pcierev = NOREV; ++ pciidx = pcieidx = BADIDX; ++ ++ for (i = 0; i < sii->numcores; i++) { ++ uint cid, crev; ++ ++ ai_setcoreidx(&sii->pub, i); ++ cid = ai_coreid(&sii->pub); ++ crev = ai_corerev(&sii->pub); ++ ++ if (cid == PCI_CORE_ID) { ++ pciidx = i; ++ pcirev = crev; ++ pci = true; ++ } else if (cid == PCIE_CORE_ID) { ++ pcieidx = i; ++ pcierev = crev; ++ pcie = true; ++ } ++ ++ /* find the core idx before entering this func. */ ++ if ((savewin && (savewin == sii->coresba[i])) || ++ (cc == sii->regs[i])) ++ *origidx = i; ++ } ++ ++ if (pci && pcie) { ++ if (ai_ispcie(sii)) ++ pci = false; ++ else ++ pcie = false; ++ } ++ if (pci) { ++ sii->pub.buscoretype = PCI_CORE_ID; ++ sii->pub.buscorerev = pcirev; ++ sii->pub.buscoreidx = pciidx; ++ } else if (pcie) { ++ sii->pub.buscoretype = PCIE_CORE_ID; ++ sii->pub.buscorerev = pcierev; ++ sii->pub.buscoreidx = pcieidx; ++ } ++ ++ /* fixup necessary chip/core configurations */ ++ if (SI_FAST(sii)) { ++ if (!sii->pch) { ++ sii->pch = pcicore_init(&sii->pub, sii->pbus, ++ (__iomem void *)PCIEREGS(sii)); ++ if (sii->pch == NULL) ++ return false; ++ } ++ } ++ if (ai_pci_fixcfg(&sii->pub)) { ++ /* si_doattach: si_pci_fixcfg failed */ ++ return false; ++ } ++ ++ /* return to the original core */ ++ ai_setcoreidx(&sii->pub, *origidx); ++ ++ return true; ++} ++ ++/* ++ * get boardtype and boardrev ++ */ ++static __used void ai_nvram_process(struct si_info *sii) ++{ ++ uint w = 0; ++ ++ /* do a pci config read to get subsystem id and subvendor id */ ++ pci_read_config_dword(sii->pbus, PCI_SUBSYSTEM_VENDOR_ID, &w); ++ ++ sii->pub.boardvendor = w & 0xffff; ++ sii->pub.boardtype = (w >> 16) & 0xffff; ++ sii->pub.boardflags = getintvar(&sii->pub, BRCMS_SROM_BOARDFLAGS); ++} ++ ++static struct si_info *ai_doattach(struct si_info *sii, ++ void __iomem *regs, struct pci_dev *pbus) ++{ ++ struct si_pub *sih = &sii->pub; ++ u32 w, savewin; ++ struct chipcregs __iomem *cc; ++ uint socitype; ++ uint origidx; ++ ++ memset((unsigned char *) sii, 0, sizeof(struct si_info)); ++ ++ savewin = 0; ++ ++ sih->buscoreidx = BADIDX; ++ ++ sii->curmap = regs; ++ sii->pbus = pbus; ++ ++ /* find Chipcommon address */ ++ pci_read_config_dword(sii->pbus, PCI_BAR0_WIN, &savewin); ++ if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) ++ savewin = SI_ENUM_BASE; ++ ++ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, ++ SI_ENUM_BASE); ++ cc = (struct chipcregs __iomem *) regs; ++ ++ /* bus/core/clk setup for register access */ ++ if (!ai_buscore_prep(sii)) ++ return NULL; ++ ++ /* ++ * ChipID recognition. ++ * We assume we can read chipid at offset 0 from the regs arg. ++ * If we add other chiptypes (or if we need to support old sdio ++ * hosts w/o chipcommon), some way of recognizing them needs to ++ * be added here. ++ */ ++ w = R_REG(&cc->chipid); ++ socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; ++ /* Might as wll fill in chip id rev & pkg */ ++ sih->chip = w & CID_ID_MASK; ++ sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; ++ sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; ++ ++ sih->issim = false; ++ ++ /* scan for cores */ ++ if (socitype == SOCI_AI) { ++ SI_MSG(("Found chip type AI (0x%08x)\n", w)); ++ /* pass chipc address instead of original core base */ ++ ai_scan(&sii->pub, cc); ++ } else { ++ /* Found chip of unknown type */ ++ return NULL; ++ } ++ /* no cores found, bail out */ ++ if (sii->numcores == 0) ++ return NULL; ++ ++ /* bus/core/clk setup */ ++ origidx = SI_CC_IDX; ++ if (!ai_buscore_setup(sii, savewin, &origidx)) ++ goto exit; ++ ++ /* Init nvram from sprom/otp if they exist */ ++ if (srom_var_init(&sii->pub, cc)) ++ goto exit; ++ ++ ai_nvram_process(sii); ++ ++ /* === NVRAM, clock is ready === */ ++ cc = (struct chipcregs __iomem *) ai_setcore(sih, CC_CORE_ID, 0); ++ W_REG(&cc->gpiopullup, 0); ++ W_REG(&cc->gpiopulldown, 0); ++ ai_setcoreidx(sih, origidx); ++ ++ /* PMU specific initializations */ ++ if (sih->cccaps & CC_CAP_PMU) { ++ u32 xtalfreq; ++ si_pmu_init(sih); ++ si_pmu_chip_init(sih); ++ ++ xtalfreq = si_pmu_measure_alpclk(sih); ++ si_pmu_pll_init(sih, xtalfreq); ++ si_pmu_res_init(sih); ++ si_pmu_swreg_init(sih); ++ } ++ ++ /* setup the GPIO based LED powersave register */ ++ w = getintvar(sih, BRCMS_SROM_LEDDC); ++ if (w == 0) ++ w = DEFAULT_GPIOTIMERVAL; ++ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, gpiotimerval), ++ ~0, w); ++ ++ if (PCIE(sii)) ++ pcicore_attach(sii->pch, SI_DOATTACH); ++ ++ if (sih->chip == BCM43224_CHIP_ID) { ++ /* ++ * enable 12 mA drive strenth for 43224 and ++ * set chipControl register bit 15 ++ */ ++ if (sih->chiprev == 0) { ++ SI_MSG(("Applying 43224A0 WARs\n")); ++ ai_corereg(sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol), ++ CCTRL43224_GPIO_TOGGLE, ++ CCTRL43224_GPIO_TOGGLE); ++ si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE, ++ CCTRL_43224A0_12MA_LED_DRIVE); ++ } ++ if (sih->chiprev >= 1) { ++ SI_MSG(("Applying 43224B0+ WARs\n")); ++ si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE, ++ CCTRL_43224B0_12MA_LED_DRIVE); ++ } ++ } ++ ++ if (sih->chip == BCM4313_CHIP_ID) { ++ /* ++ * enable 12 mA drive strenth for 4313 and ++ * set chipControl register bit 1 ++ */ ++ SI_MSG(("Applying 4313 WARs\n")); ++ si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE, ++ CCTRL_4313_12MA_LED_DRIVE); ++ } ++ ++ return sii; ++ ++ exit: ++ if (sii->pch) ++ pcicore_deinit(sii->pch); ++ sii->pch = NULL; ++ ++ return NULL; ++} ++ ++/* ++ * Allocate a si handle. ++ * devid - pci device id (used to determine chip#) ++ * osh - opaque OS handle ++ * regs - virtual address of initial core registers ++ */ ++struct si_pub * ++ai_attach(void __iomem *regs, struct pci_dev *sdh) ++{ ++ struct si_info *sii; ++ ++ /* alloc struct si_info */ ++ sii = kmalloc(sizeof(struct si_info), GFP_ATOMIC); ++ if (sii == NULL) ++ return NULL; ++ ++ if (ai_doattach(sii, regs, sdh) == NULL) { ++ kfree(sii); ++ return NULL; ++ } ++ ++ return (struct si_pub *) sii; ++} ++ ++/* may be called with core in reset */ ++void ai_detach(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ ++ struct si_pub *si_local = NULL; ++ memcpy(&si_local, &sih, sizeof(struct si_pub **)); ++ ++ sii = (struct si_info *)sih; ++ ++ if (sii == NULL) ++ return; ++ ++ if (sii->pch) ++ pcicore_deinit(sii->pch); ++ sii->pch = NULL; ++ ++ srom_free_vars(sih); ++ kfree(sii); ++} ++ ++/* register driver interrupt disabling and restoring callback functions */ ++void ++ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn, ++ void *intrsrestore_fn, ++ void *intrsenabled_fn, void *intr_arg) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ sii->intr_arg = intr_arg; ++ sii->intrsoff_fn = (u32 (*)(void *)) intrsoff_fn; ++ sii->intrsrestore_fn = (void (*) (void *, u32)) intrsrestore_fn; ++ sii->intrsenabled_fn = (bool (*)(void *)) intrsenabled_fn; ++ /* save current core id. when this function called, the current core ++ * must be the core which provides driver functions(il, et, wl, etc.) ++ */ ++ sii->dev_coreid = sii->coreid[sii->curidx]; ++} ++ ++void ai_deregister_intr_callback(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ sii->intrsoff_fn = NULL; ++} ++ ++uint ai_coreid(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ return sii->coreid[sii->curidx]; ++} ++ ++uint ai_coreidx(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ return sii->curidx; ++} ++ ++bool ai_backplane64(struct si_pub *sih) ++{ ++ return (sih->cccaps & CC_CAP_BKPLN64) != 0; ++} ++ ++/* return index of coreid or BADIDX if not found */ ++uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit) ++{ ++ struct si_info *sii; ++ uint found; ++ uint i; ++ ++ sii = (struct si_info *)sih; ++ ++ found = 0; ++ ++ for (i = 0; i < sii->numcores; i++) ++ if (sii->coreid[i] == coreid) { ++ if (found == coreunit) ++ return i; ++ found++; ++ } ++ ++ return BADIDX; ++} ++ ++/* ++ * This function changes logical "focus" to the indicated core; ++ * must be called with interrupts off. ++ * Moreover, callers should keep interrupts off during switching ++ * out of and back to d11 core. ++ */ ++void __iomem *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit) ++{ ++ uint idx; ++ ++ idx = ai_findcoreidx(sih, coreid, coreunit); ++ if (idx >= SI_MAXCORES) ++ return NULL; ++ ++ return ai_setcoreidx(sih, idx); ++} ++ ++/* Turn off interrupt as required by ai_setcore, before switch core */ ++void __iomem *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx, ++ uint *intr_val) ++{ ++ void __iomem *cc; ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ ++ if (SI_FAST(sii)) { ++ /* Overloading the origidx variable to remember the coreid, ++ * this works because the core ids cannot be confused with ++ * core indices. ++ */ ++ *origidx = coreid; ++ if (coreid == CC_CORE_ID) ++ return CCREGS_FAST(sii); ++ else if (coreid == sih->buscoretype) ++ return PCIEREGS(sii); ++ } ++ INTR_OFF(sii, *intr_val); ++ *origidx = sii->curidx; ++ cc = ai_setcore(sih, coreid, 0); ++ return cc; ++} ++ ++/* restore coreidx and restore interrupt */ ++void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ if (SI_FAST(sii) ++ && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype))) ++ return; ++ ++ ai_setcoreidx(sih, coreid); ++ INTR_RESTORE(sii, intr_val); ++} ++ ++void ai_write_wrapperreg(struct si_pub *sih, u32 offset, u32 val) ++{ ++ struct si_info *sii = (struct si_info *)sih; ++ u32 *w = (u32 *) sii->curwrap; ++ W_REG(w + (offset / 4), val); ++ return; ++} ++ ++/* ++ * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set ++ * operation, switch back to the original core, and return the new value. ++ * ++ * When using the silicon backplane, no fiddling with interrupts or core ++ * switches is needed. ++ * ++ * Also, when using pci/pcie, we can optimize away the core switching for pci ++ * registers and (on newer pci cores) chipcommon registers. ++ */ ++uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask, ++ uint val) ++{ ++ uint origidx = 0; ++ u32 __iomem *r = NULL; ++ uint w; ++ uint intr_val = 0; ++ bool fast = false; ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ ++ if (coreidx >= SI_MAXCORES) ++ return 0; ++ ++ /* ++ * If pci/pcie, we can get at pci/pcie regs ++ * and on newer cores to chipc ++ */ ++ if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) { ++ /* Chipc registers are mapped at 12KB */ ++ fast = true; ++ r = (u32 __iomem *)((__iomem char *)sii->curmap + ++ PCI_16KB0_CCREGS_OFFSET + regoff); ++ } else if (sii->pub.buscoreidx == coreidx) { ++ /* ++ * pci registers are at either in the last 2KB of ++ * an 8KB window or, in pcie and pci rev 13 at 8KB ++ */ ++ fast = true; ++ if (SI_FAST(sii)) ++ r = (u32 __iomem *)((__iomem char *)sii->curmap + ++ PCI_16KB0_PCIREGS_OFFSET + regoff); ++ else ++ r = (u32 __iomem *)((__iomem char *)sii->curmap + ++ ((regoff >= SBCONFIGOFF) ? ++ PCI_BAR0_PCISBR_OFFSET : ++ PCI_BAR0_PCIREGS_OFFSET) + regoff); ++ } ++ ++ if (!fast) { ++ INTR_OFF(sii, intr_val); ++ ++ /* save current core index */ ++ origidx = ai_coreidx(&sii->pub); ++ ++ /* switch core */ ++ r = (u32 __iomem *) ((unsigned char __iomem *) ++ ai_setcoreidx(&sii->pub, coreidx) + regoff); ++ } ++ ++ /* mask and set */ ++ if (mask || val) { ++ w = (R_REG(r) & ~mask) | val; ++ W_REG(r, w); ++ } ++ ++ /* readback */ ++ w = R_REG(r); ++ ++ if (!fast) { ++ /* restore core index */ ++ if (origidx != coreidx) ++ ai_setcoreidx(&sii->pub, origidx); ++ ++ INTR_RESTORE(sii, intr_val); ++ } ++ ++ return w; ++} ++ ++void ai_core_disable(struct si_pub *sih, u32 bits) ++{ ++ struct si_info *sii; ++ u32 dummy; ++ struct aidmp *ai; ++ ++ sii = (struct si_info *)sih; ++ ++ ai = sii->curwrap; ++ ++ /* if core is already in reset, just return */ ++ if (R_REG(&ai->resetctrl) & AIRC_RESET) ++ return; ++ ++ W_REG(&ai->ioctrl, bits); ++ dummy = R_REG(&ai->ioctrl); ++ udelay(10); ++ ++ W_REG(&ai->resetctrl, AIRC_RESET); ++ udelay(1); ++} ++ ++/* reset and re-enable a core ++ * inputs: ++ * bits - core specific bits that are set during and after reset sequence ++ * resetbits - core specific bits that are set only during reset sequence ++ */ ++void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits) ++{ ++ struct si_info *sii; ++ struct aidmp *ai; ++ u32 dummy; ++ ++ sii = (struct si_info *)sih; ++ ai = sii->curwrap; ++ ++ /* ++ * Must do the disable sequence first to work ++ * for arbitrary current core state. ++ */ ++ ai_core_disable(sih, (bits | resetbits)); ++ ++ /* ++ * Now do the initialization sequence. ++ */ ++ W_REG(&ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN)); ++ dummy = R_REG(&ai->ioctrl); ++ W_REG(&ai->resetctrl, 0); ++ udelay(1); ++ ++ W_REG(&ai->ioctrl, (bits | SICF_CLOCK_EN)); ++ dummy = R_REG(&ai->ioctrl); ++ udelay(1); ++} ++ ++/* return the slow clock source - LPO, XTAL, or PCI */ ++static uint ai_slowclk_src(struct si_info *sii) ++{ ++ struct chipcregs __iomem *cc; ++ u32 val; ++ ++ if (sii->pub.ccrev < 6) { ++ pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, ++ &val); ++ if (val & PCI_CFG_GPIO_SCS) ++ return SCC_SS_PCI; ++ return SCC_SS_XTAL; ++ } else if (sii->pub.ccrev < 10) { ++ cc = (struct chipcregs __iomem *) ++ ai_setcoreidx(&sii->pub, sii->curidx); ++ return R_REG(&cc->slow_clk_ctl) & SCC_SS_MASK; ++ } else /* Insta-clock */ ++ return SCC_SS_XTAL; ++} ++ ++/* ++* return the ILP (slowclock) min or max frequency ++* precondition: we've established the chip has dynamic clk control ++*/ ++static uint ai_slowclk_freq(struct si_info *sii, bool max_freq, ++ struct chipcregs __iomem *cc) ++{ ++ u32 slowclk; ++ uint div; ++ ++ slowclk = ai_slowclk_src(sii); ++ if (sii->pub.ccrev < 6) { ++ if (slowclk == SCC_SS_PCI) ++ return max_freq ? (PCIMAXFREQ / 64) ++ : (PCIMINFREQ / 64); ++ else ++ return max_freq ? (XTALMAXFREQ / 32) ++ : (XTALMINFREQ / 32); ++ } else if (sii->pub.ccrev < 10) { ++ div = 4 * ++ (((R_REG(&cc->slow_clk_ctl) & SCC_CD_MASK) >> ++ SCC_CD_SHIFT) + 1); ++ if (slowclk == SCC_SS_LPO) ++ return max_freq ? LPOMAXFREQ : LPOMINFREQ; ++ else if (slowclk == SCC_SS_XTAL) ++ return max_freq ? (XTALMAXFREQ / div) ++ : (XTALMINFREQ / div); ++ else if (slowclk == SCC_SS_PCI) ++ return max_freq ? (PCIMAXFREQ / div) ++ : (PCIMINFREQ / div); ++ } else { ++ /* Chipc rev 10 is InstaClock */ ++ div = R_REG(&cc->system_clk_ctl) >> SYCC_CD_SHIFT; ++ div = 4 * (div + 1); ++ return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div); ++ } ++ return 0; ++} ++ ++static void ++ai_clkctl_setdelay(struct si_info *sii, struct chipcregs __iomem *cc) ++{ ++ uint slowmaxfreq, pll_delay, slowclk; ++ uint pll_on_delay, fref_sel_delay; ++ ++ pll_delay = PLL_DELAY; ++ ++ /* ++ * If the slow clock is not sourced by the xtal then ++ * add the xtal_on_delay since the xtal will also be ++ * powered down by dynamic clk control logic. ++ */ ++ ++ slowclk = ai_slowclk_src(sii); ++ if (slowclk != SCC_SS_XTAL) ++ pll_delay += XTAL_ON_DELAY; ++ ++ /* Starting with 4318 it is ILP that is used for the delays */ ++ slowmaxfreq = ++ ai_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? false : true, cc); ++ ++ pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; ++ fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; ++ ++ W_REG(&cc->pll_on_delay, pll_on_delay); ++ W_REG(&cc->fref_sel_delay, fref_sel_delay); ++} ++ ++/* initialize power control delay registers */ ++void ai_clkctl_init(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ uint origidx = 0; ++ struct chipcregs __iomem *cc; ++ bool fast; ++ ++ if (!(sih->cccaps & CC_CAP_PWR_CTL)) ++ return; ++ ++ sii = (struct si_info *)sih; ++ fast = SI_FAST(sii); ++ if (!fast) { ++ origidx = sii->curidx; ++ cc = (struct chipcregs __iomem *) ++ ai_setcore(sih, CC_CORE_ID, 0); ++ if (cc == NULL) ++ return; ++ } else { ++ cc = (struct chipcregs __iomem *) CCREGS_FAST(sii); ++ if (cc == NULL) ++ return; ++ } ++ ++ /* set all Instaclk chip ILP to 1 MHz */ ++ if (sih->ccrev >= 10) ++ SET_REG(&cc->system_clk_ctl, SYCC_CD_MASK, ++ (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); ++ ++ ai_clkctl_setdelay(sii, cc); ++ ++ if (!fast) ++ ai_setcoreidx(sih, origidx); ++} ++ ++/* ++ * return the value suitable for writing to the ++ * dot11 core FAST_PWRUP_DELAY register ++ */ ++u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ uint origidx = 0; ++ struct chipcregs __iomem *cc; ++ uint slowminfreq; ++ u16 fpdelay; ++ uint intr_val = 0; ++ bool fast; ++ ++ sii = (struct si_info *)sih; ++ if (sih->cccaps & CC_CAP_PMU) { ++ INTR_OFF(sii, intr_val); ++ fpdelay = si_pmu_fast_pwrup_delay(sih); ++ INTR_RESTORE(sii, intr_val); ++ return fpdelay; ++ } ++ ++ if (!(sih->cccaps & CC_CAP_PWR_CTL)) ++ return 0; ++ ++ fast = SI_FAST(sii); ++ fpdelay = 0; ++ if (!fast) { ++ origidx = sii->curidx; ++ INTR_OFF(sii, intr_val); ++ cc = (struct chipcregs __iomem *) ++ ai_setcore(sih, CC_CORE_ID, 0); ++ if (cc == NULL) ++ goto done; ++ } else { ++ cc = (struct chipcregs __iomem *) CCREGS_FAST(sii); ++ if (cc == NULL) ++ goto done; ++ } ++ ++ slowminfreq = ai_slowclk_freq(sii, false, cc); ++ fpdelay = (((R_REG(&cc->pll_on_delay) + 2) * 1000000) + ++ (slowminfreq - 1)) / slowminfreq; ++ ++ done: ++ if (!fast) { ++ ai_setcoreidx(sih, origidx); ++ INTR_RESTORE(sii, intr_val); ++ } ++ return fpdelay; ++} ++ ++/* turn primary xtal and/or pll off/on */ ++int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on) ++{ ++ struct si_info *sii; ++ u32 in, out, outen; ++ ++ sii = (struct si_info *)sih; ++ ++ /* pcie core doesn't have any mapping to control the xtal pu */ ++ if (PCIE(sii)) ++ return -1; ++ ++ pci_read_config_dword(sii->pbus, PCI_GPIO_IN, &in); ++ pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, &out); ++ pci_read_config_dword(sii->pbus, PCI_GPIO_OUTEN, &outen); ++ ++ /* ++ * Avoid glitching the clock if GPRS is already using it. ++ * We can't actually read the state of the PLLPD so we infer it ++ * by the value of XTAL_PU which *is* readable via gpioin. ++ */ ++ if (on && (in & PCI_CFG_GPIO_XTAL)) ++ return 0; ++ ++ if (what & XTAL) ++ outen |= PCI_CFG_GPIO_XTAL; ++ if (what & PLL) ++ outen |= PCI_CFG_GPIO_PLL; ++ ++ if (on) { ++ /* turn primary xtal on */ ++ if (what & XTAL) { ++ out |= PCI_CFG_GPIO_XTAL; ++ if (what & PLL) ++ out |= PCI_CFG_GPIO_PLL; ++ pci_write_config_dword(sii->pbus, ++ PCI_GPIO_OUT, out); ++ pci_write_config_dword(sii->pbus, ++ PCI_GPIO_OUTEN, outen); ++ udelay(XTAL_ON_DELAY); ++ } ++ ++ /* turn pll on */ ++ if (what & PLL) { ++ out &= ~PCI_CFG_GPIO_PLL; ++ pci_write_config_dword(sii->pbus, ++ PCI_GPIO_OUT, out); ++ mdelay(2); ++ } ++ } else { ++ if (what & XTAL) ++ out &= ~PCI_CFG_GPIO_XTAL; ++ if (what & PLL) ++ out |= PCI_CFG_GPIO_PLL; ++ pci_write_config_dword(sii->pbus, ++ PCI_GPIO_OUT, out); ++ pci_write_config_dword(sii->pbus, ++ PCI_GPIO_OUTEN, outen); ++ } ++ ++ return 0; ++} ++ ++/* clk control mechanism through chipcommon, no policy checking */ ++static bool _ai_clkctl_cc(struct si_info *sii, uint mode) ++{ ++ uint origidx = 0; ++ struct chipcregs __iomem *cc; ++ u32 scc; ++ uint intr_val = 0; ++ bool fast = SI_FAST(sii); ++ ++ /* chipcommon cores prior to rev6 don't support dynamic clock control */ ++ if (sii->pub.ccrev < 6) ++ return false; ++ ++ if (!fast) { ++ INTR_OFF(sii, intr_val); ++ origidx = sii->curidx; ++ cc = (struct chipcregs __iomem *) ++ ai_setcore(&sii->pub, CC_CORE_ID, 0); ++ } else { ++ cc = (struct chipcregs __iomem *) CCREGS_FAST(sii); ++ if (cc == NULL) ++ goto done; ++ } ++ ++ if (!(sii->pub.cccaps & CC_CAP_PWR_CTL) && (sii->pub.ccrev < 20)) ++ goto done; ++ ++ switch (mode) { ++ case CLK_FAST: /* FORCEHT, fast (pll) clock */ ++ if (sii->pub.ccrev < 10) { ++ /* ++ * don't forget to force xtal back ++ * on before we clear SCC_DYN_XTAL.. ++ */ ++ ai_clkctl_xtal(&sii->pub, XTAL, ON); ++ SET_REG(&cc->slow_clk_ctl, ++ (SCC_XC | SCC_FS | SCC_IP), SCC_IP); ++ } else if (sii->pub.ccrev < 20) { ++ OR_REG(&cc->system_clk_ctl, SYCC_HR); ++ } else { ++ OR_REG(&cc->clk_ctl_st, CCS_FORCEHT); ++ } ++ ++ /* wait for the PLL */ ++ if (sii->pub.cccaps & CC_CAP_PMU) { ++ u32 htavail = CCS_HTAVAIL; ++ SPINWAIT(((R_REG(&cc->clk_ctl_st) & htavail) ++ == 0), PMU_MAX_TRANSITION_DLY); ++ } else { ++ udelay(PLL_DELAY); ++ } ++ break; ++ ++ case CLK_DYNAMIC: /* enable dynamic clock control */ ++ if (sii->pub.ccrev < 10) { ++ scc = R_REG(&cc->slow_clk_ctl); ++ scc &= ~(SCC_FS | SCC_IP | SCC_XC); ++ if ((scc & SCC_SS_MASK) != SCC_SS_XTAL) ++ scc |= SCC_XC; ++ W_REG(&cc->slow_clk_ctl, scc); ++ ++ /* ++ * for dynamic control, we have to ++ * release our xtal_pu "force on" ++ */ ++ if (scc & SCC_XC) ++ ai_clkctl_xtal(&sii->pub, XTAL, OFF); ++ } else if (sii->pub.ccrev < 20) { ++ /* Instaclock */ ++ AND_REG(&cc->system_clk_ctl, ~SYCC_HR); ++ } else { ++ AND_REG(&cc->clk_ctl_st, ~CCS_FORCEHT); ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ done: ++ if (!fast) { ++ ai_setcoreidx(&sii->pub, origidx); ++ INTR_RESTORE(sii, intr_val); ++ } ++ return mode == CLK_FAST; ++} ++ ++/* ++ * clock control policy function throught chipcommon ++ * ++ * set dynamic clk control mode (forceslow, forcefast, dynamic) ++ * returns true if we are forcing fast clock ++ * this is a wrapper over the next internal function ++ * to allow flexible policy settings for outside caller ++ */ ++bool ai_clkctl_cc(struct si_pub *sih, uint mode) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ ++ /* chipcommon cores prior to rev6 don't support dynamic clock control */ ++ if (sih->ccrev < 6) ++ return false; ++ ++ if (PCI_FORCEHT(sii)) ++ return mode == CLK_FAST; ++ ++ return _ai_clkctl_cc(sii, mode); ++} ++ ++/* Build device path */ ++int ai_devpath(struct si_pub *sih, char *path, int size) ++{ ++ int slen; ++ ++ if (!path || size <= 0) ++ return -1; ++ ++ slen = snprintf(path, (size_t) size, "pci/%u/%u/", ++ ((struct si_info *)sih)->pbus->bus->number, ++ PCI_SLOT(((struct pci_dev *) ++ (((struct si_info *)(sih))->pbus))->devfn)); ++ ++ if (slen < 0 || slen >= size) { ++ path[0] = '\0'; ++ return -1; ++ } ++ ++ return 0; ++} ++ ++void ai_pci_up(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ ++ if (PCI_FORCEHT(sii)) ++ _ai_clkctl_cc(sii, CLK_FAST); ++ ++ if (PCIE(sii)) ++ pcicore_up(sii->pch, SI_PCIUP); ++ ++} ++ ++/* Unconfigure and/or apply various WARs when system is going to sleep mode */ ++void ai_pci_sleep(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ ++ pcicore_sleep(sii->pch); ++} ++ ++/* Unconfigure and/or apply various WARs when going down */ ++void ai_pci_down(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ ++ /* release FORCEHT since chip is going to "down" state */ ++ if (PCI_FORCEHT(sii)) ++ _ai_clkctl_cc(sii, CLK_DYNAMIC); ++ ++ pcicore_down(sii->pch, SI_PCIDOWN); ++} ++ ++/* ++ * Configure the pci core for pci client (NIC) action ++ * coremask is the bitvec of cores by index to be enabled. ++ */ ++void ai_pci_setup(struct si_pub *sih, uint coremask) ++{ ++ struct si_info *sii; ++ struct sbpciregs __iomem *regs = NULL; ++ u32 siflag = 0, w; ++ uint idx = 0; ++ ++ sii = (struct si_info *)sih; ++ ++ if (PCI(sii)) { ++ /* get current core index */ ++ idx = sii->curidx; ++ ++ /* we interrupt on this backplane flag number */ ++ siflag = ai_flag(sih); ++ ++ /* switch over to pci core */ ++ regs = ai_setcoreidx(sih, sii->pub.buscoreidx); ++ } ++ ++ /* ++ * Enable sb->pci interrupts. Assume ++ * PCI rev 2.3 support was added in pci core rev 6 and things changed.. ++ */ ++ if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) { ++ /* pci config write to set this core bit in PCIIntMask */ ++ pci_read_config_dword(sii->pbus, PCI_INT_MASK, &w); ++ w |= (coremask << PCI_SBIM_SHIFT); ++ pci_write_config_dword(sii->pbus, PCI_INT_MASK, w); ++ } else { ++ /* set sbintvec bit for our flag number */ ++ ai_setint(sih, siflag); ++ } ++ ++ if (PCI(sii)) { ++ pcicore_pci_setup(sii->pch, regs); ++ ++ /* switch back to previous core */ ++ ai_setcoreidx(sih, idx); ++ } ++} ++ ++/* ++ * Fixup SROMless PCI device's configuration. ++ * The current core may be changed upon return. ++ */ ++int ai_pci_fixcfg(struct si_pub *sih) ++{ ++ uint origidx; ++ void __iomem *regs = NULL; ++ struct si_info *sii = (struct si_info *)sih; ++ ++ /* Fixup PI in SROM shadow area to enable the correct PCI core access */ ++ /* save the current index */ ++ origidx = ai_coreidx(&sii->pub); ++ ++ /* check 'pi' is correct and fix it if not */ ++ regs = ai_setcore(&sii->pub, sii->pub.buscoretype, 0); ++ if (sii->pub.buscoretype == PCIE_CORE_ID) ++ pcicore_fixcfg_pcie(sii->pch, ++ (struct sbpcieregs __iomem *)regs); ++ else if (sii->pub.buscoretype == PCI_CORE_ID) ++ pcicore_fixcfg_pci(sii->pch, (struct sbpciregs __iomem *)regs); ++ ++ /* restore the original index */ ++ ai_setcoreidx(&sii->pub, origidx); ++ ++ pcicore_hwup(sii->pch); ++ return 0; ++} ++ ++/* mask&set gpiocontrol bits */ ++u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, u8 priority) ++{ ++ uint regoff; ++ ++ regoff = offsetof(struct chipcregs, gpiocontrol); ++ return ai_corereg(sih, SI_CC_IDX, regoff, mask, val); ++} ++ ++void ai_chipcontrl_epa4331(struct si_pub *sih, bool on) ++{ ++ struct si_info *sii; ++ struct chipcregs __iomem *cc; ++ uint origidx; ++ u32 val; ++ ++ sii = (struct si_info *)sih; ++ origidx = ai_coreidx(sih); ++ ++ cc = (struct chipcregs __iomem *) ai_setcore(sih, CC_CORE_ID, 0); ++ ++ val = R_REG(&cc->chipcontrol); ++ ++ if (on) { ++ if (sih->chippkg == 9 || sih->chippkg == 0xb) ++ /* Ext PA Controls for 4331 12x9 Package */ ++ W_REG(&cc->chipcontrol, val | ++ CCTRL4331_EXTPA_EN | ++ CCTRL4331_EXTPA_ON_GPIO2_5); ++ else ++ /* Ext PA Controls for 4331 12x12 Package */ ++ W_REG(&cc->chipcontrol, ++ val | CCTRL4331_EXTPA_EN); ++ } else { ++ val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); ++ W_REG(&cc->chipcontrol, val); ++ } ++ ++ ai_setcoreidx(sih, origidx); ++} ++ ++/* Enable BT-COEX & Ex-PA for 4313 */ ++void ai_epa_4313war(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ struct chipcregs __iomem *cc; ++ uint origidx; ++ ++ sii = (struct si_info *)sih; ++ origidx = ai_coreidx(sih); ++ ++ cc = ai_setcore(sih, CC_CORE_ID, 0); ++ ++ /* EPA Fix */ ++ W_REG(&cc->gpiocontrol, ++ R_REG(&cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK); ++ ++ ai_setcoreidx(sih, origidx); ++} ++ ++/* check if the device is removed */ ++bool ai_deviceremoved(struct si_pub *sih) ++{ ++ u32 w; ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ ++ pci_read_config_dword(sii->pbus, PCI_VENDOR_ID, &w); ++ if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM) ++ return true; ++ ++ return false; ++} ++ ++bool ai_is_sprom_available(struct si_pub *sih) ++{ ++ if (sih->ccrev >= 31) { ++ struct si_info *sii; ++ uint origidx; ++ struct chipcregs __iomem *cc; ++ u32 sromctrl; ++ ++ if ((sih->cccaps & CC_CAP_SROM) == 0) ++ return false; ++ ++ sii = (struct si_info *)sih; ++ origidx = sii->curidx; ++ cc = ai_setcoreidx(sih, SI_CC_IDX); ++ sromctrl = R_REG(&cc->sromcontrol); ++ ai_setcoreidx(sih, origidx); ++ return sromctrl & SRC_PRESENT; ++ } ++ ++ switch (sih->chip) { ++ case BCM4313_CHIP_ID: ++ return (sih->chipst & CST4313_SPROM_PRESENT) != 0; ++ default: ++ return true; ++ } ++} ++ ++bool ai_is_otp_disabled(struct si_pub *sih) ++{ ++ switch (sih->chip) { ++ case BCM4313_CHIP_ID: ++ return (sih->chipst & CST4313_OTP_PRESENT) == 0; ++ /* These chips always have their OTP on */ ++ case BCM43224_CHIP_ID: ++ case BCM43225_CHIP_ID: ++ default: ++ return false; ++ } ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h.orig 2011-11-09 13:46:58.239800709 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h 2011-11-09 13:47:16.991566278 -0500 +@@ -0,0 +1,378 @@ ++/* ++ * Copyright (c) 2011 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_AIUTILS_H_ ++#define _BRCM_AIUTILS_H_ ++ ++#include "types.h" ++ ++/* ++ * SOC Interconnect Address Map. ++ * All regions may not exist on all chips. ++ */ ++/* each core gets 4Kbytes for registers */ ++#define SI_CORE_SIZE 0x1000 ++/* ++ * Max cores (this is arbitrary, for software ++ * convenience and could be changed if we ++ * make any larger chips ++ */ ++#define SI_MAXCORES 16 ++ ++/* Client Mode sb2pcitranslation2 size in bytes */ ++#define SI_PCI_DMA_SZ 0x40000000 ++ ++/* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */ ++#define SI_PCIE_DMA_H32 0x80000000 ++ ++/* core codes */ ++#define NODEV_CORE_ID 0x700 /* Invalid coreid */ ++#define CC_CORE_ID 0x800 /* chipcommon core */ ++#define ILINE20_CORE_ID 0x801 /* iline20 core */ ++#define SRAM_CORE_ID 0x802 /* sram core */ ++#define SDRAM_CORE_ID 0x803 /* sdram core */ ++#define PCI_CORE_ID 0x804 /* pci core */ ++#define MIPS_CORE_ID 0x805 /* mips core */ ++#define ENET_CORE_ID 0x806 /* enet mac core */ ++#define CODEC_CORE_ID 0x807 /* v90 codec core */ ++#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */ ++#define ADSL_CORE_ID 0x809 /* ADSL core */ ++#define ILINE100_CORE_ID 0x80a /* iline100 core */ ++#define IPSEC_CORE_ID 0x80b /* ipsec core */ ++#define UTOPIA_CORE_ID 0x80c /* utopia core */ ++#define PCMCIA_CORE_ID 0x80d /* pcmcia core */ ++#define SOCRAM_CORE_ID 0x80e /* internal memory core */ ++#define MEMC_CORE_ID 0x80f /* memc sdram core */ ++#define OFDM_CORE_ID 0x810 /* OFDM phy core */ ++#define EXTIF_CORE_ID 0x811 /* external interface core */ ++#define D11_CORE_ID 0x812 /* 802.11 MAC core */ ++#define APHY_CORE_ID 0x813 /* 802.11a phy core */ ++#define BPHY_CORE_ID 0x814 /* 802.11b phy core */ ++#define GPHY_CORE_ID 0x815 /* 802.11g phy core */ ++#define MIPS33_CORE_ID 0x816 /* mips3302 core */ ++#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */ ++#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */ ++#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */ ++#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */ ++#define SDIOH_CORE_ID 0x81b /* sdio host core */ ++#define ROBO_CORE_ID 0x81c /* roboswitch core */ ++#define ATA100_CORE_ID 0x81d /* parallel ATA core */ ++#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */ ++#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */ ++#define PCIE_CORE_ID 0x820 /* pci express core */ ++#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */ ++#define SRAMC_CORE_ID 0x822 /* SRAM controller core */ ++#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */ ++#define ARM11_CORE_ID 0x824 /* ARM 1176 core */ ++#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */ ++#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */ ++#define PMU_CORE_ID 0x827 /* PMU core */ ++#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */ ++#define SDIOD_CORE_ID 0x829 /* SDIO device core */ ++#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */ ++#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */ ++#define MIPS74K_CORE_ID 0x82c /* mips 74k core */ ++#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */ ++#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */ ++#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */ ++#define SC_CORE_ID 0x831 /* shared common core */ ++#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */ ++#define SPIH_CORE_ID 0x833 /* SPI host core */ ++#define I2S_CORE_ID 0x834 /* I2S core */ ++#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */ ++#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */ ++#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */ ++#define DEF_AI_COMP 0xfff /* Default component, in ai chips it ++ * maps all unused address ranges ++ */ ++ ++/* chipcommon being the first core: */ ++#define SI_CC_IDX 0 ++ ++/* SOC Interconnect types (aka chip types) */ ++#define SOCI_AI 1 ++ ++/* Common core control flags */ ++#define SICF_BIST_EN 0x8000 ++#define SICF_PME_EN 0x4000 ++#define SICF_CORE_BITS 0x3ffc ++#define SICF_FGC 0x0002 ++#define SICF_CLOCK_EN 0x0001 ++ ++/* Common core status flags */ ++#define SISF_BIST_DONE 0x8000 ++#define SISF_BIST_ERROR 0x4000 ++#define SISF_GATED_CLK 0x2000 ++#define SISF_DMA64 0x1000 ++#define SISF_CORE_BITS 0x0fff ++ ++/* A register that is common to all cores to ++ * communicate w/PMU regarding clock control. ++ */ ++#define SI_CLK_CTL_ST 0x1e0 /* clock control and status */ ++ ++/* clk_ctl_st register */ ++#define CCS_FORCEALP 0x00000001 /* force ALP request */ ++#define CCS_FORCEHT 0x00000002 /* force HT request */ ++#define CCS_FORCEILP 0x00000004 /* force ILP request */ ++#define CCS_ALPAREQ 0x00000008 /* ALP Avail Request */ ++#define CCS_HTAREQ 0x00000010 /* HT Avail Request */ ++#define CCS_FORCEHWREQOFF 0x00000020 /* Force HW Clock Request Off */ ++#define CCS_ERSRC_REQ_MASK 0x00000700 /* external resource requests */ ++#define CCS_ERSRC_REQ_SHIFT 8 ++#define CCS_ALPAVAIL 0x00010000 /* ALP is available */ ++#define CCS_HTAVAIL 0x00020000 /* HT is available */ ++#define CCS_BP_ON_APL 0x00040000 /* RO: running on ALP clock */ ++#define CCS_BP_ON_HT 0x00080000 /* RO: running on HT clock */ ++#define CCS_ERSRC_STS_MASK 0x07000000 /* external resource status */ ++#define CCS_ERSRC_STS_SHIFT 24 ++ ++/* HT avail in chipc and pcmcia on 4328a0 */ ++#define CCS0_HTAVAIL 0x00010000 ++/* ALP avail in chipc and pcmcia on 4328a0 */ ++#define CCS0_ALPAVAIL 0x00020000 ++ ++/* Not really related to SOC Interconnect, but a couple of software ++ * conventions for the use the flash space: ++ */ ++ ++/* Minumum amount of flash we support */ ++#define FLASH_MIN 0x00020000 /* Minimum flash size */ ++ ++#define CC_SROM_OTP 0x800 /* SROM/OTP address space */ ++ ++/* gpiotimerval */ ++#define GPIO_ONTIME_SHIFT 16 ++ ++/* Fields in clkdiv */ ++#define CLKD_OTP 0x000f0000 ++#define CLKD_OTP_SHIFT 16 ++ ++/* Package IDs */ ++#define BCM4717_PKG_ID 9 /* 4717 package id */ ++#define BCM4718_PKG_ID 10 /* 4718 package id */ ++#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */ ++ ++/* these are router chips */ ++#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */ ++#define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */ ++#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */ ++ ++/* dynamic clock control defines */ ++#define LPOMINFREQ 25000 /* low power oscillator min */ ++#define LPOMAXFREQ 43000 /* low power oscillator max */ ++#define XTALMINFREQ 19800000 /* 20 MHz - 1% */ ++#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */ ++#define PCIMINFREQ 25000000 /* 25 MHz */ ++#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */ ++ ++#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ ++#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ ++ ++/* clkctl xtal what flags */ ++#define XTAL 0x1 /* primary crystal oscillator (2050) */ ++#define PLL 0x2 /* main chip pll */ ++ ++/* clkctl clk mode */ ++#define CLK_FAST 0 /* force fast (pll) clock */ ++#define CLK_DYNAMIC 2 /* enable dynamic clock control */ ++ ++/* GPIO usage priorities */ ++#define GPIO_DRV_PRIORITY 0 /* Driver */ ++#define GPIO_APP_PRIORITY 1 /* Application */ ++#define GPIO_HI_PRIORITY 2 /* Highest priority. Ignore GPIO ++ * reservation ++ */ ++ ++/* GPIO pull up/down */ ++#define GPIO_PULLUP 0 ++#define GPIO_PULLDN 1 ++ ++/* GPIO event regtype */ ++#define GPIO_REGEVT 0 /* GPIO register event */ ++#define GPIO_REGEVT_INTMSK 1 /* GPIO register event int mask */ ++#define GPIO_REGEVT_INTPOL 2 /* GPIO register event int polarity */ ++ ++/* device path */ ++#define SI_DEVPATH_BUFSZ 16 /* min buffer size in bytes */ ++ ++/* SI routine enumeration: to be used by update function with multiple hooks */ ++#define SI_DOATTACH 1 ++#define SI_PCIDOWN 2 ++#define SI_PCIUP 3 ++ ++/* ++ * Data structure to export all chip specific common variables ++ * public (read-only) portion of aiutils handle returned by si_attach() ++ */ ++struct si_pub { ++ uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */ ++ uint buscorerev; /* buscore rev */ ++ uint buscoreidx; /* buscore index */ ++ int ccrev; /* chip common core rev */ ++ u32 cccaps; /* chip common capabilities */ ++ u32 cccaps_ext; /* chip common capabilities extension */ ++ int pmurev; /* pmu core rev */ ++ u32 pmucaps; /* pmu capabilities */ ++ uint boardtype; /* board type */ ++ uint boardvendor; /* board vendor */ ++ uint boardflags; /* board flags */ ++ uint boardflags2; /* board flags2 */ ++ uint chip; /* chip number */ ++ uint chiprev; /* chip revision */ ++ uint chippkg; /* chip package option */ ++ u32 chipst; /* chip status */ ++ bool issim; /* chip is in simulation or emulation */ ++ uint socirev; /* SOC interconnect rev */ ++ bool pci_pr32414; ++ ++}; ++ ++struct pci_dev; ++ ++struct gpioh_item { ++ void *arg; ++ bool level; ++ void (*handler) (u32 stat, void *arg); ++ u32 event; ++ struct gpioh_item *next; ++}; ++ ++/* misc si info needed by some of the routines */ ++struct si_info { ++ struct si_pub pub; /* back plane public state (must be first) */ ++ struct pci_dev *pbus; /* handle to pci bus */ ++ uint dev_coreid; /* the core provides driver functions */ ++ void *intr_arg; /* interrupt callback function arg */ ++ u32 (*intrsoff_fn) (void *intr_arg); /* turns chip interrupts off */ ++ /* restore chip interrupts */ ++ void (*intrsrestore_fn) (void *intr_arg, u32 arg); ++ /* check if interrupts are enabled */ ++ bool (*intrsenabled_fn) (void *intr_arg); ++ ++ struct pcicore_info *pch; /* PCI/E core handle */ ++ ++ struct list_head var_list; /* list of srom variables */ ++ ++ void __iomem *curmap; /* current regs va */ ++ void __iomem *regs[SI_MAXCORES]; /* other regs va */ ++ ++ uint curidx; /* current core index */ ++ uint numcores; /* # discovered cores */ ++ uint coreid[SI_MAXCORES]; /* id of each core */ ++ u32 coresba[SI_MAXCORES]; /* backplane address of each core */ ++ void *regs2[SI_MAXCORES]; /* 2nd virtual address per core (usbh20) */ ++ u32 coresba2[SI_MAXCORES]; /* 2nd phys address per core (usbh20) */ ++ u32 coresba_size[SI_MAXCORES]; /* backplane address space size */ ++ u32 coresba2_size[SI_MAXCORES]; /* second address space size */ ++ ++ void *curwrap; /* current wrapper va */ ++ void *wrappers[SI_MAXCORES]; /* other cores wrapper va */ ++ u32 wrapba[SI_MAXCORES]; /* address of controlling wrapper */ ++ ++ u32 cia[SI_MAXCORES]; /* erom cia entry for each core */ ++ u32 cib[SI_MAXCORES]; /* erom cia entry for each core */ ++ u32 oob_router; /* oob router registers for axi */ ++}; ++ ++/* ++ * Many of the routines below take an 'sih' handle as their first arg. ++ * Allocate this by calling si_attach(). Free it by calling si_detach(). ++ * At any one time, the sih is logically focused on one particular si core ++ * (the "current core"). ++ * Use si_setcore() or si_setcoreidx() to change the association to another core ++ */ ++ ++ ++/* AMBA Interconnect exported externs */ ++extern uint ai_flag(struct si_pub *sih); ++extern void ai_setint(struct si_pub *sih, int siflag); ++extern uint ai_coreidx(struct si_pub *sih); ++extern uint ai_corevendor(struct si_pub *sih); ++extern uint ai_corerev(struct si_pub *sih); ++extern bool ai_iscoreup(struct si_pub *sih); ++extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val); ++extern void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val); ++extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val); ++extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask, ++ uint val); ++extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits); ++extern void ai_core_disable(struct si_pub *sih, u32 bits); ++extern int ai_numaddrspaces(struct si_pub *sih); ++extern u32 ai_addrspace(struct si_pub *sih, uint asidx); ++extern u32 ai_addrspacesize(struct si_pub *sih, uint asidx); ++extern void ai_write_wrap_reg(struct si_pub *sih, u32 offset, u32 val); ++ ++/* === exported functions === */ ++extern struct si_pub *ai_attach(void __iomem *regs, struct pci_dev *sdh); ++extern void ai_detach(struct si_pub *sih); ++extern uint ai_coreid(struct si_pub *sih); ++extern uint ai_corerev(struct si_pub *sih); ++extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask, ++ uint val); ++extern void ai_write_wrapperreg(struct si_pub *sih, u32 offset, u32 val); ++extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val); ++extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val); ++extern bool ai_iscoreup(struct si_pub *sih); ++extern uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit); ++extern void __iomem *ai_setcoreidx(struct si_pub *sih, uint coreidx); ++extern void __iomem *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit); ++extern void __iomem *ai_switch_core(struct si_pub *sih, uint coreid, ++ uint *origidx, uint *intr_val); ++extern void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val); ++extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits); ++extern void ai_core_disable(struct si_pub *sih, u32 bits); ++extern u32 ai_alp_clock(struct si_pub *sih); ++extern u32 ai_ilp_clock(struct si_pub *sih); ++extern void ai_pci_setup(struct si_pub *sih, uint coremask); ++extern void ai_setint(struct si_pub *sih, int siflag); ++extern bool ai_backplane64(struct si_pub *sih); ++extern void ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn, ++ void *intrsrestore_fn, ++ void *intrsenabled_fn, void *intr_arg); ++extern void ai_deregister_intr_callback(struct si_pub *sih); ++extern void ai_clkctl_init(struct si_pub *sih); ++extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih); ++extern bool ai_clkctl_cc(struct si_pub *sih, uint mode); ++extern int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on); ++extern bool ai_deviceremoved(struct si_pub *sih); ++extern u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, ++ u8 priority); ++ ++/* OTP status */ ++extern bool ai_is_otp_disabled(struct si_pub *sih); ++ ++/* SPROM availability */ ++extern bool ai_is_sprom_available(struct si_pub *sih); ++ ++/* ++ * Build device path. Path size must be >= SI_DEVPATH_BUFSZ. ++ * The returned path is NULL terminated and has trailing '/'. ++ * Return 0 on success, nonzero otherwise. ++ */ ++extern int ai_devpath(struct si_pub *sih, char *path, int size); ++ ++extern void ai_pci_sleep(struct si_pub *sih); ++extern void ai_pci_down(struct si_pub *sih); ++extern void ai_pci_up(struct si_pub *sih); ++extern int ai_pci_fixcfg(struct si_pub *sih); ++ ++extern void ai_chipcontrl_epa4331(struct si_pub *sih, bool on); ++/* Enable Ex-PA for 4313 */ ++extern void ai_epa_4313war(struct si_pub *sih); ++ ++#endif /* _BRCM_AIUTILS_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c.orig 2011-11-09 13:46:58.240800696 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c 2011-11-09 13:47:16.992566265 -0500 +@@ -0,0 +1,1241 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++ ++#include "rate.h" ++#include "scb.h" ++#include "phy/phy_hal.h" ++#include "antsel.h" ++#include "main.h" ++#include "ampdu.h" ++ ++/* max number of mpdus in an ampdu */ ++#define AMPDU_MAX_MPDU 32 ++/* max number of mpdus in an ampdu to a legacy */ ++#define AMPDU_NUM_MPDU_LEGACY 16 ++/* max Tx ba window size (in pdu) */ ++#define AMPDU_TX_BA_MAX_WSIZE 64 ++/* default Tx ba window size (in pdu) */ ++#define AMPDU_TX_BA_DEF_WSIZE 64 ++/* default Rx ba window size (in pdu) */ ++#define AMPDU_RX_BA_DEF_WSIZE 64 ++/* max Rx ba window size (in pdu) */ ++#define AMPDU_RX_BA_MAX_WSIZE 64 ++/* max dur of tx ampdu (in msec) */ ++#define AMPDU_MAX_DUR 5 ++/* default tx retry limit */ ++#define AMPDU_DEF_RETRY_LIMIT 5 ++/* default tx retry limit at reg rate */ ++#define AMPDU_DEF_RR_RETRY_LIMIT 2 ++/* default weight of ampdu in txfifo */ ++#define AMPDU_DEF_TXPKT_WEIGHT 2 ++/* default ffpld reserved bytes */ ++#define AMPDU_DEF_FFPLD_RSVD 2048 ++/* # of inis to be freed on detach */ ++#define AMPDU_INI_FREE 10 ++/* max # of mpdus released at a time */ ++#define AMPDU_SCB_MAX_RELEASE 20 ++ ++#define NUM_FFPLD_FIFO 4 /* number of fifo concerned by pre-loading */ ++#define FFPLD_TX_MAX_UNFL 200 /* default value of the average number of ampdu ++ * without underflows ++ */ ++#define FFPLD_MPDU_SIZE 1800 /* estimate of maximum mpdu size */ ++#define FFPLD_MAX_MCS 23 /* we don't deal with mcs 32 */ ++#define FFPLD_PLD_INCR 1000 /* increments in bytes */ ++#define FFPLD_MAX_AMPDU_CNT 5000 /* maximum number of ampdu we ++ * accumulate between resets. ++ */ ++ ++#define AMPDU_DELIMITER_LEN 4 ++ ++/* max allowed number of mpdus in an ampdu (2 streams) */ ++#define AMPDU_NUM_MPDU 16 ++ ++#define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE) ++ ++/* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */ ++#define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\ ++ AMPDU_DELIMITER_LEN + 3\ ++ + DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN) ++ ++/* modulo add/sub, bound = 2^k */ ++#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1)) ++#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1)) ++ ++/* structure to hold tx fifo information and pre-loading state ++ * counters specific to tx underflows of ampdus ++ * some counters might be redundant with the ones in wlc or ampdu structures. ++ * This allows to maintain a specific state independently of ++ * how often and/or when the wlc counters are updated. ++ * ++ * ampdu_pld_size: number of bytes to be pre-loaded ++ * mcs2ampdu_table: per-mcs max # of mpdus in an ampdu ++ * prev_txfunfl: num of underflows last read from the HW macstats counter ++ * accum_txfunfl: num of underflows since we modified pld params ++ * accum_txampdu: num of tx ampdu since we modified pld params ++ * prev_txampdu: previous reading of tx ampdu ++ * dmaxferrate: estimated dma avg xfer rate in kbits/sec ++ */ ++struct brcms_fifo_info { ++ u16 ampdu_pld_size; ++ u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1]; ++ u16 prev_txfunfl; ++ u32 accum_txfunfl; ++ u32 accum_txampdu; ++ u32 prev_txampdu; ++ u32 dmaxferrate; ++}; ++ ++/* AMPDU module specific state ++ * ++ * wlc: pointer to main wlc structure ++ * scb_handle: scb cubby handle to retrieve data from scb ++ * ini_enable: per-tid initiator enable/disable of ampdu ++ * ba_tx_wsize: Tx ba window size (in pdu) ++ * ba_rx_wsize: Rx ba window size (in pdu) ++ * retry_limit: mpdu transmit retry limit ++ * rr_retry_limit: mpdu transmit retry limit at regular rate ++ * retry_limit_tid: per-tid mpdu transmit retry limit ++ * rr_retry_limit_tid: per-tid mpdu transmit retry limit at regular rate ++ * mpdu_density: min mpdu spacing (0-7) ==> 2^(x-1)/8 usec ++ * max_pdu: max pdus allowed in ampdu ++ * dur: max duration of an ampdu (in msec) ++ * txpkt_weight: weight of ampdu in txfifo; reduces rate lag ++ * rx_factor: maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes ++ * ffpld_rsvd: number of bytes to reserve for preload ++ * max_txlen: max size of ampdu per mcs, bw and sgi ++ * mfbr: enable multiple fallback rate ++ * tx_max_funl: underflows should be kept such that ++ * (tx_max_funfl*underflows) < tx frames ++ * fifo_tb: table of fifo infos ++ */ ++struct ampdu_info { ++ struct brcms_c_info *wlc; ++ int scb_handle; ++ u8 ini_enable[AMPDU_MAX_SCB_TID]; ++ u8 ba_tx_wsize; ++ u8 ba_rx_wsize; ++ u8 retry_limit; ++ u8 rr_retry_limit; ++ u8 retry_limit_tid[AMPDU_MAX_SCB_TID]; ++ u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID]; ++ u8 mpdu_density; ++ s8 max_pdu; ++ u8 dur; ++ u8 txpkt_weight; ++ u8 rx_factor; ++ u32 ffpld_rsvd; ++ u32 max_txlen[MCS_TABLE_SIZE][2][2]; ++ bool mfbr; ++ u32 tx_max_funl; ++ struct brcms_fifo_info fifo_tb[NUM_FFPLD_FIFO]; ++}; ++ ++/* used for flushing ampdu packets */ ++struct cb_del_ampdu_pars { ++ struct ieee80211_sta *sta; ++ u16 tid; ++}; ++ ++static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur) ++{ ++ u32 rate, mcs; ++ ++ for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) { ++ /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */ ++ /* 20MHz, No SGI */ ++ rate = mcs_2_rate(mcs, false, false); ++ ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3; ++ /* 40 MHz, No SGI */ ++ rate = mcs_2_rate(mcs, true, false); ++ ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3; ++ /* 20MHz, SGI */ ++ rate = mcs_2_rate(mcs, false, true); ++ ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3; ++ /* 40 MHz, SGI */ ++ rate = mcs_2_rate(mcs, true, true); ++ ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3; ++ } ++} ++ ++static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu) ++{ ++ if (BRCMS_PHY_11N_CAP(ampdu->wlc->band)) ++ return true; ++ else ++ return false; ++} ++ ++static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on) ++{ ++ struct brcms_c_info *wlc = ampdu->wlc; ++ ++ wlc->pub->_ampdu = false; ++ ++ if (on) { ++ if (!(wlc->pub->_n_enab & SUPPORT_11N)) { ++ wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not " ++ "nmode enabled\n", wlc->pub->unit); ++ return -ENOTSUPP; ++ } ++ if (!brcms_c_ampdu_cap(ampdu)) { ++ wiphy_err(ampdu->wlc->wiphy, "wl%d: device not " ++ "ampdu capable\n", wlc->pub->unit); ++ return -ENOTSUPP; ++ } ++ wlc->pub->_ampdu = on; ++ } ++ ++ return 0; ++} ++ ++static void brcms_c_ffpld_init(struct ampdu_info *ampdu) ++{ ++ int i, j; ++ struct brcms_fifo_info *fifo; ++ ++ for (j = 0; j < NUM_FFPLD_FIFO; j++) { ++ fifo = (ampdu->fifo_tb + j); ++ fifo->ampdu_pld_size = 0; ++ for (i = 0; i <= FFPLD_MAX_MCS; i++) ++ fifo->mcs2ampdu_table[i] = 255; ++ fifo->dmaxferrate = 0; ++ fifo->accum_txampdu = 0; ++ fifo->prev_txfunfl = 0; ++ fifo->accum_txfunfl = 0; ++ ++ } ++} ++ ++struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc) ++{ ++ struct ampdu_info *ampdu; ++ int i; ++ ++ ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC); ++ if (!ampdu) ++ return NULL; ++ ++ ampdu->wlc = wlc; ++ ++ for (i = 0; i < AMPDU_MAX_SCB_TID; i++) ++ ampdu->ini_enable[i] = true; ++ /* Disable ampdu for VO by default */ ++ ampdu->ini_enable[PRIO_8021D_VO] = false; ++ ampdu->ini_enable[PRIO_8021D_NC] = false; ++ ++ /* Disable ampdu for BK by default since not enough fifo space */ ++ ampdu->ini_enable[PRIO_8021D_NONE] = false; ++ ampdu->ini_enable[PRIO_8021D_BK] = false; ++ ++ ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE; ++ ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE; ++ ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY; ++ ampdu->max_pdu = AUTO; ++ ampdu->dur = AMPDU_MAX_DUR; ++ ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT; ++ ++ ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD; ++ /* ++ * bump max ampdu rcv size to 64k for all 11n ++ * devices except 4321A0 and 4321A1 ++ */ ++ if (BRCMS_ISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2)) ++ ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K; ++ else ++ ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K; ++ ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT; ++ ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT; ++ ++ for (i = 0; i < AMPDU_MAX_SCB_TID; i++) { ++ ampdu->retry_limit_tid[i] = ampdu->retry_limit; ++ ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit; ++ } ++ ++ brcms_c_scb_ampdu_update_max_txlen(ampdu, ampdu->dur); ++ ampdu->mfbr = false; ++ /* try to set ampdu to the default value */ ++ brcms_c_ampdu_set(ampdu, wlc->pub->_ampdu); ++ ++ ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL; ++ brcms_c_ffpld_init(ampdu); ++ ++ return ampdu; ++} ++ ++void brcms_c_ampdu_detach(struct ampdu_info *ampdu) ++{ ++ kfree(ampdu); ++} ++ ++static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu, ++ struct scb *scb) ++{ ++ struct scb_ampdu *scb_ampdu = &scb->scb_ampdu; ++ int i; ++ ++ scb_ampdu->max_pdu = AMPDU_NUM_MPDU; ++ ++ /* go back to legacy size if some preloading is occurring */ ++ for (i = 0; i < NUM_FFPLD_FIFO; i++) { ++ if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR) ++ scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY; ++ } ++ ++ /* apply user override */ ++ if (ampdu->max_pdu != AUTO) ++ scb_ampdu->max_pdu = (u8) ampdu->max_pdu; ++ ++ scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, ++ AMPDU_SCB_MAX_RELEASE); ++ ++ if (scb_ampdu->max_rx_ampdu_bytes) ++ scb_ampdu->release = min_t(u8, scb_ampdu->release, ++ scb_ampdu->max_rx_ampdu_bytes / 1600); ++ ++ scb_ampdu->release = min(scb_ampdu->release, ++ ampdu->fifo_tb[TX_AC_BE_FIFO]. ++ mcs2ampdu_table[FFPLD_MAX_MCS]); ++} ++ ++static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu) ++{ ++ brcms_c_scb_ampdu_update_config(ampdu, &du->wlc->pri_scb); ++} ++ ++static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f) ++{ ++ int i; ++ u32 phy_rate, dma_rate, tmp; ++ u8 max_mpdu; ++ struct brcms_fifo_info *fifo = (ampdu->fifo_tb + f); ++ ++ /* recompute the dma rate */ ++ /* note : we divide/multiply by 100 to avoid integer overflows */ ++ max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], ++ AMPDU_NUM_MPDU_LEGACY); ++ phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false); ++ dma_rate = ++ (((phy_rate / 100) * ++ (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size)) ++ / (max_mpdu * FFPLD_MPDU_SIZE)) * 100; ++ fifo->dmaxferrate = dma_rate; ++ ++ /* fill up the mcs2ampdu table; do not recalc the last mcs */ ++ dma_rate = dma_rate >> 7; ++ for (i = 0; i < FFPLD_MAX_MCS; i++) { ++ /* shifting to keep it within integer range */ ++ phy_rate = mcs_2_rate(i, true, false) >> 7; ++ if (phy_rate > dma_rate) { ++ tmp = ((fifo->ampdu_pld_size * phy_rate) / ++ ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1; ++ tmp = min_t(u32, tmp, 255); ++ fifo->mcs2ampdu_table[i] = (u8) tmp; ++ } ++ } ++} ++ ++/* evaluate the dma transfer rate using the tx underflows as feedback. ++ * If necessary, increase tx fifo preloading. If not enough, ++ * decrease maximum ampdu size for each mcs till underflows stop ++ * Return 1 if pre-loading not active, -1 if not an underflow event, ++ * 0 if pre-loading module took care of the event. ++ */ ++static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid) ++{ ++ struct ampdu_info *ampdu = wlc->ampdu; ++ u32 phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false); ++ u32 txunfl_ratio; ++ u8 max_mpdu; ++ u32 current_ampdu_cnt = 0; ++ u16 max_pld_size; ++ u32 new_txunfl; ++ struct brcms_fifo_info *fifo = (ampdu->fifo_tb + fid); ++ uint xmtfifo_sz; ++ u16 cur_txunfl; ++ ++ /* return if we got here for a different reason than underflows */ ++ cur_txunfl = brcms_b_read_shm(wlc->hw, ++ M_UCODE_MACSTAT + ++ offsetof(struct macstat, txfunfl[fid])); ++ new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl); ++ if (new_txunfl == 0) { ++ BCMMSG(wlc->wiphy, "TX status FRAG set but no tx underflows\n"); ++ return -1; ++ } ++ fifo->prev_txfunfl = cur_txunfl; ++ ++ if (!ampdu->tx_max_funl) ++ return 1; ++ ++ /* check if fifo is big enough */ ++ if (brcms_b_xmtfifo_sz_get(wlc->hw, fid, &xmtfifo_sz)) ++ return -1; ++ ++ if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd) ++ return 1; ++ ++ max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd; ++ fifo->accum_txfunfl += new_txunfl; ++ ++ /* we need to wait for at least 10 underflows */ ++ if (fifo->accum_txfunfl < 10) ++ return 0; ++ ++ BCMMSG(wlc->wiphy, "ampdu_count %d tx_underflows %d\n", ++ current_ampdu_cnt, fifo->accum_txfunfl); ++ ++ /* ++ compute the current ratio of tx unfl per ampdu. ++ When the current ampdu count becomes too ++ big while the ratio remains small, we reset ++ the current count in order to not ++ introduce too big of a latency in detecting a ++ large amount of tx underflows later. ++ */ ++ ++ txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl; ++ ++ if (txunfl_ratio > ampdu->tx_max_funl) { ++ if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) ++ fifo->accum_txfunfl = 0; ++ ++ return 0; ++ } ++ max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], ++ AMPDU_NUM_MPDU_LEGACY); ++ ++ /* In case max value max_pdu is already lower than ++ the fifo depth, there is nothing more we can do. ++ */ ++ ++ if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) { ++ fifo->accum_txfunfl = 0; ++ return 0; ++ } ++ ++ if (fifo->ampdu_pld_size < max_pld_size) { ++ ++ /* increment by TX_FIFO_PLD_INC bytes */ ++ fifo->ampdu_pld_size += FFPLD_PLD_INCR; ++ if (fifo->ampdu_pld_size > max_pld_size) ++ fifo->ampdu_pld_size = max_pld_size; ++ ++ /* update scb release size */ ++ brcms_c_scb_ampdu_update_config_all(ampdu); ++ ++ /* ++ * compute a new dma xfer rate for max_mpdu @ max mcs. ++ * This is the minimum dma rate that can achieve no ++ * underflow condition for the current mpdu size. ++ * ++ * note : we divide/multiply by 100 to avoid integer overflows ++ */ ++ fifo->dmaxferrate = ++ (((phy_rate / 100) * ++ (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size)) ++ / (max_mpdu * FFPLD_MPDU_SIZE)) * 100; ++ ++ BCMMSG(wlc->wiphy, "DMA estimated transfer rate %d; " ++ "pre-load size %d\n", ++ fifo->dmaxferrate, fifo->ampdu_pld_size); ++ } else { ++ ++ /* decrease ampdu size */ ++ if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) { ++ if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255) ++ fifo->mcs2ampdu_table[FFPLD_MAX_MCS] = ++ AMPDU_NUM_MPDU_LEGACY - 1; ++ else ++ fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1; ++ ++ /* recompute the table */ ++ brcms_c_ffpld_calc_mcs2ampdu_table(ampdu, fid); ++ ++ /* update scb release size */ ++ brcms_c_scb_ampdu_update_config_all(ampdu); ++ } ++ } ++ fifo->accum_txfunfl = 0; ++ return 0; ++} ++ ++void ++brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, ++ u8 ba_wsize, /* negotiated ba window size (in pdu) */ ++ uint max_rx_ampdu_bytes) /* from ht_cap in beacon */ ++{ ++ struct scb_ampdu *scb_ampdu; ++ struct scb_ampdu_tid_ini *ini; ++ struct ampdu_info *ampdu = wlc->ampdu; ++ struct scb *scb = &wlc->pri_scb; ++ scb_ampdu = &scb->scb_ampdu; ++ ++ if (!ampdu->ini_enable[tid]) { ++ wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n", ++ __func__, tid); ++ return; ++ } ++ ++ ini = &scb_ampdu->ini[tid]; ++ ini->tid = tid; ++ ini->scb = scb_ampdu->scb; ++ ini->ba_wsize = ba_wsize; ++ scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes; ++} ++ ++int ++brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi, ++ struct sk_buff **pdu, int prec) ++{ ++ struct brcms_c_info *wlc; ++ struct sk_buff *p, *pkt[AMPDU_MAX_MPDU]; ++ u8 tid, ndelim; ++ int err = 0; ++ u8 preamble_type = BRCMS_GF_PREAMBLE; ++ u8 fbr_preamble_type = BRCMS_GF_PREAMBLE; ++ u8 rts_preamble_type = BRCMS_LONG_PREAMBLE; ++ u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE; ++ ++ bool rr = true, fbr = false; ++ uint i, count = 0, fifo, seg_cnt = 0; ++ u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0; ++ u32 ampdu_len, max_ampdu_bytes = 0; ++ struct d11txh *txh = NULL; ++ u8 *plcp; ++ struct ieee80211_hdr *h; ++ struct scb *scb; ++ struct scb_ampdu *scb_ampdu; ++ struct scb_ampdu_tid_ini *ini; ++ u8 mcs = 0; ++ bool use_rts = false, use_cts = false; ++ u32 rspec = 0, rspec_fallback = 0; ++ u32 rts_rspec = 0, rts_rspec_fallback = 0; ++ u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ; ++ struct ieee80211_rts *rts; ++ u8 rr_retry_limit; ++ struct brcms_fifo_info *f; ++ bool fbr_iscck; ++ struct ieee80211_tx_info *tx_info; ++ u16 qlen; ++ struct wiphy *wiphy; ++ ++ wlc = ampdu->wlc; ++ wiphy = wlc->wiphy; ++ p = *pdu; ++ ++ tid = (u8) (p->priority); ++ ++ f = ampdu->fifo_tb + prio2fifo[tid]; ++ ++ scb = &wlc->pri_scb; ++ scb_ampdu = &scb->scb_ampdu; ++ ini = &scb_ampdu->ini[tid]; ++ ++ /* Let pressure continue to build ... */ ++ qlen = pktq_plen(&qi->q, prec); ++ if (ini->tx_in_transit > 0 && ++ qlen < min(scb_ampdu->max_pdu, ini->ba_wsize)) ++ /* Collect multiple MPDU's to be sent in the next AMPDU */ ++ return -EBUSY; ++ ++ /* at this point we intend to transmit an AMPDU */ ++ rr_retry_limit = ampdu->rr_retry_limit_tid[tid]; ++ ampdu_len = 0; ++ dma_len = 0; ++ while (p) { ++ struct ieee80211_tx_rate *txrate; ++ ++ tx_info = IEEE80211_SKB_CB(p); ++ txrate = tx_info->status.rates; ++ ++ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { ++ err = brcms_c_prep_pdu(wlc, p, &fifo); ++ } else { ++ wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__); ++ *pdu = NULL; ++ err = 0; ++ break; ++ } ++ ++ if (err) { ++ if (err == -EBUSY) { ++ wiphy_err(wiphy, "wl%d: sendampdu: " ++ "prep_xdu retry; seq 0x%x\n", ++ wlc->pub->unit, seq); ++ *pdu = p; ++ break; ++ } ++ ++ /* error in the packet; reject it */ ++ wiphy_err(wiphy, "wl%d: sendampdu: prep_xdu " ++ "rejected; seq 0x%x\n", wlc->pub->unit, seq); ++ *pdu = NULL; ++ break; ++ } ++ ++ /* pkt is good to be aggregated */ ++ txh = (struct d11txh *) p->data; ++ plcp = (u8 *) (txh + 1); ++ h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN); ++ seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT; ++ index = TX_SEQ_TO_INDEX(seq); ++ ++ /* check mcl fields and test whether it can be agg'd */ ++ mcl = le16_to_cpu(txh->MacTxControlLow); ++ mcl &= ~TXC_AMPDU_MASK; ++ fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3); ++ txh->PreloadSize = 0; /* always default to 0 */ ++ ++ /* Handle retry limits */ ++ if (txrate[0].count <= rr_retry_limit) { ++ txrate[0].count++; ++ rr = true; ++ fbr = false; ++ } else { ++ fbr = true; ++ rr = false; ++ txrate[1].count++; ++ } ++ ++ /* extract the length info */ ++ len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) ++ : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback); ++ ++ /* retrieve null delimiter count */ ++ ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM]; ++ seg_cnt += 1; ++ ++ BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n", ++ wlc->pub->unit, count, len); ++ ++ /* ++ * aggregateable mpdu. For ucode/hw agg, ++ * test whether need to break or change the epoch ++ */ ++ if (count == 0) { ++ mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT); ++ /* refill the bits since might be a retx mpdu */ ++ mcl |= TXC_STARTMSDU; ++ rts = (struct ieee80211_rts *)&txh->rts_frame; ++ ++ if (ieee80211_is_rts(rts->frame_control)) { ++ mcl |= TXC_SENDRTS; ++ use_rts = true; ++ } ++ if (ieee80211_is_cts(rts->frame_control)) { ++ mcl |= TXC_SENDCTS; ++ use_cts = true; ++ } ++ } else { ++ mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT); ++ mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS); ++ } ++ ++ len = roundup(len, 4); ++ ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN); ++ ++ dma_len += (u16) brcmu_pkttotlen(p); ++ ++ BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d" ++ " seg_cnt %d null delim %d\n", ++ wlc->pub->unit, ampdu_len, seg_cnt, ndelim); ++ ++ txh->MacTxControlLow = cpu_to_le16(mcl); ++ ++ /* this packet is added */ ++ pkt[count++] = p; ++ ++ /* patch the first MPDU */ ++ if (count == 1) { ++ u8 plcp0, plcp3, is40, sgi; ++ struct ieee80211_sta *sta; ++ ++ sta = tx_info->control.sta; ++ ++ if (rr) { ++ plcp0 = plcp[0]; ++ plcp3 = plcp[3]; ++ } else { ++ plcp0 = txh->FragPLCPFallback[0]; ++ plcp3 = txh->FragPLCPFallback[3]; ++ ++ } ++ is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0; ++ sgi = plcp3_issgi(plcp3) ? 1 : 0; ++ mcs = plcp0 & ~MIMO_PLCP_40MHZ; ++ max_ampdu_bytes = ++ min(scb_ampdu->max_rx_ampdu_bytes, ++ ampdu->max_txlen[mcs][is40][sgi]); ++ ++ if (is40) ++ mimo_ctlchbw = ++ CHSPEC_SB_UPPER(wlc_phy_chanspec_get( ++ wlc->band->pi)) ++ ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ; ++ ++ /* rebuild the rspec and rspec_fallback */ ++ rspec = RSPEC_MIMORATE; ++ rspec |= plcp[0] & ~MIMO_PLCP_40MHZ; ++ if (plcp[0] & MIMO_PLCP_40MHZ) ++ rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT); ++ ++ if (fbr_iscck) /* CCK */ ++ rspec_fallback = cck_rspec(cck_phy2mac_rate ++ (txh->FragPLCPFallback[0])); ++ else { /* MIMO */ ++ rspec_fallback = RSPEC_MIMORATE; ++ rspec_fallback |= ++ txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ; ++ if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ) ++ rspec_fallback |= ++ (PHY_TXC1_BW_40MHZ << ++ RSPEC_BW_SHIFT); ++ } ++ ++ if (use_rts || use_cts) { ++ rts_rspec = ++ brcms_c_rspec_to_rts_rspec(wlc, ++ rspec, false, mimo_ctlchbw); ++ rts_rspec_fallback = ++ brcms_c_rspec_to_rts_rspec(wlc, ++ rspec_fallback, false, mimo_ctlchbw); ++ } ++ } ++ ++ /* if (first mpdu for host agg) */ ++ /* test whether to add more */ ++ if ((mcs_2_rate(mcs, true, false) >= f->dmaxferrate) && ++ (count == f->mcs2ampdu_table[mcs])) { ++ BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping" ++ " ampdu at %d for mcs %d\n", ++ wlc->pub->unit, count, mcs); ++ break; ++ } ++ ++ if (count == scb_ampdu->max_pdu) ++ break; ++ ++ /* ++ * check to see if the next pkt is ++ * a candidate for aggregation ++ */ ++ p = pktq_ppeek(&qi->q, prec); ++ /* tx_info must be checked with current p */ ++ tx_info = IEEE80211_SKB_CB(p); ++ ++ if (p) { ++ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && ++ ((u8) (p->priority) == tid)) { ++ ++ plen = brcmu_pkttotlen(p) + ++ AMPDU_MAX_MPDU_OVERHEAD; ++ plen = max(scb_ampdu->min_len, plen); ++ ++ if ((plen + ampdu_len) > max_ampdu_bytes) { ++ p = NULL; ++ continue; ++ } ++ ++ /* ++ * check if there are enough ++ * descriptors available ++ */ ++ if (*wlc->core->txavail[fifo] <= seg_cnt + 1) { ++ wiphy_err(wiphy, "%s: No fifo space " ++ "!!\n", __func__); ++ p = NULL; ++ continue; ++ } ++ p = brcmu_pktq_pdeq(&qi->q, prec); ++ } else { ++ p = NULL; ++ } ++ } ++ } /* end while(p) */ ++ ++ ini->tx_in_transit += count; ++ ++ if (count) { ++ /* patch up the last txh */ ++ txh = (struct d11txh *) pkt[count - 1]->data; ++ mcl = le16_to_cpu(txh->MacTxControlLow); ++ mcl &= ~TXC_AMPDU_MASK; ++ mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT); ++ txh->MacTxControlLow = cpu_to_le16(mcl); ++ ++ /* remove the null delimiter after last mpdu */ ++ ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM]; ++ txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0; ++ ampdu_len -= ndelim * AMPDU_DELIMITER_LEN; ++ ++ /* remove the pad len from last mpdu */ ++ fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0); ++ len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) ++ : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback); ++ ampdu_len -= roundup(len, 4) - len; ++ ++ /* patch up the first txh & plcp */ ++ txh = (struct d11txh *) pkt[0]->data; ++ plcp = (u8 *) (txh + 1); ++ ++ BRCMS_SET_MIMO_PLCP_LEN(plcp, ampdu_len); ++ /* mark plcp to indicate ampdu */ ++ BRCMS_SET_MIMO_PLCP_AMPDU(plcp); ++ ++ /* reset the mixed mode header durations */ ++ if (txh->MModeLen) { ++ u16 mmodelen = ++ brcms_c_calc_lsig_len(wlc, rspec, ampdu_len); ++ txh->MModeLen = cpu_to_le16(mmodelen); ++ preamble_type = BRCMS_MM_PREAMBLE; ++ } ++ if (txh->MModeFbrLen) { ++ u16 mmfbrlen = ++ brcms_c_calc_lsig_len(wlc, rspec_fallback, ++ ampdu_len); ++ txh->MModeFbrLen = cpu_to_le16(mmfbrlen); ++ fbr_preamble_type = BRCMS_MM_PREAMBLE; ++ } ++ ++ /* set the preload length */ ++ if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) { ++ dma_len = min(dma_len, f->ampdu_pld_size); ++ txh->PreloadSize = cpu_to_le16(dma_len); ++ } else ++ txh->PreloadSize = 0; ++ ++ mch = le16_to_cpu(txh->MacTxControlHigh); ++ ++ /* update RTS dur fields */ ++ if (use_rts || use_cts) { ++ u16 durid; ++ rts = (struct ieee80211_rts *)&txh->rts_frame; ++ if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) == ++ TXC_PREAMBLE_RTS_MAIN_SHORT) ++ rts_preamble_type = BRCMS_SHORT_PREAMBLE; ++ ++ if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) == ++ TXC_PREAMBLE_RTS_FB_SHORT) ++ rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE; ++ ++ durid = ++ brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec, ++ rspec, rts_preamble_type, ++ preamble_type, ampdu_len, ++ true); ++ rts->duration = cpu_to_le16(durid); ++ durid = brcms_c_compute_rtscts_dur(wlc, use_cts, ++ rts_rspec_fallback, ++ rspec_fallback, ++ rts_fbr_preamble_type, ++ fbr_preamble_type, ++ ampdu_len, true); ++ txh->RTSDurFallback = cpu_to_le16(durid); ++ /* set TxFesTimeNormal */ ++ txh->TxFesTimeNormal = rts->duration; ++ /* set fallback rate version of TxFesTimeNormal */ ++ txh->TxFesTimeFallback = txh->RTSDurFallback; ++ } ++ ++ /* set flag and plcp for fallback rate */ ++ if (fbr) { ++ mch |= TXC_AMPDU_FBR; ++ txh->MacTxControlHigh = cpu_to_le16(mch); ++ BRCMS_SET_MIMO_PLCP_AMPDU(plcp); ++ BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback); ++ } ++ ++ BCMMSG(wlc->wiphy, "wl%d: count %d ampdu_len %d\n", ++ wlc->pub->unit, count, ampdu_len); ++ ++ /* inform rate_sel if it this is a rate probe pkt */ ++ frameid = le16_to_cpu(txh->TxFrameID); ++ if (frameid & TXFID_RATE_PROBE_MASK) ++ wiphy_err(wiphy, "%s: XXX what to do with " ++ "TXFID_RATE_PROBE_MASK!?\n", __func__); ++ ++ for (i = 0; i < count; i++) ++ brcms_c_txfifo(wlc, fifo, pkt[i], i == (count - 1), ++ ampdu->txpkt_weight); ++ ++ } ++ /* endif (count) */ ++ return err; ++} ++ ++static void ++brcms_c_ampdu_rate_status(struct brcms_c_info *wlc, ++ struct ieee80211_tx_info *tx_info, ++ struct tx_status *txs, u8 mcs) ++{ ++ struct ieee80211_tx_rate *txrate = tx_info->status.rates; ++ int i; ++ ++ /* clear the rest of the rates */ ++ for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) { ++ txrate[i].idx = -1; ++ txrate[i].count = 0; ++ } ++} ++ ++static void ++brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, ++ struct sk_buff *p, struct tx_status *txs, ++ u32 s1, u32 s2) ++{ ++ struct scb_ampdu *scb_ampdu; ++ struct brcms_c_info *wlc = ampdu->wlc; ++ struct scb_ampdu_tid_ini *ini; ++ u8 bitmap[8], queue, tid; ++ struct d11txh *txh; ++ u8 *plcp; ++ struct ieee80211_hdr *h; ++ u16 seq, start_seq = 0, bindex, index, mcl; ++ u8 mcs = 0; ++ bool ba_recd = false, ack_recd = false; ++ u8 suc_mpdu = 0, tot_mpdu = 0; ++ uint supr_status; ++ bool update_rate = true, retry = true, tx_error = false; ++ u16 mimoantsel = 0; ++ u8 antselid = 0; ++ u8 retry_limit, rr_retry_limit; ++ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p); ++ struct wiphy *wiphy = wlc->wiphy; ++ ++#ifdef BCMDBG ++ u8 hole[AMPDU_MAX_MPDU]; ++ memset(hole, 0, sizeof(hole)); ++#endif ++ ++ scb_ampdu = &scb->scb_ampdu; ++ tid = (u8) (p->priority); ++ ++ ini = &scb_ampdu->ini[tid]; ++ retry_limit = ampdu->retry_limit_tid[tid]; ++ rr_retry_limit = ampdu->rr_retry_limit_tid[tid]; ++ memset(bitmap, 0, sizeof(bitmap)); ++ queue = txs->frameid & TXFID_QUEUE_MASK; ++ supr_status = txs->status & TX_STATUS_SUPR_MASK; ++ ++ if (txs->status & TX_STATUS_ACK_RCV) { ++ if (TX_STATUS_SUPR_UF == supr_status) ++ update_rate = false; ++ ++ WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE)); ++ start_seq = txs->sequence >> SEQNUM_SHIFT; ++ bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >> ++ TX_STATUS_BA_BMAP03_SHIFT; ++ ++ WARN_ON(s1 & TX_STATUS_INTERMEDIATE); ++ WARN_ON(!(s1 & TX_STATUS_AMPDU)); ++ ++ bitmap[0] |= ++ (s1 & TX_STATUS_BA_BMAP47_MASK) << ++ TX_STATUS_BA_BMAP47_SHIFT; ++ bitmap[1] = (s1 >> 8) & 0xff; ++ bitmap[2] = (s1 >> 16) & 0xff; ++ bitmap[3] = (s1 >> 24) & 0xff; ++ ++ bitmap[4] = s2 & 0xff; ++ bitmap[5] = (s2 >> 8) & 0xff; ++ bitmap[6] = (s2 >> 16) & 0xff; ++ bitmap[7] = (s2 >> 24) & 0xff; ++ ++ ba_recd = true; ++ } else { ++ if (supr_status) { ++ update_rate = false; ++ if (supr_status == TX_STATUS_SUPR_BADCH) { ++ wiphy_err(wiphy, "%s: Pkt tx suppressed, " ++ "illegal channel possibly %d\n", ++ __func__, CHSPEC_CHANNEL( ++ wlc->default_bss->chanspec)); ++ } else { ++ if (supr_status != TX_STATUS_SUPR_FRAG) ++ wiphy_err(wiphy, "%s:" ++ "supr_status 0x%x\n", ++ __func__, supr_status); ++ } ++ /* no need to retry for badch; will fail again */ ++ if (supr_status == TX_STATUS_SUPR_BADCH || ++ supr_status == TX_STATUS_SUPR_EXPTIME) { ++ retry = false; ++ } else if (supr_status == TX_STATUS_SUPR_EXPTIME) { ++ /* TX underflow: ++ * try tuning pre-loading or ampdu size ++ */ ++ } else if (supr_status == TX_STATUS_SUPR_FRAG) { ++ /* ++ * if there were underflows, but pre-loading ++ * is not active, notify rate adaptation. ++ */ ++ if (brcms_c_ffpld_check_txfunfl(wlc, ++ prio2fifo[tid]) > 0) ++ tx_error = true; ++ } ++ } else if (txs->phyerr) { ++ update_rate = false; ++ wiphy_err(wiphy, "wl%d: ampdu tx phy " ++ "error (0x%x)\n", wlc->pub->unit, ++ txs->phyerr); ++ ++ if (brcm_msg_level & LOG_ERROR_VAL) { ++ brcmu_prpkt("txpkt (AMPDU)", p); ++ brcms_c_print_txdesc((struct d11txh *) p->data); ++ } ++ brcms_c_print_txstatus(txs); ++ } ++ } ++ ++ /* loop through all pkts and retry if not acked */ ++ while (p) { ++ tx_info = IEEE80211_SKB_CB(p); ++ txh = (struct d11txh *) p->data; ++ mcl = le16_to_cpu(txh->MacTxControlLow); ++ plcp = (u8 *) (txh + 1); ++ h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN); ++ seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT; ++ ++ if (tot_mpdu == 0) { ++ mcs = plcp[0] & MIMO_PLCP_MCS_MASK; ++ mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel); ++ } ++ ++ index = TX_SEQ_TO_INDEX(seq); ++ ack_recd = false; ++ if (ba_recd) { ++ bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX); ++ BCMMSG(wlc->wiphy, "tid %d seq %d," ++ " start_seq %d, bindex %d set %d, index %d\n", ++ tid, seq, start_seq, bindex, ++ isset(bitmap, bindex), index); ++ /* if acked then clear bit and free packet */ ++ if ((bindex < AMPDU_TX_BA_MAX_WSIZE) ++ && isset(bitmap, bindex)) { ++ ini->tx_in_transit--; ++ ini->txretry[index] = 0; ++ ++ /* ++ * ampdu_ack_len: ++ * number of acked aggregated frames ++ */ ++ /* ampdu_len: number of aggregated frames */ ++ brcms_c_ampdu_rate_status(wlc, tx_info, txs, ++ mcs); ++ tx_info->flags |= IEEE80211_TX_STAT_ACK; ++ tx_info->flags |= IEEE80211_TX_STAT_AMPDU; ++ tx_info->status.ampdu_ack_len = ++ tx_info->status.ampdu_len = 1; ++ ++ skb_pull(p, D11_PHY_HDR_LEN); ++ skb_pull(p, D11_TXH_LEN); ++ ++ ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, ++ p); ++ ack_recd = true; ++ suc_mpdu++; ++ } ++ } ++ /* either retransmit or send bar if ack not recd */ ++ if (!ack_recd) { ++ struct ieee80211_tx_rate *txrate = ++ tx_info->status.rates; ++ if (retry && (txrate[0].count < (int)retry_limit)) { ++ ini->txretry[index]++; ++ ini->tx_in_transit--; ++ /* ++ * Use high prededence for retransmit to ++ * give some punch ++ */ ++ /* brcms_c_txq_enq(wlc, scb, p, ++ * BRCMS_PRIO_TO_PREC(tid)); */ ++ brcms_c_txq_enq(wlc, scb, p, ++ BRCMS_PRIO_TO_HI_PREC(tid)); ++ } else { ++ /* Retry timeout */ ++ ini->tx_in_transit--; ++ ieee80211_tx_info_clear_status(tx_info); ++ tx_info->status.ampdu_ack_len = 0; ++ tx_info->status.ampdu_len = 1; ++ tx_info->flags |= ++ IEEE80211_TX_STAT_AMPDU_NO_BACK; ++ skb_pull(p, D11_PHY_HDR_LEN); ++ skb_pull(p, D11_TXH_LEN); ++ wiphy_err(wiphy, "%s: BA Timeout, seq %d, in_" ++ "transit %d\n", "AMPDU status", seq, ++ ini->tx_in_transit); ++ ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, ++ p); ++ } ++ } ++ tot_mpdu++; ++ ++ /* break out if last packet of ampdu */ ++ if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) == ++ TXC_AMPDU_LAST) ++ break; ++ ++ p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED); ++ } ++ brcms_c_send_q(wlc); ++ ++ /* update rate state */ ++ antselid = brcms_c_antsel_antsel2id(wlc->asi, mimoantsel); ++ ++ brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight); ++} ++ ++void ++brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb, ++ struct sk_buff *p, struct tx_status *txs) ++{ ++ struct scb_ampdu *scb_ampdu; ++ struct brcms_c_info *wlc = ampdu->wlc; ++ struct scb_ampdu_tid_ini *ini; ++ u32 s1 = 0, s2 = 0; ++ struct ieee80211_tx_info *tx_info; ++ ++ tx_info = IEEE80211_SKB_CB(p); ++ ++ /* BMAC_NOTE: For the split driver, second level txstatus comes later ++ * So if the ACK was received then wait for the second level else just ++ * call the first one ++ */ ++ if (txs->status & TX_STATUS_ACK_RCV) { ++ u8 status_delay = 0; ++ ++ /* wait till the next 8 bytes of txstatus is available */ ++ while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) { ++ udelay(1); ++ status_delay++; ++ if (status_delay > 10) ++ return; /* error condition */ ++ } ++ ++ s2 = R_REG(&wlc->regs->frmtxstatus2); ++ } ++ ++ if (scb) { ++ scb_ampdu = &scb->scb_ampdu; ++ ini = &scb_ampdu->ini[p->priority]; ++ brcms_c_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2); ++ } else { ++ /* loop through all pkts and free */ ++ u8 queue = txs->frameid & TXFID_QUEUE_MASK; ++ struct d11txh *txh; ++ u16 mcl; ++ while (p) { ++ tx_info = IEEE80211_SKB_CB(p); ++ txh = (struct d11txh *) p->data; ++ mcl = le16_to_cpu(txh->MacTxControlLow); ++ brcmu_pkt_buf_free_skb(p); ++ /* break out if last packet of ampdu */ ++ if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) == ++ TXC_AMPDU_LAST) ++ break; ++ p = dma_getnexttxp(wlc->hw->di[queue], ++ DMA_RANGE_TRANSMITTED); ++ } ++ brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight); ++ } ++} ++ ++void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc) ++{ ++ char template[T_RAM_ACCESS_SZ * 2]; ++ ++ /* driver needs to write the ta in the template; ta is at offset 16 */ ++ memset(template, 0, sizeof(template)); ++ memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN); ++ brcms_b_write_template_ram(wlc->hw, (T_BA_TPL_BASE + 16), ++ (T_RAM_ACCESS_SZ * 2), ++ template); ++} ++ ++bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid) ++{ ++ return wlc->ampdu->ini_enable[tid]; ++} ++ ++void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu) ++{ ++ struct brcms_c_info *wlc = ampdu->wlc; ++ ++ /* ++ * Extend ucode internal watchdog timer to ++ * match larger received frames ++ */ ++ if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) == ++ IEEE80211_HT_MAX_AMPDU_64K) { ++ brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX); ++ brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX); ++ } else { ++ brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF); ++ brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF); ++ } ++} ++ ++/* ++ * callback function that helps flushing ampdu packets from a priority queue ++ */ ++static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a) ++{ ++ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu); ++ struct cb_del_ampdu_pars *ampdu_pars = ++ (struct cb_del_ampdu_pars *)arg_a; ++ bool rc; ++ ++ rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false; ++ rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL || ++ tx_info->control.sta == ampdu_pars->sta); ++ rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid); ++ return rc; ++} ++ ++/* ++ * callback function that helps invalidating ampdu packets in a DMA queue ++ */ ++static void dma_cb_fn_ampdu(void *txi, void *arg_a) ++{ ++ struct ieee80211_sta *sta = arg_a; ++ struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi; ++ ++ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && ++ (tx_info->control.sta == sta || sta == NULL)) ++ tx_info->control.sta = NULL; ++} ++ ++/* ++ * When a remote party is no longer available for ampdu communication, any ++ * pending tx ampdu packets in the driver have to be flushed. ++ */ ++void brcms_c_ampdu_flush(struct brcms_c_info *wlc, ++ struct ieee80211_sta *sta, u16 tid) ++{ ++ struct brcms_txq_info *qi = wlc->pkt_queue; ++ struct pktq *pq = &qi->q; ++ int prec; ++ struct cb_del_ampdu_pars ampdu_pars; ++ ++ ampdu_pars.sta = sta; ++ ampdu_pars.tid = tid; ++ for (prec = 0; prec < pq->num_prec; prec++) ++ brcmu_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt, ++ (void *)&du_pars); ++ brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h.orig 2011-11-09 13:46:58.240800696 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h 2011-11-09 13:47:16.992566265 -0500 +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_AMPDU_H_ ++#define _BRCM_AMPDU_H_ ++ ++extern struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc); ++extern void brcms_c_ampdu_detach(struct ampdu_info *ampdu); ++extern int brcms_c_sendampdu(struct ampdu_info *ampdu, ++ struct brcms_txq_info *qi, ++ struct sk_buff **aggp, int prec); ++extern void brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb, ++ struct sk_buff *p, struct tx_status *txs); ++extern void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc); ++extern void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu); ++ ++#endif /* _BRCM_AMPDU_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.c.orig 2011-11-09 13:46:58.240800696 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.c 2011-11-09 13:47:16.992566265 -0500 +@@ -0,0 +1,307 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include "types.h" ++#include "main.h" ++#include "phy_shim.h" ++#include "antsel.h" ++ ++#define ANT_SELCFG_AUTO 0x80 /* bit indicates antenna sel AUTO */ ++#define ANT_SELCFG_MASK 0x33 /* antenna configuration mask */ ++#define ANT_SELCFG_TX_UNICAST 0 /* unicast tx antenna configuration */ ++#define ANT_SELCFG_RX_UNICAST 1 /* unicast rx antenna configuration */ ++#define ANT_SELCFG_TX_DEF 2 /* default tx antenna configuration */ ++#define ANT_SELCFG_RX_DEF 3 /* default rx antenna configuration */ ++ ++/* useful macros */ ++#define BRCMS_ANTSEL_11N_0(ant) ((((ant) & ANT_SELCFG_MASK) >> 4) & 0xf) ++#define BRCMS_ANTSEL_11N_1(ant) (((ant) & ANT_SELCFG_MASK) & 0xf) ++#define BRCMS_ANTIDX_11N(ant) (((BRCMS_ANTSEL_11N_0(ant)) << 2) +\ ++ (BRCMS_ANTSEL_11N_1(ant))) ++#define BRCMS_ANT_ISAUTO_11N(ant) (((ant) & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO) ++#define BRCMS_ANTSEL_11N(ant) ((ant) & ANT_SELCFG_MASK) ++ ++/* antenna switch */ ++/* defines for no boardlevel antenna diversity */ ++#define ANT_SELCFG_DEF_2x2 0x01 /* default antenna configuration */ ++ ++/* 2x3 antdiv defines and tables for GPIO communication */ ++#define ANT_SELCFG_NUM_2x3 3 ++#define ANT_SELCFG_DEF_2x3 0x01 /* default antenna configuration */ ++ ++/* 2x4 antdiv rev4 defines and tables for GPIO communication */ ++#define ANT_SELCFG_NUM_2x4 4 ++#define ANT_SELCFG_DEF_2x4 0x02 /* default antenna configuration */ ++ ++static const u16 mimo_2x4_div_antselpat_tbl[] = { ++ 0, 0, 0x9, 0xa, /* ant0: 0 ant1: 2,3 */ ++ 0, 0, 0x5, 0x6, /* ant0: 1 ant1: 2,3 */ ++ 0, 0, 0, 0, /* n.a. */ ++ 0, 0, 0, 0 /* n.a. */ ++}; ++ ++static const u8 mimo_2x4_div_antselid_tbl[16] = { ++ 0, 0, 0, 0, 0, 2, 3, 0, ++ 0, 0, 1, 0, 0, 0, 0, 0 /* pat to antselid */ ++}; ++ ++static const u16 mimo_2x3_div_antselpat_tbl[] = { ++ 16, 0, 1, 16, /* ant0: 0 ant1: 1,2 */ ++ 16, 16, 16, 16, /* n.a. */ ++ 16, 2, 16, 16, /* ant0: 2 ant1: 1 */ ++ 16, 16, 16, 16 /* n.a. */ ++}; ++ ++static const u8 mimo_2x3_div_antselid_tbl[16] = { ++ 0, 1, 2, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0 /* pat to antselid */ ++}; ++ ++/* boardlevel antenna selection: init antenna selection structure */ ++static void ++brcms_c_antsel_init_cfg(struct antsel_info *asi, struct brcms_antselcfg *antsel, ++ bool auto_sel) ++{ ++ if (asi->antsel_type == ANTSEL_2x3) { ++ u8 antcfg_def = ANT_SELCFG_DEF_2x3 | ++ ((asi->antsel_avail && auto_sel) ? ANT_SELCFG_AUTO : 0); ++ antsel->ant_config[ANT_SELCFG_TX_DEF] = antcfg_def; ++ antsel->ant_config[ANT_SELCFG_TX_UNICAST] = antcfg_def; ++ antsel->ant_config[ANT_SELCFG_RX_DEF] = antcfg_def; ++ antsel->ant_config[ANT_SELCFG_RX_UNICAST] = antcfg_def; ++ antsel->num_antcfg = ANT_SELCFG_NUM_2x3; ++ ++ } else if (asi->antsel_type == ANTSEL_2x4) { ++ ++ antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x4; ++ antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x4; ++ antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x4; ++ antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x4; ++ antsel->num_antcfg = ANT_SELCFG_NUM_2x4; ++ ++ } else { /* no antenna selection available */ ++ ++ antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x2; ++ antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x2; ++ antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x2; ++ antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x2; ++ antsel->num_antcfg = 0; ++ } ++} ++ ++struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) ++{ ++ struct antsel_info *asi; ++ struct si_pub *sih = wlc->hw->sih; ++ ++ asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC); ++ if (!asi) ++ return NULL; ++ ++ asi->wlc = wlc; ++ asi->pub = wlc->pub; ++ asi->antsel_type = ANTSEL_NA; ++ asi->antsel_avail = false; ++ asi->antsel_antswitch = (u8) getintvar(sih, BRCMS_SROM_ANTSWITCH); ++ ++ if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) { ++ switch (asi->antsel_antswitch) { ++ case ANTSWITCH_TYPE_1: ++ case ANTSWITCH_TYPE_2: ++ case ANTSWITCH_TYPE_3: ++ /* 4321/2 board with 2x3 switch logic */ ++ asi->antsel_type = ANTSEL_2x3; ++ /* Antenna selection availability */ ++ if (((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) || ++ ((u16) getintvar(sih, BRCMS_SROM_AA5G) == 7)) { ++ asi->antsel_avail = true; ++ } else if ( ++ (u16) getintvar(sih, BRCMS_SROM_AA2G) == 3 || ++ (u16) getintvar(sih, BRCMS_SROM_AA5G) == 3) { ++ asi->antsel_avail = false; ++ } else { ++ asi->antsel_avail = false; ++ wiphy_err(wlc->wiphy, "antsel_attach: 2o3 " ++ "board cfg invalid\n"); ++ } ++ ++ break; ++ default: ++ break; ++ } ++ } else if ((asi->pub->sromrev == 4) && ++ ((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) && ++ ((u16) getintvar(sih, BRCMS_SROM_AA5G) == 0)) { ++ /* hack to match old 4321CB2 cards with 2of3 antenna switch */ ++ asi->antsel_type = ANTSEL_2x3; ++ asi->antsel_avail = true; ++ } else if (asi->pub->boardflags2 & BFL2_2X4_DIV) { ++ asi->antsel_type = ANTSEL_2x4; ++ asi->antsel_avail = true; ++ } ++ ++ /* Set the antenna selection type for the low driver */ ++ brcms_b_antsel_type_set(wlc->hw, asi->antsel_type); ++ ++ /* Init (auto/manual) antenna selection */ ++ brcms_c_antsel_init_cfg(asi, &asi->antcfg_11n, true); ++ brcms_c_antsel_init_cfg(asi, &asi->antcfg_cur, true); ++ ++ return asi; ++} ++ ++void brcms_c_antsel_detach(struct antsel_info *asi) ++{ ++ kfree(asi); ++} ++ ++/* ++ * boardlevel antenna selection: ++ * convert ant_cfg to mimo_antsel (ucode interface) ++ */ ++static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg) ++{ ++ u8 idx = BRCMS_ANTIDX_11N(BRCMS_ANTSEL_11N(ant_cfg)); ++ u16 mimo_antsel = 0; ++ ++ if (asi->antsel_type == ANTSEL_2x4) { ++ /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */ ++ mimo_antsel = (mimo_2x4_div_antselpat_tbl[idx] & 0xf); ++ return mimo_antsel; ++ ++ } else if (asi->antsel_type == ANTSEL_2x3) { ++ /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */ ++ mimo_antsel = (mimo_2x3_div_antselpat_tbl[idx] & 0xf); ++ return mimo_antsel; ++ } ++ ++ return mimo_antsel; ++} ++ ++/* boardlevel antenna selection: ucode interface control */ ++static int brcms_c_antsel_cfgupd(struct antsel_info *asi, ++ struct brcms_antselcfg *antsel) ++{ ++ struct brcms_c_info *wlc = asi->wlc; ++ u8 ant_cfg; ++ u16 mimo_antsel; ++ ++ /* 1) Update TX antconfig for all frames that are not unicast data ++ * (aka default TX) ++ */ ++ ant_cfg = antsel->ant_config[ANT_SELCFG_TX_DEF]; ++ mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg); ++ brcms_b_write_shm(wlc->hw, M_MIMO_ANTSEL_TXDFLT, mimo_antsel); ++ /* ++ * Update driver stats for currently selected ++ * default tx/rx antenna config ++ */ ++ asi->antcfg_cur.ant_config[ANT_SELCFG_TX_DEF] = ant_cfg; ++ ++ /* 2) Update RX antconfig for all frames that are not unicast data ++ * (aka default RX) ++ */ ++ ant_cfg = antsel->ant_config[ANT_SELCFG_RX_DEF]; ++ mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg); ++ brcms_b_write_shm(wlc->hw, M_MIMO_ANTSEL_RXDFLT, mimo_antsel); ++ /* ++ * Update driver stats for currently selected ++ * default tx/rx antenna config ++ */ ++ asi->antcfg_cur.ant_config[ANT_SELCFG_RX_DEF] = ant_cfg; ++ ++ return 0; ++} ++ ++void brcms_c_antsel_init(struct antsel_info *asi) ++{ ++ if ((asi->antsel_type == ANTSEL_2x3) || ++ (asi->antsel_type == ANTSEL_2x4)) ++ brcms_c_antsel_cfgupd(asi, &asi->antcfg_11n); ++} ++ ++/* boardlevel antenna selection: convert id to ant_cfg */ ++static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id) ++{ ++ u8 antcfg = ANT_SELCFG_DEF_2x2; ++ ++ if (asi->antsel_type == ANTSEL_2x4) { ++ /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */ ++ antcfg = (((id & 0x2) << 3) | ((id & 0x1) + 2)); ++ return antcfg; ++ ++ } else if (asi->antsel_type == ANTSEL_2x3) { ++ /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */ ++ antcfg = (((id & 0x02) << 4) | ((id & 0x1) + 1)); ++ return antcfg; ++ } ++ ++ return antcfg; ++} ++ ++void ++brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef, bool sel, ++ u8 antselid, u8 fbantselid, u8 *antcfg, ++ u8 *fbantcfg) ++{ ++ u8 ant; ++ ++ /* if use default, assign it and return */ ++ if (usedef) { ++ *antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_DEF]; ++ *fbantcfg = *antcfg; ++ return; ++ } ++ ++ if (!sel) { ++ *antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST]; ++ *fbantcfg = *antcfg; ++ ++ } else { ++ ant = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST]; ++ if ((ant & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO) { ++ *antcfg = brcms_c_antsel_id2antcfg(asi, antselid); ++ *fbantcfg = brcms_c_antsel_id2antcfg(asi, fbantselid); ++ } else { ++ *antcfg = ++ asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST]; ++ *fbantcfg = *antcfg; ++ } ++ } ++ return; ++} ++ ++/* boardlevel antenna selection: convert mimo_antsel (ucode interface) to id */ ++u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel) ++{ ++ u8 antselid = 0; ++ ++ if (asi->antsel_type == ANTSEL_2x4) { ++ /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */ ++ antselid = mimo_2x4_div_antselid_tbl[(antsel & 0xf)]; ++ return antselid; ++ ++ } else if (asi->antsel_type == ANTSEL_2x3) { ++ /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */ ++ antselid = mimo_2x3_div_antselid_tbl[(antsel & 0xf)]; ++ return antselid; ++ } ++ ++ return antselid; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.h.orig 2011-11-09 13:46:58.241800683 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.h 2011-11-09 13:47:16.993566253 -0500 +@@ -0,0 +1,29 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_ANTSEL_H_ ++#define _BRCM_ANTSEL_H_ ++ ++extern struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc); ++extern void brcms_c_antsel_detach(struct antsel_info *asi); ++extern void brcms_c_antsel_init(struct antsel_info *asi); ++extern void brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef, ++ bool sel, ++ u8 id, u8 fbid, u8 *antcfg, ++ u8 *fbantcfg); ++extern u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel); ++ ++#endif /* _BRCM_ANTSEL_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.c.orig 2011-11-09 13:46:58.241800683 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.c 2011-11-09 13:47:16.993566253 -0500 +@@ -0,0 +1,23 @@ ++/* ++ * Copyright (c) 2011 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include /* bug in tracepoint.h, it should include this */ ++ ++#ifndef __CHECKER__ ++#include "mac80211_if.h" ++#define CREATE_TRACE_POINTS ++#include "brcms_trace_events.h" ++#endif +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h.orig 2011-11-09 13:46:58.241800683 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h 2011-11-09 13:47:16.993566253 -0500 +@@ -0,0 +1,92 @@ ++/* ++ * Copyright (c) 2011 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM brcmsmac ++ ++#if !defined(__TRACE_BRCMSMAC_H) || defined(TRACE_HEADER_MULTI_READ) ++ ++#define __TRACE_BRCMSMAC_H ++ ++#include ++#include "mac80211_if.h" ++ ++#ifndef CONFIG_BRCMDBG ++#undef TRACE_EVENT ++#define TRACE_EVENT(name, proto, ...) \ ++static inline void trace_ ## name(proto) {} ++#endif ++ ++/* ++ * We define a tracepoint, its arguments, its printk format and its ++ * 'fast binary record' layout. ++ */ ++TRACE_EVENT(brcms_timer, ++ /* TPPROTO is the prototype of the function called by this tracepoint */ ++ TP_PROTO(struct brcms_timer *t), ++ /* ++ * TPARGS(firstarg, p) are the parameters names, same as found in the ++ * prototype. ++ */ ++ TP_ARGS(t), ++ /* ++ * Fast binary tracing: define the trace record via TP_STRUCT__entry(). ++ * You can think about it like a regular C structure local variable ++ * definition. ++ */ ++ TP_STRUCT__entry( ++ __field(uint, ms) ++ __field(uint, set) ++ __field(uint, periodic) ++ ), ++ TP_fast_assign( ++ __entry->ms = t->ms; ++ __entry->set = t->set; ++ __entry->periodic = t->periodic; ++ ), ++ TP_printk( ++ "ms=%u set=%u periodic=%u", ++ __entry->ms, __entry->set, __entry->periodic ++ ) ++); ++ ++TRACE_EVENT(brcms_dpc, ++ TP_PROTO(unsigned long data), ++ TP_ARGS(data), ++ TP_STRUCT__entry( ++ __field(unsigned long, data) ++ ), ++ TP_fast_assign( ++ __entry->data = data; ++ ), ++ TP_printk( ++ "data=%p", ++ (void *)__entry->data ++ ) ++); ++ ++#endif /* __TRACE_BRCMSMAC_H */ ++ ++#ifdef CONFIG_BRCMDBG ++ ++#undef TRACE_INCLUDE_PATH ++#define TRACE_INCLUDE_PATH . ++#undef TRACE_INCLUDE_FILE ++#define TRACE_INCLUDE_FILE brcms_trace_events ++ ++#include ++ ++#endif /* CONFIG_BRCMDBG */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.c.orig 2011-11-09 13:46:58.242800670 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.c 2011-11-09 13:47:16.994566241 -0500 +@@ -0,0 +1,1591 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include ++#include "pub.h" ++#include "phy/phy_hal.h" ++#include "main.h" ++#include "stf.h" ++#include "channel.h" ++ ++/* QDB() macro takes a dB value and converts to a quarter dB value */ ++#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR) ++ ++#define LOCALE_CHAN_01_11 (1<<0) ++#define LOCALE_CHAN_12_13 (1<<1) ++#define LOCALE_CHAN_14 (1<<2) ++#define LOCALE_SET_5G_LOW_JP1 (1<<3) /* 34-48, step 2 */ ++#define LOCALE_SET_5G_LOW_JP2 (1<<4) /* 34-46, step 4 */ ++#define LOCALE_SET_5G_LOW1 (1<<5) /* 36-48, step 4 */ ++#define LOCALE_SET_5G_LOW2 (1<<6) /* 52 */ ++#define LOCALE_SET_5G_LOW3 (1<<7) /* 56-64, step 4 */ ++#define LOCALE_SET_5G_MID1 (1<<8) /* 100-116, step 4 */ ++#define LOCALE_SET_5G_MID2 (1<<9) /* 120-124, step 4 */ ++#define LOCALE_SET_5G_MID3 (1<<10) /* 128 */ ++#define LOCALE_SET_5G_HIGH1 (1<<11) /* 132-140, step 4 */ ++#define LOCALE_SET_5G_HIGH2 (1<<12) /* 149-161, step 4 */ ++#define LOCALE_SET_5G_HIGH3 (1<<13) /* 165 */ ++#define LOCALE_CHAN_52_140_ALL (1<<14) ++#define LOCALE_SET_5G_HIGH4 (1<<15) /* 184-216 */ ++ ++#define LOCALE_CHAN_36_64 (LOCALE_SET_5G_LOW1 | \ ++ LOCALE_SET_5G_LOW2 | \ ++ LOCALE_SET_5G_LOW3) ++#define LOCALE_CHAN_52_64 (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3) ++#define LOCALE_CHAN_100_124 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2) ++#define LOCALE_CHAN_100_140 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | \ ++ LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1) ++#define LOCALE_CHAN_149_165 (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3) ++#define LOCALE_CHAN_184_216 LOCALE_SET_5G_HIGH4 ++ ++#define LOCALE_CHAN_01_14 (LOCALE_CHAN_01_11 | \ ++ LOCALE_CHAN_12_13 | \ ++ LOCALE_CHAN_14) ++ ++#define LOCALE_RADAR_SET_NONE 0 ++#define LOCALE_RADAR_SET_1 1 ++ ++#define LOCALE_RESTRICTED_NONE 0 ++#define LOCALE_RESTRICTED_SET_2G_SHORT 1 ++#define LOCALE_RESTRICTED_CHAN_165 2 ++#define LOCALE_CHAN_ALL_5G 3 ++#define LOCALE_RESTRICTED_JAPAN_LEGACY 4 ++#define LOCALE_RESTRICTED_11D_2G 5 ++#define LOCALE_RESTRICTED_11D_5G 6 ++#define LOCALE_RESTRICTED_LOW_HI 7 ++#define LOCALE_RESTRICTED_12_13_14 8 ++ ++#define LOCALE_2G_IDX_i 0 ++#define LOCALE_5G_IDX_11 0 ++#define LOCALE_MIMO_IDX_bn 0 ++#define LOCALE_MIMO_IDX_11n 0 ++ ++/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */ ++#define BRCMS_MAXPWR_TBL_SIZE 6 ++/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */ ++#define BRCMS_MAXPWR_MIMO_TBL_SIZE 14 ++ ++/* power level in group of 2.4GHz band channels: ++ * maxpwr[0] - CCK channels [1] ++ * maxpwr[1] - CCK channels [2-10] ++ * maxpwr[2] - CCK channels [11-14] ++ * maxpwr[3] - OFDM channels [1] ++ * maxpwr[4] - OFDM channels [2-10] ++ * maxpwr[5] - OFDM channels [11-14] ++ */ ++ ++/* maxpwr mapping to 5GHz band channels: ++ * maxpwr[0] - channels [34-48] ++ * maxpwr[1] - channels [52-60] ++ * maxpwr[2] - channels [62-64] ++ * maxpwr[3] - channels [100-140] ++ * maxpwr[4] - channels [149-165] ++ */ ++#define BAND_5G_PWR_LVLS 5 /* 5 power levels for 5G */ ++ ++#define LC(id) LOCALE_MIMO_IDX_ ## id ++ ++#define LC_2G(id) LOCALE_2G_IDX_ ## id ++ ++#define LC_5G(id) LOCALE_5G_IDX_ ## id ++ ++#define LOCALES(band2, band5, mimo2, mimo5) \ ++ {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)} ++ ++/* macro to get 2.4 GHz channel group index for tx power */ ++#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2)) ++#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5)) ++ ++/* macro to get 5 GHz channel group index for tx power */ ++#define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \ ++ (((c) < 62) ? 1 : \ ++ (((c) < 100) ? 2 : \ ++ (((c) < 149) ? 3 : 4)))) ++ ++#define ISDFS_EU(fl) (((fl) & BRCMS_DFS_EU) == BRCMS_DFS_EU) ++ ++struct brcms_cm_band { ++ /* struct locale_info flags */ ++ u8 locale_flags; ++ /* List of valid channels in the country */ ++ struct brcms_chanvec valid_channels; ++ /* List of restricted use channels */ ++ const struct brcms_chanvec *restricted_channels; ++ /* List of radar sensitive channels */ ++ const struct brcms_chanvec *radar_channels; ++ u8 PAD[8]; ++}; ++ ++ /* locale per-channel tx power limits for MIMO frames ++ * maxpwr arrays are index by channel for 2.4 GHz limits, and ++ * by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel) ++ */ ++struct locale_mimo_info { ++ /* tx 20 MHz power limits, qdBm units */ ++ s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE]; ++ /* tx 40 MHz power limits, qdBm units */ ++ s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE]; ++ u8 flags; ++}; ++ ++/* Country names and abbreviations with locale defined from ISO 3166 */ ++struct country_info { ++ const u8 locale_2G; /* 2.4G band locale */ ++ const u8 locale_5G; /* 5G band locale */ ++ const u8 locale_mimo_2G; /* 2.4G mimo info */ ++ const u8 locale_mimo_5G; /* 5G mimo info */ ++}; ++ ++struct brcms_cm_info { ++ struct brcms_pub *pub; ++ struct brcms_c_info *wlc; ++ char srom_ccode[BRCM_CNTRY_BUF_SZ]; /* Country Code in SROM */ ++ uint srom_regrev; /* Regulatory Rev for the SROM ccode */ ++ const struct country_info *country; /* current country def */ ++ char ccode[BRCM_CNTRY_BUF_SZ]; /* current internal Country Code */ ++ uint regrev; /* current Regulatory Revision */ ++ char country_abbrev[BRCM_CNTRY_BUF_SZ]; /* current advertised ccode */ ++ /* per-band state (one per phy/radio) */ ++ struct brcms_cm_band bandstate[MAXBANDS]; ++ /* quiet channels currently for radar sensitivity or 11h support */ ++ /* channels on which we cannot transmit */ ++ struct brcms_chanvec quiet_channels; ++}; ++ ++/* locale channel and power info. */ ++struct locale_info { ++ u32 valid_channels; ++ /* List of radar sensitive channels */ ++ u8 radar_channels; ++ /* List of channels used only if APs are detected */ ++ u8 restricted_channels; ++ /* Max tx pwr in qdBm for each sub-band */ ++ s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE]; ++ /* Country IE advertised max tx pwr in dBm per sub-band */ ++ s8 pub_maxpwr[BAND_5G_PWR_LVLS]; ++ u8 flags; ++}; ++ ++/* Regulatory Matrix Spreadsheet (CLM) MIMO v3.7.9 */ ++ ++/* ++ * Some common channel sets ++ */ ++ ++/* No channels */ ++static const struct brcms_chanvec chanvec_none = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* All 2.4 GHz HW channels */ ++static const struct brcms_chanvec chanvec_all_2G = { ++ {0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* All 5 GHz HW channels */ ++static const struct brcms_chanvec chanvec_all_5G = { ++ {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x11, 0x11, ++ 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, ++ 0x11, 0x11, 0x20, 0x22, 0x22, 0x00, 0x00, 0x11, ++ 0x11, 0x11, 0x11, 0x01} ++}; ++ ++/* ++ * Radar channel sets ++ */ ++ ++/* Channels 52 - 64, 100 - 140 */ ++static const struct brcms_chanvec radar_set1 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, /* 52 - 60 */ ++ 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, /* 64, 100 - 124 */ ++ 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 - 140 */ ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* ++ * Restricted channel sets ++ */ ++ ++/* Channels 34, 38, 42, 46 */ ++static const struct brcms_chanvec restricted_set_japan_legacy = { ++ {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* Channels 12, 13 */ ++static const struct brcms_chanvec restricted_set_2g_short = { ++ {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* Channel 165 */ ++static const struct brcms_chanvec restricted_chan_165 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* Channels 36 - 48 & 149 - 165 */ ++static const struct brcms_chanvec restricted_low_hi = { ++ {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x20, 0x22, 0x22, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* Channels 12 - 14 */ ++static const struct brcms_chanvec restricted_set_12_13_14 = { ++ {0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* global memory to provide working buffer for expanded locale */ ++ ++static const struct brcms_chanvec *g_table_radar_set[] = { ++ &chanvec_none, ++ &radar_set1 ++}; ++ ++static const struct brcms_chanvec *g_table_restricted_chan[] = { ++ &chanvec_none, /* restricted_set_none */ ++ &restricted_set_2g_short, ++ &restricted_chan_165, ++ &chanvec_all_5G, ++ &restricted_set_japan_legacy, ++ &chanvec_all_2G, /* restricted_set_11d_2G */ ++ &chanvec_all_5G, /* restricted_set_11d_5G */ ++ &restricted_low_hi, ++ &restricted_set_12_13_14 ++}; ++ ++static const struct brcms_chanvec locale_2g_01_11 = { ++ {0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_2g_12_13 = { ++ {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_2g_14 = { ++ {0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_LOW_JP1 = { ++ {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_LOW_JP2 = { ++ {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_LOW1 = { ++ {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_LOW2 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_LOW3 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_MID1 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_MID2 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_MID3 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_HIGH1 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_HIGH2 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x20, 0x22, 0x02, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_HIGH3 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_52_140_ALL = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, ++ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, ++ 0x11, 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_HIGH4 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, ++ 0x11, 0x11, 0x11, 0x11} ++}; ++ ++static const struct brcms_chanvec *g_table_locale_base[] = { ++ &locale_2g_01_11, ++ &locale_2g_12_13, ++ &locale_2g_14, ++ &locale_5g_LOW_JP1, ++ &locale_5g_LOW_JP2, ++ &locale_5g_LOW1, ++ &locale_5g_LOW2, ++ &locale_5g_LOW3, ++ &locale_5g_MID1, ++ &locale_5g_MID2, ++ &locale_5g_MID3, ++ &locale_5g_HIGH1, ++ &locale_5g_HIGH2, ++ &locale_5g_HIGH3, ++ &locale_5g_52_140_ALL, ++ &locale_5g_HIGH4 ++}; ++ ++static void brcms_c_locale_add_channels(struct brcms_chanvec *target, ++ const struct brcms_chanvec *channels) ++{ ++ u8 i; ++ for (i = 0; i < sizeof(struct brcms_chanvec); i++) ++ target->vec[i] |= channels->vec[i]; ++} ++ ++static void brcms_c_locale_get_channels(const struct locale_info *locale, ++ struct brcms_chanvec *channels) ++{ ++ u8 i; ++ ++ memset(channels, 0, sizeof(struct brcms_chanvec)); ++ ++ for (i = 0; i < ARRAY_SIZE(g_table_locale_base); i++) { ++ if (locale->valid_channels & (1 << i)) ++ brcms_c_locale_add_channels(channels, ++ g_table_locale_base[i]); ++ } ++} ++ ++/* ++ * Locale Definitions - 2.4 GHz ++ */ ++static const struct locale_info locale_i = { /* locale i. channel 1 - 13 */ ++ LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13, ++ LOCALE_RADAR_SET_NONE, ++ LOCALE_RESTRICTED_SET_2G_SHORT, ++ {QDB(19), QDB(19), QDB(19), ++ QDB(19), QDB(19), QDB(19)}, ++ {20, 20, 20, 0}, ++ BRCMS_EIRP ++}; ++ ++/* ++ * Locale Definitions - 5 GHz ++ */ ++static const struct locale_info locale_11 = { ++ /* locale 11. channel 36 - 48, 52 - 64, 100 - 140, 149 - 165 */ ++ LOCALE_CHAN_36_64 | LOCALE_CHAN_100_140 | LOCALE_CHAN_149_165, ++ LOCALE_RADAR_SET_1, ++ LOCALE_RESTRICTED_NONE, ++ {QDB(21), QDB(21), QDB(21), QDB(21), QDB(21)}, ++ {23, 23, 23, 30, 30}, ++ BRCMS_EIRP | BRCMS_DFS_EU ++}; ++ ++static const struct locale_info *g_locale_2g_table[] = { ++ &locale_i ++}; ++ ++static const struct locale_info *g_locale_5g_table[] = { ++ &locale_11 ++}; ++ ++/* ++ * MIMO Locale Definitions - 2.4 GHz ++ */ ++static const struct locale_mimo_info locale_bn = { ++ {QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), ++ QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), ++ QDB(13), QDB(13), QDB(13)}, ++ {0, 0, QDB(13), QDB(13), QDB(13), ++ QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), ++ QDB(13), 0, 0}, ++ 0 ++}; ++ ++static const struct locale_mimo_info *g_mimo_2g_table[] = { ++ &locale_bn ++}; ++ ++/* ++ * MIMO Locale Definitions - 5 GHz ++ */ ++static const struct locale_mimo_info locale_11n = { ++ { /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)}, ++ {QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)}, ++ 0 ++}; ++ ++static const struct locale_mimo_info *g_mimo_5g_table[] = { ++ &locale_11n ++}; ++ ++static const struct { ++ char abbrev[BRCM_CNTRY_BUF_SZ]; /* country abbreviation */ ++ struct country_info country; ++} cntry_locales[] = { ++ { ++ "X2", LOCALES(i, 11, bn, 11n)}, /* Worldwide RoW 2 */ ++}; ++ ++#ifdef SUPPORT_40MHZ ++/* 20MHz channel info for 40MHz pairing support */ ++struct chan20_info { ++ u8 sb; ++ u8 adj_sbs; ++}; ++ ++/* indicates adjacent channels that are allowed for a 40 Mhz channel and ++ * those that permitted by the HT ++ */ ++struct chan20_info chan20_info[] = { ++ /* 11b/11g */ ++/* 0 */ {1, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 1 */ {2, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 2 */ {3, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 3 */ {4, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 4 */ {5, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, ++/* 5 */ {6, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, ++/* 6 */ {7, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, ++/* 7 */ {8, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, ++/* 8 */ {9, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, ++/* 9 */ {10, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 10 */ {11, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 11 */ {12, (CH_LOWER_SB)}, ++/* 12 */ {13, (CH_LOWER_SB)}, ++/* 13 */ {14, (CH_LOWER_SB)}, ++ ++/* 11a japan high */ ++/* 14 */ {34, (CH_UPPER_SB)}, ++/* 15 */ {38, (CH_LOWER_SB)}, ++/* 16 */ {42, (CH_LOWER_SB)}, ++/* 17 */ {46, (CH_LOWER_SB)}, ++ ++/* 11a usa low */ ++/* 18 */ {36, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 19 */ {40, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 20 */ {44, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 21 */ {48, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 22 */ {52, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 23 */ {56, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 24 */ {60, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 25 */ {64, (CH_LOWER_SB | CH_EWA_VALID)}, ++ ++/* 11a Europe */ ++/* 26 */ {100, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 27 */ {104, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 28 */ {108, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 29 */ {112, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 30 */ {116, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 31 */ {120, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 32 */ {124, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 33 */ {128, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 34 */ {132, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 35 */ {136, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 36 */ {140, (CH_LOWER_SB)}, ++ ++/* 11a usa high, ref5 only */ ++/* The 0x80 bit in pdiv means these are REF5, other entries are REF20 */ ++/* 37 */ {149, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 38 */ {153, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 39 */ {157, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 40 */ {161, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 41 */ {165, (CH_LOWER_SB)}, ++ ++/* 11a japan */ ++/* 42 */ {184, (CH_UPPER_SB)}, ++/* 43 */ {188, (CH_LOWER_SB)}, ++/* 44 */ {192, (CH_UPPER_SB)}, ++/* 45 */ {196, (CH_LOWER_SB)}, ++/* 46 */ {200, (CH_UPPER_SB)}, ++/* 47 */ {204, (CH_LOWER_SB)}, ++/* 48 */ {208, (CH_UPPER_SB)}, ++/* 49 */ {212, (CH_LOWER_SB)}, ++/* 50 */ {216, (CH_LOWER_SB)} ++}; ++#endif /* SUPPORT_40MHZ */ ++ ++static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx) ++{ ++ if (locale_idx >= ARRAY_SIZE(g_locale_2g_table)) ++ return NULL; /* error condition */ ++ ++ return g_locale_2g_table[locale_idx]; ++} ++ ++static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx) ++{ ++ if (locale_idx >= ARRAY_SIZE(g_locale_5g_table)) ++ return NULL; /* error condition */ ++ ++ return g_locale_5g_table[locale_idx]; ++} ++ ++static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx) ++{ ++ if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table)) ++ return NULL; ++ ++ return g_mimo_2g_table[locale_idx]; ++} ++ ++static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx) ++{ ++ if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table)) ++ return NULL; ++ ++ return g_mimo_5g_table[locale_idx]; ++} ++ ++static int ++brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm, const char *ccode, ++ char *mapped_ccode, uint *mapped_regrev) ++{ ++ return false; ++} ++ ++/* Lookup a country info structure from a null terminated country ++ * abbreviation and regrev directly with no translation. ++ */ ++static const struct country_info * ++brcms_c_country_lookup_direct(const char *ccode, uint regrev) ++{ ++ uint size, i; ++ ++ /* Should just return 0 for single locale driver. */ ++ /* Keep it this way in case we add more locales. (for now anyway) */ ++ ++ /* ++ * all other country def arrays are for regrev == 0, so if ++ * regrev is non-zero, fail ++ */ ++ if (regrev > 0) ++ return NULL; ++ ++ /* find matched table entry from country code */ ++ size = ARRAY_SIZE(cntry_locales); ++ for (i = 0; i < size; i++) { ++ if (strcmp(ccode, cntry_locales[i].abbrev) == 0) ++ return &cntry_locales[i].country; ++ } ++ return NULL; ++} ++ ++static const struct country_info * ++brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, const char *ccode, ++ char *mapped_ccode, uint *mapped_regrev) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ const struct country_info *country; ++ uint srom_regrev = wlc_cm->srom_regrev; ++ const char *srom_ccode = wlc_cm->srom_ccode; ++ int mapped; ++ ++ /* check for currently supported ccode size */ ++ if (strlen(ccode) > (BRCM_CNTRY_BUF_SZ - 1)) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: ccode \"%s\" too long for " ++ "match\n", wlc->pub->unit, __func__, ccode); ++ return NULL; ++ } ++ ++ /* default mapping is the given ccode and regrev 0 */ ++ strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ); ++ *mapped_regrev = 0; ++ ++ /* If the desired country code matches the srom country code, ++ * then the mapped country is the srom regulatory rev. ++ * Otherwise look for an aggregate mapping. ++ */ ++ if (!strcmp(srom_ccode, ccode)) { ++ *mapped_regrev = srom_regrev; ++ mapped = 0; ++ wiphy_err(wlc->wiphy, "srom_code == ccode %s\n", __func__); ++ } else { ++ mapped = ++ brcms_c_country_aggregate_map(wlc_cm, ccode, mapped_ccode, ++ mapped_regrev); ++ } ++ ++ /* find the matching built-in country definition */ ++ country = brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev); ++ ++ /* if there is not an exact rev match, default to rev zero */ ++ if (country == NULL && *mapped_regrev != 0) { ++ *mapped_regrev = 0; ++ country = ++ brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev); ++ } ++ ++ return country; ++} ++ ++/* Lookup a country info structure from a null terminated country code ++ * The lookup is case sensitive. ++ */ ++static const struct country_info * ++brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode) ++{ ++ const struct country_info *country; ++ char mapped_ccode[BRCM_CNTRY_BUF_SZ]; ++ uint mapped_regrev; ++ ++ /* ++ * map the country code to a built-in country code, regrev, and ++ * country_info struct ++ */ ++ country = brcms_c_countrycode_map(wlc->cmi, ccode, mapped_ccode, ++ &mapped_regrev); ++ ++ return country; ++} ++ ++/* ++ * reset the quiet channels vector to the union ++ * of the restricted and radar channel sets ++ */ ++static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ uint i, j; ++ struct brcms_band *band; ++ const struct brcms_chanvec *chanvec; ++ ++ memset(&wlc_cm->quiet_channels, 0, sizeof(struct brcms_chanvec)); ++ ++ band = wlc->band; ++ for (i = 0; i < wlc->pub->_nbands; ++ i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) { ++ ++ /* initialize quiet channels for restricted channels */ ++ chanvec = wlc_cm->bandstate[band->bandunit].restricted_channels; ++ for (j = 0; j < sizeof(struct brcms_chanvec); j++) ++ wlc_cm->quiet_channels.vec[j] |= chanvec->vec[j]; ++ ++ } ++} ++ ++/* Is the channel valid for the current locale and current band? */ ++static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ ++ return ((val < MAXCHANNEL) && ++ isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec, ++ val)); ++} ++ ++/* Is the channel valid for the current locale and specified band? */ ++static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm, ++ uint bandunit, uint val) ++{ ++ return ((val < MAXCHANNEL) ++ && isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val)); ++} ++ ++/* Is the channel valid for the current locale? (but don't consider channels not ++ * available due to bandlocking) ++ */ ++static bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ ++ return brcms_c_valid_channel20(wlc->cmi, val) || ++ (!wlc->bandlocked ++ && brcms_c_valid_channel20_in_band(wlc->cmi, ++ OTHERBANDUNIT(wlc), val)); ++} ++ ++/* JP, J1 - J10 are Japan ccodes */ ++static bool brcms_c_japan_ccode(const char *ccode) ++{ ++ return (ccode[0] == 'J' && ++ (ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9'))); ++} ++ ++/* Returns true if currently set country is Japan or variant */ ++static bool brcms_c_japan(struct brcms_c_info *wlc) ++{ ++ return brcms_c_japan_ccode(wlc->cmi->country_abbrev); ++} ++ ++static void ++brcms_c_channel_min_txpower_limits_with_local_constraint( ++ struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr, ++ u8 local_constraint_qdbm) ++{ ++ int j; ++ ++ /* CCK Rates */ ++ for (j = 0; j < WL_TX_POWER_CCK_NUM; j++) ++ txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm); ++ ++ /* 20 MHz Legacy OFDM SISO */ ++ for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++) ++ txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm); ++ ++ /* 20 MHz Legacy OFDM CDD */ ++ for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) ++ txpwr->ofdm_cdd[j] = ++ min(txpwr->ofdm_cdd[j], local_constraint_qdbm); ++ ++ /* 40 MHz Legacy OFDM SISO */ ++ for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) ++ txpwr->ofdm_40_siso[j] = ++ min(txpwr->ofdm_40_siso[j], local_constraint_qdbm); ++ ++ /* 40 MHz Legacy OFDM CDD */ ++ for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) ++ txpwr->ofdm_40_cdd[j] = ++ min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm); ++ ++ /* 20MHz MCS 0-7 SISO */ ++ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) ++ txpwr->mcs_20_siso[j] = ++ min(txpwr->mcs_20_siso[j], local_constraint_qdbm); ++ ++ /* 20MHz MCS 0-7 CDD */ ++ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) ++ txpwr->mcs_20_cdd[j] = ++ min(txpwr->mcs_20_cdd[j], local_constraint_qdbm); ++ ++ /* 20MHz MCS 0-7 STBC */ ++ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) ++ txpwr->mcs_20_stbc[j] = ++ min(txpwr->mcs_20_stbc[j], local_constraint_qdbm); ++ ++ /* 20MHz MCS 8-15 MIMO */ ++ for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++) ++ txpwr->mcs_20_mimo[j] = ++ min(txpwr->mcs_20_mimo[j], local_constraint_qdbm); ++ ++ /* 40MHz MCS 0-7 SISO */ ++ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) ++ txpwr->mcs_40_siso[j] = ++ min(txpwr->mcs_40_siso[j], local_constraint_qdbm); ++ ++ /* 40MHz MCS 0-7 CDD */ ++ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) ++ txpwr->mcs_40_cdd[j] = ++ min(txpwr->mcs_40_cdd[j], local_constraint_qdbm); ++ ++ /* 40MHz MCS 0-7 STBC */ ++ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) ++ txpwr->mcs_40_stbc[j] = ++ min(txpwr->mcs_40_stbc[j], local_constraint_qdbm); ++ ++ /* 40MHz MCS 8-15 MIMO */ ++ for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++) ++ txpwr->mcs_40_mimo[j] = ++ min(txpwr->mcs_40_mimo[j], local_constraint_qdbm); ++ ++ /* 40MHz MCS 32 */ ++ txpwr->mcs32 = min(txpwr->mcs32, local_constraint_qdbm); ++ ++} ++ ++/* Update the radio state (enable/disable) and tx power targets ++ * based on a new set of channel/regulatory information ++ */ ++static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ uint chan; ++ struct txpwr_limits txpwr; ++ ++ /* search for the existence of any valid channel */ ++ for (chan = 0; chan < MAXCHANNEL; chan++) { ++ if (brcms_c_valid_channel20_db(wlc->cmi, chan)) ++ break; ++ } ++ if (chan == MAXCHANNEL) ++ chan = INVCHANNEL; ++ ++ /* ++ * based on the channel search above, set or ++ * clear WL_RADIO_COUNTRY_DISABLE. ++ */ ++ if (chan == INVCHANNEL) { ++ /* ++ * country/locale with no valid channels, set ++ * the radio disable bit ++ */ ++ mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); ++ wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" " ++ "nbands %d bandlocked %d\n", wlc->pub->unit, ++ __func__, wlc_cm->country_abbrev, wlc->pub->_nbands, ++ wlc->bandlocked); ++ } else if (mboolisset(wlc->pub->radio_disabled, ++ WL_RADIO_COUNTRY_DISABLE)) { ++ /* ++ * country/locale with valid channel, clear ++ * the radio disable bit ++ */ ++ mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); ++ } ++ ++ /* ++ * Now that the country abbreviation is set, if the radio supports 2G, ++ * then set channel 14 restrictions based on the new locale. ++ */ ++ if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G) ++ wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi, ++ brcms_c_japan(wlc) ? true : ++ false); ++ ++ if (wlc->pub->up && chan != INVCHANNEL) { ++ brcms_c_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr); ++ brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm, ++ &txpwr, BRCMS_TXPWR_MAX); ++ wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec); ++ } ++} ++ ++static int ++brcms_c_channels_init(struct brcms_cm_info *wlc_cm, ++ const struct country_info *country) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ uint i, j; ++ struct brcms_band *band; ++ const struct locale_info *li; ++ struct brcms_chanvec sup_chan; ++ const struct locale_mimo_info *li_mimo; ++ ++ band = wlc->band; ++ for (i = 0; i < wlc->pub->_nbands; ++ i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) { ++ ++ li = (band->bandtype == BRCM_BAND_5G) ? ++ brcms_c_get_locale_5g(country->locale_5G) : ++ brcms_c_get_locale_2g(country->locale_2G); ++ wlc_cm->bandstate[band->bandunit].locale_flags = li->flags; ++ li_mimo = (band->bandtype == BRCM_BAND_5G) ? ++ brcms_c_get_mimo_5g(country->locale_mimo_5G) : ++ brcms_c_get_mimo_2g(country->locale_mimo_2G); ++ ++ /* merge the mimo non-mimo locale flags */ ++ wlc_cm->bandstate[band->bandunit].locale_flags |= ++ li_mimo->flags; ++ ++ wlc_cm->bandstate[band->bandunit].restricted_channels = ++ g_table_restricted_chan[li->restricted_channels]; ++ wlc_cm->bandstate[band->bandunit].radar_channels = ++ g_table_radar_set[li->radar_channels]; ++ ++ /* ++ * set the channel availability, masking out the channels ++ * that may not be supported on this phy. ++ */ ++ wlc_phy_chanspec_band_validch(band->pi, band->bandtype, ++ &sup_chan); ++ brcms_c_locale_get_channels(li, ++ &wlc_cm->bandstate[band->bandunit]. ++ valid_channels); ++ for (j = 0; j < sizeof(struct brcms_chanvec); j++) ++ wlc_cm->bandstate[band->bandunit].valid_channels. ++ vec[j] &= sup_chan.vec[j]; ++ } ++ ++ brcms_c_quiet_channels_reset(wlc_cm); ++ brcms_c_channels_commit(wlc_cm); ++ ++ return 0; ++} ++ ++/* ++ * set the driver's current country and regulatory information ++ * using a country code as the source. Look up built in country ++ * information found with the country code. ++ */ ++static void ++brcms_c_set_country_common(struct brcms_cm_info *wlc_cm, ++ const char *country_abbrev, ++ const char *ccode, uint regrev, ++ const struct country_info *country) ++{ ++ const struct locale_info *locale; ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ char prev_country_abbrev[BRCM_CNTRY_BUF_SZ]; ++ ++ /* save current country state */ ++ wlc_cm->country = country; ++ ++ memset(&prev_country_abbrev, 0, BRCM_CNTRY_BUF_SZ); ++ strncpy(prev_country_abbrev, wlc_cm->country_abbrev, ++ BRCM_CNTRY_BUF_SZ - 1); ++ ++ strncpy(wlc_cm->country_abbrev, country_abbrev, BRCM_CNTRY_BUF_SZ - 1); ++ strncpy(wlc_cm->ccode, ccode, BRCM_CNTRY_BUF_SZ - 1); ++ wlc_cm->regrev = regrev; ++ ++ if ((wlc->pub->_n_enab & SUPPORT_11N) != ++ wlc->protection->nmode_user) ++ brcms_c_set_nmode(wlc); ++ ++ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]); ++ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]); ++ /* set or restore gmode as required by regulatory */ ++ locale = brcms_c_get_locale_2g(country->locale_2G); ++ if (locale && (locale->flags & BRCMS_NO_OFDM)) ++ brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false); ++ else ++ brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); ++ ++ brcms_c_channels_init(wlc_cm, country); ++ ++ return; ++} ++ ++static int ++brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm, ++ const char *country_abbrev, ++ const char *ccode, int regrev) ++{ ++ const struct country_info *country; ++ char mapped_ccode[BRCM_CNTRY_BUF_SZ]; ++ uint mapped_regrev; ++ ++ /* if regrev is -1, lookup the mapped country code, ++ * otherwise use the ccode and regrev directly ++ */ ++ if (regrev == -1) { ++ /* ++ * map the country code to a built-in country ++ * code, regrev, and country_info ++ */ ++ country = ++ brcms_c_countrycode_map(wlc_cm, ccode, mapped_ccode, ++ &mapped_regrev); ++ } else { ++ /* find the matching built-in country definition */ ++ country = brcms_c_country_lookup_direct(ccode, regrev); ++ strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ); ++ mapped_regrev = regrev; ++ } ++ ++ if (country == NULL) ++ return -EINVAL; ++ ++ /* set the driver state for the country */ ++ brcms_c_set_country_common(wlc_cm, country_abbrev, mapped_ccode, ++ mapped_regrev, country); ++ ++ return 0; ++} ++ ++/* ++ * set the driver's current country and regulatory information using ++ * a country code as the source. Lookup built in country information ++ * found with the country code. ++ */ ++static int ++brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm, const char *ccode) ++{ ++ char country_abbrev[BRCM_CNTRY_BUF_SZ]; ++ strncpy(country_abbrev, ccode, BRCM_CNTRY_BUF_SZ); ++ return brcms_c_set_countrycode_rev(wlc_cm, country_abbrev, ccode, -1); ++} ++ ++struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc) ++{ ++ struct brcms_cm_info *wlc_cm; ++ char country_abbrev[BRCM_CNTRY_BUF_SZ]; ++ const struct country_info *country; ++ struct brcms_pub *pub = wlc->pub; ++ char *ccode; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ ++ wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC); ++ if (wlc_cm == NULL) ++ return NULL; ++ wlc_cm->pub = pub; ++ wlc_cm->wlc = wlc; ++ wlc->cmi = wlc_cm; ++ ++ /* store the country code for passing up as a regulatory hint */ ++ ccode = getvar(wlc->hw->sih, BRCMS_SROM_CCODE); ++ if (ccode) ++ strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1); ++ ++ /* ++ * internal country information which must match ++ * regulatory constraints in firmware ++ */ ++ memset(country_abbrev, 0, BRCM_CNTRY_BUF_SZ); ++ strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1); ++ country = brcms_c_country_lookup(wlc, country_abbrev); ++ ++ /* save default country for exiting 11d regulatory mode */ ++ strncpy(wlc->country_default, country_abbrev, BRCM_CNTRY_BUF_SZ - 1); ++ ++ /* initialize autocountry_default to driver default */ ++ strncpy(wlc->autocountry_default, "X2", BRCM_CNTRY_BUF_SZ - 1); ++ ++ brcms_c_set_countrycode(wlc_cm, country_abbrev); ++ ++ return wlc_cm; ++} ++ ++void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm) ++{ ++ kfree(wlc_cm); ++} ++ ++u8 ++brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm, ++ uint bandunit) ++{ ++ return wlc_cm->bandstate[bandunit].locale_flags; ++} ++ ++static bool ++brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, u16 chspec) ++{ ++ return (wlc_cm->wlc->pub->_n_enab & SUPPORT_11N) && ++ CHSPEC_IS40(chspec) ? ++ (isset(wlc_cm->quiet_channels.vec, ++ lower_20_sb(CHSPEC_CHANNEL(chspec))) || ++ isset(wlc_cm->quiet_channels.vec, ++ upper_20_sb(CHSPEC_CHANNEL(chspec)))) : ++ isset(wlc_cm->quiet_channels.vec, CHSPEC_CHANNEL(chspec)); ++} ++ ++void ++brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, ++ u8 local_constraint_qdbm) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ struct txpwr_limits txpwr; ++ ++ brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr); ++ ++ brcms_c_channel_min_txpower_limits_with_local_constraint( ++ wlc_cm, &txpwr, local_constraint_qdbm ++ ); ++ ++ brcms_b_set_chanspec(wlc->hw, chanspec, ++ (brcms_c_quiet_chanspec(wlc_cm, chanspec) != 0), ++ &txpwr); ++} ++ ++#ifdef POWER_DBG ++static void wlc_phy_txpower_limits_dump(struct txpwr_limits *txpwr) ++{ ++ int i; ++ char buf[80]; ++ char fraction[4][4] = { " ", ".25", ".5 ", ".75" }; ++ ++ sprintf(buf, "CCK "); ++ for (i = 0; i < BRCMS_NUM_RATES_CCK; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->cck[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->cck[i] % BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "20 MHz OFDM SISO "); ++ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->ofdm[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->ofdm[i] % BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "20 MHz OFDM CDD "); ++ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->ofdm_cdd[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->ofdm_cdd[i] % BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "40 MHz OFDM SISO "); ++ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->ofdm_40_siso[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->ofdm_40_siso[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "40 MHz OFDM CDD "); ++ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->ofdm_40_cdd[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->ofdm_40_cdd[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "20 MHz MCS0-7 SISO "); ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->mcs_20_siso[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs_20_siso[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "20 MHz MCS0-7 CDD "); ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->mcs_20_cdd[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs_20_cdd[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "20 MHz MCS0-7 STBC "); ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->mcs_20_stbc[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs_20_stbc[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "20 MHz MCS8-15 SDM "); ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->mcs_20_mimo[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs_20_mimo[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "40 MHz MCS0-7 SISO "); ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->mcs_40_siso[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs_40_siso[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "40 MHz MCS0-7 CDD "); ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->mcs_40_cdd[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs_40_cdd[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "40 MHz MCS0-7 STBC "); ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->mcs_40_stbc[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs_40_stbc[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "40 MHz MCS8-15 SDM "); ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->mcs_40_mimo[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs_40_mimo[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ } ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ printk(KERN_DEBUG "MCS32 %2d%s\n", ++ txpwr->mcs32 / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs32 % BRCMS_TXPWR_DB_FACTOR]); ++} ++#endif /* POWER_DBG */ ++ ++void ++brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, ++ struct txpwr_limits *txpwr) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ uint i; ++ uint chan; ++ int maxpwr; ++ int delta; ++ const struct country_info *country; ++ struct brcms_band *band; ++ const struct locale_info *li; ++ int conducted_max = BRCMS_TXPWR_MAX; ++ int conducted_ofdm_max = BRCMS_TXPWR_MAX; ++ const struct locale_mimo_info *li_mimo; ++ int maxpwr20, maxpwr40; ++ int maxpwr_idx; ++ uint j; ++ ++ memset(txpwr, 0, sizeof(struct txpwr_limits)); ++ ++ if (!brcms_c_valid_chanspec_db(wlc_cm, chanspec)) { ++ country = brcms_c_country_lookup(wlc, wlc->autocountry_default); ++ if (country == NULL) ++ return; ++ } else { ++ country = wlc_cm->country; ++ } ++ ++ chan = CHSPEC_CHANNEL(chanspec); ++ band = wlc->bandstate[chspec_bandunit(chanspec)]; ++ li = (band->bandtype == BRCM_BAND_5G) ? ++ brcms_c_get_locale_5g(country->locale_5G) : ++ brcms_c_get_locale_2g(country->locale_2G); ++ ++ li_mimo = (band->bandtype == BRCM_BAND_5G) ? ++ brcms_c_get_mimo_5g(country->locale_mimo_5G) : ++ brcms_c_get_mimo_2g(country->locale_mimo_2G); ++ ++ if (li->flags & BRCMS_EIRP) { ++ delta = band->antgain; ++ } else { ++ delta = 0; ++ if (band->antgain > QDB(6)) ++ delta = band->antgain - QDB(6); /* Excess over 6 dB */ ++ } ++ ++ if (li == &locale_i) { ++ conducted_max = QDB(22); ++ conducted_ofdm_max = QDB(22); ++ } ++ ++ /* CCK txpwr limits for 2.4G band */ ++ if (band->bandtype == BRCM_BAND_2G) { ++ maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_CCK(chan)]; ++ ++ maxpwr = maxpwr - delta; ++ maxpwr = max(maxpwr, 0); ++ maxpwr = min(maxpwr, conducted_max); ++ ++ for (i = 0; i < BRCMS_NUM_RATES_CCK; i++) ++ txpwr->cck[i] = (u8) maxpwr; ++ } ++ ++ /* OFDM txpwr limits for 2.4G or 5G bands */ ++ if (band->bandtype == BRCM_BAND_2G) ++ maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)]; ++ else ++ maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)]; ++ ++ maxpwr = maxpwr - delta; ++ maxpwr = max(maxpwr, 0); ++ maxpwr = min(maxpwr, conducted_ofdm_max); ++ ++ /* Keep OFDM lmit below CCK limit */ ++ if (band->bandtype == BRCM_BAND_2G) ++ maxpwr = min_t(int, maxpwr, txpwr->cck[0]); ++ ++ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) ++ txpwr->ofdm[i] = (u8) maxpwr; ++ ++ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) { ++ /* ++ * OFDM 40 MHz SISO has the same power as the corresponding ++ * MCS0-7 rate unless overriden by the locale specific code. ++ * We set this value to 0 as a flag (presumably 0 dBm isn't ++ * a possibility) and then copy the MCS0-7 value to the 40 MHz ++ * value if it wasn't explicitly set. ++ */ ++ txpwr->ofdm_40_siso[i] = 0; ++ ++ txpwr->ofdm_cdd[i] = (u8) maxpwr; ++ ++ txpwr->ofdm_40_cdd[i] = 0; ++ } ++ ++ /* MIMO/HT specific limits */ ++ if (li_mimo->flags & BRCMS_EIRP) { ++ delta = band->antgain; ++ } else { ++ delta = 0; ++ if (band->antgain > QDB(6)) ++ delta = band->antgain - QDB(6); /* Excess over 6 dB */ ++ } ++ ++ if (band->bandtype == BRCM_BAND_2G) ++ maxpwr_idx = (chan - 1); ++ else ++ maxpwr_idx = CHANNEL_POWER_IDX_5G(chan); ++ ++ maxpwr20 = li_mimo->maxpwr20[maxpwr_idx]; ++ maxpwr40 = li_mimo->maxpwr40[maxpwr_idx]; ++ ++ maxpwr20 = maxpwr20 - delta; ++ maxpwr20 = max(maxpwr20, 0); ++ maxpwr40 = maxpwr40 - delta; ++ maxpwr40 = max(maxpwr40, 0); ++ ++ /* Fill in the MCS 0-7 (SISO) rates */ ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { ++ ++ /* ++ * 20 MHz has the same power as the corresponding OFDM rate ++ * unless overriden by the locale specific code. ++ */ ++ txpwr->mcs_20_siso[i] = txpwr->ofdm[i]; ++ txpwr->mcs_40_siso[i] = 0; ++ } ++ ++ /* Fill in the MCS 0-7 CDD rates */ ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { ++ txpwr->mcs_20_cdd[i] = (u8) maxpwr20; ++ txpwr->mcs_40_cdd[i] = (u8) maxpwr40; ++ } ++ ++ /* ++ * These locales have SISO expressed in the ++ * table and override CDD later ++ */ ++ if (li_mimo == &locale_bn) { ++ if (li_mimo == &locale_bn) { ++ maxpwr20 = QDB(16); ++ maxpwr40 = 0; ++ ++ if (chan >= 3 && chan <= 11) ++ maxpwr40 = QDB(16); ++ } ++ ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { ++ txpwr->mcs_20_siso[i] = (u8) maxpwr20; ++ txpwr->mcs_40_siso[i] = (u8) maxpwr40; ++ } ++ } ++ ++ /* Fill in the MCS 0-7 STBC rates */ ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { ++ txpwr->mcs_20_stbc[i] = 0; ++ txpwr->mcs_40_stbc[i] = 0; ++ } ++ ++ /* Fill in the MCS 8-15 SDM rates */ ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) { ++ txpwr->mcs_20_mimo[i] = (u8) maxpwr20; ++ txpwr->mcs_40_mimo[i] = (u8) maxpwr40; ++ } ++ ++ /* Fill in MCS32 */ ++ txpwr->mcs32 = (u8) maxpwr40; ++ ++ for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) { ++ if (txpwr->ofdm_40_cdd[i] == 0) ++ txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j]; ++ if (i == 0) { ++ i = i + 1; ++ if (txpwr->ofdm_40_cdd[i] == 0) ++ txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j]; ++ } ++ } ++ ++ /* ++ * Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO ++ * value if it wasn't provided explicitly. ++ */ ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { ++ if (txpwr->mcs_40_siso[i] == 0) ++ txpwr->mcs_40_siso[i] = txpwr->mcs_40_cdd[i]; ++ } ++ ++ for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) { ++ if (txpwr->ofdm_40_siso[i] == 0) ++ txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j]; ++ if (i == 0) { ++ i = i + 1; ++ if (txpwr->ofdm_40_siso[i] == 0) ++ txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j]; ++ } ++ } ++ ++ /* ++ * Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding ++ * STBC values if they weren't provided explicitly. ++ */ ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { ++ if (txpwr->mcs_20_stbc[i] == 0) ++ txpwr->mcs_20_stbc[i] = txpwr->mcs_20_cdd[i]; ++ ++ if (txpwr->mcs_40_stbc[i] == 0) ++ txpwr->mcs_40_stbc[i] = txpwr->mcs_40_cdd[i]; ++ } ++ ++#ifdef POWER_DBG ++ wlc_phy_txpower_limits_dump(txpwr); ++#endif ++ return; ++} ++ ++/* ++ * Verify the chanspec is using a legal set of parameters, i.e. that the ++ * chanspec specified a band, bw, ctl_sb and channel and that the ++ * combination could be legal given any set of circumstances. ++ * RETURNS: true is the chanspec is malformed, false if it looks good. ++ */ ++static bool brcms_c_chspec_malformed(u16 chanspec) ++{ ++ /* must be 2G or 5G band */ ++ if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec)) ++ return true; ++ /* must be 20 or 40 bandwidth */ ++ if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec)) ++ return true; ++ ++ /* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */ ++ if (CHSPEC_IS20(chanspec)) { ++ if (!CHSPEC_SB_NONE(chanspec)) ++ return true; ++ } else if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) { ++ return true; ++ } ++ ++ return false; ++} ++ ++/* ++ * Validate the chanspec for this locale, for 40MHZ we need to also ++ * check that the sidebands are valid 20MZH channels in this locale ++ * and they are also a legal HT combination ++ */ ++static bool ++brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec, ++ bool dualband) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ u8 channel = CHSPEC_CHANNEL(chspec); ++ ++ /* check the chanspec */ ++ if (brcms_c_chspec_malformed(chspec)) { ++ wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n", ++ wlc->pub->unit, chspec); ++ return false; ++ } ++ ++ if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) != ++ chspec_bandunit(chspec)) ++ return false; ++ ++ /* Check a 20Mhz channel */ ++ if (CHSPEC_IS20(chspec)) { ++ if (dualband) ++ return brcms_c_valid_channel20_db(wlc_cm->wlc->cmi, ++ channel); ++ else ++ return brcms_c_valid_channel20(wlc_cm->wlc->cmi, ++ channel); ++ } ++#ifdef SUPPORT_40MHZ ++ /* ++ * We know we are now checking a 40MHZ channel, so we should ++ * only be here for NPHYS ++ */ ++ if (BRCMS_ISNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) { ++ u8 upper_sideband = 0, idx; ++ u8 num_ch20_entries = ++ sizeof(chan20_info) / sizeof(struct chan20_info); ++ ++ if (!VALID_40CHANSPEC_IN_BAND(wlc, chspec_bandunit(chspec))) ++ return false; ++ ++ if (dualband) { ++ if (!brcms_c_valid_channel20_db(wlc->cmi, ++ lower_20_sb(channel)) || ++ !brcms_c_valid_channel20_db(wlc->cmi, ++ upper_20_sb(channel))) ++ return false; ++ } else { ++ if (!brcms_c_valid_channel20(wlc->cmi, ++ lower_20_sb(channel)) || ++ !brcms_c_valid_channel20(wlc->cmi, ++ upper_20_sb(channel))) ++ return false; ++ } ++ ++ /* find the lower sideband info in the sideband array */ ++ for (idx = 0; idx < num_ch20_entries; idx++) { ++ if (chan20_info[idx].sb == lower_20_sb(channel)) ++ upper_sideband = chan20_info[idx].adj_sbs; ++ } ++ /* check that the lower sideband allows an upper sideband */ ++ if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) == ++ (CH_UPPER_SB | CH_EWA_VALID)) ++ return true; ++ return false; ++ } ++#endif /* 40 MHZ */ ++ ++ return false; ++} ++ ++bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec) ++{ ++ return brcms_c_valid_chanspec_ext(wlc_cm, chspec, true); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.h.orig 2011-11-09 13:46:58.242800670 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.h 2011-11-09 13:47:16.994566241 -0500 +@@ -0,0 +1,53 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_CHANNEL_H_ ++#define _BRCM_CHANNEL_H_ ++ ++/* conversion for phy txpwr calculations that use .25 dB units */ ++#define BRCMS_TXPWR_DB_FACTOR 4 ++ ++/* bits for locale_info flags */ ++#define BRCMS_PEAK_CONDUCTED 0x00 /* Peak for locals */ ++#define BRCMS_EIRP 0x01 /* Flag for EIRP */ ++#define BRCMS_DFS_TPC 0x02 /* Flag for DFS TPC */ ++#define BRCMS_NO_OFDM 0x04 /* Flag for No OFDM */ ++#define BRCMS_NO_40MHZ 0x08 /* Flag for No MIMO 40MHz */ ++#define BRCMS_NO_MIMO 0x10 /* Flag for No MIMO, 20 or 40 MHz */ ++#define BRCMS_RADAR_TYPE_EU 0x20 /* Flag for EU */ ++#define BRCMS_DFS_FCC BRCMS_DFS_TPC /* Flag for DFS FCC */ ++ ++#define BRCMS_DFS_EU (BRCMS_DFS_TPC | BRCMS_RADAR_TYPE_EU) /* Flag for DFS EU */ ++ ++extern struct brcms_cm_info * ++brcms_c_channel_mgr_attach(struct brcms_c_info *wlc); ++ ++extern void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm); ++ ++extern u8 brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm, ++ uint bandunit); ++ ++extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, ++ u16 chspec); ++ ++extern void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, ++ u16 chanspec, ++ struct txpwr_limits *txpwr); ++extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, ++ u16 chanspec, ++ u8 local_constraint_qdbm); ++ ++#endif /* _WLC_CHANNEL_H */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/d11.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/d11.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/d11.h.orig 2011-11-09 13:46:58.243800657 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/d11.h 2011-11-09 13:47:16.996566217 -0500 +@@ -0,0 +1,1898 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_D11_H_ ++#define _BRCM_D11_H_ ++ ++#include ++ ++#include ++#include "pub.h" ++#include "dma.h" ++ ++/* RX FIFO numbers */ ++#define RX_FIFO 0 /* data and ctl frames */ ++#define RX_TXSTATUS_FIFO 3 /* RX fifo for tx status packages */ ++ ++/* TX FIFO numbers using WME Access Category */ ++#define TX_AC_BK_FIFO 0 /* Background TX FIFO */ ++#define TX_AC_BE_FIFO 1 /* Best-Effort TX FIFO */ ++#define TX_AC_VI_FIFO 2 /* Video TX FIFO */ ++#define TX_AC_VO_FIFO 3 /* Voice TX FIFO */ ++#define TX_BCMC_FIFO 4 /* Broadcast/Multicast TX FIFO */ ++#define TX_ATIM_FIFO 5 /* TX fifo for ATIM window info */ ++ ++/* Addr is byte address used by SW; offset is word offset used by uCode */ ++ ++/* Per AC TX limit settings */ ++#define M_AC_TXLMT_BASE_ADDR (0x180 * 2) ++#define M_AC_TXLMT_ADDR(_ac) (M_AC_TXLMT_BASE_ADDR + (2 * (_ac))) ++ ++/* Legacy TX FIFO numbers */ ++#define TX_DATA_FIFO TX_AC_BE_FIFO ++#define TX_CTL_FIFO TX_AC_VO_FIFO ++ ++#define WL_RSSI_ANT_MAX 4 /* max possible rx antennas */ ++ ++struct intctrlregs { ++ u32 intstatus; ++ u32 intmask; ++}; ++ ++/* PIO structure, ++ * support two PIO format: 2 bytes access and 4 bytes access ++ * basic FIFO register set is per channel(transmit or receive) ++ * a pair of channels is defined for convenience ++ */ ++/* 2byte-wide pio register set per channel(xmt or rcv) */ ++struct pio2regs { ++ u16 fifocontrol; ++ u16 fifodata; ++ u16 fifofree; /* only valid in xmt channel, not in rcv channel */ ++ u16 PAD; ++}; ++ ++/* a pair of pio channels(tx and rx) */ ++struct pio2regp { ++ struct pio2regs tx; ++ struct pio2regs rx; ++}; ++ ++/* 4byte-wide pio register set per channel(xmt or rcv) */ ++struct pio4regs { ++ u32 fifocontrol; ++ u32 fifodata; ++}; ++ ++/* a pair of pio channels(tx and rx) */ ++struct pio4regp { ++ struct pio4regs tx; ++ struct pio4regs rx; ++}; ++ ++/* read: 32-bit register that can be read as 32-bit or as 2 16-bit ++ * write: only low 16b-it half can be written ++ */ ++union pmqreg { ++ u32 pmqhostdata; /* read only! */ ++ struct { ++ u16 pmqctrlstatus; /* read/write */ ++ u16 PAD; ++ } w; ++}; ++ ++struct fifo64 { ++ struct dma64regs dmaxmt; /* dma tx */ ++ struct pio4regs piotx; /* pio tx */ ++ struct dma64regs dmarcv; /* dma rx */ ++ struct pio4regs piorx; /* pio rx */ ++}; ++ ++/* ++ * Host Interface Registers ++ */ ++struct d11regs { ++ /* Device Control ("semi-standard host registers") */ ++ u32 PAD[3]; /* 0x0 - 0x8 */ ++ u32 biststatus; /* 0xC */ ++ u32 biststatus2; /* 0x10 */ ++ u32 PAD; /* 0x14 */ ++ u32 gptimer; /* 0x18 */ ++ u32 usectimer; /* 0x1c *//* for corerev >= 26 */ ++ ++ /* Interrupt Control *//* 0x20 */ ++ struct intctrlregs intctrlregs[8]; ++ ++ u32 PAD[40]; /* 0x60 - 0xFC */ ++ ++ u32 intrcvlazy[4]; /* 0x100 - 0x10C */ ++ ++ u32 PAD[4]; /* 0x110 - 0x11c */ ++ ++ u32 maccontrol; /* 0x120 */ ++ u32 maccommand; /* 0x124 */ ++ u32 macintstatus; /* 0x128 */ ++ u32 macintmask; /* 0x12C */ ++ ++ /* Transmit Template Access */ ++ u32 tplatewrptr; /* 0x130 */ ++ u32 tplatewrdata; /* 0x134 */ ++ u32 PAD[2]; /* 0x138 - 0x13C */ ++ ++ /* PMQ registers */ ++ union pmqreg pmqreg; /* 0x140 */ ++ u32 pmqpatl; /* 0x144 */ ++ u32 pmqpath; /* 0x148 */ ++ u32 PAD; /* 0x14C */ ++ ++ u32 chnstatus; /* 0x150 */ ++ u32 psmdebug; /* 0x154 */ ++ u32 phydebug; /* 0x158 */ ++ u32 machwcap; /* 0x15C */ ++ ++ /* Extended Internal Objects */ ++ u32 objaddr; /* 0x160 */ ++ u32 objdata; /* 0x164 */ ++ u32 PAD[2]; /* 0x168 - 0x16c */ ++ ++ u32 frmtxstatus; /* 0x170 */ ++ u32 frmtxstatus2; /* 0x174 */ ++ u32 PAD[2]; /* 0x178 - 0x17c */ ++ ++ /* TSF host access */ ++ u32 tsf_timerlow; /* 0x180 */ ++ u32 tsf_timerhigh; /* 0x184 */ ++ u32 tsf_cfprep; /* 0x188 */ ++ u32 tsf_cfpstart; /* 0x18c */ ++ u32 tsf_cfpmaxdur32; /* 0x190 */ ++ u32 PAD[3]; /* 0x194 - 0x19c */ ++ ++ u32 maccontrol1; /* 0x1a0 */ ++ u32 machwcap1; /* 0x1a4 */ ++ u32 PAD[14]; /* 0x1a8 - 0x1dc */ ++ ++ /* Clock control and hardware workarounds*/ ++ u32 clk_ctl_st; /* 0x1e0 */ ++ u32 hw_war; ++ u32 d11_phypllctl; /* the phypll request/avail bits are ++ * moved to clk_ctl_st ++ */ ++ u32 PAD[5]; /* 0x1ec - 0x1fc */ ++ ++ /* 0x200-0x37F dma/pio registers */ ++ struct fifo64 fifo64regs[6]; ++ ++ /* FIFO diagnostic port access */ ++ struct dma32diag dmafifo; /* 0x380 - 0x38C */ ++ ++ u32 aggfifocnt; /* 0x390 */ ++ u32 aggfifodata; /* 0x394 */ ++ u32 PAD[16]; /* 0x398 - 0x3d4 */ ++ u16 radioregaddr; /* 0x3d8 */ ++ u16 radioregdata; /* 0x3da */ ++ ++ /* ++ * time delay between the change on rf disable input and ++ * radio shutdown ++ */ ++ u32 rfdisabledly; /* 0x3DC */ ++ ++ /* PHY register access */ ++ u16 phyversion; /* 0x3e0 - 0x0 */ ++ u16 phybbconfig; /* 0x3e2 - 0x1 */ ++ u16 phyadcbias; /* 0x3e4 - 0x2 Bphy only */ ++ u16 phyanacore; /* 0x3e6 - 0x3 pwwrdwn on aphy */ ++ u16 phyrxstatus0; /* 0x3e8 - 0x4 */ ++ u16 phyrxstatus1; /* 0x3ea - 0x5 */ ++ u16 phycrsth; /* 0x3ec - 0x6 */ ++ u16 phytxerror; /* 0x3ee - 0x7 */ ++ u16 phychannel; /* 0x3f0 - 0x8 */ ++ u16 PAD[1]; /* 0x3f2 - 0x9 */ ++ u16 phytest; /* 0x3f4 - 0xa */ ++ u16 phy4waddr; /* 0x3f6 - 0xb */ ++ u16 phy4wdatahi; /* 0x3f8 - 0xc */ ++ u16 phy4wdatalo; /* 0x3fa - 0xd */ ++ u16 phyregaddr; /* 0x3fc - 0xe */ ++ u16 phyregdata; /* 0x3fe - 0xf */ ++ ++ /* IHR *//* 0x400 - 0x7FE */ ++ ++ /* RXE Block */ ++ u16 PAD[3]; /* 0x400 - 0x406 */ ++ u16 rcv_fifo_ctl; /* 0x406 */ ++ u16 PAD; /* 0x408 - 0x40a */ ++ u16 rcv_frm_cnt; /* 0x40a */ ++ u16 PAD[4]; /* 0x40a - 0x414 */ ++ u16 rssi; /* 0x414 */ ++ u16 PAD[5]; /* 0x414 - 0x420 */ ++ u16 rcm_ctl; /* 0x420 */ ++ u16 rcm_mat_data; /* 0x422 */ ++ u16 rcm_mat_mask; /* 0x424 */ ++ u16 rcm_mat_dly; /* 0x426 */ ++ u16 rcm_cond_mask_l; /* 0x428 */ ++ u16 rcm_cond_mask_h; /* 0x42A */ ++ u16 rcm_cond_dly; /* 0x42C */ ++ u16 PAD[1]; /* 0x42E */ ++ u16 ext_ihr_addr; /* 0x430 */ ++ u16 ext_ihr_data; /* 0x432 */ ++ u16 rxe_phyrs_2; /* 0x434 */ ++ u16 rxe_phyrs_3; /* 0x436 */ ++ u16 phy_mode; /* 0x438 */ ++ u16 rcmta_ctl; /* 0x43a */ ++ u16 rcmta_size; /* 0x43c */ ++ u16 rcmta_addr0; /* 0x43e */ ++ u16 rcmta_addr1; /* 0x440 */ ++ u16 rcmta_addr2; /* 0x442 */ ++ u16 PAD[30]; /* 0x444 - 0x480 */ ++ ++ /* PSM Block *//* 0x480 - 0x500 */ ++ ++ u16 PAD; /* 0x480 */ ++ u16 psm_maccontrol_h; /* 0x482 */ ++ u16 psm_macintstatus_l; /* 0x484 */ ++ u16 psm_macintstatus_h; /* 0x486 */ ++ u16 psm_macintmask_l; /* 0x488 */ ++ u16 psm_macintmask_h; /* 0x48A */ ++ u16 PAD; /* 0x48C */ ++ u16 psm_maccommand; /* 0x48E */ ++ u16 psm_brc; /* 0x490 */ ++ u16 psm_phy_hdr_param; /* 0x492 */ ++ u16 psm_postcard; /* 0x494 */ ++ u16 psm_pcard_loc_l; /* 0x496 */ ++ u16 psm_pcard_loc_h; /* 0x498 */ ++ u16 psm_gpio_in; /* 0x49A */ ++ u16 psm_gpio_out; /* 0x49C */ ++ u16 psm_gpio_oe; /* 0x49E */ ++ ++ u16 psm_bred_0; /* 0x4A0 */ ++ u16 psm_bred_1; /* 0x4A2 */ ++ u16 psm_bred_2; /* 0x4A4 */ ++ u16 psm_bred_3; /* 0x4A6 */ ++ u16 psm_brcl_0; /* 0x4A8 */ ++ u16 psm_brcl_1; /* 0x4AA */ ++ u16 psm_brcl_2; /* 0x4AC */ ++ u16 psm_brcl_3; /* 0x4AE */ ++ u16 psm_brpo_0; /* 0x4B0 */ ++ u16 psm_brpo_1; /* 0x4B2 */ ++ u16 psm_brpo_2; /* 0x4B4 */ ++ u16 psm_brpo_3; /* 0x4B6 */ ++ u16 psm_brwk_0; /* 0x4B8 */ ++ u16 psm_brwk_1; /* 0x4BA */ ++ u16 psm_brwk_2; /* 0x4BC */ ++ u16 psm_brwk_3; /* 0x4BE */ ++ ++ u16 psm_base_0; /* 0x4C0 */ ++ u16 psm_base_1; /* 0x4C2 */ ++ u16 psm_base_2; /* 0x4C4 */ ++ u16 psm_base_3; /* 0x4C6 */ ++ u16 psm_base_4; /* 0x4C8 */ ++ u16 psm_base_5; /* 0x4CA */ ++ u16 psm_base_6; /* 0x4CC */ ++ u16 psm_pc_reg_0; /* 0x4CE */ ++ u16 psm_pc_reg_1; /* 0x4D0 */ ++ u16 psm_pc_reg_2; /* 0x4D2 */ ++ u16 psm_pc_reg_3; /* 0x4D4 */ ++ u16 PAD[0xD]; /* 0x4D6 - 0x4DE */ ++ u16 psm_corectlsts; /* 0x4f0 *//* Corerev >= 13 */ ++ u16 PAD[0x7]; /* 0x4f2 - 0x4fE */ ++ ++ /* TXE0 Block *//* 0x500 - 0x580 */ ++ u16 txe_ctl; /* 0x500 */ ++ u16 txe_aux; /* 0x502 */ ++ u16 txe_ts_loc; /* 0x504 */ ++ u16 txe_time_out; /* 0x506 */ ++ u16 txe_wm_0; /* 0x508 */ ++ u16 txe_wm_1; /* 0x50A */ ++ u16 txe_phyctl; /* 0x50C */ ++ u16 txe_status; /* 0x50E */ ++ u16 txe_mmplcp0; /* 0x510 */ ++ u16 txe_mmplcp1; /* 0x512 */ ++ u16 txe_phyctl1; /* 0x514 */ ++ ++ u16 PAD[0x05]; /* 0x510 - 0x51E */ ++ ++ /* Transmit control */ ++ u16 xmtfifodef; /* 0x520 */ ++ u16 xmtfifo_frame_cnt; /* 0x522 *//* Corerev >= 16 */ ++ u16 xmtfifo_byte_cnt; /* 0x524 *//* Corerev >= 16 */ ++ u16 xmtfifo_head; /* 0x526 *//* Corerev >= 16 */ ++ u16 xmtfifo_rd_ptr; /* 0x528 *//* Corerev >= 16 */ ++ u16 xmtfifo_wr_ptr; /* 0x52A *//* Corerev >= 16 */ ++ u16 xmtfifodef1; /* 0x52C *//* Corerev >= 16 */ ++ ++ u16 PAD[0x09]; /* 0x52E - 0x53E */ ++ ++ u16 xmtfifocmd; /* 0x540 */ ++ u16 xmtfifoflush; /* 0x542 */ ++ u16 xmtfifothresh; /* 0x544 */ ++ u16 xmtfifordy; /* 0x546 */ ++ u16 xmtfifoprirdy; /* 0x548 */ ++ u16 xmtfiforqpri; /* 0x54A */ ++ u16 xmttplatetxptr; /* 0x54C */ ++ u16 PAD; /* 0x54E */ ++ u16 xmttplateptr; /* 0x550 */ ++ u16 smpl_clct_strptr; /* 0x552 *//* Corerev >= 22 */ ++ u16 smpl_clct_stpptr; /* 0x554 *//* Corerev >= 22 */ ++ u16 smpl_clct_curptr; /* 0x556 *//* Corerev >= 22 */ ++ u16 PAD[0x04]; /* 0x558 - 0x55E */ ++ u16 xmttplatedatalo; /* 0x560 */ ++ u16 xmttplatedatahi; /* 0x562 */ ++ ++ u16 PAD[2]; /* 0x564 - 0x566 */ ++ ++ u16 xmtsel; /* 0x568 */ ++ u16 xmttxcnt; /* 0x56A */ ++ u16 xmttxshmaddr; /* 0x56C */ ++ ++ u16 PAD[0x09]; /* 0x56E - 0x57E */ ++ ++ /* TXE1 Block */ ++ u16 PAD[0x40]; /* 0x580 - 0x5FE */ ++ ++ /* TSF Block */ ++ u16 PAD[0X02]; /* 0x600 - 0x602 */ ++ u16 tsf_cfpstrt_l; /* 0x604 */ ++ u16 tsf_cfpstrt_h; /* 0x606 */ ++ u16 PAD[0X05]; /* 0x608 - 0x610 */ ++ u16 tsf_cfppretbtt; /* 0x612 */ ++ u16 PAD[0XD]; /* 0x614 - 0x62C */ ++ u16 tsf_clk_frac_l; /* 0x62E */ ++ u16 tsf_clk_frac_h; /* 0x630 */ ++ u16 PAD[0X14]; /* 0x632 - 0x658 */ ++ u16 tsf_random; /* 0x65A */ ++ u16 PAD[0x05]; /* 0x65C - 0x664 */ ++ /* GPTimer 2 registers */ ++ u16 tsf_gpt2_stat; /* 0x666 */ ++ u16 tsf_gpt2_ctr_l; /* 0x668 */ ++ u16 tsf_gpt2_ctr_h; /* 0x66A */ ++ u16 tsf_gpt2_val_l; /* 0x66C */ ++ u16 tsf_gpt2_val_h; /* 0x66E */ ++ u16 tsf_gptall_stat; /* 0x670 */ ++ u16 PAD[0x07]; /* 0x672 - 0x67E */ ++ ++ /* IFS Block */ ++ u16 ifs_sifs_rx_tx_tx; /* 0x680 */ ++ u16 ifs_sifs_nav_tx; /* 0x682 */ ++ u16 ifs_slot; /* 0x684 */ ++ u16 PAD; /* 0x686 */ ++ u16 ifs_ctl; /* 0x688 */ ++ u16 PAD[0x3]; /* 0x68a - 0x68F */ ++ u16 ifsstat; /* 0x690 */ ++ u16 ifsmedbusyctl; /* 0x692 */ ++ u16 iftxdur; /* 0x694 */ ++ u16 PAD[0x3]; /* 0x696 - 0x69b */ ++ /* EDCF support in dot11macs */ ++ u16 ifs_aifsn; /* 0x69c */ ++ u16 ifs_ctl1; /* 0x69e */ ++ ++ /* slow clock registers */ ++ u16 scc_ctl; /* 0x6a0 */ ++ u16 scc_timer_l; /* 0x6a2 */ ++ u16 scc_timer_h; /* 0x6a4 */ ++ u16 scc_frac; /* 0x6a6 */ ++ u16 scc_fastpwrup_dly; /* 0x6a8 */ ++ u16 scc_per; /* 0x6aa */ ++ u16 scc_per_frac; /* 0x6ac */ ++ u16 scc_cal_timer_l; /* 0x6ae */ ++ u16 scc_cal_timer_h; /* 0x6b0 */ ++ u16 PAD; /* 0x6b2 */ ++ ++ u16 PAD[0x26]; ++ ++ /* NAV Block */ ++ u16 nav_ctl; /* 0x700 */ ++ u16 navstat; /* 0x702 */ ++ u16 PAD[0x3e]; /* 0x702 - 0x77E */ ++ ++ /* WEP/PMQ Block *//* 0x780 - 0x7FE */ ++ u16 PAD[0x20]; /* 0x780 - 0x7BE */ ++ ++ u16 wepctl; /* 0x7C0 */ ++ u16 wepivloc; /* 0x7C2 */ ++ u16 wepivkey; /* 0x7C4 */ ++ u16 wepwkey; /* 0x7C6 */ ++ ++ u16 PAD[4]; /* 0x7C8 - 0x7CE */ ++ u16 pcmctl; /* 0X7D0 */ ++ u16 pcmstat; /* 0X7D2 */ ++ u16 PAD[6]; /* 0x7D4 - 0x7DE */ ++ ++ u16 pmqctl; /* 0x7E0 */ ++ u16 pmqstatus; /* 0x7E2 */ ++ u16 pmqpat0; /* 0x7E4 */ ++ u16 pmqpat1; /* 0x7E6 */ ++ u16 pmqpat2; /* 0x7E8 */ ++ ++ u16 pmqdat; /* 0x7EA */ ++ u16 pmqdator; /* 0x7EC */ ++ u16 pmqhst; /* 0x7EE */ ++ u16 pmqpath0; /* 0x7F0 */ ++ u16 pmqpath1; /* 0x7F2 */ ++ u16 pmqpath2; /* 0x7F4 */ ++ u16 pmqdath; /* 0x7F6 */ ++ ++ u16 PAD[0x04]; /* 0x7F8 - 0x7FE */ ++ ++ /* SHM *//* 0x800 - 0xEFE */ ++ u16 PAD[0x380]; /* 0x800 - 0xEFE */ ++}; ++ ++#define PIHR_BASE 0x0400 /* byte address of packed IHR region */ ++ ++/* biststatus */ ++#define BT_DONE (1U << 31) /* bist done */ ++#define BT_B2S (1 << 30) /* bist2 ram summary bit */ ++ ++/* intstatus and intmask */ ++#define I_PC (1 << 10) /* pci descriptor error */ ++#define I_PD (1 << 11) /* pci data error */ ++#define I_DE (1 << 12) /* descriptor protocol error */ ++#define I_RU (1 << 13) /* receive descriptor underflow */ ++#define I_RO (1 << 14) /* receive fifo overflow */ ++#define I_XU (1 << 15) /* transmit fifo underflow */ ++#define I_RI (1 << 16) /* receive interrupt */ ++#define I_XI (1 << 24) /* transmit interrupt */ ++ ++/* interrupt receive lazy */ ++#define IRL_TO_MASK 0x00ffffff /* timeout */ ++#define IRL_FC_MASK 0xff000000 /* frame count */ ++#define IRL_FC_SHIFT 24 /* frame count */ ++ ++/*== maccontrol register ==*/ ++#define MCTL_GMODE (1U << 31) ++#define MCTL_DISCARD_PMQ (1 << 30) ++#define MCTL_WAKE (1 << 26) ++#define MCTL_HPS (1 << 25) ++#define MCTL_PROMISC (1 << 24) ++#define MCTL_KEEPBADFCS (1 << 23) ++#define MCTL_KEEPCONTROL (1 << 22) ++#define MCTL_PHYLOCK (1 << 21) ++#define MCTL_BCNS_PROMISC (1 << 20) ++#define MCTL_LOCK_RADIO (1 << 19) ++#define MCTL_AP (1 << 18) ++#define MCTL_INFRA (1 << 17) ++#define MCTL_BIGEND (1 << 16) ++#define MCTL_GPOUT_SEL_MASK (3 << 14) ++#define MCTL_GPOUT_SEL_SHIFT 14 ++#define MCTL_EN_PSMDBG (1 << 13) ++#define MCTL_IHR_EN (1 << 10) ++#define MCTL_SHM_UPPER (1 << 9) ++#define MCTL_SHM_EN (1 << 8) ++#define MCTL_PSM_JMP_0 (1 << 2) ++#define MCTL_PSM_RUN (1 << 1) ++#define MCTL_EN_MAC (1 << 0) ++ ++/*== maccommand register ==*/ ++#define MCMD_BCN0VLD (1 << 0) ++#define MCMD_BCN1VLD (1 << 1) ++#define MCMD_DIRFRMQVAL (1 << 2) ++#define MCMD_CCA (1 << 3) ++#define MCMD_BG_NOISE (1 << 4) ++#define MCMD_SKIP_SHMINIT (1 << 5) /* only used for simulation */ ++#define MCMD_SAMPLECOLL MCMD_SKIP_SHMINIT /* reuse for sample collect */ ++ ++/*== macintstatus/macintmask ==*/ ++/* gracefully suspended */ ++#define MI_MACSSPNDD (1 << 0) ++/* beacon template available */ ++#define MI_BCNTPL (1 << 1) ++/* TBTT indication */ ++#define MI_TBTT (1 << 2) ++/* beacon successfully tx'd */ ++#define MI_BCNSUCCESS (1 << 3) ++/* beacon canceled (IBSS) */ ++#define MI_BCNCANCLD (1 << 4) ++/* end of ATIM-window (IBSS) */ ++#define MI_ATIMWINEND (1 << 5) ++/* PMQ entries available */ ++#define MI_PMQ (1 << 6) ++/* non-specific gen-stat bits that are set by PSM */ ++#define MI_NSPECGEN_0 (1 << 7) ++/* non-specific gen-stat bits that are set by PSM */ ++#define MI_NSPECGEN_1 (1 << 8) ++/* MAC level Tx error */ ++#define MI_MACTXERR (1 << 9) ++/* non-specific gen-stat bits that are set by PSM */ ++#define MI_NSPECGEN_3 (1 << 10) ++/* PHY Tx error */ ++#define MI_PHYTXERR (1 << 11) ++/* Power Management Event */ ++#define MI_PME (1 << 12) ++/* General-purpose timer0 */ ++#define MI_GP0 (1 << 13) ++/* General-purpose timer1 */ ++#define MI_GP1 (1 << 14) ++/* (ORed) DMA-interrupts */ ++#define MI_DMAINT (1 << 15) ++/* MAC has completed a TX FIFO Suspend/Flush */ ++#define MI_TXSTOP (1 << 16) ++/* MAC has completed a CCA measurement */ ++#define MI_CCA (1 << 17) ++/* MAC has collected background noise samples */ ++#define MI_BG_NOISE (1 << 18) ++/* MBSS DTIM TBTT indication */ ++#define MI_DTIM_TBTT (1 << 19) ++/* Probe response queue needs attention */ ++#define MI_PRQ (1 << 20) ++/* Radio/PHY has been powered back up. */ ++#define MI_PWRUP (1 << 21) ++#define MI_RESERVED3 (1 << 22) ++#define MI_RESERVED2 (1 << 23) ++#define MI_RESERVED1 (1 << 25) ++/* MAC detected change on RF Disable input*/ ++#define MI_RFDISABLE (1 << 28) ++/* MAC has completed a TX */ ++#define MI_TFS (1 << 29) ++/* A phy status change wrt G mode */ ++#define MI_PHYCHANGED (1 << 30) ++/* general purpose timeout */ ++#define MI_TO (1U << 31) ++ ++/* Mac capabilities registers */ ++/*== machwcap ==*/ ++#define MCAP_TKIPMIC 0x80000000 /* TKIP MIC hardware present */ ++ ++/*== pmqhost data ==*/ ++/* data entry of head pmq entry */ ++#define PMQH_DATA_MASK 0xffff0000 ++/* PM entry for BSS config */ ++#define PMQH_BSSCFG 0x00100000 ++/* PM Mode OFF: power save off */ ++#define PMQH_PMOFF 0x00010000 ++/* PM Mode ON: power save on */ ++#define PMQH_PMON 0x00020000 ++/* Dis-associated or De-authenticated */ ++#define PMQH_DASAT 0x00040000 ++/* ATIM not acknowledged */ ++#define PMQH_ATIMFAIL 0x00080000 ++/* delete head entry */ ++#define PMQH_DEL_ENTRY 0x00000001 ++/* delete head entry to cur read pointer -1 */ ++#define PMQH_DEL_MULT 0x00000002 ++/* pmq overflow indication */ ++#define PMQH_OFLO 0x00000004 ++/* entries are present in pmq */ ++#define PMQH_NOT_EMPTY 0x00000008 ++ ++/*== phydebug ==*/ ++/* phy is asserting carrier sense */ ++#define PDBG_CRS (1 << 0) ++/* phy is taking xmit byte from mac this cycle */ ++#define PDBG_TXA (1 << 1) ++/* mac is instructing the phy to transmit a frame */ ++#define PDBG_TXF (1 << 2) ++/* phy is signalling a transmit Error to the mac */ ++#define PDBG_TXE (1 << 3) ++/* phy detected the end of a valid frame preamble */ ++#define PDBG_RXF (1 << 4) ++/* phy detected the end of a valid PLCP header */ ++#define PDBG_RXS (1 << 5) ++/* rx start not asserted */ ++#define PDBG_RXFRG (1 << 6) ++/* mac is taking receive byte from phy this cycle */ ++#define PDBG_RXV (1 << 7) ++/* RF portion of the radio is disabled */ ++#define PDBG_RFD (1 << 16) ++ ++/*== objaddr register ==*/ ++#define OBJADDR_SEL_MASK 0x000F0000 ++#define OBJADDR_UCM_SEL 0x00000000 ++#define OBJADDR_SHM_SEL 0x00010000 ++#define OBJADDR_SCR_SEL 0x00020000 ++#define OBJADDR_IHR_SEL 0x00030000 ++#define OBJADDR_RCMTA_SEL 0x00040000 ++#define OBJADDR_SRCHM_SEL 0x00060000 ++#define OBJADDR_WINC 0x01000000 ++#define OBJADDR_RINC 0x02000000 ++#define OBJADDR_AUTO_INC 0x03000000 ++ ++#define WEP_PCMADDR 0x07d4 ++#define WEP_PCMDATA 0x07d6 ++ ++/*== frmtxstatus ==*/ ++#define TXS_V (1 << 0) /* valid bit */ ++#define TXS_STATUS_MASK 0xffff ++#define TXS_FID_MASK 0xffff0000 ++#define TXS_FID_SHIFT 16 ++ ++/*== frmtxstatus2 ==*/ ++#define TXS_SEQ_MASK 0xffff ++#define TXS_PTX_MASK 0xff0000 ++#define TXS_PTX_SHIFT 16 ++#define TXS_MU_MASK 0x01000000 ++#define TXS_MU_SHIFT 24 ++ ++/*== clk_ctl_st ==*/ ++#define CCS_ERSRC_REQ_D11PLL 0x00000100 /* d11 core pll request */ ++#define CCS_ERSRC_REQ_PHYPLL 0x00000200 /* PHY pll request */ ++#define CCS_ERSRC_AVAIL_D11PLL 0x01000000 /* d11 core pll available */ ++#define CCS_ERSRC_AVAIL_PHYPLL 0x02000000 /* PHY pll available */ ++ ++/* HT Cloclk Ctrl and Clock Avail for 4313 */ ++#define CCS_ERSRC_REQ_HT 0x00000010 /* HT avail request */ ++#define CCS_ERSRC_AVAIL_HT 0x00020000 /* HT clock available */ ++ ++/* tsf_cfprep register */ ++#define CFPREP_CBI_MASK 0xffffffc0 ++#define CFPREP_CBI_SHIFT 6 ++#define CFPREP_CFPP 0x00000001 ++ ++/* tx fifo sizes values are in terms of 256 byte blocks */ ++#define TXFIFOCMD_RESET_MASK (1 << 15) /* reset */ ++#define TXFIFOCMD_FIFOSEL_SHIFT 8 /* fifo */ ++#define TXFIFO_FIFOTOP_SHIFT 8 /* fifo start */ ++ ++#define TXFIFO_START_BLK16 65 /* Base address + 32 * 512 B/P */ ++#define TXFIFO_START_BLK 6 /* Base address + 6 * 256 B */ ++#define TXFIFO_SIZE_UNIT 256 /* one unit corresponds to 256 bytes */ ++#define MBSS16_TEMPLMEM_MINBLKS 65 /* one unit corresponds to 256 bytes */ ++ ++/*== phy versions (PhyVersion:Revision field) ==*/ ++/* analog block version */ ++#define PV_AV_MASK 0xf000 ++/* analog block version bitfield offset */ ++#define PV_AV_SHIFT 12 ++/* phy type */ ++#define PV_PT_MASK 0x0f00 ++/* phy type bitfield offset */ ++#define PV_PT_SHIFT 8 ++/* phy version */ ++#define PV_PV_MASK 0x000f ++#define PHY_TYPE(v) ((v & PV_PT_MASK) >> PV_PT_SHIFT) ++ ++/*== phy types (PhyVersion:PhyType field) ==*/ ++#define PHY_TYPE_N 4 /* N-Phy value */ ++#define PHY_TYPE_SSN 6 /* SSLPN-Phy value */ ++#define PHY_TYPE_LCN 8 /* LCN-Phy value */ ++#define PHY_TYPE_LCNXN 9 /* LCNXN-Phy value */ ++#define PHY_TYPE_NULL 0xf /* Invalid Phy value */ ++ ++/*== analog types (PhyVersion:AnalogType field) ==*/ ++#define ANA_11N_013 5 ++ ++/* 802.11a PLCP header def */ ++struct ofdm_phy_hdr { ++ u8 rlpt[3]; /* rate, length, parity, tail */ ++ u16 service; ++ u8 pad; ++} __packed; ++ ++#define D11A_PHY_HDR_GRATE(phdr) ((phdr)->rlpt[0] & 0x0f) ++#define D11A_PHY_HDR_GRES(phdr) (((phdr)->rlpt[0] >> 4) & 0x01) ++#define D11A_PHY_HDR_GLENGTH(phdr) (((u32 *)((phdr)->rlpt) >> 5) & 0x0fff) ++#define D11A_PHY_HDR_GPARITY(phdr) (((phdr)->rlpt[3] >> 1) & 0x01) ++#define D11A_PHY_HDR_GTAIL(phdr) (((phdr)->rlpt[3] >> 2) & 0x3f) ++ ++/* rate encoded per 802.11a-1999 sec 17.3.4.1 */ ++#define D11A_PHY_HDR_SRATE(phdr, rate) \ ++ ((phdr)->rlpt[0] = ((phdr)->rlpt[0] & 0xf0) | ((rate) & 0xf)) ++/* set reserved field to zero */ ++#define D11A_PHY_HDR_SRES(phdr) ((phdr)->rlpt[0] &= 0xef) ++/* length is number of octets in PSDU */ ++#define D11A_PHY_HDR_SLENGTH(phdr, length) \ ++ (*(u32 *)((phdr)->rlpt) = *(u32 *)((phdr)->rlpt) | \ ++ (((length) & 0x0fff) << 5)) ++/* set the tail to all zeros */ ++#define D11A_PHY_HDR_STAIL(phdr) ((phdr)->rlpt[3] &= 0x03) ++ ++#define D11A_PHY_HDR_LEN_L 3 /* low-rate part of PLCP header */ ++#define D11A_PHY_HDR_LEN_R 2 /* high-rate part of PLCP header */ ++ ++#define D11A_PHY_TX_DELAY (2) /* 2.1 usec */ ++ ++#define D11A_PHY_HDR_TIME (4) /* low-rate part of PLCP header */ ++#define D11A_PHY_PRE_TIME (16) ++#define D11A_PHY_PREHDR_TIME (D11A_PHY_PRE_TIME + D11A_PHY_HDR_TIME) ++ ++/* 802.11b PLCP header def */ ++struct cck_phy_hdr { ++ u8 signal; ++ u8 service; ++ u16 length; ++ u16 crc; ++} __packed; ++ ++#define D11B_PHY_HDR_LEN 6 ++ ++#define D11B_PHY_TX_DELAY (3) /* 3.4 usec */ ++ ++#define D11B_PHY_LHDR_TIME (D11B_PHY_HDR_LEN << 3) ++#define D11B_PHY_LPRE_TIME (144) ++#define D11B_PHY_LPREHDR_TIME (D11B_PHY_LPRE_TIME + D11B_PHY_LHDR_TIME) ++ ++#define D11B_PHY_SHDR_TIME (D11B_PHY_LHDR_TIME >> 1) ++#define D11B_PHY_SPRE_TIME (D11B_PHY_LPRE_TIME >> 1) ++#define D11B_PHY_SPREHDR_TIME (D11B_PHY_SPRE_TIME + D11B_PHY_SHDR_TIME) ++ ++#define D11B_PLCP_SIGNAL_LOCKED (1 << 2) ++#define D11B_PLCP_SIGNAL_LE (1 << 7) ++ ++#define MIMO_PLCP_MCS_MASK 0x7f /* mcs index */ ++#define MIMO_PLCP_40MHZ 0x80 /* 40 Hz frame */ ++#define MIMO_PLCP_AMPDU 0x08 /* ampdu */ ++ ++#define BRCMS_GET_CCK_PLCP_LEN(plcp) (plcp[4] + (plcp[5] << 8)) ++#define BRCMS_GET_MIMO_PLCP_LEN(plcp) (plcp[1] + (plcp[2] << 8)) ++#define BRCMS_SET_MIMO_PLCP_LEN(plcp, len) \ ++ do { \ ++ plcp[1] = len & 0xff; \ ++ plcp[2] = ((len >> 8) & 0xff); \ ++ } while (0); ++ ++#define BRCMS_SET_MIMO_PLCP_AMPDU(plcp) (plcp[3] |= MIMO_PLCP_AMPDU) ++#define BRCMS_CLR_MIMO_PLCP_AMPDU(plcp) (plcp[3] &= ~MIMO_PLCP_AMPDU) ++#define BRCMS_IS_MIMO_PLCP_AMPDU(plcp) (plcp[3] & MIMO_PLCP_AMPDU) ++ ++/* ++ * The dot11a PLCP header is 5 bytes. To simplify the software (so that we ++ * don't need e.g. different tx DMA headers for 11a and 11b), the PLCP header ++ * has padding added in the ucode. ++ */ ++#define D11_PHY_HDR_LEN 6 ++ ++/* TX DMA buffer header */ ++struct d11txh { ++ __le16 MacTxControlLow; /* 0x0 */ ++ __le16 MacTxControlHigh; /* 0x1 */ ++ __le16 MacFrameControl; /* 0x2 */ ++ __le16 TxFesTimeNormal; /* 0x3 */ ++ __le16 PhyTxControlWord; /* 0x4 */ ++ __le16 PhyTxControlWord_1; /* 0x5 */ ++ __le16 PhyTxControlWord_1_Fbr; /* 0x6 */ ++ __le16 PhyTxControlWord_1_Rts; /* 0x7 */ ++ __le16 PhyTxControlWord_1_FbrRts; /* 0x8 */ ++ __le16 MainRates; /* 0x9 */ ++ __le16 XtraFrameTypes; /* 0xa */ ++ u8 IV[16]; /* 0x0b - 0x12 */ ++ u8 TxFrameRA[6]; /* 0x13 - 0x15 */ ++ __le16 TxFesTimeFallback; /* 0x16 */ ++ u8 RTSPLCPFallback[6]; /* 0x17 - 0x19 */ ++ __le16 RTSDurFallback; /* 0x1a */ ++ u8 FragPLCPFallback[6]; /* 0x1b - 1d */ ++ __le16 FragDurFallback; /* 0x1e */ ++ __le16 MModeLen; /* 0x1f */ ++ __le16 MModeFbrLen; /* 0x20 */ ++ __le16 TstampLow; /* 0x21 */ ++ __le16 TstampHigh; /* 0x22 */ ++ __le16 ABI_MimoAntSel; /* 0x23 */ ++ __le16 PreloadSize; /* 0x24 */ ++ __le16 AmpduSeqCtl; /* 0x25 */ ++ __le16 TxFrameID; /* 0x26 */ ++ __le16 TxStatus; /* 0x27 */ ++ __le16 MaxNMpdus; /* 0x28 */ ++ __le16 MaxABytes_MRT; /* 0x29 */ ++ __le16 MaxABytes_FBR; /* 0x2a */ ++ __le16 MinMBytes; /* 0x2b */ ++ u8 RTSPhyHeader[D11_PHY_HDR_LEN]; /* 0x2c - 0x2e */ ++ struct ieee80211_rts rts_frame; /* 0x2f - 0x36 */ ++ u16 PAD; /* 0x37 */ ++} __packed; ++ ++#define D11_TXH_LEN 112 /* bytes */ ++ ++/* Frame Types */ ++#define FT_CCK 0 ++#define FT_OFDM 1 ++#define FT_HT 2 ++#define FT_N 3 ++ ++/* ++ * Position of MPDU inside A-MPDU; indicated with bits 10:9 ++ * of MacTxControlLow ++ */ ++#define TXC_AMPDU_SHIFT 9 /* shift for ampdu settings */ ++#define TXC_AMPDU_NONE 0 /* Regular MPDU, not an A-MPDU */ ++#define TXC_AMPDU_FIRST 1 /* first MPDU of an A-MPDU */ ++#define TXC_AMPDU_MIDDLE 2 /* intermediate MPDU of an A-MPDU */ ++#define TXC_AMPDU_LAST 3 /* last (or single) MPDU of an A-MPDU */ ++ ++/*== MacTxControlLow ==*/ ++#define TXC_AMIC 0x8000 ++#define TXC_SENDCTS 0x0800 ++#define TXC_AMPDU_MASK 0x0600 ++#define TXC_BW_40 0x0100 ++#define TXC_FREQBAND_5G 0x0080 ++#define TXC_DFCS 0x0040 ++#define TXC_IGNOREPMQ 0x0020 ++#define TXC_HWSEQ 0x0010 ++#define TXC_STARTMSDU 0x0008 ++#define TXC_SENDRTS 0x0004 ++#define TXC_LONGFRAME 0x0002 ++#define TXC_IMMEDACK 0x0001 ++ ++/*== MacTxControlHigh ==*/ ++/* RTS fallback preamble type 1 = SHORT 0 = LONG */ ++#define TXC_PREAMBLE_RTS_FB_SHORT 0x8000 ++/* RTS main rate preamble type 1 = SHORT 0 = LONG */ ++#define TXC_PREAMBLE_RTS_MAIN_SHORT 0x4000 ++/* ++ * Main fallback rate preamble type ++ * 1 = SHORT for OFDM/GF for MIMO ++ * 0 = LONG for CCK/MM for MIMO ++ */ ++#define TXC_PREAMBLE_DATA_FB_SHORT 0x2000 ++ ++/* TXC_PREAMBLE_DATA_MAIN is in PhyTxControl bit 5 */ ++/* use fallback rate for this AMPDU */ ++#define TXC_AMPDU_FBR 0x1000 ++#define TXC_SECKEY_MASK 0x0FF0 ++#define TXC_SECKEY_SHIFT 4 ++/* Use alternate txpwr defined at loc. M_ALT_TXPWR_IDX */ ++#define TXC_ALT_TXPWR 0x0008 ++#define TXC_SECTYPE_MASK 0x0007 ++#define TXC_SECTYPE_SHIFT 0 ++ ++/* Null delimiter for Fallback rate */ ++#define AMPDU_FBR_NULL_DELIM 5 /* Location of Null delimiter count for AMPDU */ ++ ++/* PhyTxControl for Mimophy */ ++#define PHY_TXC_PWR_MASK 0xFC00 ++#define PHY_TXC_PWR_SHIFT 10 ++#define PHY_TXC_ANT_MASK 0x03C0 /* bit 6, 7, 8, 9 */ ++#define PHY_TXC_ANT_SHIFT 6 ++#define PHY_TXC_ANT_0_1 0x00C0 /* auto, last rx */ ++#define PHY_TXC_LCNPHY_ANT_LAST 0x0000 ++#define PHY_TXC_ANT_3 0x0200 /* virtual antenna 3 */ ++#define PHY_TXC_ANT_2 0x0100 /* virtual antenna 2 */ ++#define PHY_TXC_ANT_1 0x0080 /* virtual antenna 1 */ ++#define PHY_TXC_ANT_0 0x0040 /* virtual antenna 0 */ ++#define PHY_TXC_SHORT_HDR 0x0010 ++ ++#define PHY_TXC_OLD_ANT_0 0x0000 ++#define PHY_TXC_OLD_ANT_1 0x0100 ++#define PHY_TXC_OLD_ANT_LAST 0x0300 ++ ++/* PhyTxControl_1 for Mimophy */ ++#define PHY_TXC1_BW_MASK 0x0007 ++#define PHY_TXC1_BW_10MHZ 0 ++#define PHY_TXC1_BW_10MHZ_UP 1 ++#define PHY_TXC1_BW_20MHZ 2 ++#define PHY_TXC1_BW_20MHZ_UP 3 ++#define PHY_TXC1_BW_40MHZ 4 ++#define PHY_TXC1_BW_40MHZ_DUP 5 ++#define PHY_TXC1_MODE_SHIFT 3 ++#define PHY_TXC1_MODE_MASK 0x0038 ++#define PHY_TXC1_MODE_SISO 0 ++#define PHY_TXC1_MODE_CDD 1 ++#define PHY_TXC1_MODE_STBC 2 ++#define PHY_TXC1_MODE_SDM 3 ++ ++/* PhyTxControl for HTphy that are different from Mimophy */ ++#define PHY_TXC_HTANT_MASK 0x3fC0 /* bits 6-13 */ ++ ++/* XtraFrameTypes */ ++#define XFTS_RTS_FT_SHIFT 2 ++#define XFTS_FBRRTS_FT_SHIFT 4 ++#define XFTS_CHANNEL_SHIFT 8 ++ ++/* Antenna diversity bit in ant_wr_settle */ ++#define PHY_AWS_ANTDIV 0x2000 ++ ++/* IFS ctl */ ++#define IFS_USEEDCF (1 << 2) ++ ++/* IFS ctl1 */ ++#define IFS_CTL1_EDCRS (1 << 3) ++#define IFS_CTL1_EDCRS_20L (1 << 4) ++#define IFS_CTL1_EDCRS_40 (1 << 5) ++ ++/* ABI_MimoAntSel */ ++#define ABI_MAS_ADDR_BMP_IDX_MASK 0x0f00 ++#define ABI_MAS_ADDR_BMP_IDX_SHIFT 8 ++#define ABI_MAS_FBR_ANT_PTN_MASK 0x00f0 ++#define ABI_MAS_FBR_ANT_PTN_SHIFT 4 ++#define ABI_MAS_MRT_ANT_PTN_MASK 0x000f ++ ++/* tx status packet */ ++struct tx_status { ++ u16 framelen; ++ u16 PAD; ++ u16 frameid; ++ u16 status; ++ u16 lasttxtime; ++ u16 sequence; ++ u16 phyerr; ++ u16 ackphyrxsh; ++} __packed; ++ ++#define TXSTATUS_LEN 16 ++ ++/* status field bit definitions */ ++#define TX_STATUS_FRM_RTX_MASK 0xF000 ++#define TX_STATUS_FRM_RTX_SHIFT 12 ++#define TX_STATUS_RTS_RTX_MASK 0x0F00 ++#define TX_STATUS_RTS_RTX_SHIFT 8 ++#define TX_STATUS_MASK 0x00FE ++#define TX_STATUS_PMINDCTD (1 << 7) /* PM mode indicated to AP */ ++#define TX_STATUS_INTERMEDIATE (1 << 6) /* intermediate or 1st ampdu pkg */ ++#define TX_STATUS_AMPDU (1 << 5) /* AMPDU status */ ++#define TX_STATUS_SUPR_MASK 0x1C /* suppress status bits (4:2) */ ++#define TX_STATUS_SUPR_SHIFT 2 ++#define TX_STATUS_ACK_RCV (1 << 1) /* ACK received */ ++#define TX_STATUS_VALID (1 << 0) /* Tx status valid */ ++#define TX_STATUS_NO_ACK 0 ++ ++/* suppress status reason codes */ ++#define TX_STATUS_SUPR_PMQ (1 << 2) /* PMQ entry */ ++#define TX_STATUS_SUPR_FLUSH (2 << 2) /* flush request */ ++#define TX_STATUS_SUPR_FRAG (3 << 2) /* previous frag failure */ ++#define TX_STATUS_SUPR_TBTT (3 << 2) /* SHARED: Probe resp supr for TBTT */ ++#define TX_STATUS_SUPR_BADCH (4 << 2) /* channel mismatch */ ++#define TX_STATUS_SUPR_EXPTIME (5 << 2) /* lifetime expiry */ ++#define TX_STATUS_SUPR_UF (6 << 2) /* underflow */ ++ ++/* Unexpected tx status for rate update */ ++#define TX_STATUS_UNEXP(status) \ ++ ((((status) & TX_STATUS_INTERMEDIATE) != 0) && \ ++ TX_STATUS_UNEXP_AMPDU(status)) ++ ++/* Unexpected tx status for A-MPDU rate update */ ++#define TX_STATUS_UNEXP_AMPDU(status) \ ++ ((((status) & TX_STATUS_SUPR_MASK) != 0) && \ ++ (((status) & TX_STATUS_SUPR_MASK) != TX_STATUS_SUPR_EXPTIME)) ++ ++#define TX_STATUS_BA_BMAP03_MASK 0xF000 /* ba bitmap 0:3 in 1st pkg */ ++#define TX_STATUS_BA_BMAP03_SHIFT 12 /* ba bitmap 0:3 in 1st pkg */ ++#define TX_STATUS_BA_BMAP47_MASK 0x001E /* ba bitmap 4:7 in 2nd pkg */ ++#define TX_STATUS_BA_BMAP47_SHIFT 3 /* ba bitmap 4:7 in 2nd pkg */ ++ ++/* RXE (Receive Engine) */ ++ ++/* RCM_CTL */ ++#define RCM_INC_MASK_H 0x0080 ++#define RCM_INC_MASK_L 0x0040 ++#define RCM_INC_DATA 0x0020 ++#define RCM_INDEX_MASK 0x001F ++#define RCM_SIZE 15 ++ ++#define RCM_MAC_OFFSET 0 /* current MAC address */ ++#define RCM_BSSID_OFFSET 3 /* current BSSID address */ ++#define RCM_F_BSSID_0_OFFSET 6 /* foreign BSS CFP tracking */ ++#define RCM_F_BSSID_1_OFFSET 9 /* foreign BSS CFP tracking */ ++#define RCM_F_BSSID_2_OFFSET 12 /* foreign BSS CFP tracking */ ++ ++#define RCM_WEP_TA0_OFFSET 16 ++#define RCM_WEP_TA1_OFFSET 19 ++#define RCM_WEP_TA2_OFFSET 22 ++#define RCM_WEP_TA3_OFFSET 25 ++ ++/* PSM Block */ ++ ++/* psm_phy_hdr_param bits */ ++#define MAC_PHY_RESET 1 ++#define MAC_PHY_CLOCK_EN 2 ++#define MAC_PHY_FORCE_CLK 4 ++ ++/* WEP Block */ ++ ++/* WEP_WKEY */ ++#define WKEY_START (1 << 8) ++#define WKEY_SEL_MASK 0x1F ++ ++/* WEP data formats */ ++ ++/* the number of RCMTA entries */ ++#define RCMTA_SIZE 50 ++ ++#define M_ADDR_BMP_BLK (0x37e * 2) ++#define M_ADDR_BMP_BLK_SZ 12 ++ ++#define ADDR_BMP_RA (1 << 0) /* Receiver Address (RA) */ ++#define ADDR_BMP_TA (1 << 1) /* Transmitter Address (TA) */ ++#define ADDR_BMP_BSSID (1 << 2) /* BSSID */ ++#define ADDR_BMP_AP (1 << 3) /* Infra-BSS Access Point */ ++#define ADDR_BMP_STA (1 << 4) /* Infra-BSS Station */ ++#define ADDR_BMP_RESERVED1 (1 << 5) ++#define ADDR_BMP_RESERVED2 (1 << 6) ++#define ADDR_BMP_RESERVED3 (1 << 7) ++#define ADDR_BMP_BSS_IDX_MASK (3 << 8) /* BSS control block index */ ++#define ADDR_BMP_BSS_IDX_SHIFT 8 ++ ++#define WSEC_MAX_RCMTA_KEYS 54 ++ ++/* max keys in M_TKMICKEYS_BLK */ ++#define WSEC_MAX_TKMIC_ENGINE_KEYS 12 /* 8 + 4 default */ ++ ++/* max RXE match registers */ ++#define WSEC_MAX_RXE_KEYS 4 ++ ++/* SECKINDXALGO (Security Key Index & Algorithm Block) word format */ ++/* SKL (Security Key Lookup) */ ++#define SKL_ALGO_MASK 0x0007 ++#define SKL_ALGO_SHIFT 0 ++#define SKL_KEYID_MASK 0x0008 ++#define SKL_KEYID_SHIFT 3 ++#define SKL_INDEX_MASK 0x03F0 ++#define SKL_INDEX_SHIFT 4 ++#define SKL_GRP_ALGO_MASK 0x1c00 ++#define SKL_GRP_ALGO_SHIFT 10 ++ ++/* additional bits defined for IBSS group key support */ ++#define SKL_IBSS_INDEX_MASK 0x01F0 ++#define SKL_IBSS_INDEX_SHIFT 4 ++#define SKL_IBSS_KEYID1_MASK 0x0600 ++#define SKL_IBSS_KEYID1_SHIFT 9 ++#define SKL_IBSS_KEYID2_MASK 0x1800 ++#define SKL_IBSS_KEYID2_SHIFT 11 ++#define SKL_IBSS_KEYALGO_MASK 0xE000 ++#define SKL_IBSS_KEYALGO_SHIFT 13 ++ ++#define WSEC_MODE_OFF 0 ++#define WSEC_MODE_HW 1 ++#define WSEC_MODE_SW 2 ++ ++#define WSEC_ALGO_OFF 0 ++#define WSEC_ALGO_WEP1 1 ++#define WSEC_ALGO_TKIP 2 ++#define WSEC_ALGO_AES 3 ++#define WSEC_ALGO_WEP128 4 ++#define WSEC_ALGO_AES_LEGACY 5 ++#define WSEC_ALGO_NALG 6 ++ ++#define AES_MODE_NONE 0 ++#define AES_MODE_CCM 1 ++ ++/* WEP_CTL (Rev 0) */ ++#define WECR0_KEYREG_SHIFT 0 ++#define WECR0_KEYREG_MASK 0x7 ++#define WECR0_DECRYPT (1 << 3) ++#define WECR0_IVINLINE (1 << 4) ++#define WECR0_WEPALG_SHIFT 5 ++#define WECR0_WEPALG_MASK (0x7 << 5) ++#define WECR0_WKEYSEL_SHIFT 8 ++#define WECR0_WKEYSEL_MASK (0x7 << 8) ++#define WECR0_WKEYSTART (1 << 11) ++#define WECR0_WEPINIT (1 << 14) ++#define WECR0_ICVERR (1 << 15) ++ ++/* Frame template map byte offsets */ ++#define T_ACTS_TPL_BASE (0) ++#define T_NULL_TPL_BASE (0xc * 2) ++#define T_QNULL_TPL_BASE (0x1c * 2) ++#define T_RR_TPL_BASE (0x2c * 2) ++#define T_BCN0_TPL_BASE (0x34 * 2) ++#define T_PRS_TPL_BASE (0x134 * 2) ++#define T_BCN1_TPL_BASE (0x234 * 2) ++#define T_TX_FIFO_TXRAM_BASE (T_ACTS_TPL_BASE + \ ++ (TXFIFO_START_BLK * TXFIFO_SIZE_UNIT)) ++ ++#define T_BA_TPL_BASE T_QNULL_TPL_BASE /* template area for BA */ ++ ++#define T_RAM_ACCESS_SZ 4 /* template ram is 4 byte access only */ ++ ++/* Shared Mem byte offsets */ ++ ++/* Location where the ucode expects the corerev */ ++#define M_MACHW_VER (0x00b * 2) ++ ++/* Location where the ucode expects the MAC capabilities */ ++#define M_MACHW_CAP_L (0x060 * 2) ++#define M_MACHW_CAP_H (0x061 * 2) ++ ++/* WME shared memory */ ++#define M_EDCF_STATUS_OFF (0x007 * 2) ++#define M_TXF_CUR_INDEX (0x018 * 2) ++#define M_EDCF_QINFO (0x120 * 2) ++ ++/* PS-mode related parameters */ ++#define M_DOT11_SLOT (0x008 * 2) ++#define M_DOT11_DTIMPERIOD (0x009 * 2) ++#define M_NOSLPZNATDTIM (0x026 * 2) ++ ++/* Beacon-related parameters */ ++#define M_BCN0_FRM_BYTESZ (0x00c * 2) /* Bcn 0 template length */ ++#define M_BCN1_FRM_BYTESZ (0x00d * 2) /* Bcn 1 template length */ ++#define M_BCN_TXTSF_OFFSET (0x00e * 2) ++#define M_TIMBPOS_INBEACON (0x00f * 2) ++#define M_SFRMTXCNTFBRTHSD (0x022 * 2) ++#define M_LFRMTXCNTFBRTHSD (0x023 * 2) ++#define M_BCN_PCTLWD (0x02a * 2) ++#define M_BCN_LI (0x05b * 2) /* beacon listen interval */ ++ ++/* MAX Rx Frame len */ ++#define M_MAXRXFRM_LEN (0x010 * 2) ++ ++/* ACK/CTS related params */ ++#define M_RSP_PCTLWD (0x011 * 2) ++ ++/* Hardware Power Control */ ++#define M_TXPWR_N (0x012 * 2) ++#define M_TXPWR_TARGET (0x013 * 2) ++#define M_TXPWR_MAX (0x014 * 2) ++#define M_TXPWR_CUR (0x019 * 2) ++ ++/* Rx-related parameters */ ++#define M_RX_PAD_DATA_OFFSET (0x01a * 2) ++ ++/* WEP Shared mem data */ ++#define M_SEC_DEFIVLOC (0x01e * 2) ++#define M_SEC_VALNUMSOFTMCHTA (0x01f * 2) ++#define M_PHYVER (0x028 * 2) ++#define M_PHYTYPE (0x029 * 2) ++#define M_SECRXKEYS_PTR (0x02b * 2) ++#define M_TKMICKEYS_PTR (0x059 * 2) ++#define M_SECKINDXALGO_BLK (0x2ea * 2) ++#define M_SECKINDXALGO_BLK_SZ 54 ++#define M_SECPSMRXTAMCH_BLK (0x2fa * 2) ++#define M_TKIP_TSC_TTAK (0x18c * 2) ++#define D11_MAX_KEY_SIZE 16 ++ ++#define M_MAX_ANTCNT (0x02e * 2) /* antenna swap threshold */ ++ ++/* Probe response related parameters */ ++#define M_SSIDLEN (0x024 * 2) ++#define M_PRB_RESP_FRM_LEN (0x025 * 2) ++#define M_PRS_MAXTIME (0x03a * 2) ++#define M_SSID (0xb0 * 2) ++#define M_CTXPRS_BLK (0xc0 * 2) ++#define C_CTX_PCTLWD_POS (0x4 * 2) ++ ++/* Delta between OFDM and CCK power in CCK power boost mode */ ++#define M_OFDM_OFFSET (0x027 * 2) ++ ++/* TSSI for last 4 11b/g CCK packets transmitted */ ++#define M_B_TSSI_0 (0x02c * 2) ++#define M_B_TSSI_1 (0x02d * 2) ++ ++/* Host flags to turn on ucode options */ ++#define M_HOST_FLAGS1 (0x02f * 2) ++#define M_HOST_FLAGS2 (0x030 * 2) ++#define M_HOST_FLAGS3 (0x031 * 2) ++#define M_HOST_FLAGS4 (0x03c * 2) ++#define M_HOST_FLAGS5 (0x06a * 2) ++#define M_HOST_FLAGS_SZ 16 ++ ++#define M_RADAR_REG (0x033 * 2) ++ ++/* TSSI for last 4 11a OFDM packets transmitted */ ++#define M_A_TSSI_0 (0x034 * 2) ++#define M_A_TSSI_1 (0x035 * 2) ++ ++/* noise interference measurement */ ++#define M_NOISE_IF_COUNT (0x034 * 2) ++#define M_NOISE_IF_TIMEOUT (0x035 * 2) ++ ++#define M_RF_RX_SP_REG1 (0x036 * 2) ++ ++/* TSSI for last 4 11g OFDM packets transmitted */ ++#define M_G_TSSI_0 (0x038 * 2) ++#define M_G_TSSI_1 (0x039 * 2) ++ ++/* Background noise measure */ ++#define M_JSSI_0 (0x44 * 2) ++#define M_JSSI_1 (0x45 * 2) ++#define M_JSSI_AUX (0x46 * 2) ++ ++#define M_CUR_2050_RADIOCODE (0x47 * 2) ++ ++/* TX fifo sizes */ ++#define M_FIFOSIZE0 (0x4c * 2) ++#define M_FIFOSIZE1 (0x4d * 2) ++#define M_FIFOSIZE2 (0x4e * 2) ++#define M_FIFOSIZE3 (0x4f * 2) ++#define D11_MAX_TX_FRMS 32 /* max frames allowed in tx fifo */ ++ ++/* Current channel number plus upper bits */ ++#define M_CURCHANNEL (0x50 * 2) ++#define D11_CURCHANNEL_5G 0x0100; ++#define D11_CURCHANNEL_40 0x0200; ++#define D11_CURCHANNEL_MAX 0x00FF; ++ ++/* last posted frameid on the bcmc fifo */ ++#define M_BCMC_FID (0x54 * 2) ++#define INVALIDFID 0xffff ++ ++/* extended beacon phyctl bytes for 11N */ ++#define M_BCN_PCTL1WD (0x058 * 2) ++ ++/* idle busy ratio to duty_cycle requirement */ ++#define M_TX_IDLE_BUSY_RATIO_X_16_CCK (0x52 * 2) ++#define M_TX_IDLE_BUSY_RATIO_X_16_OFDM (0x5A * 2) ++ ++/* CW RSSI for LCNPHY */ ++#define M_LCN_RSSI_0 0x1332 ++#define M_LCN_RSSI_1 0x1338 ++#define M_LCN_RSSI_2 0x133e ++#define M_LCN_RSSI_3 0x1344 ++ ++/* SNR for LCNPHY */ ++#define M_LCN_SNR_A_0 0x1334 ++#define M_LCN_SNR_B_0 0x1336 ++ ++#define M_LCN_SNR_A_1 0x133a ++#define M_LCN_SNR_B_1 0x133c ++ ++#define M_LCN_SNR_A_2 0x1340 ++#define M_LCN_SNR_B_2 0x1342 ++ ++#define M_LCN_SNR_A_3 0x1346 ++#define M_LCN_SNR_B_3 0x1348 ++ ++#define M_LCN_LAST_RESET (81*2) ++#define M_LCN_LAST_LOC (63*2) ++#define M_LCNPHY_RESET_STATUS (4902) ++#define M_LCNPHY_DSC_TIME (0x98d*2) ++#define M_LCNPHY_RESET_CNT_DSC (0x98b*2) ++#define M_LCNPHY_RESET_CNT (0x98c*2) ++ ++/* Rate table offsets */ ++#define M_RT_DIRMAP_A (0xe0 * 2) ++#define M_RT_BBRSMAP_A (0xf0 * 2) ++#define M_RT_DIRMAP_B (0x100 * 2) ++#define M_RT_BBRSMAP_B (0x110 * 2) ++ ++/* Rate table entry offsets */ ++#define M_RT_PRS_PLCP_POS 10 ++#define M_RT_PRS_DUR_POS 16 ++#define M_RT_OFDM_PCTL1_POS 18 ++ ++#define M_20IN40_IQ (0x380 * 2) ++ ++/* SHM locations where ucode stores the current power index */ ++#define M_CURR_IDX1 (0x384 * 2) ++#define M_CURR_IDX2 (0x387 * 2) ++ ++#define M_BSCALE_ANT0 (0x5e * 2) ++#define M_BSCALE_ANT1 (0x5f * 2) ++ ++/* Antenna Diversity Testing */ ++#define M_MIMO_ANTSEL_RXDFLT (0x63 * 2) ++#define M_ANTSEL_CLKDIV (0x61 * 2) ++#define M_MIMO_ANTSEL_TXDFLT (0x64 * 2) ++ ++#define M_MIMO_MAXSYM (0x5d * 2) ++#define MIMO_MAXSYM_DEF 0x8000 /* 32k */ ++#define MIMO_MAXSYM_MAX 0xffff /* 64k */ ++ ++#define M_WATCHDOG_8TU (0x1e * 2) ++#define WATCHDOG_8TU_DEF 5 ++#define WATCHDOG_8TU_MAX 10 ++ ++/* Manufacturing Test Variables */ ++/* PER test mode */ ++#define M_PKTENG_CTRL (0x6c * 2) ++/* IFS for TX mode */ ++#define M_PKTENG_IFS (0x6d * 2) ++/* Lower word of tx frmcnt/rx lostcnt */ ++#define M_PKTENG_FRMCNT_LO (0x6e * 2) ++/* Upper word of tx frmcnt/rx lostcnt */ ++#define M_PKTENG_FRMCNT_HI (0x6f * 2) ++ ++/* Index variation in vbat ripple */ ++#define M_LCN_PWR_IDX_MAX (0x67 * 2) /* highest index read by ucode */ ++#define M_LCN_PWR_IDX_MIN (0x66 * 2) /* lowest index read by ucode */ ++ ++/* M_PKTENG_CTRL bit definitions */ ++#define M_PKTENG_MODE_TX 0x0001 ++#define M_PKTENG_MODE_TX_RIFS 0x0004 ++#define M_PKTENG_MODE_TX_CTS 0x0008 ++#define M_PKTENG_MODE_RX 0x0002 ++#define M_PKTENG_MODE_RX_WITH_ACK 0x0402 ++#define M_PKTENG_MODE_MASK 0x0003 ++/* TX frames indicated in the frmcnt reg */ ++#define M_PKTENG_FRMCNT_VLD 0x0100 ++ ++/* Sample Collect parameters (bitmap and type) */ ++/* Trigger bitmap for sample collect */ ++#define M_SMPL_COL_BMP (0x37d * 2) ++/* Sample collect type */ ++#define M_SMPL_COL_CTL (0x3b2 * 2) ++ ++#define ANTSEL_CLKDIV_4MHZ 6 ++#define MIMO_ANTSEL_BUSY 0x4000 /* bit 14 (busy) */ ++#define MIMO_ANTSEL_SEL 0x8000 /* bit 15 write the value */ ++#define MIMO_ANTSEL_WAIT 50 /* 50us wait */ ++#define MIMO_ANTSEL_OVERRIDE 0x8000 /* flag */ ++ ++struct shm_acparams { ++ u16 txop; ++ u16 cwmin; ++ u16 cwmax; ++ u16 cwcur; ++ u16 aifs; ++ u16 bslots; ++ u16 reggap; ++ u16 status; ++ u16 rsvd[8]; ++} __packed; ++#define M_EDCF_QLEN (16 * 2) ++ ++#define WME_STATUS_NEWAC (1 << 8) ++ ++/* M_HOST_FLAGS */ ++#define MHFMAX 5 /* Number of valid hostflag half-word (u16) */ ++#define MHF1 0 /* Hostflag 1 index */ ++#define MHF2 1 /* Hostflag 2 index */ ++#define MHF3 2 /* Hostflag 3 index */ ++#define MHF4 3 /* Hostflag 4 index */ ++#define MHF5 4 /* Hostflag 5 index */ ++ ++/* Flags in M_HOST_FLAGS */ ++/* Enable ucode antenna diversity help */ ++#define MHF1_ANTDIV 0x0001 ++/* Enable EDCF access control */ ++#define MHF1_EDCF 0x0100 ++#define MHF1_IQSWAP_WAR 0x0200 ++/* Disable Slow clock request, for corerev < 11 */ ++#define MHF1_FORCEFASTCLK 0x0400 ++ ++/* Flags in M_HOST_FLAGS2 */ ++ ++/* Flush BCMC FIFO immediately */ ++#define MHF2_TXBCMC_NOW 0x0040 ++/* Enable ucode/hw power control */ ++#define MHF2_HWPWRCTL 0x0080 ++#define MHF2_NPHY40MHZ_WAR 0x0800 ++ ++/* Flags in M_HOST_FLAGS3 */ ++/* enabled mimo antenna selection */ ++#define MHF3_ANTSEL_EN 0x0001 ++/* antenna selection mode: 0: 2x3, 1: 2x4 */ ++#define MHF3_ANTSEL_MODE 0x0002 ++#define MHF3_RESERVED1 0x0004 ++#define MHF3_RESERVED2 0x0008 ++#define MHF3_NPHY_MLADV_WAR 0x0010 ++ ++/* Flags in M_HOST_FLAGS4 */ ++/* force bphy Tx on core 0 (board level WAR) */ ++#define MHF4_BPHY_TXCORE0 0x0080 ++/* for 4313A0 FEM boards */ ++#define MHF4_EXTPA_ENABLE 0x4000 ++ ++/* Flags in M_HOST_FLAGS5 */ ++#define MHF5_4313_GPIOCTRL 0x0001 ++#define MHF5_RESERVED1 0x0002 ++#define MHF5_RESERVED2 0x0004 ++/* Radio power setting for ucode */ ++#define M_RADIO_PWR (0x32 * 2) ++ ++/* phy noise recorded by ucode right after tx */ ++#define M_PHY_NOISE (0x037 * 2) ++#define PHY_NOISE_MASK 0x00ff ++ ++/* ++ * Receive Frame Data Header for 802.11b DCF-only frames ++ * ++ * RxFrameSize: Actual byte length of the frame data received ++ * PAD: padding (not used) ++ * PhyRxStatus_0: PhyRxStatus 15:0 ++ * PhyRxStatus_1: PhyRxStatus 31:16 ++ * PhyRxStatus_2: PhyRxStatus 47:32 ++ * PhyRxStatus_3: PhyRxStatus 63:48 ++ * PhyRxStatus_4: PhyRxStatus 79:64 ++ * PhyRxStatus_5: PhyRxStatus 95:80 ++ * RxStatus1: MAC Rx Status ++ * RxStatus2: extended MAC Rx status ++ * RxTSFTime: RxTSFTime time of first MAC symbol + M_PHY_PLCPRX_DLY ++ * RxChan: gain code, channel radio code, and phy type ++ */ ++struct d11rxhdr_le { ++ __le16 RxFrameSize; ++ u16 PAD; ++ __le16 PhyRxStatus_0; ++ __le16 PhyRxStatus_1; ++ __le16 PhyRxStatus_2; ++ __le16 PhyRxStatus_3; ++ __le16 PhyRxStatus_4; ++ __le16 PhyRxStatus_5; ++ __le16 RxStatus1; ++ __le16 RxStatus2; ++ __le16 RxTSFTime; ++ __le16 RxChan; ++} __packed; ++ ++struct d11rxhdr { ++ u16 RxFrameSize; ++ u16 PAD; ++ u16 PhyRxStatus_0; ++ u16 PhyRxStatus_1; ++ u16 PhyRxStatus_2; ++ u16 PhyRxStatus_3; ++ u16 PhyRxStatus_4; ++ u16 PhyRxStatus_5; ++ u16 RxStatus1; ++ u16 RxStatus2; ++ u16 RxTSFTime; ++ u16 RxChan; ++} __packed; ++ ++/* PhyRxStatus_0: */ ++/* NPHY only: CCK, OFDM, preN, N */ ++#define PRXS0_FT_MASK 0x0003 ++/* NPHY only: clip count adjustment steps by AGC */ ++#define PRXS0_CLIP_MASK 0x000C ++#define PRXS0_CLIP_SHIFT 2 ++/* PHY received a frame with unsupported rate */ ++#define PRXS0_UNSRATE 0x0010 ++/* GPHY: rx ant, NPHY: upper sideband */ ++#define PRXS0_RXANT_UPSUBBAND 0x0020 ++/* CCK frame only: lost crs during cck frame reception */ ++#define PRXS0_LCRS 0x0040 ++/* Short Preamble */ ++#define PRXS0_SHORTH 0x0080 ++/* PLCP violation */ ++#define PRXS0_PLCPFV 0x0100 ++/* PLCP header integrity check failed */ ++#define PRXS0_PLCPHCF 0x0200 ++/* legacy PHY gain control */ ++#define PRXS0_GAIN_CTL 0x4000 ++/* NPHY: Antennas used for received frame, bitmask */ ++#define PRXS0_ANTSEL_MASK 0xF000 ++#define PRXS0_ANTSEL_SHIFT 0x12 ++ ++/* subfield PRXS0_FT_MASK */ ++#define PRXS0_CCK 0x0000 ++/* valid only for G phy, use rxh->RxChan for A phy */ ++#define PRXS0_OFDM 0x0001 ++#define PRXS0_PREN 0x0002 ++#define PRXS0_STDN 0x0003 ++ ++/* subfield PRXS0_ANTSEL_MASK */ ++#define PRXS0_ANTSEL_0 0x0 /* antenna 0 is used */ ++#define PRXS0_ANTSEL_1 0x2 /* antenna 1 is used */ ++#define PRXS0_ANTSEL_2 0x4 /* antenna 2 is used */ ++#define PRXS0_ANTSEL_3 0x8 /* antenna 3 is used */ ++ ++/* PhyRxStatus_1: */ ++#define PRXS1_JSSI_MASK 0x00FF ++#define PRXS1_JSSI_SHIFT 0 ++#define PRXS1_SQ_MASK 0xFF00 ++#define PRXS1_SQ_SHIFT 8 ++ ++/* nphy PhyRxStatus_1: */ ++#define PRXS1_nphy_PWR0_MASK 0x00FF ++#define PRXS1_nphy_PWR1_MASK 0xFF00 ++ ++/* HTPHY Rx Status defines */ ++/* htphy PhyRxStatus_0: those bit are overlapped with PhyRxStatus_0 */ ++#define PRXS0_BAND 0x0400 /* 0 = 2.4G, 1 = 5G */ ++#define PRXS0_RSVD 0x0800 /* reserved; set to 0 */ ++#define PRXS0_UNUSED 0xF000 /* unused and not defined; set to 0 */ ++ ++/* htphy PhyRxStatus_1: */ ++/* core enables for {3..0}, 0=disabled, 1=enabled */ ++#define PRXS1_HTPHY_CORE_MASK 0x000F ++/* antenna configation */ ++#define PRXS1_HTPHY_ANTCFG_MASK 0x00F0 ++/* Mixmode PLCP Length low byte mask */ ++#define PRXS1_HTPHY_MMPLCPLenL_MASK 0xFF00 ++ ++/* htphy PhyRxStatus_2: */ ++/* Mixmode PLCP Length high byte maskw */ ++#define PRXS2_HTPHY_MMPLCPLenH_MASK 0x000F ++/* Mixmode PLCP rate mask */ ++#define PRXS2_HTPHY_MMPLCH_RATE_MASK 0x00F0 ++/* Rx power on core 0 */ ++#define PRXS2_HTPHY_RXPWR_ANT0 0xFF00 ++ ++/* htphy PhyRxStatus_3: */ ++/* Rx power on core 1 */ ++#define PRXS3_HTPHY_RXPWR_ANT1 0x00FF ++/* Rx power on core 2 */ ++#define PRXS3_HTPHY_RXPWR_ANT2 0xFF00 ++ ++/* htphy PhyRxStatus_4: */ ++/* Rx power on core 3 */ ++#define PRXS4_HTPHY_RXPWR_ANT3 0x00FF ++/* Coarse frequency offset */ ++#define PRXS4_HTPHY_CFO 0xFF00 ++ ++/* htphy PhyRxStatus_5: */ ++/* Fine frequency offset */ ++#define PRXS5_HTPHY_FFO 0x00FF ++/* Advance Retard */ ++#define PRXS5_HTPHY_AR 0xFF00 ++ ++#define HTPHY_MMPLCPLen(rxs) \ ++ ((((rxs)->PhyRxStatus_1 & PRXS1_HTPHY_MMPLCPLenL_MASK) >> 8) | \ ++ (((rxs)->PhyRxStatus_2 & PRXS2_HTPHY_MMPLCPLenH_MASK) << 8)) ++/* Get Rx power on core 0 */ ++#define HTPHY_RXPWR_ANT0(rxs) \ ++ ((((rxs)->PhyRxStatus_2) & PRXS2_HTPHY_RXPWR_ANT0) >> 8) ++/* Get Rx power on core 1 */ ++#define HTPHY_RXPWR_ANT1(rxs) \ ++ (((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT1) ++/* Get Rx power on core 2 */ ++#define HTPHY_RXPWR_ANT2(rxs) \ ++ ((((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT2) >> 8) ++ ++/* ucode RxStatus1: */ ++#define RXS_BCNSENT 0x8000 ++#define RXS_SECKINDX_MASK 0x07e0 ++#define RXS_SECKINDX_SHIFT 5 ++#define RXS_DECERR (1 << 4) ++#define RXS_DECATMPT (1 << 3) ++/* PAD bytes to make IP data 4 bytes aligned */ ++#define RXS_PBPRES (1 << 2) ++#define RXS_RESPFRAMETX (1 << 1) ++#define RXS_FCSERR (1 << 0) ++ ++/* ucode RxStatus2: */ ++#define RXS_AMSDU_MASK 1 ++#define RXS_AGGTYPE_MASK 0x6 ++#define RXS_AGGTYPE_SHIFT 1 ++#define RXS_PHYRXST_VALID (1 << 8) ++#define RXS_RXANT_MASK 0x3 ++#define RXS_RXANT_SHIFT 12 ++ ++/* RxChan */ ++#define RXS_CHAN_40 0x1000 ++#define RXS_CHAN_5G 0x0800 ++#define RXS_CHAN_ID_MASK 0x07f8 ++#define RXS_CHAN_ID_SHIFT 3 ++#define RXS_CHAN_PHYTYPE_MASK 0x0007 ++#define RXS_CHAN_PHYTYPE_SHIFT 0 ++ ++/* Index of attenuations used during ucode power control. */ ++#define M_PWRIND_BLKS (0x184 * 2) ++#define M_PWRIND_MAP0 (M_PWRIND_BLKS + 0x0) ++#define M_PWRIND_MAP1 (M_PWRIND_BLKS + 0x2) ++#define M_PWRIND_MAP2 (M_PWRIND_BLKS + 0x4) ++#define M_PWRIND_MAP3 (M_PWRIND_BLKS + 0x6) ++/* M_PWRIND_MAP(core) macro */ ++#define M_PWRIND_MAP(core) (M_PWRIND_BLKS + ((core)<<1)) ++ ++/* PSM SHM variable offsets */ ++#define M_PSM_SOFT_REGS 0x0 ++#define M_BOM_REV_MAJOR (M_PSM_SOFT_REGS + 0x0) ++#define M_BOM_REV_MINOR (M_PSM_SOFT_REGS + 0x2) ++#define M_UCODE_DBGST (M_PSM_SOFT_REGS + 0x40) /* ucode debug status code */ ++#define M_UCODE_MACSTAT (M_PSM_SOFT_REGS + 0xE0) /* macstat counters */ ++ ++#define M_AGING_THRSH (0x3e * 2) /* max time waiting for medium before tx */ ++#define M_MBURST_SIZE (0x40 * 2) /* max frames in a frameburst */ ++#define M_MBURST_TXOP (0x41 * 2) /* max frameburst TXOP in unit of us */ ++#define M_SYNTHPU_DLY (0x4a * 2) /* pre-wakeup for synthpu, default: 500 */ ++#define M_PRETBTT (0x4b * 2) ++ ++/* offset to the target txpwr */ ++#define M_ALT_TXPWR_IDX (M_PSM_SOFT_REGS + (0x3b * 2)) ++#define M_PHY_TX_FLT_PTR (M_PSM_SOFT_REGS + (0x3d * 2)) ++#define M_CTS_DURATION (M_PSM_SOFT_REGS + (0x5c * 2)) ++#define M_LP_RCCAL_OVR (M_PSM_SOFT_REGS + (0x6b * 2)) ++ ++/* PKTENG Rx Stats Block */ ++#define M_RXSTATS_BLK_PTR (M_PSM_SOFT_REGS + (0x65 * 2)) ++ ++/* ucode debug status codes */ ++/* not valid really */ ++#define DBGST_INACTIVE 0 ++/* after zeroing SHM, before suspending at init */ ++#define DBGST_INIT 1 ++/* "normal" state */ ++#define DBGST_ACTIVE 2 ++/* suspended */ ++#define DBGST_SUSPENDED 3 ++/* asleep (PS mode) */ ++#define DBGST_ASLEEP 4 ++ ++/* Scratch Reg defs */ ++enum _ePsmScratchPadRegDefinitions { ++ S_RSV0 = 0, ++ S_RSV1, ++ S_RSV2, ++ ++ /* offset 0x03: scratch registers for Dot11-contants */ ++ S_DOT11_CWMIN, /* CW-minimum */ ++ S_DOT11_CWMAX, /* CW-maximum */ ++ S_DOT11_CWCUR, /* CW-current */ ++ S_DOT11_SRC_LMT, /* short retry count limit */ ++ S_DOT11_LRC_LMT, /* long retry count limit */ ++ S_DOT11_DTIMCOUNT, /* DTIM-count */ ++ ++ /* offset 0x09: Tx-side scratch registers */ ++ S_SEQ_NUM, /* hardware sequence number reg */ ++ S_SEQ_NUM_FRAG, /* seq num for frags (at the start of MSDU) */ ++ S_FRMRETX_CNT, /* frame retx count */ ++ S_SSRC, /* Station short retry count */ ++ S_SLRC, /* Station long retry count */ ++ S_EXP_RSP, /* Expected response frame */ ++ S_OLD_BREM, /* Remaining backoff ctr */ ++ S_OLD_CWWIN, /* saved-off CW-cur */ ++ S_TXECTL, /* TXE-Ctl word constructed in scr-pad */ ++ S_CTXTST, /* frm type-subtype as read from Tx-descr */ ++ ++ /* offset 0x13: Rx-side scratch registers */ ++ S_RXTST, /* Type and subtype in Rxframe */ ++ ++ /* Global state register */ ++ S_STREG, /* state storage actual bit maps below */ ++ ++ S_TXPWR_SUM, /* Tx power control: accumulator */ ++ S_TXPWR_ITER, /* Tx power control: iteration */ ++ S_RX_FRMTYPE, /* Rate and PHY type for frames */ ++ S_THIS_AGG, /* Size of this AGG (A-MSDU) */ ++ ++ S_KEYINDX, ++ S_RXFRMLEN, /* Receive MPDU length in bytes */ ++ ++ /* offset 0x1B: Receive TSF time stored in SCR */ ++ S_RXTSFTMRVAL_WD3, /* TSF value at the start of rx */ ++ S_RXTSFTMRVAL_WD2, /* TSF value at the start of rx */ ++ S_RXTSFTMRVAL_WD1, /* TSF value at the start of rx */ ++ S_RXTSFTMRVAL_WD0, /* TSF value at the start of rx */ ++ S_RXSSN, /* Received start seq number for A-MPDU BA */ ++ S_RXQOSFLD, /* Rx-QoS field (if present) */ ++ ++ /* offset 0x21: Scratch pad regs used in microcode as temp storage */ ++ S_TMP0, /* stmp0 */ ++ S_TMP1, /* stmp1 */ ++ S_TMP2, /* stmp2 */ ++ S_TMP3, /* stmp3 */ ++ S_TMP4, /* stmp4 */ ++ S_TMP5, /* stmp5 */ ++ S_PRQPENALTY_CTR, /* Probe response queue penalty counter */ ++ S_ANTCNT, /* unsuccessful attempts on current ant. */ ++ S_SYMBOL, /* flag for possible symbol ctl frames */ ++ S_RXTP, /* rx frame type */ ++ S_STREG2, /* extra state storage */ ++ S_STREG3, /* even more extra state storage */ ++ S_STREG4, /* ... */ ++ S_STREG5, /* remember to initialize it to zero */ ++ ++ S_ADJPWR_IDX, ++ S_CUR_PTR, /* Temp pointer for A-MPDU re-Tx SHM table */ ++ S_REVID4, /* 0x33 */ ++ S_INDX, /* 0x34 */ ++ S_ADDR0, /* 0x35 */ ++ S_ADDR1, /* 0x36 */ ++ S_ADDR2, /* 0x37 */ ++ S_ADDR3, /* 0x38 */ ++ S_ADDR4, /* 0x39 */ ++ S_ADDR5, /* 0x3A */ ++ S_TMP6, /* 0x3B */ ++ S_KEYINDX_BU, /* Backup for Key index */ ++ S_MFGTEST_TMP0, /* Temp regs used for RX test calculations */ ++ S_RXESN, /* Received end sequence number for A-MPDU BA */ ++ S_STREG6, /* 0x3F */ ++}; ++ ++#define S_BEACON_INDX S_OLD_BREM ++#define S_PRS_INDX S_OLD_CWWIN ++#define S_PHYTYPE S_SSRC ++#define S_PHYVER S_SLRC ++ ++/* IHR SLOW_CTRL values */ ++#define SLOW_CTRL_PDE (1 << 0) ++#define SLOW_CTRL_FD (1 << 8) ++ ++/* ucode mac statistic counters in shared memory */ ++struct macstat { ++ u16 txallfrm; /* 0x80 */ ++ u16 txrtsfrm; /* 0x82 */ ++ u16 txctsfrm; /* 0x84 */ ++ u16 txackfrm; /* 0x86 */ ++ u16 txdnlfrm; /* 0x88 */ ++ u16 txbcnfrm; /* 0x8a */ ++ u16 txfunfl[8]; /* 0x8c - 0x9b */ ++ u16 txtplunfl; /* 0x9c */ ++ u16 txphyerr; /* 0x9e */ ++ u16 pktengrxducast; /* 0xa0 */ ++ u16 pktengrxdmcast; /* 0xa2 */ ++ u16 rxfrmtoolong; /* 0xa4 */ ++ u16 rxfrmtooshrt; /* 0xa6 */ ++ u16 rxinvmachdr; /* 0xa8 */ ++ u16 rxbadfcs; /* 0xaa */ ++ u16 rxbadplcp; /* 0xac */ ++ u16 rxcrsglitch; /* 0xae */ ++ u16 rxstrt; /* 0xb0 */ ++ u16 rxdfrmucastmbss; /* 0xb2 */ ++ u16 rxmfrmucastmbss; /* 0xb4 */ ++ u16 rxcfrmucast; /* 0xb6 */ ++ u16 rxrtsucast; /* 0xb8 */ ++ u16 rxctsucast; /* 0xba */ ++ u16 rxackucast; /* 0xbc */ ++ u16 rxdfrmocast; /* 0xbe */ ++ u16 rxmfrmocast; /* 0xc0 */ ++ u16 rxcfrmocast; /* 0xc2 */ ++ u16 rxrtsocast; /* 0xc4 */ ++ u16 rxctsocast; /* 0xc6 */ ++ u16 rxdfrmmcast; /* 0xc8 */ ++ u16 rxmfrmmcast; /* 0xca */ ++ u16 rxcfrmmcast; /* 0xcc */ ++ u16 rxbeaconmbss; /* 0xce */ ++ u16 rxdfrmucastobss; /* 0xd0 */ ++ u16 rxbeaconobss; /* 0xd2 */ ++ u16 rxrsptmout; /* 0xd4 */ ++ u16 bcntxcancl; /* 0xd6 */ ++ u16 PAD; ++ u16 rxf0ovfl; /* 0xda */ ++ u16 rxf1ovfl; /* 0xdc */ ++ u16 rxf2ovfl; /* 0xde */ ++ u16 txsfovfl; /* 0xe0 */ ++ u16 pmqovfl; /* 0xe2 */ ++ u16 rxcgprqfrm; /* 0xe4 */ ++ u16 rxcgprsqovfl; /* 0xe6 */ ++ u16 txcgprsfail; /* 0xe8 */ ++ u16 txcgprssuc; /* 0xea */ ++ u16 prs_timeout; /* 0xec */ ++ u16 rxnack; ++ u16 frmscons; ++ u16 txnack; ++ u16 txglitch_nack; ++ u16 txburst; /* 0xf6 # tx bursts */ ++ u16 bphy_rxcrsglitch; /* bphy rx crs glitch */ ++ u16 phywatchdog; /* 0xfa # of phy watchdog events */ ++ u16 PAD; ++ u16 bphy_badplcp; /* bphy bad plcp */ ++}; ++ ++/* dot11 core-specific control flags */ ++#define SICF_PCLKE 0x0004 /* PHY clock enable */ ++#define SICF_PRST 0x0008 /* PHY reset */ ++#define SICF_MPCLKE 0x0010 /* MAC PHY clockcontrol enable */ ++#define SICF_FREF 0x0020 /* PLL FreqRefSelect */ ++/* NOTE: the following bw bits only apply when the core is attached ++ * to a NPHY ++ */ ++#define SICF_BWMASK 0x00c0 /* phy clock mask (b6 & b7) */ ++#define SICF_BW40 0x0080 /* 40MHz BW (160MHz phyclk) */ ++#define SICF_BW20 0x0040 /* 20MHz BW (80MHz phyclk) */ ++#define SICF_BW10 0x0000 /* 10MHz BW (40MHz phyclk) */ ++#define SICF_GMODE 0x2000 /* gmode enable */ ++ ++/* dot11 core-specific status flags */ ++#define SISF_2G_PHY 0x0001 /* 2.4G capable phy */ ++#define SISF_5G_PHY 0x0002 /* 5G capable phy */ ++#define SISF_FCLKA 0x0004 /* FastClkAvailable */ ++#define SISF_DB_PHY 0x0008 /* Dualband phy */ ++ ++/* === End of MAC reg, Beginning of PHY(b/a/g/n) reg === */ ++/* radio and LPPHY regs are separated */ ++ ++#define BPHY_REG_OFT_BASE 0x0 ++/* offsets for indirect access to bphy registers */ ++#define BPHY_BB_CONFIG 0x01 ++#define BPHY_ADCBIAS 0x02 ++#define BPHY_ANACORE 0x03 ++#define BPHY_PHYCRSTH 0x06 ++#define BPHY_TEST 0x0a ++#define BPHY_PA_TX_TO 0x10 ++#define BPHY_SYNTH_DC_TO 0x11 ++#define BPHY_PA_TX_TIME_UP 0x12 ++#define BPHY_RX_FLTR_TIME_UP 0x13 ++#define BPHY_TX_POWER_OVERRIDE 0x14 ++#define BPHY_RF_OVERRIDE 0x15 ++#define BPHY_RF_TR_LOOKUP1 0x16 ++#define BPHY_RF_TR_LOOKUP2 0x17 ++#define BPHY_COEFFS 0x18 ++#define BPHY_PLL_OUT 0x19 ++#define BPHY_REFRESH_MAIN 0x1a ++#define BPHY_REFRESH_TO0 0x1b ++#define BPHY_REFRESH_TO1 0x1c ++#define BPHY_RSSI_TRESH 0x20 ++#define BPHY_IQ_TRESH_HH 0x21 ++#define BPHY_IQ_TRESH_H 0x22 ++#define BPHY_IQ_TRESH_L 0x23 ++#define BPHY_IQ_TRESH_LL 0x24 ++#define BPHY_GAIN 0x25 ++#define BPHY_LNA_GAIN_RANGE 0x26 ++#define BPHY_JSSI 0x27 ++#define BPHY_TSSI_CTL 0x28 ++#define BPHY_TSSI 0x29 ++#define BPHY_TR_LOSS_CTL 0x2a ++#define BPHY_LO_LEAKAGE 0x2b ++#define BPHY_LO_RSSI_ACC 0x2c ++#define BPHY_LO_IQMAG_ACC 0x2d ++#define BPHY_TX_DC_OFF1 0x2e ++#define BPHY_TX_DC_OFF2 0x2f ++#define BPHY_PEAK_CNT_THRESH 0x30 ++#define BPHY_FREQ_OFFSET 0x31 ++#define BPHY_DIVERSITY_CTL 0x32 ++#define BPHY_PEAK_ENERGY_LO 0x33 ++#define BPHY_PEAK_ENERGY_HI 0x34 ++#define BPHY_SYNC_CTL 0x35 ++#define BPHY_TX_PWR_CTRL 0x36 ++#define BPHY_TX_EST_PWR 0x37 ++#define BPHY_STEP 0x38 ++#define BPHY_WARMUP 0x39 ++#define BPHY_LMS_CFF_READ 0x3a ++#define BPHY_LMS_COEFF_I 0x3b ++#define BPHY_LMS_COEFF_Q 0x3c ++#define BPHY_SIG_POW 0x3d ++#define BPHY_RFDC_CANCEL_CTL 0x3e ++#define BPHY_HDR_TYPE 0x40 ++#define BPHY_SFD_TO 0x41 ++#define BPHY_SFD_CTL 0x42 ++#define BPHY_DEBUG 0x43 ++#define BPHY_RX_DELAY_COMP 0x44 ++#define BPHY_CRS_DROP_TO 0x45 ++#define BPHY_SHORT_SFD_NZEROS 0x46 ++#define BPHY_DSSS_COEFF1 0x48 ++#define BPHY_DSSS_COEFF2 0x49 ++#define BPHY_CCK_COEFF1 0x4a ++#define BPHY_CCK_COEFF2 0x4b ++#define BPHY_TR_CORR 0x4c ++#define BPHY_ANGLE_SCALE 0x4d ++#define BPHY_TX_PWR_BASE_IDX 0x4e ++#define BPHY_OPTIONAL_MODES2 0x4f ++#define BPHY_CCK_LMS_STEP 0x50 ++#define BPHY_BYPASS 0x51 ++#define BPHY_CCK_DELAY_LONG 0x52 ++#define BPHY_CCK_DELAY_SHORT 0x53 ++#define BPHY_PPROC_CHAN_DELAY 0x54 ++#define BPHY_DDFS_ENABLE 0x58 ++#define BPHY_PHASE_SCALE 0x59 ++#define BPHY_FREQ_CONTROL 0x5a ++#define BPHY_LNA_GAIN_RANGE_10 0x5b ++#define BPHY_LNA_GAIN_RANGE_32 0x5c ++#define BPHY_OPTIONAL_MODES 0x5d ++#define BPHY_RX_STATUS2 0x5e ++#define BPHY_RX_STATUS3 0x5f ++#define BPHY_DAC_CONTROL 0x60 ++#define BPHY_ANA11G_FILT_CTRL 0x62 ++#define BPHY_REFRESH_CTRL 0x64 ++#define BPHY_RF_OVERRIDE2 0x65 ++#define BPHY_SPUR_CANCEL_CTRL 0x66 ++#define BPHY_FINE_DIGIGAIN_CTRL 0x67 ++#define BPHY_RSSI_LUT 0x88 ++#define BPHY_RSSI_LUT_END 0xa7 ++#define BPHY_TSSI_LUT 0xa8 ++#define BPHY_TSSI_LUT_END 0xc7 ++#define BPHY_TSSI2PWR_LUT 0x380 ++#define BPHY_TSSI2PWR_LUT_END 0x39f ++#define BPHY_LOCOMP_LUT 0x3a0 ++#define BPHY_LOCOMP_LUT_END 0x3bf ++#define BPHY_TXGAIN_LUT 0x3c0 ++#define BPHY_TXGAIN_LUT_END 0x3ff ++ ++/* Bits in BB_CONFIG: */ ++#define PHY_BBC_ANT_MASK 0x0180 ++#define PHY_BBC_ANT_SHIFT 7 ++#define BB_DARWIN 0x1000 ++#define BBCFG_RESETCCA 0x4000 ++#define BBCFG_RESETRX 0x8000 ++ ++/* Bits in phytest(0x0a): */ ++#define TST_DDFS 0x2000 ++#define TST_TXFILT1 0x0800 ++#define TST_UNSCRAM 0x0400 ++#define TST_CARR_SUPP 0x0200 ++#define TST_DC_COMP_LOOP 0x0100 ++#define TST_LOOPBACK 0x0080 ++#define TST_TXFILT0 0x0040 ++#define TST_TXTEST_ENABLE 0x0020 ++#define TST_TXTEST_RATE 0x0018 ++#define TST_TXTEST_PHASE 0x0007 ++ ++/* phytest txTestRate values */ ++#define TST_TXTEST_RATE_1MBPS 0 ++#define TST_TXTEST_RATE_2MBPS 1 ++#define TST_TXTEST_RATE_5_5MBPS 2 ++#define TST_TXTEST_RATE_11MBPS 3 ++#define TST_TXTEST_RATE_SHIFT 3 ++ ++#define SHM_BYT_CNT 0x2 /* IHR location */ ++#define MAX_BYT_CNT 0x600 /* Maximum frame len */ ++ ++struct d11cnt { ++ u32 txfrag; ++ u32 txmulti; ++ u32 txfail; ++ u32 txretry; ++ u32 txretrie; ++ u32 rxdup; ++ u32 txrts; ++ u32 txnocts; ++ u32 txnoack; ++ u32 rxfrag; ++ u32 rxmulti; ++ u32 rxcrc; ++ u32 txfrmsnt; ++ u32 rxundec; ++}; ++ ++#endif /* _BRCM_D11_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.c.orig 2011-11-09 13:46:58.244800645 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.c 2011-11-09 13:47:16.997566205 -0500 +@@ -0,0 +1,1425 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include "types.h" ++#include "dma.h" ++ ++/* ++ * DMA hardware requires each descriptor ring to be 8kB aligned, and fit within ++ * a contiguous 8kB physical address. ++ */ ++#define D64RINGALIGN_BITS 13 ++#define D64MAXRINGSZ (1 << D64RINGALIGN_BITS) ++#define D64RINGALIGN (1 << D64RINGALIGN_BITS) ++ ++#define D64MAXDD (D64MAXRINGSZ / sizeof(struct dma64desc)) ++ ++/* transmit channel control */ ++#define D64_XC_XE 0x00000001 /* transmit enable */ ++#define D64_XC_SE 0x00000002 /* transmit suspend request */ ++#define D64_XC_LE 0x00000004 /* loopback enable */ ++#define D64_XC_FL 0x00000010 /* flush request */ ++#define D64_XC_PD 0x00000800 /* parity check disable */ ++#define D64_XC_AE 0x00030000 /* address extension bits */ ++#define D64_XC_AE_SHIFT 16 ++ ++/* transmit descriptor table pointer */ ++#define D64_XP_LD_MASK 0x00000fff /* last valid descriptor */ ++ ++/* transmit channel status */ ++#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */ ++#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */ ++#define D64_XS0_XS_SHIFT 28 ++#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */ ++#define D64_XS0_XS_ACTIVE 0x10000000 /* active */ ++#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */ ++#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */ ++#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */ ++ ++#define D64_XS1_AD_MASK 0x00001fff /* active descriptor */ ++#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */ ++#define D64_XS1_XE_SHIFT 28 ++#define D64_XS1_XE_NOERR 0x00000000 /* no error */ ++#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */ ++#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */ ++#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */ ++#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */ ++#define D64_XS1_XE_COREE 0x50000000 /* core error */ ++ ++/* receive channel control */ ++/* receive enable */ ++#define D64_RC_RE 0x00000001 ++/* receive frame offset */ ++#define D64_RC_RO_MASK 0x000000fe ++#define D64_RC_RO_SHIFT 1 ++/* direct fifo receive (pio) mode */ ++#define D64_RC_FM 0x00000100 ++/* separate rx header descriptor enable */ ++#define D64_RC_SH 0x00000200 ++/* overflow continue */ ++#define D64_RC_OC 0x00000400 ++/* parity check disable */ ++#define D64_RC_PD 0x00000800 ++/* address extension bits */ ++#define D64_RC_AE 0x00030000 ++#define D64_RC_AE_SHIFT 16 ++ ++/* flags for dma controller */ ++/* partity enable */ ++#define DMA_CTRL_PEN (1 << 0) ++/* rx overflow continue */ ++#define DMA_CTRL_ROC (1 << 1) ++/* allow rx scatter to multiple descriptors */ ++#define DMA_CTRL_RXMULTI (1 << 2) ++/* Unframed Rx/Tx data */ ++#define DMA_CTRL_UNFRAMED (1 << 3) ++ ++/* receive descriptor table pointer */ ++#define D64_RP_LD_MASK 0x00000fff /* last valid descriptor */ ++ ++/* receive channel status */ ++#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */ ++#define D64_RS0_RS_MASK 0xf0000000 /* receive state */ ++#define D64_RS0_RS_SHIFT 28 ++#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */ ++#define D64_RS0_RS_ACTIVE 0x10000000 /* active */ ++#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */ ++#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */ ++#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */ ++ ++#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */ ++#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */ ++#define D64_RS1_RE_SHIFT 28 ++#define D64_RS1_RE_NOERR 0x00000000 /* no error */ ++#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */ ++#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */ ++#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */ ++#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */ ++#define D64_RS1_RE_COREE 0x50000000 /* core error */ ++ ++/* fifoaddr */ ++#define D64_FA_OFF_MASK 0xffff /* offset */ ++#define D64_FA_SEL_MASK 0xf0000 /* select */ ++#define D64_FA_SEL_SHIFT 16 ++#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */ ++#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */ ++#define D64_FA_SEL_RDD 0x40000 /* receive dma data */ ++#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */ ++#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */ ++#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */ ++#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */ ++#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */ ++#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */ ++#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */ ++ ++/* descriptor control flags 1 */ ++#define D64_CTRL_COREFLAGS 0x0ff00000 /* core specific flags */ ++#define D64_CTRL1_EOT ((u32)1 << 28) /* end of descriptor table */ ++#define D64_CTRL1_IOC ((u32)1 << 29) /* interrupt on completion */ ++#define D64_CTRL1_EOF ((u32)1 << 30) /* end of frame */ ++#define D64_CTRL1_SOF ((u32)1 << 31) /* start of frame */ ++ ++/* descriptor control flags 2 */ ++/* buffer byte count. real data len must <= 16KB */ ++#define D64_CTRL2_BC_MASK 0x00007fff ++/* address extension bits */ ++#define D64_CTRL2_AE 0x00030000 ++#define D64_CTRL2_AE_SHIFT 16 ++/* parity bit */ ++#define D64_CTRL2_PARITY 0x00040000 ++ ++/* control flags in the range [27:20] are core-specific and not defined here */ ++#define D64_CTRL_CORE_MASK 0x0ff00000 ++ ++#define D64_RX_FRM_STS_LEN 0x0000ffff /* frame length mask */ ++#define D64_RX_FRM_STS_OVFL 0x00800000 /* RxOverFlow */ ++#define D64_RX_FRM_STS_DSCRCNT 0x0f000000 /* no. of descriptors used - 1 */ ++#define D64_RX_FRM_STS_DATATYPE 0xf0000000 /* core-dependent data type */ ++ ++/* ++ * packet headroom necessary to accommodate the largest header ++ * in the system, (i.e TXOFF). By doing, we avoid the need to ++ * allocate an extra buffer for the header when bridging to WL. ++ * There is a compile time check in wlc.c which ensure that this ++ * value is at least as big as TXOFF. This value is used in ++ * dma_rxfill(). ++ */ ++ ++#define BCMEXTRAHDROOM 172 ++ ++/* debug/trace */ ++#ifdef BCMDBG ++#define DMA_ERROR(args) \ ++ do { \ ++ if (!(*di->msg_level & 1)) \ ++ ; \ ++ else \ ++ printk args; \ ++ } while (0) ++#define DMA_TRACE(args) \ ++ do { \ ++ if (!(*di->msg_level & 2)) \ ++ ; \ ++ else \ ++ printk args; \ ++ } while (0) ++#else ++#define DMA_ERROR(args) ++#define DMA_TRACE(args) ++#endif /* BCMDBG */ ++ ++#define DMA_NONE(args) ++ ++#define MAXNAMEL 8 /* 8 char names */ ++ ++/* macros to convert between byte offsets and indexes */ ++#define B2I(bytes, type) ((bytes) / sizeof(type)) ++#define I2B(index, type) ((index) * sizeof(type)) ++ ++#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */ ++#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */ ++ ++#define PCI64ADDR_HIGH 0x80000000 /* address[63] */ ++#define PCI64ADDR_HIGH_SHIFT 31 /* address[63] */ ++ ++/* ++ * DMA Descriptor ++ * Descriptors are only read by the hardware, never written back. ++ */ ++struct dma64desc { ++ __le32 ctrl1; /* misc control bits & bufcount */ ++ __le32 ctrl2; /* buffer count and address extension */ ++ __le32 addrlow; /* memory address of the date buffer, bits 31:0 */ ++ __le32 addrhigh; /* memory address of the date buffer, bits 63:32 */ ++}; ++ ++/* dma engine software state */ ++struct dma_info { ++ struct dma_pub dma; /* exported structure */ ++ uint *msg_level; /* message level pointer */ ++ char name[MAXNAMEL]; /* callers name for diag msgs */ ++ ++ struct pci_dev *pbus; /* bus handle */ ++ ++ bool dma64; /* this dma engine is operating in 64-bit mode */ ++ bool addrext; /* this dma engine supports DmaExtendedAddrChanges */ ++ ++ /* 64-bit dma tx engine registers */ ++ struct dma64regs __iomem *d64txregs; ++ /* 64-bit dma rx engine registers */ ++ struct dma64regs __iomem *d64rxregs; ++ /* pointer to dma64 tx descriptor ring */ ++ struct dma64desc *txd64; ++ /* pointer to dma64 rx descriptor ring */ ++ struct dma64desc *rxd64; ++ ++ u16 dmadesc_align; /* alignment requirement for dma descriptors */ ++ ++ u16 ntxd; /* # tx descriptors tunable */ ++ u16 txin; /* index of next descriptor to reclaim */ ++ u16 txout; /* index of next descriptor to post */ ++ /* pointer to parallel array of pointers to packets */ ++ struct sk_buff **txp; ++ /* Aligned physical address of descriptor ring */ ++ dma_addr_t txdpa; ++ /* Original physical address of descriptor ring */ ++ dma_addr_t txdpaorig; ++ u16 txdalign; /* #bytes added to alloc'd mem to align txd */ ++ u32 txdalloc; /* #bytes allocated for the ring */ ++ u32 xmtptrbase; /* When using unaligned descriptors, the ptr register ++ * is not just an index, it needs all 13 bits to be ++ * an offset from the addr register. ++ */ ++ ++ u16 nrxd; /* # rx descriptors tunable */ ++ u16 rxin; /* index of next descriptor to reclaim */ ++ u16 rxout; /* index of next descriptor to post */ ++ /* pointer to parallel array of pointers to packets */ ++ struct sk_buff **rxp; ++ /* Aligned physical address of descriptor ring */ ++ dma_addr_t rxdpa; ++ /* Original physical address of descriptor ring */ ++ dma_addr_t rxdpaorig; ++ u16 rxdalign; /* #bytes added to alloc'd mem to align rxd */ ++ u32 rxdalloc; /* #bytes allocated for the ring */ ++ u32 rcvptrbase; /* Base for ptr reg when using unaligned descriptors */ ++ ++ /* tunables */ ++ unsigned int rxbufsize; /* rx buffer size in bytes, not including ++ * the extra headroom ++ */ ++ uint rxextrahdrroom; /* extra rx headroom, reverseved to assist upper ++ * stack, e.g. some rx pkt buffers will be ++ * bridged to tx side without byte copying. ++ * The extra headroom needs to be large enough ++ * to fit txheader needs. Some dongle driver may ++ * not need it. ++ */ ++ uint nrxpost; /* # rx buffers to keep posted */ ++ unsigned int rxoffset; /* rxcontrol offset */ ++ /* add to get dma address of descriptor ring, low 32 bits */ ++ uint ddoffsetlow; ++ /* high 32 bits */ ++ uint ddoffsethigh; ++ /* add to get dma address of data buffer, low 32 bits */ ++ uint dataoffsetlow; ++ /* high 32 bits */ ++ uint dataoffsethigh; ++ /* descriptor base need to be aligned or not */ ++ bool aligndesc_4k; ++}; ++ ++/* ++ * default dma message level (if input msg_level ++ * pointer is null in dma_attach()) ++ */ ++static uint dma_msg_level; ++ ++/* Check for odd number of 1's */ ++static u32 parity32(__le32 data) ++{ ++ /* no swap needed for counting 1's */ ++ u32 par_data = *(u32 *)&data; ++ ++ par_data ^= par_data >> 16; ++ par_data ^= par_data >> 8; ++ par_data ^= par_data >> 4; ++ par_data ^= par_data >> 2; ++ par_data ^= par_data >> 1; ++ ++ return par_data & 1; ++} ++ ++static bool dma64_dd_parity(struct dma64desc *dd) ++{ ++ return parity32(dd->addrlow ^ dd->addrhigh ^ dd->ctrl1 ^ dd->ctrl2); ++} ++ ++/* descriptor bumping functions */ ++ ++static uint xxd(uint x, uint n) ++{ ++ return x & (n - 1); /* faster than %, but n must be power of 2 */ ++} ++ ++static uint txd(struct dma_info *di, uint x) ++{ ++ return xxd(x, di->ntxd); ++} ++ ++static uint rxd(struct dma_info *di, uint x) ++{ ++ return xxd(x, di->nrxd); ++} ++ ++static uint nexttxd(struct dma_info *di, uint i) ++{ ++ return txd(di, i + 1); ++} ++ ++static uint prevtxd(struct dma_info *di, uint i) ++{ ++ return txd(di, i - 1); ++} ++ ++static uint nextrxd(struct dma_info *di, uint i) ++{ ++ return txd(di, i + 1); ++} ++ ++static uint ntxdactive(struct dma_info *di, uint h, uint t) ++{ ++ return txd(di, t-h); ++} ++ ++static uint nrxdactive(struct dma_info *di, uint h, uint t) ++{ ++ return rxd(di, t-h); ++} ++ ++static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags) ++{ ++ uint dmactrlflags = di->dma.dmactrlflags; ++ ++ if (di == NULL) { ++ DMA_ERROR(("%s: _dma_ctrlflags: NULL dma handle\n", di->name)); ++ return 0; ++ } ++ ++ dmactrlflags &= ~mask; ++ dmactrlflags |= flags; ++ ++ /* If trying to enable parity, check if parity is actually supported */ ++ if (dmactrlflags & DMA_CTRL_PEN) { ++ u32 control; ++ ++ control = R_REG(&di->d64txregs->control); ++ W_REG(&di->d64txregs->control, ++ control | D64_XC_PD); ++ if (R_REG(&di->d64txregs->control) & D64_XC_PD) ++ /* We *can* disable it so it is supported, ++ * restore control register ++ */ ++ W_REG(&di->d64txregs->control, ++ control); ++ else ++ /* Not supported, don't allow it to be enabled */ ++ dmactrlflags &= ~DMA_CTRL_PEN; ++ } ++ ++ di->dma.dmactrlflags = dmactrlflags; ++ ++ return dmactrlflags; ++} ++ ++static bool _dma64_addrext(struct dma64regs __iomem *dma64regs) ++{ ++ u32 w; ++ OR_REG(&dma64regs->control, D64_XC_AE); ++ w = R_REG(&dma64regs->control); ++ AND_REG(&dma64regs->control, ~D64_XC_AE); ++ return (w & D64_XC_AE) == D64_XC_AE; ++} ++ ++/* ++ * return true if this dma engine supports DmaExtendedAddrChanges, ++ * otherwise false ++ */ ++static bool _dma_isaddrext(struct dma_info *di) ++{ ++ /* DMA64 supports full 32- or 64-bit operation. AE is always valid */ ++ ++ /* not all tx or rx channel are available */ ++ if (di->d64txregs != NULL) { ++ if (!_dma64_addrext(di->d64txregs)) ++ DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have " ++ "AE set\n", di->name)); ++ return true; ++ } else if (di->d64rxregs != NULL) { ++ if (!_dma64_addrext(di->d64rxregs)) ++ DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have " ++ "AE set\n", di->name)); ++ return true; ++ } ++ ++ return false; ++} ++ ++static bool _dma_descriptor_align(struct dma_info *di) ++{ ++ u32 addrl; ++ ++ /* Check to see if the descriptors need to be aligned on 4K/8K or not */ ++ if (di->d64txregs != NULL) { ++ W_REG(&di->d64txregs->addrlow, 0xff0); ++ addrl = R_REG(&di->d64txregs->addrlow); ++ if (addrl != 0) ++ return false; ++ } else if (di->d64rxregs != NULL) { ++ W_REG(&di->d64rxregs->addrlow, 0xff0); ++ addrl = R_REG(&di->d64rxregs->addrlow); ++ if (addrl != 0) ++ return false; ++ } ++ return true; ++} ++ ++/* ++ * Descriptor table must start at the DMA hardware dictated alignment, so ++ * allocated memory must be large enough to support this requirement. ++ */ ++static void *dma_alloc_consistent(struct pci_dev *pdev, uint size, ++ u16 align_bits, uint *alloced, ++ dma_addr_t *pap) ++{ ++ if (align_bits) { ++ u16 align = (1 << align_bits); ++ if (!IS_ALIGNED(PAGE_SIZE, align)) ++ size += align; ++ *alloced = size; ++ } ++ return pci_alloc_consistent(pdev, size, pap); ++} ++ ++static ++u8 dma_align_sizetobits(uint size) ++{ ++ u8 bitpos = 0; ++ while (size >>= 1) ++ bitpos++; ++ return bitpos; ++} ++ ++/* This function ensures that the DMA descriptor ring will not get allocated ++ * across Page boundary. If the allocation is done across the page boundary ++ * at the first time, then it is freed and the allocation is done at ++ * descriptor ring size aligned location. This will ensure that the ring will ++ * not cross page boundary ++ */ ++static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size, ++ u16 *alignbits, uint *alloced, ++ dma_addr_t *descpa) ++{ ++ void *va; ++ u32 desc_strtaddr; ++ u32 alignbytes = 1 << *alignbits; ++ ++ va = dma_alloc_consistent(di->pbus, size, *alignbits, alloced, descpa); ++ ++ if (NULL == va) ++ return NULL; ++ ++ desc_strtaddr = (u32) roundup((unsigned long)va, alignbytes); ++ if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr ++ & boundary)) { ++ *alignbits = dma_align_sizetobits(size); ++ pci_free_consistent(di->pbus, size, va, *descpa); ++ va = dma_alloc_consistent(di->pbus, size, *alignbits, ++ alloced, descpa); ++ } ++ return va; ++} ++ ++static bool dma64_alloc(struct dma_info *di, uint direction) ++{ ++ u16 size; ++ uint ddlen; ++ void *va; ++ uint alloced = 0; ++ u16 align; ++ u16 align_bits; ++ ++ ddlen = sizeof(struct dma64desc); ++ ++ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); ++ align_bits = di->dmadesc_align; ++ align = (1 << align_bits); ++ ++ if (direction == DMA_TX) { ++ va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits, ++ &alloced, &di->txdpaorig); ++ if (va == NULL) { ++ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd)" ++ " failed\n", di->name)); ++ return false; ++ } ++ align = (1 << align_bits); ++ di->txd64 = (struct dma64desc *) ++ roundup((unsigned long)va, align); ++ di->txdalign = (uint) ((s8 *)di->txd64 - (s8 *) va); ++ di->txdpa = di->txdpaorig + di->txdalign; ++ di->txdalloc = alloced; ++ } else { ++ va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits, ++ &alloced, &di->rxdpaorig); ++ if (va == NULL) { ++ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd)" ++ " failed\n", di->name)); ++ return false; ++ } ++ align = (1 << align_bits); ++ di->rxd64 = (struct dma64desc *) ++ roundup((unsigned long)va, align); ++ di->rxdalign = (uint) ((s8 *)di->rxd64 - (s8 *) va); ++ di->rxdpa = di->rxdpaorig + di->rxdalign; ++ di->rxdalloc = alloced; ++ } ++ ++ return true; ++} ++ ++static bool _dma_alloc(struct dma_info *di, uint direction) ++{ ++ return dma64_alloc(di, direction); ++} ++ ++struct dma_pub *dma_attach(char *name, struct si_pub *sih, ++ void __iomem *dmaregstx, void __iomem *dmaregsrx, ++ uint ntxd, uint nrxd, ++ uint rxbufsize, int rxextheadroom, ++ uint nrxpost, uint rxoffset, uint *msg_level) ++{ ++ struct dma_info *di; ++ uint size; ++ ++ /* allocate private info structure */ ++ di = kzalloc(sizeof(struct dma_info), GFP_ATOMIC); ++ if (di == NULL) ++ return NULL; ++ ++ di->msg_level = msg_level ? msg_level : &dma_msg_level; ++ ++ ++ di->dma64 = ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64); ++ ++ /* init dma reg pointer */ ++ di->d64txregs = (struct dma64regs __iomem *) dmaregstx; ++ di->d64rxregs = (struct dma64regs __iomem *) dmaregsrx; ++ ++ /* ++ * Default flags (which can be changed by the driver calling ++ * dma_ctrlflags before enable): For backwards compatibility ++ * both Rx Overflow Continue and Parity are DISABLED. ++ */ ++ _dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0); ++ ++ DMA_TRACE(("%s: dma_attach: %s flags 0x%x ntxd %d nrxd %d " ++ "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d " ++ "dmaregstx %p dmaregsrx %p\n", name, "DMA64", ++ di->dma.dmactrlflags, ntxd, nrxd, rxbufsize, ++ rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx)); ++ ++ /* make a private copy of our callers name */ ++ strncpy(di->name, name, MAXNAMEL); ++ di->name[MAXNAMEL - 1] = '\0'; ++ ++ di->pbus = ((struct si_info *)sih)->pbus; ++ ++ /* save tunables */ ++ di->ntxd = (u16) ntxd; ++ di->nrxd = (u16) nrxd; ++ ++ /* the actual dma size doesn't include the extra headroom */ ++ di->rxextrahdrroom = ++ (rxextheadroom == -1) ? BCMEXTRAHDROOM : rxextheadroom; ++ if (rxbufsize > BCMEXTRAHDROOM) ++ di->rxbufsize = (u16) (rxbufsize - di->rxextrahdrroom); ++ else ++ di->rxbufsize = (u16) rxbufsize; ++ ++ di->nrxpost = (u16) nrxpost; ++ di->rxoffset = (u8) rxoffset; ++ ++ /* ++ * figure out the DMA physical address offset for dd and data ++ * PCI/PCIE: they map silicon backplace address to zero ++ * based memory, need offset ++ * Other bus: use zero SI_BUS BIGENDIAN kludge: use sdram ++ * swapped region for data buffer, not descriptor ++ */ ++ di->ddoffsetlow = 0; ++ di->dataoffsetlow = 0; ++ /* add offset for pcie with DMA64 bus */ ++ di->ddoffsetlow = 0; ++ di->ddoffsethigh = SI_PCIE_DMA_H32; ++ di->dataoffsetlow = di->ddoffsetlow; ++ di->dataoffsethigh = di->ddoffsethigh; ++ /* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */ ++ if ((ai_coreid(sih) == SDIOD_CORE_ID) ++ && ((ai_corerev(sih) > 0) && (ai_corerev(sih) <= 2))) ++ di->addrext = 0; ++ else if ((ai_coreid(sih) == I2S_CORE_ID) && ++ ((ai_corerev(sih) == 0) || (ai_corerev(sih) == 1))) ++ di->addrext = 0; ++ else ++ di->addrext = _dma_isaddrext(di); ++ ++ /* does the descriptor need to be aligned and if yes, on 4K/8K or not */ ++ di->aligndesc_4k = _dma_descriptor_align(di); ++ if (di->aligndesc_4k) { ++ di->dmadesc_align = D64RINGALIGN_BITS; ++ if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) ++ /* for smaller dd table, HW relax alignment reqmnt */ ++ di->dmadesc_align = D64RINGALIGN_BITS - 1; ++ } else { ++ di->dmadesc_align = 4; /* 16 byte alignment */ ++ } ++ ++ DMA_NONE(("DMA descriptor align_needed %d, align %d\n", ++ di->aligndesc_4k, di->dmadesc_align)); ++ ++ /* allocate tx packet pointer vector */ ++ if (ntxd) { ++ size = ntxd * sizeof(void *); ++ di->txp = kzalloc(size, GFP_ATOMIC); ++ if (di->txp == NULL) ++ goto fail; ++ } ++ ++ /* allocate rx packet pointer vector */ ++ if (nrxd) { ++ size = nrxd * sizeof(void *); ++ di->rxp = kzalloc(size, GFP_ATOMIC); ++ if (di->rxp == NULL) ++ goto fail; ++ } ++ ++ /* ++ * allocate transmit descriptor ring, only need ntxd descriptors ++ * but it must be aligned ++ */ ++ if (ntxd) { ++ if (!_dma_alloc(di, DMA_TX)) ++ goto fail; ++ } ++ ++ /* ++ * allocate receive descriptor ring, only need nrxd descriptors ++ * but it must be aligned ++ */ ++ if (nrxd) { ++ if (!_dma_alloc(di, DMA_RX)) ++ goto fail; ++ } ++ ++ if ((di->ddoffsetlow != 0) && !di->addrext) { ++ if (di->txdpa > SI_PCI_DMA_SZ) { ++ DMA_ERROR(("%s: dma_attach: txdpa 0x%x: addrext not " ++ "supported\n", di->name, (u32)di->txdpa)); ++ goto fail; ++ } ++ if (di->rxdpa > SI_PCI_DMA_SZ) { ++ DMA_ERROR(("%s: dma_attach: rxdpa 0x%x: addrext not " ++ "supported\n", di->name, (u32)di->rxdpa)); ++ goto fail; ++ } ++ } ++ ++ DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x " ++ "dataoffsethigh " "0x%x addrext %d\n", di->ddoffsetlow, ++ di->ddoffsethigh, di->dataoffsetlow, di->dataoffsethigh, ++ di->addrext)); ++ ++ return (struct dma_pub *) di; ++ ++ fail: ++ dma_detach((struct dma_pub *)di); ++ return NULL; ++} ++ ++static inline void ++dma64_dd_upd(struct dma_info *di, struct dma64desc *ddring, ++ dma_addr_t pa, uint outidx, u32 *flags, u32 bufcount) ++{ ++ u32 ctrl2 = bufcount & D64_CTRL2_BC_MASK; ++ ++ /* PCI bus with big(>1G) physical address, use address extension */ ++ if ((di->dataoffsetlow == 0) || !(pa & PCI32ADDR_HIGH)) { ++ ddring[outidx].addrlow = cpu_to_le32(pa + di->dataoffsetlow); ++ ddring[outidx].addrhigh = cpu_to_le32(di->dataoffsethigh); ++ ddring[outidx].ctrl1 = cpu_to_le32(*flags); ++ ddring[outidx].ctrl2 = cpu_to_le32(ctrl2); ++ } else { ++ /* address extension for 32-bit PCI */ ++ u32 ae; ++ ++ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ pa &= ~PCI32ADDR_HIGH; ++ ++ ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE; ++ ddring[outidx].addrlow = cpu_to_le32(pa + di->dataoffsetlow); ++ ddring[outidx].addrhigh = cpu_to_le32(di->dataoffsethigh); ++ ddring[outidx].ctrl1 = cpu_to_le32(*flags); ++ ddring[outidx].ctrl2 = cpu_to_le32(ctrl2); ++ } ++ if (di->dma.dmactrlflags & DMA_CTRL_PEN) { ++ if (dma64_dd_parity(&ddring[outidx])) ++ ddring[outidx].ctrl2 = ++ cpu_to_le32(ctrl2 | D64_CTRL2_PARITY); ++ } ++} ++ ++/* !! may be called with core in reset */ ++void dma_detach(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ ++ DMA_TRACE(("%s: dma_detach\n", di->name)); ++ ++ /* free dma descriptor rings */ ++ if (di->txd64) ++ pci_free_consistent(di->pbus, di->txdalloc, ++ ((s8 *)di->txd64 - di->txdalign), ++ (di->txdpaorig)); ++ if (di->rxd64) ++ pci_free_consistent(di->pbus, di->rxdalloc, ++ ((s8 *)di->rxd64 - di->rxdalign), ++ (di->rxdpaorig)); ++ ++ /* free packet pointer vectors */ ++ kfree(di->txp); ++ kfree(di->rxp); ++ ++ /* free our private info structure */ ++ kfree(di); ++ ++} ++ ++/* initialize descriptor table base address */ ++static void ++_dma_ddtable_init(struct dma_info *di, uint direction, dma_addr_t pa) ++{ ++ if (!di->aligndesc_4k) { ++ if (direction == DMA_TX) ++ di->xmtptrbase = pa; ++ else ++ di->rcvptrbase = pa; ++ } ++ ++ if ((di->ddoffsetlow == 0) ++ || !(pa & PCI32ADDR_HIGH)) { ++ if (direction == DMA_TX) { ++ W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow); ++ W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh); ++ } else { ++ W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow); ++ W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh); ++ } ++ } else { ++ /* DMA64 32bits address extension */ ++ u32 ae; ++ ++ /* shift the high bit(s) from pa to ae */ ++ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ pa &= ~PCI32ADDR_HIGH; ++ ++ if (direction == DMA_TX) { ++ W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow); ++ W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh); ++ SET_REG(&di->d64txregs->control, ++ D64_XC_AE, (ae << D64_XC_AE_SHIFT)); ++ } else { ++ W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow); ++ W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh); ++ SET_REG(&di->d64rxregs->control, ++ D64_RC_AE, (ae << D64_RC_AE_SHIFT)); ++ } ++ } ++} ++ ++static void _dma_rxenable(struct dma_info *di) ++{ ++ uint dmactrlflags = di->dma.dmactrlflags; ++ u32 control; ++ ++ DMA_TRACE(("%s: dma_rxenable\n", di->name)); ++ ++ control = ++ (R_REG(&di->d64rxregs->control) & D64_RC_AE) | ++ D64_RC_RE; ++ ++ if ((dmactrlflags & DMA_CTRL_PEN) == 0) ++ control |= D64_RC_PD; ++ ++ if (dmactrlflags & DMA_CTRL_ROC) ++ control |= D64_RC_OC; ++ ++ W_REG(&di->d64rxregs->control, ++ ((di->rxoffset << D64_RC_RO_SHIFT) | control)); ++} ++ ++void dma_rxinit(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ ++ DMA_TRACE(("%s: dma_rxinit\n", di->name)); ++ ++ if (di->nrxd == 0) ++ return; ++ ++ di->rxin = di->rxout = 0; ++ ++ /* clear rx descriptor ring */ ++ memset(di->rxd64, '\0', di->nrxd * sizeof(struct dma64desc)); ++ ++ /* DMA engine with out alignment requirement requires table to be inited ++ * before enabling the engine ++ */ ++ if (!di->aligndesc_4k) ++ _dma_ddtable_init(di, DMA_RX, di->rxdpa); ++ ++ _dma_rxenable(di); ++ ++ if (di->aligndesc_4k) ++ _dma_ddtable_init(di, DMA_RX, di->rxdpa); ++} ++ ++static struct sk_buff *dma64_getnextrxp(struct dma_info *di, bool forceall) ++{ ++ uint i, curr; ++ struct sk_buff *rxp; ++ dma_addr_t pa; ++ ++ i = di->rxin; ++ ++ /* return if no packets posted */ ++ if (i == di->rxout) ++ return NULL; ++ ++ curr = ++ B2I(((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, struct dma64desc); ++ ++ /* ignore curr if forceall */ ++ if (!forceall && (i == curr)) ++ return NULL; ++ ++ /* get the packet pointer that corresponds to the rx descriptor */ ++ rxp = di->rxp[i]; ++ di->rxp[i] = NULL; ++ ++ pa = le32_to_cpu(di->rxd64[i].addrlow) - di->dataoffsetlow; ++ ++ /* clear this packet from the descriptor ring */ ++ pci_unmap_single(di->pbus, pa, di->rxbufsize, PCI_DMA_FROMDEVICE); ++ ++ di->rxd64[i].addrlow = cpu_to_le32(0xdeadbeef); ++ di->rxd64[i].addrhigh = cpu_to_le32(0xdeadbeef); ++ ++ di->rxin = nextrxd(di, i); ++ ++ return rxp; ++} ++ ++static struct sk_buff *_dma_getnextrxp(struct dma_info *di, bool forceall) ++{ ++ if (di->nrxd == 0) ++ return NULL; ++ ++ return dma64_getnextrxp(di, forceall); ++} ++ ++/* ++ * !! rx entry routine ++ * returns a pointer to the next frame received, or NULL if there are no more ++ * if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is ++ * supported with pkts chain ++ * otherwise, it's treated as giant pkt and will be tossed. ++ * The DMA scattering starts with normal DMA header, followed by first ++ * buffer data. After it reaches the max size of buffer, the data continues ++ * in next DMA descriptor buffer WITHOUT DMA header ++ */ ++struct sk_buff *dma_rx(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ struct sk_buff *p, *head, *tail; ++ uint len; ++ uint pkt_len; ++ int resid = 0; ++ ++ next_frame: ++ head = _dma_getnextrxp(di, false); ++ if (head == NULL) ++ return NULL; ++ ++ len = le16_to_cpu(*(__le16 *) (head->data)); ++ DMA_TRACE(("%s: dma_rx len %d\n", di->name, len)); ++ dma_spin_for_len(len, head); ++ ++ /* set actual length */ ++ pkt_len = min((di->rxoffset + len), di->rxbufsize); ++ __skb_trim(head, pkt_len); ++ resid = len - (di->rxbufsize - di->rxoffset); ++ ++ /* check for single or multi-buffer rx */ ++ if (resid > 0) { ++ tail = head; ++ while ((resid > 0) && (p = _dma_getnextrxp(di, false))) { ++ tail->next = p; ++ pkt_len = min_t(uint, resid, di->rxbufsize); ++ __skb_trim(p, pkt_len); ++ ++ tail = p; ++ resid -= di->rxbufsize; ++ } ++ ++#ifdef BCMDBG ++ if (resid > 0) { ++ uint cur; ++ cur = ++ B2I(((R_REG(&di->d64rxregs->status0) & ++ D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, ++ struct dma64desc); ++ DMA_ERROR(("dma_rx, rxin %d rxout %d, hw_curr %d\n", ++ di->rxin, di->rxout, cur)); ++ } ++#endif /* BCMDBG */ ++ ++ if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) { ++ DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n", ++ di->name, len)); ++ brcmu_pkt_buf_free_skb(head); ++ di->dma.rxgiants++; ++ goto next_frame; ++ } ++ } ++ ++ return head; ++} ++ ++static bool dma64_rxidle(struct dma_info *di) ++{ ++ DMA_TRACE(("%s: dma_rxidle\n", di->name)); ++ ++ if (di->nrxd == 0) ++ return true; ++ ++ return ((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) == ++ (R_REG(&di->d64rxregs->ptr) & D64_RS0_CD_MASK)); ++} ++ ++/* ++ * post receive buffers ++ * return false is refill failed completely and ring is empty this will stall ++ * the rx dma and user might want to call rxfill again asap. This unlikely ++ * happens on memory-rich NIC, but often on memory-constrained dongle ++ */ ++bool dma_rxfill(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ struct sk_buff *p; ++ u16 rxin, rxout; ++ u32 flags = 0; ++ uint n; ++ uint i; ++ dma_addr_t pa; ++ uint extra_offset = 0; ++ bool ring_empty; ++ ++ ring_empty = false; ++ ++ /* ++ * Determine how many receive buffers we're lacking ++ * from the full complement, allocate, initialize, ++ * and post them, then update the chip rx lastdscr. ++ */ ++ ++ rxin = di->rxin; ++ rxout = di->rxout; ++ ++ n = di->nrxpost - nrxdactive(di, rxin, rxout); ++ ++ DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n)); ++ ++ if (di->rxbufsize > BCMEXTRAHDROOM) ++ extra_offset = di->rxextrahdrroom; ++ ++ for (i = 0; i < n; i++) { ++ /* ++ * the di->rxbufsize doesn't include the extra headroom, ++ * we need to add it to the size to be allocated ++ */ ++ p = brcmu_pkt_buf_get_skb(di->rxbufsize + extra_offset); ++ ++ if (p == NULL) { ++ DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n", ++ di->name)); ++ if (i == 0 && dma64_rxidle(di)) { ++ DMA_ERROR(("%s: rxfill64: ring is empty !\n", ++ di->name)); ++ ring_empty = true; ++ } ++ di->dma.rxnobuf++; ++ break; ++ } ++ /* reserve an extra headroom, if applicable */ ++ if (extra_offset) ++ skb_pull(p, extra_offset); ++ ++ /* Do a cached write instead of uncached write since DMA_MAP ++ * will flush the cache. ++ */ ++ *(u32 *) (p->data) = 0; ++ ++ pa = pci_map_single(di->pbus, p->data, ++ di->rxbufsize, PCI_DMA_FROMDEVICE); ++ ++ /* save the free packet pointer */ ++ di->rxp[rxout] = p; ++ ++ /* reset flags for each descriptor */ ++ flags = 0; ++ if (rxout == (di->nrxd - 1)) ++ flags = D64_CTRL1_EOT; ++ ++ dma64_dd_upd(di, di->rxd64, pa, rxout, &flags, ++ di->rxbufsize); ++ rxout = nextrxd(di, rxout); ++ } ++ ++ di->rxout = rxout; ++ ++ /* update the chip lastdscr pointer */ ++ W_REG(&di->d64rxregs->ptr, ++ di->rcvptrbase + I2B(rxout, struct dma64desc)); ++ ++ return ring_empty; ++} ++ ++void dma_rxreclaim(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ struct sk_buff *p; ++ ++ DMA_TRACE(("%s: dma_rxreclaim\n", di->name)); ++ ++ while ((p = _dma_getnextrxp(di, true))) ++ brcmu_pkt_buf_free_skb(p); ++} ++ ++void dma_counterreset(struct dma_pub *pub) ++{ ++ /* reset all software counters */ ++ pub->rxgiants = 0; ++ pub->rxnobuf = 0; ++ pub->txnobuf = 0; ++} ++ ++/* get the address of the var in order to change later */ ++unsigned long dma_getvar(struct dma_pub *pub, const char *name) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ ++ if (!strcmp(name, "&txavail")) ++ return (unsigned long)&(di->dma.txavail); ++ return 0; ++} ++ ++/* 64-bit DMA functions */ ++ ++void dma_txinit(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ u32 control = D64_XC_XE; ++ ++ DMA_TRACE(("%s: dma_txinit\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ di->txin = di->txout = 0; ++ di->dma.txavail = di->ntxd - 1; ++ ++ /* clear tx descriptor ring */ ++ memset(di->txd64, '\0', (di->ntxd * sizeof(struct dma64desc))); ++ ++ /* DMA engine with out alignment requirement requires table to be inited ++ * before enabling the engine ++ */ ++ if (!di->aligndesc_4k) ++ _dma_ddtable_init(di, DMA_TX, di->txdpa); ++ ++ if ((di->dma.dmactrlflags & DMA_CTRL_PEN) == 0) ++ control |= D64_XC_PD; ++ OR_REG(&di->d64txregs->control, control); ++ ++ /* DMA engine with alignment requirement requires table to be inited ++ * before enabling the engine ++ */ ++ if (di->aligndesc_4k) ++ _dma_ddtable_init(di, DMA_TX, di->txdpa); ++} ++ ++void dma_txsuspend(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ ++ DMA_TRACE(("%s: dma_txsuspend\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ OR_REG(&di->d64txregs->control, D64_XC_SE); ++} ++ ++void dma_txresume(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ ++ DMA_TRACE(("%s: dma_txresume\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ AND_REG(&di->d64txregs->control, ~D64_XC_SE); ++} ++ ++bool dma_txsuspended(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ ++ return (di->ntxd == 0) || ++ ((R_REG(&di->d64txregs->control) & D64_XC_SE) == ++ D64_XC_SE); ++} ++ ++void dma_txreclaim(struct dma_pub *pub, enum txd_range range) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ struct sk_buff *p; ++ ++ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, ++ (range == DMA_RANGE_ALL) ? "all" : ++ ((range == ++ DMA_RANGE_TRANSMITTED) ? "transmitted" : ++ "transferred"))); ++ ++ if (di->txin == di->txout) ++ return; ++ ++ while ((p = dma_getnexttxp(pub, range))) { ++ /* For unframed data, we don't have any packets to free */ ++ if (!(di->dma.dmactrlflags & DMA_CTRL_UNFRAMED)) ++ brcmu_pkt_buf_free_skb(p); ++ } ++} ++ ++bool dma_txreset(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ u32 status; ++ ++ if (di->ntxd == 0) ++ return true; ++ ++ /* suspend tx DMA first */ ++ W_REG(&di->d64txregs->control, D64_XC_SE); ++ SPINWAIT(((status = ++ (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK)) ++ != D64_XS0_XS_DISABLED) && (status != D64_XS0_XS_IDLE) ++ && (status != D64_XS0_XS_STOPPED), 10000); ++ ++ W_REG(&di->d64txregs->control, 0); ++ SPINWAIT(((status = ++ (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK)) ++ != D64_XS0_XS_DISABLED), 10000); ++ ++ /* wait for the last transaction to complete */ ++ udelay(300); ++ ++ return status == D64_XS0_XS_DISABLED; ++} ++ ++bool dma_rxreset(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ u32 status; ++ ++ if (di->nrxd == 0) ++ return true; ++ ++ W_REG(&di->d64rxregs->control, 0); ++ SPINWAIT(((status = ++ (R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK)) ++ != D64_RS0_RS_DISABLED), 10000); ++ ++ return status == D64_RS0_RS_DISABLED; ++} ++ ++/* ++ * !! tx entry routine ++ * WARNING: call must check the return value for error. ++ * the error(toss frames) could be fatal and cause many subsequent hard ++ * to debug problems ++ */ ++int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ struct sk_buff *p, *next; ++ unsigned char *data; ++ uint len; ++ u16 txout; ++ u32 flags = 0; ++ dma_addr_t pa; ++ ++ DMA_TRACE(("%s: dma_txfast\n", di->name)); ++ ++ txout = di->txout; ++ ++ /* ++ * Walk the chain of packet buffers ++ * allocating and initializing transmit descriptor entries. ++ */ ++ for (p = p0; p; p = next) { ++ data = p->data; ++ len = p->len; ++ next = p->next; ++ ++ /* return nonzero if out of tx descriptors */ ++ if (nexttxd(di, txout) == di->txin) ++ goto outoftxd; ++ ++ if (len == 0) ++ continue; ++ ++ /* get physical address of buffer start */ ++ pa = pci_map_single(di->pbus, data, len, PCI_DMA_TODEVICE); ++ ++ flags = 0; ++ if (p == p0) ++ flags |= D64_CTRL1_SOF; ++ ++ /* With a DMA segment list, Descriptor table is filled ++ * using the segment list instead of looping over ++ * buffers in multi-chain DMA. Therefore, EOF for SGLIST ++ * is when end of segment list is reached. ++ */ ++ if (next == NULL) ++ flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF); ++ if (txout == (di->ntxd - 1)) ++ flags |= D64_CTRL1_EOT; ++ ++ dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); ++ ++ txout = nexttxd(di, txout); ++ } ++ ++ /* if last txd eof not set, fix it */ ++ if (!(flags & D64_CTRL1_EOF)) ++ di->txd64[prevtxd(di, txout)].ctrl1 = ++ cpu_to_le32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF); ++ ++ /* save the packet */ ++ di->txp[prevtxd(di, txout)] = p0; ++ ++ /* bump the tx descriptor index */ ++ di->txout = txout; ++ ++ /* kick the chip */ ++ if (commit) ++ W_REG(&di->d64txregs->ptr, ++ di->xmtptrbase + I2B(txout, struct dma64desc)); ++ ++ /* tx flow control */ ++ di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1; ++ ++ return 0; ++ ++ outoftxd: ++ DMA_ERROR(("%s: dma_txfast: out of txds !!!\n", di->name)); ++ brcmu_pkt_buf_free_skb(p0); ++ di->dma.txavail = 0; ++ di->dma.txnobuf++; ++ return -1; ++} ++ ++/* ++ * Reclaim next completed txd (txds if using chained buffers) in the range ++ * specified and return associated packet. ++ * If range is DMA_RANGE_TRANSMITTED, reclaim descriptors that have be ++ * transmitted as noted by the hardware "CurrDescr" pointer. ++ * If range is DMA_RANGE_TRANSFERED, reclaim descriptors that have be ++ * transferred by the DMA as noted by the hardware "ActiveDescr" pointer. ++ * If range is DMA_RANGE_ALL, reclaim all txd(s) posted to the ring and ++ * return associated packet regardless of the value of hardware pointers. ++ */ ++struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ u16 start, end, i; ++ u16 active_desc; ++ struct sk_buff *txp; ++ ++ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, ++ (range == DMA_RANGE_ALL) ? "all" : ++ ((range == ++ DMA_RANGE_TRANSMITTED) ? "transmitted" : ++ "transferred"))); ++ ++ if (di->ntxd == 0) ++ return NULL; ++ ++ txp = NULL; ++ ++ start = di->txin; ++ if (range == DMA_RANGE_ALL) ++ end = di->txout; ++ else { ++ struct dma64regs __iomem *dregs = di->d64txregs; ++ ++ end = (u16) (B2I(((R_REG(&dregs->status0) & ++ D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, ++ struct dma64desc)); ++ ++ if (range == DMA_RANGE_TRANSFERED) { ++ active_desc = ++ (u16) (R_REG(&dregs->status1) & ++ D64_XS1_AD_MASK); ++ active_desc = ++ (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK; ++ active_desc = B2I(active_desc, struct dma64desc); ++ if (end != active_desc) ++ end = prevtxd(di, active_desc); ++ } ++ } ++ ++ if ((start == 0) && (end > di->txout)) ++ goto bogus; ++ ++ for (i = start; i != end && !txp; i = nexttxd(di, i)) { ++ dma_addr_t pa; ++ uint size; ++ ++ pa = le32_to_cpu(di->txd64[i].addrlow) - di->dataoffsetlow; ++ ++ size = ++ (le32_to_cpu(di->txd64[i].ctrl2) & ++ D64_CTRL2_BC_MASK); ++ ++ di->txd64[i].addrlow = cpu_to_le32(0xdeadbeef); ++ di->txd64[i].addrhigh = cpu_to_le32(0xdeadbeef); ++ ++ txp = di->txp[i]; ++ di->txp[i] = NULL; ++ ++ pci_unmap_single(di->pbus, pa, size, PCI_DMA_TODEVICE); ++ } ++ ++ di->txin = i; ++ ++ /* tx flow control */ ++ di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1; ++ ++ return txp; ++ ++ bogus: ++ DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d " ++ "force %d\n", start, end, di->txout, forceall)); ++ return NULL; ++} ++ ++/* ++ * Mac80211 initiated actions sometimes require packets in the DMA queue to be ++ * modified. The modified portion of the packet is not under control of the DMA ++ * engine. This function calls a caller-supplied function for each packet in ++ * the caller specified dma chain. ++ */ ++void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc) ++ (void *pkt, void *arg_a), void *arg_a) ++{ ++ struct dma_info *di = (struct dma_info *) dmah; ++ uint i = di->txin; ++ uint end = di->txout; ++ struct sk_buff *skb; ++ struct ieee80211_tx_info *tx_info; ++ ++ while (i != end) { ++ skb = (struct sk_buff *)di->txp[i]; ++ if (skb != NULL) { ++ tx_info = (struct ieee80211_tx_info *)skb->cb; ++ (callback_fnc)(tx_info, arg_a); ++ } ++ i = nexttxd(di, i); ++ } ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.h.orig 2011-11-09 13:46:58.244800645 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.h 2011-11-09 13:47:16.997566205 -0500 +@@ -0,0 +1,120 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_DMA_H_ ++#define _BRCM_DMA_H_ ++ ++#include ++#include "types.h" /* forward structure declarations */ ++ ++/* map/unmap direction */ ++#define DMA_TX 1 /* TX direction for DMA */ ++#define DMA_RX 2 /* RX direction for DMA */ ++ ++/* DMA structure: ++ * support two DMA engines: 32 bits address or 64 bit addressing ++ * basic DMA register set is per channel(transmit or receive) ++ * a pair of channels is defined for convenience ++ */ ++ ++/* 32 bits addressing */ ++ ++struct dma32diag { /* diag access */ ++ u32 fifoaddr; /* diag address */ ++ u32 fifodatalow; /* low 32bits of data */ ++ u32 fifodatahigh; /* high 32bits of data */ ++ u32 pad; /* reserved */ ++}; ++ ++/* 64 bits addressing */ ++ ++/* dma registers per channel(xmt or rcv) */ ++struct dma64regs { ++ u32 control; /* enable, et al */ ++ u32 ptr; /* last descriptor posted to chip */ ++ u32 addrlow; /* desc ring base address low 32-bits (8K aligned) */ ++ u32 addrhigh; /* desc ring base address bits 63:32 (8K aligned) */ ++ u32 status0; /* current descriptor, xmt state */ ++ u32 status1; /* active descriptor, xmt error */ ++}; ++ ++/* range param for dma_getnexttxp() and dma_txreclaim */ ++enum txd_range { ++ DMA_RANGE_ALL = 1, ++ DMA_RANGE_TRANSMITTED, ++ DMA_RANGE_TRANSFERED ++}; ++ ++/* ++ * Exported data structure (read-only) ++ */ ++/* export structure */ ++struct dma_pub { ++ uint txavail; /* # free tx descriptors */ ++ uint dmactrlflags; /* dma control flags */ ++ ++ /* rx error counters */ ++ uint rxgiants; /* rx giant frames */ ++ uint rxnobuf; /* rx out of dma descriptors */ ++ /* tx error counters */ ++ uint txnobuf; /* tx out of dma descriptors */ ++}; ++ ++extern struct dma_pub *dma_attach(char *name, struct si_pub *sih, ++ void __iomem *dmaregstx, void __iomem *dmaregsrx, ++ uint ntxd, uint nrxd, ++ uint rxbufsize, int rxextheadroom, ++ uint nrxpost, uint rxoffset, uint *msg_level); ++ ++void dma_rxinit(struct dma_pub *pub); ++struct sk_buff *dma_rx(struct dma_pub *pub); ++bool dma_rxfill(struct dma_pub *pub); ++bool dma_rxreset(struct dma_pub *pub); ++bool dma_txreset(struct dma_pub *pub); ++void dma_txinit(struct dma_pub *pub); ++int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit); ++void dma_txsuspend(struct dma_pub *pub); ++bool dma_txsuspended(struct dma_pub *pub); ++void dma_txresume(struct dma_pub *pub); ++void dma_txreclaim(struct dma_pub *pub, enum txd_range range); ++void dma_rxreclaim(struct dma_pub *pub); ++void dma_detach(struct dma_pub *pub); ++unsigned long dma_getvar(struct dma_pub *pub, const char *name); ++struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range); ++void dma_counterreset(struct dma_pub *pub); ++ ++void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc) ++ (void *pkt, void *arg_a), void *arg_a); ++ ++/* ++ * DMA(Bug) on bcm47xx chips seems to declare that the packet is ready, but ++ * the packet length is not updated yet (by DMA) on the expected time. ++ * Workaround is to hold processor till DMA updates the length, and stay off ++ * the bus to allow DMA update the length in buffer ++ */ ++static inline void dma_spin_for_len(uint len, struct sk_buff *head) ++{ ++#if defined(CONFIG_BCM47XX) ++ if (!len) { ++ while (!(len = *(u16 *) KSEG1ADDR(head->data))) ++ udelay(1); ++ ++ *(u16 *) (head->data) = cpu_to_le16((u16) len); ++ } ++#endif /* defined(CONFIG_BCM47XX) */ ++} ++ ++#endif /* _BRCM_DMA_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c.orig 2011-11-09 13:46:58.245800633 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c 2011-11-09 13:47:16.998566192 -0500 +@@ -0,0 +1,1697 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#define __UNDEF_NO_VERSION__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "nicpci.h" ++#include "phy/phy_int.h" ++#include "d11.h" ++#include "channel.h" ++#include "scb.h" ++#include "pub.h" ++#include "ucode_loader.h" ++#include "mac80211_if.h" ++#include "main.h" ++ ++#define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ ++ ++/* Flags we support */ ++#define MAC_FILTERS (FIF_PROMISC_IN_BSS | \ ++ FIF_ALLMULTI | \ ++ FIF_FCSFAIL | \ ++ FIF_PLCPFAIL | \ ++ FIF_CONTROL | \ ++ FIF_OTHER_BSS | \ ++ FIF_BCN_PRBRESP_PROMISC) ++ ++#define CHAN2GHZ(channel, freqency, chflags) { \ ++ .band = IEEE80211_BAND_2GHZ, \ ++ .center_freq = (freqency), \ ++ .hw_value = (channel), \ ++ .flags = chflags, \ ++ .max_antenna_gain = 0, \ ++ .max_power = 19, \ ++} ++ ++#define CHAN5GHZ(channel, chflags) { \ ++ .band = IEEE80211_BAND_5GHZ, \ ++ .center_freq = 5000 + 5*(channel), \ ++ .hw_value = (channel), \ ++ .flags = chflags, \ ++ .max_antenna_gain = 0, \ ++ .max_power = 21, \ ++} ++ ++#define RATE(rate100m, _flags) { \ ++ .bitrate = (rate100m), \ ++ .flags = (_flags), \ ++ .hw_value = (rate100m / 5), \ ++} ++ ++struct firmware_hdr { ++ __le32 offset; ++ __le32 len; ++ __le32 idx; ++}; ++ ++static const char * const brcms_firmwares[MAX_FW_IMAGES] = { ++ "brcm/bcm43xx", ++ NULL ++}; ++ ++static int n_adapters_found; ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver."); ++MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards"); ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++/* recognized PCI IDs */ ++static DEFINE_PCI_DEVICE_TABLE(brcms_pci_id_table) = { ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, /* 43225 2G */ ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, /* 43224 DUAL */ ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, /* 4313 DUAL */ ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, /* 43224 Ven */ ++ {0} ++}; ++ ++MODULE_DEVICE_TABLE(pci, brcms_pci_id_table); ++ ++#ifdef BCMDBG ++static int msglevel = 0xdeadbeef; ++module_param(msglevel, int, 0); ++#endif /* BCMDBG */ ++ ++static struct ieee80211_channel brcms_2ghz_chantable[] = { ++ CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN2GHZ(2, 2417, IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN2GHZ(3, 2422, IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN2GHZ(4, 2427, IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN2GHZ(5, 2432, 0), ++ CHAN2GHZ(6, 2437, 0), ++ CHAN2GHZ(7, 2442, 0), ++ CHAN2GHZ(8, 2447, IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN2GHZ(9, 2452, IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN2GHZ(12, 2467, ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN2GHZ(13, 2472, ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN2GHZ(14, 2484, ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) ++}; ++ ++static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = { ++ /* UNII-1 */ ++ CHAN5GHZ(36, IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(40, IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(44, IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS), ++ /* UNII-2 */ ++ CHAN5GHZ(52, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(56, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(60, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(64, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), ++ /* MID */ ++ CHAN5GHZ(100, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(104, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(108, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(112, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(116, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(120, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(124, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(128, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(132, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(136, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(140, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS | ++ IEEE80211_CHAN_NO_HT40MINUS), ++ /* UNII-3 */ ++ CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(153, IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(157, IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(161, IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(165, IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) ++}; ++ ++/* ++ * The rate table is used for both 2.4G and 5G rates. The ++ * latter being a subset as it does not support CCK rates. ++ */ ++static struct ieee80211_rate legacy_ratetable[] = { ++ RATE(10, 0), ++ RATE(20, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATE(55, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATE(110, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATE(60, 0), ++ RATE(90, 0), ++ RATE(120, 0), ++ RATE(180, 0), ++ RATE(240, 0), ++ RATE(360, 0), ++ RATE(480, 0), ++ RATE(540, 0), ++}; ++ ++static const struct ieee80211_supported_band brcms_band_2GHz_nphy_template = { ++ .band = IEEE80211_BAND_2GHZ, ++ .channels = brcms_2ghz_chantable, ++ .n_channels = ARRAY_SIZE(brcms_2ghz_chantable), ++ .bitrates = legacy_ratetable, ++ .n_bitrates = ARRAY_SIZE(legacy_ratetable), ++ .ht_cap = { ++ /* from include/linux/ieee80211.h */ ++ .cap = IEEE80211_HT_CAP_GRN_FLD | ++ IEEE80211_HT_CAP_SGI_20 | ++ IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT, ++ .ht_supported = true, ++ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, ++ .ampdu_density = AMPDU_DEF_MPDU_DENSITY, ++ .mcs = { ++ /* placeholders for now */ ++ .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}, ++ .rx_highest = cpu_to_le16(500), ++ .tx_params = IEEE80211_HT_MCS_TX_DEFINED} ++ } ++}; ++ ++static const struct ieee80211_supported_band brcms_band_5GHz_nphy_template = { ++ .band = IEEE80211_BAND_5GHZ, ++ .channels = brcms_5ghz_nphy_chantable, ++ .n_channels = ARRAY_SIZE(brcms_5ghz_nphy_chantable), ++ .bitrates = legacy_ratetable + BRCMS_LEGACY_5G_RATE_OFFSET, ++ .n_bitrates = ARRAY_SIZE(legacy_ratetable) - ++ BRCMS_LEGACY_5G_RATE_OFFSET, ++ .ht_cap = { ++ .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | ++ IEEE80211_HT_CAP_SGI_40 | ++ IEEE80211_HT_CAP_40MHZ_INTOLERANT, /* No 40 mhz yet */ ++ .ht_supported = true, ++ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, ++ .ampdu_density = AMPDU_DEF_MPDU_DENSITY, ++ .mcs = { ++ /* placeholders for now */ ++ .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}, ++ .rx_highest = cpu_to_le16(500), ++ .tx_params = IEEE80211_HT_MCS_TX_DEFINED} ++ } ++}; ++ ++/* flags the given rate in rateset as requested */ ++static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br) ++{ ++ u32 i; ++ ++ for (i = 0; i < rs->count; i++) { ++ if (rate != (rs->rates[i] & 0x7f)) ++ continue; ++ ++ if (is_br) ++ rs->rates[i] |= BRCMS_RATE_FLAG; ++ else ++ rs->rates[i] &= BRCMS_RATE_MASK; ++ return; ++ } ++} ++ ++static void brcms_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb) ++{ ++ struct brcms_info *wl = hw->priv; ++ ++ spin_lock_bh(&wl->lock); ++ if (!wl->pub->up) { ++ wiphy_err(wl->wiphy, "ops->tx called while down\n"); ++ kfree_skb(skb); ++ goto done; ++ } ++ brcms_c_sendpkt_mac80211(wl->wlc, skb, hw); ++ done: ++ spin_unlock_bh(&wl->lock); ++} ++ ++static int brcms_ops_start(struct ieee80211_hw *hw) ++{ ++ struct brcms_info *wl = hw->priv; ++ bool blocked; ++ ++ ieee80211_wake_queues(hw); ++ spin_lock_bh(&wl->lock); ++ blocked = brcms_rfkill_set_hw_state(wl); ++ spin_unlock_bh(&wl->lock); ++ if (!blocked) ++ wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); ++ ++ return 0; ++} ++ ++static void brcms_ops_stop(struct ieee80211_hw *hw) ++{ ++ ieee80211_stop_queues(hw); ++} ++ ++static int ++brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ++{ ++ struct brcms_info *wl; ++ int err; ++ ++ /* Just STA for now */ ++ if (vif->type != NL80211_IFTYPE_AP && ++ vif->type != NL80211_IFTYPE_MESH_POINT && ++ vif->type != NL80211_IFTYPE_STATION && ++ vif->type != NL80211_IFTYPE_WDS && ++ vif->type != NL80211_IFTYPE_ADHOC) { ++ wiphy_err(hw->wiphy, "%s: Attempt to add type %d, only" ++ " STA for now\n", __func__, vif->type); ++ return -EOPNOTSUPP; ++ } ++ ++ wl = hw->priv; ++ spin_lock_bh(&wl->lock); ++ if (!wl->pub->up) ++ err = brcms_up(wl); ++ else ++ err = -ENODEV; ++ spin_unlock_bh(&wl->lock); ++ ++ if (err != 0) ++ wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__, ++ err); ++ ++ return err; ++} ++ ++static void ++brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ++{ ++ struct brcms_info *wl; ++ ++ wl = hw->priv; ++ ++ /* put driver in down state */ ++ spin_lock_bh(&wl->lock); ++ brcms_down(wl); ++ spin_unlock_bh(&wl->lock); ++} ++ ++static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed) ++{ ++ struct ieee80211_conf *conf = &hw->conf; ++ struct brcms_info *wl = hw->priv; ++ int err = 0; ++ int new_int; ++ struct wiphy *wiphy = hw->wiphy; ++ ++ spin_lock_bh(&wl->lock); ++ if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { ++ brcms_c_set_beacon_listen_interval(wl->wlc, ++ conf->listen_interval); ++ } ++ if (changed & IEEE80211_CONF_CHANGE_MONITOR) ++ wiphy_err(wiphy, "%s: change monitor mode: %s (implement)\n", ++ __func__, conf->flags & IEEE80211_CONF_MONITOR ? ++ "true" : "false"); ++ if (changed & IEEE80211_CONF_CHANGE_PS) ++ wiphy_err(wiphy, "%s: change power-save mode: %s (implement)\n", ++ __func__, conf->flags & IEEE80211_CONF_PS ? ++ "true" : "false"); ++ ++ if (changed & IEEE80211_CONF_CHANGE_POWER) { ++ err = brcms_c_set_tx_power(wl->wlc, conf->power_level); ++ if (err < 0) { ++ wiphy_err(wiphy, "%s: Error setting power_level\n", ++ __func__); ++ goto config_out; ++ } ++ new_int = brcms_c_get_tx_power(wl->wlc); ++ if (new_int != conf->power_level) ++ wiphy_err(wiphy, "%s: Power level req != actual, %d %d" ++ "\n", __func__, conf->power_level, ++ new_int); ++ } ++ if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { ++ if (conf->channel_type == NL80211_CHAN_HT20 || ++ conf->channel_type == NL80211_CHAN_NO_HT) ++ err = brcms_c_set_channel(wl->wlc, ++ conf->channel->hw_value); ++ else ++ err = -ENOTSUPP; ++ } ++ if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) ++ err = brcms_c_set_rate_limit(wl->wlc, ++ conf->short_frame_max_tx_count, ++ conf->long_frame_max_tx_count); ++ ++ config_out: ++ spin_unlock_bh(&wl->lock); ++ return err; ++} ++ ++static void ++brcms_ops_bss_info_changed(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_bss_conf *info, u32 changed) ++{ ++ struct brcms_info *wl = hw->priv; ++ struct wiphy *wiphy = hw->wiphy; ++ ++ if (changed & BSS_CHANGED_ASSOC) { ++ /* association status changed (associated/disassociated) ++ * also implies a change in the AID. ++ */ ++ wiphy_err(wiphy, "%s: %s: %sassociated\n", KBUILD_MODNAME, ++ __func__, info->assoc ? "" : "dis"); ++ spin_lock_bh(&wl->lock); ++ brcms_c_associate_upd(wl->wlc, info->assoc); ++ spin_unlock_bh(&wl->lock); ++ } ++ if (changed & BSS_CHANGED_ERP_SLOT) { ++ s8 val; ++ ++ /* slot timing changed */ ++ if (info->use_short_slot) ++ val = 1; ++ else ++ val = 0; ++ spin_lock_bh(&wl->lock); ++ brcms_c_set_shortslot_override(wl->wlc, val); ++ spin_unlock_bh(&wl->lock); ++ } ++ ++ if (changed & BSS_CHANGED_HT) { ++ /* 802.11n parameters changed */ ++ u16 mode = info->ht_operation_mode; ++ ++ spin_lock_bh(&wl->lock); ++ brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_CFG, ++ mode & IEEE80211_HT_OP_MODE_PROTECTION); ++ brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_NONGF, ++ mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); ++ brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_OBSS, ++ mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT); ++ spin_unlock_bh(&wl->lock); ++ } ++ if (changed & BSS_CHANGED_BASIC_RATES) { ++ struct ieee80211_supported_band *bi; ++ u32 br_mask, i; ++ u16 rate; ++ struct brcm_rateset rs; ++ int error; ++ ++ /* retrieve the current rates */ ++ spin_lock_bh(&wl->lock); ++ brcms_c_get_current_rateset(wl->wlc, &rs); ++ spin_unlock_bh(&wl->lock); ++ ++ br_mask = info->basic_rates; ++ bi = hw->wiphy->bands[brcms_c_get_curband(wl->wlc)]; ++ for (i = 0; i < bi->n_bitrates; i++) { ++ /* convert to internal rate value */ ++ rate = (bi->bitrates[i].bitrate << 1) / 10; ++ ++ /* set/clear basic rate flag */ ++ brcms_set_basic_rate(&rs, rate, br_mask & 1); ++ br_mask >>= 1; ++ } ++ ++ /* update the rate set */ ++ spin_lock_bh(&wl->lock); ++ error = brcms_c_set_rateset(wl->wlc, &rs); ++ spin_unlock_bh(&wl->lock); ++ if (error) ++ wiphy_err(wiphy, "changing basic rates failed: %d\n", ++ error); ++ } ++ if (changed & BSS_CHANGED_BEACON_INT) { ++ /* Beacon interval changed */ ++ spin_lock_bh(&wl->lock); ++ brcms_c_set_beacon_period(wl->wlc, info->beacon_int); ++ spin_unlock_bh(&wl->lock); ++ } ++ if (changed & BSS_CHANGED_BSSID) { ++ /* BSSID changed, for whatever reason (IBSS and managed mode) */ ++ spin_lock_bh(&wl->lock); ++ brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid); ++ spin_unlock_bh(&wl->lock); ++ } ++ if (changed & BSS_CHANGED_BEACON) ++ /* Beacon data changed, retrieve new beacon (beaconing modes) */ ++ wiphy_err(wiphy, "%s: beacon changed\n", __func__); ++ ++ if (changed & BSS_CHANGED_BEACON_ENABLED) { ++ /* Beaconing should be enabled/disabled (beaconing modes) */ ++ wiphy_err(wiphy, "%s: Beacon enabled: %s\n", __func__, ++ info->enable_beacon ? "true" : "false"); ++ } ++ ++ if (changed & BSS_CHANGED_CQM) { ++ /* Connection quality monitor config changed */ ++ wiphy_err(wiphy, "%s: cqm change: threshold %d, hys %d " ++ " (implement)\n", __func__, info->cqm_rssi_thold, ++ info->cqm_rssi_hyst); ++ } ++ ++ if (changed & BSS_CHANGED_IBSS) { ++ /* IBSS join status changed */ ++ wiphy_err(wiphy, "%s: IBSS joined: %s (implement)\n", __func__, ++ info->ibss_joined ? "true" : "false"); ++ } ++ ++ if (changed & BSS_CHANGED_ARP_FILTER) { ++ /* Hardware ARP filter address list or state changed */ ++ wiphy_err(wiphy, "%s: arp filtering: enabled %s, count %d" ++ " (implement)\n", __func__, info->arp_filter_enabled ? ++ "true" : "false", info->arp_addr_cnt); ++ } ++ ++ if (changed & BSS_CHANGED_QOS) { ++ /* ++ * QoS for this association was enabled/disabled. ++ * Note that it is only ever disabled for station mode. ++ */ ++ wiphy_err(wiphy, "%s: qos enabled: %s (implement)\n", __func__, ++ info->qos ? "true" : "false"); ++ } ++ return; ++} ++ ++static void ++brcms_ops_configure_filter(struct ieee80211_hw *hw, ++ unsigned int changed_flags, ++ unsigned int *total_flags, u64 multicast) ++{ ++ struct brcms_info *wl = hw->priv; ++ struct wiphy *wiphy = hw->wiphy; ++ ++ changed_flags &= MAC_FILTERS; ++ *total_flags &= MAC_FILTERS; ++ if (changed_flags & FIF_PROMISC_IN_BSS) ++ wiphy_err(wiphy, "FIF_PROMISC_IN_BSS\n"); ++ if (changed_flags & FIF_ALLMULTI) ++ wiphy_err(wiphy, "FIF_ALLMULTI\n"); ++ if (changed_flags & FIF_FCSFAIL) ++ wiphy_err(wiphy, "FIF_FCSFAIL\n"); ++ if (changed_flags & FIF_PLCPFAIL) ++ wiphy_err(wiphy, "FIF_PLCPFAIL\n"); ++ if (changed_flags & FIF_CONTROL) ++ wiphy_err(wiphy, "FIF_CONTROL\n"); ++ if (changed_flags & FIF_OTHER_BSS) ++ wiphy_err(wiphy, "FIF_OTHER_BSS\n"); ++ if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { ++ spin_lock_bh(&wl->lock); ++ if (*total_flags & FIF_BCN_PRBRESP_PROMISC) { ++ wl->pub->mac80211_state |= MAC80211_PROMISC_BCNS; ++ brcms_c_mac_bcn_promisc_change(wl->wlc, 1); ++ } else { ++ brcms_c_mac_bcn_promisc_change(wl->wlc, 0); ++ wl->pub->mac80211_state &= ~MAC80211_PROMISC_BCNS; ++ } ++ spin_unlock_bh(&wl->lock); ++ } ++ return; ++} ++ ++static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw) ++{ ++ struct brcms_info *wl = hw->priv; ++ spin_lock_bh(&wl->lock); ++ brcms_c_scan_start(wl->wlc); ++ spin_unlock_bh(&wl->lock); ++ return; ++} ++ ++static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw) ++{ ++ struct brcms_info *wl = hw->priv; ++ spin_lock_bh(&wl->lock); ++ brcms_c_scan_stop(wl->wlc); ++ spin_unlock_bh(&wl->lock); ++ return; ++} ++ ++static int ++brcms_ops_conf_tx(struct ieee80211_hw *hw, u16 queue, ++ const struct ieee80211_tx_queue_params *params) ++{ ++ struct brcms_info *wl = hw->priv; ++ ++ spin_lock_bh(&wl->lock); ++ brcms_c_wme_setparams(wl->wlc, queue, params, true); ++ spin_unlock_bh(&wl->lock); ++ ++ return 0; ++} ++ ++static int ++brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta) ++{ ++ struct brcms_info *wl = hw->priv; ++ struct scb *scb = &wl->wlc->pri_scb; ++ ++ brcms_c_init_scb(scb); ++ ++ wl->pub->global_ampdu = &(scb->scb_ampdu); ++ wl->pub->global_ampdu->scb = scb; ++ wl->pub->global_ampdu->max_pdu = 16; ++ ++ sta->ht_cap.ht_supported = true; ++ sta->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; ++ sta->ht_cap.ampdu_density = AMPDU_DEF_MPDU_DENSITY; ++ sta->ht_cap.cap = IEEE80211_HT_CAP_GRN_FLD | ++ IEEE80211_HT_CAP_SGI_20 | ++ IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT; ++ ++ /* ++ * minstrel_ht initiates addBA on our behalf by calling ++ * ieee80211_start_tx_ba_session() ++ */ ++ return 0; ++} ++ ++static int ++brcms_ops_ampdu_action(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ enum ieee80211_ampdu_mlme_action action, ++ struct ieee80211_sta *sta, u16 tid, u16 *ssn, ++ u8 buf_size) ++{ ++ struct brcms_info *wl = hw->priv; ++ struct scb *scb = &wl->wlc->pri_scb; ++ int status; ++ ++ if (WARN_ON(scb->magic != SCB_MAGIC)) ++ return -EIDRM; ++ switch (action) { ++ case IEEE80211_AMPDU_RX_START: ++ break; ++ case IEEE80211_AMPDU_RX_STOP: ++ break; ++ case IEEE80211_AMPDU_TX_START: ++ spin_lock_bh(&wl->lock); ++ status = brcms_c_aggregatable(wl->wlc, tid); ++ spin_unlock_bh(&wl->lock); ++ if (!status) { ++ wiphy_err(wl->wiphy, "START: tid %d is not agg\'able\n", ++ tid); ++ return -EINVAL; ++ } ++ ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); ++ break; ++ ++ case IEEE80211_AMPDU_TX_STOP: ++ spin_lock_bh(&wl->lock); ++ brcms_c_ampdu_flush(wl->wlc, sta, tid); ++ spin_unlock_bh(&wl->lock); ++ ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); ++ break; ++ case IEEE80211_AMPDU_TX_OPERATIONAL: ++ /* ++ * BA window size from ADDBA response ('buf_size') defines how ++ * many outstanding MPDUs are allowed for the BA stream by ++ * recipient and traffic class. 'ampdu_factor' gives maximum ++ * AMPDU size. ++ */ ++ spin_lock_bh(&wl->lock); ++ brcms_c_ampdu_tx_operational(wl->wlc, tid, buf_size, ++ (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + ++ sta->ht_cap.ampdu_factor)) - 1); ++ spin_unlock_bh(&wl->lock); ++ /* Power save wakeup */ ++ break; ++ default: ++ wiphy_err(wl->wiphy, "%s: Invalid command, ignoring\n", ++ __func__); ++ } ++ ++ return 0; ++} ++ ++static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw) ++{ ++ struct brcms_info *wl = hw->priv; ++ bool blocked; ++ ++ spin_lock_bh(&wl->lock); ++ blocked = brcms_c_check_radio_disabled(wl->wlc); ++ spin_unlock_bh(&wl->lock); ++ ++ wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked); ++} ++ ++static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop) ++{ ++ struct brcms_info *wl = hw->priv; ++ ++ no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false"); ++ ++ /* wait for packet queue and dma fifos to run empty */ ++ spin_lock_bh(&wl->lock); ++ brcms_c_wait_for_tx_completion(wl->wlc, drop); ++ spin_unlock_bh(&wl->lock); ++} ++ ++static const struct ieee80211_ops brcms_ops = { ++ .tx = brcms_ops_tx, ++ .start = brcms_ops_start, ++ .stop = brcms_ops_stop, ++ .add_interface = brcms_ops_add_interface, ++ .remove_interface = brcms_ops_remove_interface, ++ .config = brcms_ops_config, ++ .bss_info_changed = brcms_ops_bss_info_changed, ++ .configure_filter = brcms_ops_configure_filter, ++ .sw_scan_start = brcms_ops_sw_scan_start, ++ .sw_scan_complete = brcms_ops_sw_scan_complete, ++ .conf_tx = brcms_ops_conf_tx, ++ .sta_add = brcms_ops_sta_add, ++ .ampdu_action = brcms_ops_ampdu_action, ++ .rfkill_poll = brcms_ops_rfkill_poll, ++ .flush = brcms_ops_flush, ++}; ++ ++/* ++ * is called in brcms_pci_probe() context, therefore no locking required. ++ */ ++static int brcms_set_hint(struct brcms_info *wl, char *abbrev) ++{ ++ return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev); ++} ++ ++void brcms_dpc(unsigned long data) ++{ ++ struct brcms_info *wl; ++ ++ wl = (struct brcms_info *) data; ++ ++ spin_lock_bh(&wl->lock); ++ ++ /* call the common second level interrupt handler */ ++ if (wl->pub->up) { ++ if (wl->resched) { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wl->isr_lock, flags); ++ brcms_c_intrsupd(wl->wlc); ++ spin_unlock_irqrestore(&wl->isr_lock, flags); ++ } ++ ++ wl->resched = brcms_c_dpc(wl->wlc, true); ++ } ++ ++ /* brcms_c_dpc() may bring the driver down */ ++ if (!wl->pub->up) ++ goto done; ++ ++ /* re-schedule dpc */ ++ if (wl->resched) ++ tasklet_schedule(&wl->tasklet); ++ else ++ /* re-enable interrupts */ ++ brcms_intrson(wl); ++ ++ done: ++ spin_unlock_bh(&wl->lock); ++} ++ ++/* ++ * Precondition: Since this function is called in brcms_pci_probe() context, ++ * no locking is required. ++ */ ++static int brcms_request_fw(struct brcms_info *wl, struct pci_dev *pdev) ++{ ++ int status; ++ struct device *device = &pdev->dev; ++ char fw_name[100]; ++ int i; ++ ++ memset(&wl->fw, 0, sizeof(struct brcms_firmware)); ++ for (i = 0; i < MAX_FW_IMAGES; i++) { ++ if (brcms_firmwares[i] == NULL) ++ break; ++ sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i], ++ UCODE_LOADER_API_VER); ++ status = request_firmware(&wl->fw.fw_bin[i], fw_name, device); ++ if (status) { ++ wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n", ++ KBUILD_MODNAME, fw_name); ++ return status; ++ } ++ sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i], ++ UCODE_LOADER_API_VER); ++ status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device); ++ if (status) { ++ wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n", ++ KBUILD_MODNAME, fw_name); ++ return status; ++ } ++ wl->fw.hdr_num_entries[i] = ++ wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr)); ++ } ++ wl->fw.fw_cnt = i; ++ return brcms_ucode_data_init(wl, &wl->ucode); ++} ++ ++/* ++ * Precondition: Since this function is called in brcms_pci_probe() context, ++ * no locking is required. ++ */ ++static void brcms_release_fw(struct brcms_info *wl) ++{ ++ int i; ++ for (i = 0; i < MAX_FW_IMAGES; i++) { ++ release_firmware(wl->fw.fw_bin[i]); ++ release_firmware(wl->fw.fw_hdr[i]); ++ } ++} ++ ++/** ++ * This function frees the WL per-device resources. ++ * ++ * This function frees resources owned by the WL device pointed to ++ * by the wl parameter. ++ * ++ * precondition: can both be called locked and unlocked ++ * ++ */ ++static void brcms_free(struct brcms_info *wl) ++{ ++ struct brcms_timer *t, *next; ++ ++ /* free ucode data */ ++ if (wl->fw.fw_cnt) ++ brcms_ucode_data_free(&wl->ucode); ++ if (wl->irq) ++ free_irq(wl->irq, wl); ++ ++ /* kill dpc */ ++ tasklet_kill(&wl->tasklet); ++ ++ if (wl->pub) ++ brcms_c_module_unregister(wl->pub, "linux", wl); ++ ++ /* free common resources */ ++ if (wl->wlc) { ++ brcms_c_detach(wl->wlc); ++ wl->wlc = NULL; ++ wl->pub = NULL; ++ } ++ ++ /* virtual interface deletion is deferred so we cannot spinwait */ ++ ++ /* wait for all pending callbacks to complete */ ++ while (atomic_read(&wl->callbacks) > 0) ++ schedule(); ++ ++ /* free timers */ ++ for (t = wl->timers; t; t = next) { ++ next = t->next; ++#ifdef BCMDBG ++ kfree(t->name); ++#endif ++ kfree(t); ++ } ++ ++ /* ++ * unregister_netdev() calls get_stats() which may read chip ++ * registers so we cannot unmap the chip registers until ++ * after calling unregister_netdev() . ++ */ ++ if (wl->regsva) ++ iounmap(wl->regsva); ++ ++ wl->regsva = NULL; ++} ++ ++/* ++* called from both kernel as from this kernel module. ++* precondition: perimeter lock is not acquired. ++*/ ++static void brcms_remove(struct pci_dev *pdev) ++{ ++ struct brcms_info *wl; ++ struct ieee80211_hw *hw; ++ int status; ++ ++ hw = pci_get_drvdata(pdev); ++ wl = hw->priv; ++ if (!wl) { ++ pr_err("wl: brcms_remove: pci_get_drvdata failed\n"); ++ return; ++ } ++ ++ spin_lock_bh(&wl->lock); ++ status = brcms_c_chipmatch(pdev->vendor, pdev->device); ++ spin_unlock_bh(&wl->lock); ++ if (!status) { ++ wiphy_err(wl->wiphy, "wl: brcms_remove: chipmatch " ++ "failed\n"); ++ return; ++ } ++ if (wl->wlc) { ++ wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); ++ wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); ++ ieee80211_unregister_hw(hw); ++ spin_lock_bh(&wl->lock); ++ brcms_down(wl); ++ spin_unlock_bh(&wl->lock); ++ } ++ pci_disable_device(pdev); ++ ++ brcms_free(wl); ++ ++ pci_set_drvdata(pdev, NULL); ++ ieee80211_free_hw(hw); ++} ++ ++static irqreturn_t brcms_isr(int irq, void *dev_id) ++{ ++ struct brcms_info *wl; ++ bool ours, wantdpc; ++ ++ wl = (struct brcms_info *) dev_id; ++ ++ spin_lock(&wl->isr_lock); ++ ++ /* call common first level interrupt handler */ ++ ours = brcms_c_isr(wl->wlc, &wantdpc); ++ if (ours) { ++ /* if more to do... */ ++ if (wantdpc) { ++ ++ /* ...and call the second level interrupt handler */ ++ /* schedule dpc */ ++ tasklet_schedule(&wl->tasklet); ++ } ++ } ++ ++ spin_unlock(&wl->isr_lock); ++ ++ return IRQ_RETVAL(ours); ++} ++ ++/* ++ * is called in brcms_pci_probe() context, therefore no locking required. ++ */ ++static int ieee_hw_rate_init(struct ieee80211_hw *hw) ++{ ++ struct brcms_info *wl = hw->priv; ++ struct brcms_c_info *wlc = wl->wlc; ++ struct ieee80211_supported_band *band; ++ int has_5g = 0; ++ u16 phy_type; ++ ++ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; ++ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; ++ ++ phy_type = brcms_c_get_phy_type(wl->wlc, 0); ++ if (phy_type == PHY_TYPE_N || phy_type == PHY_TYPE_LCN) { ++ band = &wlc->bandstate[BAND_2G_INDEX]->band; ++ *band = brcms_band_2GHz_nphy_template; ++ if (phy_type == PHY_TYPE_LCN) { ++ /* Single stream */ ++ band->ht_cap.mcs.rx_mask[1] = 0; ++ band->ht_cap.mcs.rx_highest = cpu_to_le16(72); ++ } ++ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band; ++ } else { ++ return -EPERM; ++ } ++ ++ /* Assume all bands use the same phy. True for 11n devices. */ ++ if (wl->pub->_nbands > 1) { ++ has_5g++; ++ if (phy_type == PHY_TYPE_N || phy_type == PHY_TYPE_LCN) { ++ band = &wlc->bandstate[BAND_5G_INDEX]->band; ++ *band = brcms_band_5GHz_nphy_template; ++ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band; ++ } else { ++ return -EPERM; ++ } ++ } ++ return 0; ++} ++ ++/* ++ * is called in brcms_pci_probe() context, therefore no locking required. ++ */ ++static int ieee_hw_init(struct ieee80211_hw *hw) ++{ ++ hw->flags = IEEE80211_HW_SIGNAL_DBM ++ /* | IEEE80211_HW_CONNECTION_MONITOR What is this? */ ++ | IEEE80211_HW_REPORTS_TX_ACK_STATUS ++ | IEEE80211_HW_AMPDU_AGGREGATION; ++ ++ hw->extra_tx_headroom = brcms_c_get_header_len(); ++ hw->queues = N_TX_QUEUES; ++ hw->max_rates = 2; /* Primary rate and 1 fallback rate */ ++ ++ /* channel change time is dependent on chip and band */ ++ hw->channel_change_time = 7 * 1000; ++ hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); ++ ++ hw->rate_control_algorithm = "minstrel_ht"; ++ ++ hw->sta_data_size = 0; ++ return ieee_hw_rate_init(hw); ++} ++ ++/** ++ * attach to the WL device. ++ * ++ * Attach to the WL device identified by vendor and device parameters. ++ * regs is a host accessible memory address pointing to WL device registers. ++ * ++ * brcms_attach is not defined as static because in the case where no bus ++ * is defined, wl_attach will never be called, and thus, gcc will issue ++ * a warning that this function is defined but not used if we declare ++ * it as static. ++ * ++ * ++ * is called in brcms_pci_probe() context, therefore no locking required. ++ */ ++static struct brcms_info *brcms_attach(u16 vendor, u16 device, ++ resource_size_t regs, ++ struct pci_dev *btparam, uint irq) ++{ ++ struct brcms_info *wl = NULL; ++ int unit, err; ++ struct ieee80211_hw *hw; ++ u8 perm[ETH_ALEN]; ++ ++ unit = n_adapters_found; ++ err = 0; ++ ++ if (unit < 0) ++ return NULL; ++ ++ /* allocate private info */ ++ hw = pci_get_drvdata(btparam); /* btparam == pdev */ ++ if (hw != NULL) ++ wl = hw->priv; ++ if (WARN_ON(hw == NULL) || WARN_ON(wl == NULL)) ++ return NULL; ++ wl->wiphy = hw->wiphy; ++ ++ atomic_set(&wl->callbacks, 0); ++ ++ /* setup the bottom half handler */ ++ tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl); ++ ++ wl->regsva = ioremap_nocache(regs, PCI_BAR0_WINSZ); ++ if (wl->regsva == NULL) { ++ wiphy_err(wl->wiphy, "wl%d: ioremap() failed\n", unit); ++ goto fail; ++ } ++ spin_lock_init(&wl->lock); ++ spin_lock_init(&wl->isr_lock); ++ ++ /* prepare ucode */ ++ if (brcms_request_fw(wl, btparam) < 0) { ++ wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in " ++ "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm"); ++ brcms_release_fw(wl); ++ brcms_remove(btparam); ++ return NULL; ++ } ++ ++ /* common load-time initialization */ ++ wl->wlc = brcms_c_attach(wl, vendor, device, unit, false, ++ wl->regsva, btparam, &err); ++ brcms_release_fw(wl); ++ if (!wl->wlc) { ++ wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n", ++ KBUILD_MODNAME, err); ++ goto fail; ++ } ++ wl->pub = brcms_c_pub(wl->wlc); ++ ++ wl->pub->ieee_hw = hw; ++ ++ /* disable mpc */ ++ brcms_c_set_radio_mpc(wl->wlc, false); ++ ++ /* register our interrupt handler */ ++ if (request_irq(irq, brcms_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) { ++ wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit); ++ goto fail; ++ } ++ wl->irq = irq; ++ ++ /* register module */ ++ brcms_c_module_register(wl->pub, "linux", wl, NULL); ++ ++ if (ieee_hw_init(hw)) { ++ wiphy_err(wl->wiphy, "wl%d: %s: ieee_hw_init failed!\n", unit, ++ __func__); ++ goto fail; ++ } ++ ++ memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN); ++ if (WARN_ON(!is_valid_ether_addr(perm))) ++ goto fail; ++ SET_IEEE80211_PERM_ADDR(hw, perm); ++ ++ err = ieee80211_register_hw(hw); ++ if (err) ++ wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status" ++ "%d\n", __func__, err); ++ ++ if (wl->pub->srom_ccode[0]) ++ err = brcms_set_hint(wl, wl->pub->srom_ccode); ++ else ++ err = brcms_set_hint(wl, "US"); ++ if (err) ++ wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n", ++ __func__, err); ++ ++ n_adapters_found++; ++ return wl; ++ ++fail: ++ brcms_free(wl); ++ return NULL; ++} ++ ++ ++ ++/** ++ * determines if a device is a WL device, and if so, attaches it. ++ * ++ * This function determines if a device pointed to by pdev is a WL device, ++ * and if so, performs a brcms_attach() on it. ++ * ++ * Perimeter lock is initialized in the course of this function. ++ */ ++static int __devinit ++brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ++{ ++ int rc; ++ struct brcms_info *wl; ++ struct ieee80211_hw *hw; ++ u32 val; ++ ++ dev_info(&pdev->dev, "bus %d slot %d func %d irq %d\n", ++ pdev->bus->number, PCI_SLOT(pdev->devfn), ++ PCI_FUNC(pdev->devfn), pdev->irq); ++ ++ if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) || ++ ((pdev->device != 0x0576) && ++ ((pdev->device & 0xff00) != 0x4300) && ++ ((pdev->device & 0xff00) != 0x4700) && ++ ((pdev->device < 43000) || (pdev->device > 43999)))) ++ return -ENODEV; ++ ++ rc = pci_enable_device(pdev); ++ if (rc) { ++ pr_err("%s: Cannot enable device %d-%d_%d\n", ++ __func__, pdev->bus->number, PCI_SLOT(pdev->devfn), ++ PCI_FUNC(pdev->devfn)); ++ return -ENODEV; ++ } ++ pci_set_master(pdev); ++ ++ pci_read_config_dword(pdev, 0x40, &val); ++ if ((val & 0x0000ff00) != 0) ++ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); ++ ++ hw = ieee80211_alloc_hw(sizeof(struct brcms_info), &brcms_ops); ++ if (!hw) { ++ pr_err("%s: ieee80211_alloc_hw failed\n", __func__); ++ return -ENOMEM; ++ } ++ ++ SET_IEEE80211_DEV(hw, &pdev->dev); ++ ++ pci_set_drvdata(pdev, hw); ++ ++ memset(hw->priv, 0, sizeof(*wl)); ++ ++ wl = brcms_attach(pdev->vendor, pdev->device, ++ pci_resource_start(pdev, 0), pdev, ++ pdev->irq); ++ ++ if (!wl) { ++ pr_err("%s: %s: brcms_attach failed!\n", KBUILD_MODNAME, ++ __func__); ++ return -ENODEV; ++ } ++ return 0; ++} ++ ++static int brcms_suspend(struct pci_dev *pdev, pm_message_t state) ++{ ++ struct brcms_info *wl; ++ struct ieee80211_hw *hw; ++ ++ hw = pci_get_drvdata(pdev); ++ wl = hw->priv; ++ if (!wl) { ++ wiphy_err(wl->wiphy, ++ "brcms_suspend: pci_get_drvdata failed\n"); ++ return -ENODEV; ++ } ++ ++ /* only need to flag hw is down for proper resume */ ++ spin_lock_bh(&wl->lock); ++ wl->pub->hw_up = false; ++ spin_unlock_bh(&wl->lock); ++ ++ pci_save_state(pdev); ++ pci_disable_device(pdev); ++ return pci_set_power_state(pdev, PCI_D3hot); ++} ++ ++static int brcms_resume(struct pci_dev *pdev) ++{ ++ struct brcms_info *wl; ++ struct ieee80211_hw *hw; ++ int err = 0; ++ u32 val; ++ ++ hw = pci_get_drvdata(pdev); ++ wl = hw->priv; ++ if (!wl) { ++ wiphy_err(wl->wiphy, ++ "wl: brcms_resume: pci_get_drvdata failed\n"); ++ return -ENODEV; ++ } ++ ++ err = pci_set_power_state(pdev, PCI_D0); ++ if (err) ++ return err; ++ ++ pci_restore_state(pdev); ++ ++ err = pci_enable_device(pdev); ++ if (err) ++ return err; ++ ++ pci_set_master(pdev); ++ ++ pci_read_config_dword(pdev, 0x40, &val); ++ if ((val & 0x0000ff00) != 0) ++ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); ++ ++ /* ++ * done. driver will be put in up state ++ * in brcms_ops_add_interface() call. ++ */ ++ return err; ++} ++ ++static struct pci_driver brcms_pci_driver = { ++ .name = KBUILD_MODNAME, ++ .probe = brcms_pci_probe, ++ .suspend = brcms_suspend, ++ .resume = brcms_resume, ++ .remove = __devexit_p(brcms_remove), ++ .id_table = brcms_pci_id_table, ++}; ++ ++/** ++ * This is the main entry point for the WL driver. ++ * ++ * This function determines if a device pointed to by pdev is a WL device, ++ * and if so, performs a brcms_attach() on it. ++ * ++ */ ++static int __init brcms_module_init(void) ++{ ++ int error = -ENODEV; ++ ++#ifdef BCMDBG ++ if (msglevel != 0xdeadbeef) ++ brcm_msg_level = msglevel; ++#endif /* BCMDBG */ ++ ++ error = pci_register_driver(&brcms_pci_driver); ++ if (!error) ++ return 0; ++ ++ ++ ++ return error; ++} ++ ++/** ++ * This function unloads the WL driver from the system. ++ * ++ * This function unconditionally unloads the WL driver module from the ++ * system. ++ * ++ */ ++static void __exit brcms_module_exit(void) ++{ ++ pci_unregister_driver(&brcms_pci_driver); ++ ++} ++ ++module_init(brcms_module_init); ++module_exit(brcms_module_exit); ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif, ++ bool state, int prio) ++{ ++ wiphy_err(wl->wiphy, "Shouldn't be here %s\n", __func__); ++} ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++void brcms_init(struct brcms_info *wl) ++{ ++ BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit); ++ brcms_reset(wl); ++ ++ brcms_c_init(wl->wlc); ++} ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++uint brcms_reset(struct brcms_info *wl) ++{ ++ BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit); ++ brcms_c_reset(wl->wlc); ++ ++ /* dpc will not be rescheduled */ ++ wl->resched = 0; ++ ++ return 0; ++} ++ ++/* ++ * These are interrupt on/off entry points. Disable interrupts ++ * during interrupt state transition. ++ */ ++void brcms_intrson(struct brcms_info *wl) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wl->isr_lock, flags); ++ brcms_c_intrson(wl->wlc); ++ spin_unlock_irqrestore(&wl->isr_lock, flags); ++} ++ ++u32 brcms_intrsoff(struct brcms_info *wl) ++{ ++ unsigned long flags; ++ u32 status; ++ ++ spin_lock_irqsave(&wl->isr_lock, flags); ++ status = brcms_c_intrsoff(wl->wlc); ++ spin_unlock_irqrestore(&wl->isr_lock, flags); ++ return status; ++} ++ ++void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wl->isr_lock, flags); ++ brcms_c_intrsrestore(wl->wlc, macintmask); ++ spin_unlock_irqrestore(&wl->isr_lock, flags); ++} ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++int brcms_up(struct brcms_info *wl) ++{ ++ int error = 0; ++ ++ if (wl->pub->up) ++ return 0; ++ ++ error = brcms_c_up(wl->wlc); ++ ++ return error; ++} ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++void brcms_down(struct brcms_info *wl) ++{ ++ uint callbacks, ret_val = 0; ++ ++ /* call common down function */ ++ ret_val = brcms_c_down(wl->wlc); ++ callbacks = atomic_read(&wl->callbacks) - ret_val; ++ ++ /* wait for down callbacks to complete */ ++ spin_unlock_bh(&wl->lock); ++ ++ /* For HIGH_only driver, it's important to actually schedule other work, ++ * not just spin wait since everything runs at schedule level ++ */ ++ SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000); ++ ++ spin_lock_bh(&wl->lock); ++} ++ ++/* ++* precondition: perimeter lock is not acquired ++ */ ++static void _brcms_timer(struct work_struct *work) ++{ ++ struct brcms_timer *t = container_of(work, struct brcms_timer, ++ dly_wrk.work); ++ ++ spin_lock_bh(&t->wl->lock); ++ ++ if (t->set) { ++ if (t->periodic) { ++ atomic_inc(&t->wl->callbacks); ++ ieee80211_queue_delayed_work(t->wl->pub->ieee_hw, ++ &t->dly_wrk, ++ msecs_to_jiffies(t->ms)); ++ } else { ++ t->set = false; ++ } ++ ++ t->fn(t->arg); ++ } ++ ++ atomic_dec(&t->wl->callbacks); ++ ++ spin_unlock_bh(&t->wl->lock); ++} ++ ++/* ++ * Adds a timer to the list. Caller supplies a timer function. ++ * Is called from wlc. ++ * ++ * precondition: perimeter lock has been acquired ++ */ ++struct brcms_timer *brcms_init_timer(struct brcms_info *wl, ++ void (*fn) (void *arg), ++ void *arg, const char *name) ++{ ++ struct brcms_timer *t; ++ ++ t = kzalloc(sizeof(struct brcms_timer), GFP_ATOMIC); ++ if (!t) ++ return NULL; ++ ++ INIT_DELAYED_WORK(&t->dly_wrk, _brcms_timer); ++ t->wl = wl; ++ t->fn = fn; ++ t->arg = arg; ++ t->next = wl->timers; ++ wl->timers = t; ++ ++#ifdef BCMDBG ++ t->name = kmalloc(strlen(name) + 1, GFP_ATOMIC); ++ if (t->name) ++ strcpy(t->name, name); ++#endif ++ ++ return t; ++} ++ ++/* ++ * adds only the kernel timer since it's going to be more accurate ++ * as well as it's easier to make it periodic ++ * ++ * precondition: perimeter lock has been acquired ++ */ ++void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic) ++{ ++ struct ieee80211_hw *hw = t->wl->pub->ieee_hw; ++ ++#ifdef BCMDBG ++ if (t->set) ++ wiphy_err(hw->wiphy, "%s: Already set. Name: %s, per %d\n", ++ __func__, t->name, periodic); ++#endif ++ t->ms = ms; ++ t->periodic = (bool) periodic; ++ t->set = true; ++ ++ atomic_inc(&t->wl->callbacks); ++ ++ ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms)); ++} ++ ++/* ++ * return true if timer successfully deleted, false if still pending ++ * ++ * precondition: perimeter lock has been acquired ++ */ ++bool brcms_del_timer(struct brcms_timer *t) ++{ ++ if (t->set) { ++ t->set = false; ++ if (!cancel_delayed_work(&t->dly_wrk)) ++ return false; ++ ++ atomic_dec(&t->wl->callbacks); ++ } ++ ++ return true; ++} ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++void brcms_free_timer(struct brcms_timer *t) ++{ ++ struct brcms_info *wl = t->wl; ++ struct brcms_timer *tmp; ++ ++ /* delete the timer in case it is active */ ++ brcms_del_timer(t); ++ ++ if (wl->timers == t) { ++ wl->timers = wl->timers->next; ++#ifdef BCMDBG ++ kfree(t->name); ++#endif ++ kfree(t); ++ return; ++ ++ } ++ ++ tmp = wl->timers; ++ while (tmp) { ++ if (tmp->next == t) { ++ tmp->next = t->next; ++#ifdef BCMDBG ++ kfree(t->name); ++#endif ++ kfree(t); ++ return; ++ } ++ tmp = tmp->next; ++ } ++ ++} ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx) ++{ ++ int i, entry; ++ const u8 *pdata; ++ struct firmware_hdr *hdr; ++ for (i = 0; i < wl->fw.fw_cnt; i++) { ++ hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data; ++ for (entry = 0; entry < wl->fw.hdr_num_entries[i]; ++ entry++, hdr++) { ++ u32 len = le32_to_cpu(hdr->len); ++ if (le32_to_cpu(hdr->idx) == idx) { ++ pdata = wl->fw.fw_bin[i]->data + ++ le32_to_cpu(hdr->offset); ++ *pbuf = kmalloc(len, GFP_ATOMIC); ++ if (*pbuf == NULL) ++ goto fail; ++ ++ memcpy(*pbuf, pdata, len); ++ return 0; ++ } ++ } ++ } ++ wiphy_err(wl->wiphy, "ERROR: ucode buf tag:%d can not be found!\n", ++ idx); ++ *pbuf = NULL; ++fail: ++ return -ENODATA; ++} ++ ++/* ++ * Precondition: Since this function is called in brcms_pci_probe() context, ++ * no locking is required. ++ */ ++int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx) ++{ ++ int i, entry; ++ const u8 *pdata; ++ struct firmware_hdr *hdr; ++ for (i = 0; i < wl->fw.fw_cnt; i++) { ++ hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data; ++ for (entry = 0; entry < wl->fw.hdr_num_entries[i]; ++ entry++, hdr++) { ++ if (le32_to_cpu(hdr->idx) == idx) { ++ pdata = wl->fw.fw_bin[i]->data + ++ le32_to_cpu(hdr->offset); ++ if (le32_to_cpu(hdr->len) != 4) { ++ wiphy_err(wl->wiphy, ++ "ERROR: fw hdr len\n"); ++ return -ENOMSG; ++ } ++ *n_bytes = le32_to_cpu(*((__le32 *) pdata)); ++ return 0; ++ } ++ } ++ } ++ wiphy_err(wl->wiphy, "ERROR: ucode tag:%d can not be found!\n", idx); ++ return -ENOMSG; ++} ++ ++/* ++ * precondition: can both be called locked and unlocked ++ */ ++void brcms_ucode_free_buf(void *p) ++{ ++ kfree(p); ++} ++ ++/* ++ * checks validity of all firmware images loaded from user space ++ * ++ * Precondition: Since this function is called in brcms_pci_probe() context, ++ * no locking is required. ++ */ ++int brcms_check_firmwares(struct brcms_info *wl) ++{ ++ int i; ++ int entry; ++ int rc = 0; ++ const struct firmware *fw; ++ const struct firmware *fw_hdr; ++ struct firmware_hdr *ucode_hdr; ++ for (i = 0; i < MAX_FW_IMAGES && rc == 0; i++) { ++ fw = wl->fw.fw_bin[i]; ++ fw_hdr = wl->fw.fw_hdr[i]; ++ if (fw == NULL && fw_hdr == NULL) { ++ break; ++ } else if (fw == NULL || fw_hdr == NULL) { ++ wiphy_err(wl->wiphy, "%s: invalid bin/hdr fw\n", ++ __func__); ++ rc = -EBADF; ++ } else if (fw_hdr->size % sizeof(struct firmware_hdr)) { ++ wiphy_err(wl->wiphy, "%s: non integral fw hdr file " ++ "size %zu/%zu\n", __func__, fw_hdr->size, ++ sizeof(struct firmware_hdr)); ++ rc = -EBADF; ++ } else if (fw->size < MIN_FW_SIZE || fw->size > MAX_FW_SIZE) { ++ wiphy_err(wl->wiphy, "%s: out of bounds fw file size " ++ "%zu\n", __func__, fw->size); ++ rc = -EBADF; ++ } else { ++ /* check if ucode section overruns firmware image */ ++ ucode_hdr = (struct firmware_hdr *)fw_hdr->data; ++ for (entry = 0; entry < wl->fw.hdr_num_entries[i] && ++ !rc; entry++, ucode_hdr++) { ++ if (le32_to_cpu(ucode_hdr->offset) + ++ le32_to_cpu(ucode_hdr->len) > ++ fw->size) { ++ wiphy_err(wl->wiphy, ++ "%s: conflicting bin/hdr\n", ++ __func__); ++ rc = -EBADF; ++ } ++ } ++ } ++ } ++ if (rc == 0 && wl->fw.fw_cnt != i) { ++ wiphy_err(wl->wiphy, "%s: invalid fw_cnt=%d\n", __func__, ++ wl->fw.fw_cnt); ++ rc = -EBADF; ++ } ++ return rc; ++} ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++bool brcms_rfkill_set_hw_state(struct brcms_info *wl) ++{ ++ bool blocked = brcms_c_check_radio_disabled(wl->wlc); ++ ++ spin_unlock_bh(&wl->lock); ++ wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked); ++ if (blocked) ++ wiphy_rfkill_start_polling(wl->pub->ieee_hw->wiphy); ++ spin_lock_bh(&wl->lock); ++ return blocked; ++} ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++void brcms_msleep(struct brcms_info *wl, uint ms) ++{ ++ spin_unlock_bh(&wl->lock); ++ msleep(ms); ++ spin_lock_bh(&wl->lock); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h.orig 2011-11-09 13:46:58.246800621 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h 2011-11-09 13:47:16.998566192 -0500 +@@ -0,0 +1,108 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_MAC80211_IF_H_ ++#define _BRCM_MAC80211_IF_H_ ++ ++#include ++#include ++#include ++ ++#include "ucode_loader.h" ++/* ++ * Starting index for 5G rates in the ++ * legacy rate table. ++ */ ++#define BRCMS_LEGACY_5G_RATE_OFFSET 4 ++ ++/* softmac ioctl definitions */ ++#define BRCMS_SET_SHORTSLOT_OVERRIDE 146 ++ ++struct brcms_timer { ++ struct delayed_work dly_wrk; ++ struct brcms_info *wl; ++ void (*fn) (void *); /* function called upon expiration */ ++ void *arg; /* fixed argument provided to called function */ ++ uint ms; ++ bool periodic; ++ bool set; /* indicates if timer is active */ ++ struct brcms_timer *next; /* for freeing on unload */ ++#ifdef BCMDBG ++ char *name; /* Description of the timer */ ++#endif ++}; ++ ++struct brcms_if { ++ uint subunit; /* WDS/BSS unit */ ++ struct pci_dev *pci_dev; ++}; ++ ++#define MAX_FW_IMAGES 4 ++struct brcms_firmware { ++ u32 fw_cnt; ++ const struct firmware *fw_bin[MAX_FW_IMAGES]; ++ const struct firmware *fw_hdr[MAX_FW_IMAGES]; ++ u32 hdr_num_entries[MAX_FW_IMAGES]; ++}; ++ ++struct brcms_info { ++ struct brcms_pub *pub; /* pointer to public wlc state */ ++ struct brcms_c_info *wlc; /* pointer to private common data */ ++ u32 magic; ++ ++ int irq; ++ ++ spinlock_t lock; /* per-device perimeter lock */ ++ spinlock_t isr_lock; /* per-device ISR synchronization lock */ ++ ++ /* regsva for unmap in brcms_free() */ ++ void __iomem *regsva; /* opaque chip registers virtual address */ ++ ++ /* timer related fields */ ++ atomic_t callbacks; /* # outstanding callback functions */ ++ struct brcms_timer *timers; /* timer cleanup queue */ ++ ++ struct tasklet_struct tasklet; /* dpc tasklet */ ++ bool resched; /* dpc needs to be and is rescheduled */ ++ struct brcms_firmware fw; ++ struct wiphy *wiphy; ++ struct brcms_ucode ucode; ++}; ++ ++/* misc callbacks */ ++extern void brcms_init(struct brcms_info *wl); ++extern uint brcms_reset(struct brcms_info *wl); ++extern void brcms_intrson(struct brcms_info *wl); ++extern u32 brcms_intrsoff(struct brcms_info *wl); ++extern void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask); ++extern int brcms_up(struct brcms_info *wl); ++extern void brcms_down(struct brcms_info *wl); ++extern void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif, ++ bool state, int prio); ++extern bool brcms_rfkill_set_hw_state(struct brcms_info *wl); ++ ++/* timer functions */ ++extern struct brcms_timer *brcms_init_timer(struct brcms_info *wl, ++ void (*fn) (void *arg), void *arg, ++ const char *name); ++extern void brcms_free_timer(struct brcms_timer *timer); ++extern void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic); ++extern bool brcms_del_timer(struct brcms_timer *timer); ++extern void brcms_msleep(struct brcms_info *wl, uint ms); ++extern void brcms_dpc(unsigned long data); ++extern void brcms_timer(struct brcms_timer *t); ++ ++#endif /* _BRCM_MAC80211_IF_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.c.orig 2011-11-09 13:46:58.250800570 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.c 2011-11-09 13:47:17.004566116 -0500 +@@ -0,0 +1,8775 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rate.h" ++#include "scb.h" ++#include "phy/phy_hal.h" ++#include "channel.h" ++#include "antsel.h" ++#include "stf.h" ++#include "ampdu.h" ++#include "mac80211_if.h" ++#include "ucode_loader.h" ++#include "main.h" ++ ++/* ++ * Indication for txflowcontrol that all priority bits in ++ * TXQ_STOP_FOR_PRIOFC_MASK are to be considered. ++ */ ++#define ALLPRIO -1 ++ ++/* ++ * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL. ++ */ ++#define SSID_FMT_BUF_LEN ((4 * IEEE80211_MAX_SSID_LEN) + 1) ++ ++/* watchdog timer, in unit of ms */ ++#define TIMER_INTERVAL_WATCHDOG 1000 ++/* radio monitor timer, in unit of ms */ ++#define TIMER_INTERVAL_RADIOCHK 800 ++ ++/* Max MPC timeout, in unit of watchdog */ ++#ifndef BRCMS_MPC_MAX_DELAYCNT ++#define BRCMS_MPC_MAX_DELAYCNT 10 ++#endif ++ ++/* Min MPC timeout, in unit of watchdog */ ++#define BRCMS_MPC_MIN_DELAYCNT 1 ++#define BRCMS_MPC_THRESHOLD 3 /* MPC count threshold level */ ++ ++/* beacon interval, in unit of 1024TU */ ++#define BEACON_INTERVAL_DEFAULT 100 ++/* DTIM interval, in unit of beacon interval */ ++#define DTIM_INTERVAL_DEFAULT 3 ++ ++/* Scale down delays to accommodate QT slow speed */ ++/* beacon interval, in unit of 1024TU */ ++#define BEACON_INTERVAL_DEF_QT 20 ++/* DTIM interval, in unit of beacon interval */ ++#define DTIM_INTERVAL_DEF_QT 1 ++ ++#define TBTT_ALIGN_LEEWAY_US 100 /* min leeway before first TBTT in us */ ++ ++/* n-mode support capability */ ++/* 2x2 includes both 1x1 & 2x2 devices ++ * reserved #define 2 for future when we want to separate 1x1 & 2x2 and ++ * control it independently ++ */ ++#define WL_11N_2x2 1 ++#define WL_11N_3x3 3 ++#define WL_11N_4x4 4 ++ ++/* define 11n feature disable flags */ ++#define WLFEATURE_DISABLE_11N 0x00000001 ++#define WLFEATURE_DISABLE_11N_STBC_TX 0x00000002 ++#define WLFEATURE_DISABLE_11N_STBC_RX 0x00000004 ++#define WLFEATURE_DISABLE_11N_SGI_TX 0x00000008 ++#define WLFEATURE_DISABLE_11N_SGI_RX 0x00000010 ++#define WLFEATURE_DISABLE_11N_AMPDU_TX 0x00000020 ++#define WLFEATURE_DISABLE_11N_AMPDU_RX 0x00000040 ++#define WLFEATURE_DISABLE_11N_GF 0x00000080 ++ ++#define EDCF_ACI_MASK 0x60 ++#define EDCF_ACI_SHIFT 5 ++#define EDCF_ECWMIN_MASK 0x0f ++#define EDCF_ECWMAX_SHIFT 4 ++#define EDCF_AIFSN_MASK 0x0f ++#define EDCF_AIFSN_MAX 15 ++#define EDCF_ECWMAX_MASK 0xf0 ++ ++#define EDCF_AC_BE_TXOP_STA 0x0000 ++#define EDCF_AC_BK_TXOP_STA 0x0000 ++#define EDCF_AC_VO_ACI_STA 0x62 ++#define EDCF_AC_VO_ECW_STA 0x32 ++#define EDCF_AC_VI_ACI_STA 0x42 ++#define EDCF_AC_VI_ECW_STA 0x43 ++#define EDCF_AC_BK_ECW_STA 0xA4 ++#define EDCF_AC_VI_TXOP_STA 0x005e ++#define EDCF_AC_VO_TXOP_STA 0x002f ++#define EDCF_AC_BE_ACI_STA 0x03 ++#define EDCF_AC_BE_ECW_STA 0xA4 ++#define EDCF_AC_BK_ACI_STA 0x27 ++#define EDCF_AC_VO_TXOP_AP 0x002f ++ ++#define EDCF_TXOP2USEC(txop) ((txop) << 5) ++#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1) ++ ++#define APHY_SYMBOL_TIME 4 ++#define APHY_PREAMBLE_TIME 16 ++#define APHY_SIGNAL_TIME 4 ++#define APHY_SIFS_TIME 16 ++#define APHY_SERVICE_NBITS 16 ++#define APHY_TAIL_NBITS 6 ++#define BPHY_SIFS_TIME 10 ++#define BPHY_PLCP_SHORT_TIME 96 ++ ++#define PREN_PREAMBLE 24 ++#define PREN_MM_EXT 12 ++#define PREN_PREAMBLE_EXT 4 ++ ++#define DOT11_MAC_HDR_LEN 24 ++#define DOT11_ACK_LEN 10 ++#define DOT11_BA_LEN 4 ++#define DOT11_OFDM_SIGNAL_EXTENSION 6 ++#define DOT11_MIN_FRAG_LEN 256 ++#define DOT11_RTS_LEN 16 ++#define DOT11_CTS_LEN 10 ++#define DOT11_BA_BITMAP_LEN 128 ++#define DOT11_MIN_BEACON_PERIOD 1 ++#define DOT11_MAX_BEACON_PERIOD 0xFFFF ++#define DOT11_MAXNUMFRAGS 16 ++#define DOT11_MAX_FRAG_LEN 2346 ++ ++#define BPHY_PLCP_TIME 192 ++#define RIFS_11N_TIME 2 ++ ++#define WME_VER 1 ++#define WME_SUBTYPE_PARAM_IE 1 ++#define WME_TYPE 2 ++#define WME_OUI "\x00\x50\xf2" ++ ++#define AC_BE 0 ++#define AC_BK 1 ++#define AC_VI 2 ++#define AC_VO 3 ++ ++#define BCN_TMPL_LEN 512 /* length of the BCN template area */ ++ ++/* brcms_bss_info flag bit values */ ++#define BRCMS_BSS_HT 0x0020 /* BSS is HT (MIMO) capable */ ++ ++/* Flags used in brcms_c_txq_info.stopped */ ++/* per prio flow control bits */ ++#define TXQ_STOP_FOR_PRIOFC_MASK 0x000000FF ++/* stop txq enqueue for packet drain */ ++#define TXQ_STOP_FOR_PKT_DRAIN 0x00000100 ++/* stop txq enqueue for ampdu flow control */ ++#define TXQ_STOP_FOR_AMPDU_FLOW_CNTRL 0x00000200 ++ ++#define BRCMS_HWRXOFF 38 /* chip rx buffer offset */ ++ ++/* Find basic rate for a given rate */ ++static u8 brcms_basic_rate(struct brcms_c_info *wlc, u32 rspec) ++{ ++ if (is_mcs_rate(rspec)) ++ return wlc->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK] ++ .leg_ofdm]; ++ return wlc->band->basic_rate[rspec & RSPEC_RATE_MASK]; ++} ++ ++static u16 frametype(u32 rspec, u8 mimoframe) ++{ ++ if (is_mcs_rate(rspec)) ++ return mimoframe; ++ return is_cck_rate(rspec) ? FT_CCK : FT_OFDM; ++} ++ ++/* rfdisable delay timer 500 ms, runs of ALP clock */ ++#define RFDISABLE_DEFAULT 10000000 ++ ++#define BRCMS_TEMPSENSE_PERIOD 10 /* 10 second timeout */ ++ ++/* precedences numbers for wlc queues. These are twice as may levels as ++ * 802.1D priorities. ++ * Odd numbers are used for HI priority traffic at same precedence levels ++ * These constants are used ONLY by wlc_prio2prec_map. Do not use them ++ * elsewhere. ++ */ ++#define _BRCMS_PREC_NONE 0 /* None = - */ ++#define _BRCMS_PREC_BK 2 /* BK - Background */ ++#define _BRCMS_PREC_BE 4 /* BE - Best-effort */ ++#define _BRCMS_PREC_EE 6 /* EE - Excellent-effort */ ++#define _BRCMS_PREC_CL 8 /* CL - Controlled Load */ ++#define _BRCMS_PREC_VI 10 /* Vi - Video */ ++#define _BRCMS_PREC_VO 12 /* Vo - Voice */ ++#define _BRCMS_PREC_NC 14 /* NC - Network Control */ ++ ++/* The BSS is generating beacons in HW */ ++#define BRCMS_BSSCFG_HW_BCN 0x20 ++ ++#define SYNTHPU_DLY_APHY_US 3700 /* a phy synthpu_dly time in us */ ++#define SYNTHPU_DLY_BPHY_US 1050 /* b/g phy synthpu_dly time in us */ ++#define SYNTHPU_DLY_NPHY_US 2048 /* n phy REV3 synthpu_dly time in us */ ++#define SYNTHPU_DLY_LPPHY_US 300 /* lpphy synthpu_dly time in us */ ++ ++#define SYNTHPU_DLY_PHY_US_QT 100 /* QT synthpu_dly time in us */ ++ ++#define ANTCNT 10 /* vanilla M_MAX_ANTCNT value */ ++ ++/* Per-AC retry limit register definitions; uses defs.h bitfield macros */ ++#define EDCF_SHORT_S 0 ++#define EDCF_SFB_S 4 ++#define EDCF_LONG_S 8 ++#define EDCF_LFB_S 12 ++#define EDCF_SHORT_M BITFIELD_MASK(4) ++#define EDCF_SFB_M BITFIELD_MASK(4) ++#define EDCF_LONG_M BITFIELD_MASK(4) ++#define EDCF_LFB_M BITFIELD_MASK(4) ++ ++#define RETRY_SHORT_DEF 7 /* Default Short retry Limit */ ++#define RETRY_SHORT_MAX 255 /* Maximum Short retry Limit */ ++#define RETRY_LONG_DEF 4 /* Default Long retry count */ ++#define RETRY_SHORT_FB 3 /* Short count for fallback rate */ ++#define RETRY_LONG_FB 2 /* Long count for fallback rate */ ++ ++#define APHY_CWMIN 15 ++#define PHY_CWMAX 1023 ++ ++#define EDCF_AIFSN_MIN 1 ++ ++#define FRAGNUM_MASK 0xF ++ ++#define APHY_SLOT_TIME 9 ++#define BPHY_SLOT_TIME 20 ++ ++#define WL_SPURAVOID_OFF 0 ++#define WL_SPURAVOID_ON1 1 ++#define WL_SPURAVOID_ON2 2 ++ ++/* invalid core flags, use the saved coreflags */ ++#define BRCMS_USE_COREFLAGS 0xffffffff ++ ++/* values for PLCPHdr_override */ ++#define BRCMS_PLCP_AUTO -1 ++#define BRCMS_PLCP_SHORT 0 ++#define BRCMS_PLCP_LONG 1 ++ ++/* values for g_protection_override and n_protection_override */ ++#define BRCMS_PROTECTION_AUTO -1 ++#define BRCMS_PROTECTION_OFF 0 ++#define BRCMS_PROTECTION_ON 1 ++#define BRCMS_PROTECTION_MMHDR_ONLY 2 ++#define BRCMS_PROTECTION_CTS_ONLY 3 ++ ++/* values for g_protection_control and n_protection_control */ ++#define BRCMS_PROTECTION_CTL_OFF 0 ++#define BRCMS_PROTECTION_CTL_LOCAL 1 ++#define BRCMS_PROTECTION_CTL_OVERLAP 2 ++ ++/* values for n_protection */ ++#define BRCMS_N_PROTECTION_OFF 0 ++#define BRCMS_N_PROTECTION_OPTIONAL 1 ++#define BRCMS_N_PROTECTION_20IN40 2 ++#define BRCMS_N_PROTECTION_MIXEDMODE 3 ++ ++/* values for band specific 40MHz capabilities */ ++#define BRCMS_N_BW_20ALL 0 ++#define BRCMS_N_BW_40ALL 1 ++#define BRCMS_N_BW_20IN2G_40IN5G 2 ++ ++/* bitflags for SGI support (sgi_rx iovar) */ ++#define BRCMS_N_SGI_20 0x01 ++#define BRCMS_N_SGI_40 0x02 ++ ++/* defines used by the nrate iovar */ ++/* MSC in use,indicates b0-6 holds an mcs */ ++#define NRATE_MCS_INUSE 0x00000080 ++/* rate/mcs value */ ++#define NRATE_RATE_MASK 0x0000007f ++/* stf mode mask: siso, cdd, stbc, sdm */ ++#define NRATE_STF_MASK 0x0000ff00 ++/* stf mode shift */ ++#define NRATE_STF_SHIFT 8 ++/* bit indicates override both rate & mode */ ++#define NRATE_OVERRIDE 0x80000000 ++/* bit indicate to override mcs only */ ++#define NRATE_OVERRIDE_MCS_ONLY 0x40000000 ++#define NRATE_SGI_MASK 0x00800000 /* sgi mode */ ++#define NRATE_SGI_SHIFT 23 /* sgi mode */ ++#define NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */ ++#define NRATE_LDPC_SHIFT 22 /* ldpc shift */ ++ ++#define NRATE_STF_SISO 0 /* stf mode SISO */ ++#define NRATE_STF_CDD 1 /* stf mode CDD */ ++#define NRATE_STF_STBC 2 /* stf mode STBC */ ++#define NRATE_STF_SDM 3 /* stf mode SDM */ ++ ++#define MAX_DMA_SEGS 4 ++ ++/* Max # of entries in Tx FIFO based on 4kb page size */ ++#define NTXD 256 ++/* Max # of entries in Rx FIFO based on 4kb page size */ ++#define NRXD 256 ++ ++/* try to keep this # rbufs posted to the chip */ ++#define NRXBUFPOST 32 ++ ++/* data msg txq hiwat mark */ ++#define BRCMS_DATAHIWAT 50 ++ ++/* bounded rx loops */ ++#define RXBND 8 /* max # frames to process in brcms_c_recv() */ ++#define TXSBND 8 /* max # tx status to process in wlc_txstatus() */ ++ ++/* ++ * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL. ++ */ ++#define SSID_FMT_BUF_LEN ((4 * IEEE80211_MAX_SSID_LEN) + 1) ++ ++/* brcmu_format_flags() bit description structure */ ++struct brcms_c_bit_desc { ++ u32 bit; ++ const char *name; ++}; ++ ++/* ++ * The following table lists the buffer memory allocated to xmt fifos in HW. ++ * the size is in units of 256bytes(one block), total size is HW dependent ++ * ucode has default fifo partition, sw can overwrite if necessary ++ * ++ * This is documented in twiki under the topic UcodeTxFifo. Please ensure ++ * the twiki is updated before making changes. ++ */ ++ ++/* Starting corerev for the fifo size table */ ++#define XMTFIFOTBL_STARTREV 20 ++ ++struct d11init { ++ __le16 addr; ++ __le16 size; ++ __le32 value; ++}; ++ ++struct edcf_acparam { ++ u8 ACI; ++ u8 ECW; ++ u16 TXOP; ++} __packed; ++ ++const u8 prio2fifo[NUMPRIO] = { ++ TX_AC_BE_FIFO, /* 0 BE AC_BE Best Effort */ ++ TX_AC_BK_FIFO, /* 1 BK AC_BK Background */ ++ TX_AC_BK_FIFO, /* 2 -- AC_BK Background */ ++ TX_AC_BE_FIFO, /* 3 EE AC_BE Best Effort */ ++ TX_AC_VI_FIFO, /* 4 CL AC_VI Video */ ++ TX_AC_VI_FIFO, /* 5 VI AC_VI Video */ ++ TX_AC_VO_FIFO, /* 6 VO AC_VO Voice */ ++ TX_AC_VO_FIFO /* 7 NC AC_VO Voice */ ++}; ++ ++/* debug/trace */ ++uint brcm_msg_level = ++#if defined(BCMDBG) ++ LOG_ERROR_VAL; ++#else ++ 0; ++#endif /* BCMDBG */ ++ ++/* TX FIFO number to WME/802.1E Access Category */ ++static const u8 wme_fifo2ac[] = { AC_BK, AC_BE, AC_VI, AC_VO, AC_BE, AC_BE }; ++ ++/* WME/802.1E Access Category to TX FIFO number */ ++static const u8 wme_ac2fifo[] = { 1, 0, 2, 3 }; ++ ++/* 802.1D Priority to precedence queue mapping */ ++const u8 wlc_prio2prec_map[] = { ++ _BRCMS_PREC_BE, /* 0 BE - Best-effort */ ++ _BRCMS_PREC_BK, /* 1 BK - Background */ ++ _BRCMS_PREC_NONE, /* 2 None = - */ ++ _BRCMS_PREC_EE, /* 3 EE - Excellent-effort */ ++ _BRCMS_PREC_CL, /* 4 CL - Controlled Load */ ++ _BRCMS_PREC_VI, /* 5 Vi - Video */ ++ _BRCMS_PREC_VO, /* 6 Vo - Voice */ ++ _BRCMS_PREC_NC, /* 7 NC - Network Control */ ++}; ++ ++static const u16 xmtfifo_sz[][NFIFO] = { ++ /* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */ ++ {20, 192, 192, 21, 17, 5}, ++ /* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */ ++ {9, 58, 22, 14, 14, 5}, ++ /* corerev 22: 5120, 49152, 49152, 5376, 4352, 1280 */ ++ {20, 192, 192, 21, 17, 5}, ++ /* corerev 23: 5120, 49152, 49152, 5376, 4352, 1280 */ ++ {20, 192, 192, 21, 17, 5}, ++ /* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */ ++ {9, 58, 22, 14, 14, 5}, ++}; ++ ++static const u8 acbitmap2maxprio[] = { ++ PRIO_8021D_BE, PRIO_8021D_BE, PRIO_8021D_BK, PRIO_8021D_BK, ++ PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, ++ PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, ++ PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO ++}; ++ ++#ifdef BCMDBG ++static const char * const fifo_names[] = { ++ "AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" }; ++#else ++static const char fifo_names[6][0]; ++#endif ++ ++#ifdef BCMDBG ++/* pointer to most recently allocated wl/wlc */ ++static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL); ++#endif ++ ++/* currently the best mechanism for determining SIFS is the band in use */ ++static u16 get_sifs(struct brcms_band *band) ++{ ++ return band->bandtype == BRCM_BAND_5G ? APHY_SIFS_TIME : ++ BPHY_SIFS_TIME; ++} ++ ++/* ++ * Detect Card removed. ++ * Even checking an sbconfig register read will not false trigger when the core ++ * is in reset it breaks CF address mechanism. Accessing gphy phyversion will ++ * cause SB error if aphy is in reset on 4306B0-DB. Need a simple accessible ++ * reg with fixed 0/1 pattern (some platforms return all 0). ++ * If clocks are present, call the sb routine which will figure out if the ++ * device is removed. ++ */ ++static bool brcms_deviceremoved(struct brcms_c_info *wlc) ++{ ++ if (!wlc->hw->clk) ++ return ai_deviceremoved(wlc->hw->sih); ++ return (R_REG(&wlc->hw->regs->maccontrol) & ++ (MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN; ++} ++ ++/* sum the individual fifo tx pending packet counts */ ++static s16 brcms_txpktpendtot(struct brcms_c_info *wlc) ++{ ++ return wlc->core->txpktpend[0] + wlc->core->txpktpend[1] + ++ wlc->core->txpktpend[2] + wlc->core->txpktpend[3]; ++} ++ ++static bool brcms_is_mband_unlocked(struct brcms_c_info *wlc) ++{ ++ return wlc->pub->_nbands > 1 && !wlc->bandlocked; ++} ++ ++static int brcms_chspec_bw(u16 chanspec) ++{ ++ if (CHSPEC_IS40(chanspec)) ++ return BRCMS_40_MHZ; ++ if (CHSPEC_IS20(chanspec)) ++ return BRCMS_20_MHZ; ++ ++ return BRCMS_10_MHZ; ++} ++ ++/* ++ * return true if Minimum Power Consumption should ++ * be entered, false otherwise ++ */ ++static bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc) ++{ ++ return false; ++} ++ ++static bool brcms_c_ismpc(struct brcms_c_info *wlc) ++{ ++ return (wlc->mpc_delay_off == 0) && (brcms_c_is_non_delay_mpc(wlc)); ++} ++ ++static void brcms_c_bsscfg_mfree(struct brcms_bss_cfg *cfg) ++{ ++ if (cfg == NULL) ++ return; ++ ++ kfree(cfg->current_bss); ++ kfree(cfg); ++} ++ ++static void brcms_c_detach_mfree(struct brcms_c_info *wlc) ++{ ++ if (wlc == NULL) ++ return; ++ ++ brcms_c_bsscfg_mfree(wlc->bsscfg); ++ kfree(wlc->pub); ++ kfree(wlc->modulecb); ++ kfree(wlc->default_bss); ++ kfree(wlc->protection); ++ kfree(wlc->stf); ++ kfree(wlc->bandstate[0]); ++ kfree(wlc->corestate->macstat_snapshot); ++ kfree(wlc->corestate); ++ kfree(wlc->hw->bandstate[0]); ++ kfree(wlc->hw); ++ ++ /* free the wlc */ ++ kfree(wlc); ++ wlc = NULL; ++} ++ ++static struct brcms_bss_cfg *brcms_c_bsscfg_malloc(uint unit) ++{ ++ struct brcms_bss_cfg *cfg; ++ ++ cfg = kzalloc(sizeof(struct brcms_bss_cfg), GFP_ATOMIC); ++ if (cfg == NULL) ++ goto fail; ++ ++ cfg->current_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC); ++ if (cfg->current_bss == NULL) ++ goto fail; ++ ++ return cfg; ++ ++ fail: ++ brcms_c_bsscfg_mfree(cfg); ++ return NULL; ++} ++ ++static struct brcms_c_info * ++brcms_c_attach_malloc(uint unit, uint *err, uint devid) ++{ ++ struct brcms_c_info *wlc; ++ ++ wlc = kzalloc(sizeof(struct brcms_c_info), GFP_ATOMIC); ++ if (wlc == NULL) { ++ *err = 1002; ++ goto fail; ++ } ++ ++ /* allocate struct brcms_c_pub state structure */ ++ wlc->pub = kzalloc(sizeof(struct brcms_pub), GFP_ATOMIC); ++ if (wlc->pub == NULL) { ++ *err = 1003; ++ goto fail; ++ } ++ wlc->pub->wlc = wlc; ++ ++ /* allocate struct brcms_hardware state structure */ ++ ++ wlc->hw = kzalloc(sizeof(struct brcms_hardware), GFP_ATOMIC); ++ if (wlc->hw == NULL) { ++ *err = 1005; ++ goto fail; ++ } ++ wlc->hw->wlc = wlc; ++ ++ wlc->hw->bandstate[0] = ++ kzalloc(sizeof(struct brcms_hw_band) * MAXBANDS, GFP_ATOMIC); ++ if (wlc->hw->bandstate[0] == NULL) { ++ *err = 1006; ++ goto fail; ++ } else { ++ int i; ++ ++ for (i = 1; i < MAXBANDS; i++) ++ wlc->hw->bandstate[i] = (struct brcms_hw_band *) ++ ((unsigned long)wlc->hw->bandstate[0] + ++ (sizeof(struct brcms_hw_band) * i)); ++ } ++ ++ wlc->modulecb = ++ kzalloc(sizeof(struct modulecb) * BRCMS_MAXMODULES, GFP_ATOMIC); ++ if (wlc->modulecb == NULL) { ++ *err = 1009; ++ goto fail; ++ } ++ ++ wlc->default_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC); ++ if (wlc->default_bss == NULL) { ++ *err = 1010; ++ goto fail; ++ } ++ ++ wlc->bsscfg = brcms_c_bsscfg_malloc(unit); ++ if (wlc->bsscfg == NULL) { ++ *err = 1011; ++ goto fail; ++ } ++ ++ wlc->protection = kzalloc(sizeof(struct brcms_protection), ++ GFP_ATOMIC); ++ if (wlc->protection == NULL) { ++ *err = 1016; ++ goto fail; ++ } ++ ++ wlc->stf = kzalloc(sizeof(struct brcms_stf), GFP_ATOMIC); ++ if (wlc->stf == NULL) { ++ *err = 1017; ++ goto fail; ++ } ++ ++ wlc->bandstate[0] = ++ kzalloc(sizeof(struct brcms_band)*MAXBANDS, GFP_ATOMIC); ++ if (wlc->bandstate[0] == NULL) { ++ *err = 1025; ++ goto fail; ++ } else { ++ int i; ++ ++ for (i = 1; i < MAXBANDS; i++) ++ wlc->bandstate[i] = (struct brcms_band *) ++ ((unsigned long)wlc->bandstate[0] ++ + (sizeof(struct brcms_band)*i)); ++ } ++ ++ wlc->corestate = kzalloc(sizeof(struct brcms_core), GFP_ATOMIC); ++ if (wlc->corestate == NULL) { ++ *err = 1026; ++ goto fail; ++ } ++ ++ wlc->corestate->macstat_snapshot = ++ kzalloc(sizeof(struct macstat), GFP_ATOMIC); ++ if (wlc->corestate->macstat_snapshot == NULL) { ++ *err = 1027; ++ goto fail; ++ } ++ ++ return wlc; ++ ++ fail: ++ brcms_c_detach_mfree(wlc); ++ return NULL; ++} ++ ++/* ++ * Update the slot timing for standard 11b/g (20us slots) ++ * or shortslot 11g (9us slots) ++ * The PSM needs to be suspended for this call. ++ */ ++static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw, ++ bool shortslot) ++{ ++ struct d11regs __iomem *regs; ++ ++ regs = wlc_hw->regs; ++ ++ if (shortslot) { ++ /* 11g short slot: 11a timing */ ++ W_REG(®s->ifs_slot, 0x0207); /* APHY_SLOT_TIME */ ++ brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME); ++ } else { ++ /* 11g long slot: 11b timing */ ++ W_REG(®s->ifs_slot, 0x0212); /* BPHY_SLOT_TIME */ ++ brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME); ++ } ++} ++ ++/* ++ * calculate frame duration of a given rate and length, return ++ * time in usec unit ++ */ ++uint ++brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec, ++ u8 preamble_type, uint mac_len) ++{ ++ uint nsyms, dur = 0, Ndps, kNdps; ++ uint rate = rspec2rate(ratespec); ++ ++ if (rate == 0) { ++ wiphy_err(wlc->wiphy, "wl%d: WAR: using rate of 1 mbps\n", ++ wlc->pub->unit); ++ rate = BRCM_RATE_1M; ++ } ++ ++ BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, len%d\n", ++ wlc->pub->unit, ratespec, preamble_type, mac_len); ++ ++ if (is_mcs_rate(ratespec)) { ++ uint mcs = ratespec & RSPEC_RATE_MASK; ++ int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec); ++ ++ dur = PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT); ++ if (preamble_type == BRCMS_MM_PREAMBLE) ++ dur += PREN_MM_EXT; ++ /* 1000Ndbps = kbps * 4 */ ++ kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec), ++ rspec_issgi(ratespec)) * 4; ++ ++ if (rspec_stc(ratespec) == 0) ++ nsyms = ++ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + ++ APHY_TAIL_NBITS) * 1000, kNdps); ++ else ++ /* STBC needs to have even number of symbols */ ++ nsyms = ++ 2 * ++ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + ++ APHY_TAIL_NBITS) * 1000, 2 * kNdps); ++ ++ dur += APHY_SYMBOL_TIME * nsyms; ++ if (wlc->band->bandtype == BRCM_BAND_2G) ++ dur += DOT11_OFDM_SIGNAL_EXTENSION; ++ } else if (is_ofdm_rate(rate)) { ++ dur = APHY_PREAMBLE_TIME; ++ dur += APHY_SIGNAL_TIME; ++ /* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */ ++ Ndps = rate * 2; ++ /* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */ ++ nsyms = ++ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS), ++ Ndps); ++ dur += APHY_SYMBOL_TIME * nsyms; ++ if (wlc->band->bandtype == BRCM_BAND_2G) ++ dur += DOT11_OFDM_SIGNAL_EXTENSION; ++ } else { ++ /* ++ * calc # bits * 2 so factor of 2 in rate (1/2 mbps) ++ * will divide out ++ */ ++ mac_len = mac_len * 8 * 2; ++ /* calc ceiling of bits/rate = microseconds of air time */ ++ dur = (mac_len + rate - 1) / rate; ++ if (preamble_type & BRCMS_SHORT_PREAMBLE) ++ dur += BPHY_PLCP_SHORT_TIME; ++ else ++ dur += BPHY_PLCP_TIME; ++ } ++ return dur; ++} ++ ++static void brcms_c_write_inits(struct brcms_hardware *wlc_hw, ++ const struct d11init *inits) ++{ ++ int i; ++ u8 __iomem *base; ++ u8 __iomem *addr; ++ u16 size; ++ u32 value; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ base = (u8 __iomem *)wlc_hw->regs; ++ ++ for (i = 0; inits[i].addr != cpu_to_le16(0xffff); i++) { ++ size = le16_to_cpu(inits[i].size); ++ addr = base + le16_to_cpu(inits[i].addr); ++ value = le32_to_cpu(inits[i].value); ++ if (size == 2) ++ W_REG((u16 __iomem *)addr, value); ++ else if (size == 4) ++ W_REG((u32 __iomem *)addr, value); ++ else ++ break; ++ } ++} ++ ++static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs) ++{ ++ u8 idx; ++ u16 addr[] = { ++ M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4, ++ M_HOST_FLAGS5 ++ }; ++ ++ for (idx = 0; idx < MHFMAX; idx++) ++ brcms_b_write_shm(wlc_hw, addr[idx], mhfs[idx]); ++} ++ ++static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw) ++{ ++ struct wiphy *wiphy = wlc_hw->wlc->wiphy; ++ struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode; ++ ++ /* init microcode host flags */ ++ brcms_c_write_mhf(wlc_hw, wlc_hw->band->mhfs); ++ ++ /* do band-specific ucode IHR, SHM, and SCR inits */ ++ if (D11REV_IS(wlc_hw->corerev, 23)) { ++ if (BRCMS_ISNPHY(wlc_hw->band)) ++ brcms_c_write_inits(wlc_hw, ucode->d11n0bsinitvals16); ++ else ++ wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" ++ " %d\n", __func__, wlc_hw->unit, ++ wlc_hw->corerev); ++ } else { ++ if (D11REV_IS(wlc_hw->corerev, 24)) { ++ if (BRCMS_ISLCNPHY(wlc_hw->band)) ++ brcms_c_write_inits(wlc_hw, ++ ucode->d11lcn0bsinitvals24); ++ else ++ wiphy_err(wiphy, "%s: wl%d: unsupported phy in" ++ " core rev %d\n", __func__, ++ wlc_hw->unit, wlc_hw->corerev); ++ } else { ++ wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n", ++ __func__, wlc_hw->unit, wlc_hw->corerev); ++ } ++ } ++} ++ ++static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk) ++{ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk); ++ ++ wlc_hw->phyclk = clk; ++ ++ if (OFF == clk) { /* clear gmode bit, put phy into reset */ ++ ++ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE), ++ (SICF_PRST | SICF_FGC)); ++ udelay(1); ++ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST); ++ udelay(1); ++ ++ } else { /* take phy out of reset */ ++ ++ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC); ++ udelay(1); ++ ai_core_cflags(wlc_hw->sih, (SICF_FGC), 0); ++ udelay(1); ++ ++ } ++} ++ ++/* low-level band switch utility routine */ ++static void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit) ++{ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, ++ bandunit); ++ ++ wlc_hw->band = wlc_hw->bandstate[bandunit]; ++ ++ /* ++ * BMAC_NOTE: ++ * until we eliminate need for wlc->band refs in low level code ++ */ ++ wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit]; ++ ++ /* set gmode core flag */ ++ if (wlc_hw->sbclk && !wlc_hw->noreset) ++ ai_core_cflags(wlc_hw->sih, SICF_GMODE, ++ ((bandunit == 0) ? SICF_GMODE : 0)); ++} ++ ++/* switch to new band but leave it inactive */ ++static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ u32 macintmask; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0); ++ ++ /* disable interrupts */ ++ macintmask = brcms_intrsoff(wlc->wl); ++ ++ /* radio off */ ++ wlc_phy_switch_radio(wlc_hw->band->pi, OFF); ++ ++ brcms_b_core_phy_clk(wlc_hw, OFF); ++ ++ brcms_c_setxband(wlc_hw, bandunit); ++ ++ return macintmask; ++} ++ ++/* process an individual struct tx_status */ ++static bool ++brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs) ++{ ++ struct sk_buff *p; ++ uint queue; ++ struct d11txh *txh; ++ struct scb *scb = NULL; ++ bool free_pdu; ++ int tx_rts, tx_frame_count, tx_rts_count; ++ uint totlen, supr_status; ++ bool lastframe; ++ struct ieee80211_hdr *h; ++ u16 mcl; ++ struct ieee80211_tx_info *tx_info; ++ struct ieee80211_tx_rate *txrate; ++ int i; ++ ++ /* discard intermediate indications for ucode with one legitimate case: ++ * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, ++ * but the subsequent tx of DATA failed. so it will start rts/cts ++ * from the beginning (resetting the rts transmission count) ++ */ ++ if (!(txs->status & TX_STATUS_AMPDU) ++ && (txs->status & TX_STATUS_INTERMEDIATE)) { ++ wiphy_err(wlc->wiphy, "%s: INTERMEDIATE but not AMPDU\n", ++ __func__); ++ return false; ++ } ++ ++ queue = txs->frameid & TXFID_QUEUE_MASK; ++ if (queue >= NFIFO) { ++ p = NULL; ++ goto fatal; ++ } ++ ++ p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED); ++ if (p == NULL) ++ goto fatal; ++ ++ txh = (struct d11txh *) (p->data); ++ mcl = le16_to_cpu(txh->MacTxControlLow); ++ ++ if (txs->phyerr) { ++ if (brcm_msg_level & LOG_ERROR_VAL) { ++ wiphy_err(wlc->wiphy, "phyerr 0x%x, rate 0x%x\n", ++ txs->phyerr, txh->MainRates); ++ brcms_c_print_txdesc(txh); ++ } ++ brcms_c_print_txstatus(txs); ++ } ++ ++ if (txs->frameid != le16_to_cpu(txh->TxFrameID)) ++ goto fatal; ++ tx_info = IEEE80211_SKB_CB(p); ++ h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN); ++ ++ if (tx_info->control.sta) ++ scb = &wlc->pri_scb; ++ ++ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { ++ brcms_c_ampdu_dotxstatus(wlc->ampdu, scb, p, txs); ++ return false; ++ } ++ ++ supr_status = txs->status & TX_STATUS_SUPR_MASK; ++ if (supr_status == TX_STATUS_SUPR_BADCH) ++ BCMMSG(wlc->wiphy, ++ "%s: Pkt tx suppressed, possibly channel %d\n", ++ __func__, CHSPEC_CHANNEL(wlc->default_bss->chanspec)); ++ ++ tx_rts = le16_to_cpu(txh->MacTxControlLow) & TXC_SENDRTS; ++ tx_frame_count = ++ (txs->status & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT; ++ tx_rts_count = ++ (txs->status & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT; ++ ++ lastframe = !ieee80211_has_morefrags(h->frame_control); ++ ++ if (!lastframe) { ++ wiphy_err(wlc->wiphy, "Not last frame!\n"); ++ } else { ++ /* ++ * Set information to be consumed by Minstrel ht. ++ * ++ * The "fallback limit" is the number of tx attempts a given ++ * MPDU is sent at the "primary" rate. Tx attempts beyond that ++ * limit are sent at the "secondary" rate. ++ * A 'short frame' does not exceed RTS treshold. ++ */ ++ u16 sfbl, /* Short Frame Rate Fallback Limit */ ++ lfbl, /* Long Frame Rate Fallback Limit */ ++ fbl; ++ ++ if (queue < AC_COUNT) { ++ sfbl = GFIELD(wlc->wme_retries[wme_fifo2ac[queue]], ++ EDCF_SFB); ++ lfbl = GFIELD(wlc->wme_retries[wme_fifo2ac[queue]], ++ EDCF_LFB); ++ } else { ++ sfbl = wlc->SFBL; ++ lfbl = wlc->LFBL; ++ } ++ ++ txrate = tx_info->status.rates; ++ if (txrate[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ++ fbl = lfbl; ++ else ++ fbl = sfbl; ++ ++ ieee80211_tx_info_clear_status(tx_info); ++ ++ if ((tx_frame_count > fbl) && (txrate[1].idx >= 0)) { ++ /* ++ * rate selection requested a fallback rate ++ * and we used it ++ */ ++ txrate[0].count = fbl; ++ txrate[1].count = tx_frame_count - fbl; ++ } else { ++ /* ++ * rate selection did not request fallback rate, or ++ * we didn't need it ++ */ ++ txrate[0].count = tx_frame_count; ++ /* ++ * rc80211_minstrel.c:minstrel_tx_status() expects ++ * unused rates to be marked with idx = -1 ++ */ ++ txrate[1].idx = -1; ++ txrate[1].count = 0; ++ } ++ ++ /* clear the rest of the rates */ ++ for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) { ++ txrate[i].idx = -1; ++ txrate[i].count = 0; ++ } ++ ++ if (txs->status & TX_STATUS_ACK_RCV) ++ tx_info->flags |= IEEE80211_TX_STAT_ACK; ++ } ++ ++ totlen = brcmu_pkttotlen(p); ++ free_pdu = true; ++ ++ brcms_c_txfifo_complete(wlc, queue, 1); ++ ++ if (lastframe) { ++ p->next = NULL; ++ p->prev = NULL; ++ /* remove PLCP & Broadcom tx descriptor header */ ++ skb_pull(p, D11_PHY_HDR_LEN); ++ skb_pull(p, D11_TXH_LEN); ++ ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, p); ++ } else { ++ wiphy_err(wlc->wiphy, "%s: Not last frame => not calling " ++ "tx_status\n", __func__); ++ } ++ ++ return false; ++ ++ fatal: ++ if (p) ++ brcmu_pkt_buf_free_skb(p); ++ ++ return true; ++ ++} ++ ++/* process tx completion events in BMAC ++ * Return true if more tx status need to be processed. false otherwise. ++ */ ++static bool ++brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) ++{ ++ bool morepending = false; ++ struct brcms_c_info *wlc = wlc_hw->wlc; ++ struct d11regs __iomem *regs; ++ struct tx_status txstatus, *txs; ++ u32 s1, s2; ++ uint n = 0; ++ /* ++ * Param 'max_tx_num' indicates max. # tx status to process before ++ * break out. ++ */ ++ uint max_tx_num = bound ? TXSBND : -1; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ txs = &txstatus; ++ regs = wlc_hw->regs; ++ *fatal = false; ++ while (!(*fatal) ++ && (s1 = R_REG(®s->frmtxstatus)) & TXS_V) { ++ ++ if (s1 == 0xffffffff) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", ++ wlc_hw->unit, __func__); ++ return morepending; ++ } ++ ++ s2 = R_REG(®s->frmtxstatus2); ++ ++ txs->status = s1 & TXS_STATUS_MASK; ++ txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT; ++ txs->sequence = s2 & TXS_SEQ_MASK; ++ txs->phyerr = (s2 & TXS_PTX_MASK) >> TXS_PTX_SHIFT; ++ txs->lasttxtime = 0; ++ ++ *fatal = brcms_c_dotxstatus(wlc_hw->wlc, txs); ++ ++ /* !give others some time to run! */ ++ if (++n >= max_tx_num) ++ break; ++ } ++ ++ if (*fatal) ++ return 0; ++ ++ if (n >= max_tx_num) ++ morepending = true; ++ ++ if (!pktq_empty(&wlc->pkt_queue->q)) ++ brcms_c_send_q(wlc); ++ ++ return morepending; ++} ++ ++static void brcms_c_tbtt(struct brcms_c_info *wlc) ++{ ++ if (!wlc->bsscfg->BSS) ++ /* ++ * DirFrmQ is now valid...defer setting until end ++ * of ATIM window ++ */ ++ wlc->qvalid |= MCMD_DIRFRMQVAL; ++} ++ ++/* set initial host flags value */ ++static void ++brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ ++ memset(mhfs, 0, MHFMAX * sizeof(u16)); ++ ++ mhfs[MHF2] |= mhf2_init; ++ ++ /* prohibit use of slowclock on multifunction boards */ ++ if (wlc_hw->boardflags & BFL_NOPLLDOWN) ++ mhfs[MHF1] |= MHF1_FORCEFASTCLK; ++ ++ if (BRCMS_ISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 2)) { ++ mhfs[MHF2] |= MHF2_NPHY40MHZ_WAR; ++ mhfs[MHF1] |= MHF1_IQSWAP_WAR; ++ } ++} ++ ++static struct dma64regs __iomem * ++dmareg(struct brcms_hardware *hw, uint direction, uint fifonum) ++{ ++ if (direction == DMA_TX) ++ return &(hw->regs->fifo64regs[fifonum].dmaxmt); ++ return &(hw->regs->fifo64regs[fifonum].dmarcv); ++} ++ ++static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme) ++{ ++ uint i; ++ char name[8]; ++ /* ++ * ucode host flag 2 needed for pio mode, independent of band and fifo ++ */ ++ u16 pio_mhf2 = 0; ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ uint unit = wlc_hw->unit; ++ struct wiphy *wiphy = wlc->wiphy; ++ ++ /* name and offsets for dma_attach */ ++ snprintf(name, sizeof(name), "wl%d", unit); ++ ++ if (wlc_hw->di[0] == NULL) { /* Init FIFOs */ ++ int dma_attach_err = 0; ++ ++ /* ++ * FIFO 0 ++ * TX: TX_AC_BK_FIFO (TX AC Background data packets) ++ * RX: RX_FIFO (RX data packets) ++ */ ++ wlc_hw->di[0] = dma_attach(name, wlc_hw->sih, ++ (wme ? dmareg(wlc_hw, DMA_TX, 0) : ++ NULL), dmareg(wlc_hw, DMA_RX, 0), ++ (wme ? NTXD : 0), NRXD, ++ RXBUFSZ, -1, NRXBUFPOST, ++ BRCMS_HWRXOFF, &brcm_msg_level); ++ dma_attach_err |= (NULL == wlc_hw->di[0]); ++ ++ /* ++ * FIFO 1 ++ * TX: TX_AC_BE_FIFO (TX AC Best-Effort data packets) ++ * (legacy) TX_DATA_FIFO (TX data packets) ++ * RX: UNUSED ++ */ ++ wlc_hw->di[1] = dma_attach(name, wlc_hw->sih, ++ dmareg(wlc_hw, DMA_TX, 1), NULL, ++ NTXD, 0, 0, -1, 0, 0, ++ &brcm_msg_level); ++ dma_attach_err |= (NULL == wlc_hw->di[1]); ++ ++ /* ++ * FIFO 2 ++ * TX: TX_AC_VI_FIFO (TX AC Video data packets) ++ * RX: UNUSED ++ */ ++ wlc_hw->di[2] = dma_attach(name, wlc_hw->sih, ++ dmareg(wlc_hw, DMA_TX, 2), NULL, ++ NTXD, 0, 0, -1, 0, 0, ++ &brcm_msg_level); ++ dma_attach_err |= (NULL == wlc_hw->di[2]); ++ /* ++ * FIFO 3 ++ * TX: TX_AC_VO_FIFO (TX AC Voice data packets) ++ * (legacy) TX_CTL_FIFO (TX control & mgmt packets) ++ */ ++ wlc_hw->di[3] = dma_attach(name, wlc_hw->sih, ++ dmareg(wlc_hw, DMA_TX, 3), ++ NULL, NTXD, 0, 0, -1, ++ 0, 0, &brcm_msg_level); ++ dma_attach_err |= (NULL == wlc_hw->di[3]); ++/* Cleaner to leave this as if with AP defined */ ++ ++ if (dma_attach_err) { ++ wiphy_err(wiphy, "wl%d: wlc_attach: dma_attach failed" ++ "\n", unit); ++ return false; ++ } ++ ++ /* get pointer to dma engine tx flow control variable */ ++ for (i = 0; i < NFIFO; i++) ++ if (wlc_hw->di[i]) ++ wlc_hw->txavail[i] = ++ (uint *) dma_getvar(wlc_hw->di[i], ++ "&txavail"); ++ } ++ ++ /* initial ucode host flags */ ++ brcms_c_mhfdef(wlc, wlc_hw->band->mhfs, pio_mhf2); ++ ++ return true; ++} ++ ++static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw) ++{ ++ uint j; ++ ++ for (j = 0; j < NFIFO; j++) { ++ if (wlc_hw->di[j]) { ++ dma_detach(wlc_hw->di[j]); ++ wlc_hw->di[j] = NULL; ++ } ++ } ++} ++ ++/* ++ * Initialize brcms_c_info default values ... ++ * may get overrides later in this function ++ * BMAC_NOTES, move low out and resolve the dangling ones ++ */ ++static void brcms_b_info_init(struct brcms_hardware *wlc_hw) ++{ ++ struct brcms_c_info *wlc = wlc_hw->wlc; ++ ++ /* set default sw macintmask value */ ++ wlc->defmacintmask = DEF_MACINTMASK; ++ ++ /* various 802.11g modes */ ++ wlc_hw->shortslot = false; ++ ++ wlc_hw->SFBL = RETRY_SHORT_FB; ++ wlc_hw->LFBL = RETRY_LONG_FB; ++ ++ /* default mac retry limits */ ++ wlc_hw->SRL = RETRY_SHORT_DEF; ++ wlc_hw->LRL = RETRY_LONG_DEF; ++ wlc_hw->chanspec = ch20mhz_chspec(1); ++} ++ ++static void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw) ++{ ++ /* delay before first read of ucode state */ ++ udelay(40); ++ ++ /* wait until ucode is no longer asleep */ ++ SPINWAIT((brcms_b_read_shm(wlc_hw, M_UCODE_DBGST) == ++ DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly); ++} ++ ++/* control chip clock to save power, enable dynamic clock or force fast clock */ ++static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode) ++{ ++ if (wlc_hw->sih->cccaps & CC_CAP_PMU) { ++ /* new chips with PMU, CCS_FORCEHT will distribute the HT clock ++ * on backplane, but mac core will still run on ALP(not HT) when ++ * it enters powersave mode, which means the FCA bit may not be ++ * set. Should wakeup mac if driver wants it to run on HT. ++ */ ++ ++ if (wlc_hw->clk) { ++ if (mode == CLK_FAST) { ++ OR_REG(&wlc_hw->regs->clk_ctl_st, ++ CCS_FORCEHT); ++ ++ udelay(64); ++ ++ SPINWAIT(((R_REG ++ (&wlc_hw->regs-> ++ clk_ctl_st) & CCS_HTAVAIL) == 0), ++ PMU_MAX_TRANSITION_DLY); ++ WARN_ON(!(R_REG ++ (&wlc_hw->regs-> ++ clk_ctl_st) & CCS_HTAVAIL)); ++ } else { ++ if ((wlc_hw->sih->pmurev == 0) && ++ (R_REG ++ (&wlc_hw->regs-> ++ clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ))) ++ SPINWAIT(((R_REG ++ (&wlc_hw->regs-> ++ clk_ctl_st) & CCS_HTAVAIL) ++ == 0), ++ PMU_MAX_TRANSITION_DLY); ++ AND_REG(&wlc_hw->regs->clk_ctl_st, ++ ~CCS_FORCEHT); ++ } ++ } ++ wlc_hw->forcefastclk = (mode == CLK_FAST); ++ } else { ++ ++ /* old chips w/o PMU, force HT through cc, ++ * then use FCA to verify mac is running fast clock ++ */ ++ ++ wlc_hw->forcefastclk = ai_clkctl_cc(wlc_hw->sih, mode); ++ ++ /* check fast clock is available (if core is not in reset) */ ++ if (wlc_hw->forcefastclk && wlc_hw->clk) ++ WARN_ON(!(ai_core_sflags(wlc_hw->sih, 0, 0) & ++ SISF_FCLKA)); ++ ++ /* ++ * keep the ucode wake bit on if forcefastclk is on since we ++ * do not want ucode to put us back to slow clock when it dozes ++ * for PM mode. Code below matches the wake override bit with ++ * current forcefastclk state. Only setting bit in wake_override ++ * instead of waking ucode immediately since old code had this ++ * behavior. Older code set wlc->forcefastclk but only had the ++ * wake happen if the wakup_ucode work (protected by an up ++ * check) was executed just below. ++ */ ++ if (wlc_hw->forcefastclk) ++ mboolset(wlc_hw->wake_override, ++ BRCMS_WAKE_OVERRIDE_FORCEFAST); ++ else ++ mboolclr(wlc_hw->wake_override, ++ BRCMS_WAKE_OVERRIDE_FORCEFAST); ++ } ++} ++ ++/* set or clear ucode host flag bits ++ * it has an optimization for no-change write ++ * it only writes through shared memory when the core has clock; ++ * pre-CLK changes should use wlc_write_mhf to get around the optimization ++ * ++ * ++ * bands values are: BRCM_BAND_AUTO <--- Current band only ++ * BRCM_BAND_5G <--- 5G band only ++ * BRCM_BAND_2G <--- 2G band only ++ * BRCM_BAND_ALL <--- All bands ++ */ ++void ++brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val, ++ int bands) ++{ ++ u16 save; ++ u16 addr[MHFMAX] = { ++ M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4, ++ M_HOST_FLAGS5 ++ }; ++ struct brcms_hw_band *band; ++ ++ if ((val & ~mask) || idx >= MHFMAX) ++ return; /* error condition */ ++ ++ switch (bands) { ++ /* Current band only or all bands, ++ * then set the band to current band ++ */ ++ case BRCM_BAND_AUTO: ++ case BRCM_BAND_ALL: ++ band = wlc_hw->band; ++ break; ++ case BRCM_BAND_5G: ++ band = wlc_hw->bandstate[BAND_5G_INDEX]; ++ break; ++ case BRCM_BAND_2G: ++ band = wlc_hw->bandstate[BAND_2G_INDEX]; ++ break; ++ default: ++ band = NULL; /* error condition */ ++ } ++ ++ if (band) { ++ save = band->mhfs[idx]; ++ band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val; ++ ++ /* optimization: only write through if changed, and ++ * changed band is the current band ++ */ ++ if (wlc_hw->clk && (band->mhfs[idx] != save) ++ && (band == wlc_hw->band)) ++ brcms_b_write_shm(wlc_hw, addr[idx], ++ (u16) band->mhfs[idx]); ++ } ++ ++ if (bands == BRCM_BAND_ALL) { ++ wlc_hw->bandstate[0]->mhfs[idx] = ++ (wlc_hw->bandstate[0]->mhfs[idx] & ~mask) | val; ++ wlc_hw->bandstate[1]->mhfs[idx] = ++ (wlc_hw->bandstate[1]->mhfs[idx] & ~mask) | val; ++ } ++} ++ ++/* set the maccontrol register to desired reset state and ++ * initialize the sw cache of the register ++ */ ++static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw) ++{ ++ /* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */ ++ wlc_hw->maccontrol = 0; ++ wlc_hw->suspended_fifos = 0; ++ wlc_hw->wake_override = 0; ++ wlc_hw->mute_override = 0; ++ brcms_b_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE); ++} ++ ++/* ++ * write the software state of maccontrol and ++ * overrides to the maccontrol register ++ */ ++static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw) ++{ ++ u32 maccontrol = wlc_hw->maccontrol; ++ ++ /* OR in the wake bit if overridden */ ++ if (wlc_hw->wake_override) ++ maccontrol |= MCTL_WAKE; ++ ++ /* set AP and INFRA bits for mute if needed */ ++ if (wlc_hw->mute_override) { ++ maccontrol &= ~(MCTL_AP); ++ maccontrol |= MCTL_INFRA; ++ } ++ ++ W_REG(&wlc_hw->regs->maccontrol, maccontrol); ++} ++ ++/* set or clear maccontrol bits */ ++void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val) ++{ ++ u32 maccontrol; ++ u32 new_maccontrol; ++ ++ if (val & ~mask) ++ return; /* error condition */ ++ maccontrol = wlc_hw->maccontrol; ++ new_maccontrol = (maccontrol & ~mask) | val; ++ ++ /* if the new maccontrol value is the same as the old, nothing to do */ ++ if (new_maccontrol == maccontrol) ++ return; ++ ++ /* something changed, cache the new value */ ++ wlc_hw->maccontrol = new_maccontrol; ++ ++ /* write the new values with overrides applied */ ++ brcms_c_mctrl_write(wlc_hw); ++} ++ ++void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw, ++ u32 override_bit) ++{ ++ if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) { ++ mboolset(wlc_hw->wake_override, override_bit); ++ return; ++ } ++ ++ mboolset(wlc_hw->wake_override, override_bit); ++ ++ brcms_c_mctrl_write(wlc_hw); ++ brcms_b_wait_for_wake(wlc_hw); ++} ++ ++void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw, ++ u32 override_bit) ++{ ++ mboolclr(wlc_hw->wake_override, override_bit); ++ ++ if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) ++ return; ++ ++ brcms_c_mctrl_write(wlc_hw); ++} ++ ++/* When driver needs ucode to stop beaconing, it has to make sure that ++ * MCTL_AP is clear and MCTL_INFRA is set ++ * Mode MCTL_AP MCTL_INFRA ++ * AP 1 1 ++ * STA 0 1 <--- This will ensure no beacons ++ * IBSS 0 0 ++ */ ++static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw) ++{ ++ wlc_hw->mute_override = 1; ++ ++ /* if maccontrol already has AP == 0 and INFRA == 1 without this ++ * override, then there is no change to write ++ */ ++ if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA) ++ return; ++ ++ brcms_c_mctrl_write(wlc_hw); ++} ++ ++/* Clear the override on AP and INFRA bits */ ++static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw) ++{ ++ if (wlc_hw->mute_override == 0) ++ return; ++ ++ wlc_hw->mute_override = 0; ++ ++ /* if maccontrol already has AP == 0 and INFRA == 1 without this ++ * override, then there is no change to write ++ */ ++ if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA) ++ return; ++ ++ brcms_c_mctrl_write(wlc_hw); ++} ++ ++/* ++ * Write a MAC address to the given match reg offset in the RXE match engine. ++ */ ++static void ++brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset, ++ const u8 *addr) ++{ ++ struct d11regs __iomem *regs; ++ u16 mac_l; ++ u16 mac_m; ++ u16 mac_h; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n", ++ wlc_hw->unit); ++ ++ regs = wlc_hw->regs; ++ mac_l = addr[0] | (addr[1] << 8); ++ mac_m = addr[2] | (addr[3] << 8); ++ mac_h = addr[4] | (addr[5] << 8); ++ ++ /* enter the MAC addr into the RXE match registers */ ++ W_REG(®s->rcm_ctl, RCM_INC_DATA | match_reg_offset); ++ W_REG(®s->rcm_mat_data, mac_l); ++ W_REG(®s->rcm_mat_data, mac_m); ++ W_REG(®s->rcm_mat_data, mac_h); ++ ++} ++ ++void ++brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len, ++ void *buf) ++{ ++ struct d11regs __iomem *regs; ++ u32 word; ++ __le32 word_le; ++ __be32 word_be; ++ bool be_bit; ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ regs = wlc_hw->regs; ++ W_REG(®s->tplatewrptr, offset); ++ ++ /* if MCTL_BIGEND bit set in mac control register, ++ * the chip swaps data in fifo, as well as data in ++ * template ram ++ */ ++ be_bit = (R_REG(®s->maccontrol) & MCTL_BIGEND) != 0; ++ ++ while (len > 0) { ++ memcpy(&word, buf, sizeof(u32)); ++ ++ if (be_bit) { ++ word_be = cpu_to_be32(word); ++ word = *(u32 *)&word_be; ++ } else { ++ word_le = cpu_to_le32(word); ++ word = *(u32 *)&word_le; ++ } ++ ++ W_REG(®s->tplatewrdata, word); ++ ++ buf = (u8 *) buf + sizeof(u32); ++ len -= sizeof(u32); ++ } ++} ++ ++static void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin) ++{ ++ wlc_hw->band->CWmin = newmin; ++ ++ W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN); ++ (void)R_REG(&wlc_hw->regs->objaddr); ++ W_REG(&wlc_hw->regs->objdata, newmin); ++} ++ ++static void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax) ++{ ++ wlc_hw->band->CWmax = newmax; ++ ++ W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX); ++ (void)R_REG(&wlc_hw->regs->objaddr); ++ W_REG(&wlc_hw->regs->objdata, newmax); ++} ++ ++void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw) ++{ ++ bool fastclk; ++ ++ /* request FAST clock if not on */ ++ fastclk = wlc_hw->forcefastclk; ++ if (!fastclk) ++ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); ++ ++ wlc_phy_bw_state_set(wlc_hw->band->pi, bw); ++ ++ brcms_b_phy_reset(wlc_hw); ++ wlc_phy_init(wlc_hw->band->pi, wlc_phy_chanspec_get(wlc_hw->band->pi)); ++ ++ /* restore the clk */ ++ if (!fastclk) ++ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); ++} ++ ++static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw) ++{ ++ u16 v; ++ struct brcms_c_info *wlc = wlc_hw->wlc; ++ /* update SYNTHPU_DLY */ ++ ++ if (BRCMS_ISLCNPHY(wlc->band)) ++ v = SYNTHPU_DLY_LPPHY_US; ++ else if (BRCMS_ISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3))) ++ v = SYNTHPU_DLY_NPHY_US; ++ else ++ v = SYNTHPU_DLY_BPHY_US; ++ ++ brcms_b_write_shm(wlc_hw, M_SYNTHPU_DLY, v); ++} ++ ++static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw) ++{ ++ u16 phyctl; ++ u16 phytxant = wlc_hw->bmac_phytxant; ++ u16 mask = PHY_TXC_ANT_MASK; ++ ++ /* set the Probe Response frame phy control word */ ++ phyctl = brcms_b_read_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS); ++ phyctl = (phyctl & ~mask) | phytxant; ++ brcms_b_write_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS, phyctl); ++ ++ /* set the Response (ACK/CTS) frame phy control word */ ++ phyctl = brcms_b_read_shm(wlc_hw, M_RSP_PCTLWD); ++ phyctl = (phyctl & ~mask) | phytxant; ++ brcms_b_write_shm(wlc_hw, M_RSP_PCTLWD, phyctl); ++} ++ ++static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw, ++ u8 rate) ++{ ++ uint i; ++ u8 plcp_rate = 0; ++ struct plcp_signal_rate_lookup { ++ u8 rate; ++ u8 signal_rate; ++ }; ++ /* OFDM RATE sub-field of PLCP SIGNAL field, per 802.11 sec 17.3.4.1 */ ++ const struct plcp_signal_rate_lookup rate_lookup[] = { ++ {BRCM_RATE_6M, 0xB}, ++ {BRCM_RATE_9M, 0xF}, ++ {BRCM_RATE_12M, 0xA}, ++ {BRCM_RATE_18M, 0xE}, ++ {BRCM_RATE_24M, 0x9}, ++ {BRCM_RATE_36M, 0xD}, ++ {BRCM_RATE_48M, 0x8}, ++ {BRCM_RATE_54M, 0xC} ++ }; ++ ++ for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) { ++ if (rate == rate_lookup[i].rate) { ++ plcp_rate = rate_lookup[i].signal_rate; ++ break; ++ } ++ } ++ ++ /* Find the SHM pointer to the rate table entry by looking in the ++ * Direct-map Table ++ */ ++ return 2 * brcms_b_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2)); ++} ++ ++static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw) ++{ ++ u8 rate; ++ u8 rates[8] = { ++ BRCM_RATE_6M, BRCM_RATE_9M, BRCM_RATE_12M, BRCM_RATE_18M, ++ BRCM_RATE_24M, BRCM_RATE_36M, BRCM_RATE_48M, BRCM_RATE_54M ++ }; ++ u16 entry_ptr; ++ u16 pctl1; ++ uint i; ++ ++ if (!BRCMS_PHY_11N_CAP(wlc_hw->band)) ++ return; ++ ++ /* walk the phy rate table and update the entries */ ++ for (i = 0; i < ARRAY_SIZE(rates); i++) { ++ rate = rates[i]; ++ ++ entry_ptr = brcms_b_ofdm_ratetable_offset(wlc_hw, rate); ++ ++ /* read the SHM Rate Table entry OFDM PCTL1 values */ ++ pctl1 = ++ brcms_b_read_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS); ++ ++ /* modify the value */ ++ pctl1 &= ~PHY_TXC1_MODE_MASK; ++ pctl1 |= (wlc_hw->hw_stf_ss_opmode << PHY_TXC1_MODE_SHIFT); ++ ++ /* Update the SHM Rate Table entry OFDM PCTL1 values */ ++ brcms_b_write_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS, ++ pctl1); ++ } ++} ++ ++/* band-specific init */ ++static void brcms_b_bsinit(struct brcms_c_info *wlc, u16 chanspec) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ ++ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, ++ wlc_hw->band->bandunit); ++ ++ brcms_c_ucode_bsinit(wlc_hw); ++ ++ wlc_phy_init(wlc_hw->band->pi, chanspec); ++ ++ brcms_c_ucode_txant_set(wlc_hw); ++ ++ /* ++ * cwmin is band-specific, update hardware ++ * with value for current band ++ */ ++ brcms_b_set_cwmin(wlc_hw, wlc_hw->band->CWmin); ++ brcms_b_set_cwmax(wlc_hw, wlc_hw->band->CWmax); ++ ++ brcms_b_update_slot_timing(wlc_hw, ++ wlc_hw->band->bandtype == BRCM_BAND_5G ? ++ true : wlc_hw->shortslot); ++ ++ /* write phytype and phyvers */ ++ brcms_b_write_shm(wlc_hw, M_PHYTYPE, (u16) wlc_hw->band->phytype); ++ brcms_b_write_shm(wlc_hw, M_PHYVER, (u16) wlc_hw->band->phyrev); ++ ++ /* ++ * initialize the txphyctl1 rate table since ++ * shmem is shared between bands ++ */ ++ brcms_upd_ofdm_pctl1_table(wlc_hw); ++ ++ brcms_b_upd_synthpu(wlc_hw); ++} ++ ++/* Perform a soft reset of the PHY PLL */ ++void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw) ++{ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ ai_corereg(wlc_hw->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_addr), ~0, 0); ++ udelay(1); ++ ai_corereg(wlc_hw->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_data), 0x4, 0); ++ udelay(1); ++ ai_corereg(wlc_hw->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_data), 0x4, 4); ++ udelay(1); ++ ai_corereg(wlc_hw->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_data), 0x4, 0); ++ udelay(1); ++} ++ ++/* light way to turn on phy clock without reset for NPHY only ++ * refer to brcms_b_core_phy_clk for full version ++ */ ++void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk) ++{ ++ /* support(necessary for NPHY and HYPHY) only */ ++ if (!BRCMS_ISNPHY(wlc_hw->band)) ++ return; ++ ++ if (ON == clk) ++ ai_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC); ++ else ++ ai_core_cflags(wlc_hw->sih, SICF_FGC, 0); ++ ++} ++ ++void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk) ++{ ++ if (ON == clk) ++ ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE); ++ else ++ ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0); ++} ++ ++void brcms_b_phy_reset(struct brcms_hardware *wlc_hw) ++{ ++ struct brcms_phy_pub *pih = wlc_hw->band->pi; ++ u32 phy_bw_clkbits; ++ bool phy_in_reset = false; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ if (pih == NULL) ++ return; ++ ++ phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi); ++ ++ /* Specific reset sequence required for NPHY rev 3 and 4 */ ++ if (BRCMS_ISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) && ++ NREV_LE(wlc_hw->band->phyrev, 4)) { ++ /* Set the PHY bandwidth */ ++ ai_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits); ++ ++ udelay(1); ++ ++ /* Perform a soft reset of the PHY PLL */ ++ brcms_b_core_phypll_reset(wlc_hw); ++ ++ /* reset the PHY */ ++ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE), ++ (SICF_PRST | SICF_PCLKE)); ++ phy_in_reset = true; ++ } else { ++ ai_core_cflags(wlc_hw->sih, ++ (SICF_PRST | SICF_PCLKE | SICF_BWMASK), ++ (SICF_PRST | SICF_PCLKE | phy_bw_clkbits)); ++ } ++ ++ udelay(2); ++ brcms_b_core_phy_clk(wlc_hw, ON); ++ ++ if (pih) ++ wlc_phy_anacore(pih, ON); ++} ++ ++/* switch to and initialize new band */ ++static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit, ++ u16 chanspec) { ++ struct brcms_c_info *wlc = wlc_hw->wlc; ++ u32 macintmask; ++ ++ /* Enable the d11 core before accessing it */ ++ if (!ai_iscoreup(wlc_hw->sih)) { ++ ai_core_reset(wlc_hw->sih, 0, 0); ++ brcms_c_mctrl_reset(wlc_hw); ++ } ++ ++ macintmask = brcms_c_setband_inact(wlc, bandunit); ++ ++ if (!wlc_hw->up) ++ return; ++ ++ brcms_b_core_phy_clk(wlc_hw, ON); ++ ++ /* band-specific initializations */ ++ brcms_b_bsinit(wlc, chanspec); ++ ++ /* ++ * If there are any pending software interrupt bits, ++ * then replace these with a harmless nonzero value ++ * so brcms_c_dpc() will re-enable interrupts when done. ++ */ ++ if (wlc->macintstatus) ++ wlc->macintstatus = MI_DMAINT; ++ ++ /* restore macintmask */ ++ brcms_intrsrestore(wlc->wl, macintmask); ++ ++ /* ucode should still be suspended.. */ ++ WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0); ++} ++ ++static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw) ++{ ++ ++ /* reject unsupported corerev */ ++ if (!CONF_HAS(D11CONF, wlc_hw->corerev)) { ++ wiphy_err(wlc_hw->wlc->wiphy, "unsupported core rev %d\n", ++ wlc_hw->corerev); ++ return false; ++ } ++ ++ return true; ++} ++ ++/* Validate some board info parameters */ ++static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw) ++{ ++ uint boardrev = wlc_hw->boardrev; ++ ++ /* 4 bits each for board type, major, minor, and tiny version */ ++ uint brt = (boardrev & 0xf000) >> 12; ++ uint b0 = (boardrev & 0xf00) >> 8; ++ uint b1 = (boardrev & 0xf0) >> 4; ++ uint b2 = boardrev & 0xf; ++ ++ /* voards from other vendors are always considered valid */ ++ if (wlc_hw->sih->boardvendor != PCI_VENDOR_ID_BROADCOM) ++ return true; ++ ++ /* do some boardrev sanity checks when boardvendor is Broadcom */ ++ if (boardrev == 0) ++ return false; ++ ++ if (boardrev <= 0xff) ++ return true; ++ ++ if ((brt > 2) || (brt == 0) || (b0 > 9) || (b0 == 0) || (b1 > 9) ++ || (b2 > 9)) ++ return false; ++ ++ return true; ++} ++ ++static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw) ++{ ++ enum brcms_srom_id var_id = BRCMS_SROM_MACADDR; ++ char *macaddr; ++ ++ /* If macaddr exists, use it (Sromrev4, CIS, ...). */ ++ macaddr = getvar(wlc_hw->sih, var_id); ++ if (macaddr != NULL) ++ return macaddr; ++ ++ if (wlc_hw->_nbands > 1) ++ var_id = BRCMS_SROM_ET1MACADDR; ++ else ++ var_id = BRCMS_SROM_IL0MACADDR; ++ ++ macaddr = getvar(wlc_hw->sih, var_id); ++ if (macaddr == NULL) ++ wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_get_macaddr: macaddr " ++ "getvar(%d) not found\n", wlc_hw->unit, var_id); ++ ++ return macaddr; ++} ++ ++/* power both the pll and external oscillator on/off */ ++static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want) ++{ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: want %d\n", wlc_hw->unit, want); ++ ++ /* ++ * dont power down if plldown is false or ++ * we must poll hw radio disable ++ */ ++ if (!want && wlc_hw->pllreq) ++ return; ++ ++ if (wlc_hw->sih) ++ ai_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want); ++ ++ wlc_hw->sbclk = want; ++ if (!wlc_hw->sbclk) { ++ wlc_hw->clk = false; ++ if (wlc_hw->band && wlc_hw->band->pi) ++ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); ++ } ++} ++ ++/* ++ * Return true if radio is disabled, otherwise false. ++ * hw radio disable signal is an external pin, users activate it asynchronously ++ * this function could be called when driver is down and w/o clock ++ * it operates on different registers depending on corerev and boardflag. ++ */ ++static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw) ++{ ++ bool v, clk, xtal; ++ u32 resetbits = 0, flags = 0; ++ ++ xtal = wlc_hw->sbclk; ++ if (!xtal) ++ brcms_b_xtal(wlc_hw, ON); ++ ++ /* may need to take core out of reset first */ ++ clk = wlc_hw->clk; ++ if (!clk) { ++ /* ++ * mac no longer enables phyclk automatically when driver ++ * accesses phyreg throughput mac. This can be skipped since ++ * only mac reg is accessed below ++ */ ++ flags |= SICF_PCLKE; ++ ++ /* ++ * AI chip doesn't restore bar0win2 on ++ * hibernation/resume, need sw fixup ++ */ ++ if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || ++ (wlc_hw->sih->chip == BCM43225_CHIP_ID)) ++ wlc_hw->regs = (struct d11regs __iomem *) ++ ai_setcore(wlc_hw->sih, D11_CORE_ID, 0); ++ ai_core_reset(wlc_hw->sih, flags, resetbits); ++ brcms_c_mctrl_reset(wlc_hw); ++ } ++ ++ v = ((R_REG(&wlc_hw->regs->phydebug) & PDBG_RFD) != 0); ++ ++ /* put core back into reset */ ++ if (!clk) ++ ai_core_disable(wlc_hw->sih, 0); ++ ++ if (!xtal) ++ brcms_b_xtal(wlc_hw, OFF); ++ ++ return v; ++} ++ ++static bool wlc_dma_rxreset(struct brcms_hardware *wlc_hw, uint fifo) ++{ ++ struct dma_pub *di = wlc_hw->di[fifo]; ++ return dma_rxreset(di); ++} ++ ++/* d11 core reset ++ * ensure fask clock during reset ++ * reset dma ++ * reset d11(out of reset) ++ * reset phy(out of reset) ++ * clear software macintstatus for fresh new start ++ * one testing hack wlc_hw->noreset will bypass the d11/phy reset ++ */ ++void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) ++{ ++ struct d11regs __iomem *regs; ++ uint i; ++ bool fastclk; ++ u32 resetbits = 0; ++ ++ if (flags == BRCMS_USE_COREFLAGS) ++ flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0); ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ regs = wlc_hw->regs; ++ ++ /* request FAST clock if not on */ ++ fastclk = wlc_hw->forcefastclk; ++ if (!fastclk) ++ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); ++ ++ /* reset the dma engines except first time thru */ ++ if (ai_iscoreup(wlc_hw->sih)) { ++ for (i = 0; i < NFIFO; i++) ++ if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i]))) ++ wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: " ++ "dma_txreset[%d]: cannot stop dma\n", ++ wlc_hw->unit, __func__, i); ++ ++ if ((wlc_hw->di[RX_FIFO]) ++ && (!wlc_dma_rxreset(wlc_hw, RX_FIFO))) ++ wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: dma_rxreset" ++ "[%d]: cannot stop dma\n", ++ wlc_hw->unit, __func__, RX_FIFO); ++ } ++ /* if noreset, just stop the psm and return */ ++ if (wlc_hw->noreset) { ++ wlc_hw->wlc->macintstatus = 0; /* skip wl_dpc after down */ ++ brcms_b_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0); ++ return; ++ } ++ ++ /* ++ * mac no longer enables phyclk automatically when driver accesses ++ * phyreg throughput mac, AND phy_reset is skipped at early stage when ++ * band->pi is invalid. need to enable PHY CLK ++ */ ++ flags |= SICF_PCLKE; ++ ++ /* ++ * reset the core ++ * In chips with PMU, the fastclk request goes through d11 core ++ * reg 0x1e0, which is cleared by the core_reset. have to re-request it. ++ * ++ * This adds some delay and we can optimize it by also requesting ++ * fastclk through chipcommon during this period if necessary. But ++ * that has to work coordinate with other driver like mips/arm since ++ * they may touch chipcommon as well. ++ */ ++ wlc_hw->clk = false; ++ ai_core_reset(wlc_hw->sih, flags, resetbits); ++ wlc_hw->clk = true; ++ if (wlc_hw->band && wlc_hw->band->pi) ++ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true); ++ ++ brcms_c_mctrl_reset(wlc_hw); ++ ++ if (wlc_hw->sih->cccaps & CC_CAP_PMU) ++ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); ++ ++ brcms_b_phy_reset(wlc_hw); ++ ++ /* turn on PHY_PLL */ ++ brcms_b_core_phypll_ctl(wlc_hw, true); ++ ++ /* clear sw intstatus */ ++ wlc_hw->wlc->macintstatus = 0; ++ ++ /* restore the clk setting */ ++ if (!fastclk) ++ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); ++} ++ ++/* txfifo sizes needs to be modified(increased) since the newer cores ++ * have more memory. ++ */ ++static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw) ++{ ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ u16 fifo_nu; ++ u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk; ++ u16 txfifo_def, txfifo_def1; ++ u16 txfifo_cmd; ++ ++ /* tx fifos start at TXFIFO_START_BLK from the Base address */ ++ txfifo_startblk = TXFIFO_START_BLK; ++ ++ /* sequence of operations: reset fifo, set fifo size, reset fifo */ ++ for (fifo_nu = 0; fifo_nu < NFIFO; fifo_nu++) { ++ ++ txfifo_endblk = txfifo_startblk + wlc_hw->xmtfifo_sz[fifo_nu]; ++ txfifo_def = (txfifo_startblk & 0xff) | ++ (((txfifo_endblk - 1) & 0xff) << TXFIFO_FIFOTOP_SHIFT); ++ txfifo_def1 = ((txfifo_startblk >> 8) & 0x1) | ++ ((((txfifo_endblk - ++ 1) >> 8) & 0x1) << TXFIFO_FIFOTOP_SHIFT); ++ txfifo_cmd = ++ TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT); ++ ++ W_REG(®s->xmtfifocmd, txfifo_cmd); ++ W_REG(®s->xmtfifodef, txfifo_def); ++ W_REG(®s->xmtfifodef1, txfifo_def1); ++ ++ W_REG(®s->xmtfifocmd, txfifo_cmd); ++ ++ txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu]; ++ } ++ /* ++ * need to propagate to shm location to be in sync since ucode/hw won't ++ * do this ++ */ ++ brcms_b_write_shm(wlc_hw, M_FIFOSIZE0, ++ wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]); ++ brcms_b_write_shm(wlc_hw, M_FIFOSIZE1, ++ wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]); ++ brcms_b_write_shm(wlc_hw, M_FIFOSIZE2, ++ ((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw-> ++ xmtfifo_sz[TX_AC_BK_FIFO])); ++ brcms_b_write_shm(wlc_hw, M_FIFOSIZE3, ++ ((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw-> ++ xmtfifo_sz[TX_BCMC_FIFO])); ++} ++ ++/* This function is used for changing the tsf frac register ++ * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz ++ * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz ++ * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz ++ * HTPHY Formula is 2^26/freq(MHz) e.g. ++ * For spuron2 - 126MHz -> 2^26/126 = 532610.0 ++ * - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082 ++ * For spuron: 123MHz -> 2^26/123 = 545600.5 ++ * - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341 ++ * For spur off: 120MHz -> 2^26/120 = 559240.5 ++ * - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889 ++ */ ++ ++void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode) ++{ ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ ++ if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || ++ (wlc_hw->sih->chip == BCM43225_CHIP_ID)) { ++ if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */ ++ W_REG(®s->tsf_clk_frac_l, 0x2082); ++ W_REG(®s->tsf_clk_frac_h, 0x8); ++ } else if (spurmode == WL_SPURAVOID_ON1) { /* 123Mhz */ ++ W_REG(®s->tsf_clk_frac_l, 0x5341); ++ W_REG(®s->tsf_clk_frac_h, 0x8); ++ } else { /* 120Mhz */ ++ W_REG(®s->tsf_clk_frac_l, 0x8889); ++ W_REG(®s->tsf_clk_frac_h, 0x8); ++ } ++ } else if (BRCMS_ISLCNPHY(wlc_hw->band)) { ++ if (spurmode == WL_SPURAVOID_ON1) { /* 82Mhz */ ++ W_REG(®s->tsf_clk_frac_l, 0x7CE0); ++ W_REG(®s->tsf_clk_frac_h, 0xC); ++ } else { /* 80Mhz */ ++ W_REG(®s->tsf_clk_frac_l, 0xCCCD); ++ W_REG(®s->tsf_clk_frac_h, 0xC); ++ } ++ } ++} ++ ++/* Initialize GPIOs that are controlled by D11 core */ ++static void brcms_c_gpio_init(struct brcms_c_info *wlc) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ struct d11regs __iomem *regs; ++ u32 gc, gm; ++ ++ regs = wlc_hw->regs; ++ ++ /* use GPIO select 0 to get all gpio signals from the gpio out reg */ ++ brcms_b_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0); ++ ++ /* ++ * Common GPIO setup: ++ * G0 = LED 0 = WLAN Activity ++ * G1 = LED 1 = WLAN 2.4 GHz Radio State ++ * G2 = LED 2 = WLAN 5 GHz Radio State ++ * G4 = radio disable input (HI enabled, LO disabled) ++ */ ++ ++ gc = gm = 0; ++ ++ /* Allocate GPIOs for mimo antenna diversity feature */ ++ if (wlc_hw->antsel_type == ANTSEL_2x3) { ++ /* Enable antenna diversity, use 2x3 mode */ ++ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN, ++ MHF3_ANTSEL_EN, BRCM_BAND_ALL); ++ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, ++ MHF3_ANTSEL_MODE, BRCM_BAND_ALL); ++ ++ /* init superswitch control */ ++ wlc_phy_antsel_init(wlc_hw->band->pi, false); ++ ++ } else if (wlc_hw->antsel_type == ANTSEL_2x4) { ++ gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13); ++ /* ++ * The board itself is powered by these GPIOs ++ * (when not sending pattern) so set them high ++ */ ++ OR_REG(®s->psm_gpio_oe, ++ (BOARD_GPIO_12 | BOARD_GPIO_13)); ++ OR_REG(®s->psm_gpio_out, ++ (BOARD_GPIO_12 | BOARD_GPIO_13)); ++ ++ /* Enable antenna diversity, use 2x4 mode */ ++ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN, ++ MHF3_ANTSEL_EN, BRCM_BAND_ALL); ++ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, 0, ++ BRCM_BAND_ALL); ++ ++ /* Configure the desired clock to be 4Mhz */ ++ brcms_b_write_shm(wlc_hw, M_ANTSEL_CLKDIV, ++ ANTSEL_CLKDIV_4MHZ); ++ } ++ ++ /* ++ * gpio 9 controls the PA. ucode is responsible ++ * for wiggling out and oe ++ */ ++ if (wlc_hw->boardflags & BFL_PACTRL) ++ gm |= gc |= BOARD_GPIO_PACTRL; ++ ++ /* apply to gpiocontrol register */ ++ ai_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY); ++} ++ ++static void brcms_ucode_write(struct brcms_hardware *wlc_hw, ++ const __le32 ucode[], const size_t nbytes) ++{ ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ uint i; ++ uint count; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ count = (nbytes / sizeof(u32)); ++ ++ W_REG(®s->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL)); ++ (void)R_REG(®s->objaddr); ++ for (i = 0; i < count; i++) ++ W_REG(®s->objdata, le32_to_cpu(ucode[i])); ++ ++} ++ ++static void brcms_ucode_download(struct brcms_hardware *wlc_hw) ++{ ++ struct brcms_c_info *wlc; ++ struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode; ++ ++ wlc = wlc_hw->wlc; ++ ++ if (wlc_hw->ucode_loaded) ++ return; ++ ++ if (D11REV_IS(wlc_hw->corerev, 23)) { ++ if (BRCMS_ISNPHY(wlc_hw->band)) { ++ brcms_ucode_write(wlc_hw, ucode->bcm43xx_16_mimo, ++ ucode->bcm43xx_16_mimosz); ++ wlc_hw->ucode_loaded = true; ++ } else ++ wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in " ++ "corerev %d\n", ++ __func__, wlc_hw->unit, wlc_hw->corerev); ++ } else if (D11REV_IS(wlc_hw->corerev, 24)) { ++ if (BRCMS_ISLCNPHY(wlc_hw->band)) { ++ brcms_ucode_write(wlc_hw, ucode->bcm43xx_24_lcn, ++ ucode->bcm43xx_24_lcnsz); ++ wlc_hw->ucode_loaded = true; ++ } else { ++ wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in " ++ "corerev %d\n", ++ __func__, wlc_hw->unit, wlc_hw->corerev); ++ } ++ } ++} ++ ++void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant) ++{ ++ /* update sw state */ ++ wlc_hw->bmac_phytxant = phytxant; ++ ++ /* push to ucode if up */ ++ if (!wlc_hw->up) ++ return; ++ brcms_c_ucode_txant_set(wlc_hw); ++ ++} ++ ++u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw) ++{ ++ return (u16) wlc_hw->wlc->stf->txant; ++} ++ ++void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type) ++{ ++ wlc_hw->antsel_type = antsel_type; ++ ++ /* Update the antsel type for phy module to use */ ++ wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type); ++} ++ ++static void brcms_c_fatal_error(struct brcms_c_info *wlc) ++{ ++ wiphy_err(wlc->wiphy, "wl%d: fatal error, reinitializing\n", ++ wlc->pub->unit); ++ brcms_init(wlc->wl); ++} ++ ++static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw) ++{ ++ bool fatal = false; ++ uint unit; ++ uint intstatus, idx; ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ struct wiphy *wiphy = wlc_hw->wlc->wiphy; ++ ++ unit = wlc_hw->unit; ++ ++ for (idx = 0; idx < NFIFO; idx++) { ++ /* read intstatus register and ignore any non-error bits */ ++ intstatus = ++ R_REG(®s->intctrlregs[idx].intstatus) & I_ERRORS; ++ if (!intstatus) ++ continue; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: intstatus%d 0x%x\n", ++ unit, idx, intstatus); ++ ++ if (intstatus & I_RO) { ++ wiphy_err(wiphy, "wl%d: fifo %d: receive fifo " ++ "overflow\n", unit, idx); ++ fatal = true; ++ } ++ ++ if (intstatus & I_PC) { ++ wiphy_err(wiphy, "wl%d: fifo %d: descriptor error\n", ++ unit, idx); ++ fatal = true; ++ } ++ ++ if (intstatus & I_PD) { ++ wiphy_err(wiphy, "wl%d: fifo %d: data error\n", unit, ++ idx); ++ fatal = true; ++ } ++ ++ if (intstatus & I_DE) { ++ wiphy_err(wiphy, "wl%d: fifo %d: descriptor protocol " ++ "error\n", unit, idx); ++ fatal = true; ++ } ++ ++ if (intstatus & I_RU) ++ wiphy_err(wiphy, "wl%d: fifo %d: receive descriptor " ++ "underflow\n", idx, unit); ++ ++ if (intstatus & I_XU) { ++ wiphy_err(wiphy, "wl%d: fifo %d: transmit fifo " ++ "underflow\n", idx, unit); ++ fatal = true; ++ } ++ ++ if (fatal) { ++ brcms_c_fatal_error(wlc_hw->wlc); /* big hammer */ ++ break; ++ } else ++ W_REG(®s->intctrlregs[idx].intstatus, ++ intstatus); ++ } ++} ++ ++void brcms_c_intrson(struct brcms_c_info *wlc) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ wlc->macintmask = wlc->defmacintmask; ++ W_REG(&wlc_hw->regs->macintmask, wlc->macintmask); ++} ++ ++/* ++ * callback for siutils.c, which has only wlc handler, no wl they both check ++ * up, not only because there is no need to off/restore d11 interrupt but also ++ * because per-port code may require sync with valid interrupt. ++ */ ++static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc) ++{ ++ if (!wlc->hw->up) ++ return 0; ++ ++ return brcms_intrsoff(wlc->wl); ++} ++ ++static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask) ++{ ++ if (!wlc->hw->up) ++ return; ++ ++ brcms_intrsrestore(wlc->wl, macintmask); ++} ++ ++u32 brcms_c_intrsoff(struct brcms_c_info *wlc) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ u32 macintmask; ++ ++ if (!wlc_hw->clk) ++ return 0; ++ ++ macintmask = wlc->macintmask; /* isr can still happen */ ++ ++ W_REG(&wlc_hw->regs->macintmask, 0); ++ (void)R_REG(&wlc_hw->regs->macintmask); /* sync readback */ ++ udelay(1); /* ensure int line is no longer driven */ ++ wlc->macintmask = 0; ++ ++ /* return previous macintmask; resolve race between us and our isr */ ++ return wlc->macintstatus ? 0 : macintmask; ++} ++ ++void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ if (!wlc_hw->clk) ++ return; ++ ++ wlc->macintmask = macintmask; ++ W_REG(&wlc_hw->regs->macintmask, wlc->macintmask); ++} ++ ++static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw, ++ uint tx_fifo) ++{ ++ u8 fifo = 1 << tx_fifo; ++ ++ /* Two clients of this code, 11h Quiet period and scanning. */ ++ ++ /* only suspend if not already suspended */ ++ if ((wlc_hw->suspended_fifos & fifo) == fifo) ++ return; ++ ++ /* force the core awake only if not already */ ++ if (wlc_hw->suspended_fifos == 0) ++ brcms_c_ucode_wake_override_set(wlc_hw, ++ BRCMS_WAKE_OVERRIDE_TXFIFO); ++ ++ wlc_hw->suspended_fifos |= fifo; ++ ++ if (wlc_hw->di[tx_fifo]) { ++ /* ++ * Suspending AMPDU transmissions in the middle can cause ++ * underflow which may result in mismatch between ucode and ++ * driver so suspend the mac before suspending the FIFO ++ */ ++ if (BRCMS_PHY_11N_CAP(wlc_hw->band)) ++ brcms_c_suspend_mac_and_wait(wlc_hw->wlc); ++ ++ dma_txsuspend(wlc_hw->di[tx_fifo]); ++ ++ if (BRCMS_PHY_11N_CAP(wlc_hw->band)) ++ brcms_c_enable_mac(wlc_hw->wlc); ++ } ++} ++ ++static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw, ++ uint tx_fifo) ++{ ++ /* BMAC_NOTE: BRCMS_TX_FIFO_ENAB is done in brcms_c_dpc() for DMA case ++ * but need to be done here for PIO otherwise the watchdog will catch ++ * the inconsistency and fire ++ */ ++ /* Two clients of this code, 11h Quiet period and scanning. */ ++ if (wlc_hw->di[tx_fifo]) ++ dma_txresume(wlc_hw->di[tx_fifo]); ++ ++ /* allow core to sleep again */ ++ if (wlc_hw->suspended_fifos == 0) ++ return; ++ else { ++ wlc_hw->suspended_fifos &= ~(1 << tx_fifo); ++ if (wlc_hw->suspended_fifos == 0) ++ brcms_c_ucode_wake_override_clear(wlc_hw, ++ BRCMS_WAKE_OVERRIDE_TXFIFO); ++ } ++} ++ ++static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool on, u32 flags) ++{ ++ static const u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; ++ ++ if (on) { ++ /* suspend tx fifos */ ++ brcms_b_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO); ++ brcms_b_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO); ++ brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_BK_FIFO); ++ brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO); ++ ++ /* zero the address match register so we do not send ACKs */ ++ brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, ++ null_ether_addr); ++ } else { ++ /* resume tx fifos */ ++ brcms_b_tx_fifo_resume(wlc_hw, TX_DATA_FIFO); ++ brcms_b_tx_fifo_resume(wlc_hw, TX_CTL_FIFO); ++ brcms_b_tx_fifo_resume(wlc_hw, TX_AC_BK_FIFO); ++ brcms_b_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO); ++ ++ /* Restore address */ ++ brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, ++ wlc_hw->etheraddr); ++ } ++ ++ wlc_phy_mute_upd(wlc_hw->band->pi, on, flags); ++ ++ if (on) ++ brcms_c_ucode_mute_override_set(wlc_hw); ++ else ++ brcms_c_ucode_mute_override_clear(wlc_hw); ++} ++ ++/* ++ * Read and clear macintmask and macintstatus and intstatus registers. ++ * This routine should be called with interrupts off ++ * Return: ++ * -1 if brcms_deviceremoved(wlc) evaluates to true; ++ * 0 if the interrupt is not for us, or we are in some special cases; ++ * device interrupt status bits otherwise. ++ */ ++static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ u32 macintstatus; ++ ++ /* macintstatus includes a DMA interrupt summary bit */ ++ macintstatus = R_REG(®s->macintstatus); ++ ++ BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit, ++ macintstatus); ++ ++ /* detect cardbus removed, in power down(suspend) and in reset */ ++ if (brcms_deviceremoved(wlc)) ++ return -1; ++ ++ /* brcms_deviceremoved() succeeds even when the core is still resetting, ++ * handle that case here. ++ */ ++ if (macintstatus == 0xffffffff) ++ return 0; ++ ++ /* defer unsolicited interrupts */ ++ macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask); ++ ++ /* if not for us */ ++ if (macintstatus == 0) ++ return 0; ++ ++ /* interrupts are already turned off for CFE build ++ * Caution: For CFE Turning off the interrupts again has some undesired ++ * consequences ++ */ ++ /* turn off the interrupts */ ++ W_REG(®s->macintmask, 0); ++ (void)R_REG(®s->macintmask); /* sync readback */ ++ wlc->macintmask = 0; ++ ++ /* clear device interrupts */ ++ W_REG(®s->macintstatus, macintstatus); ++ ++ /* MI_DMAINT is indication of non-zero intstatus */ ++ if (macintstatus & MI_DMAINT) ++ /* ++ * only fifo interrupt enabled is I_RI in ++ * RX_FIFO. If MI_DMAINT is set, assume it ++ * is set and clear the interrupt. ++ */ ++ W_REG(®s->intctrlregs[RX_FIFO].intstatus, ++ DEF_RXINTMASK); ++ ++ return macintstatus; ++} ++ ++/* Update wlc->macintstatus and wlc->intstatus[]. */ ++/* Return true if they are updated successfully. false otherwise */ ++bool brcms_c_intrsupd(struct brcms_c_info *wlc) ++{ ++ u32 macintstatus; ++ ++ /* read and clear macintstatus and intstatus registers */ ++ macintstatus = wlc_intstatus(wlc, false); ++ ++ /* device is removed */ ++ if (macintstatus == 0xffffffff) ++ return false; ++ ++ /* update interrupt status in software */ ++ wlc->macintstatus |= macintstatus; ++ ++ return true; ++} ++ ++/* ++ * First-level interrupt processing. ++ * Return true if this was our interrupt, false otherwise. ++ * *wantdpc will be set to true if further brcms_c_dpc() processing is required, ++ * false otherwise. ++ */ ++bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ u32 macintstatus; ++ ++ *wantdpc = false; ++ ++ if (!wlc_hw->up || !wlc->macintmask) ++ return false; ++ ++ /* read and clear macintstatus and intstatus registers */ ++ macintstatus = wlc_intstatus(wlc, true); ++ ++ if (macintstatus == 0xffffffff) ++ wiphy_err(wlc->wiphy, "DEVICEREMOVED detected in the ISR code" ++ " path\n"); ++ ++ /* it is not for us */ ++ if (macintstatus == 0) ++ return false; ++ ++ *wantdpc = true; ++ ++ /* save interrupt status bits */ ++ wlc->macintstatus = macintstatus; ++ ++ return true; ++ ++} ++ ++void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ u32 mc, mi; ++ struct wiphy *wiphy = wlc->wiphy; ++ ++ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, ++ wlc_hw->band->bandunit); ++ ++ /* ++ * Track overlapping suspend requests ++ */ ++ wlc_hw->mac_suspend_depth++; ++ if (wlc_hw->mac_suspend_depth > 1) ++ return; ++ ++ /* force the core awake */ ++ brcms_c_ucode_wake_override_set(wlc_hw, BRCMS_WAKE_OVERRIDE_MACSUSPEND); ++ ++ mc = R_REG(®s->maccontrol); ++ ++ if (mc == 0xffffffff) { ++ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, ++ __func__); ++ brcms_down(wlc->wl); ++ return; ++ } ++ WARN_ON(mc & MCTL_PSM_JMP_0); ++ WARN_ON(!(mc & MCTL_PSM_RUN)); ++ WARN_ON(!(mc & MCTL_EN_MAC)); ++ ++ mi = R_REG(®s->macintstatus); ++ if (mi == 0xffffffff) { ++ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, ++ __func__); ++ brcms_down(wlc->wl); ++ return; ++ } ++ WARN_ON(mi & MI_MACSSPNDD); ++ ++ brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, 0); ++ ++ SPINWAIT(!(R_REG(®s->macintstatus) & MI_MACSSPNDD), ++ BRCMS_MAX_MAC_SUSPEND); ++ ++ if (!(R_REG(®s->macintstatus) & MI_MACSSPNDD)) { ++ wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS" ++ " and MI_MACSSPNDD is still not on.\n", ++ wlc_hw->unit, BRCMS_MAX_MAC_SUSPEND); ++ wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, " ++ "psm_brc 0x%04x\n", wlc_hw->unit, ++ R_REG(®s->psmdebug), ++ R_REG(®s->phydebug), ++ R_REG(®s->psm_brc)); ++ } ++ ++ mc = R_REG(®s->maccontrol); ++ if (mc == 0xffffffff) { ++ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, ++ __func__); ++ brcms_down(wlc->wl); ++ return; ++ } ++ WARN_ON(mc & MCTL_PSM_JMP_0); ++ WARN_ON(!(mc & MCTL_PSM_RUN)); ++ WARN_ON(mc & MCTL_EN_MAC); ++} ++ ++void brcms_c_enable_mac(struct brcms_c_info *wlc) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ u32 mc, mi; ++ ++ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, ++ wlc->band->bandunit); ++ ++ /* ++ * Track overlapping suspend requests ++ */ ++ wlc_hw->mac_suspend_depth--; ++ if (wlc_hw->mac_suspend_depth > 0) ++ return; ++ ++ mc = R_REG(®s->maccontrol); ++ WARN_ON(mc & MCTL_PSM_JMP_0); ++ WARN_ON(mc & MCTL_EN_MAC); ++ WARN_ON(!(mc & MCTL_PSM_RUN)); ++ ++ brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC); ++ W_REG(®s->macintstatus, MI_MACSSPNDD); ++ ++ mc = R_REG(®s->maccontrol); ++ WARN_ON(mc & MCTL_PSM_JMP_0); ++ WARN_ON(!(mc & MCTL_EN_MAC)); ++ WARN_ON(!(mc & MCTL_PSM_RUN)); ++ ++ mi = R_REG(®s->macintstatus); ++ WARN_ON(mi & MI_MACSSPNDD); ++ ++ brcms_c_ucode_wake_override_clear(wlc_hw, ++ BRCMS_WAKE_OVERRIDE_MACSUSPEND); ++} ++ ++void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode) ++{ ++ wlc_hw->hw_stf_ss_opmode = stf_mode; ++ ++ if (wlc_hw->clk) ++ brcms_upd_ofdm_pctl1_table(wlc_hw); ++} ++ ++static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw) ++{ ++ struct d11regs __iomem *regs; ++ u32 w, val; ++ struct wiphy *wiphy = wlc_hw->wlc->wiphy; ++ ++ BCMMSG(wiphy, "wl%d\n", wlc_hw->unit); ++ ++ regs = wlc_hw->regs; ++ ++ /* Validate dchip register access */ ++ ++ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); ++ (void)R_REG(®s->objaddr); ++ w = R_REG(®s->objdata); ++ ++ /* Can we write and read back a 32bit register? */ ++ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); ++ (void)R_REG(®s->objaddr); ++ W_REG(®s->objdata, (u32) 0xaa5555aa); ++ ++ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); ++ (void)R_REG(®s->objaddr); ++ val = R_REG(®s->objdata); ++ if (val != (u32) 0xaa5555aa) { ++ wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, " ++ "expected 0xaa5555aa\n", wlc_hw->unit, val); ++ return false; ++ } ++ ++ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); ++ (void)R_REG(®s->objaddr); ++ W_REG(®s->objdata, (u32) 0x55aaaa55); ++ ++ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); ++ (void)R_REG(®s->objaddr); ++ val = R_REG(®s->objdata); ++ if (val != (u32) 0x55aaaa55) { ++ wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, " ++ "expected 0x55aaaa55\n", wlc_hw->unit, val); ++ return false; ++ } ++ ++ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); ++ (void)R_REG(®s->objaddr); ++ W_REG(®s->objdata, w); ++ ++ /* clear CFPStart */ ++ W_REG(®s->tsf_cfpstart, 0); ++ ++ w = R_REG(®s->maccontrol); ++ if ((w != (MCTL_IHR_EN | MCTL_WAKE)) && ++ (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) { ++ wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = " ++ "0x%x, expected 0x%x or 0x%x\n", wlc_hw->unit, w, ++ (MCTL_IHR_EN | MCTL_WAKE), ++ (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE)); ++ return false; ++ } ++ ++ return true; ++} ++ ++#define PHYPLL_WAIT_US 100000 ++ ++void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on) ++{ ++ struct d11regs __iomem *regs; ++ u32 tmp; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ tmp = 0; ++ regs = wlc_hw->regs; ++ ++ if (on) { ++ if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) { ++ OR_REG(®s->clk_ctl_st, ++ (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL | ++ CCS_ERSRC_REQ_PHYPLL)); ++ SPINWAIT((R_REG(®s->clk_ctl_st) & ++ (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT), ++ PHYPLL_WAIT_US); ++ ++ tmp = R_REG(®s->clk_ctl_st); ++ if ((tmp & (CCS_ERSRC_AVAIL_HT)) != ++ (CCS_ERSRC_AVAIL_HT)) ++ wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY" ++ " PLL failed\n", __func__); ++ } else { ++ OR_REG(®s->clk_ctl_st, ++ (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL)); ++ SPINWAIT((R_REG(®s->clk_ctl_st) & ++ (CCS_ERSRC_AVAIL_D11PLL | ++ CCS_ERSRC_AVAIL_PHYPLL)) != ++ (CCS_ERSRC_AVAIL_D11PLL | ++ CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US); ++ ++ tmp = R_REG(®s->clk_ctl_st); ++ if ((tmp & ++ (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) ++ != ++ (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) ++ wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on " ++ "PHY PLL failed\n", __func__); ++ } ++ } else { ++ /* ++ * Since the PLL may be shared, other cores can still ++ * be requesting it; so we'll deassert the request but ++ * not wait for status to comply. ++ */ ++ AND_REG(®s->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL); ++ tmp = R_REG(®s->clk_ctl_st); ++ } ++} ++ ++static void brcms_c_coredisable(struct brcms_hardware *wlc_hw) ++{ ++ bool dev_gone; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ dev_gone = brcms_deviceremoved(wlc_hw->wlc); ++ ++ if (dev_gone) ++ return; ++ ++ if (wlc_hw->noreset) ++ return; ++ ++ /* radio off */ ++ wlc_phy_switch_radio(wlc_hw->band->pi, OFF); ++ ++ /* turn off analog core */ ++ wlc_phy_anacore(wlc_hw->band->pi, OFF); ++ ++ /* turn off PHYPLL to save power */ ++ brcms_b_core_phypll_ctl(wlc_hw, false); ++ ++ wlc_hw->clk = false; ++ ai_core_disable(wlc_hw->sih, 0); ++ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); ++} ++ ++static void brcms_c_flushqueues(struct brcms_c_info *wlc) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ uint i; ++ ++ /* free any posted tx packets */ ++ for (i = 0; i < NFIFO; i++) ++ if (wlc_hw->di[i]) { ++ dma_txreclaim(wlc_hw->di[i], DMA_RANGE_ALL); ++ wlc->core->txpktpend[i] = 0; ++ BCMMSG(wlc->wiphy, "pktpend fifo %d clrd\n", i); ++ } ++ ++ /* free any posted rx packets */ ++ dma_rxreclaim(wlc_hw->di[RX_FIFO]); ++} ++ ++static u16 ++brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel) ++{ ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ u16 __iomem *objdata_lo = (u16 __iomem *)®s->objdata; ++ u16 __iomem *objdata_hi = objdata_lo + 1; ++ u16 v; ++ ++ W_REG(®s->objaddr, sel | (offset >> 2)); ++ (void)R_REG(®s->objaddr); ++ if (offset & 2) ++ v = R_REG(objdata_hi); ++ else ++ v = R_REG(objdata_lo); ++ ++ return v; ++} ++ ++static void ++brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, u16 v, ++ u32 sel) ++{ ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ u16 __iomem *objdata_lo = (u16 __iomem *)®s->objdata; ++ u16 __iomem *objdata_hi = objdata_lo + 1; ++ ++ W_REG(®s->objaddr, sel | (offset >> 2)); ++ (void)R_REG(®s->objaddr); ++ if (offset & 2) ++ W_REG(objdata_hi, v); ++ else ++ W_REG(objdata_lo, v); ++} ++ ++/* ++ * Read a single u16 from shared memory. ++ * SHM 'offset' needs to be an even address ++ */ ++u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset) ++{ ++ return brcms_b_read_objmem(wlc_hw, offset, OBJADDR_SHM_SEL); ++} ++ ++/* ++ * Write a single u16 to shared memory. ++ * SHM 'offset' needs to be an even address ++ */ ++void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, u16 v) ++{ ++ brcms_b_write_objmem(wlc_hw, offset, v, OBJADDR_SHM_SEL); ++} ++ ++/* ++ * Copy a buffer to shared memory of specified type . ++ * SHM 'offset' needs to be an even address and ++ * Buffer length 'len' must be an even number of bytes ++ * 'sel' selects the type of memory ++ */ ++void ++brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, uint offset, ++ const void *buf, int len, u32 sel) ++{ ++ u16 v; ++ const u8 *p = (const u8 *)buf; ++ int i; ++ ++ if (len <= 0 || (offset & 1) || (len & 1)) ++ return; ++ ++ for (i = 0; i < len; i += 2) { ++ v = p[i] | (p[i + 1] << 8); ++ brcms_b_write_objmem(wlc_hw, offset + i, v, sel); ++ } ++} ++ ++/* ++ * Copy a piece of shared memory of specified type to a buffer . ++ * SHM 'offset' needs to be an even address and ++ * Buffer length 'len' must be an even number of bytes ++ * 'sel' selects the type of memory ++ */ ++void ++brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, void *buf, ++ int len, u32 sel) ++{ ++ u16 v; ++ u8 *p = (u8 *) buf; ++ int i; ++ ++ if (len <= 0 || (offset & 1) || (len & 1)) ++ return; ++ ++ for (i = 0; i < len; i += 2) { ++ v = brcms_b_read_objmem(wlc_hw, offset + i, sel); ++ p[i] = v & 0xFF; ++ p[i + 1] = (v >> 8) & 0xFF; ++ } ++} ++ ++/* Copy a buffer to shared memory. ++ * SHM 'offset' needs to be an even address and ++ * Buffer length 'len' must be an even number of bytes ++ */ ++static void brcms_c_copyto_shm(struct brcms_c_info *wlc, uint offset, ++ const void *buf, int len) ++{ ++ brcms_b_copyto_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL); ++} ++ ++static void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw, ++ u16 SRL, u16 LRL) ++{ ++ wlc_hw->SRL = SRL; ++ wlc_hw->LRL = LRL; ++ ++ /* write retry limit to SCR, shouldn't need to suspend */ ++ if (wlc_hw->up) { ++ W_REG(&wlc_hw->regs->objaddr, ++ OBJADDR_SCR_SEL | S_DOT11_SRC_LMT); ++ (void)R_REG(&wlc_hw->regs->objaddr); ++ W_REG(&wlc_hw->regs->objdata, wlc_hw->SRL); ++ W_REG(&wlc_hw->regs->objaddr, ++ OBJADDR_SCR_SEL | S_DOT11_LRC_LMT); ++ (void)R_REG(&wlc_hw->regs->objaddr); ++ W_REG(&wlc_hw->regs->objdata, wlc_hw->LRL); ++ } ++} ++ ++static void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set, u32 req_bit) ++{ ++ if (set) { ++ if (mboolisset(wlc_hw->pllreq, req_bit)) ++ return; ++ ++ mboolset(wlc_hw->pllreq, req_bit); ++ ++ if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) { ++ if (!wlc_hw->sbclk) ++ brcms_b_xtal(wlc_hw, ON); ++ } ++ } else { ++ if (!mboolisset(wlc_hw->pllreq, req_bit)) ++ return; ++ ++ mboolclr(wlc_hw->pllreq, req_bit); ++ ++ if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) { ++ if (wlc_hw->sbclk) ++ brcms_b_xtal(wlc_hw, OFF); ++ } ++ } ++} ++ ++static void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail) ++{ ++ wlc_hw->antsel_avail = antsel_avail; ++} ++ ++/* ++ * conditions under which the PM bit should be set in outgoing frames ++ * and STAY_AWAKE is meaningful ++ */ ++static bool brcms_c_ps_allowed(struct brcms_c_info *wlc) ++{ ++ struct brcms_bss_cfg *cfg = wlc->bsscfg; ++ ++ /* disallow PS when one of the following global conditions meets */ ++ if (!wlc->pub->associated) ++ return false; ++ ++ /* disallow PS when one of these meets when not scanning */ ++ if (wlc->monitor) ++ return false; ++ ++ if (cfg->associated) { ++ /* ++ * disallow PS when one of the following ++ * bsscfg specific conditions meets ++ */ ++ if (!cfg->BSS) ++ return false; ++ ++ return false; ++ } ++ ++ return true; ++} ++ ++static void brcms_c_statsupd(struct brcms_c_info *wlc) ++{ ++ int i; ++ struct macstat macstats; ++#ifdef BCMDBG ++ u16 delta; ++ u16 rxf0ovfl; ++ u16 txfunfl[NFIFO]; ++#endif /* BCMDBG */ ++ ++ /* if driver down, make no sense to update stats */ ++ if (!wlc->pub->up) ++ return; ++ ++#ifdef BCMDBG ++ /* save last rx fifo 0 overflow count */ ++ rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl; ++ ++ /* save last tx fifo underflow count */ ++ for (i = 0; i < NFIFO; i++) ++ txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i]; ++#endif /* BCMDBG */ ++ ++ /* Read mac stats from contiguous shared memory */ ++ brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, &macstats, ++ sizeof(struct macstat), OBJADDR_SHM_SEL); ++ ++#ifdef BCMDBG ++ /* check for rx fifo 0 overflow */ ++ delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl); ++ if (delta) ++ wiphy_err(wlc->wiphy, "wl%d: %u rx fifo 0 overflows!\n", ++ wlc->pub->unit, delta); ++ ++ /* check for tx fifo underflows */ ++ for (i = 0; i < NFIFO; i++) { ++ delta = ++ (u16) (wlc->core->macstat_snapshot->txfunfl[i] - ++ txfunfl[i]); ++ if (delta) ++ wiphy_err(wlc->wiphy, "wl%d: %u tx fifo %d underflows!" ++ "\n", wlc->pub->unit, delta, i); ++ } ++#endif /* BCMDBG */ ++ ++ /* merge counters from dma module */ ++ for (i = 0; i < NFIFO; i++) { ++ if (wlc->hw->di[i]) ++ dma_counterreset(wlc->hw->di[i]); ++ } ++} ++ ++static void brcms_b_reset(struct brcms_hardware *wlc_hw) ++{ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ /* reset the core */ ++ if (!brcms_deviceremoved(wlc_hw->wlc)) ++ brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); ++ ++ /* purge the dma rings */ ++ brcms_c_flushqueues(wlc_hw->wlc); ++} ++ ++void brcms_c_reset(struct brcms_c_info *wlc) ++{ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ ++ /* slurp up hw mac counters before core reset */ ++ brcms_c_statsupd(wlc); ++ ++ /* reset our snapshot of macstat counters */ ++ memset((char *)wlc->core->macstat_snapshot, 0, ++ sizeof(struct macstat)); ++ ++ brcms_b_reset(wlc->hw); ++} ++ ++/* Return the channel the driver should initialize during brcms_c_init. ++ * the channel may have to be changed from the currently configured channel ++ * if other configurations are in conflict (bandlocked, 11n mode disabled, ++ * invalid channel for current country, etc.) ++ */ ++static u16 brcms_c_init_chanspec(struct brcms_c_info *wlc) ++{ ++ u16 chanspec = ++ 1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE | ++ WL_CHANSPEC_BAND_2G; ++ ++ return chanspec; ++} ++ ++void brcms_c_init_scb(struct scb *scb) ++{ ++ int i; ++ ++ memset(scb, 0, sizeof(struct scb)); ++ scb->flags = SCB_WMECAP | SCB_HTCAP; ++ for (i = 0; i < NUMPRIO; i++) { ++ scb->seqnum[i] = 0; ++ scb->seqctl[i] = 0xFFFF; ++ } ++ ++ scb->seqctl_nonqos = 0xFFFF; ++ scb->magic = SCB_MAGIC; ++} ++ ++/* d11 core init ++ * reset PSM ++ * download ucode/PCM ++ * let ucode run to suspended ++ * download ucode inits ++ * config other core registers ++ * init dma ++ */ ++static void brcms_b_coreinit(struct brcms_c_info *wlc) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ struct d11regs __iomem *regs; ++ u32 sflags; ++ uint bcnint_us; ++ uint i = 0; ++ bool fifosz_fixup = false; ++ int err = 0; ++ u16 buf[NFIFO]; ++ struct wiphy *wiphy = wlc->wiphy; ++ struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode; ++ ++ regs = wlc_hw->regs; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ /* reset PSM */ ++ brcms_b_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE)); ++ ++ brcms_ucode_download(wlc_hw); ++ /* ++ * FIFOSZ fixup. driver wants to controls the fifo allocation. ++ */ ++ fifosz_fixup = true; ++ ++ /* let the PSM run to the suspended state, set mode to BSS STA */ ++ W_REG(®s->macintstatus, -1); ++ brcms_b_mctrl(wlc_hw, ~0, ++ (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE)); ++ ++ /* wait for ucode to self-suspend after auto-init */ ++ SPINWAIT(((R_REG(®s->macintstatus) & MI_MACSSPNDD) == 0), ++ 1000 * 1000); ++ if ((R_REG(®s->macintstatus) & MI_MACSSPNDD) == 0) ++ wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-" ++ "suspend!\n", wlc_hw->unit); ++ ++ brcms_c_gpio_init(wlc); ++ ++ sflags = ai_core_sflags(wlc_hw->sih, 0, 0); ++ ++ if (D11REV_IS(wlc_hw->corerev, 23)) { ++ if (BRCMS_ISNPHY(wlc_hw->band)) ++ brcms_c_write_inits(wlc_hw, ucode->d11n0initvals16); ++ else ++ wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" ++ " %d\n", __func__, wlc_hw->unit, ++ wlc_hw->corerev); ++ } else if (D11REV_IS(wlc_hw->corerev, 24)) { ++ if (BRCMS_ISLCNPHY(wlc_hw->band)) ++ brcms_c_write_inits(wlc_hw, ucode->d11lcn0initvals24); ++ else ++ wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" ++ " %d\n", __func__, wlc_hw->unit, ++ wlc_hw->corerev); ++ } else { ++ wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n", ++ __func__, wlc_hw->unit, wlc_hw->corerev); ++ } ++ ++ /* For old ucode, txfifo sizes needs to be modified(increased) */ ++ if (fifosz_fixup == true) ++ brcms_b_corerev_fifofixup(wlc_hw); ++ ++ /* check txfifo allocations match between ucode and driver */ ++ buf[TX_AC_BE_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE0); ++ if (buf[TX_AC_BE_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]) { ++ i = TX_AC_BE_FIFO; ++ err = -1; ++ } ++ buf[TX_AC_VI_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE1); ++ if (buf[TX_AC_VI_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]) { ++ i = TX_AC_VI_FIFO; ++ err = -1; ++ } ++ buf[TX_AC_BK_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE2); ++ buf[TX_AC_VO_FIFO] = (buf[TX_AC_BK_FIFO] >> 8) & 0xff; ++ buf[TX_AC_BK_FIFO] &= 0xff; ++ if (buf[TX_AC_BK_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BK_FIFO]) { ++ i = TX_AC_BK_FIFO; ++ err = -1; ++ } ++ if (buf[TX_AC_VO_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO]) { ++ i = TX_AC_VO_FIFO; ++ err = -1; ++ } ++ buf[TX_BCMC_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE3); ++ buf[TX_ATIM_FIFO] = (buf[TX_BCMC_FIFO] >> 8) & 0xff; ++ buf[TX_BCMC_FIFO] &= 0xff; ++ if (buf[TX_BCMC_FIFO] != wlc_hw->xmtfifo_sz[TX_BCMC_FIFO]) { ++ i = TX_BCMC_FIFO; ++ err = -1; ++ } ++ if (buf[TX_ATIM_FIFO] != wlc_hw->xmtfifo_sz[TX_ATIM_FIFO]) { ++ i = TX_ATIM_FIFO; ++ err = -1; ++ } ++ if (err != 0) ++ wiphy_err(wiphy, "wlc_coreinit: txfifo mismatch: ucode size %d" ++ " driver size %d index %d\n", buf[i], ++ wlc_hw->xmtfifo_sz[i], i); ++ ++ /* make sure we can still talk to the mac */ ++ WARN_ON(R_REG(®s->maccontrol) == 0xffffffff); ++ ++ /* band-specific inits done by wlc_bsinit() */ ++ ++ /* Set up frame burst size and antenna swap threshold init values */ ++ brcms_b_write_shm(wlc_hw, M_MBURST_SIZE, MAXTXFRAMEBURST); ++ brcms_b_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT); ++ ++ /* enable one rx interrupt per received frame */ ++ W_REG(®s->intrcvlazy[0], (1 << IRL_FC_SHIFT)); ++ ++ /* set the station mode (BSS STA) */ ++ brcms_b_mctrl(wlc_hw, ++ (MCTL_INFRA | MCTL_DISCARD_PMQ | MCTL_AP), ++ (MCTL_INFRA | MCTL_DISCARD_PMQ)); ++ ++ /* set up Beacon interval */ ++ bcnint_us = 0x8000 << 10; ++ W_REG(®s->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT)); ++ W_REG(®s->tsf_cfpstart, bcnint_us); ++ W_REG(®s->macintstatus, MI_GP1); ++ ++ /* write interrupt mask */ ++ W_REG(®s->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK); ++ ++ /* allow the MAC to control the PHY clock (dynamic on/off) */ ++ brcms_b_macphyclk_set(wlc_hw, ON); ++ ++ /* program dynamic clock control fast powerup delay register */ ++ wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih); ++ W_REG(®s->scc_fastpwrup_dly, wlc->fastpwrup_dly); ++ ++ /* tell the ucode the corerev */ ++ brcms_b_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev); ++ ++ /* tell the ucode MAC capabilities */ ++ brcms_b_write_shm(wlc_hw, M_MACHW_CAP_L, ++ (u16) (wlc_hw->machwcap & 0xffff)); ++ brcms_b_write_shm(wlc_hw, M_MACHW_CAP_H, ++ (u16) ((wlc_hw-> ++ machwcap >> 16) & 0xffff)); ++ ++ /* write retry limits to SCR, this done after PSM init */ ++ W_REG(®s->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT); ++ (void)R_REG(®s->objaddr); ++ W_REG(®s->objdata, wlc_hw->SRL); ++ W_REG(®s->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT); ++ (void)R_REG(®s->objaddr); ++ W_REG(®s->objdata, wlc_hw->LRL); ++ ++ /* write rate fallback retry limits */ ++ brcms_b_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL); ++ brcms_b_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL); ++ ++ AND_REG(®s->ifs_ctl, 0x0FFF); ++ W_REG(®s->ifs_aifsn, EDCF_AIFSN_MIN); ++ ++ /* init the tx dma engines */ ++ for (i = 0; i < NFIFO; i++) { ++ if (wlc_hw->di[i]) ++ dma_txinit(wlc_hw->di[i]); ++ } ++ ++ /* init the rx dma engine(s) and post receive buffers */ ++ dma_rxinit(wlc_hw->di[RX_FIFO]); ++ dma_rxfill(wlc_hw->di[RX_FIFO]); ++} ++ ++void ++static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec, ++ bool mute) { ++ u32 macintmask; ++ bool fastclk; ++ struct brcms_c_info *wlc = wlc_hw->wlc; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ /* request FAST clock if not on */ ++ fastclk = wlc_hw->forcefastclk; ++ if (!fastclk) ++ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); ++ ++ /* disable interrupts */ ++ macintmask = brcms_intrsoff(wlc->wl); ++ ++ /* set up the specified band and chanspec */ ++ brcms_c_setxband(wlc_hw, chspec_bandunit(chanspec)); ++ wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec); ++ ++ /* do one-time phy inits and calibration */ ++ wlc_phy_cal_init(wlc_hw->band->pi); ++ ++ /* core-specific initialization */ ++ brcms_b_coreinit(wlc); ++ ++ /* suspend the tx fifos and mute the phy for preism cac time */ ++ if (mute) ++ brcms_b_mute(wlc_hw, ON, PHY_MUTE_FOR_PREISM); ++ ++ /* band-specific inits */ ++ brcms_b_bsinit(wlc, chanspec); ++ ++ /* restore macintmask */ ++ brcms_intrsrestore(wlc->wl, macintmask); ++ ++ /* seed wake_override with BRCMS_WAKE_OVERRIDE_MACSUSPEND since the mac ++ * is suspended and brcms_c_enable_mac() will clear this override bit. ++ */ ++ mboolset(wlc_hw->wake_override, BRCMS_WAKE_OVERRIDE_MACSUSPEND); ++ ++ /* ++ * initialize mac_suspend_depth to 1 to match ucode ++ * initial suspended state ++ */ ++ wlc_hw->mac_suspend_depth = 1; ++ ++ /* restore the clk */ ++ if (!fastclk) ++ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); ++} ++ ++static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc, ++ u16 chanspec) ++{ ++ /* Save our copy of the chanspec */ ++ wlc->chanspec = chanspec; ++ ++ /* Set the chanspec and power limits for this locale */ ++ brcms_c_channel_set_chanspec(wlc->cmi, chanspec, BRCMS_TXPWR_MAX); ++ ++ if (wlc->stf->ss_algosel_auto) ++ brcms_c_stf_ss_algo_channel_get(wlc, &wlc->stf->ss_algo_channel, ++ chanspec); ++ ++ brcms_c_stf_ss_update(wlc, wlc->band); ++} ++ ++static void ++brcms_default_rateset(struct brcms_c_info *wlc, struct brcms_c_rateset *rs) ++{ ++ brcms_c_rateset_default(rs, NULL, wlc->band->phytype, ++ wlc->band->bandtype, false, BRCMS_RATE_MASK_FULL, ++ (bool) (wlc->pub->_n_enab & SUPPORT_11N), ++ brcms_chspec_bw(wlc->default_bss->chanspec), ++ wlc->stf->txstreams); ++} ++ ++/* derive wlc->band->basic_rate[] table from 'rateset' */ ++static void brcms_c_rate_lookup_init(struct brcms_c_info *wlc, ++ struct brcms_c_rateset *rateset) ++{ ++ u8 rate; ++ u8 mandatory; ++ u8 cck_basic = 0; ++ u8 ofdm_basic = 0; ++ u8 *br = wlc->band->basic_rate; ++ uint i; ++ ++ /* incoming rates are in 500kbps units as in 802.11 Supported Rates */ ++ memset(br, 0, BRCM_MAXRATE + 1); ++ ++ /* For each basic rate in the rates list, make an entry in the ++ * best basic lookup. ++ */ ++ for (i = 0; i < rateset->count; i++) { ++ /* only make an entry for a basic rate */ ++ if (!(rateset->rates[i] & BRCMS_RATE_FLAG)) ++ continue; ++ ++ /* mask off basic bit */ ++ rate = (rateset->rates[i] & BRCMS_RATE_MASK); ++ ++ if (rate > BRCM_MAXRATE) { ++ wiphy_err(wlc->wiphy, "brcms_c_rate_lookup_init: " ++ "invalid rate 0x%X in rate set\n", ++ rateset->rates[i]); ++ continue; ++ } ++ ++ br[rate] = rate; ++ } ++ ++ /* The rate lookup table now has non-zero entries for each ++ * basic rate, equal to the basic rate: br[basicN] = basicN ++ * ++ * To look up the best basic rate corresponding to any ++ * particular rate, code can use the basic_rate table ++ * like this ++ * ++ * basic_rate = wlc->band->basic_rate[tx_rate] ++ * ++ * Make sure there is a best basic rate entry for ++ * every rate by walking up the table from low rates ++ * to high, filling in holes in the lookup table ++ */ ++ ++ for (i = 0; i < wlc->band->hw_rateset.count; i++) { ++ rate = wlc->band->hw_rateset.rates[i]; ++ ++ if (br[rate] != 0) { ++ /* This rate is a basic rate. ++ * Keep track of the best basic rate so far by ++ * modulation type. ++ */ ++ if (is_ofdm_rate(rate)) ++ ofdm_basic = rate; ++ else ++ cck_basic = rate; ++ ++ continue; ++ } ++ ++ /* This rate is not a basic rate so figure out the ++ * best basic rate less than this rate and fill in ++ * the hole in the table ++ */ ++ ++ br[rate] = is_ofdm_rate(rate) ? ofdm_basic : cck_basic; ++ ++ if (br[rate] != 0) ++ continue; ++ ++ if (is_ofdm_rate(rate)) { ++ /* ++ * In 11g and 11a, the OFDM mandatory rates ++ * are 6, 12, and 24 Mbps ++ */ ++ if (rate >= BRCM_RATE_24M) ++ mandatory = BRCM_RATE_24M; ++ else if (rate >= BRCM_RATE_12M) ++ mandatory = BRCM_RATE_12M; ++ else ++ mandatory = BRCM_RATE_6M; ++ } else { ++ /* In 11b, all CCK rates are mandatory 1 - 11 Mbps */ ++ mandatory = rate; ++ } ++ ++ br[rate] = mandatory; ++ } ++} ++ ++static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc, ++ u16 chanspec) ++{ ++ struct brcms_c_rateset default_rateset; ++ uint parkband; ++ uint i, band_order[2]; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ /* ++ * We might have been bandlocked during down and the chip ++ * power-cycled (hibernate). Figure out the right band to park on ++ */ ++ if (wlc->bandlocked || wlc->pub->_nbands == 1) { ++ /* updated in brcms_c_bandlock() */ ++ parkband = wlc->band->bandunit; ++ band_order[0] = band_order[1] = parkband; ++ } else { ++ /* park on the band of the specified chanspec */ ++ parkband = chspec_bandunit(chanspec); ++ ++ /* order so that parkband initialize last */ ++ band_order[0] = parkband ^ 1; ++ band_order[1] = parkband; ++ } ++ ++ /* make each band operational, software state init */ ++ for (i = 0; i < wlc->pub->_nbands; i++) { ++ uint j = band_order[i]; ++ ++ wlc->band = wlc->bandstate[j]; ++ ++ brcms_default_rateset(wlc, &default_rateset); ++ ++ /* fill in hw_rate */ ++ brcms_c_rateset_filter(&default_rateset, &wlc->band->hw_rateset, ++ false, BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK, ++ (bool) (wlc->pub->_n_enab & SUPPORT_11N)); ++ ++ /* init basic rate lookup */ ++ brcms_c_rate_lookup_init(wlc, &default_rateset); ++ } ++ ++ /* sync up phy/radio chanspec */ ++ brcms_c_set_phy_chanspec(wlc, chanspec); ++} ++ ++static void brcms_c_mac_bcn_promisc(struct brcms_c_info *wlc) ++{ ++ if (wlc->bcnmisc_monitor) ++ brcms_b_mctrl(wlc->hw, MCTL_BCNS_PROMISC, MCTL_BCNS_PROMISC); ++ else ++ brcms_b_mctrl(wlc->hw, MCTL_BCNS_PROMISC, 0); ++} ++ ++void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc, bool promisc) ++{ ++ wlc->bcnmisc_monitor = promisc; ++ brcms_c_mac_bcn_promisc(wlc); ++} ++ ++/* set or clear maccontrol bits MCTL_PROMISC and MCTL_KEEPCONTROL */ ++static void brcms_c_mac_promisc(struct brcms_c_info *wlc) ++{ ++ u32 promisc_bits = 0; ++ ++ /* ++ * promiscuous mode just sets MCTL_PROMISC ++ * Note: APs get all BSS traffic without the need to set ++ * the MCTL_PROMISC bit since all BSS data traffic is ++ * directed at the AP ++ */ ++ if (wlc->pub->promisc) ++ promisc_bits |= MCTL_PROMISC; ++ ++ /* monitor mode needs both MCTL_PROMISC and MCTL_KEEPCONTROL ++ * Note: monitor mode also needs MCTL_BCNS_PROMISC, but that is ++ * handled in brcms_c_mac_bcn_promisc() ++ */ ++ if (wlc->monitor) ++ promisc_bits |= MCTL_PROMISC | MCTL_KEEPCONTROL; ++ ++ brcms_b_mctrl(wlc->hw, MCTL_PROMISC | MCTL_KEEPCONTROL, promisc_bits); ++} ++ ++/* ++ * ucode, hwmac update ++ * Channel dependent updates for ucode and hw ++ */ ++static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc) ++{ ++ /* enable or disable any active IBSSs depending on whether or not ++ * we are on the home channel ++ */ ++ if (wlc->home_chanspec == wlc_phy_chanspec_get(wlc->band->pi)) { ++ if (wlc->pub->associated) { ++ /* ++ * BMAC_NOTE: This is something that should be fixed ++ * in ucode inits. I think that the ucode inits set ++ * up the bcn templates and shm values with a bogus ++ * beacon. This should not be done in the inits. If ++ * ucode needs to set up a beacon for testing, the ++ * test routines should write it down, not expect the ++ * inits to populate a bogus beacon. ++ */ ++ if (BRCMS_PHY_11N_CAP(wlc->band)) ++ brcms_b_write_shm(wlc->hw, ++ M_BCN_TXTSF_OFFSET, 0); ++ } ++ } else { ++ /* disable an active IBSS if we are not on the home channel */ ++ } ++ ++ /* update the various promisc bits */ ++ brcms_c_mac_bcn_promisc(wlc); ++ brcms_c_mac_promisc(wlc); ++} ++ ++static void brcms_c_write_rate_shm(struct brcms_c_info *wlc, u8 rate, ++ u8 basic_rate) ++{ ++ u8 phy_rate, index; ++ u8 basic_phy_rate, basic_index; ++ u16 dir_table, basic_table; ++ u16 basic_ptr; ++ ++ /* Shared memory address for the table we are reading */ ++ dir_table = is_ofdm_rate(basic_rate) ? M_RT_DIRMAP_A : M_RT_DIRMAP_B; ++ ++ /* Shared memory address for the table we are writing */ ++ basic_table = is_ofdm_rate(rate) ? M_RT_BBRSMAP_A : M_RT_BBRSMAP_B; ++ ++ /* ++ * for a given rate, the LS-nibble of the PLCP SIGNAL field is ++ * the index into the rate table. ++ */ ++ phy_rate = rate_info[rate] & BRCMS_RATE_MASK; ++ basic_phy_rate = rate_info[basic_rate] & BRCMS_RATE_MASK; ++ index = phy_rate & 0xf; ++ basic_index = basic_phy_rate & 0xf; ++ ++ /* Find the SHM pointer to the ACK rate entry by looking in the ++ * Direct-map Table ++ */ ++ basic_ptr = brcms_b_read_shm(wlc->hw, (dir_table + basic_index * 2)); ++ ++ /* Update the SHM BSS-basic-rate-set mapping table with the pointer ++ * to the correct basic rate for the given incoming rate ++ */ ++ brcms_b_write_shm(wlc->hw, (basic_table + index * 2), basic_ptr); ++} ++ ++static const struct brcms_c_rateset * ++brcms_c_rateset_get_hwrs(struct brcms_c_info *wlc) ++{ ++ const struct brcms_c_rateset *rs_dflt; ++ ++ if (BRCMS_PHY_11N_CAP(wlc->band)) { ++ if (wlc->band->bandtype == BRCM_BAND_5G) ++ rs_dflt = &ofdm_mimo_rates; ++ else ++ rs_dflt = &cck_ofdm_mimo_rates; ++ } else if (wlc->band->gmode) ++ rs_dflt = &cck_ofdm_rates; ++ else ++ rs_dflt = &cck_rates; ++ ++ return rs_dflt; ++} ++ ++static void brcms_c_set_ratetable(struct brcms_c_info *wlc) ++{ ++ const struct brcms_c_rateset *rs_dflt; ++ struct brcms_c_rateset rs; ++ u8 rate, basic_rate; ++ uint i; ++ ++ rs_dflt = brcms_c_rateset_get_hwrs(wlc); ++ ++ brcms_c_rateset_copy(rs_dflt, &rs); ++ brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams); ++ ++ /* walk the phy rate table and update SHM basic rate lookup table */ ++ for (i = 0; i < rs.count; i++) { ++ rate = rs.rates[i] & BRCMS_RATE_MASK; ++ ++ /* for a given rate brcms_basic_rate returns the rate at ++ * which a response ACK/CTS should be sent. ++ */ ++ basic_rate = brcms_basic_rate(wlc, rate); ++ if (basic_rate == 0) ++ /* This should only happen if we are using a ++ * restricted rateset. ++ */ ++ basic_rate = rs.rates[0] & BRCMS_RATE_MASK; ++ ++ brcms_c_write_rate_shm(wlc, rate, basic_rate); ++ } ++} ++ ++/* band-specific init */ ++static void brcms_c_bsinit(struct brcms_c_info *wlc) ++{ ++ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", ++ wlc->pub->unit, wlc->band->bandunit); ++ ++ /* write ucode ACK/CTS rate table */ ++ brcms_c_set_ratetable(wlc); ++ ++ /* update some band specific mac configuration */ ++ brcms_c_ucode_mac_upd(wlc); ++ ++ /* init antenna selection */ ++ brcms_c_antsel_init(wlc->asi); ++ ++} ++ ++/* formula: IDLE_BUSY_RATIO_X_16 = (100-duty_cycle)/duty_cycle*16 */ ++static int ++brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM, ++ bool writeToShm) ++{ ++ int idle_busy_ratio_x_16 = 0; ++ uint offset = ++ isOFDM ? M_TX_IDLE_BUSY_RATIO_X_16_OFDM : ++ M_TX_IDLE_BUSY_RATIO_X_16_CCK; ++ if (duty_cycle > 100 || duty_cycle < 0) { ++ wiphy_err(wlc->wiphy, "wl%d: duty cycle value off limit\n", ++ wlc->pub->unit); ++ return -EINVAL; ++ } ++ if (duty_cycle) ++ idle_busy_ratio_x_16 = (100 - duty_cycle) * 16 / duty_cycle; ++ /* Only write to shared memory when wl is up */ ++ if (writeToShm) ++ brcms_b_write_shm(wlc->hw, offset, (u16) idle_busy_ratio_x_16); ++ ++ if (isOFDM) ++ wlc->tx_duty_cycle_ofdm = (u16) duty_cycle; ++ else ++ wlc->tx_duty_cycle_cck = (u16) duty_cycle; ++ ++ return 0; ++} ++ ++/* ++ * Initialize the base precedence map for dequeueing ++ * from txq based on WME settings ++ */ ++static void brcms_c_tx_prec_map_init(struct brcms_c_info *wlc) ++{ ++ wlc->tx_prec_map = BRCMS_PREC_BMP_ALL; ++ memset(wlc->fifo2prec_map, 0, NFIFO * sizeof(u16)); ++ ++ wlc->fifo2prec_map[TX_AC_BK_FIFO] = BRCMS_PREC_BMP_AC_BK; ++ wlc->fifo2prec_map[TX_AC_BE_FIFO] = BRCMS_PREC_BMP_AC_BE; ++ wlc->fifo2prec_map[TX_AC_VI_FIFO] = BRCMS_PREC_BMP_AC_VI; ++ wlc->fifo2prec_map[TX_AC_VO_FIFO] = BRCMS_PREC_BMP_AC_VO; ++} ++ ++static void ++brcms_c_txflowcontrol_signal(struct brcms_c_info *wlc, ++ struct brcms_txq_info *qi, bool on, int prio) ++{ ++ /* transmit flowcontrol is not yet implemented */ ++} ++ ++static void brcms_c_txflowcontrol_reset(struct brcms_c_info *wlc) ++{ ++ struct brcms_txq_info *qi; ++ ++ for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) { ++ if (qi->stopped) { ++ brcms_c_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO); ++ qi->stopped = 0; ++ } ++ } ++} ++ ++/* push sw hps and wake state through hardware */ ++static void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc) ++{ ++ u32 v1, v2; ++ bool hps; ++ bool awake_before; ++ ++ hps = brcms_c_ps_allowed(wlc); ++ ++ BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps); ++ ++ v1 = R_REG(&wlc->regs->maccontrol); ++ v2 = MCTL_WAKE; ++ if (hps) ++ v2 |= MCTL_HPS; ++ ++ brcms_b_mctrl(wlc->hw, MCTL_WAKE | MCTL_HPS, v2); ++ ++ awake_before = ((v1 & MCTL_WAKE) || ((v1 & MCTL_HPS) == 0)); ++ ++ if (!awake_before) ++ brcms_b_wait_for_wake(wlc->hw); ++} ++ ++/* ++ * Write this BSS config's MAC address to core. ++ * Updates RXE match engine. ++ */ ++static int brcms_c_set_mac(struct brcms_bss_cfg *bsscfg) ++{ ++ int err = 0; ++ struct brcms_c_info *wlc = bsscfg->wlc; ++ ++ /* enter the MAC addr into the RXE match registers */ ++ brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, bsscfg->cur_etheraddr); ++ ++ brcms_c_ampdu_macaddr_upd(wlc); ++ ++ return err; ++} ++ ++/* Write the BSS config's BSSID address to core (set_bssid in d11procs.tcl). ++ * Updates RXE match engine. ++ */ ++static void brcms_c_set_bssid(struct brcms_bss_cfg *bsscfg) ++{ ++ /* we need to update BSSID in RXE match registers */ ++ brcms_c_set_addrmatch(bsscfg->wlc, RCM_BSSID_OFFSET, bsscfg->BSSID); ++} ++ ++static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot) ++{ ++ wlc_hw->shortslot = shortslot; ++ ++ if (wlc_hw->band->bandtype == BRCM_BAND_2G && wlc_hw->up) { ++ brcms_c_suspend_mac_and_wait(wlc_hw->wlc); ++ brcms_b_update_slot_timing(wlc_hw, shortslot); ++ brcms_c_enable_mac(wlc_hw->wlc); ++ } ++} ++ ++/* ++ * Suspend the the MAC and update the slot timing ++ * for standard 11b/g (20us slots) or shortslot 11g (9us slots). ++ */ ++static void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot) ++{ ++ /* use the override if it is set */ ++ if (wlc->shortslot_override != BRCMS_SHORTSLOT_AUTO) ++ shortslot = (wlc->shortslot_override == BRCMS_SHORTSLOT_ON); ++ ++ if (wlc->shortslot == shortslot) ++ return; ++ ++ wlc->shortslot = shortslot; ++ ++ brcms_b_set_shortslot(wlc->hw, shortslot); ++} ++ ++static void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec) ++{ ++ if (wlc->home_chanspec != chanspec) { ++ wlc->home_chanspec = chanspec; ++ ++ if (wlc->bsscfg->associated) ++ wlc->bsscfg->current_bss->chanspec = chanspec; ++ } ++} ++ ++void ++brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec, ++ bool mute, struct txpwr_limits *txpwr) ++{ ++ uint bandunit; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: 0x%x\n", wlc_hw->unit, chanspec); ++ ++ wlc_hw->chanspec = chanspec; ++ ++ /* Switch bands if necessary */ ++ if (wlc_hw->_nbands > 1) { ++ bandunit = chspec_bandunit(chanspec); ++ if (wlc_hw->band->bandunit != bandunit) { ++ /* brcms_b_setband disables other bandunit, ++ * use light band switch if not up yet ++ */ ++ if (wlc_hw->up) { ++ wlc_phy_chanspec_radio_set(wlc_hw-> ++ bandstate[bandunit]-> ++ pi, chanspec); ++ brcms_b_setband(wlc_hw, bandunit, chanspec); ++ } else { ++ brcms_c_setxband(wlc_hw, bandunit); ++ } ++ } ++ } ++ ++ wlc_phy_initcal_enable(wlc_hw->band->pi, !mute); ++ ++ if (!wlc_hw->up) { ++ if (wlc_hw->clk) ++ wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, ++ chanspec); ++ wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec); ++ } else { ++ wlc_phy_chanspec_set(wlc_hw->band->pi, chanspec); ++ wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec); ++ ++ /* Update muting of the channel */ ++ brcms_b_mute(wlc_hw, mute, 0); ++ } ++} ++ ++/* switch to and initialize new band */ ++static void brcms_c_setband(struct brcms_c_info *wlc, ++ uint bandunit) ++{ ++ wlc->band = wlc->bandstate[bandunit]; ++ ++ if (!wlc->pub->up) ++ return; ++ ++ /* wait for at least one beacon before entering sleeping state */ ++ brcms_c_set_ps_ctrl(wlc); ++ ++ /* band-specific initializations */ ++ brcms_c_bsinit(wlc); ++} ++ ++static void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec) ++{ ++ uint bandunit; ++ bool switchband = false; ++ u16 old_chanspec = wlc->chanspec; ++ ++ if (!brcms_c_valid_chanspec_db(wlc->cmi, chanspec)) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Bad channel %d\n", ++ wlc->pub->unit, __func__, CHSPEC_CHANNEL(chanspec)); ++ return; ++ } ++ ++ /* Switch bands if necessary */ ++ if (wlc->pub->_nbands > 1) { ++ bandunit = chspec_bandunit(chanspec); ++ if (wlc->band->bandunit != bandunit || wlc->bandinit_pending) { ++ switchband = true; ++ if (wlc->bandlocked) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: chspec %d " ++ "band is locked!\n", ++ wlc->pub->unit, __func__, ++ CHSPEC_CHANNEL(chanspec)); ++ return; ++ } ++ /* ++ * should the setband call come after the ++ * brcms_b_chanspec() ? if the setband updates ++ * (brcms_c_bsinit) use low level calls to inspect and ++ * set state, the state inspected may be from the wrong ++ * band, or the following brcms_b_set_chanspec() may ++ * undo the work. ++ */ ++ brcms_c_setband(wlc, bandunit); ++ } ++ } ++ ++ /* sync up phy/radio chanspec */ ++ brcms_c_set_phy_chanspec(wlc, chanspec); ++ ++ /* init antenna selection */ ++ if (brcms_chspec_bw(old_chanspec) != brcms_chspec_bw(chanspec)) { ++ brcms_c_antsel_init(wlc->asi); ++ ++ /* Fix the hardware rateset based on bw. ++ * Mainly add MCS32 for 40Mhz, remove MCS 32 for 20Mhz ++ */ ++ brcms_c_rateset_bw_mcs_filter(&wlc->band->hw_rateset, ++ wlc->band->mimo_cap_40 ? brcms_chspec_bw(chanspec) : 0); ++ } ++ ++ /* update some mac configuration since chanspec changed */ ++ brcms_c_ucode_mac_upd(wlc); ++} ++ ++/* ++ * This function changes the phytxctl for beacon based on current ++ * beacon ratespec AND txant setting as per this table: ++ * ratespec CCK ant = wlc->stf->txant ++ * OFDM ant = 3 ++ */ ++void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, ++ u32 bcn_rspec) ++{ ++ u16 phyctl; ++ u16 phytxant = wlc->stf->phytxant; ++ u16 mask = PHY_TXC_ANT_MASK; ++ ++ /* for non-siso rates or default setting, use the available chains */ ++ if (BRCMS_PHY_11N_CAP(wlc->band)) ++ phytxant = brcms_c_stf_phytxchain_sel(wlc, bcn_rspec); ++ ++ phyctl = brcms_b_read_shm(wlc->hw, M_BCN_PCTLWD); ++ phyctl = (phyctl & ~mask) | phytxant; ++ brcms_b_write_shm(wlc->hw, M_BCN_PCTLWD, phyctl); ++} ++ ++/* ++ * centralized protection config change function to simplify debugging, no ++ * consistency checking this should be called only on changes to avoid overhead ++ * in periodic function ++ */ ++void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val) ++{ ++ BCMMSG(wlc->wiphy, "idx %d, val %d\n", idx, val); ++ ++ switch (idx) { ++ case BRCMS_PROT_G_SPEC: ++ wlc->protection->_g = (bool) val; ++ break; ++ case BRCMS_PROT_G_OVR: ++ wlc->protection->g_override = (s8) val; ++ break; ++ case BRCMS_PROT_G_USER: ++ wlc->protection->gmode_user = (u8) val; ++ break; ++ case BRCMS_PROT_OVERLAP: ++ wlc->protection->overlap = (s8) val; ++ break; ++ case BRCMS_PROT_N_USER: ++ wlc->protection->nmode_user = (s8) val; ++ break; ++ case BRCMS_PROT_N_CFG: ++ wlc->protection->n_cfg = (s8) val; ++ break; ++ case BRCMS_PROT_N_CFG_OVR: ++ wlc->protection->n_cfg_override = (s8) val; ++ break; ++ case BRCMS_PROT_N_NONGF: ++ wlc->protection->nongf = (bool) val; ++ break; ++ case BRCMS_PROT_N_NONGF_OVR: ++ wlc->protection->nongf_override = (s8) val; ++ break; ++ case BRCMS_PROT_N_PAM_OVR: ++ wlc->protection->n_pam_override = (s8) val; ++ break; ++ case BRCMS_PROT_N_OBSS: ++ wlc->protection->n_obss = (bool) val; ++ break; ++ ++ default: ++ break; ++ } ++ ++} ++ ++static void brcms_c_ht_update_sgi_rx(struct brcms_c_info *wlc, int val) ++{ ++ if (wlc->pub->up) { ++ brcms_c_update_beacon(wlc); ++ brcms_c_update_probe_resp(wlc, true); ++ } ++} ++ ++static void brcms_c_ht_update_ldpc(struct brcms_c_info *wlc, s8 val) ++{ ++ wlc->stf->ldpc = val; ++ ++ if (wlc->pub->up) { ++ brcms_c_update_beacon(wlc); ++ brcms_c_update_probe_resp(wlc, true); ++ wlc_phy_ldpc_override_set(wlc->band->pi, (val ? true : false)); ++ } ++} ++ ++void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci, ++ const struct ieee80211_tx_queue_params *params, ++ bool suspend) ++{ ++ int i; ++ struct shm_acparams acp_shm; ++ u16 *shm_entry; ++ ++ /* Only apply params if the core is out of reset and has clocks */ ++ if (!wlc->clk) { ++ wiphy_err(wlc->wiphy, "wl%d: %s : no-clock\n", wlc->pub->unit, ++ __func__); ++ return; ++ } ++ ++ memset((char *)&acp_shm, 0, sizeof(struct shm_acparams)); ++ /* fill in shm ac params struct */ ++ acp_shm.txop = params->txop; ++ /* convert from units of 32us to us for ucode */ ++ wlc->edcf_txop[aci & 0x3] = acp_shm.txop = ++ EDCF_TXOP2USEC(acp_shm.txop); ++ acp_shm.aifs = (params->aifs & EDCF_AIFSN_MASK); ++ ++ if (aci == AC_VI && acp_shm.txop == 0 ++ && acp_shm.aifs < EDCF_AIFSN_MAX) ++ acp_shm.aifs++; ++ ++ if (acp_shm.aifs < EDCF_AIFSN_MIN ++ || acp_shm.aifs > EDCF_AIFSN_MAX) { ++ wiphy_err(wlc->wiphy, "wl%d: edcf_setparams: bad " ++ "aifs %d\n", wlc->pub->unit, acp_shm.aifs); ++ } else { ++ acp_shm.cwmin = params->cw_min; ++ acp_shm.cwmax = params->cw_max; ++ acp_shm.cwcur = acp_shm.cwmin; ++ acp_shm.bslots = ++ R_REG(&wlc->regs->tsf_random) & acp_shm.cwcur; ++ acp_shm.reggap = acp_shm.bslots + acp_shm.aifs; ++ /* Indicate the new params to the ucode */ ++ acp_shm.status = brcms_b_read_shm(wlc->hw, (M_EDCF_QINFO + ++ wme_ac2fifo[aci] * ++ M_EDCF_QLEN + ++ M_EDCF_STATUS_OFF)); ++ acp_shm.status |= WME_STATUS_NEWAC; ++ ++ /* Fill in shm acparam table */ ++ shm_entry = (u16 *) &acp_shm; ++ for (i = 0; i < (int)sizeof(struct shm_acparams); i += 2) ++ brcms_b_write_shm(wlc->hw, ++ M_EDCF_QINFO + ++ wme_ac2fifo[aci] * M_EDCF_QLEN + i, ++ *shm_entry++); ++ } ++ ++ if (suspend) { ++ brcms_c_suspend_mac_and_wait(wlc); ++ brcms_c_enable_mac(wlc); ++ } ++} ++ ++void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend) ++{ ++ u16 aci; ++ int i_ac; ++ struct ieee80211_tx_queue_params txq_pars; ++ static const struct edcf_acparam default_edcf_acparams[] = { ++ {EDCF_AC_BE_ACI_STA, EDCF_AC_BE_ECW_STA, EDCF_AC_BE_TXOP_STA}, ++ {EDCF_AC_BK_ACI_STA, EDCF_AC_BK_ECW_STA, EDCF_AC_BK_TXOP_STA}, ++ {EDCF_AC_VI_ACI_STA, EDCF_AC_VI_ECW_STA, EDCF_AC_VI_TXOP_STA}, ++ {EDCF_AC_VO_ACI_STA, EDCF_AC_VO_ECW_STA, EDCF_AC_VO_TXOP_STA} ++ }; /* ucode needs these parameters during its initialization */ ++ const struct edcf_acparam *edcf_acp = &default_edcf_acparams[0]; ++ ++ for (i_ac = 0; i_ac < AC_COUNT; i_ac++, edcf_acp++) { ++ /* find out which ac this set of params applies to */ ++ aci = (edcf_acp->ACI & EDCF_ACI_MASK) >> EDCF_ACI_SHIFT; ++ ++ /* fill in shm ac params struct */ ++ txq_pars.txop = edcf_acp->TXOP; ++ txq_pars.aifs = edcf_acp->ACI; ++ ++ /* CWmin = 2^(ECWmin) - 1 */ ++ txq_pars.cw_min = EDCF_ECW2CW(edcf_acp->ECW & EDCF_ECWMIN_MASK); ++ /* CWmax = 2^(ECWmax) - 1 */ ++ txq_pars.cw_max = EDCF_ECW2CW((edcf_acp->ECW & EDCF_ECWMAX_MASK) ++ >> EDCF_ECWMAX_SHIFT); ++ brcms_c_wme_setparams(wlc, aci, &txq_pars, suspend); ++ } ++ ++ if (suspend) { ++ brcms_c_suspend_mac_and_wait(wlc); ++ brcms_c_enable_mac(wlc); ++ } ++} ++ ++/* maintain LED behavior in down state */ ++static void brcms_c_down_led_upd(struct brcms_c_info *wlc) ++{ ++ /* ++ * maintain LEDs while in down state, turn on sbclk if ++ * not available yet. Turn on sbclk if necessary ++ */ ++ brcms_b_pllreq(wlc->hw, true, BRCMS_PLLREQ_FLIP); ++ brcms_b_pllreq(wlc->hw, false, BRCMS_PLLREQ_FLIP); ++} ++ ++static void brcms_c_radio_monitor_start(struct brcms_c_info *wlc) ++{ ++ /* Don't start the timer if HWRADIO feature is disabled */ ++ if (wlc->radio_monitor) ++ return; ++ ++ wlc->radio_monitor = true; ++ brcms_b_pllreq(wlc->hw, true, BRCMS_PLLREQ_RADIO_MON); ++ brcms_add_timer(wlc->radio_timer, TIMER_INTERVAL_RADIOCHK, true); ++} ++ ++static void brcms_c_radio_disable(struct brcms_c_info *wlc) ++{ ++ if (!wlc->pub->up) { ++ brcms_c_down_led_upd(wlc); ++ return; ++ } ++ ++ brcms_c_radio_monitor_start(wlc); ++ brcms_down(wlc->wl); ++} ++ ++static void brcms_c_radio_enable(struct brcms_c_info *wlc) ++{ ++ if (wlc->pub->up) ++ return; ++ ++ if (brcms_deviceremoved(wlc)) ++ return; ++ ++ brcms_up(wlc->wl); ++} ++ ++static bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc) ++{ ++ if (!wlc->radio_monitor) ++ return true; ++ ++ wlc->radio_monitor = false; ++ brcms_b_pllreq(wlc->hw, false, BRCMS_PLLREQ_RADIO_MON); ++ return brcms_del_timer(wlc->radio_timer); ++} ++ ++/* read hwdisable state and propagate to wlc flag */ ++static void brcms_c_radio_hwdisable_upd(struct brcms_c_info *wlc) ++{ ++ if (wlc->pub->hw_off) ++ return; ++ ++ if (brcms_b_radio_read_hwdisabled(wlc->hw)) ++ mboolset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE); ++ else ++ mboolclr(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE); ++} ++ ++/* ++ * centralized radio disable/enable function, ++ * invoke radio enable/disable after updating hwradio status ++ */ ++static void brcms_c_radio_upd(struct brcms_c_info *wlc) ++{ ++ if (wlc->pub->radio_disabled) ++ brcms_c_radio_disable(wlc); ++ else ++ brcms_c_radio_enable(wlc); ++} ++ ++/* update hwradio status and return it */ ++bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc) ++{ ++ brcms_c_radio_hwdisable_upd(wlc); ++ ++ return mboolisset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE) ? ++ true : false; ++} ++ ++/* periodical query hw radio button while driver is "down" */ ++static void brcms_c_radio_timer(void *arg) ++{ ++ struct brcms_c_info *wlc = (struct brcms_c_info *) arg; ++ ++ if (brcms_deviceremoved(wlc)) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit, ++ __func__); ++ brcms_down(wlc->wl); ++ return; ++ } ++ ++ /* cap mpc off count */ ++ if (wlc->mpc_offcnt < BRCMS_MPC_MAX_DELAYCNT) ++ wlc->mpc_offcnt++; ++ ++ brcms_c_radio_hwdisable_upd(wlc); ++ brcms_c_radio_upd(wlc); ++} ++ ++/* common low-level watchdog code */ ++static void brcms_b_watchdog(void *arg) ++{ ++ struct brcms_c_info *wlc = (struct brcms_c_info *) arg; ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ if (!wlc_hw->up) ++ return; ++ ++ /* increment second count */ ++ wlc_hw->now++; ++ ++ /* Check for FIFO error interrupts */ ++ brcms_b_fifoerrors(wlc_hw); ++ ++ /* make sure RX dma has buffers */ ++ dma_rxfill(wlc->hw->di[RX_FIFO]); ++ ++ wlc_phy_watchdog(wlc_hw->band->pi); ++} ++ ++static void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc) ++{ ++ bool mpc_radio, radio_state; ++ ++ /* ++ * Clear the WL_RADIO_MPC_DISABLE bit when mpc feature is disabled ++ * in case the WL_RADIO_MPC_DISABLE bit was set. Stop the radio ++ * monitor also when WL_RADIO_MPC_DISABLE is the only reason that ++ * the radio is going down. ++ */ ++ if (!wlc->mpc) { ++ if (!wlc->pub->radio_disabled) ++ return; ++ mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE); ++ brcms_c_radio_upd(wlc); ++ if (!wlc->pub->radio_disabled) ++ brcms_c_radio_monitor_stop(wlc); ++ return; ++ } ++ ++ /* ++ * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in ++ * wlc->pub->radio_disabled to go ON, always call radio_upd ++ * synchronously to go OFF, postpone radio_upd to later when ++ * context is safe(e.g. watchdog) ++ */ ++ radio_state = ++ (mboolisset(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE) ? OFF : ++ ON); ++ mpc_radio = (brcms_c_ismpc(wlc) == true) ? OFF : ON; ++ ++ if (radio_state == ON && mpc_radio == OFF) ++ wlc->mpc_delay_off = wlc->mpc_dlycnt; ++ else if (radio_state == OFF && mpc_radio == ON) { ++ mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE); ++ brcms_c_radio_upd(wlc); ++ if (wlc->mpc_offcnt < BRCMS_MPC_THRESHOLD) ++ wlc->mpc_dlycnt = BRCMS_MPC_MAX_DELAYCNT; ++ else ++ wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT; ++ } ++ /* ++ * Below logic is meant to capture the transition from mpc off ++ * to mpc on for reasons other than wlc->mpc_delay_off keeping ++ * the mpc off. In that case reset wlc->mpc_delay_off to ++ * wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off ++ */ ++ if ((wlc->prev_non_delay_mpc == false) && ++ (brcms_c_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off) ++ wlc->mpc_delay_off = wlc->mpc_dlycnt; ++ ++ wlc->prev_non_delay_mpc = brcms_c_is_non_delay_mpc(wlc); ++} ++ ++/* common watchdog code */ ++static void brcms_c_watchdog(void *arg) ++{ ++ struct brcms_c_info *wlc = (struct brcms_c_info *) arg; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ ++ if (!wlc->pub->up) ++ return; ++ ++ if (brcms_deviceremoved(wlc)) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit, ++ __func__); ++ brcms_down(wlc->wl); ++ return; ++ } ++ ++ /* increment second count */ ++ wlc->pub->now++; ++ ++ /* delay radio disable */ ++ if (wlc->mpc_delay_off) { ++ if (--wlc->mpc_delay_off == 0) { ++ mboolset(wlc->pub->radio_disabled, ++ WL_RADIO_MPC_DISABLE); ++ if (wlc->mpc && brcms_c_ismpc(wlc)) ++ wlc->mpc_offcnt = 0; ++ } ++ } ++ ++ /* mpc sync */ ++ brcms_c_radio_mpc_upd(wlc); ++ /* radio sync: sw/hw/mpc --> radio_disable/radio_enable */ ++ brcms_c_radio_hwdisable_upd(wlc); ++ brcms_c_radio_upd(wlc); ++ /* if radio is disable, driver may be down, quit here */ ++ if (wlc->pub->radio_disabled) ++ return; ++ ++ brcms_b_watchdog(wlc); ++ ++ /* ++ * occasionally sample mac stat counters to ++ * detect 16-bit counter wrap ++ */ ++ if ((wlc->pub->now % SW_TIMER_MAC_STAT_UPD) == 0) ++ brcms_c_statsupd(wlc); ++ ++ if (BRCMS_ISNPHY(wlc->band) && ++ ((wlc->pub->now - wlc->tempsense_lasttime) >= ++ BRCMS_TEMPSENSE_PERIOD)) { ++ wlc->tempsense_lasttime = wlc->pub->now; ++ brcms_c_tempsense_upd(wlc); ++ } ++} ++ ++static void brcms_c_watchdog_by_timer(void *arg) ++{ ++ brcms_c_watchdog(arg); ++} ++ ++static bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit) ++{ ++ wlc->wdtimer = brcms_init_timer(wlc->wl, brcms_c_watchdog_by_timer, ++ wlc, "watchdog"); ++ if (!wlc->wdtimer) { ++ wiphy_err(wlc->wiphy, "wl%d: wl_init_timer for wdtimer " ++ "failed\n", unit); ++ goto fail; ++ } ++ ++ wlc->radio_timer = brcms_init_timer(wlc->wl, brcms_c_radio_timer, ++ wlc, "radio"); ++ if (!wlc->radio_timer) { ++ wiphy_err(wlc->wiphy, "wl%d: wl_init_timer for radio_timer " ++ "failed\n", unit); ++ goto fail; ++ } ++ ++ return true; ++ ++ fail: ++ return false; ++} ++ ++/* ++ * Initialize brcms_c_info default values ... ++ * may get overrides later in this function ++ */ ++static void brcms_c_info_init(struct brcms_c_info *wlc, int unit) ++{ ++ int i; ++ ++ /* Save our copy of the chanspec */ ++ wlc->chanspec = ch20mhz_chspec(1); ++ ++ /* various 802.11g modes */ ++ wlc->shortslot = false; ++ wlc->shortslot_override = BRCMS_SHORTSLOT_AUTO; ++ ++ brcms_c_protection_upd(wlc, BRCMS_PROT_G_OVR, BRCMS_PROTECTION_AUTO); ++ brcms_c_protection_upd(wlc, BRCMS_PROT_G_SPEC, false); ++ ++ brcms_c_protection_upd(wlc, BRCMS_PROT_N_CFG_OVR, ++ BRCMS_PROTECTION_AUTO); ++ brcms_c_protection_upd(wlc, BRCMS_PROT_N_CFG, BRCMS_N_PROTECTION_OFF); ++ brcms_c_protection_upd(wlc, BRCMS_PROT_N_NONGF_OVR, ++ BRCMS_PROTECTION_AUTO); ++ brcms_c_protection_upd(wlc, BRCMS_PROT_N_NONGF, false); ++ brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR, AUTO); ++ ++ brcms_c_protection_upd(wlc, BRCMS_PROT_OVERLAP, ++ BRCMS_PROTECTION_CTL_OVERLAP); ++ ++ /* 802.11g draft 4.0 NonERP elt advertisement */ ++ wlc->include_legacy_erp = true; ++ ++ wlc->stf->ant_rx_ovr = ANT_RX_DIV_DEF; ++ wlc->stf->txant = ANT_TX_DEF; ++ ++ wlc->prb_resp_timeout = BRCMS_PRB_RESP_TIMEOUT; ++ ++ wlc->usr_fragthresh = DOT11_DEFAULT_FRAG_LEN; ++ for (i = 0; i < NFIFO; i++) ++ wlc->fragthresh[i] = DOT11_DEFAULT_FRAG_LEN; ++ wlc->RTSThresh = DOT11_DEFAULT_RTS_LEN; ++ ++ /* default rate fallback retry limits */ ++ wlc->SFBL = RETRY_SHORT_FB; ++ wlc->LFBL = RETRY_LONG_FB; ++ ++ /* default mac retry limits */ ++ wlc->SRL = RETRY_SHORT_DEF; ++ wlc->LRL = RETRY_LONG_DEF; ++ ++ /* WME QoS mode is Auto by default */ ++ wlc->pub->_ampdu = AMPDU_AGG_HOST; ++ wlc->pub->bcmerror = 0; ++ ++ /* initialize mpc delay */ ++ wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT; ++} ++ ++static uint brcms_c_attach_module(struct brcms_c_info *wlc) ++{ ++ uint err = 0; ++ uint unit; ++ unit = wlc->pub->unit; ++ ++ wlc->asi = brcms_c_antsel_attach(wlc); ++ if (wlc->asi == NULL) { ++ wiphy_err(wlc->wiphy, "wl%d: attach: antsel_attach " ++ "failed\n", unit); ++ err = 44; ++ goto fail; ++ } ++ ++ wlc->ampdu = brcms_c_ampdu_attach(wlc); ++ if (wlc->ampdu == NULL) { ++ wiphy_err(wlc->wiphy, "wl%d: attach: ampdu_attach " ++ "failed\n", unit); ++ err = 50; ++ goto fail; ++ } ++ ++ if ((brcms_c_stf_attach(wlc) != 0)) { ++ wiphy_err(wlc->wiphy, "wl%d: attach: stf_attach " ++ "failed\n", unit); ++ err = 68; ++ goto fail; ++ } ++ fail: ++ return err; ++} ++ ++struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc) ++{ ++ return wlc->pub; ++} ++ ++/* low level attach ++ * run backplane attach, init nvram ++ * run phy attach ++ * initialize software state for each core and band ++ * put the whole chip in reset(driver down state), no clock ++ */ ++static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, ++ uint unit, bool piomode, void __iomem *regsva, ++ struct pci_dev *btparam) ++{ ++ struct brcms_hardware *wlc_hw; ++ struct d11regs __iomem *regs; ++ char *macaddr = NULL; ++ uint err = 0; ++ uint j; ++ bool wme = false; ++ struct shared_phy_params sha_params; ++ struct wiphy *wiphy = wlc->wiphy; ++ ++ BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, vendor, ++ device); ++ ++ wme = true; ++ ++ wlc_hw = wlc->hw; ++ wlc_hw->wlc = wlc; ++ wlc_hw->unit = unit; ++ wlc_hw->band = wlc_hw->bandstate[0]; ++ wlc_hw->_piomode = piomode; ++ ++ /* populate struct brcms_hardware with default values */ ++ brcms_b_info_init(wlc_hw); ++ ++ /* ++ * Do the hardware portion of the attach. Also initialize software ++ * state that depends on the particular hardware we are running. ++ */ ++ wlc_hw->sih = ai_attach(regsva, btparam); ++ if (wlc_hw->sih == NULL) { ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: si_attach failed\n", ++ unit); ++ err = 11; ++ goto fail; ++ } ++ ++ /* verify again the device is supported */ ++ if (!brcms_c_chipmatch(vendor, device)) { ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported " ++ "vendor/device (0x%x/0x%x)\n", ++ unit, vendor, device); ++ err = 12; ++ goto fail; ++ } ++ ++ wlc_hw->vendorid = vendor; ++ wlc_hw->deviceid = device; ++ ++ /* set bar0 window to point at D11 core */ ++ wlc_hw->regs = (struct d11regs __iomem *) ++ ai_setcore(wlc_hw->sih, D11_CORE_ID, 0); ++ wlc_hw->corerev = ai_corerev(wlc_hw->sih); ++ ++ regs = wlc_hw->regs; ++ ++ wlc->regs = wlc_hw->regs; ++ ++ /* validate chip, chiprev and corerev */ ++ if (!brcms_c_isgoodchip(wlc_hw)) { ++ err = 13; ++ goto fail; ++ } ++ ++ /* initialize power control registers */ ++ ai_clkctl_init(wlc_hw->sih); ++ ++ /* request fastclock and force fastclock for the rest of attach ++ * bring the d11 core out of reset. ++ * For PMU chips, the first wlc_clkctl_clk is no-op since core-clk ++ * is still false; But it will be called again inside wlc_corereset, ++ * after d11 is out of reset. ++ */ ++ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); ++ brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); ++ ++ if (!brcms_b_validate_chip_access(wlc_hw)) { ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: validate_chip_access " ++ "failed\n", unit); ++ err = 14; ++ goto fail; ++ } ++ ++ /* get the board rev, used just below */ ++ j = getintvar(wlc_hw->sih, BRCMS_SROM_BOARDREV); ++ /* promote srom boardrev of 0xFF to 1 */ ++ if (j == BOARDREV_PROMOTABLE) ++ j = BOARDREV_PROMOTED; ++ wlc_hw->boardrev = (u16) j; ++ if (!brcms_c_validboardtype(wlc_hw)) { ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported Broadcom " ++ "board type (0x%x)" " or revision level (0x%x)\n", ++ unit, wlc_hw->sih->boardtype, wlc_hw->boardrev); ++ err = 15; ++ goto fail; ++ } ++ wlc_hw->sromrev = (u8) getintvar(wlc_hw->sih, BRCMS_SROM_REV); ++ wlc_hw->boardflags = (u32) getintvar(wlc_hw->sih, ++ BRCMS_SROM_BOARDFLAGS); ++ wlc_hw->boardflags2 = (u32) getintvar(wlc_hw->sih, ++ BRCMS_SROM_BOARDFLAGS2); ++ ++ if (wlc_hw->boardflags & BFL_NOPLLDOWN) ++ brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED); ++ ++ /* check device id(srom, nvram etc.) to set bands */ ++ if (wlc_hw->deviceid == BCM43224_D11N_ID || ++ wlc_hw->deviceid == BCM43224_D11N_ID_VEN1) ++ /* Dualband boards */ ++ wlc_hw->_nbands = 2; ++ else ++ wlc_hw->_nbands = 1; ++ ++ if ((wlc_hw->sih->chip == BCM43225_CHIP_ID)) ++ wlc_hw->_nbands = 1; ++ ++ /* BMAC_NOTE: remove init of pub values when brcms_c_attach() ++ * unconditionally does the init of these values ++ */ ++ wlc->vendorid = wlc_hw->vendorid; ++ wlc->deviceid = wlc_hw->deviceid; ++ wlc->pub->sih = wlc_hw->sih; ++ wlc->pub->corerev = wlc_hw->corerev; ++ wlc->pub->sromrev = wlc_hw->sromrev; ++ wlc->pub->boardrev = wlc_hw->boardrev; ++ wlc->pub->boardflags = wlc_hw->boardflags; ++ wlc->pub->boardflags2 = wlc_hw->boardflags2; ++ wlc->pub->_nbands = wlc_hw->_nbands; ++ ++ wlc_hw->physhim = wlc_phy_shim_attach(wlc_hw, wlc->wl, wlc); ++ ++ if (wlc_hw->physhim == NULL) { ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_shim_attach " ++ "failed\n", unit); ++ err = 25; ++ goto fail; ++ } ++ ++ /* pass all the parameters to wlc_phy_shared_attach in one struct */ ++ sha_params.sih = wlc_hw->sih; ++ sha_params.physhim = wlc_hw->physhim; ++ sha_params.unit = unit; ++ sha_params.corerev = wlc_hw->corerev; ++ sha_params.vid = wlc_hw->vendorid; ++ sha_params.did = wlc_hw->deviceid; ++ sha_params.chip = wlc_hw->sih->chip; ++ sha_params.chiprev = wlc_hw->sih->chiprev; ++ sha_params.chippkg = wlc_hw->sih->chippkg; ++ sha_params.sromrev = wlc_hw->sromrev; ++ sha_params.boardtype = wlc_hw->sih->boardtype; ++ sha_params.boardrev = wlc_hw->boardrev; ++ sha_params.boardvendor = wlc_hw->sih->boardvendor; ++ sha_params.boardflags = wlc_hw->boardflags; ++ sha_params.boardflags2 = wlc_hw->boardflags2; ++ sha_params.buscorerev = wlc_hw->sih->buscorerev; ++ ++ /* alloc and save pointer to shared phy state area */ ++ wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params); ++ if (!wlc_hw->phy_sh) { ++ err = 16; ++ goto fail; ++ } ++ ++ /* initialize software state for each core and band */ ++ for (j = 0; j < wlc_hw->_nbands; j++) { ++ /* ++ * band0 is always 2.4Ghz ++ * band1, if present, is 5Ghz ++ */ ++ ++ brcms_c_setxband(wlc_hw, j); ++ ++ wlc_hw->band->bandunit = j; ++ wlc_hw->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G; ++ wlc->band->bandunit = j; ++ wlc->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G; ++ wlc->core->coreidx = ai_coreidx(wlc_hw->sih); ++ ++ wlc_hw->machwcap = R_REG(®s->machwcap); ++ wlc_hw->machwcap_backup = wlc_hw->machwcap; ++ ++ /* init tx fifo size */ ++ wlc_hw->xmtfifo_sz = ++ xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)]; ++ ++ /* Get a phy for this band */ ++ wlc_hw->band->pi = ++ wlc_phy_attach(wlc_hw->phy_sh, regs, ++ wlc_hw->band->bandtype, ++ wlc->wiphy); ++ if (wlc_hw->band->pi == NULL) { ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_" ++ "attach failed\n", unit); ++ err = 17; ++ goto fail; ++ } ++ ++ wlc_phy_machwcap_set(wlc_hw->band->pi, wlc_hw->machwcap); ++ ++ wlc_phy_get_phyversion(wlc_hw->band->pi, &wlc_hw->band->phytype, ++ &wlc_hw->band->phyrev, ++ &wlc_hw->band->radioid, ++ &wlc_hw->band->radiorev); ++ wlc_hw->band->abgphy_encore = ++ wlc_phy_get_encore(wlc_hw->band->pi); ++ wlc->band->abgphy_encore = wlc_phy_get_encore(wlc_hw->band->pi); ++ wlc_hw->band->core_flags = ++ wlc_phy_get_coreflags(wlc_hw->band->pi); ++ ++ /* verify good phy_type & supported phy revision */ ++ if (BRCMS_ISNPHY(wlc_hw->band)) { ++ if (NCONF_HAS(wlc_hw->band->phyrev)) ++ goto good_phy; ++ else ++ goto bad_phy; ++ } else if (BRCMS_ISLCNPHY(wlc_hw->band)) { ++ if (LCNCONF_HAS(wlc_hw->band->phyrev)) ++ goto good_phy; ++ else ++ goto bad_phy; ++ } else { ++ bad_phy: ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: unsupported " ++ "phy type/rev (%d/%d)\n", unit, ++ wlc_hw->band->phytype, wlc_hw->band->phyrev); ++ err = 18; ++ goto fail; ++ } ++ ++ good_phy: ++ /* ++ * BMAC_NOTE: wlc->band->pi should not be set below and should ++ * be done in the high level attach. However we can not make ++ * that change until all low level access is changed to ++ * wlc_hw->band->pi. Instead do the wlc->band->pi init below, ++ * keeping wlc_hw->band->pi as well for incremental update of ++ * low level fns, and cut over low only init when all fns ++ * updated. ++ */ ++ wlc->band->pi = wlc_hw->band->pi; ++ wlc->band->phytype = wlc_hw->band->phytype; ++ wlc->band->phyrev = wlc_hw->band->phyrev; ++ wlc->band->radioid = wlc_hw->band->radioid; ++ wlc->band->radiorev = wlc_hw->band->radiorev; ++ ++ /* default contention windows size limits */ ++ wlc_hw->band->CWmin = APHY_CWMIN; ++ wlc_hw->band->CWmax = PHY_CWMAX; ++ ++ if (!brcms_b_attach_dmapio(wlc, j, wme)) { ++ err = 19; ++ goto fail; ++ } ++ } ++ ++ /* disable core to match driver "down" state */ ++ brcms_c_coredisable(wlc_hw); ++ ++ /* Match driver "down" state */ ++ ai_pci_down(wlc_hw->sih); ++ ++ /* register sb interrupt callback functions */ ++ ai_register_intr_callback(wlc_hw->sih, (void *)brcms_c_wlintrsoff, ++ (void *)brcms_c_wlintrsrestore, NULL, wlc); ++ ++ /* turn off pll and xtal to match driver "down" state */ ++ brcms_b_xtal(wlc_hw, OFF); ++ ++ /* ******************************************************************* ++ * The hardware is in the DOWN state at this point. D11 core ++ * or cores are in reset with clocks off, and the board PLLs ++ * are off if possible. ++ * ++ * Beyond this point, wlc->sbclk == false and chip registers ++ * should not be touched. ++ ********************************************************************* ++ */ ++ ++ /* init etheraddr state variables */ ++ macaddr = brcms_c_get_macaddr(wlc_hw); ++ if (macaddr == NULL) { ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: macaddr not found\n", ++ unit); ++ err = 21; ++ goto fail; ++ } ++ if (!mac_pton(macaddr, wlc_hw->etheraddr) || ++ is_broadcast_ether_addr(wlc_hw->etheraddr) || ++ is_zero_ether_addr(wlc_hw->etheraddr)) { ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr %s\n", ++ unit, macaddr); ++ err = 22; ++ goto fail; ++ } ++ ++ BCMMSG(wlc->wiphy, ++ "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n", ++ wlc_hw->deviceid, wlc_hw->_nbands, ++ wlc_hw->sih->boardtype, macaddr); ++ ++ return err; ++ ++ fail: ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: failed with err %d\n", unit, ++ err); ++ return err; ++} ++ ++static void brcms_c_attach_antgain_init(struct brcms_c_info *wlc) ++{ ++ uint unit; ++ unit = wlc->pub->unit; ++ ++ if ((wlc->band->antgain == -1) && (wlc->pub->sromrev == 1)) { ++ /* default antenna gain for srom rev 1 is 2 dBm (8 qdbm) */ ++ wlc->band->antgain = 8; ++ } else if (wlc->band->antgain == -1) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in" ++ " srom, using 2dB\n", unit, __func__); ++ wlc->band->antgain = 8; ++ } else { ++ s8 gain, fract; ++ /* Older sroms specified gain in whole dbm only. In order ++ * be able to specify qdbm granularity and remain backward ++ * compatible the whole dbms are now encoded in only ++ * low 6 bits and remaining qdbms are encoded in the hi 2 bits. ++ * 6 bit signed number ranges from -32 - 31. ++ * ++ * Examples: ++ * 0x1 = 1 db, ++ * 0xc1 = 1.75 db (1 + 3 quarters), ++ * 0x3f = -1 (-1 + 0 quarters), ++ * 0x7f = -.75 (-1 + 1 quarters) = -3 qdbm. ++ * 0xbf = -.50 (-1 + 2 quarters) = -2 qdbm. ++ */ ++ gain = wlc->band->antgain & 0x3f; ++ gain <<= 2; /* Sign extend */ ++ gain >>= 2; ++ fract = (wlc->band->antgain & 0xc0) >> 6; ++ wlc->band->antgain = 4 * gain + fract; ++ } ++} ++ ++static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc) ++{ ++ int aa; ++ uint unit; ++ int bandtype; ++ struct si_pub *sih = wlc->hw->sih; ++ ++ unit = wlc->pub->unit; ++ bandtype = wlc->band->bandtype; ++ ++ /* get antennas available */ ++ if (bandtype == BRCM_BAND_5G) ++ aa = (s8) getintvar(sih, BRCMS_SROM_AA5G); ++ else ++ aa = (s8) getintvar(sih, BRCMS_SROM_AA2G); ++ ++ if ((aa < 1) || (aa > 15)) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in" ++ " srom (0x%x), using 3\n", unit, __func__, aa); ++ aa = 3; ++ } ++ ++ /* reset the defaults if we have a single antenna */ ++ if (aa == 1) { ++ wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_0; ++ wlc->stf->txant = ANT_TX_FORCE_0; ++ } else if (aa == 2) { ++ wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_1; ++ wlc->stf->txant = ANT_TX_FORCE_1; ++ } else { ++ } ++ ++ /* Compute Antenna Gain */ ++ if (bandtype == BRCM_BAND_5G) ++ wlc->band->antgain = (s8) getintvar(sih, BRCMS_SROM_AG1); ++ else ++ wlc->band->antgain = (s8) getintvar(sih, BRCMS_SROM_AG0); ++ ++ brcms_c_attach_antgain_init(wlc); ++ ++ return true; ++} ++ ++static void brcms_c_bss_default_init(struct brcms_c_info *wlc) ++{ ++ u16 chanspec; ++ struct brcms_band *band; ++ struct brcms_bss_info *bi = wlc->default_bss; ++ ++ /* init default and target BSS with some sane initial values */ ++ memset((char *)(bi), 0, sizeof(struct brcms_bss_info)); ++ bi->beacon_period = BEACON_INTERVAL_DEFAULT; ++ ++ /* fill the default channel as the first valid channel ++ * starting from the 2G channels ++ */ ++ chanspec = ch20mhz_chspec(1); ++ wlc->home_chanspec = bi->chanspec = chanspec; ++ ++ /* find the band of our default channel */ ++ band = wlc->band; ++ if (wlc->pub->_nbands > 1 && ++ band->bandunit != chspec_bandunit(chanspec)) ++ band = wlc->bandstate[OTHERBANDUNIT(wlc)]; ++ ++ /* init bss rates to the band specific default rate set */ ++ brcms_c_rateset_default(&bi->rateset, NULL, band->phytype, ++ band->bandtype, false, BRCMS_RATE_MASK_FULL, ++ (bool) (wlc->pub->_n_enab & SUPPORT_11N), ++ brcms_chspec_bw(chanspec), wlc->stf->txstreams); ++ ++ if (wlc->pub->_n_enab & SUPPORT_11N) ++ bi->flags |= BRCMS_BSS_HT; ++} ++ ++static struct brcms_txq_info *brcms_c_txq_alloc(struct brcms_c_info *wlc) ++{ ++ struct brcms_txq_info *qi, *p; ++ ++ qi = kzalloc(sizeof(struct brcms_txq_info), GFP_ATOMIC); ++ if (qi != NULL) { ++ /* ++ * Have enough room for control packets along with HI watermark ++ * Also, add room to txq for total psq packets if all the SCBs ++ * leave PS mode. The watermark for flowcontrol to OS packets ++ * will remain the same ++ */ ++ brcmu_pktq_init(&qi->q, BRCMS_PREC_COUNT, ++ 2 * BRCMS_DATAHIWAT + PKTQ_LEN_DEFAULT); ++ ++ /* add this queue to the the global list */ ++ p = wlc->tx_queues; ++ if (p == NULL) { ++ wlc->tx_queues = qi; ++ } else { ++ while (p->next != NULL) ++ p = p->next; ++ p->next = qi; ++ } ++ } ++ return qi; ++} ++ ++static void brcms_c_txq_free(struct brcms_c_info *wlc, ++ struct brcms_txq_info *qi) ++{ ++ struct brcms_txq_info *p; ++ ++ if (qi == NULL) ++ return; ++ ++ /* remove the queue from the linked list */ ++ p = wlc->tx_queues; ++ if (p == qi) ++ wlc->tx_queues = p->next; ++ else { ++ while (p != NULL && p->next != qi) ++ p = p->next; ++ if (p != NULL) ++ p->next = p->next->next; ++ } ++ ++ kfree(qi); ++} ++ ++static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap) ++{ ++ uint i; ++ struct brcms_band *band; ++ ++ for (i = 0; i < wlc->pub->_nbands; i++) { ++ band = wlc->bandstate[i]; ++ if (band->bandtype == BRCM_BAND_5G) { ++ if ((bwcap == BRCMS_N_BW_40ALL) ++ || (bwcap == BRCMS_N_BW_20IN2G_40IN5G)) ++ band->mimo_cap_40 = true; ++ else ++ band->mimo_cap_40 = false; ++ } else { ++ if (bwcap == BRCMS_N_BW_40ALL) ++ band->mimo_cap_40 = true; ++ else ++ band->mimo_cap_40 = false; ++ } ++ } ++} ++ ++static void brcms_c_timers_deinit(struct brcms_c_info *wlc) ++{ ++ /* free timer state */ ++ if (wlc->wdtimer) { ++ brcms_free_timer(wlc->wdtimer); ++ wlc->wdtimer = NULL; ++ } ++ if (wlc->radio_timer) { ++ brcms_free_timer(wlc->radio_timer); ++ wlc->radio_timer = NULL; ++ } ++} ++ ++static void brcms_c_detach_module(struct brcms_c_info *wlc) ++{ ++ if (wlc->asi) { ++ brcms_c_antsel_detach(wlc->asi); ++ wlc->asi = NULL; ++ } ++ ++ if (wlc->ampdu) { ++ brcms_c_ampdu_detach(wlc->ampdu); ++ wlc->ampdu = NULL; ++ } ++ ++ brcms_c_stf_detach(wlc); ++} ++ ++/* ++ * low level detach ++ */ ++static int brcms_b_detach(struct brcms_c_info *wlc) ++{ ++ uint i; ++ struct brcms_hw_band *band; ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ int callbacks; ++ ++ callbacks = 0; ++ ++ if (wlc_hw->sih) { ++ /* ++ * detach interrupt sync mechanism since interrupt is disabled ++ * and per-port interrupt object may has been freed. this must ++ * be done before sb core switch ++ */ ++ ai_deregister_intr_callback(wlc_hw->sih); ++ ai_pci_sleep(wlc_hw->sih); ++ } ++ ++ brcms_b_detach_dmapio(wlc_hw); ++ ++ band = wlc_hw->band; ++ for (i = 0; i < wlc_hw->_nbands; i++) { ++ if (band->pi) { ++ /* Detach this band's phy */ ++ wlc_phy_detach(band->pi); ++ band->pi = NULL; ++ } ++ band = wlc_hw->bandstate[OTHERBANDUNIT(wlc)]; ++ } ++ ++ /* Free shared phy state */ ++ kfree(wlc_hw->phy_sh); ++ ++ wlc_phy_shim_detach(wlc_hw->physhim); ++ ++ if (wlc_hw->sih) { ++ ai_detach(wlc_hw->sih); ++ wlc_hw->sih = NULL; ++ } ++ ++ return callbacks; ++ ++} ++ ++/* ++ * Return a count of the number of driver callbacks still pending. ++ * ++ * General policy is that brcms_c_detach can only dealloc/free software states. ++ * It can NOT touch hardware registers since the d11core may be in reset and ++ * clock may not be available. ++ * One exception is sb register access, which is possible if crystal is turned ++ * on after "down" state, driver should avoid software timer with the exception ++ * of radio_monitor. ++ */ ++uint brcms_c_detach(struct brcms_c_info *wlc) ++{ ++ uint callbacks = 0; ++ ++ if (wlc == NULL) ++ return 0; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ ++ callbacks += brcms_b_detach(wlc); ++ ++ /* delete software timers */ ++ if (!brcms_c_radio_monitor_stop(wlc)) ++ callbacks++; ++ ++ brcms_c_channel_mgr_detach(wlc->cmi); ++ ++ brcms_c_timers_deinit(wlc); ++ ++ brcms_c_detach_module(wlc); ++ ++ ++ while (wlc->tx_queues != NULL) ++ brcms_c_txq_free(wlc, wlc->tx_queues); ++ ++ brcms_c_detach_mfree(wlc); ++ return callbacks; ++} ++ ++/* update state that depends on the current value of "ap" */ ++static void brcms_c_ap_upd(struct brcms_c_info *wlc) ++{ ++ /* STA-BSS; short capable */ ++ wlc->PLCPHdr_override = BRCMS_PLCP_SHORT; ++ ++ /* fixup mpc */ ++ wlc->mpc = true; ++} ++ ++/* Initialize just the hardware when coming out of POR or S3/S5 system states */ ++static void brcms_b_hw_up(struct brcms_hardware *wlc_hw) ++{ ++ if (wlc_hw->wlc->pub->hw_up) ++ return; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ /* ++ * Enable pll and xtal, initialize the power control registers, ++ * and force fastclock for the remainder of brcms_c_up(). ++ */ ++ brcms_b_xtal(wlc_hw, ON); ++ ai_clkctl_init(wlc_hw->sih); ++ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); ++ ++ ai_pci_fixcfg(wlc_hw->sih); ++ ++ /* ++ * AI chip doesn't restore bar0win2 on ++ * hibernation/resume, need sw fixup ++ */ ++ if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || ++ (wlc_hw->sih->chip == BCM43225_CHIP_ID)) ++ wlc_hw->regs = (struct d11regs __iomem *) ++ ai_setcore(wlc_hw->sih, D11_CORE_ID, 0); ++ ++ /* ++ * Inform phy that a POR reset has occurred so ++ * it does a complete phy init ++ */ ++ wlc_phy_por_inform(wlc_hw->band->pi); ++ ++ wlc_hw->ucode_loaded = false; ++ wlc_hw->wlc->pub->hw_up = true; ++ ++ if ((wlc_hw->boardflags & BFL_FEM) ++ && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) { ++ if (! ++ (wlc_hw->boardrev >= 0x1250 ++ && (wlc_hw->boardflags & BFL_FEM_BT))) ++ ai_epa_4313war(wlc_hw->sih); ++ } ++} ++ ++static int brcms_b_up_prep(struct brcms_hardware *wlc_hw) ++{ ++ uint coremask; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ /* ++ * Enable pll and xtal, initialize the power control registers, ++ * and force fastclock for the remainder of brcms_c_up(). ++ */ ++ brcms_b_xtal(wlc_hw, ON); ++ ai_clkctl_init(wlc_hw->sih); ++ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); ++ ++ /* ++ * Configure pci/pcmcia here instead of in brcms_c_attach() ++ * to allow mfg hotswap: down, hotswap (chip power cycle), up. ++ */ ++ coremask = (1 << wlc_hw->wlc->core->coreidx); ++ ++ ai_pci_setup(wlc_hw->sih, coremask); ++ ++ /* ++ * Need to read the hwradio status here to cover the case where the ++ * system is loaded with the hw radio disabled. We do not want to ++ * bring the driver up in this case. ++ */ ++ if (brcms_b_radio_read_hwdisabled(wlc_hw)) { ++ /* put SB PCI in down state again */ ++ ai_pci_down(wlc_hw->sih); ++ brcms_b_xtal(wlc_hw, OFF); ++ return -ENOMEDIUM; ++ } ++ ++ ai_pci_up(wlc_hw->sih); ++ ++ /* reset the d11 core */ ++ brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); ++ ++ return 0; ++} ++ ++static int brcms_b_up_finish(struct brcms_hardware *wlc_hw) ++{ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ wlc_hw->up = true; ++ wlc_phy_hw_state_upd(wlc_hw->band->pi, true); ++ ++ /* FULLY enable dynamic power control and d11 core interrupt */ ++ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); ++ brcms_intrson(wlc_hw->wlc->wl); ++ return 0; ++} ++ ++/* ++ * Write WME tunable parameters for retransmit/max rate ++ * from wlc struct to ucode ++ */ ++static void brcms_c_wme_retries_write(struct brcms_c_info *wlc) ++{ ++ int ac; ++ ++ /* Need clock to do this */ ++ if (!wlc->clk) ++ return; ++ ++ for (ac = 0; ac < AC_COUNT; ac++) ++ brcms_b_write_shm(wlc->hw, M_AC_TXLMT_ADDR(ac), ++ wlc->wme_retries[ac]); ++} ++ ++/* make interface operational */ ++int brcms_c_up(struct brcms_c_info *wlc) ++{ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ ++ /* HW is turned off so don't try to access it */ ++ if (wlc->pub->hw_off || brcms_deviceremoved(wlc)) ++ return -ENOMEDIUM; ++ ++ if (!wlc->pub->hw_up) { ++ brcms_b_hw_up(wlc->hw); ++ wlc->pub->hw_up = true; ++ } ++ ++ if ((wlc->pub->boardflags & BFL_FEM) ++ && (wlc->pub->sih->chip == BCM4313_CHIP_ID)) { ++ if (wlc->pub->boardrev >= 0x1250 ++ && (wlc->pub->boardflags & BFL_FEM_BT)) ++ brcms_b_mhf(wlc->hw, MHF5, MHF5_4313_GPIOCTRL, ++ MHF5_4313_GPIOCTRL, BRCM_BAND_ALL); ++ else ++ brcms_b_mhf(wlc->hw, MHF4, MHF4_EXTPA_ENABLE, ++ MHF4_EXTPA_ENABLE, BRCM_BAND_ALL); ++ } ++ ++ /* ++ * Need to read the hwradio status here to cover the case where the ++ * system is loaded with the hw radio disabled. We do not want to bring ++ * the driver up in this case. If radio is disabled, abort up, lower ++ * power, start radio timer and return 0(for NDIS) don't call ++ * radio_update to avoid looping brcms_c_up. ++ * ++ * brcms_b_up_prep() returns either 0 or -BCME_RADIOOFF only ++ */ ++ if (!wlc->pub->radio_disabled) { ++ int status = brcms_b_up_prep(wlc->hw); ++ if (status == -ENOMEDIUM) { ++ if (!mboolisset ++ (wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE)) { ++ struct brcms_bss_cfg *bsscfg = wlc->bsscfg; ++ mboolset(wlc->pub->radio_disabled, ++ WL_RADIO_HW_DISABLE); ++ ++ if (bsscfg->enable && bsscfg->BSS) ++ wiphy_err(wlc->wiphy, "wl%d: up" ++ ": rfdisable -> " ++ "bsscfg_disable()\n", ++ wlc->pub->unit); ++ } ++ } ++ } ++ ++ if (wlc->pub->radio_disabled) { ++ brcms_c_radio_monitor_start(wlc); ++ return 0; ++ } ++ ++ /* brcms_b_up_prep has done brcms_c_corereset(). so clk is on, set it */ ++ wlc->clk = true; ++ ++ brcms_c_radio_monitor_stop(wlc); ++ ++ /* Set EDCF hostflags */ ++ brcms_b_mhf(wlc->hw, MHF1, MHF1_EDCF, MHF1_EDCF, BRCM_BAND_ALL); ++ ++ brcms_init(wlc->wl); ++ wlc->pub->up = true; ++ ++ if (wlc->bandinit_pending) { ++ brcms_c_suspend_mac_and_wait(wlc); ++ brcms_c_set_chanspec(wlc, wlc->default_bss->chanspec); ++ wlc->bandinit_pending = false; ++ brcms_c_enable_mac(wlc); ++ } ++ ++ brcms_b_up_finish(wlc->hw); ++ ++ /* Program the TX wme params with the current settings */ ++ brcms_c_wme_retries_write(wlc); ++ ++ /* start one second watchdog timer */ ++ brcms_add_timer(wlc->wdtimer, TIMER_INTERVAL_WATCHDOG, true); ++ wlc->WDarmed = true; ++ ++ /* ensure antenna config is up to date */ ++ brcms_c_stf_phy_txant_upd(wlc); ++ /* ensure LDPC config is in sync */ ++ brcms_c_ht_update_ldpc(wlc, wlc->stf->ldpc); ++ ++ return 0; ++} ++ ++static uint brcms_c_down_del_timer(struct brcms_c_info *wlc) ++{ ++ uint callbacks = 0; ++ ++ return callbacks; ++} ++ ++static int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw) ++{ ++ bool dev_gone; ++ uint callbacks = 0; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ if (!wlc_hw->up) ++ return callbacks; ++ ++ dev_gone = brcms_deviceremoved(wlc_hw->wlc); ++ ++ /* disable interrupts */ ++ if (dev_gone) ++ wlc_hw->wlc->macintmask = 0; ++ else { ++ /* now disable interrupts */ ++ brcms_intrsoff(wlc_hw->wlc->wl); ++ ++ /* ensure we're running on the pll clock again */ ++ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); ++ } ++ /* down phy at the last of this stage */ ++ callbacks += wlc_phy_down(wlc_hw->band->pi); ++ ++ return callbacks; ++} ++ ++static int brcms_b_down_finish(struct brcms_hardware *wlc_hw) ++{ ++ uint callbacks = 0; ++ bool dev_gone; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ if (!wlc_hw->up) ++ return callbacks; ++ ++ wlc_hw->up = false; ++ wlc_phy_hw_state_upd(wlc_hw->band->pi, false); ++ ++ dev_gone = brcms_deviceremoved(wlc_hw->wlc); ++ ++ if (dev_gone) { ++ wlc_hw->sbclk = false; ++ wlc_hw->clk = false; ++ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); ++ ++ /* reclaim any posted packets */ ++ brcms_c_flushqueues(wlc_hw->wlc); ++ } else { ++ ++ /* Reset and disable the core */ ++ if (ai_iscoreup(wlc_hw->sih)) { ++ if (R_REG(&wlc_hw->regs->maccontrol) & ++ MCTL_EN_MAC) ++ brcms_c_suspend_mac_and_wait(wlc_hw->wlc); ++ callbacks += brcms_reset(wlc_hw->wlc->wl); ++ brcms_c_coredisable(wlc_hw); ++ } ++ ++ /* turn off primary xtal and pll */ ++ if (!wlc_hw->noreset) { ++ ai_pci_down(wlc_hw->sih); ++ brcms_b_xtal(wlc_hw, OFF); ++ } ++ } ++ ++ return callbacks; ++} ++ ++/* ++ * Mark the interface nonoperational, stop the software mechanisms, ++ * disable the hardware, free any transient buffer state. ++ * Return a count of the number of driver callbacks still pending. ++ */ ++uint brcms_c_down(struct brcms_c_info *wlc) ++{ ++ ++ uint callbacks = 0; ++ int i; ++ bool dev_gone = false; ++ struct brcms_txq_info *qi; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ ++ /* check if we are already in the going down path */ ++ if (wlc->going_down) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Driver going down so return" ++ "\n", wlc->pub->unit, __func__); ++ return 0; ++ } ++ if (!wlc->pub->up) ++ return callbacks; ++ ++ /* in between, mpc could try to bring down again.. */ ++ wlc->going_down = true; ++ ++ callbacks += brcms_b_bmac_down_prep(wlc->hw); ++ ++ dev_gone = brcms_deviceremoved(wlc); ++ ++ /* Call any registered down handlers */ ++ for (i = 0; i < BRCMS_MAXMODULES; i++) { ++ if (wlc->modulecb[i].down_fn) ++ callbacks += ++ wlc->modulecb[i].down_fn(wlc->modulecb[i].hdl); ++ } ++ ++ /* cancel the watchdog timer */ ++ if (wlc->WDarmed) { ++ if (!brcms_del_timer(wlc->wdtimer)) ++ callbacks++; ++ wlc->WDarmed = false; ++ } ++ /* cancel all other timers */ ++ callbacks += brcms_c_down_del_timer(wlc); ++ ++ wlc->pub->up = false; ++ ++ wlc_phy_mute_upd(wlc->band->pi, false, PHY_MUTE_ALL); ++ ++ /* clear txq flow control */ ++ brcms_c_txflowcontrol_reset(wlc); ++ ++ /* flush tx queues */ ++ for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) ++ brcmu_pktq_flush(&qi->q, true, NULL, NULL); ++ ++ callbacks += brcms_b_down_finish(wlc->hw); ++ ++ /* brcms_b_down_finish has done brcms_c_coredisable(). so clk is off */ ++ wlc->clk = false; ++ ++ wlc->going_down = false; ++ return callbacks; ++} ++ ++/* Set the current gmode configuration */ ++int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config) ++{ ++ int ret = 0; ++ uint i; ++ struct brcms_c_rateset rs; ++ /* Default to 54g Auto */ ++ /* Advertise and use shortslot (-1/0/1 Auto/Off/On) */ ++ s8 shortslot = BRCMS_SHORTSLOT_AUTO; ++ bool shortslot_restrict = false; /* Restrict association to stations ++ * that support shortslot ++ */ ++ bool ofdm_basic = false; /* Make 6, 12, and 24 basic rates */ ++ /* Advertise and use short preambles (-1/0/1 Auto/Off/On) */ ++ int preamble = BRCMS_PLCP_LONG; ++ bool preamble_restrict = false; /* Restrict association to stations ++ * that support short preambles ++ */ ++ struct brcms_band *band; ++ ++ /* if N-support is enabled, allow Gmode set as long as requested ++ * Gmode is not GMODE_LEGACY_B ++ */ ++ if ((wlc->pub->_n_enab & SUPPORT_11N) && gmode == GMODE_LEGACY_B) ++ return -ENOTSUPP; ++ ++ /* verify that we are dealing with 2G band and grab the band pointer */ ++ if (wlc->band->bandtype == BRCM_BAND_2G) ++ band = wlc->band; ++ else if ((wlc->pub->_nbands > 1) && ++ (wlc->bandstate[OTHERBANDUNIT(wlc)]->bandtype == BRCM_BAND_2G)) ++ band = wlc->bandstate[OTHERBANDUNIT(wlc)]; ++ else ++ return -EINVAL; ++ ++ /* Legacy or bust when no OFDM is supported by regulatory */ ++ if ((brcms_c_channel_locale_flags_in_band(wlc->cmi, band->bandunit) & ++ BRCMS_NO_OFDM) && (gmode != GMODE_LEGACY_B)) ++ return -EINVAL; ++ ++ /* update configuration value */ ++ if (config == true) ++ brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode); ++ ++ /* Clear rateset override */ ++ memset(&rs, 0, sizeof(struct brcms_c_rateset)); ++ ++ switch (gmode) { ++ case GMODE_LEGACY_B: ++ shortslot = BRCMS_SHORTSLOT_OFF; ++ brcms_c_rateset_copy(&gphy_legacy_rates, &rs); ++ ++ break; ++ ++ case GMODE_LRS: ++ break; ++ ++ case GMODE_AUTO: ++ /* Accept defaults */ ++ break; ++ ++ case GMODE_ONLY: ++ ofdm_basic = true; ++ preamble = BRCMS_PLCP_SHORT; ++ preamble_restrict = true; ++ break; ++ ++ case GMODE_PERFORMANCE: ++ shortslot = BRCMS_SHORTSLOT_ON; ++ shortslot_restrict = true; ++ ofdm_basic = true; ++ preamble = BRCMS_PLCP_SHORT; ++ preamble_restrict = true; ++ break; ++ ++ default: ++ /* Error */ ++ wiphy_err(wlc->wiphy, "wl%d: %s: invalid gmode %d\n", ++ wlc->pub->unit, __func__, gmode); ++ return -ENOTSUPP; ++ } ++ ++ band->gmode = gmode; ++ ++ wlc->shortslot_override = shortslot; ++ ++ /* Use the default 11g rateset */ ++ if (!rs.count) ++ brcms_c_rateset_copy(&cck_ofdm_rates, &rs); ++ ++ if (ofdm_basic) { ++ for (i = 0; i < rs.count; i++) { ++ if (rs.rates[i] == BRCM_RATE_6M ++ || rs.rates[i] == BRCM_RATE_12M ++ || rs.rates[i] == BRCM_RATE_24M) ++ rs.rates[i] |= BRCMS_RATE_FLAG; ++ } ++ } ++ ++ /* Set default bss rateset */ ++ wlc->default_bss->rateset.count = rs.count; ++ memcpy(wlc->default_bss->rateset.rates, rs.rates, ++ sizeof(wlc->default_bss->rateset.rates)); ++ ++ return ret; ++} ++ ++int brcms_c_set_nmode(struct brcms_c_info *wlc) ++{ ++ uint i; ++ s32 nmode = AUTO; ++ ++ if (wlc->stf->txstreams == WL_11N_3x3) ++ nmode = WL_11N_3x3; ++ else ++ nmode = WL_11N_2x2; ++ ++ /* force GMODE_AUTO if NMODE is ON */ ++ brcms_c_set_gmode(wlc, GMODE_AUTO, true); ++ if (nmode == WL_11N_3x3) ++ wlc->pub->_n_enab = SUPPORT_HT; ++ else ++ wlc->pub->_n_enab = SUPPORT_11N; ++ wlc->default_bss->flags |= BRCMS_BSS_HT; ++ /* add the mcs rates to the default and hw ratesets */ ++ brcms_c_rateset_mcs_build(&wlc->default_bss->rateset, ++ wlc->stf->txstreams); ++ for (i = 0; i < wlc->pub->_nbands; i++) ++ memcpy(wlc->bandstate[i]->hw_rateset.mcs, ++ wlc->default_bss->rateset.mcs, MCSSET_LEN); ++ ++ return 0; ++} ++ ++static int ++brcms_c_set_internal_rateset(struct brcms_c_info *wlc, ++ struct brcms_c_rateset *rs_arg) ++{ ++ struct brcms_c_rateset rs, new; ++ uint bandunit; ++ ++ memcpy(&rs, rs_arg, sizeof(struct brcms_c_rateset)); ++ ++ /* check for bad count value */ ++ if ((rs.count == 0) || (rs.count > BRCMS_NUMRATES)) ++ return -EINVAL; ++ ++ /* try the current band */ ++ bandunit = wlc->band->bandunit; ++ memcpy(&new, &rs, sizeof(struct brcms_c_rateset)); ++ if (brcms_c_rate_hwrs_filter_sort_validate ++ (&new, &wlc->bandstate[bandunit]->hw_rateset, true, ++ wlc->stf->txstreams)) ++ goto good; ++ ++ /* try the other band */ ++ if (brcms_is_mband_unlocked(wlc)) { ++ bandunit = OTHERBANDUNIT(wlc); ++ memcpy(&new, &rs, sizeof(struct brcms_c_rateset)); ++ if (brcms_c_rate_hwrs_filter_sort_validate(&new, ++ &wlc-> ++ bandstate[bandunit]-> ++ hw_rateset, true, ++ wlc->stf->txstreams)) ++ goto good; ++ } ++ ++ return -EBADE; ++ ++ good: ++ /* apply new rateset */ ++ memcpy(&wlc->default_bss->rateset, &new, ++ sizeof(struct brcms_c_rateset)); ++ memcpy(&wlc->bandstate[bandunit]->defrateset, &new, ++ sizeof(struct brcms_c_rateset)); ++ return 0; ++} ++ ++static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc) ++{ ++ u8 r; ++ bool war = false; ++ ++ if (wlc->bsscfg->associated) ++ r = wlc->bsscfg->current_bss->rateset.rates[0]; ++ else ++ r = wlc->default_bss->rateset.rates[0]; ++ ++ wlc_phy_ofdm_rateset_war(wlc->band->pi, war); ++} ++ ++int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel) ++{ ++ u16 chspec = ch20mhz_chspec(channel); ++ ++ if (channel < 0 || channel > MAXCHANNEL) ++ return -EINVAL; ++ ++ if (!brcms_c_valid_chanspec_db(wlc->cmi, chspec)) ++ return -EINVAL; ++ ++ ++ if (!wlc->pub->up && brcms_is_mband_unlocked(wlc)) { ++ if (wlc->band->bandunit != chspec_bandunit(chspec)) ++ wlc->bandinit_pending = true; ++ else ++ wlc->bandinit_pending = false; ++ } ++ ++ wlc->default_bss->chanspec = chspec; ++ /* brcms_c_BSSinit() will sanitize the rateset before ++ * using it.. */ ++ if (wlc->pub->up && (wlc_phy_chanspec_get(wlc->band->pi) != chspec)) { ++ brcms_c_set_home_chanspec(wlc, chspec); ++ brcms_c_suspend_mac_and_wait(wlc); ++ brcms_c_set_chanspec(wlc, chspec); ++ brcms_c_enable_mac(wlc); ++ } ++ return 0; ++} ++ ++int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl) ++{ ++ int ac; ++ ++ if (srl < 1 || srl > RETRY_SHORT_MAX || ++ lrl < 1 || lrl > RETRY_SHORT_MAX) ++ return -EINVAL; ++ ++ wlc->SRL = srl; ++ wlc->LRL = lrl; ++ ++ brcms_b_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL); ++ ++ for (ac = 0; ac < AC_COUNT; ac++) { ++ wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], ++ EDCF_SHORT, wlc->SRL); ++ wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], ++ EDCF_LONG, wlc->LRL); ++ } ++ brcms_c_wme_retries_write(wlc); ++ ++ return 0; ++} ++ ++void brcms_c_get_current_rateset(struct brcms_c_info *wlc, ++ struct brcm_rateset *currs) ++{ ++ struct brcms_c_rateset *rs; ++ ++ if (wlc->pub->associated) ++ rs = &wlc->bsscfg->current_bss->rateset; ++ else ++ rs = &wlc->default_bss->rateset; ++ ++ /* Copy only legacy rateset section */ ++ currs->count = rs->count; ++ memcpy(&currs->rates, &rs->rates, rs->count); ++} ++ ++int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs) ++{ ++ struct brcms_c_rateset internal_rs; ++ int bcmerror; ++ ++ if (rs->count > BRCMS_NUMRATES) ++ return -ENOBUFS; ++ ++ memset(&internal_rs, 0, sizeof(struct brcms_c_rateset)); ++ ++ /* Copy only legacy rateset section */ ++ internal_rs.count = rs->count; ++ memcpy(&internal_rs.rates, &rs->rates, internal_rs.count); ++ ++ /* merge rateset coming in with the current mcsset */ ++ if (wlc->pub->_n_enab & SUPPORT_11N) { ++ struct brcms_bss_info *mcsset_bss; ++ if (wlc->bsscfg->associated) ++ mcsset_bss = wlc->bsscfg->current_bss; ++ else ++ mcsset_bss = wlc->default_bss; ++ memcpy(internal_rs.mcs, &mcsset_bss->rateset.mcs[0], ++ MCSSET_LEN); ++ } ++ ++ bcmerror = brcms_c_set_internal_rateset(wlc, &internal_rs); ++ if (!bcmerror) ++ brcms_c_ofdm_rateset_war(wlc); ++ ++ return bcmerror; ++} ++ ++int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period) ++{ ++ if (period < DOT11_MIN_BEACON_PERIOD || ++ period > DOT11_MAX_BEACON_PERIOD) ++ return -EINVAL; ++ ++ wlc->default_bss->beacon_period = period; ++ return 0; ++} ++ ++u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx) ++{ ++ return wlc->band->phytype; ++} ++ ++void brcms_c_set_shortslot_override(struct brcms_c_info *wlc, s8 sslot_override) ++{ ++ wlc->shortslot_override = sslot_override; ++ ++ /* ++ * shortslot is an 11g feature, so no more work if we are ++ * currently on the 5G band ++ */ ++ if (wlc->band->bandtype == BRCM_BAND_5G) ++ return; ++ ++ if (wlc->pub->up && wlc->pub->associated) { ++ /* let watchdog or beacon processing update shortslot */ ++ } else if (wlc->pub->up) { ++ /* unassociated shortslot is off */ ++ brcms_c_switch_shortslot(wlc, false); ++ } else { ++ /* driver is down, so just update the brcms_c_info ++ * value */ ++ if (wlc->shortslot_override == BRCMS_SHORTSLOT_AUTO) ++ wlc->shortslot = false; ++ else ++ wlc->shortslot = ++ (wlc->shortslot_override == ++ BRCMS_SHORTSLOT_ON); ++ } ++} ++ ++/* ++ * register watchdog and down handlers. ++ */ ++int brcms_c_module_register(struct brcms_pub *pub, ++ const char *name, struct brcms_info *hdl, ++ int (*d_fn)(void *handle)) ++{ ++ struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc; ++ int i; ++ ++ /* find an empty entry and just add, no duplication check! */ ++ for (i = 0; i < BRCMS_MAXMODULES; i++) { ++ if (wlc->modulecb[i].name[0] == '\0') { ++ strncpy(wlc->modulecb[i].name, name, ++ sizeof(wlc->modulecb[i].name) - 1); ++ wlc->modulecb[i].hdl = hdl; ++ wlc->modulecb[i].down_fn = d_fn; ++ return 0; ++ } ++ } ++ ++ return -ENOSR; ++} ++ ++/* unregister module callbacks */ ++int brcms_c_module_unregister(struct brcms_pub *pub, const char *name, ++ struct brcms_info *hdl) ++{ ++ struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc; ++ int i; ++ ++ if (wlc == NULL) ++ return -ENODATA; ++ ++ for (i = 0; i < BRCMS_MAXMODULES; i++) { ++ if (!strcmp(wlc->modulecb[i].name, name) && ++ (wlc->modulecb[i].hdl == hdl)) { ++ memset(&wlc->modulecb[i], 0, sizeof(struct modulecb)); ++ return 0; ++ } ++ } ++ ++ /* table not found! */ ++ return -ENODATA; ++} ++ ++#ifdef BCMDBG ++static const char * const supr_reason[] = { ++ "None", "PMQ Entry", "Flush request", ++ "Previous frag failure", "Channel mismatch", ++ "Lifetime Expiry", "Underflow" ++}; ++ ++static void brcms_c_print_txs_status(u16 s) ++{ ++ printk(KERN_DEBUG "[15:12] %d frame attempts\n", ++ (s & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT); ++ printk(KERN_DEBUG " [11:8] %d rts attempts\n", ++ (s & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT); ++ printk(KERN_DEBUG " [7] %d PM mode indicated\n", ++ ((s & TX_STATUS_PMINDCTD) ? 1 : 0)); ++ printk(KERN_DEBUG " [6] %d intermediate status\n", ++ ((s & TX_STATUS_INTERMEDIATE) ? 1 : 0)); ++ printk(KERN_DEBUG " [5] %d AMPDU\n", ++ (s & TX_STATUS_AMPDU) ? 1 : 0); ++ printk(KERN_DEBUG " [4:2] %d Frame Suppressed Reason (%s)\n", ++ ((s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT), ++ supr_reason[(s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT]); ++ printk(KERN_DEBUG " [1] %d acked\n", ++ ((s & TX_STATUS_ACK_RCV) ? 1 : 0)); ++} ++#endif /* BCMDBG */ ++ ++void brcms_c_print_txstatus(struct tx_status *txs) ++{ ++#if defined(BCMDBG) ++ u16 s = txs->status; ++ u16 ackphyrxsh = txs->ackphyrxsh; ++ ++ printk(KERN_DEBUG "\ntxpkt (MPDU) Complete\n"); ++ ++ printk(KERN_DEBUG "FrameID: %04x ", txs->frameid); ++ printk(KERN_DEBUG "TxStatus: %04x", s); ++ printk(KERN_DEBUG "\n"); ++ ++ brcms_c_print_txs_status(s); ++ ++ printk(KERN_DEBUG "LastTxTime: %04x ", txs->lasttxtime); ++ printk(KERN_DEBUG "Seq: %04x ", txs->sequence); ++ printk(KERN_DEBUG "PHYTxStatus: %04x ", txs->phyerr); ++ printk(KERN_DEBUG "RxAckRSSI: %04x ", ++ (ackphyrxsh & PRXS1_JSSI_MASK) >> PRXS1_JSSI_SHIFT); ++ printk(KERN_DEBUG "RxAckSQ: %04x", ++ (ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT); ++ printk(KERN_DEBUG "\n"); ++#endif /* defined(BCMDBG) */ ++} ++ ++bool brcms_c_chipmatch(u16 vendor, u16 device) ++{ ++ if (vendor != PCI_VENDOR_ID_BROADCOM) { ++ pr_err("chipmatch: unknown vendor id %04x\n", vendor); ++ return false; ++ } ++ ++ if (device == BCM43224_D11N_ID_VEN1) ++ return true; ++ if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID)) ++ return true; ++ if (device == BCM4313_D11N2G_ID) ++ return true; ++ if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID)) ++ return true; ++ ++ pr_err("chipmatch: unknown device id %04x\n", device); ++ return false; ++} ++ ++#if defined(BCMDBG) ++void brcms_c_print_txdesc(struct d11txh *txh) ++{ ++ u16 mtcl = le16_to_cpu(txh->MacTxControlLow); ++ u16 mtch = le16_to_cpu(txh->MacTxControlHigh); ++ u16 mfc = le16_to_cpu(txh->MacFrameControl); ++ u16 tfest = le16_to_cpu(txh->TxFesTimeNormal); ++ u16 ptcw = le16_to_cpu(txh->PhyTxControlWord); ++ u16 ptcw_1 = le16_to_cpu(txh->PhyTxControlWord_1); ++ u16 ptcw_1_Fbr = le16_to_cpu(txh->PhyTxControlWord_1_Fbr); ++ u16 ptcw_1_Rts = le16_to_cpu(txh->PhyTxControlWord_1_Rts); ++ u16 ptcw_1_FbrRts = le16_to_cpu(txh->PhyTxControlWord_1_FbrRts); ++ u16 mainrates = le16_to_cpu(txh->MainRates); ++ u16 xtraft = le16_to_cpu(txh->XtraFrameTypes); ++ u8 *iv = txh->IV; ++ u8 *ra = txh->TxFrameRA; ++ u16 tfestfb = le16_to_cpu(txh->TxFesTimeFallback); ++ u8 *rtspfb = txh->RTSPLCPFallback; ++ u16 rtsdfb = le16_to_cpu(txh->RTSDurFallback); ++ u8 *fragpfb = txh->FragPLCPFallback; ++ u16 fragdfb = le16_to_cpu(txh->FragDurFallback); ++ u16 mmodelen = le16_to_cpu(txh->MModeLen); ++ u16 mmodefbrlen = le16_to_cpu(txh->MModeFbrLen); ++ u16 tfid = le16_to_cpu(txh->TxFrameID); ++ u16 txs = le16_to_cpu(txh->TxStatus); ++ u16 mnmpdu = le16_to_cpu(txh->MaxNMpdus); ++ u16 mabyte = le16_to_cpu(txh->MaxABytes_MRT); ++ u16 mabyte_f = le16_to_cpu(txh->MaxABytes_FBR); ++ u16 mmbyte = le16_to_cpu(txh->MinMBytes); ++ ++ u8 *rtsph = txh->RTSPhyHeader; ++ struct ieee80211_rts rts = txh->rts_frame; ++ char hexbuf[256]; ++ ++ /* add plcp header along with txh descriptor */ ++ printk(KERN_DEBUG "Raw TxDesc + plcp header:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ txh, sizeof(struct d11txh) + 48); ++ ++ printk(KERN_DEBUG "TxCtlLow: %04x ", mtcl); ++ printk(KERN_DEBUG "TxCtlHigh: %04x ", mtch); ++ printk(KERN_DEBUG "FC: %04x ", mfc); ++ printk(KERN_DEBUG "FES Time: %04x\n", tfest); ++ printk(KERN_DEBUG "PhyCtl: %04x%s ", ptcw, ++ (ptcw & PHY_TXC_SHORT_HDR) ? " short" : ""); ++ printk(KERN_DEBUG "PhyCtl_1: %04x ", ptcw_1); ++ printk(KERN_DEBUG "PhyCtl_1_Fbr: %04x\n", ptcw_1_Fbr); ++ printk(KERN_DEBUG "PhyCtl_1_Rts: %04x ", ptcw_1_Rts); ++ printk(KERN_DEBUG "PhyCtl_1_Fbr_Rts: %04x\n", ptcw_1_FbrRts); ++ printk(KERN_DEBUG "MainRates: %04x ", mainrates); ++ printk(KERN_DEBUG "XtraFrameTypes: %04x ", xtraft); ++ printk(KERN_DEBUG "\n"); ++ ++ brcmu_format_hex(hexbuf, iv, sizeof(txh->IV)); ++ printk(KERN_DEBUG "SecIV: %s\n", hexbuf); ++ brcmu_format_hex(hexbuf, ra, sizeof(txh->TxFrameRA)); ++ printk(KERN_DEBUG "RA: %s\n", hexbuf); ++ ++ printk(KERN_DEBUG "Fb FES Time: %04x ", tfestfb); ++ brcmu_format_hex(hexbuf, rtspfb, sizeof(txh->RTSPLCPFallback)); ++ printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf); ++ printk(KERN_DEBUG "RTS DUR: %04x ", rtsdfb); ++ brcmu_format_hex(hexbuf, fragpfb, sizeof(txh->FragPLCPFallback)); ++ printk(KERN_DEBUG "PLCP: %s ", hexbuf); ++ printk(KERN_DEBUG "DUR: %04x", fragdfb); ++ printk(KERN_DEBUG "\n"); ++ ++ printk(KERN_DEBUG "MModeLen: %04x ", mmodelen); ++ printk(KERN_DEBUG "MModeFbrLen: %04x\n", mmodefbrlen); ++ ++ printk(KERN_DEBUG "FrameID: %04x\n", tfid); ++ printk(KERN_DEBUG "TxStatus: %04x\n", txs); ++ ++ printk(KERN_DEBUG "MaxNumMpdu: %04x\n", mnmpdu); ++ printk(KERN_DEBUG "MaxAggbyte: %04x\n", mabyte); ++ printk(KERN_DEBUG "MaxAggbyte_fb: %04x\n", mabyte_f); ++ printk(KERN_DEBUG "MinByte: %04x\n", mmbyte); ++ ++ brcmu_format_hex(hexbuf, rtsph, sizeof(txh->RTSPhyHeader)); ++ printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf); ++ brcmu_format_hex(hexbuf, (u8 *) &rts, sizeof(txh->rts_frame)); ++ printk(KERN_DEBUG "RTS Frame: %s", hexbuf); ++ printk(KERN_DEBUG "\n"); ++} ++#endif /* defined(BCMDBG) */ ++ ++#if defined(BCMDBG) ++int ++brcms_c_format_flags(const struct brcms_c_bit_desc *bd, u32 flags, char *buf, ++ int len) ++{ ++ int i; ++ char *p = buf; ++ char hexstr[16]; ++ int slen = 0, nlen = 0; ++ u32 bit; ++ const char *name; ++ ++ if (len < 2 || !buf) ++ return 0; ++ ++ buf[0] = '\0'; ++ ++ for (i = 0; flags != 0; i++) { ++ bit = bd[i].bit; ++ name = bd[i].name; ++ if (bit == 0 && flags != 0) { ++ /* print any unnamed bits */ ++ snprintf(hexstr, 16, "0x%X", flags); ++ name = hexstr; ++ flags = 0; /* exit loop */ ++ } else if ((flags & bit) == 0) ++ continue; ++ flags &= ~bit; ++ nlen = strlen(name); ++ slen += nlen; ++ /* count btwn flag space */ ++ if (flags != 0) ++ slen += 1; ++ /* need NULL char as well */ ++ if (len <= slen) ++ break; ++ /* copy NULL char but don't count it */ ++ strncpy(p, name, nlen + 1); ++ p += nlen; ++ /* copy btwn flag space and NULL char */ ++ if (flags != 0) ++ p += snprintf(p, 2, " "); ++ len -= slen; ++ } ++ ++ /* indicate the str was too short */ ++ if (flags != 0) { ++ if (len < 2) ++ p -= 2 - len; /* overwrite last char */ ++ p += snprintf(p, 2, ">"); ++ } ++ ++ return (int)(p - buf); ++} ++#endif /* defined(BCMDBG) */ ++ ++#if defined(BCMDBG) ++void brcms_c_print_rxh(struct d11rxhdr *rxh) ++{ ++ u16 len = rxh->RxFrameSize; ++ u16 phystatus_0 = rxh->PhyRxStatus_0; ++ u16 phystatus_1 = rxh->PhyRxStatus_1; ++ u16 phystatus_2 = rxh->PhyRxStatus_2; ++ u16 phystatus_3 = rxh->PhyRxStatus_3; ++ u16 macstatus1 = rxh->RxStatus1; ++ u16 macstatus2 = rxh->RxStatus2; ++ char flagstr[64]; ++ char lenbuf[20]; ++ static const struct brcms_c_bit_desc macstat_flags[] = { ++ {RXS_FCSERR, "FCSErr"}, ++ {RXS_RESPFRAMETX, "Reply"}, ++ {RXS_PBPRES, "PADDING"}, ++ {RXS_DECATMPT, "DeCr"}, ++ {RXS_DECERR, "DeCrErr"}, ++ {RXS_BCNSENT, "Bcn"}, ++ {0, NULL} ++ }; ++ ++ printk(KERN_DEBUG "Raw RxDesc:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, rxh, ++ sizeof(struct d11rxhdr)); ++ ++ brcms_c_format_flags(macstat_flags, macstatus1, flagstr, 64); ++ ++ snprintf(lenbuf, sizeof(lenbuf), "0x%x", len); ++ ++ printk(KERN_DEBUG "RxFrameSize: %6s (%d)%s\n", lenbuf, len, ++ (rxh->PhyRxStatus_0 & PRXS0_SHORTH) ? " short preamble" : ""); ++ printk(KERN_DEBUG "RxPHYStatus: %04x %04x %04x %04x\n", ++ phystatus_0, phystatus_1, phystatus_2, phystatus_3); ++ printk(KERN_DEBUG "RxMACStatus: %x %s\n", macstatus1, flagstr); ++ printk(KERN_DEBUG "RXMACaggtype: %x\n", ++ (macstatus2 & RXS_AGGTYPE_MASK)); ++ printk(KERN_DEBUG "RxTSFTime: %04x\n", rxh->RxTSFTime); ++} ++#endif /* defined(BCMDBG) */ ++ ++u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate) ++{ ++ u16 table_ptr; ++ u8 phy_rate, index; ++ ++ /* get the phy specific rate encoding for the PLCP SIGNAL field */ ++ if (is_ofdm_rate(rate)) ++ table_ptr = M_RT_DIRMAP_A; ++ else ++ table_ptr = M_RT_DIRMAP_B; ++ ++ /* for a given rate, the LS-nibble of the PLCP SIGNAL field is ++ * the index into the rate table. ++ */ ++ phy_rate = rate_info[rate] & BRCMS_RATE_MASK; ++ index = phy_rate & 0xf; ++ ++ /* Find the SHM pointer to the rate table entry by looking in the ++ * Direct-map Table ++ */ ++ return 2 * brcms_b_read_shm(wlc_hw, table_ptr + (index * 2)); ++} ++ ++static bool ++brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q, ++ struct sk_buff *pkt, int prec, bool head) ++{ ++ struct sk_buff *p; ++ int eprec = -1; /* precedence to evict from */ ++ ++ /* Determine precedence from which to evict packet, if any */ ++ if (pktq_pfull(q, prec)) ++ eprec = prec; ++ else if (pktq_full(q)) { ++ p = brcmu_pktq_peek_tail(q, &eprec); ++ if (eprec > prec) { ++ wiphy_err(wlc->wiphy, "%s: Failing: eprec %d > prec %d" ++ "\n", __func__, eprec, prec); ++ return false; ++ } ++ } ++ ++ /* Evict if needed */ ++ if (eprec >= 0) { ++ bool discard_oldest; ++ ++ discard_oldest = ac_bitmap_tst(0, eprec); ++ ++ /* Refuse newer packet unless configured to discard oldest */ ++ if (eprec == prec && !discard_oldest) { ++ wiphy_err(wlc->wiphy, "%s: No where to go, prec == %d" ++ "\n", __func__, prec); ++ return false; ++ } ++ ++ /* Evict packet according to discard policy */ ++ p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) : ++ brcmu_pktq_pdeq_tail(q, eprec); ++ brcmu_pkt_buf_free_skb(p); ++ } ++ ++ /* Enqueue */ ++ if (head) ++ p = brcmu_pktq_penq_head(q, prec, pkt); ++ else ++ p = brcmu_pktq_penq(q, prec, pkt); ++ ++ return true; ++} ++ ++/* ++ * Attempts to queue a packet onto a multiple-precedence queue, ++ * if necessary evicting a lower precedence packet from the queue. ++ * ++ * 'prec' is the precedence number that has already been mapped ++ * from the packet priority. ++ * ++ * Returns true if packet consumed (queued), false if not. ++ */ ++static bool brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q, ++ struct sk_buff *pkt, int prec) ++{ ++ return brcms_c_prec_enq_head(wlc, q, pkt, prec, false); ++} ++ ++void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb, ++ struct sk_buff *sdu, uint prec) ++{ ++ struct brcms_txq_info *qi = wlc->pkt_queue; /* Check me */ ++ struct pktq *q = &qi->q; ++ int prio; ++ ++ prio = sdu->priority; ++ ++ if (!brcms_c_prec_enq(wlc, q, sdu, prec)) { ++ /* ++ * we might hit this condtion in case ++ * packet flooding from mac80211 stack ++ */ ++ brcmu_pkt_buf_free_skb(sdu); ++ } ++} ++ ++/* ++ * bcmc_fid_generate: ++ * Generate frame ID for a BCMC packet. The frag field is not used ++ * for MC frames so is used as part of the sequence number. ++ */ ++static inline u16 ++bcmc_fid_generate(struct brcms_c_info *wlc, struct brcms_bss_cfg *bsscfg, ++ struct d11txh *txh) ++{ ++ u16 frameid; ++ ++ frameid = le16_to_cpu(txh->TxFrameID) & ~(TXFID_SEQ_MASK | ++ TXFID_QUEUE_MASK); ++ frameid |= ++ (((wlc-> ++ mc_fid_counter++) << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) | ++ TX_BCMC_FIFO; ++ ++ return frameid; ++} ++ ++static uint ++brcms_c_calc_ack_time(struct brcms_c_info *wlc, u32 rspec, ++ u8 preamble_type) ++{ ++ uint dur = 0; ++ ++ BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d\n", ++ wlc->pub->unit, rspec, preamble_type); ++ /* ++ * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that ++ * is less than or equal to the rate of the immediately previous ++ * frame in the FES ++ */ ++ rspec = brcms_basic_rate(wlc, rspec); ++ /* ACK frame len == 14 == 2(fc) + 2(dur) + 6(ra) + 4(fcs) */ ++ dur = ++ brcms_c_calc_frame_time(wlc, rspec, preamble_type, ++ (DOT11_ACK_LEN + FCS_LEN)); ++ return dur; ++} ++ ++static uint ++brcms_c_calc_cts_time(struct brcms_c_info *wlc, u32 rspec, ++ u8 preamble_type) ++{ ++ BCMMSG(wlc->wiphy, "wl%d: ratespec 0x%x, preamble_type %d\n", ++ wlc->pub->unit, rspec, preamble_type); ++ return brcms_c_calc_ack_time(wlc, rspec, preamble_type); ++} ++ ++static uint ++brcms_c_calc_ba_time(struct brcms_c_info *wlc, u32 rspec, ++ u8 preamble_type) ++{ ++ BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, " ++ "preamble_type %d\n", wlc->pub->unit, rspec, preamble_type); ++ /* ++ * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that ++ * is less than or equal to the rate of the immediately previous ++ * frame in the FES ++ */ ++ rspec = brcms_basic_rate(wlc, rspec); ++ /* BA len == 32 == 16(ctl hdr) + 4(ba len) + 8(bitmap) + 4(fcs) */ ++ return brcms_c_calc_frame_time(wlc, rspec, preamble_type, ++ (DOT11_BA_LEN + DOT11_BA_BITMAP_LEN + ++ FCS_LEN)); ++} ++ ++/* brcms_c_compute_frame_dur() ++ * ++ * Calculate the 802.11 MAC header DUR field for MPDU ++ * DUR for a single frame = 1 SIFS + 1 ACK ++ * DUR for a frame with following frags = 3 SIFS + 2 ACK + next frag time ++ * ++ * rate MPDU rate in unit of 500kbps ++ * next_frag_len next MPDU length in bytes ++ * preamble_type use short/GF or long/MM PLCP header ++ */ ++static u16 ++brcms_c_compute_frame_dur(struct brcms_c_info *wlc, u32 rate, ++ u8 preamble_type, uint next_frag_len) ++{ ++ u16 dur, sifs; ++ ++ sifs = get_sifs(wlc->band); ++ ++ dur = sifs; ++ dur += (u16) brcms_c_calc_ack_time(wlc, rate, preamble_type); ++ ++ if (next_frag_len) { ++ /* Double the current DUR to get 2 SIFS + 2 ACKs */ ++ dur *= 2; ++ /* add another SIFS and the frag time */ ++ dur += sifs; ++ dur += ++ (u16) brcms_c_calc_frame_time(wlc, rate, preamble_type, ++ next_frag_len); ++ } ++ return dur; ++} ++ ++/* The opposite of brcms_c_calc_frame_time */ ++static uint ++brcms_c_calc_frame_len(struct brcms_c_info *wlc, u32 ratespec, ++ u8 preamble_type, uint dur) ++{ ++ uint nsyms, mac_len, Ndps, kNdps; ++ uint rate = rspec2rate(ratespec); ++ ++ BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, dur %d\n", ++ wlc->pub->unit, ratespec, preamble_type, dur); ++ ++ if (is_mcs_rate(ratespec)) { ++ uint mcs = ratespec & RSPEC_RATE_MASK; ++ int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec); ++ dur -= PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT); ++ /* payload calculation matches that of regular ofdm */ ++ if (wlc->band->bandtype == BRCM_BAND_2G) ++ dur -= DOT11_OFDM_SIGNAL_EXTENSION; ++ /* kNdbps = kbps * 4 */ ++ kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec), ++ rspec_issgi(ratespec)) * 4; ++ nsyms = dur / APHY_SYMBOL_TIME; ++ mac_len = ++ ((nsyms * kNdps) - ++ ((APHY_SERVICE_NBITS + APHY_TAIL_NBITS) * 1000)) / 8000; ++ } else if (is_ofdm_rate(ratespec)) { ++ dur -= APHY_PREAMBLE_TIME; ++ dur -= APHY_SIGNAL_TIME; ++ /* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */ ++ Ndps = rate * 2; ++ nsyms = dur / APHY_SYMBOL_TIME; ++ mac_len = ++ ((nsyms * Ndps) - ++ (APHY_SERVICE_NBITS + APHY_TAIL_NBITS)) / 8; ++ } else { ++ if (preamble_type & BRCMS_SHORT_PREAMBLE) ++ dur -= BPHY_PLCP_SHORT_TIME; ++ else ++ dur -= BPHY_PLCP_TIME; ++ mac_len = dur * rate; ++ /* divide out factor of 2 in rate (1/2 mbps) */ ++ mac_len = mac_len / 8 / 2; ++ } ++ return mac_len; ++} ++ ++/* ++ * Return true if the specified rate is supported by the specified band. ++ * BRCM_BAND_AUTO indicates the current band. ++ */ ++static bool brcms_c_valid_rate(struct brcms_c_info *wlc, u32 rspec, int band, ++ bool verbose) ++{ ++ struct brcms_c_rateset *hw_rateset; ++ uint i; ++ ++ if ((band == BRCM_BAND_AUTO) || (band == wlc->band->bandtype)) ++ hw_rateset = &wlc->band->hw_rateset; ++ else if (wlc->pub->_nbands > 1) ++ hw_rateset = &wlc->bandstate[OTHERBANDUNIT(wlc)]->hw_rateset; ++ else ++ /* other band specified and we are a single band device */ ++ return false; ++ ++ /* check if this is a mimo rate */ ++ if (is_mcs_rate(rspec)) { ++ if ((rspec & RSPEC_RATE_MASK) >= MCS_TABLE_SIZE) ++ goto error; ++ ++ return isset(hw_rateset->mcs, (rspec & RSPEC_RATE_MASK)); ++ } ++ ++ for (i = 0; i < hw_rateset->count; i++) ++ if (hw_rateset->rates[i] == rspec2rate(rspec)) ++ return true; ++ error: ++ if (verbose) ++ wiphy_err(wlc->wiphy, "wl%d: valid_rate: rate spec 0x%x " ++ "not in hw_rateset\n", wlc->pub->unit, rspec); ++ ++ return false; ++} ++ ++static u32 ++mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band, ++ u32 int_val) ++{ ++ u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT; ++ u8 rate = int_val & NRATE_RATE_MASK; ++ u32 rspec; ++ bool ismcs = ((int_val & NRATE_MCS_INUSE) == NRATE_MCS_INUSE); ++ bool issgi = ((int_val & NRATE_SGI_MASK) >> NRATE_SGI_SHIFT); ++ bool override_mcs_only = ((int_val & NRATE_OVERRIDE_MCS_ONLY) ++ == NRATE_OVERRIDE_MCS_ONLY); ++ int bcmerror = 0; ++ ++ if (!ismcs) ++ return (u32) rate; ++ ++ /* validate the combination of rate/mcs/stf is allowed */ ++ if ((wlc->pub->_n_enab & SUPPORT_11N) && ismcs) { ++ /* mcs only allowed when nmode */ ++ if (stf > PHY_TXC1_MODE_SDM) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid stf\n", ++ wlc->pub->unit, __func__); ++ bcmerror = -EINVAL; ++ goto done; ++ } ++ ++ /* mcs 32 is a special case, DUP mode 40 only */ ++ if (rate == 32) { ++ if (!CHSPEC_IS40(wlc->home_chanspec) || ++ ((stf != PHY_TXC1_MODE_SISO) ++ && (stf != PHY_TXC1_MODE_CDD))) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid mcs " ++ "32\n", wlc->pub->unit, __func__); ++ bcmerror = -EINVAL; ++ goto done; ++ } ++ /* mcs > 7 must use stf SDM */ ++ } else if (rate > HIGHEST_SINGLE_STREAM_MCS) { ++ /* mcs > 7 must use stf SDM */ ++ if (stf != PHY_TXC1_MODE_SDM) { ++ BCMMSG(wlc->wiphy, "wl%d: enabling " ++ "SDM mode for mcs %d\n", ++ wlc->pub->unit, rate); ++ stf = PHY_TXC1_MODE_SDM; ++ } ++ } else { ++ /* ++ * MCS 0-7 may use SISO, CDD, and for ++ * phy_rev >= 3 STBC ++ */ ++ if ((stf > PHY_TXC1_MODE_STBC) || ++ (!BRCMS_STBC_CAP_PHY(wlc) ++ && (stf == PHY_TXC1_MODE_STBC))) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid STBC" ++ "\n", wlc->pub->unit, __func__); ++ bcmerror = -EINVAL; ++ goto done; ++ } ++ } ++ } else if (is_ofdm_rate(rate)) { ++ if ((stf != PHY_TXC1_MODE_CDD) && (stf != PHY_TXC1_MODE_SISO)) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid OFDM\n", ++ wlc->pub->unit, __func__); ++ bcmerror = -EINVAL; ++ goto done; ++ } ++ } else if (is_cck_rate(rate)) { ++ if ((cur_band->bandtype != BRCM_BAND_2G) ++ || (stf != PHY_TXC1_MODE_SISO)) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid CCK\n", ++ wlc->pub->unit, __func__); ++ bcmerror = -EINVAL; ++ goto done; ++ } ++ } else { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Unknown rate type\n", ++ wlc->pub->unit, __func__); ++ bcmerror = -EINVAL; ++ goto done; ++ } ++ /* make sure multiple antennae are available for non-siso rates */ ++ if ((stf != PHY_TXC1_MODE_SISO) && (wlc->stf->txstreams == 1)) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: SISO antenna but !SISO " ++ "request\n", wlc->pub->unit, __func__); ++ bcmerror = -EINVAL; ++ goto done; ++ } ++ ++ rspec = rate; ++ if (ismcs) { ++ rspec |= RSPEC_MIMORATE; ++ /* For STBC populate the STC field of the ratespec */ ++ if (stf == PHY_TXC1_MODE_STBC) { ++ u8 stc; ++ stc = 1; /* Nss for single stream is always 1 */ ++ rspec |= (stc << RSPEC_STC_SHIFT); ++ } ++ } ++ ++ rspec |= (stf << RSPEC_STF_SHIFT); ++ ++ if (override_mcs_only) ++ rspec |= RSPEC_OVERRIDE_MCS_ONLY; ++ ++ if (issgi) ++ rspec |= RSPEC_SHORT_GI; ++ ++ if ((rate != 0) ++ && !brcms_c_valid_rate(wlc, rspec, cur_band->bandtype, true)) ++ return rate; ++ ++ return rspec; ++done: ++ return rate; ++} ++ ++/* ++ * Compute PLCP, but only requires actual rate and length of pkt. ++ * Rate is given in the driver standard multiple of 500 kbps. ++ * le is set for 11 Mbps rate if necessary. ++ * Broken out for PRQ. ++ */ ++ ++static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500, ++ uint length, u8 *plcp) ++{ ++ u16 usec = 0; ++ u8 le = 0; ++ ++ switch (rate_500) { ++ case BRCM_RATE_1M: ++ usec = length << 3; ++ break; ++ case BRCM_RATE_2M: ++ usec = length << 2; ++ break; ++ case BRCM_RATE_5M5: ++ usec = (length << 4) / 11; ++ if ((length << 4) - (usec * 11) > 0) ++ usec++; ++ break; ++ case BRCM_RATE_11M: ++ usec = (length << 3) / 11; ++ if ((length << 3) - (usec * 11) > 0) { ++ usec++; ++ if ((usec * 11) - (length << 3) >= 8) ++ le = D11B_PLCP_SIGNAL_LE; ++ } ++ break; ++ ++ default: ++ wiphy_err(wlc->wiphy, ++ "brcms_c_cck_plcp_set: unsupported rate %d\n", ++ rate_500); ++ rate_500 = BRCM_RATE_1M; ++ usec = length << 3; ++ break; ++ } ++ /* PLCP signal byte */ ++ plcp[0] = rate_500 * 5; /* r (500kbps) * 5 == r (100kbps) */ ++ /* PLCP service byte */ ++ plcp[1] = (u8) (le | D11B_PLCP_SIGNAL_LOCKED); ++ /* PLCP length u16, little endian */ ++ plcp[2] = usec & 0xff; ++ plcp[3] = (usec >> 8) & 0xff; ++ /* PLCP CRC16 */ ++ plcp[4] = 0; ++ plcp[5] = 0; ++} ++ ++/* Rate: 802.11 rate code, length: PSDU length in octets */ ++static void brcms_c_compute_mimo_plcp(u32 rspec, uint length, u8 *plcp) ++{ ++ u8 mcs = (u8) (rspec & RSPEC_RATE_MASK); ++ plcp[0] = mcs; ++ if (rspec_is40mhz(rspec) || (mcs == 32)) ++ plcp[0] |= MIMO_PLCP_40MHZ; ++ BRCMS_SET_MIMO_PLCP_LEN(plcp, length); ++ plcp[3] = rspec_mimoplcp3(rspec); /* rspec already holds this byte */ ++ plcp[3] |= 0x7; /* set smoothing, not sounding ppdu & reserved */ ++ plcp[4] = 0; /* number of extension spatial streams bit 0 & 1 */ ++ plcp[5] = 0; ++} ++ ++/* Rate: 802.11 rate code, length: PSDU length in octets */ ++static void ++brcms_c_compute_ofdm_plcp(u32 rspec, u32 length, u8 *plcp) ++{ ++ u8 rate_signal; ++ u32 tmp = 0; ++ int rate = rspec2rate(rspec); ++ ++ /* ++ * encode rate per 802.11a-1999 sec 17.3.4.1, with lsb ++ * transmitted first ++ */ ++ rate_signal = rate_info[rate] & BRCMS_RATE_MASK; ++ memset(plcp, 0, D11_PHY_HDR_LEN); ++ D11A_PHY_HDR_SRATE((struct ofdm_phy_hdr *) plcp, rate_signal); ++ ++ tmp = (length & 0xfff) << 5; ++ plcp[2] |= (tmp >> 16) & 0xff; ++ plcp[1] |= (tmp >> 8) & 0xff; ++ plcp[0] |= tmp & 0xff; ++} ++ ++/* Rate: 802.11 rate code, length: PSDU length in octets */ ++static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, u32 rspec, ++ uint length, u8 *plcp) ++{ ++ int rate = rspec2rate(rspec); ++ ++ brcms_c_cck_plcp_set(wlc, rate, length, plcp); ++} ++ ++static void ++brcms_c_compute_plcp(struct brcms_c_info *wlc, u32 rspec, ++ uint length, u8 *plcp) ++{ ++ if (is_mcs_rate(rspec)) ++ brcms_c_compute_mimo_plcp(rspec, length, plcp); ++ else if (is_ofdm_rate(rspec)) ++ brcms_c_compute_ofdm_plcp(rspec, length, plcp); ++ else ++ brcms_c_compute_cck_plcp(wlc, rspec, length, plcp); ++} ++ ++/* brcms_c_compute_rtscts_dur() ++ * ++ * Calculate the 802.11 MAC header DUR field for an RTS or CTS frame ++ * DUR for normal RTS/CTS w/ frame = 3 SIFS + 1 CTS + next frame time + 1 ACK ++ * DUR for CTS-TO-SELF w/ frame = 2 SIFS + next frame time + 1 ACK ++ * ++ * cts cts-to-self or rts/cts ++ * rts_rate rts or cts rate in unit of 500kbps ++ * rate next MPDU rate in unit of 500kbps ++ * frame_len next MPDU frame length in bytes ++ */ ++u16 ++brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only, ++ u32 rts_rate, ++ u32 frame_rate, u8 rts_preamble_type, ++ u8 frame_preamble_type, uint frame_len, bool ba) ++{ ++ u16 dur, sifs; ++ ++ sifs = get_sifs(wlc->band); ++ ++ if (!cts_only) { ++ /* RTS/CTS */ ++ dur = 3 * sifs; ++ dur += ++ (u16) brcms_c_calc_cts_time(wlc, rts_rate, ++ rts_preamble_type); ++ } else { ++ /* CTS-TO-SELF */ ++ dur = 2 * sifs; ++ } ++ ++ dur += ++ (u16) brcms_c_calc_frame_time(wlc, frame_rate, frame_preamble_type, ++ frame_len); ++ if (ba) ++ dur += ++ (u16) brcms_c_calc_ba_time(wlc, frame_rate, ++ BRCMS_SHORT_PREAMBLE); ++ else ++ dur += ++ (u16) brcms_c_calc_ack_time(wlc, frame_rate, ++ frame_preamble_type); ++ return dur; ++} ++ ++static u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec) ++{ ++ u16 phyctl1 = 0; ++ u16 bw; ++ ++ if (BRCMS_ISLCNPHY(wlc->band)) { ++ bw = PHY_TXC1_BW_20MHZ; ++ } else { ++ bw = rspec_get_bw(rspec); ++ /* 10Mhz is not supported yet */ ++ if (bw < PHY_TXC1_BW_20MHZ) { ++ wiphy_err(wlc->wiphy, "phytxctl1_calc: bw %d is " ++ "not supported yet, set to 20L\n", bw); ++ bw = PHY_TXC1_BW_20MHZ; ++ } ++ } ++ ++ if (is_mcs_rate(rspec)) { ++ uint mcs = rspec & RSPEC_RATE_MASK; ++ ++ /* bw, stf, coding-type is part of rspec_phytxbyte2 returns */ ++ phyctl1 = rspec_phytxbyte2(rspec); ++ /* set the upper byte of phyctl1 */ ++ phyctl1 |= (mcs_table[mcs].tx_phy_ctl3 << 8); ++ } else if (is_cck_rate(rspec) && !BRCMS_ISLCNPHY(wlc->band) ++ && !BRCMS_ISSSLPNPHY(wlc->band)) { ++ /* ++ * In CCK mode LPPHY overloads OFDM Modulation bits with CCK ++ * Data Rate. Eventually MIMOPHY would also be converted to ++ * this format ++ */ ++ /* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */ ++ phyctl1 = (bw | (rspec_stf(rspec) << PHY_TXC1_MODE_SHIFT)); ++ } else { /* legacy OFDM/CCK */ ++ s16 phycfg; ++ /* get the phyctl byte from rate phycfg table */ ++ phycfg = brcms_c_rate_legacy_phyctl(rspec2rate(rspec)); ++ if (phycfg == -1) { ++ wiphy_err(wlc->wiphy, "phytxctl1_calc: wrong " ++ "legacy OFDM/CCK rate\n"); ++ phycfg = 0; ++ } ++ /* set the upper byte of phyctl1 */ ++ phyctl1 = ++ (bw | (phycfg << 8) | ++ (rspec_stf(rspec) << PHY_TXC1_MODE_SHIFT)); ++ } ++ return phyctl1; ++} ++ ++/* ++ * Add struct d11txh, struct cck_phy_hdr. ++ * ++ * 'p' data must start with 802.11 MAC header ++ * 'p' must allow enough bytes of local headers to be "pushed" onto the packet ++ * ++ * headroom == D11_PHY_HDR_LEN + D11_TXH_LEN (D11_TXH_LEN is now 104 bytes) ++ * ++ */ ++static u16 ++brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, ++ struct sk_buff *p, struct scb *scb, uint frag, ++ uint nfrags, uint queue, uint next_frag_len) ++{ ++ struct ieee80211_hdr *h; ++ struct d11txh *txh; ++ u8 *plcp, plcp_fallback[D11_PHY_HDR_LEN]; ++ int len, phylen, rts_phylen; ++ u16 mch, phyctl, xfts, mainrates; ++ u16 seq = 0, mcl = 0, status = 0, frameid = 0; ++ u32 rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M }; ++ u32 rts_rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M }; ++ bool use_rts = false; ++ bool use_cts = false; ++ bool use_rifs = false; ++ bool short_preamble[2] = { false, false }; ++ u8 preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE }; ++ u8 rts_preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE }; ++ u8 *rts_plcp, rts_plcp_fallback[D11_PHY_HDR_LEN]; ++ struct ieee80211_rts *rts = NULL; ++ bool qos; ++ uint ac; ++ bool hwtkmic = false; ++ u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ; ++#define ANTCFG_NONE 0xFF ++ u8 antcfg = ANTCFG_NONE; ++ u8 fbantcfg = ANTCFG_NONE; ++ uint phyctl1_stf = 0; ++ u16 durid = 0; ++ struct ieee80211_tx_rate *txrate[2]; ++ int k; ++ struct ieee80211_tx_info *tx_info; ++ bool is_mcs; ++ u16 mimo_txbw; ++ u8 mimo_preamble_type; ++ ++ /* locate 802.11 MAC header */ ++ h = (struct ieee80211_hdr *)(p->data); ++ qos = ieee80211_is_data_qos(h->frame_control); ++ ++ /* compute length of frame in bytes for use in PLCP computations */ ++ len = brcmu_pkttotlen(p); ++ phylen = len + FCS_LEN; ++ ++ /* Get tx_info */ ++ tx_info = IEEE80211_SKB_CB(p); ++ ++ /* add PLCP */ ++ plcp = skb_push(p, D11_PHY_HDR_LEN); ++ ++ /* add Broadcom tx descriptor header */ ++ txh = (struct d11txh *) skb_push(p, D11_TXH_LEN); ++ memset(txh, 0, D11_TXH_LEN); ++ ++ /* setup frameid */ ++ if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { ++ /* non-AP STA should never use BCMC queue */ ++ if (queue == TX_BCMC_FIFO) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: ASSERT queue == " ++ "TX_BCMC!\n", wlc->pub->unit, __func__); ++ frameid = bcmc_fid_generate(wlc, NULL, txh); ++ } else { ++ /* Increment the counter for first fragment */ ++ if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) ++ scb->seqnum[p->priority]++; ++ ++ /* extract fragment number from frame first */ ++ seq = le16_to_cpu(h->seq_ctrl) & FRAGNUM_MASK; ++ seq |= (scb->seqnum[p->priority] << SEQNUM_SHIFT); ++ h->seq_ctrl = cpu_to_le16(seq); ++ ++ frameid = ((seq << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) | ++ (queue & TXFID_QUEUE_MASK); ++ } ++ } ++ frameid |= queue & TXFID_QUEUE_MASK; ++ ++ /* set the ignpmq bit for all pkts tx'd in PS mode and for beacons */ ++ if (ieee80211_is_beacon(h->frame_control)) ++ mcl |= TXC_IGNOREPMQ; ++ ++ txrate[0] = tx_info->control.rates; ++ txrate[1] = txrate[0] + 1; ++ ++ /* ++ * if rate control algorithm didn't give us a fallback ++ * rate, use the primary rate ++ */ ++ if (txrate[1]->idx < 0) ++ txrate[1] = txrate[0]; ++ ++ for (k = 0; k < hw->max_rates; k++) { ++ is_mcs = txrate[k]->flags & IEEE80211_TX_RC_MCS ? true : false; ++ if (!is_mcs) { ++ if ((txrate[k]->idx >= 0) ++ && (txrate[k]->idx < ++ hw->wiphy->bands[tx_info->band]->n_bitrates)) { ++ rspec[k] = ++ hw->wiphy->bands[tx_info->band]-> ++ bitrates[txrate[k]->idx].hw_value; ++ short_preamble[k] = ++ txrate[k]-> ++ flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE ? ++ true : false; ++ } else { ++ rspec[k] = BRCM_RATE_1M; ++ } ++ } else { ++ rspec[k] = mac80211_wlc_set_nrate(wlc, wlc->band, ++ NRATE_MCS_INUSE | txrate[k]->idx); ++ } ++ ++ /* ++ * Currently only support same setting for primay and ++ * fallback rates. Unify flags for each rate into a ++ * single value for the frame ++ */ ++ use_rts |= ++ txrate[k]-> ++ flags & IEEE80211_TX_RC_USE_RTS_CTS ? true : false; ++ use_cts |= ++ txrate[k]-> ++ flags & IEEE80211_TX_RC_USE_CTS_PROTECT ? true : false; ++ ++ ++ /* ++ * (1) RATE: ++ * determine and validate primary rate ++ * and fallback rates ++ */ ++ if (!rspec_active(rspec[k])) { ++ rspec[k] = BRCM_RATE_1M; ++ } else { ++ if (!is_multicast_ether_addr(h->addr1)) { ++ /* set tx antenna config */ ++ brcms_c_antsel_antcfg_get(wlc->asi, false, ++ false, 0, 0, &antcfg, &fbantcfg); ++ } ++ } ++ } ++ ++ phyctl1_stf = wlc->stf->ss_opmode; ++ ++ if (wlc->pub->_n_enab & SUPPORT_11N) { ++ for (k = 0; k < hw->max_rates; k++) { ++ /* ++ * apply siso/cdd to single stream mcs's or ofdm ++ * if rspec is auto selected ++ */ ++ if (((is_mcs_rate(rspec[k]) && ++ is_single_stream(rspec[k] & RSPEC_RATE_MASK)) || ++ is_ofdm_rate(rspec[k])) ++ && ((rspec[k] & RSPEC_OVERRIDE_MCS_ONLY) ++ || !(rspec[k] & RSPEC_OVERRIDE))) { ++ rspec[k] &= ~(RSPEC_STF_MASK | RSPEC_STC_MASK); ++ ++ /* For SISO MCS use STBC if possible */ ++ if (is_mcs_rate(rspec[k]) ++ && BRCMS_STF_SS_STBC_TX(wlc, scb)) { ++ u8 stc; ++ ++ /* Nss for single stream is always 1 */ ++ stc = 1; ++ rspec[k] |= (PHY_TXC1_MODE_STBC << ++ RSPEC_STF_SHIFT) | ++ (stc << RSPEC_STC_SHIFT); ++ } else ++ rspec[k] |= ++ (phyctl1_stf << RSPEC_STF_SHIFT); ++ } ++ ++ /* ++ * Is the phy configured to use 40MHZ frames? If ++ * so then pick the desired txbw ++ */ ++ if (brcms_chspec_bw(wlc->chanspec) == BRCMS_40_MHZ) { ++ /* default txbw is 20in40 SB */ ++ mimo_ctlchbw = mimo_txbw = ++ CHSPEC_SB_UPPER(wlc_phy_chanspec_get( ++ wlc->band->pi)) ++ ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ; ++ ++ if (is_mcs_rate(rspec[k])) { ++ /* mcs 32 must be 40b/w DUP */ ++ if ((rspec[k] & RSPEC_RATE_MASK) ++ == 32) { ++ mimo_txbw = ++ PHY_TXC1_BW_40MHZ_DUP; ++ /* use override */ ++ } else if (wlc->mimo_40txbw != AUTO) ++ mimo_txbw = wlc->mimo_40txbw; ++ /* else check if dst is using 40 Mhz */ ++ else if (scb->flags & SCB_IS40) ++ mimo_txbw = PHY_TXC1_BW_40MHZ; ++ } else if (is_ofdm_rate(rspec[k])) { ++ if (wlc->ofdm_40txbw != AUTO) ++ mimo_txbw = wlc->ofdm_40txbw; ++ } else if (wlc->cck_40txbw != AUTO) { ++ mimo_txbw = wlc->cck_40txbw; ++ } ++ } else { ++ /* ++ * mcs32 is 40 b/w only. ++ * This is possible for probe packets on ++ * a STA during SCAN ++ */ ++ if ((rspec[k] & RSPEC_RATE_MASK) == 32) ++ /* mcs 0 */ ++ rspec[k] = RSPEC_MIMORATE; ++ ++ mimo_txbw = PHY_TXC1_BW_20MHZ; ++ } ++ ++ /* Set channel width */ ++ rspec[k] &= ~RSPEC_BW_MASK; ++ if ((k == 0) || ((k > 0) && is_mcs_rate(rspec[k]))) ++ rspec[k] |= (mimo_txbw << RSPEC_BW_SHIFT); ++ else ++ rspec[k] |= (mimo_ctlchbw << RSPEC_BW_SHIFT); ++ ++ /* Disable short GI, not supported yet */ ++ rspec[k] &= ~RSPEC_SHORT_GI; ++ ++ mimo_preamble_type = BRCMS_MM_PREAMBLE; ++ if (txrate[k]->flags & IEEE80211_TX_RC_GREEN_FIELD) ++ mimo_preamble_type = BRCMS_GF_PREAMBLE; ++ ++ if ((txrate[k]->flags & IEEE80211_TX_RC_MCS) ++ && (!is_mcs_rate(rspec[k]))) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: IEEE80211_TX_" ++ "RC_MCS != is_mcs_rate(rspec)\n", ++ wlc->pub->unit, __func__); ++ } ++ ++ if (is_mcs_rate(rspec[k])) { ++ preamble_type[k] = mimo_preamble_type; ++ ++ /* ++ * if SGI is selected, then forced mm ++ * for single stream ++ */ ++ if ((rspec[k] & RSPEC_SHORT_GI) ++ && is_single_stream(rspec[k] & ++ RSPEC_RATE_MASK)) ++ preamble_type[k] = BRCMS_MM_PREAMBLE; ++ } ++ ++ /* should be better conditionalized */ ++ if (!is_mcs_rate(rspec[0]) ++ && (tx_info->control.rates[0]. ++ flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)) ++ preamble_type[k] = BRCMS_SHORT_PREAMBLE; ++ } ++ } else { ++ for (k = 0; k < hw->max_rates; k++) { ++ /* Set ctrlchbw as 20Mhz */ ++ rspec[k] &= ~RSPEC_BW_MASK; ++ rspec[k] |= (PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT); ++ ++ /* for nphy, stf of ofdm frames must follow policies */ ++ if (BRCMS_ISNPHY(wlc->band) && is_ofdm_rate(rspec[k])) { ++ rspec[k] &= ~RSPEC_STF_MASK; ++ rspec[k] |= phyctl1_stf << RSPEC_STF_SHIFT; ++ } ++ } ++ } ++ ++ /* Reset these for use with AMPDU's */ ++ txrate[0]->count = 0; ++ txrate[1]->count = 0; ++ ++ /* (2) PROTECTION, may change rspec */ ++ if ((ieee80211_is_data(h->frame_control) || ++ ieee80211_is_mgmt(h->frame_control)) && ++ (phylen > wlc->RTSThresh) && !is_multicast_ether_addr(h->addr1)) ++ use_rts = true; ++ ++ /* (3) PLCP: determine PLCP header and MAC duration, ++ * fill struct d11txh */ ++ brcms_c_compute_plcp(wlc, rspec[0], phylen, plcp); ++ brcms_c_compute_plcp(wlc, rspec[1], phylen, plcp_fallback); ++ memcpy(&txh->FragPLCPFallback, ++ plcp_fallback, sizeof(txh->FragPLCPFallback)); ++ ++ /* Length field now put in CCK FBR CRC field */ ++ if (is_cck_rate(rspec[1])) { ++ txh->FragPLCPFallback[4] = phylen & 0xff; ++ txh->FragPLCPFallback[5] = (phylen & 0xff00) >> 8; ++ } ++ ++ /* MIMO-RATE: need validation ?? */ ++ mainrates = is_ofdm_rate(rspec[0]) ? ++ D11A_PHY_HDR_GRATE((struct ofdm_phy_hdr *) plcp) : ++ plcp[0]; ++ ++ /* DUR field for main rate */ ++ if (!ieee80211_is_pspoll(h->frame_control) && ++ !is_multicast_ether_addr(h->addr1) && !use_rifs) { ++ durid = ++ brcms_c_compute_frame_dur(wlc, rspec[0], preamble_type[0], ++ next_frag_len); ++ h->duration_id = cpu_to_le16(durid); ++ } else if (use_rifs) { ++ /* NAV protect to end of next max packet size */ ++ durid = ++ (u16) brcms_c_calc_frame_time(wlc, rspec[0], ++ preamble_type[0], ++ DOT11_MAX_FRAG_LEN); ++ durid += RIFS_11N_TIME; ++ h->duration_id = cpu_to_le16(durid); ++ } ++ ++ /* DUR field for fallback rate */ ++ if (ieee80211_is_pspoll(h->frame_control)) ++ txh->FragDurFallback = h->duration_id; ++ else if (is_multicast_ether_addr(h->addr1) || use_rifs) ++ txh->FragDurFallback = 0; ++ else { ++ durid = brcms_c_compute_frame_dur(wlc, rspec[1], ++ preamble_type[1], next_frag_len); ++ txh->FragDurFallback = cpu_to_le16(durid); ++ } ++ ++ /* (4) MAC-HDR: MacTxControlLow */ ++ if (frag == 0) ++ mcl |= TXC_STARTMSDU; ++ ++ if (!is_multicast_ether_addr(h->addr1)) ++ mcl |= TXC_IMMEDACK; ++ ++ if (wlc->band->bandtype == BRCM_BAND_5G) ++ mcl |= TXC_FREQBAND_5G; ++ ++ if (CHSPEC_IS40(wlc_phy_chanspec_get(wlc->band->pi))) ++ mcl |= TXC_BW_40; ++ ++ /* set AMIC bit if using hardware TKIP MIC */ ++ if (hwtkmic) ++ mcl |= TXC_AMIC; ++ ++ txh->MacTxControlLow = cpu_to_le16(mcl); ++ ++ /* MacTxControlHigh */ ++ mch = 0; ++ ++ /* Set fallback rate preamble type */ ++ if ((preamble_type[1] == BRCMS_SHORT_PREAMBLE) || ++ (preamble_type[1] == BRCMS_GF_PREAMBLE)) { ++ if (rspec2rate(rspec[1]) != BRCM_RATE_1M) ++ mch |= TXC_PREAMBLE_DATA_FB_SHORT; ++ } ++ ++ /* MacFrameControl */ ++ memcpy(&txh->MacFrameControl, &h->frame_control, sizeof(u16)); ++ txh->TxFesTimeNormal = cpu_to_le16(0); ++ ++ txh->TxFesTimeFallback = cpu_to_le16(0); ++ ++ /* TxFrameRA */ ++ memcpy(&txh->TxFrameRA, &h->addr1, ETH_ALEN); ++ ++ /* TxFrameID */ ++ txh->TxFrameID = cpu_to_le16(frameid); ++ ++ /* ++ * TxStatus, Note the case of recreating the first frag of a suppressed ++ * frame then we may need to reset the retry cnt's via the status reg ++ */ ++ txh->TxStatus = cpu_to_le16(status); ++ ++ /* ++ * extra fields for ucode AMPDU aggregation, the new fields are added to ++ * the END of previous structure so that it's compatible in driver. ++ */ ++ txh->MaxNMpdus = cpu_to_le16(0); ++ txh->MaxABytes_MRT = cpu_to_le16(0); ++ txh->MaxABytes_FBR = cpu_to_le16(0); ++ txh->MinMBytes = cpu_to_le16(0); ++ ++ /* (5) RTS/CTS: determine RTS/CTS PLCP header and MAC duration, ++ * furnish struct d11txh */ ++ /* RTS PLCP header and RTS frame */ ++ if (use_rts || use_cts) { ++ if (use_rts && use_cts) ++ use_cts = false; ++ ++ for (k = 0; k < 2; k++) { ++ rts_rspec[k] = brcms_c_rspec_to_rts_rspec(wlc, rspec[k], ++ false, ++ mimo_ctlchbw); ++ } ++ ++ if (!is_ofdm_rate(rts_rspec[0]) && ++ !((rspec2rate(rts_rspec[0]) == BRCM_RATE_1M) || ++ (wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) { ++ rts_preamble_type[0] = BRCMS_SHORT_PREAMBLE; ++ mch |= TXC_PREAMBLE_RTS_MAIN_SHORT; ++ } ++ ++ if (!is_ofdm_rate(rts_rspec[1]) && ++ !((rspec2rate(rts_rspec[1]) == BRCM_RATE_1M) || ++ (wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) { ++ rts_preamble_type[1] = BRCMS_SHORT_PREAMBLE; ++ mch |= TXC_PREAMBLE_RTS_FB_SHORT; ++ } ++ ++ /* RTS/CTS additions to MacTxControlLow */ ++ if (use_cts) { ++ txh->MacTxControlLow |= cpu_to_le16(TXC_SENDCTS); ++ } else { ++ txh->MacTxControlLow |= cpu_to_le16(TXC_SENDRTS); ++ txh->MacTxControlLow |= cpu_to_le16(TXC_LONGFRAME); ++ } ++ ++ /* RTS PLCP header */ ++ rts_plcp = txh->RTSPhyHeader; ++ if (use_cts) ++ rts_phylen = DOT11_CTS_LEN + FCS_LEN; ++ else ++ rts_phylen = DOT11_RTS_LEN + FCS_LEN; ++ ++ brcms_c_compute_plcp(wlc, rts_rspec[0], rts_phylen, rts_plcp); ++ ++ /* fallback rate version of RTS PLCP header */ ++ brcms_c_compute_plcp(wlc, rts_rspec[1], rts_phylen, ++ rts_plcp_fallback); ++ memcpy(&txh->RTSPLCPFallback, rts_plcp_fallback, ++ sizeof(txh->RTSPLCPFallback)); ++ ++ /* RTS frame fields... */ ++ rts = (struct ieee80211_rts *)&txh->rts_frame; ++ ++ durid = brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec[0], ++ rspec[0], rts_preamble_type[0], ++ preamble_type[0], phylen, false); ++ rts->duration = cpu_to_le16(durid); ++ /* fallback rate version of RTS DUR field */ ++ durid = brcms_c_compute_rtscts_dur(wlc, use_cts, ++ rts_rspec[1], rspec[1], ++ rts_preamble_type[1], ++ preamble_type[1], phylen, false); ++ txh->RTSDurFallback = cpu_to_le16(durid); ++ ++ if (use_cts) { ++ rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | ++ IEEE80211_STYPE_CTS); ++ ++ memcpy(&rts->ra, &h->addr2, ETH_ALEN); ++ } else { ++ rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | ++ IEEE80211_STYPE_RTS); ++ ++ memcpy(&rts->ra, &h->addr1, 2 * ETH_ALEN); ++ } ++ ++ /* mainrate ++ * low 8 bits: main frag rate/mcs, ++ * high 8 bits: rts/cts rate/mcs ++ */ ++ mainrates |= (is_ofdm_rate(rts_rspec[0]) ? ++ D11A_PHY_HDR_GRATE( ++ (struct ofdm_phy_hdr *) rts_plcp) : ++ rts_plcp[0]) << 8; ++ } else { ++ memset((char *)txh->RTSPhyHeader, 0, D11_PHY_HDR_LEN); ++ memset((char *)&txh->rts_frame, 0, ++ sizeof(struct ieee80211_rts)); ++ memset((char *)txh->RTSPLCPFallback, 0, ++ sizeof(txh->RTSPLCPFallback)); ++ txh->RTSDurFallback = 0; ++ } ++ ++#ifdef SUPPORT_40MHZ ++ /* add null delimiter count */ ++ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && is_mcs_rate(rspec)) ++ txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = ++ brcm_c_ampdu_null_delim_cnt(wlc->ampdu, scb, rspec, phylen); ++ ++#endif ++ ++ /* ++ * Now that RTS/RTS FB preamble types are updated, write ++ * the final value ++ */ ++ txh->MacTxControlHigh = cpu_to_le16(mch); ++ ++ /* ++ * MainRates (both the rts and frag plcp rates have ++ * been calculated now) ++ */ ++ txh->MainRates = cpu_to_le16(mainrates); ++ ++ /* XtraFrameTypes */ ++ xfts = frametype(rspec[1], wlc->mimoft); ++ xfts |= (frametype(rts_rspec[0], wlc->mimoft) << XFTS_RTS_FT_SHIFT); ++ xfts |= (frametype(rts_rspec[1], wlc->mimoft) << XFTS_FBRRTS_FT_SHIFT); ++ xfts |= CHSPEC_CHANNEL(wlc_phy_chanspec_get(wlc->band->pi)) << ++ XFTS_CHANNEL_SHIFT; ++ txh->XtraFrameTypes = cpu_to_le16(xfts); ++ ++ /* PhyTxControlWord */ ++ phyctl = frametype(rspec[0], wlc->mimoft); ++ if ((preamble_type[0] == BRCMS_SHORT_PREAMBLE) || ++ (preamble_type[0] == BRCMS_GF_PREAMBLE)) { ++ if (rspec2rate(rspec[0]) != BRCM_RATE_1M) ++ phyctl |= PHY_TXC_SHORT_HDR; ++ } ++ ++ /* phytxant is properly bit shifted */ ++ phyctl |= brcms_c_stf_d11hdrs_phyctl_txant(wlc, rspec[0]); ++ txh->PhyTxControlWord = cpu_to_le16(phyctl); ++ ++ /* PhyTxControlWord_1 */ ++ if (BRCMS_PHY_11N_CAP(wlc->band)) { ++ u16 phyctl1 = 0; ++ ++ phyctl1 = brcms_c_phytxctl1_calc(wlc, rspec[0]); ++ txh->PhyTxControlWord_1 = cpu_to_le16(phyctl1); ++ phyctl1 = brcms_c_phytxctl1_calc(wlc, rspec[1]); ++ txh->PhyTxControlWord_1_Fbr = cpu_to_le16(phyctl1); ++ ++ if (use_rts || use_cts) { ++ phyctl1 = brcms_c_phytxctl1_calc(wlc, rts_rspec[0]); ++ txh->PhyTxControlWord_1_Rts = cpu_to_le16(phyctl1); ++ phyctl1 = brcms_c_phytxctl1_calc(wlc, rts_rspec[1]); ++ txh->PhyTxControlWord_1_FbrRts = cpu_to_le16(phyctl1); ++ } ++ ++ /* ++ * For mcs frames, if mixedmode(overloaded with long preamble) ++ * is going to be set, fill in non-zero MModeLen and/or ++ * MModeFbrLen it will be unnecessary if they are separated ++ */ ++ if (is_mcs_rate(rspec[0]) && ++ (preamble_type[0] == BRCMS_MM_PREAMBLE)) { ++ u16 mmodelen = ++ brcms_c_calc_lsig_len(wlc, rspec[0], phylen); ++ txh->MModeLen = cpu_to_le16(mmodelen); ++ } ++ ++ if (is_mcs_rate(rspec[1]) && ++ (preamble_type[1] == BRCMS_MM_PREAMBLE)) { ++ u16 mmodefbrlen = ++ brcms_c_calc_lsig_len(wlc, rspec[1], phylen); ++ txh->MModeFbrLen = cpu_to_le16(mmodefbrlen); ++ } ++ } ++ ++ ac = skb_get_queue_mapping(p); ++ if ((scb->flags & SCB_WMECAP) && qos && wlc->edcf_txop[ac]) { ++ uint frag_dur, dur, dur_fallback; ++ ++ /* WME: Update TXOP threshold */ ++ if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) && frag == 0) { ++ frag_dur = ++ brcms_c_calc_frame_time(wlc, rspec[0], ++ preamble_type[0], phylen); ++ ++ if (rts) { ++ /* 1 RTS or CTS-to-self frame */ ++ dur = ++ brcms_c_calc_cts_time(wlc, rts_rspec[0], ++ rts_preamble_type[0]); ++ dur_fallback = ++ brcms_c_calc_cts_time(wlc, rts_rspec[1], ++ rts_preamble_type[1]); ++ /* (SIFS + CTS) + SIFS + frame + SIFS + ACK */ ++ dur += le16_to_cpu(rts->duration); ++ dur_fallback += ++ le16_to_cpu(txh->RTSDurFallback); ++ } else if (use_rifs) { ++ dur = frag_dur; ++ dur_fallback = 0; ++ } else { ++ /* frame + SIFS + ACK */ ++ dur = frag_dur; ++ dur += ++ brcms_c_compute_frame_dur(wlc, rspec[0], ++ preamble_type[0], 0); ++ ++ dur_fallback = ++ brcms_c_calc_frame_time(wlc, rspec[1], ++ preamble_type[1], ++ phylen); ++ dur_fallback += ++ brcms_c_compute_frame_dur(wlc, rspec[1], ++ preamble_type[1], 0); ++ } ++ /* NEED to set TxFesTimeNormal (hard) */ ++ txh->TxFesTimeNormal = cpu_to_le16((u16) dur); ++ /* ++ * NEED to set fallback rate version of ++ * TxFesTimeNormal (hard) ++ */ ++ txh->TxFesTimeFallback = ++ cpu_to_le16((u16) dur_fallback); ++ ++ /* ++ * update txop byte threshold (txop minus intraframe ++ * overhead) ++ */ ++ if (wlc->edcf_txop[ac] >= (dur - frag_dur)) { ++ uint newfragthresh; ++ ++ newfragthresh = ++ brcms_c_calc_frame_len(wlc, ++ rspec[0], preamble_type[0], ++ (wlc->edcf_txop[ac] - ++ (dur - frag_dur))); ++ /* range bound the fragthreshold */ ++ if (newfragthresh < DOT11_MIN_FRAG_LEN) ++ newfragthresh = ++ DOT11_MIN_FRAG_LEN; ++ else if (newfragthresh > ++ wlc->usr_fragthresh) ++ newfragthresh = ++ wlc->usr_fragthresh; ++ /* update the fragthresh and do txc update */ ++ if (wlc->fragthresh[queue] != ++ (u16) newfragthresh) ++ wlc->fragthresh[queue] = ++ (u16) newfragthresh; ++ } else { ++ wiphy_err(wlc->wiphy, "wl%d: %s txop invalid " ++ "for rate %d\n", ++ wlc->pub->unit, fifo_names[queue], ++ rspec2rate(rspec[0])); ++ } ++ ++ if (dur > wlc->edcf_txop[ac]) ++ wiphy_err(wlc->wiphy, "wl%d: %s: %s txop " ++ "exceeded phylen %d/%d dur %d/%d\n", ++ wlc->pub->unit, __func__, ++ fifo_names[queue], ++ phylen, wlc->fragthresh[queue], ++ dur, wlc->edcf_txop[ac]); ++ } ++ } ++ ++ return 0; ++} ++ ++void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu, ++ struct ieee80211_hw *hw) ++{ ++ u8 prio; ++ uint fifo; ++ struct scb *scb = &wlc->pri_scb; ++ struct ieee80211_hdr *d11_header = (struct ieee80211_hdr *)(sdu->data); ++ ++ /* ++ * 802.11 standard requires management traffic ++ * to go at highest priority ++ */ ++ prio = ieee80211_is_data(d11_header->frame_control) ? sdu->priority : ++ MAXPRIO; ++ fifo = prio2fifo[prio]; ++ if (brcms_c_d11hdrs_mac80211(wlc, hw, sdu, scb, 0, 1, fifo, 0)) ++ return; ++ brcms_c_txq_enq(wlc, scb, sdu, BRCMS_PRIO_TO_PREC(prio)); ++ brcms_c_send_q(wlc); ++} ++ ++void brcms_c_send_q(struct brcms_c_info *wlc) ++{ ++ struct sk_buff *pkt[DOT11_MAXNUMFRAGS]; ++ int prec; ++ u16 prec_map; ++ int err = 0, i, count; ++ uint fifo; ++ struct brcms_txq_info *qi = wlc->pkt_queue; ++ struct pktq *q = &qi->q; ++ struct ieee80211_tx_info *tx_info; ++ ++ prec_map = wlc->tx_prec_map; ++ ++ /* Send all the enq'd pkts that we can. ++ * Dequeue packets with precedence with empty HW fifo only ++ */ ++ while (prec_map && (pkt[0] = brcmu_pktq_mdeq(q, prec_map, &prec))) { ++ tx_info = IEEE80211_SKB_CB(pkt[0]); ++ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { ++ err = brcms_c_sendampdu(wlc->ampdu, qi, pkt, prec); ++ } else { ++ count = 1; ++ err = brcms_c_prep_pdu(wlc, pkt[0], &fifo); ++ if (!err) { ++ for (i = 0; i < count; i++) ++ brcms_c_txfifo(wlc, fifo, pkt[i], true, ++ 1); ++ } ++ } ++ ++ if (err == -EBUSY) { ++ brcmu_pktq_penq_head(q, prec, pkt[0]); ++ /* ++ * If send failed due to any other reason than a ++ * change in HW FIFO condition, quit. Otherwise, ++ * read the new prec_map! ++ */ ++ if (prec_map == wlc->tx_prec_map) ++ break; ++ prec_map = wlc->tx_prec_map; ++ } ++ } ++} ++ ++void ++brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p, ++ bool commit, s8 txpktpend) ++{ ++ u16 frameid = INVALIDFID; ++ struct d11txh *txh; ++ ++ txh = (struct d11txh *) (p->data); ++ ++ /* When a BC/MC frame is being committed to the BCMC fifo ++ * via DMA (NOT PIO), update ucode or BSS info as appropriate. ++ */ ++ if (fifo == TX_BCMC_FIFO) ++ frameid = le16_to_cpu(txh->TxFrameID); ++ ++ /* ++ * Bump up pending count for if not using rpc. If rpc is ++ * used, this will be handled in brcms_b_txfifo() ++ */ ++ if (commit) { ++ wlc->core->txpktpend[fifo] += txpktpend; ++ BCMMSG(wlc->wiphy, "pktpend inc %d to %d\n", ++ txpktpend, wlc->core->txpktpend[fifo]); ++ } ++ ++ /* Commit BCMC sequence number in the SHM frame ID location */ ++ if (frameid != INVALIDFID) { ++ /* ++ * To inform the ucode of the last mcast frame posted ++ * so that it can clear moredata bit ++ */ ++ brcms_b_write_shm(wlc->hw, M_BCMC_FID, frameid); ++ } ++ ++ if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0) ++ wiphy_err(wlc->wiphy, "txfifo: fatal, toss frames !!!\n"); ++} ++ ++u32 ++brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec, ++ bool use_rspec, u16 mimo_ctlchbw) ++{ ++ u32 rts_rspec = 0; ++ ++ if (use_rspec) ++ /* use frame rate as rts rate */ ++ rts_rspec = rspec; ++ else if (wlc->band->gmode && wlc->protection->_g && !is_cck_rate(rspec)) ++ /* Use 11Mbps as the g protection RTS target rate and fallback. ++ * Use the brcms_basic_rate() lookup to find the best basic rate ++ * under the target in case 11 Mbps is not Basic. ++ * 6 and 9 Mbps are not usually selected by rate selection, but ++ * even if the OFDM rate we are protecting is 6 or 9 Mbps, 11 ++ * is more robust. ++ */ ++ rts_rspec = brcms_basic_rate(wlc, BRCM_RATE_11M); ++ else ++ /* calculate RTS rate and fallback rate based on the frame rate ++ * RTS must be sent at a basic rate since it is a ++ * control frame, sec 9.6 of 802.11 spec ++ */ ++ rts_rspec = brcms_basic_rate(wlc, rspec); ++ ++ if (BRCMS_PHY_11N_CAP(wlc->band)) { ++ /* set rts txbw to correct side band */ ++ rts_rspec &= ~RSPEC_BW_MASK; ++ ++ /* ++ * if rspec/rspec_fallback is 40MHz, then send RTS on both ++ * 20MHz channel (DUP), otherwise send RTS on control channel ++ */ ++ if (rspec_is40mhz(rspec) && !is_cck_rate(rts_rspec)) ++ rts_rspec |= (PHY_TXC1_BW_40MHZ_DUP << RSPEC_BW_SHIFT); ++ else ++ rts_rspec |= (mimo_ctlchbw << RSPEC_BW_SHIFT); ++ ++ /* pick siso/cdd as default for ofdm */ ++ if (is_ofdm_rate(rts_rspec)) { ++ rts_rspec &= ~RSPEC_STF_MASK; ++ rts_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT); ++ } ++ } ++ return rts_rspec; ++} ++ ++void ++brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, s8 txpktpend) ++{ ++ wlc->core->txpktpend[fifo] -= txpktpend; ++ BCMMSG(wlc->wiphy, "pktpend dec %d to %d\n", txpktpend, ++ wlc->core->txpktpend[fifo]); ++ ++ /* There is more room; mark precedences related to this FIFO sendable */ ++ wlc->tx_prec_map |= wlc->fifo2prec_map[fifo]; ++ ++ /* figure out which bsscfg is being worked on... */ ++} ++ ++/* Update beacon listen interval in shared memory */ ++static void brcms_c_bcn_li_upd(struct brcms_c_info *wlc) ++{ ++ /* wake up every DTIM is the default */ ++ if (wlc->bcn_li_dtim == 1) ++ brcms_b_write_shm(wlc->hw, M_BCN_LI, 0); ++ else ++ brcms_b_write_shm(wlc->hw, M_BCN_LI, ++ (wlc->bcn_li_dtim << 8) | wlc->bcn_li_bcn); ++} ++ ++static void ++brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr, ++ u32 *tsf_h_ptr) ++{ ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ ++ /* read the tsf timer low, then high to get an atomic read */ ++ *tsf_l_ptr = R_REG(®s->tsf_timerlow); ++ *tsf_h_ptr = R_REG(®s->tsf_timerhigh); ++} ++ ++/* ++ * recover 64bit TSF value from the 16bit TSF value in the rx header ++ * given the assumption that the TSF passed in header is within 65ms ++ * of the current tsf. ++ * ++ * 6 5 4 4 3 2 1 ++ * 3.......6.......8.......0.......2.......4.......6.......8......0 ++ * |<---------- tsf_h ----------->||<--- tsf_l -->||<-RxTSFTime ->| ++ * ++ * The RxTSFTime are the lowest 16 bits and provided by the ucode. The ++ * tsf_l is filled in by brcms_b_recv, which is done earlier in the ++ * receive call sequence after rx interrupt. Only the higher 16 bits ++ * are used. Finally, the tsf_h is read from the tsf register. ++ */ ++static u64 brcms_c_recover_tsf64(struct brcms_c_info *wlc, ++ struct d11rxhdr *rxh) ++{ ++ u32 tsf_h, tsf_l; ++ u16 rx_tsf_0_15, rx_tsf_16_31; ++ ++ brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h); ++ ++ rx_tsf_16_31 = (u16)(tsf_l >> 16); ++ rx_tsf_0_15 = rxh->RxTSFTime; ++ ++ /* ++ * a greater tsf time indicates the low 16 bits of ++ * tsf_l wrapped, so decrement the high 16 bits. ++ */ ++ if ((u16)tsf_l < rx_tsf_0_15) { ++ rx_tsf_16_31 -= 1; ++ if (rx_tsf_16_31 == 0xffff) ++ tsf_h -= 1; ++ } ++ ++ return ((u64)tsf_h << 32) | (((u32)rx_tsf_16_31 << 16) + rx_tsf_0_15); ++} ++ ++static void ++prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh, ++ struct sk_buff *p, ++ struct ieee80211_rx_status *rx_status) ++{ ++ int preamble; ++ int channel; ++ u32 rspec; ++ unsigned char *plcp; ++ ++ /* fill in TSF and flag its presence */ ++ rx_status->mactime = brcms_c_recover_tsf64(wlc, rxh); ++ rx_status->flag |= RX_FLAG_MACTIME_MPDU; ++ ++ channel = BRCMS_CHAN_CHANNEL(rxh->RxChan); ++ ++ if (channel > 14) { ++ rx_status->band = IEEE80211_BAND_5GHZ; ++ rx_status->freq = ieee80211_ofdm_chan_to_freq( ++ WF_CHAN_FACTOR_5_G/2, channel); ++ ++ } else { ++ rx_status->band = IEEE80211_BAND_2GHZ; ++ rx_status->freq = ieee80211_dsss_chan_to_freq(channel); ++ } ++ ++ rx_status->signal = wlc_phy_rssi_compute(wlc->hw->band->pi, rxh); ++ ++ /* noise */ ++ /* qual */ ++ rx_status->antenna = ++ (rxh->PhyRxStatus_0 & PRXS0_RXANT_UPSUBBAND) ? 1 : 0; ++ ++ plcp = p->data; ++ ++ rspec = brcms_c_compute_rspec(rxh, plcp); ++ if (is_mcs_rate(rspec)) { ++ rx_status->rate_idx = rspec & RSPEC_RATE_MASK; ++ rx_status->flag |= RX_FLAG_HT; ++ if (rspec_is40mhz(rspec)) ++ rx_status->flag |= RX_FLAG_40MHZ; ++ } else { ++ switch (rspec2rate(rspec)) { ++ case BRCM_RATE_1M: ++ rx_status->rate_idx = 0; ++ break; ++ case BRCM_RATE_2M: ++ rx_status->rate_idx = 1; ++ break; ++ case BRCM_RATE_5M5: ++ rx_status->rate_idx = 2; ++ break; ++ case BRCM_RATE_11M: ++ rx_status->rate_idx = 3; ++ break; ++ case BRCM_RATE_6M: ++ rx_status->rate_idx = 4; ++ break; ++ case BRCM_RATE_9M: ++ rx_status->rate_idx = 5; ++ break; ++ case BRCM_RATE_12M: ++ rx_status->rate_idx = 6; ++ break; ++ case BRCM_RATE_18M: ++ rx_status->rate_idx = 7; ++ break; ++ case BRCM_RATE_24M: ++ rx_status->rate_idx = 8; ++ break; ++ case BRCM_RATE_36M: ++ rx_status->rate_idx = 9; ++ break; ++ case BRCM_RATE_48M: ++ rx_status->rate_idx = 10; ++ break; ++ case BRCM_RATE_54M: ++ rx_status->rate_idx = 11; ++ break; ++ default: ++ wiphy_err(wlc->wiphy, "%s: Unknown rate\n", __func__); ++ } ++ ++ /* ++ * For 5GHz, we should decrease the index as it is ++ * a subset of the 2.4G rates. See bitrates field ++ * of brcms_band_5GHz_nphy (in mac80211_if.c). ++ */ ++ if (rx_status->band == IEEE80211_BAND_5GHZ) ++ rx_status->rate_idx -= BRCMS_LEGACY_5G_RATE_OFFSET; ++ ++ /* Determine short preamble and rate_idx */ ++ preamble = 0; ++ if (is_cck_rate(rspec)) { ++ if (rxh->PhyRxStatus_0 & PRXS0_SHORTH) ++ rx_status->flag |= RX_FLAG_SHORTPRE; ++ } else if (is_ofdm_rate(rspec)) { ++ rx_status->flag |= RX_FLAG_SHORTPRE; ++ } else { ++ wiphy_err(wlc->wiphy, "%s: Unknown modulation\n", ++ __func__); ++ } ++ } ++ ++ if (plcp3_issgi(plcp[3])) ++ rx_status->flag |= RX_FLAG_SHORT_GI; ++ ++ if (rxh->RxStatus1 & RXS_DECERR) { ++ rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC; ++ wiphy_err(wlc->wiphy, "%s: RX_FLAG_FAILED_PLCP_CRC\n", ++ __func__); ++ } ++ if (rxh->RxStatus1 & RXS_FCSERR) { ++ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; ++ wiphy_err(wlc->wiphy, "%s: RX_FLAG_FAILED_FCS_CRC\n", ++ __func__); ++ } ++} ++ ++static void ++brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh, ++ struct sk_buff *p) ++{ ++ int len_mpdu; ++ struct ieee80211_rx_status rx_status; ++ ++ memset(&rx_status, 0, sizeof(rx_status)); ++ prep_mac80211_status(wlc, rxh, p, &rx_status); ++ ++ /* mac header+body length, exclude CRC and plcp header */ ++ len_mpdu = p->len - D11_PHY_HDR_LEN - FCS_LEN; ++ skb_pull(p, D11_PHY_HDR_LEN); ++ __skb_trim(p, len_mpdu); ++ ++ memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status)); ++ ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p); ++} ++ ++/* calculate frame duration for Mixed-mode L-SIG spoofing, return ++ * number of bytes goes in the length field ++ * ++ * Formula given by HT PHY Spec v 1.13 ++ * len = 3(nsyms + nstream + 3) - 3 ++ */ ++u16 ++brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, ++ uint mac_len) ++{ ++ uint nsyms, len = 0, kNdps; ++ ++ BCMMSG(wlc->wiphy, "wl%d: rate %d, len%d\n", ++ wlc->pub->unit, rspec2rate(ratespec), mac_len); ++ ++ if (is_mcs_rate(ratespec)) { ++ uint mcs = ratespec & RSPEC_RATE_MASK; ++ int tot_streams = (mcs_2_txstreams(mcs) + 1) + ++ rspec_stc(ratespec); ++ ++ /* ++ * the payload duration calculation matches that ++ * of regular ofdm ++ */ ++ /* 1000Ndbps = kbps * 4 */ ++ kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec), ++ rspec_issgi(ratespec)) * 4; ++ ++ if (rspec_stc(ratespec) == 0) ++ nsyms = ++ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + ++ APHY_TAIL_NBITS) * 1000, kNdps); ++ else ++ /* STBC needs to have even number of symbols */ ++ nsyms = ++ 2 * ++ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + ++ APHY_TAIL_NBITS) * 1000, 2 * kNdps); ++ ++ /* (+3) account for HT-SIG(2) and HT-STF(1) */ ++ nsyms += (tot_streams + 3); ++ /* ++ * 3 bytes/symbol @ legacy 6Mbps rate ++ * (-3) excluding service bits and tail bits ++ */ ++ len = (3 * nsyms) - 3; ++ } ++ ++ return (u16) len; ++} ++ ++static void ++brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len) ++{ ++ const struct brcms_c_rateset *rs_dflt; ++ struct brcms_c_rateset rs; ++ u8 rate; ++ u16 entry_ptr; ++ u8 plcp[D11_PHY_HDR_LEN]; ++ u16 dur, sifs; ++ uint i; ++ ++ sifs = get_sifs(wlc->band); ++ ++ rs_dflt = brcms_c_rateset_get_hwrs(wlc); ++ ++ brcms_c_rateset_copy(rs_dflt, &rs); ++ brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams); ++ ++ /* ++ * walk the phy rate table and update MAC core SHM ++ * basic rate table entries ++ */ ++ for (i = 0; i < rs.count; i++) { ++ rate = rs.rates[i] & BRCMS_RATE_MASK; ++ ++ entry_ptr = brcms_b_rate_shm_offset(wlc->hw, rate); ++ ++ /* Calculate the Probe Response PLCP for the given rate */ ++ brcms_c_compute_plcp(wlc, rate, frame_len, plcp); ++ ++ /* ++ * Calculate the duration of the Probe Response ++ * frame plus SIFS for the MAC ++ */ ++ dur = (u16) brcms_c_calc_frame_time(wlc, rate, ++ BRCMS_LONG_PREAMBLE, frame_len); ++ dur += sifs; ++ ++ /* Update the SHM Rate Table entry Probe Response values */ ++ brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_PLCP_POS, ++ (u16) (plcp[0] + (plcp[1] << 8))); ++ brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_PLCP_POS + 2, ++ (u16) (plcp[2] + (plcp[3] << 8))); ++ brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_DUR_POS, dur); ++ } ++} ++ ++/* Max buffering needed for beacon template/prb resp template is 142 bytes. ++ * ++ * PLCP header is 6 bytes. ++ * 802.11 A3 header is 24 bytes. ++ * Max beacon frame body template length is 112 bytes. ++ * Max probe resp frame body template length is 110 bytes. ++ * ++ * *len on input contains the max length of the packet available. ++ * ++ * The *len value is set to the number of bytes in buf used, and starts ++ * with the PLCP and included up to, but not including, the 4 byte FCS. ++ */ ++static void ++brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type, ++ u32 bcn_rspec, ++ struct brcms_bss_cfg *cfg, u16 *buf, int *len) ++{ ++ static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255}; ++ struct cck_phy_hdr *plcp; ++ struct ieee80211_mgmt *h; ++ int hdr_len, body_len; ++ ++ hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN; ++ ++ /* calc buffer size provided for frame body */ ++ body_len = *len - hdr_len; ++ /* return actual size */ ++ *len = hdr_len + body_len; ++ ++ /* format PHY and MAC headers */ ++ memset((char *)buf, 0, hdr_len); ++ ++ plcp = (struct cck_phy_hdr *) buf; ++ ++ /* ++ * PLCP for Probe Response frames are filled in from ++ * core's rate table ++ */ ++ if (type == IEEE80211_STYPE_BEACON) ++ /* fill in PLCP */ ++ brcms_c_compute_plcp(wlc, bcn_rspec, ++ (DOT11_MAC_HDR_LEN + body_len + FCS_LEN), ++ (u8 *) plcp); ++ ++ /* "Regular" and 16 MBSS but not for 4 MBSS */ ++ /* Update the phytxctl for the beacon based on the rspec */ ++ brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec); ++ ++ h = (struct ieee80211_mgmt *)&plcp[1]; ++ ++ /* fill in 802.11 header */ ++ h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type); ++ ++ /* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */ ++ /* A1 filled in by MAC for prb resp, broadcast for bcn */ ++ if (type == IEEE80211_STYPE_BEACON) ++ memcpy(&h->da, ðer_bcast, ETH_ALEN); ++ memcpy(&h->sa, &cfg->cur_etheraddr, ETH_ALEN); ++ memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN); ++ ++ /* SEQ filled in by MAC */ ++} ++ ++int brcms_c_get_header_len(void) ++{ ++ return TXOFF; ++} ++ ++/* ++ * Update all beacons for the system. ++ */ ++void brcms_c_update_beacon(struct brcms_c_info *wlc) ++{ ++ struct brcms_bss_cfg *bsscfg = wlc->bsscfg; ++ ++ if (bsscfg->up && !bsscfg->BSS) ++ /* Clear the soft intmask */ ++ wlc->defmacintmask &= ~MI_BCNTPL; ++} ++ ++/* Write ssid into shared memory */ ++static void ++brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg) ++{ ++ u8 *ssidptr = cfg->SSID; ++ u16 base = M_SSID; ++ u8 ssidbuf[IEEE80211_MAX_SSID_LEN]; ++ ++ /* padding the ssid with zero and copy it into shm */ ++ memset(ssidbuf, 0, IEEE80211_MAX_SSID_LEN); ++ memcpy(ssidbuf, ssidptr, cfg->SSID_len); ++ ++ brcms_c_copyto_shm(wlc, base, ssidbuf, IEEE80211_MAX_SSID_LEN); ++ brcms_b_write_shm(wlc->hw, M_SSIDLEN, (u16) cfg->SSID_len); ++} ++ ++static void ++brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, ++ struct brcms_bss_cfg *cfg, ++ bool suspend) ++{ ++ u16 prb_resp[BCN_TMPL_LEN / 2]; ++ int len = BCN_TMPL_LEN; ++ ++ /* ++ * write the probe response to hardware, or save in ++ * the config structure ++ */ ++ ++ /* create the probe response template */ ++ brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0, ++ cfg, prb_resp, &len); ++ ++ if (suspend) ++ brcms_c_suspend_mac_and_wait(wlc); ++ ++ /* write the probe response into the template region */ ++ brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE, ++ (len + 3) & ~3, prb_resp); ++ ++ /* write the length of the probe response frame (+PLCP/-FCS) */ ++ brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len); ++ ++ /* write the SSID and SSID length */ ++ brcms_c_shm_ssid_upd(wlc, cfg); ++ ++ /* ++ * Write PLCP headers and durations for probe response frames ++ * at all rates. Use the actual frame length covered by the ++ * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table() ++ * by subtracting the PLCP len and adding the FCS. ++ */ ++ len += (-D11_PHY_HDR_LEN + FCS_LEN); ++ brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len); ++ ++ if (suspend) ++ brcms_c_enable_mac(wlc); ++} ++ ++void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend) ++{ ++ struct brcms_bss_cfg *bsscfg = wlc->bsscfg; ++ ++ /* update AP or IBSS probe responses */ ++ if (bsscfg->up && !bsscfg->BSS) ++ brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend); ++} ++ ++/* prepares pdu for transmission. returns BCM error codes */ ++int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu, uint *fifop) ++{ ++ uint fifo; ++ struct d11txh *txh; ++ struct ieee80211_hdr *h; ++ struct scb *scb; ++ ++ txh = (struct d11txh *) (pdu->data); ++ h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN); ++ ++ /* get the pkt queue info. This was put at brcms_c_sendctl or ++ * brcms_c_send for PDU */ ++ fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK; ++ ++ scb = NULL; ++ ++ *fifop = fifo; ++ ++ /* return if insufficient dma resources */ ++ if (*wlc->core->txavail[fifo] < MAX_DMA_SEGS) { ++ /* Mark precedences related to this FIFO, unsendable */ ++ /* A fifo is full. Clear precedences related to that FIFO */ ++ wlc->tx_prec_map &= ~(wlc->fifo2prec_map[fifo]); ++ return -EBUSY; ++ } ++ return 0; ++} ++ ++int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, ++ uint *blocks) ++{ ++ if (fifo >= NFIFO) ++ return -EINVAL; ++ ++ *blocks = wlc_hw->xmtfifo_sz[fifo]; ++ ++ return 0; ++} ++ ++void ++brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset, ++ const u8 *addr) ++{ ++ brcms_b_set_addrmatch(wlc->hw, match_reg_offset, addr); ++ if (match_reg_offset == RCM_BSSID_OFFSET) ++ memcpy(wlc->bsscfg->BSSID, addr, ETH_ALEN); ++} ++ ++/* ++ * Flag 'scan in progress' to withhold dynamic phy calibration ++ */ ++void brcms_c_scan_start(struct brcms_c_info *wlc) ++{ ++ wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, true); ++} ++ ++void brcms_c_scan_stop(struct brcms_c_info *wlc) ++{ ++ wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, false); ++} ++ ++void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state) ++{ ++ wlc->pub->associated = state; ++ wlc->bsscfg->associated = state; ++} ++ ++/* ++ * When a remote STA/AP is removed by Mac80211, or when it can no longer accept ++ * AMPDU traffic, packets pending in hardware have to be invalidated so that ++ * when later on hardware releases them, they can be handled appropriately. ++ */ ++void brcms_c_inval_dma_pkts(struct brcms_hardware *hw, ++ struct ieee80211_sta *sta, ++ void (*dma_callback_fn)) ++{ ++ struct dma_pub *dmah; ++ int i; ++ for (i = 0; i < NFIFO; i++) { ++ dmah = hw->di[i]; ++ if (dmah != NULL) ++ dma_walk_packets(dmah, dma_callback_fn, sta); ++ } ++} ++ ++int brcms_c_get_curband(struct brcms_c_info *wlc) ++{ ++ return wlc->band->bandunit; ++} ++ ++void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop) ++{ ++ /* flush packet queue when requested */ ++ if (drop) ++ brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL); ++ ++ /* wait for queue and DMA fifos to run dry */ ++ while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0) ++ brcms_msleep(wlc->wl, 1); ++} ++ ++void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval) ++{ ++ wlc->bcn_li_bcn = interval; ++ if (wlc->pub->up) ++ brcms_c_bcn_li_upd(wlc); ++} ++ ++int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr) ++{ ++ uint qdbm; ++ ++ /* Remove override bit and clip to max qdbm value */ ++ qdbm = min_t(uint, txpwr * BRCMS_TXPWR_DB_FACTOR, 0xff); ++ return wlc_phy_txpower_set(wlc->band->pi, qdbm, false); ++} ++ ++int brcms_c_get_tx_power(struct brcms_c_info *wlc) ++{ ++ uint qdbm; ++ bool override; ++ ++ wlc_phy_txpower_get(wlc->band->pi, &qdbm, &override); ++ ++ /* Return qdbm units */ ++ return (int)(qdbm / BRCMS_TXPWR_DB_FACTOR); ++} ++ ++void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc) ++{ ++ wlc->mpc = mpc; ++ brcms_c_radio_mpc_upd(wlc); ++} ++ ++/* Process received frames */ ++/* ++ * Return true if more frames need to be processed. false otherwise. ++ * Param 'bound' indicates max. # frames to process before break out. ++ */ ++static void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p) ++{ ++ struct d11rxhdr *rxh; ++ struct ieee80211_hdr *h; ++ uint len; ++ bool is_amsdu; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ ++ /* frame starts with rxhdr */ ++ rxh = (struct d11rxhdr *) (p->data); ++ ++ /* strip off rxhdr */ ++ skb_pull(p, BRCMS_HWRXOFF); ++ ++ /* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */ ++ if (rxh->RxStatus1 & RXS_PBPRES) { ++ if (p->len < 2) { ++ wiphy_err(wlc->wiphy, "wl%d: recv: rcvd runt of " ++ "len %d\n", wlc->pub->unit, p->len); ++ goto toss; ++ } ++ skb_pull(p, 2); ++ } ++ ++ h = (struct ieee80211_hdr *)(p->data + D11_PHY_HDR_LEN); ++ len = p->len; ++ ++ if (rxh->RxStatus1 & RXS_FCSERR) { ++ if (wlc->pub->mac80211_state & MAC80211_PROMISC_BCNS) { ++ wiphy_err(wlc->wiphy, "FCSERR while scanning******* -" ++ " tossing\n"); ++ goto toss; ++ } else { ++ wiphy_err(wlc->wiphy, "RCSERR!!!\n"); ++ goto toss; ++ } ++ } ++ ++ /* check received pkt has at least frame control field */ ++ if (len < D11_PHY_HDR_LEN + sizeof(h->frame_control)) ++ goto toss; ++ ++ /* not supporting A-MSDU */ ++ is_amsdu = rxh->RxStatus2 & RXS_AMSDU_MASK; ++ if (is_amsdu) ++ goto toss; ++ ++ brcms_c_recvctl(wlc, rxh, p); ++ return; ++ ++ toss: ++ brcmu_pkt_buf_free_skb(p); ++} ++ ++/* Process received frames */ ++/* ++ * Return true if more frames need to be processed. false otherwise. ++ * Param 'bound' indicates max. # frames to process before break out. ++ */ ++static bool ++brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound) ++{ ++ struct sk_buff *p; ++ struct sk_buff *head = NULL; ++ struct sk_buff *tail = NULL; ++ uint n = 0; ++ uint bound_limit = bound ? RXBND : -1; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ /* gather received frames */ ++ while ((p = dma_rx(wlc_hw->di[fifo]))) { ++ ++ if (!tail) ++ head = tail = p; ++ else { ++ tail->prev = p; ++ tail = p; ++ } ++ ++ /* !give others some time to run! */ ++ if (++n >= bound_limit) ++ break; ++ } ++ ++ /* post more rbufs */ ++ dma_rxfill(wlc_hw->di[fifo]); ++ ++ /* process each frame */ ++ while ((p = head) != NULL) { ++ struct d11rxhdr_le *rxh_le; ++ struct d11rxhdr *rxh; ++ head = head->prev; ++ p->prev = NULL; ++ ++ rxh_le = (struct d11rxhdr_le *)p->data; ++ rxh = (struct d11rxhdr *)p->data; ++ ++ /* fixup rx header endianness */ ++ rxh->RxFrameSize = le16_to_cpu(rxh_le->RxFrameSize); ++ rxh->PhyRxStatus_0 = le16_to_cpu(rxh_le->PhyRxStatus_0); ++ rxh->PhyRxStatus_1 = le16_to_cpu(rxh_le->PhyRxStatus_1); ++ rxh->PhyRxStatus_2 = le16_to_cpu(rxh_le->PhyRxStatus_2); ++ rxh->PhyRxStatus_3 = le16_to_cpu(rxh_le->PhyRxStatus_3); ++ rxh->PhyRxStatus_4 = le16_to_cpu(rxh_le->PhyRxStatus_4); ++ rxh->PhyRxStatus_5 = le16_to_cpu(rxh_le->PhyRxStatus_5); ++ rxh->RxStatus1 = le16_to_cpu(rxh_le->RxStatus1); ++ rxh->RxStatus2 = le16_to_cpu(rxh_le->RxStatus2); ++ rxh->RxTSFTime = le16_to_cpu(rxh_le->RxTSFTime); ++ rxh->RxChan = le16_to_cpu(rxh_le->RxChan); ++ ++ brcms_c_recv(wlc_hw->wlc, p); ++ } ++ ++ return n >= bound_limit; ++} ++ ++/* second-level interrupt processing ++ * Return true if another dpc needs to be re-scheduled. false otherwise. ++ * Param 'bounded' indicates if applicable loops should be bounded. ++ */ ++bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) ++{ ++ u32 macintstatus; ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ struct wiphy *wiphy = wlc->wiphy; ++ ++ if (brcms_deviceremoved(wlc)) { ++ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, ++ __func__); ++ brcms_down(wlc->wl); ++ return false; ++ } ++ ++ /* grab and clear the saved software intstatus bits */ ++ macintstatus = wlc->macintstatus; ++ wlc->macintstatus = 0; ++ ++ BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n", ++ wlc_hw->unit, macintstatus); ++ ++ WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */ ++ ++ /* tx status */ ++ if (macintstatus & MI_TFS) { ++ bool fatal; ++ if (brcms_b_txstatus(wlc->hw, bounded, &fatal)) ++ wlc->macintstatus |= MI_TFS; ++ if (fatal) { ++ wiphy_err(wiphy, "MI_TFS: fatal\n"); ++ goto fatal; ++ } ++ } ++ ++ if (macintstatus & (MI_TBTT | MI_DTIM_TBTT)) ++ brcms_c_tbtt(wlc); ++ ++ /* ATIM window end */ ++ if (macintstatus & MI_ATIMWINEND) { ++ BCMMSG(wlc->wiphy, "end of ATIM window\n"); ++ OR_REG(®s->maccommand, wlc->qvalid); ++ wlc->qvalid = 0; ++ } ++ ++ /* ++ * received data or control frame, MI_DMAINT is ++ * indication of RX_FIFO interrupt ++ */ ++ if (macintstatus & MI_DMAINT) ++ if (brcms_b_recv(wlc_hw, RX_FIFO, bounded)) ++ wlc->macintstatus |= MI_DMAINT; ++ ++ /* noise sample collected */ ++ if (macintstatus & MI_BG_NOISE) ++ wlc_phy_noise_sample_intr(wlc_hw->band->pi); ++ ++ if (macintstatus & MI_GP0) { ++ wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d " ++ "(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now); ++ ++ printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n", ++ __func__, wlc_hw->sih->chip, ++ wlc_hw->sih->chiprev); ++ /* big hammer */ ++ brcms_init(wlc->wl); ++ } ++ ++ /* gptimer timeout */ ++ if (macintstatus & MI_TO) ++ W_REG(®s->gptimer, 0); ++ ++ if (macintstatus & MI_RFDISABLE) { ++ BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the" ++ " RF Disable Input\n", wlc_hw->unit); ++ brcms_rfkill_set_hw_state(wlc->wl); ++ } ++ ++ /* send any enq'd tx packets. Just makes sure to jump start tx */ ++ if (!pktq_empty(&wlc->pkt_queue->q)) ++ brcms_c_send_q(wlc); ++ ++ /* it isn't done and needs to be resched if macintstatus is non-zero */ ++ return wlc->macintstatus != 0; ++ ++ fatal: ++ brcms_init(wlc->wl); ++ return wlc->macintstatus != 0; ++} ++ ++void brcms_c_init(struct brcms_c_info *wlc) ++{ ++ struct d11regs __iomem *regs; ++ u16 chanspec; ++ bool mute = false; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ ++ regs = wlc->regs; ++ ++ /* ++ * This will happen if a big-hammer was executed. In ++ * that case, we want to go back to the channel that ++ * we were on and not new channel ++ */ ++ if (wlc->pub->associated) ++ chanspec = wlc->home_chanspec; ++ else ++ chanspec = brcms_c_init_chanspec(wlc); ++ ++ brcms_b_init(wlc->hw, chanspec, mute); ++ ++ /* update beacon listen interval */ ++ brcms_c_bcn_li_upd(wlc); ++ ++ /* write ethernet address to core */ ++ brcms_c_set_mac(wlc->bsscfg); ++ brcms_c_set_bssid(wlc->bsscfg); ++ ++ /* Update tsf_cfprep if associated and up */ ++ if (wlc->pub->associated && wlc->bsscfg->up) { ++ u32 bi; ++ ++ /* get beacon period and convert to uS */ ++ bi = wlc->bsscfg->current_bss->beacon_period << 10; ++ /* ++ * update since init path would reset ++ * to default value ++ */ ++ W_REG(®s->tsf_cfprep, ++ (bi << CFPREP_CBI_SHIFT)); ++ ++ /* Update maccontrol PM related bits */ ++ brcms_c_set_ps_ctrl(wlc); ++ } ++ ++ brcms_c_bandinit_ordered(wlc, chanspec); ++ ++ /* init probe response timeout */ ++ brcms_b_write_shm(wlc->hw, M_PRS_MAXTIME, wlc->prb_resp_timeout); ++ ++ /* init max burst txop (framebursting) */ ++ brcms_b_write_shm(wlc->hw, M_MBURST_TXOP, ++ (wlc-> ++ _rifs ? (EDCF_AC_VO_TXOP_AP << 5) : MAXFRAMEBURST_TXOP)); ++ ++ /* initialize maximum allowed duty cycle */ ++ brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_ofdm, true, true); ++ brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_cck, false, true); ++ ++ /* ++ * Update some shared memory locations related to ++ * max AMPDU size allowed to received ++ */ ++ brcms_c_ampdu_shm_upd(wlc->ampdu); ++ ++ /* band-specific inits */ ++ brcms_c_bsinit(wlc); ++ ++ /* Enable EDCF mode (while the MAC is suspended) */ ++ OR_REG(®s->ifs_ctl, IFS_USEEDCF); ++ brcms_c_edcf_setparams(wlc, false); ++ ++ /* Init precedence maps for empty FIFOs */ ++ brcms_c_tx_prec_map_init(wlc); ++ ++ /* read the ucode version if we have not yet done so */ ++ if (wlc->ucode_rev == 0) { ++ wlc->ucode_rev = ++ brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR) << NBITS(u16); ++ wlc->ucode_rev |= brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR); ++ } ++ ++ /* ..now really unleash hell (allow the MAC out of suspend) */ ++ brcms_c_enable_mac(wlc); ++ ++ /* clear tx flow control */ ++ brcms_c_txflowcontrol_reset(wlc); ++ ++ /* enable the RF Disable Delay timer */ ++ W_REG(&wlc->regs->rfdisabledly, RFDISABLE_DEFAULT); ++ ++ /* initialize mpc delay */ ++ wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT; ++ ++ /* ++ * Initialize WME parameters; if they haven't been set by some other ++ * mechanism (IOVar, etc) then read them from the hardware. ++ */ ++ if (GFIELD(wlc->wme_retries[0], EDCF_SHORT) == 0) { ++ /* Uninitialized; read from HW */ ++ int ac; ++ ++ for (ac = 0; ac < AC_COUNT; ac++) ++ wlc->wme_retries[ac] = ++ brcms_b_read_shm(wlc->hw, M_AC_TXLMT_ADDR(ac)); ++ } ++} ++ ++/* ++ * The common driver entry routine. Error codes should be unique ++ */ ++struct brcms_c_info * ++brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit, ++ bool piomode, void __iomem *regsva, struct pci_dev *btparam, ++ uint *perr) ++{ ++ struct brcms_c_info *wlc; ++ uint err = 0; ++ uint i, j; ++ struct brcms_pub *pub; ++ ++ /* allocate struct brcms_c_info state and its substructures */ ++ wlc = (struct brcms_c_info *) brcms_c_attach_malloc(unit, &err, device); ++ if (wlc == NULL) ++ goto fail; ++ wlc->wiphy = wl->wiphy; ++ pub = wlc->pub; ++ ++#if defined(BCMDBG) ++ wlc_info_dbg = wlc; ++#endif ++ ++ wlc->band = wlc->bandstate[0]; ++ wlc->core = wlc->corestate; ++ wlc->wl = wl; ++ pub->unit = unit; ++ pub->_piomode = piomode; ++ wlc->bandinit_pending = false; ++ ++ /* populate struct brcms_c_info with default values */ ++ brcms_c_info_init(wlc, unit); ++ ++ /* update sta/ap related parameters */ ++ brcms_c_ap_upd(wlc); ++ ++ /* ++ * low level attach steps(all hw accesses go ++ * inside, no more in rest of the attach) ++ */ ++ err = brcms_b_attach(wlc, vendor, device, unit, piomode, regsva, ++ btparam); ++ if (err) ++ goto fail; ++ ++ brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR, OFF); ++ ++ pub->phy_11ncapable = BRCMS_PHY_11N_CAP(wlc->band); ++ ++ /* disable allowed duty cycle */ ++ wlc->tx_duty_cycle_ofdm = 0; ++ wlc->tx_duty_cycle_cck = 0; ++ ++ brcms_c_stf_phy_chain_calc(wlc); ++ ++ /* txchain 1: txant 0, txchain 2: txant 1 */ ++ if (BRCMS_ISNPHY(wlc->band) && (wlc->stf->txstreams == 1)) ++ wlc->stf->txant = wlc->stf->hw_txchain - 1; ++ ++ /* push to BMAC driver */ ++ wlc_phy_stf_chain_init(wlc->band->pi, wlc->stf->hw_txchain, ++ wlc->stf->hw_rxchain); ++ ++ /* pull up some info resulting from the low attach */ ++ for (i = 0; i < NFIFO; i++) ++ wlc->core->txavail[i] = wlc->hw->txavail[i]; ++ ++ memcpy(&wlc->perm_etheraddr, &wlc->hw->etheraddr, ETH_ALEN); ++ memcpy(&pub->cur_etheraddr, &wlc->hw->etheraddr, ETH_ALEN); ++ ++ for (j = 0; j < wlc->pub->_nbands; j++) { ++ wlc->band = wlc->bandstate[j]; ++ ++ if (!brcms_c_attach_stf_ant_init(wlc)) { ++ err = 24; ++ goto fail; ++ } ++ ++ /* default contention windows size limits */ ++ wlc->band->CWmin = APHY_CWMIN; ++ wlc->band->CWmax = PHY_CWMAX; ++ ++ /* init gmode value */ ++ if (wlc->band->bandtype == BRCM_BAND_2G) { ++ wlc->band->gmode = GMODE_AUTO; ++ brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, ++ wlc->band->gmode); ++ } ++ ++ /* init _n_enab supported mode */ ++ if (BRCMS_PHY_11N_CAP(wlc->band)) { ++ pub->_n_enab = SUPPORT_11N; ++ brcms_c_protection_upd(wlc, BRCMS_PROT_N_USER, ++ ((pub->_n_enab == ++ SUPPORT_11N) ? WL_11N_2x2 : ++ WL_11N_3x3)); ++ } ++ ++ /* init per-band default rateset, depend on band->gmode */ ++ brcms_default_rateset(wlc, &wlc->band->defrateset); ++ ++ /* fill in hw_rateset */ ++ brcms_c_rateset_filter(&wlc->band->defrateset, ++ &wlc->band->hw_rateset, false, ++ BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK, ++ (bool) (wlc->pub->_n_enab & SUPPORT_11N)); ++ } ++ ++ /* ++ * update antenna config due to ++ * wlc->stf->txant/txchain/ant_rx_ovr change ++ */ ++ brcms_c_stf_phy_txant_upd(wlc); ++ ++ /* attach each modules */ ++ err = brcms_c_attach_module(wlc); ++ if (err != 0) ++ goto fail; ++ ++ if (!brcms_c_timers_init(wlc, unit)) { ++ wiphy_err(wl->wiphy, "wl%d: %s: init_timer failed\n", unit, ++ __func__); ++ err = 32; ++ goto fail; ++ } ++ ++ /* depend on rateset, gmode */ ++ wlc->cmi = brcms_c_channel_mgr_attach(wlc); ++ if (!wlc->cmi) { ++ wiphy_err(wl->wiphy, "wl%d: %s: channel_mgr_attach failed" ++ "\n", unit, __func__); ++ err = 33; ++ goto fail; ++ } ++ ++ /* init default when all parameters are ready, i.e. ->rateset */ ++ brcms_c_bss_default_init(wlc); ++ ++ /* ++ * Complete the wlc default state initializations.. ++ */ ++ ++ /* allocate our initial queue */ ++ wlc->pkt_queue = brcms_c_txq_alloc(wlc); ++ if (wlc->pkt_queue == NULL) { ++ wiphy_err(wl->wiphy, "wl%d: %s: failed to malloc tx queue\n", ++ unit, __func__); ++ err = 100; ++ goto fail; ++ } ++ ++ wlc->bsscfg->wlc = wlc; ++ ++ wlc->mimoft = FT_HT; ++ wlc->mimo_40txbw = AUTO; ++ wlc->ofdm_40txbw = AUTO; ++ wlc->cck_40txbw = AUTO; ++ brcms_c_update_mimo_band_bwcap(wlc, BRCMS_N_BW_20IN2G_40IN5G); ++ ++ /* Set default values of SGI */ ++ if (BRCMS_SGI_CAP_PHY(wlc)) { ++ brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 | ++ BRCMS_N_SGI_40)); ++ } else if (BRCMS_ISSSLPNPHY(wlc->band)) { ++ brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 | ++ BRCMS_N_SGI_40)); ++ } else { ++ brcms_c_ht_update_sgi_rx(wlc, 0); ++ } ++ ++ /* initialize radio_mpc_disable according to wlc->mpc */ ++ brcms_c_radio_mpc_upd(wlc); ++ brcms_b_antsel_set(wlc->hw, wlc->asi->antsel_avail); ++ ++ if (perr) ++ *perr = 0; ++ ++ return wlc; ++ ++ fail: ++ wiphy_err(wl->wiphy, "wl%d: %s: failed with err %d\n", ++ unit, __func__, err); ++ if (wlc) ++ brcms_c_detach(wlc); ++ ++ if (perr) ++ *perr = err; ++ return NULL; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.h.orig 2011-11-09 13:46:58.251800557 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.h 2011-11-09 13:47:17.004566116 -0500 +@@ -0,0 +1,735 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_MAIN_H_ ++#define _BRCM_MAIN_H_ ++ ++#include ++ ++#include ++#include "types.h" ++#include "d11.h" ++#include "scb.h" ++ ++#define INVCHANNEL 255 /* invalid channel */ ++ ++/* max # brcms_c_module_register() calls */ ++#define BRCMS_MAXMODULES 22 ++ ++#define SEQNUM_SHIFT 4 ++#define SEQNUM_MAX 0x1000 ++ ++#define NTXRATE 64 /* # tx MPDUs rate is reported for */ ++ ++/* Maximum wait time for a MAC suspend */ ++/* uS: 83mS is max packet time (64KB ampdu @ 6Mbps) */ ++#define BRCMS_MAX_MAC_SUSPEND 83000 ++ ++/* responses for probe requests older that this are tossed, zero to disable */ ++#define BRCMS_PRB_RESP_TIMEOUT 0 /* Disable probe response timeout */ ++ ++/* transmit buffer max headroom for protocol headers */ ++#define TXOFF (D11_TXH_LEN + D11_PHY_HDR_LEN) ++ ++#define AC_COUNT 4 ++ ++/* Macros for doing definition and get/set of bitfields ++ * Usage example, e.g. a three-bit field (bits 4-6): ++ * #define _M BITFIELD_MASK(3) ++ * #define _S 4 ++ * ... ++ * regval = R_REG(osh, ®s->regfoo); ++ * field = GFIELD(regval, ); ++ * regval = SFIELD(regval, , 1); ++ * W_REG(osh, ®s->regfoo, regval); ++ */ ++#define BITFIELD_MASK(width) \ ++ (((unsigned)1 << (width)) - 1) ++#define GFIELD(val, field) \ ++ (((val) >> field ## _S) & field ## _M) ++#define SFIELD(val, field, bits) \ ++ (((val) & (~(field ## _M << field ## _S))) | \ ++ ((unsigned)(bits) << field ## _S)) ++ ++#define SW_TIMER_MAC_STAT_UPD 30 /* periodic MAC stats update */ ++ ++/* max # supported core revisions (0 .. MAXCOREREV - 1) */ ++#define MAXCOREREV 28 ++ ++/* Double check that unsupported cores are not enabled */ ++#if CONF_MSK(D11CONF, 0x4f) || CONF_GE(D11CONF, MAXCOREREV) ++#error "Configuration for D11CONF includes unsupported versions." ++#endif /* Bad versions */ ++ ++/* values for shortslot_override */ ++#define BRCMS_SHORTSLOT_AUTO -1 /* Driver will manage Shortslot setting */ ++#define BRCMS_SHORTSLOT_OFF 0 /* Turn off short slot */ ++#define BRCMS_SHORTSLOT_ON 1 /* Turn on short slot */ ++ ++/* value for short/long and mixmode/greenfield preamble */ ++#define BRCMS_LONG_PREAMBLE (0) ++#define BRCMS_SHORT_PREAMBLE (1 << 0) ++#define BRCMS_GF_PREAMBLE (1 << 1) ++#define BRCMS_MM_PREAMBLE (1 << 2) ++#define BRCMS_IS_MIMO_PREAMBLE(_pre) (((_pre) == BRCMS_GF_PREAMBLE) || \ ++ ((_pre) == BRCMS_MM_PREAMBLE)) ++ ++/* TxFrameID */ ++/* seq and frag bits: SEQNUM_SHIFT, FRAGNUM_MASK (802.11.h) */ ++/* rate epoch bits: TXFID_RATE_SHIFT, TXFID_RATE_MASK ((wlc_rate.c) */ ++#define TXFID_QUEUE_MASK 0x0007 /* Bits 0-2 */ ++#define TXFID_SEQ_MASK 0x7FE0 /* Bits 5-15 */ ++#define TXFID_SEQ_SHIFT 5 /* Number of bit shifts */ ++#define TXFID_RATE_PROBE_MASK 0x8000 /* Bit 15 for rate probe */ ++#define TXFID_RATE_MASK 0x0018 /* Mask for bits 3 and 4 */ ++#define TXFID_RATE_SHIFT 3 /* Shift 3 bits for rate mask */ ++ ++/* promote boardrev */ ++#define BOARDREV_PROMOTABLE 0xFF /* from */ ++#define BOARDREV_PROMOTED 1 /* to */ ++ ++#define DATA_BLOCK_TX_SUPR (1 << 4) ++ ++/* 802.1D Priority to TX FIFO number for wme */ ++extern const u8 prio2fifo[]; ++ ++/* Ucode MCTL_WAKE override bits */ ++#define BRCMS_WAKE_OVERRIDE_CLKCTL 0x01 ++#define BRCMS_WAKE_OVERRIDE_PHYREG 0x02 ++#define BRCMS_WAKE_OVERRIDE_MACSUSPEND 0x04 ++#define BRCMS_WAKE_OVERRIDE_TXFIFO 0x08 ++#define BRCMS_WAKE_OVERRIDE_FORCEFAST 0x10 ++ ++/* stuff pulled in from wlc.c */ ++ ++/* Interrupt bit error summary. Don't include I_RU: we refill DMA at other ++ * times; and if we run out, constant I_RU interrupts may cause lockup. We ++ * will still get error counts from rx0ovfl. ++ */ ++#define I_ERRORS (I_PC | I_PD | I_DE | I_RO | I_XU) ++/* default software intmasks */ ++#define DEF_RXINTMASK (I_RI) /* enable rx int on rxfifo only */ ++#define DEF_MACINTMASK (MI_TXSTOP | MI_TBTT | MI_ATIMWINEND | MI_PMQ | \ ++ MI_PHYTXERR | MI_DMAINT | MI_TFS | MI_BG_NOISE | \ ++ MI_CCA | MI_TO | MI_GP0 | MI_RFDISABLE | MI_PWRUP) ++ ++#define MAXTXPKTS 6 /* max # pkts pending */ ++ ++/* frameburst */ ++#define MAXTXFRAMEBURST 8 /* vanilla xpress mode: max frames/burst */ ++#define MAXFRAMEBURST_TXOP 10000 /* Frameburst TXOP in usec */ ++ ++#define NFIFO 6 /* # tx/rx fifopairs */ ++ ++/* PLL requests */ ++ ++/* pll is shared on old chips */ ++#define BRCMS_PLLREQ_SHARED 0x1 ++/* hold pll for radio monitor register checking */ ++#define BRCMS_PLLREQ_RADIO_MON 0x2 ++/* hold/release pll for some short operation */ ++#define BRCMS_PLLREQ_FLIP 0x4 ++ ++#define CHANNEL_BANDUNIT(wlc, ch) \ ++ (((ch) <= CH_MAX_2G_CHANNEL) ? BAND_2G_INDEX : BAND_5G_INDEX) ++ ++#define OTHERBANDUNIT(wlc) \ ++ ((uint)((wlc)->band->bandunit ? BAND_2G_INDEX : BAND_5G_INDEX)) ++ ++/* ++ * 802.11 protection information ++ * ++ * _g: use g spec protection, driver internal. ++ * g_override: override for use of g spec protection. ++ * gmode_user: user config gmode, operating band->gmode is different. ++ * overlap: Overlap BSS/IBSS protection for both 11g and 11n. ++ * nmode_user: user config nmode, operating pub->nmode is different. ++ * n_cfg: use OFDM protection on MIMO frames. ++ * n_cfg_override: override for use of N protection. ++ * nongf: non-GF present protection. ++ * nongf_override: override for use of GF protection. ++ * n_pam_override: override for preamble: MM or GF. ++ * n_obss: indicated OBSS Non-HT STA present. ++*/ ++struct brcms_protection { ++ bool _g; ++ s8 g_override; ++ u8 gmode_user; ++ s8 overlap; ++ s8 nmode_user; ++ s8 n_cfg; ++ s8 n_cfg_override; ++ bool nongf; ++ s8 nongf_override; ++ s8 n_pam_override; ++ bool n_obss; ++}; ++ ++/* ++ * anything affecting the single/dual streams/antenna operation ++ * ++ * hw_txchain: HW txchain bitmap cfg. ++ * txchain: txchain bitmap being used. ++ * txstreams: number of txchains being used. ++ * hw_rxchain: HW rxchain bitmap cfg. ++ * rxchain: rxchain bitmap being used. ++ * rxstreams: number of rxchains being used. ++ * ant_rx_ovr: rx antenna override. ++ * txant: userTx antenna setting. ++ * phytxant: phyTx antenna setting in txheader. ++ * ss_opmode: singlestream Operational mode, 0:siso; 1:cdd. ++ * ss_algosel_auto: if true, use wlc->stf->ss_algo_channel; ++ * else use wlc->band->stf->ss_mode_band. ++ * ss_algo_channel: ss based on per-channel algo: 0: SISO, 1: CDD 2: STBC. ++ * rxchain_restore_delay: delay time to restore default rxchain. ++ * ldpc: AUTO/ON/OFF ldpc cap supported. ++ * txcore[MAX_STREAMS_SUPPORTED + 1]: bitmap of selected core for each Nsts. ++ * spatial_policy: ++ */ ++struct brcms_stf { ++ u8 hw_txchain; ++ u8 txchain; ++ u8 txstreams; ++ u8 hw_rxchain; ++ u8 rxchain; ++ u8 rxstreams; ++ u8 ant_rx_ovr; ++ s8 txant; ++ u16 phytxant; ++ u8 ss_opmode; ++ bool ss_algosel_auto; ++ u16 ss_algo_channel; ++ u8 rxchain_restore_delay; ++ s8 ldpc; ++ u8 txcore[MAX_STREAMS_SUPPORTED + 1]; ++ s8 spatial_policy; ++}; ++ ++#define BRCMS_STF_SS_STBC_TX(wlc, scb) \ ++ (((wlc)->stf->txstreams > 1) && (((wlc)->band->band_stf_stbc_tx == ON) \ ++ || (((scb)->flags & SCB_STBCCAP) && \ ++ (wlc)->band->band_stf_stbc_tx == AUTO && \ ++ isset(&((wlc)->stf->ss_algo_channel), PHY_TXC1_MODE_STBC)))) ++ ++#define BRCMS_STBC_CAP_PHY(wlc) (BRCMS_ISNPHY(wlc->band) && \ ++ NREV_GE(wlc->band->phyrev, 3)) ++ ++#define BRCMS_SGI_CAP_PHY(wlc) ((BRCMS_ISNPHY(wlc->band) && \ ++ NREV_GE(wlc->band->phyrev, 3)) || \ ++ BRCMS_ISLCNPHY(wlc->band)) ++ ++#define BRCMS_CHAN_PHYTYPE(x) (((x) & RXS_CHAN_PHYTYPE_MASK) \ ++ >> RXS_CHAN_PHYTYPE_SHIFT) ++#define BRCMS_CHAN_CHANNEL(x) (((x) & RXS_CHAN_ID_MASK) \ ++ >> RXS_CHAN_ID_SHIFT) ++ ++/* ++ * core state (mac) ++ */ ++struct brcms_core { ++ uint coreidx; /* # sb enumerated core */ ++ ++ /* fifo */ ++ uint *txavail[NFIFO]; /* # tx descriptors available */ ++ s16 txpktpend[NFIFO]; /* tx admission control */ ++ ++ struct macstat *macstat_snapshot; /* mac hw prev read values */ ++}; ++ ++/* ++ * band state (phy+ana+radio) ++ */ ++struct brcms_band { ++ int bandtype; /* BRCM_BAND_2G, BRCM_BAND_5G */ ++ uint bandunit; /* bandstate[] index */ ++ ++ u16 phytype; /* phytype */ ++ u16 phyrev; ++ u16 radioid; ++ u16 radiorev; ++ struct brcms_phy_pub *pi; /* pointer to phy specific information */ ++ bool abgphy_encore; ++ ++ u8 gmode; /* currently active gmode */ ++ ++ struct scb *hwrs_scb; /* permanent scb for hw rateset */ ++ ++ /* band-specific copy of default_bss.rateset */ ++ struct brcms_c_rateset defrateset; ++ ++ u8 band_stf_ss_mode; /* Configured STF type, 0:siso; 1:cdd */ ++ s8 band_stf_stbc_tx; /* STBC TX 0:off; 1:force on; -1:auto */ ++ /* rates supported by chip (phy-specific) */ ++ struct brcms_c_rateset hw_rateset; ++ u8 basic_rate[BRCM_MAXRATE + 1]; /* basic rates indexed by rate */ ++ bool mimo_cap_40; /* 40 MHz cap enabled on this band */ ++ s8 antgain; /* antenna gain from srom */ ++ ++ u16 CWmin; /* minimum size of contention window, in unit of aSlotTime */ ++ u16 CWmax; /* maximum size of contention window, in unit of aSlotTime */ ++ struct ieee80211_supported_band band; ++}; ++ ++/* module control blocks */ ++struct modulecb { ++ /* module name : NULL indicates empty array member */ ++ char name[32]; ++ /* handle passed when handler 'doiovar' is called */ ++ struct brcms_info *hdl; ++ ++ int (*down_fn)(void *handle); /* down handler. Note: the int returned ++ * by the down function is a count of the ++ * number of timers that could not be ++ * freed. ++ */ ++ ++}; ++ ++struct brcms_hw_band { ++ int bandtype; /* BRCM_BAND_2G, BRCM_BAND_5G */ ++ uint bandunit; /* bandstate[] index */ ++ u16 mhfs[MHFMAX]; /* MHF array shadow */ ++ u8 bandhw_stf_ss_mode; /* HW configured STF type, 0:siso; 1:cdd */ ++ u16 CWmin; ++ u16 CWmax; ++ u32 core_flags; ++ ++ u16 phytype; /* phytype */ ++ u16 phyrev; ++ u16 radioid; ++ u16 radiorev; ++ struct brcms_phy_pub *pi; /* pointer to phy specific information */ ++ bool abgphy_encore; ++}; ++ ++struct brcms_hardware { ++ bool _piomode; /* true if pio mode */ ++ struct brcms_c_info *wlc; ++ ++ /* fifo */ ++ struct dma_pub *di[NFIFO]; /* dma handles, per fifo */ ++ ++ uint unit; /* device instance number */ ++ ++ /* version info */ ++ u16 vendorid; /* PCI vendor id */ ++ u16 deviceid; /* PCI device id */ ++ uint corerev; /* core revision */ ++ u8 sromrev; /* version # of the srom */ ++ u16 boardrev; /* version # of particular board */ ++ u32 boardflags; /* Board specific flags from srom */ ++ u32 boardflags2; /* More board flags if sromrev >= 4 */ ++ u32 machwcap; /* MAC capabilities */ ++ u32 machwcap_backup; /* backup of machwcap */ ++ ++ struct si_pub *sih; /* SI handle (cookie for siutils calls) */ ++ struct d11regs __iomem *regs; /* pointer to device registers */ ++ struct phy_shim_info *physhim; /* phy shim layer handler */ ++ struct shared_phy *phy_sh; /* pointer to shared phy state */ ++ struct brcms_hw_band *band;/* pointer to active per-band state */ ++ /* band state per phy/radio */ ++ struct brcms_hw_band *bandstate[MAXBANDS]; ++ u16 bmac_phytxant; /* cache of high phytxant state */ ++ bool shortslot; /* currently using 11g ShortSlot timing */ ++ u16 SRL; /* 802.11 dot11ShortRetryLimit */ ++ u16 LRL; /* 802.11 dot11LongRetryLimit */ ++ u16 SFBL; /* Short Frame Rate Fallback Limit */ ++ u16 LFBL; /* Long Frame Rate Fallback Limit */ ++ ++ bool up; /* d11 hardware up and running */ ++ uint now; /* # elapsed seconds */ ++ uint _nbands; /* # bands supported */ ++ u16 chanspec; /* bmac chanspec shadow */ ++ ++ uint *txavail[NFIFO]; /* # tx descriptors available */ ++ const u16 *xmtfifo_sz; /* fifo size in 256B for each xmt fifo */ ++ ++ u32 pllreq; /* pll requests to keep PLL on */ ++ ++ u8 suspended_fifos; /* Which TX fifo to remain awake for */ ++ u32 maccontrol; /* Cached value of maccontrol */ ++ uint mac_suspend_depth; /* current depth of mac_suspend levels */ ++ u32 wake_override; /* bit flags to force MAC to WAKE mode */ ++ u32 mute_override; /* Prevent ucode from sending beacons */ ++ u8 etheraddr[ETH_ALEN]; /* currently configured ethernet address */ ++ bool noreset; /* true= do not reset hw, used by WLC_OUT */ ++ bool forcefastclk; /* true if h/w is forcing to use fast clk */ ++ bool clk; /* core is out of reset and has clock */ ++ bool sbclk; /* sb has clock */ ++ bool phyclk; /* phy is out of reset and has clock */ ++ ++ bool ucode_loaded; /* true after ucode downloaded */ ++ ++ ++ u8 hw_stf_ss_opmode; /* STF single stream operation mode */ ++ u8 antsel_type; /* Type of boardlevel mimo antenna switch-logic ++ * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board ++ */ ++ u32 antsel_avail; /* ++ * put struct antsel_info here if more info is ++ * needed ++ */ ++}; ++ ++/* TX Queue information ++ * ++ * Each flow of traffic out of the device has a TX Queue with independent ++ * flow control. Several interfaces may be associated with a single TX Queue ++ * if they belong to the same flow of traffic from the device. For multi-channel ++ * operation there are independent TX Queues for each channel. ++ */ ++struct brcms_txq_info { ++ struct brcms_txq_info *next; ++ struct pktq q; ++ uint stopped; /* tx flow control bits */ ++}; ++ ++/* ++ * Principal common driver data structure. ++ * ++ * pub: pointer to driver public state. ++ * wl: pointer to specific private state. ++ * regs: pointer to device registers. ++ * hw: HW related state. ++ * clkreq_override: setting for clkreq for PCIE : Auto, 0, 1. ++ * fastpwrup_dly: time in us needed to bring up d11 fast clock. ++ * macintstatus: bit channel between isr and dpc. ++ * macintmask: sw runtime master macintmask value. ++ * defmacintmask: default "on" macintmask value. ++ * clk: core is out of reset and has clock. ++ * core: pointer to active io core. ++ * band: pointer to active per-band state. ++ * corestate: per-core state (one per hw core). ++ * bandstate: per-band state (one per phy/radio). ++ * qvalid: DirFrmQValid and BcMcFrmQValid. ++ * ampdu: ampdu module handler. ++ * asi: antsel module handler. ++ * cmi: channel manager module handler. ++ * vendorid: PCI vendor id. ++ * deviceid: PCI device id. ++ * ucode_rev: microcode revision. ++ * machwcap: MAC capabilities, BMAC shadow. ++ * perm_etheraddr: original sprom local ethernet address. ++ * bandlocked: disable auto multi-band switching. ++ * bandinit_pending: track band init in auto band. ++ * radio_monitor: radio timer is running. ++ * going_down: down path intermediate variable. ++ * mpc: enable minimum power consumption. ++ * mpc_dlycnt: # of watchdog cnt before turn disable radio. ++ * mpc_offcnt: # of watchdog cnt that radio is disabled. ++ * mpc_delay_off: delay radio disable by # of watchdog cnt. ++ * prev_non_delay_mpc: prev state brcms_c_is_non_delay_mpc. ++ * wdtimer: timer for watchdog routine. ++ * radio_timer: timer for hw radio button monitor routine. ++ * monitor: monitor (MPDU sniffing) mode. ++ * bcnmisc_monitor: bcns promisc mode override for monitor. ++ * _rifs: enable per-packet rifs. ++ * bcn_li_bcn: beacon listen interval in # beacons. ++ * bcn_li_dtim: beacon listen interval in # dtims. ++ * WDarmed: watchdog timer is armed. ++ * WDlast: last time wlc_watchdog() was called. ++ * edcf_txop[AC_COUNT]: current txop for each ac. ++ * wme_retries: per-AC retry limits. ++ * tx_prec_map: Precedence map based on HW FIFO space. ++ * fifo2prec_map[NFIFO]: pointer to fifo2_prec map based on WME. ++ * bsscfg: set of BSS configurations, idx 0 is default and always valid. ++ * cfg: the primary bsscfg (can be AP or STA). ++ * tx_queues: common TX Queue list. ++ * modulecb: ++ * mimoft: SIGN or 11N. ++ * cck_40txbw: 11N, cck tx b/w override when in 40MHZ mode. ++ * ofdm_40txbw: 11N, ofdm tx b/w override when in 40MHZ mode. ++ * mimo_40txbw: 11N, mimo tx b/w override when in 40MHZ mode. ++ * default_bss: configured BSS parameters. ++ * mc_fid_counter: BC/MC FIFO frame ID counter. ++ * country_default: saved country for leaving 802.11d auto-country mode. ++ * autocountry_default: initial country for 802.11d auto-country mode. ++ * prb_resp_timeout: do not send prb resp if request older ++ * than this, 0 = disable. ++ * home_chanspec: shared home chanspec. ++ * chanspec: target operational channel. ++ * usr_fragthresh: user configured fragmentation threshold. ++ * fragthresh[NFIFO]: per-fifo fragmentation thresholds. ++ * RTSThresh: 802.11 dot11RTSThreshold. ++ * SRL: 802.11 dot11ShortRetryLimit. ++ * LRL: 802.11 dot11LongRetryLimit. ++ * SFBL: Short Frame Rate Fallback Limit. ++ * LFBL: Long Frame Rate Fallback Limit. ++ * shortslot: currently using 11g ShortSlot timing. ++ * shortslot_override: 11g ShortSlot override. ++ * include_legacy_erp: include Legacy ERP info elt ID 47 as well as g ID 42. ++ * PLCPHdr_override: 802.11b Preamble Type override. ++ * stf: ++ * bcn_rspec: save bcn ratespec purpose. ++ * tempsense_lasttime; ++ * tx_duty_cycle_ofdm: maximum allowed duty cycle for OFDM. ++ * tx_duty_cycle_cck: maximum allowed duty cycle for CCK. ++ * pkt_queue: txq for transmit packets. ++ * wiphy: ++ * pri_scb: primary Station Control Block ++ */ ++struct brcms_c_info { ++ struct brcms_pub *pub; ++ struct brcms_info *wl; ++ struct d11regs __iomem *regs; ++ struct brcms_hardware *hw; ++ ++ /* clock */ ++ u16 fastpwrup_dly; ++ ++ /* interrupt */ ++ u32 macintstatus; ++ u32 macintmask; ++ u32 defmacintmask; ++ ++ bool clk; ++ ++ /* multiband */ ++ struct brcms_core *core; ++ struct brcms_band *band; ++ struct brcms_core *corestate; ++ struct brcms_band *bandstate[MAXBANDS]; ++ ++ /* packet queue */ ++ uint qvalid; ++ ++ struct ampdu_info *ampdu; ++ struct antsel_info *asi; ++ struct brcms_cm_info *cmi; ++ ++ u16 vendorid; ++ u16 deviceid; ++ uint ucode_rev; ++ ++ u8 perm_etheraddr[ETH_ALEN]; ++ ++ bool bandlocked; ++ bool bandinit_pending; ++ ++ bool radio_monitor; ++ bool going_down; ++ ++ bool mpc; ++ u8 mpc_dlycnt; ++ u8 mpc_offcnt; ++ u8 mpc_delay_off; ++ u8 prev_non_delay_mpc; ++ ++ struct brcms_timer *wdtimer; ++ struct brcms_timer *radio_timer; ++ ++ /* promiscuous */ ++ bool monitor; ++ bool bcnmisc_monitor; ++ ++ /* driver feature */ ++ bool _rifs; ++ ++ /* AP-STA synchronization, power save */ ++ u8 bcn_li_bcn; ++ u8 bcn_li_dtim; ++ ++ bool WDarmed; ++ u32 WDlast; ++ ++ /* WME */ ++ u16 edcf_txop[AC_COUNT]; ++ ++ u16 wme_retries[AC_COUNT]; ++ u16 tx_prec_map; ++ u16 fifo2prec_map[NFIFO]; ++ ++ struct brcms_bss_cfg *bsscfg; ++ ++ /* tx queue */ ++ struct brcms_txq_info *tx_queues; ++ ++ struct modulecb *modulecb; ++ ++ u8 mimoft; ++ s8 cck_40txbw; ++ s8 ofdm_40txbw; ++ s8 mimo_40txbw; ++ ++ struct brcms_bss_info *default_bss; ++ ++ u16 mc_fid_counter; ++ ++ char country_default[BRCM_CNTRY_BUF_SZ]; ++ char autocountry_default[BRCM_CNTRY_BUF_SZ]; ++ u16 prb_resp_timeout; ++ ++ u16 home_chanspec; ++ ++ /* PHY parameters */ ++ u16 chanspec; ++ u16 usr_fragthresh; ++ u16 fragthresh[NFIFO]; ++ u16 RTSThresh; ++ u16 SRL; ++ u16 LRL; ++ u16 SFBL; ++ u16 LFBL; ++ ++ /* network config */ ++ bool shortslot; ++ s8 shortslot_override; ++ bool include_legacy_erp; ++ ++ struct brcms_protection *protection; ++ s8 PLCPHdr_override; ++ ++ struct brcms_stf *stf; ++ ++ u32 bcn_rspec; ++ ++ uint tempsense_lasttime; ++ ++ u16 tx_duty_cycle_ofdm; ++ u16 tx_duty_cycle_cck; ++ ++ struct brcms_txq_info *pkt_queue; ++ struct wiphy *wiphy; ++ struct scb pri_scb; ++}; ++ ++/* antsel module specific state */ ++struct antsel_info { ++ struct brcms_c_info *wlc; /* pointer to main wlc structure */ ++ struct brcms_pub *pub; /* pointer to public fn */ ++ u8 antsel_type; /* Type of boardlevel mimo antenna switch-logic ++ * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board ++ */ ++ u8 antsel_antswitch; /* board level antenna switch type */ ++ bool antsel_avail; /* Ant selection availability (SROM based) */ ++ struct brcms_antselcfg antcfg_11n; /* antenna configuration */ ++ struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */ ++}; ++ ++/* ++ * BSS configuration state ++ * ++ * wlc: wlc to which this bsscfg belongs to. ++ * up: is this configuration up operational ++ * enable: is this configuration enabled ++ * associated: is BSS in ASSOCIATED state ++ * BSS: infraustructure or adhoc ++ * SSID_len: the length of SSID ++ * SSID: SSID string ++ * ++ * ++ * BSSID: BSSID (associated) ++ * cur_etheraddr: h/w address ++ * flags: BSSCFG flags; see below ++ * ++ * current_bss: BSS parms in ASSOCIATED state ++ * ++ * ++ * ID: 'unique' ID of this bsscfg, assigned at bsscfg allocation ++ */ ++struct brcms_bss_cfg { ++ struct brcms_c_info *wlc; ++ bool up; ++ bool enable; ++ bool associated; ++ bool BSS; ++ u8 SSID_len; ++ u8 SSID[IEEE80211_MAX_SSID_LEN]; ++ u8 BSSID[ETH_ALEN]; ++ u8 cur_etheraddr[ETH_ALEN]; ++ struct brcms_bss_info *current_bss; ++}; ++ ++extern void brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, ++ struct sk_buff *p, ++ bool commit, s8 txpktpend); ++extern void brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, ++ s8 txpktpend); ++extern void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb, ++ struct sk_buff *sdu, uint prec); ++extern void brcms_c_print_txstatus(struct tx_status *txs); ++extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, ++ uint *blocks); ++ ++#if defined(BCMDBG) ++extern void brcms_c_print_txdesc(struct d11txh *txh); ++#else ++#define brcms_c_print_txdesc(a) ++#endif ++ ++extern int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config); ++extern void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc, ++ bool promisc); ++extern void brcms_c_send_q(struct brcms_c_info *wlc); ++extern int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu, ++ uint *fifo); ++extern u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, ++ uint mac_len); ++extern u32 brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, ++ u32 rspec, ++ bool use_rspec, u16 mimo_ctlchbw); ++extern u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only, ++ u32 rts_rate, ++ u32 frame_rate, ++ u8 rts_preamble_type, ++ u8 frame_preamble_type, uint frame_len, ++ bool ba); ++extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw, ++ struct ieee80211_sta *sta, ++ void (*dma_callback_fn)); ++extern void brcms_c_update_beacon(struct brcms_c_info *wlc); ++extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend); ++extern int brcms_c_set_nmode(struct brcms_c_info *wlc); ++extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, ++ u32 bcn_rate); ++extern void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, ++ u8 antsel_type); ++extern void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, ++ u16 chanspec, ++ bool mute, struct txpwr_limits *txpwr); ++extern void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, ++ u16 v); ++extern u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset); ++extern void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, ++ u16 val, int bands); ++extern void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags); ++extern void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val); ++extern void brcms_b_phy_reset(struct brcms_hardware *wlc_hw); ++extern void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw); ++extern void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw); ++extern void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw, ++ u32 override_bit); ++extern void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw, ++ u32 override_bit); ++extern void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, ++ int offset, int len, void *buf); ++extern u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate); ++extern void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, ++ uint offset, const void *buf, int len, ++ u32 sel); ++extern void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, ++ void *buf, int len, u32 sel); ++extern void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode); ++extern u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw); ++extern void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk); ++extern void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk); ++extern void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on); ++extern void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant); ++extern void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, ++ u8 stf_mode); ++extern void brcms_c_init_scb(struct scb *scb); ++ ++#endif /* _BRCM_MAIN_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/Makefile.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/Makefile +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/Makefile.orig 2011-11-09 13:46:58.251800557 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/Makefile 2011-11-09 13:47:17.005566104 -0500 +@@ -0,0 +1,51 @@ ++# ++# Makefile fragment for Broadcom 802.11n Networking Device Driver ++# ++# Copyright (c) 2010 Broadcom Corporation ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ccflags-y := \ ++ -D__CHECK_ENDIAN__ \ ++ -Idrivers/net/wireless/brcm80211/brcmsmac \ ++ -Idrivers/net/wireless/brcm80211/brcmsmac/phy \ ++ -Idrivers/net/wireless/brcm80211/include ++ ++BRCMSMAC_OFILES := \ ++ mac80211_if.o \ ++ ucode_loader.o \ ++ ampdu.o \ ++ antsel.o \ ++ channel.o \ ++ main.o \ ++ phy_shim.o \ ++ pmu.o \ ++ rate.o \ ++ stf.o \ ++ aiutils.o \ ++ phy/phy_cmn.o \ ++ phy/phy_lcn.o \ ++ phy/phy_n.o \ ++ phy/phytbl_lcn.o \ ++ phy/phytbl_n.o \ ++ phy/phy_qmath.o \ ++ otp.o \ ++ srom.o \ ++ dma.o \ ++ nicpci.o \ ++ brcms_trace_events.o ++ ++MODULEPFX := brcmsmac ++ ++obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o ++$(MODULEPFX)-objs = $(BRCMSMAC_OFILES) +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c.orig 2011-11-09 13:46:58.252800545 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c 2011-11-09 13:47:17.005566104 -0500 +@@ -0,0 +1,835 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include "aiutils.h" ++#include "pub.h" ++#include "nicpci.h" ++ ++/* SPROM offsets */ ++#define SRSH_ASPM_OFFSET 4 /* word 4 */ ++#define SRSH_ASPM_ENB 0x18 /* bit 3, 4 */ ++#define SRSH_ASPM_L1_ENB 0x10 /* bit 4 */ ++#define SRSH_ASPM_L0s_ENB 0x8 /* bit 3 */ ++ ++#define SRSH_PCIE_MISC_CONFIG 5 /* word 5 */ ++#define SRSH_L23READY_EXIT_NOPERST 0x8000 /* bit 15 */ ++#define SRSH_CLKREQ_OFFSET_REV5 20 /* word 20 for srom rev <= 5 */ ++#define SRSH_CLKREQ_ENB 0x0800 /* bit 11 */ ++#define SRSH_BD_OFFSET 6 /* word 6 */ ++ ++/* chipcontrol */ ++#define CHIPCTRL_4321_PLL_DOWN 0x800000/* serdes PLL down override */ ++ ++/* MDIO control */ ++#define MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */ ++#define MDIOCTL_DIVISOR_VAL 0x2 ++#define MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */ ++#define MDIOCTL_ACCESS_DONE 0x100 /* Transaction complete */ ++ ++/* MDIO Data */ ++#define MDIODATA_MASK 0x0000ffff /* data 2 bytes */ ++#define MDIODATA_TA 0x00020000 /* Turnaround */ ++ ++#define MDIODATA_REGADDR_SHF 18 /* Regaddr shift */ ++#define MDIODATA_REGADDR_MASK 0x007c0000 /* Regaddr Mask */ ++#define MDIODATA_DEVADDR_SHF 23 /* Physmedia devaddr shift */ ++#define MDIODATA_DEVADDR_MASK 0x0f800000 ++ /* Physmedia devaddr Mask */ ++ ++/* MDIO Data for older revisions < 10 */ ++#define MDIODATA_REGADDR_SHF_OLD 18 /* Regaddr shift */ ++#define MDIODATA_REGADDR_MASK_OLD 0x003c0000 ++ /* Regaddr Mask */ ++#define MDIODATA_DEVADDR_SHF_OLD 22 /* Physmedia devaddr shift */ ++#define MDIODATA_DEVADDR_MASK_OLD 0x0fc00000 ++ /* Physmedia devaddr Mask */ ++ ++/* Transactions flags */ ++#define MDIODATA_WRITE 0x10000000 ++#define MDIODATA_READ 0x20000000 ++#define MDIODATA_START 0x40000000 ++ ++#define MDIODATA_DEV_ADDR 0x0 /* dev address for serdes */ ++#define MDIODATA_BLK_ADDR 0x1F /* blk address for serdes */ ++ ++/* serdes regs (rev < 10) */ ++#define MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */ ++#define MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */ ++#define MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */ ++ ++/* SERDES RX registers */ ++#define SERDES_RX_CTRL 1 /* Rx cntrl */ ++#define SERDES_RX_TIMER1 2 /* Rx Timer1 */ ++#define SERDES_RX_CDR 6 /* CDR */ ++#define SERDES_RX_CDRBW 7 /* CDR BW */ ++/* SERDES RX control register */ ++#define SERDES_RX_CTRL_FORCE 0x80 /* rxpolarity_force */ ++#define SERDES_RX_CTRL_POLARITY 0x40 /* rxpolarity_value */ ++ ++/* SERDES PLL registers */ ++#define SERDES_PLL_CTRL 1 /* PLL control reg */ ++#define PLL_CTRL_FREQDET_EN 0x4000 /* bit 14 is FREQDET on */ ++ ++/* Linkcontrol reg offset in PCIE Cap */ ++#define PCIE_CAP_LINKCTRL_OFFSET 16 /* offset in pcie cap */ ++#define PCIE_CAP_LCREG_ASPML0s 0x01 /* ASPM L0s in linkctrl */ ++#define PCIE_CAP_LCREG_ASPML1 0x02 /* ASPM L1 in linkctrl */ ++#define PCIE_CLKREQ_ENAB 0x100 /* CLKREQ Enab in linkctrl */ ++ ++#define PCIE_ASPM_ENAB 3 /* ASPM L0s & L1 in linkctrl */ ++#define PCIE_ASPM_L1_ENAB 2 /* ASPM L0s & L1 in linkctrl */ ++#define PCIE_ASPM_L0s_ENAB 1 /* ASPM L0s & L1 in linkctrl */ ++#define PCIE_ASPM_DISAB 0 /* ASPM L0s & L1 in linkctrl */ ++ ++/* Power management threshold */ ++#define PCIE_L1THRESHOLDTIME_MASK 0xFF00 /* bits 8 - 15 */ ++#define PCIE_L1THRESHOLDTIME_SHIFT 8 /* PCIE_L1THRESHOLDTIME_SHIFT */ ++#define PCIE_L1THRESHOLD_WARVAL 0x72 /* WAR value */ ++#define PCIE_ASPMTIMER_EXTEND 0x01000000 ++ /* > rev7: ++ * enable extend ASPM timer ++ */ ++ ++/* different register spaces to access thru pcie indirect access */ ++#define PCIE_CONFIGREGS 1 /* Access to config space */ ++#define PCIE_PCIEREGS 2 /* Access to pcie registers */ ++ ++/* PCIE protocol PHY diagnostic registers */ ++#define PCIE_PLP_STATUSREG 0x204 /* Status */ ++ ++/* Status reg PCIE_PLP_STATUSREG */ ++#define PCIE_PLP_POLARITYINV_STAT 0x10 ++ ++/* PCIE protocol DLLP diagnostic registers */ ++#define PCIE_DLLP_LCREG 0x100 /* Link Control */ ++#define PCIE_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold */ ++ ++/* PCIE protocol TLP diagnostic registers */ ++#define PCIE_TLP_WORKAROUNDSREG 0x004 /* TLP Workarounds */ ++ ++/* Sonics to PCI translation types */ ++#define SBTOPCI_PREF 0x4 /* prefetch enable */ ++#define SBTOPCI_BURST 0x8 /* burst enable */ ++#define SBTOPCI_RC_READMULTI 0x20 /* memory read multiple */ ++ ++#define PCI_CLKRUN_DSBL 0x8000 /* Bit 15 forceClkrun */ ++ ++/* PCI core index in SROM shadow area */ ++#define SRSH_PI_OFFSET 0 /* first word */ ++#define SRSH_PI_MASK 0xf000 /* bit 15:12 */ ++#define SRSH_PI_SHIFT 12 /* bit 15:12 */ ++ ++/* Sonics side: PCI core and host control registers */ ++struct sbpciregs { ++ u32 control; /* PCI control */ ++ u32 PAD[3]; ++ u32 arbcontrol; /* PCI arbiter control */ ++ u32 clkrun; /* Clkrun Control (>=rev11) */ ++ u32 PAD[2]; ++ u32 intstatus; /* Interrupt status */ ++ u32 intmask; /* Interrupt mask */ ++ u32 sbtopcimailbox; /* Sonics to PCI mailbox */ ++ u32 PAD[9]; ++ u32 bcastaddr; /* Sonics broadcast address */ ++ u32 bcastdata; /* Sonics broadcast data */ ++ u32 PAD[2]; ++ u32 gpioin; /* ro: gpio input (>=rev2) */ ++ u32 gpioout; /* rw: gpio output (>=rev2) */ ++ u32 gpioouten; /* rw: gpio output enable (>= rev2) */ ++ u32 gpiocontrol; /* rw: gpio control (>= rev2) */ ++ u32 PAD[36]; ++ u32 sbtopci0; /* Sonics to PCI translation 0 */ ++ u32 sbtopci1; /* Sonics to PCI translation 1 */ ++ u32 sbtopci2; /* Sonics to PCI translation 2 */ ++ u32 PAD[189]; ++ u32 pcicfg[4][64]; /* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */ ++ u16 sprom[36]; /* SPROM shadow Area */ ++ u32 PAD[46]; ++}; ++ ++/* SB side: PCIE core and host control registers */ ++struct sbpcieregs { ++ u32 control; /* host mode only */ ++ u32 PAD[2]; ++ u32 biststatus; /* bist Status: 0x00C */ ++ u32 gpiosel; /* PCIE gpio sel: 0x010 */ ++ u32 gpioouten; /* PCIE gpio outen: 0x14 */ ++ u32 PAD[2]; ++ u32 intstatus; /* Interrupt status: 0x20 */ ++ u32 intmask; /* Interrupt mask: 0x24 */ ++ u32 sbtopcimailbox; /* sb to pcie mailbox: 0x028 */ ++ u32 PAD[53]; ++ u32 sbtopcie0; /* sb to pcie translation 0: 0x100 */ ++ u32 sbtopcie1; /* sb to pcie translation 1: 0x104 */ ++ u32 sbtopcie2; /* sb to pcie translation 2: 0x108 */ ++ u32 PAD[5]; ++ ++ /* pcie core supports in direct access to config space */ ++ u32 configaddr; /* pcie config space access: Address field: 0x120 */ ++ u32 configdata; /* pcie config space access: Data field: 0x124 */ ++ ++ /* mdio access to serdes */ ++ u32 mdiocontrol; /* controls the mdio access: 0x128 */ ++ u32 mdiodata; /* Data to the mdio access: 0x12c */ ++ ++ /* pcie protocol phy/dllp/tlp register indirect access mechanism */ ++ u32 pcieindaddr; /* indirect access to ++ * the internal register: 0x130 ++ */ ++ u32 pcieinddata; /* Data to/from the internal regsiter: 0x134 */ ++ ++ u32 clkreqenctrl; /* >= rev 6, Clkreq rdma control : 0x138 */ ++ u32 PAD[177]; ++ u32 pciecfg[4][64]; /* 0x400 - 0x7FF, PCIE Cfg Space */ ++ u16 sprom[64]; /* SPROM shadow Area */ ++}; ++ ++struct pcicore_info { ++ union { ++ struct sbpcieregs __iomem *pcieregs; ++ struct sbpciregs __iomem *pciregs; ++ } regs; /* Memory mapped register to the core */ ++ ++ struct si_pub *sih; /* System interconnect handle */ ++ struct pci_dev *dev; ++ u8 pciecap_lcreg_offset;/* PCIE capability LCreg offset ++ * in the config space ++ */ ++ bool pcie_pr42767; ++ u8 pcie_polarity; ++ u8 pcie_war_aspm_ovr; /* Override ASPM/Clkreq settings */ ++ ++ u8 pmecap_offset; /* PM Capability offset in the config space */ ++ bool pmecap; /* Capable of generating PME */ ++}; ++ ++#define PCIE_ASPM(sih) \ ++ (((sih)->buscoretype == PCIE_CORE_ID) && \ ++ (((sih)->buscorerev >= 3) && \ ++ ((sih)->buscorerev <= 5))) ++ ++ ++/* delay needed between the mdio control/ mdiodata register data access */ ++static void pr28829_delay(void) ++{ ++ udelay(10); ++} ++ ++/* Initialize the PCI core. ++ * It's caller's responsibility to make sure that this is done only once ++ */ ++struct pcicore_info *pcicore_init(struct si_pub *sih, struct pci_dev *pdev, ++ void __iomem *regs) ++{ ++ struct pcicore_info *pi; ++ ++ /* alloc struct pcicore_info */ ++ pi = kzalloc(sizeof(struct pcicore_info), GFP_ATOMIC); ++ if (pi == NULL) ++ return NULL; ++ ++ pi->sih = sih; ++ pi->dev = pdev; ++ ++ if (sih->buscoretype == PCIE_CORE_ID) { ++ u8 cap_ptr; ++ pi->regs.pcieregs = regs; ++ cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP, ++ NULL, NULL); ++ pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET; ++ } else ++ pi->regs.pciregs = regs; ++ ++ return pi; ++} ++ ++void pcicore_deinit(struct pcicore_info *pch) ++{ ++ kfree(pch); ++} ++ ++/* return cap_offset if requested capability exists in the PCI config space */ ++/* Note that it's caller's responsibility to make sure it's a pci bus */ ++u8 ++pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id, ++ unsigned char *buf, u32 *buflen) ++{ ++ u8 cap_id; ++ u8 cap_ptr = 0; ++ u32 bufsize; ++ u8 byte_val; ++ ++ /* check for Header type 0 */ ++ pci_read_config_byte(dev, PCI_HEADER_TYPE, &byte_val); ++ if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL) ++ goto end; ++ ++ /* check if the capability pointer field exists */ ++ pci_read_config_byte(dev, PCI_STATUS, &byte_val); ++ if (!(byte_val & PCI_STATUS_CAP_LIST)) ++ goto end; ++ ++ pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &cap_ptr); ++ /* check if the capability pointer is 0x00 */ ++ if (cap_ptr == 0x00) ++ goto end; ++ ++ /* loop thru the capability list ++ * and see if the pcie capability exists ++ */ ++ ++ pci_read_config_byte(dev, cap_ptr, &cap_id); ++ ++ while (cap_id != req_cap_id) { ++ pci_read_config_byte(dev, cap_ptr + 1, &cap_ptr); ++ if (cap_ptr == 0x00) ++ break; ++ pci_read_config_byte(dev, cap_ptr, &cap_id); ++ } ++ if (cap_id != req_cap_id) ++ goto end; ++ ++ /* found the caller requested capability */ ++ if (buf != NULL && buflen != NULL) { ++ u8 cap_data; ++ ++ bufsize = *buflen; ++ if (!bufsize) ++ goto end; ++ *buflen = 0; ++ /* copy the capability data excluding cap ID and next ptr */ ++ cap_data = cap_ptr + 2; ++ if ((bufsize + cap_data) > PCI_SZPCR) ++ bufsize = PCI_SZPCR - cap_data; ++ *buflen = bufsize; ++ while (bufsize--) { ++ pci_read_config_byte(dev, cap_data, buf); ++ cap_data++; ++ buf++; ++ } ++ } ++end: ++ return cap_ptr; ++} ++ ++/* ***** Register Access API */ ++static uint ++pcie_readreg(struct sbpcieregs __iomem *pcieregs, uint addrtype, uint offset) ++{ ++ uint retval = 0xFFFFFFFF; ++ ++ switch (addrtype) { ++ case PCIE_CONFIGREGS: ++ W_REG(&pcieregs->configaddr, offset); ++ (void)R_REG((&pcieregs->configaddr)); ++ retval = R_REG(&pcieregs->configdata); ++ break; ++ case PCIE_PCIEREGS: ++ W_REG(&pcieregs->pcieindaddr, offset); ++ (void)R_REG(&pcieregs->pcieindaddr); ++ retval = R_REG(&pcieregs->pcieinddata); ++ break; ++ } ++ ++ return retval; ++} ++ ++static uint pcie_writereg(struct sbpcieregs __iomem *pcieregs, uint addrtype, ++ uint offset, uint val) ++{ ++ switch (addrtype) { ++ case PCIE_CONFIGREGS: ++ W_REG((&pcieregs->configaddr), offset); ++ W_REG((&pcieregs->configdata), val); ++ break; ++ case PCIE_PCIEREGS: ++ W_REG((&pcieregs->pcieindaddr), offset); ++ W_REG((&pcieregs->pcieinddata), val); ++ break; ++ default: ++ break; ++ } ++ return 0; ++} ++ ++static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk) ++{ ++ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; ++ uint mdiodata, i = 0; ++ uint pcie_serdes_spinwait = 200; ++ ++ mdiodata = (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | ++ (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | ++ (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) | ++ (blk << 4)); ++ W_REG(&pcieregs->mdiodata, mdiodata); ++ ++ pr28829_delay(); ++ /* retry till the transaction is complete */ ++ while (i < pcie_serdes_spinwait) { ++ if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) ++ break; ++ ++ udelay(1000); ++ i++; ++ } ++ ++ if (i >= pcie_serdes_spinwait) ++ return false; ++ ++ return true; ++} ++ ++static int ++pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write, ++ uint *val) ++{ ++ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; ++ uint mdiodata; ++ uint i = 0; ++ uint pcie_serdes_spinwait = 10; ++ ++ /* enable mdio access to SERDES */ ++ W_REG(&pcieregs->mdiocontrol, MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); ++ ++ if (pi->sih->buscorerev >= 10) { ++ /* new serdes is slower in rw, ++ * using two layers of reg address mapping ++ */ ++ if (!pcie_mdiosetblock(pi, physmedia)) ++ return 1; ++ mdiodata = ((MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | ++ (regaddr << MDIODATA_REGADDR_SHF)); ++ pcie_serdes_spinwait *= 20; ++ } else { ++ mdiodata = ((physmedia << MDIODATA_DEVADDR_SHF_OLD) | ++ (regaddr << MDIODATA_REGADDR_SHF_OLD)); ++ } ++ ++ if (!write) ++ mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA); ++ else ++ mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | ++ *val); ++ ++ W_REG(&pcieregs->mdiodata, mdiodata); ++ ++ pr28829_delay(); ++ ++ /* retry till the transaction is complete */ ++ while (i < pcie_serdes_spinwait) { ++ if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) { ++ if (!write) { ++ pr28829_delay(); ++ *val = (R_REG(&pcieregs->mdiodata) & ++ MDIODATA_MASK); ++ } ++ /* Disable mdio access to SERDES */ ++ W_REG(&pcieregs->mdiocontrol, 0); ++ return 0; ++ } ++ udelay(1000); ++ i++; ++ } ++ ++ /* Timed out. Disable mdio access to SERDES. */ ++ W_REG(&pcieregs->mdiocontrol, 0); ++ return 1; ++} ++ ++/* use the mdio interface to read from mdio slaves */ ++static int ++pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint regaddr, ++ uint *regval) ++{ ++ return pcie_mdioop(pi, physmedia, regaddr, false, regval); ++} ++ ++/* use the mdio interface to write to mdio slaves */ ++static int ++pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint regaddr, uint val) ++{ ++ return pcie_mdioop(pi, physmedia, regaddr, true, &val); ++} ++ ++/* ***** Support functions ***** */ ++static u8 pcie_clkreq(struct pcicore_info *pi, u32 mask, u32 val) ++{ ++ u32 reg_val; ++ u8 offset; ++ ++ offset = pi->pciecap_lcreg_offset; ++ if (!offset) ++ return 0; ++ ++ pci_read_config_dword(pi->dev, offset, ®_val); ++ /* set operation */ ++ if (mask) { ++ if (val) ++ reg_val |= PCIE_CLKREQ_ENAB; ++ else ++ reg_val &= ~PCIE_CLKREQ_ENAB; ++ pci_write_config_dword(pi->dev, offset, reg_val); ++ pci_read_config_dword(pi->dev, offset, ®_val); ++ } ++ if (reg_val & PCIE_CLKREQ_ENAB) ++ return 1; ++ else ++ return 0; ++} ++ ++static void pcie_extendL1timer(struct pcicore_info *pi, bool extend) ++{ ++ u32 w; ++ struct si_pub *sih = pi->sih; ++ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; ++ ++ if (sih->buscoretype != PCIE_CORE_ID || sih->buscorerev < 7) ++ return; ++ ++ w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); ++ if (extend) ++ w |= PCIE_ASPMTIMER_EXTEND; ++ else ++ w &= ~PCIE_ASPMTIMER_EXTEND; ++ pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w); ++ w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); ++} ++ ++/* centralized clkreq control policy */ ++static void pcie_clkreq_upd(struct pcicore_info *pi, uint state) ++{ ++ struct si_pub *sih = pi->sih; ++ ++ switch (state) { ++ case SI_DOATTACH: ++ if (PCIE_ASPM(sih)) ++ pcie_clkreq(pi, 1, 0); ++ break; ++ case SI_PCIDOWN: ++ if (sih->buscorerev == 6) { /* turn on serdes PLL down */ ++ ai_corereg(sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_addr), ++ ~0, 0); ++ ai_corereg(sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_data), ++ ~0x40, 0); ++ } else if (pi->pcie_pr42767) { ++ pcie_clkreq(pi, 1, 1); ++ } ++ break; ++ case SI_PCIUP: ++ if (sih->buscorerev == 6) { /* turn off serdes PLL down */ ++ ai_corereg(sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_addr), ++ ~0, 0); ++ ai_corereg(sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_data), ++ ~0x40, 0x40); ++ } else if (PCIE_ASPM(sih)) { /* disable clkreq */ ++ pcie_clkreq(pi, 1, 0); ++ } ++ break; ++ } ++} ++ ++/* ***** PCI core WARs ***** */ ++/* Done only once at attach time */ ++static void pcie_war_polarity(struct pcicore_info *pi) ++{ ++ u32 w; ++ ++ if (pi->pcie_polarity != 0) ++ return; ++ ++ w = pcie_readreg(pi->regs.pcieregs, PCIE_PCIEREGS, PCIE_PLP_STATUSREG); ++ ++ /* Detect the current polarity at attach and force that polarity and ++ * disable changing the polarity ++ */ ++ if ((w & PCIE_PLP_POLARITYINV_STAT) == 0) ++ pi->pcie_polarity = SERDES_RX_CTRL_FORCE; ++ else ++ pi->pcie_polarity = (SERDES_RX_CTRL_FORCE | ++ SERDES_RX_CTRL_POLARITY); ++} ++ ++/* enable ASPM and CLKREQ if srom doesn't have it */ ++/* Needs to happen when update to shadow SROM is needed ++ * : Coming out of 'standby'/'hibernate' ++ * : If pcie_war_aspm_ovr state changed ++ */ ++static void pcie_war_aspm_clkreq(struct pcicore_info *pi) ++{ ++ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; ++ struct si_pub *sih = pi->sih; ++ u16 val16; ++ u16 __iomem *reg16; ++ u32 w; ++ ++ if (!PCIE_ASPM(sih)) ++ return; ++ ++ /* bypass this on QT or VSIM */ ++ reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET]; ++ val16 = R_REG(reg16); ++ ++ val16 &= ~SRSH_ASPM_ENB; ++ if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB) ++ val16 |= SRSH_ASPM_ENB; ++ else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L1_ENAB) ++ val16 |= SRSH_ASPM_L1_ENB; ++ else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB) ++ val16 |= SRSH_ASPM_L0s_ENB; ++ ++ W_REG(reg16, val16); ++ ++ pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w); ++ w &= ~PCIE_ASPM_ENAB; ++ w |= pi->pcie_war_aspm_ovr; ++ pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w); ++ ++ reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET_REV5]; ++ val16 = R_REG(reg16); ++ ++ if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) { ++ val16 |= SRSH_CLKREQ_ENB; ++ pi->pcie_pr42767 = true; ++ } else ++ val16 &= ~SRSH_CLKREQ_ENB; ++ ++ W_REG(reg16, val16); ++} ++ ++/* Apply the polarity determined at the start */ ++/* Needs to happen when coming out of 'standby'/'hibernate' */ ++static void pcie_war_serdes(struct pcicore_info *pi) ++{ ++ u32 w = 0; ++ ++ if (pi->pcie_polarity != 0) ++ pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CTRL, ++ pi->pcie_polarity); ++ ++ pcie_mdioread(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w); ++ if (w & PLL_CTRL_FREQDET_EN) { ++ w &= ~PLL_CTRL_FREQDET_EN; ++ pcie_mdiowrite(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w); ++ } ++} ++ ++/* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */ ++/* Needs to happen when coming out of 'standby'/'hibernate' */ ++static void pcie_misc_config_fixup(struct pcicore_info *pi) ++{ ++ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; ++ u16 val16; ++ u16 __iomem *reg16; ++ ++ reg16 = &pcieregs->sprom[SRSH_PCIE_MISC_CONFIG]; ++ val16 = R_REG(reg16); ++ ++ if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) { ++ val16 |= SRSH_L23READY_EXIT_NOPERST; ++ W_REG(reg16, val16); ++ } ++} ++ ++/* quick hack for testing */ ++/* Needs to happen when coming out of 'standby'/'hibernate' */ ++static void pcie_war_noplldown(struct pcicore_info *pi) ++{ ++ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; ++ u16 __iomem *reg16; ++ ++ /* turn off serdes PLL down */ ++ ai_corereg(pi->sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol), ++ CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN); ++ ++ /* clear srom shadow backdoor */ ++ reg16 = &pcieregs->sprom[SRSH_BD_OFFSET]; ++ W_REG(reg16, 0); ++} ++ ++/* Needs to happen when coming out of 'standby'/'hibernate' */ ++static void pcie_war_pci_setup(struct pcicore_info *pi) ++{ ++ struct si_pub *sih = pi->sih; ++ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; ++ u32 w; ++ ++ if (sih->buscorerev == 0 || sih->buscorerev == 1) { ++ w = pcie_readreg(pcieregs, PCIE_PCIEREGS, ++ PCIE_TLP_WORKAROUNDSREG); ++ w |= 0x8; ++ pcie_writereg(pcieregs, PCIE_PCIEREGS, ++ PCIE_TLP_WORKAROUNDSREG, w); ++ } ++ ++ if (sih->buscorerev == 1) { ++ w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG); ++ w |= 0x40; ++ pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w); ++ } ++ ++ if (sih->buscorerev == 0) { ++ pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128); ++ pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100); ++ pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466); ++ } else if (PCIE_ASPM(sih)) { ++ /* Change the L1 threshold for better performance */ ++ w = pcie_readreg(pcieregs, PCIE_PCIEREGS, ++ PCIE_DLLP_PMTHRESHREG); ++ w &= ~PCIE_L1THRESHOLDTIME_MASK; ++ w |= PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT; ++ pcie_writereg(pcieregs, PCIE_PCIEREGS, ++ PCIE_DLLP_PMTHRESHREG, w); ++ ++ pcie_war_serdes(pi); ++ ++ pcie_war_aspm_clkreq(pi); ++ } else if (pi->sih->buscorerev == 7) ++ pcie_war_noplldown(pi); ++ ++ /* Note that the fix is actually in the SROM, ++ * that's why this is open-ended ++ */ ++ if (pi->sih->buscorerev >= 6) ++ pcie_misc_config_fixup(pi); ++} ++ ++/* ***** Functions called during driver state changes ***** */ ++void pcicore_attach(struct pcicore_info *pi, int state) ++{ ++ struct si_pub *sih = pi->sih; ++ u32 bfl2 = (u32)getintvar(sih, BRCMS_SROM_BOARDFLAGS2); ++ ++ /* Determine if this board needs override */ ++ if (PCIE_ASPM(sih)) { ++ if (bfl2 & BFL2_PCIEWAR_OVR) ++ pi->pcie_war_aspm_ovr = PCIE_ASPM_DISAB; ++ else ++ pi->pcie_war_aspm_ovr = PCIE_ASPM_ENAB; ++ } ++ ++ /* These need to happen in this order only */ ++ pcie_war_polarity(pi); ++ ++ pcie_war_serdes(pi); ++ ++ pcie_war_aspm_clkreq(pi); ++ ++ pcie_clkreq_upd(pi, state); ++ ++} ++ ++void pcicore_hwup(struct pcicore_info *pi) ++{ ++ if (!pi || pi->sih->buscoretype != PCIE_CORE_ID) ++ return; ++ ++ pcie_war_pci_setup(pi); ++} ++ ++void pcicore_up(struct pcicore_info *pi, int state) ++{ ++ if (!pi || pi->sih->buscoretype != PCIE_CORE_ID) ++ return; ++ ++ /* Restore L1 timer for better performance */ ++ pcie_extendL1timer(pi, true); ++ ++ pcie_clkreq_upd(pi, state); ++} ++ ++/* When the device is going to enter D3 state ++ * (or the system is going to enter S3/S4 states) ++ */ ++void pcicore_sleep(struct pcicore_info *pi) ++{ ++ u32 w; ++ ++ if (!pi || !PCIE_ASPM(pi->sih)) ++ return; ++ ++ pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w); ++ w &= ~PCIE_CAP_LCREG_ASPML1; ++ pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w); ++ ++ pi->pcie_pr42767 = false; ++} ++ ++void pcicore_down(struct pcicore_info *pi, int state) ++{ ++ if (!pi || pi->sih->buscoretype != PCIE_CORE_ID) ++ return; ++ ++ pcie_clkreq_upd(pi, state); ++ ++ /* Reduce L1 timer for better power savings */ ++ pcie_extendL1timer(pi, false); ++} ++ ++/* precondition: current core is sii->buscoretype */ ++static void pcicore_fixcfg(struct pcicore_info *pi, u16 __iomem *reg16) ++{ ++ struct si_info *sii = (struct si_info *)(pi->sih); ++ u16 val16; ++ uint pciidx; ++ ++ pciidx = ai_coreidx(&sii->pub); ++ val16 = R_REG(reg16); ++ if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16)pciidx) { ++ val16 = (u16)(pciidx << SRSH_PI_SHIFT) | ++ (val16 & ~SRSH_PI_MASK); ++ W_REG(reg16, val16); ++ } ++} ++ ++void ++pcicore_fixcfg_pci(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs) ++{ ++ pcicore_fixcfg(pi, &pciregs->sprom[SRSH_PI_OFFSET]); ++} ++ ++void pcicore_fixcfg_pcie(struct pcicore_info *pi, ++ struct sbpcieregs __iomem *pcieregs) ++{ ++ pcicore_fixcfg(pi, &pcieregs->sprom[SRSH_PI_OFFSET]); ++} ++ ++/* precondition: current core is pci core */ ++void ++pcicore_pci_setup(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs) ++{ ++ u32 w; ++ ++ OR_REG(&pciregs->sbtopci2, SBTOPCI_PREF | SBTOPCI_BURST); ++ ++ if (((struct si_info *)(pi->sih))->pub.buscorerev >= 11) { ++ OR_REG(&pciregs->sbtopci2, SBTOPCI_RC_READMULTI); ++ w = R_REG(&pciregs->clkrun); ++ W_REG(&pciregs->clkrun, w | PCI_CLKRUN_DSBL); ++ w = R_REG(&pciregs->clkrun); ++ } ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h.orig 2011-11-09 13:46:58.252800545 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h 2011-11-09 13:47:17.005566104 -0500 +@@ -0,0 +1,82 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_NICPCI_H_ ++#define _BRCM_NICPCI_H_ ++ ++#include "types.h" ++ ++/* PCI configuration address space size */ ++#define PCI_SZPCR 256 ++ ++/* Brcm PCI configuration registers */ ++/* backplane address space accessed by BAR0 */ ++#define PCI_BAR0_WIN 0x80 ++/* sprom property control */ ++#define PCI_SPROM_CONTROL 0x88 ++/* mask of PCI and other cores interrupts */ ++#define PCI_INT_MASK 0x94 ++/* backplane core interrupt mask bits offset */ ++#define PCI_SBIM_SHIFT 8 ++/* backplane address space accessed by second 4KB of BAR0 */ ++#define PCI_BAR0_WIN2 0xac ++/* pci config space gpio input (>=rev3) */ ++#define PCI_GPIO_IN 0xb0 ++/* pci config space gpio output (>=rev3) */ ++#define PCI_GPIO_OUT 0xb4 ++/* pci config space gpio output enable (>=rev3) */ ++#define PCI_GPIO_OUTEN 0xb8 ++ ++/* bar0 + 4K accesses external sprom */ ++#define PCI_BAR0_SPROM_OFFSET (4 * 1024) ++/* bar0 + 6K accesses pci core registers */ ++#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) ++/* ++ * pci core SB registers are at the end of the ++ * 8KB window, so their address is the "regular" ++ * address plus 4K ++ */ ++#define PCI_BAR0_PCISBR_OFFSET (4 * 1024) ++/* bar0 window size Match with corerev 13 */ ++#define PCI_BAR0_WINSZ (16 * 1024) ++/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */ ++/* bar0 + 8K accesses pci/pcie core registers */ ++#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024) ++/* bar0 + 12K accesses chipc core registers */ ++#define PCI_16KB0_CCREGS_OFFSET (12 * 1024) ++ ++struct sbpciregs; ++struct sbpcieregs; ++ ++extern struct pcicore_info *pcicore_init(struct si_pub *sih, ++ struct pci_dev *pdev, ++ void __iomem *regs); ++extern void pcicore_deinit(struct pcicore_info *pch); ++extern void pcicore_attach(struct pcicore_info *pch, int state); ++extern void pcicore_hwup(struct pcicore_info *pch); ++extern void pcicore_up(struct pcicore_info *pch, int state); ++extern void pcicore_sleep(struct pcicore_info *pch); ++extern void pcicore_down(struct pcicore_info *pch, int state); ++extern u8 pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id, ++ unsigned char *buf, u32 *buflen); ++extern void pcicore_fixcfg_pci(struct pcicore_info *pch, ++ struct sbpciregs __iomem *pciregs); ++extern void pcicore_fixcfg_pcie(struct pcicore_info *pch, ++ struct sbpcieregs __iomem *pciregs); ++extern void pcicore_pci_setup(struct pcicore_info *pch, ++ struct sbpciregs __iomem *pciregs); ++ ++#endif /* _BRCM_NICPCI_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.c.orig 2011-11-09 13:46:58.252800545 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.c 2011-11-09 13:47:17.006566092 -0500 +@@ -0,0 +1,426 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include "aiutils.h" ++#include "otp.h" ++ ++#define OTPS_GUP_MASK 0x00000f00 ++#define OTPS_GUP_SHIFT 8 ++/* h/w subregion is programmed */ ++#define OTPS_GUP_HW 0x00000100 ++/* s/w subregion is programmed */ ++#define OTPS_GUP_SW 0x00000200 ++/* chipid/pkgopt subregion is programmed */ ++#define OTPS_GUP_CI 0x00000400 ++/* fuse subregion is programmed */ ++#define OTPS_GUP_FUSE 0x00000800 ++ ++/* Fields in otpprog in rev >= 21 */ ++#define OTPP_COL_MASK 0x000000ff ++#define OTPP_COL_SHIFT 0 ++#define OTPP_ROW_MASK 0x0000ff00 ++#define OTPP_ROW_SHIFT 8 ++#define OTPP_OC_MASK 0x0f000000 ++#define OTPP_OC_SHIFT 24 ++#define OTPP_READERR 0x10000000 ++#define OTPP_VALUE_MASK 0x20000000 ++#define OTPP_VALUE_SHIFT 29 ++#define OTPP_START_BUSY 0x80000000 ++#define OTPP_READ 0x40000000 ++ ++/* Opcodes for OTPP_OC field */ ++#define OTPPOC_READ 0 ++#define OTPPOC_BIT_PROG 1 ++#define OTPPOC_VERIFY 3 ++#define OTPPOC_INIT 4 ++#define OTPPOC_SET 5 ++#define OTPPOC_RESET 6 ++#define OTPPOC_OCST 7 ++#define OTPPOC_ROW_LOCK 8 ++#define OTPPOC_PRESCN_TEST 9 ++ ++#define OTPTYPE_IPX(ccrev) ((ccrev) == 21 || (ccrev) >= 23) ++ ++#define OTPP_TRIES 10000000 /* # of tries for OTPP */ ++ ++#define MAXNUMRDES 9 /* Maximum OTP redundancy entries */ ++ ++/* Fixed size subregions sizes in words */ ++#define OTPGU_CI_SZ 2 ++ ++struct otpinfo; ++ ++/* OTP function struct */ ++struct otp_fn_s { ++ int (*init)(struct si_pub *sih, struct otpinfo *oi); ++ int (*read_region)(struct otpinfo *oi, int region, u16 *data, ++ uint *wlen); ++}; ++ ++struct otpinfo { ++ uint ccrev; /* chipc revision */ ++ const struct otp_fn_s *fn; /* OTP functions */ ++ struct si_pub *sih; /* Saved sb handle */ ++ ++ /* IPX OTP section */ ++ u16 wsize; /* Size of otp in words */ ++ u16 rows; /* Geometry */ ++ u16 cols; /* Geometry */ ++ u32 status; /* Flag bits (lock/prog/rv). ++ * (Reflected only when OTP is power cycled) ++ */ ++ u16 hwbase; /* hardware subregion offset */ ++ u16 hwlim; /* hardware subregion boundary */ ++ u16 swbase; /* software subregion offset */ ++ u16 swlim; /* software subregion boundary */ ++ u16 fbase; /* fuse subregion offset */ ++ u16 flim; /* fuse subregion boundary */ ++ int otpgu_base; /* offset to General Use Region */ ++}; ++ ++/* OTP layout */ ++/* CC revs 21, 24 and 27 OTP General Use Region word offset */ ++#define REVA4_OTPGU_BASE 12 ++ ++/* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */ ++#define REVB8_OTPGU_BASE 20 ++ ++/* CC rev 36 OTP General Use Region word offset */ ++#define REV36_OTPGU_BASE 12 ++ ++/* Subregion word offsets in General Use region */ ++#define OTPGU_HSB_OFF 0 ++#define OTPGU_SFB_OFF 1 ++#define OTPGU_CI_OFF 2 ++#define OTPGU_P_OFF 3 ++#define OTPGU_SROM_OFF 4 ++ ++/* Flag bit offsets in General Use region */ ++#define OTPGU_HWP_OFF 60 ++#define OTPGU_SWP_OFF 61 ++#define OTPGU_CIP_OFF 62 ++#define OTPGU_FUSEP_OFF 63 ++#define OTPGU_CIP_MSK 0x4000 ++#define OTPGU_P_MSK 0xf000 ++#define OTPGU_P_SHIFT (OTPGU_HWP_OFF % 16) ++ ++/* OTP Size */ ++#define OTP_SZ_FU_324 ((roundup(324, 8))/8) /* 324 bits */ ++#define OTP_SZ_FU_288 (288/8) /* 288 bits */ ++#define OTP_SZ_FU_216 (216/8) /* 216 bits */ ++#define OTP_SZ_FU_72 (72/8) /* 72 bits */ ++#define OTP_SZ_CHECKSUM (16/8) /* 16 bits */ ++#define OTP4315_SWREG_SZ 178 /* 178 bytes */ ++#define OTP_SZ_FU_144 (144/8) /* 144 bits */ ++ ++static u16 ++ipxotp_otpr(struct otpinfo *oi, struct chipcregs __iomem *cc, uint wn) ++{ ++ return R_REG(&cc->sromotp[wn]); ++} ++ ++/* ++ * Calculate max HW/SW region byte size by subtracting fuse region ++ * and checksum size, osizew is oi->wsize (OTP size - GU size) in words ++ */ ++static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew) ++{ ++ int ret = 0; ++ ++ switch (sih->chip) { ++ case BCM43224_CHIP_ID: ++ case BCM43225_CHIP_ID: ++ ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM; ++ break; ++ case BCM4313_CHIP_ID: ++ ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM; ++ break; ++ default: ++ break; /* Don't know about this chip */ ++ } ++ ++ return ret; ++} ++ ++static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc) ++{ ++ uint k; ++ u32 otpp, st; ++ ++ /* ++ * record word offset of General Use Region ++ * for various chipcommon revs ++ */ ++ if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24 ++ || oi->sih->ccrev == 27) { ++ oi->otpgu_base = REVA4_OTPGU_BASE; ++ } else if (oi->sih->ccrev == 36) { ++ /* ++ * OTP size greater than equal to 2KB (128 words), ++ * otpgu_base is similar to rev23 ++ */ ++ if (oi->wsize >= 128) ++ oi->otpgu_base = REVB8_OTPGU_BASE; ++ else ++ oi->otpgu_base = REV36_OTPGU_BASE; ++ } else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) { ++ oi->otpgu_base = REVB8_OTPGU_BASE; ++ } ++ ++ /* First issue an init command so the status is up to date */ ++ otpp = ++ OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK); ++ ++ W_REG(&cc->otpprog, otpp); ++ for (k = 0; ++ ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY) ++ && (k < OTPP_TRIES); k++) ++ ; ++ if (k >= OTPP_TRIES) ++ return; ++ ++ /* Read OTP lock bits and subregion programmed indication bits */ ++ oi->status = R_REG(&cc->otpstatus); ++ ++ if ((oi->sih->chip == BCM43224_CHIP_ID) ++ || (oi->sih->chip == BCM43225_CHIP_ID)) { ++ u32 p_bits; ++ p_bits = ++ (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) & ++ OTPGU_P_MSK) ++ >> OTPGU_P_SHIFT; ++ oi->status |= (p_bits << OTPS_GUP_SHIFT); ++ } ++ ++ /* ++ * h/w region base and fuse region limit are fixed to ++ * the top and the bottom of the general use region. ++ * Everything else can be flexible. ++ */ ++ oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF; ++ oi->hwlim = oi->wsize; ++ if (oi->status & OTPS_GUP_HW) { ++ oi->hwlim = ++ ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16; ++ oi->swbase = oi->hwlim; ++ } else ++ oi->swbase = oi->hwbase; ++ ++ /* subtract fuse and checksum from beginning */ ++ oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2; ++ ++ if (oi->status & OTPS_GUP_SW) { ++ oi->swlim = ++ ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16; ++ oi->fbase = oi->swlim; ++ } else ++ oi->fbase = oi->swbase; ++ ++ oi->flim = oi->wsize; ++} ++ ++static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi) ++{ ++ uint idx; ++ struct chipcregs __iomem *cc; ++ ++ /* Make sure we're running IPX OTP */ ++ if (!OTPTYPE_IPX(sih->ccrev)) ++ return -EBADE; ++ ++ /* Make sure OTP is not disabled */ ++ if (ai_is_otp_disabled(sih)) ++ return -EBADE; ++ ++ /* Check for otp size */ ++ switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) { ++ case 0: ++ /* Nothing there */ ++ return -EBADE; ++ case 1: /* 32x64 */ ++ oi->rows = 32; ++ oi->cols = 64; ++ oi->wsize = 128; ++ break; ++ case 2: /* 64x64 */ ++ oi->rows = 64; ++ oi->cols = 64; ++ oi->wsize = 256; ++ break; ++ case 5: /* 96x64 */ ++ oi->rows = 96; ++ oi->cols = 64; ++ oi->wsize = 384; ++ break; ++ case 7: /* 16x64 *//* 1024 bits */ ++ oi->rows = 16; ++ oi->cols = 64; ++ oi->wsize = 64; ++ break; ++ default: ++ /* Don't know the geometry */ ++ return -EBADE; ++ } ++ ++ /* Retrieve OTP region info */ ++ idx = ai_coreidx(sih); ++ cc = ai_setcoreidx(sih, SI_CC_IDX); ++ ++ _ipxotp_init(oi, cc); ++ ++ ai_setcoreidx(sih, idx); ++ ++ return 0; ++} ++ ++static int ++ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen) ++{ ++ uint idx; ++ struct chipcregs __iomem *cc; ++ uint base, i, sz; ++ ++ /* Validate region selection */ ++ switch (region) { ++ case OTP_HW_RGN: ++ sz = (uint) oi->hwlim - oi->hwbase; ++ if (!(oi->status & OTPS_GUP_HW)) { ++ *wlen = sz; ++ return -ENODATA; ++ } ++ if (*wlen < sz) { ++ *wlen = sz; ++ return -EOVERFLOW; ++ } ++ base = oi->hwbase; ++ break; ++ case OTP_SW_RGN: ++ sz = ((uint) oi->swlim - oi->swbase); ++ if (!(oi->status & OTPS_GUP_SW)) { ++ *wlen = sz; ++ return -ENODATA; ++ } ++ if (*wlen < sz) { ++ *wlen = sz; ++ return -EOVERFLOW; ++ } ++ base = oi->swbase; ++ break; ++ case OTP_CI_RGN: ++ sz = OTPGU_CI_SZ; ++ if (!(oi->status & OTPS_GUP_CI)) { ++ *wlen = sz; ++ return -ENODATA; ++ } ++ if (*wlen < sz) { ++ *wlen = sz; ++ return -EOVERFLOW; ++ } ++ base = oi->otpgu_base + OTPGU_CI_OFF; ++ break; ++ case OTP_FUSE_RGN: ++ sz = (uint) oi->flim - oi->fbase; ++ if (!(oi->status & OTPS_GUP_FUSE)) { ++ *wlen = sz; ++ return -ENODATA; ++ } ++ if (*wlen < sz) { ++ *wlen = sz; ++ return -EOVERFLOW; ++ } ++ base = oi->fbase; ++ break; ++ case OTP_ALL_RGN: ++ sz = ((uint) oi->flim - oi->hwbase); ++ if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) { ++ *wlen = sz; ++ return -ENODATA; ++ } ++ if (*wlen < sz) { ++ *wlen = sz; ++ return -EOVERFLOW; ++ } ++ base = oi->hwbase; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ idx = ai_coreidx(oi->sih); ++ cc = ai_setcoreidx(oi->sih, SI_CC_IDX); ++ ++ /* Read the data */ ++ for (i = 0; i < sz; i++) ++ data[i] = ipxotp_otpr(oi, cc, base + i); ++ ++ ai_setcoreidx(oi->sih, idx); ++ *wlen = sz; ++ return 0; ++} ++ ++static const struct otp_fn_s ipxotp_fn = { ++ (int (*)(struct si_pub *, struct otpinfo *)) ipxotp_init, ++ (int (*)(struct otpinfo *, int, u16 *, uint *)) ipxotp_read_region, ++}; ++ ++static int otp_init(struct si_pub *sih, struct otpinfo *oi) ++{ ++ ++ int ret; ++ ++ memset(oi, 0, sizeof(struct otpinfo)); ++ ++ oi->ccrev = sih->ccrev; ++ ++ if (OTPTYPE_IPX(oi->ccrev)) ++ oi->fn = &ipxotp_fn; ++ ++ if (oi->fn == NULL) ++ return -EBADE; ++ ++ oi->sih = sih; ++ ++ ret = (oi->fn->init) (sih, oi); ++ ++ return ret; ++} ++ ++int ++otp_read_region(struct si_pub *sih, int region, u16 *data, uint *wlen) { ++ struct otpinfo otpinfo; ++ struct otpinfo *oi = &otpinfo; ++ int err = 0; ++ ++ if (ai_is_otp_disabled(sih)) { ++ err = -EPERM; ++ goto out; ++ } ++ ++ err = otp_init(sih, oi); ++ if (err) ++ goto out; ++ ++ err = ((oi)->fn->read_region)(oi, region, data, wlen); ++ ++ out: ++ return err; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.h.orig 2011-11-09 13:46:58.252800545 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.h 2011-11-09 13:47:17.006566092 -0500 +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_OTP_H_ ++#define _BRCM_OTP_H_ ++ ++#include "types.h" ++ ++/* OTP regions */ ++#define OTP_HW_RGN 1 ++#define OTP_SW_RGN 2 ++#define OTP_CI_RGN 4 ++#define OTP_FUSE_RGN 8 ++/* From h/w region to end of OTP including checksum */ ++#define OTP_ALL_RGN 0xf ++ ++/* OTP Size */ ++#define OTP_SZ_MAX (6144/8) /* maximum bytes in one CIS */ ++ ++extern int otp_read_region(struct si_pub *sih, int region, u16 *data, ++ uint *wlen); ++ ++#endif /* _BRCM_OTP_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c.orig 2011-11-09 13:46:58.254800521 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c 2011-11-09 13:47:17.008566067 -0500 +@@ -0,0 +1,2988 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include "phy_hal.h" ++#include "phy_int.h" ++#include "phy_radio.h" ++#include "phy_lcn.h" ++#include "phyreg_n.h" ++ ++#define VALID_N_RADIO(radioid) ((radioid == BCM2055_ID) || \ ++ (radioid == BCM2056_ID) || \ ++ (radioid == BCM2057_ID)) ++ ++#define VALID_LCN_RADIO(radioid) (radioid == BCM2064_ID) ++ ++#define VALID_RADIO(pi, radioid) ( \ ++ (ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \ ++ (ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false)) ++ ++/* basic mux operation - can be optimized on several architectures */ ++#define MUX(pred, true, false) ((pred) ? (true) : (false)) ++ ++/* modulo inc/dec - assumes x E [0, bound - 1] */ ++#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1) ++ ++/* modulo inc/dec, bound = 2^k */ ++#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1)) ++#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1)) ++ ++struct chan_info_basic { ++ u16 chan; ++ u16 freq; ++}; ++ ++static const struct chan_info_basic chan_info_all[] = { ++ {1, 2412}, ++ {2, 2417}, ++ {3, 2422}, ++ {4, 2427}, ++ {5, 2432}, ++ {6, 2437}, ++ {7, 2442}, ++ {8, 2447}, ++ {9, 2452}, ++ {10, 2457}, ++ {11, 2462}, ++ {12, 2467}, ++ {13, 2472}, ++ {14, 2484}, ++ ++ {34, 5170}, ++ {38, 5190}, ++ {42, 5210}, ++ {46, 5230}, ++ ++ {36, 5180}, ++ {40, 5200}, ++ {44, 5220}, ++ {48, 5240}, ++ {52, 5260}, ++ {56, 5280}, ++ {60, 5300}, ++ {64, 5320}, ++ ++ {100, 5500}, ++ {104, 5520}, ++ {108, 5540}, ++ {112, 5560}, ++ {116, 5580}, ++ {120, 5600}, ++ {124, 5620}, ++ {128, 5640}, ++ {132, 5660}, ++ {136, 5680}, ++ {140, 5700}, ++ ++ {149, 5745}, ++ {153, 5765}, ++ {157, 5785}, ++ {161, 5805}, ++ {165, 5825}, ++ ++ {184, 4920}, ++ {188, 4940}, ++ {192, 4960}, ++ {196, 4980}, ++ {200, 5000}, ++ {204, 5020}, ++ {208, 5040}, ++ {212, 5060}, ++ {216, 50800} ++}; ++ ++const u8 ofdm_rate_lookup[] = { ++ ++ BRCM_RATE_48M, ++ BRCM_RATE_24M, ++ BRCM_RATE_12M, ++ BRCM_RATE_6M, ++ BRCM_RATE_54M, ++ BRCM_RATE_36M, ++ BRCM_RATE_18M, ++ BRCM_RATE_9M ++}; ++ ++#define PHY_WREG_LIMIT 24 ++ ++void wlc_phyreg_enter(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ wlapi_bmac_ucode_wake_override_phyreg_set(pi->sh->physhim); ++} ++ ++void wlc_phyreg_exit(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ wlapi_bmac_ucode_wake_override_phyreg_clear(pi->sh->physhim); ++} ++ ++void wlc_radioreg_enter(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, MCTL_LOCK_RADIO); ++ ++ udelay(10); ++} ++ ++void wlc_radioreg_exit(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ u16 dummy; ++ ++ dummy = R_REG(&pi->regs->phyversion); ++ pi->phy_wreg = 0; ++ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, 0); ++} ++ ++u16 read_radio_reg(struct brcms_phy *pi, u16 addr) ++{ ++ u16 data; ++ ++ if ((addr == RADIO_IDCODE)) ++ return 0xffff; ++ ++ switch (pi->pubpi.phy_type) { ++ case PHY_TYPE_N: ++ if (!CONF_HAS(PHYTYPE, PHY_TYPE_N)) ++ break; ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ addr |= RADIO_2057_READ_OFF; ++ else ++ addr |= RADIO_2055_READ_OFF; ++ break; ++ ++ case PHY_TYPE_LCN: ++ if (!CONF_HAS(PHYTYPE, PHY_TYPE_LCN)) ++ break; ++ addr |= RADIO_2064_READ_OFF; ++ break; ++ ++ default: ++ break; ++ } ++ ++ if ((D11REV_GE(pi->sh->corerev, 24)) || ++ (D11REV_IS(pi->sh->corerev, 22) ++ && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { ++ W_REG_FLUSH(&pi->regs->radioregaddr, addr); ++ data = R_REG(&pi->regs->radioregdata); ++ } else { ++ W_REG_FLUSH(&pi->regs->phy4waddr, addr); ++ ++#ifdef __ARM_ARCH_4T__ ++ __asm__(" .align 4 "); ++ __asm__(" nop "); ++ data = R_REG(&pi->regs->phy4wdatalo); ++#else ++ data = R_REG(&pi->regs->phy4wdatalo); ++#endif ++ ++ } ++ pi->phy_wreg = 0; ++ ++ return data; ++} ++ ++void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) ++{ ++ if ((D11REV_GE(pi->sh->corerev, 24)) || ++ (D11REV_IS(pi->sh->corerev, 22) ++ && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { ++ ++ W_REG_FLUSH(&pi->regs->radioregaddr, addr); ++ W_REG(&pi->regs->radioregdata, val); ++ } else { ++ W_REG_FLUSH(&pi->regs->phy4waddr, addr); ++ W_REG(&pi->regs->phy4wdatalo, val); ++ } ++ ++ if (++pi->phy_wreg >= pi->phy_wreg_limit) { ++ (void)R_REG(&pi->regs->maccontrol); ++ pi->phy_wreg = 0; ++ } ++} ++ ++static u32 read_radio_id(struct brcms_phy *pi) ++{ ++ u32 id; ++ ++ if (D11REV_GE(pi->sh->corerev, 24)) { ++ u32 b0, b1, b2; ++ ++ W_REG_FLUSH(&pi->regs->radioregaddr, 0); ++ b0 = (u32) R_REG(&pi->regs->radioregdata); ++ W_REG_FLUSH(&pi->regs->radioregaddr, 1); ++ b1 = (u32) R_REG(&pi->regs->radioregdata); ++ W_REG_FLUSH(&pi->regs->radioregaddr, 2); ++ b2 = (u32) R_REG(&pi->regs->radioregdata); ++ ++ id = ((b0 & 0xf) << 28) | (((b2 << 8) | b1) << 12) | ((b0 >> 4) ++ & 0xf); ++ } else { ++ W_REG_FLUSH(&pi->regs->phy4waddr, RADIO_IDCODE); ++ id = (u32) R_REG(&pi->regs->phy4wdatalo); ++ id |= (u32) R_REG(&pi->regs->phy4wdatahi) << 16; ++ } ++ pi->phy_wreg = 0; ++ return id; ++} ++ ++void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) ++{ ++ u16 rval; ++ ++ rval = read_radio_reg(pi, addr); ++ write_radio_reg(pi, addr, (rval & val)); ++} ++ ++void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) ++{ ++ u16 rval; ++ ++ rval = read_radio_reg(pi, addr); ++ write_radio_reg(pi, addr, (rval | val)); ++} ++ ++void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask) ++{ ++ u16 rval; ++ ++ rval = read_radio_reg(pi, addr); ++ write_radio_reg(pi, addr, (rval ^ mask)); ++} ++ ++void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val) ++{ ++ u16 rval; ++ ++ rval = read_radio_reg(pi, addr); ++ write_radio_reg(pi, addr, (rval & ~mask) | (val & mask)); ++} ++ ++void write_phy_channel_reg(struct brcms_phy *pi, uint val) ++{ ++ W_REG(&pi->regs->phychannel, val); ++} ++ ++u16 read_phy_reg(struct brcms_phy *pi, u16 addr) ++{ ++ struct d11regs __iomem *regs; ++ ++ regs = pi->regs; ++ ++ W_REG_FLUSH(®s->phyregaddr, addr); ++ ++ pi->phy_wreg = 0; ++ return R_REG(®s->phyregdata); ++} ++ ++void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) ++{ ++ struct d11regs __iomem *regs; ++ ++ regs = pi->regs; ++ ++#ifdef CONFIG_BCM47XX ++ W_REG_FLUSH(®s->phyregaddr, addr); ++ W_REG(®s->phyregdata, val); ++ if (addr == 0x72) ++ (void)R_REG(®s->phyregdata); ++#else ++ W_REG((u32 __iomem *)(®s->phyregaddr), addr | (val << 16)); ++ if (++pi->phy_wreg >= pi->phy_wreg_limit) { ++ pi->phy_wreg = 0; ++ (void)R_REG(®s->phyversion); ++ } ++#endif ++} ++ ++void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) ++{ ++ struct d11regs __iomem *regs; ++ ++ regs = pi->regs; ++ ++ W_REG_FLUSH(®s->phyregaddr, addr); ++ ++ W_REG(®s->phyregdata, (R_REG(®s->phyregdata) & val)); ++ pi->phy_wreg = 0; ++} ++ ++void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) ++{ ++ struct d11regs __iomem *regs; ++ ++ regs = pi->regs; ++ ++ W_REG_FLUSH(®s->phyregaddr, addr); ++ ++ W_REG(®s->phyregdata, (R_REG(®s->phyregdata) | val)); ++ pi->phy_wreg = 0; ++} ++ ++void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val) ++{ ++ struct d11regs __iomem *regs; ++ ++ regs = pi->regs; ++ ++ W_REG_FLUSH(®s->phyregaddr, addr); ++ ++ W_REG(®s->phyregdata, ++ ((R_REG(®s->phyregdata) & ~mask) | (val & mask))); ++ pi->phy_wreg = 0; ++} ++ ++static void wlc_set_phy_uninitted(struct brcms_phy *pi) ++{ ++ int i, j; ++ ++ pi->initialized = false; ++ ++ pi->tx_vos = 0xffff; ++ pi->nrssi_table_delta = 0x7fffffff; ++ pi->rc_cal = 0xffff; ++ pi->mintxbias = 0xffff; ++ pi->txpwridx = -1; ++ if (ISNPHY(pi)) { ++ pi->phy_spuravoid = SPURAVOID_DISABLE; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) ++ && NREV_LT(pi->pubpi.phy_rev, 7)) ++ pi->phy_spuravoid = SPURAVOID_AUTO; ++ ++ pi->nphy_papd_skip = 0; ++ pi->nphy_papd_epsilon_offset[0] = 0xf588; ++ pi->nphy_papd_epsilon_offset[1] = 0xf588; ++ pi->nphy_txpwr_idx[0] = 128; ++ pi->nphy_txpwr_idx[1] = 128; ++ pi->nphy_txpwrindex[0].index_internal = 40; ++ pi->nphy_txpwrindex[1].index_internal = 40; ++ pi->phy_pabias = 0; ++ } else { ++ pi->phy_spuravoid = SPURAVOID_AUTO; ++ } ++ pi->radiopwr = 0xffff; ++ for (i = 0; i < STATIC_NUM_RF; i++) { ++ for (j = 0; j < STATIC_NUM_BB; j++) ++ pi->stats_11b_txpower[i][j] = -1; ++ } ++} ++ ++struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp) ++{ ++ struct shared_phy *sh; ++ ++ sh = kzalloc(sizeof(struct shared_phy), GFP_ATOMIC); ++ if (sh == NULL) ++ return NULL; ++ ++ sh->sih = shp->sih; ++ sh->physhim = shp->physhim; ++ sh->unit = shp->unit; ++ sh->corerev = shp->corerev; ++ ++ sh->vid = shp->vid; ++ sh->did = shp->did; ++ sh->chip = shp->chip; ++ sh->chiprev = shp->chiprev; ++ sh->chippkg = shp->chippkg; ++ sh->sromrev = shp->sromrev; ++ sh->boardtype = shp->boardtype; ++ sh->boardrev = shp->boardrev; ++ sh->boardvendor = shp->boardvendor; ++ sh->boardflags = shp->boardflags; ++ sh->boardflags2 = shp->boardflags2; ++ sh->buscorerev = shp->buscorerev; ++ ++ sh->fast_timer = PHY_SW_TIMER_FAST; ++ sh->slow_timer = PHY_SW_TIMER_SLOW; ++ sh->glacial_timer = PHY_SW_TIMER_GLACIAL; ++ ++ sh->rssi_mode = RSSI_ANT_MERGE_MAX; ++ ++ return sh; ++} ++ ++static void wlc_phy_timercb_phycal(struct brcms_phy *pi) ++{ ++ uint delay = 5; ++ ++ if (PHY_PERICAL_MPHASE_PENDING(pi)) { ++ if (!pi->sh->up) { ++ wlc_phy_cal_perical_mphase_reset(pi); ++ return; ++ } ++ ++ if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)) { ++ ++ delay = 1000; ++ wlc_phy_cal_perical_mphase_restart(pi); ++ } else ++ wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO); ++ wlapi_add_timer(pi->phycal_timer, delay, 0); ++ return; ++ } ++ ++} ++ ++static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi) ++{ ++ u32 ver; ++ ++ ver = read_radio_id(pi); ++ ++ return ver; ++} ++ ++struct brcms_phy_pub * ++wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs, ++ int bandtype, struct wiphy *wiphy) ++{ ++ struct brcms_phy *pi; ++ u32 sflags = 0; ++ uint phyversion; ++ u32 idcode; ++ int i; ++ ++ if (D11REV_IS(sh->corerev, 4)) ++ sflags = SISF_2G_PHY | SISF_5G_PHY; ++ else ++ sflags = ai_core_sflags(sh->sih, 0, 0); ++ ++ if (bandtype == BRCM_BAND_5G) { ++ if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0) ++ return NULL; ++ } ++ ++ pi = sh->phy_head; ++ if ((sflags & SISF_DB_PHY) && pi) { ++ wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags); ++ pi->refcnt++; ++ return &pi->pubpi_ro; ++ } ++ ++ pi = kzalloc(sizeof(struct brcms_phy), GFP_ATOMIC); ++ if (pi == NULL) ++ return NULL; ++ pi->wiphy = wiphy; ++ pi->regs = regs; ++ pi->sh = sh; ++ pi->phy_init_por = true; ++ pi->phy_wreg_limit = PHY_WREG_LIMIT; ++ ++ pi->txpwr_percent = 100; ++ ++ pi->do_initcal = true; ++ ++ pi->phycal_tempdelta = 0; ++ ++ if (bandtype == BRCM_BAND_2G && (sflags & SISF_2G_PHY)) ++ pi->pubpi.coreflags = SICF_GMODE; ++ ++ wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags); ++ phyversion = R_REG(&pi->regs->phyversion); ++ ++ pi->pubpi.phy_type = PHY_TYPE(phyversion); ++ pi->pubpi.phy_rev = phyversion & PV_PV_MASK; ++ ++ if (pi->pubpi.phy_type == PHY_TYPE_LCNXN) { ++ pi->pubpi.phy_type = PHY_TYPE_N; ++ pi->pubpi.phy_rev += LCNXN_BASEREV; ++ } ++ pi->pubpi.phy_corenum = PHY_CORE_NUM_2; ++ pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT; ++ ++ if (!pi->pubpi.phy_type == PHY_TYPE_N && ++ !pi->pubpi.phy_type == PHY_TYPE_LCN) ++ goto err; ++ ++ if (bandtype == BRCM_BAND_5G) { ++ if (!ISNPHY(pi)) ++ goto err; ++ } else if (!ISNPHY(pi) && !ISLCNPHY(pi)) { ++ goto err; ++ } ++ ++ wlc_phy_anacore((struct brcms_phy_pub *) pi, ON); ++ ++ idcode = wlc_phy_get_radio_ver(pi); ++ pi->pubpi.radioid = ++ (idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT; ++ pi->pubpi.radiorev = ++ (idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT; ++ pi->pubpi.radiover = ++ (idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT; ++ if (!VALID_RADIO(pi, pi->pubpi.radioid)) ++ goto err; ++ ++ wlc_phy_switch_radio((struct brcms_phy_pub *) pi, OFF); ++ ++ wlc_set_phy_uninitted(pi); ++ ++ pi->bw = WL_CHANSPEC_BW_20; ++ pi->radio_chanspec = (bandtype == BRCM_BAND_2G) ? ++ ch20mhz_chspec(1) : ch20mhz_chspec(36); ++ ++ pi->rxiq_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY; ++ pi->rxiq_antsel = ANT_RX_DIV_DEF; ++ ++ pi->watchdog_override = true; ++ ++ pi->cal_type_override = PHY_PERICAL_AUTO; ++ ++ pi->nphy_saved_noisevars.bufcount = 0; ++ ++ if (ISNPHY(pi)) ++ pi->min_txpower = PHY_TXPWR_MIN_NPHY; ++ else ++ pi->min_txpower = PHY_TXPWR_MIN; ++ ++ pi->sh->phyrxchain = 0x3; ++ ++ pi->rx2tx_biasentry = -1; ++ ++ pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP; ++ pi->phy_txcore_enable_temp = ++ PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP; ++ pi->phy_tempsense_offset = 0; ++ pi->phy_txcore_heatedup = false; ++ ++ pi->nphy_lastcal_temp = -50; ++ ++ pi->phynoise_polling = true; ++ if (ISNPHY(pi) || ISLCNPHY(pi)) ++ pi->phynoise_polling = false; ++ ++ for (i = 0; i < TXP_NUM_RATES; i++) { ++ pi->txpwr_limit[i] = BRCMS_TXPWR_MAX; ++ pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX; ++ pi->tx_user_target[i] = BRCMS_TXPWR_MAX; ++ } ++ ++ pi->radiopwr_override = RADIOPWR_OVERRIDE_DEF; ++ ++ pi->user_txpwr_at_rfport = false; ++ ++ if (ISNPHY(pi)) { ++ ++ pi->phycal_timer = wlapi_init_timer(pi->sh->physhim, ++ wlc_phy_timercb_phycal, ++ pi, "phycal"); ++ if (!pi->phycal_timer) ++ goto err; ++ ++ if (!wlc_phy_attach_nphy(pi)) ++ goto err; ++ ++ } else if (ISLCNPHY(pi)) { ++ if (!wlc_phy_attach_lcnphy(pi)) ++ goto err; ++ ++ } ++ ++ pi->refcnt++; ++ pi->next = pi->sh->phy_head; ++ sh->phy_head = pi; ++ ++ memcpy(&pi->pubpi_ro, &pi->pubpi, sizeof(struct brcms_phy_pub)); ++ ++ return &pi->pubpi_ro; ++ ++err: ++ kfree(pi); ++ return NULL; ++} ++ ++void wlc_phy_detach(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (pih) { ++ if (--pi->refcnt) ++ return; ++ ++ if (pi->phycal_timer) { ++ wlapi_free_timer(pi->phycal_timer); ++ pi->phycal_timer = NULL; ++ } ++ ++ if (pi->sh->phy_head == pi) ++ pi->sh->phy_head = pi->next; ++ else if (pi->sh->phy_head->next == pi) ++ pi->sh->phy_head->next = NULL; ++ ++ if (pi->pi_fptr.detach) ++ (pi->pi_fptr.detach)(pi); ++ ++ kfree(pi); ++ } ++} ++ ++bool ++wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype, u16 *phyrev, ++ u16 *radioid, u16 *radiover) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ *phytype = (u16) pi->pubpi.phy_type; ++ *phyrev = (u16) pi->pubpi.phy_rev; ++ *radioid = pi->pubpi.radioid; ++ *radiover = pi->pubpi.radiorev; ++ ++ return true; ++} ++ ++bool wlc_phy_get_encore(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ return pi->pubpi.abgphy_encore; ++} ++ ++u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ return pi->pubpi.coreflags; ++} ++ ++void wlc_phy_anacore(struct brcms_phy_pub *pih, bool on) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (ISNPHY(pi)) { ++ if (on) { ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ write_phy_reg(pi, 0xa6, 0x0d); ++ write_phy_reg(pi, 0x8f, 0x0); ++ write_phy_reg(pi, 0xa7, 0x0d); ++ write_phy_reg(pi, 0xa5, 0x0); ++ } else { ++ write_phy_reg(pi, 0xa5, 0x0); ++ } ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ write_phy_reg(pi, 0x8f, 0x07ff); ++ write_phy_reg(pi, 0xa6, 0x0fd); ++ write_phy_reg(pi, 0xa5, 0x07ff); ++ write_phy_reg(pi, 0xa7, 0x0fd); ++ } else { ++ write_phy_reg(pi, 0xa5, 0x7fff); ++ } ++ } ++ } else if (ISLCNPHY(pi)) { ++ if (on) { ++ and_phy_reg(pi, 0x43b, ++ ~((0x1 << 0) | (0x1 << 1) | (0x1 << 2))); ++ } else { ++ or_phy_reg(pi, 0x43c, ++ (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); ++ or_phy_reg(pi, 0x43b, ++ (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); ++ } ++ } ++} ++ ++u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ u32 phy_bw_clkbits = 0; ++ ++ if (pi && (ISNPHY(pi) || ISLCNPHY(pi))) { ++ switch (pi->bw) { ++ case WL_CHANSPEC_BW_10: ++ phy_bw_clkbits = SICF_BW10; ++ break; ++ case WL_CHANSPEC_BW_20: ++ phy_bw_clkbits = SICF_BW20; ++ break; ++ case WL_CHANSPEC_BW_40: ++ phy_bw_clkbits = SICF_BW40; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ return phy_bw_clkbits; ++} ++ ++void wlc_phy_por_inform(struct brcms_phy_pub *ppi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ pi->phy_init_por = true; ++} ++ ++void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ pi->edcrs_threshold_lock = lock; ++ ++ write_phy_reg(pi, 0x22c, 0x46b); ++ write_phy_reg(pi, 0x22d, 0x46b); ++ write_phy_reg(pi, 0x22e, 0x3c0); ++ write_phy_reg(pi, 0x22f, 0x3c0); ++} ++ ++void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ pi->do_initcal = initcal; ++} ++ ++void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *pih, bool newstate) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (!pi || !pi->sh) ++ return; ++ ++ pi->sh->clk = newstate; ++} ++ ++void wlc_phy_hw_state_upd(struct brcms_phy_pub *pih, bool newstate) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (!pi || !pi->sh) ++ return; ++ ++ pi->sh->up = newstate; ++} ++ ++void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec) ++{ ++ u32 mc; ++ void (*phy_init)(struct brcms_phy *) = NULL; ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (pi->init_in_progress) ++ return; ++ ++ pi->init_in_progress = true; ++ ++ pi->radio_chanspec = chanspec; ++ ++ mc = R_REG(&pi->regs->maccontrol); ++ if (WARN(mc & MCTL_EN_MAC, "HW error MAC running on init")) ++ return; ++ ++ if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) ++ pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC; ++ ++ if (WARN(!(ai_core_sflags(pi->sh->sih, 0, 0) & SISF_FCLKA), ++ "HW error SISF_FCLKA\n")) ++ return; ++ ++ phy_init = pi->pi_fptr.init; ++ ++ if (phy_init == NULL) ++ return; ++ ++ wlc_phy_anacore(pih, ON); ++ ++ if (CHSPEC_BW(pi->radio_chanspec) != pi->bw) ++ wlapi_bmac_bw_set(pi->sh->physhim, ++ CHSPEC_BW(pi->radio_chanspec)); ++ ++ pi->nphy_gain_boost = true; ++ ++ wlc_phy_switch_radio((struct brcms_phy_pub *) pi, ON); ++ ++ (*phy_init)(pi); ++ ++ pi->phy_init_por = false; ++ ++ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) ++ wlc_phy_do_dummy_tx(pi, true, OFF); ++ ++ if (!(ISNPHY(pi))) ++ wlc_phy_txpower_update_shm(pi); ++ ++ wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, pi->sh->rx_antdiv); ++ ++ pi->init_in_progress = false; ++} ++ ++void wlc_phy_cal_init(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ void (*cal_init)(struct brcms_phy *) = NULL; ++ ++ if (WARN((R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) != 0, ++ "HW error: MAC enabled during phy cal\n")) ++ return; ++ ++ if (!pi->initialized) { ++ cal_init = pi->pi_fptr.calinit; ++ if (cal_init) ++ (*cal_init)(pi); ++ ++ pi->initialized = true; ++ } ++} ++ ++int wlc_phy_down(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ int callbacks = 0; ++ ++ if (pi->phycal_timer ++ && !wlapi_del_timer(pi->phycal_timer)) ++ callbacks++; ++ ++ pi->nphy_iqcal_chanspec_2G = 0; ++ pi->nphy_iqcal_chanspec_5G = 0; ++ ++ return callbacks; ++} ++ ++void ++wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset, ++ u16 tblAddr, u16 tblDataHi, u16 tblDataLo) ++{ ++ write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset); ++ ++ pi->tbl_data_hi = tblDataHi; ++ pi->tbl_data_lo = tblDataLo; ++ ++ if (pi->sh->chip == BCM43224_CHIP_ID && ++ pi->sh->chiprev == 1) { ++ pi->tbl_addr = tblAddr; ++ pi->tbl_save_id = tbl_id; ++ pi->tbl_save_offset = tbl_offset; ++ } ++} ++ ++void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val) ++{ ++ if ((pi->sh->chip == BCM43224_CHIP_ID) && ++ (pi->sh->chiprev == 1) && ++ (pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) { ++ read_phy_reg(pi, pi->tbl_data_lo); ++ ++ write_phy_reg(pi, pi->tbl_addr, ++ (pi->tbl_save_id << 10) | pi->tbl_save_offset); ++ pi->tbl_save_offset++; ++ } ++ ++ if (width == 32) { ++ write_phy_reg(pi, pi->tbl_data_hi, (u16) (val >> 16)); ++ write_phy_reg(pi, pi->tbl_data_lo, (u16) val); ++ } else { ++ write_phy_reg(pi, pi->tbl_data_lo, (u16) val); ++ } ++} ++ ++void ++wlc_phy_write_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info, ++ u16 tblAddr, u16 tblDataHi, u16 tblDataLo) ++{ ++ uint idx; ++ uint tbl_id = ptbl_info->tbl_id; ++ uint tbl_offset = ptbl_info->tbl_offset; ++ uint tbl_width = ptbl_info->tbl_width; ++ const u8 *ptbl_8b = (const u8 *)ptbl_info->tbl_ptr; ++ const u16 *ptbl_16b = (const u16 *)ptbl_info->tbl_ptr; ++ const u32 *ptbl_32b = (const u32 *)ptbl_info->tbl_ptr; ++ ++ write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset); ++ ++ for (idx = 0; idx < ptbl_info->tbl_len; idx++) { ++ ++ if ((pi->sh->chip == BCM43224_CHIP_ID) && ++ (pi->sh->chiprev == 1) && ++ (tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) { ++ read_phy_reg(pi, tblDataLo); ++ ++ write_phy_reg(pi, tblAddr, ++ (tbl_id << 10) | (tbl_offset + idx)); ++ } ++ ++ if (tbl_width == 32) { ++ write_phy_reg(pi, tblDataHi, ++ (u16) (ptbl_32b[idx] >> 16)); ++ write_phy_reg(pi, tblDataLo, (u16) ptbl_32b[idx]); ++ } else if (tbl_width == 16) { ++ write_phy_reg(pi, tblDataLo, ptbl_16b[idx]); ++ } else { ++ write_phy_reg(pi, tblDataLo, ptbl_8b[idx]); ++ } ++ } ++} ++ ++void ++wlc_phy_read_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info, ++ u16 tblAddr, u16 tblDataHi, u16 tblDataLo) ++{ ++ uint idx; ++ uint tbl_id = ptbl_info->tbl_id; ++ uint tbl_offset = ptbl_info->tbl_offset; ++ uint tbl_width = ptbl_info->tbl_width; ++ u8 *ptbl_8b = (u8 *)ptbl_info->tbl_ptr; ++ u16 *ptbl_16b = (u16 *)ptbl_info->tbl_ptr; ++ u32 *ptbl_32b = (u32 *)ptbl_info->tbl_ptr; ++ ++ write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset); ++ ++ for (idx = 0; idx < ptbl_info->tbl_len; idx++) { ++ ++ if ((pi->sh->chip == BCM43224_CHIP_ID) && ++ (pi->sh->chiprev == 1)) { ++ (void)read_phy_reg(pi, tblDataLo); ++ ++ write_phy_reg(pi, tblAddr, ++ (tbl_id << 10) | (tbl_offset + idx)); ++ } ++ ++ if (tbl_width == 32) { ++ ptbl_32b[idx] = read_phy_reg(pi, tblDataLo); ++ ptbl_32b[idx] |= (read_phy_reg(pi, tblDataHi) << 16); ++ } else if (tbl_width == 16) { ++ ptbl_16b[idx] = read_phy_reg(pi, tblDataLo); ++ } else { ++ ptbl_8b[idx] = (u8) read_phy_reg(pi, tblDataLo); ++ } ++ } ++} ++ ++uint ++wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi, ++ struct radio_20xx_regs *radioregs) ++{ ++ uint i = 0; ++ ++ do { ++ if (radioregs[i].do_init) ++ write_radio_reg(pi, radioregs[i].address, ++ (u16) radioregs[i].init); ++ ++ i++; ++ } while (radioregs[i].address != 0xffff); ++ ++ return i; ++} ++ ++uint ++wlc_phy_init_radio_regs(struct brcms_phy *pi, ++ const struct radio_regs *radioregs, ++ u16 core_offset) ++{ ++ uint i = 0; ++ uint count = 0; ++ ++ do { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (radioregs[i].do_init_a) { ++ write_radio_reg(pi, ++ radioregs[i]. ++ address | core_offset, ++ (u16) radioregs[i].init_a); ++ if (ISNPHY(pi) && (++count % 4 == 0)) ++ BRCMS_PHY_WAR_PR51571(pi); ++ } ++ } else { ++ if (radioregs[i].do_init_g) { ++ write_radio_reg(pi, ++ radioregs[i]. ++ address | core_offset, ++ (u16) radioregs[i].init_g); ++ if (ISNPHY(pi) && (++count % 4 == 0)) ++ BRCMS_PHY_WAR_PR51571(pi); ++ } ++ } ++ ++ i++; ++ } while (radioregs[i].address != 0xffff); ++ ++ return i; ++} ++ ++void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on) ++{ ++#define DUMMY_PKT_LEN 20 ++ struct d11regs __iomem *regs = pi->regs; ++ int i, count; ++ u8 ofdmpkt[DUMMY_PKT_LEN] = { ++ 0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 ++ }; ++ u8 cckpkt[DUMMY_PKT_LEN] = { ++ 0x6e, 0x84, 0x0b, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 ++ }; ++ u32 *dummypkt; ++ ++ dummypkt = (u32 *) (ofdm ? ofdmpkt : cckpkt); ++ wlapi_bmac_write_template_ram(pi->sh->physhim, 0, DUMMY_PKT_LEN, ++ dummypkt); ++ ++ W_REG(®s->xmtsel, 0); ++ ++ if (D11REV_GE(pi->sh->corerev, 11)) ++ W_REG(®s->wepctl, 0x100); ++ else ++ W_REG(®s->wepctl, 0); ++ ++ W_REG(®s->txe_phyctl, (ofdm ? 1 : 0) | PHY_TXC_ANT_0); ++ if (ISNPHY(pi) || ISLCNPHY(pi)) ++ W_REG(®s->txe_phyctl1, 0x1A02); ++ ++ W_REG(®s->txe_wm_0, 0); ++ W_REG(®s->txe_wm_1, 0); ++ ++ W_REG(®s->xmttplatetxptr, 0); ++ W_REG(®s->xmttxcnt, DUMMY_PKT_LEN); ++ ++ W_REG(®s->xmtsel, ((8 << 8) | (1 << 5) | (1 << 2) | 2)); ++ ++ W_REG(®s->txe_ctl, 0); ++ ++ if (!pa_on) { ++ if (ISNPHY(pi)) ++ wlc_phy_pa_override_nphy(pi, OFF); ++ } ++ ++ if (ISNPHY(pi) || ISLCNPHY(pi)) ++ W_REG(®s->txe_aux, 0xD0); ++ else ++ W_REG(®s->txe_aux, ((1 << 5) | (1 << 4))); ++ ++ (void)R_REG(®s->txe_aux); ++ ++ i = 0; ++ count = ofdm ? 30 : 250; ++ while ((i++ < count) ++ && (R_REG(®s->txe_status) & (1 << 7))) ++ udelay(10); ++ ++ i = 0; ++ ++ while ((i++ < 10) ++ && ((R_REG(®s->txe_status) & (1 << 10)) == 0)) ++ udelay(10); ++ ++ i = 0; ++ ++ while ((i++ < 10) && ((R_REG(®s->ifsstat) & (1 << 8)))) ++ udelay(10); ++ ++ if (!pa_on) { ++ if (ISNPHY(pi)) ++ wlc_phy_pa_override_nphy(pi, ON); ++ } ++} ++ ++void wlc_phy_hold_upd(struct brcms_phy_pub *pih, u32 id, bool set) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (set) ++ mboolset(pi->measure_hold, id); ++ else ++ mboolclr(pi->measure_hold, id); ++ ++ return; ++} ++ ++void wlc_phy_mute_upd(struct brcms_phy_pub *pih, bool mute, u32 flags) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (mute) ++ mboolset(pi->measure_hold, PHY_HOLD_FOR_MUTE); ++ else ++ mboolclr(pi->measure_hold, PHY_HOLD_FOR_MUTE); ++ ++ if (!mute && (flags & PHY_MUTE_FOR_PREISM)) ++ pi->nphy_perical_last = pi->sh->now - pi->sh->glacial_timer; ++ return; ++} ++ ++void wlc_phy_clear_tssi(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (ISNPHY(pi)) { ++ return; ++ } else { ++ wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_0, NULL_TSSI_W); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_1, NULL_TSSI_W); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_0, NULL_TSSI_W); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_1, NULL_TSSI_W); ++ } ++} ++ ++static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi) ++{ ++ return false; ++} ++ ++void wlc_phy_switch_radio(struct brcms_phy_pub *pih, bool on) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ (void)R_REG(&pi->regs->maccontrol); ++ ++ if (ISNPHY(pi)) { ++ wlc_phy_switch_radio_nphy(pi, on); ++ } else if (ISLCNPHY(pi)) { ++ if (on) { ++ and_phy_reg(pi, 0x44c, ++ ~((0x1 << 8) | ++ (0x1 << 9) | ++ (0x1 << 10) | (0x1 << 11) | (0x1 << 12))); ++ and_phy_reg(pi, 0x4b0, ~((0x1 << 3) | (0x1 << 11))); ++ and_phy_reg(pi, 0x4f9, ~(0x1 << 3)); ++ } else { ++ and_phy_reg(pi, 0x44d, ++ ~((0x1 << 10) | ++ (0x1 << 11) | ++ (0x1 << 12) | (0x1 << 13) | (0x1 << 14))); ++ or_phy_reg(pi, 0x44c, ++ (0x1 << 8) | ++ (0x1 << 9) | ++ (0x1 << 10) | (0x1 << 11) | (0x1 << 12)); ++ ++ and_phy_reg(pi, 0x4b7, ~((0x7f << 8))); ++ and_phy_reg(pi, 0x4b1, ~((0x1 << 13))); ++ or_phy_reg(pi, 0x4b0, (0x1 << 3) | (0x1 << 11)); ++ and_phy_reg(pi, 0x4fa, ~((0x1 << 3))); ++ or_phy_reg(pi, 0x4f9, (0x1 << 3)); ++ } ++ } ++} ++ ++u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ return pi->bw; ++} ++ ++void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ pi->bw = bw; ++} ++ ++void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, u16 newch) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ pi->radio_chanspec = newch; ++ ++} ++ ++u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ return pi->radio_chanspec; ++} ++ ++void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, u16 chanspec) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ u16 m_cur_channel; ++ void (*chanspec_set)(struct brcms_phy *, u16) = NULL; ++ m_cur_channel = CHSPEC_CHANNEL(chanspec); ++ if (CHSPEC_IS5G(chanspec)) ++ m_cur_channel |= D11_CURCHANNEL_5G; ++ if (CHSPEC_IS40(chanspec)) ++ m_cur_channel |= D11_CURCHANNEL_40; ++ wlapi_bmac_write_shm(pi->sh->physhim, M_CURCHANNEL, m_cur_channel); ++ ++ chanspec_set = pi->pi_fptr.chanset; ++ if (chanspec_set) ++ (*chanspec_set)(pi, chanspec); ++ ++} ++ ++int wlc_phy_chanspec_freq2bandrange_lpssn(uint freq) ++{ ++ int range = -1; ++ ++ if (freq < 2500) ++ range = WL_CHAN_FREQ_RANGE_2G; ++ else if (freq <= 5320) ++ range = WL_CHAN_FREQ_RANGE_5GL; ++ else if (freq <= 5700) ++ range = WL_CHAN_FREQ_RANGE_5GM; ++ else ++ range = WL_CHAN_FREQ_RANGE_5GH; ++ ++ return range; ++} ++ ++int wlc_phy_chanspec_bandrange_get(struct brcms_phy *pi, u16 chanspec) ++{ ++ int range = -1; ++ uint channel = CHSPEC_CHANNEL(chanspec); ++ uint freq = wlc_phy_channel2freq(channel); ++ ++ if (ISNPHY(pi)) ++ range = wlc_phy_get_chan_freq_range_nphy(pi, channel); ++ else if (ISLCNPHY(pi)) ++ range = wlc_phy_chanspec_freq2bandrange_lpssn(freq); ++ ++ return range; ++} ++ ++void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi, ++ bool wide_filter) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ pi->channel_14_wide_filter = wide_filter; ++ ++} ++ ++int wlc_phy_channel2freq(uint channel) ++{ ++ uint i; ++ ++ for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) ++ if (chan_info_all[i].chan == channel) ++ return chan_info_all[i].freq; ++ return 0; ++} ++ ++void ++wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band, ++ struct brcms_chanvec *channels) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ uint i; ++ uint channel; ++ ++ memset(channels, 0, sizeof(struct brcms_chanvec)); ++ ++ for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) { ++ channel = chan_info_all[i].chan; ++ ++ if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM) ++ && (channel <= LAST_REF5_CHANNUM)) ++ continue; ++ ++ if ((band == BRCM_BAND_2G && channel <= CH_MAX_2G_CHANNEL) || ++ (band == BRCM_BAND_5G && channel > CH_MAX_2G_CHANNEL)) ++ setbit(channels->vec, channel); ++ } ++} ++ ++u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ uint i; ++ uint channel; ++ u16 chspec; ++ ++ for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) { ++ channel = chan_info_all[i].chan; ++ ++ if (ISNPHY(pi) && pi->bw == WL_CHANSPEC_BW_40) { ++ uint j; ++ ++ for (j = 0; j < ARRAY_SIZE(chan_info_all); j++) { ++ if (chan_info_all[j].chan == ++ channel + CH_10MHZ_APART) ++ break; ++ } ++ ++ if (j == ARRAY_SIZE(chan_info_all)) ++ continue; ++ ++ channel = upper_20_sb(channel); ++ chspec = channel | WL_CHANSPEC_BW_40 | ++ WL_CHANSPEC_CTL_SB_LOWER; ++ if (band == BRCM_BAND_2G) ++ chspec |= WL_CHANSPEC_BAND_2G; ++ else ++ chspec |= WL_CHANSPEC_BAND_5G; ++ } else ++ chspec = ch20mhz_chspec(channel); ++ ++ if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM) ++ && (channel <= LAST_REF5_CHANNUM)) ++ continue; ++ ++ if ((band == BRCM_BAND_2G && channel <= CH_MAX_2G_CHANNEL) || ++ (band == BRCM_BAND_5G && channel > CH_MAX_2G_CHANNEL)) ++ return chspec; ++ } ++ ++ return (u16) INVCHANSPEC; ++} ++ ++int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ *qdbm = pi->tx_user_target[0]; ++ if (override != NULL) ++ *override = pi->txpwroverride; ++ return 0; ++} ++ ++void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi, ++ struct txpwr_limits *txpwr) ++{ ++ bool mac_enabled = false; ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ memcpy(&pi->tx_user_target[TXP_FIRST_CCK], ++ &txpwr->cck[0], BRCMS_NUM_RATES_CCK); ++ ++ memcpy(&pi->tx_user_target[TXP_FIRST_OFDM], ++ &txpwr->ofdm[0], BRCMS_NUM_RATES_OFDM); ++ memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_20_CDD], ++ &txpwr->ofdm_cdd[0], BRCMS_NUM_RATES_OFDM); ++ ++ memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_SISO], ++ &txpwr->ofdm_40_siso[0], BRCMS_NUM_RATES_OFDM); ++ memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_CDD], ++ &txpwr->ofdm_40_cdd[0], BRCMS_NUM_RATES_OFDM); ++ ++ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SISO], ++ &txpwr->mcs_20_siso[0], BRCMS_NUM_RATES_MCS_1_STREAM); ++ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_CDD], ++ &txpwr->mcs_20_cdd[0], BRCMS_NUM_RATES_MCS_1_STREAM); ++ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_STBC], ++ &txpwr->mcs_20_stbc[0], BRCMS_NUM_RATES_MCS_1_STREAM); ++ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SDM], ++ &txpwr->mcs_20_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM); ++ ++ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SISO], ++ &txpwr->mcs_40_siso[0], BRCMS_NUM_RATES_MCS_1_STREAM); ++ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_CDD], ++ &txpwr->mcs_40_cdd[0], BRCMS_NUM_RATES_MCS_1_STREAM); ++ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_STBC], ++ &txpwr->mcs_40_stbc[0], BRCMS_NUM_RATES_MCS_1_STREAM); ++ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SDM], ++ &txpwr->mcs_40_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM); ++ ++ if (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ++ mac_enabled = true; ++ ++ if (mac_enabled) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ wlc_phy_txpower_recalc_target(pi); ++ wlc_phy_cal_txpower_recalc_sw(pi); ++ ++ if (mac_enabled) ++ wlapi_enable_mac(pi->sh->physhim); ++} ++ ++int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ int i; ++ ++ if (qdbm > 127) ++ return -EINVAL; ++ ++ for (i = 0; i < TXP_NUM_RATES; i++) ++ pi->tx_user_target[i] = (u8) qdbm; ++ ++ pi->txpwroverride = false; ++ ++ if (pi->sh->up) { ++ if (!SCAN_INPROG_PHY(pi)) { ++ bool suspend; ++ ++ suspend = (0 == (R_REG(&pi->regs->maccontrol) & ++ MCTL_EN_MAC)); ++ ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ wlc_phy_txpower_recalc_target(pi); ++ wlc_phy_cal_txpower_recalc_sw(pi); ++ ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++ } ++ } ++ return 0; ++} ++ ++void ++wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint channel, u8 *min_pwr, ++ u8 *max_pwr, int txp_rate_idx) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ uint i; ++ ++ *min_pwr = pi->min_txpower * BRCMS_TXPWR_DB_FACTOR; ++ ++ if (ISNPHY(pi)) { ++ if (txp_rate_idx < 0) ++ txp_rate_idx = TXP_FIRST_CCK; ++ wlc_phy_txpower_sromlimit_get_nphy(pi, channel, max_pwr, ++ (u8) txp_rate_idx); ++ ++ } else if ((channel <= CH_MAX_2G_CHANNEL)) { ++ if (txp_rate_idx < 0) ++ txp_rate_idx = TXP_FIRST_CCK; ++ *max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx]; ++ } else { ++ ++ *max_pwr = BRCMS_TXPWR_MAX; ++ ++ if (txp_rate_idx < 0) ++ txp_rate_idx = TXP_FIRST_OFDM; ++ ++ for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) { ++ if (channel == chan_info_all[i].chan) ++ break; ++ } ++ ++ if (pi->hwtxpwr) { ++ *max_pwr = pi->hwtxpwr[i]; ++ } else { ++ ++ if ((i >= FIRST_MID_5G_CHAN) && (i <= LAST_MID_5G_CHAN)) ++ *max_pwr = ++ pi->tx_srom_max_rate_5g_mid[txp_rate_idx]; ++ if ((i >= FIRST_HIGH_5G_CHAN) ++ && (i <= LAST_HIGH_5G_CHAN)) ++ *max_pwr = ++ pi->tx_srom_max_rate_5g_hi[txp_rate_idx]; ++ if ((i >= FIRST_LOW_5G_CHAN) && (i <= LAST_LOW_5G_CHAN)) ++ *max_pwr = ++ pi->tx_srom_max_rate_5g_low[txp_rate_idx]; ++ } ++ } ++} ++ ++void ++wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, uint chan, ++ u8 *max_txpwr, u8 *min_txpwr) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ u8 tx_pwr_max = 0; ++ u8 tx_pwr_min = 255; ++ u8 max_num_rate; ++ u8 maxtxpwr, mintxpwr, rate, pactrl; ++ ++ pactrl = 0; ++ ++ max_num_rate = ISNPHY(pi) ? TXP_NUM_RATES : ++ ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 + ++ 1) : (TXP_LAST_OFDM + 1); ++ ++ for (rate = 0; rate < max_num_rate; rate++) { ++ ++ wlc_phy_txpower_sromlimit(ppi, chan, &mintxpwr, &maxtxpwr, ++ rate); ++ ++ maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0; ++ ++ maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0; ++ ++ tx_pwr_max = max(tx_pwr_max, maxtxpwr); ++ tx_pwr_min = min(tx_pwr_min, maxtxpwr); ++ } ++ *max_txpwr = tx_pwr_max; ++ *min_txpwr = tx_pwr_min; ++} ++ ++void ++wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi, uint bandunit, ++ s32 *max_pwr, s32 *min_pwr, u32 *step_pwr) ++{ ++ return; ++} ++ ++u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ return pi->tx_power_min; ++} ++ ++u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ return pi->tx_power_max; ++} ++ ++static s8 wlc_phy_env_measure_vbat(struct brcms_phy *pi) ++{ ++ if (ISLCNPHY(pi)) ++ return wlc_lcnphy_vbatsense(pi, 0); ++ else ++ return 0; ++} ++ ++static s8 wlc_phy_env_measure_temperature(struct brcms_phy *pi) ++{ ++ if (ISLCNPHY(pi)) ++ return wlc_lcnphy_tempsense_degree(pi, 0); ++ else ++ return 0; ++} ++ ++static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy *pi, u32 band) ++{ ++ u8 i; ++ s8 temp, vbat; ++ ++ for (i = 0; i < TXP_NUM_RATES; i++) ++ pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX; ++ ++ vbat = wlc_phy_env_measure_vbat(pi); ++ temp = wlc_phy_env_measure_temperature(pi); ++ ++} ++ ++static s8 ++wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band, ++ u8 rate) ++{ ++ s8 offset = 0; ++ ++ if (!pi->user_txpwr_at_rfport) ++ return offset; ++ return offset; ++} ++ ++void wlc_phy_txpower_recalc_target(struct brcms_phy *pi) ++{ ++ u8 maxtxpwr, mintxpwr, rate, pactrl; ++ uint target_chan; ++ u8 tx_pwr_target[TXP_NUM_RATES]; ++ u8 tx_pwr_max = 0; ++ u8 tx_pwr_min = 255; ++ u8 tx_pwr_max_rate_ind = 0; ++ u8 max_num_rate; ++ u8 start_rate = 0; ++ u16 chspec; ++ u32 band = CHSPEC2BAND(pi->radio_chanspec); ++ void (*txpwr_recalc_fn)(struct brcms_phy *) = NULL; ++ ++ chspec = pi->radio_chanspec; ++ if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) ++ target_chan = CHSPEC_CHANNEL(chspec); ++ else if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) ++ target_chan = upper_20_sb(CHSPEC_CHANNEL(chspec)); ++ else ++ target_chan = lower_20_sb(CHSPEC_CHANNEL(chspec)); ++ ++ pactrl = 0; ++ if (ISLCNPHY(pi)) { ++ u32 offset_mcs, i; ++ ++ if (CHSPEC_IS40(pi->radio_chanspec)) { ++ offset_mcs = pi->mcs40_po; ++ for (i = TXP_FIRST_SISO_MCS_20; ++ i <= TXP_LAST_SISO_MCS_20; i++) { ++ pi->tx_srom_max_rate_2g[i - 8] = ++ pi->tx_srom_max_2g - ++ ((offset_mcs & 0xf) * 2); ++ offset_mcs >>= 4; ++ } ++ } else { ++ offset_mcs = pi->mcs20_po; ++ for (i = TXP_FIRST_SISO_MCS_20; ++ i <= TXP_LAST_SISO_MCS_20; i++) { ++ pi->tx_srom_max_rate_2g[i - 8] = ++ pi->tx_srom_max_2g - ++ ((offset_mcs & 0xf) * 2); ++ offset_mcs >>= 4; ++ } ++ } ++ } ++ ++ max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : ++ ((ISLCNPHY(pi)) ? ++ (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1))); ++ ++ wlc_phy_upd_env_txpwr_rate_limits(pi, band); ++ ++ for (rate = start_rate; rate < max_num_rate; rate++) { ++ ++ tx_pwr_target[rate] = pi->tx_user_target[rate]; ++ ++ if (pi->user_txpwr_at_rfport) ++ tx_pwr_target[rate] += ++ wlc_user_txpwr_antport_to_rfport(pi, ++ target_chan, ++ band, ++ rate); ++ ++ wlc_phy_txpower_sromlimit((struct brcms_phy_pub *) pi, ++ target_chan, ++ &mintxpwr, &maxtxpwr, rate); ++ ++ maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]); ++ ++ maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0; ++ ++ maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0; ++ ++ maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]); ++ ++ if (pi->txpwr_percent <= 100) ++ maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100; ++ ++ tx_pwr_target[rate] = max(maxtxpwr, mintxpwr); ++ ++ tx_pwr_target[rate] = ++ min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]); ++ ++ if (tx_pwr_target[rate] > tx_pwr_max) ++ tx_pwr_max_rate_ind = rate; ++ ++ tx_pwr_max = max(tx_pwr_max, tx_pwr_target[rate]); ++ tx_pwr_min = min(tx_pwr_min, tx_pwr_target[rate]); ++ } ++ ++ memset(pi->tx_power_offset, 0, sizeof(pi->tx_power_offset)); ++ pi->tx_power_max = tx_pwr_max; ++ pi->tx_power_min = tx_pwr_min; ++ pi->tx_power_max_rate_ind = tx_pwr_max_rate_ind; ++ for (rate = 0; rate < max_num_rate; rate++) { ++ ++ pi->tx_power_target[rate] = tx_pwr_target[rate]; ++ ++ if (!pi->hwpwrctrl || ISNPHY(pi)) ++ pi->tx_power_offset[rate] = ++ pi->tx_power_max - pi->tx_power_target[rate]; ++ else ++ pi->tx_power_offset[rate] = ++ pi->tx_power_target[rate] - pi->tx_power_min; ++ } ++ ++ txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc; ++ if (txpwr_recalc_fn) ++ (*txpwr_recalc_fn)(pi); ++} ++ ++static void ++wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr, ++ u16 chanspec) ++{ ++ u8 tmp_txpwr_limit[2 * BRCMS_NUM_RATES_OFDM]; ++ u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL; ++ int rate_start_index = 0, rate1, rate2, k; ++ ++ for (rate1 = WL_TX_POWER_CCK_FIRST, rate2 = 0; ++ rate2 < WL_TX_POWER_CCK_NUM; rate1++, rate2++) ++ pi->txpwr_limit[rate1] = txpwr->cck[rate2]; ++ ++ for (rate1 = WL_TX_POWER_OFDM_FIRST, rate2 = 0; ++ rate2 < WL_TX_POWER_OFDM_NUM; rate1++, rate2++) ++ pi->txpwr_limit[rate1] = txpwr->ofdm[rate2]; ++ ++ if (ISNPHY(pi)) { ++ ++ for (k = 0; k < 4; k++) { ++ switch (k) { ++ case 0: ++ ++ txpwr_ptr1 = txpwr->mcs_20_siso; ++ txpwr_ptr2 = txpwr->ofdm; ++ rate_start_index = WL_TX_POWER_OFDM_FIRST; ++ break; ++ case 1: ++ ++ txpwr_ptr1 = txpwr->mcs_20_cdd; ++ txpwr_ptr2 = txpwr->ofdm_cdd; ++ rate_start_index = WL_TX_POWER_OFDM20_CDD_FIRST; ++ break; ++ case 2: ++ ++ txpwr_ptr1 = txpwr->mcs_40_siso; ++ txpwr_ptr2 = txpwr->ofdm_40_siso; ++ rate_start_index = ++ WL_TX_POWER_OFDM40_SISO_FIRST; ++ break; ++ case 3: ++ ++ txpwr_ptr1 = txpwr->mcs_40_cdd; ++ txpwr_ptr2 = txpwr->ofdm_40_cdd; ++ rate_start_index = WL_TX_POWER_OFDM40_CDD_FIRST; ++ break; ++ } ++ ++ for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; ++ rate2++) { ++ tmp_txpwr_limit[rate2] = 0; ++ tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] = ++ txpwr_ptr1[rate2]; ++ } ++ wlc_phy_mcs_to_ofdm_powers_nphy( ++ tmp_txpwr_limit, 0, ++ BRCMS_NUM_RATES_OFDM - ++ 1, BRCMS_NUM_RATES_OFDM); ++ for (rate1 = rate_start_index, rate2 = 0; ++ rate2 < BRCMS_NUM_RATES_OFDM; rate1++, rate2++) ++ pi->txpwr_limit[rate1] = ++ min(txpwr_ptr2[rate2], ++ tmp_txpwr_limit[rate2]); ++ } ++ ++ for (k = 0; k < 4; k++) { ++ switch (k) { ++ case 0: ++ ++ txpwr_ptr1 = txpwr->ofdm; ++ txpwr_ptr2 = txpwr->mcs_20_siso; ++ rate_start_index = WL_TX_POWER_MCS20_SISO_FIRST; ++ break; ++ case 1: ++ ++ txpwr_ptr1 = txpwr->ofdm_cdd; ++ txpwr_ptr2 = txpwr->mcs_20_cdd; ++ rate_start_index = WL_TX_POWER_MCS20_CDD_FIRST; ++ break; ++ case 2: ++ ++ txpwr_ptr1 = txpwr->ofdm_40_siso; ++ txpwr_ptr2 = txpwr->mcs_40_siso; ++ rate_start_index = WL_TX_POWER_MCS40_SISO_FIRST; ++ break; ++ case 3: ++ ++ txpwr_ptr1 = txpwr->ofdm_40_cdd; ++ txpwr_ptr2 = txpwr->mcs_40_cdd; ++ rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST; ++ break; ++ } ++ for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; ++ rate2++) { ++ tmp_txpwr_limit[rate2] = 0; ++ tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] = ++ txpwr_ptr1[rate2]; ++ } ++ wlc_phy_ofdm_to_mcs_powers_nphy( ++ tmp_txpwr_limit, 0, ++ BRCMS_NUM_RATES_OFDM - ++ 1, BRCMS_NUM_RATES_OFDM); ++ for (rate1 = rate_start_index, rate2 = 0; ++ rate2 < BRCMS_NUM_RATES_MCS_1_STREAM; ++ rate1++, rate2++) ++ pi->txpwr_limit[rate1] = ++ min(txpwr_ptr2[rate2], ++ tmp_txpwr_limit[rate2]); ++ } ++ ++ for (k = 0; k < 2; k++) { ++ switch (k) { ++ case 0: ++ ++ rate_start_index = WL_TX_POWER_MCS20_STBC_FIRST; ++ txpwr_ptr1 = txpwr->mcs_20_stbc; ++ break; ++ case 1: ++ ++ rate_start_index = WL_TX_POWER_MCS40_STBC_FIRST; ++ txpwr_ptr1 = txpwr->mcs_40_stbc; ++ break; ++ } ++ for (rate1 = rate_start_index, rate2 = 0; ++ rate2 < BRCMS_NUM_RATES_MCS_1_STREAM; ++ rate1++, rate2++) ++ pi->txpwr_limit[rate1] = txpwr_ptr1[rate2]; ++ } ++ ++ for (k = 0; k < 2; k++) { ++ switch (k) { ++ case 0: ++ ++ rate_start_index = WL_TX_POWER_MCS20_SDM_FIRST; ++ txpwr_ptr1 = txpwr->mcs_20_mimo; ++ break; ++ case 1: ++ ++ rate_start_index = WL_TX_POWER_MCS40_SDM_FIRST; ++ txpwr_ptr1 = txpwr->mcs_40_mimo; ++ break; ++ } ++ for (rate1 = rate_start_index, rate2 = 0; ++ rate2 < BRCMS_NUM_RATES_MCS_2_STREAM; ++ rate1++, rate2++) ++ pi->txpwr_limit[rate1] = txpwr_ptr1[rate2]; ++ } ++ ++ pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32; ++ ++ pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] = ++ min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST], ++ pi->txpwr_limit[WL_TX_POWER_MCS_32]); ++ pi->txpwr_limit[WL_TX_POWER_MCS_32] = ++ pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST]; ++ } ++} ++ ++void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, u8 txpwr_percent) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ pi->txpwr_percent = txpwr_percent; ++} ++ ++void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ pi->sh->machwcap = machwcap; ++} ++ ++void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ u16 rxc; ++ rxc = 0; ++ ++ if (start_end == ON) { ++ if (!ISNPHY(pi)) ++ return; ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 3) ++ || NREV_IS(pi->pubpi.phy_rev, 4)) { ++ W_REG(&pi->regs->phyregaddr, 0xa0); ++ (void)R_REG(&pi->regs->phyregaddr); ++ rxc = R_REG(&pi->regs->phyregdata); ++ W_REG(&pi->regs->phyregdata, ++ (0x1 << 15) | rxc); ++ } ++ } else { ++ if (NREV_IS(pi->pubpi.phy_rev, 3) ++ || NREV_IS(pi->pubpi.phy_rev, 4)) { ++ W_REG(&pi->regs->phyregaddr, 0xa0); ++ (void)R_REG(&pi->regs->phyregaddr); ++ W_REG(&pi->regs->phyregdata, rxc); ++ } ++ ++ wlc_phy_por_inform(ppi); ++ } ++} ++ ++void ++wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *txpwr, ++ u16 chanspec) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ wlc_phy_txpower_reg_limit_calc(pi, txpwr, chanspec); ++ ++ if (ISLCNPHY(pi)) { ++ int i, j; ++ for (i = TXP_FIRST_OFDM_20_CDD, j = 0; ++ j < BRCMS_NUM_RATES_MCS_1_STREAM; i++, j++) { ++ if (txpwr->mcs_20_siso[j]) ++ pi->txpwr_limit[i] = txpwr->mcs_20_siso[j]; ++ else ++ pi->txpwr_limit[i] = txpwr->ofdm[j]; ++ } ++ } ++ ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ wlc_phy_txpower_recalc_target(pi); ++ wlc_phy_cal_txpower_recalc_sw(pi); ++ wlapi_enable_mac(pi->sh->physhim); ++} ++ ++void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ pi->ofdm_rateset_war = war; ++} ++ ++void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ pi->bf_preempt_4306 = bf_preempt; ++} ++ ++void wlc_phy_txpower_update_shm(struct brcms_phy *pi) ++{ ++ int j; ++ if (ISNPHY(pi)) ++ return; ++ ++ if (!pi->sh->clk) ++ return; ++ ++ if (pi->hwpwrctrl) { ++ u16 offset; ++ ++ wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_MAX, 63); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_N, ++ 1 << NUM_TSSI_FRAMES); ++ ++ wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_TARGET, ++ pi->tx_power_min << NUM_TSSI_FRAMES); ++ ++ wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_CUR, ++ pi->hwpwr_txcur); ++ ++ for (j = TXP_FIRST_OFDM; j <= TXP_LAST_OFDM; j++) { ++ const u8 ucode_ofdm_rates[] = { ++ 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c ++ }; ++ offset = wlapi_bmac_rate_shm_offset( ++ pi->sh->physhim, ++ ucode_ofdm_rates[j - TXP_FIRST_OFDM]); ++ wlapi_bmac_write_shm(pi->sh->physhim, offset + 6, ++ pi->tx_power_offset[j]); ++ wlapi_bmac_write_shm(pi->sh->physhim, offset + 14, ++ -(pi->tx_power_offset[j] / 2)); ++ } ++ ++ wlapi_bmac_mhf(pi->sh->physhim, MHF2, MHF2_HWPWRCTL, ++ MHF2_HWPWRCTL, BRCM_BAND_ALL); ++ } else { ++ int i; ++ ++ for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) ++ pi->tx_power_offset[i] = ++ (u8) roundup(pi->tx_power_offset[i], 8); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET, ++ (u16) ++ ((pi->tx_power_offset[TXP_FIRST_OFDM] ++ + 7) >> 3)); ++ } ++} ++ ++bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ if (ISNPHY(pi)) ++ return pi->nphy_txpwrctrl; ++ else ++ return pi->hwpwrctrl; ++} ++ ++void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ bool suspend; ++ ++ if (!pi->hwpwrctrl_capable) ++ return; ++ ++ pi->hwpwrctrl = hwpwrctrl; ++ pi->nphy_txpwrctrl = hwpwrctrl; ++ pi->txpwrctrl = hwpwrctrl; ++ ++ if (ISNPHY(pi)) { ++ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl); ++ if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) ++ wlc_phy_txpwr_fixpower_nphy(pi); ++ else ++ mod_phy_reg(pi, 0x1e7, (0x7f << 0), ++ pi->saved_txpwr_idx); ++ ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++ } ++} ++ ++void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi) ++{ ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ pi->ipa2g_on = (pi->srom_fem2g.extpagain == 2); ++ pi->ipa5g_on = (pi->srom_fem5g.extpagain == 2); ++ } else { ++ pi->ipa2g_on = false; ++ pi->ipa5g_on = false; ++ } ++} ++ ++static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi) ++{ ++ s16 tx0_status, tx1_status; ++ u16 estPower1, estPower2; ++ u8 pwr0, pwr1, adj_pwr0, adj_pwr1; ++ u32 est_pwr; ++ ++ estPower1 = read_phy_reg(pi, 0x118); ++ estPower2 = read_phy_reg(pi, 0x119); ++ ++ if ((estPower1 & (0x1 << 8)) == (0x1 << 8)) ++ pwr0 = (u8) (estPower1 & (0xff << 0)) >> 0; ++ else ++ pwr0 = 0x80; ++ ++ if ((estPower2 & (0x1 << 8)) == (0x1 << 8)) ++ pwr1 = (u8) (estPower2 & (0xff << 0)) >> 0; ++ else ++ pwr1 = 0x80; ++ ++ tx0_status = read_phy_reg(pi, 0x1ed); ++ tx1_status = read_phy_reg(pi, 0x1ee); ++ ++ if ((tx0_status & (0x1 << 15)) == (0x1 << 15)) ++ adj_pwr0 = (u8) (tx0_status & (0xff << 0)) >> 0; ++ else ++ adj_pwr0 = 0x80; ++ if ((tx1_status & (0x1 << 15)) == (0x1 << 15)) ++ adj_pwr1 = (u8) (tx1_status & (0xff << 0)) >> 0; ++ else ++ adj_pwr1 = 0x80; ++ ++ est_pwr = (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) | ++ adj_pwr1); ++ ++ return est_pwr; ++} ++ ++void ++wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, struct tx_power *power, ++ uint channel) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ uint rate, num_rates; ++ u8 min_pwr, max_pwr; ++ ++#if WL_TX_POWER_RATES != TXP_NUM_RATES ++#error "struct tx_power out of sync with this fn" ++#endif ++ ++ if (ISNPHY(pi)) { ++ power->rf_cores = 2; ++ power->flags |= (WL_TX_POWER_F_MIMO); ++ if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON) ++ power->flags |= ++ (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW); ++ } else if (ISLCNPHY(pi)) { ++ power->rf_cores = 1; ++ power->flags |= (WL_TX_POWER_F_SISO); ++ if (pi->radiopwr_override == RADIOPWR_OVERRIDE_DEF) ++ power->flags |= WL_TX_POWER_F_ENABLED; ++ if (pi->hwpwrctrl) ++ power->flags |= WL_TX_POWER_F_HW; ++ } ++ ++ num_rates = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : ++ ((ISLCNPHY(pi)) ? ++ (TXP_LAST_OFDM_20_CDD + 1) : (TXP_LAST_OFDM + 1))); ++ ++ for (rate = 0; rate < num_rates; rate++) { ++ power->user_limit[rate] = pi->tx_user_target[rate]; ++ wlc_phy_txpower_sromlimit(ppi, channel, &min_pwr, &max_pwr, ++ rate); ++ power->board_limit[rate] = (u8) max_pwr; ++ power->target[rate] = pi->tx_power_target[rate]; ++ } ++ ++ if (ISNPHY(pi)) { ++ u32 est_pout; ++ ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ wlc_phyreg_enter((struct brcms_phy_pub *) pi); ++ est_pout = wlc_phy_txpower_est_power_nphy(pi); ++ wlc_phyreg_exit((struct brcms_phy_pub *) pi); ++ wlapi_enable_mac(pi->sh->physhim); ++ ++ power->est_Pout[0] = (est_pout >> 8) & 0xff; ++ power->est_Pout[1] = est_pout & 0xff; ++ ++ power->est_Pout_act[0] = est_pout >> 24; ++ power->est_Pout_act[1] = (est_pout >> 16) & 0xff; ++ ++ if (power->est_Pout[0] == 0x80) ++ power->est_Pout[0] = 0; ++ if (power->est_Pout[1] == 0x80) ++ power->est_Pout[1] = 0; ++ ++ if (power->est_Pout_act[0] == 0x80) ++ power->est_Pout_act[0] = 0; ++ if (power->est_Pout_act[1] == 0x80) ++ power->est_Pout_act[1] = 0; ++ ++ power->est_Pout_cck = 0; ++ ++ power->tx_power_max[0] = pi->tx_power_max; ++ power->tx_power_max[1] = pi->tx_power_max; ++ ++ power->tx_power_max_rate_ind[0] = pi->tx_power_max_rate_ind; ++ power->tx_power_max_rate_ind[1] = pi->tx_power_max_rate_ind; ++ } else if (pi->hwpwrctrl && pi->sh->up) { ++ ++ wlc_phyreg_enter(ppi); ++ if (ISLCNPHY(pi)) { ++ ++ power->tx_power_max[0] = pi->tx_power_max; ++ power->tx_power_max[1] = pi->tx_power_max; ++ ++ power->tx_power_max_rate_ind[0] = ++ pi->tx_power_max_rate_ind; ++ power->tx_power_max_rate_ind[1] = ++ pi->tx_power_max_rate_ind; ++ ++ if (wlc_phy_tpc_isenabled_lcnphy(pi)) ++ power->flags |= ++ (WL_TX_POWER_F_HW | ++ WL_TX_POWER_F_ENABLED); ++ else ++ power->flags &= ++ ~(WL_TX_POWER_F_HW | ++ WL_TX_POWER_F_ENABLED); ++ ++ wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0], ++ (s8 *) &power->est_Pout_cck); ++ } ++ wlc_phyreg_exit(ppi); ++ } ++} ++ ++void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ pi->antsel_type = antsel_type; ++} ++ ++bool wlc_phy_test_ison(struct brcms_phy_pub *ppi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ return pi->phytest_on; ++} ++ ++void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ bool suspend; ++ ++ pi->sh->rx_antdiv = val; ++ ++ if (!(ISNPHY(pi) && D11REV_IS(pi->sh->corerev, 16))) { ++ if (val > ANT_RX_DIV_FORCE_1) ++ wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, ++ MHF1_ANTDIV, BRCM_BAND_ALL); ++ else ++ wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, 0, ++ BRCM_BAND_ALL); ++ } ++ ++ if (ISNPHY(pi)) ++ return; ++ ++ if (!pi->sh->clk) ++ return; ++ ++ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ if (ISLCNPHY(pi)) { ++ if (val > ANT_RX_DIV_FORCE_1) { ++ mod_phy_reg(pi, 0x410, (0x1 << 1), 0x01 << 1); ++ mod_phy_reg(pi, 0x410, ++ (0x1 << 0), ++ ((ANT_RX_DIV_START_1 == val) ? 1 : 0) << 0); ++ } else { ++ mod_phy_reg(pi, 0x410, (0x1 << 1), 0x00 << 1); ++ mod_phy_reg(pi, 0x410, (0x1 << 0), (u16) val << 0); ++ } ++ } ++ ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++ ++ return; ++} ++ ++static bool ++wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr, s8 *pwr_ant) ++{ ++ s8 cmplx_pwr_dbm[PHY_CORE_MAX]; ++ u8 i; ++ ++ memset((u8 *) cmplx_pwr_dbm, 0, sizeof(cmplx_pwr_dbm)); ++ wlc_phy_compute_dB(cmplx_pwr, cmplx_pwr_dbm, pi->pubpi.phy_corenum); ++ ++ for (i = 0; i < pi->pubpi.phy_corenum; i++) { ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ cmplx_pwr_dbm[i] += (s8) PHY_NOISE_OFFSETFACT_4322; ++ else ++ ++ cmplx_pwr_dbm[i] += (s8) (16 - (15) * 3 - 70); ++ } ++ ++ for (i = 0; i < pi->pubpi.phy_corenum; i++) { ++ pi->nphy_noise_win[i][pi->nphy_noise_index] = cmplx_pwr_dbm[i]; ++ pwr_ant[i] = cmplx_pwr_dbm[i]; ++ } ++ pi->nphy_noise_index = ++ MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ); ++ return true; ++} ++ ++static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm) ++{ ++ if (!pi->phynoise_state) ++ return; ++ ++ if (pi->phynoise_state & PHY_NOISE_STATE_MON) { ++ if (pi->phynoise_chan_watchdog == channel) { ++ pi->sh->phy_noise_window[pi->sh->phy_noise_index] = ++ noise_dbm; ++ pi->sh->phy_noise_index = ++ MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ); ++ } ++ pi->phynoise_state &= ~PHY_NOISE_STATE_MON; ++ } ++ ++ if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL) ++ pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL; ++ ++} ++ ++static s8 wlc_phy_noise_read_shmem(struct brcms_phy *pi) ++{ ++ u32 cmplx_pwr[PHY_CORE_MAX]; ++ s8 noise_dbm_ant[PHY_CORE_MAX]; ++ u16 lo, hi; ++ u32 cmplx_pwr_tot = 0; ++ s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; ++ u8 idx, core; ++ ++ memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr)); ++ memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant)); ++ ++ for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2, ++ core++) { ++ lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx)); ++ hi = wlapi_bmac_read_shm(pi->sh->physhim, ++ M_PWRIND_MAP(idx + 1)); ++ cmplx_pwr[core] = (hi << 16) + lo; ++ cmplx_pwr_tot += cmplx_pwr[core]; ++ if (cmplx_pwr[core] == 0) ++ noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY; ++ else ++ cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE; ++ } ++ ++ if (cmplx_pwr_tot != 0) ++ wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant); ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ pi->nphy_noise_win[core][pi->nphy_noise_index] = ++ noise_dbm_ant[core]; ++ ++ if (noise_dbm_ant[core] > noise_dbm) ++ noise_dbm = noise_dbm_ant[core]; ++ } ++ pi->nphy_noise_index = ++ MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ); ++ ++ return noise_dbm; ++ ++} ++ ++void wlc_phy_noise_sample_intr(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ u16 jssi_aux; ++ u8 channel = 0; ++ s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; ++ ++ if (ISLCNPHY(pi)) { ++ u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1; ++ u16 lo, hi; ++ s32 pwr_offset_dB, gain_dB; ++ u16 status_0, status_1; ++ ++ jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX); ++ channel = jssi_aux & D11_CURCHANNEL_MAX; ++ ++ lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0); ++ hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1); ++ cmplx_pwr0 = (hi << 16) + lo; ++ ++ lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2); ++ hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3); ++ cmplx_pwr1 = (hi << 16) + lo; ++ cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6; ++ ++ status_0 = 0x44; ++ status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0); ++ if ((cmplx_pwr > 0 && cmplx_pwr < 500) ++ && ((status_1 & 0xc000) == 0x4000)) { ++ ++ wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm, ++ pi->pubpi.phy_corenum); ++ pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF); ++ if (pwr_offset_dB > 127) ++ pwr_offset_dB -= 256; ++ ++ noise_dbm += (s8) (pwr_offset_dB - 30); ++ ++ gain_dB = (status_0 & 0x1ff); ++ noise_dbm -= (s8) (gain_dB); ++ } else { ++ noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY; ++ } ++ } else if (ISNPHY(pi)) { ++ ++ jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX); ++ channel = jssi_aux & D11_CURCHANNEL_MAX; ++ ++ noise_dbm = wlc_phy_noise_read_shmem(pi); ++ } ++ ++ wlc_phy_noise_cb(pi, channel, noise_dbm); ++ ++} ++ ++static void ++wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; ++ bool sampling_in_progress = (pi->phynoise_state != 0); ++ bool wait_for_intr = true; ++ ++ switch (reason) { ++ case PHY_NOISE_SAMPLE_MON: ++ pi->phynoise_chan_watchdog = ch; ++ pi->phynoise_state |= PHY_NOISE_STATE_MON; ++ break; ++ ++ case PHY_NOISE_SAMPLE_EXTERNAL: ++ pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL; ++ break; ++ ++ default: ++ break; ++ } ++ ++ if (sampling_in_progress) ++ return; ++ ++ pi->phynoise_now = pi->sh->now; ++ ++ if (pi->phy_fixed_noise) { ++ if (ISNPHY(pi)) { ++ pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] = ++ PHY_NOISE_FIXED_VAL_NPHY; ++ pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] = ++ PHY_NOISE_FIXED_VAL_NPHY; ++ pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index, ++ PHY_NOISE_WINDOW_SZ); ++ noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; ++ } else { ++ noise_dbm = PHY_NOISE_FIXED_VAL; ++ } ++ ++ wait_for_intr = false; ++ goto done; ++ } ++ ++ if (ISLCNPHY(pi)) { ++ if (!pi->phynoise_polling ++ || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) { ++ wlapi_bmac_write_shm(pi->sh->physhim, M_JSSI_0, 0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0); ++ ++ OR_REG(&pi->regs->maccommand, ++ MCMD_BG_NOISE); ++ } else { ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ wlc_lcnphy_deaf_mode(pi, (bool) 0); ++ noise_dbm = (s8) wlc_lcnphy_rx_signal_power(pi, 20); ++ wlc_lcnphy_deaf_mode(pi, (bool) 1); ++ wlapi_enable_mac(pi->sh->physhim); ++ wait_for_intr = false; ++ } ++ } else if (ISNPHY(pi)) { ++ if (!pi->phynoise_polling ++ || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) { ++ ++ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0); ++ ++ OR_REG(&pi->regs->maccommand, ++ MCMD_BG_NOISE); ++ } else { ++ struct phy_iq_est est[PHY_CORE_MAX]; ++ u32 cmplx_pwr[PHY_CORE_MAX]; ++ s8 noise_dbm_ant[PHY_CORE_MAX]; ++ u16 log_num_samps, num_samps, classif_state = 0; ++ u8 wait_time = 32; ++ u8 wait_crs = 0; ++ u8 i; ++ ++ memset((u8 *) est, 0, sizeof(est)); ++ memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr)); ++ memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant)); ++ ++ log_num_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY; ++ num_samps = 1 << log_num_samps; ++ ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ classif_state = wlc_phy_classifier_nphy(pi, 0, 0); ++ wlc_phy_classifier_nphy(pi, 3, 0); ++ wlc_phy_rx_iq_est_nphy(pi, est, num_samps, wait_time, ++ wait_crs); ++ wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state); ++ wlapi_enable_mac(pi->sh->physhim); ++ ++ for (i = 0; i < pi->pubpi.phy_corenum; i++) ++ cmplx_pwr[i] = (est[i].i_pwr + est[i].q_pwr) >> ++ log_num_samps; ++ ++ wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant); ++ ++ for (i = 0; i < pi->pubpi.phy_corenum; i++) { ++ pi->nphy_noise_win[i][pi->nphy_noise_index] = ++ noise_dbm_ant[i]; ++ ++ if (noise_dbm_ant[i] > noise_dbm) ++ noise_dbm = noise_dbm_ant[i]; ++ } ++ pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index, ++ PHY_NOISE_WINDOW_SZ); ++ ++ wait_for_intr = false; ++ } ++ } ++ ++done: ++ ++ if (!wait_for_intr) ++ wlc_phy_noise_cb(pi, ch, noise_dbm); ++ ++} ++ ++void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *pih) ++{ ++ u8 channel; ++ ++ channel = CHSPEC_CHANNEL(wlc_phy_chanspec_get(pih)); ++ ++ wlc_phy_noise_sample_request(pih, PHY_NOISE_SAMPLE_EXTERNAL, channel); ++} ++ ++static const s8 lcnphy_gain_index_offset_for_pkt_rssi[] = { ++ 8, ++ 8, ++ 8, ++ 8, ++ 8, ++ 8, ++ 8, ++ 9, ++ 10, ++ 8, ++ 8, ++ 7, ++ 7, ++ 1, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 1, ++ 1, ++ 0, ++ 0, ++ 0, ++ 0 ++}; ++ ++void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core) ++{ ++ u8 msb, secondmsb, i; ++ u32 tmp; ++ ++ for (i = 0; i < core; i++) { ++ secondmsb = 0; ++ tmp = cmplx_pwr[i]; ++ msb = fls(tmp); ++ if (msb) ++ secondmsb = (u8) ((tmp >> (--msb - 1)) & 1); ++ p_cmplx_pwr_dB[i] = (s8) (3 * msb + 2 * secondmsb); ++ } ++} ++ ++int wlc_phy_rssi_compute(struct brcms_phy_pub *pih, ++ struct d11rxhdr *rxh) ++{ ++ int rssi = rxh->PhyRxStatus_1 & PRXS1_JSSI_MASK; ++ uint radioid = pih->radioid; ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if ((pi->sh->corerev >= 11) ++ && !(rxh->RxStatus2 & RXS_PHYRXST_VALID)) { ++ rssi = BRCMS_RSSI_INVALID; ++ goto end; ++ } ++ ++ if (ISLCNPHY(pi)) { ++ u8 gidx = (rxh->PhyRxStatus_2 & 0xFC00) >> 10; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ if (rssi > 127) ++ rssi -= 256; ++ ++ rssi = rssi + lcnphy_gain_index_offset_for_pkt_rssi[gidx]; ++ if ((rssi > -46) && (gidx > 18)) ++ rssi = rssi + 7; ++ ++ rssi = rssi + pi_lcn->lcnphy_pkteng_rssi_slope; ++ ++ rssi = rssi + 2; ++ ++ } ++ ++ if (ISLCNPHY(pi)) { ++ if (rssi > 127) ++ rssi -= 256; ++ } else if (radioid == BCM2055_ID || radioid == BCM2056_ID ++ || radioid == BCM2057_ID) { ++ rssi = wlc_phy_rssi_compute_nphy(pi, rxh); ++ } ++ ++end: ++ return rssi; ++} ++ ++void wlc_phy_freqtrack_start(struct brcms_phy_pub *pih) ++{ ++ return; ++} ++ ++void wlc_phy_freqtrack_end(struct brcms_phy_pub *pih) ++{ ++ return; ++} ++ ++void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag) ++{ ++ struct brcms_phy *pi; ++ pi = (struct brcms_phy *) ppi; ++ ++ if (ISLCNPHY(pi)) ++ wlc_lcnphy_deaf_mode(pi, true); ++ else if (ISNPHY(pi)) ++ wlc_nphy_deaf_mode(pi, true); ++} ++ ++void wlc_phy_watchdog(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ bool delay_phy_cal = false; ++ pi->sh->now++; ++ ++ if (!pi->watchdog_override) ++ return; ++ ++ if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi))) ++ wlc_phy_noise_sample_request((struct brcms_phy_pub *) pi, ++ PHY_NOISE_SAMPLE_MON, ++ CHSPEC_CHANNEL(pi-> ++ radio_chanspec)); ++ ++ if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5) ++ pi->phynoise_state = 0; ++ ++ if ((!pi->phycal_txpower) || ++ ((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) { ++ ++ if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi)) ++ pi->phycal_txpower = pi->sh->now; ++ } ++ ++ if ((SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) ++ || ASSOC_INPROG_PHY(pi))) ++ return; ++ ++ if (ISNPHY(pi) && !pi->disable_percal && !delay_phy_cal) { ++ ++ if ((pi->nphy_perical != PHY_PERICAL_DISABLE) && ++ (pi->nphy_perical != PHY_PERICAL_MANUAL) && ++ ((pi->sh->now - pi->nphy_perical_last) >= ++ pi->sh->glacial_timer)) ++ wlc_phy_cal_perical((struct brcms_phy_pub *) pi, ++ PHY_PERICAL_WATCHDOG); ++ ++ wlc_phy_txpwr_papd_cal_nphy(pi); ++ } ++ ++ if (ISLCNPHY(pi)) { ++ if (pi->phy_forcecal || ++ ((pi->sh->now - pi->phy_lastcal) >= ++ pi->sh->glacial_timer)) { ++ if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi))) ++ wlc_lcnphy_calib_modes( ++ pi, ++ LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL); ++ if (! ++ (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) ++ || ASSOC_INPROG_PHY(pi) ++ || pi->carrier_suppr_disable ++ || pi->disable_percal)) ++ wlc_lcnphy_calib_modes(pi, ++ PHY_PERICAL_WATCHDOG); ++ } ++ } ++} ++ ++void wlc_phy_BSSinit(struct brcms_phy_pub *pih, bool bonlyap, int rssi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ uint i; ++ uint k; ++ ++ for (i = 0; i < MA_WINDOW_SZ; i++) ++ pi->sh->phy_noise_window[i] = (s8) (rssi & 0xff); ++ if (ISLCNPHY(pi)) { ++ for (i = 0; i < MA_WINDOW_SZ; i++) ++ pi->sh->phy_noise_window[i] = ++ PHY_NOISE_FIXED_VAL_LCNPHY; ++ } ++ pi->sh->phy_noise_index = 0; ++ ++ for (i = 0; i < PHY_NOISE_WINDOW_SZ; i++) { ++ for (k = WL_ANT_IDX_1; k < WL_ANT_RX_MAX; k++) ++ pi->nphy_noise_win[k][i] = PHY_NOISE_FIXED_VAL_NPHY; ++ } ++ pi->nphy_noise_index = 0; ++} ++ ++void ++wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag) ++{ ++ *eps_imag = (epsilon >> 13); ++ if (*eps_imag > 0xfff) ++ *eps_imag -= 0x2000; ++ ++ *eps_real = (epsilon & 0x1fff); ++ if (*eps_real > 0xfff) ++ *eps_real -= 0x2000; ++} ++ ++void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi) ++{ ++ wlapi_del_timer(pi->phycal_timer); ++ ++ pi->cal_type_override = PHY_PERICAL_AUTO; ++ pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE; ++ pi->mphase_txcal_cmdidx = 0; ++} ++ ++static void ++wlc_phy_cal_perical_mphase_schedule(struct brcms_phy *pi, uint delay) ++{ ++ ++ if ((pi->nphy_perical != PHY_PERICAL_MPHASE) && ++ (pi->nphy_perical != PHY_PERICAL_MANUAL)) ++ return; ++ ++ wlapi_del_timer(pi->phycal_timer); ++ ++ pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT; ++ wlapi_add_timer(pi->phycal_timer, delay, 0); ++} ++ ++void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason) ++{ ++ s16 nphy_currtemp = 0; ++ s16 delta_temp = 0; ++ bool do_periodic_cal = true; ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (!ISNPHY(pi)) ++ return; ++ ++ if ((pi->nphy_perical == PHY_PERICAL_DISABLE) || ++ (pi->nphy_perical == PHY_PERICAL_MANUAL)) ++ return; ++ ++ switch (reason) { ++ case PHY_PERICAL_DRIVERUP: ++ break; ++ ++ case PHY_PERICAL_PHYINIT: ++ if (pi->nphy_perical == PHY_PERICAL_MPHASE) { ++ if (PHY_PERICAL_MPHASE_PENDING(pi)) ++ wlc_phy_cal_perical_mphase_reset(pi); ++ ++ wlc_phy_cal_perical_mphase_schedule( ++ pi, ++ PHY_PERICAL_INIT_DELAY); ++ } ++ break; ++ ++ case PHY_PERICAL_JOIN_BSS: ++ case PHY_PERICAL_START_IBSS: ++ case PHY_PERICAL_UP_BSS: ++ if ((pi->nphy_perical == PHY_PERICAL_MPHASE) && ++ PHY_PERICAL_MPHASE_PENDING(pi)) ++ wlc_phy_cal_perical_mphase_reset(pi); ++ ++ pi->first_cal_after_assoc = true; ++ ++ pi->cal_type_override = PHY_PERICAL_FULL; ++ ++ if (pi->phycal_tempdelta) ++ pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi); ++ ++ wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL); ++ break; ++ ++ case PHY_PERICAL_WATCHDOG: ++ if (pi->phycal_tempdelta) { ++ nphy_currtemp = wlc_phy_tempsense_nphy(pi); ++ delta_temp = ++ (nphy_currtemp > pi->nphy_lastcal_temp) ? ++ nphy_currtemp - pi->nphy_lastcal_temp : ++ pi->nphy_lastcal_temp - nphy_currtemp; ++ ++ if ((delta_temp < (s16) pi->phycal_tempdelta) && ++ (pi->nphy_txiqlocal_chanspec == ++ pi->radio_chanspec)) ++ do_periodic_cal = false; ++ else ++ pi->nphy_lastcal_temp = nphy_currtemp; ++ } ++ ++ if (do_periodic_cal) { ++ if (pi->nphy_perical == PHY_PERICAL_MPHASE) { ++ if (!PHY_PERICAL_MPHASE_PENDING(pi)) ++ wlc_phy_cal_perical_mphase_schedule( ++ pi, ++ PHY_PERICAL_WDOG_DELAY); ++ } else if (pi->nphy_perical == PHY_PERICAL_SPHASE) ++ wlc_phy_cal_perical_nphy_run(pi, ++ PHY_PERICAL_AUTO); ++ } ++ break; ++ default: ++ break; ++ } ++} ++ ++void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi) ++{ ++ pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT; ++ pi->mphase_txcal_cmdidx = 0; ++} ++ ++u8 wlc_phy_nbits(s32 value) ++{ ++ s32 abs_val; ++ u8 nbits = 0; ++ ++ abs_val = abs(value); ++ while ((abs_val >> nbits) > 0) ++ nbits++; ++ ++ return nbits; ++} ++ ++void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ pi->sh->hw_phytxchain = txchain; ++ pi->sh->hw_phyrxchain = rxchain; ++ pi->sh->phytxchain = txchain; ++ pi->sh->phyrxchain = rxchain; ++ pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain); ++} ++ ++void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ pi->sh->phytxchain = txchain; ++ ++ if (ISNPHY(pi)) ++ wlc_phy_rxcore_setstate_nphy(pih, rxchain); ++ ++ pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain); ++} ++ ++void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, u8 *rxchain) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ *txchain = pi->sh->phytxchain; ++ *rxchain = pi->sh->phyrxchain; ++} ++ ++u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih) ++{ ++ s16 nphy_currtemp; ++ u8 active_bitmap; ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ active_bitmap = (pi->phy_txcore_heatedup) ? 0x31 : 0x33; ++ ++ if (!pi->watchdog_override) ++ return active_bitmap; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 6)) { ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ nphy_currtemp = wlc_phy_tempsense_nphy(pi); ++ wlapi_enable_mac(pi->sh->physhim); ++ ++ if (!pi->phy_txcore_heatedup) { ++ if (nphy_currtemp >= pi->phy_txcore_disable_temp) { ++ active_bitmap &= 0xFD; ++ pi->phy_txcore_heatedup = true; ++ } ++ } else { ++ if (nphy_currtemp <= pi->phy_txcore_enable_temp) { ++ active_bitmap |= 0x2; ++ pi->phy_txcore_heatedup = false; ++ } ++ } ++ } ++ ++ return active_bitmap; ++} ++ ++s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, u16 chanspec) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ u8 siso_mcs_id, cdd_mcs_id; ++ ++ siso_mcs_id = ++ (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO : ++ TXP_FIRST_MCS_20_SISO; ++ cdd_mcs_id = ++ (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD : ++ TXP_FIRST_MCS_20_CDD; ++ ++ if (pi->tx_power_target[siso_mcs_id] > ++ (pi->tx_power_target[cdd_mcs_id] + 12)) ++ return PHY_TXC1_MODE_SISO; ++ else ++ return PHY_TXC1_MODE_CDD; ++} ++ ++const u8 *wlc_phy_get_ofdm_rate_lookup(void) ++{ ++ return ofdm_rate_lookup; ++} ++ ++void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode) ++{ ++ if ((pi->sh->chip == BCM4313_CHIP_ID) && ++ (pi->sh->boardflags & BFL_FEM)) { ++ if (mode) { ++ u16 txant = 0; ++ txant = wlapi_bmac_get_txant(pi->sh->physhim); ++ if (txant == 1) { ++ mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2); ++ ++ } ++ ai_corereg(pi->sh->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, gpiocontrol), ++ ~0x0, 0x0); ++ ai_corereg(pi->sh->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, gpioout), 0x40, ++ 0x40); ++ ai_corereg(pi->sh->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, gpioouten), 0x40, ++ 0x40); ++ } else { ++ mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2); ++ ++ mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2); ++ ++ ai_corereg(pi->sh->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, gpioout), 0x40, ++ 0x00); ++ ai_corereg(pi->sh->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, gpioouten), 0x40, ++ 0x0); ++ ai_corereg(pi->sh->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, gpiocontrol), ++ ~0x0, 0x40); ++ } ++ } ++} ++ ++void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool ldpc) ++{ ++ return; ++} ++ ++void ++wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, s8 *ofdmoffset) ++{ ++ *cckoffset = 0; ++ *ofdmoffset = 0; ++} ++ ++s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, u16 chanspec) ++{ ++ ++ return rssi; ++} ++ ++bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *ppi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ if (ISNPHY(pi)) ++ return wlc_phy_n_txpower_ipa_ison(pi); ++ else ++ return 0; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h.orig 2011-11-09 13:46:58.254800521 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h 2011-11-09 13:47:17.008566067 -0500 +@@ -0,0 +1,301 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/* ++ * phy_hal.h: functionality exported from the phy to higher layers ++ */ ++ ++#ifndef _BRCM_PHY_HAL_H_ ++#define _BRCM_PHY_HAL_H_ ++ ++#include ++#include ++#include ++ ++#define IDCODE_VER_MASK 0x0000000f ++#define IDCODE_VER_SHIFT 0 ++#define IDCODE_MFG_MASK 0x00000fff ++#define IDCODE_MFG_SHIFT 0 ++#define IDCODE_ID_MASK 0x0ffff000 ++#define IDCODE_ID_SHIFT 12 ++#define IDCODE_REV_MASK 0xf0000000 ++#define IDCODE_REV_SHIFT 28 ++ ++#define NORADIO_ID 0xe4f5 ++#define NORADIO_IDCODE 0x4e4f5246 ++ ++#define BCM2055_ID 0x2055 ++#define BCM2055_IDCODE 0x02055000 ++#define BCM2055A0_IDCODE 0x1205517f ++ ++#define BCM2056_ID 0x2056 ++#define BCM2056_IDCODE 0x02056000 ++#define BCM2056A0_IDCODE 0x1205617f ++ ++#define BCM2057_ID 0x2057 ++#define BCM2057_IDCODE 0x02057000 ++#define BCM2057A0_IDCODE 0x1205717f ++ ++#define BCM2064_ID 0x2064 ++#define BCM2064_IDCODE 0x02064000 ++#define BCM2064A0_IDCODE 0x0206417f ++ ++#define PHY_TPC_HW_OFF false ++#define PHY_TPC_HW_ON true ++ ++#define PHY_PERICAL_DRIVERUP 1 ++#define PHY_PERICAL_WATCHDOG 2 ++#define PHY_PERICAL_PHYINIT 3 ++#define PHY_PERICAL_JOIN_BSS 4 ++#define PHY_PERICAL_START_IBSS 5 ++#define PHY_PERICAL_UP_BSS 6 ++#define PHY_PERICAL_CHAN 7 ++#define PHY_FULLCAL 8 ++ ++#define PHY_PERICAL_DISABLE 0 ++#define PHY_PERICAL_SPHASE 1 ++#define PHY_PERICAL_MPHASE 2 ++#define PHY_PERICAL_MANUAL 3 ++ ++#define PHY_HOLD_FOR_ASSOC 1 ++#define PHY_HOLD_FOR_SCAN 2 ++#define PHY_HOLD_FOR_RM 4 ++#define PHY_HOLD_FOR_PLT 8 ++#define PHY_HOLD_FOR_MUTE 16 ++#define PHY_HOLD_FOR_NOT_ASSOC 0x20 ++ ++#define PHY_MUTE_FOR_PREISM 1 ++#define PHY_MUTE_ALL 0xffffffff ++ ++#define PHY_NOISE_FIXED_VAL (-95) ++#define PHY_NOISE_FIXED_VAL_NPHY (-92) ++#define PHY_NOISE_FIXED_VAL_LCNPHY (-92) ++ ++#define PHY_MODE_CAL 0x0002 ++#define PHY_MODE_NOISEM 0x0004 ++ ++#define BRCMS_TXPWR_DB_FACTOR 4 ++ ++/* a large TX Power as an init value to factor out of min() calculations, ++ * keep low enough to fit in an s8, units are .25 dBm ++ */ ++#define BRCMS_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */ ++ ++#define BRCMS_NUM_RATES_CCK 4 ++#define BRCMS_NUM_RATES_OFDM 8 ++#define BRCMS_NUM_RATES_MCS_1_STREAM 8 ++#define BRCMS_NUM_RATES_MCS_2_STREAM 8 ++#define BRCMS_NUM_RATES_MCS_3_STREAM 8 ++#define BRCMS_NUM_RATES_MCS_4_STREAM 8 ++ ++#define BRCMS_RSSI_INVALID 0 /* invalid RSSI value */ ++ ++struct d11regs; ++struct phy_shim_info; ++ ++struct txpwr_limits { ++ u8 cck[BRCMS_NUM_RATES_CCK]; ++ u8 ofdm[BRCMS_NUM_RATES_OFDM]; ++ ++ u8 ofdm_cdd[BRCMS_NUM_RATES_OFDM]; ++ ++ u8 ofdm_40_siso[BRCMS_NUM_RATES_OFDM]; ++ u8 ofdm_40_cdd[BRCMS_NUM_RATES_OFDM]; ++ ++ u8 mcs_20_siso[BRCMS_NUM_RATES_MCS_1_STREAM]; ++ u8 mcs_20_cdd[BRCMS_NUM_RATES_MCS_1_STREAM]; ++ u8 mcs_20_stbc[BRCMS_NUM_RATES_MCS_1_STREAM]; ++ u8 mcs_20_mimo[BRCMS_NUM_RATES_MCS_2_STREAM]; ++ ++ u8 mcs_40_siso[BRCMS_NUM_RATES_MCS_1_STREAM]; ++ u8 mcs_40_cdd[BRCMS_NUM_RATES_MCS_1_STREAM]; ++ u8 mcs_40_stbc[BRCMS_NUM_RATES_MCS_1_STREAM]; ++ u8 mcs_40_mimo[BRCMS_NUM_RATES_MCS_2_STREAM]; ++ u8 mcs32; ++}; ++ ++struct tx_power { ++ u32 flags; ++ u16 chanspec; /* txpwr report for this channel */ ++ u16 local_chanspec; /* channel on which we are associated */ ++ u8 local_max; /* local max according to the AP */ ++ u8 local_constraint; /* local constraint according to the AP */ ++ s8 antgain[2]; /* Ant gain for each band - from SROM */ ++ u8 rf_cores; /* count of RF Cores being reported */ ++ u8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ ++ u8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain ++ * without adjustment */ ++ u8 est_Pout_cck; /* Latest CCK tx power out estimate */ ++ u8 tx_power_max[4]; /* Maximum target power among all rates */ ++ /* Index of the rate with the max target power */ ++ u8 tx_power_max_rate_ind[4]; ++ /* User limit */ ++ u8 user_limit[WL_TX_POWER_RATES]; ++ /* Regulatory power limit */ ++ u8 reg_limit[WL_TX_POWER_RATES]; ++ /* Max power board can support (SROM) */ ++ u8 board_limit[WL_TX_POWER_RATES]; ++ /* Latest target power */ ++ u8 target[WL_TX_POWER_RATES]; ++}; ++ ++struct tx_inst_power { ++ u8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ ++ u8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ ++}; ++ ++struct brcms_chanvec { ++ u8 vec[MAXCHANNEL / NBBY]; ++}; ++ ++struct shared_phy_params { ++ struct si_pub *sih; ++ struct phy_shim_info *physhim; ++ uint unit; ++ uint corerev; ++ uint buscorerev; ++ u16 vid; ++ u16 did; ++ uint chip; ++ uint chiprev; ++ uint chippkg; ++ uint sromrev; ++ uint boardtype; ++ uint boardrev; ++ uint boardvendor; ++ u32 boardflags; ++ u32 boardflags2; ++}; ++ ++ ++extern struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp); ++extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh, ++ struct d11regs __iomem *regs, ++ int bandtype, struct wiphy *wiphy); ++extern void wlc_phy_detach(struct brcms_phy_pub *ppi); ++ ++extern bool wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype, ++ u16 *phyrev, u16 *radioid, ++ u16 *radiover); ++extern bool wlc_phy_get_encore(struct brcms_phy_pub *pih); ++extern u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih); ++ ++extern void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *ppi, bool newstate); ++extern void wlc_phy_hw_state_upd(struct brcms_phy_pub *ppi, bool newstate); ++extern void wlc_phy_init(struct brcms_phy_pub *ppi, u16 chanspec); ++extern void wlc_phy_watchdog(struct brcms_phy_pub *ppi); ++extern int wlc_phy_down(struct brcms_phy_pub *ppi); ++extern u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih); ++extern void wlc_phy_cal_init(struct brcms_phy_pub *ppi); ++extern void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init); ++ ++extern void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, ++ u16 chanspec); ++extern u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi); ++extern void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, ++ u16 newch); ++extern u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi); ++extern void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw); ++ ++extern int wlc_phy_rssi_compute(struct brcms_phy_pub *pih, ++ struct d11rxhdr *rxh); ++extern void wlc_phy_por_inform(struct brcms_phy_pub *ppi); ++extern void wlc_phy_noise_sample_intr(struct brcms_phy_pub *ppi); ++extern bool wlc_phy_bist_check_phy(struct brcms_phy_pub *ppi); ++ ++extern void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag); ++ ++extern void wlc_phy_switch_radio(struct brcms_phy_pub *ppi, bool on); ++extern void wlc_phy_anacore(struct brcms_phy_pub *ppi, bool on); ++ ++ ++extern void wlc_phy_BSSinit(struct brcms_phy_pub *ppi, bool bonlyap, int rssi); ++ ++extern void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi, ++ bool wide_filter); ++extern void wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band, ++ struct brcms_chanvec *channels); ++extern u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, ++ uint band); ++ ++extern void wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint chan, ++ u8 *_min_, u8 *_max_, int rate); ++extern void wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, ++ uint chan, u8 *_max_, u8 *_min_); ++extern void wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi, ++ uint band, s32 *, s32 *, u32 *); ++extern void wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, ++ struct txpwr_limits *, ++ u16 chanspec); ++extern int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, ++ bool *override); ++extern int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, ++ bool override); ++extern void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi, ++ struct txpwr_limits *); ++extern bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi); ++extern void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, ++ bool hwpwrctrl); ++extern u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi); ++extern u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi); ++extern bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *pih); ++ ++extern void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, ++ u8 rxchain); ++extern void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, ++ u8 rxchain); ++extern void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, ++ u8 *rxchain); ++extern u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih); ++extern s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, ++ u16 chanspec); ++extern void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool val); ++ ++extern void wlc_phy_cal_perical(struct brcms_phy_pub *ppi, u8 reason); ++extern void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *ppi); ++extern void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock); ++extern void wlc_phy_cal_papd_recal(struct brcms_phy_pub *ppi); ++ ++extern void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val); ++extern void wlc_phy_clear_tssi(struct brcms_phy_pub *ppi); ++extern void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, u32 id, bool val); ++extern void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, u32 flags); ++ ++extern void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type); ++ ++extern void wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, ++ struct tx_power *power, uint channel); ++ ++extern void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal); ++extern bool wlc_phy_test_ison(struct brcms_phy_pub *ppi); ++extern void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, ++ u8 txpwr_percent); ++extern void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war); ++extern void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, ++ bool bf_preempt); ++extern void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap); ++ ++extern void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end); ++ ++extern void wlc_phy_freqtrack_start(struct brcms_phy_pub *ppi); ++extern void wlc_phy_freqtrack_end(struct brcms_phy_pub *ppi); ++ ++extern const u8 *wlc_phy_get_ofdm_rate_lookup(void); ++ ++extern s8 wlc_phy_get_tx_power_offset_by_mcs(struct brcms_phy_pub *ppi, ++ u8 mcs_offset); ++extern s8 wlc_phy_get_tx_power_offset(struct brcms_phy_pub *ppi, u8 tbl_offset); ++#endif /* _BRCM_PHY_HAL_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h.orig 2011-11-09 13:46:58.255800509 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h 2011-11-09 13:47:17.009566054 -0500 +@@ -0,0 +1,1169 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_PHY_INT_H_ ++#define _BRCM_PHY_INT_H_ ++ ++#include ++#include ++#include ++ ++#define PHY_VERSION { 1, 82, 8, 0 } ++ ++#define LCNXN_BASEREV 16 ++ ++struct phy_shim_info; ++ ++struct brcms_phy_srom_fem { ++ /* TSSI positive slope, 1: positive, 0: negative */ ++ u8 tssipos; ++ /* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */ ++ u8 extpagain; ++ /* support 32 combinations of different Pdet dynamic ranges */ ++ u8 pdetrange; ++ /* TR switch isolation */ ++ u8 triso; ++ /* antswctrl lookup table configuration: 32 possible choices */ ++ u8 antswctrllut; ++}; ++ ++#define ISNPHY(pi) PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_N) ++#define ISLCNPHY(pi) PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_LCN) ++ ++#define PHY_GET_RFATTN(rfgain) ((rfgain) & 0x0f) ++#define PHY_GET_PADMIX(rfgain) (((rfgain) & 0x10) >> 4) ++#define PHY_GET_RFGAINID(rfattn, padmix, width) ((rfattn) + ((padmix)*(width))) ++#define PHY_SAT(x, n) ((x) > ((1<<((n)-1))-1) ? ((1<<((n)-1))-1) : \ ++ ((x) < -(1<<((n)-1)) ? -(1<<((n)-1)) : (x))) ++#define PHY_SHIFT_ROUND(x, n) ((x) >= 0 ? ((x)+(1<<((n)-1)))>>(n) : (x)>>(n)) ++#define PHY_HW_ROUND(x, s) ((x >> s) + ((x >> (s-1)) & (s != 0))) ++ ++#define CH_5G_GROUP 3 ++#define A_LOW_CHANS 0 ++#define A_MID_CHANS 1 ++#define A_HIGH_CHANS 2 ++#define CH_2G_GROUP 1 ++#define G_ALL_CHANS 0 ++ ++#define FIRST_REF5_CHANNUM 149 ++#define LAST_REF5_CHANNUM 165 ++#define FIRST_5G_CHAN 14 ++#define LAST_5G_CHAN 50 ++#define FIRST_MID_5G_CHAN 14 ++#define LAST_MID_5G_CHAN 35 ++#define FIRST_HIGH_5G_CHAN 36 ++#define LAST_HIGH_5G_CHAN 41 ++#define FIRST_LOW_5G_CHAN 42 ++#define LAST_LOW_5G_CHAN 50 ++ ++#define BASE_LOW_5G_CHAN 4900 ++#define BASE_MID_5G_CHAN 5100 ++#define BASE_HIGH_5G_CHAN 5500 ++ ++#define CHAN5G_FREQ(chan) (5000 + chan*5) ++#define CHAN2G_FREQ(chan) (2407 + chan*5) ++ ++#define TXP_FIRST_CCK 0 ++#define TXP_LAST_CCK 3 ++#define TXP_FIRST_OFDM 4 ++#define TXP_LAST_OFDM 11 ++#define TXP_FIRST_OFDM_20_CDD 12 ++#define TXP_LAST_OFDM_20_CDD 19 ++#define TXP_FIRST_MCS_20_SISO 20 ++#define TXP_LAST_MCS_20_SISO 27 ++#define TXP_FIRST_MCS_20_CDD 28 ++#define TXP_LAST_MCS_20_CDD 35 ++#define TXP_FIRST_MCS_20_STBC 36 ++#define TXP_LAST_MCS_20_STBC 43 ++#define TXP_FIRST_MCS_20_SDM 44 ++#define TXP_LAST_MCS_20_SDM 51 ++#define TXP_FIRST_OFDM_40_SISO 52 ++#define TXP_LAST_OFDM_40_SISO 59 ++#define TXP_FIRST_OFDM_40_CDD 60 ++#define TXP_LAST_OFDM_40_CDD 67 ++#define TXP_FIRST_MCS_40_SISO 68 ++#define TXP_LAST_MCS_40_SISO 75 ++#define TXP_FIRST_MCS_40_CDD 76 ++#define TXP_LAST_MCS_40_CDD 83 ++#define TXP_FIRST_MCS_40_STBC 84 ++#define TXP_LAST_MCS_40_STBC 91 ++#define TXP_FIRST_MCS_40_SDM 92 ++#define TXP_LAST_MCS_40_SDM 99 ++#define TXP_MCS_32 100 ++#define TXP_NUM_RATES 101 ++#define ADJ_PWR_TBL_LEN 84 ++ ++#define TXP_FIRST_SISO_MCS_20 20 ++#define TXP_LAST_SISO_MCS_20 27 ++ ++#define PHY_CORE_NUM_1 1 ++#define PHY_CORE_NUM_2 2 ++#define PHY_CORE_NUM_3 3 ++#define PHY_CORE_NUM_4 4 ++#define PHY_CORE_MAX PHY_CORE_NUM_4 ++#define PHY_CORE_0 0 ++#define PHY_CORE_1 1 ++#define PHY_CORE_2 2 ++#define PHY_CORE_3 3 ++ ++#define MA_WINDOW_SZ 8 ++ ++#define PHY_NOISE_SAMPLE_MON 1 ++#define PHY_NOISE_SAMPLE_EXTERNAL 2 ++#define PHY_NOISE_WINDOW_SZ 16 ++#define PHY_NOISE_GLITCH_INIT_MA 10 ++#define PHY_NOISE_GLITCH_INIT_MA_BADPlCP 10 ++#define PHY_NOISE_STATE_MON 0x1 ++#define PHY_NOISE_STATE_EXTERNAL 0x2 ++#define PHY_NOISE_SAMPLE_LOG_NUM_NPHY 10 ++#define PHY_NOISE_SAMPLE_LOG_NUM_UCODE 9 ++ ++#define PHY_NOISE_OFFSETFACT_4322 (-103) ++#define PHY_NOISE_MA_WINDOW_SZ 2 ++ ++#define PHY_RSSI_TABLE_SIZE 64 ++#define RSSI_ANT_MERGE_MAX 0 ++#define RSSI_ANT_MERGE_MIN 1 ++#define RSSI_ANT_MERGE_AVG 2 ++ ++#define PHY_TSSI_TABLE_SIZE 64 ++#define APHY_TSSI_TABLE_SIZE 256 ++#define TX_GAIN_TABLE_LENGTH 64 ++#define DEFAULT_11A_TXP_IDX 24 ++#define NUM_TSSI_FRAMES 4 ++#define NULL_TSSI 0x7f ++#define NULL_TSSI_W 0x7f7f ++ ++#define PHY_PAPD_EPS_TBL_SIZE_LCNPHY 64 ++ ++#define LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL 9 ++ ++#define PHY_TXPWR_MIN 10 ++#define PHY_TXPWR_MIN_NPHY 8 ++#define RADIOPWR_OVERRIDE_DEF (-1) ++ ++#define PWRTBL_NUM_COEFF 3 ++ ++#define SPURAVOID_DISABLE 0 ++#define SPURAVOID_AUTO 1 ++#define SPURAVOID_FORCEON 2 ++#define SPURAVOID_FORCEON2 3 ++ ++#define PHY_SW_TIMER_FAST 15 ++#define PHY_SW_TIMER_SLOW 60 ++#define PHY_SW_TIMER_GLACIAL 120 ++ ++#define PHY_PERICAL_AUTO 0 ++#define PHY_PERICAL_FULL 1 ++#define PHY_PERICAL_PARTIAL 2 ++ ++#define PHY_PERICAL_NODELAY 0 ++#define PHY_PERICAL_INIT_DELAY 5 ++#define PHY_PERICAL_ASSOC_DELAY 5 ++#define PHY_PERICAL_WDOG_DELAY 5 ++ ++#define MPHASE_TXCAL_NUMCMDS 2 ++ ++#define PHY_PERICAL_MPHASE_PENDING(pi) \ ++ (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_IDLE) ++ ++enum { ++ MPHASE_CAL_STATE_IDLE = 0, ++ MPHASE_CAL_STATE_INIT = 1, ++ MPHASE_CAL_STATE_TXPHASE0, ++ MPHASE_CAL_STATE_TXPHASE1, ++ MPHASE_CAL_STATE_TXPHASE2, ++ MPHASE_CAL_STATE_TXPHASE3, ++ MPHASE_CAL_STATE_TXPHASE4, ++ MPHASE_CAL_STATE_TXPHASE5, ++ MPHASE_CAL_STATE_PAPDCAL, ++ MPHASE_CAL_STATE_RXCAL, ++ MPHASE_CAL_STATE_RSSICAL, ++ MPHASE_CAL_STATE_IDLETSSI ++}; ++ ++enum phy_cal_mode { ++ CAL_FULL, ++ CAL_RECAL, ++ CAL_CURRECAL, ++ CAL_DIGCAL, ++ CAL_GCTRL, ++ CAL_SOFT, ++ CAL_DIGLO ++}; ++ ++#define RDR_NTIERS 1 ++#define RDR_TIER_SIZE 64 ++#define RDR_LIST_SIZE (512/3) ++#define RDR_EPOCH_SIZE 40 ++#define RDR_NANTENNAS 2 ++#define RDR_NTIER_SIZE RDR_LIST_SIZE ++#define RDR_LP_BUFFER_SIZE 64 ++#define LP_LEN_HIS_SIZE 10 ++ ++#define STATIC_NUM_RF 32 ++#define STATIC_NUM_BB 9 ++ ++#define BB_MULT_MASK 0x0000ffff ++#define BB_MULT_VALID_MASK 0x80000000 ++ ++#define CORDIC_AG 39797 ++#define CORDIC_NI 18 ++#define FIXED(X) ((s32)((X) << 16)) ++ ++#define FLOAT(X) \ ++ (((X) >= 0) ? ((((X) >> 15) + 1) >> 1) : -((((-(X)) >> 15) + 1) >> 1)) ++ ++#define PHY_CHAIN_TX_DISABLE_TEMP 115 ++#define PHY_HYSTERESIS_DELTATEMP 5 ++ ++#define SCAN_INPROG_PHY(pi) \ ++ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN)) ++ ++#define PLT_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_PLT)) ++ ++#define ASSOC_INPROG_PHY(pi) \ ++ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_ASSOC)) ++ ++#define SCAN_RM_IN_PROGRESS(pi) \ ++ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN | PHY_HOLD_FOR_RM)) ++ ++#define PHY_MUTED(pi) \ ++ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_MUTE)) ++ ++#define PUB_NOT_ASSOC(pi) \ ++ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_NOT_ASSOC)) ++ ++struct phy_table_info { ++ uint table; ++ int q; ++ uint max; ++}; ++ ++struct phytbl_info { ++ const void *tbl_ptr; ++ u32 tbl_len; ++ u32 tbl_id; ++ u32 tbl_offset; ++ u32 tbl_width; ++}; ++ ++struct interference_info { ++ u8 curr_home_channel; ++ u16 crsminpwrthld_40_stored; ++ u16 crsminpwrthld_20L_stored; ++ u16 crsminpwrthld_20U_stored; ++ u16 init_gain_code_core1_stored; ++ u16 init_gain_code_core2_stored; ++ u16 init_gain_codeb_core1_stored; ++ u16 init_gain_codeb_core2_stored; ++ u16 init_gain_table_stored[4]; ++ ++ u16 clip1_hi_gain_code_core1_stored; ++ u16 clip1_hi_gain_code_core2_stored; ++ u16 clip1_hi_gain_codeb_core1_stored; ++ u16 clip1_hi_gain_codeb_core2_stored; ++ u16 nb_clip_thresh_core1_stored; ++ u16 nb_clip_thresh_core2_stored; ++ u16 init_ofdmlna2gainchange_stored[4]; ++ u16 init_ccklna2gainchange_stored[4]; ++ u16 clip1_lo_gain_code_core1_stored; ++ u16 clip1_lo_gain_code_core2_stored; ++ u16 clip1_lo_gain_codeb_core1_stored; ++ u16 clip1_lo_gain_codeb_core2_stored; ++ u16 w1_clip_thresh_core1_stored; ++ u16 w1_clip_thresh_core2_stored; ++ u16 radio_2056_core1_rssi_gain_stored; ++ u16 radio_2056_core2_rssi_gain_stored; ++ u16 energy_drop_timeout_len_stored; ++ ++ u16 ed_crs40_assertthld0_stored; ++ u16 ed_crs40_assertthld1_stored; ++ u16 ed_crs40_deassertthld0_stored; ++ u16 ed_crs40_deassertthld1_stored; ++ u16 ed_crs20L_assertthld0_stored; ++ u16 ed_crs20L_assertthld1_stored; ++ u16 ed_crs20L_deassertthld0_stored; ++ u16 ed_crs20L_deassertthld1_stored; ++ u16 ed_crs20U_assertthld0_stored; ++ u16 ed_crs20U_assertthld1_stored; ++ u16 ed_crs20U_deassertthld0_stored; ++ u16 ed_crs20U_deassertthld1_stored; ++ ++ u16 badplcp_ma; ++ u16 badplcp_ma_previous; ++ u16 badplcp_ma_total; ++ u16 badplcp_ma_list[MA_WINDOW_SZ]; ++ int badplcp_ma_index; ++ s16 pre_badplcp_cnt; ++ s16 bphy_pre_badplcp_cnt; ++ ++ u16 init_gain_core1; ++ u16 init_gain_core2; ++ u16 init_gainb_core1; ++ u16 init_gainb_core2; ++ u16 init_gain_rfseq[4]; ++ ++ u16 crsminpwr0; ++ u16 crsminpwrl0; ++ u16 crsminpwru0; ++ ++ s16 crsminpwr_index; ++ ++ u16 radio_2057_core1_rssi_wb1a_gc_stored; ++ u16 radio_2057_core2_rssi_wb1a_gc_stored; ++ u16 radio_2057_core1_rssi_wb1g_gc_stored; ++ u16 radio_2057_core2_rssi_wb1g_gc_stored; ++ u16 radio_2057_core1_rssi_wb2_gc_stored; ++ u16 radio_2057_core2_rssi_wb2_gc_stored; ++ u16 radio_2057_core1_rssi_nb_gc_stored; ++ u16 radio_2057_core2_rssi_nb_gc_stored; ++}; ++ ++struct aci_save_gphy { ++ u16 rc_cal_ovr; ++ u16 phycrsth1; ++ u16 phycrsth2; ++ u16 init_n1p1_gain; ++ u16 p1_p2_gain; ++ u16 n1_n2_gain; ++ u16 n1_p1_gain; ++ u16 div_search_gain; ++ u16 div_p1_p2_gain; ++ u16 div_search_gn_change; ++ u16 table_7_2; ++ u16 table_7_3; ++ u16 cckshbits_gnref; ++ u16 clip_thresh; ++ u16 clip2_thresh; ++ u16 clip3_thresh; ++ u16 clip_p2_thresh; ++ u16 clip_pwdn_thresh; ++ u16 clip_n1p1_thresh; ++ u16 clip_n1_pwdn_thresh; ++ u16 bbconfig; ++ u16 cthr_sthr_shdin; ++ u16 energy; ++ u16 clip_p1_p2_thresh; ++ u16 threshold; ++ u16 reg15; ++ u16 reg16; ++ u16 reg17; ++ u16 div_srch_idx; ++ u16 div_srch_p1_p2; ++ u16 div_srch_gn_back; ++ u16 ant_dwell; ++ u16 ant_wr_settle; ++}; ++ ++struct lo_complex_abgphy_info { ++ s8 i; ++ s8 q; ++}; ++ ++struct nphy_iq_comp { ++ s16 a0; ++ s16 b0; ++ s16 a1; ++ s16 b1; ++}; ++ ++struct nphy_txpwrindex { ++ s8 index; ++ s8 index_internal; ++ s8 index_internal_save; ++ u16 AfectrlOverride; ++ u16 AfeCtrlDacGain; ++ u16 rad_gain; ++ u8 bbmult; ++ u16 iqcomp_a; ++ u16 iqcomp_b; ++ u16 locomp; ++}; ++ ++struct txiqcal_cache { ++ ++ u16 txcal_coeffs_2G[8]; ++ u16 txcal_radio_regs_2G[8]; ++ struct nphy_iq_comp rxcal_coeffs_2G; ++ ++ u16 txcal_coeffs_5G[8]; ++ u16 txcal_radio_regs_5G[8]; ++ struct nphy_iq_comp rxcal_coeffs_5G; ++}; ++ ++struct nphy_pwrctrl { ++ s8 max_pwr_2g; ++ s8 idle_targ_2g; ++ s16 pwrdet_2g_a1; ++ s16 pwrdet_2g_b0; ++ s16 pwrdet_2g_b1; ++ s8 max_pwr_5gm; ++ s8 idle_targ_5gm; ++ s8 max_pwr_5gh; ++ s8 max_pwr_5gl; ++ s16 pwrdet_5gm_a1; ++ s16 pwrdet_5gm_b0; ++ s16 pwrdet_5gm_b1; ++ s16 pwrdet_5gl_a1; ++ s16 pwrdet_5gl_b0; ++ s16 pwrdet_5gl_b1; ++ s16 pwrdet_5gh_a1; ++ s16 pwrdet_5gh_b0; ++ s16 pwrdet_5gh_b1; ++ s8 idle_targ_5gl; ++ s8 idle_targ_5gh; ++ s8 idle_tssi_2g; ++ s8 idle_tssi_5g; ++ s8 idle_tssi; ++ s16 a1; ++ s16 b0; ++ s16 b1; ++}; ++ ++struct nphy_txgains { ++ u16 txlpf[2]; ++ u16 txgm[2]; ++ u16 pga[2]; ++ u16 pad[2]; ++ u16 ipa[2]; ++}; ++ ++#define PHY_NOISEVAR_BUFSIZE 10 ++ ++struct nphy_noisevar_buf { ++ int bufcount; ++ int tone_id[PHY_NOISEVAR_BUFSIZE]; ++ u32 noise_vars[PHY_NOISEVAR_BUFSIZE]; ++ u32 min_noise_vars[PHY_NOISEVAR_BUFSIZE]; ++}; ++ ++struct rssical_cache { ++ u16 rssical_radio_regs_2G[2]; ++ u16 rssical_phyregs_2G[12]; ++ ++ u16 rssical_radio_regs_5G[2]; ++ u16 rssical_phyregs_5G[12]; ++}; ++ ++struct lcnphy_cal_results { ++ ++ u16 txiqlocal_a; ++ u16 txiqlocal_b; ++ u16 txiqlocal_didq; ++ u8 txiqlocal_ei0; ++ u8 txiqlocal_eq0; ++ u8 txiqlocal_fi0; ++ u8 txiqlocal_fq0; ++ ++ u16 txiqlocal_bestcoeffs[11]; ++ u16 txiqlocal_bestcoeffs_valid; ++ ++ u32 papd_eps_tbl[PHY_PAPD_EPS_TBL_SIZE_LCNPHY]; ++ u16 analog_gain_ref; ++ u16 lut_begin; ++ u16 lut_end; ++ u16 lut_step; ++ u16 rxcompdbm; ++ u16 papdctrl; ++ u16 sslpnCalibClkEnCtrl; ++ ++ u16 rxiqcal_coeff_a0; ++ u16 rxiqcal_coeff_b0; ++}; ++ ++struct shared_phy { ++ struct brcms_phy *phy_head; ++ uint unit; ++ struct si_pub *sih; ++ struct phy_shim_info *physhim; ++ uint corerev; ++ u32 machwcap; ++ bool up; ++ bool clk; ++ uint now; ++ u16 vid; ++ u16 did; ++ uint chip; ++ uint chiprev; ++ uint chippkg; ++ uint sromrev; ++ uint boardtype; ++ uint boardrev; ++ uint boardvendor; ++ u32 boardflags; ++ u32 boardflags2; ++ uint buscorerev; ++ uint fast_timer; ++ uint slow_timer; ++ uint glacial_timer; ++ u8 rx_antdiv; ++ s8 phy_noise_window[MA_WINDOW_SZ]; ++ uint phy_noise_index; ++ u8 hw_phytxchain; ++ u8 hw_phyrxchain; ++ u8 phytxchain; ++ u8 phyrxchain; ++ u8 rssi_mode; ++ bool _rifs_phy; ++}; ++ ++struct brcms_phy_pub { ++ uint phy_type; ++ uint phy_rev; ++ u8 phy_corenum; ++ u16 radioid; ++ u8 radiorev; ++ u8 radiover; ++ ++ uint coreflags; ++ uint ana_rev; ++ bool abgphy_encore; ++}; ++ ++struct phy_func_ptr { ++ void (*init)(struct brcms_phy *); ++ void (*calinit)(struct brcms_phy *); ++ void (*chanset)(struct brcms_phy *, u16 chanspec); ++ void (*txpwrrecalc)(struct brcms_phy *); ++ int (*longtrn)(struct brcms_phy *, int); ++ void (*txiqccget)(struct brcms_phy *, u16 *, u16 *); ++ void (*txiqccset)(struct brcms_phy *, u16, u16); ++ u16 (*txloccget)(struct brcms_phy *); ++ void (*radioloftget)(struct brcms_phy *, u8 *, u8 *, u8 *, u8 *); ++ void (*carrsuppr)(struct brcms_phy *); ++ s32 (*rxsigpwr)(struct brcms_phy *, s32); ++ void (*detach)(struct brcms_phy *); ++}; ++ ++struct brcms_phy { ++ struct brcms_phy_pub pubpi_ro; ++ struct shared_phy *sh; ++ struct phy_func_ptr pi_fptr; ++ ++ union { ++ struct brcms_phy_lcnphy *pi_lcnphy; ++ } u; ++ bool user_txpwr_at_rfport; ++ ++ struct d11regs __iomem *regs; ++ struct brcms_phy *next; ++ struct brcms_phy_pub pubpi; ++ ++ bool do_initcal; ++ bool phytest_on; ++ bool ofdm_rateset_war; ++ bool bf_preempt_4306; ++ u16 radio_chanspec; ++ u8 antsel_type; ++ u16 bw; ++ u8 txpwr_percent; ++ bool phy_init_por; ++ ++ bool init_in_progress; ++ bool initialized; ++ bool sbtml_gm; ++ uint refcnt; ++ bool watchdog_override; ++ u8 phynoise_state; ++ uint phynoise_now; ++ int phynoise_chan_watchdog; ++ bool phynoise_polling; ++ bool disable_percal; ++ u32 measure_hold; ++ ++ s16 txpa_2g[PWRTBL_NUM_COEFF]; ++ s16 txpa_2g_low_temp[PWRTBL_NUM_COEFF]; ++ s16 txpa_2g_high_temp[PWRTBL_NUM_COEFF]; ++ s16 txpa_5g_low[PWRTBL_NUM_COEFF]; ++ s16 txpa_5g_mid[PWRTBL_NUM_COEFF]; ++ s16 txpa_5g_hi[PWRTBL_NUM_COEFF]; ++ ++ u8 tx_srom_max_2g; ++ u8 tx_srom_max_5g_low; ++ u8 tx_srom_max_5g_mid; ++ u8 tx_srom_max_5g_hi; ++ u8 tx_srom_max_rate_2g[TXP_NUM_RATES]; ++ u8 tx_srom_max_rate_5g_low[TXP_NUM_RATES]; ++ u8 tx_srom_max_rate_5g_mid[TXP_NUM_RATES]; ++ u8 tx_srom_max_rate_5g_hi[TXP_NUM_RATES]; ++ u8 tx_user_target[TXP_NUM_RATES]; ++ s8 tx_power_offset[TXP_NUM_RATES]; ++ u8 tx_power_target[TXP_NUM_RATES]; ++ ++ struct brcms_phy_srom_fem srom_fem2g; ++ struct brcms_phy_srom_fem srom_fem5g; ++ ++ u8 tx_power_max; ++ u8 tx_power_max_rate_ind; ++ bool hwpwrctrl; ++ u8 nphy_txpwrctrl; ++ s8 nphy_txrx_chain; ++ bool phy_5g_pwrgain; ++ ++ u16 phy_wreg; ++ u16 phy_wreg_limit; ++ ++ s8 n_preamble_override; ++ u8 antswitch; ++ u8 aa2g, aa5g; ++ ++ s8 idle_tssi[CH_5G_GROUP]; ++ s8 target_idle_tssi; ++ s8 txpwr_est_Pout; ++ u8 tx_power_min; ++ u8 txpwr_limit[TXP_NUM_RATES]; ++ u8 txpwr_env_limit[TXP_NUM_RATES]; ++ u8 adj_pwr_tbl_nphy[ADJ_PWR_TBL_LEN]; ++ ++ bool channel_14_wide_filter; ++ ++ bool txpwroverride; ++ bool txpwridx_override_aphy; ++ s16 radiopwr_override; ++ u16 hwpwr_txcur; ++ u8 saved_txpwr_idx; ++ ++ bool edcrs_threshold_lock; ++ ++ u32 tr_R_gain_val; ++ u32 tr_T_gain_val; ++ ++ s16 ofdm_analog_filt_bw_override; ++ s16 cck_analog_filt_bw_override; ++ s16 ofdm_rccal_override; ++ s16 cck_rccal_override; ++ u16 extlna_type; ++ ++ uint interference_mode_crs_time; ++ u16 crsglitch_prev; ++ bool interference_mode_crs; ++ ++ u32 phy_tx_tone_freq; ++ uint phy_lastcal; ++ bool phy_forcecal; ++ bool phy_fixed_noise; ++ u32 xtalfreq; ++ u8 pdiv; ++ s8 carrier_suppr_disable; ++ ++ bool phy_bphy_evm; ++ bool phy_bphy_rfcs; ++ s8 phy_scraminit; ++ u8 phy_gpiosel; ++ ++ s16 phy_txcore_disable_temp; ++ s16 phy_txcore_enable_temp; ++ s8 phy_tempsense_offset; ++ bool phy_txcore_heatedup; ++ ++ u16 radiopwr; ++ u16 bb_atten; ++ u16 txctl1; ++ ++ u16 mintxbias; ++ u16 mintxmag; ++ struct lo_complex_abgphy_info gphy_locomp_iq ++ [STATIC_NUM_RF][STATIC_NUM_BB]; ++ s8 stats_11b_txpower[STATIC_NUM_RF][STATIC_NUM_BB]; ++ u16 gain_table[TX_GAIN_TABLE_LENGTH]; ++ bool loopback_gain; ++ s16 max_lpback_gain_hdB; ++ s16 trsw_rx_gain_hdB; ++ u8 power_vec[8]; ++ ++ u16 rc_cal; ++ int nrssi_table_delta; ++ int nrssi_slope_scale; ++ int nrssi_slope_offset; ++ int min_rssi; ++ int max_rssi; ++ ++ s8 txpwridx; ++ u8 min_txpower; ++ ++ u8 a_band_high_disable; ++ ++ u16 tx_vos; ++ u16 global_tx_bb_dc_bias_loft; ++ ++ int rf_max; ++ int bb_max; ++ int rf_list_size; ++ int bb_list_size; ++ u16 *rf_attn_list; ++ u16 *bb_attn_list; ++ u16 padmix_mask; ++ u16 padmix_reg; ++ u16 *txmag_list; ++ uint txmag_len; ++ bool txmag_enable; ++ ++ s8 *a_tssi_to_dbm; ++ s8 *m_tssi_to_dbm; ++ s8 *l_tssi_to_dbm; ++ s8 *h_tssi_to_dbm; ++ u8 *hwtxpwr; ++ ++ u16 freqtrack_saved_regs[2]; ++ int cur_interference_mode; ++ bool hwpwrctrl_capable; ++ bool temppwrctrl_capable; ++ ++ uint phycal_nslope; ++ uint phycal_noffset; ++ uint phycal_mlo; ++ uint phycal_txpower; ++ ++ u8 phy_aa2g; ++ ++ bool nphy_tableloaded; ++ s8 nphy_rssisel; ++ u32 nphy_bb_mult_save; ++ u16 nphy_txiqlocal_bestc[11]; ++ bool nphy_txiqlocal_coeffsvalid; ++ struct nphy_txpwrindex nphy_txpwrindex[PHY_CORE_NUM_2]; ++ struct nphy_pwrctrl nphy_pwrctrl_info[PHY_CORE_NUM_2]; ++ u16 cck2gpo; ++ u32 ofdm2gpo; ++ u32 ofdm5gpo; ++ u32 ofdm5glpo; ++ u32 ofdm5ghpo; ++ u8 bw402gpo; ++ u8 bw405gpo; ++ u8 bw405glpo; ++ u8 bw405ghpo; ++ u8 cdd2gpo; ++ u8 cdd5gpo; ++ u8 cdd5glpo; ++ u8 cdd5ghpo; ++ u8 stbc2gpo; ++ u8 stbc5gpo; ++ u8 stbc5glpo; ++ u8 stbc5ghpo; ++ u8 bwdup2gpo; ++ u8 bwdup5gpo; ++ u8 bwdup5glpo; ++ u8 bwdup5ghpo; ++ u16 mcs2gpo[8]; ++ u16 mcs5gpo[8]; ++ u16 mcs5glpo[8]; ++ u16 mcs5ghpo[8]; ++ u32 nphy_rxcalparams; ++ ++ u8 phy_spuravoid; ++ bool phy_isspuravoid; ++ ++ u8 phy_pabias; ++ u8 nphy_papd_skip; ++ u8 nphy_tssi_slope; ++ ++ s16 nphy_noise_win[PHY_CORE_MAX][PHY_NOISE_WINDOW_SZ]; ++ u8 nphy_noise_index; ++ ++ u8 nphy_txpid2g[PHY_CORE_NUM_2]; ++ u8 nphy_txpid5g[PHY_CORE_NUM_2]; ++ u8 nphy_txpid5gl[PHY_CORE_NUM_2]; ++ u8 nphy_txpid5gh[PHY_CORE_NUM_2]; ++ ++ bool nphy_gain_boost; ++ bool nphy_elna_gain_config; ++ u16 old_bphy_test; ++ u16 old_bphy_testcontrol; ++ ++ bool phyhang_avoid; ++ ++ bool rssical_nphy; ++ u8 nphy_perical; ++ uint nphy_perical_last; ++ u8 cal_type_override; ++ u8 mphase_cal_phase_id; ++ u8 mphase_txcal_cmdidx; ++ u8 mphase_txcal_numcmds; ++ u16 mphase_txcal_bestcoeffs[11]; ++ u16 nphy_txiqlocal_chanspec; ++ u16 nphy_iqcal_chanspec_2G; ++ u16 nphy_iqcal_chanspec_5G; ++ u16 nphy_rssical_chanspec_2G; ++ u16 nphy_rssical_chanspec_5G; ++ struct wlapi_timer *phycal_timer; ++ bool use_int_tx_iqlo_cal_nphy; ++ bool internal_tx_iqlo_cal_tapoff_intpa_nphy; ++ s16 nphy_lastcal_temp; ++ ++ struct txiqcal_cache calibration_cache; ++ struct rssical_cache rssical_cache; ++ ++ u8 nphy_txpwr_idx[2]; ++ u8 nphy_papd_cal_type; ++ uint nphy_papd_last_cal; ++ u16 nphy_papd_tx_gain_at_last_cal[2]; ++ u8 nphy_papd_cal_gain_index[2]; ++ s16 nphy_papd_epsilon_offset[2]; ++ bool nphy_papd_recal_enable; ++ u32 nphy_papd_recal_counter; ++ bool nphy_force_papd_cal; ++ bool nphy_papdcomp; ++ bool ipa2g_on; ++ bool ipa5g_on; ++ ++ u16 classifier_state; ++ u16 clip_state[2]; ++ uint nphy_deaf_count; ++ u8 rxiq_samps; ++ u8 rxiq_antsel; ++ ++ u16 rfctrlIntc1_save; ++ u16 rfctrlIntc2_save; ++ bool first_cal_after_assoc; ++ u16 tx_rx_cal_radio_saveregs[22]; ++ u16 tx_rx_cal_phy_saveregs[15]; ++ ++ u8 nphy_cal_orig_pwr_idx[2]; ++ u8 nphy_txcal_pwr_idx[2]; ++ u8 nphy_rxcal_pwr_idx[2]; ++ u16 nphy_cal_orig_tx_gain[2]; ++ struct nphy_txgains nphy_cal_target_gain; ++ u16 nphy_txcal_bbmult; ++ u16 nphy_gmval; ++ ++ u16 nphy_saved_bbconf; ++ ++ bool nphy_gband_spurwar_en; ++ bool nphy_gband_spurwar2_en; ++ bool nphy_aband_spurwar_en; ++ u16 nphy_rccal_value; ++ u16 nphy_crsminpwr[3]; ++ struct nphy_noisevar_buf nphy_saved_noisevars; ++ bool nphy_anarxlpf_adjusted; ++ bool nphy_crsminpwr_adjusted; ++ bool nphy_noisevars_adjusted; ++ ++ bool nphy_rxcal_active; ++ u16 radar_percal_mask; ++ bool dfs_lp_buffer_nphy; ++ ++ u16 nphy_fineclockgatecontrol; ++ ++ s8 rx2tx_biasentry; ++ ++ u16 crsminpwr0; ++ u16 crsminpwrl0; ++ u16 crsminpwru0; ++ s16 noise_crsminpwr_index; ++ u16 init_gain_core1; ++ u16 init_gain_core2; ++ u16 init_gainb_core1; ++ u16 init_gainb_core2; ++ u8 aci_noise_curr_channel; ++ u16 init_gain_rfseq[4]; ++ ++ bool radio_is_on; ++ ++ bool nphy_sample_play_lpf_bw_ctl_ovr; ++ ++ u16 tbl_data_hi; ++ u16 tbl_data_lo; ++ u16 tbl_addr; ++ ++ uint tbl_save_id; ++ uint tbl_save_offset; ++ ++ u8 txpwrctrl; ++ s8 txpwrindex[PHY_CORE_MAX]; ++ ++ u8 phycal_tempdelta; ++ u32 mcs20_po; ++ u32 mcs40_po; ++ struct wiphy *wiphy; ++}; ++ ++struct cs32 { ++ s32 q; ++ s32 i; ++}; ++ ++struct radio_regs { ++ u16 address; ++ u32 init_a; ++ u32 init_g; ++ u8 do_init_a; ++ u8 do_init_g; ++}; ++ ++struct radio_20xx_regs { ++ u16 address; ++ u8 init; ++ u8 do_init; ++}; ++ ++struct lcnphy_radio_regs { ++ u16 address; ++ u8 init_a; ++ u8 init_g; ++ u8 do_init_a; ++ u8 do_init_g; ++}; ++ ++extern u16 read_phy_reg(struct brcms_phy *pi, u16 addr); ++extern void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val); ++extern void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val); ++extern void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val); ++extern void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val); ++ ++extern u16 read_radio_reg(struct brcms_phy *pi, u16 addr); ++extern void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val); ++extern void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val); ++extern void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, ++ u16 val); ++extern void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask); ++ ++extern void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val); ++ ++extern void wlc_phyreg_enter(struct brcms_phy_pub *pih); ++extern void wlc_phyreg_exit(struct brcms_phy_pub *pih); ++extern void wlc_radioreg_enter(struct brcms_phy_pub *pih); ++extern void wlc_radioreg_exit(struct brcms_phy_pub *pih); ++ ++extern void wlc_phy_read_table(struct brcms_phy *pi, ++ const struct phytbl_info *ptbl_info, ++ u16 tblAddr, u16 tblDataHi, ++ u16 tblDatalo); ++extern void wlc_phy_write_table(struct brcms_phy *pi, ++ const struct phytbl_info *ptbl_info, ++ u16 tblAddr, u16 tblDataHi, u16 tblDatalo); ++extern void wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, ++ uint tbl_offset, u16 tblAddr, u16 tblDataHi, ++ u16 tblDataLo); ++extern void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val); ++ ++extern void write_phy_channel_reg(struct brcms_phy *pi, uint val); ++extern void wlc_phy_txpower_update_shm(struct brcms_phy *pi); ++ ++extern u8 wlc_phy_nbits(s32 value); ++extern void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_dB, u8 core); ++ ++extern uint wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi, ++ struct radio_20xx_regs *radioregs); ++extern uint wlc_phy_init_radio_regs(struct brcms_phy *pi, ++ const struct radio_regs *radioregs, ++ u16 core_offset); ++ ++extern void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi); ++ ++extern void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on); ++extern void wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, ++ s32 *eps_imag); ++ ++extern void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi); ++extern void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi); ++ ++extern bool wlc_phy_attach_nphy(struct brcms_phy *pi); ++extern bool wlc_phy_attach_lcnphy(struct brcms_phy *pi); ++ ++extern void wlc_phy_detach_lcnphy(struct brcms_phy *pi); ++ ++extern void wlc_phy_init_nphy(struct brcms_phy *pi); ++extern void wlc_phy_init_lcnphy(struct brcms_phy *pi); ++ ++extern void wlc_phy_cal_init_nphy(struct brcms_phy *pi); ++extern void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi); ++ ++extern void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, ++ u16 chanspec); ++extern void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, ++ u16 chanspec); ++extern void wlc_phy_chanspec_set_fixup_lcnphy(struct brcms_phy *pi, ++ u16 chanspec); ++extern int wlc_phy_channel2freq(uint channel); ++extern int wlc_phy_chanspec_freq2bandrange_lpssn(uint); ++extern int wlc_phy_chanspec_bandrange_get(struct brcms_phy *, u16 chanspec); ++ ++extern void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode); ++extern s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi); ++ ++extern void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi); ++extern void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi); ++extern void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi); ++ ++extern void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index); ++extern void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable); ++extern void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi); ++extern void wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, ++ u16 max_val, bool iqcalmode); ++ ++extern void wlc_phy_txpower_sromlimit_get_nphy(struct brcms_phy *pi, uint chan, ++ u8 *max_pwr, u8 rate_id); ++extern void wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start, ++ u8 rate_mcs_end, ++ u8 rate_ofdm_start); ++extern void wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power, ++ u8 rate_ofdm_start, ++ u8 rate_ofdm_end, ++ u8 rate_mcs_start); ++ ++extern u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode); ++extern s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode); ++extern s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode); ++extern s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode); ++extern void wlc_phy_carrier_suppress_lcnphy(struct brcms_phy *pi); ++extern void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel); ++extern void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode); ++extern void wlc_2064_vco_cal(struct brcms_phy *pi); ++ ++extern void wlc_phy_txpower_recalc_target(struct brcms_phy *pi); ++ ++#define LCNPHY_TBL_ID_PAPDCOMPDELTATBL 0x18 ++#define LCNPHY_TX_POWER_TABLE_SIZE 128 ++#define LCNPHY_MAX_TX_POWER_INDEX (LCNPHY_TX_POWER_TABLE_SIZE - 1) ++#define LCNPHY_TBL_ID_TXPWRCTL 0x07 ++#define LCNPHY_TX_PWR_CTRL_OFF 0 ++#define LCNPHY_TX_PWR_CTRL_SW (0x1 << 15) ++#define LCNPHY_TX_PWR_CTRL_HW ((0x1 << 15) | \ ++ (0x1 << 14) | \ ++ (0x1 << 13)) ++ ++#define LCNPHY_TX_PWR_CTRL_TEMPBASED 0xE001 ++ ++extern void wlc_lcnphy_write_table(struct brcms_phy *pi, ++ const struct phytbl_info *pti); ++extern void wlc_lcnphy_read_table(struct brcms_phy *pi, ++ struct phytbl_info *pti); ++extern void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b); ++extern void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq); ++extern void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b); ++extern u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi); ++extern void wlc_lcnphy_get_radio_loft(struct brcms_phy *pi, u8 *ei0, ++ u8 *eq0, u8 *fi0, u8 *fq0); ++extern void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode); ++extern void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode); ++extern bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi); ++extern void wlc_lcnphy_tx_pwr_update_npt(struct brcms_phy *pi); ++extern s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1); ++extern void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, ++ s8 *cck_pwr); ++extern void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi); ++ ++extern s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index); ++ ++#define NPHY_MAX_HPVGA1_INDEX 10 ++#define NPHY_DEF_HPVGA1_INDEXLIMIT 7 ++ ++struct phy_iq_est { ++ s32 iq_prod; ++ u32 i_pwr; ++ u32 q_pwr; ++}; ++ ++extern void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi, ++ bool enable); ++extern void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode); ++ ++#define wlc_phy_write_table_nphy(pi, pti) \ ++ wlc_phy_write_table(pi, pti, 0x72, 0x74, 0x73) ++ ++#define wlc_phy_read_table_nphy(pi, pti) \ ++ wlc_phy_read_table(pi, pti, 0x72, 0x74, 0x73) ++ ++#define wlc_nphy_table_addr(pi, id, off) \ ++ wlc_phy_table_addr((pi), (id), (off), 0x72, 0x74, 0x73) ++ ++#define wlc_nphy_table_data_write(pi, w, v) \ ++ wlc_phy_table_data_write((pi), (w), (v)) ++ ++extern void wlc_phy_table_read_nphy(struct brcms_phy *pi, u32, u32 l, u32 o, ++ u32 w, void *d); ++extern void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32, ++ u32, const void *); ++ ++#define PHY_IPA(pi) \ ++ ((pi->ipa2g_on && CHSPEC_IS2G(pi->radio_chanspec)) || \ ++ (pi->ipa5g_on && CHSPEC_IS5G(pi->radio_chanspec))) ++ ++#define BRCMS_PHY_WAR_PR51571(pi) \ ++ if (NREV_LT((pi)->pubpi.phy_rev, 3)) \ ++ (void)R_REG(&(pi)->regs->maccontrol) ++ ++extern void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype); ++extern void wlc_phy_aci_reset_nphy(struct brcms_phy *pi); ++extern void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en); ++ ++extern u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint chan); ++extern void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on); ++ ++extern void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi); ++ ++extern void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd); ++extern s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi); ++ ++extern u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val); ++ ++extern void wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est, ++ u16 num_samps, u8 wait_time, ++ u8 wait_for_crs); ++ ++extern void wlc_phy_rx_iq_coeffs_nphy(struct brcms_phy *pi, u8 write, ++ struct nphy_iq_comp *comp); ++extern void wlc_phy_aci_and_noise_reduction_nphy(struct brcms_phy *pi); ++ ++extern void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, ++ u8 rxcore_bitmask); ++extern u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih); ++ ++extern void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type); ++extern void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi); ++extern void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi); ++extern void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi); ++extern u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi); ++ ++extern struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi); ++extern int wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, ++ struct nphy_txgains target_gain, ++ bool full, bool m); ++extern int wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi, ++ struct nphy_txgains target_gain, ++ u8 type, bool d); ++extern void wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, ++ s8 txpwrindex, bool res); ++extern void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core, u8 rssi_type); ++extern int wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, ++ s32 *rssi_buf, u8 nsamps); ++extern void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi); ++extern int wlc_phy_aci_scan_nphy(struct brcms_phy *pi); ++extern void wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, ++ s32 dBm_targetpower, bool debug); ++extern int wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, ++ u8 mode, u8, bool); ++extern void wlc_phy_stopplayback_nphy(struct brcms_phy *pi); ++extern void wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, ++ u8 num_samps); ++extern void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi); ++ ++extern int wlc_phy_rssi_compute_nphy(struct brcms_phy *pi, ++ struct d11rxhdr *rxh); ++ ++#define NPHY_TESTPATTERN_BPHY_EVM 0 ++#define NPHY_TESTPATTERN_BPHY_RFCS 1 ++ ++extern void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs); ++ ++void wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, ++ s8 *ofdmoffset); ++extern s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, ++ u16 chanspec); ++ ++extern bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pih); ++#endif /* _BRCM_PHY_INT_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c.orig 2011-11-09 13:46:58.257800483 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c 2011-11-09 13:47:17.012566015 -0500 +@@ -0,0 +1,5154 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include "phy_qmath.h" ++#include "phy_hal.h" ++#include "phy_radio.h" ++#include "phytbl_lcn.h" ++#include "phy_lcn.h" ++ ++#define PLL_2064_NDIV 90 ++#define PLL_2064_LOW_END_VCO 3000 ++#define PLL_2064_LOW_END_KVCO 27 ++#define PLL_2064_HIGH_END_VCO 4200 ++#define PLL_2064_HIGH_END_KVCO 68 ++#define PLL_2064_LOOP_BW_DOUBLER 200 ++#define PLL_2064_D30_DOUBLER 10500 ++#define PLL_2064_LOOP_BW 260 ++#define PLL_2064_D30 8000 ++#define PLL_2064_CAL_REF_TO 8 ++#define PLL_2064_MHZ 1000000 ++#define PLL_2064_OPEN_LOOP_DELAY 5 ++ ++#define TEMPSENSE 1 ++#define VBATSENSE 2 ++ ++#define NOISE_IF_UPD_CHK_INTERVAL 1 ++#define NOISE_IF_UPD_RST_INTERVAL 60 ++#define NOISE_IF_UPD_THRESHOLD_CNT 1 ++#define NOISE_IF_UPD_TRHRESHOLD 50 ++#define NOISE_IF_UPD_TIMEOUT 1000 ++#define NOISE_IF_OFF 0 ++#define NOISE_IF_CHK 1 ++#define NOISE_IF_ON 2 ++ ++#define PAPD_BLANKING_PROFILE 3 ++#define PAPD2LUT 0 ++#define PAPD_CORR_NORM 0 ++#define PAPD_BLANKING_THRESHOLD 0 ++#define PAPD_STOP_AFTER_LAST_UPDATE 0 ++ ++#define LCN_TARGET_PWR 60 ++ ++#define LCN_VBAT_OFFSET_433X 34649679 ++#define LCN_VBAT_SLOPE_433X 8258032 ++ ++#define LCN_VBAT_SCALE_NOM 53 ++#define LCN_VBAT_SCALE_DEN 432 ++ ++#define LCN_TEMPSENSE_OFFSET 80812 ++#define LCN_TEMPSENSE_DEN 2647 ++ ++#define LCN_BW_LMT 200 ++#define LCN_CUR_LMT 1250 ++#define LCN_MULT 1 ++#define LCN_VCO_DIV 30 ++#define LCN_OFFSET 680 ++#define LCN_FACT 490 ++#define LCN_CUR_DIV 2640 ++ ++#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT \ ++ (0 + 8) ++#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK \ ++ (0x7f << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT) ++ ++#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT \ ++ (0 + 8) ++#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK \ ++ (0x7f << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT) ++ ++#define wlc_lcnphy_enable_tx_gain_override(pi) \ ++ wlc_lcnphy_set_tx_gain_override(pi, true) ++#define wlc_lcnphy_disable_tx_gain_override(pi) \ ++ wlc_lcnphy_set_tx_gain_override(pi, false) ++ ++#define wlc_lcnphy_iqcal_active(pi) \ ++ (read_phy_reg((pi), 0x451) & \ ++ ((0x1 << 15) | (0x1 << 14))) ++ ++#define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13)) ++#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \ ++ (pi->temppwrctrl_capable) ++#define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \ ++ (pi->hwpwrctrl_capable) ++ ++#define SWCTRL_BT_TX 0x18 ++#define SWCTRL_OVR_DISABLE 0x40 ++ ++#define AFE_CLK_INIT_MODE_TXRX2X 1 ++#define AFE_CLK_INIT_MODE_PAPD 0 ++ ++#define LCNPHY_TBL_ID_IQLOCAL 0x00 ++ ++#define LCNPHY_TBL_ID_RFSEQ 0x08 ++#define LCNPHY_TBL_ID_GAIN_IDX 0x0d ++#define LCNPHY_TBL_ID_SW_CTRL 0x0f ++#define LCNPHY_TBL_ID_GAIN_TBL 0x12 ++#define LCNPHY_TBL_ID_SPUR 0x14 ++#define LCNPHY_TBL_ID_SAMPLEPLAY 0x15 ++#define LCNPHY_TBL_ID_SAMPLEPLAY1 0x16 ++ ++#define LCNPHY_TX_PWR_CTRL_RATE_OFFSET 832 ++#define LCNPHY_TX_PWR_CTRL_MAC_OFFSET 128 ++#define LCNPHY_TX_PWR_CTRL_GAIN_OFFSET 192 ++#define LCNPHY_TX_PWR_CTRL_IQ_OFFSET 320 ++#define LCNPHY_TX_PWR_CTRL_LO_OFFSET 448 ++#define LCNPHY_TX_PWR_CTRL_PWR_OFFSET 576 ++ ++#define LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313 140 ++ ++#define LCNPHY_TX_PWR_CTRL_START_NPT 1 ++#define LCNPHY_TX_PWR_CTRL_MAX_NPT 7 ++ ++#define LCNPHY_NOISE_SAMPLES_DEFAULT 5000 ++ ++#define LCNPHY_ACI_DETECT_START 1 ++#define LCNPHY_ACI_DETECT_PROGRESS 2 ++#define LCNPHY_ACI_DETECT_STOP 3 ++ ++#define LCNPHY_ACI_CRSHIFRMLO_TRSH 100 ++#define LCNPHY_ACI_GLITCH_TRSH 2000 ++#define LCNPHY_ACI_TMOUT 250 ++#define LCNPHY_ACI_DETECT_TIMEOUT 2 ++#define LCNPHY_ACI_START_DELAY 0 ++ ++#define wlc_lcnphy_tx_gain_override_enabled(pi) \ ++ (0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6))) ++ ++#define wlc_lcnphy_total_tx_frames(pi) \ ++ wlapi_bmac_read_shm((pi)->sh->physhim, M_UCODE_MACSTAT + \ ++ offsetof(struct macstat, txallfrm)) ++ ++struct lcnphy_txgains { ++ u16 gm_gain; ++ u16 pga_gain; ++ u16 pad_gain; ++ u16 dac_gain; ++}; ++ ++enum lcnphy_cal_mode { ++ LCNPHY_CAL_FULL, ++ LCNPHY_CAL_RECAL, ++ LCNPHY_CAL_CURRECAL, ++ LCNPHY_CAL_DIGCAL, ++ LCNPHY_CAL_GCTRL ++}; ++ ++struct lcnphy_rx_iqcomp { ++ u8 chan; ++ s16 a; ++ s16 b; ++}; ++ ++struct lcnphy_spb_tone { ++ s16 re; ++ s16 im; ++}; ++ ++struct lcnphy_unsign16_struct { ++ u16 re; ++ u16 im; ++}; ++ ++struct lcnphy_iq_est { ++ u32 iq_prod; ++ u32 i_pwr; ++ u32 q_pwr; ++}; ++ ++struct lcnphy_sfo_cfg { ++ u16 ptcentreTs20; ++ u16 ptcentreFactor; ++}; ++ ++enum lcnphy_papd_cal_type { ++ LCNPHY_PAPD_CAL_CW, ++ LCNPHY_PAPD_CAL_OFDM ++}; ++ ++typedef u16 iqcal_gain_params_lcnphy[9]; ++ ++static const iqcal_gain_params_lcnphy tbl_iqcal_gainparams_lcnphy_2G[] = { ++ {0, 0, 0, 0, 0, 0, 0, 0, 0}, ++}; ++ ++static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = { ++ tbl_iqcal_gainparams_lcnphy_2G, ++}; ++ ++static const u16 iqcal_gainparams_numgains_lcnphy[1] = { ++ sizeof(tbl_iqcal_gainparams_lcnphy_2G) / ++ sizeof(*tbl_iqcal_gainparams_lcnphy_2G), ++}; ++ ++static const struct lcnphy_sfo_cfg lcnphy_sfo_cfg[] = { ++ {965, 1087}, ++ {967, 1085}, ++ {969, 1082}, ++ {971, 1080}, ++ {973, 1078}, ++ {975, 1076}, ++ {977, 1073}, ++ {979, 1071}, ++ {981, 1069}, ++ {983, 1067}, ++ {985, 1065}, ++ {987, 1063}, ++ {989, 1060}, ++ {994, 1055} ++}; ++ ++static const ++u16 lcnphy_iqcal_loft_gainladder[] = { ++ ((2 << 8) | 0), ++ ((3 << 8) | 0), ++ ((4 << 8) | 0), ++ ((6 << 8) | 0), ++ ((8 << 8) | 0), ++ ((11 << 8) | 0), ++ ((16 << 8) | 0), ++ ((16 << 8) | 1), ++ ((16 << 8) | 2), ++ ((16 << 8) | 3), ++ ((16 << 8) | 4), ++ ((16 << 8) | 5), ++ ((16 << 8) | 6), ++ ((16 << 8) | 7), ++ ((23 << 8) | 7), ++ ((32 << 8) | 7), ++ ((45 << 8) | 7), ++ ((64 << 8) | 7), ++ ((91 << 8) | 7), ++ ((128 << 8) | 7) ++}; ++ ++static const ++u16 lcnphy_iqcal_ir_gainladder[] = { ++ ((1 << 8) | 0), ++ ((2 << 8) | 0), ++ ((4 << 8) | 0), ++ ((6 << 8) | 0), ++ ((8 << 8) | 0), ++ ((11 << 8) | 0), ++ ((16 << 8) | 0), ++ ((23 << 8) | 0), ++ ((32 << 8) | 0), ++ ((45 << 8) | 0), ++ ((64 << 8) | 0), ++ ((64 << 8) | 1), ++ ((64 << 8) | 2), ++ ((64 << 8) | 3), ++ ((64 << 8) | 4), ++ ((64 << 8) | 5), ++ ((64 << 8) | 6), ++ ((64 << 8) | 7), ++ ((91 << 8) | 7), ++ ((128 << 8) | 7) ++}; ++ ++static const ++struct lcnphy_spb_tone lcnphy_spb_tone_3750[] = { ++ {88, 0}, ++ {73, 49}, ++ {34, 81}, ++ {-17, 86}, ++ {-62, 62}, ++ {-86, 17}, ++ {-81, -34}, ++ {-49, -73}, ++ {0, -88}, ++ {49, -73}, ++ {81, -34}, ++ {86, 17}, ++ {62, 62}, ++ {17, 86}, ++ {-34, 81}, ++ {-73, 49}, ++ {-88, 0}, ++ {-73, -49}, ++ {-34, -81}, ++ {17, -86}, ++ {62, -62}, ++ {86, -17}, ++ {81, 34}, ++ {49, 73}, ++ {0, 88}, ++ {-49, 73}, ++ {-81, 34}, ++ {-86, -17}, ++ {-62, -62}, ++ {-17, -86}, ++ {34, -81}, ++ {73, -49}, ++}; ++ ++static const ++u16 iqlo_loopback_rf_regs[20] = { ++ RADIO_2064_REG036, ++ RADIO_2064_REG11A, ++ RADIO_2064_REG03A, ++ RADIO_2064_REG025, ++ RADIO_2064_REG028, ++ RADIO_2064_REG005, ++ RADIO_2064_REG112, ++ RADIO_2064_REG0FF, ++ RADIO_2064_REG11F, ++ RADIO_2064_REG00B, ++ RADIO_2064_REG113, ++ RADIO_2064_REG007, ++ RADIO_2064_REG0FC, ++ RADIO_2064_REG0FD, ++ RADIO_2064_REG012, ++ RADIO_2064_REG057, ++ RADIO_2064_REG059, ++ RADIO_2064_REG05C, ++ RADIO_2064_REG078, ++ RADIO_2064_REG092, ++}; ++ ++static const ++u16 tempsense_phy_regs[14] = { ++ 0x503, ++ 0x4a4, ++ 0x4d0, ++ 0x4d9, ++ 0x4da, ++ 0x4a6, ++ 0x938, ++ 0x939, ++ 0x4d8, ++ 0x4d0, ++ 0x4d7, ++ 0x4a5, ++ 0x40d, ++ 0x4a2, ++}; ++ ++static const ++u16 rxiq_cal_rf_reg[11] = { ++ RADIO_2064_REG098, ++ RADIO_2064_REG116, ++ RADIO_2064_REG12C, ++ RADIO_2064_REG06A, ++ RADIO_2064_REG00B, ++ RADIO_2064_REG01B, ++ RADIO_2064_REG113, ++ RADIO_2064_REG01D, ++ RADIO_2064_REG114, ++ RADIO_2064_REG02E, ++ RADIO_2064_REG12A, ++}; ++ ++static const ++struct lcnphy_rx_iqcomp lcnphy_rx_iqcomp_table_rev0[] = { ++ {1, 0, 0}, ++ {2, 0, 0}, ++ {3, 0, 0}, ++ {4, 0, 0}, ++ {5, 0, 0}, ++ {6, 0, 0}, ++ {7, 0, 0}, ++ {8, 0, 0}, ++ {9, 0, 0}, ++ {10, 0, 0}, ++ {11, 0, 0}, ++ {12, 0, 0}, ++ {13, 0, 0}, ++ {14, 0, 0}, ++ {34, 0, 0}, ++ {38, 0, 0}, ++ {42, 0, 0}, ++ {46, 0, 0}, ++ {36, 0, 0}, ++ {40, 0, 0}, ++ {44, 0, 0}, ++ {48, 0, 0}, ++ {52, 0, 0}, ++ {56, 0, 0}, ++ {60, 0, 0}, ++ {64, 0, 0}, ++ {100, 0, 0}, ++ {104, 0, 0}, ++ {108, 0, 0}, ++ {112, 0, 0}, ++ {116, 0, 0}, ++ {120, 0, 0}, ++ {124, 0, 0}, ++ {128, 0, 0}, ++ {132, 0, 0}, ++ {136, 0, 0}, ++ {140, 0, 0}, ++ {149, 0, 0}, ++ {153, 0, 0}, ++ {157, 0, 0}, ++ {161, 0, 0}, ++ {165, 0, 0}, ++ {184, 0, 0}, ++ {188, 0, 0}, ++ {192, 0, 0}, ++ {196, 0, 0}, ++ {200, 0, 0}, ++ {204, 0, 0}, ++ {208, 0, 0}, ++ {212, 0, 0}, ++ {216, 0, 0}, ++}; ++ ++static const u32 lcnphy_23bitgaincode_table[] = { ++ 0x200100, ++ 0x200200, ++ 0x200004, ++ 0x200014, ++ 0x200024, ++ 0x200034, ++ 0x200134, ++ 0x200234, ++ 0x200334, ++ 0x200434, ++ 0x200037, ++ 0x200137, ++ 0x200237, ++ 0x200337, ++ 0x200437, ++ 0x000035, ++ 0x000135, ++ 0x000235, ++ 0x000037, ++ 0x000137, ++ 0x000237, ++ 0x000337, ++ 0x00013f, ++ 0x00023f, ++ 0x00033f, ++ 0x00034f, ++ 0x00044f, ++ 0x00144f, ++ 0x00244f, ++ 0x00254f, ++ 0x00354f, ++ 0x00454f, ++ 0x00464f, ++ 0x01464f, ++ 0x02464f, ++ 0x03464f, ++ 0x04464f, ++}; ++ ++static const s8 lcnphy_gain_table[] = { ++ -16, ++ -13, ++ 10, ++ 7, ++ 4, ++ 0, ++ 3, ++ 6, ++ 9, ++ 12, ++ 15, ++ 18, ++ 21, ++ 24, ++ 27, ++ 30, ++ 33, ++ 36, ++ 39, ++ 42, ++ 45, ++ 48, ++ 50, ++ 53, ++ 56, ++ 59, ++ 62, ++ 65, ++ 68, ++ 71, ++ 74, ++ 77, ++ 80, ++ 83, ++ 86, ++ 89, ++ 92, ++}; ++ ++static const s8 lcnphy_gain_index_offset_for_rssi[] = { ++ 7, ++ 7, ++ 7, ++ 7, ++ 7, ++ 7, ++ 7, ++ 8, ++ 7, ++ 7, ++ 6, ++ 7, ++ 7, ++ 4, ++ 4, ++ 4, ++ 4, ++ 4, ++ 4, ++ 4, ++ 4, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 4, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ -1, ++ -2, ++ -2, ++ -2 ++}; ++ ++struct chan_info_2064_lcnphy { ++ uint chan; ++ uint freq; ++ u8 logen_buftune; ++ u8 logen_rccr_tx; ++ u8 txrf_mix_tune_ctrl; ++ u8 pa_input_tune_g; ++ u8 logen_rccr_rx; ++ u8 pa_rxrf_lna1_freq_tune; ++ u8 pa_rxrf_lna2_freq_tune; ++ u8 rxrf_rxrf_spare1; ++}; ++ ++static const struct chan_info_2064_lcnphy chan_info_2064_lcnphy[] = { ++ {1, 2412, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {2, 2417, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {3, 2422, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {4, 2427, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {5, 2432, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {6, 2437, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {7, 2442, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {8, 2447, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {9, 2452, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {10, 2457, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {11, 2462, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {12, 2467, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {13, 2472, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {14, 2484, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++}; ++ ++static const struct lcnphy_radio_regs lcnphy_radio_regs_2064[] = { ++ {0x00, 0, 0, 0, 0}, ++ {0x01, 0x64, 0x64, 0, 0}, ++ {0x02, 0x20, 0x20, 0, 0}, ++ {0x03, 0x66, 0x66, 0, 0}, ++ {0x04, 0xf8, 0xf8, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0x10, 0x10, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0x37, 0x37, 0, 0}, ++ {0x0B, 0x6, 0x6, 0, 0}, ++ {0x0C, 0x55, 0x55, 0, 0}, ++ {0x0D, 0x8b, 0x8b, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0x5, 0x5, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0xe, 0xe, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0xb, 0xb, 0, 0}, ++ {0x14, 0x2, 0x2, 0, 0}, ++ {0x15, 0x12, 0x12, 0, 0}, ++ {0x16, 0x12, 0x12, 0, 0}, ++ {0x17, 0xc, 0xc, 0, 0}, ++ {0x18, 0xc, 0xc, 0, 0}, ++ {0x19, 0xc, 0xc, 0, 0}, ++ {0x1A, 0x8, 0x8, 0, 0}, ++ {0x1B, 0x2, 0x2, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0x1, 0x1, 0, 0}, ++ {0x1E, 0x12, 0x12, 0, 0}, ++ {0x1F, 0x6e, 0x6e, 0, 0}, ++ {0x20, 0x2, 0x2, 0, 0}, ++ {0x21, 0x23, 0x23, 0, 0}, ++ {0x22, 0x8, 0x8, 0, 0}, ++ {0x23, 0, 0, 0, 0}, ++ {0x24, 0, 0, 0, 0}, ++ {0x25, 0xc, 0xc, 0, 0}, ++ {0x26, 0x33, 0x33, 0, 0}, ++ {0x27, 0x55, 0x55, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0x30, 0x30, 0, 0}, ++ {0x2A, 0xb, 0xb, 0, 0}, ++ {0x2B, 0x1b, 0x1b, 0, 0}, ++ {0x2C, 0x3, 0x3, 0, 0}, ++ {0x2D, 0x1b, 0x1b, 0, 0}, ++ {0x2E, 0, 0, 0, 0}, ++ {0x2F, 0x20, 0x20, 0, 0}, ++ {0x30, 0xa, 0xa, 0, 0}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0x62, 0x62, 0, 0}, ++ {0x33, 0x19, 0x19, 0, 0}, ++ {0x34, 0x33, 0x33, 0, 0}, ++ {0x35, 0x77, 0x77, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0x70, 0x70, 0, 0}, ++ {0x38, 0x3, 0x3, 0, 0}, ++ {0x39, 0xf, 0xf, 0, 0}, ++ {0x3A, 0x6, 0x6, 0, 0}, ++ {0x3B, 0xcf, 0xcf, 0, 0}, ++ {0x3C, 0x1a, 0x1a, 0, 0}, ++ {0x3D, 0x6, 0x6, 0, 0}, ++ {0x3E, 0x42, 0x42, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0xfb, 0xfb, 0, 0}, ++ {0x41, 0x9a, 0x9a, 0, 0}, ++ {0x42, 0x7a, 0x7a, 0, 0}, ++ {0x43, 0x29, 0x29, 0, 0}, ++ {0x44, 0, 0, 0, 0}, ++ {0x45, 0x8, 0x8, 0, 0}, ++ {0x46, 0xce, 0xce, 0, 0}, ++ {0x47, 0x27, 0x27, 0, 0}, ++ {0x48, 0x62, 0x62, 0, 0}, ++ {0x49, 0x6, 0x6, 0, 0}, ++ {0x4A, 0x58, 0x58, 0, 0}, ++ {0x4B, 0xf7, 0xf7, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0xb3, 0xb3, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0x2, 0x2, 0, 0}, ++ {0x50, 0, 0, 0, 0}, ++ {0x51, 0x9, 0x9, 0, 0}, ++ {0x52, 0x5, 0x5, 0, 0}, ++ {0x53, 0x17, 0x17, 0, 0}, ++ {0x54, 0x38, 0x38, 0, 0}, ++ {0x55, 0, 0, 0, 0}, ++ {0x56, 0, 0, 0, 0}, ++ {0x57, 0xb, 0xb, 0, 0}, ++ {0x58, 0, 0, 0, 0}, ++ {0x59, 0, 0, 0, 0}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0, 0, 0, 0}, ++ {0x5C, 0, 0, 0, 0}, ++ {0x5D, 0, 0, 0, 0}, ++ {0x5E, 0x88, 0x88, 0, 0}, ++ {0x5F, 0xcc, 0xcc, 0, 0}, ++ {0x60, 0x74, 0x74, 0, 0}, ++ {0x61, 0x74, 0x74, 0, 0}, ++ {0x62, 0x74, 0x74, 0, 0}, ++ {0x63, 0x44, 0x44, 0, 0}, ++ {0x64, 0x77, 0x77, 0, 0}, ++ {0x65, 0x44, 0x44, 0, 0}, ++ {0x66, 0x77, 0x77, 0, 0}, ++ {0x67, 0x55, 0x55, 0, 0}, ++ {0x68, 0x77, 0x77, 0, 0}, ++ {0x69, 0x77, 0x77, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0x7f, 0x7f, 0, 0}, ++ {0x6C, 0x8, 0x8, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0x88, 0x88, 0, 0}, ++ {0x6F, 0x66, 0x66, 0, 0}, ++ {0x70, 0x66, 0x66, 0, 0}, ++ {0x71, 0x28, 0x28, 0, 0}, ++ {0x72, 0x55, 0x55, 0, 0}, ++ {0x73, 0x4, 0x4, 0, 0}, ++ {0x74, 0, 0, 0, 0}, ++ {0x75, 0, 0, 0, 0}, ++ {0x76, 0, 0, 0, 0}, ++ {0x77, 0x1, 0x1, 0, 0}, ++ {0x78, 0xd6, 0xd6, 0, 0}, ++ {0x79, 0, 0, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0xb4, 0xb4, 0, 0}, ++ {0x84, 0x1, 0x1, 0, 0}, ++ {0x85, 0x20, 0x20, 0, 0}, ++ {0x86, 0x5, 0x5, 0, 0}, ++ {0x87, 0xff, 0xff, 0, 0}, ++ {0x88, 0x7, 0x7, 0, 0}, ++ {0x89, 0x77, 0x77, 0, 0}, ++ {0x8A, 0x77, 0x77, 0, 0}, ++ {0x8B, 0x77, 0x77, 0, 0}, ++ {0x8C, 0x77, 0x77, 0, 0}, ++ {0x8D, 0x8, 0x8, 0, 0}, ++ {0x8E, 0xa, 0xa, 0, 0}, ++ {0x8F, 0x8, 0x8, 0, 0}, ++ {0x90, 0x18, 0x18, 0, 0}, ++ {0x91, 0x5, 0x5, 0, 0}, ++ {0x92, 0x1f, 0x1f, 0, 0}, ++ {0x93, 0x10, 0x10, 0, 0}, ++ {0x94, 0x3, 0x3, 0, 0}, ++ {0x95, 0, 0, 0, 0}, ++ {0x96, 0, 0, 0, 0}, ++ {0x97, 0xaa, 0xaa, 0, 0}, ++ {0x98, 0, 0, 0, 0}, ++ {0x99, 0x23, 0x23, 0, 0}, ++ {0x9A, 0x7, 0x7, 0, 0}, ++ {0x9B, 0xf, 0xf, 0, 0}, ++ {0x9C, 0x10, 0x10, 0, 0}, ++ {0x9D, 0x3, 0x3, 0, 0}, ++ {0x9E, 0x4, 0x4, 0, 0}, ++ {0x9F, 0x20, 0x20, 0, 0}, ++ {0xA0, 0, 0, 0, 0}, ++ {0xA1, 0, 0, 0, 0}, ++ {0xA2, 0, 0, 0, 0}, ++ {0xA3, 0, 0, 0, 0}, ++ {0xA4, 0x1, 0x1, 0, 0}, ++ {0xA5, 0x77, 0x77, 0, 0}, ++ {0xA6, 0x77, 0x77, 0, 0}, ++ {0xA7, 0x77, 0x77, 0, 0}, ++ {0xA8, 0x77, 0x77, 0, 0}, ++ {0xA9, 0x8c, 0x8c, 0, 0}, ++ {0xAA, 0x88, 0x88, 0, 0}, ++ {0xAB, 0x78, 0x78, 0, 0}, ++ {0xAC, 0x57, 0x57, 0, 0}, ++ {0xAD, 0x88, 0x88, 0, 0}, ++ {0xAE, 0, 0, 0, 0}, ++ {0xAF, 0x8, 0x8, 0, 0}, ++ {0xB0, 0x88, 0x88, 0, 0}, ++ {0xB1, 0, 0, 0, 0}, ++ {0xB2, 0x1b, 0x1b, 0, 0}, ++ {0xB3, 0x3, 0x3, 0, 0}, ++ {0xB4, 0x24, 0x24, 0, 0}, ++ {0xB5, 0x3, 0x3, 0, 0}, ++ {0xB6, 0x1b, 0x1b, 0, 0}, ++ {0xB7, 0x24, 0x24, 0, 0}, ++ {0xB8, 0x3, 0x3, 0, 0}, ++ {0xB9, 0, 0, 0, 0}, ++ {0xBA, 0xaa, 0xaa, 0, 0}, ++ {0xBB, 0, 0, 0, 0}, ++ {0xBC, 0x4, 0x4, 0, 0}, ++ {0xBD, 0, 0, 0, 0}, ++ {0xBE, 0x8, 0x8, 0, 0}, ++ {0xBF, 0x11, 0x11, 0, 0}, ++ {0xC0, 0, 0, 0, 0}, ++ {0xC1, 0, 0, 0, 0}, ++ {0xC2, 0x62, 0x62, 0, 0}, ++ {0xC3, 0x1e, 0x1e, 0, 0}, ++ {0xC4, 0x33, 0x33, 0, 0}, ++ {0xC5, 0x37, 0x37, 0, 0}, ++ {0xC6, 0, 0, 0, 0}, ++ {0xC7, 0x70, 0x70, 0, 0}, ++ {0xC8, 0x1e, 0x1e, 0, 0}, ++ {0xC9, 0x6, 0x6, 0, 0}, ++ {0xCA, 0x4, 0x4, 0, 0}, ++ {0xCB, 0x2f, 0x2f, 0, 0}, ++ {0xCC, 0xf, 0xf, 0, 0}, ++ {0xCD, 0, 0, 0, 0}, ++ {0xCE, 0xff, 0xff, 0, 0}, ++ {0xCF, 0x8, 0x8, 0, 0}, ++ {0xD0, 0x3f, 0x3f, 0, 0}, ++ {0xD1, 0x3f, 0x3f, 0, 0}, ++ {0xD2, 0x3f, 0x3f, 0, 0}, ++ {0xD3, 0, 0, 0, 0}, ++ {0xD4, 0, 0, 0, 0}, ++ {0xD5, 0, 0, 0, 0}, ++ {0xD6, 0xcc, 0xcc, 0, 0}, ++ {0xD7, 0, 0, 0, 0}, ++ {0xD8, 0x8, 0x8, 0, 0}, ++ {0xD9, 0x8, 0x8, 0, 0}, ++ {0xDA, 0x8, 0x8, 0, 0}, ++ {0xDB, 0x11, 0x11, 0, 0}, ++ {0xDC, 0, 0, 0, 0}, ++ {0xDD, 0x87, 0x87, 0, 0}, ++ {0xDE, 0x88, 0x88, 0, 0}, ++ {0xDF, 0x8, 0x8, 0, 0}, ++ {0xE0, 0x8, 0x8, 0, 0}, ++ {0xE1, 0x8, 0x8, 0, 0}, ++ {0xE2, 0, 0, 0, 0}, ++ {0xE3, 0, 0, 0, 0}, ++ {0xE4, 0, 0, 0, 0}, ++ {0xE5, 0xf5, 0xf5, 0, 0}, ++ {0xE6, 0x30, 0x30, 0, 0}, ++ {0xE7, 0x1, 0x1, 0, 0}, ++ {0xE8, 0, 0, 0, 0}, ++ {0xE9, 0xff, 0xff, 0, 0}, ++ {0xEA, 0, 0, 0, 0}, ++ {0xEB, 0, 0, 0, 0}, ++ {0xEC, 0x22, 0x22, 0, 0}, ++ {0xED, 0, 0, 0, 0}, ++ {0xEE, 0, 0, 0, 0}, ++ {0xEF, 0, 0, 0, 0}, ++ {0xF0, 0x3, 0x3, 0, 0}, ++ {0xF1, 0x1, 0x1, 0, 0}, ++ {0xF2, 0, 0, 0, 0}, ++ {0xF3, 0, 0, 0, 0}, ++ {0xF4, 0, 0, 0, 0}, ++ {0xF5, 0, 0, 0, 0}, ++ {0xF6, 0, 0, 0, 0}, ++ {0xF7, 0x6, 0x6, 0, 0}, ++ {0xF8, 0, 0, 0, 0}, ++ {0xF9, 0, 0, 0, 0}, ++ {0xFA, 0x40, 0x40, 0, 0}, ++ {0xFB, 0, 0, 0, 0}, ++ {0xFC, 0x1, 0x1, 0, 0}, ++ {0xFD, 0x80, 0x80, 0, 0}, ++ {0xFE, 0x2, 0x2, 0, 0}, ++ {0xFF, 0x10, 0x10, 0, 0}, ++ {0x100, 0x2, 0x2, 0, 0}, ++ {0x101, 0x1e, 0x1e, 0, 0}, ++ {0x102, 0x1e, 0x1e, 0, 0}, ++ {0x103, 0, 0, 0, 0}, ++ {0x104, 0x1f, 0x1f, 0, 0}, ++ {0x105, 0, 0x8, 0, 1}, ++ {0x106, 0x2a, 0x2a, 0, 0}, ++ {0x107, 0xf, 0xf, 0, 0}, ++ {0x108, 0, 0, 0, 0}, ++ {0x109, 0, 0, 0, 0}, ++ {0x10A, 0, 0, 0, 0}, ++ {0x10B, 0, 0, 0, 0}, ++ {0x10C, 0, 0, 0, 0}, ++ {0x10D, 0, 0, 0, 0}, ++ {0x10E, 0, 0, 0, 0}, ++ {0x10F, 0, 0, 0, 0}, ++ {0x110, 0, 0, 0, 0}, ++ {0x111, 0, 0, 0, 0}, ++ {0x112, 0, 0, 0, 0}, ++ {0x113, 0, 0, 0, 0}, ++ {0x114, 0, 0, 0, 0}, ++ {0x115, 0, 0, 0, 0}, ++ {0x116, 0, 0, 0, 0}, ++ {0x117, 0, 0, 0, 0}, ++ {0x118, 0, 0, 0, 0}, ++ {0x119, 0, 0, 0, 0}, ++ {0x11A, 0, 0, 0, 0}, ++ {0x11B, 0, 0, 0, 0}, ++ {0x11C, 0x1, 0x1, 0, 0}, ++ {0x11D, 0, 0, 0, 0}, ++ {0x11E, 0, 0, 0, 0}, ++ {0x11F, 0, 0, 0, 0}, ++ {0x120, 0, 0, 0, 0}, ++ {0x121, 0, 0, 0, 0}, ++ {0x122, 0x80, 0x80, 0, 0}, ++ {0x123, 0, 0, 0, 0}, ++ {0x124, 0xf8, 0xf8, 0, 0}, ++ {0x125, 0, 0, 0, 0}, ++ {0x126, 0, 0, 0, 0}, ++ {0x127, 0, 0, 0, 0}, ++ {0x128, 0, 0, 0, 0}, ++ {0x129, 0, 0, 0, 0}, ++ {0x12A, 0, 0, 0, 0}, ++ {0x12B, 0, 0, 0, 0}, ++ {0x12C, 0, 0, 0, 0}, ++ {0x12D, 0, 0, 0, 0}, ++ {0x12E, 0, 0, 0, 0}, ++ {0x12F, 0, 0, 0, 0}, ++ {0x130, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++#define LCNPHY_NUM_DIG_FILT_COEFFS 16 ++#define LCNPHY_NUM_TX_DIG_FILTERS_CCK 13 ++ ++static const u16 LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK] ++ [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = { ++ {0, 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778, 1582, 64, ++ 128, 64,}, ++ {1, 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608, 1863, 93, ++ 167, 93,}, ++ {2, 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192, 778, 1582, 64, ++ 128, 64,}, ++ {3, 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205, 754, 1760, ++ 170, 340, 170,}, ++ {20, 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205, 767, 1760, ++ 256, 185, 256,}, ++ {21, 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205, 767, 1760, ++ 256, 273, 256,}, ++ {22, 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205, 767, 1760, ++ 256, 352, 256,}, ++ {23, 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205, 767, 1760, ++ 128, 233, 128,}, ++ {24, 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766, 1760, 256, ++ 1881, 256,}, ++ {25, 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765, 1760, 256, ++ 1881, 256,}, ++ {26, 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614, 1864, 128, ++ 384, 288,}, ++ {27, 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576, 613, 1864, ++ 128, 384, 288,}, ++ {30, 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205, 754, 1760, ++ 170, 340, 170,}, ++}; ++ ++#define LCNPHY_NUM_TX_DIG_FILTERS_OFDM 3 ++static const u16 LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM] ++ [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = { ++ {0, 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0, 0x0, ++ 0x278, 0xfea0, 0x80, 0x100, 0x80,}, ++ {1, 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50, ++ 750, 0xFE2B, 212, 0xFFCE, 212,}, ++ {2, 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748, ++ 0xFEF2, 128, 0xFFE2, 128} ++}; ++ ++#define wlc_lcnphy_set_start_tx_pwr_idx(pi, idx) \ ++ mod_phy_reg(pi, 0x4a4, \ ++ (0x1ff << 0), \ ++ (u16)(idx) << 0) ++ ++#define wlc_lcnphy_set_tx_pwr_npt(pi, npt) \ ++ mod_phy_reg(pi, 0x4a5, \ ++ (0x7 << 8), \ ++ (u16)(npt) << 8) ++ ++#define wlc_lcnphy_get_tx_pwr_ctrl(pi) \ ++ (read_phy_reg((pi), 0x4a4) & \ ++ ((0x1 << 15) | \ ++ (0x1 << 14) | \ ++ (0x1 << 13))) ++ ++#define wlc_lcnphy_get_tx_pwr_npt(pi) \ ++ ((read_phy_reg(pi, 0x4a5) & \ ++ (0x7 << 8)) >> \ ++ 8) ++ ++#define wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) \ ++ (read_phy_reg(pi, 0x473) & 0x1ff) ++ ++#define wlc_lcnphy_get_target_tx_pwr(pi) \ ++ ((read_phy_reg(pi, 0x4a7) & \ ++ (0xff << 0)) >> \ ++ 0) ++ ++#define wlc_lcnphy_set_target_tx_pwr(pi, target) \ ++ mod_phy_reg(pi, 0x4a7, \ ++ (0xff << 0), \ ++ (u16)(target) << 0) ++ ++#define wlc_radio_2064_rcal_done(pi) \ ++ (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20)) ++ ++#define tempsense_done(pi) \ ++ (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000)) ++ ++#define LCNPHY_IQLOCC_READ(val) \ ++ ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f))) ++ ++#define FIXED_TXPWR 78 ++#define LCNPHY_TEMPSENSE(val) ((s16)((val > 255) ? (val - 512) : val)) ++ ++void wlc_lcnphy_write_table(struct brcms_phy *pi, const struct phytbl_info *pti) ++{ ++ wlc_phy_write_table(pi, pti, 0x455, 0x457, 0x456); ++} ++ ++void wlc_lcnphy_read_table(struct brcms_phy *pi, struct phytbl_info *pti) ++{ ++ wlc_phy_read_table(pi, pti, 0x455, 0x457, 0x456); ++} ++ ++static void ++wlc_lcnphy_common_read_table(struct brcms_phy *pi, u32 tbl_id, ++ const u16 *tbl_ptr, u32 tbl_len, ++ u32 tbl_width, u32 tbl_offset) ++{ ++ struct phytbl_info tab; ++ tab.tbl_id = tbl_id; ++ tab.tbl_ptr = tbl_ptr; ++ tab.tbl_len = tbl_len; ++ tab.tbl_width = tbl_width; ++ tab.tbl_offset = tbl_offset; ++ wlc_lcnphy_read_table(pi, &tab); ++} ++ ++static void ++wlc_lcnphy_common_write_table(struct brcms_phy *pi, u32 tbl_id, ++ const u16 *tbl_ptr, u32 tbl_len, ++ u32 tbl_width, u32 tbl_offset) ++{ ++ ++ struct phytbl_info tab; ++ tab.tbl_id = tbl_id; ++ tab.tbl_ptr = tbl_ptr; ++ tab.tbl_len = tbl_len; ++ tab.tbl_width = tbl_width; ++ tab.tbl_offset = tbl_offset; ++ wlc_lcnphy_write_table(pi, &tab); ++} ++ ++static u32 ++wlc_lcnphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision) ++{ ++ u32 quotient, remainder, roundup, rbit; ++ ++ quotient = dividend / divisor; ++ remainder = dividend % divisor; ++ rbit = divisor & 1; ++ roundup = (divisor >> 1) + rbit; ++ ++ while (precision--) { ++ quotient <<= 1; ++ if (remainder >= roundup) { ++ quotient++; ++ remainder = ((remainder - roundup) << 1) + rbit; ++ } else { ++ remainder <<= 1; ++ } ++ } ++ ++ if (remainder >= roundup) ++ quotient++; ++ ++ return quotient; ++} ++ ++static int wlc_lcnphy_calc_floor(s16 coeff_x, int type) ++{ ++ int k; ++ k = 0; ++ if (type == 0) { ++ if (coeff_x < 0) ++ k = (coeff_x - 1) / 2; ++ else ++ k = coeff_x / 2; ++ } ++ ++ if (type == 1) { ++ if ((coeff_x + 1) < 0) ++ k = (coeff_x) / 2; ++ else ++ k = (coeff_x + 1) / 2; ++ } ++ return k; ++} ++ ++static void ++wlc_lcnphy_get_tx_gain(struct brcms_phy *pi, struct lcnphy_txgains *gains) ++{ ++ u16 dac_gain, rfgain0, rfgain1; ++ ++ dac_gain = read_phy_reg(pi, 0x439) >> 0; ++ gains->dac_gain = (dac_gain & 0x380) >> 7; ++ ++ rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0; ++ rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0; ++ ++ gains->gm_gain = rfgain0 & 0xff; ++ gains->pga_gain = (rfgain0 >> 8) & 0xff; ++ gains->pad_gain = rfgain1 & 0xff; ++} ++ ++ ++static void wlc_lcnphy_set_dac_gain(struct brcms_phy *pi, u16 dac_gain) ++{ ++ u16 dac_ctrl; ++ ++ dac_ctrl = (read_phy_reg(pi, 0x439) >> 0); ++ dac_ctrl = dac_ctrl & 0xc7f; ++ dac_ctrl = dac_ctrl | (dac_gain << 7); ++ mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0); ++ ++} ++ ++static void wlc_lcnphy_set_tx_gain_override(struct brcms_phy *pi, bool bEnable) ++{ ++ u16 bit = bEnable ? 1 : 0; ++ ++ mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7); ++ ++ mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14); ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6); ++} ++ ++static void ++wlc_lcnphy_rx_gain_override_enable(struct brcms_phy *pi, bool enable) ++{ ++ u16 ebit = enable ? 1 : 0; ++ ++ mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0); ++ ++ if (LCNREV_LT(pi->pubpi.phy_rev, 2)) { ++ mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4); ++ mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6); ++ mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5); ++ mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6); ++ } else { ++ mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12); ++ mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13); ++ mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5); ++ } ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10); ++ mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3); ++ } ++} ++ ++static void ++wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi, ++ u16 trsw, ++ u16 ext_lna, ++ u16 biq2, ++ u16 biq1, ++ u16 tia, u16 lna2, u16 lna1) ++{ ++ u16 gain0_15, gain16_19; ++ ++ gain16_19 = biq2 & 0xf; ++ gain0_15 = ((biq1 & 0xf) << 12) | ++ ((tia & 0xf) << 8) | ++ ((lna2 & 0x3) << 6) | ++ ((lna2 & ++ 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0); ++ ++ mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0); ++ mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0); ++ mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11); ++ ++ if (LCNREV_LT(pi->pubpi.phy_rev, 2)) { ++ mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9); ++ mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10); ++ } else { ++ mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10); ++ ++ mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15); ++ ++ mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9); ++ } ++ ++ mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0); ++ ++} ++ ++static void wlc_lcnphy_set_trsw_override(struct brcms_phy *pi, bool tx, bool rx) ++{ ++ ++ mod_phy_reg(pi, 0x44d, ++ (0x1 << 1) | ++ (0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0)); ++ ++ or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0)); ++} ++ ++static void wlc_lcnphy_clear_trsw_override(struct brcms_phy *pi) ++{ ++ ++ and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0))); ++} ++ ++static void wlc_lcnphy_set_rx_iq_comp(struct brcms_phy *pi, u16 a, u16 b) ++{ ++ mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0); ++ ++ mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0); ++ ++ mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0); ++ ++ mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0); ++ ++ mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0); ++ ++ mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0); ++ ++} ++ ++static bool ++wlc_lcnphy_rx_iq_est(struct brcms_phy *pi, ++ u16 num_samps, ++ u8 wait_time, struct lcnphy_iq_est *iq_est) ++{ ++ int wait_count = 0; ++ bool result = true; ++ u8 phybw40; ++ phybw40 = CHSPEC_IS40(pi->radio_chanspec); ++ ++ mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5); ++ ++ mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3); ++ ++ mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0); ++ ++ mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0); ++ ++ mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8); ++ ++ mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9); ++ ++ while (read_phy_reg(pi, 0x481) & (0x1 << 9)) { ++ ++ if (wait_count > (10 * 500)) { ++ result = false; ++ goto cleanup; ++ } ++ udelay(100); ++ wait_count++; ++ } ++ ++ iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) | ++ (u32) read_phy_reg(pi, 0x484); ++ iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) | ++ (u32) read_phy_reg(pi, 0x486); ++ iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) | ++ (u32) read_phy_reg(pi, 0x488); ++ ++cleanup: ++ mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3); ++ ++ mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5); ++ ++ return result; ++} ++ ++static bool wlc_lcnphy_calc_rx_iq_comp(struct brcms_phy *pi, u16 num_samps) ++{ ++#define LCNPHY_MIN_RXIQ_PWR 2 ++ bool result; ++ u16 a0_new, b0_new; ++ struct lcnphy_iq_est iq_est = { 0, 0, 0 }; ++ s32 a, b, temp; ++ s16 iq_nbits, qq_nbits, arsh, brsh; ++ s32 iq; ++ u32 ii, qq; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0); ++ b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0); ++ mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2); ++ ++ mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6); ++ ++ wlc_lcnphy_set_rx_iq_comp(pi, 0, 0); ++ ++ result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est); ++ if (!result) ++ goto cleanup; ++ ++ iq = (s32) iq_est.iq_prod; ++ ii = iq_est.i_pwr; ++ qq = iq_est.q_pwr; ++ ++ if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) { ++ result = false; ++ goto cleanup; ++ } ++ ++ iq_nbits = wlc_phy_nbits(iq); ++ qq_nbits = wlc_phy_nbits(qq); ++ ++ arsh = 10 - (30 - iq_nbits); ++ if (arsh >= 0) { ++ a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); ++ temp = (s32) (ii >> arsh); ++ if (temp == 0) ++ return false; ++ } else { ++ a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); ++ temp = (s32) (ii << -arsh); ++ if (temp == 0) ++ return false; ++ } ++ a /= temp; ++ brsh = qq_nbits - 31 + 20; ++ if (brsh >= 0) { ++ b = (qq << (31 - qq_nbits)); ++ temp = (s32) (ii >> brsh); ++ if (temp == 0) ++ return false; ++ } else { ++ b = (qq << (31 - qq_nbits)); ++ temp = (s32) (ii << -brsh); ++ if (temp == 0) ++ return false; ++ } ++ b /= temp; ++ b -= a * a; ++ b = (s32) int_sqrt((unsigned long) b); ++ b -= (1 << 10); ++ a0_new = (u16) (a & 0x3ff); ++ b0_new = (u16) (b & 0x3ff); ++cleanup: ++ ++ wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new); ++ ++ mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0); ++ ++ mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3); ++ ++ pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new; ++ pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new; ++ ++ return result; ++} ++ ++static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples) ++{ ++ struct lcnphy_iq_est iq_est = { 0, 0, 0 }; ++ ++ if (!wlc_lcnphy_rx_iq_est(pi, nsamples, 32, &iq_est)) ++ return 0; ++ return (iq_est.i_pwr + iq_est.q_pwr) / nsamples; ++} ++ ++static bool ++wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, ++ const struct lcnphy_rx_iqcomp *iqcomp, ++ int iqcomp_sz, bool tx_switch, bool rx_switch, int module, ++ int tx_gain_idx) ++{ ++ struct lcnphy_txgains old_gains; ++ u16 tx_pwr_ctrl; ++ u8 tx_gain_index_old = 0; ++ bool result = false, tx_gain_override_old = false; ++ u16 i, Core1TxControl_old, RFOverride0_old, ++ RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old, ++ rfoverride3_old, rfoverride3val_old, rfoverride4_old, ++ rfoverride4val_old, afectrlovr_old, afectrlovrval_old; ++ int tia_gain; ++ u32 received_power, rx_pwr_threshold; ++ u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl; ++ u16 values_to_save[11]; ++ s16 *ptr; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC); ++ if (NULL == ptr) ++ return false; ++ if (module == 2) { ++ while (iqcomp_sz--) { ++ if (iqcomp[iqcomp_sz].chan == ++ CHSPEC_CHANNEL(pi->radio_chanspec)) { ++ wlc_lcnphy_set_rx_iq_comp(pi, ++ (u16) ++ iqcomp[iqcomp_sz].a, ++ (u16) ++ iqcomp[iqcomp_sz].b); ++ result = true; ++ break; ++ } ++ } ++ goto cal_done; ++ } ++ ++ if (module == 1) { ++ ++ tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); ++ ++ for (i = 0; i < 11; i++) ++ values_to_save[i] = ++ read_radio_reg(pi, rxiq_cal_rf_reg[i]); ++ Core1TxControl_old = read_phy_reg(pi, 0x631); ++ ++ or_phy_reg(pi, 0x631, 0x0015); ++ ++ RFOverride0_old = read_phy_reg(pi, 0x44c); ++ RFOverrideVal0_old = read_phy_reg(pi, 0x44d); ++ rfoverride2_old = read_phy_reg(pi, 0x4b0); ++ rfoverride2val_old = read_phy_reg(pi, 0x4b1); ++ rfoverride3_old = read_phy_reg(pi, 0x4f9); ++ rfoverride3val_old = read_phy_reg(pi, 0x4fa); ++ rfoverride4_old = read_phy_reg(pi, 0x938); ++ rfoverride4val_old = read_phy_reg(pi, 0x939); ++ afectrlovr_old = read_phy_reg(pi, 0x43b); ++ afectrlovrval_old = read_phy_reg(pi, 0x43c); ++ old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); ++ old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); ++ ++ tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); ++ if (tx_gain_override_old) { ++ wlc_lcnphy_get_tx_gain(pi, &old_gains); ++ tx_gain_index_old = pi_lcn->lcnphy_current_index; ++ } ++ ++ wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx); ++ ++ mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0); ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); ++ mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); ++ ++ write_radio_reg(pi, RADIO_2064_REG116, 0x06); ++ write_radio_reg(pi, RADIO_2064_REG12C, 0x07); ++ write_radio_reg(pi, RADIO_2064_REG06A, 0xd3); ++ write_radio_reg(pi, RADIO_2064_REG098, 0x03); ++ write_radio_reg(pi, RADIO_2064_REG00B, 0x7); ++ mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4); ++ write_radio_reg(pi, RADIO_2064_REG01D, 0x01); ++ write_radio_reg(pi, RADIO_2064_REG114, 0x01); ++ write_radio_reg(pi, RADIO_2064_REG02E, 0x10); ++ write_radio_reg(pi, RADIO_2064_REG12A, 0x08); ++ ++ mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0); ++ mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1); ++ mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1); ++ mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2); ++ mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2); ++ mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3); ++ mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3); ++ mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5); ++ mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5); ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0); ++ ++ wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0); ++ write_phy_reg(pi, 0x6da, 0xffff); ++ or_phy_reg(pi, 0x6db, 0x3); ++ wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch); ++ wlc_lcnphy_rx_gain_override_enable(pi, true); ++ ++ tia_gain = 8; ++ rx_pwr_threshold = 950; ++ while (tia_gain > 0) { ++ tia_gain -= 1; ++ wlc_lcnphy_set_rx_gain_by_distribution(pi, ++ 0, 0, 2, 2, ++ (u16) ++ tia_gain, 1, 0); ++ udelay(500); ++ ++ received_power = ++ wlc_lcnphy_measure_digital_power(pi, 2000); ++ if (received_power < rx_pwr_threshold) ++ break; ++ } ++ result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff); ++ ++ wlc_lcnphy_stop_tx_tone(pi); ++ ++ write_phy_reg(pi, 0x631, Core1TxControl_old); ++ ++ write_phy_reg(pi, 0x44c, RFOverrideVal0_old); ++ write_phy_reg(pi, 0x44d, RFOverrideVal0_old); ++ write_phy_reg(pi, 0x4b0, rfoverride2_old); ++ write_phy_reg(pi, 0x4b1, rfoverride2val_old); ++ write_phy_reg(pi, 0x4f9, rfoverride3_old); ++ write_phy_reg(pi, 0x4fa, rfoverride3val_old); ++ write_phy_reg(pi, 0x938, rfoverride4_old); ++ write_phy_reg(pi, 0x939, rfoverride4val_old); ++ write_phy_reg(pi, 0x43b, afectrlovr_old); ++ write_phy_reg(pi, 0x43c, afectrlovrval_old); ++ write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); ++ write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl); ++ ++ wlc_lcnphy_clear_trsw_override(pi); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2); ++ ++ for (i = 0; i < 11; i++) ++ write_radio_reg(pi, rxiq_cal_rf_reg[i], ++ values_to_save[i]); ++ ++ if (tx_gain_override_old) ++ wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old); ++ else ++ wlc_lcnphy_disable_tx_gain_override(pi); ++ ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl); ++ wlc_lcnphy_rx_gain_override_enable(pi, false); ++ } ++ ++cal_done: ++ kfree(ptr); ++ return result; ++} ++ ++s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi) ++{ ++ s8 index; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ if (txpwrctrl_off(pi)) ++ index = pi_lcn->lcnphy_current_index; ++ else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) ++ index = (s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on( ++ pi) / 2); ++ else ++ index = pi_lcn->lcnphy_current_index; ++ return index; ++} ++ ++void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel) ++{ ++ u16 afectrlovr, afectrlovrval; ++ afectrlovr = read_phy_reg(pi, 0x43b); ++ afectrlovrval = read_phy_reg(pi, 0x43c); ++ if (channel != 0) { ++ mod_phy_reg(pi, 0x43b, (0x1 << 1), (1) << 1); ++ ++ mod_phy_reg(pi, 0x43c, (0x1 << 1), (0) << 1); ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 4), (1) << 4); ++ ++ mod_phy_reg(pi, 0x43c, (0x1 << 6), (0) << 6); ++ ++ write_phy_reg(pi, 0x44b, 0xffff); ++ wlc_lcnphy_tx_pu(pi, 1); ++ ++ mod_phy_reg(pi, 0x634, (0xff << 8), (0) << 8); ++ ++ or_phy_reg(pi, 0x6da, 0x0080); ++ ++ or_phy_reg(pi, 0x00a, 0x228); ++ } else { ++ and_phy_reg(pi, 0x00a, ~(0x228)); ++ ++ and_phy_reg(pi, 0x6da, 0xFF7F); ++ write_phy_reg(pi, 0x43b, afectrlovr); ++ write_phy_reg(pi, 0x43c, afectrlovrval); ++ } ++} ++ ++static void wlc_lcnphy_toggle_afe_pwdn(struct brcms_phy *pi) ++{ ++ u16 save_AfeCtrlOvrVal, save_AfeCtrlOvr; ++ ++ save_AfeCtrlOvrVal = read_phy_reg(pi, 0x43c); ++ save_AfeCtrlOvr = read_phy_reg(pi, 0x43b); ++ ++ write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal | 0x1); ++ write_phy_reg(pi, 0x43b, save_AfeCtrlOvr | 0x1); ++ ++ write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal & 0xfffe); ++ write_phy_reg(pi, 0x43b, save_AfeCtrlOvr & 0xfffe); ++ ++ write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal); ++ write_phy_reg(pi, 0x43b, save_AfeCtrlOvr); ++} ++ ++static void ++wlc_lcnphy_txrx_spur_avoidance_mode(struct brcms_phy *pi, bool enable) ++{ ++ if (enable) { ++ write_phy_reg(pi, 0x942, 0x7); ++ write_phy_reg(pi, 0x93b, ((1 << 13) + 23)); ++ write_phy_reg(pi, 0x93c, ((1 << 13) + 1989)); ++ ++ write_phy_reg(pi, 0x44a, 0x084); ++ write_phy_reg(pi, 0x44a, 0x080); ++ write_phy_reg(pi, 0x6d3, 0x2222); ++ write_phy_reg(pi, 0x6d3, 0x2220); ++ } else { ++ write_phy_reg(pi, 0x942, 0x0); ++ write_phy_reg(pi, 0x93b, ((0 << 13) + 23)); ++ write_phy_reg(pi, 0x93c, ((0 << 13) + 1989)); ++ } ++ wlapi_switch_macfreq(pi->sh->physhim, enable); ++} ++ ++static void ++wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec) ++{ ++ u8 channel = CHSPEC_CHANNEL(chanspec); ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ if (channel == 14) ++ mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8); ++ else ++ mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8); ++ ++ pi_lcn->lcnphy_bandedge_corr = 2; ++ if (channel == 1) ++ pi_lcn->lcnphy_bandedge_corr = 4; ++ ++ if (channel == 1 || channel == 2 || channel == 3 || ++ channel == 4 || channel == 9 || ++ channel == 10 || channel == 11 || channel == 12) { ++ si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04); ++ si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0); ++ si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0); ++ ++ si_pmu_pllupd(pi->sh->sih); ++ write_phy_reg(pi, 0x942, 0); ++ wlc_lcnphy_txrx_spur_avoidance_mode(pi, false); ++ pi_lcn->lcnphy_spurmod = 0; ++ mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8); ++ ++ write_phy_reg(pi, 0x425, 0x5907); ++ } else { ++ si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04); ++ si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333); ++ si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820); ++ ++ si_pmu_pllupd(pi->sh->sih); ++ write_phy_reg(pi, 0x942, 0); ++ wlc_lcnphy_txrx_spur_avoidance_mode(pi, true); ++ ++ pi_lcn->lcnphy_spurmod = 0; ++ mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8); ++ ++ write_phy_reg(pi, 0x425, 0x590a); ++ } ++ ++ or_phy_reg(pi, 0x44a, 0x44); ++ write_phy_reg(pi, 0x44a, 0x80); ++} ++ ++static void ++wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel) ++{ ++ uint i; ++ const struct chan_info_2064_lcnphy *ci; ++ u8 rfpll_doubler = 0; ++ u8 pll_pwrup, pll_pwrup_ovr; ++ s32 qFxtal, qFref, qFvco, qFcal; ++ u8 d15, d16, f16, e44, e45; ++ u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div; ++ u16 loop_bw, d30, setCount; ++ ++ u8 h29, h28_ten, e30, h30_ten, cp_current; ++ u16 g30, d28; ++ ++ ci = &chan_info_2064_lcnphy[0]; ++ rfpll_doubler = 1; ++ ++ mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2); ++ ++ write_radio_reg(pi, RADIO_2064_REG09E, 0xf); ++ if (!rfpll_doubler) { ++ loop_bw = PLL_2064_LOOP_BW; ++ d30 = PLL_2064_D30; ++ } else { ++ loop_bw = PLL_2064_LOOP_BW_DOUBLER; ++ d30 = PLL_2064_D30_DOUBLER; ++ } ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++) ++ if (chan_info_2064_lcnphy[i].chan == channel) ++ break; ++ ++ if (i >= ARRAY_SIZE(chan_info_2064_lcnphy)) ++ return; ++ ++ ci = &chan_info_2064_lcnphy[i]; ++ } ++ ++ write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune); ++ ++ mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx); ++ ++ mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl); ++ ++ mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g); ++ ++ mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2, ++ (ci->logen_rccr_rx) << 2); ++ ++ mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune); ++ ++ mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4, ++ (ci->pa_rxrf_lna2_freq_tune) << 4); ++ ++ write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1); ++ ++ pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044); ++ pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B); ++ ++ or_radio_reg(pi, RADIO_2064_REG044, 0x07); ++ ++ or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1); ++ e44 = 0; ++ e45 = 0; ++ ++ fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq); ++ if (pi->xtalfreq > 26000000) ++ e44 = 1; ++ if (pi->xtalfreq > 52000000) ++ e45 = 1; ++ if (e44 == 0) ++ fcal_div = 1; ++ else if (e45 == 0) ++ fcal_div = 2; ++ else ++ fcal_div = 4; ++ fvco3 = (ci->freq * 3); ++ fref3 = 2 * fpfd; ++ ++ qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16); ++ qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16); ++ qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ; ++ qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16); ++ ++ write_radio_reg(pi, RADIO_2064_REG04F, 0x02); ++ ++ d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1; ++ write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2))); ++ write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5); ++ ++ d16 = (qFcal * 8 / (d15 + 1)) - 1; ++ write_radio_reg(pi, RADIO_2064_REG051, d16); ++ ++ f16 = ((d16 + 1) * (d15 + 1)) / qFcal; ++ setCount = f16 * 3 * (ci->freq) / 32 - 1; ++ mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0), ++ (u8) (setCount >> 8)); ++ ++ or_radio_reg(pi, RADIO_2064_REG053, 0x10); ++ write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff)); ++ ++ div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4; ++ ++ div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4; ++ while (div_frac >= fref3) { ++ div_int++; ++ div_frac -= fref3; ++ } ++ div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20); ++ ++ mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0), ++ (u8) (div_int >> 4)); ++ mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4), ++ (u8) (div_int << 4)); ++ mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0), ++ (u8) (div_frac >> 16)); ++ write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff); ++ write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff); ++ ++ write_radio_reg(pi, RADIO_2064_REG040, 0xfb); ++ ++ write_radio_reg(pi, RADIO_2064_REG041, 0x9A); ++ write_radio_reg(pi, RADIO_2064_REG042, 0xA3); ++ write_radio_reg(pi, RADIO_2064_REG043, 0x0C); ++ ++ h29 = LCN_BW_LMT / loop_bw; ++ d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) * ++ (fvco3 / 2 - PLL_2064_LOW_END_VCO)) / ++ (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO)) ++ + PLL_2064_LOW_END_KVCO; ++ h28_ten = (d28 * 10) / LCN_VCO_DIV; ++ e30 = (d30 - LCN_OFFSET) / LCN_FACT; ++ g30 = LCN_OFFSET + (e30 * LCN_FACT); ++ h30_ten = (g30 * 10) / LCN_CUR_DIV; ++ cp_current = ((LCN_CUR_LMT * h29 * LCN_MULT * 100) / h28_ten) / h30_ten; ++ mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current); ++ ++ if (channel >= 1 && channel <= 5) ++ write_radio_reg(pi, RADIO_2064_REG03C, 0x8); ++ else ++ write_radio_reg(pi, RADIO_2064_REG03C, 0x7); ++ write_radio_reg(pi, RADIO_2064_REG03D, 0x3); ++ ++ mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c); ++ udelay(1); ++ ++ wlc_2064_vco_cal(pi); ++ ++ write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup); ++ write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr); ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { ++ write_radio_reg(pi, RADIO_2064_REG038, 3); ++ write_radio_reg(pi, RADIO_2064_REG091, 7); ++ } ++} ++ ++static int ++wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type) ++{ ++ s16 filt_index = -1; ++ int j; ++ ++ u16 addr[] = { ++ 0x910, ++ 0x91e, ++ 0x91f, ++ 0x924, ++ 0x925, ++ 0x926, ++ 0x920, ++ 0x921, ++ 0x927, ++ 0x928, ++ 0x929, ++ 0x922, ++ 0x923, ++ 0x930, ++ 0x931, ++ 0x932 ++ }; ++ ++ u16 addr_ofdm[] = { ++ 0x90f, ++ 0x900, ++ 0x901, ++ 0x906, ++ 0x907, ++ 0x908, ++ 0x902, ++ 0x903, ++ 0x909, ++ 0x90a, ++ 0x90b, ++ 0x904, ++ 0x905, ++ 0x90c, ++ 0x90d, ++ 0x90e ++ }; ++ ++ if (!is_ofdm) { ++ for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) { ++ if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) { ++ filt_index = (s16) j; ++ break; ++ } ++ } ++ ++ if (filt_index != -1) { ++ for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, addr[j], ++ LCNPHY_txdigfiltcoeffs_cck ++ [filt_index][j + 1]); ++ } ++ } else { ++ for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) { ++ if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) { ++ filt_index = (s16) j; ++ break; ++ } ++ } ++ ++ if (filt_index != -1) { ++ for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, addr_ofdm[j], ++ LCNPHY_txdigfiltcoeffs_ofdm ++ [filt_index][j + 1]); ++ } ++ } ++ ++ return (filt_index != -1) ? 0 : -1; ++} ++ ++void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec) ++{ ++ u8 channel = CHSPEC_CHANNEL(chanspec); ++ ++ wlc_phy_chanspec_radio_set((struct brcms_phy_pub *) pi, chanspec); ++ ++ wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec); ++ ++ or_phy_reg(pi, 0x44a, 0x44); ++ write_phy_reg(pi, 0x44a, 0x80); ++ ++ wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel); ++ udelay(1000); ++ ++ wlc_lcnphy_toggle_afe_pwdn(pi); ++ ++ write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20); ++ write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor); ++ ++ if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) { ++ mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8); ++ ++ wlc_lcnphy_load_tx_iir_filter(pi, false, 3); ++ } else { ++ mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8); ++ ++ wlc_lcnphy_load_tx_iir_filter(pi, false, 2); ++ } ++ ++ wlc_lcnphy_load_tx_iir_filter(pi, true, 0); ++ ++ mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3); ++ ++} ++ ++static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi) ++{ ++ u16 pa_gain; ++ ++ pa_gain = (read_phy_reg(pi, 0x4fb) & ++ LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >> ++ LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT; ++ ++ return pa_gain; ++} ++ ++static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi, ++ struct lcnphy_txgains *target_gains) ++{ ++ u16 pa_gain = wlc_lcnphy_get_pa_gain(pi); ++ ++ mod_phy_reg( ++ pi, 0x4b5, ++ (0xffff << 0), ++ ((target_gains->gm_gain) | ++ (target_gains->pga_gain << 8)) << ++ 0); ++ mod_phy_reg(pi, 0x4fb, ++ (0x7fff << 0), ++ ((target_gains->pad_gain) | (pa_gain << 8)) << 0); ++ ++ mod_phy_reg( ++ pi, 0x4fc, ++ (0xffff << 0), ++ ((target_gains->gm_gain) | ++ (target_gains->pga_gain << 8)) << ++ 0); ++ mod_phy_reg(pi, 0x4fd, ++ (0x7fff << 0), ++ ((target_gains->pad_gain) | (pa_gain << 8)) << 0); ++ ++ wlc_lcnphy_set_dac_gain(pi, target_gains->dac_gain); ++ ++ wlc_lcnphy_enable_tx_gain_override(pi); ++} ++ ++static void wlc_lcnphy_set_bbmult(struct brcms_phy *pi, u8 m0) ++{ ++ u16 m0m1 = (u16) m0 << 8; ++ struct phytbl_info tab; ++ ++ tab.tbl_ptr = &m0m1; ++ tab.tbl_len = 1; ++ tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; ++ tab.tbl_offset = 87; ++ tab.tbl_width = 16; ++ wlc_lcnphy_write_table(pi, &tab); ++} ++ ++static void wlc_lcnphy_clear_tx_power_offsets(struct brcms_phy *pi) ++{ ++ u32 data_buf[64]; ++ struct phytbl_info tab; ++ ++ memset(data_buf, 0, sizeof(data_buf)); ++ ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_ptr = data_buf; ++ ++ if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { ++ ++ tab.tbl_len = 30; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET; ++ wlc_lcnphy_write_table(pi, &tab); ++ } ++ ++ tab.tbl_len = 64; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_MAC_OFFSET; ++ wlc_lcnphy_write_table(pi, &tab); ++} ++ ++enum lcnphy_tssi_mode { ++ LCNPHY_TSSI_PRE_PA, ++ LCNPHY_TSSI_POST_PA, ++ LCNPHY_TSSI_EXT ++}; ++ ++static void ++wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos) ++{ ++ mod_phy_reg(pi, 0x4d7, (0x1 << 0), (0x1) << 0); ++ ++ mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1) << 6); ++ ++ if (LCNPHY_TSSI_POST_PA == pos) { ++ mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0) << 2); ++ ++ mod_phy_reg(pi, 0x4d9, (0x1 << 3), (1) << 3); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { ++ mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); ++ } else { ++ mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1); ++ mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); ++ } ++ } else { ++ mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2); ++ ++ mod_phy_reg(pi, 0x4d9, (0x1 << 3), (0) << 3); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { ++ mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); ++ } else { ++ mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0); ++ mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); ++ } ++ } ++ mod_phy_reg(pi, 0x637, (0x3 << 14), (0) << 14); ++ ++ if (LCNPHY_TSSI_EXT == pos) { ++ write_radio_reg(pi, RADIO_2064_REG07F, 1); ++ mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 0x2); ++ mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 0x1 << 7); ++ mod_radio_reg(pi, RADIO_2064_REG028, 0x1f, 0x3); ++ } ++} ++ ++static u16 wlc_lcnphy_rfseq_tbl_adc_pwrup(struct brcms_phy *pi) ++{ ++ u16 N1, N2, N3, N4, N5, N6, N; ++ N1 = ((read_phy_reg(pi, 0x4a5) & (0xff << 0)) ++ >> 0); ++ N2 = 1 << ((read_phy_reg(pi, 0x4a5) & (0x7 << 12)) ++ >> 12); ++ N3 = ((read_phy_reg(pi, 0x40d) & (0xff << 0)) ++ >> 0); ++ N4 = 1 << ((read_phy_reg(pi, 0x40d) & (0x7 << 8)) ++ >> 8); ++ N5 = ((read_phy_reg(pi, 0x4a2) & (0xff << 0)) ++ >> 0); ++ N6 = 1 << ((read_phy_reg(pi, 0x4a2) & (0x7 << 8)) ++ >> 8); ++ N = 2 * (N1 + N2 + N3 + N4 + 2 * (N5 + N6)) + 80; ++ if (N < 1600) ++ N = 1600; ++ return N; ++} ++ ++static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi) ++{ ++ u16 auxpga_vmid, auxpga_vmid_temp, auxpga_gain_temp; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ auxpga_vmid = (2 << 8) | ++ (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf; ++ auxpga_vmid_temp = (2 << 8) | (8 << 4) | 4; ++ auxpga_gain_temp = 2; ++ ++ mod_phy_reg(pi, 0x4d8, (0x1 << 0), (0) << 0); ++ ++ mod_phy_reg(pi, 0x4d8, (0x1 << 1), (0) << 1); ++ ++ mod_phy_reg(pi, 0x4d7, (0x1 << 3), (0) << 3); ++ ++ mod_phy_reg(pi, 0x4db, ++ (0x3ff << 0) | ++ (0x7 << 12), ++ (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12)); ++ ++ mod_phy_reg(pi, 0x4dc, ++ (0x3ff << 0) | ++ (0x7 << 12), ++ (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12)); ++ ++ mod_phy_reg(pi, 0x40a, ++ (0x3ff << 0) | ++ (0x7 << 12), ++ (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12)); ++ ++ mod_phy_reg(pi, 0x40b, ++ (0x3ff << 0) | ++ (0x7 << 12), ++ (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12)); ++ ++ mod_phy_reg(pi, 0x40c, ++ (0x3ff << 0) | ++ (0x7 << 12), ++ (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12)); ++ ++ mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5)); ++} ++ ++static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) ++{ ++ struct phytbl_info tab; ++ u32 rfseq, ind; ++ ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_ptr = &ind; ++ tab.tbl_len = 1; ++ tab.tbl_offset = 0; ++ for (ind = 0; ind < 128; ind++) { ++ wlc_lcnphy_write_table(pi, &tab); ++ tab.tbl_offset++; ++ } ++ tab.tbl_offset = 704; ++ for (ind = 0; ind < 128; ind++) { ++ wlc_lcnphy_write_table(pi, &tab); ++ tab.tbl_offset++; ++ } ++ mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0); ++ ++ mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2); ++ ++ mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4); ++ ++ wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT); ++ mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15); ++ ++ mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1ff << 0), (0) << 0); ++ ++ mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0); ++ ++ mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12); ++ ++ mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8); ++ ++ mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0); ++ ++ mod_phy_reg(pi, 0x40d, (0x7 << 8), (4) << 8); ++ ++ mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0); ++ ++ mod_phy_reg(pi, 0x4a2, (0x7 << 8), (4) << 8); ++ ++ mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (0) << 6); ++ ++ mod_phy_reg(pi, 0x4a8, (0xff << 0), (0x1) << 0); ++ ++ wlc_lcnphy_clear_tx_power_offsets(pi); ++ ++ mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15); ++ ++ mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (0xff) << 0); ++ ++ mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { ++ mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe); ++ mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); ++ } else { ++ mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1); ++ mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3); ++ } ++ ++ write_radio_reg(pi, RADIO_2064_REG025, 0xc); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { ++ mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1); ++ } else { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1); ++ else ++ mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 0 << 1); ++ } ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) ++ mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1); ++ else ++ mod_radio_reg(pi, RADIO_2064_REG03A, 0x4, 1 << 2); ++ ++ mod_radio_reg(pi, RADIO_2064_REG11A, 0x1, 1 << 0); ++ ++ mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 1 << 3); ++ ++ if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) ++ mod_phy_reg(pi, 0x4d7, ++ (0x1 << 3) | (0x7 << 12), 0 << 3 | 2 << 12); ++ ++ rfseq = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi); ++ tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; ++ tab.tbl_width = 16; ++ tab.tbl_ptr = &rfseq; ++ tab.tbl_len = 1; ++ tab.tbl_offset = 6; ++ wlc_lcnphy_write_table(pi, &tab); ++ ++ mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2); ++ ++ mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12); ++ ++ mod_phy_reg(pi, 0x4d7, (0x1 << 2), (1) << 2); ++ ++ mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8); ++ ++ wlc_lcnphy_pwrctrl_rssiparams(pi); ++} ++ ++void wlc_lcnphy_tx_pwr_update_npt(struct brcms_phy *pi) ++{ ++ u16 tx_cnt, tx_total, npt; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ tx_total = wlc_lcnphy_total_tx_frames(pi); ++ tx_cnt = tx_total - pi_lcn->lcnphy_tssi_tx_cnt; ++ npt = wlc_lcnphy_get_tx_pwr_npt(pi); ++ ++ if (tx_cnt > (1 << npt)) { ++ ++ pi_lcn->lcnphy_tssi_tx_cnt = tx_total; ++ ++ pi_lcn->lcnphy_tssi_idx = wlc_lcnphy_get_current_tx_pwr_idx(pi); ++ pi_lcn->lcnphy_tssi_npt = npt; ++ ++ } ++} ++ ++s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1) ++{ ++ s32 a, b, p; ++ ++ a = 32768 + (a1 * tssi); ++ b = (1024 * b0) + (64 * b1 * tssi); ++ p = ((2 * b) + a) / (2 * a); ++ ++ return p; ++} ++ ++static void wlc_lcnphy_txpower_reset_npt(struct brcms_phy *pi) ++{ ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) ++ return; ++ ++ pi_lcn->lcnphy_tssi_idx = LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313; ++ pi_lcn->lcnphy_tssi_npt = LCNPHY_TX_PWR_CTRL_START_NPT; ++} ++ ++void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi) ++{ ++ struct phytbl_info tab; ++ u32 rate_table[BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM + ++ BRCMS_NUM_RATES_MCS_1_STREAM]; ++ uint i, j; ++ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) ++ return; ++ ++ for (i = 0, j = 0; i < ARRAY_SIZE(rate_table); i++, j++) { ++ ++ if (i == BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM) ++ j = TXP_FIRST_MCS_20_SISO; ++ ++ rate_table[i] = (u32) ((s32) (-pi->tx_power_offset[j])); ++ } ++ ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_len = ARRAY_SIZE(rate_table); ++ tab.tbl_ptr = rate_table; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET; ++ wlc_lcnphy_write_table(pi, &tab); ++ ++ if (wlc_lcnphy_get_target_tx_pwr(pi) != pi->tx_power_min) { ++ wlc_lcnphy_set_target_tx_pwr(pi, pi->tx_power_min); ++ ++ wlc_lcnphy_txpower_reset_npt(pi); ++ } ++} ++ ++static void wlc_lcnphy_set_tx_pwr_soft_ctrl(struct brcms_phy *pi, s8 index) ++{ ++ u32 cck_offset[4] = { 22, 22, 22, 22 }; ++ u32 ofdm_offset, reg_offset_cck; ++ int i; ++ u16 index2; ++ struct phytbl_info tab; ++ ++ if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) ++ return; ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x0) << 14); ++ ++ or_phy_reg(pi, 0x6da, 0x0040); ++ ++ reg_offset_cck = 0; ++ for (i = 0; i < 4; i++) ++ cck_offset[i] -= reg_offset_cck; ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_len = 4; ++ tab.tbl_ptr = cck_offset; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET; ++ wlc_lcnphy_write_table(pi, &tab); ++ ofdm_offset = 0; ++ tab.tbl_len = 1; ++ tab.tbl_ptr = &ofdm_offset; ++ for (i = 836; i < 862; i++) { ++ tab.tbl_offset = i; ++ wlc_lcnphy_write_table(pi, &tab); ++ } ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0x1) << 15); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 13), (0x1) << 13); ++ ++ mod_phy_reg(pi, 0x4b0, (0x1 << 7), (0) << 7); ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 6), (0) << 6); ++ ++ mod_phy_reg(pi, 0x4a9, (0x1 << 15), (1) << 15); ++ ++ index2 = (u16) (index * 2); ++ mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0); ++ ++ mod_phy_reg(pi, 0x6a3, (0x1 << 4), (0) << 4); ++ ++} ++ ++static s8 wlc_lcnphy_tempcompensated_txpwrctrl(struct brcms_phy *pi) ++{ ++ s8 index, delta_brd, delta_temp, new_index, tempcorrx; ++ s16 manp, meas_temp, temp_diff; ++ bool neg = 0; ++ u16 temp; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) ++ return pi_lcn->lcnphy_current_index; ++ ++ index = FIXED_TXPWR; ++ ++ if (pi_lcn->lcnphy_tempsense_slope == 0) ++ return index; ++ ++ temp = (u16) wlc_lcnphy_tempsense(pi, 0); ++ meas_temp = LCNPHY_TEMPSENSE(temp); ++ ++ if (pi->tx_power_min != 0) ++ delta_brd = (pi_lcn->lcnphy_measPower - pi->tx_power_min); ++ else ++ delta_brd = 0; ++ ++ manp = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_rawtempsense); ++ temp_diff = manp - meas_temp; ++ if (temp_diff < 0) { ++ neg = 1; ++ temp_diff = -temp_diff; ++ } ++ ++ delta_temp = (s8) wlc_lcnphy_qdiv_roundup((u32) (temp_diff * 192), ++ (u32) (pi_lcn-> ++ lcnphy_tempsense_slope ++ * 10), 0); ++ if (neg) ++ delta_temp = -delta_temp; ++ ++ if (pi_lcn->lcnphy_tempsense_option == 3 ++ && LCNREV_IS(pi->pubpi.phy_rev, 0)) ++ delta_temp = 0; ++ if (pi_lcn->lcnphy_tempcorrx > 31) ++ tempcorrx = (s8) (pi_lcn->lcnphy_tempcorrx - 64); ++ else ++ tempcorrx = (s8) pi_lcn->lcnphy_tempcorrx; ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) ++ tempcorrx = 4; ++ new_index = ++ index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr; ++ new_index += tempcorrx; ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) ++ index = 127; ++ ++ if (new_index < 0 || new_index > 126) ++ return index; ++ ++ return new_index; ++} ++ ++static u16 wlc_lcnphy_set_tx_pwr_ctrl_mode(struct brcms_phy *pi, u16 mode) ++{ ++ ++ u16 current_mode = mode; ++ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && ++ mode == LCNPHY_TX_PWR_CTRL_HW) ++ current_mode = LCNPHY_TX_PWR_CTRL_TEMPBASED; ++ if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) && ++ mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) ++ current_mode = LCNPHY_TX_PWR_CTRL_HW; ++ return current_mode; ++} ++ ++void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode) ++{ ++ u16 old_mode = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ s8 index; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, mode); ++ old_mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, old_mode); ++ ++ mod_phy_reg(pi, 0x6da, (0x1 << 6), ++ ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 1 : 0) << 6); ++ ++ mod_phy_reg(pi, 0x6a3, (0x1 << 4), ++ ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 0 : 1) << 4); ++ ++ if (old_mode != mode) { ++ if (LCNPHY_TX_PWR_CTRL_HW == old_mode) { ++ ++ wlc_lcnphy_tx_pwr_update_npt(pi); ++ ++ wlc_lcnphy_clear_tx_power_offsets(pi); ++ } ++ if (LCNPHY_TX_PWR_CTRL_HW == mode) { ++ ++ wlc_lcnphy_txpower_recalc_target(pi); ++ ++ wlc_lcnphy_set_start_tx_pwr_idx(pi, ++ pi_lcn-> ++ lcnphy_tssi_idx); ++ wlc_lcnphy_set_tx_pwr_npt(pi, pi_lcn->lcnphy_tssi_npt); ++ mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0); ++ ++ pi_lcn->lcnphy_tssi_tx_cnt = ++ wlc_lcnphy_total_tx_frames(pi); ++ ++ wlc_lcnphy_disable_tx_gain_override(pi); ++ pi_lcn->lcnphy_tx_power_idx_override = -1; ++ } else ++ wlc_lcnphy_enable_tx_gain_override(pi); ++ ++ mod_phy_reg(pi, 0x4a4, ++ ((0x1 << 15) | (0x1 << 14) | (0x1 << 13)), mode); ++ if (mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) { ++ index = wlc_lcnphy_tempcompensated_txpwrctrl(pi); ++ wlc_lcnphy_set_tx_pwr_soft_ctrl(pi, index); ++ pi_lcn->lcnphy_current_index = (s8) ++ ((read_phy_reg(pi, ++ 0x4a9) & ++ 0xFF) / 2); ++ } ++ } ++} ++ ++static void ++wlc_lcnphy_tx_iqlo_loopback(struct brcms_phy *pi, u16 *values_to_save) ++{ ++ u16 vmid; ++ int i; ++ for (i = 0; i < 20; i++) ++ values_to_save[i] = ++ read_radio_reg(pi, iqlo_loopback_rf_regs[i]); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12); ++ mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11); ++ mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13); ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); ++ mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) ++ and_radio_reg(pi, RADIO_2064_REG03A, 0xFD); ++ else ++ and_radio_reg(pi, RADIO_2064_REG03A, 0xF9); ++ or_radio_reg(pi, RADIO_2064_REG11A, 0x1); ++ ++ or_radio_reg(pi, RADIO_2064_REG036, 0x01); ++ or_radio_reg(pi, RADIO_2064_REG11A, 0x18); ++ udelay(20); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) ++ mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0); ++ else ++ or_radio_reg(pi, RADIO_2064_REG03A, 1); ++ } else { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) ++ mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1); ++ else ++ or_radio_reg(pi, RADIO_2064_REG03A, 0x3); ++ } ++ ++ udelay(20); ++ ++ write_radio_reg(pi, RADIO_2064_REG025, 0xF); ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) ++ mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4); ++ else ++ mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6); ++ } else { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) ++ mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1); ++ else ++ mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1); ++ } ++ ++ udelay(20); ++ ++ write_radio_reg(pi, RADIO_2064_REG005, 0x8); ++ or_radio_reg(pi, RADIO_2064_REG112, 0x80); ++ udelay(20); ++ ++ or_radio_reg(pi, RADIO_2064_REG0FF, 0x10); ++ or_radio_reg(pi, RADIO_2064_REG11F, 0x44); ++ udelay(20); ++ ++ or_radio_reg(pi, RADIO_2064_REG00B, 0x7); ++ or_radio_reg(pi, RADIO_2064_REG113, 0x10); ++ udelay(20); ++ ++ write_radio_reg(pi, RADIO_2064_REG007, 0x1); ++ udelay(20); ++ ++ vmid = 0x2A6; ++ mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3); ++ write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff)); ++ or_radio_reg(pi, RADIO_2064_REG11F, 0x44); ++ udelay(20); ++ ++ or_radio_reg(pi, RADIO_2064_REG0FF, 0x10); ++ udelay(20); ++ write_radio_reg(pi, RADIO_2064_REG012, 0x02); ++ or_radio_reg(pi, RADIO_2064_REG112, 0x06); ++ write_radio_reg(pi, RADIO_2064_REG036, 0x11); ++ write_radio_reg(pi, RADIO_2064_REG059, 0xcc); ++ write_radio_reg(pi, RADIO_2064_REG05C, 0x2e); ++ write_radio_reg(pi, RADIO_2064_REG078, 0xd7); ++ write_radio_reg(pi, RADIO_2064_REG092, 0x15); ++} ++ ++static bool wlc_lcnphy_iqcal_wait(struct brcms_phy *pi) ++{ ++ uint delay_count = 0; ++ ++ while (wlc_lcnphy_iqcal_active(pi)) { ++ udelay(100); ++ delay_count++; ++ ++ if (delay_count > (10 * 500)) ++ break; ++ } ++ ++ return (0 == wlc_lcnphy_iqcal_active(pi)); ++} ++ ++static void ++wlc_lcnphy_tx_iqlo_loopback_cleanup(struct brcms_phy *pi, u16 *values_to_save) ++{ ++ int i; ++ ++ and_phy_reg(pi, 0x44c, 0x0 >> 11); ++ ++ and_phy_reg(pi, 0x43b, 0xC); ++ ++ for (i = 0; i < 20; i++) ++ write_radio_reg(pi, iqlo_loopback_rf_regs[i], ++ values_to_save[i]); ++} ++ ++static void ++wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi, ++ struct lcnphy_txgains *target_gains, ++ enum lcnphy_cal_mode cal_mode, bool keep_tone) ++{ ++ ++ struct lcnphy_txgains cal_gains, temp_gains; ++ u16 hash; ++ u8 band_idx; ++ int j; ++ u16 ncorr_override[5]; ++ u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}; ++ ++ u16 commands_fullcal[] = { ++ 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 ++ }; ++ ++ u16 commands_recal[] = { ++ 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 ++ }; ++ ++ u16 command_nums_fullcal[] = { ++ 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 ++ }; ++ ++ u16 command_nums_recal[] = { ++ 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 ++ }; ++ u16 *command_nums = command_nums_fullcal; ++ ++ u16 *start_coeffs = NULL, *cal_cmds = NULL, cal_type, diq_start; ++ u16 tx_pwr_ctrl_old, save_txpwrctrlrfctrl2; ++ u16 save_sslpnCalibClkEnCtrl, save_sslpnRxFeClkEnCtrl; ++ bool tx_gain_override_old; ++ struct lcnphy_txgains old_gains; ++ uint i, n_cal_cmds = 0, n_cal_start = 0; ++ u16 *values_to_save; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ values_to_save = kmalloc(sizeof(u16) * 20, GFP_ATOMIC); ++ if (NULL == values_to_save) ++ return; ++ ++ save_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); ++ save_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); ++ ++ or_phy_reg(pi, 0x6da, 0x40); ++ or_phy_reg(pi, 0x6db, 0x3); ++ ++ switch (cal_mode) { ++ case LCNPHY_CAL_FULL: ++ start_coeffs = syst_coeffs; ++ cal_cmds = commands_fullcal; ++ n_cal_cmds = ARRAY_SIZE(commands_fullcal); ++ break; ++ ++ case LCNPHY_CAL_RECAL: ++ start_coeffs = syst_coeffs; ++ cal_cmds = commands_recal; ++ n_cal_cmds = ARRAY_SIZE(commands_recal); ++ command_nums = command_nums_recal; ++ break; ++ ++ default: ++ break; ++ } ++ ++ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ start_coeffs, 11, 16, 64); ++ ++ write_phy_reg(pi, 0x6da, 0xffff); ++ mod_phy_reg(pi, 0x503, (0x1 << 3), (1) << 3); ++ ++ tx_pwr_ctrl_old = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12); ++ ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); ++ ++ save_txpwrctrlrfctrl2 = read_phy_reg(pi, 0x4db); ++ ++ mod_phy_reg(pi, 0x4db, (0x3ff << 0), (0x2a6) << 0); ++ ++ mod_phy_reg(pi, 0x4db, (0x7 << 12), (2) << 12); ++ ++ wlc_lcnphy_tx_iqlo_loopback(pi, values_to_save); ++ ++ tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); ++ if (tx_gain_override_old) ++ wlc_lcnphy_get_tx_gain(pi, &old_gains); ++ ++ if (!target_gains) { ++ if (!tx_gain_override_old) ++ wlc_lcnphy_set_tx_pwr_by_index(pi, ++ pi_lcn->lcnphy_tssi_idx); ++ wlc_lcnphy_get_tx_gain(pi, &temp_gains); ++ target_gains = &temp_gains; ++ } ++ ++ hash = (target_gains->gm_gain << 8) | ++ (target_gains->pga_gain << 4) | (target_gains->pad_gain); ++ ++ band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0); ++ ++ cal_gains = *target_gains; ++ memset(ncorr_override, 0, sizeof(ncorr_override)); ++ for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) { ++ if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) { ++ cal_gains.gm_gain = ++ tbl_iqcal_gainparams_lcnphy[band_idx][j][1]; ++ cal_gains.pga_gain = ++ tbl_iqcal_gainparams_lcnphy[band_idx][j][2]; ++ cal_gains.pad_gain = ++ tbl_iqcal_gainparams_lcnphy[band_idx][j][3]; ++ memcpy(ncorr_override, ++ &tbl_iqcal_gainparams_lcnphy[band_idx][j][3], ++ sizeof(ncorr_override)); ++ break; ++ } ++ } ++ ++ wlc_lcnphy_set_tx_gain(pi, &cal_gains); ++ ++ write_phy_reg(pi, 0x453, 0xaa9); ++ write_phy_reg(pi, 0x93d, 0xc0); ++ ++ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ lcnphy_iqcal_loft_gainladder, ++ ARRAY_SIZE(lcnphy_iqcal_loft_gainladder), ++ 16, 0); ++ ++ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ lcnphy_iqcal_ir_gainladder, ++ ARRAY_SIZE( ++ lcnphy_iqcal_ir_gainladder), 16, ++ 32); ++ ++ if (pi->phy_tx_tone_freq) { ++ ++ wlc_lcnphy_stop_tx_tone(pi); ++ udelay(5); ++ wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1); ++ } else { ++ wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1); ++ } ++ ++ write_phy_reg(pi, 0x6da, 0xffff); ++ ++ for (i = n_cal_start; i < n_cal_cmds; i++) { ++ u16 zero_diq = 0; ++ u16 best_coeffs[11]; ++ u16 command_num; ++ ++ cal_type = (cal_cmds[i] & 0x0f00) >> 8; ++ ++ command_num = command_nums[i]; ++ if (ncorr_override[cal_type]) ++ command_num = ++ ncorr_override[cal_type] << 8 | (command_num & ++ 0xff); ++ ++ write_phy_reg(pi, 0x452, command_num); ++ ++ if ((cal_type == 3) || (cal_type == 4)) { ++ wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ &diq_start, 1, 16, 69); ++ ++ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ &zero_diq, 1, 16, 69); ++ } ++ ++ write_phy_reg(pi, 0x451, cal_cmds[i]); ++ ++ if (!wlc_lcnphy_iqcal_wait(pi)) ++ goto cleanup; ++ ++ wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ best_coeffs, ++ ARRAY_SIZE(best_coeffs), 16, 96); ++ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ best_coeffs, ++ ARRAY_SIZE(best_coeffs), 16, 64); ++ ++ if ((cal_type == 3) || (cal_type == 4)) ++ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ &diq_start, 1, 16, 69); ++ wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ pi_lcn->lcnphy_cal_results. ++ txiqlocal_bestcoeffs, ++ ARRAY_SIZE(pi_lcn-> ++ lcnphy_cal_results. ++ txiqlocal_bestcoeffs), ++ 16, 96); ++ } ++ ++ wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ pi_lcn->lcnphy_cal_results. ++ txiqlocal_bestcoeffs, ++ ARRAY_SIZE(pi_lcn->lcnphy_cal_results. ++ txiqlocal_bestcoeffs), 16, 96); ++ pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid = true; ++ ++ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ &pi_lcn->lcnphy_cal_results. ++ txiqlocal_bestcoeffs[0], 4, 16, 80); ++ ++ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ &pi_lcn->lcnphy_cal_results. ++ txiqlocal_bestcoeffs[5], 2, 16, 85); ++ ++cleanup: ++ wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, values_to_save); ++ kfree(values_to_save); ++ ++ if (!keep_tone) ++ wlc_lcnphy_stop_tx_tone(pi); ++ ++ write_phy_reg(pi, 0x4db, save_txpwrctrlrfctrl2); ++ ++ write_phy_reg(pi, 0x453, 0); ++ ++ if (tx_gain_override_old) ++ wlc_lcnphy_set_tx_gain(pi, &old_gains); ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl_old); ++ ++ write_phy_reg(pi, 0x6da, save_sslpnCalibClkEnCtrl); ++ write_phy_reg(pi, 0x6db, save_sslpnRxFeClkEnCtrl); ++ ++} ++ ++static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) ++{ ++ bool suspend, tx_gain_override_old; ++ struct lcnphy_txgains old_gains; ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ u16 idleTssi, idleTssi0_2C, idleTssi0_OB, idleTssi0_regvalue_OB, ++ idleTssi0_regvalue_2C; ++ u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ u16 SAVE_lpfgain = read_radio_reg(pi, RADIO_2064_REG112); ++ u16 SAVE_jtag_bb_afe_switch = ++ read_radio_reg(pi, RADIO_2064_REG007) & 1; ++ u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10; ++ u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4; ++ idleTssi = read_phy_reg(pi, 0x4ab); ++ suspend = ++ (0 == ++ (R_REG(&((struct brcms_phy *) pi)->regs->maccontrol) & ++ MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); ++ ++ tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); ++ wlc_lcnphy_get_tx_gain(pi, &old_gains); ++ ++ wlc_lcnphy_enable_tx_gain_override(pi); ++ wlc_lcnphy_set_tx_pwr_by_index(pi, 127); ++ write_radio_reg(pi, RADIO_2064_REG112, 0x6); ++ mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 1); ++ mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4); ++ mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2); ++ wlc_lcnphy_tssi_setup(pi); ++ wlc_phy_do_dummy_tx(pi, true, OFF); ++ idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0)) ++ >> 0); ++ ++ idleTssi0_2C = ((read_phy_reg(pi, 0x63e) & (0x1ff << 0)) ++ >> 0); ++ ++ if (idleTssi0_2C >= 256) ++ idleTssi0_OB = idleTssi0_2C - 256; ++ else ++ idleTssi0_OB = idleTssi0_2C + 256; ++ ++ idleTssi0_regvalue_OB = idleTssi0_OB; ++ if (idleTssi0_regvalue_OB >= 256) ++ idleTssi0_regvalue_2C = idleTssi0_regvalue_OB - 256; ++ else ++ idleTssi0_regvalue_2C = idleTssi0_regvalue_OB + 256; ++ mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (idleTssi0_regvalue_2C) << 0); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12); ++ ++ wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old); ++ wlc_lcnphy_set_tx_gain(pi, &old_gains); ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); ++ ++ write_radio_reg(pi, RADIO_2064_REG112, SAVE_lpfgain); ++ mod_radio_reg(pi, RADIO_2064_REG007, 0x1, SAVE_jtag_bb_afe_switch); ++ mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, SAVE_jtag_auxpga); ++ mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, SAVE_iqadc_aux_en); ++ mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1 << 7); ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++} ++ ++static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode) ++{ ++ bool suspend; ++ u16 save_txpwrCtrlEn; ++ u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain; ++ u16 auxpga_vmid; ++ struct phytbl_info tab; ++ u32 val; ++ u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025, ++ save_reg112; ++ u16 values_to_save[14]; ++ s8 index; ++ int i; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ udelay(999); ++ ++ save_reg007 = (u8) read_radio_reg(pi, RADIO_2064_REG007); ++ save_reg0FF = (u8) read_radio_reg(pi, RADIO_2064_REG0FF); ++ save_reg11F = (u8) read_radio_reg(pi, RADIO_2064_REG11F); ++ save_reg005 = (u8) read_radio_reg(pi, RADIO_2064_REG005); ++ save_reg025 = (u8) read_radio_reg(pi, RADIO_2064_REG025); ++ save_reg112 = (u8) read_radio_reg(pi, RADIO_2064_REG112); ++ ++ for (i = 0; i < 14; i++) ++ values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]); ++ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4); ++ ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); ++ index = pi_lcn->lcnphy_current_index; ++ wlc_lcnphy_set_tx_pwr_by_index(pi, 127); ++ mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 0x1); ++ mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 0x1 << 4); ++ mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0x1 << 2); ++ mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0); ++ ++ mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0) << 15); ++ ++ mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5); ++ ++ mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0); ++ ++ mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12); ++ ++ mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8); ++ ++ mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0); ++ ++ mod_phy_reg(pi, 0x40d, (0x7 << 8), (6) << 8); ++ ++ mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0); ++ ++ mod_phy_reg(pi, 0x4a2, (0x7 << 8), (6) << 8); ++ ++ mod_phy_reg(pi, 0x4d9, (0x7 << 4), (2) << 4); ++ ++ mod_phy_reg(pi, 0x4d9, (0x7 << 8), (3) << 8); ++ ++ mod_phy_reg(pi, 0x4d9, (0x7 << 12), (1) << 12); ++ ++ mod_phy_reg(pi, 0x4da, (0x1 << 12), (0) << 12); ++ ++ mod_phy_reg(pi, 0x4da, (0x1 << 13), (1) << 13); ++ ++ mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15); ++ ++ write_radio_reg(pi, RADIO_2064_REG025, 0xC); ++ ++ mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 0x1 << 3); ++ ++ mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2); ++ ++ mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12); ++ ++ val = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi); ++ tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; ++ tab.tbl_width = 16; ++ tab.tbl_len = 1; ++ tab.tbl_ptr = &val; ++ tab.tbl_offset = 6; ++ wlc_lcnphy_write_table(pi, &tab); ++ if (mode == TEMPSENSE) { ++ mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3); ++ ++ mod_phy_reg(pi, 0x4d7, (0x7 << 12), (1) << 12); ++ ++ auxpga_vmidcourse = 8; ++ auxpga_vmidfine = 0x4; ++ auxpga_gain = 2; ++ mod_radio_reg(pi, RADIO_2064_REG082, 0x20, 1 << 5); ++ } else { ++ mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3); ++ ++ mod_phy_reg(pi, 0x4d7, (0x7 << 12), (3) << 12); ++ ++ auxpga_vmidcourse = 7; ++ auxpga_vmidfine = 0xa; ++ auxpga_gain = 2; ++ } ++ auxpga_vmid = ++ (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine); ++ mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0); ++ ++ mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2); ++ ++ mod_phy_reg(pi, 0x4d8, (0x1 << 1), (1) << 1); ++ ++ mod_phy_reg(pi, 0x4d8, (0x7 << 12), (auxpga_gain) << 12); ++ ++ mod_phy_reg(pi, 0x4d0, (0x1 << 5), (1) << 5); ++ ++ write_radio_reg(pi, RADIO_2064_REG112, 0x6); ++ ++ wlc_phy_do_dummy_tx(pi, true, OFF); ++ if (!tempsense_done(pi)) ++ udelay(10); ++ ++ write_radio_reg(pi, RADIO_2064_REG007, (u16) save_reg007); ++ write_radio_reg(pi, RADIO_2064_REG0FF, (u16) save_reg0FF); ++ write_radio_reg(pi, RADIO_2064_REG11F, (u16) save_reg11F); ++ write_radio_reg(pi, RADIO_2064_REG005, (u16) save_reg005); ++ write_radio_reg(pi, RADIO_2064_REG025, (u16) save_reg025); ++ write_radio_reg(pi, RADIO_2064_REG112, (u16) save_reg112); ++ for (i = 0; i < 14; i++) ++ write_phy_reg(pi, tempsense_phy_regs[i], values_to_save[i]); ++ wlc_lcnphy_set_tx_pwr_by_index(pi, (int)index); ++ ++ write_radio_reg(pi, 0x4a4, save_txpwrCtrlEn); ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++ udelay(999); ++} ++ ++static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi) ++{ ++ struct lcnphy_txgains tx_gains; ++ u8 bbmult; ++ struct phytbl_info tab; ++ s32 a1, b0, b1; ++ s32 tssi, pwr, maxtargetpwr, mintargetpwr; ++ bool suspend; ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ suspend = ++ (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ if (!pi->hwpwrctrl_capable) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ tx_gains.gm_gain = 4; ++ tx_gains.pga_gain = 12; ++ tx_gains.pad_gain = 12; ++ tx_gains.dac_gain = 0; ++ ++ bbmult = 150; ++ } else { ++ tx_gains.gm_gain = 7; ++ tx_gains.pga_gain = 15; ++ tx_gains.pad_gain = 14; ++ tx_gains.dac_gain = 0; ++ ++ bbmult = 150; ++ } ++ wlc_lcnphy_set_tx_gain(pi, &tx_gains); ++ wlc_lcnphy_set_bbmult(pi, bbmult); ++ wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); ++ } else { ++ ++ wlc_lcnphy_idle_tssi_est(ppi); ++ ++ wlc_lcnphy_clear_tx_power_offsets(pi); ++ ++ b0 = pi->txpa_2g[0]; ++ b1 = pi->txpa_2g[1]; ++ a1 = pi->txpa_2g[2]; ++ maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1); ++ mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1); ++ ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_ptr = &pwr; ++ tab.tbl_len = 1; ++ tab.tbl_offset = 0; ++ for (tssi = 0; tssi < 128; tssi++) { ++ pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1); ++ ++ pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr; ++ wlc_lcnphy_write_table(pi, &tab); ++ tab.tbl_offset++; ++ } ++ ++ mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7); ++ ++ write_phy_reg(pi, 0x4a8, 10); ++ ++ wlc_lcnphy_set_target_tx_pwr(pi, LCN_TARGET_PWR); ++ ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW); ++ } ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++} ++ ++static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi) ++{ ++ u16 m0m1; ++ struct phytbl_info tab; ++ ++ tab.tbl_ptr = &m0m1; ++ tab.tbl_len = 1; ++ tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; ++ tab.tbl_offset = 87; ++ tab.tbl_width = 16; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ return (u8) ((m0m1 & 0xff00) >> 8); ++} ++ ++static void wlc_lcnphy_set_pa_gain(struct brcms_phy *pi, u16 gain) ++{ ++ mod_phy_reg(pi, 0x4fb, ++ LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK, ++ gain << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT); ++ mod_phy_reg(pi, 0x4fd, ++ LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK, ++ gain << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT); ++} ++ ++void ++wlc_lcnphy_get_radio_loft(struct brcms_phy *pi, ++ u8 *ei0, u8 *eq0, u8 *fi0, u8 *fq0) ++{ ++ *ei0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG089)); ++ *eq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08A)); ++ *fi0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08B)); ++ *fq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08C)); ++} ++ ++void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b) ++{ ++ struct phytbl_info tab; ++ u16 iqcc[2]; ++ ++ iqcc[0] = a; ++ iqcc[1] = b; ++ ++ tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; ++ tab.tbl_width = 16; ++ tab.tbl_ptr = iqcc; ++ tab.tbl_len = 2; ++ tab.tbl_offset = 80; ++ wlc_lcnphy_write_table(pi, &tab); ++} ++ ++void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq) ++{ ++ struct phytbl_info tab; ++ ++ tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; ++ tab.tbl_width = 16; ++ tab.tbl_ptr = &didq; ++ tab.tbl_len = 1; ++ tab.tbl_offset = 85; ++ wlc_lcnphy_write_table(pi, &tab); ++} ++ ++void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index) ++{ ++ struct phytbl_info tab; ++ u16 a, b; ++ u8 bb_mult; ++ u32 bbmultiqcomp, txgain, locoeffs, rfpower; ++ struct lcnphy_txgains gains; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ pi_lcn->lcnphy_tx_power_idx_override = (s8) index; ++ pi_lcn->lcnphy_current_index = (u8) index; ++ ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_len = 1; ++ ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); ++ ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index; ++ tab.tbl_ptr = &bbmultiqcomp; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index; ++ tab.tbl_width = 32; ++ tab.tbl_ptr = &txgain; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ gains.gm_gain = (u16) (txgain & 0xff); ++ gains.pga_gain = (u16) (txgain >> 8) & 0xff; ++ gains.pad_gain = (u16) (txgain >> 16) & 0xff; ++ gains.dac_gain = (u16) (bbmultiqcomp >> 28) & 0x07; ++ wlc_lcnphy_set_tx_gain(pi, &gains); ++ wlc_lcnphy_set_pa_gain(pi, (u16) (txgain >> 24) & 0x7f); ++ ++ bb_mult = (u8) ((bbmultiqcomp >> 20) & 0xff); ++ wlc_lcnphy_set_bbmult(pi, bb_mult); ++ ++ wlc_lcnphy_enable_tx_gain_override(pi); ++ ++ if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { ++ ++ a = (u16) ((bbmultiqcomp >> 10) & 0x3ff); ++ b = (u16) (bbmultiqcomp & 0x3ff); ++ wlc_lcnphy_set_tx_iqcc(pi, a, b); ++ ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + index; ++ tab.tbl_ptr = &locoeffs; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ wlc_lcnphy_set_tx_locc(pi, (u16) locoeffs); ++ ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index; ++ tab.tbl_ptr = &rfpower; ++ wlc_lcnphy_read_table(pi, &tab); ++ mod_phy_reg(pi, 0x6a6, (0x1fff << 0), (rfpower * 8) << 0); ++ ++ } ++} ++ ++static void wlc_lcnphy_clear_papd_comptable(struct brcms_phy *pi) ++{ ++ u32 j; ++ struct phytbl_info tab; ++ u32 temp_offset[128]; ++ tab.tbl_ptr = temp_offset; ++ tab.tbl_len = 128; ++ tab.tbl_id = LCNPHY_TBL_ID_PAPDCOMPDELTATBL; ++ tab.tbl_width = 32; ++ tab.tbl_offset = 0; ++ ++ memset(temp_offset, 0, sizeof(temp_offset)); ++ for (j = 1; j < 128; j += 2) ++ temp_offset[j] = 0x80000; ++ ++ wlc_lcnphy_write_table(pi, &tab); ++ return; ++} ++ ++void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable) ++{ ++ if (!bEnable) { ++ ++ and_phy_reg(pi, 0x43b, ~(u16) ((0x1 << 1) | (0x1 << 4))); ++ ++ mod_phy_reg(pi, 0x43c, (0x1 << 1), 1 << 1); ++ ++ and_phy_reg(pi, 0x44c, ++ ~(u16) ((0x1 << 3) | ++ (0x1 << 5) | ++ (0x1 << 12) | ++ (0x1 << 0) | (0x1 << 1) | (0x1 << 2))); ++ ++ and_phy_reg(pi, 0x44d, ++ ~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14))); ++ mod_phy_reg(pi, 0x44d, (0x1 << 2), 1 << 2); ++ ++ mod_phy_reg(pi, 0x44d, (0x1 << 1) | (0x1 << 0), (0x1 << 0)); ++ ++ and_phy_reg(pi, 0x4f9, ++ ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2))); ++ ++ and_phy_reg(pi, 0x4fa, ++ ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2))); ++ } else { ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); ++ mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 4), 1 << 4); ++ mod_phy_reg(pi, 0x43c, (0x1 << 6), 0 << 6); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12); ++ mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14); ++ ++ wlc_lcnphy_set_trsw_override(pi, true, false); ++ ++ mod_phy_reg(pi, 0x44d, (0x1 << 2), 0 << 2); ++ mod_phy_reg(pi, 0x44c, (0x1 << 2), 1 << 2); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3); ++ mod_phy_reg(pi, 0x44d, (0x1 << 3), 1 << 3); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5); ++ mod_phy_reg(pi, 0x44d, (0x1 << 5), 0 << 5); ++ ++ mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1); ++ mod_phy_reg(pi, 0x4fa, (0x1 << 1), 1 << 1); ++ ++ mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2); ++ mod_phy_reg(pi, 0x4fa, (0x1 << 2), 1 << 2); ++ ++ mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0x4fa, (0x1 << 0), 1 << 0); ++ } else { ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3); ++ mod_phy_reg(pi, 0x44d, (0x1 << 3), 0 << 3); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5); ++ mod_phy_reg(pi, 0x44d, (0x1 << 5), 1 << 5); ++ ++ mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1); ++ mod_phy_reg(pi, 0x4fa, (0x1 << 1), 0 << 1); ++ ++ mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2); ++ mod_phy_reg(pi, 0x4fa, (0x1 << 2), 0 << 2); ++ ++ mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0); ++ } ++ } ++} ++ ++static void ++wlc_lcnphy_run_samples(struct brcms_phy *pi, ++ u16 num_samps, ++ u16 num_loops, u16 wait, bool iqcalmode) ++{ ++ ++ or_phy_reg(pi, 0x6da, 0x8080); ++ ++ mod_phy_reg(pi, 0x642, (0x7f << 0), (num_samps - 1) << 0); ++ if (num_loops != 0xffff) ++ num_loops--; ++ mod_phy_reg(pi, 0x640, (0xffff << 0), num_loops << 0); ++ ++ mod_phy_reg(pi, 0x641, (0xffff << 0), wait << 0); ++ ++ if (iqcalmode) { ++ ++ and_phy_reg(pi, 0x453, (u16) ~(0x1 << 15)); ++ or_phy_reg(pi, 0x453, (0x1 << 15)); ++ } else { ++ write_phy_reg(pi, 0x63f, 1); ++ wlc_lcnphy_tx_pu(pi, 1); ++ } ++ ++ or_radio_reg(pi, RADIO_2064_REG112, 0x6); ++} ++ ++void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode) ++{ ++ ++ u8 phybw40; ++ phybw40 = CHSPEC_IS40(pi->radio_chanspec); ++ ++ if (LCNREV_LT(pi->pubpi.phy_rev, 2)) { ++ mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5); ++ mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9); ++ } else { ++ mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5); ++ mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9); ++ } ++ ++ if (phybw40 == 0) { ++ mod_phy_reg((pi), 0x410, ++ (0x1 << 6) | ++ (0x1 << 5), ++ ((CHSPEC_IS2G( ++ pi->radio_chanspec)) ? (!mode) : 0) << ++ 6 | (!mode) << 5); ++ mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7); ++ } ++} ++ ++void ++wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val, ++ bool iqcalmode) ++{ ++ u8 phy_bw; ++ u16 num_samps, t, k; ++ u32 bw; ++ s32 theta = 0, rot = 0; ++ struct cordic_iq tone_samp; ++ u32 data_buf[64]; ++ u16 i_samp, q_samp; ++ struct phytbl_info tab; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ pi->phy_tx_tone_freq = f_kHz; ++ ++ wlc_lcnphy_deaf_mode(pi, true); ++ ++ phy_bw = 40; ++ if (pi_lcn->lcnphy_spurmod) { ++ write_phy_reg(pi, 0x942, 0x2); ++ write_phy_reg(pi, 0x93b, 0x0); ++ write_phy_reg(pi, 0x93c, 0x0); ++ wlc_lcnphy_txrx_spur_avoidance_mode(pi, false); ++ } ++ ++ if (f_kHz) { ++ k = 1; ++ do { ++ bw = phy_bw * 1000 * k; ++ num_samps = bw / abs(f_kHz); ++ k++; ++ } while ((num_samps * (u32) (abs(f_kHz))) != bw); ++ } else ++ num_samps = 2; ++ ++ rot = ((f_kHz * 36) / phy_bw) / 100; ++ theta = 0; ++ ++ for (t = 0; t < num_samps; t++) { ++ ++ tone_samp = cordic_calc_iq(theta); ++ ++ theta += rot; ++ ++ i_samp = (u16) (FLOAT(tone_samp.i * max_val) & 0x3ff); ++ q_samp = (u16) (FLOAT(tone_samp.q * max_val) & 0x3ff); ++ data_buf[t] = (i_samp << 10) | q_samp; ++ } ++ ++ mod_phy_reg(pi, 0x6d6, (0x3 << 0), 0 << 0); ++ ++ mod_phy_reg(pi, 0x6da, (0x1 << 3), 1 << 3); ++ ++ tab.tbl_ptr = data_buf; ++ tab.tbl_len = num_samps; ++ tab.tbl_id = LCNPHY_TBL_ID_SAMPLEPLAY; ++ tab.tbl_offset = 0; ++ tab.tbl_width = 32; ++ wlc_lcnphy_write_table(pi, &tab); ++ ++ wlc_lcnphy_run_samples(pi, num_samps, 0xffff, 0, iqcalmode); ++} ++ ++void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi) ++{ ++ s16 playback_status; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ pi->phy_tx_tone_freq = 0; ++ if (pi_lcn->lcnphy_spurmod) { ++ write_phy_reg(pi, 0x942, 0x7); ++ write_phy_reg(pi, 0x93b, 0x2017); ++ write_phy_reg(pi, 0x93c, 0x27c5); ++ wlc_lcnphy_txrx_spur_avoidance_mode(pi, true); ++ } ++ ++ playback_status = read_phy_reg(pi, 0x644); ++ if (playback_status & (0x1 << 0)) { ++ wlc_lcnphy_tx_pu(pi, 0); ++ mod_phy_reg(pi, 0x63f, (0x1 << 1), 1 << 1); ++ } else if (playback_status & (0x1 << 1)) ++ mod_phy_reg(pi, 0x453, (0x1 << 15), 0 << 15); ++ ++ mod_phy_reg(pi, 0x6d6, (0x3 << 0), 1 << 0); ++ ++ mod_phy_reg(pi, 0x6da, (0x1 << 3), 0 << 3); ++ ++ mod_phy_reg(pi, 0x6da, (0x1 << 7), 0 << 7); ++ ++ and_radio_reg(pi, RADIO_2064_REG112, 0xFFF9); ++ ++ wlc_lcnphy_deaf_mode(pi, false); ++} ++ ++static void ++wlc_lcnphy_set_cc(struct brcms_phy *pi, int cal_type, s16 coeff_x, s16 coeff_y) ++{ ++ u16 di0dq0; ++ u16 x, y, data_rf; ++ int k; ++ switch (cal_type) { ++ case 0: ++ wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y); ++ break; ++ case 2: ++ di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff); ++ wlc_lcnphy_set_tx_locc(pi, di0dq0); ++ break; ++ case 3: ++ k = wlc_lcnphy_calc_floor(coeff_x, 0); ++ y = 8 + k; ++ k = wlc_lcnphy_calc_floor(coeff_x, 1); ++ x = 8 - k; ++ data_rf = (x * 16 + y); ++ write_radio_reg(pi, RADIO_2064_REG089, data_rf); ++ k = wlc_lcnphy_calc_floor(coeff_y, 0); ++ y = 8 + k; ++ k = wlc_lcnphy_calc_floor(coeff_y, 1); ++ x = 8 - k; ++ data_rf = (x * 16 + y); ++ write_radio_reg(pi, RADIO_2064_REG08A, data_rf); ++ break; ++ case 4: ++ k = wlc_lcnphy_calc_floor(coeff_x, 0); ++ y = 8 + k; ++ k = wlc_lcnphy_calc_floor(coeff_x, 1); ++ x = 8 - k; ++ data_rf = (x * 16 + y); ++ write_radio_reg(pi, RADIO_2064_REG08B, data_rf); ++ k = wlc_lcnphy_calc_floor(coeff_y, 0); ++ y = 8 + k; ++ k = wlc_lcnphy_calc_floor(coeff_y, 1); ++ x = 8 - k; ++ data_rf = (x * 16 + y); ++ write_radio_reg(pi, RADIO_2064_REG08C, data_rf); ++ break; ++ } ++} ++ ++static struct lcnphy_unsign16_struct ++wlc_lcnphy_get_cc(struct brcms_phy *pi, int cal_type) ++{ ++ u16 a, b, didq; ++ u8 di0, dq0, ei, eq, fi, fq; ++ struct lcnphy_unsign16_struct cc; ++ cc.re = 0; ++ cc.im = 0; ++ switch (cal_type) { ++ case 0: ++ wlc_lcnphy_get_tx_iqcc(pi, &a, &b); ++ cc.re = a; ++ cc.im = b; ++ break; ++ case 2: ++ didq = wlc_lcnphy_get_tx_locc(pi); ++ di0 = (((didq & 0xff00) << 16) >> 24); ++ dq0 = (((didq & 0x00ff) << 24) >> 24); ++ cc.re = (u16) di0; ++ cc.im = (u16) dq0; ++ break; ++ case 3: ++ wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq); ++ cc.re = (u16) ei; ++ cc.im = (u16) eq; ++ break; ++ case 4: ++ wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq); ++ cc.re = (u16) fi; ++ cc.im = (u16) fq; ++ break; ++ } ++ return cc; ++} ++ ++static void ++wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh, ++ s16 *ptr, int mode) ++{ ++ u32 curval1, curval2, stpptr, curptr, strptr, val; ++ u16 sslpnCalibClkEnCtrl, timer; ++ u16 old_sslpnCalibClkEnCtrl; ++ s16 imag, real; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ timer = 0; ++ old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); ++ ++ curval1 = R_REG(&pi->regs->psm_corectlsts); ++ ptr[130] = 0; ++ W_REG(&pi->regs->psm_corectlsts, ((1 << 6) | curval1)); ++ ++ W_REG(&pi->regs->smpl_clct_strptr, 0x7E00); ++ W_REG(&pi->regs->smpl_clct_stpptr, 0x8000); ++ udelay(20); ++ curval2 = R_REG(&pi->regs->psm_phy_hdr_param); ++ W_REG(&pi->regs->psm_phy_hdr_param, curval2 | 0x30); ++ ++ write_phy_reg(pi, 0x555, 0x0); ++ write_phy_reg(pi, 0x5a6, 0x5); ++ ++ write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6)); ++ write_phy_reg(pi, 0x5cf, 3); ++ write_phy_reg(pi, 0x5a5, 0x3); ++ write_phy_reg(pi, 0x583, 0x0); ++ write_phy_reg(pi, 0x584, 0x0); ++ write_phy_reg(pi, 0x585, 0x0fff); ++ write_phy_reg(pi, 0x586, 0x0000); ++ ++ write_phy_reg(pi, 0x580, 0x4501); ++ ++ sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); ++ write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008)); ++ stpptr = R_REG(&pi->regs->smpl_clct_stpptr); ++ curptr = R_REG(&pi->regs->smpl_clct_curptr); ++ do { ++ udelay(10); ++ curptr = R_REG(&pi->regs->smpl_clct_curptr); ++ timer++; ++ } while ((curptr != stpptr) && (timer < 500)); ++ ++ W_REG(&pi->regs->psm_phy_hdr_param, 0x2); ++ strptr = 0x7E00; ++ W_REG(&pi->regs->tplatewrptr, strptr); ++ while (strptr < 0x8000) { ++ val = R_REG(&pi->regs->tplatewrdata); ++ imag = ((val >> 16) & 0x3ff); ++ real = ((val) & 0x3ff); ++ if (imag > 511) ++ imag -= 1024; ++ ++ if (real > 511) ++ real -= 1024; ++ ++ if (pi_lcn->lcnphy_iqcal_swp_dis) ++ ptr[(strptr - 0x7E00) / 4] = real; ++ else ++ ptr[(strptr - 0x7E00) / 4] = imag; ++ ++ if (clip_detect_algo) { ++ if (imag > thresh || imag < -thresh) { ++ strptr = 0x8000; ++ ptr[130] = 1; ++ } ++ } ++ ++ strptr += 4; ++ } ++ ++ write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); ++ W_REG(&pi->regs->psm_phy_hdr_param, curval2); ++ W_REG(&pi->regs->psm_corectlsts, curval1); ++} ++ ++static void ++wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels, ++ int step_size_lg2) ++{ ++ const struct lcnphy_spb_tone *phy_c1; ++ struct lcnphy_spb_tone phy_c2; ++ struct lcnphy_unsign16_struct phy_c3; ++ int phy_c4, phy_c5, k, l, j, phy_c6; ++ u16 phy_c7, phy_c8, phy_c9; ++ s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16; ++ s16 *ptr, phy_c17; ++ s32 phy_c18, phy_c19; ++ u32 phy_c20, phy_c21; ++ bool phy_c22, phy_c23, phy_c24, phy_c25; ++ u16 phy_c26, phy_c27; ++ u16 phy_c28, phy_c29, phy_c30; ++ u16 phy_c31; ++ u16 *phy_c32; ++ phy_c21 = 0; ++ phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0; ++ ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC); ++ if (NULL == ptr) ++ return; ++ ++ phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC); ++ if (NULL == phy_c32) { ++ kfree(ptr); ++ return; ++ } ++ phy_c26 = read_phy_reg(pi, 0x6da); ++ phy_c27 = read_phy_reg(pi, 0x6db); ++ phy_c31 = read_radio_reg(pi, RADIO_2064_REG026); ++ write_phy_reg(pi, 0x93d, 0xC0); ++ ++ wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0); ++ write_phy_reg(pi, 0x6da, 0xffff); ++ or_phy_reg(pi, 0x6db, 0x3); ++ ++ wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32); ++ udelay(500); ++ phy_c28 = read_phy_reg(pi, 0x938); ++ phy_c29 = read_phy_reg(pi, 0x4d7); ++ phy_c30 = read_phy_reg(pi, 0x4d8); ++ or_phy_reg(pi, 0x938, 0x1 << 2); ++ or_phy_reg(pi, 0x4d7, 0x1 << 2); ++ or_phy_reg(pi, 0x4d7, 0x1 << 3); ++ mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12); ++ or_phy_reg(pi, 0x4d8, 1 << 0); ++ or_phy_reg(pi, 0x4d8, 1 << 1); ++ mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2); ++ mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12); ++ phy_c1 = &lcnphy_spb_tone_3750[0]; ++ phy_c4 = 32; ++ ++ if (num_levels == 0) { ++ if (cal_type != 0) ++ num_levels = 4; ++ else ++ num_levels = 9; ++ } ++ if (step_size_lg2 == 0) { ++ if (cal_type != 0) ++ step_size_lg2 = 3; ++ else ++ step_size_lg2 = 8; ++ } ++ ++ phy_c7 = (1 << step_size_lg2); ++ phy_c3 = wlc_lcnphy_get_cc(pi, cal_type); ++ phy_c15 = (s16) phy_c3.re; ++ phy_c16 = (s16) phy_c3.im; ++ if (cal_type == 2) { ++ if (phy_c3.re > 127) ++ phy_c15 = phy_c3.re - 256; ++ if (phy_c3.im > 127) ++ phy_c16 = phy_c3.im - 256; ++ } ++ wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16); ++ udelay(20); ++ for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) { ++ phy_c23 = 1; ++ phy_c22 = 0; ++ switch (cal_type) { ++ case 0: ++ phy_c10 = 511; ++ break; ++ case 2: ++ phy_c10 = 127; ++ break; ++ case 3: ++ phy_c10 = 15; ++ break; ++ case 4: ++ phy_c10 = 15; ++ break; ++ } ++ ++ phy_c9 = read_phy_reg(pi, 0x93d); ++ phy_c9 = 2 * phy_c9; ++ phy_c24 = 0; ++ phy_c5 = 7; ++ phy_c25 = 1; ++ while (1) { ++ write_radio_reg(pi, RADIO_2064_REG026, ++ (phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4)); ++ udelay(50); ++ phy_c22 = 0; ++ ptr[130] = 0; ++ wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2); ++ if (ptr[130] == 1) ++ phy_c22 = 1; ++ if (phy_c22) ++ phy_c5 -= 1; ++ if ((phy_c22 != phy_c24) && (!phy_c25)) ++ break; ++ if (!phy_c22) ++ phy_c5 += 1; ++ if (phy_c5 <= 0 || phy_c5 >= 7) ++ break; ++ phy_c24 = phy_c22; ++ phy_c25 = 0; ++ } ++ ++ if (phy_c5 < 0) ++ phy_c5 = 0; ++ else if (phy_c5 > 7) ++ phy_c5 = 7; ++ ++ for (k = -phy_c7; k <= phy_c7; k += phy_c7) { ++ for (l = -phy_c7; l <= phy_c7; l += phy_c7) { ++ phy_c11 = phy_c15 + k; ++ phy_c12 = phy_c16 + l; ++ ++ if (phy_c11 < -phy_c10) ++ phy_c11 = -phy_c10; ++ else if (phy_c11 > phy_c10) ++ phy_c11 = phy_c10; ++ if (phy_c12 < -phy_c10) ++ phy_c12 = -phy_c10; ++ else if (phy_c12 > phy_c10) ++ phy_c12 = phy_c10; ++ wlc_lcnphy_set_cc(pi, cal_type, phy_c11, ++ phy_c12); ++ udelay(20); ++ wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2); ++ ++ phy_c18 = 0; ++ phy_c19 = 0; ++ for (j = 0; j < 128; j++) { ++ if (cal_type != 0) ++ phy_c6 = j % phy_c4; ++ else ++ phy_c6 = (2 * j) % phy_c4; ++ ++ phy_c2.re = phy_c1[phy_c6].re; ++ phy_c2.im = phy_c1[phy_c6].im; ++ phy_c17 = ptr[j]; ++ phy_c18 = phy_c18 + phy_c17 * phy_c2.re; ++ phy_c19 = phy_c19 + phy_c17 * phy_c2.im; ++ } ++ ++ phy_c18 = phy_c18 >> 10; ++ phy_c19 = phy_c19 >> 10; ++ phy_c20 = ((phy_c18 * phy_c18) + ++ (phy_c19 * phy_c19)); ++ ++ if (phy_c23 || phy_c20 < phy_c21) { ++ phy_c21 = phy_c20; ++ phy_c13 = phy_c11; ++ phy_c14 = phy_c12; ++ } ++ phy_c23 = 0; ++ } ++ } ++ phy_c23 = 1; ++ phy_c15 = phy_c13; ++ phy_c16 = phy_c14; ++ phy_c7 = phy_c7 >> 1; ++ wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16); ++ udelay(20); ++ } ++ goto cleanup; ++cleanup: ++ wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32); ++ wlc_lcnphy_stop_tx_tone(pi); ++ write_phy_reg(pi, 0x6da, phy_c26); ++ write_phy_reg(pi, 0x6db, phy_c27); ++ write_phy_reg(pi, 0x938, phy_c28); ++ write_phy_reg(pi, 0x4d7, phy_c29); ++ write_phy_reg(pi, 0x4d8, phy_c30); ++ write_radio_reg(pi, RADIO_2064_REG026, phy_c31); ++ ++ kfree(phy_c32); ++ kfree(ptr); ++} ++ ++void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b) ++{ ++ u16 iqcc[2]; ++ struct phytbl_info tab; ++ ++ tab.tbl_ptr = iqcc; ++ tab.tbl_len = 2; ++ tab.tbl_id = 0; ++ tab.tbl_offset = 80; ++ tab.tbl_width = 16; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ *a = iqcc[0]; ++ *b = iqcc[1]; ++} ++ ++static void wlc_lcnphy_tx_iqlo_soft_cal_full(struct brcms_phy *pi) ++{ ++ struct lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4; ++ ++ wlc_lcnphy_set_cc(pi, 0, 0, 0); ++ wlc_lcnphy_set_cc(pi, 2, 0, 0); ++ wlc_lcnphy_set_cc(pi, 3, 0, 0); ++ wlc_lcnphy_set_cc(pi, 4, 0, 0); ++ ++ wlc_lcnphy_a1(pi, 4, 0, 0); ++ wlc_lcnphy_a1(pi, 3, 0, 0); ++ wlc_lcnphy_a1(pi, 2, 3, 2); ++ wlc_lcnphy_a1(pi, 0, 5, 8); ++ wlc_lcnphy_a1(pi, 2, 2, 1); ++ wlc_lcnphy_a1(pi, 0, 4, 3); ++ ++ iqcc0 = wlc_lcnphy_get_cc(pi, 0); ++ locc2 = wlc_lcnphy_get_cc(pi, 2); ++ locc3 = wlc_lcnphy_get_cc(pi, 3); ++ locc4 = wlc_lcnphy_get_cc(pi, 4); ++} ++ ++u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi) ++{ ++ struct phytbl_info tab; ++ u16 didq; ++ ++ tab.tbl_id = 0; ++ tab.tbl_width = 16; ++ tab.tbl_ptr = &didq; ++ tab.tbl_len = 1; ++ tab.tbl_offset = 85; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ return didq; ++} ++ ++static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi) ++{ ++ ++ struct lcnphy_txgains target_gains, old_gains; ++ u8 save_bb_mult; ++ u16 a, b, didq, save_pa_gain = 0; ++ uint idx, SAVE_txpwrindex = 0xFF; ++ u32 val; ++ u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ struct phytbl_info tab; ++ u8 ei0, eq0, fi0, fq0; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ wlc_lcnphy_get_tx_gain(pi, &old_gains); ++ save_pa_gain = wlc_lcnphy_get_pa_gain(pi); ++ ++ save_bb_mult = wlc_lcnphy_get_bbmult(pi); ++ ++ if (SAVE_txpwrctrl == LCNPHY_TX_PWR_CTRL_OFF) ++ SAVE_txpwrindex = wlc_lcnphy_get_current_tx_pwr_idx(pi); ++ ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); ++ ++ target_gains.gm_gain = 7; ++ target_gains.pga_gain = 0; ++ target_gains.pad_gain = 21; ++ target_gains.dac_gain = 0; ++ wlc_lcnphy_set_tx_gain(pi, &target_gains); ++ wlc_lcnphy_set_tx_pwr_by_index(pi, 16); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) { ++ ++ wlc_lcnphy_set_tx_pwr_by_index(pi, 30); ++ ++ wlc_lcnphy_tx_iqlo_cal(pi, &target_gains, ++ (pi_lcn-> ++ lcnphy_recal ? LCNPHY_CAL_RECAL : ++ LCNPHY_CAL_FULL), false); ++ } else { ++ wlc_lcnphy_tx_iqlo_soft_cal_full(pi); ++ } ++ ++ wlc_lcnphy_get_radio_loft(pi, &ei0, &eq0, &fi0, &fq0); ++ if ((abs((s8) fi0) == 15) && (abs((s8) fq0) == 15)) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ target_gains.gm_gain = 255; ++ target_gains.pga_gain = 255; ++ target_gains.pad_gain = 0xf0; ++ target_gains.dac_gain = 0; ++ } else { ++ target_gains.gm_gain = 7; ++ target_gains.pga_gain = 45; ++ target_gains.pad_gain = 186; ++ target_gains.dac_gain = 0; ++ } ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1) ++ || pi_lcn->lcnphy_hw_iqcal_en) { ++ ++ target_gains.pga_gain = 0; ++ target_gains.pad_gain = 30; ++ wlc_lcnphy_set_tx_pwr_by_index(pi, 16); ++ wlc_lcnphy_tx_iqlo_cal(pi, &target_gains, ++ LCNPHY_CAL_FULL, false); ++ } else { ++ wlc_lcnphy_tx_iqlo_soft_cal_full(pi); ++ } ++ } ++ ++ wlc_lcnphy_get_tx_iqcc(pi, &a, &b); ++ ++ didq = wlc_lcnphy_get_tx_locc(pi); ++ ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_ptr = &val; ++ ++ tab.tbl_len = 1; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET; ++ ++ for (idx = 0; idx < 128; idx++) { ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + idx; ++ ++ wlc_lcnphy_read_table(pi, &tab); ++ val = (val & 0xfff00000) | ++ ((u32) (a & 0x3FF) << 10) | (b & 0x3ff); ++ wlc_lcnphy_write_table(pi, &tab); ++ ++ val = didq; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + idx; ++ wlc_lcnphy_write_table(pi, &tab); ++ } ++ ++ pi_lcn->lcnphy_cal_results.txiqlocal_a = a; ++ pi_lcn->lcnphy_cal_results.txiqlocal_b = b; ++ pi_lcn->lcnphy_cal_results.txiqlocal_didq = didq; ++ pi_lcn->lcnphy_cal_results.txiqlocal_ei0 = ei0; ++ pi_lcn->lcnphy_cal_results.txiqlocal_eq0 = eq0; ++ pi_lcn->lcnphy_cal_results.txiqlocal_fi0 = fi0; ++ pi_lcn->lcnphy_cal_results.txiqlocal_fq0 = fq0; ++ ++ wlc_lcnphy_set_bbmult(pi, save_bb_mult); ++ wlc_lcnphy_set_pa_gain(pi, save_pa_gain); ++ wlc_lcnphy_set_tx_gain(pi, &old_gains); ++ ++ if (SAVE_txpwrctrl != LCNPHY_TX_PWR_CTRL_OFF) ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); ++ else ++ wlc_lcnphy_set_tx_pwr_by_index(pi, SAVE_txpwrindex); ++} ++ ++s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode) ++{ ++ u16 tempsenseval1, tempsenseval2; ++ s16 avg = 0; ++ bool suspend = 0; ++ ++ if (mode == 1) { ++ suspend = ++ (0 == ++ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); ++ } ++ tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF; ++ tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF; ++ ++ if (tempsenseval1 > 255) ++ avg = (s16) (tempsenseval1 - 512); ++ else ++ avg = (s16) tempsenseval1; ++ ++ if (tempsenseval2 > 255) ++ avg += (s16) (tempsenseval2 - 512); ++ else ++ avg += (s16) tempsenseval2; ++ ++ avg /= 2; ++ ++ if (mode == 1) { ++ ++ mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14); ++ ++ udelay(100); ++ mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14); ++ ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++ } ++ return avg; ++} ++ ++u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode) ++{ ++ u16 tempsenseval1, tempsenseval2; ++ s32 avg = 0; ++ bool suspend = 0; ++ u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ if (mode == 1) { ++ suspend = ++ (0 == ++ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); ++ } ++ tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF; ++ tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF; ++ ++ if (tempsenseval1 > 255) ++ avg = (int)(tempsenseval1 - 512); ++ else ++ avg = (int)tempsenseval1; ++ ++ if (pi_lcn->lcnphy_tempsense_option == 1 || pi->hwpwrctrl_capable) { ++ if (tempsenseval2 > 255) ++ avg = (int)(avg - tempsenseval2 + 512); ++ else ++ avg = (int)(avg - tempsenseval2); ++ } else { ++ if (tempsenseval2 > 255) ++ avg = (int)(avg + tempsenseval2 - 512); ++ else ++ avg = (int)(avg + tempsenseval2); ++ avg = avg / 2; ++ } ++ if (avg < 0) ++ avg = avg + 512; ++ ++ if (pi_lcn->lcnphy_tempsense_option == 2) ++ avg = tempsenseval1; ++ ++ if (mode) ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); ++ ++ if (mode == 1) { ++ ++ mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14); ++ ++ udelay(100); ++ mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14); ++ ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++ } ++ return (u16) avg; ++} ++ ++s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode) ++{ ++ s32 degree = wlc_lcnphy_tempsense_new(pi, mode); ++ degree = ++ ((degree << ++ 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1)) ++ / LCN_TEMPSENSE_DEN; ++ return (s8) degree; ++} ++ ++s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode) ++{ ++ u16 vbatsenseval; ++ s32 avg = 0; ++ bool suspend = 0; ++ ++ if (mode == 1) { ++ suspend = ++ (0 == ++ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE); ++ } ++ ++ vbatsenseval = read_phy_reg(pi, 0x475) & 0x1FF; ++ ++ if (vbatsenseval > 255) ++ avg = (s32) (vbatsenseval - 512); ++ else ++ avg = (s32) vbatsenseval; ++ ++ avg = (avg * LCN_VBAT_SCALE_NOM + ++ (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN; ++ ++ if (mode == 1) { ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++ } ++ return (s8) avg; ++} ++ ++static void wlc_lcnphy_afe_clk_init(struct brcms_phy *pi, u8 mode) ++{ ++ u8 phybw40; ++ phybw40 = CHSPEC_IS40(pi->radio_chanspec); ++ ++ mod_phy_reg(pi, 0x6d1, (0x1 << 7), (1) << 7); ++ ++ if (((mode == AFE_CLK_INIT_MODE_PAPD) && (phybw40 == 0)) || ++ (mode == AFE_CLK_INIT_MODE_TXRX2X)) ++ write_phy_reg(pi, 0x6d0, 0x7); ++ ++ wlc_lcnphy_toggle_afe_pwdn(pi); ++} ++ ++static void wlc_lcnphy_temp_adj(struct brcms_phy *pi) ++{ ++} ++ ++static void wlc_lcnphy_glacial_timer_based_cal(struct brcms_phy *pi) ++{ ++ bool suspend; ++ s8 index; ++ u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ suspend = ++ (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ wlc_lcnphy_deaf_mode(pi, true); ++ pi->phy_lastcal = pi->sh->now; ++ pi->phy_forcecal = false; ++ index = pi_lcn->lcnphy_current_index; ++ ++ wlc_lcnphy_txpwrtbl_iqlo_cal(pi); ++ ++ wlc_lcnphy_set_tx_pwr_by_index(pi, index); ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl); ++ wlc_lcnphy_deaf_mode(pi, false); ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++ ++} ++ ++static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi) ++{ ++ bool suspend, full_cal; ++ const struct lcnphy_rx_iqcomp *rx_iqcomp; ++ int rx_iqcomp_sz; ++ u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ s8 index; ++ struct phytbl_info tab; ++ s32 a1, b0, b1; ++ s32 tssi, pwr, maxtargetpwr, mintargetpwr; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ pi->phy_lastcal = pi->sh->now; ++ pi->phy_forcecal = false; ++ full_cal = ++ (pi_lcn->lcnphy_full_cal_channel != ++ CHSPEC_CHANNEL(pi->radio_chanspec)); ++ pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec); ++ index = pi_lcn->lcnphy_current_index; ++ ++ suspend = ++ (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) { ++ wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000); ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ } ++ ++ wlc_lcnphy_deaf_mode(pi, true); ++ ++ wlc_lcnphy_txpwrtbl_iqlo_cal(pi); ++ ++ rx_iqcomp = lcnphy_rx_iqcomp_table_rev0; ++ rx_iqcomp_sz = ARRAY_SIZE(lcnphy_rx_iqcomp_table_rev0); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) ++ wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 40); ++ else ++ wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 127); ++ ++ if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) { ++ ++ wlc_lcnphy_idle_tssi_est((struct brcms_phy_pub *) pi); ++ ++ b0 = pi->txpa_2g[0]; ++ b1 = pi->txpa_2g[1]; ++ a1 = pi->txpa_2g[2]; ++ maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1); ++ mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1); ++ ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_ptr = &pwr; ++ tab.tbl_len = 1; ++ tab.tbl_offset = 0; ++ for (tssi = 0; tssi < 128; tssi++) { ++ pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1); ++ pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr; ++ wlc_lcnphy_write_table(pi, &tab); ++ tab.tbl_offset++; ++ } ++ } ++ ++ wlc_lcnphy_set_tx_pwr_by_index(pi, index); ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl); ++ wlc_lcnphy_deaf_mode(pi, false); ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++} ++ ++void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode) ++{ ++ u16 temp_new; ++ int temp1, temp2, temp_diff; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ switch (mode) { ++ case PHY_PERICAL_CHAN: ++ break; ++ case PHY_FULLCAL: ++ wlc_lcnphy_periodic_cal(pi); ++ break; ++ case PHY_PERICAL_PHYINIT: ++ wlc_lcnphy_periodic_cal(pi); ++ break; ++ case PHY_PERICAL_WATCHDOG: ++ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { ++ temp_new = wlc_lcnphy_tempsense(pi, 0); ++ temp1 = LCNPHY_TEMPSENSE(temp_new); ++ temp2 = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_cal_temper); ++ temp_diff = temp1 - temp2; ++ if ((pi_lcn->lcnphy_cal_counter > 90) || ++ (temp_diff > 60) || (temp_diff < -60)) { ++ wlc_lcnphy_glacial_timer_based_cal(pi); ++ wlc_2064_vco_cal(pi); ++ pi_lcn->lcnphy_cal_temper = temp_new; ++ pi_lcn->lcnphy_cal_counter = 0; ++ } else ++ pi_lcn->lcnphy_cal_counter++; ++ } ++ break; ++ case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL: ++ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) ++ wlc_lcnphy_tx_power_adjustment( ++ (struct brcms_phy_pub *) pi); ++ break; ++ } ++} ++ ++void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, s8 *cck_pwr) ++{ ++ s8 cck_offset; ++ u16 status; ++ status = (read_phy_reg(pi, 0x4ab)); ++ if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) && ++ (status & (0x1 << 15))) { ++ *ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0)) ++ >> 0) >> 1); ++ ++ if (wlc_phy_tpc_isenabled_lcnphy(pi)) ++ cck_offset = pi->tx_power_offset[TXP_FIRST_CCK]; ++ else ++ cck_offset = 0; ++ ++ *cck_pwr = *ofdm_pwr + cck_offset; ++ } else { ++ *cck_pwr = 0; ++ *ofdm_pwr = 0; ++ } ++} ++ ++void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi) ++{ ++ return; ++ ++} ++ ++void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi) ++{ ++ s8 index; ++ u16 index2; ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && ++ SAVE_txpwrctrl) { ++ index = wlc_lcnphy_tempcompensated_txpwrctrl(pi); ++ index2 = (u16) (index * 2); ++ mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0); ++ ++ pi_lcn->lcnphy_current_index = ++ (s8)((read_phy_reg(pi, 0x4a9) & 0xFF) / 2); ++ } ++} ++ ++static void ++wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi, ++ const struct lcnphy_tx_gain_tbl_entry *gain_table) ++{ ++ u32 j; ++ struct phytbl_info tab; ++ u32 val; ++ u16 pa_gain; ++ u16 gm_gain; ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) ++ pa_gain = 0x70; ++ else ++ pa_gain = 0x70; ++ ++ if (pi->sh->boardflags & BFL_FEM) ++ pa_gain = 0x10; ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_len = 1; ++ tab.tbl_ptr = &val; ++ ++ for (j = 0; j < 128; j++) { ++ gm_gain = gain_table[j].gm; ++ val = (((u32) pa_gain << 24) | ++ (gain_table[j].pad << 16) | ++ (gain_table[j].pga << 8) | gm_gain); ++ ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + j; ++ wlc_lcnphy_write_table(pi, &tab); ++ ++ val = (gain_table[j].dac << 28) | (gain_table[j].bb_mult << 20); ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + j; ++ wlc_lcnphy_write_table(pi, &tab); ++ } ++} ++ ++static void wlc_lcnphy_load_rfpower(struct brcms_phy *pi) ++{ ++ struct phytbl_info tab; ++ u32 val, bbmult, rfgain; ++ u8 index; ++ u8 scale_factor = 1; ++ s16 temp, temp1, temp2, qQ, qQ1, qQ2, shift; ++ ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_len = 1; ++ ++ for (index = 0; index < 128; index++) { ++ tab.tbl_ptr = &bbmult; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index; ++ wlc_lcnphy_read_table(pi, &tab); ++ bbmult = bbmult >> 20; ++ ++ tab.tbl_ptr = &rfgain; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ qm_log10((s32) (bbmult), 0, &temp1, &qQ1); ++ qm_log10((s32) (1 << 6), 0, &temp2, &qQ2); ++ ++ if (qQ1 < qQ2) { ++ temp2 = qm_shr16(temp2, qQ2 - qQ1); ++ qQ = qQ1; ++ } else { ++ temp1 = qm_shr16(temp1, qQ1 - qQ2); ++ qQ = qQ2; ++ } ++ temp = qm_sub16(temp1, temp2); ++ ++ if (qQ >= 4) ++ shift = qQ - 4; ++ else ++ shift = 4 - qQ; ++ ++ val = (((index << shift) + (5 * temp) + ++ (1 << (scale_factor + shift - 3))) >> (scale_factor + ++ shift - 2)); ++ ++ tab.tbl_ptr = &val; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index; ++ wlc_lcnphy_write_table(pi, &tab); ++ } ++} ++ ++static void wlc_lcnphy_bu_tweaks(struct brcms_phy *pi) ++{ ++ or_phy_reg(pi, 0x805, 0x1); ++ ++ mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0); ++ ++ mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0); ++ ++ write_phy_reg(pi, 0x414, 0x1e10); ++ write_phy_reg(pi, 0x415, 0x0640); ++ ++ mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8); ++ ++ or_phy_reg(pi, 0x44a, 0x44); ++ write_phy_reg(pi, 0x44a, 0x80); ++ mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0); ++ ++ mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0); ++ ++ if (!(pi->sh->boardrev < 0x1204)) ++ mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0); ++ ++ write_phy_reg(pi, 0x7d6, 0x0902); ++ mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0); ++ ++ mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { ++ mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0); ++ ++ mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0); ++ ++ mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0); ++ ++ mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0); ++ ++ mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2); ++ ++ mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4); ++ mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0); ++ mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90); ++ mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2); ++ mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0); ++ ++ mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2); ++ ++ wlc_lcnphy_clear_tx_power_offsets(pi); ++ mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6); ++ ++ } ++} ++ ++static void wlc_lcnphy_rcal(struct brcms_phy *pi) ++{ ++ u8 rcal_value; ++ ++ and_radio_reg(pi, RADIO_2064_REG05B, 0xfD); ++ ++ or_radio_reg(pi, RADIO_2064_REG004, 0x40); ++ or_radio_reg(pi, RADIO_2064_REG120, 0x10); ++ ++ or_radio_reg(pi, RADIO_2064_REG078, 0x80); ++ or_radio_reg(pi, RADIO_2064_REG129, 0x02); ++ ++ or_radio_reg(pi, RADIO_2064_REG057, 0x01); ++ ++ or_radio_reg(pi, RADIO_2064_REG05B, 0x02); ++ mdelay(5); ++ SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000); ++ ++ if (wlc_radio_2064_rcal_done(pi)) { ++ rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C); ++ rcal_value = rcal_value & 0x1f; ++ } ++ ++ and_radio_reg(pi, RADIO_2064_REG05B, 0xfD); ++ ++ and_radio_reg(pi, RADIO_2064_REG057, 0xFE); ++} ++ ++static void wlc_lcnphy_rc_cal(struct brcms_phy *pi) ++{ ++ u8 dflt_rc_cal_val; ++ u16 flt_val; ++ ++ dflt_rc_cal_val = 7; ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) ++ dflt_rc_cal_val = 11; ++ flt_val = ++ (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) | ++ (dflt_rc_cal_val); ++ write_phy_reg(pi, 0x933, flt_val); ++ write_phy_reg(pi, 0x934, flt_val); ++ write_phy_reg(pi, 0x935, flt_val); ++ write_phy_reg(pi, 0x936, flt_val); ++ write_phy_reg(pi, 0x937, (flt_val & 0x1FF)); ++ ++ return; ++} ++ ++static void wlc_radio_2064_init(struct brcms_phy *pi) ++{ ++ u32 i; ++ const struct lcnphy_radio_regs *lcnphyregs = NULL; ++ ++ lcnphyregs = lcnphy_radio_regs_2064; ++ ++ for (i = 0; lcnphyregs[i].address != 0xffff; i++) ++ if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a) ++ write_radio_reg(pi, ++ ((lcnphyregs[i].address & 0x3fff) | ++ RADIO_DEFAULT_CORE), ++ (u16) lcnphyregs[i].init_a); ++ else if (lcnphyregs[i].do_init_g) ++ write_radio_reg(pi, ++ ((lcnphyregs[i].address & 0x3fff) | ++ RADIO_DEFAULT_CORE), ++ (u16) lcnphyregs[i].init_g); ++ ++ write_radio_reg(pi, RADIO_2064_REG032, 0x62); ++ write_radio_reg(pi, RADIO_2064_REG033, 0x19); ++ ++ write_radio_reg(pi, RADIO_2064_REG090, 0x10); ++ ++ write_radio_reg(pi, RADIO_2064_REG010, 0x00); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { ++ ++ write_radio_reg(pi, RADIO_2064_REG060, 0x7f); ++ write_radio_reg(pi, RADIO_2064_REG061, 0x72); ++ write_radio_reg(pi, RADIO_2064_REG062, 0x7f); ++ } ++ ++ write_radio_reg(pi, RADIO_2064_REG01D, 0x02); ++ write_radio_reg(pi, RADIO_2064_REG01E, 0x06); ++ ++ mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0); ++ ++ mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3); ++ ++ mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6); ++ ++ mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9); ++ ++ mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12); ++ ++ write_phy_reg(pi, 0x4ea, 0x4688); ++ ++ mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0); ++ ++ mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6); ++ ++ mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0); ++ ++ wlc_lcnphy_set_tx_locc(pi, 0); ++ ++ wlc_lcnphy_rcal(pi); ++ ++ wlc_lcnphy_rc_cal(pi); ++} ++ ++static void wlc_lcnphy_radio_init(struct brcms_phy *pi) ++{ ++ wlc_radio_2064_init(pi); ++} ++ ++static void wlc_lcnphy_tbl_init(struct brcms_phy *pi) ++{ ++ uint idx; ++ u8 phybw40; ++ struct phytbl_info tab; ++ u32 val; ++ ++ phybw40 = CHSPEC_IS40(pi->radio_chanspec); ++ ++ for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++) ++ wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]); ++ ++ if (pi->sh->boardflags & BFL_FEM_BT) { ++ tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; ++ tab.tbl_width = 16; ++ tab.tbl_ptr = &val; ++ tab.tbl_len = 1; ++ val = 100; ++ tab.tbl_offset = 4; ++ wlc_lcnphy_write_table(pi, &tab); ++ } ++ ++ tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; ++ tab.tbl_width = 16; ++ tab.tbl_ptr = &val; ++ tab.tbl_len = 1; ++ ++ val = 114; ++ tab.tbl_offset = 0; ++ wlc_lcnphy_write_table(pi, &tab); ++ ++ val = 130; ++ tab.tbl_offset = 1; ++ wlc_lcnphy_write_table(pi, &tab); ++ ++ val = 6; ++ tab.tbl_offset = 8; ++ wlc_lcnphy_write_table(pi, &tab); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (pi->sh->boardflags & BFL_FEM) ++ wlc_lcnphy_load_tx_gain_table( ++ pi, ++ dot11lcnphy_2GHz_extPA_gaintable_rev0); ++ else ++ wlc_lcnphy_load_tx_gain_table( ++ pi, ++ dot11lcnphy_2GHz_gaintable_rev0); ++ } ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { ++ const struct phytbl_info *tb; ++ int l; ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ l = dot11lcnphytbl_rx_gain_info_2G_rev2_sz; ++ if (pi->sh->boardflags & BFL_EXTLNA) ++ tb = dot11lcnphytbl_rx_gain_info_extlna_2G_rev2; ++ else ++ tb = dot11lcnphytbl_rx_gain_info_2G_rev2; ++ } else { ++ l = dot11lcnphytbl_rx_gain_info_5G_rev2_sz; ++ if (pi->sh->boardflags & BFL_EXTLNA_5GHz) ++ tb = dot11lcnphytbl_rx_gain_info_extlna_5G_rev2; ++ else ++ tb = dot11lcnphytbl_rx_gain_info_5G_rev2; ++ } ++ ++ for (idx = 0; idx < l; idx++) ++ wlc_lcnphy_write_table(pi, &tb[idx]); ++ } ++ ++ if ((pi->sh->boardflags & BFL_FEM) ++ && !(pi->sh->boardflags & BFL_FEM_BT)) ++ wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa); ++ else if (pi->sh->boardflags & BFL_FEM_BT) { ++ if (pi->sh->boardrev < 0x1250) ++ wlc_lcnphy_write_table( ++ pi, ++ &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa); ++ else ++ wlc_lcnphy_write_table( ++ pi, ++ &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250); ++ } else ++ wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313); ++ ++ wlc_lcnphy_load_rfpower(pi); ++ ++ wlc_lcnphy_clear_papd_comptable(pi); ++} ++ ++static void wlc_lcnphy_rev0_baseband_init(struct brcms_phy *pi) ++{ ++ u16 afectrl1; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ write_radio_reg(pi, RADIO_2064_REG11C, 0x0); ++ ++ write_phy_reg(pi, 0x43b, 0x0); ++ write_phy_reg(pi, 0x43c, 0x0); ++ write_phy_reg(pi, 0x44c, 0x0); ++ write_phy_reg(pi, 0x4e6, 0x0); ++ write_phy_reg(pi, 0x4f9, 0x0); ++ write_phy_reg(pi, 0x4b0, 0x0); ++ write_phy_reg(pi, 0x938, 0x0); ++ write_phy_reg(pi, 0x4b0, 0x0); ++ write_phy_reg(pi, 0x44e, 0); ++ ++ or_phy_reg(pi, 0x567, 0x03); ++ ++ or_phy_reg(pi, 0x44a, 0x44); ++ write_phy_reg(pi, 0x44a, 0x80); ++ ++ if (!(pi->sh->boardflags & BFL_FEM)) ++ wlc_lcnphy_set_tx_pwr_by_index(pi, 52); ++ ++ if (0) { ++ afectrl1 = 0; ++ afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) | ++ (pi_lcn->lcnphy_rssi_vc << 4) | ++ (pi_lcn->lcnphy_rssi_gs << 10)); ++ write_phy_reg(pi, 0x43e, afectrl1); ++ } ++ ++ mod_phy_reg(pi, 0x634, (0xff << 0), 0xC << 0); ++ if (pi->sh->boardflags & BFL_FEM) { ++ mod_phy_reg(pi, 0x634, (0xff << 0), 0xA << 0); ++ ++ write_phy_reg(pi, 0x910, 0x1); ++ } ++ ++ mod_phy_reg(pi, 0x448, (0x3 << 8), 1 << 8); ++ mod_phy_reg(pi, 0x608, (0xff << 0), 0x17 << 0); ++ mod_phy_reg(pi, 0x604, (0x7ff << 0), 0x3EA << 0); ++ ++} ++ ++static void wlc_lcnphy_rev2_baseband_init(struct brcms_phy *pi) ++{ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0); ++ mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8); ++ } ++} ++ ++static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi) ++{ ++ s16 temp; ++ struct phytbl_info tab; ++ u32 tableBuffer[2]; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ temp = (s16) read_phy_reg(pi, 0x4df); ++ pi_lcn->lcnphy_ofdmgainidxtableoffset = (temp & (0xff << 0)) >> 0; ++ ++ if (pi_lcn->lcnphy_ofdmgainidxtableoffset > 127) ++ pi_lcn->lcnphy_ofdmgainidxtableoffset -= 256; ++ ++ pi_lcn->lcnphy_dsssgainidxtableoffset = (temp & (0xff << 8)) >> 8; ++ ++ if (pi_lcn->lcnphy_dsssgainidxtableoffset > 127) ++ pi_lcn->lcnphy_dsssgainidxtableoffset -= 256; ++ ++ tab.tbl_ptr = tableBuffer; ++ tab.tbl_len = 2; ++ tab.tbl_id = 17; ++ tab.tbl_offset = 59; ++ tab.tbl_width = 32; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ if (tableBuffer[0] > 63) ++ tableBuffer[0] -= 128; ++ pi_lcn->lcnphy_tr_R_gain_val = tableBuffer[0]; ++ ++ if (tableBuffer[1] > 63) ++ tableBuffer[1] -= 128; ++ pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1]; ++ ++ temp = (s16) (read_phy_reg(pi, 0x434) & (0xff << 0)); ++ if (temp > 127) ++ temp -= 256; ++ pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp; ++ ++ pi_lcn->lcnphy_Med_Low_Gain_db = ++ (read_phy_reg(pi, 0x424) & (0xff << 8)) >> 8; ++ pi_lcn->lcnphy_Very_Low_Gain_db = ++ (read_phy_reg(pi, 0x425) & (0xff << 0)) >> 0; ++ ++ tab.tbl_ptr = tableBuffer; ++ tab.tbl_len = 2; ++ tab.tbl_id = LCNPHY_TBL_ID_GAIN_IDX; ++ tab.tbl_offset = 28; ++ tab.tbl_width = 32; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ pi_lcn->lcnphy_gain_idx_14_lowword = tableBuffer[0]; ++ pi_lcn->lcnphy_gain_idx_14_hiword = tableBuffer[1]; ++ ++} ++ ++static void wlc_lcnphy_baseband_init(struct brcms_phy *pi) ++{ ++ ++ wlc_lcnphy_tbl_init(pi); ++ wlc_lcnphy_rev0_baseband_init(pi); ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) ++ wlc_lcnphy_rev2_baseband_init(pi); ++ wlc_lcnphy_bu_tweaks(pi); ++} ++ ++void wlc_phy_init_lcnphy(struct brcms_phy *pi) ++{ ++ u8 phybw40; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ phybw40 = CHSPEC_IS40(pi->radio_chanspec); ++ ++ pi_lcn->lcnphy_cal_counter = 0; ++ pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense; ++ ++ or_phy_reg(pi, 0x44a, 0x80); ++ and_phy_reg(pi, 0x44a, 0x7f); ++ ++ wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X); ++ ++ write_phy_reg(pi, 0x60a, 160); ++ ++ write_phy_reg(pi, 0x46a, 25); ++ ++ wlc_lcnphy_baseband_init(pi); ++ ++ wlc_lcnphy_radio_init(pi); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ wlc_lcnphy_tx_pwr_ctrl_init((struct brcms_phy_pub *) pi); ++ ++ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec); ++ ++ si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9); ++ ++ si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD); ++ ++ if ((pi->sh->boardflags & BFL_FEM) ++ && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) ++ wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR); ++ ++ wlc_lcnphy_agc_temp_init(pi); ++ ++ wlc_lcnphy_temp_adj(pi); ++ ++ mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14); ++ ++ udelay(100); ++ mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14); ++ ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW); ++ pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT; ++ wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT); ++} ++ ++static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) ++{ ++ s8 txpwr = 0; ++ int i; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ struct phy_shim_info *shim = pi->sh->physhim; ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ u16 cckpo = 0; ++ u32 offset_ofdm, offset_mcs; ++ ++ pi_lcn->lcnphy_tr_isolation_mid = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_TRISO2G); ++ ++ pi_lcn->lcnphy_rx_power_offset = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_RXPO2G); ++ ++ pi->txpa_2g[0] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B0); ++ pi->txpa_2g[1] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B1); ++ pi->txpa_2g[2] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B2); ++ ++ pi_lcn->lcnphy_rssi_vf = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMF2G); ++ pi_lcn->lcnphy_rssi_vc = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMC2G); ++ pi_lcn->lcnphy_rssi_gs = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISAV2G); ++ ++ pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf; ++ pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc; ++ pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs; ++ ++ pi_lcn->lcnphy_rssi_vf_hightemp = pi_lcn->lcnphy_rssi_vf; ++ pi_lcn->lcnphy_rssi_vc_hightemp = pi_lcn->lcnphy_rssi_vc; ++ pi_lcn->lcnphy_rssi_gs_hightemp = pi_lcn->lcnphy_rssi_gs; ++ ++ txpwr = (s8)wlapi_getintvar(shim, BRCMS_SROM_MAXP2GA0); ++ pi->tx_srom_max_2g = txpwr; ++ ++ for (i = 0; i < PWRTBL_NUM_COEFF; i++) { ++ pi->txpa_2g_low_temp[i] = pi->txpa_2g[i]; ++ pi->txpa_2g_high_temp[i] = pi->txpa_2g[i]; ++ } ++ ++ cckpo = (u16)wlapi_getintvar(shim, BRCMS_SROM_CCK2GPO); ++ offset_ofdm = (u32)wlapi_getintvar(shim, BRCMS_SROM_OFDM2GPO); ++ if (cckpo) { ++ uint max_pwr_chan = txpwr; ++ ++ for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) { ++ pi->tx_srom_max_rate_2g[i] = ++ max_pwr_chan - ((cckpo & 0xf) * 2); ++ cckpo >>= 4; ++ } ++ ++ for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) { ++ pi->tx_srom_max_rate_2g[i] = ++ max_pwr_chan - ++ ((offset_ofdm & 0xf) * 2); ++ offset_ofdm >>= 4; ++ } ++ } else { ++ u8 opo = 0; ++ ++ opo = (u8)wlapi_getintvar(shim, BRCMS_SROM_OPO); ++ ++ for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) ++ pi->tx_srom_max_rate_2g[i] = txpwr; ++ ++ for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) { ++ pi->tx_srom_max_rate_2g[i] = txpwr - ++ ((offset_ofdm & 0xf) * 2); ++ offset_ofdm >>= 4; ++ } ++ offset_mcs = ++ wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO1) << 16; ++ offset_mcs |= ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO0); ++ pi_lcn->lcnphy_mcs20_po = offset_mcs; ++ for (i = TXP_FIRST_SISO_MCS_20; ++ i <= TXP_LAST_SISO_MCS_20; i++) { ++ pi->tx_srom_max_rate_2g[i] = ++ txpwr - ((offset_mcs & 0xf) * 2); ++ offset_mcs >>= 4; ++ } ++ } ++ ++ pi_lcn->lcnphy_rawtempsense = ++ (u16)wlapi_getintvar(shim, BRCMS_SROM_RAWTEMPSENSE); ++ pi_lcn->lcnphy_measPower = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_MEASPOWER); ++ pi_lcn->lcnphy_tempsense_slope = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_SLOPE); ++ pi_lcn->lcnphy_hw_iqcal_en = ++ (bool)wlapi_getintvar(shim, BRCMS_SROM_HW_IQCAL_EN); ++ pi_lcn->lcnphy_iqcal_swp_dis = ++ (bool)wlapi_getintvar(shim, BRCMS_SROM_IQCAL_SWP_DIS); ++ pi_lcn->lcnphy_tempcorrx = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPCORRX); ++ pi_lcn->lcnphy_tempsense_option = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_OPTION); ++ pi_lcn->lcnphy_freqoffset_corr = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_FREQOFFSET_CORR); ++ if ((u8)wlapi_getintvar(shim, BRCMS_SROM_AA2G) > 1) ++ wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, ++ (u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G)); ++ } ++ pi_lcn->lcnphy_cck_dig_filt_type = -1; ++ ++ return true; ++} ++ ++void wlc_2064_vco_cal(struct brcms_phy *pi) ++{ ++ u8 calnrst; ++ ++ mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 1 << 3); ++ calnrst = (u8) read_radio_reg(pi, RADIO_2064_REG056) & 0xf8; ++ write_radio_reg(pi, RADIO_2064_REG056, calnrst); ++ udelay(1); ++ write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x03); ++ udelay(1); ++ write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x07); ++ udelay(300); ++ mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 0); ++} ++ ++bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi) ++{ ++ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) ++ return 0; ++ else ++ return (LCNPHY_TX_PWR_CTRL_HW == ++ wlc_lcnphy_get_tx_pwr_ctrl((pi))); ++} ++ ++void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi) ++{ ++ u16 pwr_ctrl; ++ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { ++ wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL); ++ } else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) { ++ pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); ++ wlc_lcnphy_txpower_recalc_target(pi); ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl); ++ } ++} ++ ++void wlc_phy_detach_lcnphy(struct brcms_phy *pi) ++{ ++ kfree(pi->u.pi_lcnphy); ++} ++ ++bool wlc_phy_attach_lcnphy(struct brcms_phy *pi) ++{ ++ struct brcms_phy_lcnphy *pi_lcn; ++ ++ pi->u.pi_lcnphy = kzalloc(sizeof(struct brcms_phy_lcnphy), GFP_ATOMIC); ++ if (pi->u.pi_lcnphy == NULL) ++ return false; ++ ++ pi_lcn = pi->u.pi_lcnphy; ++ ++ if (0 == (pi->sh->boardflags & BFL_NOPA)) { ++ pi->hwpwrctrl = true; ++ pi->hwpwrctrl_capable = true; ++ } ++ ++ pi->xtalfreq = si_pmu_alp_clock(pi->sh->sih); ++ pi_lcn->lcnphy_papd_rxGnCtrl_init = 0; ++ ++ pi->pi_fptr.init = wlc_phy_init_lcnphy; ++ pi->pi_fptr.calinit = wlc_phy_cal_init_lcnphy; ++ pi->pi_fptr.chanset = wlc_phy_chanspec_set_lcnphy; ++ pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_lcnphy; ++ pi->pi_fptr.txiqccget = wlc_lcnphy_get_tx_iqcc; ++ pi->pi_fptr.txiqccset = wlc_lcnphy_set_tx_iqcc; ++ pi->pi_fptr.txloccget = wlc_lcnphy_get_tx_locc; ++ pi->pi_fptr.radioloftget = wlc_lcnphy_get_radio_loft; ++ pi->pi_fptr.detach = wlc_phy_detach_lcnphy; ++ ++ if (!wlc_phy_txpwr_srom_read_lcnphy(pi)) ++ return false; ++ ++ if ((pi->sh->boardflags & BFL_FEM) && ++ (LCNREV_IS(pi->pubpi.phy_rev, 1))) { ++ if (pi_lcn->lcnphy_tempsense_option == 3) { ++ pi->hwpwrctrl = true; ++ pi->hwpwrctrl_capable = true; ++ pi->temppwrctrl_capable = false; ++ } else { ++ pi->hwpwrctrl = false; ++ pi->hwpwrctrl_capable = false; ++ pi->temppwrctrl_capable = true; ++ } ++ } ++ ++ return true; ++} ++ ++static void wlc_lcnphy_set_rx_gain(struct brcms_phy *pi, u32 gain) ++{ ++ u16 trsw, ext_lna, lna1, lna2, tia, biq0, biq1, gain0_15, gain16_19; ++ ++ trsw = (gain & ((u32) 1 << 28)) ? 0 : 1; ++ ext_lna = (u16) (gain >> 29) & 0x01; ++ lna1 = (u16) (gain >> 0) & 0x0f; ++ lna2 = (u16) (gain >> 4) & 0x0f; ++ tia = (u16) (gain >> 8) & 0xf; ++ biq0 = (u16) (gain >> 12) & 0xf; ++ biq1 = (u16) (gain >> 16) & 0xf; ++ ++ gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) | ++ ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) | ++ ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12)); ++ gain16_19 = biq1; ++ ++ mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0); ++ mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9); ++ mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10); ++ mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0); ++ mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11); ++ mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3); ++ } ++ wlc_lcnphy_rx_gain_override_enable(pi, true); ++} ++ ++static u32 wlc_lcnphy_get_receive_power(struct brcms_phy *pi, s32 *gain_index) ++{ ++ u32 received_power = 0; ++ s32 max_index = 0; ++ u32 gain_code = 0; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ max_index = 36; ++ if (*gain_index >= 0) ++ gain_code = lcnphy_23bitgaincode_table[*gain_index]; ++ ++ if (-1 == *gain_index) { ++ *gain_index = 0; ++ while ((*gain_index <= (s32) max_index) ++ && (received_power < 700)) { ++ wlc_lcnphy_set_rx_gain(pi, ++ lcnphy_23bitgaincode_table ++ [*gain_index]); ++ received_power = ++ wlc_lcnphy_measure_digital_power( ++ pi, ++ pi_lcn-> ++ lcnphy_noise_samples); ++ (*gain_index)++; ++ } ++ (*gain_index)--; ++ } else { ++ wlc_lcnphy_set_rx_gain(pi, gain_code); ++ received_power = ++ wlc_lcnphy_measure_digital_power(pi, ++ pi_lcn-> ++ lcnphy_noise_samples); ++ } ++ ++ return received_power; ++} ++ ++s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index) ++{ ++ s32 gain = 0; ++ s32 nominal_power_db; ++ s32 log_val, gain_mismatch, desired_gain, input_power_offset_db, ++ input_power_db; ++ s32 received_power, temperature; ++ u32 power; ++ u32 msb1, msb2, val1, val2, diff1, diff2; ++ uint freq; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ received_power = wlc_lcnphy_get_receive_power(pi, &gain_index); ++ ++ gain = lcnphy_gain_table[gain_index]; ++ ++ nominal_power_db = read_phy_reg(pi, 0x425) >> 8; ++ ++ power = (received_power * 16); ++ msb1 = ffs(power) - 1; ++ msb2 = msb1 + 1; ++ val1 = 1 << msb1; ++ val2 = 1 << msb2; ++ diff1 = (power - val1); ++ diff2 = (val2 - power); ++ if (diff1 < diff2) ++ log_val = msb1; ++ else ++ log_val = msb2; ++ ++ log_val = log_val * 3; ++ ++ gain_mismatch = (nominal_power_db / 2) - (log_val); ++ ++ desired_gain = gain + gain_mismatch; ++ ++ input_power_offset_db = read_phy_reg(pi, 0x434) & 0xFF; ++ ++ if (input_power_offset_db > 127) ++ input_power_offset_db -= 256; ++ ++ input_power_db = input_power_offset_db - desired_gain; ++ ++ input_power_db = ++ input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index]; ++ ++ freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec)); ++ if ((freq > 2427) && (freq <= 2467)) ++ input_power_db = input_power_db - 1; ++ ++ temperature = pi_lcn->lcnphy_lastsensed_temperature; ++ ++ if ((temperature - 15) < -30) ++ input_power_db = ++ input_power_db + ++ (((temperature - 10 - 25) * 286) >> 12) - ++ 7; ++ else if ((temperature - 15) < 4) ++ input_power_db = ++ input_power_db + ++ (((temperature - 10 - 25) * 286) >> 12) - ++ 3; ++ else ++ input_power_db = input_power_db + ++ (((temperature - 10 - 25) * 286) >> 12); ++ ++ wlc_lcnphy_rx_gain_override_enable(pi, 0); ++ ++ return input_power_db; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.h.orig 2011-11-09 13:46:58.258800470 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.h 2011-11-09 13:47:17.012566015 -0500 +@@ -0,0 +1,121 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_PHY_LCN_H_ ++#define _BRCM_PHY_LCN_H_ ++ ++#include ++ ++struct brcms_phy_lcnphy { ++ int lcnphy_txrf_sp_9_override; ++ u8 lcnphy_full_cal_channel; ++ u8 lcnphy_cal_counter; ++ u16 lcnphy_cal_temper; ++ bool lcnphy_recal; ++ ++ u8 lcnphy_rc_cap; ++ u32 lcnphy_mcs20_po; ++ ++ u8 lcnphy_tr_isolation_mid; ++ u8 lcnphy_tr_isolation_low; ++ u8 lcnphy_tr_isolation_hi; ++ ++ u8 lcnphy_bx_arch; ++ u8 lcnphy_rx_power_offset; ++ u8 lcnphy_rssi_vf; ++ u8 lcnphy_rssi_vc; ++ u8 lcnphy_rssi_gs; ++ u8 lcnphy_tssi_val; ++ u8 lcnphy_rssi_vf_lowtemp; ++ u8 lcnphy_rssi_vc_lowtemp; ++ u8 lcnphy_rssi_gs_lowtemp; ++ ++ u8 lcnphy_rssi_vf_hightemp; ++ u8 lcnphy_rssi_vc_hightemp; ++ u8 lcnphy_rssi_gs_hightemp; ++ ++ s16 lcnphy_pa0b0; ++ s16 lcnphy_pa0b1; ++ s16 lcnphy_pa0b2; ++ ++ u16 lcnphy_rawtempsense; ++ u8 lcnphy_measPower; ++ u8 lcnphy_tempsense_slope; ++ u8 lcnphy_freqoffset_corr; ++ u8 lcnphy_tempsense_option; ++ u8 lcnphy_tempcorrx; ++ bool lcnphy_iqcal_swp_dis; ++ bool lcnphy_hw_iqcal_en; ++ uint lcnphy_bandedge_corr; ++ bool lcnphy_spurmod; ++ u16 lcnphy_tssi_tx_cnt; ++ u16 lcnphy_tssi_idx; ++ u16 lcnphy_tssi_npt; ++ ++ u16 lcnphy_target_tx_freq; ++ s8 lcnphy_tx_power_idx_override; ++ u16 lcnphy_noise_samples; ++ ++ u32 lcnphy_papdRxGnIdx; ++ u32 lcnphy_papd_rxGnCtrl_init; ++ ++ u32 lcnphy_gain_idx_14_lowword; ++ u32 lcnphy_gain_idx_14_hiword; ++ u32 lcnphy_gain_idx_27_lowword; ++ u32 lcnphy_gain_idx_27_hiword; ++ s16 lcnphy_ofdmgainidxtableoffset; ++ s16 lcnphy_dsssgainidxtableoffset; ++ u32 lcnphy_tr_R_gain_val; ++ u32 lcnphy_tr_T_gain_val; ++ s8 lcnphy_input_pwr_offset_db; ++ u16 lcnphy_Med_Low_Gain_db; ++ u16 lcnphy_Very_Low_Gain_db; ++ s8 lcnphy_lastsensed_temperature; ++ s8 lcnphy_pkteng_rssi_slope; ++ u8 lcnphy_saved_tx_user_target[TXP_NUM_RATES]; ++ u8 lcnphy_volt_winner; ++ u8 lcnphy_volt_low; ++ u8 lcnphy_54_48_36_24mbps_backoff; ++ u8 lcnphy_11n_backoff; ++ u8 lcnphy_lowerofdm; ++ u8 lcnphy_cck; ++ u8 lcnphy_psat_2pt3_detected; ++ s32 lcnphy_lowest_Re_div_Im; ++ s8 lcnphy_final_papd_cal_idx; ++ u16 lcnphy_extstxctrl4; ++ u16 lcnphy_extstxctrl0; ++ u16 lcnphy_extstxctrl1; ++ s16 lcnphy_cck_dig_filt_type; ++ s16 lcnphy_ofdm_dig_filt_type; ++ struct lcnphy_cal_results lcnphy_cal_results; ++ ++ u8 lcnphy_psat_pwr; ++ u8 lcnphy_psat_indx; ++ s32 lcnphy_min_phase; ++ u8 lcnphy_final_idx; ++ u8 lcnphy_start_idx; ++ u8 lcnphy_current_index; ++ u16 lcnphy_logen_buf_1; ++ u16 lcnphy_local_ovr_2; ++ u16 lcnphy_local_oval_6; ++ u16 lcnphy_local_oval_5; ++ u16 lcnphy_logen_mixer_1; ++ ++ u8 lcnphy_aci_stat; ++ uint lcnphy_aci_start_time; ++ s8 lcnphy_tx_power_offset[TXP_NUM_RATES]; ++}; ++#endif /* _BRCM_PHY_LCN_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c.orig 2011-11-09 13:46:58.275800257 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c 2011-11-09 13:47:17.032565765 -0500 +@@ -0,0 +1,28876 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "phy_int.h" ++#include "phy_hal.h" ++#include "phy_radio.h" ++#include "phyreg_n.h" ++#include "phytbl_n.h" ++ ++#define READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name) \ ++ read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \ ++ ((core == PHY_CORE_0) ? \ ++ radio_type##_##jspace##0 : \ ++ radio_type##_##jspace##1)) ++ ++#define WRITE_RADIO_REG2(pi, radio_type, jspace, core, reg_name, value) \ ++ write_radio_reg(pi, radio_type##_##jspace##_##reg_name | \ ++ ((core == PHY_CORE_0) ? \ ++ radio_type##_##jspace##0 : \ ++ radio_type##_##jspace##1), value) ++ ++#define WRITE_RADIO_SYN(pi, radio_type, reg_name, value) \ ++ write_radio_reg(pi, radio_type##_##SYN##_##reg_name, value) ++ ++#define READ_RADIO_REG3(pi, radio_type, jspace, core, reg_name) \ ++ read_radio_reg(pi, ((core == PHY_CORE_0) ? \ ++ radio_type##_##jspace##0##_##reg_name : \ ++ radio_type##_##jspace##1##_##reg_name)) ++ ++#define WRITE_RADIO_REG3(pi, radio_type, jspace, core, reg_name, value) \ ++ write_radio_reg(pi, ((core == PHY_CORE_0) ? \ ++ radio_type##_##jspace##0##_##reg_name : \ ++ radio_type##_##jspace##1##_##reg_name), \ ++ value) ++ ++#define READ_RADIO_REG4(pi, radio_type, jspace, core, reg_name) \ ++ read_radio_reg(pi, ((core == PHY_CORE_0) ? \ ++ radio_type##_##reg_name##_##jspace##0 : \ ++ radio_type##_##reg_name##_##jspace##1)) ++ ++#define WRITE_RADIO_REG4(pi, radio_type, jspace, core, reg_name, value) \ ++ write_radio_reg(pi, ((core == PHY_CORE_0) ? \ ++ radio_type##_##reg_name##_##jspace##0 : \ ++ radio_type##_##reg_name##_##jspace##1), \ ++ value) ++ ++#define NPHY_ACI_MAX_UNDETECT_WINDOW_SZ 40 ++#define NPHY_ACI_CHANNEL_DELTA 5 ++#define NPHY_ACI_CHANNEL_SKIP 4 ++#define NPHY_ACI_40MHZ_CHANNEL_DELTA 6 ++#define NPHY_ACI_40MHZ_CHANNEL_SKIP 5 ++#define NPHY_ACI_40MHZ_CHANNEL_DELTA_GE_REV3 6 ++#define NPHY_ACI_40MHZ_CHANNEL_SKIP_GE_REV3 5 ++#define NPHY_ACI_CHANNEL_DELTA_GE_REV3 4 ++#define NPHY_ACI_CHANNEL_SKIP_GE_REV3 3 ++ ++#define NPHY_NOISE_NOASSOC_GLITCH_TH_UP 2 ++ ++#define NPHY_NOISE_NOASSOC_GLITCH_TH_DN 8 ++ ++#define NPHY_NOISE_ASSOC_GLITCH_TH_UP 2 ++ ++#define NPHY_NOISE_ASSOC_GLITCH_TH_DN 8 ++ ++#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_UP 2 ++ ++#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_DN 8 ++ ++#define NPHY_NOISE_NOASSOC_ENTER_TH 400 ++ ++#define NPHY_NOISE_ASSOC_ENTER_TH 400 ++ ++#define NPHY_NOISE_ASSOC_RX_GLITCH_BADPLCP_ENTER_TH 400 ++ ++#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX 44 ++#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX_REV_7 56 ++ ++#define NPHY_NOISE_NOASSOC_CRSIDX_INCR 16 ++ ++#define NPHY_NOISE_ASSOC_CRSIDX_INCR 8 ++ ++#define NPHY_IS_SROM_REINTERPRET NREV_GE(pi->pubpi.phy_rev, 5) ++ ++#define NPHY_RSSICAL_MAXREAD 31 ++ ++#define NPHY_RSSICAL_NPOLL 8 ++#define NPHY_RSSICAL_MAXD (1<<20) ++#define NPHY_MIN_RXIQ_PWR 2 ++ ++#define NPHY_RSSICAL_W1_TARGET 25 ++#define NPHY_RSSICAL_W2_TARGET NPHY_RSSICAL_W1_TARGET ++#define NPHY_RSSICAL_NB_TARGET 0 ++ ++#define NPHY_RSSICAL_W1_TARGET_REV3 29 ++#define NPHY_RSSICAL_W2_TARGET_REV3 NPHY_RSSICAL_W1_TARGET_REV3 ++ ++#define NPHY_CALSANITY_RSSI_NB_MAX_POS 9 ++#define NPHY_CALSANITY_RSSI_NB_MAX_NEG -9 ++#define NPHY_CALSANITY_RSSI_W1_MAX_POS 12 ++#define NPHY_CALSANITY_RSSI_W1_MAX_NEG (NPHY_RSSICAL_W1_TARGET - \ ++ NPHY_RSSICAL_MAXREAD) ++#define NPHY_CALSANITY_RSSI_W2_MAX_POS NPHY_CALSANITY_RSSI_W1_MAX_POS ++#define NPHY_CALSANITY_RSSI_W2_MAX_NEG (NPHY_RSSICAL_W2_TARGET - \ ++ NPHY_RSSICAL_MAXREAD) ++#define NPHY_RSSI_SXT(x) ((s8) (-((x) & 0x20) + ((x) & 0x1f))) ++#define NPHY_RSSI_NB_VIOL(x) (((x) > NPHY_CALSANITY_RSSI_NB_MAX_POS) || \ ++ ((x) < NPHY_CALSANITY_RSSI_NB_MAX_NEG)) ++#define NPHY_RSSI_W1_VIOL(x) (((x) > NPHY_CALSANITY_RSSI_W1_MAX_POS) || \ ++ ((x) < NPHY_CALSANITY_RSSI_W1_MAX_NEG)) ++#define NPHY_RSSI_W2_VIOL(x) (((x) > NPHY_CALSANITY_RSSI_W2_MAX_POS) || \ ++ ((x) < NPHY_CALSANITY_RSSI_W2_MAX_NEG)) ++ ++#define NPHY_IQCAL_NUMGAINS 9 ++#define NPHY_N_GCTL 0x66 ++ ++#define NPHY_PAPD_EPS_TBL_SIZE 64 ++#define NPHY_PAPD_SCL_TBL_SIZE 64 ++#define NPHY_NUM_DIG_FILT_COEFFS 15 ++ ++#define NPHY_PAPD_COMP_OFF 0 ++#define NPHY_PAPD_COMP_ON 1 ++ ++#define NPHY_SROM_TEMPSHIFT 32 ++#define NPHY_SROM_MAXTEMPOFFSET 16 ++#define NPHY_SROM_MINTEMPOFFSET -16 ++ ++#define NPHY_CAL_MAXTEMPDELTA 64 ++ ++#define NPHY_NOISEVAR_TBLLEN40 256 ++#define NPHY_NOISEVAR_TBLLEN20 128 ++ ++#define NPHY_ANARXLPFBW_REDUCTIONFACT 7 ++ ++#define NPHY_ADJUSTED_MINCRSPOWER 0x1e ++ ++/* 5357 Chip specific ChipControl register bits */ ++#define CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */ ++#define CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */ ++ ++#define NPHY_CAL_TSSISAMPS 64 ++#define NPHY_TEST_TONE_FREQ_40MHz 4000 ++#define NPHY_TEST_TONE_FREQ_20MHz 2500 ++ ++#define MAX_205x_RCAL_WAITLOOPS 10000 ++ ++#define NPHY_RXCAL_TONEAMP 181 ++#define NPHY_RXCAL_TONEFREQ_40MHz 4000 ++#define NPHY_RXCAL_TONEFREQ_20MHz 2000 ++ ++#define TXFILT_SHAPING_OFDM20 0 ++#define TXFILT_SHAPING_OFDM40 1 ++#define TXFILT_SHAPING_CCK 2 ++#define TXFILT_DEFAULT_OFDM20 3 ++#define TXFILT_DEFAULT_OFDM40 4 ++ ++struct nphy_iqcal_params { ++ u16 txlpf; ++ u16 txgm; ++ u16 pga; ++ u16 pad; ++ u16 ipa; ++ u16 cal_gain; ++ u16 ncorr[5]; ++}; ++ ++struct nphy_txiqcal_ladder { ++ u8 percent; ++ u8 g_env; ++}; ++ ++struct nphy_ipa_txcalgains { ++ struct nphy_txgains gains; ++ bool useindex; ++ u8 index; ++}; ++ ++struct nphy_papd_restore_state { ++ u16 fbmix[2]; ++ u16 vga_master[2]; ++ u16 intpa_master[2]; ++ u16 afectrl[2]; ++ u16 afeoverride[2]; ++ u16 pwrup[2]; ++ u16 atten[2]; ++ u16 mm; ++}; ++ ++struct nphy_ipa_txrxgain { ++ u16 hpvga; ++ u16 lpf_biq1; ++ u16 lpf_biq0; ++ u16 lna2; ++ u16 lna1; ++ s8 txpwrindex; ++}; ++ ++#define NPHY_IPA_RXCAL_MAXGAININDEX (6 - 1) ++ ++static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz[] = { ++ {0, 0, 0, 0, 0, 100}, ++ {0, 0, 0, 0, 0, 50}, ++ {0, 0, 0, 0, 0, -1}, ++ {0, 0, 0, 3, 0, -1}, ++ {0, 0, 3, 3, 0, -1}, ++ {0, 2, 3, 3, 0, -1} ++}; ++ ++static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz[] = { ++ {0, 0, 0, 0, 0, 128}, ++ {0, 0, 0, 0, 0, 70}, ++ {0, 0, 0, 0, 0, 20}, ++ {0, 0, 0, 3, 0, 20}, ++ {0, 0, 3, 3, 0, 20}, ++ {0, 2, 3, 3, 0, 20} ++}; ++ ++static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz_rev7[] = { ++ {0, 0, 0, 0, 0, 100}, ++ {0, 0, 0, 0, 0, 50}, ++ {0, 0, 0, 0, 0, -1}, ++ {0, 0, 0, 3, 0, -1}, ++ {0, 0, 3, 3, 0, -1}, ++ {0, 0, 5, 3, 0, -1} ++}; ++ ++static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz_rev7[] = { ++ {0, 0, 0, 0, 0, 10}, ++ {0, 0, 0, 1, 0, 10}, ++ {0, 0, 1, 2, 0, 10}, ++ {0, 0, 1, 3, 0, 10}, ++ {0, 0, 4, 3, 0, 10}, ++ {0, 0, 6, 3, 0, 10} ++}; ++ ++enum { ++ NPHY_RXCAL_GAIN_INIT = 0, ++ NPHY_RXCAL_GAIN_UP, ++ NPHY_RXCAL_GAIN_DOWN ++}; ++ ++#define wlc_phy_get_papd_nphy(pi) \ ++ (read_phy_reg((pi), 0x1e7) & \ ++ ((0x1 << 15) | \ ++ (0x1 << 14) | \ ++ (0x1 << 13))) ++ ++static const u16 NPHY_IPA_REV4_txdigi_filtcoeffs[][NPHY_NUM_DIG_FILT_COEFFS] = { ++ {-377, 137, -407, 208, -1527, 956, 93, 186, 93, ++ 230, -44, 230, 201, -191, 201}, ++ {-77, 20, -98, 49, -93, 60, 56, 111, 56, 26, -5, ++ 26, 34, -32, 34}, ++ {-360, 164, -376, 164, -1533, 576, 308, -314, 308, ++ 121, -73, 121, 91, 124, 91}, ++ {-295, 200, -363, 142, -1391, 826, 151, 301, 151, ++ 151, 301, 151, 602, -752, 602}, ++ {-92, 58, -96, 49, -104, 44, 17, 35, 17, ++ 12, 25, 12, 13, 27, 13}, ++ {-375, 136, -399, 209, -1479, 949, 130, 260, 130, ++ 230, -44, 230, 201, -191, 201}, ++ {0xed9, 0xc8, 0xe95, 0x8e, 0xa91, 0x33a, 0x97, 0x12d, 0x97, ++ 0x97, 0x12d, 0x97, 0x25a, 0xd10, 0x25a} ++}; ++ ++struct chan_info_nphy_2055 { ++ u16 chan; ++ u16 freq; ++ uint unknown; ++ u8 RF_pll_ref; ++ u8 RF_rf_pll_mod1; ++ u8 RF_rf_pll_mod0; ++ u8 RF_vco_cap_tail; ++ u8 RF_vco_cal1; ++ u8 RF_vco_cal2; ++ u8 RF_pll_lf_c1; ++ u8 RF_pll_lf_r1; ++ u8 RF_pll_lf_c2; ++ u8 RF_lgbuf_cen_buf; ++ u8 RF_lgen_tune1; ++ u8 RF_lgen_tune2; ++ u8 RF_core1_lgbuf_a_tune; ++ u8 RF_core1_lgbuf_g_tune; ++ u8 RF_core1_rxrf_reg1; ++ u8 RF_core1_tx_pga_pad_tn; ++ u8 RF_core1_tx_mx_bgtrim; ++ u8 RF_core2_lgbuf_a_tune; ++ u8 RF_core2_lgbuf_g_tune; ++ u8 RF_core2_rxrf_reg1; ++ u8 RF_core2_tx_pga_pad_tn; ++ u8 RF_core2_tx_mx_bgtrim; ++ u16 PHY_BW1a; ++ u16 PHY_BW2; ++ u16 PHY_BW3; ++ u16 PHY_BW4; ++ u16 PHY_BW5; ++ u16 PHY_BW6; ++}; ++ ++struct chan_info_nphy_radio205x { ++ u16 chan; ++ u16 freq; ++ u8 RF_SYN_pll_vcocal1; ++ u8 RF_SYN_pll_vcocal2; ++ u8 RF_SYN_pll_refdiv; ++ u8 RF_SYN_pll_mmd2; ++ u8 RF_SYN_pll_mmd1; ++ u8 RF_SYN_pll_loopfilter1; ++ u8 RF_SYN_pll_loopfilter2; ++ u8 RF_SYN_pll_loopfilter3; ++ u8 RF_SYN_pll_loopfilter4; ++ u8 RF_SYN_pll_loopfilter5; ++ u8 RF_SYN_reserved_addr27; ++ u8 RF_SYN_reserved_addr28; ++ u8 RF_SYN_reserved_addr29; ++ u8 RF_SYN_logen_VCOBUF1; ++ u8 RF_SYN_logen_MIXER2; ++ u8 RF_SYN_logen_BUF3; ++ u8 RF_SYN_logen_BUF4; ++ u8 RF_RX0_lnaa_tune; ++ u8 RF_RX0_lnag_tune; ++ u8 RF_TX0_intpaa_boost_tune; ++ u8 RF_TX0_intpag_boost_tune; ++ u8 RF_TX0_pada_boost_tune; ++ u8 RF_TX0_padg_boost_tune; ++ u8 RF_TX0_pgaa_boost_tune; ++ u8 RF_TX0_pgag_boost_tune; ++ u8 RF_TX0_mixa_boost_tune; ++ u8 RF_TX0_mixg_boost_tune; ++ u8 RF_RX1_lnaa_tune; ++ u8 RF_RX1_lnag_tune; ++ u8 RF_TX1_intpaa_boost_tune; ++ u8 RF_TX1_intpag_boost_tune; ++ u8 RF_TX1_pada_boost_tune; ++ u8 RF_TX1_padg_boost_tune; ++ u8 RF_TX1_pgaa_boost_tune; ++ u8 RF_TX1_pgag_boost_tune; ++ u8 RF_TX1_mixa_boost_tune; ++ u8 RF_TX1_mixg_boost_tune; ++ u16 PHY_BW1a; ++ u16 PHY_BW2; ++ u16 PHY_BW3; ++ u16 PHY_BW4; ++ u16 PHY_BW5; ++ u16 PHY_BW6; ++}; ++ ++struct chan_info_nphy_radio2057 { ++ u16 chan; ++ u16 freq; ++ u8 RF_vcocal_countval0; ++ u8 RF_vcocal_countval1; ++ u8 RF_rfpll_refmaster_sparextalsize; ++ u8 RF_rfpll_loopfilter_r1; ++ u8 RF_rfpll_loopfilter_c2; ++ u8 RF_rfpll_loopfilter_c1; ++ u8 RF_cp_kpd_idac; ++ u8 RF_rfpll_mmd0; ++ u8 RF_rfpll_mmd1; ++ u8 RF_vcobuf_tune; ++ u8 RF_logen_mx2g_tune; ++ u8 RF_logen_mx5g_tune; ++ u8 RF_logen_indbuf2g_tune; ++ u8 RF_logen_indbuf5g_tune; ++ u8 RF_txmix2g_tune_boost_pu_core0; ++ u8 RF_pad2g_tune_pus_core0; ++ u8 RF_pga_boost_tune_core0; ++ u8 RF_txmix5g_boost_tune_core0; ++ u8 RF_pad5g_tune_misc_pus_core0; ++ u8 RF_lna2g_tune_core0; ++ u8 RF_lna5g_tune_core0; ++ u8 RF_txmix2g_tune_boost_pu_core1; ++ u8 RF_pad2g_tune_pus_core1; ++ u8 RF_pga_boost_tune_core1; ++ u8 RF_txmix5g_boost_tune_core1; ++ u8 RF_pad5g_tune_misc_pus_core1; ++ u8 RF_lna2g_tune_core1; ++ u8 RF_lna5g_tune_core1; ++ u16 PHY_BW1a; ++ u16 PHY_BW2; ++ u16 PHY_BW3; ++ u16 PHY_BW4; ++ u16 PHY_BW5; ++ u16 PHY_BW6; ++}; ++ ++struct chan_info_nphy_radio2057_rev5 { ++ u16 chan; ++ u16 freq; ++ u8 RF_vcocal_countval0; ++ u8 RF_vcocal_countval1; ++ u8 RF_rfpll_refmaster_sparextalsize; ++ u8 RF_rfpll_loopfilter_r1; ++ u8 RF_rfpll_loopfilter_c2; ++ u8 RF_rfpll_loopfilter_c1; ++ u8 RF_cp_kpd_idac; ++ u8 RF_rfpll_mmd0; ++ u8 RF_rfpll_mmd1; ++ u8 RF_vcobuf_tune; ++ u8 RF_logen_mx2g_tune; ++ u8 RF_logen_indbuf2g_tune; ++ u8 RF_txmix2g_tune_boost_pu_core0; ++ u8 RF_pad2g_tune_pus_core0; ++ u8 RF_lna2g_tune_core0; ++ u8 RF_txmix2g_tune_boost_pu_core1; ++ u8 RF_pad2g_tune_pus_core1; ++ u8 RF_lna2g_tune_core1; ++ u16 PHY_BW1a; ++ u16 PHY_BW2; ++ u16 PHY_BW3; ++ u16 PHY_BW4; ++ u16 PHY_BW5; ++ u16 PHY_BW6; ++}; ++ ++struct nphy_sfo_cfg { ++ u16 PHY_BW1a; ++ u16 PHY_BW2; ++ u16 PHY_BW3; ++ u16 PHY_BW4; ++ u16 PHY_BW5; ++ u16 PHY_BW6; ++}; ++ ++static const struct chan_info_nphy_2055 chan_info_nphy_2055[] = { ++ { ++ 184, 4920, 3280, 0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7B4, 0x7B0, 0x7AC, 0x214, 0x215, 0x216}, ++ { ++ 186, 4930, 3287, 0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7B8, 0x7B4, 0x7B0, 0x213, 0x214, 0x215}, ++ { ++ 188, 4940, 3293, 0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7BC, 0x7B8, 0x7B4, 0x212, 0x213, 0x214}, ++ { ++ 190, 4950, 3300, 0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7C0, 0x7BC, 0x7B8, 0x211, 0x212, 0x213}, ++ { ++ 192, 4960, 3307, 0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7C4, 0x7C0, 0x7BC, 0x20F, 0x211, 0x212}, ++ { ++ 194, 4970, 3313, 0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7C8, 0x7C4, 0x7C0, 0x20E, 0x20F, 0x211}, ++ { ++ 196, 4980, 3320, 0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7CC, 0x7C8, 0x7C4, 0x20D, 0x20E, 0x20F}, ++ { ++ 198, 4990, 3327, 0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7D0, 0x7CC, 0x7C8, 0x20C, 0x20D, 0x20E}, ++ { ++ 200, 5000, 3333, 0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7D4, 0x7D0, 0x7CC, 0x20B, 0x20C, 0x20D}, ++ { ++ 202, 5010, 3340, 0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7D8, 0x7D4, 0x7D0, 0x20A, 0x20B, 0x20C}, ++ { ++ 204, 5020, 3347, 0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7DC, 0x7D8, 0x7D4, 0x209, 0x20A, 0x20B}, ++ { ++ 206, 5030, 3353, 0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7E0, 0x7DC, 0x7D8, 0x208, 0x209, 0x20A}, ++ { ++ 208, 5040, 3360, 0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7E4, 0x7E0, 0x7DC, 0x207, 0x208, 0x209}, ++ { ++ 210, 5050, 3367, 0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7E8, 0x7E4, 0x7E0, 0x206, 0x207, 0x208}, ++ { ++ 212, 5060, 3373, 0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E, ++ 0x0F, 0x8E, 0x7EC, 0x7E8, 0x7E4, 0x205, 0x206, 0x207}, ++ { ++ 214, 5070, 3380, 0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E, ++ 0x0F, 0x8E, 0x7F0, 0x7EC, 0x7E8, 0x204, 0x205, 0x206}, ++ { ++ 216, 5080, 3387, 0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A, ++ 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E, ++ 0x0F, 0x8D, 0x7F4, 0x7F0, 0x7EC, 0x203, 0x204, 0x205}, ++ { ++ 218, 5090, 3393, 0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A, ++ 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E, ++ 0x0F, 0x8D, 0x7F8, 0x7F4, 0x7F0, 0x202, 0x203, 0x204}, ++ { ++ 220, 5100, 3400, 0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A, ++ 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D, ++ 0x0F, 0x8D, 0x7FC, 0x7F8, 0x7F4, 0x201, 0x202, 0x203}, ++ { ++ 222, 5110, 3407, 0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A, ++ 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D, ++ 0x0F, 0x8D, 0x800, 0x7FC, 0x7F8, 0x200, 0x201, 0x202}, ++ { ++ 224, 5120, 3413, 0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A, ++ 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D, ++ 0x0F, 0x8C, 0x804, 0x800, 0x7FC, 0x1FF, 0x200, 0x201}, ++ { ++ 226, 5130, 3420, 0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A, ++ 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D, ++ 0x0F, 0x8C, 0x808, 0x804, 0x800, 0x1FE, 0x1FF, 0x200}, ++ { ++ 228, 5140, 3427, 0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A, ++ 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E, 0x8B, 0xDD, 0x00, 0x0C, ++ 0x0E, 0x8B, 0x80C, 0x808, 0x804, 0x1FD, 0x1FE, 0x1FF}, ++ { ++ 32, 5160, 3440, 0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A, ++ 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B, ++ 0x0D, 0x8A, 0x814, 0x810, 0x80C, 0x1FB, 0x1FC, 0x1FD}, ++ { ++ 34, 5170, 3447, 0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A, ++ 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B, ++ 0x0D, 0x8A, 0x818, 0x814, 0x810, 0x1FA, 0x1FB, 0x1FC}, ++ { ++ 36, 5180, 3453, 0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A, ++ 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B, ++ 0x0C, 0x89, 0x81C, 0x818, 0x814, 0x1F9, 0x1FA, 0x1FB}, ++ { ++ 38, 5190, 3460, 0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A, ++ 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B, ++ 0x0C, 0x89, 0x820, 0x81C, 0x818, 0x1F8, 0x1F9, 0x1FA}, ++ { ++ 40, 5200, 3467, 0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A, ++ 0x0B, 0x89, 0x824, 0x820, 0x81C, 0x1F7, 0x1F8, 0x1F9}, ++ { ++ 42, 5210, 3473, 0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A, ++ 0x0B, 0x89, 0x828, 0x824, 0x820, 0x1F6, 0x1F7, 0x1F8}, ++ { ++ 44, 5220, 3480, 0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A, ++ 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09, ++ 0x0A, 0x88, 0x82C, 0x828, 0x824, 0x1F5, 0x1F6, 0x1F7}, ++ { ++ 46, 5230, 3487, 0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A, ++ 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09, ++ 0x0A, 0x88, 0x830, 0x82C, 0x828, 0x1F4, 0x1F5, 0x1F6}, ++ { ++ 48, 5240, 3493, 0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A, ++ 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09, ++ 0x0A, 0x87, 0x834, 0x830, 0x82C, 0x1F3, 0x1F4, 0x1F5}, ++ { ++ 50, 5250, 3500, 0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A, ++ 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09, ++ 0x0A, 0x87, 0x838, 0x834, 0x830, 0x1F2, 0x1F3, 0x1F4}, ++ { ++ 52, 5260, 3507, 0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A, ++ 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08, ++ 0x09, 0x87, 0x83C, 0x838, 0x834, 0x1F1, 0x1F2, 0x1F3}, ++ { ++ 54, 5270, 3513, 0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A, ++ 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08, ++ 0x09, 0x87, 0x840, 0x83C, 0x838, 0x1F0, 0x1F1, 0x1F2}, ++ { ++ 56, 5280, 3520, 0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A, ++ 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08, ++ 0x08, 0x86, 0x844, 0x840, 0x83C, 0x1F0, 0x1F0, 0x1F1}, ++ { ++ 58, 5290, 3527, 0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A, ++ 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08, ++ 0x08, 0x86, 0x848, 0x844, 0x840, 0x1EF, 0x1F0, 0x1F0}, ++ { ++ 60, 5300, 3533, 0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A, ++ 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08, ++ 0x07, 0x85, 0x84C, 0x848, 0x844, 0x1EE, 0x1EF, 0x1F0}, ++ { ++ 62, 5310, 3540, 0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A, ++ 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08, ++ 0x07, 0x85, 0x850, 0x84C, 0x848, 0x1ED, 0x1EE, 0x1EF}, ++ { ++ 64, 5320, 3547, 0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A, ++ 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07, ++ 0x07, 0x84, 0x854, 0x850, 0x84C, 0x1EC, 0x1ED, 0x1EE}, ++ { ++ 66, 5330, 3553, 0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A, ++ 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07, ++ 0x07, 0x84, 0x858, 0x854, 0x850, 0x1EB, 0x1EC, 0x1ED}, ++ { ++ 68, 5340, 3560, 0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A, ++ 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07, ++ 0x06, 0x84, 0x85C, 0x858, 0x854, 0x1EA, 0x1EB, 0x1EC}, ++ { ++ 70, 5350, 3567, 0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A, ++ 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07, ++ 0x06, 0x84, 0x860, 0x85C, 0x858, 0x1E9, 0x1EA, 0x1EB}, ++ { ++ 72, 5360, 3573, 0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A, ++ 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06, ++ 0x05, 0x83, 0x864, 0x860, 0x85C, 0x1E8, 0x1E9, 0x1EA}, ++ { ++ 74, 5370, 3580, 0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A, ++ 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06, ++ 0x05, 0x83, 0x868, 0x864, 0x860, 0x1E7, 0x1E8, 0x1E9}, ++ { ++ 76, 5380, 3587, 0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A, ++ 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06, ++ 0x04, 0x82, 0x86C, 0x868, 0x864, 0x1E6, 0x1E7, 0x1E8}, ++ { ++ 78, 5390, 3593, 0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A, ++ 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06, ++ 0x04, 0x82, 0x870, 0x86C, 0x868, 0x1E5, 0x1E6, 0x1E7}, ++ { ++ 80, 5400, 3600, 0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A, ++ 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05, ++ 0x04, 0x81, 0x874, 0x870, 0x86C, 0x1E5, 0x1E5, 0x1E6}, ++ { ++ 82, 5410, 3607, 0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A, ++ 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05, ++ 0x04, 0x81, 0x878, 0x874, 0x870, 0x1E4, 0x1E5, 0x1E5}, ++ { ++ 84, 5420, 3613, 0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A, ++ 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05, ++ 0x03, 0x80, 0x87C, 0x878, 0x874, 0x1E3, 0x1E4, 0x1E5}, ++ { ++ 86, 5430, 3620, 0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A, ++ 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05, ++ 0x03, 0x80, 0x880, 0x87C, 0x878, 0x1E2, 0x1E3, 0x1E4}, ++ { ++ 88, 5440, 3627, 0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A, ++ 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04, ++ 0x02, 0x80, 0x884, 0x880, 0x87C, 0x1E1, 0x1E2, 0x1E3}, ++ { ++ 90, 5450, 3633, 0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A, ++ 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04, ++ 0x02, 0x80, 0x888, 0x884, 0x880, 0x1E0, 0x1E1, 0x1E2}, ++ { ++ 92, 5460, 3640, 0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A, ++ 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04, ++ 0x01, 0x80, 0x88C, 0x888, 0x884, 0x1DF, 0x1E0, 0x1E1}, ++ { ++ 94, 5470, 3647, 0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A, ++ 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04, ++ 0x01, 0x80, 0x890, 0x88C, 0x888, 0x1DE, 0x1DF, 0x1E0}, ++ { ++ 96, 5480, 3653, 0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A, ++ 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, ++ 0x00, 0x80, 0x894, 0x890, 0x88C, 0x1DD, 0x1DE, 0x1DF}, ++ { ++ 98, 5490, 3660, 0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A, ++ 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, ++ 0x00, 0x80, 0x898, 0x894, 0x890, 0x1DD, 0x1DD, 0x1DE}, ++ { ++ 100, 5500, 3667, 0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A, ++ 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, ++ 0x00, 0x80, 0x89C, 0x898, 0x894, 0x1DC, 0x1DD, 0x1DD}, ++ { ++ 102, 5510, 3673, 0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A, ++ 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, ++ 0x00, 0x80, 0x8A0, 0x89C, 0x898, 0x1DB, 0x1DC, 0x1DD}, ++ { ++ 104, 5520, 3680, 0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A, ++ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, ++ 0x00, 0x80, 0x8A4, 0x8A0, 0x89C, 0x1DA, 0x1DB, 0x1DC}, ++ { ++ 106, 5530, 3687, 0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A, ++ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, ++ 0x00, 0x80, 0x8A8, 0x8A4, 0x8A0, 0x1D9, 0x1DA, 0x1DB}, ++ { ++ 108, 5540, 3693, 0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A, ++ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, ++ 0x00, 0x80, 0x8AC, 0x8A8, 0x8A4, 0x1D8, 0x1D9, 0x1DA}, ++ { ++ 110, 5550, 3700, 0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A, ++ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, ++ 0x00, 0x80, 0x8B0, 0x8AC, 0x8A8, 0x1D7, 0x1D8, 0x1D9}, ++ { ++ 112, 5560, 3707, 0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A, ++ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, ++ 0x00, 0x80, 0x8B4, 0x8B0, 0x8AC, 0x1D7, 0x1D7, 0x1D8}, ++ { ++ 114, 5570, 3713, 0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A, ++ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, ++ 0x00, 0x80, 0x8B8, 0x8B4, 0x8B0, 0x1D6, 0x1D7, 0x1D7}, ++ { ++ 116, 5580, 3720, 0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A, ++ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, ++ 0x00, 0x80, 0x8BC, 0x8B8, 0x8B4, 0x1D5, 0x1D6, 0x1D7}, ++ { ++ 118, 5590, 3727, 0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A, ++ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, ++ 0x00, 0x80, 0x8C0, 0x8BC, 0x8B8, 0x1D4, 0x1D5, 0x1D6}, ++ { ++ 120, 5600, 3733, 0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A, ++ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01, ++ 0x00, 0x80, 0x8C4, 0x8C0, 0x8BC, 0x1D3, 0x1D4, 0x1D5}, ++ { ++ 122, 5610, 3740, 0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A, ++ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01, ++ 0x00, 0x80, 0x8C8, 0x8C4, 0x8C0, 0x1D2, 0x1D3, 0x1D4}, ++ { ++ 124, 5620, 3747, 0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A, ++ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, ++ 0x00, 0x80, 0x8CC, 0x8C8, 0x8C4, 0x1D2, 0x1D2, 0x1D3}, ++ { ++ 126, 5630, 3753, 0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A, ++ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, ++ 0x00, 0x80, 0x8D0, 0x8CC, 0x8C8, 0x1D1, 0x1D2, 0x1D2}, ++ { ++ 128, 5640, 3760, 0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8D4, 0x8D0, 0x8CC, 0x1D0, 0x1D1, 0x1D2}, ++ { ++ 130, 5650, 3767, 0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8D8, 0x8D4, 0x8D0, 0x1CF, 0x1D0, 0x1D1}, ++ { ++ 132, 5660, 3773, 0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8DC, 0x8D8, 0x8D4, 0x1CE, 0x1CF, 0x1D0}, ++ { ++ 134, 5670, 3780, 0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8E0, 0x8DC, 0x8D8, 0x1CE, 0x1CE, 0x1CF}, ++ { ++ 136, 5680, 3787, 0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8E4, 0x8E0, 0x8DC, 0x1CD, 0x1CE, 0x1CE}, ++ { ++ 138, 5690, 3793, 0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8E8, 0x8E4, 0x8E0, 0x1CC, 0x1CD, 0x1CE}, ++ { ++ 140, 5700, 3800, 0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8EC, 0x8E8, 0x8E4, 0x1CB, 0x1CC, 0x1CD}, ++ { ++ 142, 5710, 3807, 0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8F0, 0x8EC, 0x8E8, 0x1CA, 0x1CB, 0x1CC}, ++ { ++ 144, 5720, 3813, 0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8F4, 0x8F0, 0x8EC, 0x1C9, 0x1CA, 0x1CB}, ++ { ++ 145, 5725, 3817, 0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8F6, 0x8F2, 0x8EE, 0x1C9, 0x1CA, 0x1CB}, ++ { ++ 146, 5730, 3820, 0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8F8, 0x8F4, 0x8F0, 0x1C9, 0x1C9, 0x1CA}, ++ { ++ 147, 5735, 3823, 0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8FA, 0x8F6, 0x8F2, 0x1C8, 0x1C9, 0x1CA}, ++ { ++ 148, 5740, 3827, 0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8FC, 0x8F8, 0x8F4, 0x1C8, 0x1C9, 0x1C9}, ++ { ++ 149, 5745, 3830, 0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8FE, 0x8FA, 0x8F6, 0x1C8, 0x1C8, 0x1C9}, ++ { ++ 150, 5750, 3833, 0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x900, 0x8FC, 0x8F8, 0x1C7, 0x1C8, 0x1C9}, ++ { ++ 151, 5755, 3837, 0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x902, 0x8FE, 0x8FA, 0x1C7, 0x1C8, 0x1C8}, ++ { ++ 152, 5760, 3840, 0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x904, 0x900, 0x8FC, 0x1C6, 0x1C7, 0x1C8}, ++ { ++ 153, 5765, 3843, 0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x906, 0x902, 0x8FE, 0x1C6, 0x1C7, 0x1C8}, ++ { ++ 154, 5770, 3847, 0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x908, 0x904, 0x900, 0x1C6, 0x1C6, 0x1C7}, ++ { ++ 155, 5775, 3850, 0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x90A, 0x906, 0x902, 0x1C5, 0x1C6, 0x1C7}, ++ { ++ 156, 5780, 3853, 0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x90C, 0x908, 0x904, 0x1C5, 0x1C6, 0x1C6}, ++ { ++ 157, 5785, 3857, 0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x90E, 0x90A, 0x906, 0x1C4, 0x1C5, 0x1C6}, ++ { ++ 158, 5790, 3860, 0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x910, 0x90C, 0x908, 0x1C4, 0x1C5, 0x1C6}, ++ { ++ 159, 5795, 3863, 0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x912, 0x90E, 0x90A, 0x1C4, 0x1C4, 0x1C5}, ++ { ++ 160, 5800, 3867, 0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x914, 0x910, 0x90C, 0x1C3, 0x1C4, 0x1C5}, ++ { ++ 161, 5805, 3870, 0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x916, 0x912, 0x90E, 0x1C3, 0x1C4, 0x1C4}, ++ { ++ 162, 5810, 3873, 0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x918, 0x914, 0x910, 0x1C2, 0x1C3, 0x1C4}, ++ { ++ 163, 5815, 3877, 0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x91A, 0x916, 0x912, 0x1C2, 0x1C3, 0x1C4}, ++ { ++ 164, 5820, 3880, 0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x91C, 0x918, 0x914, 0x1C2, 0x1C2, 0x1C3}, ++ { ++ 165, 5825, 3883, 0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x91E, 0x91A, 0x916, 0x1C1, 0x1C2, 0x1C3}, ++ { ++ 166, 5830, 3887, 0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x920, 0x91C, 0x918, 0x1C1, 0x1C2, 0x1C2}, ++ { ++ 168, 5840, 3893, 0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x924, 0x920, 0x91C, 0x1C0, 0x1C1, 0x1C2}, ++ { ++ 170, 5850, 3900, 0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x928, 0x924, 0x920, 0x1BF, 0x1C0, 0x1C1}, ++ { ++ 172, 5860, 3907, 0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x92C, 0x928, 0x924, 0x1BF, 0x1BF, 0x1C0}, ++ { ++ 174, 5870, 3913, 0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x930, 0x92C, 0x928, 0x1BE, 0x1BF, 0x1BF}, ++ { ++ 176, 5880, 3920, 0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x934, 0x930, 0x92C, 0x1BD, 0x1BE, 0x1BF}, ++ { ++ 178, 5890, 3927, 0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x938, 0x934, 0x930, 0x1BC, 0x1BD, 0x1BE}, ++ { ++ 180, 5900, 3933, 0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x93C, 0x938, 0x934, 0x1BC, 0x1BC, 0x1BD}, ++ { ++ 182, 5910, 3940, 0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x940, 0x93C, 0x938, 0x1BB, 0x1BC, 0x1BC}, ++ { ++ 1, 2412, 3216, 0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C, 0x80, 0xFF, 0x88, 0x0D, ++ 0x0C, 0x80, 0x3C9, 0x3C5, 0x3C1, 0x43A, 0x43F, 0x443}, ++ { ++ 2, 2417, 3223, 0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B, 0x80, 0xFF, 0x88, 0x0C, ++ 0x0B, 0x80, 0x3CB, 0x3C7, 0x3C3, 0x438, 0x43D, 0x441}, ++ { ++ 3, 2422, 3229, 0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C, ++ 0x0A, 0x80, 0x3CD, 0x3C9, 0x3C5, 0x436, 0x43A, 0x43F}, ++ { ++ 4, 2427, 3236, 0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C, ++ 0x0A, 0x80, 0x3CF, 0x3CB, 0x3C7, 0x434, 0x438, 0x43D}, ++ { ++ 5, 2432, 3243, 0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09, 0x80, 0xFF, 0x88, 0x0C, ++ 0x09, 0x80, 0x3D1, 0x3CD, 0x3C9, 0x431, 0x436, 0x43A}, ++ { ++ 6, 2437, 3249, 0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08, 0x80, 0xFF, 0x88, 0x0B, ++ 0x08, 0x80, 0x3D3, 0x3CF, 0x3CB, 0x42F, 0x434, 0x438}, ++ { ++ 7, 2442, 3256, 0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07, 0x80, 0xFF, 0x88, 0x0A, ++ 0x07, 0x80, 0x3D5, 0x3D1, 0x3CD, 0x42D, 0x431, 0x436}, ++ { ++ 8, 2447, 3263, 0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06, 0x80, 0xFF, 0x88, 0x0A, ++ 0x06, 0x80, 0x3D7, 0x3D3, 0x3CF, 0x42B, 0x42F, 0x434}, ++ { ++ 9, 2452, 3269, 0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06, 0x80, 0xFF, 0x88, 0x09, ++ 0x06, 0x80, 0x3D9, 0x3D5, 0x3D1, 0x429, 0x42D, 0x431}, ++ { ++ 10, 2457, 3276, 0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05, 0x80, 0xFF, 0x88, 0x08, ++ 0x05, 0x80, 0x3DB, 0x3D7, 0x3D3, 0x427, 0x42B, 0x42F}, ++ { ++ 11, 2462, 3283, 0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04, 0x80, 0xFF, 0x88, 0x08, ++ 0x04, 0x80, 0x3DD, 0x3D9, 0x3D5, 0x424, 0x429, 0x42D}, ++ { ++ 12, 2467, 3289, 0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03, 0x80, 0xFF, 0x88, 0x08, ++ 0x03, 0x80, 0x3DF, 0x3DB, 0x3D7, 0x422, 0x427, 0x42B}, ++ { ++ 13, 2472, 3296, 0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03, 0x80, 0xFF, 0x88, 0x07, ++ 0x03, 0x80, 0x3E1, 0x3DD, 0x3D9, 0x420, 0x424, 0x429}, ++ { ++ 14, 2484, 3312, 0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01, 0x80, 0xFF, 0x88, 0x07, ++ 0x01, 0x80, 0x3E6, 0x3E2, 0x3DE, 0x41B, 0x41F, 0x424} ++}; ++ ++static const struct chan_info_nphy_radio205x chan_info_nphyrev3_2056[] = { ++ { ++ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, ++ { ++ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, ++ { ++ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, ++ { ++ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, ++ { ++ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, ++ { ++ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, ++ { ++ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, ++ { ++ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, ++ { ++ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, ++ { ++ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, ++ { ++ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, ++ { ++ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, ++ { ++ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, ++ { ++ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, ++ { ++ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, ++ { ++ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, ++ { ++ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, ++ { ++ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, ++ { ++ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, ++ { ++ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xfc, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, ++ { ++ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xfc, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, ++ { ++ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xfc, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, ++ { ++ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xfc, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, ++ { ++ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xfc, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, ++ { ++ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xfc, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, ++ { ++ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xfc, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, ++ { ++ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xfc, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, ++ { ++ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, ++ { ++ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, ++ { ++ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, ++ { ++ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, ++ { ++ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, ++ { ++ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, ++ { ++ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, ++ { ++ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, ++ { ++ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, ++ { ++ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, ++ { ++ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfc, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, ++ { ++ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, ++ { ++ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, ++ { ++ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, ++ { ++ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, ++ { ++ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, ++ { ++ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, ++ { ++ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, ++ { ++ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, ++ { ++ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, ++ { ++ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xfa, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, ++ { ++ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xfa, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, ++ { ++ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xfa, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, ++ { ++ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xfa, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, ++ { ++ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xfa, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, ++ { ++ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xfa, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, ++ { ++ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, ++ { ++ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, ++ { ++ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, ++ { ++ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, ++ { ++ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, ++ { ++ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, ++ { ++ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, ++ { ++ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, ++ { ++ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, ++ { ++ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, ++ { ++ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, ++ { ++ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, ++ { ++ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, ++ { ++ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, ++ { ++ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, ++ { ++ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, ++ { ++ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, ++ { ++ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, ++ { ++ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, ++ { ++ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf6, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, ++ { ++ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf6, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, ++ { ++ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf6, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, ++ { ++ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf6, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, ++ { ++ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf6, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, ++ { ++ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, ++ { ++ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, ++ { ++ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, ++ { ++ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, ++ { ++ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, ++ { ++ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, ++ { ++ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, ++ { ++ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, ++ { ++ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, ++ { ++ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, ++ { ++ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, ++ { ++ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, ++ { ++ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, ++ { ++ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, ++ { ++ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, ++ { ++ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, ++ { ++ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, ++ { ++ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, ++ { ++ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf2, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf2, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, ++ { ++ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf2, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, ++ { ++ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf2, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, ++ { ++ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf2, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, ++ { ++ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x05, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05, ++ 0x00, 0xf2, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, ++ { ++ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x05, 0x00, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05, ++ 0x00, 0xf2, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, ++ { ++ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfd, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfb, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf7, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf6, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf5, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0d, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0d, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf3, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0d, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0d, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf0, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0d, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio205x chan_info_nphyrev4_2056_A1[] = { ++ { ++ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, ++ { ++ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, ++ { ++ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, ++ { ++ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, ++ { ++ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, ++ { ++ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, ++ { ++ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, ++ { ++ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, ++ { ++ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, ++ { ++ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, ++ { ++ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, ++ { ++ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, ++ { ++ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, ++ { ++ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, ++ { ++ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, ++ { ++ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, ++ { ++ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, ++ { ++ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, ++ { ++ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, ++ { ++ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, ++ { ++ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, ++ { ++ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, ++ { ++ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, ++ { ++ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, ++ { ++ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, ++ { ++ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, ++ { ++ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, ++ { ++ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, ++ { ++ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, ++ { ++ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, ++ { ++ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, ++ { ++ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, ++ { ++ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, ++ { ++ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, ++ { ++ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, ++ { ++ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, ++ { ++ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, ++ { ++ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, ++ { ++ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, ++ { ++ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, ++ { ++ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, ++ { ++ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, ++ { ++ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, ++ { ++ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, ++ { ++ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, ++ { ++ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, ++ { ++ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, ++ { ++ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, ++ { ++ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, ++ { ++ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, ++ { ++ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, ++ { ++ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, ++ { ++ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, ++ { ++ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, ++ { ++ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, ++ { ++ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, ++ { ++ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, ++ { ++ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x5c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, ++ { ++ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, ++ { ++ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, ++ { ++ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, ++ { ++ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, ++ { ++ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, ++ { ++ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, ++ { ++ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, ++ { ++ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, ++ { ++ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, ++ { ++ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, ++ { ++ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, ++ { ++ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, ++ { ++ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, ++ { ++ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, ++ { ++ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, ++ { ++ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, ++ { ++ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, ++ { ++ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, ++ { ++ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, ++ { ++ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, ++ { ++ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, ++ { ++ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, ++ { ++ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, ++ { ++ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, ++ { ++ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, ++ { ++ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, ++ { ++ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, ++ { ++ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, ++ { ++ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, ++ { ++ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, ++ { ++ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, ++ { ++ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, ++ { ++ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, ++ { ++ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, ++ { ++ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, ++ { ++ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, ++ { ++ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, ++ { ++ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, ++ { ++ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, ++ { ++ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, ++ { ++ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, ++ { ++ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf0, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, ++ { ++ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf0, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, ++ { ++ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfd, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfb, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf8, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf7, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf5, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf3, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio205x chan_info_nphyrev5_2056v5[] = { ++ { ++ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, ++ 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, ++ { ++ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, ++ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, ++ { ++ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, ++ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, ++ { ++ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, ++ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, ++ { ++ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, ++ { ++ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, ++ { ++ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, ++ { ++ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, ++ { ++ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, ++ { ++ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, ++ { ++ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, ++ { ++ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, ++ { ++ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, ++ { ++ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, ++ { ++ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, ++ { ++ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, ++ { ++ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, ++ { ++ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, ++ { ++ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, ++ { ++ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, ++ { ++ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, ++ { ++ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, ++ { ++ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, ++ 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, ++ { ++ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, ++ { ++ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, ++ { ++ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, ++ { ++ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, ++ { ++ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, ++ { ++ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, ++ { ++ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, ++ { ++ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xea, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08, ++ 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, ++ { ++ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70, ++ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, ++ 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, ++ { ++ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70, ++ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, ++ 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, ++ { ++ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xd9, 0x00, 0x05, 0x00, 0x70, ++ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, ++ 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, ++ { ++ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xd8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, ++ { ++ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, ++ { ++ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, ++ { ++ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, ++ { ++ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, ++ { ++ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, ++ { ++ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, ++ { ++ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, ++ { ++ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa7, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, ++ { ++ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, ++ { ++ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x5b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, ++ { ++ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x96, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x5a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, ++ { ++ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x95, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x5a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, ++ { ++ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x5a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, ++ { ++ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x5a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, ++ { ++ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x5a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, ++ { ++ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x85, 0x00, 0x02, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x59, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, ++ { ++ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x59, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, ++ { ++ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x59, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, ++ { ++ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, ++ { ++ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x74, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, ++ { ++ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, ++ { ++ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, ++ { ++ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, ++ { ++ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, ++ { ++ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, ++ { ++ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x63, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03, ++ 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, ++ { ++ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, ++ 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, ++ 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, ++ { ++ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, ++ 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, ++ { ++ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, ++ { ++ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x76, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, ++ { ++ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x76, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, ++ { ++ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x76, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, ++ { ++ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x76, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, ++ { ++ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x76, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, ++ { ++ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x76, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, ++ { ++ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x75, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, ++ { ++ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x75, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, ++ { ++ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x75, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, ++ { ++ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x74, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, ++ { ++ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x74, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, ++ { ++ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x74, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, ++ { ++ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x74, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, ++ { ++ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x74, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, ++ { ++ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x74, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x74, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x84, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, ++ { ++ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x83, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, ++ { ++ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x83, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, ++ { ++ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x83, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, ++ { ++ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x83, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, ++ { ++ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x83, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, ++ { ++ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x83, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, ++ { ++ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, ++ { ++ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, ++ { ++ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, ++ { ++ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, ++ { ++ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, ++ { ++ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, ++ { ++ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, ++ { ++ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x72, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, ++ { ++ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x72, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, ++ { ++ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x72, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, ++ { ++ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x72, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, ++ { ++ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x71, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, ++ { ++ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x71, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, ++ { ++ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x71, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, ++ { ++ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x71, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, ++ { ++ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x71, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, ++ { ++ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x08, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x07, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x06, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x05, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x03, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v6[] = { ++ { ++ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, ++ { ++ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, ++ { ++ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, ++ { ++ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, ++ { ++ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, ++ { ++ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, ++ { ++ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, ++ { ++ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, ++ { ++ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, ++ { ++ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, ++ { ++ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, ++ { ++ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, ++ { ++ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, ++ { ++ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, ++ { ++ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, ++ { ++ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, ++ { ++ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, ++ { ++ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, ++ { ++ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, ++ { ++ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, ++ { ++ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, ++ { ++ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, ++ { ++ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, ++ { ++ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, ++ { ++ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, ++ { ++ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, ++ { ++ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, ++ { ++ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, ++ { ++ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, ++ { ++ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, ++ { ++ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, ++ { ++ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, ++ { ++ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, ++ { ++ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, ++ { ++ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, ++ { ++ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, ++ { ++ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, ++ { ++ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, ++ { ++ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, ++ { ++ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, ++ { ++ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, ++ { ++ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, ++ { ++ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, ++ { ++ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, ++ { ++ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, ++ { ++ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, ++ { ++ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, ++ { ++ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, ++ { ++ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, ++ { ++ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, ++ { ++ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, ++ { ++ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, ++ { ++ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, ++ { ++ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, ++ { ++ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, ++ { ++ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, ++ { ++ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, ++ { ++ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, ++ { ++ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, ++ { ++ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, ++ { ++ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, ++ { ++ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, ++ { ++ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, ++ { ++ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, ++ { ++ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, ++ { ++ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, ++ { ++ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, ++ { ++ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, ++ { ++ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, ++ { ++ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, ++ { ++ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, ++ { ++ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, ++ { ++ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, ++ { ++ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, ++ { ++ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, ++ { ++ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, ++ { ++ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, ++ { ++ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, ++ { ++ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, ++ { ++ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, ++ { ++ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, ++ { ++ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, ++ { ++ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, ++ { ++ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, ++ { ++ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, ++ { ++ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, ++ { ++ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, ++ { ++ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, ++ { ++ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, ++ { ++ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, ++ { ++ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, ++ { ++ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, ++ { ++ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, ++ { ++ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, ++ { ++ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, ++ { ++ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, ++ { ++ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, ++ { ++ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, ++ { ++ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, ++ { ++ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, ++ { ++ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, ++ { ++ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio205x chan_info_nphyrev5n6_2056v7[] = { ++ { ++ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, ++ 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, ++ { ++ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, ++ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, ++ { ++ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, ++ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, ++ { ++ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, ++ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, ++ { ++ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, ++ { ++ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, ++ { ++ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, ++ { ++ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, ++ { ++ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, ++ { ++ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, ++ { ++ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, ++ { ++ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, ++ { ++ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, ++ { ++ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, ++ { ++ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, ++ { ++ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, ++ { ++ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, ++ { ++ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, ++ { ++ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, ++ { ++ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, ++ { ++ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, ++ { ++ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, ++ { ++ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, ++ 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, ++ { ++ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, ++ { ++ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, ++ { ++ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, ++ { ++ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, ++ { ++ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, ++ { ++ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, ++ { ++ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, ++ { ++ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xea, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08, ++ 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, ++ { ++ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xe9, 0x00, 0x05, 0x00, 0x70, ++ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, ++ 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, ++ { ++ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xe9, 0x00, 0x05, 0x00, 0x70, ++ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, ++ 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, ++ { ++ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xd9, 0x00, 0x05, 0x00, 0x70, ++ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, ++ 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, ++ { ++ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xd8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, ++ { ++ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, ++ { ++ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, ++ { ++ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, ++ { ++ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, ++ { ++ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, ++ { ++ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xb7, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, ++ { ++ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xb7, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, ++ { ++ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa7, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, ++ { ++ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, ++ { ++ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x7b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, ++ { ++ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x96, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x7a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, ++ { ++ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x7a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, ++ { ++ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x7a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, ++ { ++ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x95, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x7a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, ++ { ++ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x95, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x7a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, ++ { ++ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x85, 0x00, 0x02, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x79, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, ++ { ++ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x79, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, ++ { ++ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x79, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, ++ { ++ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x79, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, ++ { ++ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x74, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x79, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, ++ { ++ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x78, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, ++ { ++ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x78, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, ++ { ++ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, ++ { ++ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, ++ { ++ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, ++ { ++ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x63, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03, ++ 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, ++ { ++ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x62, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, ++ 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, ++ 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, ++ { ++ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, ++ 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, ++ { ++ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x52, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, ++ { ++ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x52, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x86, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, ++ { ++ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x86, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, ++ { ++ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x86, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, ++ { ++ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x86, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, ++ { ++ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x86, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, ++ { ++ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x86, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, ++ { ++ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x85, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, ++ { ++ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x85, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, ++ { ++ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x85, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, ++ { ++ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x84, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, ++ { ++ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x84, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, ++ { ++ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x94, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, ++ { ++ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x94, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, ++ { ++ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x94, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, ++ { ++ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x94, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x94, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x94, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, ++ { ++ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x93, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, ++ { ++ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x93, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, ++ { ++ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x93, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, ++ { ++ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x93, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, ++ { ++ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x93, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, ++ { ++ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x93, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, ++ { ++ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, ++ { ++ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, ++ { ++ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, ++ { ++ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, ++ { ++ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, ++ { ++ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, ++ { ++ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, ++ { ++ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, ++ { ++ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, ++ { ++ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, ++ { ++ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, ++ { ++ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x91, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, ++ { ++ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x91, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, ++ { ++ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x91, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, ++ { ++ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x91, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, ++ { ++ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x91, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, ++ { ++ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x76, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x66, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x55, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x22, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v8[] = { ++ { ++ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, ++ { ++ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, ++ { ++ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, ++ { ++ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, ++ { ++ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, ++ { ++ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, ++ { ++ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, ++ { ++ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, ++ { ++ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, ++ { ++ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, ++ { ++ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, ++ { ++ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, ++ { ++ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, ++ { ++ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, ++ { ++ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, ++ { ++ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, ++ { ++ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, ++ { ++ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, ++ { ++ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, ++ { ++ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, ++ { ++ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, ++ { ++ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, ++ { ++ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, ++ { ++ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, ++ { ++ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, ++ { ++ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, ++ { ++ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, ++ { ++ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, ++ { ++ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, ++ { ++ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, ++ { ++ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, ++ { ++ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, ++ { ++ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, ++ { ++ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, ++ { ++ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, ++ { ++ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, ++ { ++ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, ++ { ++ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, ++ { ++ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, ++ { ++ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, ++ { ++ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, ++ { ++ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, ++ { ++ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, ++ { ++ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, ++ { ++ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, ++ { ++ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, ++ { ++ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, ++ { ++ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, ++ { ++ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, ++ { ++ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, ++ { ++ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, ++ { ++ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, ++ { ++ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, ++ { ++ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, ++ { ++ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, ++ { ++ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, ++ { ++ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, ++ { ++ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, ++ { ++ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, ++ { ++ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, ++ { ++ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, ++ { ++ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, ++ { ++ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, ++ { ++ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, ++ { ++ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, ++ { ++ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, ++ { ++ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, ++ { ++ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, ++ { ++ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, ++ { ++ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, ++ { ++ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, ++ { ++ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, ++ { ++ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, ++ { ++ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, ++ { ++ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, ++ { ++ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, ++ { ++ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, ++ { ++ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, ++ { ++ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, ++ { ++ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, ++ { ++ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, ++ { ++ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, ++ { ++ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, ++ { ++ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, ++ { ++ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, ++ { ++ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, ++ { ++ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, ++ { ++ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, ++ { ++ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, ++ { ++ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, ++ { ++ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, ++ { ++ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, ++ { ++ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, ++ { ++ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, ++ { ++ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, ++ { ++ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, ++ { ++ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, ++ { ++ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, ++ { ++ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, ++ { ++ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, ++ { ++ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, ++ { ++ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v11[] = { ++ { ++ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, ++ { ++ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, ++ { ++ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, ++ { ++ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, ++ { ++ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, ++ { ++ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, ++ { ++ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, ++ { ++ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, ++ { ++ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, ++ { ++ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, ++ { ++ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, ++ { ++ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, ++ { ++ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, ++ { ++ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, ++ { ++ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, ++ { ++ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, ++ { ++ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, ++ { ++ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, ++ { ++ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, ++ { ++ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, ++ { ++ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, ++ { ++ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, ++ { ++ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, ++ { ++ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, ++ { ++ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, ++ { ++ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, ++ { ++ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, ++ { ++ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, ++ { ++ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, ++ { ++ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, ++ { ++ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, ++ { ++ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, ++ { ++ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, ++ { ++ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, ++ { ++ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, ++ { ++ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, ++ { ++ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, ++ { ++ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, ++ { ++ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, ++ { ++ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, ++ { ++ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, ++ { ++ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, ++ { ++ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, ++ { ++ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, ++ { ++ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, ++ { ++ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, ++ { ++ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, ++ { ++ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, ++ { ++ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, ++ { ++ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, ++ { ++ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, ++ { ++ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, ++ { ++ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, ++ { ++ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, ++ { ++ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, ++ { ++ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, ++ { ++ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, ++ { ++ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, ++ { ++ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, ++ { ++ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, ++ { ++ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, ++ { ++ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, ++ { ++ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, ++ { ++ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, ++ { ++ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, ++ { ++ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, ++ { ++ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, ++ { ++ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, ++ { ++ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, ++ { ++ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, ++ { ++ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, ++ { ++ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, ++ { ++ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, ++ { ++ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, ++ { ++ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, ++ { ++ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, ++ { ++ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, ++ { ++ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, ++ { ++ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, ++ { ++ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, ++ { ++ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, ++ { ++ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, ++ { ++ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, ++ { ++ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, ++ { ++ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, ++ { ++ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, ++ { ++ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, ++ { ++ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, ++ { ++ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, ++ { ++ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, ++ { ++ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, ++ { ++ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, ++ { ++ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, ++ { ++ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, ++ { ++ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, ++ { ++ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, ++ { ++ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, ++ { ++ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, ++ { ++ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, ++ { ++ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, ++ { ++ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, ++ { ++ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio2057 chan_info_nphyrev7_2057_rev4[] = { ++ { ++ 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b4, 0x07b0, 0x07ac, 0x0214, ++ 0x0215, ++ 0x0216, ++ }, ++ { ++ 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b8, 0x07b4, 0x07b0, 0x0213, ++ 0x0214, ++ 0x0215, ++ }, ++ { ++ 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07bc, 0x07b8, 0x07b4, 0x0212, ++ 0x0213, ++ 0x0214, ++ }, ++ { ++ 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c0, 0x07bc, 0x07b8, 0x0211, ++ 0x0212, ++ 0x0213, ++ }, ++ { ++ 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c4, 0x07c0, 0x07bc, 0x020f, ++ 0x0211, ++ 0x0212, ++ }, ++ { ++ 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c8, 0x07c4, 0x07c0, 0x020e, ++ 0x020f, ++ 0x0211, ++ }, ++ { ++ 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07cc, 0x07c8, 0x07c4, 0x020d, ++ 0x020e, ++ 0x020f, ++ }, ++ { ++ 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d0, 0x07cc, 0x07c8, 0x020c, ++ 0x020d, ++ 0x020e, ++ }, ++ { ++ 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d4, 0x07d0, 0x07cc, 0x020b, ++ 0x020c, ++ 0x020d, ++ }, ++ { ++ 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d8, 0x07d4, 0x07d0, 0x020a, ++ 0x020b, ++ 0x020c, ++ }, ++ { ++ 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07dc, 0x07d8, 0x07d4, 0x0209, ++ 0x020a, ++ 0x020b, ++ }, ++ { ++ 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e0, 0x07dc, 0x07d8, 0x0208, ++ 0x0209, ++ 0x020a, ++ }, ++ { ++ 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e4, 0x07e0, 0x07dc, 0x0207, ++ 0x0208, ++ 0x0209, ++ }, ++ { ++ 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e8, 0x07e4, 0x07e0, 0x0206, ++ 0x0207, ++ 0x0208, ++ }, ++ { ++ 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x07ec, 0x07e8, 0x07e4, 0x0205, ++ 0x0206, ++ 0x0207, ++ }, ++ { ++ 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00, ++ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f0, 0x07ec, 0x07e8, 0x0204, ++ 0x0205, ++ 0x0206, ++ }, ++ { ++ 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00, ++ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f4, 0x07f0, 0x07ec, 0x0203, ++ 0x0204, ++ 0x0205, ++ }, ++ { ++ 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07f8, 0x07f4, 0x07f0, 0x0202, ++ 0x0203, ++ 0x0204, ++ }, ++ { ++ 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07fc, 0x07f8, 0x07f4, 0x0201, ++ 0x0202, ++ 0x0203, ++ }, ++ { ++ 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0800, 0x07fc, 0x07f8, 0x0200, ++ 0x0201, ++ 0x0202, ++ }, ++ { ++ 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0804, 0x0800, 0x07fc, 0x01ff, ++ 0x0200, ++ 0x0201, ++ }, ++ { ++ 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0808, 0x0804, 0x0800, 0x01fe, ++ 0x01ff, ++ 0x0200, ++ }, ++ { ++ 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x080c, 0x0808, 0x0804, 0x01fd, ++ 0x01fe, ++ 0x01ff, ++ }, ++ { ++ 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0814, 0x0810, 0x080c, 0x01fb, ++ 0x01fc, ++ 0x01fd, ++ }, ++ { ++ 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0818, 0x0814, 0x0810, 0x01fa, ++ 0x01fb, ++ 0x01fc, ++ }, ++ { ++ 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x081c, 0x0818, 0x0814, 0x01f9, ++ 0x01fa, ++ 0x01fb, ++ }, ++ { ++ 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0820, 0x081c, 0x0818, 0x01f8, ++ 0x01f9, ++ 0x01fa, ++ }, ++ { ++ 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0824, 0x0820, 0x081c, 0x01f7, ++ 0x01f8, ++ 0x01f9, ++ }, ++ { ++ 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0828, 0x0824, 0x0820, 0x01f6, ++ 0x01f7, ++ 0x01f8, ++ }, ++ { ++ 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x082c, 0x0828, 0x0824, 0x01f5, ++ 0x01f6, ++ 0x01f7, ++ }, ++ { ++ 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0830, 0x082c, 0x0828, 0x01f4, ++ 0x01f5, ++ 0x01f6, ++ }, ++ { ++ 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0834, 0x0830, 0x082c, 0x01f3, ++ 0x01f4, ++ 0x01f5, ++ }, ++ { ++ 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0838, 0x0834, 0x0830, 0x01f2, ++ 0x01f3, ++ 0x01f4, ++ }, ++ { ++ 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x083c, 0x0838, 0x0834, 0x01f1, ++ 0x01f2, ++ 0x01f3, ++ }, ++ { ++ 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x0840, 0x083c, 0x0838, 0x01f0, ++ 0x01f1, ++ 0x01f2, ++ }, ++ { ++ 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00, ++ 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0844, 0x0840, 0x083c, 0x01f0, ++ 0x01f0, ++ 0x01f1, ++ }, ++ { ++ 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00, ++ 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0848, 0x0844, 0x0840, 0x01ef, ++ 0x01f0, ++ 0x01f0, ++ }, ++ { ++ 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00, ++ 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x084c, 0x0848, 0x0844, 0x01ee, ++ 0x01ef, ++ 0x01f0, ++ }, ++ { ++ 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00, ++ 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0850, 0x084c, 0x0848, 0x01ed, ++ 0x01ee, ++ 0x01ef, ++ }, ++ { ++ 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00, ++ 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0854, 0x0850, 0x084c, 0x01ec, ++ 0x01ed, ++ 0x01ee, ++ }, ++ { ++ 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00, ++ 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0858, 0x0854, 0x0850, 0x01eb, ++ 0x01ec, ++ 0x01ed, ++ }, ++ { ++ 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x00, ++ 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x085c, 0x0858, 0x0854, 0x01ea, ++ 0x01eb, ++ 0x01ec, ++ }, ++ { ++ 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00, ++ 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0860, 0x085c, 0x0858, 0x01e9, ++ 0x01ea, ++ 0x01eb, ++ }, ++ { ++ 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00, ++ 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0864, 0x0860, 0x085c, 0x01e8, ++ 0x01e9, ++ 0x01ea, ++ }, ++ { ++ 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00, ++ 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0868, 0x0864, 0x0860, 0x01e7, ++ 0x01e8, ++ 0x01e9, ++ }, ++ { ++ 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00, ++ 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x086c, 0x0868, 0x0864, 0x01e6, ++ 0x01e7, ++ 0x01e8, ++ }, ++ { ++ 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x00, ++ 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x0870, 0x086c, 0x0868, 0x01e5, ++ 0x01e6, ++ 0x01e7, ++ }, ++ { ++ 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00, ++ 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0874, 0x0870, 0x086c, 0x01e5, ++ 0x01e5, ++ 0x01e6, ++ }, ++ { ++ 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00, ++ 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0878, 0x0874, 0x0870, 0x01e4, ++ 0x01e5, ++ 0x01e5, ++ }, ++ { ++ 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x00, ++ 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x087c, 0x0878, 0x0874, 0x01e3, ++ 0x01e4, ++ 0x01e5, ++ }, ++ { ++ 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00, ++ 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0880, 0x087c, 0x0878, 0x01e2, ++ 0x01e3, ++ 0x01e4, ++ }, ++ { ++ 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00, ++ 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0884, 0x0880, 0x087c, 0x01e1, ++ 0x01e2, ++ 0x01e3, ++ }, ++ { ++ 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00, ++ 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0888, 0x0884, 0x0880, 0x01e0, ++ 0x01e1, ++ 0x01e2, ++ }, ++ { ++ 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x00, ++ 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x088c, 0x0888, 0x0884, 0x01df, ++ 0x01e0, ++ 0x01e1, ++ }, ++ { ++ 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x0890, 0x088c, 0x0888, 0x01de, ++ 0x01df, ++ 0x01e0, ++ }, ++ { ++ 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0894, 0x0890, 0x088c, 0x01dd, ++ 0x01de, ++ 0x01df, ++ }, ++ { ++ 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0898, 0x0894, 0x0890, 0x01dd, ++ 0x01dd, ++ 0x01de, ++ }, ++ { ++ 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x089c, 0x0898, 0x0894, 0x01dc, ++ 0x01dd, ++ 0x01dd, ++ }, ++ { ++ 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x08a0, 0x089c, 0x0898, 0x01db, ++ 0x01dc, ++ 0x01dd, ++ }, ++ { ++ 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a4, 0x08a0, 0x089c, 0x01da, ++ 0x01db, ++ 0x01dc, ++ }, ++ { ++ 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a8, 0x08a4, 0x08a0, 0x01d9, ++ 0x01da, ++ 0x01db, ++ }, ++ { ++ 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08ac, 0x08a8, 0x08a4, 0x01d8, ++ 0x01d9, ++ 0x01da, ++ }, ++ { ++ 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b0, 0x08ac, 0x08a8, 0x01d7, ++ 0x01d8, ++ 0x01d9, ++ }, ++ { ++ 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b4, 0x08b0, 0x08ac, 0x01d7, ++ 0x01d7, ++ 0x01d8, ++ }, ++ { ++ 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b8, 0x08b4, 0x08b0, 0x01d6, ++ 0x01d7, ++ 0x01d7, ++ }, ++ { ++ 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x00, ++ 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x08bc, 0x08b8, 0x08b4, 0x01d5, ++ 0x01d6, ++ 0x01d7, ++ }, ++ { ++ 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x00, ++ 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x08c0, 0x08bc, 0x08b8, 0x01d4, ++ 0x01d5, ++ 0x01d6, ++ }, ++ { ++ 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x00, ++ 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x08c4, 0x08c0, 0x08bc, 0x01d3, ++ 0x01d4, ++ 0x01d5, ++ }, ++ { ++ 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00, ++ 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08c8, 0x08c4, 0x08c0, 0x01d2, ++ 0x01d3, ++ 0x01d4, ++ }, ++ { ++ 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00, ++ 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08cc, 0x08c8, 0x08c4, 0x01d2, ++ 0x01d2, ++ 0x01d3, ++ }, ++ { ++ 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00, ++ 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d0, 0x08cc, 0x08c8, 0x01d1, ++ 0x01d2, ++ 0x01d2, ++ }, ++ { ++ 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00, ++ 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d4, 0x08d0, 0x08cc, 0x01d0, ++ 0x01d1, ++ 0x01d2, ++ }, ++ { ++ 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00, ++ 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08d8, 0x08d4, 0x08d0, 0x01cf, ++ 0x01d0, ++ 0x01d1, ++ }, ++ { ++ 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00, ++ 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08dc, 0x08d8, 0x08d4, 0x01ce, ++ 0x01cf, ++ 0x01d0, ++ }, ++ { ++ 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x00, ++ 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, ++ 0x01ce, ++ 0x01cf, ++ }, ++ { ++ 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, ++ 0x01ce, ++ 0x01ce, ++ }, ++ { ++ 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, ++ 0x01cd, ++ 0x01ce, ++ }, ++ { ++ 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, ++ 0x01cc, ++ 0x01cd, ++ }, ++ { ++ 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, ++ 0x01cb, ++ 0x01cc, ++ }, ++ { ++ 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, ++ 0x01ca, ++ 0x01cb, ++ }, ++ { ++ 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, ++ 0x01ca, ++ 0x01cb, ++ }, ++ { ++ 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, ++ 0x01c9, ++ 0x01ca, ++ }, ++ { ++ 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, ++ 0x01c9, ++ 0x01ca, ++ }, ++ { ++ 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, ++ 0x01c9, ++ 0x01c9, ++ }, ++ { ++ 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, ++ 0x01c8, ++ 0x01c9, ++ }, ++ { ++ 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, ++ 0x01c8, ++ 0x01c9, ++ }, ++ { ++ 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, ++ 0x01c8, ++ 0x01c8, ++ }, ++ { ++ 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, ++ 0x01c7, ++ 0x01c8, ++ }, ++ { ++ 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, ++ 0x01c7, ++ 0x01c8, ++ }, ++ { ++ 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, ++ 0x01c6, ++ 0x01c7, ++ }, ++ { ++ 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, ++ 0x01c6, ++ 0x01c7, ++ }, ++ { ++ 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, ++ 0x01c6, ++ 0x01c6, ++ }, ++ { ++ 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, ++ 0x01c5, ++ 0x01c6, ++ }, ++ { ++ 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, ++ 0x01c5, ++ 0x01c6, ++ }, ++ { ++ 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, ++ 0x01c4, ++ 0x01c5, ++ }, ++ { ++ 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, ++ 0x01c4, ++ 0x01c5, ++ }, ++ { ++ 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, ++ 0x01c4, ++ 0x01c4, ++ }, ++ { ++ 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, ++ 0x01c3, ++ 0x01c4, ++ }, ++ { ++ 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, ++ 0x01c3, ++ 0x01c4, ++ }, ++ { ++ 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, ++ 0x01c2, ++ 0x01c3, ++ }, ++ { ++ 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, ++ 0x01c2, ++ 0x01c3, ++ }, ++ { ++ 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, ++ 0x01c2, ++ 0x01c2, ++ }, ++ { ++ 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, ++ 0x01c1, ++ 0x01c2, ++ }, ++ { ++ 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, ++ 0x01c0, ++ 0x01c1, ++ }, ++ { ++ 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, ++ 0x01bf, ++ 0x01c0, ++ }, ++ { ++ 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, ++ 0x01bf, ++ 0x01bf, ++ }, ++ { ++ 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, ++ 0x01be, ++ 0x01bf, ++ }, ++ { ++ 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, ++ 0x01bd, ++ 0x01be, ++ }, ++ { ++ 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, ++ 0x01bc, ++ 0x01bd, ++ }, ++ { ++ 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f, ++ 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71, ++ 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a, ++ 0x043f, ++ 0x0443, ++ }, ++ { ++ 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f, ++ 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71, ++ 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438, ++ 0x043d, ++ 0x0441, ++ }, ++ { ++ 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f, ++ 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71, ++ 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436, ++ 0x043a, ++ 0x043f, ++ }, ++ { ++ 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f, ++ 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71, ++ 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434, ++ 0x0438, ++ 0x043d, ++ }, ++ { ++ 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f, ++ 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51, ++ 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431, ++ 0x0436, ++ 0x043a, ++ }, ++ { ++ 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f, ++ 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51, ++ 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f, ++ 0x0434, ++ 0x0438, ++ }, ++ { ++ 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x51, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d, ++ 0x0431, ++ 0x0436, ++ }, ++ { ++ 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b, ++ 0x042f, ++ 0x0434, ++ }, ++ { ++ 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429, ++ 0x042d, ++ 0x0431, ++ }, ++ { ++ 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f, ++ 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31, ++ 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427, ++ 0x042b, ++ 0x042f, ++ }, ++ { ++ 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f, ++ 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31, ++ 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424, ++ 0x0429, ++ 0x042d, ++ }, ++ { ++ 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f, ++ 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11, ++ 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422, ++ 0x0427, ++ 0x042b, ++ }, ++ { ++ 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f, ++ 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11, ++ 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420, ++ 0x0424, ++ 0x0429, ++ }, ++ { ++ 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f, ++ 0x04, 0x00, 0x04, 0x00, 0x11, 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x11, ++ 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b, ++ 0x041f, ++ 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio2057_rev5 ++chan_info_nphyrev8_2057_rev5[] = { ++ { ++ 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d, ++ 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1, ++ 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d, ++ 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3, ++ 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d, ++ 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5, ++ 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c, ++ 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7, ++ 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c, ++ 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9, ++ 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c, ++ 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb, ++ 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b, ++ 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd, ++ 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b, ++ 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf, ++ 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b, ++ 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1, ++ 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b, ++ 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3, ++ 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b, ++ 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5, ++ 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b, ++ 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7, ++ 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a, ++ 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9, ++ 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a, ++ 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de, ++ 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio2057_rev5 ++chan_info_nphyrev9_2057_rev5v1[] = { ++ { ++ 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d, ++ 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1, ++ 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d, ++ 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3, ++ 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d, ++ 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5, ++ 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c, ++ 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7, ++ 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c, ++ 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9, ++ 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c, ++ 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb, ++ 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b, ++ 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd, ++ 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b, ++ 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf, ++ 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b, ++ 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1, ++ 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b, ++ 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3, ++ 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b, ++ 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5, ++ 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b, ++ 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7, ++ 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a, ++ 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9, ++ 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a, ++ 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de, ++ 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev7[] = { ++ { ++ 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b4, 0x07b0, 0x07ac, 0x0214, ++ 0x0215, ++ 0x0216}, ++ { ++ 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213, ++ 0x0214, ++ 0x0215}, ++ { ++ 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212, ++ 0x0213, ++ 0x0214}, ++ { ++ 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211, ++ 0x0212, ++ 0x0213}, ++ { ++ 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f, ++ 0x0211, ++ 0x0212}, ++ { ++ 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e, ++ 0x020f, ++ 0x0211}, ++ { ++ 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d, ++ 0x020e, ++ 0x020f}, ++ { ++ 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c, ++ 0x020d, ++ 0x020e}, ++ { ++ 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b, ++ 0x020c, ++ 0x020d}, ++ { ++ 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a, ++ 0x020b, ++ 0x020c}, ++ { ++ 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209, ++ 0x020a, ++ 0x020b}, ++ { ++ 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208, ++ 0x0209, ++ 0x020a}, ++ { ++ 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207, ++ 0x0208, ++ 0x0209}, ++ { ++ 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206, ++ 0x0207, ++ 0x0208}, ++ { ++ 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205, ++ 0x0206, ++ 0x0207}, ++ { ++ 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204, ++ 0x0205, ++ 0x0206}, ++ { ++ 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203, ++ 0x0204, ++ 0x0205}, ++ { ++ 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202, ++ 0x0203, ++ 0x0204}, ++ { ++ 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201, ++ 0x0202, ++ 0x0203}, ++ { ++ 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200, ++ 0x0201, ++ 0x0202}, ++ { ++ 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff, ++ 0x0200, ++ 0x0201}, ++ { ++ 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe, ++ 0x01ff, ++ 0x0200}, ++ { ++ 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd, ++ 0x01fe, ++ 0x01ff}, ++ { ++ 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb, ++ 0x01fc, ++ 0x01fd}, ++ { ++ 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa, ++ 0x01fb, ++ 0x01fc}, ++ { ++ 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9, ++ 0x01fa, ++ 0x01fb}, ++ { ++ 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8, ++ 0x01f9, ++ 0x01fa}, ++ { ++ 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7, ++ 0x01f8, ++ 0x01f9}, ++ { ++ 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6, ++ 0x01f7, ++ 0x01f8}, ++ { ++ 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5, ++ 0x01f6, ++ 0x01f7}, ++ { ++ 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4, ++ 0x01f5, ++ 0x01f6}, ++ { ++ 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3, ++ 0x01f4, ++ 0x01f5}, ++ { ++ 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2, ++ 0x01f3, ++ 0x01f4}, ++ { ++ 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1, ++ 0x01f2, ++ 0x01f3}, ++ { ++ 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0, ++ 0x01f1, ++ 0x01f2}, ++ { ++ 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0, ++ 0x01f0, ++ 0x01f1}, ++ { ++ 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef, ++ 0x01f0, ++ 0x01f0}, ++ { ++ 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee, ++ 0x01ef, ++ 0x01f0}, ++ { ++ 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed, ++ 0x01ee, ++ 0x01ef}, ++ { ++ 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec, ++ 0x01ed, ++ 0x01ee}, ++ { ++ 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb, ++ 0x01ec, ++ 0x01ed}, ++ { ++ 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea, ++ 0x01eb, ++ 0x01ec}, ++ { ++ 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9, ++ 0x01ea, ++ 0x01eb}, ++ { ++ 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8, ++ 0x01e9, ++ 0x01ea}, ++ { ++ 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7, ++ 0x01e8, ++ 0x01e9}, ++ { ++ 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6, ++ 0x01e7, ++ 0x01e8}, ++ { ++ 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5, ++ 0x01e6, ++ 0x01e7}, ++ { ++ 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5, ++ 0x01e5, ++ 0x01e6}, ++ { ++ 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4, ++ 0x01e5, ++ 0x01e5}, ++ { ++ 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3, ++ 0x01e4, ++ 0x01e5}, ++ { ++ 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2, ++ 0x01e3, ++ 0x01e4}, ++ { ++ 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1, ++ 0x01e2, ++ 0x01e3}, ++ { ++ 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0, ++ 0x01e1, ++ 0x01e2}, ++ { ++ 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df, ++ 0x01e0, ++ 0x01e1}, ++ { ++ 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de, ++ 0x01df, ++ 0x01e0}, ++ { ++ 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd, ++ 0x01de, ++ 0x01df}, ++ { ++ 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd, ++ 0x01dd, ++ 0x01de}, ++ { ++ 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc, ++ 0x01dd, ++ 0x01dd}, ++ { ++ 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db, ++ 0x01dc, ++ 0x01dd}, ++ { ++ 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da, ++ 0x01db, ++ 0x01dc}, ++ { ++ 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9, ++ 0x01da, ++ 0x01db}, ++ { ++ 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8, ++ 0x01d9, ++ 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7, ++ 0x01d8, ++ 0x01d9}, ++ { ++ 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7, ++ 0x01d7, ++ 0x01d8}, ++ { ++ 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6, ++ 0x01d7, ++ 0x01d7}, ++ { ++ 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5, ++ 0x01d6, ++ 0x01d7}, ++ { ++ 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4, ++ 0x01d5, ++ 0x01d6}, ++ { ++ 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3, ++ 0x01d4, ++ 0x01d5}, ++ { ++ 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2, ++ 0x01d3, ++ 0x01d4}, ++ { ++ 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2, ++ 0x01d2, ++ 0x01d3}, ++ { ++ 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1, ++ 0x01d2, ++ 0x01d2}, ++ { ++ 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0, ++ 0x01d1, ++ 0x01d2}, ++ { ++ 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf, ++ 0x01d0, ++ 0x01d1}, ++ { ++ 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce, ++ 0x01cf, ++ 0x01d0}, ++ { ++ 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce, ++ 0x01ce, ++ 0x01cf}, ++ { ++ 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd, ++ 0x01ce, ++ 0x01ce}, ++ { ++ 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc, ++ 0x01cd, ++ 0x01ce}, ++ { ++ 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb, ++ 0x01cc, ++ 0x01cd}, ++ { ++ 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca, ++ 0x01cb, ++ 0x01cc}, ++ { ++ 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9, ++ 0x01ca, ++ 0x01cb}, ++ { ++ 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9, ++ 0x01ca, ++ 0x01cb}, ++ { ++ 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9, ++ 0x01c9, ++ 0x01ca}, ++ { ++ 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8, ++ 0x01c9, ++ 0x01ca}, ++ { ++ 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8, ++ 0x01c9, ++ 0x01c9}, ++ { ++ 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8, ++ 0x01c8, ++ 0x01c9}, ++ { ++ 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, ++ 0x01c8, ++ 0x01c9}, ++ { ++ 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, ++ 0x01c8, ++ 0x01c8}, ++ { ++ 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, ++ 0x01c7, ++ 0x01c8}, ++ { ++ 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, ++ 0x01c7, ++ 0x01c8}, ++ { ++ 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, ++ 0x01c6, ++ 0x01c7}, ++ { ++ 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, ++ 0x01c6, ++ 0x01c7}, ++ { ++ 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, ++ 0x01c6, ++ 0x01c6}, ++ { ++ 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, ++ 0x01c5, ++ 0x01c6}, ++ { ++ 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, ++ 0x01c5, ++ 0x01c6}, ++ { ++ 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, ++ 0x01c4, ++ 0x01c5}, ++ { ++ 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, ++ 0x01c4, ++ 0x01c5}, ++ { ++ 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, ++ 0x01c4, ++ 0x01c4}, ++ { ++ 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, ++ 0x01c3, ++ 0x01c4}, ++ { ++ 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, ++ 0x01c3, ++ 0x01c4}, ++ { ++ 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, ++ 0x01c2, ++ 0x01c3}, ++ { ++ 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, ++ 0x01c2, ++ 0x01c3}, ++ { ++ 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, ++ 0x01c2, ++ 0x01c2}, ++ { ++ 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, ++ 0x01c1, ++ 0x01c2}, ++ { ++ 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, ++ 0x01c0, ++ 0x01c1}, ++ { ++ 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, ++ 0x01bf, ++ 0x01c0}, ++ { ++ 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, ++ 0x01bf, ++ 0x01bf}, ++ { ++ 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, ++ 0x01be, ++ 0x01bf}, ++ { ++ 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, ++ 0x01bd, ++ 0x01be}, ++ { ++ 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, ++ 0x01bc, ++ 0x01bd}, ++ { ++ 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f, ++ 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a, ++ 0x043f, ++ 0x0443}, ++ { ++ 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f, ++ 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438, ++ 0x043d, ++ 0x0441}, ++ { ++ 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f, ++ 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436, ++ 0x043a, ++ 0x043f}, ++ { ++ 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f, ++ 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434, ++ 0x0438, ++ 0x043d}, ++ { ++ 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f, ++ 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431, ++ 0x0436, ++ 0x043a}, ++ { ++ 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f, ++ 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f, ++ 0x0434, ++ 0x0438}, ++ { ++ 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d, ++ 0x0431, ++ 0x0436}, ++ { ++ 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b, ++ 0x042f, ++ 0x0434}, ++ { ++ 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429, ++ 0x042d, ++ 0x0431}, ++ { ++ 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f, ++ 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427, ++ 0x042b, ++ 0x042f}, ++ { ++ 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f, ++ 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424, ++ 0x0429, ++ 0x042d}, ++ { ++ 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f, ++ 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422, ++ 0x0427, ++ 0x042b}, ++ { ++ 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f, ++ 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420, ++ 0x0424, ++ 0x0429}, ++ { ++ 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f, ++ 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b, ++ 0x041f, ++ 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev8[] = { ++ { ++ 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213, ++ 0x0214, ++ 0x0215}, ++ { ++ 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212, ++ 0x0213, ++ 0x0214}, ++ { ++ 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211, ++ 0x0212, ++ 0x0213}, ++ { ++ 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f, ++ 0x0211, ++ 0x0212}, ++ { ++ 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e, ++ 0x020f, ++ 0x0211}, ++ { ++ 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d, ++ 0x020e, ++ 0x020f}, ++ { ++ 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c, ++ 0x020d, ++ 0x020e}, ++ { ++ 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b, ++ 0x020c, ++ 0x020d}, ++ { ++ 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a, ++ 0x020b, ++ 0x020c}, ++ { ++ 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209, ++ 0x020a, ++ 0x020b}, ++ { ++ 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208, ++ 0x0209, ++ 0x020a}, ++ { ++ 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207, ++ 0x0208, ++ 0x0209}, ++ { ++ 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206, ++ 0x0207, ++ 0x0208}, ++ { ++ 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205, ++ 0x0206, ++ 0x0207}, ++ { ++ 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204, ++ 0x0205, ++ 0x0206}, ++ { ++ 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203, ++ 0x0204, ++ 0x0205}, ++ { ++ 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202, ++ 0x0203, ++ 0x0204}, ++ { ++ 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201, ++ 0x0202, ++ 0x0203}, ++ { ++ 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200, ++ 0x0201, ++ 0x0202}, ++ { ++ 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff, ++ 0x0200, ++ 0x0201}, ++ { ++ 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe, ++ 0x01ff, ++ 0x0200}, ++ { ++ 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd, ++ 0x01fe, ++ 0x01ff}, ++ { ++ 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb, ++ 0x01fc, ++ 0x01fd}, ++ { ++ 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa, ++ 0x01fb, ++ 0x01fc}, ++ { ++ 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9, ++ 0x01fa, ++ 0x01fb}, ++ { ++ 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8, ++ 0x01f9, ++ 0x01fa}, ++ { ++ 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7, ++ 0x01f8, ++ 0x01f9}, ++ { ++ 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6, ++ 0x01f7, ++ 0x01f8}, ++ { ++ 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5, ++ 0x01f6, ++ 0x01f7}, ++ { ++ 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4, ++ 0x01f5, ++ 0x01f6}, ++ { ++ 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3, ++ 0x01f4, ++ 0x01f5}, ++ { ++ 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2, ++ 0x01f3, ++ 0x01f4}, ++ { ++ 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1, ++ 0x01f2, ++ 0x01f3}, ++ { ++ 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0, ++ 0x01f1, ++ 0x01f2}, ++ { ++ 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0, ++ 0x01f0, ++ 0x01f1}, ++ { ++ 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef, ++ 0x01f0, ++ 0x01f0}, ++ { ++ 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee, ++ 0x01ef, ++ 0x01f0}, ++ { ++ 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed, ++ 0x01ee, ++ 0x01ef}, ++ { ++ 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec, ++ 0x01ed, ++ 0x01ee}, ++ { ++ 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb, ++ 0x01ec, ++ 0x01ed}, ++ { ++ 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea, ++ 0x01eb, ++ 0x01ec}, ++ { ++ 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9, ++ 0x01ea, ++ 0x01eb}, ++ { ++ 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8, ++ 0x01e9, ++ 0x01ea}, ++ { ++ 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7, ++ 0x01e8, ++ 0x01e9}, ++ { ++ 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6, ++ 0x01e7, ++ 0x01e8}, ++ { ++ 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5, ++ 0x01e6, ++ 0x01e7}, ++ { ++ 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5, ++ 0x01e5, ++ 0x01e6}, ++ { ++ 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4, ++ 0x01e5, ++ 0x01e5}, ++ { ++ 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3, ++ 0x01e4, ++ 0x01e5}, ++ { ++ 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2, ++ 0x01e3, ++ 0x01e4}, ++ { ++ 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1, ++ 0x01e2, ++ 0x01e3}, ++ { ++ 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0, ++ 0x01e1, ++ 0x01e2}, ++ { ++ 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df, ++ 0x01e0, ++ 0x01e1}, ++ { ++ 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de, ++ 0x01df, ++ 0x01e0}, ++ { ++ 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd, ++ 0x01de, ++ 0x01df}, ++ { ++ 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd, ++ 0x01dd, ++ 0x01de}, ++ { ++ 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc, ++ 0x01dd, ++ 0x01dd}, ++ { ++ 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db, ++ 0x01dc, ++ 0x01dd}, ++ { ++ 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da, ++ 0x01db, ++ 0x01dc}, ++ { ++ 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9, ++ 0x01da, ++ 0x01db}, ++ { ++ 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8, ++ 0x01d9, ++ 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7, ++ 0x01d8, ++ 0x01d9}, ++ { ++ 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7, ++ 0x01d7, ++ 0x01d8}, ++ { ++ 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6, ++ 0x01d7, ++ 0x01d7}, ++ { ++ 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5, ++ 0x01d6, ++ 0x01d7}, ++ { ++ 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4, ++ 0x01d5, ++ 0x01d6}, ++ { ++ 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3, ++ 0x01d4, ++ 0x01d5}, ++ { ++ 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2, ++ 0x01d3, ++ 0x01d4}, ++ { ++ 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2, ++ 0x01d2, ++ 0x01d3}, ++ { ++ 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1, ++ 0x01d2, ++ 0x01d2}, ++ { ++ 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0, ++ 0x01d1, ++ 0x01d2}, ++ { ++ 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf, ++ 0x01d0, ++ 0x01d1}, ++ { ++ 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce, ++ 0x01cf, ++ 0x01d0}, ++ { ++ 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce, ++ 0x01ce, ++ 0x01cf}, ++ { ++ 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd, ++ 0x01ce, ++ 0x01ce}, ++ { ++ 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc, ++ 0x01cd, ++ 0x01ce}, ++ { ++ 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb, ++ 0x01cc, ++ 0x01cd}, ++ { ++ 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca, ++ 0x01cb, ++ 0x01cc}, ++ { ++ 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9, ++ 0x01ca, ++ 0x01cb}, ++ { ++ 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9, ++ 0x01ca, ++ 0x01cb}, ++ { ++ 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9, ++ 0x01c9, ++ 0x01ca}, ++ { ++ 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8, ++ 0x01c9, ++ 0x01ca}, ++ { ++ 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8, ++ 0x01c9, ++ 0x01c9}, ++ { ++ 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8, ++ 0x01c8, ++ 0x01c9}, ++ { ++ 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, ++ 0x01c8, ++ 0x01c9}, ++ { ++ 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, ++ 0x01c8, ++ 0x01c8}, ++ { ++ 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, ++ 0x01c7, ++ 0x01c8}, ++ { ++ 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, ++ 0x01c7, ++ 0x01c8}, ++ { ++ 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, ++ 0x01c6, ++ 0x01c7}, ++ { ++ 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, ++ 0x01c6, ++ 0x01c7}, ++ { ++ 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, ++ 0x01c6, ++ 0x01c6}, ++ { ++ 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, ++ 0x01c5, ++ 0x01c6}, ++ { ++ 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, ++ 0x01c5, ++ 0x01c6}, ++ { ++ 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, ++ 0x01c4, ++ 0x01c5}, ++ { ++ 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, ++ 0x01c4, ++ 0x01c5}, ++ { ++ 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, ++ 0x01c4, ++ 0x01c4}, ++ { ++ 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, ++ 0x01c3, ++ 0x01c4}, ++ { ++ 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, ++ 0x01c3, ++ 0x01c4}, ++ { ++ 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, ++ 0x01c2, ++ 0x01c3}, ++ { ++ 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, ++ 0x01c2, ++ 0x01c3}, ++ { ++ 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, ++ 0x01c2, ++ 0x01c2}, ++ { ++ 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, ++ 0x01c1, ++ 0x01c2}, ++ { ++ 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, ++ 0x01c0, ++ 0x01c1}, ++ { ++ 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, ++ 0x01bf, ++ 0x01c0}, ++ { ++ 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, ++ 0x01bf, ++ 0x01bf}, ++ { ++ 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, ++ 0x01be, ++ 0x01bf}, ++ { ++ 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, ++ 0x01bd, ++ 0x01be}, ++ { ++ 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, ++ 0x01bc, ++ 0x01bd}, ++ { ++ 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f, ++ 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a, ++ 0x043f, ++ 0x0443}, ++ { ++ 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f, ++ 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438, ++ 0x043d, ++ 0x0441}, ++ { ++ 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f, ++ 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436, ++ 0x043a, ++ 0x043f}, ++ { ++ 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f, ++ 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434, ++ 0x0438, ++ 0x043d}, ++ { ++ 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f, ++ 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431, ++ 0x0436, ++ 0x043a}, ++ { ++ 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f, ++ 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f, ++ 0x0434, ++ 0x0438}, ++ { ++ 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d, ++ 0x0431, ++ 0x0436}, ++ { ++ 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b, ++ 0x042f, ++ 0x0434}, ++ { ++ 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429, ++ 0x042d, ++ 0x0431}, ++ { ++ 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f, ++ 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427, ++ 0x042b, ++ 0x042f}, ++ { ++ 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f, ++ 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424, ++ 0x0429, ++ 0x042d}, ++ { ++ 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f, ++ 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422, ++ 0x0427, ++ 0x042b}, ++ { ++ 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f, ++ 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420, ++ 0x0424, ++ 0x0429}, ++ { ++ 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f, ++ 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b, ++ 0x041f, ++ 0x0424} ++}; ++ ++static struct radio_regs regs_2055[] = { ++ {0x02, 0x80, 0x80, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0x27, 0x27, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0x27, 0x27, 0, 0}, ++ {0x07, 0x7f, 0x7f, 1, 1}, ++ {0x08, 0x7, 0x7, 1, 1}, ++ {0x09, 0x7f, 0x7f, 1, 1}, ++ {0x0A, 0x7, 0x7, 1, 1}, ++ {0x0B, 0x15, 0x15, 0, 0}, ++ {0x0C, 0x15, 0x15, 0, 0}, ++ {0x0D, 0x4f, 0x4f, 1, 1}, ++ {0x0E, 0x5, 0x5, 1, 1}, ++ {0x0F, 0x4f, 0x4f, 1, 1}, ++ {0x10, 0x5, 0x5, 1, 1}, ++ {0x11, 0xd0, 0xd0, 0, 0}, ++ {0x12, 0x2, 0x2, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0x40, 0x40, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0xc0, 0xc0, 0, 0}, ++ {0x1E, 0xff, 0xff, 0, 0}, ++ {0x1F, 0xc0, 0xc0, 0, 0}, ++ {0x20, 0xff, 0xff, 0, 0}, ++ {0x21, 0xc0, 0xc0, 0, 0}, ++ {0x22, 0, 0, 0, 0}, ++ {0x23, 0x2c, 0x2c, 0, 0}, ++ {0x24, 0, 0, 0, 0}, ++ {0x25, 0, 0, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0, 0, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0, 0, 0, 0}, ++ {0x2A, 0, 0, 0, 0}, ++ {0x2B, 0, 0, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0xa4, 0xa4, 0, 0}, ++ {0x2E, 0x38, 0x38, 0, 0}, ++ {0x2F, 0, 0, 0, 0}, ++ {0x30, 0x4, 0x4, 1, 1}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0xa, 0xa, 0, 0}, ++ {0x33, 0x87, 0x87, 0, 0}, ++ {0x34, 0x9, 0x9, 0, 0}, ++ {0x35, 0x70, 0x70, 0, 0}, ++ {0x36, 0x11, 0x11, 0, 0}, ++ {0x37, 0x18, 0x18, 1, 1}, ++ {0x38, 0x6, 0x6, 0, 0}, ++ {0x39, 0x4, 0x4, 1, 1}, ++ {0x3A, 0x6, 0x6, 0, 0}, ++ {0x3B, 0x9e, 0x9e, 0, 0}, ++ {0x3C, 0x9, 0x9, 0, 0}, ++ {0x3D, 0xc8, 0xc8, 1, 1}, ++ {0x3E, 0x88, 0x88, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0, 0, 0, 0}, ++ {0x42, 0x1, 0x1, 0, 0}, ++ {0x43, 0x2, 0x2, 0, 0}, ++ {0x44, 0x96, 0x96, 0, 0}, ++ {0x45, 0x3e, 0x3e, 0, 0}, ++ {0x46, 0x3e, 0x3e, 0, 0}, ++ {0x47, 0x13, 0x13, 0, 0}, ++ {0x48, 0x2, 0x2, 0, 0}, ++ {0x49, 0x15, 0x15, 0, 0}, ++ {0x4A, 0x7, 0x7, 0, 0}, ++ {0x4B, 0, 0, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0, 0, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0, 0, 0, 0}, ++ {0x50, 0x8, 0x8, 0, 0}, ++ {0x51, 0x8, 0x8, 0, 0}, ++ {0x52, 0x6, 0x6, 0, 0}, ++ {0x53, 0x84, 0x84, 1, 1}, ++ {0x54, 0xc3, 0xc3, 0, 0}, ++ {0x55, 0x8f, 0x8f, 0, 0}, ++ {0x56, 0xff, 0xff, 0, 0}, ++ {0x57, 0xff, 0xff, 0, 0}, ++ {0x58, 0x88, 0x88, 0, 0}, ++ {0x59, 0x88, 0x88, 0, 0}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0xcc, 0xcc, 0, 0}, ++ {0x5C, 0x6, 0x6, 0, 0}, ++ {0x5D, 0x80, 0x80, 0, 0}, ++ {0x5E, 0x80, 0x80, 0, 0}, ++ {0x5F, 0xf8, 0xf8, 0, 0}, ++ {0x60, 0x88, 0x88, 0, 0}, ++ {0x61, 0x88, 0x88, 0, 0}, ++ {0x62, 0x88, 0x8, 1, 1}, ++ {0x63, 0x88, 0x88, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0x1, 0x1, 1, 1}, ++ {0x66, 0x8a, 0x8a, 0, 0}, ++ {0x67, 0x8, 0x8, 0, 0}, ++ {0x68, 0x83, 0x83, 0, 0}, ++ {0x69, 0x6, 0x6, 0, 0}, ++ {0x6A, 0xa0, 0xa0, 0, 0}, ++ {0x6B, 0xa, 0xa, 0, 0}, ++ {0x6C, 0x87, 0x87, 1, 1}, ++ {0x6D, 0x2a, 0x2a, 0, 0}, ++ {0x6E, 0x2a, 0x2a, 0, 0}, ++ {0x6F, 0x2a, 0x2a, 0, 0}, ++ {0x70, 0x2a, 0x2a, 0, 0}, ++ {0x71, 0x18, 0x18, 0, 0}, ++ {0x72, 0x6a, 0x6a, 1, 1}, ++ {0x73, 0xab, 0xab, 1, 1}, ++ {0x74, 0x13, 0x13, 1, 1}, ++ {0x75, 0xc1, 0xc1, 1, 1}, ++ {0x76, 0xaa, 0xaa, 1, 1}, ++ {0x77, 0x87, 0x87, 1, 1}, ++ {0x78, 0, 0, 0, 0}, ++ {0x79, 0x6, 0x6, 0, 0}, ++ {0x7A, 0x7, 0x7, 0, 0}, ++ {0x7B, 0x7, 0x7, 0, 0}, ++ {0x7C, 0x15, 0x15, 0, 0}, ++ {0x7D, 0x55, 0x55, 0, 0}, ++ {0x7E, 0x97, 0x97, 1, 1}, ++ {0x7F, 0x8, 0x8, 0, 0}, ++ {0x80, 0x14, 0x14, 1, 1}, ++ {0x81, 0x33, 0x33, 0, 0}, ++ {0x82, 0x88, 0x88, 0, 0}, ++ {0x83, 0x6, 0x6, 0, 0}, ++ {0x84, 0x3, 0x3, 1, 1}, ++ {0x85, 0xa, 0xa, 0, 0}, ++ {0x86, 0x3, 0x3, 1, 1}, ++ {0x87, 0x2a, 0x2a, 0, 0}, ++ {0x88, 0xa4, 0xa4, 0, 0}, ++ {0x89, 0x18, 0x18, 0, 0}, ++ {0x8A, 0x28, 0x28, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0x4a, 0x4a, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0xf8, 0xf8, 0, 0}, ++ {0x8F, 0x88, 0x88, 0, 0}, ++ {0x90, 0x88, 0x88, 0, 0}, ++ {0x91, 0x88, 0x8, 1, 1}, ++ {0x92, 0x88, 0x88, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0x1, 0x1, 1, 1}, ++ {0x95, 0x8a, 0x8a, 0, 0}, ++ {0x96, 0x8, 0x8, 0, 0}, ++ {0x97, 0x83, 0x83, 0, 0}, ++ {0x98, 0x6, 0x6, 0, 0}, ++ {0x99, 0xa0, 0xa0, 0, 0}, ++ {0x9A, 0xa, 0xa, 0, 0}, ++ {0x9B, 0x87, 0x87, 1, 1}, ++ {0x9C, 0x2a, 0x2a, 0, 0}, ++ {0x9D, 0x2a, 0x2a, 0, 0}, ++ {0x9E, 0x2a, 0x2a, 0, 0}, ++ {0x9F, 0x2a, 0x2a, 0, 0}, ++ {0xA0, 0x18, 0x18, 0, 0}, ++ {0xA1, 0x6a, 0x6a, 1, 1}, ++ {0xA2, 0xab, 0xab, 1, 1}, ++ {0xA3, 0x13, 0x13, 1, 1}, ++ {0xA4, 0xc1, 0xc1, 1, 1}, ++ {0xA5, 0xaa, 0xaa, 1, 1}, ++ {0xA6, 0x87, 0x87, 1, 1}, ++ {0xA7, 0, 0, 0, 0}, ++ {0xA8, 0x6, 0x6, 0, 0}, ++ {0xA9, 0x7, 0x7, 0, 0}, ++ {0xAA, 0x7, 0x7, 0, 0}, ++ {0xAB, 0x15, 0x15, 0, 0}, ++ {0xAC, 0x55, 0x55, 0, 0}, ++ {0xAD, 0x97, 0x97, 1, 1}, ++ {0xAE, 0x8, 0x8, 0, 0}, ++ {0xAF, 0x14, 0x14, 1, 1}, ++ {0xB0, 0x33, 0x33, 0, 0}, ++ {0xB1, 0x88, 0x88, 0, 0}, ++ {0xB2, 0x6, 0x6, 0, 0}, ++ {0xB3, 0x3, 0x3, 1, 1}, ++ {0xB4, 0xa, 0xa, 0, 0}, ++ {0xB5, 0x3, 0x3, 1, 1}, ++ {0xB6, 0x2a, 0x2a, 0, 0}, ++ {0xB7, 0xa4, 0xa4, 0, 0}, ++ {0xB8, 0x18, 0x18, 0, 0}, ++ {0xB9, 0x28, 0x28, 0, 0}, ++ {0xBA, 0, 0, 0, 0}, ++ {0xBB, 0x4a, 0x4a, 0, 0}, ++ {0xBC, 0, 0, 0, 0}, ++ {0xBD, 0x71, 0x71, 0, 0}, ++ {0xBE, 0x72, 0x72, 0, 0}, ++ {0xBF, 0x73, 0x73, 0, 0}, ++ {0xC0, 0x74, 0x74, 0, 0}, ++ {0xC1, 0x75, 0x75, 0, 0}, ++ {0xC2, 0x76, 0x76, 0, 0}, ++ {0xC3, 0x77, 0x77, 0, 0}, ++ {0xC4, 0x78, 0x78, 0, 0}, ++ {0xC5, 0x79, 0x79, 0, 0}, ++ {0xC6, 0x7a, 0x7a, 0, 0}, ++ {0xC7, 0, 0, 0, 0}, ++ {0xC8, 0, 0, 0, 0}, ++ {0xC9, 0, 0, 0, 0}, ++ {0xCA, 0, 0, 0, 0}, ++ {0xCB, 0, 0, 0, 0}, ++ {0xCC, 0, 0, 0, 0}, ++ {0xCD, 0, 0, 0, 0}, ++ {0xCE, 0x6, 0x6, 0, 0}, ++ {0xCF, 0, 0, 0, 0}, ++ {0xD0, 0, 0, 0, 0}, ++ {0xD1, 0x18, 0x18, 0, 0}, ++ {0xD2, 0x88, 0x88, 0, 0}, ++ {0xD3, 0, 0, 0, 0}, ++ {0xD4, 0, 0, 0, 0}, ++ {0xD5, 0, 0, 0, 0}, ++ {0xD6, 0, 0, 0, 0}, ++ {0xD7, 0, 0, 0, 0}, ++ {0xD8, 0, 0, 0, 0}, ++ {0xD9, 0, 0, 0, 0}, ++ {0xDA, 0x6, 0x6, 0, 0}, ++ {0xDB, 0, 0, 0, 0}, ++ {0xDC, 0, 0, 0, 0}, ++ {0xDD, 0x18, 0x18, 0, 0}, ++ {0xDE, 0x88, 0x88, 0, 0}, ++ {0xDF, 0, 0, 0, 0}, ++ {0xE0, 0, 0, 0, 0}, ++ {0xE1, 0, 0, 0, 0}, ++ {0xE2, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static struct radio_regs regs_SYN_2056[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0x1, 0x1, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0x60, 0x60, 0, 0}, ++ {0x23, 0x6, 0x6, 0, 0}, ++ {0x24, 0xc, 0xc, 0, 0}, ++ {0x25, 0, 0, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0, 0, 0, 0}, ++ {0x28, 0x1, 0x1, 0, 0}, ++ {0x29, 0, 0, 0, 0}, ++ {0x2A, 0, 0, 0, 0}, ++ {0x2B, 0, 0, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0xd, 0xd, 0, 0}, ++ {0x2F, 0x1f, 0x1f, 0, 0}, ++ {0x30, 0x15, 0x15, 0, 0}, ++ {0x31, 0xf, 0xf, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0, 0, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0, 0, 0, 0}, ++ {0x38, 0, 0, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0, 0, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x13, 0x13, 0, 0}, ++ {0x3D, 0xf, 0xf, 0, 0}, ++ {0x3E, 0x18, 0x18, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x20, 0x20, 0, 0}, ++ {0x42, 0x20, 0x20, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x77, 0x77, 0, 0}, ++ {0x45, 0x7, 0x7, 0, 0}, ++ {0x46, 0x1, 0x1, 0, 0}, ++ {0x47, 0x4, 0x4, 0, 0}, ++ {0x48, 0xf, 0xf, 0, 0}, ++ {0x49, 0x30, 0x30, 0, 0}, ++ {0x4A, 0x32, 0x32, 0, 0}, ++ {0x4B, 0xd, 0xd, 0, 0}, ++ {0x4C, 0xd, 0xd, 0, 0}, ++ {0x4D, 0x4, 0x4, 0, 0}, ++ {0x4E, 0x6, 0x6, 0, 0}, ++ {0x4F, 0x1, 0x1, 0, 0}, ++ {0x50, 0x1c, 0x1c, 0, 0}, ++ {0x51, 0x2, 0x2, 0, 0}, ++ {0x52, 0x2, 0x2, 0, 0}, ++ {0x53, 0xf7, 0xf7, 1, 1}, ++ {0x54, 0xb4, 0xb4, 0, 0}, ++ {0x55, 0xd2, 0xd2, 0, 0}, ++ {0x56, 0, 0, 0, 0}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x4, 0x4, 0, 0}, ++ {0x59, 0x96, 0x96, 0, 0}, ++ {0x5A, 0x3e, 0x3e, 0, 0}, ++ {0x5B, 0x3e, 0x3e, 0, 0}, ++ {0x5C, 0x13, 0x13, 0, 0}, ++ {0x5D, 0x2, 0x2, 0, 0}, ++ {0x5E, 0, 0, 0, 0}, ++ {0x5F, 0x7, 0x7, 0, 0}, ++ {0x60, 0x7, 0x7, 1, 1}, ++ {0x61, 0x8, 0x8, 0, 0}, ++ {0x62, 0x3, 0x3, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0x40, 0x40, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0x1, 0x1, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0x60, 0x60, 0, 0}, ++ {0x71, 0x66, 0x66, 0, 0}, ++ {0x72, 0xc, 0xc, 0, 0}, ++ {0x73, 0x66, 0x66, 0, 0}, ++ {0x74, 0x8f, 0x8f, 1, 1}, ++ {0x75, 0, 0, 0, 0}, ++ {0x76, 0xcc, 0xcc, 0, 0}, ++ {0x77, 0x1, 0x1, 0, 0}, ++ {0x78, 0x66, 0x66, 0, 0}, ++ {0x79, 0x66, 0x66, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0xff, 0xff, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0x95, 0, 0, 0, 0}, ++ {0x96, 0, 0, 0, 0}, ++ {0x97, 0, 0, 0, 0}, ++ {0x98, 0, 0, 0, 0}, ++ {0x99, 0, 0, 0, 0}, ++ {0x9A, 0, 0, 0, 0}, ++ {0x9B, 0, 0, 0, 0}, ++ {0x9C, 0, 0, 0, 0}, ++ {0x9D, 0, 0, 0, 0}, ++ {0x9E, 0, 0, 0, 0}, ++ {0x9F, 0x6, 0x6, 0, 0}, ++ {0xA0, 0x66, 0x66, 0, 0}, ++ {0xA1, 0x66, 0x66, 0, 0}, ++ {0xA2, 0x66, 0x66, 0, 0}, ++ {0xA3, 0x66, 0x66, 0, 0}, ++ {0xA4, 0x66, 0x66, 0, 0}, ++ {0xA5, 0x66, 0x66, 0, 0}, ++ {0xA6, 0x66, 0x66, 0, 0}, ++ {0xA7, 0x66, 0x66, 0, 0}, ++ {0xA8, 0x66, 0x66, 0, 0}, ++ {0xA9, 0x66, 0x66, 0, 0}, ++ {0xAA, 0x66, 0x66, 0, 0}, ++ {0xAB, 0x66, 0x66, 0, 0}, ++ {0xAC, 0x66, 0x66, 0, 0}, ++ {0xAD, 0x66, 0x66, 0, 0}, ++ {0xAE, 0x66, 0x66, 0, 0}, ++ {0xAF, 0x66, 0x66, 0, 0}, ++ {0xB0, 0x66, 0x66, 0, 0}, ++ {0xB1, 0x66, 0x66, 0, 0}, ++ {0xB2, 0x66, 0x66, 0, 0}, ++ {0xB3, 0xa, 0xa, 0, 0}, ++ {0xB4, 0, 0, 0, 0}, ++ {0xB5, 0, 0, 0, 0}, ++ {0xB6, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_TX_2056[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0x88, 0x88, 0, 0}, ++ {0x22, 0x88, 0x88, 0, 0}, ++ {0x23, 0x88, 0x88, 0, 0}, ++ {0x24, 0x88, 0x88, 0, 0}, ++ {0x25, 0xc, 0xc, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0x3, 0x3, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0x3, 0x3, 0, 0}, ++ {0x2A, 0x37, 0x37, 0, 0}, ++ {0x2B, 0x3, 0x3, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0x1, 0x1, 0, 0}, ++ {0x2F, 0x1, 0x1, 0, 0}, ++ {0x30, 0, 0, 0, 0}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0x11, 0x11, 0, 0}, ++ {0x34, 0x11, 0x11, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0x3, 0x3, 0, 0}, ++ {0x38, 0xf, 0xf, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0x2d, 0x2d, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x6e, 0x6e, 0, 0}, ++ {0x3D, 0xf0, 0xf0, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x3, 0x3, 0, 0}, ++ {0x42, 0x3, 0x3, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x1e, 0x1e, 0, 0}, ++ {0x45, 0, 0, 0, 0}, ++ {0x46, 0x6e, 0x6e, 0, 0}, ++ {0x47, 0xf0, 0xf0, 1, 1}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x2, 0x2, 0, 0}, ++ {0x4A, 0xff, 0xff, 1, 1}, ++ {0x4B, 0xc, 0xc, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0x38, 0x38, 0, 0}, ++ {0x4E, 0x70, 0x70, 1, 1}, ++ {0x4F, 0x2, 0x2, 0, 0}, ++ {0x50, 0x88, 0x88, 0, 0}, ++ {0x51, 0xc, 0xc, 0, 0}, ++ {0x52, 0, 0, 0, 0}, ++ {0x53, 0x8, 0x8, 0, 0}, ++ {0x54, 0x70, 0x70, 1, 1}, ++ {0x55, 0x2, 0x2, 0, 0}, ++ {0x56, 0xff, 0xff, 1, 1}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x83, 0x83, 0, 0}, ++ {0x59, 0x77, 0x77, 1, 1}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x88, 0x88, 0, 0}, ++ {0x5D, 0, 0, 0, 0}, ++ {0x5E, 0x8, 0x8, 0, 0}, ++ {0x5F, 0x77, 0x77, 1, 1}, ++ {0x60, 0x1, 0x1, 0, 0}, ++ {0x61, 0, 0, 0, 0}, ++ {0x62, 0x7, 0x7, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0x7, 0x7, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0x74, 0x74, 1, 1}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0xa, 0xa, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0x2, 0x2, 0, 0}, ++ {0x72, 0, 0, 0, 0}, ++ {0x73, 0, 0, 0, 0}, ++ {0x74, 0xe, 0xe, 0, 0}, ++ {0x75, 0xe, 0xe, 0, 0}, ++ {0x76, 0xe, 0xe, 0, 0}, ++ {0x77, 0x13, 0x13, 0, 0}, ++ {0x78, 0x13, 0x13, 0, 0}, ++ {0x79, 0x1b, 0x1b, 0, 0}, ++ {0x7A, 0x1b, 0x1b, 0, 0}, ++ {0x7B, 0x55, 0x55, 0, 0}, ++ {0x7C, 0x5b, 0x5b, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_RX_2056[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0x3, 0x3, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0, 0, 0, 0}, ++ {0x23, 0x90, 0x90, 0, 0}, ++ {0x24, 0x55, 0x55, 0, 0}, ++ {0x25, 0x15, 0x15, 0, 0}, ++ {0x26, 0x5, 0x5, 0, 0}, ++ {0x27, 0x15, 0x15, 0, 0}, ++ {0x28, 0x5, 0x5, 0, 0}, ++ {0x29, 0x20, 0x20, 0, 0}, ++ {0x2A, 0x11, 0x11, 0, 0}, ++ {0x2B, 0x90, 0x90, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0x88, 0x88, 0, 0}, ++ {0x2E, 0x32, 0x32, 0, 0}, ++ {0x2F, 0x77, 0x77, 0, 0}, ++ {0x30, 0x17, 0x17, 1, 1}, ++ {0x31, 0xff, 0xff, 1, 1}, ++ {0x32, 0x20, 0x20, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0x88, 0x88, 0, 0}, ++ {0x35, 0x32, 0x32, 0, 0}, ++ {0x36, 0x77, 0x77, 0, 0}, ++ {0x37, 0x17, 0x17, 1, 1}, ++ {0x38, 0xf0, 0xf0, 1, 1}, ++ {0x39, 0x20, 0x20, 0, 0}, ++ {0x3A, 0x8, 0x8, 0, 0}, ++ {0x3B, 0x99, 0x99, 0, 0}, ++ {0x3C, 0, 0, 0, 0}, ++ {0x3D, 0x44, 0x44, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0x44, 0x44, 0, 0}, ++ {0x40, 0xf, 0xf, 1, 1}, ++ {0x41, 0x6, 0x6, 0, 0}, ++ {0x42, 0x4, 0x4, 0, 0}, ++ {0x43, 0x50, 0x50, 1, 1}, ++ {0x44, 0x8, 0x8, 0, 0}, ++ {0x45, 0x99, 0x99, 0, 0}, ++ {0x46, 0, 0, 0, 0}, ++ {0x47, 0x11, 0x11, 0, 0}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x44, 0x44, 0, 0}, ++ {0x4A, 0x7, 0x7, 0, 0}, ++ {0x4B, 0x6, 0x6, 0, 0}, ++ {0x4C, 0x4, 0x4, 0, 0}, ++ {0x4D, 0, 0, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0x66, 0x66, 0, 0}, ++ {0x50, 0x66, 0x66, 0, 0}, ++ {0x51, 0x57, 0x57, 0, 0}, ++ {0x52, 0x57, 0x57, 0, 0}, ++ {0x53, 0x44, 0x44, 0, 0}, ++ {0x54, 0, 0, 0, 0}, ++ {0x55, 0, 0, 0, 0}, ++ {0x56, 0x8, 0x8, 0, 0}, ++ {0x57, 0x8, 0x8, 0, 0}, ++ {0x58, 0x7, 0x7, 0, 0}, ++ {0x59, 0x22, 0x22, 0, 0}, ++ {0x5A, 0x22, 0x22, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x23, 0x23, 0, 0}, ++ {0x5D, 0x7, 0x7, 0, 0}, ++ {0x5E, 0x55, 0x55, 0, 0}, ++ {0x5F, 0x23, 0x23, 0, 0}, ++ {0x60, 0x41, 0x41, 0, 0}, ++ {0x61, 0x1, 0x1, 0, 0}, ++ {0x62, 0xa, 0xa, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0xc, 0xc, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0, 0, 0, 0}, ++ {0x72, 0x22, 0x22, 0, 0}, ++ {0x73, 0x22, 0x22, 0, 0}, ++ {0x74, 0x2, 0x2, 0, 0}, ++ {0x75, 0xa, 0xa, 0, 0}, ++ {0x76, 0x1, 0x1, 0, 0}, ++ {0x77, 0x22, 0x22, 0, 0}, ++ {0x78, 0x30, 0x30, 0, 0}, ++ {0x79, 0, 0, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_SYN_2056_A1[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0x1, 0x1, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0x60, 0x60, 0, 0}, ++ {0x23, 0x6, 0x6, 0, 0}, ++ {0x24, 0xc, 0xc, 0, 0}, ++ {0x25, 0, 0, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0, 0, 0, 0}, ++ {0x28, 0x1, 0x1, 0, 0}, ++ {0x29, 0, 0, 0, 0}, ++ {0x2A, 0, 0, 0, 0}, ++ {0x2B, 0, 0, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0xd, 0xd, 0, 0}, ++ {0x2F, 0x1f, 0x1f, 0, 0}, ++ {0x30, 0x15, 0x15, 0, 0}, ++ {0x31, 0xf, 0xf, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0, 0, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0, 0, 0, 0}, ++ {0x38, 0, 0, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0, 0, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x13, 0x13, 0, 0}, ++ {0x3D, 0xf, 0xf, 0, 0}, ++ {0x3E, 0x18, 0x18, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x20, 0x20, 0, 0}, ++ {0x42, 0x20, 0x20, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x77, 0x77, 0, 0}, ++ {0x45, 0x7, 0x7, 0, 0}, ++ {0x46, 0x1, 0x1, 0, 0}, ++ {0x47, 0x4, 0x4, 0, 0}, ++ {0x48, 0xf, 0xf, 0, 0}, ++ {0x49, 0x30, 0x30, 0, 0}, ++ {0x4A, 0x32, 0x32, 0, 0}, ++ {0x4B, 0xd, 0xd, 0, 0}, ++ {0x4C, 0xd, 0xd, 0, 0}, ++ {0x4D, 0x4, 0x4, 0, 0}, ++ {0x4E, 0x6, 0x6, 0, 0}, ++ {0x4F, 0x1, 0x1, 0, 0}, ++ {0x50, 0x1c, 0x1c, 0, 0}, ++ {0x51, 0x2, 0x2, 0, 0}, ++ {0x52, 0x2, 0x2, 0, 0}, ++ {0x53, 0xf7, 0xf7, 1, 1}, ++ {0x54, 0xb4, 0xb4, 0, 0}, ++ {0x55, 0xd2, 0xd2, 0, 0}, ++ {0x56, 0, 0, 0, 0}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x4, 0x4, 0, 0}, ++ {0x59, 0x96, 0x96, 0, 0}, ++ {0x5A, 0x3e, 0x3e, 0, 0}, ++ {0x5B, 0x3e, 0x3e, 0, 0}, ++ {0x5C, 0x13, 0x13, 0, 0}, ++ {0x5D, 0x2, 0x2, 0, 0}, ++ {0x5E, 0, 0, 0, 0}, ++ {0x5F, 0x7, 0x7, 0, 0}, ++ {0x60, 0x7, 0x7, 1, 1}, ++ {0x61, 0x8, 0x8, 0, 0}, ++ {0x62, 0x3, 0x3, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0x40, 0x40, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0x1, 0x1, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0x60, 0x60, 0, 0}, ++ {0x71, 0x66, 0x66, 0, 0}, ++ {0x72, 0xc, 0xc, 0, 0}, ++ {0x73, 0x66, 0x66, 0, 0}, ++ {0x74, 0x8f, 0x8f, 1, 1}, ++ {0x75, 0, 0, 0, 0}, ++ {0x76, 0xcc, 0xcc, 0, 0}, ++ {0x77, 0x1, 0x1, 0, 0}, ++ {0x78, 0x66, 0x66, 0, 0}, ++ {0x79, 0x66, 0x66, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0xff, 0xff, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0x95, 0, 0, 0, 0}, ++ {0x96, 0, 0, 0, 0}, ++ {0x97, 0, 0, 0, 0}, ++ {0x98, 0, 0, 0, 0}, ++ {0x99, 0, 0, 0, 0}, ++ {0x9A, 0, 0, 0, 0}, ++ {0x9B, 0, 0, 0, 0}, ++ {0x9C, 0, 0, 0, 0}, ++ {0x9D, 0, 0, 0, 0}, ++ {0x9E, 0, 0, 0, 0}, ++ {0x9F, 0x6, 0x6, 0, 0}, ++ {0xA0, 0x66, 0x66, 0, 0}, ++ {0xA1, 0x66, 0x66, 0, 0}, ++ {0xA2, 0x66, 0x66, 0, 0}, ++ {0xA3, 0x66, 0x66, 0, 0}, ++ {0xA4, 0x66, 0x66, 0, 0}, ++ {0xA5, 0x66, 0x66, 0, 0}, ++ {0xA6, 0x66, 0x66, 0, 0}, ++ {0xA7, 0x66, 0x66, 0, 0}, ++ {0xA8, 0x66, 0x66, 0, 0}, ++ {0xA9, 0x66, 0x66, 0, 0}, ++ {0xAA, 0x66, 0x66, 0, 0}, ++ {0xAB, 0x66, 0x66, 0, 0}, ++ {0xAC, 0x66, 0x66, 0, 0}, ++ {0xAD, 0x66, 0x66, 0, 0}, ++ {0xAE, 0x66, 0x66, 0, 0}, ++ {0xAF, 0x66, 0x66, 0, 0}, ++ {0xB0, 0x66, 0x66, 0, 0}, ++ {0xB1, 0x66, 0x66, 0, 0}, ++ {0xB2, 0x66, 0x66, 0, 0}, ++ {0xB3, 0xa, 0xa, 0, 0}, ++ {0xB4, 0, 0, 0, 0}, ++ {0xB5, 0, 0, 0, 0}, ++ {0xB6, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_TX_2056_A1[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0x88, 0x88, 0, 0}, ++ {0x22, 0x88, 0x88, 0, 0}, ++ {0x23, 0x88, 0x88, 0, 0}, ++ {0x24, 0x88, 0x88, 0, 0}, ++ {0x25, 0xc, 0xc, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0x3, 0x3, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0x3, 0x3, 0, 0}, ++ {0x2A, 0x37, 0x37, 0, 0}, ++ {0x2B, 0x3, 0x3, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0x1, 0x1, 0, 0}, ++ {0x2F, 0x1, 0x1, 0, 0}, ++ {0x30, 0, 0, 0, 0}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0x11, 0x11, 0, 0}, ++ {0x34, 0x11, 0x11, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0x3, 0x3, 0, 0}, ++ {0x38, 0xf, 0xf, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0x2d, 0x2d, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x6e, 0x6e, 0, 0}, ++ {0x3D, 0xf0, 0xf0, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x3, 0x3, 0, 0}, ++ {0x42, 0x3, 0x3, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x1e, 0x1e, 0, 0}, ++ {0x45, 0, 0, 0, 0}, ++ {0x46, 0x6e, 0x6e, 0, 0}, ++ {0x47, 0xf0, 0xf0, 1, 1}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x2, 0x2, 0, 0}, ++ {0x4A, 0xff, 0xff, 1, 1}, ++ {0x4B, 0xc, 0xc, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0x38, 0x38, 0, 0}, ++ {0x4E, 0x70, 0x70, 1, 1}, ++ {0x4F, 0x2, 0x2, 0, 0}, ++ {0x50, 0x88, 0x88, 0, 0}, ++ {0x51, 0xc, 0xc, 0, 0}, ++ {0x52, 0, 0, 0, 0}, ++ {0x53, 0x8, 0x8, 0, 0}, ++ {0x54, 0x70, 0x70, 1, 1}, ++ {0x55, 0x2, 0x2, 0, 0}, ++ {0x56, 0xff, 0xff, 1, 1}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x83, 0x83, 0, 0}, ++ {0x59, 0x77, 0x77, 1, 1}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x88, 0x88, 0, 0}, ++ {0x5D, 0, 0, 0, 0}, ++ {0x5E, 0x8, 0x8, 0, 0}, ++ {0x5F, 0x77, 0x77, 1, 1}, ++ {0x60, 0x1, 0x1, 0, 0}, ++ {0x61, 0, 0, 0, 0}, ++ {0x62, 0x7, 0x7, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0x7, 0x7, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0x72, 0x72, 1, 1}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0xa, 0xa, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0x2, 0x2, 0, 0}, ++ {0x72, 0, 0, 0, 0}, ++ {0x73, 0, 0, 0, 0}, ++ {0x74, 0xe, 0xe, 0, 0}, ++ {0x75, 0xe, 0xe, 0, 0}, ++ {0x76, 0xe, 0xe, 0, 0}, ++ {0x77, 0x13, 0x13, 0, 0}, ++ {0x78, 0x13, 0x13, 0, 0}, ++ {0x79, 0x1b, 0x1b, 0, 0}, ++ {0x7A, 0x1b, 0x1b, 0, 0}, ++ {0x7B, 0x55, 0x55, 0, 0}, ++ {0x7C, 0x5b, 0x5b, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_RX_2056_A1[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0x3, 0x3, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0, 0, 0, 0}, ++ {0x23, 0x90, 0x90, 0, 0}, ++ {0x24, 0x55, 0x55, 0, 0}, ++ {0x25, 0x15, 0x15, 0, 0}, ++ {0x26, 0x5, 0x5, 0, 0}, ++ {0x27, 0x15, 0x15, 0, 0}, ++ {0x28, 0x5, 0x5, 0, 0}, ++ {0x29, 0x20, 0x20, 0, 0}, ++ {0x2A, 0x11, 0x11, 0, 0}, ++ {0x2B, 0x90, 0x90, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0x88, 0x88, 0, 0}, ++ {0x2E, 0x32, 0x32, 0, 0}, ++ {0x2F, 0x77, 0x77, 0, 0}, ++ {0x30, 0x17, 0x17, 1, 1}, ++ {0x31, 0xff, 0xff, 1, 1}, ++ {0x32, 0x20, 0x20, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0x88, 0x88, 0, 0}, ++ {0x35, 0x32, 0x32, 0, 0}, ++ {0x36, 0x77, 0x77, 0, 0}, ++ {0x37, 0x17, 0x17, 1, 1}, ++ {0x38, 0xf0, 0xf0, 1, 1}, ++ {0x39, 0x20, 0x20, 0, 0}, ++ {0x3A, 0x8, 0x8, 0, 0}, ++ {0x3B, 0x55, 0x55, 1, 1}, ++ {0x3C, 0, 0, 0, 0}, ++ {0x3D, 0x44, 0x44, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0x44, 0x44, 0, 0}, ++ {0x40, 0xf, 0xf, 1, 1}, ++ {0x41, 0x6, 0x6, 0, 0}, ++ {0x42, 0x4, 0x4, 0, 0}, ++ {0x43, 0x50, 0x50, 1, 1}, ++ {0x44, 0x8, 0x8, 0, 0}, ++ {0x45, 0x55, 0x55, 1, 1}, ++ {0x46, 0, 0, 0, 0}, ++ {0x47, 0x11, 0x11, 0, 0}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x44, 0x44, 0, 0}, ++ {0x4A, 0x7, 0x7, 0, 0}, ++ {0x4B, 0x6, 0x6, 0, 0}, ++ {0x4C, 0x4, 0x4, 0, 0}, ++ {0x4D, 0, 0, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0x26, 0x26, 1, 1}, ++ {0x50, 0x26, 0x26, 1, 1}, ++ {0x51, 0xf, 0xf, 1, 1}, ++ {0x52, 0xf, 0xf, 1, 1}, ++ {0x53, 0x44, 0x44, 0, 0}, ++ {0x54, 0, 0, 0, 0}, ++ {0x55, 0, 0, 0, 0}, ++ {0x56, 0x8, 0x8, 0, 0}, ++ {0x57, 0x8, 0x8, 0, 0}, ++ {0x58, 0x7, 0x7, 0, 0}, ++ {0x59, 0x22, 0x22, 0, 0}, ++ {0x5A, 0x22, 0x22, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x2f, 0x2f, 1, 1}, ++ {0x5D, 0x7, 0x7, 0, 0}, ++ {0x5E, 0x55, 0x55, 0, 0}, ++ {0x5F, 0x23, 0x23, 0, 0}, ++ {0x60, 0x41, 0x41, 0, 0}, ++ {0x61, 0x1, 0x1, 0, 0}, ++ {0x62, 0xa, 0xa, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0xc, 0xc, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0, 0, 0, 0}, ++ {0x72, 0x22, 0x22, 0, 0}, ++ {0x73, 0x22, 0x22, 0, 0}, ++ {0x74, 0, 0, 1, 1}, ++ {0x75, 0xa, 0xa, 0, 0}, ++ {0x76, 0x1, 0x1, 0, 0}, ++ {0x77, 0x22, 0x22, 0, 0}, ++ {0x78, 0x30, 0x30, 0, 0}, ++ {0x79, 0, 0, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_SYN_2056_rev5[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0x1, 0x1, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0x60, 0x60, 0, 0}, ++ {0x23, 0x6, 0x6, 0, 0}, ++ {0x24, 0xc, 0xc, 0, 0}, ++ {0x25, 0, 0, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0, 0, 0, 0}, ++ {0x28, 0x1, 0x1, 0, 0}, ++ {0x29, 0, 0, 0, 0}, ++ {0x2A, 0, 0, 0, 0}, ++ {0x2B, 0, 0, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0, 0, 0, 0}, ++ {0x2F, 0x1f, 0x1f, 0, 0}, ++ {0x30, 0x15, 0x15, 0, 0}, ++ {0x31, 0xf, 0xf, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0, 0, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0, 0, 0, 0}, ++ {0x38, 0, 0, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0, 0, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x13, 0x13, 0, 0}, ++ {0x3D, 0xf, 0xf, 0, 0}, ++ {0x3E, 0x18, 0x18, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x20, 0x20, 0, 0}, ++ {0x42, 0x20, 0x20, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x77, 0x77, 0, 0}, ++ {0x45, 0x7, 0x7, 0, 0}, ++ {0x46, 0x1, 0x1, 0, 0}, ++ {0x47, 0x4, 0x4, 0, 0}, ++ {0x48, 0xf, 0xf, 0, 0}, ++ {0x49, 0x30, 0x30, 0, 0}, ++ {0x4A, 0x32, 0x32, 0, 0}, ++ {0x4B, 0xd, 0xd, 0, 0}, ++ {0x4C, 0xd, 0xd, 0, 0}, ++ {0x4D, 0x4, 0x4, 0, 0}, ++ {0x4E, 0x6, 0x6, 0, 0}, ++ {0x4F, 0x1, 0x1, 0, 0}, ++ {0x50, 0x1c, 0x1c, 0, 0}, ++ {0x51, 0x2, 0x2, 0, 0}, ++ {0x52, 0x2, 0x2, 0, 0}, ++ {0x53, 0xf7, 0xf7, 1, 1}, ++ {0x54, 0xb4, 0xb4, 0, 0}, ++ {0x55, 0xd2, 0xd2, 0, 0}, ++ {0x56, 0, 0, 0, 0}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x4, 0x4, 0, 0}, ++ {0x59, 0x96, 0x96, 0, 0}, ++ {0x5A, 0x3e, 0x3e, 0, 0}, ++ {0x5B, 0x3e, 0x3e, 0, 0}, ++ {0x5C, 0x13, 0x13, 0, 0}, ++ {0x5D, 0x2, 0x2, 0, 0}, ++ {0x5E, 0, 0, 0, 0}, ++ {0x5F, 0x7, 0x7, 0, 0}, ++ {0x60, 0x7, 0x7, 1, 1}, ++ {0x61, 0x8, 0x8, 0, 0}, ++ {0x62, 0x3, 0x3, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0x40, 0x40, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0x1, 0x1, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0x60, 0x60, 0, 0}, ++ {0x71, 0x66, 0x66, 0, 0}, ++ {0x72, 0xc, 0xc, 0, 0}, ++ {0x73, 0x66, 0x66, 0, 0}, ++ {0x74, 0x8f, 0x8f, 1, 1}, ++ {0x75, 0, 0, 0, 0}, ++ {0x76, 0xcc, 0xcc, 0, 0}, ++ {0x77, 0x1, 0x1, 0, 0}, ++ {0x78, 0x66, 0x66, 0, 0}, ++ {0x79, 0x66, 0x66, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0xff, 0xff, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0x95, 0, 0, 0, 0}, ++ {0x96, 0, 0, 0, 0}, ++ {0x97, 0, 0, 0, 0}, ++ {0x98, 0, 0, 0, 0}, ++ {0x99, 0, 0, 0, 0}, ++ {0x9A, 0, 0, 0, 0}, ++ {0x9B, 0, 0, 0, 0}, ++ {0x9C, 0, 0, 0, 0}, ++ {0x9D, 0, 0, 0, 0}, ++ {0x9E, 0, 0, 0, 0}, ++ {0x9F, 0x6, 0x6, 0, 0}, ++ {0xA0, 0x66, 0x66, 0, 0}, ++ {0xA1, 0x66, 0x66, 0, 0}, ++ {0xA2, 0x66, 0x66, 0, 0}, ++ {0xA3, 0x66, 0x66, 0, 0}, ++ {0xA4, 0x66, 0x66, 0, 0}, ++ {0xA5, 0x66, 0x66, 0, 0}, ++ {0xA6, 0x66, 0x66, 0, 0}, ++ {0xA7, 0x66, 0x66, 0, 0}, ++ {0xA8, 0x66, 0x66, 0, 0}, ++ {0xA9, 0x66, 0x66, 0, 0}, ++ {0xAA, 0x66, 0x66, 0, 0}, ++ {0xAB, 0x66, 0x66, 0, 0}, ++ {0xAC, 0x66, 0x66, 0, 0}, ++ {0xAD, 0x66, 0x66, 0, 0}, ++ {0xAE, 0x66, 0x66, 0, 0}, ++ {0xAF, 0x66, 0x66, 0, 0}, ++ {0xB0, 0x66, 0x66, 0, 0}, ++ {0xB1, 0x66, 0x66, 0, 0}, ++ {0xB2, 0x66, 0x66, 0, 0}, ++ {0xB3, 0xa, 0xa, 0, 0}, ++ {0xB4, 0, 0, 0, 0}, ++ {0xB5, 0, 0, 0, 0}, ++ {0xB6, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_TX_2056_rev5[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0x88, 0x88, 0, 0}, ++ {0x22, 0x88, 0x88, 0, 0}, ++ {0x23, 0x88, 0x88, 0, 0}, ++ {0x24, 0x88, 0x88, 0, 0}, ++ {0x25, 0xc, 0xc, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0x3, 0x3, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0x3, 0x3, 0, 0}, ++ {0x2A, 0x37, 0x37, 0, 0}, ++ {0x2B, 0x3, 0x3, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0x1, 0x1, 0, 0}, ++ {0x2F, 0x1, 0x1, 0, 0}, ++ {0x30, 0, 0, 0, 0}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0x11, 0x11, 0, 0}, ++ {0x34, 0x11, 0x11, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0x3, 0x3, 0, 0}, ++ {0x38, 0xf, 0xf, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0x2d, 0x2d, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x6e, 0x6e, 0, 0}, ++ {0x3D, 0xf0, 0xf0, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x3, 0x3, 0, 0}, ++ {0x42, 0x3, 0x3, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x1e, 0x1e, 0, 0}, ++ {0x45, 0, 0, 0, 0}, ++ {0x46, 0x6e, 0x6e, 0, 0}, ++ {0x47, 0xf0, 0xf0, 1, 1}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x2, 0x2, 0, 0}, ++ {0x4A, 0xff, 0xff, 1, 1}, ++ {0x4B, 0xc, 0xc, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0x38, 0x38, 0, 0}, ++ {0x4E, 0x70, 0x70, 1, 1}, ++ {0x4F, 0x2, 0x2, 0, 0}, ++ {0x50, 0x88, 0x88, 0, 0}, ++ {0x51, 0xc, 0xc, 0, 0}, ++ {0x52, 0, 0, 0, 0}, ++ {0x53, 0x8, 0x8, 0, 0}, ++ {0x54, 0x70, 0x70, 1, 1}, ++ {0x55, 0x2, 0x2, 0, 0}, ++ {0x56, 0xff, 0xff, 1, 1}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x83, 0x83, 0, 0}, ++ {0x59, 0x77, 0x77, 1, 1}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x88, 0x88, 0, 0}, ++ {0x5D, 0, 0, 0, 0}, ++ {0x5E, 0x8, 0x8, 0, 0}, ++ {0x5F, 0x77, 0x77, 1, 1}, ++ {0x60, 0x1, 0x1, 0, 0}, ++ {0x61, 0, 0, 0, 0}, ++ {0x62, 0x7, 0x7, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0x7, 0x7, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 1, 1}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0xa, 0xa, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0x2, 0x2, 0, 0}, ++ {0x72, 0, 0, 0, 0}, ++ {0x73, 0, 0, 0, 0}, ++ {0x74, 0xe, 0xe, 0, 0}, ++ {0x75, 0xe, 0xe, 0, 0}, ++ {0x76, 0xe, 0xe, 0, 0}, ++ {0x77, 0x13, 0x13, 0, 0}, ++ {0x78, 0x13, 0x13, 0, 0}, ++ {0x79, 0x1b, 0x1b, 0, 0}, ++ {0x7A, 0x1b, 0x1b, 0, 0}, ++ {0x7B, 0x55, 0x55, 0, 0}, ++ {0x7C, 0x5b, 0x5b, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0x70, 0x70, 0, 0}, ++ {0x94, 0x70, 0x70, 0, 0}, ++ {0x95, 0x71, 0x71, 1, 1}, ++ {0x96, 0x71, 0x71, 1, 1}, ++ {0x97, 0x72, 0x72, 1, 1}, ++ {0x98, 0x73, 0x73, 1, 1}, ++ {0x99, 0x74, 0x74, 1, 1}, ++ {0x9A, 0x75, 0x75, 1, 1}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_RX_2056_rev5[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0x3, 0x3, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0, 0, 0, 0}, ++ {0x23, 0x90, 0x90, 0, 0}, ++ {0x24, 0x55, 0x55, 0, 0}, ++ {0x25, 0x15, 0x15, 0, 0}, ++ {0x26, 0x5, 0x5, 0, 0}, ++ {0x27, 0x15, 0x15, 0, 0}, ++ {0x28, 0x5, 0x5, 0, 0}, ++ {0x29, 0x20, 0x20, 0, 0}, ++ {0x2A, 0x11, 0x11, 0, 0}, ++ {0x2B, 0x90, 0x90, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0x88, 0x88, 0, 0}, ++ {0x2E, 0x32, 0x32, 0, 0}, ++ {0x2F, 0x77, 0x77, 0, 0}, ++ {0x30, 0x17, 0x17, 1, 1}, ++ {0x31, 0xff, 0xff, 1, 1}, ++ {0x32, 0x20, 0x20, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0x88, 0x88, 0, 0}, ++ {0x35, 0x32, 0x32, 0, 0}, ++ {0x36, 0x77, 0x77, 0, 0}, ++ {0x37, 0x17, 0x17, 1, 1}, ++ {0x38, 0xf0, 0xf0, 1, 1}, ++ {0x39, 0x20, 0x20, 0, 0}, ++ {0x3A, 0x8, 0x8, 0, 0}, ++ {0x3B, 0x55, 0x55, 1, 1}, ++ {0x3C, 0, 0, 0, 0}, ++ {0x3D, 0x88, 0x88, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 1, 1}, ++ {0x40, 0x7, 0x7, 1, 1}, ++ {0x41, 0x6, 0x6, 0, 0}, ++ {0x42, 0x4, 0x4, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x8, 0x8, 0, 0}, ++ {0x45, 0x55, 0x55, 1, 1}, ++ {0x46, 0, 0, 0, 0}, ++ {0x47, 0x11, 0x11, 0, 0}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0, 0, 1, 1}, ++ {0x4A, 0x7, 0x7, 0, 0}, ++ {0x4B, 0x6, 0x6, 0, 0}, ++ {0x4C, 0x4, 0x4, 0, 0}, ++ {0x4D, 0, 0, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0x26, 0x26, 1, 1}, ++ {0x50, 0x26, 0x26, 1, 1}, ++ {0x51, 0xf, 0xf, 1, 1}, ++ {0x52, 0xf, 0xf, 1, 1}, ++ {0x53, 0x44, 0x44, 0, 0}, ++ {0x54, 0, 0, 0, 0}, ++ {0x55, 0, 0, 0, 0}, ++ {0x56, 0x8, 0x8, 0, 0}, ++ {0x57, 0x8, 0x8, 0, 0}, ++ {0x58, 0x7, 0x7, 0, 0}, ++ {0x59, 0x22, 0x22, 0, 0}, ++ {0x5A, 0x22, 0x22, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x4, 0x4, 1, 1}, ++ {0x5D, 0x7, 0x7, 0, 0}, ++ {0x5E, 0x55, 0x55, 0, 0}, ++ {0x5F, 0x23, 0x23, 0, 0}, ++ {0x60, 0x41, 0x41, 0, 0}, ++ {0x61, 0x1, 0x1, 0, 0}, ++ {0x62, 0xa, 0xa, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0xc, 0xc, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0, 0, 0, 0}, ++ {0x72, 0x22, 0x22, 0, 0}, ++ {0x73, 0x22, 0x22, 0, 0}, ++ {0x74, 0, 0, 1, 1}, ++ {0x75, 0xa, 0xa, 0, 0}, ++ {0x76, 0x1, 0x1, 0, 0}, ++ {0x77, 0x22, 0x22, 0, 0}, ++ {0x78, 0x30, 0x30, 0, 0}, ++ {0x79, 0, 0, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_SYN_2056_rev6[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0x1, 0x1, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0x60, 0x60, 0, 0}, ++ {0x23, 0x6, 0x6, 0, 0}, ++ {0x24, 0xc, 0xc, 0, 0}, ++ {0x25, 0, 0, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0, 0, 0, 0}, ++ {0x28, 0x1, 0x1, 0, 0}, ++ {0x29, 0, 0, 0, 0}, ++ {0x2A, 0, 0, 0, 0}, ++ {0x2B, 0, 0, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0, 0, 0, 0}, ++ {0x2F, 0x1f, 0x1f, 0, 0}, ++ {0x30, 0x15, 0x15, 0, 0}, ++ {0x31, 0xf, 0xf, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0, 0, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0, 0, 0, 0}, ++ {0x38, 0, 0, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0, 0, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x13, 0x13, 0, 0}, ++ {0x3D, 0xf, 0xf, 0, 0}, ++ {0x3E, 0x18, 0x18, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x20, 0x20, 0, 0}, ++ {0x42, 0x20, 0x20, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x77, 0x77, 0, 0}, ++ {0x45, 0x7, 0x7, 0, 0}, ++ {0x46, 0x1, 0x1, 0, 0}, ++ {0x47, 0x4, 0x4, 0, 0}, ++ {0x48, 0xf, 0xf, 0, 0}, ++ {0x49, 0x30, 0x30, 0, 0}, ++ {0x4A, 0x32, 0x32, 0, 0}, ++ {0x4B, 0xd, 0xd, 0, 0}, ++ {0x4C, 0xd, 0xd, 0, 0}, ++ {0x4D, 0x4, 0x4, 0, 0}, ++ {0x4E, 0x6, 0x6, 0, 0}, ++ {0x4F, 0x1, 0x1, 0, 0}, ++ {0x50, 0x1c, 0x1c, 0, 0}, ++ {0x51, 0x2, 0x2, 0, 0}, ++ {0x52, 0x2, 0x2, 0, 0}, ++ {0x53, 0xf7, 0xf7, 1, 1}, ++ {0x54, 0xb4, 0xb4, 0, 0}, ++ {0x55, 0xd2, 0xd2, 0, 0}, ++ {0x56, 0, 0, 0, 0}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x4, 0x4, 0, 0}, ++ {0x59, 0x96, 0x96, 0, 0}, ++ {0x5A, 0x3e, 0x3e, 0, 0}, ++ {0x5B, 0x3e, 0x3e, 0, 0}, ++ {0x5C, 0x13, 0x13, 0, 0}, ++ {0x5D, 0x2, 0x2, 0, 0}, ++ {0x5E, 0, 0, 0, 0}, ++ {0x5F, 0x7, 0x7, 0, 0}, ++ {0x60, 0x7, 0x7, 1, 1}, ++ {0x61, 0x8, 0x8, 0, 0}, ++ {0x62, 0x3, 0x3, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0x40, 0x40, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0x1, 0x1, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0x60, 0x60, 0, 0}, ++ {0x71, 0x66, 0x66, 0, 0}, ++ {0x72, 0xc, 0xc, 0, 0}, ++ {0x73, 0x66, 0x66, 0, 0}, ++ {0x74, 0x8f, 0x8f, 1, 1}, ++ {0x75, 0, 0, 0, 0}, ++ {0x76, 0xcc, 0xcc, 0, 0}, ++ {0x77, 0x1, 0x1, 0, 0}, ++ {0x78, 0x66, 0x66, 0, 0}, ++ {0x79, 0x66, 0x66, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0xff, 0xff, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0x95, 0, 0, 0, 0}, ++ {0x96, 0, 0, 0, 0}, ++ {0x97, 0, 0, 0, 0}, ++ {0x98, 0, 0, 0, 0}, ++ {0x99, 0, 0, 0, 0}, ++ {0x9A, 0, 0, 0, 0}, ++ {0x9B, 0, 0, 0, 0}, ++ {0x9C, 0, 0, 0, 0}, ++ {0x9D, 0, 0, 0, 0}, ++ {0x9E, 0, 0, 0, 0}, ++ {0x9F, 0x6, 0x6, 0, 0}, ++ {0xA0, 0x66, 0x66, 0, 0}, ++ {0xA1, 0x66, 0x66, 0, 0}, ++ {0xA2, 0x66, 0x66, 0, 0}, ++ {0xA3, 0x66, 0x66, 0, 0}, ++ {0xA4, 0x66, 0x66, 0, 0}, ++ {0xA5, 0x66, 0x66, 0, 0}, ++ {0xA6, 0x66, 0x66, 0, 0}, ++ {0xA7, 0x66, 0x66, 0, 0}, ++ {0xA8, 0x66, 0x66, 0, 0}, ++ {0xA9, 0x66, 0x66, 0, 0}, ++ {0xAA, 0x66, 0x66, 0, 0}, ++ {0xAB, 0x66, 0x66, 0, 0}, ++ {0xAC, 0x66, 0x66, 0, 0}, ++ {0xAD, 0x66, 0x66, 0, 0}, ++ {0xAE, 0x66, 0x66, 0, 0}, ++ {0xAF, 0x66, 0x66, 0, 0}, ++ {0xB0, 0x66, 0x66, 0, 0}, ++ {0xB1, 0x66, 0x66, 0, 0}, ++ {0xB2, 0x66, 0x66, 0, 0}, ++ {0xB3, 0xa, 0xa, 0, 0}, ++ {0xB4, 0, 0, 0, 0}, ++ {0xB5, 0, 0, 0, 0}, ++ {0xB6, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_TX_2056_rev6[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0x88, 0x88, 0, 0}, ++ {0x22, 0x88, 0x88, 0, 0}, ++ {0x23, 0x88, 0x88, 0, 0}, ++ {0x24, 0x88, 0x88, 0, 0}, ++ {0x25, 0xc, 0xc, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0x3, 0x3, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0x3, 0x3, 0, 0}, ++ {0x2A, 0x37, 0x37, 0, 0}, ++ {0x2B, 0x3, 0x3, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0x1, 0x1, 0, 0}, ++ {0x2F, 0x1, 0x1, 0, 0}, ++ {0x30, 0, 0, 0, 0}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0x11, 0x11, 0, 0}, ++ {0x34, 0xee, 0xee, 1, 1}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0x3, 0x3, 0, 0}, ++ {0x38, 0x50, 0x50, 1, 1}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0x50, 0x50, 1, 1}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x6e, 0x6e, 0, 0}, ++ {0x3D, 0xf0, 0xf0, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x3, 0x3, 0, 0}, ++ {0x42, 0x3, 0x3, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x1e, 0x1e, 0, 0}, ++ {0x45, 0, 0, 0, 0}, ++ {0x46, 0x6e, 0x6e, 0, 0}, ++ {0x47, 0xf0, 0xf0, 1, 1}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x2, 0x2, 0, 0}, ++ {0x4A, 0xff, 0xff, 1, 1}, ++ {0x4B, 0xc, 0xc, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0x38, 0x38, 0, 0}, ++ {0x4E, 0x70, 0x70, 1, 1}, ++ {0x4F, 0x2, 0x2, 0, 0}, ++ {0x50, 0x88, 0x88, 0, 0}, ++ {0x51, 0xc, 0xc, 0, 0}, ++ {0x52, 0, 0, 0, 0}, ++ {0x53, 0x8, 0x8, 0, 0}, ++ {0x54, 0x70, 0x70, 1, 1}, ++ {0x55, 0x2, 0x2, 0, 0}, ++ {0x56, 0xff, 0xff, 1, 1}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x83, 0x83, 0, 0}, ++ {0x59, 0x77, 0x77, 1, 1}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x88, 0x88, 0, 0}, ++ {0x5D, 0, 0, 0, 0}, ++ {0x5E, 0x8, 0x8, 0, 0}, ++ {0x5F, 0x77, 0x77, 1, 1}, ++ {0x60, 0x1, 0x1, 0, 0}, ++ {0x61, 0, 0, 0, 0}, ++ {0x62, 0x7, 0x7, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0x7, 0x7, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 1, 1}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0xa, 0xa, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0x2, 0x2, 0, 0}, ++ {0x72, 0, 0, 0, 0}, ++ {0x73, 0, 0, 0, 0}, ++ {0x74, 0xe, 0xe, 0, 0}, ++ {0x75, 0xe, 0xe, 0, 0}, ++ {0x76, 0xe, 0xe, 0, 0}, ++ {0x77, 0x13, 0x13, 0, 0}, ++ {0x78, 0x13, 0x13, 0, 0}, ++ {0x79, 0x1b, 0x1b, 0, 0}, ++ {0x7A, 0x1b, 0x1b, 0, 0}, ++ {0x7B, 0x55, 0x55, 0, 0}, ++ {0x7C, 0x5b, 0x5b, 0, 0}, ++ {0x7D, 0x30, 0x30, 1, 1}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0x70, 0x70, 0, 0}, ++ {0x94, 0x70, 0x70, 0, 0}, ++ {0x95, 0x70, 0x70, 0, 0}, ++ {0x96, 0x70, 0x70, 0, 0}, ++ {0x97, 0x70, 0x70, 0, 0}, ++ {0x98, 0x70, 0x70, 0, 0}, ++ {0x99, 0x70, 0x70, 0, 0}, ++ {0x9A, 0x70, 0x70, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_RX_2056_rev6[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0x3, 0x3, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0, 0, 0, 0}, ++ {0x23, 0x90, 0x90, 0, 0}, ++ {0x24, 0x55, 0x55, 0, 0}, ++ {0x25, 0x15, 0x15, 0, 0}, ++ {0x26, 0x5, 0x5, 0, 0}, ++ {0x27, 0x15, 0x15, 0, 0}, ++ {0x28, 0x5, 0x5, 0, 0}, ++ {0x29, 0x20, 0x20, 0, 0}, ++ {0x2A, 0x11, 0x11, 0, 0}, ++ {0x2B, 0x90, 0x90, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0x88, 0x88, 0, 0}, ++ {0x2E, 0x32, 0x32, 0, 0}, ++ {0x2F, 0x77, 0x77, 0, 0}, ++ {0x30, 0x17, 0x17, 1, 1}, ++ {0x31, 0xff, 0xff, 1, 1}, ++ {0x32, 0x20, 0x20, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0x88, 0x88, 0, 0}, ++ {0x35, 0x32, 0x32, 0, 0}, ++ {0x36, 0x77, 0x77, 0, 0}, ++ {0x37, 0x17, 0x17, 1, 1}, ++ {0x38, 0xf0, 0xf0, 1, 1}, ++ {0x39, 0x20, 0x20, 0, 0}, ++ {0x3A, 0x8, 0x8, 0, 0}, ++ {0x3B, 0x55, 0x55, 1, 1}, ++ {0x3C, 0, 0, 0, 0}, ++ {0x3D, 0x88, 0x88, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0x44, 0x44, 0, 0}, ++ {0x40, 0x7, 0x7, 1, 1}, ++ {0x41, 0x6, 0x6, 0, 0}, ++ {0x42, 0x4, 0x4, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x8, 0x8, 0, 0}, ++ {0x45, 0x55, 0x55, 1, 1}, ++ {0x46, 0, 0, 0, 0}, ++ {0x47, 0x11, 0x11, 0, 0}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x44, 0x44, 0, 0}, ++ {0x4A, 0x7, 0x7, 0, 0}, ++ {0x4B, 0x6, 0x6, 0, 0}, ++ {0x4C, 0x4, 0x4, 0, 0}, ++ {0x4D, 0, 0, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0x26, 0x26, 1, 1}, ++ {0x50, 0x26, 0x26, 1, 1}, ++ {0x51, 0xf, 0xf, 1, 1}, ++ {0x52, 0xf, 0xf, 1, 1}, ++ {0x53, 0x44, 0x44, 0, 0}, ++ {0x54, 0, 0, 0, 0}, ++ {0x55, 0, 0, 0, 0}, ++ {0x56, 0x8, 0x8, 0, 0}, ++ {0x57, 0x8, 0x8, 0, 0}, ++ {0x58, 0x7, 0x7, 0, 0}, ++ {0x59, 0x22, 0x22, 0, 0}, ++ {0x5A, 0x22, 0x22, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x4, 0x4, 1, 1}, ++ {0x5D, 0x7, 0x7, 0, 0}, ++ {0x5E, 0x55, 0x55, 0, 0}, ++ {0x5F, 0x23, 0x23, 0, 0}, ++ {0x60, 0x41, 0x41, 0, 0}, ++ {0x61, 0x1, 0x1, 0, 0}, ++ {0x62, 0xa, 0xa, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0xc, 0xc, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0, 0, 0, 0}, ++ {0x72, 0x22, 0x22, 0, 0}, ++ {0x73, 0x22, 0x22, 0, 0}, ++ {0x74, 0, 0, 1, 1}, ++ {0x75, 0xa, 0xa, 0, 0}, ++ {0x76, 0x1, 0x1, 0, 0}, ++ {0x77, 0x22, 0x22, 0, 0}, ++ {0x78, 0x30, 0x30, 0, 0}, ++ {0x79, 0, 0, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0x5, 0x5, 1, 1}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_SYN_2056_rev7[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0x1, 0x1, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0x60, 0x60, 0, 0}, ++ {0x23, 0x6, 0x6, 0, 0}, ++ {0x24, 0xc, 0xc, 0, 0}, ++ {0x25, 0, 0, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0, 0, 0, 0}, ++ {0x28, 0x1, 0x1, 0, 0}, ++ {0x29, 0, 0, 0, 0}, ++ {0x2A, 0, 0, 0, 0}, ++ {0x2B, 0, 0, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0, 0, 0, 0}, ++ {0x2F, 0x1f, 0x1f, 0, 0}, ++ {0x30, 0x15, 0x15, 0, 0}, ++ {0x31, 0xf, 0xf, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0, 0, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0, 0, 0, 0}, ++ {0x38, 0, 0, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0, 0, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x13, 0x13, 0, 0}, ++ {0x3D, 0xf, 0xf, 0, 0}, ++ {0x3E, 0x18, 0x18, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x20, 0x20, 0, 0}, ++ {0x42, 0x20, 0x20, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x77, 0x77, 0, 0}, ++ {0x45, 0x7, 0x7, 0, 0}, ++ {0x46, 0x1, 0x1, 0, 0}, ++ {0x47, 0x4, 0x4, 0, 0}, ++ {0x48, 0xf, 0xf, 0, 0}, ++ {0x49, 0x30, 0x30, 0, 0}, ++ {0x4A, 0x32, 0x32, 0, 0}, ++ {0x4B, 0xd, 0xd, 0, 0}, ++ {0x4C, 0xd, 0xd, 0, 0}, ++ {0x4D, 0x4, 0x4, 0, 0}, ++ {0x4E, 0x6, 0x6, 0, 0}, ++ {0x4F, 0x1, 0x1, 0, 0}, ++ {0x50, 0x1c, 0x1c, 0, 0}, ++ {0x51, 0x2, 0x2, 0, 0}, ++ {0x52, 0x2, 0x2, 0, 0}, ++ {0x53, 0xf7, 0xf7, 1, 1}, ++ {0x54, 0xb4, 0xb4, 0, 0}, ++ {0x55, 0xd2, 0xd2, 0, 0}, ++ {0x56, 0, 0, 0, 0}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x4, 0x4, 0, 0}, ++ {0x59, 0x96, 0x96, 0, 0}, ++ {0x5A, 0x3e, 0x3e, 0, 0}, ++ {0x5B, 0x3e, 0x3e, 0, 0}, ++ {0x5C, 0x13, 0x13, 0, 0}, ++ {0x5D, 0x2, 0x2, 0, 0}, ++ {0x5E, 0, 0, 0, 0}, ++ {0x5F, 0x7, 0x7, 0, 0}, ++ {0x60, 0x7, 0x7, 1, 1}, ++ {0x61, 0x8, 0x8, 0, 0}, ++ {0x62, 0x3, 0x3, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0x40, 0x40, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0x1, 0x1, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0x60, 0x60, 0, 0}, ++ {0x71, 0x66, 0x66, 0, 0}, ++ {0x72, 0xc, 0xc, 0, 0}, ++ {0x73, 0x66, 0x66, 0, 0}, ++ {0x74, 0x8f, 0x8f, 1, 1}, ++ {0x75, 0, 0, 0, 0}, ++ {0x76, 0xcc, 0xcc, 0, 0}, ++ {0x77, 0x1, 0x1, 0, 0}, ++ {0x78, 0x66, 0x66, 0, 0}, ++ {0x79, 0x66, 0x66, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0xff, 0xff, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0x95, 0, 0, 0, 0}, ++ {0x96, 0, 0, 0, 0}, ++ {0x97, 0, 0, 0, 0}, ++ {0x98, 0, 0, 0, 0}, ++ {0x99, 0, 0, 0, 0}, ++ {0x9A, 0, 0, 0, 0}, ++ {0x9B, 0, 0, 0, 0}, ++ {0x9C, 0, 0, 0, 0}, ++ {0x9D, 0, 0, 0, 0}, ++ {0x9E, 0, 0, 0, 0}, ++ {0x9F, 0x6, 0x6, 0, 0}, ++ {0xA0, 0x66, 0x66, 0, 0}, ++ {0xA1, 0x66, 0x66, 0, 0}, ++ {0xA2, 0x66, 0x66, 0, 0}, ++ {0xA3, 0x66, 0x66, 0, 0}, ++ {0xA4, 0x66, 0x66, 0, 0}, ++ {0xA5, 0x66, 0x66, 0, 0}, ++ {0xA6, 0x66, 0x66, 0, 0}, ++ {0xA7, 0x66, 0x66, 0, 0}, ++ {0xA8, 0x66, 0x66, 0, 0}, ++ {0xA9, 0x66, 0x66, 0, 0}, ++ {0xAA, 0x66, 0x66, 0, 0}, ++ {0xAB, 0x66, 0x66, 0, 0}, ++ {0xAC, 0x66, 0x66, 0, 0}, ++ {0xAD, 0x66, 0x66, 0, 0}, ++ {0xAE, 0x66, 0x66, 0, 0}, ++ {0xAF, 0x66, 0x66, 0, 0}, ++ {0xB0, 0x66, 0x66, 0, 0}, ++ {0xB1, 0x66, 0x66, 0, 0}, ++ {0xB2, 0x66, 0x66, 0, 0}, ++ {0xB3, 0xa, 0xa, 0, 0}, ++ {0xB4, 0, 0, 0, 0}, ++ {0xB5, 0, 0, 0, 0}, ++ {0xB6, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static struct radio_regs regs_TX_2056_rev7[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0x88, 0x88, 0, 0}, ++ {0x22, 0x88, 0x88, 0, 0}, ++ {0x23, 0x88, 0x88, 0, 0}, ++ {0x24, 0x88, 0x88, 0, 0}, ++ {0x25, 0xc, 0xc, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0x3, 0x3, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0x3, 0x3, 0, 0}, ++ {0x2A, 0x37, 0x37, 0, 0}, ++ {0x2B, 0x3, 0x3, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0x1, 0x1, 0, 0}, ++ {0x2F, 0x1, 0x1, 0, 0}, ++ {0x30, 0, 0, 0, 0}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0x11, 0x11, 0, 0}, ++ {0x34, 0xee, 0xee, 1, 1}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0x3, 0x3, 0, 0}, ++ {0x38, 0x50, 0x50, 1, 1}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0x50, 0x50, 1, 1}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x6e, 0x6e, 0, 0}, ++ {0x3D, 0xf0, 0xf0, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x3, 0x3, 0, 0}, ++ {0x42, 0x3, 0x3, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x1e, 0x1e, 0, 0}, ++ {0x45, 0, 0, 0, 0}, ++ {0x46, 0x6e, 0x6e, 0, 0}, ++ {0x47, 0xf0, 0xf0, 1, 1}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x2, 0x2, 0, 0}, ++ {0x4A, 0xff, 0xff, 1, 1}, ++ {0x4B, 0xc, 0xc, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0x38, 0x38, 0, 0}, ++ {0x4E, 0x70, 0x70, 1, 1}, ++ {0x4F, 0x2, 0x2, 0, 0}, ++ {0x50, 0x88, 0x88, 0, 0}, ++ {0x51, 0xc, 0xc, 0, 0}, ++ {0x52, 0, 0, 0, 0}, ++ {0x53, 0x8, 0x8, 0, 0}, ++ {0x54, 0x70, 0x70, 1, 1}, ++ {0x55, 0x2, 0x2, 0, 0}, ++ {0x56, 0xff, 0xff, 1, 1}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x83, 0x83, 0, 0}, ++ {0x59, 0x77, 0x77, 1, 1}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x88, 0x88, 0, 0}, ++ {0x5D, 0, 0, 0, 0}, ++ {0x5E, 0x8, 0x8, 0, 0}, ++ {0x5F, 0x77, 0x77, 1, 1}, ++ {0x60, 0x1, 0x1, 0, 0}, ++ {0x61, 0, 0, 0, 0}, ++ {0x62, 0x7, 0x7, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0x7, 0x7, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 1, 1}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0xa, 0xa, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0x2, 0x2, 0, 0}, ++ {0x72, 0, 0, 0, 0}, ++ {0x73, 0, 0, 0, 0}, ++ {0x74, 0xe, 0xe, 0, 0}, ++ {0x75, 0xe, 0xe, 0, 0}, ++ {0x76, 0xe, 0xe, 0, 0}, ++ {0x77, 0x13, 0x13, 0, 0}, ++ {0x78, 0x13, 0x13, 0, 0}, ++ {0x79, 0x1b, 0x1b, 0, 0}, ++ {0x7A, 0x1b, 0x1b, 0, 0}, ++ {0x7B, 0x55, 0x55, 0, 0}, ++ {0x7C, 0x5b, 0x5b, 0, 0}, ++ {0x7D, 0x30, 0x30, 1, 1}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0x70, 0x70, 0, 0}, ++ {0x94, 0x70, 0x70, 0, 0}, ++ {0x95, 0x71, 0x71, 1, 1}, ++ {0x96, 0x71, 0x71, 1, 1}, ++ {0x97, 0x72, 0x72, 1, 1}, ++ {0x98, 0x73, 0x73, 1, 1}, ++ {0x99, 0x74, 0x74, 1, 1}, ++ {0x9A, 0x75, 0x75, 1, 1}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static struct radio_regs regs_RX_2056_rev7[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0x3, 0x3, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0, 0, 0, 0}, ++ {0x23, 0x90, 0x90, 0, 0}, ++ {0x24, 0x55, 0x55, 0, 0}, ++ {0x25, 0x15, 0x15, 0, 0}, ++ {0x26, 0x5, 0x5, 0, 0}, ++ {0x27, 0x15, 0x15, 0, 0}, ++ {0x28, 0x5, 0x5, 0, 0}, ++ {0x29, 0x20, 0x20, 0, 0}, ++ {0x2A, 0x11, 0x11, 0, 0}, ++ {0x2B, 0x90, 0x90, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0x88, 0x88, 0, 0}, ++ {0x2E, 0x32, 0x32, 0, 0}, ++ {0x2F, 0x77, 0x77, 0, 0}, ++ {0x30, 0x17, 0x17, 1, 1}, ++ {0x31, 0xff, 0xff, 1, 1}, ++ {0x32, 0x20, 0x20, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0x88, 0x88, 0, 0}, ++ {0x35, 0x32, 0x32, 0, 0}, ++ {0x36, 0x77, 0x77, 0, 0}, ++ {0x37, 0x17, 0x17, 1, 1}, ++ {0x38, 0xf0, 0xf0, 1, 1}, ++ {0x39, 0x20, 0x20, 0, 0}, ++ {0x3A, 0x8, 0x8, 0, 0}, ++ {0x3B, 0x55, 0x55, 1, 1}, ++ {0x3C, 0, 0, 0, 0}, ++ {0x3D, 0x88, 0x88, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 1, 1}, ++ {0x40, 0x7, 0x7, 1, 1}, ++ {0x41, 0x6, 0x6, 0, 0}, ++ {0x42, 0x4, 0x4, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x8, 0x8, 0, 0}, ++ {0x45, 0x55, 0x55, 1, 1}, ++ {0x46, 0, 0, 0, 0}, ++ {0x47, 0x11, 0x11, 0, 0}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0, 0, 1, 1}, ++ {0x4A, 0x7, 0x7, 0, 0}, ++ {0x4B, 0x6, 0x6, 0, 0}, ++ {0x4C, 0x4, 0x4, 0, 0}, ++ {0x4D, 0, 0, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0x26, 0x26, 1, 1}, ++ {0x50, 0x26, 0x26, 1, 1}, ++ {0x51, 0xf, 0xf, 1, 1}, ++ {0x52, 0xf, 0xf, 1, 1}, ++ {0x53, 0x44, 0x44, 0, 0}, ++ {0x54, 0, 0, 0, 0}, ++ {0x55, 0, 0, 0, 0}, ++ {0x56, 0x8, 0x8, 0, 0}, ++ {0x57, 0x8, 0x8, 0, 0}, ++ {0x58, 0x7, 0x7, 0, 0}, ++ {0x59, 0x22, 0x22, 0, 0}, ++ {0x5A, 0x22, 0x22, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x4, 0x4, 1, 1}, ++ {0x5D, 0x7, 0x7, 0, 0}, ++ {0x5E, 0x55, 0x55, 0, 0}, ++ {0x5F, 0x23, 0x23, 0, 0}, ++ {0x60, 0x41, 0x41, 0, 0}, ++ {0x61, 0x1, 0x1, 0, 0}, ++ {0x62, 0xa, 0xa, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0xc, 0xc, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0, 0, 0, 0}, ++ {0x72, 0x22, 0x22, 0, 0}, ++ {0x73, 0x22, 0x22, 0, 0}, ++ {0x74, 0, 0, 1, 1}, ++ {0x75, 0xa, 0xa, 0, 0}, ++ {0x76, 0x1, 0x1, 0, 0}, ++ {0x77, 0x22, 0x22, 0, 0}, ++ {0x78, 0x30, 0x30, 0, 0}, ++ {0x79, 0, 0, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static struct radio_regs regs_SYN_2056_rev8[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0x1, 0x1, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0x60, 0x60, 0, 0}, ++ {0x23, 0x6, 0x6, 0, 0}, ++ {0x24, 0xc, 0xc, 0, 0}, ++ {0x25, 0, 0, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0, 0, 0, 0}, ++ {0x28, 0x1, 0x1, 0, 0}, ++ {0x29, 0, 0, 0, 0}, ++ {0x2A, 0, 0, 0, 0}, ++ {0x2B, 0, 0, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0, 0, 0, 0}, ++ {0x2F, 0x1f, 0x1f, 0, 0}, ++ {0x30, 0x15, 0x15, 0, 0}, ++ {0x31, 0xf, 0xf, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0, 0, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0, 0, 0, 0}, ++ {0x38, 0, 0, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0, 0, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x13, 0x13, 0, 0}, ++ {0x3D, 0xf, 0xf, 0, 0}, ++ {0x3E, 0x18, 0x18, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x20, 0x20, 0, 0}, ++ {0x42, 0x20, 0x20, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x77, 0x77, 0, 0}, ++ {0x45, 0x7, 0x7, 0, 0}, ++ {0x46, 0x1, 0x1, 0, 0}, ++ {0x47, 0x4, 0x4, 0, 0}, ++ {0x48, 0xf, 0xf, 0, 0}, ++ {0x49, 0x30, 0x30, 0, 0}, ++ {0x4A, 0x32, 0x32, 0, 0}, ++ {0x4B, 0xd, 0xd, 0, 0}, ++ {0x4C, 0xd, 0xd, 0, 0}, ++ {0x4D, 0x4, 0x4, 0, 0}, ++ {0x4E, 0x6, 0x6, 0, 0}, ++ {0x4F, 0x1, 0x1, 0, 0}, ++ {0x50, 0x1c, 0x1c, 0, 0}, ++ {0x51, 0x2, 0x2, 0, 0}, ++ {0x52, 0x2, 0x2, 0, 0}, ++ {0x53, 0xf7, 0xf7, 1, 1}, ++ {0x54, 0xb4, 0xb4, 0, 0}, ++ {0x55, 0xd2, 0xd2, 0, 0}, ++ {0x56, 0, 0, 0, 0}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x4, 0x4, 0, 0}, ++ {0x59, 0x96, 0x96, 0, 0}, ++ {0x5A, 0x3e, 0x3e, 0, 0}, ++ {0x5B, 0x3e, 0x3e, 0, 0}, ++ {0x5C, 0x13, 0x13, 0, 0}, ++ {0x5D, 0x2, 0x2, 0, 0}, ++ {0x5E, 0, 0, 0, 0}, ++ {0x5F, 0x7, 0x7, 0, 0}, ++ {0x60, 0x7, 0x7, 1, 1}, ++ {0x61, 0x8, 0x8, 0, 0}, ++ {0x62, 0x3, 0x3, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0x40, 0x40, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0x1, 0x1, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0x60, 0x60, 0, 0}, ++ {0x71, 0x66, 0x66, 0, 0}, ++ {0x72, 0xc, 0xc, 0, 0}, ++ {0x73, 0x66, 0x66, 0, 0}, ++ {0x74, 0x8f, 0x8f, 1, 1}, ++ {0x75, 0, 0, 0, 0}, ++ {0x76, 0xcc, 0xcc, 0, 0}, ++ {0x77, 0x1, 0x1, 0, 0}, ++ {0x78, 0x66, 0x66, 0, 0}, ++ {0x79, 0x66, 0x66, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0xff, 0xff, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0x95, 0, 0, 0, 0}, ++ {0x96, 0, 0, 0, 0}, ++ {0x97, 0, 0, 0, 0}, ++ {0x98, 0, 0, 0, 0}, ++ {0x99, 0, 0, 0, 0}, ++ {0x9A, 0, 0, 0, 0}, ++ {0x9B, 0, 0, 0, 0}, ++ {0x9C, 0, 0, 0, 0}, ++ {0x9D, 0, 0, 0, 0}, ++ {0x9E, 0, 0, 0, 0}, ++ {0x9F, 0x6, 0x6, 0, 0}, ++ {0xA0, 0x66, 0x66, 0, 0}, ++ {0xA1, 0x66, 0x66, 0, 0}, ++ {0xA2, 0x66, 0x66, 0, 0}, ++ {0xA3, 0x66, 0x66, 0, 0}, ++ {0xA4, 0x66, 0x66, 0, 0}, ++ {0xA5, 0x66, 0x66, 0, 0}, ++ {0xA6, 0x66, 0x66, 0, 0}, ++ {0xA7, 0x66, 0x66, 0, 0}, ++ {0xA8, 0x66, 0x66, 0, 0}, ++ {0xA9, 0x66, 0x66, 0, 0}, ++ {0xAA, 0x66, 0x66, 0, 0}, ++ {0xAB, 0x66, 0x66, 0, 0}, ++ {0xAC, 0x66, 0x66, 0, 0}, ++ {0xAD, 0x66, 0x66, 0, 0}, ++ {0xAE, 0x66, 0x66, 0, 0}, ++ {0xAF, 0x66, 0x66, 0, 0}, ++ {0xB0, 0x66, 0x66, 0, 0}, ++ {0xB1, 0x66, 0x66, 0, 0}, ++ {0xB2, 0x66, 0x66, 0, 0}, ++ {0xB3, 0xa, 0xa, 0, 0}, ++ {0xB4, 0, 0, 0, 0}, ++ {0xB5, 0, 0, 0, 0}, ++ {0xB6, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static struct radio_regs regs_TX_2056_rev8[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0x88, 0x88, 0, 0}, ++ {0x22, 0x88, 0x88, 0, 0}, ++ {0x23, 0x88, 0x88, 0, 0}, ++ {0x24, 0x88, 0x88, 0, 0}, ++ {0x25, 0xc, 0xc, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0x3, 0x3, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0x3, 0x3, 0, 0}, ++ {0x2A, 0x37, 0x37, 0, 0}, ++ {0x2B, 0x3, 0x3, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0x1, 0x1, 0, 0}, ++ {0x2F, 0x1, 0x1, 0, 0}, ++ {0x30, 0, 0, 0, 0}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0x11, 0x11, 0, 0}, ++ {0x34, 0xee, 0xee, 1, 1}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0x3, 0x3, 0, 0}, ++ {0x38, 0x50, 0x50, 1, 1}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0x50, 0x50, 1, 1}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x6e, 0x6e, 0, 0}, ++ {0x3D, 0xf0, 0xf0, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x3, 0x3, 0, 0}, ++ {0x42, 0x3, 0x3, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x1e, 0x1e, 0, 0}, ++ {0x45, 0, 0, 0, 0}, ++ {0x46, 0x6e, 0x6e, 0, 0}, ++ {0x47, 0xf0, 0xf0, 1, 1}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x2, 0x2, 0, 0}, ++ {0x4A, 0xff, 0xff, 1, 1}, ++ {0x4B, 0xc, 0xc, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0x38, 0x38, 0, 0}, ++ {0x4E, 0x70, 0x70, 1, 1}, ++ {0x4F, 0x2, 0x2, 0, 0}, ++ {0x50, 0x88, 0x88, 0, 0}, ++ {0x51, 0xc, 0xc, 0, 0}, ++ {0x52, 0, 0, 0, 0}, ++ {0x53, 0x8, 0x8, 0, 0}, ++ {0x54, 0x70, 0x70, 1, 1}, ++ {0x55, 0x2, 0x2, 0, 0}, ++ {0x56, 0xff, 0xff, 1, 1}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x83, 0x83, 0, 0}, ++ {0x59, 0x77, 0x77, 1, 1}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x88, 0x88, 0, 0}, ++ {0x5D, 0, 0, 0, 0}, ++ {0x5E, 0x8, 0x8, 0, 0}, ++ {0x5F, 0x77, 0x77, 1, 1}, ++ {0x60, 0x1, 0x1, 0, 0}, ++ {0x61, 0, 0, 0, 0}, ++ {0x62, 0x7, 0x7, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0x7, 0x7, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 1, 1}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0xa, 0xa, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0x2, 0x2, 0, 0}, ++ {0x72, 0, 0, 0, 0}, ++ {0x73, 0, 0, 0, 0}, ++ {0x74, 0xe, 0xe, 0, 0}, ++ {0x75, 0xe, 0xe, 0, 0}, ++ {0x76, 0xe, 0xe, 0, 0}, ++ {0x77, 0x13, 0x13, 0, 0}, ++ {0x78, 0x13, 0x13, 0, 0}, ++ {0x79, 0x1b, 0x1b, 0, 0}, ++ {0x7A, 0x1b, 0x1b, 0, 0}, ++ {0x7B, 0x55, 0x55, 0, 0}, ++ {0x7C, 0x5b, 0x5b, 0, 0}, ++ {0x7D, 0x30, 0x30, 1, 1}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0x70, 0x70, 0, 0}, ++ {0x94, 0x70, 0x70, 0, 0}, ++ {0x95, 0x70, 0x70, 0, 0}, ++ {0x96, 0x70, 0x70, 0, 0}, ++ {0x97, 0x70, 0x70, 0, 0}, ++ {0x98, 0x70, 0x70, 0, 0}, ++ {0x99, 0x70, 0x70, 0, 0}, ++ {0x9A, 0x70, 0x70, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static struct radio_regs regs_RX_2056_rev8[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0x3, 0x3, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0, 0, 0, 0}, ++ {0x23, 0x90, 0x90, 0, 0}, ++ {0x24, 0x55, 0x55, 0, 0}, ++ {0x25, 0x15, 0x15, 0, 0}, ++ {0x26, 0x5, 0x5, 0, 0}, ++ {0x27, 0x15, 0x15, 0, 0}, ++ {0x28, 0x5, 0x5, 0, 0}, ++ {0x29, 0x20, 0x20, 0, 0}, ++ {0x2A, 0x11, 0x11, 0, 0}, ++ {0x2B, 0x90, 0x90, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0x88, 0x88, 0, 0}, ++ {0x2E, 0x32, 0x32, 0, 0}, ++ {0x2F, 0x77, 0x77, 0, 0}, ++ {0x30, 0x17, 0x17, 1, 1}, ++ {0x31, 0xff, 0xff, 1, 1}, ++ {0x32, 0x20, 0x20, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0x88, 0x88, 0, 0}, ++ {0x35, 0x32, 0x32, 0, 0}, ++ {0x36, 0x77, 0x77, 0, 0}, ++ {0x37, 0x17, 0x17, 1, 1}, ++ {0x38, 0xf0, 0xf0, 1, 1}, ++ {0x39, 0x20, 0x20, 0, 0}, ++ {0x3A, 0x8, 0x8, 0, 0}, ++ {0x3B, 0x55, 0x55, 1, 1}, ++ {0x3C, 0, 0, 0, 0}, ++ {0x3D, 0x88, 0x88, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0x44, 0x44, 0, 0}, ++ {0x40, 0x7, 0x7, 1, 1}, ++ {0x41, 0x6, 0x6, 0, 0}, ++ {0x42, 0x4, 0x4, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x8, 0x8, 0, 0}, ++ {0x45, 0x55, 0x55, 1, 1}, ++ {0x46, 0, 0, 0, 0}, ++ {0x47, 0x11, 0x11, 0, 0}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x44, 0x44, 0, 0}, ++ {0x4A, 0x7, 0x7, 0, 0}, ++ {0x4B, 0x6, 0x6, 0, 0}, ++ {0x4C, 0x4, 0x4, 0, 0}, ++ {0x4D, 0, 0, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0x26, 0x26, 1, 1}, ++ {0x50, 0x26, 0x26, 1, 1}, ++ {0x51, 0xf, 0xf, 1, 1}, ++ {0x52, 0xf, 0xf, 1, 1}, ++ {0x53, 0x44, 0x44, 0, 0}, ++ {0x54, 0, 0, 0, 0}, ++ {0x55, 0, 0, 0, 0}, ++ {0x56, 0x8, 0x8, 0, 0}, ++ {0x57, 0x8, 0x8, 0, 0}, ++ {0x58, 0x7, 0x7, 0, 0}, ++ {0x59, 0x22, 0x22, 0, 0}, ++ {0x5A, 0x22, 0x22, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x4, 0x4, 1, 1}, ++ {0x5D, 0x7, 0x7, 0, 0}, ++ {0x5E, 0x55, 0x55, 0, 0}, ++ {0x5F, 0x23, 0x23, 0, 0}, ++ {0x60, 0x41, 0x41, 0, 0}, ++ {0x61, 0x1, 0x1, 0, 0}, ++ {0x62, 0xa, 0xa, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0xc, 0xc, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0, 0, 0, 0}, ++ {0x72, 0x22, 0x22, 0, 0}, ++ {0x73, 0x22, 0x22, 0, 0}, ++ {0x74, 0, 0, 1, 1}, ++ {0x75, 0xa, 0xa, 0, 0}, ++ {0x76, 0x1, 0x1, 0, 0}, ++ {0x77, 0x22, 0x22, 0, 0}, ++ {0x78, 0x30, 0x30, 0, 0}, ++ {0x79, 0, 0, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0x5, 0x5, 1, 1}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static const struct radio_regs regs_SYN_2056_rev11[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0x1, 0x1, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0x60, 0x60, 0, 0}, ++ {0x23, 0x6, 0x6, 0, 0}, ++ {0x24, 0xc, 0xc, 0, 0}, ++ {0x25, 0, 0, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0, 0, 0, 0}, ++ {0x28, 0x1, 0x1, 0, 0}, ++ {0x29, 0, 0, 0, 0}, ++ {0x2A, 0, 0, 0, 0}, ++ {0x2B, 0, 0, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0, 0, 0, 0}, ++ {0x2F, 0x1f, 0x1f, 0, 0}, ++ {0x30, 0x15, 0x15, 0, 0}, ++ {0x31, 0xf, 0xf, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0, 0, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0, 0, 0, 0}, ++ {0x38, 0, 0, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0, 0, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x13, 0x13, 0, 0}, ++ {0x3D, 0xf, 0xf, 0, 0}, ++ {0x3E, 0x18, 0x18, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x20, 0x20, 0, 0}, ++ {0x42, 0x20, 0x20, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x77, 0x77, 0, 0}, ++ {0x45, 0x7, 0x7, 0, 0}, ++ {0x46, 0x1, 0x1, 0, 0}, ++ {0x47, 0x6, 0x6, 1, 1}, ++ {0x48, 0xf, 0xf, 0, 0}, ++ {0x49, 0x3f, 0x3f, 1, 1}, ++ {0x4A, 0x32, 0x32, 0, 0}, ++ {0x4B, 0x6, 0x6, 1, 1}, ++ {0x4C, 0x6, 0x6, 1, 1}, ++ {0x4D, 0x4, 0x4, 0, 0}, ++ {0x4E, 0x2b, 0x2b, 1, 1}, ++ {0x4F, 0x1, 0x1, 0, 0}, ++ {0x50, 0x1c, 0x1c, 0, 0}, ++ {0x51, 0x2, 0x2, 0, 0}, ++ {0x52, 0x2, 0x2, 0, 0}, ++ {0x53, 0xf7, 0xf7, 1, 1}, ++ {0x54, 0xb4, 0xb4, 0, 0}, ++ {0x55, 0xd2, 0xd2, 0, 0}, ++ {0x56, 0, 0, 0, 0}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x4, 0x4, 0, 0}, ++ {0x59, 0x96, 0x96, 0, 0}, ++ {0x5A, 0x3e, 0x3e, 0, 0}, ++ {0x5B, 0x3e, 0x3e, 0, 0}, ++ {0x5C, 0x13, 0x13, 0, 0}, ++ {0x5D, 0x2, 0x2, 0, 0}, ++ {0x5E, 0, 0, 0, 0}, ++ {0x5F, 0x7, 0x7, 0, 0}, ++ {0x60, 0x7, 0x7, 1, 1}, ++ {0x61, 0x8, 0x8, 0, 0}, ++ {0x62, 0x3, 0x3, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0x40, 0x40, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0x1, 0x1, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0x60, 0x60, 0, 0}, ++ {0x71, 0x66, 0x66, 0, 0}, ++ {0x72, 0xc, 0xc, 0, 0}, ++ {0x73, 0x66, 0x66, 0, 0}, ++ {0x74, 0x8f, 0x8f, 1, 1}, ++ {0x75, 0, 0, 0, 0}, ++ {0x76, 0xcc, 0xcc, 0, 0}, ++ {0x77, 0x1, 0x1, 0, 0}, ++ {0x78, 0x66, 0x66, 0, 0}, ++ {0x79, 0x66, 0x66, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0xff, 0xff, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0x95, 0, 0, 0, 0}, ++ {0x96, 0, 0, 0, 0}, ++ {0x97, 0, 0, 0, 0}, ++ {0x98, 0, 0, 0, 0}, ++ {0x99, 0, 0, 0, 0}, ++ {0x9A, 0, 0, 0, 0}, ++ {0x9B, 0, 0, 0, 0}, ++ {0x9C, 0, 0, 0, 0}, ++ {0x9D, 0, 0, 0, 0}, ++ {0x9E, 0, 0, 0, 0}, ++ {0x9F, 0x6, 0x6, 0, 0}, ++ {0xA0, 0x66, 0x66, 0, 0}, ++ {0xA1, 0x66, 0x66, 0, 0}, ++ {0xA2, 0x66, 0x66, 0, 0}, ++ {0xA3, 0x66, 0x66, 0, 0}, ++ {0xA4, 0x66, 0x66, 0, 0}, ++ {0xA5, 0x66, 0x66, 0, 0}, ++ {0xA6, 0x66, 0x66, 0, 0}, ++ {0xA7, 0x66, 0x66, 0, 0}, ++ {0xA8, 0x66, 0x66, 0, 0}, ++ {0xA9, 0x66, 0x66, 0, 0}, ++ {0xAA, 0x66, 0x66, 0, 0}, ++ {0xAB, 0x66, 0x66, 0, 0}, ++ {0xAC, 0x66, 0x66, 0, 0}, ++ {0xAD, 0x66, 0x66, 0, 0}, ++ {0xAE, 0x66, 0x66, 0, 0}, ++ {0xAF, 0x66, 0x66, 0, 0}, ++ {0xB0, 0x66, 0x66, 0, 0}, ++ {0xB1, 0x66, 0x66, 0, 0}, ++ {0xB2, 0x66, 0x66, 0, 0}, ++ {0xB3, 0xa, 0xa, 0, 0}, ++ {0xB4, 0, 0, 0, 0}, ++ {0xB5, 0, 0, 0, 0}, ++ {0xB6, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static const struct radio_regs regs_TX_2056_rev11[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0x88, 0x88, 0, 0}, ++ {0x22, 0x88, 0x88, 0, 0}, ++ {0x23, 0x88, 0x88, 0, 0}, ++ {0x24, 0x88, 0x88, 0, 0}, ++ {0x25, 0xc, 0xc, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0x3, 0x3, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0x3, 0x3, 0, 0}, ++ {0x2A, 0x37, 0x37, 0, 0}, ++ {0x2B, 0x3, 0x3, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0x1, 0x1, 0, 0}, ++ {0x2F, 0x1, 0x1, 0, 0}, ++ {0x30, 0, 0, 0, 0}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0x11, 0x11, 0, 0}, ++ {0x34, 0xee, 0xee, 1, 1}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0x3, 0x3, 0, 0}, ++ {0x38, 0x50, 0x50, 1, 1}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0x50, 0x50, 1, 1}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x6e, 0x6e, 0, 0}, ++ {0x3D, 0xf0, 0xf0, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x3, 0x3, 0, 0}, ++ {0x42, 0x3, 0x3, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x1e, 0x1e, 0, 0}, ++ {0x45, 0, 0, 0, 0}, ++ {0x46, 0x6e, 0x6e, 0, 0}, ++ {0x47, 0xf0, 0xf0, 1, 1}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x2, 0x2, 0, 0}, ++ {0x4A, 0xff, 0xff, 1, 1}, ++ {0x4B, 0xc, 0xc, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0x38, 0x38, 0, 0}, ++ {0x4E, 0x70, 0x70, 1, 1}, ++ {0x4F, 0x2, 0x2, 0, 0}, ++ {0x50, 0x88, 0x88, 0, 0}, ++ {0x51, 0xc, 0xc, 0, 0}, ++ {0x52, 0, 0, 0, 0}, ++ {0x53, 0x8, 0x8, 0, 0}, ++ {0x54, 0x70, 0x70, 1, 1}, ++ {0x55, 0x2, 0x2, 0, 0}, ++ {0x56, 0xff, 0xff, 1, 1}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x83, 0x83, 0, 0}, ++ {0x59, 0x77, 0x77, 1, 1}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x88, 0x88, 0, 0}, ++ {0x5D, 0, 0, 0, 0}, ++ {0x5E, 0x8, 0x8, 0, 0}, ++ {0x5F, 0x77, 0x77, 1, 1}, ++ {0x60, 0x1, 0x1, 0, 0}, ++ {0x61, 0, 0, 0, 0}, ++ {0x62, 0x7, 0x7, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0x7, 0x7, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 1, 1}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0xa, 0xa, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0x2, 0x2, 0, 0}, ++ {0x72, 0, 0, 0, 0}, ++ {0x73, 0, 0, 0, 0}, ++ {0x74, 0xe, 0xe, 0, 0}, ++ {0x75, 0xe, 0xe, 0, 0}, ++ {0x76, 0xe, 0xe, 0, 0}, ++ {0x77, 0x13, 0x13, 0, 0}, ++ {0x78, 0x13, 0x13, 0, 0}, ++ {0x79, 0x1b, 0x1b, 0, 0}, ++ {0x7A, 0x1b, 0x1b, 0, 0}, ++ {0x7B, 0x55, 0x55, 0, 0}, ++ {0x7C, 0x5b, 0x5b, 0, 0}, ++ {0x7D, 0x30, 0x30, 1, 1}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0x70, 0x70, 0, 0}, ++ {0x94, 0x70, 0x70, 0, 0}, ++ {0x95, 0x70, 0x70, 0, 0}, ++ {0x96, 0x70, 0x70, 0, 0}, ++ {0x97, 0x70, 0x70, 0, 0}, ++ {0x98, 0x70, 0x70, 0, 0}, ++ {0x99, 0x70, 0x70, 0, 0}, ++ {0x9A, 0x70, 0x70, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static const struct radio_regs regs_RX_2056_rev11[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0x3, 0x3, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0, 0, 0, 0}, ++ {0x23, 0x90, 0x90, 0, 0}, ++ {0x24, 0x55, 0x55, 0, 0}, ++ {0x25, 0x15, 0x15, 0, 0}, ++ {0x26, 0x5, 0x5, 0, 0}, ++ {0x27, 0x15, 0x15, 0, 0}, ++ {0x28, 0x5, 0x5, 0, 0}, ++ {0x29, 0x20, 0x20, 0, 0}, ++ {0x2A, 0x11, 0x11, 0, 0}, ++ {0x2B, 0x90, 0x90, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0x88, 0x88, 0, 0}, ++ {0x2E, 0x32, 0x32, 0, 0}, ++ {0x2F, 0x77, 0x77, 0, 0}, ++ {0x30, 0x17, 0x17, 1, 1}, ++ {0x31, 0xff, 0xff, 1, 1}, ++ {0x32, 0x20, 0x20, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0x88, 0x88, 0, 0}, ++ {0x35, 0x32, 0x32, 0, 0}, ++ {0x36, 0x77, 0x77, 0, 0}, ++ {0x37, 0x17, 0x17, 1, 1}, ++ {0x38, 0xf0, 0xf0, 1, 1}, ++ {0x39, 0x20, 0x20, 0, 0}, ++ {0x3A, 0x8, 0x8, 0, 0}, ++ {0x3B, 0x55, 0x55, 1, 1}, ++ {0x3C, 0, 0, 0, 0}, ++ {0x3D, 0x88, 0x88, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0x44, 0x44, 0, 0}, ++ {0x40, 0x7, 0x7, 1, 1}, ++ {0x41, 0x6, 0x6, 0, 0}, ++ {0x42, 0x4, 0x4, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x8, 0x8, 0, 0}, ++ {0x45, 0x55, 0x55, 1, 1}, ++ {0x46, 0, 0, 0, 0}, ++ {0x47, 0x11, 0x11, 0, 0}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x44, 0x44, 0, 0}, ++ {0x4A, 0x7, 0x7, 0, 0}, ++ {0x4B, 0x6, 0x6, 0, 0}, ++ {0x4C, 0x4, 0x4, 0, 0}, ++ {0x4D, 0, 0, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0x26, 0x26, 1, 1}, ++ {0x50, 0x26, 0x26, 1, 1}, ++ {0x51, 0xf, 0xf, 1, 1}, ++ {0x52, 0xf, 0xf, 1, 1}, ++ {0x53, 0x44, 0x44, 0, 0}, ++ {0x54, 0, 0, 0, 0}, ++ {0x55, 0, 0, 0, 0}, ++ {0x56, 0x8, 0x8, 0, 0}, ++ {0x57, 0x8, 0x8, 0, 0}, ++ {0x58, 0x7, 0x7, 0, 0}, ++ {0x59, 0x22, 0x22, 0, 0}, ++ {0x5A, 0x22, 0x22, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x4, 0x4, 1, 1}, ++ {0x5D, 0x7, 0x7, 0, 0}, ++ {0x5E, 0x55, 0x55, 0, 0}, ++ {0x5F, 0x23, 0x23, 0, 0}, ++ {0x60, 0x41, 0x41, 0, 0}, ++ {0x61, 0x1, 0x1, 0, 0}, ++ {0x62, 0xa, 0xa, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0xc, 0xc, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0, 0, 0, 0}, ++ {0x72, 0x22, 0x22, 0, 0}, ++ {0x73, 0x22, 0x22, 0, 0}, ++ {0x74, 0, 0, 1, 1}, ++ {0x75, 0xa, 0xa, 0, 0}, ++ {0x76, 0x1, 0x1, 0, 0}, ++ {0x77, 0x22, 0x22, 0, 0}, ++ {0x78, 0x30, 0x30, 0, 0}, ++ {0x79, 0, 0, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0x5, 0x5, 1, 1}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static struct radio_20xx_regs regs_2057_rev4[] = { ++ {0x00, 0x84, 0}, ++ {0x01, 0, 0}, ++ {0x02, 0x60, 0}, ++ {0x03, 0x1f, 0}, ++ {0x04, 0x4, 0}, ++ {0x05, 0x2, 0}, ++ {0x06, 0x1, 0}, ++ {0x07, 0x1, 0}, ++ {0x08, 0x1, 0}, ++ {0x09, 0x69, 0}, ++ {0x0A, 0x66, 0}, ++ {0x0B, 0x6, 0}, ++ {0x0C, 0x18, 0}, ++ {0x0D, 0x3, 0}, ++ {0x0E, 0x20, 1}, ++ {0x0F, 0x20, 0}, ++ {0x10, 0, 0}, ++ {0x11, 0x7c, 0}, ++ {0x12, 0x42, 0}, ++ {0x13, 0xbd, 0}, ++ {0x14, 0x7, 0}, ++ {0x15, 0xf7, 0}, ++ {0x16, 0x8, 0}, ++ {0x17, 0x17, 0}, ++ {0x18, 0x7, 0}, ++ {0x19, 0, 0}, ++ {0x1A, 0x2, 0}, ++ {0x1B, 0x13, 0}, ++ {0x1C, 0x3e, 0}, ++ {0x1D, 0x3e, 0}, ++ {0x1E, 0x96, 0}, ++ {0x1F, 0x4, 0}, ++ {0x20, 0, 0}, ++ {0x21, 0, 0}, ++ {0x22, 0x17, 0}, ++ {0x23, 0x4, 0}, ++ {0x24, 0x1, 0}, ++ {0x25, 0x6, 0}, ++ {0x26, 0x4, 0}, ++ {0x27, 0xd, 0}, ++ {0x28, 0xd, 0}, ++ {0x29, 0x30, 0}, ++ {0x2A, 0x32, 0}, ++ {0x2B, 0x8, 0}, ++ {0x2C, 0x1c, 0}, ++ {0x2D, 0x2, 0}, ++ {0x2E, 0x4, 0}, ++ {0x2F, 0x7f, 0}, ++ {0x30, 0x27, 0}, ++ {0x31, 0, 1}, ++ {0x32, 0, 1}, ++ {0x33, 0, 1}, ++ {0x34, 0, 0}, ++ {0x35, 0x26, 1}, ++ {0x36, 0x18, 0}, ++ {0x37, 0x7, 0}, ++ {0x38, 0x66, 0}, ++ {0x39, 0x66, 0}, ++ {0x3A, 0x66, 0}, ++ {0x3B, 0x66, 0}, ++ {0x3C, 0xff, 1}, ++ {0x3D, 0xff, 1}, ++ {0x3E, 0xff, 1}, ++ {0x3F, 0xff, 1}, ++ {0x40, 0x16, 0}, ++ {0x41, 0x7, 0}, ++ {0x42, 0x19, 0}, ++ {0x43, 0x7, 0}, ++ {0x44, 0x6, 0}, ++ {0x45, 0x3, 0}, ++ {0x46, 0x1, 0}, ++ {0x47, 0x7, 0}, ++ {0x48, 0x33, 0}, ++ {0x49, 0x5, 0}, ++ {0x4A, 0x77, 0}, ++ {0x4B, 0x66, 0}, ++ {0x4C, 0x66, 0}, ++ {0x4D, 0, 0}, ++ {0x4E, 0x4, 0}, ++ {0x4F, 0xc, 0}, ++ {0x50, 0, 0}, ++ {0x51, 0x75, 0}, ++ {0x56, 0x7, 0}, ++ {0x57, 0, 0}, ++ {0x58, 0, 0}, ++ {0x59, 0xa8, 0}, ++ {0x5A, 0, 0}, ++ {0x5B, 0x1f, 0}, ++ {0x5C, 0x30, 0}, ++ {0x5D, 0x1, 0}, ++ {0x5E, 0x30, 0}, ++ {0x5F, 0x70, 0}, ++ {0x60, 0, 0}, ++ {0x61, 0, 0}, ++ {0x62, 0x33, 1}, ++ {0x63, 0x19, 0}, ++ {0x64, 0x62, 0}, ++ {0x65, 0, 0}, ++ {0x66, 0x11, 0}, ++ {0x69, 0, 0}, ++ {0x6A, 0x7e, 0}, ++ {0x6B, 0x3f, 0}, ++ {0x6C, 0x7f, 0}, ++ {0x6D, 0x78, 0}, ++ {0x6E, 0xc8, 0}, ++ {0x6F, 0x88, 0}, ++ {0x70, 0x8, 0}, ++ {0x71, 0xf, 0}, ++ {0x72, 0xbc, 0}, ++ {0x73, 0x8, 0}, ++ {0x74, 0x60, 0}, ++ {0x75, 0x1e, 0}, ++ {0x76, 0x70, 0}, ++ {0x77, 0, 0}, ++ {0x78, 0, 0}, ++ {0x79, 0, 0}, ++ {0x7A, 0x33, 0}, ++ {0x7B, 0x1e, 0}, ++ {0x7C, 0x62, 0}, ++ {0x7D, 0x11, 0}, ++ {0x80, 0x3c, 0}, ++ {0x81, 0x9c, 0}, ++ {0x82, 0xa, 0}, ++ {0x83, 0x9d, 0}, ++ {0x84, 0xa, 0}, ++ {0x85, 0, 0}, ++ {0x86, 0x40, 0}, ++ {0x87, 0x40, 0}, ++ {0x88, 0x88, 0}, ++ {0x89, 0x10, 0}, ++ {0x8A, 0xf0, 1}, ++ {0x8B, 0x10, 1}, ++ {0x8C, 0xf0, 1}, ++ {0x8D, 0, 0}, ++ {0x8E, 0, 0}, ++ {0x8F, 0x10, 0}, ++ {0x90, 0x55, 0}, ++ {0x91, 0x3f, 1}, ++ {0x92, 0x36, 1}, ++ {0x93, 0, 0}, ++ {0x94, 0, 0}, ++ {0x95, 0, 0}, ++ {0x96, 0x87, 0}, ++ {0x97, 0x11, 0}, ++ {0x98, 0, 0}, ++ {0x99, 0x33, 0}, ++ {0x9A, 0x88, 0}, ++ {0x9B, 0, 0}, ++ {0x9C, 0x87, 0}, ++ {0x9D, 0x11, 0}, ++ {0x9E, 0, 0}, ++ {0x9F, 0x33, 0}, ++ {0xA0, 0x88, 0}, ++ {0xA1, 0xe1, 0}, ++ {0xA2, 0x3f, 0}, ++ {0xA3, 0x44, 0}, ++ {0xA4, 0x8c, 1}, ++ {0xA5, 0x6d, 0}, ++ {0xA6, 0x22, 0}, ++ {0xA7, 0xbe, 0}, ++ {0xA8, 0x55, 1}, ++ {0xA9, 0xc, 0}, ++ {0xAA, 0xc, 0}, ++ {0xAB, 0xaa, 0}, ++ {0xAC, 0x2, 0}, ++ {0xAD, 0, 0}, ++ {0xAE, 0x10, 0}, ++ {0xAF, 0x1, 1}, ++ {0xB0, 0, 0}, ++ {0xB1, 0, 0}, ++ {0xB2, 0x80, 0}, ++ {0xB3, 0x60, 0}, ++ {0xB4, 0x44, 0}, ++ {0xB5, 0x55, 0}, ++ {0xB6, 0x1, 0}, ++ {0xB7, 0x55, 0}, ++ {0xB8, 0x1, 0}, ++ {0xB9, 0x5, 0}, ++ {0xBA, 0x55, 0}, ++ {0xBB, 0x55, 0}, ++ {0xC1, 0, 0}, ++ {0xC2, 0, 0}, ++ {0xC3, 0, 0}, ++ {0xC4, 0, 0}, ++ {0xC5, 0, 0}, ++ {0xC6, 0, 0}, ++ {0xC7, 0, 0}, ++ {0xC8, 0, 0}, ++ {0xC9, 0, 0}, ++ {0xCA, 0, 0}, ++ {0xCB, 0, 0}, ++ {0xCC, 0, 0}, ++ {0xCD, 0, 0}, ++ {0xCE, 0x5e, 0}, ++ {0xCF, 0xc, 0}, ++ {0xD0, 0xc, 0}, ++ {0xD1, 0xc, 0}, ++ {0xD2, 0, 0}, ++ {0xD3, 0x2b, 0}, ++ {0xD4, 0xc, 0}, ++ {0xD5, 0, 0}, ++ {0xD6, 0x75, 0}, ++ {0xDB, 0x7, 0}, ++ {0xDC, 0, 0}, ++ {0xDD, 0, 0}, ++ {0xDE, 0xa8, 0}, ++ {0xDF, 0, 0}, ++ {0xE0, 0x1f, 0}, ++ {0xE1, 0x30, 0}, ++ {0xE2, 0x1, 0}, ++ {0xE3, 0x30, 0}, ++ {0xE4, 0x70, 0}, ++ {0xE5, 0, 0}, ++ {0xE6, 0, 0}, ++ {0xE7, 0x33, 0}, ++ {0xE8, 0x19, 0}, ++ {0xE9, 0x62, 0}, ++ {0xEA, 0, 0}, ++ {0xEB, 0x11, 0}, ++ {0xEE, 0, 0}, ++ {0xEF, 0x7e, 0}, ++ {0xF0, 0x3f, 0}, ++ {0xF1, 0x7f, 0}, ++ {0xF2, 0x78, 0}, ++ {0xF3, 0xc8, 0}, ++ {0xF4, 0x88, 0}, ++ {0xF5, 0x8, 0}, ++ {0xF6, 0xf, 0}, ++ {0xF7, 0xbc, 0}, ++ {0xF8, 0x8, 0}, ++ {0xF9, 0x60, 0}, ++ {0xFA, 0x1e, 0}, ++ {0xFB, 0x70, 0}, ++ {0xFC, 0, 0}, ++ {0xFD, 0, 0}, ++ {0xFE, 0, 0}, ++ {0xFF, 0x33, 0}, ++ {0x100, 0x1e, 0}, ++ {0x101, 0x62, 0}, ++ {0x102, 0x11, 0}, ++ {0x105, 0x3c, 0}, ++ {0x106, 0x9c, 0}, ++ {0x107, 0xa, 0}, ++ {0x108, 0x9d, 0}, ++ {0x109, 0xa, 0}, ++ {0x10A, 0, 0}, ++ {0x10B, 0x40, 0}, ++ {0x10C, 0x40, 0}, ++ {0x10D, 0x88, 0}, ++ {0x10E, 0x10, 0}, ++ {0x10F, 0xf0, 1}, ++ {0x110, 0x10, 1}, ++ {0x111, 0xf0, 1}, ++ {0x112, 0, 0}, ++ {0x113, 0, 0}, ++ {0x114, 0x10, 0}, ++ {0x115, 0x55, 0}, ++ {0x116, 0x3f, 1}, ++ {0x117, 0x36, 1}, ++ {0x118, 0, 0}, ++ {0x119, 0, 0}, ++ {0x11A, 0, 0}, ++ {0x11B, 0x87, 0}, ++ {0x11C, 0x11, 0}, ++ {0x11D, 0, 0}, ++ {0x11E, 0x33, 0}, ++ {0x11F, 0x88, 0}, ++ {0x120, 0, 0}, ++ {0x121, 0x87, 0}, ++ {0x122, 0x11, 0}, ++ {0x123, 0, 0}, ++ {0x124, 0x33, 0}, ++ {0x125, 0x88, 0}, ++ {0x126, 0xe1, 0}, ++ {0x127, 0x3f, 0}, ++ {0x128, 0x44, 0}, ++ {0x129, 0x8c, 1}, ++ {0x12A, 0x6d, 0}, ++ {0x12B, 0x22, 0}, ++ {0x12C, 0xbe, 0}, ++ {0x12D, 0x55, 1}, ++ {0x12E, 0xc, 0}, ++ {0x12F, 0xc, 0}, ++ {0x130, 0xaa, 0}, ++ {0x131, 0x2, 0}, ++ {0x132, 0, 0}, ++ {0x133, 0x10, 0}, ++ {0x134, 0x1, 1}, ++ {0x135, 0, 0}, ++ {0x136, 0, 0}, ++ {0x137, 0x80, 0}, ++ {0x138, 0x60, 0}, ++ {0x139, 0x44, 0}, ++ {0x13A, 0x55, 0}, ++ {0x13B, 0x1, 0}, ++ {0x13C, 0x55, 0}, ++ {0x13D, 0x1, 0}, ++ {0x13E, 0x5, 0}, ++ {0x13F, 0x55, 0}, ++ {0x140, 0x55, 0}, ++ {0x146, 0, 0}, ++ {0x147, 0, 0}, ++ {0x148, 0, 0}, ++ {0x149, 0, 0}, ++ {0x14A, 0, 0}, ++ {0x14B, 0, 0}, ++ {0x14C, 0, 0}, ++ {0x14D, 0, 0}, ++ {0x14E, 0, 0}, ++ {0x14F, 0, 0}, ++ {0x150, 0, 0}, ++ {0x151, 0, 0}, ++ {0x152, 0, 0}, ++ {0x153, 0, 0}, ++ {0x154, 0xc, 0}, ++ {0x155, 0xc, 0}, ++ {0x156, 0xc, 0}, ++ {0x157, 0, 0}, ++ {0x158, 0x2b, 0}, ++ {0x159, 0x84, 0}, ++ {0x15A, 0x15, 0}, ++ {0x15B, 0xf, 0}, ++ {0x15C, 0, 0}, ++ {0x15D, 0, 0}, ++ {0x15E, 0, 1}, ++ {0x15F, 0, 1}, ++ {0x160, 0, 1}, ++ {0x161, 0, 1}, ++ {0x162, 0, 1}, ++ {0x163, 0, 1}, ++ {0x164, 0, 0}, ++ {0x165, 0, 0}, ++ {0x166, 0, 0}, ++ {0x167, 0, 0}, ++ {0x168, 0, 0}, ++ {0x169, 0x2, 1}, ++ {0x16A, 0, 1}, ++ {0x16B, 0, 1}, ++ {0x16C, 0, 1}, ++ {0x16D, 0, 0}, ++ {0x170, 0, 0}, ++ {0x171, 0x77, 0}, ++ {0x172, 0x77, 0}, ++ {0x173, 0x77, 0}, ++ {0x174, 0x77, 0}, ++ {0x175, 0, 0}, ++ {0x176, 0x3, 0}, ++ {0x177, 0x37, 0}, ++ {0x178, 0x3, 0}, ++ {0x179, 0, 0}, ++ {0x17A, 0x21, 0}, ++ {0x17B, 0x21, 0}, ++ {0x17C, 0, 0}, ++ {0x17D, 0xaa, 0}, ++ {0x17E, 0, 0}, ++ {0x17F, 0xaa, 0}, ++ {0x180, 0, 0}, ++ {0x190, 0, 0}, ++ {0x191, 0x77, 0}, ++ {0x192, 0x77, 0}, ++ {0x193, 0x77, 0}, ++ {0x194, 0x77, 0}, ++ {0x195, 0, 0}, ++ {0x196, 0x3, 0}, ++ {0x197, 0x37, 0}, ++ {0x198, 0x3, 0}, ++ {0x199, 0, 0}, ++ {0x19A, 0x21, 0}, ++ {0x19B, 0x21, 0}, ++ {0x19C, 0, 0}, ++ {0x19D, 0xaa, 0}, ++ {0x19E, 0, 0}, ++ {0x19F, 0xaa, 0}, ++ {0x1A0, 0, 0}, ++ {0x1A1, 0x2, 0}, ++ {0x1A2, 0xf, 0}, ++ {0x1A3, 0xf, 0}, ++ {0x1A4, 0, 1}, ++ {0x1A5, 0, 1}, ++ {0x1A6, 0, 1}, ++ {0x1A7, 0x2, 0}, ++ {0x1A8, 0xf, 0}, ++ {0x1A9, 0xf, 0}, ++ {0x1AA, 0, 1}, ++ {0x1AB, 0, 1}, ++ {0x1AC, 0, 1}, ++ {0xFFFF, 0, 0}, ++}; ++ ++static struct radio_20xx_regs regs_2057_rev5[] = { ++ {0x00, 0, 1}, ++ {0x01, 0x57, 1}, ++ {0x02, 0x20, 1}, ++ {0x03, 0x1f, 0}, ++ {0x04, 0x4, 0}, ++ {0x05, 0x2, 0}, ++ {0x06, 0x1, 0}, ++ {0x07, 0x1, 0}, ++ {0x08, 0x1, 0}, ++ {0x09, 0x69, 0}, ++ {0x0A, 0x66, 0}, ++ {0x0B, 0x6, 0}, ++ {0x0C, 0x18, 0}, ++ {0x0D, 0x3, 0}, ++ {0x0E, 0x20, 0}, ++ {0x0F, 0x20, 0}, ++ {0x10, 0, 0}, ++ {0x11, 0x7c, 0}, ++ {0x12, 0x42, 0}, ++ {0x13, 0xbd, 0}, ++ {0x14, 0x7, 0}, ++ {0x15, 0x87, 0}, ++ {0x16, 0x8, 0}, ++ {0x17, 0x17, 0}, ++ {0x18, 0x7, 0}, ++ {0x19, 0, 0}, ++ {0x1A, 0x2, 0}, ++ {0x1B, 0x13, 0}, ++ {0x1C, 0x3e, 0}, ++ {0x1D, 0x3e, 0}, ++ {0x1E, 0x96, 0}, ++ {0x1F, 0x4, 0}, ++ {0x20, 0, 0}, ++ {0x21, 0, 0}, ++ {0x22, 0x17, 0}, ++ {0x23, 0x6, 1}, ++ {0x24, 0x1, 0}, ++ {0x25, 0x6, 0}, ++ {0x26, 0x4, 0}, ++ {0x27, 0xd, 0}, ++ {0x28, 0xd, 0}, ++ {0x29, 0x30, 0}, ++ {0x2A, 0x32, 0}, ++ {0x2B, 0x8, 0}, ++ {0x2C, 0x1c, 0}, ++ {0x2D, 0x2, 0}, ++ {0x2E, 0x4, 0}, ++ {0x2F, 0x7f, 0}, ++ {0x30, 0x27, 0}, ++ {0x31, 0, 1}, ++ {0x32, 0, 1}, ++ {0x33, 0, 1}, ++ {0x34, 0, 0}, ++ {0x35, 0x20, 0}, ++ {0x36, 0x18, 0}, ++ {0x37, 0x7, 0}, ++ {0x38, 0x66, 0}, ++ {0x39, 0x66, 0}, ++ {0x3C, 0xff, 0}, ++ {0x3D, 0xff, 0}, ++ {0x40, 0x16, 0}, ++ {0x41, 0x7, 0}, ++ {0x45, 0x3, 0}, ++ {0x46, 0x1, 0}, ++ {0x47, 0x7, 0}, ++ {0x4B, 0x66, 0}, ++ {0x4C, 0x66, 0}, ++ {0x4D, 0, 0}, ++ {0x4E, 0x4, 0}, ++ {0x4F, 0xc, 0}, ++ {0x50, 0, 0}, ++ {0x51, 0x70, 1}, ++ {0x56, 0x7, 0}, ++ {0x57, 0, 0}, ++ {0x58, 0, 0}, ++ {0x59, 0x88, 1}, ++ {0x5A, 0, 0}, ++ {0x5B, 0x1f, 0}, ++ {0x5C, 0x20, 1}, ++ {0x5D, 0x1, 0}, ++ {0x5E, 0x30, 0}, ++ {0x5F, 0x70, 0}, ++ {0x60, 0, 0}, ++ {0x61, 0, 0}, ++ {0x62, 0x33, 1}, ++ {0x63, 0xf, 1}, ++ {0x64, 0xf, 1}, ++ {0x65, 0, 0}, ++ {0x66, 0x11, 0}, ++ {0x80, 0x3c, 0}, ++ {0x81, 0x1, 1}, ++ {0x82, 0xa, 0}, ++ {0x85, 0, 0}, ++ {0x86, 0x40, 0}, ++ {0x87, 0x40, 0}, ++ {0x88, 0x88, 0}, ++ {0x89, 0x10, 0}, ++ {0x8A, 0xf0, 0}, ++ {0x8B, 0x10, 0}, ++ {0x8C, 0xf0, 0}, ++ {0x8F, 0x10, 0}, ++ {0x90, 0x55, 0}, ++ {0x91, 0x3f, 1}, ++ {0x92, 0x36, 1}, ++ {0x93, 0, 0}, ++ {0x94, 0, 0}, ++ {0x95, 0, 0}, ++ {0x96, 0x87, 0}, ++ {0x97, 0x11, 0}, ++ {0x98, 0, 0}, ++ {0x99, 0x33, 0}, ++ {0x9A, 0x88, 0}, ++ {0xA1, 0x20, 1}, ++ {0xA2, 0x3f, 0}, ++ {0xA3, 0x44, 0}, ++ {0xA4, 0x8c, 0}, ++ {0xA5, 0x6c, 0}, ++ {0xA6, 0x22, 0}, ++ {0xA7, 0xbe, 0}, ++ {0xA8, 0x55, 0}, ++ {0xAA, 0xc, 0}, ++ {0xAB, 0xaa, 0}, ++ {0xAC, 0x2, 0}, ++ {0xAD, 0, 0}, ++ {0xAE, 0x10, 0}, ++ {0xAF, 0x1, 0}, ++ {0xB0, 0, 0}, ++ {0xB1, 0, 0}, ++ {0xB2, 0x80, 0}, ++ {0xB3, 0x60, 0}, ++ {0xB4, 0x44, 0}, ++ {0xB5, 0x55, 0}, ++ {0xB6, 0x1, 0}, ++ {0xB7, 0x55, 0}, ++ {0xB8, 0x1, 0}, ++ {0xB9, 0x5, 0}, ++ {0xBA, 0x55, 0}, ++ {0xBB, 0x55, 0}, ++ {0xC3, 0, 0}, ++ {0xC4, 0, 0}, ++ {0xC5, 0, 0}, ++ {0xC6, 0, 0}, ++ {0xC7, 0, 0}, ++ {0xC8, 0, 0}, ++ {0xC9, 0, 0}, ++ {0xCA, 0, 0}, ++ {0xCB, 0, 0}, ++ {0xCD, 0, 0}, ++ {0xCE, 0x5e, 0}, ++ {0xCF, 0xc, 0}, ++ {0xD0, 0xc, 0}, ++ {0xD1, 0xc, 0}, ++ {0xD2, 0, 0}, ++ {0xD3, 0x2b, 0}, ++ {0xD4, 0xc, 0}, ++ {0xD5, 0, 0}, ++ {0xD6, 0x70, 1}, ++ {0xDB, 0x7, 0}, ++ {0xDC, 0, 0}, ++ {0xDD, 0, 0}, ++ {0xDE, 0x88, 1}, ++ {0xDF, 0, 0}, ++ {0xE0, 0x1f, 0}, ++ {0xE1, 0x20, 1}, ++ {0xE2, 0x1, 0}, ++ {0xE3, 0x30, 0}, ++ {0xE4, 0x70, 0}, ++ {0xE5, 0, 0}, ++ {0xE6, 0, 0}, ++ {0xE7, 0x33, 0}, ++ {0xE8, 0xf, 1}, ++ {0xE9, 0xf, 1}, ++ {0xEA, 0, 0}, ++ {0xEB, 0x11, 0}, ++ {0x105, 0x3c, 0}, ++ {0x106, 0x1, 1}, ++ {0x107, 0xa, 0}, ++ {0x10A, 0, 0}, ++ {0x10B, 0x40, 0}, ++ {0x10C, 0x40, 0}, ++ {0x10D, 0x88, 0}, ++ {0x10E, 0x10, 0}, ++ {0x10F, 0xf0, 0}, ++ {0x110, 0x10, 0}, ++ {0x111, 0xf0, 0}, ++ {0x114, 0x10, 0}, ++ {0x115, 0x55, 0}, ++ {0x116, 0x3f, 1}, ++ {0x117, 0x36, 1}, ++ {0x118, 0, 0}, ++ {0x119, 0, 0}, ++ {0x11A, 0, 0}, ++ {0x11B, 0x87, 0}, ++ {0x11C, 0x11, 0}, ++ {0x11D, 0, 0}, ++ {0x11E, 0x33, 0}, ++ {0x11F, 0x88, 0}, ++ {0x126, 0x20, 1}, ++ {0x127, 0x3f, 0}, ++ {0x128, 0x44, 0}, ++ {0x129, 0x8c, 0}, ++ {0x12A, 0x6c, 0}, ++ {0x12B, 0x22, 0}, ++ {0x12C, 0xbe, 0}, ++ {0x12D, 0x55, 0}, ++ {0x12F, 0xc, 0}, ++ {0x130, 0xaa, 0}, ++ {0x131, 0x2, 0}, ++ {0x132, 0, 0}, ++ {0x133, 0x10, 0}, ++ {0x134, 0x1, 0}, ++ {0x135, 0, 0}, ++ {0x136, 0, 0}, ++ {0x137, 0x80, 0}, ++ {0x138, 0x60, 0}, ++ {0x139, 0x44, 0}, ++ {0x13A, 0x55, 0}, ++ {0x13B, 0x1, 0}, ++ {0x13C, 0x55, 0}, ++ {0x13D, 0x1, 0}, ++ {0x13E, 0x5, 0}, ++ {0x13F, 0x55, 0}, ++ {0x140, 0x55, 0}, ++ {0x148, 0, 0}, ++ {0x149, 0, 0}, ++ {0x14A, 0, 0}, ++ {0x14B, 0, 0}, ++ {0x14C, 0, 0}, ++ {0x14D, 0, 0}, ++ {0x14E, 0, 0}, ++ {0x14F, 0, 0}, ++ {0x150, 0, 0}, ++ {0x154, 0xc, 0}, ++ {0x155, 0xc, 0}, ++ {0x156, 0xc, 0}, ++ {0x157, 0, 0}, ++ {0x158, 0x2b, 0}, ++ {0x159, 0x84, 0}, ++ {0x15A, 0x15, 0}, ++ {0x15B, 0xf, 0}, ++ {0x15C, 0, 0}, ++ {0x15D, 0, 0}, ++ {0x15E, 0, 1}, ++ {0x15F, 0, 1}, ++ {0x160, 0, 1}, ++ {0x161, 0, 1}, ++ {0x162, 0, 1}, ++ {0x163, 0, 1}, ++ {0x164, 0, 0}, ++ {0x165, 0, 0}, ++ {0x166, 0, 0}, ++ {0x167, 0, 0}, ++ {0x168, 0, 0}, ++ {0x169, 0, 0}, ++ {0x16A, 0, 1}, ++ {0x16B, 0, 1}, ++ {0x16C, 0, 1}, ++ {0x16D, 0, 0}, ++ {0x170, 0, 0}, ++ {0x171, 0x77, 0}, ++ {0x172, 0x77, 0}, ++ {0x173, 0x77, 0}, ++ {0x174, 0x77, 0}, ++ {0x175, 0, 0}, ++ {0x176, 0x3, 0}, ++ {0x177, 0x37, 0}, ++ {0x178, 0x3, 0}, ++ {0x179, 0, 0}, ++ {0x17B, 0x21, 0}, ++ {0x17C, 0, 0}, ++ {0x17D, 0xaa, 0}, ++ {0x17E, 0, 0}, ++ {0x190, 0, 0}, ++ {0x191, 0x77, 0}, ++ {0x192, 0x77, 0}, ++ {0x193, 0x77, 0}, ++ {0x194, 0x77, 0}, ++ {0x195, 0, 0}, ++ {0x196, 0x3, 0}, ++ {0x197, 0x37, 0}, ++ {0x198, 0x3, 0}, ++ {0x199, 0, 0}, ++ {0x19B, 0x21, 0}, ++ {0x19C, 0, 0}, ++ {0x19D, 0xaa, 0}, ++ {0x19E, 0, 0}, ++ {0x1A1, 0x2, 0}, ++ {0x1A2, 0xf, 0}, ++ {0x1A3, 0xf, 0}, ++ {0x1A4, 0, 1}, ++ {0x1A5, 0, 1}, ++ {0x1A6, 0, 1}, ++ {0x1A7, 0x2, 0}, ++ {0x1A8, 0xf, 0}, ++ {0x1A9, 0xf, 0}, ++ {0x1AA, 0, 1}, ++ {0x1AB, 0, 1}, ++ {0x1AC, 0, 1}, ++ {0x1AD, 0x84, 0}, ++ {0x1AE, 0x60, 0}, ++ {0x1AF, 0x47, 0}, ++ {0x1B0, 0x47, 0}, ++ {0x1B1, 0, 0}, ++ {0x1B2, 0, 0}, ++ {0x1B3, 0, 0}, ++ {0x1B4, 0, 0}, ++ {0x1B5, 0, 0}, ++ {0x1B6, 0, 0}, ++ {0x1B7, 0xc, 1}, ++ {0x1B8, 0, 0}, ++ {0x1B9, 0, 0}, ++ {0x1BA, 0, 0}, ++ {0x1BB, 0, 0}, ++ {0x1BC, 0, 0}, ++ {0x1BD, 0, 0}, ++ {0x1BE, 0, 0}, ++ {0x1BF, 0, 0}, ++ {0x1C0, 0, 0}, ++ {0x1C1, 0x1, 1}, ++ {0x1C2, 0x80, 1}, ++ {0x1C3, 0, 0}, ++ {0x1C4, 0, 0}, ++ {0x1C5, 0, 0}, ++ {0x1C6, 0, 0}, ++ {0x1C7, 0, 0}, ++ {0x1C8, 0, 0}, ++ {0x1C9, 0, 0}, ++ {0x1CA, 0, 0}, ++ {0xFFFF, 0, 0} ++}; ++ ++static struct radio_20xx_regs regs_2057_rev5v1[] = { ++ {0x00, 0x15, 1}, ++ {0x01, 0x57, 1}, ++ {0x02, 0x20, 1}, ++ {0x03, 0x1f, 0}, ++ {0x04, 0x4, 0}, ++ {0x05, 0x2, 0}, ++ {0x06, 0x1, 0}, ++ {0x07, 0x1, 0}, ++ {0x08, 0x1, 0}, ++ {0x09, 0x69, 0}, ++ {0x0A, 0x66, 0}, ++ {0x0B, 0x6, 0}, ++ {0x0C, 0x18, 0}, ++ {0x0D, 0x3, 0}, ++ {0x0E, 0x20, 0}, ++ {0x0F, 0x20, 0}, ++ {0x10, 0, 0}, ++ {0x11, 0x7c, 0}, ++ {0x12, 0x42, 0}, ++ {0x13, 0xbd, 0}, ++ {0x14, 0x7, 0}, ++ {0x15, 0x87, 0}, ++ {0x16, 0x8, 0}, ++ {0x17, 0x17, 0}, ++ {0x18, 0x7, 0}, ++ {0x19, 0, 0}, ++ {0x1A, 0x2, 0}, ++ {0x1B, 0x13, 0}, ++ {0x1C, 0x3e, 0}, ++ {0x1D, 0x3e, 0}, ++ {0x1E, 0x96, 0}, ++ {0x1F, 0x4, 0}, ++ {0x20, 0, 0}, ++ {0x21, 0, 0}, ++ {0x22, 0x17, 0}, ++ {0x23, 0x6, 1}, ++ {0x24, 0x1, 0}, ++ {0x25, 0x6, 0}, ++ {0x26, 0x4, 0}, ++ {0x27, 0xd, 0}, ++ {0x28, 0xd, 0}, ++ {0x29, 0x30, 0}, ++ {0x2A, 0x32, 0}, ++ {0x2B, 0x8, 0}, ++ {0x2C, 0x1c, 0}, ++ {0x2D, 0x2, 0}, ++ {0x2E, 0x4, 0}, ++ {0x2F, 0x7f, 0}, ++ {0x30, 0x27, 0}, ++ {0x31, 0, 1}, ++ {0x32, 0, 1}, ++ {0x33, 0, 1}, ++ {0x34, 0, 0}, ++ {0x35, 0x20, 0}, ++ {0x36, 0x18, 0}, ++ {0x37, 0x7, 0}, ++ {0x38, 0x66, 0}, ++ {0x39, 0x66, 0}, ++ {0x3C, 0xff, 0}, ++ {0x3D, 0xff, 0}, ++ {0x40, 0x16, 0}, ++ {0x41, 0x7, 0}, ++ {0x45, 0x3, 0}, ++ {0x46, 0x1, 0}, ++ {0x47, 0x7, 0}, ++ {0x4B, 0x66, 0}, ++ {0x4C, 0x66, 0}, ++ {0x4D, 0, 0}, ++ {0x4E, 0x4, 0}, ++ {0x4F, 0xc, 0}, ++ {0x50, 0, 0}, ++ {0x51, 0x70, 1}, ++ {0x56, 0x7, 0}, ++ {0x57, 0, 0}, ++ {0x58, 0, 0}, ++ {0x59, 0x88, 1}, ++ {0x5A, 0, 0}, ++ {0x5B, 0x1f, 0}, ++ {0x5C, 0x20, 1}, ++ {0x5D, 0x1, 0}, ++ {0x5E, 0x30, 0}, ++ {0x5F, 0x70, 0}, ++ {0x60, 0, 0}, ++ {0x61, 0, 0}, ++ {0x62, 0x33, 1}, ++ {0x63, 0xf, 1}, ++ {0x64, 0xf, 1}, ++ {0x65, 0, 0}, ++ {0x66, 0x11, 0}, ++ {0x80, 0x3c, 0}, ++ {0x81, 0x1, 1}, ++ {0x82, 0xa, 0}, ++ {0x85, 0, 0}, ++ {0x86, 0x40, 0}, ++ {0x87, 0x40, 0}, ++ {0x88, 0x88, 0}, ++ {0x89, 0x10, 0}, ++ {0x8A, 0xf0, 0}, ++ {0x8B, 0x10, 0}, ++ {0x8C, 0xf0, 0}, ++ {0x8F, 0x10, 0}, ++ {0x90, 0x55, 0}, ++ {0x91, 0x3f, 1}, ++ {0x92, 0x36, 1}, ++ {0x93, 0, 0}, ++ {0x94, 0, 0}, ++ {0x95, 0, 0}, ++ {0x96, 0x87, 0}, ++ {0x97, 0x11, 0}, ++ {0x98, 0, 0}, ++ {0x99, 0x33, 0}, ++ {0x9A, 0x88, 0}, ++ {0xA1, 0x20, 1}, ++ {0xA2, 0x3f, 0}, ++ {0xA3, 0x44, 0}, ++ {0xA4, 0x8c, 0}, ++ {0xA5, 0x6c, 0}, ++ {0xA6, 0x22, 0}, ++ {0xA7, 0xbe, 0}, ++ {0xA8, 0x55, 0}, ++ {0xAA, 0xc, 0}, ++ {0xAB, 0xaa, 0}, ++ {0xAC, 0x2, 0}, ++ {0xAD, 0, 0}, ++ {0xAE, 0x10, 0}, ++ {0xAF, 0x1, 0}, ++ {0xB0, 0, 0}, ++ {0xB1, 0, 0}, ++ {0xB2, 0x80, 0}, ++ {0xB3, 0x60, 0}, ++ {0xB4, 0x44, 0}, ++ {0xB5, 0x55, 0}, ++ {0xB6, 0x1, 0}, ++ {0xB7, 0x55, 0}, ++ {0xB8, 0x1, 0}, ++ {0xB9, 0x5, 0}, ++ {0xBA, 0x55, 0}, ++ {0xBB, 0x55, 0}, ++ {0xC3, 0, 0}, ++ {0xC4, 0, 0}, ++ {0xC5, 0, 0}, ++ {0xC6, 0, 0}, ++ {0xC7, 0, 0}, ++ {0xC8, 0, 0}, ++ {0xC9, 0x1, 1}, ++ {0xCA, 0, 0}, ++ {0xCB, 0, 0}, ++ {0xCD, 0, 0}, ++ {0xCE, 0x5e, 0}, ++ {0xCF, 0xc, 0}, ++ {0xD0, 0xc, 0}, ++ {0xD1, 0xc, 0}, ++ {0xD2, 0, 0}, ++ {0xD3, 0x2b, 0}, ++ {0xD4, 0xc, 0}, ++ {0xD5, 0, 0}, ++ {0xD6, 0x70, 1}, ++ {0xDB, 0x7, 0}, ++ {0xDC, 0, 0}, ++ {0xDD, 0, 0}, ++ {0xDE, 0x88, 1}, ++ {0xDF, 0, 0}, ++ {0xE0, 0x1f, 0}, ++ {0xE1, 0x20, 1}, ++ {0xE2, 0x1, 0}, ++ {0xE3, 0x30, 0}, ++ {0xE4, 0x70, 0}, ++ {0xE5, 0, 0}, ++ {0xE6, 0, 0}, ++ {0xE7, 0x33, 0}, ++ {0xE8, 0xf, 1}, ++ {0xE9, 0xf, 1}, ++ {0xEA, 0, 0}, ++ {0xEB, 0x11, 0}, ++ {0x105, 0x3c, 0}, ++ {0x106, 0x1, 1}, ++ {0x107, 0xa, 0}, ++ {0x10A, 0, 0}, ++ {0x10B, 0x40, 0}, ++ {0x10C, 0x40, 0}, ++ {0x10D, 0x88, 0}, ++ {0x10E, 0x10, 0}, ++ {0x10F, 0xf0, 0}, ++ {0x110, 0x10, 0}, ++ {0x111, 0xf0, 0}, ++ {0x114, 0x10, 0}, ++ {0x115, 0x55, 0}, ++ {0x116, 0x3f, 1}, ++ {0x117, 0x36, 1}, ++ {0x118, 0, 0}, ++ {0x119, 0, 0}, ++ {0x11A, 0, 0}, ++ {0x11B, 0x87, 0}, ++ {0x11C, 0x11, 0}, ++ {0x11D, 0, 0}, ++ {0x11E, 0x33, 0}, ++ {0x11F, 0x88, 0}, ++ {0x126, 0x20, 1}, ++ {0x127, 0x3f, 0}, ++ {0x128, 0x44, 0}, ++ {0x129, 0x8c, 0}, ++ {0x12A, 0x6c, 0}, ++ {0x12B, 0x22, 0}, ++ {0x12C, 0xbe, 0}, ++ {0x12D, 0x55, 0}, ++ {0x12F, 0xc, 0}, ++ {0x130, 0xaa, 0}, ++ {0x131, 0x2, 0}, ++ {0x132, 0, 0}, ++ {0x133, 0x10, 0}, ++ {0x134, 0x1, 0}, ++ {0x135, 0, 0}, ++ {0x136, 0, 0}, ++ {0x137, 0x80, 0}, ++ {0x138, 0x60, 0}, ++ {0x139, 0x44, 0}, ++ {0x13A, 0x55, 0}, ++ {0x13B, 0x1, 0}, ++ {0x13C, 0x55, 0}, ++ {0x13D, 0x1, 0}, ++ {0x13E, 0x5, 0}, ++ {0x13F, 0x55, 0}, ++ {0x140, 0x55, 0}, ++ {0x148, 0, 0}, ++ {0x149, 0, 0}, ++ {0x14A, 0, 0}, ++ {0x14B, 0, 0}, ++ {0x14C, 0, 0}, ++ {0x14D, 0, 0}, ++ {0x14E, 0x1, 1}, ++ {0x14F, 0, 0}, ++ {0x150, 0, 0}, ++ {0x154, 0xc, 0}, ++ {0x155, 0xc, 0}, ++ {0x156, 0xc, 0}, ++ {0x157, 0, 0}, ++ {0x158, 0x2b, 0}, ++ {0x159, 0x84, 0}, ++ {0x15A, 0x15, 0}, ++ {0x15B, 0xf, 0}, ++ {0x15C, 0, 0}, ++ {0x15D, 0, 0}, ++ {0x15E, 0, 1}, ++ {0x15F, 0, 1}, ++ {0x160, 0, 1}, ++ {0x161, 0, 1}, ++ {0x162, 0, 1}, ++ {0x163, 0, 1}, ++ {0x164, 0, 0}, ++ {0x165, 0, 0}, ++ {0x166, 0, 0}, ++ {0x167, 0, 0}, ++ {0x168, 0, 0}, ++ {0x169, 0, 0}, ++ {0x16A, 0, 1}, ++ {0x16B, 0, 1}, ++ {0x16C, 0, 1}, ++ {0x16D, 0, 0}, ++ {0x170, 0, 0}, ++ {0x171, 0x77, 0}, ++ {0x172, 0x77, 0}, ++ {0x173, 0x77, 0}, ++ {0x174, 0x77, 0}, ++ {0x175, 0, 0}, ++ {0x176, 0x3, 0}, ++ {0x177, 0x37, 0}, ++ {0x178, 0x3, 0}, ++ {0x179, 0, 0}, ++ {0x17B, 0x21, 0}, ++ {0x17C, 0, 0}, ++ {0x17D, 0xaa, 0}, ++ {0x17E, 0, 0}, ++ {0x190, 0, 0}, ++ {0x191, 0x77, 0}, ++ {0x192, 0x77, 0}, ++ {0x193, 0x77, 0}, ++ {0x194, 0x77, 0}, ++ {0x195, 0, 0}, ++ {0x196, 0x3, 0}, ++ {0x197, 0x37, 0}, ++ {0x198, 0x3, 0}, ++ {0x199, 0, 0}, ++ {0x19B, 0x21, 0}, ++ {0x19C, 0, 0}, ++ {0x19D, 0xaa, 0}, ++ {0x19E, 0, 0}, ++ {0x1A1, 0x2, 0}, ++ {0x1A2, 0xf, 0}, ++ {0x1A3, 0xf, 0}, ++ {0x1A4, 0, 1}, ++ {0x1A5, 0, 1}, ++ {0x1A6, 0, 1}, ++ {0x1A7, 0x2, 0}, ++ {0x1A8, 0xf, 0}, ++ {0x1A9, 0xf, 0}, ++ {0x1AA, 0, 1}, ++ {0x1AB, 0, 1}, ++ {0x1AC, 0, 1}, ++ {0x1AD, 0x84, 0}, ++ {0x1AE, 0x60, 0}, ++ {0x1AF, 0x47, 0}, ++ {0x1B0, 0x47, 0}, ++ {0x1B1, 0, 0}, ++ {0x1B2, 0, 0}, ++ {0x1B3, 0, 0}, ++ {0x1B4, 0, 0}, ++ {0x1B5, 0, 0}, ++ {0x1B6, 0, 0}, ++ {0x1B7, 0xc, 1}, ++ {0x1B8, 0, 0}, ++ {0x1B9, 0, 0}, ++ {0x1BA, 0, 0}, ++ {0x1BB, 0, 0}, ++ {0x1BC, 0, 0}, ++ {0x1BD, 0, 0}, ++ {0x1BE, 0, 0}, ++ {0x1BF, 0, 0}, ++ {0x1C0, 0, 0}, ++ {0x1C1, 0x1, 1}, ++ {0x1C2, 0x80, 1}, ++ {0x1C3, 0, 0}, ++ {0x1C4, 0, 0}, ++ {0x1C5, 0, 0}, ++ {0x1C6, 0, 0}, ++ {0x1C7, 0, 0}, ++ {0x1C8, 0, 0}, ++ {0x1C9, 0, 0}, ++ {0x1CA, 0, 0}, ++ {0xFFFF, 0, 0} ++}; ++ ++static struct radio_20xx_regs regs_2057_rev7[] = { ++ {0x00, 0, 1}, ++ {0x01, 0x57, 1}, ++ {0x02, 0x20, 1}, ++ {0x03, 0x1f, 0}, ++ {0x04, 0x4, 0}, ++ {0x05, 0x2, 0}, ++ {0x06, 0x1, 0}, ++ {0x07, 0x1, 0}, ++ {0x08, 0x1, 0}, ++ {0x09, 0x69, 0}, ++ {0x0A, 0x66, 0}, ++ {0x0B, 0x6, 0}, ++ {0x0C, 0x18, 0}, ++ {0x0D, 0x3, 0}, ++ {0x0E, 0x20, 0}, ++ {0x0F, 0x20, 0}, ++ {0x10, 0, 0}, ++ {0x11, 0x7c, 0}, ++ {0x12, 0x42, 0}, ++ {0x13, 0xbd, 0}, ++ {0x14, 0x7, 0}, ++ {0x15, 0x87, 0}, ++ {0x16, 0x8, 0}, ++ {0x17, 0x17, 0}, ++ {0x18, 0x7, 0}, ++ {0x19, 0, 0}, ++ {0x1A, 0x2, 0}, ++ {0x1B, 0x13, 0}, ++ {0x1C, 0x3e, 0}, ++ {0x1D, 0x3e, 0}, ++ {0x1E, 0x96, 0}, ++ {0x1F, 0x4, 0}, ++ {0x20, 0, 0}, ++ {0x21, 0, 0}, ++ {0x22, 0x17, 0}, ++ {0x23, 0x6, 0}, ++ {0x24, 0x1, 0}, ++ {0x25, 0x6, 0}, ++ {0x26, 0x4, 0}, ++ {0x27, 0xd, 0}, ++ {0x28, 0xd, 0}, ++ {0x29, 0x30, 0}, ++ {0x2A, 0x32, 0}, ++ {0x2B, 0x8, 0}, ++ {0x2C, 0x1c, 0}, ++ {0x2D, 0x2, 0}, ++ {0x2E, 0x4, 0}, ++ {0x2F, 0x7f, 0}, ++ {0x30, 0x27, 0}, ++ {0x31, 0, 1}, ++ {0x32, 0, 1}, ++ {0x33, 0, 1}, ++ {0x34, 0, 0}, ++ {0x35, 0x20, 0}, ++ {0x36, 0x18, 0}, ++ {0x37, 0x7, 0}, ++ {0x38, 0x66, 0}, ++ {0x39, 0x66, 0}, ++ {0x3A, 0x66, 0}, ++ {0x3B, 0x66, 0}, ++ {0x3C, 0xff, 0}, ++ {0x3D, 0xff, 0}, ++ {0x3E, 0xff, 0}, ++ {0x3F, 0xff, 0}, ++ {0x40, 0x16, 0}, ++ {0x41, 0x7, 0}, ++ {0x42, 0x19, 0}, ++ {0x43, 0x7, 0}, ++ {0x44, 0x6, 0}, ++ {0x45, 0x3, 0}, ++ {0x46, 0x1, 0}, ++ {0x47, 0x7, 0}, ++ {0x48, 0x33, 0}, ++ {0x49, 0x5, 0}, ++ {0x4A, 0x77, 0}, ++ {0x4B, 0x66, 0}, ++ {0x4C, 0x66, 0}, ++ {0x4D, 0, 0}, ++ {0x4E, 0x4, 0}, ++ {0x4F, 0xc, 0}, ++ {0x50, 0, 0}, ++ {0x51, 0x70, 1}, ++ {0x56, 0x7, 0}, ++ {0x57, 0, 0}, ++ {0x58, 0, 0}, ++ {0x59, 0x88, 1}, ++ {0x5A, 0, 0}, ++ {0x5B, 0x1f, 0}, ++ {0x5C, 0x20, 1}, ++ {0x5D, 0x1, 0}, ++ {0x5E, 0x30, 0}, ++ {0x5F, 0x70, 0}, ++ {0x60, 0, 0}, ++ {0x61, 0, 0}, ++ {0x62, 0x33, 1}, ++ {0x63, 0xf, 1}, ++ {0x64, 0x13, 1}, ++ {0x65, 0, 0}, ++ {0x66, 0xee, 1}, ++ {0x69, 0, 0}, ++ {0x6A, 0x7e, 0}, ++ {0x6B, 0x3f, 0}, ++ {0x6C, 0x7f, 0}, ++ {0x6D, 0x78, 0}, ++ {0x6E, 0x58, 1}, ++ {0x6F, 0x88, 0}, ++ {0x70, 0x8, 0}, ++ {0x71, 0xf, 0}, ++ {0x72, 0xbc, 0}, ++ {0x73, 0x8, 0}, ++ {0x74, 0x60, 0}, ++ {0x75, 0x13, 1}, ++ {0x76, 0x70, 0}, ++ {0x77, 0, 0}, ++ {0x78, 0, 0}, ++ {0x79, 0, 0}, ++ {0x7A, 0x33, 0}, ++ {0x7B, 0x13, 1}, ++ {0x7C, 0x14, 1}, ++ {0x7D, 0xee, 1}, ++ {0x80, 0x3c, 0}, ++ {0x81, 0x1, 1}, ++ {0x82, 0xa, 0}, ++ {0x83, 0x9d, 0}, ++ {0x84, 0xa, 0}, ++ {0x85, 0, 0}, ++ {0x86, 0x40, 0}, ++ {0x87, 0x40, 0}, ++ {0x88, 0x88, 0}, ++ {0x89, 0x10, 0}, ++ {0x8A, 0xf0, 0}, ++ {0x8B, 0x10, 0}, ++ {0x8C, 0xf0, 0}, ++ {0x8D, 0, 0}, ++ {0x8E, 0, 0}, ++ {0x8F, 0x10, 0}, ++ {0x90, 0x55, 0}, ++ {0x91, 0x3f, 1}, ++ {0x92, 0x36, 1}, ++ {0x93, 0, 0}, ++ {0x94, 0, 0}, ++ {0x95, 0, 0}, ++ {0x96, 0x87, 0}, ++ {0x97, 0x11, 0}, ++ {0x98, 0, 0}, ++ {0x99, 0x33, 0}, ++ {0x9A, 0x88, 0}, ++ {0x9B, 0, 0}, ++ {0x9C, 0x87, 0}, ++ {0x9D, 0x11, 0}, ++ {0x9E, 0, 0}, ++ {0x9F, 0x33, 0}, ++ {0xA0, 0x88, 0}, ++ {0xA1, 0x20, 1}, ++ {0xA2, 0x3f, 0}, ++ {0xA3, 0x44, 0}, ++ {0xA4, 0x8c, 0}, ++ {0xA5, 0x6c, 0}, ++ {0xA6, 0x22, 0}, ++ {0xA7, 0xbe, 0}, ++ {0xA8, 0x55, 0}, ++ {0xAA, 0xc, 0}, ++ {0xAB, 0xaa, 0}, ++ {0xAC, 0x2, 0}, ++ {0xAD, 0, 0}, ++ {0xAE, 0x10, 0}, ++ {0xAF, 0x1, 0}, ++ {0xB0, 0, 0}, ++ {0xB1, 0, 0}, ++ {0xB2, 0x80, 0}, ++ {0xB3, 0x60, 0}, ++ {0xB4, 0x44, 0}, ++ {0xB5, 0x55, 0}, ++ {0xB6, 0x1, 0}, ++ {0xB7, 0x55, 0}, ++ {0xB8, 0x1, 0}, ++ {0xB9, 0x5, 0}, ++ {0xBA, 0x55, 0}, ++ {0xBB, 0x55, 0}, ++ {0xC1, 0, 0}, ++ {0xC2, 0, 0}, ++ {0xC3, 0, 0}, ++ {0xC4, 0, 0}, ++ {0xC5, 0, 0}, ++ {0xC6, 0, 0}, ++ {0xC7, 0, 0}, ++ {0xC8, 0, 0}, ++ {0xC9, 0, 0}, ++ {0xCA, 0, 0}, ++ {0xCB, 0, 0}, ++ {0xCC, 0, 0}, ++ {0xCD, 0, 0}, ++ {0xCE, 0x5e, 0}, ++ {0xCF, 0xc, 0}, ++ {0xD0, 0xc, 0}, ++ {0xD1, 0xc, 0}, ++ {0xD2, 0, 0}, ++ {0xD3, 0x2b, 0}, ++ {0xD4, 0xc, 0}, ++ {0xD5, 0, 0}, ++ {0xD6, 0x70, 1}, ++ {0xDB, 0x7, 0}, ++ {0xDC, 0, 0}, ++ {0xDD, 0, 0}, ++ {0xDE, 0x88, 1}, ++ {0xDF, 0, 0}, ++ {0xE0, 0x1f, 0}, ++ {0xE1, 0x20, 1}, ++ {0xE2, 0x1, 0}, ++ {0xE3, 0x30, 0}, ++ {0xE4, 0x70, 0}, ++ {0xE5, 0, 0}, ++ {0xE6, 0, 0}, ++ {0xE7, 0x33, 0}, ++ {0xE8, 0xf, 1}, ++ {0xE9, 0x13, 1}, ++ {0xEA, 0, 0}, ++ {0xEB, 0xee, 1}, ++ {0xEE, 0, 0}, ++ {0xEF, 0x7e, 0}, ++ {0xF0, 0x3f, 0}, ++ {0xF1, 0x7f, 0}, ++ {0xF2, 0x78, 0}, ++ {0xF3, 0x58, 1}, ++ {0xF4, 0x88, 0}, ++ {0xF5, 0x8, 0}, ++ {0xF6, 0xf, 0}, ++ {0xF7, 0xbc, 0}, ++ {0xF8, 0x8, 0}, ++ {0xF9, 0x60, 0}, ++ {0xFA, 0x13, 1}, ++ {0xFB, 0x70, 0}, ++ {0xFC, 0, 0}, ++ {0xFD, 0, 0}, ++ {0xFE, 0, 0}, ++ {0xFF, 0x33, 0}, ++ {0x100, 0x13, 1}, ++ {0x101, 0x14, 1}, ++ {0x102, 0xee, 1}, ++ {0x105, 0x3c, 0}, ++ {0x106, 0x1, 1}, ++ {0x107, 0xa, 0}, ++ {0x108, 0x9d, 0}, ++ {0x109, 0xa, 0}, ++ {0x10A, 0, 0}, ++ {0x10B, 0x40, 0}, ++ {0x10C, 0x40, 0}, ++ {0x10D, 0x88, 0}, ++ {0x10E, 0x10, 0}, ++ {0x10F, 0xf0, 0}, ++ {0x110, 0x10, 0}, ++ {0x111, 0xf0, 0}, ++ {0x112, 0, 0}, ++ {0x113, 0, 0}, ++ {0x114, 0x10, 0}, ++ {0x115, 0x55, 0}, ++ {0x116, 0x3f, 1}, ++ {0x117, 0x36, 1}, ++ {0x118, 0, 0}, ++ {0x119, 0, 0}, ++ {0x11A, 0, 0}, ++ {0x11B, 0x87, 0}, ++ {0x11C, 0x11, 0}, ++ {0x11D, 0, 0}, ++ {0x11E, 0x33, 0}, ++ {0x11F, 0x88, 0}, ++ {0x120, 0, 0}, ++ {0x121, 0x87, 0}, ++ {0x122, 0x11, 0}, ++ {0x123, 0, 0}, ++ {0x124, 0x33, 0}, ++ {0x125, 0x88, 0}, ++ {0x126, 0x20, 1}, ++ {0x127, 0x3f, 0}, ++ {0x128, 0x44, 0}, ++ {0x129, 0x8c, 0}, ++ {0x12A, 0x6c, 0}, ++ {0x12B, 0x22, 0}, ++ {0x12C, 0xbe, 0}, ++ {0x12D, 0x55, 0}, ++ {0x12F, 0xc, 0}, ++ {0x130, 0xaa, 0}, ++ {0x131, 0x2, 0}, ++ {0x132, 0, 0}, ++ {0x133, 0x10, 0}, ++ {0x134, 0x1, 0}, ++ {0x135, 0, 0}, ++ {0x136, 0, 0}, ++ {0x137, 0x80, 0}, ++ {0x138, 0x60, 0}, ++ {0x139, 0x44, 0}, ++ {0x13A, 0x55, 0}, ++ {0x13B, 0x1, 0}, ++ {0x13C, 0x55, 0}, ++ {0x13D, 0x1, 0}, ++ {0x13E, 0x5, 0}, ++ {0x13F, 0x55, 0}, ++ {0x140, 0x55, 0}, ++ {0x146, 0, 0}, ++ {0x147, 0, 0}, ++ {0x148, 0, 0}, ++ {0x149, 0, 0}, ++ {0x14A, 0, 0}, ++ {0x14B, 0, 0}, ++ {0x14C, 0, 0}, ++ {0x14D, 0, 0}, ++ {0x14E, 0, 0}, ++ {0x14F, 0, 0}, ++ {0x150, 0, 0}, ++ {0x151, 0, 0}, ++ {0x154, 0xc, 0}, ++ {0x155, 0xc, 0}, ++ {0x156, 0xc, 0}, ++ {0x157, 0, 0}, ++ {0x158, 0x2b, 0}, ++ {0x159, 0x84, 0}, ++ {0x15A, 0x15, 0}, ++ {0x15B, 0xf, 0}, ++ {0x15C, 0, 0}, ++ {0x15D, 0, 0}, ++ {0x15E, 0, 1}, ++ {0x15F, 0, 1}, ++ {0x160, 0, 1}, ++ {0x161, 0, 1}, ++ {0x162, 0, 1}, ++ {0x163, 0, 1}, ++ {0x164, 0, 0}, ++ {0x165, 0, 0}, ++ {0x166, 0, 0}, ++ {0x167, 0, 0}, ++ {0x168, 0, 0}, ++ {0x169, 0, 0}, ++ {0x16A, 0, 1}, ++ {0x16B, 0, 1}, ++ {0x16C, 0, 1}, ++ {0x16D, 0, 0}, ++ {0x170, 0, 0}, ++ {0x171, 0x77, 0}, ++ {0x172, 0x77, 0}, ++ {0x173, 0x77, 0}, ++ {0x174, 0x77, 0}, ++ {0x175, 0, 0}, ++ {0x176, 0x3, 0}, ++ {0x177, 0x37, 0}, ++ {0x178, 0x3, 0}, ++ {0x179, 0, 0}, ++ {0x17A, 0x21, 0}, ++ {0x17B, 0x21, 0}, ++ {0x17C, 0, 0}, ++ {0x17D, 0xaa, 0}, ++ {0x17E, 0, 0}, ++ {0x17F, 0xaa, 0}, ++ {0x180, 0, 0}, ++ {0x190, 0, 0}, ++ {0x191, 0x77, 0}, ++ {0x192, 0x77, 0}, ++ {0x193, 0x77, 0}, ++ {0x194, 0x77, 0}, ++ {0x195, 0, 0}, ++ {0x196, 0x3, 0}, ++ {0x197, 0x37, 0}, ++ {0x198, 0x3, 0}, ++ {0x199, 0, 0}, ++ {0x19A, 0x21, 0}, ++ {0x19B, 0x21, 0}, ++ {0x19C, 0, 0}, ++ {0x19D, 0xaa, 0}, ++ {0x19E, 0, 0}, ++ {0x19F, 0xaa, 0}, ++ {0x1A0, 0, 0}, ++ {0x1A1, 0x2, 0}, ++ {0x1A2, 0xf, 0}, ++ {0x1A3, 0xf, 0}, ++ {0x1A4, 0, 1}, ++ {0x1A5, 0, 1}, ++ {0x1A6, 0, 1}, ++ {0x1A7, 0x2, 0}, ++ {0x1A8, 0xf, 0}, ++ {0x1A9, 0xf, 0}, ++ {0x1AA, 0, 1}, ++ {0x1AB, 0, 1}, ++ {0x1AC, 0, 1}, ++ {0x1AD, 0x84, 0}, ++ {0x1AE, 0x60, 0}, ++ {0x1AF, 0x47, 0}, ++ {0x1B0, 0x47, 0}, ++ {0x1B1, 0, 0}, ++ {0x1B2, 0, 0}, ++ {0x1B3, 0, 0}, ++ {0x1B4, 0, 0}, ++ {0x1B5, 0, 0}, ++ {0x1B6, 0, 0}, ++ {0x1B7, 0x5, 1}, ++ {0x1B8, 0, 0}, ++ {0x1B9, 0, 0}, ++ {0x1BA, 0, 0}, ++ {0x1BB, 0, 0}, ++ {0x1BC, 0, 0}, ++ {0x1BD, 0, 0}, ++ {0x1BE, 0, 0}, ++ {0x1BF, 0, 0}, ++ {0x1C0, 0, 0}, ++ {0x1C1, 0, 0}, ++ {0x1C2, 0xa0, 1}, ++ {0x1C3, 0, 0}, ++ {0x1C4, 0, 0}, ++ {0x1C5, 0, 0}, ++ {0x1C6, 0, 0}, ++ {0x1C7, 0, 0}, ++ {0x1C8, 0, 0}, ++ {0x1C9, 0, 0}, ++ {0x1CA, 0, 0}, ++ {0xFFFF, 0, 0} ++}; ++ ++static struct radio_20xx_regs regs_2057_rev8[] = { ++ {0x00, 0x8, 1}, ++ {0x01, 0x57, 1}, ++ {0x02, 0x20, 1}, ++ {0x03, 0x1f, 0}, ++ {0x04, 0x4, 0}, ++ {0x05, 0x2, 0}, ++ {0x06, 0x1, 0}, ++ {0x07, 0x1, 0}, ++ {0x08, 0x1, 0}, ++ {0x09, 0x69, 0}, ++ {0x0A, 0x66, 0}, ++ {0x0B, 0x6, 0}, ++ {0x0C, 0x18, 0}, ++ {0x0D, 0x3, 0}, ++ {0x0E, 0x20, 0}, ++ {0x0F, 0x20, 0}, ++ {0x10, 0, 0}, ++ {0x11, 0x7c, 0}, ++ {0x12, 0x42, 0}, ++ {0x13, 0xbd, 0}, ++ {0x14, 0x7, 0}, ++ {0x15, 0x87, 0}, ++ {0x16, 0x8, 0}, ++ {0x17, 0x17, 0}, ++ {0x18, 0x7, 0}, ++ {0x19, 0, 0}, ++ {0x1A, 0x2, 0}, ++ {0x1B, 0x13, 0}, ++ {0x1C, 0x3e, 0}, ++ {0x1D, 0x3e, 0}, ++ {0x1E, 0x96, 0}, ++ {0x1F, 0x4, 0}, ++ {0x20, 0, 0}, ++ {0x21, 0, 0}, ++ {0x22, 0x17, 0}, ++ {0x23, 0x6, 0}, ++ {0x24, 0x1, 0}, ++ {0x25, 0x6, 0}, ++ {0x26, 0x4, 0}, ++ {0x27, 0xd, 0}, ++ {0x28, 0xd, 0}, ++ {0x29, 0x30, 0}, ++ {0x2A, 0x32, 0}, ++ {0x2B, 0x8, 0}, ++ {0x2C, 0x1c, 0}, ++ {0x2D, 0x2, 0}, ++ {0x2E, 0x4, 0}, ++ {0x2F, 0x7f, 0}, ++ {0x30, 0x27, 0}, ++ {0x31, 0, 1}, ++ {0x32, 0, 1}, ++ {0x33, 0, 1}, ++ {0x34, 0, 0}, ++ {0x35, 0x20, 0}, ++ {0x36, 0x18, 0}, ++ {0x37, 0x7, 0}, ++ {0x38, 0x66, 0}, ++ {0x39, 0x66, 0}, ++ {0x3A, 0x66, 0}, ++ {0x3B, 0x66, 0}, ++ {0x3C, 0xff, 0}, ++ {0x3D, 0xff, 0}, ++ {0x3E, 0xff, 0}, ++ {0x3F, 0xff, 0}, ++ {0x40, 0x16, 0}, ++ {0x41, 0x7, 0}, ++ {0x42, 0x19, 0}, ++ {0x43, 0x7, 0}, ++ {0x44, 0x6, 0}, ++ {0x45, 0x3, 0}, ++ {0x46, 0x1, 0}, ++ {0x47, 0x7, 0}, ++ {0x48, 0x33, 0}, ++ {0x49, 0x5, 0}, ++ {0x4A, 0x77, 0}, ++ {0x4B, 0x66, 0}, ++ {0x4C, 0x66, 0}, ++ {0x4D, 0, 0}, ++ {0x4E, 0x4, 0}, ++ {0x4F, 0xc, 0}, ++ {0x50, 0, 0}, ++ {0x51, 0x70, 1}, ++ {0x56, 0x7, 0}, ++ {0x57, 0, 0}, ++ {0x58, 0, 0}, ++ {0x59, 0x88, 1}, ++ {0x5A, 0, 0}, ++ {0x5B, 0x1f, 0}, ++ {0x5C, 0x20, 1}, ++ {0x5D, 0x1, 0}, ++ {0x5E, 0x30, 0}, ++ {0x5F, 0x70, 0}, ++ {0x60, 0, 0}, ++ {0x61, 0, 0}, ++ {0x62, 0x33, 1}, ++ {0x63, 0xf, 1}, ++ {0x64, 0xf, 1}, ++ {0x65, 0, 0}, ++ {0x66, 0x11, 0}, ++ {0x69, 0, 0}, ++ {0x6A, 0x7e, 0}, ++ {0x6B, 0x3f, 0}, ++ {0x6C, 0x7f, 0}, ++ {0x6D, 0x78, 0}, ++ {0x6E, 0x58, 1}, ++ {0x6F, 0x88, 0}, ++ {0x70, 0x8, 0}, ++ {0x71, 0xf, 0}, ++ {0x72, 0xbc, 0}, ++ {0x73, 0x8, 0}, ++ {0x74, 0x60, 0}, ++ {0x75, 0x13, 1}, ++ {0x76, 0x70, 0}, ++ {0x77, 0, 0}, ++ {0x78, 0, 0}, ++ {0x79, 0, 0}, ++ {0x7A, 0x33, 0}, ++ {0x7B, 0x13, 1}, ++ {0x7C, 0xf, 1}, ++ {0x7D, 0xee, 1}, ++ {0x80, 0x3c, 0}, ++ {0x81, 0x1, 1}, ++ {0x82, 0xa, 0}, ++ {0x83, 0x9d, 0}, ++ {0x84, 0xa, 0}, ++ {0x85, 0, 0}, ++ {0x86, 0x40, 0}, ++ {0x87, 0x40, 0}, ++ {0x88, 0x88, 0}, ++ {0x89, 0x10, 0}, ++ {0x8A, 0xf0, 0}, ++ {0x8B, 0x10, 0}, ++ {0x8C, 0xf0, 0}, ++ {0x8D, 0, 0}, ++ {0x8E, 0, 0}, ++ {0x8F, 0x10, 0}, ++ {0x90, 0x55, 0}, ++ {0x91, 0x3f, 1}, ++ {0x92, 0x36, 1}, ++ {0x93, 0, 0}, ++ {0x94, 0, 0}, ++ {0x95, 0, 0}, ++ {0x96, 0x87, 0}, ++ {0x97, 0x11, 0}, ++ {0x98, 0, 0}, ++ {0x99, 0x33, 0}, ++ {0x9A, 0x88, 0}, ++ {0x9B, 0, 0}, ++ {0x9C, 0x87, 0}, ++ {0x9D, 0x11, 0}, ++ {0x9E, 0, 0}, ++ {0x9F, 0x33, 0}, ++ {0xA0, 0x88, 0}, ++ {0xA1, 0x20, 1}, ++ {0xA2, 0x3f, 0}, ++ {0xA3, 0x44, 0}, ++ {0xA4, 0x8c, 0}, ++ {0xA5, 0x6c, 0}, ++ {0xA6, 0x22, 0}, ++ {0xA7, 0xbe, 0}, ++ {0xA8, 0x55, 0}, ++ {0xAA, 0xc, 0}, ++ {0xAB, 0xaa, 0}, ++ {0xAC, 0x2, 0}, ++ {0xAD, 0, 0}, ++ {0xAE, 0x10, 0}, ++ {0xAF, 0x1, 0}, ++ {0xB0, 0, 0}, ++ {0xB1, 0, 0}, ++ {0xB2, 0x80, 0}, ++ {0xB3, 0x60, 0}, ++ {0xB4, 0x44, 0}, ++ {0xB5, 0x55, 0}, ++ {0xB6, 0x1, 0}, ++ {0xB7, 0x55, 0}, ++ {0xB8, 0x1, 0}, ++ {0xB9, 0x5, 0}, ++ {0xBA, 0x55, 0}, ++ {0xBB, 0x55, 0}, ++ {0xC1, 0, 0}, ++ {0xC2, 0, 0}, ++ {0xC3, 0, 0}, ++ {0xC4, 0, 0}, ++ {0xC5, 0, 0}, ++ {0xC6, 0, 0}, ++ {0xC7, 0, 0}, ++ {0xC8, 0, 0}, ++ {0xC9, 0x1, 1}, ++ {0xCA, 0, 0}, ++ {0xCB, 0, 0}, ++ {0xCC, 0, 0}, ++ {0xCD, 0, 0}, ++ {0xCE, 0x5e, 0}, ++ {0xCF, 0xc, 0}, ++ {0xD0, 0xc, 0}, ++ {0xD1, 0xc, 0}, ++ {0xD2, 0, 0}, ++ {0xD3, 0x2b, 0}, ++ {0xD4, 0xc, 0}, ++ {0xD5, 0, 0}, ++ {0xD6, 0x70, 1}, ++ {0xDB, 0x7, 0}, ++ {0xDC, 0, 0}, ++ {0xDD, 0, 0}, ++ {0xDE, 0x88, 1}, ++ {0xDF, 0, 0}, ++ {0xE0, 0x1f, 0}, ++ {0xE1, 0x20, 1}, ++ {0xE2, 0x1, 0}, ++ {0xE3, 0x30, 0}, ++ {0xE4, 0x70, 0}, ++ {0xE5, 0, 0}, ++ {0xE6, 0, 0}, ++ {0xE7, 0x33, 0}, ++ {0xE8, 0xf, 1}, ++ {0xE9, 0xf, 1}, ++ {0xEA, 0, 0}, ++ {0xEB, 0x11, 0}, ++ {0xEE, 0, 0}, ++ {0xEF, 0x7e, 0}, ++ {0xF0, 0x3f, 0}, ++ {0xF1, 0x7f, 0}, ++ {0xF2, 0x78, 0}, ++ {0xF3, 0x58, 1}, ++ {0xF4, 0x88, 0}, ++ {0xF5, 0x8, 0}, ++ {0xF6, 0xf, 0}, ++ {0xF7, 0xbc, 0}, ++ {0xF8, 0x8, 0}, ++ {0xF9, 0x60, 0}, ++ {0xFA, 0x13, 1}, ++ {0xFB, 0x70, 0}, ++ {0xFC, 0, 0}, ++ {0xFD, 0, 0}, ++ {0xFE, 0, 0}, ++ {0xFF, 0x33, 0}, ++ {0x100, 0x13, 1}, ++ {0x101, 0xf, 1}, ++ {0x102, 0xee, 1}, ++ {0x105, 0x3c, 0}, ++ {0x106, 0x1, 1}, ++ {0x107, 0xa, 0}, ++ {0x108, 0x9d, 0}, ++ {0x109, 0xa, 0}, ++ {0x10A, 0, 0}, ++ {0x10B, 0x40, 0}, ++ {0x10C, 0x40, 0}, ++ {0x10D, 0x88, 0}, ++ {0x10E, 0x10, 0}, ++ {0x10F, 0xf0, 0}, ++ {0x110, 0x10, 0}, ++ {0x111, 0xf0, 0}, ++ {0x112, 0, 0}, ++ {0x113, 0, 0}, ++ {0x114, 0x10, 0}, ++ {0x115, 0x55, 0}, ++ {0x116, 0x3f, 1}, ++ {0x117, 0x36, 1}, ++ {0x118, 0, 0}, ++ {0x119, 0, 0}, ++ {0x11A, 0, 0}, ++ {0x11B, 0x87, 0}, ++ {0x11C, 0x11, 0}, ++ {0x11D, 0, 0}, ++ {0x11E, 0x33, 0}, ++ {0x11F, 0x88, 0}, ++ {0x120, 0, 0}, ++ {0x121, 0x87, 0}, ++ {0x122, 0x11, 0}, ++ {0x123, 0, 0}, ++ {0x124, 0x33, 0}, ++ {0x125, 0x88, 0}, ++ {0x126, 0x20, 1}, ++ {0x127, 0x3f, 0}, ++ {0x128, 0x44, 0}, ++ {0x129, 0x8c, 0}, ++ {0x12A, 0x6c, 0}, ++ {0x12B, 0x22, 0}, ++ {0x12C, 0xbe, 0}, ++ {0x12D, 0x55, 0}, ++ {0x12F, 0xc, 0}, ++ {0x130, 0xaa, 0}, ++ {0x131, 0x2, 0}, ++ {0x132, 0, 0}, ++ {0x133, 0x10, 0}, ++ {0x134, 0x1, 0}, ++ {0x135, 0, 0}, ++ {0x136, 0, 0}, ++ {0x137, 0x80, 0}, ++ {0x138, 0x60, 0}, ++ {0x139, 0x44, 0}, ++ {0x13A, 0x55, 0}, ++ {0x13B, 0x1, 0}, ++ {0x13C, 0x55, 0}, ++ {0x13D, 0x1, 0}, ++ {0x13E, 0x5, 0}, ++ {0x13F, 0x55, 0}, ++ {0x140, 0x55, 0}, ++ {0x146, 0, 0}, ++ {0x147, 0, 0}, ++ {0x148, 0, 0}, ++ {0x149, 0, 0}, ++ {0x14A, 0, 0}, ++ {0x14B, 0, 0}, ++ {0x14C, 0, 0}, ++ {0x14D, 0, 0}, ++ {0x14E, 0x1, 1}, ++ {0x14F, 0, 0}, ++ {0x150, 0, 0}, ++ {0x151, 0, 0}, ++ {0x154, 0xc, 0}, ++ {0x155, 0xc, 0}, ++ {0x156, 0xc, 0}, ++ {0x157, 0, 0}, ++ {0x158, 0x2b, 0}, ++ {0x159, 0x84, 0}, ++ {0x15A, 0x15, 0}, ++ {0x15B, 0xf, 0}, ++ {0x15C, 0, 0}, ++ {0x15D, 0, 0}, ++ {0x15E, 0, 1}, ++ {0x15F, 0, 1}, ++ {0x160, 0, 1}, ++ {0x161, 0, 1}, ++ {0x162, 0, 1}, ++ {0x163, 0, 1}, ++ {0x164, 0, 0}, ++ {0x165, 0, 0}, ++ {0x166, 0, 0}, ++ {0x167, 0, 0}, ++ {0x168, 0, 0}, ++ {0x169, 0, 0}, ++ {0x16A, 0, 1}, ++ {0x16B, 0, 1}, ++ {0x16C, 0, 1}, ++ {0x16D, 0, 0}, ++ {0x170, 0, 0}, ++ {0x171, 0x77, 0}, ++ {0x172, 0x77, 0}, ++ {0x173, 0x77, 0}, ++ {0x174, 0x77, 0}, ++ {0x175, 0, 0}, ++ {0x176, 0x3, 0}, ++ {0x177, 0x37, 0}, ++ {0x178, 0x3, 0}, ++ {0x179, 0, 0}, ++ {0x17A, 0x21, 0}, ++ {0x17B, 0x21, 0}, ++ {0x17C, 0, 0}, ++ {0x17D, 0xaa, 0}, ++ {0x17E, 0, 0}, ++ {0x17F, 0xaa, 0}, ++ {0x180, 0, 0}, ++ {0x190, 0, 0}, ++ {0x191, 0x77, 0}, ++ {0x192, 0x77, 0}, ++ {0x193, 0x77, 0}, ++ {0x194, 0x77, 0}, ++ {0x195, 0, 0}, ++ {0x196, 0x3, 0}, ++ {0x197, 0x37, 0}, ++ {0x198, 0x3, 0}, ++ {0x199, 0, 0}, ++ {0x19A, 0x21, 0}, ++ {0x19B, 0x21, 0}, ++ {0x19C, 0, 0}, ++ {0x19D, 0xaa, 0}, ++ {0x19E, 0, 0}, ++ {0x19F, 0xaa, 0}, ++ {0x1A0, 0, 0}, ++ {0x1A1, 0x2, 0}, ++ {0x1A2, 0xf, 0}, ++ {0x1A3, 0xf, 0}, ++ {0x1A4, 0, 1}, ++ {0x1A5, 0, 1}, ++ {0x1A6, 0, 1}, ++ {0x1A7, 0x2, 0}, ++ {0x1A8, 0xf, 0}, ++ {0x1A9, 0xf, 0}, ++ {0x1AA, 0, 1}, ++ {0x1AB, 0, 1}, ++ {0x1AC, 0, 1}, ++ {0x1AD, 0x84, 0}, ++ {0x1AE, 0x60, 0}, ++ {0x1AF, 0x47, 0}, ++ {0x1B0, 0x47, 0}, ++ {0x1B1, 0, 0}, ++ {0x1B2, 0, 0}, ++ {0x1B3, 0, 0}, ++ {0x1B4, 0, 0}, ++ {0x1B5, 0, 0}, ++ {0x1B6, 0, 0}, ++ {0x1B7, 0x5, 1}, ++ {0x1B8, 0, 0}, ++ {0x1B9, 0, 0}, ++ {0x1BA, 0, 0}, ++ {0x1BB, 0, 0}, ++ {0x1BC, 0, 0}, ++ {0x1BD, 0, 0}, ++ {0x1BE, 0, 0}, ++ {0x1BF, 0, 0}, ++ {0x1C0, 0, 0}, ++ {0x1C1, 0, 0}, ++ {0x1C2, 0xa0, 1}, ++ {0x1C3, 0, 0}, ++ {0x1C4, 0, 0}, ++ {0x1C5, 0, 0}, ++ {0x1C6, 0, 0}, ++ {0x1C7, 0, 0}, ++ {0x1C8, 0, 0}, ++ {0x1C9, 0, 0}, ++ {0x1CA, 0, 0}, ++ {0xFFFF, 0, 0} ++}; ++ ++static s16 nphy_def_lnagains[] = { -2, 10, 19, 25 }; ++ ++static s32 nphy_lnagain_est0[] = { -315, 40370 }; ++static s32 nphy_lnagain_est1[] = { -224, 23242 }; ++ ++static const u16 tbl_iqcal_gainparams_nphy[2][NPHY_IQCAL_NUMGAINS][8] = { ++ { ++ {0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69}, ++ {0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69}, ++ {0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68}, ++ {0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67}, ++ {0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66}, ++ {0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65}, ++ {0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65}, ++ {0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65}, ++ {0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65} ++ }, ++ { ++ {0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79}, ++ {0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79}, ++ {0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79}, ++ {0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78}, ++ {0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78}, ++ {0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78}, ++ {0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78}, ++ {0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78}, ++ {0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78} ++ } ++}; ++ ++static const u32 nphy_tpc_txgain[] = { ++ 0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42, ++ 0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44, ++ 0x03c82a42, 0x03c82944, 0x03c82942, 0x03c82844, ++ 0x03c82842, 0x03c42b44, 0x03c42b42, 0x03c42a44, ++ 0x03c42a42, 0x03c42944, 0x03c42942, 0x03c42844, ++ 0x03c42842, 0x03c42744, 0x03c42742, 0x03c42644, ++ 0x03c42642, 0x03c42544, 0x03c42542, 0x03c42444, ++ 0x03c42442, 0x03c02b44, 0x03c02b42, 0x03c02a44, ++ 0x03c02a42, 0x03c02944, 0x03c02942, 0x03c02844, ++ 0x03c02842, 0x03c02744, 0x03c02742, 0x03b02b44, ++ 0x03b02b42, 0x03b02a44, 0x03b02a42, 0x03b02944, ++ 0x03b02942, 0x03b02844, 0x03b02842, 0x03b02744, ++ 0x03b02742, 0x03b02644, 0x03b02642, 0x03b02544, ++ 0x03b02542, 0x03a02b44, 0x03a02b42, 0x03a02a44, ++ 0x03a02a42, 0x03a02944, 0x03a02942, 0x03a02844, ++ 0x03a02842, 0x03a02744, 0x03a02742, 0x03902b44, ++ 0x03902b42, 0x03902a44, 0x03902a42, 0x03902944, ++ 0x03902942, 0x03902844, 0x03902842, 0x03902744, ++ 0x03902742, 0x03902644, 0x03902642, 0x03902544, ++ 0x03902542, 0x03802b44, 0x03802b42, 0x03802a44, ++ 0x03802a42, 0x03802944, 0x03802942, 0x03802844, ++ 0x03802842, 0x03802744, 0x03802742, 0x03802644, ++ 0x03802642, 0x03802544, 0x03802542, 0x03802444, ++ 0x03802442, 0x03802344, 0x03802342, 0x03802244, ++ 0x03802242, 0x03802144, 0x03802142, 0x03802044, ++ 0x03802042, 0x03801f44, 0x03801f42, 0x03801e44, ++ 0x03801e42, 0x03801d44, 0x03801d42, 0x03801c44, ++ 0x03801c42, 0x03801b44, 0x03801b42, 0x03801a44, ++ 0x03801a42, 0x03801944, 0x03801942, 0x03801844, ++ 0x03801842, 0x03801744, 0x03801742, 0x03801644, ++ 0x03801642, 0x03801544, 0x03801542, 0x03801444, ++ 0x03801442, 0x03801344, 0x03801342, 0x00002b00 ++}; ++ ++static const u16 nphy_tpc_loscale[] = { ++ 256, 256, 271, 271, 287, 256, 256, 271, ++ 271, 287, 287, 304, 304, 256, 256, 271, ++ 271, 287, 287, 304, 304, 322, 322, 341, ++ 341, 362, 362, 383, 383, 256, 256, 271, ++ 271, 287, 287, 304, 304, 322, 322, 256, ++ 256, 271, 271, 287, 287, 304, 304, 322, ++ 322, 341, 341, 362, 362, 256, 256, 271, ++ 271, 287, 287, 304, 304, 322, 322, 256, ++ 256, 271, 271, 287, 287, 304, 304, 322, ++ 322, 341, 341, 362, 362, 256, 256, 271, ++ 271, 287, 287, 304, 304, 322, 322, 341, ++ 341, 362, 362, 383, 383, 406, 406, 430, ++ 430, 455, 455, 482, 482, 511, 511, 541, ++ 541, 573, 573, 607, 607, 643, 643, 681, ++ 681, 722, 722, 764, 764, 810, 810, 858, ++ 858, 908, 908, 962, 962, 1019, 1019, 256 ++}; ++ ++static u32 nphy_tpc_txgain_ipa[] = { ++ 0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029, ++ 0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025, ++ 0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029, ++ 0x5ef70028, 0x5ef70027, 0x5ef70026, 0x5ef70025, ++ 0x5df7002d, 0x5df7002b, 0x5df7002a, 0x5df70029, ++ 0x5df70028, 0x5df70027, 0x5df70026, 0x5df70025, ++ 0x5cf7002d, 0x5cf7002b, 0x5cf7002a, 0x5cf70029, ++ 0x5cf70028, 0x5cf70027, 0x5cf70026, 0x5cf70025, ++ 0x5bf7002d, 0x5bf7002b, 0x5bf7002a, 0x5bf70029, ++ 0x5bf70028, 0x5bf70027, 0x5bf70026, 0x5bf70025, ++ 0x5af7002d, 0x5af7002b, 0x5af7002a, 0x5af70029, ++ 0x5af70028, 0x5af70027, 0x5af70026, 0x5af70025, ++ 0x59f7002d, 0x59f7002b, 0x59f7002a, 0x59f70029, ++ 0x59f70028, 0x59f70027, 0x59f70026, 0x59f70025, ++ 0x58f7002d, 0x58f7002b, 0x58f7002a, 0x58f70029, ++ 0x58f70028, 0x58f70027, 0x58f70026, 0x58f70025, ++ 0x57f7002d, 0x57f7002b, 0x57f7002a, 0x57f70029, ++ 0x57f70028, 0x57f70027, 0x57f70026, 0x57f70025, ++ 0x56f7002d, 0x56f7002b, 0x56f7002a, 0x56f70029, ++ 0x56f70028, 0x56f70027, 0x56f70026, 0x56f70025, ++ 0x55f7002d, 0x55f7002b, 0x55f7002a, 0x55f70029, ++ 0x55f70028, 0x55f70027, 0x55f70026, 0x55f70025, ++ 0x54f7002d, 0x54f7002b, 0x54f7002a, 0x54f70029, ++ 0x54f70028, 0x54f70027, 0x54f70026, 0x54f70025, ++ 0x53f7002d, 0x53f7002b, 0x53f7002a, 0x53f70029, ++ 0x53f70028, 0x53f70027, 0x53f70026, 0x53f70025, ++ 0x52f7002d, 0x52f7002b, 0x52f7002a, 0x52f70029, ++ 0x52f70028, 0x52f70027, 0x52f70026, 0x52f70025, ++ 0x51f7002d, 0x51f7002b, 0x51f7002a, 0x51f70029, ++ 0x51f70028, 0x51f70027, 0x51f70026, 0x51f70025, ++ 0x50f7002d, 0x50f7002b, 0x50f7002a, 0x50f70029, ++ 0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025 ++}; ++ ++static u32 nphy_tpc_txgain_ipa_rev5[] = { ++ 0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029, ++ 0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025, ++ 0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029, ++ 0x1ef70028, 0x1ef70027, 0x1ef70026, 0x1ef70025, ++ 0x1df7002d, 0x1df7002b, 0x1df7002a, 0x1df70029, ++ 0x1df70028, 0x1df70027, 0x1df70026, 0x1df70025, ++ 0x1cf7002d, 0x1cf7002b, 0x1cf7002a, 0x1cf70029, ++ 0x1cf70028, 0x1cf70027, 0x1cf70026, 0x1cf70025, ++ 0x1bf7002d, 0x1bf7002b, 0x1bf7002a, 0x1bf70029, ++ 0x1bf70028, 0x1bf70027, 0x1bf70026, 0x1bf70025, ++ 0x1af7002d, 0x1af7002b, 0x1af7002a, 0x1af70029, ++ 0x1af70028, 0x1af70027, 0x1af70026, 0x1af70025, ++ 0x19f7002d, 0x19f7002b, 0x19f7002a, 0x19f70029, ++ 0x19f70028, 0x19f70027, 0x19f70026, 0x19f70025, ++ 0x18f7002d, 0x18f7002b, 0x18f7002a, 0x18f70029, ++ 0x18f70028, 0x18f70027, 0x18f70026, 0x18f70025, ++ 0x17f7002d, 0x17f7002b, 0x17f7002a, 0x17f70029, ++ 0x17f70028, 0x17f70027, 0x17f70026, 0x17f70025, ++ 0x16f7002d, 0x16f7002b, 0x16f7002a, 0x16f70029, ++ 0x16f70028, 0x16f70027, 0x16f70026, 0x16f70025, ++ 0x15f7002d, 0x15f7002b, 0x15f7002a, 0x15f70029, ++ 0x15f70028, 0x15f70027, 0x15f70026, 0x15f70025, ++ 0x14f7002d, 0x14f7002b, 0x14f7002a, 0x14f70029, ++ 0x14f70028, 0x14f70027, 0x14f70026, 0x14f70025, ++ 0x13f7002d, 0x13f7002b, 0x13f7002a, 0x13f70029, ++ 0x13f70028, 0x13f70027, 0x13f70026, 0x13f70025, ++ 0x12f7002d, 0x12f7002b, 0x12f7002a, 0x12f70029, ++ 0x12f70028, 0x12f70027, 0x12f70026, 0x12f70025, ++ 0x11f7002d, 0x11f7002b, 0x11f7002a, 0x11f70029, ++ 0x11f70028, 0x11f70027, 0x11f70026, 0x11f70025, ++ 0x10f7002d, 0x10f7002b, 0x10f7002a, 0x10f70029, ++ 0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025 ++}; ++ ++static u32 nphy_tpc_txgain_ipa_rev6[] = { ++ 0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029, ++ 0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025, ++ 0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029, ++ 0x0ef70028, 0x0ef70027, 0x0ef70026, 0x0ef70025, ++ 0x0df7002d, 0x0df7002b, 0x0df7002a, 0x0df70029, ++ 0x0df70028, 0x0df70027, 0x0df70026, 0x0df70025, ++ 0x0cf7002d, 0x0cf7002b, 0x0cf7002a, 0x0cf70029, ++ 0x0cf70028, 0x0cf70027, 0x0cf70026, 0x0cf70025, ++ 0x0bf7002d, 0x0bf7002b, 0x0bf7002a, 0x0bf70029, ++ 0x0bf70028, 0x0bf70027, 0x0bf70026, 0x0bf70025, ++ 0x0af7002d, 0x0af7002b, 0x0af7002a, 0x0af70029, ++ 0x0af70028, 0x0af70027, 0x0af70026, 0x0af70025, ++ 0x09f7002d, 0x09f7002b, 0x09f7002a, 0x09f70029, ++ 0x09f70028, 0x09f70027, 0x09f70026, 0x09f70025, ++ 0x08f7002d, 0x08f7002b, 0x08f7002a, 0x08f70029, ++ 0x08f70028, 0x08f70027, 0x08f70026, 0x08f70025, ++ 0x07f7002d, 0x07f7002b, 0x07f7002a, 0x07f70029, ++ 0x07f70028, 0x07f70027, 0x07f70026, 0x07f70025, ++ 0x06f7002d, 0x06f7002b, 0x06f7002a, 0x06f70029, ++ 0x06f70028, 0x06f70027, 0x06f70026, 0x06f70025, ++ 0x05f7002d, 0x05f7002b, 0x05f7002a, 0x05f70029, ++ 0x05f70028, 0x05f70027, 0x05f70026, 0x05f70025, ++ 0x04f7002d, 0x04f7002b, 0x04f7002a, 0x04f70029, ++ 0x04f70028, 0x04f70027, 0x04f70026, 0x04f70025, ++ 0x03f7002d, 0x03f7002b, 0x03f7002a, 0x03f70029, ++ 0x03f70028, 0x03f70027, 0x03f70026, 0x03f70025, ++ 0x02f7002d, 0x02f7002b, 0x02f7002a, 0x02f70029, ++ 0x02f70028, 0x02f70027, 0x02f70026, 0x02f70025, ++ 0x01f7002d, 0x01f7002b, 0x01f7002a, 0x01f70029, ++ 0x01f70028, 0x01f70027, 0x01f70026, 0x01f70025, ++ 0x00f7002d, 0x00f7002b, 0x00f7002a, 0x00f70029, ++ 0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025 ++}; ++ ++static u32 nphy_tpc_txgain_ipa_2g_2057rev3[] = { ++ 0x70ff0040, 0x70f7003e, 0x70ef003b, 0x70e70039, ++ 0x70df0037, 0x70d70036, 0x70cf0033, 0x70c70032, ++ 0x70bf0031, 0x70b7002f, 0x70af002e, 0x70a7002d, ++ 0x709f002d, 0x7097002c, 0x708f002c, 0x7087002c, ++ 0x707f002b, 0x7077002c, 0x706f002c, 0x7067002d, ++ 0x705f002e, 0x705f002b, 0x705f0029, 0x7057002a, ++ 0x70570028, 0x704f002a, 0x7047002c, 0x7047002a, ++ 0x70470028, 0x70470026, 0x70470024, 0x70470022, ++ 0x7047001f, 0x70370027, 0x70370024, 0x70370022, ++ 0x70370020, 0x7037001f, 0x7037001d, 0x7037001b, ++ 0x7037001a, 0x70370018, 0x70370017, 0x7027001e, ++ 0x7027001d, 0x7027001a, 0x701f0024, 0x701f0022, ++ 0x701f0020, 0x701f001f, 0x701f001d, 0x701f001b, ++ 0x701f001a, 0x701f0018, 0x701f0017, 0x701f0015, ++ 0x701f0014, 0x701f0013, 0x701f0012, 0x701f0011, ++ 0x70170019, 0x70170018, 0x70170016, 0x70170015, ++ 0x70170014, 0x70170013, 0x70170012, 0x70170010, ++ 0x70170010, 0x7017000f, 0x700f001d, 0x700f001b, ++ 0x700f001a, 0x700f0018, 0x700f0017, 0x700f0015, ++ 0x700f0015, 0x700f0013, 0x700f0013, 0x700f0011, ++ 0x700f0010, 0x700f0010, 0x700f000f, 0x700f000e, ++ 0x700f000d, 0x700f000c, 0x700f000b, 0x700f000b, ++ 0x700f000b, 0x700f000a, 0x700f0009, 0x700f0009, ++ 0x700f0009, 0x700f0008, 0x700f0007, 0x700f0007, ++ 0x700f0006, 0x700f0006, 0x700f0006, 0x700f0006, ++ 0x700f0005, 0x700f0005, 0x700f0005, 0x700f0004, ++ 0x700f0004, 0x700f0004, 0x700f0004, 0x700f0004, ++ 0x700f0004, 0x700f0003, 0x700f0003, 0x700f0003, ++ 0x700f0003, 0x700f0002, 0x700f0002, 0x700f0002, ++ 0x700f0002, 0x700f0002, 0x700f0002, 0x700f0001, ++ 0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001, ++ 0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001 ++}; ++ ++static u32 nphy_tpc_txgain_ipa_2g_2057rev4n6[] = { ++ 0xf0ff0040, 0xf0f7003e, 0xf0ef003b, 0xf0e70039, ++ 0xf0df0037, 0xf0d70036, 0xf0cf0033, 0xf0c70032, ++ 0xf0bf0031, 0xf0b7002f, 0xf0af002e, 0xf0a7002d, ++ 0xf09f002d, 0xf097002c, 0xf08f002c, 0xf087002c, ++ 0xf07f002b, 0xf077002c, 0xf06f002c, 0xf067002d, ++ 0xf05f002e, 0xf05f002b, 0xf05f0029, 0xf057002a, ++ 0xf0570028, 0xf04f002a, 0xf047002c, 0xf047002a, ++ 0xf0470028, 0xf0470026, 0xf0470024, 0xf0470022, ++ 0xf047001f, 0xf0370027, 0xf0370024, 0xf0370022, ++ 0xf0370020, 0xf037001f, 0xf037001d, 0xf037001b, ++ 0xf037001a, 0xf0370018, 0xf0370017, 0xf027001e, ++ 0xf027001d, 0xf027001a, 0xf01f0024, 0xf01f0022, ++ 0xf01f0020, 0xf01f001f, 0xf01f001d, 0xf01f001b, ++ 0xf01f001a, 0xf01f0018, 0xf01f0017, 0xf01f0015, ++ 0xf01f0014, 0xf01f0013, 0xf01f0012, 0xf01f0011, ++ 0xf0170019, 0xf0170018, 0xf0170016, 0xf0170015, ++ 0xf0170014, 0xf0170013, 0xf0170012, 0xf0170010, ++ 0xf0170010, 0xf017000f, 0xf00f001d, 0xf00f001b, ++ 0xf00f001a, 0xf00f0018, 0xf00f0017, 0xf00f0015, ++ 0xf00f0015, 0xf00f0013, 0xf00f0013, 0xf00f0011, ++ 0xf00f0010, 0xf00f0010, 0xf00f000f, 0xf00f000e, ++ 0xf00f000d, 0xf00f000c, 0xf00f000b, 0xf00f000b, ++ 0xf00f000b, 0xf00f000a, 0xf00f0009, 0xf00f0009, ++ 0xf00f0009, 0xf00f0008, 0xf00f0007, 0xf00f0007, ++ 0xf00f0006, 0xf00f0006, 0xf00f0006, 0xf00f0006, ++ 0xf00f0005, 0xf00f0005, 0xf00f0005, 0xf00f0004, ++ 0xf00f0004, 0xf00f0004, 0xf00f0004, 0xf00f0004, ++ 0xf00f0004, 0xf00f0003, 0xf00f0003, 0xf00f0003, ++ 0xf00f0003, 0xf00f0002, 0xf00f0002, 0xf00f0002, ++ 0xf00f0002, 0xf00f0002, 0xf00f0002, 0xf00f0001, ++ 0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001, ++ 0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001 ++}; ++ ++static u32 nphy_tpc_txgain_ipa_2g_2057rev5[] = { ++ 0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e, ++ 0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033, ++ 0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e, ++ 0x3067002e, 0x305f002f, 0x30570030, 0x3057002d, ++ 0x304f002e, 0x30470031, 0x3047002e, 0x3047002c, ++ 0x30470029, 0x303f002c, 0x303f0029, 0x3037002d, ++ 0x3037002a, 0x30370028, 0x302f002c, 0x302f002a, ++ 0x302f0028, 0x302f0026, 0x3027002c, 0x30270029, ++ 0x30270027, 0x30270025, 0x30270023, 0x301f002c, ++ 0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024, ++ 0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b, ++ 0x30170028, 0x30170026, 0x30170024, 0x30170022, ++ 0x30170020, 0x3017001e, 0x3017001d, 0x3017001b, ++ 0x3017001a, 0x30170018, 0x30170017, 0x30170015, ++ 0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024, ++ 0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d, ++ 0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017, ++ 0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215, ++ 0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715 ++}; ++ ++static u32 nphy_tpc_txgain_ipa_2g_2057rev7[] = { ++ 0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e, ++ 0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033, ++ 0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e, ++ 0x3067002e, 0x305f002f, 0x30570030, 0x3057002d, ++ 0x304f002e, 0x30470031, 0x3047002e, 0x3047002c, ++ 0x30470029, 0x303f002c, 0x303f0029, 0x3037002d, ++ 0x3037002a, 0x30370028, 0x302f002c, 0x302f002a, ++ 0x302f0028, 0x302f0026, 0x3027002c, 0x30270029, ++ 0x30270027, 0x30270025, 0x30270023, 0x301f002c, ++ 0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024, ++ 0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b, ++ 0x30170028, 0x30170026, 0x30170024, 0x30170022, ++ 0x30170020, 0x3017001e, 0x3017001d, 0x3017001b, ++ 0x3017001a, 0x30170018, 0x30170017, 0x30170015, ++ 0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024, ++ 0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d, ++ 0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017, ++ 0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215, ++ 0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715 ++}; ++ ++static u32 nphy_tpc_txgain_ipa_5g[] = { ++ 0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031, ++ 0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b, ++ 0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027, ++ 0x7ff70026, 0x7ff70024, 0x7ff70023, 0x7ff70022, ++ 0x7ef70028, 0x7ef70027, 0x7ef70026, 0x7ef70025, ++ 0x7ef70024, 0x7ef70023, 0x7df70028, 0x7df70027, ++ 0x7df70026, 0x7df70025, 0x7df70024, 0x7df70023, ++ 0x7df70022, 0x7cf70029, 0x7cf70028, 0x7cf70027, ++ 0x7cf70026, 0x7cf70025, 0x7cf70023, 0x7cf70022, ++ 0x7bf70029, 0x7bf70028, 0x7bf70026, 0x7bf70025, ++ 0x7bf70024, 0x7bf70023, 0x7bf70022, 0x7bf70021, ++ 0x7af70029, 0x7af70028, 0x7af70027, 0x7af70026, ++ 0x7af70025, 0x7af70024, 0x7af70023, 0x7af70022, ++ 0x79f70029, 0x79f70028, 0x79f70027, 0x79f70026, ++ 0x79f70025, 0x79f70024, 0x79f70023, 0x79f70022, ++ 0x78f70029, 0x78f70028, 0x78f70027, 0x78f70026, ++ 0x78f70025, 0x78f70024, 0x78f70023, 0x78f70022, ++ 0x77f70029, 0x77f70028, 0x77f70027, 0x77f70026, ++ 0x77f70025, 0x77f70024, 0x77f70023, 0x77f70022, ++ 0x76f70029, 0x76f70028, 0x76f70027, 0x76f70026, ++ 0x76f70024, 0x76f70023, 0x76f70022, 0x76f70021, ++ 0x75f70029, 0x75f70028, 0x75f70027, 0x75f70026, ++ 0x75f70025, 0x75f70024, 0x75f70023, 0x74f70029, ++ 0x74f70028, 0x74f70026, 0x74f70025, 0x74f70024, ++ 0x74f70023, 0x74f70022, 0x73f70029, 0x73f70027, ++ 0x73f70026, 0x73f70025, 0x73f70024, 0x73f70023, ++ 0x73f70022, 0x72f70028, 0x72f70027, 0x72f70026, ++ 0x72f70025, 0x72f70024, 0x72f70023, 0x72f70022, ++ 0x71f70028, 0x71f70027, 0x71f70026, 0x71f70025, ++ 0x71f70024, 0x71f70023, 0x70f70028, 0x70f70027, ++ 0x70f70026, 0x70f70024, 0x70f70023, 0x70f70022, ++ 0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f ++}; ++ ++static u32 nphy_tpc_txgain_ipa_5g_2057[] = { ++ 0x7f7f0044, 0x7f7f0040, 0x7f7f003c, 0x7f7f0039, ++ 0x7f7f0036, 0x7e7f003c, 0x7e7f0038, 0x7e7f0035, ++ 0x7d7f003c, 0x7d7f0039, 0x7d7f0036, 0x7d7f0033, ++ 0x7c7f003b, 0x7c7f0037, 0x7c7f0034, 0x7b7f003a, ++ 0x7b7f0036, 0x7b7f0033, 0x7a7f003c, 0x7a7f0039, ++ 0x7a7f0036, 0x7a7f0033, 0x797f003b, 0x797f0038, ++ 0x797f0035, 0x797f0032, 0x787f003b, 0x787f0038, ++ 0x787f0035, 0x787f0032, 0x777f003a, 0x777f0037, ++ 0x777f0034, 0x777f0031, 0x767f003a, 0x767f0036, ++ 0x767f0033, 0x767f0031, 0x757f003a, 0x757f0037, ++ 0x757f0034, 0x747f003c, 0x747f0039, 0x747f0036, ++ 0x747f0033, 0x737f003b, 0x737f0038, 0x737f0035, ++ 0x737f0032, 0x727f0039, 0x727f0036, 0x727f0033, ++ 0x727f0030, 0x717f003a, 0x717f0037, 0x717f0034, ++ 0x707f003b, 0x707f0038, 0x707f0035, 0x707f0032, ++ 0x707f002f, 0x707f002d, 0x707f002a, 0x707f0028, ++ 0x707f0025, 0x707f0023, 0x707f0021, 0x707f0020, ++ 0x707f001e, 0x707f001c, 0x707f001b, 0x707f0019, ++ 0x707f0018, 0x707f0016, 0x707f0015, 0x707f0014, ++ 0x707f0013, 0x707f0012, 0x707f0011, 0x707f0010, ++ 0x707f000f, 0x707f000e, 0x707f000d, 0x707f000d, ++ 0x707f000c, 0x707f000b, 0x707f000b, 0x707f000a, ++ 0x707f0009, 0x707f0009, 0x707f0008, 0x707f0008, ++ 0x707f0007, 0x707f0007, 0x707f0007, 0x707f0006, ++ 0x707f0006, 0x707f0006, 0x707f0005, 0x707f0005, ++ 0x707f0005, 0x707f0004, 0x707f0004, 0x707f0004, ++ 0x707f0004, 0x707f0004, 0x707f0003, 0x707f0003, ++ 0x707f0003, 0x707f0003, 0x707f0003, 0x707f0003, ++ 0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002, ++ 0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002, ++ 0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001, ++ 0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001 ++}; ++ ++static u32 nphy_tpc_txgain_ipa_5g_2057rev7[] = { ++ 0x6f7f0031, 0x6f7f002e, 0x6f7f002c, 0x6f7f002a, ++ 0x6f7f0027, 0x6e7f002e, 0x6e7f002c, 0x6e7f002a, ++ 0x6d7f0030, 0x6d7f002d, 0x6d7f002a, 0x6d7f0028, ++ 0x6c7f0030, 0x6c7f002d, 0x6c7f002b, 0x6b7f002e, ++ 0x6b7f002c, 0x6b7f002a, 0x6b7f0027, 0x6a7f002e, ++ 0x6a7f002c, 0x6a7f002a, 0x697f0030, 0x697f002e, ++ 0x697f002b, 0x697f0029, 0x687f002f, 0x687f002d, ++ 0x687f002a, 0x687f0027, 0x677f002f, 0x677f002d, ++ 0x677f002a, 0x667f0031, 0x667f002e, 0x667f002c, ++ 0x667f002a, 0x657f0030, 0x657f002e, 0x657f002b, ++ 0x657f0029, 0x647f0030, 0x647f002d, 0x647f002b, ++ 0x647f0029, 0x637f002f, 0x637f002d, 0x637f002a, ++ 0x627f0030, 0x627f002d, 0x627f002b, 0x627f0029, ++ 0x617f0030, 0x617f002e, 0x617f002b, 0x617f0029, ++ 0x607f002f, 0x607f002d, 0x607f002a, 0x607f0027, ++ 0x607f0026, 0x607f0023, 0x607f0021, 0x607f0020, ++ 0x607f001e, 0x607f001c, 0x607f001a, 0x607f0019, ++ 0x607f0018, 0x607f0016, 0x607f0015, 0x607f0014, ++ 0x607f0012, 0x607f0012, 0x607f0011, 0x607f000f, ++ 0x607f000f, 0x607f000e, 0x607f000d, 0x607f000c, ++ 0x607f000c, 0x607f000b, 0x607f000b, 0x607f000a, ++ 0x607f0009, 0x607f0009, 0x607f0008, 0x607f0008, ++ 0x607f0008, 0x607f0007, 0x607f0007, 0x607f0006, ++ 0x607f0006, 0x607f0005, 0x607f0005, 0x607f0005, ++ 0x607f0005, 0x607f0005, 0x607f0004, 0x607f0004, ++ 0x607f0004, 0x607f0004, 0x607f0003, 0x607f0003, ++ 0x607f0003, 0x607f0003, 0x607f0002, 0x607f0002, ++ 0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002, ++ 0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002, ++ 0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002, ++ 0x607f0002, 0x607f0001, 0x607f0001, 0x607f0001, ++ 0x607f0001, 0x607f0001, 0x607f0001, 0x607f0001 ++}; ++ ++static s8 nphy_papd_pga_gain_delta_ipa_2g[] = { ++ -114, -108, -98, -91, -84, -78, -70, -62, ++ -54, -46, -39, -31, -23, -15, -8, 0 ++}; ++ ++static s8 nphy_papd_pga_gain_delta_ipa_5g[] = { ++ -100, -95, -89, -83, -77, -70, -63, -56, ++ -48, -41, -33, -25, -19, -12, -6, 0 ++}; ++ ++static s16 nphy_papd_padgain_dlt_2g_2057rev3n4[] = { ++ -159, -113, -86, -72, -62, -54, -48, -43, ++ -39, -35, -31, -28, -25, -23, -20, -18, ++ -17, -15, -13, -11, -10, -8, -7, -6, ++ -5, -4, -3, -3, -2, -1, -1, 0 ++}; ++ ++static s16 nphy_papd_padgain_dlt_2g_2057rev5[] = { ++ -109, -109, -82, -68, -58, -50, -44, -39, ++ -35, -31, -28, -26, -23, -21, -19, -17, ++ -16, -14, -13, -11, -10, -9, -8, -7, ++ -5, -5, -4, -3, -2, -1, -1, 0 ++}; ++ ++static s16 nphy_papd_padgain_dlt_2g_2057rev7[] = { ++ -122, -122, -95, -80, -69, -61, -54, -49, ++ -43, -39, -35, -32, -28, -26, -23, -21, ++ -18, -16, -15, -13, -11, -10, -8, -7, ++ -6, -5, -4, -3, -2, -1, -1, 0 ++}; ++ ++static s8 nphy_papd_pgagain_dlt_5g_2057[] = { ++ -107, -101, -92, -85, -78, -71, -62, -55, ++ -47, -39, -32, -24, -19, -12, -6, 0 ++}; ++ ++static s8 nphy_papd_pgagain_dlt_5g_2057rev7[] = { ++ -110, -104, -95, -88, -81, -74, -66, -58, ++ -50, -44, -36, -28, -23, -15, -8, 0 ++}; ++ ++static u8 pad_gain_codes_used_2057rev5[] = { ++ 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, ++ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ++}; ++ ++static u8 pad_gain_codes_used_2057rev7[] = { ++ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, ++ 5, 4, 3, 2, 1 ++}; ++ ++static u8 pad_all_gain_codes_2057[] = { ++ 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, ++ 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, ++ 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, ++ 1, 0 ++}; ++ ++static u8 pga_all_gain_codes_2057[] = { ++ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ++}; ++ ++static u32 nphy_papd_scaltbl[] = { ++ 0x0ae2002f, 0x0a3b0032, 0x09a70035, 0x09220038, ++ 0x0887003c, 0x081f003f, 0x07a20043, 0x07340047, ++ 0x06d2004b, 0x067a004f, 0x06170054, 0x05bf0059, ++ 0x0571005e, 0x051e0064, 0x04d3006a, 0x04910070, ++ 0x044c0077, 0x040f007e, 0x03d90085, 0x03a1008d, ++ 0x036f0095, 0x033d009e, 0x030b00a8, 0x02e000b2, ++ 0x02b900bc, 0x029200c7, 0x026d00d3, 0x024900e0, ++ 0x022900ed, 0x020a00fb, 0x01ec010a, 0x01d0011a, ++ 0x01b7012a, 0x019e013c, 0x0187014f, 0x01720162, ++ 0x015d0177, 0x0149018e, 0x013701a5, 0x012601be, ++ 0x011501d9, 0x010501f5, 0x00f70212, 0x00e90232, ++ 0x00dc0253, 0x00d00276, 0x00c4029c, 0x00b902c3, ++ 0x00af02ed, 0x00a5031a, 0x009c0349, 0x0093037a, ++ 0x008b03af, 0x008303e7, 0x007c0422, 0x00750461, ++ 0x006e04a3, 0x006804ea, 0x00620534, 0x005d0583, ++ 0x005805d7, 0x0053062f, 0x004e068d, 0x004a06f1 ++}; ++ ++static u32 nphy_tpc_txgain_rev3[] = { ++ 0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e, ++ 0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037, ++ 0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e, ++ 0x1e41003c, 0x1e41003b, 0x1e410039, 0x1e410037, ++ 0x1d410044, 0x1d410042, 0x1d410040, 0x1d41003e, ++ 0x1d41003c, 0x1d41003b, 0x1d410039, 0x1d410037, ++ 0x1c410044, 0x1c410042, 0x1c410040, 0x1c41003e, ++ 0x1c41003c, 0x1c41003b, 0x1c410039, 0x1c410037, ++ 0x1b410044, 0x1b410042, 0x1b410040, 0x1b41003e, ++ 0x1b41003c, 0x1b41003b, 0x1b410039, 0x1b410037, ++ 0x1a410044, 0x1a410042, 0x1a410040, 0x1a41003e, ++ 0x1a41003c, 0x1a41003b, 0x1a410039, 0x1a410037, ++ 0x19410044, 0x19410042, 0x19410040, 0x1941003e, ++ 0x1941003c, 0x1941003b, 0x19410039, 0x19410037, ++ 0x18410044, 0x18410042, 0x18410040, 0x1841003e, ++ 0x1841003c, 0x1841003b, 0x18410039, 0x18410037, ++ 0x17410044, 0x17410042, 0x17410040, 0x1741003e, ++ 0x1741003c, 0x1741003b, 0x17410039, 0x17410037, ++ 0x16410044, 0x16410042, 0x16410040, 0x1641003e, ++ 0x1641003c, 0x1641003b, 0x16410039, 0x16410037, ++ 0x15410044, 0x15410042, 0x15410040, 0x1541003e, ++ 0x1541003c, 0x1541003b, 0x15410039, 0x15410037, ++ 0x14410044, 0x14410042, 0x14410040, 0x1441003e, ++ 0x1441003c, 0x1441003b, 0x14410039, 0x14410037, ++ 0x13410044, 0x13410042, 0x13410040, 0x1341003e, ++ 0x1341003c, 0x1341003b, 0x13410039, 0x13410037, ++ 0x12410044, 0x12410042, 0x12410040, 0x1241003e, ++ 0x1241003c, 0x1241003b, 0x12410039, 0x12410037, ++ 0x11410044, 0x11410042, 0x11410040, 0x1141003e, ++ 0x1141003c, 0x1141003b, 0x11410039, 0x11410037, ++ 0x10410044, 0x10410042, 0x10410040, 0x1041003e, ++ 0x1041003c, 0x1041003b, 0x10410039, 0x10410037 ++}; ++ ++static u32 nphy_tpc_txgain_HiPwrEPA[] = { ++ 0x0f410044, 0x0f410042, 0x0f410040, 0x0f41003e, ++ 0x0f41003c, 0x0f41003b, 0x0f410039, 0x0f410037, ++ 0x0e410044, 0x0e410042, 0x0e410040, 0x0e41003e, ++ 0x0e41003c, 0x0e41003b, 0x0e410039, 0x0e410037, ++ 0x0d410044, 0x0d410042, 0x0d410040, 0x0d41003e, ++ 0x0d41003c, 0x0d41003b, 0x0d410039, 0x0d410037, ++ 0x0c410044, 0x0c410042, 0x0c410040, 0x0c41003e, ++ 0x0c41003c, 0x0c41003b, 0x0c410039, 0x0c410037, ++ 0x0b410044, 0x0b410042, 0x0b410040, 0x0b41003e, ++ 0x0b41003c, 0x0b41003b, 0x0b410039, 0x0b410037, ++ 0x0a410044, 0x0a410042, 0x0a410040, 0x0a41003e, ++ 0x0a41003c, 0x0a41003b, 0x0a410039, 0x0a410037, ++ 0x09410044, 0x09410042, 0x09410040, 0x0941003e, ++ 0x0941003c, 0x0941003b, 0x09410039, 0x09410037, ++ 0x08410044, 0x08410042, 0x08410040, 0x0841003e, ++ 0x0841003c, 0x0841003b, 0x08410039, 0x08410037, ++ 0x07410044, 0x07410042, 0x07410040, 0x0741003e, ++ 0x0741003c, 0x0741003b, 0x07410039, 0x07410037, ++ 0x06410044, 0x06410042, 0x06410040, 0x0641003e, ++ 0x0641003c, 0x0641003b, 0x06410039, 0x06410037, ++ 0x05410044, 0x05410042, 0x05410040, 0x0541003e, ++ 0x0541003c, 0x0541003b, 0x05410039, 0x05410037, ++ 0x04410044, 0x04410042, 0x04410040, 0x0441003e, ++ 0x0441003c, 0x0441003b, 0x04410039, 0x04410037, ++ 0x03410044, 0x03410042, 0x03410040, 0x0341003e, ++ 0x0341003c, 0x0341003b, 0x03410039, 0x03410037, ++ 0x02410044, 0x02410042, 0x02410040, 0x0241003e, ++ 0x0241003c, 0x0241003b, 0x02410039, 0x02410037, ++ 0x01410044, 0x01410042, 0x01410040, 0x0141003e, ++ 0x0141003c, 0x0141003b, 0x01410039, 0x01410037, ++ 0x00410044, 0x00410042, 0x00410040, 0x0041003e, ++ 0x0041003c, 0x0041003b, 0x00410039, 0x00410037 ++}; ++ ++static u32 nphy_tpc_txgain_epa_2057rev3[] = { ++ 0x80f90040, 0x80e10040, 0x80e1003c, 0x80c9003d, ++ 0x80b9003c, 0x80a9003d, 0x80a1003c, 0x8099003b, ++ 0x8091003b, 0x8089003a, 0x8081003a, 0x80790039, ++ 0x80710039, 0x8069003a, 0x8061003b, 0x8059003d, ++ 0x8051003f, 0x80490042, 0x8049003e, 0x8049003b, ++ 0x8041003e, 0x8041003b, 0x8039003e, 0x8039003b, ++ 0x80390038, 0x80390035, 0x8031003a, 0x80310036, ++ 0x80310033, 0x8029003a, 0x80290037, 0x80290034, ++ 0x80290031, 0x80210039, 0x80210036, 0x80210033, ++ 0x80210030, 0x8019003c, 0x80190039, 0x80190036, ++ 0x80190033, 0x80190030, 0x8019002d, 0x8019002b, ++ 0x80190028, 0x8011003a, 0x80110036, 0x80110033, ++ 0x80110030, 0x8011002e, 0x8011002b, 0x80110029, ++ 0x80110027, 0x80110024, 0x80110022, 0x80110020, ++ 0x8011001f, 0x8011001d, 0x8009003a, 0x80090037, ++ 0x80090034, 0x80090031, 0x8009002e, 0x8009002c, ++ 0x80090029, 0x80090027, 0x80090025, 0x80090023, ++ 0x80090021, 0x8009001f, 0x8009001d, 0x8009011d, ++ 0x8009021d, 0x8009031d, 0x8009041d, 0x8009051d, ++ 0x8009061d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d ++}; ++ ++static u32 nphy_tpc_txgain_epa_2057rev5[] = { ++ 0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d, ++ 0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b, ++ 0x1091003b, 0x1089003a, 0x1081003a, 0x10790039, ++ 0x10710039, 0x1069003a, 0x1061003b, 0x1059003d, ++ 0x1051003f, 0x10490042, 0x1049003e, 0x1049003b, ++ 0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b, ++ 0x10390038, 0x10390035, 0x1031003a, 0x10310036, ++ 0x10310033, 0x1029003a, 0x10290037, 0x10290034, ++ 0x10290031, 0x10210039, 0x10210036, 0x10210033, ++ 0x10210030, 0x1019003c, 0x10190039, 0x10190036, ++ 0x10190033, 0x10190030, 0x1019002d, 0x1019002b, ++ 0x10190028, 0x1011003a, 0x10110036, 0x10110033, ++ 0x10110030, 0x1011002e, 0x1011002b, 0x10110029, ++ 0x10110027, 0x10110024, 0x10110022, 0x10110020, ++ 0x1011001f, 0x1011001d, 0x1009003a, 0x10090037, ++ 0x10090034, 0x10090031, 0x1009002e, 0x1009002c, ++ 0x10090029, 0x10090027, 0x10090025, 0x10090023, ++ 0x10090021, 0x1009001f, 0x1009001d, 0x1009001b, ++ 0x1009001a, 0x10090018, 0x10090017, 0x10090016, ++ 0x10090015, 0x10090013, 0x10090012, 0x10090011, ++ 0x10090010, 0x1009000f, 0x1009000f, 0x1009000e, ++ 0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b, ++ 0x1009000a, 0x1009000a, 0x10090009, 0x10090009, ++ 0x10090008, 0x10090008, 0x10090007, 0x10090007, ++ 0x10090007, 0x10090006, 0x10090006, 0x10090005, ++ 0x10090005, 0x10090005, 0x10090005, 0x10090004, ++ 0x10090004, 0x10090004, 0x10090004, 0x10090003, ++ 0x10090003, 0x10090003, 0x10090003, 0x10090003, ++ 0x10090003, 0x10090002, 0x10090002, 0x10090002, ++ 0x10090002, 0x10090002, 0x10090002, 0x10090002, ++ 0x10090002, 0x10090002, 0x10090001, 0x10090001, ++ 0x10090001, 0x10090001, 0x10090001, 0x10090001 ++}; ++ ++static u32 nphy_tpc_5GHz_txgain_rev3[] = { ++ 0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e, ++ 0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037, ++ 0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e, ++ 0xcef7003c, 0xcef7003b, 0xcef70039, 0xcef70037, ++ 0xcdf70044, 0xcdf70042, 0xcdf70040, 0xcdf7003e, ++ 0xcdf7003c, 0xcdf7003b, 0xcdf70039, 0xcdf70037, ++ 0xccf70044, 0xccf70042, 0xccf70040, 0xccf7003e, ++ 0xccf7003c, 0xccf7003b, 0xccf70039, 0xccf70037, ++ 0xcbf70044, 0xcbf70042, 0xcbf70040, 0xcbf7003e, ++ 0xcbf7003c, 0xcbf7003b, 0xcbf70039, 0xcbf70037, ++ 0xcaf70044, 0xcaf70042, 0xcaf70040, 0xcaf7003e, ++ 0xcaf7003c, 0xcaf7003b, 0xcaf70039, 0xcaf70037, ++ 0xc9f70044, 0xc9f70042, 0xc9f70040, 0xc9f7003e, ++ 0xc9f7003c, 0xc9f7003b, 0xc9f70039, 0xc9f70037, ++ 0xc8f70044, 0xc8f70042, 0xc8f70040, 0xc8f7003e, ++ 0xc8f7003c, 0xc8f7003b, 0xc8f70039, 0xc8f70037, ++ 0xc7f70044, 0xc7f70042, 0xc7f70040, 0xc7f7003e, ++ 0xc7f7003c, 0xc7f7003b, 0xc7f70039, 0xc7f70037, ++ 0xc6f70044, 0xc6f70042, 0xc6f70040, 0xc6f7003e, ++ 0xc6f7003c, 0xc6f7003b, 0xc6f70039, 0xc6f70037, ++ 0xc5f70044, 0xc5f70042, 0xc5f70040, 0xc5f7003e, ++ 0xc5f7003c, 0xc5f7003b, 0xc5f70039, 0xc5f70037, ++ 0xc4f70044, 0xc4f70042, 0xc4f70040, 0xc4f7003e, ++ 0xc4f7003c, 0xc4f7003b, 0xc4f70039, 0xc4f70037, ++ 0xc3f70044, 0xc3f70042, 0xc3f70040, 0xc3f7003e, ++ 0xc3f7003c, 0xc3f7003b, 0xc3f70039, 0xc3f70037, ++ 0xc2f70044, 0xc2f70042, 0xc2f70040, 0xc2f7003e, ++ 0xc2f7003c, 0xc2f7003b, 0xc2f70039, 0xc2f70037, ++ 0xc1f70044, 0xc1f70042, 0xc1f70040, 0xc1f7003e, ++ 0xc1f7003c, 0xc1f7003b, 0xc1f70039, 0xc1f70037, ++ 0xc0f70044, 0xc0f70042, 0xc0f70040, 0xc0f7003e, ++ 0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037 ++}; ++ ++static u32 nphy_tpc_5GHz_txgain_rev4[] = { ++ 0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e, ++ 0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037, ++ 0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e, ++ 0x2ef2003c, 0x2ef2003b, 0x2ef20039, 0x2ef20037, ++ 0x2df20044, 0x2df20042, 0x2df20040, 0x2df2003e, ++ 0x2df2003c, 0x2df2003b, 0x2df20039, 0x2df20037, ++ 0x2cf20044, 0x2cf20042, 0x2cf20040, 0x2cf2003e, ++ 0x2cf2003c, 0x2cf2003b, 0x2cf20039, 0x2cf20037, ++ 0x2bf20044, 0x2bf20042, 0x2bf20040, 0x2bf2003e, ++ 0x2bf2003c, 0x2bf2003b, 0x2bf20039, 0x2bf20037, ++ 0x2af20044, 0x2af20042, 0x2af20040, 0x2af2003e, ++ 0x2af2003c, 0x2af2003b, 0x2af20039, 0x2af20037, ++ 0x29f20044, 0x29f20042, 0x29f20040, 0x29f2003e, ++ 0x29f2003c, 0x29f2003b, 0x29f20039, 0x29f20037, ++ 0x28f20044, 0x28f20042, 0x28f20040, 0x28f2003e, ++ 0x28f2003c, 0x28f2003b, 0x28f20039, 0x28f20037, ++ 0x27f20044, 0x27f20042, 0x27f20040, 0x27f2003e, ++ 0x27f2003c, 0x27f2003b, 0x27f20039, 0x27f20037, ++ 0x26f20044, 0x26f20042, 0x26f20040, 0x26f2003e, ++ 0x26f2003c, 0x26f2003b, 0x26f20039, 0x26f20037, ++ 0x25f20044, 0x25f20042, 0x25f20040, 0x25f2003e, ++ 0x25f2003c, 0x25f2003b, 0x25f20039, 0x25f20037, ++ 0x24f20044, 0x24f20042, 0x24f20040, 0x24f2003e, ++ 0x24f2003c, 0x24f2003b, 0x24f20039, 0x24f20038, ++ 0x23f20041, 0x23f20040, 0x23f2003f, 0x23f2003e, ++ 0x23f2003c, 0x23f2003b, 0x23f20039, 0x23f20037, ++ 0x22f20044, 0x22f20042, 0x22f20040, 0x22f2003e, ++ 0x22f2003c, 0x22f2003b, 0x22f20039, 0x22f20037, ++ 0x21f20044, 0x21f20042, 0x21f20040, 0x21f2003e, ++ 0x21f2003c, 0x21f2003b, 0x21f20039, 0x21f20037, ++ 0x20d20043, 0x20d20041, 0x20d2003e, 0x20d2003c, ++ 0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034 ++}; ++ ++static u32 nphy_tpc_5GHz_txgain_rev5[] = { ++ 0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044, ++ 0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c, ++ 0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e, ++ 0x0e62003c, 0x0e62003d, 0x0e62003b, 0x0e62003a, ++ 0x0d620043, 0x0d620041, 0x0d620040, 0x0d62003e, ++ 0x0d62003d, 0x0d62003c, 0x0d62003b, 0x0d62003a, ++ 0x0c620041, 0x0c620040, 0x0c62003f, 0x0c62003e, ++ 0x0c62003c, 0x0c62003b, 0x0c620039, 0x0c620037, ++ 0x0b620046, 0x0b620044, 0x0b620042, 0x0b620040, ++ 0x0b62003e, 0x0b62003c, 0x0b62003b, 0x0b62003a, ++ 0x0a620041, 0x0a620040, 0x0a62003e, 0x0a62003c, ++ 0x0a62003b, 0x0a62003a, 0x0a620039, 0x0a620038, ++ 0x0962003e, 0x0962003d, 0x0962003c, 0x0962003b, ++ 0x09620039, 0x09620037, 0x09620035, 0x09620033, ++ 0x08620044, 0x08620042, 0x08620040, 0x0862003e, ++ 0x0862003c, 0x0862003b, 0x0862003a, 0x08620039, ++ 0x07620043, 0x07620042, 0x07620040, 0x0762003f, ++ 0x0762003d, 0x0762003b, 0x0762003a, 0x07620039, ++ 0x0662003e, 0x0662003d, 0x0662003c, 0x0662003b, ++ 0x06620039, 0x06620037, 0x06620035, 0x06620033, ++ 0x05620046, 0x05620044, 0x05620042, 0x05620040, ++ 0x0562003e, 0x0562003c, 0x0562003b, 0x05620039, ++ 0x04620044, 0x04620042, 0x04620040, 0x0462003e, ++ 0x0462003c, 0x0462003b, 0x04620039, 0x04620038, ++ 0x0362003c, 0x0362003b, 0x0362003a, 0x03620039, ++ 0x03620038, 0x03620037, 0x03620035, 0x03620033, ++ 0x0262004c, 0x0262004a, 0x02620048, 0x02620047, ++ 0x02620046, 0x02620044, 0x02620043, 0x02620042, ++ 0x0162004a, 0x01620048, 0x01620046, 0x01620044, ++ 0x01620043, 0x01620042, 0x01620041, 0x01620040, ++ 0x00620042, 0x00620040, 0x0062003e, 0x0062003c, ++ 0x0062003b, 0x00620039, 0x00620037, 0x00620035 ++}; ++ ++static u32 nphy_tpc_5GHz_txgain_HiPwrEPA[] = { ++ 0x2ff10044, 0x2ff10042, 0x2ff10040, 0x2ff1003e, ++ 0x2ff1003c, 0x2ff1003b, 0x2ff10039, 0x2ff10037, ++ 0x2ef10044, 0x2ef10042, 0x2ef10040, 0x2ef1003e, ++ 0x2ef1003c, 0x2ef1003b, 0x2ef10039, 0x2ef10037, ++ 0x2df10044, 0x2df10042, 0x2df10040, 0x2df1003e, ++ 0x2df1003c, 0x2df1003b, 0x2df10039, 0x2df10037, ++ 0x2cf10044, 0x2cf10042, 0x2cf10040, 0x2cf1003e, ++ 0x2cf1003c, 0x2cf1003b, 0x2cf10039, 0x2cf10037, ++ 0x2bf10044, 0x2bf10042, 0x2bf10040, 0x2bf1003e, ++ 0x2bf1003c, 0x2bf1003b, 0x2bf10039, 0x2bf10037, ++ 0x2af10044, 0x2af10042, 0x2af10040, 0x2af1003e, ++ 0x2af1003c, 0x2af1003b, 0x2af10039, 0x2af10037, ++ 0x29f10044, 0x29f10042, 0x29f10040, 0x29f1003e, ++ 0x29f1003c, 0x29f1003b, 0x29f10039, 0x29f10037, ++ 0x28f10044, 0x28f10042, 0x28f10040, 0x28f1003e, ++ 0x28f1003c, 0x28f1003b, 0x28f10039, 0x28f10037, ++ 0x27f10044, 0x27f10042, 0x27f10040, 0x27f1003e, ++ 0x27f1003c, 0x27f1003b, 0x27f10039, 0x27f10037, ++ 0x26f10044, 0x26f10042, 0x26f10040, 0x26f1003e, ++ 0x26f1003c, 0x26f1003b, 0x26f10039, 0x26f10037, ++ 0x25f10044, 0x25f10042, 0x25f10040, 0x25f1003e, ++ 0x25f1003c, 0x25f1003b, 0x25f10039, 0x25f10037, ++ 0x24f10044, 0x24f10042, 0x24f10040, 0x24f1003e, ++ 0x24f1003c, 0x24f1003b, 0x24f10039, 0x24f10038, ++ 0x23f10041, 0x23f10040, 0x23f1003f, 0x23f1003e, ++ 0x23f1003c, 0x23f1003b, 0x23f10039, 0x23f10037, ++ 0x22f10044, 0x22f10042, 0x22f10040, 0x22f1003e, ++ 0x22f1003c, 0x22f1003b, 0x22f10039, 0x22f10037, ++ 0x21f10044, 0x21f10042, 0x21f10040, 0x21f1003e, ++ 0x21f1003c, 0x21f1003b, 0x21f10039, 0x21f10037, ++ 0x20d10043, 0x20d10041, 0x20d1003e, 0x20d1003c, ++ 0x20d1003a, 0x20d10038, 0x20d10036, 0x20d10034 ++}; ++ ++static u8 ant_sw_ctrl_tbl_rev8_2o3[] = { 0x14, 0x18 }; ++static u8 ant_sw_ctrl_tbl_rev8[] = { 0x4, 0x8, 0x4, 0x8, 0x11, 0x12 }; ++static u8 ant_sw_ctrl_tbl_rev8_2057v7_core0[] = { ++ 0x09, 0x0a, 0x15, 0x16, 0x09, 0x0a ++}; ++static u8 ant_sw_ctrl_tbl_rev8_2057v7_core1[] = { ++ 0x09, 0x0a, 0x09, 0x0a, 0x15, 0x16 ++}; ++ ++bool wlc_phy_bist_check_phy(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ u32 phybist0, phybist1, phybist2, phybist3, phybist4; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 16)) ++ return true; ++ ++ phybist0 = read_phy_reg(pi, 0x0e); ++ phybist1 = read_phy_reg(pi, 0x0f); ++ phybist2 = read_phy_reg(pi, 0xea); ++ phybist3 = read_phy_reg(pi, 0xeb); ++ phybist4 = read_phy_reg(pi, 0x156); ++ ++ if ((phybist0 == 0) && (phybist1 == 0x4000) && (phybist2 == 0x1fe0) && ++ (phybist3 == 0) && (phybist4 == 0)) ++ return true; ++ ++ return false; ++} ++ ++static void wlc_phy_bphy_init_nphy(struct brcms_phy *pi) ++{ ++ u16 addr, val; ++ ++ val = 0x1e1f; ++ for (addr = (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT); ++ addr <= (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT_END); addr++) { ++ write_phy_reg(pi, addr, val); ++ if (addr == (NPHY_TO_BPHY_OFF + 0x97)) ++ val = 0x3e3f; ++ else ++ val -= 0x0202; ++ } ++ ++ write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_STEP, 0x668); ++} ++ ++void ++wlc_phy_table_write_nphy(struct brcms_phy *pi, u32 id, u32 len, u32 offset, ++ u32 width, const void *data) ++{ ++ struct phytbl_info tbl; ++ ++ tbl.tbl_id = id; ++ tbl.tbl_len = len; ++ tbl.tbl_offset = offset; ++ tbl.tbl_width = width; ++ tbl.tbl_ptr = data; ++ wlc_phy_write_table_nphy(pi, &tbl); ++} ++ ++void ++wlc_phy_table_read_nphy(struct brcms_phy *pi, u32 id, u32 len, u32 offset, ++ u32 width, void *data) ++{ ++ struct phytbl_info tbl; ++ ++ tbl.tbl_id = id; ++ tbl.tbl_len = len; ++ tbl.tbl_offset = offset; ++ tbl.tbl_width = width; ++ tbl.tbl_ptr = data; ++ wlc_phy_read_table_nphy(pi, &tbl); ++} ++ ++static void ++wlc_phy_static_table_download_nphy(struct brcms_phy *pi) ++{ ++ uint idx; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 16)) { ++ for (idx = 0; idx < mimophytbl_info_sz_rev16; idx++) ++ wlc_phy_write_table_nphy(pi, ++ &mimophytbl_info_rev16[idx]); ++ } else if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ for (idx = 0; idx < mimophytbl_info_sz_rev7; idx++) ++ wlc_phy_write_table_nphy(pi, ++ &mimophytbl_info_rev7[idx]); ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ for (idx = 0; idx < mimophytbl_info_sz_rev3; idx++) ++ wlc_phy_write_table_nphy(pi, ++ &mimophytbl_info_rev3[idx]); ++ } else { ++ for (idx = 0; idx < mimophytbl_info_sz_rev0; idx++) ++ wlc_phy_write_table_nphy(pi, ++ &mimophytbl_info_rev0[idx]); ++ } ++} ++ ++static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi) ++{ ++ uint idx = 0; ++ u8 antswctrllut; ++ ++ if (pi->phy_init_por) ++ wlc_phy_static_table_download_nphy(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ? ++ pi->srom_fem2g.antswctrllut : pi->srom_fem5g. ++ antswctrllut; ++ ++ switch (antswctrllut) { ++ case 0: ++ ++ break; ++ ++ case 1: ++ ++ if (pi->aa2g == 7) ++ wlc_phy_table_write_nphy( ++ pi, ++ NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x21, 8, ++ &ant_sw_ctrl_tbl_rev8_2o3[0]); ++ else ++ wlc_phy_table_write_nphy( ++ pi, ++ NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x21, 8, ++ &ant_sw_ctrl_tbl_rev8 ++ [0]); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x25, 8, ++ &ant_sw_ctrl_tbl_rev8[2]); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x29, 8, ++ &ant_sw_ctrl_tbl_rev8[4]); ++ break; ++ ++ case 2: ++ ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x1, 8, ++ &ant_sw_ctrl_tbl_rev8_2057v7_core0[0]); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x5, 8, ++ &ant_sw_ctrl_tbl_rev8_2057v7_core0[2]); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x9, 8, ++ &ant_sw_ctrl_tbl_rev8_2057v7_core0[4]); ++ ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x21, 8, ++ &ant_sw_ctrl_tbl_rev8_2057v7_core1[0]); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x25, 8, ++ &ant_sw_ctrl_tbl_rev8_2057v7_core1[2]); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x29, 8, ++ &ant_sw_ctrl_tbl_rev8_2057v7_core1[4]); ++ break; ++ ++ default: ++ break; ++ } ++ ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ for (idx = 0; idx < mimophytbl_info_sz_rev3_volatile; idx++) { ++ ++ if (idx == ANT_SWCTRL_TBL_REV3_IDX) { ++ antswctrllut = ++ CHSPEC_IS2G(pi->radio_chanspec) ? ++ pi->srom_fem2g.antswctrllut : ++ pi->srom_fem5g.antswctrllut; ++ switch (antswctrllut) { ++ case 0: ++ wlc_phy_write_table_nphy( ++ pi, ++ &mimophytbl_info_rev3_volatile ++ [idx]); ++ break; ++ case 1: ++ wlc_phy_write_table_nphy( ++ pi, ++ &mimophytbl_info_rev3_volatile1 ++ [idx]); ++ break; ++ case 2: ++ wlc_phy_write_table_nphy( ++ pi, ++ &mimophytbl_info_rev3_volatile2 ++ [idx]); ++ break; ++ case 3: ++ wlc_phy_write_table_nphy( ++ pi, ++ &mimophytbl_info_rev3_volatile3 ++ [idx]); ++ break; ++ default: ++ break; ++ } ++ } else { ++ wlc_phy_write_table_nphy( ++ pi, ++ &mimophytbl_info_rev3_volatile[idx]); ++ } ++ } ++ } else { ++ for (idx = 0; idx < mimophytbl_info_sz_rev0_volatile; idx++) ++ wlc_phy_write_table_nphy(pi, ++ &mimophytbl_info_rev0_volatile ++ [idx]); ++ } ++} ++ ++static void ++wlc_phy_write_txmacreg_nphy(struct brcms_phy *pi, u16 holdoff, u16 delay) ++{ ++ write_phy_reg(pi, 0x77, holdoff); ++ write_phy_reg(pi, 0xb4, delay); ++} ++ ++void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs) ++{ ++ u16 holdoff, delay; ++ ++ if (rifs) { ++ ++ holdoff = 0x10; ++ delay = 0x258; ++ } else { ++ ++ holdoff = 0x15; ++ delay = 0x320; ++ } ++ ++ wlc_phy_write_txmacreg_nphy(pi, holdoff, delay); ++ ++ if (pi && pi->sh && (pi->sh->_rifs_phy != rifs)) ++ pi->sh->_rifs_phy = rifs; ++} ++ ++static void wlc_phy_txpwrctrl_config_nphy(struct brcms_phy *pi) ++{ ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ pi->nphy_txpwrctrl = PHY_TPC_HW_ON; ++ pi->phy_5g_pwrgain = true; ++ return; ++ } ++ ++ pi->nphy_txpwrctrl = PHY_TPC_HW_OFF; ++ pi->phy_5g_pwrgain = false; ++ ++ if ((pi->sh->boardflags2 & BFL2_TXPWRCTRL_EN) && ++ NREV_GE(pi->pubpi.phy_rev, 2) && (pi->sh->sromrev >= 4)) ++ pi->nphy_txpwrctrl = PHY_TPC_HW_ON; ++ else if ((pi->sh->sromrev >= 4) ++ && (pi->sh->boardflags2 & BFL2_5G_PWRGAIN)) ++ pi->phy_5g_pwrgain = true; ++} ++ ++static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi) ++{ ++ u16 bw40po, cddpo, stbcpo, bwduppo; ++ uint band_num; ++ struct phy_shim_info *shim = pi->sh->physhim; ++ ++ if (pi->sh->sromrev >= 9) ++ return; ++ ++ bw40po = (u16) wlapi_getintvar(shim, BRCMS_SROM_BW40PO); ++ pi->bw402gpo = bw40po & 0xf; ++ pi->bw405gpo = (bw40po & 0xf0) >> 4; ++ pi->bw405glpo = (bw40po & 0xf00) >> 8; ++ pi->bw405ghpo = (bw40po & 0xf000) >> 12; ++ ++ cddpo = (u16) wlapi_getintvar(shim, BRCMS_SROM_CDDPO); ++ pi->cdd2gpo = cddpo & 0xf; ++ pi->cdd5gpo = (cddpo & 0xf0) >> 4; ++ pi->cdd5glpo = (cddpo & 0xf00) >> 8; ++ pi->cdd5ghpo = (cddpo & 0xf000) >> 12; ++ ++ stbcpo = (u16) wlapi_getintvar(shim, BRCMS_SROM_STBCPO); ++ pi->stbc2gpo = stbcpo & 0xf; ++ pi->stbc5gpo = (stbcpo & 0xf0) >> 4; ++ pi->stbc5glpo = (stbcpo & 0xf00) >> 8; ++ pi->stbc5ghpo = (stbcpo & 0xf000) >> 12; ++ ++ bwduppo = (u16) wlapi_getintvar(shim, BRCMS_SROM_BWDUPPO); ++ pi->bwdup2gpo = bwduppo & 0xf; ++ pi->bwdup5gpo = (bwduppo & 0xf0) >> 4; ++ pi->bwdup5glpo = (bwduppo & 0xf00) >> 8; ++ pi->bwdup5ghpo = (bwduppo & 0xf000) >> 12; ++ ++ for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); ++ band_num++) { ++ switch (band_num) { ++ case 0: ++ ++ pi->nphy_txpid2g[PHY_CORE_0] = ++ (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TXPID2GA0); ++ pi->nphy_txpid2g[PHY_CORE_1] = ++ (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TXPID2GA1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g = ++ (s8) wlapi_getintvar(shim, ++ BRCMS_SROM_MAXP2GA0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g = ++ (s8) wlapi_getintvar(shim, ++ BRCMS_SROM_MAXP2GA1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA2GW0A0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA2GW0A1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA2GW1A0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA2GW1A1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA2GW2A0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA2GW2A1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g = ++ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT2GA0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g = ++ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT2GA1); ++ ++ pi->cck2gpo = (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_CCK2GPO); ++ ++ pi->ofdm2gpo = ++ (u32) wlapi_getintvar(shim, ++ BRCMS_SROM_OFDM2GPO); ++ ++ pi->mcs2gpo[0] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO0); ++ pi->mcs2gpo[1] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO1); ++ pi->mcs2gpo[2] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO2); ++ pi->mcs2gpo[3] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO3); ++ pi->mcs2gpo[4] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO4); ++ pi->mcs2gpo[5] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO5); ++ pi->mcs2gpo[6] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO6); ++ pi->mcs2gpo[7] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO7); ++ break; ++ case 1: ++ ++ pi->nphy_txpid5g[PHY_CORE_0] = ++ (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TXPID5GA0); ++ pi->nphy_txpid5g[PHY_CORE_1] = ++ (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TXPID5GA1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm = ++ (s8) wlapi_getintvar(shim, BRCMS_SROM_MAXP5GA0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm = ++ (s8) wlapi_getintvar(shim, ++ BRCMS_SROM_MAXP5GA1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GW0A0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GW0A1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GW1A0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GW1A1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GW2A0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GW2A1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm = ++ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT5GA0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm = ++ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT5GA1); ++ ++ pi->ofdm5gpo = ++ (u32) wlapi_getintvar(shim, ++ BRCMS_SROM_OFDM5GPO); ++ ++ pi->mcs5gpo[0] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GPO0); ++ pi->mcs5gpo[1] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GPO1); ++ pi->mcs5gpo[2] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GPO2); ++ pi->mcs5gpo[3] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GPO3); ++ pi->mcs5gpo[4] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GPO4); ++ pi->mcs5gpo[5] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GPO5); ++ pi->mcs5gpo[6] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GPO6); ++ pi->mcs5gpo[7] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GPO7); ++ break; ++ case 2: ++ ++ pi->nphy_txpid5gl[0] = ++ (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TXPID5GLA0); ++ pi->nphy_txpid5gl[1] = ++ (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TXPID5GLA1); ++ pi->nphy_pwrctrl_info[0].max_pwr_5gl = ++ (s8) wlapi_getintvar(shim, ++ BRCMS_SROM_MAXP5GLA0); ++ pi->nphy_pwrctrl_info[1].max_pwr_5gl = ++ (s8) wlapi_getintvar(shim, ++ BRCMS_SROM_MAXP5GLA1); ++ pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GLW0A0); ++ pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GLW0A1); ++ pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GLW1A0); ++ pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GLW1A1); ++ pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GLW2A0); ++ pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GLW2A1); ++ pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0; ++ pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0; ++ ++ pi->ofdm5glpo = ++ (u32) wlapi_getintvar(shim, ++ BRCMS_SROM_OFDM5GLPO); ++ ++ pi->mcs5glpo[0] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GLPO0); ++ pi->mcs5glpo[1] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GLPO1); ++ pi->mcs5glpo[2] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GLPO2); ++ pi->mcs5glpo[3] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GLPO3); ++ pi->mcs5glpo[4] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GLPO4); ++ pi->mcs5glpo[5] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GLPO5); ++ pi->mcs5glpo[6] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GLPO6); ++ pi->mcs5glpo[7] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GLPO7); ++ break; ++ case 3: ++ ++ pi->nphy_txpid5gh[0] = ++ (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TXPID5GHA0); ++ pi->nphy_txpid5gh[1] = ++ (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TXPID5GHA1); ++ pi->nphy_pwrctrl_info[0].max_pwr_5gh = ++ (s8) wlapi_getintvar(shim, ++ BRCMS_SROM_MAXP5GHA0); ++ pi->nphy_pwrctrl_info[1].max_pwr_5gh = ++ (s8) wlapi_getintvar(shim, ++ BRCMS_SROM_MAXP5GHA1); ++ pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GHW0A0); ++ pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GHW0A1); ++ pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GHW1A0); ++ pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GHW1A1); ++ pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GHW2A0); ++ pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GHW2A1); ++ pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0; ++ pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0; ++ ++ pi->ofdm5ghpo = ++ (u32) wlapi_getintvar(shim, ++ BRCMS_SROM_OFDM5GHPO); ++ ++ pi->mcs5ghpo[0] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GHPO0); ++ pi->mcs5ghpo[1] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GHPO1); ++ pi->mcs5ghpo[2] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GHPO2); ++ pi->mcs5ghpo[3] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GHPO3); ++ pi->mcs5ghpo[4] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GHPO4); ++ pi->mcs5ghpo[5] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GHPO5); ++ pi->mcs5ghpo[6] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GHPO6); ++ pi->mcs5ghpo[7] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GHPO7); ++ break; ++ } ++ } ++ ++ wlc_phy_txpwr_apply_nphy(pi); ++} ++ ++static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi) ++{ ++ struct phy_shim_info *shim = pi->sh->physhim; ++ ++ pi->antswitch = (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWITCH); ++ pi->aa2g = (u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G); ++ pi->aa5g = (u8) wlapi_getintvar(shim, BRCMS_SROM_AA5G); ++ ++ pi->srom_fem2g.tssipos = (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TSSIPOS2G); ++ pi->srom_fem2g.extpagain = (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_EXTPAGAIN2G); ++ pi->srom_fem2g.pdetrange = (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_PDETRANGE2G); ++ pi->srom_fem2g.triso = (u8) wlapi_getintvar(shim, BRCMS_SROM_TRISO2G); ++ pi->srom_fem2g.antswctrllut = ++ (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL2G); ++ ++ pi->srom_fem5g.tssipos = (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TSSIPOS5G); ++ pi->srom_fem5g.extpagain = (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_EXTPAGAIN5G); ++ pi->srom_fem5g.pdetrange = (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_PDETRANGE5G); ++ pi->srom_fem5g.triso = (u8) wlapi_getintvar(shim, BRCMS_SROM_TRISO5G); ++ if (wlapi_getvar(shim, BRCMS_SROM_ANTSWCTL5G)) ++ pi->srom_fem5g.antswctrllut = ++ (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL5G); ++ else ++ pi->srom_fem5g.antswctrllut = ++ (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL2G); ++ ++ wlc_phy_txpower_ipa_upd(pi); ++ ++ pi->phy_txcore_disable_temp = ++ (s16) wlapi_getintvar(shim, BRCMS_SROM_TEMPTHRESH); ++ if (pi->phy_txcore_disable_temp == 0) ++ pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP; ++ ++ pi->phy_tempsense_offset = (s8) wlapi_getintvar(shim, ++ BRCMS_SROM_TEMPOFFSET); ++ if (pi->phy_tempsense_offset != 0) { ++ if (pi->phy_tempsense_offset > ++ (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET)) ++ pi->phy_tempsense_offset = NPHY_SROM_MAXTEMPOFFSET; ++ else if (pi->phy_tempsense_offset < (NPHY_SROM_TEMPSHIFT + ++ NPHY_SROM_MINTEMPOFFSET)) ++ pi->phy_tempsense_offset = NPHY_SROM_MINTEMPOFFSET; ++ else ++ pi->phy_tempsense_offset -= NPHY_SROM_TEMPSHIFT; ++ } ++ ++ pi->phy_txcore_enable_temp = ++ pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP; ++ ++ pi->phycal_tempdelta = ++ (u8) wlapi_getintvar(shim, BRCMS_SROM_PHYCAL_TEMPDELTA); ++ if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA) ++ pi->phycal_tempdelta = 0; ++ ++ wlc_phy_txpwr_srom_read_ppr_nphy(pi); ++ ++ return true; ++} ++ ++bool wlc_phy_attach_nphy(struct brcms_phy *pi) ++{ ++ uint i; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 6)) ++ pi->phyhang_avoid = true; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) { ++ pi->nphy_gband_spurwar_en = true; ++ if (pi->sh->boardflags2 & BFL2_SPUR_WAR) ++ pi->nphy_aband_spurwar_en = true; ++ } ++ if (NREV_GE(pi->pubpi.phy_rev, 6) && NREV_LT(pi->pubpi.phy_rev, 7)) { ++ if (pi->sh->boardflags2 & BFL2_2G_SPUR_WAR) ++ pi->nphy_gband_spurwar2_en = true; ++ } ++ ++ pi->n_preamble_override = AUTO; ++ if (NREV_IS(pi->pubpi.phy_rev, 3) || NREV_IS(pi->pubpi.phy_rev, 4)) ++ pi->n_preamble_override = BRCMS_N_PREAMBLE_MIXEDMODE; ++ ++ pi->nphy_txrx_chain = AUTO; ++ pi->phy_scraminit = AUTO; ++ ++ pi->nphy_rxcalparams = 0x010100B5; ++ ++ pi->nphy_perical = PHY_PERICAL_MPHASE; ++ pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE; ++ pi->mphase_txcal_numcmds = MPHASE_TXCAL_NUMCMDS; ++ ++ pi->nphy_gain_boost = true; ++ pi->nphy_elna_gain_config = false; ++ pi->radio_is_on = false; ++ ++ for (i = 0; i < pi->pubpi.phy_corenum; i++) ++ pi->nphy_txpwrindex[i].index = AUTO; ++ ++ wlc_phy_txpwrctrl_config_nphy(pi); ++ if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON) ++ pi->hwpwrctrl_capable = true; ++ ++ pi->pi_fptr.init = wlc_phy_init_nphy; ++ pi->pi_fptr.calinit = wlc_phy_cal_init_nphy; ++ pi->pi_fptr.chanset = wlc_phy_chanspec_set_nphy; ++ pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_nphy; ++ ++ if (!wlc_phy_txpwr_srom_read_nphy(pi)) ++ return false; ++ ++ return true; ++} ++ ++static s32 get_rf_pwr_offset(struct brcms_phy *pi, s16 pga_gn, s16 pad_gn) ++{ ++ s32 rfpwr_offset = 0; ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if ((pi->pubpi.radiorev == 3) || ++ (pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) ++ rfpwr_offset = (s16) ++ nphy_papd_padgain_dlt_2g_2057rev3n4 ++ [pad_gn]; ++ else if (pi->pubpi.radiorev == 5) ++ rfpwr_offset = (s16) ++ nphy_papd_padgain_dlt_2g_2057rev5 ++ [pad_gn]; ++ else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == ++ 8)) ++ rfpwr_offset = (s16) ++ nphy_papd_padgain_dlt_2g_2057rev7 ++ [pad_gn]; ++ } else { ++ if ((pi->pubpi.radiorev == 3) || ++ (pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) ++ rfpwr_offset = (s16) ++ nphy_papd_pgagain_dlt_5g_2057 ++ [pga_gn]; ++ else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == ++ 8)) ++ rfpwr_offset = (s16) ++ nphy_papd_pgagain_dlt_5g_2057rev7 ++ [pga_gn]; ++ } ++ return rfpwr_offset; ++} ++ ++static void wlc_phy_update_mimoconfig_nphy(struct brcms_phy *pi, s32 preamble) ++{ ++ bool gf_preamble = false; ++ u16 val; ++ ++ if (preamble == BRCMS_N_PREAMBLE_GF) ++ gf_preamble = true; ++ ++ val = read_phy_reg(pi, 0xed); ++ ++ val |= RX_GF_MM_AUTO; ++ val &= ~RX_GF_OR_MM; ++ if (gf_preamble) ++ val |= RX_GF_OR_MM; ++ ++ write_phy_reg(pi, 0xed, val); ++} ++ ++static void wlc_phy_ipa_set_tx_digi_filts_nphy(struct brcms_phy *pi) ++{ ++ int j, type; ++ u16 addr_offset[] = { 0x186, 0x195, 0x2c5}; ++ ++ for (type = 0; type < 3; type++) { ++ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, addr_offset[type] + j, ++ NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]); ++ } ++ ++ if (pi->bw == WL_CHANSPEC_BW_40) { ++ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, 0x186 + j, ++ NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]); ++ } else { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, 0x186 + j, ++ NPHY_IPA_REV4_txdigi_filtcoeffs[5][j]); ++ } ++ ++ if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) { ++ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, 0x2c5 + j, ++ NPHY_IPA_REV4_txdigi_filtcoeffs[6][j]); ++ } ++ } ++} ++ ++static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi) ++{ ++ int j; ++ ++ if (pi->bw == WL_CHANSPEC_BW_40) { ++ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, 0x195 + j, ++ NPHY_IPA_REV4_txdigi_filtcoeffs[4][j]); ++ } else { ++ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, 0x186 + j, ++ NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]); ++ } ++} ++ ++static void ++wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *events, u8 *dlys, ++ u8 len) ++{ ++ u32 t1_offset, t2_offset; ++ u8 ctr; ++ u8 end_event = ++ NREV_GE(pi->pubpi.phy_rev, ++ 3) ? NPHY_REV3_RFSEQ_CMD_END : NPHY_RFSEQ_CMD_END; ++ u8 end_dly = 1; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ t1_offset = cmd << 4; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t1_offset, 8, ++ events); ++ t2_offset = t1_offset + 0x080; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t2_offset, 8, ++ dlys); ++ ++ for (ctr = len; ctr < 16; ctr++) { ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, ++ t1_offset + ctr, 8, &end_event); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, ++ t2_offset + ctr, 8, &end_dly); ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static u16 wlc_phy_read_lpf_bw_ctl_nphy(struct brcms_phy *pi, u16 offset) ++{ ++ u16 lpf_bw_ctl_val = 0; ++ u16 rx2tx_lpf_rc_lut_offset = 0; ++ ++ if (offset == 0) { ++ if (CHSPEC_IS40(pi->radio_chanspec)) ++ rx2tx_lpf_rc_lut_offset = 0x159; ++ else ++ rx2tx_lpf_rc_lut_offset = 0x154; ++ } else { ++ rx2tx_lpf_rc_lut_offset = offset; ++ } ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, ++ (u32) rx2tx_lpf_rc_lut_offset, 16, ++ &lpf_bw_ctl_val); ++ ++ lpf_bw_ctl_val = lpf_bw_ctl_val & 0x7; ++ ++ return lpf_bw_ctl_val; ++} ++ ++static void ++wlc_phy_rfctrl_override_nphy_rev7(struct brcms_phy *pi, u16 field, u16 value, ++ u8 core_mask, u8 off, u8 override_id) ++{ ++ u8 core_num; ++ u16 addr = 0, en_addr = 0, val_addr = 0, en_mask = 0, val_mask = 0; ++ u8 val_shift = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ en_mask = field; ++ for (core_num = 0; core_num < 2; core_num++) { ++ if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID0) { ++ ++ switch (field) { ++ case (0x1 << 2): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : ++ 0x7d; ++ val_mask = (0x1 << 1); ++ val_shift = 1; ++ break; ++ case (0x1 << 3): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : ++ 0x7d; ++ val_mask = (0x1 << 2); ++ val_shift = 2; ++ break; ++ case (0x1 << 4): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : ++ 0x7d; ++ val_mask = (0x1 << 4); ++ val_shift = 4; ++ break; ++ case (0x1 << 5): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : ++ 0x7d; ++ val_mask = (0x1 << 5); ++ val_shift = 5; ++ break; ++ case (0x1 << 6): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : ++ 0x7d; ++ val_mask = (0x1 << 6); ++ val_shift = 6; ++ break; ++ case (0x1 << 7): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : ++ 0x7d; ++ val_mask = (0x1 << 7); ++ val_shift = 7; ++ break; ++ case (0x1 << 10): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0xf8 : ++ 0xfa; ++ val_mask = (0x7 << 4); ++ val_shift = 4; ++ break; ++ case (0x1 << 11): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7b : ++ 0x7e; ++ val_mask = (0xffff << 0); ++ val_shift = 0; ++ break; ++ case (0x1 << 12): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7c : ++ 0x7f; ++ val_mask = (0xffff << 0); ++ val_shift = 0; ++ break; ++ case (0x3 << 13): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x348 : ++ 0x349; ++ val_mask = (0xff << 0); ++ val_shift = 0; ++ break; ++ case (0x1 << 13): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x348 : ++ 0x349; ++ val_mask = (0xf << 0); ++ val_shift = 0; ++ break; ++ default: ++ addr = 0xffff; ++ break; ++ } ++ } else if (override_id == ++ NPHY_REV7_RFCTRLOVERRIDE_ID1) { ++ ++ switch (field) { ++ case (0x1 << 1): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 1); ++ val_shift = 1; ++ break; ++ case (0x1 << 3): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 3); ++ val_shift = 3; ++ break; ++ case (0x1 << 5): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 5); ++ val_shift = 5; ++ break; ++ case (0x1 << 4): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 4); ++ val_shift = 4; ++ break; ++ case (0x1 << 2): ++ ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 2); ++ val_shift = 2; ++ break; ++ case (0x1 << 7): ++ ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x7 << 8); ++ val_shift = 8; ++ break; ++ case (0x1 << 11): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 14); ++ val_shift = 14; ++ break; ++ case (0x1 << 10): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 13); ++ val_shift = 13; ++ break; ++ case (0x1 << 9): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 12); ++ val_shift = 12; ++ break; ++ case (0x1 << 8): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 11); ++ val_shift = 11; ++ break; ++ case (0x1 << 6): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 6); ++ val_shift = 6; ++ break; ++ case (0x1 << 0): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 0); ++ val_shift = 0; ++ break; ++ default: ++ addr = 0xffff; ++ break; ++ } ++ } else if (override_id == ++ NPHY_REV7_RFCTRLOVERRIDE_ID2) { ++ ++ switch (field) { ++ case (0x1 << 3): ++ en_addr = (core_num == 0) ? 0x346 : ++ 0x347; ++ val_addr = (core_num == 0) ? 0x344 : ++ 0x345; ++ val_mask = (0x1 << 3); ++ val_shift = 3; ++ break; ++ case (0x1 << 1): ++ en_addr = (core_num == 0) ? 0x346 : ++ 0x347; ++ val_addr = (core_num == 0) ? 0x344 : ++ 0x345; ++ val_mask = (0x1 << 1); ++ val_shift = 1; ++ break; ++ case (0x1 << 0): ++ en_addr = (core_num == 0) ? 0x346 : ++ 0x347; ++ val_addr = (core_num == 0) ? 0x344 : ++ 0x345; ++ val_mask = (0x1 << 0); ++ val_shift = 0; ++ break; ++ case (0x1 << 2): ++ en_addr = (core_num == 0) ? 0x346 : ++ 0x347; ++ val_addr = (core_num == 0) ? 0x344 : ++ 0x345; ++ val_mask = (0x1 << 2); ++ val_shift = 2; ++ break; ++ case (0x1 << 4): ++ en_addr = (core_num == 0) ? 0x346 : ++ 0x347; ++ val_addr = (core_num == 0) ? 0x344 : ++ 0x345; ++ val_mask = (0x1 << 4); ++ val_shift = 4; ++ break; ++ default: ++ addr = 0xffff; ++ break; ++ } ++ } ++ ++ if (off) { ++ and_phy_reg(pi, en_addr, ~en_mask); ++ and_phy_reg(pi, val_addr, ~val_mask); ++ } else { ++ ++ if ((core_mask == 0) ++ || (core_mask & (1 << core_num))) { ++ or_phy_reg(pi, en_addr, en_mask); ++ ++ if (addr != 0xffff) ++ mod_phy_reg(pi, val_addr, ++ val_mask, ++ (value << ++ val_shift)); ++ } ++ } ++ } ++ } ++} ++ ++static void wlc_phy_adjust_lnagaintbl_nphy(struct brcms_phy *pi) ++{ ++ uint core; ++ int ctr; ++ s16 gain_delta[2]; ++ u8 curr_channel; ++ u16 minmax_gain[2]; ++ u16 regval[4]; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ if (pi->nphy_gain_boost) { ++ if ((CHSPEC_IS2G(pi->radio_chanspec))) { ++ ++ gain_delta[0] = 6; ++ gain_delta[1] = 6; ++ } else { ++ ++ curr_channel = CHSPEC_CHANNEL(pi->radio_chanspec); ++ gain_delta[0] = ++ (s16) ++ PHY_HW_ROUND(((nphy_lnagain_est0[0] * ++ curr_channel) + ++ nphy_lnagain_est0[1]), 13); ++ gain_delta[1] = ++ (s16) ++ PHY_HW_ROUND(((nphy_lnagain_est1[0] * ++ curr_channel) + ++ nphy_lnagain_est1[1]), 13); ++ } ++ } else { ++ ++ gain_delta[0] = 0; ++ gain_delta[1] = 0; ++ } ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ if (pi->nphy_elna_gain_config) { ++ ++ regval[0] = nphy_def_lnagains[2] + gain_delta[core]; ++ regval[1] = nphy_def_lnagains[3] + gain_delta[core]; ++ regval[2] = nphy_def_lnagains[3] + gain_delta[core]; ++ regval[3] = nphy_def_lnagains[3] + gain_delta[core]; ++ } else { ++ for (ctr = 0; ctr < 4; ctr++) ++ regval[ctr] = ++ nphy_def_lnagains[ctr] + ++ gain_delta[core]; ++ } ++ wlc_phy_table_write_nphy(pi, core, 4, 8, 16, regval); ++ ++ minmax_gain[core] = ++ (u16) (nphy_def_lnagains[2] + gain_delta[core] + 4); ++ } ++ ++ mod_phy_reg(pi, 0x1e, (0xff << 0), (minmax_gain[0] << 0)); ++ mod_phy_reg(pi, 0x34, (0xff << 0), (minmax_gain[1] << 0)); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static void ++wlc_phy_war_force_trsw_to_R_cliplo_nphy(struct brcms_phy *pi, u8 core) ++{ ++ if (core == PHY_CORE_0) { ++ write_phy_reg(pi, 0x38, 0x4); ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ write_phy_reg(pi, 0x37, 0x0060); ++ else ++ write_phy_reg(pi, 0x37, 0x1080); ++ } else if (core == PHY_CORE_1) { ++ write_phy_reg(pi, 0x2ae, 0x4); ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ write_phy_reg(pi, 0x2ad, 0x0060); ++ else ++ write_phy_reg(pi, 0x2ad, 0x1080); ++ } ++} ++ ++static void wlc_phy_war_txchain_upd_nphy(struct brcms_phy *pi, u8 txchain) ++{ ++ u8 txchain0, txchain1; ++ ++ txchain0 = txchain & 0x1; ++ txchain1 = (txchain & 0x2) >> 1; ++ if (!txchain0) ++ wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0); ++ ++ if (!txchain1) ++ wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1); ++} ++ ++static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi) ++{ ++ s8 lna1_gain_db[] = { 8, 13, 17, 22 }; ++ s8 lna2_gain_db[] = { -2, 7, 11, 15 }; ++ s8 tia_gain_db[] = { -4, -1, 2, 5, 5, 5, 5, 5, 5, 5 }; ++ s8 tia_gainbits[] = { ++ 0x0, 0x01, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }; ++ ++ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13)); ++ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13)); ++ ++ mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0)); ++ ++ mod_phy_reg(pi, 0x283, (0xff << 0), (0x3c << 0)); ++ mod_phy_reg(pi, 0x280, (0xff << 0), (0x3c << 0)); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x8, 8, ++ lna1_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x8, 8, ++ lna1_gain_db); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, 8, ++ lna2_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, 8, ++ lna2_gain_db); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8, ++ tia_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8, ++ tia_gain_db); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8, ++ tia_gainbits); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8, ++ tia_gainbits); ++ ++ write_phy_reg(pi, 0x37, 0x74); ++ write_phy_reg(pi, 0x2ad, 0x74); ++ write_phy_reg(pi, 0x38, 0x18); ++ write_phy_reg(pi, 0x2ae, 0x18); ++ ++ write_phy_reg(pi, 0x2b, 0xe8); ++ write_phy_reg(pi, 0x41, 0xe8); ++ ++ if (CHSPEC_IS20(pi->radio_chanspec)) { ++ ++ mod_phy_reg(pi, 0x300, (0x3f << 0), (0x12 << 0)); ++ mod_phy_reg(pi, 0x301, (0x3f << 0), (0x12 << 0)); ++ } else { ++ ++ mod_phy_reg(pi, 0x300, (0x3f << 0), (0x10 << 0)); ++ mod_phy_reg(pi, 0x301, (0x3f << 0), (0x10 << 0)); ++ } ++} ++ ++static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) ++{ ++ u16 currband; ++ s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 }; ++ s8 *lna1_gain_db = NULL; ++ s8 *lna1_gain_db_2 = NULL; ++ s8 *lna2_gain_db = NULL; ++ s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 }; ++ s8 *tia_gain_db; ++ s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 }; ++ s8 *tia_gainbits; ++ u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f }; ++ u16 *rfseq_init_gain; ++ u16 init_gaincode; ++ u16 clip1hi_gaincode; ++ u16 clip1md_gaincode = 0; ++ u16 clip1md_gaincode_B; ++ u16 clip1lo_gaincode; ++ u16 clip1lo_gaincode_B; ++ u8 crsminl_th = 0; ++ u8 crsminu_th; ++ u16 nbclip_th = 0; ++ u8 w1clip_th; ++ u16 freq; ++ s8 nvar_baseline_offset0 = 0, nvar_baseline_offset1 = 0; ++ u8 chg_nbclip_th = 0; ++ ++ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13)); ++ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13)); ++ ++ currband = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; ++ if (currband == 0) { ++ ++ lna1_gain_db = lna1G_gain_db_rev7; ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8, ++ lna1_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8, ++ lna1_gain_db); ++ ++ mod_phy_reg(pi, 0x283, (0xff << 0), (0x40 << 0)); ++ ++ if (CHSPEC_IS40(pi->radio_chanspec)) { ++ mod_phy_reg(pi, 0x280, (0xff << 0), (0x3e << 0)); ++ mod_phy_reg(pi, 0x283, (0xff << 0), (0x3e << 0)); ++ } ++ ++ mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0)); ++ ++ if (CHSPEC_IS20(pi->radio_chanspec)) { ++ mod_phy_reg(pi, 0x300, (0x3f << 0), (13 << 0)); ++ mod_phy_reg(pi, 0x301, (0x3f << 0), (13 << 0)); ++ } ++ } else { ++ ++ init_gaincode = 0x9e; ++ clip1hi_gaincode = 0x9e; ++ clip1md_gaincode_B = 0x24; ++ clip1lo_gaincode = 0x8a; ++ clip1lo_gaincode_B = 8; ++ rfseq_init_gain = rfseqA_init_gain_rev7; ++ ++ tia_gain_db = tiaA_gain_db_rev7; ++ tia_gainbits = tiaA_gainbits_rev7; ++ ++ freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec)); ++ if (CHSPEC_IS20(pi->radio_chanspec)) { ++ ++ w1clip_th = 25; ++ clip1md_gaincode = 0x82; ++ ++ if ((freq <= 5080) || (freq == 5825)) { ++ ++ s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 }; ++ s8 lna1A_gain_db_2_rev7[] = { ++ 11, 17, 22, 25}; ++ s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; ++ ++ crsminu_th = 0x3e; ++ lna1_gain_db = lna1A_gain_db_rev7; ++ lna1_gain_db_2 = lna1A_gain_db_2_rev7; ++ lna2_gain_db = lna2A_gain_db_rev7; ++ } else if ((freq >= 5500) && (freq <= 5700)) { ++ ++ s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 }; ++ s8 lna1A_gain_db_2_rev7[] = { ++ 12, 18, 22, 26}; ++ s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 }; ++ ++ crsminu_th = 0x45; ++ clip1md_gaincode_B = 0x14; ++ nbclip_th = 0xff; ++ chg_nbclip_th = 1; ++ lna1_gain_db = lna1A_gain_db_rev7; ++ lna1_gain_db_2 = lna1A_gain_db_2_rev7; ++ lna2_gain_db = lna2A_gain_db_rev7; ++ } else { ++ ++ s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 }; ++ s8 lna1A_gain_db_2_rev7[] = { ++ 12, 18, 22, 26}; ++ s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; ++ ++ crsminu_th = 0x41; ++ lna1_gain_db = lna1A_gain_db_rev7; ++ lna1_gain_db_2 = lna1A_gain_db_2_rev7; ++ lna2_gain_db = lna2A_gain_db_rev7; ++ } ++ ++ if (freq <= 4920) { ++ nvar_baseline_offset0 = 5; ++ nvar_baseline_offset1 = 5; ++ } else if ((freq > 4920) && (freq <= 5320)) { ++ nvar_baseline_offset0 = 3; ++ nvar_baseline_offset1 = 5; ++ } else if ((freq > 5320) && (freq <= 5700)) { ++ nvar_baseline_offset0 = 3; ++ nvar_baseline_offset1 = 2; ++ } else { ++ nvar_baseline_offset0 = 4; ++ nvar_baseline_offset1 = 0; ++ } ++ } else { ++ ++ crsminu_th = 0x3a; ++ crsminl_th = 0x3a; ++ w1clip_th = 20; ++ ++ if ((freq >= 4920) && (freq <= 5320)) { ++ nvar_baseline_offset0 = 4; ++ nvar_baseline_offset1 = 5; ++ } else if ((freq > 5320) && (freq <= 5550)) { ++ nvar_baseline_offset0 = 4; ++ nvar_baseline_offset1 = 2; ++ } else { ++ nvar_baseline_offset0 = 5; ++ nvar_baseline_offset1 = 3; ++ } ++ } ++ ++ write_phy_reg(pi, 0x20, init_gaincode); ++ write_phy_reg(pi, 0x2a7, init_gaincode); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, ++ pi->pubpi.phy_corenum, 0x106, 16, ++ rfseq_init_gain); ++ ++ write_phy_reg(pi, 0x22, clip1hi_gaincode); ++ write_phy_reg(pi, 0x2a9, clip1hi_gaincode); ++ ++ write_phy_reg(pi, 0x36, clip1md_gaincode_B); ++ write_phy_reg(pi, 0x2ac, clip1md_gaincode_B); ++ ++ write_phy_reg(pi, 0x37, clip1lo_gaincode); ++ write_phy_reg(pi, 0x2ad, clip1lo_gaincode); ++ write_phy_reg(pi, 0x38, clip1lo_gaincode_B); ++ write_phy_reg(pi, 0x2ae, clip1lo_gaincode_B); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8, ++ tia_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8, ++ tia_gain_db); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8, ++ tia_gainbits); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8, ++ tia_gainbits); ++ ++ mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0)); ++ ++ if (chg_nbclip_th == 1) { ++ write_phy_reg(pi, 0x2b, nbclip_th); ++ write_phy_reg(pi, 0x41, nbclip_th); ++ } ++ ++ mod_phy_reg(pi, 0x300, (0x3f << 0), (w1clip_th << 0)); ++ mod_phy_reg(pi, 0x301, (0x3f << 0), (w1clip_th << 0)); ++ ++ mod_phy_reg(pi, 0x2e4, ++ (0x3f << 0), (nvar_baseline_offset0 << 0)); ++ ++ mod_phy_reg(pi, 0x2e4, ++ (0x3f << 6), (nvar_baseline_offset1 << 6)); ++ ++ if (CHSPEC_IS20(pi->radio_chanspec)) { ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8, ++ lna1_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8, ++ lna1_gain_db_2); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, ++ 8, lna2_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, ++ 8, lna2_gain_db); ++ ++ write_phy_reg(pi, 0x24, clip1md_gaincode); ++ write_phy_reg(pi, 0x2ab, clip1md_gaincode); ++ } else { ++ mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0)); ++ } ++ } ++} ++ ++static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) ++{ ++ u16 w1th, hpf_code, currband; ++ int ctr; ++ u8 rfseq_updategainu_events[] = { ++ NPHY_RFSEQ_CMD_RX_GAIN, ++ NPHY_RFSEQ_CMD_CLR_HIQ_DIS, ++ NPHY_RFSEQ_CMD_SET_HPF_BW ++ }; ++ u8 rfseq_updategainu_dlys[] = { 10, 30, 1 }; ++ s8 lna1G_gain_db[] = { 7, 11, 16, 23 }; ++ s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 }; ++ s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 }; ++ s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 }; ++ s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 }; ++ s8 lna1A_gain_db[] = { 7, 11, 17, 23 }; ++ s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 }; ++ s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 }; ++ s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 }; ++ s8 *lna1_gain_db = NULL; ++ s8 lna2G_gain_db[] = { -5, 6, 10, 14 }; ++ s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 }; ++ s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 }; ++ s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 }; ++ s8 lna2A_gain_db[] = { -6, 2, 6, 10 }; ++ s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 }; ++ s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 }; ++ s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 }; ++ s8 *lna2_gain_db = NULL; ++ s8 tiaG_gain_db[] = { ++ 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A }; ++ s8 tiaA_gain_db[] = { ++ 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 }; ++ s8 tiaA_gain_db_rev4[] = { ++ 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; ++ s8 tiaA_gain_db_rev5[] = { ++ 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; ++ s8 tiaA_gain_db_rev6[] = { ++ 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; ++ s8 *tia_gain_db; ++ s8 tiaG_gainbits[] = { ++ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }; ++ s8 tiaA_gainbits[] = { ++ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 }; ++ s8 tiaA_gainbits_rev4[] = { ++ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; ++ s8 tiaA_gainbits_rev5[] = { ++ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; ++ s8 tiaA_gainbits_rev6[] = { ++ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; ++ s8 *tia_gainbits; ++ s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 }; ++ s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 }; ++ u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f }; ++ u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f }; ++ u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f }; ++ u16 rfseqG_init_gain_rev5_elna[] = { ++ 0x013f, 0x013f, 0x013f, 0x013f }; ++ u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f }; ++ u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f }; ++ u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f }; ++ u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f }; ++ u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f }; ++ u16 rfseqA_init_gain_rev4_elna[] = { ++ 0x314f, 0x314f, 0x314f, 0x314f }; ++ u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f }; ++ u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f }; ++ u16 *rfseq_init_gain; ++ u16 initG_gaincode = 0x627e; ++ u16 initG_gaincode_rev4 = 0x527e; ++ u16 initG_gaincode_rev5 = 0x427e; ++ u16 initG_gaincode_rev5_elna = 0x027e; ++ u16 initG_gaincode_rev6 = 0x527e; ++ u16 initG_gaincode_rev6_224B0 = 0x427e; ++ u16 initG_gaincode_rev6_elna = 0x127e; ++ u16 initA_gaincode = 0x52de; ++ u16 initA_gaincode_rev4 = 0x629e; ++ u16 initA_gaincode_rev4_elna = 0x329e; ++ u16 initA_gaincode_rev5 = 0x729e; ++ u16 initA_gaincode_rev6 = 0x729e; ++ u16 init_gaincode; ++ u16 clip1hiG_gaincode = 0x107e; ++ u16 clip1hiG_gaincode_rev4 = 0x007e; ++ u16 clip1hiG_gaincode_rev5 = 0x1076; ++ u16 clip1hiG_gaincode_rev6 = 0x007e; ++ u16 clip1hiA_gaincode = 0x00de; ++ u16 clip1hiA_gaincode_rev4 = 0x029e; ++ u16 clip1hiA_gaincode_rev5 = 0x029e; ++ u16 clip1hiA_gaincode_rev6 = 0x029e; ++ u16 clip1hi_gaincode; ++ u16 clip1mdG_gaincode = 0x0066; ++ u16 clip1mdA_gaincode = 0x00ca; ++ u16 clip1mdA_gaincode_rev4 = 0x1084; ++ u16 clip1mdA_gaincode_rev5 = 0x2084; ++ u16 clip1mdA_gaincode_rev6 = 0x2084; ++ u16 clip1md_gaincode = 0; ++ u16 clip1loG_gaincode = 0x0074; ++ u16 clip1loG_gaincode_rev5[] = { ++ 0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c ++ }; ++ u16 clip1loG_gaincode_rev6[] = { ++ 0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e ++ }; ++ u16 clip1loG_gaincode_rev6_224B0 = 0x1074; ++ u16 clip1loA_gaincode = 0x00cc; ++ u16 clip1loA_gaincode_rev4 = 0x0086; ++ u16 clip1loA_gaincode_rev5 = 0x2086; ++ u16 clip1loA_gaincode_rev6 = 0x2086; ++ u16 clip1lo_gaincode; ++ u8 crsminG_th = 0x18; ++ u8 crsminG_th_rev5 = 0x18; ++ u8 crsminG_th_rev6 = 0x18; ++ u8 crsminA_th = 0x1e; ++ u8 crsminA_th_rev4 = 0x24; ++ u8 crsminA_th_rev5 = 0x24; ++ u8 crsminA_th_rev6 = 0x24; ++ u8 crsmin_th; ++ u8 crsminlG_th = 0x18; ++ u8 crsminlG_th_rev5 = 0x18; ++ u8 crsminlG_th_rev6 = 0x18; ++ u8 crsminlA_th = 0x1e; ++ u8 crsminlA_th_rev4 = 0x24; ++ u8 crsminlA_th_rev5 = 0x24; ++ u8 crsminlA_th_rev6 = 0x24; ++ u8 crsminl_th = 0; ++ u8 crsminuG_th = 0x18; ++ u8 crsminuG_th_rev5 = 0x18; ++ u8 crsminuG_th_rev6 = 0x18; ++ u8 crsminuA_th = 0x1e; ++ u8 crsminuA_th_rev4 = 0x24; ++ u8 crsminuA_th_rev5 = 0x24; ++ u8 crsminuA_th_rev6 = 0x24; ++ u8 crsminuA_th_rev6_224B0 = 0x2d; ++ u8 crsminu_th; ++ u16 nbclipG_th = 0x20d; ++ u16 nbclipG_th_rev4 = 0x1a1; ++ u16 nbclipG_th_rev5 = 0x1d0; ++ u16 nbclipG_th_rev6 = 0x1d0; ++ u16 nbclipA_th = 0x1a1; ++ u16 nbclipA_th_rev4 = 0x107; ++ u16 nbclipA_th_rev5 = 0x0a9; ++ u16 nbclipA_th_rev6 = 0x0f0; ++ u16 nbclip_th = 0; ++ u8 w1clipG_th = 5; ++ u8 w1clipG_th_rev5 = 9; ++ u8 w1clipG_th_rev6 = 5; ++ u8 w1clipA_th = 25, w1clip_th; ++ u8 rssi_gain_default = 0x50; ++ u8 rssiG_gain_rev6_224B0 = 0x50; ++ u8 rssiA_gain_rev5 = 0x90; ++ u8 rssiA_gain_rev6 = 0x90; ++ u8 rssi_gain; ++ u16 regval[21]; ++ u8 triso; ++ ++ triso = (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.triso : ++ pi->srom_fem2g.triso; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (pi->pubpi.radiorev == 5) { ++ wlc_phy_workarounds_nphy_gainctrl_2057_rev5(pi); ++ } else if (pi->pubpi.radiorev == 7) { ++ wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi); ++ ++ mod_phy_reg(pi, 0x283, (0xff << 0), (0x44 << 0)); ++ mod_phy_reg(pi, 0x280, (0xff << 0), (0x44 << 0)); ++ ++ } else if ((pi->pubpi.radiorev == 3) ++ || (pi->pubpi.radiorev == 8)) { ++ wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi); ++ ++ if (pi->pubpi.radiorev == 8) { ++ mod_phy_reg(pi, 0x283, ++ (0xff << 0), (0x44 << 0)); ++ mod_phy_reg(pi, 0x280, ++ (0xff << 0), (0x44 << 0)); ++ } ++ } else { ++ wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi); ++ } ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ mod_phy_reg(pi, 0xa0, (0x1 << 6), (1 << 6)); ++ ++ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13)); ++ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13)); ++ ++ currband = ++ read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; ++ if (currband == 0) { ++ if (NREV_GE(pi->pubpi.phy_rev, 6)) { ++ if (pi->pubpi.radiorev == 11) { ++ lna1_gain_db = lna1G_gain_db_rev6_224B0; ++ lna2_gain_db = lna2G_gain_db_rev6_224B0; ++ rfseq_init_gain = ++ rfseqG_init_gain_rev6_224B0; ++ init_gaincode = ++ initG_gaincode_rev6_224B0; ++ clip1hi_gaincode = ++ clip1hiG_gaincode_rev6; ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6_224B0; ++ nbclip_th = nbclipG_th_rev6; ++ w1clip_th = w1clipG_th_rev6; ++ crsmin_th = crsminG_th_rev6; ++ crsminl_th = crsminlG_th_rev6; ++ crsminu_th = crsminuG_th_rev6; ++ rssi_gain = rssiG_gain_rev6_224B0; ++ } else { ++ lna1_gain_db = lna1G_gain_db_rev6; ++ lna2_gain_db = lna2G_gain_db_rev6; ++ if (pi->sh->boardflags & BFL_EXTLNA) { ++ ++ rfseq_init_gain = ++ rfseqG_init_gain_rev6_elna; ++ init_gaincode = ++ initG_gaincode_rev6_elna; ++ } else { ++ rfseq_init_gain = ++ rfseqG_init_gain_rev6; ++ init_gaincode = ++ initG_gaincode_rev6; ++ } ++ clip1hi_gaincode = ++ clip1hiG_gaincode_rev6; ++ switch (triso) { ++ case 0: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6 ++ [0]; ++ break; ++ case 1: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6 ++ [1]; ++ break; ++ case 2: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6 ++ [2]; ++ break; ++ case 3: ++ default: ++ ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6 ++ [3]; ++ break; ++ case 4: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6 ++ [4]; ++ break; ++ case 5: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6 ++ [5]; ++ break; ++ case 6: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6 ++ [6]; ++ break; ++ case 7: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6 ++ [7]; ++ break; ++ } ++ nbclip_th = nbclipG_th_rev6; ++ w1clip_th = w1clipG_th_rev6; ++ crsmin_th = crsminG_th_rev6; ++ crsminl_th = crsminlG_th_rev6; ++ crsminu_th = crsminuG_th_rev6; ++ rssi_gain = rssi_gain_default; ++ } ++ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { ++ lna1_gain_db = lna1G_gain_db_rev5; ++ lna2_gain_db = lna2G_gain_db_rev5; ++ if (pi->sh->boardflags & BFL_EXTLNA) { ++ ++ rfseq_init_gain = ++ rfseqG_init_gain_rev5_elna; ++ init_gaincode = ++ initG_gaincode_rev5_elna; ++ } else { ++ rfseq_init_gain = rfseqG_init_gain_rev5; ++ init_gaincode = initG_gaincode_rev5; ++ } ++ clip1hi_gaincode = clip1hiG_gaincode_rev5; ++ switch (triso) { ++ case 0: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[0]; ++ break; ++ case 1: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[1]; ++ break; ++ case 2: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[2]; ++ break; ++ case 3: ++ ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[3]; ++ break; ++ case 4: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[4]; ++ break; ++ case 5: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[5]; ++ break; ++ case 6: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[6]; ++ break; ++ case 7: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[7]; ++ break; ++ default: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[3]; ++ break; ++ } ++ nbclip_th = nbclipG_th_rev5; ++ w1clip_th = w1clipG_th_rev5; ++ crsmin_th = crsminG_th_rev5; ++ crsminl_th = crsminlG_th_rev5; ++ crsminu_th = crsminuG_th_rev5; ++ rssi_gain = rssi_gain_default; ++ } else if (NREV_IS(pi->pubpi.phy_rev, 4)) { ++ lna1_gain_db = lna1G_gain_db_rev4; ++ lna2_gain_db = lna2G_gain_db; ++ rfseq_init_gain = rfseqG_init_gain_rev4; ++ init_gaincode = initG_gaincode_rev4; ++ clip1hi_gaincode = clip1hiG_gaincode_rev4; ++ clip1lo_gaincode = clip1loG_gaincode; ++ nbclip_th = nbclipG_th_rev4; ++ w1clip_th = w1clipG_th; ++ crsmin_th = crsminG_th; ++ crsminl_th = crsminlG_th; ++ crsminu_th = crsminuG_th; ++ rssi_gain = rssi_gain_default; ++ } else { ++ lna1_gain_db = lna1G_gain_db; ++ lna2_gain_db = lna2G_gain_db; ++ rfseq_init_gain = rfseqG_init_gain; ++ init_gaincode = initG_gaincode; ++ clip1hi_gaincode = clip1hiG_gaincode; ++ clip1lo_gaincode = clip1loG_gaincode; ++ nbclip_th = nbclipG_th; ++ w1clip_th = w1clipG_th; ++ crsmin_th = crsminG_th; ++ crsminl_th = crsminlG_th; ++ crsminu_th = crsminuG_th; ++ rssi_gain = rssi_gain_default; ++ } ++ tia_gain_db = tiaG_gain_db; ++ tia_gainbits = tiaG_gainbits; ++ clip1md_gaincode = clip1mdG_gaincode; ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 6)) { ++ lna1_gain_db = lna1A_gain_db_rev6; ++ lna2_gain_db = lna2A_gain_db_rev6; ++ tia_gain_db = tiaA_gain_db_rev6; ++ tia_gainbits = tiaA_gainbits_rev6; ++ rfseq_init_gain = rfseqA_init_gain_rev6; ++ init_gaincode = initA_gaincode_rev6; ++ clip1hi_gaincode = clip1hiA_gaincode_rev6; ++ clip1md_gaincode = clip1mdA_gaincode_rev6; ++ clip1lo_gaincode = clip1loA_gaincode_rev6; ++ crsmin_th = crsminA_th_rev6; ++ crsminl_th = crsminlA_th_rev6; ++ if ((pi->pubpi.radiorev == 11) && ++ (CHSPEC_IS40(pi->radio_chanspec) == 0)) ++ crsminu_th = crsminuA_th_rev6_224B0; ++ else ++ crsminu_th = crsminuA_th_rev6; ++ ++ nbclip_th = nbclipA_th_rev6; ++ rssi_gain = rssiA_gain_rev6; ++ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { ++ lna1_gain_db = lna1A_gain_db_rev5; ++ lna2_gain_db = lna2A_gain_db_rev5; ++ tia_gain_db = tiaA_gain_db_rev5; ++ tia_gainbits = tiaA_gainbits_rev5; ++ rfseq_init_gain = rfseqA_init_gain_rev5; ++ init_gaincode = initA_gaincode_rev5; ++ clip1hi_gaincode = clip1hiA_gaincode_rev5; ++ clip1md_gaincode = clip1mdA_gaincode_rev5; ++ clip1lo_gaincode = clip1loA_gaincode_rev5; ++ crsmin_th = crsminA_th_rev5; ++ crsminl_th = crsminlA_th_rev5; ++ crsminu_th = crsminuA_th_rev5; ++ nbclip_th = nbclipA_th_rev5; ++ rssi_gain = rssiA_gain_rev5; ++ } else if (NREV_IS(pi->pubpi.phy_rev, 4)) { ++ lna1_gain_db = lna1A_gain_db_rev4; ++ lna2_gain_db = lna2A_gain_db_rev4; ++ tia_gain_db = tiaA_gain_db_rev4; ++ tia_gainbits = tiaA_gainbits_rev4; ++ if (pi->sh->boardflags & BFL_EXTLNA_5GHz) { ++ ++ rfseq_init_gain = ++ rfseqA_init_gain_rev4_elna; ++ init_gaincode = ++ initA_gaincode_rev4_elna; ++ } else { ++ rfseq_init_gain = rfseqA_init_gain_rev4; ++ init_gaincode = initA_gaincode_rev4; ++ } ++ clip1hi_gaincode = clip1hiA_gaincode_rev4; ++ clip1md_gaincode = clip1mdA_gaincode_rev4; ++ clip1lo_gaincode = clip1loA_gaincode_rev4; ++ crsmin_th = crsminA_th_rev4; ++ crsminl_th = crsminlA_th_rev4; ++ crsminu_th = crsminuA_th_rev4; ++ nbclip_th = nbclipA_th_rev4; ++ rssi_gain = rssi_gain_default; ++ } else { ++ lna1_gain_db = lna1A_gain_db; ++ lna2_gain_db = lna2A_gain_db; ++ tia_gain_db = tiaA_gain_db; ++ tia_gainbits = tiaA_gainbits; ++ rfseq_init_gain = rfseqA_init_gain; ++ init_gaincode = initA_gaincode; ++ clip1hi_gaincode = clip1hiA_gaincode; ++ clip1md_gaincode = clip1mdA_gaincode; ++ clip1lo_gaincode = clip1loA_gaincode; ++ crsmin_th = crsminA_th; ++ crsminl_th = crsminlA_th; ++ crsminu_th = crsminuA_th; ++ nbclip_th = nbclipA_th; ++ rssi_gain = rssi_gain_default; ++ } ++ w1clip_th = w1clipA_th; ++ } ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_BIASPOLE_LNAG1_IDAC | ++ RADIO_2056_RX0), 0x17); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_BIASPOLE_LNAG1_IDAC | ++ RADIO_2056_RX1), 0x17); ++ ++ write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX0), ++ 0xf0); ++ write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX1), ++ 0xf0); ++ ++ write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX0), ++ 0x0); ++ write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX1), ++ 0x0); ++ ++ write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX0), ++ rssi_gain); ++ write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX1), ++ rssi_gain); ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_BIASPOLE_LNAA1_IDAC | ++ RADIO_2056_RX0), 0x17); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_BIASPOLE_LNAA1_IDAC | ++ RADIO_2056_RX1), 0x17); ++ ++ write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX0), ++ 0xFF); ++ write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX1), ++ 0xFF); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, ++ 8, lna1_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, ++ 8, lna1_gain_db); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, ++ 8, lna2_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, ++ 8, lna2_gain_db); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, ++ 8, tia_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, ++ 8, tia_gain_db); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, ++ 8, tia_gainbits); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, ++ 8, tia_gainbits); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 6, 0x40, ++ 8, &lpf_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 6, 0x40, ++ 8, &lpf_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 6, 0x40, ++ 8, &lpf_gainbits); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 6, 0x40, ++ 8, &lpf_gainbits); ++ ++ write_phy_reg(pi, 0x20, init_gaincode); ++ write_phy_reg(pi, 0x2a7, init_gaincode); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, ++ pi->pubpi.phy_corenum, 0x106, 16, ++ rfseq_init_gain); ++ ++ write_phy_reg(pi, 0x22, clip1hi_gaincode); ++ write_phy_reg(pi, 0x2a9, clip1hi_gaincode); ++ ++ write_phy_reg(pi, 0x24, clip1md_gaincode); ++ write_phy_reg(pi, 0x2ab, clip1md_gaincode); ++ ++ write_phy_reg(pi, 0x37, clip1lo_gaincode); ++ write_phy_reg(pi, 0x2ad, clip1lo_gaincode); ++ ++ mod_phy_reg(pi, 0x27d, (0xff << 0), (crsmin_th << 0)); ++ mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0)); ++ mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0)); ++ ++ write_phy_reg(pi, 0x2b, nbclip_th); ++ write_phy_reg(pi, 0x41, nbclip_th); ++ ++ mod_phy_reg(pi, 0x27, (0x3f << 0), (w1clip_th << 0)); ++ mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1clip_th << 0)); ++ ++ write_phy_reg(pi, 0x150, 0x809c); ++ ++ } else { ++ ++ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13)); ++ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13)); ++ ++ write_phy_reg(pi, 0x2b, 0x84); ++ write_phy_reg(pi, 0x41, 0x84); ++ ++ if (CHSPEC_IS20(pi->radio_chanspec)) { ++ write_phy_reg(pi, 0x6b, 0x2b); ++ write_phy_reg(pi, 0x6c, 0x2b); ++ write_phy_reg(pi, 0x6d, 0x9); ++ write_phy_reg(pi, 0x6e, 0x9); ++ } ++ ++ w1th = NPHY_RSSICAL_W1_TARGET - 4; ++ mod_phy_reg(pi, 0x27, (0x3f << 0), (w1th << 0)); ++ mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1th << 0)); ++ ++ if (CHSPEC_IS20(pi->radio_chanspec)) { ++ mod_phy_reg(pi, 0x1c, (0x1f << 0), (0x1 << 0)); ++ mod_phy_reg(pi, 0x32, (0x1f << 0), (0x1 << 0)); ++ ++ mod_phy_reg(pi, 0x1d, (0x1f << 0), (0x1 << 0)); ++ mod_phy_reg(pi, 0x33, (0x1f << 0), (0x1 << 0)); ++ } ++ ++ write_phy_reg(pi, 0x150, 0x809c); ++ ++ if (pi->nphy_gain_boost) ++ if ((CHSPEC_IS2G(pi->radio_chanspec)) && ++ (CHSPEC_IS40(pi->radio_chanspec))) ++ hpf_code = 4; ++ else ++ hpf_code = 5; ++ else if (CHSPEC_IS40(pi->radio_chanspec)) ++ hpf_code = 6; ++ else ++ hpf_code = 7; ++ ++ mod_phy_reg(pi, 0x20, (0x1f << 7), (hpf_code << 7)); ++ mod_phy_reg(pi, 0x36, (0x1f << 7), (hpf_code << 7)); ++ ++ for (ctr = 0; ctr < 4; ctr++) ++ regval[ctr] = (hpf_code << 8) | 0x7c; ++ wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval); ++ ++ wlc_phy_adjust_lnagaintbl_nphy(pi); ++ ++ if (pi->nphy_elna_gain_config) { ++ regval[0] = 0; ++ regval[1] = 1; ++ regval[2] = 1; ++ regval[3] = 1; ++ wlc_phy_table_write_nphy(pi, 2, 4, 8, 16, regval); ++ wlc_phy_table_write_nphy(pi, 3, 4, 8, 16, regval); ++ ++ for (ctr = 0; ctr < 4; ctr++) ++ regval[ctr] = (hpf_code << 8) | 0x74; ++ wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval); ++ } ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 2)) { ++ for (ctr = 0; ctr < 21; ctr++) ++ regval[ctr] = 3 * ctr; ++ wlc_phy_table_write_nphy(pi, 0, 21, 32, 16, regval); ++ wlc_phy_table_write_nphy(pi, 1, 21, 32, 16, regval); ++ ++ for (ctr = 0; ctr < 21; ctr++) ++ regval[ctr] = (u16) ctr; ++ wlc_phy_table_write_nphy(pi, 2, 21, 32, 16, regval); ++ wlc_phy_table_write_nphy(pi, 3, 21, 32, 16, regval); ++ } ++ ++ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_UPDATEGAINU, ++ rfseq_updategainu_events, ++ rfseq_updategainu_dlys, ++ sizeof(rfseq_updategainu_events) / ++ sizeof(rfseq_updategainu_events[0])); ++ ++ mod_phy_reg(pi, 0x153, (0xff << 8), (90 << 8)); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ mod_phy_reg(pi, ++ (NPHY_TO_BPHY_OFF + BPHY_OPTIONAL_MODES), ++ 0x7f, 0x4); ++ } ++} ++ ++static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) ++{ ++ u8 rfseq_rx2tx_events[] = { ++ NPHY_RFSEQ_CMD_NOP, ++ NPHY_RFSEQ_CMD_RXG_FBW, ++ NPHY_RFSEQ_CMD_TR_SWITCH, ++ NPHY_RFSEQ_CMD_CLR_HIQ_DIS, ++ NPHY_RFSEQ_CMD_RXPD_TXPD, ++ NPHY_RFSEQ_CMD_TX_GAIN, ++ NPHY_RFSEQ_CMD_EXT_PA ++ }; ++ u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 }; ++ u8 rfseq_tx2rx_events[] = { ++ NPHY_RFSEQ_CMD_NOP, ++ NPHY_RFSEQ_CMD_EXT_PA, ++ NPHY_RFSEQ_CMD_TX_GAIN, ++ NPHY_RFSEQ_CMD_RXPD_TXPD, ++ NPHY_RFSEQ_CMD_TR_SWITCH, ++ NPHY_RFSEQ_CMD_RXG_FBW, ++ NPHY_RFSEQ_CMD_CLR_HIQ_DIS ++ }; ++ u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 }; ++ u8 rfseq_tx2rx_events_rev3[] = { ++ NPHY_REV3_RFSEQ_CMD_EXT_PA, ++ NPHY_REV3_RFSEQ_CMD_INT_PA_PU, ++ NPHY_REV3_RFSEQ_CMD_TX_GAIN, ++ NPHY_REV3_RFSEQ_CMD_RXPD_TXPD, ++ NPHY_REV3_RFSEQ_CMD_TR_SWITCH, ++ NPHY_REV3_RFSEQ_CMD_RXG_FBW, ++ NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, ++ NPHY_REV3_RFSEQ_CMD_END ++ }; ++ u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 }; ++ u8 rfseq_rx2tx_events_rev3[] = { ++ NPHY_REV3_RFSEQ_CMD_NOP, ++ NPHY_REV3_RFSEQ_CMD_RXG_FBW, ++ NPHY_REV3_RFSEQ_CMD_TR_SWITCH, ++ NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, ++ NPHY_REV3_RFSEQ_CMD_RXPD_TXPD, ++ NPHY_REV3_RFSEQ_CMD_TX_GAIN, ++ NPHY_REV3_RFSEQ_CMD_INT_PA_PU, ++ NPHY_REV3_RFSEQ_CMD_EXT_PA, ++ NPHY_REV3_RFSEQ_CMD_END ++ }; ++ u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 }; ++ ++ u8 rfseq_rx2tx_events_rev3_ipa[] = { ++ NPHY_REV3_RFSEQ_CMD_NOP, ++ NPHY_REV3_RFSEQ_CMD_RXG_FBW, ++ NPHY_REV3_RFSEQ_CMD_TR_SWITCH, ++ NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, ++ NPHY_REV3_RFSEQ_CMD_RXPD_TXPD, ++ NPHY_REV3_RFSEQ_CMD_TX_GAIN, ++ NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS, ++ NPHY_REV3_RFSEQ_CMD_INT_PA_PU, ++ NPHY_REV3_RFSEQ_CMD_END ++ }; ++ u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; ++ u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f }; ++ ++ s16 alpha0, alpha1, alpha2; ++ s16 beta0, beta1, beta2; ++ u32 leg_data_weights, ht_data_weights, nss1_data_weights, ++ stbc_data_weights; ++ u8 chan_freq_range = 0; ++ u16 dac_control = 0x0002; ++ u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 }; ++ u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 }; ++ u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 }; ++ u16 aux_adc_vmid_rev3[] = { 0xa2, 0xb4, 0xb4, 0x89 }; ++ u16 *aux_adc_vmid; ++ u16 aux_adc_gain_rev7[] = { 0x02, 0x02, 0x02, 0x02 }; ++ u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 }; ++ u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 }; ++ u16 *aux_adc_gain; ++ u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 }; ++ u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 }; ++ s32 min_nvar_val = 0x18d; ++ s32 min_nvar_offset_6mbps = 20; ++ u8 pdetrange; ++ u8 triso; ++ u16 regval; ++ u16 afectrl_adc_ctrl1_rev7 = 0x20; ++ u16 afectrl_adc_ctrl2_rev7 = 0x0; ++ u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77; ++ u16 rfseq_tx2rx_lpf_h_hpc_rev7 = 0x77; ++ u16 rfseq_pktgn_lpf_h_hpc_rev7 = 0x77; ++ u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 }; ++ u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; ++ u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; ++ u16 ipalvlshift_3p3_war_en = 0; ++ u16 rccal_bcap_val, rccal_scap_val; ++ u16 rccal_tx20_11b_bcap = 0; ++ u16 rccal_tx20_11b_scap = 0; ++ u16 rccal_tx20_11n_bcap = 0; ++ u16 rccal_tx20_11n_scap = 0; ++ u16 rccal_tx40_11n_bcap = 0; ++ u16 rccal_tx40_11n_scap = 0; ++ u16 rx2tx_lpf_rc_lut_tx20_11b = 0; ++ u16 rx2tx_lpf_rc_lut_tx20_11n = 0; ++ u16 rx2tx_lpf_rc_lut_tx40_11n = 0; ++ u16 tx_lpf_bw_ofdm_20mhz = 0; ++ u16 tx_lpf_bw_ofdm_40mhz = 0; ++ u16 tx_lpf_bw_11b = 0; ++ u16 ipa2g_mainbias, ipa2g_casconv, ipa2g_biasfilt; ++ u16 txgm_idac_bleed = 0; ++ bool rccal_ovrd = false; ++ u16 freq; ++ int coreNum; ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) ++ wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 0); ++ else ++ wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 1); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ or_phy_reg(pi, 0xb1, NPHY_IQFlip_ADC1 | NPHY_IQFlip_ADC2); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7)) { ++ mod_phy_reg(pi, 0x221, (0x1 << 4), (1 << 4)); ++ ++ mod_phy_reg(pi, 0x160, (0x7f << 0), (32 << 0)); ++ mod_phy_reg(pi, 0x160, (0x7f << 8), (39 << 8)); ++ mod_phy_reg(pi, 0x161, (0x7f << 0), (46 << 0)); ++ mod_phy_reg(pi, 0x161, (0x7f << 8), (51 << 8)); ++ mod_phy_reg(pi, 0x162, (0x7f << 0), (55 << 0)); ++ mod_phy_reg(pi, 0x162, (0x7f << 8), (58 << 8)); ++ mod_phy_reg(pi, 0x163, (0x7f << 0), (60 << 0)); ++ mod_phy_reg(pi, 0x163, (0x7f << 8), (62 << 8)); ++ mod_phy_reg(pi, 0x164, (0x7f << 0), (62 << 0)); ++ mod_phy_reg(pi, 0x164, (0x7f << 8), (63 << 8)); ++ mod_phy_reg(pi, 0x165, (0x7f << 0), (63 << 0)); ++ mod_phy_reg(pi, 0x165, (0x7f << 8), (64 << 8)); ++ mod_phy_reg(pi, 0x166, (0x7f << 0), (64 << 0)); ++ mod_phy_reg(pi, 0x166, (0x7f << 8), (64 << 8)); ++ mod_phy_reg(pi, 0x167, (0x7f << 0), (64 << 0)); ++ mod_phy_reg(pi, 0x167, (0x7f << 8), (64 << 8)); ++ } ++ ++ if (NREV_LE(pi->pubpi.phy_rev, 8)) { ++ write_phy_reg(pi, 0x23f, 0x1b0); ++ write_phy_reg(pi, 0x240, 0x1b0); ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 8)) ++ mod_phy_reg(pi, 0xbd, (0xff << 0), (114 << 0)); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16, ++ &dac_control); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16, ++ &dac_control); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, ++ 1, 0, 32, &leg_data_weights); ++ leg_data_weights = leg_data_weights & 0xffffff; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, ++ 1, 0, 32, &leg_data_weights); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, ++ 2, 0x15e, 16, ++ rfseq_rx2tx_dacbufpu_rev7); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x16e, 16, ++ rfseq_rx2tx_dacbufpu_rev7); ++ ++ if (PHY_IPA(pi)) ++ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, ++ rfseq_rx2tx_events_rev3_ipa, ++ rfseq_rx2tx_dlys_rev3_ipa, ++ sizeof ++ (rfseq_rx2tx_events_rev3_ipa) / ++ sizeof ++ (rfseq_rx2tx_events_rev3_ipa ++ [0])); ++ ++ mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14)); ++ mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14)); ++ ++ tx_lpf_bw_ofdm_20mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x154); ++ tx_lpf_bw_ofdm_40mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x159); ++ tx_lpf_bw_11b = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x152); ++ ++ if (PHY_IPA(pi)) { ++ ++ if (((pi->pubpi.radiorev == 5) ++ && (CHSPEC_IS40(pi->radio_chanspec) == 1)) ++ || (pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) { ++ ++ rccal_bcap_val = ++ read_radio_reg( ++ pi, ++ RADIO_2057_RCCAL_BCAP_VAL); ++ rccal_scap_val = ++ read_radio_reg( ++ pi, ++ RADIO_2057_RCCAL_SCAP_VAL); ++ ++ rccal_tx20_11b_bcap = rccal_bcap_val; ++ rccal_tx20_11b_scap = rccal_scap_val; ++ ++ if ((pi->pubpi.radiorev == 5) && ++ (CHSPEC_IS40(pi->radio_chanspec) == 1)) { ++ ++ rccal_tx20_11n_bcap = rccal_bcap_val; ++ rccal_tx20_11n_scap = rccal_scap_val; ++ rccal_tx40_11n_bcap = 0xc; ++ rccal_tx40_11n_scap = 0xc; ++ ++ rccal_ovrd = true; ++ ++ } else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) { ++ ++ tx_lpf_bw_ofdm_20mhz = 4; ++ tx_lpf_bw_11b = 1; ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ rccal_tx20_11n_bcap = 0xc; ++ rccal_tx20_11n_scap = 0xc; ++ rccal_tx40_11n_bcap = 0xa; ++ rccal_tx40_11n_scap = 0xa; ++ } else { ++ rccal_tx20_11n_bcap = 0x14; ++ rccal_tx20_11n_scap = 0x14; ++ rccal_tx40_11n_bcap = 0xf; ++ rccal_tx40_11n_scap = 0xf; ++ } ++ ++ rccal_ovrd = true; ++ } ++ } ++ ++ } else { ++ ++ if (pi->pubpi.radiorev == 5) { ++ ++ tx_lpf_bw_ofdm_20mhz = 1; ++ tx_lpf_bw_ofdm_40mhz = 3; ++ ++ rccal_bcap_val = ++ read_radio_reg( ++ pi, ++ RADIO_2057_RCCAL_BCAP_VAL); ++ rccal_scap_val = ++ read_radio_reg( ++ pi, ++ RADIO_2057_RCCAL_SCAP_VAL); ++ ++ rccal_tx20_11b_bcap = rccal_bcap_val; ++ rccal_tx20_11b_scap = rccal_scap_val; ++ ++ rccal_tx20_11n_bcap = 0x13; ++ rccal_tx20_11n_scap = 0x11; ++ rccal_tx40_11n_bcap = 0x13; ++ rccal_tx40_11n_scap = 0x11; ++ ++ rccal_ovrd = true; ++ } ++ } ++ ++ if (rccal_ovrd) { ++ ++ rx2tx_lpf_rc_lut_tx20_11b = ++ (rccal_tx20_11b_bcap << 8) | ++ (rccal_tx20_11b_scap << 3) | ++ tx_lpf_bw_11b; ++ rx2tx_lpf_rc_lut_tx20_11n = ++ (rccal_tx20_11n_bcap << 8) | ++ (rccal_tx20_11n_scap << 3) | ++ tx_lpf_bw_ofdm_20mhz; ++ rx2tx_lpf_rc_lut_tx40_11n = ++ (rccal_tx40_11n_bcap << 8) | ++ (rccal_tx40_11n_scap << 3) | ++ tx_lpf_bw_ofdm_40mhz; ++ ++ for (coreNum = 0; coreNum <= 1; coreNum++) { ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_RFSEQ, ++ 1, ++ 0x152 + coreNum * 0x10, ++ 16, ++ &rx2tx_lpf_rc_lut_tx20_11b); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_RFSEQ, ++ 1, ++ 0x153 + coreNum * 0x10, ++ 16, ++ &rx2tx_lpf_rc_lut_tx20_11n); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_RFSEQ, ++ 1, ++ 0x154 + coreNum * 0x10, ++ 16, ++ &rx2tx_lpf_rc_lut_tx20_11n); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_RFSEQ, ++ 1, ++ 0x155 + coreNum * 0x10, ++ 16, ++ &rx2tx_lpf_rc_lut_tx40_11n); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_RFSEQ, ++ 1, ++ 0x156 + coreNum * 0x10, ++ 16, ++ &rx2tx_lpf_rc_lut_tx40_11n); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_RFSEQ, ++ 1, ++ 0x157 + coreNum * 0x10, ++ 16, ++ &rx2tx_lpf_rc_lut_tx40_11n); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_RFSEQ, ++ 1, ++ 0x158 + coreNum * 0x10, ++ 16, ++ &rx2tx_lpf_rc_lut_tx40_11n); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_RFSEQ, ++ 1, ++ 0x159 + coreNum * 0x10, ++ 16, ++ &rx2tx_lpf_rc_lut_tx40_11n); ++ } ++ ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 4), ++ 1, 0x3, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ } ++ ++ write_phy_reg(pi, 0x32f, 0x3); ++ ++ if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 2), ++ 1, 0x3, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ ++ if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) { ++ if ((pi->sh->sromrev >= 8) ++ && (pi->sh->boardflags2 & BFL2_IPALVLSHIFT_3P3)) ++ ipalvlshift_3p3_war_en = 1; ++ ++ if (ipalvlshift_3p3_war_en) { ++ write_radio_reg(pi, RADIO_2057_GPAIO_CONFIG, ++ 0x5); ++ write_radio_reg(pi, RADIO_2057_GPAIO_SEL1, ++ 0x30); ++ write_radio_reg(pi, RADIO_2057_GPAIO_SEL0, 0x0); ++ or_radio_reg(pi, ++ RADIO_2057_RXTXBIAS_CONFIG_CORE0, ++ 0x1); ++ or_radio_reg(pi, ++ RADIO_2057_RXTXBIAS_CONFIG_CORE1, ++ 0x1); ++ ++ ipa2g_mainbias = 0x1f; ++ ++ ipa2g_casconv = 0x6f; ++ ++ ipa2g_biasfilt = 0xaa; ++ } else { ++ ++ ipa2g_mainbias = 0x2b; ++ ++ ipa2g_casconv = 0x7f; ++ ++ ipa2g_biasfilt = 0xee; ++ } ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ for (coreNum = 0; coreNum <= 1; coreNum++) { ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, ++ coreNum, IPA2G_IMAIN, ++ ipa2g_mainbias); ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, ++ coreNum, IPA2G_CASCONV, ++ ipa2g_casconv); ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, ++ coreNum, ++ IPA2G_BIAS_FILTER, ++ ipa2g_biasfilt); ++ } ++ } ++ } ++ ++ if (PHY_IPA(pi)) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if ((pi->pubpi.radiorev == 3) ++ || (pi->pubpi.radiorev == 4) ++ || (pi->pubpi.radiorev == 6)) ++ txgm_idac_bleed = 0x7f; ++ ++ for (coreNum = 0; coreNum <= 1; coreNum++) { ++ if (txgm_idac_bleed != 0) ++ WRITE_RADIO_REG4( ++ pi, RADIO_2057, ++ CORE, coreNum, ++ TXGM_IDAC_BLEED, ++ txgm_idac_bleed); ++ } ++ ++ if (pi->pubpi.radiorev == 5) { ++ ++ for (coreNum = 0; coreNum <= 1; ++ coreNum++) { ++ WRITE_RADIO_REG4(pi, RADIO_2057, ++ CORE, coreNum, ++ IPA2G_CASCONV, ++ 0x13); ++ WRITE_RADIO_REG4(pi, RADIO_2057, ++ CORE, coreNum, ++ IPA2G_IMAIN, ++ 0x1f); ++ WRITE_RADIO_REG4( ++ pi, RADIO_2057, ++ CORE, coreNum, ++ IPA2G_BIAS_FILTER, ++ 0xee); ++ WRITE_RADIO_REG4(pi, RADIO_2057, ++ CORE, coreNum, ++ PAD2G_IDACS, ++ 0x8a); ++ WRITE_RADIO_REG4( ++ pi, RADIO_2057, ++ CORE, coreNum, ++ PAD_BIAS_FILTER_BWS, ++ 0x3e); ++ } ++ ++ } else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) { ++ ++ if (CHSPEC_IS40(pi->radio_chanspec) == ++ 0) { ++ WRITE_RADIO_REG4(pi, RADIO_2057, ++ CORE, 0, ++ IPA2G_IMAIN, ++ 0x14); ++ WRITE_RADIO_REG4(pi, RADIO_2057, ++ CORE, 1, ++ IPA2G_IMAIN, ++ 0x12); ++ } else { ++ WRITE_RADIO_REG4(pi, RADIO_2057, ++ CORE, 0, ++ IPA2G_IMAIN, ++ 0x16); ++ WRITE_RADIO_REG4(pi, RADIO_2057, ++ CORE, 1, ++ IPA2G_IMAIN, ++ 0x16); ++ } ++ } ++ ++ } else { ++ freq = CHAN5G_FREQ(CHSPEC_CHANNEL( ++ pi->radio_chanspec)); ++ if (((freq >= 5180) && (freq <= 5230)) ++ || ((freq >= 5745) && (freq <= 5805))) { ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, ++ 0, IPA5G_BIAS_FILTER, ++ 0xff); ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, ++ 1, IPA5G_BIAS_FILTER, ++ 0xff); ++ } ++ } ++ } else { ++ ++ if (pi->pubpi.radiorev != 5) { ++ for (coreNum = 0; coreNum <= 1; coreNum++) { ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, ++ coreNum, ++ TXMIX2G_TUNE_BOOST_PU, ++ 0x61); ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, ++ coreNum, ++ TXGM_IDAC_BLEED, 0x70); ++ } ++ } ++ } ++ ++ if (pi->pubpi.radiorev == 4) { ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, ++ 0x05, 16, ++ &afectrl_adc_ctrl1_rev7); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, ++ 0x15, 16, ++ &afectrl_adc_ctrl1_rev7); ++ ++ for (coreNum = 0; coreNum <= 1; coreNum++) { ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, ++ AFE_VCM_CAL_MASTER, 0x0); ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, ++ AFE_SET_VCM_I, 0x3f); ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, ++ AFE_SET_VCM_Q, 0x3f); ++ } ++ } else { ++ mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2)); ++ mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2)); ++ mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2)); ++ mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2)); ++ ++ mod_phy_reg(pi, 0xa6, (0x1 << 0), 0); ++ mod_phy_reg(pi, 0x8f, (0x1 << 0), (0x1 << 0)); ++ mod_phy_reg(pi, 0xa7, (0x1 << 0), 0); ++ mod_phy_reg(pi, 0xa5, (0x1 << 0), (0x1 << 0)); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, ++ 0x05, 16, ++ &afectrl_adc_ctrl2_rev7); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, ++ 0x15, 16, ++ &afectrl_adc_ctrl2_rev7); ++ ++ mod_phy_reg(pi, 0xa6, (0x1 << 2), 0); ++ mod_phy_reg(pi, 0x8f, (0x1 << 2), 0); ++ mod_phy_reg(pi, 0xa7, (0x1 << 2), 0); ++ mod_phy_reg(pi, 0xa5, (0x1 << 2), 0); ++ } ++ ++ write_phy_reg(pi, 0x6a, 0x2); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 256, 32, ++ &min_nvar_offset_6mbps); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x138, 16, ++ &rfseq_pktgn_lpf_hpc_rev7); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x141, 16, ++ &rfseq_pktgn_lpf_h_hpc_rev7); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 3, 0x133, 16, ++ &rfseq_htpktgn_lpf_hpc_rev7); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x146, 16, ++ &rfseq_cckpktgn_lpf_hpc_rev7); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x123, 16, ++ &rfseq_tx2rx_lpf_h_hpc_rev7); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x12A, 16, ++ &rfseq_rx2tx_lpf_h_hpc_rev7); ++ ++ if (CHSPEC_IS40(pi->radio_chanspec) == 0) { ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, ++ 32, &min_nvar_val); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, ++ 127, 32, &min_nvar_val); ++ } else { ++ min_nvar_val = noise_var_tbl_rev7[3]; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, ++ 32, &min_nvar_val); ++ ++ min_nvar_val = noise_var_tbl_rev7[127]; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, ++ 127, 32, &min_nvar_val); ++ } ++ ++ wlc_phy_workarounds_nphy_gainctrl(pi); ++ ++ pdetrange = ++ (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. ++ pdetrange : pi->srom_fem2g.pdetrange; ++ ++ if (pdetrange == 0) { ++ chan_freq_range = ++ wlc_phy_get_chan_freq_range_nphy(pi, 0); ++ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { ++ aux_adc_vmid_rev7_core0[3] = 0x70; ++ aux_adc_vmid_rev7_core1[3] = 0x70; ++ aux_adc_gain_rev7[3] = 2; ++ } else { ++ aux_adc_vmid_rev7_core0[3] = 0x80; ++ aux_adc_vmid_rev7_core1[3] = 0x80; ++ aux_adc_gain_rev7[3] = 3; ++ } ++ } else if (pdetrange == 1) { ++ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { ++ aux_adc_vmid_rev7_core0[3] = 0x7c; ++ aux_adc_vmid_rev7_core1[3] = 0x7c; ++ aux_adc_gain_rev7[3] = 2; ++ } else { ++ aux_adc_vmid_rev7_core0[3] = 0x8c; ++ aux_adc_vmid_rev7_core1[3] = 0x8c; ++ aux_adc_gain_rev7[3] = 1; ++ } ++ } else if (pdetrange == 2) { ++ if (pi->pubpi.radioid == BCM2057_ID) { ++ if ((pi->pubpi.radiorev == 5) ++ || (pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) { ++ if (chan_freq_range == ++ WL_CHAN_FREQ_RANGE_2G) { ++ aux_adc_vmid_rev7_core0[3] = ++ 0x8c; ++ aux_adc_vmid_rev7_core1[3] = ++ 0x8c; ++ aux_adc_gain_rev7[3] = 0; ++ } else { ++ aux_adc_vmid_rev7_core0[3] = ++ 0x96; ++ aux_adc_vmid_rev7_core1[3] = ++ 0x96; ++ aux_adc_gain_rev7[3] = 0; ++ } ++ } ++ } ++ ++ } else if (pdetrange == 3) { ++ if (chan_freq_range == WL_CHAN_FREQ_RANGE_2G) { ++ aux_adc_vmid_rev7_core0[3] = 0x89; ++ aux_adc_vmid_rev7_core1[3] = 0x89; ++ aux_adc_gain_rev7[3] = 0; ++ } ++ ++ } else if (pdetrange == 5) { ++ ++ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { ++ aux_adc_vmid_rev7_core0[3] = 0x80; ++ aux_adc_vmid_rev7_core1[3] = 0x80; ++ aux_adc_gain_rev7[3] = 3; ++ } else { ++ aux_adc_vmid_rev7_core0[3] = 0x70; ++ aux_adc_vmid_rev7_core1[3] = 0x70; ++ aux_adc_gain_rev7[3] = 2; ++ } ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x08, 16, ++ &aux_adc_vmid_rev7_core0); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x18, 16, ++ &aux_adc_vmid_rev7_core1); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x0c, 16, ++ &aux_adc_gain_rev7); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x1c, 16, ++ &aux_adc_gain_rev7); ++ ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ write_phy_reg(pi, 0x23f, 0x1f8); ++ write_phy_reg(pi, 0x240, 0x1f8); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, ++ 1, 0, 32, &leg_data_weights); ++ leg_data_weights = leg_data_weights & 0xffffff; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, ++ 1, 0, 32, &leg_data_weights); ++ ++ alpha0 = 293; ++ alpha1 = 435; ++ alpha2 = 261; ++ beta0 = 366; ++ beta1 = 205; ++ beta2 = 32; ++ write_phy_reg(pi, 0x145, alpha0); ++ write_phy_reg(pi, 0x146, alpha1); ++ write_phy_reg(pi, 0x147, alpha2); ++ write_phy_reg(pi, 0x148, beta0); ++ write_phy_reg(pi, 0x149, beta1); ++ write_phy_reg(pi, 0x14a, beta2); ++ ++ write_phy_reg(pi, 0x38, 0xC); ++ write_phy_reg(pi, 0x2ae, 0xC); ++ ++ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, ++ rfseq_tx2rx_events_rev3, ++ rfseq_tx2rx_dlys_rev3, ++ sizeof(rfseq_tx2rx_events_rev3) / ++ sizeof(rfseq_tx2rx_events_rev3[0])); ++ ++ if (PHY_IPA(pi)) ++ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, ++ rfseq_rx2tx_events_rev3_ipa, ++ rfseq_rx2tx_dlys_rev3_ipa, ++ sizeof ++ (rfseq_rx2tx_events_rev3_ipa) / ++ sizeof ++ (rfseq_rx2tx_events_rev3_ipa ++ [0])); ++ ++ if ((pi->sh->hw_phyrxchain != 0x3) && ++ (pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) { ++ ++ if (PHY_IPA(pi)) { ++ rfseq_rx2tx_dlys_rev3[5] = 59; ++ rfseq_rx2tx_dlys_rev3[6] = 1; ++ rfseq_rx2tx_events_rev3[7] = ++ NPHY_REV3_RFSEQ_CMD_END; ++ } ++ ++ wlc_phy_set_rfseq_nphy( ++ pi, NPHY_RFSEQ_RX2TX, ++ rfseq_rx2tx_events_rev3, ++ rfseq_rx2tx_dlys_rev3, ++ sizeof(rfseq_rx2tx_events_rev3) / ++ sizeof(rfseq_rx2tx_events_rev3[0])); ++ } ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ write_phy_reg(pi, 0x6a, 0x2); ++ else ++ write_phy_reg(pi, 0x6a, 0x9c40); ++ ++ mod_phy_reg(pi, 0x294, (0xf << 8), (7 << 8)); ++ ++ if (CHSPEC_IS40(pi->radio_chanspec) == 0) { ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, ++ 32, &min_nvar_val); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, ++ 127, 32, &min_nvar_val); ++ } else { ++ min_nvar_val = noise_var_tbl_rev3[3]; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, ++ 32, &min_nvar_val); ++ ++ min_nvar_val = noise_var_tbl_rev3[127]; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, ++ 127, 32, &min_nvar_val); ++ } ++ ++ wlc_phy_workarounds_nphy_gainctrl(pi); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16, ++ &dac_control); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16, ++ &dac_control); ++ ++ pdetrange = ++ (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. ++ pdetrange : pi->srom_fem2g.pdetrange; ++ ++ if (pdetrange == 0) { ++ if (NREV_GE(pi->pubpi.phy_rev, 4)) { ++ aux_adc_vmid = aux_adc_vmid_rev4; ++ aux_adc_gain = aux_adc_gain_rev4; ++ } else { ++ aux_adc_vmid = aux_adc_vmid_rev3; ++ aux_adc_gain = aux_adc_gain_rev3; ++ } ++ chan_freq_range = ++ wlc_phy_get_chan_freq_range_nphy(pi, 0); ++ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { ++ switch (chan_freq_range) { ++ case WL_CHAN_FREQ_RANGE_5GL: ++ aux_adc_vmid[3] = 0x89; ++ aux_adc_gain[3] = 0; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GM: ++ aux_adc_vmid[3] = 0x89; ++ aux_adc_gain[3] = 0; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GH: ++ aux_adc_vmid[3] = 0x89; ++ aux_adc_gain[3] = 0; ++ break; ++ default: ++ break; ++ } ++ } ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x08, 16, aux_adc_vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x18, 16, aux_adc_vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x0c, 16, aux_adc_gain); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x1c, 16, aux_adc_gain); ++ } else if (pdetrange == 1) { ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x08, 16, sk_adc_vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x18, 16, sk_adc_vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x0c, 16, sk_adc_gain); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x1c, 16, sk_adc_gain); ++ } else if (pdetrange == 2) { ++ ++ u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x74 }; ++ u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x04 }; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 6)) { ++ chan_freq_range = ++ wlc_phy_get_chan_freq_range_nphy(pi, 0); ++ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { ++ bcm_adc_vmid[3] = 0x8e; ++ bcm_adc_gain[3] = 0x03; ++ } else { ++ bcm_adc_vmid[3] = 0x94; ++ bcm_adc_gain[3] = 0x03; ++ } ++ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { ++ bcm_adc_vmid[3] = 0x84; ++ bcm_adc_gain[3] = 0x02; ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x08, 16, bcm_adc_vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x18, 16, bcm_adc_vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x0c, 16, bcm_adc_gain); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x1c, 16, bcm_adc_gain); ++ } else if (pdetrange == 3) { ++ chan_freq_range = ++ wlc_phy_get_chan_freq_range_nphy(pi, 0); ++ if ((NREV_GE(pi->pubpi.phy_rev, 4)) ++ && (chan_freq_range == WL_CHAN_FREQ_RANGE_2G)) { ++ ++ u16 auxadc_vmid[] = { ++ 0xa2, 0xb4, 0xb4, 0x270 ++ }; ++ u16 auxadc_gain[] = { ++ 0x02, 0x02, 0x02, 0x00 ++ }; ++ ++ wlc_phy_table_write_nphy(pi, ++ NPHY_TBL_ID_AFECTRL, 4, ++ 0x08, 16, auxadc_vmid); ++ wlc_phy_table_write_nphy(pi, ++ NPHY_TBL_ID_AFECTRL, 4, ++ 0x18, 16, auxadc_vmid); ++ wlc_phy_table_write_nphy(pi, ++ NPHY_TBL_ID_AFECTRL, 4, ++ 0x0c, 16, auxadc_gain); ++ wlc_phy_table_write_nphy(pi, ++ NPHY_TBL_ID_AFECTRL, 4, ++ 0x1c, 16, auxadc_gain); ++ } ++ } else if ((pdetrange == 4) || (pdetrange == 5)) { ++ u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x0 }; ++ u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x0 }; ++ u16 Vmid[2], Av[2]; ++ ++ chan_freq_range = ++ wlc_phy_get_chan_freq_range_nphy(pi, 0); ++ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { ++ Vmid[0] = (pdetrange == 4) ? 0x8e : 0x89; ++ Vmid[1] = (pdetrange == 4) ? 0x96 : 0x89; ++ Av[0] = (pdetrange == 4) ? 2 : 0; ++ Av[1] = (pdetrange == 4) ? 2 : 0; ++ } else { ++ Vmid[0] = (pdetrange == 4) ? 0x89 : 0x74; ++ Vmid[1] = (pdetrange == 4) ? 0x8b : 0x70; ++ Av[0] = (pdetrange == 4) ? 2 : 0; ++ Av[1] = (pdetrange == 4) ? 2 : 0; ++ } ++ ++ bcm_adc_vmid[3] = Vmid[0]; ++ bcm_adc_gain[3] = Av[0]; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x08, 16, bcm_adc_vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x0c, 16, bcm_adc_gain); ++ ++ bcm_adc_vmid[3] = Vmid[1]; ++ bcm_adc_gain[3] = Av[1]; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x18, 16, bcm_adc_vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x1c, 16, bcm_adc_gain); ++ } ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX0), ++ 0x0); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX1), ++ 0x0); ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX0), ++ 0x6); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX1), ++ 0x6); ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX0), ++ 0x7); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX1), ++ 0x7); ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX0), ++ 0x88); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX1), ++ 0x88); ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX0), ++ 0x0); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX1), ++ 0x0); ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX0), ++ 0x0); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX1), ++ 0x0); ++ ++ triso = ++ (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. ++ triso : pi->srom_fem2g.triso; ++ if (triso == 7) { ++ wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0); ++ wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1); ++ } ++ ++ wlc_phy_war_txchain_upd_nphy(pi, pi->sh->hw_phytxchain); ++ ++ if (((pi->sh->boardflags2 & BFL2_APLL_WAR) && ++ (CHSPEC_IS5G(pi->radio_chanspec))) || ++ (((pi->sh->boardflags2 & BFL2_GPLL_WAR) || ++ (pi->sh->boardflags2 & BFL2_GPLL_WAR2)) && ++ (CHSPEC_IS2G(pi->radio_chanspec)))) { ++ nss1_data_weights = 0x00088888; ++ ht_data_weights = 0x00088888; ++ stbc_data_weights = 0x00088888; ++ } else { ++ nss1_data_weights = 0x88888888; ++ ht_data_weights = 0x88888888; ++ stbc_data_weights = 0x88888888; ++ } ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, ++ 1, 1, 32, &nss1_data_weights); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, ++ 1, 2, 32, &ht_data_weights); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, ++ 1, 3, 32, &stbc_data_weights); ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 4)) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ write_radio_reg(pi, ++ RADIO_2056_TX_GMBB_IDAC | ++ RADIO_2056_TX0, 0x70); ++ write_radio_reg(pi, ++ RADIO_2056_TX_GMBB_IDAC | ++ RADIO_2056_TX1, 0x70); ++ } ++ } ++ ++ if (!pi->edcrs_threshold_lock) { ++ write_phy_reg(pi, 0x224, 0x3eb); ++ write_phy_reg(pi, 0x225, 0x3eb); ++ write_phy_reg(pi, 0x226, 0x341); ++ write_phy_reg(pi, 0x227, 0x341); ++ write_phy_reg(pi, 0x228, 0x42b); ++ write_phy_reg(pi, 0x229, 0x42b); ++ write_phy_reg(pi, 0x22a, 0x381); ++ write_phy_reg(pi, 0x22b, 0x381); ++ write_phy_reg(pi, 0x22c, 0x42b); ++ write_phy_reg(pi, 0x22d, 0x42b); ++ write_phy_reg(pi, 0x22e, 0x381); ++ write_phy_reg(pi, 0x22f, 0x381); ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 6)) { ++ ++ if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK) ++ wlapi_bmac_mhf(pi->sh->physhim, MHF4, ++ MHF4_BPHY_TXCORE0, ++ MHF4_BPHY_TXCORE0, BRCM_BAND_ALL); ++ } ++ } else { ++ ++ if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD || ++ (pi->sh->boardtype == 0x8b)) { ++ uint i; ++ u8 war_dlys[] = { 1, 6, 6, 2, 4, 20, 1 }; ++ for (i = 0; i < ARRAY_SIZE(rfseq_rx2tx_dlys); i++) ++ rfseq_rx2tx_dlys[i] = war_dlys[i]; ++ } ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec) && pi->phy_5g_pwrgain) { ++ and_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0xf7); ++ and_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0xf7); ++ } else { ++ or_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0x8); ++ or_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0x8); ++ } ++ ++ regval = 0x000a; ++ wlc_phy_table_write_nphy(pi, 8, 1, 0, 16, ®val); ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x10, 16, ®val); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) { ++ regval = 0xcdaa; ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x02, 16, ®val); ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x12, 16, ®val); ++ } ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) { ++ regval = 0x0000; ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x08, 16, ®val); ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x18, 16, ®val); ++ ++ regval = 0x7aab; ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x07, 16, ®val); ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x17, 16, ®val); ++ ++ regval = 0x0800; ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x06, 16, ®val); ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x16, 16, ®val); ++ } ++ ++ write_phy_reg(pi, 0xf8, 0x02d8); ++ write_phy_reg(pi, 0xf9, 0x0301); ++ write_phy_reg(pi, 0xfa, 0x02d8); ++ write_phy_reg(pi, 0xfb, 0x0301); ++ ++ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events, ++ rfseq_rx2tx_dlys, ++ sizeof(rfseq_rx2tx_events) / ++ sizeof(rfseq_rx2tx_events[0])); ++ ++ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, rfseq_tx2rx_events, ++ rfseq_tx2rx_dlys, ++ sizeof(rfseq_tx2rx_events) / ++ sizeof(rfseq_tx2rx_events[0])); ++ ++ wlc_phy_workarounds_nphy_gainctrl(pi); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) { ++ ++ if (read_phy_reg(pi, 0xa0) & NPHY_MLenable) ++ wlapi_bmac_mhf(pi->sh->physhim, MHF3, ++ MHF3_NPHY_MLADV_WAR, ++ MHF3_NPHY_MLADV_WAR, ++ BRCM_BAND_ALL); ++ ++ } else if (NREV_IS(pi->pubpi.phy_rev, 2)) { ++ write_phy_reg(pi, 0x1e3, 0x0); ++ write_phy_reg(pi, 0x1e4, 0x0); ++ } ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) ++ mod_phy_reg(pi, 0x90, (0x1 << 7), 0); ++ ++ alpha0 = 293; ++ alpha1 = 435; ++ alpha2 = 261; ++ beta0 = 366; ++ beta1 = 205; ++ beta2 = 32; ++ write_phy_reg(pi, 0x145, alpha0); ++ write_phy_reg(pi, 0x146, alpha1); ++ write_phy_reg(pi, 0x147, alpha2); ++ write_phy_reg(pi, 0x148, beta0); ++ write_phy_reg(pi, 0x149, beta1); ++ write_phy_reg(pi, 0x14a, beta2); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) { ++ mod_phy_reg(pi, 0x142, (0xf << 12), 0); ++ ++ write_phy_reg(pi, 0x192, 0xb5); ++ write_phy_reg(pi, 0x193, 0xa4); ++ write_phy_reg(pi, 0x194, 0x0); ++ } ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 2)) ++ mod_phy_reg(pi, 0x221, ++ NPHY_FORCESIG_DECODEGATEDCLKS, ++ NPHY_FORCESIG_DECODEGATEDCLKS); ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static void wlc_phy_extpa_set_tx_digi_filts_nphy(struct brcms_phy *pi) ++{ ++ int j, type = 2; ++ u16 addr_offset = 0x2c5; ++ ++ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, addr_offset + j, ++ NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]); ++} ++ ++static void wlc_phy_clip_det_nphy(struct brcms_phy *pi, u8 write, u16 *vals) ++{ ++ ++ if (write == 0) { ++ vals[0] = read_phy_reg(pi, 0x2c); ++ vals[1] = read_phy_reg(pi, 0x42); ++ } else { ++ write_phy_reg(pi, 0x2c, vals[0]); ++ write_phy_reg(pi, 0x42, vals[1]); ++ } ++} ++ ++static void wlc_phy_ipa_internal_tssi_setup_nphy(struct brcms_phy *pi) ++{ ++ u8 core; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MASTER, 0x5); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MUX, 0xe); ++ ++ if (pi->pubpi.radiorev != 5) ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, ++ core, TSSIA, 0); ++ ++ if (!NREV_IS(pi->pubpi.phy_rev, 7)) ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, ++ core, TSSIG, 0x1); ++ else ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, ++ core, TSSIG, 0x31); ++ } else { ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MASTER, 0x9); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MUX, 0xc); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSIG, 0); ++ ++ if (pi->pubpi.radiorev != 5) { ++ if (!NREV_IS(pi->pubpi.phy_rev, 7)) ++ WRITE_RADIO_REG3(pi, RADIO_2057, ++ TX, core, ++ TSSIA, 0x1); ++ else ++ WRITE_RADIO_REG3(pi, RADIO_2057, ++ TX, core, ++ TSSIA, 0x31); ++ } ++ } ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG, ++ 0); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC, ++ 0); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM, ++ 0x3); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1, ++ 0x0); ++ } ++ } else { ++ WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR31, ++ (CHSPEC_IS2G(pi->radio_chanspec)) ? 0x128 : ++ 0x80); ++ WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR30, 0x0); ++ WRITE_RADIO_SYN(pi, RADIO_2056, GPIO_MASTER1, 0x29); ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_VCM_HG, ++ 0x0); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_IDAC, ++ 0x0); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_VCM, ++ 0x3); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TX_AMP_DET, ++ 0x0); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC1, ++ 0x8); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC2, ++ 0x0); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC3, ++ 0x0); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ TX_SSI_MASTER, 0x5); ++ ++ if (pi->pubpi.radiorev != 5) ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, ++ core, TSSIA, 0x0); ++ if (NREV_GE(pi->pubpi.phy_rev, 5)) ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, ++ core, TSSIG, 0x31); ++ else ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, ++ core, TSSIG, 0x11); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ TX_SSI_MUX, 0xe); ++ } else { ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ TX_SSI_MASTER, 0x9); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ TSSIA, 0x31); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ TSSIG, 0x0); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ TX_SSI_MUX, 0xc); ++ } ++ } ++ } ++} ++ ++static void ++wlc_phy_rfctrl_override_nphy(struct brcms_phy *pi, u16 field, u16 value, ++ u8 core_mask, u8 off) ++{ ++ u8 core_num; ++ u16 addr = 0, mask = 0, en_addr = 0, val_addr = 0, en_mask = ++ 0, val_mask = 0; ++ u8 shift = 0, val_shift = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) { ++ ++ en_mask = field; ++ for (core_num = 0; core_num < 2; core_num++) { ++ ++ switch (field) { ++ case (0x1 << 1): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x1 << 0); ++ val_shift = 0; ++ break; ++ case (0x1 << 2): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x1 << 1); ++ val_shift = 1; ++ break; ++ case (0x1 << 3): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x1 << 2); ++ val_shift = 2; ++ break; ++ case (0x1 << 4): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x1 << 4); ++ val_shift = 4; ++ break; ++ case (0x1 << 5): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x1 << 5); ++ val_shift = 5; ++ break; ++ case (0x1 << 6): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x1 << 6); ++ val_shift = 6; ++ break; ++ case (0x1 << 7): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x1 << 7); ++ val_shift = 7; ++ break; ++ case (0x1 << 8): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x7 << 8); ++ val_shift = 8; ++ break; ++ case (0x1 << 11): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x7 << 13); ++ val_shift = 13; ++ break; ++ ++ case (0x1 << 9): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0xf8 : 0xfa; ++ val_mask = (0x7 << 0); ++ val_shift = 0; ++ break; ++ ++ case (0x1 << 10): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0xf8 : 0xfa; ++ val_mask = (0x7 << 4); ++ val_shift = 4; ++ break; ++ ++ case (0x1 << 12): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7b : 0x7e; ++ val_mask = (0xffff << 0); ++ val_shift = 0; ++ break; ++ case (0x1 << 13): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7c : 0x7f; ++ val_mask = (0xffff << 0); ++ val_shift = 0; ++ break; ++ case (0x1 << 14): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0xf9 : 0xfb; ++ val_mask = (0x3 << 6); ++ val_shift = 6; ++ break; ++ case (0x1 << 0): ++ en_addr = (core_num == 0) ? 0xe5 : 0xe6; ++ val_addr = (core_num == 0) ? 0xf9 : 0xfb; ++ val_mask = (0x1 << 15); ++ val_shift = 15; ++ break; ++ default: ++ addr = 0xffff; ++ break; ++ } ++ ++ if (off) { ++ and_phy_reg(pi, en_addr, ~en_mask); ++ and_phy_reg(pi, val_addr, ~val_mask); ++ } else { ++ ++ if ((core_mask == 0) ++ || (core_mask & (1 << core_num))) { ++ or_phy_reg(pi, en_addr, en_mask); ++ ++ if (addr != 0xffff) ++ mod_phy_reg(pi, val_addr, ++ val_mask, ++ (value << ++ val_shift)); ++ } ++ } ++ } ++ } else { ++ ++ if (off) { ++ and_phy_reg(pi, 0xec, ~field); ++ value = 0x0; ++ } else { ++ or_phy_reg(pi, 0xec, field); ++ } ++ ++ for (core_num = 0; core_num < 2; core_num++) { ++ ++ switch (field) { ++ case (0x1 << 1): ++ case (0x1 << 9): ++ case (0x1 << 12): ++ case (0x1 << 13): ++ case (0x1 << 14): ++ addr = 0x78; ++ ++ core_mask = 0x1; ++ break; ++ case (0x1 << 2): ++ case (0x1 << 3): ++ case (0x1 << 4): ++ case (0x1 << 5): ++ case (0x1 << 6): ++ case (0x1 << 7): ++ case (0x1 << 8): ++ addr = (core_num == 0) ? 0x7a : 0x7d; ++ break; ++ case (0x1 << 10): ++ addr = (core_num == 0) ? 0x7b : 0x7e; ++ break; ++ case (0x1 << 11): ++ addr = (core_num == 0) ? 0x7c : 0x7f; ++ break; ++ default: ++ addr = 0xffff; ++ } ++ ++ switch (field) { ++ case (0x1 << 1): ++ mask = (0x7 << 3); ++ shift = 3; ++ break; ++ case (0x1 << 9): ++ mask = (0x1 << 2); ++ shift = 2; ++ break; ++ case (0x1 << 12): ++ mask = (0x1 << 8); ++ shift = 8; ++ break; ++ case (0x1 << 13): ++ mask = (0x1 << 9); ++ shift = 9; ++ break; ++ case (0x1 << 14): ++ mask = (0xf << 12); ++ shift = 12; ++ break; ++ case (0x1 << 2): ++ mask = (0x1 << 0); ++ shift = 0; ++ break; ++ case (0x1 << 3): ++ mask = (0x1 << 1); ++ shift = 1; ++ break; ++ case (0x1 << 4): ++ mask = (0x1 << 2); ++ shift = 2; ++ break; ++ case (0x1 << 5): ++ mask = (0x3 << 4); ++ shift = 4; ++ break; ++ case (0x1 << 6): ++ mask = (0x3 << 6); ++ shift = 6; ++ break; ++ case (0x1 << 7): ++ mask = (0x1 << 8); ++ shift = 8; ++ break; ++ case (0x1 << 8): ++ mask = (0x1 << 9); ++ shift = 9; ++ break; ++ case (0x1 << 10): ++ mask = 0x1fff; ++ shift = 0x0; ++ break; ++ case (0x1 << 11): ++ mask = 0x1fff; ++ shift = 0x0; ++ break; ++ default: ++ mask = 0x0; ++ shift = 0x0; ++ break; ++ } ++ ++ if ((addr != 0xffff) && (core_mask & (1 << core_num))) ++ mod_phy_reg(pi, addr, mask, (value << shift)); ++ } ++ ++ or_phy_reg(pi, 0xec, (0x1 << 0)); ++ or_phy_reg(pi, 0x78, (0x1 << 0)); ++ udelay(1); ++ and_phy_reg(pi, 0xec, ~(0x1 << 0)); ++ } ++} ++ ++static void wlc_phy_txpwrctrl_idle_tssi_nphy(struct brcms_phy *pi) ++{ ++ s32 rssi_buf[4]; ++ s32 int_val; ++ ++ if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) || PHY_MUTED(pi)) ++ ++ return; ++ ++ if (PHY_IPA(pi)) ++ wlc_phy_ipa_internal_tssi_setup_nphy(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), ++ 0, 0x3, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ else if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 0); ++ ++ wlc_phy_stopplayback_nphy(pi); ++ ++ wlc_phy_tx_tone_nphy(pi, 4000, 0, 0, 0, false); ++ ++ udelay(20); ++ int_val = ++ wlc_phy_poll_rssi_nphy(pi, (u8) NPHY_RSSI_SEL_TSSI_2G, rssi_buf, ++ 1); ++ wlc_phy_stopplayback_nphy(pi); ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, 0); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), ++ 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ else if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 1); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g = ++ (u8) ((int_val >> 24) & 0xff); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g = ++ (u8) ((int_val >> 24) & 0xff); ++ ++ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g = ++ (u8) ((int_val >> 8) & 0xff); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g = ++ (u8) ((int_val >> 8) & 0xff); ++ } else { ++ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g = ++ (u8) ((int_val >> 24) & 0xff); ++ ++ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g = ++ (u8) ((int_val >> 8) & 0xff); ++ ++ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g = ++ (u8) ((int_val >> 16) & 0xff); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g = ++ (u8) ((int_val) & 0xff); ++ } ++ ++} ++ ++static void wlc_phy_txpwr_limit_to_tbl_nphy(struct brcms_phy *pi) ++{ ++ u8 idx, idx2, i, delta_ind; ++ ++ for (idx = TXP_FIRST_CCK; idx <= TXP_LAST_CCK; idx++) ++ pi->adj_pwr_tbl_nphy[idx] = pi->tx_power_offset[idx]; ++ ++ for (i = 0; i < 4; i++) { ++ idx2 = 0; ++ ++ delta_ind = 0; ++ ++ switch (i) { ++ case 0: ++ ++ if (CHSPEC_IS40(pi->radio_chanspec) ++ && NPHY_IS_SROM_REINTERPRET) { ++ idx = TXP_FIRST_MCS_40_SISO; ++ } else { ++ idx = (CHSPEC_IS40(pi->radio_chanspec)) ? ++ TXP_FIRST_OFDM_40_SISO : TXP_FIRST_OFDM; ++ delta_ind = 1; ++ } ++ break; ++ ++ case 1: ++ ++ idx = (CHSPEC_IS40(pi->radio_chanspec)) ? ++ TXP_FIRST_MCS_40_CDD : TXP_FIRST_MCS_20_CDD; ++ break; ++ ++ case 2: ++ ++ idx = (CHSPEC_IS40(pi->radio_chanspec)) ? ++ TXP_FIRST_MCS_40_STBC : TXP_FIRST_MCS_20_STBC; ++ break; ++ ++ case 3: ++ ++ idx = (CHSPEC_IS40(pi->radio_chanspec)) ? ++ TXP_FIRST_MCS_40_SDM : TXP_FIRST_MCS_20_SDM; ++ break; ++ } ++ ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ idx = idx + delta_ind; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx++]; ++ ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx++]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx++]; ++ ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx++]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx++]; ++ ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx++]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ idx = idx + 1 - delta_ind; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ } ++} ++ ++static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) ++{ ++ u32 idx; ++ s16 a1[2], b0[2], b1[2]; ++ s8 target_pwr_qtrdbm[2]; ++ s32 num, den, pwr_est; ++ u8 chan_freq_range; ++ u8 idle_tssi[2]; ++ u32 tbl_id, tbl_len, tbl_offset; ++ u32 regval[64]; ++ u8 core; ++ ++ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) { ++ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK); ++ (void)R_REG(&pi->regs->maccontrol); ++ udelay(1); ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ or_phy_reg(pi, 0x122, (0x1 << 0)); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ and_phy_reg(pi, 0x1e7, (u16) (~(0x1 << 15))); ++ else ++ or_phy_reg(pi, 0x1e7, (0x1 << 15)); ++ ++ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) ++ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0); ++ ++ if (pi->sh->sromrev < 4) { ++ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g; ++ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g; ++ target_pwr_qtrdbm[0] = 13 * 4; ++ target_pwr_qtrdbm[1] = 13 * 4; ++ a1[0] = -424; ++ a1[1] = -424; ++ b0[0] = 5612; ++ b0[1] = 5612; ++ b1[1] = -1393; ++ b1[0] = -1393; ++ } else { ++ ++ chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0); ++ switch (chan_freq_range) { ++ case WL_CHAN_FREQ_RANGE_2G: ++ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g; ++ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g; ++ target_pwr_qtrdbm[0] = ++ pi->nphy_pwrctrl_info[0].max_pwr_2g; ++ target_pwr_qtrdbm[1] = ++ pi->nphy_pwrctrl_info[1].max_pwr_2g; ++ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_a1; ++ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_a1; ++ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b0; ++ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b0; ++ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b1; ++ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b1; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GL: ++ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; ++ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; ++ target_pwr_qtrdbm[0] = ++ pi->nphy_pwrctrl_info[0].max_pwr_5gl; ++ target_pwr_qtrdbm[1] = ++ pi->nphy_pwrctrl_info[1].max_pwr_5gl; ++ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1; ++ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1; ++ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0; ++ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0; ++ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1; ++ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GM: ++ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; ++ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; ++ target_pwr_qtrdbm[0] = ++ pi->nphy_pwrctrl_info[0].max_pwr_5gm; ++ target_pwr_qtrdbm[1] = ++ pi->nphy_pwrctrl_info[1].max_pwr_5gm; ++ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_a1; ++ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_a1; ++ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b0; ++ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b0; ++ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b1; ++ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b1; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GH: ++ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; ++ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; ++ target_pwr_qtrdbm[0] = ++ pi->nphy_pwrctrl_info[0].max_pwr_5gh; ++ target_pwr_qtrdbm[1] = ++ pi->nphy_pwrctrl_info[1].max_pwr_5gh; ++ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1; ++ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1; ++ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0; ++ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0; ++ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1; ++ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1; ++ break; ++ default: ++ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g; ++ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g; ++ target_pwr_qtrdbm[0] = 13 * 4; ++ target_pwr_qtrdbm[1] = 13 * 4; ++ a1[0] = -424; ++ a1[1] = -424; ++ b0[0] = 5612; ++ b0[1] = 5612; ++ b1[1] = -1393; ++ b1[0] = -1393; ++ break; ++ } ++ } ++ ++ target_pwr_qtrdbm[0] = (s8) pi->tx_power_max; ++ target_pwr_qtrdbm[1] = (s8) pi->tx_power_max; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (pi->srom_fem2g.tssipos) ++ or_phy_reg(pi, 0x1e9, (0x1 << 14)); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ for (core = 0; core <= 1; core++) { ++ if (PHY_IPA(pi)) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ WRITE_RADIO_REG3(pi, RADIO_2057, ++ TX, core, ++ TX_SSI_MUX, ++ 0xe); ++ else ++ WRITE_RADIO_REG3(pi, RADIO_2057, ++ TX, core, ++ TX_SSI_MUX, ++ 0xc); ++ } ++ } ++ } else { ++ if (PHY_IPA(pi)) { ++ ++ write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX | ++ RADIO_2056_TX0, ++ (CHSPEC_IS5G ++ (pi->radio_chanspec)) ? ++ 0xc : 0xe); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MUX | ++ RADIO_2056_TX1, ++ (CHSPEC_IS5G ++ (pi->radio_chanspec)) ? ++ 0xc : 0xe); ++ } else { ++ ++ write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX | ++ RADIO_2056_TX0, 0x11); ++ write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX | ++ RADIO_2056_TX1, 0x11); ++ } ++ } ++ } ++ ++ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) { ++ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK); ++ (void)R_REG(&pi->regs->maccontrol); ++ udelay(1); ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ mod_phy_reg(pi, 0x1e7, (0x7f << 0), ++ (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0)); ++ else ++ mod_phy_reg(pi, 0x1e7, (0x7f << 0), ++ (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0)); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ mod_phy_reg(pi, 0x222, (0xff << 0), ++ (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0)); ++ else if (NREV_GT(pi->pubpi.phy_rev, 1)) ++ mod_phy_reg(pi, 0x222, (0xff << 0), ++ (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0)); ++ ++ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) ++ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0); ++ ++ write_phy_reg(pi, 0x1e8, (0x3 << 8) | (240 << 0)); ++ ++ write_phy_reg(pi, 0x1e9, ++ (1 << 15) | (idle_tssi[0] << 0) | (idle_tssi[1] << 8)); ++ ++ write_phy_reg(pi, 0x1ea, ++ (target_pwr_qtrdbm[0] << 0) | ++ (target_pwr_qtrdbm[1] << 8)); ++ ++ tbl_len = 64; ++ tbl_offset = 0; ++ for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL; ++ tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) { ++ ++ for (idx = 0; idx < tbl_len; idx++) { ++ num = 8 * ++ (16 * b0[tbl_id - 26] + b1[tbl_id - 26] * idx); ++ den = 32768 + a1[tbl_id - 26] * idx; ++ pwr_est = max(((4 * num + den / 2) / den), -8); ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) { ++ if (idx <= ++ (uint) (31 - idle_tssi[tbl_id - 26] + 1)) ++ pwr_est = ++ max(pwr_est, ++ target_pwr_qtrdbm ++ [tbl_id - 26] + 1); ++ } ++ regval[idx] = (u32) pwr_est; ++ } ++ wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32, ++ regval); ++ } ++ ++ wlc_phy_txpwr_limit_to_tbl_nphy(pi); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64, 8, ++ pi->adj_pwr_tbl_nphy); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64, 8, ++ pi->adj_pwr_tbl_nphy); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi) ++{ ++ u32 *tx_pwrctrl_tbl = NULL; ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if ((pi->pubpi.radiorev == 4) ++ || (pi->pubpi.radiorev == 6)) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_ipa_2g_2057rev4n6; ++ else if (pi->pubpi.radiorev == 3) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_ipa_2g_2057rev3; ++ else if (pi->pubpi.radiorev == 5) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_ipa_2g_2057rev5; ++ else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_ipa_2g_2057rev7; ++ } else if (NREV_IS(pi->pubpi.phy_rev, 6)) { ++ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6; ++ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { ++ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5; ++ } else { ++ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa; ++ } ++ } else { ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if ((pi->pubpi.radiorev == 3) || ++ (pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) ++ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g_2057; ++ else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_ipa_5g_2057rev7; ++ } else { ++ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g; ++ } ++ } ++ ++ return tx_pwrctrl_tbl; ++} ++ ++static void wlc_phy_restore_rssical_nphy(struct brcms_phy *pi) ++{ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (pi->nphy_rssical_chanspec_2G == 0) ++ return; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0, ++ RADIO_2057_VCM_MASK, ++ pi->rssical_cache. ++ rssical_radio_regs_2G[0]); ++ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1, ++ RADIO_2057_VCM_MASK, ++ pi->rssical_cache. ++ rssical_radio_regs_2G[1]); ++ } else { ++ mod_radio_reg(pi, ++ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0, ++ RADIO_2056_VCM_MASK, ++ pi->rssical_cache. ++ rssical_radio_regs_2G[0]); ++ mod_radio_reg(pi, ++ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1, ++ RADIO_2056_VCM_MASK, ++ pi->rssical_cache. ++ rssical_radio_regs_2G[1]); ++ } ++ ++ write_phy_reg(pi, 0x1a6, ++ pi->rssical_cache.rssical_phyregs_2G[0]); ++ write_phy_reg(pi, 0x1ac, ++ pi->rssical_cache.rssical_phyregs_2G[1]); ++ write_phy_reg(pi, 0x1b2, ++ pi->rssical_cache.rssical_phyregs_2G[2]); ++ write_phy_reg(pi, 0x1b8, ++ pi->rssical_cache.rssical_phyregs_2G[3]); ++ write_phy_reg(pi, 0x1a4, ++ pi->rssical_cache.rssical_phyregs_2G[4]); ++ write_phy_reg(pi, 0x1aa, ++ pi->rssical_cache.rssical_phyregs_2G[5]); ++ write_phy_reg(pi, 0x1b0, ++ pi->rssical_cache.rssical_phyregs_2G[6]); ++ write_phy_reg(pi, 0x1b6, ++ pi->rssical_cache.rssical_phyregs_2G[7]); ++ write_phy_reg(pi, 0x1a5, ++ pi->rssical_cache.rssical_phyregs_2G[8]); ++ write_phy_reg(pi, 0x1ab, ++ pi->rssical_cache.rssical_phyregs_2G[9]); ++ write_phy_reg(pi, 0x1b1, ++ pi->rssical_cache.rssical_phyregs_2G[10]); ++ write_phy_reg(pi, 0x1b7, ++ pi->rssical_cache.rssical_phyregs_2G[11]); ++ ++ } else { ++ if (pi->nphy_rssical_chanspec_5G == 0) ++ return; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0, ++ RADIO_2057_VCM_MASK, ++ pi->rssical_cache. ++ rssical_radio_regs_5G[0]); ++ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1, ++ RADIO_2057_VCM_MASK, ++ pi->rssical_cache. ++ rssical_radio_regs_5G[1]); ++ } else { ++ mod_radio_reg(pi, ++ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0, ++ RADIO_2056_VCM_MASK, ++ pi->rssical_cache. ++ rssical_radio_regs_5G[0]); ++ mod_radio_reg(pi, ++ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1, ++ RADIO_2056_VCM_MASK, ++ pi->rssical_cache. ++ rssical_radio_regs_5G[1]); ++ } ++ ++ write_phy_reg(pi, 0x1a6, ++ pi->rssical_cache.rssical_phyregs_5G[0]); ++ write_phy_reg(pi, 0x1ac, ++ pi->rssical_cache.rssical_phyregs_5G[1]); ++ write_phy_reg(pi, 0x1b2, ++ pi->rssical_cache.rssical_phyregs_5G[2]); ++ write_phy_reg(pi, 0x1b8, ++ pi->rssical_cache.rssical_phyregs_5G[3]); ++ write_phy_reg(pi, 0x1a4, ++ pi->rssical_cache.rssical_phyregs_5G[4]); ++ write_phy_reg(pi, 0x1aa, ++ pi->rssical_cache.rssical_phyregs_5G[5]); ++ write_phy_reg(pi, 0x1b0, ++ pi->rssical_cache.rssical_phyregs_5G[6]); ++ write_phy_reg(pi, 0x1b6, ++ pi->rssical_cache.rssical_phyregs_5G[7]); ++ write_phy_reg(pi, 0x1a5, ++ pi->rssical_cache.rssical_phyregs_5G[8]); ++ write_phy_reg(pi, 0x1ab, ++ pi->rssical_cache.rssical_phyregs_5G[9]); ++ write_phy_reg(pi, 0x1b1, ++ pi->rssical_cache.rssical_phyregs_5G[10]); ++ write_phy_reg(pi, 0x1b7, ++ pi->rssical_cache.rssical_phyregs_5G[11]); ++ } ++} ++ ++static void wlc_phy_internal_cal_txgain_nphy(struct brcms_phy *pi) ++{ ++ u16 txcal_gain[2]; ++ ++ pi->nphy_txcal_pwr_idx[0] = pi->nphy_cal_orig_pwr_idx[0]; ++ pi->nphy_txcal_pwr_idx[1] = pi->nphy_cal_orig_pwr_idx[0]; ++ wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true); ++ wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, ++ txcal_gain); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F40; ++ txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F40; ++ } else { ++ txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F60; ++ txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F60; ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, ++ txcal_gain); ++} ++ ++static void wlc_phy_precal_txgain_nphy(struct brcms_phy *pi) ++{ ++ bool save_bbmult = false; ++ u8 txcal_index_2057_rev5n7 = 0; ++ u8 txcal_index_2057_rev3n4n6 = 10; ++ ++ if (pi->use_int_tx_iqlo_cal_nphy) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if ((pi->pubpi.radiorev == 3) || ++ (pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) { ++ ++ pi->nphy_txcal_pwr_idx[0] = ++ txcal_index_2057_rev3n4n6; ++ pi->nphy_txcal_pwr_idx[1] = ++ txcal_index_2057_rev3n4n6; ++ wlc_phy_txpwr_index_nphy( ++ pi, 3, ++ txcal_index_2057_rev3n4n6, ++ false); ++ } else { ++ ++ pi->nphy_txcal_pwr_idx[0] = ++ txcal_index_2057_rev5n7; ++ pi->nphy_txcal_pwr_idx[1] = ++ txcal_index_2057_rev5n7; ++ wlc_phy_txpwr_index_nphy( ++ pi, 3, ++ txcal_index_2057_rev5n7, ++ false); ++ } ++ save_bbmult = true; ++ ++ } else if (NREV_LT(pi->pubpi.phy_rev, 5)) { ++ wlc_phy_cal_txgainctrl_nphy(pi, 11, false); ++ if (pi->sh->hw_phytxchain != 3) { ++ pi->nphy_txcal_pwr_idx[1] = ++ pi->nphy_txcal_pwr_idx[0]; ++ wlc_phy_txpwr_index_nphy(pi, 3, ++ pi-> ++ nphy_txcal_pwr_idx[0], ++ true); ++ save_bbmult = true; ++ } ++ ++ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { ++ if (PHY_IPA(pi)) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ wlc_phy_cal_txgainctrl_nphy(pi, 12, ++ false); ++ } else { ++ pi->nphy_txcal_pwr_idx[0] = 80; ++ pi->nphy_txcal_pwr_idx[1] = 80; ++ wlc_phy_txpwr_index_nphy(pi, 3, 80, ++ false); ++ save_bbmult = true; ++ } ++ } else { ++ wlc_phy_internal_cal_txgain_nphy(pi); ++ save_bbmult = true; ++ } ++ ++ } else if (NREV_IS(pi->pubpi.phy_rev, 6)) { ++ if (PHY_IPA(pi)) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ wlc_phy_cal_txgainctrl_nphy(pi, 12, ++ false); ++ else ++ wlc_phy_cal_txgainctrl_nphy(pi, 14, ++ false); ++ } else { ++ wlc_phy_internal_cal_txgain_nphy(pi); ++ save_bbmult = true; ++ } ++ } ++ ++ } else { ++ wlc_phy_cal_txgainctrl_nphy(pi, 10, false); ++ } ++ ++ if (save_bbmult) ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, ++ &pi->nphy_txcal_bbmult); ++} ++ ++static void ++wlc_phy_rfctrlintc_override_nphy(struct brcms_phy *pi, u8 field, u16 value, ++ u8 core_code) ++{ ++ u16 mask; ++ u16 val; ++ u8 core; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ if (core_code == RADIO_MIMO_CORESEL_CORE1 ++ && core == PHY_CORE_1) ++ continue; ++ else if (core_code == RADIO_MIMO_CORESEL_CORE2 ++ && core == PHY_CORE_0) ++ continue; ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 7)) { ++ ++ mask = (0x1 << 10); ++ val = 1 << 10; ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 : ++ 0x92, mask, val); ++ } ++ ++ if (field == NPHY_RfctrlIntc_override_OFF) { ++ ++ write_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 : ++ 0x92, 0); ++ ++ wlc_phy_force_rfseq_nphy(pi, ++ NPHY_RFSEQ_RESET2RX); ++ } else if (field == NPHY_RfctrlIntc_override_TRSW) { ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ mask = (0x1 << 6) | (0x1 << 7); ++ ++ val = value << 6; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ mask, val); ++ ++ or_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ (0x1 << 10)); ++ ++ and_phy_reg(pi, 0x2ff, (u16) ++ ~(0x3 << 14)); ++ or_phy_reg(pi, 0x2ff, (0x1 << 13)); ++ or_phy_reg(pi, 0x2ff, (0x1 << 0)); ++ } else { ++ ++ mask = (0x1 << 6) | ++ (0x1 << 7) | ++ (0x1 << 8) | (0x1 << 9); ++ val = value << 6; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ mask, val); ++ ++ mask = (0x1 << 0); ++ val = 1 << 0; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xe7 : 0xec, ++ mask, val); ++ ++ mask = (core == PHY_CORE_0) ? ++ (0x1 << 0) : (0x1 << 1); ++ val = 1 << ((core == PHY_CORE_0) ? ++ 0 : 1); ++ mod_phy_reg(pi, 0x78, mask, val); ++ ++ SPINWAIT(((read_phy_reg(pi, 0x78) & val) ++ != 0), 10000); ++ if (WARN(read_phy_reg(pi, 0x78) & val, ++ "HW error: override failed")) ++ return; ++ ++ mask = (0x1 << 0); ++ val = 0 << 0; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xe7 : 0xec, ++ mask, val); ++ } ++ } else if (field == NPHY_RfctrlIntc_override_PA) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ mask = (0x1 << 4) | (0x1 << 5); ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) ++ val = value << 5; ++ else ++ val = value << 4; ++ ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ mask, val); ++ ++ or_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ (0x1 << 12)); ++ } else { ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ mask = (0x1 << 5); ++ val = value << 5; ++ } else { ++ mask = (0x1 << 4); ++ val = value << 4; ++ } ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ mask, val); ++ } ++ } else if (field == ++ NPHY_RfctrlIntc_override_EXT_LNA_PU) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ ++ mask = (0x1 << 0); ++ val = value << 0; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 ++ : 0x92, mask, val); ++ ++ mask = (0x1 << 2); ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 ++ : 0x92, mask, 0); ++ } else { ++ ++ mask = (0x1 << 2); ++ val = value << 2; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 ++ : 0x92, mask, val); ++ ++ mask = (0x1 << 0); ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 ++ : 0x92, mask, 0); ++ } ++ ++ mask = (0x1 << 11); ++ val = 1 << 11; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ mask, val); ++ } else { ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ mask = (0x1 << 0); ++ val = value << 0; ++ } else { ++ mask = (0x1 << 2); ++ val = value << 2; ++ } ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ mask, val); ++ } ++ } else if (field == ++ NPHY_RfctrlIntc_override_EXT_LNA_GAIN) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ ++ mask = (0x1 << 1); ++ val = value << 1; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 ++ : 0x92, mask, val); ++ ++ mask = (0x1 << 3); ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 ++ : 0x92, mask, 0); ++ } else { ++ ++ mask = (0x1 << 3); ++ val = value << 3; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 ++ : 0x92, mask, val); ++ ++ mask = (0x1 << 1); ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 ++ : 0x92, mask, 0); ++ } ++ ++ mask = (0x1 << 11); ++ val = 1 << 11; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ mask, val); ++ } else { ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ mask = (0x1 << 1); ++ val = value << 1; ++ } else { ++ mask = (0x1 << 3); ++ val = value << 3; ++ } ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ mask, val); ++ } ++ } ++ } ++ } ++} ++ ++void ++wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, s32 dBm_targetpower, ++ bool debug) ++{ ++ int gainctrl_loopidx; ++ uint core; ++ u16 m0m1, curr_m0m1; ++ s32 delta_power; ++ s32 txpwrindex; ++ s32 qdBm_power[2]; ++ u16 orig_BBConfig; ++ u16 phy_saveregs[4]; ++ u32 freq_test; ++ u16 ampl_test = 250; ++ uint stepsize; ++ bool phyhang_avoid_state = false; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ stepsize = 2; ++ else ++ stepsize = 1; ++ ++ if (CHSPEC_IS40(pi->radio_chanspec)) ++ freq_test = 5000; ++ else ++ freq_test = 2500; ++ ++ wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true); ++ wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ phyhang_avoid_state = pi->phyhang_avoid; ++ pi->phyhang_avoid = false; ++ ++ phy_saveregs[0] = read_phy_reg(pi, 0x91); ++ phy_saveregs[1] = read_phy_reg(pi, 0x92); ++ phy_saveregs[2] = read_phy_reg(pi, 0xe7); ++ phy_saveregs[3] = read_phy_reg(pi, 0xec); ++ wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 1, ++ RADIO_MIMO_CORESEL_CORE1 | ++ RADIO_MIMO_CORESEL_CORE2); ++ ++ if (!debug) { ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ 0x2, RADIO_MIMO_CORESEL_CORE1); ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ 0x8, RADIO_MIMO_CORESEL_CORE2); ++ } else { ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ 0x1, RADIO_MIMO_CORESEL_CORE1); ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ 0x7, RADIO_MIMO_CORESEL_CORE2); ++ } ++ ++ orig_BBConfig = read_phy_reg(pi, 0x01); ++ mod_phy_reg(pi, 0x01, (0x1 << 15), 0); ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1); ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ txpwrindex = (s32) pi->nphy_cal_orig_pwr_idx[core]; ++ ++ for (gainctrl_loopidx = 0; gainctrl_loopidx < 2; ++ gainctrl_loopidx++) { ++ wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0, ++ false); ++ ++ if (core == PHY_CORE_0) ++ curr_m0m1 = m0m1 & 0xff00; ++ else ++ curr_m0m1 = m0m1 & 0x00ff; ++ ++ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &curr_m0m1); ++ wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &curr_m0m1); ++ ++ udelay(50); ++ ++ wlc_phy_est_tonepwr_nphy(pi, qdBm_power, ++ NPHY_CAL_TSSISAMPS); ++ ++ pi->nphy_bb_mult_save = 0; ++ wlc_phy_stopplayback_nphy(pi); ++ ++ delta_power = (dBm_targetpower * 4) - qdBm_power[core]; ++ ++ txpwrindex -= stepsize * delta_power; ++ if (txpwrindex < 0) ++ txpwrindex = 0; ++ else if (txpwrindex > 127) ++ txpwrindex = 127; ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (NREV_IS(pi->pubpi.phy_rev, 4) && ++ (pi->srom_fem5g.extpagain == 3)) { ++ if (txpwrindex < 30) ++ txpwrindex = 30; ++ } ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 5) && ++ (pi->srom_fem2g.extpagain == 3)) { ++ if (txpwrindex < 50) ++ txpwrindex = 50; ++ } ++ } ++ ++ wlc_phy_txpwr_index_nphy(pi, (1 << core), ++ (u8) txpwrindex, true); ++ } ++ ++ pi->nphy_txcal_pwr_idx[core] = (u8) txpwrindex; ++ ++ if (debug) { ++ u16 radio_gain; ++ u16 dbg_m0m1; ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &dbg_m0m1); ++ ++ wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0, ++ false); ++ ++ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &dbg_m0m1); ++ wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &dbg_m0m1); ++ ++ udelay(100); ++ ++ wlc_phy_est_tonepwr_nphy(pi, qdBm_power, ++ NPHY_CAL_TSSISAMPS); ++ ++ wlc_phy_table_read_nphy(pi, 7, 1, (0x110 + core), 16, ++ &radio_gain); ++ ++ mdelay(4000); ++ pi->nphy_bb_mult_save = 0; ++ wlc_phy_stopplayback_nphy(pi); ++ } ++ } ++ ++ wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_txcal_pwr_idx[0], true); ++ wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_txcal_pwr_idx[1], true); ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &pi->nphy_txcal_bbmult); ++ ++ write_phy_reg(pi, 0x01, orig_BBConfig); ++ ++ write_phy_reg(pi, 0x91, phy_saveregs[0]); ++ write_phy_reg(pi, 0x92, phy_saveregs[1]); ++ write_phy_reg(pi, 0xe7, phy_saveregs[2]); ++ write_phy_reg(pi, 0xec, phy_saveregs[3]); ++ ++ pi->phyhang_avoid = phyhang_avoid_state; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static void wlc_phy_savecal_nphy(struct brcms_phy *pi) ++{ ++ void *tbl_ptr; ++ int coreNum; ++ u16 *txcal_radio_regs = NULL; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ ++ wlc_phy_rx_iq_coeffs_nphy(pi, 0, ++ &pi->calibration_cache. ++ rxcal_coeffs_2G); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ txcal_radio_regs = ++ pi->calibration_cache.txcal_radio_regs_2G; ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ pi->calibration_cache.txcal_radio_regs_2G[0] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_I | ++ RADIO_2056_TX0); ++ pi->calibration_cache.txcal_radio_regs_2G[1] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_Q | ++ RADIO_2056_TX0); ++ pi->calibration_cache.txcal_radio_regs_2G[2] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_I | ++ RADIO_2056_TX1); ++ pi->calibration_cache.txcal_radio_regs_2G[3] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_Q | ++ RADIO_2056_TX1); ++ ++ pi->calibration_cache.txcal_radio_regs_2G[4] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_I | ++ RADIO_2056_TX0); ++ pi->calibration_cache.txcal_radio_regs_2G[5] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_Q | ++ RADIO_2056_TX0); ++ pi->calibration_cache.txcal_radio_regs_2G[6] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_I | ++ RADIO_2056_TX1); ++ pi->calibration_cache.txcal_radio_regs_2G[7] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_Q | ++ RADIO_2056_TX1); ++ } else { ++ pi->calibration_cache.txcal_radio_regs_2G[0] = ++ read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL); ++ pi->calibration_cache.txcal_radio_regs_2G[1] = ++ read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL); ++ pi->calibration_cache.txcal_radio_regs_2G[2] = ++ read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM); ++ pi->calibration_cache.txcal_radio_regs_2G[3] = ++ read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM); ++ } ++ ++ pi->nphy_iqcal_chanspec_2G = pi->radio_chanspec; ++ tbl_ptr = pi->calibration_cache.txcal_coeffs_2G; ++ } else { ++ ++ wlc_phy_rx_iq_coeffs_nphy(pi, 0, ++ &pi->calibration_cache. ++ rxcal_coeffs_5G); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ txcal_radio_regs = ++ pi->calibration_cache.txcal_radio_regs_5G; ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ pi->calibration_cache.txcal_radio_regs_5G[0] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_I | ++ RADIO_2056_TX0); ++ pi->calibration_cache.txcal_radio_regs_5G[1] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_Q | ++ RADIO_2056_TX0); ++ pi->calibration_cache.txcal_radio_regs_5G[2] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_I | ++ RADIO_2056_TX1); ++ pi->calibration_cache.txcal_radio_regs_5G[3] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_Q | ++ RADIO_2056_TX1); ++ ++ pi->calibration_cache.txcal_radio_regs_5G[4] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_I | ++ RADIO_2056_TX0); ++ pi->calibration_cache.txcal_radio_regs_5G[5] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_Q | ++ RADIO_2056_TX0); ++ pi->calibration_cache.txcal_radio_regs_5G[6] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_I | ++ RADIO_2056_TX1); ++ pi->calibration_cache.txcal_radio_regs_5G[7] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_Q | ++ RADIO_2056_TX1); ++ } else { ++ pi->calibration_cache.txcal_radio_regs_5G[0] = ++ read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL); ++ pi->calibration_cache.txcal_radio_regs_5G[1] = ++ read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL); ++ pi->calibration_cache.txcal_radio_regs_5G[2] = ++ read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM); ++ pi->calibration_cache.txcal_radio_regs_5G[3] = ++ read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM); ++ } ++ ++ pi->nphy_iqcal_chanspec_5G = pi->radio_chanspec; ++ tbl_ptr = pi->calibration_cache.txcal_coeffs_5G; ++ } ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ for (coreNum = 0; coreNum <= 1; coreNum++) { ++ ++ txcal_radio_regs[2 * coreNum] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, ++ LOFT_FINE_I); ++ txcal_radio_regs[2 * coreNum + 1] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, ++ LOFT_FINE_Q); ++ ++ txcal_radio_regs[2 * coreNum + 4] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, ++ LOFT_COARSE_I); ++ txcal_radio_regs[2 * coreNum + 5] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, ++ LOFT_COARSE_Q); ++ } ++ } ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 8, 80, 16, tbl_ptr); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static void wlc_phy_tx_iq_war_nphy(struct brcms_phy *pi) ++{ ++ struct nphy_iq_comp tx_comp; ++ ++ wlc_phy_table_read_nphy(pi, 15, 4, 0x50, 16, &tx_comp); ++ ++ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ, tx_comp.a0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 2, tx_comp.b0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 4, tx_comp.a1); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 6, tx_comp.b1); ++} ++ ++static void wlc_phy_restorecal_nphy(struct brcms_phy *pi) ++{ ++ u16 *loft_comp; ++ u16 txcal_coeffs_bphy[4]; ++ u16 *tbl_ptr; ++ int coreNum; ++ u16 *txcal_radio_regs = NULL; ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (pi->nphy_iqcal_chanspec_2G == 0) ++ return; ++ ++ tbl_ptr = pi->calibration_cache.txcal_coeffs_2G; ++ loft_comp = &pi->calibration_cache.txcal_coeffs_2G[5]; ++ } else { ++ if (pi->nphy_iqcal_chanspec_5G == 0) ++ return; ++ ++ tbl_ptr = pi->calibration_cache.txcal_coeffs_5G; ++ loft_comp = &pi->calibration_cache.txcal_coeffs_5G[5]; ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, 16, tbl_ptr); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ txcal_coeffs_bphy[0] = tbl_ptr[0]; ++ txcal_coeffs_bphy[1] = tbl_ptr[1]; ++ txcal_coeffs_bphy[2] = tbl_ptr[2]; ++ txcal_coeffs_bphy[3] = tbl_ptr[3]; ++ } else { ++ txcal_coeffs_bphy[0] = 0; ++ txcal_coeffs_bphy[1] = 0; ++ txcal_coeffs_bphy[2] = 0; ++ txcal_coeffs_bphy[3] = 0; ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, 16, ++ txcal_coeffs_bphy); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, 16, loft_comp); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, 16, loft_comp); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) ++ wlc_phy_tx_iq_war_nphy(pi); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ txcal_radio_regs = ++ pi->calibration_cache.txcal_radio_regs_2G; ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_I | ++ RADIO_2056_TX0, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[0]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_Q | ++ RADIO_2056_TX0, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[1]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_I | ++ RADIO_2056_TX1, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[2]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_Q | ++ RADIO_2056_TX1, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[3]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_I | ++ RADIO_2056_TX0, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[4]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_Q | ++ RADIO_2056_TX0, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[5]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_I | ++ RADIO_2056_TX1, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[6]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_Q | ++ RADIO_2056_TX1, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[7]); ++ } else { ++ write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[0]); ++ write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[1]); ++ write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[2]); ++ write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[3]); ++ } ++ ++ wlc_phy_rx_iq_coeffs_nphy(pi, 1, ++ &pi->calibration_cache. ++ rxcal_coeffs_2G); ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ txcal_radio_regs = ++ pi->calibration_cache.txcal_radio_regs_5G; ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_I | ++ RADIO_2056_TX0, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[0]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_Q | ++ RADIO_2056_TX0, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[1]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_I | ++ RADIO_2056_TX1, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[2]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_Q | ++ RADIO_2056_TX1, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[3]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_I | ++ RADIO_2056_TX0, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[4]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_Q | ++ RADIO_2056_TX0, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[5]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_I | ++ RADIO_2056_TX1, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[6]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_Q | ++ RADIO_2056_TX1, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[7]); ++ } else { ++ write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[0]); ++ write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[1]); ++ write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[2]); ++ write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[3]); ++ } ++ ++ wlc_phy_rx_iq_coeffs_nphy(pi, 1, ++ &pi->calibration_cache. ++ rxcal_coeffs_5G); ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ for (coreNum = 0; coreNum <= 1; coreNum++) { ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum, ++ LOFT_FINE_I, ++ txcal_radio_regs[2 * coreNum]); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum, ++ LOFT_FINE_Q, ++ txcal_radio_regs[2 * coreNum + 1]); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum, ++ LOFT_COARSE_I, ++ txcal_radio_regs[2 * coreNum + 4]); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum, ++ LOFT_COARSE_Q, ++ txcal_radio_regs[2 * coreNum + 5]); ++ } ++ } ++} ++ ++static void wlc_phy_txpwrctrl_coeff_setup_nphy(struct brcms_phy *pi) ++{ ++ u32 idx; ++ u16 iqloCalbuf[7]; ++ u32 iqcomp, locomp, curr_locomp; ++ s8 locomp_i, locomp_q; ++ s8 curr_locomp_i, curr_locomp_q; ++ u32 tbl_id, tbl_len, tbl_offset; ++ u32 regval[128]; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ wlc_phy_table_read_nphy(pi, 15, 7, 80, 16, iqloCalbuf); ++ ++ tbl_len = 128; ++ tbl_offset = 320; ++ for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL; ++ tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) { ++ iqcomp = ++ (tbl_id == ++ 26) ? (((u32) (iqloCalbuf[0] & 0x3ff)) << 10) | ++ (iqloCalbuf[1] & 0x3ff) ++ : (((u32) (iqloCalbuf[2] & 0x3ff)) << 10) | ++ (iqloCalbuf[3] & 0x3ff); ++ ++ for (idx = 0; idx < tbl_len; idx++) ++ regval[idx] = iqcomp; ++ wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32, ++ regval); ++ } ++ ++ tbl_offset = 448; ++ for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL; ++ tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) { ++ ++ locomp = ++ (u32) ((tbl_id == 26) ? iqloCalbuf[5] : iqloCalbuf[6]); ++ locomp_i = (s8) ((locomp >> 8) & 0xff); ++ locomp_q = (s8) ((locomp) & 0xff); ++ for (idx = 0; idx < tbl_len; idx++) { ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ curr_locomp_i = locomp_i; ++ curr_locomp_q = locomp_q; ++ } else { ++ curr_locomp_i = (s8) ((locomp_i * ++ nphy_tpc_loscale[idx] + ++ 128) >> 8); ++ curr_locomp_q = ++ (s8) ((locomp_q * ++ nphy_tpc_loscale[idx] + ++ 128) >> 8); ++ } ++ curr_locomp = (u32) ((curr_locomp_i & 0xff) << 8); ++ curr_locomp |= (u32) (curr_locomp_q & 0xff); ++ regval[idx] = curr_locomp; ++ } ++ wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32, ++ regval); ++ } ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) { ++ ++ wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX1, 0xFFFF); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX2, 0xFFFF); ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static void wlc_phy_txlpfbw_nphy(struct brcms_phy *pi) ++{ ++ u8 tx_lpf_bw = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) { ++ if (CHSPEC_IS40(pi->radio_chanspec)) ++ tx_lpf_bw = 3; ++ else ++ tx_lpf_bw = 1; ++ ++ if (PHY_IPA(pi)) { ++ if (CHSPEC_IS40(pi->radio_chanspec)) ++ tx_lpf_bw = 5; ++ else ++ tx_lpf_bw = 4; ++ } ++ ++ write_phy_reg(pi, 0xe8, ++ (tx_lpf_bw << 0) | ++ (tx_lpf_bw << 3) | ++ (tx_lpf_bw << 6) | (tx_lpf_bw << 9)); ++ ++ if (PHY_IPA(pi)) { ++ ++ if (CHSPEC_IS40(pi->radio_chanspec)) ++ tx_lpf_bw = 4; ++ else ++ tx_lpf_bw = 1; ++ ++ write_phy_reg(pi, 0xe9, ++ (tx_lpf_bw << 0) | ++ (tx_lpf_bw << 3) | ++ (tx_lpf_bw << 6) | (tx_lpf_bw << 9)); ++ } ++ } ++} ++ ++static void ++wlc_phy_adjust_rx_analpfbw_nphy(struct brcms_phy *pi, u16 reduction_factr) ++{ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) { ++ if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) && ++ CHSPEC_IS40(pi->radio_chanspec)) { ++ if (!pi->nphy_anarxlpf_adjusted) { ++ write_radio_reg(pi, ++ (RADIO_2056_RX_RXLPF_RCCAL_LPC | ++ RADIO_2056_RX0), ++ ((pi->nphy_rccal_value + ++ reduction_factr) | 0x80)); ++ ++ pi->nphy_anarxlpf_adjusted = true; ++ } ++ } else { ++ if (pi->nphy_anarxlpf_adjusted) { ++ write_radio_reg(pi, ++ (RADIO_2056_RX_RXLPF_RCCAL_LPC | ++ RADIO_2056_RX0), ++ (pi->nphy_rccal_value | 0x80)); ++ ++ pi->nphy_anarxlpf_adjusted = false; ++ } ++ } ++ } ++} ++ ++static void ++wlc_phy_adjust_min_noisevar_nphy(struct brcms_phy *pi, int ntones, ++ int *tone_id_buf, u32 *noise_var_buf) ++{ ++ int i; ++ u32 offset; ++ int tone_id; ++ int tbllen = ++ CHSPEC_IS40(pi->radio_chanspec) ? ++ NPHY_NOISEVAR_TBLLEN40 : NPHY_NOISEVAR_TBLLEN20; ++ ++ if (pi->nphy_noisevars_adjusted) { ++ for (i = 0; i < pi->nphy_saved_noisevars.bufcount; i++) { ++ tone_id = pi->nphy_saved_noisevars.tone_id[i]; ++ offset = (tone_id >= 0) ? ++ ((tone_id * ++ 2) + 1) : (tbllen + (tone_id * 2) + 1); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_NOISEVAR, 1, ++ offset, 32, ++ &pi->nphy_saved_noisevars.min_noise_vars[i]); ++ } ++ ++ pi->nphy_saved_noisevars.bufcount = 0; ++ pi->nphy_noisevars_adjusted = false; ++ } ++ ++ if ((noise_var_buf != NULL) && (tone_id_buf != NULL)) { ++ pi->nphy_saved_noisevars.bufcount = 0; ++ ++ for (i = 0; i < ntones; i++) { ++ tone_id = tone_id_buf[i]; ++ offset = (tone_id >= 0) ? ++ ((tone_id * 2) + 1) : ++ (tbllen + (tone_id * 2) + 1); ++ pi->nphy_saved_noisevars.tone_id[i] = tone_id; ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, ++ offset, 32, ++ &pi->nphy_saved_noisevars. ++ min_noise_vars[i]); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, ++ offset, 32, &noise_var_buf[i]); ++ pi->nphy_saved_noisevars.bufcount++; ++ } ++ ++ pi->nphy_noisevars_adjusted = true; ++ } ++} ++ ++static void wlc_phy_adjust_crsminpwr_nphy(struct brcms_phy *pi, u8 minpwr) ++{ ++ u16 regval; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) && ++ CHSPEC_IS40(pi->radio_chanspec)) { ++ if (!pi->nphy_crsminpwr_adjusted) { ++ regval = read_phy_reg(pi, 0x27d); ++ pi->nphy_crsminpwr[0] = regval & 0xff; ++ regval &= 0xff00; ++ regval |= (u16) minpwr; ++ write_phy_reg(pi, 0x27d, regval); ++ ++ regval = read_phy_reg(pi, 0x280); ++ pi->nphy_crsminpwr[1] = regval & 0xff; ++ regval &= 0xff00; ++ regval |= (u16) minpwr; ++ write_phy_reg(pi, 0x280, regval); ++ ++ regval = read_phy_reg(pi, 0x283); ++ pi->nphy_crsminpwr[2] = regval & 0xff; ++ regval &= 0xff00; ++ regval |= (u16) minpwr; ++ write_phy_reg(pi, 0x283, regval); ++ ++ pi->nphy_crsminpwr_adjusted = true; ++ } ++ } else { ++ if (pi->nphy_crsminpwr_adjusted) { ++ regval = read_phy_reg(pi, 0x27d); ++ regval &= 0xff00; ++ regval |= pi->nphy_crsminpwr[0]; ++ write_phy_reg(pi, 0x27d, regval); ++ ++ regval = read_phy_reg(pi, 0x280); ++ regval &= 0xff00; ++ regval |= pi->nphy_crsminpwr[1]; ++ write_phy_reg(pi, 0x280, regval); ++ ++ regval = read_phy_reg(pi, 0x283); ++ regval &= 0xff00; ++ regval |= pi->nphy_crsminpwr[2]; ++ write_phy_reg(pi, 0x283, regval); ++ ++ pi->nphy_crsminpwr_adjusted = false; ++ } ++ } ++ } ++} ++ ++static void wlc_phy_spurwar_nphy(struct brcms_phy *pi) ++{ ++ u16 cur_channel = 0; ++ int nphy_adj_tone_id_buf[] = { 57, 58 }; ++ u32 nphy_adj_noise_var_buf[] = { 0x3ff, 0x3ff }; ++ bool isAdjustNoiseVar = false; ++ uint numTonesAdjust = 0; ++ u32 tempval = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ cur_channel = CHSPEC_CHANNEL(pi->radio_chanspec); ++ ++ if (pi->nphy_gband_spurwar_en) { ++ ++ wlc_phy_adjust_rx_analpfbw_nphy( ++ pi, ++ NPHY_ANARXLPFBW_REDUCTIONFACT); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if ((cur_channel == 11) ++ && CHSPEC_IS40(pi->radio_chanspec)) ++ wlc_phy_adjust_min_noisevar_nphy( ++ pi, 2, ++ nphy_adj_tone_id_buf, ++ nphy_adj_noise_var_buf); ++ else ++ wlc_phy_adjust_min_noisevar_nphy(pi, 0, ++ NULL, ++ NULL); ++ } ++ ++ wlc_phy_adjust_crsminpwr_nphy(pi, ++ NPHY_ADJUSTED_MINCRSPOWER); ++ } ++ ++ if ((pi->nphy_gband_spurwar2_en) ++ && CHSPEC_IS2G(pi->radio_chanspec)) { ++ ++ if (CHSPEC_IS40(pi->radio_chanspec)) { ++ switch (cur_channel) { ++ case 3: ++ nphy_adj_tone_id_buf[0] = 57; ++ nphy_adj_tone_id_buf[1] = 58; ++ nphy_adj_noise_var_buf[0] = 0x22f; ++ nphy_adj_noise_var_buf[1] = 0x25f; ++ isAdjustNoiseVar = true; ++ break; ++ case 4: ++ nphy_adj_tone_id_buf[0] = 41; ++ nphy_adj_tone_id_buf[1] = 42; ++ nphy_adj_noise_var_buf[0] = 0x22f; ++ nphy_adj_noise_var_buf[1] = 0x25f; ++ isAdjustNoiseVar = true; ++ break; ++ case 5: ++ nphy_adj_tone_id_buf[0] = 25; ++ nphy_adj_tone_id_buf[1] = 26; ++ nphy_adj_noise_var_buf[0] = 0x24f; ++ nphy_adj_noise_var_buf[1] = 0x25f; ++ isAdjustNoiseVar = true; ++ break; ++ case 6: ++ nphy_adj_tone_id_buf[0] = 9; ++ nphy_adj_tone_id_buf[1] = 10; ++ nphy_adj_noise_var_buf[0] = 0x22f; ++ nphy_adj_noise_var_buf[1] = 0x24f; ++ isAdjustNoiseVar = true; ++ break; ++ case 7: ++ nphy_adj_tone_id_buf[0] = 121; ++ nphy_adj_tone_id_buf[1] = 122; ++ nphy_adj_noise_var_buf[0] = 0x18f; ++ nphy_adj_noise_var_buf[1] = 0x24f; ++ isAdjustNoiseVar = true; ++ break; ++ case 8: ++ nphy_adj_tone_id_buf[0] = 105; ++ nphy_adj_tone_id_buf[1] = 106; ++ nphy_adj_noise_var_buf[0] = 0x22f; ++ nphy_adj_noise_var_buf[1] = 0x25f; ++ isAdjustNoiseVar = true; ++ break; ++ case 9: ++ nphy_adj_tone_id_buf[0] = 89; ++ nphy_adj_tone_id_buf[1] = 90; ++ nphy_adj_noise_var_buf[0] = 0x22f; ++ nphy_adj_noise_var_buf[1] = 0x24f; ++ isAdjustNoiseVar = true; ++ break; ++ case 10: ++ nphy_adj_tone_id_buf[0] = 73; ++ nphy_adj_tone_id_buf[1] = 74; ++ nphy_adj_noise_var_buf[0] = 0x22f; ++ nphy_adj_noise_var_buf[1] = 0x24f; ++ isAdjustNoiseVar = true; ++ break; ++ default: ++ isAdjustNoiseVar = false; ++ break; ++ } ++ } ++ ++ if (isAdjustNoiseVar) { ++ numTonesAdjust = sizeof(nphy_adj_tone_id_buf) / ++ sizeof(nphy_adj_tone_id_buf[0]); ++ ++ wlc_phy_adjust_min_noisevar_nphy( ++ pi, ++ numTonesAdjust, ++ nphy_adj_tone_id_buf, ++ nphy_adj_noise_var_buf); ++ ++ tempval = 0; ++ ++ } else { ++ wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL, ++ NULL); ++ } ++ } ++ ++ if ((pi->nphy_aband_spurwar_en) && ++ (CHSPEC_IS5G(pi->radio_chanspec))) { ++ switch (cur_channel) { ++ case 54: ++ nphy_adj_tone_id_buf[0] = 32; ++ nphy_adj_noise_var_buf[0] = 0x25f; ++ break; ++ case 38: ++ case 102: ++ case 118: ++ nphy_adj_tone_id_buf[0] = 0; ++ nphy_adj_noise_var_buf[0] = 0x0; ++ break; ++ case 134: ++ nphy_adj_tone_id_buf[0] = 32; ++ nphy_adj_noise_var_buf[0] = 0x21f; ++ break; ++ case 151: ++ nphy_adj_tone_id_buf[0] = 16; ++ nphy_adj_noise_var_buf[0] = 0x23f; ++ break; ++ case 153: ++ case 161: ++ nphy_adj_tone_id_buf[0] = 48; ++ nphy_adj_noise_var_buf[0] = 0x23f; ++ break; ++ default: ++ nphy_adj_tone_id_buf[0] = 0; ++ nphy_adj_noise_var_buf[0] = 0x0; ++ break; ++ } ++ ++ if (nphy_adj_tone_id_buf[0] ++ && nphy_adj_noise_var_buf[0]) ++ wlc_phy_adjust_min_noisevar_nphy( ++ pi, 1, ++ nphy_adj_tone_id_buf, ++ nphy_adj_noise_var_buf); ++ else ++ wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL, ++ NULL); ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ } ++} ++ ++void wlc_phy_init_nphy(struct brcms_phy *pi) ++{ ++ u16 val; ++ u16 clip1_ths[2]; ++ struct nphy_txgains target_gain; ++ u8 tx_pwr_ctrl_state; ++ bool do_nphy_cal = false; ++ uint core; ++ uint origidx, intr_val; ++ struct d11regs __iomem *regs; ++ u32 d11_clk_ctl_st; ++ bool do_rssi_cal = false; ++ ++ core = 0; ++ ++ if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) ++ pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC; ++ ++ if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) && ++ ((pi->sh->chippkg == BCM4717_PKG_ID) || ++ (pi->sh->chippkg == BCM4718_PKG_ID))) { ++ if ((pi->sh->boardflags & BFL_EXTLNA) && ++ (CHSPEC_IS2G(pi->radio_chanspec))) ++ ai_corereg(pi->sh->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol), ++ 0x40, 0x40); ++ } ++ ++ if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) && ++ CHSPEC_IS40(pi->radio_chanspec)) { ++ ++ regs = (struct d11regs __iomem *) ++ ai_switch_core(pi->sh->sih, ++ D11_CORE_ID, &origidx, ++ &intr_val); ++ d11_clk_ctl_st = R_REG(®s->clk_ctl_st); ++ AND_REG(®s->clk_ctl_st, ++ ~(CCS_FORCEHT | CCS_HTAREQ)); ++ ++ W_REG(®s->clk_ctl_st, d11_clk_ctl_st); ++ ++ ai_restore_core(pi->sh->sih, origidx, intr_val); ++ } ++ ++ pi->use_int_tx_iqlo_cal_nphy = ++ (PHY_IPA(pi) || ++ (NREV_GE(pi->pubpi.phy_rev, 7) || ++ (NREV_GE(pi->pubpi.phy_rev, 5) ++ && pi->sh->boardflags2 & BFL2_INTERNDET_TXIQCAL))); ++ ++ pi->internal_tx_iqlo_cal_tapoff_intpa_nphy = false; ++ ++ pi->nphy_deaf_count = 0; ++ ++ wlc_phy_tbl_init_nphy(pi); ++ ++ pi->nphy_crsminpwr_adjusted = false; ++ pi->nphy_noisevars_adjusted = false; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ write_phy_reg(pi, 0xe7, 0); ++ write_phy_reg(pi, 0xec, 0); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ write_phy_reg(pi, 0x342, 0); ++ write_phy_reg(pi, 0x343, 0); ++ write_phy_reg(pi, 0x346, 0); ++ write_phy_reg(pi, 0x347, 0); ++ } ++ write_phy_reg(pi, 0xe5, 0); ++ write_phy_reg(pi, 0xe6, 0); ++ } else { ++ write_phy_reg(pi, 0xec, 0); ++ } ++ ++ write_phy_reg(pi, 0x91, 0); ++ write_phy_reg(pi, 0x92, 0); ++ if (NREV_LT(pi->pubpi.phy_rev, 6)) { ++ write_phy_reg(pi, 0x93, 0); ++ write_phy_reg(pi, 0x94, 0); ++ } ++ ++ and_phy_reg(pi, 0xa1, ~3); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ write_phy_reg(pi, 0x8f, 0); ++ write_phy_reg(pi, 0xa5, 0); ++ } else { ++ write_phy_reg(pi, 0xa5, 0); ++ } ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 2)) ++ mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b); ++ else if (NREV_LT(pi->pubpi.phy_rev, 2)) ++ mod_phy_reg(pi, 0xdc, 0x00ff, 0x40); ++ ++ write_phy_reg(pi, 0x203, 32); ++ write_phy_reg(pi, 0x201, 32); ++ ++ if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD) ++ write_phy_reg(pi, 0x20d, 160); ++ else ++ write_phy_reg(pi, 0x20d, 184); ++ ++ write_phy_reg(pi, 0x13a, 200); ++ ++ write_phy_reg(pi, 0x70, 80); ++ ++ write_phy_reg(pi, 0x1ff, 48); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 8)) ++ wlc_phy_update_mimoconfig_nphy(pi, pi->n_preamble_override); ++ ++ wlc_phy_stf_chain_upd_nphy(pi); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) { ++ write_phy_reg(pi, 0x180, 0xaa8); ++ write_phy_reg(pi, 0x181, 0x9a4); ++ } ++ ++ if (PHY_IPA(pi)) { ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (1) << 0); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x298 : ++ 0x29c, (0x1ff << 7), ++ (pi->nphy_papd_epsilon_offset[core]) << 7); ++ ++ } ++ ++ wlc_phy_ipa_set_tx_digi_filts_nphy(pi); ++ } else if (NREV_GE(pi->pubpi.phy_rev, 5)) { ++ wlc_phy_extpa_set_tx_digi_filts_nphy(pi); ++ } ++ ++ wlc_phy_workarounds_nphy(pi); ++ ++ wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON); ++ ++ val = read_phy_reg(pi, 0x01); ++ write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA); ++ write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA)); ++ wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF); ++ ++ wlapi_bmac_macphyclk_set(pi->sh->physhim, ON); ++ ++ wlc_phy_pa_override_nphy(pi, OFF); ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX); ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); ++ wlc_phy_pa_override_nphy(pi, ON); ++ ++ wlc_phy_classifier_nphy(pi, 0, 0); ++ wlc_phy_clip_det_nphy(pi, 0, clip1_ths); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ wlc_phy_bphy_init_nphy(pi); ++ ++ tx_pwr_ctrl_state = pi->nphy_txpwrctrl; ++ wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF); ++ ++ wlc_phy_txpwr_fixpower_nphy(pi); ++ ++ wlc_phy_txpwrctrl_idle_tssi_nphy(pi); ++ ++ wlc_phy_txpwrctrl_pwr_setup_nphy(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ u32 *tx_pwrctrl_tbl = NULL; ++ u16 idx; ++ s16 pga_gn = 0; ++ s16 pad_gn = 0; ++ s32 rfpwr_offset; ++ ++ if (PHY_IPA(pi)) { ++ tx_pwrctrl_tbl = wlc_phy_get_ipa_gaintbl_nphy(pi); ++ } else { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (NREV_IS(pi->pubpi.phy_rev, 3)) ++ tx_pwrctrl_tbl = ++ nphy_tpc_5GHz_txgain_rev3; ++ else if (NREV_IS(pi->pubpi.phy_rev, 4)) ++ tx_pwrctrl_tbl = ++ (pi->srom_fem5g.extpagain == ++ 3) ? ++ nphy_tpc_5GHz_txgain_HiPwrEPA : ++ nphy_tpc_5GHz_txgain_rev4; ++ else ++ tx_pwrctrl_tbl = ++ nphy_tpc_5GHz_txgain_rev5; ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (pi->pubpi.radiorev == 5) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_epa_2057rev5; ++ else if (pi->pubpi.radiorev == 3) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_epa_2057rev3; ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 5) && ++ (pi->srom_fem2g.extpagain == 3)) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_HiPwrEPA; ++ else ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_rev3; ++ } ++ } ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128, ++ 192, 32, tx_pwrctrl_tbl); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128, ++ 192, 32, tx_pwrctrl_tbl); ++ ++ pi->nphy_gmval = (u16) ((*tx_pwrctrl_tbl >> 16) & 0x7000); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ for (idx = 0; idx < 128; idx++) { ++ pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf; ++ pad_gn = (tx_pwrctrl_tbl[idx] >> 19) & 0x1f; ++ rfpwr_offset = get_rf_pwr_offset(pi, pga_gn, ++ pad_gn); ++ wlc_phy_table_write_nphy( ++ pi, ++ NPHY_TBL_ID_CORE1TXPWRCTL, ++ 1, 576 + idx, 32, ++ &rfpwr_offset); ++ wlc_phy_table_write_nphy( ++ pi, ++ NPHY_TBL_ID_CORE2TXPWRCTL, ++ 1, 576 + idx, 32, ++ &rfpwr_offset); ++ } ++ } else { ++ ++ for (idx = 0; idx < 128; idx++) { ++ pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf; ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ rfpwr_offset = (s16) ++ nphy_papd_pga_gain_delta_ipa_2g ++ [pga_gn]; ++ else ++ rfpwr_offset = (s16) ++ nphy_papd_pga_gain_delta_ipa_5g ++ [pga_gn]; ++ ++ wlc_phy_table_write_nphy( ++ pi, ++ NPHY_TBL_ID_CORE1TXPWRCTL, ++ 1, 576 + idx, 32, ++ &rfpwr_offset); ++ wlc_phy_table_write_nphy( ++ pi, ++ NPHY_TBL_ID_CORE2TXPWRCTL, ++ 1, 576 + idx, 32, ++ &rfpwr_offset); ++ } ++ ++ } ++ } else { ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128, ++ 192, 32, nphy_tpc_txgain); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128, ++ 192, 32, nphy_tpc_txgain); ++ } ++ ++ if (pi->sh->phyrxchain != 0x3) ++ wlc_phy_rxcore_setstate_nphy((struct brcms_phy_pub *) pi, ++ pi->sh->phyrxchain); ++ ++ if (PHY_PERICAL_MPHASE_PENDING(pi)) ++ wlc_phy_cal_perical_mphase_restart(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ do_rssi_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ? ++ (pi->nphy_rssical_chanspec_2G == 0) : ++ (pi->nphy_rssical_chanspec_5G == 0); ++ ++ if (do_rssi_cal) ++ wlc_phy_rssi_cal_nphy(pi); ++ else ++ wlc_phy_restore_rssical_nphy(pi); ++ } else { ++ wlc_phy_rssi_cal_nphy(pi); ++ } ++ ++ if (!SCAN_RM_IN_PROGRESS(pi)) ++ do_nphy_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ? ++ (pi->nphy_iqcal_chanspec_2G == 0) : ++ (pi->nphy_iqcal_chanspec_5G == 0); ++ ++ if (!pi->do_initcal) ++ do_nphy_cal = false; ++ ++ if (do_nphy_cal) { ++ ++ target_gain = wlc_phy_get_tx_gain_nphy(pi); ++ ++ if (pi->antsel_type == ANTSEL_2x3) ++ wlc_phy_antsel_init((struct brcms_phy_pub *) pi, ++ true); ++ ++ if (pi->nphy_perical != PHY_PERICAL_MPHASE) { ++ wlc_phy_rssi_cal_nphy(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ pi->nphy_cal_orig_pwr_idx[0] = ++ pi->nphy_txpwrindex[PHY_CORE_0] ++ . ++ index_internal; ++ pi->nphy_cal_orig_pwr_idx[1] = ++ pi->nphy_txpwrindex[PHY_CORE_1] ++ . ++ index_internal; ++ ++ wlc_phy_precal_txgain_nphy(pi); ++ target_gain = ++ wlc_phy_get_tx_gain_nphy(pi); ++ } ++ ++ if (wlc_phy_cal_txiqlo_nphy ++ (pi, target_gain, true, ++ false) == 0) { ++ if (wlc_phy_cal_rxiq_nphy ++ (pi, target_gain, 2, ++ false) == 0) ++ wlc_phy_savecal_nphy(pi); ++ ++ } ++ } else if (pi->mphase_cal_phase_id == ++ MPHASE_CAL_STATE_IDLE) { ++ wlc_phy_cal_perical((struct brcms_phy_pub *) pi, ++ PHY_PERICAL_PHYINIT); ++ } ++ } else { ++ wlc_phy_restorecal_nphy(pi); ++ } ++ ++ wlc_phy_txpwrctrl_coeff_setup_nphy(pi); ++ ++ wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state); ++ ++ wlc_phy_nphy_tkip_rifs_war(pi, pi->sh->_rifs_phy); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LE(pi->pubpi.phy_rev, 6)) ++ ++ write_phy_reg(pi, 0x70, 50); ++ ++ wlc_phy_txlpfbw_nphy(pi); ++ ++ wlc_phy_spurwar_nphy(pi); ++ ++} ++ ++static void wlc_phy_resetcca_nphy(struct brcms_phy *pi) ++{ ++ u16 val; ++ ++ wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON); ++ ++ val = read_phy_reg(pi, 0x01); ++ write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA); ++ udelay(1); ++ write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA)); ++ ++ wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF); ++ ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); ++} ++ ++void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en) ++{ ++ u16 rfctrlintc_override_val; ++ ++ if (!en) { ++ ++ pi->rfctrlIntc1_save = read_phy_reg(pi, 0x91); ++ pi->rfctrlIntc2_save = read_phy_reg(pi, 0x92); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ rfctrlintc_override_val = 0x1480; ++ else if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ rfctrlintc_override_val = ++ CHSPEC_IS5G(pi->radio_chanspec) ? 0x600 : 0x480; ++ else ++ rfctrlintc_override_val = ++ CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120; ++ ++ write_phy_reg(pi, 0x91, rfctrlintc_override_val); ++ write_phy_reg(pi, 0x92, rfctrlintc_override_val); ++ } else { ++ write_phy_reg(pi, 0x91, pi->rfctrlIntc1_save); ++ write_phy_reg(pi, 0x92, pi->rfctrlIntc2_save); ++ } ++ ++} ++ ++void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi) ++{ ++ ++ u16 txrx_chain = ++ (NPHY_RfseqCoreActv_TxRxChain0 | NPHY_RfseqCoreActv_TxRxChain1); ++ bool CoreActv_override = false; ++ ++ if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN0) { ++ txrx_chain = NPHY_RfseqCoreActv_TxRxChain0; ++ CoreActv_override = true; ++ ++ if (NREV_LE(pi->pubpi.phy_rev, 2)) ++ and_phy_reg(pi, 0xa0, ~0x20); ++ } else if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN1) { ++ txrx_chain = NPHY_RfseqCoreActv_TxRxChain1; ++ CoreActv_override = true; ++ ++ if (NREV_LE(pi->pubpi.phy_rev, 2)) ++ or_phy_reg(pi, 0xa0, 0x20); ++ } ++ ++ mod_phy_reg(pi, 0xa2, ((0xf << 0) | (0xf << 4)), txrx_chain); ++ ++ if (CoreActv_override) { ++ pi->nphy_perical = PHY_PERICAL_DISABLE; ++ or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override); ++ } else { ++ pi->nphy_perical = PHY_PERICAL_MPHASE; ++ and_phy_reg(pi, 0xa1, ~NPHY_RfseqMode_CoreActv_override); ++ } ++} ++ ++void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask) ++{ ++ u16 regval; ++ u16 tbl_buf[16]; ++ uint i; ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ u16 tbl_opcode; ++ bool suspend; ++ ++ pi->sh->phyrxchain = rxcore_bitmask; ++ ++ if (!pi->sh->clk) ++ return; ++ ++ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ regval = read_phy_reg(pi, 0xa2); ++ regval &= ~(0xf << 4); ++ regval |= ((u16) (rxcore_bitmask & 0x3)) << 4; ++ write_phy_reg(pi, 0xa2, regval); ++ ++ if ((rxcore_bitmask & 0x3) != 0x3) { ++ ++ write_phy_reg(pi, 0x20e, 1); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (pi->rx2tx_biasentry == -1) { ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, ++ ARRAY_SIZE(tbl_buf), 80, ++ 16, tbl_buf); ++ ++ for (i = 0; i < ARRAY_SIZE(tbl_buf); i++) { ++ if (tbl_buf[i] == ++ NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS) { ++ pi->rx2tx_biasentry = (u8) i; ++ tbl_opcode = ++ NPHY_REV3_RFSEQ_CMD_NOP; ++ wlc_phy_table_write_nphy( ++ pi, ++ NPHY_TBL_ID_RFSEQ, ++ 1, i, ++ 16, ++ &tbl_opcode); ++ break; ++ } else if (tbl_buf[i] == ++ NPHY_REV3_RFSEQ_CMD_END) ++ break; ++ } ++ } ++ } ++ } else { ++ ++ write_phy_reg(pi, 0x20e, 30); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (pi->rx2tx_biasentry != -1) { ++ tbl_opcode = NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, ++ 1, pi->rx2tx_biasentry, ++ 16, &tbl_opcode); ++ pi->rx2tx_biasentry = -1; ++ } ++ } ++ } ++ ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++} ++ ++u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih) ++{ ++ u16 regval, rxen_bits; ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ regval = read_phy_reg(pi, 0xa2); ++ rxen_bits = (regval >> 4) & 0xf; ++ ++ return (u8) rxen_bits; ++} ++ ++bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pi) ++{ ++ return PHY_IPA(pi); ++} ++ ++void wlc_phy_cal_init_nphy(struct brcms_phy *pi) ++{ ++} ++ ++static void wlc_phy_radio_preinit_205x(struct brcms_phy *pi) ++{ ++ ++ and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU); ++ and_phy_reg(pi, 0x78, RFCC_OE_POR_FORCE); ++ ++ or_phy_reg(pi, 0x78, ~RFCC_OE_POR_FORCE); ++ or_phy_reg(pi, 0x78, RFCC_CHIP0_PU); ++ ++} ++ ++static void wlc_phy_radio_init_2057(struct brcms_phy *pi) ++{ ++ struct radio_20xx_regs *regs_2057_ptr = NULL; ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7)) { ++ regs_2057_ptr = regs_2057_rev4; ++ } else if (NREV_IS(pi->pubpi.phy_rev, 8) ++ || NREV_IS(pi->pubpi.phy_rev, 9)) { ++ switch (pi->pubpi.radiorev) { ++ case 5: ++ ++ if (pi->pubpi.radiover == 0x0) ++ regs_2057_ptr = regs_2057_rev5; ++ else if (pi->pubpi.radiover == 0x1) ++ regs_2057_ptr = regs_2057_rev5v1; ++ else ++ break; ++ ++ case 7: ++ ++ regs_2057_ptr = regs_2057_rev7; ++ break; ++ ++ case 8: ++ ++ regs_2057_ptr = regs_2057_rev8; ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ wlc_phy_init_radio_regs_allbands(pi, regs_2057_ptr); ++} ++ ++static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi) ++{ ++ u16 rcal_reg = 0; ++ int i; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ if (pi->pubpi.radiorev == 5) { ++ ++ and_phy_reg(pi, 0x342, ~(0x1 << 1)); ++ ++ udelay(10); ++ ++ mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x1); ++ mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2, ++ 0x1); ++ } ++ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x1); ++ ++ udelay(10); ++ ++ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x3, 0x3); ++ ++ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { ++ rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS); ++ if (rcal_reg & 0x1) ++ break; ++ ++ udelay(100); ++ } ++ ++ if (WARN(i == MAX_205x_RCAL_WAITLOOPS, ++ "HW error: radio calib2")) ++ return 0; ++ ++ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x2, 0x0); ++ ++ rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS) & 0x3e; ++ ++ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x0); ++ if (pi->pubpi.radiorev == 5) { ++ ++ mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x0); ++ mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2, ++ 0x0); ++ } ++ ++ if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) { ++ ++ mod_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x3c, ++ rcal_reg); ++ mod_radio_reg(pi, RADIO_2057_BANDGAP_RCAL_TRIM, 0xf0, ++ rcal_reg << 2); ++ } ++ ++ } else if (NREV_IS(pi->pubpi.phy_rev, 3)) { ++ u16 savereg; ++ ++ savereg = ++ read_radio_reg( ++ pi, ++ RADIO_2056_SYN_PLL_MAST2 | ++ RADIO_2056_SYN); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN, ++ savereg | 0x7); ++ udelay(10); ++ ++ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN, ++ 0x1); ++ udelay(10); ++ ++ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN, ++ 0x9); ++ ++ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { ++ rcal_reg = read_radio_reg( ++ pi, ++ RADIO_2056_SYN_RCAL_CODE_OUT | ++ RADIO_2056_SYN); ++ if (rcal_reg & 0x80) ++ break; ++ ++ udelay(100); ++ } ++ ++ if (WARN(i == MAX_205x_RCAL_WAITLOOPS, ++ "HW error: radio calib3")) ++ return 0; ++ ++ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN, ++ 0x1); ++ ++ rcal_reg = ++ read_radio_reg(pi, ++ RADIO_2056_SYN_RCAL_CODE_OUT | ++ RADIO_2056_SYN); ++ ++ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN, ++ 0x0); ++ ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN, ++ savereg); ++ ++ return rcal_reg & 0x1f; ++ } ++ return rcal_reg & 0x3e; ++} ++ ++static u16 wlc_phy_radio2057_rccal(struct brcms_phy *pi) ++{ ++ u16 rccal_valid; ++ int i; ++ bool chip43226_6362A0; ++ ++ chip43226_6362A0 = ((pi->pubpi.radiorev == 3) ++ || (pi->pubpi.radiorev == 4) ++ || (pi->pubpi.radiorev == 6)); ++ ++ rccal_valid = 0; ++ if (chip43226_6362A0) { ++ write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x61); ++ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xc0); ++ } else { ++ write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x61); ++ ++ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xe9); ++ } ++ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e); ++ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55); ++ ++ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { ++ rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP); ++ if (rccal_valid & 0x2) ++ break; ++ ++ udelay(500); ++ } ++ ++ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15); ++ ++ rccal_valid = 0; ++ if (chip43226_6362A0) { ++ write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x69); ++ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0); ++ } else { ++ write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x69); ++ ++ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xd5); ++ } ++ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e); ++ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55); ++ ++ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { ++ rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP); ++ if (rccal_valid & 0x2) ++ break; ++ ++ udelay(500); ++ } ++ ++ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15); ++ ++ rccal_valid = 0; ++ if (chip43226_6362A0) { ++ write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x73); ++ ++ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x28); ++ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0); ++ } else { ++ write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x73); ++ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e); ++ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0x99); ++ } ++ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55); ++ ++ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { ++ rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP); ++ if (rccal_valid & 0x2) ++ break; ++ ++ udelay(500); ++ } ++ ++ if (WARN(!(rccal_valid & 0x2), "HW error: radio calib4")) ++ return 0; ++ ++ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15); ++ ++ return rccal_valid; ++} ++ ++static void wlc_phy_radio_postinit_2057(struct brcms_phy *pi) ++{ ++ ++ mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x1, 0x1); ++ ++ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x78); ++ mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x80); ++ mdelay(2); ++ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x0); ++ mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x0); ++ ++ if (pi->phy_init_por) { ++ wlc_phy_radio205x_rcal(pi); ++ wlc_phy_radio2057_rccal(pi); ++ } ++ ++ mod_radio_reg(pi, RADIO_2057_RFPLL_MASTER, 0x8, 0x0); ++} ++ ++static void wlc_phy_radio_init_2056(struct brcms_phy *pi) ++{ ++ const struct radio_regs *regs_SYN_2056_ptr = NULL; ++ const struct radio_regs *regs_TX_2056_ptr = NULL; ++ const struct radio_regs *regs_RX_2056_ptr = NULL; ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 3)) { ++ regs_SYN_2056_ptr = regs_SYN_2056; ++ regs_TX_2056_ptr = regs_TX_2056; ++ regs_RX_2056_ptr = regs_RX_2056; ++ } else if (NREV_IS(pi->pubpi.phy_rev, 4)) { ++ regs_SYN_2056_ptr = regs_SYN_2056_A1; ++ regs_TX_2056_ptr = regs_TX_2056_A1; ++ regs_RX_2056_ptr = regs_RX_2056_A1; ++ } else { ++ switch (pi->pubpi.radiorev) { ++ case 5: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev5; ++ regs_TX_2056_ptr = regs_TX_2056_rev5; ++ regs_RX_2056_ptr = regs_RX_2056_rev5; ++ break; ++ ++ case 6: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev6; ++ regs_TX_2056_ptr = regs_TX_2056_rev6; ++ regs_RX_2056_ptr = regs_RX_2056_rev6; ++ break; ++ ++ case 7: ++ case 9: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev7; ++ regs_TX_2056_ptr = regs_TX_2056_rev7; ++ regs_RX_2056_ptr = regs_RX_2056_rev7; ++ break; ++ ++ case 8: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev8; ++ regs_TX_2056_ptr = regs_TX_2056_rev8; ++ regs_RX_2056_ptr = regs_RX_2056_rev8; ++ break; ++ ++ case 11: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev11; ++ regs_TX_2056_ptr = regs_TX_2056_rev11; ++ regs_RX_2056_ptr = regs_RX_2056_rev11; ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ wlc_phy_init_radio_regs(pi, regs_SYN_2056_ptr, (u16) RADIO_2056_SYN); ++ ++ wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX0); ++ ++ wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX1); ++ ++ wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX0); ++ ++ wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX1); ++} ++ ++static void wlc_phy_radio_postinit_2056(struct brcms_phy *pi) ++{ ++ mod_radio_reg(pi, RADIO_2056_SYN_COM_CTRL, 0xb, 0xb); ++ ++ mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x2); ++ mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x2); ++ udelay(1000); ++ mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x0); ++ ++ if ((pi->sh->boardflags2 & BFL2_LEGACY) ++ || (pi->sh->boardflags2 & BFL2_XTALBUFOUTEN)) ++ mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xf4, 0x0); ++ else ++ mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xfc, 0x0); ++ ++ mod_radio_reg(pi, RADIO_2056_SYN_RCCAL_CTRL0, 0x1, 0x0); ++ ++ if (pi->phy_init_por) ++ wlc_phy_radio205x_rcal(pi); ++} ++ ++static void wlc_phy_radio_preinit_2055(struct brcms_phy *pi) ++{ ++ ++ and_phy_reg(pi, 0x78, ~RFCC_POR_FORCE); ++ or_phy_reg(pi, 0x78, RFCC_CHIP0_PU | RFCC_OE_POR_FORCE); ++ ++ or_phy_reg(pi, 0x78, RFCC_POR_FORCE); ++} ++ ++static void wlc_phy_radio_init_2055(struct brcms_phy *pi) ++{ ++ wlc_phy_init_radio_regs(pi, regs_2055, RADIO_DEFAULT_CORE); ++} ++ ++static void wlc_phy_radio_postinit_2055(struct brcms_phy *pi) ++{ ++ ++ and_radio_reg(pi, RADIO_2055_MASTER_CNTRL1, ++ ~(RADIO_2055_JTAGCTRL_MASK | RADIO_2055_JTAGSYNC_MASK)); ++ ++ if (((pi->sh->sromrev >= 4) ++ && !(pi->sh->boardflags2 & BFL2_RXBB_INT_REG_DIS)) ++ || ((pi->sh->sromrev < 4))) { ++ and_radio_reg(pi, RADIO_2055_CORE1_RXBB_REGULATOR, 0x7F); ++ and_radio_reg(pi, RADIO_2055_CORE2_RXBB_REGULATOR, 0x7F); ++ } ++ ++ mod_radio_reg(pi, RADIO_2055_RRCCAL_N_OPT_SEL, 0x3F, 0x2C); ++ write_radio_reg(pi, RADIO_2055_CAL_MISC, 0x3C); ++ ++ and_radio_reg(pi, RADIO_2055_CAL_MISC, ++ ~(RADIO_2055_RRCAL_START | RADIO_2055_RRCAL_RST_N)); ++ ++ or_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL, RADIO_2055_CAL_LPO_ENABLE); ++ ++ or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_RST_N); ++ ++ udelay(1000); ++ ++ or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_START); ++ ++ SPINWAIT(((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) & ++ RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE), 2000); ++ ++ if (WARN((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) & ++ RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE, ++ "HW error: radio calibration1\n")) ++ return; ++ ++ and_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL, ++ ~(RADIO_2055_CAL_LPO_ENABLE)); ++ ++ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec); ++ ++ write_radio_reg(pi, RADIO_2055_CORE1_RXBB_LPF, 9); ++ write_radio_reg(pi, RADIO_2055_CORE2_RXBB_LPF, 9); ++ ++ write_radio_reg(pi, RADIO_2055_CORE1_RXBB_MIDAC_HIPAS, 0x83); ++ write_radio_reg(pi, RADIO_2055_CORE2_RXBB_MIDAC_HIPAS, 0x83); ++ ++ mod_radio_reg(pi, RADIO_2055_CORE1_LNA_GAINBST, ++ RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE); ++ mod_radio_reg(pi, RADIO_2055_CORE2_LNA_GAINBST, ++ RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE); ++ if (pi->nphy_gain_boost) { ++ and_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1, ++ ~(RADIO_2055_GAINBST_DISABLE)); ++ and_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1, ++ ~(RADIO_2055_GAINBST_DISABLE)); ++ } else { ++ or_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1, ++ RADIO_2055_GAINBST_DISABLE); ++ or_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1, ++ RADIO_2055_GAINBST_DISABLE); ++ } ++ ++ udelay(2); ++} ++ ++void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on) ++{ ++ if (on) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (!pi->radio_is_on) { ++ wlc_phy_radio_preinit_205x(pi); ++ wlc_phy_radio_init_2057(pi); ++ wlc_phy_radio_postinit_2057(pi); ++ } ++ ++ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, ++ pi->radio_chanspec); ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ wlc_phy_radio_preinit_205x(pi); ++ wlc_phy_radio_init_2056(pi); ++ wlc_phy_radio_postinit_2056(pi); ++ ++ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, ++ pi->radio_chanspec); ++ } else { ++ wlc_phy_radio_preinit_2055(pi); ++ wlc_phy_radio_init_2055(pi); ++ wlc_phy_radio_postinit_2055(pi); ++ } ++ ++ pi->radio_is_on = true; ++ ++ } else { ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) ++ && NREV_LT(pi->pubpi.phy_rev, 7)) { ++ and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU); ++ mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x0); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_PADA_BOOST_TUNE | ++ RADIO_2056_TX0, 0); ++ write_radio_reg(pi, ++ RADIO_2056_TX_PADG_BOOST_TUNE | ++ RADIO_2056_TX0, 0); ++ write_radio_reg(pi, ++ RADIO_2056_TX_PGAA_BOOST_TUNE | ++ RADIO_2056_TX0, 0); ++ write_radio_reg(pi, ++ RADIO_2056_TX_PGAG_BOOST_TUNE | ++ RADIO_2056_TX0, 0); ++ mod_radio_reg(pi, ++ RADIO_2056_TX_MIXA_BOOST_TUNE | ++ RADIO_2056_TX0, 0xf0, 0); ++ write_radio_reg(pi, ++ RADIO_2056_TX_MIXG_BOOST_TUNE | ++ RADIO_2056_TX0, 0); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_PADA_BOOST_TUNE | ++ RADIO_2056_TX1, 0); ++ write_radio_reg(pi, ++ RADIO_2056_TX_PADG_BOOST_TUNE | ++ RADIO_2056_TX1, 0); ++ write_radio_reg(pi, ++ RADIO_2056_TX_PGAA_BOOST_TUNE | ++ RADIO_2056_TX1, 0); ++ write_radio_reg(pi, ++ RADIO_2056_TX_PGAG_BOOST_TUNE | ++ RADIO_2056_TX1, 0); ++ mod_radio_reg(pi, ++ RADIO_2056_TX_MIXA_BOOST_TUNE | ++ RADIO_2056_TX1, 0xf0, 0); ++ write_radio_reg(pi, ++ RADIO_2056_TX_MIXG_BOOST_TUNE | ++ RADIO_2056_TX1, 0); ++ ++ pi->radio_is_on = false; ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 8)) { ++ and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU); ++ pi->radio_is_on = false; ++ } ++ ++ } ++} ++ ++static bool ++wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f, ++ const struct chan_info_nphy_radio2057 **t0, ++ const struct chan_info_nphy_radio205x **t1, ++ const struct chan_info_nphy_radio2057_rev5 **t2, ++ const struct chan_info_nphy_2055 **t3) ++{ ++ uint i; ++ const struct chan_info_nphy_radio2057 *chan_info_tbl_p_0 = NULL; ++ const struct chan_info_nphy_radio205x *chan_info_tbl_p_1 = NULL; ++ const struct chan_info_nphy_radio2057_rev5 *chan_info_tbl_p_2 = NULL; ++ u32 tbl_len = 0; ++ ++ int freq = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7)) { ++ ++ chan_info_tbl_p_0 = chan_info_nphyrev7_2057_rev4; ++ tbl_len = ARRAY_SIZE(chan_info_nphyrev7_2057_rev4); ++ ++ } else if (NREV_IS(pi->pubpi.phy_rev, 8) ++ || NREV_IS(pi->pubpi.phy_rev, 9)) { ++ switch (pi->pubpi.radiorev) { ++ ++ case 5: ++ ++ if (pi->pubpi.radiover == 0x0) { ++ ++ chan_info_tbl_p_2 = ++ chan_info_nphyrev8_2057_rev5; ++ tbl_len = ARRAY_SIZE( ++ chan_info_nphyrev8_2057_rev5); ++ ++ } else if (pi->pubpi.radiover == 0x1) { ++ ++ chan_info_tbl_p_2 = ++ chan_info_nphyrev9_2057_rev5v1; ++ tbl_len = ARRAY_SIZE( ++ chan_info_nphyrev9_2057_rev5v1); ++ ++ } ++ break; ++ ++ case 7: ++ chan_info_tbl_p_0 = ++ chan_info_nphyrev8_2057_rev7; ++ tbl_len = ARRAY_SIZE( ++ chan_info_nphyrev8_2057_rev7); ++ break; ++ ++ case 8: ++ chan_info_tbl_p_0 = ++ chan_info_nphyrev8_2057_rev8; ++ tbl_len = ARRAY_SIZE( ++ chan_info_nphyrev8_2057_rev8); ++ break; ++ ++ default: ++ break; ++ } ++ } else if (NREV_IS(pi->pubpi.phy_rev, 16)) { ++ ++ chan_info_tbl_p_0 = chan_info_nphyrev8_2057_rev8; ++ tbl_len = ARRAY_SIZE(chan_info_nphyrev8_2057_rev8); ++ } else { ++ goto fail; ++ } ++ ++ for (i = 0; i < tbl_len; i++) { ++ if (pi->pubpi.radiorev == 5) { ++ ++ if (chan_info_tbl_p_2[i].chan == channel) ++ break; ++ } else { ++ ++ if (chan_info_tbl_p_0[i].chan == channel) ++ break; ++ } ++ } ++ ++ if (i >= tbl_len) ++ goto fail; ++ ++ if (pi->pubpi.radiorev == 5) { ++ *t2 = &chan_info_tbl_p_2[i]; ++ freq = chan_info_tbl_p_2[i].freq; ++ } else { ++ *t0 = &chan_info_tbl_p_0[i]; ++ freq = chan_info_tbl_p_0[i].freq; ++ } ++ ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (NREV_IS(pi->pubpi.phy_rev, 3)) { ++ chan_info_tbl_p_1 = chan_info_nphyrev3_2056; ++ tbl_len = ARRAY_SIZE(chan_info_nphyrev3_2056); ++ } else if (NREV_IS(pi->pubpi.phy_rev, 4)) { ++ chan_info_tbl_p_1 = chan_info_nphyrev4_2056_A1; ++ tbl_len = ARRAY_SIZE(chan_info_nphyrev4_2056_A1); ++ } else if (NREV_IS(pi->pubpi.phy_rev, 5) ++ || NREV_IS(pi->pubpi.phy_rev, 6)) { ++ switch (pi->pubpi.radiorev) { ++ case 5: ++ chan_info_tbl_p_1 = chan_info_nphyrev5_2056v5; ++ tbl_len = ARRAY_SIZE(chan_info_nphyrev5_2056v5); ++ break; ++ case 6: ++ chan_info_tbl_p_1 = chan_info_nphyrev6_2056v6; ++ tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v6); ++ break; ++ case 7: ++ case 9: ++ chan_info_tbl_p_1 = chan_info_nphyrev5n6_2056v7; ++ tbl_len = ++ ARRAY_SIZE(chan_info_nphyrev5n6_2056v7); ++ break; ++ case 8: ++ chan_info_tbl_p_1 = chan_info_nphyrev6_2056v8; ++ tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v8); ++ break; ++ case 11: ++ chan_info_tbl_p_1 = chan_info_nphyrev6_2056v11; ++ tbl_len = ARRAY_SIZE( ++ chan_info_nphyrev6_2056v11); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ for (i = 0; i < tbl_len; i++) { ++ if (chan_info_tbl_p_1[i].chan == channel) ++ break; ++ } ++ ++ if (i >= tbl_len) ++ goto fail; ++ ++ *t1 = &chan_info_tbl_p_1[i]; ++ freq = chan_info_tbl_p_1[i].freq; ++ ++ } else { ++ for (i = 0; i < ARRAY_SIZE(chan_info_nphy_2055); i++) ++ if (chan_info_nphy_2055[i].chan == channel) ++ break; ++ ++ if (i >= ARRAY_SIZE(chan_info_nphy_2055)) ++ goto fail; ++ ++ *t3 = &chan_info_nphy_2055[i]; ++ freq = chan_info_nphy_2055[i].freq; ++ } ++ ++ *f = freq; ++ return true; ++ ++fail: ++ *f = WL_CHAN_FREQ_RANGE_2G; ++ return false; ++} ++ ++u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint channel) ++{ ++ int freq; ++ const struct chan_info_nphy_radio2057 *t0 = NULL; ++ const struct chan_info_nphy_radio205x *t1 = NULL; ++ const struct chan_info_nphy_radio2057_rev5 *t2 = NULL; ++ const struct chan_info_nphy_2055 *t3 = NULL; ++ ++ if (channel == 0) ++ channel = CHSPEC_CHANNEL(pi->radio_chanspec); ++ ++ wlc_phy_chan2freq_nphy(pi, channel, &freq, &t0, &t1, &t2, &t3); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ return WL_CHAN_FREQ_RANGE_2G; ++ ++ if ((freq >= BASE_LOW_5G_CHAN) && (freq < BASE_MID_5G_CHAN)) ++ return WL_CHAN_FREQ_RANGE_5GL; ++ else if ((freq >= BASE_MID_5G_CHAN) && (freq < BASE_HIGH_5G_CHAN)) ++ return WL_CHAN_FREQ_RANGE_5GM; ++ else ++ return WL_CHAN_FREQ_RANGE_5GH; ++} ++ ++static void ++wlc_phy_chanspec_radio2055_setup(struct brcms_phy *pi, ++ const struct chan_info_nphy_2055 *ci) ++{ ++ ++ write_radio_reg(pi, RADIO_2055_PLL_REF, ci->RF_pll_ref); ++ write_radio_reg(pi, RADIO_2055_RF_PLL_MOD0, ci->RF_rf_pll_mod0); ++ write_radio_reg(pi, RADIO_2055_RF_PLL_MOD1, ci->RF_rf_pll_mod1); ++ write_radio_reg(pi, RADIO_2055_VCO_CAP_TAIL, ci->RF_vco_cap_tail); ++ ++ BRCMS_PHY_WAR_PR51571(pi); ++ ++ write_radio_reg(pi, RADIO_2055_VCO_CAL1, ci->RF_vco_cal1); ++ write_radio_reg(pi, RADIO_2055_VCO_CAL2, ci->RF_vco_cal2); ++ write_radio_reg(pi, RADIO_2055_PLL_LF_C1, ci->RF_pll_lf_c1); ++ write_radio_reg(pi, RADIO_2055_PLL_LF_R1, ci->RF_pll_lf_r1); ++ ++ BRCMS_PHY_WAR_PR51571(pi); ++ ++ write_radio_reg(pi, RADIO_2055_PLL_LF_C2, ci->RF_pll_lf_c2); ++ write_radio_reg(pi, RADIO_2055_LGBUF_CEN_BUF, ci->RF_lgbuf_cen_buf); ++ write_radio_reg(pi, RADIO_2055_LGEN_TUNE1, ci->RF_lgen_tune1); ++ write_radio_reg(pi, RADIO_2055_LGEN_TUNE2, ci->RF_lgen_tune2); ++ ++ BRCMS_PHY_WAR_PR51571(pi); ++ ++ write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_A_TUNE, ++ ci->RF_core1_lgbuf_a_tune); ++ write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_G_TUNE, ++ ci->RF_core1_lgbuf_g_tune); ++ write_radio_reg(pi, RADIO_2055_CORE1_RXRF_REG1, ci->RF_core1_rxrf_reg1); ++ write_radio_reg(pi, RADIO_2055_CORE1_TX_PGA_PAD_TN, ++ ci->RF_core1_tx_pga_pad_tn); ++ ++ BRCMS_PHY_WAR_PR51571(pi); ++ ++ write_radio_reg(pi, RADIO_2055_CORE1_TX_MX_BGTRIM, ++ ci->RF_core1_tx_mx_bgtrim); ++ write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_A_TUNE, ++ ci->RF_core2_lgbuf_a_tune); ++ write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_G_TUNE, ++ ci->RF_core2_lgbuf_g_tune); ++ write_radio_reg(pi, RADIO_2055_CORE2_RXRF_REG1, ci->RF_core2_rxrf_reg1); ++ ++ BRCMS_PHY_WAR_PR51571(pi); ++ ++ write_radio_reg(pi, RADIO_2055_CORE2_TX_PGA_PAD_TN, ++ ci->RF_core2_tx_pga_pad_tn); ++ write_radio_reg(pi, RADIO_2055_CORE2_TX_MX_BGTRIM, ++ ci->RF_core2_tx_mx_bgtrim); ++ ++ udelay(50); ++ ++ write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x05); ++ write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x45); ++ ++ BRCMS_PHY_WAR_PR51571(pi); ++ ++ write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x65); ++ ++ udelay(300); ++} ++ ++static void ++wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi, ++ const struct chan_info_nphy_radio205x *ci) ++{ ++ const struct radio_regs *regs_SYN_2056_ptr = NULL; ++ ++ write_radio_reg(pi, ++ RADIO_2056_SYN_PLL_VCOCAL1 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_vcocal1); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL2 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_vcocal2); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_REFDIV | RADIO_2056_SYN, ++ ci->RF_SYN_pll_refdiv); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD2 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_mmd2); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD1 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_mmd1); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_loopfilter1); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_loopfilter2); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER3 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_loopfilter3); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_loopfilter4); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER5 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_loopfilter5); ++ write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR27 | RADIO_2056_SYN, ++ ci->RF_SYN_reserved_addr27); ++ write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR28 | RADIO_2056_SYN, ++ ci->RF_SYN_reserved_addr28); ++ write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR29 | RADIO_2056_SYN, ++ ci->RF_SYN_reserved_addr29); ++ write_radio_reg(pi, RADIO_2056_SYN_LOGEN_VCOBUF1 | RADIO_2056_SYN, ++ ci->RF_SYN_logen_VCOBUF1); ++ write_radio_reg(pi, RADIO_2056_SYN_LOGEN_MIXER2 | RADIO_2056_SYN, ++ ci->RF_SYN_logen_MIXER2); ++ write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF3 | RADIO_2056_SYN, ++ ci->RF_SYN_logen_BUF3); ++ write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF4 | RADIO_2056_SYN, ++ ci->RF_SYN_logen_BUF4); ++ ++ write_radio_reg(pi, ++ RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX0, ++ ci->RF_RX0_lnaa_tune); ++ write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX0, ++ ci->RF_RX0_lnag_tune); ++ write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX0, ++ ci->RF_TX0_intpaa_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX0, ++ ci->RF_TX0_intpag_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX0, ++ ci->RF_TX0_pada_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX0, ++ ci->RF_TX0_padg_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX0, ++ ci->RF_TX0_pgaa_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX0, ++ ci->RF_TX0_pgag_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX0, ++ ci->RF_TX0_mixa_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX0, ++ ci->RF_TX0_mixg_boost_tune); ++ ++ write_radio_reg(pi, ++ RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX1, ++ ci->RF_RX1_lnaa_tune); ++ write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX1, ++ ci->RF_RX1_lnag_tune); ++ write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX1, ++ ci->RF_TX1_intpaa_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX1, ++ ci->RF_TX1_intpag_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX1, ++ ci->RF_TX1_pada_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX1, ++ ci->RF_TX1_padg_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX1, ++ ci->RF_TX1_pgaa_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX1, ++ ci->RF_TX1_pgag_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX1, ++ ci->RF_TX1_mixa_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX1, ++ ci->RF_TX1_mixg_boost_tune); ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 3)) ++ regs_SYN_2056_ptr = regs_SYN_2056; ++ else if (NREV_IS(pi->pubpi.phy_rev, 4)) ++ regs_SYN_2056_ptr = regs_SYN_2056_A1; ++ else { ++ switch (pi->pubpi.radiorev) { ++ case 5: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev5; ++ break; ++ case 6: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev6; ++ break; ++ case 7: ++ case 9: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev7; ++ break; ++ case 8: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev8; ++ break; ++ case 11: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev11; ++ break; ++ } ++ } ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | ++ RADIO_2056_SYN, ++ (u16) regs_SYN_2056_ptr[0x49 - 2].init_g); ++ else ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | ++ RADIO_2056_SYN, ++ (u16) regs_SYN_2056_ptr[0x49 - 2].init_a); ++ ++ if (pi->sh->boardflags2 & BFL2_GPLL_WAR) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 | ++ RADIO_2056_SYN, 0x1f); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | ++ RADIO_2056_SYN, 0x1f); ++ ++ write_radio_reg(pi, ++ RADIO_2056_SYN_PLL_LOOPFILTER4 | ++ RADIO_2056_SYN, 0xb); ++ write_radio_reg(pi, ++ RADIO_2056_SYN_PLL_CP2 | ++ RADIO_2056_SYN, 0x14); ++ } ++ } ++ ++ if ((pi->sh->boardflags2 & BFL2_GPLL_WAR2) && ++ (CHSPEC_IS2G(pi->radio_chanspec))) { ++ write_radio_reg(pi, ++ RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN, ++ 0x1f); ++ write_radio_reg(pi, ++ RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN, ++ 0x1f); ++ write_radio_reg(pi, ++ RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN, ++ 0xb); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | RADIO_2056_SYN, ++ 0x20); ++ } ++ ++ if (pi->sh->boardflags2 & BFL2_APLL_WAR) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 | ++ RADIO_2056_SYN, 0x1f); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | ++ RADIO_2056_SYN, 0x1f); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 | ++ RADIO_2056_SYN, 0x5); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | ++ RADIO_2056_SYN, 0xc); ++ } ++ } ++ ++ if (PHY_IPA(pi) && CHSPEC_IS2G(pi->radio_chanspec)) { ++ u16 pag_boost_tune; ++ u16 padg_boost_tune; ++ u16 pgag_boost_tune; ++ u16 mixg_boost_tune; ++ u16 bias, cascbias; ++ uint core; ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 5)) { ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ PADG_IDAC, 0xcc); ++ ++ bias = 0x25; ++ cascbias = 0x20; ++ ++ if ((pi->sh->chip == ++ BCM43224_CHIP_ID) ++ || (pi->sh->chip == ++ BCM43225_CHIP_ID)) { ++ if (pi->sh->chippkg == ++ BCM43224_FAB_SMIC) { ++ bias = 0x2a; ++ cascbias = 0x38; ++ } ++ } ++ ++ pag_boost_tune = 0x4; ++ pgag_boost_tune = 0x03; ++ padg_boost_tune = 0x77; ++ mixg_boost_tune = 0x65; ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_IMAIN_STAT, bias); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_IAUX_STAT, bias); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_CASCBIAS, cascbias); ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_BOOST_TUNE, ++ pag_boost_tune); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ PGAG_BOOST_TUNE, ++ pgag_boost_tune); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ PADG_BOOST_TUNE, ++ padg_boost_tune); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ MIXG_BOOST_TUNE, ++ mixg_boost_tune); ++ } else { ++ ++ bias = (pi->bw == WL_CHANSPEC_BW_40) ? ++ 0x40 : 0x20; ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_IMAIN_STAT, bias); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_IAUX_STAT, bias); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_CASCBIAS, 0x30); ++ } ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, PA_SPARE1, ++ 0xee); ++ } ++ } ++ ++ if (PHY_IPA(pi) && NREV_IS(pi->pubpi.phy_rev, 6) ++ && CHSPEC_IS5G(pi->radio_chanspec)) { ++ u16 paa_boost_tune; ++ u16 pada_boost_tune; ++ u16 pgaa_boost_tune; ++ u16 mixa_boost_tune; ++ u16 freq, pabias, cascbias; ++ uint core; ++ ++ freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec)); ++ ++ if (freq < 5150) { ++ ++ paa_boost_tune = 0xa; ++ pada_boost_tune = 0x77; ++ pgaa_boost_tune = 0xf; ++ mixa_boost_tune = 0xf; ++ } else if (freq < 5340) { ++ ++ paa_boost_tune = 0x8; ++ pada_boost_tune = 0x77; ++ pgaa_boost_tune = 0xfb; ++ mixa_boost_tune = 0xf; ++ } else if (freq < 5650) { ++ ++ paa_boost_tune = 0x0; ++ pada_boost_tune = 0x77; ++ pgaa_boost_tune = 0xb; ++ mixa_boost_tune = 0xf; ++ } else { ++ ++ paa_boost_tune = 0x0; ++ pada_boost_tune = 0x77; ++ if (freq != 5825) ++ pgaa_boost_tune = -(int)(freq - 18) / 36 + 168; ++ else ++ pgaa_boost_tune = 6; ++ ++ mixa_boost_tune = 0xf; ++ } ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAA_BOOST_TUNE, paa_boost_tune); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ PADA_BOOST_TUNE, pada_boost_tune); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ PGAA_BOOST_TUNE, pgaa_boost_tune); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ MIXA_BOOST_TUNE, mixa_boost_tune); ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ TXSPARE1, 0x30); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ PA_SPARE2, 0xee); ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ PADA_CASCBIAS, 0x3); ++ ++ cascbias = 0x30; ++ ++ if ((pi->sh->chip == BCM43224_CHIP_ID) || ++ (pi->sh->chip == BCM43225_CHIP_ID)) { ++ if (pi->sh->chippkg == BCM43224_FAB_SMIC) ++ cascbias = 0x35; ++ } ++ ++ pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias; ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAA_IAUX_STAT, pabias); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAA_IMAIN_STAT, pabias); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAA_CASCBIAS, cascbias); ++ } ++ } ++ ++ udelay(50); ++ ++ wlc_phy_radio205x_vcocal_nphy(pi); ++} ++ ++void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi) ++{ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x0); ++ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04, 0x0); ++ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04, ++ (1 << 2)); ++ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x01); ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL12, 0x0); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x18); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x39); ++ } ++ ++ udelay(300); ++} ++ ++static void ++wlc_phy_chanspec_radio2057_setup( ++ struct brcms_phy *pi, ++ const struct chan_info_nphy_radio2057 *ci, ++ const struct chan_info_nphy_radio2057_rev5 * ++ ci2) ++{ ++ int coreNum; ++ u16 txmix2g_tune_boost_pu = 0; ++ u16 pad2g_tune_pus = 0; ++ ++ if (pi->pubpi.radiorev == 5) { ++ ++ write_radio_reg(pi, ++ RADIO_2057_VCOCAL_COUNTVAL0, ++ ci2->RF_vcocal_countval0); ++ write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1, ++ ci2->RF_vcocal_countval1); ++ write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE, ++ ci2->RF_rfpll_refmaster_sparextalsize); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, ++ ci2->RF_rfpll_loopfilter_r1); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, ++ ci2->RF_rfpll_loopfilter_c2); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, ++ ci2->RF_rfpll_loopfilter_c1); ++ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, ++ ci2->RF_cp_kpd_idac); ++ write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci2->RF_rfpll_mmd0); ++ write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci2->RF_rfpll_mmd1); ++ write_radio_reg(pi, ++ RADIO_2057_VCOBUF_TUNE, ci2->RF_vcobuf_tune); ++ write_radio_reg(pi, ++ RADIO_2057_LOGEN_MX2G_TUNE, ++ ci2->RF_logen_mx2g_tune); ++ write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE, ++ ci2->RF_logen_indbuf2g_tune); ++ ++ write_radio_reg(pi, ++ RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0, ++ ci2->RF_txmix2g_tune_boost_pu_core0); ++ write_radio_reg(pi, ++ RADIO_2057_PAD2G_TUNE_PUS_CORE0, ++ ci2->RF_pad2g_tune_pus_core0); ++ write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0, ++ ci2->RF_lna2g_tune_core0); ++ ++ write_radio_reg(pi, ++ RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1, ++ ci2->RF_txmix2g_tune_boost_pu_core1); ++ write_radio_reg(pi, ++ RADIO_2057_PAD2G_TUNE_PUS_CORE1, ++ ci2->RF_pad2g_tune_pus_core1); ++ write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1, ++ ci2->RF_lna2g_tune_core1); ++ ++ } else { ++ ++ write_radio_reg(pi, ++ RADIO_2057_VCOCAL_COUNTVAL0, ++ ci->RF_vcocal_countval0); ++ write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1, ++ ci->RF_vcocal_countval1); ++ write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE, ++ ci->RF_rfpll_refmaster_sparextalsize); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, ++ ci->RF_rfpll_loopfilter_r1); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, ++ ci->RF_rfpll_loopfilter_c2); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, ++ ci->RF_rfpll_loopfilter_c1); ++ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, ci->RF_cp_kpd_idac); ++ write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci->RF_rfpll_mmd0); ++ write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci->RF_rfpll_mmd1); ++ write_radio_reg(pi, RADIO_2057_VCOBUF_TUNE, ci->RF_vcobuf_tune); ++ write_radio_reg(pi, ++ RADIO_2057_LOGEN_MX2G_TUNE, ++ ci->RF_logen_mx2g_tune); ++ write_radio_reg(pi, RADIO_2057_LOGEN_MX5G_TUNE, ++ ci->RF_logen_mx5g_tune); ++ write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE, ++ ci->RF_logen_indbuf2g_tune); ++ write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF5G_TUNE, ++ ci->RF_logen_indbuf5g_tune); ++ ++ write_radio_reg(pi, ++ RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0, ++ ci->RF_txmix2g_tune_boost_pu_core0); ++ write_radio_reg(pi, ++ RADIO_2057_PAD2G_TUNE_PUS_CORE0, ++ ci->RF_pad2g_tune_pus_core0); ++ write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE0, ++ ci->RF_pga_boost_tune_core0); ++ write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0, ++ ci->RF_txmix5g_boost_tune_core0); ++ write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0, ++ ci->RF_pad5g_tune_misc_pus_core0); ++ write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0, ++ ci->RF_lna2g_tune_core0); ++ write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE0, ++ ci->RF_lna5g_tune_core0); ++ ++ write_radio_reg(pi, ++ RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1, ++ ci->RF_txmix2g_tune_boost_pu_core1); ++ write_radio_reg(pi, ++ RADIO_2057_PAD2G_TUNE_PUS_CORE1, ++ ci->RF_pad2g_tune_pus_core1); ++ write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE1, ++ ci->RF_pga_boost_tune_core1); ++ write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1, ++ ci->RF_txmix5g_boost_tune_core1); ++ write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1, ++ ci->RF_pad5g_tune_misc_pus_core1); ++ write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1, ++ ci->RF_lna2g_tune_core1); ++ write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE1, ++ ci->RF_lna5g_tune_core1); ++ } ++ ++ if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) { ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, ++ 0x3f); ++ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, ++ 0x8); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, ++ 0x8); ++ } else { ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, ++ 0x1f); ++ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, ++ 0x8); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, ++ 0x8); ++ } ++ } else if ((pi->pubpi.radiorev == 5) || (pi->pubpi.radiorev == 7) || ++ (pi->pubpi.radiorev == 8)) { ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, ++ 0x1b); ++ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x30); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, ++ 0xa); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, ++ 0xa); ++ } else { ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, ++ 0x1f); ++ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, ++ 0x8); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, ++ 0x8); ++ } ++ ++ } ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (PHY_IPA(pi)) { ++ if (pi->pubpi.radiorev == 3) ++ txmix2g_tune_boost_pu = 0x6b; ++ ++ if (pi->pubpi.radiorev == 5) ++ pad2g_tune_pus = 0x73; ++ ++ } else { ++ if (pi->pubpi.radiorev != 5) { ++ pad2g_tune_pus = 0x3; ++ ++ txmix2g_tune_boost_pu = 0x61; ++ } ++ } ++ ++ for (coreNum = 0; coreNum <= 1; coreNum++) { ++ ++ if (txmix2g_tune_boost_pu != 0) ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, ++ TXMIX2G_TUNE_BOOST_PU, ++ txmix2g_tune_boost_pu); ++ ++ if (pad2g_tune_pus != 0) ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, ++ PAD2G_TUNE_PUS, ++ pad2g_tune_pus); ++ } ++ } ++ ++ udelay(50); ++ ++ wlc_phy_radio205x_vcocal_nphy(pi); ++} ++ ++static void ++wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, ++ const struct nphy_sfo_cfg *ci) ++{ ++ u16 val; ++ ++ val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; ++ if (CHSPEC_IS5G(chanspec) && !val) { ++ ++ val = R_REG(&pi->regs->psm_phy_hdr_param); ++ W_REG(&pi->regs->psm_phy_hdr_param, ++ (val | MAC_PHY_FORCE_CLK)); ++ ++ or_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG), ++ (BBCFG_RESETCCA | BBCFG_RESETRX)); ++ ++ W_REG(&pi->regs->psm_phy_hdr_param, val); ++ ++ or_phy_reg(pi, 0x09, NPHY_BandControl_currentBand); ++ } else if (!CHSPEC_IS5G(chanspec) && val) { ++ ++ and_phy_reg(pi, 0x09, ~NPHY_BandControl_currentBand); ++ ++ val = R_REG(&pi->regs->psm_phy_hdr_param); ++ W_REG(&pi->regs->psm_phy_hdr_param, ++ (val | MAC_PHY_FORCE_CLK)); ++ ++ and_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG), ++ (u16) (~(BBCFG_RESETCCA | BBCFG_RESETRX))); ++ ++ W_REG(&pi->regs->psm_phy_hdr_param, val); ++ } ++ ++ write_phy_reg(pi, 0x1ce, ci->PHY_BW1a); ++ write_phy_reg(pi, 0x1cf, ci->PHY_BW2); ++ write_phy_reg(pi, 0x1d0, ci->PHY_BW3); ++ ++ write_phy_reg(pi, 0x1d1, ci->PHY_BW4); ++ write_phy_reg(pi, 0x1d2, ci->PHY_BW5); ++ write_phy_reg(pi, 0x1d3, ci->PHY_BW6); ++ ++ if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) { ++ wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en, 0); ++ ++ or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, 0x800); ++ } else { ++ wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en, ++ NPHY_ClassifierCtrl_ofdm_en); ++ ++ if (CHSPEC_IS2G(chanspec)) ++ and_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, ~0x840); ++ } ++ ++ if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) ++ wlc_phy_txpwr_fixpower_nphy(pi); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) ++ wlc_phy_adjust_lnagaintbl_nphy(pi); ++ ++ wlc_phy_txlpfbw_nphy(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) ++ && (pi->phy_spuravoid != SPURAVOID_DISABLE)) { ++ u8 spuravoid = 0; ++ ++ val = CHSPEC_CHANNEL(chanspec); ++ if (!CHSPEC_IS40(pi->radio_chanspec)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if ((val == 13) || (val == 14) || (val == 153)) ++ spuravoid = 1; ++ } else if (((val >= 5) && (val <= 8)) || (val == 13) ++ || (val == 14)) { ++ spuravoid = 1; ++ } ++ } else if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (val == 54) ++ spuravoid = 1; ++ } else { ++ if (pi->nphy_aband_spurwar_en && ++ ((val == 38) || (val == 102) ++ || (val == 118))) ++ spuravoid = 1; ++ } ++ ++ if (pi->phy_spuravoid == SPURAVOID_FORCEON) ++ spuravoid = 1; ++ ++ wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false); ++ si_pmu_spuravoid(pi->sh->sih, spuravoid); ++ wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true); ++ ++ if ((pi->sh->chip == BCM43224_CHIP_ID) || ++ (pi->sh->chip == BCM43225_CHIP_ID)) { ++ ++ if (spuravoid == 1) { ++ ++ W_REG(&pi->regs->tsf_clk_frac_l, ++ 0x5341); ++ W_REG(&pi->regs->tsf_clk_frac_h, ++ 0x8); ++ } else { ++ ++ W_REG(&pi->regs->tsf_clk_frac_l, ++ 0x8889); ++ W_REG(&pi->regs->tsf_clk_frac_h, ++ 0x8); ++ } ++ } ++ ++ wlapi_bmac_core_phypll_reset(pi->sh->physhim); ++ ++ mod_phy_reg(pi, 0x01, (0x1 << 15), ++ ((spuravoid > 0) ? (0x1 << 15) : 0)); ++ ++ wlc_phy_resetcca_nphy(pi); ++ ++ pi->phy_isspuravoid = (spuravoid > 0); ++ } ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 7)) ++ write_phy_reg(pi, 0x17e, 0x3830); ++ ++ wlc_phy_spurwar_nphy(pi); ++} ++ ++void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, u16 chanspec) ++{ ++ int freq; ++ const struct chan_info_nphy_radio2057 *t0 = NULL; ++ const struct chan_info_nphy_radio205x *t1 = NULL; ++ const struct chan_info_nphy_radio2057_rev5 *t2 = NULL; ++ const struct chan_info_nphy_2055 *t3 = NULL; ++ ++ if (!wlc_phy_chan2freq_nphy ++ (pi, CHSPEC_CHANNEL(chanspec), &freq, &t0, &t1, &t2, &t3)) ++ return; ++ ++ wlc_phy_chanspec_radio_set((struct brcms_phy_pub *) pi, chanspec); ++ ++ if (CHSPEC_BW(chanspec) != pi->bw) ++ wlapi_bmac_bw_set(pi->sh->physhim, CHSPEC_BW(chanspec)); ++ ++ if (CHSPEC_IS40(chanspec)) { ++ if (CHSPEC_SB_UPPER(chanspec)) { ++ or_phy_reg(pi, 0xa0, BPHY_BAND_SEL_UP20); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ or_phy_reg(pi, 0x310, PRIM_SEL_UP20); ++ } else { ++ and_phy_reg(pi, 0xa0, ~BPHY_BAND_SEL_UP20); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ and_phy_reg(pi, 0x310, ++ (~PRIM_SEL_UP20 & 0xffff)); ++ } ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ if ((pi->pubpi.radiorev <= 4) ++ || (pi->pubpi.radiorev == 6)) { ++ mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE0, ++ 0x2, ++ (CHSPEC_IS5G(chanspec) ? (1 << 1) ++ : 0)); ++ mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE1, ++ 0x2, ++ (CHSPEC_IS5G(chanspec) ? (1 << 1) ++ : 0)); ++ } ++ ++ wlc_phy_chanspec_radio2057_setup(pi, t0, t2); ++ wlc_phy_chanspec_nphy_setup(pi, chanspec, ++ (pi->pubpi.radiorev == 5) ? ++ (const struct nphy_sfo_cfg *)&(t2->PHY_BW1a) : ++ (const struct nphy_sfo_cfg *)&(t0->PHY_BW1a)); ++ ++ } else { ++ ++ mod_radio_reg(pi, ++ RADIO_2056_SYN_COM_CTRL | RADIO_2056_SYN, ++ 0x4, ++ (CHSPEC_IS5G(chanspec) ? (0x1 << 2) : 0)); ++ wlc_phy_chanspec_radio2056_setup(pi, t1); ++ ++ wlc_phy_chanspec_nphy_setup(pi, chanspec, ++ (const struct nphy_sfo_cfg *) &(t1->PHY_BW1a)); ++ } ++ ++ } else { ++ ++ mod_radio_reg(pi, RADIO_2055_MASTER_CNTRL1, 0x70, ++ (CHSPEC_IS5G(chanspec) ? (0x02 << 4) ++ : (0x05 << 4))); ++ ++ wlc_phy_chanspec_radio2055_setup(pi, t3); ++ wlc_phy_chanspec_nphy_setup(pi, chanspec, ++ (const struct nphy_sfo_cfg *) ++ &(t3->PHY_BW1a)); ++ } ++ ++} ++ ++void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ u16 mask = 0xfc00; ++ u32 mc = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ return; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ u16 v0 = 0x211, v1 = 0x222, v2 = 0x144, v3 = 0x188; ++ ++ if (lut_init == false) ++ return; ++ ++ if (pi->srom_fem2g.antswctrllut == 0) { ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 1, 0x02, 16, &v0); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 1, 0x03, 16, &v1); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 1, 0x08, 16, &v2); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 1, 0x0C, 16, &v3); ++ } ++ ++ if (pi->srom_fem5g.antswctrllut == 0) { ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 1, 0x12, 16, &v0); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 1, 0x13, 16, &v1); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 1, 0x18, 16, &v2); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 1, 0x1C, 16, &v3); ++ } ++ } else { ++ ++ write_phy_reg(pi, 0xc8, 0x0); ++ write_phy_reg(pi, 0xc9, 0x0); ++ ++ ai_gpiocontrol(pi->sh->sih, mask, mask, GPIO_DRV_PRIORITY); ++ ++ mc = R_REG(&pi->regs->maccontrol); ++ mc &= ~MCTL_GPOUT_SEL_MASK; ++ W_REG(&pi->regs->maccontrol, mc); ++ ++ OR_REG(&pi->regs->psm_gpio_oe, mask); ++ ++ AND_REG(&pi->regs->psm_gpio_out, ~mask); ++ ++ if (lut_init) { ++ write_phy_reg(pi, 0xf8, 0x02d8); ++ write_phy_reg(pi, 0xf9, 0x0301); ++ write_phy_reg(pi, 0xfa, 0x02d8); ++ write_phy_reg(pi, 0xfb, 0x0301); ++ } ++ } ++} ++ ++u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val) ++{ ++ u16 curr_ctl, new_ctl; ++ bool suspended = false; ++ ++ if (D11REV_IS(pi->sh->corerev, 16)) { ++ suspended = ++ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ? ++ false : true; ++ if (!suspended) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ } ++ ++ curr_ctl = read_phy_reg(pi, 0xb0) & (0x7 << 0); ++ ++ new_ctl = (curr_ctl & (~mask)) | (val & mask); ++ ++ mod_phy_reg(pi, 0xb0, (0x7 << 0), new_ctl); ++ ++ if (D11REV_IS(pi->sh->corerev, 16) && !suspended) ++ wlapi_enable_mac(pi->sh->physhim); ++ ++ return new_ctl; ++} ++ ++void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd) ++{ ++ u16 trigger_mask, status_mask; ++ u16 orig_RfseqCoreActv; ++ ++ switch (cmd) { ++ case NPHY_RFSEQ_RX2TX: ++ trigger_mask = NPHY_RfseqTrigger_rx2tx; ++ status_mask = NPHY_RfseqStatus_rx2tx; ++ break; ++ case NPHY_RFSEQ_TX2RX: ++ trigger_mask = NPHY_RfseqTrigger_tx2rx; ++ status_mask = NPHY_RfseqStatus_tx2rx; ++ break; ++ case NPHY_RFSEQ_RESET2RX: ++ trigger_mask = NPHY_RfseqTrigger_reset2rx; ++ status_mask = NPHY_RfseqStatus_reset2rx; ++ break; ++ case NPHY_RFSEQ_UPDATEGAINH: ++ trigger_mask = NPHY_RfseqTrigger_updategainh; ++ status_mask = NPHY_RfseqStatus_updategainh; ++ break; ++ case NPHY_RFSEQ_UPDATEGAINL: ++ trigger_mask = NPHY_RfseqTrigger_updategainl; ++ status_mask = NPHY_RfseqStatus_updategainl; ++ break; ++ case NPHY_RFSEQ_UPDATEGAINU: ++ trigger_mask = NPHY_RfseqTrigger_updategainu; ++ status_mask = NPHY_RfseqStatus_updategainu; ++ break; ++ default: ++ return; ++ } ++ ++ orig_RfseqCoreActv = read_phy_reg(pi, 0xa1); ++ or_phy_reg(pi, 0xa1, ++ (NPHY_RfseqMode_CoreActv_override | ++ NPHY_RfseqMode_Trigger_override)); ++ or_phy_reg(pi, 0xa3, trigger_mask); ++ SPINWAIT((read_phy_reg(pi, 0xa4) & status_mask), 200000); ++ write_phy_reg(pi, 0xa1, orig_RfseqCoreActv); ++ WARN(read_phy_reg(pi, 0xa4) & status_mask, "HW error in rf"); ++} ++ ++static void ++wlc_phy_rfctrl_override_1tomany_nphy(struct brcms_phy *pi, u16 cmd, u16 value, ++ u8 core_mask, u8 off) ++{ ++ u16 rfmxgain = 0, lpfgain = 0; ++ u16 tgain = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ switch (cmd) { ++ case NPHY_REV7_RfctrlOverride_cmd_rxrf_pu: ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 5), ++ value, core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 4), value, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 3), value, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ break; ++ case NPHY_REV7_RfctrlOverride_cmd_rx_pu: ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 2), ++ value, core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 1), value, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 0), value, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 1), value, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 11), 0, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ break; ++ case NPHY_REV7_RfctrlOverride_cmd_tx_pu: ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 2), ++ value, core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 1), value, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 0), value, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 2), value, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 11), 1, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ break; ++ case NPHY_REV7_RfctrlOverride_cmd_rxgain: ++ rfmxgain = value & 0x000ff; ++ lpfgain = value & 0x0ff00; ++ lpfgain = lpfgain >> 8; ++ ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 11), ++ rfmxgain, core_mask, ++ off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x3 << 13), ++ lpfgain, core_mask, ++ off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ break; ++ case NPHY_REV7_RfctrlOverride_cmd_txgain: ++ tgain = value & 0x7fff; ++ lpfgain = value & 0x8000; ++ lpfgain = lpfgain >> 14; ++ ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 12), ++ tgain, core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 13), ++ lpfgain, core_mask, ++ off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ break; ++ } ++ } ++} ++ ++static void ++wlc_phy_scale_offset_rssi_nphy(struct brcms_phy *pi, u16 scale, s8 offset, ++ u8 coresel, u8 rail, u8 rssi_type) ++{ ++ u16 valuetostuff; ++ ++ offset = (offset > NPHY_RSSICAL_MAXREAD) ? ++ NPHY_RSSICAL_MAXREAD : offset; ++ offset = (offset < (-NPHY_RSSICAL_MAXREAD - 1)) ? ++ -NPHY_RSSICAL_MAXREAD - 1 : offset; ++ ++ valuetostuff = ((scale & 0x3f) << 8) | (offset & 0x3f); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) ++ write_phy_reg(pi, 0x1a6, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) ++ write_phy_reg(pi, 0x1ac, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) ++ write_phy_reg(pi, 0x1b2, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) ++ write_phy_reg(pi, 0x1b8, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) ++ write_phy_reg(pi, 0x1a4, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) ++ write_phy_reg(pi, 0x1aa, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) ++ write_phy_reg(pi, 0x1b0, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) ++ write_phy_reg(pi, 0x1b6, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) ++ write_phy_reg(pi, 0x1a5, valuetostuff); ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) ++ write_phy_reg(pi, 0x1ab, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) ++ write_phy_reg(pi, 0x1b1, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) ++ write_phy_reg(pi, 0x1b7, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) ++ write_phy_reg(pi, 0x1a7, valuetostuff); ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) ++ write_phy_reg(pi, 0x1ad, valuetostuff); ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) ++ write_phy_reg(pi, 0x1b3, valuetostuff); ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) ++ write_phy_reg(pi, 0x1b9, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) ++ write_phy_reg(pi, 0x1a8, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) ++ write_phy_reg(pi, 0x1ae, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) ++ write_phy_reg(pi, 0x1b4, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) ++ write_phy_reg(pi, 0x1ba, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) ++ write_phy_reg(pi, 0x1a9, valuetostuff); ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) ++ write_phy_reg(pi, 0x1b5, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) ++ write_phy_reg(pi, 0x1af, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) ++ write_phy_reg(pi, 0x1bb, valuetostuff); ++} ++ ++static void brcms_phy_wr_tx_mux(struct brcms_phy *pi, u8 core) ++{ ++ if (PHY_IPA(pi)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ write_radio_reg(pi, ++ ((core == PHY_CORE_0) ? ++ RADIO_2057_TX0_TX_SSI_MUX : ++ RADIO_2057_TX1_TX_SSI_MUX), ++ (CHSPEC_IS5G(pi->radio_chanspec) ? ++ 0xc : 0xe)); ++ else ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MUX | ++ ((core == PHY_CORE_0) ? ++ RADIO_2056_TX0 : RADIO_2056_TX1), ++ (CHSPEC_IS5G(pi->radio_chanspec) ? ++ 0xc : 0xe)); ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ write_radio_reg(pi, ++ ((core == PHY_CORE_0) ? ++ RADIO_2057_TX0_TX_SSI_MUX : ++ RADIO_2057_TX1_TX_SSI_MUX), ++ 0x11); ++ ++ if (pi->pubpi.radioid == BCM2057_ID) ++ write_radio_reg(pi, ++ RADIO_2057_IQTEST_SEL_PU, 0x1); ++ ++ } else { ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MUX | ++ ((core == PHY_CORE_0) ? ++ RADIO_2056_TX0 : RADIO_2056_TX1), ++ 0x11); ++ } ++ } ++} ++ ++void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type) ++{ ++ u16 mask, val; ++ u16 afectrlovr_rssi_val, rfctrlcmd_rxen_val, rfctrlcmd_coresel_val, ++ startseq; ++ u16 rfctrlovr_rssi_val, rfctrlovr_rxen_val, rfctrlovr_coresel_val, ++ rfctrlovr_trigger_val; ++ u16 afectrlovr_rssi_mask, rfctrlcmd_mask, rfctrlovr_mask; ++ u16 rfctrlcmd_val, rfctrlovr_val; ++ u8 core; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (core_code == RADIO_MIMO_CORESEL_OFF) { ++ mod_phy_reg(pi, 0x8f, (0x1 << 9), 0); ++ mod_phy_reg(pi, 0xa5, (0x1 << 9), 0); ++ ++ mod_phy_reg(pi, 0xa6, (0x3 << 8), 0); ++ mod_phy_reg(pi, 0xa7, (0x3 << 8), 0); ++ ++ mod_phy_reg(pi, 0xe5, (0x1 << 5), 0); ++ mod_phy_reg(pi, 0xe6, (0x1 << 5), 0); ++ ++ mask = (0x1 << 2) | ++ (0x1 << 3) | (0x1 << 4) | (0x1 << 5); ++ mod_phy_reg(pi, 0xf9, mask, 0); ++ mod_phy_reg(pi, 0xfb, mask, 0); ++ ++ } else { ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ if (core_code == RADIO_MIMO_CORESEL_CORE1 ++ && core == PHY_CORE_1) ++ continue; ++ else if (core_code == RADIO_MIMO_CORESEL_CORE2 ++ && core == PHY_CORE_0) ++ continue; ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0x8f : 0xa5, (0x1 << 9), 1 << 9); ++ ++ if (rssi_type == NPHY_RSSI_SEL_W1 || ++ rssi_type == NPHY_RSSI_SEL_W2 || ++ rssi_type == NPHY_RSSI_SEL_NB) { ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xa6 : 0xa7, ++ (0x3 << 8), 0); ++ ++ mask = (0x1 << 2) | ++ (0x1 << 3) | ++ (0x1 << 4) | (0x1 << 5); ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xf9 : 0xfb, ++ mask, 0); ++ ++ if (rssi_type == NPHY_RSSI_SEL_W1) { ++ if (CHSPEC_IS5G( ++ pi->radio_chanspec)) { ++ mask = (0x1 << 2); ++ val = 1 << 2; ++ } else { ++ mask = (0x1 << 3); ++ val = 1 << 3; ++ } ++ } else if (rssi_type == ++ NPHY_RSSI_SEL_W2) { ++ mask = (0x1 << 4); ++ val = 1 << 4; ++ } else { ++ mask = (0x1 << 5); ++ val = 1 << 5; ++ } ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xf9 : 0xfb, ++ mask, val); ++ ++ mask = (0x1 << 5); ++ val = 1 << 5; ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0xe5 : 0xe6, mask, val); ++ } else { ++ if (rssi_type == NPHY_RSSI_SEL_TBD) { ++ mask = (0x3 << 8); ++ val = 1 << 8; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xa6 ++ : 0xa7, mask, val); ++ mask = (0x3 << 10); ++ val = 1 << 10; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xa6 ++ : 0xa7, mask, val); ++ } else if (rssi_type == ++ NPHY_RSSI_SEL_IQ) { ++ mask = (0x3 << 8); ++ val = 2 << 8; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xa6 ++ : 0xa7, mask, val); ++ mask = (0x3 << 10); ++ val = 2 << 10; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xa6 ++ : 0xa7, mask, val); ++ } else { ++ mask = (0x3 << 8); ++ val = 3 << 8; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xa6 ++ : 0xa7, mask, val); ++ mask = (0x3 << 10); ++ val = 3 << 10; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xa6 ++ : 0xa7, mask, val); ++ brcms_phy_wr_tx_mux(pi, core); ++ afectrlovr_rssi_val = 1 << 9; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x8f ++ : 0xa5, (0x1 << 9), ++ afectrlovr_rssi_val); ++ } ++ } ++ } ++ } ++ } else { ++ ++ if ((rssi_type == NPHY_RSSI_SEL_W1) || ++ (rssi_type == NPHY_RSSI_SEL_W2) || ++ (rssi_type == NPHY_RSSI_SEL_NB)) ++ val = 0x0; ++ else if (rssi_type == NPHY_RSSI_SEL_TBD) ++ val = 0x1; ++ else if (rssi_type == NPHY_RSSI_SEL_IQ) ++ val = 0x2; ++ else ++ val = 0x3; ++ ++ mask = ((0x3 << 12) | (0x3 << 14)); ++ val = (val << 12) | (val << 14); ++ mod_phy_reg(pi, 0xa6, mask, val); ++ mod_phy_reg(pi, 0xa7, mask, val); ++ ++ if ((rssi_type == NPHY_RSSI_SEL_W1) || ++ (rssi_type == NPHY_RSSI_SEL_W2) || ++ (rssi_type == NPHY_RSSI_SEL_NB)) { ++ if (rssi_type == NPHY_RSSI_SEL_W1) ++ val = 0x1; ++ if (rssi_type == NPHY_RSSI_SEL_W2) ++ val = 0x2; ++ if (rssi_type == NPHY_RSSI_SEL_NB) ++ val = 0x3; ++ ++ mask = (0x3 << 4); ++ val = (val << 4); ++ mod_phy_reg(pi, 0x7a, mask, val); ++ mod_phy_reg(pi, 0x7d, mask, val); ++ } ++ ++ if (core_code == RADIO_MIMO_CORESEL_OFF) { ++ afectrlovr_rssi_val = 0; ++ rfctrlcmd_rxen_val = 0; ++ rfctrlcmd_coresel_val = 0; ++ rfctrlovr_rssi_val = 0; ++ rfctrlovr_rxen_val = 0; ++ rfctrlovr_coresel_val = 0; ++ rfctrlovr_trigger_val = 0; ++ startseq = 0; ++ } else { ++ afectrlovr_rssi_val = 1; ++ rfctrlcmd_rxen_val = 1; ++ rfctrlcmd_coresel_val = core_code; ++ rfctrlovr_rssi_val = 1; ++ rfctrlovr_rxen_val = 1; ++ rfctrlovr_coresel_val = 1; ++ rfctrlovr_trigger_val = 1; ++ startseq = 1; ++ } ++ ++ afectrlovr_rssi_mask = ((0x1 << 12) | (0x1 << 13)); ++ afectrlovr_rssi_val = (afectrlovr_rssi_val << ++ 12) | (afectrlovr_rssi_val << 13); ++ mod_phy_reg(pi, 0xa5, afectrlovr_rssi_mask, ++ afectrlovr_rssi_val); ++ ++ if ((rssi_type == NPHY_RSSI_SEL_W1) || ++ (rssi_type == NPHY_RSSI_SEL_W2) || ++ (rssi_type == NPHY_RSSI_SEL_NB)) { ++ rfctrlcmd_mask = ((0x1 << 8) | (0x7 << 3)); ++ rfctrlcmd_val = (rfctrlcmd_rxen_val << 8) | ++ (rfctrlcmd_coresel_val << 3); ++ ++ rfctrlovr_mask = ((0x1 << 5) | ++ (0x1 << 12) | ++ (0x1 << 1) | (0x1 << 0)); ++ rfctrlovr_val = (rfctrlovr_rssi_val << ++ 5) | ++ (rfctrlovr_rxen_val << 12) | ++ (rfctrlovr_coresel_val << 1) | ++ (rfctrlovr_trigger_val << 0); ++ ++ mod_phy_reg(pi, 0x78, rfctrlcmd_mask, rfctrlcmd_val); ++ mod_phy_reg(pi, 0xec, rfctrlovr_mask, rfctrlovr_val); ++ ++ mod_phy_reg(pi, 0x78, (0x1 << 0), (startseq << 0)); ++ udelay(20); ++ ++ mod_phy_reg(pi, 0xec, (0x1 << 0), 0); ++ } ++ } ++} ++ ++int ++wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, s32 *rssi_buf, ++ u8 nsamps) ++{ ++ s16 rssi0, rssi1; ++ u16 afectrlCore1_save = 0; ++ u16 afectrlCore2_save = 0; ++ u16 afectrlOverride1_save = 0; ++ u16 afectrlOverride2_save = 0; ++ u16 rfctrlOverrideAux0_save = 0; ++ u16 rfctrlOverrideAux1_save = 0; ++ u16 rfctrlMiscReg1_save = 0; ++ u16 rfctrlMiscReg2_save = 0; ++ u16 rfctrlcmd_save = 0; ++ u16 rfctrloverride_save = 0; ++ u16 rfctrlrssiothers1_save = 0; ++ u16 rfctrlrssiothers2_save = 0; ++ s8 tmp_buf[4]; ++ u8 ctr = 0, samp = 0; ++ s32 rssi_out_val; ++ u16 gpiosel_orig; ++ ++ afectrlCore1_save = read_phy_reg(pi, 0xa6); ++ afectrlCore2_save = read_phy_reg(pi, 0xa7); ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ rfctrlMiscReg1_save = read_phy_reg(pi, 0xf9); ++ rfctrlMiscReg2_save = read_phy_reg(pi, 0xfb); ++ afectrlOverride1_save = read_phy_reg(pi, 0x8f); ++ afectrlOverride2_save = read_phy_reg(pi, 0xa5); ++ rfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5); ++ rfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6); ++ } else { ++ afectrlOverride1_save = read_phy_reg(pi, 0xa5); ++ rfctrlcmd_save = read_phy_reg(pi, 0x78); ++ rfctrloverride_save = read_phy_reg(pi, 0xec); ++ rfctrlrssiothers1_save = read_phy_reg(pi, 0x7a); ++ rfctrlrssiothers2_save = read_phy_reg(pi, 0x7d); ++ } ++ ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type); ++ ++ gpiosel_orig = read_phy_reg(pi, 0xca); ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) ++ write_phy_reg(pi, 0xca, 5); ++ ++ for (ctr = 0; ctr < 4; ctr++) ++ rssi_buf[ctr] = 0; ++ ++ for (samp = 0; samp < nsamps; samp++) { ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) { ++ rssi0 = read_phy_reg(pi, 0x1c9); ++ rssi1 = read_phy_reg(pi, 0x1ca); ++ } else { ++ rssi0 = read_phy_reg(pi, 0x219); ++ rssi1 = read_phy_reg(pi, 0x21a); ++ } ++ ++ ctr = 0; ++ tmp_buf[ctr++] = ((s8) ((rssi0 & 0x3f) << 2)) >> 2; ++ tmp_buf[ctr++] = ((s8) (((rssi0 >> 8) & 0x3f) << 2)) >> 2; ++ tmp_buf[ctr++] = ((s8) ((rssi1 & 0x3f) << 2)) >> 2; ++ tmp_buf[ctr++] = ((s8) (((rssi1 >> 8) & 0x3f) << 2)) >> 2; ++ ++ for (ctr = 0; ctr < 4; ctr++) ++ rssi_buf[ctr] += tmp_buf[ctr]; ++ ++ } ++ ++ rssi_out_val = rssi_buf[3] & 0xff; ++ rssi_out_val |= (rssi_buf[2] & 0xff) << 8; ++ rssi_out_val |= (rssi_buf[1] & 0xff) << 16; ++ rssi_out_val |= (rssi_buf[0] & 0xff) << 24; ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) ++ write_phy_reg(pi, 0xca, gpiosel_orig); ++ ++ write_phy_reg(pi, 0xa6, afectrlCore1_save); ++ write_phy_reg(pi, 0xa7, afectrlCore2_save); ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ write_phy_reg(pi, 0xf9, rfctrlMiscReg1_save); ++ write_phy_reg(pi, 0xfb, rfctrlMiscReg2_save); ++ write_phy_reg(pi, 0x8f, afectrlOverride1_save); ++ write_phy_reg(pi, 0xa5, afectrlOverride2_save); ++ write_phy_reg(pi, 0xe5, rfctrlOverrideAux0_save); ++ write_phy_reg(pi, 0xe6, rfctrlOverrideAux1_save); ++ } else { ++ write_phy_reg(pi, 0xa5, afectrlOverride1_save); ++ write_phy_reg(pi, 0x78, rfctrlcmd_save); ++ write_phy_reg(pi, 0xec, rfctrloverride_save); ++ write_phy_reg(pi, 0x7a, rfctrlrssiothers1_save); ++ write_phy_reg(pi, 0x7d, rfctrlrssiothers2_save); ++ } ++ ++ return rssi_out_val; ++} ++ ++s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi) ++{ ++ u16 core1_txrf_iqcal1_save, core1_txrf_iqcal2_save; ++ u16 core2_txrf_iqcal1_save, core2_txrf_iqcal2_save; ++ u16 pwrdet_rxtx_core1_save; ++ u16 pwrdet_rxtx_core2_save; ++ u16 afectrlCore1_save; ++ u16 afectrlCore2_save; ++ u16 afectrlOverride_save; ++ u16 afectrlOverride2_save; ++ u16 pd_pll_ts_save; ++ u16 gpioSel_save; ++ s32 radio_temp[4]; ++ s32 radio_temp2[4]; ++ u16 syn_tempprocsense_save; ++ s16 offset = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ u16 auxADC_Vmid, auxADC_Av, auxADC_Vmid_save, auxADC_Av_save; ++ u16 auxADC_rssi_ctrlL_save, auxADC_rssi_ctrlH_save; ++ u16 auxADC_rssi_ctrlL, auxADC_rssi_ctrlH; ++ s32 auxADC_Vl; ++ u16 RfctrlOverride5_save, RfctrlOverride6_save; ++ u16 RfctrlMiscReg5_save, RfctrlMiscReg6_save; ++ u16 RSSIMultCoef0QPowerDet_save; ++ u16 tempsense_Rcal; ++ ++ syn_tempprocsense_save = ++ read_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG); ++ ++ afectrlCore1_save = read_phy_reg(pi, 0xa6); ++ afectrlCore2_save = read_phy_reg(pi, 0xa7); ++ afectrlOverride_save = read_phy_reg(pi, 0x8f); ++ afectrlOverride2_save = read_phy_reg(pi, 0xa5); ++ RSSIMultCoef0QPowerDet_save = read_phy_reg(pi, 0x1ae); ++ RfctrlOverride5_save = read_phy_reg(pi, 0x346); ++ RfctrlOverride6_save = read_phy_reg(pi, 0x347); ++ RfctrlMiscReg5_save = read_phy_reg(pi, 0x344); ++ RfctrlMiscReg6_save = read_phy_reg(pi, 0x345); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16, ++ &auxADC_Vmid_save); ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16, ++ &auxADC_Av_save); ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16, ++ &auxADC_rssi_ctrlL_save); ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16, ++ &auxADC_rssi_ctrlH_save); ++ ++ write_phy_reg(pi, 0x1ae, 0x0); ++ ++ auxADC_rssi_ctrlL = 0x0; ++ auxADC_rssi_ctrlH = 0x20; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16, ++ &auxADC_rssi_ctrlL); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16, ++ &auxADC_rssi_ctrlH); ++ ++ tempsense_Rcal = syn_tempprocsense_save & 0x1c; ++ ++ write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, ++ tempsense_Rcal | 0x01); ++ ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), ++ 1, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ mod_phy_reg(pi, 0xa6, (0x1 << 7), 0); ++ mod_phy_reg(pi, 0xa7, (0x1 << 7), 0); ++ mod_phy_reg(pi, 0x8f, (0x1 << 7), (0x1 << 7)); ++ mod_phy_reg(pi, 0xa5, (0x1 << 7), (0x1 << 7)); ++ ++ mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2)); ++ mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2)); ++ mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2)); ++ mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2)); ++ udelay(5); ++ mod_phy_reg(pi, 0xa6, (0x1 << 2), 0); ++ mod_phy_reg(pi, 0xa7, (0x1 << 2), 0); ++ mod_phy_reg(pi, 0xa6, (0x1 << 3), 0); ++ mod_phy_reg(pi, 0xa7, (0x1 << 3), 0); ++ mod_phy_reg(pi, 0x8f, (0x1 << 3), (0x1 << 3)); ++ mod_phy_reg(pi, 0xa5, (0x1 << 3), (0x1 << 3)); ++ mod_phy_reg(pi, 0xa6, (0x1 << 6), 0); ++ mod_phy_reg(pi, 0xa7, (0x1 << 6), 0); ++ mod_phy_reg(pi, 0x8f, (0x1 << 6), (0x1 << 6)); ++ mod_phy_reg(pi, 0xa5, (0x1 << 6), (0x1 << 6)); ++ ++ auxADC_Vmid = 0xA3; ++ auxADC_Av = 0x0; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16, ++ &auxADC_Vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16, ++ &auxADC_Av); ++ ++ udelay(3); ++ ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1); ++ write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, ++ tempsense_Rcal | 0x03); ++ ++ udelay(5); ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1); ++ ++ auxADC_Av = 0x7; ++ if (radio_temp[1] + radio_temp2[1] < -30) { ++ auxADC_Vmid = 0x45; ++ auxADC_Vl = 263; ++ } else if (radio_temp[1] + radio_temp2[1] < -9) { ++ auxADC_Vmid = 0x200; ++ auxADC_Vl = 467; ++ } else if (radio_temp[1] + radio_temp2[1] < 11) { ++ auxADC_Vmid = 0x266; ++ auxADC_Vl = 634; ++ } else { ++ auxADC_Vmid = 0x2D5; ++ auxADC_Vl = 816; ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16, ++ &auxADC_Vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16, ++ &auxADC_Av); ++ ++ udelay(3); ++ ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1); ++ write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, ++ tempsense_Rcal | 0x01); ++ ++ udelay(5); ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1); ++ ++ write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, ++ syn_tempprocsense_save); ++ ++ write_phy_reg(pi, 0xa6, afectrlCore1_save); ++ write_phy_reg(pi, 0xa7, afectrlCore2_save); ++ write_phy_reg(pi, 0x8f, afectrlOverride_save); ++ write_phy_reg(pi, 0xa5, afectrlOverride2_save); ++ write_phy_reg(pi, 0x1ae, RSSIMultCoef0QPowerDet_save); ++ write_phy_reg(pi, 0x346, RfctrlOverride5_save); ++ write_phy_reg(pi, 0x347, RfctrlOverride6_save); ++ write_phy_reg(pi, 0x344, RfctrlMiscReg5_save); ++ write_phy_reg(pi, 0x345, RfctrlMiscReg5_save); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16, ++ &auxADC_Vmid_save); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16, ++ &auxADC_Av_save); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16, ++ &auxADC_rssi_ctrlL_save); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16, ++ &auxADC_rssi_ctrlH_save); ++ ++ radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1]) ++ + 82 * (auxADC_Vl) - 28861 + ++ 128) / 256; ++ ++ offset = (s16) pi->phy_tempsense_offset; ++ ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ syn_tempprocsense_save = ++ read_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE); ++ ++ afectrlCore1_save = read_phy_reg(pi, 0xa6); ++ afectrlCore2_save = read_phy_reg(pi, 0xa7); ++ afectrlOverride_save = read_phy_reg(pi, 0x8f); ++ afectrlOverride2_save = read_phy_reg(pi, 0xa5); ++ gpioSel_save = read_phy_reg(pi, 0xca); ++ ++ write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01); ++ ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1); ++ if (NREV_LT(pi->pubpi.phy_rev, 7)) ++ write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x05); ++ ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x01); ++ else ++ write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01); ++ ++ radio_temp[0] = ++ (126 * (radio_temp[1] + radio_temp2[1]) + 3987) / 64; ++ ++ write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, ++ syn_tempprocsense_save); ++ ++ write_phy_reg(pi, 0xca, gpioSel_save); ++ write_phy_reg(pi, 0xa6, afectrlCore1_save); ++ write_phy_reg(pi, 0xa7, afectrlCore2_save); ++ write_phy_reg(pi, 0x8f, afectrlOverride_save); ++ write_phy_reg(pi, 0xa5, afectrlOverride2_save); ++ ++ offset = (s16) pi->phy_tempsense_offset; ++ } else { ++ ++ pwrdet_rxtx_core1_save = ++ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1); ++ pwrdet_rxtx_core2_save = ++ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2); ++ core1_txrf_iqcal1_save = ++ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1); ++ core1_txrf_iqcal2_save = ++ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2); ++ core2_txrf_iqcal1_save = ++ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1); ++ core2_txrf_iqcal2_save = ++ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2); ++ pd_pll_ts_save = read_radio_reg(pi, RADIO_2055_PD_PLL_TS); ++ ++ afectrlCore1_save = read_phy_reg(pi, 0xa6); ++ afectrlCore2_save = read_phy_reg(pi, 0xa7); ++ afectrlOverride_save = read_phy_reg(pi, 0xa5); ++ gpioSel_save = read_phy_reg(pi, 0xca); ++ ++ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x01); ++ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x01); ++ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x08); ++ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x08); ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04); ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04); ++ write_radio_reg(pi, RADIO_2055_PD_PLL_TS, 0x00); ++ ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1); ++ xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80); ++ ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1); ++ xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80); ++ ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1); ++ xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80); ++ ++ radio_temp[0] = (radio_temp[0] + radio_temp2[0]); ++ radio_temp[1] = (radio_temp[1] + radio_temp2[1]); ++ radio_temp[2] = (radio_temp[2] + radio_temp2[2]); ++ radio_temp[3] = (radio_temp[3] + radio_temp2[3]); ++ ++ radio_temp[0] = ++ (radio_temp[0] + radio_temp[1] + radio_temp[2] + ++ radio_temp[3]); ++ ++ radio_temp[0] = ++ (radio_temp[0] + ++ (8 * 32)) * (950 - 350) / 63 + (350 * 8); ++ ++ radio_temp[0] = (radio_temp[0] - (8 * 420)) / 38; ++ ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, ++ pwrdet_rxtx_core1_save); ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, ++ pwrdet_rxtx_core2_save); ++ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, ++ core1_txrf_iqcal1_save); ++ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, ++ core2_txrf_iqcal1_save); ++ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, ++ core1_txrf_iqcal2_save); ++ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, ++ core2_txrf_iqcal2_save); ++ write_radio_reg(pi, RADIO_2055_PD_PLL_TS, pd_pll_ts_save); ++ ++ write_phy_reg(pi, 0xca, gpioSel_save); ++ write_phy_reg(pi, 0xa6, afectrlCore1_save); ++ write_phy_reg(pi, 0xa7, afectrlCore2_save); ++ write_phy_reg(pi, 0xa5, afectrlOverride_save); ++ } ++ ++ return (s16) radio_temp[0] + offset; ++} ++ ++static void ++wlc_phy_set_rssi_2055_vcm(struct brcms_phy *pi, u8 rssi_type, u8 *vcm_buf) ++{ ++ u8 core; ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ if (rssi_type == NPHY_RSSI_SEL_NB) { ++ if (core == PHY_CORE_0) { ++ mod_radio_reg(pi, ++ RADIO_2055_CORE1_B0_NBRSSI_VCM, ++ RADIO_2055_NBRSSI_VCM_I_MASK, ++ vcm_buf[2 * ++ core] << ++ RADIO_2055_NBRSSI_VCM_I_SHIFT); ++ mod_radio_reg(pi, ++ RADIO_2055_CORE1_RXBB_RSSI_CTRL5, ++ RADIO_2055_NBRSSI_VCM_Q_MASK, ++ vcm_buf[2 * core + ++ 1] << ++ RADIO_2055_NBRSSI_VCM_Q_SHIFT); ++ } else { ++ mod_radio_reg(pi, ++ RADIO_2055_CORE2_B0_NBRSSI_VCM, ++ RADIO_2055_NBRSSI_VCM_I_MASK, ++ vcm_buf[2 * ++ core] << ++ RADIO_2055_NBRSSI_VCM_I_SHIFT); ++ mod_radio_reg(pi, ++ RADIO_2055_CORE2_RXBB_RSSI_CTRL5, ++ RADIO_2055_NBRSSI_VCM_Q_MASK, ++ vcm_buf[2 * core + ++ 1] << ++ RADIO_2055_NBRSSI_VCM_Q_SHIFT); ++ } ++ } else { ++ if (core == PHY_CORE_0) ++ mod_radio_reg(pi, ++ RADIO_2055_CORE1_RXBB_RSSI_CTRL5, ++ RADIO_2055_WBRSSI_VCM_IQ_MASK, ++ vcm_buf[2 * ++ core] << ++ RADIO_2055_WBRSSI_VCM_IQ_SHIFT); ++ else ++ mod_radio_reg(pi, ++ RADIO_2055_CORE2_RXBB_RSSI_CTRL5, ++ RADIO_2055_WBRSSI_VCM_IQ_MASK, ++ vcm_buf[2 * ++ core] << ++ RADIO_2055_WBRSSI_VCM_IQ_SHIFT); ++ } ++ } ++} ++ ++static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi) ++{ ++ u16 classif_state; ++ u16 clip_state[2]; ++ u16 clip_off[] = { 0xffff, 0xffff }; ++ s32 target_code; ++ u8 vcm, min_vcm; ++ u8 vcm_final = 0; ++ u8 result_idx; ++ s32 poll_results[8][4] = { ++ {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} ++ }; ++ s32 poll_result_core[4] = { 0, 0, 0, 0 }; ++ s32 min_d = NPHY_RSSICAL_MAXD, curr_d; ++ s32 fine_digital_offset[4]; ++ s32 poll_results_min[4] = { 0, 0, 0, 0 }; ++ s32 min_poll; ++ u8 vcm_level_max; ++ u8 core; ++ u8 wb_cnt; ++ u8 rssi_type; ++ u16 NPHY_Rfctrlintc1_save, NPHY_Rfctrlintc2_save; ++ u16 NPHY_AfectrlOverride1_save, NPHY_AfectrlOverride2_save; ++ u16 NPHY_AfectrlCore1_save, NPHY_AfectrlCore2_save; ++ u16 NPHY_RfctrlOverride0_save, NPHY_RfctrlOverride1_save; ++ u16 NPHY_RfctrlOverrideAux0_save, NPHY_RfctrlOverrideAux1_save; ++ u16 NPHY_RfctrlCmd_save; ++ u16 NPHY_RfctrlMiscReg1_save, NPHY_RfctrlMiscReg2_save; ++ u16 NPHY_RfctrlRSSIOTHERS1_save, NPHY_RfctrlRSSIOTHERS2_save; ++ u8 rxcore_state; ++ u16 NPHY_REV7_RfctrlOverride3_save, NPHY_REV7_RfctrlOverride4_save; ++ u16 NPHY_REV7_RfctrlOverride5_save, NPHY_REV7_RfctrlOverride6_save; ++ u16 NPHY_REV7_RfctrlMiscReg3_save, NPHY_REV7_RfctrlMiscReg4_save; ++ u16 NPHY_REV7_RfctrlMiscReg5_save, NPHY_REV7_RfctrlMiscReg6_save; ++ ++ NPHY_REV7_RfctrlOverride3_save = ++ NPHY_REV7_RfctrlOverride4_save = ++ NPHY_REV7_RfctrlOverride5_save = ++ NPHY_REV7_RfctrlOverride6_save = ++ NPHY_REV7_RfctrlMiscReg3_save = ++ NPHY_REV7_RfctrlMiscReg4_save = ++ NPHY_REV7_RfctrlMiscReg5_save = ++ NPHY_REV7_RfctrlMiscReg6_save = 0; ++ ++ classif_state = wlc_phy_classifier_nphy(pi, 0, 0); ++ wlc_phy_classifier_nphy(pi, (0x7 << 0), 4); ++ wlc_phy_clip_det_nphy(pi, 0, clip_state); ++ wlc_phy_clip_det_nphy(pi, 1, clip_off); ++ ++ NPHY_Rfctrlintc1_save = read_phy_reg(pi, 0x91); ++ NPHY_Rfctrlintc2_save = read_phy_reg(pi, 0x92); ++ NPHY_AfectrlOverride1_save = read_phy_reg(pi, 0x8f); ++ NPHY_AfectrlOverride2_save = read_phy_reg(pi, 0xa5); ++ NPHY_AfectrlCore1_save = read_phy_reg(pi, 0xa6); ++ NPHY_AfectrlCore2_save = read_phy_reg(pi, 0xa7); ++ NPHY_RfctrlOverride0_save = read_phy_reg(pi, 0xe7); ++ NPHY_RfctrlOverride1_save = read_phy_reg(pi, 0xec); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ NPHY_REV7_RfctrlOverride3_save = read_phy_reg(pi, 0x342); ++ NPHY_REV7_RfctrlOverride4_save = read_phy_reg(pi, 0x343); ++ NPHY_REV7_RfctrlOverride5_save = read_phy_reg(pi, 0x346); ++ NPHY_REV7_RfctrlOverride6_save = read_phy_reg(pi, 0x347); ++ } ++ NPHY_RfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5); ++ NPHY_RfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6); ++ NPHY_RfctrlCmd_save = read_phy_reg(pi, 0x78); ++ NPHY_RfctrlMiscReg1_save = read_phy_reg(pi, 0xf9); ++ NPHY_RfctrlMiscReg2_save = read_phy_reg(pi, 0xfb); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ NPHY_REV7_RfctrlMiscReg3_save = read_phy_reg(pi, 0x340); ++ NPHY_REV7_RfctrlMiscReg4_save = read_phy_reg(pi, 0x341); ++ NPHY_REV7_RfctrlMiscReg5_save = read_phy_reg(pi, 0x344); ++ NPHY_REV7_RfctrlMiscReg6_save = read_phy_reg(pi, 0x345); ++ } ++ NPHY_RfctrlRSSIOTHERS1_save = read_phy_reg(pi, 0x7a); ++ NPHY_RfctrlRSSIOTHERS2_save = read_phy_reg(pi, 0x7d); ++ ++ wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_OFF, 0, ++ RADIO_MIMO_CORESEL_ALLRXTX); ++ wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_TRSW, 1, ++ RADIO_MIMO_CORESEL_ALLRXTX); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_rxrf_pu, ++ 0, 0, 0); ++ else ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0, 0); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_rx_pu, ++ 1, 0, 0); ++ else ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0, 0); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), ++ 1, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 6), 1, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ } else { ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 7), 1, 0, 0); ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 6), 1, 0, 0); ++ } ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 5), ++ 0, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 4), 1, 0, ++ 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ } else { ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 0, 0, 0); ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 1, 0, 0); ++ } ++ ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 4), ++ 0, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 5), 1, 0, ++ 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ } else { ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 0, 0, 0); ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 1, 0, 0); ++ } ++ } ++ ++ rxcore_state = wlc_phy_rxcore_getstate_nphy( ++ (struct brcms_phy_pub *) pi); ++ ++ vcm_level_max = 8; ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ ++ if ((rxcore_state & (1 << core)) == 0) ++ continue; ++ ++ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, ++ core == ++ PHY_CORE_0 ? ++ RADIO_MIMO_CORESEL_CORE1 : ++ RADIO_MIMO_CORESEL_CORE2, ++ NPHY_RAIL_I, NPHY_RSSI_SEL_NB); ++ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, ++ core == ++ PHY_CORE_0 ? ++ RADIO_MIMO_CORESEL_CORE1 : ++ RADIO_MIMO_CORESEL_CORE2, ++ NPHY_RAIL_Q, NPHY_RSSI_SEL_NB); ++ ++ for (vcm = 0; vcm < vcm_level_max; vcm++) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ mod_radio_reg(pi, (core == PHY_CORE_0) ? ++ RADIO_2057_NB_MASTER_CORE0 : ++ RADIO_2057_NB_MASTER_CORE1, ++ RADIO_2057_VCM_MASK, vcm); ++ else ++ mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC | ++ ((core == ++ PHY_CORE_0) ? RADIO_2056_RX0 : ++ RADIO_2056_RX1), ++ RADIO_2056_VCM_MASK, ++ vcm << RADIO_2056_RSSI_VCM_SHIFT); ++ ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_NB, ++ &poll_results[vcm][0], ++ NPHY_RSSICAL_NPOLL); ++ } ++ ++ for (result_idx = 0; result_idx < 4; result_idx++) { ++ if ((core == result_idx / 2) && ++ (result_idx % 2 == 0)) { ++ ++ min_d = NPHY_RSSICAL_MAXD; ++ min_vcm = 0; ++ min_poll = ++ NPHY_RSSICAL_MAXREAD * ++ NPHY_RSSICAL_NPOLL + 1; ++ for (vcm = 0; vcm < vcm_level_max; vcm++) { ++ curr_d = ++ poll_results[vcm][result_idx] * ++ poll_results[vcm][result_idx] + ++ poll_results[vcm][result_idx + ++ 1] * ++ poll_results[vcm][result_idx + ++ 1]; ++ if (curr_d < min_d) { ++ min_d = curr_d; ++ min_vcm = vcm; ++ } ++ if (poll_results[vcm][result_idx] < ++ min_poll) ++ min_poll = ++ poll_results[vcm] ++ [result_idx]; ++ } ++ vcm_final = min_vcm; ++ poll_results_min[result_idx] = min_poll; ++ } ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ mod_radio_reg(pi, (core == PHY_CORE_0) ? ++ RADIO_2057_NB_MASTER_CORE0 : ++ RADIO_2057_NB_MASTER_CORE1, ++ RADIO_2057_VCM_MASK, vcm_final); ++ else ++ mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC | ++ ((core == ++ PHY_CORE_0) ? RADIO_2056_RX0 : ++ RADIO_2056_RX1), RADIO_2056_VCM_MASK, ++ vcm_final << RADIO_2056_RSSI_VCM_SHIFT); ++ ++ for (result_idx = 0; result_idx < 4; result_idx++) { ++ if (core == result_idx / 2) { ++ fine_digital_offset[result_idx] = ++ (NPHY_RSSICAL_NB_TARGET * ++ NPHY_RSSICAL_NPOLL) - ++ poll_results[vcm_final][result_idx]; ++ if (fine_digital_offset[result_idx] < 0) { ++ fine_digital_offset[result_idx] = ++ abs(fine_digital_offset ++ [result_idx]); ++ fine_digital_offset[result_idx] += ++ (NPHY_RSSICAL_NPOLL / 2); ++ fine_digital_offset[result_idx] /= ++ NPHY_RSSICAL_NPOLL; ++ fine_digital_offset[result_idx] = ++ -fine_digital_offset[ ++ result_idx]; ++ } else { ++ fine_digital_offset[result_idx] += ++ (NPHY_RSSICAL_NPOLL / 2); ++ fine_digital_offset[result_idx] /= ++ NPHY_RSSICAL_NPOLL; ++ } ++ ++ if (poll_results_min[result_idx] == ++ NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) ++ fine_digital_offset[result_idx] = ++ (NPHY_RSSICAL_NB_TARGET - ++ NPHY_RSSICAL_MAXREAD - 1); ++ ++ wlc_phy_scale_offset_rssi_nphy( ++ pi, 0x0, ++ (s8) ++ fine_digital_offset ++ [result_idx], ++ (result_idx / 2 == 0) ? ++ RADIO_MIMO_CORESEL_CORE1 : ++ RADIO_MIMO_CORESEL_CORE2, ++ (result_idx % 2 == 0) ? ++ NPHY_RAIL_I : NPHY_RAIL_Q, ++ NPHY_RSSI_SEL_NB); ++ } ++ } ++ ++ } ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ ++ if ((rxcore_state & (1 << core)) == 0) ++ continue; ++ ++ for (wb_cnt = 0; wb_cnt < 2; wb_cnt++) { ++ if (wb_cnt == 0) { ++ rssi_type = NPHY_RSSI_SEL_W1; ++ target_code = NPHY_RSSICAL_W1_TARGET_REV3; ++ } else { ++ rssi_type = NPHY_RSSI_SEL_W2; ++ target_code = NPHY_RSSICAL_W2_TARGET_REV3; ++ } ++ ++ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, ++ core == ++ PHY_CORE_0 ? ++ RADIO_MIMO_CORESEL_CORE1 ++ : ++ RADIO_MIMO_CORESEL_CORE2, ++ NPHY_RAIL_I, rssi_type); ++ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, ++ core == ++ PHY_CORE_0 ? ++ RADIO_MIMO_CORESEL_CORE1 ++ : ++ RADIO_MIMO_CORESEL_CORE2, ++ NPHY_RAIL_Q, rssi_type); ++ ++ wlc_phy_poll_rssi_nphy(pi, rssi_type, poll_result_core, ++ NPHY_RSSICAL_NPOLL); ++ ++ for (result_idx = 0; result_idx < 4; result_idx++) { ++ if (core == result_idx / 2) { ++ fine_digital_offset[result_idx] = ++ (target_code * ++ NPHY_RSSICAL_NPOLL) - ++ poll_result_core[result_idx]; ++ if (fine_digital_offset[result_idx] < ++ 0) { ++ fine_digital_offset[result_idx] ++ = abs( ++ fine_digital_offset ++ [result_idx]); ++ fine_digital_offset[result_idx] ++ += (NPHY_RSSICAL_NPOLL ++ / 2); ++ fine_digital_offset[result_idx] ++ /= NPHY_RSSICAL_NPOLL; ++ fine_digital_offset[result_idx] ++ = -fine_digital_offset ++ [result_idx]; ++ } else { ++ fine_digital_offset[result_idx] ++ += (NPHY_RSSICAL_NPOLL ++ / 2); ++ fine_digital_offset[result_idx] ++ /= NPHY_RSSICAL_NPOLL; ++ } ++ ++ wlc_phy_scale_offset_rssi_nphy( ++ pi, 0x0, ++ (s8) ++ fine_digital_offset ++ [core * ++ 2], ++ (core == PHY_CORE_0) ? ++ RADIO_MIMO_CORESEL_CORE1 : ++ RADIO_MIMO_CORESEL_CORE2, ++ (result_idx % 2 == 0) ? ++ NPHY_RAIL_I : ++ NPHY_RAIL_Q, ++ rssi_type); ++ } ++ } ++ ++ } ++ } ++ ++ write_phy_reg(pi, 0x91, NPHY_Rfctrlintc1_save); ++ write_phy_reg(pi, 0x92, NPHY_Rfctrlintc2_save); ++ ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); ++ ++ mod_phy_reg(pi, 0xe7, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0x78, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0xe7, (0x1 << 0), 0); ++ ++ mod_phy_reg(pi, 0xec, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0x78, (0x1 << 1), 1 << 1); ++ mod_phy_reg(pi, 0xec, (0x1 << 0), 0); ++ ++ write_phy_reg(pi, 0x8f, NPHY_AfectrlOverride1_save); ++ write_phy_reg(pi, 0xa5, NPHY_AfectrlOverride2_save); ++ write_phy_reg(pi, 0xa6, NPHY_AfectrlCore1_save); ++ write_phy_reg(pi, 0xa7, NPHY_AfectrlCore2_save); ++ write_phy_reg(pi, 0xe7, NPHY_RfctrlOverride0_save); ++ write_phy_reg(pi, 0xec, NPHY_RfctrlOverride1_save); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ write_phy_reg(pi, 0x342, NPHY_REV7_RfctrlOverride3_save); ++ write_phy_reg(pi, 0x343, NPHY_REV7_RfctrlOverride4_save); ++ write_phy_reg(pi, 0x346, NPHY_REV7_RfctrlOverride5_save); ++ write_phy_reg(pi, 0x347, NPHY_REV7_RfctrlOverride6_save); ++ } ++ write_phy_reg(pi, 0xe5, NPHY_RfctrlOverrideAux0_save); ++ write_phy_reg(pi, 0xe6, NPHY_RfctrlOverrideAux1_save); ++ write_phy_reg(pi, 0x78, NPHY_RfctrlCmd_save); ++ write_phy_reg(pi, 0xf9, NPHY_RfctrlMiscReg1_save); ++ write_phy_reg(pi, 0xfb, NPHY_RfctrlMiscReg2_save); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ write_phy_reg(pi, 0x340, NPHY_REV7_RfctrlMiscReg3_save); ++ write_phy_reg(pi, 0x341, NPHY_REV7_RfctrlMiscReg4_save); ++ write_phy_reg(pi, 0x344, NPHY_REV7_RfctrlMiscReg5_save); ++ write_phy_reg(pi, 0x345, NPHY_REV7_RfctrlMiscReg6_save); ++ } ++ write_phy_reg(pi, 0x7a, NPHY_RfctrlRSSIOTHERS1_save); ++ write_phy_reg(pi, 0x7d, NPHY_RfctrlRSSIOTHERS2_save); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ pi->rssical_cache.rssical_radio_regs_2G[0] = ++ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0); ++ pi->rssical_cache.rssical_radio_regs_2G[1] = ++ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1); ++ } else { ++ pi->rssical_cache.rssical_radio_regs_2G[0] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_RSSI_MISC | ++ RADIO_2056_RX0); ++ pi->rssical_cache.rssical_radio_regs_2G[1] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_RSSI_MISC | ++ RADIO_2056_RX1); ++ } ++ ++ pi->rssical_cache.rssical_phyregs_2G[0] = ++ read_phy_reg(pi, 0x1a6); ++ pi->rssical_cache.rssical_phyregs_2G[1] = ++ read_phy_reg(pi, 0x1ac); ++ pi->rssical_cache.rssical_phyregs_2G[2] = ++ read_phy_reg(pi, 0x1b2); ++ pi->rssical_cache.rssical_phyregs_2G[3] = ++ read_phy_reg(pi, 0x1b8); ++ pi->rssical_cache.rssical_phyregs_2G[4] = ++ read_phy_reg(pi, 0x1a4); ++ pi->rssical_cache.rssical_phyregs_2G[5] = ++ read_phy_reg(pi, 0x1aa); ++ pi->rssical_cache.rssical_phyregs_2G[6] = ++ read_phy_reg(pi, 0x1b0); ++ pi->rssical_cache.rssical_phyregs_2G[7] = ++ read_phy_reg(pi, 0x1b6); ++ pi->rssical_cache.rssical_phyregs_2G[8] = ++ read_phy_reg(pi, 0x1a5); ++ pi->rssical_cache.rssical_phyregs_2G[9] = ++ read_phy_reg(pi, 0x1ab); ++ pi->rssical_cache.rssical_phyregs_2G[10] = ++ read_phy_reg(pi, 0x1b1); ++ pi->rssical_cache.rssical_phyregs_2G[11] = ++ read_phy_reg(pi, 0x1b7); ++ ++ pi->nphy_rssical_chanspec_2G = pi->radio_chanspec; ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ pi->rssical_cache.rssical_radio_regs_5G[0] = ++ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0); ++ pi->rssical_cache.rssical_radio_regs_5G[1] = ++ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1); ++ } else { ++ pi->rssical_cache.rssical_radio_regs_5G[0] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_RSSI_MISC | ++ RADIO_2056_RX0); ++ pi->rssical_cache.rssical_radio_regs_5G[1] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_RSSI_MISC | ++ RADIO_2056_RX1); ++ } ++ ++ pi->rssical_cache.rssical_phyregs_5G[0] = ++ read_phy_reg(pi, 0x1a6); ++ pi->rssical_cache.rssical_phyregs_5G[1] = ++ read_phy_reg(pi, 0x1ac); ++ pi->rssical_cache.rssical_phyregs_5G[2] = ++ read_phy_reg(pi, 0x1b2); ++ pi->rssical_cache.rssical_phyregs_5G[3] = ++ read_phy_reg(pi, 0x1b8); ++ pi->rssical_cache.rssical_phyregs_5G[4] = ++ read_phy_reg(pi, 0x1a4); ++ pi->rssical_cache.rssical_phyregs_5G[5] = ++ read_phy_reg(pi, 0x1aa); ++ pi->rssical_cache.rssical_phyregs_5G[6] = ++ read_phy_reg(pi, 0x1b0); ++ pi->rssical_cache.rssical_phyregs_5G[7] = ++ read_phy_reg(pi, 0x1b6); ++ pi->rssical_cache.rssical_phyregs_5G[8] = ++ read_phy_reg(pi, 0x1a5); ++ pi->rssical_cache.rssical_phyregs_5G[9] = ++ read_phy_reg(pi, 0x1ab); ++ pi->rssical_cache.rssical_phyregs_5G[10] = ++ read_phy_reg(pi, 0x1b1); ++ pi->rssical_cache.rssical_phyregs_5G[11] = ++ read_phy_reg(pi, 0x1b7); ++ ++ pi->nphy_rssical_chanspec_5G = pi->radio_chanspec; ++ } ++ ++ wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state); ++ wlc_phy_clip_det_nphy(pi, 1, clip_state); ++} ++ ++static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type) ++{ ++ s32 target_code; ++ u16 classif_state; ++ u16 clip_state[2]; ++ u16 rssi_ctrl_state[2], pd_state[2]; ++ u16 rfctrlintc_state[2], rfpdcorerxtx_state[2]; ++ u16 rfctrlintc_override_val; ++ u16 clip_off[] = { 0xffff, 0xffff }; ++ u16 rf_pd_val, pd_mask, rssi_ctrl_mask; ++ u8 vcm, min_vcm, vcm_tmp[4]; ++ u8 vcm_final[4] = { 0, 0, 0, 0 }; ++ u8 result_idx, ctr; ++ s32 poll_results[4][4] = { ++ {0, 0, 0, 0}, ++ {0, 0, 0, 0}, ++ {0, 0, 0, 0}, ++ {0, 0, 0, 0} ++ }; ++ s32 poll_miniq[4][2] = { ++ {0, 0}, ++ {0, 0}, ++ {0, 0}, ++ {0, 0} ++ }; ++ s32 min_d, curr_d; ++ s32 fine_digital_offset[4]; ++ s32 poll_results_min[4] = { 0, 0, 0, 0 }; ++ s32 min_poll; ++ ++ switch (rssi_type) { ++ case NPHY_RSSI_SEL_NB: ++ target_code = NPHY_RSSICAL_NB_TARGET; ++ break; ++ case NPHY_RSSI_SEL_W1: ++ target_code = NPHY_RSSICAL_W1_TARGET; ++ break; ++ case NPHY_RSSI_SEL_W2: ++ target_code = NPHY_RSSICAL_W2_TARGET; ++ break; ++ default: ++ return; ++ break; ++ } ++ ++ classif_state = wlc_phy_classifier_nphy(pi, 0, 0); ++ wlc_phy_classifier_nphy(pi, (0x7 << 0), 4); ++ wlc_phy_clip_det_nphy(pi, 0, clip_state); ++ wlc_phy_clip_det_nphy(pi, 1, clip_off); ++ ++ rf_pd_val = (rssi_type == NPHY_RSSI_SEL_NB) ? 0x6 : 0x4; ++ rfctrlintc_override_val = ++ CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 : 0x110; ++ ++ rfctrlintc_state[0] = read_phy_reg(pi, 0x91); ++ rfpdcorerxtx_state[0] = read_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX); ++ write_phy_reg(pi, 0x91, rfctrlintc_override_val); ++ write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rf_pd_val); ++ ++ rfctrlintc_state[1] = read_phy_reg(pi, 0x92); ++ rfpdcorerxtx_state[1] = read_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX); ++ write_phy_reg(pi, 0x92, rfctrlintc_override_val); ++ write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rf_pd_val); ++ ++ pd_mask = RADIO_2055_NBRSSI_PD | RADIO_2055_WBRSSI_G1_PD | ++ RADIO_2055_WBRSSI_G2_PD; ++ pd_state[0] = ++ read_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC) & pd_mask; ++ pd_state[1] = ++ read_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC) & pd_mask; ++ mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, 0); ++ mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, 0); ++ rssi_ctrl_mask = RADIO_2055_NBRSSI_SEL | RADIO_2055_WBRSSI_G1_SEL | ++ RADIO_2055_WBRSSI_G2_SEL; ++ rssi_ctrl_state[0] = ++ read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE1) & rssi_ctrl_mask; ++ rssi_ctrl_state[1] = ++ read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE2) & rssi_ctrl_mask; ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type); ++ ++ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX, ++ NPHY_RAIL_I, rssi_type); ++ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX, ++ NPHY_RAIL_Q, rssi_type); ++ ++ for (vcm = 0; vcm < 4; vcm++) { ++ ++ vcm_tmp[0] = vcm_tmp[1] = vcm_tmp[2] = vcm_tmp[3] = vcm; ++ if (rssi_type != NPHY_RSSI_SEL_W2) ++ wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_tmp); ++ ++ wlc_phy_poll_rssi_nphy(pi, rssi_type, &poll_results[vcm][0], ++ NPHY_RSSICAL_NPOLL); ++ ++ if ((rssi_type == NPHY_RSSI_SEL_W1) ++ || (rssi_type == NPHY_RSSI_SEL_W2)) { ++ for (ctr = 0; ctr < 2; ctr++) ++ poll_miniq[vcm][ctr] = ++ min(poll_results[vcm][ctr * 2 + 0], ++ poll_results[vcm][ctr * 2 + 1]); ++ } ++ } ++ ++ for (result_idx = 0; result_idx < 4; result_idx++) { ++ min_d = NPHY_RSSICAL_MAXD; ++ min_vcm = 0; ++ min_poll = NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL + 1; ++ for (vcm = 0; vcm < 4; vcm++) { ++ curr_d = abs(((rssi_type == NPHY_RSSI_SEL_NB) ? ++ poll_results[vcm][result_idx] : ++ poll_miniq[vcm][result_idx / 2]) - ++ (target_code * NPHY_RSSICAL_NPOLL)); ++ if (curr_d < min_d) { ++ min_d = curr_d; ++ min_vcm = vcm; ++ } ++ if (poll_results[vcm][result_idx] < min_poll) ++ min_poll = poll_results[vcm][result_idx]; ++ } ++ vcm_final[result_idx] = min_vcm; ++ poll_results_min[result_idx] = min_poll; ++ } ++ ++ if (rssi_type != NPHY_RSSI_SEL_W2) ++ wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_final); ++ ++ for (result_idx = 0; result_idx < 4; result_idx++) { ++ fine_digital_offset[result_idx] = ++ (target_code * NPHY_RSSICAL_NPOLL) - ++ poll_results[vcm_final[result_idx]][result_idx]; ++ if (fine_digital_offset[result_idx] < 0) { ++ fine_digital_offset[result_idx] = ++ abs(fine_digital_offset[result_idx]); ++ fine_digital_offset[result_idx] += ++ (NPHY_RSSICAL_NPOLL / 2); ++ fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL; ++ fine_digital_offset[result_idx] = ++ -fine_digital_offset[result_idx]; ++ } else { ++ fine_digital_offset[result_idx] += ++ (NPHY_RSSICAL_NPOLL / 2); ++ fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL; ++ } ++ ++ if (poll_results_min[result_idx] == ++ NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) ++ fine_digital_offset[result_idx] = ++ (target_code - NPHY_RSSICAL_MAXREAD - 1); ++ ++ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, ++ (s8) ++ fine_digital_offset[result_idx], ++ (result_idx / 2 == ++ 0) ? RADIO_MIMO_CORESEL_CORE1 : ++ RADIO_MIMO_CORESEL_CORE2, ++ (result_idx % 2 == ++ 0) ? NPHY_RAIL_I : NPHY_RAIL_Q, ++ rssi_type); ++ } ++ ++ mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, pd_state[0]); ++ mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, pd_state[1]); ++ if (rssi_ctrl_state[0] == RADIO_2055_NBRSSI_SEL) ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1, ++ NPHY_RSSI_SEL_NB); ++ else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G1_SEL) ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1, ++ NPHY_RSSI_SEL_W1); ++ else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G2_SEL) ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1, ++ NPHY_RSSI_SEL_W2); ++ else ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1, ++ NPHY_RSSI_SEL_W2); ++ if (rssi_ctrl_state[1] == RADIO_2055_NBRSSI_SEL) ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2, ++ NPHY_RSSI_SEL_NB); ++ else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G1_SEL) ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2, ++ NPHY_RSSI_SEL_W1); ++ else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G2_SEL) ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2, ++ NPHY_RSSI_SEL_W2); ++ else ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2, ++ NPHY_RSSI_SEL_W2); ++ ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, rssi_type); ++ ++ write_phy_reg(pi, 0x91, rfctrlintc_state[0]); ++ write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rfpdcorerxtx_state[0]); ++ write_phy_reg(pi, 0x92, rfctrlintc_state[1]); ++ write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rfpdcorerxtx_state[1]); ++ ++ wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state); ++ wlc_phy_clip_det_nphy(pi, 1, clip_state); ++ ++ wlc_phy_resetcca_nphy(pi); ++} ++ ++void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi) ++{ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ wlc_phy_rssi_cal_nphy_rev3(pi); ++ } else { ++ wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_NB); ++ wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W1); ++ wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W2); ++ } ++} ++ ++int ++wlc_phy_rssi_compute_nphy(struct brcms_phy *pi, struct d11rxhdr *rxh) ++{ ++ s16 rxpwr, rxpwr0, rxpwr1; ++ s16 phyRx0_l, phyRx2_l; ++ ++ rxpwr = 0; ++ rxpwr0 = rxh->PhyRxStatus_1 & PRXS1_nphy_PWR0_MASK; ++ rxpwr1 = (rxh->PhyRxStatus_1 & PRXS1_nphy_PWR1_MASK) >> 8; ++ ++ if (rxpwr0 > 127) ++ rxpwr0 -= 256; ++ if (rxpwr1 > 127) ++ rxpwr1 -= 256; ++ ++ phyRx0_l = rxh->PhyRxStatus_0 & 0x00ff; ++ phyRx2_l = rxh->PhyRxStatus_2 & 0x00ff; ++ if (phyRx2_l > 127) ++ phyRx2_l -= 256; ++ ++ if (((rxpwr0 == 16) || (rxpwr0 == 32))) { ++ rxpwr0 = rxpwr1; ++ rxpwr1 = phyRx2_l; ++ } ++ ++ if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MAX) ++ rxpwr = (rxpwr0 > rxpwr1) ? rxpwr0 : rxpwr1; ++ else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MIN) ++ rxpwr = (rxpwr0 < rxpwr1) ? rxpwr0 : rxpwr1; ++ else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_AVG) ++ rxpwr = (rxpwr0 + rxpwr1) >> 1; ++ ++ return rxpwr; ++} ++ ++static void ++wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, struct cordic_iq *tone_buf, ++ u16 num_samps) ++{ ++ u16 t; ++ u32 *data_buf = NULL; ++ ++ data_buf = kmalloc(sizeof(u32) * num_samps, GFP_ATOMIC); ++ if (data_buf == NULL) ++ return; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ for (t = 0; t < num_samps; t++) ++ data_buf[t] = ((((unsigned int)tone_buf[t].i) & 0x3ff) << 10) | ++ (((unsigned int)tone_buf[t].q) & 0x3ff); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SAMPLEPLAY, num_samps, 0, 32, ++ data_buf); ++ ++ kfree(data_buf); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static u16 ++wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, ++ u8 dac_test_mode) ++{ ++ u8 phy_bw, is_phybw40; ++ u16 num_samps, t, spur; ++ s32 theta = 0, rot = 0; ++ u32 tbl_len; ++ struct cordic_iq *tone_buf = NULL; ++ ++ is_phybw40 = CHSPEC_IS40(pi->radio_chanspec); ++ phy_bw = (is_phybw40 == 1) ? 40 : 20; ++ tbl_len = (phy_bw << 3); ++ ++ if (dac_test_mode == 1) { ++ spur = read_phy_reg(pi, 0x01); ++ spur = (spur >> 15) & 1; ++ phy_bw = (spur == 1) ? 82 : 80; ++ phy_bw = (is_phybw40 == 1) ? (phy_bw << 1) : phy_bw; ++ ++ tbl_len = (phy_bw << 1); ++ } ++ ++ tone_buf = kmalloc(sizeof(struct cordic_iq) * tbl_len, GFP_ATOMIC); ++ if (tone_buf == NULL) ++ return 0; ++ ++ num_samps = (u16) tbl_len; ++ rot = ((f_kHz * 36) / phy_bw) / 100; ++ theta = 0; ++ ++ for (t = 0; t < num_samps; t++) { ++ ++ tone_buf[t] = cordic_calc_iq(theta); ++ ++ theta += rot; ++ ++ tone_buf[t].q = (s32) FLOAT(tone_buf[t].q * max_val); ++ tone_buf[t].i = (s32) FLOAT(tone_buf[t].i * max_val); ++ } ++ ++ wlc_phy_loadsampletable_nphy(pi, tone_buf, num_samps); ++ ++ kfree(tone_buf); ++ ++ return num_samps; ++} ++ ++static void ++wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops, ++ u16 wait, u8 iqmode, u8 dac_test_mode, ++ bool modify_bbmult) ++{ ++ u16 bb_mult; ++ u8 phy_bw, sample_cmd; ++ u16 orig_RfseqCoreActv; ++ u16 lpf_bw_ctl_override3, lpf_bw_ctl_override4, lpf_bw_ctl_miscreg3, ++ lpf_bw_ctl_miscreg4; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ phy_bw = 20; ++ if (CHSPEC_IS40(pi->radio_chanspec)) ++ phy_bw = 40; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ lpf_bw_ctl_override3 = read_phy_reg(pi, 0x342) & (0x1 << 7); ++ lpf_bw_ctl_override4 = read_phy_reg(pi, 0x343) & (0x1 << 7); ++ if (lpf_bw_ctl_override3 | lpf_bw_ctl_override4) { ++ lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) & ++ (0x7 << 8); ++ lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) & ++ (0x7 << 8); ++ } else { ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, ++ (0x1 << 7), ++ wlc_phy_read_lpf_bw_ctl_nphy ++ (pi, ++ 0), 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ ++ pi->nphy_sample_play_lpf_bw_ctl_ovr = true; ++ ++ lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) & ++ (0x7 << 8); ++ lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) & ++ (0x7 << 8); ++ } ++ } ++ ++ if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) == 0) { ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16, ++ &bb_mult); ++ pi->nphy_bb_mult_save = ++ BB_MULT_VALID_MASK | (bb_mult & BB_MULT_MASK); ++ } ++ ++ if (modify_bbmult) { ++ bb_mult = (phy_bw == 20) ? 100 : 71; ++ bb_mult = (bb_mult << 8) + bb_mult; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16, ++ &bb_mult); ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ ++ write_phy_reg(pi, 0xc6, num_samps - 1); ++ ++ if (loops != 0xffff) ++ write_phy_reg(pi, 0xc4, loops - 1); ++ else ++ write_phy_reg(pi, 0xc4, loops); ++ ++ write_phy_reg(pi, 0xc5, wait); ++ ++ orig_RfseqCoreActv = read_phy_reg(pi, 0xa1); ++ or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override); ++ if (iqmode) { ++ ++ and_phy_reg(pi, 0xc2, 0x7FFF); ++ ++ or_phy_reg(pi, 0xc2, 0x8000); ++ } else { ++ ++ sample_cmd = (dac_test_mode == 1) ? 0x5 : 0x1; ++ write_phy_reg(pi, 0xc3, sample_cmd); ++ } ++ ++ SPINWAIT(((read_phy_reg(pi, 0xa4) & 0x1) == 1), 1000); ++ ++ write_phy_reg(pi, 0xa1, orig_RfseqCoreActv); ++} ++ ++int ++wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, ++ u8 iqmode, u8 dac_test_mode, bool modify_bbmult) ++{ ++ u16 num_samps; ++ u16 loops = 0xffff; ++ u16 wait = 0; ++ ++ num_samps = wlc_phy_gen_load_samples_nphy(pi, f_kHz, max_val, ++ dac_test_mode); ++ if (num_samps == 0) ++ return -EBADE; ++ ++ wlc_phy_runsamples_nphy(pi, num_samps, loops, wait, iqmode, ++ dac_test_mode, modify_bbmult); ++ ++ return 0; ++} ++ ++void wlc_phy_stopplayback_nphy(struct brcms_phy *pi) ++{ ++ u16 playback_status; ++ u16 bb_mult; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ playback_status = read_phy_reg(pi, 0xc7); ++ if (playback_status & 0x1) ++ or_phy_reg(pi, 0xc3, NPHY_sampleCmd_STOP); ++ else if (playback_status & 0x2) ++ and_phy_reg(pi, 0xc2, ++ (u16) ~NPHY_iqloCalCmdGctl_IQLO_CAL_EN); ++ ++ and_phy_reg(pi, 0xc3, (u16) ~(0x1 << 2)); ++ ++ if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) != 0) { ++ ++ bb_mult = pi->nphy_bb_mult_save & BB_MULT_MASK; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16, ++ &bb_mult); ++ ++ pi->nphy_bb_mult_save = 0; ++ } ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7) || NREV_GE(pi->pubpi.phy_rev, 8)) { ++ if (pi->nphy_sample_play_lpf_bw_ctl_ovr) { ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, ++ (0x1 << 7), ++ 0, 0, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ pi->nphy_sample_play_lpf_bw_ctl_ovr = false; ++ } ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static u32 *brcms_phy_get_tx_pwrctrl_tbl(struct brcms_phy *pi) ++{ ++ u32 *tx_pwrctrl_tbl = NULL; ++ uint phyrev = pi->pubpi.phy_rev; ++ ++ if (PHY_IPA(pi)) { ++ tx_pwrctrl_tbl = ++ wlc_phy_get_ipa_gaintbl_nphy(pi); ++ } else { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (NREV_IS(phyrev, 3)) ++ tx_pwrctrl_tbl = nphy_tpc_5GHz_txgain_rev3; ++ else if (NREV_IS(phyrev, 4)) ++ tx_pwrctrl_tbl = ++ (pi->srom_fem5g.extpagain == 3) ? ++ nphy_tpc_5GHz_txgain_HiPwrEPA : ++ nphy_tpc_5GHz_txgain_rev4; ++ else ++ tx_pwrctrl_tbl = nphy_tpc_5GHz_txgain_rev5; ++ } else { ++ if (NREV_GE(phyrev, 7)) { ++ if (pi->pubpi.radiorev == 3) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_epa_2057rev3; ++ else if (pi->pubpi.radiorev == 5) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_epa_2057rev5; ++ } else { ++ if (NREV_GE(phyrev, 5) && ++ (pi->srom_fem2g.extpagain == 3)) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_HiPwrEPA; ++ else ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_rev3; ++ } ++ } ++ } ++ return tx_pwrctrl_tbl; ++} ++ ++struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi) ++{ ++ u16 base_idx[2], curr_gain[2]; ++ u8 core_no; ++ struct nphy_txgains target_gain; ++ u32 *tx_pwrctrl_tbl = NULL; ++ ++ if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) { ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, ++ curr_gain); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ ++ for (core_no = 0; core_no < 2; core_no++) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ target_gain.ipa[core_no] = ++ curr_gain[core_no] & 0x0007; ++ target_gain.pad[core_no] = ++ ((curr_gain[core_no] & 0x00F8) >> 3); ++ target_gain.pga[core_no] = ++ ((curr_gain[core_no] & 0x0F00) >> 8); ++ target_gain.txgm[core_no] = ++ ((curr_gain[core_no] & 0x7000) >> 12); ++ target_gain.txlpf[core_no] = ++ ((curr_gain[core_no] & 0x8000) >> 15); ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ target_gain.ipa[core_no] = ++ curr_gain[core_no] & 0x000F; ++ target_gain.pad[core_no] = ++ ((curr_gain[core_no] & 0x00F0) >> 4); ++ target_gain.pga[core_no] = ++ ((curr_gain[core_no] & 0x0F00) >> 8); ++ target_gain.txgm[core_no] = ++ ((curr_gain[core_no] & 0x7000) >> 12); ++ } else { ++ target_gain.ipa[core_no] = ++ curr_gain[core_no] & 0x0003; ++ target_gain.pad[core_no] = ++ ((curr_gain[core_no] & 0x000C) >> 2); ++ target_gain.pga[core_no] = ++ ((curr_gain[core_no] & 0x0070) >> 4); ++ target_gain.txgm[core_no] = ++ ((curr_gain[core_no] & 0x0380) >> 7); ++ } ++ } ++ } else { ++ uint phyrev = pi->pubpi.phy_rev; ++ ++ base_idx[0] = (read_phy_reg(pi, 0x1ed) >> 8) & 0x7f; ++ base_idx[1] = (read_phy_reg(pi, 0x1ee) >> 8) & 0x7f; ++ for (core_no = 0; core_no < 2; core_no++) { ++ if (NREV_GE(phyrev, 3)) { ++ tx_pwrctrl_tbl = ++ brcms_phy_get_tx_pwrctrl_tbl(pi); ++ if (NREV_GE(phyrev, 7)) { ++ target_gain.ipa[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 16) & 0x7; ++ target_gain.pad[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 19) & 0x1f; ++ target_gain.pga[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 24) & 0xf; ++ target_gain.txgm[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 28) & 0x7; ++ target_gain.txlpf[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 31) & 0x1; ++ } else { ++ target_gain.ipa[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 16) & 0xf; ++ target_gain.pad[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 20) & 0xf; ++ target_gain.pga[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 24) & 0xf; ++ target_gain.txgm[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 28) & 0x7; ++ } ++ } else { ++ target_gain.ipa[core_no] = ++ (nphy_tpc_txgain[base_idx[core_no]] >> ++ 16) & 0x3; ++ target_gain.pad[core_no] = ++ (nphy_tpc_txgain[base_idx[core_no]] >> ++ 18) & 0x3; ++ target_gain.pga[core_no] = ++ (nphy_tpc_txgain[base_idx[core_no]] >> ++ 20) & 0x7; ++ target_gain.txgm[core_no] = ++ (nphy_tpc_txgain[base_idx[core_no]] >> ++ 23) & 0x7; ++ } ++ } ++ } ++ ++ return target_gain; ++} ++ ++static void ++wlc_phy_iqcal_gainparams_nphy(struct brcms_phy *pi, u16 core_no, ++ struct nphy_txgains target_gain, ++ struct nphy_iqcal_params *params) ++{ ++ u8 k; ++ int idx; ++ u16 gain_index; ++ u8 band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ params->txlpf = target_gain.txlpf[core_no]; ++ ++ params->txgm = target_gain.txgm[core_no]; ++ params->pga = target_gain.pga[core_no]; ++ params->pad = target_gain.pad[core_no]; ++ params->ipa = target_gain.ipa[core_no]; ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ params->cal_gain = ++ ((params->txlpf << 15) | (params->txgm << 12) | ++ (params->pga << 8) | ++ (params->pad << 3) | (params->ipa)); ++ else ++ params->cal_gain = ++ ((params->txgm << 12) | (params->pga << 8) | ++ (params->pad << 4) | (params->ipa)); ++ ++ params->ncorr[0] = 0x79; ++ params->ncorr[1] = 0x79; ++ params->ncorr[2] = 0x79; ++ params->ncorr[3] = 0x79; ++ params->ncorr[4] = 0x79; ++ } else { ++ ++ gain_index = ((target_gain.pad[core_no] << 0) | ++ (target_gain.pga[core_no] << 4) | ++ (target_gain.txgm[core_no] << 8)); ++ ++ idx = -1; ++ for (k = 0; k < NPHY_IQCAL_NUMGAINS; k++) { ++ if (tbl_iqcal_gainparams_nphy[band_idx][k][0] == ++ gain_index) { ++ idx = k; ++ break; ++ } ++ } ++ ++ params->txgm = tbl_iqcal_gainparams_nphy[band_idx][k][1]; ++ params->pga = tbl_iqcal_gainparams_nphy[band_idx][k][2]; ++ params->pad = tbl_iqcal_gainparams_nphy[band_idx][k][3]; ++ params->cal_gain = ((params->txgm << 7) | (params->pga << 4) | ++ (params->pad << 2)); ++ params->ncorr[0] = tbl_iqcal_gainparams_nphy[band_idx][k][4]; ++ params->ncorr[1] = tbl_iqcal_gainparams_nphy[band_idx][k][5]; ++ params->ncorr[2] = tbl_iqcal_gainparams_nphy[band_idx][k][6]; ++ params->ncorr[3] = tbl_iqcal_gainparams_nphy[band_idx][k][7]; ++ } ++} ++ ++static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi) ++{ ++ u16 jtag_core, core; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ for (core = 0; core <= 1; core++) { ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MASTER); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ IQCAL_VCM_HG); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ IQCAL_IDAC); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSI_VCM); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] = 0; ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MUX); ++ ++ if (pi->pubpi.radiorev != 5) ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, ++ core, ++ TSSIA); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSI_MISC1); ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MASTER, 0x0a); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ IQCAL_VCM_HG, 0x43); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ IQCAL_IDAC, 0x55); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSI_VCM, 0x00); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSIG, 0x00); ++ if (pi->use_int_tx_iqlo_cal_nphy) { ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, ++ core, TX_SSI_MUX, 0x4); ++ if (!(pi-> ++ internal_tx_iqlo_cal_tapoff_intpa_nphy)) ++ WRITE_RADIO_REG3(pi, RADIO_2057, ++ TX, core, ++ TSSIA, 0x31); ++ else ++ WRITE_RADIO_REG3(pi, RADIO_2057, ++ TX, core, ++ TSSIA, 0x21); ++ } ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSI_MISC1, 0x00); ++ } else { ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MASTER, 0x06); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ IQCAL_VCM_HG, 0x43); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ IQCAL_IDAC, 0x55); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSI_VCM, 0x00); ++ ++ if (pi->pubpi.radiorev != 5) ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, ++ core, TSSIA, 0x00); ++ if (pi->use_int_tx_iqlo_cal_nphy) { ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, ++ core, TX_SSI_MUX, ++ 0x06); ++ if (!(pi-> ++ internal_tx_iqlo_cal_tapoff_intpa_nphy)) ++ WRITE_RADIO_REG3(pi, RADIO_2057, ++ TX, core, ++ TSSIG, 0x31); ++ else ++ WRITE_RADIO_REG3(pi, RADIO_2057, ++ TX, core, ++ TSSIG, 0x21); ++ } ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSI_MISC1, 0x00); ++ } ++ } ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ for (core = 0; core <= 1; core++) { ++ jtag_core = ++ (core == ++ PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1; ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MASTER | ++ jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_IQCAL_VCM_HG | ++ jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_IQCAL_IDAC | ++ jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] = ++ read_radio_reg( ++ pi, ++ RADIO_2056_TX_TSSI_VCM | ++ jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TX_AMP_DET | ++ jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MUX | ++ jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TSSIA | jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TSSIG | jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC1 | ++ jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 9] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC2 | ++ jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 10] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC3 | ++ jtag_core); ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MASTER | ++ jtag_core, 0x0a); ++ write_radio_reg(pi, ++ RADIO_2056_TX_IQCAL_VCM_HG | ++ jtag_core, 0x40); ++ write_radio_reg(pi, ++ RADIO_2056_TX_IQCAL_IDAC | ++ jtag_core, 0x55); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_VCM | ++ jtag_core, 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_AMP_DET | ++ jtag_core, 0x00); ++ ++ if (PHY_IPA(pi)) { ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TX_SSI_MUX ++ | jtag_core, 0x4); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSIA | ++ jtag_core, 0x1); ++ } else { ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TX_SSI_MUX ++ | jtag_core, 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSIA | ++ jtag_core, 0x2f); ++ } ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSIG | jtag_core, ++ 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC1 | ++ jtag_core, 0x00); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC2 | ++ jtag_core, 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC3 | ++ jtag_core, 0x00); ++ } else { ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MASTER | ++ jtag_core, 0x06); ++ write_radio_reg(pi, ++ RADIO_2056_TX_IQCAL_VCM_HG | ++ jtag_core, 0x40); ++ write_radio_reg(pi, ++ RADIO_2056_TX_IQCAL_IDAC | ++ jtag_core, 0x55); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_VCM | ++ jtag_core, 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_AMP_DET | ++ jtag_core, 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSIA | jtag_core, ++ 0x00); ++ ++ if (PHY_IPA(pi)) { ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TX_SSI_MUX ++ | jtag_core, 0x06); ++ if (NREV_LT(pi->pubpi.phy_rev, 5)) ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TSSIG ++ | jtag_core, ++ 0x11); ++ else ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TSSIG ++ | jtag_core, ++ 0x1); ++ } else { ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TX_SSI_MUX ++ | jtag_core, 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSIG | ++ jtag_core, 0x20); ++ } ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC1 | ++ jtag_core, 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC2 | ++ jtag_core, 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC3 | ++ jtag_core, 0x00); ++ } ++ } ++ } else { ++ ++ pi->tx_rx_cal_radio_saveregs[0] = ++ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1); ++ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x29); ++ pi->tx_rx_cal_radio_saveregs[1] = ++ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2); ++ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x54); ++ ++ pi->tx_rx_cal_radio_saveregs[2] = ++ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1); ++ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x29); ++ pi->tx_rx_cal_radio_saveregs[3] = ++ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2); ++ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x54); ++ ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1); ++ pi->tx_rx_cal_radio_saveregs[5] = ++ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2); ++ ++ if ((read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand) == ++ 0) { ++ ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04); ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04); ++ } else { ++ ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x20); ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x20); ++ } ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) { ++ ++ or_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0x20); ++ or_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0x20); ++ } else { ++ ++ and_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0xdf); ++ and_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0xdf); ++ } ++ } ++} ++ ++static void wlc_phy_txcal_radio_cleanup_nphy(struct brcms_phy *pi) ++{ ++ u16 jtag_core, core; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ for (core = 0; core <= 1; core++) { ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MASTER, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 0]); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 1]); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 2]); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 3]); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TX_SSI_MUX, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 5]); ++ ++ if (pi->pubpi.radiorev != 5) ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSIA, ++ pi->tx_rx_cal_radio_saveregs ++ [(core * 11) + 6]); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 7]); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 8]); ++ } ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ for (core = 0; core <= 1; core++) { ++ jtag_core = (core == PHY_CORE_0) ? ++ RADIO_2056_TX0 : RADIO_2056_TX1; ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MASTER | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 0]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_IQCAL_VCM_HG | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 1]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_IQCAL_IDAC | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 2]); ++ ++ write_radio_reg(pi, RADIO_2056_TX_TSSI_VCM | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 3]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_AMP_DET | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 4]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MUX | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 5]); ++ ++ write_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 6]); ++ ++ write_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 7]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC1 | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 8]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC2 | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 9]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC3 | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 10]); ++ } ++ } else { ++ ++ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, ++ pi->tx_rx_cal_radio_saveregs[0]); ++ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, ++ pi->tx_rx_cal_radio_saveregs[1]); ++ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, ++ pi->tx_rx_cal_radio_saveregs[2]); ++ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, ++ pi->tx_rx_cal_radio_saveregs[3]); ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, ++ pi->tx_rx_cal_radio_saveregs[4]); ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, ++ pi->tx_rx_cal_radio_saveregs[5]); ++ } ++} ++ ++static void wlc_phy_txcal_physetup_nphy(struct brcms_phy *pi) ++{ ++ u16 val, mask; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6); ++ pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7); ++ ++ mask = ((0x3 << 8) | (0x3 << 10)); ++ val = (0x2 << 8); ++ val |= (0x2 << 10); ++ mod_phy_reg(pi, 0xa6, mask, val); ++ mod_phy_reg(pi, 0xa7, mask, val); ++ ++ val = read_phy_reg(pi, 0x8f); ++ pi->tx_rx_cal_phy_saveregs[2] = val; ++ val |= ((0x1 << 9) | (0x1 << 10)); ++ write_phy_reg(pi, 0x8f, val); ++ ++ val = read_phy_reg(pi, 0xa5); ++ pi->tx_rx_cal_phy_saveregs[3] = val; ++ val |= ((0x1 << 9) | (0x1 << 10)); ++ write_phy_reg(pi, 0xa5, val); ++ ++ pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x01); ++ mod_phy_reg(pi, 0x01, (0x1 << 15), 0); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16, ++ &val); ++ pi->tx_rx_cal_phy_saveregs[5] = val; ++ val = 0; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16, ++ &val); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16, ++ &val); ++ pi->tx_rx_cal_phy_saveregs[6] = val; ++ val = 0; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16, ++ &val); ++ ++ pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0x91); ++ pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0x92); ++ ++ if (!(pi->use_int_tx_iqlo_cal_nphy)) ++ wlc_phy_rfctrlintc_override_nphy( ++ pi, ++ NPHY_RfctrlIntc_override_PA, ++ 1, ++ RADIO_MIMO_CORESEL_CORE1 ++ | ++ RADIO_MIMO_CORESEL_CORE2); ++ else ++ wlc_phy_rfctrlintc_override_nphy( ++ pi, ++ NPHY_RfctrlIntc_override_PA, ++ 0, ++ RADIO_MIMO_CORESEL_CORE1 ++ | ++ RADIO_MIMO_CORESEL_CORE2); ++ ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ 0x2, RADIO_MIMO_CORESEL_CORE1); ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ 0x8, RADIO_MIMO_CORESEL_CORE2); ++ ++ pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297); ++ pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b); ++ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (0) << 0); ++ ++ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (0) << 0); ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7) ++ || NREV_GE(pi->pubpi.phy_rev, 8)) ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 7), ++ wlc_phy_read_lpf_bw_ctl_nphy ++ (pi, ++ 0), 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ ++ if (pi->use_int_tx_iqlo_cal_nphy ++ && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) { ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7)) { ++ ++ mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4, ++ 1 << 4); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ mod_radio_reg( ++ pi, ++ RADIO_2057_PAD2G_TUNE_PUS_CORE0, ++ 1, 0); ++ mod_radio_reg( ++ pi, ++ RADIO_2057_PAD2G_TUNE_PUS_CORE1, ++ 1, 0); ++ } else { ++ mod_radio_reg( ++ pi, ++ RADIO_2057_IPA5G_CASCOFFV_PU_CORE0, ++ 1, 0); ++ mod_radio_reg( ++ pi, ++ RADIO_2057_IPA5G_CASCOFFV_PU_CORE1, ++ 1, 0); ++ } ++ } else if (NREV_GE(pi->pubpi.phy_rev, 8)) { ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, ++ (0x1 << 3), 0, ++ 0x3, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ } ++ } ++ } else { ++ pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6); ++ pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7); ++ ++ mask = ((0x3 << 12) | (0x3 << 14)); ++ val = (0x2 << 12); ++ val |= (0x2 << 14); ++ mod_phy_reg(pi, 0xa6, mask, val); ++ mod_phy_reg(pi, 0xa7, mask, val); ++ ++ val = read_phy_reg(pi, 0xa5); ++ pi->tx_rx_cal_phy_saveregs[2] = val; ++ val |= ((0x1 << 12) | (0x1 << 13)); ++ write_phy_reg(pi, 0xa5, val); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16, ++ &val); ++ pi->tx_rx_cal_phy_saveregs[3] = val; ++ val |= 0x2000; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16, ++ &val); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16, ++ &val); ++ pi->tx_rx_cal_phy_saveregs[4] = val; ++ val |= 0x2000; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16, ++ &val); ++ ++ pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x91); ++ pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x92); ++ val = CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120; ++ write_phy_reg(pi, 0x91, val); ++ write_phy_reg(pi, 0x92, val); ++ } ++} ++ ++static void wlc_phy_txcal_phycleanup_nphy(struct brcms_phy *pi) ++{ ++ u16 mask; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ write_phy_reg(pi, 0xa6, pi->tx_rx_cal_phy_saveregs[0]); ++ write_phy_reg(pi, 0xa7, pi->tx_rx_cal_phy_saveregs[1]); ++ write_phy_reg(pi, 0x8f, pi->tx_rx_cal_phy_saveregs[2]); ++ write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[3]); ++ write_phy_reg(pi, 0x01, pi->tx_rx_cal_phy_saveregs[4]); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16, ++ &pi->tx_rx_cal_phy_saveregs[5]); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16, ++ &pi->tx_rx_cal_phy_saveregs[6]); ++ ++ write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[7]); ++ write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[8]); ++ ++ write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]); ++ write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]); ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7) ++ || NREV_GE(pi->pubpi.phy_rev, 8)) ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 7), 0, 0, ++ 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ ++ wlc_phy_resetcca_nphy(pi); ++ ++ if (pi->use_int_tx_iqlo_cal_nphy ++ && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) { ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7)) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ mod_radio_reg( ++ pi, ++ RADIO_2057_PAD2G_TUNE_PUS_CORE0, ++ 1, 1); ++ mod_radio_reg( ++ pi, ++ RADIO_2057_PAD2G_TUNE_PUS_CORE1, ++ 1, 1); ++ } else { ++ mod_radio_reg( ++ pi, ++ RADIO_2057_IPA5G_CASCOFFV_PU_CORE0, ++ 1, 1); ++ mod_radio_reg( ++ pi, ++ RADIO_2057_IPA5G_CASCOFFV_PU_CORE1, ++ 1, 1); ++ } ++ ++ mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4, ++ 0); ++ } else if (NREV_GE(pi->pubpi.phy_rev, 8)) { ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, ++ (0x1 << 3), 0, ++ 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ } ++ } ++ } else { ++ mask = ((0x3 << 12) | (0x3 << 14)); ++ mod_phy_reg(pi, 0xa6, mask, pi->tx_rx_cal_phy_saveregs[0]); ++ mod_phy_reg(pi, 0xa7, mask, pi->tx_rx_cal_phy_saveregs[1]); ++ write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[2]); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16, ++ &pi->tx_rx_cal_phy_saveregs[3]); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16, ++ &pi->tx_rx_cal_phy_saveregs[4]); ++ ++ write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[5]); ++ write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[6]); ++ } ++} ++ ++void ++wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, u8 num_samps) ++{ ++ u16 tssi_reg; ++ s32 temp, pwrindex[2]; ++ s32 idle_tssi[2]; ++ s32 rssi_buf[4]; ++ s32 tssival[2]; ++ u8 tssi_type; ++ ++ tssi_reg = read_phy_reg(pi, 0x1e9); ++ ++ temp = (s32) (tssi_reg & 0x3f); ++ idle_tssi[0] = (temp <= 31) ? temp : (temp - 64); ++ ++ temp = (s32) ((tssi_reg >> 8) & 0x3f); ++ idle_tssi[1] = (temp <= 31) ? temp : (temp - 64); ++ ++ tssi_type = ++ CHSPEC_IS5G(pi->radio_chanspec) ? ++ (u8)NPHY_RSSI_SEL_TSSI_5G : (u8)NPHY_RSSI_SEL_TSSI_2G; ++ ++ wlc_phy_poll_rssi_nphy(pi, tssi_type, rssi_buf, num_samps); ++ ++ tssival[0] = rssi_buf[0] / ((s32) num_samps); ++ tssival[1] = rssi_buf[2] / ((s32) num_samps); ++ ++ pwrindex[0] = idle_tssi[0] - tssival[0] + 64; ++ pwrindex[1] = idle_tssi[1] - tssival[1] + 64; ++ ++ if (pwrindex[0] < 0) ++ pwrindex[0] = 0; ++ else if (pwrindex[0] > 63) ++ pwrindex[0] = 63; ++ ++ if (pwrindex[1] < 0) ++ pwrindex[1] = 0; ++ else if (pwrindex[1] > 63) ++ pwrindex[1] = 63; ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 1, ++ (u32) pwrindex[0], 32, &qdBm_pwrbuf[0]); ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 1, ++ (u32) pwrindex[1], 32, &qdBm_pwrbuf[1]); ++} ++ ++static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core) ++{ ++ int index; ++ u32 bbmult_scale; ++ u16 bbmult; ++ u16 tblentry; ++ ++ struct nphy_txiqcal_ladder ladder_lo[] = { ++ {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0}, ++ {25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5}, ++ {25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7} ++ }; ++ ++ struct nphy_txiqcal_ladder ladder_iq[] = { ++ {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0}, ++ {25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1}, ++ {100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7} ++ }; ++ ++ bbmult = (core == PHY_CORE_0) ? ++ ((pi->nphy_txcal_bbmult >> 8) & 0xff) : ++ (pi->nphy_txcal_bbmult & 0xff); ++ ++ for (index = 0; index < 18; index++) { ++ bbmult_scale = ladder_lo[index].percent * bbmult; ++ bbmult_scale /= 100; ++ ++ tblentry = ++ ((bbmult_scale & 0xff) << 8) | ladder_lo[index].g_env; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index, 16, ++ &tblentry); ++ ++ bbmult_scale = ladder_iq[index].percent * bbmult; ++ bbmult_scale /= 100; ++ ++ tblentry = ++ ((bbmult_scale & 0xff) << 8) | ladder_iq[index].g_env; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index + 32, ++ 16, &tblentry); ++ } ++} ++ ++static u8 wlc_phy_txpwr_idx_cur_get_nphy(struct brcms_phy *pi, u8 core) ++{ ++ u16 tmp; ++ tmp = read_phy_reg(pi, ((core == PHY_CORE_0) ? 0x1ed : 0x1ee)); ++ ++ tmp = (tmp & (0x7f << 8)) >> 8; ++ return (u8) tmp; ++} ++ ++static void ++wlc_phy_txpwr_idx_cur_set_nphy(struct brcms_phy *pi, u8 idx0, u8 idx1) ++{ ++ mod_phy_reg(pi, 0x1e7, (0x7f << 0), idx0); ++ ++ if (NREV_GT(pi->pubpi.phy_rev, 1)) ++ mod_phy_reg(pi, 0x222, (0xff << 0), idx1); ++} ++ ++static u16 wlc_phy_ipa_get_bbmult_nphy(struct brcms_phy *pi) ++{ ++ u16 m0m1; ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1); ++ ++ return m0m1; ++} ++ ++static void wlc_phy_ipa_set_bbmult_nphy(struct brcms_phy *pi, u8 m0, u8 m1) ++{ ++ u16 m0m1 = (u16) ((m0 << 8) | m1); ++ ++ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m0m1); ++ wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &m0m1); ++} ++ ++static void ++wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi, ++ struct nphy_papd_restore_state *state, u8 core) ++{ ++ s32 tone_freq; ++ u8 off_core; ++ u16 mixgain = 0; ++ ++ off_core = core ^ 0x1; ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7) ++ || NREV_GE(pi->pubpi.phy_rev, 8)) ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 7), ++ wlc_phy_read_lpf_bw_ctl_nphy ++ (pi, ++ 0), 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (pi->pubpi.radiorev == 5) ++ mixgain = (core == 0) ? 0x20 : 0x00; ++ else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) ++ mixgain = 0x00; ++ else if ((pi->pubpi.radiorev <= 4) ++ || (pi->pubpi.radiorev == 6)) ++ mixgain = 0x00; ++ } else { ++ if ((pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) ++ mixgain = 0x50; ++ else if ((pi->pubpi.radiorev == 3) ++ || (pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) ++ mixgain = 0x0; ++ } ++ ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), ++ mixgain, (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_tx_pu, ++ 1, (1 << core), 0); ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_tx_pu, ++ 0, (1 << off_core), 0); ++ ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), ++ 0, 0x3, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, ++ (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, ++ (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, ++ (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0, ++ (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1, ++ (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0, ++ (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1, ++ (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), ++ 0, (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0, ++ (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ ++ state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0xa6 : 0xa7); ++ state->afeoverride[core] = ++ read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5); ++ state->afectrl[off_core] = ++ read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa7 : 0xa6); ++ state->afeoverride[off_core] = ++ read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa5 : 0x8f); ++ ++ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7), ++ (0x1 << 2), 0); ++ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f : ++ 0xa5), (0x1 << 2), (0x1 << 2)); ++ ++ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa7 : 0xa6), ++ (0x1 << 2), (0x1 << 2)); ++ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa5 : ++ 0x8f), (0x1 << 2), (0x1 << 2)); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ state->pwrup[core] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_2G_PWRUP); ++ state->atten[core] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_2G_ATTEN); ++ state->pwrup[off_core] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, ++ TXRXCOUPLE_2G_PWRUP); ++ state->atten[off_core] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, ++ TXRXCOUPLE_2G_ATTEN); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_2G_PWRUP, 0xc); ++ ++ if ((pi->pubpi.radiorev == 3) || ++ (pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_2G_ATTEN, 0xf0); ++ else if (pi->pubpi.radiorev == 5) ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_2G_ATTEN, ++ (core == 0) ? 0xf7 : 0xf2); ++ else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_2G_ATTEN, 0xf0); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core, ++ TXRXCOUPLE_2G_PWRUP, 0x0); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core, ++ TXRXCOUPLE_2G_ATTEN, 0xff); ++ } else { ++ state->pwrup[core] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_5G_PWRUP); ++ state->atten[core] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_5G_ATTEN); ++ state->pwrup[off_core] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, ++ TXRXCOUPLE_5G_PWRUP); ++ state->atten[off_core] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, ++ TXRXCOUPLE_5G_ATTEN); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_5G_PWRUP, 0xc); ++ ++ if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_5G_ATTEN, 0xf4); ++ ++ else ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_5G_ATTEN, 0xf0); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core, ++ TXRXCOUPLE_5G_PWRUP, 0x0); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core, ++ TXRXCOUPLE_5G_ATTEN, 0xff); ++ } ++ ++ tone_freq = 4000; ++ ++ wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 13), (1) << 13); ++ ++ mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_OFF) << 0); ++ ++ mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 13), (0) << 13); ++ ++ } else { ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 0); ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0, 0); ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 0); ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 1, 0x3, 0); ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0x3, 0); ++ ++ state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0xa6 : 0xa7); ++ state->afeoverride[core] = ++ read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5); ++ ++ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7), ++ (0x1 << 0) | (0x1 << 1) | (0x1 << 2), 0); ++ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f : ++ 0xa5), ++ (0x1 << 0) | ++ (0x1 << 1) | ++ (0x1 << 2), (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); ++ ++ state->vga_master[core] = ++ READ_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER); ++ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, 0x2b); ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ state->fbmix[core] = ++ READ_RADIO_REG2(pi, RADIO_2056, RX, core, ++ TXFBMIX_G); ++ state->intpa_master[core] = ++ READ_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_MASTER); ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_G, ++ 0x03); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_MASTER, 0x04); ++ } else { ++ state->fbmix[core] = ++ READ_RADIO_REG2(pi, RADIO_2056, RX, core, ++ TXFBMIX_A); ++ state->intpa_master[core] = ++ READ_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAA_MASTER); ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_A, ++ 0x03); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAA_MASTER, 0x04); ++ ++ } ++ ++ tone_freq = 4000; ++ ++ wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (1) << 0); ++ ++ mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (0) << 0); ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0); ++ } ++} ++ ++static void ++wlc_phy_papd_cal_cleanup_nphy(struct brcms_phy *pi, ++ struct nphy_papd_restore_state *state) ++{ ++ u8 core; ++ ++ wlc_phy_stopplayback_nphy(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_2G_PWRUP, 0); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_2G_ATTEN, ++ state->atten[core]); ++ } else { ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_5G_PWRUP, 0); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_5G_ATTEN, ++ state->atten[core]); ++ } ++ } ++ ++ if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 2), ++ 1, 0x3, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ else ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 2), ++ 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), ++ 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ ++ write_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0xa6 : 0xa7, state->afectrl[core]); ++ write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : ++ 0xa5, state->afeoverride[core]); ++ } ++ ++ wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff, ++ (state->mm & 0xff)); ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7) ++ || NREV_GE(pi->pubpi.phy_rev, 8)) ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 7), 0, 0, ++ 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ } else { ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1); ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 0x3, 1); ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 1); ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 0, 0x3, 1); ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 0, 0x3, 1); ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, ++ state->vga_master[core]); ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, ++ TXFBMIX_G, state->fbmix[core]); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_MASTER, ++ state->intpa_master[core]); ++ } else { ++ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, ++ TXFBMIX_A, state->fbmix[core]); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAA_MASTER, ++ state->intpa_master[core]); ++ } ++ ++ write_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0xa6 : 0xa7, state->afectrl[core]); ++ write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : ++ 0xa5, state->afeoverride[core]); ++ } ++ ++ wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff, ++ (state->mm & 0xff)); ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 1); ++ } ++} ++ ++static void ++wlc_phy_a1_nphy(struct brcms_phy *pi, u8 core, u32 winsz, u32 start, ++ u32 end) ++{ ++ u32 *buf, *src, *dst, sz; ++ ++ sz = end - start + 1; ++ ++ buf = kmalloc(2 * sizeof(u32) * NPHY_PAPD_EPS_TBL_SIZE, GFP_ATOMIC); ++ if (NULL == buf) ++ return; ++ ++ src = buf; ++ dst = buf + NPHY_PAPD_EPS_TBL_SIZE; ++ ++ wlc_phy_table_read_nphy(pi, ++ (core == ++ PHY_CORE_0 ? NPHY_TBL_ID_EPSILONTBL0 : ++ NPHY_TBL_ID_EPSILONTBL1), ++ NPHY_PAPD_EPS_TBL_SIZE, 0, 32, src); ++ ++ do { ++ u32 phy_a1, phy_a2; ++ s32 phy_a3, phy_a4, phy_a5, phy_a6, phy_a7; ++ ++ phy_a1 = end - min(end, (winsz >> 1)); ++ phy_a2 = min_t(u32, NPHY_PAPD_EPS_TBL_SIZE - 1, ++ end + (winsz >> 1)); ++ phy_a3 = phy_a2 - phy_a1 + 1; ++ phy_a6 = 0; ++ phy_a7 = 0; ++ ++ do { ++ wlc_phy_papd_decode_epsilon(src[phy_a2], &phy_a4, ++ &phy_a5); ++ phy_a6 += phy_a4; ++ phy_a7 += phy_a5; ++ } while (phy_a2-- != phy_a1); ++ ++ phy_a6 /= phy_a3; ++ phy_a7 /= phy_a3; ++ dst[end] = ((u32) phy_a7 << 13) | ((u32) phy_a6 & 0x1fff); ++ } while (end-- != start); ++ ++ wlc_phy_table_write_nphy(pi, ++ (core == ++ PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 : ++ NPHY_TBL_ID_EPSILONTBL1, sz, start, 32, dst); ++ ++ kfree(buf); ++} ++ ++static void ++wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains, ++ enum phy_cal_mode cal_mode, u8 core) ++{ ++ u16 phy_a1, phy_a2, phy_a3; ++ u16 phy_a4, phy_a5; ++ bool phy_a6; ++ u8 phy_a7, m[2]; ++ u32 phy_a8 = 0; ++ struct nphy_txgains phy_a9; ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) ++ return; ++ ++ phy_a7 = (core == PHY_CORE_0) ? 1 : 0; ++ ++ phy_a6 = ((cal_mode == CAL_GCTRL) ++ || (cal_mode == CAL_SOFT)) ? true : false; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ phy_a9 = wlc_phy_get_tx_gain_nphy(pi); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ phy_a5 = ((phy_a9.txlpf[core] << 15) | ++ (phy_a9.txgm[core] << 12) | ++ (phy_a9.pga[core] << 8) | ++ (txgains->gains.pad[core] << 3) | ++ (phy_a9.ipa[core])); ++ else ++ phy_a5 = ((phy_a9.txlpf[core] << 15) | ++ (phy_a9.txgm[core] << 12) | ++ (txgains->gains.pga[core] << 8) | ++ (phy_a9.pad[core] << 3) | (phy_a9.ipa[core])); ++ ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_txgain, ++ phy_a5, (1 << core), 0); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if ((pi->pubpi.radiorev <= 4) ++ || (pi->pubpi.radiorev == 6)) ++ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? ++ 60 : 79; ++ else ++ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? ++ 45 : 64; ++ } else { ++ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 75 : 107; ++ } ++ ++ m[phy_a7] = 0; ++ wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]); ++ ++ phy_a2 = 63; ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if ((pi->pubpi.radiorev == 4) ++ || (pi->pubpi.radiorev == 6)) { ++ phy_a1 = 30; ++ phy_a3 = 30; ++ } else { ++ phy_a1 = 25; ++ phy_a3 = 25; ++ } ++ } else { ++ if ((pi->pubpi.radiorev == 5) ++ || (pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) { ++ phy_a1 = 25; ++ phy_a3 = 25; ++ } else { ++ phy_a1 = 35; ++ phy_a3 = 35; ++ } ++ } ++ ++ if (cal_mode == CAL_GCTRL) { ++ if ((pi->pubpi.radiorev == 5) ++ && (CHSPEC_IS2G(pi->radio_chanspec))) ++ phy_a1 = 55; ++ else if (((pi->pubpi.radiorev == 7) && ++ (CHSPEC_IS2G(pi->radio_chanspec))) || ++ ((pi->pubpi.radiorev == 8) && ++ (CHSPEC_IS2G(pi->radio_chanspec)))) ++ phy_a1 = 60; ++ else ++ phy_a1 = 63; ++ ++ } else if ((cal_mode != CAL_FULL) && (cal_mode != CAL_SOFT)) { ++ ++ phy_a1 = 35; ++ phy_a3 = 35; ++ } ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (1) << 0); ++ ++ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (0) << 0); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 13), (1) << 13); ++ ++ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 13), (0) << 13); ++ ++ write_phy_reg(pi, 0x2a1, 0x80); ++ write_phy_reg(pi, 0x2a2, 0x100); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x7 << 4), (11) << 4); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x7 << 8), (11) << 8); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x7 << 0), (0x3) << 0); ++ ++ write_phy_reg(pi, 0x2e5, 0x20); ++ ++ mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0); ++ ++ mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0); ++ ++ mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8); ++ ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), ++ 1, ((core == 0) ? 1 : 2), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), ++ 0, ((core == 0) ? 2 : 1), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ ++ write_phy_reg(pi, 0x2be, 1); ++ SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000); ++ ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), ++ 0, 0x3, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ ++ wlc_phy_table_write_nphy(pi, ++ (core == ++ PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 ++ : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3, ++ 32, &phy_a8); ++ ++ if (cal_mode != CAL_GCTRL) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) ++ wlc_phy_a1_nphy(pi, core, 5, 0, 35); ++ } ++ ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_txgain, ++ phy_a5, (1 << core), 1); ++ ++ } else { ++ ++ if (txgains) { ++ if (txgains->useindex) { ++ phy_a4 = 15 - ((txgains->index) >> 3); ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 6)) ++ phy_a5 = 0x00f7 | (phy_a4 << 8); ++ ++ else ++ if (NREV_IS(pi->pubpi.phy_rev, 5)) ++ phy_a5 = 0x10f7 | (phy_a4 << 8); ++ else ++ phy_a5 = 0x50f7 | (phy_a4 << 8); ++ } else { ++ phy_a5 = 0x70f7 | (phy_a4 << 8); ++ } ++ wlc_phy_rfctrl_override_nphy(pi, ++ (0x1 << 13), ++ phy_a5, ++ (1 << core), 0); ++ } else { ++ wlc_phy_rfctrl_override_nphy(pi, ++ (0x1 << 13), ++ 0x5bf7, ++ (1 << core), 0); ++ } ++ } ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 45 : 64; ++ else ++ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 75 : 107; ++ ++ m[phy_a7] = 0; ++ wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]); ++ ++ phy_a2 = 63; ++ ++ if (cal_mode == CAL_FULL) { ++ phy_a1 = 25; ++ phy_a3 = 25; ++ } else if (cal_mode == CAL_SOFT) { ++ phy_a1 = 25; ++ phy_a3 = 25; ++ } else if (cal_mode == CAL_GCTRL) { ++ phy_a1 = 63; ++ phy_a3 = 25; ++ } else { ++ ++ phy_a1 = 25; ++ phy_a3 = 25; ++ } ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (1) << 0); ++ ++ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (0) << 0); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 6)) { ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 13), (1) << 13); ++ ++ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 13), (0) << 13); ++ ++ write_phy_reg(pi, 0x2a1, 0x20); ++ write_phy_reg(pi, 0x2a2, 0x60); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0xf << 4), (9) << 4); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0xf << 8), (9) << 8); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0xf << 0), (0x2) << 0); ++ ++ write_phy_reg(pi, 0x2e5, 0x20); ++ } else { ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 11), (1) << 11); ++ ++ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 11), (0) << 11); ++ ++ write_phy_reg(pi, 0x2a1, 0x80); ++ write_phy_reg(pi, 0x2a2, 0x600); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x7 << 4), (0) << 4); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x7 << 8), (0) << 8); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x7 << 0), (0x3) << 0); ++ ++ mod_phy_reg(pi, 0x2a0, (0x3f << 8), (0x20) << 8); ++ ++ } ++ ++ mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0); ++ ++ mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0); ++ ++ mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8); ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0x3, 0); ++ ++ write_phy_reg(pi, 0x2be, 1); ++ SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000); ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0); ++ ++ wlc_phy_table_write_nphy(pi, ++ (core == ++ PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 ++ : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3, ++ 32, &phy_a8); ++ ++ if (cal_mode != CAL_GCTRL) ++ wlc_phy_a1_nphy(pi, core, 5, 0, 40); ++ } ++} ++ ++static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core) ++{ ++ int phy_a1; ++ int phy_a2; ++ bool phy_a3; ++ struct nphy_ipa_txcalgains phy_a4; ++ bool phy_a5 = false; ++ bool phy_a6 = true; ++ s32 phy_a7, phy_a8; ++ u32 phy_a9; ++ int phy_a10; ++ bool phy_a11 = false; ++ int phy_a12; ++ u8 phy_a13 = 0; ++ u8 phy_a14; ++ u8 *phy_a15 = NULL; ++ ++ phy_a4.useindex = true; ++ phy_a12 = start_gain; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ phy_a2 = 20; ++ phy_a1 = 1; ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (pi->pubpi.radiorev == 5) { ++ ++ phy_a15 = pad_gain_codes_used_2057rev5; ++ phy_a13 = ++ sizeof(pad_gain_codes_used_2057rev5) / ++ sizeof(pad_gain_codes_used_2057rev5 ++ [0]) - 1; ++ ++ } else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) { ++ ++ phy_a15 = pad_gain_codes_used_2057rev7; ++ phy_a13 = ++ sizeof(pad_gain_codes_used_2057rev7) / ++ sizeof(pad_gain_codes_used_2057rev7 ++ [0]) - 1; ++ ++ } else { ++ ++ phy_a15 = pad_all_gain_codes_2057; ++ phy_a13 = sizeof(pad_all_gain_codes_2057) / ++ sizeof(pad_all_gain_codes_2057[0]) - ++ 1; ++ } ++ ++ } else { ++ ++ phy_a15 = pga_all_gain_codes_2057; ++ phy_a13 = sizeof(pga_all_gain_codes_2057) / ++ sizeof(pga_all_gain_codes_2057[0]) - 1; ++ } ++ ++ phy_a14 = 0; ++ ++ for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ phy_a4.gains.pad[core] = ++ (u16) phy_a15[phy_a12]; ++ else ++ phy_a4.gains.pga[core] = ++ (u16) phy_a15[phy_a12]; ++ ++ wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core); ++ ++ wlc_phy_table_read_nphy(pi, ++ (core == ++ PHY_CORE_0 ? ++ NPHY_TBL_ID_EPSILONTBL0 : ++ NPHY_TBL_ID_EPSILONTBL1), 1, ++ 63, 32, &phy_a9); ++ ++ wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8); ++ ++ phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) || ++ (phy_a8 == 4095) || (phy_a8 == -4096)); ++ ++ if (!phy_a6 && (phy_a3 != phy_a5)) { ++ if (!phy_a3) ++ phy_a12 -= (u8) phy_a1; ++ ++ phy_a11 = true; ++ break; ++ } ++ ++ if (phy_a3) ++ phy_a12 += (u8) phy_a1; ++ else ++ phy_a12 -= (u8) phy_a1; ++ ++ if ((phy_a12 < phy_a14) || (phy_a12 > phy_a13)) { ++ if (phy_a12 < phy_a14) ++ phy_a12 = phy_a14; ++ else ++ phy_a12 = phy_a13; ++ ++ phy_a11 = true; ++ break; ++ } ++ ++ phy_a6 = false; ++ phy_a5 = phy_a3; ++ } ++ ++ } else { ++ phy_a2 = 10; ++ phy_a1 = 8; ++ for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) { ++ phy_a4.index = (u8) phy_a12; ++ wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core); ++ ++ wlc_phy_table_read_nphy(pi, ++ (core == ++ PHY_CORE_0 ? ++ NPHY_TBL_ID_EPSILONTBL0 : ++ NPHY_TBL_ID_EPSILONTBL1), 1, ++ 63, 32, &phy_a9); ++ ++ wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8); ++ ++ phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) || ++ (phy_a8 == 4095) || (phy_a8 == -4096)); ++ ++ if (!phy_a6 && (phy_a3 != phy_a5)) { ++ if (!phy_a3) ++ phy_a12 -= (u8) phy_a1; ++ ++ phy_a11 = true; ++ break; ++ } ++ ++ if (phy_a3) ++ phy_a12 += (u8) phy_a1; ++ else ++ phy_a12 -= (u8) phy_a1; ++ ++ if ((phy_a12 < 0) || (phy_a12 > 127)) { ++ if (phy_a12 < 0) ++ phy_a12 = 0; ++ else ++ phy_a12 = 127; ++ ++ phy_a11 = true; ++ break; ++ } ++ ++ phy_a6 = false; ++ phy_a5 = phy_a3; ++ } ++ ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ return (u8) phy_a15[phy_a12]; ++ else ++ return (u8) phy_a12; ++ ++} ++ ++static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal) ++{ ++ struct nphy_ipa_txcalgains phy_b1[2]; ++ struct nphy_papd_restore_state phy_b2; ++ bool phy_b3; ++ u8 phy_b4; ++ u8 phy_b5; ++ s16 phy_b6, phy_b7, phy_b8; ++ u16 phy_b9; ++ s16 phy_b10, phy_b11, phy_b12; ++ ++ phy_b11 = 0; ++ phy_b12 = 0; ++ phy_b7 = 0; ++ phy_b8 = 0; ++ phy_b6 = 0; ++ ++ if (pi->nphy_papd_skip == 1) ++ return; ++ ++ phy_b3 = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!phy_b3) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ pi->nphy_force_papd_cal = false; ++ ++ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) ++ pi->nphy_papd_tx_gain_at_last_cal[phy_b5] = ++ wlc_phy_txpwr_idx_cur_get_nphy(pi, phy_b5); ++ ++ pi->nphy_papd_last_cal = pi->sh->now; ++ pi->nphy_papd_recal_counter++; ++ ++ phy_b4 = pi->nphy_txpwrctrl; ++ wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL0, 64, 0, 32, ++ nphy_papd_scaltbl); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL1, 64, 0, 32, ++ nphy_papd_scaltbl); ++ ++ phy_b9 = read_phy_reg(pi, 0x01); ++ mod_phy_reg(pi, 0x01, (0x1 << 15), 0); ++ ++ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) { ++ s32 i, val = 0; ++ for (i = 0; i < 64; i++) ++ wlc_phy_table_write_nphy(pi, ++ ((phy_b5 == ++ PHY_CORE_0) ? ++ NPHY_TBL_ID_EPSILONTBL0 : ++ NPHY_TBL_ID_EPSILONTBL1), 1, ++ i, 32, &val); ++ } ++ ++ wlc_phy_ipa_restore_tx_digi_filts_nphy(pi); ++ ++ phy_b2.mm = wlc_phy_ipa_get_bbmult_nphy(pi); ++ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) { ++ wlc_phy_papd_cal_setup_nphy(pi, &phy_b2, phy_b5); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if ((pi->pubpi.radiorev == 3) ++ || (pi->pubpi.radiorev == 4) ++ || (pi->pubpi.radiorev == 6)) { ++ pi->nphy_papd_cal_gain_index[phy_b5] = ++ 23; ++ } else if (pi->pubpi.radiorev == 5) { ++ pi->nphy_papd_cal_gain_index[phy_b5] = ++ 0; ++ pi->nphy_papd_cal_gain_index[phy_b5] = ++ wlc_phy_a3_nphy( ++ pi, ++ pi-> ++ nphy_papd_cal_gain_index ++ [phy_b5], ++ phy_b5); ++ ++ } else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) { ++ ++ pi->nphy_papd_cal_gain_index[phy_b5] = ++ 0; ++ pi->nphy_papd_cal_gain_index[phy_b5] = ++ wlc_phy_a3_nphy( ++ pi, ++ pi-> ++ nphy_papd_cal_gain_index ++ [phy_b5], ++ phy_b5); ++ ++ } ++ ++ phy_b1[phy_b5].gains.pad[phy_b5] = ++ pi->nphy_papd_cal_gain_index[phy_b5]; ++ ++ } else { ++ pi->nphy_papd_cal_gain_index[phy_b5] = 0; ++ pi->nphy_papd_cal_gain_index[phy_b5] = ++ wlc_phy_a3_nphy( ++ pi, ++ pi-> ++ nphy_papd_cal_gain_index ++ [phy_b5], phy_b5); ++ phy_b1[phy_b5].gains.pga[phy_b5] = ++ pi->nphy_papd_cal_gain_index[phy_b5]; ++ } ++ } else { ++ phy_b1[phy_b5].useindex = true; ++ phy_b1[phy_b5].index = 16; ++ phy_b1[phy_b5].index = ++ wlc_phy_a3_nphy(pi, phy_b1[phy_b5].index, ++ phy_b5); ++ ++ pi->nphy_papd_cal_gain_index[phy_b5] = ++ 15 - ((phy_b1[phy_b5].index) >> 3); ++ } ++ ++ switch (pi->nphy_papd_cal_type) { ++ case 0: ++ wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_FULL, phy_b5); ++ break; ++ case 1: ++ wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_SOFT, phy_b5); ++ break; ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2); ++ } ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 7)) ++ wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2); ++ ++ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) { ++ int eps_offset = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (pi->pubpi.radiorev == 3) ++ eps_offset = -2; ++ else if (pi->pubpi.radiorev == 5) ++ eps_offset = 3; ++ else ++ eps_offset = -1; ++ } else { ++ eps_offset = 2; ++ } ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ phy_b8 = phy_b1[phy_b5].gains.pad[phy_b5]; ++ phy_b10 = 0; ++ if ((pi->pubpi.radiorev == 3) || ++ (pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) { ++ phy_b12 = -( ++ nphy_papd_padgain_dlt_2g_2057rev3n4 ++ [phy_b8] + 1) / 2; ++ phy_b10 = -1; ++ } else if (pi->pubpi.radiorev == 5) { ++ phy_b12 = -( ++ nphy_papd_padgain_dlt_2g_2057rev5 ++ [phy_b8] + 1) / 2; ++ } else if ((pi->pubpi.radiorev == 7) || ++ (pi->pubpi.radiorev == 8)) { ++ phy_b12 = -( ++ nphy_papd_padgain_dlt_2g_2057rev7 ++ [phy_b8] + 1) / 2; ++ } ++ } else { ++ phy_b7 = phy_b1[phy_b5].gains.pga[phy_b5]; ++ if ((pi->pubpi.radiorev == 3) || ++ (pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) ++ phy_b11 = ++ -(nphy_papd_pgagain_dlt_5g_2057 ++ [phy_b7] ++ + 1) / 2; ++ else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) ++ phy_b11 = -( ++ nphy_papd_pgagain_dlt_5g_2057rev7 ++ [phy_b7] + 1) / 2; ++ ++ phy_b10 = -9; ++ } ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ phy_b6 = ++ -60 + 27 + eps_offset + phy_b12 + ++ phy_b10; ++ else ++ phy_b6 = ++ -60 + 27 + eps_offset + phy_b11 + ++ phy_b10; ++ ++ mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 : ++ 0x29c, (0x1ff << 7), (phy_b6) << 7); ++ ++ pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6; ++ } else { ++ if (NREV_LT(pi->pubpi.phy_rev, 5)) ++ eps_offset = 4; ++ else ++ eps_offset = 2; ++ ++ phy_b7 = 15 - ((phy_b1[phy_b5].index) >> 3); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ phy_b11 = ++ -(nphy_papd_pga_gain_delta_ipa_2g[ ++ phy_b7] + ++ 1) / 2; ++ phy_b10 = 0; ++ } else { ++ phy_b11 = ++ -(nphy_papd_pga_gain_delta_ipa_5g[ ++ phy_b7] + ++ 1) / 2; ++ phy_b10 = -9; ++ } ++ ++ phy_b6 = -60 + 27 + eps_offset + phy_b11 + phy_b10; ++ ++ mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 : ++ 0x29c, (0x1ff << 7), (phy_b6) << 7); ++ ++ pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6; ++ } ++ } ++ ++ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0); ++ ++ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 6)) { ++ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 13), (0) << 13); ++ ++ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 13), (0) << 13); ++ ++ } else { ++ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 11), (0) << 11); ++ ++ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 11), (0) << 11); ++ ++ } ++ pi->nphy_papdcomp = NPHY_PAPD_COMP_ON; ++ ++ write_phy_reg(pi, 0x01, phy_b9); ++ ++ wlc_phy_ipa_set_tx_digi_filts_nphy(pi); ++ ++ wlc_phy_txpwrctrl_enable_nphy(pi, phy_b4); ++ if (phy_b4 == PHY_TPC_HW_OFF) { ++ wlc_phy_txpwr_index_nphy(pi, (1 << 0), ++ (s8) (pi->nphy_txpwrindex[0]. ++ index_internal), false); ++ wlc_phy_txpwr_index_nphy(pi, (1 << 1), ++ (s8) (pi->nphy_txpwrindex[1]. ++ index_internal), false); ++ } ++ ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ ++ if (!phy_b3) ++ wlapi_enable_mac(pi->sh->physhim); ++} ++ ++void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype) ++{ ++ struct nphy_txgains target_gain; ++ u8 tx_pwr_ctrl_state; ++ bool fullcal = true; ++ bool restore_tx_gain = false; ++ bool mphase; ++ ++ if (PHY_MUTED(pi)) ++ return; ++ ++ if (caltype == PHY_PERICAL_AUTO) ++ fullcal = (pi->radio_chanspec != pi->nphy_txiqlocal_chanspec); ++ else if (caltype == PHY_PERICAL_PARTIAL) ++ fullcal = false; ++ ++ if (pi->cal_type_override != PHY_PERICAL_AUTO) ++ fullcal = ++ (pi->cal_type_override == ++ PHY_PERICAL_FULL) ? true : false; ++ ++ if ((pi->mphase_cal_phase_id > MPHASE_CAL_STATE_INIT)) { ++ if (pi->nphy_txiqlocal_chanspec != pi->radio_chanspec) ++ wlc_phy_cal_perical_mphase_restart(pi); ++ } ++ ++ if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_RXCAL)) ++ wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000); ++ ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ wlc_phyreg_enter((struct brcms_phy_pub *) pi); ++ ++ if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_IDLE) || ++ (pi->mphase_cal_phase_id == MPHASE_CAL_STATE_INIT)) { ++ pi->nphy_cal_orig_pwr_idx[0] = ++ (u8) ((read_phy_reg(pi, 0x1ed) >> 8) & 0x7f); ++ pi->nphy_cal_orig_pwr_idx[1] = ++ (u8) ((read_phy_reg(pi, 0x1ee) >> 8) & 0x7f); ++ ++ if (pi->nphy_txpwrctrl != PHY_TPC_HW_OFF) { ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, ++ 0x110, 16, ++ pi->nphy_cal_orig_tx_gain); ++ } else { ++ pi->nphy_cal_orig_tx_gain[0] = 0; ++ pi->nphy_cal_orig_tx_gain[1] = 0; ++ } ++ } ++ target_gain = wlc_phy_get_tx_gain_nphy(pi); ++ tx_pwr_ctrl_state = pi->nphy_txpwrctrl; ++ wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF); ++ ++ if (pi->antsel_type == ANTSEL_2x3) ++ wlc_phy_antsel_init((struct brcms_phy_pub *) pi, true); ++ ++ mphase = (pi->mphase_cal_phase_id != MPHASE_CAL_STATE_IDLE); ++ if (!mphase) { ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ wlc_phy_precal_txgain_nphy(pi); ++ pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi); ++ restore_tx_gain = true; ++ ++ target_gain = pi->nphy_cal_target_gain; ++ } ++ if (0 == ++ wlc_phy_cal_txiqlo_nphy(pi, target_gain, fullcal, ++ mphase)) { ++ if (PHY_IPA(pi)) ++ wlc_phy_a4(pi, true); ++ ++ wlc_phyreg_exit((struct brcms_phy_pub *) pi); ++ wlapi_enable_mac(pi->sh->physhim); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, ++ 10000); ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ wlc_phyreg_enter((struct brcms_phy_pub *) pi); ++ ++ if (0 == wlc_phy_cal_rxiq_nphy(pi, target_gain, ++ (pi->first_cal_after_assoc || ++ (pi->cal_type_override == ++ PHY_PERICAL_FULL)) ? 2 : 0, false)) { ++ wlc_phy_savecal_nphy(pi); ++ ++ wlc_phy_txpwrctrl_coeff_setup_nphy(pi); ++ ++ pi->nphy_perical_last = pi->sh->now; ++ } ++ } ++ if (caltype != PHY_PERICAL_AUTO) ++ wlc_phy_rssi_cal_nphy(pi); ++ ++ if (pi->first_cal_after_assoc ++ || (pi->cal_type_override == PHY_PERICAL_FULL)) { ++ pi->first_cal_after_assoc = false; ++ wlc_phy_txpwrctrl_idle_tssi_nphy(pi); ++ wlc_phy_txpwrctrl_pwr_setup_nphy(pi); ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ wlc_phy_radio205x_vcocal_nphy(pi); ++ } else { ++ switch (pi->mphase_cal_phase_id) { ++ case MPHASE_CAL_STATE_INIT: ++ pi->nphy_perical_last = pi->sh->now; ++ pi->nphy_txiqlocal_chanspec = pi->radio_chanspec; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ wlc_phy_precal_txgain_nphy(pi); ++ ++ pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi); ++ pi->mphase_cal_phase_id++; ++ break; ++ ++ case MPHASE_CAL_STATE_TXPHASE0: ++ case MPHASE_CAL_STATE_TXPHASE1: ++ case MPHASE_CAL_STATE_TXPHASE2: ++ case MPHASE_CAL_STATE_TXPHASE3: ++ case MPHASE_CAL_STATE_TXPHASE4: ++ case MPHASE_CAL_STATE_TXPHASE5: ++ if ((pi->radar_percal_mask & 0x10) != 0) ++ pi->nphy_rxcal_active = true; ++ ++ if (wlc_phy_cal_txiqlo_nphy ++ (pi, pi->nphy_cal_target_gain, fullcal, ++ true) != 0) { ++ ++ wlc_phy_cal_perical_mphase_reset(pi); ++ break; ++ } ++ ++ if (NREV_LE(pi->pubpi.phy_rev, 2) && ++ (pi->mphase_cal_phase_id == ++ MPHASE_CAL_STATE_TXPHASE4)) ++ pi->mphase_cal_phase_id += 2; ++ else ++ pi->mphase_cal_phase_id++; ++ break; ++ ++ case MPHASE_CAL_STATE_PAPDCAL: ++ if ((pi->radar_percal_mask & 0x2) != 0) ++ pi->nphy_rxcal_active = true; ++ ++ if (PHY_IPA(pi)) ++ wlc_phy_a4(pi, true); ++ ++ pi->mphase_cal_phase_id++; ++ break; ++ ++ case MPHASE_CAL_STATE_RXCAL: ++ if ((pi->radar_percal_mask & 0x1) != 0) ++ pi->nphy_rxcal_active = true; ++ if (wlc_phy_cal_rxiq_nphy(pi, target_gain, ++ (pi->first_cal_after_assoc || ++ (pi->cal_type_override == ++ PHY_PERICAL_FULL)) ? 2 : 0, ++ false) == 0) ++ wlc_phy_savecal_nphy(pi); ++ ++ pi->mphase_cal_phase_id++; ++ break; ++ ++ case MPHASE_CAL_STATE_RSSICAL: ++ if ((pi->radar_percal_mask & 0x4) != 0) ++ pi->nphy_rxcal_active = true; ++ wlc_phy_txpwrctrl_coeff_setup_nphy(pi); ++ wlc_phy_rssi_cal_nphy(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ wlc_phy_radio205x_vcocal_nphy(pi); ++ ++ restore_tx_gain = true; ++ ++ if (pi->first_cal_after_assoc) ++ pi->mphase_cal_phase_id++; ++ else ++ wlc_phy_cal_perical_mphase_reset(pi); ++ ++ break; ++ ++ case MPHASE_CAL_STATE_IDLETSSI: ++ if ((pi->radar_percal_mask & 0x8) != 0) ++ pi->nphy_rxcal_active = true; ++ ++ if (pi->first_cal_after_assoc) { ++ pi->first_cal_after_assoc = false; ++ wlc_phy_txpwrctrl_idle_tssi_nphy(pi); ++ wlc_phy_txpwrctrl_pwr_setup_nphy(pi); ++ } ++ ++ wlc_phy_cal_perical_mphase_reset(pi); ++ break; ++ ++ default: ++ wlc_phy_cal_perical_mphase_reset(pi); ++ break; ++ } ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (restore_tx_gain) { ++ if (tx_pwr_ctrl_state != PHY_TPC_HW_OFF) { ++ ++ wlc_phy_txpwr_index_nphy(pi, 1, ++ pi-> ++ nphy_cal_orig_pwr_idx ++ [0], false); ++ wlc_phy_txpwr_index_nphy(pi, 2, ++ pi-> ++ nphy_cal_orig_pwr_idx ++ [1], false); ++ ++ pi->nphy_txpwrindex[0].index = -1; ++ pi->nphy_txpwrindex[1].index = -1; ++ } else { ++ wlc_phy_txpwr_index_nphy(pi, (1 << 0), ++ (s8) (pi-> ++ nphy_txpwrindex ++ [0]. ++ index_internal), ++ false); ++ wlc_phy_txpwr_index_nphy(pi, (1 << 1), ++ (s8) (pi-> ++ nphy_txpwrindex ++ [1]. ++ index_internal), ++ false); ++ } ++ } ++ } ++ ++ wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state); ++ wlc_phyreg_exit((struct brcms_phy_pub *) pi); ++ wlapi_enable_mac(pi->sh->physhim); ++} ++ ++int ++wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, ++ bool fullcal, bool mphase) ++{ ++ u16 val; ++ u16 tbl_buf[11]; ++ u8 cal_cnt; ++ u16 cal_cmd; ++ u8 num_cals, max_cal_cmds; ++ u16 core_no, cal_type; ++ u16 diq_start = 0; ++ u8 phy_bw; ++ u16 max_val; ++ u16 tone_freq; ++ u16 gain_save[2]; ++ u16 cal_gain[2]; ++ struct nphy_iqcal_params cal_params[2]; ++ u32 tbl_len; ++ void *tbl_ptr; ++ bool ladder_updated[2]; ++ u8 mphase_cal_lastphase = 0; ++ int bcmerror = 0; ++ bool phyhang_avoid_state = false; ++ ++ u16 tbl_tx_iqlo_cal_loft_ladder_20[] = { ++ 0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901, ++ 0x1902, ++ 0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607, ++ 0x6407 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = { ++ 0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400, ++ 0x3200, ++ 0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406, ++ 0x6407 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_loft_ladder_40[] = { ++ 0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201, ++ 0x1202, ++ 0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207, ++ 0x4707 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = { ++ 0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900, ++ 0x2300, ++ 0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706, ++ 0x4707 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_startcoefs[] = { ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ++ 0x0000 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_cmds_fullcal[] = { ++ 0x8123, 0x8264, 0x8086, 0x8245, 0x8056, ++ 0x9123, 0x9264, 0x9086, 0x9245, 0x9056 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_cmds_recal[] = { ++ 0x8101, 0x8253, 0x8053, 0x8234, 0x8034, ++ 0x9101, 0x9253, 0x9053, 0x9234, 0x9034 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = { ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ++ 0x0000 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { ++ 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234, ++ 0x9434, 0x9334, 0x9084, 0x9267, 0x9056, 0x9234 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = { ++ 0x8423, 0x8323, 0x8073, 0x8256, 0x8045, 0x8223, ++ 0x9423, 0x9323, 0x9073, 0x9256, 0x9045, 0x9223 ++ }; ++ ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 4)) { ++ phyhang_avoid_state = pi->phyhang_avoid; ++ pi->phyhang_avoid = false; ++ } ++ ++ if (CHSPEC_IS40(pi->radio_chanspec)) ++ phy_bw = 40; ++ else ++ phy_bw = 20; ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save); ++ ++ for (core_no = 0; core_no <= 1; core_no++) { ++ wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain, ++ &cal_params[core_no]); ++ cal_gain[core_no] = cal_params[core_no].cal_gain; ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain); ++ ++ wlc_phy_txcal_radio_setup_nphy(pi); ++ ++ wlc_phy_txcal_physetup_nphy(pi); ++ ++ ladder_updated[0] = ladder_updated[1] = false; ++ if (!(NREV_GE(pi->pubpi.phy_rev, 6) || ++ (NREV_IS(pi->pubpi.phy_rev, 5) && PHY_IPA(pi) ++ && (CHSPEC_IS2G(pi->radio_chanspec))))) { ++ ++ if (phy_bw == 40) { ++ tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_40; ++ tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_40); ++ } else { ++ tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_20; ++ tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_20); ++ } ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 0, ++ 16, tbl_ptr); ++ ++ if (phy_bw == 40) { ++ tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_40; ++ tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_40); ++ } else { ++ tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_20; ++ tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_20); ++ } ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 32, ++ 16, tbl_ptr); ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ write_phy_reg(pi, 0xc2, 0x8ad9); ++ else ++ write_phy_reg(pi, 0xc2, 0x8aa9); ++ ++ max_val = 250; ++ tone_freq = (phy_bw == 20) ? 2500 : 5000; ++ ++ if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) { ++ wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff, 0, 1, 0, false); ++ bcmerror = 0; ++ } else { ++ bcmerror = ++ wlc_phy_tx_tone_nphy(pi, tone_freq, max_val, 1, 0, ++ false); ++ } ++ ++ if (bcmerror == 0) { ++ ++ if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) { ++ tbl_ptr = pi->mphase_txcal_bestcoeffs; ++ tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs); ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) ++ tbl_len -= 2; ++ } else { ++ if ((!fullcal) && (pi->nphy_txiqlocal_coeffsvalid)) { ++ ++ tbl_ptr = pi->nphy_txiqlocal_bestc; ++ tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc); ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) ++ tbl_len -= 2; ++ } else { ++ ++ fullcal = true; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ tbl_ptr = ++ tbl_tx_iqlo_cal_startcoefs_nphyrev3; ++ tbl_len = ARRAY_SIZE( ++ tbl_tx_iqlo_cal_startcoefs_nphyrev3); ++ } else { ++ tbl_ptr = tbl_tx_iqlo_cal_startcoefs; ++ tbl_len = ARRAY_SIZE( ++ tbl_tx_iqlo_cal_startcoefs); ++ } ++ } ++ } ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 64, ++ 16, tbl_ptr); ++ ++ if (fullcal) { ++ max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ? ++ ARRAY_SIZE( ++ tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3) : ++ ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal); ++ } else { ++ max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ? ++ ARRAY_SIZE( ++ tbl_tx_iqlo_cal_cmds_recal_nphyrev3) : ++ ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal); ++ } ++ ++ if (mphase) { ++ cal_cnt = pi->mphase_txcal_cmdidx; ++ if ((cal_cnt + pi->mphase_txcal_numcmds) < max_cal_cmds) ++ num_cals = cal_cnt + pi->mphase_txcal_numcmds; ++ else ++ num_cals = max_cal_cmds; ++ } else { ++ cal_cnt = 0; ++ num_cals = max_cal_cmds; ++ } ++ ++ for (; cal_cnt < num_cals; cal_cnt++) { ++ ++ if (fullcal) { ++ cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ? ++ tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3 ++ [cal_cnt] : ++ tbl_tx_iqlo_cal_cmds_fullcal[cal_cnt]; ++ } else { ++ cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ? ++ tbl_tx_iqlo_cal_cmds_recal_nphyrev3[ ++ cal_cnt] ++ : tbl_tx_iqlo_cal_cmds_recal[cal_cnt]; ++ } ++ ++ core_no = ((cal_cmd & 0x3000) >> 12); ++ cal_type = ((cal_cmd & 0x0F00) >> 8); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 6) || ++ (NREV_IS(pi->pubpi.phy_rev, 5) && ++ PHY_IPA(pi) ++ && (CHSPEC_IS2G(pi->radio_chanspec)))) { ++ if (!ladder_updated[core_no]) { ++ wlc_phy_update_txcal_ladder_nphy( ++ pi, ++ core_no); ++ ladder_updated[core_no] = true; ++ } ++ } ++ ++ val = ++ (cal_params[core_no]. ++ ncorr[cal_type] << 8) | NPHY_N_GCTL; ++ write_phy_reg(pi, 0xc1, val); ++ ++ if ((cal_type == 1) || (cal_type == 3) ++ || (cal_type == 4)) { ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, ++ 1, 69 + core_no, 16, ++ tbl_buf); ++ ++ diq_start = tbl_buf[0]; ++ ++ tbl_buf[0] = 0; ++ wlc_phy_table_write_nphy(pi, ++ NPHY_TBL_ID_IQLOCAL, 1, ++ 69 + core_no, 16, ++ tbl_buf); ++ } ++ ++ write_phy_reg(pi, 0xc0, cal_cmd); ++ ++ SPINWAIT(((read_phy_reg(pi, 0xc0) & 0xc000) != 0), ++ 20000); ++ if (WARN(read_phy_reg(pi, 0xc0) & 0xc000, ++ "HW error: txiq calib")) ++ return -EIO; ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, ++ tbl_len, 96, 16, tbl_buf); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, ++ tbl_len, 64, 16, tbl_buf); ++ ++ if ((cal_type == 1) || (cal_type == 3) ++ || (cal_type == 4)) { ++ ++ tbl_buf[0] = diq_start; ++ ++ } ++ ++ } ++ ++ if (mphase) { ++ pi->mphase_txcal_cmdidx = num_cals; ++ if (pi->mphase_txcal_cmdidx >= max_cal_cmds) ++ pi->mphase_txcal_cmdidx = 0; ++ } ++ ++ mphase_cal_lastphase = ++ (NREV_LE(pi->pubpi.phy_rev, 2)) ? ++ MPHASE_CAL_STATE_TXPHASE4 : MPHASE_CAL_STATE_TXPHASE5; ++ ++ if (!mphase ++ || (pi->mphase_cal_phase_id == mphase_cal_lastphase)) { ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 96, ++ 16, tbl_buf); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, ++ 16, tbl_buf); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) { ++ ++ tbl_buf[0] = 0; ++ tbl_buf[1] = 0; ++ tbl_buf[2] = 0; ++ tbl_buf[3] = 0; ++ ++ } ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, ++ 16, tbl_buf); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 101, ++ 16, tbl_buf); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, ++ 16, tbl_buf); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, ++ 16, tbl_buf); ++ ++ tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc); ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) ++ tbl_len -= 2; ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, ++ tbl_len, 96, 16, ++ pi->nphy_txiqlocal_bestc); ++ ++ pi->nphy_txiqlocal_coeffsvalid = true; ++ pi->nphy_txiqlocal_chanspec = pi->radio_chanspec; ++ } else { ++ tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs); ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) ++ tbl_len -= 2; ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, ++ tbl_len, 96, 16, ++ pi->mphase_txcal_bestcoeffs); ++ } ++ ++ wlc_phy_stopplayback_nphy(pi); ++ ++ write_phy_reg(pi, 0xc2, 0x0000); ++ ++ } ++ ++ wlc_phy_txcal_phycleanup_nphy(pi); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, ++ gain_save); ++ ++ wlc_phy_txcal_radio_cleanup_nphy(pi); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) { ++ if (!mphase ++ || (pi->mphase_cal_phase_id == mphase_cal_lastphase)) ++ wlc_phy_tx_iq_war_nphy(pi); ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 4)) ++ pi->phyhang_avoid = phyhang_avoid_state; ++ ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ ++ return bcmerror; ++} ++ ++static void wlc_phy_reapply_txcal_coeffs_nphy(struct brcms_phy *pi) ++{ ++ u16 tbl_buf[7]; ++ ++ if ((pi->nphy_txiqlocal_chanspec == pi->radio_chanspec) && ++ (pi->nphy_txiqlocal_coeffsvalid)) { ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, ++ ARRAY_SIZE(tbl_buf), 80, 16, tbl_buf); ++ ++ if ((pi->nphy_txiqlocal_bestc[0] != tbl_buf[0]) || ++ (pi->nphy_txiqlocal_bestc[1] != tbl_buf[1]) || ++ (pi->nphy_txiqlocal_bestc[2] != tbl_buf[2]) || ++ (pi->nphy_txiqlocal_bestc[3] != tbl_buf[3])) { ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, ++ 16, pi->nphy_txiqlocal_bestc); ++ ++ tbl_buf[0] = 0; ++ tbl_buf[1] = 0; ++ tbl_buf[2] = 0; ++ tbl_buf[3] = 0; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, ++ 16, tbl_buf); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, ++ 16, ++ &pi->nphy_txiqlocal_bestc[5]); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, ++ 16, ++ &pi->nphy_txiqlocal_bestc[5]); ++ } ++ } ++} ++ ++void ++wlc_phy_rx_iq_coeffs_nphy(struct brcms_phy *pi, u8 write, ++ struct nphy_iq_comp *pcomp) ++{ ++ if (write) { ++ write_phy_reg(pi, 0x9a, pcomp->a0); ++ write_phy_reg(pi, 0x9b, pcomp->b0); ++ write_phy_reg(pi, 0x9c, pcomp->a1); ++ write_phy_reg(pi, 0x9d, pcomp->b1); ++ } else { ++ pcomp->a0 = read_phy_reg(pi, 0x9a); ++ pcomp->b0 = read_phy_reg(pi, 0x9b); ++ pcomp->a1 = read_phy_reg(pi, 0x9c); ++ pcomp->b1 = read_phy_reg(pi, 0x9d); ++ } ++} ++ ++void ++wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est, ++ u16 num_samps, u8 wait_time, u8 wait_for_crs) ++{ ++ u8 core; ++ ++ write_phy_reg(pi, 0x12b, num_samps); ++ mod_phy_reg(pi, 0x12a, (0xff << 0), (wait_time << 0)); ++ mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqMode, ++ (wait_for_crs) ? NPHY_IqestCmd_iqMode : 0); ++ ++ mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqstart, NPHY_IqestCmd_iqstart); ++ ++ SPINWAIT(((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) != 0), ++ 10000); ++ if (WARN(read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart, ++ "HW error: rxiq est")) ++ return; ++ ++ if ((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) == 0) { ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ est[core].i_pwr = ++ (read_phy_reg(pi, ++ NPHY_IqestipwrAccHi(core)) << 16) ++ | read_phy_reg(pi, NPHY_IqestipwrAccLo(core)); ++ est[core].q_pwr = ++ (read_phy_reg(pi, ++ NPHY_IqestqpwrAccHi(core)) << 16) ++ | read_phy_reg(pi, NPHY_IqestqpwrAccLo(core)); ++ est[core].iq_prod = ++ (read_phy_reg(pi, ++ NPHY_IqestIqAccHi(core)) << 16) | ++ read_phy_reg(pi, NPHY_IqestIqAccLo(core)); ++ } ++ } ++} ++ ++#define CAL_RETRY_CNT 2 ++static void wlc_phy_calc_rx_iq_comp_nphy(struct brcms_phy *pi, u8 core_mask) ++{ ++ u8 curr_core; ++ struct phy_iq_est est[PHY_CORE_MAX]; ++ struct nphy_iq_comp old_comp, new_comp; ++ s32 iq = 0; ++ u32 ii = 0, qq = 0; ++ s16 iq_nbits, qq_nbits, brsh, arsh; ++ s32 a, b, temp; ++ int bcmerror = 0; ++ uint cal_retry = 0; ++ ++ if (core_mask == 0x0) ++ return; ++ ++ wlc_phy_rx_iq_coeffs_nphy(pi, 0, &old_comp); ++ new_comp.a0 = new_comp.b0 = new_comp.a1 = new_comp.b1 = 0x0; ++ wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp); ++ ++cal_try: ++ wlc_phy_rx_iq_est_nphy(pi, est, 0x4000, 32, 0); ++ ++ new_comp = old_comp; ++ ++ for (curr_core = 0; curr_core < pi->pubpi.phy_corenum; curr_core++) { ++ ++ if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) { ++ iq = est[curr_core].iq_prod; ++ ii = est[curr_core].i_pwr; ++ qq = est[curr_core].q_pwr; ++ } else if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) { ++ iq = est[curr_core].iq_prod; ++ ii = est[curr_core].i_pwr; ++ qq = est[curr_core].q_pwr; ++ } else { ++ continue; ++ } ++ ++ if ((ii + qq) < NPHY_MIN_RXIQ_PWR) { ++ bcmerror = -EBADE; ++ break; ++ } ++ ++ iq_nbits = wlc_phy_nbits(iq); ++ qq_nbits = wlc_phy_nbits(qq); ++ ++ arsh = 10 - (30 - iq_nbits); ++ if (arsh >= 0) { ++ a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); ++ temp = (s32) (ii >> arsh); ++ if (temp == 0) { ++ bcmerror = -EBADE; ++ break; ++ } ++ } else { ++ a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); ++ temp = (s32) (ii << -arsh); ++ if (temp == 0) { ++ bcmerror = -EBADE; ++ break; ++ } ++ } ++ ++ a /= temp; ++ ++ brsh = qq_nbits - 31 + 20; ++ if (brsh >= 0) { ++ b = (qq << (31 - qq_nbits)); ++ temp = (s32) (ii >> brsh); ++ if (temp == 0) { ++ bcmerror = -EBADE; ++ break; ++ } ++ } else { ++ b = (qq << (31 - qq_nbits)); ++ temp = (s32) (ii << -brsh); ++ if (temp == 0) { ++ bcmerror = -EBADE; ++ break; ++ } ++ } ++ b /= temp; ++ b -= a * a; ++ b = (s32) int_sqrt((unsigned long) b); ++ b -= (1 << 10); ++ ++ if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ new_comp.a0 = (s16) a & 0x3ff; ++ new_comp.b0 = (s16) b & 0x3ff; ++ } else { ++ ++ new_comp.a0 = (s16) b & 0x3ff; ++ new_comp.b0 = (s16) a & 0x3ff; ++ } ++ } ++ if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ new_comp.a1 = (s16) a & 0x3ff; ++ new_comp.b1 = (s16) b & 0x3ff; ++ } else { ++ ++ new_comp.a1 = (s16) b & 0x3ff; ++ new_comp.b1 = (s16) a & 0x3ff; ++ } ++ } ++ } ++ ++ if (bcmerror != 0) { ++ printk(KERN_DEBUG "%s: Failed, cnt = %d\n", __func__, ++ cal_retry); ++ ++ if (cal_retry < CAL_RETRY_CNT) { ++ cal_retry++; ++ goto cal_try; ++ } ++ ++ new_comp = old_comp; ++ } ++ ++ wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp); ++} ++ ++static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core) ++{ ++ u16 offtune_val; ++ u16 bias_g = 0; ++ u16 bias_a = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (rx_core == PHY_CORE_0) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ pi->tx_rx_cal_radio_saveregs[0] = ++ read_radio_reg(pi, ++ RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP); ++ pi->tx_rx_cal_radio_saveregs[1] = ++ read_radio_reg(pi, ++ RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN); ++ ++ write_radio_reg(pi, ++ RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP, ++ 0x3); ++ write_radio_reg(pi, ++ RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN, ++ 0xaf); ++ ++ } else { ++ pi->tx_rx_cal_radio_saveregs[0] = ++ read_radio_reg(pi, ++ RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP); ++ pi->tx_rx_cal_radio_saveregs[1] = ++ read_radio_reg(pi, ++ RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP, ++ 0x3); ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN, ++ 0x7f); ++ } ++ ++ } else { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ pi->tx_rx_cal_radio_saveregs[0] = ++ read_radio_reg(pi, ++ RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP); ++ pi->tx_rx_cal_radio_saveregs[1] = ++ read_radio_reg(pi, ++ RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP, ++ 0x3); ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN, ++ 0xaf); ++ ++ } else { ++ pi->tx_rx_cal_radio_saveregs[0] = ++ read_radio_reg(pi, ++ RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP); ++ pi->tx_rx_cal_radio_saveregs[1] = ++ read_radio_reg(pi, ++ RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN); ++ ++ write_radio_reg(pi, ++ RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP, ++ 0x3); ++ write_radio_reg(pi, ++ RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN, ++ 0x7f); ++ } ++ } ++ ++ } else { ++ if (rx_core == PHY_CORE_0) { ++ pi->tx_rx_cal_radio_saveregs[0] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_RXIQCAL_TXMUX | ++ RADIO_2056_TX1); ++ pi->tx_rx_cal_radio_saveregs[1] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_RXIQCAL_RXMUX | ++ RADIO_2056_RX0); ++ ++ if (pi->pubpi.radiorev >= 5) { ++ pi->tx_rx_cal_radio_saveregs[2] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_RXSPARE2 | ++ RADIO_2056_RX0); ++ pi->tx_rx_cal_radio_saveregs[3] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TXSPARE2 | ++ RADIO_2056_TX1); ++ } ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ ++ if (pi->pubpi.radiorev >= 5) { ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_LNAA_MASTER ++ | RADIO_2056_RX0); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAA_MASTER ++ | RADIO_2056_RX0, 0x40); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TXSPARE2 | ++ RADIO_2056_TX1, bias_a); ++ ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXSPARE2 | ++ RADIO_2056_RX0, bias_a); ++ } else { ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_LNAA_TUNE ++ | RADIO_2056_RX0); ++ ++ offtune_val = ++ (pi->tx_rx_cal_radio_saveregs ++ [2] & 0xF0) >> 8; ++ offtune_val = ++ (offtune_val <= 0x7) ? 0xF : 0; ++ ++ mod_radio_reg(pi, ++ RADIO_2056_RX_LNAA_TUNE | ++ RADIO_2056_RX0, 0xF0, ++ (offtune_val << 8)); ++ } ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_RXIQCAL_TXMUX | ++ RADIO_2056_TX1, 0x9); ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXIQCAL_RXMUX | ++ RADIO_2056_RX0, 0x9); ++ } else { ++ if (pi->pubpi.radiorev >= 5) { ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_MASTER ++ | RADIO_2056_RX0); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_MASTER ++ | RADIO_2056_RX0, 0x40); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TXSPARE2 ++ | ++ RADIO_2056_TX1, bias_g); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_RXSPARE2 ++ | ++ RADIO_2056_RX0, bias_g); ++ ++ } else { ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_TUNE ++ | RADIO_2056_RX0); ++ ++ offtune_val = ++ (pi-> ++ tx_rx_cal_radio_saveregs[2] & ++ 0xF0) >> 8; ++ offtune_val = ++ (offtune_val <= 0x7) ? 0xF : 0; ++ ++ mod_radio_reg(pi, ++ RADIO_2056_RX_LNAG_TUNE | ++ RADIO_2056_RX0, 0xF0, ++ (offtune_val << 8)); ++ } ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_RXIQCAL_TXMUX | ++ RADIO_2056_TX1, 0x6); ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXIQCAL_RXMUX | ++ RADIO_2056_RX0, 0x6); ++ } ++ ++ } else { ++ pi->tx_rx_cal_radio_saveregs[0] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_RXIQCAL_TXMUX | ++ RADIO_2056_TX0); ++ pi->tx_rx_cal_radio_saveregs[1] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_RXIQCAL_RXMUX | ++ RADIO_2056_RX1); ++ ++ if (pi->pubpi.radiorev >= 5) { ++ pi->tx_rx_cal_radio_saveregs[2] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_RXSPARE2 | ++ RADIO_2056_RX1); ++ pi->tx_rx_cal_radio_saveregs[3] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TXSPARE2 | ++ RADIO_2056_TX0); ++ } ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ ++ if (pi->pubpi.radiorev >= 5) { ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAA_MASTER ++ | RADIO_2056_RX1); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAA_MASTER | ++ RADIO_2056_RX1, 0x40); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TXSPARE2 ++ | ++ RADIO_2056_TX0, bias_a); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_RXSPARE2 ++ | ++ RADIO_2056_RX1, bias_a); ++ } else { ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAA_TUNE ++ | RADIO_2056_RX1); ++ ++ offtune_val = ++ (pi-> ++ tx_rx_cal_radio_saveregs[2] & ++ 0xF0) >> 8; ++ offtune_val = ++ (offtune_val <= 0x7) ? 0xF : 0; ++ ++ mod_radio_reg(pi, ++ RADIO_2056_RX_LNAA_TUNE | ++ RADIO_2056_RX1, 0xF0, ++ (offtune_val << 8)); ++ } ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_RXIQCAL_TXMUX | ++ RADIO_2056_TX0, 0x9); ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXIQCAL_RXMUX | ++ RADIO_2056_RX1, 0x9); ++ } else { ++ if (pi->pubpi.radiorev >= 5) { ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_MASTER ++ | RADIO_2056_RX1); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_MASTER ++ | RADIO_2056_RX1, 0x40); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TXSPARE2 ++ | ++ RADIO_2056_TX0, bias_g); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_RXSPARE2 ++ | ++ RADIO_2056_RX1, bias_g); ++ } else { ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_TUNE ++ | RADIO_2056_RX1); ++ ++ offtune_val = ++ (pi-> ++ tx_rx_cal_radio_saveregs[2] & ++ 0xF0) >> 8; ++ offtune_val = ++ (offtune_val <= 0x7) ? 0xF : 0; ++ ++ mod_radio_reg(pi, ++ RADIO_2056_RX_LNAG_TUNE | ++ RADIO_2056_RX1, 0xF0, ++ (offtune_val << 8)); ++ } ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_RXIQCAL_TXMUX | ++ RADIO_2056_TX0, 0x6); ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXIQCAL_RXMUX | ++ RADIO_2056_RX1, 0x6); ++ } ++ } ++ } ++} ++ ++static void wlc_phy_rxcal_radio_cleanup_nphy(struct brcms_phy *pi, u8 rx_core) ++{ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (rx_core == PHY_CORE_0) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP, ++ pi-> ++ tx_rx_cal_radio_saveregs[0]); ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN, ++ pi-> ++ tx_rx_cal_radio_saveregs[1]); ++ ++ } else { ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP, ++ pi-> ++ tx_rx_cal_radio_saveregs[0]); ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN, ++ pi-> ++ tx_rx_cal_radio_saveregs[1]); ++ } ++ ++ } else { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP, ++ pi-> ++ tx_rx_cal_radio_saveregs[0]); ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN, ++ pi-> ++ tx_rx_cal_radio_saveregs[1]); ++ ++ } else { ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP, ++ pi-> ++ tx_rx_cal_radio_saveregs[0]); ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN, ++ pi-> ++ tx_rx_cal_radio_saveregs[1]); ++ } ++ } ++ ++ } else { ++ if (rx_core == PHY_CORE_0) { ++ write_radio_reg(pi, ++ RADIO_2056_TX_RXIQCAL_TXMUX | ++ RADIO_2056_TX1, ++ pi->tx_rx_cal_radio_saveregs[0]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXIQCAL_RXMUX | ++ RADIO_2056_RX0, ++ pi->tx_rx_cal_radio_saveregs[1]); ++ ++ if (pi->pubpi.radiorev >= 5) { ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXSPARE2 | ++ RADIO_2056_RX0, ++ pi-> ++ tx_rx_cal_radio_saveregs[2]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TXSPARE2 | ++ RADIO_2056_TX1, ++ pi-> ++ tx_rx_cal_radio_saveregs[3]); ++ } ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (pi->pubpi.radiorev >= 5) ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAA_MASTER ++ | RADIO_2056_RX0, ++ pi-> ++ tx_rx_cal_radio_saveregs ++ [4]); ++ else ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAA_TUNE ++ | RADIO_2056_RX0, ++ pi-> ++ tx_rx_cal_radio_saveregs ++ [4]); ++ } else { ++ if (pi->pubpi.radiorev >= 5) ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_MASTER ++ | RADIO_2056_RX0, ++ pi-> ++ tx_rx_cal_radio_saveregs ++ [4]); ++ else ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_TUNE ++ | RADIO_2056_RX0, ++ pi-> ++ tx_rx_cal_radio_saveregs ++ [4]); ++ } ++ ++ } else { ++ write_radio_reg(pi, ++ RADIO_2056_TX_RXIQCAL_TXMUX | ++ RADIO_2056_TX0, ++ pi->tx_rx_cal_radio_saveregs[0]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXIQCAL_RXMUX | ++ RADIO_2056_RX1, ++ pi->tx_rx_cal_radio_saveregs[1]); ++ ++ if (pi->pubpi.radiorev >= 5) { ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXSPARE2 | ++ RADIO_2056_RX1, ++ pi-> ++ tx_rx_cal_radio_saveregs[2]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TXSPARE2 | ++ RADIO_2056_TX0, ++ pi-> ++ tx_rx_cal_radio_saveregs[3]); ++ } ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (pi->pubpi.radiorev >= 5) ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAA_MASTER ++ | RADIO_2056_RX1, ++ pi-> ++ tx_rx_cal_radio_saveregs ++ [4]); ++ else ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAA_TUNE ++ | RADIO_2056_RX1, ++ pi-> ++ tx_rx_cal_radio_saveregs ++ [4]); ++ } else { ++ if (pi->pubpi.radiorev >= 5) ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_MASTER ++ | RADIO_2056_RX1, ++ pi-> ++ tx_rx_cal_radio_saveregs ++ [4]); ++ else ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_TUNE ++ | RADIO_2056_RX1, ++ pi-> ++ tx_rx_cal_radio_saveregs ++ [4]); ++ } ++ } ++ } ++} ++ ++static void wlc_phy_rxcal_physetup_nphy(struct brcms_phy *pi, u8 rx_core) ++{ ++ u8 tx_core; ++ u16 rx_antval, tx_antval; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ tx_core = rx_core; ++ else ++ tx_core = (rx_core == PHY_CORE_0) ? 1 : 0; ++ ++ pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa2); ++ pi->tx_rx_cal_phy_saveregs[1] = ++ read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7); ++ pi->tx_rx_cal_phy_saveregs[2] = ++ read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5); ++ pi->tx_rx_cal_phy_saveregs[3] = read_phy_reg(pi, 0x91); ++ pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x92); ++ pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x7a); ++ pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x7d); ++ pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0xe7); ++ pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0xec); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ pi->tx_rx_cal_phy_saveregs[11] = read_phy_reg(pi, 0x342); ++ pi->tx_rx_cal_phy_saveregs[12] = read_phy_reg(pi, 0x343); ++ pi->tx_rx_cal_phy_saveregs[13] = read_phy_reg(pi, 0x346); ++ pi->tx_rx_cal_phy_saveregs[14] = read_phy_reg(pi, 0x347); ++ } ++ ++ pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297); ++ pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b); ++ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (0) << 0); ++ ++ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (0) << 0); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0); ++ ++ mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << (1 - rx_core)) << 12); ++ ++ } else { ++ ++ mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12); ++ mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0); ++ mod_phy_reg(pi, 0xa2, (0xf << 4), (1 << rx_core) << 4); ++ mod_phy_reg(pi, 0xa2, (0xf << 8), (1 << rx_core) << 8); ++ } ++ ++ mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7), (0x1 << 2), 0); ++ mod_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5, ++ (0x1 << 2), (0x1 << 2)); ++ if (NREV_LT(pi->pubpi.phy_rev, 7)) { ++ mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7), ++ (0x1 << 0) | (0x1 << 1), 0); ++ mod_phy_reg(pi, (rx_core == PHY_CORE_0) ? ++ 0x8f : 0xa5, ++ (0x1 << 0) | (0x1 << 1), (0x1 << 0) | (0x1 << 1)); ++ } ++ ++ wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 0, ++ RADIO_MIMO_CORESEL_CORE1 | ++ RADIO_MIMO_CORESEL_CORE2); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), ++ 0, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 0, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 1, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 1, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ if (CHSPEC_IS40(pi->radio_chanspec)) ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, ++ (0x1 << 7), ++ 2, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ else ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, ++ (0x1 << 7), ++ 0, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), ++ 0, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ } else { ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 3, 0); ++ } ++ ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ 0x1, rx_core + 1); ++ } else { ++ ++ if (rx_core == PHY_CORE_0) { ++ rx_antval = 0x1; ++ tx_antval = 0x8; ++ } else { ++ rx_antval = 0x4; ++ tx_antval = 0x2; ++ } ++ ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ rx_antval, rx_core + 1); ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ tx_antval, tx_core + 1); ++ } ++} ++ ++static void wlc_phy_rxcal_phycleanup_nphy(struct brcms_phy *pi, u8 rx_core) ++{ ++ ++ write_phy_reg(pi, 0xa2, pi->tx_rx_cal_phy_saveregs[0]); ++ write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7, ++ pi->tx_rx_cal_phy_saveregs[1]); ++ write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5, ++ pi->tx_rx_cal_phy_saveregs[2]); ++ write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[3]); ++ write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[4]); ++ ++ write_phy_reg(pi, 0x7a, pi->tx_rx_cal_phy_saveregs[5]); ++ write_phy_reg(pi, 0x7d, pi->tx_rx_cal_phy_saveregs[6]); ++ write_phy_reg(pi, 0xe7, pi->tx_rx_cal_phy_saveregs[7]); ++ write_phy_reg(pi, 0xec, pi->tx_rx_cal_phy_saveregs[8]); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ write_phy_reg(pi, 0x342, pi->tx_rx_cal_phy_saveregs[11]); ++ write_phy_reg(pi, 0x343, pi->tx_rx_cal_phy_saveregs[12]); ++ write_phy_reg(pi, 0x346, pi->tx_rx_cal_phy_saveregs[13]); ++ write_phy_reg(pi, 0x347, pi->tx_rx_cal_phy_saveregs[14]); ++ } ++ ++ write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]); ++ write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]); ++} ++ ++static void ++wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core, ++ u16 *rxgain, u8 cal_type) ++{ ++ ++ u16 num_samps; ++ struct phy_iq_est est[PHY_CORE_MAX]; ++ u8 tx_core; ++ struct nphy_iq_comp save_comp, zero_comp; ++ u32 i_pwr, q_pwr, curr_pwr, optim_pwr = 0, prev_pwr = 0, ++ thresh_pwr = 10000; ++ s16 desired_log2_pwr, actual_log2_pwr, delta_pwr; ++ bool gainctrl_done = false; ++ u8 mix_tia_gain = 3; ++ s8 optim_gaintbl_index = 0, prev_gaintbl_index = 0; ++ s8 curr_gaintbl_index = 3; ++ u8 gainctrl_dirn = NPHY_RXCAL_GAIN_INIT; ++ const struct nphy_ipa_txrxgain *nphy_rxcal_gaintbl; ++ u16 hpvga, lpf_biq1, lpf_biq0, lna2, lna1; ++ int fine_gain_idx; ++ s8 txpwrindex; ++ u16 nphy_rxcal_txgain[2]; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ tx_core = rx_core; ++ else ++ tx_core = 1 - rx_core; ++ ++ num_samps = 1024; ++ desired_log2_pwr = (cal_type == 0) ? 13 : 13; ++ ++ wlc_phy_rx_iq_coeffs_nphy(pi, 0, &save_comp); ++ zero_comp.a0 = zero_comp.b0 = zero_comp.a1 = zero_comp.b1 = 0x0; ++ wlc_phy_rx_iq_coeffs_nphy(pi, 1, &zero_comp); ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ mix_tia_gain = 3; ++ else if (NREV_GE(pi->pubpi.phy_rev, 4)) ++ mix_tia_gain = 4; ++ else ++ mix_tia_gain = 6; ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz_rev7; ++ else ++ nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz; ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz_rev7; ++ else ++ nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz; ++ } ++ ++ do { ++ ++ hpvga = (NREV_GE(pi->pubpi.phy_rev, 7)) ? ++ 0 : nphy_rxcal_gaintbl[curr_gaintbl_index].hpvga; ++ lpf_biq1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq1; ++ lpf_biq0 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq0; ++ lna2 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna2; ++ lna1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna1; ++ txpwrindex = nphy_rxcal_gaintbl[curr_gaintbl_index].txpwrindex; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_rxgain, ++ ((lpf_biq1 << 12) | ++ (lpf_biq0 << 8) | ++ (mix_tia_gain << 4) | (lna2 << 2) ++ | lna1), 0x3, 0); ++ else ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), ++ ((hpvga << 12) | ++ (lpf_biq1 << 10) | ++ (lpf_biq0 << 8) | ++ (mix_tia_gain << 4) | ++ (lna2 << 2) | lna1), 0x3, ++ 0); ++ ++ pi->nphy_rxcal_pwr_idx[tx_core] = txpwrindex; ++ ++ if (txpwrindex == -1) { ++ nphy_rxcal_txgain[0] = 0x8ff0 | pi->nphy_gmval; ++ nphy_rxcal_txgain[1] = 0x8ff0 | pi->nphy_gmval; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, ++ 2, 0x110, 16, ++ nphy_rxcal_txgain); ++ } else { ++ wlc_phy_txpwr_index_nphy(pi, tx_core + 1, txpwrindex, ++ false); ++ } ++ ++ wlc_phy_tx_tone_nphy(pi, (CHSPEC_IS40(pi->radio_chanspec)) ? ++ NPHY_RXCAL_TONEFREQ_40MHz : ++ NPHY_RXCAL_TONEFREQ_20MHz, ++ NPHY_RXCAL_TONEAMP, 0, cal_type, false); ++ ++ wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0); ++ i_pwr = (est[rx_core].i_pwr + num_samps / 2) / num_samps; ++ q_pwr = (est[rx_core].q_pwr + num_samps / 2) / num_samps; ++ curr_pwr = i_pwr + q_pwr; ++ ++ switch (gainctrl_dirn) { ++ case NPHY_RXCAL_GAIN_INIT: ++ if (curr_pwr > thresh_pwr) { ++ gainctrl_dirn = NPHY_RXCAL_GAIN_DOWN; ++ prev_gaintbl_index = curr_gaintbl_index; ++ curr_gaintbl_index--; ++ } else { ++ gainctrl_dirn = NPHY_RXCAL_GAIN_UP; ++ prev_gaintbl_index = curr_gaintbl_index; ++ curr_gaintbl_index++; ++ } ++ break; ++ ++ case NPHY_RXCAL_GAIN_UP: ++ if (curr_pwr > thresh_pwr) { ++ gainctrl_done = true; ++ optim_pwr = prev_pwr; ++ optim_gaintbl_index = prev_gaintbl_index; ++ } else { ++ prev_gaintbl_index = curr_gaintbl_index; ++ curr_gaintbl_index++; ++ } ++ break; ++ ++ case NPHY_RXCAL_GAIN_DOWN: ++ if (curr_pwr > thresh_pwr) { ++ prev_gaintbl_index = curr_gaintbl_index; ++ curr_gaintbl_index--; ++ } else { ++ gainctrl_done = true; ++ optim_pwr = curr_pwr; ++ optim_gaintbl_index = curr_gaintbl_index; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ if ((curr_gaintbl_index < 0) || ++ (curr_gaintbl_index > NPHY_IPA_RXCAL_MAXGAININDEX)) { ++ gainctrl_done = true; ++ optim_pwr = curr_pwr; ++ optim_gaintbl_index = prev_gaintbl_index; ++ } else { ++ prev_pwr = curr_pwr; ++ } ++ ++ wlc_phy_stopplayback_nphy(pi); ++ } while (!gainctrl_done); ++ ++ hpvga = nphy_rxcal_gaintbl[optim_gaintbl_index].hpvga; ++ lpf_biq1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq1; ++ lpf_biq0 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq0; ++ lna2 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna2; ++ lna1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna1; ++ txpwrindex = nphy_rxcal_gaintbl[optim_gaintbl_index].txpwrindex; ++ ++ actual_log2_pwr = wlc_phy_nbits(optim_pwr); ++ delta_pwr = desired_log2_pwr - actual_log2_pwr; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ fine_gain_idx = (int)lpf_biq1 + delta_pwr; ++ ++ if (fine_gain_idx + (int)lpf_biq0 > 10) ++ lpf_biq1 = 10 - lpf_biq0; ++ else ++ lpf_biq1 = (u16) max(fine_gain_idx, 0); ++ ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_rxgain, ++ ((lpf_biq1 << 12) | ++ (lpf_biq0 << 8) | ++ (mix_tia_gain << 4) | ++ (lna2 << 2) | lna1), 0x3, ++ 0); ++ } else { ++ hpvga = (u16) max(min(((int)hpvga) + delta_pwr, 10), 0); ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), ++ ((hpvga << 12) | ++ (lpf_biq1 << 10) | ++ (lpf_biq0 << 8) | ++ (mix_tia_gain << 4) | ++ (lna2 << 2) | ++ lna1), 0x3, 0); ++ } ++ ++ if (rxgain != NULL) { ++ *rxgain++ = lna1; ++ *rxgain++ = lna2; ++ *rxgain++ = mix_tia_gain; ++ *rxgain++ = lpf_biq0; ++ *rxgain++ = lpf_biq1; ++ *rxgain = hpvga; ++ } ++ ++ wlc_phy_rx_iq_coeffs_nphy(pi, 1, &save_comp); ++} ++ ++static void ++wlc_phy_rxcal_gainctrl_nphy(struct brcms_phy *pi, u8 rx_core, u16 *rxgain, ++ u8 cal_type) ++{ ++ wlc_phy_rxcal_gainctrl_nphy_rev5(pi, rx_core, rxgain, cal_type); ++} ++ ++static u8 ++wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type) ++{ ++ u32 target_bws[2] = { 9500, 21000 }; ++ u32 ref_tones[2] = { 3000, 6000 }; ++ u32 target_bw, ref_tone; ++ ++ u32 target_pwr_ratios[2] = { 28606, 18468 }; ++ u32 target_pwr_ratio, pwr_ratio, last_pwr_ratio = 0; ++ ++ u16 start_rccal_ovr_val = 128; ++ u16 txlpf_rccal_lpc_ovr_val = 128; ++ u16 rxlpf_rccal_hpc_ovr_val = 159; ++ ++ u16 orig_txlpf_rccal_lpc_ovr_val; ++ u16 orig_rxlpf_rccal_hpc_ovr_val; ++ u16 radio_addr_offset_rx; ++ u16 radio_addr_offset_tx; ++ u16 orig_dcBypass; ++ u16 orig_RxStrnFilt40Num[6]; ++ u16 orig_RxStrnFilt40Den[4]; ++ u16 orig_rfctrloverride[2]; ++ u16 orig_rfctrlauxreg[2]; ++ u16 orig_rfctrlrssiothers; ++ u16 tx_lpf_bw = 4; ++ ++ u16 rx_lpf_bw, rx_lpf_bws[2] = { 2, 4 }; ++ u16 lpf_hpc = 7, hpvga_hpc = 7; ++ ++ s8 rccal_stepsize; ++ u16 rccal_val, last_rccal_val = 0, best_rccal_val = 0; ++ u32 ref_iq_vals = 0, target_iq_vals = 0; ++ u16 num_samps, log_num_samps = 10; ++ struct phy_iq_est est[PHY_CORE_MAX]; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ return 0; ++ ++ num_samps = (1 << log_num_samps); ++ ++ if (CHSPEC_IS40(pi->radio_chanspec)) { ++ target_bw = target_bws[1]; ++ target_pwr_ratio = target_pwr_ratios[1]; ++ ref_tone = ref_tones[1]; ++ rx_lpf_bw = rx_lpf_bws[1]; ++ } else { ++ target_bw = target_bws[0]; ++ target_pwr_ratio = target_pwr_ratios[0]; ++ ref_tone = ref_tones[0]; ++ rx_lpf_bw = rx_lpf_bws[0]; ++ } ++ ++ if (core_idx == 0) { ++ radio_addr_offset_rx = RADIO_2056_RX0; ++ radio_addr_offset_tx = ++ (loopback_type == 0) ? RADIO_2056_TX0 : RADIO_2056_TX1; ++ } else { ++ radio_addr_offset_rx = RADIO_2056_RX1; ++ radio_addr_offset_tx = ++ (loopback_type == 0) ? RADIO_2056_TX1 : RADIO_2056_TX0; ++ } ++ ++ orig_txlpf_rccal_lpc_ovr_val = ++ read_radio_reg(pi, ++ (RADIO_2056_TX_TXLPF_RCCAL | ++ radio_addr_offset_tx)); ++ orig_rxlpf_rccal_hpc_ovr_val = ++ read_radio_reg(pi, ++ (RADIO_2056_RX_RXLPF_RCCAL_HPC | ++ radio_addr_offset_rx)); ++ ++ orig_dcBypass = ((read_phy_reg(pi, 0x48) >> 8) & 1); ++ ++ orig_RxStrnFilt40Num[0] = read_phy_reg(pi, 0x267); ++ orig_RxStrnFilt40Num[1] = read_phy_reg(pi, 0x268); ++ orig_RxStrnFilt40Num[2] = read_phy_reg(pi, 0x269); ++ orig_RxStrnFilt40Den[0] = read_phy_reg(pi, 0x26a); ++ orig_RxStrnFilt40Den[1] = read_phy_reg(pi, 0x26b); ++ orig_RxStrnFilt40Num[3] = read_phy_reg(pi, 0x26c); ++ orig_RxStrnFilt40Num[4] = read_phy_reg(pi, 0x26d); ++ orig_RxStrnFilt40Num[5] = read_phy_reg(pi, 0x26e); ++ orig_RxStrnFilt40Den[2] = read_phy_reg(pi, 0x26f); ++ orig_RxStrnFilt40Den[3] = read_phy_reg(pi, 0x270); ++ ++ orig_rfctrloverride[0] = read_phy_reg(pi, 0xe7); ++ orig_rfctrloverride[1] = read_phy_reg(pi, 0xec); ++ orig_rfctrlauxreg[0] = read_phy_reg(pi, 0xf8); ++ orig_rfctrlauxreg[1] = read_phy_reg(pi, 0xfa); ++ orig_rfctrlrssiothers = read_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d); ++ ++ write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx), ++ txlpf_rccal_lpc_ovr_val); ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx), ++ rxlpf_rccal_hpc_ovr_val); ++ ++ mod_phy_reg(pi, 0x48, (0x1 << 8), (0x1 << 8)); ++ ++ write_phy_reg(pi, 0x267, 0x02d4); ++ write_phy_reg(pi, 0x268, 0x0000); ++ write_phy_reg(pi, 0x269, 0x0000); ++ write_phy_reg(pi, 0x26a, 0x0000); ++ write_phy_reg(pi, 0x26b, 0x0000); ++ write_phy_reg(pi, 0x26c, 0x02d4); ++ write_phy_reg(pi, 0x26d, 0x0000); ++ write_phy_reg(pi, 0x26e, 0x0000); ++ write_phy_reg(pi, 0x26f, 0x0000); ++ write_phy_reg(pi, 0x270, 0x0000); ++ ++ or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 8)); ++ or_phy_reg(pi, (core_idx == 0) ? 0xec : 0xe7, (0x1 << 15)); ++ or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 9)); ++ or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 10)); ++ ++ mod_phy_reg(pi, (core_idx == 0) ? 0xfa : 0xf8, ++ (0x7 << 10), (tx_lpf_bw << 10)); ++ mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa, ++ (0x7 << 0), (hpvga_hpc << 0)); ++ mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa, ++ (0x7 << 4), (lpf_hpc << 4)); ++ mod_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d, ++ (0x7 << 8), (rx_lpf_bw << 8)); ++ ++ rccal_stepsize = 16; ++ rccal_val = start_rccal_ovr_val + rccal_stepsize; ++ ++ while (rccal_stepsize >= 0) { ++ write_radio_reg(pi, ++ (RADIO_2056_RX_RXLPF_RCCAL_LPC | ++ radio_addr_offset_rx), rccal_val); ++ ++ if (rccal_stepsize == 16) { ++ ++ wlc_phy_tx_tone_nphy(pi, ref_tone, NPHY_RXCAL_TONEAMP, ++ 0, 1, false); ++ udelay(2); ++ ++ wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0); ++ ++ if (core_idx == 0) ++ ref_iq_vals = ++ max_t(u32, (est[0].i_pwr + ++ est[0].q_pwr) >> ++ (log_num_samps + 1), ++ 1); ++ else ++ ref_iq_vals = ++ max_t(u32, (est[1].i_pwr + ++ est[1].q_pwr) >> ++ (log_num_samps + 1), ++ 1); ++ ++ wlc_phy_tx_tone_nphy(pi, target_bw, NPHY_RXCAL_TONEAMP, ++ 0, 1, false); ++ udelay(2); ++ } ++ ++ wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0); ++ ++ if (core_idx == 0) ++ target_iq_vals = (est[0].i_pwr + est[0].q_pwr) >> ++ (log_num_samps + 1); ++ else ++ target_iq_vals = ++ (est[1].i_pwr + ++ est[1].q_pwr) >> (log_num_samps + 1); ++ ++ pwr_ratio = (uint) ((target_iq_vals << 16) / ref_iq_vals); ++ ++ if (rccal_stepsize == 0) ++ rccal_stepsize--; ++ else if (rccal_stepsize == 1) { ++ last_rccal_val = rccal_val; ++ rccal_val += (pwr_ratio > target_pwr_ratio) ? 1 : -1; ++ last_pwr_ratio = pwr_ratio; ++ rccal_stepsize--; ++ } else { ++ rccal_stepsize = (rccal_stepsize >> 1); ++ rccal_val += ((pwr_ratio > target_pwr_ratio) ? ++ rccal_stepsize : (-rccal_stepsize)); ++ } ++ ++ if (rccal_stepsize == -1) { ++ best_rccal_val = ++ (abs((int)last_pwr_ratio - ++ (int)target_pwr_ratio) < ++ abs((int)pwr_ratio - ++ (int)target_pwr_ratio)) ? last_rccal_val : ++ rccal_val; ++ ++ if (CHSPEC_IS40(pi->radio_chanspec)) { ++ if ((best_rccal_val > 140) ++ || (best_rccal_val < 135)) ++ best_rccal_val = 138; ++ } else { ++ if ((best_rccal_val > 142) ++ || (best_rccal_val < 137)) ++ best_rccal_val = 140; ++ } ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_RXLPF_RCCAL_LPC | ++ radio_addr_offset_rx), best_rccal_val); ++ } ++ } ++ ++ wlc_phy_stopplayback_nphy(pi); ++ ++ write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx), ++ orig_txlpf_rccal_lpc_ovr_val); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx), ++ orig_rxlpf_rccal_hpc_ovr_val); ++ ++ mod_phy_reg(pi, 0x48, (0x1 << 8), (orig_dcBypass << 8)); ++ ++ write_phy_reg(pi, 0x267, orig_RxStrnFilt40Num[0]); ++ write_phy_reg(pi, 0x268, orig_RxStrnFilt40Num[1]); ++ write_phy_reg(pi, 0x269, orig_RxStrnFilt40Num[2]); ++ write_phy_reg(pi, 0x26a, orig_RxStrnFilt40Den[0]); ++ write_phy_reg(pi, 0x26b, orig_RxStrnFilt40Den[1]); ++ write_phy_reg(pi, 0x26c, orig_RxStrnFilt40Num[3]); ++ write_phy_reg(pi, 0x26d, orig_RxStrnFilt40Num[4]); ++ write_phy_reg(pi, 0x26e, orig_RxStrnFilt40Num[5]); ++ write_phy_reg(pi, 0x26f, orig_RxStrnFilt40Den[2]); ++ write_phy_reg(pi, 0x270, orig_RxStrnFilt40Den[3]); ++ ++ write_phy_reg(pi, 0xe7, orig_rfctrloverride[0]); ++ write_phy_reg(pi, 0xec, orig_rfctrloverride[1]); ++ write_phy_reg(pi, 0xf8, orig_rfctrlauxreg[0]); ++ write_phy_reg(pi, 0xfa, orig_rfctrlauxreg[1]); ++ write_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d, orig_rfctrlrssiothers); ++ ++ pi->nphy_anarxlpf_adjusted = false; ++ ++ return best_rccal_val - 0x80; ++} ++ ++#define WAIT_FOR_SCOPE 4000 ++static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi, ++ struct nphy_txgains target_gain, ++ u8 cal_type, bool debug) ++{ ++ u16 orig_BBConfig; ++ u8 core_no, rx_core; ++ u8 best_rccal[2]; ++ u16 gain_save[2]; ++ u16 cal_gain[2]; ++ struct nphy_iqcal_params cal_params[2]; ++ u8 rxcore_state; ++ s8 rxlpf_rccal_hpc, txlpf_rccal_lpc; ++ s8 txlpf_idac; ++ bool phyhang_avoid_state = false; ++ bool skip_rxiqcal = false; ++ ++ orig_BBConfig = read_phy_reg(pi, 0x01); ++ mod_phy_reg(pi, 0x01, (0x1 << 15), 0); ++ ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 4)) { ++ phyhang_avoid_state = pi->phyhang_avoid; ++ pi->phyhang_avoid = false; ++ } ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save); ++ ++ for (core_no = 0; core_no <= 1; core_no++) { ++ wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain, ++ &cal_params[core_no]); ++ cal_gain[core_no] = cal_params[core_no].cal_gain; ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain); ++ ++ rxcore_state = wlc_phy_rxcore_getstate_nphy( ++ (struct brcms_phy_pub *) pi); ++ ++ for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) { ++ ++ skip_rxiqcal = ++ ((rxcore_state & (1 << rx_core)) == 0) ? true : false; ++ ++ wlc_phy_rxcal_physetup_nphy(pi, rx_core); ++ ++ wlc_phy_rxcal_radio_setup_nphy(pi, rx_core); ++ ++ if ((!skip_rxiqcal) && ((cal_type == 0) || (cal_type == 2))) { ++ ++ wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL, 0); ++ ++ wlc_phy_tx_tone_nphy(pi, ++ (CHSPEC_IS40( ++ pi->radio_chanspec)) ? ++ NPHY_RXCAL_TONEFREQ_40MHz : ++ NPHY_RXCAL_TONEFREQ_20MHz, ++ NPHY_RXCAL_TONEAMP, 0, cal_type, ++ false); ++ ++ if (debug) ++ mdelay(WAIT_FOR_SCOPE); ++ ++ wlc_phy_calc_rx_iq_comp_nphy(pi, rx_core + 1); ++ wlc_phy_stopplayback_nphy(pi); ++ } ++ ++ if (((cal_type == 1) || (cal_type == 2)) ++ && NREV_LT(pi->pubpi.phy_rev, 7)) { ++ ++ if (rx_core == PHY_CORE_1) { ++ ++ if (rxcore_state == 1) ++ wlc_phy_rxcore_setstate_nphy( ++ (struct brcms_phy_pub *) pi, 3); ++ ++ wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL, ++ 1); ++ ++ best_rccal[rx_core] = ++ wlc_phy_rc_sweep_nphy(pi, rx_core, 1); ++ pi->nphy_rccal_value = best_rccal[rx_core]; ++ ++ if (rxcore_state == 1) ++ wlc_phy_rxcore_setstate_nphy( ++ (struct brcms_phy_pub *) pi, ++ rxcore_state); ++ } ++ } ++ ++ wlc_phy_rxcal_radio_cleanup_nphy(pi, rx_core); ++ ++ wlc_phy_rxcal_phycleanup_nphy(pi, rx_core); ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); ++ } ++ ++ if ((cal_type == 1) || (cal_type == 2)) { ++ ++ best_rccal[0] = best_rccal[1]; ++ write_radio_reg(pi, ++ (RADIO_2056_RX_RXLPF_RCCAL_LPC | ++ RADIO_2056_RX0), (best_rccal[0] | 0x80)); ++ ++ for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) { ++ rxlpf_rccal_hpc = ++ (((int)best_rccal[rx_core] - 12) >> 1) + 10; ++ txlpf_rccal_lpc = ((int)best_rccal[rx_core] - 12) + 10; ++ ++ if (PHY_IPA(pi)) { ++ txlpf_rccal_lpc += ++ (pi->bw == WL_CHANSPEC_BW_40) ? 24 : 12; ++ txlpf_idac = (pi->bw == WL_CHANSPEC_BW_40) ? ++ 0x0e : 0x13; ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, rx_core, ++ TXLPF_IDAC_4, txlpf_idac); ++ } ++ ++ rxlpf_rccal_hpc = max(min_t(u8, rxlpf_rccal_hpc, 31), ++ 0); ++ txlpf_rccal_lpc = max(min_t(u8, txlpf_rccal_lpc, 31), ++ 0); ++ ++ write_radio_reg(pi, (RADIO_2056_RX_RXLPF_RCCAL_HPC | ++ ((rx_core == ++ PHY_CORE_0) ? RADIO_2056_RX0 : ++ RADIO_2056_RX1)), ++ (rxlpf_rccal_hpc | 0x80)); ++ ++ write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | ++ ((rx_core == ++ PHY_CORE_0) ? RADIO_2056_TX0 : ++ RADIO_2056_TX1)), ++ (txlpf_rccal_lpc | 0x80)); ++ } ++ } ++ ++ write_phy_reg(pi, 0x01, orig_BBConfig); ++ ++ wlc_phy_resetcca_nphy(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_rxgain, ++ 0, 0x3, 1); ++ else ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1); ++ ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, ++ gain_save); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 4)) ++ pi->phyhang_avoid = phyhang_avoid_state; ++ ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ ++ return 0; ++} ++ ++static int ++wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi, ++ struct nphy_txgains target_gain, bool debug) ++{ ++ struct phy_iq_est est[PHY_CORE_MAX]; ++ u8 core_num, rx_core, tx_core; ++ u16 lna_vals[] = { 0x3, 0x3, 0x1 }; ++ u16 hpf1_vals[] = { 0x7, 0x2, 0x0 }; ++ u16 hpf2_vals[] = { 0x2, 0x0, 0x0 }; ++ s16 curr_hpf1, curr_hpf2, curr_hpf, curr_lna; ++ s16 desired_log2_pwr, actual_log2_pwr, hpf_change; ++ u16 orig_RfseqCoreActv, orig_AfectrlCore, orig_AfectrlOverride; ++ u16 orig_RfctrlIntcRx, orig_RfctrlIntcTx; ++ u16 num_samps; ++ u32 i_pwr, q_pwr, tot_pwr[3]; ++ u8 gain_pass, use_hpf_num; ++ u16 mask, val1, val2; ++ u16 core_no; ++ u16 gain_save[2]; ++ u16 cal_gain[2]; ++ struct nphy_iqcal_params cal_params[2]; ++ u8 phy_bw; ++ int bcmerror = 0; ++ bool first_playtone = true; ++ ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) ++ wlc_phy_reapply_txcal_coeffs_nphy(pi); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save); ++ ++ for (core_no = 0; core_no <= 1; core_no++) { ++ wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain, ++ &cal_params[core_no]); ++ cal_gain[core_no] = cal_params[core_no].cal_gain; ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain); ++ ++ num_samps = 1024; ++ desired_log2_pwr = 13; ++ ++ for (core_num = 0; core_num < 2; core_num++) { ++ ++ rx_core = core_num; ++ tx_core = 1 - core_num; ++ ++ orig_RfseqCoreActv = read_phy_reg(pi, 0xa2); ++ orig_AfectrlCore = read_phy_reg(pi, (rx_core == PHY_CORE_0) ? ++ 0xa6 : 0xa7); ++ orig_AfectrlOverride = read_phy_reg(pi, 0xa5); ++ orig_RfctrlIntcRx = read_phy_reg(pi, (rx_core == PHY_CORE_0) ? ++ 0x91 : 0x92); ++ orig_RfctrlIntcTx = read_phy_reg(pi, (tx_core == PHY_CORE_0) ? ++ 0x91 : 0x92); ++ ++ mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12); ++ mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0); ++ ++ or_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7), ++ ((0x1 << 1) | (0x1 << 2))); ++ or_phy_reg(pi, 0xa5, ((0x1 << 1) | (0x1 << 2))); ++ ++ if (((pi->nphy_rxcalparams) & 0xff000000)) ++ write_phy_reg(pi, ++ (rx_core == PHY_CORE_0) ? 0x91 : 0x92, ++ (CHSPEC_IS5G(pi->radio_chanspec) ? ++ 0x140 : 0x110)); ++ else ++ write_phy_reg(pi, ++ (rx_core == PHY_CORE_0) ? 0x91 : 0x92, ++ (CHSPEC_IS5G(pi->radio_chanspec) ? ++ 0x180 : 0x120)); ++ ++ write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 : 0x92, ++ (CHSPEC_IS5G(pi->radio_chanspec) ? 0x148 : ++ 0x114)); ++ ++ mask = RADIO_2055_COUPLE_RX_MASK | RADIO_2055_COUPLE_TX_MASK; ++ if (rx_core == PHY_CORE_0) { ++ val1 = RADIO_2055_COUPLE_RX_MASK; ++ val2 = RADIO_2055_COUPLE_TX_MASK; ++ } else { ++ val1 = RADIO_2055_COUPLE_TX_MASK; ++ val2 = RADIO_2055_COUPLE_RX_MASK; ++ } ++ ++ if ((pi->nphy_rxcalparams & 0x10000)) { ++ mod_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, mask, ++ val1); ++ mod_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, mask, ++ val2); ++ } ++ ++ for (gain_pass = 0; gain_pass < 4; gain_pass++) { ++ ++ if (debug) ++ mdelay(WAIT_FOR_SCOPE); ++ ++ if (gain_pass < 3) { ++ curr_lna = lna_vals[gain_pass]; ++ curr_hpf1 = hpf1_vals[gain_pass]; ++ curr_hpf2 = hpf2_vals[gain_pass]; ++ } else { ++ ++ if (tot_pwr[1] > 10000) { ++ curr_lna = lna_vals[2]; ++ curr_hpf1 = hpf1_vals[2]; ++ curr_hpf2 = hpf2_vals[2]; ++ use_hpf_num = 1; ++ curr_hpf = curr_hpf1; ++ actual_log2_pwr = ++ wlc_phy_nbits(tot_pwr[2]); ++ } else { ++ if (tot_pwr[0] > 10000) { ++ curr_lna = lna_vals[1]; ++ curr_hpf1 = hpf1_vals[1]; ++ curr_hpf2 = hpf2_vals[1]; ++ use_hpf_num = 1; ++ curr_hpf = curr_hpf1; ++ actual_log2_pwr = ++ wlc_phy_nbits( ++ tot_pwr[1]); ++ } else { ++ curr_lna = lna_vals[0]; ++ curr_hpf1 = hpf1_vals[0]; ++ curr_hpf2 = hpf2_vals[0]; ++ use_hpf_num = 2; ++ curr_hpf = curr_hpf2; ++ actual_log2_pwr = ++ wlc_phy_nbits( ++ tot_pwr[0]); ++ } ++ } ++ ++ hpf_change = desired_log2_pwr - actual_log2_pwr; ++ curr_hpf += hpf_change; ++ curr_hpf = max(min_t(u16, curr_hpf, 10), 0); ++ if (use_hpf_num == 1) ++ curr_hpf1 = curr_hpf; ++ else ++ curr_hpf2 = curr_hpf; ++ } ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10), ++ ((curr_hpf2 << 8) | ++ (curr_hpf1 << 4) | ++ (curr_lna << 2)), 0x3, 0); ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); ++ ++ wlc_phy_stopplayback_nphy(pi); ++ ++ if (first_playtone) { ++ bcmerror = wlc_phy_tx_tone_nphy(pi, 4000, ++ (u16) (pi->nphy_rxcalparams & ++ 0xffff), 0, 0, true); ++ first_playtone = false; ++ } else { ++ phy_bw = (CHSPEC_IS40(pi->radio_chanspec)) ? ++ 40 : 20; ++ wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff, ++ 0, 0, 0, true); ++ } ++ ++ if (bcmerror == 0) { ++ if (gain_pass < 3) { ++ ++ wlc_phy_rx_iq_est_nphy(pi, est, ++ num_samps, 32, ++ 0); ++ i_pwr = (est[rx_core].i_pwr + ++ num_samps / 2) / num_samps; ++ q_pwr = (est[rx_core].q_pwr + ++ num_samps / 2) / num_samps; ++ tot_pwr[gain_pass] = i_pwr + q_pwr; ++ } else { ++ ++ wlc_phy_calc_rx_iq_comp_nphy(pi, ++ (1 << ++ rx_core)); ++ } ++ ++ wlc_phy_stopplayback_nphy(pi); ++ } ++ ++ if (bcmerror != 0) ++ break; ++ } ++ ++ and_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, ~mask); ++ and_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, ~mask); ++ ++ write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 : ++ 0x92, orig_RfctrlIntcTx); ++ write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x91 : ++ 0x92, orig_RfctrlIntcRx); ++ write_phy_reg(pi, 0xa5, orig_AfectrlOverride); ++ write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : ++ 0xa7, orig_AfectrlCore); ++ write_phy_reg(pi, 0xa2, orig_RfseqCoreActv); ++ ++ if (bcmerror != 0) ++ break; ++ } ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10), 0, 0x3, 1); ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, ++ gain_save); ++ ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ ++ return bcmerror; ++} ++ ++int ++wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, ++ u8 cal_type, bool debug) ++{ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ cal_type = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ return wlc_phy_cal_rxiq_nphy_rev3(pi, target_gain, cal_type, ++ debug); ++ else ++ return wlc_phy_cal_rxiq_nphy_rev2(pi, target_gain, debug); ++} ++ ++void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi) ++{ ++ uint core; ++ u32 txgain; ++ u16 rad_gain, dac_gain, bbmult, m1m2; ++ u8 txpi[2], chan_freq_range; ++ s32 rfpwr_offset; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ if (pi->sh->sromrev < 4) { ++ txpi[0] = txpi[1] = 72; ++ } else { ++ ++ chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0); ++ switch (chan_freq_range) { ++ case WL_CHAN_FREQ_RANGE_2G: ++ txpi[0] = pi->nphy_txpid2g[0]; ++ txpi[1] = pi->nphy_txpid2g[1]; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GL: ++ txpi[0] = pi->nphy_txpid5gl[0]; ++ txpi[1] = pi->nphy_txpid5gl[1]; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GM: ++ txpi[0] = pi->nphy_txpid5g[0]; ++ txpi[1] = pi->nphy_txpid5g[1]; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GH: ++ txpi[0] = pi->nphy_txpid5gh[0]; ++ txpi[1] = pi->nphy_txpid5gh[1]; ++ break; ++ default: ++ txpi[0] = txpi[1] = 91; ++ break; ++ } ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ txpi[0] = txpi[1] = 30; ++ else if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ txpi[0] = txpi[1] = 40; ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 7)) { ++ ++ if ((txpi[0] < 40) || (txpi[0] > 100) || ++ (txpi[1] < 40) || (txpi[1] > 100)) ++ txpi[0] = txpi[1] = 91; ++ } ++ ++ pi->nphy_txpwrindex[PHY_CORE_0].index_internal = txpi[0]; ++ pi->nphy_txpwrindex[PHY_CORE_1].index_internal = txpi[1]; ++ pi->nphy_txpwrindex[PHY_CORE_0].index_internal_save = txpi[0]; ++ pi->nphy_txpwrindex[PHY_CORE_1].index_internal_save = txpi[1]; ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ uint phyrev = pi->pubpi.phy_rev; ++ ++ if (NREV_GE(phyrev, 3)) { ++ if (PHY_IPA(pi)) { ++ u32 *tx_gaintbl = ++ wlc_phy_get_ipa_gaintbl_nphy(pi); ++ txgain = tx_gaintbl[txpi[core]]; ++ } else { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (NREV_IS(phyrev, 3)) { ++ txgain = ++ nphy_tpc_5GHz_txgain_rev3 ++ [txpi[core]]; ++ } else if (NREV_IS(phyrev, 4)) { ++ txgain = ( ++ pi->srom_fem5g.extpagain == ++ 3) ? ++ nphy_tpc_5GHz_txgain_HiPwrEPA ++ [txpi[core]] : ++ nphy_tpc_5GHz_txgain_rev4 ++ [txpi[core]]; ++ } else { ++ txgain = ++ nphy_tpc_5GHz_txgain_rev5 ++ [txpi[core]]; ++ } ++ } else { ++ if (NREV_GE(phyrev, 5) && ++ (pi->srom_fem2g.extpagain == 3)) { ++ txgain = ++ nphy_tpc_txgain_HiPwrEPA ++ [txpi[core]]; ++ } else { ++ txgain = nphy_tpc_txgain_rev3 ++ [txpi[core]]; ++ } ++ } ++ } ++ } else { ++ txgain = nphy_tpc_txgain[txpi[core]]; ++ } ++ ++ if (NREV_GE(phyrev, 3)) ++ rad_gain = (txgain >> 16) & ((1 << (32 - 16 + 1)) - 1); ++ else ++ rad_gain = (txgain >> 16) & ((1 << (28 - 16 + 1)) - 1); ++ ++ if (NREV_GE(phyrev, 7)) ++ dac_gain = (txgain >> 8) & ((1 << (10 - 8 + 1)) - 1); ++ else ++ dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1); ++ ++ bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1); ++ ++ if (NREV_GE(phyrev, 3)) ++ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f : ++ 0xa5), (0x1 << 8), (0x1 << 8)); ++ else ++ mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14)); ++ ++ write_phy_reg(pi, (core == PHY_CORE_0) ? 0xaa : 0xab, dac_gain); ++ ++ wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16, ++ &rad_gain); ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2); ++ m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00); ++ m1m2 |= ((core == PHY_CORE_0) ? (bbmult << 8) : (bbmult << 0)); ++ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2); ++ ++ if (PHY_IPA(pi)) { ++ wlc_phy_table_read_nphy(pi, ++ (core == ++ PHY_CORE_0 ? ++ NPHY_TBL_ID_CORE1TXPWRCTL : ++ NPHY_TBL_ID_CORE2TXPWRCTL), 1, ++ 576 + txpi[core], 32, ++ &rfpwr_offset); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1ff << 4), ++ ((s16) rfpwr_offset) << 4); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 2), (1) << 2); ++ ++ } ++ } ++ ++ and_phy_reg(pi, 0xbf, (u16) (~(0x1f << 0))); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static void ++wlc_phy_txpwr_nphy_srom_convert(u8 *srom_max, u16 *pwr_offset, ++ u8 tmp_max_pwr, u8 rate_start, ++ u8 rate_end) ++{ ++ u8 rate; ++ u8 word_num, nibble_num; ++ u8 tmp_nibble; ++ ++ for (rate = rate_start; rate <= rate_end; rate++) { ++ word_num = (rate - rate_start) >> 2; ++ nibble_num = (rate - rate_start) & 0x3; ++ tmp_nibble = (pwr_offset[word_num] >> 4 * nibble_num) & 0xf; ++ ++ srom_max[rate] = tmp_max_pwr - 2 * tmp_nibble; ++ } ++} ++ ++static void ++wlc_phy_txpwr_nphy_po_apply(u8 *srom_max, u8 pwr_offset, ++ u8 rate_start, u8 rate_end) ++{ ++ u8 rate; ++ ++ for (rate = rate_start; rate <= rate_end; rate++) ++ srom_max[rate] -= 2 * pwr_offset; ++} ++ ++void ++wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start, ++ u8 rate_mcs_end, u8 rate_ofdm_start) ++{ ++ u8 rate1, rate2; ++ ++ rate2 = rate_ofdm_start; ++ for (rate1 = rate_mcs_start; rate1 <= rate_mcs_end - 1; rate1++) { ++ power[rate1] = power[rate2]; ++ rate2 += (rate1 == rate_mcs_start) ? 2 : 1; ++ } ++ power[rate_mcs_end] = power[rate_mcs_end - 1]; ++} ++ ++void ++wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power, u8 rate_ofdm_start, ++ u8 rate_ofdm_end, u8 rate_mcs_start) ++{ ++ u8 rate1, rate2; ++ ++ for (rate1 = rate_ofdm_start, rate2 = rate_mcs_start; ++ rate1 <= rate_ofdm_end; rate1++, rate2++) { ++ power[rate1] = power[rate2]; ++ if (rate1 == rate_ofdm_start) ++ power[++rate1] = power[rate2]; ++ } ++} ++ ++void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi) ++{ ++ uint rate1, rate2, band_num; ++ u8 tmp_bw40po = 0, tmp_cddpo = 0, tmp_stbcpo = 0; ++ u8 tmp_max_pwr = 0; ++ u16 pwr_offsets1[2], *pwr_offsets2 = NULL; ++ u8 *tx_srom_max_rate = NULL; ++ ++ for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); ++ band_num++) { ++ switch (band_num) { ++ case 0: ++ ++ tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_2g, ++ pi->nphy_pwrctrl_info[1].max_pwr_2g); ++ ++ pwr_offsets1[0] = pi->cck2gpo; ++ wlc_phy_txpwr_nphy_srom_convert(pi->tx_srom_max_rate_2g, ++ pwr_offsets1, ++ tmp_max_pwr, ++ TXP_FIRST_CCK, ++ TXP_LAST_CCK); ++ ++ pwr_offsets1[0] = (u16) (pi->ofdm2gpo & 0xffff); ++ pwr_offsets1[1] = ++ (u16) (pi->ofdm2gpo >> 16) & 0xffff; ++ ++ pwr_offsets2 = pi->mcs2gpo; ++ ++ tmp_cddpo = pi->cdd2gpo; ++ tmp_stbcpo = pi->stbc2gpo; ++ tmp_bw40po = pi->bw402gpo; ++ ++ tx_srom_max_rate = pi->tx_srom_max_rate_2g; ++ break; ++ case 1: ++ ++ tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gm, ++ pi->nphy_pwrctrl_info[1].max_pwr_5gm); ++ ++ pwr_offsets1[0] = (u16) (pi->ofdm5gpo & 0xffff); ++ pwr_offsets1[1] = ++ (u16) (pi->ofdm5gpo >> 16) & 0xffff; ++ ++ pwr_offsets2 = pi->mcs5gpo; ++ ++ tmp_cddpo = pi->cdd5gpo; ++ tmp_stbcpo = pi->stbc5gpo; ++ tmp_bw40po = pi->bw405gpo; ++ ++ tx_srom_max_rate = pi->tx_srom_max_rate_5g_mid; ++ break; ++ case 2: ++ ++ tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gl, ++ pi->nphy_pwrctrl_info[1].max_pwr_5gl); ++ ++ pwr_offsets1[0] = (u16) (pi->ofdm5glpo & 0xffff); ++ pwr_offsets1[1] = ++ (u16) (pi->ofdm5glpo >> 16) & 0xffff; ++ ++ pwr_offsets2 = pi->mcs5glpo; ++ ++ tmp_cddpo = pi->cdd5glpo; ++ tmp_stbcpo = pi->stbc5glpo; ++ tmp_bw40po = pi->bw405glpo; ++ ++ tx_srom_max_rate = pi->tx_srom_max_rate_5g_low; ++ break; ++ case 3: ++ ++ tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gh, ++ pi->nphy_pwrctrl_info[1].max_pwr_5gh); ++ ++ pwr_offsets1[0] = (u16) (pi->ofdm5ghpo & 0xffff); ++ pwr_offsets1[1] = ++ (u16) (pi->ofdm5ghpo >> 16) & 0xffff; ++ ++ pwr_offsets2 = pi->mcs5ghpo; ++ ++ tmp_cddpo = pi->cdd5ghpo; ++ tmp_stbcpo = pi->stbc5ghpo; ++ tmp_bw40po = pi->bw405ghpo; ++ ++ tx_srom_max_rate = pi->tx_srom_max_rate_5g_hi; ++ break; ++ } ++ ++ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets1, ++ tmp_max_pwr, TXP_FIRST_OFDM, ++ TXP_LAST_OFDM); ++ ++ wlc_phy_ofdm_to_mcs_powers_nphy(tx_srom_max_rate, ++ TXP_FIRST_MCS_20_SISO, ++ TXP_LAST_MCS_20_SISO, ++ TXP_FIRST_OFDM); ++ ++ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets2, ++ tmp_max_pwr, ++ TXP_FIRST_MCS_20_CDD, ++ TXP_LAST_MCS_20_CDD); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo, ++ TXP_FIRST_MCS_20_CDD, ++ TXP_LAST_MCS_20_CDD); ++ ++ wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate, ++ TXP_FIRST_OFDM_20_CDD, ++ TXP_LAST_OFDM_20_CDD, ++ TXP_FIRST_MCS_20_CDD); ++ ++ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets2, ++ tmp_max_pwr, ++ TXP_FIRST_MCS_20_STBC, ++ TXP_LAST_MCS_20_STBC); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, ++ tmp_stbcpo, ++ TXP_FIRST_MCS_20_STBC, ++ TXP_LAST_MCS_20_STBC); ++ ++ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, ++ &pwr_offsets2[2], tmp_max_pwr, ++ TXP_FIRST_MCS_20_SDM, ++ TXP_LAST_MCS_20_SDM); ++ ++ if (NPHY_IS_SROM_REINTERPRET) { ++ ++ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, ++ &pwr_offsets2[4], ++ tmp_max_pwr, ++ TXP_FIRST_MCS_40_SISO, ++ TXP_LAST_MCS_40_SISO); ++ ++ wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate, ++ TXP_FIRST_OFDM_40_SISO, ++ TXP_LAST_OFDM_40_SISO, ++ TXP_FIRST_MCS_40_SISO); ++ ++ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, ++ &pwr_offsets2[4], ++ tmp_max_pwr, ++ TXP_FIRST_MCS_40_CDD, ++ TXP_LAST_MCS_40_CDD); ++ ++ wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo, ++ TXP_FIRST_MCS_40_CDD, ++ TXP_LAST_MCS_40_CDD); ++ ++ wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate, ++ TXP_FIRST_OFDM_40_CDD, ++ TXP_LAST_OFDM_40_CDD, ++ TXP_FIRST_MCS_40_CDD); ++ ++ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, ++ &pwr_offsets2[4], ++ tmp_max_pwr, ++ TXP_FIRST_MCS_40_STBC, ++ TXP_LAST_MCS_40_STBC); ++ ++ wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, ++ tmp_stbcpo, ++ TXP_FIRST_MCS_40_STBC, ++ TXP_LAST_MCS_40_STBC); ++ ++ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, ++ &pwr_offsets2[6], ++ tmp_max_pwr, ++ TXP_FIRST_MCS_40_SDM, ++ TXP_LAST_MCS_40_SDM); ++ } else { ++ ++ for (rate1 = TXP_FIRST_OFDM_40_SISO, rate2 = ++ TXP_FIRST_OFDM; ++ rate1 <= TXP_LAST_MCS_40_SDM; ++ rate1++, rate2++) ++ tx_srom_max_rate[rate1] = ++ tx_srom_max_rate[rate2]; ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, ++ tmp_bw40po, ++ TXP_FIRST_OFDM_40_SISO, ++ TXP_LAST_MCS_40_SDM); ++ ++ tx_srom_max_rate[TXP_MCS_32] = ++ tx_srom_max_rate[TXP_FIRST_MCS_40_CDD]; ++ } ++ ++ return; ++} ++ ++void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi) ++{ ++ u8 tx_pwr_ctrl_state; ++ wlc_phy_txpwr_limit_to_tbl_nphy(pi); ++ wlc_phy_txpwrctrl_pwr_setup_nphy(pi); ++ ++ tx_pwr_ctrl_state = pi->nphy_txpwrctrl; ++ ++ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) { ++ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK); ++ (void)R_REG(&pi->regs->maccontrol); ++ udelay(1); ++ } ++ ++ wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state); ++ ++ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) ++ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0); ++} ++ ++static bool wlc_phy_txpwr_ison_nphy(struct brcms_phy *pi) ++{ ++ return read_phy_reg((pi), 0x1e7) & ((0x1 << 15) | ++ (0x1 << 14) | (0x1 << 13)); ++} ++ ++u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi) ++{ ++ u16 tmp; ++ u16 pwr_idx[2]; ++ ++ if (wlc_phy_txpwr_ison_nphy(pi)) { ++ pwr_idx[0] = wlc_phy_txpwr_idx_cur_get_nphy(pi, PHY_CORE_0); ++ pwr_idx[1] = wlc_phy_txpwr_idx_cur_get_nphy(pi, PHY_CORE_1); ++ ++ tmp = (pwr_idx[0] << 8) | pwr_idx[1]; ++ } else { ++ tmp = ((pi->nphy_txpwrindex[PHY_CORE_0].index_internal & 0xff) ++ << 8) | ++ (pi->nphy_txpwrindex[PHY_CORE_1].index_internal & 0xff); ++ } ++ ++ return tmp; ++} ++ ++void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi) ++{ ++ if (PHY_IPA(pi) ++ && (pi->nphy_force_papd_cal ++ || (wlc_phy_txpwr_ison_nphy(pi) ++ && ++ (((u32) ++ abs(wlc_phy_txpwr_idx_cur_get_nphy(pi, 0) - ++ pi->nphy_papd_tx_gain_at_last_cal[0]) >= 4) ++ || ((u32) ++ abs(wlc_phy_txpwr_idx_cur_get_nphy(pi, 1) - ++ pi->nphy_papd_tx_gain_at_last_cal[1]) >= 4))))) ++ wlc_phy_a4(pi, true); ++} ++ ++void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type) ++{ ++ u16 mask = 0, val = 0, ishw = 0; ++ u8 ctr; ++ uint core; ++ u32 tbl_offset; ++ u32 tbl_len; ++ u16 regval[84]; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ switch (ctrl_type) { ++ case PHY_TPC_HW_OFF: ++ case PHY_TPC_HW_ON: ++ pi->nphy_txpwrctrl = ctrl_type; ++ break; ++ default: ++ break; ++ } ++ ++ if (ctrl_type == PHY_TPC_HW_OFF) { ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ if (wlc_phy_txpwr_ison_nphy(pi)) { ++ for (core = 0; core < pi->pubpi.phy_corenum; ++ core++) ++ pi->nphy_txpwr_idx[core] = ++ wlc_phy_txpwr_idx_cur_get_nphy( ++ pi, ++ (u8) core); ++ } ++ ++ } ++ ++ tbl_len = 84; ++ tbl_offset = 64; ++ for (ctr = 0; ctr < tbl_len; ctr++) ++ regval[ctr] = 0; ++ wlc_phy_table_write_nphy(pi, 26, tbl_len, tbl_offset, 16, ++ regval); ++ wlc_phy_table_write_nphy(pi, 27, tbl_len, tbl_offset, 16, ++ regval); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ and_phy_reg(pi, 0x1e7, ++ (u16) (~((0x1 << 15) | ++ (0x1 << 14) | (0x1 << 13)))); ++ else ++ and_phy_reg(pi, 0x1e7, ++ (u16) (~((0x1 << 14) | (0x1 << 13)))); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ or_phy_reg(pi, 0x8f, (0x1 << 8)); ++ or_phy_reg(pi, 0xa5, (0x1 << 8)); ++ } else { ++ or_phy_reg(pi, 0xa5, (0x1 << 14)); ++ } ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 2)) ++ mod_phy_reg(pi, 0xdc, 0x00ff, 0x53); ++ else if (NREV_LT(pi->pubpi.phy_rev, 2)) ++ mod_phy_reg(pi, 0xdc, 0x00ff, 0x5a); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2) && ++ pi->bw == WL_CHANSPEC_BW_40) ++ wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR, ++ MHF1_IQSWAP_WAR, BRCM_BAND_ALL); ++ ++ } else { ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64, ++ 8, pi->adj_pwr_tbl_nphy); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64, ++ 8, pi->adj_pwr_tbl_nphy); ++ ++ ishw = (ctrl_type == PHY_TPC_HW_ON) ? 0x1 : 0x0; ++ mask = (0x1 << 14) | (0x1 << 13); ++ val = (ishw << 14) | (ishw << 13); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ mask |= (0x1 << 15); ++ val |= (ishw << 15); ++ } ++ ++ mod_phy_reg(pi, 0x1e7, mask, val); ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ mod_phy_reg(pi, 0x1e7, (0x7f << 0), 0x32); ++ mod_phy_reg(pi, 0x222, (0xff << 0), 0x32); ++ } else { ++ mod_phy_reg(pi, 0x1e7, (0x7f << 0), 0x64); ++ if (NREV_GT(pi->pubpi.phy_rev, 1)) ++ mod_phy_reg(pi, 0x222, ++ (0xff << 0), 0x64); ++ } ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if ((pi->nphy_txpwr_idx[0] != 128) ++ && (pi->nphy_txpwr_idx[1] != 128)) ++ wlc_phy_txpwr_idx_cur_set_nphy(pi, ++ pi-> ++ nphy_txpwr_idx ++ [0], ++ pi-> ++ nphy_txpwr_idx ++ [1]); ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ and_phy_reg(pi, 0x8f, ~(0x1 << 8)); ++ and_phy_reg(pi, 0xa5, ~(0x1 << 8)); ++ } else { ++ and_phy_reg(pi, 0xa5, ~(0x1 << 14)); ++ } ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 2)) ++ mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b); ++ else if (NREV_LT(pi->pubpi.phy_rev, 2)) ++ mod_phy_reg(pi, 0xdc, 0x00ff, 0x40); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2) && ++ pi->bw == WL_CHANSPEC_BW_40) ++ wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR, ++ 0x0, BRCM_BAND_ALL); ++ ++ if (PHY_IPA(pi)) { ++ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 2), (0) << 2); ++ ++ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 2), (0) << 2); ++ ++ } ++ ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++void ++wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex, ++ bool restore_cals) ++{ ++ u8 core, txpwrctl_tbl; ++ u16 tx_ind0, iq_ind0, lo_ind0; ++ u16 m1m2; ++ u32 txgain; ++ u16 rad_gain, dac_gain; ++ u8 bbmult; ++ u32 iqcomp; ++ u16 iqcomp_a, iqcomp_b; ++ u32 locomp; ++ u16 tmpval; ++ u8 tx_pwr_ctrl_state; ++ s32 rfpwr_offset; ++ u16 regval[2]; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ tx_ind0 = 192; ++ iq_ind0 = 320; ++ lo_ind0 = 448; ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ ++ if ((core_mask & (1 << core)) == 0) ++ continue; ++ ++ txpwrctl_tbl = (core == PHY_CORE_0) ? 26 : 27; ++ ++ if (txpwrindex < 0) { ++ if (pi->nphy_txpwrindex[core].index < 0) ++ continue; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ mod_phy_reg(pi, 0x8f, ++ (0x1 << 8), ++ pi->nphy_txpwrindex[core]. ++ AfectrlOverride); ++ mod_phy_reg(pi, 0xa5, (0x1 << 8), ++ pi->nphy_txpwrindex[core]. ++ AfectrlOverride); ++ } else { ++ mod_phy_reg(pi, 0xa5, ++ (0x1 << 14), ++ pi->nphy_txpwrindex[core]. ++ AfectrlOverride); ++ } ++ ++ write_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0xaa : 0xab, ++ pi->nphy_txpwrindex[core].AfeCtrlDacGain); ++ ++ wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16, ++ &pi->nphy_txpwrindex[core]. ++ rad_gain); ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2); ++ m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00); ++ m1m2 |= ((core == PHY_CORE_0) ? ++ (pi->nphy_txpwrindex[core].bbmult << 8) : ++ (pi->nphy_txpwrindex[core].bbmult << 0)); ++ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2); ++ ++ if (restore_cals) { ++ wlc_phy_table_write_nphy( ++ pi, 15, 2, (80 + 2 * core), 16, ++ &pi->nphy_txpwrindex[core].iqcomp_a); ++ wlc_phy_table_write_nphy( ++ pi, 15, 1, (85 + core), 16, ++ &pi->nphy_txpwrindex[core].locomp); ++ wlc_phy_table_write_nphy( ++ pi, 15, 1, (93 + core), 16, ++ &pi->nphy_txpwrindex[core].locomp); ++ } ++ ++ wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl); ++ ++ pi->nphy_txpwrindex[core].index_internal = ++ pi->nphy_txpwrindex[core].index_internal_save; ++ } else { ++ ++ if (pi->nphy_txpwrindex[core].index < 0) { ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ mod_phy_reg(pi, 0x8f, ++ (0x1 << 8), ++ pi->nphy_txpwrindex[core]. ++ AfectrlOverride); ++ mod_phy_reg(pi, 0xa5, (0x1 << 8), ++ pi->nphy_txpwrindex[core]. ++ AfectrlOverride); ++ } else { ++ pi->nphy_txpwrindex[core]. ++ AfectrlOverride = ++ read_phy_reg(pi, 0xa5); ++ } ++ ++ pi->nphy_txpwrindex[core].AfeCtrlDacGain = ++ read_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0xaa : 0xab); ++ ++ wlc_phy_table_read_nphy(pi, 7, 1, ++ (0x110 + core), 16, ++ &pi-> ++ nphy_txpwrindex[core]. ++ rad_gain); ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, ++ &tmpval); ++ tmpval >>= ((core == PHY_CORE_0) ? 8 : 0); ++ tmpval &= 0xff; ++ pi->nphy_txpwrindex[core].bbmult = (u8) tmpval; ++ ++ wlc_phy_table_read_nphy(pi, 15, 2, ++ (80 + 2 * core), 16, ++ &pi-> ++ nphy_txpwrindex[core]. ++ iqcomp_a); ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, (85 + core), ++ 16, ++ &pi-> ++ nphy_txpwrindex[core]. ++ locomp); ++ ++ pi->nphy_txpwrindex[core].index_internal_save = ++ pi->nphy_txpwrindex[core]. ++ index_internal; ++ } ++ ++ tx_pwr_ctrl_state = pi->nphy_txpwrctrl; ++ wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF); ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 1)) ++ wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON); ++ ++ wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1, ++ (tx_ind0 + txpwrindex), 32, ++ &txgain); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ rad_gain = (txgain >> 16) & ++ ((1 << (32 - 16 + 1)) - 1); ++ else ++ rad_gain = (txgain >> 16) & ++ ((1 << (28 - 16 + 1)) - 1); ++ ++ dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1); ++ bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f : ++ 0xa5), (0x1 << 8), (0x1 << 8)); ++ else ++ mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14)); ++ ++ write_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0xaa : 0xab, dac_gain); ++ ++ wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16, ++ &rad_gain); ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2); ++ m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00); ++ m1m2 |= ((core == PHY_CORE_0) ? ++ (bbmult << 8) : (bbmult << 0)); ++ ++ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2); ++ ++ wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1, ++ (iq_ind0 + txpwrindex), 32, ++ &iqcomp); ++ iqcomp_a = (iqcomp >> 10) & ((1 << (19 - 10 + 1)) - 1); ++ iqcomp_b = (iqcomp >> 0) & ((1 << (9 - 0 + 1)) - 1); ++ ++ if (restore_cals) { ++ regval[0] = (u16) iqcomp_a; ++ regval[1] = (u16) iqcomp_b; ++ wlc_phy_table_write_nphy(pi, 15, 2, ++ (80 + 2 * core), 16, ++ regval); ++ } ++ ++ wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1, ++ (lo_ind0 + txpwrindex), 32, ++ &locomp); ++ if (restore_cals) ++ wlc_phy_table_write_nphy(pi, 15, 1, (85 + core), ++ 16, &locomp); ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 1)) ++ wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF); ++ ++ if (PHY_IPA(pi)) { ++ wlc_phy_table_read_nphy(pi, ++ (core == PHY_CORE_0 ? ++ NPHY_TBL_ID_CORE1TXPWRCTL : ++ NPHY_TBL_ID_CORE2TXPWRCTL), ++ 1, 576 + txpwrindex, 32, ++ &rfpwr_offset); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1ff << 4), ++ ((s16) rfpwr_offset) << 4); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 2), (1) << 2); ++ ++ } ++ ++ wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state); ++ } ++ ++ pi->nphy_txpwrindex[core].index = txpwrindex; ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++void ++wlc_phy_txpower_sromlimit_get_nphy(struct brcms_phy *pi, uint chan, u8 *max_pwr, ++ u8 txp_rate_idx) ++{ ++ u8 chan_freq_range; ++ ++ chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, chan); ++ switch (chan_freq_range) { ++ case WL_CHAN_FREQ_RANGE_2G: ++ *max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx]; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GM: ++ *max_pwr = pi->tx_srom_max_rate_5g_mid[txp_rate_idx]; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GL: ++ *max_pwr = pi->tx_srom_max_rate_5g_low[txp_rate_idx]; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GH: ++ *max_pwr = pi->tx_srom_max_rate_5g_hi[txp_rate_idx]; ++ break; ++ default: ++ *max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx]; ++ break; ++ } ++ ++ return; ++} ++ ++void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi, bool enable) ++{ ++ u16 clip_off[] = { 0xffff, 0xffff }; ++ ++ if (enable) { ++ if (pi->nphy_deaf_count == 0) { ++ pi->classifier_state = ++ wlc_phy_classifier_nphy(pi, 0, 0); ++ wlc_phy_classifier_nphy(pi, (0x7 << 0), 4); ++ wlc_phy_clip_det_nphy(pi, 0, pi->clip_state); ++ wlc_phy_clip_det_nphy(pi, 1, clip_off); ++ } ++ ++ pi->nphy_deaf_count++; ++ ++ wlc_phy_resetcca_nphy(pi); ++ ++ } else { ++ pi->nphy_deaf_count--; ++ ++ if (pi->nphy_deaf_count == 0) { ++ wlc_phy_classifier_nphy(pi, (0x7 << 0), ++ pi->classifier_state); ++ wlc_phy_clip_det_nphy(pi, 1, pi->clip_state); ++ } ++ } ++} ++ ++void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode) ++{ ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ if (mode) { ++ if (pi->nphy_deaf_count == 0) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ } else if (pi->nphy_deaf_count > 0) { ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ } ++ ++ wlapi_enable_mac(pi->sh->physhim); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.c.orig 2011-11-09 13:46:58.276800245 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.c 2011-11-09 13:47:17.032565765 -0500 +@@ -0,0 +1,308 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include "phy_qmath.h" ++ ++/* ++ * Description: This function make 16 bit unsigned multiplication. ++ * To fit the output into 16 bits the 32 bit multiplication result is right ++ * shifted by 16 bits. ++ */ ++u16 qm_mulu16(u16 op1, u16 op2) ++{ ++ return (u16) (((u32) op1 * (u32) op2) >> 16); ++} ++ ++/* ++ * Description: This function make 16 bit multiplication and return the result ++ * in 16 bits. To fit the multiplication result into 16 bits the multiplication ++ * result is right shifted by 15 bits. Right shifting 15 bits instead of 16 bits ++ * is done to remove the extra sign bit formed due to the multiplication. ++ * When both the 16bit inputs are 0x8000 then the output is saturated to ++ * 0x7fffffff. ++ */ ++s16 qm_muls16(s16 op1, s16 op2) ++{ ++ s32 result; ++ if (op1 == (s16) 0x8000 && op2 == (s16) 0x8000) ++ result = 0x7fffffff; ++ else ++ result = ((s32) (op1) * (s32) (op2)); ++ ++ return (s16) (result >> 15); ++} ++ ++/* ++ * Description: This function add two 32 bit numbers and return the 32bit ++ * result. If the result overflow 32 bits, the output will be saturated to ++ * 32bits. ++ */ ++s32 qm_add32(s32 op1, s32 op2) ++{ ++ s32 result; ++ result = op1 + op2; ++ if (op1 < 0 && op2 < 0 && result > 0) ++ result = 0x80000000; ++ else if (op1 > 0 && op2 > 0 && result < 0) ++ result = 0x7fffffff; ++ ++ return result; ++} ++ ++/* ++ * Description: This function add two 16 bit numbers and return the 16bit ++ * result. If the result overflow 16 bits, the output will be saturated to ++ * 16bits. ++ */ ++s16 qm_add16(s16 op1, s16 op2) ++{ ++ s16 result; ++ s32 temp = (s32) op1 + (s32) op2; ++ if (temp > (s32) 0x7fff) ++ result = (s16) 0x7fff; ++ else if (temp < (s32) 0xffff8000) ++ result = (s16) 0xffff8000; ++ else ++ result = (s16) temp; ++ ++ return result; ++} ++ ++/* ++ * Description: This function make 16 bit subtraction and return the 16bit ++ * result. If the result overflow 16 bits, the output will be saturated to ++ * 16bits. ++ */ ++s16 qm_sub16(s16 op1, s16 op2) ++{ ++ s16 result; ++ s32 temp = (s32) op1 - (s32) op2; ++ if (temp > (s32) 0x7fff) ++ result = (s16) 0x7fff; ++ else if (temp < (s32) 0xffff8000) ++ result = (s16) 0xffff8000; ++ else ++ result = (s16) temp; ++ ++ return result; ++} ++ ++/* ++ * Description: This function make a 32 bit saturated left shift when the ++ * specified shift is +ve. This function will make a 32 bit right shift when ++ * the specified shift is -ve. This function return the result after shifting ++ * operation. ++ */ ++s32 qm_shl32(s32 op, int shift) ++{ ++ int i; ++ s32 result; ++ result = op; ++ if (shift > 31) ++ shift = 31; ++ else if (shift < -31) ++ shift = -31; ++ if (shift >= 0) { ++ for (i = 0; i < shift; i++) ++ result = qm_add32(result, result); ++ } else { ++ result = result >> (-shift); ++ } ++ ++ return result; ++} ++ ++/* ++ * Description: This function make a 16 bit saturated left shift when the ++ * specified shift is +ve. This function will make a 16 bit right shift when ++ * the specified shift is -ve. This function return the result after shifting ++ * operation. ++ */ ++s16 qm_shl16(s16 op, int shift) ++{ ++ int i; ++ s16 result; ++ result = op; ++ if (shift > 15) ++ shift = 15; ++ else if (shift < -15) ++ shift = -15; ++ if (shift > 0) { ++ for (i = 0; i < shift; i++) ++ result = qm_add16(result, result); ++ } else { ++ result = result >> (-shift); ++ } ++ ++ return result; ++} ++ ++/* ++ * Description: This function make a 16 bit right shift when shift is +ve. ++ * This function make a 16 bit saturated left shift when shift is -ve. This ++ * function return the result of the shift operation. ++ */ ++s16 qm_shr16(s16 op, int shift) ++{ ++ return qm_shl16(op, -shift); ++} ++ ++/* ++ * Description: This function return the number of redundant sign bits in a ++ * 32 bit number. Example: qm_norm32(0x00000080) = 23 ++ */ ++s16 qm_norm32(s32 op) ++{ ++ u16 u16extraSignBits; ++ if (op == 0) { ++ return 31; ++ } else { ++ u16extraSignBits = 0; ++ while ((op >> 31) == (op >> 30)) { ++ u16extraSignBits++; ++ op = op << 1; ++ } ++ } ++ return u16extraSignBits; ++} ++ ++/* This table is log2(1+(i/32)) where i=[0:1:31], in q.15 format */ ++static const s16 log_table[] = { ++ 0, ++ 1455, ++ 2866, ++ 4236, ++ 5568, ++ 6863, ++ 8124, ++ 9352, ++ 10549, ++ 11716, ++ 12855, ++ 13968, ++ 15055, ++ 16117, ++ 17156, ++ 18173, ++ 19168, ++ 20143, ++ 21098, ++ 22034, ++ 22952, ++ 23852, ++ 24736, ++ 25604, ++ 26455, ++ 27292, ++ 28114, ++ 28922, ++ 29717, ++ 30498, ++ 31267, ++ 32024 ++}; ++ ++#define LOG_TABLE_SIZE 32 /* log_table size */ ++#define LOG2_LOG_TABLE_SIZE 5 /* log2(log_table size) */ ++#define Q_LOG_TABLE 15 /* qformat of log_table */ ++#define LOG10_2 19728 /* log10(2) in q.16 */ ++ ++/* ++ * Description: ++ * This routine takes the input number N and its q format qN and compute ++ * the log10(N). This routine first normalizes the input no N. Then N is in ++ * mag*(2^x) format. mag is any number in the range 2^30-(2^31 - 1). ++ * Then log2(mag * 2^x) = log2(mag) + x is computed. From that ++ * log10(mag * 2^x) = log2(mag * 2^x) * log10(2) is computed. ++ * This routine looks the log2 value in the table considering ++ * LOG2_LOG_TABLE_SIZE+1 MSBs. As the MSB is always 1, only next ++ * LOG2_OF_LOG_TABLE_SIZE MSBs are used for table lookup. Next 16 MSBs are used ++ * for interpolation. ++ * Inputs: ++ * N - number to which log10 has to be found. ++ * qN - q format of N ++ * log10N - address where log10(N) will be written. ++ * qLog10N - address where log10N qformat will be written. ++ * Note/Problem: ++ * For accurate results input should be in normalized or near normalized form. ++ */ ++void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N) ++{ ++ s16 s16norm, s16tableIndex, s16errorApproximation; ++ u16 u16offset; ++ s32 s32log; ++ ++ /* normalize the N. */ ++ s16norm = qm_norm32(N); ++ N = N << s16norm; ++ ++ /* The qformat of N after normalization. ++ * -30 is added to treat the no as between 1.0 to 2.0 ++ * i.e. after adding the -30 to the qformat the decimal point will be ++ * just rigtht of the MSB. (i.e. after sign bit and 1st MSB). i.e. ++ * at the right side of 30th bit. ++ */ ++ qN = qN + s16norm - 30; ++ ++ /* take the table index as the LOG2_OF_LOG_TABLE_SIZE bits right of the ++ * MSB */ ++ s16tableIndex = (s16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE))); ++ ++ /* remove the MSB. the MSB is always 1 after normalization. */ ++ s16tableIndex = ++ s16tableIndex & (s16) ((1 << LOG2_LOG_TABLE_SIZE) - 1); ++ ++ /* remove the (1+LOG2_OF_LOG_TABLE_SIZE) MSBs in the N. */ ++ N = N & ((1 << (32 - (2 + LOG2_LOG_TABLE_SIZE))) - 1); ++ ++ /* take the offset as the 16 MSBS after table index. ++ */ ++ u16offset = (u16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE + 16))); ++ ++ /* look the log value in the table. */ ++ s32log = log_table[s16tableIndex]; /* q.15 format */ ++ ++ /* interpolate using the offset. q.15 format. */ ++ s16errorApproximation = (s16) qm_mulu16(u16offset, ++ (u16) (log_table[s16tableIndex + 1] - ++ log_table[s16tableIndex])); ++ ++ /* q.15 format */ ++ s32log = qm_add16((s16) s32log, s16errorApproximation); ++ ++ /* adjust for the qformat of the N as ++ * log2(mag * 2^x) = log2(mag) + x ++ */ ++ s32log = qm_add32(s32log, ((s32) -qN) << 15); /* q.15 format */ ++ ++ /* normalize the result. */ ++ s16norm = qm_norm32(s32log); ++ ++ /* bring all the important bits into lower 16 bits */ ++ /* q.15+s16norm-16 format */ ++ s32log = qm_shl32(s32log, s16norm - 16); ++ ++ /* compute the log10(N) by multiplying log2(N) with log10(2). ++ * as log10(mag * 2^x) = log2(mag * 2^x) * log10(2) ++ * log10N in q.15+s16norm-16+1 (LOG10_2 is in q.16) ++ */ ++ *log10N = qm_muls16((s16) s32log, (s16) LOG10_2); ++ ++ /* write the q format of the result. */ ++ *qLog10N = 15 + s16norm - 16 + 1; ++ ++ return; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.h.orig 2011-11-09 13:46:58.276800245 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.h 2011-11-09 13:47:17.032565765 -0500 +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_QMATH_H_ ++#define _BRCM_QMATH_H_ ++ ++#include ++ ++u16 qm_mulu16(u16 op1, u16 op2); ++ ++s16 qm_muls16(s16 op1, s16 op2); ++ ++s32 qm_add32(s32 op1, s32 op2); ++ ++s16 qm_add16(s16 op1, s16 op2); ++ ++s16 qm_sub16(s16 op1, s16 op2); ++ ++s32 qm_shl32(s32 op, int shift); ++ ++s16 qm_shl16(s16 op, int shift); ++ ++s16 qm_shr16(s16 op, int shift); ++ ++s16 qm_norm32(s32 op); ++ ++void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N); ++ ++#endif /* #ifndef _BRCM_QMATH_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_radio.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_radio.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_radio.h.orig 2011-11-09 13:46:58.277800233 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_radio.h 2011-11-09 13:47:17.035565729 -0500 +@@ -0,0 +1,1533 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_PHY_RADIO_H_ ++#define _BRCM_PHY_RADIO_H_ ++ ++#define RADIO_IDCODE 0x01 ++ ++#define RADIO_DEFAULT_CORE 0 ++ ++#define RXC0_RSSI_RST 0x80 ++#define RXC0_MODE_RSSI 0x40 ++#define RXC0_MODE_OFF 0x20 ++#define RXC0_MODE_CM 0x10 ++#define RXC0_LAN_LOAD 0x08 ++#define RXC0_OFF_ADJ_MASK 0x07 ++ ++#define TXC0_MODE_TXLPF 0x04 ++#define TXC0_PA_TSSI_EN 0x02 ++#define TXC0_TSSI_EN 0x01 ++ ++#define TXC1_PA_GAIN_MASK 0x60 ++#define TXC1_PA_GAIN_3DB 0x40 ++#define TXC1_PA_GAIN_2DB 0x20 ++#define TXC1_TX_MIX_GAIN 0x10 ++#define TXC1_OFF_I_MASK 0x0c ++#define TXC1_OFF_Q_MASK 0x03 ++ ++#define RADIO_2055_READ_OFF 0x100 ++#define RADIO_2057_READ_OFF 0x200 ++ ++#define RADIO_2055_GEN_SPARE 0x00 ++#define RADIO_2055_SP_PIN_PD 0x02 ++#define RADIO_2055_SP_RSSI_CORE1 0x03 ++#define RADIO_2055_SP_PD_MISC_CORE1 0x04 ++#define RADIO_2055_SP_RSSI_CORE2 0x05 ++#define RADIO_2055_SP_PD_MISC_CORE2 0x06 ++#define RADIO_2055_SP_RX_GC1_CORE1 0x07 ++#define RADIO_2055_SP_RX_GC2_CORE1 0x08 ++#define RADIO_2055_SP_RX_GC1_CORE2 0x09 ++#define RADIO_2055_SP_RX_GC2_CORE2 0x0a ++#define RADIO_2055_SP_LPF_BW_SELECT_CORE1 0x0b ++#define RADIO_2055_SP_LPF_BW_SELECT_CORE2 0x0c ++#define RADIO_2055_SP_TX_GC1_CORE1 0x0d ++#define RADIO_2055_SP_TX_GC2_CORE1 0x0e ++#define RADIO_2055_SP_TX_GC1_CORE2 0x0f ++#define RADIO_2055_SP_TX_GC2_CORE2 0x10 ++#define RADIO_2055_MASTER_CNTRL1 0x11 ++#define RADIO_2055_MASTER_CNTRL2 0x12 ++#define RADIO_2055_PD_LGEN 0x13 ++#define RADIO_2055_PD_PLL_TS 0x14 ++#define RADIO_2055_PD_CORE1_LGBUF 0x15 ++#define RADIO_2055_PD_CORE1_TX 0x16 ++#define RADIO_2055_PD_CORE1_RXTX 0x17 ++#define RADIO_2055_PD_CORE1_RSSI_MISC 0x18 ++#define RADIO_2055_PD_CORE2_LGBUF 0x19 ++#define RADIO_2055_PD_CORE2_TX 0x1a ++#define RADIO_2055_PD_CORE2_RXTX 0x1b ++#define RADIO_2055_PD_CORE2_RSSI_MISC 0x1c ++#define RADIO_2055_PWRDET_LGEN 0x1d ++#define RADIO_2055_PWRDET_LGBUF_CORE1 0x1e ++#define RADIO_2055_PWRDET_RXTX_CORE1 0x1f ++#define RADIO_2055_PWRDET_LGBUF_CORE2 0x20 ++#define RADIO_2055_PWRDET_RXTX_CORE2 0x21 ++#define RADIO_2055_RRCCAL_CNTRL_SPARE 0x22 ++#define RADIO_2055_RRCCAL_N_OPT_SEL 0x23 ++#define RADIO_2055_CAL_MISC 0x24 ++#define RADIO_2055_CAL_COUNTER_OUT 0x25 ++#define RADIO_2055_CAL_COUNTER_OUT2 0x26 ++#define RADIO_2055_CAL_CVAR_CNTRL 0x27 ++#define RADIO_2055_CAL_RVAR_CNTRL 0x28 ++#define RADIO_2055_CAL_LPO_CNTRL 0x29 ++#define RADIO_2055_CAL_TS 0x2a ++#define RADIO_2055_CAL_RCCAL_READ_TS 0x2b ++#define RADIO_2055_CAL_RCAL_READ_TS 0x2c ++#define RADIO_2055_PAD_DRIVER 0x2d ++#define RADIO_2055_XO_CNTRL1 0x2e ++#define RADIO_2055_XO_CNTRL2 0x2f ++#define RADIO_2055_XO_REGULATOR 0x30 ++#define RADIO_2055_XO_MISC 0x31 ++#define RADIO_2055_PLL_LF_C1 0x32 ++#define RADIO_2055_PLL_CAL_VTH 0x33 ++#define RADIO_2055_PLL_LF_C2 0x34 ++#define RADIO_2055_PLL_REF 0x35 ++#define RADIO_2055_PLL_LF_R1 0x36 ++#define RADIO_2055_PLL_PFD_CP 0x37 ++#define RADIO_2055_PLL_IDAC_CPOPAMP 0x38 ++#define RADIO_2055_PLL_CP_REGULATOR 0x39 ++#define RADIO_2055_PLL_RCAL 0x3a ++#define RADIO_2055_RF_PLL_MOD0 0x3b ++#define RADIO_2055_RF_PLL_MOD1 0x3c ++#define RADIO_2055_RF_MMD_IDAC1 0x3d ++#define RADIO_2055_RF_MMD_IDAC0 0x3e ++#define RADIO_2055_RF_MMD_SPARE 0x3f ++#define RADIO_2055_VCO_CAL1 0x40 ++#define RADIO_2055_VCO_CAL2 0x41 ++#define RADIO_2055_VCO_CAL3 0x42 ++#define RADIO_2055_VCO_CAL4 0x43 ++#define RADIO_2055_VCO_CAL5 0x44 ++#define RADIO_2055_VCO_CAL6 0x45 ++#define RADIO_2055_VCO_CAL7 0x46 ++#define RADIO_2055_VCO_CAL8 0x47 ++#define RADIO_2055_VCO_CAL9 0x48 ++#define RADIO_2055_VCO_CAL10 0x49 ++#define RADIO_2055_VCO_CAL11 0x4a ++#define RADIO_2055_VCO_CAL12 0x4b ++#define RADIO_2055_VCO_CAL13 0x4c ++#define RADIO_2055_VCO_CAL14 0x4d ++#define RADIO_2055_VCO_CAL15 0x4e ++#define RADIO_2055_VCO_CAL16 0x4f ++#define RADIO_2055_VCO_KVCO 0x50 ++#define RADIO_2055_VCO_CAP_TAIL 0x51 ++#define RADIO_2055_VCO_IDAC_VCO 0x52 ++#define RADIO_2055_VCO_REGULATOR 0x53 ++#define RADIO_2055_PLL_RF_VTH 0x54 ++#define RADIO_2055_LGBUF_CEN_BUF 0x55 ++#define RADIO_2055_LGEN_TUNE1 0x56 ++#define RADIO_2055_LGEN_TUNE2 0x57 ++#define RADIO_2055_LGEN_IDAC1 0x58 ++#define RADIO_2055_LGEN_IDAC2 0x59 ++#define RADIO_2055_LGEN_BIAS_CNT 0x5a ++#define RADIO_2055_LGEN_BIAS_IDAC 0x5b ++#define RADIO_2055_LGEN_RCAL 0x5c ++#define RADIO_2055_LGEN_DIV 0x5d ++#define RADIO_2055_LGEN_SPARE2 0x5e ++#define RADIO_2055_CORE1_LGBUF_A_TUNE 0x5f ++#define RADIO_2055_CORE1_LGBUF_G_TUNE 0x60 ++#define RADIO_2055_CORE1_LGBUF_DIV 0x61 ++#define RADIO_2055_CORE1_LGBUF_A_IDAC 0x62 ++#define RADIO_2055_CORE1_LGBUF_G_IDAC 0x63 ++#define RADIO_2055_CORE1_LGBUF_IDACFIL_OVR 0x64 ++#define RADIO_2055_CORE1_LGBUF_SPARE 0x65 ++#define RADIO_2055_CORE1_RXRF_SPC1 0x66 ++#define RADIO_2055_CORE1_RXRF_REG1 0x67 ++#define RADIO_2055_CORE1_RXRF_REG2 0x68 ++#define RADIO_2055_CORE1_RXRF_RCAL 0x69 ++#define RADIO_2055_CORE1_RXBB_BUFI_LPFCMP 0x6a ++#define RADIO_2055_CORE1_RXBB_LPF 0x6b ++#define RADIO_2055_CORE1_RXBB_MIDAC_HIPAS 0x6c ++#define RADIO_2055_CORE1_RXBB_VGA1_IDAC 0x6d ++#define RADIO_2055_CORE1_RXBB_VGA2_IDAC 0x6e ++#define RADIO_2055_CORE1_RXBB_VGA3_IDAC 0x6f ++#define RADIO_2055_CORE1_RXBB_BUFO_CTRL 0x70 ++#define RADIO_2055_CORE1_RXBB_RCCAL_CTRL 0x71 ++#define RADIO_2055_CORE1_RXBB_RSSI_CTRL1 0x72 ++#define RADIO_2055_CORE1_RXBB_RSSI_CTRL2 0x73 ++#define RADIO_2055_CORE1_RXBB_RSSI_CTRL3 0x74 ++#define RADIO_2055_CORE1_RXBB_RSSI_CTRL4 0x75 ++#define RADIO_2055_CORE1_RXBB_RSSI_CTRL5 0x76 ++#define RADIO_2055_CORE1_RXBB_REGULATOR 0x77 ++#define RADIO_2055_CORE1_RXBB_SPARE1 0x78 ++#define RADIO_2055_CORE1_RXTXBB_RCAL 0x79 ++#define RADIO_2055_CORE1_TXRF_SGM_PGA 0x7a ++#define RADIO_2055_CORE1_TXRF_SGM_PAD 0x7b ++#define RADIO_2055_CORE1_TXRF_CNTR_PGA1 0x7c ++#define RADIO_2055_CORE1_TXRF_CNTR_PAD1 0x7d ++#define RADIO_2055_CORE1_TX_RFPGA_IDAC 0x7e ++#define RADIO_2055_CORE1_TX_PGA_PAD_TN 0x7f ++#define RADIO_2055_CORE1_TX_PAD_IDAC1 0x80 ++#define RADIO_2055_CORE1_TX_PAD_IDAC2 0x81 ++#define RADIO_2055_CORE1_TX_MX_BGTRIM 0x82 ++#define RADIO_2055_CORE1_TXRF_RCAL 0x83 ++#define RADIO_2055_CORE1_TXRF_PAD_TSSI1 0x84 ++#define RADIO_2055_CORE1_TXRF_PAD_TSSI2 0x85 ++#define RADIO_2055_CORE1_TX_RF_SPARE 0x86 ++#define RADIO_2055_CORE1_TXRF_IQCAL1 0x87 ++#define RADIO_2055_CORE1_TXRF_IQCAL2 0x88 ++#define RADIO_2055_CORE1_TXBB_RCCAL_CTRL 0x89 ++#define RADIO_2055_CORE1_TXBB_LPF1 0x8a ++#define RADIO_2055_CORE1_TX_VOS_CNCL 0x8b ++#define RADIO_2055_CORE1_TX_LPF_MXGM_IDAC 0x8c ++#define RADIO_2055_CORE1_TX_BB_MXGM 0x8d ++#define RADIO_2055_CORE2_LGBUF_A_TUNE 0x8e ++#define RADIO_2055_CORE2_LGBUF_G_TUNE 0x8f ++#define RADIO_2055_CORE2_LGBUF_DIV 0x90 ++#define RADIO_2055_CORE2_LGBUF_A_IDAC 0x91 ++#define RADIO_2055_CORE2_LGBUF_G_IDAC 0x92 ++#define RADIO_2055_CORE2_LGBUF_IDACFIL_OVR 0x93 ++#define RADIO_2055_CORE2_LGBUF_SPARE 0x94 ++#define RADIO_2055_CORE2_RXRF_SPC1 0x95 ++#define RADIO_2055_CORE2_RXRF_REG1 0x96 ++#define RADIO_2055_CORE2_RXRF_REG2 0x97 ++#define RADIO_2055_CORE2_RXRF_RCAL 0x98 ++#define RADIO_2055_CORE2_RXBB_BUFI_LPFCMP 0x99 ++#define RADIO_2055_CORE2_RXBB_LPF 0x9a ++#define RADIO_2055_CORE2_RXBB_MIDAC_HIPAS 0x9b ++#define RADIO_2055_CORE2_RXBB_VGA1_IDAC 0x9c ++#define RADIO_2055_CORE2_RXBB_VGA2_IDAC 0x9d ++#define RADIO_2055_CORE2_RXBB_VGA3_IDAC 0x9e ++#define RADIO_2055_CORE2_RXBB_BUFO_CTRL 0x9f ++#define RADIO_2055_CORE2_RXBB_RCCAL_CTRL 0xa0 ++#define RADIO_2055_CORE2_RXBB_RSSI_CTRL1 0xa1 ++#define RADIO_2055_CORE2_RXBB_RSSI_CTRL2 0xa2 ++#define RADIO_2055_CORE2_RXBB_RSSI_CTRL3 0xa3 ++#define RADIO_2055_CORE2_RXBB_RSSI_CTRL4 0xa4 ++#define RADIO_2055_CORE2_RXBB_RSSI_CTRL5 0xa5 ++#define RADIO_2055_CORE2_RXBB_REGULATOR 0xa6 ++#define RADIO_2055_CORE2_RXBB_SPARE1 0xa7 ++#define RADIO_2055_CORE2_RXTXBB_RCAL 0xa8 ++#define RADIO_2055_CORE2_TXRF_SGM_PGA 0xa9 ++#define RADIO_2055_CORE2_TXRF_SGM_PAD 0xaa ++#define RADIO_2055_CORE2_TXRF_CNTR_PGA1 0xab ++#define RADIO_2055_CORE2_TXRF_CNTR_PAD1 0xac ++#define RADIO_2055_CORE2_TX_RFPGA_IDAC 0xad ++#define RADIO_2055_CORE2_TX_PGA_PAD_TN 0xae ++#define RADIO_2055_CORE2_TX_PAD_IDAC1 0xaf ++#define RADIO_2055_CORE2_TX_PAD_IDAC2 0xb0 ++#define RADIO_2055_CORE2_TX_MX_BGTRIM 0xb1 ++#define RADIO_2055_CORE2_TXRF_RCAL 0xb2 ++#define RADIO_2055_CORE2_TXRF_PAD_TSSI1 0xb3 ++#define RADIO_2055_CORE2_TXRF_PAD_TSSI2 0xb4 ++#define RADIO_2055_CORE2_TX_RF_SPARE 0xb5 ++#define RADIO_2055_CORE2_TXRF_IQCAL1 0xb6 ++#define RADIO_2055_CORE2_TXRF_IQCAL2 0xb7 ++#define RADIO_2055_CORE2_TXBB_RCCAL_CTRL 0xb8 ++#define RADIO_2055_CORE2_TXBB_LPF1 0xb9 ++#define RADIO_2055_CORE2_TX_VOS_CNCL 0xba ++#define RADIO_2055_CORE2_TX_LPF_MXGM_IDAC 0xbb ++#define RADIO_2055_CORE2_TX_BB_MXGM 0xbc ++#define RADIO_2055_PRG_GC_HPVGA23_21 0xbd ++#define RADIO_2055_PRG_GC_HPVGA23_22 0xbe ++#define RADIO_2055_PRG_GC_HPVGA23_23 0xbf ++#define RADIO_2055_PRG_GC_HPVGA23_24 0xc0 ++#define RADIO_2055_PRG_GC_HPVGA23_25 0xc1 ++#define RADIO_2055_PRG_GC_HPVGA23_26 0xc2 ++#define RADIO_2055_PRG_GC_HPVGA23_27 0xc3 ++#define RADIO_2055_PRG_GC_HPVGA23_28 0xc4 ++#define RADIO_2055_PRG_GC_HPVGA23_29 0xc5 ++#define RADIO_2055_PRG_GC_HPVGA23_30 0xc6 ++#define RADIO_2055_CORE1_LNA_GAINBST 0xcd ++#define RADIO_2055_CORE1_B0_NBRSSI_VCM 0xd2 ++#define RADIO_2055_CORE1_GEN_SPARE2 0xd6 ++#define RADIO_2055_CORE2_LNA_GAINBST 0xd9 ++#define RADIO_2055_CORE2_B0_NBRSSI_VCM 0xde ++#define RADIO_2055_CORE2_GEN_SPARE2 0xe2 ++ ++#define RADIO_2055_GAINBST_GAIN_DB 6 ++#define RADIO_2055_GAINBST_CODE 0x6 ++ ++#define RADIO_2055_JTAGCTRL_MASK 0x04 ++#define RADIO_2055_JTAGSYNC_MASK 0x08 ++#define RADIO_2055_RRCAL_START 0x40 ++#define RADIO_2055_RRCAL_RST_N 0x01 ++#define RADIO_2055_CAL_LPO_ENABLE 0x80 ++#define RADIO_2055_RCAL_DONE 0x80 ++#define RADIO_2055_NBRSSI_VCM_I_MASK 0x03 ++#define RADIO_2055_NBRSSI_VCM_I_SHIFT 0x00 ++#define RADIO_2055_NBRSSI_VCM_Q_MASK 0x03 ++#define RADIO_2055_NBRSSI_VCM_Q_SHIFT 0x00 ++#define RADIO_2055_WBRSSI_VCM_IQ_MASK 0x0c ++#define RADIO_2055_WBRSSI_VCM_IQ_SHIFT 0x02 ++#define RADIO_2055_NBRSSI_PD 0x01 ++#define RADIO_2055_WBRSSI_G1_PD 0x04 ++#define RADIO_2055_WBRSSI_G2_PD 0x02 ++#define RADIO_2055_NBRSSI_SEL 0x01 ++#define RADIO_2055_WBRSSI_G1_SEL 0x04 ++#define RADIO_2055_WBRSSI_G2_SEL 0x02 ++#define RADIO_2055_COUPLE_RX_MASK 0x01 ++#define RADIO_2055_COUPLE_TX_MASK 0x02 ++#define RADIO_2055_GAINBST_DISABLE 0x02 ++#define RADIO_2055_GAINBST_VAL_MASK 0x07 ++#define RADIO_2055_RXMX_GC_MASK 0x0c ++ ++#define RADIO_MIMO_CORESEL_OFF 0x0 ++#define RADIO_MIMO_CORESEL_CORE1 0x1 ++#define RADIO_MIMO_CORESEL_CORE2 0x2 ++#define RADIO_MIMO_CORESEL_CORE3 0x3 ++#define RADIO_MIMO_CORESEL_CORE4 0x4 ++#define RADIO_MIMO_CORESEL_ALLRX 0x5 ++#define RADIO_MIMO_CORESEL_ALLTX 0x6 ++#define RADIO_MIMO_CORESEL_ALLRXTX 0x7 ++ ++#define RADIO_2064_READ_OFF 0x200 ++ ++#define RADIO_2064_REG000 0x0 ++#define RADIO_2064_REG001 0x1 ++#define RADIO_2064_REG002 0x2 ++#define RADIO_2064_REG003 0x3 ++#define RADIO_2064_REG004 0x4 ++#define RADIO_2064_REG005 0x5 ++#define RADIO_2064_REG006 0x6 ++#define RADIO_2064_REG007 0x7 ++#define RADIO_2064_REG008 0x8 ++#define RADIO_2064_REG009 0x9 ++#define RADIO_2064_REG00A 0xa ++#define RADIO_2064_REG00B 0xb ++#define RADIO_2064_REG00C 0xc ++#define RADIO_2064_REG00D 0xd ++#define RADIO_2064_REG00E 0xe ++#define RADIO_2064_REG00F 0xf ++#define RADIO_2064_REG010 0x10 ++#define RADIO_2064_REG011 0x11 ++#define RADIO_2064_REG012 0x12 ++#define RADIO_2064_REG013 0x13 ++#define RADIO_2064_REG014 0x14 ++#define RADIO_2064_REG015 0x15 ++#define RADIO_2064_REG016 0x16 ++#define RADIO_2064_REG017 0x17 ++#define RADIO_2064_REG018 0x18 ++#define RADIO_2064_REG019 0x19 ++#define RADIO_2064_REG01A 0x1a ++#define RADIO_2064_REG01B 0x1b ++#define RADIO_2064_REG01C 0x1c ++#define RADIO_2064_REG01D 0x1d ++#define RADIO_2064_REG01E 0x1e ++#define RADIO_2064_REG01F 0x1f ++#define RADIO_2064_REG020 0x20 ++#define RADIO_2064_REG021 0x21 ++#define RADIO_2064_REG022 0x22 ++#define RADIO_2064_REG023 0x23 ++#define RADIO_2064_REG024 0x24 ++#define RADIO_2064_REG025 0x25 ++#define RADIO_2064_REG026 0x26 ++#define RADIO_2064_REG027 0x27 ++#define RADIO_2064_REG028 0x28 ++#define RADIO_2064_REG029 0x29 ++#define RADIO_2064_REG02A 0x2a ++#define RADIO_2064_REG02B 0x2b ++#define RADIO_2064_REG02C 0x2c ++#define RADIO_2064_REG02D 0x2d ++#define RADIO_2064_REG02E 0x2e ++#define RADIO_2064_REG02F 0x2f ++#define RADIO_2064_REG030 0x30 ++#define RADIO_2064_REG031 0x31 ++#define RADIO_2064_REG032 0x32 ++#define RADIO_2064_REG033 0x33 ++#define RADIO_2064_REG034 0x34 ++#define RADIO_2064_REG035 0x35 ++#define RADIO_2064_REG036 0x36 ++#define RADIO_2064_REG037 0x37 ++#define RADIO_2064_REG038 0x38 ++#define RADIO_2064_REG039 0x39 ++#define RADIO_2064_REG03A 0x3a ++#define RADIO_2064_REG03B 0x3b ++#define RADIO_2064_REG03C 0x3c ++#define RADIO_2064_REG03D 0x3d ++#define RADIO_2064_REG03E 0x3e ++#define RADIO_2064_REG03F 0x3f ++#define RADIO_2064_REG040 0x40 ++#define RADIO_2064_REG041 0x41 ++#define RADIO_2064_REG042 0x42 ++#define RADIO_2064_REG043 0x43 ++#define RADIO_2064_REG044 0x44 ++#define RADIO_2064_REG045 0x45 ++#define RADIO_2064_REG046 0x46 ++#define RADIO_2064_REG047 0x47 ++#define RADIO_2064_REG048 0x48 ++#define RADIO_2064_REG049 0x49 ++#define RADIO_2064_REG04A 0x4a ++#define RADIO_2064_REG04B 0x4b ++#define RADIO_2064_REG04C 0x4c ++#define RADIO_2064_REG04D 0x4d ++#define RADIO_2064_REG04E 0x4e ++#define RADIO_2064_REG04F 0x4f ++#define RADIO_2064_REG050 0x50 ++#define RADIO_2064_REG051 0x51 ++#define RADIO_2064_REG052 0x52 ++#define RADIO_2064_REG053 0x53 ++#define RADIO_2064_REG054 0x54 ++#define RADIO_2064_REG055 0x55 ++#define RADIO_2064_REG056 0x56 ++#define RADIO_2064_REG057 0x57 ++#define RADIO_2064_REG058 0x58 ++#define RADIO_2064_REG059 0x59 ++#define RADIO_2064_REG05A 0x5a ++#define RADIO_2064_REG05B 0x5b ++#define RADIO_2064_REG05C 0x5c ++#define RADIO_2064_REG05D 0x5d ++#define RADIO_2064_REG05E 0x5e ++#define RADIO_2064_REG05F 0x5f ++#define RADIO_2064_REG060 0x60 ++#define RADIO_2064_REG061 0x61 ++#define RADIO_2064_REG062 0x62 ++#define RADIO_2064_REG063 0x63 ++#define RADIO_2064_REG064 0x64 ++#define RADIO_2064_REG065 0x65 ++#define RADIO_2064_REG066 0x66 ++#define RADIO_2064_REG067 0x67 ++#define RADIO_2064_REG068 0x68 ++#define RADIO_2064_REG069 0x69 ++#define RADIO_2064_REG06A 0x6a ++#define RADIO_2064_REG06B 0x6b ++#define RADIO_2064_REG06C 0x6c ++#define RADIO_2064_REG06D 0x6d ++#define RADIO_2064_REG06E 0x6e ++#define RADIO_2064_REG06F 0x6f ++#define RADIO_2064_REG070 0x70 ++#define RADIO_2064_REG071 0x71 ++#define RADIO_2064_REG072 0x72 ++#define RADIO_2064_REG073 0x73 ++#define RADIO_2064_REG074 0x74 ++#define RADIO_2064_REG075 0x75 ++#define RADIO_2064_REG076 0x76 ++#define RADIO_2064_REG077 0x77 ++#define RADIO_2064_REG078 0x78 ++#define RADIO_2064_REG079 0x79 ++#define RADIO_2064_REG07A 0x7a ++#define RADIO_2064_REG07B 0x7b ++#define RADIO_2064_REG07C 0x7c ++#define RADIO_2064_REG07D 0x7d ++#define RADIO_2064_REG07E 0x7e ++#define RADIO_2064_REG07F 0x7f ++#define RADIO_2064_REG080 0x80 ++#define RADIO_2064_REG081 0x81 ++#define RADIO_2064_REG082 0x82 ++#define RADIO_2064_REG083 0x83 ++#define RADIO_2064_REG084 0x84 ++#define RADIO_2064_REG085 0x85 ++#define RADIO_2064_REG086 0x86 ++#define RADIO_2064_REG087 0x87 ++#define RADIO_2064_REG088 0x88 ++#define RADIO_2064_REG089 0x89 ++#define RADIO_2064_REG08A 0x8a ++#define RADIO_2064_REG08B 0x8b ++#define RADIO_2064_REG08C 0x8c ++#define RADIO_2064_REG08D 0x8d ++#define RADIO_2064_REG08E 0x8e ++#define RADIO_2064_REG08F 0x8f ++#define RADIO_2064_REG090 0x90 ++#define RADIO_2064_REG091 0x91 ++#define RADIO_2064_REG092 0x92 ++#define RADIO_2064_REG093 0x93 ++#define RADIO_2064_REG094 0x94 ++#define RADIO_2064_REG095 0x95 ++#define RADIO_2064_REG096 0x96 ++#define RADIO_2064_REG097 0x97 ++#define RADIO_2064_REG098 0x98 ++#define RADIO_2064_REG099 0x99 ++#define RADIO_2064_REG09A 0x9a ++#define RADIO_2064_REG09B 0x9b ++#define RADIO_2064_REG09C 0x9c ++#define RADIO_2064_REG09D 0x9d ++#define RADIO_2064_REG09E 0x9e ++#define RADIO_2064_REG09F 0x9f ++#define RADIO_2064_REG0A0 0xa0 ++#define RADIO_2064_REG0A1 0xa1 ++#define RADIO_2064_REG0A2 0xa2 ++#define RADIO_2064_REG0A3 0xa3 ++#define RADIO_2064_REG0A4 0xa4 ++#define RADIO_2064_REG0A5 0xa5 ++#define RADIO_2064_REG0A6 0xa6 ++#define RADIO_2064_REG0A7 0xa7 ++#define RADIO_2064_REG0A8 0xa8 ++#define RADIO_2064_REG0A9 0xa9 ++#define RADIO_2064_REG0AA 0xaa ++#define RADIO_2064_REG0AB 0xab ++#define RADIO_2064_REG0AC 0xac ++#define RADIO_2064_REG0AD 0xad ++#define RADIO_2064_REG0AE 0xae ++#define RADIO_2064_REG0AF 0xaf ++#define RADIO_2064_REG0B0 0xb0 ++#define RADIO_2064_REG0B1 0xb1 ++#define RADIO_2064_REG0B2 0xb2 ++#define RADIO_2064_REG0B3 0xb3 ++#define RADIO_2064_REG0B4 0xb4 ++#define RADIO_2064_REG0B5 0xb5 ++#define RADIO_2064_REG0B6 0xb6 ++#define RADIO_2064_REG0B7 0xb7 ++#define RADIO_2064_REG0B8 0xb8 ++#define RADIO_2064_REG0B9 0xb9 ++#define RADIO_2064_REG0BA 0xba ++#define RADIO_2064_REG0BB 0xbb ++#define RADIO_2064_REG0BC 0xbc ++#define RADIO_2064_REG0BD 0xbd ++#define RADIO_2064_REG0BE 0xbe ++#define RADIO_2064_REG0BF 0xbf ++#define RADIO_2064_REG0C0 0xc0 ++#define RADIO_2064_REG0C1 0xc1 ++#define RADIO_2064_REG0C2 0xc2 ++#define RADIO_2064_REG0C3 0xc3 ++#define RADIO_2064_REG0C4 0xc4 ++#define RADIO_2064_REG0C5 0xc5 ++#define RADIO_2064_REG0C6 0xc6 ++#define RADIO_2064_REG0C7 0xc7 ++#define RADIO_2064_REG0C8 0xc8 ++#define RADIO_2064_REG0C9 0xc9 ++#define RADIO_2064_REG0CA 0xca ++#define RADIO_2064_REG0CB 0xcb ++#define RADIO_2064_REG0CC 0xcc ++#define RADIO_2064_REG0CD 0xcd ++#define RADIO_2064_REG0CE 0xce ++#define RADIO_2064_REG0CF 0xcf ++#define RADIO_2064_REG0D0 0xd0 ++#define RADIO_2064_REG0D1 0xd1 ++#define RADIO_2064_REG0D2 0xd2 ++#define RADIO_2064_REG0D3 0xd3 ++#define RADIO_2064_REG0D4 0xd4 ++#define RADIO_2064_REG0D5 0xd5 ++#define RADIO_2064_REG0D6 0xd6 ++#define RADIO_2064_REG0D7 0xd7 ++#define RADIO_2064_REG0D8 0xd8 ++#define RADIO_2064_REG0D9 0xd9 ++#define RADIO_2064_REG0DA 0xda ++#define RADIO_2064_REG0DB 0xdb ++#define RADIO_2064_REG0DC 0xdc ++#define RADIO_2064_REG0DD 0xdd ++#define RADIO_2064_REG0DE 0xde ++#define RADIO_2064_REG0DF 0xdf ++#define RADIO_2064_REG0E0 0xe0 ++#define RADIO_2064_REG0E1 0xe1 ++#define RADIO_2064_REG0E2 0xe2 ++#define RADIO_2064_REG0E3 0xe3 ++#define RADIO_2064_REG0E4 0xe4 ++#define RADIO_2064_REG0E5 0xe5 ++#define RADIO_2064_REG0E6 0xe6 ++#define RADIO_2064_REG0E7 0xe7 ++#define RADIO_2064_REG0E8 0xe8 ++#define RADIO_2064_REG0E9 0xe9 ++#define RADIO_2064_REG0EA 0xea ++#define RADIO_2064_REG0EB 0xeb ++#define RADIO_2064_REG0EC 0xec ++#define RADIO_2064_REG0ED 0xed ++#define RADIO_2064_REG0EE 0xee ++#define RADIO_2064_REG0EF 0xef ++#define RADIO_2064_REG0F0 0xf0 ++#define RADIO_2064_REG0F1 0xf1 ++#define RADIO_2064_REG0F2 0xf2 ++#define RADIO_2064_REG0F3 0xf3 ++#define RADIO_2064_REG0F4 0xf4 ++#define RADIO_2064_REG0F5 0xf5 ++#define RADIO_2064_REG0F6 0xf6 ++#define RADIO_2064_REG0F7 0xf7 ++#define RADIO_2064_REG0F8 0xf8 ++#define RADIO_2064_REG0F9 0xf9 ++#define RADIO_2064_REG0FA 0xfa ++#define RADIO_2064_REG0FB 0xfb ++#define RADIO_2064_REG0FC 0xfc ++#define RADIO_2064_REG0FD 0xfd ++#define RADIO_2064_REG0FE 0xfe ++#define RADIO_2064_REG0FF 0xff ++#define RADIO_2064_REG100 0x100 ++#define RADIO_2064_REG101 0x101 ++#define RADIO_2064_REG102 0x102 ++#define RADIO_2064_REG103 0x103 ++#define RADIO_2064_REG104 0x104 ++#define RADIO_2064_REG105 0x105 ++#define RADIO_2064_REG106 0x106 ++#define RADIO_2064_REG107 0x107 ++#define RADIO_2064_REG108 0x108 ++#define RADIO_2064_REG109 0x109 ++#define RADIO_2064_REG10A 0x10a ++#define RADIO_2064_REG10B 0x10b ++#define RADIO_2064_REG10C 0x10c ++#define RADIO_2064_REG10D 0x10d ++#define RADIO_2064_REG10E 0x10e ++#define RADIO_2064_REG10F 0x10f ++#define RADIO_2064_REG110 0x110 ++#define RADIO_2064_REG111 0x111 ++#define RADIO_2064_REG112 0x112 ++#define RADIO_2064_REG113 0x113 ++#define RADIO_2064_REG114 0x114 ++#define RADIO_2064_REG115 0x115 ++#define RADIO_2064_REG116 0x116 ++#define RADIO_2064_REG117 0x117 ++#define RADIO_2064_REG118 0x118 ++#define RADIO_2064_REG119 0x119 ++#define RADIO_2064_REG11A 0x11a ++#define RADIO_2064_REG11B 0x11b ++#define RADIO_2064_REG11C 0x11c ++#define RADIO_2064_REG11D 0x11d ++#define RADIO_2064_REG11E 0x11e ++#define RADIO_2064_REG11F 0x11f ++#define RADIO_2064_REG120 0x120 ++#define RADIO_2064_REG121 0x121 ++#define RADIO_2064_REG122 0x122 ++#define RADIO_2064_REG123 0x123 ++#define RADIO_2064_REG124 0x124 ++#define RADIO_2064_REG125 0x125 ++#define RADIO_2064_REG126 0x126 ++#define RADIO_2064_REG127 0x127 ++#define RADIO_2064_REG128 0x128 ++#define RADIO_2064_REG129 0x129 ++#define RADIO_2064_REG12A 0x12a ++#define RADIO_2064_REG12B 0x12b ++#define RADIO_2064_REG12C 0x12c ++#define RADIO_2064_REG12D 0x12d ++#define RADIO_2064_REG12E 0x12e ++#define RADIO_2064_REG12F 0x12f ++#define RADIO_2064_REG130 0x130 ++ ++#define RADIO_2056_SYN (0x0 << 12) ++#define RADIO_2056_TX0 (0x2 << 12) ++#define RADIO_2056_TX1 (0x3 << 12) ++#define RADIO_2056_RX0 (0x6 << 12) ++#define RADIO_2056_RX1 (0x7 << 12) ++#define RADIO_2056_ALLTX (0xe << 12) ++#define RADIO_2056_ALLRX (0xf << 12) ++ ++#define RADIO_2056_SYN_RESERVED_ADDR0 0x0 ++#define RADIO_2056_SYN_IDCODE 0x1 ++#define RADIO_2056_SYN_RESERVED_ADDR2 0x2 ++#define RADIO_2056_SYN_RESERVED_ADDR3 0x3 ++#define RADIO_2056_SYN_RESERVED_ADDR4 0x4 ++#define RADIO_2056_SYN_RESERVED_ADDR5 0x5 ++#define RADIO_2056_SYN_RESERVED_ADDR6 0x6 ++#define RADIO_2056_SYN_RESERVED_ADDR7 0x7 ++#define RADIO_2056_SYN_COM_CTRL 0x8 ++#define RADIO_2056_SYN_COM_PU 0x9 ++#define RADIO_2056_SYN_COM_OVR 0xa ++#define RADIO_2056_SYN_COM_RESET 0xb ++#define RADIO_2056_SYN_COM_RCAL 0xc ++#define RADIO_2056_SYN_COM_RC_RXLPF 0xd ++#define RADIO_2056_SYN_COM_RC_TXLPF 0xe ++#define RADIO_2056_SYN_COM_RC_RXHPF 0xf ++#define RADIO_2056_SYN_RESERVED_ADDR16 0x10 ++#define RADIO_2056_SYN_RESERVED_ADDR17 0x11 ++#define RADIO_2056_SYN_RESERVED_ADDR18 0x12 ++#define RADIO_2056_SYN_RESERVED_ADDR19 0x13 ++#define RADIO_2056_SYN_RESERVED_ADDR20 0x14 ++#define RADIO_2056_SYN_RESERVED_ADDR21 0x15 ++#define RADIO_2056_SYN_RESERVED_ADDR22 0x16 ++#define RADIO_2056_SYN_RESERVED_ADDR23 0x17 ++#define RADIO_2056_SYN_RESERVED_ADDR24 0x18 ++#define RADIO_2056_SYN_RESERVED_ADDR25 0x19 ++#define RADIO_2056_SYN_RESERVED_ADDR26 0x1a ++#define RADIO_2056_SYN_RESERVED_ADDR27 0x1b ++#define RADIO_2056_SYN_RESERVED_ADDR28 0x1c ++#define RADIO_2056_SYN_RESERVED_ADDR29 0x1d ++#define RADIO_2056_SYN_RESERVED_ADDR30 0x1e ++#define RADIO_2056_SYN_RESERVED_ADDR31 0x1f ++#define RADIO_2056_SYN_GPIO_MASTER1 0x20 ++#define RADIO_2056_SYN_GPIO_MASTER2 0x21 ++#define RADIO_2056_SYN_TOPBIAS_MASTER 0x22 ++#define RADIO_2056_SYN_TOPBIAS_RCAL 0x23 ++#define RADIO_2056_SYN_AFEREG 0x24 ++#define RADIO_2056_SYN_TEMPPROCSENSE 0x25 ++#define RADIO_2056_SYN_TEMPPROCSENSEIDAC 0x26 ++#define RADIO_2056_SYN_TEMPPROCSENSERCAL 0x27 ++#define RADIO_2056_SYN_LPO 0x28 ++#define RADIO_2056_SYN_VDDCAL_MASTER 0x29 ++#define RADIO_2056_SYN_VDDCAL_IDAC 0x2a ++#define RADIO_2056_SYN_VDDCAL_STATUS 0x2b ++#define RADIO_2056_SYN_RCAL_MASTER 0x2c ++#define RADIO_2056_SYN_RCAL_CODE_OUT 0x2d ++#define RADIO_2056_SYN_RCCAL_CTRL0 0x2e ++#define RADIO_2056_SYN_RCCAL_CTRL1 0x2f ++#define RADIO_2056_SYN_RCCAL_CTRL2 0x30 ++#define RADIO_2056_SYN_RCCAL_CTRL3 0x31 ++#define RADIO_2056_SYN_RCCAL_CTRL4 0x32 ++#define RADIO_2056_SYN_RCCAL_CTRL5 0x33 ++#define RADIO_2056_SYN_RCCAL_CTRL6 0x34 ++#define RADIO_2056_SYN_RCCAL_CTRL7 0x35 ++#define RADIO_2056_SYN_RCCAL_CTRL8 0x36 ++#define RADIO_2056_SYN_RCCAL_CTRL9 0x37 ++#define RADIO_2056_SYN_RCCAL_CTRL10 0x38 ++#define RADIO_2056_SYN_RCCAL_CTRL11 0x39 ++#define RADIO_2056_SYN_ZCAL_SPARE1 0x3a ++#define RADIO_2056_SYN_ZCAL_SPARE2 0x3b ++#define RADIO_2056_SYN_PLL_MAST1 0x3c ++#define RADIO_2056_SYN_PLL_MAST2 0x3d ++#define RADIO_2056_SYN_PLL_MAST3 0x3e ++#define RADIO_2056_SYN_PLL_BIAS_RESET 0x3f ++#define RADIO_2056_SYN_PLL_XTAL0 0x40 ++#define RADIO_2056_SYN_PLL_XTAL1 0x41 ++#define RADIO_2056_SYN_PLL_XTAL3 0x42 ++#define RADIO_2056_SYN_PLL_XTAL4 0x43 ++#define RADIO_2056_SYN_PLL_XTAL5 0x44 ++#define RADIO_2056_SYN_PLL_XTAL6 0x45 ++#define RADIO_2056_SYN_PLL_REFDIV 0x46 ++#define RADIO_2056_SYN_PLL_PFD 0x47 ++#define RADIO_2056_SYN_PLL_CP1 0x48 ++#define RADIO_2056_SYN_PLL_CP2 0x49 ++#define RADIO_2056_SYN_PLL_CP3 0x4a ++#define RADIO_2056_SYN_PLL_LOOPFILTER1 0x4b ++#define RADIO_2056_SYN_PLL_LOOPFILTER2 0x4c ++#define RADIO_2056_SYN_PLL_LOOPFILTER3 0x4d ++#define RADIO_2056_SYN_PLL_LOOPFILTER4 0x4e ++#define RADIO_2056_SYN_PLL_LOOPFILTER5 0x4f ++#define RADIO_2056_SYN_PLL_MMD1 0x50 ++#define RADIO_2056_SYN_PLL_MMD2 0x51 ++#define RADIO_2056_SYN_PLL_VCO1 0x52 ++#define RADIO_2056_SYN_PLL_VCO2 0x53 ++#define RADIO_2056_SYN_PLL_MONITOR1 0x54 ++#define RADIO_2056_SYN_PLL_MONITOR2 0x55 ++#define RADIO_2056_SYN_PLL_VCOCAL1 0x56 ++#define RADIO_2056_SYN_PLL_VCOCAL2 0x57 ++#define RADIO_2056_SYN_PLL_VCOCAL4 0x58 ++#define RADIO_2056_SYN_PLL_VCOCAL5 0x59 ++#define RADIO_2056_SYN_PLL_VCOCAL6 0x5a ++#define RADIO_2056_SYN_PLL_VCOCAL7 0x5b ++#define RADIO_2056_SYN_PLL_VCOCAL8 0x5c ++#define RADIO_2056_SYN_PLL_VCOCAL9 0x5d ++#define RADIO_2056_SYN_PLL_VCOCAL10 0x5e ++#define RADIO_2056_SYN_PLL_VCOCAL11 0x5f ++#define RADIO_2056_SYN_PLL_VCOCAL12 0x60 ++#define RADIO_2056_SYN_PLL_VCOCAL13 0x61 ++#define RADIO_2056_SYN_PLL_VREG 0x62 ++#define RADIO_2056_SYN_PLL_STATUS1 0x63 ++#define RADIO_2056_SYN_PLL_STATUS2 0x64 ++#define RADIO_2056_SYN_PLL_STATUS3 0x65 ++#define RADIO_2056_SYN_LOGEN_PU0 0x66 ++#define RADIO_2056_SYN_LOGEN_PU1 0x67 ++#define RADIO_2056_SYN_LOGEN_PU2 0x68 ++#define RADIO_2056_SYN_LOGEN_PU3 0x69 ++#define RADIO_2056_SYN_LOGEN_PU5 0x6a ++#define RADIO_2056_SYN_LOGEN_PU6 0x6b ++#define RADIO_2056_SYN_LOGEN_PU7 0x6c ++#define RADIO_2056_SYN_LOGEN_PU8 0x6d ++#define RADIO_2056_SYN_LOGEN_BIAS_RESET 0x6e ++#define RADIO_2056_SYN_LOGEN_RCCR1 0x6f ++#define RADIO_2056_SYN_LOGEN_VCOBUF1 0x70 ++#define RADIO_2056_SYN_LOGEN_MIXER1 0x71 ++#define RADIO_2056_SYN_LOGEN_MIXER2 0x72 ++#define RADIO_2056_SYN_LOGEN_BUF1 0x73 ++#define RADIO_2056_SYN_LOGENBUF2 0x74 ++#define RADIO_2056_SYN_LOGEN_BUF3 0x75 ++#define RADIO_2056_SYN_LOGEN_BUF4 0x76 ++#define RADIO_2056_SYN_LOGEN_DIV1 0x77 ++#define RADIO_2056_SYN_LOGEN_DIV2 0x78 ++#define RADIO_2056_SYN_LOGEN_DIV3 0x79 ++#define RADIO_2056_SYN_LOGEN_ACL1 0x7a ++#define RADIO_2056_SYN_LOGEN_ACL2 0x7b ++#define RADIO_2056_SYN_LOGEN_ACL3 0x7c ++#define RADIO_2056_SYN_LOGEN_ACL4 0x7d ++#define RADIO_2056_SYN_LOGEN_ACL5 0x7e ++#define RADIO_2056_SYN_LOGEN_ACL6 0x7f ++#define RADIO_2056_SYN_LOGEN_ACLOUT 0x80 ++#define RADIO_2056_SYN_LOGEN_ACLCAL1 0x81 ++#define RADIO_2056_SYN_LOGEN_ACLCAL2 0x82 ++#define RADIO_2056_SYN_LOGEN_ACLCAL3 0x83 ++#define RADIO_2056_SYN_CALEN 0x84 ++#define RADIO_2056_SYN_LOGEN_PEAKDET1 0x85 ++#define RADIO_2056_SYN_LOGEN_CORE_ACL_OVR 0x86 ++#define RADIO_2056_SYN_LOGEN_RX_DIFF_ACL_OVR 0x87 ++#define RADIO_2056_SYN_LOGEN_TX_DIFF_ACL_OVR 0x88 ++#define RADIO_2056_SYN_LOGEN_RX_CMOS_ACL_OVR 0x89 ++#define RADIO_2056_SYN_LOGEN_TX_CMOS_ACL_OVR 0x8a ++#define RADIO_2056_SYN_LOGEN_VCOBUF2 0x8b ++#define RADIO_2056_SYN_LOGEN_MIXER3 0x8c ++#define RADIO_2056_SYN_LOGEN_BUF5 0x8d ++#define RADIO_2056_SYN_LOGEN_BUF6 0x8e ++#define RADIO_2056_SYN_LOGEN_CBUFRX1 0x8f ++#define RADIO_2056_SYN_LOGEN_CBUFRX2 0x90 ++#define RADIO_2056_SYN_LOGEN_CBUFRX3 0x91 ++#define RADIO_2056_SYN_LOGEN_CBUFRX4 0x92 ++#define RADIO_2056_SYN_LOGEN_CBUFTX1 0x93 ++#define RADIO_2056_SYN_LOGEN_CBUFTX2 0x94 ++#define RADIO_2056_SYN_LOGEN_CBUFTX3 0x95 ++#define RADIO_2056_SYN_LOGEN_CBUFTX4 0x96 ++#define RADIO_2056_SYN_LOGEN_CMOSRX1 0x97 ++#define RADIO_2056_SYN_LOGEN_CMOSRX2 0x98 ++#define RADIO_2056_SYN_LOGEN_CMOSRX3 0x99 ++#define RADIO_2056_SYN_LOGEN_CMOSRX4 0x9a ++#define RADIO_2056_SYN_LOGEN_CMOSTX1 0x9b ++#define RADIO_2056_SYN_LOGEN_CMOSTX2 0x9c ++#define RADIO_2056_SYN_LOGEN_CMOSTX3 0x9d ++#define RADIO_2056_SYN_LOGEN_CMOSTX4 0x9e ++#define RADIO_2056_SYN_LOGEN_VCOBUF2_OVRVAL 0x9f ++#define RADIO_2056_SYN_LOGEN_MIXER3_OVRVAL 0xa0 ++#define RADIO_2056_SYN_LOGEN_BUF5_OVRVAL 0xa1 ++#define RADIO_2056_SYN_LOGEN_BUF6_OVRVAL 0xa2 ++#define RADIO_2056_SYN_LOGEN_CBUFRX1_OVRVAL 0xa3 ++#define RADIO_2056_SYN_LOGEN_CBUFRX2_OVRVAL 0xa4 ++#define RADIO_2056_SYN_LOGEN_CBUFRX3_OVRVAL 0xa5 ++#define RADIO_2056_SYN_LOGEN_CBUFRX4_OVRVAL 0xa6 ++#define RADIO_2056_SYN_LOGEN_CBUFTX1_OVRVAL 0xa7 ++#define RADIO_2056_SYN_LOGEN_CBUFTX2_OVRVAL 0xa8 ++#define RADIO_2056_SYN_LOGEN_CBUFTX3_OVRVAL 0xa9 ++#define RADIO_2056_SYN_LOGEN_CBUFTX4_OVRVAL 0xaa ++#define RADIO_2056_SYN_LOGEN_CMOSRX1_OVRVAL 0xab ++#define RADIO_2056_SYN_LOGEN_CMOSRX2_OVRVAL 0xac ++#define RADIO_2056_SYN_LOGEN_CMOSRX3_OVRVAL 0xad ++#define RADIO_2056_SYN_LOGEN_CMOSRX4_OVRVAL 0xae ++#define RADIO_2056_SYN_LOGEN_CMOSTX1_OVRVAL 0xaf ++#define RADIO_2056_SYN_LOGEN_CMOSTX2_OVRVAL 0xb0 ++#define RADIO_2056_SYN_LOGEN_CMOSTX3_OVRVAL 0xb1 ++#define RADIO_2056_SYN_LOGEN_CMOSTX4_OVRVAL 0xb2 ++#define RADIO_2056_SYN_LOGEN_ACL_WAITCNT 0xb3 ++#define RADIO_2056_SYN_LOGEN_CORE_CALVALID 0xb4 ++#define RADIO_2056_SYN_LOGEN_RX_CMOS_CALVALID 0xb5 ++#define RADIO_2056_SYN_LOGEN_TX_CMOS_VALID 0xb6 ++ ++#define RADIO_2056_TX_RESERVED_ADDR0 0x0 ++#define RADIO_2056_TX_IDCODE 0x1 ++#define RADIO_2056_TX_RESERVED_ADDR2 0x2 ++#define RADIO_2056_TX_RESERVED_ADDR3 0x3 ++#define RADIO_2056_TX_RESERVED_ADDR4 0x4 ++#define RADIO_2056_TX_RESERVED_ADDR5 0x5 ++#define RADIO_2056_TX_RESERVED_ADDR6 0x6 ++#define RADIO_2056_TX_RESERVED_ADDR7 0x7 ++#define RADIO_2056_TX_COM_CTRL 0x8 ++#define RADIO_2056_TX_COM_PU 0x9 ++#define RADIO_2056_TX_COM_OVR 0xa ++#define RADIO_2056_TX_COM_RESET 0xb ++#define RADIO_2056_TX_COM_RCAL 0xc ++#define RADIO_2056_TX_COM_RC_RXLPF 0xd ++#define RADIO_2056_TX_COM_RC_TXLPF 0xe ++#define RADIO_2056_TX_COM_RC_RXHPF 0xf ++#define RADIO_2056_TX_RESERVED_ADDR16 0x10 ++#define RADIO_2056_TX_RESERVED_ADDR17 0x11 ++#define RADIO_2056_TX_RESERVED_ADDR18 0x12 ++#define RADIO_2056_TX_RESERVED_ADDR19 0x13 ++#define RADIO_2056_TX_RESERVED_ADDR20 0x14 ++#define RADIO_2056_TX_RESERVED_ADDR21 0x15 ++#define RADIO_2056_TX_RESERVED_ADDR22 0x16 ++#define RADIO_2056_TX_RESERVED_ADDR23 0x17 ++#define RADIO_2056_TX_RESERVED_ADDR24 0x18 ++#define RADIO_2056_TX_RESERVED_ADDR25 0x19 ++#define RADIO_2056_TX_RESERVED_ADDR26 0x1a ++#define RADIO_2056_TX_RESERVED_ADDR27 0x1b ++#define RADIO_2056_TX_RESERVED_ADDR28 0x1c ++#define RADIO_2056_TX_RESERVED_ADDR29 0x1d ++#define RADIO_2056_TX_RESERVED_ADDR30 0x1e ++#define RADIO_2056_TX_RESERVED_ADDR31 0x1f ++#define RADIO_2056_TX_IQCAL_GAIN_BW 0x20 ++#define RADIO_2056_TX_LOFT_FINE_I 0x21 ++#define RADIO_2056_TX_LOFT_FINE_Q 0x22 ++#define RADIO_2056_TX_LOFT_COARSE_I 0x23 ++#define RADIO_2056_TX_LOFT_COARSE_Q 0x24 ++#define RADIO_2056_TX_TX_COM_MASTER1 0x25 ++#define RADIO_2056_TX_TX_COM_MASTER2 0x26 ++#define RADIO_2056_TX_RXIQCAL_TXMUX 0x27 ++#define RADIO_2056_TX_TX_SSI_MASTER 0x28 ++#define RADIO_2056_TX_IQCAL_VCM_HG 0x29 ++#define RADIO_2056_TX_IQCAL_IDAC 0x2a ++#define RADIO_2056_TX_TSSI_VCM 0x2b ++#define RADIO_2056_TX_TX_AMP_DET 0x2c ++#define RADIO_2056_TX_TX_SSI_MUX 0x2d ++#define RADIO_2056_TX_TSSIA 0x2e ++#define RADIO_2056_TX_TSSIG 0x2f ++#define RADIO_2056_TX_TSSI_MISC1 0x30 ++#define RADIO_2056_TX_TSSI_MISC2 0x31 ++#define RADIO_2056_TX_TSSI_MISC3 0x32 ++#define RADIO_2056_TX_PA_SPARE1 0x33 ++#define RADIO_2056_TX_PA_SPARE2 0x34 ++#define RADIO_2056_TX_INTPAA_MASTER 0x35 ++#define RADIO_2056_TX_INTPAA_GAIN 0x36 ++#define RADIO_2056_TX_INTPAA_BOOST_TUNE 0x37 ++#define RADIO_2056_TX_INTPAA_IAUX_STAT 0x38 ++#define RADIO_2056_TX_INTPAA_IAUX_DYN 0x39 ++#define RADIO_2056_TX_INTPAA_IMAIN_STAT 0x3a ++#define RADIO_2056_TX_INTPAA_IMAIN_DYN 0x3b ++#define RADIO_2056_TX_INTPAA_CASCBIAS 0x3c ++#define RADIO_2056_TX_INTPAA_PASLOPE 0x3d ++#define RADIO_2056_TX_INTPAA_PA_MISC 0x3e ++#define RADIO_2056_TX_INTPAG_MASTER 0x3f ++#define RADIO_2056_TX_INTPAG_GAIN 0x40 ++#define RADIO_2056_TX_INTPAG_BOOST_TUNE 0x41 ++#define RADIO_2056_TX_INTPAG_IAUX_STAT 0x42 ++#define RADIO_2056_TX_INTPAG_IAUX_DYN 0x43 ++#define RADIO_2056_TX_INTPAG_IMAIN_STAT 0x44 ++#define RADIO_2056_TX_INTPAG_IMAIN_DYN 0x45 ++#define RADIO_2056_TX_INTPAG_CASCBIAS 0x46 ++#define RADIO_2056_TX_INTPAG_PASLOPE 0x47 ++#define RADIO_2056_TX_INTPAG_PA_MISC 0x48 ++#define RADIO_2056_TX_PADA_MASTER 0x49 ++#define RADIO_2056_TX_PADA_IDAC 0x4a ++#define RADIO_2056_TX_PADA_CASCBIAS 0x4b ++#define RADIO_2056_TX_PADA_GAIN 0x4c ++#define RADIO_2056_TX_PADA_BOOST_TUNE 0x4d ++#define RADIO_2056_TX_PADA_SLOPE 0x4e ++#define RADIO_2056_TX_PADG_MASTER 0x4f ++#define RADIO_2056_TX_PADG_IDAC 0x50 ++#define RADIO_2056_TX_PADG_CASCBIAS 0x51 ++#define RADIO_2056_TX_PADG_GAIN 0x52 ++#define RADIO_2056_TX_PADG_BOOST_TUNE 0x53 ++#define RADIO_2056_TX_PADG_SLOPE 0x54 ++#define RADIO_2056_TX_PGAA_MASTER 0x55 ++#define RADIO_2056_TX_PGAA_IDAC 0x56 ++#define RADIO_2056_TX_PGAA_GAIN 0x57 ++#define RADIO_2056_TX_PGAA_BOOST_TUNE 0x58 ++#define RADIO_2056_TX_PGAA_SLOPE 0x59 ++#define RADIO_2056_TX_PGAA_MISC 0x5a ++#define RADIO_2056_TX_PGAG_MASTER 0x5b ++#define RADIO_2056_TX_PGAG_IDAC 0x5c ++#define RADIO_2056_TX_PGAG_GAIN 0x5d ++#define RADIO_2056_TX_PGAG_BOOST_TUNE 0x5e ++#define RADIO_2056_TX_PGAG_SLOPE 0x5f ++#define RADIO_2056_TX_PGAG_MISC 0x60 ++#define RADIO_2056_TX_MIXA_MASTER 0x61 ++#define RADIO_2056_TX_MIXA_BOOST_TUNE 0x62 ++#define RADIO_2056_TX_MIXG 0x63 ++#define RADIO_2056_TX_MIXG_BOOST_TUNE 0x64 ++#define RADIO_2056_TX_BB_GM_MASTER 0x65 ++#define RADIO_2056_TX_GMBB_GM 0x66 ++#define RADIO_2056_TX_GMBB_IDAC 0x67 ++#define RADIO_2056_TX_TXLPF_MASTER 0x68 ++#define RADIO_2056_TX_TXLPF_RCCAL 0x69 ++#define RADIO_2056_TX_TXLPF_RCCAL_OFF0 0x6a ++#define RADIO_2056_TX_TXLPF_RCCAL_OFF1 0x6b ++#define RADIO_2056_TX_TXLPF_RCCAL_OFF2 0x6c ++#define RADIO_2056_TX_TXLPF_RCCAL_OFF3 0x6d ++#define RADIO_2056_TX_TXLPF_RCCAL_OFF4 0x6e ++#define RADIO_2056_TX_TXLPF_RCCAL_OFF5 0x6f ++#define RADIO_2056_TX_TXLPF_RCCAL_OFF6 0x70 ++#define RADIO_2056_TX_TXLPF_BW 0x71 ++#define RADIO_2056_TX_TXLPF_GAIN 0x72 ++#define RADIO_2056_TX_TXLPF_IDAC 0x73 ++#define RADIO_2056_TX_TXLPF_IDAC_0 0x74 ++#define RADIO_2056_TX_TXLPF_IDAC_1 0x75 ++#define RADIO_2056_TX_TXLPF_IDAC_2 0x76 ++#define RADIO_2056_TX_TXLPF_IDAC_3 0x77 ++#define RADIO_2056_TX_TXLPF_IDAC_4 0x78 ++#define RADIO_2056_TX_TXLPF_IDAC_5 0x79 ++#define RADIO_2056_TX_TXLPF_IDAC_6 0x7a ++#define RADIO_2056_TX_TXLPF_OPAMP_IDAC 0x7b ++#define RADIO_2056_TX_TXLPF_MISC 0x7c ++#define RADIO_2056_TX_TXSPARE1 0x7d ++#define RADIO_2056_TX_TXSPARE2 0x7e ++#define RADIO_2056_TX_TXSPARE3 0x7f ++#define RADIO_2056_TX_TXSPARE4 0x80 ++#define RADIO_2056_TX_TXSPARE5 0x81 ++#define RADIO_2056_TX_TXSPARE6 0x82 ++#define RADIO_2056_TX_TXSPARE7 0x83 ++#define RADIO_2056_TX_TXSPARE8 0x84 ++#define RADIO_2056_TX_TXSPARE9 0x85 ++#define RADIO_2056_TX_TXSPARE10 0x86 ++#define RADIO_2056_TX_TXSPARE11 0x87 ++#define RADIO_2056_TX_TXSPARE12 0x88 ++#define RADIO_2056_TX_TXSPARE13 0x89 ++#define RADIO_2056_TX_TXSPARE14 0x8a ++#define RADIO_2056_TX_TXSPARE15 0x8b ++#define RADIO_2056_TX_TXSPARE16 0x8c ++#define RADIO_2056_TX_STATUS_INTPA_GAIN 0x8d ++#define RADIO_2056_TX_STATUS_PAD_GAIN 0x8e ++#define RADIO_2056_TX_STATUS_PGA_GAIN 0x8f ++#define RADIO_2056_TX_STATUS_GM_TXLPF_GAIN 0x90 ++#define RADIO_2056_TX_STATUS_TXLPF_BW 0x91 ++#define RADIO_2056_TX_STATUS_TXLPF_RC 0x92 ++#define RADIO_2056_TX_GMBB_IDAC0 0x93 ++#define RADIO_2056_TX_GMBB_IDAC1 0x94 ++#define RADIO_2056_TX_GMBB_IDAC2 0x95 ++#define RADIO_2056_TX_GMBB_IDAC3 0x96 ++#define RADIO_2056_TX_GMBB_IDAC4 0x97 ++#define RADIO_2056_TX_GMBB_IDAC5 0x98 ++#define RADIO_2056_TX_GMBB_IDAC6 0x99 ++#define RADIO_2056_TX_GMBB_IDAC7 0x9a ++ ++#define RADIO_2056_RX_RESERVED_ADDR0 0x0 ++#define RADIO_2056_RX_IDCODE 0x1 ++#define RADIO_2056_RX_RESERVED_ADDR2 0x2 ++#define RADIO_2056_RX_RESERVED_ADDR3 0x3 ++#define RADIO_2056_RX_RESERVED_ADDR4 0x4 ++#define RADIO_2056_RX_RESERVED_ADDR5 0x5 ++#define RADIO_2056_RX_RESERVED_ADDR6 0x6 ++#define RADIO_2056_RX_RESERVED_ADDR7 0x7 ++#define RADIO_2056_RX_COM_CTRL 0x8 ++#define RADIO_2056_RX_COM_PU 0x9 ++#define RADIO_2056_RX_COM_OVR 0xa ++#define RADIO_2056_RX_COM_RESET 0xb ++#define RADIO_2056_RX_COM_RCAL 0xc ++#define RADIO_2056_RX_COM_RC_RXLPF 0xd ++#define RADIO_2056_RX_COM_RC_TXLPF 0xe ++#define RADIO_2056_RX_COM_RC_RXHPF 0xf ++#define RADIO_2056_RX_RESERVED_ADDR16 0x10 ++#define RADIO_2056_RX_RESERVED_ADDR17 0x11 ++#define RADIO_2056_RX_RESERVED_ADDR18 0x12 ++#define RADIO_2056_RX_RESERVED_ADDR19 0x13 ++#define RADIO_2056_RX_RESERVED_ADDR20 0x14 ++#define RADIO_2056_RX_RESERVED_ADDR21 0x15 ++#define RADIO_2056_RX_RESERVED_ADDR22 0x16 ++#define RADIO_2056_RX_RESERVED_ADDR23 0x17 ++#define RADIO_2056_RX_RESERVED_ADDR24 0x18 ++#define RADIO_2056_RX_RESERVED_ADDR25 0x19 ++#define RADIO_2056_RX_RESERVED_ADDR26 0x1a ++#define RADIO_2056_RX_RESERVED_ADDR27 0x1b ++#define RADIO_2056_RX_RESERVED_ADDR28 0x1c ++#define RADIO_2056_RX_RESERVED_ADDR29 0x1d ++#define RADIO_2056_RX_RESERVED_ADDR30 0x1e ++#define RADIO_2056_RX_RESERVED_ADDR31 0x1f ++#define RADIO_2056_RX_RXIQCAL_RXMUX 0x20 ++#define RADIO_2056_RX_RSSI_PU 0x21 ++#define RADIO_2056_RX_RSSI_SEL 0x22 ++#define RADIO_2056_RX_RSSI_GAIN 0x23 ++#define RADIO_2056_RX_RSSI_NB_IDAC 0x24 ++#define RADIO_2056_RX_RSSI_WB2I_IDAC_1 0x25 ++#define RADIO_2056_RX_RSSI_WB2I_IDAC_2 0x26 ++#define RADIO_2056_RX_RSSI_WB2Q_IDAC_1 0x27 ++#define RADIO_2056_RX_RSSI_WB2Q_IDAC_2 0x28 ++#define RADIO_2056_RX_RSSI_POLE 0x29 ++#define RADIO_2056_RX_RSSI_WB1_IDAC 0x2a ++#define RADIO_2056_RX_RSSI_MISC 0x2b ++#define RADIO_2056_RX_LNAA_MASTER 0x2c ++#define RADIO_2056_RX_LNAA_TUNE 0x2d ++#define RADIO_2056_RX_LNAA_GAIN 0x2e ++#define RADIO_2056_RX_LNA_A_SLOPE 0x2f ++#define RADIO_2056_RX_BIASPOLE_LNAA1_IDAC 0x30 ++#define RADIO_2056_RX_LNAA2_IDAC 0x31 ++#define RADIO_2056_RX_LNA1A_MISC 0x32 ++#define RADIO_2056_RX_LNAG_MASTER 0x33 ++#define RADIO_2056_RX_LNAG_TUNE 0x34 ++#define RADIO_2056_RX_LNAG_GAIN 0x35 ++#define RADIO_2056_RX_LNA_G_SLOPE 0x36 ++#define RADIO_2056_RX_BIASPOLE_LNAG1_IDAC 0x37 ++#define RADIO_2056_RX_LNAG2_IDAC 0x38 ++#define RADIO_2056_RX_LNA1G_MISC 0x39 ++#define RADIO_2056_RX_MIXA_MASTER 0x3a ++#define RADIO_2056_RX_MIXA_VCM 0x3b ++#define RADIO_2056_RX_MIXA_CTRLPTAT 0x3c ++#define RADIO_2056_RX_MIXA_LOB_BIAS 0x3d ++#define RADIO_2056_RX_MIXA_CORE_IDAC 0x3e ++#define RADIO_2056_RX_MIXA_CMFB_IDAC 0x3f ++#define RADIO_2056_RX_MIXA_BIAS_AUX 0x40 ++#define RADIO_2056_RX_MIXA_BIAS_MAIN 0x41 ++#define RADIO_2056_RX_MIXA_BIAS_MISC 0x42 ++#define RADIO_2056_RX_MIXA_MAST_BIAS 0x43 ++#define RADIO_2056_RX_MIXG_MASTER 0x44 ++#define RADIO_2056_RX_MIXG_VCM 0x45 ++#define RADIO_2056_RX_MIXG_CTRLPTAT 0x46 ++#define RADIO_2056_RX_MIXG_LOB_BIAS 0x47 ++#define RADIO_2056_RX_MIXG_CORE_IDAC 0x48 ++#define RADIO_2056_RX_MIXG_CMFB_IDAC 0x49 ++#define RADIO_2056_RX_MIXG_BIAS_AUX 0x4a ++#define RADIO_2056_RX_MIXG_BIAS_MAIN 0x4b ++#define RADIO_2056_RX_MIXG_BIAS_MISC 0x4c ++#define RADIO_2056_RX_MIXG_MAST_BIAS 0x4d ++#define RADIO_2056_RX_TIA_MASTER 0x4e ++#define RADIO_2056_RX_TIA_IOPAMP 0x4f ++#define RADIO_2056_RX_TIA_QOPAMP 0x50 ++#define RADIO_2056_RX_TIA_IMISC 0x51 ++#define RADIO_2056_RX_TIA_QMISC 0x52 ++#define RADIO_2056_RX_TIA_GAIN 0x53 ++#define RADIO_2056_RX_TIA_SPARE1 0x54 ++#define RADIO_2056_RX_TIA_SPARE2 0x55 ++#define RADIO_2056_RX_BB_LPF_MASTER 0x56 ++#define RADIO_2056_RX_AACI_MASTER 0x57 ++#define RADIO_2056_RX_RXLPF_IDAC 0x58 ++#define RADIO_2056_RX_RXLPF_OPAMPBIAS_LOWQ 0x59 ++#define RADIO_2056_RX_RXLPF_OPAMPBIAS_HIGHQ 0x5a ++#define RADIO_2056_RX_RXLPF_BIAS_DCCANCEL 0x5b ++#define RADIO_2056_RX_RXLPF_OUTVCM 0x5c ++#define RADIO_2056_RX_RXLPF_INVCM_BODY 0x5d ++#define RADIO_2056_RX_RXLPF_CC_OP 0x5e ++#define RADIO_2056_RX_RXLPF_GAIN 0x5f ++#define RADIO_2056_RX_RXLPF_Q_BW 0x60 ++#define RADIO_2056_RX_RXLPF_HP_CORNER_BW 0x61 ++#define RADIO_2056_RX_RXLPF_RCCAL_HPC 0x62 ++#define RADIO_2056_RX_RXHPF_OFF0 0x63 ++#define RADIO_2056_RX_RXHPF_OFF1 0x64 ++#define RADIO_2056_RX_RXHPF_OFF2 0x65 ++#define RADIO_2056_RX_RXHPF_OFF3 0x66 ++#define RADIO_2056_RX_RXHPF_OFF4 0x67 ++#define RADIO_2056_RX_RXHPF_OFF5 0x68 ++#define RADIO_2056_RX_RXHPF_OFF6 0x69 ++#define RADIO_2056_RX_RXHPF_OFF7 0x6a ++#define RADIO_2056_RX_RXLPF_RCCAL_LPC 0x6b ++#define RADIO_2056_RX_RXLPF_OFF_0 0x6c ++#define RADIO_2056_RX_RXLPF_OFF_1 0x6d ++#define RADIO_2056_RX_RXLPF_OFF_2 0x6e ++#define RADIO_2056_RX_RXLPF_OFF_3 0x6f ++#define RADIO_2056_RX_RXLPF_OFF_4 0x70 ++#define RADIO_2056_RX_UNUSED 0x71 ++#define RADIO_2056_RX_VGA_MASTER 0x72 ++#define RADIO_2056_RX_VGA_BIAS 0x73 ++#define RADIO_2056_RX_VGA_BIAS_DCCANCEL 0x74 ++#define RADIO_2056_RX_VGA_GAIN 0x75 ++#define RADIO_2056_RX_VGA_HP_CORNER_BW 0x76 ++#define RADIO_2056_RX_VGABUF_BIAS 0x77 ++#define RADIO_2056_RX_VGABUF_GAIN_BW 0x78 ++#define RADIO_2056_RX_TXFBMIX_A 0x79 ++#define RADIO_2056_RX_TXFBMIX_G 0x7a ++#define RADIO_2056_RX_RXSPARE1 0x7b ++#define RADIO_2056_RX_RXSPARE2 0x7c ++#define RADIO_2056_RX_RXSPARE3 0x7d ++#define RADIO_2056_RX_RXSPARE4 0x7e ++#define RADIO_2056_RX_RXSPARE5 0x7f ++#define RADIO_2056_RX_RXSPARE6 0x80 ++#define RADIO_2056_RX_RXSPARE7 0x81 ++#define RADIO_2056_RX_RXSPARE8 0x82 ++#define RADIO_2056_RX_RXSPARE9 0x83 ++#define RADIO_2056_RX_RXSPARE10 0x84 ++#define RADIO_2056_RX_RXSPARE11 0x85 ++#define RADIO_2056_RX_RXSPARE12 0x86 ++#define RADIO_2056_RX_RXSPARE13 0x87 ++#define RADIO_2056_RX_RXSPARE14 0x88 ++#define RADIO_2056_RX_RXSPARE15 0x89 ++#define RADIO_2056_RX_RXSPARE16 0x8a ++#define RADIO_2056_RX_STATUS_LNAA_GAIN 0x8b ++#define RADIO_2056_RX_STATUS_LNAG_GAIN 0x8c ++#define RADIO_2056_RX_STATUS_MIXTIA_GAIN 0x8d ++#define RADIO_2056_RX_STATUS_RXLPF_GAIN 0x8e ++#define RADIO_2056_RX_STATUS_VGA_BUF_GAIN 0x8f ++#define RADIO_2056_RX_STATUS_RXLPF_Q 0x90 ++#define RADIO_2056_RX_STATUS_RXLPF_BUF_BW 0x91 ++#define RADIO_2056_RX_STATUS_RXLPF_VGA_HPC 0x92 ++#define RADIO_2056_RX_STATUS_RXLPF_RC 0x93 ++#define RADIO_2056_RX_STATUS_HPC_RC 0x94 ++ ++#define RADIO_2056_LNA1_A_PU 0x01 ++#define RADIO_2056_LNA2_A_PU 0x02 ++#define RADIO_2056_LNA1_G_PU 0x01 ++#define RADIO_2056_LNA2_G_PU 0x02 ++#define RADIO_2056_MIXA_PU_I 0x01 ++#define RADIO_2056_MIXA_PU_Q 0x02 ++#define RADIO_2056_MIXA_PU_GM 0x10 ++#define RADIO_2056_MIXG_PU_I 0x01 ++#define RADIO_2056_MIXG_PU_Q 0x02 ++#define RADIO_2056_MIXG_PU_GM 0x10 ++#define RADIO_2056_TIA_PU 0x01 ++#define RADIO_2056_BB_LPF_PU 0x20 ++#define RADIO_2056_W1_PU 0x02 ++#define RADIO_2056_W2_PU 0x04 ++#define RADIO_2056_NB_PU 0x08 ++#define RADIO_2056_RSSI_W1_SEL 0x02 ++#define RADIO_2056_RSSI_W2_SEL 0x04 ++#define RADIO_2056_RSSI_NB_SEL 0x08 ++#define RADIO_2056_VCM_MASK 0x1c ++#define RADIO_2056_RSSI_VCM_SHIFT 0x02 ++ ++#define RADIO_2057_DACBUF_VINCM_CORE0 0x0 ++#define RADIO_2057_IDCODE 0x1 ++#define RADIO_2057_RCCAL_MASTER 0x2 ++#define RADIO_2057_RCCAL_CAP_SIZE 0x3 ++#define RADIO_2057_RCAL_CONFIG 0x4 ++#define RADIO_2057_GPAIO_CONFIG 0x5 ++#define RADIO_2057_GPAIO_SEL1 0x6 ++#define RADIO_2057_GPAIO_SEL0 0x7 ++#define RADIO_2057_CLPO_CONFIG 0x8 ++#define RADIO_2057_BANDGAP_CONFIG 0x9 ++#define RADIO_2057_BANDGAP_RCAL_TRIM 0xa ++#define RADIO_2057_AFEREG_CONFIG 0xb ++#define RADIO_2057_TEMPSENSE_CONFIG 0xc ++#define RADIO_2057_XTAL_CONFIG1 0xd ++#define RADIO_2057_XTAL_ICORE_SIZE 0xe ++#define RADIO_2057_XTAL_BUF_SIZE 0xf ++#define RADIO_2057_XTAL_PULLCAP_SIZE 0x10 ++#define RADIO_2057_RFPLL_MASTER 0x11 ++#define RADIO_2057_VCOMONITOR_VTH_L 0x12 ++#define RADIO_2057_VCOMONITOR_VTH_H 0x13 ++#define RADIO_2057_VCOCAL_BIASRESET_RFPLLREG_VOUT 0x14 ++#define RADIO_2057_VCO_VARCSIZE_IDAC 0x15 ++#define RADIO_2057_VCOCAL_COUNTVAL0 0x16 ++#define RADIO_2057_VCOCAL_COUNTVAL1 0x17 ++#define RADIO_2057_VCOCAL_INTCLK_COUNT 0x18 ++#define RADIO_2057_VCOCAL_MASTER 0x19 ++#define RADIO_2057_VCOCAL_NUMCAPCHANGE 0x1a ++#define RADIO_2057_VCOCAL_WINSIZE 0x1b ++#define RADIO_2057_VCOCAL_DELAY_AFTER_REFRESH 0x1c ++#define RADIO_2057_VCOCAL_DELAY_AFTER_CLOSELOOP 0x1d ++#define RADIO_2057_VCOCAL_DELAY_AFTER_OPENLOOP 0x1e ++#define RADIO_2057_VCOCAL_DELAY_BEFORE_OPENLOOP 0x1f ++#define RADIO_2057_VCO_FORCECAPEN_FORCECAP1 0x20 ++#define RADIO_2057_VCO_FORCECAP0 0x21 ++#define RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE 0x22 ++#define RADIO_2057_RFPLL_PFD_RESET_PW 0x23 ++#define RADIO_2057_RFPLL_LOOPFILTER_R2 0x24 ++#define RADIO_2057_RFPLL_LOOPFILTER_R1 0x25 ++#define RADIO_2057_RFPLL_LOOPFILTER_C3 0x26 ++#define RADIO_2057_RFPLL_LOOPFILTER_C2 0x27 ++#define RADIO_2057_RFPLL_LOOPFILTER_C1 0x28 ++#define RADIO_2057_CP_KPD_IDAC 0x29 ++#define RADIO_2057_RFPLL_IDACS 0x2a ++#define RADIO_2057_RFPLL_MISC_EN 0x2b ++#define RADIO_2057_RFPLL_MMD0 0x2c ++#define RADIO_2057_RFPLL_MMD1 0x2d ++#define RADIO_2057_RFPLL_MISC_CAL_RESETN 0x2e ++#define RADIO_2057_JTAGXTAL_SIZE_CPBIAS_FILTRES 0x2f ++#define RADIO_2057_VCO_ALCREF_BBPLLXTAL_SIZE 0x30 ++#define RADIO_2057_VCOCAL_READCAP0 0x31 ++#define RADIO_2057_VCOCAL_READCAP1 0x32 ++#define RADIO_2057_VCOCAL_STATUS 0x33 ++#define RADIO_2057_LOGEN_PUS 0x34 ++#define RADIO_2057_LOGEN_PTAT_RESETS 0x35 ++#define RADIO_2057_VCOBUF_IDACS 0x36 ++#define RADIO_2057_VCOBUF_TUNE 0x37 ++#define RADIO_2057_CMOSBUF_TX2GQ_IDACS 0x38 ++#define RADIO_2057_CMOSBUF_TX2GI_IDACS 0x39 ++#define RADIO_2057_CMOSBUF_TX5GQ_IDACS 0x3a ++#define RADIO_2057_CMOSBUF_TX5GI_IDACS 0x3b ++#define RADIO_2057_CMOSBUF_RX2GQ_IDACS 0x3c ++#define RADIO_2057_CMOSBUF_RX2GI_IDACS 0x3d ++#define RADIO_2057_CMOSBUF_RX5GQ_IDACS 0x3e ++#define RADIO_2057_CMOSBUF_RX5GI_IDACS 0x3f ++#define RADIO_2057_LOGEN_MX2G_IDACS 0x40 ++#define RADIO_2057_LOGEN_MX2G_TUNE 0x41 ++#define RADIO_2057_LOGEN_MX5G_IDACS 0x42 ++#define RADIO_2057_LOGEN_MX5G_TUNE 0x43 ++#define RADIO_2057_LOGEN_MX5G_RCCR 0x44 ++#define RADIO_2057_LOGEN_INDBUF2G_IDAC 0x45 ++#define RADIO_2057_LOGEN_INDBUF2G_IBOOST 0x46 ++#define RADIO_2057_LOGEN_INDBUF2G_TUNE 0x47 ++#define RADIO_2057_LOGEN_INDBUF5G_IDAC 0x48 ++#define RADIO_2057_LOGEN_INDBUF5G_IBOOST 0x49 ++#define RADIO_2057_LOGEN_INDBUF5G_TUNE 0x4a ++#define RADIO_2057_CMOSBUF_TX_RCCR 0x4b ++#define RADIO_2057_CMOSBUF_RX_RCCR 0x4c ++#define RADIO_2057_LOGEN_SEL_PKDET 0x4d ++#define RADIO_2057_CMOSBUF_SHAREIQ_PTAT 0x4e ++#define RADIO_2057_RXTXBIAS_CONFIG_CORE0 0x4f ++#define RADIO_2057_TXGM_TXRF_PUS_CORE0 0x50 ++#define RADIO_2057_TXGM_IDAC_BLEED_CORE0 0x51 ++#define RADIO_2057_TXGM_GAIN_CORE0 0x56 ++#define RADIO_2057_TXGM2G_PKDET_PUS_CORE0 0x57 ++#define RADIO_2057_PAD2G_PTATS_CORE0 0x58 ++#define RADIO_2057_PAD2G_IDACS_CORE0 0x59 ++#define RADIO_2057_PAD2G_BOOST_PU_CORE0 0x5a ++#define RADIO_2057_PAD2G_CASCV_GAIN_CORE0 0x5b ++#define RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0 0x5c ++#define RADIO_2057_TXMIX2G_LODC_CORE0 0x5d ++#define RADIO_2057_PAD2G_TUNE_PUS_CORE0 0x5e ++#define RADIO_2057_IPA2G_GAIN_CORE0 0x5f ++#define RADIO_2057_TSSI2G_SPARE1_CORE0 0x60 ++#define RADIO_2057_TSSI2G_SPARE2_CORE0 0x61 ++#define RADIO_2057_IPA2G_TUNEV_CASCV_PTAT_CORE0 0x62 ++#define RADIO_2057_IPA2G_IMAIN_CORE0 0x63 ++#define RADIO_2057_IPA2G_CASCONV_CORE0 0x64 ++#define RADIO_2057_IPA2G_CASCOFFV_CORE0 0x65 ++#define RADIO_2057_IPA2G_BIAS_FILTER_CORE0 0x66 ++#define RADIO_2057_TX5G_PKDET_CORE0 0x69 ++#define RADIO_2057_PGA_PTAT_TXGM5G_PU_CORE0 0x6a ++#define RADIO_2057_PAD5G_PTATS1_CORE0 0x6b ++#define RADIO_2057_PAD5G_CLASS_PTATS2_CORE0 0x6c ++#define RADIO_2057_PGA_BOOSTPTAT_IMAIN_CORE0 0x6d ++#define RADIO_2057_PAD5G_CASCV_IMAIN_CORE0 0x6e ++#define RADIO_2057_TXMIX5G_IBOOST_PAD_IAUX_CORE0 0x6f ++#define RADIO_2057_PGA_BOOST_TUNE_CORE0 0x70 ++#define RADIO_2057_PGA_GAIN_CORE0 0x71 ++#define RADIO_2057_PAD5G_CASCOFFV_GAIN_PUS_CORE0 0x72 ++#define RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0 0x73 ++#define RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0 0x74 ++#define RADIO_2057_IPA5G_IAUX_CORE0 0x75 ++#define RADIO_2057_IPA5G_GAIN_CORE0 0x76 ++#define RADIO_2057_TSSI5G_SPARE1_CORE0 0x77 ++#define RADIO_2057_TSSI5G_SPARE2_CORE0 0x78 ++#define RADIO_2057_IPA5G_CASCOFFV_PU_CORE0 0x79 ++#define RADIO_2057_IPA5G_PTAT_CORE0 0x7a ++#define RADIO_2057_IPA5G_IMAIN_CORE0 0x7b ++#define RADIO_2057_IPA5G_CASCONV_CORE0 0x7c ++#define RADIO_2057_IPA5G_BIAS_FILTER_CORE0 0x7d ++#define RADIO_2057_PAD_BIAS_FILTER_BWS_CORE0 0x80 ++#define RADIO_2057_TR2G_CONFIG1_CORE0_NU 0x81 ++#define RADIO_2057_TR2G_CONFIG2_CORE0_NU 0x82 ++#define RADIO_2057_LNA5G_RFEN_CORE0 0x83 ++#define RADIO_2057_TR5G_CONFIG2_CORE0_NU 0x84 ++#define RADIO_2057_RXRFBIAS_IBOOST_PU_CORE0 0x85 ++#define RADIO_2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE0 0x86 ++#define RADIO_2057_RXGM_CMFBITAIL_AUXPTAT_CORE0 0x87 ++#define RADIO_2057_RXMIX_ICORE_RXGM_IAUX_CORE0 0x88 ++#define RADIO_2057_RXMIX_CMFBITAIL_PU_CORE0 0x89 ++#define RADIO_2057_LNA2_IMAIN_PTAT_PU_CORE0 0x8a ++#define RADIO_2057_LNA2_IAUX_PTAT_CORE0 0x8b ++#define RADIO_2057_LNA1_IMAIN_PTAT_PU_CORE0 0x8c ++#define RADIO_2057_LNA15G_INPUT_MATCH_TUNE_CORE0 0x8d ++#define RADIO_2057_RXRFBIAS_BANDSEL_CORE0 0x8e ++#define RADIO_2057_TIA_CONFIG_CORE0 0x8f ++#define RADIO_2057_TIA_IQGAIN_CORE0 0x90 ++#define RADIO_2057_TIA_IBIAS2_CORE0 0x91 ++#define RADIO_2057_TIA_IBIAS1_CORE0 0x92 ++#define RADIO_2057_TIA_SPARE_Q_CORE0 0x93 ++#define RADIO_2057_TIA_SPARE_I_CORE0 0x94 ++#define RADIO_2057_RXMIX2G_PUS_CORE0 0x95 ++#define RADIO_2057_RXMIX2G_VCMREFS_CORE0 0x96 ++#define RADIO_2057_RXMIX2G_LODC_QI_CORE0 0x97 ++#define RADIO_2057_W12G_BW_LNA2G_PUS_CORE0 0x98 ++#define RADIO_2057_LNA2G_GAIN_CORE0 0x99 ++#define RADIO_2057_LNA2G_TUNE_CORE0 0x9a ++#define RADIO_2057_RXMIX5G_PUS_CORE0 0x9b ++#define RADIO_2057_RXMIX5G_VCMREFS_CORE0 0x9c ++#define RADIO_2057_RXMIX5G_LODC_QI_CORE0 0x9d ++#define RADIO_2057_W15G_BW_LNA5G_PUS_CORE0 0x9e ++#define RADIO_2057_LNA5G_GAIN_CORE0 0x9f ++#define RADIO_2057_LNA5G_TUNE_CORE0 0xa0 ++#define RADIO_2057_LPFSEL_TXRX_RXBB_PUS_CORE0 0xa1 ++#define RADIO_2057_RXBB_BIAS_MASTER_CORE0 0xa2 ++#define RADIO_2057_RXBB_VGABUF_IDACS_CORE0 0xa3 ++#define RADIO_2057_LPF_VCMREF_TXBUF_VCMREF_CORE0 0xa4 ++#define RADIO_2057_TXBUF_VINCM_CORE0 0xa5 ++#define RADIO_2057_TXBUF_IDACS_CORE0 0xa6 ++#define RADIO_2057_LPF_RESP_RXBUF_BW_CORE0 0xa7 ++#define RADIO_2057_RXBB_CC_CORE0 0xa8 ++#define RADIO_2057_RXBB_SPARE3_CORE0 0xa9 ++#define RADIO_2057_RXBB_RCCAL_HPC_CORE0 0xaa ++#define RADIO_2057_LPF_IDACS_CORE0 0xab ++#define RADIO_2057_LPFBYP_DCLOOP_BYP_IDAC_CORE0 0xac ++#define RADIO_2057_TXBUF_GAIN_CORE0 0xad ++#define RADIO_2057_AFELOOPBACK_AACI_RESP_CORE0 0xae ++#define RADIO_2057_RXBUF_DEGEN_CORE0 0xaf ++#define RADIO_2057_RXBB_SPARE2_CORE0 0xb0 ++#define RADIO_2057_RXBB_SPARE1_CORE0 0xb1 ++#define RADIO_2057_RSSI_MASTER_CORE0 0xb2 ++#define RADIO_2057_W2_MASTER_CORE0 0xb3 ++#define RADIO_2057_NB_MASTER_CORE0 0xb4 ++#define RADIO_2057_W2_IDACS0_Q_CORE0 0xb5 ++#define RADIO_2057_W2_IDACS1_Q_CORE0 0xb6 ++#define RADIO_2057_W2_IDACS0_I_CORE0 0xb7 ++#define RADIO_2057_W2_IDACS1_I_CORE0 0xb8 ++#define RADIO_2057_RSSI_GPAIOSEL_W1_IDACS_CORE0 0xb9 ++#define RADIO_2057_NB_IDACS_Q_CORE0 0xba ++#define RADIO_2057_NB_IDACS_I_CORE0 0xbb ++#define RADIO_2057_BACKUP4_CORE0 0xc1 ++#define RADIO_2057_BACKUP3_CORE0 0xc2 ++#define RADIO_2057_BACKUP2_CORE0 0xc3 ++#define RADIO_2057_BACKUP1_CORE0 0xc4 ++#define RADIO_2057_SPARE16_CORE0 0xc5 ++#define RADIO_2057_SPARE15_CORE0 0xc6 ++#define RADIO_2057_SPARE14_CORE0 0xc7 ++#define RADIO_2057_SPARE13_CORE0 0xc8 ++#define RADIO_2057_SPARE12_CORE0 0xc9 ++#define RADIO_2057_SPARE11_CORE0 0xca ++#define RADIO_2057_TX2G_BIAS_RESETS_CORE0 0xcb ++#define RADIO_2057_TX5G_BIAS_RESETS_CORE0 0xcc ++#define RADIO_2057_IQTEST_SEL_PU 0xcd ++#define RADIO_2057_XTAL_CONFIG2 0xce ++#define RADIO_2057_BUFS_MISC_LPFBW_CORE0 0xcf ++#define RADIO_2057_TXLPF_RCCAL_CORE0 0xd0 ++#define RADIO_2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0xd1 ++#define RADIO_2057_LPF_GAIN_CORE0 0xd2 ++#define RADIO_2057_DACBUF_IDACS_BW_CORE0 0xd3 ++#define RADIO_2057_RXTXBIAS_CONFIG_CORE1 0xd4 ++#define RADIO_2057_TXGM_TXRF_PUS_CORE1 0xd5 ++#define RADIO_2057_TXGM_IDAC_BLEED_CORE1 0xd6 ++#define RADIO_2057_TXGM_GAIN_CORE1 0xdb ++#define RADIO_2057_TXGM2G_PKDET_PUS_CORE1 0xdc ++#define RADIO_2057_PAD2G_PTATS_CORE1 0xdd ++#define RADIO_2057_PAD2G_IDACS_CORE1 0xde ++#define RADIO_2057_PAD2G_BOOST_PU_CORE1 0xdf ++#define RADIO_2057_PAD2G_CASCV_GAIN_CORE1 0xe0 ++#define RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1 0xe1 ++#define RADIO_2057_TXMIX2G_LODC_CORE1 0xe2 ++#define RADIO_2057_PAD2G_TUNE_PUS_CORE1 0xe3 ++#define RADIO_2057_IPA2G_GAIN_CORE1 0xe4 ++#define RADIO_2057_TSSI2G_SPARE1_CORE1 0xe5 ++#define RADIO_2057_TSSI2G_SPARE2_CORE1 0xe6 ++#define RADIO_2057_IPA2G_TUNEV_CASCV_PTAT_CORE1 0xe7 ++#define RADIO_2057_IPA2G_IMAIN_CORE1 0xe8 ++#define RADIO_2057_IPA2G_CASCONV_CORE1 0xe9 ++#define RADIO_2057_IPA2G_CASCOFFV_CORE1 0xea ++#define RADIO_2057_IPA2G_BIAS_FILTER_CORE1 0xeb ++#define RADIO_2057_TX5G_PKDET_CORE1 0xee ++#define RADIO_2057_PGA_PTAT_TXGM5G_PU_CORE1 0xef ++#define RADIO_2057_PAD5G_PTATS1_CORE1 0xf0 ++#define RADIO_2057_PAD5G_CLASS_PTATS2_CORE1 0xf1 ++#define RADIO_2057_PGA_BOOSTPTAT_IMAIN_CORE1 0xf2 ++#define RADIO_2057_PAD5G_CASCV_IMAIN_CORE1 0xf3 ++#define RADIO_2057_TXMIX5G_IBOOST_PAD_IAUX_CORE1 0xf4 ++#define RADIO_2057_PGA_BOOST_TUNE_CORE1 0xf5 ++#define RADIO_2057_PGA_GAIN_CORE1 0xf6 ++#define RADIO_2057_PAD5G_CASCOFFV_GAIN_PUS_CORE1 0xf7 ++#define RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1 0xf8 ++#define RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1 0xf9 ++#define RADIO_2057_IPA5G_IAUX_CORE1 0xfa ++#define RADIO_2057_IPA5G_GAIN_CORE1 0xfb ++#define RADIO_2057_TSSI5G_SPARE1_CORE1 0xfc ++#define RADIO_2057_TSSI5G_SPARE2_CORE1 0xfd ++#define RADIO_2057_IPA5G_CASCOFFV_PU_CORE1 0xfe ++#define RADIO_2057_IPA5G_PTAT_CORE1 0xff ++#define RADIO_2057_IPA5G_IMAIN_CORE1 0x100 ++#define RADIO_2057_IPA5G_CASCONV_CORE1 0x101 ++#define RADIO_2057_IPA5G_BIAS_FILTER_CORE1 0x102 ++#define RADIO_2057_PAD_BIAS_FILTER_BWS_CORE1 0x105 ++#define RADIO_2057_TR2G_CONFIG1_CORE1_NU 0x106 ++#define RADIO_2057_TR2G_CONFIG2_CORE1_NU 0x107 ++#define RADIO_2057_LNA5G_RFEN_CORE1 0x108 ++#define RADIO_2057_TR5G_CONFIG2_CORE1_NU 0x109 ++#define RADIO_2057_RXRFBIAS_IBOOST_PU_CORE1 0x10a ++#define RADIO_2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE1 0x10b ++#define RADIO_2057_RXGM_CMFBITAIL_AUXPTAT_CORE1 0x10c ++#define RADIO_2057_RXMIX_ICORE_RXGM_IAUX_CORE1 0x10d ++#define RADIO_2057_RXMIX_CMFBITAIL_PU_CORE1 0x10e ++#define RADIO_2057_LNA2_IMAIN_PTAT_PU_CORE1 0x10f ++#define RADIO_2057_LNA2_IAUX_PTAT_CORE1 0x110 ++#define RADIO_2057_LNA1_IMAIN_PTAT_PU_CORE1 0x111 ++#define RADIO_2057_LNA15G_INPUT_MATCH_TUNE_CORE1 0x112 ++#define RADIO_2057_RXRFBIAS_BANDSEL_CORE1 0x113 ++#define RADIO_2057_TIA_CONFIG_CORE1 0x114 ++#define RADIO_2057_TIA_IQGAIN_CORE1 0x115 ++#define RADIO_2057_TIA_IBIAS2_CORE1 0x116 ++#define RADIO_2057_TIA_IBIAS1_CORE1 0x117 ++#define RADIO_2057_TIA_SPARE_Q_CORE1 0x118 ++#define RADIO_2057_TIA_SPARE_I_CORE1 0x119 ++#define RADIO_2057_RXMIX2G_PUS_CORE1 0x11a ++#define RADIO_2057_RXMIX2G_VCMREFS_CORE1 0x11b ++#define RADIO_2057_RXMIX2G_LODC_QI_CORE1 0x11c ++#define RADIO_2057_W12G_BW_LNA2G_PUS_CORE1 0x11d ++#define RADIO_2057_LNA2G_GAIN_CORE1 0x11e ++#define RADIO_2057_LNA2G_TUNE_CORE1 0x11f ++#define RADIO_2057_RXMIX5G_PUS_CORE1 0x120 ++#define RADIO_2057_RXMIX5G_VCMREFS_CORE1 0x121 ++#define RADIO_2057_RXMIX5G_LODC_QI_CORE1 0x122 ++#define RADIO_2057_W15G_BW_LNA5G_PUS_CORE1 0x123 ++#define RADIO_2057_LNA5G_GAIN_CORE1 0x124 ++#define RADIO_2057_LNA5G_TUNE_CORE1 0x125 ++#define RADIO_2057_LPFSEL_TXRX_RXBB_PUS_CORE1 0x126 ++#define RADIO_2057_RXBB_BIAS_MASTER_CORE1 0x127 ++#define RADIO_2057_RXBB_VGABUF_IDACS_CORE1 0x128 ++#define RADIO_2057_LPF_VCMREF_TXBUF_VCMREF_CORE1 0x129 ++#define RADIO_2057_TXBUF_VINCM_CORE1 0x12a ++#define RADIO_2057_TXBUF_IDACS_CORE1 0x12b ++#define RADIO_2057_LPF_RESP_RXBUF_BW_CORE1 0x12c ++#define RADIO_2057_RXBB_CC_CORE1 0x12d ++#define RADIO_2057_RXBB_SPARE3_CORE1 0x12e ++#define RADIO_2057_RXBB_RCCAL_HPC_CORE1 0x12f ++#define RADIO_2057_LPF_IDACS_CORE1 0x130 ++#define RADIO_2057_LPFBYP_DCLOOP_BYP_IDAC_CORE1 0x131 ++#define RADIO_2057_TXBUF_GAIN_CORE1 0x132 ++#define RADIO_2057_AFELOOPBACK_AACI_RESP_CORE1 0x133 ++#define RADIO_2057_RXBUF_DEGEN_CORE1 0x134 ++#define RADIO_2057_RXBB_SPARE2_CORE1 0x135 ++#define RADIO_2057_RXBB_SPARE1_CORE1 0x136 ++#define RADIO_2057_RSSI_MASTER_CORE1 0x137 ++#define RADIO_2057_W2_MASTER_CORE1 0x138 ++#define RADIO_2057_NB_MASTER_CORE1 0x139 ++#define RADIO_2057_W2_IDACS0_Q_CORE1 0x13a ++#define RADIO_2057_W2_IDACS1_Q_CORE1 0x13b ++#define RADIO_2057_W2_IDACS0_I_CORE1 0x13c ++#define RADIO_2057_W2_IDACS1_I_CORE1 0x13d ++#define RADIO_2057_RSSI_GPAIOSEL_W1_IDACS_CORE1 0x13e ++#define RADIO_2057_NB_IDACS_Q_CORE1 0x13f ++#define RADIO_2057_NB_IDACS_I_CORE1 0x140 ++#define RADIO_2057_BACKUP4_CORE1 0x146 ++#define RADIO_2057_BACKUP3_CORE1 0x147 ++#define RADIO_2057_BACKUP2_CORE1 0x148 ++#define RADIO_2057_BACKUP1_CORE1 0x149 ++#define RADIO_2057_SPARE16_CORE1 0x14a ++#define RADIO_2057_SPARE15_CORE1 0x14b ++#define RADIO_2057_SPARE14_CORE1 0x14c ++#define RADIO_2057_SPARE13_CORE1 0x14d ++#define RADIO_2057_SPARE12_CORE1 0x14e ++#define RADIO_2057_SPARE11_CORE1 0x14f ++#define RADIO_2057_TX2G_BIAS_RESETS_CORE1 0x150 ++#define RADIO_2057_TX5G_BIAS_RESETS_CORE1 0x151 ++#define RADIO_2057_SPARE8_CORE1 0x152 ++#define RADIO_2057_SPARE7_CORE1 0x153 ++#define RADIO_2057_BUFS_MISC_LPFBW_CORE1 0x154 ++#define RADIO_2057_TXLPF_RCCAL_CORE1 0x155 ++#define RADIO_2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156 ++#define RADIO_2057_LPF_GAIN_CORE1 0x157 ++#define RADIO_2057_DACBUF_IDACS_BW_CORE1 0x158 ++#define RADIO_2057_DACBUF_VINCM_CORE1 0x159 ++#define RADIO_2057_RCCAL_START_R1_Q1_P1 0x15a ++#define RADIO_2057_RCCAL_X1 0x15b ++#define RADIO_2057_RCCAL_TRC0 0x15c ++#define RADIO_2057_RCCAL_TRC1 0x15d ++#define RADIO_2057_RCCAL_DONE_OSCCAP 0x15e ++#define RADIO_2057_RCCAL_N0_0 0x15f ++#define RADIO_2057_RCCAL_N0_1 0x160 ++#define RADIO_2057_RCCAL_N1_0 0x161 ++#define RADIO_2057_RCCAL_N1_1 0x162 ++#define RADIO_2057_RCAL_STATUS 0x163 ++#define RADIO_2057_XTALPUOVR_PINCTRL 0x164 ++#define RADIO_2057_OVR_REG0 0x165 ++#define RADIO_2057_OVR_REG1 0x166 ++#define RADIO_2057_OVR_REG2 0x167 ++#define RADIO_2057_OVR_REG3 0x168 ++#define RADIO_2057_OVR_REG4 0x169 ++#define RADIO_2057_RCCAL_SCAP_VAL 0x16a ++#define RADIO_2057_RCCAL_BCAP_VAL 0x16b ++#define RADIO_2057_RCCAL_HPC_VAL 0x16c ++#define RADIO_2057_RCCAL_OVERRIDES 0x16d ++#define RADIO_2057_TX0_IQCAL_GAIN_BW 0x170 ++#define RADIO_2057_TX0_LOFT_FINE_I 0x171 ++#define RADIO_2057_TX0_LOFT_FINE_Q 0x172 ++#define RADIO_2057_TX0_LOFT_COARSE_I 0x173 ++#define RADIO_2057_TX0_LOFT_COARSE_Q 0x174 ++#define RADIO_2057_TX0_TX_SSI_MASTER 0x175 ++#define RADIO_2057_TX0_IQCAL_VCM_HG 0x176 ++#define RADIO_2057_TX0_IQCAL_IDAC 0x177 ++#define RADIO_2057_TX0_TSSI_VCM 0x178 ++#define RADIO_2057_TX0_TX_SSI_MUX 0x179 ++#define RADIO_2057_TX0_TSSIA 0x17a ++#define RADIO_2057_TX0_TSSIG 0x17b ++#define RADIO_2057_TX0_TSSI_MISC1 0x17c ++#define RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN 0x17d ++#define RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP 0x17e ++#define RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN 0x17f ++#define RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP 0x180 ++#define RADIO_2057_TX1_IQCAL_GAIN_BW 0x190 ++#define RADIO_2057_TX1_LOFT_FINE_I 0x191 ++#define RADIO_2057_TX1_LOFT_FINE_Q 0x192 ++#define RADIO_2057_TX1_LOFT_COARSE_I 0x193 ++#define RADIO_2057_TX1_LOFT_COARSE_Q 0x194 ++#define RADIO_2057_TX1_TX_SSI_MASTER 0x195 ++#define RADIO_2057_TX1_IQCAL_VCM_HG 0x196 ++#define RADIO_2057_TX1_IQCAL_IDAC 0x197 ++#define RADIO_2057_TX1_TSSI_VCM 0x198 ++#define RADIO_2057_TX1_TX_SSI_MUX 0x199 ++#define RADIO_2057_TX1_TSSIA 0x19a ++#define RADIO_2057_TX1_TSSIG 0x19b ++#define RADIO_2057_TX1_TSSI_MISC1 0x19c ++#define RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN 0x19d ++#define RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP 0x19e ++#define RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN 0x19f ++#define RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP 0x1a0 ++#define RADIO_2057_AFE_VCM_CAL_MASTER_CORE0 0x1a1 ++#define RADIO_2057_AFE_SET_VCM_I_CORE0 0x1a2 ++#define RADIO_2057_AFE_SET_VCM_Q_CORE0 0x1a3 ++#define RADIO_2057_AFE_STATUS_VCM_IQADC_CORE0 0x1a4 ++#define RADIO_2057_AFE_STATUS_VCM_I_CORE0 0x1a5 ++#define RADIO_2057_AFE_STATUS_VCM_Q_CORE0 0x1a6 ++#define RADIO_2057_AFE_VCM_CAL_MASTER_CORE1 0x1a7 ++#define RADIO_2057_AFE_SET_VCM_I_CORE1 0x1a8 ++#define RADIO_2057_AFE_SET_VCM_Q_CORE1 0x1a9 ++#define RADIO_2057_AFE_STATUS_VCM_IQADC_CORE1 0x1aa ++#define RADIO_2057_AFE_STATUS_VCM_I_CORE1 0x1ab ++#define RADIO_2057_AFE_STATUS_VCM_Q_CORE1 0x1ac ++ ++#define RADIO_2057v7_DACBUF_VINCM_CORE0 0x1ad ++#define RADIO_2057v7_RCCAL_MASTER 0x1ae ++#define RADIO_2057v7_TR2G_CONFIG3_CORE0_NU 0x1af ++#define RADIO_2057v7_TR2G_CONFIG3_CORE1_NU 0x1b0 ++#define RADIO_2057v7_LOGEN_PUS1 0x1b1 ++#define RADIO_2057v7_OVR_REG5 0x1b2 ++#define RADIO_2057v7_OVR_REG6 0x1b3 ++#define RADIO_2057v7_OVR_REG7 0x1b4 ++#define RADIO_2057v7_OVR_REG8 0x1b5 ++#define RADIO_2057v7_OVR_REG9 0x1b6 ++#define RADIO_2057v7_OVR_REG10 0x1b7 ++#define RADIO_2057v7_OVR_REG11 0x1b8 ++#define RADIO_2057v7_OVR_REG12 0x1b9 ++#define RADIO_2057v7_OVR_REG13 0x1ba ++#define RADIO_2057v7_OVR_REG14 0x1bb ++#define RADIO_2057v7_OVR_REG15 0x1bc ++#define RADIO_2057v7_OVR_REG16 0x1bd ++#define RADIO_2057v7_OVR_REG1 0x1be ++#define RADIO_2057v7_OVR_REG18 0x1bf ++#define RADIO_2057v7_OVR_REG19 0x1c0 ++#define RADIO_2057v7_OVR_REG20 0x1c1 ++#define RADIO_2057v7_OVR_REG21 0x1c2 ++#define RADIO_2057v7_OVR_REG2 0x1c3 ++#define RADIO_2057v7_OVR_REG23 0x1c4 ++#define RADIO_2057v7_OVR_REG24 0x1c5 ++#define RADIO_2057v7_OVR_REG25 0x1c6 ++#define RADIO_2057v7_OVR_REG26 0x1c7 ++#define RADIO_2057v7_OVR_REG27 0x1c8 ++#define RADIO_2057v7_OVR_REG28 0x1c9 ++#define RADIO_2057v7_IQTEST_SEL_PU2 0x1ca ++ ++#define RADIO_2057_VCM_MASK 0x7 ++ ++#endif /* _BRCM_PHY_RADIO_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phyreg_n.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phyreg_n.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phyreg_n.h.orig 2011-11-09 13:46:58.277800233 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phyreg_n.h 2011-11-09 13:47:17.035565729 -0500 +@@ -0,0 +1,167 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#define NPHY_TBL_ID_GAIN1 0 ++#define NPHY_TBL_ID_GAIN2 1 ++#define NPHY_TBL_ID_GAINBITS1 2 ++#define NPHY_TBL_ID_GAINBITS2 3 ++#define NPHY_TBL_ID_GAINLIMIT 4 ++#define NPHY_TBL_ID_WRSSIGainLimit 5 ++#define NPHY_TBL_ID_RFSEQ 7 ++#define NPHY_TBL_ID_AFECTRL 8 ++#define NPHY_TBL_ID_ANTSWCTRLLUT 9 ++#define NPHY_TBL_ID_IQLOCAL 15 ++#define NPHY_TBL_ID_NOISEVAR 16 ++#define NPHY_TBL_ID_SAMPLEPLAY 17 ++#define NPHY_TBL_ID_CORE1TXPWRCTL 26 ++#define NPHY_TBL_ID_CORE2TXPWRCTL 27 ++#define NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL 30 ++ ++#define NPHY_TBL_ID_EPSILONTBL0 31 ++#define NPHY_TBL_ID_SCALARTBL0 32 ++#define NPHY_TBL_ID_EPSILONTBL1 33 ++#define NPHY_TBL_ID_SCALARTBL1 34 ++ ++#define NPHY_TO_BPHY_OFF 0xc00 ++ ++#define NPHY_BandControl_currentBand 0x0001 ++#define RFCC_CHIP0_PU 0x0400 ++#define RFCC_POR_FORCE 0x0040 ++#define RFCC_OE_POR_FORCE 0x0080 ++#define NPHY_RfctrlIntc_override_OFF 0 ++#define NPHY_RfctrlIntc_override_TRSW 1 ++#define NPHY_RfctrlIntc_override_PA 2 ++#define NPHY_RfctrlIntc_override_EXT_LNA_PU 3 ++#define NPHY_RfctrlIntc_override_EXT_LNA_GAIN 4 ++#define RIFS_ENABLE 0x80 ++#define BPHY_BAND_SEL_UP20 0x10 ++#define NPHY_MLenable 0x02 ++ ++#define NPHY_RfseqMode_CoreActv_override 0x0001 ++#define NPHY_RfseqMode_Trigger_override 0x0002 ++#define NPHY_RfseqCoreActv_TxRxChain0 (0x11) ++#define NPHY_RfseqCoreActv_TxRxChain1 (0x22) ++ ++#define NPHY_RfseqTrigger_rx2tx 0x0001 ++#define NPHY_RfseqTrigger_tx2rx 0x0002 ++#define NPHY_RfseqTrigger_updategainh 0x0004 ++#define NPHY_RfseqTrigger_updategainl 0x0008 ++#define NPHY_RfseqTrigger_updategainu 0x0010 ++#define NPHY_RfseqTrigger_reset2rx 0x0020 ++#define NPHY_RfseqStatus_rx2tx 0x0001 ++#define NPHY_RfseqStatus_tx2rx 0x0002 ++#define NPHY_RfseqStatus_updategainh 0x0004 ++#define NPHY_RfseqStatus_updategainl 0x0008 ++#define NPHY_RfseqStatus_updategainu 0x0010 ++#define NPHY_RfseqStatus_reset2rx 0x0020 ++#define NPHY_ClassifierCtrl_cck_en 0x1 ++#define NPHY_ClassifierCtrl_ofdm_en 0x2 ++#define NPHY_ClassifierCtrl_waited_en 0x4 ++#define NPHY_IQFlip_ADC1 0x0001 ++#define NPHY_IQFlip_ADC2 0x0010 ++#define NPHY_sampleCmd_STOP 0x0002 ++ ++#define RX_GF_OR_MM 0x0004 ++#define RX_GF_MM_AUTO 0x0100 ++ ++#define NPHY_iqloCalCmdGctl_IQLO_CAL_EN 0x8000 ++ ++#define NPHY_IqestCmd_iqstart 0x1 ++#define NPHY_IqestCmd_iqMode 0x2 ++ ++#define NPHY_TxPwrCtrlCmd_pwrIndex_init 0x40 ++#define NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 0x19 ++ ++#define PRIM_SEL_UP20 0x8000 ++ ++#define NPHY_RFSEQ_RX2TX 0x0 ++#define NPHY_RFSEQ_TX2RX 0x1 ++#define NPHY_RFSEQ_RESET2RX 0x2 ++#define NPHY_RFSEQ_UPDATEGAINH 0x3 ++#define NPHY_RFSEQ_UPDATEGAINL 0x4 ++#define NPHY_RFSEQ_UPDATEGAINU 0x5 ++ ++#define NPHY_RFSEQ_CMD_NOP 0x0 ++#define NPHY_RFSEQ_CMD_RXG_FBW 0x1 ++#define NPHY_RFSEQ_CMD_TR_SWITCH 0x2 ++#define NPHY_RFSEQ_CMD_EXT_PA 0x3 ++#define NPHY_RFSEQ_CMD_RXPD_TXPD 0x4 ++#define NPHY_RFSEQ_CMD_TX_GAIN 0x5 ++#define NPHY_RFSEQ_CMD_RX_GAIN 0x6 ++#define NPHY_RFSEQ_CMD_SET_HPF_BW 0x7 ++#define NPHY_RFSEQ_CMD_CLR_HIQ_DIS 0x8 ++#define NPHY_RFSEQ_CMD_END 0xf ++ ++#define NPHY_REV3_RFSEQ_CMD_NOP 0x0 ++#define NPHY_REV3_RFSEQ_CMD_RXG_FBW 0x1 ++#define NPHY_REV3_RFSEQ_CMD_TR_SWITCH 0x2 ++#define NPHY_REV3_RFSEQ_CMD_INT_PA_PU 0x3 ++#define NPHY_REV3_RFSEQ_CMD_EXT_PA 0x4 ++#define NPHY_REV3_RFSEQ_CMD_RXPD_TXPD 0x5 ++#define NPHY_REV3_RFSEQ_CMD_TX_GAIN 0x6 ++#define NPHY_REV3_RFSEQ_CMD_RX_GAIN 0x7 ++#define NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS 0x8 ++#define NPHY_REV3_RFSEQ_CMD_SET_HPF_H_HPC 0x9 ++#define NPHY_REV3_RFSEQ_CMD_SET_LPF_H_HPC 0xa ++#define NPHY_REV3_RFSEQ_CMD_SET_HPF_M_HPC 0xb ++#define NPHY_REV3_RFSEQ_CMD_SET_LPF_M_HPC 0xc ++#define NPHY_REV3_RFSEQ_CMD_SET_HPF_L_HPC 0xd ++#define NPHY_REV3_RFSEQ_CMD_SET_LPF_L_HPC 0xe ++#define NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS 0xf ++#define NPHY_REV3_RFSEQ_CMD_END 0x1f ++ ++#define NPHY_RSSI_SEL_W1 0x0 ++#define NPHY_RSSI_SEL_W2 0x1 ++#define NPHY_RSSI_SEL_NB 0x2 ++#define NPHY_RSSI_SEL_IQ 0x3 ++#define NPHY_RSSI_SEL_TSSI_2G 0x4 ++#define NPHY_RSSI_SEL_TSSI_5G 0x5 ++#define NPHY_RSSI_SEL_TBD 0x6 ++ ++#define NPHY_RAIL_I 0x0 ++#define NPHY_RAIL_Q 0x1 ++ ++#define NPHY_FORCESIG_DECODEGATEDCLKS 0x8 ++ ++#define NPHY_REV7_RfctrlOverride_cmd_rxrf_pu 0x0 ++#define NPHY_REV7_RfctrlOverride_cmd_rx_pu 0x1 ++#define NPHY_REV7_RfctrlOverride_cmd_tx_pu 0x2 ++#define NPHY_REV7_RfctrlOverride_cmd_rxgain 0x3 ++#define NPHY_REV7_RfctrlOverride_cmd_txgain 0x4 ++ ++#define NPHY_REV7_RXGAINCODE_RFMXGAIN_MASK 0x000ff ++#define NPHY_REV7_RXGAINCODE_LPFGAIN_MASK 0x0ff00 ++#define NPHY_REV7_RXGAINCODE_DVGAGAIN_MASK 0xf0000 ++ ++#define NPHY_REV7_TXGAINCODE_TGAIN_MASK 0x7fff ++#define NPHY_REV7_TXGAINCODE_LPFGAIN_MASK 0x8000 ++#define NPHY_REV7_TXGAINCODE_BIQ0GAIN_SHIFT 14 ++ ++#define NPHY_REV7_RFCTRLOVERRIDE_ID0 0x0 ++#define NPHY_REV7_RFCTRLOVERRIDE_ID1 0x1 ++#define NPHY_REV7_RFCTRLOVERRIDE_ID2 0x2 ++ ++#define NPHY_IqestIqAccLo(core) ((core == 0) ? 0x12c : 0x134) ++ ++#define NPHY_IqestIqAccHi(core) ((core == 0) ? 0x12d : 0x135) ++ ++#define NPHY_IqestipwrAccLo(core) ((core == 0) ? 0x12e : 0x136) ++ ++#define NPHY_IqestipwrAccHi(core) ((core == 0) ? 0x12f : 0x137) ++ ++#define NPHY_IqestqpwrAccLo(core) ((core == 0) ? 0x130 : 0x138) ++ ++#define NPHY_IqestqpwrAccHi(core) ((core == 0) ? 0x131 : 0x139) +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c.orig 2011-11-09 13:46:58.278800221 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c 2011-11-09 13:47:17.036565717 -0500 +@@ -0,0 +1,3250 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include "phytbl_lcn.h" ++ ++static const u32 dot11lcn_gain_tbl_rev0[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000004, ++ 0x00000000, ++ 0x00000004, ++ 0x00000008, ++ 0x00000001, ++ 0x00000005, ++ 0x00000009, ++ 0x0000000d, ++ 0x0000004d, ++ 0x0000008d, ++ 0x0000000d, ++ 0x0000004d, ++ 0x0000008d, ++ 0x000000cd, ++ 0x0000004f, ++ 0x0000008f, ++ 0x000000cf, ++ 0x000000d3, ++ 0x00000113, ++ 0x00000513, ++ 0x00000913, ++ 0x00000953, ++ 0x00000d53, ++ 0x00001153, ++ 0x00001193, ++ 0x00005193, ++ 0x00009193, ++ 0x0000d193, ++ 0x00011193, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000004, ++ 0x00000000, ++ 0x00000004, ++ 0x00000008, ++ 0x00000001, ++ 0x00000005, ++ 0x00000009, ++ 0x0000000d, ++ 0x0000004d, ++ 0x0000008d, ++ 0x0000000d, ++ 0x0000004d, ++ 0x0000008d, ++ 0x000000cd, ++ 0x0000004f, ++ 0x0000008f, ++ 0x000000cf, ++ 0x000000d3, ++ 0x00000113, ++ 0x00000513, ++ 0x00000913, ++ 0x00000953, ++ 0x00000d53, ++ 0x00001153, ++ 0x00005153, ++ 0x00009153, ++ 0x0000d153, ++ 0x00011153, ++ 0x00015153, ++ 0x00019153, ++ 0x0001d153, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 dot11lcn_gain_tbl_rev1[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000008, ++ 0x00000004, ++ 0x00000008, ++ 0x00000001, ++ 0x00000005, ++ 0x00000009, ++ 0x0000000D, ++ 0x00000011, ++ 0x00000051, ++ 0x00000091, ++ 0x00000011, ++ 0x00000051, ++ 0x00000091, ++ 0x000000d1, ++ 0x00000053, ++ 0x00000093, ++ 0x000000d3, ++ 0x000000d7, ++ 0x00000117, ++ 0x00000517, ++ 0x00000917, ++ 0x00000957, ++ 0x00000d57, ++ 0x00001157, ++ 0x00001197, ++ 0x00005197, ++ 0x00009197, ++ 0x0000d197, ++ 0x00011197, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000008, ++ 0x00000004, ++ 0x00000008, ++ 0x00000001, ++ 0x00000005, ++ 0x00000009, ++ 0x0000000D, ++ 0x00000011, ++ 0x00000051, ++ 0x00000091, ++ 0x00000011, ++ 0x00000051, ++ 0x00000091, ++ 0x000000d1, ++ 0x00000053, ++ 0x00000093, ++ 0x000000d3, ++ 0x000000d7, ++ 0x00000117, ++ 0x00000517, ++ 0x00000917, ++ 0x00000957, ++ 0x00000d57, ++ 0x00001157, ++ 0x00005157, ++ 0x00009157, ++ 0x0000d157, ++ 0x00011157, ++ 0x00015157, ++ 0x00019157, ++ 0x0001d157, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u16 dot11lcn_aux_gain_idx_tbl_rev0[] = { ++ 0x0401, ++ 0x0402, ++ 0x0403, ++ 0x0404, ++ 0x0405, ++ 0x0406, ++ 0x0407, ++ 0x0408, ++ 0x0409, ++ 0x040a, ++ 0x058b, ++ 0x058c, ++ 0x058d, ++ 0x058e, ++ 0x058f, ++ 0x0090, ++ 0x0091, ++ 0x0092, ++ 0x0193, ++ 0x0194, ++ 0x0195, ++ 0x0196, ++ 0x0197, ++ 0x0198, ++ 0x0199, ++ 0x019a, ++ 0x019b, ++ 0x019c, ++ 0x019d, ++ 0x019e, ++ 0x019f, ++ 0x01a0, ++ 0x01a1, ++ 0x01a2, ++ 0x01a3, ++ 0x01a4, ++ 0x01a5, ++ 0x0000, ++}; ++ ++static const u32 dot11lcn_gain_idx_tbl_rev0[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x10000000, ++ 0x00000000, ++ 0x20000000, ++ 0x00000000, ++ 0x30000000, ++ 0x00000000, ++ 0x40000000, ++ 0x00000000, ++ 0x50000000, ++ 0x00000000, ++ 0x60000000, ++ 0x00000000, ++ 0x70000000, ++ 0x00000000, ++ 0x80000000, ++ 0x00000000, ++ 0x90000000, ++ 0x00000008, ++ 0xa0000000, ++ 0x00000008, ++ 0xb0000000, ++ 0x00000008, ++ 0xc0000000, ++ 0x00000008, ++ 0xd0000000, ++ 0x00000008, ++ 0xe0000000, ++ 0x00000008, ++ 0xf0000000, ++ 0x00000008, ++ 0x00000000, ++ 0x00000009, ++ 0x10000000, ++ 0x00000009, ++ 0x20000000, ++ 0x00000019, ++ 0x30000000, ++ 0x00000019, ++ 0x40000000, ++ 0x00000019, ++ 0x50000000, ++ 0x00000019, ++ 0x60000000, ++ 0x00000019, ++ 0x70000000, ++ 0x00000019, ++ 0x80000000, ++ 0x00000019, ++ 0x90000000, ++ 0x00000019, ++ 0xa0000000, ++ 0x00000019, ++ 0xb0000000, ++ 0x00000019, ++ 0xc0000000, ++ 0x00000019, ++ 0xd0000000, ++ 0x00000019, ++ 0xe0000000, ++ 0x00000019, ++ 0xf0000000, ++ 0x00000019, ++ 0x00000000, ++ 0x0000001a, ++ 0x10000000, ++ 0x0000001a, ++ 0x20000000, ++ 0x0000001a, ++ 0x30000000, ++ 0x0000001a, ++ 0x40000000, ++ 0x0000001a, ++ 0x50000000, ++ 0x00000002, ++ 0x60000000, ++ 0x00000002, ++ 0x70000000, ++ 0x00000002, ++ 0x80000000, ++ 0x00000002, ++ 0x90000000, ++ 0x00000002, ++ 0xa0000000, ++ 0x00000002, ++ 0xb0000000, ++ 0x00000002, ++ 0xc0000000, ++ 0x0000000a, ++ 0xd0000000, ++ 0x0000000a, ++ 0xe0000000, ++ 0x0000000a, ++ 0xf0000000, ++ 0x0000000a, ++ 0x00000000, ++ 0x0000000b, ++ 0x10000000, ++ 0x0000000b, ++ 0x20000000, ++ 0x0000000b, ++ 0x30000000, ++ 0x0000000b, ++ 0x40000000, ++ 0x0000000b, ++ 0x50000000, ++ 0x0000001b, ++ 0x60000000, ++ 0x0000001b, ++ 0x70000000, ++ 0x0000001b, ++ 0x80000000, ++ 0x0000001b, ++ 0x90000000, ++ 0x0000001b, ++ 0xa0000000, ++ 0x0000001b, ++ 0xb0000000, ++ 0x0000001b, ++ 0xc0000000, ++ 0x0000001b, ++ 0xd0000000, ++ 0x0000001b, ++ 0xe0000000, ++ 0x0000001b, ++ 0xf0000000, ++ 0x0000001b, ++ 0x00000000, ++ 0x0000001c, ++ 0x10000000, ++ 0x0000001c, ++ 0x20000000, ++ 0x0000001c, ++ 0x30000000, ++ 0x0000001c, ++ 0x40000000, ++ 0x0000001c, ++ 0x50000000, ++ 0x0000001c, ++ 0x60000000, ++ 0x0000001c, ++ 0x70000000, ++ 0x0000001c, ++ 0x80000000, ++ 0x0000001c, ++ 0x90000000, ++ 0x0000001c, ++}; ++ ++static const u16 dot11lcn_aux_gain_idx_tbl_2G[] = { ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0001, ++ 0x0080, ++ 0x0081, ++ 0x0100, ++ 0x0101, ++ 0x0180, ++ 0x0181, ++ 0x0182, ++ 0x0183, ++ 0x0184, ++ 0x0185, ++ 0x0186, ++ 0x0187, ++ 0x0188, ++ 0x0285, ++ 0x0289, ++ 0x028a, ++ 0x028b, ++ 0x028c, ++ 0x028d, ++ 0x028e, ++ 0x028f, ++ 0x0290, ++ 0x0291, ++ 0x0292, ++ 0x0293, ++ 0x0294, ++ 0x0295, ++ 0x0296, ++ 0x0297, ++ 0x0298, ++ 0x0299, ++ 0x029a, ++ 0x0000 ++}; ++ ++static const u8 dot11lcn_gain_val_tbl_2G[] = { ++ 0xfc, ++ 0x02, ++ 0x08, ++ 0x0e, ++ 0x13, ++ 0x1b, ++ 0xfc, ++ 0x02, ++ 0x08, ++ 0x0e, ++ 0x13, ++ 0x1b, ++ 0xfc, ++ 0x00, ++ 0x0c, ++ 0x03, ++ 0xeb, ++ 0xfe, ++ 0x07, ++ 0x0b, ++ 0x0f, ++ 0xfb, ++ 0xfe, ++ 0x01, ++ 0x05, ++ 0x08, ++ 0x0b, ++ 0x0e, ++ 0x11, ++ 0x14, ++ 0x17, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x15, ++ 0x18, ++ 0x1b, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00 ++}; ++ ++static const u32 dot11lcn_gain_idx_tbl_2G[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x10000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000008, ++ 0x10000000, ++ 0x00000008, ++ 0x00000000, ++ 0x00000010, ++ 0x10000000, ++ 0x00000010, ++ 0x00000000, ++ 0x00000018, ++ 0x10000000, ++ 0x00000018, ++ 0x20000000, ++ 0x00000018, ++ 0x30000000, ++ 0x00000018, ++ 0x40000000, ++ 0x00000018, ++ 0x50000000, ++ 0x00000018, ++ 0x60000000, ++ 0x00000018, ++ 0x70000000, ++ 0x00000018, ++ 0x80000000, ++ 0x00000018, ++ 0x50000000, ++ 0x00000028, ++ 0x90000000, ++ 0x00000028, ++ 0xa0000000, ++ 0x00000028, ++ 0xb0000000, ++ 0x00000028, ++ 0xc0000000, ++ 0x00000028, ++ 0xd0000000, ++ 0x00000028, ++ 0xe0000000, ++ 0x00000028, ++ 0xf0000000, ++ 0x00000028, ++ 0x00000000, ++ 0x00000029, ++ 0x10000000, ++ 0x00000029, ++ 0x20000000, ++ 0x00000029, ++ 0x30000000, ++ 0x00000029, ++ 0x40000000, ++ 0x00000029, ++ 0x50000000, ++ 0x00000029, ++ 0x60000000, ++ 0x00000029, ++ 0x70000000, ++ 0x00000029, ++ 0x80000000, ++ 0x00000029, ++ 0x90000000, ++ 0x00000029, ++ 0xa0000000, ++ 0x00000029, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x10000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000008, ++ 0x10000000, ++ 0x00000008, ++ 0x00000000, ++ 0x00000010, ++ 0x10000000, ++ 0x00000010, ++ 0x00000000, ++ 0x00000018, ++ 0x10000000, ++ 0x00000018, ++ 0x20000000, ++ 0x00000018, ++ 0x30000000, ++ 0x00000018, ++ 0x40000000, ++ 0x00000018, ++ 0x50000000, ++ 0x00000018, ++ 0x60000000, ++ 0x00000018, ++ 0x70000000, ++ 0x00000018, ++ 0x80000000, ++ 0x00000018, ++ 0x50000000, ++ 0x00000028, ++ 0x90000000, ++ 0x00000028, ++ 0xa0000000, ++ 0x00000028, ++ 0xb0000000, ++ 0x00000028, ++ 0xc0000000, ++ 0x00000028, ++ 0xd0000000, ++ 0x00000028, ++ 0xe0000000, ++ 0x00000028, ++ 0xf0000000, ++ 0x00000028, ++ 0x00000000, ++ 0x00000029, ++ 0x10000000, ++ 0x00000029, ++ 0x20000000, ++ 0x00000029, ++ 0x30000000, ++ 0x00000029, ++ 0x40000000, ++ 0x00000029, ++ 0x50000000, ++ 0x00000029, ++ 0x60000000, ++ 0x00000029, ++ 0x70000000, ++ 0x00000029, ++ 0x80000000, ++ 0x00000029, ++ 0x90000000, ++ 0x00000029, ++ 0xa0000000, ++ 0x00000029, ++ 0xb0000000, ++ 0x00000029, ++ 0xc0000000, ++ 0x00000029, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000 ++}; ++ ++static const u32 dot11lcn_gain_tbl_2G[] = { ++ 0x00000000, ++ 0x00000004, ++ 0x00000008, ++ 0x00000001, ++ 0x00000005, ++ 0x00000009, ++ 0x0000000d, ++ 0x0000004d, ++ 0x0000008d, ++ 0x00000049, ++ 0x00000089, ++ 0x000000c9, ++ 0x0000004b, ++ 0x0000008b, ++ 0x000000cb, ++ 0x000000cf, ++ 0x0000010f, ++ 0x0000050f, ++ 0x0000090f, ++ 0x0000094f, ++ 0x00000d4f, ++ 0x0000114f, ++ 0x0000118f, ++ 0x0000518f, ++ 0x0000918f, ++ 0x0000d18f, ++ 0x0001118f, ++ 0x0001518f, ++ 0x0001918f, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000 ++}; ++ ++static const u32 dot11lcn_gain_tbl_extlna_2G[] = { ++ 0x00000000, ++ 0x00000004, ++ 0x00000008, ++ 0x00000001, ++ 0x00000005, ++ 0x00000009, ++ 0x0000000d, ++ 0x00000003, ++ 0x00000007, ++ 0x0000000b, ++ 0x0000000f, ++ 0x0000004f, ++ 0x0000008f, ++ 0x000000cf, ++ 0x0000010f, ++ 0x0000014f, ++ 0x0000018f, ++ 0x0000058f, ++ 0x0000098f, ++ 0x00000d8f, ++ 0x00008000, ++ 0x00008004, ++ 0x00008008, ++ 0x00008001, ++ 0x00008005, ++ 0x00008009, ++ 0x0000800d, ++ 0x00008003, ++ 0x00008007, ++ 0x0000800b, ++ 0x0000800f, ++ 0x0000804f, ++ 0x0000808f, ++ 0x000080cf, ++ 0x0000810f, ++ 0x0000814f, ++ 0x0000818f, ++ 0x0000858f, ++ 0x0000898f, ++ 0x00008d8f, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000 ++}; ++ ++static const u16 dot11lcn_aux_gain_idx_tbl_extlna_2G[] = { ++ 0x0400, ++ 0x0400, ++ 0x0400, ++ 0x0400, ++ 0x0400, ++ 0x0400, ++ 0x0400, ++ 0x0400, ++ 0x0400, ++ 0x0401, ++ 0x0402, ++ 0x0403, ++ 0x0404, ++ 0x0483, ++ 0x0484, ++ 0x0485, ++ 0x0486, ++ 0x0583, ++ 0x0584, ++ 0x0585, ++ 0x0587, ++ 0x0588, ++ 0x0589, ++ 0x058a, ++ 0x0687, ++ 0x0688, ++ 0x0689, ++ 0x068a, ++ 0x068b, ++ 0x068c, ++ 0x068d, ++ 0x068e, ++ 0x068f, ++ 0x0690, ++ 0x0691, ++ 0x0692, ++ 0x0693, ++ 0x0000 ++}; ++ ++static const u8 dot11lcn_gain_val_tbl_extlna_2G[] = { ++ 0xfc, ++ 0x02, ++ 0x08, ++ 0x0e, ++ 0x13, ++ 0x1b, ++ 0xfc, ++ 0x02, ++ 0x08, ++ 0x0e, ++ 0x13, ++ 0x1b, ++ 0xfc, ++ 0x00, ++ 0x0f, ++ 0x03, ++ 0xeb, ++ 0xfe, ++ 0x07, ++ 0x0b, ++ 0x0f, ++ 0xfb, ++ 0xfe, ++ 0x01, ++ 0x05, ++ 0x08, ++ 0x0b, ++ 0x0e, ++ 0x11, ++ 0x14, ++ 0x17, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x15, ++ 0x18, ++ 0x1b, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00 ++}; ++ ++static const u32 dot11lcn_gain_idx_tbl_extlna_2G[] = { ++ 0x00000000, ++ 0x00000040, ++ 0x00000000, ++ 0x00000040, ++ 0x00000000, ++ 0x00000040, ++ 0x00000000, ++ 0x00000040, ++ 0x00000000, ++ 0x00000040, ++ 0x00000000, ++ 0x00000040, ++ 0x00000000, ++ 0x00000040, ++ 0x00000000, ++ 0x00000040, ++ 0x00000000, ++ 0x00000040, ++ 0x10000000, ++ 0x00000040, ++ 0x20000000, ++ 0x00000040, ++ 0x30000000, ++ 0x00000040, ++ 0x40000000, ++ 0x00000040, ++ 0x30000000, ++ 0x00000048, ++ 0x40000000, ++ 0x00000048, ++ 0x50000000, ++ 0x00000048, ++ 0x60000000, ++ 0x00000048, ++ 0x30000000, ++ 0x00000058, ++ 0x40000000, ++ 0x00000058, ++ 0x50000000, ++ 0x00000058, ++ 0x70000000, ++ 0x00000058, ++ 0x80000000, ++ 0x00000058, ++ 0x90000000, ++ 0x00000058, ++ 0xa0000000, ++ 0x00000058, ++ 0x70000000, ++ 0x00000068, ++ 0x80000000, ++ 0x00000068, ++ 0x90000000, ++ 0x00000068, ++ 0xa0000000, ++ 0x00000068, ++ 0xb0000000, ++ 0x00000068, ++ 0xc0000000, ++ 0x00000068, ++ 0xd0000000, ++ 0x00000068, ++ 0xe0000000, ++ 0x00000068, ++ 0xf0000000, ++ 0x00000068, ++ 0x00000000, ++ 0x00000069, ++ 0x10000000, ++ 0x00000069, ++ 0x20000000, ++ 0x00000069, ++ 0x30000000, ++ 0x00000069, ++ 0x40000000, ++ 0x00000041, ++ 0x40000000, ++ 0x00000041, ++ 0x40000000, ++ 0x00000041, ++ 0x40000000, ++ 0x00000041, ++ 0x40000000, ++ 0x00000041, ++ 0x40000000, ++ 0x00000041, ++ 0x40000000, ++ 0x00000041, ++ 0x40000000, ++ 0x00000041, ++ 0x40000000, ++ 0x00000041, ++ 0x50000000, ++ 0x00000041, ++ 0x60000000, ++ 0x00000041, ++ 0x70000000, ++ 0x00000041, ++ 0x80000000, ++ 0x00000041, ++ 0x70000000, ++ 0x00000049, ++ 0x80000000, ++ 0x00000049, ++ 0x90000000, ++ 0x00000049, ++ 0xa0000000, ++ 0x00000049, ++ 0x70000000, ++ 0x00000059, ++ 0x80000000, ++ 0x00000059, ++ 0x90000000, ++ 0x00000059, ++ 0xb0000000, ++ 0x00000059, ++ 0xc0000000, ++ 0x00000059, ++ 0xd0000000, ++ 0x00000059, ++ 0xe0000000, ++ 0x00000059, ++ 0xb0000000, ++ 0x00000069, ++ 0xc0000000, ++ 0x00000069, ++ 0xd0000000, ++ 0x00000069, ++ 0xe0000000, ++ 0x00000069, ++ 0xf0000000, ++ 0x00000069, ++ 0x00000000, ++ 0x0000006a, ++ 0x10000000, ++ 0x0000006a, ++ 0x20000000, ++ 0x0000006a, ++ 0x30000000, ++ 0x0000006a, ++ 0x40000000, ++ 0x0000006a, ++ 0x50000000, ++ 0x0000006a, ++ 0x60000000, ++ 0x0000006a, ++ 0x70000000, ++ 0x0000006a, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000 ++}; ++ ++static const u32 dot11lcn_aux_gain_idx_tbl_5G[] = { ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0001, ++ 0x0002, ++ 0x0003, ++ 0x0004, ++ 0x0083, ++ 0x0084, ++ 0x0085, ++ 0x0086, ++ 0x0087, ++ 0x0186, ++ 0x0187, ++ 0x0188, ++ 0x0189, ++ 0x018a, ++ 0x018b, ++ 0x018c, ++ 0x018d, ++ 0x018e, ++ 0x018f, ++ 0x0190, ++ 0x0191, ++ 0x0192, ++ 0x0193, ++ 0x0194, ++ 0x0195, ++ 0x0196, ++ 0x0197, ++ 0x0198, ++ 0x0199, ++ 0x019a, ++ 0x019b, ++ 0x019c, ++ 0x019d, ++ 0x0000 ++}; ++ ++static const u32 dot11lcn_gain_val_tbl_5G[] = { ++ 0xf7, ++ 0xfd, ++ 0x00, ++ 0x04, ++ 0x04, ++ 0x04, ++ 0xf7, ++ 0xfd, ++ 0x00, ++ 0x04, ++ 0x04, ++ 0x04, ++ 0xf6, ++ 0x00, ++ 0x0c, ++ 0x03, ++ 0xeb, ++ 0xfe, ++ 0x06, ++ 0x0a, ++ 0x10, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x15, ++ 0x18, ++ 0x1b, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x15, ++ 0x18, ++ 0x1b, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00 ++}; ++ ++static const u32 dot11lcn_gain_idx_tbl_5G[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x10000000, ++ 0x00000000, ++ 0x20000000, ++ 0x00000000, ++ 0x30000000, ++ 0x00000000, ++ 0x40000000, ++ 0x00000000, ++ 0x30000000, ++ 0x00000008, ++ 0x40000000, ++ 0x00000008, ++ 0x50000000, ++ 0x00000008, ++ 0x60000000, ++ 0x00000008, ++ 0x70000000, ++ 0x00000008, ++ 0x60000000, ++ 0x00000018, ++ 0x70000000, ++ 0x00000018, ++ 0x80000000, ++ 0x00000018, ++ 0x90000000, ++ 0x00000018, ++ 0xa0000000, ++ 0x00000018, ++ 0xb0000000, ++ 0x00000018, ++ 0xc0000000, ++ 0x00000018, ++ 0xd0000000, ++ 0x00000018, ++ 0xe0000000, ++ 0x00000018, ++ 0xf0000000, ++ 0x00000018, ++ 0x00000000, ++ 0x00000019, ++ 0x10000000, ++ 0x00000019, ++ 0x20000000, ++ 0x00000019, ++ 0x30000000, ++ 0x00000019, ++ 0x40000000, ++ 0x00000019, ++ 0x50000000, ++ 0x00000019, ++ 0x60000000, ++ 0x00000019, ++ 0x70000000, ++ 0x00000019, ++ 0x80000000, ++ 0x00000019, ++ 0x90000000, ++ 0x00000019, ++ 0xa0000000, ++ 0x00000019, ++ 0xb0000000, ++ 0x00000019, ++ 0xc0000000, ++ 0x00000019, ++ 0xd0000000, ++ 0x00000019, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000 ++}; ++ ++static const u32 dot11lcn_gain_tbl_5G[] = { ++ 0x00000000, ++ 0x00000040, ++ 0x00000080, ++ 0x00000001, ++ 0x00000005, ++ 0x00000009, ++ 0x0000000d, ++ 0x00000011, ++ 0x00000015, ++ 0x00000055, ++ 0x00000095, ++ 0x00000017, ++ 0x0000001b, ++ 0x0000005b, ++ 0x0000009b, ++ 0x000000db, ++ 0x0000011b, ++ 0x0000015b, ++ 0x0000019b, ++ 0x0000059b, ++ 0x0000099b, ++ 0x00000d9b, ++ 0x0000119b, ++ 0x0000519b, ++ 0x0000919b, ++ 0x0000d19b, ++ 0x0001119b, ++ 0x0001519b, ++ 0x0001919b, ++ 0x0001d19b, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000 ++}; ++ ++const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev0[] = { ++ {&dot11lcn_gain_tbl_rev0, ++ sizeof(dot11lcn_gain_tbl_rev0) / sizeof(dot11lcn_gain_tbl_rev0[0]), 18, ++ 0, 32} ++ , ++ {&dot11lcn_aux_gain_idx_tbl_rev0, ++ sizeof(dot11lcn_aux_gain_idx_tbl_rev0) / ++ sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16} ++ , ++ {&dot11lcn_gain_idx_tbl_rev0, ++ sizeof(dot11lcn_gain_idx_tbl_rev0) / ++ sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32} ++ , ++}; ++ ++static const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev1[] = { ++ {&dot11lcn_gain_tbl_rev1, ++ sizeof(dot11lcn_gain_tbl_rev1) / sizeof(dot11lcn_gain_tbl_rev1[0]), 18, ++ 0, 32} ++ , ++ {&dot11lcn_aux_gain_idx_tbl_rev0, ++ sizeof(dot11lcn_aux_gain_idx_tbl_rev0) / ++ sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16} ++ , ++ {&dot11lcn_gain_idx_tbl_rev0, ++ sizeof(dot11lcn_gain_idx_tbl_rev0) / ++ sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32} ++ , ++}; ++ ++const struct phytbl_info dot11lcnphytbl_rx_gain_info_2G_rev2[] = { ++ {&dot11lcn_gain_tbl_2G, ++ sizeof(dot11lcn_gain_tbl_2G) / sizeof(dot11lcn_gain_tbl_2G[0]), 18, 0, ++ 32} ++ , ++ {&dot11lcn_aux_gain_idx_tbl_2G, ++ sizeof(dot11lcn_aux_gain_idx_tbl_2G) / ++ sizeof(dot11lcn_aux_gain_idx_tbl_2G[0]), 14, 0, 16} ++ , ++ {&dot11lcn_gain_idx_tbl_2G, ++ sizeof(dot11lcn_gain_idx_tbl_2G) / sizeof(dot11lcn_gain_idx_tbl_2G[0]), ++ 13, 0, 32} ++ , ++ {&dot11lcn_gain_val_tbl_2G, ++ sizeof(dot11lcn_gain_val_tbl_2G) / sizeof(dot11lcn_gain_val_tbl_2G[0]), ++ 17, 0, 8} ++}; ++ ++const struct phytbl_info dot11lcnphytbl_rx_gain_info_5G_rev2[] = { ++ {&dot11lcn_gain_tbl_5G, ++ sizeof(dot11lcn_gain_tbl_5G) / sizeof(dot11lcn_gain_tbl_5G[0]), 18, 0, ++ 32} ++ , ++ {&dot11lcn_aux_gain_idx_tbl_5G, ++ sizeof(dot11lcn_aux_gain_idx_tbl_5G) / ++ sizeof(dot11lcn_aux_gain_idx_tbl_5G[0]), 14, 0, 16} ++ , ++ {&dot11lcn_gain_idx_tbl_5G, ++ sizeof(dot11lcn_gain_idx_tbl_5G) / sizeof(dot11lcn_gain_idx_tbl_5G[0]), ++ 13, 0, 32} ++ , ++ {&dot11lcn_gain_val_tbl_5G, ++ sizeof(dot11lcn_gain_val_tbl_5G) / sizeof(dot11lcn_gain_val_tbl_5G[0]), ++ 17, 0, 8} ++}; ++ ++const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[] = { ++ {&dot11lcn_gain_tbl_extlna_2G, ++ sizeof(dot11lcn_gain_tbl_extlna_2G) / ++ sizeof(dot11lcn_gain_tbl_extlna_2G[0]), 18, 0, 32} ++ , ++ {&dot11lcn_aux_gain_idx_tbl_extlna_2G, ++ sizeof(dot11lcn_aux_gain_idx_tbl_extlna_2G) / ++ sizeof(dot11lcn_aux_gain_idx_tbl_extlna_2G[0]), 14, 0, 16} ++ , ++ {&dot11lcn_gain_idx_tbl_extlna_2G, ++ sizeof(dot11lcn_gain_idx_tbl_extlna_2G) / ++ sizeof(dot11lcn_gain_idx_tbl_extlna_2G[0]), 13, 0, 32} ++ , ++ {&dot11lcn_gain_val_tbl_extlna_2G, ++ sizeof(dot11lcn_gain_val_tbl_extlna_2G) / ++ sizeof(dot11lcn_gain_val_tbl_extlna_2G[0]), 17, 0, 8} ++}; ++ ++const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[] = { ++ {&dot11lcn_gain_tbl_5G, ++ sizeof(dot11lcn_gain_tbl_5G) / sizeof(dot11lcn_gain_tbl_5G[0]), 18, 0, ++ 32} ++ , ++ {&dot11lcn_aux_gain_idx_tbl_5G, ++ sizeof(dot11lcn_aux_gain_idx_tbl_5G) / ++ sizeof(dot11lcn_aux_gain_idx_tbl_5G[0]), 14, 0, 16} ++ , ++ {&dot11lcn_gain_idx_tbl_5G, ++ sizeof(dot11lcn_gain_idx_tbl_5G) / sizeof(dot11lcn_gain_idx_tbl_5G[0]), ++ 13, 0, 32} ++ , ++ {&dot11lcn_gain_val_tbl_5G, ++ sizeof(dot11lcn_gain_val_tbl_5G) / sizeof(dot11lcn_gain_val_tbl_5G[0]), ++ 17, 0, 8} ++}; ++ ++const u32 dot11lcnphytbl_rx_gain_info_sz_rev0 = ++ sizeof(dot11lcnphytbl_rx_gain_info_rev0) / ++ sizeof(dot11lcnphytbl_rx_gain_info_rev0[0]); ++ ++const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz = ++ sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2) / ++ sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2[0]); ++ ++const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz = ++ sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2) / ++ sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2[0]); ++ ++static const u16 dot11lcn_min_sig_sq_tbl_rev0[] = { ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++}; ++ ++static const u16 dot11lcn_noise_scale_tbl_rev0[] = { ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++}; ++ ++static const u32 dot11lcn_fltr_ctrl_tbl_rev0[] = { ++ 0x000141f8, ++ 0x000021f8, ++ 0x000021fb, ++ 0x000041fb, ++ 0x0001fe4b, ++ 0x0000217b, ++ 0x00002133, ++ 0x000040eb, ++ 0x0001fea3, ++ 0x0000024b, ++}; ++ ++static const u32 dot11lcn_ps_ctrl_tbl_rev0[] = { ++ 0x00100001, ++ 0x00200010, ++ 0x00300001, ++ 0x00400010, ++ 0x00500022, ++ 0x00600122, ++ 0x00700222, ++ 0x00800322, ++ 0x00900422, ++ 0x00a00522, ++ 0x00b00622, ++ 0x00c00722, ++ 0x00d00822, ++ 0x00f00922, ++ 0x00100a22, ++ 0x00200b22, ++ 0x00300c22, ++ 0x00400d22, ++ 0x00500e22, ++ 0x00600f22, ++}; ++ ++static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[] = { ++ 0x0007, ++ 0x0005, ++ 0x0006, ++ 0x0004, ++ 0x0007, ++ 0x0005, ++ 0x0006, ++ 0x0004, ++ 0x0007, ++ 0x0005, ++ 0x0006, ++ 0x0004, ++ 0x0007, ++ 0x0005, ++ 0x0006, ++ 0x0004, ++ 0x000b, ++ 0x000b, ++ 0x000a, ++ 0x000a, ++ 0x000b, ++ 0x000b, ++ 0x000a, ++ 0x000a, ++ 0x000b, ++ 0x000b, ++ 0x000a, ++ 0x000a, ++ 0x000b, ++ 0x000b, ++ 0x000a, ++ 0x000a, ++ 0x0007, ++ 0x0005, ++ 0x0006, ++ 0x0004, ++ 0x0007, ++ 0x0005, ++ 0x0006, ++ 0x0004, ++ 0x0007, ++ 0x0005, ++ 0x0006, ++ 0x0004, ++ 0x0007, ++ 0x0005, ++ 0x0006, ++ 0x0004, ++ 0x000b, ++ 0x000b, ++ 0x000a, ++ 0x000a, ++ 0x000b, ++ 0x000b, ++ 0x000a, ++ 0x000a, ++ 0x000b, ++ 0x000b, ++ 0x000a, ++ 0x000a, ++ 0x000b, ++ 0x000b, ++ 0x000a, ++ 0x000a, ++ ++}; ++ ++static const u16 dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[] = { ++ 0x0007, ++ 0x0005, ++ 0x0002, ++ 0x0000, ++ 0x0007, ++ 0x0005, ++ 0x0002, ++ 0x0000, ++ 0x0007, ++ 0x0005, ++ 0x0002, ++ 0x0000, ++ 0x0007, ++ 0x0005, ++ 0x0002, ++ 0x0000, ++ 0x0007, ++ 0x0007, ++ 0x0002, ++ 0x0002, ++ 0x0007, ++ 0x0007, ++ 0x0002, ++ 0x0002, ++ 0x0007, ++ 0x0007, ++ 0x0002, ++ 0x0002, ++ 0x0007, ++ 0x0007, ++ 0x0002, ++ 0x0002, ++ 0x0007, ++ 0x0005, ++ 0x0002, ++ 0x0000, ++ 0x0007, ++ 0x0005, ++ 0x0002, ++ 0x0000, ++ 0x0007, ++ 0x0005, ++ 0x0002, ++ 0x0000, ++ 0x0007, ++ 0x0005, ++ 0x0002, ++ 0x0000, ++ 0x0007, ++ 0x0007, ++ 0x0002, ++ 0x0002, ++ 0x0007, ++ 0x0007, ++ 0x0002, ++ 0x0002, ++ 0x0007, ++ 0x0007, ++ 0x0002, ++ 0x0002, ++ 0x0007, ++ 0x0007, ++ 0x0002, ++ 0x0002, ++}; ++ ++static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = { ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++}; ++ ++static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = { ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++}; ++ ++static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = { ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++}; ++ ++static const u8 dot11lcn_nf_table_rev0[] = { ++ 0x5f, ++ 0x36, ++ 0x29, ++ 0x1f, ++ 0x5f, ++ 0x36, ++ 0x29, ++ 0x1f, ++ 0x5f, ++ 0x36, ++ 0x29, ++ 0x1f, ++ 0x5f, ++ 0x36, ++ 0x29, ++ 0x1f, ++}; ++ ++static const u8 dot11lcn_gain_val_tbl_rev0[] = { ++ 0x09, ++ 0x0f, ++ 0x14, ++ 0x18, ++ 0xfe, ++ 0x07, ++ 0x0b, ++ 0x0f, ++ 0xfb, ++ 0xfe, ++ 0x01, ++ 0x05, ++ 0x08, ++ 0x0b, ++ 0x0e, ++ 0x11, ++ 0x14, ++ 0x17, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x15, ++ 0x18, ++ 0x1b, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0xeb, ++ 0x00, ++ 0x00, ++}; ++ ++static const u8 dot11lcn_spur_tbl_rev0[] = { ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x02, ++ 0x03, ++ 0x01, ++ 0x03, ++ 0x02, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x02, ++ 0x03, ++ 0x01, ++ 0x03, ++ 0x02, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++}; ++ ++static const u16 dot11lcn_unsup_mcs_tbl_rev0[] = { ++ 0x001a, ++ 0x0034, ++ 0x004e, ++ 0x0068, ++ 0x009c, ++ 0x00d0, ++ 0x00ea, ++ 0x0104, ++ 0x0034, ++ 0x0068, ++ 0x009c, ++ 0x00d0, ++ 0x0138, ++ 0x01a0, ++ 0x01d4, ++ 0x0208, ++ 0x004e, ++ 0x009c, ++ 0x00ea, ++ 0x0138, ++ 0x01d4, ++ 0x0270, ++ 0x02be, ++ 0x030c, ++ 0x0068, ++ 0x00d0, ++ 0x0138, ++ 0x01a0, ++ 0x0270, ++ 0x0340, ++ 0x03a8, ++ 0x0410, ++ 0x0018, ++ 0x009c, ++ 0x00d0, ++ 0x0104, ++ 0x00ea, ++ 0x0138, ++ 0x0186, ++ 0x00d0, ++ 0x0104, ++ 0x0104, ++ 0x0138, ++ 0x016c, ++ 0x016c, ++ 0x01a0, ++ 0x0138, ++ 0x0186, ++ 0x0186, ++ 0x01d4, ++ 0x0222, ++ 0x0222, ++ 0x0270, ++ 0x0104, ++ 0x0138, ++ 0x016c, ++ 0x0138, ++ 0x016c, ++ 0x01a0, ++ 0x01d4, ++ 0x01a0, ++ 0x01d4, ++ 0x0208, ++ 0x0208, ++ 0x023c, ++ 0x0186, ++ 0x01d4, ++ 0x0222, ++ 0x01d4, ++ 0x0222, ++ 0x0270, ++ 0x02be, ++ 0x0270, ++ 0x02be, ++ 0x030c, ++ 0x030c, ++ 0x035a, ++ 0x0036, ++ 0x006c, ++ 0x00a2, ++ 0x00d8, ++ 0x0144, ++ 0x01b0, ++ 0x01e6, ++ 0x021c, ++ 0x006c, ++ 0x00d8, ++ 0x0144, ++ 0x01b0, ++ 0x0288, ++ 0x0360, ++ 0x03cc, ++ 0x0438, ++ 0x00a2, ++ 0x0144, ++ 0x01e6, ++ 0x0288, ++ 0x03cc, ++ 0x0510, ++ 0x05b2, ++ 0x0654, ++ 0x00d8, ++ 0x01b0, ++ 0x0288, ++ 0x0360, ++ 0x0510, ++ 0x06c0, ++ 0x0798, ++ 0x0870, ++ 0x0018, ++ 0x0144, ++ 0x01b0, ++ 0x021c, ++ 0x01e6, ++ 0x0288, ++ 0x032a, ++ 0x01b0, ++ 0x021c, ++ 0x021c, ++ 0x0288, ++ 0x02f4, ++ 0x02f4, ++ 0x0360, ++ 0x0288, ++ 0x032a, ++ 0x032a, ++ 0x03cc, ++ 0x046e, ++ 0x046e, ++ 0x0510, ++ 0x021c, ++ 0x0288, ++ 0x02f4, ++ 0x0288, ++ 0x02f4, ++ 0x0360, ++ 0x03cc, ++ 0x0360, ++ 0x03cc, ++ 0x0438, ++ 0x0438, ++ 0x04a4, ++ 0x032a, ++ 0x03cc, ++ 0x046e, ++ 0x03cc, ++ 0x046e, ++ 0x0510, ++ 0x05b2, ++ 0x0510, ++ 0x05b2, ++ 0x0654, ++ 0x0654, ++ 0x06f6, ++}; ++ ++static const u16 dot11lcn_iq_local_tbl_rev0[] = { ++ 0x0200, ++ 0x0300, ++ 0x0400, ++ 0x0600, ++ 0x0800, ++ 0x0b00, ++ 0x1000, ++ 0x1001, ++ 0x1002, ++ 0x1003, ++ 0x1004, ++ 0x1005, ++ 0x1006, ++ 0x1007, ++ 0x1707, ++ 0x2007, ++ 0x2d07, ++ 0x4007, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0200, ++ 0x0300, ++ 0x0400, ++ 0x0600, ++ 0x0800, ++ 0x0b00, ++ 0x1000, ++ 0x1001, ++ 0x1002, ++ 0x1003, ++ 0x1004, ++ 0x1005, ++ 0x1006, ++ 0x1007, ++ 0x1707, ++ 0x2007, ++ 0x2d07, ++ 0x4007, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x4000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++}; ++ ++static const u32 dot11lcn_papd_compdelta_tbl_rev0[] = { ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++}; ++ ++const struct phytbl_info dot11lcnphytbl_info_rev0[] = { ++ {&dot11lcn_min_sig_sq_tbl_rev0, ++ sizeof(dot11lcn_min_sig_sq_tbl_rev0) / ++ sizeof(dot11lcn_min_sig_sq_tbl_rev0[0]), 2, 0, 16} ++ , ++ {&dot11lcn_noise_scale_tbl_rev0, ++ sizeof(dot11lcn_noise_scale_tbl_rev0) / ++ sizeof(dot11lcn_noise_scale_tbl_rev0[0]), 1, 0, 16} ++ , ++ {&dot11lcn_fltr_ctrl_tbl_rev0, ++ sizeof(dot11lcn_fltr_ctrl_tbl_rev0) / ++ sizeof(dot11lcn_fltr_ctrl_tbl_rev0[0]), 11, 0, 32} ++ , ++ {&dot11lcn_ps_ctrl_tbl_rev0, ++ sizeof(dot11lcn_ps_ctrl_tbl_rev0) / ++ sizeof(dot11lcn_ps_ctrl_tbl_rev0[0]), 12, 0, 32} ++ , ++ {&dot11lcn_gain_idx_tbl_rev0, ++ sizeof(dot11lcn_gain_idx_tbl_rev0) / ++ sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32} ++ , ++ {&dot11lcn_aux_gain_idx_tbl_rev0, ++ sizeof(dot11lcn_aux_gain_idx_tbl_rev0) / ++ sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16} ++ , ++ {&dot11lcn_sw_ctrl_tbl_rev0, ++ sizeof(dot11lcn_sw_ctrl_tbl_rev0) / ++ sizeof(dot11lcn_sw_ctrl_tbl_rev0[0]), 15, 0, 16} ++ , ++ {&dot11lcn_nf_table_rev0, ++ sizeof(dot11lcn_nf_table_rev0) / sizeof(dot11lcn_nf_table_rev0[0]), 16, ++ 0, 8} ++ , ++ {&dot11lcn_gain_val_tbl_rev0, ++ sizeof(dot11lcn_gain_val_tbl_rev0) / ++ sizeof(dot11lcn_gain_val_tbl_rev0[0]), 17, 0, 8} ++ , ++ {&dot11lcn_gain_tbl_rev0, ++ sizeof(dot11lcn_gain_tbl_rev0) / sizeof(dot11lcn_gain_tbl_rev0[0]), 18, ++ 0, 32} ++ , ++ {&dot11lcn_spur_tbl_rev0, ++ sizeof(dot11lcn_spur_tbl_rev0) / sizeof(dot11lcn_spur_tbl_rev0[0]), 20, ++ 0, 8} ++ , ++ {&dot11lcn_unsup_mcs_tbl_rev0, ++ sizeof(dot11lcn_unsup_mcs_tbl_rev0) / ++ sizeof(dot11lcn_unsup_mcs_tbl_rev0[0]), 23, 0, 16} ++ , ++ {&dot11lcn_iq_local_tbl_rev0, ++ sizeof(dot11lcn_iq_local_tbl_rev0) / ++ sizeof(dot11lcn_iq_local_tbl_rev0[0]), 0, 0, 16} ++ , ++ {&dot11lcn_papd_compdelta_tbl_rev0, ++ sizeof(dot11lcn_papd_compdelta_tbl_rev0) / ++ sizeof(dot11lcn_papd_compdelta_tbl_rev0[0]), 24, 0, 32} ++ , ++}; ++ ++const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313 = { ++ &dot11lcn_sw_ctrl_tbl_4313_rev0, ++ sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0) / ++ sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0[0]), 15, 0, 16 ++}; ++ ++const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa = { ++ &dot11lcn_sw_ctrl_tbl_4313_epa_rev0, ++ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0) / ++ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0[0]), 15, 0, 16 ++}; ++ ++const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa = { ++ &dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo, ++ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo) / ++ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[0]), 15, 0, 16 ++}; ++ ++const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250 = { ++ &dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0, ++ sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0) / ++ sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[0]), 15, 0, 16 ++}; ++ ++const u32 dot11lcnphytbl_info_sz_rev0 = ++ sizeof(dot11lcnphytbl_info_rev0) / sizeof(dot11lcnphytbl_info_rev0[0]); ++ ++const struct lcnphy_tx_gain_tbl_entry ++dot11lcnphy_2GHz_extPA_gaintable_rev0[128] = { ++ {3, 0, 31, 0, 72}, ++ {3, 0, 31, 0, 70}, ++ {3, 0, 31, 0, 68}, ++ {3, 0, 30, 0, 67}, ++ {3, 0, 29, 0, 68}, ++ {3, 0, 28, 0, 68}, ++ {3, 0, 27, 0, 69}, ++ {3, 0, 26, 0, 70}, ++ {3, 0, 25, 0, 70}, ++ {3, 0, 24, 0, 71}, ++ {3, 0, 23, 0, 72}, ++ {3, 0, 23, 0, 70}, ++ {3, 0, 22, 0, 71}, ++ {3, 0, 21, 0, 72}, ++ {3, 0, 21, 0, 70}, ++ {3, 0, 21, 0, 68}, ++ {3, 0, 21, 0, 66}, ++ {3, 0, 21, 0, 64}, ++ {3, 0, 21, 0, 63}, ++ {3, 0, 20, 0, 64}, ++ {3, 0, 19, 0, 65}, ++ {3, 0, 19, 0, 64}, ++ {3, 0, 18, 0, 65}, ++ {3, 0, 18, 0, 64}, ++ {3, 0, 17, 0, 65}, ++ {3, 0, 17, 0, 64}, ++ {3, 0, 16, 0, 65}, ++ {3, 0, 16, 0, 64}, ++ {3, 0, 16, 0, 62}, ++ {3, 0, 16, 0, 60}, ++ {3, 0, 16, 0, 58}, ++ {3, 0, 15, 0, 61}, ++ {3, 0, 15, 0, 59}, ++ {3, 0, 14, 0, 61}, ++ {3, 0, 14, 0, 60}, ++ {3, 0, 14, 0, 58}, ++ {3, 0, 13, 0, 60}, ++ {3, 0, 13, 0, 59}, ++ {3, 0, 12, 0, 62}, ++ {3, 0, 12, 0, 60}, ++ {3, 0, 12, 0, 58}, ++ {3, 0, 11, 0, 62}, ++ {3, 0, 11, 0, 60}, ++ {3, 0, 11, 0, 59}, ++ {3, 0, 11, 0, 57}, ++ {3, 0, 10, 0, 61}, ++ {3, 0, 10, 0, 59}, ++ {3, 0, 10, 0, 57}, ++ {3, 0, 9, 0, 62}, ++ {3, 0, 9, 0, 60}, ++ {3, 0, 9, 0, 58}, ++ {3, 0, 9, 0, 57}, ++ {3, 0, 8, 0, 62}, ++ {3, 0, 8, 0, 60}, ++ {3, 0, 8, 0, 58}, ++ {3, 0, 8, 0, 57}, ++ {3, 0, 8, 0, 55}, ++ {3, 0, 7, 0, 61}, ++ {3, 0, 7, 0, 60}, ++ {3, 0, 7, 0, 58}, ++ {3, 0, 7, 0, 56}, ++ {3, 0, 7, 0, 55}, ++ {3, 0, 6, 0, 62}, ++ {3, 0, 6, 0, 60}, ++ {3, 0, 6, 0, 58}, ++ {3, 0, 6, 0, 57}, ++ {3, 0, 6, 0, 55}, ++ {3, 0, 6, 0, 54}, ++ {3, 0, 6, 0, 52}, ++ {3, 0, 5, 0, 61}, ++ {3, 0, 5, 0, 59}, ++ {3, 0, 5, 0, 57}, ++ {3, 0, 5, 0, 56}, ++ {3, 0, 5, 0, 54}, ++ {3, 0, 5, 0, 53}, ++ {3, 0, 5, 0, 51}, ++ {3, 0, 4, 0, 62}, ++ {3, 0, 4, 0, 60}, ++ {3, 0, 4, 0, 58}, ++ {3, 0, 4, 0, 57}, ++ {3, 0, 4, 0, 55}, ++ {3, 0, 4, 0, 54}, ++ {3, 0, 4, 0, 52}, ++ {3, 0, 4, 0, 51}, ++ {3, 0, 4, 0, 49}, ++ {3, 0, 4, 0, 48}, ++ {3, 0, 4, 0, 46}, ++ {3, 0, 3, 0, 60}, ++ {3, 0, 3, 0, 58}, ++ {3, 0, 3, 0, 57}, ++ {3, 0, 3, 0, 55}, ++ {3, 0, 3, 0, 54}, ++ {3, 0, 3, 0, 52}, ++ {3, 0, 3, 0, 51}, ++ {3, 0, 3, 0, 49}, ++ {3, 0, 3, 0, 48}, ++ {3, 0, 3, 0, 46}, ++ {3, 0, 3, 0, 45}, ++ {3, 0, 3, 0, 44}, ++ {3, 0, 3, 0, 43}, ++ {3, 0, 3, 0, 41}, ++ {3, 0, 2, 0, 61}, ++ {3, 0, 2, 0, 59}, ++ {3, 0, 2, 0, 57}, ++ {3, 0, 2, 0, 56}, ++ {3, 0, 2, 0, 54}, ++ {3, 0, 2, 0, 53}, ++ {3, 0, 2, 0, 51}, ++ {3, 0, 2, 0, 50}, ++ {3, 0, 2, 0, 48}, ++ {3, 0, 2, 0, 47}, ++ {3, 0, 2, 0, 46}, ++ {3, 0, 2, 0, 44}, ++ {3, 0, 2, 0, 43}, ++ {3, 0, 2, 0, 42}, ++ {3, 0, 2, 0, 41}, ++ {3, 0, 2, 0, 39}, ++ {3, 0, 2, 0, 38}, ++ {3, 0, 2, 0, 37}, ++ {3, 0, 2, 0, 36}, ++ {3, 0, 2, 0, 35}, ++ {3, 0, 2, 0, 34}, ++ {3, 0, 2, 0, 33}, ++ {3, 0, 2, 0, 32}, ++ {3, 0, 1, 0, 63}, ++ {3, 0, 1, 0, 61}, ++ {3, 0, 1, 0, 59}, ++ {3, 0, 1, 0, 57}, ++}; ++ ++const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[128] = { ++ {7, 0, 31, 0, 72}, ++ {7, 0, 31, 0, 70}, ++ {7, 0, 31, 0, 68}, ++ {7, 0, 30, 0, 67}, ++ {7, 0, 29, 0, 68}, ++ {7, 0, 28, 0, 68}, ++ {7, 0, 27, 0, 69}, ++ {7, 0, 26, 0, 70}, ++ {7, 0, 25, 0, 70}, ++ {7, 0, 24, 0, 71}, ++ {7, 0, 23, 0, 72}, ++ {7, 0, 23, 0, 70}, ++ {7, 0, 22, 0, 71}, ++ {7, 0, 21, 0, 72}, ++ {7, 0, 21, 0, 70}, ++ {7, 0, 21, 0, 68}, ++ {7, 0, 21, 0, 66}, ++ {7, 0, 21, 0, 64}, ++ {7, 0, 21, 0, 63}, ++ {7, 0, 20, 0, 64}, ++ {7, 0, 19, 0, 65}, ++ {7, 0, 19, 0, 64}, ++ {7, 0, 18, 0, 65}, ++ {7, 0, 18, 0, 64}, ++ {7, 0, 17, 0, 65}, ++ {7, 0, 17, 0, 64}, ++ {7, 0, 16, 0, 65}, ++ {7, 0, 16, 0, 64}, ++ {7, 0, 16, 0, 62}, ++ {7, 0, 16, 0, 60}, ++ {7, 0, 16, 0, 58}, ++ {7, 0, 15, 0, 61}, ++ {7, 0, 15, 0, 59}, ++ {7, 0, 14, 0, 61}, ++ {7, 0, 14, 0, 60}, ++ {7, 0, 14, 0, 58}, ++ {7, 0, 13, 0, 60}, ++ {7, 0, 13, 0, 59}, ++ {7, 0, 12, 0, 62}, ++ {7, 0, 12, 0, 60}, ++ {7, 0, 12, 0, 58}, ++ {7, 0, 11, 0, 62}, ++ {7, 0, 11, 0, 60}, ++ {7, 0, 11, 0, 59}, ++ {7, 0, 11, 0, 57}, ++ {7, 0, 10, 0, 61}, ++ {7, 0, 10, 0, 59}, ++ {7, 0, 10, 0, 57}, ++ {7, 0, 9, 0, 62}, ++ {7, 0, 9, 0, 60}, ++ {7, 0, 9, 0, 58}, ++ {7, 0, 9, 0, 57}, ++ {7, 0, 8, 0, 62}, ++ {7, 0, 8, 0, 60}, ++ {7, 0, 8, 0, 58}, ++ {7, 0, 8, 0, 57}, ++ {7, 0, 8, 0, 55}, ++ {7, 0, 7, 0, 61}, ++ {7, 0, 7, 0, 60}, ++ {7, 0, 7, 0, 58}, ++ {7, 0, 7, 0, 56}, ++ {7, 0, 7, 0, 55}, ++ {7, 0, 6, 0, 62}, ++ {7, 0, 6, 0, 60}, ++ {7, 0, 6, 0, 58}, ++ {7, 0, 6, 0, 57}, ++ {7, 0, 6, 0, 55}, ++ {7, 0, 6, 0, 54}, ++ {7, 0, 6, 0, 52}, ++ {7, 0, 5, 0, 61}, ++ {7, 0, 5, 0, 59}, ++ {7, 0, 5, 0, 57}, ++ {7, 0, 5, 0, 56}, ++ {7, 0, 5, 0, 54}, ++ {7, 0, 5, 0, 53}, ++ {7, 0, 5, 0, 51}, ++ {7, 0, 4, 0, 62}, ++ {7, 0, 4, 0, 60}, ++ {7, 0, 4, 0, 58}, ++ {7, 0, 4, 0, 57}, ++ {7, 0, 4, 0, 55}, ++ {7, 0, 4, 0, 54}, ++ {7, 0, 4, 0, 52}, ++ {7, 0, 4, 0, 51}, ++ {7, 0, 4, 0, 49}, ++ {7, 0, 4, 0, 48}, ++ {7, 0, 4, 0, 46}, ++ {7, 0, 3, 0, 60}, ++ {7, 0, 3, 0, 58}, ++ {7, 0, 3, 0, 57}, ++ {7, 0, 3, 0, 55}, ++ {7, 0, 3, 0, 54}, ++ {7, 0, 3, 0, 52}, ++ {7, 0, 3, 0, 51}, ++ {7, 0, 3, 0, 49}, ++ {7, 0, 3, 0, 48}, ++ {7, 0, 3, 0, 46}, ++ {7, 0, 3, 0, 45}, ++ {7, 0, 3, 0, 44}, ++ {7, 0, 3, 0, 43}, ++ {7, 0, 3, 0, 41}, ++ {7, 0, 2, 0, 61}, ++ {7, 0, 2, 0, 59}, ++ {7, 0, 2, 0, 57}, ++ {7, 0, 2, 0, 56}, ++ {7, 0, 2, 0, 54}, ++ {7, 0, 2, 0, 53}, ++ {7, 0, 2, 0, 51}, ++ {7, 0, 2, 0, 50}, ++ {7, 0, 2, 0, 48}, ++ {7, 0, 2, 0, 47}, ++ {7, 0, 2, 0, 46}, ++ {7, 0, 2, 0, 44}, ++ {7, 0, 2, 0, 43}, ++ {7, 0, 2, 0, 42}, ++ {7, 0, 2, 0, 41}, ++ {7, 0, 2, 0, 39}, ++ {7, 0, 2, 0, 38}, ++ {7, 0, 2, 0, 37}, ++ {7, 0, 2, 0, 36}, ++ {7, 0, 2, 0, 35}, ++ {7, 0, 2, 0, 34}, ++ {7, 0, 2, 0, 33}, ++ {7, 0, 2, 0, 32}, ++ {7, 0, 1, 0, 63}, ++ {7, 0, 1, 0, 61}, ++ {7, 0, 1, 0, 59}, ++ {7, 0, 1, 0, 57}, ++}; ++ ++const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[128] = { ++ {255, 255, 0xf0, 0, 152}, ++ {255, 255, 0xf0, 0, 147}, ++ {255, 255, 0xf0, 0, 143}, ++ {255, 255, 0xf0, 0, 139}, ++ {255, 255, 0xf0, 0, 135}, ++ {255, 255, 0xf0, 0, 131}, ++ {255, 255, 0xf0, 0, 128}, ++ {255, 255, 0xf0, 0, 124}, ++ {255, 255, 0xf0, 0, 121}, ++ {255, 255, 0xf0, 0, 117}, ++ {255, 255, 0xf0, 0, 114}, ++ {255, 255, 0xf0, 0, 111}, ++ {255, 255, 0xf0, 0, 107}, ++ {255, 255, 0xf0, 0, 104}, ++ {255, 255, 0xf0, 0, 101}, ++ {255, 255, 0xf0, 0, 99}, ++ {255, 255, 0xf0, 0, 96}, ++ {255, 255, 0xf0, 0, 93}, ++ {255, 255, 0xf0, 0, 90}, ++ {255, 255, 0xf0, 0, 88}, ++ {255, 255, 0xf0, 0, 85}, ++ {255, 255, 0xf0, 0, 83}, ++ {255, 255, 0xf0, 0, 81}, ++ {255, 255, 0xf0, 0, 78}, ++ {255, 255, 0xf0, 0, 76}, ++ {255, 255, 0xf0, 0, 74}, ++ {255, 255, 0xf0, 0, 72}, ++ {255, 255, 0xf0, 0, 70}, ++ {255, 255, 0xf0, 0, 68}, ++ {255, 255, 0xf0, 0, 66}, ++ {255, 255, 0xf0, 0, 64}, ++ {255, 248, 0xf0, 0, 64}, ++ {255, 241, 0xf0, 0, 64}, ++ {255, 251, 0xe0, 0, 64}, ++ {255, 244, 0xe0, 0, 64}, ++ {255, 254, 0xd0, 0, 64}, ++ {255, 246, 0xd0, 0, 64}, ++ {255, 239, 0xd0, 0, 64}, ++ {255, 249, 0xc0, 0, 64}, ++ {255, 242, 0xc0, 0, 64}, ++ {255, 255, 0xb0, 0, 64}, ++ {255, 248, 0xb0, 0, 64}, ++ {255, 241, 0xb0, 0, 64}, ++ {255, 254, 0xa0, 0, 64}, ++ {255, 246, 0xa0, 0, 64}, ++ {255, 239, 0xa0, 0, 64}, ++ {255, 255, 0x90, 0, 64}, ++ {255, 248, 0x90, 0, 64}, ++ {255, 241, 0x90, 0, 64}, ++ {255, 234, 0x90, 0, 64}, ++ {255, 255, 0x80, 0, 64}, ++ {255, 248, 0x80, 0, 64}, ++ {255, 241, 0x80, 0, 64}, ++ {255, 234, 0x80, 0, 64}, ++ {255, 255, 0x70, 0, 64}, ++ {255, 248, 0x70, 0, 64}, ++ {255, 241, 0x70, 0, 64}, ++ {255, 234, 0x70, 0, 64}, ++ {255, 227, 0x70, 0, 64}, ++ {255, 221, 0x70, 0, 64}, ++ {255, 215, 0x70, 0, 64}, ++ {255, 208, 0x70, 0, 64}, ++ {255, 203, 0x70, 0, 64}, ++ {255, 197, 0x70, 0, 64}, ++ {255, 255, 0x60, 0, 64}, ++ {255, 248, 0x60, 0, 64}, ++ {255, 241, 0x60, 0, 64}, ++ {255, 234, 0x60, 0, 64}, ++ {255, 227, 0x60, 0, 64}, ++ {255, 221, 0x60, 0, 64}, ++ {255, 255, 0x50, 0, 64}, ++ {255, 248, 0x50, 0, 64}, ++ {255, 241, 0x50, 0, 64}, ++ {255, 234, 0x50, 0, 64}, ++ {255, 227, 0x50, 0, 64}, ++ {255, 221, 0x50, 0, 64}, ++ {255, 215, 0x50, 0, 64}, ++ {255, 208, 0x50, 0, 64}, ++ {255, 255, 0x40, 0, 64}, ++ {255, 248, 0x40, 0, 64}, ++ {255, 241, 0x40, 0, 64}, ++ {255, 234, 0x40, 0, 64}, ++ {255, 227, 0x40, 0, 64}, ++ {255, 221, 0x40, 0, 64}, ++ {255, 215, 0x40, 0, 64}, ++ {255, 208, 0x40, 0, 64}, ++ {255, 203, 0x40, 0, 64}, ++ {255, 197, 0x40, 0, 64}, ++ {255, 255, 0x30, 0, 64}, ++ {255, 248, 0x30, 0, 64}, ++ {255, 241, 0x30, 0, 64}, ++ {255, 234, 0x30, 0, 64}, ++ {255, 227, 0x30, 0, 64}, ++ {255, 221, 0x30, 0, 64}, ++ {255, 215, 0x30, 0, 64}, ++ {255, 208, 0x30, 0, 64}, ++ {255, 203, 0x30, 0, 64}, ++ {255, 197, 0x30, 0, 64}, ++ {255, 191, 0x30, 0, 64}, ++ {255, 186, 0x30, 0, 64}, ++ {255, 181, 0x30, 0, 64}, ++ {255, 175, 0x30, 0, 64}, ++ {255, 255, 0x20, 0, 64}, ++ {255, 248, 0x20, 0, 64}, ++ {255, 241, 0x20, 0, 64}, ++ {255, 234, 0x20, 0, 64}, ++ {255, 227, 0x20, 0, 64}, ++ {255, 221, 0x20, 0, 64}, ++ {255, 215, 0x20, 0, 64}, ++ {255, 208, 0x20, 0, 64}, ++ {255, 203, 0x20, 0, 64}, ++ {255, 197, 0x20, 0, 64}, ++ {255, 191, 0x20, 0, 64}, ++ {255, 186, 0x20, 0, 64}, ++ {255, 181, 0x20, 0, 64}, ++ {255, 175, 0x20, 0, 64}, ++ {255, 170, 0x20, 0, 64}, ++ {255, 166, 0x20, 0, 64}, ++ {255, 161, 0x20, 0, 64}, ++ {255, 156, 0x20, 0, 64}, ++ {255, 152, 0x20, 0, 64}, ++ {255, 148, 0x20, 0, 64}, ++ {255, 143, 0x20, 0, 64}, ++ {255, 139, 0x20, 0, 64}, ++ {255, 135, 0x20, 0, 64}, ++ {255, 132, 0x20, 0, 64}, ++ {255, 255, 0x10, 0, 64}, ++ {255, 248, 0x10, 0, 64}, ++}; +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h.orig 2011-11-09 13:46:58.278800221 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h 2011-11-09 13:47:17.036565717 -0500 +@@ -0,0 +1,54 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include "phy_int.h" ++ ++extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev0[]; ++extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev0; ++extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313; ++extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa; ++extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa_combo; ++extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa; ++extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250; ++ ++extern const struct phytbl_info dot11lcnphytbl_info_rev0[]; ++extern const u32 dot11lcnphytbl_info_sz_rev0; ++ ++extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_2G_rev2[]; ++extern const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz; ++ ++extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_5G_rev2[]; ++extern const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz; ++ ++extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[]; ++ ++extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[]; ++ ++struct lcnphy_tx_gain_tbl_entry { ++ unsigned char gm; ++ unsigned char pga; ++ unsigned char pad; ++ unsigned char dac; ++ unsigned char bb_mult; ++}; ++ ++extern const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[]; ++ ++extern const struct ++lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_extPA_gaintable_rev0[]; ++ ++extern const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[]; +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.c.orig 2011-11-09 13:46:58.282800170 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.c 2011-11-09 13:47:17.040565666 -0500 +@@ -0,0 +1,10630 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include "phytbl_n.h" ++ ++static const u32 frame_struct_rev0[] = { ++ 0x08004a04, ++ 0x00100000, ++ 0x01000a05, ++ 0x00100020, ++ 0x09804506, ++ 0x00100030, ++ 0x09804507, ++ 0x00100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x08004a0c, ++ 0x00100004, ++ 0x01000a0d, ++ 0x00100024, ++ 0x0980450e, ++ 0x00100034, ++ 0x0980450f, ++ 0x00100034, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000a04, ++ 0x00100000, ++ 0x11008a05, ++ 0x00100020, ++ 0x1980c506, ++ 0x00100030, ++ 0x21810506, ++ 0x00100030, ++ 0x21810506, ++ 0x00100030, ++ 0x01800504, ++ 0x00100030, ++ 0x11808505, ++ 0x00100030, ++ 0x29814507, ++ 0x01100030, ++ 0x00000a04, ++ 0x00100000, ++ 0x11008a05, ++ 0x00100020, ++ 0x21810506, ++ 0x00100030, ++ 0x21810506, ++ 0x00100030, ++ 0x29814507, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000a0c, ++ 0x00100008, ++ 0x11008a0d, ++ 0x00100028, ++ 0x1980c50e, ++ 0x00100038, ++ 0x2181050e, ++ 0x00100038, ++ 0x2181050e, ++ 0x00100038, ++ 0x0180050c, ++ 0x00100038, ++ 0x1180850d, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000a0c, ++ 0x00100008, ++ 0x11008a0d, ++ 0x00100028, ++ 0x2181050e, ++ 0x00100038, ++ 0x2181050e, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x08004a04, ++ 0x00100000, ++ 0x01000a05, ++ 0x00100020, ++ 0x1980c506, ++ 0x00100030, ++ 0x1980c506, ++ 0x00100030, ++ 0x11808504, ++ 0x00100030, ++ 0x3981ca05, ++ 0x00100030, ++ 0x29814507, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x10008a04, ++ 0x00100000, ++ 0x3981ca05, ++ 0x00100030, ++ 0x1980c506, ++ 0x00100030, ++ 0x29814507, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x08004a0c, ++ 0x00100008, ++ 0x01000a0d, ++ 0x00100028, ++ 0x1980c50e, ++ 0x00100038, ++ 0x1980c50e, ++ 0x00100038, ++ 0x1180850c, ++ 0x00100038, ++ 0x3981ca0d, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x10008a0c, ++ 0x00100008, ++ 0x3981ca0d, ++ 0x00100038, ++ 0x1980c50e, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x40021404, ++ 0x00100000, ++ 0x02001405, ++ 0x00100040, ++ 0x0b004a06, ++ 0x01900060, ++ 0x13008a06, ++ 0x01900060, ++ 0x13008a06, ++ 0x01900060, ++ 0x43020a04, ++ 0x00100060, ++ 0x1b00ca05, ++ 0x00100060, ++ 0x23010a07, ++ 0x01500060, ++ 0x40021404, ++ 0x00100000, ++ 0x1a00d405, ++ 0x00100040, ++ 0x13008a06, ++ 0x01900060, ++ 0x13008a06, ++ 0x01900060, ++ 0x23010a07, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100010, ++ 0x0200140d, ++ 0x00100050, ++ 0x0b004a0e, ++ 0x01900070, ++ 0x13008a0e, ++ 0x01900070, ++ 0x13008a0e, ++ 0x01900070, ++ 0x43020a0c, ++ 0x00100070, ++ 0x1b00ca0d, ++ 0x00100070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x4002140c, ++ 0x00100010, ++ 0x1a00d40d, ++ 0x00100050, ++ 0x13008a0e, ++ 0x01900070, ++ 0x13008a0e, ++ 0x01900070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x50029404, ++ 0x00100000, ++ 0x32019405, ++ 0x00100040, ++ 0x0b004a06, ++ 0x01900060, ++ 0x0b004a06, ++ 0x01900060, ++ 0x5b02ca04, ++ 0x00100060, ++ 0x3b01d405, ++ 0x00100060, ++ 0x23010a07, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x5802d404, ++ 0x00100000, ++ 0x3b01d405, ++ 0x00100060, ++ 0x0b004a06, ++ 0x01900060, ++ 0x23010a07, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x5002940c, ++ 0x00100010, ++ 0x3201940d, ++ 0x00100050, ++ 0x0b004a0e, ++ 0x01900070, ++ 0x0b004a0e, ++ 0x01900070, ++ 0x5b02ca0c, ++ 0x00100070, ++ 0x3b01d40d, ++ 0x00100070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x5802d40c, ++ 0x00100010, ++ 0x3b01d40d, ++ 0x00100070, ++ 0x0b004a0e, ++ 0x01900070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x40021404, ++ 0x000f4800, ++ 0x62031405, ++ 0x00100040, ++ 0x53028a06, ++ 0x01900060, ++ 0x53028a07, ++ 0x01900060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x000f4808, ++ 0x6203140d, ++ 0x00100048, ++ 0x53028a0e, ++ 0x01900068, ++ 0x53028a0f, ++ 0x01900068, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000a0c, ++ 0x00100004, ++ 0x11008a0d, ++ 0x00100024, ++ 0x1980c50e, ++ 0x00100034, ++ 0x2181050e, ++ 0x00100034, ++ 0x2181050e, ++ 0x00100034, ++ 0x0180050c, ++ 0x00100038, ++ 0x1180850d, ++ 0x00100038, ++ 0x1181850d, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000a0c, ++ 0x00100008, ++ 0x11008a0d, ++ 0x00100028, ++ 0x2181050e, ++ 0x00100038, ++ 0x2181050e, ++ 0x00100038, ++ 0x1181850d, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x08004a04, ++ 0x00100000, ++ 0x01000a05, ++ 0x00100020, ++ 0x0180c506, ++ 0x00100030, ++ 0x0180c506, ++ 0x00100030, ++ 0x2180c50c, ++ 0x00100030, ++ 0x49820a0d, ++ 0x0016a130, ++ 0x41824a0d, ++ 0x0016a130, ++ 0x2981450f, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x2000ca0c, ++ 0x00100000, ++ 0x49820a0d, ++ 0x0016a130, ++ 0x1980c50e, ++ 0x00100030, ++ 0x41824a0d, ++ 0x0016a130, ++ 0x2981450f, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100008, ++ 0x0200140d, ++ 0x00100048, ++ 0x0b004a0e, ++ 0x01900068, ++ 0x13008a0e, ++ 0x01900068, ++ 0x13008a0e, ++ 0x01900068, ++ 0x43020a0c, ++ 0x00100070, ++ 0x1b00ca0d, ++ 0x00100070, ++ 0x1b014a0d, ++ 0x00100070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100010, ++ 0x1a00d40d, ++ 0x00100050, ++ 0x13008a0e, ++ 0x01900070, ++ 0x13008a0e, ++ 0x01900070, ++ 0x1b014a0d, ++ 0x00100070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x50029404, ++ 0x00100000, ++ 0x32019405, ++ 0x00100040, ++ 0x03004a06, ++ 0x01900060, ++ 0x03004a06, ++ 0x01900060, ++ 0x6b030a0c, ++ 0x00100060, ++ 0x4b02140d, ++ 0x0016a160, ++ 0x4302540d, ++ 0x0016a160, ++ 0x23010a0f, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x6b03140c, ++ 0x00100060, ++ 0x4b02140d, ++ 0x0016a160, ++ 0x0b004a0e, ++ 0x01900060, ++ 0x4302540d, ++ 0x0016a160, ++ 0x23010a0f, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x40021404, ++ 0x00100000, ++ 0x1a00d405, ++ 0x00100040, ++ 0x53028a06, ++ 0x01900060, ++ 0x5b02ca06, ++ 0x01900060, ++ 0x5b02ca06, ++ 0x01900060, ++ 0x43020a04, ++ 0x00100060, ++ 0x1b00ca05, ++ 0x00100060, ++ 0x53028a07, ++ 0x0190c060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100010, ++ 0x1a00d40d, ++ 0x00100050, ++ 0x53028a0e, ++ 0x01900070, ++ 0x5b02ca0e, ++ 0x01900070, ++ 0x5b02ca0e, ++ 0x01900070, ++ 0x43020a0c, ++ 0x00100070, ++ 0x1b00ca0d, ++ 0x00100070, ++ 0x53028a0f, ++ 0x0190c070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x40021404, ++ 0x00100000, ++ 0x1a00d405, ++ 0x00100040, ++ 0x5b02ca06, ++ 0x01900060, ++ 0x5b02ca06, ++ 0x01900060, ++ 0x53028a07, ++ 0x0190c060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100010, ++ 0x1a00d40d, ++ 0x00100050, ++ 0x5b02ca0e, ++ 0x01900070, ++ 0x5b02ca0e, ++ 0x01900070, ++ 0x53028a0f, ++ 0x0190c070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u8 frame_lut_rev0[] = { ++ 0x02, ++ 0x04, ++ 0x14, ++ 0x14, ++ 0x03, ++ 0x05, ++ 0x16, ++ 0x16, ++ 0x0a, ++ 0x0c, ++ 0x1c, ++ 0x1c, ++ 0x0b, ++ 0x0d, ++ 0x1e, ++ 0x1e, ++ 0x06, ++ 0x08, ++ 0x18, ++ 0x18, ++ 0x07, ++ 0x09, ++ 0x1a, ++ 0x1a, ++ 0x0e, ++ 0x10, ++ 0x20, ++ 0x28, ++ 0x0f, ++ 0x11, ++ 0x22, ++ 0x2a, ++}; ++ ++static const u32 tmap_tbl_rev0[] = { ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x000aa888, ++ 0x88880000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa2222220, ++ 0x22222222, ++ 0x22c22222, ++ 0x00000222, ++ 0x22000000, ++ 0x2222a222, ++ 0x22222222, ++ 0x222222a2, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00011111, ++ 0x11110000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0xa8aa88a0, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x00088aaa, ++ 0xaaaa0000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xaaa8aaa0, ++ 0x8aaa8aaa, ++ 0xaa8a8a8a, ++ 0x000aaa88, ++ 0x8aaa0000, ++ 0xaaa8a888, ++ 0x8aa88a8a, ++ 0x8a88a888, ++ 0x08080a00, ++ 0x0a08080a, ++ 0x080a0a08, ++ 0x00080808, ++ 0x080a0000, ++ 0x080a0808, ++ 0x080a0808, ++ 0x0a0a0a08, ++ 0xa0a0a0a0, ++ 0x80a0a080, ++ 0x8080a0a0, ++ 0x00008080, ++ 0x80a00000, ++ 0x80a080a0, ++ 0xa080a0a0, ++ 0x8080a0a0, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x99999000, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb90, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00aaa888, ++ 0x22000000, ++ 0x2222b222, ++ 0x22222222, ++ 0x222222b2, ++ 0xb2222220, ++ 0x22222222, ++ 0x22d22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x33000000, ++ 0x3333b333, ++ 0x33333333, ++ 0x333333b3, ++ 0xb3333330, ++ 0x33333333, ++ 0x33d33333, ++ 0x00000333, ++ 0x22000000, ++ 0x2222a222, ++ 0x22222222, ++ 0x222222a2, ++ 0xa2222220, ++ 0x22222222, ++ 0x22c22222, ++ 0x00000222, ++ 0x99b99b00, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb99, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x08aaa888, ++ 0x22222200, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0x22222222, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x11111111, ++ 0xf1111111, ++ 0x11111111, ++ 0x11f11111, ++ 0x01111111, ++ 0xbb9bb900, ++ 0xb9b9bb99, ++ 0xb99bbbbb, ++ 0xbbbb9b9b, ++ 0xb9bb99bb, ++ 0xb99999b9, ++ 0xb9b9b99b, ++ 0x00000bbb, ++ 0xaa000000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xa8aa88aa, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x0a888aaa, ++ 0xaa000000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xa8aa88a0, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x00000aaa, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0xbbbbbb00, ++ 0x999bbbbb, ++ 0x9bb99b9b, ++ 0xb9b9b9bb, ++ 0xb9b99bbb, ++ 0xb9b9b9bb, ++ 0xb9bb9b99, ++ 0x00000999, ++ 0x8a000000, ++ 0xaa88a888, ++ 0xa88888aa, ++ 0xa88a8a88, ++ 0xa88aa88a, ++ 0x88a8aaaa, ++ 0xa8aa8aaa, ++ 0x0888a88a, ++ 0x0b0b0b00, ++ 0x090b0b0b, ++ 0x0b090b0b, ++ 0x0909090b, ++ 0x09090b0b, ++ 0x09090b0b, ++ 0x09090b09, ++ 0x00000909, ++ 0x0a000000, ++ 0x0a080808, ++ 0x080a080a, ++ 0x080a0a08, ++ 0x080a080a, ++ 0x0808080a, ++ 0x0a0a0a08, ++ 0x0808080a, ++ 0xb0b0b000, ++ 0x9090b0b0, ++ 0x90b09090, ++ 0xb0b0b090, ++ 0xb0b090b0, ++ 0x90b0b0b0, ++ 0xb0b09090, ++ 0x00000090, ++ 0x80000000, ++ 0xa080a080, ++ 0xa08080a0, ++ 0xa0808080, ++ 0xa080a080, ++ 0x80a0a0a0, ++ 0xa0a080a0, ++ 0x00a0a0a0, ++ 0x22000000, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0xf2222220, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00000111, ++ 0x33000000, ++ 0x3333f333, ++ 0x33333333, ++ 0x333333f3, ++ 0xf3333330, ++ 0x33333333, ++ 0x33f33333, ++ 0x00000333, ++ 0x22000000, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0xf2222220, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x99000000, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb90, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88888000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00aaa888, ++ 0x88a88a00, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x08aaa888, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 tdtrn_tbl_rev0[] = { ++ 0x061c061c, ++ 0x0050ee68, ++ 0xf592fe36, ++ 0xfe5212f6, ++ 0x00000c38, ++ 0xfe5212f6, ++ 0xf592fe36, ++ 0x0050ee68, ++ 0x061c061c, ++ 0xee680050, ++ 0xfe36f592, ++ 0x12f6fe52, ++ 0x0c380000, ++ 0x12f6fe52, ++ 0xfe36f592, ++ 0xee680050, ++ 0x061c061c, ++ 0x0050ee68, ++ 0xf592fe36, ++ 0xfe5212f6, ++ 0x00000c38, ++ 0xfe5212f6, ++ 0xf592fe36, ++ 0x0050ee68, ++ 0x061c061c, ++ 0xee680050, ++ 0xfe36f592, ++ 0x12f6fe52, ++ 0x0c380000, ++ 0x12f6fe52, ++ 0xfe36f592, ++ 0xee680050, ++ 0x05e305e3, ++ 0x004def0c, ++ 0xf5f3fe47, ++ 0xfe611246, ++ 0x00000bc7, ++ 0xfe611246, ++ 0xf5f3fe47, ++ 0x004def0c, ++ 0x05e305e3, ++ 0xef0c004d, ++ 0xfe47f5f3, ++ 0x1246fe61, ++ 0x0bc70000, ++ 0x1246fe61, ++ 0xfe47f5f3, ++ 0xef0c004d, ++ 0x05e305e3, ++ 0x004def0c, ++ 0xf5f3fe47, ++ 0xfe611246, ++ 0x00000bc7, ++ 0xfe611246, ++ 0xf5f3fe47, ++ 0x004def0c, ++ 0x05e305e3, ++ 0xef0c004d, ++ 0xfe47f5f3, ++ 0x1246fe61, ++ 0x0bc70000, ++ 0x1246fe61, ++ 0xfe47f5f3, ++ 0xef0c004d, ++ 0xfa58fa58, ++ 0xf895043b, ++ 0xff4c09c0, ++ 0xfbc6ffa8, ++ 0xfb84f384, ++ 0x0798f6f9, ++ 0x05760122, ++ 0x058409f6, ++ 0x0b500000, ++ 0x05b7f542, ++ 0x08860432, ++ 0x06ddfee7, ++ 0xfb84f384, ++ 0xf9d90664, ++ 0xf7e8025c, ++ 0x00fff7bd, ++ 0x05a805a8, ++ 0xf7bd00ff, ++ 0x025cf7e8, ++ 0x0664f9d9, ++ 0xf384fb84, ++ 0xfee706dd, ++ 0x04320886, ++ 0xf54205b7, ++ 0x00000b50, ++ 0x09f60584, ++ 0x01220576, ++ 0xf6f90798, ++ 0xf384fb84, ++ 0xffa8fbc6, ++ 0x09c0ff4c, ++ 0x043bf895, ++ 0x02d402d4, ++ 0x07de0270, ++ 0xfc96079c, ++ 0xf90afe94, ++ 0xfe00ff2c, ++ 0x02d4065d, ++ 0x092a0096, ++ 0x0014fbb8, ++ 0xfd2cfd2c, ++ 0x076afb3c, ++ 0x0096f752, ++ 0xf991fd87, ++ 0xfb2c0200, ++ 0xfeb8f960, ++ 0x08e0fc96, ++ 0x049802a8, ++ 0xfd2cfd2c, ++ 0x02a80498, ++ 0xfc9608e0, ++ 0xf960feb8, ++ 0x0200fb2c, ++ 0xfd87f991, ++ 0xf7520096, ++ 0xfb3c076a, ++ 0xfd2cfd2c, ++ 0xfbb80014, ++ 0x0096092a, ++ 0x065d02d4, ++ 0xff2cfe00, ++ 0xfe94f90a, ++ 0x079cfc96, ++ 0x027007de, ++ 0x02d402d4, ++ 0x027007de, ++ 0x079cfc96, ++ 0xfe94f90a, ++ 0xff2cfe00, ++ 0x065d02d4, ++ 0x0096092a, ++ 0xfbb80014, ++ 0xfd2cfd2c, ++ 0xfb3c076a, ++ 0xf7520096, ++ 0xfd87f991, ++ 0x0200fb2c, ++ 0xf960feb8, ++ 0xfc9608e0, ++ 0x02a80498, ++ 0xfd2cfd2c, ++ 0x049802a8, ++ 0x08e0fc96, ++ 0xfeb8f960, ++ 0xfb2c0200, ++ 0xf991fd87, ++ 0x0096f752, ++ 0x076afb3c, ++ 0xfd2cfd2c, ++ 0x0014fbb8, ++ 0x092a0096, ++ 0x02d4065d, ++ 0xfe00ff2c, ++ 0xf90afe94, ++ 0xfc96079c, ++ 0x07de0270, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x062a0000, ++ 0xfefa0759, ++ 0x08b80908, ++ 0xf396fc2d, ++ 0xf9d6045c, ++ 0xfc4ef608, ++ 0xf748f596, ++ 0x07b207bf, ++ 0x062a062a, ++ 0xf84ef841, ++ 0xf748f596, ++ 0x03b209f8, ++ 0xf9d6045c, ++ 0x0c6a03d3, ++ 0x08b80908, ++ 0x0106f8a7, ++ 0x062a0000, ++ 0xfefaf8a7, ++ 0x08b8f6f8, ++ 0xf39603d3, ++ 0xf9d6fba4, ++ 0xfc4e09f8, ++ 0xf7480a6a, ++ 0x07b2f841, ++ 0x062af9d6, ++ 0xf84e07bf, ++ 0xf7480a6a, ++ 0x03b2f608, ++ 0xf9d6fba4, ++ 0x0c6afc2d, ++ 0x08b8f6f8, ++ 0x01060759, ++ 0x062a0000, ++ 0xfefa0759, ++ 0x08b80908, ++ 0xf396fc2d, ++ 0xf9d6045c, ++ 0xfc4ef608, ++ 0xf748f596, ++ 0x07b207bf, ++ 0x062a062a, ++ 0xf84ef841, ++ 0xf748f596, ++ 0x03b209f8, ++ 0xf9d6045c, ++ 0x0c6a03d3, ++ 0x08b80908, ++ 0x0106f8a7, ++ 0x062a0000, ++ 0xfefaf8a7, ++ 0x08b8f6f8, ++ 0xf39603d3, ++ 0xf9d6fba4, ++ 0xfc4e09f8, ++ 0xf7480a6a, ++ 0x07b2f841, ++ 0x062af9d6, ++ 0xf84e07bf, ++ 0xf7480a6a, ++ 0x03b2f608, ++ 0xf9d6fba4, ++ 0x0c6afc2d, ++ 0x08b8f6f8, ++ 0x01060759, ++ 0x061c061c, ++ 0xff30009d, ++ 0xffb21141, ++ 0xfd87fb54, ++ 0xf65dfe59, ++ 0x02eef99e, ++ 0x0166f03c, ++ 0xfff809b6, ++ 0x000008a4, ++ 0x000af42b, ++ 0x00eff577, ++ 0xfa840bf2, ++ 0xfc02ff51, ++ 0x08260f67, ++ 0xfff0036f, ++ 0x0842f9c3, ++ 0x00000000, ++ 0x063df7be, ++ 0xfc910010, ++ 0xf099f7da, ++ 0x00af03fe, ++ 0xf40e057c, ++ 0x0a89ff11, ++ 0x0bd5fff6, ++ 0xf75c0000, ++ 0xf64a0008, ++ 0x0fc4fe9a, ++ 0x0662fd12, ++ 0x01a709a3, ++ 0x04ac0279, ++ 0xeebf004e, ++ 0xff6300d0, ++ 0xf9e4f9e4, ++ 0x00d0ff63, ++ 0x004eeebf, ++ 0x027904ac, ++ 0x09a301a7, ++ 0xfd120662, ++ 0xfe9a0fc4, ++ 0x0008f64a, ++ 0x0000f75c, ++ 0xfff60bd5, ++ 0xff110a89, ++ 0x057cf40e, ++ 0x03fe00af, ++ 0xf7daf099, ++ 0x0010fc91, ++ 0xf7be063d, ++ 0x00000000, ++ 0xf9c30842, ++ 0x036ffff0, ++ 0x0f670826, ++ 0xff51fc02, ++ 0x0bf2fa84, ++ 0xf57700ef, ++ 0xf42b000a, ++ 0x08a40000, ++ 0x09b6fff8, ++ 0xf03c0166, ++ 0xf99e02ee, ++ 0xfe59f65d, ++ 0xfb54fd87, ++ 0x1141ffb2, ++ 0x009dff30, ++ 0x05e30000, ++ 0xff060705, ++ 0x085408a0, ++ 0xf425fc59, ++ 0xfa1d042a, ++ 0xfc78f67a, ++ 0xf7acf60e, ++ 0x075a0766, ++ 0x05e305e3, ++ 0xf8a6f89a, ++ 0xf7acf60e, ++ 0x03880986, ++ 0xfa1d042a, ++ 0x0bdb03a7, ++ 0x085408a0, ++ 0x00faf8fb, ++ 0x05e30000, ++ 0xff06f8fb, ++ 0x0854f760, ++ 0xf42503a7, ++ 0xfa1dfbd6, ++ 0xfc780986, ++ 0xf7ac09f2, ++ 0x075af89a, ++ 0x05e3fa1d, ++ 0xf8a60766, ++ 0xf7ac09f2, ++ 0x0388f67a, ++ 0xfa1dfbd6, ++ 0x0bdbfc59, ++ 0x0854f760, ++ 0x00fa0705, ++ 0x05e30000, ++ 0xff060705, ++ 0x085408a0, ++ 0xf425fc59, ++ 0xfa1d042a, ++ 0xfc78f67a, ++ 0xf7acf60e, ++ 0x075a0766, ++ 0x05e305e3, ++ 0xf8a6f89a, ++ 0xf7acf60e, ++ 0x03880986, ++ 0xfa1d042a, ++ 0x0bdb03a7, ++ 0x085408a0, ++ 0x00faf8fb, ++ 0x05e30000, ++ 0xff06f8fb, ++ 0x0854f760, ++ 0xf42503a7, ++ 0xfa1dfbd6, ++ 0xfc780986, ++ 0xf7ac09f2, ++ 0x075af89a, ++ 0x05e3fa1d, ++ 0xf8a60766, ++ 0xf7ac09f2, ++ 0x0388f67a, ++ 0xfa1dfbd6, ++ 0x0bdbfc59, ++ 0x0854f760, ++ 0x00fa0705, ++ 0xfa58fa58, ++ 0xf8f0fe00, ++ 0x0448073d, ++ 0xfdc9fe46, ++ 0xf9910258, ++ 0x089d0407, ++ 0xfd5cf71a, ++ 0x02affde0, ++ 0x083e0496, ++ 0xff5a0740, ++ 0xff7afd97, ++ 0x00fe01f1, ++ 0x0009082e, ++ 0xfa94ff75, ++ 0xfecdf8ea, ++ 0xffb0f693, ++ 0xfd2cfa58, ++ 0x0433ff16, ++ 0xfba405dd, ++ 0xfa610341, ++ 0x06a606cb, ++ 0x0039fd2d, ++ 0x0677fa97, ++ 0x01fa05e0, ++ 0xf896003e, ++ 0x075a068b, ++ 0x012cfc3e, ++ 0xfa23f98d, ++ 0xfc7cfd43, ++ 0xff90fc0d, ++ 0x01c10982, ++ 0x00c601d6, ++ 0xfd2cfd2c, ++ 0x01d600c6, ++ 0x098201c1, ++ 0xfc0dff90, ++ 0xfd43fc7c, ++ 0xf98dfa23, ++ 0xfc3e012c, ++ 0x068b075a, ++ 0x003ef896, ++ 0x05e001fa, ++ 0xfa970677, ++ 0xfd2d0039, ++ 0x06cb06a6, ++ 0x0341fa61, ++ 0x05ddfba4, ++ 0xff160433, ++ 0xfa58fd2c, ++ 0xf693ffb0, ++ 0xf8eafecd, ++ 0xff75fa94, ++ 0x082e0009, ++ 0x01f100fe, ++ 0xfd97ff7a, ++ 0x0740ff5a, ++ 0x0496083e, ++ 0xfde002af, ++ 0xf71afd5c, ++ 0x0407089d, ++ 0x0258f991, ++ 0xfe46fdc9, ++ 0x073d0448, ++ 0xfe00f8f0, ++ 0xfd2cfd2c, ++ 0xfce00500, ++ 0xfc09fddc, ++ 0xfe680157, ++ 0x04c70571, ++ 0xfc3aff21, ++ 0xfcd70228, ++ 0x056d0277, ++ 0x0200fe00, ++ 0x0022f927, ++ 0xfe3c032b, ++ 0xfc44ff3c, ++ 0x03e9fbdb, ++ 0x04570313, ++ 0x04c9ff5c, ++ 0x000d03b8, ++ 0xfa580000, ++ 0xfbe900d2, ++ 0xf9d0fe0b, ++ 0x0125fdf9, ++ 0x042501bf, ++ 0x0328fa2b, ++ 0xffa902f0, ++ 0xfa250157, ++ 0x0200fe00, ++ 0x03740438, ++ 0xff0405fd, ++ 0x030cfe52, ++ 0x0037fb39, ++ 0xff6904c5, ++ 0x04f8fd23, ++ 0xfd31fc1b, ++ 0xfd2cfd2c, ++ 0xfc1bfd31, ++ 0xfd2304f8, ++ 0x04c5ff69, ++ 0xfb390037, ++ 0xfe52030c, ++ 0x05fdff04, ++ 0x04380374, ++ 0xfe000200, ++ 0x0157fa25, ++ 0x02f0ffa9, ++ 0xfa2b0328, ++ 0x01bf0425, ++ 0xfdf90125, ++ 0xfe0bf9d0, ++ 0x00d2fbe9, ++ 0x0000fa58, ++ 0x03b8000d, ++ 0xff5c04c9, ++ 0x03130457, ++ 0xfbdb03e9, ++ 0xff3cfc44, ++ 0x032bfe3c, ++ 0xf9270022, ++ 0xfe000200, ++ 0x0277056d, ++ 0x0228fcd7, ++ 0xff21fc3a, ++ 0x057104c7, ++ 0x0157fe68, ++ 0xfddcfc09, ++ 0x0500fce0, ++ 0xfd2cfd2c, ++ 0x0500fce0, ++ 0xfddcfc09, ++ 0x0157fe68, ++ 0x057104c7, ++ 0xff21fc3a, ++ 0x0228fcd7, ++ 0x0277056d, ++ 0xfe000200, ++ 0xf9270022, ++ 0x032bfe3c, ++ 0xff3cfc44, ++ 0xfbdb03e9, ++ 0x03130457, ++ 0xff5c04c9, ++ 0x03b8000d, ++ 0x0000fa58, ++ 0x00d2fbe9, ++ 0xfe0bf9d0, ++ 0xfdf90125, ++ 0x01bf0425, ++ 0xfa2b0328, ++ 0x02f0ffa9, ++ 0x0157fa25, ++ 0xfe000200, ++ 0x04380374, ++ 0x05fdff04, ++ 0xfe52030c, ++ 0xfb390037, ++ 0x04c5ff69, ++ 0xfd2304f8, ++ 0xfc1bfd31, ++ 0xfd2cfd2c, ++ 0xfd31fc1b, ++ 0x04f8fd23, ++ 0xff6904c5, ++ 0x0037fb39, ++ 0x030cfe52, ++ 0xff0405fd, ++ 0x03740438, ++ 0x0200fe00, ++ 0xfa250157, ++ 0xffa902f0, ++ 0x0328fa2b, ++ 0x042501bf, ++ 0x0125fdf9, ++ 0xf9d0fe0b, ++ 0xfbe900d2, ++ 0xfa580000, ++ 0x000d03b8, ++ 0x04c9ff5c, ++ 0x04570313, ++ 0x03e9fbdb, ++ 0xfc44ff3c, ++ 0xfe3c032b, ++ 0x0022f927, ++ 0x0200fe00, ++ 0x056d0277, ++ 0xfcd70228, ++ 0xfc3aff21, ++ 0x04c70571, ++ 0xfe680157, ++ 0xfc09fddc, ++ 0xfce00500, ++ 0x05a80000, ++ 0xff1006be, ++ 0x0800084a, ++ 0xf49cfc7e, ++ 0xfa580400, ++ 0xfc9cf6da, ++ 0xf800f672, ++ 0x0710071c, ++ 0x05a805a8, ++ 0xf8f0f8e4, ++ 0xf800f672, ++ 0x03640926, ++ 0xfa580400, ++ 0x0b640382, ++ 0x0800084a, ++ 0x00f0f942, ++ 0x05a80000, ++ 0xff10f942, ++ 0x0800f7b6, ++ 0xf49c0382, ++ 0xfa58fc00, ++ 0xfc9c0926, ++ 0xf800098e, ++ 0x0710f8e4, ++ 0x05a8fa58, ++ 0xf8f0071c, ++ 0xf800098e, ++ 0x0364f6da, ++ 0xfa58fc00, ++ 0x0b64fc7e, ++ 0x0800f7b6, ++ 0x00f006be, ++ 0x05a80000, ++ 0xff1006be, ++ 0x0800084a, ++ 0xf49cfc7e, ++ 0xfa580400, ++ 0xfc9cf6da, ++ 0xf800f672, ++ 0x0710071c, ++ 0x05a805a8, ++ 0xf8f0f8e4, ++ 0xf800f672, ++ 0x03640926, ++ 0xfa580400, ++ 0x0b640382, ++ 0x0800084a, ++ 0x00f0f942, ++ 0x05a80000, ++ 0xff10f942, ++ 0x0800f7b6, ++ 0xf49c0382, ++ 0xfa58fc00, ++ 0xfc9c0926, ++ 0xf800098e, ++ 0x0710f8e4, ++ 0x05a8fa58, ++ 0xf8f0071c, ++ 0xf800098e, ++ 0x0364f6da, ++ 0xfa58fc00, ++ 0x0b64fc7e, ++ 0x0800f7b6, ++ 0x00f006be, ++}; ++ ++static const u32 intlv_tbl_rev0[] = { ++ 0x00802070, ++ 0x0671188d, ++ 0x0a60192c, ++ 0x0a300e46, ++ 0x00c1188d, ++ 0x080024d2, ++ 0x00000070, ++}; ++ ++static const u16 pilot_tbl_rev0[] = { ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0xff0a, ++ 0xff82, ++ 0xffa0, ++ 0xff28, ++ 0xffff, ++ 0xffff, ++ 0xffff, ++ 0xffff, ++ 0xff82, ++ 0xffa0, ++ 0xff28, ++ 0xff0a, ++ 0xffff, ++ 0xffff, ++ 0xffff, ++ 0xffff, ++ 0xf83f, ++ 0xfa1f, ++ 0xfa97, ++ 0xfab5, ++ 0xf2bd, ++ 0xf0bf, ++ 0xffff, ++ 0xffff, ++ 0xf017, ++ 0xf815, ++ 0xf215, ++ 0xf095, ++ 0xf035, ++ 0xf01d, ++ 0xffff, ++ 0xffff, ++ 0xff08, ++ 0xff02, ++ 0xff80, ++ 0xff20, ++ 0xff08, ++ 0xff02, ++ 0xff80, ++ 0xff20, ++ 0xf01f, ++ 0xf817, ++ 0xfa15, ++ 0xf295, ++ 0xf0b5, ++ 0xf03d, ++ 0xffff, ++ 0xffff, ++ 0xf82a, ++ 0xfa0a, ++ 0xfa82, ++ 0xfaa0, ++ 0xf2a8, ++ 0xf0aa, ++ 0xffff, ++ 0xffff, ++ 0xf002, ++ 0xf800, ++ 0xf200, ++ 0xf080, ++ 0xf020, ++ 0xf008, ++ 0xffff, ++ 0xffff, ++ 0xf00a, ++ 0xf802, ++ 0xfa00, ++ 0xf280, ++ 0xf0a0, ++ 0xf028, ++ 0xffff, ++ 0xffff, ++}; ++ ++static const u32 pltlut_tbl_rev0[] = { ++ 0x76540123, ++ 0x62407351, ++ 0x76543201, ++ 0x76540213, ++ 0x76540123, ++ 0x76430521, ++}; ++ ++static const u32 tdi_tbl20_ant0_rev0[] = { ++ 0x00091226, ++ 0x000a1429, ++ 0x000b56ad, ++ 0x000c58b0, ++ 0x000d5ab3, ++ 0x000e9cb6, ++ 0x000f9eba, ++ 0x0000c13d, ++ 0x00020301, ++ 0x00030504, ++ 0x00040708, ++ 0x0005090b, ++ 0x00064b8e, ++ 0x00095291, ++ 0x000a5494, ++ 0x000b9718, ++ 0x000c9927, ++ 0x000d9b2a, ++ 0x000edd2e, ++ 0x000fdf31, ++ 0x000101b4, ++ 0x000243b7, ++ 0x000345bb, ++ 0x000447be, ++ 0x00058982, ++ 0x00068c05, ++ 0x00099309, ++ 0x000a950c, ++ 0x000bd78f, ++ 0x000cd992, ++ 0x000ddb96, ++ 0x000f1d99, ++ 0x00005fa8, ++ 0x0001422c, ++ 0x0002842f, ++ 0x00038632, ++ 0x00048835, ++ 0x0005ca38, ++ 0x0006ccbc, ++ 0x0009d3bf, ++ 0x000b1603, ++ 0x000c1806, ++ 0x000d1a0a, ++ 0x000e1c0d, ++ 0x000f5e10, ++ 0x00008093, ++ 0x00018297, ++ 0x0002c49a, ++ 0x0003c680, ++ 0x0004c880, ++ 0x00060b00, ++ 0x00070d00, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 tdi_tbl20_ant1_rev0[] = { ++ 0x00014b26, ++ 0x00028d29, ++ 0x000393ad, ++ 0x00049630, ++ 0x0005d833, ++ 0x0006da36, ++ 0x00099c3a, ++ 0x000a9e3d, ++ 0x000bc081, ++ 0x000cc284, ++ 0x000dc488, ++ 0x000f068b, ++ 0x0000488e, ++ 0x00018b91, ++ 0x0002d214, ++ 0x0003d418, ++ 0x0004d6a7, ++ 0x000618aa, ++ 0x00071aae, ++ 0x0009dcb1, ++ 0x000b1eb4, ++ 0x000c0137, ++ 0x000d033b, ++ 0x000e053e, ++ 0x000f4702, ++ 0x00008905, ++ 0x00020c09, ++ 0x0003128c, ++ 0x0004148f, ++ 0x00051712, ++ 0x00065916, ++ 0x00091b19, ++ 0x000a1d28, ++ 0x000b5f2c, ++ 0x000c41af, ++ 0x000d43b2, ++ 0x000e85b5, ++ 0x000f87b8, ++ 0x0000c9bc, ++ 0x00024cbf, ++ 0x00035303, ++ 0x00045506, ++ 0x0005978a, ++ 0x0006998d, ++ 0x00095b90, ++ 0x000a5d93, ++ 0x000b9f97, ++ 0x000c821a, ++ 0x000d8400, ++ 0x000ec600, ++ 0x000fc800, ++ 0x00010a00, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 tdi_tbl40_ant0_rev0[] = { ++ 0x0011a346, ++ 0x00136ccf, ++ 0x0014f5d9, ++ 0x001641e2, ++ 0x0017cb6b, ++ 0x00195475, ++ 0x001b2383, ++ 0x001cad0c, ++ 0x001e7616, ++ 0x0000821f, ++ 0x00020ba8, ++ 0x0003d4b2, ++ 0x00056447, ++ 0x00072dd0, ++ 0x0008b6da, ++ 0x000a02e3, ++ 0x000b8c6c, ++ 0x000d15f6, ++ 0x0011e484, ++ 0x0013ae0d, ++ 0x00153717, ++ 0x00168320, ++ 0x00180ca9, ++ 0x00199633, ++ 0x001b6548, ++ 0x001ceed1, ++ 0x001eb7db, ++ 0x0000c3e4, ++ 0x00024d6d, ++ 0x000416f7, ++ 0x0005a585, ++ 0x00076f0f, ++ 0x0008f818, ++ 0x000a4421, ++ 0x000bcdab, ++ 0x000d9734, ++ 0x00122649, ++ 0x0013efd2, ++ 0x001578dc, ++ 0x0016c4e5, ++ 0x00184e6e, ++ 0x001a17f8, ++ 0x001ba686, ++ 0x001d3010, ++ 0x001ef999, ++ 0x00010522, ++ 0x00028eac, ++ 0x00045835, ++ 0x0005e74a, ++ 0x0007b0d3, ++ 0x00093a5d, ++ 0x000a85e6, ++ 0x000c0f6f, ++ 0x000dd8f9, ++ 0x00126787, ++ 0x00143111, ++ 0x0015ba9a, ++ 0x00170623, ++ 0x00188fad, ++ 0x001a5936, ++ 0x001be84b, ++ 0x001db1d4, ++ 0x001f3b5e, ++ 0x000146e7, ++ 0x00031070, ++ 0x000499fa, ++ 0x00062888, ++ 0x0007f212, ++ 0x00097b9b, ++ 0x000ac7a4, ++ 0x000c50ae, ++ 0x000e1a37, ++ 0x0012a94c, ++ 0x001472d5, ++ 0x0015fc5f, ++ 0x00174868, ++ 0x0018d171, ++ 0x001a9afb, ++ 0x001c2989, ++ 0x001df313, ++ 0x001f7c9c, ++ 0x000188a5, ++ 0x000351af, ++ 0x0004db38, ++ 0x0006aa4d, ++ 0x000833d7, ++ 0x0009bd60, ++ 0x000b0969, ++ 0x000c9273, ++ 0x000e5bfc, ++ 0x00132a8a, ++ 0x0014b414, ++ 0x00163d9d, ++ 0x001789a6, ++ 0x001912b0, ++ 0x001adc39, ++ 0x001c6bce, ++ 0x001e34d8, ++ 0x001fbe61, ++ 0x0001ca6a, ++ 0x00039374, ++ 0x00051cfd, ++ 0x0006ec0b, ++ 0x00087515, ++ 0x0009fe9e, ++ 0x000b4aa7, ++ 0x000cd3b1, ++ 0x000e9d3a, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 tdi_tbl40_ant1_rev0[] = { ++ 0x001edb36, ++ 0x000129ca, ++ 0x0002b353, ++ 0x00047cdd, ++ 0x0005c8e6, ++ 0x000791ef, ++ 0x00091bf9, ++ 0x000aaa07, ++ 0x000c3391, ++ 0x000dfd1a, ++ 0x00120923, ++ 0x0013d22d, ++ 0x00155c37, ++ 0x0016eacb, ++ 0x00187454, ++ 0x001a3dde, ++ 0x001b89e7, ++ 0x001d12f0, ++ 0x001f1cfa, ++ 0x00016b88, ++ 0x00033492, ++ 0x0004be1b, ++ 0x00060a24, ++ 0x0007d32e, ++ 0x00095d38, ++ 0x000aec4c, ++ 0x000c7555, ++ 0x000e3edf, ++ 0x00124ae8, ++ 0x001413f1, ++ 0x0015a37b, ++ 0x00172c89, ++ 0x0018b593, ++ 0x001a419c, ++ 0x001bcb25, ++ 0x001d942f, ++ 0x001f63b9, ++ 0x0001ad4d, ++ 0x00037657, ++ 0x0004c260, ++ 0x00068be9, ++ 0x000814f3, ++ 0x0009a47c, ++ 0x000b2d8a, ++ 0x000cb694, ++ 0x000e429d, ++ 0x00128c26, ++ 0x001455b0, ++ 0x0015e4ba, ++ 0x00176e4e, ++ 0x0018f758, ++ 0x001a8361, ++ 0x001c0cea, ++ 0x001dd674, ++ 0x001fa57d, ++ 0x0001ee8b, ++ 0x0003b795, ++ 0x0005039e, ++ 0x0006cd27, ++ 0x000856b1, ++ 0x0009e5c6, ++ 0x000b6f4f, ++ 0x000cf859, ++ 0x000e8462, ++ 0x00130deb, ++ 0x00149775, ++ 0x00162603, ++ 0x0017af8c, ++ 0x00193896, ++ 0x001ac49f, ++ 0x001c4e28, ++ 0x001e17b2, ++ 0x0000a6c7, ++ 0x00023050, ++ 0x0003f9da, ++ 0x00054563, ++ 0x00070eec, ++ 0x00089876, ++ 0x000a2704, ++ 0x000bb08d, ++ 0x000d3a17, ++ 0x001185a0, ++ 0x00134f29, ++ 0x0014d8b3, ++ 0x001667c8, ++ 0x0017f151, ++ 0x00197adb, ++ 0x001b0664, ++ 0x001c8fed, ++ 0x001e5977, ++ 0x0000e805, ++ 0x0002718f, ++ 0x00043b18, ++ 0x000586a1, ++ 0x0007502b, ++ 0x0008d9b4, ++ 0x000a68c9, ++ 0x000bf252, ++ 0x000dbbdc, ++ 0x0011c7e5, ++ 0x001390ee, ++ 0x00151a78, ++ 0x0016a906, ++ 0x00183290, ++ 0x0019bc19, ++ 0x001b4822, ++ 0x001cd12c, ++ 0x001e9ab5, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u16 bdi_tbl_rev0[] = { ++ 0x0070, ++ 0x0126, ++ 0x012c, ++ 0x0246, ++ 0x048d, ++ 0x04d2, ++}; ++ ++static const u32 chanest_tbl_rev0[] = { ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++}; ++ ++static const u8 mcs_tbl_rev0[] = { ++ 0x00, ++ 0x08, ++ 0x0a, ++ 0x10, ++ 0x12, ++ 0x19, ++ 0x1a, ++ 0x1c, ++ 0x40, ++ 0x48, ++ 0x4a, ++ 0x50, ++ 0x52, ++ 0x59, ++ 0x5a, ++ 0x5c, ++ 0x80, ++ 0x88, ++ 0x8a, ++ 0x90, ++ 0x92, ++ 0x99, ++ 0x9a, ++ 0x9c, ++ 0xc0, ++ 0xc8, ++ 0xca, ++ 0xd0, ++ 0xd2, ++ 0xd9, ++ 0xda, ++ 0xdc, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x01, ++ 0x02, ++ 0x04, ++ 0x08, ++ 0x09, ++ 0x0a, ++ 0x0c, ++ 0x10, ++ 0x11, ++ 0x12, ++ 0x14, ++ 0x18, ++ 0x19, ++ 0x1a, ++ 0x1c, ++ 0x20, ++ 0x21, ++ 0x22, ++ 0x24, ++ 0x40, ++ 0x41, ++ 0x42, ++ 0x44, ++ 0x48, ++ 0x49, ++ 0x4a, ++ 0x4c, ++ 0x50, ++ 0x51, ++ 0x52, ++ 0x54, ++ 0x58, ++ 0x59, ++ 0x5a, ++ 0x5c, ++ 0x60, ++ 0x61, ++ 0x62, ++ 0x64, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++}; ++ ++static const u32 noise_var_tbl0_rev0[] = { ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++}; ++ ++static const u32 noise_var_tbl1_rev0[] = { ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++}; ++ ++static const u8 est_pwr_lut_core0_rev0[] = { ++ 0x50, ++ 0x4f, ++ 0x4e, ++ 0x4d, ++ 0x4c, ++ 0x4b, ++ 0x4a, ++ 0x49, ++ 0x48, ++ 0x47, ++ 0x46, ++ 0x45, ++ 0x44, ++ 0x43, ++ 0x42, ++ 0x41, ++ 0x40, ++ 0x3f, ++ 0x3e, ++ 0x3d, ++ 0x3c, ++ 0x3b, ++ 0x3a, ++ 0x39, ++ 0x38, ++ 0x37, ++ 0x36, ++ 0x35, ++ 0x34, ++ 0x33, ++ 0x32, ++ 0x31, ++ 0x30, ++ 0x2f, ++ 0x2e, ++ 0x2d, ++ 0x2c, ++ 0x2b, ++ 0x2a, ++ 0x29, ++ 0x28, ++ 0x27, ++ 0x26, ++ 0x25, ++ 0x24, ++ 0x23, ++ 0x22, ++ 0x21, ++ 0x20, ++ 0x1f, ++ 0x1e, ++ 0x1d, ++ 0x1c, ++ 0x1b, ++ 0x1a, ++ 0x19, ++ 0x18, ++ 0x17, ++ 0x16, ++ 0x15, ++ 0x14, ++ 0x13, ++ 0x12, ++ 0x11, ++}; ++ ++static const u8 est_pwr_lut_core1_rev0[] = { ++ 0x50, ++ 0x4f, ++ 0x4e, ++ 0x4d, ++ 0x4c, ++ 0x4b, ++ 0x4a, ++ 0x49, ++ 0x48, ++ 0x47, ++ 0x46, ++ 0x45, ++ 0x44, ++ 0x43, ++ 0x42, ++ 0x41, ++ 0x40, ++ 0x3f, ++ 0x3e, ++ 0x3d, ++ 0x3c, ++ 0x3b, ++ 0x3a, ++ 0x39, ++ 0x38, ++ 0x37, ++ 0x36, ++ 0x35, ++ 0x34, ++ 0x33, ++ 0x32, ++ 0x31, ++ 0x30, ++ 0x2f, ++ 0x2e, ++ 0x2d, ++ 0x2c, ++ 0x2b, ++ 0x2a, ++ 0x29, ++ 0x28, ++ 0x27, ++ 0x26, ++ 0x25, ++ 0x24, ++ 0x23, ++ 0x22, ++ 0x21, ++ 0x20, ++ 0x1f, ++ 0x1e, ++ 0x1d, ++ 0x1c, ++ 0x1b, ++ 0x1a, ++ 0x19, ++ 0x18, ++ 0x17, ++ 0x16, ++ 0x15, ++ 0x14, ++ 0x13, ++ 0x12, ++ 0x11, ++}; ++ ++static const u8 adj_pwr_lut_core0_rev0[] = { ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++}; ++ ++static const u8 adj_pwr_lut_core1_rev0[] = { ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++}; ++ ++static const u32 gainctrl_lut_core0_rev0[] = { ++ 0x03cc2b44, ++ 0x03cc2b42, ++ 0x03cc2b40, ++ 0x03cc2b3e, ++ 0x03cc2b3d, ++ 0x03cc2b3b, ++ 0x03c82b44, ++ 0x03c82b42, ++ 0x03c82b40, ++ 0x03c82b3e, ++ 0x03c82b3d, ++ 0x03c82b3b, ++ 0x03c82b39, ++ 0x03c82b38, ++ 0x03c82b36, ++ 0x03c82b34, ++ 0x03c42b44, ++ 0x03c42b42, ++ 0x03c42b40, ++ 0x03c42b3e, ++ 0x03c42b3d, ++ 0x03c42b3b, ++ 0x03c42b39, ++ 0x03c42b38, ++ 0x03c42b36, ++ 0x03c42b34, ++ 0x03c42b33, ++ 0x03c42b32, ++ 0x03c42b30, ++ 0x03c42b2f, ++ 0x03c42b2d, ++ 0x03c02b44, ++ 0x03c02b42, ++ 0x03c02b40, ++ 0x03c02b3e, ++ 0x03c02b3d, ++ 0x03c02b3b, ++ 0x03c02b39, ++ 0x03c02b38, ++ 0x03c02b36, ++ 0x03c02b34, ++ 0x03b02b44, ++ 0x03b02b42, ++ 0x03b02b40, ++ 0x03b02b3e, ++ 0x03b02b3d, ++ 0x03b02b3b, ++ 0x03b02b39, ++ 0x03b02b38, ++ 0x03b02b36, ++ 0x03b02b34, ++ 0x03b02b33, ++ 0x03b02b32, ++ 0x03b02b30, ++ 0x03b02b2f, ++ 0x03b02b2d, ++ 0x03a02b44, ++ 0x03a02b42, ++ 0x03a02b40, ++ 0x03a02b3e, ++ 0x03a02b3d, ++ 0x03a02b3b, ++ 0x03a02b39, ++ 0x03a02b38, ++ 0x03a02b36, ++ 0x03a02b34, ++ 0x03902b44, ++ 0x03902b42, ++ 0x03902b40, ++ 0x03902b3e, ++ 0x03902b3d, ++ 0x03902b3b, ++ 0x03902b39, ++ 0x03902b38, ++ 0x03902b36, ++ 0x03902b34, ++ 0x03902b33, ++ 0x03902b32, ++ 0x03902b30, ++ 0x03802b44, ++ 0x03802b42, ++ 0x03802b40, ++ 0x03802b3e, ++ 0x03802b3d, ++ 0x03802b3b, ++ 0x03802b39, ++ 0x03802b38, ++ 0x03802b36, ++ 0x03802b34, ++ 0x03802b33, ++ 0x03802b32, ++ 0x03802b30, ++ 0x03802b2f, ++ 0x03802b2d, ++ 0x03802b2c, ++ 0x03802b2b, ++ 0x03802b2a, ++ 0x03802b29, ++ 0x03802b27, ++ 0x03802b26, ++ 0x03802b25, ++ 0x03802b24, ++ 0x03802b23, ++ 0x03802b22, ++ 0x03802b21, ++ 0x03802b20, ++ 0x03802b1f, ++ 0x03802b1e, ++ 0x03802b1e, ++ 0x03802b1d, ++ 0x03802b1c, ++ 0x03802b1b, ++ 0x03802b1a, ++ 0x03802b1a, ++ 0x03802b19, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x00002b00, ++}; ++ ++static const u32 gainctrl_lut_core1_rev0[] = { ++ 0x03cc2b44, ++ 0x03cc2b42, ++ 0x03cc2b40, ++ 0x03cc2b3e, ++ 0x03cc2b3d, ++ 0x03cc2b3b, ++ 0x03c82b44, ++ 0x03c82b42, ++ 0x03c82b40, ++ 0x03c82b3e, ++ 0x03c82b3d, ++ 0x03c82b3b, ++ 0x03c82b39, ++ 0x03c82b38, ++ 0x03c82b36, ++ 0x03c82b34, ++ 0x03c42b44, ++ 0x03c42b42, ++ 0x03c42b40, ++ 0x03c42b3e, ++ 0x03c42b3d, ++ 0x03c42b3b, ++ 0x03c42b39, ++ 0x03c42b38, ++ 0x03c42b36, ++ 0x03c42b34, ++ 0x03c42b33, ++ 0x03c42b32, ++ 0x03c42b30, ++ 0x03c42b2f, ++ 0x03c42b2d, ++ 0x03c02b44, ++ 0x03c02b42, ++ 0x03c02b40, ++ 0x03c02b3e, ++ 0x03c02b3d, ++ 0x03c02b3b, ++ 0x03c02b39, ++ 0x03c02b38, ++ 0x03c02b36, ++ 0x03c02b34, ++ 0x03b02b44, ++ 0x03b02b42, ++ 0x03b02b40, ++ 0x03b02b3e, ++ 0x03b02b3d, ++ 0x03b02b3b, ++ 0x03b02b39, ++ 0x03b02b38, ++ 0x03b02b36, ++ 0x03b02b34, ++ 0x03b02b33, ++ 0x03b02b32, ++ 0x03b02b30, ++ 0x03b02b2f, ++ 0x03b02b2d, ++ 0x03a02b44, ++ 0x03a02b42, ++ 0x03a02b40, ++ 0x03a02b3e, ++ 0x03a02b3d, ++ 0x03a02b3b, ++ 0x03a02b39, ++ 0x03a02b38, ++ 0x03a02b36, ++ 0x03a02b34, ++ 0x03902b44, ++ 0x03902b42, ++ 0x03902b40, ++ 0x03902b3e, ++ 0x03902b3d, ++ 0x03902b3b, ++ 0x03902b39, ++ 0x03902b38, ++ 0x03902b36, ++ 0x03902b34, ++ 0x03902b33, ++ 0x03902b32, ++ 0x03902b30, ++ 0x03802b44, ++ 0x03802b42, ++ 0x03802b40, ++ 0x03802b3e, ++ 0x03802b3d, ++ 0x03802b3b, ++ 0x03802b39, ++ 0x03802b38, ++ 0x03802b36, ++ 0x03802b34, ++ 0x03802b33, ++ 0x03802b32, ++ 0x03802b30, ++ 0x03802b2f, ++ 0x03802b2d, ++ 0x03802b2c, ++ 0x03802b2b, ++ 0x03802b2a, ++ 0x03802b29, ++ 0x03802b27, ++ 0x03802b26, ++ 0x03802b25, ++ 0x03802b24, ++ 0x03802b23, ++ 0x03802b22, ++ 0x03802b21, ++ 0x03802b20, ++ 0x03802b1f, ++ 0x03802b1e, ++ 0x03802b1e, ++ 0x03802b1d, ++ 0x03802b1c, ++ 0x03802b1b, ++ 0x03802b1a, ++ 0x03802b1a, ++ 0x03802b19, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x00002b00, ++}; ++ ++static const u32 iq_lut_core0_rev0[] = { ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++}; ++ ++static const u32 iq_lut_core1_rev0[] = { ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++}; ++ ++static const u16 loft_lut_core0_rev0[] = { ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++}; ++ ++static const u16 loft_lut_core1_rev0[] = { ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++}; ++ ++const struct phytbl_info mimophytbl_info_rev0_volatile[] = { ++ {&bdi_tbl_rev0, sizeof(bdi_tbl_rev0) / sizeof(bdi_tbl_rev0[0]), 21, 0, ++ 16} ++ , ++ {&pltlut_tbl_rev0, sizeof(pltlut_tbl_rev0) / sizeof(pltlut_tbl_rev0[0]), ++ 20, 0, 32} ++ , ++ {&gainctrl_lut_core0_rev0, ++ sizeof(gainctrl_lut_core0_rev0) / sizeof(gainctrl_lut_core0_rev0[0]), ++ 26, 192, 32} ++ , ++ {&gainctrl_lut_core1_rev0, ++ sizeof(gainctrl_lut_core1_rev0) / sizeof(gainctrl_lut_core1_rev0[0]), ++ 27, 192, 32} ++ , ++ ++ {&est_pwr_lut_core0_rev0, ++ sizeof(est_pwr_lut_core0_rev0) / sizeof(est_pwr_lut_core0_rev0[0]), 26, ++ 0, 8} ++ , ++ {&est_pwr_lut_core1_rev0, ++ sizeof(est_pwr_lut_core1_rev0) / sizeof(est_pwr_lut_core1_rev0[0]), 27, ++ 0, 8} ++ , ++ {&adj_pwr_lut_core0_rev0, ++ sizeof(adj_pwr_lut_core0_rev0) / sizeof(adj_pwr_lut_core0_rev0[0]), 26, ++ 64, 8} ++ , ++ {&adj_pwr_lut_core1_rev0, ++ sizeof(adj_pwr_lut_core1_rev0) / sizeof(adj_pwr_lut_core1_rev0[0]), 27, ++ 64, 8} ++ , ++ {&iq_lut_core0_rev0, ++ sizeof(iq_lut_core0_rev0) / sizeof(iq_lut_core0_rev0[0]), 26, 320, 32} ++ , ++ {&iq_lut_core1_rev0, ++ sizeof(iq_lut_core1_rev0) / sizeof(iq_lut_core1_rev0[0]), 27, 320, 32} ++ , ++ {&loft_lut_core0_rev0, ++ sizeof(loft_lut_core0_rev0) / sizeof(loft_lut_core0_rev0[0]), 26, 448, ++ 16} ++ , ++ {&loft_lut_core1_rev0, ++ sizeof(loft_lut_core1_rev0) / sizeof(loft_lut_core1_rev0[0]), 27, 448, ++ 16} ++ , ++}; ++ ++const struct phytbl_info mimophytbl_info_rev0[] = { ++ {&frame_struct_rev0, ++ sizeof(frame_struct_rev0) / sizeof(frame_struct_rev0[0]), 10, 0, 32} ++ , ++ {&frame_lut_rev0, sizeof(frame_lut_rev0) / sizeof(frame_lut_rev0[0]), ++ 24, 0, 8} ++ , ++ {&tmap_tbl_rev0, sizeof(tmap_tbl_rev0) / sizeof(tmap_tbl_rev0[0]), 12, ++ 0, 32} ++ , ++ {&tdtrn_tbl_rev0, sizeof(tdtrn_tbl_rev0) / sizeof(tdtrn_tbl_rev0[0]), ++ 14, 0, 32} ++ , ++ {&intlv_tbl_rev0, sizeof(intlv_tbl_rev0) / sizeof(intlv_tbl_rev0[0]), ++ 13, 0, 32} ++ , ++ {&pilot_tbl_rev0, sizeof(pilot_tbl_rev0) / sizeof(pilot_tbl_rev0[0]), ++ 11, 0, 16} ++ , ++ {&tdi_tbl20_ant0_rev0, ++ sizeof(tdi_tbl20_ant0_rev0) / sizeof(tdi_tbl20_ant0_rev0[0]), 19, 128, ++ 32} ++ , ++ {&tdi_tbl20_ant1_rev0, ++ sizeof(tdi_tbl20_ant1_rev0) / sizeof(tdi_tbl20_ant1_rev0[0]), 19, 256, ++ 32} ++ , ++ {&tdi_tbl40_ant0_rev0, ++ sizeof(tdi_tbl40_ant0_rev0) / sizeof(tdi_tbl40_ant0_rev0[0]), 19, 640, ++ 32} ++ , ++ {&tdi_tbl40_ant1_rev0, ++ sizeof(tdi_tbl40_ant1_rev0) / sizeof(tdi_tbl40_ant1_rev0[0]), 19, 768, ++ 32} ++ , ++ {&chanest_tbl_rev0, ++ sizeof(chanest_tbl_rev0) / sizeof(chanest_tbl_rev0[0]), 22, 0, 32} ++ , ++ {&mcs_tbl_rev0, sizeof(mcs_tbl_rev0) / sizeof(mcs_tbl_rev0[0]), 18, 0, ++ 8} ++ , ++ {&noise_var_tbl0_rev0, ++ sizeof(noise_var_tbl0_rev0) / sizeof(noise_var_tbl0_rev0[0]), 16, 0, ++ 32} ++ , ++ {&noise_var_tbl1_rev0, ++ sizeof(noise_var_tbl1_rev0) / sizeof(noise_var_tbl1_rev0[0]), 16, 128, ++ 32} ++ , ++}; ++ ++const u32 mimophytbl_info_sz_rev0 = ++ sizeof(mimophytbl_info_rev0) / sizeof(mimophytbl_info_rev0[0]); ++const u32 mimophytbl_info_sz_rev0_volatile = ++ sizeof(mimophytbl_info_rev0_volatile) / ++ sizeof(mimophytbl_info_rev0_volatile[0]); ++ ++static const u16 ant_swctrl_tbl_rev3[] = { ++ 0x0082, ++ 0x0082, ++ 0x0211, ++ 0x0222, ++ 0x0328, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0144, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0188, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0082, ++ 0x0082, ++ 0x0211, ++ 0x0222, ++ 0x0328, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0144, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0188, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++}; ++ ++static const u16 ant_swctrl_tbl_rev3_1[] = { ++ 0x0022, ++ 0x0022, ++ 0x0011, ++ 0x0022, ++ 0x0022, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0011, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0022, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0022, ++ 0x0022, ++ 0x0011, ++ 0x0022, ++ 0x0022, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0011, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0022, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++}; ++ ++static const u16 ant_swctrl_tbl_rev3_2[] = { ++ 0x0088, ++ 0x0088, ++ 0x0044, ++ 0x0088, ++ 0x0088, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0044, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0088, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0088, ++ 0x0088, ++ 0x0044, ++ 0x0088, ++ 0x0088, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0044, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0088, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++}; ++ ++static const u16 ant_swctrl_tbl_rev3_3[] = { ++ 0x022, ++ 0x022, ++ 0x011, ++ 0x022, ++ 0x000, ++ 0x000, ++ 0x000, ++ 0x000, ++ 0x011, ++ 0x000, ++ 0x000, ++ 0x000, ++ 0x022, ++ 0x000, ++ 0x000, ++ 0x3cc, ++ 0x022, ++ 0x022, ++ 0x011, ++ 0x022, ++ 0x000, ++ 0x000, ++ 0x000, ++ 0x000, ++ 0x011, ++ 0x000, ++ 0x000, ++ 0x000, ++ 0x022, ++ 0x000, ++ 0x000, ++ 0x3cc ++}; ++ ++static const u32 frame_struct_rev3[] = { ++ 0x08004a04, ++ 0x00100000, ++ 0x01000a05, ++ 0x00100020, ++ 0x09804506, ++ 0x00100030, ++ 0x09804507, ++ 0x00100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x08004a0c, ++ 0x00100004, ++ 0x01000a0d, ++ 0x00100024, ++ 0x0980450e, ++ 0x00100034, ++ 0x0980450f, ++ 0x00100034, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000a04, ++ 0x00100000, ++ 0x11008a05, ++ 0x00100020, ++ 0x1980c506, ++ 0x00100030, ++ 0x21810506, ++ 0x00100030, ++ 0x21810506, ++ 0x00100030, ++ 0x01800504, ++ 0x00100030, ++ 0x11808505, ++ 0x00100030, ++ 0x29814507, ++ 0x01100030, ++ 0x00000a04, ++ 0x00100000, ++ 0x11008a05, ++ 0x00100020, ++ 0x21810506, ++ 0x00100030, ++ 0x21810506, ++ 0x00100030, ++ 0x29814507, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000a0c, ++ 0x00100008, ++ 0x11008a0d, ++ 0x00100028, ++ 0x1980c50e, ++ 0x00100038, ++ 0x2181050e, ++ 0x00100038, ++ 0x2181050e, ++ 0x00100038, ++ 0x0180050c, ++ 0x00100038, ++ 0x1180850d, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000a0c, ++ 0x00100008, ++ 0x11008a0d, ++ 0x00100028, ++ 0x2181050e, ++ 0x00100038, ++ 0x2181050e, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x08004a04, ++ 0x00100000, ++ 0x01000a05, ++ 0x00100020, ++ 0x1980c506, ++ 0x00100030, ++ 0x1980c506, ++ 0x00100030, ++ 0x11808504, ++ 0x00100030, ++ 0x3981ca05, ++ 0x00100030, ++ 0x29814507, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x10008a04, ++ 0x00100000, ++ 0x3981ca05, ++ 0x00100030, ++ 0x1980c506, ++ 0x00100030, ++ 0x29814507, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x08004a0c, ++ 0x00100008, ++ 0x01000a0d, ++ 0x00100028, ++ 0x1980c50e, ++ 0x00100038, ++ 0x1980c50e, ++ 0x00100038, ++ 0x1180850c, ++ 0x00100038, ++ 0x3981ca0d, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x10008a0c, ++ 0x00100008, ++ 0x3981ca0d, ++ 0x00100038, ++ 0x1980c50e, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x40021404, ++ 0x00100000, ++ 0x02001405, ++ 0x00100040, ++ 0x0b004a06, ++ 0x01900060, ++ 0x13008a06, ++ 0x01900060, ++ 0x13008a06, ++ 0x01900060, ++ 0x43020a04, ++ 0x00100060, ++ 0x1b00ca05, ++ 0x00100060, ++ 0x23010a07, ++ 0x01500060, ++ 0x40021404, ++ 0x00100000, ++ 0x1a00d405, ++ 0x00100040, ++ 0x13008a06, ++ 0x01900060, ++ 0x13008a06, ++ 0x01900060, ++ 0x23010a07, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100010, ++ 0x0200140d, ++ 0x00100050, ++ 0x0b004a0e, ++ 0x01900070, ++ 0x13008a0e, ++ 0x01900070, ++ 0x13008a0e, ++ 0x01900070, ++ 0x43020a0c, ++ 0x00100070, ++ 0x1b00ca0d, ++ 0x00100070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x4002140c, ++ 0x00100010, ++ 0x1a00d40d, ++ 0x00100050, ++ 0x13008a0e, ++ 0x01900070, ++ 0x13008a0e, ++ 0x01900070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x50029404, ++ 0x00100000, ++ 0x32019405, ++ 0x00100040, ++ 0x0b004a06, ++ 0x01900060, ++ 0x0b004a06, ++ 0x01900060, ++ 0x5b02ca04, ++ 0x00100060, ++ 0x3b01d405, ++ 0x00100060, ++ 0x23010a07, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x5802d404, ++ 0x00100000, ++ 0x3b01d405, ++ 0x00100060, ++ 0x0b004a06, ++ 0x01900060, ++ 0x23010a07, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x5002940c, ++ 0x00100010, ++ 0x3201940d, ++ 0x00100050, ++ 0x0b004a0e, ++ 0x01900070, ++ 0x0b004a0e, ++ 0x01900070, ++ 0x5b02ca0c, ++ 0x00100070, ++ 0x3b01d40d, ++ 0x00100070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x5802d40c, ++ 0x00100010, ++ 0x3b01d40d, ++ 0x00100070, ++ 0x0b004a0e, ++ 0x01900070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x40021404, ++ 0x000f4800, ++ 0x62031405, ++ 0x00100040, ++ 0x53028a06, ++ 0x01900060, ++ 0x53028a07, ++ 0x01900060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x000f4808, ++ 0x6203140d, ++ 0x00100048, ++ 0x53028a0e, ++ 0x01900068, ++ 0x53028a0f, ++ 0x01900068, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000a0c, ++ 0x00100004, ++ 0x11008a0d, ++ 0x00100024, ++ 0x1980c50e, ++ 0x00100034, ++ 0x2181050e, ++ 0x00100034, ++ 0x2181050e, ++ 0x00100034, ++ 0x0180050c, ++ 0x00100038, ++ 0x1180850d, ++ 0x00100038, ++ 0x1181850d, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000a0c, ++ 0x00100008, ++ 0x11008a0d, ++ 0x00100028, ++ 0x2181050e, ++ 0x00100038, ++ 0x2181050e, ++ 0x00100038, ++ 0x1181850d, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x08004a04, ++ 0x00100000, ++ 0x01000a05, ++ 0x00100020, ++ 0x0180c506, ++ 0x00100030, ++ 0x0180c506, ++ 0x00100030, ++ 0x2180c50c, ++ 0x00100030, ++ 0x49820a0d, ++ 0x0016a130, ++ 0x41824a0d, ++ 0x0016a130, ++ 0x2981450f, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x2000ca0c, ++ 0x00100000, ++ 0x49820a0d, ++ 0x0016a130, ++ 0x1980c50e, ++ 0x00100030, ++ 0x41824a0d, ++ 0x0016a130, ++ 0x2981450f, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100008, ++ 0x0200140d, ++ 0x00100048, ++ 0x0b004a0e, ++ 0x01900068, ++ 0x13008a0e, ++ 0x01900068, ++ 0x13008a0e, ++ 0x01900068, ++ 0x43020a0c, ++ 0x00100070, ++ 0x1b00ca0d, ++ 0x00100070, ++ 0x1b014a0d, ++ 0x00100070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100010, ++ 0x1a00d40d, ++ 0x00100050, ++ 0x13008a0e, ++ 0x01900070, ++ 0x13008a0e, ++ 0x01900070, ++ 0x1b014a0d, ++ 0x00100070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x50029404, ++ 0x00100000, ++ 0x32019405, ++ 0x00100040, ++ 0x03004a06, ++ 0x01900060, ++ 0x03004a06, ++ 0x01900060, ++ 0x6b030a0c, ++ 0x00100060, ++ 0x4b02140d, ++ 0x0016a160, ++ 0x4302540d, ++ 0x0016a160, ++ 0x23010a0f, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x6b03140c, ++ 0x00100060, ++ 0x4b02140d, ++ 0x0016a160, ++ 0x0b004a0e, ++ 0x01900060, ++ 0x4302540d, ++ 0x0016a160, ++ 0x23010a0f, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x40021404, ++ 0x00100000, ++ 0x1a00d405, ++ 0x00100040, ++ 0x53028a06, ++ 0x01900060, ++ 0x5b02ca06, ++ 0x01900060, ++ 0x5b02ca06, ++ 0x01900060, ++ 0x43020a04, ++ 0x00100060, ++ 0x1b00ca05, ++ 0x00100060, ++ 0x53028a07, ++ 0x0190c060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100010, ++ 0x1a00d40d, ++ 0x00100050, ++ 0x53028a0e, ++ 0x01900070, ++ 0x5b02ca0e, ++ 0x01900070, ++ 0x5b02ca0e, ++ 0x01900070, ++ 0x43020a0c, ++ 0x00100070, ++ 0x1b00ca0d, ++ 0x00100070, ++ 0x53028a0f, ++ 0x0190c070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x40021404, ++ 0x00100000, ++ 0x1a00d405, ++ 0x00100040, ++ 0x5b02ca06, ++ 0x01900060, ++ 0x5b02ca06, ++ 0x01900060, ++ 0x53028a07, ++ 0x0190c060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100010, ++ 0x1a00d40d, ++ 0x00100050, ++ 0x5b02ca0e, ++ 0x01900070, ++ 0x5b02ca0e, ++ 0x01900070, ++ 0x53028a0f, ++ 0x0190c070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u16 pilot_tbl_rev3[] = { ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0xff0a, ++ 0xff82, ++ 0xffa0, ++ 0xff28, ++ 0xffff, ++ 0xffff, ++ 0xffff, ++ 0xffff, ++ 0xff82, ++ 0xffa0, ++ 0xff28, ++ 0xff0a, ++ 0xffff, ++ 0xffff, ++ 0xffff, ++ 0xffff, ++ 0xf83f, ++ 0xfa1f, ++ 0xfa97, ++ 0xfab5, ++ 0xf2bd, ++ 0xf0bf, ++ 0xffff, ++ 0xffff, ++ 0xf017, ++ 0xf815, ++ 0xf215, ++ 0xf095, ++ 0xf035, ++ 0xf01d, ++ 0xffff, ++ 0xffff, ++ 0xff08, ++ 0xff02, ++ 0xff80, ++ 0xff20, ++ 0xff08, ++ 0xff02, ++ 0xff80, ++ 0xff20, ++ 0xf01f, ++ 0xf817, ++ 0xfa15, ++ 0xf295, ++ 0xf0b5, ++ 0xf03d, ++ 0xffff, ++ 0xffff, ++ 0xf82a, ++ 0xfa0a, ++ 0xfa82, ++ 0xfaa0, ++ 0xf2a8, ++ 0xf0aa, ++ 0xffff, ++ 0xffff, ++ 0xf002, ++ 0xf800, ++ 0xf200, ++ 0xf080, ++ 0xf020, ++ 0xf008, ++ 0xffff, ++ 0xffff, ++ 0xf00a, ++ 0xf802, ++ 0xfa00, ++ 0xf280, ++ 0xf0a0, ++ 0xf028, ++ 0xffff, ++ 0xffff, ++}; ++ ++static const u32 tmap_tbl_rev3[] = { ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x000aa888, ++ 0x88880000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa2222220, ++ 0x22222222, ++ 0x22c22222, ++ 0x00000222, ++ 0x22000000, ++ 0x2222a222, ++ 0x22222222, ++ 0x222222a2, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00011111, ++ 0x11110000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0xa8aa88a0, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x00088aaa, ++ 0xaaaa0000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xaaa8aaa0, ++ 0x8aaa8aaa, ++ 0xaa8a8a8a, ++ 0x000aaa88, ++ 0x8aaa0000, ++ 0xaaa8a888, ++ 0x8aa88a8a, ++ 0x8a88a888, ++ 0x08080a00, ++ 0x0a08080a, ++ 0x080a0a08, ++ 0x00080808, ++ 0x080a0000, ++ 0x080a0808, ++ 0x080a0808, ++ 0x0a0a0a08, ++ 0xa0a0a0a0, ++ 0x80a0a080, ++ 0x8080a0a0, ++ 0x00008080, ++ 0x80a00000, ++ 0x80a080a0, ++ 0xa080a0a0, ++ 0x8080a0a0, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x99999000, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb90, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00aaa888, ++ 0x22000000, ++ 0x2222b222, ++ 0x22222222, ++ 0x222222b2, ++ 0xb2222220, ++ 0x22222222, ++ 0x22d22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x33000000, ++ 0x3333b333, ++ 0x33333333, ++ 0x333333b3, ++ 0xb3333330, ++ 0x33333333, ++ 0x33d33333, ++ 0x00000333, ++ 0x22000000, ++ 0x2222a222, ++ 0x22222222, ++ 0x222222a2, ++ 0xa2222220, ++ 0x22222222, ++ 0x22c22222, ++ 0x00000222, ++ 0x99b99b00, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb99, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x08aaa888, ++ 0x22222200, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0x22222222, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x11111111, ++ 0xf1111111, ++ 0x11111111, ++ 0x11f11111, ++ 0x01111111, ++ 0xbb9bb900, ++ 0xb9b9bb99, ++ 0xb99bbbbb, ++ 0xbbbb9b9b, ++ 0xb9bb99bb, ++ 0xb99999b9, ++ 0xb9b9b99b, ++ 0x00000bbb, ++ 0xaa000000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xa8aa88aa, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x0a888aaa, ++ 0xaa000000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xa8aa88a0, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x00000aaa, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0xbbbbbb00, ++ 0x999bbbbb, ++ 0x9bb99b9b, ++ 0xb9b9b9bb, ++ 0xb9b99bbb, ++ 0xb9b9b9bb, ++ 0xb9bb9b99, ++ 0x00000999, ++ 0x8a000000, ++ 0xaa88a888, ++ 0xa88888aa, ++ 0xa88a8a88, ++ 0xa88aa88a, ++ 0x88a8aaaa, ++ 0xa8aa8aaa, ++ 0x0888a88a, ++ 0x0b0b0b00, ++ 0x090b0b0b, ++ 0x0b090b0b, ++ 0x0909090b, ++ 0x09090b0b, ++ 0x09090b0b, ++ 0x09090b09, ++ 0x00000909, ++ 0x0a000000, ++ 0x0a080808, ++ 0x080a080a, ++ 0x080a0a08, ++ 0x080a080a, ++ 0x0808080a, ++ 0x0a0a0a08, ++ 0x0808080a, ++ 0xb0b0b000, ++ 0x9090b0b0, ++ 0x90b09090, ++ 0xb0b0b090, ++ 0xb0b090b0, ++ 0x90b0b0b0, ++ 0xb0b09090, ++ 0x00000090, ++ 0x80000000, ++ 0xa080a080, ++ 0xa08080a0, ++ 0xa0808080, ++ 0xa080a080, ++ 0x80a0a0a0, ++ 0xa0a080a0, ++ 0x00a0a0a0, ++ 0x22000000, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0xf2222220, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00000111, ++ 0x33000000, ++ 0x3333f333, ++ 0x33333333, ++ 0x333333f3, ++ 0xf3333330, ++ 0x33333333, ++ 0x33f33333, ++ 0x00000333, ++ 0x22000000, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0xf2222220, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x99000000, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb90, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88888000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00aaa888, ++ 0x88a88a00, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x08aaa888, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 intlv_tbl_rev3[] = { ++ 0x00802070, ++ 0x0671188d, ++ 0x0a60192c, ++ 0x0a300e46, ++ 0x00c1188d, ++ 0x080024d2, ++ 0x00000070, ++}; ++ ++static const u32 tdtrn_tbl_rev3[] = { ++ 0x061c061c, ++ 0x0050ee68, ++ 0xf592fe36, ++ 0xfe5212f6, ++ 0x00000c38, ++ 0xfe5212f6, ++ 0xf592fe36, ++ 0x0050ee68, ++ 0x061c061c, ++ 0xee680050, ++ 0xfe36f592, ++ 0x12f6fe52, ++ 0x0c380000, ++ 0x12f6fe52, ++ 0xfe36f592, ++ 0xee680050, ++ 0x061c061c, ++ 0x0050ee68, ++ 0xf592fe36, ++ 0xfe5212f6, ++ 0x00000c38, ++ 0xfe5212f6, ++ 0xf592fe36, ++ 0x0050ee68, ++ 0x061c061c, ++ 0xee680050, ++ 0xfe36f592, ++ 0x12f6fe52, ++ 0x0c380000, ++ 0x12f6fe52, ++ 0xfe36f592, ++ 0xee680050, ++ 0x05e305e3, ++ 0x004def0c, ++ 0xf5f3fe47, ++ 0xfe611246, ++ 0x00000bc7, ++ 0xfe611246, ++ 0xf5f3fe47, ++ 0x004def0c, ++ 0x05e305e3, ++ 0xef0c004d, ++ 0xfe47f5f3, ++ 0x1246fe61, ++ 0x0bc70000, ++ 0x1246fe61, ++ 0xfe47f5f3, ++ 0xef0c004d, ++ 0x05e305e3, ++ 0x004def0c, ++ 0xf5f3fe47, ++ 0xfe611246, ++ 0x00000bc7, ++ 0xfe611246, ++ 0xf5f3fe47, ++ 0x004def0c, ++ 0x05e305e3, ++ 0xef0c004d, ++ 0xfe47f5f3, ++ 0x1246fe61, ++ 0x0bc70000, ++ 0x1246fe61, ++ 0xfe47f5f3, ++ 0xef0c004d, ++ 0xfa58fa58, ++ 0xf895043b, ++ 0xff4c09c0, ++ 0xfbc6ffa8, ++ 0xfb84f384, ++ 0x0798f6f9, ++ 0x05760122, ++ 0x058409f6, ++ 0x0b500000, ++ 0x05b7f542, ++ 0x08860432, ++ 0x06ddfee7, ++ 0xfb84f384, ++ 0xf9d90664, ++ 0xf7e8025c, ++ 0x00fff7bd, ++ 0x05a805a8, ++ 0xf7bd00ff, ++ 0x025cf7e8, ++ 0x0664f9d9, ++ 0xf384fb84, ++ 0xfee706dd, ++ 0x04320886, ++ 0xf54205b7, ++ 0x00000b50, ++ 0x09f60584, ++ 0x01220576, ++ 0xf6f90798, ++ 0xf384fb84, ++ 0xffa8fbc6, ++ 0x09c0ff4c, ++ 0x043bf895, ++ 0x02d402d4, ++ 0x07de0270, ++ 0xfc96079c, ++ 0xf90afe94, ++ 0xfe00ff2c, ++ 0x02d4065d, ++ 0x092a0096, ++ 0x0014fbb8, ++ 0xfd2cfd2c, ++ 0x076afb3c, ++ 0x0096f752, ++ 0xf991fd87, ++ 0xfb2c0200, ++ 0xfeb8f960, ++ 0x08e0fc96, ++ 0x049802a8, ++ 0xfd2cfd2c, ++ 0x02a80498, ++ 0xfc9608e0, ++ 0xf960feb8, ++ 0x0200fb2c, ++ 0xfd87f991, ++ 0xf7520096, ++ 0xfb3c076a, ++ 0xfd2cfd2c, ++ 0xfbb80014, ++ 0x0096092a, ++ 0x065d02d4, ++ 0xff2cfe00, ++ 0xfe94f90a, ++ 0x079cfc96, ++ 0x027007de, ++ 0x02d402d4, ++ 0x027007de, ++ 0x079cfc96, ++ 0xfe94f90a, ++ 0xff2cfe00, ++ 0x065d02d4, ++ 0x0096092a, ++ 0xfbb80014, ++ 0xfd2cfd2c, ++ 0xfb3c076a, ++ 0xf7520096, ++ 0xfd87f991, ++ 0x0200fb2c, ++ 0xf960feb8, ++ 0xfc9608e0, ++ 0x02a80498, ++ 0xfd2cfd2c, ++ 0x049802a8, ++ 0x08e0fc96, ++ 0xfeb8f960, ++ 0xfb2c0200, ++ 0xf991fd87, ++ 0x0096f752, ++ 0x076afb3c, ++ 0xfd2cfd2c, ++ 0x0014fbb8, ++ 0x092a0096, ++ 0x02d4065d, ++ 0xfe00ff2c, ++ 0xf90afe94, ++ 0xfc96079c, ++ 0x07de0270, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x062a0000, ++ 0xfefa0759, ++ 0x08b80908, ++ 0xf396fc2d, ++ 0xf9d6045c, ++ 0xfc4ef608, ++ 0xf748f596, ++ 0x07b207bf, ++ 0x062a062a, ++ 0xf84ef841, ++ 0xf748f596, ++ 0x03b209f8, ++ 0xf9d6045c, ++ 0x0c6a03d3, ++ 0x08b80908, ++ 0x0106f8a7, ++ 0x062a0000, ++ 0xfefaf8a7, ++ 0x08b8f6f8, ++ 0xf39603d3, ++ 0xf9d6fba4, ++ 0xfc4e09f8, ++ 0xf7480a6a, ++ 0x07b2f841, ++ 0x062af9d6, ++ 0xf84e07bf, ++ 0xf7480a6a, ++ 0x03b2f608, ++ 0xf9d6fba4, ++ 0x0c6afc2d, ++ 0x08b8f6f8, ++ 0x01060759, ++ 0x062a0000, ++ 0xfefa0759, ++ 0x08b80908, ++ 0xf396fc2d, ++ 0xf9d6045c, ++ 0xfc4ef608, ++ 0xf748f596, ++ 0x07b207bf, ++ 0x062a062a, ++ 0xf84ef841, ++ 0xf748f596, ++ 0x03b209f8, ++ 0xf9d6045c, ++ 0x0c6a03d3, ++ 0x08b80908, ++ 0x0106f8a7, ++ 0x062a0000, ++ 0xfefaf8a7, ++ 0x08b8f6f8, ++ 0xf39603d3, ++ 0xf9d6fba4, ++ 0xfc4e09f8, ++ 0xf7480a6a, ++ 0x07b2f841, ++ 0x062af9d6, ++ 0xf84e07bf, ++ 0xf7480a6a, ++ 0x03b2f608, ++ 0xf9d6fba4, ++ 0x0c6afc2d, ++ 0x08b8f6f8, ++ 0x01060759, ++ 0x061c061c, ++ 0xff30009d, ++ 0xffb21141, ++ 0xfd87fb54, ++ 0xf65dfe59, ++ 0x02eef99e, ++ 0x0166f03c, ++ 0xfff809b6, ++ 0x000008a4, ++ 0x000af42b, ++ 0x00eff577, ++ 0xfa840bf2, ++ 0xfc02ff51, ++ 0x08260f67, ++ 0xfff0036f, ++ 0x0842f9c3, ++ 0x00000000, ++ 0x063df7be, ++ 0xfc910010, ++ 0xf099f7da, ++ 0x00af03fe, ++ 0xf40e057c, ++ 0x0a89ff11, ++ 0x0bd5fff6, ++ 0xf75c0000, ++ 0xf64a0008, ++ 0x0fc4fe9a, ++ 0x0662fd12, ++ 0x01a709a3, ++ 0x04ac0279, ++ 0xeebf004e, ++ 0xff6300d0, ++ 0xf9e4f9e4, ++ 0x00d0ff63, ++ 0x004eeebf, ++ 0x027904ac, ++ 0x09a301a7, ++ 0xfd120662, ++ 0xfe9a0fc4, ++ 0x0008f64a, ++ 0x0000f75c, ++ 0xfff60bd5, ++ 0xff110a89, ++ 0x057cf40e, ++ 0x03fe00af, ++ 0xf7daf099, ++ 0x0010fc91, ++ 0xf7be063d, ++ 0x00000000, ++ 0xf9c30842, ++ 0x036ffff0, ++ 0x0f670826, ++ 0xff51fc02, ++ 0x0bf2fa84, ++ 0xf57700ef, ++ 0xf42b000a, ++ 0x08a40000, ++ 0x09b6fff8, ++ 0xf03c0166, ++ 0xf99e02ee, ++ 0xfe59f65d, ++ 0xfb54fd87, ++ 0x1141ffb2, ++ 0x009dff30, ++ 0x05e30000, ++ 0xff060705, ++ 0x085408a0, ++ 0xf425fc59, ++ 0xfa1d042a, ++ 0xfc78f67a, ++ 0xf7acf60e, ++ 0x075a0766, ++ 0x05e305e3, ++ 0xf8a6f89a, ++ 0xf7acf60e, ++ 0x03880986, ++ 0xfa1d042a, ++ 0x0bdb03a7, ++ 0x085408a0, ++ 0x00faf8fb, ++ 0x05e30000, ++ 0xff06f8fb, ++ 0x0854f760, ++ 0xf42503a7, ++ 0xfa1dfbd6, ++ 0xfc780986, ++ 0xf7ac09f2, ++ 0x075af89a, ++ 0x05e3fa1d, ++ 0xf8a60766, ++ 0xf7ac09f2, ++ 0x0388f67a, ++ 0xfa1dfbd6, ++ 0x0bdbfc59, ++ 0x0854f760, ++ 0x00fa0705, ++ 0x05e30000, ++ 0xff060705, ++ 0x085408a0, ++ 0xf425fc59, ++ 0xfa1d042a, ++ 0xfc78f67a, ++ 0xf7acf60e, ++ 0x075a0766, ++ 0x05e305e3, ++ 0xf8a6f89a, ++ 0xf7acf60e, ++ 0x03880986, ++ 0xfa1d042a, ++ 0x0bdb03a7, ++ 0x085408a0, ++ 0x00faf8fb, ++ 0x05e30000, ++ 0xff06f8fb, ++ 0x0854f760, ++ 0xf42503a7, ++ 0xfa1dfbd6, ++ 0xfc780986, ++ 0xf7ac09f2, ++ 0x075af89a, ++ 0x05e3fa1d, ++ 0xf8a60766, ++ 0xf7ac09f2, ++ 0x0388f67a, ++ 0xfa1dfbd6, ++ 0x0bdbfc59, ++ 0x0854f760, ++ 0x00fa0705, ++ 0xfa58fa58, ++ 0xf8f0fe00, ++ 0x0448073d, ++ 0xfdc9fe46, ++ 0xf9910258, ++ 0x089d0407, ++ 0xfd5cf71a, ++ 0x02affde0, ++ 0x083e0496, ++ 0xff5a0740, ++ 0xff7afd97, ++ 0x00fe01f1, ++ 0x0009082e, ++ 0xfa94ff75, ++ 0xfecdf8ea, ++ 0xffb0f693, ++ 0xfd2cfa58, ++ 0x0433ff16, ++ 0xfba405dd, ++ 0xfa610341, ++ 0x06a606cb, ++ 0x0039fd2d, ++ 0x0677fa97, ++ 0x01fa05e0, ++ 0xf896003e, ++ 0x075a068b, ++ 0x012cfc3e, ++ 0xfa23f98d, ++ 0xfc7cfd43, ++ 0xff90fc0d, ++ 0x01c10982, ++ 0x00c601d6, ++ 0xfd2cfd2c, ++ 0x01d600c6, ++ 0x098201c1, ++ 0xfc0dff90, ++ 0xfd43fc7c, ++ 0xf98dfa23, ++ 0xfc3e012c, ++ 0x068b075a, ++ 0x003ef896, ++ 0x05e001fa, ++ 0xfa970677, ++ 0xfd2d0039, ++ 0x06cb06a6, ++ 0x0341fa61, ++ 0x05ddfba4, ++ 0xff160433, ++ 0xfa58fd2c, ++ 0xf693ffb0, ++ 0xf8eafecd, ++ 0xff75fa94, ++ 0x082e0009, ++ 0x01f100fe, ++ 0xfd97ff7a, ++ 0x0740ff5a, ++ 0x0496083e, ++ 0xfde002af, ++ 0xf71afd5c, ++ 0x0407089d, ++ 0x0258f991, ++ 0xfe46fdc9, ++ 0x073d0448, ++ 0xfe00f8f0, ++ 0xfd2cfd2c, ++ 0xfce00500, ++ 0xfc09fddc, ++ 0xfe680157, ++ 0x04c70571, ++ 0xfc3aff21, ++ 0xfcd70228, ++ 0x056d0277, ++ 0x0200fe00, ++ 0x0022f927, ++ 0xfe3c032b, ++ 0xfc44ff3c, ++ 0x03e9fbdb, ++ 0x04570313, ++ 0x04c9ff5c, ++ 0x000d03b8, ++ 0xfa580000, ++ 0xfbe900d2, ++ 0xf9d0fe0b, ++ 0x0125fdf9, ++ 0x042501bf, ++ 0x0328fa2b, ++ 0xffa902f0, ++ 0xfa250157, ++ 0x0200fe00, ++ 0x03740438, ++ 0xff0405fd, ++ 0x030cfe52, ++ 0x0037fb39, ++ 0xff6904c5, ++ 0x04f8fd23, ++ 0xfd31fc1b, ++ 0xfd2cfd2c, ++ 0xfc1bfd31, ++ 0xfd2304f8, ++ 0x04c5ff69, ++ 0xfb390037, ++ 0xfe52030c, ++ 0x05fdff04, ++ 0x04380374, ++ 0xfe000200, ++ 0x0157fa25, ++ 0x02f0ffa9, ++ 0xfa2b0328, ++ 0x01bf0425, ++ 0xfdf90125, ++ 0xfe0bf9d0, ++ 0x00d2fbe9, ++ 0x0000fa58, ++ 0x03b8000d, ++ 0xff5c04c9, ++ 0x03130457, ++ 0xfbdb03e9, ++ 0xff3cfc44, ++ 0x032bfe3c, ++ 0xf9270022, ++ 0xfe000200, ++ 0x0277056d, ++ 0x0228fcd7, ++ 0xff21fc3a, ++ 0x057104c7, ++ 0x0157fe68, ++ 0xfddcfc09, ++ 0x0500fce0, ++ 0xfd2cfd2c, ++ 0x0500fce0, ++ 0xfddcfc09, ++ 0x0157fe68, ++ 0x057104c7, ++ 0xff21fc3a, ++ 0x0228fcd7, ++ 0x0277056d, ++ 0xfe000200, ++ 0xf9270022, ++ 0x032bfe3c, ++ 0xff3cfc44, ++ 0xfbdb03e9, ++ 0x03130457, ++ 0xff5c04c9, ++ 0x03b8000d, ++ 0x0000fa58, ++ 0x00d2fbe9, ++ 0xfe0bf9d0, ++ 0xfdf90125, ++ 0x01bf0425, ++ 0xfa2b0328, ++ 0x02f0ffa9, ++ 0x0157fa25, ++ 0xfe000200, ++ 0x04380374, ++ 0x05fdff04, ++ 0xfe52030c, ++ 0xfb390037, ++ 0x04c5ff69, ++ 0xfd2304f8, ++ 0xfc1bfd31, ++ 0xfd2cfd2c, ++ 0xfd31fc1b, ++ 0x04f8fd23, ++ 0xff6904c5, ++ 0x0037fb39, ++ 0x030cfe52, ++ 0xff0405fd, ++ 0x03740438, ++ 0x0200fe00, ++ 0xfa250157, ++ 0xffa902f0, ++ 0x0328fa2b, ++ 0x042501bf, ++ 0x0125fdf9, ++ 0xf9d0fe0b, ++ 0xfbe900d2, ++ 0xfa580000, ++ 0x000d03b8, ++ 0x04c9ff5c, ++ 0x04570313, ++ 0x03e9fbdb, ++ 0xfc44ff3c, ++ 0xfe3c032b, ++ 0x0022f927, ++ 0x0200fe00, ++ 0x056d0277, ++ 0xfcd70228, ++ 0xfc3aff21, ++ 0x04c70571, ++ 0xfe680157, ++ 0xfc09fddc, ++ 0xfce00500, ++ 0x05a80000, ++ 0xff1006be, ++ 0x0800084a, ++ 0xf49cfc7e, ++ 0xfa580400, ++ 0xfc9cf6da, ++ 0xf800f672, ++ 0x0710071c, ++ 0x05a805a8, ++ 0xf8f0f8e4, ++ 0xf800f672, ++ 0x03640926, ++ 0xfa580400, ++ 0x0b640382, ++ 0x0800084a, ++ 0x00f0f942, ++ 0x05a80000, ++ 0xff10f942, ++ 0x0800f7b6, ++ 0xf49c0382, ++ 0xfa58fc00, ++ 0xfc9c0926, ++ 0xf800098e, ++ 0x0710f8e4, ++ 0x05a8fa58, ++ 0xf8f0071c, ++ 0xf800098e, ++ 0x0364f6da, ++ 0xfa58fc00, ++ 0x0b64fc7e, ++ 0x0800f7b6, ++ 0x00f006be, ++ 0x05a80000, ++ 0xff1006be, ++ 0x0800084a, ++ 0xf49cfc7e, ++ 0xfa580400, ++ 0xfc9cf6da, ++ 0xf800f672, ++ 0x0710071c, ++ 0x05a805a8, ++ 0xf8f0f8e4, ++ 0xf800f672, ++ 0x03640926, ++ 0xfa580400, ++ 0x0b640382, ++ 0x0800084a, ++ 0x00f0f942, ++ 0x05a80000, ++ 0xff10f942, ++ 0x0800f7b6, ++ 0xf49c0382, ++ 0xfa58fc00, ++ 0xfc9c0926, ++ 0xf800098e, ++ 0x0710f8e4, ++ 0x05a8fa58, ++ 0xf8f0071c, ++ 0xf800098e, ++ 0x0364f6da, ++ 0xfa58fc00, ++ 0x0b64fc7e, ++ 0x0800f7b6, ++ 0x00f006be, ++}; ++ ++const u32 noise_var_tbl_rev3[] = { ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++}; ++ ++static const u16 mcs_tbl_rev3[] = { ++ 0x0000, ++ 0x0008, ++ 0x000a, ++ 0x0010, ++ 0x0012, ++ 0x0019, ++ 0x001a, ++ 0x001c, ++ 0x0080, ++ 0x0088, ++ 0x008a, ++ 0x0090, ++ 0x0092, ++ 0x0099, ++ 0x009a, ++ 0x009c, ++ 0x0100, ++ 0x0108, ++ 0x010a, ++ 0x0110, ++ 0x0112, ++ 0x0119, ++ 0x011a, ++ 0x011c, ++ 0x0180, ++ 0x0188, ++ 0x018a, ++ 0x0190, ++ 0x0192, ++ 0x0199, ++ 0x019a, ++ 0x019c, ++ 0x0000, ++ 0x0098, ++ 0x00a0, ++ 0x00a8, ++ 0x009a, ++ 0x00a2, ++ 0x00aa, ++ 0x0120, ++ 0x0128, ++ 0x0128, ++ 0x0130, ++ 0x0138, ++ 0x0138, ++ 0x0140, ++ 0x0122, ++ 0x012a, ++ 0x012a, ++ 0x0132, ++ 0x013a, ++ 0x013a, ++ 0x0142, ++ 0x01a8, ++ 0x01b0, ++ 0x01b8, ++ 0x01b0, ++ 0x01b8, ++ 0x01c0, ++ 0x01c8, ++ 0x01c0, ++ 0x01c8, ++ 0x01d0, ++ 0x01d0, ++ 0x01d8, ++ 0x01aa, ++ 0x01b2, ++ 0x01ba, ++ 0x01b2, ++ 0x01ba, ++ 0x01c2, ++ 0x01ca, ++ 0x01c2, ++ 0x01ca, ++ 0x01d2, ++ 0x01d2, ++ 0x01da, ++ 0x0001, ++ 0x0002, ++ 0x0004, ++ 0x0009, ++ 0x000c, ++ 0x0011, ++ 0x0014, ++ 0x0018, ++ 0x0020, ++ 0x0021, ++ 0x0022, ++ 0x0024, ++ 0x0081, ++ 0x0082, ++ 0x0084, ++ 0x0089, ++ 0x008c, ++ 0x0091, ++ 0x0094, ++ 0x0098, ++ 0x00a0, ++ 0x00a1, ++ 0x00a2, ++ 0x00a4, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++}; ++ ++static const u32 tdi_tbl20_ant0_rev3[] = { ++ 0x00091226, ++ 0x000a1429, ++ 0x000b56ad, ++ 0x000c58b0, ++ 0x000d5ab3, ++ 0x000e9cb6, ++ 0x000f9eba, ++ 0x0000c13d, ++ 0x00020301, ++ 0x00030504, ++ 0x00040708, ++ 0x0005090b, ++ 0x00064b8e, ++ 0x00095291, ++ 0x000a5494, ++ 0x000b9718, ++ 0x000c9927, ++ 0x000d9b2a, ++ 0x000edd2e, ++ 0x000fdf31, ++ 0x000101b4, ++ 0x000243b7, ++ 0x000345bb, ++ 0x000447be, ++ 0x00058982, ++ 0x00068c05, ++ 0x00099309, ++ 0x000a950c, ++ 0x000bd78f, ++ 0x000cd992, ++ 0x000ddb96, ++ 0x000f1d99, ++ 0x00005fa8, ++ 0x0001422c, ++ 0x0002842f, ++ 0x00038632, ++ 0x00048835, ++ 0x0005ca38, ++ 0x0006ccbc, ++ 0x0009d3bf, ++ 0x000b1603, ++ 0x000c1806, ++ 0x000d1a0a, ++ 0x000e1c0d, ++ 0x000f5e10, ++ 0x00008093, ++ 0x00018297, ++ 0x0002c49a, ++ 0x0003c680, ++ 0x0004c880, ++ 0x00060b00, ++ 0x00070d00, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 tdi_tbl20_ant1_rev3[] = { ++ 0x00014b26, ++ 0x00028d29, ++ 0x000393ad, ++ 0x00049630, ++ 0x0005d833, ++ 0x0006da36, ++ 0x00099c3a, ++ 0x000a9e3d, ++ 0x000bc081, ++ 0x000cc284, ++ 0x000dc488, ++ 0x000f068b, ++ 0x0000488e, ++ 0x00018b91, ++ 0x0002d214, ++ 0x0003d418, ++ 0x0004d6a7, ++ 0x000618aa, ++ 0x00071aae, ++ 0x0009dcb1, ++ 0x000b1eb4, ++ 0x000c0137, ++ 0x000d033b, ++ 0x000e053e, ++ 0x000f4702, ++ 0x00008905, ++ 0x00020c09, ++ 0x0003128c, ++ 0x0004148f, ++ 0x00051712, ++ 0x00065916, ++ 0x00091b19, ++ 0x000a1d28, ++ 0x000b5f2c, ++ 0x000c41af, ++ 0x000d43b2, ++ 0x000e85b5, ++ 0x000f87b8, ++ 0x0000c9bc, ++ 0x00024cbf, ++ 0x00035303, ++ 0x00045506, ++ 0x0005978a, ++ 0x0006998d, ++ 0x00095b90, ++ 0x000a5d93, ++ 0x000b9f97, ++ 0x000c821a, ++ 0x000d8400, ++ 0x000ec600, ++ 0x000fc800, ++ 0x00010a00, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 tdi_tbl40_ant0_rev3[] = { ++ 0x0011a346, ++ 0x00136ccf, ++ 0x0014f5d9, ++ 0x001641e2, ++ 0x0017cb6b, ++ 0x00195475, ++ 0x001b2383, ++ 0x001cad0c, ++ 0x001e7616, ++ 0x0000821f, ++ 0x00020ba8, ++ 0x0003d4b2, ++ 0x00056447, ++ 0x00072dd0, ++ 0x0008b6da, ++ 0x000a02e3, ++ 0x000b8c6c, ++ 0x000d15f6, ++ 0x0011e484, ++ 0x0013ae0d, ++ 0x00153717, ++ 0x00168320, ++ 0x00180ca9, ++ 0x00199633, ++ 0x001b6548, ++ 0x001ceed1, ++ 0x001eb7db, ++ 0x0000c3e4, ++ 0x00024d6d, ++ 0x000416f7, ++ 0x0005a585, ++ 0x00076f0f, ++ 0x0008f818, ++ 0x000a4421, ++ 0x000bcdab, ++ 0x000d9734, ++ 0x00122649, ++ 0x0013efd2, ++ 0x001578dc, ++ 0x0016c4e5, ++ 0x00184e6e, ++ 0x001a17f8, ++ 0x001ba686, ++ 0x001d3010, ++ 0x001ef999, ++ 0x00010522, ++ 0x00028eac, ++ 0x00045835, ++ 0x0005e74a, ++ 0x0007b0d3, ++ 0x00093a5d, ++ 0x000a85e6, ++ 0x000c0f6f, ++ 0x000dd8f9, ++ 0x00126787, ++ 0x00143111, ++ 0x0015ba9a, ++ 0x00170623, ++ 0x00188fad, ++ 0x001a5936, ++ 0x001be84b, ++ 0x001db1d4, ++ 0x001f3b5e, ++ 0x000146e7, ++ 0x00031070, ++ 0x000499fa, ++ 0x00062888, ++ 0x0007f212, ++ 0x00097b9b, ++ 0x000ac7a4, ++ 0x000c50ae, ++ 0x000e1a37, ++ 0x0012a94c, ++ 0x001472d5, ++ 0x0015fc5f, ++ 0x00174868, ++ 0x0018d171, ++ 0x001a9afb, ++ 0x001c2989, ++ 0x001df313, ++ 0x001f7c9c, ++ 0x000188a5, ++ 0x000351af, ++ 0x0004db38, ++ 0x0006aa4d, ++ 0x000833d7, ++ 0x0009bd60, ++ 0x000b0969, ++ 0x000c9273, ++ 0x000e5bfc, ++ 0x00132a8a, ++ 0x0014b414, ++ 0x00163d9d, ++ 0x001789a6, ++ 0x001912b0, ++ 0x001adc39, ++ 0x001c6bce, ++ 0x001e34d8, ++ 0x001fbe61, ++ 0x0001ca6a, ++ 0x00039374, ++ 0x00051cfd, ++ 0x0006ec0b, ++ 0x00087515, ++ 0x0009fe9e, ++ 0x000b4aa7, ++ 0x000cd3b1, ++ 0x000e9d3a, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 tdi_tbl40_ant1_rev3[] = { ++ 0x001edb36, ++ 0x000129ca, ++ 0x0002b353, ++ 0x00047cdd, ++ 0x0005c8e6, ++ 0x000791ef, ++ 0x00091bf9, ++ 0x000aaa07, ++ 0x000c3391, ++ 0x000dfd1a, ++ 0x00120923, ++ 0x0013d22d, ++ 0x00155c37, ++ 0x0016eacb, ++ 0x00187454, ++ 0x001a3dde, ++ 0x001b89e7, ++ 0x001d12f0, ++ 0x001f1cfa, ++ 0x00016b88, ++ 0x00033492, ++ 0x0004be1b, ++ 0x00060a24, ++ 0x0007d32e, ++ 0x00095d38, ++ 0x000aec4c, ++ 0x000c7555, ++ 0x000e3edf, ++ 0x00124ae8, ++ 0x001413f1, ++ 0x0015a37b, ++ 0x00172c89, ++ 0x0018b593, ++ 0x001a419c, ++ 0x001bcb25, ++ 0x001d942f, ++ 0x001f63b9, ++ 0x0001ad4d, ++ 0x00037657, ++ 0x0004c260, ++ 0x00068be9, ++ 0x000814f3, ++ 0x0009a47c, ++ 0x000b2d8a, ++ 0x000cb694, ++ 0x000e429d, ++ 0x00128c26, ++ 0x001455b0, ++ 0x0015e4ba, ++ 0x00176e4e, ++ 0x0018f758, ++ 0x001a8361, ++ 0x001c0cea, ++ 0x001dd674, ++ 0x001fa57d, ++ 0x0001ee8b, ++ 0x0003b795, ++ 0x0005039e, ++ 0x0006cd27, ++ 0x000856b1, ++ 0x0009e5c6, ++ 0x000b6f4f, ++ 0x000cf859, ++ 0x000e8462, ++ 0x00130deb, ++ 0x00149775, ++ 0x00162603, ++ 0x0017af8c, ++ 0x00193896, ++ 0x001ac49f, ++ 0x001c4e28, ++ 0x001e17b2, ++ 0x0000a6c7, ++ 0x00023050, ++ 0x0003f9da, ++ 0x00054563, ++ 0x00070eec, ++ 0x00089876, ++ 0x000a2704, ++ 0x000bb08d, ++ 0x000d3a17, ++ 0x001185a0, ++ 0x00134f29, ++ 0x0014d8b3, ++ 0x001667c8, ++ 0x0017f151, ++ 0x00197adb, ++ 0x001b0664, ++ 0x001c8fed, ++ 0x001e5977, ++ 0x0000e805, ++ 0x0002718f, ++ 0x00043b18, ++ 0x000586a1, ++ 0x0007502b, ++ 0x0008d9b4, ++ 0x000a68c9, ++ 0x000bf252, ++ 0x000dbbdc, ++ 0x0011c7e5, ++ 0x001390ee, ++ 0x00151a78, ++ 0x0016a906, ++ 0x00183290, ++ 0x0019bc19, ++ 0x001b4822, ++ 0x001cd12c, ++ 0x001e9ab5, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 pltlut_tbl_rev3[] = { ++ 0x76540213, ++ 0x62407351, ++ 0x76543210, ++ 0x76540213, ++ 0x76540213, ++ 0x76430521, ++}; ++ ++static const u32 chanest_tbl_rev3[] = { ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++}; ++ ++static const u8 frame_lut_rev3[] = { ++ 0x02, ++ 0x04, ++ 0x14, ++ 0x14, ++ 0x03, ++ 0x05, ++ 0x16, ++ 0x16, ++ 0x0a, ++ 0x0c, ++ 0x1c, ++ 0x1c, ++ 0x0b, ++ 0x0d, ++ 0x1e, ++ 0x1e, ++ 0x06, ++ 0x08, ++ 0x18, ++ 0x18, ++ 0x07, ++ 0x09, ++ 0x1a, ++ 0x1a, ++ 0x0e, ++ 0x10, ++ 0x20, ++ 0x28, ++ 0x0f, ++ 0x11, ++ 0x22, ++ 0x2a, ++}; ++ ++static const u8 est_pwr_lut_core0_rev3[] = { ++ 0x55, ++ 0x54, ++ 0x54, ++ 0x53, ++ 0x52, ++ 0x52, ++ 0x51, ++ 0x51, ++ 0x50, ++ 0x4f, ++ 0x4f, ++ 0x4e, ++ 0x4e, ++ 0x4d, ++ 0x4c, ++ 0x4c, ++ 0x4b, ++ 0x4a, ++ 0x49, ++ 0x49, ++ 0x48, ++ 0x47, ++ 0x46, ++ 0x46, ++ 0x45, ++ 0x44, ++ 0x43, ++ 0x42, ++ 0x41, ++ 0x40, ++ 0x40, ++ 0x3f, ++ 0x3e, ++ 0x3d, ++ 0x3c, ++ 0x3a, ++ 0x39, ++ 0x38, ++ 0x37, ++ 0x36, ++ 0x35, ++ 0x33, ++ 0x32, ++ 0x31, ++ 0x2f, ++ 0x2e, ++ 0x2c, ++ 0x2b, ++ 0x29, ++ 0x27, ++ 0x25, ++ 0x23, ++ 0x21, ++ 0x1f, ++ 0x1d, ++ 0x1a, ++ 0x18, ++ 0x15, ++ 0x12, ++ 0x0e, ++ 0x0b, ++ 0x07, ++ 0x02, ++ 0xfd, ++}; ++ ++static const u8 est_pwr_lut_core1_rev3[] = { ++ 0x55, ++ 0x54, ++ 0x54, ++ 0x53, ++ 0x52, ++ 0x52, ++ 0x51, ++ 0x51, ++ 0x50, ++ 0x4f, ++ 0x4f, ++ 0x4e, ++ 0x4e, ++ 0x4d, ++ 0x4c, ++ 0x4c, ++ 0x4b, ++ 0x4a, ++ 0x49, ++ 0x49, ++ 0x48, ++ 0x47, ++ 0x46, ++ 0x46, ++ 0x45, ++ 0x44, ++ 0x43, ++ 0x42, ++ 0x41, ++ 0x40, ++ 0x40, ++ 0x3f, ++ 0x3e, ++ 0x3d, ++ 0x3c, ++ 0x3a, ++ 0x39, ++ 0x38, ++ 0x37, ++ 0x36, ++ 0x35, ++ 0x33, ++ 0x32, ++ 0x31, ++ 0x2f, ++ 0x2e, ++ 0x2c, ++ 0x2b, ++ 0x29, ++ 0x27, ++ 0x25, ++ 0x23, ++ 0x21, ++ 0x1f, ++ 0x1d, ++ 0x1a, ++ 0x18, ++ 0x15, ++ 0x12, ++ 0x0e, ++ 0x0b, ++ 0x07, ++ 0x02, ++ 0xfd, ++}; ++ ++static const u8 adj_pwr_lut_core0_rev3[] = { ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++}; ++ ++static const u8 adj_pwr_lut_core1_rev3[] = { ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++}; ++ ++static const u32 gainctrl_lut_core0_rev3[] = { ++ 0x5bf70044, ++ 0x5bf70042, ++ 0x5bf70040, ++ 0x5bf7003e, ++ 0x5bf7003c, ++ 0x5bf7003b, ++ 0x5bf70039, ++ 0x5bf70037, ++ 0x5bf70036, ++ 0x5bf70034, ++ 0x5bf70033, ++ 0x5bf70031, ++ 0x5bf70030, ++ 0x5ba70044, ++ 0x5ba70042, ++ 0x5ba70040, ++ 0x5ba7003e, ++ 0x5ba7003c, ++ 0x5ba7003b, ++ 0x5ba70039, ++ 0x5ba70037, ++ 0x5ba70036, ++ 0x5ba70034, ++ 0x5ba70033, ++ 0x5b770044, ++ 0x5b770042, ++ 0x5b770040, ++ 0x5b77003e, ++ 0x5b77003c, ++ 0x5b77003b, ++ 0x5b770039, ++ 0x5b770037, ++ 0x5b770036, ++ 0x5b770034, ++ 0x5b770033, ++ 0x5b770031, ++ 0x5b770030, ++ 0x5b77002f, ++ 0x5b77002d, ++ 0x5b77002c, ++ 0x5b470044, ++ 0x5b470042, ++ 0x5b470040, ++ 0x5b47003e, ++ 0x5b47003c, ++ 0x5b47003b, ++ 0x5b470039, ++ 0x5b470037, ++ 0x5b470036, ++ 0x5b470034, ++ 0x5b470033, ++ 0x5b470031, ++ 0x5b470030, ++ 0x5b47002f, ++ 0x5b47002d, ++ 0x5b47002c, ++ 0x5b47002b, ++ 0x5b47002a, ++ 0x5b270044, ++ 0x5b270042, ++ 0x5b270040, ++ 0x5b27003e, ++ 0x5b27003c, ++ 0x5b27003b, ++ 0x5b270039, ++ 0x5b270037, ++ 0x5b270036, ++ 0x5b270034, ++ 0x5b270033, ++ 0x5b270031, ++ 0x5b270030, ++ 0x5b27002f, ++ 0x5b170044, ++ 0x5b170042, ++ 0x5b170040, ++ 0x5b17003e, ++ 0x5b17003c, ++ 0x5b17003b, ++ 0x5b170039, ++ 0x5b170037, ++ 0x5b170036, ++ 0x5b170034, ++ 0x5b170033, ++ 0x5b170031, ++ 0x5b170030, ++ 0x5b17002f, ++ 0x5b17002d, ++ 0x5b17002c, ++ 0x5b17002b, ++ 0x5b17002a, ++ 0x5b170028, ++ 0x5b170027, ++ 0x5b170026, ++ 0x5b170025, ++ 0x5b170024, ++ 0x5b170023, ++ 0x5b070044, ++ 0x5b070042, ++ 0x5b070040, ++ 0x5b07003e, ++ 0x5b07003c, ++ 0x5b07003b, ++ 0x5b070039, ++ 0x5b070037, ++ 0x5b070036, ++ 0x5b070034, ++ 0x5b070033, ++ 0x5b070031, ++ 0x5b070030, ++ 0x5b07002f, ++ 0x5b07002d, ++ 0x5b07002c, ++ 0x5b07002b, ++ 0x5b07002a, ++ 0x5b070028, ++ 0x5b070027, ++ 0x5b070026, ++ 0x5b070025, ++ 0x5b070024, ++ 0x5b070023, ++ 0x5b070022, ++ 0x5b070021, ++ 0x5b070020, ++ 0x5b07001f, ++ 0x5b07001e, ++ 0x5b07001d, ++ 0x5b07001d, ++ 0x5b07001c, ++}; ++ ++static const u32 gainctrl_lut_core1_rev3[] = { ++ 0x5bf70044, ++ 0x5bf70042, ++ 0x5bf70040, ++ 0x5bf7003e, ++ 0x5bf7003c, ++ 0x5bf7003b, ++ 0x5bf70039, ++ 0x5bf70037, ++ 0x5bf70036, ++ 0x5bf70034, ++ 0x5bf70033, ++ 0x5bf70031, ++ 0x5bf70030, ++ 0x5ba70044, ++ 0x5ba70042, ++ 0x5ba70040, ++ 0x5ba7003e, ++ 0x5ba7003c, ++ 0x5ba7003b, ++ 0x5ba70039, ++ 0x5ba70037, ++ 0x5ba70036, ++ 0x5ba70034, ++ 0x5ba70033, ++ 0x5b770044, ++ 0x5b770042, ++ 0x5b770040, ++ 0x5b77003e, ++ 0x5b77003c, ++ 0x5b77003b, ++ 0x5b770039, ++ 0x5b770037, ++ 0x5b770036, ++ 0x5b770034, ++ 0x5b770033, ++ 0x5b770031, ++ 0x5b770030, ++ 0x5b77002f, ++ 0x5b77002d, ++ 0x5b77002c, ++ 0x5b470044, ++ 0x5b470042, ++ 0x5b470040, ++ 0x5b47003e, ++ 0x5b47003c, ++ 0x5b47003b, ++ 0x5b470039, ++ 0x5b470037, ++ 0x5b470036, ++ 0x5b470034, ++ 0x5b470033, ++ 0x5b470031, ++ 0x5b470030, ++ 0x5b47002f, ++ 0x5b47002d, ++ 0x5b47002c, ++ 0x5b47002b, ++ 0x5b47002a, ++ 0x5b270044, ++ 0x5b270042, ++ 0x5b270040, ++ 0x5b27003e, ++ 0x5b27003c, ++ 0x5b27003b, ++ 0x5b270039, ++ 0x5b270037, ++ 0x5b270036, ++ 0x5b270034, ++ 0x5b270033, ++ 0x5b270031, ++ 0x5b270030, ++ 0x5b27002f, ++ 0x5b170044, ++ 0x5b170042, ++ 0x5b170040, ++ 0x5b17003e, ++ 0x5b17003c, ++ 0x5b17003b, ++ 0x5b170039, ++ 0x5b170037, ++ 0x5b170036, ++ 0x5b170034, ++ 0x5b170033, ++ 0x5b170031, ++ 0x5b170030, ++ 0x5b17002f, ++ 0x5b17002d, ++ 0x5b17002c, ++ 0x5b17002b, ++ 0x5b17002a, ++ 0x5b170028, ++ 0x5b170027, ++ 0x5b170026, ++ 0x5b170025, ++ 0x5b170024, ++ 0x5b170023, ++ 0x5b070044, ++ 0x5b070042, ++ 0x5b070040, ++ 0x5b07003e, ++ 0x5b07003c, ++ 0x5b07003b, ++ 0x5b070039, ++ 0x5b070037, ++ 0x5b070036, ++ 0x5b070034, ++ 0x5b070033, ++ 0x5b070031, ++ 0x5b070030, ++ 0x5b07002f, ++ 0x5b07002d, ++ 0x5b07002c, ++ 0x5b07002b, ++ 0x5b07002a, ++ 0x5b070028, ++ 0x5b070027, ++ 0x5b070026, ++ 0x5b070025, ++ 0x5b070024, ++ 0x5b070023, ++ 0x5b070022, ++ 0x5b070021, ++ 0x5b070020, ++ 0x5b07001f, ++ 0x5b07001e, ++ 0x5b07001d, ++ 0x5b07001d, ++ 0x5b07001c, ++}; ++ ++static const u32 iq_lut_core0_rev3[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 iq_lut_core1_rev3[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u16 loft_lut_core0_rev3[] = { ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++}; ++ ++static const u16 loft_lut_core1_rev3[] = { ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++}; ++ ++static const u16 papd_comp_rfpwr_tbl_core0_rev3[] = { ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++}; ++ ++static const u16 papd_comp_rfpwr_tbl_core1_rev3[] = { ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++}; ++ ++static const u32 papd_comp_epsilon_tbl_core0_rev3[] = { ++ 0x00000000, ++ 0x00001fa0, ++ 0x00019f78, ++ 0x0001df7e, ++ 0x03fa9f86, ++ 0x03fd1f90, ++ 0x03fe5f8a, ++ 0x03fb1f94, ++ 0x03fd9fa0, ++ 0x00009f98, ++ 0x03fd1fac, ++ 0x03ff9fa2, ++ 0x03fe9fae, ++ 0x00001fae, ++ 0x03fddfb4, ++ 0x03ff1fb8, ++ 0x03ff9fbc, ++ 0x03ffdfbe, ++ 0x03fe9fc2, ++ 0x03fedfc6, ++ 0x03fedfc6, ++ 0x03ff9fc8, ++ 0x03ff5fc6, ++ 0x03fedfc2, ++ 0x03ff9fc0, ++ 0x03ff5fac, ++ 0x03ff5fac, ++ 0x03ff9fa2, ++ 0x03ff9fa6, ++ 0x03ff9faa, ++ 0x03ff5fb0, ++ 0x03ff5fb4, ++ 0x03ff1fca, ++ 0x03ff5fce, ++ 0x03fcdfdc, ++ 0x03fb4006, ++ 0x00000030, ++ 0x03ff808a, ++ 0x03ff80da, ++ 0x0000016c, ++ 0x03ff8318, ++ 0x03ff063a, ++ 0x03fd8bd6, ++ 0x00014ffe, ++ 0x00034ffe, ++ 0x00034ffe, ++ 0x0003cffe, ++ 0x00040ffe, ++ 0x00040ffe, ++ 0x0003cffe, ++ 0x0003cffe, ++ 0x00020ffe, ++ 0x03fe0ffe, ++ 0x03fdcffe, ++ 0x03f94ffe, ++ 0x03f54ffe, ++ 0x03f44ffe, ++ 0x03ef8ffe, ++ 0x03ee0ffe, ++ 0x03ebcffe, ++ 0x03e8cffe, ++ 0x03e74ffe, ++ 0x03e4cffe, ++ 0x03e38ffe, ++}; ++ ++static const u32 papd_cal_scalars_tbl_core0_rev3[] = { ++ 0x05af005a, ++ 0x0571005e, ++ 0x05040066, ++ 0x04bd006c, ++ 0x047d0072, ++ 0x04430078, ++ 0x03f70081, ++ 0x03cb0087, ++ 0x03870091, ++ 0x035e0098, ++ 0x032e00a1, ++ 0x030300aa, ++ 0x02d800b4, ++ 0x02ae00bf, ++ 0x028900ca, ++ 0x026400d6, ++ 0x024100e3, ++ 0x022200f0, ++ 0x020200ff, ++ 0x01e5010e, ++ 0x01ca011e, ++ 0x01b0012f, ++ 0x01990140, ++ 0x01830153, ++ 0x016c0168, ++ 0x0158017d, ++ 0x01450193, ++ 0x013301ab, ++ 0x012101c5, ++ 0x011101e0, ++ 0x010201fc, ++ 0x00f4021a, ++ 0x00e6011d, ++ 0x00d9012e, ++ 0x00cd0140, ++ 0x00c20153, ++ 0x00b70167, ++ 0x00ac017c, ++ 0x00a30193, ++ 0x009a01ab, ++ 0x009101c4, ++ 0x008901df, ++ 0x008101fb, ++ 0x007a0219, ++ 0x00730239, ++ 0x006d025b, ++ 0x0067027e, ++ 0x006102a4, ++ 0x005c02cc, ++ 0x005602f6, ++ 0x00520323, ++ 0x004d0353, ++ 0x00490385, ++ 0x004503bb, ++ 0x004103f3, ++ 0x003d042f, ++ 0x003a046f, ++ 0x003704b2, ++ 0x003404f9, ++ 0x00310545, ++ 0x002e0596, ++ 0x002b05f5, ++ 0x00290640, ++ 0x002606a4, ++}; ++ ++static const u32 papd_comp_epsilon_tbl_core1_rev3[] = { ++ 0x00000000, ++ 0x00001fa0, ++ 0x00019f78, ++ 0x0001df7e, ++ 0x03fa9f86, ++ 0x03fd1f90, ++ 0x03fe5f8a, ++ 0x03fb1f94, ++ 0x03fd9fa0, ++ 0x00009f98, ++ 0x03fd1fac, ++ 0x03ff9fa2, ++ 0x03fe9fae, ++ 0x00001fae, ++ 0x03fddfb4, ++ 0x03ff1fb8, ++ 0x03ff9fbc, ++ 0x03ffdfbe, ++ 0x03fe9fc2, ++ 0x03fedfc6, ++ 0x03fedfc6, ++ 0x03ff9fc8, ++ 0x03ff5fc6, ++ 0x03fedfc2, ++ 0x03ff9fc0, ++ 0x03ff5fac, ++ 0x03ff5fac, ++ 0x03ff9fa2, ++ 0x03ff9fa6, ++ 0x03ff9faa, ++ 0x03ff5fb0, ++ 0x03ff5fb4, ++ 0x03ff1fca, ++ 0x03ff5fce, ++ 0x03fcdfdc, ++ 0x03fb4006, ++ 0x00000030, ++ 0x03ff808a, ++ 0x03ff80da, ++ 0x0000016c, ++ 0x03ff8318, ++ 0x03ff063a, ++ 0x03fd8bd6, ++ 0x00014ffe, ++ 0x00034ffe, ++ 0x00034ffe, ++ 0x0003cffe, ++ 0x00040ffe, ++ 0x00040ffe, ++ 0x0003cffe, ++ 0x0003cffe, ++ 0x00020ffe, ++ 0x03fe0ffe, ++ 0x03fdcffe, ++ 0x03f94ffe, ++ 0x03f54ffe, ++ 0x03f44ffe, ++ 0x03ef8ffe, ++ 0x03ee0ffe, ++ 0x03ebcffe, ++ 0x03e8cffe, ++ 0x03e74ffe, ++ 0x03e4cffe, ++ 0x03e38ffe, ++}; ++ ++static const u32 papd_cal_scalars_tbl_core1_rev3[] = { ++ 0x05af005a, ++ 0x0571005e, ++ 0x05040066, ++ 0x04bd006c, ++ 0x047d0072, ++ 0x04430078, ++ 0x03f70081, ++ 0x03cb0087, ++ 0x03870091, ++ 0x035e0098, ++ 0x032e00a1, ++ 0x030300aa, ++ 0x02d800b4, ++ 0x02ae00bf, ++ 0x028900ca, ++ 0x026400d6, ++ 0x024100e3, ++ 0x022200f0, ++ 0x020200ff, ++ 0x01e5010e, ++ 0x01ca011e, ++ 0x01b0012f, ++ 0x01990140, ++ 0x01830153, ++ 0x016c0168, ++ 0x0158017d, ++ 0x01450193, ++ 0x013301ab, ++ 0x012101c5, ++ 0x011101e0, ++ 0x010201fc, ++ 0x00f4021a, ++ 0x00e6011d, ++ 0x00d9012e, ++ 0x00cd0140, ++ 0x00c20153, ++ 0x00b70167, ++ 0x00ac017c, ++ 0x00a30193, ++ 0x009a01ab, ++ 0x009101c4, ++ 0x008901df, ++ 0x008101fb, ++ 0x007a0219, ++ 0x00730239, ++ 0x006d025b, ++ 0x0067027e, ++ 0x006102a4, ++ 0x005c02cc, ++ 0x005602f6, ++ 0x00520323, ++ 0x004d0353, ++ 0x00490385, ++ 0x004503bb, ++ 0x004103f3, ++ 0x003d042f, ++ 0x003a046f, ++ 0x003704b2, ++ 0x003404f9, ++ 0x00310545, ++ 0x002e0596, ++ 0x002b05f5, ++ 0x00290640, ++ 0x002606a4, ++}; ++ ++const struct phytbl_info mimophytbl_info_rev3_volatile[] = { ++ {&ant_swctrl_tbl_rev3, ++ sizeof(ant_swctrl_tbl_rev3) / sizeof(ant_swctrl_tbl_rev3[0]), 9, 0, 16} ++ , ++}; ++ ++const struct phytbl_info mimophytbl_info_rev3_volatile1[] = { ++ {&ant_swctrl_tbl_rev3_1, ++ sizeof(ant_swctrl_tbl_rev3_1) / sizeof(ant_swctrl_tbl_rev3_1[0]), 9, 0, ++ 16} ++ , ++}; ++ ++const struct phytbl_info mimophytbl_info_rev3_volatile2[] = { ++ {&ant_swctrl_tbl_rev3_2, ++ sizeof(ant_swctrl_tbl_rev3_2) / sizeof(ant_swctrl_tbl_rev3_2[0]), 9, 0, ++ 16} ++ , ++}; ++ ++const struct phytbl_info mimophytbl_info_rev3_volatile3[] = { ++ {&ant_swctrl_tbl_rev3_3, ++ sizeof(ant_swctrl_tbl_rev3_3) / sizeof(ant_swctrl_tbl_rev3_3[0]), 9, 0, ++ 16} ++ , ++}; ++ ++const struct phytbl_info mimophytbl_info_rev3[] = { ++ {&frame_struct_rev3, ++ sizeof(frame_struct_rev3) / sizeof(frame_struct_rev3[0]), 10, 0, 32} ++ , ++ {&pilot_tbl_rev3, sizeof(pilot_tbl_rev3) / sizeof(pilot_tbl_rev3[0]), ++ 11, 0, 16} ++ , ++ {&tmap_tbl_rev3, sizeof(tmap_tbl_rev3) / sizeof(tmap_tbl_rev3[0]), 12, ++ 0, 32} ++ , ++ {&intlv_tbl_rev3, sizeof(intlv_tbl_rev3) / sizeof(intlv_tbl_rev3[0]), ++ 13, 0, 32} ++ , ++ {&tdtrn_tbl_rev3, sizeof(tdtrn_tbl_rev3) / sizeof(tdtrn_tbl_rev3[0]), ++ 14, 0, 32} ++ , ++ {&noise_var_tbl_rev3, ++ sizeof(noise_var_tbl_rev3) / sizeof(noise_var_tbl_rev3[0]), 16, 0, 32} ++ , ++ {&mcs_tbl_rev3, sizeof(mcs_tbl_rev3) / sizeof(mcs_tbl_rev3[0]), 18, 0, ++ 16} ++ , ++ {&tdi_tbl20_ant0_rev3, ++ sizeof(tdi_tbl20_ant0_rev3) / sizeof(tdi_tbl20_ant0_rev3[0]), 19, 128, ++ 32} ++ , ++ {&tdi_tbl20_ant1_rev3, ++ sizeof(tdi_tbl20_ant1_rev3) / sizeof(tdi_tbl20_ant1_rev3[0]), 19, 256, ++ 32} ++ , ++ {&tdi_tbl40_ant0_rev3, ++ sizeof(tdi_tbl40_ant0_rev3) / sizeof(tdi_tbl40_ant0_rev3[0]), 19, 640, ++ 32} ++ , ++ {&tdi_tbl40_ant1_rev3, ++ sizeof(tdi_tbl40_ant1_rev3) / sizeof(tdi_tbl40_ant1_rev3[0]), 19, 768, ++ 32} ++ , ++ {&pltlut_tbl_rev3, sizeof(pltlut_tbl_rev3) / sizeof(pltlut_tbl_rev3[0]), ++ 20, 0, 32} ++ , ++ {&chanest_tbl_rev3, ++ sizeof(chanest_tbl_rev3) / sizeof(chanest_tbl_rev3[0]), 22, 0, 32} ++ , ++ {&frame_lut_rev3, sizeof(frame_lut_rev3) / sizeof(frame_lut_rev3[0]), ++ 24, 0, 8} ++ , ++ {&est_pwr_lut_core0_rev3, ++ sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26, ++ 0, 8} ++ , ++ {&est_pwr_lut_core1_rev3, ++ sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27, ++ 0, 8} ++ , ++ {&adj_pwr_lut_core0_rev3, ++ sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26, ++ 64, 8} ++ , ++ {&adj_pwr_lut_core1_rev3, ++ sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27, ++ 64, 8} ++ , ++ {&gainctrl_lut_core0_rev3, ++ sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]), ++ 26, 192, 32} ++ , ++ {&gainctrl_lut_core1_rev3, ++ sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]), ++ 27, 192, 32} ++ , ++ {&iq_lut_core0_rev3, ++ sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32} ++ , ++ {&iq_lut_core1_rev3, ++ sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32} ++ , ++ {&loft_lut_core0_rev3, ++ sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448, ++ 16} ++ , ++ {&loft_lut_core1_rev3, ++ sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448, ++ 16} ++}; ++ ++const u32 mimophytbl_info_sz_rev3 = ++ sizeof(mimophytbl_info_rev3) / sizeof(mimophytbl_info_rev3[0]); ++const u32 mimophytbl_info_sz_rev3_volatile = ++ sizeof(mimophytbl_info_rev3_volatile) / ++ sizeof(mimophytbl_info_rev3_volatile[0]); ++const u32 mimophytbl_info_sz_rev3_volatile1 = ++ sizeof(mimophytbl_info_rev3_volatile1) / ++ sizeof(mimophytbl_info_rev3_volatile1[0]); ++const u32 mimophytbl_info_sz_rev3_volatile2 = ++ sizeof(mimophytbl_info_rev3_volatile2) / ++ sizeof(mimophytbl_info_rev3_volatile2[0]); ++const u32 mimophytbl_info_sz_rev3_volatile3 = ++ sizeof(mimophytbl_info_rev3_volatile3) / ++ sizeof(mimophytbl_info_rev3_volatile3[0]); ++ ++static const u32 tmap_tbl_rev7[] = { ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x000aa888, ++ 0x88880000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa2222220, ++ 0x22222222, ++ 0x22c22222, ++ 0x00000222, ++ 0x22000000, ++ 0x2222a222, ++ 0x22222222, ++ 0x222222a2, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00011111, ++ 0x11110000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0xa8aa88a0, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x00088aaa, ++ 0xaaaa0000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xaaa8aaa0, ++ 0x8aaa8aaa, ++ 0xaa8a8a8a, ++ 0x000aaa88, ++ 0x8aaa0000, ++ 0xaaa8a888, ++ 0x8aa88a8a, ++ 0x8a88a888, ++ 0x08080a00, ++ 0x0a08080a, ++ 0x080a0a08, ++ 0x00080808, ++ 0x080a0000, ++ 0x080a0808, ++ 0x080a0808, ++ 0x0a0a0a08, ++ 0xa0a0a0a0, ++ 0x80a0a080, ++ 0x8080a0a0, ++ 0x00008080, ++ 0x80a00000, ++ 0x80a080a0, ++ 0xa080a0a0, ++ 0x8080a0a0, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x99999000, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb90, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00aaa888, ++ 0x22000000, ++ 0x2222b222, ++ 0x22222222, ++ 0x222222b2, ++ 0xb2222220, ++ 0x22222222, ++ 0x22d22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x33000000, ++ 0x3333b333, ++ 0x33333333, ++ 0x333333b3, ++ 0xb3333330, ++ 0x33333333, ++ 0x33d33333, ++ 0x00000333, ++ 0x22000000, ++ 0x2222a222, ++ 0x22222222, ++ 0x222222a2, ++ 0xa2222220, ++ 0x22222222, ++ 0x22c22222, ++ 0x00000222, ++ 0x99b99b00, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb99, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x08aaa888, ++ 0x22222200, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0x22222222, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x11111111, ++ 0xf1111111, ++ 0x11111111, ++ 0x11f11111, ++ 0x01111111, ++ 0xbb9bb900, ++ 0xb9b9bb99, ++ 0xb99bbbbb, ++ 0xbbbb9b9b, ++ 0xb9bb99bb, ++ 0xb99999b9, ++ 0xb9b9b99b, ++ 0x00000bbb, ++ 0xaa000000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xa8aa88aa, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x0a888aaa, ++ 0xaa000000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xa8aa88a0, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x00000aaa, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0xbbbbbb00, ++ 0x999bbbbb, ++ 0x9bb99b9b, ++ 0xb9b9b9bb, ++ 0xb9b99bbb, ++ 0xb9b9b9bb, ++ 0xb9bb9b99, ++ 0x00000999, ++ 0x8a000000, ++ 0xaa88a888, ++ 0xa88888aa, ++ 0xa88a8a88, ++ 0xa88aa88a, ++ 0x88a8aaaa, ++ 0xa8aa8aaa, ++ 0x0888a88a, ++ 0x0b0b0b00, ++ 0x090b0b0b, ++ 0x0b090b0b, ++ 0x0909090b, ++ 0x09090b0b, ++ 0x09090b0b, ++ 0x09090b09, ++ 0x00000909, ++ 0x0a000000, ++ 0x0a080808, ++ 0x080a080a, ++ 0x080a0a08, ++ 0x080a080a, ++ 0x0808080a, ++ 0x0a0a0a08, ++ 0x0808080a, ++ 0xb0b0b000, ++ 0x9090b0b0, ++ 0x90b09090, ++ 0xb0b0b090, ++ 0xb0b090b0, ++ 0x90b0b0b0, ++ 0xb0b09090, ++ 0x00000090, ++ 0x80000000, ++ 0xa080a080, ++ 0xa08080a0, ++ 0xa0808080, ++ 0xa080a080, ++ 0x80a0a0a0, ++ 0xa0a080a0, ++ 0x00a0a0a0, ++ 0x22000000, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0xf2222220, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00000111, ++ 0x33000000, ++ 0x3333f333, ++ 0x33333333, ++ 0x333333f3, ++ 0xf3333330, ++ 0x33333333, ++ 0x33f33333, ++ 0x00000333, ++ 0x22000000, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0xf2222220, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x99000000, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb90, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88888000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00aaa888, ++ 0x88a88a00, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x000aa888, ++ 0x88880000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x08aaa888, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++const u32 noise_var_tbl_rev7[] = { ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++}; ++ ++static const u32 papd_comp_epsilon_tbl_core0_rev7[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00016023, ++ 0x00006028, ++ 0x00034036, ++ 0x0003402e, ++ 0x0007203c, ++ 0x0006e037, ++ 0x00070030, ++ 0x0009401f, ++ 0x0009a00f, ++ 0x000b600d, ++ 0x000c8007, ++ 0x000ce007, ++ 0x00101fff, ++ 0x00121ff9, ++ 0x0012e004, ++ 0x0014dffc, ++ 0x0016dff6, ++ 0x0018dfe9, ++ 0x001b3fe5, ++ 0x001c5fd0, ++ 0x001ddfc2, ++ 0x001f1fb6, ++ 0x00207fa4, ++ 0x00219f8f, ++ 0x0022ff7d, ++ 0x00247f6c, ++ 0x0024df5b, ++ 0x00267f4b, ++ 0x0027df3b, ++ 0x0029bf3b, ++ 0x002b5f2f, ++ 0x002d3f2e, ++ 0x002f5f2a, ++ 0x002fff15, ++ 0x00315f0b, ++ 0x0032defa, ++ 0x0033beeb, ++ 0x0034fed9, ++ 0x00353ec5, ++ 0x00361eb0, ++ 0x00363e9b, ++ 0x0036be87, ++ 0x0036be70, ++ 0x0038fe67, ++ 0x0044beb2, ++ 0x00513ef3, ++ 0x00595f11, ++ 0x00669f3d, ++ 0x0078dfdf, ++ 0x00a143aa, ++ 0x01642fff, ++ 0x0162afff, ++ 0x01620fff, ++ 0x0160cfff, ++ 0x015f0fff, ++ 0x015dafff, ++ 0x015bcfff, ++ 0x015bcfff, ++ 0x015b4fff, ++ 0x015acfff, ++ 0x01590fff, ++ 0x0156cfff, ++}; ++ ++static const u32 papd_cal_scalars_tbl_core0_rev7[] = { ++ 0x0b5e002d, ++ 0x0ae2002f, ++ 0x0a3b0032, ++ 0x09a70035, ++ 0x09220038, ++ 0x08ab003b, ++ 0x081f003f, ++ 0x07a20043, ++ 0x07340047, ++ 0x06d2004b, ++ 0x067a004f, ++ 0x06170054, ++ 0x05bf0059, ++ 0x0571005e, ++ 0x051e0064, ++ 0x04d3006a, ++ 0x04910070, ++ 0x044c0077, ++ 0x040f007e, ++ 0x03d90085, ++ 0x03a1008d, ++ 0x036f0095, ++ 0x033d009e, ++ 0x030b00a8, ++ 0x02e000b2, ++ 0x02b900bc, ++ 0x029200c7, ++ 0x026d00d3, ++ 0x024900e0, ++ 0x022900ed, ++ 0x020a00fb, ++ 0x01ec010a, ++ 0x01d20119, ++ 0x01b7012a, ++ 0x019e013c, ++ 0x0188014e, ++ 0x01720162, ++ 0x015d0177, ++ 0x0149018e, ++ 0x013701a5, ++ 0x012601be, ++ 0x011501d8, ++ 0x010601f4, ++ 0x00f70212, ++ 0x00e90231, ++ 0x00dc0253, ++ 0x00d00276, ++ 0x00c4029b, ++ 0x00b902c3, ++ 0x00af02ed, ++ 0x00a50319, ++ 0x009c0348, ++ 0x0093037a, ++ 0x008b03af, ++ 0x008303e6, ++ 0x007c0422, ++ 0x00750460, ++ 0x006e04a3, ++ 0x006804e9, ++ 0x00620533, ++ 0x005d0582, ++ 0x005805d6, ++ 0x0053062e, ++ 0x004e068c, ++}; ++ ++static const u32 papd_comp_epsilon_tbl_core1_rev7[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00016023, ++ 0x00006028, ++ 0x00034036, ++ 0x0003402e, ++ 0x0007203c, ++ 0x0006e037, ++ 0x00070030, ++ 0x0009401f, ++ 0x0009a00f, ++ 0x000b600d, ++ 0x000c8007, ++ 0x000ce007, ++ 0x00101fff, ++ 0x00121ff9, ++ 0x0012e004, ++ 0x0014dffc, ++ 0x0016dff6, ++ 0x0018dfe9, ++ 0x001b3fe5, ++ 0x001c5fd0, ++ 0x001ddfc2, ++ 0x001f1fb6, ++ 0x00207fa4, ++ 0x00219f8f, ++ 0x0022ff7d, ++ 0x00247f6c, ++ 0x0024df5b, ++ 0x00267f4b, ++ 0x0027df3b, ++ 0x0029bf3b, ++ 0x002b5f2f, ++ 0x002d3f2e, ++ 0x002f5f2a, ++ 0x002fff15, ++ 0x00315f0b, ++ 0x0032defa, ++ 0x0033beeb, ++ 0x0034fed9, ++ 0x00353ec5, ++ 0x00361eb0, ++ 0x00363e9b, ++ 0x0036be87, ++ 0x0036be70, ++ 0x0038fe67, ++ 0x0044beb2, ++ 0x00513ef3, ++ 0x00595f11, ++ 0x00669f3d, ++ 0x0078dfdf, ++ 0x00a143aa, ++ 0x01642fff, ++ 0x0162afff, ++ 0x01620fff, ++ 0x0160cfff, ++ 0x015f0fff, ++ 0x015dafff, ++ 0x015bcfff, ++ 0x015bcfff, ++ 0x015b4fff, ++ 0x015acfff, ++ 0x01590fff, ++ 0x0156cfff, ++}; ++ ++static const u32 papd_cal_scalars_tbl_core1_rev7[] = { ++ 0x0b5e002d, ++ 0x0ae2002f, ++ 0x0a3b0032, ++ 0x09a70035, ++ 0x09220038, ++ 0x08ab003b, ++ 0x081f003f, ++ 0x07a20043, ++ 0x07340047, ++ 0x06d2004b, ++ 0x067a004f, ++ 0x06170054, ++ 0x05bf0059, ++ 0x0571005e, ++ 0x051e0064, ++ 0x04d3006a, ++ 0x04910070, ++ 0x044c0077, ++ 0x040f007e, ++ 0x03d90085, ++ 0x03a1008d, ++ 0x036f0095, ++ 0x033d009e, ++ 0x030b00a8, ++ 0x02e000b2, ++ 0x02b900bc, ++ 0x029200c7, ++ 0x026d00d3, ++ 0x024900e0, ++ 0x022900ed, ++ 0x020a00fb, ++ 0x01ec010a, ++ 0x01d20119, ++ 0x01b7012a, ++ 0x019e013c, ++ 0x0188014e, ++ 0x01720162, ++ 0x015d0177, ++ 0x0149018e, ++ 0x013701a5, ++ 0x012601be, ++ 0x011501d8, ++ 0x010601f4, ++ 0x00f70212, ++ 0x00e90231, ++ 0x00dc0253, ++ 0x00d00276, ++ 0x00c4029b, ++ 0x00b902c3, ++ 0x00af02ed, ++ 0x00a50319, ++ 0x009c0348, ++ 0x0093037a, ++ 0x008b03af, ++ 0x008303e6, ++ 0x007c0422, ++ 0x00750460, ++ 0x006e04a3, ++ 0x006804e9, ++ 0x00620533, ++ 0x005d0582, ++ 0x005805d6, ++ 0x0053062e, ++ 0x004e068c, ++}; ++ ++const struct phytbl_info mimophytbl_info_rev7[] = { ++ {&frame_struct_rev3, ++ sizeof(frame_struct_rev3) / sizeof(frame_struct_rev3[0]), 10, 0, 32} ++ , ++ {&pilot_tbl_rev3, sizeof(pilot_tbl_rev3) / sizeof(pilot_tbl_rev3[0]), ++ 11, 0, 16} ++ , ++ {&tmap_tbl_rev7, sizeof(tmap_tbl_rev7) / sizeof(tmap_tbl_rev7[0]), 12, ++ 0, 32} ++ , ++ {&intlv_tbl_rev3, sizeof(intlv_tbl_rev3) / sizeof(intlv_tbl_rev3[0]), ++ 13, 0, 32} ++ , ++ {&tdtrn_tbl_rev3, sizeof(tdtrn_tbl_rev3) / sizeof(tdtrn_tbl_rev3[0]), ++ 14, 0, 32} ++ , ++ {&noise_var_tbl_rev7, ++ sizeof(noise_var_tbl_rev7) / sizeof(noise_var_tbl_rev7[0]), 16, 0, 32} ++ , ++ {&mcs_tbl_rev3, sizeof(mcs_tbl_rev3) / sizeof(mcs_tbl_rev3[0]), 18, 0, ++ 16} ++ , ++ {&tdi_tbl20_ant0_rev3, ++ sizeof(tdi_tbl20_ant0_rev3) / sizeof(tdi_tbl20_ant0_rev3[0]), 19, 128, ++ 32} ++ , ++ {&tdi_tbl20_ant1_rev3, ++ sizeof(tdi_tbl20_ant1_rev3) / sizeof(tdi_tbl20_ant1_rev3[0]), 19, 256, ++ 32} ++ , ++ {&tdi_tbl40_ant0_rev3, ++ sizeof(tdi_tbl40_ant0_rev3) / sizeof(tdi_tbl40_ant0_rev3[0]), 19, 640, ++ 32} ++ , ++ {&tdi_tbl40_ant1_rev3, ++ sizeof(tdi_tbl40_ant1_rev3) / sizeof(tdi_tbl40_ant1_rev3[0]), 19, 768, ++ 32} ++ , ++ {&pltlut_tbl_rev3, sizeof(pltlut_tbl_rev3) / sizeof(pltlut_tbl_rev3[0]), ++ 20, 0, 32} ++ , ++ {&chanest_tbl_rev3, ++ sizeof(chanest_tbl_rev3) / sizeof(chanest_tbl_rev3[0]), 22, 0, 32} ++ , ++ {&frame_lut_rev3, sizeof(frame_lut_rev3) / sizeof(frame_lut_rev3[0]), ++ 24, 0, 8} ++ , ++ {&est_pwr_lut_core0_rev3, ++ sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26, ++ 0, 8} ++ , ++ {&est_pwr_lut_core1_rev3, ++ sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27, ++ 0, 8} ++ , ++ {&adj_pwr_lut_core0_rev3, ++ sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26, ++ 64, 8} ++ , ++ {&adj_pwr_lut_core1_rev3, ++ sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27, ++ 64, 8} ++ , ++ {&gainctrl_lut_core0_rev3, ++ sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]), ++ 26, 192, 32} ++ , ++ {&gainctrl_lut_core1_rev3, ++ sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]), ++ 27, 192, 32} ++ , ++ {&iq_lut_core0_rev3, ++ sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32} ++ , ++ {&iq_lut_core1_rev3, ++ sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32} ++ , ++ {&loft_lut_core0_rev3, ++ sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448, ++ 16} ++ , ++ {&loft_lut_core1_rev3, ++ sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448, ++ 16} ++ , ++ {&papd_comp_rfpwr_tbl_core0_rev3, ++ sizeof(papd_comp_rfpwr_tbl_core0_rev3) / ++ sizeof(papd_comp_rfpwr_tbl_core0_rev3[0]), 26, 576, 16} ++ , ++ {&papd_comp_rfpwr_tbl_core1_rev3, ++ sizeof(papd_comp_rfpwr_tbl_core1_rev3) / ++ sizeof(papd_comp_rfpwr_tbl_core1_rev3[0]), 27, 576, 16} ++ , ++ {&papd_comp_epsilon_tbl_core0_rev7, ++ sizeof(papd_comp_epsilon_tbl_core0_rev7) / ++ sizeof(papd_comp_epsilon_tbl_core0_rev7[0]), 31, 0, 32} ++ , ++ {&papd_cal_scalars_tbl_core0_rev7, ++ sizeof(papd_cal_scalars_tbl_core0_rev7) / ++ sizeof(papd_cal_scalars_tbl_core0_rev7[0]), 32, 0, 32} ++ , ++ {&papd_comp_epsilon_tbl_core1_rev7, ++ sizeof(papd_comp_epsilon_tbl_core1_rev7) / ++ sizeof(papd_comp_epsilon_tbl_core1_rev7[0]), 33, 0, 32} ++ , ++ {&papd_cal_scalars_tbl_core1_rev7, ++ sizeof(papd_cal_scalars_tbl_core1_rev7) / ++ sizeof(papd_cal_scalars_tbl_core1_rev7[0]), 34, 0, 32} ++ , ++}; ++ ++const u32 mimophytbl_info_sz_rev7 = ++ sizeof(mimophytbl_info_rev7) / sizeof(mimophytbl_info_rev7[0]); ++ ++const struct phytbl_info mimophytbl_info_rev16[] = { ++ {&noise_var_tbl_rev7, ++ sizeof(noise_var_tbl_rev7) / sizeof(noise_var_tbl_rev7[0]), 16, 0, 32} ++ , ++ {&est_pwr_lut_core0_rev3, ++ sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26, ++ 0, 8} ++ , ++ {&est_pwr_lut_core1_rev3, ++ sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27, ++ 0, 8} ++ , ++ {&adj_pwr_lut_core0_rev3, ++ sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26, ++ 64, 8} ++ , ++ {&adj_pwr_lut_core1_rev3, ++ sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27, ++ 64, 8} ++ , ++ {&gainctrl_lut_core0_rev3, ++ sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]), ++ 26, 192, 32} ++ , ++ {&gainctrl_lut_core1_rev3, ++ sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]), ++ 27, 192, 32} ++ , ++ {&iq_lut_core0_rev3, ++ sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32} ++ , ++ {&iq_lut_core1_rev3, ++ sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32} ++ , ++ {&loft_lut_core0_rev3, ++ sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448, ++ 16} ++ , ++ {&loft_lut_core1_rev3, ++ sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448, ++ 16} ++ , ++}; ++ ++const u32 mimophytbl_info_sz_rev16 = ++ sizeof(mimophytbl_info_rev16) / sizeof(mimophytbl_info_rev16[0]); +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.h.orig 2011-11-09 13:46:58.282800170 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.h 2011-11-09 13:47:17.040565666 -0500 +@@ -0,0 +1,50 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#define ANT_SWCTRL_TBL_REV3_IDX (0) ++ ++#include ++#include "phy_int.h" ++ ++extern const struct phytbl_info mimophytbl_info_rev0[], ++ mimophytbl_info_rev0_volatile[]; ++ ++extern const u32 mimophytbl_info_sz_rev0, ++ mimophytbl_info_sz_rev0_volatile; ++ ++extern const struct phytbl_info mimophytbl_info_rev3[], ++ mimophytbl_info_rev3_volatile[], ++ mimophytbl_info_rev3_volatile1[], ++ mimophytbl_info_rev3_volatile2[], ++ mimophytbl_info_rev3_volatile3[]; ++ ++extern const u32 mimophytbl_info_sz_rev3, ++ mimophytbl_info_sz_rev3_volatile, ++ mimophytbl_info_sz_rev3_volatile1, ++ mimophytbl_info_sz_rev3_volatile2, ++ mimophytbl_info_sz_rev3_volatile3; ++ ++extern const u32 noise_var_tbl_rev3[]; ++ ++extern const struct phytbl_info mimophytbl_info_rev7[]; ++ ++extern const u32 mimophytbl_info_sz_rev7; ++ ++extern const u32 noise_var_tbl_rev7[]; ++ ++extern const struct phytbl_info mimophytbl_info_rev16[]; ++ ++extern const u32 mimophytbl_info_sz_rev16; +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c.orig 2011-11-09 13:46:58.282800170 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c 2011-11-09 13:47:17.040565666 -0500 +@@ -0,0 +1,225 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/* ++ * This is "two-way" interface, acting as the SHIM layer between driver ++ * and PHY layer. The driver can optionally call this translation layer ++ * to do some preprocessing, then reach PHY. On the PHY->driver direction, ++ * all calls go through this layer since PHY doesn't have access to the ++ * driver's brcms_hardware pointer. ++ */ ++#include ++#include ++ ++#include "main.h" ++#include "mac80211_if.h" ++#include "phy_shim.h" ++ ++/* PHY SHIM module specific state */ ++struct phy_shim_info { ++ struct brcms_hardware *wlc_hw; /* pointer to main wlc_hw structure */ ++ struct brcms_c_info *wlc; /* pointer to main wlc structure */ ++ struct brcms_info *wl; /* pointer to os-specific private state */ ++}; ++ ++struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw, ++ struct brcms_info *wl, ++ struct brcms_c_info *wlc) { ++ struct phy_shim_info *physhim = NULL; ++ ++ physhim = kzalloc(sizeof(struct phy_shim_info), GFP_ATOMIC); ++ if (!physhim) ++ return NULL; ++ ++ physhim->wlc_hw = wlc_hw; ++ physhim->wlc = wlc; ++ physhim->wl = wl; ++ ++ return physhim; ++} ++ ++void wlc_phy_shim_detach(struct phy_shim_info *physhim) ++{ ++ kfree(physhim); ++} ++ ++struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim, ++ void (*fn)(struct brcms_phy *pi), ++ void *arg, const char *name) ++{ ++ return (struct wlapi_timer *) ++ brcms_init_timer(physhim->wl, (void (*)(void *))fn, ++ arg, name); ++} ++ ++void wlapi_free_timer(struct wlapi_timer *t) ++{ ++ brcms_free_timer((struct brcms_timer *)t); ++} ++ ++void ++wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic) ++{ ++ brcms_add_timer((struct brcms_timer *)t, ms, periodic); ++} ++ ++bool wlapi_del_timer(struct wlapi_timer *t) ++{ ++ return brcms_del_timer((struct brcms_timer *)t); ++} ++ ++void wlapi_intrson(struct phy_shim_info *physhim) ++{ ++ brcms_intrson(physhim->wl); ++} ++ ++u32 wlapi_intrsoff(struct phy_shim_info *physhim) ++{ ++ return brcms_intrsoff(physhim->wl); ++} ++ ++void wlapi_intrsrestore(struct phy_shim_info *physhim, u32 macintmask) ++{ ++ brcms_intrsrestore(physhim->wl, macintmask); ++} ++ ++void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset, u16 v) ++{ ++ brcms_b_write_shm(physhim->wlc_hw, offset, v); ++} ++ ++u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset) ++{ ++ return brcms_b_read_shm(physhim->wlc_hw, offset); ++} ++ ++void ++wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx, u16 mask, ++ u16 val, int bands) ++{ ++ brcms_b_mhf(physhim->wlc_hw, idx, mask, val, bands); ++} ++ ++void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags) ++{ ++ brcms_b_corereset(physhim->wlc_hw, flags); ++} ++ ++void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim) ++{ ++ brcms_c_suspend_mac_and_wait(physhim->wlc); ++} ++ ++void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode) ++{ ++ brcms_b_switch_macfreq(physhim->wlc_hw, spurmode); ++} ++ ++void wlapi_enable_mac(struct phy_shim_info *physhim) ++{ ++ brcms_c_enable_mac(physhim->wlc); ++} ++ ++void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask, u32 val) ++{ ++ brcms_b_mctrl(physhim->wlc_hw, mask, val); ++} ++ ++void wlapi_bmac_phy_reset(struct phy_shim_info *physhim) ++{ ++ brcms_b_phy_reset(physhim->wlc_hw); ++} ++ ++void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw) ++{ ++ brcms_b_bw_set(physhim->wlc_hw, bw); ++} ++ ++u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim) ++{ ++ return brcms_b_get_txant(physhim->wlc_hw); ++} ++ ++void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk) ++{ ++ brcms_b_phyclk_fgc(physhim->wlc_hw, clk); ++} ++ ++void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk) ++{ ++ brcms_b_macphyclk_set(physhim->wlc_hw, clk); ++} ++ ++void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on) ++{ ++ brcms_b_core_phypll_ctl(physhim->wlc_hw, on); ++} ++ ++void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim) ++{ ++ brcms_b_core_phypll_reset(physhim->wlc_hw); ++} ++ ++void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info *physhim) ++{ ++ brcms_c_ucode_wake_override_set(physhim->wlc_hw, ++ BRCMS_WAKE_OVERRIDE_PHYREG); ++} ++ ++void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info *physhim) ++{ ++ brcms_c_ucode_wake_override_clear(physhim->wlc_hw, ++ BRCMS_WAKE_OVERRIDE_PHYREG); ++} ++ ++void ++wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int offset, ++ int len, void *buf) ++{ ++ brcms_b_write_template_ram(physhim->wlc_hw, offset, len, buf); ++} ++ ++u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim, u8 rate) ++{ ++ return brcms_b_rate_shm_offset(physhim->wlc_hw, rate); ++} ++ ++void wlapi_ucode_sample_init(struct phy_shim_info *physhim) ++{ ++} ++ ++void ++wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint offset, void *buf, ++ int len, u32 sel) ++{ ++ brcms_b_copyfrom_objmem(physhim->wlc_hw, offset, buf, len, sel); ++} ++ ++void ++wlapi_copyto_objmem(struct phy_shim_info *physhim, uint offset, const void *buf, ++ int l, u32 sel) ++{ ++ brcms_b_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel); ++} ++ ++char *wlapi_getvar(struct phy_shim_info *physhim, enum brcms_srom_id id) ++{ ++ return getvar(physhim->wlc_hw->sih, id); ++} ++int wlapi_getintvar(struct phy_shim_info *physhim, enum brcms_srom_id id) ++{ ++ return getintvar(physhim->wlc_hw->sih, id); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h.orig 2011-11-09 13:46:58.282800170 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h 2011-11-09 13:47:17.041565653 -0500 +@@ -0,0 +1,182 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/* ++ * phy_shim.h: stuff defined in phy_shim.c and included only by the phy ++ */ ++ ++#ifndef _BRCM_PHY_SHIM_H_ ++#define _BRCM_PHY_SHIM_H_ ++ ++#include "types.h" ++ ++#define RADAR_TYPE_NONE 0 /* Radar type None */ ++#define RADAR_TYPE_ETSI_1 1 /* ETSI 1 Radar type */ ++#define RADAR_TYPE_ETSI_2 2 /* ETSI 2 Radar type */ ++#define RADAR_TYPE_ETSI_3 3 /* ETSI 3 Radar type */ ++#define RADAR_TYPE_ITU_E 4 /* ITU E Radar type */ ++#define RADAR_TYPE_ITU_K 5 /* ITU K Radar type */ ++#define RADAR_TYPE_UNCLASSIFIED 6 /* Unclassified Radar type */ ++#define RADAR_TYPE_BIN5 7 /* long pulse radar type */ ++#define RADAR_TYPE_STG2 8 /* staggered-2 radar */ ++#define RADAR_TYPE_STG3 9 /* staggered-3 radar */ ++#define RADAR_TYPE_FRA 10 /* French radar */ ++ ++/* French radar pulse widths */ ++#define FRA_T1_20MHZ 52770 ++#define FRA_T2_20MHZ 61538 ++#define FRA_T3_20MHZ 66002 ++#define FRA_T1_40MHZ 105541 ++#define FRA_T2_40MHZ 123077 ++#define FRA_T3_40MHZ 132004 ++#define FRA_ERR_20MHZ 60 ++#define FRA_ERR_40MHZ 120 ++ ++#define ANTSEL_NA 0 /* No boardlevel selection available */ ++#define ANTSEL_2x4 1 /* 2x4 boardlevel selection available */ ++#define ANTSEL_2x3 2 /* 2x3 CB2 boardlevel selection available */ ++ ++/* Rx Antenna diversity control values */ ++#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */ ++#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */ ++#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */ ++#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */ ++#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */ ++#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0 /* default antdiv setting */ ++ ++#define WL_ANT_RX_MAX 2 /* max 2 receive antennas */ ++#define WL_ANT_HT_RX_MAX 3 /* max 3 receive antennas/cores */ ++#define WL_ANT_IDX_1 0 /* antenna index 1 */ ++#define WL_ANT_IDX_2 1 /* antenna index 2 */ ++ ++/* values for n_preamble_type */ ++#define BRCMS_N_PREAMBLE_MIXEDMODE 0 ++#define BRCMS_N_PREAMBLE_GF 1 ++#define BRCMS_N_PREAMBLE_GF_BRCM 2 ++ ++#define WL_TX_POWER_RATES_LEGACY 45 ++#define WL_TX_POWER_MCS20_FIRST 12 ++#define WL_TX_POWER_MCS20_NUM 16 ++#define WL_TX_POWER_MCS40_FIRST 28 ++#define WL_TX_POWER_MCS40_NUM 17 ++ ++ ++#define WL_TX_POWER_RATES 101 ++#define WL_TX_POWER_CCK_FIRST 0 ++#define WL_TX_POWER_CCK_NUM 4 ++/* Index for first 20MHz OFDM SISO rate */ ++#define WL_TX_POWER_OFDM_FIRST 4 ++/* Index for first 20MHz OFDM CDD rate */ ++#define WL_TX_POWER_OFDM20_CDD_FIRST 12 ++/* Index for first 40MHz OFDM SISO rate */ ++#define WL_TX_POWER_OFDM40_SISO_FIRST 52 ++/* Index for first 40MHz OFDM CDD rate */ ++#define WL_TX_POWER_OFDM40_CDD_FIRST 60 ++#define WL_TX_POWER_OFDM_NUM 8 ++/* Index for first 20MHz MCS SISO rate */ ++#define WL_TX_POWER_MCS20_SISO_FIRST 20 ++/* Index for first 20MHz MCS CDD rate */ ++#define WL_TX_POWER_MCS20_CDD_FIRST 28 ++/* Index for first 20MHz MCS STBC rate */ ++#define WL_TX_POWER_MCS20_STBC_FIRST 36 ++/* Index for first 20MHz MCS SDM rate */ ++#define WL_TX_POWER_MCS20_SDM_FIRST 44 ++/* Index for first 40MHz MCS SISO rate */ ++#define WL_TX_POWER_MCS40_SISO_FIRST 68 ++/* Index for first 40MHz MCS CDD rate */ ++#define WL_TX_POWER_MCS40_CDD_FIRST 76 ++/* Index for first 40MHz MCS STBC rate */ ++#define WL_TX_POWER_MCS40_STBC_FIRST 84 ++/* Index for first 40MHz MCS SDM rate */ ++#define WL_TX_POWER_MCS40_SDM_FIRST 92 ++#define WL_TX_POWER_MCS_1_STREAM_NUM 8 ++#define WL_TX_POWER_MCS_2_STREAM_NUM 8 ++/* Index for 40MHz rate MCS 32 */ ++#define WL_TX_POWER_MCS_32 100 ++#define WL_TX_POWER_MCS_32_NUM 1 ++ ++/* sslpnphy specifics */ ++/* Index for first 20MHz MCS SISO rate */ ++#define WL_TX_POWER_MCS20_SISO_FIRST_SSN 12 ++ ++/* struct tx_power::flags bits */ ++#define WL_TX_POWER_F_ENABLED 1 ++#define WL_TX_POWER_F_HW 2 ++#define WL_TX_POWER_F_MIMO 4 ++#define WL_TX_POWER_F_SISO 8 ++ ++/* values to force tx/rx chain */ ++#define BRCMS_N_TXRX_CHAIN0 0 ++#define BRCMS_N_TXRX_CHAIN1 1 ++ ++struct brcms_phy; ++ ++extern struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw, ++ struct brcms_info *wl, ++ struct brcms_c_info *wlc); ++extern void wlc_phy_shim_detach(struct phy_shim_info *physhim); ++ ++/* PHY to WL utility functions */ ++extern struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim, ++ void (*fn) (struct brcms_phy *pi), ++ void *arg, const char *name); ++extern void wlapi_free_timer(struct wlapi_timer *t); ++extern void wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic); ++extern bool wlapi_del_timer(struct wlapi_timer *t); ++extern void wlapi_intrson(struct phy_shim_info *physhim); ++extern u32 wlapi_intrsoff(struct phy_shim_info *physhim); ++extern void wlapi_intrsrestore(struct phy_shim_info *physhim, ++ u32 macintmask); ++ ++extern void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset, ++ u16 v); ++extern u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset); ++extern void wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx, ++ u16 mask, u16 val, int bands); ++extern void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags); ++extern void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim); ++extern void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode); ++extern void wlapi_enable_mac(struct phy_shim_info *physhim); ++extern void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask, ++ u32 val); ++extern void wlapi_bmac_phy_reset(struct phy_shim_info *physhim); ++extern void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw); ++extern void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk); ++extern void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk); ++extern void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on); ++extern void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim); ++extern void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info * ++ physhim); ++extern void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info * ++ physhim); ++extern void wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int o, ++ int len, void *buf); ++extern u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim, ++ u8 rate); ++extern void wlapi_ucode_sample_init(struct phy_shim_info *physhim); ++extern void wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint, ++ void *buf, int, u32 sel); ++extern void wlapi_copyto_objmem(struct phy_shim_info *physhim, uint, ++ const void *buf, int, u32); ++ ++extern void wlapi_high_update_phy_mode(struct phy_shim_info *physhim, ++ u32 phy_mode); ++extern u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim); ++extern char *wlapi_getvar(struct phy_shim_info *physhim, enum brcms_srom_id id); ++extern int wlapi_getintvar(struct phy_shim_info *physhim, ++ enum brcms_srom_id id); ++ ++#endif /* _BRCM_PHY_SHIM_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.c.orig 2011-11-09 13:46:58.283800157 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.c 2011-11-09 13:47:17.041565653 -0500 +@@ -0,0 +1,458 @@ ++/* ++ * Copyright (c) 2011 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include "pub.h" ++#include "aiutils.h" ++#include "pmu.h" ++ ++/* ++ * external LPO crystal frequency ++ */ ++#define EXT_ILP_HZ 32768 ++ ++/* ++ * Duration for ILP clock frequency measurment in milliseconds ++ * ++ * remark: 1000 must be an integer multiple of this duration ++ */ ++#define ILP_CALC_DUR 10 ++ ++/* Fields in pmucontrol */ ++#define PCTL_ILP_DIV_MASK 0xffff0000 ++#define PCTL_ILP_DIV_SHIFT 16 ++#define PCTL_PLL_PLLCTL_UPD 0x00000400 /* rev 2 */ ++#define PCTL_NOILP_ON_WAIT 0x00000200 /* rev 1 */ ++#define PCTL_HT_REQ_EN 0x00000100 ++#define PCTL_ALP_REQ_EN 0x00000080 ++#define PCTL_XTALFREQ_MASK 0x0000007c ++#define PCTL_XTALFREQ_SHIFT 2 ++#define PCTL_ILP_DIV_EN 0x00000002 ++#define PCTL_LPO_SEL 0x00000001 ++ ++/* ILP clock */ ++#define ILP_CLOCK 32000 ++ ++/* ALP clock on pre-PMU chips */ ++#define ALP_CLOCK 20000000 ++ ++/* pmustatus */ ++#define PST_EXTLPOAVAIL 0x0100 ++#define PST_WDRESET 0x0080 ++#define PST_INTPEND 0x0040 ++#define PST_SBCLKST 0x0030 ++#define PST_SBCLKST_ILP 0x0010 ++#define PST_SBCLKST_ALP 0x0020 ++#define PST_SBCLKST_HT 0x0030 ++#define PST_ALPAVAIL 0x0008 ++#define PST_HTAVAIL 0x0004 ++#define PST_RESINIT 0x0003 ++ ++/* PMU resource bit position */ ++#define PMURES_BIT(bit) (1 << (bit)) ++ ++/* PMU corerev and chip specific PLL controls. ++ * PMU_PLL_XX where is PMU corerev and is an arbitrary ++ * number to differentiate different PLLs controlled by the same PMU rev. ++ */ ++/* pllcontrol registers: ++ * ndiv_pwrdn, pwrdn_ch, refcomp_pwrdn, dly_ch, ++ * p1div, p2div, _bypass_sdmod ++ */ ++#define PMU1_PLL0_PLLCTL0 0 ++#define PMU1_PLL0_PLLCTL1 1 ++#define PMU1_PLL0_PLLCTL2 2 ++#define PMU1_PLL0_PLLCTL3 3 ++#define PMU1_PLL0_PLLCTL4 4 ++#define PMU1_PLL0_PLLCTL5 5 ++ ++/* pmu XtalFreqRatio */ ++#define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF ++#define PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000 ++#define PMU_XTALFREQ_REG_MEASURE_SHIFT 31 ++ ++/* 4313 resources */ ++#define RES4313_BB_PU_RSRC 0 ++#define RES4313_ILP_REQ_RSRC 1 ++#define RES4313_XTAL_PU_RSRC 2 ++#define RES4313_ALP_AVAIL_RSRC 3 ++#define RES4313_RADIO_PU_RSRC 4 ++#define RES4313_BG_PU_RSRC 5 ++#define RES4313_VREG1P4_PU_RSRC 6 ++#define RES4313_AFE_PWRSW_RSRC 7 ++#define RES4313_RX_PWRSW_RSRC 8 ++#define RES4313_TX_PWRSW_RSRC 9 ++#define RES4313_BB_PWRSW_RSRC 10 ++#define RES4313_SYNTH_PWRSW_RSRC 11 ++#define RES4313_MISC_PWRSW_RSRC 12 ++#define RES4313_BB_PLL_PWRSW_RSRC 13 ++#define RES4313_HT_AVAIL_RSRC 14 ++#define RES4313_MACPHY_CLK_AVAIL_RSRC 15 ++ ++/* Determine min/max rsrc masks. Value 0 leaves hardware at default. */ ++static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax) ++{ ++ u32 min_mask = 0, max_mask = 0; ++ uint rsrcs; ++ ++ /* # resources */ ++ rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT; ++ ++ /* determine min/max rsrc masks */ ++ switch (sih->chip) { ++ case BCM43224_CHIP_ID: ++ case BCM43225_CHIP_ID: ++ /* ??? */ ++ break; ++ ++ case BCM4313_CHIP_ID: ++ min_mask = PMURES_BIT(RES4313_BB_PU_RSRC) | ++ PMURES_BIT(RES4313_XTAL_PU_RSRC) | ++ PMURES_BIT(RES4313_ALP_AVAIL_RSRC) | ++ PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC); ++ max_mask = 0xffff; ++ break; ++ default: ++ break; ++ } ++ ++ *pmin = min_mask; ++ *pmax = max_mask; ++} ++ ++static void ++si_pmu_spuravoid_pllupdate(struct si_pub *sih, struct chipcregs __iomem *cc, ++ u8 spuravoid) ++{ ++ u32 tmp = 0; ++ ++ switch (sih->chip) { ++ case BCM43224_CHIP_ID: ++ case BCM43225_CHIP_ID: ++ if (spuravoid == 1) { ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0); ++ W_REG(&cc->pllcontrol_data, 0x11500010); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1); ++ W_REG(&cc->pllcontrol_data, 0x000C0C06); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2); ++ W_REG(&cc->pllcontrol_data, 0x0F600a08); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3); ++ W_REG(&cc->pllcontrol_data, 0x00000000); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4); ++ W_REG(&cc->pllcontrol_data, 0x2001E920); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5); ++ W_REG(&cc->pllcontrol_data, 0x88888815); ++ } else { ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0); ++ W_REG(&cc->pllcontrol_data, 0x11100010); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1); ++ W_REG(&cc->pllcontrol_data, 0x000c0c06); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2); ++ W_REG(&cc->pllcontrol_data, 0x03000a08); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3); ++ W_REG(&cc->pllcontrol_data, 0x00000000); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4); ++ W_REG(&cc->pllcontrol_data, 0x200005c0); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5); ++ W_REG(&cc->pllcontrol_data, 0x88888815); ++ } ++ tmp = 1 << 10; ++ break; ++ ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0); ++ W_REG(&cc->pllcontrol_data, 0x11100008); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1); ++ W_REG(&cc->pllcontrol_data, 0x0c000c06); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2); ++ W_REG(&cc->pllcontrol_data, 0x03000a08); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3); ++ W_REG(&cc->pllcontrol_data, 0x00000000); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4); ++ W_REG(&cc->pllcontrol_data, 0x200005c0); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5); ++ W_REG(&cc->pllcontrol_data, 0x88888855); ++ ++ tmp = 1 << 10; ++ break; ++ ++ default: ++ /* bail out */ ++ return; ++ } ++ ++ tmp |= R_REG(&cc->pmucontrol); ++ W_REG(&cc->pmucontrol, tmp); ++} ++ ++u16 si_pmu_fast_pwrup_delay(struct si_pub *sih) ++{ ++ uint delay = PMU_MAX_TRANSITION_DLY; ++ ++ switch (sih->chip) { ++ case BCM43224_CHIP_ID: ++ case BCM43225_CHIP_ID: ++ case BCM4313_CHIP_ID: ++ delay = 3700; ++ break; ++ default: ++ break; ++ } ++ ++ return (u16) delay; ++} ++ ++void si_pmu_sprom_enable(struct si_pub *sih, bool enable) ++{ ++ struct chipcregs __iomem *cc; ++ uint origidx; ++ ++ /* Remember original core before switch to chipc */ ++ origidx = ai_coreidx(sih); ++ cc = ai_setcoreidx(sih, SI_CC_IDX); ++ ++ /* Return to original core */ ++ ai_setcoreidx(sih, origidx); ++} ++ ++/* Read/write a chipcontrol reg */ ++u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) ++{ ++ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol_addr), ++ ~0, reg); ++ return ai_corereg(sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_data), mask, ++ val); ++} ++ ++/* Read/write a regcontrol reg */ ++u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) ++{ ++ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, regcontrol_addr), ++ ~0, reg); ++ return ai_corereg(sih, SI_CC_IDX, ++ offsetof(struct chipcregs, regcontrol_data), mask, ++ val); ++} ++ ++/* Read/write a pllcontrol reg */ ++u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) ++{ ++ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pllcontrol_addr), ++ ~0, reg); ++ return ai_corereg(sih, SI_CC_IDX, ++ offsetof(struct chipcregs, pllcontrol_data), mask, ++ val); ++} ++ ++/* PMU PLL update */ ++void si_pmu_pllupd(struct si_pub *sih) ++{ ++ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pmucontrol), ++ PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD); ++} ++ ++/* query alp/xtal clock frequency */ ++u32 si_pmu_alp_clock(struct si_pub *sih) ++{ ++ u32 clock = ALP_CLOCK; ++ ++ /* bail out with default */ ++ if (!(sih->cccaps & CC_CAP_PMU)) ++ return clock; ++ ++ switch (sih->chip) { ++ case BCM43224_CHIP_ID: ++ case BCM43225_CHIP_ID: ++ case BCM4313_CHIP_ID: ++ /* always 20Mhz */ ++ clock = 20000 * 1000; ++ break; ++ default: ++ break; ++ } ++ ++ return clock; ++} ++ ++void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid) ++{ ++ struct chipcregs __iomem *cc; ++ uint origidx, intr_val; ++ ++ /* Remember original core before switch to chipc */ ++ cc = (struct chipcregs __iomem *) ++ ai_switch_core(sih, CC_CORE_ID, &origidx, &intr_val); ++ ++ /* update the pll changes */ ++ si_pmu_spuravoid_pllupdate(sih, cc, spuravoid); ++ ++ /* Return to original core */ ++ ai_restore_core(sih, origidx, intr_val); ++} ++ ++/* initialize PMU */ ++void si_pmu_init(struct si_pub *sih) ++{ ++ struct chipcregs __iomem *cc; ++ uint origidx; ++ ++ /* Remember original core before switch to chipc */ ++ origidx = ai_coreidx(sih); ++ cc = ai_setcoreidx(sih, SI_CC_IDX); ++ ++ if (sih->pmurev == 1) ++ AND_REG(&cc->pmucontrol, ~PCTL_NOILP_ON_WAIT); ++ else if (sih->pmurev >= 2) ++ OR_REG(&cc->pmucontrol, PCTL_NOILP_ON_WAIT); ++ ++ /* Return to original core */ ++ ai_setcoreidx(sih, origidx); ++} ++ ++/* initialize PMU chip controls and other chip level stuff */ ++void si_pmu_chip_init(struct si_pub *sih) ++{ ++ uint origidx; ++ ++ /* Gate off SPROM clock and chip select signals */ ++ si_pmu_sprom_enable(sih, false); ++ ++ /* Remember original core */ ++ origidx = ai_coreidx(sih); ++ ++ /* Return to original core */ ++ ai_setcoreidx(sih, origidx); ++} ++ ++/* initialize PMU switch/regulators */ ++void si_pmu_swreg_init(struct si_pub *sih) ++{ ++} ++ ++/* initialize PLL */ ++void si_pmu_pll_init(struct si_pub *sih, uint xtalfreq) ++{ ++ struct chipcregs __iomem *cc; ++ uint origidx; ++ ++ /* Remember original core before switch to chipc */ ++ origidx = ai_coreidx(sih); ++ cc = ai_setcoreidx(sih, SI_CC_IDX); ++ ++ switch (sih->chip) { ++ case BCM4313_CHIP_ID: ++ case BCM43224_CHIP_ID: ++ case BCM43225_CHIP_ID: ++ /* ??? */ ++ break; ++ default: ++ break; ++ } ++ ++ /* Return to original core */ ++ ai_setcoreidx(sih, origidx); ++} ++ ++/* initialize PMU resources */ ++void si_pmu_res_init(struct si_pub *sih) ++{ ++ struct chipcregs __iomem *cc; ++ uint origidx; ++ u32 min_mask = 0, max_mask = 0; ++ ++ /* Remember original core before switch to chipc */ ++ origidx = ai_coreidx(sih); ++ cc = ai_setcoreidx(sih, SI_CC_IDX); ++ ++ /* Determine min/max rsrc masks */ ++ si_pmu_res_masks(sih, &min_mask, &max_mask); ++ ++ /* It is required to program max_mask first and then min_mask */ ++ ++ /* Program max resource mask */ ++ ++ if (max_mask) ++ W_REG(&cc->max_res_mask, max_mask); ++ ++ /* Program min resource mask */ ++ ++ if (min_mask) ++ W_REG(&cc->min_res_mask, min_mask); ++ ++ /* Add some delay; allow resources to come up and settle. */ ++ mdelay(2); ++ ++ /* Return to original core */ ++ ai_setcoreidx(sih, origidx); ++} ++ ++u32 si_pmu_measure_alpclk(struct si_pub *sih) ++{ ++ struct chipcregs __iomem *cc; ++ uint origidx; ++ u32 alp_khz; ++ ++ if (sih->pmurev < 10) ++ return 0; ++ ++ /* Remember original core before switch to chipc */ ++ origidx = ai_coreidx(sih); ++ cc = ai_setcoreidx(sih, SI_CC_IDX); ++ ++ if (R_REG(&cc->pmustatus) & PST_EXTLPOAVAIL) { ++ u32 ilp_ctr, alp_hz; ++ ++ /* ++ * Enable the reg to measure the freq, ++ * in case it was disabled before ++ */ ++ W_REG(&cc->pmu_xtalfreq, ++ 1U << PMU_XTALFREQ_REG_MEASURE_SHIFT); ++ ++ /* Delay for well over 4 ILP clocks */ ++ udelay(1000); ++ ++ /* Read the latched number of ALP ticks per 4 ILP ticks */ ++ ilp_ctr = ++ R_REG(&cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK; ++ ++ /* ++ * Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT ++ * bit to save power ++ */ ++ W_REG(&cc->pmu_xtalfreq, 0); ++ ++ /* Calculate ALP frequency */ ++ alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4; ++ ++ /* ++ * Round to nearest 100KHz, and at ++ * the same time convert to KHz ++ */ ++ alp_khz = (alp_hz + 50000) / 100000 * 100; ++ } else ++ alp_khz = 0; ++ ++ /* Return to original core */ ++ ai_setcoreidx(sih, origidx); ++ ++ return alp_khz; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.h.orig 2011-11-09 13:46:58.283800157 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.h 2011-11-09 13:47:17.041565653 -0500 +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef _BRCM_PMU_H_ ++#define _BRCM_PMU_H_ ++ ++#include "types.h" ++ ++extern u16 si_pmu_fast_pwrup_delay(struct si_pub *sih); ++extern void si_pmu_sprom_enable(struct si_pub *sih, bool enable); ++extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); ++extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); ++extern u32 si_pmu_alp_clock(struct si_pub *sih); ++extern void si_pmu_pllupd(struct si_pub *sih); ++extern void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid); ++extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); ++extern void si_pmu_init(struct si_pub *sih); ++extern void si_pmu_chip_init(struct si_pub *sih); ++extern void si_pmu_pll_init(struct si_pub *sih, u32 xtalfreq); ++extern void si_pmu_res_init(struct si_pub *sih); ++extern void si_pmu_swreg_init(struct si_pub *sih); ++extern u32 si_pmu_measure_alpclk(struct si_pub *sih); ++ ++#endif /* _BRCM_PMU_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pub.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pub.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pub.h.orig 2011-11-09 13:46:58.283800157 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pub.h 2011-11-09 13:47:17.042565640 -0500 +@@ -0,0 +1,634 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_PUB_H_ ++#define _BRCM_PUB_H_ ++ ++#include ++#include "types.h" ++#include "defs.h" ++ ++enum brcms_srom_id { ++ BRCMS_SROM_NULL, ++ BRCMS_SROM_CONT, ++ BRCMS_SROM_AA2G, ++ BRCMS_SROM_AA5G, ++ BRCMS_SROM_AG0, ++ BRCMS_SROM_AG1, ++ BRCMS_SROM_AG2, ++ BRCMS_SROM_AG3, ++ BRCMS_SROM_ANTSWCTL2G, ++ BRCMS_SROM_ANTSWCTL5G, ++ BRCMS_SROM_ANTSWITCH, ++ BRCMS_SROM_BOARDFLAGS2, ++ BRCMS_SROM_BOARDFLAGS, ++ BRCMS_SROM_BOARDNUM, ++ BRCMS_SROM_BOARDREV, ++ BRCMS_SROM_BOARDTYPE, ++ BRCMS_SROM_BW40PO, ++ BRCMS_SROM_BWDUPPO, ++ BRCMS_SROM_BXA2G, ++ BRCMS_SROM_BXA5G, ++ BRCMS_SROM_CC, ++ BRCMS_SROM_CCK2GPO, ++ BRCMS_SROM_CCKBW202GPO, ++ BRCMS_SROM_CCKBW20UL2GPO, ++ BRCMS_SROM_CCODE, ++ BRCMS_SROM_CDDPO, ++ BRCMS_SROM_DEVID, ++ BRCMS_SROM_ET1MACADDR, ++ BRCMS_SROM_EXTPAGAIN2G, ++ BRCMS_SROM_EXTPAGAIN5G, ++ BRCMS_SROM_FREQOFFSET_CORR, ++ BRCMS_SROM_HW_IQCAL_EN, ++ BRCMS_SROM_IL0MACADDR, ++ BRCMS_SROM_IQCAL_SWP_DIS, ++ BRCMS_SROM_LEDBH0, ++ BRCMS_SROM_LEDBH1, ++ BRCMS_SROM_LEDBH2, ++ BRCMS_SROM_LEDBH3, ++ BRCMS_SROM_LEDDC, ++ BRCMS_SROM_LEGOFDM40DUPPO, ++ BRCMS_SROM_LEGOFDMBW202GPO, ++ BRCMS_SROM_LEGOFDMBW205GHPO, ++ BRCMS_SROM_LEGOFDMBW205GLPO, ++ BRCMS_SROM_LEGOFDMBW205GMPO, ++ BRCMS_SROM_LEGOFDMBW20UL2GPO, ++ BRCMS_SROM_LEGOFDMBW20UL5GHPO, ++ BRCMS_SROM_LEGOFDMBW20UL5GLPO, ++ BRCMS_SROM_LEGOFDMBW20UL5GMPO, ++ BRCMS_SROM_MACADDR, ++ BRCMS_SROM_MCS2GPO0, ++ BRCMS_SROM_MCS2GPO1, ++ BRCMS_SROM_MCS2GPO2, ++ BRCMS_SROM_MCS2GPO3, ++ BRCMS_SROM_MCS2GPO4, ++ BRCMS_SROM_MCS2GPO5, ++ BRCMS_SROM_MCS2GPO6, ++ BRCMS_SROM_MCS2GPO7, ++ BRCMS_SROM_MCS32PO, ++ BRCMS_SROM_MCS5GHPO0, ++ BRCMS_SROM_MCS5GHPO1, ++ BRCMS_SROM_MCS5GHPO2, ++ BRCMS_SROM_MCS5GHPO3, ++ BRCMS_SROM_MCS5GHPO4, ++ BRCMS_SROM_MCS5GHPO5, ++ BRCMS_SROM_MCS5GHPO6, ++ BRCMS_SROM_MCS5GHPO7, ++ BRCMS_SROM_MCS5GLPO0, ++ BRCMS_SROM_MCS5GLPO1, ++ BRCMS_SROM_MCS5GLPO2, ++ BRCMS_SROM_MCS5GLPO3, ++ BRCMS_SROM_MCS5GLPO4, ++ BRCMS_SROM_MCS5GLPO5, ++ BRCMS_SROM_MCS5GLPO6, ++ BRCMS_SROM_MCS5GLPO7, ++ BRCMS_SROM_MCS5GPO0, ++ BRCMS_SROM_MCS5GPO1, ++ BRCMS_SROM_MCS5GPO2, ++ BRCMS_SROM_MCS5GPO3, ++ BRCMS_SROM_MCS5GPO4, ++ BRCMS_SROM_MCS5GPO5, ++ BRCMS_SROM_MCS5GPO6, ++ BRCMS_SROM_MCS5GPO7, ++ BRCMS_SROM_MCSBW202GPO, ++ BRCMS_SROM_MCSBW205GHPO, ++ BRCMS_SROM_MCSBW205GLPO, ++ BRCMS_SROM_MCSBW205GMPO, ++ BRCMS_SROM_MCSBW20UL2GPO, ++ BRCMS_SROM_MCSBW20UL5GHPO, ++ BRCMS_SROM_MCSBW20UL5GLPO, ++ BRCMS_SROM_MCSBW20UL5GMPO, ++ BRCMS_SROM_MCSBW402GPO, ++ BRCMS_SROM_MCSBW405GHPO, ++ BRCMS_SROM_MCSBW405GLPO, ++ BRCMS_SROM_MCSBW405GMPO, ++ BRCMS_SROM_MEASPOWER, ++ BRCMS_SROM_OFDM2GPO, ++ BRCMS_SROM_OFDM5GHPO, ++ BRCMS_SROM_OFDM5GLPO, ++ BRCMS_SROM_OFDM5GPO, ++ BRCMS_SROM_OPO, ++ BRCMS_SROM_PA0B0, ++ BRCMS_SROM_PA0B1, ++ BRCMS_SROM_PA0B2, ++ BRCMS_SROM_PA0ITSSIT, ++ BRCMS_SROM_PA0MAXPWR, ++ BRCMS_SROM_PA1B0, ++ BRCMS_SROM_PA1B1, ++ BRCMS_SROM_PA1B2, ++ BRCMS_SROM_PA1HIB0, ++ BRCMS_SROM_PA1HIB1, ++ BRCMS_SROM_PA1HIB2, ++ BRCMS_SROM_PA1HIMAXPWR, ++ BRCMS_SROM_PA1ITSSIT, ++ BRCMS_SROM_PA1LOB0, ++ BRCMS_SROM_PA1LOB1, ++ BRCMS_SROM_PA1LOB2, ++ BRCMS_SROM_PA1LOMAXPWR, ++ BRCMS_SROM_PA1MAXPWR, ++ BRCMS_SROM_PDETRANGE2G, ++ BRCMS_SROM_PDETRANGE5G, ++ BRCMS_SROM_PHYCAL_TEMPDELTA, ++ BRCMS_SROM_RAWTEMPSENSE, ++ BRCMS_SROM_REGREV, ++ BRCMS_SROM_REV, ++ BRCMS_SROM_RSSISAV2G, ++ BRCMS_SROM_RSSISAV5G, ++ BRCMS_SROM_RSSISMC2G, ++ BRCMS_SROM_RSSISMC5G, ++ BRCMS_SROM_RSSISMF2G, ++ BRCMS_SROM_RSSISMF5G, ++ BRCMS_SROM_RXCHAIN, ++ BRCMS_SROM_RXPO2G, ++ BRCMS_SROM_RXPO5G, ++ BRCMS_SROM_STBCPO, ++ BRCMS_SROM_TEMPCORRX, ++ BRCMS_SROM_TEMPOFFSET, ++ BRCMS_SROM_TEMPSENSE_OPTION, ++ BRCMS_SROM_TEMPSENSE_SLOPE, ++ BRCMS_SROM_TEMPTHRESH, ++ BRCMS_SROM_TRI2G, ++ BRCMS_SROM_TRI5GH, ++ BRCMS_SROM_TRI5GL, ++ BRCMS_SROM_TRI5G, ++ BRCMS_SROM_TRISO2G, ++ BRCMS_SROM_TRISO5G, ++ BRCMS_SROM_TSSIPOS2G, ++ BRCMS_SROM_TSSIPOS5G, ++ BRCMS_SROM_TXCHAIN, ++ BRCMS_SROM_TXPID2GA0, ++ BRCMS_SROM_TXPID2GA1, ++ BRCMS_SROM_TXPID2GA2, ++ BRCMS_SROM_TXPID2GA3, ++ BRCMS_SROM_TXPID5GA0, ++ BRCMS_SROM_TXPID5GA1, ++ BRCMS_SROM_TXPID5GA2, ++ BRCMS_SROM_TXPID5GA3, ++ BRCMS_SROM_TXPID5GHA0, ++ BRCMS_SROM_TXPID5GHA1, ++ BRCMS_SROM_TXPID5GHA2, ++ BRCMS_SROM_TXPID5GHA3, ++ BRCMS_SROM_TXPID5GLA0, ++ BRCMS_SROM_TXPID5GLA1, ++ BRCMS_SROM_TXPID5GLA2, ++ BRCMS_SROM_TXPID5GLA3, ++ /* ++ * per-path identifiers (see srom.c) ++ */ ++ BRCMS_SROM_ITT2GA0, ++ BRCMS_SROM_ITT2GA1, ++ BRCMS_SROM_ITT2GA2, ++ BRCMS_SROM_ITT2GA3, ++ BRCMS_SROM_ITT5GA0, ++ BRCMS_SROM_ITT5GA1, ++ BRCMS_SROM_ITT5GA2, ++ BRCMS_SROM_ITT5GA3, ++ BRCMS_SROM_MAXP2GA0, ++ BRCMS_SROM_MAXP2GA1, ++ BRCMS_SROM_MAXP2GA2, ++ BRCMS_SROM_MAXP2GA3, ++ BRCMS_SROM_MAXP5GA0, ++ BRCMS_SROM_MAXP5GA1, ++ BRCMS_SROM_MAXP5GA2, ++ BRCMS_SROM_MAXP5GA3, ++ BRCMS_SROM_MAXP5GHA0, ++ BRCMS_SROM_MAXP5GHA1, ++ BRCMS_SROM_MAXP5GHA2, ++ BRCMS_SROM_MAXP5GHA3, ++ BRCMS_SROM_MAXP5GLA0, ++ BRCMS_SROM_MAXP5GLA1, ++ BRCMS_SROM_MAXP5GLA2, ++ BRCMS_SROM_MAXP5GLA3, ++ BRCMS_SROM_PA2GW0A0, ++ BRCMS_SROM_PA2GW0A1, ++ BRCMS_SROM_PA2GW0A2, ++ BRCMS_SROM_PA2GW0A3, ++ BRCMS_SROM_PA2GW1A0, ++ BRCMS_SROM_PA2GW1A1, ++ BRCMS_SROM_PA2GW1A2, ++ BRCMS_SROM_PA2GW1A3, ++ BRCMS_SROM_PA2GW2A0, ++ BRCMS_SROM_PA2GW2A1, ++ BRCMS_SROM_PA2GW2A2, ++ BRCMS_SROM_PA2GW2A3, ++ BRCMS_SROM_PA2GW3A0, ++ BRCMS_SROM_PA2GW3A1, ++ BRCMS_SROM_PA2GW3A2, ++ BRCMS_SROM_PA2GW3A3, ++ BRCMS_SROM_PA5GHW0A0, ++ BRCMS_SROM_PA5GHW0A1, ++ BRCMS_SROM_PA5GHW0A2, ++ BRCMS_SROM_PA5GHW0A3, ++ BRCMS_SROM_PA5GHW1A0, ++ BRCMS_SROM_PA5GHW1A1, ++ BRCMS_SROM_PA5GHW1A2, ++ BRCMS_SROM_PA5GHW1A3, ++ BRCMS_SROM_PA5GHW2A0, ++ BRCMS_SROM_PA5GHW2A1, ++ BRCMS_SROM_PA5GHW2A2, ++ BRCMS_SROM_PA5GHW2A3, ++ BRCMS_SROM_PA5GHW3A0, ++ BRCMS_SROM_PA5GHW3A1, ++ BRCMS_SROM_PA5GHW3A2, ++ BRCMS_SROM_PA5GHW3A3, ++ BRCMS_SROM_PA5GLW0A0, ++ BRCMS_SROM_PA5GLW0A1, ++ BRCMS_SROM_PA5GLW0A2, ++ BRCMS_SROM_PA5GLW0A3, ++ BRCMS_SROM_PA5GLW1A0, ++ BRCMS_SROM_PA5GLW1A1, ++ BRCMS_SROM_PA5GLW1A2, ++ BRCMS_SROM_PA5GLW1A3, ++ BRCMS_SROM_PA5GLW2A0, ++ BRCMS_SROM_PA5GLW2A1, ++ BRCMS_SROM_PA5GLW2A2, ++ BRCMS_SROM_PA5GLW2A3, ++ BRCMS_SROM_PA5GLW3A0, ++ BRCMS_SROM_PA5GLW3A1, ++ BRCMS_SROM_PA5GLW3A2, ++ BRCMS_SROM_PA5GLW3A3, ++ BRCMS_SROM_PA5GW0A0, ++ BRCMS_SROM_PA5GW0A1, ++ BRCMS_SROM_PA5GW0A2, ++ BRCMS_SROM_PA5GW0A3, ++ BRCMS_SROM_PA5GW1A0, ++ BRCMS_SROM_PA5GW1A1, ++ BRCMS_SROM_PA5GW1A2, ++ BRCMS_SROM_PA5GW1A3, ++ BRCMS_SROM_PA5GW2A0, ++ BRCMS_SROM_PA5GW2A1, ++ BRCMS_SROM_PA5GW2A2, ++ BRCMS_SROM_PA5GW2A3, ++ BRCMS_SROM_PA5GW3A0, ++ BRCMS_SROM_PA5GW3A1, ++ BRCMS_SROM_PA5GW3A2, ++ BRCMS_SROM_PA5GW3A3, ++}; ++ ++#define BRCMS_NUMRATES 16 /* max # of rates in a rateset */ ++#define D11_PHY_HDR_LEN 6 /* Phy header length - 6 bytes */ ++ ++/* phy types */ ++#define PHY_TYPE_A 0 /* Phy type A */ ++#define PHY_TYPE_G 2 /* Phy type G */ ++#define PHY_TYPE_N 4 /* Phy type N */ ++#define PHY_TYPE_LP 5 /* Phy type Low Power A/B/G */ ++#define PHY_TYPE_SSN 6 /* Phy type Single Stream N */ ++#define PHY_TYPE_LCN 8 /* Phy type Single Stream N */ ++#define PHY_TYPE_LCNXN 9 /* Phy type 2-stream N */ ++#define PHY_TYPE_HT 7 /* Phy type 3-Stream N */ ++ ++/* bw */ ++#define BRCMS_10_MHZ 10 /* 10Mhz nphy channel bandwidth */ ++#define BRCMS_20_MHZ 20 /* 20Mhz nphy channel bandwidth */ ++#define BRCMS_40_MHZ 40 /* 40Mhz nphy channel bandwidth */ ++ ++#define BRCMS_RSSI_MINVAL -200 /* Low value, e.g. for forcing roam */ ++#define BRCMS_RSSI_NO_SIGNAL -91 /* NDIS RSSI link quality cutoffs */ ++#define BRCMS_RSSI_VERY_LOW -80 /* Very low quality cutoffs */ ++#define BRCMS_RSSI_LOW -70 /* Low quality cutoffs */ ++#define BRCMS_RSSI_GOOD -68 /* Good quality cutoffs */ ++#define BRCMS_RSSI_VERY_GOOD -58 /* Very good quality cutoffs */ ++#define BRCMS_RSSI_EXCELLENT -57 /* Excellent quality cutoffs */ ++ ++/* a large TX Power as an init value to factor out of min() calculations, ++ * keep low enough to fit in an s8, units are .25 dBm ++ */ ++#define BRCMS_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */ ++ ++/* rate related definitions */ ++#define BRCMS_RATE_FLAG 0x80 /* Flag to indicate it is a basic rate */ ++#define BRCMS_RATE_MASK 0x7f /* Rate value mask w/o basic rate flag */ ++ ++/* legacy rx Antenna diversity for SISO rates */ ++#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */ ++#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */ ++#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */ ++#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */ ++#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */ ++/* default antdiv setting */ ++#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0 ++ ++/* legacy rx Antenna diversity for SISO rates */ ++/* Tx on antenna 0, "legacy term Main" */ ++#define ANT_TX_FORCE_0 0 ++/* Tx on antenna 1, "legacy term Aux" */ ++#define ANT_TX_FORCE_1 1 ++/* Tx on phy's last good Rx antenna */ ++#define ANT_TX_LAST_RX 3 ++/* driver's default tx antenna setting */ ++#define ANT_TX_DEF 3 ++ ++/* Tx Chain values */ ++/* def bitmap of txchain */ ++#define TXCHAIN_DEF 0x1 ++/* default bitmap of tx chains for nphy */ ++#define TXCHAIN_DEF_NPHY 0x3 ++/* default bitmap of tx chains for nphy */ ++#define TXCHAIN_DEF_HTPHY 0x7 ++/* def bitmap of rxchain */ ++#define RXCHAIN_DEF 0x1 ++/* default bitmap of rx chains for nphy */ ++#define RXCHAIN_DEF_NPHY 0x3 ++/* default bitmap of rx chains for nphy */ ++#define RXCHAIN_DEF_HTPHY 0x7 ++/* no antenna switch */ ++#define ANTSWITCH_NONE 0 ++/* antenna switch on 4321CB2, 2of3 */ ++#define ANTSWITCH_TYPE_1 1 ++/* antenna switch on 4321MPCI, 2of3 */ ++#define ANTSWITCH_TYPE_2 2 ++/* antenna switch on 4322, 2of3 */ ++#define ANTSWITCH_TYPE_3 3 ++ ++#define RXBUFSZ PKTBUFSZ ++ ++#define MAX_STREAMS_SUPPORTED 4 /* max number of streams supported */ ++ ++struct brcm_rateset { ++ /* # rates in this set */ ++ u32 count; ++ /* rates in 500kbps units w/hi bit set if basic */ ++ u8 rates[WL_NUMRATES]; ++}; ++ ++struct brcms_c_rateset { ++ uint count; /* number of rates in rates[] */ ++ /* rates in 500kbps units w/hi bit set if basic */ ++ u8 rates[BRCMS_NUMRATES]; ++ u8 htphy_membership; /* HT PHY Membership */ ++ u8 mcs[MCSSET_LEN]; /* supported mcs index bit map */ ++}; ++ ++/* All the HT-specific default advertised capabilities (including AMPDU) ++ * should be grouped here at one place ++ */ ++#define AMPDU_DEF_MPDU_DENSITY 6 /* default mpdu density (110 ==> 4us) */ ++ ++/* wlc internal bss_info */ ++struct brcms_bss_info { ++ u8 BSSID[ETH_ALEN]; /* network BSSID */ ++ u16 flags; /* flags for internal attributes */ ++ u8 SSID_len; /* the length of SSID */ ++ u8 SSID[32]; /* SSID string */ ++ s16 RSSI; /* receive signal strength (in dBm) */ ++ s16 SNR; /* receive signal SNR in dB */ ++ u16 beacon_period; /* units are Kusec */ ++ u16 chanspec; /* Channel num, bw, ctrl_sb and band */ ++ struct brcms_c_rateset rateset; /* supported rates */ ++}; ++ ++#define MAC80211_PROMISC_BCNS (1 << 0) ++#define MAC80211_SCAN (1 << 1) ++ ++/* ++ * Public portion of common driver state structure. ++ * The wlc handle points at this. ++ */ ++struct brcms_pub { ++ struct brcms_c_info *wlc; ++ struct ieee80211_hw *ieee_hw; ++ struct scb_ampdu *global_ampdu; ++ uint mac80211_state; ++ uint unit; /* device instance number */ ++ uint corerev; /* core revision */ ++ struct si_pub *sih; /* SI handle (cookie for siutils calls) */ ++ bool up; /* interface up and running */ ++ bool hw_off; /* HW is off */ ++ bool hw_up; /* one time hw up/down */ ++ bool _piomode; /* true if pio mode */ ++ uint _nbands; /* # bands supported */ ++ uint now; /* # elapsed seconds */ ++ ++ bool promisc; /* promiscuous destination address */ ++ bool delayed_down; /* down delayed */ ++ bool associated; /* true:part of [I]BSS, false: not */ ++ /* (union of stas_associated, aps_associated) */ ++ bool _ampdu; /* ampdu enabled or not */ ++ u8 _n_enab; /* bitmap of 11N + HT support */ ++ ++ u8 cur_etheraddr[ETH_ALEN]; /* our local ethernet address */ ++ ++ int bcmerror; /* last bcm error */ ++ ++ u32 radio_disabled; /* bit vector for radio disabled reasons */ ++ ++ u16 boardrev; /* version # of particular board */ ++ u8 sromrev; /* version # of the srom */ ++ char srom_ccode[BRCM_CNTRY_BUF_SZ]; /* Country Code in SROM */ ++ u32 boardflags; /* Board specific flags from srom */ ++ u32 boardflags2; /* More board flags if sromrev >= 4 */ ++ bool phy_11ncapable; /* the PHY/HW is capable of 802.11N */ ++ ++ struct wl_cnt *_cnt; /* low-level counters in driver */ ++}; ++ ++enum wlc_par_id { ++ IOV_MPC = 1, ++ IOV_RTSTHRESH, ++ IOV_QTXPOWER, ++ IOV_BCN_LI_BCN /* Beacon listen interval in # of beacons */ ++}; ++ ++/*********************************************** ++ * Feature-related macros to optimize out code * ++ * ********************************************* ++ */ ++ ++#define ENAB_1x1 0x01 ++#define ENAB_2x2 0x02 ++#define ENAB_3x3 0x04 ++#define ENAB_4x4 0x08 ++#define SUPPORT_11N (ENAB_1x1|ENAB_2x2) ++#define SUPPORT_HT (ENAB_1x1|ENAB_2x2|ENAB_3x3) ++ ++/* WL11N Support */ ++#define AMPDU_AGG_HOST 1 ++ ++/* pri is priority encoded in the packet. This maps the Packet priority to ++ * enqueue precedence as defined in wlc_prec_map ++ */ ++extern const u8 wlc_prio2prec_map[]; ++#define BRCMS_PRIO_TO_PREC(pri) wlc_prio2prec_map[(pri) & 7] ++ ++#define BRCMS_PREC_COUNT 16 /* Max precedence level implemented */ ++ ++/* Mask to describe all precedence levels */ ++#define BRCMS_PREC_BMP_ALL MAXBITVAL(BRCMS_PREC_COUNT) ++ ++/* ++ * This maps priority to one precedence higher - Used by PS-Poll response ++ * packets to simulate enqueue-at-head operation, but still maintain the ++ * order on the queue ++ */ ++#define BRCMS_PRIO_TO_HI_PREC(pri) min(BRCMS_PRIO_TO_PREC(pri) + 1,\ ++ BRCMS_PREC_COUNT - 1) ++ ++/* Define a bitmap of precedences comprised by each AC */ ++#define BRCMS_PREC_BMP_AC_BE (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BE)) | \ ++ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BE)) | \ ++ NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_EE)) | \ ++ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_EE))) ++#define BRCMS_PREC_BMP_AC_BK (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BK)) | \ ++ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BK)) | \ ++ NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NONE)) | \ ++ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NONE))) ++#define BRCMS_PREC_BMP_AC_VI (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_CL)) | \ ++ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_CL)) | \ ++ NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VI)) | \ ++ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VI))) ++#define BRCMS_PREC_BMP_AC_VO (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VO)) | \ ++ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VO)) | \ ++ NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NC)) | \ ++ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NC))) ++ ++/* network protection config */ ++#define BRCMS_PROT_G_SPEC 1 /* SPEC g protection */ ++#define BRCMS_PROT_G_OVR 2 /* SPEC g prot override */ ++#define BRCMS_PROT_G_USER 3 /* gmode specified by user */ ++#define BRCMS_PROT_OVERLAP 4 /* overlap */ ++#define BRCMS_PROT_N_USER 10 /* nmode specified by user */ ++#define BRCMS_PROT_N_CFG 11 /* n protection */ ++#define BRCMS_PROT_N_CFG_OVR 12 /* n protection override */ ++#define BRCMS_PROT_N_NONGF 13 /* non-GF protection */ ++#define BRCMS_PROT_N_NONGF_OVR 14 /* non-GF protection override */ ++#define BRCMS_PROT_N_PAM_OVR 15 /* n preamble override */ ++#define BRCMS_PROT_N_OBSS 16 /* non-HT OBSS present */ ++ ++/* ++ * 54g modes (basic bits may still be overridden) ++ * ++ * GMODE_LEGACY_B ++ * Rateset: 1b, 2b, 5.5, 11 ++ * Preamble: Long ++ * Shortslot: Off ++ * GMODE_AUTO ++ * Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 ++ * Extended Rateset: 6, 9, 12, 48 ++ * Preamble: Long ++ * Shortslot: Auto ++ * GMODE_ONLY ++ * Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54 ++ * Extended Rateset: 6b, 9, 12b, 48 ++ * Preamble: Short required ++ * Shortslot: Auto ++ * GMODE_B_DEFERRED ++ * Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 ++ * Extended Rateset: 6, 9, 12, 48 ++ * Preamble: Long ++ * Shortslot: On ++ * GMODE_PERFORMANCE ++ * Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54 ++ * Preamble: Short required ++ * Shortslot: On and required ++ * GMODE_LRS ++ * Rateset: 1b, 2b, 5.5b, 11b ++ * Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54 ++ * Preamble: Long ++ * Shortslot: Auto ++ */ ++#define GMODE_LEGACY_B 0 ++#define GMODE_AUTO 1 ++#define GMODE_ONLY 2 ++#define GMODE_B_DEFERRED 3 ++#define GMODE_PERFORMANCE 4 ++#define GMODE_LRS 5 ++#define GMODE_MAX 6 ++ ++/* MCS values greater than this enable multiple streams */ ++#define HIGHEST_SINGLE_STREAM_MCS 7 ++ ++#define MAXBANDS 2 /* Maximum #of bands */ ++ ++/* max number of antenna configurations */ ++#define ANT_SELCFG_MAX 4 ++ ++struct brcms_antselcfg { ++ u8 ant_config[ANT_SELCFG_MAX]; /* antenna configuration */ ++ u8 num_antcfg; /* number of available antenna configurations */ ++}; ++ ++/* common functions for every port */ ++extern struct brcms_c_info * ++brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit, ++ bool piomode, void __iomem *regsva, struct pci_dev *btparam, ++ uint *perr); ++extern uint brcms_c_detach(struct brcms_c_info *wlc); ++extern int brcms_c_up(struct brcms_c_info *wlc); ++extern uint brcms_c_down(struct brcms_c_info *wlc); ++ ++extern bool brcms_c_chipmatch(u16 vendor, u16 device); ++extern void brcms_c_init(struct brcms_c_info *wlc); ++extern void brcms_c_reset(struct brcms_c_info *wlc); ++ ++extern void brcms_c_intrson(struct brcms_c_info *wlc); ++extern u32 brcms_c_intrsoff(struct brcms_c_info *wlc); ++extern void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask); ++extern bool brcms_c_intrsupd(struct brcms_c_info *wlc); ++extern bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc); ++extern bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded); ++extern void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, ++ struct sk_buff *sdu, ++ struct ieee80211_hw *hw); ++extern bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid); ++extern void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, ++ int val); ++extern int brcms_c_get_header_len(void); ++extern void brcms_c_set_addrmatch(struct brcms_c_info *wlc, ++ int match_reg_offset, ++ const u8 *addr); ++extern void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci, ++ const struct ieee80211_tx_queue_params *arg, ++ bool suspend); ++extern struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc); ++extern void brcms_c_ampdu_flush(struct brcms_c_info *wlc, ++ struct ieee80211_sta *sta, u16 tid); ++extern void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, ++ u8 ba_wsize, uint max_rx_ampdu_bytes); ++extern char *getvar(struct si_pub *sih, enum brcms_srom_id id); ++extern int getintvar(struct si_pub *sih, enum brcms_srom_id id); ++extern int brcms_c_module_register(struct brcms_pub *pub, ++ const char *name, struct brcms_info *hdl, ++ int (*down_fn)(void *handle)); ++extern int brcms_c_module_unregister(struct brcms_pub *pub, const char *name, ++ struct brcms_info *hdl); ++extern void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc); ++extern void brcms_c_enable_mac(struct brcms_c_info *wlc); ++extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state); ++extern void brcms_c_scan_start(struct brcms_c_info *wlc); ++extern void brcms_c_scan_stop(struct brcms_c_info *wlc); ++extern int brcms_c_get_curband(struct brcms_c_info *wlc); ++extern void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, ++ bool drop); ++extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel); ++extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl); ++extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc, ++ struct brcm_rateset *currs); ++extern int brcms_c_set_rateset(struct brcms_c_info *wlc, ++ struct brcm_rateset *rs); ++extern int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period); ++extern u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx); ++extern void brcms_c_set_shortslot_override(struct brcms_c_info *wlc, ++ s8 sslot_override); ++extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, ++ u8 interval); ++extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr); ++extern int brcms_c_get_tx_power(struct brcms_c_info *wlc); ++extern void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc); ++extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); ++ ++#endif /* _BRCM_PUB_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.c.orig 2011-11-09 13:46:58.284800145 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.c 2011-11-09 13:47:17.042565640 -0500 +@@ -0,0 +1,514 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include "d11.h" ++#include "pub.h" ++#include "rate.h" ++ ++/* ++ * Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate ++ * value ++ */ ++const u8 rate_info[BRCM_MAXRATE + 1] = { ++ /* 0 1 2 3 4 5 6 7 8 9 */ ++/* 0 */ 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, ++/* 10 */ 0x00, 0x37, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00, ++/* 20 */ 0x00, 0x00, 0x6e, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, ++/* 30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, ++/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, ++/* 50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++/* 60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++/* 70 */ 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++/* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++/* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, ++/* 100 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c ++}; ++ ++/* rates are in units of Kbps */ ++const struct brcms_mcs_info mcs_table[MCS_TABLE_SIZE] = { ++ /* MCS 0: SS 1, MOD: BPSK, CR 1/2 */ ++ {6500, 13500, CEIL(6500 * 10, 9), CEIL(13500 * 10, 9), 0x00, ++ BRCM_RATE_6M}, ++ /* MCS 1: SS 1, MOD: QPSK, CR 1/2 */ ++ {13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x08, ++ BRCM_RATE_12M}, ++ /* MCS 2: SS 1, MOD: QPSK, CR 3/4 */ ++ {19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x0A, ++ BRCM_RATE_18M}, ++ /* MCS 3: SS 1, MOD: 16QAM, CR 1/2 */ ++ {26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x10, ++ BRCM_RATE_24M}, ++ /* MCS 4: SS 1, MOD: 16QAM, CR 3/4 */ ++ {39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x12, ++ BRCM_RATE_36M}, ++ /* MCS 5: SS 1, MOD: 64QAM, CR 2/3 */ ++ {52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x19, ++ BRCM_RATE_48M}, ++ /* MCS 6: SS 1, MOD: 64QAM, CR 3/4 */ ++ {58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x1A, ++ BRCM_RATE_54M}, ++ /* MCS 7: SS 1, MOD: 64QAM, CR 5/6 */ ++ {65000, 135000, CEIL(65000 * 10, 9), CEIL(135000 * 10, 9), 0x1C, ++ BRCM_RATE_54M}, ++ /* MCS 8: SS 2, MOD: BPSK, CR 1/2 */ ++ {13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x40, ++ BRCM_RATE_6M}, ++ /* MCS 9: SS 2, MOD: QPSK, CR 1/2 */ ++ {26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x48, ++ BRCM_RATE_12M}, ++ /* MCS 10: SS 2, MOD: QPSK, CR 3/4 */ ++ {39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x4A, ++ BRCM_RATE_18M}, ++ /* MCS 11: SS 2, MOD: 16QAM, CR 1/2 */ ++ {52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x50, ++ BRCM_RATE_24M}, ++ /* MCS 12: SS 2, MOD: 16QAM, CR 3/4 */ ++ {78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x52, ++ BRCM_RATE_36M}, ++ /* MCS 13: SS 2, MOD: 64QAM, CR 2/3 */ ++ {104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0x59, ++ BRCM_RATE_48M}, ++ /* MCS 14: SS 2, MOD: 64QAM, CR 3/4 */ ++ {117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x5A, ++ BRCM_RATE_54M}, ++ /* MCS 15: SS 2, MOD: 64QAM, CR 5/6 */ ++ {130000, 270000, CEIL(130000 * 10, 9), CEIL(270000 * 10, 9), 0x5C, ++ BRCM_RATE_54M}, ++ /* MCS 16: SS 3, MOD: BPSK, CR 1/2 */ ++ {19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x80, ++ BRCM_RATE_6M}, ++ /* MCS 17: SS 3, MOD: QPSK, CR 1/2 */ ++ {39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x88, ++ BRCM_RATE_12M}, ++ /* MCS 18: SS 3, MOD: QPSK, CR 3/4 */ ++ {58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x8A, ++ BRCM_RATE_18M}, ++ /* MCS 19: SS 3, MOD: 16QAM, CR 1/2 */ ++ {78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x90, ++ BRCM_RATE_24M}, ++ /* MCS 20: SS 3, MOD: 16QAM, CR 3/4 */ ++ {117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x92, ++ BRCM_RATE_36M}, ++ /* MCS 21: SS 3, MOD: 64QAM, CR 2/3 */ ++ {156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0x99, ++ BRCM_RATE_48M}, ++ /* MCS 22: SS 3, MOD: 64QAM, CR 3/4 */ ++ {175500, 364500, CEIL(175500 * 10, 9), CEIL(364500 * 10, 9), 0x9A, ++ BRCM_RATE_54M}, ++ /* MCS 23: SS 3, MOD: 64QAM, CR 5/6 */ ++ {195000, 405000, CEIL(195000 * 10, 9), CEIL(405000 * 10, 9), 0x9B, ++ BRCM_RATE_54M}, ++ /* MCS 24: SS 4, MOD: BPSK, CR 1/2 */ ++ {26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0xC0, ++ BRCM_RATE_6M}, ++ /* MCS 25: SS 4, MOD: QPSK, CR 1/2 */ ++ {52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0xC8, ++ BRCM_RATE_12M}, ++ /* MCS 26: SS 4, MOD: QPSK, CR 3/4 */ ++ {78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0xCA, ++ BRCM_RATE_18M}, ++ /* MCS 27: SS 4, MOD: 16QAM, CR 1/2 */ ++ {104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0xD0, ++ BRCM_RATE_24M}, ++ /* MCS 28: SS 4, MOD: 16QAM, CR 3/4 */ ++ {156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0xD2, ++ BRCM_RATE_36M}, ++ /* MCS 29: SS 4, MOD: 64QAM, CR 2/3 */ ++ {208000, 432000, CEIL(208000 * 10, 9), CEIL(432000 * 10, 9), 0xD9, ++ BRCM_RATE_48M}, ++ /* MCS 30: SS 4, MOD: 64QAM, CR 3/4 */ ++ {234000, 486000, CEIL(234000 * 10, 9), CEIL(486000 * 10, 9), 0xDA, ++ BRCM_RATE_54M}, ++ /* MCS 31: SS 4, MOD: 64QAM, CR 5/6 */ ++ {260000, 540000, CEIL(260000 * 10, 9), CEIL(540000 * 10, 9), 0xDB, ++ BRCM_RATE_54M}, ++ /* MCS 32: SS 1, MOD: BPSK, CR 1/2 */ ++ {0, 6000, 0, CEIL(6000 * 10, 9), 0x00, BRCM_RATE_6M}, ++}; ++ ++/* ++ * phycfg for legacy OFDM frames: code rate, modulation scheme, spatial streams ++ * Number of spatial streams: always 1 other fields: refer to table 78 of ++ * section 17.3.2.2 of the original .11a standard ++ */ ++struct legacy_phycfg { ++ u32 rate_ofdm; /* ofdm mac rate */ ++ /* phy ctl byte 3, code rate, modulation type, # of streams */ ++ u8 tx_phy_ctl3; ++}; ++ ++/* Number of legacy_rate_cfg entries in the table */ ++#define LEGACY_PHYCFG_TABLE_SIZE 12 ++ ++/* ++ * In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate ++ * Eventually MIMOPHY would also be converted to this format ++ * 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps ++ */ ++static const struct ++legacy_phycfg legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = { ++ {BRCM_RATE_1M, 0x00}, /* CCK 1Mbps, data rate 0 */ ++ {BRCM_RATE_2M, 0x08}, /* CCK 2Mbps, data rate 1 */ ++ {BRCM_RATE_5M5, 0x10}, /* CCK 5.5Mbps, data rate 2 */ ++ {BRCM_RATE_11M, 0x18}, /* CCK 11Mbps, data rate 3 */ ++ /* OFDM 6Mbps, code rate 1/2, BPSK, 1 spatial stream */ ++ {BRCM_RATE_6M, 0x00}, ++ /* OFDM 9Mbps, code rate 3/4, BPSK, 1 spatial stream */ ++ {BRCM_RATE_9M, 0x02}, ++ /* OFDM 12Mbps, code rate 1/2, QPSK, 1 spatial stream */ ++ {BRCM_RATE_12M, 0x08}, ++ /* OFDM 18Mbps, code rate 3/4, QPSK, 1 spatial stream */ ++ {BRCM_RATE_18M, 0x0A}, ++ /* OFDM 24Mbps, code rate 1/2, 16-QAM, 1 spatial stream */ ++ {BRCM_RATE_24M, 0x10}, ++ /* OFDM 36Mbps, code rate 3/4, 16-QAM, 1 spatial stream */ ++ {BRCM_RATE_36M, 0x12}, ++ /* OFDM 48Mbps, code rate 2/3, 64-QAM, 1 spatial stream */ ++ {BRCM_RATE_48M, 0x19}, ++ /* OFDM 54Mbps, code rate 3/4, 64-QAM, 1 spatial stream */ ++ {BRCM_RATE_54M, 0x1A}, ++}; ++ ++/* Hardware rates (also encodes default basic rates) */ ++ ++const struct brcms_c_rateset cck_ofdm_mimo_rates = { ++ 12, ++ /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, */ ++ { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, ++ /* 54 Mbps */ ++ 0x6c}, ++ 0x00, ++ { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00} ++}; ++ ++const struct brcms_c_rateset ofdm_mimo_rates = { ++ 8, ++ /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */ ++ { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c}, ++ 0x00, ++ { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* Default ratesets that include MCS32 for 40BW channels */ ++static const struct brcms_c_rateset cck_ofdm_40bw_mimo_rates = { ++ 12, ++ /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48 */ ++ { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, ++ /* 54 Mbps */ ++ 0x6c}, ++ 0x00, ++ { 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_c_rateset ofdm_40bw_mimo_rates = { ++ 8, ++ /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */ ++ { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c}, ++ 0x00, ++ { 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00} ++}; ++ ++const struct brcms_c_rateset cck_ofdm_rates = { ++ 12, ++ /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48,*/ ++ { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, ++ /*54 Mbps */ ++ 0x6c}, ++ 0x00, ++ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00} ++}; ++ ++const struct brcms_c_rateset gphy_legacy_rates = { ++ 4, ++ /* 1b, 2b, 5.5b, 11b Mbps */ ++ { 0x82, 0x84, 0x8b, 0x96}, ++ 0x00, ++ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00} ++}; ++ ++const struct brcms_c_rateset ofdm_rates = { ++ 8, ++ /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */ ++ { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c}, ++ 0x00, ++ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00} ++}; ++ ++const struct brcms_c_rateset cck_rates = { ++ 4, ++ /* 1b, 2b, 5.5, 11 Mbps */ ++ { 0x82, 0x84, 0x0b, 0x16}, ++ 0x00, ++ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* check if rateset is valid. ++ * if check_brate is true, rateset without a basic rate is considered NOT valid. ++ */ ++static bool brcms_c_rateset_valid(struct brcms_c_rateset *rs, bool check_brate) ++{ ++ uint idx; ++ ++ if (!rs->count) ++ return false; ++ ++ if (!check_brate) ++ return true; ++ ++ /* error if no basic rates */ ++ for (idx = 0; idx < rs->count; idx++) { ++ if (rs->rates[idx] & BRCMS_RATE_FLAG) ++ return true; ++ } ++ return false; ++} ++ ++void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams) ++{ ++ int i; ++ for (i = txstreams; i < MAX_STREAMS_SUPPORTED; i++) ++ rs->mcs[i] = 0; ++} ++ ++/* ++ * filter based on hardware rateset, and sort filtered rateset with basic ++ * bit(s) preserved, and check if resulting rateset is valid. ++*/ ++bool ++brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs, ++ const struct brcms_c_rateset *hw_rs, ++ bool check_brate, u8 txstreams) ++{ ++ u8 rateset[BRCM_MAXRATE + 1]; ++ u8 r; ++ uint count; ++ uint i; ++ ++ memset(rateset, 0, sizeof(rateset)); ++ count = rs->count; ++ ++ for (i = 0; i < count; i++) { ++ /* mask off "basic rate" bit, BRCMS_RATE_FLAG */ ++ r = (int)rs->rates[i] & BRCMS_RATE_MASK; ++ if ((r > BRCM_MAXRATE) || (rate_info[r] == 0)) ++ continue; ++ rateset[r] = rs->rates[i]; /* preserve basic bit! */ ++ } ++ ++ /* fill out the rates in order, looking at only supported rates */ ++ count = 0; ++ for (i = 0; i < hw_rs->count; i++) { ++ r = hw_rs->rates[i] & BRCMS_RATE_MASK; ++ if (rateset[r]) ++ rs->rates[count++] = rateset[r]; ++ } ++ ++ rs->count = count; ++ ++ /* only set the mcs rate bit if the equivalent hw mcs bit is set */ ++ for (i = 0; i < MCSSET_LEN; i++) ++ rs->mcs[i] = (rs->mcs[i] & hw_rs->mcs[i]); ++ ++ if (brcms_c_rateset_valid(rs, check_brate)) ++ return true; ++ else ++ return false; ++} ++ ++/* calculate the rate of a rx'd frame and return it as a ratespec */ ++u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp) ++{ ++ int phy_type; ++ u32 rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT; ++ ++ phy_type = ++ ((rxh->RxChan & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT); ++ ++ if ((phy_type == PHY_TYPE_N) || (phy_type == PHY_TYPE_SSN) || ++ (phy_type == PHY_TYPE_LCN) || (phy_type == PHY_TYPE_HT)) { ++ switch (rxh->PhyRxStatus_0 & PRXS0_FT_MASK) { ++ case PRXS0_CCK: ++ rspec = ++ cck_phy2mac_rate( ++ ((struct cck_phy_hdr *) plcp)->signal); ++ break; ++ case PRXS0_OFDM: ++ rspec = ++ ofdm_phy2mac_rate( ++ ((struct ofdm_phy_hdr *) plcp)->rlpt[0]); ++ break; ++ case PRXS0_PREN: ++ rspec = (plcp[0] & MIMO_PLCP_MCS_MASK) | RSPEC_MIMORATE; ++ if (plcp[0] & MIMO_PLCP_40MHZ) { ++ /* indicate rspec is for 40 MHz mode */ ++ rspec &= ~RSPEC_BW_MASK; ++ rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT); ++ } ++ break; ++ case PRXS0_STDN: ++ /* fallthru */ ++ default: ++ /* not supported, error condition */ ++ break; ++ } ++ if (plcp3_issgi(plcp[3])) ++ rspec |= RSPEC_SHORT_GI; ++ } else ++ if ((phy_type == PHY_TYPE_A) || (rxh->PhyRxStatus_0 & PRXS0_OFDM)) ++ rspec = ofdm_phy2mac_rate( ++ ((struct ofdm_phy_hdr *) plcp)->rlpt[0]); ++ else ++ rspec = cck_phy2mac_rate( ++ ((struct cck_phy_hdr *) plcp)->signal); ++ ++ return rspec; ++} ++ ++/* copy rateset src to dst as-is (no masking or sorting) */ ++void brcms_c_rateset_copy(const struct brcms_c_rateset *src, ++ struct brcms_c_rateset *dst) ++{ ++ memcpy(dst, src, sizeof(struct brcms_c_rateset)); ++} ++ ++/* ++ * Copy and selectively filter one rateset to another. ++ * 'basic_only' means only copy basic rates. ++ * 'rates' indicates cck (11b) and ofdm rates combinations. ++ * - 0: cck and ofdm ++ * - 1: cck only ++ * - 2: ofdm only ++ * 'xmask' is the copy mask (typically 0x7f or 0xff). ++ */ ++void ++brcms_c_rateset_filter(struct brcms_c_rateset *src, struct brcms_c_rateset *dst, ++ bool basic_only, u8 rates, uint xmask, bool mcsallow) ++{ ++ uint i; ++ uint r; ++ uint count; ++ ++ count = 0; ++ for (i = 0; i < src->count; i++) { ++ r = src->rates[i]; ++ if (basic_only && !(r & BRCMS_RATE_FLAG)) ++ continue; ++ if (rates == BRCMS_RATES_CCK && ++ is_ofdm_rate((r & BRCMS_RATE_MASK))) ++ continue; ++ if (rates == BRCMS_RATES_OFDM && ++ is_cck_rate((r & BRCMS_RATE_MASK))) ++ continue; ++ dst->rates[count++] = r & xmask; ++ } ++ dst->count = count; ++ dst->htphy_membership = src->htphy_membership; ++ ++ if (mcsallow && rates != BRCMS_RATES_CCK) ++ memcpy(&dst->mcs[0], &src->mcs[0], MCSSET_LEN); ++ else ++ brcms_c_rateset_mcs_clear(dst); ++} ++ ++/* select rateset for a given phy_type and bandtype and filter it, sort it ++ * and fill rs_tgt with result ++ */ ++void ++brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt, ++ const struct brcms_c_rateset *rs_hw, ++ uint phy_type, int bandtype, bool cck_only, ++ uint rate_mask, bool mcsallow, u8 bw, u8 txstreams) ++{ ++ const struct brcms_c_rateset *rs_dflt; ++ struct brcms_c_rateset rs_sel; ++ if ((PHYTYPE_IS(phy_type, PHY_TYPE_HT)) || ++ (PHYTYPE_IS(phy_type, PHY_TYPE_N)) || ++ (PHYTYPE_IS(phy_type, PHY_TYPE_LCN)) || ++ (PHYTYPE_IS(phy_type, PHY_TYPE_SSN))) { ++ if (bandtype == BRCM_BAND_5G) ++ rs_dflt = (bw == BRCMS_20_MHZ ? ++ &ofdm_mimo_rates : &ofdm_40bw_mimo_rates); ++ else ++ rs_dflt = (bw == BRCMS_20_MHZ ? ++ &cck_ofdm_mimo_rates : ++ &cck_ofdm_40bw_mimo_rates); ++ } else if (PHYTYPE_IS(phy_type, PHY_TYPE_LP)) { ++ rs_dflt = (bandtype == BRCM_BAND_5G) ? ++ &ofdm_rates : &cck_ofdm_rates; ++ } else if (PHYTYPE_IS(phy_type, PHY_TYPE_A)) { ++ rs_dflt = &ofdm_rates; ++ } else if (PHYTYPE_IS(phy_type, PHY_TYPE_G)) { ++ rs_dflt = &cck_ofdm_rates; ++ } else { ++ /* should not happen, error condition */ ++ rs_dflt = &cck_rates; /* force cck */ ++ } ++ ++ /* if hw rateset is not supplied, assign selected rateset to it */ ++ if (!rs_hw) ++ rs_hw = rs_dflt; ++ ++ brcms_c_rateset_copy(rs_dflt, &rs_sel); ++ brcms_c_rateset_mcs_upd(&rs_sel, txstreams); ++ brcms_c_rateset_filter(&rs_sel, rs_tgt, false, ++ cck_only ? BRCMS_RATES_CCK : BRCMS_RATES_CCK_OFDM, ++ rate_mask, mcsallow); ++ brcms_c_rate_hwrs_filter_sort_validate(rs_tgt, rs_hw, false, ++ mcsallow ? txstreams : 1); ++} ++ ++s16 brcms_c_rate_legacy_phyctl(uint rate) ++{ ++ uint i; ++ for (i = 0; i < LEGACY_PHYCFG_TABLE_SIZE; i++) ++ if (rate == legacy_phycfg_table[i].rate_ofdm) ++ return legacy_phycfg_table[i].tx_phy_ctl3; ++ ++ return -1; ++} ++ ++void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset) ++{ ++ uint i; ++ for (i = 0; i < MCSSET_LEN; i++) ++ rateset->mcs[i] = 0; ++} ++ ++void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, u8 txstreams) ++{ ++ memcpy(&rateset->mcs[0], &cck_ofdm_mimo_rates.mcs[0], MCSSET_LEN); ++ brcms_c_rateset_mcs_upd(rateset, txstreams); ++} ++ ++/* Based on bandwidth passed, allow/disallow MCS 32 in the rateset */ ++void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, u8 bw) ++{ ++ if (bw == BRCMS_40_MHZ) ++ setbit(rateset->mcs, 32); ++ else ++ clrbit(rateset->mcs, 32); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.h.orig 2011-11-09 13:46:58.284800145 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.h 2011-11-09 13:47:17.043565628 -0500 +@@ -0,0 +1,250 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_RATE_H_ ++#define _BRCM_RATE_H_ ++ ++#include "types.h" ++#include "d11.h" ++ ++extern const u8 rate_info[]; ++extern const struct brcms_c_rateset cck_ofdm_mimo_rates; ++extern const struct brcms_c_rateset ofdm_mimo_rates; ++extern const struct brcms_c_rateset cck_ofdm_rates; ++extern const struct brcms_c_rateset ofdm_rates; ++extern const struct brcms_c_rateset cck_rates; ++extern const struct brcms_c_rateset gphy_legacy_rates; ++extern const struct brcms_c_rateset rate_limit_1_2; ++ ++struct brcms_mcs_info { ++ /* phy rate in kbps [20Mhz] */ ++ u32 phy_rate_20; ++ /* phy rate in kbps [40Mhz] */ ++ u32 phy_rate_40; ++ /* phy rate in kbps [20Mhz] with SGI */ ++ u32 phy_rate_20_sgi; ++ /* phy rate in kbps [40Mhz] with SGI */ ++ u32 phy_rate_40_sgi; ++ /* phy ctl byte 3, code rate, modulation type, # of streams */ ++ u8 tx_phy_ctl3; ++ /* matching legacy ofdm rate in 500bkps */ ++ u8 leg_ofdm; ++}; ++ ++#define BRCMS_MAXMCS 32 /* max valid mcs index */ ++#define MCS_TABLE_SIZE 33 /* Number of mcs entries in the table */ ++extern const struct brcms_mcs_info mcs_table[]; ++ ++#define MCS_TXS_MASK 0xc0 /* num tx streams - 1 bit mask */ ++#define MCS_TXS_SHIFT 6 /* num tx streams - 1 bit shift */ ++ ++/* returns num tx streams - 1 */ ++static inline u8 mcs_2_txstreams(u8 mcs) ++{ ++ return (mcs_table[mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT; ++} ++ ++static inline uint mcs_2_rate(u8 mcs, bool is40, bool sgi) ++{ ++ if (sgi) { ++ if (is40) ++ return mcs_table[mcs].phy_rate_40_sgi; ++ return mcs_table[mcs].phy_rate_20_sgi; ++ } ++ if (is40) ++ return mcs_table[mcs].phy_rate_40; ++ ++ return mcs_table[mcs].phy_rate_20; ++} ++ ++/* Macro to use the rate_info table */ ++#define BRCMS_RATE_MASK_FULL 0xff /* Rate value mask with basic rate flag */ ++ ++/* ++ * rate spec : holds rate and mode specific information required to generate a ++ * tx frame. Legacy CCK and OFDM information is held in the same manner as was ++ * done in the past (in the lower byte) the upper 3 bytes primarily hold MIMO ++ * specific information ++ */ ++ ++/* rate spec bit fields */ ++ ++/* Either 500Kbps units or MIMO MCS idx */ ++#define RSPEC_RATE_MASK 0x0000007F ++/* mimo MCS is stored in RSPEC_RATE_MASK */ ++#define RSPEC_MIMORATE 0x08000000 ++/* mimo bw mask */ ++#define RSPEC_BW_MASK 0x00000700 ++/* mimo bw shift */ ++#define RSPEC_BW_SHIFT 8 ++/* mimo Space/Time/Frequency mode mask */ ++#define RSPEC_STF_MASK 0x00003800 ++/* mimo Space/Time/Frequency mode shift */ ++#define RSPEC_STF_SHIFT 11 ++/* mimo coding type mask */ ++#define RSPEC_CT_MASK 0x0000C000 ++/* mimo coding type shift */ ++#define RSPEC_CT_SHIFT 14 ++/* mimo num STC streams per PLCP defn. */ ++#define RSPEC_STC_MASK 0x00300000 ++/* mimo num STC streams per PLCP defn. */ ++#define RSPEC_STC_SHIFT 20 ++/* mimo bit indicates adv coding in use */ ++#define RSPEC_LDPC_CODING 0x00400000 ++/* mimo bit indicates short GI in use */ ++#define RSPEC_SHORT_GI 0x00800000 ++/* bit indicates override both rate & mode */ ++#define RSPEC_OVERRIDE 0x80000000 ++/* bit indicates override rate only */ ++#define RSPEC_OVERRIDE_MCS_ONLY 0x40000000 ++ ++static inline bool rspec_active(u32 rspec) ++{ ++ return rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE); ++} ++ ++static inline u8 rspec_phytxbyte2(u32 rspec) ++{ ++ return (rspec & 0xff00) >> 8; ++} ++ ++static inline u32 rspec_get_bw(u32 rspec) ++{ ++ return (rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT; ++} ++ ++static inline bool rspec_issgi(u32 rspec) ++{ ++ return (rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI; ++} ++ ++static inline bool rspec_is40mhz(u32 rspec) ++{ ++ u32 bw = rspec_get_bw(rspec); ++ ++ return bw == PHY_TXC1_BW_40MHZ || bw == PHY_TXC1_BW_40MHZ_DUP; ++} ++ ++static inline uint rspec2rate(u32 rspec) ++{ ++ if (rspec & RSPEC_MIMORATE) ++ return mcs_2_rate(rspec & RSPEC_RATE_MASK, rspec_is40mhz(rspec), ++ rspec_issgi(rspec)); ++ return rspec & RSPEC_RATE_MASK; ++} ++ ++static inline u8 rspec_mimoplcp3(u32 rspec) ++{ ++ return (rspec & 0xf00000) >> 16; ++} ++ ++static inline bool plcp3_issgi(u8 plcp) ++{ ++ return (plcp & (RSPEC_SHORT_GI >> 16)) != 0; ++} ++ ++static inline uint rspec_stc(u32 rspec) ++{ ++ return (rspec & RSPEC_STC_MASK) >> RSPEC_STC_SHIFT; ++} ++ ++static inline uint rspec_stf(u32 rspec) ++{ ++ return (rspec & RSPEC_STF_MASK) >> RSPEC_STF_SHIFT; ++} ++ ++static inline bool is_mcs_rate(u32 ratespec) ++{ ++ return (ratespec & RSPEC_MIMORATE) != 0; ++} ++ ++static inline bool is_ofdm_rate(u32 ratespec) ++{ ++ return !is_mcs_rate(ratespec) && ++ (rate_info[ratespec & RSPEC_RATE_MASK] & BRCMS_RATE_FLAG); ++} ++ ++static inline bool is_cck_rate(u32 ratespec) ++{ ++ u32 rate = (ratespec & BRCMS_RATE_MASK); ++ ++ return !is_mcs_rate(ratespec) && ( ++ rate == BRCM_RATE_1M || rate == BRCM_RATE_2M || ++ rate == BRCM_RATE_5M5 || rate == BRCM_RATE_11M); ++} ++ ++static inline bool is_single_stream(u8 mcs) ++{ ++ return mcs <= HIGHEST_SINGLE_STREAM_MCS || mcs == 32; ++} ++ ++static inline u8 cck_rspec(u8 cck) ++{ ++ return cck & RSPEC_RATE_MASK; ++} ++ ++/* Convert encoded rate value in plcp header to numerical rates in 500 KHz ++ * increments */ ++extern const u8 ofdm_rate_lookup[]; ++ ++static inline u8 ofdm_phy2mac_rate(u8 rlpt) ++{ ++ return ofdm_rate_lookup[rlpt & 0x7]; ++} ++ ++static inline u8 cck_phy2mac_rate(u8 signal) ++{ ++ return signal/5; ++} ++ ++/* Rates specified in brcms_c_rateset_filter() */ ++#define BRCMS_RATES_CCK_OFDM 0 ++#define BRCMS_RATES_CCK 1 ++#define BRCMS_RATES_OFDM 2 ++ ++/* sanitize, and sort a rateset with the basic bit(s) preserved, validate ++ * rateset */ ++extern bool ++brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs, ++ const struct brcms_c_rateset *hw_rs, ++ bool check_brate, u8 txstreams); ++/* copy rateset src to dst as-is (no masking or sorting) */ ++extern void brcms_c_rateset_copy(const struct brcms_c_rateset *src, ++ struct brcms_c_rateset *dst); ++ ++/* would be nice to have these documented ... */ ++extern u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp); ++ ++extern void brcms_c_rateset_filter(struct brcms_c_rateset *src, ++ struct brcms_c_rateset *dst, bool basic_only, u8 rates, uint xmask, ++ bool mcsallow); ++ ++extern void ++brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt, ++ const struct brcms_c_rateset *rs_hw, uint phy_type, ++ int bandtype, bool cck_only, uint rate_mask, ++ bool mcsallow, u8 bw, u8 txstreams); ++ ++extern s16 brcms_c_rate_legacy_phyctl(uint rate); ++ ++extern void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams); ++extern void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset); ++extern void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, ++ u8 txstreams); ++extern void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, ++ u8 bw); ++ ++#endif /* _BRCM_RATE_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/scb.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/scb.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/scb.h.orig 2011-11-09 13:46:58.284800145 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/scb.h 2011-11-09 13:47:17.043565628 -0500 +@@ -0,0 +1,82 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_SCB_H_ ++#define _BRCM_SCB_H_ ++ ++#include ++#include ++#include ++#include "types.h" ++ ++#define AMPDU_TX_BA_MAX_WSIZE 64 /* max Tx ba window size (in pdu) */ ++ ++#define AMPDU_MAX_SCB_TID NUMPRIO ++ ++/* scb flags */ ++#define SCB_WMECAP 0x0040 ++#define SCB_HTCAP 0x10000 /* HT (MIMO) capable device */ ++#define SCB_IS40 0x80000 /* 40MHz capable */ ++#define SCB_STBCCAP 0x40000000 /* STBC Capable */ ++ ++#define SCB_MAGIC 0xbeefcafe ++ ++/* structure to store per-tid state for the ampdu initiator */ ++struct scb_ampdu_tid_ini { ++ u8 tx_in_transit; /* number of pending mpdus in transit in driver */ ++ u8 tid; /* initiator tid for easy lookup */ ++ /* tx retry count; indexed by seq modulo */ ++ u8 txretry[AMPDU_TX_BA_MAX_WSIZE]; ++ struct scb *scb; /* backptr for easy lookup */ ++ u8 ba_wsize; /* negotiated ba window size (in pdu) */ ++}; ++ ++struct scb_ampdu { ++ struct scb *scb; /* back pointer for easy reference */ ++ u8 mpdu_density; /* mpdu density */ ++ u8 max_pdu; /* max pdus allowed in ampdu */ ++ u8 release; /* # of mpdus released at a time */ ++ u16 min_len; /* min mpdu len to support the density */ ++ u32 max_rx_ampdu_bytes; /* max ampdu rcv length; 8k, 16k, 32k, 64k */ ++ ++ /* ++ * This could easily be a ini[] pointer and we keep this info in wl ++ * itself instead of having mac80211 hold it for us. Also could be made ++ * dynamic per tid instead of static. ++ */ ++ /* initiator info - per tid (NUMPRIO): */ ++ struct scb_ampdu_tid_ini ini[AMPDU_MAX_SCB_TID]; ++}; ++ ++/* station control block - one per remote MAC address */ ++struct scb { ++ u32 magic; ++ u32 flags; /* various bit flags as defined below */ ++ u32 flags2; /* various bit flags2 as defined below */ ++ u8 state; /* current state bitfield of auth/assoc process */ ++ u8 ea[ETH_ALEN]; /* station address */ ++ uint fragresid[NUMPRIO];/* #bytes unused in frag buffer per prio */ ++ ++ u16 seqctl[NUMPRIO]; /* seqctl of last received frame (for dups) */ ++ /* seqctl of last received frame (for dups) for non-QoS data and ++ * management */ ++ u16 seqctl_nonqos; ++ u16 seqnum[NUMPRIO];/* WME: driver maintained sw seqnum per priority */ ++ ++ struct scb_ampdu scb_ampdu; /* AMPDU state including per tid info */ ++}; ++ ++#endif /* _BRCM_SCB_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.c.orig 2011-11-09 13:46:58.285800133 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.c 2011-11-09 13:47:17.044565616 -0500 +@@ -0,0 +1,1298 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include "pub.h" ++#include "nicpci.h" ++#include "aiutils.h" ++#include "otp.h" ++#include "srom.h" ++ ++/* ++ * SROM CRC8 polynomial value: ++ * ++ * x^8 + x^7 +x^6 + x^4 + x^2 + 1 ++ */ ++#define SROM_CRC8_POLY 0xAB ++ ++/* Maximum srom: 6 Kilobits == 768 bytes */ ++#define SROM_MAX 768 ++ ++/* PCI fields */ ++#define PCI_F0DEVID 48 ++ ++#define SROM_WORDS 64 ++ ++#define SROM_SSID 2 ++ ++#define SROM_WL1LHMAXP 29 ++ ++#define SROM_WL1LPAB0 30 ++#define SROM_WL1LPAB1 31 ++#define SROM_WL1LPAB2 32 ++ ++#define SROM_WL1HPAB0 33 ++#define SROM_WL1HPAB1 34 ++#define SROM_WL1HPAB2 35 ++ ++#define SROM_MACHI_IL0 36 ++#define SROM_MACMID_IL0 37 ++#define SROM_MACLO_IL0 38 ++#define SROM_MACHI_ET1 42 ++#define SROM_MACMID_ET1 43 ++#define SROM_MACLO_ET1 44 ++#define SROM3_MACHI 37 ++#define SROM3_MACMID 38 ++#define SROM3_MACLO 39 ++ ++#define SROM_BXARSSI2G 40 ++#define SROM_BXARSSI5G 41 ++ ++#define SROM_TRI52G 42 ++#define SROM_TRI5GHL 43 ++ ++#define SROM_RXPO52G 45 ++ ++#define SROM_AABREV 46 ++/* Fields in AABREV */ ++#define SROM_BR_MASK 0x00ff ++#define SROM_CC_MASK 0x0f00 ++#define SROM_CC_SHIFT 8 ++#define SROM_AA0_MASK 0x3000 ++#define SROM_AA0_SHIFT 12 ++#define SROM_AA1_MASK 0xc000 ++#define SROM_AA1_SHIFT 14 ++ ++#define SROM_WL0PAB0 47 ++#define SROM_WL0PAB1 48 ++#define SROM_WL0PAB2 49 ++ ++#define SROM_LEDBH10 50 ++#define SROM_LEDBH32 51 ++ ++#define SROM_WL10MAXP 52 ++ ++#define SROM_WL1PAB0 53 ++#define SROM_WL1PAB1 54 ++#define SROM_WL1PAB2 55 ++ ++#define SROM_ITT 56 ++ ++#define SROM_BFL 57 ++#define SROM_BFL2 28 ++#define SROM3_BFL2 61 ++ ++#define SROM_AG10 58 ++ ++#define SROM_CCODE 59 ++ ++#define SROM_OPO 60 ++ ++#define SROM3_LEDDC 62 ++ ++#define SROM_CRCREV 63 ++ ++/* SROM Rev 4: Reallocate the software part of the srom to accommodate ++ * MIMO features. It assumes up to two PCIE functions and 440 bytes ++ * of usable srom i.e. the usable storage in chips with OTP that ++ * implements hardware redundancy. ++ */ ++ ++#define SROM4_WORDS 220 ++ ++#define SROM4_SIGN 32 ++#define SROM4_SIGNATURE 0x5372 ++ ++#define SROM4_BREV 33 ++ ++#define SROM4_BFL0 34 ++#define SROM4_BFL1 35 ++#define SROM4_BFL2 36 ++#define SROM4_BFL3 37 ++#define SROM5_BFL0 37 ++#define SROM5_BFL1 38 ++#define SROM5_BFL2 39 ++#define SROM5_BFL3 40 ++ ++#define SROM4_MACHI 38 ++#define SROM4_MACMID 39 ++#define SROM4_MACLO 40 ++#define SROM5_MACHI 41 ++#define SROM5_MACMID 42 ++#define SROM5_MACLO 43 ++ ++#define SROM4_CCODE 41 ++#define SROM4_REGREV 42 ++#define SROM5_CCODE 34 ++#define SROM5_REGREV 35 ++ ++#define SROM4_LEDBH10 43 ++#define SROM4_LEDBH32 44 ++#define SROM5_LEDBH10 59 ++#define SROM5_LEDBH32 60 ++ ++#define SROM4_LEDDC 45 ++#define SROM5_LEDDC 45 ++ ++#define SROM4_AA 46 ++ ++#define SROM4_AG10 47 ++#define SROM4_AG32 48 ++ ++#define SROM4_TXPID2G 49 ++#define SROM4_TXPID5G 51 ++#define SROM4_TXPID5GL 53 ++#define SROM4_TXPID5GH 55 ++ ++#define SROM4_TXRXC 61 ++#define SROM4_TXCHAIN_MASK 0x000f ++#define SROM4_TXCHAIN_SHIFT 0 ++#define SROM4_RXCHAIN_MASK 0x00f0 ++#define SROM4_RXCHAIN_SHIFT 4 ++#define SROM4_SWITCH_MASK 0xff00 ++#define SROM4_SWITCH_SHIFT 8 ++ ++/* Per-path fields */ ++#define MAX_PATH_SROM 4 ++#define SROM4_PATH0 64 ++#define SROM4_PATH1 87 ++#define SROM4_PATH2 110 ++#define SROM4_PATH3 133 ++ ++#define SROM4_2G_ITT_MAXP 0 ++#define SROM4_2G_PA 1 ++#define SROM4_5G_ITT_MAXP 5 ++#define SROM4_5GLH_MAXP 6 ++#define SROM4_5G_PA 7 ++#define SROM4_5GL_PA 11 ++#define SROM4_5GH_PA 15 ++ ++/* All the miriad power offsets */ ++#define SROM4_2G_CCKPO 156 ++#define SROM4_2G_OFDMPO 157 ++#define SROM4_5G_OFDMPO 159 ++#define SROM4_5GL_OFDMPO 161 ++#define SROM4_5GH_OFDMPO 163 ++#define SROM4_2G_MCSPO 165 ++#define SROM4_5G_MCSPO 173 ++#define SROM4_5GL_MCSPO 181 ++#define SROM4_5GH_MCSPO 189 ++#define SROM4_CDDPO 197 ++#define SROM4_STBCPO 198 ++#define SROM4_BW40PO 199 ++#define SROM4_BWDUPPO 200 ++ ++#define SROM4_CRCREV 219 ++ ++/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6. ++ * This is acombined srom for both MIMO and SISO boards, usable in ++ * the .130 4Kilobit OTP with hardware redundancy. ++ */ ++#define SROM8_BREV 65 ++ ++#define SROM8_BFL0 66 ++#define SROM8_BFL1 67 ++#define SROM8_BFL2 68 ++#define SROM8_BFL3 69 ++ ++#define SROM8_MACHI 70 ++#define SROM8_MACMID 71 ++#define SROM8_MACLO 72 ++ ++#define SROM8_CCODE 73 ++#define SROM8_REGREV 74 ++ ++#define SROM8_LEDBH10 75 ++#define SROM8_LEDBH32 76 ++ ++#define SROM8_LEDDC 77 ++ ++#define SROM8_AA 78 ++ ++#define SROM8_AG10 79 ++#define SROM8_AG32 80 ++ ++#define SROM8_TXRXC 81 ++ ++#define SROM8_BXARSSI2G 82 ++#define SROM8_BXARSSI5G 83 ++#define SROM8_TRI52G 84 ++#define SROM8_TRI5GHL 85 ++#define SROM8_RXPO52G 86 ++ ++#define SROM8_FEM2G 87 ++#define SROM8_FEM5G 88 ++#define SROM8_FEM_ANTSWLUT_MASK 0xf800 ++#define SROM8_FEM_ANTSWLUT_SHIFT 11 ++#define SROM8_FEM_TR_ISO_MASK 0x0700 ++#define SROM8_FEM_TR_ISO_SHIFT 8 ++#define SROM8_FEM_PDET_RANGE_MASK 0x00f8 ++#define SROM8_FEM_PDET_RANGE_SHIFT 3 ++#define SROM8_FEM_EXTPA_GAIN_MASK 0x0006 ++#define SROM8_FEM_EXTPA_GAIN_SHIFT 1 ++#define SROM8_FEM_TSSIPOS_MASK 0x0001 ++#define SROM8_FEM_TSSIPOS_SHIFT 0 ++ ++#define SROM8_THERMAL 89 ++ ++/* Temp sense related entries */ ++#define SROM8_MPWR_RAWTS 90 ++#define SROM8_TS_SLP_OPT_CORRX 91 ++/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, ++ * IQSWP: IQ CAL swap disable */ ++#define SROM8_FOC_HWIQ_IQSWP 92 ++ ++/* Temperature delta for PHY calibration */ ++#define SROM8_PHYCAL_TEMPDELTA 93 ++ ++/* Per-path offsets & fields */ ++#define SROM8_PATH0 96 ++#define SROM8_PATH1 112 ++#define SROM8_PATH2 128 ++#define SROM8_PATH3 144 ++ ++#define SROM8_2G_ITT_MAXP 0 ++#define SROM8_2G_PA 1 ++#define SROM8_5G_ITT_MAXP 4 ++#define SROM8_5GLH_MAXP 5 ++#define SROM8_5G_PA 6 ++#define SROM8_5GL_PA 9 ++#define SROM8_5GH_PA 12 ++ ++/* All the miriad power offsets */ ++#define SROM8_2G_CCKPO 160 ++ ++#define SROM8_2G_OFDMPO 161 ++#define SROM8_5G_OFDMPO 163 ++#define SROM8_5GL_OFDMPO 165 ++#define SROM8_5GH_OFDMPO 167 ++ ++#define SROM8_2G_MCSPO 169 ++#define SROM8_5G_MCSPO 177 ++#define SROM8_5GL_MCSPO 185 ++#define SROM8_5GH_MCSPO 193 ++ ++#define SROM8_CDDPO 201 ++#define SROM8_STBCPO 202 ++#define SROM8_BW40PO 203 ++#define SROM8_BWDUPPO 204 ++ ++/* SISO PA parameters are in the path0 spaces */ ++#define SROM8_SISO 96 ++ ++/* Legacy names for SISO PA paramters */ ++#define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP) ++#define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA) ++#define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1) ++#define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2) ++#define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP) ++#define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP) ++#define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA) ++#define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1) ++#define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2) ++#define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA) ++#define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1) ++#define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2) ++#define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA) ++#define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1) ++#define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2) ++ ++/* SROM REV 9 */ ++#define SROM9_2GPO_CCKBW20 160 ++#define SROM9_2GPO_CCKBW20UL 161 ++#define SROM9_2GPO_LOFDMBW20 162 ++#define SROM9_2GPO_LOFDMBW20UL 164 ++ ++#define SROM9_5GLPO_LOFDMBW20 166 ++#define SROM9_5GLPO_LOFDMBW20UL 168 ++#define SROM9_5GMPO_LOFDMBW20 170 ++#define SROM9_5GMPO_LOFDMBW20UL 172 ++#define SROM9_5GHPO_LOFDMBW20 174 ++#define SROM9_5GHPO_LOFDMBW20UL 176 ++ ++#define SROM9_2GPO_MCSBW20 178 ++#define SROM9_2GPO_MCSBW20UL 180 ++#define SROM9_2GPO_MCSBW40 182 ++ ++#define SROM9_5GLPO_MCSBW20 184 ++#define SROM9_5GLPO_MCSBW20UL 186 ++#define SROM9_5GLPO_MCSBW40 188 ++#define SROM9_5GMPO_MCSBW20 190 ++#define SROM9_5GMPO_MCSBW20UL 192 ++#define SROM9_5GMPO_MCSBW40 194 ++#define SROM9_5GHPO_MCSBW20 196 ++#define SROM9_5GHPO_MCSBW20UL 198 ++#define SROM9_5GHPO_MCSBW40 200 ++ ++#define SROM9_PO_MCS32 202 ++#define SROM9_PO_LOFDM40DUP 203 ++ ++/* SROM flags (see sromvar_t) */ ++ ++/* value continues as described by the next entry */ ++#define SRFL_MORE 1 ++#define SRFL_NOFFS 2 /* value bits can't be all one's */ ++#define SRFL_PRHEX 4 /* value is in hexdecimal format */ ++#define SRFL_PRSIGN 8 /* value is in signed decimal format */ ++#define SRFL_CCODE 0x10 /* value is in country code format */ ++#define SRFL_ETHADDR 0x20 /* value is an Ethernet address */ ++#define SRFL_LEDDC 0x40 /* value is an LED duty cycle */ ++/* do not generate a nvram param, entry is for mfgc */ ++#define SRFL_NOVAR 0x80 ++ ++/* Max. nvram variable table size */ ++#define MAXSZ_NVRAM_VARS 4096 ++ ++/* ++ * indicates type of value. ++ */ ++enum brcms_srom_var_type { ++ BRCMS_SROM_STRING, ++ BRCMS_SROM_SNUMBER, ++ BRCMS_SROM_UNUMBER ++}; ++ ++/* ++ * storage type for srom variable. ++ * ++ * var_list: for linked list operations. ++ * varid: identifier of the variable. ++ * var_type: type of variable. ++ * buf: variable value when var_type == BRCMS_SROM_STRING. ++ * uval: unsigned variable value when var_type == BRCMS_SROM_UNUMBER. ++ * sval: signed variable value when var_type == BRCMS_SROM_SNUMBER. ++ */ ++struct brcms_srom_list_head { ++ struct list_head var_list; ++ enum brcms_srom_id varid; ++ enum brcms_srom_var_type var_type; ++ union { ++ char buf[0]; ++ u32 uval; ++ s32 sval; ++ }; ++}; ++ ++struct brcms_sromvar { ++ enum brcms_srom_id varid; ++ u32 revmask; ++ u32 flags; ++ u16 off; ++ u16 mask; ++}; ++ ++struct brcms_varbuf { ++ char *base; /* pointer to buffer base */ ++ char *buf; /* pointer to current position */ ++ unsigned int size; /* current (residual) size in bytes */ ++}; ++ ++/* ++ * Assumptions: ++ * - Ethernet address spans across 3 consecutive words ++ * ++ * Table rules: ++ * - Add multiple entries next to each other if a value spans across multiple ++ * words (even multiple fields in the same word) with each entry except the ++ * last having it's SRFL_MORE bit set. ++ * - Ethernet address entry does not follow above rule and must not have ++ * SRFL_MORE bit set. Its SRFL_ETHADDR bit implies it takes multiple words. ++ * - The last entry's name field must be NULL to indicate the end of the table. ++ * Other entries must have non-NULL name. ++ */ ++static const struct brcms_sromvar pci_sromvars[] = { ++ {BRCMS_SROM_DEVID, 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID, ++ 0xffff}, ++ {BRCMS_SROM_BOARDREV, 0x0000000e, SRFL_PRHEX, SROM_AABREV, ++ SROM_BR_MASK}, ++ {BRCMS_SROM_BOARDREV, 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff}, ++ {BRCMS_SROM_BOARDREV, 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS, 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS, 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM_BFL2, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS, 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM3_BFL2, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS, 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM4_BFL1, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS, 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM5_BFL1, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM8_BFL1, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS2, 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM4_BFL3, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS2, 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM5_BFL3, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS2, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM8_BFL3, 0xffff}, ++ {BRCMS_SROM_BOARDTYPE, 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff}, ++ {BRCMS_SROM_BOARDNUM, 0x00000006, 0, SROM_MACLO_IL0, 0xffff}, ++ {BRCMS_SROM_BOARDNUM, 0x00000008, 0, SROM3_MACLO, 0xffff}, ++ {BRCMS_SROM_BOARDNUM, 0x00000010, 0, SROM4_MACLO, 0xffff}, ++ {BRCMS_SROM_BOARDNUM, 0x000000e0, 0, SROM5_MACLO, 0xffff}, ++ {BRCMS_SROM_BOARDNUM, 0xffffff00, 0, SROM8_MACLO, 0xffff}, ++ {BRCMS_SROM_CC, 0x00000002, 0, SROM_AABREV, SROM_CC_MASK}, ++ {BRCMS_SROM_REGREV, 0x00000008, 0, SROM_OPO, 0xff00}, ++ {BRCMS_SROM_REGREV, 0x00000010, 0, SROM4_REGREV, 0x00ff}, ++ {BRCMS_SROM_REGREV, 0x000000e0, 0, SROM5_REGREV, 0x00ff}, ++ {BRCMS_SROM_REGREV, 0xffffff00, 0, SROM8_REGREV, 0x00ff}, ++ {BRCMS_SROM_LEDBH0, 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff}, ++ {BRCMS_SROM_LEDBH1, 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00}, ++ {BRCMS_SROM_LEDBH2, 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff}, ++ {BRCMS_SROM_LEDBH3, 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00}, ++ {BRCMS_SROM_LEDBH0, 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff}, ++ {BRCMS_SROM_LEDBH1, 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00}, ++ {BRCMS_SROM_LEDBH2, 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff}, ++ {BRCMS_SROM_LEDBH3, 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00}, ++ {BRCMS_SROM_LEDBH0, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff}, ++ {BRCMS_SROM_LEDBH1, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00}, ++ {BRCMS_SROM_LEDBH2, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff}, ++ {BRCMS_SROM_LEDBH3, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00}, ++ {BRCMS_SROM_LEDBH0, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff}, ++ {BRCMS_SROM_LEDBH1, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00}, ++ {BRCMS_SROM_LEDBH2, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff}, ++ {BRCMS_SROM_LEDBH3, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00}, ++ {BRCMS_SROM_PA0B0, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff}, ++ {BRCMS_SROM_PA0B1, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff}, ++ {BRCMS_SROM_PA0B2, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff}, ++ {BRCMS_SROM_PA0ITSSIT, 0x0000000e, 0, SROM_ITT, 0x00ff}, ++ {BRCMS_SROM_PA0MAXPWR, 0x0000000e, 0, SROM_WL10MAXP, 0x00ff}, ++ {BRCMS_SROM_PA0B0, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff}, ++ {BRCMS_SROM_PA0B1, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff}, ++ {BRCMS_SROM_PA0B2, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff}, ++ {BRCMS_SROM_PA0ITSSIT, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00}, ++ {BRCMS_SROM_PA0MAXPWR, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff}, ++ {BRCMS_SROM_OPO, 0x0000000c, 0, SROM_OPO, 0x00ff}, ++ {BRCMS_SROM_OPO, 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff}, ++ {BRCMS_SROM_AA2G, 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK}, ++ {BRCMS_SROM_AA2G, 0x000000f0, 0, SROM4_AA, 0x00ff}, ++ {BRCMS_SROM_AA2G, 0xffffff00, 0, SROM8_AA, 0x00ff}, ++ {BRCMS_SROM_AA5G, 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK}, ++ {BRCMS_SROM_AA5G, 0x000000f0, 0, SROM4_AA, 0xff00}, ++ {BRCMS_SROM_AA5G, 0xffffff00, 0, SROM8_AA, 0xff00}, ++ {BRCMS_SROM_AG0, 0x0000000e, 0, SROM_AG10, 0x00ff}, ++ {BRCMS_SROM_AG1, 0x0000000e, 0, SROM_AG10, 0xff00}, ++ {BRCMS_SROM_AG0, 0x000000f0, 0, SROM4_AG10, 0x00ff}, ++ {BRCMS_SROM_AG1, 0x000000f0, 0, SROM4_AG10, 0xff00}, ++ {BRCMS_SROM_AG2, 0x000000f0, 0, SROM4_AG32, 0x00ff}, ++ {BRCMS_SROM_AG3, 0x000000f0, 0, SROM4_AG32, 0xff00}, ++ {BRCMS_SROM_AG0, 0xffffff00, 0, SROM8_AG10, 0x00ff}, ++ {BRCMS_SROM_AG1, 0xffffff00, 0, SROM8_AG10, 0xff00}, ++ {BRCMS_SROM_AG2, 0xffffff00, 0, SROM8_AG32, 0x00ff}, ++ {BRCMS_SROM_AG3, 0xffffff00, 0, SROM8_AG32, 0xff00}, ++ {BRCMS_SROM_PA1B0, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff}, ++ {BRCMS_SROM_PA1B1, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff}, ++ {BRCMS_SROM_PA1B2, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff}, ++ {BRCMS_SROM_PA1LOB0, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff}, ++ {BRCMS_SROM_PA1LOB1, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff}, ++ {BRCMS_SROM_PA1LOB2, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff}, ++ {BRCMS_SROM_PA1HIB0, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff}, ++ {BRCMS_SROM_PA1HIB1, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff}, ++ {BRCMS_SROM_PA1HIB2, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff}, ++ {BRCMS_SROM_PA1ITSSIT, 0x0000000e, 0, SROM_ITT, 0xff00}, ++ {BRCMS_SROM_PA1MAXPWR, 0x0000000e, 0, SROM_WL10MAXP, 0xff00}, ++ {BRCMS_SROM_PA1LOMAXPWR, 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00}, ++ {BRCMS_SROM_PA1HIMAXPWR, 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff}, ++ {BRCMS_SROM_PA1B0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff}, ++ {BRCMS_SROM_PA1B1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff}, ++ {BRCMS_SROM_PA1B2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff}, ++ {BRCMS_SROM_PA1LOB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff}, ++ {BRCMS_SROM_PA1LOB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff}, ++ {BRCMS_SROM_PA1LOB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff}, ++ {BRCMS_SROM_PA1HIB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff}, ++ {BRCMS_SROM_PA1HIB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff}, ++ {BRCMS_SROM_PA1HIB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff}, ++ {BRCMS_SROM_PA1ITSSIT, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00}, ++ {BRCMS_SROM_PA1MAXPWR, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff}, ++ {BRCMS_SROM_PA1LOMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00}, ++ {BRCMS_SROM_PA1HIMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff}, ++ {BRCMS_SROM_BXA2G, 0x00000008, 0, SROM_BXARSSI2G, 0x1800}, ++ {BRCMS_SROM_RSSISAV2G, 0x00000008, 0, SROM_BXARSSI2G, 0x0700}, ++ {BRCMS_SROM_RSSISMC2G, 0x00000008, 0, SROM_BXARSSI2G, 0x00f0}, ++ {BRCMS_SROM_RSSISMF2G, 0x00000008, 0, SROM_BXARSSI2G, 0x000f}, ++ {BRCMS_SROM_BXA2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800}, ++ {BRCMS_SROM_RSSISAV2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700}, ++ {BRCMS_SROM_RSSISMC2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0}, ++ {BRCMS_SROM_RSSISMF2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f}, ++ {BRCMS_SROM_BXA5G, 0x00000008, 0, SROM_BXARSSI5G, 0x1800}, ++ {BRCMS_SROM_RSSISAV5G, 0x00000008, 0, SROM_BXARSSI5G, 0x0700}, ++ {BRCMS_SROM_RSSISMC5G, 0x00000008, 0, SROM_BXARSSI5G, 0x00f0}, ++ {BRCMS_SROM_RSSISMF5G, 0x00000008, 0, SROM_BXARSSI5G, 0x000f}, ++ {BRCMS_SROM_BXA5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800}, ++ {BRCMS_SROM_RSSISAV5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700}, ++ {BRCMS_SROM_RSSISMC5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0}, ++ {BRCMS_SROM_RSSISMF5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f}, ++ {BRCMS_SROM_TRI2G, 0x00000008, 0, SROM_TRI52G, 0x00ff}, ++ {BRCMS_SROM_TRI5G, 0x00000008, 0, SROM_TRI52G, 0xff00}, ++ {BRCMS_SROM_TRI5GL, 0x00000008, 0, SROM_TRI5GHL, 0x00ff}, ++ {BRCMS_SROM_TRI5GH, 0x00000008, 0, SROM_TRI5GHL, 0xff00}, ++ {BRCMS_SROM_TRI2G, 0xffffff00, 0, SROM8_TRI52G, 0x00ff}, ++ {BRCMS_SROM_TRI5G, 0xffffff00, 0, SROM8_TRI52G, 0xff00}, ++ {BRCMS_SROM_TRI5GL, 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff}, ++ {BRCMS_SROM_TRI5GH, 0xffffff00, 0, SROM8_TRI5GHL, 0xff00}, ++ {BRCMS_SROM_RXPO2G, 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff}, ++ {BRCMS_SROM_RXPO5G, 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00}, ++ {BRCMS_SROM_RXPO2G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff}, ++ {BRCMS_SROM_RXPO5G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00}, ++ {BRCMS_SROM_TXCHAIN, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, ++ SROM4_TXCHAIN_MASK}, ++ {BRCMS_SROM_RXCHAIN, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, ++ SROM4_RXCHAIN_MASK}, ++ {BRCMS_SROM_ANTSWITCH, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, ++ SROM4_SWITCH_MASK}, ++ {BRCMS_SROM_TXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, ++ SROM4_TXCHAIN_MASK}, ++ {BRCMS_SROM_RXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, ++ SROM4_RXCHAIN_MASK}, ++ {BRCMS_SROM_ANTSWITCH, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, ++ SROM4_SWITCH_MASK}, ++ {BRCMS_SROM_TSSIPOS2G, 0xffffff00, 0, SROM8_FEM2G, ++ SROM8_FEM_TSSIPOS_MASK}, ++ {BRCMS_SROM_EXTPAGAIN2G, 0xffffff00, 0, SROM8_FEM2G, ++ SROM8_FEM_EXTPA_GAIN_MASK}, ++ {BRCMS_SROM_PDETRANGE2G, 0xffffff00, 0, SROM8_FEM2G, ++ SROM8_FEM_PDET_RANGE_MASK}, ++ {BRCMS_SROM_TRISO2G, 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK}, ++ {BRCMS_SROM_ANTSWCTL2G, 0xffffff00, 0, SROM8_FEM2G, ++ SROM8_FEM_ANTSWLUT_MASK}, ++ {BRCMS_SROM_TSSIPOS5G, 0xffffff00, 0, SROM8_FEM5G, ++ SROM8_FEM_TSSIPOS_MASK}, ++ {BRCMS_SROM_EXTPAGAIN5G, 0xffffff00, 0, SROM8_FEM5G, ++ SROM8_FEM_EXTPA_GAIN_MASK}, ++ {BRCMS_SROM_PDETRANGE5G, 0xffffff00, 0, SROM8_FEM5G, ++ SROM8_FEM_PDET_RANGE_MASK}, ++ {BRCMS_SROM_TRISO5G, 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK}, ++ {BRCMS_SROM_ANTSWCTL5G, 0xffffff00, 0, SROM8_FEM5G, ++ SROM8_FEM_ANTSWLUT_MASK}, ++ {BRCMS_SROM_TEMPTHRESH, 0xffffff00, 0, SROM8_THERMAL, 0xff00}, ++ {BRCMS_SROM_TEMPOFFSET, 0xffffff00, 0, SROM8_THERMAL, 0x00ff}, ++ {BRCMS_SROM_TXPID2GA0, 0x000000f0, 0, SROM4_TXPID2G, 0x00ff}, ++ {BRCMS_SROM_TXPID2GA1, 0x000000f0, 0, SROM4_TXPID2G, 0xff00}, ++ {BRCMS_SROM_TXPID2GA2, 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff}, ++ {BRCMS_SROM_TXPID2GA3, 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00}, ++ {BRCMS_SROM_TXPID5GA0, 0x000000f0, 0, SROM4_TXPID5G, 0x00ff}, ++ {BRCMS_SROM_TXPID5GA1, 0x000000f0, 0, SROM4_TXPID5G, 0xff00}, ++ {BRCMS_SROM_TXPID5GA2, 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff}, ++ {BRCMS_SROM_TXPID5GA3, 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00}, ++ {BRCMS_SROM_TXPID5GLA0, 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff}, ++ {BRCMS_SROM_TXPID5GLA1, 0x000000f0, 0, SROM4_TXPID5GL, 0xff00}, ++ {BRCMS_SROM_TXPID5GLA2, 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff}, ++ {BRCMS_SROM_TXPID5GLA3, 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00}, ++ {BRCMS_SROM_TXPID5GHA0, 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff}, ++ {BRCMS_SROM_TXPID5GHA1, 0x000000f0, 0, SROM4_TXPID5GH, 0xff00}, ++ {BRCMS_SROM_TXPID5GHA2, 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff}, ++ {BRCMS_SROM_TXPID5GHA3, 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00}, ++ ++ {BRCMS_SROM_CCODE, 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff}, ++ {BRCMS_SROM_CCODE, 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff}, ++ {BRCMS_SROM_CCODE, 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff}, ++ {BRCMS_SROM_CCODE, 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff}, ++ {BRCMS_SROM_MACADDR, 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff}, ++ {BRCMS_SROM_MACADDR, 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff}, ++ {BRCMS_SROM_MACADDR, 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff}, ++ {BRCMS_SROM_MACADDR, 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff}, ++ {BRCMS_SROM_IL0MACADDR, 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, ++ 0xffff}, ++ {BRCMS_SROM_ET1MACADDR, 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, ++ 0xffff}, ++ {BRCMS_SROM_LEDDC, 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, ++ 0xffff}, ++ {BRCMS_SROM_LEDDC, 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC, ++ 0xffff}, ++ {BRCMS_SROM_LEDDC, 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC, ++ 0xffff}, ++ {BRCMS_SROM_LEDDC, 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC, ++ 0xffff}, ++ {BRCMS_SROM_RAWTEMPSENSE, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, ++ 0x01ff}, ++ {BRCMS_SROM_MEASPOWER, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, ++ 0xfe00}, ++ {BRCMS_SROM_TEMPSENSE_SLOPE, 0xffffff00, SRFL_PRHEX, ++ SROM8_TS_SLP_OPT_CORRX, 0x00ff}, ++ {BRCMS_SROM_TEMPCORRX, 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, ++ 0xfc00}, ++ {BRCMS_SROM_TEMPSENSE_OPTION, 0xffffff00, SRFL_PRHEX, ++ SROM8_TS_SLP_OPT_CORRX, 0x0300}, ++ {BRCMS_SROM_FREQOFFSET_CORR, 0xffffff00, SRFL_PRHEX, ++ SROM8_FOC_HWIQ_IQSWP, 0x000f}, ++ {BRCMS_SROM_IQCAL_SWP_DIS, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, ++ 0x0010}, ++ {BRCMS_SROM_HW_IQCAL_EN, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, ++ 0x0020}, ++ {BRCMS_SROM_PHYCAL_TEMPDELTA, 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA, ++ 0x00ff}, ++ ++ {BRCMS_SROM_CCK2GPO, 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff}, ++ {BRCMS_SROM_CCK2GPO, 0x00000100, 0, SROM8_2G_CCKPO, 0xffff}, ++ {BRCMS_SROM_OFDM2GPO, 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM4_2G_OFDMPO + 1, 0xffff}, ++ {BRCMS_SROM_OFDM5GPO, 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM4_5G_OFDMPO + 1, 0xffff}, ++ {BRCMS_SROM_OFDM5GLPO, 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff}, ++ {BRCMS_SROM_OFDM5GHPO, 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff}, ++ {BRCMS_SROM_OFDM2GPO, 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM8_2G_OFDMPO + 1, 0xffff}, ++ {BRCMS_SROM_OFDM5GPO, 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM8_5G_OFDMPO + 1, 0xffff}, ++ {BRCMS_SROM_OFDM5GLPO, 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff}, ++ {BRCMS_SROM_OFDM5GHPO, 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS2GPO0, 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff}, ++ {BRCMS_SROM_MCS2GPO1, 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS2GPO2, 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff}, ++ {BRCMS_SROM_MCS2GPO3, 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff}, ++ {BRCMS_SROM_MCS2GPO4, 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff}, ++ {BRCMS_SROM_MCS2GPO5, 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff}, ++ {BRCMS_SROM_MCS2GPO6, 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff}, ++ {BRCMS_SROM_MCS2GPO7, 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff}, ++ {BRCMS_SROM_MCS5GPO0, 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff}, ++ {BRCMS_SROM_MCS5GPO1, 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS5GPO2, 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff}, ++ {BRCMS_SROM_MCS5GPO3, 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff}, ++ {BRCMS_SROM_MCS5GPO4, 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff}, ++ {BRCMS_SROM_MCS5GPO5, 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff}, ++ {BRCMS_SROM_MCS5GPO6, 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff}, ++ {BRCMS_SROM_MCS5GPO7, 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO0, 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO1, 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO2, 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO3, 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO4, 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO5, 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO6, 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO7, 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO0, 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO1, 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO2, 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO3, 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO4, 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO5, 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO6, 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO7, 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff}, ++ {BRCMS_SROM_MCS2GPO0, 0x00000100, 0, SROM8_2G_MCSPO, 0xffff}, ++ {BRCMS_SROM_MCS2GPO1, 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS2GPO2, 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff}, ++ {BRCMS_SROM_MCS2GPO3, 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff}, ++ {BRCMS_SROM_MCS2GPO4, 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff}, ++ {BRCMS_SROM_MCS2GPO5, 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff}, ++ {BRCMS_SROM_MCS2GPO6, 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff}, ++ {BRCMS_SROM_MCS2GPO7, 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff}, ++ {BRCMS_SROM_MCS5GPO0, 0x00000100, 0, SROM8_5G_MCSPO, 0xffff}, ++ {BRCMS_SROM_MCS5GPO1, 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS5GPO2, 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff}, ++ {BRCMS_SROM_MCS5GPO3, 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff}, ++ {BRCMS_SROM_MCS5GPO4, 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff}, ++ {BRCMS_SROM_MCS5GPO5, 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff}, ++ {BRCMS_SROM_MCS5GPO6, 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff}, ++ {BRCMS_SROM_MCS5GPO7, 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO0, 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO1, 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO2, 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO3, 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO4, 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO5, 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO6, 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO7, 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO0, 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO1, 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO2, 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO3, 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO4, 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO5, 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO6, 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO7, 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff}, ++ {BRCMS_SROM_CDDPO, 0x000000f0, 0, SROM4_CDDPO, 0xffff}, ++ {BRCMS_SROM_STBCPO, 0x000000f0, 0, SROM4_STBCPO, 0xffff}, ++ {BRCMS_SROM_BW40PO, 0x000000f0, 0, SROM4_BW40PO, 0xffff}, ++ {BRCMS_SROM_BWDUPPO, 0x000000f0, 0, SROM4_BWDUPPO, 0xffff}, ++ {BRCMS_SROM_CDDPO, 0x00000100, 0, SROM8_CDDPO, 0xffff}, ++ {BRCMS_SROM_STBCPO, 0x00000100, 0, SROM8_STBCPO, 0xffff}, ++ {BRCMS_SROM_BW40PO, 0x00000100, 0, SROM8_BW40PO, 0xffff}, ++ {BRCMS_SROM_BWDUPPO, 0x00000100, 0, SROM8_BWDUPPO, 0xffff}, ++ ++ /* power per rate from sromrev 9 */ ++ {BRCMS_SROM_CCKBW202GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff}, ++ {BRCMS_SROM_CCKBW20UL2GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff}, ++ {BRCMS_SROM_LEGOFDMBW202GPO, 0xfffffe00, SRFL_MORE, ++ SROM9_2GPO_LOFDMBW20, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff}, ++ {BRCMS_SROM_LEGOFDMBW20UL2GPO, 0xfffffe00, SRFL_MORE, ++ SROM9_2GPO_LOFDMBW20UL, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff}, ++ {BRCMS_SROM_LEGOFDMBW205GLPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GLPO_LOFDMBW20, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff}, ++ {BRCMS_SROM_LEGOFDMBW20UL5GLPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GLPO_LOFDMBW20UL, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff}, ++ {BRCMS_SROM_LEGOFDMBW205GMPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GMPO_LOFDMBW20, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff}, ++ {BRCMS_SROM_LEGOFDMBW20UL5GMPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GMPO_LOFDMBW20UL, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff}, ++ {BRCMS_SROM_LEGOFDMBW205GHPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GHPO_LOFDMBW20, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff}, ++ {BRCMS_SROM_LEGOFDMBW20UL5GHPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GHPO_LOFDMBW20UL, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW202GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW20UL2GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW402GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW205GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW20UL5GLPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GLPO_MCSBW20UL, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW405GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW205GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW20UL5GMPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GMPO_MCSBW20UL, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW405GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW205GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW20UL5GHPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GHPO_MCSBW20UL, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW405GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff}, ++ {BRCMS_SROM_MCS32PO, 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff}, ++ {BRCMS_SROM_LEGOFDM40DUPPO, 0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff}, ++ ++ {BRCMS_SROM_NULL, 0, 0, 0, 0} ++}; ++ ++static const struct brcms_sromvar perpath_pci_sromvars[] = { ++ {BRCMS_SROM_MAXP2GA0, 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff}, ++ {BRCMS_SROM_ITT2GA0, 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00}, ++ {BRCMS_SROM_ITT5GA0, 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00}, ++ {BRCMS_SROM_PA2GW0A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff}, ++ {BRCMS_SROM_PA2GW1A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff}, ++ {BRCMS_SROM_PA2GW2A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff}, ++ {BRCMS_SROM_PA2GW3A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff}, ++ {BRCMS_SROM_MAXP5GA0, 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff}, ++ {BRCMS_SROM_MAXP5GHA0, 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff}, ++ {BRCMS_SROM_MAXP5GLA0, 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00}, ++ {BRCMS_SROM_PA5GW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff}, ++ {BRCMS_SROM_PA5GW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff}, ++ {BRCMS_SROM_PA5GW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff}, ++ {BRCMS_SROM_PA5GW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff}, ++ {BRCMS_SROM_PA5GLW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff}, ++ {BRCMS_SROM_PA5GLW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1, ++ 0xffff}, ++ {BRCMS_SROM_PA5GLW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2, ++ 0xffff}, ++ {BRCMS_SROM_PA5GLW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3, ++ 0xffff}, ++ {BRCMS_SROM_PA5GHW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff}, ++ {BRCMS_SROM_PA5GHW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1, ++ 0xffff}, ++ {BRCMS_SROM_PA5GHW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2, ++ 0xffff}, ++ {BRCMS_SROM_PA5GHW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3, ++ 0xffff}, ++ {BRCMS_SROM_MAXP2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff}, ++ {BRCMS_SROM_ITT2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00}, ++ {BRCMS_SROM_ITT5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00}, ++ {BRCMS_SROM_PA2GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff}, ++ {BRCMS_SROM_PA2GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff}, ++ {BRCMS_SROM_PA2GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff}, ++ {BRCMS_SROM_MAXP5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff}, ++ {BRCMS_SROM_MAXP5GHA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff}, ++ {BRCMS_SROM_MAXP5GLA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00}, ++ {BRCMS_SROM_PA5GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff}, ++ {BRCMS_SROM_PA5GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff}, ++ {BRCMS_SROM_PA5GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff}, ++ {BRCMS_SROM_PA5GLW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff}, ++ {BRCMS_SROM_PA5GLW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1, ++ 0xffff}, ++ {BRCMS_SROM_PA5GLW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2, ++ 0xffff}, ++ {BRCMS_SROM_PA5GHW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff}, ++ {BRCMS_SROM_PA5GHW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1, ++ 0xffff}, ++ {BRCMS_SROM_PA5GHW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2, ++ 0xffff}, ++ {BRCMS_SROM_NULL, 0, 0, 0, 0} ++}; ++ ++/* crc table has the same contents for every device instance, so it can be ++ * shared between devices. */ ++static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE]; ++ ++static u16 __iomem * ++srom_window_address(struct si_pub *sih, u8 __iomem *curmap) ++{ ++ if (sih->ccrev < 32) ++ return (u16 __iomem *)(curmap + PCI_BAR0_SPROM_OFFSET); ++ if (sih->cccaps & CC_CAP_SROM) ++ return (u16 __iomem *) ++ (curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP); ++ ++ return NULL; ++} ++ ++/* Parse SROM and create name=value pairs. 'srom' points to ++ * the SROM word array. 'off' specifies the offset of the ++ * first word 'srom' points to, which should be either 0 or ++ * SROM3_SWRG_OFF (full SROM or software region). ++ */ ++ ++static uint mask_shift(u16 mask) ++{ ++ uint i; ++ for (i = 0; i < (sizeof(mask) << 3); i++) { ++ if (mask & (1 << i)) ++ return i; ++ } ++ return 0; ++} ++ ++static uint mask_width(u16 mask) ++{ ++ int i; ++ for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) { ++ if (mask & (1 << i)) ++ return (uint) (i - mask_shift(mask) + 1); ++ } ++ return 0; ++} ++ ++static inline void ltoh16_buf(u16 *buf, unsigned int size) ++{ ++ size /= 2; ++ while (size--) ++ *(buf + size) = le16_to_cpu(*(__le16 *)(buf + size)); ++} ++ ++static inline void htol16_buf(u16 *buf, unsigned int size) ++{ ++ size /= 2; ++ while (size--) ++ *(__le16 *)(buf + size) = cpu_to_le16(*(buf + size)); ++} ++ ++/* ++ * convert binary srom data into linked list of srom variable items. ++ */ ++static void ++_initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list) ++{ ++ struct brcms_srom_list_head *entry; ++ enum brcms_srom_id id; ++ u16 w; ++ u32 val; ++ const struct brcms_sromvar *srv; ++ uint width; ++ uint flags; ++ u32 sr = (1 << sromrev); ++ ++ /* first store the srom revision */ ++ entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL); ++ entry->varid = BRCMS_SROM_REV; ++ entry->var_type = BRCMS_SROM_UNUMBER; ++ entry->uval = sromrev; ++ list_add(&entry->var_list, var_list); ++ ++ for (srv = pci_sromvars; srv->varid != BRCMS_SROM_NULL; srv++) { ++ enum brcms_srom_var_type type; ++ u8 ea[ETH_ALEN]; ++ u8 extra_space = 0; ++ ++ if ((srv->revmask & sr) == 0) ++ continue; ++ ++ flags = srv->flags; ++ id = srv->varid; ++ ++ /* This entry is for mfgc only. Don't generate param for it, */ ++ if (flags & SRFL_NOVAR) ++ continue; ++ ++ if (flags & SRFL_ETHADDR) { ++ /* ++ * stored in string format XX:XX:XX:XX:XX:XX (17 chars) ++ */ ++ ea[0] = (srom[srv->off] >> 8) & 0xff; ++ ea[1] = srom[srv->off] & 0xff; ++ ea[2] = (srom[srv->off + 1] >> 8) & 0xff; ++ ea[3] = srom[srv->off + 1] & 0xff; ++ ea[4] = (srom[srv->off + 2] >> 8) & 0xff; ++ ea[5] = srom[srv->off + 2] & 0xff; ++ /* 17 characters + string terminator - union size */ ++ extra_space = 18 - sizeof(s32); ++ type = BRCMS_SROM_STRING; ++ } else { ++ w = srom[srv->off]; ++ val = (w & srv->mask) >> mask_shift(srv->mask); ++ width = mask_width(srv->mask); ++ ++ while (srv->flags & SRFL_MORE) { ++ srv++; ++ if (srv->off == 0) ++ continue; ++ ++ w = srom[srv->off]; ++ val += ++ ((w & srv->mask) >> mask_shift(srv-> ++ mask)) << ++ width; ++ width += mask_width(srv->mask); ++ } ++ ++ if ((flags & SRFL_NOFFS) ++ && ((int)val == (1 << width) - 1)) ++ continue; ++ ++ if (flags & SRFL_CCODE) { ++ type = BRCMS_SROM_STRING; ++ } else if (flags & SRFL_LEDDC) { ++ /* LED Powersave duty cycle has to be scaled: ++ *(oncount >> 24) (offcount >> 8) ++ */ ++ u32 w32 = /* oncount */ ++ (((val >> 8) & 0xff) << 24) | ++ /* offcount */ ++ (((val & 0xff)) << 8); ++ type = BRCMS_SROM_UNUMBER; ++ val = w32; ++ } else if ((flags & SRFL_PRSIGN) ++ && (val & (1 << (width - 1)))) { ++ type = BRCMS_SROM_SNUMBER; ++ val |= ~0 << width; ++ } else ++ type = BRCMS_SROM_UNUMBER; ++ } ++ ++ entry = kzalloc(sizeof(struct brcms_srom_list_head) + ++ extra_space, GFP_KERNEL); ++ entry->varid = id; ++ entry->var_type = type; ++ if (flags & SRFL_ETHADDR) { ++ snprintf(entry->buf, 18, "%pM", ea); ++ } else if (flags & SRFL_CCODE) { ++ if (val == 0) ++ entry->buf[0] = '\0'; ++ else ++ snprintf(entry->buf, 3, "%c%c", ++ (val >> 8), (val & 0xff)); ++ } else { ++ entry->uval = val; ++ } ++ ++ list_add(&entry->var_list, var_list); ++ } ++ ++ if (sromrev >= 4) { ++ /* Do per-path variables */ ++ uint p, pb, psz; ++ ++ if (sromrev >= 8) { ++ pb = SROM8_PATH0; ++ psz = SROM8_PATH1 - SROM8_PATH0; ++ } else { ++ pb = SROM4_PATH0; ++ psz = SROM4_PATH1 - SROM4_PATH0; ++ } ++ ++ for (p = 0; p < MAX_PATH_SROM; p++) { ++ for (srv = perpath_pci_sromvars; ++ srv->varid != BRCMS_SROM_NULL; srv++) { ++ if ((srv->revmask & sr) == 0) ++ continue; ++ ++ if (srv->flags & SRFL_NOVAR) ++ continue; ++ ++ w = srom[pb + srv->off]; ++ val = (w & srv->mask) >> mask_shift(srv->mask); ++ width = mask_width(srv->mask); ++ ++ /* Cheating: no per-path var is more than ++ * 1 word */ ++ if ((srv->flags & SRFL_NOFFS) ++ && ((int)val == (1 << width) - 1)) ++ continue; ++ ++ entry = ++ kzalloc(sizeof(struct brcms_srom_list_head), ++ GFP_KERNEL); ++ entry->varid = srv->varid+p; ++ entry->var_type = BRCMS_SROM_UNUMBER; ++ entry->uval = val; ++ list_add(&entry->var_list, var_list); ++ } ++ pb += psz; ++ } ++ } ++} ++ ++/* ++ * Read in and validate sprom. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++sprom_read_pci(struct si_pub *sih, u16 __iomem *sprom, uint wordoff, ++ u16 *buf, uint nwords, bool check_crc) ++{ ++ int err = 0; ++ uint i; ++ ++ /* read the sprom */ ++ for (i = 0; i < nwords; i++) ++ buf[i] = R_REG(&sprom[wordoff + i]); ++ ++ if (check_crc) { ++ ++ if (buf[0] == 0xffff) ++ /* ++ * The hardware thinks that an srom that starts with ++ * 0xffff is blank, regardless of the rest of the ++ * content, so declare it bad. ++ */ ++ return -ENODATA; ++ ++ /* fixup the endianness so crc8 will pass */ ++ htol16_buf(buf, nwords * 2); ++ if (crc8(brcms_srom_crc8_table, (u8 *) buf, nwords * 2, ++ CRC8_INIT_VALUE) != ++ CRC8_GOOD_VALUE(brcms_srom_crc8_table)) ++ /* DBG only pci always read srom4 first, then srom8/9 */ ++ err = -EIO; ++ ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(buf, nwords * 2); ++ } ++ return err; ++} ++ ++static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz) ++{ ++ u8 *otp; ++ uint sz = OTP_SZ_MAX / 2; /* size in words */ ++ int err = 0; ++ ++ otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC); ++ if (otp == NULL) ++ return -ENOMEM; ++ ++ err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz); ++ ++ memcpy(buf, otp, bufsz); ++ ++ kfree(otp); ++ ++ /* Check CRC */ ++ if (buf[0] == 0xffff) ++ /* The hardware thinks that an srom that starts with 0xffff ++ * is blank, regardless of the rest of the content, so declare ++ * it bad. ++ */ ++ return -ENODATA; ++ ++ /* fixup the endianness so crc8 will pass */ ++ htol16_buf(buf, bufsz); ++ if (crc8(brcms_srom_crc8_table, (u8 *) buf, SROM4_WORDS * 2, ++ CRC8_INIT_VALUE) != CRC8_GOOD_VALUE(brcms_srom_crc8_table)) ++ err = -EIO; ++ ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(buf, bufsz); ++ ++ return err; ++} ++ ++/* ++ * Initialize nonvolatile variable table from sprom. ++ * Return 0 on success, nonzero on error. ++ */ ++static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap) ++{ ++ u16 *srom; ++ u16 __iomem *sromwindow; ++ u8 sromrev = 0; ++ u32 sr; ++ int err = 0; ++ ++ /* ++ * Apply CRC over SROM content regardless SROM is present or not. ++ */ ++ srom = kmalloc(SROM_MAX, GFP_ATOMIC); ++ if (!srom) ++ return -ENOMEM; ++ ++ sromwindow = srom_window_address(sih, curmap); ++ ++ crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY); ++ if (ai_is_sprom_available(sih)) { ++ err = sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS, ++ true); ++ ++ if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) || ++ (((sih->buscoretype == PCIE_CORE_ID) ++ && (sih->buscorerev >= 6)) ++ || ((sih->buscoretype == PCI_CORE_ID) ++ && (sih->buscorerev >= 0xe)))) { ++ /* sromrev >= 4, read more */ ++ err = sprom_read_pci(sih, sromwindow, 0, srom, ++ SROM4_WORDS, true); ++ sromrev = srom[SROM4_CRCREV] & 0xff; ++ } else if (err == 0) { ++ /* srom is good and is rev < 4 */ ++ /* top word of sprom contains version and crc8 */ ++ sromrev = srom[SROM_CRCREV] & 0xff; ++ /* bcm4401 sroms misprogrammed */ ++ if (sromrev == 0x10) ++ sromrev = 1; ++ } ++ } else { ++ /* Use OTP if SPROM not available */ ++ err = otp_read_pci(sih, srom, SROM_MAX); ++ if (err == 0) ++ /* OTP only contain SROM rev8/rev9 for now */ ++ sromrev = srom[SROM4_CRCREV] & 0xff; ++ } ++ ++ if (!err) { ++ struct si_info *sii = (struct si_info *)sih; ++ ++ /* Bitmask for the sromrev */ ++ sr = 1 << sromrev; ++ ++ /* ++ * srom version check: Current valid versions: 1, 2, 3, 4, 5, 8, ++ * 9 ++ */ ++ if ((sr & 0x33e) == 0) { ++ err = -EINVAL; ++ goto errout; ++ } ++ ++ INIT_LIST_HEAD(&sii->var_list); ++ ++ /* parse SROM into name=value pairs. */ ++ _initvars_srom_pci(sromrev, srom, &sii->var_list); ++ } ++ ++errout: ++ kfree(srom); ++ return err; ++} ++ ++void srom_free_vars(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ struct brcms_srom_list_head *entry, *next; ++ ++ sii = (struct si_info *)sih; ++ list_for_each_entry_safe(entry, next, &sii->var_list, var_list) { ++ list_del(&entry->var_list); ++ kfree(entry); ++ } ++} ++/* ++ * Initialize local vars from the right source for this platform. ++ * Return 0 on success, nonzero on error. ++ */ ++int srom_var_init(struct si_pub *sih, void __iomem *curmap) ++{ ++ uint len; ++ ++ len = 0; ++ ++ if (curmap != NULL) ++ return initvars_srom_pci(sih, curmap); ++ ++ return -EINVAL; ++} ++ ++/* ++ * Search the name=value vars for a specific one and return its value. ++ * Returns NULL if not found. ++ */ ++char *getvar(struct si_pub *sih, enum brcms_srom_id id) ++{ ++ struct si_info *sii; ++ struct brcms_srom_list_head *entry; ++ ++ sii = (struct si_info *)sih; ++ ++ list_for_each_entry(entry, &sii->var_list, var_list) ++ if (entry->varid == id) ++ return &entry->buf[0]; ++ ++ /* nothing found */ ++ return NULL; ++} ++ ++/* ++ * Search the vars for a specific one and return its value as ++ * an integer. Returns 0 if not found.- ++ */ ++int getintvar(struct si_pub *sih, enum brcms_srom_id id) ++{ ++ struct si_info *sii; ++ struct brcms_srom_list_head *entry; ++ unsigned long res; ++ ++ sii = (struct si_info *)sih; ++ ++ list_for_each_entry(entry, &sii->var_list, var_list) ++ if (entry->varid == id) { ++ if (entry->var_type == BRCMS_SROM_SNUMBER || ++ entry->var_type == BRCMS_SROM_UNUMBER) ++ return (int)entry->sval; ++ else if (!kstrtoul(&entry->buf[0], 0, &res)) ++ return (int)res; ++ } ++ ++ return 0; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.h.orig 2011-11-09 13:46:58.285800133 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.h 2011-11-09 13:47:17.044565616 -0500 +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_SROM_H_ ++#define _BRCM_SROM_H_ ++ ++#include "types.h" ++ ++/* Prototypes */ ++extern int srom_var_init(struct si_pub *sih, void __iomem *curmap); ++extern void srom_free_vars(struct si_pub *sih); ++ ++extern int srom_read(struct si_pub *sih, uint bus, void *curmap, ++ uint byteoff, uint nbytes, u16 *buf, bool check_crc); ++ ++/* parse standard PCMCIA cis, normally used by SB/PCMCIA/SDIO/SPI/OTP ++ * and extract from it into name=value pairs ++ */ ++extern int srom_parsecis(u8 **pcis, uint ciscnt, ++ char **vars, uint *count); ++#endif /* _BRCM_SROM_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.c.orig 2011-11-09 13:46:58.286800121 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.c 2011-11-09 13:47:17.045565604 -0500 +@@ -0,0 +1,436 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++ ++#include "types.h" ++#include "d11.h" ++#include "rate.h" ++#include "phy/phy_hal.h" ++#include "channel.h" ++#include "main.h" ++#include "stf.h" ++ ++#define MIN_SPATIAL_EXPANSION 0 ++#define MAX_SPATIAL_EXPANSION 1 ++ ++#define BRCMS_STF_SS_STBC_RX(wlc) (BRCMS_ISNPHY(wlc->band) && \ ++ NREV_GT(wlc->band->phyrev, 3) && NREV_LE(wlc->band->phyrev, 6)) ++ ++#define NSTS_1 1 ++#define NSTS_2 2 ++#define NSTS_3 3 ++#define NSTS_4 4 ++ ++static const u8 txcore_default[5] = { ++ (0), /* bitmap of the core enabled */ ++ (0x01), /* For Nsts = 1, enable core 1 */ ++ (0x03), /* For Nsts = 2, enable core 1 & 2 */ ++ (0x07), /* For Nsts = 3, enable core 1, 2 & 3 */ ++ (0x0f) /* For Nsts = 4, enable all cores */ ++}; ++ ++static void brcms_c_stf_stbc_rx_ht_update(struct brcms_c_info *wlc, int val) ++{ ++ /* MIMOPHYs rev3-6 cannot receive STBC with only one rx core active */ ++ if (BRCMS_STF_SS_STBC_RX(wlc)) { ++ if ((wlc->stf->rxstreams == 1) && (val != HT_CAP_RX_STBC_NO)) ++ return; ++ } ++ ++ if (wlc->pub->up) { ++ brcms_c_update_beacon(wlc); ++ brcms_c_update_probe_resp(wlc, true); ++ } ++} ++ ++/* ++ * every WLC_TEMPSENSE_PERIOD seconds temperature check to decide whether to ++ * turn on/off txchain. ++ */ ++void brcms_c_tempsense_upd(struct brcms_c_info *wlc) ++{ ++ struct brcms_phy_pub *pi = wlc->band->pi; ++ uint active_chains, txchain; ++ ++ /* Check if the chip is too hot. Disable one Tx chain, if it is */ ++ /* high 4 bits are for Rx chain, low 4 bits are for Tx chain */ ++ active_chains = wlc_phy_stf_chain_active_get(pi); ++ txchain = active_chains & 0xf; ++ ++ if (wlc->stf->txchain == wlc->stf->hw_txchain) { ++ if (txchain && (txchain < wlc->stf->hw_txchain)) ++ /* turn off 1 tx chain */ ++ brcms_c_stf_txchain_set(wlc, txchain, true); ++ } else if (wlc->stf->txchain < wlc->stf->hw_txchain) { ++ if (txchain == wlc->stf->hw_txchain) ++ /* turn back on txchain */ ++ brcms_c_stf_txchain_set(wlc, txchain, true); ++ } ++} ++ ++void ++brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel, ++ u16 chanspec) ++{ ++ struct tx_power power; ++ u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id; ++ ++ /* Clear previous settings */ ++ *ss_algo_channel = 0; ++ ++ if (!wlc->pub->up) { ++ *ss_algo_channel = (u16) -1; ++ return; ++ } ++ ++ wlc_phy_txpower_get_current(wlc->band->pi, &power, ++ CHSPEC_CHANNEL(chanspec)); ++ ++ siso_mcs_id = (CHSPEC_IS40(chanspec)) ? ++ WL_TX_POWER_MCS40_SISO_FIRST : WL_TX_POWER_MCS20_SISO_FIRST; ++ cdd_mcs_id = (CHSPEC_IS40(chanspec)) ? ++ WL_TX_POWER_MCS40_CDD_FIRST : WL_TX_POWER_MCS20_CDD_FIRST; ++ stbc_mcs_id = (CHSPEC_IS40(chanspec)) ? ++ WL_TX_POWER_MCS40_STBC_FIRST : WL_TX_POWER_MCS20_STBC_FIRST; ++ ++ /* criteria to choose stf mode */ ++ ++ /* ++ * the "+3dbm (12 0.25db units)" is to account for the fact that with ++ * CDD, tx occurs on both chains ++ */ ++ if (power.target[siso_mcs_id] > (power.target[cdd_mcs_id] + 12)) ++ setbit(ss_algo_channel, PHY_TXC1_MODE_SISO); ++ else ++ setbit(ss_algo_channel, PHY_TXC1_MODE_CDD); ++ ++ /* ++ * STBC is ORed into to algo channel as STBC requires per-packet SCB ++ * capability check so cannot be default mode of operation. One of ++ * SISO, CDD have to be set ++ */ ++ if (power.target[siso_mcs_id] <= (power.target[stbc_mcs_id] + 12)) ++ setbit(ss_algo_channel, PHY_TXC1_MODE_STBC); ++} ++ ++static bool brcms_c_stf_stbc_tx_set(struct brcms_c_info *wlc, s32 int_val) ++{ ++ if ((int_val != AUTO) && (int_val != OFF) && (int_val != ON)) ++ return false; ++ ++ if ((int_val == ON) && (wlc->stf->txstreams == 1)) ++ return false; ++ ++ wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = (s8) int_val; ++ wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = (s8) int_val; ++ ++ return true; ++} ++ ++bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val) ++{ ++ if ((int_val != HT_CAP_RX_STBC_NO) ++ && (int_val != HT_CAP_RX_STBC_ONE_STREAM)) ++ return false; ++ ++ if (BRCMS_STF_SS_STBC_RX(wlc)) { ++ if ((int_val != HT_CAP_RX_STBC_NO) ++ && (wlc->stf->rxstreams == 1)) ++ return false; ++ } ++ ++ brcms_c_stf_stbc_rx_ht_update(wlc, int_val); ++ return true; ++} ++ ++static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts, ++ u8 core_mask) ++{ ++ BCMMSG(wlc->wiphy, "wl%d: Nsts %d core_mask %x\n", ++ wlc->pub->unit, Nsts, core_mask); ++ ++ if (hweight8(core_mask) > wlc->stf->txstreams) ++ core_mask = 0; ++ ++ if ((hweight8(core_mask) == wlc->stf->txstreams) && ++ ((core_mask & ~wlc->stf->txchain) ++ || !(core_mask & wlc->stf->txchain))) ++ core_mask = wlc->stf->txchain; ++ ++ wlc->stf->txcore[Nsts] = core_mask; ++ /* Nsts = 1..4, txcore index = 1..4 */ ++ if (Nsts == 1) { ++ /* Needs to update beacon and ucode generated response ++ * frames when 1 stream core map changed ++ */ ++ wlc->stf->phytxant = core_mask << PHY_TXC_ANT_SHIFT; ++ brcms_b_txant_set(wlc->hw, wlc->stf->phytxant); ++ if (wlc->clk) { ++ brcms_c_suspend_mac_and_wait(wlc); ++ brcms_c_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec); ++ brcms_c_enable_mac(wlc); ++ } ++ } ++ ++ return 0; ++} ++ ++static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val) ++{ ++ int i; ++ u8 core_mask = 0; ++ ++ BCMMSG(wlc->wiphy, "wl%d: val %x\n", wlc->pub->unit, val); ++ ++ wlc->stf->spatial_policy = (s8) val; ++ for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) { ++ core_mask = (val == MAX_SPATIAL_EXPANSION) ? ++ wlc->stf->txchain : txcore_default[i]; ++ brcms_c_stf_txcore_set(wlc, (u8) i, core_mask); ++ } ++ return 0; ++} ++ ++/* ++ * Centralized txant update function. call it whenever wlc->stf->txant and/or ++ * wlc->stf->txchain change. ++ * ++ * Antennas are controlled by ucode indirectly, which drives PHY or GPIO to ++ * achieve various tx/rx antenna selection schemes ++ * ++ * legacy phy, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 ++ * means auto(last rx). ++ * for NREV<3, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 ++ * means last rx and do tx-antenna selection for SISO transmissions ++ * for NREV=3, bit 6 and bit _8_ means antenna 0 and 1 respectively, bit6+bit7 ++ * means last rx and do tx-antenna selection for SISO transmissions ++ * for NREV>=7, bit 6 and bit 7 mean antenna 0 and 1 respectively, nit6+bit7 ++ * means both cores active ++*/ ++static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc) ++{ ++ s8 txant; ++ ++ txant = (s8) wlc->stf->txant; ++ if (BRCMS_PHY_11N_CAP(wlc->band)) { ++ if (txant == ANT_TX_FORCE_0) { ++ wlc->stf->phytxant = PHY_TXC_ANT_0; ++ } else if (txant == ANT_TX_FORCE_1) { ++ wlc->stf->phytxant = PHY_TXC_ANT_1; ++ ++ if (BRCMS_ISNPHY(wlc->band) && ++ NREV_GE(wlc->band->phyrev, 3) ++ && NREV_LT(wlc->band->phyrev, 7)) ++ wlc->stf->phytxant = PHY_TXC_ANT_2; ++ } else { ++ if (BRCMS_ISLCNPHY(wlc->band) || ++ BRCMS_ISSSLPNPHY(wlc->band)) ++ wlc->stf->phytxant = PHY_TXC_LCNPHY_ANT_LAST; ++ else { ++ /* catch out of sync wlc->stf->txcore */ ++ WARN_ON(wlc->stf->txchain <= 0); ++ wlc->stf->phytxant = ++ wlc->stf->txchain << PHY_TXC_ANT_SHIFT; ++ } ++ } ++ } else { ++ if (txant == ANT_TX_FORCE_0) ++ wlc->stf->phytxant = PHY_TXC_OLD_ANT_0; ++ else if (txant == ANT_TX_FORCE_1) ++ wlc->stf->phytxant = PHY_TXC_OLD_ANT_1; ++ else ++ wlc->stf->phytxant = PHY_TXC_OLD_ANT_LAST; ++ } ++ ++ brcms_b_txant_set(wlc->hw, wlc->stf->phytxant); ++} ++ ++int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force) ++{ ++ u8 txchain = (u8) int_val; ++ u8 txstreams; ++ uint i; ++ ++ if (wlc->stf->txchain == txchain) ++ return 0; ++ ++ if ((txchain & ~wlc->stf->hw_txchain) ++ || !(txchain & wlc->stf->hw_txchain)) ++ return -EINVAL; ++ ++ /* ++ * if nrate override is configured to be non-SISO STF mode, reject ++ * reducing txchain to 1 ++ */ ++ txstreams = (u8) hweight8(txchain); ++ if (txstreams > MAX_STREAMS_SUPPORTED) ++ return -EINVAL; ++ ++ wlc->stf->txchain = txchain; ++ wlc->stf->txstreams = txstreams; ++ brcms_c_stf_stbc_tx_set(wlc, wlc->band->band_stf_stbc_tx); ++ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]); ++ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]); ++ wlc->stf->txant = ++ (wlc->stf->txstreams == 1) ? ANT_TX_FORCE_0 : ANT_TX_DEF; ++ _brcms_c_stf_phy_txant_upd(wlc); ++ ++ wlc_phy_stf_chain_set(wlc->band->pi, wlc->stf->txchain, ++ wlc->stf->rxchain); ++ ++ for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) ++ brcms_c_stf_txcore_set(wlc, (u8) i, txcore_default[i]); ++ ++ return 0; ++} ++ ++/* ++ * update wlc->stf->ss_opmode which represents the operational stf_ss mode ++ * we're using ++ */ ++int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band) ++{ ++ int ret_code = 0; ++ u8 prev_stf_ss; ++ u8 upd_stf_ss; ++ ++ prev_stf_ss = wlc->stf->ss_opmode; ++ ++ /* ++ * NOTE: opmode can only be SISO or CDD as STBC is decided on a ++ * per-packet basis ++ */ ++ if (BRCMS_STBC_CAP_PHY(wlc) && ++ wlc->stf->ss_algosel_auto ++ && (wlc->stf->ss_algo_channel != (u16) -1)) { ++ upd_stf_ss = (wlc->stf->txstreams == 1 || ++ isset(&wlc->stf->ss_algo_channel, ++ PHY_TXC1_MODE_SISO)) ? ++ PHY_TXC1_MODE_SISO : PHY_TXC1_MODE_CDD; ++ } else { ++ if (wlc->band != band) ++ return ret_code; ++ upd_stf_ss = (wlc->stf->txstreams == 1) ? ++ PHY_TXC1_MODE_SISO : band->band_stf_ss_mode; ++ } ++ if (prev_stf_ss != upd_stf_ss) { ++ wlc->stf->ss_opmode = upd_stf_ss; ++ brcms_b_band_stf_ss_set(wlc->hw, upd_stf_ss); ++ } ++ ++ return ret_code; ++} ++ ++int brcms_c_stf_attach(struct brcms_c_info *wlc) ++{ ++ wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_SISO; ++ wlc->bandstate[BAND_5G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_CDD; ++ ++ if (BRCMS_ISNPHY(wlc->band) && ++ (wlc_phy_txpower_hw_ctrl_get(wlc->band->pi) != PHY_TPC_HW_ON)) ++ wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode = ++ PHY_TXC1_MODE_CDD; ++ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]); ++ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]); ++ ++ brcms_c_stf_stbc_rx_ht_update(wlc, HT_CAP_RX_STBC_NO); ++ wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF; ++ wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF; ++ ++ if (BRCMS_STBC_CAP_PHY(wlc)) { ++ wlc->stf->ss_algosel_auto = true; ++ /* Init the default value */ ++ wlc->stf->ss_algo_channel = (u16) -1; ++ } ++ return 0; ++} ++ ++void brcms_c_stf_detach(struct brcms_c_info *wlc) ++{ ++} ++ ++void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc) ++{ ++ _brcms_c_stf_phy_txant_upd(wlc); ++} ++ ++void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc) ++{ ++ /* get available rx/tx chains */ ++ wlc->stf->hw_txchain = (u8) getintvar(wlc->hw->sih, BRCMS_SROM_TXCHAIN); ++ wlc->stf->hw_rxchain = (u8) getintvar(wlc->hw->sih, BRCMS_SROM_RXCHAIN); ++ ++ /* these parameter are intended to be used for all PHY types */ ++ if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) { ++ if (BRCMS_ISNPHY(wlc->band)) ++ wlc->stf->hw_txchain = TXCHAIN_DEF_NPHY; ++ else ++ wlc->stf->hw_txchain = TXCHAIN_DEF; ++ } ++ ++ wlc->stf->txchain = wlc->stf->hw_txchain; ++ wlc->stf->txstreams = (u8) hweight8(wlc->stf->hw_txchain); ++ ++ if (wlc->stf->hw_rxchain == 0 || wlc->stf->hw_rxchain == 0xf) { ++ if (BRCMS_ISNPHY(wlc->band)) ++ wlc->stf->hw_rxchain = RXCHAIN_DEF_NPHY; ++ else ++ wlc->stf->hw_rxchain = RXCHAIN_DEF; ++ } ++ ++ wlc->stf->rxchain = wlc->stf->hw_rxchain; ++ wlc->stf->rxstreams = (u8) hweight8(wlc->stf->hw_rxchain); ++ ++ /* initialize the txcore table */ ++ memcpy(wlc->stf->txcore, txcore_default, sizeof(wlc->stf->txcore)); ++ ++ /* default spatial_policy */ ++ wlc->stf->spatial_policy = MIN_SPATIAL_EXPANSION; ++ brcms_c_stf_spatial_policy_set(wlc, MIN_SPATIAL_EXPANSION); ++} ++ ++static u16 _brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, ++ u32 rspec) ++{ ++ u16 phytxant = wlc->stf->phytxant; ++ ++ if (rspec_stf(rspec) != PHY_TXC1_MODE_SISO) ++ phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT; ++ else if (wlc->stf->txant == ANT_TX_DEF) ++ phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT; ++ phytxant &= PHY_TXC_ANT_MASK; ++ return phytxant; ++} ++ ++u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, u32 rspec) ++{ ++ return _brcms_c_stf_phytxchain_sel(wlc, rspec); ++} ++ ++u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, u32 rspec) ++{ ++ u16 phytxant = wlc->stf->phytxant; ++ u16 mask = PHY_TXC_ANT_MASK; ++ ++ /* for non-siso rates or default setting, use the available chains */ ++ if (BRCMS_ISNPHY(wlc->band)) { ++ phytxant = _brcms_c_stf_phytxchain_sel(wlc, rspec); ++ mask = PHY_TXC_HTANT_MASK; ++ } ++ phytxant |= phytxant & mask; ++ return phytxant; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.h.orig 2011-11-09 13:46:58.286800121 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.h 2011-11-09 13:47:17.045565604 -0500 +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_STF_H_ ++#define _BRCM_STF_H_ ++ ++#include "types.h" ++ ++extern int brcms_c_stf_attach(struct brcms_c_info *wlc); ++extern void brcms_c_stf_detach(struct brcms_c_info *wlc); ++ ++extern void brcms_c_tempsense_upd(struct brcms_c_info *wlc); ++extern void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, ++ u16 *ss_algo_channel, ++ u16 chanspec); ++extern int brcms_c_stf_ss_update(struct brcms_c_info *wlc, ++ struct brcms_band *band); ++extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc); ++extern int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, ++ bool force); ++extern bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val); ++extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc); ++extern void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc); ++extern u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, ++ u32 rspec); ++extern u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, ++ u32 rspec); ++ ++#endif /* _BRCM_STF_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/types.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/types.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/types.h.orig 2011-11-09 13:46:58.286800121 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/types.h 2011-11-09 13:47:17.045565604 -0500 +@@ -0,0 +1,352 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_TYPES_H_ ++#define _BRCM_TYPES_H_ ++ ++#include ++#include ++ ++#define WL_CHAN_FREQ_RANGE_2G 0 ++#define WL_CHAN_FREQ_RANGE_5GL 1 ++#define WL_CHAN_FREQ_RANGE_5GM 2 ++#define WL_CHAN_FREQ_RANGE_5GH 3 ++ ++/* boardflags */ ++ ++/* Board has gpio 9 controlling the PA */ ++#define BFL_PACTRL 0x00000002 ++/* Not ok to power down the chip pll and oscillator */ ++#define BFL_NOPLLDOWN 0x00000020 ++/* Board supports the Front End Module */ ++#define BFL_FEM 0x00000800 ++/* Board has an external LNA in 2.4GHz band */ ++#define BFL_EXTLNA 0x00001000 ++/* Board has no PA */ ++#define BFL_NOPA 0x00010000 ++/* Power topology uses BUCKBOOST */ ++#define BFL_BUCKBOOST 0x00200000 ++/* Board has FEM and switch to share antenna w/ BT */ ++#define BFL_FEM_BT 0x00400000 ++/* Power topology doesn't use CBUCK */ ++#define BFL_NOCBUCK 0x00800000 ++/* Power topology uses PALDO */ ++#define BFL_PALDO 0x02000000 ++/* Board has an external LNA in 5GHz band */ ++#define BFL_EXTLNA_5GHz 0x10000000 ++ ++/* boardflags2 */ ++ ++/* Board has an external rxbb regulator */ ++#define BFL2_RXBB_INT_REG_DIS 0x00000001 ++/* Flag to implement alternative A-band PLL settings */ ++#define BFL2_APLL_WAR 0x00000002 ++/* Board permits enabling TX Power Control */ ++#define BFL2_TXPWRCTRL_EN 0x00000004 ++/* Board supports the 2X4 diversity switch */ ++#define BFL2_2X4_DIV 0x00000008 ++/* Board supports 5G band power gain */ ++#define BFL2_5G_PWRGAIN 0x00000010 ++/* Board overrides ASPM and Clkreq settings */ ++#define BFL2_PCIEWAR_OVR 0x00000020 ++#define BFL2_LEGACY 0x00000080 ++/* 4321mcm93 board uses Skyworks FEM */ ++#define BFL2_SKWRKFEM_BRD 0x00000100 ++/* Board has a WAR for clock-harmonic spurs */ ++#define BFL2_SPUR_WAR 0x00000200 ++/* Flag to narrow G-band PLL loop b/w */ ++#define BFL2_GPLL_WAR 0x00000400 ++/* Tx CCK pkts on Ant 0 only */ ++#define BFL2_SINGLEANT_CCK 0x00001000 ++/* WAR to reduce and avoid clock-harmonic spurs in 2G */ ++#define BFL2_2G_SPUR_WAR 0x00002000 ++/* Flag to widen G-band PLL loop b/w */ ++#define BFL2_GPLL_WAR2 0x00010000 ++#define BFL2_IPALVLSHIFT_3P3 0x00020000 ++/* Use internal envelope detector for TX IQCAL */ ++#define BFL2_INTERNDET_TXIQCAL 0x00040000 ++/* Keep the buffered Xtal output from radio "ON". Most drivers will turn it ++ * off without this flag to save power. */ ++#define BFL2_XTALBUFOUTEN 0x00080000 ++ ++/* ++ * board specific GPIO assignment, gpio 0-3 are also customer-configurable ++ * led ++ */ ++ ++/* bit 9 controls the PA on new 4306 boards */ ++#define BOARD_GPIO_PACTRL 0x200 ++#define BOARD_GPIO_12 0x1000 ++#define BOARD_GPIO_13 0x2000 ++ ++/* **** Core type/rev defaults **** */ ++#define D11CONF 0x0fffffb0 /* Supported D11 revs: 4, 5, 7-27 ++ * also need to update wlc.h MAXCOREREV ++ */ ++ ++#define NCONF 0x000001ff /* Supported nphy revs: ++ * 0 4321a0 ++ * 1 4321a1 ++ * 2 4321b0/b1/c0/c1 ++ * 3 4322a0 ++ * 4 4322a1 ++ * 5 4716a0 ++ * 6 43222a0, 43224a0 ++ * 7 43226a0 ++ * 8 5357a0, 43236a0 ++ */ ++ ++#define LCNCONF 0x00000007 /* Supported lcnphy revs: ++ * 0 4313a0, 4336a0, 4330a0 ++ * 1 ++ * 2 4330a0 ++ */ ++ ++#define SSLPNCONF 0x0000000f /* Supported sslpnphy revs: ++ * 0 4329a0/k0 ++ * 1 4329b0/4329C0 ++ * 2 4319a0 ++ * 3 5356a0 ++ */ ++ ++/******************************************************************** ++ * Phy/Core Configuration. Defines macros to to check core phy/rev * ++ * compile-time configuration. Defines default core support. * ++ * ****************************************************************** ++ */ ++ ++/* Basic macros to check a configuration bitmask */ ++ ++#define CONF_HAS(config, val) ((config) & (1 << (val))) ++#define CONF_MSK(config, mask) ((config) & (mask)) ++#define MSK_RANGE(low, hi) ((1 << ((hi)+1)) - (1 << (low))) ++#define CONF_RANGE(config, low, hi) (CONF_MSK(config, MSK_RANGE(low, high))) ++ ++#define CONF_IS(config, val) ((config) == (1 << (val))) ++#define CONF_GE(config, val) ((config) & (0-(1 << (val)))) ++#define CONF_GT(config, val) ((config) & (0-2*(1 << (val)))) ++#define CONF_LT(config, val) ((config) & ((1 << (val))-1)) ++#define CONF_LE(config, val) ((config) & (2*(1 << (val))-1)) ++ ++/* Wrappers for some of the above, specific to config constants */ ++ ++#define NCONF_HAS(val) CONF_HAS(NCONF, val) ++#define NCONF_MSK(mask) CONF_MSK(NCONF, mask) ++#define NCONF_IS(val) CONF_IS(NCONF, val) ++#define NCONF_GE(val) CONF_GE(NCONF, val) ++#define NCONF_GT(val) CONF_GT(NCONF, val) ++#define NCONF_LT(val) CONF_LT(NCONF, val) ++#define NCONF_LE(val) CONF_LE(NCONF, val) ++ ++#define LCNCONF_HAS(val) CONF_HAS(LCNCONF, val) ++#define LCNCONF_MSK(mask) CONF_MSK(LCNCONF, mask) ++#define LCNCONF_IS(val) CONF_IS(LCNCONF, val) ++#define LCNCONF_GE(val) CONF_GE(LCNCONF, val) ++#define LCNCONF_GT(val) CONF_GT(LCNCONF, val) ++#define LCNCONF_LT(val) CONF_LT(LCNCONF, val) ++#define LCNCONF_LE(val) CONF_LE(LCNCONF, val) ++ ++#define D11CONF_HAS(val) CONF_HAS(D11CONF, val) ++#define D11CONF_MSK(mask) CONF_MSK(D11CONF, mask) ++#define D11CONF_IS(val) CONF_IS(D11CONF, val) ++#define D11CONF_GE(val) CONF_GE(D11CONF, val) ++#define D11CONF_GT(val) CONF_GT(D11CONF, val) ++#define D11CONF_LT(val) CONF_LT(D11CONF, val) ++#define D11CONF_LE(val) CONF_LE(D11CONF, val) ++ ++#define PHYCONF_HAS(val) CONF_HAS(PHYTYPE, val) ++#define PHYCONF_IS(val) CONF_IS(PHYTYPE, val) ++ ++#define NREV_IS(var, val) \ ++ (NCONF_HAS(val) && (NCONF_IS(val) || ((var) == (val)))) ++ ++#define NREV_GE(var, val) \ ++ (NCONF_GE(val) && (!NCONF_LT(val) || ((var) >= (val)))) ++ ++#define NREV_GT(var, val) \ ++ (NCONF_GT(val) && (!NCONF_LE(val) || ((var) > (val)))) ++ ++#define NREV_LT(var, val) \ ++ (NCONF_LT(val) && (!NCONF_GE(val) || ((var) < (val)))) ++ ++#define NREV_LE(var, val) \ ++ (NCONF_LE(val) && (!NCONF_GT(val) || ((var) <= (val)))) ++ ++#define LCNREV_IS(var, val) \ ++ (LCNCONF_HAS(val) && (LCNCONF_IS(val) || ((var) == (val)))) ++ ++#define LCNREV_GE(var, val) \ ++ (LCNCONF_GE(val) && (!LCNCONF_LT(val) || ((var) >= (val)))) ++ ++#define LCNREV_GT(var, val) \ ++ (LCNCONF_GT(val) && (!LCNCONF_LE(val) || ((var) > (val)))) ++ ++#define LCNREV_LT(var, val) \ ++ (LCNCONF_LT(val) && (!LCNCONF_GE(val) || ((var) < (val)))) ++ ++#define LCNREV_LE(var, val) \ ++ (LCNCONF_LE(val) && (!LCNCONF_GT(val) || ((var) <= (val)))) ++ ++#define D11REV_IS(var, val) \ ++ (D11CONF_HAS(val) && (D11CONF_IS(val) || ((var) == (val)))) ++ ++#define D11REV_GE(var, val) \ ++ (D11CONF_GE(val) && (!D11CONF_LT(val) || ((var) >= (val)))) ++ ++#define D11REV_GT(var, val) \ ++ (D11CONF_GT(val) && (!D11CONF_LE(val) || ((var) > (val)))) ++ ++#define D11REV_LT(var, val) \ ++ (D11CONF_LT(val) && (!D11CONF_GE(val) || ((var) < (val)))) ++ ++#define D11REV_LE(var, val) \ ++ (D11CONF_LE(val) && (!D11CONF_GT(val) || ((var) <= (val)))) ++ ++#define PHYTYPE_IS(var, val)\ ++ (PHYCONF_HAS(val) && (PHYCONF_IS(val) || ((var) == (val)))) ++ ++/* Set up PHYTYPE automatically: (depends on PHY_TYPE_X, from d11.h) */ ++ ++#define _PHYCONF_N (1 << PHY_TYPE_N) ++#define _PHYCONF_LCN (1 << PHY_TYPE_LCN) ++#define _PHYCONF_SSLPN (1 << PHY_TYPE_SSN) ++ ++#define PHYTYPE (_PHYCONF_N | _PHYCONF_LCN | _PHYCONF_SSLPN) ++ ++/* Utility macro to identify 802.11n (HT) capable PHYs */ ++#define PHYTYPE_11N_CAP(phytype) \ ++ (PHYTYPE_IS(phytype, PHY_TYPE_N) || \ ++ PHYTYPE_IS(phytype, PHY_TYPE_LCN) || \ ++ PHYTYPE_IS(phytype, PHY_TYPE_SSN)) ++ ++/* Last but not least: shorter wlc-specific var checks */ ++#define BRCMS_ISNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_N) ++#define BRCMS_ISLCNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_LCN) ++#define BRCMS_ISSSLPNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_SSN) ++ ++#define BRCMS_PHY_11N_CAP(band) PHYTYPE_11N_CAP((band)->phytype) ++ ++/********************************************************************** ++ * ------------- End of Core phy/rev configuration. ----------------- * ++ * ******************************************************************** ++ */ ++ ++#define BCMMSG(dev, fmt, args...) \ ++do { \ ++ if (brcm_msg_level & LOG_TRACE_VAL) \ ++ wiphy_err(dev, "%s: " fmt, __func__, ##args); \ ++} while (0) ++ ++/* ++ * Register access macros. ++ * ++ * These macro's take a pointer to the address to read as one of their ++ * arguments. The macro itself deduces the size of the IO transaction (u8, u16 ++ * or u32). Advantage of this approach in combination with using a struct to ++ * define the registers in a register block, is that access size and access ++ * location are defined in only one spot. This reduces the risk of the ++ * programmer trying to use an unsupported transaction size on a register. ++ * ++ */ ++ ++#define R_REG(r) \ ++ ({ \ ++ __typeof(*(r)) __osl_v; \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(u8): \ ++ __osl_v = readb((u8 __iomem *)(r)); \ ++ break; \ ++ case sizeof(u16): \ ++ __osl_v = readw((u16 __iomem *)(r)); \ ++ break; \ ++ case sizeof(u32): \ ++ __osl_v = readl((u32 __iomem *)(r)); \ ++ break; \ ++ } \ ++ __osl_v; \ ++ }) ++ ++#define W_REG(r, v) do { \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(u8): \ ++ writeb((u8)((v) & 0xFF), (u8 __iomem *)(r)); \ ++ break; \ ++ case sizeof(u16): \ ++ writew((u16)((v) & 0xFFFF), (u16 __iomem *)(r)); \ ++ break; \ ++ case sizeof(u32): \ ++ writel((u32)(v), (u32 __iomem *)(r)); \ ++ break; \ ++ } \ ++ } while (0) ++ ++#ifdef CONFIG_BCM47XX ++/* ++ * bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder ++ * transactions. As a fix, a read after write is performed on certain places ++ * in the code. Older chips and the newer 5357 family don't require this fix. ++ */ ++#define W_REG_FLUSH(r, v) ({ W_REG((r), (v)); (void)R_REG(r); }) ++#else ++#define W_REG_FLUSH(r, v) W_REG((r), (v)) ++#endif /* CONFIG_BCM47XX */ ++ ++#define AND_REG(r, v) W_REG((r), R_REG(r) & (v)) ++#define OR_REG(r, v) W_REG((r), R_REG(r) | (v)) ++ ++#define SET_REG(r, mask, val) \ ++ W_REG((r), ((R_REG(r) & ~(mask)) | (val))) ++ ++/* multi-bool data type: set of bools, mbool is true if any is set */ ++ ++/* set one bool */ ++#define mboolset(mb, bit) ((mb) |= (bit)) ++/* clear one bool */ ++#define mboolclr(mb, bit) ((mb) &= ~(bit)) ++/* true if one bool is set */ ++#define mboolisset(mb, bit) (((mb) & (bit)) != 0) ++#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val))) ++ ++#define CEIL(x, y) (((x) + ((y)-1)) / (y)) ++ ++/* forward declarations */ ++struct wiphy; ++struct ieee80211_sta; ++struct ieee80211_tx_queue_params; ++struct brcms_info; ++struct brcms_c_info; ++struct brcms_hardware; ++struct brcms_txq_info; ++struct brcms_band; ++struct dma_pub; ++struct si_pub; ++struct tx_status; ++struct d11rxhdr; ++struct txpwr_limits; ++ ++/* iovar structure */ ++struct brcmu_iovar { ++ const char *name; /* name for lookup and display */ ++ u16 varid; /* id for switch */ ++ u16 flags; /* driver-specific flag bits */ ++ u16 type; /* base type of argument */ ++ u16 minlen; /* min length for buffer vars */ ++}; ++ ++/* brcm_msg_level is a bit vector with defs in defs.h */ ++extern u32 brcm_msg_level; ++ ++#endif /* _BRCM_TYPES_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.c.orig 2011-11-09 13:46:58.286800121 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.c 2011-11-09 13:47:17.045565604 -0500 +@@ -0,0 +1,109 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include "types.h" ++#include ++ ++enum { ++ D11UCODE_NAMETAG_START = 0, ++ D11LCN0BSINITVALS24, ++ D11LCN0INITVALS24, ++ D11LCN1BSINITVALS24, ++ D11LCN1INITVALS24, ++ D11LCN2BSINITVALS24, ++ D11LCN2INITVALS24, ++ D11N0ABSINITVALS16, ++ D11N0BSINITVALS16, ++ D11N0INITVALS16, ++ D11UCODE_OVERSIGHT16_MIMO, ++ D11UCODE_OVERSIGHT16_MIMOSZ, ++ D11UCODE_OVERSIGHT24_LCN, ++ D11UCODE_OVERSIGHT24_LCNSZ, ++ D11UCODE_OVERSIGHT_BOMMAJOR, ++ D11UCODE_OVERSIGHT_BOMMINOR ++}; ++ ++int brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode) ++{ ++ int rc; ++ ++ rc = brcms_check_firmwares(wl); ++ ++ rc = rc < 0 ? rc : ++ brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn0bsinitvals24, ++ D11LCN0BSINITVALS24); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn0initvals24, ++ D11LCN0INITVALS24); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn1bsinitvals24, ++ D11LCN1BSINITVALS24); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn1initvals24, ++ D11LCN1INITVALS24); ++ rc = rc < 0 ? rc : ++ brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn2bsinitvals24, ++ D11LCN2BSINITVALS24); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn2initvals24, ++ D11LCN2INITVALS24); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0absinitvals16, ++ D11N0ABSINITVALS16); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0bsinitvals16, ++ D11N0BSINITVALS16); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0initvals16, ++ D11N0INITVALS16); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_16_mimo, ++ D11UCODE_OVERSIGHT16_MIMO); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_uint(wl, &ucode->bcm43xx_16_mimosz, ++ D11UCODE_OVERSIGHT16_MIMOSZ); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_24_lcn, ++ D11UCODE_OVERSIGHT24_LCN); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_uint(wl, &ucode->bcm43xx_24_lcnsz, ++ D11UCODE_OVERSIGHT24_LCNSZ); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_bommajor, ++ D11UCODE_OVERSIGHT_BOMMAJOR); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_bomminor, ++ D11UCODE_OVERSIGHT_BOMMINOR); ++ return rc; ++} ++ ++void brcms_ucode_data_free(struct brcms_ucode *ucode) ++{ ++ brcms_ucode_free_buf((void *)ucode->d11lcn0bsinitvals24); ++ brcms_ucode_free_buf((void *)ucode->d11lcn0initvals24); ++ brcms_ucode_free_buf((void *)ucode->d11lcn1bsinitvals24); ++ brcms_ucode_free_buf((void *)ucode->d11lcn1initvals24); ++ brcms_ucode_free_buf((void *)ucode->d11lcn2bsinitvals24); ++ brcms_ucode_free_buf((void *)ucode->d11lcn2initvals24); ++ brcms_ucode_free_buf((void *)ucode->d11n0absinitvals16); ++ brcms_ucode_free_buf((void *)ucode->d11n0bsinitvals16); ++ brcms_ucode_free_buf((void *)ucode->d11n0initvals16); ++ brcms_ucode_free_buf((void *)ucode->bcm43xx_16_mimo); ++ brcms_ucode_free_buf((void *)ucode->bcm43xx_24_lcn); ++ brcms_ucode_free_buf((void *)ucode->bcm43xx_bommajor); ++ brcms_ucode_free_buf((void *)ucode->bcm43xx_bomminor); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h.orig 2011-11-09 13:46:58.287800109 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h 2011-11-09 13:47:17.046565592 -0500 +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef _BRCM_UCODE_H_ ++#define _BRCM_UCODE_H_ ++ ++#include "types.h" /* forward structure declarations */ ++ ++#define MIN_FW_SIZE 40000 /* minimum firmware file size in bytes */ ++#define MAX_FW_SIZE 150000 ++ ++#define UCODE_LOADER_API_VER 0 ++ ++struct d11init; ++ ++struct brcms_ucode { ++ struct d11init *d11lcn0bsinitvals24; ++ struct d11init *d11lcn0initvals24; ++ struct d11init *d11lcn1bsinitvals24; ++ struct d11init *d11lcn1initvals24; ++ struct d11init *d11lcn2bsinitvals24; ++ struct d11init *d11lcn2initvals24; ++ struct d11init *d11n0absinitvals16; ++ struct d11init *d11n0bsinitvals16; ++ struct d11init *d11n0initvals16; ++ __le32 *bcm43xx_16_mimo; ++ size_t bcm43xx_16_mimosz; ++ __le32 *bcm43xx_24_lcn; ++ size_t bcm43xx_24_lcnsz; ++ u32 *bcm43xx_bommajor; ++ u32 *bcm43xx_bomminor; ++}; ++ ++extern int ++brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode); ++ ++extern void brcms_ucode_data_free(struct brcms_ucode *ucode); ++ ++extern int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, ++ unsigned int idx); ++extern int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, ++ unsigned int idx); ++extern void brcms_ucode_free_buf(void *); ++extern int brcms_check_firmwares(struct brcms_info *wl); ++ ++#endif /* _BRCM_UCODE_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/Makefile.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/Makefile +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/Makefile.orig 2011-11-09 13:46:58.287800109 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/Makefile 2011-11-09 13:47:17.046565592 -0500 +@@ -0,0 +1,28 @@ ++# ++# Makefile fragment for Broadcom 802.11n Networking Device Driver Utilities ++# ++# Copyright (c) 2011 Broadcom Corporation ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ccflags-y := \ ++ -Idrivers/net/wireless/brcm80211/brcmutil \ ++ -Idrivers/net/wireless/brcm80211/include ++ ++BRCMUTIL_OFILES := \ ++ utils.o ++ ++MODULEPFX := brcmutil ++ ++obj-$(CONFIG_BRCMUTIL) += $(MODULEPFX).o ++$(MODULEPFX)-objs = $(BRCMUTIL_OFILES) +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/utils.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/utils.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/utils.c.orig 2011-11-09 13:46:58.287800109 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/utils.c 2011-11-09 13:47:17.046565592 -0500 +@@ -0,0 +1,386 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver utilities."); ++MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards"); ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++struct sk_buff *brcmu_pkt_buf_get_skb(uint len) ++{ ++ struct sk_buff *skb; ++ ++ skb = dev_alloc_skb(len); ++ if (skb) { ++ skb_put(skb, len); ++ skb->priority = 0; ++ } ++ ++ return skb; ++} ++EXPORT_SYMBOL(brcmu_pkt_buf_get_skb); ++ ++/* Free the driver packet. Free the tag if present */ ++void brcmu_pkt_buf_free_skb(struct sk_buff *skb) ++{ ++ struct sk_buff *nskb; ++ int nest = 0; ++ ++ /* perversion: we use skb->next to chain multi-skb packets */ ++ while (skb) { ++ nskb = skb->next; ++ skb->next = NULL; ++ ++ if (skb->destructor) ++ /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if ++ * destructor exists ++ */ ++ dev_kfree_skb_any(skb); ++ else ++ /* can free immediately (even in_irq()) if destructor ++ * does not exist ++ */ ++ dev_kfree_skb(skb); ++ ++ nest++; ++ skb = nskb; ++ } ++} ++EXPORT_SYMBOL(brcmu_pkt_buf_free_skb); ++ ++ ++/* copy a buffer into a pkt buffer chain */ ++uint brcmu_pktfrombuf(struct sk_buff *p, uint offset, int len, ++ unsigned char *buf) ++{ ++ uint n, ret = 0; ++ ++ /* skip 'offset' bytes */ ++ for (; p && offset; p = p->next) { ++ if (offset < (uint) (p->len)) ++ break; ++ offset -= p->len; ++ } ++ ++ if (!p) ++ return 0; ++ ++ /* copy the data */ ++ for (; p && len; p = p->next) { ++ n = min((uint) (p->len) - offset, (uint) len); ++ memcpy(p->data + offset, buf, n); ++ buf += n; ++ len -= n; ++ ret += n; ++ offset = 0; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL(brcmu_pktfrombuf); ++ ++/* return total length of buffer chain */ ++uint brcmu_pkttotlen(struct sk_buff *p) ++{ ++ uint total; ++ ++ total = 0; ++ for (; p; p = p->next) ++ total += p->len; ++ return total; ++} ++EXPORT_SYMBOL(brcmu_pkttotlen); ++ ++/* ++ * osl multiple-precedence packet queue ++ * hi_prec is always >= the number of the highest non-empty precedence ++ */ ++struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec, ++ struct sk_buff *p) ++{ ++ struct pktq_prec *q; ++ ++ if (pktq_full(pq) || pktq_pfull(pq, prec)) ++ return NULL; ++ ++ q = &pq->q[prec]; ++ ++ if (q->head) ++ q->tail->prev = p; ++ else ++ q->head = p; ++ ++ q->tail = p; ++ q->len++; ++ ++ pq->len++; ++ ++ if (pq->hi_prec < prec) ++ pq->hi_prec = (u8) prec; ++ ++ return p; ++} ++EXPORT_SYMBOL(brcmu_pktq_penq); ++ ++struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec, ++ struct sk_buff *p) ++{ ++ struct pktq_prec *q; ++ ++ if (pktq_full(pq) || pktq_pfull(pq, prec)) ++ return NULL; ++ ++ q = &pq->q[prec]; ++ ++ if (q->head == NULL) ++ q->tail = p; ++ ++ p->prev = q->head; ++ q->head = p; ++ q->len++; ++ ++ pq->len++; ++ ++ if (pq->hi_prec < prec) ++ pq->hi_prec = (u8) prec; ++ ++ return p; ++} ++EXPORT_SYMBOL(brcmu_pktq_penq_head); ++ ++struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec) ++{ ++ struct pktq_prec *q; ++ struct sk_buff *p; ++ ++ q = &pq->q[prec]; ++ ++ p = q->head; ++ if (p == NULL) ++ return NULL; ++ ++ q->head = p->prev; ++ if (q->head == NULL) ++ q->tail = NULL; ++ ++ q->len--; ++ ++ pq->len--; ++ ++ p->prev = NULL; ++ ++ return p; ++} ++EXPORT_SYMBOL(brcmu_pktq_pdeq); ++ ++struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec) ++{ ++ struct pktq_prec *q; ++ struct sk_buff *p, *prev; ++ ++ q = &pq->q[prec]; ++ ++ p = q->head; ++ if (p == NULL) ++ return NULL; ++ ++ for (prev = NULL; p != q->tail; p = p->prev) ++ prev = p; ++ ++ if (prev) ++ prev->prev = NULL; ++ else ++ q->head = NULL; ++ ++ q->tail = prev; ++ q->len--; ++ ++ pq->len--; ++ ++ return p; ++} ++EXPORT_SYMBOL(brcmu_pktq_pdeq_tail); ++ ++void ++brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir, ++ bool (*fn)(struct sk_buff *, void *), void *arg) ++{ ++ struct pktq_prec *q; ++ struct sk_buff *p, *prev = NULL; ++ ++ q = &pq->q[prec]; ++ p = q->head; ++ while (p) { ++ if (fn == NULL || (*fn) (p, arg)) { ++ bool head = (p == q->head); ++ if (head) ++ q->head = p->prev; ++ else ++ prev->prev = p->prev; ++ p->prev = NULL; ++ brcmu_pkt_buf_free_skb(p); ++ q->len--; ++ pq->len--; ++ p = (head ? q->head : prev->prev); ++ } else { ++ prev = p; ++ p = p->prev; ++ } ++ } ++ ++ if (q->head == NULL) ++ q->tail = NULL; ++} ++EXPORT_SYMBOL(brcmu_pktq_pflush); ++ ++void brcmu_pktq_flush(struct pktq *pq, bool dir, ++ bool (*fn)(struct sk_buff *, void *), void *arg) ++{ ++ int prec; ++ for (prec = 0; prec < pq->num_prec; prec++) ++ brcmu_pktq_pflush(pq, prec, dir, fn, arg); ++} ++EXPORT_SYMBOL(brcmu_pktq_flush); ++ ++void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len) ++{ ++ int prec; ++ ++ /* pq is variable size; only zero out what's requested */ ++ memset(pq, 0, ++ offsetof(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec)); ++ ++ pq->num_prec = (u16) num_prec; ++ ++ pq->max = (u16) max_len; ++ ++ for (prec = 0; prec < num_prec; prec++) ++ pq->q[prec].max = pq->max; ++} ++EXPORT_SYMBOL(brcmu_pktq_init); ++ ++struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out) ++{ ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ for (prec = 0; prec < pq->hi_prec; prec++) ++ if (pq->q[prec].head) ++ break; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ return pq->q[prec].tail; ++} ++EXPORT_SYMBOL(brcmu_pktq_peek_tail); ++ ++/* Return sum of lengths of a specific set of precedences */ ++int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp) ++{ ++ int prec, len; ++ ++ len = 0; ++ ++ for (prec = 0; prec <= pq->hi_prec; prec++) ++ if (prec_bmp & (1 << prec)) ++ len += pq->q[prec].len; ++ ++ return len; ++} ++EXPORT_SYMBOL(brcmu_pktq_mlen); ++ ++/* Priority dequeue from a specific set of precedences */ ++struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, ++ int *prec_out) ++{ ++ struct pktq_prec *q; ++ struct sk_buff *p; ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) ++ if (prec-- == 0) ++ return NULL; ++ ++ q = &pq->q[prec]; ++ ++ p = q->head; ++ if (p == NULL) ++ return NULL; ++ ++ q->head = p->prev; ++ if (q->head == NULL) ++ q->tail = NULL; ++ ++ q->len--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ pq->len--; ++ ++ p->prev = NULL; ++ ++ return p; ++} ++EXPORT_SYMBOL(brcmu_pktq_mdeq); ++ ++#if defined(BCMDBG) ++/* pretty hex print a pkt buffer chain */ ++void brcmu_prpkt(const char *msg, struct sk_buff *p0) ++{ ++ struct sk_buff *p; ++ ++ if (msg && (msg[0] != '\0')) ++ printk(KERN_DEBUG "%s:\n", msg); ++ ++ for (p = p0; p; p = p->next) ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, p->data, p->len); ++} ++EXPORT_SYMBOL(brcmu_prpkt); ++#endif /* defined(BCMDBG) */ ++ ++#if defined(BCMDBG) ++/* ++ * print bytes formatted as hex to a string. return the resulting ++ * string length ++ */ ++int brcmu_format_hex(char *str, const void *bytes, int len) ++{ ++ int i; ++ char *p = str; ++ const u8 *src = (const u8 *)bytes; ++ ++ for (i = 0; i < len; i++) { ++ p += snprintf(p, 3, "%02X", *src); ++ src++; ++ } ++ return (int)(p - str); ++} ++EXPORT_SYMBOL(brcmu_format_hex); ++#endif /* defined(BCMDBG) */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h.orig 2011-11-09 13:46:58.287800109 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h 2011-11-09 13:47:17.046565592 -0500 +@@ -0,0 +1,59 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_HW_IDS_H_ ++#define _BRCM_HW_IDS_H_ ++ ++#define BCM4325_D11DUAL_ID 0x431b ++#define BCM4325_D11G_ID 0x431c ++#define BCM4325_D11A_ID 0x431d ++ ++#define BCM4329_D11N2G_ID 0x432f /* 4329 802.11n 2.4G device */ ++#define BCM4329_D11N5G_ID 0x4330 /* 4329 802.11n 5G device */ ++#define BCM4329_D11NDUAL_ID 0x432e ++ ++#define BCM4319_D11N_ID 0x4337 /* 4319 802.11n dualband device */ ++#define BCM4319_D11N2G_ID 0x4338 /* 4319 802.11n 2.4G device */ ++#define BCM4319_D11N5G_ID 0x4339 /* 4319 802.11n 5G device */ ++ ++#define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */ ++#define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db */ ++ ++#define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */ ++ ++#define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */ ++#define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */ ++ ++#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ ++ ++/* Chip IDs */ ++#define BCM4313_CHIP_ID 0x4313 /* 4313 chip id */ ++#define BCM4319_CHIP_ID 0x4319 /* 4319 chip id */ ++ ++#define BCM43224_CHIP_ID 43224 /* 43224 chipcommon chipid */ ++#define BCM43225_CHIP_ID 43225 /* 43225 chipcommon chipid */ ++#define BCM43421_CHIP_ID 43421 /* 43421 chipcommon chipid */ ++#define BCM43235_CHIP_ID 43235 /* 43235 chipcommon chipid */ ++#define BCM43236_CHIP_ID 43236 /* 43236 chipcommon chipid */ ++#define BCM43238_CHIP_ID 43238 /* 43238 chipcommon chipid */ ++#define BCM4329_CHIP_ID 0x4329 /* 4329 chipcommon chipid */ ++#define BCM4325_CHIP_ID 0x4325 /* 4325 chipcommon chipid */ ++#define BCM4331_CHIP_ID 0x4331 /* 4331 chipcommon chipid */ ++#define BCM4336_CHIP_ID 0x4336 /* 4336 chipcommon chipid */ ++#define BCM4330_CHIP_ID 0x4330 /* 4330 chipcommon chipid */ ++#define BCM6362_CHIP_ID 0x6362 /* 6362 chipcommon chipid */ ++ ++#endif /* _BRCM_HW_IDS_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_utils.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_utils.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_utils.h.orig 2011-11-09 13:46:58.288800096 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_utils.h 2011-11-09 13:47:17.047565580 -0500 +@@ -0,0 +1,195 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCMU_UTILS_H_ ++#define _BRCMU_UTILS_H_ ++ ++#include ++ ++/* ++ * Spin at most 'us' microseconds while 'exp' is true. ++ * Caller should explicitly test 'exp' when this completes ++ * and take appropriate error action if 'exp' is still true. ++ */ ++#define SPINWAIT(exp, us) { \ ++ uint countdown = (us) + 9; \ ++ while ((exp) && (countdown >= 10)) {\ ++ udelay(10); \ ++ countdown -= 10; \ ++ } \ ++} ++ ++/* osl multi-precedence packet queue */ ++#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */ ++#define PKTQ_MAX_PREC 16 /* Maximum precedence levels */ ++ ++#define BCME_STRLEN 64 /* Max string length for BCM errors */ ++ ++/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */ ++#define PKTBUFSZ 2048 ++ ++#ifndef setbit ++#ifndef NBBY /* the BSD family defines NBBY */ ++#define NBBY 8 /* 8 bits per byte */ ++#endif /* #ifndef NBBY */ ++#define setbit(a, i) (((u8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY)) ++#define clrbit(a, i) (((u8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) ++#define isset(a, i) (((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) ++#define isclr(a, i) ((((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) ++#endif /* setbit */ ++ ++#define NBITS(type) (sizeof(type) * 8) ++#define NBITVAL(nbits) (1 << (nbits)) ++#define MAXBITVAL(nbits) ((1 << (nbits)) - 1) ++#define NBITMASK(nbits) MAXBITVAL(nbits) ++#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8) ++ ++/* crc defines */ ++#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */ ++#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */ ++ ++/* 18-bytes of Ethernet address buffer length */ ++#define ETHER_ADDR_STR_LEN 18 ++ ++struct pktq_prec { ++ struct sk_buff *head; /* first packet to dequeue */ ++ struct sk_buff *tail; /* last packet to dequeue */ ++ u16 len; /* number of queued packets */ ++ u16 max; /* maximum number of queued packets */ ++}; ++ ++/* multi-priority pkt queue */ ++struct pktq { ++ u16 num_prec; /* number of precedences in use */ ++ u16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */ ++ u16 max; /* total max packets */ ++ u16 len; /* total number of packets */ ++ /* ++ * q array must be last since # of elements can be either ++ * PKTQ_MAX_PREC or 1 ++ */ ++ struct pktq_prec q[PKTQ_MAX_PREC]; ++}; ++ ++/* operations on a specific precedence in packet queue */ ++ ++static inline int pktq_plen(struct pktq *pq, int prec) ++{ ++ return pq->q[prec].len; ++} ++ ++static inline int pktq_pavail(struct pktq *pq, int prec) ++{ ++ return pq->q[prec].max - pq->q[prec].len; ++} ++ ++static inline bool pktq_pfull(struct pktq *pq, int prec) ++{ ++ return pq->q[prec].len >= pq->q[prec].max; ++} ++ ++static inline bool pktq_pempty(struct pktq *pq, int prec) ++{ ++ return pq->q[prec].len == 0; ++} ++ ++static inline struct sk_buff *pktq_ppeek(struct pktq *pq, int prec) ++{ ++ return pq->q[prec].head; ++} ++ ++static inline struct sk_buff *pktq_ppeek_tail(struct pktq *pq, int prec) ++{ ++ return pq->q[prec].tail; ++} ++ ++extern struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec, ++ struct sk_buff *p); ++extern struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec, ++ struct sk_buff *p); ++extern struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec); ++extern struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec); ++ ++/* packet primitives */ ++extern struct sk_buff *brcmu_pkt_buf_get_skb(uint len); ++extern void brcmu_pkt_buf_free_skb(struct sk_buff *skb); ++ ++/* Empty the queue at particular precedence level */ ++/* callback function fn(pkt, arg) returns true if pkt belongs to if */ ++extern void brcmu_pktq_pflush(struct pktq *pq, int prec, ++ bool dir, bool (*fn)(struct sk_buff *, void *), void *arg); ++ ++/* operations on a set of precedences in packet queue */ ++ ++extern int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp); ++extern struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, ++ int *prec_out); ++ ++/* operations on packet queue as a whole */ ++ ++static inline int pktq_len(struct pktq *pq) ++{ ++ return (int)pq->len; ++} ++ ++static inline int pktq_max(struct pktq *pq) ++{ ++ return (int)pq->max; ++} ++ ++static inline int pktq_avail(struct pktq *pq) ++{ ++ return (int)(pq->max - pq->len); ++} ++ ++static inline bool pktq_full(struct pktq *pq) ++{ ++ return pq->len >= pq->max; ++} ++ ++static inline bool pktq_empty(struct pktq *pq) ++{ ++ return pq->len == 0; ++} ++ ++extern void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len); ++/* prec_out may be NULL if caller is not interested in return value */ ++extern struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out); ++extern void brcmu_pktq_flush(struct pktq *pq, bool dir, ++ bool (*fn)(struct sk_buff *, void *), void *arg); ++ ++/* externs */ ++/* packet */ ++extern uint brcmu_pktfrombuf(struct sk_buff *p, ++ uint offset, int len, unsigned char *buf); ++extern uint brcmu_pkttotlen(struct sk_buff *p); ++ ++/* ip address */ ++struct ipv4_addr; ++ ++#ifdef BCMDBG ++extern void brcmu_prpkt(const char *msg, struct sk_buff *p0); ++#else ++#define brcmu_prpkt(a, b) ++#endif /* BCMDBG */ ++ ++/* externs */ ++/* format/print */ ++#if defined(BCMDBG) ++extern int brcmu_format_hex(char *str, const void *bytes, int len); ++#endif ++ ++#endif /* _BRCMU_UTILS_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_wifi.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_wifi.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_wifi.h.orig 2011-11-09 13:46:58.288800096 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_wifi.h 2011-11-09 13:47:17.047565580 -0500 +@@ -0,0 +1,239 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCMU_WIFI_H_ ++#define _BRCMU_WIFI_H_ ++ ++#include /* for ETH_ALEN */ ++#include /* for WLAN_PMKID_LEN */ ++ ++/* ++ * A chanspec (u16) holds the channel number, band, bandwidth and control ++ * sideband ++ */ ++ ++/* channel defines */ ++#define CH_UPPER_SB 0x01 ++#define CH_LOWER_SB 0x02 ++#define CH_EWA_VALID 0x04 ++#define CH_20MHZ_APART 4 ++#define CH_10MHZ_APART 2 ++#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ ++#define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ ++#define BRCM_MAX_2G_CHANNEL CH_MAX_2G_CHANNEL /* legacy define */ ++ ++/* bandstate array indices */ ++#define BAND_2G_INDEX 0 /* wlc->bandstate[x] index */ ++#define BAND_5G_INDEX 1 /* wlc->bandstate[x] index */ ++ ++/* ++ * max # supported channels. The max channel no is 216, this is that + 1 ++ * rounded up to a multiple of NBBY (8). DO NOT MAKE it > 255: channels are ++ * u8's all over ++*/ ++#define MAXCHANNEL 224 ++ ++#define WL_CHANSPEC_CHAN_MASK 0x00ff ++#define WL_CHANSPEC_CHAN_SHIFT 0 ++ ++#define WL_CHANSPEC_CTL_SB_MASK 0x0300 ++#define WL_CHANSPEC_CTL_SB_SHIFT 8 ++#define WL_CHANSPEC_CTL_SB_LOWER 0x0100 ++#define WL_CHANSPEC_CTL_SB_UPPER 0x0200 ++#define WL_CHANSPEC_CTL_SB_NONE 0x0300 ++ ++#define WL_CHANSPEC_BW_MASK 0x0C00 ++#define WL_CHANSPEC_BW_SHIFT 10 ++#define WL_CHANSPEC_BW_10 0x0400 ++#define WL_CHANSPEC_BW_20 0x0800 ++#define WL_CHANSPEC_BW_40 0x0C00 ++ ++#define WL_CHANSPEC_BAND_MASK 0xf000 ++#define WL_CHANSPEC_BAND_SHIFT 12 ++#define WL_CHANSPEC_BAND_5G 0x1000 ++#define WL_CHANSPEC_BAND_2G 0x2000 ++#define INVCHANSPEC 255 ++ ++/* used to calculate the chan_freq = chan_factor * 500Mhz + 5 * chan_number */ ++#define WF_CHAN_FACTOR_2_4_G 4814 /* 2.4 GHz band, 2407 MHz */ ++#define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */ ++#define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */ ++ ++#define CHSPEC_CHANNEL(chspec) ((u8)((chspec) & WL_CHANSPEC_CHAN_MASK)) ++#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) ++ ++#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) ++#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) ++ ++#define CHSPEC_IS10(chspec) \ ++ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) ++ ++#define CHSPEC_IS20(chspec) \ ++ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) ++ ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) \ ++ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) ++#endif ++ ++#define CHSPEC_IS5G(chspec) \ ++ (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) ++ ++#define CHSPEC_IS2G(chspec) \ ++ (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) ++ ++#define CHSPEC_SB_NONE(chspec) \ ++ (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE) ++ ++#define CHSPEC_SB_UPPER(chspec) \ ++ (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) ++ ++#define CHSPEC_SB_LOWER(chspec) \ ++ (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) ++ ++#define CHSPEC_CTL_CHAN(chspec) \ ++ ((CHSPEC_SB_LOWER(chspec)) ? \ ++ (lower_20_sb(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \ ++ (upper_20_sb(((chspec) & WL_CHANSPEC_CHAN_MASK)))) ++ ++#define CHSPEC2BAND(chspec) (CHSPEC_IS5G(chspec) ? BRCM_BAND_5G : BRCM_BAND_2G) ++ ++#define CHANSPEC_STR_LEN 8 ++ ++static inline int lower_20_sb(int channel) ++{ ++ return channel > CH_10MHZ_APART ? (channel - CH_10MHZ_APART) : 0; ++} ++ ++static inline int upper_20_sb(int channel) ++{ ++ return (channel < (MAXCHANNEL - CH_10MHZ_APART)) ? ++ channel + CH_10MHZ_APART : 0; ++} ++ ++static inline int chspec_bandunit(u16 chspec) ++{ ++ return CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX; ++} ++ ++static inline u16 ch20mhz_chspec(int channel) ++{ ++ u16 rc = channel <= CH_MAX_2G_CHANNEL ? ++ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G; ++ ++ return (u16)((u16)channel | WL_CHANSPEC_BW_20 | ++ WL_CHANSPEC_CTL_SB_NONE | rc); ++} ++ ++static inline int next_20mhz_chan(int channel) ++{ ++ return channel < (MAXCHANNEL - CH_20MHZ_APART) ? ++ channel + CH_20MHZ_APART : 0; ++} ++ ++/* defined rate in 500kbps */ ++#define BRCM_MAXRATE 108 /* in 500kbps units */ ++#define BRCM_RATE_1M 2 /* in 500kbps units */ ++#define BRCM_RATE_2M 4 /* in 500kbps units */ ++#define BRCM_RATE_5M5 11 /* in 500kbps units */ ++#define BRCM_RATE_11M 22 /* in 500kbps units */ ++#define BRCM_RATE_6M 12 /* in 500kbps units */ ++#define BRCM_RATE_9M 18 /* in 500kbps units */ ++#define BRCM_RATE_12M 24 /* in 500kbps units */ ++#define BRCM_RATE_18M 36 /* in 500kbps units */ ++#define BRCM_RATE_24M 48 /* in 500kbps units */ ++#define BRCM_RATE_36M 72 /* in 500kbps units */ ++#define BRCM_RATE_48M 96 /* in 500kbps units */ ++#define BRCM_RATE_54M 108 /* in 500kbps units */ ++ ++#define BRCM_2G_25MHZ_OFFSET 5 /* 2.4GHz band channel offset */ ++ ++#define MCSSET_LEN 16 ++ ++static inline bool ac_bitmap_tst(u8 bitmap, int prec) ++{ ++ return (bitmap & (1 << (prec))) != 0; ++} ++ ++/* Enumerate crypto algorithms */ ++#define CRYPTO_ALGO_OFF 0 ++#define CRYPTO_ALGO_WEP1 1 ++#define CRYPTO_ALGO_TKIP 2 ++#define CRYPTO_ALGO_WEP128 3 ++#define CRYPTO_ALGO_AES_CCM 4 ++#define CRYPTO_ALGO_AES_RESERVED1 5 ++#define CRYPTO_ALGO_AES_RESERVED2 6 ++#define CRYPTO_ALGO_NALG 7 ++ ++/* wireless security bitvec */ ++ ++#define WEP_ENABLED 0x0001 ++#define TKIP_ENABLED 0x0002 ++#define AES_ENABLED 0x0004 ++#define WSEC_SWFLAG 0x0008 ++/* to go into transition mode without setting wep */ ++#define SES_OW_ENABLED 0x0040 ++ ++/* WPA authentication mode bitvec */ ++#define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */ ++#define WPA_AUTH_NONE 0x0001 /* none (IBSS) */ ++#define WPA_AUTH_UNSPECIFIED 0x0002 /* over 802.1x */ ++#define WPA_AUTH_PSK 0x0004 /* Pre-shared key */ ++#define WPA_AUTH_RESERVED1 0x0008 ++#define WPA_AUTH_RESERVED2 0x0010 ++ ++#define WPA2_AUTH_RESERVED1 0x0020 ++#define WPA2_AUTH_UNSPECIFIED 0x0040 /* over 802.1x */ ++#define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */ ++#define WPA2_AUTH_RESERVED3 0x0200 ++#define WPA2_AUTH_RESERVED4 0x0400 ++#define WPA2_AUTH_RESERVED5 0x0800 ++ ++/* pmkid */ ++#define MAXPMKID 16 ++ ++#define DOT11_DEFAULT_RTS_LEN 2347 ++#define DOT11_DEFAULT_FRAG_LEN 2346 ++ ++#define DOT11_ICV_AES_LEN 8 ++#define DOT11_QOS_LEN 2 ++#define DOT11_IV_MAX_LEN 8 ++#define DOT11_A4_HDR_LEN 30 ++ ++#define HT_CAP_RX_STBC_NO 0x0 ++#define HT_CAP_RX_STBC_ONE_STREAM 0x1 ++ ++struct pmkid { ++ u8 BSSID[ETH_ALEN]; ++ u8 PMKID[WLAN_PMKID_LEN]; ++}; ++ ++struct pmkid_list { ++ __le32 npmkid; ++ struct pmkid pmkid[1]; ++}; ++ ++struct pmkid_cand { ++ u8 BSSID[ETH_ALEN]; ++ u8 preauth; ++}; ++ ++struct pmkid_cand_list { ++ u32 npmkid_cand; ++ struct pmkid_cand pmkid_cand[1]; ++}; ++ ++#endif /* _BRCMU_WIFI_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/chipcommon.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/chipcommon.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/chipcommon.h.orig 2011-11-09 13:46:58.288800096 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/chipcommon.h 2011-11-09 13:47:17.047565580 -0500 +@@ -0,0 +1,284 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _SBCHIPC_H ++#define _SBCHIPC_H ++ ++#include "defs.h" /* for PAD macro */ ++ ++struct chipcregs { ++ u32 chipid; /* 0x0 */ ++ u32 capabilities; ++ u32 corecontrol; /* corerev >= 1 */ ++ u32 bist; ++ ++ /* OTP */ ++ u32 otpstatus; /* 0x10, corerev >= 10 */ ++ u32 otpcontrol; ++ u32 otpprog; ++ u32 otplayout; /* corerev >= 23 */ ++ ++ /* Interrupt control */ ++ u32 intstatus; /* 0x20 */ ++ u32 intmask; ++ ++ /* Chip specific regs */ ++ u32 chipcontrol; /* 0x28, rev >= 11 */ ++ u32 chipstatus; /* 0x2c, rev >= 11 */ ++ ++ /* Jtag Master */ ++ u32 jtagcmd; /* 0x30, rev >= 10 */ ++ u32 jtagir; ++ u32 jtagdr; ++ u32 jtagctrl; ++ ++ /* serial flash interface registers */ ++ u32 flashcontrol; /* 0x40 */ ++ u32 flashaddress; ++ u32 flashdata; ++ u32 PAD[1]; ++ ++ /* Silicon backplane configuration broadcast control */ ++ u32 broadcastaddress; /* 0x50 */ ++ u32 broadcastdata; ++ ++ /* gpio - cleared only by power-on-reset */ ++ u32 gpiopullup; /* 0x58, corerev >= 20 */ ++ u32 gpiopulldown; /* 0x5c, corerev >= 20 */ ++ u32 gpioin; /* 0x60 */ ++ u32 gpioout; /* 0x64 */ ++ u32 gpioouten; /* 0x68 */ ++ u32 gpiocontrol; /* 0x6C */ ++ u32 gpiointpolarity; /* 0x70 */ ++ u32 gpiointmask; /* 0x74 */ ++ ++ /* GPIO events corerev >= 11 */ ++ u32 gpioevent; ++ u32 gpioeventintmask; ++ ++ /* Watchdog timer */ ++ u32 watchdog; /* 0x80 */ ++ ++ /* GPIO events corerev >= 11 */ ++ u32 gpioeventintpolarity; ++ ++ /* GPIO based LED powersave registers corerev >= 16 */ ++ u32 gpiotimerval; /* 0x88 */ ++ u32 gpiotimeroutmask; ++ ++ /* clock control */ ++ u32 clockcontrol_n; /* 0x90 */ ++ u32 clockcontrol_sb; /* aka m0 */ ++ u32 clockcontrol_pci; /* aka m1 */ ++ u32 clockcontrol_m2; /* mii/uart/mipsref */ ++ u32 clockcontrol_m3; /* cpu */ ++ u32 clkdiv; /* corerev >= 3 */ ++ u32 gpiodebugsel; /* corerev >= 28 */ ++ u32 capabilities_ext; /* 0xac */ ++ ++ /* pll delay registers (corerev >= 4) */ ++ u32 pll_on_delay; /* 0xb0 */ ++ u32 fref_sel_delay; ++ u32 slow_clk_ctl; /* 5 < corerev < 10 */ ++ u32 PAD; ++ ++ /* Instaclock registers (corerev >= 10) */ ++ u32 system_clk_ctl; /* 0xc0 */ ++ u32 clkstatestretch; ++ u32 PAD[2]; ++ ++ /* Indirect backplane access (corerev >= 22) */ ++ u32 bp_addrlow; /* 0xd0 */ ++ u32 bp_addrhigh; ++ u32 bp_data; ++ u32 PAD; ++ u32 bp_indaccess; ++ u32 PAD[3]; ++ ++ /* More clock dividers (corerev >= 32) */ ++ u32 clkdiv2; ++ u32 PAD[2]; ++ ++ /* In AI chips, pointer to erom */ ++ u32 eromptr; /* 0xfc */ ++ ++ /* ExtBus control registers (corerev >= 3) */ ++ u32 pcmcia_config; /* 0x100 */ ++ u32 pcmcia_memwait; ++ u32 pcmcia_attrwait; ++ u32 pcmcia_iowait; ++ u32 ide_config; ++ u32 ide_memwait; ++ u32 ide_attrwait; ++ u32 ide_iowait; ++ u32 prog_config; ++ u32 prog_waitcount; ++ u32 flash_config; ++ u32 flash_waitcount; ++ u32 SECI_config; /* 0x130 SECI configuration */ ++ u32 PAD[3]; ++ ++ /* Enhanced Coexistence Interface (ECI) registers (corerev >= 21) */ ++ u32 eci_output; /* 0x140 */ ++ u32 eci_control; ++ u32 eci_inputlo; ++ u32 eci_inputmi; ++ u32 eci_inputhi; ++ u32 eci_inputintpolaritylo; ++ u32 eci_inputintpolaritymi; ++ u32 eci_inputintpolarityhi; ++ u32 eci_intmasklo; ++ u32 eci_intmaskmi; ++ u32 eci_intmaskhi; ++ u32 eci_eventlo; ++ u32 eci_eventmi; ++ u32 eci_eventhi; ++ u32 eci_eventmasklo; ++ u32 eci_eventmaskmi; ++ u32 eci_eventmaskhi; ++ u32 PAD[3]; ++ ++ /* SROM interface (corerev >= 32) */ ++ u32 sromcontrol; /* 0x190 */ ++ u32 sromaddress; ++ u32 sromdata; ++ u32 PAD[17]; ++ ++ /* Clock control and hardware workarounds (corerev >= 20) */ ++ u32 clk_ctl_st; /* 0x1e0 */ ++ u32 hw_war; ++ u32 PAD[70]; ++ ++ /* UARTs */ ++ u8 uart0data; /* 0x300 */ ++ u8 uart0imr; ++ u8 uart0fcr; ++ u8 uart0lcr; ++ u8 uart0mcr; ++ u8 uart0lsr; ++ u8 uart0msr; ++ u8 uart0scratch; ++ u8 PAD[248]; /* corerev >= 1 */ ++ ++ u8 uart1data; /* 0x400 */ ++ u8 uart1imr; ++ u8 uart1fcr; ++ u8 uart1lcr; ++ u8 uart1mcr; ++ u8 uart1lsr; ++ u8 uart1msr; ++ u8 uart1scratch; ++ u32 PAD[126]; ++ ++ /* PMU registers (corerev >= 20) */ ++ u32 pmucontrol; /* 0x600 */ ++ u32 pmucapabilities; ++ u32 pmustatus; ++ u32 res_state; ++ u32 res_pending; ++ u32 pmutimer; ++ u32 min_res_mask; ++ u32 max_res_mask; ++ u32 res_table_sel; ++ u32 res_dep_mask; ++ u32 res_updn_timer; ++ u32 res_timer; ++ u32 clkstretch; ++ u32 pmuwatchdog; ++ u32 gpiosel; /* 0x638, rev >= 1 */ ++ u32 gpioenable; /* 0x63c, rev >= 1 */ ++ u32 res_req_timer_sel; ++ u32 res_req_timer; ++ u32 res_req_mask; ++ u32 PAD; ++ u32 chipcontrol_addr; /* 0x650 */ ++ u32 chipcontrol_data; /* 0x654 */ ++ u32 regcontrol_addr; ++ u32 regcontrol_data; ++ u32 pllcontrol_addr; ++ u32 pllcontrol_data; ++ u32 pmustrapopt; /* 0x668, corerev >= 28 */ ++ u32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ ++ u32 PAD[100]; ++ u16 sromotp[768]; ++}; ++ ++/* chipid */ ++#define CID_ID_MASK 0x0000ffff /* Chip Id mask */ ++#define CID_REV_MASK 0x000f0000 /* Chip Revision mask */ ++#define CID_REV_SHIFT 16 /* Chip Revision shift */ ++#define CID_PKG_MASK 0x00f00000 /* Package Option mask */ ++#define CID_PKG_SHIFT 20 /* Package Option shift */ ++#define CID_CC_MASK 0x0f000000 /* CoreCount (corerev >= 4) */ ++#define CID_CC_SHIFT 24 ++#define CID_TYPE_MASK 0xf0000000 /* Chip Type */ ++#define CID_TYPE_SHIFT 28 ++ ++/* capabilities */ ++#define CC_CAP_UARTS_MASK 0x00000003 /* Number of UARTs */ ++#define CC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ ++#define CC_CAP_UCLKSEL 0x00000018 /* UARTs clock select */ ++/* UARTs are driven by internal divided clock */ ++#define CC_CAP_UINTCLK 0x00000008 ++#define CC_CAP_UARTGPIO 0x00000020 /* UARTs own GPIOs 15:12 */ ++#define CC_CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */ ++#define CC_CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */ ++#define CC_CAP_EXTBUS_FULL 0x00000040 /* ExtBus: PCMCIA, IDE & Prog */ ++#define CC_CAP_EXTBUS_PROG 0x00000080 /* ExtBus: ProgIf only */ ++#define CC_CAP_FLASH_MASK 0x00000700 /* Type of flash */ ++#define CC_CAP_PLL_MASK 0x00038000 /* Type of PLL */ ++#define CC_CAP_PWR_CTL 0x00040000 /* Power control */ ++#define CC_CAP_OTPSIZE 0x00380000 /* OTP Size (0 = none) */ ++#define CC_CAP_OTPSIZE_SHIFT 19 /* OTP Size shift */ ++#define CC_CAP_OTPSIZE_BASE 5 /* OTP Size base */ ++#define CC_CAP_JTAGP 0x00400000 /* JTAG Master Present */ ++#define CC_CAP_ROM 0x00800000 /* Internal boot rom active */ ++#define CC_CAP_BKPLN64 0x08000000 /* 64-bit backplane */ ++#define CC_CAP_PMU 0x10000000 /* PMU Present, rev >= 20 */ ++#define CC_CAP_SROM 0x40000000 /* Srom Present, rev >= 32 */ ++/* Nand flash present, rev >= 35 */ ++#define CC_CAP_NFLASH 0x80000000 ++ ++#define CC_CAP2_SECI 0x00000001 /* SECI Present, rev >= 36 */ ++/* GSIO (spi/i2c) present, rev >= 37 */ ++#define CC_CAP2_GSIO 0x00000002 ++ ++/* pmucapabilities */ ++#define PCAP_REV_MASK 0x000000ff ++#define PCAP_RC_MASK 0x00001f00 ++#define PCAP_RC_SHIFT 8 ++#define PCAP_TC_MASK 0x0001e000 ++#define PCAP_TC_SHIFT 13 ++#define PCAP_PC_MASK 0x001e0000 ++#define PCAP_PC_SHIFT 17 ++#define PCAP_VC_MASK 0x01e00000 ++#define PCAP_VC_SHIFT 21 ++#define PCAP_CC_MASK 0x1e000000 ++#define PCAP_CC_SHIFT 25 ++#define PCAP5_PC_MASK 0x003e0000 /* PMU corerev >= 5 */ ++#define PCAP5_PC_SHIFT 17 ++#define PCAP5_VC_MASK 0x07c00000 ++#define PCAP5_VC_SHIFT 22 ++#define PCAP5_CC_MASK 0xf8000000 ++#define PCAP5_CC_SHIFT 27 ++ ++/* ++* Maximum delay for the PMU state transition in us. ++* This is an upper bound intended for spinwaits etc. ++*/ ++#define PMU_MAX_TRANSITION_DLY 15000 ++ ++#endif /* _SBCHIPC_H */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/defs.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/defs.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/defs.h.orig 2011-11-09 13:46:58.288800096 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/defs.h 2011-11-09 13:47:17.047565580 -0500 +@@ -0,0 +1,104 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_DEFS_H_ ++#define _BRCM_DEFS_H_ ++ ++#include ++ ++#define SI_BUS 0 ++#define PCI_BUS 1 ++#define PCMCIA_BUS 2 ++#define SDIO_BUS 3 ++#define JTAG_BUS 4 ++#define USB_BUS 5 ++#define SPI_BUS 6 ++ ++#define OFF 0 ++#define ON 1 /* ON = 1 */ ++#define AUTO (-1) /* Auto = -1 */ ++ ++/* ++ * Priority definitions according 802.1D ++ */ ++#define PRIO_8021D_NONE 2 ++#define PRIO_8021D_BK 1 ++#define PRIO_8021D_BE 0 ++#define PRIO_8021D_EE 3 ++#define PRIO_8021D_CL 4 ++#define PRIO_8021D_VI 5 ++#define PRIO_8021D_VO 6 ++#define PRIO_8021D_NC 7 ++ ++#define MAXPRIO 7 ++#define NUMPRIO (MAXPRIO + 1) ++ ++#define WL_NUMRATES 16 /* max # of rates in a rateset */ ++ ++#define BRCM_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NUL */ ++ ++#define BRCM_SET_CHANNEL 30 ++#define BRCM_SET_SRL 32 ++#define BRCM_SET_LRL 34 ++#define BRCM_SET_BCNPRD 76 ++ ++#define BRCM_GET_CURR_RATESET 114 /* current rateset */ ++#define BRCM_GET_PHYLIST 180 ++ ++/* Bit masks for radio disabled status - returned by WL_GET_RADIO */ ++ ++#define WL_RADIO_SW_DISABLE (1<<0) ++#define WL_RADIO_HW_DISABLE (1<<1) ++#define WL_RADIO_MPC_DISABLE (1<<2) ++/* some countries don't support any channel */ ++#define WL_RADIO_COUNTRY_DISABLE (1<<3) ++ ++/* Override bit for SET_TXPWR. if set, ignore other level limits */ ++#define WL_TXPWR_OVERRIDE (1U<<31) ++ ++/* band types */ ++#define BRCM_BAND_AUTO 0 /* auto-select */ ++#define BRCM_BAND_5G 1 /* 5 Ghz */ ++#define BRCM_BAND_2G 2 /* 2.4 Ghz */ ++#define BRCM_BAND_ALL 3 /* all bands */ ++ ++/* Values for PM */ ++#define PM_OFF 0 ++#define PM_MAX 1 ++ ++/* Message levels */ ++#define LOG_ERROR_VAL 0x00000001 ++#define LOG_TRACE_VAL 0x00000002 ++ ++#define PM_OFF 0 ++#define PM_MAX 1 ++#define PM_FAST 2 ++ ++/* ++ * Sonics Configuration Space Registers. ++ */ ++ ++/* core sbconfig regs are top 256bytes of regs */ ++#define SBCONFIGOFF 0xf00 ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif ++ ++#endif /* _BRCM_DEFS_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/soc.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/soc.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/soc.h.orig 2011-11-09 13:46:58.288800096 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/soc.h 2011-11-09 13:47:17.048565567 -0500 +@@ -0,0 +1,90 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_SOC_H ++#define _BRCM_SOC_H ++ ++#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */ ++ ++/* core codes */ ++#define NODEV_CORE_ID 0x700 /* Invalid coreid */ ++#define CC_CORE_ID 0x800 /* chipcommon core */ ++#define ILINE20_CORE_ID 0x801 /* iline20 core */ ++#define SRAM_CORE_ID 0x802 /* sram core */ ++#define SDRAM_CORE_ID 0x803 /* sdram core */ ++#define PCI_CORE_ID 0x804 /* pci core */ ++#define MIPS_CORE_ID 0x805 /* mips core */ ++#define ENET_CORE_ID 0x806 /* enet mac core */ ++#define CODEC_CORE_ID 0x807 /* v90 codec core */ ++#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */ ++#define ADSL_CORE_ID 0x809 /* ADSL core */ ++#define ILINE100_CORE_ID 0x80a /* iline100 core */ ++#define IPSEC_CORE_ID 0x80b /* ipsec core */ ++#define UTOPIA_CORE_ID 0x80c /* utopia core */ ++#define PCMCIA_CORE_ID 0x80d /* pcmcia core */ ++#define SOCRAM_CORE_ID 0x80e /* internal memory core */ ++#define MEMC_CORE_ID 0x80f /* memc sdram core */ ++#define OFDM_CORE_ID 0x810 /* OFDM phy core */ ++#define EXTIF_CORE_ID 0x811 /* external interface core */ ++#define D11_CORE_ID 0x812 /* 802.11 MAC core */ ++#define APHY_CORE_ID 0x813 /* 802.11a phy core */ ++#define BPHY_CORE_ID 0x814 /* 802.11b phy core */ ++#define GPHY_CORE_ID 0x815 /* 802.11g phy core */ ++#define MIPS33_CORE_ID 0x816 /* mips3302 core */ ++#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */ ++#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */ ++#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */ ++#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */ ++#define SDIOH_CORE_ID 0x81b /* sdio host core */ ++#define ROBO_CORE_ID 0x81c /* roboswitch core */ ++#define ATA100_CORE_ID 0x81d /* parallel ATA core */ ++#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */ ++#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */ ++#define PCIE_CORE_ID 0x820 /* pci express core */ ++#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */ ++#define SRAMC_CORE_ID 0x822 /* SRAM controller core */ ++#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */ ++#define ARM11_CORE_ID 0x824 /* ARM 1176 core */ ++#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */ ++#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */ ++#define PMU_CORE_ID 0x827 /* PMU core */ ++#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */ ++#define SDIOD_CORE_ID 0x829 /* SDIO device core */ ++#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */ ++#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */ ++#define MIPS74K_CORE_ID 0x82c /* mips 74k core */ ++#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */ ++#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */ ++#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */ ++#define SC_CORE_ID 0x831 /* shared common core */ ++#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */ ++#define SPIH_CORE_ID 0x833 /* SPI host core */ ++#define I2S_CORE_ID 0x834 /* I2S core */ ++#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */ ++#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */ ++#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */ ++/* Default component, in ai chips it maps all unused address ranges */ ++#define DEF_AI_COMP 0xfff ++ ++/* Common core control flags */ ++#define SICF_BIST_EN 0x8000 ++#define SICF_PME_EN 0x4000 ++#define SICF_CORE_BITS 0x3ffc ++#define SICF_FGC 0x0002 ++#define SICF_CLOCK_EN 0x0001 ++ ++#endif /* _BRCM_SOC_H */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig 2011-11-09 13:46:58.289800083 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig 2011-11-09 13:47:17.048565567 -0500 +@@ -0,0 +1,35 @@ ++config BRCMUTIL ++ tristate ++ ++config BRCMSMAC ++ tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" ++ depends on PCI ++ depends on MAC80211 ++ depends on BCMA=n ++ select BRCMUTIL ++ select FW_LOADER ++ select CRC_CCITT ++ select CRC8 ++ select CORDIC ++ ---help--- ++ This module adds support for PCIe wireless adapters based on Broadcom ++ IEEE802.11n SoftMAC chipsets. If you choose to build a module, it'll ++ be called brcmsmac.ko. ++ ++config BRCMFMAC ++ tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver" ++ depends on MMC ++ depends on CFG80211 ++ select BRCMUTIL ++ select FW_LOADER ++ ---help--- ++ This module adds support for embedded wireless adapters based on ++ Broadcom IEEE802.11n FullMAC chipsets. This driver uses the kernel's ++ wireless extensions subsystem. If you choose to build a module, ++ it'll be called brcmfmac.ko. ++ ++config BRCMDBG ++ bool "Broadcom driver debug functions" ++ depends on BRCMSMAC || BRCMFMAC ++ ---help--- ++ Selecting this enables additional code for debug purposes. +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/Makefile.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/Makefile +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/Makefile.orig 2011-11-09 13:46:58.289800083 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/Makefile 2011-11-09 13:47:17.048565567 -0500 +@@ -0,0 +1,23 @@ ++# ++# Makefile fragment for Broadcom 802.11n Networking Device Driver ++# ++# Copyright (c) 2010 Broadcom Corporation ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++# common flags ++subdir-ccflags-$(CONFIG_BRCMDBG) += -DBCMDBG ++ ++obj-$(CONFIG_BRCMUTIL) += brcmutil/ ++obj-$(CONFIG_BRCMFMAC) += brcmfmac/ ++obj-$(CONFIG_BRCMSMAC) += brcmsmac/ +diff -up linux-3.1.x86_64/drivers/net/wireless/Kconfig.orig linux-3.1.x86_64/drivers/net/wireless/Kconfig +--- linux-3.1.x86_64/drivers/net/wireless/Kconfig.orig 2011-11-09 13:48:16.411823422 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/Kconfig 2011-11-09 13:48:24.808718444 -0500 +@@ -271,6 +271,7 @@ config MWL8K + source "drivers/net/wireless/ath/Kconfig" + source "drivers/net/wireless/b43/Kconfig" + source "drivers/net/wireless/b43legacy/Kconfig" ++source "drivers/net/wireless/brcm80211/Kconfig" + source "drivers/net/wireless/hostap/Kconfig" + source "drivers/net/wireless/ipw2x00/Kconfig" + source "drivers/net/wireless/iwlwifi/Kconfig" +diff -up linux-3.1.x86_64/drivers/net/wireless/Makefile.orig linux-3.1.x86_64/drivers/net/wireless/Makefile +--- linux-3.1.x86_64/drivers/net/wireless/Makefile.orig 2011-11-09 13:47:55.028090756 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/Makefile 2011-11-09 13:47:49.856155362 -0500 +@@ -58,3 +58,6 @@ obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl + obj-$(CONFIG_IWM) += iwmc3200wifi/ + + obj-$(CONFIG_MWIFIEX) += mwifiex/ ++ ++obj-$(CONFIG_BRCMFMAC) += brcm80211/ ++obj-$(CONFIG_BRCMSMAC) += brcm80211/ diff --git a/config-generic b/config-generic index 39851a235..84800507d 100644 --- a/config-generic +++ b/config-generic @@ -1573,6 +1573,10 @@ CONFIG_RTL8192DE=m CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m +CONFIG_BRCMFMAC=m +CONFIG_BRCMSMAC=m +# CONFIG_BRCMDBG is not set + # # Token Ring devices # @@ -4408,8 +4412,6 @@ CONFIG_USB_ATMEL=m # 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 diff --git a/kernel.spec b/kernel.spec index a96c36874..8b141c37a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -685,6 +685,8 @@ Patch21060: elantech.patch #rhbz 748210 Patch21061: ideapad-Check-if-acpi-already-handle-backlight.patch +#backport brcm80211 from 3.2-rc1 +Patch21090: brcm80211.patch %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1258,6 +1260,9 @@ ApplyPatch elantech.patch #rhbz 748210 ApplyPatch ideapad-Check-if-acpi-already-handle-backlight.patch +#backport brcm80211 from 3.2-rc1 +ApplyPatch brcm80211.patch + # END OF PATCH APPLICATIONS %endif @@ -1878,6 +1883,9 @@ fi # and build. %changelog +* Wed Nov 09 2011 John W. Linville +- Backport brcm80211 from 3.2-rc1 + * Mon Nov 07 2011 Dave Jones - Rebase to 3.1.0 From e6f683f90076eaf0545695fb1551fc7da10660a2 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 9 Nov 2011 20:30:03 -0500 Subject: [PATCH 206/397] Linux 3.1.1-rc1 (Fedora 2.6.41.1-rc1) Comment out merged patches, will drop when release is final: ums-realtek-driver-uses-stack-memory-for-DMA.patch epoll-fix-spurious-lockdep-warnings.patch crypto-register-cryptd-first.patch add-macbookair41-keyboard.patch powerpc-Fix-deadlock-in-icswx-code.patch iwlagn-fix-ht_params-NULL-pointer-dereference.patch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch media-DiBcom-protect-the-I2C-bufer-access.patch media-dib0700-protect-the-dib0700-buffer-access.patch WMI-properly-cleanup-devices-to-avoid-crashes.patch --- config-generic | 3 +- kernel.spec | 40 ++++++++----- sources | 1 + usb-add-quirk-for-logitech-webcams.patch | 71 ++---------------------- 4 files changed, 35 insertions(+), 80 deletions(-) diff --git a/config-generic b/config-generic index 84800507d..b6d99db1f 100644 --- a/config-generic +++ b/config-generic @@ -3105,6 +3105,7 @@ CONFIG_USB_STORAGE_ONETOUCH=m CONFIG_USB_STORAGE_ALAUDA=m CONFIG_USB_STORAGE_KARMA=m CONFIG_USB_STORAGE_REALTEK=m +CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set CONFIG_USB_UAS=m @@ -3158,7 +3159,6 @@ CONFIG_HID_TOPSEED=m CONFIG_HID_THRUSTMASTER=m CONFIG_HID_ZEROPLUS=m CONFIG_HID_ZYDACRON=m -CONFIG_HID_ACRUX_FF=m CONFIG_HID_EMS_FF=m CONFIG_HID_ELECOM=m CONFIG_HID_UCLOGIC=m @@ -3166,6 +3166,7 @@ CONFIG_HID_WALTOP=m CONFIG_HID_ROCCAT_PYRA=m CONFIG_HID_ROCCAT_KONEPLUS=m CONFIG_HID_ACRUX=m +CONFIG_HID_ACRUX_FF=y CONFIG_HID_KEYTOUCH=m CONFIG_HID_LCPOWER=m CONFIG_HID_ROCCAT_ARVO=m diff --git a/kernel.spec b/kernel.spec index 8b141c37a..c06dced9c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 0 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,9 +51,9 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 +%define stable_rc 1 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev .%{stable_update} @@ -1207,14 +1207,14 @@ ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch add-appleir-usb-driver.patch ApplyPatch udlfb-bind-framebuffer-to-interface.patch -ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch -ApplyPatch epoll-fix-spurious-lockdep-warnings.patch +#ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch +#ApplyPatch epoll-fix-spurious-lockdep-warnings.patch ApplyPatch epoll-limit-paths.patch ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch ApplyPatch block-stray-block-put-after-teardown.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch -ApplyPatch crypto-register-cryptd-first.patch +#ApplyPatch crypto-register-cryptd-first.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -1222,19 +1222,19 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch revert-efi-rtclock.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch -ApplyPatch add-macbookair41-keyboard.patch +#ApplyPatch add-macbookair41-keyboard.patch ApplyPatch hvcs_pi_buf_alloc.patch -ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch +#ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch -ApplyPatch iwlagn-fix-ht_params-NULL-pointer-dereference.patch +#ApplyPatch iwlagn-fix-ht_params-NULL-pointer-dereference.patch #rhbz #722509 -ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch +#ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch -ApplyPatch media-DiBcom-protect-the-I2C-bufer-access.patch -ApplyPatch media-dib0700-protect-the-dib0700-buffer-access.patch +#ApplyPatch media-DiBcom-protect-the-I2C-bufer-access.patch +#ApplyPatch media-dib0700-protect-the-dib0700-buffer-access.patch ApplyPatch media-dib0700-correct-error-message.patch # utrace. @@ -1252,7 +1252,7 @@ ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch ApplyPatch oom-fix-integer-overflow-of-points.patch #rhbz 706574 -ApplyPatch WMI-properly-cleanup-devices-to-avoid-crashes.patch +#ApplyPatch WMI-properly-cleanup-devices-to-avoid-crashes.patch #rhbz 728607 ApplyPatch elantech.patch @@ -1883,6 +1883,20 @@ fi # and build. %changelog +* Wed Nov 09 2011 Chuck Ebbert 2.6.41.1-1.rc1 +- Linux 3.1.1-rc1 (Fedora 2.6.41.1-rc1) +- Comment out merged patches, will drop when release is final: + ums-realtek-driver-uses-stack-memory-for-DMA.patch + epoll-fix-spurious-lockdep-warnings.patch + crypto-register-cryptd-first.patch + add-macbookair41-keyboard.patch + powerpc-Fix-deadlock-in-icswx-code.patch + iwlagn-fix-ht_params-NULL-pointer-dereference.patch + mmc-Always-check-for-lower-base-frequency-quirk-for-.patch + media-DiBcom-protect-the-I2C-bufer-access.patch + media-dib0700-protect-the-dib0700-buffer-access.patch + WMI-properly-cleanup-devices-to-avoid-crashes.patch + * Wed Nov 09 2011 John W. Linville - Backport brcm80211 from 3.2-rc1 diff --git a/sources b/sources index 9529d7a05..da0608dfe 100644 --- a/sources +++ b/sources @@ -1 +1,2 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 +0582554c78b9979dc91223e3f4e4ec22 patch-3.1.1-rc1.bz2 diff --git a/usb-add-quirk-for-logitech-webcams.patch b/usb-add-quirk-for-logitech-webcams.patch index 052a27e73..b4c795133 100644 --- a/usb-add-quirk-for-logitech-webcams.patch +++ b/usb-add-quirk-for-logitech-webcams.patch @@ -1,75 +1,14 @@ -From d5446509abd85b6845d91a319a033c5bd17e494d Mon Sep 17 00:00:00 2001 -From: Oliver Neukum -Date: Tue, 13 Sep 2011 08:42:21 +0200 -Subject: [PATCH] USB:add RESET_RESUME for webcams shown to be quirky - -From 6f673c5ef819548b2cbaf7bb607779af6fdbe731 Mon Sep 17 00:00:00 2001 -From: Oliver Neukum -Date: Tue, 30 Aug 2011 15:34:32 +0200 -Subject: [PATCH] USB:add RESET_RESUME for webcams shown to be quirky - -The new runtime PM code has shown that many webcams suffer -from a race condition that may crash them upon resume. -Runtime PM is especially prone to show the problem because -it retains power to the cameras at all times. However -system suspension may also crash the devices and retain -power to the devices. -The only way to solve this problem without races is in -usbcore with the RESET_RESUME quirk. - -Signed-off-by: Oliver Neukum - -Add C300 ID from patch in rhbz #742010 Add C600 ID from rhbz #742010 --- - drivers/usb/core/quirks.c | 27 +++++++++++++++++++++++++++ - 1 files changed, 27 insertions(+), 0 deletions(-) - -diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c -index 81ce6a8..caa1991 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c -@@ -38,6 +38,30 @@ static const struct usb_device_id usb_quirk_list[] = { - /* Creative SB Audigy 2 NX */ - { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, +@@ -38,6 +38,9 @@ static const struct usb_device_id usb_quirk_list[] = { + /* Logitech Webcam B/C500 */ + { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME }, -+ /* Logitech Webcam C200 */ -+ { USB_DEVICE(0x046d, 0x0802), .driver_info = USB_QUIRK_RESET_RESUME }, -+ -+ /* Logitech Webcam C250 */ -+ { USB_DEVICE(0x046d, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, -+ -+ /* Logitech Webcam C300 */ -+ { USB_DEVICE(0x046d, 0x0805), .driver_info = USB_QUIRK_RESET_RESUME }, -+ -+ /* Logitech Webcam B/C500 */ -+ { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME }, -+ + /* Logitech Webcam C600 */ + { USB_DEVICE(0x046d, 0x0808), .driver_info = USB_QUIRK_RESET_RESUME }, + -+ /* Logitech Webcam Pro 9000 */ -+ { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME }, -+ -+ /* Logitech Webcam C310 */ -+ { USB_DEVICE(0x046d, 0x081b), .driver_info = USB_QUIRK_RESET_RESUME }, -+ -+ /* Logitech Webcam C270 */ -+ { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME }, -+ - /* Logitech Harmony 700-series */ - { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, + /* Logitech Webcam Pro 9000 */ + { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME }, -@@ -69,6 +93,9 @@ static const struct usb_device_id usb_quirk_list[] = { - { USB_DEVICE(0x06a3, 0x0006), .driver_info = - USB_QUIRK_CONFIG_INTF_STRINGS }, - -+ /* Guillemot Webcam Hercules Dualpix Exchange*/ -+ { USB_DEVICE(0x06f8, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, -+ - /* M-Systems Flash Disk Pioneers */ - { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, - --- -1.7.6.4 - From 37120dd5396419787c9560bc9858584621a95c8c Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 10 Nov 2011 16:39:05 -0500 Subject: [PATCH 207/397] Sync samsung-laptop driver with what's in 3.2 (rhbz 747560) --- kernel.spec | 11 +- samsung-laptop-brightness-fixes-3.2.patch | 238 ++++++++++++++++++++++ 2 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 samsung-laptop-brightness-fixes-3.2.patch diff --git a/kernel.spec b/kernel.spec index c06dced9c..7cd70d30a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -585,6 +585,9 @@ Patch700: linux-2.6-e1000-ich9-montevina.patch Patch800: linux-2.6-crash-driver.patch +# Platform +Patch900: samsung-laptop-brightness-fixes-3.2.patch + # crypto/ # virt + ksm patches @@ -1199,6 +1202,9 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-fixes.patch ApplyOptionalPatch linux-2.6-v4l-dvb-update.patch ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch +# Platform fixes not sent for -stable +ApplyPatch samsung-laptop-brightness-fixes-3.2.patch + # Patches headed upstream ApplyPatch rcutree-avoid-false-quiescent-states.patch @@ -1883,6 +1889,9 @@ fi # and build. %changelog +* Thu Nov 10 2011 Chuck Ebbert +- Sync samsung-laptop driver with what's in 3.2 (rhbz 747560) + * Wed Nov 09 2011 Chuck Ebbert 2.6.41.1-1.rc1 - Linux 3.1.1-rc1 (Fedora 2.6.41.1-rc1) - Comment out merged patches, will drop when release is final: diff --git a/samsung-laptop-brightness-fixes-3.2.patch b/samsung-laptop-brightness-fixes-3.2.patch new file mode 100644 index 000000000..61032176b --- /dev/null +++ b/samsung-laptop-brightness-fixes-3.2.patch @@ -0,0 +1,238 @@ +From: Jason Stubbs +Date: Tue, 20 Sep 2011 16:16:13 +0000 (-0700) +Subject: Platform: Brightness quirk for samsung laptop driver +X-Git-Tag: v3.2-rc1~111^2~41 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=ac080523141d5bfa5f60ef2436480f645f915e9c + +Platform: Brightness quirk for samsung laptop driver + +On some Samsung laptops the brightness regulation works slightly different. +All SABI commands except for set_brightness work as expected. The behaviour +of set_brightness is as follows: + +- Setting a new brightness will only step one level toward the new brightness + level. For example, setting a level of 5 when the current level is 2 will + result in a brightness level of 3. +- A spurious KEY_BRIGHTNESS_UP or KEY_BRIGHTNESS_DOWN event is also generated + along with the change in brightness. +- Neither of the above two issues occur when changing from/to brightness + level 0. + +This patch adds detection and a non-intrusive workaround for the above issues. + +Signed-off-by: Jason Stubbs +Tested-by: David Herrmann +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Matthew Garrett +--- + +diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c +index 4d3bed4..6474e42 100644 +--- a/drivers/platform/x86/samsung-laptop.c ++++ b/drivers/platform/x86/samsung-laptop.c +@@ -226,6 +226,7 @@ static struct backlight_device *backlight_device; + static struct mutex sabi_mutex; + static struct platform_device *sdev; + static struct rfkill *rfk; ++static bool has_stepping_quirk; + + static int force; + module_param(force, bool, 0); +@@ -382,6 +383,17 @@ static void set_brightness(u8 user_brightness) + { + u8 user_level = user_brightness + sabi_config->min_brightness; + ++ if (has_stepping_quirk && user_level != 0) { ++ /* ++ * short circuit if the specified level is what's already set ++ * to prevent the screen from flickering needlessly ++ */ ++ if (user_brightness == read_brightness()) ++ return; ++ ++ sabi_set_command(sabi_config->commands.set_brightness, 0); ++ } ++ + sabi_set_command(sabi_config->commands.set_brightness, user_level); + } + +@@ -390,6 +402,34 @@ static int get_brightness(struct backlight_device *bd) + return (int)read_brightness(); + } + ++static void check_for_stepping_quirk(void) ++{ ++ u8 initial_level = read_brightness(); ++ u8 check_level; ++ ++ /* ++ * Some laptops exhibit the strange behaviour of stepping toward ++ * (rather than setting) the brightness except when changing to/from ++ * brightness level 0. This behaviour is checked for here and worked ++ * around in set_brightness. ++ */ ++ ++ if (initial_level <= 2) ++ check_level = initial_level + 2; ++ else ++ check_level = initial_level - 2; ++ ++ has_stepping_quirk = false; ++ set_brightness(check_level); ++ ++ if (read_brightness() != check_level) { ++ has_stepping_quirk = true; ++ pr_info("enabled workaround for brightness stepping quirk\n"); ++ } ++ ++ set_brightness(initial_level); ++} ++ + static int update_status(struct backlight_device *bd) + { + set_brightness(bd->props.brightness); +@@ -805,6 +845,9 @@ static int __init samsung_init(void) + } + } + ++ /* Check for stepping quirk */ ++ check_for_stepping_quirk(); ++ + /* knock up a platform device to hang stuff off of */ + sdev = platform_device_register_simple("samsung", -1, NULL, 0); + if (IS_ERR(sdev)) +From: Jason Stubbs +Date: Tue, 20 Sep 2011 16:16:14 +0000 (-0700) +Subject: Platform: Samsung laptop DMI info for NC210/NC110 +X-Git-Tag: v3.2-rc1~111^2~40 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=7b3c257ce4267e004a7c7e68c05d1eb70da8c972 + +Platform: Samsung laptop DMI info for NC210/NC110 + +This patch just adds the DMI info for the samsung laptop driver to work with +the NC210/NC110. It needs the brightness quirk patch for proper support. + +Signed-off-by: Jason Stubbs +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Matthew Garrett +--- + +diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c +index 6474e42..8ffab50 100644 +--- a/drivers/platform/x86/samsung-laptop.c ++++ b/drivers/platform/x86/samsung-laptop.c +@@ -737,6 +737,15 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { + }, + .callback = dmi_check_cb, + }, ++ { ++ .ident = "NC210/NC110", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"), ++ DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"), ++ }, ++ .callback = dmi_check_cb, ++ }, + { }, + }; + MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); +From: Raul Gutierrez Segales +Date: Tue, 20 Sep 2011 16:16:15 +0000 (-0700) +Subject: Platform: fix samsung-laptop DMI identification for N220 model +X-Git-Tag: v3.2-rc1~111^2~39 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=f689c875c13c9d62b3c4de09cd5dad66549f700d + +Platform: fix samsung-laptop DMI identification for N220 model + +This is a follow-up for commit 78a7539b, which didn't cover the +Samsung N220 laptop. With this backlight brightness works nicely +on the N220 netbook. + +Signed-off-by: Raul Gutierrez Segales +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Matthew Garrett +--- + +diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c +index 8ffab50..1e436eb 100644 +--- a/drivers/platform/x86/samsung-laptop.c ++++ b/drivers/platform/x86/samsung-laptop.c +@@ -663,6 +663,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { + .callback = dmi_check_cb, + }, + { ++ .ident = "N220", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, ++ "SAMSUNG ELECTRONICS CO., LTD."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "N220"), ++ DMI_MATCH(DMI_BOARD_NAME, "N220"), ++ }, ++ .callback = dmi_check_cb, ++ }, ++ { + .ident = "N150/N210/N220/N230", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, +From: John Serock +Date: Thu, 13 Oct 2011 10:42:01 +0000 (-0400) +Subject: Platform: Detect samsung laptop quirk when initial level is zero +X-Git-Tag: v3.2-rc1~111^2~29 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=ba05b237372bad82533d1f717569d1d817ff3c27 + +Platform: Detect samsung laptop quirk when initial level is zero + +This patch depends on the "Platform: Brightness quirk for samsung +laptop driver" patch from Jason Stubbs. This patch adds a check for an +initial brightness level of 0; if the level is 0, this patch changes +the brightness level to 1 before the driver attempts to detect the +brightness quirk. + +The Samsung N150 netbook experiences the brightness quirk. Without +Jason's patch, the only brightness levels available on the N150 are 0, +1, and 8. This patch ensures that, when the initial brightness level +is 0, the samsang-laptop driver detects the brightness quirk on the +N150, thereby making brightness levels 0 through 8 available. + +Signed-off-by: John Serock +Acked-by: Jason Stubbs +Signed-off-by: Matthew Garrett +--- + +diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c +index 1e436eb..31ddd57 100644 +--- a/drivers/platform/x86/samsung-laptop.c ++++ b/drivers/platform/x86/samsung-laptop.c +@@ -404,8 +404,9 @@ static int get_brightness(struct backlight_device *bd) + + static void check_for_stepping_quirk(void) + { +- u8 initial_level = read_brightness(); ++ u8 initial_level; + u8 check_level; ++ u8 orig_level = read_brightness(); + + /* + * Some laptops exhibit the strange behaviour of stepping toward +@@ -414,6 +415,11 @@ static void check_for_stepping_quirk(void) + * around in set_brightness. + */ + ++ if (orig_level == 0) ++ set_brightness(1); ++ ++ initial_level = read_brightness(); ++ + if (initial_level <= 2) + check_level = initial_level + 2; + else +@@ -427,7 +433,7 @@ static void check_for_stepping_quirk(void) + pr_info("enabled workaround for brightness stepping quirk\n"); + } + +- set_brightness(initial_level); ++ set_brightness(orig_level); + } + + static int update_status(struct backlight_device *bd) From b480412500f65f8457637f41161c938c3339c865 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 11 Nov 2011 10:03:43 -0500 Subject: [PATCH 208/397] Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 --- bcma-brcmsmac-compat.patch | 35 +++++++++++++++++++++++++++++++++++ config-generic | 7 ++++++- kernel.spec | 7 +++++++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 bcma-brcmsmac-compat.patch diff --git a/bcma-brcmsmac-compat.patch b/bcma-brcmsmac-compat.patch new file mode 100644 index 000000000..e16e5b0c5 --- /dev/null +++ b/bcma-brcmsmac-compat.patch @@ -0,0 +1,35 @@ +Simple patch to remove the overlap between the bcma (i.e. b43) driver +and the brcmsmac driver. David Woodhouse +confirmed that this patch restores functionality of bcm4331 devices. + +-- John W. Linville + +diff -up linux-3.1.x86_64/drivers/bcma/host_pci.c.orig linux-3.1.x86_64/drivers/bcma/host_pci.c +--- linux-3.1.x86_64/drivers/bcma/host_pci.c.orig 2011-11-10 11:41:26.829742757 -0500 ++++ linux-3.1.x86_64/drivers/bcma/host_pci.c 2011-11-10 11:41:22.884792078 -0500 +@@ -225,11 +225,13 @@ static void bcma_host_pci_remove(struct + } + + static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { +- { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, ++#if 0 /* Not in Fedora... */ ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, ++#endif + { 0, }, + }; + MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl); +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig 2011-11-10 11:42:31.764930961 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig 2011-11-10 11:42:33.613907846 -0500 +@@ -5,7 +5,6 @@ config BRCMSMAC + tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" + depends on PCI + depends on MAC80211 +- depends on BCMA=n + select BRCMUTIL + select FW_LOADER + select CRC_CCITT diff --git a/config-generic b/config-generic index b6d99db1f..162e67041 100644 --- a/config-generic +++ b/config-generic @@ -1462,6 +1462,7 @@ CONFIG_B43=m CONFIG_B43_PCMCIA=y CONFIG_B43_SDIO=y CONFIG_B43_BCMA=y +CONFIG_B43_BCMA_PIO=y # CONFIG_B43_DEBUG is not set CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y @@ -4588,7 +4589,11 @@ CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 CONFIG_TEST_KSTRTOX=m -# CONFIG_BCMA is not set +CONFIG_BCMA=m +CONFIG_BCMA_BLOCKIO=y +CONFIG_BCMA_HOST_PCI_POSSIBLE=y +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/kernel.spec b/kernel.spec index 7cd70d30a..c4ec2def7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -690,6 +690,8 @@ Patch21061: ideapad-Check-if-acpi-already-handle-backlight.patch #backport brcm80211 from 3.2-rc1 Patch21090: brcm80211.patch +Patch21091: bcma-brcmsmac-compat.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1268,6 +1270,8 @@ ApplyPatch ideapad-Check-if-acpi-already-handle-backlight.patch #backport brcm80211 from 3.2-rc1 ApplyPatch brcm80211.patch +# Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 +ApplyPatch bcma-brcmsmac-compat.patch # END OF PATCH APPLICATIONS @@ -1889,6 +1893,9 @@ fi # and build. %changelog +* Fri Nov 11 2011 John W. Linville +- Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 + * Thu Nov 10 2011 Chuck Ebbert - Sync samsung-laptop driver with what's in 3.2 (rhbz 747560) From 8ee8a6ff8cf78a1caa25856a1f5d6b91fd3a107a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 11 Nov 2011 16:21:20 -0500 Subject: [PATCH 209/397] Linux 3.1.1 (2.6.41.1) --- ...rly-cleanup-devices-to-avoid-crashes.patch | 41 - add-macbookair41-keyboard.patch | 119 -- crypto-register-cryptd-first.patch | 26 - epoll-fix-spurious-lockdep-warnings.patch | 116 -- ...x-ht_params-NULL-pointer-dereference.patch | 43 - kernel.spec | 42 +- ...-DiBcom-protect-the-I2C-bufer-access.patch | 1150 ----------------- ...00-protect-the-dib0700-buffer-access.patch | 248 ---- ...-for-lower-base-frequency-quirk-for-.patch | 73 -- powerpc-Fix-deadlock-in-icswx-code.patch | 74 -- sources | 2 +- ...tek-driver-uses-stack-memory-for-DMA.patch | 143 -- 12 files changed, 6 insertions(+), 2071 deletions(-) delete mode 100644 WMI-properly-cleanup-devices-to-avoid-crashes.patch delete mode 100644 add-macbookair41-keyboard.patch delete mode 100644 crypto-register-cryptd-first.patch delete mode 100644 epoll-fix-spurious-lockdep-warnings.patch delete mode 100644 iwlagn-fix-ht_params-NULL-pointer-dereference.patch delete mode 100644 media-DiBcom-protect-the-I2C-bufer-access.patch delete mode 100644 media-dib0700-protect-the-dib0700-buffer-access.patch delete mode 100644 mmc-Always-check-for-lower-base-frequency-quirk-for-.patch delete mode 100644 powerpc-Fix-deadlock-in-icswx-code.patch delete mode 100644 ums-realtek-driver-uses-stack-memory-for-DMA.patch diff --git a/WMI-properly-cleanup-devices-to-avoid-crashes.patch b/WMI-properly-cleanup-devices-to-avoid-crashes.patch deleted file mode 100644 index 1119d25f5..000000000 --- a/WMI-properly-cleanup-devices-to-avoid-crashes.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 023b9565972a4a5e0f01b9aa32680af6e9b5c388 Mon Sep 17 00:00:00 2001 -From: Dmitry Torokhov -Date: Wed, 7 Sep 2011 15:00:02 -0700 -Subject: [PATCH] WMI: properly cleanup devices to avoid crashes - -We need to remove devices that we destroy from the list, otherwise -we'll crash if there are more than one "_WDG" methods in DSDT. - -This fixes https://bugzilla.kernel.org/show_bug.cgi?id=32052 - -Tested-by: Ilya Tumaykin -Cc: stable@kernel.org -Signed-off-by: Dmitry Torokhov -Acked-by: Carlos Corbacho -Signed-off-by: Matthew Garrett ---- - drivers/platform/x86/wmi.c | 6 +++++- - 1 files changed, 5 insertions(+), 1 deletions(-) - -diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c -index f23d5a8..9b88be4 100644 ---- a/drivers/platform/x86/wmi.c -+++ b/drivers/platform/x86/wmi.c -@@ -754,9 +754,13 @@ static void wmi_free_devices(void) - struct wmi_block *wblock, *next; - - /* Delete devices for all the GUIDs */ -- list_for_each_entry_safe(wblock, next, &wmi_block_list, list) -+ list_for_each_entry_safe(wblock, next, &wmi_block_list, list) { -+ list_del(&wblock->list); - if (wblock->dev.class) - device_unregister(&wblock->dev); -+ else -+ kfree(wblock); -+ } - } - - static bool guid_already_parsed(const char *guid_string) --- -1.7.6.4 - diff --git a/add-macbookair41-keyboard.patch b/add-macbookair41-keyboard.patch deleted file mode 100644 index bd5afdafe..000000000 --- a/add-macbookair41-keyboard.patch +++ /dev/null @@ -1,119 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Pieter-Augustijn Van Malleghem -Newsgroups: gmane.linux.kernel.input -Subject: [PATCH] Add MacBookAir4,1 keyboard support -Date: Wed, 7 Sep 2011 16:15:52 -0400 -Lines: 72 -Approved: news@gmane.org -Message-ID: <20110907201552.GA1962@Caligula> -NNTP-Posting-Host: lo.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Trace: dough.gmane.org 1315426570 11003 80.91.229.12 (7 Sep 2011 20:16:10 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Wed, 7 Sep 2011 20:16:10 +0000 (UTC) -To: linux-input@vger.kernel.org -Original-X-From: linux-input-owner@vger.kernel.org Wed Sep 07 22:16:06 2011 -Return-path: -Envelope-to: glki-linux-input-2@lo.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1R1OXV-0007QX-Ll - for glki-linux-input-2@lo.gmane.org; Wed, 07 Sep 2011 22:16:06 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1751419Ab1IGUQE (ORCPT ); - Wed, 7 Sep 2011 16:16:04 -0400 -Original-Received: from mail-vx0-f174.google.com ([209.85.220.174]:57168 "EHLO - mail-vx0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1751237Ab1IGUQC (ORCPT - ); Wed, 7 Sep 2011 16:16:02 -0400 -Original-Received: by vxj15 with SMTP id 15so31147vxj.19 - for ; Wed, 07 Sep 2011 13:16:02 -0700 (PDT) -Original-Received: by 10.52.69.210 with SMTP id g18mr64348vdu.133.1315426562281; - Wed, 07 Sep 2011 13:16:02 -0700 (PDT) -Original-Received: from Caligula ([140.247.246.50]) - by mx.google.com with ESMTPS id ch2sm944169vdc.19.2011.09.07.13.16.01 - (version=TLSv1/SSLv3 cipher=OTHER); - Wed, 07 Sep 2011 13:16:01 -0700 (PDT) -Content-Disposition: inline -User-Agent: Mutt/1.5.21 (2010-09-15) -Original-Sender: linux-input-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-input@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel.input:21462 -Archived-At: - -This patch adds support for the Apple MacBookAir4,1 released in July -2011. It was inspired by Joshua Dillon's patch for the MacBookAir4,2 -posted on http://www.almostsure.com/mba42/hid-apple-dkms.patch. - -Signed-off-by: Pieter-Augustijn Van Malleghem -diff -uNr linux/drivers/hid/hid-apple.c patched/drivers/hid/hid-apple.c ---- linux/drivers/hid/hid-apple.c 2011-09-06 23:41:58.000000000 -0400 -+++ patched/drivers/hid/hid-apple.c 2011-09-06 23:53:05.000000000 -0400 -@@ -183,6 +183,9 @@ - if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && - hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) - table = macbookair_fn_keys; -+ else if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI && -+ hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) -+ table = apple_fn_keys; - else if (hid->product < 0x21d || hid->product >= 0x300) - table = powerbook_fn_keys; - else -@@ -493,6 +499,12 @@ - .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_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI), -+ .driver_data = APPLE_HAS_FN }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO), -+ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_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), -diff -uNr linux/drivers/hid/hid-core.c patched/drivers/hid/hid-core.c ---- linux/drivers/hid/hid-core.c 2011-09-06 23:41:58.000000000 -0400 -+++ patched/drivers/hid/hid-core.c 2011-09-06 23:56:22.000000000 -0400 -@@ -1340,6 +1340,9 @@ - { 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_WELLSPRING6A_ANSI) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) }, -@@ -1892,6 +1895,9 @@ - { 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_WELLSPRING6A_ANSI) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_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) }, - { } -diff -uNr linux/drivers/hid/hid-ids.h patched/drivers/hid/hid-ids.h ---- linux/drivers/hid/hid-ids.h 2011-09-06 23:41:58.000000000 -0400 -+++ patched/drivers/hid/hid-ids.h 2011-09-06 23:57:39.000000000 -0400 -@@ -109,6 +109,9 @@ - #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_WELLSPRING6A_ANSI 0x0249 -+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a -+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b - #define USB_DEVICE_ID_APPLE_ALU_REVB_ANSI 0x024f - #define USB_DEVICE_ID_APPLE_ALU_REVB_ISO 0x0250 - #define USB_DEVICE_ID_APPLE_ALU_REVB_JIS 0x0251 --- -To unsubscribe from this list: send the line "unsubscribe linux-input" 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/crypto-register-cryptd-first.patch b/crypto-register-cryptd-first.patch deleted file mode 100644 index 0cd55d6fc..000000000 --- a/crypto-register-cryptd-first.patch +++ /dev/null @@ -1,26 +0,0 @@ -commit 9d4c522a113f6caa8b792ae829a25490fa87b1a2 -Author: Herbert Xu -Date: Fri Aug 19 16:11:23 2011 +0800 - - crypto: cryptd - Use subsys_initcall to prevent races with aesni - - As cryptd is depeneded on by other algorithms such as aesni-intel, - it needs to be registered before them. When everything is built - as modules, this occurs naturally. However, for this to work when - they are built-in, we need to use subsys_initcall in cryptd. - - Signed-off-by: Herbert Xu - -diff --git a/crypto/cryptd.c b/crypto/cryptd.c -index e46d21a..671d4d6 100644 ---- a/crypto/cryptd.c -+++ b/crypto/cryptd.c -@@ -945,7 +945,7 @@ static void __exit cryptd_exit(void) - crypto_unregister_template(&cryptd_tmpl); - } - --module_init(cryptd_init); -+subsys_initcall(cryptd_init); - module_exit(cryptd_exit); - - MODULE_LICENSE("GPL"); diff --git a/epoll-fix-spurious-lockdep-warnings.patch b/epoll-fix-spurious-lockdep-warnings.patch deleted file mode 100644 index c163a86d7..000000000 --- a/epoll-fix-spurious-lockdep-warnings.patch +++ /dev/null @@ -1,116 +0,0 @@ -epoll can acquire multiple ep->mutex on multiple "struct eventpoll"s -at once in the case where one epoll fd is monitoring another epoll -fd. This is perfectly OK, since we're careful about the lock ordering, -but causes spurious lockdep warnings. Annotate the recursion using -mutex_lock_nested, and add a comment explaining the nesting rules for -good measure. - -Reported-by: Paul Bolle -Signed-off-by: Nelson Elhage ---- - I've tested this on a synthetic epoll test case, that just adds e1 to - e2 and then does an epoll_wait(). I verified that it caused lockdep - problems on 3.0 and that this patch fixed it, but I haven't done more - extensive testing. Paul, are you able to test systemd against this? - - fs/eventpoll.c | 25 ++++++++++++++++++------- - 1 files changed, 18 insertions(+), 7 deletions(-) - -diff --git a/fs/eventpoll.c b/fs/eventpoll.c -index f9cfd16..0cb7bc6 100644 ---- a/fs/eventpoll.c -+++ b/fs/eventpoll.c -@@ -76,6 +76,15 @@ - * Events that require holding "epmutex" are very rare, while for - * normal operations the epoll private "ep->mtx" will guarantee - * a better scalability. -+ * It is possible to acquire multiple "ep->mtx"es at once in the case -+ * when one epoll fd is added to another. In this case, we always -+ * acquire the locks in the order of nesting (i.e. after epoll_ctl(e1, -+ * EPOLL_CTL_ADD, e2), e1->mtx will always be acquired before -+ * e2->mtx). Since we disallow cycles of epoll file descriptors, this -+ * ensures that the mutexes are well-ordered. In order to communicate -+ * this nesting to lockdep, when walking a tree of epoll file -+ * descriptors, we use the current recursion depth as the lockdep -+ * subkey. - */ - - /* Epoll private bits inside the event mask */ -@@ -464,13 +473,15 @@ static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi) - * @ep: Pointer to the epoll private data structure. - * @sproc: Pointer to the scan callback. - * @priv: Private opaque data passed to the @sproc callback. -+ * @depth: The current depth of recursive f_op->poll calls. - * - * Returns: The same integer error code returned by the @sproc callback. - */ - static int ep_scan_ready_list(struct eventpoll *ep, - int (*sproc)(struct eventpoll *, - struct list_head *, void *), -- void *priv) -+ void *priv, -+ int depth) - { - int error, pwake = 0; - unsigned long flags; -@@ -481,7 +492,7 @@ static int ep_scan_ready_list(struct eventpoll *ep, - * We need to lock this because we could be hit by - * eventpoll_release_file() and epoll_ctl(). - */ -- mutex_lock(&ep->mtx); -+ mutex_lock_nested(&ep->mtx, depth); - - /* - * Steal the ready list, and re-init the original one to the -@@ -670,7 +681,7 @@ static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head, - - static int ep_poll_readyevents_proc(void *priv, void *cookie, int call_nests) - { -- return ep_scan_ready_list(priv, ep_read_events_proc, NULL); -+ return ep_scan_ready_list(priv, ep_read_events_proc, NULL, call_nests + 1); - } - - static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait) -@@ -737,7 +748,7 @@ void eventpoll_release_file(struct file *file) - - ep = epi->ep; - list_del_init(&epi->fllink); -- mutex_lock(&ep->mtx); -+ mutex_lock_nested(&ep->mtx, 0); - ep_remove(ep, epi); - mutex_unlock(&ep->mtx); - } -@@ -1134,7 +1145,7 @@ static int ep_send_events(struct eventpoll *ep, - esed.maxevents = maxevents; - esed.events = events; - -- return ep_scan_ready_list(ep, ep_send_events_proc, &esed); -+ return ep_scan_ready_list(ep, ep_send_events_proc, &esed, 0); - } - - static inline struct timespec ep_set_mstimeout(long ms) -@@ -1267,7 +1278,7 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests) - struct rb_node *rbp; - struct epitem *epi; - -- mutex_lock(&ep->mtx); -+ mutex_lock_nested(&ep->mtx, call_nests + 1); - for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) { - epi = rb_entry(rbp, struct epitem, rbn); - if (unlikely(is_file_epoll(epi->ffd.file))) { -@@ -1409,7 +1420,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, - } - - -- mutex_lock(&ep->mtx); -+ mutex_lock_nested(&ep->mtx, 0); - - /* - * Try to lookup the file inside our RB tree, Since we grabbed "mtx" --- -1.7.4.1 - --- -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/iwlagn-fix-ht_params-NULL-pointer-dereference.patch b/iwlagn-fix-ht_params-NULL-pointer-dereference.patch deleted file mode 100644 index 4dcf490bb..000000000 --- a/iwlagn-fix-ht_params-NULL-pointer-dereference.patch +++ /dev/null @@ -1,43 +0,0 @@ -This fix regression introduced by commit: - -commit 15b3f3b006b42a678523cad989bfd60b76bf4403 -Author: Wey-Yi Guy -Date: Fri Jun 3 07:54:13 2011 -0700 - - iwlagn: set smps mode after assoc for 1000 device - -Also remove unneeded brackets on the way. - -Address: -https://bugzilla.redhat.com/show_bug.cgi?id=744155 - -If fix will not get 3.1 release, it should be applied in 3.1 stable. - -Cc: stable@kernel.org # 3.1+ -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -index ca632f9..5004342 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -@@ -296,8 +296,8 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv, - return ret; - } - -- if ((ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION) && -- priv->cfg->ht_params->smps_mode) -+ if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION && -+ priv->cfg->ht_params && priv->cfg->ht_params->smps_mode) - ieee80211_request_smps(ctx->vif, - priv->cfg->ht_params->smps_mode); - --- -1.7.1 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index c4ec2def7..5dc058350 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -53,7 +53,7 @@ Summary: The Linux kernel # Do we have a -stable update to apply? %define stable_update 1 # 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 @@ Patch2899: linux-2.6-v4l-dvb-fixes.patch Patch2900: linux-2.6-v4l-dvb-update.patch Patch2901: linux-2.6-v4l-dvb-experimental.patch -Patch2903: media-DiBcom-protect-the-I2C-bufer-access.patch -Patch2904: media-dib0700-protect-the-dib0700-buffer-access.patch Patch2905: media-dib0700-correct-error-message.patch Patch3000: rcutree-avoid-false-quiescent-states.patch @@ -636,12 +634,9 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12021: udlfb-bind-framebuffer-to-interface.patch -Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch -Patch12024: epoll-fix-spurious-lockdep-warnings.patch Patch12025: rcu-avoid-just-onlined-cpu-resched.patch Patch12026: block-stray-block-put-after-teardown.patch Patch12027: usb-add-quirk-for-logitech-webcams.patch -Patch12029: crypto-register-cryptd-first.patch Patch12030: epoll-limit-paths.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch @@ -649,23 +644,14 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13002: revert-efi-rtclock.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch -Patch13007: add-macbookair41-keyboard.patch - Patch13009: hvcs_pi_buf_alloc.patch -Patch13013: powerpc-Fix-deadlock-in-icswx-code.patch - -Patch13014: iwlagn-fix-ht_params-NULL-pointer-dereference.patch - Patch20000: utrace.patch # Flattened devicetree support Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch -#rhbz #722509 -Patch21002: mmc-Always-check-for-lower-base-frequency-quirk-for-.patch - #rhbz #735946 Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch @@ -679,9 +665,6 @@ Patch21050: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch Patch21070: oom-fix-integer-overflow-of-points.patch -#rhbz 706574 -Patch21071: WMI-properly-cleanup-devices-to-avoid-crashes.patch - #rhbz 728607 Patch21060: elantech.patch @@ -1215,34 +1198,19 @@ ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch add-appleir-usb-driver.patch ApplyPatch udlfb-bind-framebuffer-to-interface.patch -#ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch -#ApplyPatch epoll-fix-spurious-lockdep-warnings.patch ApplyPatch epoll-limit-paths.patch ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch ApplyPatch block-stray-block-put-after-teardown.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch -#ApplyPatch crypto-register-cryptd-first.patch - # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch revert-efi-rtclock.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch -#ApplyPatch add-macbookair41-keyboard.patch - ApplyPatch hvcs_pi_buf_alloc.patch -#ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch - -#ApplyPatch iwlagn-fix-ht_params-NULL-pointer-dereference.patch - -#rhbz #722509 -#ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch - -#ApplyPatch media-DiBcom-protect-the-I2C-bufer-access.patch -#ApplyPatch media-dib0700-protect-the-dib0700-buffer-access.patch ApplyPatch media-dib0700-correct-error-message.patch # utrace. @@ -1259,9 +1227,6 @@ ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch #rhbz 750402 ApplyPatch oom-fix-integer-overflow-of-points.patch -#rhbz 706574 -#ApplyPatch WMI-properly-cleanup-devices-to-avoid-crashes.patch - #rhbz 728607 ApplyPatch elantech.patch @@ -1893,6 +1858,9 @@ fi # and build. %changelog +* Fri Nov 11 2011 Josh Boyer 2.6.41.1-1 +- Linux 3.1.1 + * Fri Nov 11 2011 John W. Linville - Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 diff --git a/media-DiBcom-protect-the-I2C-bufer-access.patch b/media-DiBcom-protect-the-I2C-bufer-access.patch deleted file mode 100644 index 1b2a54b86..000000000 --- a/media-DiBcom-protect-the-I2C-bufer-access.patch +++ /dev/null @@ -1,1150 +0,0 @@ -From: Patrick Boettcher -Date: Wed, 3 Aug 2011 15:08:21 +0000 (-0300) -Subject: [media] DiBcom: protect the I2C bufer access -X-Git-Tag: next-20110927~67^2~4^2~225 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=79fcce3230b140f7675f8529ee53fe2f9644f902 - -[media] DiBcom: protect the I2C bufer access - -This patch protects the I2C buffer access in order to manage concurrent -access. This protection is done using mutex. -Furthermore, for the dib9000, if a pid filtering command is -received during the tuning, this pid filtering command is delayed to -avoid any concurrent access issue. - -Cc: Mauro Carvalho Chehab -Cc: Florian Mickler -Cc: stable@kernel.org -Signed-off-by: Olivier Grenie -Signed-off-by: Patrick Boettcher -Signed-off-by: Mauro Carvalho Chehab ---- - -diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c -index 1d47d4d..dc1cb17 100644 ---- a/drivers/media/dvb/frontends/dib0070.c -+++ b/drivers/media/dvb/frontends/dib0070.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - #include "dvb_frontend.h" - -@@ -78,10 +79,18 @@ struct dib0070_state { - struct i2c_msg msg[2]; - u8 i2c_write_buffer[3]; - u8 i2c_read_buffer[2]; -+ struct mutex i2c_buffer_lock; - }; - --static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) -+static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg) - { -+ u16 ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return 0; -+ } -+ - state->i2c_write_buffer[0] = reg; - - memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); -@@ -96,13 +105,23 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) - - if (i2c_transfer(state->i2c, state->msg, 2) != 2) { - printk(KERN_WARNING "DiB0070 I2C read failed\n"); -- return 0; -- } -- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ ret = 0; -+ } else -+ ret = (state->i2c_read_buffer[0] << 8) -+ | state->i2c_read_buffer[1]; -+ -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - - static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) - { -+ int ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } - state->i2c_write_buffer[0] = reg; - state->i2c_write_buffer[1] = val >> 8; - state->i2c_write_buffer[2] = val & 0xff; -@@ -115,9 +134,12 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) - - if (i2c_transfer(state->i2c, state->msg, 1) != 1) { - printk(KERN_WARNING "DiB0070 I2C write failed\n"); -- return -EREMOTEIO; -- } -- return 0; -+ ret = -EREMOTEIO; -+ } else -+ ret = 0; -+ -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - - #define HARD_RESET(state) do { \ -@@ -734,6 +756,7 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter - state->cfg = cfg; - state->i2c = i2c; - state->fe = fe; -+ mutex_init(&state->i2c_buffer_lock); - fe->tuner_priv = state; - - if (dib0070_reset(fe) != 0) -diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c -index c9c935a..b174d1c 100644 ---- a/drivers/media/dvb/frontends/dib0090.c -+++ b/drivers/media/dvb/frontends/dib0090.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - #include "dvb_frontend.h" - -@@ -196,6 +197,7 @@ struct dib0090_state { - struct i2c_msg msg[2]; - u8 i2c_write_buffer[3]; - u8 i2c_read_buffer[2]; -+ struct mutex i2c_buffer_lock; - }; - - struct dib0090_fw_state { -@@ -208,10 +210,18 @@ struct dib0090_fw_state { - struct i2c_msg msg; - u8 i2c_write_buffer[2]; - u8 i2c_read_buffer[2]; -+ struct mutex i2c_buffer_lock; - }; - - static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) - { -+ u16 ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return 0; -+ } -+ - state->i2c_write_buffer[0] = reg; - - memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); -@@ -226,14 +236,24 @@ static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) - - if (i2c_transfer(state->i2c, state->msg, 2) != 2) { - printk(KERN_WARNING "DiB0090 I2C read failed\n"); -- return 0; -- } -+ ret = 0; -+ } else -+ ret = (state->i2c_read_buffer[0] << 8) -+ | state->i2c_read_buffer[1]; - -- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - - static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) - { -+ int ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ - state->i2c_write_buffer[0] = reg & 0xff; - state->i2c_write_buffer[1] = val >> 8; - state->i2c_write_buffer[2] = val & 0xff; -@@ -246,13 +266,23 @@ static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) - - if (i2c_transfer(state->i2c, state->msg, 1) != 1) { - printk(KERN_WARNING "DiB0090 I2C write failed\n"); -- return -EREMOTEIO; -- } -- return 0; -+ ret = -EREMOTEIO; -+ } else -+ ret = 0; -+ -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - - static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg) - { -+ u16 ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return 0; -+ } -+ - state->i2c_write_buffer[0] = reg; - - memset(&state->msg, 0, sizeof(struct i2c_msg)); -@@ -262,13 +292,24 @@ static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg) - state->msg.len = 2; - if (i2c_transfer(state->i2c, &state->msg, 1) != 1) { - printk(KERN_WARNING "DiB0090 I2C read failed\n"); -- return 0; -- } -- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ ret = 0; -+ } else -+ ret = (state->i2c_read_buffer[0] << 8) -+ | state->i2c_read_buffer[1]; -+ -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - - static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val) - { -+ int ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ - state->i2c_write_buffer[0] = val >> 8; - state->i2c_write_buffer[1] = val & 0xff; - -@@ -279,9 +320,12 @@ static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val) - state->msg.len = 2; - if (i2c_transfer(state->i2c, &state->msg, 1) != 1) { - printk(KERN_WARNING "DiB0090 I2C write failed\n"); -- return -EREMOTEIO; -- } -- return 0; -+ ret = -EREMOTEIO; -+ } else -+ ret = 0; -+ -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - - #define HARD_RESET(state) do { if (cfg->reset) { if (cfg->sleep) cfg->sleep(fe, 0); msleep(10); cfg->reset(fe, 1); msleep(10); cfg->reset(fe, 0); msleep(10); } } while (0) -@@ -2440,6 +2484,7 @@ struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapte - st->config = config; - st->i2c = i2c; - st->fe = fe; -+ mutex_init(&st->i2c_buffer_lock); - fe->tuner_priv = st; - - if (config->wbd == NULL) -@@ -2471,6 +2516,7 @@ struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_ada - st->config = config; - st->i2c = i2c; - st->fe = fe; -+ mutex_init(&st->i2c_buffer_lock); - fe->tuner_priv = st; - - if (dib0090_fw_reset_digital(fe, st->config) != 0) -diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c -index 79cb1c2..dbb76d7 100644 ---- a/drivers/media/dvb/frontends/dib7000m.c -+++ b/drivers/media/dvb/frontends/dib7000m.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - - #include "dvb_frontend.h" - -@@ -55,6 +56,7 @@ struct dib7000m_state { - struct i2c_msg msg[2]; - u8 i2c_write_buffer[4]; - u8 i2c_read_buffer[2]; -+ struct mutex i2c_buffer_lock; - }; - - enum dib7000m_power_mode { -@@ -69,6 +71,13 @@ enum dib7000m_power_mode { - - static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) - { -+ u16 ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return 0; -+ } -+ - state->i2c_write_buffer[0] = (reg >> 8) | 0x80; - state->i2c_write_buffer[1] = reg & 0xff; - -@@ -85,11 +94,21 @@ static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) - if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2) - dprintk("i2c read error on %d",reg); - -- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ mutex_unlock(&state->i2c_buffer_lock); -+ -+ return ret; - } - - static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) - { -+ int ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ - state->i2c_write_buffer[0] = (reg >> 8) & 0xff; - state->i2c_write_buffer[1] = reg & 0xff; - state->i2c_write_buffer[2] = (val >> 8) & 0xff; -@@ -101,7 +120,10 @@ static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) - state->msg[0].buf = state->i2c_write_buffer; - state->msg[0].len = 4; - -- return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; -+ ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -+ -EREMOTEIO : 0); -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf) - { -@@ -1385,6 +1407,7 @@ struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, - demod = &st->demod; - demod->demodulator_priv = st; - memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops)); -+ mutex_init(&st->i2c_buffer_lock); - - st->timf_default = cfg->bw->timf; - -diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c -index a64a538..4eb9c2b 100644 ---- a/drivers/media/dvb/frontends/dib7000p.c -+++ b/drivers/media/dvb/frontends/dib7000p.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - #include "dvb_math.h" - #include "dvb_frontend.h" -@@ -68,6 +69,7 @@ struct dib7000p_state { - struct i2c_msg msg[2]; - u8 i2c_write_buffer[4]; - u8 i2c_read_buffer[2]; -+ struct mutex i2c_buffer_lock; - }; - - enum dib7000p_power_mode { -@@ -81,6 +83,13 @@ static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff); - - static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) - { -+ u16 ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return 0; -+ } -+ - state->i2c_write_buffer[0] = reg >> 8; - state->i2c_write_buffer[1] = reg & 0xff; - -@@ -97,11 +106,20 @@ static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) - if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2) - dprintk("i2c read error on %d", reg); - -- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - - static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) - { -+ int ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ - state->i2c_write_buffer[0] = (reg >> 8) & 0xff; - state->i2c_write_buffer[1] = reg & 0xff; - state->i2c_write_buffer[2] = (val >> 8) & 0xff; -@@ -113,7 +131,10 @@ static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) - state->msg[0].buf = state->i2c_write_buffer; - state->msg[0].len = 4; - -- return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; -+ ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -+ -EREMOTEIO : 0); -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - - static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf) -@@ -1646,6 +1667,7 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau - return -ENOMEM; - - dpst->i2c_adap = i2c; -+ mutex_init(&dpst->i2c_buffer_lock); - - for (k = no_of_demods - 1; k >= 0; k--) { - dpst->cfg = cfg[k]; -@@ -2324,6 +2346,7 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, - demod = &st->demod; - demod->demodulator_priv = st; - memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops)); -+ mutex_init(&st->i2c_buffer_lock); - - dib7000p_write_word(st, 1287, 0x0003); /* sram lead in, rdy */ - -@@ -2333,8 +2356,9 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, - st->version = dib7000p_read_word(st, 897); - - /* FIXME: make sure the dev.parent field is initialized, or else -- request_firmware() will hit an OOPS (this should be moved somewhere -- more common) */ -+ request_firmware() will hit an OOPS (this should be moved somewhere -+ more common) */ -+ st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent; - - /* FIXME: make sure the dev.parent field is initialized, or else - request_firmware() will hit an OOPS (this should be moved somewhere -diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c -index 7d2ea11..fe284d5 100644 ---- a/drivers/media/dvb/frontends/dib8000.c -+++ b/drivers/media/dvb/frontends/dib8000.c -@@ -10,6 +10,8 @@ - #include - #include - #include -+#include -+ - #include "dvb_math.h" - - #include "dvb_frontend.h" -@@ -37,6 +39,7 @@ struct i2c_device { - u8 addr; - u8 *i2c_write_buffer; - u8 *i2c_read_buffer; -+ struct mutex *i2c_buffer_lock; - }; - - struct dib8000_state { -@@ -77,6 +80,7 @@ struct dib8000_state { - struct i2c_msg msg[2]; - u8 i2c_write_buffer[4]; - u8 i2c_read_buffer[2]; -+ struct mutex i2c_buffer_lock; - }; - - enum dib8000_power_mode { -@@ -86,24 +90,39 @@ enum dib8000_power_mode { - - static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg) - { -+ u16 ret; - struct i2c_msg msg[2] = { -- {.addr = i2c->addr >> 1, .flags = 0, -- .buf = i2c->i2c_write_buffer, .len = 2}, -- {.addr = i2c->addr >> 1, .flags = I2C_M_RD, -- .buf = i2c->i2c_read_buffer, .len = 2}, -+ {.addr = i2c->addr >> 1, .flags = 0, .len = 2}, -+ {.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2}, - }; - -+ if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return 0; -+ } -+ -+ msg[0].buf = i2c->i2c_write_buffer; - msg[0].buf[0] = reg >> 8; - msg[0].buf[1] = reg & 0xff; -+ msg[1].buf = i2c->i2c_read_buffer; - - if (i2c_transfer(i2c->adap, msg, 2) != 2) - dprintk("i2c read error on %d", reg); - -- return (msg[1].buf[0] << 8) | msg[1].buf[1]; -+ ret = (msg[1].buf[0] << 8) | msg[1].buf[1]; -+ mutex_unlock(i2c->i2c_buffer_lock); -+ return ret; - } - - static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) - { -+ u16 ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return 0; -+ } -+ - state->i2c_write_buffer[0] = reg >> 8; - state->i2c_write_buffer[1] = reg & 0xff; - -@@ -120,7 +139,10 @@ static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) - if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2) - dprintk("i2c read error on %d", reg); - -- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ mutex_unlock(&state->i2c_buffer_lock); -+ -+ return ret; - } - - static u32 dib8000_read32(struct dib8000_state *state, u16 reg) -@@ -135,22 +157,35 @@ static u32 dib8000_read32(struct dib8000_state *state, u16 reg) - - static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val) - { -- struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, -- .buf = i2c->i2c_write_buffer, .len = 4}; -+ struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4}; - int ret = 0; - -+ if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ -+ msg.buf = i2c->i2c_write_buffer; - msg.buf[0] = (reg >> 8) & 0xff; - msg.buf[1] = reg & 0xff; - msg.buf[2] = (val >> 8) & 0xff; - msg.buf[3] = val & 0xff; - - ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0; -+ mutex_unlock(i2c->i2c_buffer_lock); - - return ret; - } - - static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) - { -+ int ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ - state->i2c_write_buffer[0] = (reg >> 8) & 0xff; - state->i2c_write_buffer[1] = reg & 0xff; - state->i2c_write_buffer[2] = (val >> 8) & 0xff; -@@ -162,7 +197,11 @@ static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) - state->msg[0].buf = state->i2c_write_buffer; - state->msg[0].len = 4; - -- return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; -+ ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -+ -EREMOTEIO : 0); -+ mutex_unlock(&state->i2c_buffer_lock); -+ -+ return ret; - } - - static const s16 coeff_2k_sb_1seg_dqpsk[8] = { -@@ -2434,8 +2473,15 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau - if (!client.i2c_read_buffer) { - dprintk("%s: not enough memory", __func__); - ret = -ENOMEM; -- goto error_memory; -+ goto error_memory_read; -+ } -+ client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL); -+ if (!client.i2c_buffer_lock) { -+ dprintk("%s: not enough memory", __func__); -+ ret = -ENOMEM; -+ goto error_memory_lock; - } -+ mutex_init(client.i2c_buffer_lock); - - for (k = no_of_demods - 1; k >= 0; k--) { - /* designated i2c address */ -@@ -2476,8 +2522,10 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau - } - - error: -+ kfree(client.i2c_buffer_lock); -+error_memory_lock: - kfree(client.i2c_read_buffer); --error_memory: -+error_memory_read: - kfree(client.i2c_write_buffer); - - return ret; -@@ -2581,6 +2629,8 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s - state->i2c.addr = i2c_addr; - state->i2c.i2c_write_buffer = state->i2c_write_buffer; - state->i2c.i2c_read_buffer = state->i2c_read_buffer; -+ mutex_init(&state->i2c_buffer_lock); -+ state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock; - state->gpio_val = cfg->gpio_val; - state->gpio_dir = cfg->gpio_dir; - -diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb/frontends/dib9000.c -index a085588..b931074 100644 ---- a/drivers/media/dvb/frontends/dib9000.c -+++ b/drivers/media/dvb/frontends/dib9000.c -@@ -38,6 +38,15 @@ struct i2c_device { - #define DibInitLock(lock) mutex_init(lock) - #define DibFreeLock(lock) - -+struct dib9000_pid_ctrl { -+#define DIB9000_PID_FILTER_CTRL 0 -+#define DIB9000_PID_FILTER 1 -+ u8 cmd; -+ u8 id; -+ u16 pid; -+ u8 onoff; -+}; -+ - struct dib9000_state { - struct i2c_device i2c; - -@@ -99,6 +108,10 @@ struct dib9000_state { - struct i2c_msg msg[2]; - u8 i2c_write_buffer[255]; - u8 i2c_read_buffer[255]; -+ DIB_LOCK demod_lock; -+ u8 get_frontend_internal; -+ struct dib9000_pid_ctrl pid_ctrl[10]; -+ s8 pid_ctrl_index; /* -1: empty list; -2: do not use the list */ - }; - - static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -@@ -1743,19 +1756,56 @@ EXPORT_SYMBOL(dib9000_set_gpio); - int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) - { - struct dib9000_state *state = fe->demodulator_priv; -- u16 val = dib9000_read_word(state, 294 + 1) & 0xffef; -+ u16 val; -+ int ret; -+ -+ if ((state->pid_ctrl_index != -2) && (state->pid_ctrl_index < 9)) { -+ /* postpone the pid filtering cmd */ -+ dprintk("pid filter cmd postpone"); -+ state->pid_ctrl_index++; -+ state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER_CTRL; -+ state->pid_ctrl[state->pid_ctrl_index].onoff = onoff; -+ return 0; -+ } -+ -+ DibAcquireLock(&state->demod_lock); -+ -+ val = dib9000_read_word(state, 294 + 1) & 0xffef; - val |= (onoff & 0x1) << 4; - - dprintk("PID filter enabled %d", onoff); -- return dib9000_write_word(state, 294 + 1, val); -+ ret = dib9000_write_word(state, 294 + 1, val); -+ DibReleaseLock(&state->demod_lock); -+ return ret; -+ - } - EXPORT_SYMBOL(dib9000_fw_pid_filter_ctrl); - - int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) - { - struct dib9000_state *state = fe->demodulator_priv; -+ int ret; -+ -+ if (state->pid_ctrl_index != -2) { -+ /* postpone the pid filtering cmd */ -+ dprintk("pid filter postpone"); -+ if (state->pid_ctrl_index < 9) { -+ state->pid_ctrl_index++; -+ state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER; -+ state->pid_ctrl[state->pid_ctrl_index].id = id; -+ state->pid_ctrl[state->pid_ctrl_index].pid = pid; -+ state->pid_ctrl[state->pid_ctrl_index].onoff = onoff; -+ } else -+ dprintk("can not add any more pid ctrl cmd"); -+ return 0; -+ } -+ -+ DibAcquireLock(&state->demod_lock); - dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff); -- return dib9000_write_word(state, 300 + 1 + id, onoff ? (1 << 13) | pid : 0); -+ ret = dib9000_write_word(state, 300 + 1 + id, -+ onoff ? (1 << 13) | pid : 0); -+ DibReleaseLock(&state->demod_lock); -+ return ret; - } - EXPORT_SYMBOL(dib9000_fw_pid_filter); - -@@ -1778,6 +1828,7 @@ static void dib9000_release(struct dvb_frontend *demod) - DibFreeLock(&state->platform.risc.mbx_lock); - DibFreeLock(&state->platform.risc.mem_lock); - DibFreeLock(&state->platform.risc.mem_mbx_lock); -+ DibFreeLock(&state->demod_lock); - dibx000_exit_i2c_master(&st->i2c_master); - - i2c_del_adapter(&st->tuner_adap); -@@ -1795,14 +1846,19 @@ static int dib9000_sleep(struct dvb_frontend *fe) - { - struct dib9000_state *state = fe->demodulator_priv; - u8 index_frontend; -- int ret; -+ int ret = 0; - -+ DibAcquireLock(&state->demod_lock); - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]); - if (ret < 0) -- return ret; -+ goto error; - } -- return dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0); -+ ret = dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0); -+ -+error: -+ DibReleaseLock(&state->demod_lock); -+ return ret; - } - - static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune) -@@ -1816,7 +1872,10 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par - struct dib9000_state *state = fe->demodulator_priv; - u8 index_frontend, sub_index_frontend; - fe_status_t stat; -- int ret; -+ int ret = 0; -+ -+ if (state->get_frontend_internal == 0) -+ DibAcquireLock(&state->demod_lock); - - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat); -@@ -1846,14 +1905,15 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par - state->fe[index_frontend]->dtv_property_cache.rolloff; - } - } -- return 0; -+ ret = 0; -+ goto return_value; - } - } - - /* get the channel from master chip */ - ret = dib9000_fw_get_channel(fe, fep); - if (ret != 0) -- return ret; -+ goto return_value; - - /* synchronize the cache with the other frontends */ - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { -@@ -1866,8 +1926,12 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par - state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP; - state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff; - } -+ ret = 0; - -- return 0; -+return_value: -+ if (state->get_frontend_internal == 0) -+ DibReleaseLock(&state->demod_lock); -+ return ret; - } - - static int dib9000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) -@@ -1912,6 +1976,10 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par - dprintk("dib9000: must specify bandwidth "); - return 0; - } -+ -+ state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */ -+ DibAcquireLock(&state->demod_lock); -+ - fe->dtv_property_cache.delivery_system = SYS_DVBT; - - /* set the master status */ -@@ -1974,13 +2042,18 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par - /* check the tune result */ - if (exit_condition == 1) { /* tune failed */ - dprintk("tune failed"); -+ DibReleaseLock(&state->demod_lock); -+ /* tune failed; put all the pid filtering cmd to junk */ -+ state->pid_ctrl_index = -1; - return 0; - } - - dprintk("tune success on frontend%i", index_frontend_success); - - /* synchronize all the channel cache */ -+ state->get_frontend_internal = 1; - dib9000_get_frontend(state->fe[0], fep); -+ state->get_frontend_internal = 0; - - /* retune the other frontends with the found channel */ - channel_status.status = CHANNEL_STATUS_PARAMETERS_SET; -@@ -2025,6 +2098,28 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par - /* turn off the diversity for the last frontend */ - dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0); - -+ DibReleaseLock(&state->demod_lock); -+ if (state->pid_ctrl_index >= 0) { -+ u8 index_pid_filter_cmd; -+ u8 pid_ctrl_index = state->pid_ctrl_index; -+ -+ state->pid_ctrl_index = -2; -+ for (index_pid_filter_cmd = 0; -+ index_pid_filter_cmd <= pid_ctrl_index; -+ index_pid_filter_cmd++) { -+ if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER_CTRL) -+ dib9000_fw_pid_filter_ctrl(state->fe[0], -+ state->pid_ctrl[index_pid_filter_cmd].onoff); -+ else if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER) -+ dib9000_fw_pid_filter(state->fe[0], -+ state->pid_ctrl[index_pid_filter_cmd].id, -+ state->pid_ctrl[index_pid_filter_cmd].pid, -+ state->pid_ctrl[index_pid_filter_cmd].onoff); -+ } -+ } -+ /* do not postpone any more the pid filtering */ -+ state->pid_ctrl_index = -2; -+ - return 0; - } - -@@ -2041,6 +2136,7 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat) - u8 index_frontend; - u16 lock = 0, lock_slave = 0; - -+ DibAcquireLock(&state->demod_lock); - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) - lock_slave |= dib9000_read_lock(state->fe[index_frontend]); - -@@ -2059,6 +2155,8 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat) - if ((lock & 0x0008) || (lock_slave & 0x0008)) - *stat |= FE_HAS_LOCK; - -+ DibReleaseLock(&state->demod_lock); -+ - return 0; - } - -@@ -2066,10 +2164,14 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber) - { - struct dib9000_state *state = fe->demodulator_priv; - u16 *c; -+ int ret = 0; - -+ DibAcquireLock(&state->demod_lock); - DibAcquireLock(&state->platform.risc.mem_mbx_lock); -- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) -- return -EIO; -+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { -+ ret = -EIO; -+ goto error; -+ } - dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, - state->i2c_read_buffer, 16 * 2); - DibReleaseLock(&state->platform.risc.mem_mbx_lock); -@@ -2077,7 +2179,10 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber) - c = (u16 *)state->i2c_read_buffer; - - *ber = c[10] << 16 | c[11]; -- return 0; -+ -+error: -+ DibReleaseLock(&state->demod_lock); -+ return ret; - } - - static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) -@@ -2086,7 +2191,9 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) - u8 index_frontend; - u16 *c = (u16 *)state->i2c_read_buffer; - u16 val; -+ int ret = 0; - -+ DibAcquireLock(&state->demod_lock); - *strength = 0; - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val); -@@ -2097,8 +2204,10 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) - } - - DibAcquireLock(&state->platform.risc.mem_mbx_lock); -- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) -- return -EIO; -+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { -+ ret = -EIO; -+ goto error; -+ } - dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); - DibReleaseLock(&state->platform.risc.mem_mbx_lock); - -@@ -2107,7 +2216,10 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) - *strength = 65535; - else - *strength += val; -- return 0; -+ -+error: -+ DibReleaseLock(&state->demod_lock); -+ return ret; - } - - static u32 dib9000_get_snr(struct dvb_frontend *fe) -@@ -2151,6 +2263,7 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr) - u8 index_frontend; - u32 snr_master; - -+ DibAcquireLock(&state->demod_lock); - snr_master = dib9000_get_snr(fe); - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) - snr_master += dib9000_get_snr(state->fe[index_frontend]); -@@ -2161,6 +2274,8 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr) - } else - *snr = 0; - -+ DibReleaseLock(&state->demod_lock); -+ - return 0; - } - -@@ -2168,15 +2283,22 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) - { - struct dib9000_state *state = fe->demodulator_priv; - u16 *c = (u16 *)state->i2c_read_buffer; -+ int ret = 0; - -+ DibAcquireLock(&state->demod_lock); - DibAcquireLock(&state->platform.risc.mem_mbx_lock); -- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) -- return -EIO; -+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { -+ ret = -EIO; -+ goto error; -+ } - dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); - DibReleaseLock(&state->platform.risc.mem_mbx_lock); - - *unc = c[12]; -- return 0; -+ -+error: -+ DibReleaseLock(&state->demod_lock); -+ return ret; - } - - int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr) -@@ -2322,6 +2444,10 @@ struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, c - DibInitLock(&st->platform.risc.mbx_lock); - DibInitLock(&st->platform.risc.mem_lock); - DibInitLock(&st->platform.risc.mem_mbx_lock); -+ DibInitLock(&st->demod_lock); -+ st->get_frontend_internal = 0; -+ -+ st->pid_ctrl_index = -2; - - st->fe[0] = fe; - fe->demodulator_priv = st; -diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c -index dc5d17a..774d507 100644 ---- a/drivers/media/dvb/frontends/dibx000_common.c -+++ b/drivers/media/dvb/frontends/dibx000_common.c -@@ -1,4 +1,5 @@ - #include -+#include - - #include "dibx000_common.h" - -@@ -10,6 +11,13 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); - - static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) - { -+ int ret; -+ -+ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ - mst->i2c_write_buffer[0] = (reg >> 8) & 0xff; - mst->i2c_write_buffer[1] = reg & 0xff; - mst->i2c_write_buffer[2] = (val >> 8) & 0xff; -@@ -21,11 +29,21 @@ static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) - mst->msg[0].buf = mst->i2c_write_buffer; - mst->msg[0].len = 4; - -- return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0; -+ ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0; -+ mutex_unlock(&mst->i2c_buffer_lock); -+ -+ return ret; - } - - static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg) - { -+ u16 ret; -+ -+ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return 0; -+ } -+ - mst->i2c_write_buffer[0] = reg >> 8; - mst->i2c_write_buffer[1] = reg & 0xff; - -@@ -42,7 +60,10 @@ static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg) - if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2) - dprintk("i2c read error on %d", reg); - -- return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1]; -+ ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1]; -+ mutex_unlock(&mst->i2c_buffer_lock); -+ -+ return ret; - } - - static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst) -@@ -257,6 +278,7 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msg[], int num) - { - struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); -+ int ret; - - if (num > 32) { - dprintk("%s: too much I2C message to be transmitted (%i).\ -@@ -264,10 +286,15 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, - return -ENOMEM; - } - -- memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); -- - dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7); - -+ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ -+ memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); -+ - /* open the gate */ - dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); - mst->msg[0].addr = mst->i2c_addr; -@@ -282,7 +309,11 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, - mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; - mst->msg[num + 1].len = 4; - -- return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO; -+ ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? -+ num : -EIO); -+ -+ mutex_unlock(&mst->i2c_buffer_lock); -+ return ret; - } - - static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = { -@@ -294,6 +325,7 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msg[], int num) - { - struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); -+ int ret; - - if (num > 32) { - dprintk("%s: too much I2C message to be transmitted (%i).\ -@@ -301,10 +333,14 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, - return -ENOMEM; - } - -- memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); -- - dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); - -+ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); -+ - /* open the gate */ - dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); - mst->msg[0].addr = mst->i2c_addr; -@@ -319,7 +355,10 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, - mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; - mst->msg[num + 1].len = 4; - -- return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO; -+ ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? -+ num : -EIO); -+ mutex_unlock(&mst->i2c_buffer_lock); -+ return ret; - } - - static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = { -@@ -390,8 +429,18 @@ static int i2c_adapter_init(struct i2c_adapter *i2c_adap, - int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, - struct i2c_adapter *i2c_adap, u8 i2c_addr) - { -- u8 tx[4]; -- struct i2c_msg m = {.addr = i2c_addr >> 1,.buf = tx,.len = 4 }; -+ int ret; -+ -+ mutex_init(&mst->i2c_buffer_lock); -+ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ memset(mst->msg, 0, sizeof(struct i2c_msg)); -+ mst->msg[0].addr = i2c_addr >> 1; -+ mst->msg[0].flags = 0; -+ mst->msg[0].buf = mst->i2c_write_buffer; -+ mst->msg[0].len = 4; - - mst->device_rev = device_rev; - mst->i2c_adap = i2c_adap; -@@ -431,9 +480,12 @@ int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, - "DiBX000: could not initialize the master i2c_adapter\n"); - - /* initialize the i2c-master by closing the gate */ -- dibx000_i2c_gate_ctrl(mst, tx, 0, 0); -+ dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0); -+ -+ ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1); -+ mutex_unlock(&mst->i2c_buffer_lock); - -- return i2c_transfer(i2c_adap, &m, 1) == 1; -+ return ret; - } - - EXPORT_SYMBOL(dibx000_init_i2c_master); -diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h -index f031165..5e01147 100644 ---- a/drivers/media/dvb/frontends/dibx000_common.h -+++ b/drivers/media/dvb/frontends/dibx000_common.h -@@ -33,6 +33,7 @@ struct dibx000_i2c_master { - struct i2c_msg msg[34]; - u8 i2c_write_buffer[8]; - u8 i2c_read_buffer[2]; -+ struct mutex i2c_buffer_lock; - }; - - extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, diff --git a/media-dib0700-protect-the-dib0700-buffer-access.patch b/media-dib0700-protect-the-dib0700-buffer-access.patch deleted file mode 100644 index 109cab8ec..000000000 --- a/media-dib0700-protect-the-dib0700-buffer-access.patch +++ /dev/null @@ -1,248 +0,0 @@ -From: Olivier Grenie -Date: Mon, 1 Aug 2011 15:45:58 +0000 (-0300) -Subject: [media] dib0700: protect the dib0700 buffer access -X-Git-Tag: next-20110927~67^2~4^2~224 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=bff469f4167fdabfe15294f375577d7eadbaa1bb - -[media] dib0700: protect the dib0700 buffer access - -This patch protects the common buffer access inside the dib0700 in order -to manage concurrent access. This protection is done using mutex. - -Cc: Mauro Carvalho Chehab -Cc: Florian Mickler -Cc: stable@kernel.org -Signed-off-by: Javier Marcet -Signed-off-by: Olivier Grenie -Signed-off-by: Patrick Boettcher -[mchehab@redhat.com: dprint requires 3 arguments. Replaced by dib_info] -Signed-off-by: Mauro Carvalho Chehab ---- - -diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c -index 5eb91b4..a224e94 100644 ---- a/drivers/media/dvb/dvb-usb/dib0700_core.c -+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c -@@ -30,6 +30,11 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, - struct dib0700_state *st = d->priv; - int ret; - -+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } -+ - ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), - REQUEST_GET_VERSION, - USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, -@@ -46,6 +51,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, - if (fwtype != NULL) - *fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) | - (st->buf[14] << 8) | st->buf[15]; -+ mutex_unlock(&d->usb_mutex); - return ret; - } - -@@ -108,7 +114,12 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen - int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val) - { - struct dib0700_state *st = d->priv; -- s16 ret; -+ int ret; -+ -+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } - - st->buf[0] = REQUEST_SET_GPIO; - st->buf[1] = gpio; -@@ -116,6 +127,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ - - ret = dib0700_ctrl_wr(d, st->buf, 3); - -+ mutex_unlock(&d->usb_mutex); - return ret; - } - -@@ -125,6 +137,11 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) - int ret; - - if (st->fw_version >= 0x10201) { -+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } -+ - st->buf[0] = REQUEST_SET_USB_XFER_LEN; - st->buf[1] = (nb_ts_packets >> 8) & 0xff; - st->buf[2] = nb_ts_packets & 0xff; -@@ -132,6 +149,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) - deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets); - - ret = dib0700_ctrl_wr(d, st->buf, 3); -+ mutex_unlock(&d->usb_mutex); - } else { - deb_info("this firmware does not allow to change the USB xfer len\n"); - ret = -EIO; -@@ -208,6 +226,10 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, - - } else { - /* Write request */ -+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } - st->buf[0] = REQUEST_NEW_I2C_WRITE; - st->buf[1] = msg[i].addr << 1; - st->buf[2] = (en_start << 7) | (en_stop << 6) | -@@ -227,6 +249,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, - USB_TYPE_VENDOR | USB_DIR_OUT, - 0, 0, st->buf, msg[i].len + 4, - USB_CTRL_GET_TIMEOUT); -+ mutex_unlock(&d->usb_mutex); - if (result < 0) { - deb_info("i2c write error (status = %d)\n", result); - break; -@@ -249,6 +272,10 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, - - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; -+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } - - for (i = 0; i < num; i++) { - /* fill in the address */ -@@ -279,6 +306,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, - break; - } - } -+ mutex_unlock(&d->usb_mutex); - mutex_unlock(&d->i2c_mutex); - - return i; -@@ -337,7 +365,12 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, - u16 pll_loopdiv, u16 free_div, u16 dsuScaler) - { - struct dib0700_state *st = d->priv; -- s16 ret; -+ int ret; -+ -+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } - - st->buf[0] = REQUEST_SET_CLOCK; - st->buf[1] = (en_pll << 7) | (pll_src << 6) | -@@ -352,6 +385,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, - st->buf[9] = dsuScaler & 0xff; /* LSB */ - - ret = dib0700_ctrl_wr(d, st->buf, 10); -+ mutex_unlock(&d->usb_mutex); - - return ret; - } -@@ -360,10 +394,16 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) - { - struct dib0700_state *st = d->priv; - u16 divider; -+ int ret; - - if (scl_kHz == 0) - return -EINVAL; - -+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } -+ - st->buf[0] = REQUEST_SET_I2C_PARAM; - divider = (u16) (30000 / scl_kHz); - st->buf[1] = 0; -@@ -379,7 +419,11 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) - deb_info("setting I2C speed: %04x %04x %04x (%d kHz).", - (st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) | - st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz); -- return dib0700_ctrl_wr(d, st->buf, 8); -+ -+ ret = dib0700_ctrl_wr(d, st->buf, 8); -+ mutex_unlock(&d->usb_mutex); -+ -+ return ret; - } - - -@@ -515,6 +559,11 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) - } - } - -+ if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } -+ - st->buf[0] = REQUEST_ENABLE_VIDEO; - /* this bit gives a kind of command, - * rather than enabling something or not */ -@@ -548,7 +597,10 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) - - deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]); - -- return dib0700_ctrl_wr(adap->dev, st->buf, 4); -+ ret = dib0700_ctrl_wr(adap->dev, st->buf, 4); -+ mutex_unlock(&adap->dev->usb_mutex); -+ -+ return ret; - } - - int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) -@@ -557,6 +609,11 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) - struct dib0700_state *st = d->priv; - int new_proto, ret; - -+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } -+ - st->buf[0] = REQUEST_SET_RC; - st->buf[1] = 0; - st->buf[2] = 0; -@@ -567,23 +624,29 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) - else if (rc_type == RC_TYPE_NEC) - new_proto = 0; - else if (rc_type == RC_TYPE_RC6) { -- if (st->fw_version < 0x10200) -- return -EINVAL; -+ if (st->fw_version < 0x10200) { -+ ret = -EINVAL; -+ goto out; -+ } - - new_proto = 2; -- } else -- return -EINVAL; -+ } else { -+ ret = -EINVAL; -+ goto out; -+ } - - st->buf[1] = new_proto; - - ret = dib0700_ctrl_wr(d, st->buf, 3); - if (ret < 0) { - err("ir protocol setup failed"); -- return ret; -+ goto out; - } - - d->props.rc.core.protocol = rc_type; - -+out: -+ mutex_unlock(&d->usb_mutex); - return ret; - } - diff --git a/mmc-Always-check-for-lower-base-frequency-quirk-for-.patch b/mmc-Always-check-for-lower-base-frequency-quirk-for-.patch deleted file mode 100644 index 2d7caad83..000000000 --- a/mmc-Always-check-for-lower-base-frequency-quirk-for-.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 65ff02dff67bf26a9c27d9aa11a30eaf3d28469e Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Wed, 5 Oct 2011 11:29:57 -0400 -Subject: [PATCH] mmc: Always check for lower base frequency quirk for Ricoh - 1180:e823 - -Commit 15bed0f2f added a quirk for the e823 Ricoh card reader to lower the -base frequency. However, the quirk first checks to see if the proprietary -MMC controller is disabled, and returns if so. On some devices, such as the -Lenovo X220, the MMC controller is already disabled by firmware it seems, -but the frequency change is still needed so sdhci-pci can talk to the cards. -Since the MMC controller is disabled, the frequency fixup was never being run -on these machines. - -This moves the e823 check above the MMC controller check so that it always -gets run. - -This fixes https://bugzilla.redhat.com/show_bug.cgi?id=722509 - -Signed-off-by: Josh Boyer ---- - drivers/pci/quirks.c | 28 ++++++++++++++-------------- - 1 files changed, 14 insertions(+), 14 deletions(-) - -diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c -index 1196f61..cec4629 100644 ---- a/drivers/pci/quirks.c -+++ b/drivers/pci/quirks.c -@@ -2745,20 +2745,6 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) - /* disable must be done via function #0 */ - if (PCI_FUNC(dev->devfn)) - return; -- -- pci_read_config_byte(dev, 0xCB, &disable); -- -- if (disable & 0x02) -- return; -- -- pci_read_config_byte(dev, 0xCA, &write_enable); -- pci_write_config_byte(dev, 0xCA, 0x57); -- pci_write_config_byte(dev, 0xCB, disable | 0x02); -- pci_write_config_byte(dev, 0xCA, write_enable); -- -- dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n"); -- dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n"); -- - /* - * RICOH 0xe823 SD/MMC card reader fails to recognize - * certain types of SD/MMC cards. Lowering the SD base -@@ -2781,6 +2767,20 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) - - dev_notice(&dev->dev, "MMC controller base frequency changed to 50Mhz.\n"); - } -+ -+ pci_read_config_byte(dev, 0xCB, &disable); -+ -+ if (disable & 0x02) -+ return; -+ -+ pci_read_config_byte(dev, 0xCA, &write_enable); -+ pci_write_config_byte(dev, 0xCA, 0x57); -+ pci_write_config_byte(dev, 0xCB, disable | 0x02); -+ pci_write_config_byte(dev, 0xCA, write_enable); -+ -+ dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n"); -+ dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n"); -+ - } - DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); - DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); --- -1.7.6.4 - diff --git a/powerpc-Fix-deadlock-in-icswx-code.patch b/powerpc-Fix-deadlock-in-icswx-code.patch deleted file mode 100644 index a2ce3cf76..000000000 --- a/powerpc-Fix-deadlock-in-icswx-code.patch +++ /dev/null @@ -1,74 +0,0 @@ -From patchwork Wed Sep 14 19:43:15 2011 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: powerpc: Fix deadlock in icswx code -Date: Wed, 14 Sep 2011 09:43:15 -0000 -From: Anton Blanchard -X-Patchwork-Id: 114701 -Message-Id: <20110915054315.5e5ae062@kryten> -To: benh@kernel.crashing.org, paulus@samba.org -Cc: linuxppc-dev@lists.ozlabs.org - -The icswx code introduced an A-B B-A deadlock: - - CPU0 CPU1 - ---- ---- -lock(&anon_vma->mutex); - lock(&mm->mmap_sem); - lock(&anon_vma->mutex); -lock(&mm->mmap_sem); - -Instead of using the mmap_sem to keep mm_users constant, take the -page table spinlock. - -Signed-off-by: Anton Blanchard -Cc: - ---- - - -diff --git a/arch/powerpc/mm/mmu_context_hash64.c b/arch/powerpc/mm/mmu_context_hash64.c -index 3bafc3d..4ff587e 100644 ---- a/arch/powerpc/mm/mmu_context_hash64.c -+++ b/arch/powerpc/mm/mmu_context_hash64.c -@@ -136,8 +136,8 @@ int use_cop(unsigned long acop, struct mm_struct *mm) - if (!mm || !acop) - return -EINVAL; - -- /* We need to make sure mm_users doesn't change */ -- down_read(&mm->mmap_sem); -+ /* The page_table_lock ensures mm_users won't change under us */ -+ spin_lock(&mm->page_table_lock); - spin_lock(mm->context.cop_lockp); - - if (mm->context.cop_pid == COP_PID_NONE) { -@@ -164,7 +164,7 @@ int use_cop(unsigned long acop, struct mm_struct *mm) - - out: - spin_unlock(mm->context.cop_lockp); -- up_read(&mm->mmap_sem); -+ spin_unlock(&mm->page_table_lock); - - return ret; - } -@@ -185,8 +185,8 @@ void drop_cop(unsigned long acop, struct mm_struct *mm) - if (WARN_ON_ONCE(!mm)) - return; - -- /* We need to make sure mm_users doesn't change */ -- down_read(&mm->mmap_sem); -+ /* The page_table_lock ensures mm_users won't change under us */ -+ spin_lock(&mm->page_table_lock); - spin_lock(mm->context.cop_lockp); - - mm->context.acop &= ~acop; -@@ -213,7 +213,7 @@ void drop_cop(unsigned long acop, struct mm_struct *mm) - } - - spin_unlock(mm->context.cop_lockp); -- up_read(&mm->mmap_sem); -+ spin_unlock(&mm->page_table_lock); - } - EXPORT_SYMBOL_GPL(drop_cop); - diff --git a/sources b/sources index da0608dfe..07784d488 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -0582554c78b9979dc91223e3f4e4ec22 patch-3.1.1-rc1.bz2 +8eb92cc70e7f8d1d18a349ba8c029d7d patch-3.1.1.bz2 diff --git a/ums-realtek-driver-uses-stack-memory-for-DMA.patch b/ums-realtek-driver-uses-stack-memory-for-DMA.patch deleted file mode 100644 index 98c8b0cf9..000000000 --- a/ums-realtek-driver-uses-stack-memory-for-DMA.patch +++ /dev/null @@ -1,143 +0,0 @@ -From patchwork Tue Aug 2 05:04:11 2011 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 8bit -Subject: ums-realtek driver uses stack memory for DMA -Date: Tue, 02 Aug 2011 05:04:11 -0000 -From: Adam Cozzette -X-Patchwork-Id: 1028062 -Message-Id: <20110802050411.GC3857@[192.168.0.12]> -To: Josh Boyer -Cc: edwin_rong , wwang , - Greg Kroah-Hartman , linux-usb@vger.kernel.org, - linux-kernel@vger.kernel.org - -On Mon, Aug 01, 2011 at 05:09:06PM -0400, Josh Boyer wrote: -> Hello, -> -> We have a report that the ums-realtek driver is generating a backtrace -> due to using stack variables for DMA buffers. The backtrace is below -> and you can view the bug report here: -> https://bugzilla.redhat.com/show_bug.cgi?id=720054 -> -> Looking through the code, it seems that every call to rts51x_read_mem, -> rts51x_write_mem, and rts51x_read_status passes a stack variable to -> rts51x_bulk_transport, which then calls usb_stor_bulk_transfer_buf with -> this and generates the backtrace. It is my understanding that the -> driver should be passing variables that are not on the stack and have -> been allocated with memory that will be suitable for the DMA api (e.g. -> kmalloc). -> -> Was this missed during the initial review and is anyone working on -> adapting the driver to be compliant? - -Could you try out this patch if it looks ok to you? I have not tested it because -unfortunately I don't have the hardware. Right now it generates some compile -warnings like this one: - -drivers/usb/storage/realtek_cr.c:419:40: warning: ‘buf[0]’ may be used uninitialized in this function [-Wuninitialized] - -It think they are harmless but I didn't see an obvious way to get rid of them, -so if you have any suggestions I would be glad to hear them. - -This patch changed rts51x_read_mem, rts51x_write_mem, and rts51x_read_status to -allocate temporary buffers with kmalloc. This way stack addresses are not used -for DMA when these functions call rts51x_bulk_transport. - -Signed-off-by: Adam Cozzette - ---- -realtek_cr.c | 35 ++++++++++++++++++++++++++++++----- - 1 file changed, 30 insertions(+), 5 deletions(-) - --- -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/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c -index 34adc4b..232167a 100644 ---- a/drivers/usb/storage/realtek_cr.c -+++ b/drivers/usb/storage/realtek_cr.c -@@ -320,6 +320,11 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) - { - int retval; - u8 cmnd[12] = { 0 }; -+ u8 *buf; -+ -+ buf = kmalloc(len, GFP_NOIO); -+ if (buf == NULL) -+ return USB_STOR_TRANSPORT_ERROR; - - US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); - -@@ -331,10 +336,14 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) - cmnd[5] = (u8) len; - - retval = rts51x_bulk_transport(us, 0, cmnd, 12, -- data, len, DMA_FROM_DEVICE, NULL); -- if (retval != USB_STOR_TRANSPORT_GOOD) -+ buf, len, DMA_FROM_DEVICE, NULL); -+ if (retval != USB_STOR_TRANSPORT_GOOD) { -+ kfree(buf); - return -EIO; -+ } - -+ memcpy(data, buf, len); -+ kfree(buf); - return 0; - } - -@@ -342,6 +351,12 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) - { - int retval; - u8 cmnd[12] = { 0 }; -+ u8 *buf; -+ -+ buf = kmalloc(len, GFP_NOIO); -+ if (buf == NULL) -+ return USB_STOR_TRANSPORT_ERROR; -+ memcpy(buf, data, len); - - US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); - -@@ -353,7 +368,8 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) - cmnd[5] = (u8) len; - - retval = rts51x_bulk_transport(us, 0, cmnd, 12, -- data, len, DMA_TO_DEVICE, NULL); -+ buf, len, DMA_TO_DEVICE, NULL); -+ kfree(buf); - if (retval != USB_STOR_TRANSPORT_GOOD) - return -EIO; - -@@ -365,6 +381,11 @@ static int rts51x_read_status(struct us_data *us, - { - int retval; - u8 cmnd[12] = { 0 }; -+ u8 *buf; -+ -+ buf = kmalloc(len, GFP_NOIO); -+ if (buf == NULL) -+ return USB_STOR_TRANSPORT_ERROR; - - US_DEBUGP("%s, lun = %d\n", __func__, lun); - -@@ -372,10 +393,14 @@ static int rts51x_read_status(struct us_data *us, - cmnd[1] = 0x09; - - retval = rts51x_bulk_transport(us, lun, cmnd, 12, -- status, len, DMA_FROM_DEVICE, actlen); -- if (retval != USB_STOR_TRANSPORT_GOOD) -+ buf, len, DMA_FROM_DEVICE, actlen); -+ if (retval != USB_STOR_TRANSPORT_GOOD) { -+ kfree(buf); - return -EIO; -+ } - -+ memcpy(status, buf, len); -+ kfree(buf); - return 0; - } - From 97c2a18ca64a28e87677dc784441cb6ced0fd997 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 11 Nov 2011 19:58:39 -0500 Subject: [PATCH 210/397] Use the same naming scheme as rawhide for -stable RC kernels --- .gitignore | 1 + kernel.spec | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2a459583a..98392fa4d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ linux-*.tar.bz2 patch-*.bz2 clog *.rpm +*.orig kernel-[23].*/ diff --git a/kernel.spec b/kernel.spec index 5dc058350..a0b801d24 100644 --- a/kernel.spec +++ b/kernel.spec @@ -137,8 +137,10 @@ Summary: The Linux kernel %if 0%{?stable_rc} %define stable_rctag .rc%{stable_rc} +%define pkg_release 0%{stable_rctag}.%{fedora_build}%{?buildid}%{?dist} +%else +%define pkg_release %{fedora_build}%{?buildid}%{?dist} %endif -%define pkg_release %{fedora_build}%{?stable_rctag}%{?buildid}%{?dist} # The kernel tarball/base version %define realversion 3.%{real_sublevel} @@ -896,6 +898,11 @@ exit 1 %endif %endif +%if !%{baserelease} +echo "baserelease must be greater than zero" +exit 1 +%endif + # more sanity checking; do it quietly if [ "%{patches}" != "%%{patches}" ] ; then for patch in %{patches} ; do @@ -1858,6 +1865,10 @@ fi # and build. %changelog +* Fri Nov 11 2011 Chuck Ebbert +- Use the same naming scheme as rawhide for -stable RC kernels + (e.g. 2.6.41.1-0.rc1.1 instead of 2.6.41.1-1.rc1) + * Fri Nov 11 2011 Josh Boyer 2.6.41.1-1 - Linux 3.1.1 From 8edf5c6af419ae4887e851dff220e8bee65a6491 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 14 Nov 2011 10:03:45 -0500 Subject: [PATCH 211/397] Fix 2 CVEs CVE-2011-4131: nfs4_getfacl decoding kernel oops (rhbz 753236) CVE-2011-4132: jbd/jbd2: invalid value of first log block leads to oops (rhbz 753346) --- ...e-sb-s_first-in-journal_get_superblo.patch | 95 ++++++++++++++ kernel.spec | 15 ++- ...include-bitmap-in-nfsv4_get_acl_data.patch | 118 ++++++++++++++++++ 3 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch create mode 100644 nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch diff --git a/jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch b/jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch new file mode 100644 index 000000000..f5d82914f --- /dev/null +++ b/jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch @@ -0,0 +1,95 @@ +From 8762202dd0d6e46854f786bdb6fb3780a1625efe Mon Sep 17 00:00:00 2001 +From: Eryu Guan +Date: Tue, 1 Nov 2011 19:04:59 -0400 +Subject: [PATCH] jbd/jbd2: validate sb->s_first in journal_get_superblock() + +I hit a J_ASSERT(blocknr != 0) failure in cleanup_journal_tail() when +mounting a fsfuzzed ext3 image. It turns out that the corrupted ext3 +image has s_first = 0 in journal superblock, and the 0 is passed to +journal->j_head in journal_reset(), then to blocknr in +cleanup_journal_tail(), in the end the J_ASSERT failed. + +So validate s_first after reading journal superblock from disk in +journal_get_superblock() to ensure s_first is valid. + +The following script could reproduce it: + +fstype=ext3 +blocksize=1024 +img=$fstype.img +offset=0 +found=0 +magic="c0 3b 39 98" + +dd if=/dev/zero of=$img bs=1M count=8 +mkfs -t $fstype -b $blocksize -F $img +filesize=`stat -c %s $img` +while [ $offset -lt $filesize ] +do + if od -j $offset -N 4 -t x1 $img | grep -i "$magic";then + echo "Found journal: $offset" + found=1 + break + fi + offset=`echo "$offset+$blocksize" | bc` +done + +if [ $found -ne 1 ];then + echo "Magic \"$magic\" not found" + exit 1 +fi + +dd if=/dev/zero of=$img seek=$(($offset+23)) conv=notrunc bs=1 count=1 + +mkdir -p ./mnt +mount -o loop $img ./mnt + +Cc: Jan Kara +Signed-off-by: Eryu Guan +Signed-off-by: "Theodore Ts'o" +--- + fs/jbd/journal.c | 8 ++++++++ + fs/jbd2/journal.c | 8 ++++++++ + 2 files changed, 16 insertions(+), 0 deletions(-) + +diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c +index 9fe061f..fea8dd6 100644 +--- a/fs/jbd/journal.c ++++ b/fs/jbd/journal.c +@@ -1135,6 +1135,14 @@ static int journal_get_superblock(journal_t *journal) + goto out; + } + ++ if (be32_to_cpu(sb->s_first) == 0 || ++ be32_to_cpu(sb->s_first) >= journal->j_maxlen) { ++ printk(KERN_WARNING ++ "JBD: Invalid start block of journal: %u\n", ++ be32_to_cpu(sb->s_first)); ++ goto out; ++ } ++ + return 0; + + out: +diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c +index f24df13..d6e93d0 100644 +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -1251,6 +1251,14 @@ static int journal_get_superblock(journal_t *journal) + goto out; + } + ++ if (be32_to_cpu(sb->s_first) == 0 || ++ be32_to_cpu(sb->s_first) >= journal->j_maxlen) { ++ printk(KERN_WARNING ++ "JBD2: Invalid start block of journal: %u\n", ++ be32_to_cpu(sb->s_first)); ++ goto out; ++ } ++ + return 0; + + out: +-- +1.7.7.1 + diff --git a/kernel.spec b/kernel.spec index a0b801d24..9fb846f9d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -627,8 +627,14 @@ Patch3000: rcutree-avoid-false-quiescent-states.patch # fs fixes +#rhbz 753346 +Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch + # NFSv4 +#rhbz 753236 +Patch4000: nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch + # patches headed upstream Patch12010: add-appleir-usb-driver.patch @@ -1095,6 +1101,8 @@ ApplyPatch linux-2.6-i386-nx-emulation.patch # # ext4 +#rhbz 753346 +ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # xfs ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch @@ -1105,6 +1113,7 @@ ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch # eCryptfs # NFSv4 +ApplyPatch nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch # USB @@ -1865,6 +1874,10 @@ fi # and build. %changelog +* Mon Nov 14 2011 Josh Boyer 2.6.41.1-2 +- CVE-2011-4131: nfs4_getfacl decoding kernel oops (rhbz 753236) +- CVE-2011-4132: jbd/jbd2: invalid value of first log block leads to oops (rhbz 753346) + * Fri Nov 11 2011 Chuck Ebbert - Use the same naming scheme as rawhide for -stable RC kernels (e.g. 2.6.41.1-0.rc1.1 instead of 2.6.41.1-1.rc1) diff --git a/nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch b/nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch new file mode 100644 index 000000000..1b795e97f --- /dev/null +++ b/nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch @@ -0,0 +1,118 @@ +From: Andy Adamson + +The NFSv4 bitmap size is unbounded: a server can return an arbitrary +sized bitmap in an FATTR4_WORD0_ACL request. Replace using the +nfs4_fattr_bitmap_maxsz as a guess to the maximum bitmask returned by a server +with the inclusion of the bitmap (xdr length plus bitmasks) and the acl data +xdr length to the (cached) acl page data. + +This is a general solution to commit e5012d1f "NFSv4.1: update +nfs4_fattr_bitmap_maxsz" and fixes hitting a BUG_ON in xdr_shrink_bufhead +when getting ACLs. + +Cc:stable@xxxxxxxxxx +Signed-off-by: Andy Adamson +--- + fs/nfs/nfs4proc.c | 20 ++++++++++++++++++-- + fs/nfs/nfs4xdr.c | 15 ++++++++++++--- + 2 files changed, 30 insertions(+), 5 deletions(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index deb88d9..97014dd 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -3671,6 +3671,22 @@ static void nfs4_zap_acl_attr(struct inode *inode) + nfs4_set_cached_acl(inode, NULL); + } + ++/* ++ * The bitmap xdr length, bitmasks, and the attr xdr length are stored in ++ * the acl cache to handle variable length bitmasks. Just copy the acl data. ++ */ ++static void nfs4_copy_acl(char *buf, char *acl_data, size_t acl_len) ++{ ++ __be32 *q, *p = (__be32 *)acl_data; ++ int32_t len; ++ ++ len = be32_to_cpup(p); /* number of bitmasks */ ++ len += 2; /* add words for bitmap and attr xdr len */ ++ q = p + len; ++ len = len << 2; /* convert to bytes for acl_len math */ ++ memcpy(buf, (char *)q, acl_len - len); ++} ++ + static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_t buflen) + { + struct nfs_inode *nfsi = NFS_I(inode); +@@ -3688,7 +3704,7 @@ static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_ + ret = -ERANGE; /* see getxattr(2) man page */ + if (acl->len > buflen) + goto out; +- memcpy(buf, acl->data, acl->len); ++ nfs4_copy_acl(buf, acl->data, acl->len); + out_len: + ret = acl->len; + out: +@@ -3763,7 +3779,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu + if (res.acl_len > buflen) + goto out_free; + if (localpage) +- memcpy(buf, resp_buf, res.acl_len); ++ nfs4_copy_acl(buf, resp_buf, res.acl_len); + } + ret = res.acl_len; + out_free: +diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c +index f9fd96d..9c07380 100644 +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -2513,7 +2513,7 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, + encode_compound_hdr(xdr, req, &hdr); + encode_sequence(xdr, &args->seq_args, &hdr); + encode_putfh(xdr, args->fh, &hdr); +- replen = hdr.replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1; ++ replen = hdr.replen + op_decode_hdr_maxsz + 1; + encode_getattr_two(xdr, FATTR4_WORD0_ACL, 0, &hdr); + + xdr_inline_pages(&req->rq_rcv_buf, replen << 2, +@@ -4955,7 +4955,7 @@ decode_restorefh(struct xdr_stream *xdr) + static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, + size_t *acl_len) + { +- __be32 *savep; ++ __be32 *savep, *bm_p; + uint32_t attrlen, + bitmap[3] = {0}; + struct kvec *iov = req->rq_rcv_buf.head; +@@ -4964,6 +4964,7 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, + *acl_len = 0; + if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) + goto out; ++ bm_p = xdr->p; + if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) + goto out; + if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) +@@ -4972,12 +4973,20 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, + if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) + return -EIO; + if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { +- size_t hdrlen; ++ size_t hdrlen, len; + u32 recvd; + ++ /*The bitmap (xdr len + bitmasks) and the attr xdr len words ++ * are stored with the acl data to handle the problem of ++ * variable length bitmasks.*/ ++ xdr->p = bm_p; ++ len = be32_to_cpup(bm_p); ++ len += 2; /* add bitmap and attr xdr len words */ ++ + /* We ignore &savep and don't do consistency checks on + * the attr length. Let userspace figure it out.... */ + hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; ++ attrlen += len << 2; /* attrlen is in bytes */ + recvd = req->rq_rcv_buf.len - hdrlen; + if (attrlen > recvd) { + dprintk("NFS: server cheating in getattr" +-- +1.7.6.4 From c98134264ba18987036cadf67c3f8b5a7923a1bc Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 14 Nov 2011 13:09:12 -0500 Subject: [PATCH 212/397] Patch from Joshua Roys to add rtl8192* to modules.networking (rhbz 753645) --- kernel.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 9fb846f9d..4c1d71d88 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1491,7 +1491,7 @@ BuildKernel() { } collect_modules_list networking \ - 'register_netdev|ieee80211_register_hw|usbnet_probe|phy_driver_register|rt2x00(pci|usb)_probe' + 'register_netdev|ieee80211_register_hw|usbnet_probe|phy_driver_register|rt(l_|2x00)(pci|usb)_probe' collect_modules_list block \ 'ata_scsi_ioctl|scsi_add_host|scsi_add_host_with_dma|blk_init_queue|register_mtd_blktrans|scsi_esp_register|scsi_register_device_handler' collect_modules_list drm \ @@ -1874,6 +1874,9 @@ fi # and build. %changelog +* Mon Nov 14 2011 Josh Boyer +- Patch from Joshua Roys to add rtl8192* to modules.networking (rhbz 753645) + * Mon Nov 14 2011 Josh Boyer 2.6.41.1-2 - CVE-2011-4131: nfs4_getfacl decoding kernel oops (rhbz 753236) - CVE-2011-4132: jbd/jbd2: invalid value of first log block leads to oops (rhbz 753346) From 14a0317175392b5ab2120e864690b7caf251e486 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 14 Nov 2011 13:19:24 -0500 Subject: [PATCH 213/397] Add patch for wacom tablets for Bastien Nocera (upstream 3797ef6b6) --- ...m-Set-input-bits-before-registration.patch | 131 ++++++++++++++++++ kernel.spec | 5 +- 2 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 HID-wacom-Set-input-bits-before-registration.patch diff --git a/HID-wacom-Set-input-bits-before-registration.patch b/HID-wacom-Set-input-bits-before-registration.patch new file mode 100644 index 000000000..3cd178631 --- /dev/null +++ b/HID-wacom-Set-input-bits-before-registration.patch @@ -0,0 +1,131 @@ +From b28ae436288861916de0019a81b9817366fe35a9 Mon Sep 17 00:00:00 2001 +From: David Herrmann +Date: Sat, 8 Oct 2011 23:20:17 +0200 +Subject: [PATCH] HID: wacom: Set input bits before registration + +We shouldn't change the event flags of input devices after they get registered. +Otherwise, udev will not get notified of these flags and cannot setup the +devices properly. +This fixes the probing to set the input event flags on the input_mapped callback +instead of the probe function. + +Reported-by: Bastien Nocera +Signed-off-by: David Herrmann +Tested-by: Bastien Nocera +Signed-off-by: Bastien Nocera +Signed-off-by: Jiri Kosina +--- + drivers/hid/hid-wacom.c | 80 +++++++++++++++++++++++++--------------------- + 1 files changed, 43 insertions(+), 37 deletions(-) + +diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c +index 72ca689..1492728 100644 +--- a/drivers/hid/hid-wacom.c ++++ b/drivers/hid/hid-wacom.c +@@ -304,11 +304,51 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, + return 1; + } + ++static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, ++ struct hid_field *field, struct hid_usage *usage, unsigned long **bit, ++ int *max) ++{ ++ struct input_dev *input = hi->input; ++ ++ __set_bit(INPUT_PROP_POINTER, input->propbit); ++ ++ /* Basics */ ++ input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); ++ ++ __set_bit(REL_WHEEL, input->relbit); ++ ++ __set_bit(BTN_TOOL_PEN, input->keybit); ++ __set_bit(BTN_TOUCH, input->keybit); ++ __set_bit(BTN_STYLUS, input->keybit); ++ __set_bit(BTN_STYLUS2, input->keybit); ++ __set_bit(BTN_LEFT, input->keybit); ++ __set_bit(BTN_RIGHT, input->keybit); ++ __set_bit(BTN_MIDDLE, input->keybit); ++ ++ /* Pad */ ++ input->evbit[0] |= BIT(EV_MSC); ++ ++ __set_bit(MSC_SERIAL, input->mscbit); ++ ++ __set_bit(BTN_0, input->keybit); ++ __set_bit(BTN_1, input->keybit); ++ __set_bit(BTN_TOOL_FINGER, input->keybit); ++ ++ /* Distance, rubber and mouse */ ++ __set_bit(BTN_TOOL_RUBBER, input->keybit); ++ __set_bit(BTN_TOOL_MOUSE, input->keybit); ++ ++ input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); ++ input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); ++ input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); ++ input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); ++ ++ return 0; ++} ++ + static int wacom_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { +- struct hid_input *hidinput; +- struct input_dev *input; + struct wacom_data *wdata; + int ret; + +@@ -370,41 +410,6 @@ static int wacom_probe(struct hid_device *hdev, + goto err_ac; + } + #endif +- hidinput = list_entry(hdev->inputs.next, struct hid_input, list); +- input = hidinput->input; +- +- __set_bit(INPUT_PROP_POINTER, input->propbit); +- +- /* Basics */ +- input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); +- +- __set_bit(REL_WHEEL, input->relbit); +- +- __set_bit(BTN_TOOL_PEN, input->keybit); +- __set_bit(BTN_TOUCH, input->keybit); +- __set_bit(BTN_STYLUS, input->keybit); +- __set_bit(BTN_STYLUS2, input->keybit); +- __set_bit(BTN_LEFT, input->keybit); +- __set_bit(BTN_RIGHT, input->keybit); +- __set_bit(BTN_MIDDLE, input->keybit); +- +- /* Pad */ +- input->evbit[0] |= BIT(EV_MSC); +- +- __set_bit(MSC_SERIAL, input->mscbit); +- +- __set_bit(BTN_0, input->keybit); +- __set_bit(BTN_1, input->keybit); +- __set_bit(BTN_TOOL_FINGER, input->keybit); +- +- /* Distance, rubber and mouse */ +- __set_bit(BTN_TOOL_RUBBER, input->keybit); +- __set_bit(BTN_TOOL_MOUSE, input->keybit); +- +- input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); +- input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); +- input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); +- input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); + + return 0; + +@@ -448,6 +453,7 @@ static struct hid_driver wacom_driver = { + .probe = wacom_probe, + .remove = wacom_remove, + .raw_event = wacom_raw_event, ++ .input_mapped = wacom_input_mapped, + }; + + static int __init wacom_init(void) +-- +1.7.7.1 + diff --git a/kernel.spec b/kernel.spec index 4c1d71d88..715d6464e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -646,6 +646,7 @@ Patch12025: rcu-avoid-just-onlined-cpu-resched.patch Patch12026: block-stray-block-put-after-teardown.patch Patch12027: usb-add-quirk-for-logitech-webcams.patch Patch12030: epoll-limit-paths.patch +Patch12031: HID-wacom-Set-input-bits-before-registration.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch @@ -1218,6 +1219,7 @@ ApplyPatch epoll-limit-paths.patch ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch ApplyPatch block-stray-block-put-after-teardown.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch +ApplyPatch HID-wacom-Set-input-bits-before-registration.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -1876,6 +1878,7 @@ fi %changelog * Mon Nov 14 2011 Josh Boyer - Patch from Joshua Roys to add rtl8192* to modules.networking (rhbz 753645) +- Add patch for wacom tablets for Bastien Nocera (upstream 3797ef6b6) * Mon Nov 14 2011 Josh Boyer 2.6.41.1-2 - CVE-2011-4131: nfs4_getfacl decoding kernel oops (rhbz 753236) From 824676c8c8e78032e213c47be9b8b9c75fcef57a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 14 Nov 2011 13:56:46 -0500 Subject: [PATCH 214/397] Add patch to fix ip6_tunnel naming (rhbz 751165) --- ...-parms.name-after-register_netdevice.patch | 76 +++++++++++++++++++ kernel.spec | 7 ++ 2 files changed, 83 insertions(+) create mode 100644 ip6_tunnel-copy-parms.name-after-register_netdevice.patch diff --git a/ip6_tunnel-copy-parms.name-after-register_netdevice.patch b/ip6_tunnel-copy-parms.name-after-register_netdevice.patch new file mode 100644 index 000000000..d3bb6a24e --- /dev/null +++ b/ip6_tunnel-copy-parms.name-after-register_netdevice.patch @@ -0,0 +1,76 @@ +From 731abb9cb27aef6013ce60808a04e04a545f3f4e Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Thu, 10 Nov 2011 15:10:23 +0000 +Subject: [PATCH] ip6_tunnel: copy parms.name after register_netdevice + +Commit 1c5cae815d removed an explicit call to dev_alloc_name in ip6_tnl_create +because register_netdevice will now create a valid name. This works for the +net_device itself. + +However the tunnel keeps a copy of the name in the parms structure for the +ip6_tnl associated with the tunnel. parms.name is set by copying the net_device +name in ip6_tnl_dev_init_gen. That function is called from ip6_tnl_dev_init in +ip6_tnl_create, but it is done before register_netdevice is called so the name +is set to a bogus value in the parms.name structure. + +This shows up if you do a simple tunnel add, followed by a tunnel show: + +[root@localhost ~]# ip -6 tunnel add remote fec0::100 local fec0::200 +[root@localhost ~]# ip -6 tunnel show +ip6tnl0: ipv6/ipv6 remote :: local :: encaplimit 0 hoplimit 0 tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000) +ip6tnl%d: ipv6/ipv6 remote fec0::100 local fec0::200 encaplimit 4 hoplimit 64 tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000) +[root@localhost ~]# + +Fix this by moving the strcpy out of ip6_tnl_dev_init_gen, and calling it after +register_netdevice has successfully returned. + +Cc: stable@vger.kernel.org +Signed-off-by: Josh Boyer +Signed-off-by: David S. Miller +--- + net/ipv6/ip6_tunnel.c | 8 +++++++- + 1 files changed, 7 insertions(+), 1 deletions(-) + +diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c +index bdc15c9..4e2e9ff 100644 +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -289,6 +289,8 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p) + if ((err = register_netdevice(dev)) < 0) + goto failed_free; + ++ strcpy(t->parms.name, dev->name); ++ + dev_hold(dev); + ip6_tnl_link(ip6n, t); + return t; +@@ -1407,7 +1409,6 @@ ip6_tnl_dev_init_gen(struct net_device *dev) + struct ip6_tnl *t = netdev_priv(dev); + + t->dev = dev; +- strcpy(t->parms.name, dev->name); + dev->tstats = alloc_percpu(struct pcpu_tstats); + if (!dev->tstats) + return -ENOMEM; +@@ -1487,6 +1488,7 @@ static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) + static int __net_init ip6_tnl_init_net(struct net *net) + { + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); ++ struct ip6_tnl *t = NULL; + int err; + + ip6n->tnls[0] = ip6n->tnls_wc; +@@ -1507,6 +1509,10 @@ static int __net_init ip6_tnl_init_net(struct net *net) + err = register_netdev(ip6n->fb_tnl_dev); + if (err < 0) + goto err_register; ++ ++ t = netdev_priv(ip6n->fb_tnl_dev); ++ ++ strcpy(t->parms.name, ip6n->fb_tnl_dev->name); + return 0; + + err_register: +-- +1.7.6.2 + diff --git a/kernel.spec b/kernel.spec index 715d6464e..bc483b342 100644 --- a/kernel.spec +++ b/kernel.spec @@ -655,6 +655,9 @@ Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch13009: hvcs_pi_buf_alloc.patch +#rhbz 751165 +Patch13010: ip6_tunnel-copy-parms.name-after-register_netdevice.patch + Patch20000: utrace.patch # Flattened devicetree support @@ -1229,6 +1232,9 @@ ApplyPatch efi-dont-map-boot-services-on-32bit.patch ApplyPatch hvcs_pi_buf_alloc.patch +#rhbz 751165 +ApplyPatch ip6_tunnel-copy-parms.name-after-register_netdevice.patch + ApplyPatch media-dib0700-correct-error-message.patch # utrace. @@ -1879,6 +1885,7 @@ fi * Mon Nov 14 2011 Josh Boyer - Patch from Joshua Roys to add rtl8192* to modules.networking (rhbz 753645) - Add patch for wacom tablets for Bastien Nocera (upstream 3797ef6b6) +- Add patch to fix ip6_tunnel naming (rhbz 751165) * Mon Nov 14 2011 Josh Boyer 2.6.41.1-2 - CVE-2011-4131: nfs4_getfacl decoding kernel oops (rhbz 753236) From 12d4c0b4e00c5507e0961703b09f3ccf7a6785f2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 14 Nov 2011 14:26:26 -0500 Subject: [PATCH 215/397] Quite a warning in apm_cpu_idle (rhbz 753776) WARN_ONCE is now the top thing on my "BIGGEST WASTE OF TIME" list. It changes daily though. --- kernel.spec | 3 +++ quite-apm.patch | 13 +++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 quite-apm.patch diff --git a/kernel.spec b/kernel.spec index bc483b342..f86b030ed 100644 --- a/kernel.spec +++ b/kernel.spec @@ -581,6 +581,7 @@ Patch470: die-floppy-die.patch Patch471: floppy-drop-disable_hlt-warning.patch Patch510: linux-2.6-silence-noise.patch +Patch520: quite-apm.patch Patch530: linux-2.6-silence-fbcon-logo.patch Patch700: linux-2.6-e1000-ich9-montevina.patch @@ -1200,6 +1201,7 @@ ApplyPatch linux-2.6-intel-iommu-igfx.patch # silence the ACPI blacklist code ApplyPatch linux-2.6-silence-acpi-blacklist.patch +ApplyPatch quite-apm.patch # V4L/DVB updates/fixes/experimental drivers # apply if non-empty @@ -1886,6 +1888,7 @@ fi - Patch from Joshua Roys to add rtl8192* to modules.networking (rhbz 753645) - Add patch for wacom tablets for Bastien Nocera (upstream 3797ef6b6) - Add patch to fix ip6_tunnel naming (rhbz 751165) +- Quite warning in apm_cpu_idle (rhbz 753776) * Mon Nov 14 2011 Josh Boyer 2.6.41.1-2 - CVE-2011-4131: nfs4_getfacl decoding kernel oops (rhbz 753236) diff --git a/quite-apm.patch b/quite-apm.patch new file mode 100644 index 000000000..9325ae55b --- /dev/null +++ b/quite-apm.patch @@ -0,0 +1,13 @@ +diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c +index a46bd38..416dd12 100644 +--- a/arch/x86/kernel/apm_32.c ++++ b/arch/x86/kernel/apm_32.c +@@ -903,7 +903,7 @@ static void apm_cpu_idle(void) + unsigned int jiffies_since_last_check = jiffies - last_jiffies; + unsigned int bucket; + +- WARN_ONCE(1, "deprecated apm_cpu_idle will be deleted in 2012"); ++ printk(KERN_INFO "deprecated apm_cpu_idle will be deleted in 2012"); + recalc: + if (jiffies_since_last_check > IDLE_CALC_LIMIT) { + use_apm_idle = 0; From b4cf83d3b8fcd978c7ff581208c470d78b4b6fba Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 15 Nov 2011 17:15:30 -0500 Subject: [PATCH 216/397] mm: Do not stall in synchronous compaction for THP allocations --- kernel.spec | 5 + ...onous-compaction-for-THP-allocations.patch | 115 ++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch diff --git a/kernel.spec b/kernel.spec index f86b030ed..703893cfd 100644 --- a/kernel.spec +++ b/kernel.spec @@ -668,6 +668,7 @@ Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch #rhbz #735946 Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch +Patch21022: mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch #rhbz 748691 Patch21030: be2net-non-member-vlan-pkts-not-received-in-promisco.patch @@ -1245,6 +1246,7 @@ ApplyPatch utrace.patch #rhbz #735946 ApplyPatch 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch +ApplyPatch mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch #rhbz 748691 ApplyPatch be2net-non-member-vlan-pkts-not-received-in-promisco.patch @@ -1884,6 +1886,9 @@ fi # and build. %changelog +* Tue Nov 15 2011 Dave Jones +- mm: Do not stall in synchronous compaction for THP allocations + * Mon Nov 14 2011 Josh Boyer - Patch from Joshua Roys to add rtl8192* to modules.networking (rhbz 753645) - Add patch for wacom tablets for Bastien Nocera (upstream 3797ef6b6) diff --git a/mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch b/mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch new file mode 100644 index 000000000..6202341ae --- /dev/null +++ b/mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch @@ -0,0 +1,115 @@ +https://lkml.org/lkml/2011/11/10/173 + +Date Thu, 10 Nov 2011 10:06:16 +0000 +From Mel Gorman <> +Subject [PATCH] mm: Do not stall in synchronous compaction for THP allocations + + +Occasionally during large file copies to slow storage, there are still +reports of user-visible stalls when THP is enabled. Reports on this +have been intermittent and not reliable to reproduce locally but; + +Andy Isaacson reported a problem copying to VFAT on SD Card + https://lkml.org/lkml/2011/11/7/2 + + In this case, it was stuck in munmap for betwen 20 and 60 + seconds in compaction. It is also possible that khugepaged + was holding mmap_sem on this process if CONFIG_NUMA was set. + +Johannes Weiner reported stalls on USB + https://lkml.org/lkml/2011/7/25/378 + + In this case, there is no stack trace but it looks like the + same problem. The USB stick may have been using NTFS as a + filesystem based on other work done related to writing back + to USB around the same time. + +Internally in SUSE, I received a bug report related to stalls in firefox + when using Java and Flash heavily while copying from NFS + to VFAT on USB. It has not been confirmed to be the same problem + but if it looks like a duck and quacks like a duck..... +In the past, commit [11bc82d6: mm: compaction: Use async migration for +__GFP_NO_KSWAPD and enforce no writeback] forced that sync compaction +would never be used for THP allocations. This was reverted in commit +[c6a140bf: mm/compaction: reverse the change that forbade sync +migraton with __GFP_NO_KSWAPD] on the grounds that it was uncertain +it was beneficial. + +While user-visible stalls do not happen for me when writing to USB, +I setup a test running postmark while short-lived processes created +anonymous mapping. The objective was to exercise the paths that +allocate transparent huge pages. I then logged when processes were +stalled for more than 1 second, recorded a stack strace and did some +analysis to aggregate unique "stall events" which revealed + +Time stalled in this event: 47369 ms +Event count: 20 +usemem sleep_on_page 3690 ms +usemem sleep_on_page 2148 ms +usemem sleep_on_page 1534 ms +usemem sleep_on_page 1518 ms +usemem sleep_on_page 1225 ms +usemem sleep_on_page 2205 ms +usemem sleep_on_page 2399 ms +usemem sleep_on_page 2398 ms +usemem sleep_on_page 3760 ms +usemem sleep_on_page 1861 ms +usemem sleep_on_page 2948 ms +usemem sleep_on_page 1515 ms +usemem sleep_on_page 1386 ms +usemem sleep_on_page 1882 ms +usemem sleep_on_page 1850 ms +usemem sleep_on_page 3715 ms +usemem sleep_on_page 3716 ms +usemem sleep_on_page 4846 ms +usemem sleep_on_page 1306 ms +usemem sleep_on_page 1467 ms +[] wait_on_page_bit+0x6c/0x80 +[] unmap_and_move+0x1bf/0x360 +[] migrate_pages+0xa2/0x1b0 +[] compact_zone+0x1f3/0x2f0 +[] compact_zone_order+0xa8/0xf0 +[] try_to_compact_pages+0xdf/0x110 +[] __alloc_pages_direct_compact+0xda/0x1a0 +[] __alloc_pages_slowpath+0x55d/0x7a0 +[] __alloc_pages_nodemask+0x1b1/0x1c0 +[] alloc_pages_vma+0x9b/0x160 +[] do_huge_pmd_anonymous_page+0x160/0x270 +[] do_page_fault+0x207/0x4c0 +[] page_fault+0x25/0x30 +The stall times are approximate at best but the estimates represent 25% +of the worst stalls and even if the estimates are off by a factor of +10, it's severe. + +This patch once again prevents sync migration for transparent +hugepage allocations as it is preferable to fail a THP allocation +than stall. It was suggested that __GFP_NORETRY be used instead of +__GFP_NO_KSWAPD. This would look less like a special case but would +still cause compaction to run at least once with sync compaction. + +If accepted, this is a -stable candidate. + +Reported-by: Andy Isaacson +Reported-by: Johannes Weiner +Signed-off-by: Mel Gorman +--- + +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 9dd443d..84bf962 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -2168,7 +2168,13 @@ rebalance: + sync_migration); + if (page) + goto got_pg; +- sync_migration = true; ++ ++ /* ++ * Do not use sync migration for transparent hugepage allocations as ++ * it could stall writing back pages which is far worse than simply ++ * failing to promote a page. ++ */ ++ sync_migration = !(gfp_mask & __GFP_NO_KSWAPD); + + /* Try direct reclaim and then allocating */ + page = __alloc_pages_direct_reclaim(gfp_mask, order, From a770668d850105eeb6a702ddcd2239a0b42b94f8 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Wed, 16 Nov 2011 11:23:44 -0500 Subject: [PATCH 217/397] Work around #663080 on s390x and restore building perf there. --- kernel.spec | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 703893cfd..d9ff491e6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -304,7 +304,6 @@ Summary: The Linux kernel %define image_install_path boot %define make_target image %define kernel_image arch/s390/boot/image -%define with_perf 0 %endif %ifarch sparc64 @@ -1582,7 +1581,7 @@ BuildKernel %make_target %kernel_image smp %global perf_make \ make %{?_smp_mflags} -C tools/perf -s V=1 HAVE_CPLUS_DEMANGLE=1 prefix=%{_prefix} %if %{with_perf} -%{perf_make} all +%{perf_make} EXTRA_CFLAGS="-Wno-error=array-bounds" all %{perf_make} man || %{doc_build_fail} %endif @@ -1886,6 +1885,9 @@ fi # and build. %changelog +* Wed Nov 16 2011 Kyle McMartin +- Work around #663080 on s390x and restore building perf there. + * Tue Nov 15 2011 Dave Jones - mm: Do not stall in synchronous compaction for THP allocations From c8de25547e1a92dbad94449c75f8d2ce4c5ec46f Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Wed, 16 Nov 2011 14:35:06 -0500 Subject: [PATCH 218/397] Move EXTRA_CFLAGS into %{perf_make} --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index d9ff491e6..28e8eb9c3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1579,9 +1579,9 @@ BuildKernel %make_target %kernel_image smp %endif %global perf_make \ - make %{?_smp_mflags} -C tools/perf -s V=1 HAVE_CPLUS_DEMANGLE=1 prefix=%{_prefix} + make %{?_smp_mflags} -C tools/perf -s V=1 HAVE_CPLUS_DEMANGLE=1 EXTRA_CFLAGS="-Wno-error=array-bounds" prefix=%{_prefix} %if %{with_perf} -%{perf_make} EXTRA_CFLAGS="-Wno-error=array-bounds" all +%{perf_make} all %{perf_make} man || %{doc_build_fail} %endif From f42441ac992e8e4451b60e50534ca8b6c2814cd2 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 16 Nov 2011 15:59:46 -0500 Subject: [PATCH 219/397] Fix thinko in get_random_bytes(). --- get_random_bytes-consecutive-words.patch | 40 ++++++++++++++++++++++++ kernel.spec | 7 +++++ 2 files changed, 47 insertions(+) create mode 100644 get_random_bytes-consecutive-words.patch diff --git a/get_random_bytes-consecutive-words.patch b/get_random_bytes-consecutive-words.patch new file mode 100644 index 000000000..9c70424ba --- /dev/null +++ b/get_random_bytes-consecutive-words.patch @@ -0,0 +1,40 @@ +From: "Luck, Tony" +To: Linus Torvalds , + "H. Peter Anvin" , Ingo Molnar , + Thomas Gleixner , + Fenghua Yu , Matt Mackall , + Herbert Xu , + "Theodore Ts'o" , Jeff Garzik , + Arjan van de Ven , linux-kernel@vger.kernel.org +Subject: [PATCH] fix typo/thinko in get_random_bytes() +Date: Wed, 16 Nov 2011 10:50:56 -0800 +Message-Id: <4ec4061010261a4cb0@agluck-desktop.sc.intel.com> + +If there is an architecture-specific random number generator we use +it to acquire randomness one "long" at a time. We should put these +random words into consecutive words in the result buffer - not just +overwrite the first word again and again. + +Signed-off-by: Tony Luck + +--- + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 63e19ba..6035ab8 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -941,7 +941,7 @@ void get_random_bytes(void *buf, int nbytes) + if (!arch_get_random_long(&v)) + break; + +- memcpy(buf, &v, chunk); ++ memcpy(p, &v, chunk); + p += chunk; + nbytes -= chunk; + } +-- +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 28e8eb9c3..9794219ce 100644 --- a/kernel.spec +++ b/kernel.spec @@ -635,6 +635,8 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch #rhbz 753236 Patch4000: nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch +Patch10000: get_random_bytes-consecutive-words.patch + # patches headed upstream Patch12010: add-appleir-usb-driver.patch @@ -1219,6 +1221,8 @@ ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch add-appleir-usb-driver.patch +ApplyPatch get_random_bytes-consecutive-words.patch + ApplyPatch udlfb-bind-framebuffer-to-interface.patch ApplyPatch epoll-limit-paths.patch ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch @@ -1885,6 +1889,9 @@ fi # and build. %changelog +* Wed Nov 16 2011 Dave Jones +- Fix thinko in get_random_bytes(). + * Wed Nov 16 2011 Kyle McMartin - Work around #663080 on s390x and restore building perf there. From eab9ba1eb4435834b89ce8aab38e65df0bd18f79 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 16 Nov 2011 16:03:19 -0500 Subject: [PATCH 220/397] Revert "Fix thinko in get_random_bytes()." This reverts commit f42441ac992e8e4451b60e50534ca8b6c2814cd2. Doesn't affect 3.1 --- get_random_bytes-consecutive-words.patch | 40 ------------------------ kernel.spec | 7 ----- 2 files changed, 47 deletions(-) delete mode 100644 get_random_bytes-consecutive-words.patch diff --git a/get_random_bytes-consecutive-words.patch b/get_random_bytes-consecutive-words.patch deleted file mode 100644 index 9c70424ba..000000000 --- a/get_random_bytes-consecutive-words.patch +++ /dev/null @@ -1,40 +0,0 @@ -From: "Luck, Tony" -To: Linus Torvalds , - "H. Peter Anvin" , Ingo Molnar , - Thomas Gleixner , - Fenghua Yu , Matt Mackall , - Herbert Xu , - "Theodore Ts'o" , Jeff Garzik , - Arjan van de Ven , linux-kernel@vger.kernel.org -Subject: [PATCH] fix typo/thinko in get_random_bytes() -Date: Wed, 16 Nov 2011 10:50:56 -0800 -Message-Id: <4ec4061010261a4cb0@agluck-desktop.sc.intel.com> - -If there is an architecture-specific random number generator we use -it to acquire randomness one "long" at a time. We should put these -random words into consecutive words in the result buffer - not just -overwrite the first word again and again. - -Signed-off-by: Tony Luck - ---- - -diff --git a/drivers/char/random.c b/drivers/char/random.c -index 63e19ba..6035ab8 100644 ---- a/drivers/char/random.c -+++ b/drivers/char/random.c -@@ -941,7 +941,7 @@ void get_random_bytes(void *buf, int nbytes) - if (!arch_get_random_long(&v)) - break; - -- memcpy(buf, &v, chunk); -+ memcpy(p, &v, chunk); - p += chunk; - nbytes -= chunk; - } --- -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 9794219ce..28e8eb9c3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -635,8 +635,6 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch #rhbz 753236 Patch4000: nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch -Patch10000: get_random_bytes-consecutive-words.patch - # patches headed upstream Patch12010: add-appleir-usb-driver.patch @@ -1221,8 +1219,6 @@ ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch add-appleir-usb-driver.patch -ApplyPatch get_random_bytes-consecutive-words.patch - ApplyPatch udlfb-bind-framebuffer-to-interface.patch ApplyPatch epoll-limit-paths.patch ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch @@ -1889,9 +1885,6 @@ fi # and build. %changelog -* Wed Nov 16 2011 Dave Jones -- Fix thinko in get_random_bytes(). - * Wed Nov 16 2011 Kyle McMartin - Work around #663080 on s390x and restore building perf there. From 8491a176750a171fc7933e71b82fcce049bcbaf0 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Fri, 18 Nov 2011 18:10:17 -0600 Subject: [PATCH 221/397] arm config changes to enable selinux to work everywhere --- config-arm-generic | 3 +++ config-arm-omap-generic | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config-arm-generic b/config-arm-generic index 307c66d68..12ae3c30f 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -156,6 +156,9 @@ CONFIG_MMC_SDHCI_PXAV2=m CONFIG_FTGMAC100=m +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +CONFIG_LSM_MMAP_MIN_ADDR=32768 + # disable TPM on arm at least on the trimslices it causes havoc # CONFIG_TCG_TPM is not set # CONFIG_IMA is not set diff --git a/config-arm-omap-generic b/config-arm-omap-generic index 8c3ae6a24..16e665329 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -147,7 +147,6 @@ CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y CONFIG_HW_PERF_EVENTS=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_KSM is not set -CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 # CONFIG_CC_STACKPROTECTOR is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 @@ -1063,8 +1062,6 @@ CONFIG_EARLY_PRINTK=y CONFIG_OC_ETM=y # CONFIG_KEYS_DEBUG_PROC_KEYS is not set # CONFIG_SECURITY_NETWORK_XFRM is not set -CONFIG_LSM_MMAP_MIN_ADDR=0 -CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0 # CONFIG_IMA is not set CONFIG_CRYPTO_AEAD=m CONFIG_CRYPTO_RNG=m From 202bf795d8d263ef4f4ad96cd9ce89a0d09af32c Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Fri, 18 Nov 2011 18:16:31 -0600 Subject: [PATCH 222/397] enable selinux to work on arm --- kernel.spec | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel.spec b/kernel.spec index 28e8eb9c3..fbeba341c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1885,6 +1885,9 @@ fi # and build. %changelog +* Fri Nov 18 2011 Dennis Gilmore +- enable selinux to work on arm + * Wed Nov 16 2011 Kyle McMartin - Work around #663080 on s390x and restore building perf there. From 1933ff1b6a042990e6ab404059eff7ec219f9d95 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sat, 19 Nov 2011 04:11:38 -0500 Subject: [PATCH 223/397] Linux 3.1.2-rc1 (Fedora 2.6.41.2-rc1) --- kernel.spec | 9 ++++++--- sources | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index fbeba341c..6bf4812ce 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,9 +51,9 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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} @@ -1885,6 +1885,9 @@ fi # and build. %changelog +* Sat Nov 19 2011 Chuck Ebbert 2.6.41.2-0.rc1.1 +- Linux 3.1.2-rc1 (Fedora 2.6.41.2-rc1) + * Fri Nov 18 2011 Dennis Gilmore - enable selinux to work on arm diff --git a/sources b/sources index 07784d488..346980c26 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 8eb92cc70e7f8d1d18a349ba8c029d7d patch-3.1.1.bz2 +24339b23f92d963d851ee042564cdb1c patch-3.1.2-rc1.bz2 From 73d229109dd5709edf8491b93ee0cc7cdb5962c6 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Tue, 22 Nov 2011 03:21:25 -0500 Subject: [PATCH 224/397] Linux 3.1.2 (Fedora 2.6.41.2) --- kernel.spec | 5 ++++- sources | 3 +-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 6bf4812ce..e96051a11 100644 --- a/kernel.spec +++ b/kernel.spec @@ -53,7 +53,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} @@ -1885,6 +1885,9 @@ fi # and build. %changelog +* Tue Nov 22 2011 Chuck Ebbert 2.6.41.2-1 +- Linux 3.1.2 (Fedora 2.6.41.2) + * Sat Nov 19 2011 Chuck Ebbert 2.6.41.2-0.rc1.1 - Linux 3.1.2-rc1 (Fedora 2.6.41.2-rc1) diff --git a/sources b/sources index 346980c26..a72aa471b 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -8eb92cc70e7f8d1d18a349ba8c029d7d patch-3.1.1.bz2 -24339b23f92d963d851ee042564cdb1c patch-3.1.2-rc1.bz2 +7487d8e6f00c077f6e15d6f4f9947c30 patch-3.1.2.bz2 From 03734ddcf27f5a8b9476e8dda176a1df46ab4af9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 22 Nov 2011 10:36:27 -0500 Subject: [PATCH 225/397] Fix the baserelease sanity check We need to explicitly check for 0, so that we can do things like setting baserelease to 1.1 for scratch builds, etc. --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index e96051a11..5bae68563 100644 --- a/kernel.spec +++ b/kernel.spec @@ -909,7 +909,7 @@ exit 1 %endif %endif -%if !%{baserelease} +%if "%{baserelease}" == "0" echo "baserelease must be greater than zero" exit 1 %endif From 99b25750854845e1d2fd0700456c7f856900b25c Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 23 Nov 2011 08:51:38 -0500 Subject: [PATCH 226/397] Linux 3.1.3-rc1 (Fedora 2.6.41.3-rc1) Comment out merged patches: usb-add-quirk-for-logitech-webcams.patch ip6_tunnel-copy-parms.name-after-register_netdevice.patch --- .gitignore | 3 +-- kernel.spec | 14 ++++++++++---- sources | 1 + 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 98392fa4d..edb6bec0a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ -linux-*.tar.bz2 -patch-*.bz2 clog +*.bz2 *.rpm *.orig kernel-[23].*/ diff --git a/kernel.spec b/kernel.spec index 5bae68563..2e94d239f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,9 +51,9 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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} @@ -1223,7 +1223,7 @@ ApplyPatch udlfb-bind-framebuffer-to-interface.patch ApplyPatch epoll-limit-paths.patch ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch ApplyPatch block-stray-block-put-after-teardown.patch -ApplyPatch usb-add-quirk-for-logitech-webcams.patch +#ApplyPatch usb-add-quirk-for-logitech-webcams.patch ApplyPatch HID-wacom-Set-input-bits-before-registration.patch # rhbz#605888 @@ -1235,7 +1235,7 @@ ApplyPatch efi-dont-map-boot-services-on-32bit.patch ApplyPatch hvcs_pi_buf_alloc.patch #rhbz 751165 -ApplyPatch ip6_tunnel-copy-parms.name-after-register_netdevice.patch +#ApplyPatch ip6_tunnel-copy-parms.name-after-register_netdevice.patch ApplyPatch media-dib0700-correct-error-message.patch @@ -1885,6 +1885,12 @@ fi # and build. %changelog +* Wed Nov 23 2011 Chuck Ebbert 2.6.41.3-0.rc1.1 +- Linux 3.1.3-rc1 (Fedora 2.6.41.3-rc1) +- Comment out merged patches: + usb-add-quirk-for-logitech-webcams.patch + ip6_tunnel-copy-parms.name-after-register_netdevice.patch + * Tue Nov 22 2011 Chuck Ebbert 2.6.41.2-1 - Linux 3.1.2 (Fedora 2.6.41.2) diff --git a/sources b/sources index a72aa471b..a0e27e797 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 7487d8e6f00c077f6e15d6f4f9947c30 patch-3.1.2.bz2 +756c229f0565dd6073605c8654fee4b9 patch-3.1.3-rc1.bz2 From 74c0f68a133c4422ec8ee71d1cb57581ab0eb76b Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sun, 27 Nov 2011 14:46:18 -0500 Subject: [PATCH 227/397] Linux 3.1.3 (Fedora 2.6.41.3) --- kernel.spec | 13 ++++--------- sources | 3 +-- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/kernel.spec b/kernel.spec index 2e94d239f..3554ab845 100644 --- a/kernel.spec +++ b/kernel.spec @@ -53,7 +53,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} @@ -644,7 +644,6 @@ Patch12021: udlfb-bind-framebuffer-to-interface.patch Patch12025: rcu-avoid-just-onlined-cpu-resched.patch Patch12026: block-stray-block-put-after-teardown.patch -Patch12027: usb-add-quirk-for-logitech-webcams.patch Patch12030: epoll-limit-paths.patch Patch12031: HID-wacom-Set-input-bits-before-registration.patch @@ -655,9 +654,6 @@ Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch13009: hvcs_pi_buf_alloc.patch -#rhbz 751165 -Patch13010: ip6_tunnel-copy-parms.name-after-register_netdevice.patch - Patch20000: utrace.patch # Flattened devicetree support @@ -1223,7 +1219,6 @@ ApplyPatch udlfb-bind-framebuffer-to-interface.patch ApplyPatch epoll-limit-paths.patch ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch ApplyPatch block-stray-block-put-after-teardown.patch -#ApplyPatch usb-add-quirk-for-logitech-webcams.patch ApplyPatch HID-wacom-Set-input-bits-before-registration.patch # rhbz#605888 @@ -1234,9 +1229,6 @@ ApplyPatch efi-dont-map-boot-services-on-32bit.patch ApplyPatch hvcs_pi_buf_alloc.patch -#rhbz 751165 -#ApplyPatch ip6_tunnel-copy-parms.name-after-register_netdevice.patch - ApplyPatch media-dib0700-correct-error-message.patch # utrace. @@ -1885,6 +1877,9 @@ fi # and build. %changelog +* Sun Nov 26 2011 Chuck Ebbert 2.6.41.3-1 +- Linux 3.1.3 (Fedora 2.6.41.3) + * Wed Nov 23 2011 Chuck Ebbert 2.6.41.3-0.rc1.1 - Linux 3.1.3-rc1 (Fedora 2.6.41.3-rc1) - Comment out merged patches: diff --git a/sources b/sources index a0e27e797..be5ec9872 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -7487d8e6f00c077f6e15d6f4f9947c30 patch-3.1.2.bz2 -756c229f0565dd6073605c8654fee4b9 patch-3.1.3-rc1.bz2 +1efc18287f740528226af94a28349e11 patch-3.1.3.bz2 From c959f366ca46825c5f9539d97c502493a2204d77 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sun, 27 Nov 2011 14:57:44 -0500 Subject: [PATCH 228/397] Drop dead patches --- ...-parms.name-after-register_netdevice.patch | 76 ------------------- usb-add-quirk-for-logitech-webcams.patch | 14 ---- 2 files changed, 90 deletions(-) delete mode 100644 ip6_tunnel-copy-parms.name-after-register_netdevice.patch delete mode 100644 usb-add-quirk-for-logitech-webcams.patch diff --git a/ip6_tunnel-copy-parms.name-after-register_netdevice.patch b/ip6_tunnel-copy-parms.name-after-register_netdevice.patch deleted file mode 100644 index d3bb6a24e..000000000 --- a/ip6_tunnel-copy-parms.name-after-register_netdevice.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 731abb9cb27aef6013ce60808a04e04a545f3f4e Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Thu, 10 Nov 2011 15:10:23 +0000 -Subject: [PATCH] ip6_tunnel: copy parms.name after register_netdevice - -Commit 1c5cae815d removed an explicit call to dev_alloc_name in ip6_tnl_create -because register_netdevice will now create a valid name. This works for the -net_device itself. - -However the tunnel keeps a copy of the name in the parms structure for the -ip6_tnl associated with the tunnel. parms.name is set by copying the net_device -name in ip6_tnl_dev_init_gen. That function is called from ip6_tnl_dev_init in -ip6_tnl_create, but it is done before register_netdevice is called so the name -is set to a bogus value in the parms.name structure. - -This shows up if you do a simple tunnel add, followed by a tunnel show: - -[root@localhost ~]# ip -6 tunnel add remote fec0::100 local fec0::200 -[root@localhost ~]# ip -6 tunnel show -ip6tnl0: ipv6/ipv6 remote :: local :: encaplimit 0 hoplimit 0 tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000) -ip6tnl%d: ipv6/ipv6 remote fec0::100 local fec0::200 encaplimit 4 hoplimit 64 tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000) -[root@localhost ~]# - -Fix this by moving the strcpy out of ip6_tnl_dev_init_gen, and calling it after -register_netdevice has successfully returned. - -Cc: stable@vger.kernel.org -Signed-off-by: Josh Boyer -Signed-off-by: David S. Miller ---- - net/ipv6/ip6_tunnel.c | 8 +++++++- - 1 files changed, 7 insertions(+), 1 deletions(-) - -diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c -index bdc15c9..4e2e9ff 100644 ---- a/net/ipv6/ip6_tunnel.c -+++ b/net/ipv6/ip6_tunnel.c -@@ -289,6 +289,8 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p) - if ((err = register_netdevice(dev)) < 0) - goto failed_free; - -+ strcpy(t->parms.name, dev->name); -+ - dev_hold(dev); - ip6_tnl_link(ip6n, t); - return t; -@@ -1407,7 +1409,6 @@ ip6_tnl_dev_init_gen(struct net_device *dev) - struct ip6_tnl *t = netdev_priv(dev); - - t->dev = dev; -- strcpy(t->parms.name, dev->name); - dev->tstats = alloc_percpu(struct pcpu_tstats); - if (!dev->tstats) - return -ENOMEM; -@@ -1487,6 +1488,7 @@ static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) - static int __net_init ip6_tnl_init_net(struct net *net) - { - struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); -+ struct ip6_tnl *t = NULL; - int err; - - ip6n->tnls[0] = ip6n->tnls_wc; -@@ -1507,6 +1509,10 @@ static int __net_init ip6_tnl_init_net(struct net *net) - err = register_netdev(ip6n->fb_tnl_dev); - if (err < 0) - goto err_register; -+ -+ t = netdev_priv(ip6n->fb_tnl_dev); -+ -+ strcpy(t->parms.name, ip6n->fb_tnl_dev->name); - return 0; - - err_register: --- -1.7.6.2 - diff --git a/usb-add-quirk-for-logitech-webcams.patch b/usb-add-quirk-for-logitech-webcams.patch deleted file mode 100644 index b4c795133..000000000 --- a/usb-add-quirk-for-logitech-webcams.patch +++ /dev/null @@ -1,14 +0,0 @@ -Add C600 ID from rhbz #742010 ---- ---- a/drivers/usb/core/quirks.c -+++ b/drivers/usb/core/quirks.c -@@ -38,6 +38,9 @@ static const struct usb_device_id usb_quirk_list[] = { - /* Logitech Webcam B/C500 */ - { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME }, - -+ /* Logitech Webcam C600 */ -+ { USB_DEVICE(0x046d, 0x0808), .driver_info = USB_QUIRK_RESET_RESUME }, -+ - /* Logitech Webcam Pro 9000 */ - { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME }, - From 1dfe3692594402a74d3d29e17c0b259e3e29fdd7 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 28 Nov 2011 07:36:54 -0500 Subject: [PATCH 229/397] Fake version 2.6.4X by changing UTSNAME (instead of changing the internal kernel version) --- force-version-2.6.patch | 11 +++++++++++ kernel.spec | 13 +++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 force-version-2.6.patch diff --git a/force-version-2.6.patch b/force-version-2.6.patch new file mode 100644 index 000000000..c53ff9493 --- /dev/null +++ b/force-version-2.6.patch @@ -0,0 +1,11 @@ +--- a/Makefile ++++ b/Makefile +@@ -951,7 +951,7 @@ $(vmlinux-dirs): prepare scripts + # Store (new) KERNELRELASE string in include/config/kernel.release + include/config/kernel.release: include/config/auto.conf FORCE + $(Q)rm -f $@ +- $(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" > $@ ++ $(Q)echo "2.6.$$((40 + $(PATCHLEVEL)))$(EXTRAVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" > $@ + + + # Things we need to do before we recursively start building the kernel diff --git a/kernel.spec b/kernel.spec index 3554ab845..0239834bf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -684,6 +684,8 @@ Patch21061: ideapad-Check-if-acpi-already-handle-backlight.patch Patch21090: brcm80211.patch Patch21091: bcma-brcmsmac-compat.patch +Patch22000: force-version-2.6.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1257,6 +1259,8 @@ ApplyPatch brcm80211.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch +ApplyPatch force-version-2.6.patch + # END OF PATCH APPLICATIONS %endif @@ -1360,9 +1364,6 @@ BuildKernel() { # make sure EXTRAVERSION says what we want it to say perl -p -i -e "s/^EXTRAVERSION.*/EXTRAVERSION = %{?stablerev}-%{release}.%{_target_cpu}${Flavour:+.${Flavour}}/" Makefile - perl -p -i -e 's/^VERSION.*/VERSION = 2/' Makefile - perl -p -i -e 's/^PATCHLEVEL.*/PATCHLEVEL = 6/' Makefile - perl -p -i -e 's/^SUBLEVEL.*/SUBLEVEL = %{fake_sublevel}/' Makefile # and now to start the build process @@ -1877,7 +1878,11 @@ fi # and build. %changelog -* Sun Nov 26 2011 Chuck Ebbert 2.6.41.3-1 +* Mon Nov 28 2011 Chuck Ebbert 2.6.41.3-1 +- Fake version 2.6.4X by changing UTSNAME + (instead of changing the internal kernel version) + +* Sun Nov 27 2011 Chuck Ebbert - Linux 3.1.3 (Fedora 2.6.41.3) * Wed Nov 23 2011 Chuck Ebbert 2.6.41.3-0.rc1.1 From 27ec4e1df273046c07768b94c7d6f2662838566c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 28 Nov 2011 12:10:12 +1000 Subject: [PATCH 230/397] nouveau: fix two instances of an oops in ttm clear() (rhbz#751753) --- drm-nouveau-updates.patch | 1024 ++++++++++++++++++------------------- kernel.spec | 5 +- 2 files changed, 511 insertions(+), 518 deletions(-) diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index 1e7c9279e..cd9bded11 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -781,10 +781,10 @@ index 890d50e..7226f41 100644 else page_shift = 12; diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c -index b0d753f..a319d56 100644 +index 0e3241c..bb6ec9e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c -@@ -411,13 +411,17 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, +@@ -412,13 +412,17 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, return ret; init->channel = chan->id; @@ -960,12 +960,19 @@ diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouv index 7beb82a..de5efe7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c -@@ -28,418 +28,619 @@ +@@ -28,557 +28,669 @@ #include "nouveau_i2c.h" #include "nouveau_connector.h" #include "nouveau_encoder.h" +#include "nouveau_crtc.h" -+ + +-static int +-auxch_rd(struct drm_encoder *encoder, int address, uint8_t *buf, int size) +-{ +- struct drm_device *dev = encoder->dev; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct nouveau_i2c_chan *auxch; +- int ret; +/****************************************************************************** + * aux channel util functions + *****************************************************************************/ @@ -975,22 +982,7 @@ index 7beb82a..de5efe7 100644 + } \ +} while (0) +#define AUX_ERR(fmt, args...) NV_ERROR(dev, "AUXCH(%d): " fmt, ch, ##args) -+ -+static void -+auxch_fini(struct drm_device *dev, int ch) -+{ -+ nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); -+} - static int --auxch_rd(struct drm_encoder *encoder, int address, uint8_t *buf, int size) -+auxch_init(struct drm_device *dev, int ch) - { -- struct drm_device *dev = encoder->dev; -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- struct nouveau_i2c_chan *auxch; -- int ret; -- - auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); - if (!auxch) - return -ENODEV; @@ -998,11 +990,30 @@ index 7beb82a..de5efe7 100644 - ret = nouveau_dp_auxch(auxch, 9, address, buf, size); - if (ret) - return ret; +- +- return 0; ++static void ++auxch_fini(struct drm_device *dev, int ch) ++{ ++ nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); + } + + static int +-auxch_wr(struct drm_encoder *encoder, int address, uint8_t *buf, int size) ++auxch_init(struct drm_device *dev, int ch) + { +- struct drm_device *dev = encoder->dev; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct nouveau_i2c_chan *auxch; +- int ret; + const u32 unksel = 1; /* nfi which to use, or if it matters.. */ + const u32 ureq = unksel ? 0x00100000 : 0x00200000; + const u32 urep = unksel ? 0x01000000 : 0x02000000; + u32 ctrl, timeout; -+ + +- auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); +- if (!auxch) +- return -ENODEV; + /* wait up to 1ms for any previous transaction to be done... */ + timeout = 1000; + do { @@ -1013,7 +1024,9 @@ index 7beb82a..de5efe7 100644 + return -EBUSY; + } + } while (ctrl & 0x03010000); -+ + +- ret = nouveau_dp_auxch(auxch, 8, address, buf, size); +- return ret; + /* set some magic, and wait up to 1ms for it to appear */ + nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq); + timeout = 1000; @@ -1026,42 +1039,22 @@ index 7beb82a..de5efe7 100644 + return -EBUSY; + } + } while ((ctrl & 0x03000000) != urep); - - return 0; ++ ++ return 0; } static int --auxch_wr(struct drm_encoder *encoder, int address, uint8_t *buf, int size) +-nouveau_dp_lane_count_set(struct drm_encoder *encoder, uint8_t cmd) +auxch_tx(struct drm_device *dev, int ch, u8 type, u32 addr, u8 *data, u8 size) { - struct drm_device *dev = encoder->dev; - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- struct nouveau_i2c_chan *auxch; -- int ret; +- uint32_t tmp; +- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); + u32 ctrl, stat, timeout, retries; + u32 xbuf[4] = {}; + int ret, i; -- auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); -- if (!auxch) -- return -ENODEV; -+ AUX_DBG("%d: 0x%08x %d\n", type, addr, size); - -- ret = nouveau_dp_auxch(auxch, 8, address, buf, size); -- return ret; --} -+ ret = auxch_init(dev, ch); -+ if (ret) -+ goto out; - --static int --nouveau_dp_lane_count_set(struct drm_encoder *encoder, uint8_t cmd) --{ -- struct drm_device *dev = encoder->dev; -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- uint32_t tmp; -- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); -- - tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); - tmp &= ~(NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED | - NV50_SOR_DP_CTRL_LANE_MASK); @@ -1069,15 +1062,13 @@ index 7beb82a..de5efe7 100644 - if (cmd & DP_LANE_COUNT_ENHANCED_FRAME_EN) - tmp |= NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED; - nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); -- ++ AUX_DBG("%d: 0x%08x %d\n", type, addr, size); + - return auxch_wr(encoder, DP_LANE_COUNT_SET, &cmd, 1); -} -+ stat = nv_rd32(dev, 0x00e4e8 + (ch * 0x50)); -+ if (!(stat & 0x10000000)) { -+ AUX_DBG("sink not detected\n"); -+ ret = -ENXIO; ++ ret = auxch_init(dev, ch); ++ if (ret) + goto out; -+ } -static int -nouveau_dp_link_bw_set(struct drm_encoder *encoder, uint8_t cmd) @@ -1086,6 +1077,18 @@ index 7beb82a..de5efe7 100644 - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - uint32_t tmp; - int reg = 0x614300 + (nv_encoder->or * 0x800); ++ stat = nv_rd32(dev, 0x00e4e8 + (ch * 0x50)); ++ if (!(stat & 0x10000000)) { ++ AUX_DBG("sink not detected\n"); ++ ret = -ENXIO; ++ goto out; ++ } + +- tmp = nv_rd32(dev, reg); +- tmp &= 0xfff3ffff; +- if (cmd == DP_LINK_BW_2_7) +- tmp |= 0x00040000; +- nv_wr32(dev, reg, tmp); + if (!(type & 1)) { + memcpy(xbuf, data, size); + for (i = 0; i < 16; i += 4) { @@ -1094,47 +1097,13 @@ index 7beb82a..de5efe7 100644 + } + } -- tmp = nv_rd32(dev, reg); -- tmp &= 0xfff3ffff; -- if (cmd == DP_LINK_BW_2_7) -- tmp |= 0x00040000; -- nv_wr32(dev, reg, tmp); +- return auxch_wr(encoder, DP_LINK_BW_SET, &cmd, 1); +-} + ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); + ctrl &= ~0x0001f0ff; + ctrl |= type << 12; + ctrl |= size - 1; + nv_wr32(dev, 0x00e4e0 + (ch * 0x50), addr); -+ -+ /* retry transaction a number of times on failure... */ -+ ret = -EREMOTEIO; -+ for (retries = 0; retries < 32; retries++) { -+ /* reset, and delay a while if this is a retry */ -+ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); -+ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); -+ if (retries) -+ udelay(400); -+ -+ /* transaction request, wait up to 1ms for it to complete */ -+ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); -+ -+ timeout = 1000; -+ do { -+ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); -+ udelay(1); -+ if (!timeout--) { -+ AUX_ERR("tx req timeout 0x%08x\n", ctrl); -+ goto out; -+ } -+ } while (ctrl & 0x00010000); - -- return auxch_wr(encoder, DP_LINK_BW_SET, &cmd, 1); --} -+ /* read status, and check if transaction completed ok */ -+ stat = nv_mask(dev, 0x00e4e8 + (ch * 0x50), 0, 0); -+ if (!(stat & 0x000f0f00)) { -+ ret = 0; -+ break; -+ } -static int -nouveau_dp_link_train_set(struct drm_encoder *encoder, int pattern) @@ -1145,20 +1114,21 @@ index 7beb82a..de5efe7 100644 - uint8_t cmd; - int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); - int ret; -+ AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); -+ } ++ /* retry transaction a number of times on failure... */ ++ ret = -EREMOTEIO; ++ for (retries = 0; retries < 32; retries++) { ++ /* reset, and delay a while if this is a retry */ ++ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); ++ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); ++ if (retries) ++ udelay(400); - tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); - tmp &= ~NV50_SOR_DP_CTRL_TRAINING_PATTERN; - tmp |= (pattern << 24); - nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); -+ if (type & 1) { -+ for (i = 0; i < 16; i += 4) { -+ xbuf[i / 4] = nv_rd32(dev, 0x00e4d0 + (ch * 0x50) + i); -+ AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); -+ } -+ memcpy(data, xbuf, size); -+ } ++ /* transaction request, wait up to 1ms for it to complete */ ++ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); - ret = auxch_rd(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1); - if (ret) @@ -1166,13 +1136,58 @@ index 7beb82a..de5efe7 100644 - cmd &= ~DP_TRAINING_PATTERN_MASK; - cmd |= (pattern & DP_TRAINING_PATTERN_MASK); - return auxch_wr(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1); +-} ++ timeout = 1000; ++ do { ++ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); ++ udelay(1); ++ if (!timeout--) { ++ AUX_ERR("tx req timeout 0x%08x\n", ctrl); ++ goto out; ++ } ++ } while (ctrl & 0x00010000); + +-static int +-nouveau_dp_max_voltage_swing(struct drm_encoder *encoder) +-{ +- 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 i, dpe_headerlen, max_vs = 0; ++ /* read status, and check if transaction completed ok */ ++ stat = nv_mask(dev, 0x00e4e8 + (ch * 0x50), 0, 0); ++ if (!(stat & 0x000f0f00)) { ++ ret = 0; ++ break; ++ } + +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) +- return false; +- dpse = (void *)((char *)dpe + dpe_headerlen); ++ AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); ++ } + +- for (i = 0; i < dpe_headerlen; i++, dpse++) { +- if (dpse->vs_level > max_vs) +- max_vs = dpse->vs_level; ++ if (type & 1) { ++ for (i = 0; i < 16; i += 4) { ++ xbuf[i / 4] = nv_rd32(dev, 0x00e4d0 + (ch * 0x50) + i); ++ AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); ++ } ++ memcpy(data, xbuf, size); + } + +- return max_vs; +out: + auxch_fini(dev, ch); + return ret; } -static int --nouveau_dp_max_voltage_swing(struct drm_encoder *encoder) +-nouveau_dp_max_pre_emphasis(struct drm_encoder *encoder, int vs) +static u32 +dp_link_bw_get(struct drm_device *dev, int or, int link) { @@ -1180,21 +1195,24 @@ index 7beb82a..de5efe7 100644 - struct drm_device *dev = encoder->dev; - struct bit_displayport_encoder_table_entry *dpse; - struct bit_displayport_encoder_table *dpe; -- int i, dpe_headerlen, max_vs = 0; +- int i, dpe_headerlen, max_pre = 0; - - dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); - if (!dpe) - return false; - dpse = (void *)((char *)dpe + dpe_headerlen); +- +- for (i = 0; i < dpe_headerlen; i++, dpse++) { +- if (dpse->vs_level != vs) +- continue; + u32 ctrl = nv_rd32(dev, 0x614300 + (or * 0x800)); + if (!(ctrl & 0x000c0000)) + return 162000; + return 270000; +} -- for (i = 0; i < dpe_headerlen; i++, dpse++) { -- if (dpse->vs_level > max_vs) -- max_vs = dpse->vs_level; +- if (dpse->pre_level > max_pre) +- max_pre = dpse->pre_level; +static int +dp_lane_count_get(struct drm_device *dev, int or, int link) +{ @@ -1206,40 +1224,52 @@ index 7beb82a..de5efe7 100644 + return 4; } - -- return max_vs; +- return max_pre; } --static int --nouveau_dp_max_pre_emphasis(struct drm_encoder *encoder, int vs) +-static bool +-nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config) +void +nouveau_dp_tu_update(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) { - 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 i, dpe_headerlen, max_pre = 0; +- int ret, i, dpe_headerlen, vs = 0, pre = 0; +- uint8_t request[2]; + const u32 symbol = 100000; + int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0; + int TU, VTUi, VTUf, VTUa; + u64 link_data_rate, link_ratio, unk; + u32 best_diff = 64 * symbol; + u32 link_nr, link_bw, r; -+ + +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) +- return false; + /* calculate packed data rate for each lane */ + link_nr = dp_lane_count_get(dev, or, link); + link_data_rate = (clk * bpp / 8) / link_nr; -+ + +- ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2); +- if (ret) +- return false; + /* calculate ratio of packed data rate to link symbol rate */ + link_bw = dp_link_bw_get(dev, or, link); + link_ratio = link_data_rate * symbol; + r = do_div(link_ratio, link_bw); -+ + +- NV_DEBUG_KMS(dev, "\t\tadjust 0x%02x 0x%02x\n", request[0], request[1]); + for (TU = 64; TU >= 32; TU--) { + /* calculate average number of valid symbols in each TU */ + u32 tu_valid = link_ratio * TU; + u32 calc, diff; -+ + +- /* Keep all lanes at the same level.. */ +- for (i = 0; i < nv_encoder->dp.link_nr; i++) { +- int lane_req = (request[i >> 1] >> ((i & 1) << 2)) & 0xf; +- int lane_vs = lane_req & 3; +- int lane_pre = (lane_req >> 2) & 3; + /* find a hw representation for the fraction.. */ + VTUi = tu_valid / symbol; + calc = VTUi * symbol; @@ -1249,7 +1279,12 @@ index 7beb82a..de5efe7 100644 + VTUf = symbol / (symbol - diff); + if (symbol - (VTUf * diff)) + VTUf++; -+ + +- if (lane_vs > vs) +- vs = lane_vs; +- if (lane_pre > pre) +- pre = lane_pre; +- } + if (VTUf <= 15) { + VTUa = 1; + calc += symbol - (symbol / VTUf); @@ -1264,10 +1299,9 @@ index 7beb82a..de5efe7 100644 + calc += symbol / VTUf; + } -- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); -- if (!dpe) -- return false; -- dpse = (void *)((char *)dpe + dpe_headerlen); +- if (vs >= nouveau_dp_max_voltage_swing(encoder)) { +- vs = nouveau_dp_max_voltage_swing(encoder); +- vs |= 4; + diff = calc - tu_valid; + } else { + /* no remainder, but the hw doesn't like the fractional @@ -1278,10 +1312,7 @@ index 7beb82a..de5efe7 100644 + VTUf = 1; + VTUi--; + } - -- for (i = 0; i < dpe_headerlen; i++, dpse++) { -- if (dpse->vs_level != vs) -- continue; ++ + if (diff < best_diff) { + best_diff = diff; + bestTU = TU; @@ -1291,23 +1322,27 @@ index 7beb82a..de5efe7 100644 + if (diff == 0) + break; + } -+ } + } -- if (dpse->pre_level > max_pre) -- max_pre = dpse->pre_level; +- if (pre >= nouveau_dp_max_pre_emphasis(encoder, vs & 3)) { +- pre = nouveau_dp_max_pre_emphasis(encoder, vs & 3); +- pre |= 4; + if (!bestTU) { + NV_ERROR(dev, "DP: unable to find suitable config\n"); + return; } -- return max_pre; +- /* Update the configuration for all lanes.. */ +- for (i = 0; i < nv_encoder->dp.link_nr; i++) +- config[i] = (pre << 3) | vs; + /* XXX close to vbios numbers, but not right */ + unk = (symbol - link_ratio) * bestTU; + unk *= link_ratio; + r = do_div(unk, symbol); + r = do_div(unk, symbol); + unk += 6; -+ + +- return true; + nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2); + nv_mask(dev, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 | + bestVTUf << 16 | @@ -1316,63 +1351,63 @@ index 7beb82a..de5efe7 100644 } -static bool --nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config) +-nouveau_dp_link_train_commit(struct drm_encoder *encoder, uint8_t *config) +u8 * +nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) { - 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]; +- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); +- int dpe_headerlen, ret, i; - -- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); -- if (!dpe) -- return false; -- -- ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2); -- if (ret) -- return false; -- -- NV_DEBUG_KMS(dev, "\t\tadjust 0x%02x 0x%02x\n", request[0], request[1]); -- -- /* Keep all lanes at the same level.. */ -- for (i = 0; i < nv_encoder->dp.link_nr; i++) { -- int lane_req = (request[i >> 1] >> ((i & 1) << 2)) & 0xf; -- int lane_vs = lane_req & 3; -- int lane_pre = (lane_req >> 2) & 3; +- NV_DEBUG_KMS(dev, "\t\tconfig 0x%02x 0x%02x 0x%02x 0x%02x\n", +- config[0], config[1], config[2], config[3]); + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->vbios; + struct bit_entry d; + u8 *table; + int i; -+ + +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) +- return false; +- dpse = (void *)((char *)dpe + dpe_headerlen); + if (bit_table(dev, 'd', &d)) { + NV_ERROR(dev, "BIT 'd' table not found\n"); + return NULL; + } -- if (lane_vs > vs) -- vs = lane_vs; -- if (lane_pre > pre) -- pre = lane_pre; +- for (i = 0; i < dpe->record_nr; i++, dpse++) { +- if (dpse->vs_level == (config[0] & 3) && +- dpse->pre_level == ((config[0] >> 3) & 3)) +- break; + if (d.version != 1) { + NV_ERROR(dev, "BIT 'd' table version %d unknown\n", d.version); + return NULL; } +- BUG_ON(i == dpe->record_nr); -- if (vs >= nouveau_dp_max_voltage_swing(encoder)) { -- vs = nouveau_dp_max_voltage_swing(encoder); -- vs |= 4; +- for (i = 0; i < nv_encoder->dp.link_nr; i++) { +- const int shift[4] = { 16, 8, 0, 24 }; +- uint32_t mask = 0xff << shift[i]; +- uint32_t reg0, reg1, reg2; + table = ROMPTR(bios, d.data[0]); + if (!table) { + NV_ERROR(dev, "displayport table pointer invalid\n"); + return NULL; - } ++ } -- if (pre >= nouveau_dp_max_pre_emphasis(encoder, vs & 3)) { -- pre = nouveau_dp_max_pre_emphasis(encoder, vs & 3); -- pre |= 4; +- reg0 = nv_rd32(dev, NV50_SOR_DP_UNK118(or, link)) & ~mask; +- reg0 |= (dpse->reg0 << shift[i]); +- reg1 = nv_rd32(dev, NV50_SOR_DP_UNK120(or, link)) & ~mask; +- reg1 |= (dpse->reg1 << shift[i]); +- reg2 = nv_rd32(dev, NV50_SOR_DP_UNK130(or, link)) & 0xffff00ff; +- reg2 |= (dpse->reg2 << 8); +- nv_wr32(dev, NV50_SOR_DP_UNK118(or, link), reg0); +- nv_wr32(dev, NV50_SOR_DP_UNK120(or, link), reg1); +- nv_wr32(dev, NV50_SOR_DP_UNK130(or, link), reg2); + switch (table[0]) { + case 0x20: + case 0x21: @@ -1383,9 +1418,9 @@ index 7beb82a..de5efe7 100644 + return NULL; } -- /* Update the configuration for all lanes.. */ -- for (i = 0; i < nv_encoder->dp.link_nr; i++) -- config[i] = (pre << 3) | vs; +- ret = auxch_wr(encoder, DP_TRAINING_LANE0_SET, config, 4); +- if (ret) +- return false; + for (i = 0; i < table[3]; i++) { + *entry = ROMPTR(bios, table[table[1] + (i * table[2])]); + if (*entry && bios_encoder_match(dcb, ROM32((*entry)[0]))) @@ -1397,15 +1432,8 @@ index 7beb82a..de5efe7 100644 + return NULL; } --static bool --nouveau_dp_link_train_commit(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 or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); -- int dpe_headerlen, ret, i; +-bool +-nouveau_dp_link_train(struct drm_encoder *encoder) +/****************************************************************************** + * link training + *****************************************************************************/ @@ -1423,20 +1451,36 @@ index 7beb82a..de5efe7 100644 + u8 stat[6]; + u8 conf[4]; +}; - -- NV_DEBUG_KMS(dev, "\t\tconfig 0x%02x 0x%02x 0x%02x 0x%02x\n", -- config[0], config[1], config[2], config[3]); ++ +static void +dp_set_link_config(struct drm_device *dev, struct dp_state *dp) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; + { +- struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct nouveau_connector *nv_connector; +- struct bit_displayport_encoder_table *dpe; +- int dpe_headerlen; +- uint8_t config[4], status[3]; +- bool cr_done, cr_max_vs, eq_done, hpd_state; +- int ret = 0, i, tries, voltage; + int or = dp->or, link = dp->link; + u8 *entry, sink[2]; + u32 dp_ctrl; + u16 script; -+ + +- NV_DEBUG_KMS(dev, "link training!!\n"); + NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); -+ + +- nv_connector = nouveau_encoder_connector_get(nv_encoder); +- if (!nv_connector) +- return false; +- +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) { +- NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or); +- return false; + /* set selected link rate on source */ + switch (dp->link_bw) { + case 270000: @@ -1447,16 +1491,15 @@ index 7beb82a..de5efe7 100644 + nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00000000); + sink[0] = DP_LINK_BW_1_62; + break; -+ } + } -- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); -- if (!dpe) -- return false; -- dpse = (void *)((char *)dpe + dpe_headerlen); +- /* disable hotplug detect, this flips around on some panels during +- * link training. + /* offset +0x0a of each dp encoder table entry is a pointer to another + * table, that has (among other things) pointers to more scripts that + * need to be executed, this time depending on link speed. -+ */ + */ +- hpd_state = pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); + entry = ROMPTR(&dev_priv->vbios, dp->entry[10]); + if (entry) { + if (dp->table[0] < 0x30) { @@ -1469,90 +1512,77 @@ index 7beb82a..de5efe7 100644 + script = ROM16(entry[1]); + } -- for (i = 0; i < dpe->record_nr; i++, dpse++) { -- if (dpse->vs_level == (config[0] & 3) && -- dpse->pre_level == ((config[0] >> 3) & 3)) -- break; +- if (dpe->script0) { +- NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); +- nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0), +- nv_encoder->dcb); + nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc); } -- BUG_ON(i == dpe->record_nr); -- -- for (i = 0; i < nv_encoder->dp.link_nr; i++) { -- const int shift[4] = { 16, 8, 0, 24 }; -- uint32_t mask = 0xff << shift[i]; -- uint32_t reg0, reg1, reg2; -- -- reg0 = nv_rd32(dev, NV50_SOR_DP_UNK118(or, link)) & ~mask; -- reg0 |= (dpse->reg0 << shift[i]); -- reg1 = nv_rd32(dev, NV50_SOR_DP_UNK120(or, link)) & ~mask; -- reg1 |= (dpse->reg1 << shift[i]); -- reg2 = nv_rd32(dev, NV50_SOR_DP_UNK130(or, link)) & 0xffff00ff; -- reg2 |= (dpse->reg2 << 8); -- nv_wr32(dev, NV50_SOR_DP_UNK118(or, link), reg0); -- nv_wr32(dev, NV50_SOR_DP_UNK120(or, link), reg1); -- nv_wr32(dev, NV50_SOR_DP_UNK130(or, link), reg2); -+ + +-train: +- cr_done = eq_done = false; + /* configure lane count on the source */ + dp_ctrl = ((1 << dp->link_nr) - 1) << 16; + sink[1] = dp->link_nr; + if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) { + dp_ctrl |= 0x00004000; + sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; - } ++ } -- ret = auxch_wr(encoder, DP_TRAINING_LANE0_SET, config, 4); -- if (ret) -- return false; +- /* set link configuration */ +- NV_DEBUG_KMS(dev, "\tbegin train: bw %d, lanes %d\n", +- nv_encoder->dp.link_bw, nv_encoder->dp.link_nr); + nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x001f4000, dp_ctrl); -- return true; +- ret = nouveau_dp_link_bw_set(encoder, nv_encoder->dp.link_bw); +- if (ret) +- return false; + /* inform the sink of the new configuration */ + auxch_tx(dev, dp->auxch, 8, DP_LINK_BW_SET, sink, 2); - } ++} --bool --nouveau_dp_link_train(struct drm_encoder *encoder) +- config[0] = nv_encoder->dp.link_nr; +- if (nv_encoder->dp.dpcd_version >= 0x11 && +- nv_encoder->dp.enhanced_frame) +- config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; +static void +dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 tp) - { -- struct drm_device *dev = encoder->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- struct nouveau_connector *nv_connector; -- struct bit_displayport_encoder_table *dpe; -- int dpe_headerlen; -- uint8_t config[4], status[3]; -- bool cr_done, cr_max_vs, eq_done, hpd_state; -- int ret = 0, i, tries, voltage; ++{ + u8 sink_tp; -- NV_DEBUG_KMS(dev, "link training!!\n"); +- ret = nouveau_dp_lane_count_set(encoder, config[0]); +- if (ret) +- return false; + NV_DEBUG_KMS(dev, "training pattern %d\n", tp); -- nv_connector = nouveau_encoder_connector_get(nv_encoder); -- if (!nv_connector) -- return false; +- /* clock recovery */ +- NV_DEBUG_KMS(dev, "\tbegin cr\n"); +- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_1); +- if (ret) +- goto stop; + nv_mask(dev, NV50_SOR_DP_CTRL(dp->or, dp->link), 0x0f000000, tp << 24); -- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); -- if (!dpe) { -- NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or); -- return false; -- } +- tries = 0; +- voltage = -1; +- memset(config, 0x00, sizeof(config)); +- for (;;) { +- if (!nouveau_dp_link_train_commit(encoder, config)) +- break; + auxch_tx(dev, dp->auxch, 9, DP_TRAINING_PATTERN_SET, &sink_tp, 1); + sink_tp &= ~DP_TRAINING_PATTERN_MASK; + sink_tp |= tp; + auxch_tx(dev, dp->auxch, 8, DP_TRAINING_PATTERN_SET, &sink_tp, 1); +} -- /* disable hotplug detect, this flips around on some panels during -- * link training. -- */ -- hpd_state = pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); +- udelay(100); +static const u8 nv50_lane_map[] = { 16, 8, 0, 24 }; +static const u8 nvaf_lane_map[] = { 24, 16, 8, 0 }; -+ + +- ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 2); +- if (ret) +- break; +- NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n", +- status[0], status[1]); +static int +dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) +{ @@ -1562,12 +1592,21 @@ index 7beb82a..de5efe7 100644 + int link = dp->link; + int or = dp->or; + int i; -+ + +- cr_done = true; +- cr_max_vs = false; +- for (i = 0; i < nv_encoder->dp.link_nr; i++) { +- int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf; + if (dev_priv->chipset != 0xaf) + shifts = nv50_lane_map; + else + shifts = nvaf_lane_map; -+ + +- if (!(lane & DP_LANE_CR_DONE)) { +- cr_done = false; +- if (config[i] & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED) +- cr_max_vs = true; +- break; + for (i = 0; i < dp->link_nr; i++) { + u8 *conf = dp->entry + dp->table[4]; + u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; @@ -1591,8 +1630,13 @@ index 7beb82a..de5efe7 100644 + conf += dp->table[5]; + if (conf >= last) + return -EINVAL; -+ } -+ + } +- } + +- if ((config[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { +- voltage = config[0] & DP_TRAIN_VOLTAGE_SWING_MASK; +- tries = 0; +- } + conf += 2; + } else { + /* no lookup table anymore, set entries for each @@ -1605,69 +1649,57 @@ index 7beb82a..de5efe7 100644 + case 2: lpre += 7; break; + case 3: lpre += 9; break; + } -+ + +- if (cr_done || cr_max_vs || (++tries == 5)) +- break; + conf = conf + (lpre * dp->table[5]); + conf++; + } -- if (dpe->script0) { -- NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); -- nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0), -- nv_encoder->dcb); +- if (!nouveau_dp_link_train_adjust(encoder, config)) +- break; + drv |= conf[0] << shifts[i]; + pre |= conf[1] << shifts[i]; + unk = (unk & ~0x0000ff00) | (conf[2] << 8); } --train: -- cr_done = eq_done = false; +- if (!cr_done) +- goto stop; + nv_mask(dev, NV50_SOR_DP_UNK118(or, link), mask, drv); + nv_mask(dev, NV50_SOR_DP_UNK120(or, link), mask, pre); + nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000ff0f, unk); - -- /* set link configuration */ -- NV_DEBUG_KMS(dev, "\tbegin train: bw %d, lanes %d\n", -- nv_encoder->dp.link_bw, nv_encoder->dp.link_nr); ++ + return auxch_tx(dev, dp->auxch, 8, DP_TRAINING_LANE0_SET, dp->conf, 4); +} - -- ret = nouveau_dp_link_bw_set(encoder, nv_encoder->dp.link_bw); -- if (ret) -- return false; ++ +static int +dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay) +{ + int ret; - -- config[0] = nv_encoder->dp.link_nr; -- if (nv_encoder->dp.dpcd_version >= 0x11 && -- nv_encoder->dp.enhanced_frame) -- config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; ++ + udelay(delay); -- ret = nouveau_dp_lane_count_set(encoder, config[0]); +- /* channel equalisation */ +- NV_DEBUG_KMS(dev, "\tbegin eq\n"); +- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_2); + ret = auxch_tx(dev, dp->auxch, 9, DP_LANE0_1_STATUS, dp->stat, 6); if (ret) -- return false; +- goto stop; + return ret; -- /* clock recovery */ -- NV_DEBUG_KMS(dev, "\tbegin cr\n"); -- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_1); -- if (ret) -- goto stop; +- for (tries = 0; tries <= 5; tries++) { +- udelay(400); + NV_DEBUG_KMS(dev, "status %02x %02x %02x %02x %02x %02x\n", + dp->stat[0], dp->stat[1], dp->stat[2], dp->stat[3], + dp->stat[4], dp->stat[5]); + return 0; +} -- tries = 0; -- voltage = -1; -- memset(config, 0x00, sizeof(config)); -- for (;;) { -- if (!nouveau_dp_link_train_commit(encoder, config)) +- ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 3); +- if (ret) - break; +- NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n", +- status[0], status[1]); +static int +dp_link_train_cr(struct drm_device *dev, struct dp_state *dp) +{ @@ -1675,136 +1707,61 @@ index 7beb82a..de5efe7 100644 + int voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK; + int tries = 0, i; -- udelay(100); +- eq_done = true; +- if (!(status[2] & DP_INTERLANE_ALIGN_DONE)) +- eq_done = false; + dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_1); -- ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 2); -- if (ret) +- for (i = 0; eq_done && i < nv_encoder->dp.link_nr; i++) { +- int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf; + do { + if (dp_link_train_commit(dev, dp) || + dp_link_train_update(dev, dp, 100)) - break; -- NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n", -- status[0], status[1]); ++ break; - cr_done = true; -- cr_max_vs = false; -- for (i = 0; i < nv_encoder->dp.link_nr; i++) { -- int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf; -- ++ cr_done = true; + for (i = 0; i < dp->link_nr; i++) { + u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; if (!(lane & DP_LANE_CR_DONE)) { cr_done = false; -- if (config[i] & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED) -- cr_max_vs = true; + if (dp->conf[i] & DP_TRAIN_MAX_SWING_REACHED) + abort = true; break; } - } ++ } -- if ((config[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { -- voltage = config[0] & DP_TRAIN_VOLTAGE_SWING_MASK; +- if (!(lane & DP_LANE_CHANNEL_EQ_DONE) || +- !(lane & DP_LANE_SYMBOL_LOCKED)) { +- eq_done = false; +- break; +- } + if ((dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { + voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK; - tries = 0; ++ tries = 0; } + } while (!cr_done && !abort && ++tries < 5); -- if (cr_done || cr_max_vs || (++tries == 5)) +- if (eq_done || !cr_done) - break; -- -- if (!nouveau_dp_link_train_adjust(encoder, config)) -- break; -- } -- -- if (!cr_done) -- goto stop; + return cr_done ? 0 : -1; +} -- /* channel equalisation */ -- NV_DEBUG_KMS(dev, "\tbegin eq\n"); -- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_2); -- if (ret) -- goto stop; +- if (!nouveau_dp_link_train_adjust(encoder, config) || +- !nouveau_dp_link_train_commit(encoder, config)) +- break; +- } +static int +dp_link_train_eq(struct drm_device *dev, struct dp_state *dp) +{ + bool eq_done, cr_done = true; + int tries = 0, i; -- for (tries = 0; tries <= 5; tries++) { -- udelay(400); -+ dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_2); - -- ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 3); -- if (ret) -+ do { -+ if (dp_link_train_update(dev, dp, 400)) - break; -- NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n", -- status[0], status[1]); - -- eq_done = true; -- if (!(status[2] & DP_INTERLANE_ALIGN_DONE)) -- eq_done = false; -- -- for (i = 0; eq_done && i < nv_encoder->dp.link_nr; i++) { -- int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf; -- -- if (!(lane & DP_LANE_CR_DONE)) { -+ eq_done = !!(dp->stat[2] & DP_INTERLANE_ALIGN_DONE); -+ for (i = 0; i < dp->link_nr && eq_done; i++) { -+ u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; -+ if (!(lane & DP_LANE_CR_DONE)) - cr_done = false; -- break; -- } -- - if (!(lane & DP_LANE_CHANNEL_EQ_DONE) || -- !(lane & DP_LANE_SYMBOL_LOCKED)) { -+ !(lane & DP_LANE_SYMBOL_LOCKED)) - eq_done = false; -- break; -- } - } - -- if (eq_done || !cr_done) -+ if (dp_link_train_commit(dev, dp)) - break; -+ } while (!eq_done && cr_done && ++tries <= 5); - -- if (!nouveau_dp_link_train_adjust(encoder, config) || -- !nouveau_dp_link_train_commit(encoder, config)) -- break; -- } -+ return eq_done ? 0 : -1; -+} - -stop: - /* end link training */ - ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_DISABLE); - if (ret) -+bool -+nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) -+{ -+ struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; -+ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); -+ struct nouveau_connector *nv_connector = -+ nouveau_encoder_connector_get(nv_encoder); -+ struct drm_device *dev = encoder->dev; -+ struct nouveau_i2c_chan *auxch; -+ const u32 bw_list[] = { 270000, 162000, 0 }; -+ const u32 *link_bw = bw_list; -+ struct dp_state dp; -+ -+ auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); -+ if (!auxch) - return false; +- return false; ++ dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_2); - /* retry at a lower setting, if possible */ - if (!ret && !(eq_done && cr_done)) { @@ -1814,90 +1771,53 @@ index 7beb82a..de5efe7 100644 - nv_encoder->dp.link_bw = DP_LINK_BW_1_62; - goto train; - } -+ dp.table = nouveau_dp_bios_data(dev, nv_encoder->dcb, &dp.entry); -+ if (!dp.table) -+ return -EINVAL; -+ -+ dp.dcb = nv_encoder->dcb; -+ dp.crtc = nv_crtc->index; -+ dp.auxch = auxch->rd; -+ dp.or = nv_encoder->or; -+ dp.link = !(nv_encoder->dcb->sorconf.link & 1); -+ dp.dpcd = nv_encoder->dp.dpcd; -+ -+ /* some sinks toggle hotplug in response to some of the actions -+ * we take during link training (DP_SET_POWER is one), we need -+ * to ignore them for the moment to avoid races. -+ */ -+ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); -+ -+ /* enable down-spreading, if possible */ -+ if (dp.table[1] >= 16) { -+ u16 script = ROM16(dp.entry[14]); -+ if (nv_encoder->dp.dpcd[3] & 1) -+ script = ROM16(dp.entry[12]); -+ -+ nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc); - } +- } ++ do { ++ if (dp_link_train_update(dev, dp, 400)) ++ break; - if (dpe->script1) { - NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or); - nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1), - nv_encoder->dcb); -+ /* execute pre-train script from vbios */ -+ nouveau_bios_run_init_table(dev, ROM16(dp.entry[6]), dp.dcb, dp.crtc); -+ -+ /* start off at highest link rate supported by encoder and display */ -+ while (*link_bw > nv_encoder->dp.link_bw) -+ link_bw++; -+ -+ while (link_bw[0]) { -+ /* find minimum required lane count at this link rate */ -+ dp.link_nr = nv_encoder->dp.link_nr; -+ while ((dp.link_nr >> 1) * link_bw[0] > datarate) -+ dp.link_nr >>= 1; -+ -+ /* drop link rate to minimum with this lane count */ -+ while ((link_bw[1] * dp.link_nr) > datarate) -+ link_bw++; -+ dp.link_bw = link_bw[0]; -+ -+ /* program selected link configuration */ -+ dp_set_link_config(dev, &dp); -+ -+ /* attempt to train the link at this configuration */ -+ memset(dp.stat, 0x00, sizeof(dp.stat)); -+ if (!dp_link_train_cr(dev, &dp) && -+ !dp_link_train_eq(dev, &dp)) -+ break; -+ -+ /* retry at lower rate */ -+ link_bw++; - } +- } ++ eq_done = !!(dp->stat[2] & DP_INTERLANE_ALIGN_DONE); ++ for (i = 0; i < dp->link_nr && eq_done; i++) { ++ u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; ++ if (!(lane & DP_LANE_CR_DONE)) ++ cr_done = false; ++ if (!(lane & DP_LANE_CHANNEL_EQ_DONE) || ++ !(lane & DP_LANE_SYMBOL_LOCKED)) ++ eq_done = false; ++ } - /* re-enable hotplug detect */ - pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, hpd_state); -+ /* finish link training */ -+ dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE); ++ if (dp_link_train_commit(dev, dp)) ++ break; ++ } while (!eq_done && cr_done && ++tries <= 5); - return eq_done; -+ /* execute post-train script from vbios */ -+ nouveau_bios_run_init_table(dev, ROM16(dp.entry[8]), dp.dcb, dp.crtc); -+ -+ /* re-enable hotplug detect */ -+ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true); -+ return true; ++ return eq_done ? 0 : -1; } bool -@@ -447,31 +648,34 @@ nouveau_dp_detect(struct drm_encoder *encoder) +-nouveau_dp_detect(struct drm_encoder *encoder) ++nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) { ++ struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; ++ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); ++ struct nouveau_connector *nv_connector = ++ nouveau_encoder_connector_get(nv_encoder); struct drm_device *dev = encoder->dev; - uint8_t dpcd[4]; +- int ret; + struct nouveau_i2c_chan *auxch; -+ u8 *dpcd = nv_encoder->dp.dpcd; - int ret; ++ const u32 bw_list[] = { 270000, 162000, 0 }; ++ const u32 *link_bw = bw_list; ++ struct dp_state dp; - ret = auxch_rd(encoder, 0x0000, dpcd, 4); - if (ret) @@ -1910,47 +1830,64 @@ index 7beb82a..de5efe7 100644 - nv_encoder->dcb->dpconf.link_bw, - nv_encoder->dcb->dpconf.link_nr, - dpcd[1], dpcd[2] & 0x0f, dpcd[0]); -+ ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8); -+ if (ret) -+ return false; ++ dp.table = nouveau_dp_bios_data(dev, nv_encoder->dcb, &dp.entry); ++ if (!dp.table) ++ return -EINVAL; - nv_encoder->dp.dpcd_version = dpcd[0]; -+ nv_encoder->dp.link_bw = 27000 * dpcd[1]; -+ nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; ++ dp.dcb = nv_encoder->dcb; ++ dp.crtc = nv_crtc->index; ++ dp.auxch = auxch->rd; ++ dp.or = nv_encoder->or; ++ dp.link = !(nv_encoder->dcb->sorconf.link & 1); ++ dp.dpcd = nv_encoder->dp.dpcd; - nv_encoder->dp.link_bw = dpcd[1]; - if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62 && - !nv_encoder->dcb->dpconf.link_bw) - nv_encoder->dp.link_bw = DP_LINK_BW_1_62; -+ NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n", -+ nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); -+ NV_DEBUG_KMS(dev, "encoder: %dx%d\n", -+ nv_encoder->dcb->dpconf.link_nr, -+ nv_encoder->dcb->dpconf.link_bw); ++ /* some sinks toggle hotplug in response to some of the actions ++ * we take during link training (DP_SET_POWER is one), we need ++ * to ignore them for the moment to avoid races. ++ */ ++ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); - nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; - if (nv_encoder->dp.link_nr > nv_encoder->dcb->dpconf.link_nr) -+ if (nv_encoder->dcb->dpconf.link_nr < nv_encoder->dp.link_nr) - nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; -+ if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw) -+ nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw; +- nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; ++ /* enable down-spreading, if possible */ ++ if (dp.table[1] >= 16) { ++ u16 script = ROM16(dp.entry[14]); ++ if (nv_encoder->dp.dpcd[3] & 1) ++ script = ROM16(dp.entry[12]); - nv_encoder->dp.enhanced_frame = (dpcd[2] & DP_ENHANCED_FRAME_CAP); -+ NV_DEBUG_KMS(dev, "maximum: %dx%d\n", -+ nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); ++ nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc); ++ } - return true; - } -@@ -480,105 +684,13 @@ int - nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, - uint8_t *data, int data_nr) - { +- return true; +-} ++ /* execute pre-train script from vbios */ ++ nouveau_bios_run_init_table(dev, ROM16(dp.entry[6]), dp.dcb, dp.crtc); + +-int +-nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, +- uint8_t *data, int data_nr) +-{ - struct drm_device *dev = auxch->dev; - uint32_t tmp, ctrl, stat = 0, data32[4] = {}; - int ret = 0, i, index = auxch->rd; -- ++ /* start off at highest link rate supported by encoder and display */ ++ while (*link_bw > nv_encoder->dp.link_bw) ++ link_bw++; + - NV_DEBUG_KMS(dev, "ch %d cmd %d addr 0x%x len %d\n", index, cmd, addr, data_nr); -- ++ while (link_bw[0]) { ++ /* find minimum required lane count at this link rate */ ++ dp.link_nr = nv_encoder->dp.link_nr; ++ while ((dp.link_nr >> 1) * link_bw[0] > datarate) ++ dp.link_nr >>= 1; + - tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); - nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp | 0x00100000); - tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); @@ -1959,19 +1896,32 @@ index 7beb82a..de5efe7 100644 - ret = -EIO; - goto out; - } -- ++ /* drop link rate to minimum with this lane count */ ++ while ((link_bw[1] * dp.link_nr) > datarate) ++ link_bw++; ++ dp.link_bw = link_bw[0]; ++ ++ /* program selected link configuration */ ++ dp_set_link_config(dev, &dp); + - for (i = 0; i < 3; i++) { - tmp = nv_rd32(dev, NV50_AUXCH_STAT(auxch->rd)); - if (tmp & NV50_AUXCH_STAT_STATE_READY) -- break; ++ /* attempt to train the link at this configuration */ ++ memset(dp.stat, 0x00, sizeof(dp.stat)); ++ if (!dp_link_train_cr(dev, &dp) && ++ !dp_link_train_eq(dev, &dp)) + break; - udelay(100); - } -- + - if (i == 3) { - ret = -EBUSY; - goto out; -- } -- ++ /* retry at lower rate */ ++ link_bw++; + } + - if (!(cmd & 1)) { - memcpy(data32, data, data_nr); - for (i = 0; i < 4; i++) { @@ -1979,13 +1929,17 @@ index 7beb82a..de5efe7 100644 - nv_wr32(dev, NV50_AUXCH_DATA_OUT(index, i), data32[i]); - } - } -- ++ /* finish link training */ ++ dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE); + - nv_wr32(dev, NV50_AUXCH_ADDR(index), addr); - ctrl = nv_rd32(dev, NV50_AUXCH_CTRL(index)); - ctrl &= ~(NV50_AUXCH_CTRL_CMD | NV50_AUXCH_CTRL_LEN); - ctrl |= (cmd << NV50_AUXCH_CTRL_CMD_SHIFT); - ctrl |= ((data_nr - 1) << NV50_AUXCH_CTRL_LEN_SHIFT); -- ++ /* execute post-train script from vbios */ ++ nouveau_bios_run_init_table(dev, ROM16(dp.entry[8]), dp.dcb, dp.crtc); + - for (i = 0; i < 16; i++) { - nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000); - nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl); @@ -1997,34 +1951,64 @@ index 7beb82a..de5efe7 100644 - ret = -EBUSY; - goto out; - } -- ++ /* re-enable hotplug detect */ ++ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true); ++ return true; ++} ++ ++bool ++nouveau_dp_detect(struct drm_encoder *encoder) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct drm_device *dev = encoder->dev; ++ struct nouveau_i2c_chan *auxch; ++ u8 *dpcd = nv_encoder->dp.dpcd; ++ int ret; + - udelay(400); -- ++ auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); ++ if (!auxch) ++ return false; + - stat = nv_rd32(dev, NV50_AUXCH_STAT(index)); - if ((stat & NV50_AUXCH_STAT_REPLY_AUX) != - NV50_AUXCH_STAT_REPLY_AUX_DEFER) - break; - } -- ++ ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8); ++ if (ret) ++ return false; + - if (i == 16) { - NV_ERROR(dev, "auxch DEFER too many times, bailing\n"); - ret = -EREMOTEIO; - goto out; - } -- ++ nv_encoder->dp.link_bw = 27000 * dpcd[1]; ++ nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; + - if (cmd & 1) { - if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) { - ret = -EREMOTEIO; - goto out; - } -- ++ NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n", ++ nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); ++ NV_DEBUG_KMS(dev, "encoder: %dx%d\n", ++ nv_encoder->dcb->dpconf.link_nr, ++ nv_encoder->dcb->dpconf.link_bw); + - for (i = 0; i < 4; i++) { - data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i)); - NV_DEBUG_KMS(dev, "rd %d: 0x%08x\n", i, data32[i]); - } - memcpy(data, data32, data_nr); - } -- ++ if (nv_encoder->dcb->dpconf.link_nr < nv_encoder->dp.link_nr) ++ nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; ++ if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw) ++ nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw; + -out: - tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); - nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp & ~0x00100000); @@ -2033,10 +2017,18 @@ index 7beb82a..de5efe7 100644 - NV_ERROR(dev, "expected bit 24 == 0, got 0x%08x\n", tmp); - ret = -EIO; - } -- ++ NV_DEBUG_KMS(dev, "maximum: %dx%d\n", ++ nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); + - udelay(400); -- ++ return true; ++} + - return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY); ++int ++nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, ++ uint8_t *data, int data_nr) ++{ + return auxch_tx(auxch->dev, auxch->rd, cmd, addr, data, data_nr); } @@ -2165,9 +2157,6 @@ index d7d51de..29837da 100644 u32 shader; - u32 unk05; - u32 unk0a; -- -- u8 voltage; -- u8 fanspeed; + u32 rop; + u32 copy; + u32 daemon; @@ -2177,7 +2166,9 @@ index d7d51de..29837da 100644 + u32 hub01; /* nvc0- */ + u32 hub06; /* nvc0- */ + u32 hub07; /* nvc0- */ -+ + +- u8 voltage; +- u8 fanspeed; + u32 volt_min; /* microvolts */ + u32 volt_max; + u8 fanspeed; @@ -2410,7 +2401,7 @@ index ae69b61..e5d6e3f 100644 - #endif /* __NOUVEAU_ENCODER_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c -index c919cfc..81116cf 100644 +index ae22dfa..2f6daae 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -519,7 +519,7 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) @@ -2848,7 +2839,9 @@ index f9ae2fc..36bec48 100644 - /* XXX: reg_100240? */ - } timing->id = i; -- ++ timing->WR = entry[0]; ++ timing->CL = entry[2]; + - NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, - timing->reg_100220, timing->reg_100224, - timing->reg_100228, timing->reg_10022c); @@ -2856,9 +2849,6 @@ index f9ae2fc..36bec48 100644 - timing->reg_100230, timing->reg_100234, - timing->reg_100238, timing->reg_10023c); - NV_DEBUG(dev, " 240: %08x\n", timing->reg_100240); -+ timing->WR = entry[0]; -+ timing->CL = entry[2]; -+ + if(dev_priv->card_type <= NV_40) { + nv40_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]); + } else if(dev_priv->card_type == NV_50){ @@ -2993,7 +2983,12 @@ index 1640dec..b29ffb3 100644 - struct nouveau_mm *rmm; - struct nouveau_mm_node *heap; + struct nouveau_mm_node *node; -+ + +- heap = kzalloc(sizeof(*heap), GFP_KERNEL); +- if (!heap) +- return -ENOMEM; +- heap->offset = roundup(offset, block); +- heap->length = rounddown(offset + length, block) - heap->offset; + if (block) { + mutex_init(&mm->mutex); + INIT_LIST_HEAD(&mm->nodes); @@ -3002,20 +2997,12 @@ index 1640dec..b29ffb3 100644 + mm->heap_nodes = 0; + } -- heap = kzalloc(sizeof(*heap), GFP_KERNEL); -- if (!heap) -+ node = kzalloc(sizeof(*node), GFP_KERNEL); -+ if (!node) - return -ENOMEM; -- heap->offset = roundup(offset, block); -- heap->length = rounddown(offset + length, block) - heap->offset; -+ node->offset = roundup(offset, mm->block_size); -+ node->length = rounddown(offset + length, mm->block_size) - node->offset; - - rmm = kzalloc(sizeof(*rmm), GFP_KERNEL); - if (!rmm) { - kfree(heap); -- return -ENOMEM; ++ node = kzalloc(sizeof(*node), GFP_KERNEL); ++ if (!node) + return -ENOMEM; - } - rmm->block_size = block; - mutex_init(&rmm->mutex); @@ -3023,7 +3010,9 @@ index 1640dec..b29ffb3 100644 - INIT_LIST_HEAD(&rmm->free); - list_add(&heap->nl_entry, &rmm->nodes); - list_add(&heap->fl_entry, &rmm->free); -- ++ node->offset = roundup(offset, mm->block_size); ++ node->length = rounddown(offset + length, mm->block_size) - node->offset; + - *prmm = rmm; + list_add_tail(&node->nl_entry, &mm->nodes); + list_add_tail(&node->fl_entry, &mm->free); @@ -3038,15 +3027,14 @@ index 1640dec..b29ffb3 100644 - struct nouveau_mm *rmm = *prmm; struct nouveau_mm_node *node, *heap = - list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry); -- ++ list_first_entry(&mm->nodes, struct nouveau_mm_node, nl_entry); ++ int nodes = 0; + - if (!list_is_singular(&rmm->nodes)) { - printk(KERN_ERR "nouveau_mm not empty at destroy time!\n"); - list_for_each_entry(node, &rmm->nodes, nl_entry) { - printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n", - node->type, node->offset, node->length); -+ list_first_entry(&mm->nodes, struct nouveau_mm_node, nl_entry); -+ int nodes = 0; -+ + list_for_each_entry(node, &mm->nodes, nl_entry) { + if (nodes++ == mm->heap_nodes) { + printk(KERN_ERR "nouveau_mm in use at destroy time!\n"); @@ -3621,7 +3609,7 @@ index f18cdfc..43a96b9 100644 #define NV50_PDISPLAY_USER(i) ((i) * 0x1000 + 0x00640000) diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c -index 2706cb3..b75258a 100644 +index 2706cb3..c8a463b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -12,8 +12,8 @@ struct nouveau_sgdma_be { @@ -3693,7 +3681,7 @@ index 2706cb3..b75258a 100644 } return 0; -@@ -72,25 +57,16 @@ static void +@@ -72,26 +57,20 @@ static void nouveau_sgdma_clear(struct ttm_backend *be) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; @@ -3721,9 +3709,13 @@ index 2706cb3..b75258a 100644 - nvbe->pages = NULL; - nvbe->ttm_alloced = NULL; - nvbe->nr_pages = 0; ++ nvbe->unmap_pages = false; } ++ ++ nvbe->pages = NULL; } + static void diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 10656e4..82478e0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c @@ -5809,9 +5801,8 @@ index d43c46c..8c979b3 100644 -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int i; -- -- NV_DEBUG(dev, "\n"); +- NV_DEBUG(dev, "\n"); + /* upload context program, initialise ctxctl defaults */ + nv_wr32(dev, 0x400324, 0x00000000); + for (i = 0; i < pgraph->ctxprog_size; i++) @@ -5823,7 +5814,7 @@ index d43c46c..8c979b3 100644 + nv_wr32(dev, 0x400724, 0x00000000); + nv_wr32(dev, 0x40032c, 0x00000000); + nv_wr32(dev, 0x400320, 4); /* CTXCTL_CMD = NEWCTXDMA */ -+ + + /* some unknown zcull magic */ switch (dev_priv->chipset & 0xf0) { case 0x50: @@ -6088,14 +6079,13 @@ index e4b2b9e..618c144 100644 - 0x00, 0x00 - }; - const u32 *map = pll_map; -- ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 sctl, sdiv, sclk; + - while (map[1]) { - if (id == map[1]) - return map[0]; - map += 2; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ u32 sctl, sdiv, sclk; -+ + /* refclk for the 0xe8xx plls is a fixed frequency */ + if (clk >= 0x40) { + if (dev_priv->chipset == 0xaf) { @@ -6178,8 +6168,7 @@ index e4b2b9e..618c144 100644 + NV_DEBUG(dev, "no clock for 0x%04x/0x%02x\n", pll, clk); + return 0; + } - -- ret = get_pll_limits(dev, id, &pll); ++ + switch (khz) { + case 27000: + reg->clk = 0x00000100; @@ -6209,7 +6198,8 @@ index e4b2b9e..618c144 100644 + return oclk; + } + } -+ + +- ret = get_pll_limits(dev, id, &pll); + if (!pll) { + NV_ERROR(dev, "bad freq %02x: %d %d\n", clk, khz, sclk); + return -ERANGE; @@ -6325,23 +6315,20 @@ index e4b2b9e..618c144 100644 + int ret; - ret = get_pll_limits(dev, id, &limits); +- if (ret < 0) +- return (ret == -ENOENT) ? NULL : ERR_PTR(ret); + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return ERR_PTR(-ENOMEM); -+ -+ ret = calc_clk(dev, 0x10, 0x4200, perflvl->core, &info->nclk); - if (ret < 0) -- return (ret == -ENOENT) ? NULL : ERR_PTR(ret); -+ goto out; - off = nva3_pm_pll_offset(id); - if (id < 0) - return ERR_PTR(-EINVAL); -+ ret = calc_clk(dev, 0x11, 0x4220, perflvl->shader, &info->sclk); ++ ret = calc_clk(dev, 0x10, 0x4200, perflvl->core, &info->nclk); + if (ret < 0) + goto out; -+ ret = calc_clk(dev, 0x12, 0x4000, perflvl->memory, &info->mclk); ++ ret = calc_clk(dev, 0x11, 0x4220, perflvl->shader, &info->sclk); + if (ret < 0) + goto out; @@ -6353,7 +6340,10 @@ index e4b2b9e..618c144 100644 - pll->src1 = 0x004160 + (off * 4); - pll->ctrl = limits.reg + 0; - pll->coef = limits.reg + 4; -- ++ ret = calc_clk(dev, 0x12, 0x4000, perflvl->memory, &info->mclk); ++ if (ret < 0) ++ goto out; + - /* If target clock is within [-2, 3) MHz of a divisor, we'll - * use that instead of calculating MNP values - */ diff --git a/kernel.spec b/kernel.spec index 0239834bf..bd9edeb6c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -1878,6 +1878,9 @@ fi # and build. %changelog +* Mon Nov 28 2011 Ben Skeggs 3.1.3-2 +- nouveau: fix two instances of an oops in ttm clear() (rhbz#751753) + * Mon Nov 28 2011 Chuck Ebbert 2.6.41.3-1 - Fake version 2.6.4X by changing UTSNAME (instead of changing the internal kernel version) From 238fde149d178c8c7b3926b066022e1bbf98fe51 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 28 Nov 2011 16:37:18 -0500 Subject: [PATCH 231/397] Fix IRQ error preventing load of cciss module (rhbz#754907) --- cciss-fix-irqf-shared.patch | 39 +++++++++++++++++++++++++++++++++++++ hpsa-add-irqf-shared.patch | 34 ++++++++++++++++++++++++++++++++ kernel.spec | 18 ++++++++++++++--- 3 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 cciss-fix-irqf-shared.patch create mode 100644 hpsa-add-irqf-shared.patch diff --git a/cciss-fix-irqf-shared.patch b/cciss-fix-irqf-shared.patch new file mode 100644 index 000000000..d6de3d7c2 --- /dev/null +++ b/cciss-fix-irqf-shared.patch @@ -0,0 +1,39 @@ +cciss: Add IRQF_SHARED back in for the non-MSI(X) interrupt handler + +From: Stephen M. Cameron + +[ 3.1.x backport ] + +IRQF_SHARED is required for older controllers that don't support MSI(X) +and which may end up sharing an interrupt. + +Also remove deprecated IRQF_DISABLED. + +Signed-off-by: Stephen M. Cameron +--- + drivers/block/cciss.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +RHBZ 754907 +diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c +index 8004ac3..6f22ed0 100644 +--- a/drivers/block/cciss.c ++++ b/drivers/block/cciss.c +@@ -4880,7 +4880,7 @@ static int cciss_request_irq(ctlr_info_t *h, + { + if (h->msix_vector || h->msi_vector) { + if (!request_irq(h->intr[PERF_MODE_INT], msixhandler, +- IRQF_DISABLED, h->devname, h)) ++ 0, h->devname, h)) + return 0; + dev_err(&h->pdev->dev, "Unable to get msi irq %d" + " for %s\n", h->intr[h->intr_mode], +@@ -4889,7 +4889,7 @@ static int cciss_request_irq(ctlr_info_t *h, + } + + if (!request_irq(h->intr[PERF_MODE_INT], intxhandler, +- IRQF_DISABLED, h->devname, h)) ++ IRQF_SHARED, h->devname, h)) + return 0; + dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n", + h->intr[h->intr_mode], h->devname); diff --git a/hpsa-add-irqf-shared.patch b/hpsa-add-irqf-shared.patch new file mode 100644 index 000000000..d29e2353e --- /dev/null +++ b/hpsa-add-irqf-shared.patch @@ -0,0 +1,34 @@ +hpsa: Add IRQF_SHARED back in for the non-MSI(X) interrupt handler + +From: Stephen M. Cameron + +IRQF_SHARED is required for older controllers that don't support MSI(X) +and which may end up sharing an interrupt. All the controllers hpsa +normally supports have MSI(X) capability, but older controllers may be +encountered via the hpsa_allow_any=1 module parameter. + +Also remove deprecated IRQF_DISABLED. + +Signed-off-by: Stephen M. Cameron +--- + drivers/scsi/hpsa.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +RHBZ 754907 +diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c +index 865d452..594ce83 100644 +--- a/drivers/scsi/hpsa.c ++++ b/drivers/scsi/hpsa.c +@@ -4072,10 +4072,10 @@ static int hpsa_request_irq(struct ctlr_info *h, + + if (h->msix_vector || h->msi_vector) + rc = request_irq(h->intr[h->intr_mode], msixhandler, +- IRQF_DISABLED, h->devname, h); ++ 0, h->devname, h); + else + rc = request_irq(h->intr[h->intr_mode], intxhandler, +- IRQF_DISABLED, h->devname, h); ++ IRQF_SHARED, h->devname, h); + if (rc) { + dev_err(&h->pdev->dev, "unable to get irq %d for %s\n", + h->intr[h->intr_mode], h->devname); diff --git a/kernel.spec b/kernel.spec index bd9edeb6c..73218e04c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -563,6 +563,8 @@ Patch161: linux-2.6-i386-nx-emulation.patch Patch202: linux-2.6-debug-taint-vm.patch +Patch350: force-version-2.6.patch + Patch383: linux-2.6-defaults-aspm.patch Patch390: linux-2.6-defaults-acpi-video.patch @@ -684,7 +686,9 @@ Patch21061: ideapad-Check-if-acpi-already-handle-backlight.patch Patch21090: brcm80211.patch Patch21091: bcma-brcmsmac-compat.patch -Patch22000: force-version-2.6.patch +# rhbz 754907 +Patch21100: cciss-fix-irqf-shared.patch +Patch21101: hpsa-add-irqf-shared.patch %endif @@ -1129,6 +1133,9 @@ ApplyPatch linux-2.6-acpi-debug-infinite-loop.patch ApplyPatch acpi-ensure-thermal-limits-match-cpu-freq.patch ApplyPatch acpi-sony-nonvs-blacklist.patch +# force UTSNAME to show version 2.6.4X +ApplyPatch force-version-2.6.patch + # Various low-impact patches to aid debugging. ApplyPatch linux-2.6-debug-taint-vm.patch @@ -1259,7 +1266,9 @@ ApplyPatch brcm80211.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch -ApplyPatch force-version-2.6.patch +# rhbz 754907 +ApplyPatch cciss-fix-irqf-shared.patch +ApplyPatch hpsa-add-irqf-shared.patch # END OF PATCH APPLICATIONS @@ -1878,7 +1887,10 @@ fi # and build. %changelog -* Mon Nov 28 2011 Ben Skeggs 3.1.3-2 +* Mon Nov 28 2011 Chuck Ebbert +- Fix IRQ error preventing load of cciss module (rhbz#754907) + +* Mon Nov 28 2011 Ben Skeggs - nouveau: fix two instances of an oops in ttm clear() (rhbz#751753) * Mon Nov 28 2011 Chuck Ebbert 2.6.41.3-1 From 650b778c4a4999fe84ded5052698b5d8dd09b3a1 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 28 Nov 2011 20:27:56 -0500 Subject: [PATCH 232/397] Linux 3.1.4 (Fedora 2.6.41.4) --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 73218e04c..d028709d4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 @@ -1887,6 +1887,9 @@ fi # and build. %changelog +* Mon Nov 28 2011 Chuck Ebbert 2.6.41.4-1 +- Linux 3.1.4 (Fedora 2.6.41.4) + * Mon Nov 28 2011 Chuck Ebbert - Fix IRQ error preventing load of cciss module (rhbz#754907) diff --git a/sources b/sources index be5ec9872..bae460776 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -1efc18287f740528226af94a28349e11 patch-3.1.3.bz2 +b8b14bdfbf76cfef8e042e7d1a385fca patch-3.1.4.bz2 From ce96d758e2b556ff87d692685a948e541d334887 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 29 Nov 2011 10:29:39 -0500 Subject: [PATCH 233/397] Add patch to fix deadlock in rtlwifi (rhbz #755154) --- kernel.spec | 14 +- rtlwifi-fix-lps_lock-deadlock.patch | 224 ++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 rtlwifi-fix-lps_lock-deadlock.patch diff --git a/kernel.spec b/kernel.spec index d028709d4..e0ffb4524 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -690,6 +690,9 @@ Patch21091: bcma-brcmsmac-compat.patch Patch21100: cciss-fix-irqf-shared.patch Patch21101: hpsa-add-irqf-shared.patch +#rhbz 755154 +Patch21200: rtlwifi-fix-lps_lock-deadlock.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1270,6 +1273,9 @@ ApplyPatch bcma-brcmsmac-compat.patch ApplyPatch cciss-fix-irqf-shared.patch ApplyPatch hpsa-add-irqf-shared.patch +#rhbz 755154 +ApplyPatch rtlwifi-fix-lps_lock-deadlock.patch + # END OF PATCH APPLICATIONS %endif @@ -1887,9 +1893,15 @@ fi # and build. %changelog +* Tue Nov 29 2011 Josh Boyer +- Add patch to fix deadlock in rtlwifi (rhbz #755154) + * Mon Nov 28 2011 Chuck Ebbert 2.6.41.4-1 - Linux 3.1.4 (Fedora 2.6.41.4) +* Mon Nov 28 2011 Chuck Ebbert 3.1.4-1 +- Linux 3.1.4 + * Mon Nov 28 2011 Chuck Ebbert - Fix IRQ error preventing load of cciss module (rhbz#754907) diff --git a/rtlwifi-fix-lps_lock-deadlock.patch b/rtlwifi-fix-lps_lock-deadlock.patch new file mode 100644 index 000000000..4e31ee9b7 --- /dev/null +++ b/rtlwifi-fix-lps_lock-deadlock.patch @@ -0,0 +1,224 @@ +Path: news.gmane.org!not-for-mail +From: Stanislaw Gruszka +Newsgroups: gmane.linux.kernel.wireless.general +Subject: [PATCH v2] rtlwifi: fix lps_lock deadlock +Date: Mon, 28 Nov 2011 10:33:40 +0100 +Lines: 169 +Approved: news@gmane.org +Message-ID: <20111128093339.GC2372@redhat.com> +References: <1322219327-23148-1-git-send-email-sgruszka@redhat.com> + <4ECFD1BF.4070503@lwfinger.net> + <20111128092308.GB2372@redhat.com> +NNTP-Posting-Host: lo.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +X-Trace: dough.gmane.org 1322472712 10173 80.91.229.12 (28 Nov 2011 09:31:52 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Mon, 28 Nov 2011 09:31:52 +0000 (UTC) +Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, + Chaoming Li +To: Larry Finger , + "John W. Linville" +Original-X-From: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Mon Nov 28 10:31:45 2011 +Return-path: +Envelope-to: glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1RUxYu-0002H1-AY + for glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Mon, 28 Nov 2011 10:31:44 +0100 +Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand + id S1751698Ab1K1Jbm (ORCPT + ); + Mon, 28 Nov 2011 04:31:42 -0500 +Original-Received: from mx1.redhat.com ([209.132.183.28]:62078 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1751434Ab1K1Jbl (ORCPT ); + Mon, 28 Nov 2011 04:31:41 -0500 +Original-Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id pAS9VSak003418 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Mon, 28 Nov 2011 04:31:28 -0500 +Original-Received: from localhost (vpn1-4-194.ams2.redhat.com [10.36.4.194]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id pAS9VQNG013260; + Mon, 28 Nov 2011 04:31:27 -0500 +Content-Disposition: inline +In-Reply-To: <20111128092308.GB2372-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> +User-Agent: Mutt/1.5.20 (2009-12-10) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Original-Sender: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Xref: news.gmane.org gmane.linux.kernel.wireless.general:81657 +Archived-At: + +rtl_lps_leave can be called from interrupt context, so we have to +disable interrupts when taking lps_lock. + +Below is full lockdep info about deadlock: + +[ 93.815269] ================================= +[ 93.815390] [ INFO: inconsistent lock state ] +[ 93.815472] 2.6.41.1-3.offch.fc15.x86_64.debug #1 +[ 93.815556] --------------------------------- +[ 93.815635] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. +[ 93.815743] swapper/0 [HC0[0]:SC1[1]:HE1:SE0] takes: +[ 93.815832] (&(&rtlpriv->locks.lps_lock)->rlock){+.?...}, at: [] rtl_lps_leave+0x26/0x103 [rtlwifi] +[ 93.815947] {SOFTIRQ-ON-W} state was registered at: +[ 93.815947] [] __lock_acquire+0x369/0xd0c +[ 93.815947] [] lock_acquire+0xf3/0x13e +[ 93.815947] [] _raw_spin_lock+0x45/0x79 +[ 93.815947] [] rtl_swlps_rf_awake+0x5a/0x76 [rtlwifi] +[ 93.815947] [] rtl_op_config+0x12a/0x32a [rtlwifi] +[ 93.815947] [] ieee80211_hw_config+0x124/0x129 [mac80211] +[ 93.815947] [] ieee80211_dynamic_ps_disable_work+0x32/0x47 [mac80211] +[ 93.815947] [] process_one_work+0x205/0x3e7 +[ 93.815947] [] worker_thread+0xda/0x15d +[ 93.815947] [] kthread+0xa8/0xb0 +[ 93.815947] [] kernel_thread_helper+0x4/0x10 +[ 93.815947] irq event stamp: 547822 +[ 93.815947] hardirqs last enabled at (547822): [] _raw_spin_unlock_irqrestore+0x45/0x61 +[ 93.815947] hardirqs last disabled at (547821): [] _raw_spin_lock_irqsave+0x22/0x8e +[ 93.815947] softirqs last enabled at (547790): [] _local_bh_enable+0x13/0x15 +[ 93.815947] softirqs last disabled at (547791): [] call_softirq+0x1c/0x30 +[ 93.815947] +[ 93.815947] other info that might help us debug this: +[ 93.815947] Possible unsafe locking scenario: +[ 93.815947] +[ 93.815947] CPU0 +[ 93.815947] ---- +[ 93.815947] lock(&(&rtlpriv->locks.lps_lock)->rlock); +[ 93.815947] +[ 93.815947] lock(&(&rtlpriv->locks.lps_lock)->rlock); +[ 93.815947] +[ 93.815947] *** DEADLOCK *** +[ 93.815947] +[ 93.815947] no locks held by swapper/0. +[ 93.815947] +[ 93.815947] stack backtrace: +[ 93.815947] Pid: 0, comm: swapper Not tainted 2.6.41.1-3.offch.fc15.x86_64.debug #1 +[ 93.815947] Call Trace: +[ 93.815947] [] print_usage_bug+0x1e7/0x1f8 +[ 93.815947] [] ? save_stack_trace+0x2c/0x49 +[ 93.815947] [] ? print_irq_inversion_bug.part.18+0x1a0/0x1a0 +[ 93.815947] [] mark_lock+0x106/0x220 +[ 93.815947] [] __lock_acquire+0x2f5/0xd0c +[ 93.815947] [] ? native_sched_clock+0x34/0x36 +[ 93.830125] [] ? sched_clock+0x9/0xd +[ 93.830125] [] ? sched_clock_local+0x12/0x75 +[ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] +[ 93.830125] [] lock_acquire+0xf3/0x13e +[ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] +[ 93.830125] [] _raw_spin_lock+0x45/0x79 +[ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] +[ 93.830125] [] ? skb_dequeue+0x62/0x6d +[ 93.830125] [] rtl_lps_leave+0x26/0x103 [rtlwifi] +[ 93.830125] [] _rtl_pci_ips_leave_tasklet+0xe/0x10 [rtlwifi] +[ 93.830125] [] tasklet_action+0x8d/0xee +[ 93.830125] [] __do_softirq+0x112/0x25a +[ 93.830125] [] call_softirq+0x1c/0x30 +[ 93.830125] [] do_softirq+0x4b/0xa1 +[ 93.830125] [] irq_exit+0x5d/0xcf +[ 93.830125] [] do_IRQ+0x8e/0xa5 +[ 93.830125] [] common_interrupt+0x73/0x73 +[ 93.830125] [] ? trace_hardirqs_off+0xd/0xf +[ 93.830125] [] ? intel_idle+0xe5/0x10c +[ 93.830125] [] ? intel_idle+0xe1/0x10c +[ 93.830125] [] cpuidle_idle_call+0x11c/0x1fe +[ 93.830125] [] cpu_idle+0xab/0x101 +[ 93.830125] [] rest_init+0xd7/0xde +[ 93.830125] [] ? csum_partial_copy_generic+0x16c/0x16c +[ 93.830125] [] start_kernel+0x3dd/0x3ea +[ 93.830125] [] x86_64_start_reservations+0xaf/0xb3 +[ 93.830125] [] ? early_idt_handlers+0x140/0x140 +[ 93.830125] [] x86_64_start_kernel+0x102/0x111 + +Resolves: +https://bugzilla.redhat.com/show_bug.cgi?id=755154 + +Reported-by: vjain02-9geRo0GdX4mblYp+tMVdN4dd74u8MsAO@public.gmane.org +Reported-and-tested-by: Oliver Paukstadt +Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Acked-by: Larry Finger +Signed-off-by: Stanislaw Gruszka +--- +v1 -> v2: add bug report reference + + drivers/net/wireless/rtlwifi/ps.c | 17 +++++++++-------- + 1 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c +index db52628..55c8e50 100644 +--- a/drivers/net/wireless/rtlwifi/ps.c ++++ b/drivers/net/wireless/rtlwifi/ps.c +@@ -395,7 +395,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) + if (mac->link_state != MAC80211_LINKED) + return; + +- spin_lock(&rtlpriv->locks.lps_lock); ++ spin_lock_irq(&rtlpriv->locks.lps_lock); + + /* Idle for a while if we connect to AP a while ago. */ + if (mac->cnt_after_linked >= 2) { +@@ -407,7 +407,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) + } + } + +- spin_unlock(&rtlpriv->locks.lps_lock); ++ spin_unlock_irq(&rtlpriv->locks.lps_lock); + } + + /*Leave the leisure power save mode.*/ +@@ -416,8 +416,9 @@ void rtl_lps_leave(struct ieee80211_hw *hw) + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); ++ unsigned long flags; + +- spin_lock(&rtlpriv->locks.lps_lock); ++ spin_lock_irqsave(&rtlpriv->locks.lps_lock, flags); + + if (ppsc->fwctrl_lps) { + if (ppsc->dot11_psmode != EACTIVE) { +@@ -438,7 +439,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw) + rtl_lps_set_psmode(hw, EACTIVE); + } + } +- spin_unlock(&rtlpriv->locks.lps_lock); ++ spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flags); + } + + /* For sw LPS*/ +@@ -539,9 +540,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw) + RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); + } + +- spin_lock(&rtlpriv->locks.lps_lock); ++ spin_lock_irq(&rtlpriv->locks.lps_lock); + rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS); +- spin_unlock(&rtlpriv->locks.lps_lock); ++ spin_unlock_irq(&rtlpriv->locks.lps_lock); + } + + void rtl_swlps_rfon_wq_callback(void *data) +@@ -574,9 +575,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw) + if (rtlpriv->link_info.busytraffic) + return; + +- spin_lock(&rtlpriv->locks.lps_lock); ++ spin_lock_irq(&rtlpriv->locks.lps_lock); + rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS); +- spin_unlock(&rtlpriv->locks.lps_lock); ++ spin_unlock_irq(&rtlpriv->locks.lps_lock); + + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && + !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { +-- +1.7.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + From 0b706c8bb0dfffda6dc20d3d4803c19e548885bf Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 29 Nov 2011 11:19:12 -0500 Subject: [PATCH 234/397] Drop drm-intel-make-lvds-work.patch (rhbz #731296) Discussed this with mjg59 and ajax. This fix was supposed to go upstream, but never actually made it. Since it's breaking xrandr, we're dropping it. --- drm-intel-make-lvds-work.patch | 18 ------------------ kernel.spec | 4 +--- 2 files changed, 1 insertion(+), 21 deletions(-) delete mode 100644 drm-intel-make-lvds-work.patch diff --git a/drm-intel-make-lvds-work.patch b/drm-intel-make-lvds-work.patch deleted file mode 100644 index 89f4e2d48..000000000 --- a/drm-intel-make-lvds-work.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -5821,7 +5821,6 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, - struct intel_load_detect_pipe *old) - { - 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; -@@ -5832,7 +5831,6 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, - - if (old->load_detect_temp) { - connector->encoder = NULL; -- drm_helper_disable_unused_functions(dev); - - if (old->release_fb) - old->release_fb->funcs->destroy(old->release_fb); diff --git a/kernel.spec b/kernel.spec index e0ffb4524..0583065a7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -603,8 +603,6 @@ Patch1500: fix_xen_guest_on_old_EC2.patch Patch1810: drm-nouveau-updates.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch -# make sure the lvds comes back on lid open -Patch1825: drm-intel-make-lvds-work.patch # hush the i915 fbc noise Patch1826: drm-i915-fbc-stfu.patch # rhbz#729882, https://bugs.freedesktop.org/attachment.cgi?id=49069 @@ -1199,7 +1197,6 @@ ApplyOptionalPatch drm-nouveau-updates.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch -ApplyPatch drm-intel-make-lvds-work.patch ApplyPatch drm-i915-fbc-stfu.patch ApplyPatch drm-i915-sdvo-lvds-is-digital.patch @@ -1895,6 +1892,7 @@ fi %changelog * Tue Nov 29 2011 Josh Boyer - Add patch to fix deadlock in rtlwifi (rhbz #755154) +- Drop drm-intel-make-lvds-work.patch (rhbz #731296) * Mon Nov 28 2011 Chuck Ebbert 2.6.41.4-1 - Linux 3.1.4 (Fedora 2.6.41.4) From 8eb2e2e1af0ef77c2efda182da633742518206fb Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 30 Nov 2011 10:32:45 -0500 Subject: [PATCH 235/397] Include commit 3940d6185 from JJ Ding in elantech.patch --- elantech.patch | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 5 +++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/elantech.patch b/elantech.patch index 255efd2b6..fa7c67fec 100644 --- a/elantech.patch +++ b/elantech.patch @@ -2114,3 +2114,67 @@ index c2d91eb..25290b3 100644 -- 1.7.6.4 +From 3940d6185a982a970ff562e085caccbdd62f40bb Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Tue, 8 Nov 2011 22:13:14 -0800 +Subject: [PATCH] Input: elantech - adjust hw_version detection logic +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch fixes some v3 hardware (fw_version: 0x150500) wrongly detected +as v2 hardware. + +Reported-by: Marc Dietrich +Signed-off-by: JJ Ding +Tested-By: Marc Dietrich +Acked-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.c | 26 ++++++++++++++++++-------- + 1 files changed, 18 insertions(+), 8 deletions(-) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 09b93b1..e2a9867 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -1210,18 +1210,28 @@ static int elantech_reconnect(struct psmouse *psmouse) + */ + static int elantech_set_properties(struct elantech_data *etd) + { ++ /* This represents the version of IC body. */ + int ver = (etd->fw_version & 0x0f0000) >> 16; + ++ /* Early version of Elan touchpads doesn't obey the rule. */ + if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) + etd->hw_version = 1; +- else if (etd->fw_version < 0x150600) +- etd->hw_version = 2; +- else if (ver == 5) +- etd->hw_version = 3; +- else if (ver == 6) +- etd->hw_version = 4; +- else +- return -1; ++ else { ++ switch (ver) { ++ case 2: ++ case 4: ++ etd->hw_version = 2; ++ break; ++ case 5: ++ etd->hw_version = 3; ++ break; ++ case 6: ++ etd->hw_version = 4; ++ break; ++ default: ++ return -1; ++ } ++ } + + /* + * Turn on packet checking by default. +-- +1.7.7.3 + diff --git a/kernel.spec b/kernel.spec index 0583065a7..af6e07f24 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -1890,6 +1890,9 @@ fi # and build. %changelog +* Wed Nov 30 2011 Josh Boyer +- Include commit 3940d6185 from JJ Ding in elantech.patch + * Tue Nov 29 2011 Josh Boyer - Add patch to fix deadlock in rtlwifi (rhbz #755154) - Drop drm-intel-make-lvds-work.patch (rhbz #731296) From ef5737b662859c1a421c0b9c8520ff7f68444925 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 1 Dec 2011 09:10:14 -0500 Subject: [PATCH 236/397] Apply patch to revert mac80211 scan optimizations (rhbz #731365) --- kernel.spec | 11 +- mac80211_offchannel_rework_revert.patch | 594 ++++++++++++++++++++++++ 2 files changed, 604 insertions(+), 1 deletion(-) create mode 100644 mac80211_offchannel_rework_revert.patch diff --git a/kernel.spec b/kernel.spec index af6e07f24..edf854495 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -691,6 +691,9 @@ Patch21101: hpsa-add-irqf-shared.patch #rhbz 755154 Patch21200: rtlwifi-fix-lps_lock-deadlock.patch +#rhbz 731365 +Patch21220: mac80211_offchannel_rework_revert.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1273,6 +1276,9 @@ ApplyPatch hpsa-add-irqf-shared.patch #rhbz 755154 ApplyPatch rtlwifi-fix-lps_lock-deadlock.patch +#rhbz 731365 +ApplyPatch mac80211_offchannel_rework_revert.patch + # END OF PATCH APPLICATIONS %endif @@ -1890,6 +1896,9 @@ fi # and build. %changelog +* Thu Dec 01 2011 Josh Boyer +- Apply patch to revert mac80211 scan optimizations (rhbz #731365) + * Wed Nov 30 2011 Josh Boyer - Include commit 3940d6185 from JJ Ding in elantech.patch diff --git a/mac80211_offchannel_rework_revert.patch b/mac80211_offchannel_rework_revert.patch new file mode 100644 index 000000000..859799714 --- /dev/null +++ b/mac80211_offchannel_rework_revert.patch @@ -0,0 +1,594 @@ +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 9fab144..4f8cf7f 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -694,6 +694,8 @@ struct tpt_led_trigger { + * well be on the operating channel + * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to + * determine if we are on the operating channel or not ++ * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning, ++ * gets only set in conjunction with SCAN_SW_SCANNING + * @SCAN_COMPLETED: Set for our scan work function when the driver reported + * that the scan completed. + * @SCAN_ABORTED: Set for our scan work function when the driver reported +@@ -702,6 +704,7 @@ struct tpt_led_trigger { + enum { + SCAN_SW_SCANNING, + SCAN_HW_SCANNING, ++ SCAN_OFF_CHANNEL, + SCAN_COMPLETED, + SCAN_ABORTED, + }; +@@ -1197,14 +1200,10 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); + void ieee80211_sched_scan_stopped_work(struct work_struct *work); + + /* off-channel helpers */ +-bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local); +-void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, +- bool tell_ap); +-void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, +- bool offchannel_ps_enable); ++void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local); ++void ieee80211_offchannel_stop_station(struct ieee80211_local *local); + void ieee80211_offchannel_return(struct ieee80211_local *local, +- bool enable_beaconing, +- bool offchannel_ps_disable); ++ bool enable_beaconing); + void ieee80211_hw_roc_setup(struct ieee80211_local *local); + + /* interface handling */ +diff --git a/net/mac80211/main.c b/net/mac80211/main.c +index acb4423..2d607e5 100644 +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -92,47 +92,6 @@ static void ieee80211_reconfig_filter(struct work_struct *work) + ieee80211_configure_filter(local); + } + +-/* +- * Returns true if we are logically configured to be on +- * the operating channel AND the hardware-conf is currently +- * configured on the operating channel. Compares channel-type +- * as well. +- */ +-bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local) +-{ +- struct ieee80211_channel *chan, *scan_chan; +- enum nl80211_channel_type channel_type; +- +- /* This logic needs to match logic in ieee80211_hw_config */ +- if (local->scan_channel) { +- chan = local->scan_channel; +- /* If scanning on oper channel, use whatever channel-type +- * is currently in use. +- */ +- if (chan == local->oper_channel) +- channel_type = local->_oper_channel_type; +- else +- channel_type = NL80211_CHAN_NO_HT; +- } else if (local->tmp_channel) { +- chan = scan_chan = local->tmp_channel; +- channel_type = local->tmp_channel_type; +- } else { +- chan = local->oper_channel; +- channel_type = local->_oper_channel_type; +- } +- +- if (chan != local->oper_channel || +- channel_type != local->_oper_channel_type) +- return false; +- +- /* Check current hardware-config against oper_channel. */ +- if ((local->oper_channel != local->hw.conf.channel) || +- (local->_oper_channel_type != local->hw.conf.channel_type)) +- return false; +- +- return true; +-} +- + int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) + { + struct ieee80211_channel *chan, *scan_chan; +@@ -145,9 +104,6 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) + + scan_chan = local->scan_channel; + +- /* If this off-channel logic ever changes, ieee80211_on_oper_channel +- * may need to change as well. +- */ + offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; + if (scan_chan) { + chan = scan_chan; +@@ -158,19 +114,17 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) + channel_type = local->_oper_channel_type; + else + channel_type = NL80211_CHAN_NO_HT; +- } else if (local->tmp_channel) { ++ local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; ++ } else if (local->tmp_channel && ++ local->oper_channel != local->tmp_channel) { + chan = scan_chan = local->tmp_channel; + channel_type = local->tmp_channel_type; ++ local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; + } else { + chan = local->oper_channel; + channel_type = local->_oper_channel_type; +- } +- +- if (chan != local->oper_channel || +- channel_type != local->_oper_channel_type) +- local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; +- else + local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; ++ } + + offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; + +@@ -279,7 +233,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, + + if (changed & BSS_CHANGED_BEACON_ENABLED) { + if (local->quiescing || !ieee80211_sdata_running(sdata) || +- test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) { ++ test_bit(SCAN_SW_SCANNING, &local->scanning)) { + sdata->vif.bss_conf.enable_beacon = false; + } else { + /* +diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c +index 13427b1..b4e5267 100644 +--- a/net/mac80211/offchannel.c ++++ b/net/mac80211/offchannel.c +@@ -17,14 +17,10 @@ + #include "driver-trace.h" + + /* +- * Tell our hardware to disable PS. +- * Optionally inform AP that we will go to sleep so that it will buffer +- * the frames while we are doing off-channel work. This is optional +- * because we *may* be doing work on-operating channel, and want our +- * hardware unconditionally awake, but still let the AP send us normal frames. ++ * inform AP that we will go to sleep so that it will buffer the frames ++ * while we scan + */ +-static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata, +- bool tell_ap) ++static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) + { + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; +@@ -45,8 +41,8 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata, + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } + +- if (tell_ap && (!local->offchannel_ps_enabled || +- !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))) ++ if (!(local->offchannel_ps_enabled) || ++ !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) + /* + * If power save was enabled, no need to send a nullfunc + * frame because AP knows that we are sleeping. But if the +@@ -81,9 +77,6 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) + * we are sleeping, let's just enable power save mode in + * hardware. + */ +- /* TODO: Only set hardware if CONF_PS changed? +- * TODO: Should we set offchannel_ps_enabled to false? +- */ + local->hw.conf.flags |= IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } else if (local->hw.conf.dynamic_ps_timeout > 0) { +@@ -102,61 +95,63 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) + ieee80211_sta_reset_conn_monitor(sdata); + } + +-void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, +- bool offchannel_ps_enable) ++void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) + { + struct ieee80211_sub_if_data *sdata; + +- /* +- * notify the AP about us leaving the channel and stop all +- * STA interfaces. +- */ + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { + if (!ieee80211_sdata_running(sdata)) + continue; + +- if (sdata->vif.type != NL80211_IFTYPE_MONITOR) +- set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); +- +- /* Check to see if we should disable beaconing. */ ++ /* disable beaconing */ + if (sdata->vif.type == NL80211_IFTYPE_AP || + sdata->vif.type == NL80211_IFTYPE_ADHOC || + sdata->vif.type == NL80211_IFTYPE_MESH_POINT) + ieee80211_bss_info_change_notify( + sdata, BSS_CHANGED_BEACON_ENABLED); + +- if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { ++ /* ++ * only handle non-STA interfaces here, STA interfaces ++ * are handled in ieee80211_offchannel_stop_station(), ++ * e.g., from the background scan state machine. ++ * ++ * In addition, do not stop monitor interface to allow it to be ++ * used from user space controlled off-channel operations. ++ */ ++ if (sdata->vif.type != NL80211_IFTYPE_STATION && ++ sdata->vif.type != NL80211_IFTYPE_MONITOR) { ++ set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); + netif_tx_stop_all_queues(sdata->dev); +- if (offchannel_ps_enable && +- (sdata->vif.type == NL80211_IFTYPE_STATION) && +- sdata->u.mgd.associated) +- ieee80211_offchannel_ps_enable(sdata, true); + } + } + mutex_unlock(&local->iflist_mtx); + } + +-void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, +- bool tell_ap) ++void ieee80211_offchannel_stop_station(struct ieee80211_local *local) + { + struct ieee80211_sub_if_data *sdata; + ++ /* ++ * notify the AP about us leaving the channel and stop all STA interfaces ++ */ + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { + if (!ieee80211_sdata_running(sdata)) + continue; + +- if (sdata->vif.type == NL80211_IFTYPE_STATION && +- sdata->u.mgd.associated) +- ieee80211_offchannel_ps_enable(sdata, tell_ap); ++ if (sdata->vif.type == NL80211_IFTYPE_STATION) { ++ set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); ++ netif_tx_stop_all_queues(sdata->dev); ++ if (sdata->u.mgd.associated) ++ ieee80211_offchannel_ps_enable(sdata); ++ } + } + mutex_unlock(&local->iflist_mtx); + } + + void ieee80211_offchannel_return(struct ieee80211_local *local, +- bool enable_beaconing, +- bool offchannel_ps_disable) ++ bool enable_beaconing) + { + struct ieee80211_sub_if_data *sdata; + +@@ -166,8 +161,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, + continue; + + /* Tell AP we're back */ +- if (offchannel_ps_disable && +- sdata->vif.type == NL80211_IFTYPE_STATION) { ++ if (sdata->vif.type == NL80211_IFTYPE_STATION) { + if (sdata->u.mgd.associated) + ieee80211_offchannel_ps_disable(sdata); + } +@@ -187,7 +181,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, + netif_tx_wake_all_queues(sdata->dev); + } + +- /* Check to see if we should re-enable beaconing */ ++ /* re-enable beaconing */ + if (enable_beaconing && + (sdata->vif.type == NL80211_IFTYPE_AP || + sdata->vif.type == NL80211_IFTYPE_ADHOC || +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index fe2c2a7..b46880e 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -417,10 +417,16 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) + return RX_CONTINUE; + + if (test_bit(SCAN_HW_SCANNING, &local->scanning) || +- test_bit(SCAN_SW_SCANNING, &local->scanning) || + local->sched_scanning) + return ieee80211_scan_rx(rx->sdata, skb); + ++ if (test_bit(SCAN_SW_SCANNING, &local->scanning)) { ++ /* drop all the other packets during a software scan anyway */ ++ if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED) ++ dev_kfree_skb(skb); ++ return RX_QUEUED; ++ } ++ + /* scanning finished during invoking of handlers */ + I802_DEBUG_INC(local->rx_handlers_drop_passive_scan); + return RX_DROP_UNUSABLE; +@@ -2771,7 +2777,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, + local->dot11ReceivedFragmentCount++; + + if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || +- test_bit(SCAN_SW_SCANNING, &local->scanning))) ++ test_bit(SCAN_OFF_CHANNEL, &local->scanning))) + status->rx_flags |= IEEE80211_RX_IN_SCAN; + + if (ieee80211_is_mgmt(fc)) +diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c +index 6f09eca..2ba4977 100644 +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -212,14 +212,6 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) + if (bss) + ieee80211_rx_bss_put(sdata->local, bss); + +- /* If we are on-operating-channel, and this packet is for the +- * current channel, pass the pkt on up the stack so that +- * the rest of the stack can make use of it. +- */ +- if (ieee80211_cfg_on_oper_channel(sdata->local) +- && (channel == sdata->local->oper_channel)) +- return RX_CONTINUE; +- + dev_kfree_skb(skb); + return RX_QUEUED; + } +@@ -262,8 +254,6 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, + bool was_hw_scan) + { + struct ieee80211_local *local = hw_to_local(hw); +- bool on_oper_chan; +- bool enable_beacons = false; + + lockdep_assert_held(&local->mtx); + +@@ -296,25 +286,11 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, + local->scanning = 0; + local->scan_channel = NULL; + +- on_oper_chan = ieee80211_cfg_on_oper_channel(local); +- +- if (was_hw_scan || !on_oper_chan) +- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); +- else +- /* Set power back to normal operating levels. */ +- ieee80211_hw_config(local, 0); +- ++ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); + if (!was_hw_scan) { +- bool on_oper_chan2; + ieee80211_configure_filter(local); + drv_sw_scan_complete(local); +- on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); +- /* We should always be on-channel at this point. */ +- WARN_ON(!on_oper_chan2); +- if (on_oper_chan2 && (on_oper_chan != on_oper_chan2)) +- enable_beacons = true; +- +- ieee80211_offchannel_return(local, enable_beacons, true); ++ ieee80211_offchannel_return(local, true); + } + + ieee80211_recalc_idle(local); +@@ -355,15 +331,13 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) + */ + drv_sw_scan_start(local); + ++ ieee80211_offchannel_stop_beaconing(local); ++ + local->leave_oper_channel_time = 0; + local->next_scan_state = SCAN_DECISION; + local->scan_channel_idx = 0; + +- /* We always want to use off-channel PS, even if we +- * are not really leaving oper-channel. Don't +- * tell the AP though, as long as we are on-channel. +- */ +- ieee80211_offchannel_enable_all_ps(local, false); ++ drv_flush(local, false); + + ieee80211_configure_filter(local); + +@@ -506,20 +480,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, + } + mutex_unlock(&local->iflist_mtx); + +- next_chan = local->scan_req->channels[local->scan_channel_idx]; +- +- if (ieee80211_cfg_on_oper_channel(local)) { +- /* We're currently on operating channel. */ +- if (next_chan == local->oper_channel) +- /* We don't need to move off of operating channel. */ +- local->next_scan_state = SCAN_SET_CHANNEL; +- else +- /* +- * We do need to leave operating channel, as next +- * scan is somewhere else. +- */ +- local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; +- } else { ++ if (local->scan_channel) { + /* + * we're currently scanning a different channel, let's + * see if we can scan another channel without interfering +@@ -535,6 +496,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, + * + * Otherwise switch back to the operating channel. + */ ++ next_chan = local->scan_req->channels[local->scan_channel_idx]; + + bad_latency = time_after(jiffies + + ieee80211_scan_get_channel_time(next_chan), +@@ -552,6 +514,12 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, + local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; + else + local->next_scan_state = SCAN_SET_CHANNEL; ++ } else { ++ /* ++ * we're on the operating channel currently, let's ++ * leave that channel now to scan another one ++ */ ++ local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; + } + + *next_delay = 0; +@@ -560,10 +528,9 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, + static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, + unsigned long *next_delay) + { +- /* PS will already be in off-channel mode, +- * we do that once at the beginning of scanning. +- */ +- ieee80211_offchannel_stop_vifs(local, false); ++ ieee80211_offchannel_stop_station(local); ++ ++ __set_bit(SCAN_OFF_CHANNEL, &local->scanning); + + /* + * What if the nullfunc frames didn't arrive? +@@ -586,15 +553,15 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca + { + /* switch back to the operating channel */ + local->scan_channel = NULL; +- if (!ieee80211_cfg_on_oper_channel(local)) +- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); ++ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); + + /* +- * Re-enable vifs and beaconing. Leave PS +- * in off-channel state..will put that back +- * on-channel at the end of scanning. ++ * Only re-enable station mode interface now; beaconing will be ++ * re-enabled once the full scan has been completed. + */ +- ieee80211_offchannel_return(local, true, false); ++ ieee80211_offchannel_return(local, false); ++ ++ __clear_bit(SCAN_OFF_CHANNEL, &local->scanning); + + *next_delay = HZ / 5; + local->next_scan_state = SCAN_DECISION; +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index 8cb0d2d..54ea022 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -258,8 +258,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) + if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) + return TX_CONTINUE; + +- if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) && +- test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) && ++ if (unlikely(test_bit(SCAN_OFF_CHANNEL, &tx->local->scanning)) && + !ieee80211_is_probe_req(hdr->frame_control) && + !ieee80211_is_nullfunc(hdr->frame_control)) + /* +diff --git a/net/mac80211/work.c b/net/mac80211/work.c +index 7737f20..b76bf33 100644 +--- a/net/mac80211/work.c ++++ b/net/mac80211/work.c +@@ -901,26 +901,6 @@ static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct, + return false; + } + +-static enum nl80211_channel_type +-ieee80211_calc_ct(enum nl80211_channel_type wk_ct, +- enum nl80211_channel_type oper_ct) +-{ +- switch (wk_ct) { +- case NL80211_CHAN_NO_HT: +- return oper_ct; +- case NL80211_CHAN_HT20: +- if (oper_ct != NL80211_CHAN_NO_HT) +- return oper_ct; +- return wk_ct; +- case NL80211_CHAN_HT40MINUS: +- case NL80211_CHAN_HT40PLUS: +- return wk_ct; +- } +- WARN_ON(1); /* shouldn't get here */ +- return wk_ct; +-} +- +- + static void ieee80211_work_timer(unsigned long data) + { + struct ieee80211_local *local = (void *) data; +@@ -971,52 +951,18 @@ static void ieee80211_work_work(struct work_struct *work) + } + + if (!started && !local->tmp_channel) { +- bool on_oper_chan; +- bool tmp_chan_changed = false; +- bool on_oper_chan2; +- enum nl80211_channel_type wk_ct; +- on_oper_chan = ieee80211_cfg_on_oper_channel(local); +- +- /* Work with existing channel type if possible. */ +- wk_ct = wk->chan_type; +- if (wk->chan == local->hw.conf.channel) +- wk_ct = ieee80211_calc_ct(wk->chan_type, +- local->hw.conf.channel_type); +- +- if (local->tmp_channel) +- if ((local->tmp_channel != wk->chan) || +- (local->tmp_channel_type != wk_ct)) +- tmp_chan_changed = true; +- +- local->tmp_channel = wk->chan; +- local->tmp_channel_type = wk_ct; + /* +- * Leave the station vifs in awake mode if they +- * happen to be on the same channel as +- * the requested channel. ++ * TODO: could optimize this by leaving the ++ * station vifs in awake mode if they ++ * happen to be on the same channel as ++ * the requested channel + */ +- on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); +- if (on_oper_chan != on_oper_chan2) { +- if (on_oper_chan2) { +- /* going off oper channel, PS too */ +- ieee80211_offchannel_stop_vifs(local, +- true); +- ieee80211_hw_config(local, 0); +- } else { +- /* going on channel, but leave PS +- * off-channel. */ +- ieee80211_hw_config(local, 0); +- ieee80211_offchannel_return(local, +- true, +- false); +- } +- } else if (tmp_chan_changed) +- /* Still off-channel, but on some other +- * channel, so update hardware. +- * PS should already be off-channel. +- */ +- ieee80211_hw_config(local, 0); ++ ieee80211_offchannel_stop_beaconing(local); ++ ieee80211_offchannel_stop_station(local); + ++ local->tmp_channel = wk->chan; ++ local->tmp_channel_type = wk->chan_type; ++ ieee80211_hw_config(local, 0); + started = true; + wk->timeout = jiffies; + } +@@ -1102,8 +1048,7 @@ static void ieee80211_work_work(struct work_struct *work) + * we still need to do a hardware config. Currently, + * we cannot be here while scanning, however. + */ +- if (!ieee80211_cfg_on_oper_channel(local)) +- ieee80211_hw_config(local, 0); ++ ieee80211_hw_config(local, 0); + + /* At the least, we need to disable offchannel_ps, + * so just go ahead and run the entire offchannel +@@ -1111,7 +1056,7 @@ static void ieee80211_work_work(struct work_struct *work) + * beaconing if we were already on-oper-channel + * as a future optimization. + */ +- ieee80211_offchannel_return(local, true, true); ++ ieee80211_offchannel_return(local, true); + + /* give connection some time to breathe */ + run_again(local, jiffies + HZ/2); From 5ff2da42eee59b8ca87b8f467a633a52780e09e5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 1 Dec 2011 10:05:32 -0500 Subject: [PATCH 237/397] Disable the existing brcm80211 staging drivers (rhbz #759109) --- brcm80211.patch | 235 ++++++++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 1 + 2 files changed, 236 insertions(+) diff --git a/brcm80211.patch b/brcm80211.patch index 73c577f6d..00bd05f02 100644 --- a/brcm80211.patch +++ b/brcm80211.patch @@ -96989,3 +96989,238 @@ diff -up linux-3.1.x86_64/drivers/net/wireless/Makefile.orig linux-3.1.x86_64/dr + +obj-$(CONFIG_BRCMFMAC) += brcm80211/ +obj-$(CONFIG_BRCMSMAC) += brcm80211/ +diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig +index 06c9081..e2c3532 100644 +--- a/drivers/staging/Kconfig ++++ b/drivers/staging/Kconfig +@@ -44,8 +44,6 @@ source "drivers/staging/wlan-ng/Kconfig" + + source "drivers/staging/echo/Kconfig" + +-source "drivers/staging/brcm80211/Kconfig" +- + source "drivers/staging/comedi/Kconfig" + + source "drivers/staging/olpc_dcon/Kconfig" +diff --git a/drivers/staging/brcm80211/Kconfig b/drivers/staging/brcm80211/Kconfig +deleted file mode 100644 +index 379cf16..0000000 +--- a/drivers/staging/brcm80211/Kconfig ++++ /dev/null +@@ -1,40 +0,0 @@ +-config BRCMUTIL +- tristate +- default n +- +-config BRCMSMAC +- tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" +- default n +- depends on PCI +- depends on WLAN && MAC80211 +- depends on X86 || MIPS +- select BRCMUTIL +- select FW_LOADER +- select CRC_CCITT +- ---help--- +- This module adds support for PCIe wireless adapters based on Broadcom +- IEEE802.11n SoftMAC chipsets. If you choose to build a module, it'll +- be called brcmsmac.ko. +- +-config BRCMFMAC +- tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver" +- default n +- depends on MMC +- depends on WLAN && CFG80211 +- depends on X86 || MIPS +- select BRCMUTIL +- select FW_LOADER +- select WIRELESS_EXT +- select WEXT_PRIV +- ---help--- +- This module adds support for embedded wireless adapters based on +- Broadcom IEEE802.11n FullMAC chipsets. This driver uses the kernel's +- wireless extensions subsystem. If you choose to build a module, +- it'll be called brcmfmac.ko. +- +-config BRCMDBG +- bool "Broadcom driver debug functions" +- default n +- depends on BRCMSMAC || BRCMFMAC +- ---help--- +- Selecting this enables additional code for debug purposes. +diff --git a/drivers/staging/brcm80211/Makefile b/drivers/staging/brcm80211/Makefile +deleted file mode 100644 +index 8b01f5e..0000000 +--- a/drivers/staging/brcm80211/Makefile ++++ /dev/null +@@ -1,24 +0,0 @@ +-# +-# Makefile fragment for Broadcom 802.11n Networking Device Driver +-# +-# Copyright (c) 2010 Broadcom Corporation +-# +-# Permission to use, copy, modify, and/or distribute this software for any +-# purpose with or without fee is hereby granted, provided that the above +-# copyright notice and this permission notice appear in all copies. +-# +-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- +-# common flags +-subdir-ccflags-y := -DBCMDMA32 +-subdir-ccflags-$(CONFIG_BRCMDBG) += -DBCMDBG +- +-obj-$(CONFIG_BRCMUTIL) += brcmutil/ +-obj-$(CONFIG_BRCMFMAC) += brcmfmac/ +-obj-$(CONFIG_BRCMSMAC) += brcmsmac/ +diff --git a/drivers/staging/brcm80211/brcmfmac/Makefile b/drivers/staging/brcm80211/brcmfmac/Makefile +deleted file mode 100644 +index da3c805..0000000 +--- a/drivers/staging/brcm80211/brcmfmac/Makefile ++++ /dev/null +@@ -1,39 +0,0 @@ +-# +-# Makefile fragment for Broadcom 802.11n Networking Device Driver +-# +-# Copyright (c) 2010 Broadcom Corporation +-# +-# Permission to use, copy, modify, and/or distribute this software for any +-# purpose with or without fee is hereby granted, provided that the above +-# copyright notice and this permission notice appear in all copies. +-# +-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- +-ccflags-y := \ +- -DBRCMF_FIRSTREAD=64 \ +- -DBRCMF_SDALIGN=64 \ +- -DMAX_HDR_READ=64 +- +-ccflags-$(CONFIG_BRCMDBG) += -DSHOW_EVENTS +- +-ccflags-y += \ +- -Idrivers/staging/brcm80211/brcmfmac \ +- -Idrivers/staging/brcm80211/include +- +-DHDOFILES = \ +- wl_cfg80211.o \ +- dhd_cdc.o \ +- dhd_common.o \ +- dhd_sdio.o \ +- dhd_linux.o \ +- bcmsdh.o \ +- bcmsdh_sdmmc.o +- +-obj-$(CONFIG_BRCMFMAC) += brcmfmac.o +-brcmfmac-objs += $(DHDOFILES) +diff --git a/drivers/staging/brcm80211/brcmsmac/Makefile b/drivers/staging/brcm80211/brcmsmac/Makefile +deleted file mode 100644 +index 1ea3e0c..0000000 +--- a/drivers/staging/brcm80211/brcmsmac/Makefile ++++ /dev/null +@@ -1,58 +0,0 @@ +-# +-# Makefile fragment for Broadcom 802.11n Networking Device Driver +-# +-# Copyright (c) 2010 Broadcom Corporation +-# +-# Permission to use, copy, modify, and/or distribute this software for any +-# purpose with or without fee is hereby granted, provided that the above +-# copyright notice and this permission notice appear in all copies. +-# +-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- +-ccflags-y := \ +- -DWLC_HIGH \ +- -DWLC_LOW \ +- -DSTA \ +- -DWME \ +- -DWL11N \ +- -DDBAND \ +- -DBCMNVRAMR \ +- -Idrivers/staging/brcm80211/brcmsmac \ +- -Idrivers/staging/brcm80211/brcmsmac/phy \ +- -Idrivers/staging/brcm80211/include +- +-BRCMSMAC_OFILES := \ +- mac80211_if.o \ +- ucode_loader.o \ +- alloc.o \ +- ampdu.o \ +- antsel.o \ +- bmac.o \ +- channel.o \ +- main.o \ +- phy_shim.o \ +- pmu.o \ +- rate.o \ +- stf.o \ +- aiutils.o \ +- phy/phy_cmn.o \ +- phy/phy_lcn.o \ +- phy/phy_n.o \ +- phy/phytbl_lcn.o \ +- phy/phytbl_n.o \ +- phy/phy_qmath.o \ +- otp.o \ +- srom.o \ +- dma.o \ +- nicpci.o +- +-MODULEPFX := brcmsmac +- +-obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o +-$(MODULEPFX)-objs = $(BRCMSMAC_OFILES) +diff --git a/drivers/staging/brcm80211/brcmutil/Makefile b/drivers/staging/brcm80211/brcmutil/Makefile +deleted file mode 100644 +index 6403423..0000000 +--- a/drivers/staging/brcm80211/brcmutil/Makefile ++++ /dev/null +@@ -1,29 +0,0 @@ +-# +-# Makefile fragment for Broadcom 802.11n Networking Device Driver Utilities +-# +-# Copyright (c) 2011 Broadcom Corporation +-# +-# Permission to use, copy, modify, and/or distribute this software for any +-# purpose with or without fee is hereby granted, provided that the above +-# copyright notice and this permission notice appear in all copies. +-# +-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- +-ccflags-y := \ +- -Idrivers/staging/brcm80211/brcmutil \ +- -Idrivers/staging/brcm80211/include +- +-BRCMUTIL_OFILES := \ +- utils.o \ +- wifi.o +- +-MODULEPFX := brcmutil +- +-obj-$(CONFIG_BRCMUTIL) += $(MODULEPFX).o +-$(MODULEPFX)-objs = $(BRCMUTIL_OFILES) +-- +1.7.7.3 diff --git a/kernel.spec b/kernel.spec index edf854495..230e5b423 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1898,6 +1898,7 @@ fi %changelog * Thu Dec 01 2011 Josh Boyer - Apply patch to revert mac80211 scan optimizations (rhbz #731365) +- Disable the existing brcm80211 staging drivers (rhbz #759109) * Wed Nov 30 2011 Josh Boyer - Include commit 3940d6185 from JJ Ding in elantech.patch From e3f3ee30cb75a9a4e08ac6b72533ef92e8da9608 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 1 Dec 2011 11:07:19 -0500 Subject: [PATCH 238/397] Fixup brcm80211 staging neutering Need to drop references in drivers/staging/Makefile too, or 'make mrproper' fails. Doh. --- brcm80211.patch | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/brcm80211.patch b/brcm80211.patch index 00bd05f02..7c6d42e76 100644 --- a/brcm80211.patch +++ b/brcm80211.patch @@ -97223,4 +97223,16 @@ index 6403423..0000000 -obj-$(CONFIG_BRCMUTIL) += $(MODULEPFX).o -$(MODULEPFX)-objs = $(BRCMUTIL_OFILES) -- -1.7.7.3 +diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile +index f3c5e33..f2c2209 100644 +--- a/drivers/staging/Makefile ++++ b/drivers/staging/Makefile +@@ -14,8 +14,6 @@ obj-$(CONFIG_USBIP_CORE) += usbip/ + obj-$(CONFIG_W35UND) += winbond/ + obj-$(CONFIG_PRISM2_USB) += wlan-ng/ + obj-$(CONFIG_ECHO) += echo/ +-obj-$(CONFIG_BRCMSMAC) += brcm80211/ +-obj-$(CONFIG_BRCMFMAC) += brcm80211/ + obj-$(CONFIG_COMEDI) += comedi/ + obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/ + obj-$(CONFIG_ASUS_OLED) += asus_oled/ From 0564a406004264be297c0f430271321192d3457b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 5 Dec 2011 16:03:32 -0500 Subject: [PATCH 239/397] Switch from -Os to -O2 --- config-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 162e67041..f9acd1913 100644 --- a/config-generic +++ b/config-generic @@ -3778,7 +3778,7 @@ CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_INFO=y CONFIG_FRAME_POINTER=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_DEBUG_DRIVER is not set CONFIG_HEADERS_CHECK=y # CONFIG_RCU_TORTURE_TEST is not set diff --git a/kernel.spec b/kernel.spec index 230e5b423..38bdb411b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1896,6 +1896,9 @@ fi # and build. %changelog +* Mon Dec 05 2011 Dave Jones +- Switch from -Os to -O2 + * Thu Dec 01 2011 Josh Boyer - Apply patch to revert mac80211 scan optimizations (rhbz #731365) - Disable the existing brcm80211 staging drivers (rhbz #759109) From 2fcc12a9e07a7b1ed3feed052ae3608ca15335b7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 5 Dec 2011 16:50:31 -0500 Subject: [PATCH 240/397] Only print the apm_cpu_idle message once (rhbz #760341) --- kernel.spec | 5 ++++- quite-apm.patch | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 38bdb411b..04618306c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -1896,6 +1896,9 @@ fi # and build. %changelog +* Mon Dec 05 2011 Josh Boyer +- Only print the apm_cpu_idle message once (rhbz #760341) + * Mon Dec 05 2011 Dave Jones - Switch from -Os to -O2 diff --git a/quite-apm.patch b/quite-apm.patch index 9325ae55b..c38511c41 100644 --- a/quite-apm.patch +++ b/quite-apm.patch @@ -7,7 +7,7 @@ index a46bd38..416dd12 100644 unsigned int bucket; - WARN_ONCE(1, "deprecated apm_cpu_idle will be deleted in 2012"); -+ printk(KERN_INFO "deprecated apm_cpu_idle will be deleted in 2012"); ++ printk_once(KERN_INFO "deprecated apm_cpu_idle will be deleted in 2012"); recalc: if (jiffies_since_last_check > IDLE_CALC_LIMIT) { use_apm_idle = 0; From 428eca2b0ca86f5c92e24535d3fa3f8bd75eb023 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 6 Dec 2011 13:01:59 -0500 Subject: [PATCH 241/397] Add reworked pci ASPM patch from Matthew Garrett --- kernel.spec | 7 + pci-Rework-ASPM-disable-code.patch | 287 +++++++++++++++++++++++++++++ 2 files changed, 294 insertions(+) create mode 100644 pci-Rework-ASPM-disable-code.patch diff --git a/kernel.spec b/kernel.spec index 04618306c..9ca6724cd 100644 --- a/kernel.spec +++ b/kernel.spec @@ -694,6 +694,8 @@ Patch21200: rtlwifi-fix-lps_lock-deadlock.patch #rhbz 731365 Patch21220: mac80211_offchannel_rework_revert.patch +Patch21225: pci-Rework-ASPM-disable-code.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1279,6 +1281,8 @@ ApplyPatch rtlwifi-fix-lps_lock-deadlock.patch #rhbz 731365 ApplyPatch mac80211_offchannel_rework_revert.patch +ApplyPatch pci-Rework-ASPM-disable-code.patch + # END OF PATCH APPLICATIONS %endif @@ -1896,6 +1900,9 @@ fi # and build. %changelog +* Tue Dec 06 2011 Josh Boyer +- Add reworked pci ASPM patch from Matthew Garrett + * Mon Dec 05 2011 Josh Boyer - Only print the apm_cpu_idle message once (rhbz #760341) diff --git a/pci-Rework-ASPM-disable-code.patch b/pci-Rework-ASPM-disable-code.patch new file mode 100644 index 000000000..d6fb24320 --- /dev/null +++ b/pci-Rework-ASPM-disable-code.patch @@ -0,0 +1,287 @@ +Path: news.gmane.org!not-for-mail +From: Matthew Garrett +Newsgroups: gmane.linux.acpi.devel,gmane.linux.kernel.pci,gmane.linux.kernel +Subject: [PATCH] pci: Rework ASPM disable code +Date: Thu, 10 Nov 2011 16:38:33 -0500 +Lines: 232 +Approved: news@gmane.org +Message-ID: <1320961113-5050-1-git-send-email-mjg@redhat.com> +NNTP-Posting-Host: lo.gmane.org +X-Trace: dough.gmane.org 1320961145 13112 80.91.229.12 (10 Nov 2011 21:39:05 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Thu, 10 Nov 2011 21:39:05 +0000 (UTC) +Cc: linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, + linux-kernel@vger.kernel.org, Matthew Garrett +To: jbarnes@virtuousgeek.org +Original-X-From: linux-acpi-owner@vger.kernel.org Thu Nov 10 22:38:57 2011 +Return-path: +Envelope-to: glad-acpi-devel@lo.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1ROcKm-0003jN-CL + for glad-acpi-devel@lo.gmane.org; Thu, 10 Nov 2011 22:38:56 +0100 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1751342Ab1KJViu (ORCPT ); + Thu, 10 Nov 2011 16:38:50 -0500 +Original-Received: from mx1.redhat.com ([209.132.183.28]:32030 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1750805Ab1KJVit (ORCPT ); + Thu, 10 Nov 2011 16:38:49 -0500 +Original-Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id pAALcmdw013333 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Thu, 10 Nov 2011 16:38:49 -0500 +Original-Received: from cavan.codon.org.uk (ovpn-113-157.phx2.redhat.com [10.3.113.157]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id pAALclkW022022 + (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NO); + Thu, 10 Nov 2011 16:38:48 -0500 +Original-Received: from 209-6-41-104.c3-0.smr-ubr1.sbo-smr.ma.cable.rcn.com ([209.6.41.104] helo=localhost.localdomain) + by cavan.codon.org.uk with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) + (Exim 4.72) + (envelope-from ) + id 1ROcKa-0000F4-E4; Thu, 10 Nov 2011 21:38:44 +0000 +X-SA-Do-Not-Run: Yes +X-SA-Exim-Connect-IP: 209.6.41.104 +X-SA-Exim-Mail-From: mjg@redhat.com +X-SA-Exim-Scanned: No (on cavan.codon.org.uk); SAEximRunCond expanded to false +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Original-Sender: linux-acpi-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-acpi@vger.kernel.org +Xref: news.gmane.org gmane.linux.acpi.devel:51182 gmane.linux.kernel.pci:12503 gmane.linux.kernel:1214427 +Archived-At: + +Right now we forcibly clear ASPM state on all devices if the BIOS indicates +that the feature isn't supported. Based on the Microsoft presentation +"PCI Express In Depth for Windows Vista and Beyond", I'm starting to think +that this may be an error. The implication is that unless the platform +grants full control via _OSC, Windows will not touch any PCIe features - +including ASPM. In that case clearing ASPM state would be an error unless +the platform has granted us that control. + +This patch reworks the ASPM disabling code such that the actual clearing +of state is triggered by a successful handoff of PCIe control to the OS. +The general ASPM code undergoes some changes in order to ensure that the +ability to clear the bits isn't overridden by ASPM having already been +disabled. Further, this theoretically now allows for situations where +only a subset of PCIe roots hand over control, leaving the others in the +BIOS state. + +It's difficult to know for sure that this is the right thing to do - +there's zero public documentation on the interaction between all of these +components. But enough vendors enable ASPM on platforms and then set this +bit that it seems likely that they're expecting the OS to leave them alone. + +Measured to save around 5W on an idle Thinkpad X220. + +Signed-off-by: Matthew Garrett +--- + drivers/acpi/pci_root.c | 7 +++++ + drivers/pci/pci-acpi.c | 1 - + drivers/pci/pcie/aspm.c | 58 +++++++++++++++++++++++++++++---------------- + include/linux/pci-aspm.h | 4 +- + 4 files changed, 46 insertions(+), 24 deletions(-) + +diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c +index 2672c79..7aff631 100644 +--- a/drivers/acpi/pci_root.c ++++ b/drivers/acpi/pci_root.c +@@ -596,6 +596,13 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) + if (ACPI_SUCCESS(status)) { + dev_info(root->bus->bridge, + "ACPI _OSC control (0x%02x) granted\n", flags); ++ if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { ++ /* ++ * We have ASPM control, but the FADT indicates ++ * that it's unsupported. Clear it. ++ */ ++ pcie_clear_aspm(root->bus); ++ } + } else { + dev_info(root->bus->bridge, + "ACPI _OSC request failed (%s), " +diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c +index 4ecb640..c8e7585 100644 +--- a/drivers/pci/pci-acpi.c ++++ b/drivers/pci/pci-acpi.c +@@ -395,7 +395,6 @@ static int __init acpi_pci_init(void) + + if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { + printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n"); +- pcie_clear_aspm(); + pcie_no_aspm(); + } + +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index cbfbab1..1cfbf22 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -68,7 +68,7 @@ struct pcie_link_state { + struct aspm_latency acceptable[8]; + }; + +-static int aspm_disabled, aspm_force, aspm_clear_state; ++static int aspm_disabled, aspm_force; + static bool aspm_support_enabled = true; + static DEFINE_MUTEX(aspm_lock); + static LIST_HEAD(link_list); +@@ -500,9 +500,6 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) + int pos; + u32 reg32; + +- if (aspm_clear_state) +- return -EINVAL; +- + /* + * Some functions in a slot might not all be PCIe functions, + * very strange. Disable ASPM for the whole slot +@@ -574,9 +571,6 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) + pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) + return; + +- if (aspm_disabled && !aspm_clear_state) +- return; +- + /* VIA has a strange chipset, root port is under a bridge */ + if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT && + pdev->bus->self) +@@ -608,7 +602,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 || aspm_clear_state) { ++ if (aspm_policy != POLICY_POWERSAVE) { + pcie_config_aspm_path(link); + pcie_set_clkpm(link, policy_to_clkpm_state(link)); + } +@@ -649,8 +643,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) + struct pci_dev *parent = pdev->bus->self; + struct pcie_link_state *link, *root, *parent_link; + +- if ((aspm_disabled && !aspm_clear_state) || !pci_is_pcie(pdev) || +- !parent || !parent->link_state) ++ if (!pci_is_pcie(pdev) || !parent || !parent->link_state) + return; + if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && + (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) +@@ -734,13 +727,18 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev) + * pci_disable_link_state - disable pci device's link state, so the link will + * never enter specific states + */ +-static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) ++static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem, ++ bool force) + { + struct pci_dev *parent = pdev->bus->self; + struct pcie_link_state *link; + +- if (aspm_disabled || !pci_is_pcie(pdev)) ++ if (aspm_disabled && !force) ++ return; ++ ++ if (!pci_is_pcie(pdev)) + return; ++ + if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT || + pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) + parent = pdev; +@@ -768,16 +766,31 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) + + void pci_disable_link_state_locked(struct pci_dev *pdev, int state) + { +- __pci_disable_link_state(pdev, state, false); ++ __pci_disable_link_state(pdev, state, false, false); + } + EXPORT_SYMBOL(pci_disable_link_state_locked); + + void pci_disable_link_state(struct pci_dev *pdev, int state) + { +- __pci_disable_link_state(pdev, state, true); ++ __pci_disable_link_state(pdev, state, true, false); + } + EXPORT_SYMBOL(pci_disable_link_state); + ++void pcie_clear_aspm(struct pci_bus *bus) ++{ ++ struct pci_dev *child; ++ ++ /* ++ * Clear any ASPM setup that the firmware has carried out on this bus ++ */ ++ list_for_each_entry(child, &bus->devices, bus_list) { ++ __pci_disable_link_state(child, PCIE_LINK_STATE_L0S | ++ PCIE_LINK_STATE_L1 | ++ PCIE_LINK_STATE_CLKPM, ++ false, true); ++ } ++} ++ + static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp) + { + int i; +@@ -935,6 +948,7 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) + static int __init pcie_aspm_disable(char *str) + { + if (!strcmp(str, "off")) { ++ aspm_policy = POLICY_DEFAULT; + aspm_disabled = 1; + aspm_support_enabled = false; + printk(KERN_INFO "PCIe ASPM is disabled\n"); +@@ -947,16 +961,18 @@ static int __init pcie_aspm_disable(char *str) + + __setup("pcie_aspm=", pcie_aspm_disable); + +-void pcie_clear_aspm(void) +-{ +- if (!aspm_force) +- aspm_clear_state = 1; +-} +- + void pcie_no_aspm(void) + { +- if (!aspm_force) ++ /* ++ * Disabling ASPM is intended to prevent the kernel from modifying ++ * existing hardware state, not to clear existing state. To that end: ++ * (a) set policy to POLICY_DEFAULT in order to avoid changing state ++ * (b) prevent userspace from changing policy ++ */ ++ if (!aspm_force) { ++ aspm_policy = POLICY_DEFAULT; + aspm_disabled = 1; ++ } + } + + /** +diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h +index 7cea7b6..c832014 100644 +--- a/include/linux/pci-aspm.h ++++ b/include/linux/pci-aspm.h +@@ -29,7 +29,7 @@ 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 pci_disable_link_state_locked(struct pci_dev *pdev, int state); +-extern void pcie_clear_aspm(void); ++extern void pcie_clear_aspm(struct pci_bus *bus); + extern void pcie_no_aspm(void); + #else + static inline void pcie_aspm_init_link_state(struct pci_dev *pdev) +@@ -47,7 +47,7 @@ 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) + { + } +-static inline void pcie_clear_aspm(void) ++static inline void pcie_clear_aspm(struct pci_bus *bus) + { + } + static inline void pcie_no_aspm(void) +-- +1.7.7.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-acpi" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + From 1d542ed4c2cfd5b4b7a26f24b6c39acdc45df4f7 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Tue, 6 Dec 2011 14:21:27 -0500 Subject: [PATCH 242/397] Disable uas until someone can fix it (rhbz #717633) --- config-generic | 3 ++- kernel.spec | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index f9acd1913..a459ec6f3 100644 --- a/config-generic +++ b/config-generic @@ -3109,7 +3109,8 @@ CONFIG_USB_STORAGE_REALTEK=m CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set -CONFIG_USB_UAS=m +# uas is broken (#717633, #744099) +# CONFIG_USB_UAS is not set # diff --git a/kernel.spec b/kernel.spec index 9ca6724cd..28f58d208 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1900,6 +1900,9 @@ fi # and build. %changelog +* Tue Dec 06 2011 Chuck Ebbert +- Disable uas until someone can fix it (rhbz #717633) + * Tue Dec 06 2011 Josh Boyer - Add reworked pci ASPM patch from Matthew Garrett From 16571df650917e4033a9450dec890e87eca39ed4 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 7 Dec 2011 11:49:48 -0500 Subject: [PATCH 243/397] Linux 3.1.5-rc1 (Fedora 2.6.41.5-rc1) Comment out merged patches: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch rtlwifi-fix-lps_lock-deadlock.patch --- config-arm-omap-generic | 1 + config-arm-tegra | 1 + kernel.spec | 16 +++++++++++----- sources | 1 + 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/config-arm-omap-generic b/config-arm-omap-generic index 16e665329..657f548a2 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -121,6 +121,7 @@ CONFIG_ARM_ERRATA_430973=y # CONFIG_ARM_ERRATA_742230 is not set # CONFIG_ARM_ERRATA_742231 is not set CONFIG_PL310_ERRATA_588369=y +CONFIG_PL310_ERRATA_769419=y CONFIG_ARM_ERRATA_720789=y # CONFIG_ARM_ERRATA_743622 is not set # CONFIG_ARM_ERRATA_751472 is not set diff --git a/config-arm-tegra b/config-arm-tegra index 910b39f81..b131978d2 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -34,6 +34,7 @@ CONFIG_ARM_ERRATA_430973=y CONFIG_ARM_ERRATA_742230=y # CONFIG_ARM_ERRATA_742231 is not set CONFIG_PL310_ERRATA_588369=y +CONFIG_PL310_ERRATA_769419=y CONFIG_ARM_ERRATA_720789=y # CONFIG_PL310_ERRATA_727915 is not set # CONFIG_ARM_ERRATA_743622 is not set diff --git a/kernel.spec b/kernel.spec index 28f58d208..57b1b1fd0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 5 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,9 +51,9 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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} @@ -1118,7 +1118,7 @@ ApplyPatch linux-2.6-i386-nx-emulation.patch ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # xfs -ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch +#ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch # btrfs @@ -1276,7 +1276,7 @@ ApplyPatch cciss-fix-irqf-shared.patch ApplyPatch hpsa-add-irqf-shared.patch #rhbz 755154 -ApplyPatch rtlwifi-fix-lps_lock-deadlock.patch +#ApplyPatch rtlwifi-fix-lps_lock-deadlock.patch #rhbz 731365 ApplyPatch mac80211_offchannel_rework_revert.patch @@ -1900,6 +1900,12 @@ fi # and build. %changelog +* Wed Dec 07 2011 Chuck Ebbert 2.6.41.5-0.rc1.1 +- Linux 3.1.5-rc1 (Fedora 2.6.41.5-rc1) +- Comment out merged patches: + xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch + rtlwifi-fix-lps_lock-deadlock.patch + * Tue Dec 06 2011 Chuck Ebbert - Disable uas until someone can fix it (rhbz #717633) diff --git a/sources b/sources index bae460776..a60aa9318 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 b8b14bdfbf76cfef8e042e7d1a385fca patch-3.1.4.bz2 +cb4154af3daf6279680b808b6affc374 patch-3.1.5-rc1.bz2 From 8b4e9aeab7bfc5edcb153f781164e3725210eae5 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 8 Dec 2011 12:03:54 -0500 Subject: [PATCH 244/397] Linux 3.1.5-rc2 (Fedora 2.6.41.5-rc2) --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 57b1b1fd0..eb879c9b0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -53,7 +53,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 2 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev .%{stable_update} @@ -1900,7 +1900,10 @@ fi # and build. %changelog -* Wed Dec 07 2011 Chuck Ebbert 2.6.41.5-0.rc1.1 +* Thu Dec 08 2011 Chuck Ebbert 2.6.41.5-0.rc2.1 +- Linux 3.1.5-rc2 (Fedora 2.6.41.5-rc2) + +* Wed Dec 07 2011 Chuck Ebbert - Linux 3.1.5-rc1 (Fedora 2.6.41.5-rc1) - Comment out merged patches: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch diff --git a/sources b/sources index a60aa9318..4b15b125b 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 b8b14bdfbf76cfef8e042e7d1a385fca patch-3.1.4.bz2 -cb4154af3daf6279680b808b6affc374 patch-3.1.5-rc1.bz2 +c3b84ad19528dd670288e0b0bad8fdac patch-3.1.5-rc2.bz2 From 2da231f40cfdb8611edf4dafb2e27fd279c20fe4 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 8 Dec 2011 20:30:28 -0500 Subject: [PATCH 245/397] Fix wrong link speed on some sky2 network adapters (rhbz #757839) --- kernel.spec | 7 +++++ net-sky2-88e8059-fix-link-speed.patch | 42 +++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 net-sky2-88e8059-fix-link-speed.patch diff --git a/kernel.spec b/kernel.spec index eb879c9b0..0ec1019b8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -696,6 +696,9 @@ Patch21220: mac80211_offchannel_rework_revert.patch Patch21225: pci-Rework-ASPM-disable-code.patch +#rhbz #757839 +Patch21230: net-sky2-88e8059-fix-link-speed.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1283,6 +1286,9 @@ ApplyPatch mac80211_offchannel_rework_revert.patch ApplyPatch pci-Rework-ASPM-disable-code.patch +#rhbz #757839 +ApplyPatch net-sky2-88e8059-fix-link-speed.patch + # END OF PATCH APPLICATIONS %endif @@ -1902,6 +1908,7 @@ fi %changelog * Thu Dec 08 2011 Chuck Ebbert 2.6.41.5-0.rc2.1 - Linux 3.1.5-rc2 (Fedora 2.6.41.5-rc2) +- Fix wrong link speed on some sky2 network adapters (rhbz #757839) * Wed Dec 07 2011 Chuck Ebbert - Linux 3.1.5-rc1 (Fedora 2.6.41.5-rc1) diff --git a/net-sky2-88e8059-fix-link-speed.patch b/net-sky2-88e8059-fix-link-speed.patch new file mode 100644 index 000000000..61e1c75df --- /dev/null +++ b/net-sky2-88e8059-fix-link-speed.patch @@ -0,0 +1,42 @@ +commit 27d240fdae2808d727ad9ce48ec029731a457524 +Author: stephen hemminger +Date: Fri Nov 4 12:17:17 2011 +0000 + + sky2: fix regression on Yukon Optima + + [ backport to 3.1 ] + + Changes to support other Optima types, introduced an accidental + regression that caused 88E8059 to come up in 10Mbit/sec. + + The Yukon Optima supports a reverse auto-negotiation feature that + was incorrectly setup, and not needed. The feature could be used to + allow wake-on-lan at higher speeds. But doing it correctly would require + other changes to initialization. + + Reported-by: Pavel Mateja + Signed-off-by: Stephen Hemminger + Signed-off-by: David S. Miller + +diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c +index cbd026f..fdc6c39 100644 +--- a/drivers/net/sky2.c ++++ b/drivers/net/sky2.c +@@ -366,17 +366,6 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) + gm_phy_write(hw, port, PHY_MARV_FE_SPEC_2, spec); + } + } else { +- if (hw->chip_id >= CHIP_ID_YUKON_OPT) { +- u16 ctrl2 = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL_2); +- +- /* enable PHY Reverse Auto-Negotiation */ +- ctrl2 |= 1u << 13; +- +- /* Write PHY changes (SW-reset must follow) */ +- gm_phy_write(hw, port, PHY_MARV_EXT_CTRL_2, ctrl2); +- } +- +- + /* disable energy detect */ + ctrl &= ~PHY_M_PC_EN_DET_MSK; + From f906e021ead33c7c033fd79c0aacd19bd93597bc Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 9 Dec 2011 12:30:53 -0500 Subject: [PATCH 246/397] Linux 3.1.5 (Fedora 2.6.41.5) --- kernel.spec | 5 ++++- sources | 3 +-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 0ec1019b8..68f3e39e0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -53,7 +53,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 2 +%define stable_rc 0 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev .%{stable_update} @@ -1906,6 +1906,9 @@ fi # and build. %changelog +* Fri Dec 09 2011 Josh Boyer 2.6.41.5-1 +- Linux 3.1.5 (Fedora 2.6.41.5) + * Thu Dec 08 2011 Chuck Ebbert 2.6.41.5-0.rc2.1 - Linux 3.1.5-rc2 (Fedora 2.6.41.5-rc2) - Fix wrong link speed on some sky2 network adapters (rhbz #757839) diff --git a/sources b/sources index 4b15b125b..87c391c01 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -b8b14bdfbf76cfef8e042e7d1a385fca patch-3.1.4.bz2 -c3b84ad19528dd670288e0b0bad8fdac patch-3.1.5-rc2.bz2 +84c040bb8c4f46d351731cb0c05d9474 patch-3.1.5.bz2 From de6db0d55bb29a9aafa58618c622766a7ec4d877 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 9 Dec 2011 16:31:35 -0500 Subject: [PATCH 247/397] spec cleanup: drop commented out patches --- kernel.spec | 12 +- rtlwifi-fix-lps_lock-deadlock.patch | 224 ------------------ ...le-memory-corruption-in-xfs_readlink.patch | 77 ------ 3 files changed, 1 insertion(+), 312 deletions(-) delete mode 100644 rtlwifi-fix-lps_lock-deadlock.patch delete mode 100644 xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch diff --git a/kernel.spec b/kernel.spec index 68f3e39e0..aef238933 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -669,9 +669,6 @@ Patch21022: mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch Patch21030: be2net-non-member-vlan-pkts-not-received-in-promisco.patch Patch21031: benet-remove-bogus-unlikely-on-vlan-check.patch -#rhbz 749166 -Patch21050: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch - Patch21070: oom-fix-integer-overflow-of-points.patch #rhbz 728607 @@ -688,9 +685,6 @@ Patch21091: bcma-brcmsmac-compat.patch Patch21100: cciss-fix-irqf-shared.patch Patch21101: hpsa-add-irqf-shared.patch -#rhbz 755154 -Patch21200: rtlwifi-fix-lps_lock-deadlock.patch - #rhbz 731365 Patch21220: mac80211_offchannel_rework_revert.patch @@ -1121,7 +1115,6 @@ ApplyPatch linux-2.6-i386-nx-emulation.patch ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # xfs -#ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch # btrfs @@ -1278,9 +1271,6 @@ ApplyPatch bcma-brcmsmac-compat.patch ApplyPatch cciss-fix-irqf-shared.patch ApplyPatch hpsa-add-irqf-shared.patch -#rhbz 755154 -#ApplyPatch rtlwifi-fix-lps_lock-deadlock.patch - #rhbz 731365 ApplyPatch mac80211_offchannel_rework_revert.patch diff --git a/rtlwifi-fix-lps_lock-deadlock.patch b/rtlwifi-fix-lps_lock-deadlock.patch deleted file mode 100644 index 4e31ee9b7..000000000 --- a/rtlwifi-fix-lps_lock-deadlock.patch +++ /dev/null @@ -1,224 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Stanislaw Gruszka -Newsgroups: gmane.linux.kernel.wireless.general -Subject: [PATCH v2] rtlwifi: fix lps_lock deadlock -Date: Mon, 28 Nov 2011 10:33:40 +0100 -Lines: 169 -Approved: news@gmane.org -Message-ID: <20111128093339.GC2372@redhat.com> -References: <1322219327-23148-1-git-send-email-sgruszka@redhat.com> - <4ECFD1BF.4070503@lwfinger.net> - <20111128092308.GB2372@redhat.com> -NNTP-Posting-Host: lo.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Trace: dough.gmane.org 1322472712 10173 80.91.229.12 (28 Nov 2011 09:31:52 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Mon, 28 Nov 2011 09:31:52 +0000 (UTC) -Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, - Chaoming Li -To: Larry Finger , - "John W. Linville" -Original-X-From: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Mon Nov 28 10:31:45 2011 -Return-path: -Envelope-to: glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1RUxYu-0002H1-AY - for glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Mon, 28 Nov 2011 10:31:44 +0100 -Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand - id S1751698Ab1K1Jbm (ORCPT - ); - Mon, 28 Nov 2011 04:31:42 -0500 -Original-Received: from mx1.redhat.com ([209.132.183.28]:62078 "EHLO mx1.redhat.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1751434Ab1K1Jbl (ORCPT ); - Mon, 28 Nov 2011 04:31:41 -0500 -Original-Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id pAS9VSak003418 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Mon, 28 Nov 2011 04:31:28 -0500 -Original-Received: from localhost (vpn1-4-194.ams2.redhat.com [10.36.4.194]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id pAS9VQNG013260; - Mon, 28 Nov 2011 04:31:27 -0500 -Content-Disposition: inline -In-Reply-To: <20111128092308.GB2372-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> -User-Agent: Mutt/1.5.20 (2009-12-10) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Original-Sender: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Xref: news.gmane.org gmane.linux.kernel.wireless.general:81657 -Archived-At: - -rtl_lps_leave can be called from interrupt context, so we have to -disable interrupts when taking lps_lock. - -Below is full lockdep info about deadlock: - -[ 93.815269] ================================= -[ 93.815390] [ INFO: inconsistent lock state ] -[ 93.815472] 2.6.41.1-3.offch.fc15.x86_64.debug #1 -[ 93.815556] --------------------------------- -[ 93.815635] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. -[ 93.815743] swapper/0 [HC0[0]:SC1[1]:HE1:SE0] takes: -[ 93.815832] (&(&rtlpriv->locks.lps_lock)->rlock){+.?...}, at: [] rtl_lps_leave+0x26/0x103 [rtlwifi] -[ 93.815947] {SOFTIRQ-ON-W} state was registered at: -[ 93.815947] [] __lock_acquire+0x369/0xd0c -[ 93.815947] [] lock_acquire+0xf3/0x13e -[ 93.815947] [] _raw_spin_lock+0x45/0x79 -[ 93.815947] [] rtl_swlps_rf_awake+0x5a/0x76 [rtlwifi] -[ 93.815947] [] rtl_op_config+0x12a/0x32a [rtlwifi] -[ 93.815947] [] ieee80211_hw_config+0x124/0x129 [mac80211] -[ 93.815947] [] ieee80211_dynamic_ps_disable_work+0x32/0x47 [mac80211] -[ 93.815947] [] process_one_work+0x205/0x3e7 -[ 93.815947] [] worker_thread+0xda/0x15d -[ 93.815947] [] kthread+0xa8/0xb0 -[ 93.815947] [] kernel_thread_helper+0x4/0x10 -[ 93.815947] irq event stamp: 547822 -[ 93.815947] hardirqs last enabled at (547822): [] _raw_spin_unlock_irqrestore+0x45/0x61 -[ 93.815947] hardirqs last disabled at (547821): [] _raw_spin_lock_irqsave+0x22/0x8e -[ 93.815947] softirqs last enabled at (547790): [] _local_bh_enable+0x13/0x15 -[ 93.815947] softirqs last disabled at (547791): [] call_softirq+0x1c/0x30 -[ 93.815947] -[ 93.815947] other info that might help us debug this: -[ 93.815947] Possible unsafe locking scenario: -[ 93.815947] -[ 93.815947] CPU0 -[ 93.815947] ---- -[ 93.815947] lock(&(&rtlpriv->locks.lps_lock)->rlock); -[ 93.815947] -[ 93.815947] lock(&(&rtlpriv->locks.lps_lock)->rlock); -[ 93.815947] -[ 93.815947] *** DEADLOCK *** -[ 93.815947] -[ 93.815947] no locks held by swapper/0. -[ 93.815947] -[ 93.815947] stack backtrace: -[ 93.815947] Pid: 0, comm: swapper Not tainted 2.6.41.1-3.offch.fc15.x86_64.debug #1 -[ 93.815947] Call Trace: -[ 93.815947] [] print_usage_bug+0x1e7/0x1f8 -[ 93.815947] [] ? save_stack_trace+0x2c/0x49 -[ 93.815947] [] ? print_irq_inversion_bug.part.18+0x1a0/0x1a0 -[ 93.815947] [] mark_lock+0x106/0x220 -[ 93.815947] [] __lock_acquire+0x2f5/0xd0c -[ 93.815947] [] ? native_sched_clock+0x34/0x36 -[ 93.830125] [] ? sched_clock+0x9/0xd -[ 93.830125] [] ? sched_clock_local+0x12/0x75 -[ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] -[ 93.830125] [] lock_acquire+0xf3/0x13e -[ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] -[ 93.830125] [] _raw_spin_lock+0x45/0x79 -[ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] -[ 93.830125] [] ? skb_dequeue+0x62/0x6d -[ 93.830125] [] rtl_lps_leave+0x26/0x103 [rtlwifi] -[ 93.830125] [] _rtl_pci_ips_leave_tasklet+0xe/0x10 [rtlwifi] -[ 93.830125] [] tasklet_action+0x8d/0xee -[ 93.830125] [] __do_softirq+0x112/0x25a -[ 93.830125] [] call_softirq+0x1c/0x30 -[ 93.830125] [] do_softirq+0x4b/0xa1 -[ 93.830125] [] irq_exit+0x5d/0xcf -[ 93.830125] [] do_IRQ+0x8e/0xa5 -[ 93.830125] [] common_interrupt+0x73/0x73 -[ 93.830125] [] ? trace_hardirqs_off+0xd/0xf -[ 93.830125] [] ? intel_idle+0xe5/0x10c -[ 93.830125] [] ? intel_idle+0xe1/0x10c -[ 93.830125] [] cpuidle_idle_call+0x11c/0x1fe -[ 93.830125] [] cpu_idle+0xab/0x101 -[ 93.830125] [] rest_init+0xd7/0xde -[ 93.830125] [] ? csum_partial_copy_generic+0x16c/0x16c -[ 93.830125] [] start_kernel+0x3dd/0x3ea -[ 93.830125] [] x86_64_start_reservations+0xaf/0xb3 -[ 93.830125] [] ? early_idt_handlers+0x140/0x140 -[ 93.830125] [] x86_64_start_kernel+0x102/0x111 - -Resolves: -https://bugzilla.redhat.com/show_bug.cgi?id=755154 - -Reported-by: vjain02-9geRo0GdX4mblYp+tMVdN4dd74u8MsAO@public.gmane.org -Reported-and-tested-by: Oliver Paukstadt -Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Acked-by: Larry Finger -Signed-off-by: Stanislaw Gruszka ---- -v1 -> v2: add bug report reference - - drivers/net/wireless/rtlwifi/ps.c | 17 +++++++++-------- - 1 files changed, 9 insertions(+), 8 deletions(-) - -diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c -index db52628..55c8e50 100644 ---- a/drivers/net/wireless/rtlwifi/ps.c -+++ b/drivers/net/wireless/rtlwifi/ps.c -@@ -395,7 +395,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) - if (mac->link_state != MAC80211_LINKED) - return; - -- spin_lock(&rtlpriv->locks.lps_lock); -+ spin_lock_irq(&rtlpriv->locks.lps_lock); - - /* Idle for a while if we connect to AP a while ago. */ - if (mac->cnt_after_linked >= 2) { -@@ -407,7 +407,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) - } - } - -- spin_unlock(&rtlpriv->locks.lps_lock); -+ spin_unlock_irq(&rtlpriv->locks.lps_lock); - } - - /*Leave the leisure power save mode.*/ -@@ -416,8 +416,9 @@ void rtl_lps_leave(struct ieee80211_hw *hw) - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ unsigned long flags; - -- spin_lock(&rtlpriv->locks.lps_lock); -+ spin_lock_irqsave(&rtlpriv->locks.lps_lock, flags); - - if (ppsc->fwctrl_lps) { - if (ppsc->dot11_psmode != EACTIVE) { -@@ -438,7 +439,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw) - rtl_lps_set_psmode(hw, EACTIVE); - } - } -- spin_unlock(&rtlpriv->locks.lps_lock); -+ spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flags); - } - - /* For sw LPS*/ -@@ -539,9 +540,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw) - RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); - } - -- spin_lock(&rtlpriv->locks.lps_lock); -+ spin_lock_irq(&rtlpriv->locks.lps_lock); - rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS); -- spin_unlock(&rtlpriv->locks.lps_lock); -+ spin_unlock_irq(&rtlpriv->locks.lps_lock); - } - - void rtl_swlps_rfon_wq_callback(void *data) -@@ -574,9 +575,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw) - if (rtlpriv->link_info.busytraffic) - return; - -- spin_lock(&rtlpriv->locks.lps_lock); -+ spin_lock_irq(&rtlpriv->locks.lps_lock); - rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS); -- spin_unlock(&rtlpriv->locks.lps_lock); -+ spin_unlock_irq(&rtlpriv->locks.lps_lock); - - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && - !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { --- -1.7.1 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - diff --git a/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch b/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch deleted file mode 100644 index 9e810dba8..000000000 --- a/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch +++ /dev/null @@ -1,77 +0,0 @@ -X-Spam-Checker-Version: SpamAssassin 3.4.0-r929098 (2010-03-30) on oss.sgi.com -X-Spam-Level: -X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,J_CHICKENPOX_64 - autolearn=no version=3.4.0-r929098 -Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) - by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id p9I1KBVD036341 - for ; Mon, 17 Oct 2011 20:20:11 -0500 -X-ASG-Debug-ID: 1318901280-3911029d0000-NocioJ -X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi -Received: from hades.usersys.redhat.com (localhost [127.0.0.1]) - by cuda.sgi.com (Spam Firewall) with ESMTP id B9D1DF75F0A - for ; Mon, 17 Oct 2011 18:28:01 -0700 (PDT) -Received: from hades.usersys.redhat.com ([187.60.101.4]) by cuda.sgi.com with ESMTP id 81CuyNdYBqrtvtnD for ; Mon, 17 Oct 2011 18:28:01 -0700 (PDT) -Received: by hades.usersys.redhat.com (Postfix, from userid 500) - id 5B763E089B; Tue, 18 Oct 2011 02:18:59 -0200 (BRST) -From: Carlos Maiolino -To: xfs@oss.sgi.com -Cc: Carlos Maiolino -X-ASG-Orig-Subj: [PATCH] Fix possible memory corruption in xfs_readlink -Subject: [PATCH] Fix possible memory corruption in xfs_readlink -Date: Tue, 18 Oct 2011 02:18:58 -0200 -Message-Id: <1318911538-9174-1-git-send-email-cmaiolino@redhat.com> -X-Mailer: git-send-email 1.7.6.2 -X-Barracuda-Connect: UNKNOWN[187.60.101.4] -X-Barracuda-Start-Time: 1318901282 -X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 -X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com -X-Barracuda-Spam-Score: -1.42 -X-Barracuda-Spam-Status: No, SCORE=-1.42 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=BSF_SC5_MJ1963, RDNS_NONE -X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.2.77645 - Rule breakdown below - pts rule name description - ---- ---------------------- -------------------------------------------------- - 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS - 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 -X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com -X-Virus-Status: Clean - -Fixes a possible memory corruption when the link is larger than -MAXPATHLEN and XFS_DEBUG is not enabled. This also remove the -S_ISLNK assert, since the inode mode is checked previously in -xfs_readlink_by_handle() and via VFS. - -Signed-off-by: Carlos Maiolino ---- - fs/xfs/xfs_vnodeops.c | 11 ++++++++--- - 1 files changed, 8 insertions(+), 3 deletions(-) - -diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c -index 51fc429..c3288be 100644 ---- a/fs/xfs/xfs_vnodeops.c -+++ b/fs/xfs/xfs_vnodeops.c -@@ -123,13 +123,18 @@ xfs_readlink( - - xfs_ilock(ip, XFS_ILOCK_SHARED); - -- ASSERT(S_ISLNK(ip->i_d.di_mode)); -- ASSERT(ip->i_d.di_size <= MAXPATHLEN); -- - pathlen = ip->i_d.di_size; - if (!pathlen) - goto out; - -+ if (pathlen > MAXPATHLEN) { -+ xfs_alert(mp, "%s: inode (%llu) symlink length (%d) too long", -+ __func__, (unsigned long long)ip->i_ino, pathlen); -+ ASSERT(0); -+ return XFS_ERROR(EFSCORRUPTED); -+ } -+ -+ - if (ip->i_df.if_flags & XFS_IFINLINE) { - memcpy(link, ip->i_df.if_u1.if_data, pathlen); - link[pathlen] = '\0'; --- -1.7.6.2 - From 2205d2ae378a46feea20c9a87683b4b91cb43070 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Sun, 11 Dec 2011 11:16:57 -0600 Subject: [PATCH 248/397] add support for highbank, imx and kirkwood boards on arm --- Makefile.config | 26 +++++++++++++ config-arm-generic | 6 +-- config-arm-highbank | 23 +++++++++++ config-arm-imx | 95 +++++++++++++++++++++++++++++++++++++++++++++ config-arm-kirkwood | 50 ++++++++++++++++++++++++ config-arm-tegra | 6 +++ kernel.spec | 65 ++++++++++++++++++++++++++++++- 7 files changed, 267 insertions(+), 4 deletions(-) create mode 100644 config-arm-highbank create mode 100644 config-arm-imx create mode 100644 config-arm-kirkwood diff --git a/Makefile.config b/Makefile.config index d56185c15..10ca31e4a 100644 --- a/Makefile.config +++ b/Makefile.config @@ -10,7 +10,9 @@ CONFIGFILES = \ $(CFG)-x86_64.config $(CFG)-x86_64-debug.config \ $(CFG)-s390x.config \ $(CFG)-arm.config $(CFG)-armv5tel.config \ + $(CFG)-armv5tel-kirkwood.config $(CFG)-armv7l-imx.config \ $(CFG)-armv7l-omap.config $(CFG)-armv7l-tegra.config \ + $(CFG)-armv7hl-imx.config $(CFG)-armv7hl-highbank.config \ $(CFG)-armv7hl-omap.config $(CFG)-armv7hl-tegra.config \ $(CFG)-ppc.config $(CFG)-ppc-smp.config \ $(CFG)-sparc64.config \ @@ -43,6 +45,15 @@ temp-armv7l-omap-generic: config-arm-omap-generic temp-arm-generic temp-armv7l-tegra: config-arm-tegra temp-arm-generic perl merge.pl $^ > $@ +temp-armv5tel-kirkwood: config-arm-kirkwood temp-arm-generic + perl merge.pl $^ > $@ + +temp-armv7l-imx: config-arm-imx temp-arm-generic + perl merge.pl $^ > $@ + +temp-armv7l-highbank: config-arm-highbank temp-arm-generic + perl merge.pl $^ > $@ + temp-x86-32: config-x86-32-generic config-x86-generic perl merge.pl $^ > $@ @@ -112,12 +123,27 @@ kernel-$(VERSION)-arm.config: /dev/null temp-arm-generic kernel-$(VERSION)-armv5tel.config: /dev/null temp-arm-generic perl merge.pl $^ arm > $@ +kernel-$(VERSION)-armv5tel-kirkwood.config: /dev/null temp-armv5tel-kirkwood + perl merge.pl $^ arm > $@ + +kernel-$(VERSION)-armv7l-imx.config: /dev/null temp-armv7l-imx + perl merge.pl $^ arm > $@ + +kernel-$(VERSION)-armv7l-highbank.config: /dev/null temp-armv7l-highbank + perl merge.pl $^ arm > $@ + kernel-$(VERSION)-armv7l-omap.config: /dev/null temp-armv7l-omap-generic perl merge.pl $^ arm > $@ kernel-$(VERSION)-armv7l-tegra.config: /dev/null temp-armv7l-tegra perl merge.pl $^ arm > $@ +kernel-$(VERSION)-armv7hl-imx.config: /dev/null temp-armv7l-imx + perl merge.pl $^ arm > $@ + +kernel-$(VERSION)-armv7hl-highbank.config: /dev/null temp-armv7l-highbank + perl merge.pl $^ arm > $@ + kernel-$(VERSION)-armv7hl-omap.config: /dev/null temp-armv7l-omap-generic perl merge.pl $^ arm > $@ diff --git a/config-arm-generic b/config-arm-generic index 12ae3c30f..92e81e1b5 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -142,8 +142,6 @@ CONFIG_SPARSE_IRQ=y # CONFIG_ARM_PATCH_PHYS_VIRT is not set -CONFIG_FTMAC100=m - CONFIG_HWSPINLOCK_OMAP=m CONFIG_USE_OF=y @@ -154,8 +152,10 @@ CONFIG_MMC_SDHCI_OF=m CONFIG_MMC_SDHCI_PXAV3=m CONFIG_MMC_SDHCI_PXAV2=m -CONFIG_FTGMAC100=m +# CONFIG_FTGMAC100 is not set +# CONFIG_FTMAC100 is not set +# CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 CONFIG_LSM_MMAP_MIN_ADDR=32768 diff --git a/config-arm-highbank b/config-arm-highbank new file mode 100644 index 000000000..f20dfdec0 --- /dev/null +++ b/config-arm-highbank @@ -0,0 +1,23 @@ +ONFIG_ARCH_HIGHBANK=y +CONFIG_VFP=y +CONFIG_NEON=y + +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEBUG=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_STAT_DETAILS=y + + +# these all currently fail due to missing symbols __bad_udelay or +# error: implicit declaration of function ‘iowrite32be’ +# CONFIG_SND_ALI5451 is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_MLX4_EN is not set diff --git a/config-arm-imx b/config-arm-imx new file mode 100644 index 000000000..5ed7ae2ed --- /dev/null +++ b/config-arm-imx @@ -0,0 +1,95 @@ +CONFIG_ARCH_MXC=y +CONFIG_ARCH_MX51=y +CONFIG_MACH_MX51_BABBAGE=y +CONFIG_MACH_MX51_3DS=y +CONFIG_MACH_EUKREA_CPUIMX51=y +CONFIG_VFP=y +CONFIG_NEON=y + +CONFIG_MACH_EUKREA_CPUIMX51SD=y +CONFIG_MACH_MX51_EFIKAMX=y +CONFIG_MACH_MX51_EFIKASB=y +# CONFIG_SWP_EMULATE is not set +# CONFIG_THUMB2_KERNEL is not set +CONFIG_CPU_FREQ_IMX=y +CONFIG_W1_MASTER_MXC=m +CONFIG_IMX_SDMA=y +CONFIG_MACH_MX31ADS=y +CONFIG_MACH_MX31LILLY=y +CONFIG_MACH_MX31LITE=y +CONFIG_MACH_PCM037=y +CONFIG_MACH_MX31_3DS=y +CONFIG_MACH_MX31MOBOARD=y +CONFIG_MACH_QONG=y +CONFIG_MACH_ARMADILLO5X0=y +CONFIG_MACH_KZM_ARM11_01=y +CONFIG_MACH_BUG=y +CONFIG_MACH_PCM043=y +CONFIG_MACH_MX35_3DS=y +CONFIG_MACH_EUKREA_CPUIMX35=y +CONFIG_MACH_VPR200=y +CONFIG_SOC_IMX6Q=y +CONFIG_MXC_IRQ_PRIOR=y +CONFIG_MXC_PWM=m +CONFIG_MXC_DEBUG_BOARD=y +# CONFIG_CPU_BPREDICT_DISABLE is not set +# CONFIG_CACHE_L2X0 is not set +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_ARM_ERRATA_411920=y +CONFIG_PL310_ERRATA_588369=y +CONFIG_PL310_ERRATA_727915=y +CONFIG_ARM_ERRATA_364296=y +CONFIG_HW_PERF_EVENTS=y +CONFIG_RFKILL_GPIO=m +CONFIG_PATA_IMX=m +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_BROADCOM=y +CONFIG_NET_VENDOR_FREESCALE=y +CONFIG_FEC=y +CONFIG_KEYBOARD_IMX=m +CONFIG_SERIAL_IMX=y +CONFIG_HW_RANDOM_MXC_RNGA=m +CONFIG_I2C_IMX=m +CONFIG_GPIO_GENERIC_PLATFORM=y +CONFIG_GPIO_MCP23S08=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_PLL=m +CONFIG_SND_IMX_SOC=m +CONFIG_USB_EHCI_MXC=y +CONFIG_USB_IMX21_HCD=m +CONFIG_MMC_SDHCI_ESDHC_IMX=m +CONFIG_MMC_MXC=m +CONFIG_RTC_MXC=m + +CONFIG_BACKLIGHT_PWM=m +CONFIG_LEDS_PWM=m + +CONFIG_MACH_PCM037_EET=y +# CONFIG_MACH_MX31_3DS_MXC_NAND_USE_BBT is not set +CONFIG_MXC_USE_EPIT=y +CONFIG_ARM_THUMBEE=y +CONFIG_ARM_ERRATA_430973=y +CONFIG_ARM_ERRATA_458693=y +CONFIG_ARM_ERRATA_460075=y +CONFIG_ARM_ERRATA_743622=y +CONFIG_ARM_ERRATA_754322=y +CONFIG_CAN_FLEXCAN=m +CONFIG_MTD_NAND_MXC=m +CONFIG_INPUT_PWM_BEEPER=m +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_IMX2_WDT=m +CONFIG_SND_SOC_PHYCORE_AC97=m +CONFIG_SND_SOC_EUKREA_TLV320=m + +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEBUG=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_STAT_DETAILS=y diff --git a/config-arm-kirkwood b/config-arm-kirkwood new file mode 100644 index 000000000..631be67e7 --- /dev/null +++ b/config-arm-kirkwood @@ -0,0 +1,50 @@ +CONFIG_ARCH_KIRKWOOD=y +CONFIG_MACH_DB88F6281_BP=y +CONFIG_MACH_RD88F6192_NAS=y +CONFIG_MACH_RD88F6281=y +CONFIG_MACH_MV88F6281GTW_GE=y +CONFIG_MACH_SHEEVAPLUG=y +CONFIG_MACH_ESATA_SHEEVAPLUG=y +CONFIG_MACH_GURUPLUG=y +CONFIG_MACH_DOCKSTAR=y +CONFIG_MACH_TS219=y +CONFIG_MACH_TS41X=y +CONFIG_MACH_OPENRD_BASE=y +CONFIG_MACH_OPENRD_CLIENT=y +CONFIG_MACH_OPENRD_ULTIMATE=y +CONFIG_MACH_NETSPACE_V2=y +CONFIG_MACH_INETSPACE_V2=y +CONFIG_MACH_NETSPACE_MAX_V2=y +CONFIG_MACH_D2NET_V2=y +CONFIG_MACH_NET2BIG_V2=y +CONFIG_MACH_NET5BIG_V2=y +CONFIG_MACH_T5325=y +# CONFIG_CPU_FEROCEON_OLD_ID is not set + + +CONFIG_CACHE_FEROCEON_L2=y +CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH=y +CONFIG_MTD_NAND_ORION=m +CONFIG_MV643XX_ETH=m +CONFIG_I2C_MV64XXX=m +CONFIG_GPIO_GENERIC_PLATFORM=y +CONFIG_GPIO_MCP23S08=m +CONFIG_ORION_WATCHDOG=m +CONFIG_SND_KIRKWOOD_SOC=m +CONFIG_SND_KIRKWOOD_SOC_OPENRD=m +CONFIG_SND_KIRKWOOD_SOC_T5325=m +CONFIG_MMC_MVSDIO=m +CONFIG_LEDS_NS2=m +CONFIG_LEDS_NETXBIG=m +CONFIG_RTC_DRV_MV=m +CONFIG_MV_XOR=y +CONFIG_CRYPTO_DEV_MV_CESA=m + +# CONFIG_TOUCHSCREEN_EETI is not set + +# these all currently fail due to missing symbols __bad_udelay or +# error: implicit declaration of function ‘iowrite32be’ +# CONFIG_SND_ALI5451 is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_MLX4_EN is not set + diff --git a/config-arm-tegra b/config-arm-tegra index b131978d2..ce272c1b1 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -83,3 +83,9 @@ CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_CRYSTALHD=m + +# these all currently fail due to missing symbols __bad_udelay or +# error: implicit declaration of function ‘iowrite32be’ +# CONFIG_SND_ALI5451 is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_MLX4_EN is not set diff --git a/kernel.spec b/kernel.spec index aef238933..324159808 100644 --- a/kernel.spec +++ b/kernel.spec @@ -100,6 +100,12 @@ Summary: The Linux kernel %define with_omap %{?_without_omap: 0} %{?!_without_omap: 1} # kernel-tegra (only valid for arm) %define with_tegra %{?_without_tegra: 0} %{?!_without_tegra: 1} +# kernel-kirkwood (only valid for arm) +%define with_kirkwood %{?_without_kirkwood: 0} %{?!_without_kirkwood: 1} +# kernel-imx (only valid for arm) +%define with_imx %{?_without_imx: 0} %{?!_without_imx: 1} +# kernel-highbank (only valid for arm) +%define with_highbank %{?_without_highbank: 0} %{?!_without_highbank: 1} # Build the kernel-doc package, but don't fail the build if it botches. # Here "true" means "continue" and "false" means "fail the build". @@ -189,10 +195,17 @@ Summary: The Linux kernel %define with_pae 0 %endif -# kernel-tegra and omap is only built on armv7 hard and softfp +# kernel-tegra, omap, imx and highbank are only built on armv7 hard and softfp %ifnarch armv7hl armv7l %define with_tegra 0 %define with_omap 0 +%define with_imx 0 +%define with_highbank 0 +%endif + +# kernel-kirkwood is only built for armv5 +%ifnarch armv5tel +%define with_kirkwood 0 %endif # if requested, only build base kernel @@ -520,6 +533,9 @@ Source90: config-sparc64-generic Source100: config-arm-generic Source110: config-arm-omap-generic Source111: config-arm-tegra +Source112: config-arm-kirkwood +Source113: config-arm-imx +Source114: config-arm-highbank # This file is intentionally left empty in the stock kernel. Its a nicety # added for those wanting to do custom rebuilds with altered config opts. @@ -884,6 +900,23 @@ This variant of the kernel has numerous debugging options enabled. It should only be installed when trying to gather additional information on kernel bugs, as some of these options impact performance noticably. +%define variant_summary The Linux kernel compiled for marvell kirkwood boards +%kernel_variant_package kirkwood +%description kirkwood +This package includes a version of the Linux kernel with support for +marvell kirkwood based systems, i.e., guruplug, sheevaplug + +%define variant_summary The Linux kernel compiled for freescale boards +%kernel_variant_package imx +%description imx +This package includes a version of the Linux kernel with support for +freescale based systems, i.e., efika smartbook. + +%define variant_summary The Linux kernel compiled for Calxeda boards +%kernel_variant_package highbank +%description highbank +This package includes a version of the Linux kernel with support for +Calxeda based systems, i.e., HP arm servers. %define variant_summary The Linux kernel compiled for TI-OMAP boards %kernel_variant_package omap @@ -1470,6 +1503,12 @@ BuildKernel() { if [ -d arch/%{asmarch}/include ]; then cp -a --parents arch/%{asmarch}/include $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/ fi + # include the machine specific headers for ARM variants, if available. +%ifarch %{arm} + if [ -d arch/%{asmarch}/mach-${Flavour}/include ]; then + cp -a --parents arch/%{asmarch}/mach-${Flavour}/include $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/ + fi +%endif cp -a include $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include # Make sure the Makefile and version.h have a matching timestamp so that @@ -1573,6 +1612,18 @@ BuildKernel %make_target %kernel_image PAEdebug BuildKernel %make_target %kernel_image PAE %endif +%if %{with_kirkwood} +BuildKernel %make_target %kernel_image kirkwood +%endif + +%if %{with_imx} +BuildKernel %make_target %kernel_image imx +%endif + +%if %{with_highbank} +BuildKernel %make_target %kernel_image highbank +%endif + %if %{with_omap} BuildKernel %make_target %kernel_image omap %endif @@ -1773,6 +1824,15 @@ fi}\ %kernel_variant_post -v PAEdebug -r (kernel|kernel-smp) %kernel_variant_preun PAEdebug +%kernel_variant_preun kirkwood +%kernel_variant_post -v kirkwood + +%kernel_variant_preun imx +%kernel_variant_post -v imx + +%kernel_variant_preun highbank +%kernel_variant_post -v highbank + %kernel_variant_preun omap %kernel_variant_post -v omap @@ -1889,6 +1949,9 @@ fi %kernel_variant_files %{with_debug} debug %kernel_variant_files %{with_pae} PAE %kernel_variant_files %{with_pae_debug} PAEdebug +%kernel_variant_files %{with_kirkwood} kirkwood +%kernel_variant_files %{with_imx} imx +%kernel_variant_files %{with_highbank} highbank %kernel_variant_files %{with_omap} omap %kernel_variant_files %{with_tegra} tegra From d02fa968e9d84c7860b6364840ee4caa7dfcb6cd Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Mon, 12 Dec 2011 17:00:13 -0600 Subject: [PATCH 249/397] Make armv7l highbank kernel config --- Makefile.config | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.config b/Makefile.config index 10ca31e4a..e4e7b7d24 100644 --- a/Makefile.config +++ b/Makefile.config @@ -10,7 +10,8 @@ CONFIGFILES = \ $(CFG)-x86_64.config $(CFG)-x86_64-debug.config \ $(CFG)-s390x.config \ $(CFG)-arm.config $(CFG)-armv5tel.config \ - $(CFG)-armv5tel-kirkwood.config $(CFG)-armv7l-imx.config \ + $(CFG)-armv5tel-kirkwood.config \ + $(CFG)-armv7l-imx.config $(CFG)-armv7l-highbank.config \ $(CFG)-armv7l-omap.config $(CFG)-armv7l-tegra.config \ $(CFG)-armv7hl-imx.config $(CFG)-armv7hl-highbank.config \ $(CFG)-armv7hl-omap.config $(CFG)-armv7hl-tegra.config \ From 94f063e126f0b9f5ce6281def10781c0a1966ad7 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 14 Dec 2011 20:23:59 -0500 Subject: [PATCH 250/397] Disable Intel IOMMU by default. --- config-x86-generic | 2 +- kernel.spec | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/config-x86-generic b/config-x86-generic index 4252062dc..23aecbbef 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -39,7 +39,7 @@ CONFIG_FB_EFI=y CONFIG_DMAR=y CONFIG_DMAR_BROKEN_GFX_WA=y CONFIG_DMAR_FLOPPY_WA=y -CONFIG_DMAR_DEFAULT_ON=y +# CONFIG_DMAR_DEFAULT_ON is not set CONFIG_SCSI_ADVANSYS=m CONFIG_SECCOMP=y diff --git a/kernel.spec b/kernel.spec index 324159808..77c3d3bf2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -1959,6 +1959,9 @@ fi # and build. %changelog +* Thu Dec 15 2011 Dave Jones - 2.6.41.5-3 +- Disable Intel IOMMU by default. + * Fri Dec 09 2011 Josh Boyer 2.6.41.5-1 - Linux 3.1.5 (Fedora 2.6.41.5) From 504b3ab58dc196aad81f68e697d39da568277726 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 8 Dec 2011 10:14:55 -0500 Subject: [PATCH 251/397] Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735) --- kernel.spec | 9 ++ nfs-client-freezer.patch | 299 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 308 insertions(+) create mode 100644 nfs-client-freezer.patch diff --git a/kernel.spec b/kernel.spec index 77c3d3bf2..675487dd7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -709,6 +709,9 @@ Patch21225: pci-Rework-ASPM-disable-code.patch #rhbz #757839 Patch21230: net-sky2-88e8059-fix-link-speed.patch +#rhbz 717735 +Patch21045: nfs-client-freezer.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1312,6 +1315,9 @@ ApplyPatch pci-Rework-ASPM-disable-code.patch #rhbz #757839 ApplyPatch net-sky2-88e8059-fix-link-speed.patch +#rhbz 717735 +ApplyPatch nfs-client-freezer.patch + # END OF PATCH APPLICATIONS %endif @@ -1959,6 +1965,9 @@ fi # and build. %changelog +* Thu Dec 15 2011 Josh Boyer +- Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735) + * Thu Dec 15 2011 Dave Jones - 2.6.41.5-3 - Disable Intel IOMMU by default. diff --git a/nfs-client-freezer.patch b/nfs-client-freezer.patch new file mode 100644 index 000000000..6b4d34d8a --- /dev/null +++ b/nfs-client-freezer.patch @@ -0,0 +1,299 @@ +@@ -, +, @@ + fs/cifs/transport.c | 3 ++- + include/linux/freezer.h | 19 +++++++++++++++++-- + 2 files changed, 19 insertions(+), 3 deletions(-) +--- a/fs/cifs/transport.c ++++ a/fs/cifs/transport.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -324,7 +325,7 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) + { + int error; + +- error = wait_event_killable(server->response_q, ++ error = wait_event_freezekillable(server->response_q, + midQ->midState != MID_REQUEST_SUBMITTED); + if (error < 0) + return -ERESTARTSYS; +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -134,10 +134,25 @@ static inline void set_freezable_with_signal(void) + } + + /* +- * Freezer-friendly wrappers around wait_event_interruptible() and +- * wait_event_interruptible_timeout(), originally defined in ++ * Freezer-friendly wrappers around wait_event_interruptible(), ++ * wait_event_killable() and wait_event_interruptible_timeout(), originally ++ * defined in + */ + ++#define wait_event_freezekillable(wq, condition) \ ++({ \ ++ int __retval; \ ++ do { \ ++ __retval = wait_event_killable(wq, \ ++ (condition) || freezing(current)); \ ++ if (__retval && !freezing(current)) \ ++ break; \ ++ else if (!(condition)) \ ++ __retval = -ERESTARTSYS; \ ++ } while (try_to_freeze()); \ ++ __retval; \ ++}) ++ + #define wait_event_freezable(wq, condition) \ + ({ \ + int __retval; \ + include/linux/freezer.h | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -143,7 +143,7 @@ static inline void set_freezable_with_signal(void) + ({ \ + int __retval; \ + do { \ +- __retval = wait_event_killable(wq, \ ++ __retval = wait_event_killable(wq, \ + (condition) || freezing(current)); \ + if (__retval && !freezing(current)) \ + break; \ + include/linux/freezer.h | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -203,6 +203,9 @@ static inline void set_freezable_with_signal(void) {} + #define wait_event_freezable_timeout(wq, condition, timeout) \ + wait_event_interruptible_timeout(wq, condition, timeout) + ++#define wait_event_freezekillable(wq, condition) \ ++ wait_event_killable(wq, condition) ++ + #endif /* !CONFIG_FREEZER */ + + #endif /* FREEZER_H_INCLUDED */ + description on Rafael's request.] + include/linux/freezer.h | 11 +++-------- + 1 files changed, 3 insertions(+), 8 deletions(-) +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -142,14 +142,9 @@ static inline void set_freezable_with_signal(void) + #define wait_event_freezekillable(wq, condition) \ + ({ \ + int __retval; \ +- do { \ +- __retval = wait_event_killable(wq, \ +- (condition) || freezing(current)); \ +- if (__retval && !freezing(current)) \ +- break; \ +- else if (!(condition)) \ +- __retval = -ERESTARTSYS; \ +- } while (try_to_freeze()); \ ++ freezer_do_not_count(); \ ++ __retval = wait_event_killable(wq, (condition)); \ ++ freezer_count(); \ + __retval; \ + }) + + fs/nfs/inode.c | 3 ++- + fs/nfs/nfs3proc.c | 3 ++- + fs/nfs/nfs4proc.c | 5 +++-- + fs/nfs/proc.c | 3 ++- + include/linux/freezer.h | 28 ++++++++++++++++++++++++++++ + net/sunrpc/sched.c | 3 ++- + 6 files changed, 39 insertions(+), 6 deletions(-) +--- a/fs/nfs/inode.c ++++ a/fs/nfs/inode.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -77,7 +78,7 @@ int nfs_wait_bit_killable(void *word) + { + if (fatal_signal_pending(current)) + return -ERESTARTSYS; +- schedule(); ++ freezable_schedule(); + return 0; + } + +--- a/fs/nfs/nfs3proc.c ++++ a/fs/nfs/nfs3proc.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + #include "iostat.h" + #include "internal.h" +@@ -32,7 +33,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) + res = rpc_call_sync(clnt, msg, flags); + if (res != -EJUKEBOX && res != -EKEYEXPIRED) + break; +- schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); ++ freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); + res = -ERESTARTSYS; + } while (!fatal_signal_pending(current)); + return res; +--- a/fs/nfs/nfs4proc.c ++++ a/fs/nfs/nfs4proc.c +@@ -53,6 +53,7 @@ + #include + #include + #include ++#include + + #include "nfs4_fs.h" + #include "delegation.h" +@@ -244,7 +245,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) + *timeout = NFS4_POLL_RETRY_MIN; + if (*timeout > NFS4_POLL_RETRY_MAX) + *timeout = NFS4_POLL_RETRY_MAX; +- schedule_timeout_killable(*timeout); ++ freezable_schedule_timeout_killable(*timeout); + if (fatal_signal_pending(current)) + res = -ERESTARTSYS; + *timeout <<= 1; +@@ -3970,7 +3971,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 + static unsigned long + nfs4_set_lock_task_retry(unsigned long timeout) + { +- schedule_timeout_killable(timeout); ++ freezable_schedule_timeout_killable(timeout); + timeout <<= 1; + if (timeout > NFS4_LOCK_MAXTIMEOUT) + return NFS4_LOCK_MAXTIMEOUT; +--- a/fs/nfs/proc.c ++++ a/fs/nfs/proc.c +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include + #include "internal.h" + + #define NFSDBG_FACILITY NFSDBG_PROC +@@ -59,7 +60,7 @@ nfs_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) + res = rpc_call_sync(clnt, msg, flags); + if (res != -EKEYEXPIRED) + break; +- schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); ++ freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); + res = -ERESTARTSYS; + } while (!fatal_signal_pending(current)); + return res; +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -134,6 +134,29 @@ static inline void set_freezable_with_signal(void) + } + + /* ++ * These macros are intended to be used whenever you want allow a task that's ++ * sleeping in TASK_UNINTERRUPTIBLE or TASK_KILLABLE state to be frozen. Note ++ * that neither return any clear indication of whether a freeze event happened ++ * while in this function. ++ */ ++ ++/* Like schedule(), but should not block the freezer. */ ++#define freezable_schedule() \ ++({ \ ++ freezer_do_not_count(); \ ++ schedule(); \ ++ freezer_count(); \ ++}) ++ ++/* Like schedule_timeout_killable(), but should not block the freezer. */ ++#define freezable_schedule_timeout_killable(timeout) \ ++({ \ ++ freezer_do_not_count(); \ ++ schedule_timeout_killable(timeout); \ ++ freezer_count(); \ ++}) ++ ++/* + * Freezer-friendly wrappers around wait_event_interruptible(), + * wait_event_killable() and wait_event_interruptible_timeout(), originally + * defined in +@@ -192,6 +215,11 @@ static inline int freezer_should_skip(struct task_struct *p) { return 0; } + static inline void set_freezable(void) {} + static inline void set_freezable_with_signal(void) {} + ++#define freezable_schedule() schedule() ++ ++#define freezable_schedule_timeout_killable(timeout) \ ++ schedule_timeout_killable(timeout) ++ + #define wait_event_freezable(wq, condition) \ + wait_event_interruptible(wq, condition) + +--- a/net/sunrpc/sched.c ++++ a/net/sunrpc/sched.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #include + +@@ -231,7 +232,7 @@ static int rpc_wait_bit_killable(void *word) + { + if (fatal_signal_pending(current)) + return -ERESTARTSYS; +- schedule(); ++ freezable_schedule(); + return 0; + } + + include/linux/freezer.h | 21 ++++++++++++++++++--- + 1 files changed, 18 insertions(+), 3 deletions(-) +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -140,18 +140,33 @@ static inline void set_freezable_with_signal(void) + * while in this function. + */ + +-/* Like schedule(), but should not block the freezer. */ ++/* ++ * Like schedule(), but should not block the freezer. It may return immediately ++ * if it ends up racing with the freezer. Callers must be able to deal with ++ * spurious wakeups. ++ */ + #define freezable_schedule() \ + ({ \ + freezer_do_not_count(); \ +- schedule(); \ ++ if (!try_to_freeze()) \ ++ schedule(); \ + freezer_count(); \ + }) + +-/* Like schedule_timeout_killable(), but should not block the freezer. */ ++/* ++ * Like schedule_timeout_killable(), but should not block the freezer. It may ++ * end up returning immediately if it ends up racing with the freezer. Callers ++ * must be able to deal with the loose wakeup timing that can occur when the ++ * freezer races in. When that occurs, this function will return the timeout ++ * value instead of 0. ++ */ + #define freezable_schedule_timeout_killable(timeout) \ + ({ \ + freezer_do_not_count(); \ ++ if (try_to_freeze()) { \ ++ freezer_count(); \ ++ return timeout; \ ++ } \ + schedule_timeout_killable(timeout); \ + freezer_count(); \ + }) From 340d8afdfe52de284b75f83352d735db7edf8380 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 2 Dec 2011 15:57:37 -0500 Subject: [PATCH 252/397] Backport ALPS touchpad patches from input/next branch (rhbz #590880) --- alps.patch | 1990 +++++++++++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 7 + 2 files changed, 1997 insertions(+) create mode 100644 alps.patch diff --git a/alps.patch b/alps.patch new file mode 100644 index 000000000..e76dc5477 --- /dev/null +++ b/alps.patch @@ -0,0 +1,1990 @@ +From ed11aa781242216bc72f1cd7d757a4f40be10329 Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Mon, 7 Nov 2011 19:53:15 -0800 +Subject: [PATCH 1/7] Input: ALPS - move protocol information to Documentation + +In preparation for new protocol support, move the protocol +information currently documented in alps.c to +Documentation/input/alps.txt, where it can be expanded without +cluttering up the driver. + +Signed-off-by: Seth Forshee +Acked-by: Chase Douglas +Signed-off-by: Dmitry Torokhov +--- + Documentation/input/alps.txt | 75 ++++++++++++++++++++++++++++++++++++++++++ + drivers/input/mouse/alps.c | 37 +-------------------- + 2 files changed, 76 insertions(+), 36 deletions(-) + create mode 100644 Documentation/input/alps.txt + +diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt +new file mode 100644 +index 0000000..ab5478f +--- /dev/null ++++ b/Documentation/input/alps.txt +@@ -0,0 +1,75 @@ ++ALPS Touchpad Protocol ++---------------------- ++ ++Introduction ++------------ ++ ++Currently the ALPS touchpad driver supports two protocol versions in use by ++ALPS touchpads, the "old" and "new" protocol versions. Fundamentally these ++differ only in the format of their event packets (in reality many features may ++be found on new protocol devices that aren't found on the old protocol ++devices, but these are handled transparently as feature differences rather ++than protocol differences). ++ ++Detection ++--------- ++ ++All ALPS touchpads should respond to the "E6 report" command sequence: ++E8-E6-E6-E6-E9. An ALPS touchpad should respond with either 00-00-0A or ++00-00-64. ++ ++If the E6 report is successful, the touchpad model is identified using the "E7 ++report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is ++matched against known models in the alps_model_data_array. ++ ++Packet Format ++------------- ++ ++In the following tables, the following notation us used. ++ ++ CAPITALS = stick, miniscules = touchpad ++ ++?'s can have different meanings on different models, such as wheel rotation, ++extra buttons, stick buttons on a dualpoint, etc. ++ ++PS/2 packet format ++------------------ ++ ++ byte 0: 0 0 YSGN XSGN 1 M R L ++ byte 1: X7 X6 X5 X4 X3 X2 X1 X0 ++ byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 ++ ++Note that the device never signals overflow condition. ++ ++ALPS Absolute Mode - Old Format ++------------------------------- ++ ++ byte 0: 1 0 0 0 1 x9 x8 x7 ++ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 ++ byte 2: 0 ? ? l r ? fin ges ++ byte 3: 0 ? ? ? ? y9 y8 y7 ++ byte 4: 0 y6 y5 y4 y3 y2 y1 y0 ++ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 ++ ++ALPS Absolute Mode - New Format ++------------------------------- ++ ++ byte 0: 1 ? ? ? 1 ? ? ? ++ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 ++ byte 2: 0 x10 x9 x8 x7 ? fin ges ++ byte 3: 0 y9 y8 y7 1 M R L ++ byte 4: 0 y6 y5 y4 y3 y2 y1 y0 ++ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 ++ ++Dualpoint device -- interleaved packet format ++--------------------------------------------- ++ ++ byte 0: 1 1 0 0 1 1 1 1 ++ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 ++ byte 2: 0 x10 x9 x8 x7 0 fin ges ++ byte 3: 0 0 YSGN XSGN 1 1 1 1 ++ byte 4: X7 X6 X5 X4 X3 X2 X1 X0 ++ byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 ++ byte 6: 0 y9 y8 y7 1 m r l ++ byte 7: 0 y6 y5 y4 y3 y2 y1 y0 ++ byte 8: 0 z6 z5 z4 z3 z2 z1 z0 +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 99d5876..ad15e7c 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -74,42 +74,7 @@ static const struct alps_model_info alps_model_data[] = { + * isn't valid per PS/2 spec. + */ + +-/* +- * PS/2 packet format +- * +- * byte 0: 0 0 YSGN XSGN 1 M R L +- * byte 1: X7 X6 X5 X4 X3 X2 X1 X0 +- * byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 +- * +- * Note that the device never signals overflow condition. +- * +- * ALPS absolute Mode - new format +- * +- * byte 0: 1 ? ? ? 1 ? ? ? +- * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 +- * byte 2: 0 x10 x9 x8 x7 ? fin ges +- * byte 3: 0 y9 y8 y7 1 M R L +- * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 +- * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 +- * +- * Dualpoint device -- interleaved packet format +- * +- * byte 0: 1 1 0 0 1 1 1 1 +- * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 +- * byte 2: 0 x10 x9 x8 x7 0 fin ges +- * byte 3: 0 0 YSGN XSGN 1 1 1 1 +- * byte 4: X7 X6 X5 X4 X3 X2 X1 X0 +- * byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 +- * byte 6: 0 y9 y8 y7 1 m r l +- * byte 7: 0 y6 y5 y4 y3 y2 y1 y0 +- * byte 8: 0 z6 z5 z4 z3 z2 z1 z0 +- * +- * CAPITALS = stick, miniscules = touchpad +- * +- * ?'s can have different meanings on different models, +- * such as wheel rotation, extra buttons, stick buttons +- * on a dualpoint, etc. +- */ ++/* Packet formats are described in Documentation/input/alps.txt */ + + static bool alps_is_valid_first_byte(const struct alps_model_info *model, + unsigned char data) +-- +1.7.7.3 + + +From 27b8ed51ee660e9a59cf325d6339f38b216fbb31 Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Mon, 7 Nov 2011 19:53:24 -0800 +Subject: [PATCH 2/7] Input: ALPS - add protocol version field in + alps_model_info + +In preparation for adding support for more ALPS protocol versions, +add a field for the protocol version to the model info instead of +using a field in the flags. OLDPROTO and !OLDPROTO are now called +version 1 and version 2, repsectively. + +Signed-off-by: Seth Forshee +Acked-by: Chase Douglas +Signed-off-by: Dmitry Torokhov + +Conflicts: + + drivers/input/mouse/alps.c +--- + drivers/input/mouse/alps.c | 47 +++++++++++++++++++++---------------------- + drivers/input/mouse/alps.h | 4 +++ + 2 files changed, 27 insertions(+), 24 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index ad15e7c..572cb21 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -30,7 +30,6 @@ + #define dbg(format, arg...) do {} while (0) + #endif + +-#define ALPS_OLDPROTO 0x01 /* old style input */ + #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ + #define ALPS_PASS 0x04 /* device has a pass-through port */ + +@@ -42,30 +41,30 @@ + 6-byte ALPS packet */ + + static const struct alps_model_info alps_model_data[] = { +- { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ +- { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ +- { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, +- { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, +- { { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 }, /* HP ze1115 */ +- { { 0x63, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, +- { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, +- { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ +- { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ +- { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ +- { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, +- { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ +- { { 0x73, 0x00, 0x0a }, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ +- { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, +- { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ +- { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ +- { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, +- { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ ++ { { 0x32, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ ++ { { 0x33, 0x02, 0x0a }, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ ++ { { 0x53, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x53, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x60, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ ++ { { 0x63, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x63, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x63, 0x02, 0x28 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ ++ { { 0x63, 0x02, 0x3c }, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ ++ { { 0x63, 0x02, 0x50 }, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ ++ { { 0x63, 0x02, 0x64 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x63, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ ++ { { 0x73, 0x00, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ ++ { { 0x73, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x73, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ ++ { { 0x20, 0x02, 0x0e }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ ++ { { 0x22, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, ++ { { 0x22, 0x02, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ + /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ +- { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ++ { { 0x62, 0x02, 0x14 }, ALPS_PROTO_V2, 0xcf, 0xcf, + ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, +- { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ +- { { 0x52, 0x01, 0x14 }, 0xff, 0xff, +- ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ ++ { { 0x73, 0x02, 0x50 }, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ ++ { { 0x52, 0x01, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, ++ ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ + }; + + /* +@@ -119,7 +118,7 @@ static void alps_process_packet(struct psmouse *psmouse) + int x, y, z, ges, fin, left, right, middle; + int back = 0, forward = 0; + +- if (model->flags & ALPS_OLDPROTO) { ++ if (model->proto_version == ALPS_PROTO_V1) { + left = packet[2] & 0x10; + right = packet[2] & 0x08; + middle = 0; +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index 904ed8b..4ce9bba 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -12,8 +12,12 @@ + #ifndef _ALPS_H + #define _ALPS_H + ++#define ALPS_PROTO_V1 0 ++#define ALPS_PROTO_V2 1 ++ + struct alps_model_info { + unsigned char signature[3]; ++ unsigned char proto_version; + unsigned char byte0, mask0; + unsigned char flags; + }; +-- +1.7.7.3 + + +From dfab9d3e073f2a58e4ba3837a726e9a0e33ea5df Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Mon, 7 Nov 2011 19:53:30 -0800 +Subject: [PATCH 3/7] Input: ALPS - remove assumptions about packet size + +In preparation for version 4 protocol support, which has 8-byte +data packets, remove all hard-coded assumptions about packet size +and use psmouse->pktsize instead. + +Signed-off-by: Seth Forshee +Acked-by: Chase Douglas +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 10 +++++----- + 1 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 572cb21..f699698 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -315,7 +315,7 @@ static void alps_flush_packet(unsigned long data) + + serio_pause_rx(psmouse->ps2dev.serio); + +- if (psmouse->pktcnt == 6) { ++ if (psmouse->pktcnt == psmouse->pktsize) { + + /* + * We did not any more data in reasonable amount of time. +@@ -365,15 +365,15 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + return PSMOUSE_BAD_DATA; + } + +- /* Bytes 2 - 6 should have 0 in the highest bit */ +- if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && ++ /* Bytes 2 - pktsize should have 0 in the highest bit */ ++ if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && + (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { + dbg("refusing packet[%i] = %x\n", + psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]); + return PSMOUSE_BAD_DATA; + } + +- if (psmouse->pktcnt == 6) { ++ if (psmouse->pktcnt == psmouse->pktsize) { + alps_process_packet(psmouse); + return PSMOUSE_FULL_PACKET; + } +@@ -531,7 +531,7 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) + static int alps_poll(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; +- unsigned char buf[6]; ++ unsigned char buf[sizeof(psmouse->packet)]; + bool poll_failed; + + if (priv->i->flags & ALPS_PASS) +-- +1.7.7.3 + + +From 35f17ba201d7a8b8adc59811effafe62a331fd9e Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Mon, 7 Nov 2011 19:53:36 -0800 +Subject: [PATCH 4/7] Input: ALPS - add support for protocol versions 3 and 4 + +This patch adds support for two ALPS touchpad protocols not +supported currently by the driver, which I am arbitrarily naming +version 3 and version 4. Support is single-touch only at this time, +although both protocols are capable of limited multitouch support. + +Thanks to Andrew Skalski, who did the initial reverse-engineering +of the v3 protocol. + +Signed-off-by: Seth Forshee +Acked-by: Chase Douglas +Signed-off-by: Dmitry Torokhov + +Conflicts: + + drivers/input/mouse/alps.c +--- + drivers/input/mouse/alps.c | 790 +++++++++++++++++++++++++++++++++++++++-- + drivers/input/mouse/alps.h | 14 + + drivers/input/mouse/psmouse.h | 1 + + 3 files changed, 767 insertions(+), 38 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index f699698..b2bc8ca 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -30,6 +30,49 @@ + #define dbg(format, arg...) do {} while (0) + #endif + ++/* ++ * Definitions for ALPS version 3 and 4 command mode protocol ++ */ ++#define ALPS_CMD_NIBBLE_10 0x01f2 ++ ++static const struct alps_nibble_commands alps_v3_nibble_commands[] = { ++ { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ ++ { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ ++ { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ ++ { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ ++ { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ ++ { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ ++ { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ ++ { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ ++ { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ ++ { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ ++ { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ ++ { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ ++ { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ ++ { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ ++ { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ ++ { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ ++}; ++ ++static const struct alps_nibble_commands alps_v4_nibble_commands[] = { ++ { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */ ++ { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ ++ { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ ++ { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ ++ { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ ++ { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ ++ { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ ++ { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ ++ { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ ++ { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ ++ { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ ++ { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ ++ { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ ++ { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ ++ { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ ++ { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ ++}; ++ + #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ + #define ALPS_PASS 0x04 /* device has a pass-through port */ + +@@ -41,30 +84,33 @@ + 6-byte ALPS packet */ + + static const struct alps_model_info alps_model_data[] = { +- { { 0x32, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ +- { { 0x33, 0x02, 0x0a }, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ +- { { 0x53, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, +- { { 0x53, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, +- { { 0x60, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ +- { { 0x63, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, +- { { 0x63, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, +- { { 0x63, 0x02, 0x28 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ +- { { 0x63, 0x02, 0x3c }, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ +- { { 0x63, 0x02, 0x50 }, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ +- { { 0x63, 0x02, 0x64 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, +- { { 0x63, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ +- { { 0x73, 0x00, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ +- { { 0x73, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, +- { { 0x73, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ +- { { 0x20, 0x02, 0x0e }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ +- { { 0x22, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, +- { { 0x22, 0x02, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ ++ { { 0x32, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ ++ { { 0x33, 0x02, 0x0a }, 0x00, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ ++ { { 0x53, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x53, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x60, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ ++ { { 0x63, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x63, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x63, 0x02, 0x28 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ ++ { { 0x63, 0x02, 0x3c }, 0x00, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ ++ { { 0x63, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ ++ { { 0x63, 0x02, 0x64 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x63, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ ++ { { 0x73, 0x00, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ ++ { { 0x73, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x73, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ ++ { { 0x20, 0x02, 0x0e }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ ++ { { 0x22, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, ++ { { 0x22, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ + /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ +- { { 0x62, 0x02, 0x14 }, ALPS_PROTO_V2, 0xcf, 0xcf, ++ { { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, + ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, +- { { 0x73, 0x02, 0x50 }, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ +- { { 0x52, 0x01, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, +- ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ ++ { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ ++ { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ++ ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ ++ { { 0x73, 0x02, 0x64 }, 0x9b, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, ++ { { 0x73, 0x02, 0x64 }, 0x9d, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, ++ { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, + }; + + /* +@@ -108,7 +154,7 @@ static void alps_report_buttons(struct psmouse *psmouse, + input_sync(dev2); + } + +-static void alps_process_packet(struct psmouse *psmouse) ++static void alps_process_packet_v1_v2(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; + const struct alps_model_info *model = priv->i; +@@ -210,6 +256,224 @@ static void alps_process_packet(struct psmouse *psmouse) + input_sync(dev); + } + ++static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ unsigned char *packet = psmouse->packet; ++ struct input_dev *dev = priv->dev2; ++ int x, y, z, left, right, middle; ++ ++ /* Sanity check packet */ ++ if (!(packet[0] & 0x40)) { ++ psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n"); ++ return; ++ } ++ ++ /* ++ * There's a special packet that seems to indicate the end ++ * of a stream of trackstick data. Filter these out. ++ */ ++ if (packet[1] == 0x7f && packet[2] == 0x7f && packet[4] == 0x7f) ++ return; ++ ++ x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f)); ++ y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f)); ++ z = (packet[4] & 0x7c) >> 2; ++ ++ /* ++ * The x and y values tend to be quite large, and when used ++ * alone the trackstick is difficult to use. Scale them down ++ * to compensate. ++ */ ++ x /= 8; ++ y /= 8; ++ ++ input_report_rel(dev, REL_X, x); ++ input_report_rel(dev, REL_Y, -y); ++ ++ /* ++ * Most ALPS models report the trackstick buttons in the touchpad ++ * packets, but a few report them here. No reliable way has been ++ * found to differentiate between the models upfront, so we enable ++ * the quirk in response to seeing a button press in the trackstick ++ * packet. ++ */ ++ left = packet[3] & 0x01; ++ right = packet[3] & 0x02; ++ middle = packet[3] & 0x04; ++ ++ if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) && ++ (left || right || middle)) ++ priv->quirks |= ALPS_QUIRK_TRACKSTICK_BUTTONS; ++ ++ if (priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) { ++ input_report_key(dev, BTN_LEFT, left); ++ input_report_key(dev, BTN_RIGHT, right); ++ input_report_key(dev, BTN_MIDDLE, middle); ++ } ++ ++ input_sync(dev); ++ return; ++} ++ ++static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ unsigned char *packet = psmouse->packet; ++ struct input_dev *dev = psmouse->dev; ++ struct input_dev *dev2 = priv->dev2; ++ int x, y, z; ++ int left, right, middle; ++ ++ /* ++ * There's no single feature of touchpad position and bitmap ++ * packets that can be used to distinguish between them. We ++ * rely on the fact that a bitmap packet should always follow ++ * a position packet with bit 6 of packet[4] set. ++ */ ++ if (priv->multi_packet) { ++ priv->multi_packet = 0; ++ ++ /* ++ * Sometimes a position packet will indicate a multi-packet ++ * sequence, but then what follows is another position ++ * packet. Check for this, and when it happens process the ++ * position packet as usual. ++ */ ++ if (packet[0] & 0x40) { ++ /* ++ * Bitmap packets are not yet supported, so for now ++ * just ignore them. ++ */ ++ return; ++ } ++ } ++ ++ if (!priv->multi_packet && (packet[4] & 0x40)) ++ priv->multi_packet = 1; ++ else ++ priv->multi_packet = 0; ++ ++ left = packet[3] & 0x01; ++ right = packet[3] & 0x02; ++ middle = packet[3] & 0x04; ++ ++ x = ((packet[1] & 0x7f) << 4) | ((packet[4] & 0x30) >> 2) | ++ ((packet[0] & 0x30) >> 4); ++ y = ((packet[2] & 0x7f) << 4) | (packet[4] & 0x0f); ++ z = packet[5] & 0x7f; ++ ++ /* ++ * Sometimes the hardware sends a single packet with z = 0 ++ * in the middle of a stream. Real releases generate packets ++ * with x, y, and z all zero, so these seem to be flukes. ++ * Ignore them. ++ */ ++ if (x && y && !z) ++ return; ++ ++ if (z >= 64) ++ input_report_key(dev, BTN_TOUCH, 1); ++ else ++ input_report_key(dev, BTN_TOUCH, 0); ++ ++ if (z > 0) { ++ input_report_abs(dev, ABS_X, x); ++ input_report_abs(dev, ABS_Y, y); ++ } ++ input_report_abs(dev, ABS_PRESSURE, z); ++ ++ input_report_key(dev, BTN_TOOL_FINGER, z > 0); ++ input_report_key(dev, BTN_LEFT, left); ++ input_report_key(dev, BTN_RIGHT, right); ++ input_report_key(dev, BTN_MIDDLE, middle); ++ ++ input_sync(dev); ++ ++ if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { ++ left = packet[3] & 0x10; ++ right = packet[3] & 0x20; ++ middle = packet[3] & 0x40; ++ ++ input_report_key(dev2, BTN_LEFT, left); ++ input_report_key(dev2, BTN_RIGHT, right); ++ input_report_key(dev2, BTN_MIDDLE, middle); ++ input_sync(dev2); ++ } ++} ++ ++static void alps_process_packet_v3(struct psmouse *psmouse) ++{ ++ unsigned char *packet = psmouse->packet; ++ ++ /* ++ * v3 protocol packets come in three types, two representing ++ * touchpad data and one representing trackstick data. ++ * Trackstick packets seem to be distinguished by always ++ * having 0x3f in the last byte. This value has never been ++ * observed in the last byte of either of the other types ++ * of packets. ++ */ ++ if (packet[5] == 0x3f) { ++ alps_process_trackstick_packet_v3(psmouse); ++ return; ++ } ++ ++ alps_process_touchpad_packet_v3(psmouse); ++} ++ ++static void alps_process_packet_v4(struct psmouse *psmouse) ++{ ++ unsigned char *packet = psmouse->packet; ++ struct input_dev *dev = psmouse->dev; ++ int x, y, z; ++ int left, right; ++ ++ left = packet[4] & 0x01; ++ right = packet[4] & 0x02; ++ ++ x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) | ++ ((packet[0] & 0x30) >> 4); ++ y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f); ++ z = packet[5] & 0x7f; ++ ++ if (z >= 64) ++ input_report_key(dev, BTN_TOUCH, 1); ++ else ++ input_report_key(dev, BTN_TOUCH, 0); ++ ++ if (z > 0) { ++ input_report_abs(dev, ABS_X, x); ++ input_report_abs(dev, ABS_Y, y); ++ } ++ input_report_abs(dev, ABS_PRESSURE, z); ++ ++ input_report_key(dev, BTN_TOOL_FINGER, z > 0); ++ input_report_key(dev, BTN_LEFT, left); ++ input_report_key(dev, BTN_RIGHT, right); ++ ++ input_sync(dev); ++} ++ ++static void alps_process_packet(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ const struct alps_model_info *model = priv->i; ++ ++ switch (model->proto_version) { ++ case ALPS_PROTO_V1: ++ case ALPS_PROTO_V2: ++ alps_process_packet_v1_v2(psmouse); ++ break; ++ case ALPS_PROTO_V3: ++ alps_process_packet_v3(psmouse); ++ break; ++ case ALPS_PROTO_V4: ++ alps_process_packet_v4(psmouse); ++ break; ++ } ++} ++ + static void alps_report_bare_ps2_packet(struct psmouse *psmouse, + unsigned char packet[], + bool report_buttons) +@@ -381,11 +645,127 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + return PSMOUSE_GOOD_DATA; + } + ++static int alps_command_mode_send_nibble(struct psmouse *psmouse, int nibble) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ struct alps_data *priv = psmouse->private; ++ int command; ++ unsigned char *param; ++ unsigned char dummy[4]; ++ ++ BUG_ON(nibble > 0xf); ++ ++ command = priv->nibble_commands[nibble].command; ++ param = (command & 0x0f00) ? ++ dummy : (unsigned char *)&priv->nibble_commands[nibble].data; ++ ++ if (ps2_command(ps2dev, param, command)) ++ return -1; ++ ++ return 0; ++} ++ ++static int alps_command_mode_set_addr(struct psmouse *psmouse, int addr) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ struct alps_data *priv = psmouse->private; ++ int i, nibble; ++ ++ if (ps2_command(ps2dev, NULL, priv->addr_command)) ++ return -1; ++ ++ for (i = 12; i >= 0; i -= 4) { ++ nibble = (addr >> i) & 0xf; ++ if (alps_command_mode_send_nibble(psmouse, nibble)) ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int __alps_command_mode_read_reg(struct psmouse *psmouse, int addr) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ unsigned char param[4]; ++ ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) ++ return -1; ++ ++ /* ++ * The address being read is returned in the first two bytes ++ * of the result. Check that this address matches the expected ++ * address. ++ */ ++ if (addr != ((param[0] << 8) | param[1])) ++ return -1; ++ ++ return param[2]; ++} ++ ++static int alps_command_mode_read_reg(struct psmouse *psmouse, int addr) ++{ ++ if (alps_command_mode_set_addr(psmouse, addr)) ++ return -1; ++ return __alps_command_mode_read_reg(psmouse, addr); ++} ++ ++static int __alps_command_mode_write_reg(struct psmouse *psmouse, u8 value) ++{ ++ if (alps_command_mode_send_nibble(psmouse, (value >> 4) & 0xf)) ++ return -1; ++ if (alps_command_mode_send_nibble(psmouse, value & 0xf)) ++ return -1; ++ return 0; ++} ++ ++static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr, ++ u8 value) ++{ ++ if (alps_command_mode_set_addr(psmouse, addr)) ++ return -1; ++ return __alps_command_mode_write_reg(psmouse, value); ++} ++ ++static int alps_enter_command_mode(struct psmouse *psmouse, ++ unsigned char *resp) ++{ ++ unsigned char param[4]; ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ ++ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || ++ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { ++ psmouse_err(psmouse, "failed to enter command mode\n"); ++ return -1; ++ } ++ ++ if (param[0] != 0x88 && param[1] != 0x07) { ++ psmouse_dbg(psmouse, ++ "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", ++ param[0], param[1], param[2]); ++ return -1; ++ } ++ ++ if (resp) ++ *resp = param[2]; ++ return 0; ++} ++ ++static inline int alps_exit_command_mode(struct psmouse *psmouse) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) ++ return -1; ++ return 0; ++} ++ + static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) + { + struct ps2dev *ps2dev = &psmouse->ps2dev; + static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; + unsigned char param[4]; ++ const struct alps_model_info *model = NULL; + int i; + + /* +@@ -431,12 +811,41 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int + *version = (param[0] << 8) | (param[1] << 4) | i; + } + +- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) ++ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { + if (!memcmp(param, alps_model_data[i].signature, +- sizeof(alps_model_data[i].signature))) +- return alps_model_data + i; ++ sizeof(alps_model_data[i].signature))) { ++ model = alps_model_data + i; ++ break; ++ } ++ } + +- return NULL; ++ if (model && model->proto_version > ALPS_PROTO_V2) { ++ /* ++ * Need to check command mode response to identify ++ * model ++ */ ++ model = NULL; ++ if (alps_enter_command_mode(psmouse, param)) { ++ psmouse_warn(psmouse, ++ "touchpad failed to enter command mode\n"); ++ } else { ++ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { ++ if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && ++ alps_model_data[i].command_mode_resp == param[0]) { ++ model = alps_model_data + i; ++ break; ++ } ++ } ++ alps_exit_command_mode(psmouse); ++ ++ if (!model) ++ psmouse_dbg(psmouse, ++ "Unknown command mode response %2.2x\n", ++ param[0]); ++ } ++ } ++ ++ return model; + } + + /* +@@ -444,7 +853,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int + * subsequent commands. It looks like glidepad is behind stickpointer, + * I'd thought it would be other way around... + */ +-static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) ++static int alps_passthrough_mode_v2(struct psmouse *psmouse, bool enable) + { + struct ps2dev *ps2dev = &psmouse->ps2dev; + int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; +@@ -461,7 +870,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) + return 0; + } + +-static int alps_absolute_mode(struct psmouse *psmouse) ++static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) + { + struct ps2dev *ps2dev = &psmouse->ps2dev; + +@@ -535,13 +944,13 @@ static int alps_poll(struct psmouse *psmouse) + bool poll_failed; + + if (priv->i->flags & ALPS_PASS) +- alps_passthrough_mode(psmouse, true); ++ alps_passthrough_mode_v2(psmouse, true); + + poll_failed = ps2_command(&psmouse->ps2dev, buf, + PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; + + if (priv->i->flags & ALPS_PASS) +- alps_passthrough_mode(psmouse, false); ++ alps_passthrough_mode_v2(psmouse, false); + + if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) + return -1; +@@ -558,13 +967,13 @@ static int alps_poll(struct psmouse *psmouse) + return 0; + } + +-static int alps_hw_init(struct psmouse *psmouse) ++static int alps_hw_init_v1_v2(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; + const struct alps_model_info *model = priv->i; + + if ((model->flags & ALPS_PASS) && +- alps_passthrough_mode(psmouse, true)) { ++ alps_passthrough_mode_v2(psmouse, true)) { + return -1; + } + +@@ -573,13 +982,13 @@ static int alps_hw_init(struct psmouse *psmouse) + return -1; + } + +- if (alps_absolute_mode(psmouse)) { ++ if (alps_absolute_mode_v1_v2(psmouse)) { + printk(KERN_ERR "alps.c: Failed to enable absolute mode\n"); + return -1; + } + + if ((model->flags & ALPS_PASS) && +- alps_passthrough_mode(psmouse, false)) { ++ alps_passthrough_mode_v2(psmouse, false)) { + return -1; + } + +@@ -592,6 +1001,297 @@ static int alps_hw_init(struct psmouse *psmouse) + return 0; + } + ++/* ++ * Enable or disable passthrough mode to the trackstick. Must be in ++ * command mode when calling this function. ++ */ ++static int alps_passthrough_mode_v3(struct psmouse *psmouse, bool enable) ++{ ++ int reg_val; ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0008); ++ if (reg_val == -1) ++ return -1; ++ ++ if (enable) ++ reg_val |= 0x01; ++ else ++ reg_val &= ~0x01; ++ ++ if (__alps_command_mode_write_reg(psmouse, reg_val)) ++ return -1; ++ ++ return 0; ++} ++ ++/* Must be in command mode when calling this function */ ++static int alps_absolute_mode_v3(struct psmouse *psmouse) ++{ ++ int reg_val; ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0004); ++ if (reg_val == -1) ++ return -1; ++ ++ reg_val |= 0x06; ++ if (__alps_command_mode_write_reg(psmouse, reg_val)) ++ return -1; ++ ++ return 0; ++} ++ ++static int alps_hw_init_v3(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ int reg_val; ++ unsigned char param[4]; ++ ++ priv->nibble_commands = alps_v3_nibble_commands; ++ priv->addr_command = PSMOUSE_CMD_RESET_WRAP; ++ ++ if (alps_enter_command_mode(psmouse, NULL)) ++ goto error; ++ ++ /* Check for trackstick */ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0008); ++ if (reg_val == -1) ++ goto error; ++ if (reg_val & 0x80) { ++ if (alps_passthrough_mode_v3(psmouse, true)) ++ goto error; ++ if (alps_exit_command_mode(psmouse)) ++ goto error; ++ ++ /* ++ * E7 report for the trackstick ++ * ++ * There have been reports of failures to seem to trace back ++ * to the above trackstick check failing. When these occur ++ * this E7 report fails, so when that happens we continue ++ * with the assumption that there isn't a trackstick after ++ * all. ++ */ ++ param[0] = 0x64; ++ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || ++ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { ++ psmouse_warn(psmouse, "trackstick E7 report failed\n"); ++ } else { ++ psmouse_dbg(psmouse, ++ "trackstick E7 report: %2.2x %2.2x %2.2x\n", ++ param[0], param[1], param[2]); ++ ++ /* ++ * Not sure what this does, but it is absolutely ++ * essential. Without it, the touchpad does not ++ * work at all and the trackstick just emits normal ++ * PS/2 packets. ++ */ ++ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ++ alps_command_mode_send_nibble(psmouse, 0x9) || ++ alps_command_mode_send_nibble(psmouse, 0x4)) { ++ psmouse_err(psmouse, ++ "Error sending magic E6 sequence\n"); ++ goto error_passthrough; ++ } ++ } ++ ++ if (alps_enter_command_mode(psmouse, NULL)) ++ goto error_passthrough; ++ if (alps_passthrough_mode_v3(psmouse, false)) ++ goto error; ++ } ++ ++ if (alps_absolute_mode_v3(psmouse)) { ++ psmouse_err(psmouse, "Failed to enter absolute mode\n"); ++ goto error; ++ } ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0006); ++ if (reg_val == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) ++ goto error; ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0007); ++ if (reg_val == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) ++ goto error; ++ ++ if (alps_command_mode_read_reg(psmouse, 0x0144) == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, 0x04)) ++ goto error; ++ ++ if (alps_command_mode_read_reg(psmouse, 0x0159) == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_read_reg(psmouse, 0x0163) == -1) ++ goto error; ++ if (alps_command_mode_write_reg(psmouse, 0x0163, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_read_reg(psmouse, 0x0162) == -1) ++ goto error; ++ if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04)) ++ goto error; ++ ++ /* ++ * This ensures the trackstick packets are in the format ++ * supported by this driver. If bit 1 isn't set the packet ++ * format is different. ++ */ ++ if (alps_command_mode_write_reg(psmouse, 0x0008, 0x82)) ++ goto error; ++ ++ alps_exit_command_mode(psmouse); ++ ++ /* Set rate and enable data reporting */ ++ param[0] = 0x64; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { ++ psmouse_err(psmouse, "Failed to enable data reporting\n"); ++ return -1; ++ } ++ ++ return 0; ++ ++error_passthrough: ++ /* Something failed while in passthrough mode, so try to get out */ ++ if (!alps_enter_command_mode(psmouse, NULL)) ++ alps_passthrough_mode_v3(psmouse, false); ++error: ++ /* ++ * Leaving the touchpad in command mode will essentially render ++ * it unusable until the machine reboots, so exit it here just ++ * to be safe ++ */ ++ alps_exit_command_mode(psmouse); ++ return -1; ++} ++ ++/* Must be in command mode when calling this function */ ++static int alps_absolute_mode_v4(struct psmouse *psmouse) ++{ ++ int reg_val; ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0004); ++ if (reg_val == -1) ++ return -1; ++ ++ reg_val |= 0x02; ++ if (__alps_command_mode_write_reg(psmouse, reg_val)) ++ return -1; ++ ++ return 0; ++} ++ ++static int alps_hw_init_v4(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ unsigned char param[4]; ++ ++ priv->nibble_commands = alps_v4_nibble_commands; ++ priv->addr_command = PSMOUSE_CMD_DISABLE; ++ ++ if (alps_enter_command_mode(psmouse, NULL)) ++ goto error; ++ ++ if (alps_absolute_mode_v4(psmouse)) { ++ psmouse_err(psmouse, "Failed to enter absolute mode\n"); ++ goto error; ++ } ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0007, 0x8c)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0149, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0160, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x017f, 0x15)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0151, 0x01)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0168, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x014a, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0161, 0x03)) ++ goto error; ++ ++ alps_exit_command_mode(psmouse); ++ ++ /* ++ * This sequence changes the output from a 9-byte to an ++ * 8-byte format. All the same data seems to be present, ++ * just in a more compact format. ++ */ ++ param[0] = 0xc8; ++ param[1] = 0x64; ++ param[2] = 0x50; ++ if (ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, ¶m[2], PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, param, PSMOUSE_CMD_GETID)) ++ return -1; ++ ++ /* Set rate and enable data reporting */ ++ param[0] = 0x64; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { ++ psmouse_err(psmouse, "Failed to enable data reporting\n"); ++ return -1; ++ } ++ ++ return 0; ++ ++error: ++ /* ++ * Leaving the touchpad in command mode will essentially render ++ * it unusable until the machine reboots, so exit it here just ++ * to be safe ++ */ ++ alps_exit_command_mode(psmouse); ++ return -1; ++} ++ ++static int alps_hw_init(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ const struct alps_model_info *model = priv->i; ++ int ret = -1; ++ ++ switch (model->proto_version) { ++ case ALPS_PROTO_V1: ++ case ALPS_PROTO_V2: ++ ret = alps_hw_init_v1_v2(psmouse); ++ break; ++ case ALPS_PROTO_V3: ++ ret = alps_hw_init_v3(psmouse); ++ break; ++ case ALPS_PROTO_V4: ++ ret = alps_hw_init_v4(psmouse); ++ break; ++ } ++ ++ return ret; ++} ++ + static int alps_reconnect(struct psmouse *psmouse) + { + const struct alps_model_info *model; +@@ -632,6 +1332,8 @@ int alps_init(struct psmouse *psmouse) + + psmouse->private = priv; + ++ psmouse_reset(psmouse); ++ + model = alps_get_model(psmouse, &version); + if (!model) + goto init_fail; +@@ -659,8 +1361,20 @@ int alps_init(struct psmouse *psmouse) + BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); + + dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); +- input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); +- input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); ++ ++ switch (model->proto_version) { ++ case ALPS_PROTO_V1: ++ case ALPS_PROTO_V2: ++ input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); ++ input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); ++ break; ++ case ALPS_PROTO_V3: ++ case ALPS_PROTO_V4: ++ input_set_abs_params(dev1, ABS_X, 0, 2000, 0, 0); ++ input_set_abs_params(dev1, ABS_Y, 0, 1400, 0, 0); ++ break; ++ } ++ + input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); + + if (model->flags & ALPS_WHEEL) { +@@ -703,7 +1417,7 @@ int alps_init(struct psmouse *psmouse) + psmouse->poll = alps_poll; + psmouse->disconnect = alps_disconnect; + psmouse->reconnect = alps_reconnect; +- psmouse->pktsize = 6; ++ psmouse->pktsize = model->proto_version == ALPS_PROTO_V4 ? 8 : 6; + + /* We are having trouble resyncing ALPS touchpads so disable it for now */ + psmouse->resync_time = 0; +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index 4ce9bba..62db7f4 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -14,22 +14,36 @@ + + #define ALPS_PROTO_V1 0 + #define ALPS_PROTO_V2 1 ++#define ALPS_PROTO_V3 2 ++#define ALPS_PROTO_V4 3 + + struct alps_model_info { + unsigned char signature[3]; ++ unsigned char command_mode_resp; /* v3/v4 only */ + unsigned char proto_version; + unsigned char byte0, mask0; + unsigned char flags; + }; + ++struct alps_nibble_commands { ++ int command; ++ unsigned char data; ++}; ++ + struct alps_data { + struct input_dev *dev2; /* Relative device */ + char phys[32]; /* Phys */ + const struct alps_model_info *i;/* Info */ ++ const struct alps_nibble_commands *nibble_commands; ++ int addr_command; /* Command to set register address */ + int prev_fin; /* Finger bit from previous packet */ ++ int multi_packet; /* Multi-packet data in progress */ ++ u8 quirks; + struct timer_list timer; + }; + ++#define ALPS_QUIRK_TRACKSTICK_BUTTONS 1 /* trakcstick buttons in trackstick packet */ ++ + #ifdef CONFIG_MOUSE_PS2_ALPS + int alps_detect(struct psmouse *psmouse, bool set_properties); + int alps_init(struct psmouse *psmouse); +diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h +index 593e910..c2b5aa6 100644 +--- a/drivers/input/mouse/psmouse.h ++++ b/drivers/input/mouse/psmouse.h +@@ -8,6 +8,7 @@ + #define PSMOUSE_CMD_SETSTREAM 0x00ea + #define PSMOUSE_CMD_SETPOLL 0x00f0 + #define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */ ++#define PSMOUSE_CMD_RESET_WRAP 0x00ec + #define PSMOUSE_CMD_GETID 0x02f2 + #define PSMOUSE_CMD_SETRATE 0x10f3 + #define PSMOUSE_CMD_ENABLE 0x00f4 +-- +1.7.7.3 + + +From 8a2d5b12d0a47daf178a842ca009eaf344033cf8 Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Mon, 7 Nov 2011 19:54:13 -0800 +Subject: [PATCH 5/7] Input: ALPS - add semi-MT support for v3 protocol + +Signed-off-by: Seth Forshee +Acked-by: Chase Douglas +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 233 ++++++++++++++++++++++++++++++++++++++++---- + drivers/input/mouse/alps.h | 1 + + 2 files changed, 215 insertions(+), 19 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index b2bc8ca..15383e1 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -17,6 +17,7 @@ + + #include + #include ++#include + #include + #include + +@@ -33,6 +34,12 @@ + /* + * Definitions for ALPS version 3 and 4 command mode protocol + */ ++#define ALPS_V3_X_MAX 2000 ++#define ALPS_V3_Y_MAX 1400 ++ ++#define ALPS_BITMAP_X_BITS 15 ++#define ALPS_BITMAP_Y_BITS 11 ++ + #define ALPS_CMD_NIBBLE_10 0x01f2 + + static const struct alps_nibble_commands alps_v3_nibble_commands[] = { +@@ -256,6 +263,137 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) + input_sync(dev); + } + ++/* ++ * Process bitmap data from v3 and v4 protocols. Returns the number of ++ * fingers detected. A return value of 0 means at least one of the ++ * bitmaps was empty. ++ * ++ * The bitmaps don't have enough data to track fingers, so this function ++ * only generates points representing a bounding box of all contacts. ++ * These points are returned in x1, y1, x2, and y2 when the return value ++ * is greater than 0. ++ */ ++static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, ++ int *x1, int *y1, int *x2, int *y2) ++{ ++ struct alps_bitmap_point { ++ int start_bit; ++ int num_bits; ++ }; ++ ++ int fingers_x = 0, fingers_y = 0, fingers; ++ int i, bit, prev_bit; ++ struct alps_bitmap_point x_low = {0,}, x_high = {0,}; ++ struct alps_bitmap_point y_low = {0,}, y_high = {0,}; ++ struct alps_bitmap_point *point; ++ ++ if (!x_map || !y_map) ++ return 0; ++ ++ *x1 = *y1 = *x2 = *y2 = 0; ++ ++ prev_bit = 0; ++ point = &x_low; ++ for (i = 0; x_map != 0; i++, x_map >>= 1) { ++ bit = x_map & 1; ++ if (bit) { ++ if (!prev_bit) { ++ point->start_bit = i; ++ fingers_x++; ++ } ++ point->num_bits++; ++ } else { ++ if (prev_bit) ++ point = &x_high; ++ else ++ point->num_bits = 0; ++ } ++ prev_bit = bit; ++ } ++ ++ /* ++ * y bitmap is reversed for what we need (lower positions are in ++ * higher bits), so we process from the top end. ++ */ ++ y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - ALPS_BITMAP_Y_BITS); ++ prev_bit = 0; ++ point = &y_low; ++ for (i = 0; y_map != 0; i++, y_map <<= 1) { ++ bit = y_map & (1 << (sizeof(y_map) * BITS_PER_BYTE - 1)); ++ if (bit) { ++ if (!prev_bit) { ++ point->start_bit = i; ++ fingers_y++; ++ } ++ point->num_bits++; ++ } else { ++ if (prev_bit) ++ point = &y_high; ++ else ++ point->num_bits = 0; ++ } ++ prev_bit = bit; ++ } ++ ++ /* ++ * Fingers can overlap, so we use the maximum count of fingers ++ * on either axis as the finger count. ++ */ ++ fingers = max(fingers_x, fingers_y); ++ ++ /* ++ * If total fingers is > 1 but either axis reports only a single ++ * contact, we have overlapping or adjacent fingers. For the ++ * purposes of creating a bounding box, divide the single contact ++ * (roughly) equally between the two points. ++ */ ++ if (fingers > 1) { ++ if (fingers_x == 1) { ++ i = x_low.num_bits / 2; ++ x_low.num_bits = x_low.num_bits - i; ++ x_high.start_bit = x_low.start_bit + i; ++ x_high.num_bits = max(i, 1); ++ } else if (fingers_y == 1) { ++ i = y_low.num_bits / 2; ++ y_low.num_bits = y_low.num_bits - i; ++ y_high.start_bit = y_low.start_bit + i; ++ y_high.num_bits = max(i, 1); ++ } ++ } ++ ++ *x1 = (ALPS_V3_X_MAX * (2 * x_low.start_bit + x_low.num_bits - 1)) / ++ (2 * (ALPS_BITMAP_X_BITS - 1)); ++ *y1 = (ALPS_V3_Y_MAX * (2 * y_low.start_bit + y_low.num_bits - 1)) / ++ (2 * (ALPS_BITMAP_Y_BITS - 1)); ++ ++ if (fingers > 1) { ++ *x2 = (ALPS_V3_X_MAX * (2 * x_high.start_bit + x_high.num_bits - 1)) / ++ (2 * (ALPS_BITMAP_X_BITS - 1)); ++ *y2 = (ALPS_V3_Y_MAX * (2 * y_high.start_bit + y_high.num_bits - 1)) / ++ (2 * (ALPS_BITMAP_Y_BITS - 1)); ++ } ++ ++ return fingers; ++} ++ ++static void alps_set_slot(struct input_dev *dev, int slot, bool active, ++ int x, int y) ++{ ++ input_mt_slot(dev, slot); ++ input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); ++ if (active) { ++ input_report_abs(dev, ABS_MT_POSITION_X, x); ++ input_report_abs(dev, ABS_MT_POSITION_Y, y); ++ } ++} ++ ++static void alps_report_semi_mt_data(struct input_dev *dev, int num_fingers, ++ int x1, int y1, int x2, int y2) ++{ ++ alps_set_slot(dev, 0, num_fingers != 0, x1, y1); ++ alps_set_slot(dev, 1, num_fingers == 2, x2, y2); ++} ++ + static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; +@@ -324,16 +462,17 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + struct input_dev *dev2 = priv->dev2; + int x, y, z; + int left, right, middle; ++ int x1 = 0, y1 = 0, x2 = 0, y2 = 0; ++ int fingers = 0, bmap_fingers; ++ unsigned int x_bitmap, y_bitmap; + + /* +- * There's no single feature of touchpad position and bitmap +- * packets that can be used to distinguish between them. We +- * rely on the fact that a bitmap packet should always follow +- * a position packet with bit 6 of packet[4] set. ++ * There's no single feature of touchpad position and bitmap packets ++ * that can be used to distinguish between them. We rely on the fact ++ * that a bitmap packet should always follow a position packet with ++ * bit 6 of packet[4] set. + */ + if (priv->multi_packet) { +- priv->multi_packet = 0; +- + /* + * Sometimes a position packet will indicate a multi-packet + * sequence, but then what follows is another position +@@ -341,18 +480,49 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + * position packet as usual. + */ + if (packet[0] & 0x40) { ++ fingers = (packet[5] & 0x3) + 1; ++ x_bitmap = ((packet[4] & 0x7e) << 8) | ++ ((packet[1] & 0x7f) << 2) | ++ ((packet[0] & 0x30) >> 4); ++ y_bitmap = ((packet[3] & 0x70) << 4) | ++ ((packet[2] & 0x7f) << 1) | ++ (packet[4] & 0x01); ++ ++ bmap_fingers = alps_process_bitmap(x_bitmap, y_bitmap, ++ &x1, &y1, &x2, &y2); ++ + /* +- * Bitmap packets are not yet supported, so for now +- * just ignore them. ++ * We shouldn't report more than one finger if ++ * we don't have two coordinates. + */ +- return; ++ if (fingers > 1 && bmap_fingers < 2) ++ fingers = bmap_fingers; ++ ++ /* Now process position packet */ ++ packet = priv->multi_data; ++ } else { ++ priv->multi_packet = 0; + } + } + +- if (!priv->multi_packet && (packet[4] & 0x40)) ++ /* ++ * Bit 6 of byte 0 is not usually set in position packets. The only ++ * times it seems to be set is in situations where the data is ++ * suspect anyway, e.g. a palm resting flat on the touchpad. Given ++ * this combined with the fact that this bit is useful for filtering ++ * out misidentified bitmap packets, we reject anything with this ++ * bit set. ++ */ ++ if (packet[0] & 0x40) ++ return; ++ ++ if (!priv->multi_packet && (packet[4] & 0x40)) { + priv->multi_packet = 1; +- else +- priv->multi_packet = 0; ++ memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); ++ return; ++ } ++ ++ priv->multi_packet = 0; + + left = packet[3] & 0x01; + right = packet[3] & 0x02; +@@ -372,22 +542,38 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + if (x && y && !z) + return; + ++ /* ++ * If we don't have MT data or the bitmaps were empty, we have ++ * to rely on ST data. ++ */ ++ if (!fingers) { ++ x1 = x; ++ y1 = y; ++ fingers = z > 0 ? 1 : 0; ++ } ++ + if (z >= 64) + input_report_key(dev, BTN_TOUCH, 1); + else + input_report_key(dev, BTN_TOUCH, 0); + ++ alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); ++ ++ input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); ++ input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); ++ input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); ++ input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4); ++ ++ input_report_key(dev, BTN_LEFT, left); ++ input_report_key(dev, BTN_RIGHT, right); ++ input_report_key(dev, BTN_MIDDLE, middle); ++ + if (z > 0) { + input_report_abs(dev, ABS_X, x); + input_report_abs(dev, ABS_Y, y); + } + input_report_abs(dev, ABS_PRESSURE, z); + +- input_report_key(dev, BTN_TOOL_FINGER, z > 0); +- input_report_key(dev, BTN_LEFT, left); +- input_report_key(dev, BTN_RIGHT, right); +- input_report_key(dev, BTN_MIDDLE, middle); +- + input_sync(dev); + + if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { +@@ -1369,9 +1555,18 @@ int alps_init(struct psmouse *psmouse) + input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); + break; + case ALPS_PROTO_V3: ++ set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); ++ input_mt_init_slots(dev1, 2); ++ input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); ++ input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); ++ ++ set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); ++ set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); ++ set_bit(BTN_TOOL_QUADTAP, dev1->keybit); ++ /* fall through */ + case ALPS_PROTO_V4: +- input_set_abs_params(dev1, ABS_X, 0, 2000, 0, 0); +- input_set_abs_params(dev1, ABS_Y, 0, 1400, 0, 0); ++ input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); ++ input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); + break; + } + +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index 62db7f4..a00a4ab 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -38,6 +38,7 @@ struct alps_data { + int addr_command; /* Command to set register address */ + int prev_fin; /* Finger bit from previous packet */ + int multi_packet; /* Multi-packet data in progress */ ++ unsigned char multi_data[6]; /* Saved multi-packet data */ + u8 quirks; + struct timer_list timer; + }; +-- +1.7.7.3 + + +From 281688737cb83dd113cfab809b2c78841451ba32 Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Mon, 7 Nov 2011 19:54:35 -0800 +Subject: [PATCH 6/7] Input: ALPS - add documentation for protocol versions 3 + and 4 + +Also converts from using "old" and "new" to describe the already-known +protocols to using "version 1" and "version 2" to match the code. + +Signed-off-by: Seth Forshee +Acked-by: Chase Douglas +Signed-off-by: Dmitry Torokhov +--- + Documentation/input/alps.txt | 135 ++++++++++++++++++++++++++++++++++++++---- + 1 files changed, 124 insertions(+), 11 deletions(-) + +diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt +index ab5478f..f274c28 100644 +--- a/Documentation/input/alps.txt ++++ b/Documentation/input/alps.txt +@@ -4,12 +4,9 @@ ALPS Touchpad Protocol + Introduction + ------------ + +-Currently the ALPS touchpad driver supports two protocol versions in use by +-ALPS touchpads, the "old" and "new" protocol versions. Fundamentally these +-differ only in the format of their event packets (in reality many features may +-be found on new protocol devices that aren't found on the old protocol +-devices, but these are handled transparently as feature differences rather +-than protocol differences). ++Currently the ALPS touchpad driver supports four protocol versions in use by ++ALPS touchpads, called versions 1, 2, 3, and 4. Information about the various ++protocol versions is contained in the following sections. + + Detection + --------- +@@ -22,10 +19,37 @@ If the E6 report is successful, the touchpad model is identified using the "E7 + report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is + matched against known models in the alps_model_data_array. + ++With protocol versions 3 and 4, the E7 report model signature is always ++73-02-64. To differentiate between these versions, the response from the ++"Enter Command Mode" sequence must be inspected as described below. ++ ++Command Mode ++------------ ++ ++Protocol versions 3 and 4 have a command mode that is used to read and write ++one-byte device registers in a 16-bit address space. The command sequence ++EC-EC-EC-E9 places the device in command mode, and the device will respond ++with 88-07 followed by a third byte. This third byte can be used to determine ++whether the devices uses the version 3 or 4 protocol. ++ ++To exit command mode, PSMOUSE_CMD_SETSTREAM (EA) is sent to the touchpad. ++ ++While in command mode, register addresses can be set by first sending a ++specific command, either EC for v3 devices or F5 for v4 devices. Then the ++address is sent one nibble at a time, where each nibble is encoded as a ++command with optional data. This enoding differs slightly between the v3 and ++v4 protocols. ++ ++Once an address has been set, the addressed register can be read by sending ++PSMOUSE_CMD_GETINFO (E9). The first two bytes of the response contains the ++address of the register being read, and the third contains the value of the ++register. Registers are written by writing the value one nibble at a time ++using the same encoding used for addresses. ++ + Packet Format + ------------- + +-In the following tables, the following notation us used. ++In the following tables, the following notation is used. + + CAPITALS = stick, miniscules = touchpad + +@@ -41,8 +65,8 @@ PS/2 packet format + + Note that the device never signals overflow condition. + +-ALPS Absolute Mode - Old Format +-------------------------------- ++ALPS Absolute Mode - Protocol Verion 1 ++-------------------------------------- + + byte 0: 1 0 0 0 1 x9 x8 x7 + byte 1: 0 x6 x5 x4 x3 x2 x1 x0 +@@ -51,8 +75,8 @@ ALPS Absolute Mode - Old Format + byte 4: 0 y6 y5 y4 y3 y2 y1 y0 + byte 5: 0 z6 z5 z4 z3 z2 z1 z0 + +-ALPS Absolute Mode - New Format +-------------------------------- ++ALPS Absolute Mode - Protocol Version 2 ++--------------------------------------- + + byte 0: 1 ? ? ? 1 ? ? ? + byte 1: 0 x6 x5 x4 x3 x2 x1 x0 +@@ -73,3 +97,92 @@ Dualpoint device -- interleaved packet format + byte 6: 0 y9 y8 y7 1 m r l + byte 7: 0 y6 y5 y4 y3 y2 y1 y0 + byte 8: 0 z6 z5 z4 z3 z2 z1 z0 ++ ++ALPS Absolute Mode - Protocol Version 3 ++--------------------------------------- ++ ++ALPS protocol version 3 has three different packet formats. The first two are ++associated with touchpad events, and the third is associatd with trackstick ++events. ++ ++The first type is the touchpad position packet. ++ ++ byte 0: 1 ? x1 x0 1 1 1 1 ++ byte 1: 0 x10 x9 x8 x7 x6 x5 x4 ++ byte 2: 0 y10 y9 y8 y7 y6 y5 y4 ++ byte 3: 0 M R L 1 m r l ++ byte 4: 0 mt x3 x2 y3 y2 y1 y0 ++ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 ++ ++Note that for some devices the trackstick buttons are reported in this packet, ++and on others it is reported in the trackstick packets. ++ ++The second packet type contains bitmaps representing the x and y axes. In the ++bitmaps a given bit is set if there is a finger covering that position on the ++given axis. Thus the bitmap packet can be used for low-resolution multi-touch ++data, although finger tracking is not possible. This packet also encodes the ++number of contacts (f1 and f0 in the table below). ++ ++ byte 0: 1 1 x1 x0 1 1 1 1 ++ byte 1: 0 x8 x7 x6 x5 x4 x3 x2 ++ byte 2: 0 y7 y6 y5 y4 y3 y2 y1 ++ byte 3: 0 y10 y9 y8 1 1 1 1 ++ byte 4: 0 x14 x13 x12 x11 x10 x9 y0 ++ byte 5: 0 1 ? ? ? ? f1 f0 ++ ++This packet only appears after a position packet with the mt bit set, and ++ususally only appears when there are two or more contacts (although ++ocassionally it's seen with only a single contact). ++ ++The final v3 packet type is the trackstick packet. ++ ++ byte 0: 1 1 x7 y7 1 1 1 1 ++ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 ++ byte 2: 0 y6 y5 y4 y3 y2 y1 y0 ++ byte 3: 0 1 0 0 1 0 0 0 ++ byte 4: 0 z4 z3 z2 z1 z0 ? ? ++ byte 5: 0 0 1 1 1 1 1 1 ++ ++ALPS Absolute Mode - Protocol Version 4 ++--------------------------------------- ++ ++Protocol version 4 has an 8-byte packet format. ++ ++ byte 0: 1 ? x1 x0 1 1 1 1 ++ byte 1: 0 x10 x9 x8 x7 x6 x5 x4 ++ byte 2: 0 y10 y9 y8 y7 y6 y5 y4 ++ byte 3: 0 1 x3 x2 y3 y2 y1 y0 ++ byte 4: 0 ? ? ? 1 ? r l ++ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 ++ byte 6: bitmap data (described below) ++ byte 7: bitmap data (described below) ++ ++The last two bytes represent a partial bitmap packet, with 3 full packets ++required to construct a complete bitmap packet. Once assembled, the 6-byte ++bitmap packet has the following format: ++ ++ byte 0: 0 1 x7 x6 x5 x4 x3 x2 ++ byte 1: 0 x1 x0 y4 y3 y2 y1 y0 ++ byte 2: 0 0 ? x14 x13 x12 x11 x10 ++ byte 3: 0 x9 x8 y9 y8 y7 y6 y5 ++ byte 4: 0 0 0 0 0 0 0 0 ++ byte 5: 0 0 0 0 0 0 0 y10 ++ ++There are several things worth noting here. ++ ++ 1) In the bitmap data, bit 6 of byte 0 serves as a sync byte to ++ identify the first fragment of a bitmap packet. ++ ++ 2) The bitmaps represent the same data as in the v3 bitmap packets, although ++ the packet layout is different. ++ ++ 3) There doesn't seem to be a count of the contact points anywhere in the v4 ++ protocol packets. Deriving a count of contact points must be done by ++ analyzing the bitmaps. ++ ++ 4) There is a 3 to 1 ratio of position packets to bitmap packets. Therefore ++ MT position can only be updated for every third ST position update, and ++ the count of contact points can only be updated every third packet as ++ well. ++ ++So far no v4 devices with tracksticks have been encountered. +-- +1.7.7.3 + + +From 8114d422321fa6bb724a03faf25b101868d6e03d Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Mon, 12 Dec 2011 15:12:00 -0500 +Subject: [PATCH 7/7] Revert psmouse_* print format changes from the + backported patches. Sigh + +Signed-off-by: Josh Boyer +--- + drivers/input/mouse/alps.c | 29 ++++++++++++----------------- + 1 files changed, 12 insertions(+), 17 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 15383e1..4925a63 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -403,7 +403,7 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) + + /* Sanity check packet */ + if (!(packet[0] & 0x40)) { +- psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n"); ++ dbg("Bad trackstick packet, discarding\n"); + return; + } + +@@ -922,13 +922,12 @@ static int alps_enter_command_mode(struct psmouse *psmouse, + ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || + ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { +- psmouse_err(psmouse, "failed to enter command mode\n"); ++ printk(KERN_ERR "alps.c: failed to enter command mode\n"); + return -1; + } + + if (param[0] != 0x88 && param[1] != 0x07) { +- psmouse_dbg(psmouse, +- "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", ++ dbg("unknown response while entering command mode: %2.2x %2.2x %2.2x\n", + param[0], param[1], param[2]); + return -1; + } +@@ -1012,8 +1011,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int + */ + model = NULL; + if (alps_enter_command_mode(psmouse, param)) { +- psmouse_warn(psmouse, +- "touchpad failed to enter command mode\n"); ++ printk(KERN_WARNING "alps.c: touchpad failed to enter command mode\n"); + } else { + for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { + if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && +@@ -1025,8 +1023,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int + alps_exit_command_mode(psmouse); + + if (!model) +- psmouse_dbg(psmouse, +- "Unknown command mode response %2.2x\n", ++ dbg("Unknown command mode response %2.2x\n", + param[0]); + } + } +@@ -1263,10 +1260,9 @@ static int alps_hw_init_v3(struct psmouse *psmouse) + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || + ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { +- psmouse_warn(psmouse, "trackstick E7 report failed\n"); ++ printk(KERN_WARNING "alps.c: trackstick E7 report failed\n"); + } else { +- psmouse_dbg(psmouse, +- "trackstick E7 report: %2.2x %2.2x %2.2x\n", ++ dbg("trackstick E7 report: %2.2x %2.2x %2.2x\n", + param[0], param[1], param[2]); + + /* +@@ -1280,8 +1276,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || + alps_command_mode_send_nibble(psmouse, 0x9) || + alps_command_mode_send_nibble(psmouse, 0x4)) { +- psmouse_err(psmouse, +- "Error sending magic E6 sequence\n"); ++ printk(KERN_ERR "alps.c: Error sending magic E6 sequence\n"); + goto error_passthrough; + } + } +@@ -1293,7 +1288,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) + } + + if (alps_absolute_mode_v3(psmouse)) { +- psmouse_err(psmouse, "Failed to enter absolute mode\n"); ++ printk(KERN_ERR "alps.c: Failed to enter absolute mode\n"); + goto error; + } + +@@ -1343,7 +1338,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) + param[0] = 0x64; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { +- psmouse_err(psmouse, "Failed to enable data reporting\n"); ++ printk(KERN_ERR "alps.c: Failed to enable data reporting\n"); + return -1; + } + +@@ -1392,7 +1387,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse) + goto error; + + if (alps_absolute_mode_v4(psmouse)) { +- psmouse_err(psmouse, "Failed to enter absolute mode\n"); ++ printk(KERN_ERR "alps.c: Failed to enter absolute mode\n"); + goto error; + } + +@@ -1440,7 +1435,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse) + param[0] = 0x64; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { +- psmouse_err(psmouse, "Failed to enable data reporting\n"); ++ printk(KERN_ERR "alps.c: Failed to enable data reporting\n"); + return -1; + } + +-- +1.7.7.3 + diff --git a/kernel.spec b/kernel.spec index 675487dd7..4c3a327e6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -712,6 +712,9 @@ Patch21230: net-sky2-88e8059-fix-link-speed.patch #rhbz 717735 Patch21045: nfs-client-freezer.patch +#rhbz 590880 +Patch21046: alps.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1318,6 +1321,9 @@ ApplyPatch net-sky2-88e8059-fix-link-speed.patch #rhbz 717735 ApplyPatch nfs-client-freezer.patch +#rhbz 590880 +ApplyPatch alps.patch + # END OF PATCH APPLICATIONS %endif @@ -1967,6 +1973,7 @@ fi %changelog * Thu Dec 15 2011 Josh Boyer - Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735) +- Backport ALPS touchpad patches from input/next branch (rhbz #590880) * Thu Dec 15 2011 Dave Jones - 2.6.41.5-3 - Disable Intel IOMMU by default. From ddeb23923b8adf309a1f5f882e6225ce9064ba07 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 15 Dec 2011 10:21:49 -0500 Subject: [PATCH 253/397] Add patch to fix Intel wifi regression in 3.1.5 (rhbz 767173) --- ...-to-switch-to-HT40-if-not-associated.patch | 38 +++++++++++++++++++ kernel.spec | 11 +++++- 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch diff --git a/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch b/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch new file mode 100644 index 000000000..08c9e443b --- /dev/null +++ b/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch @@ -0,0 +1,38 @@ +My previous patch +34a5b4b6af104cf18eb50748509528b9bdbc4036 iwlwifi: do not re-configure +HT40 after associated + +Fix the case of HT40 after association on specified AP, but it break the +association for some APs and cause not able to establish connection. +We need to address HT40 before and after addociation. + +CC: stable@vger.kernel.org #3.0+ +Reported-by: Andrej Gelenberg +Signed-off-by: Wey-Yi Guy +Tested-by: Andrej Gelenberg +--- + drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +index a7a6def..5c7c17c 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +@@ -606,8 +606,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) + if (ctx->ht.enabled) { + /* if HT40 is used, it should not change + * after associated except channel switch */ +- if (iwl_is_associated_ctx(ctx) && +- !ctx->ht.is_40mhz) ++ if (!ctx->ht.is_40mhz || ++ !iwl_is_associated_ctx(ctx)) + iwlagn_config_ht40(conf, ctx); + } else + ctx->ht.is_40mhz = false; +-- +1.7.0.4 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index 4c3a327e6..605284452 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -715,6 +715,9 @@ Patch21045: nfs-client-freezer.patch #rhbz 590880 Patch21046: alps.patch +#rhbz 767173 +Patch21047: iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1324,6 +1327,9 @@ ApplyPatch nfs-client-freezer.patch #rhbz 590880 ApplyPatch alps.patch +#rhbz 767173 +ApplyPatch iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch + # END OF PATCH APPLICATIONS %endif @@ -1971,7 +1977,8 @@ fi # and build. %changelog -* Thu Dec 15 2011 Josh Boyer +* Thu Dec 15 2011 Josh Boyer - 2.6.41.5-4 +- Add patch to fix Intel wifi regression in 3.1.5 (rhbz 767173) - Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735) - Backport ALPS touchpad patches from input/next branch (rhbz #590880) From 01b44d5ba02ef3a5121176c96ff37456ccfae457 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Wed, 14 Dec 2011 20:46:36 -0600 Subject: [PATCH 254/397] omap config cleanups from dmarlin --- config-arm-omap-generic | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/config-arm-omap-generic b/config-arm-omap-generic index 657f548a2..6dc452357 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -182,10 +182,6 @@ CONFIG_PM_SLEEP_SMP=y # CONFIG_APM_EMULATION is not set CONFIG_ARCH_HAS_OPP=y CONFIG_PM_OPP=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPGRE_DEMUX is not set # CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set # CONFIG_ARPD is not set @@ -411,7 +407,6 @@ CONFIG_SERIAL_8250_DETECT_IRQ=y CONFIG_SERIAL_OMAP=y CONFIG_SERIAL_OMAP_CONSOLE=y # CONFIG_SERIAL_IFX6X60 is not set -# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM_TIMERIOMEM is not set # CONFIG_R3964 is not set @@ -447,7 +442,6 @@ CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y # CONFIG_DEBUG_GPIO is not set CONFIG_GPIO_SYSFS=y -# CONFIG_GPIO_GENERIC_PLATFORM is not set # # Memory mapped GPIO expanders: @@ -623,12 +617,6 @@ CONFIG_REGULATOR_TWL4030=y # CONFIG_REGULATOR_ISL6271A is not set # CONFIG_REGULATOR_AD5398 is not set # CONFIG_REGULATOR_TPS6524X is not set -CONFIG_MEDIA_SUPPORT=y -CONFIG_RC_CORE=y -CONFIG_LIRC=y -CONFIG_IR_RC5_SZ_DECODER=y -CONFIG_IR_LIRC_CODEC=y -# CONFIG_RC_LOOPBACK is not set CONFIG_VIDEOBUF_DMA_CONTIG=m CONFIG_V4L2_MEM2MEM_DEV=m # CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set @@ -805,25 +793,6 @@ CONFIG_SND_SOC_TLV320AIC3X=y CONFIG_SND_SOC_TWL4030=y CONFIG_SND_SOC_TWL6040=y # CONFIG_SOUND_PRIME is not set -CONFIG_HID=y -CONFIG_HID_3M_PCT=m -CONFIG_HID_A4TECH=m -# CONFIG_HID_ACRUX is not set -CONFIG_HID_APPLE=m -CONFIG_HID_BELKIN=m -CONFIG_HID_CHERRY=m -CONFIG_HID_CHICONY=m -CONFIG_HID_CYPRESS=m -CONFIG_HID_EZKEY=m -CONFIG_HID_KYE=m -CONFIG_HID_KENSINGTON=m -CONFIG_HID_LOGITECH=m -CONFIG_HID_MICROSOFT=m -CONFIG_HID_MOSART=m -CONFIG_HID_MONTEREY=m -CONFIG_HID_NTRIG=m -CONFIG_HID_QUANTA=m -CONFIG_HID_STANTUM=m # CONFIG_HID_TIVO_SLIDE is not set # CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set # CONFIG_USB_DEVICEFS is not set @@ -990,11 +959,6 @@ CONFIG_QUOTA_TREE=m CONFIG_QFMT_V1=m CONFIG_QFMT_V2=m CONFIG_AUTOFS4_FS=m -CONFIG_ISO9660_FS=m -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_DEBUG is not set # CONFIG_NTFS_RW is not set # CONFIG_JFFS2_SUMMARY is not set @@ -1062,7 +1026,6 @@ CONFIG_EARLY_PRINTK=y # CONFIG_DEBUG_ICEDCC is not set CONFIG_OC_ETM=y # CONFIG_KEYS_DEBUG_PROC_KEYS is not set -# CONFIG_SECURITY_NETWORK_XFRM is not set # CONFIG_IMA is not set CONFIG_CRYPTO_AEAD=m CONFIG_CRYPTO_RNG=m From 1462c71ad97a4af1a69d0f9edfcb94b7df0b2021 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Thu, 15 Dec 2011 12:00:04 -0600 Subject: [PATCH 255/397] add patch fro tegra systems so that usb-storage doesnt reset and rootfs fdoesnt drop out, this needs a better fix. --- arm-tegra-usb-no-reset.patch | 29 +++++++++++++++++++++++++++++ kernel.spec | 2 ++ 2 files changed, 31 insertions(+) create mode 100644 arm-tegra-usb-no-reset.patch diff --git a/arm-tegra-usb-no-reset.patch b/arm-tegra-usb-no-reset.patch new file mode 100644 index 000000000..2cb028eb8 --- /dev/null +++ b/arm-tegra-usb-no-reset.patch @@ -0,0 +1,29 @@ +From 6b0cbdfaf589e6f39ab7588ed1047d1a55224eb9 Mon Sep 17 00:00:00 2001 +From: Mike Rapoport +Date: Mon, 11 Apr 2011 10:33:20 +0300 +Subject: [PATCH] BUGFIX: don't allow disconnection of USB-SATA on TrimSlice + +--- + drivers/usb/core/hub.c | 7 +++++++ + 1 files changed, 7 insertions(+), 0 deletions(-) + +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 566c183..74b5165 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -3263,6 +3263,13 @@ static void hub_events(void) + (u16) hub->change_bits[0], + (u16) hub->event_bits[0]); + ++ /* Don't disconnect USB-SATA on TrimSlice */ ++ if (strcmp(dev_name(hdev->bus->controller), "tegra-ehci.0") == 0) { ++ if ((hdev->state == 7) && (hub->change_bits[0] == 0) && ++ (hub->event_bits[0] == 0x2)) ++ hub->event_bits[0] = 0; ++ } ++ + /* Lock the device, then check to see if we were + * disconnected while waiting for the lock to succeed. */ + usb_lock_device(hdev); +-- +1.7.6 diff --git a/kernel.spec b/kernel.spec index 605284452..fe4620e15 100644 --- a/kernel.spec +++ b/kernel.spec @@ -675,6 +675,7 @@ Patch20000: utrace.patch # Flattened devicetree support Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch +Patch21002: arm-tegra-usb-no-reset.patch #rhbz #735946 Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch @@ -1140,6 +1141,7 @@ ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R # ApplyPatch arm-omap-dt-compat.patch ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch +ApplyPatch arm-tegra-usb-no-reset.patch ApplyPatch taint-vbox.patch # From 5085a82dcab4931c915914ea47a0f637c81ac016 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Thu, 15 Dec 2011 12:03:07 -0600 Subject: [PATCH 256/397] build imx highbank and kirkwood kernel variants on arm add patch for tegra usb storage resets omap config cleanups from dmarlin --- kernel.spec | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel.spec b/kernel.spec index fe4620e15..f638722e1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1979,6 +1979,11 @@ fi # and build. %changelog +* Sun Dec 11 2011 Dennis Gilmore +- build imx highbank and kirkwood kernel variants on arm +- add patch for tegra usb storage resets +- omap config cleanups from dmarlin + * Thu Dec 15 2011 Josh Boyer - 2.6.41.5-4 - Add patch to fix Intel wifi regression in 3.1.5 (rhbz 767173) - Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735) From 2d997358bbcf556257064c4c00dc06bcf096997a Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Thu, 15 Dec 2011 12:09:54 -0600 Subject: [PATCH 257/397] build imx highbank and kirkwood kernel variants on arm add patch for tegra usb storage resets omap config cleanups from dmarlin --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index f638722e1..08a99a70c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1979,7 +1979,7 @@ fi # and build. %changelog -* Sun Dec 11 2011 Dennis Gilmore +* Thu Dec 15 2011 Dennis Gilmore - build imx highbank and kirkwood kernel variants on arm - add patch for tegra usb storage resets - omap config cleanups from dmarlin From e23ae9fdfc2753c9b7065e9d48e6584224b9e56a Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 19 Dec 2011 19:02:41 -0500 Subject: [PATCH 258/397] x86, dumpstack: Fix code bytes breakage due to missing KERN_CONT --- kernel.spec | 8 ++++ x86-code-dump-fix-truncation.patch | 73 ++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 x86-code-dump-fix-truncation.patch diff --git a/kernel.spec b/kernel.spec index 08a99a70c..22eaf3e6d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -686,6 +686,8 @@ Patch21022: mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch Patch21030: be2net-non-member-vlan-pkts-not-received-in-promisco.patch Patch21031: benet-remove-bogus-unlikely-on-vlan-check.patch +Patch21040: x86-code-dump-fix-truncation.patch + Patch21070: oom-fix-integer-overflow-of-points.patch #rhbz 728607 @@ -1297,6 +1299,9 @@ ApplyPatch mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch ApplyPatch be2net-non-member-vlan-pkts-not-received-in-promisco.patch ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch +#rhbz 736815 +ApplyPatch x86-code-dump-fix-truncation.patch + #rhbz 750402 ApplyPatch oom-fix-integer-overflow-of-points.patch @@ -1979,6 +1984,9 @@ fi # and build. %changelog +* Mon Dec 19 2011 Dave Jones +- x86, dumpstack: Fix code bytes breakage due to missing KERN_CONT + * Thu Dec 15 2011 Dennis Gilmore - build imx highbank and kirkwood kernel variants on arm - add patch for tegra usb storage resets diff --git a/x86-code-dump-fix-truncation.patch b/x86-code-dump-fix-truncation.patch new file mode 100644 index 000000000..dcd5a815c --- /dev/null +++ b/x86-code-dump-fix-truncation.patch @@ -0,0 +1,73 @@ +From: Clemens Ladisch +Date: Mon, 19 Dec 2011 21:07:58 +0000 (+0100) +Subject: x86, dumpstack: Fix code bytes breakage due to missing KERN_CONT +X-Git-Url: https://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftip%2Ftip.git;a=commitdiff_plain;h=13f541c10b30fc6529200d7f9a0073217709622f + +x86, dumpstack: Fix code bytes breakage due to missing KERN_CONT + +When printing the code bytes in show_registers(), the markers around the +byte at the fault address could make the printk() format string look +like a valid log level and facility code. This would prevent this byte +from being printed and result in a spurious newline: + +[ 7555.765589] Code: 8b 32 e9 94 00 00 00 81 7d 00 ff 00 00 00 0f 87 96 00 00 00 48 8b 83 c0 00 00 00 44 89 e2 44 89 e6 48 89 df 48 8b 80 d8 02 00 00 +[ 7555.765683] 8b 48 28 48 89 d0 81 e2 ff 0f 00 00 48 c1 e8 0c 48 c1 e0 04 + +Add KERN_CONT where needed, and elsewhere in show_registers() for +consistency. + +Signed-off-by: Clemens Ladisch +Link: http://lkml.kernel.org/r/4EEFA7AE.9020407@ladisch.de +Signed-off-by: H. Peter Anvin +--- + +diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c +index 3b97a80..c99f9ed 100644 +--- a/arch/x86/kernel/dumpstack_32.c ++++ b/arch/x86/kernel/dumpstack_32.c +@@ -116,16 +116,16 @@ void show_registers(struct pt_regs *regs) + for (i = 0; i < code_len; i++, ip++) { + if (ip < (u8 *)PAGE_OFFSET || + probe_kernel_address(ip, c)) { +- printk(" Bad EIP value."); ++ printk(KERN_CONT " Bad EIP value."); + break; + } + if (ip == (u8 *)regs->ip) +- printk("<%02x> ", c); ++ printk(KERN_CONT "<%02x> ", c); + else +- printk("%02x ", c); ++ printk(KERN_CONT "%02x ", c); + } + } +- printk("\n"); ++ printk(KERN_CONT "\n"); + } + + int is_valid_bugaddr(unsigned long ip) +diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c +index 19853ad..6d728d9 100644 +--- a/arch/x86/kernel/dumpstack_64.c ++++ b/arch/x86/kernel/dumpstack_64.c +@@ -284,16 +284,16 @@ void show_registers(struct pt_regs *regs) + for (i = 0; i < code_len; i++, ip++) { + if (ip < (u8 *)PAGE_OFFSET || + probe_kernel_address(ip, c)) { +- printk(" Bad RIP value."); ++ printk(KERN_CONT " Bad RIP value."); + break; + } + if (ip == (u8 *)regs->ip) +- printk("<%02x> ", c); ++ printk(KERN_CONT "<%02x> ", c); + else +- printk("%02x ", c); ++ printk(KERN_CONT "%02x ", c); + } + } +- printk("\n"); ++ printk(KERN_CONT "\n"); + } + + int is_valid_bugaddr(unsigned long ip) From 2d4a348a915cfe70181d48e6b8f35657bfe45b8e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Dec 2011 09:31:40 -0500 Subject: [PATCH 259/397] Fix config options in arm configs after latest commits --- config-arm-omap-generic | 2 ++ kernel.spec | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/config-arm-omap-generic b/config-arm-omap-generic index 6dc452357..912959b8e 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -1059,3 +1059,5 @@ CONFIG_LIBCRC32C=y # CONFIG_USB_HSO is not set CONFIG_CRYSTALHD=m + +# CONFIG_GPIO_GENERIC_PLATFORM is not set diff --git a/kernel.spec b/kernel.spec index 22eaf3e6d..a36480d50 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -1984,6 +1984,9 @@ fi # and build. %changelog +* Tue Dec 20 2011 Josh Boyer +- Fix config options in arm configs after latest commits + * Mon Dec 19 2011 Dave Jones - x86, dumpstack: Fix code bytes breakage due to missing KERN_CONT From 4c6625aa8f575ab0d65664b66716ba6fd34a9482 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Dec 2011 09:17:31 -0500 Subject: [PATCH 260/397] Backport upstream fix for b44_poll oops (rhbz #741117) --- b44-Use-dev_kfree_skb_irq-in-b44_tx.patch | 62 +++++++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 69 insertions(+) create mode 100644 b44-Use-dev_kfree_skb_irq-in-b44_tx.patch diff --git a/b44-Use-dev_kfree_skb_irq-in-b44_tx.patch b/b44-Use-dev_kfree_skb_irq-in-b44_tx.patch new file mode 100644 index 000000000..ff50bd534 --- /dev/null +++ b/b44-Use-dev_kfree_skb_irq-in-b44_tx.patch @@ -0,0 +1,62 @@ +From 15ac2b08a2fd0f4aacbe8ae39788252fea6fbe63 Mon Sep 17 00:00:00 2001 +From: Xander Hover +Date: Wed, 23 Nov 2011 16:40:31 -0500 +Subject: [PATCH] b44: Use dev_kfree_skb_irq() in b44_tx() + +Reported issues when using dev_kfree_skb() on UP systems and +systems with low numbers of cores. dev_kfree_skb_irq() will +properly save IRQ state before freeing the skb. + +Tested on 3.1.1 and 3.2_rc2 + +Example of reproducible trace of kernel 3.1.1 +------------[ cut here ]------------ + WARNING: at kernel/softirq.c:159 local_bh_enable+0x32/0x79() + ... + Pid: 0, comm: swapper Not tainted 3.1.1-gentoo #1 + Call Trace: + [] warn_slowpath_common+0x65/0x7a + [] ? local_bh_enable+0x32/0x79 + [] warn_slowpath_null+0xf/0x13 + [] local_bh_enable+0x32/0x79 + [] destroy_conntrack+0x7c/0x9b + [] nf_conntrack_destroy+0x1f/0x26 + [] skb_release_head_state+0x74/0x83 + [] __kfree_skb+0xb/0x6b + [] consume_skb+0x24/0x26 + [] b44_poll+0xaa/0x449 + [] net_rx_action+0x3f/0xea + [] __do_softirq+0x5f/0xd5 + [] ? local_bh_enable+0x79/0x79 + [] ? irq_exit+0x34/0x8d + [] ? do_IRQ+0x74/0x87 + [] ? common_interrupt+0x29/0x30 + [] ? default_idle+0x29/0x3e + [] ? cpu_idle+0x2f/0x5d + [] ? rest_init+0x79/0x7b + [] ? start_kernel+0x297/0x29c + [] ? i386_start_kernel+0xb0/0xb7 + ---[ end trace 583f33bb1aa207a9 ]--- + +Signed-off-by: Xander Hover +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/broadcom/b44.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/b44.c b/drivers/net/b44.c +index 4cf835d..3fb66d0 100644 +--- a/drivers/net/b44.c ++++ b/drivers/net/b44.c +@@ -608,7 +608,7 @@ static void b44_tx(struct b44 *bp) + skb->len, + DMA_TO_DEVICE); + rp->skb = NULL; +- dev_kfree_skb(skb); ++ dev_kfree_skb_irq(skb); + } + + bp->tx_cons = cons; +-- +1.7.7.4 + diff --git a/kernel.spec b/kernel.spec index a36480d50..42b13521e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -721,6 +721,9 @@ Patch21046: alps.patch #rhbz 767173 Patch21047: iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch +#rhbz 741117 +Patch21048: b44-Use-dev_kfree_skb_irq-in-b44_tx.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1337,6 +1340,9 @@ ApplyPatch alps.patch #rhbz 767173 ApplyPatch iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch +#rhbz 741117 +ApplyPatch b44-Use-dev_kfree_skb_irq-in-b44_tx.patch + # END OF PATCH APPLICATIONS %endif @@ -1986,6 +1992,7 @@ fi %changelog * Tue Dec 20 2011 Josh Boyer - Fix config options in arm configs after latest commits +- Backport upstream fix for b44_poll oops (rhbz #741117) * Mon Dec 19 2011 Dave Jones - x86, dumpstack: Fix code bytes breakage due to missing KERN_CONT From a4de26481e61277d79c1d6fc3be63683cdef0a1c Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Tue, 20 Dec 2011 08:44:48 -0600 Subject: [PATCH 261/397] set CONFIG_GPIO_GENERIC_PLATFORM=y on omap as its needed to be built in --- config-arm-omap-generic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-arm-omap-generic b/config-arm-omap-generic index 912959b8e..03913d36d 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -1060,4 +1060,4 @@ CONFIG_LIBCRC32C=y CONFIG_CRYSTALHD=m -# CONFIG_GPIO_GENERIC_PLATFORM is not set +CONFIG_GPIO_GENERIC_PLATFORM=y From 218e731170702d32259a47e5023b7e3588fe141a Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Wed, 21 Dec 2011 09:45:51 -0600 Subject: [PATCH 262/397] disable SND_ALI5451 DRM_NOUVEAU and MLX4_EN on all arm arches --- config-arm-generic | 6 ++++++ config-arm-highbank | 7 ------- config-arm-kirkwood | 7 ------- config-arm-tegra | 6 ------ 4 files changed, 6 insertions(+), 20 deletions(-) diff --git a/config-arm-generic b/config-arm-generic index 92e81e1b5..3141e66a5 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -174,3 +174,9 @@ CONFIG_LSM_MMAP_MIN_ADDR=32768 # CONFIG_DRM_RADEON is not set # CONFIG_ATM_HE is not set # CONFIG_SCSI_ACARD is not set + +# these all currently fail due to missing symbols __bad_udelay or +# error: implicit declaration of function ‘iowrite32be’ +# CONFIG_SND_ALI5451 is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_MLX4_EN is not set diff --git a/config-arm-highbank b/config-arm-highbank index f20dfdec0..d4aca8222 100644 --- a/config-arm-highbank +++ b/config-arm-highbank @@ -14,10 +14,3 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m CONFIG_CPU_FREQ_TABLE=y CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y - - -# these all currently fail due to missing symbols __bad_udelay or -# error: implicit declaration of function ‘iowrite32be’ -# CONFIG_SND_ALI5451 is not set -# CONFIG_DRM_NOUVEAU is not set -# CONFIG_MLX4_EN is not set diff --git a/config-arm-kirkwood b/config-arm-kirkwood index 631be67e7..415e822dc 100644 --- a/config-arm-kirkwood +++ b/config-arm-kirkwood @@ -41,10 +41,3 @@ CONFIG_MV_XOR=y CONFIG_CRYPTO_DEV_MV_CESA=m # CONFIG_TOUCHSCREEN_EETI is not set - -# these all currently fail due to missing symbols __bad_udelay or -# error: implicit declaration of function ‘iowrite32be’ -# CONFIG_SND_ALI5451 is not set -# CONFIG_DRM_NOUVEAU is not set -# CONFIG_MLX4_EN is not set - diff --git a/config-arm-tegra b/config-arm-tegra index ce272c1b1..b131978d2 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -83,9 +83,3 @@ CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_CRYSTALHD=m - -# these all currently fail due to missing symbols __bad_udelay or -# error: implicit declaration of function ‘iowrite32be’ -# CONFIG_SND_ALI5451 is not set -# CONFIG_DRM_NOUVEAU is not set -# CONFIG_MLX4_EN is not set From 3454da31210f9ef98f8369013dc34956e9bafacf Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 21 Dec 2011 13:37:14 -0500 Subject: [PATCH 263/397] Reinstate the route cache garbage collector. --- kernel.spec | 7 + route-cache-garbage-collector.patch | 201 ++++++++++++++++++++++++++++ 2 files changed, 208 insertions(+) create mode 100644 route-cache-garbage-collector.patch diff --git a/kernel.spec b/kernel.spec index 42b13521e..3bf1d45d4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -724,6 +724,8 @@ Patch21047: iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch #rhbz 741117 Patch21048: b44-Use-dev_kfree_skb_irq-in-b44_tx.patch +Patch22000: route-cache-garbage-collector.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1343,6 +1345,8 @@ ApplyPatch iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch #rhbz 741117 ApplyPatch b44-Use-dev_kfree_skb_irq-in-b44_tx.patch +ApplyPatch route-cache-garbage-collector.patch + # END OF PATCH APPLICATIONS %endif @@ -1990,6 +1994,9 @@ fi # and build. %changelog +* Wed Dec 21 2011 Dave Jones 2.6.41.5-5 +- Reinstate the route cache garbage collector. + * Tue Dec 20 2011 Josh Boyer - Fix config options in arm configs after latest commits - Backport upstream fix for b44_poll oops (rhbz #741117) diff --git a/route-cache-garbage-collector.patch b/route-cache-garbage-collector.patch new file mode 100644 index 000000000..6ea6e5e9b --- /dev/null +++ b/route-cache-garbage-collector.patch @@ -0,0 +1,201 @@ +Message-ID: <1324461072.2728.19.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC> +Subject: Re: Kernel-DOS error in arp mechanism =?UTF-8?Q?=E2=80=93?= no delete off incomplete arp adresses +From: Eric Dumazet +To: David Miller +Cc: richard.weinberger@gmail.com, gladewitz@gmx.de, + linux-kernel@vger.kernel.org, netdev@vger.kernel.org +Date: Wed, 21 Dec 2011 10:51:12 +0100 +In-Reply-To: <20111221.030727.1528369698756365464.davem@davemloft.net> +References: <4EEC5286.3070408@gmx.de> + + <1324453467.2610.20.camel@edumazet-laptop> + <20111221.030727.1528369698756365464.davem@davemloft.net> +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit +Sender: linux-kernel-owner@vger.kernel.org +List-ID: + +Le mercredi 21 décembre 2011 à 03:07 -0500, David Miller a écrit : +> From: Eric Dumazet +> Date: Wed, 21 Dec 2011 08:44:27 +0100 +> +> > David, I suggest we add back the garbage collector for current kernels, +> > we'll remove it when route cache really disappear ? +> > +> > I'll send a patch today. +> +> Yes, it's the best idea. +> +> We can actually remove it again as early as when when route neigh's +> are ref-less. + +Here is the patch I successfully tested in the neighbour stress +situation. This is a stable candidate (2.6.39+) + +Thanks ! + +[PATCH] ipv4: reintroduce route cache garbage collector + +Commit 2c8cec5c10b (ipv4: Cache learned PMTU information in inetpeer) +removed IP route cache garbage collector a bit too soon, as this gc was +responsible for expired routes cleanup, releasing their neighbour +reference. + +As pointed out by Robert Gladewitz, recent kernels can fill and exhaust +their neighbour cache. + +Reintroduce the garbage collection, since we'll have to wait our +neighbour lookups become refcount-less to not depend on this stuff. + +Reported-by: Robert Gladewitz +Signed-off-by: Eric Dumazet +--- + net/ipv4/route.c | 107 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 107 insertions(+) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 46af623..252c512 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -133,6 +134,9 @@ static int ip_rt_min_advmss __read_mostly = 256; + static int rt_chain_length_max __read_mostly = 20; + static int redirect_genid; + ++static struct delayed_work expires_work; ++static unsigned long expires_ljiffies; ++ + /* + * Interface to generic destination cache. + */ +@@ -830,6 +834,97 @@ static int has_noalias(const struct rtable *head, const struct rtable *rth) + return ONE; + } + ++static void rt_check_expire(void) ++{ ++ static unsigned int rover; ++ unsigned int i = rover, goal; ++ struct rtable *rth; ++ struct rtable __rcu **rthp; ++ unsigned long samples = 0; ++ unsigned long sum = 0, sum2 = 0; ++ unsigned long delta; ++ u64 mult; ++ ++ delta = jiffies - expires_ljiffies; ++ expires_ljiffies = jiffies; ++ mult = ((u64)delta) << rt_hash_log; ++ if (ip_rt_gc_timeout > 1) ++ do_div(mult, ip_rt_gc_timeout); ++ goal = (unsigned int)mult; ++ if (goal > rt_hash_mask) ++ goal = rt_hash_mask + 1; ++ for (; goal > 0; goal--) { ++ unsigned long tmo = ip_rt_gc_timeout; ++ unsigned long length; ++ ++ i = (i + 1) & rt_hash_mask; ++ rthp = &rt_hash_table[i].chain; ++ ++ if (need_resched()) ++ cond_resched(); ++ ++ samples++; ++ ++ if (rcu_dereference_raw(*rthp) == NULL) ++ continue; ++ length = 0; ++ spin_lock_bh(rt_hash_lock_addr(i)); ++ while ((rth = rcu_dereference_protected(*rthp, ++ lockdep_is_held(rt_hash_lock_addr(i)))) != NULL) { ++ prefetch(rth->dst.rt_next); ++ if (rt_is_expired(rth)) { ++ *rthp = rth->dst.rt_next; ++ rt_free(rth); ++ continue; ++ } ++ if (rth->dst.expires) { ++ /* Entry is expired even if it is in use */ ++ if (time_before_eq(jiffies, rth->dst.expires)) { ++nofree: ++ tmo >>= 1; ++ rthp = &rth->dst.rt_next; ++ /* ++ * We only count entries on ++ * a chain with equal hash inputs once ++ * so that entries for different QOS ++ * levels, and other non-hash input ++ * attributes don't unfairly skew ++ * the length computation ++ */ ++ length += has_noalias(rt_hash_table[i].chain, rth); ++ continue; ++ } ++ } else if (!rt_may_expire(rth, tmo, ip_rt_gc_timeout)) ++ goto nofree; ++ ++ /* Cleanup aged off entries. */ ++ *rthp = rth->dst.rt_next; ++ rt_free(rth); ++ } ++ spin_unlock_bh(rt_hash_lock_addr(i)); ++ sum += length; ++ sum2 += length*length; ++ } ++ if (samples) { ++ unsigned long avg = sum / samples; ++ unsigned long sd = int_sqrt(sum2 / samples - avg*avg); ++ rt_chain_length_max = max_t(unsigned long, ++ ip_rt_gc_elasticity, ++ (avg + 4*sd) >> FRACT_BITS); ++ } ++ rover = i; ++} ++ ++/* ++ * rt_worker_func() is run in process context. ++ * we call rt_check_expire() to scan part of the hash table ++ */ ++static void rt_worker_func(struct work_struct *work) ++{ ++ rt_check_expire(); ++ schedule_delayed_work(&expires_work, ip_rt_gc_interval); ++} ++ + /* + * Perturbation of rt_genid by a small quantity [1..256] + * Using 8 bits of shuffling ensure we can call rt_cache_invalidate() +@@ -3179,6 +3274,13 @@ static ctl_table ipv4_route_table[] = { + .proc_handler = proc_dointvec_jiffies, + }, + { ++ .procname = "gc_interval", ++ .data = &ip_rt_gc_interval, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_jiffies, ++ }, ++ { + .procname = "redirect_load", + .data = &ip_rt_redirect_load, + .maxlen = sizeof(int), +@@ -3388,6 +3490,11 @@ int __init ip_rt_init(void) + devinet_init(); + ip_fib_init(); + ++ INIT_DELAYED_WORK_DEFERRABLE(&expires_work, rt_worker_func); ++ expires_ljiffies = jiffies; ++ schedule_delayed_work(&expires_work, ++ net_random() % ip_rt_gc_interval + ip_rt_gc_interval); ++ + if (ip_rt_proc_init()) + printk(KERN_ERR "Unable to create route proc files\n"); + #ifdef CONFIG_XFRM + + +-- +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/ + From 0ae65ec719acd2ff8c2ef90699768f3a8f4d7b90 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 21 Dec 2011 17:11:25 -0500 Subject: [PATCH 264/397] Linux 3.1.6 (Fedora 2.6.31.6) --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 3bf1d45d4..7d606964d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 5 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 # Set rpm version accordingly @@ -1994,6 +1994,9 @@ fi # and build. %changelog +* Wed Dec 21 2011 Dave Jones 2.6.41.6-1 +- Linux 3.1.6 (Fedora 2.6.31.6) + * Wed Dec 21 2011 Dave Jones 2.6.41.5-5 - Reinstate the route cache garbage collector. diff --git a/sources b/sources index 87c391c01..43846ab38 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -84c040bb8c4f46d351731cb0c05d9474 patch-3.1.5.bz2 +b815dda0a05f7774a0ed0b705b8cfd4c patch-3.1.6.bz2 From 2ec5a5f81db09785dfb4e47d0d5324016a6c02f4 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 3 Jan 2012 10:21:36 -0500 Subject: [PATCH 265/397] thp: reduce khugepaged freezing latency (rhbz 771006) --- kernel.spec | 9 ++++ thp-reduce-khugepaged-freezing-latency.patch | 54 ++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 thp-reduce-khugepaged-freezing-latency.patch diff --git a/kernel.spec b/kernel.spec index 7d606964d..2b66d7fd0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -724,6 +724,9 @@ Patch21047: iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch #rhbz 741117 Patch21048: b44-Use-dev_kfree_skb_irq-in-b44_tx.patch +#rhbz 771006 +Patch21050: thp-reduce-khugepaged-freezing-latency.patch + Patch22000: route-cache-garbage-collector.patch %endif @@ -1345,6 +1348,9 @@ ApplyPatch iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch #rhbz 741117 ApplyPatch b44-Use-dev_kfree_skb_irq-in-b44_tx.patch +#rhbz 771006 +ApplyPatch thp-reduce-khugepaged-freezing-latency.patch + ApplyPatch route-cache-garbage-collector.patch # END OF PATCH APPLICATIONS @@ -1994,6 +2000,9 @@ fi # and build. %changelog +* Tue Jan 03 2012 Dave Jones +- thp: reduce khugepaged freezing latency (rhbz 771006) + * Wed Dec 21 2011 Dave Jones 2.6.41.6-1 - Linux 3.1.6 (Fedora 2.6.31.6) diff --git a/thp-reduce-khugepaged-freezing-latency.patch b/thp-reduce-khugepaged-freezing-latency.patch new file mode 100644 index 000000000..b7b205177 --- /dev/null +++ b/thp-reduce-khugepaged-freezing-latency.patch @@ -0,0 +1,54 @@ +From: Andrea Arcangeli +Subject: thp: reduce khugepaged freezing latency + +Use wait_event_freezable_timeout() instead of +schedule_timeout_interruptible() to avoid missing freezer wakeups. A +try_to_freeze() would have been needed in the +khugepaged_alloc_hugepage tight loop too in case of the allocation +failing repeatedly, and wait_event_freezable_timeout will provide it +too. + +khugepaged would still freeze just fine by trying again the next +minute but it's better if it freezes immediately. + +Reported-by: Jiri Slaby +Signed-off-by: Andrea Arcangeli + +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index 4298aba..fd925d0 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -2259,12 +2259,9 @@ static void khugepaged_do_scan(struct page **hpage) + + static void khugepaged_alloc_sleep(void) + { +- DEFINE_WAIT(wait); +- add_wait_queue(&khugepaged_wait, &wait); +- schedule_timeout_interruptible( +- msecs_to_jiffies( +- khugepaged_alloc_sleep_millisecs)); +- remove_wait_queue(&khugepaged_wait, &wait); ++ wait_event_freezable_timeout(khugepaged_wait, false, ++ msecs_to_jiffies( ++ khugepaged_alloc_sleep_millisecs)); + } + + #ifndef CONFIG_NUMA +@@ -2313,14 +2310,11 @@ static void khugepaged_loop(void) + if (unlikely(kthread_should_stop())) + break; + if (khugepaged_has_work()) { +- DEFINE_WAIT(wait); + if (!khugepaged_scan_sleep_millisecs) + continue; +- add_wait_queue(&khugepaged_wait, &wait); +- schedule_timeout_interruptible( ++ wait_event_freezable_timeout(khugepaged_wait, false, + msecs_to_jiffies( + khugepaged_scan_sleep_millisecs)); +- remove_wait_queue(&khugepaged_wait, &wait); + } else if (khugepaged_enabled()) + wait_event_freezable(khugepaged_wait, + khugepaged_wait_event()); + + From 12b320b80639dc5552157c34b9b0028f2e4374c4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 3 Jan 2012 10:27:26 -0500 Subject: [PATCH 266/397] CVE-2011-4622 kvm: pit timer with no irqchip crashes the system (rhbz 770102) --- ...tarting-PIT-timers-in-the-absence-of.patch | 69 +++++++++++++++++++ kernel.spec | 11 ++- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch diff --git a/KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch b/KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch new file mode 100644 index 000000000..07ef3e71b --- /dev/null +++ b/KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch @@ -0,0 +1,69 @@ +From 0924ab2cfa98b1ece26c033d696651fd62896c69 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka +Date: Wed, 14 Dec 2011 19:25:13 +0100 +Subject: [PATCH] KVM: x86: Prevent starting PIT timers in the absence of + irqchip support + +User space may create the PIT and forgets about setting up the irqchips. +In that case, firing PIT IRQs will crash the host: + +BUG: unable to handle kernel NULL pointer dereference at 0000000000000128 +IP: [] kvm_set_irq+0x30/0x170 [kvm] +... +Call Trace: + [] pit_do_work+0x51/0xd0 [kvm] + [] process_one_work+0x111/0x4d0 + [] worker_thread+0x152/0x340 + [] kthread+0x7e/0x90 + [] kernel_thread_helper+0x4/0x10 + +Prevent this by checking the irqchip mode before starting a timer. We +can't deny creating the PIT if the irqchips aren't set up yet as +current user land expects this order to work. + +Signed-off-by: Jan Kiszka +Signed-off-by: Marcelo Tosatti +--- + arch/x86/kvm/i8254.c | 10 +++++++--- + 1 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c +index 76e3f1c..405f262 100644 +--- a/arch/x86/kvm/i8254.c ++++ b/arch/x86/kvm/i8254.c +@@ -338,11 +338,15 @@ static enum hrtimer_restart pit_timer_fn(struct hrtimer *data) + return HRTIMER_NORESTART; + } + +-static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period) ++static void create_pit_timer(struct kvm *kvm, u32 val, int is_period) + { ++ struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state; + struct kvm_timer *pt = &ps->pit_timer; + s64 interval; + ++ if (!irqchip_in_kernel(kvm)) ++ return; ++ + interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ); + + pr_debug("create pit timer, interval is %llu nsec\n", interval); +@@ -394,13 +398,13 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val) + /* FIXME: enhance mode 4 precision */ + case 4: + if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)) { +- create_pit_timer(ps, val, 0); ++ create_pit_timer(kvm, val, 0); + } + break; + case 2: + case 3: + if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)){ +- create_pit_timer(ps, val, 1); ++ create_pit_timer(kvm, val, 1); + } + break; + default: +-- +1.7.6.2 + diff --git a/kernel.spec b/kernel.spec index 2b66d7fd0..ce210039a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -727,6 +727,9 @@ Patch21048: b44-Use-dev_kfree_skb_irq-in-b44_tx.patch #rhbz 771006 Patch21050: thp-reduce-khugepaged-freezing-latency.patch +#rhbz 770102 +Patch21055: KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch + Patch22000: route-cache-garbage-collector.patch %endif @@ -1353,6 +1356,9 @@ ApplyPatch thp-reduce-khugepaged-freezing-latency.patch ApplyPatch route-cache-garbage-collector.patch +#rhbz 770102 +ApplyPatch KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch + # END OF PATCH APPLICATIONS %endif @@ -2000,6 +2006,9 @@ fi # and build. %changelog +* Tue Jan 03 2012 Josh Boyer +- CVE-2011-4622 kvm: pit timer with no irqchip crashes the system (rhbz 770102) + * Tue Jan 03 2012 Dave Jones - thp: reduce khugepaged freezing latency (rhbz 771006) From d4809cb07393453f7e77dd364649b6cf0e4c2341 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 3 Jan 2012 10:38:53 -0500 Subject: [PATCH 267/397] thp: reduce khugepaged freezing latency (rhbz 771006) --- kernel.spec | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel.spec b/kernel.spec index ce210039a..946e14b64 100644 --- a/kernel.spec +++ b/kernel.spec @@ -730,6 +730,9 @@ Patch21050: thp-reduce-khugepaged-freezing-latency.patch #rhbz 770102 Patch21055: KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch +#rhbz 771006 +Patch21050: thp-reduce-khugepaged-freezing-latency.patch + Patch22000: route-cache-garbage-collector.patch %endif @@ -1354,6 +1357,9 @@ ApplyPatch b44-Use-dev_kfree_skb_irq-in-b44_tx.patch #rhbz 771006 ApplyPatch thp-reduce-khugepaged-freezing-latency.patch +#rhbz 771006 +ApplyPatch thp-reduce-khugepaged-freezing-latency.patch + ApplyPatch route-cache-garbage-collector.patch #rhbz 770102 @@ -2006,6 +2012,9 @@ fi # and build. %changelog +* Tue Jan 03 2012 Dave Jones +- thp: reduce khugepaged freezing latency (rhbz 771006) + * Tue Jan 03 2012 Josh Boyer - CVE-2011-4622 kvm: pit timer with no irqchip crashes the system (rhbz 770102) From 97d02603ceb4c1fdb514e9a5d70f4a27f8bee0d7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 3 Jan 2012 10:42:33 -0500 Subject: [PATCH 268/397] Add bluetooth support for BCM20102A0 (rhbz 770233) --- Bluetooth-Add-support-for-BCM20702A0.patch | 15 +++++++++++++++ kernel.spec | 9 +++++++++ 2 files changed, 24 insertions(+) create mode 100644 Bluetooth-Add-support-for-BCM20702A0.patch diff --git a/Bluetooth-Add-support-for-BCM20702A0.patch b/Bluetooth-Add-support-for-BCM20702A0.patch new file mode 100644 index 000000000..1e579342c --- /dev/null +++ b/Bluetooth-Add-support-for-BCM20702A0.patch @@ -0,0 +1,15 @@ +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index f9b7260..28a5876 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -100,6 +100,10 @@ static struct usb_device_id btusb_table[] = { + /* Canyon CN-BTU1 with HID interfaces */ + { USB_DEVICE(0x0c10, 0x0000) }, + ++ /* Broadcom BCM20702A0 */ ++ { USB_DEVICE(0x0a5c, 0x21e3) }, ++ { USB_DEVICE(0x413c, 0x8197) }, ++ + { } /* Terminating entry */ + }; + diff --git a/kernel.spec b/kernel.spec index 946e14b64..0e05f1f83 100644 --- a/kernel.spec +++ b/kernel.spec @@ -733,6 +733,9 @@ Patch21055: KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch #rhbz 771006 Patch21050: thp-reduce-khugepaged-freezing-latency.patch +#rhbz 770233 +Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch + Patch22000: route-cache-garbage-collector.patch %endif @@ -1365,6 +1368,9 @@ ApplyPatch route-cache-garbage-collector.patch #rhbz 770102 ApplyPatch KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch +#rhbz 770233 +ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch + # END OF PATCH APPLICATIONS %endif @@ -2012,6 +2018,9 @@ fi # and build. %changelog +* Tue Jan 03 2012 Josh Boyer +- Add bluetooth support for BCM20102A0 (rhbz 770233) + * Tue Jan 03 2012 Dave Jones - thp: reduce khugepaged freezing latency (rhbz 771006) From 63b68937957fa17470725fa09d7cb22d2877c209 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 3 Jan 2012 11:02:23 -0500 Subject: [PATCH 269/397] Undo multiple application of thp: reduce khugepaged freezing latency --- kernel.spec | 9 --------- 1 file changed, 9 deletions(-) diff --git a/kernel.spec b/kernel.spec index 0e05f1f83..83f8471ad 100644 --- a/kernel.spec +++ b/kernel.spec @@ -730,9 +730,6 @@ Patch21050: thp-reduce-khugepaged-freezing-latency.patch #rhbz 770102 Patch21055: KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch -#rhbz 771006 -Patch21050: thp-reduce-khugepaged-freezing-latency.patch - #rhbz 770233 Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch @@ -1360,9 +1357,6 @@ ApplyPatch b44-Use-dev_kfree_skb_irq-in-b44_tx.patch #rhbz 771006 ApplyPatch thp-reduce-khugepaged-freezing-latency.patch -#rhbz 771006 -ApplyPatch thp-reduce-khugepaged-freezing-latency.patch - ApplyPatch route-cache-garbage-collector.patch #rhbz 770102 @@ -2021,9 +2015,6 @@ fi * Tue Jan 03 2012 Josh Boyer - Add bluetooth support for BCM20102A0 (rhbz 770233) -* Tue Jan 03 2012 Dave Jones -- thp: reduce khugepaged freezing latency (rhbz 771006) - * Tue Jan 03 2012 Josh Boyer - CVE-2011-4622 kvm: pit timer with no irqchip crashes the system (rhbz 770102) From 4537a47c8922c21733c175b764b350e371ef2974 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 3 Jan 2012 14:16:34 -0500 Subject: [PATCH 270/397] Linux 3.1.7 (Fedora 2.6.41.7) Should fix rhbz 767248 and possibly other 'fails to resume' bugs --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 83f8471ad..b22d4d5b6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 # Set rpm version accordingly @@ -2012,6 +2012,9 @@ fi # and build. %changelog +* Tue Jan 03 2012 Josh Boyer 2.6.41.7-1 +- Linux 3.1.7 + * Tue Jan 03 2012 Josh Boyer - Add bluetooth support for BCM20102A0 (rhbz 770233) diff --git a/sources b/sources index 43846ab38..efd7ae008 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -b815dda0a05f7774a0ed0b705b8cfd4c patch-3.1.6.bz2 +13ea1e611a0a580138b8203e6f1353ed patch-3.1.7.bz2 From 0456a2e1990982cfba0f600fd5e6fe49c4c612a6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 4 Jan 2012 10:36:23 -0500 Subject: [PATCH 271/397] CVE-2011-4347 kvm: device assignment DoS (rhbz 770096) --- KVM-fix-device-assignment-permissions.patch | 206 ++++++++++++++++++++ kernel.spec | 11 +- 2 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 KVM-fix-device-assignment-permissions.patch diff --git a/KVM-fix-device-assignment-permissions.patch b/KVM-fix-device-assignment-permissions.patch new file mode 100644 index 000000000..208948200 --- /dev/null +++ b/KVM-fix-device-assignment-permissions.patch @@ -0,0 +1,206 @@ +From 423873736b78f549fbfa2f715f2e4de7e6c5e1e9 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 20 Dec 2011 21:59:03 -0700 +Subject: [PATCH 1/2] KVM: Remove ability to assign a device without iommu + support + +This option has no users and it exposes a security hole that we +can allow devices to be assigned without iommu protection. Make +KVM_DEV_ASSIGN_ENABLE_IOMMU a mandatory option. + +Signed-off-by: Alex Williamson +Signed-off-by: Marcelo Tosatti +--- + virt/kvm/assigned-dev.c | 18 +++++++++--------- + 1 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c +index 3ad0925..a251a28 100644 +--- a/virt/kvm/assigned-dev.c ++++ b/virt/kvm/assigned-dev.c +@@ -487,6 +487,9 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, + struct kvm_assigned_dev_kernel *match; + struct pci_dev *dev; + ++ if (!(assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU)) ++ return -EINVAL; ++ + mutex_lock(&kvm->lock); + idx = srcu_read_lock(&kvm->srcu); + +@@ -544,16 +547,14 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, + + list_add(&match->list, &kvm->arch.assigned_dev_head); + +- if (assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) { +- if (!kvm->arch.iommu_domain) { +- r = kvm_iommu_map_guest(kvm); +- if (r) +- goto out_list_del; +- } +- r = kvm_assign_device(kvm, match); ++ if (!kvm->arch.iommu_domain) { ++ r = kvm_iommu_map_guest(kvm); + if (r) + goto out_list_del; + } ++ r = kvm_assign_device(kvm, match); ++ if (r) ++ goto out_list_del; + + out: + srcu_read_unlock(&kvm->srcu, idx); +@@ -593,8 +594,7 @@ static int kvm_vm_ioctl_deassign_device(struct kvm *kvm, + goto out; + } + +- if (match->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) +- kvm_deassign_device(kvm, match); ++ kvm_deassign_device(kvm, match); + + kvm_free_assigned_device(kvm, match); + +-- +1.7.7.5 + + +From 3d27e23b17010c668db311140b17bbbb70c78fb9 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 20 Dec 2011 21:59:09 -0700 +Subject: [PATCH 2/2] KVM: Device assignment permission checks + +Only allow KVM device assignment to attach to devices which: + + - Are not bridges + - Have BAR resources (assume others are special devices) + - The user has permissions to use + +Assigning a bridge is a configuration error, it's not supported, and +typically doesn't result in the behavior the user is expecting anyway. +Devices without BAR resources are typically chipset components that +also don't have host drivers. We don't want users to hold such devices +captive or cause system problems by fencing them off into an iommu +domain. We determine "permission to use" by testing whether the user +has access to the PCI sysfs resource files. By default a normal user +will not have access to these files, so it provides a good indication +that an administration agent has granted the user access to the device. + +[Yang Bai: add missing #include] +[avi: fix comment style] + +Signed-off-by: Alex Williamson +Signed-off-by: Yang Bai +Signed-off-by: Marcelo Tosatti +--- + virt/kvm/assigned-dev.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 75 insertions(+), 0 deletions(-) + +diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c +index a251a28..758e3b3 100644 +--- a/virt/kvm/assigned-dev.c ++++ b/virt/kvm/assigned-dev.c +@@ -17,6 +17,8 @@ + #include + #include + #include ++#include ++#include + #include "irq.h" + + static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head, +@@ -480,12 +482,73 @@ out: + return r; + } + ++/* ++ * We want to test whether the caller has been granted permissions to ++ * use this device. To be able to configure and control the device, ++ * the user needs access to PCI configuration space and BAR resources. ++ * These are accessed through PCI sysfs. PCI config space is often ++ * passed to the process calling this ioctl via file descriptor, so we ++ * can't rely on access to that file. We can check for permissions ++ * on each of the BAR resource files, which is a pretty clear ++ * indicator that the user has been granted access to the device. ++ */ ++static int probe_sysfs_permissions(struct pci_dev *dev) ++{ ++#ifdef CONFIG_SYSFS ++ int i; ++ bool bar_found = false; ++ ++ for (i = PCI_STD_RESOURCES; i <= PCI_STD_RESOURCE_END; i++) { ++ char *kpath, *syspath; ++ struct path path; ++ struct inode *inode; ++ int r; ++ ++ if (!pci_resource_len(dev, i)) ++ continue; ++ ++ kpath = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); ++ if (!kpath) ++ return -ENOMEM; ++ ++ /* Per sysfs-rules, sysfs is always at /sys */ ++ syspath = kasprintf(GFP_KERNEL, "/sys%s/resource%d", kpath, i); ++ kfree(kpath); ++ if (!syspath) ++ return -ENOMEM; ++ ++ r = kern_path(syspath, LOOKUP_FOLLOW, &path); ++ kfree(syspath); ++ if (r) ++ return r; ++ ++ inode = path.dentry->d_inode; ++ ++ r = inode_permission(inode, MAY_READ | MAY_WRITE | MAY_ACCESS); ++ path_put(&path); ++ if (r) ++ return r; ++ ++ bar_found = true; ++ } ++ ++ /* If no resources, probably something special */ ++ if (!bar_found) ++ return -EPERM; ++ ++ return 0; ++#else ++ return -EINVAL; /* No way to control the device without sysfs */ ++#endif ++} ++ + static int kvm_vm_ioctl_assign_device(struct kvm *kvm, + struct kvm_assigned_pci_dev *assigned_dev) + { + int r = 0, idx; + struct kvm_assigned_dev_kernel *match; + struct pci_dev *dev; ++ u8 header_type; + + if (!(assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU)) + return -EINVAL; +@@ -516,6 +579,18 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, + r = -EINVAL; + goto out_free; + } ++ ++ /* Don't allow bridges to be assigned */ ++ pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); ++ if ((header_type & PCI_HEADER_TYPE) != PCI_HEADER_TYPE_NORMAL) { ++ r = -EPERM; ++ goto out_put; ++ } ++ ++ r = probe_sysfs_permissions(dev); ++ if (r) ++ goto out_put; ++ + if (pci_enable_device(dev)) { + printk(KERN_INFO "%s: Could not enable PCI device\n", __func__); + r = -EBUSY; +-- +1.7.7.5 + diff --git a/kernel.spec b/kernel.spec index b22d4d5b6..a4db929fc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -730,6 +730,9 @@ Patch21050: thp-reduce-khugepaged-freezing-latency.patch #rhbz 770102 Patch21055: KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch +#rhbz 770096 +Patch21056: KVM-fix-device-assignment-permissions.patch + #rhbz 770233 Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch @@ -1365,6 +1368,9 @@ ApplyPatch KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch #rhbz 770233 ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch +#rhbz 770096 +ApplyPatch KVM-fix-device-assignment-permissions.patch + # END OF PATCH APPLICATIONS %endif @@ -2012,6 +2018,9 @@ fi # and build. %changelog +* Wed Jan 04 2012 Josh Boyer +- CVE-2011-4347 kvm: device assignment DoS (rhbz 770096) + * Tue Jan 03 2012 Josh Boyer 2.6.41.7-1 - Linux 3.1.7 From dba7dc5d3e285778ab3c55461e336a4c981462e3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 6 Jan 2012 21:40:42 -0500 Subject: [PATCH 272/397] Linux 3.1.8 (Fedora 2.6.41.8) --- ...-to-switch-to-HT40-if-not-associated.patch | 38 ---- kernel.spec | 22 +- oom-fix-integer-overflow-of-points.patch | 100 --------- route-cache-garbage-collector.patch | 201 ------------------ sources | 2 +- 5 files changed, 6 insertions(+), 357 deletions(-) delete mode 100644 iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch delete mode 100644 oom-fix-integer-overflow-of-points.patch delete mode 100644 route-cache-garbage-collector.patch diff --git a/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch b/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch deleted file mode 100644 index 08c9e443b..000000000 --- a/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch +++ /dev/null @@ -1,38 +0,0 @@ -My previous patch -34a5b4b6af104cf18eb50748509528b9bdbc4036 iwlwifi: do not re-configure -HT40 after associated - -Fix the case of HT40 after association on specified AP, but it break the -association for some APs and cause not able to establish connection. -We need to address HT40 before and after addociation. - -CC: stable@vger.kernel.org #3.0+ -Reported-by: Andrej Gelenberg -Signed-off-by: Wey-Yi Guy -Tested-by: Andrej Gelenberg ---- - drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -index a7a6def..5c7c17c 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -@@ -606,8 +606,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) - if (ctx->ht.enabled) { - /* if HT40 is used, it should not change - * after associated except channel switch */ -- if (iwl_is_associated_ctx(ctx) && -- !ctx->ht.is_40mhz) -+ if (!ctx->ht.is_40mhz || -+ !iwl_is_associated_ctx(ctx)) - iwlagn_config_ht40(conf, ctx); - } else - ctx->ht.is_40mhz = false; --- -1.7.0.4 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index a4db929fc..a62c94d79 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 @@ -688,8 +688,6 @@ Patch21031: benet-remove-bogus-unlikely-on-vlan-check.patch Patch21040: x86-code-dump-fix-truncation.patch -Patch21070: oom-fix-integer-overflow-of-points.patch - #rhbz 728607 Patch21060: elantech.patch @@ -718,9 +716,6 @@ Patch21045: nfs-client-freezer.patch #rhbz 590880 Patch21046: alps.patch -#rhbz 767173 -Patch21047: iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch - #rhbz 741117 Patch21048: b44-Use-dev_kfree_skb_irq-in-b44_tx.patch @@ -736,8 +731,6 @@ Patch21056: KVM-fix-device-assignment-permissions.patch #rhbz 770233 Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch -Patch22000: route-cache-garbage-collector.patch - %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1319,9 +1312,6 @@ ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch #rhbz 736815 ApplyPatch x86-code-dump-fix-truncation.patch -#rhbz 750402 -ApplyPatch oom-fix-integer-overflow-of-points.patch - #rhbz 728607 ApplyPatch elantech.patch @@ -1351,17 +1341,12 @@ ApplyPatch nfs-client-freezer.patch #rhbz 590880 ApplyPatch alps.patch -#rhbz 767173 -ApplyPatch iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch - #rhbz 741117 ApplyPatch b44-Use-dev_kfree_skb_irq-in-b44_tx.patch #rhbz 771006 ApplyPatch thp-reduce-khugepaged-freezing-latency.patch -ApplyPatch route-cache-garbage-collector.patch - #rhbz 770102 ApplyPatch KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch @@ -2018,6 +2003,9 @@ fi # and build. %changelog +* Fri Jan 06 2012 Josh Boyer 2.6.41.8-1 +- Linux 3.1.8 + * Wed Jan 04 2012 Josh Boyer - CVE-2011-4347 kvm: device assignment DoS (rhbz 770096) diff --git a/oom-fix-integer-overflow-of-points.patch b/oom-fix-integer-overflow-of-points.patch deleted file mode 100644 index 02f6a8f72..000000000 --- a/oom-fix-integer-overflow-of-points.patch +++ /dev/null @@ -1,100 +0,0 @@ - -Delivered-To: jwboyer@gmail.com -Received: by 10.220.45.11 with SMTP id c11cs62970vcf; - Mon, 31 Oct 2011 08:56:49 -0700 (PDT) -Received: by 10.101.15.19 with SMTP id s19mr2706064ani.103.1320076596057; - Mon, 31 Oct 2011 08:56:36 -0700 (PDT) -Return-Path: -Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) - by mx.google.com with ESMTP id x8si7676575ani.27.2011.10.31.08.56.32; - Mon, 31 Oct 2011 08:56:36 -0700 (PDT) -Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; -Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=linux-kernel-owner@vger.kernel.org -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S934545Ab1JaP4X (ORCPT + 99 others); - Mon, 31 Oct 2011 11:56:23 -0400 -Received: from mx1.redhat.com ([209.132.183.28]:23653 "EHLO mx1.redhat.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S934538Ab1JaP4X (ORCPT ); - Mon, 31 Oct 2011 11:56:23 -0400 -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p9VFuHOO027543 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Mon, 31 Oct 2011 11:56:18 -0400 -Received: from dhcp-26-164.brq.redhat.com (dhcp-26-164.brq.redhat.com [10.34.26.164]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p9VFuEK3018476; - Mon, 31 Oct 2011 11:56:15 -0400 -From: Frantisek Hrbata -To: rientjes@google.com -Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, - akpm@linux-foundation.org, kosaki.motohiro@jp.fujitsu.com, - oleg@redhat.com, minchan.kim@gmail.com, stable@kernel.org, - eteo@redhat.com, pmatouse@redhat.com -Subject: [PATCH v2] oom: fix integer overflow of points in oom_badness -Date: Mon, 31 Oct 2011 16:56:09 +0100 -Message-Id: <1320076569-23872-1-git-send-email-fhrbata@redhat.com> -In-Reply-To: <1320048865-13175-1-git-send-email-fhrbata@redhat.com> -References: <1320048865-13175-1-git-send-email-fhrbata@redhat.com> -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org - -An integer overflow will happen on 64bit archs if task's sum of rss, swapents -and nr_ptes exceeds (2^31)/1000 value. This was introduced by commit - -f755a04 oom: use pte pages in OOM score - -where the oom score computation was divided into several steps and it's no -longer computed as one expression in unsigned long(rss, swapents, nr_pte are -unsigned long), where the result value assigned to points(int) is in -range(1..1000). So there could be an int overflow while computing - -176 points *= 1000; - -and points may have negative value. Meaning the oom score for a mem hog task -will be one. - -196 if (points <= 0) -197 return 1; - -For example: -[ 3366] 0 3366 35390480 24303939 5 0 0 oom01 -Out of memory: Kill process 3366 (oom01) score 1 or sacrifice child - -Here the oom1 process consumes more than 24303939(rss)*4096~=92GB physical -memory, but it's oom score is one. - -In this situation the mem hog task is skipped and oom killer kills another and -most probably innocent task with oom score greater than one. - -The points variable should be of type long instead of int to prevent the int -overflow. - -Signed-off-by: Frantisek Hrbata ---- - mm/oom_kill.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/mm/oom_kill.c b/mm/oom_kill.c -index 626303b..e9a1785 100644 ---- a/mm/oom_kill.c -+++ b/mm/oom_kill.c -@@ -162,7 +162,7 @@ static bool oom_unkillable_task(struct task_struct *p, - unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem, - const nodemask_t *nodemask, unsigned long totalpages) - { -- int points; -+ long points; - - if (oom_unkillable_task(p, mem, nodemask)) - return 0; --- -1.7.6.4 - --- -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/route-cache-garbage-collector.patch b/route-cache-garbage-collector.patch deleted file mode 100644 index 6ea6e5e9b..000000000 --- a/route-cache-garbage-collector.patch +++ /dev/null @@ -1,201 +0,0 @@ -Message-ID: <1324461072.2728.19.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC> -Subject: Re: Kernel-DOS error in arp mechanism =?UTF-8?Q?=E2=80=93?= no delete off incomplete arp adresses -From: Eric Dumazet -To: David Miller -Cc: richard.weinberger@gmail.com, gladewitz@gmx.de, - linux-kernel@vger.kernel.org, netdev@vger.kernel.org -Date: Wed, 21 Dec 2011 10:51:12 +0100 -In-Reply-To: <20111221.030727.1528369698756365464.davem@davemloft.net> -References: <4EEC5286.3070408@gmx.de> - - <1324453467.2610.20.camel@edumazet-laptop> - <20111221.030727.1528369698756365464.davem@davemloft.net> -Content-Type: text/plain; charset="UTF-8" -Content-Transfer-Encoding: 8bit -Sender: linux-kernel-owner@vger.kernel.org -List-ID: - -Le mercredi 21 décembre 2011 à 03:07 -0500, David Miller a écrit : -> From: Eric Dumazet -> Date: Wed, 21 Dec 2011 08:44:27 +0100 -> -> > David, I suggest we add back the garbage collector for current kernels, -> > we'll remove it when route cache really disappear ? -> > -> > I'll send a patch today. -> -> Yes, it's the best idea. -> -> We can actually remove it again as early as when when route neigh's -> are ref-less. - -Here is the patch I successfully tested in the neighbour stress -situation. This is a stable candidate (2.6.39+) - -Thanks ! - -[PATCH] ipv4: reintroduce route cache garbage collector - -Commit 2c8cec5c10b (ipv4: Cache learned PMTU information in inetpeer) -removed IP route cache garbage collector a bit too soon, as this gc was -responsible for expired routes cleanup, releasing their neighbour -reference. - -As pointed out by Robert Gladewitz, recent kernels can fill and exhaust -their neighbour cache. - -Reintroduce the garbage collection, since we'll have to wait our -neighbour lookups become refcount-less to not depend on this stuff. - -Reported-by: Robert Gladewitz -Signed-off-by: Eric Dumazet ---- - net/ipv4/route.c | 107 +++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 107 insertions(+) - -diff --git a/net/ipv4/route.c b/net/ipv4/route.c -index 46af623..252c512 100644 ---- a/net/ipv4/route.c -+++ b/net/ipv4/route.c -@@ -133,6 +134,9 @@ static int ip_rt_min_advmss __read_mostly = 256; - static int rt_chain_length_max __read_mostly = 20; - static int redirect_genid; - -+static struct delayed_work expires_work; -+static unsigned long expires_ljiffies; -+ - /* - * Interface to generic destination cache. - */ -@@ -830,6 +834,97 @@ static int has_noalias(const struct rtable *head, const struct rtable *rth) - return ONE; - } - -+static void rt_check_expire(void) -+{ -+ static unsigned int rover; -+ unsigned int i = rover, goal; -+ struct rtable *rth; -+ struct rtable __rcu **rthp; -+ unsigned long samples = 0; -+ unsigned long sum = 0, sum2 = 0; -+ unsigned long delta; -+ u64 mult; -+ -+ delta = jiffies - expires_ljiffies; -+ expires_ljiffies = jiffies; -+ mult = ((u64)delta) << rt_hash_log; -+ if (ip_rt_gc_timeout > 1) -+ do_div(mult, ip_rt_gc_timeout); -+ goal = (unsigned int)mult; -+ if (goal > rt_hash_mask) -+ goal = rt_hash_mask + 1; -+ for (; goal > 0; goal--) { -+ unsigned long tmo = ip_rt_gc_timeout; -+ unsigned long length; -+ -+ i = (i + 1) & rt_hash_mask; -+ rthp = &rt_hash_table[i].chain; -+ -+ if (need_resched()) -+ cond_resched(); -+ -+ samples++; -+ -+ if (rcu_dereference_raw(*rthp) == NULL) -+ continue; -+ length = 0; -+ spin_lock_bh(rt_hash_lock_addr(i)); -+ while ((rth = rcu_dereference_protected(*rthp, -+ lockdep_is_held(rt_hash_lock_addr(i)))) != NULL) { -+ prefetch(rth->dst.rt_next); -+ if (rt_is_expired(rth)) { -+ *rthp = rth->dst.rt_next; -+ rt_free(rth); -+ continue; -+ } -+ if (rth->dst.expires) { -+ /* Entry is expired even if it is in use */ -+ if (time_before_eq(jiffies, rth->dst.expires)) { -+nofree: -+ tmo >>= 1; -+ rthp = &rth->dst.rt_next; -+ /* -+ * We only count entries on -+ * a chain with equal hash inputs once -+ * so that entries for different QOS -+ * levels, and other non-hash input -+ * attributes don't unfairly skew -+ * the length computation -+ */ -+ length += has_noalias(rt_hash_table[i].chain, rth); -+ continue; -+ } -+ } else if (!rt_may_expire(rth, tmo, ip_rt_gc_timeout)) -+ goto nofree; -+ -+ /* Cleanup aged off entries. */ -+ *rthp = rth->dst.rt_next; -+ rt_free(rth); -+ } -+ spin_unlock_bh(rt_hash_lock_addr(i)); -+ sum += length; -+ sum2 += length*length; -+ } -+ if (samples) { -+ unsigned long avg = sum / samples; -+ unsigned long sd = int_sqrt(sum2 / samples - avg*avg); -+ rt_chain_length_max = max_t(unsigned long, -+ ip_rt_gc_elasticity, -+ (avg + 4*sd) >> FRACT_BITS); -+ } -+ rover = i; -+} -+ -+/* -+ * rt_worker_func() is run in process context. -+ * we call rt_check_expire() to scan part of the hash table -+ */ -+static void rt_worker_func(struct work_struct *work) -+{ -+ rt_check_expire(); -+ schedule_delayed_work(&expires_work, ip_rt_gc_interval); -+} -+ - /* - * Perturbation of rt_genid by a small quantity [1..256] - * Using 8 bits of shuffling ensure we can call rt_cache_invalidate() -@@ -3179,6 +3274,13 @@ static ctl_table ipv4_route_table[] = { - .proc_handler = proc_dointvec_jiffies, - }, - { -+ .procname = "gc_interval", -+ .data = &ip_rt_gc_interval, -+ .maxlen = sizeof(int), -+ .mode = 0644, -+ .proc_handler = proc_dointvec_jiffies, -+ }, -+ { - .procname = "redirect_load", - .data = &ip_rt_redirect_load, - .maxlen = sizeof(int), -@@ -3388,6 +3490,11 @@ int __init ip_rt_init(void) - devinet_init(); - ip_fib_init(); - -+ INIT_DELAYED_WORK_DEFERRABLE(&expires_work, rt_worker_func); -+ expires_ljiffies = jiffies; -+ schedule_delayed_work(&expires_work, -+ net_random() % ip_rt_gc_interval + ip_rt_gc_interval); -+ - if (ip_rt_proc_init()) - printk(KERN_ERR "Unable to create route proc files\n"); - #ifdef CONFIG_XFRM - - --- -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 efd7ae008..2ad581c81 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -13ea1e611a0a580138b8203e6f1353ed patch-3.1.7.bz2 +54fac8e4b0b55201e012ef0337a6cc87 patch-3.1.8.bz2 From 5e426638533530dac74d88490d3a4b4712fb59c4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 10 Jan 2012 14:08:28 -0500 Subject: [PATCH 273/397] Fix ext4 corrupted bitmap error path (pointed out by Eric Sandeen) --- ...-handling-on-inode-bitmap-corruption.patch | 19 +++++++++++++++++++ kernel.spec | 7 +++++++ 2 files changed, 26 insertions(+) create mode 100644 ext4-Fix-error-handling-on-inode-bitmap-corruption.patch diff --git a/ext4-Fix-error-handling-on-inode-bitmap-corruption.patch b/ext4-Fix-error-handling-on-inode-bitmap-corruption.patch new file mode 100644 index 000000000..e22a2b4ff --- /dev/null +++ b/ext4-Fix-error-handling-on-inode-bitmap-corruption.patch @@ -0,0 +1,19 @@ +diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c +index 00beb4f..8fb6844 100644 +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -885,8 +885,12 @@ got: + if (IS_DIRSYNC(inode)) + ext4_handle_sync(handle); + if (insert_inode_locked(inode) < 0) { +- err = -EINVAL; +- goto fail_drop; ++ /* ++ * Likely a bitmap corruption causing inode to be allocated ++ * twice. ++ */ ++ err = -EIO; ++ goto fail; + } + spin_lock(&sbi->s_next_gen_lock); + inode->i_generation = sbi->s_next_generation++; diff --git a/kernel.spec b/kernel.spec index a62c94d79..a4e875f76 100644 --- a/kernel.spec +++ b/kernel.spec @@ -731,6 +731,8 @@ Patch21056: KVM-fix-device-assignment-permissions.patch #rhbz 770233 Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch +Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1356,6 +1358,8 @@ ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch #rhbz 770096 ApplyPatch KVM-fix-device-assignment-permissions.patch +ApplyPatch ext4-Fix-error-handling-on-inode-bitmap-corruption.patch + # END OF PATCH APPLICATIONS %endif @@ -2003,6 +2007,9 @@ fi # and build. %changelog +* Tue Jan 10 2012 Josh Boyer +- Fix ext4 corrupted bitmap error path (pointed out by Eric Sandeen) + * Fri Jan 06 2012 Josh Boyer 2.6.41.8-1 - Linux 3.1.8 From d45e462d4b76a7645e33faa0959008fc604fd446 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 10 Jan 2012 14:25:04 -0500 Subject: [PATCH 274/397] Apply similar bitmap corruption fix for ext3 We still build the ext3 module in F15, so it needs the same fix. --- ...-handling-on-inode-bitmap-corruption.patch | 40 +++++++++++++++++++ kernel.spec | 4 +- 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 ext3-Fix-error-handling-on-inode-bitmap-corruption.patch diff --git a/ext3-Fix-error-handling-on-inode-bitmap-corruption.patch b/ext3-Fix-error-handling-on-inode-bitmap-corruption.patch new file mode 100644 index 000000000..73cc52228 --- /dev/null +++ b/ext3-Fix-error-handling-on-inode-bitmap-corruption.patch @@ -0,0 +1,40 @@ +From 1415dd8705394399d59a3df1ab48d149e1e41e77 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Thu, 8 Dec 2011 21:13:46 +0100 +Subject: [PATCH] ext3: Fix error handling on inode bitmap corruption + +When insert_inode_locked() fails in ext3_new_inode() it most likely +means inode bitmap got corrupted and we allocated again inode which +is already in use. Also doing unlock_new_inode() during error recovery +is wrong since inode does not have I_NEW set. Fix the problem by jumping +to fail: (instead of fail_drop:) which declares filesystem error and +does not call unlock_new_inode(). + +Reviewed-by: Eric Sandeen +Signed-off-by: Jan Kara +--- + fs/ext3/ialloc.c | 8 ++++++-- + 1 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c +index 5c866e0..adae962 100644 +--- a/fs/ext3/ialloc.c ++++ b/fs/ext3/ialloc.c +@@ -525,8 +525,12 @@ got: + if (IS_DIRSYNC(inode)) + handle->h_sync = 1; + if (insert_inode_locked(inode) < 0) { +- err = -EINVAL; +- goto fail_drop; ++ /* ++ * Likely a bitmap corruption causing inode to be allocated ++ * twice. ++ */ ++ err = -EIO; ++ goto fail; + } + spin_lock(&sbi->s_next_gen_lock); + inode->i_generation = sbi->s_next_generation++; +-- +1.7.6.5 + diff --git a/kernel.spec b/kernel.spec index a4e875f76..be3707745 100644 --- a/kernel.spec +++ b/kernel.spec @@ -732,6 +732,7 @@ Patch21056: KVM-fix-device-assignment-permissions.patch Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch +Patch21072: ext3-Fix-error-handling-on-inode-bitmap-corruption.patch %endif @@ -1359,6 +1360,7 @@ ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch ApplyPatch KVM-fix-device-assignment-permissions.patch ApplyPatch ext4-Fix-error-handling-on-inode-bitmap-corruption.patch +ApplyPatch ext3-Fix-error-handling-on-inode-bitmap-corruption.patch # END OF PATCH APPLICATIONS @@ -2008,7 +2010,7 @@ fi %changelog * Tue Jan 10 2012 Josh Boyer -- Fix ext4 corrupted bitmap error path (pointed out by Eric Sandeen) +- Fix ext3/ext4 corrupted bitmap error path (pointed out by Eric Sandeen) * Fri Jan 06 2012 Josh Boyer 2.6.41.8-1 - Linux 3.1.8 From dc54a7e0f4ffa5ef8ef64538a859125d18b1941c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 11 Jan 2012 11:12:31 -0500 Subject: [PATCH 275/397] Patch from Stanislaw Gruszka to fix NULL ptr deref in mac80211 (rhbz 769766) --- kernel.spec | 10 +++- ...y-NULL-ptr-deref-in-promiscuous-mode.patch | 47 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch diff --git a/kernel.spec b/kernel.spec index be3707745..1ed63ff3a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -734,6 +734,9 @@ Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch Patch21072: ext3-Fix-error-handling-on-inode-bitmap-corruption.patch +#rhbz 769766 +Patch21073: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1362,6 +1365,8 @@ ApplyPatch KVM-fix-device-assignment-permissions.patch ApplyPatch ext4-Fix-error-handling-on-inode-bitmap-corruption.patch ApplyPatch ext3-Fix-error-handling-on-inode-bitmap-corruption.patch +ApplyPatch mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch + # END OF PATCH APPLICATIONS %endif @@ -2009,6 +2014,9 @@ fi # and build. %changelog +* Wed Jan 11 2012 Josh Boyer +- Patch from Stanislaw Gruszka to fix NULL ptr deref in mac80211 (rhbz 769766) + * Tue Jan 10 2012 Josh Boyer - Fix ext3/ext4 corrupted bitmap error path (pointed out by Eric Sandeen) diff --git a/mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch b/mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch new file mode 100644 index 000000000..abacee637 --- /dev/null +++ b/mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch @@ -0,0 +1,47 @@ +Since: + +commit 816c04fe7ef01dd9649f5ccfe796474db8708be5 +Author: Christian Lamparter +Date: Sat Apr 30 15:24:30 2011 +0200 + + mac80211: consolidate MIC failure report handling + +is possible to that we dereference rx->key == NULL when driver set +RX_FLAG_MMIC_STRIPPED and not RX_FLAG_IV_STRIPPED and we are in +promiscuous mode. This happen with rt73usb and rt61pci at least. + +Before the commit we always check rx->key against NULL, so I assume +fix should be done in mac80211 (also mic_fail path has similar check). + +References: +https://bugzilla.redhat.com/show_bug.cgi?id=769766 +http://rt2x00.serialmonkey.com/pipermail/users_rt2x00.serialmonkey.com/2012-January/004395.html + +Cc: stable@vger.kernel.org # 3.0+ +Reported-by: Stuart D Gathman +Reported-by: Kai Wohlfahrt +Signed-off-by: Stanislaw Gruszka +--- + net/mac80211/wpa.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c +index 93aab07..422b798 100644 +--- a/net/mac80211/wpa.c ++++ b/net/mac80211/wpa.c +@@ -106,7 +106,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) + if (status->flag & RX_FLAG_MMIC_ERROR) + goto mic_fail; + +- if (!(status->flag & RX_FLAG_IV_STRIPPED)) ++ if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key) + goto update_iv; + + return RX_CONTINUE; +-- +1.7.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file From a7fae8fdfc732e60b35a9e8558b5d837eba2336b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 13 Jan 2012 11:09:52 -0500 Subject: [PATCH 276/397] Fix CVE-2012-0045 (rhbz 773392) and update to Linux 3.1.9 (Fedora 2.6.41.9) --- ...truct-x86_emulate_ops-with-get_cpuid.patch | 78 ++++++++++ ...-missing-checks-in-syscall-emulation.patch | 144 ++++++++++++++++++ kernel.spec | 16 +- sources | 2 +- 4 files changed, 237 insertions(+), 3 deletions(-) create mode 100644 KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch create mode 100644 KVM-x86-fix-missing-checks-in-syscall-emulation.patch diff --git a/KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch b/KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch new file mode 100644 index 000000000..f9dbaa014 --- /dev/null +++ b/KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch @@ -0,0 +1,78 @@ +From 0769c5de24621141c953fbe1f943582d37cb4244 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stephan=20B=C3=A4rwolf?= +Date: Thu, 12 Jan 2012 16:43:03 +0100 +Subject: [PATCH 1/2] KVM: x86: extend "struct x86_emulate_ops" with + "get_cpuid" + +In order to be able to proceed checks on CPU-specific properties +within the emulator, function "get_cpuid" is introduced. +With "get_cpuid" it is possible to virtually call the guests +"cpuid"-opcode without changing the VM's context. + +[mtosatti: cleanup/beautify code] + +Signed-off-by: Stephan Baerwolf +Signed-off-by: Marcelo Tosatti +--- + arch/x86/include/asm/kvm_emulate.h | 3 +++ + arch/x86/kvm/x86.c | 23 +++++++++++++++++++++++ + 2 files changed, 26 insertions(+), 0 deletions(-) + +diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h +index ab4092e..c8b2868 100644 +--- a/arch/x86/include/asm/kvm_emulate.h ++++ b/arch/x86/include/asm/kvm_emulate.h +@@ -190,6 +190,9 @@ struct x86_emulate_ops { + int (*intercept)(struct x86_emulate_ctxt *ctxt, + struct x86_instruction_info *info, + enum x86_intercept_stage stage); ++ ++ bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt, ++ u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); + }; + + typedef u32 __attribute__((vector_size(16))) sse128_t; +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index f0fa3fb..c95ca2d 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -4205,6 +4205,28 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt, + return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage); + } + ++static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt, ++ u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) ++{ ++ struct kvm_cpuid_entry2 *cpuid = NULL; ++ ++ if (eax && ecx) ++ cpuid = kvm_find_cpuid_entry(emul_to_vcpu(ctxt), ++ *eax, *ecx); ++ ++ if (cpuid) { ++ *eax = cpuid->eax; ++ *ecx = cpuid->ecx; ++ if (ebx) ++ *ebx = cpuid->ebx; ++ if (edx) ++ *edx = cpuid->edx; ++ return true; ++ } ++ ++ return false; ++} ++ + static struct x86_emulate_ops emulate_ops = { + .read_std = kvm_read_guest_virt_system, + .write_std = kvm_write_guest_virt_system, +@@ -4236,6 +4258,7 @@ static struct x86_emulate_ops emulate_ops = { + .get_fpu = emulator_get_fpu, + .put_fpu = emulator_put_fpu, + .intercept = emulator_intercept, ++ .get_cpuid = emulator_get_cpuid, + }; + + static void cache_all_regs(struct kvm_vcpu *vcpu) +-- +1.7.7.5 + diff --git a/KVM-x86-fix-missing-checks-in-syscall-emulation.patch b/KVM-x86-fix-missing-checks-in-syscall-emulation.patch new file mode 100644 index 000000000..933a13431 --- /dev/null +++ b/KVM-x86-fix-missing-checks-in-syscall-emulation.patch @@ -0,0 +1,144 @@ +From e28ba7bb020f07193bc000453c8775e9d2c0dda7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stephan=20B=C3=A4rwolf?= +Date: Thu, 12 Jan 2012 16:43:04 +0100 +Subject: [PATCH 2/2] KVM: x86: fix missing checks in syscall emulation + +On hosts without this patch, 32bit guests will crash (and 64bit guests +may behave in a wrong way) for example by simply executing following +nasm-demo-application: + + [bits 32] + global _start + SECTION .text + _start: syscall + +(I tested it with winxp and linux - both always crashed) + + Disassembly of section .text: + + 00000000 <_start>: + 0: 0f 05 syscall + +The reason seems a missing "invalid opcode"-trap (int6) for the +syscall opcode "0f05", which is not available on Intel CPUs +within non-longmodes, as also on some AMD CPUs within legacy-mode. +(depending on CPU vendor, MSR_EFER and cpuid) + +Because previous mentioned OSs may not engage corresponding +syscall target-registers (STAR, LSTAR, CSTAR), they remain +NULL and (non trapping) syscalls are leading to multiple +faults and finally crashs. + +Depending on the architecture (AMD or Intel) pretended by +guests, various checks according to vendor's documentation +are implemented to overcome the current issue and behave +like the CPUs physical counterparts. + +[mtosatti: cleanup/beautify code] + +Signed-off-by: Stephan Baerwolf +Signed-off-by: Marcelo Tosatti +--- + arch/x86/include/asm/kvm_emulate.h | 13 +++++++++ + arch/x86/kvm/emulate.c | 51 ++++++++++++++++++++++++++++++++++++ + 2 files changed, 64 insertions(+), 0 deletions(-) + +diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h +index c8b2868..7b9cfc4 100644 +--- a/arch/x86/include/asm/kvm_emulate.h ++++ b/arch/x86/include/asm/kvm_emulate.h +@@ -301,6 +301,19 @@ struct x86_emulate_ctxt { + #define X86EMUL_MODE_PROT (X86EMUL_MODE_PROT16|X86EMUL_MODE_PROT32| \ + X86EMUL_MODE_PROT64) + ++/* CPUID vendors */ ++#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx 0x68747541 ++#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx 0x444d4163 ++#define X86EMUL_CPUID_VENDOR_AuthenticAMD_edx 0x69746e65 ++ ++#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx 0x69444d41 ++#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx 0x21726574 ++#define X86EMUL_CPUID_VENDOR_AMDisbetterI_edx 0x74656273 ++ ++#define X86EMUL_CPUID_VENDOR_GenuineIntel_ebx 0x756e6547 ++#define X86EMUL_CPUID_VENDOR_GenuineIntel_ecx 0x6c65746e ++#define X86EMUL_CPUID_VENDOR_GenuineIntel_edx 0x49656e69 ++ + enum x86_intercept_stage { + X86_ICTP_NONE = 0, /* Allow zero-init to not match anything */ + X86_ICPT_PRE_EXCEPT, +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index 05a562b..0982507 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -1891,6 +1891,51 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt, + ss->p = 1; + } + ++static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt) ++{ ++ struct x86_emulate_ops *ops = ctxt->ops; ++ u32 eax, ebx, ecx, edx; ++ ++ /* ++ * syscall should always be enabled in longmode - so only become ++ * vendor specific (cpuid) if other modes are active... ++ */ ++ if (ctxt->mode == X86EMUL_MODE_PROT64) ++ return true; ++ ++ eax = 0x00000000; ++ ecx = 0x00000000; ++ if (ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)) { ++ /* ++ * Intel ("GenuineIntel") ++ * remark: Intel CPUs only support "syscall" in 64bit ++ * longmode. Also an 64bit guest with a ++ * 32bit compat-app running will #UD !! While this ++ * behaviour can be fixed (by emulating) into AMD ++ * response - CPUs of AMD can't behave like Intel. ++ */ ++ if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx && ++ ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx && ++ edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx) ++ return false; ++ ++ /* AMD ("AuthenticAMD") */ ++ if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx && ++ ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx && ++ edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx) ++ return true; ++ ++ /* AMD ("AMDisbetter!") */ ++ if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx && ++ ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx && ++ edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx) ++ return true; ++ } ++ ++ /* default: (not Intel, not AMD), apply Intel's stricter rules... */ ++ return false; ++} ++ + static int em_syscall(struct x86_emulate_ctxt *ctxt) + { + struct x86_emulate_ops *ops = ctxt->ops; +@@ -1904,9 +1949,15 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt) + ctxt->mode == X86EMUL_MODE_VM86) + return emulate_ud(ctxt); + ++ if (!(em_syscall_is_enabled(ctxt))) ++ return emulate_ud(ctxt); ++ + ops->get_msr(ctxt, MSR_EFER, &efer); + setup_syscalls_segments(ctxt, &cs, &ss); + ++ if (!(efer & EFER_SCE)) ++ return emulate_ud(ctxt); ++ + ops->get_msr(ctxt, MSR_STAR, &msr_data); + msr_data >>= 32; + cs_sel = (u16)(msr_data & 0xfffc); +-- +1.7.7.5 + diff --git a/kernel.spec b/kernel.spec index 1ed63ff3a..ce78f427e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # Do we have a -stable update to apply? -%define stable_update 8 +%define stable_update 9 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -737,6 +737,10 @@ Patch21072: ext3-Fix-error-handling-on-inode-bitmap-corruption.patch #rhbz 769766 Patch21073: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch +#rhbz 773392 +Patch21074: KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch +Patch21075: KVM-x86-fix-missing-checks-in-syscall-emulation.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1367,6 +1371,10 @@ ApplyPatch ext3-Fix-error-handling-on-inode-bitmap-corruption.patch ApplyPatch mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch +#rhbz 773392 +ApplyPatch KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch +ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch + # END OF PATCH APPLICATIONS %endif @@ -2014,6 +2022,10 @@ fi # and build. %changelog +* Fri Jan 13 2012 Josh Boyer 2.6.41.9-1 +- Linux 3.1.9 +- CVE-2012-0045 kvm: syscall instruction induced guest panic (rhbz 773392) + * Wed Jan 11 2012 Josh Boyer - Patch from Stanislaw Gruszka to fix NULL ptr deref in mac80211 (rhbz 769766) diff --git a/sources b/sources index 2ad581c81..7bd2ca37c 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -54fac8e4b0b55201e012ef0337a6cc87 patch-3.1.8.bz2 +fae6176f187628bcc5b330cdadc60f9e patch-3.1.9.bz2 From 63af6b006b334fe0494489460874df2c6aada19a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 13 Jan 2012 11:53:59 -0500 Subject: [PATCH 277/397] Fix verbose logging messages in the rtl8192cu driver (rhbz 728740) --- kernel.spec | 11 +- rtl8192cu-Fix-WARNING-on-suspend-resume.patch | 177 ++++++++++++++++++ 2 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 rtl8192cu-Fix-WARNING-on-suspend-resume.patch diff --git a/kernel.spec b/kernel.spec index ce78f427e..cfd4cc8eb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -741,6 +741,9 @@ Patch21073: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch Patch21074: KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch Patch21075: KVM-x86-fix-missing-checks-in-syscall-emulation.patch +#rhbz 728740 +Patch21076: rtl8192cu-Fix-WARNING-on-suspend-resume.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1375,6 +1378,9 @@ ApplyPatch mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch ApplyPatch KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch +#rhbz 728740 +ApplyPatch rtl8192cu-Fix-WARNING-on-suspend-resume.patch + # END OF PATCH APPLICATIONS %endif @@ -2022,6 +2028,9 @@ fi # and build. %changelog +* Fri Jan 13 2012 Josh Boyer +- Fix verbose logging messages in the rtl8192cu driver (rhbz 728740) + * Fri Jan 13 2012 Josh Boyer 2.6.41.9-1 - Linux 3.1.9 - CVE-2012-0045 kvm: syscall instruction induced guest panic (rhbz 773392) diff --git a/rtl8192cu-Fix-WARNING-on-suspend-resume.patch b/rtl8192cu-Fix-WARNING-on-suspend-resume.patch new file mode 100644 index 000000000..e784b1632 --- /dev/null +++ b/rtl8192cu-Fix-WARNING-on-suspend-resume.patch @@ -0,0 +1,177 @@ +From e234ca17f2d5ce23606fceef2df6c02f8555547e Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Wed, 11 Jan 2012 13:35:33 -0500 +Subject: [PATCH] rtl8192cu: Fix WARNING on suspend/resume + +A recent LKML thread (http://lkml.indiana.edu/hypermail/linux/kernel/1112.3/00965.html) +discusses warnings that occur during a suspend/resume cycle. The driver +attempts to read the firmware file before userspace is ready, leading to the +following warning: + +WARNING: at drivers/base/firmware_class.c:537 _request_firmware+0x3f6/0x420() + +For rtl8192cu, the problem is fixed by storing the firmware in a global buffer +rather than one allocated per device. The usage count is increased when +suspending and decreased when resuming. This way, the firmware is retained +through a suspend/resume cycle, and does not have to be reread. + +This patch should fix the bug reported in +https://bugzilla.redhat.com/show_bug.cgi?id=771002. + +Note: This patch also touches rtl8192ce as the "firmware" loaded message +is now printed in the wrong place. + +Reported-by: Mohammed Arafa +Reported-by: Dave Jones +Signed-off-by: Larry Finger +Cc: Linus Torvalds +Cc: Stable + +Backported to Fedora 3.1.x. +--- + drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 1 - + drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 1 + + drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 58 +++++++++++++++++---- + 3 files changed, 49 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +index 49a064b..e3c4ac7 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +@@ -226,7 +226,6 @@ int rtl92c_download_fw(struct ieee80211_hw *hw) + u32 fwsize; + enum version_8192c version = rtlhal->version; + +- pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); + if (!rtlhal->pfirmware) + return 1; + +diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +index 373dc78..9c3a8f1 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +@@ -171,6 +171,7 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) + memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); + rtlpriv->rtlhal.fwsize = firmware->size; + release_firmware(firmware); ++ pr_info("rtl8192ce: Loaded firmware file %s\n", rtlpriv->cfg->fw_name); + + return 0; + } +diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +index ef63c0d..f4230dd 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +@@ -42,6 +42,9 @@ + #include "led.h" + #include "hw.h" + #include ++#include ++#include ++ + + MODULE_AUTHOR("Georgia "); + MODULE_AUTHOR("Ziv Huang "); +@@ -50,6 +53,10 @@ MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); + MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); + ++static char *rtl8192cu_firmware; /* pointer to firmware */ ++static int firmware_size; ++static atomic_t usage_count; ++ + static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) + { + struct rtl_priv *rtlpriv = rtl_priv(hw); +@@ -60,12 +67,21 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) + rtlpriv->dm.dm_flag = 0; + rtlpriv->dm.disable_framebursting = 0; + rtlpriv->dm.thermalvalue = 0; +- rtlpriv->rtlhal.pfirmware = vmalloc(0x4000); +- if (!rtlpriv->rtlhal.pfirmware) { ++ ++ if (rtl8192cu_firmware) { ++ /* firmware already loaded - true for suspend/resume ++ * and multiple instances of the device */ ++ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware; ++ rtlpriv->rtlhal.fwsize = firmware_size; ++ return 0; ++ } ++ rtl8192cu_firmware = vzalloc(0x4000); ++ if (!rtl8192cu_firmware) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Can't alloc buffer for fw.\n")); + return 1; + } ++ + /* request fw */ + err = request_firmware(&firmware, rtlpriv->cfg->fw_name, + rtlpriv->io.dev); +@@ -80,9 +96,14 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) + release_firmware(firmware); + return 1; + } +- memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); ++ pr_info("rtl8192cu: Loaded firmware from file %s\n", ++ rtlpriv->cfg->fw_name); ++ memcpy(rtl8192cu_firmware, firmware->data, firmware->size); ++ firmware_size = firmware->size; + rtlpriv->rtlhal.fwsize = firmware->size; ++ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware; + release_firmware(firmware); ++ atomic_inc(&usage_count); + + return 0; + } +@@ -91,12 +112,30 @@ static void rtl92cu_deinit_sw_vars(struct ieee80211_hw *hw) + { + struct rtl_priv *rtlpriv = rtl_priv(hw); + +- if (rtlpriv->rtlhal.pfirmware) { +- vfree(rtlpriv->rtlhal.pfirmware); ++ atomic_dec(&usage_count); ++ if (!atomic_read(&usage_count) && rtlpriv->rtlhal.pfirmware) { ++ vfree(rtl8192cu_firmware); ++ rtl8192cu_firmware = NULL; + rtlpriv->rtlhal.pfirmware = NULL; + } + } + ++#ifdef CONFIG_PM_SLEEP ++static int rtl8192cu_usb_suspend(struct usb_interface *pusb_intf, ++ pm_message_t message) ++{ ++ /* Increase usage_count to Save loaded fw across suspend/resume */ ++ atomic_inc(&usage_count); ++ return 0; ++} ++ ++static int rtl8192cu_usb_resume(struct usb_interface *pusb_intf) ++{ ++ atomic_dec(&usage_count); /* after resume, decrease usage count */ ++ return 0; ++} ++#endif ++ + static struct rtl_hal_ops rtl8192cu_hal_ops = { + .init_sw_vars = rtl92cu_init_sw_vars, + .deinit_sw_vars = rtl92cu_deinit_sw_vars, +@@ -338,11 +377,10 @@ static struct usb_driver rtl8192cu_driver = { + .disconnect = rtl_usb_disconnect, + .id_table = rtl8192c_usb_ids, + +-#ifdef CONFIG_PM +- /* .suspend = rtl_usb_suspend, */ +- /* .resume = rtl_usb_resume, */ +- /* .reset_resume = rtl8192c_resume, */ +-#endif /* CONFIG_PM */ ++#ifdef CONFIG_PM_SLEEP ++ .suspend = rtl8192cu_usb_suspend, ++ .resume = rtl8192cu_usb_resume, ++#endif /* CONFIG_PM_SLEEP */ + #ifdef CONFIG_AUTOSUSPEND + .supports_autosuspend = 1, + #endif +-- +1.7.7.5 + From aebb47b0eeff28ade22d42e7824d582c0bd6fd9a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sun, 15 Jan 2012 15:48:57 -0500 Subject: [PATCH 278/397] Avoid packaging symlinks for kernel-doc files (rhbz 767351) --- kernel.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index cfd4cc8eb..2fdc0c137 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -1760,7 +1760,7 @@ man9dir=$RPM_BUILD_ROOT%{_datadir}/man/man9 # copy the source over mkdir -p $docdir -tar -f - --exclude=man --exclude='.*' -c Documentation | tar xf - -C $docdir +tar -h -f - --exclude=man --exclude='.*' -c Documentation | tar xf - -C $docdir # Install man pages for the kernel API. mkdir -p $man9dir @@ -2028,6 +2028,9 @@ fi # and build. %changelog +* Sun Jan 15 2012 Josh Boyer +- Avoid packaging symlinks for kernel-doc files (rhbz 767351) + * Fri Jan 13 2012 Josh Boyer - Fix verbose logging messages in the rtl8192cu driver (rhbz 728740) From 94aa5a9c602cf858122577453a596b5fc4d80717 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 17 Jan 2012 15:30:50 -0500 Subject: [PATCH 279/397] CVE-2011-4127 possible privilege escalation via SG_IO ioctl (rhbz 769911) --- 01-block-add-and-use-scsi_blk_cmd_ioctl.patch | 166 ++++++++++++++++++ ...passthrough-ioctls-on-partition-devs.patch | 165 +++++++++++++++++ ...wd-ioctls-from-LVs-to-underlying-dev.patch | 91 ++++++++++ kernel.spec | 15 +- 4 files changed, 436 insertions(+), 1 deletion(-) create mode 100644 01-block-add-and-use-scsi_blk_cmd_ioctl.patch create mode 100644 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch create mode 100644 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch diff --git a/01-block-add-and-use-scsi_blk_cmd_ioctl.patch b/01-block-add-and-use-scsi_blk_cmd_ioctl.patch new file mode 100644 index 000000000..fdf4c5039 --- /dev/null +++ b/01-block-add-and-use-scsi_blk_cmd_ioctl.patch @@ -0,0 +1,166 @@ +From 6051b3759d3d4b70d33a7be70ab6b86ed3559224 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 16 Jan 2012 17:12:58 +0100 +Subject: [PATCH 1/3] block: add and use scsi_blk_cmd_ioctl + +Introduce a wrapper around scsi_cmd_ioctl that takes a block device. + +The function will then be enhanced to detect partition block devices +and, in that case, subject the ioctls to whitelisting. + +[ Cherry picked from 6ad62f051ef784a48a6103af289f91b5c472e955 ] + +Cc: stable@kernel.org +Cc: linux-scsi@vger.kernel.org +Cc: Jens Axboe +Cc: James Bottomley +Signed-off-by: Paolo Bonzini +Signed-off-by: Linus Torvalds +--- + block/scsi_ioctl.c | 7 +++++++ + drivers/block/cciss.c | 6 +++--- + drivers/block/ub.c | 3 +-- + drivers/block/virtio_blk.c | 4 ++-- + drivers/cdrom/cdrom.c | 3 +-- + drivers/ide/ide-floppy_ioctl.c | 3 +-- + drivers/scsi/sd.c | 2 +- + include/linux/blkdev.h | 2 ++ + 8 files changed, 18 insertions(+), 12 deletions(-) + +diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c +index 4f4230b..57ac937 100644 +--- a/block/scsi_ioctl.c ++++ b/block/scsi_ioctl.c +@@ -691,6 +691,13 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod + } + EXPORT_SYMBOL(scsi_cmd_ioctl); + ++int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode, ++ unsigned int cmd, void __user *arg) ++{ ++ return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg); ++} ++EXPORT_SYMBOL(scsi_cmd_blk_ioctl); ++ + static int __init blk_scsi_ioctl_init(void) + { + blk_set_cmd_filter_defaults(&blk_default_cmd_filter); +diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c +index c2f9b3e..1dab802 100644 +--- a/drivers/block/cciss.c ++++ b/drivers/block/cciss.c +@@ -1716,7 +1716,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, + case CCISS_BIG_PASSTHRU: + return cciss_bigpassthru(h, argp); + +- /* scsi_cmd_ioctl handles these, below, though some are not */ ++ /* scsi_cmd_blk_ioctl handles these, below, though some are not */ + /* very meaningful for cciss. SG_IO is the main one people want. */ + + case SG_GET_VERSION_NUM: +@@ -1727,9 +1727,9 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, + case SG_EMULATED_HOST: + case SG_IO: + case SCSI_IOCTL_SEND_COMMAND: +- return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp); ++ return scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); + +- /* scsi_cmd_ioctl would normally handle these, below, but */ ++ /* scsi_cmd_blk_ioctl would normally handle these, below, but */ + /* they aren't a good fit for cciss, as CD-ROMs are */ + /* not supported, and we don't have any bus/target/lun */ + /* which we present to the kernel. */ +diff --git a/drivers/block/ub.c b/drivers/block/ub.c +index 0e376d4..7333b9e 100644 +--- a/drivers/block/ub.c ++++ b/drivers/block/ub.c +@@ -1744,12 +1744,11 @@ static int ub_bd_release(struct gendisk *disk, fmode_t mode) + static int ub_bd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) + { +- struct gendisk *disk = bdev->bd_disk; + void __user *usermem = (void __user *) arg; + int ret; + + mutex_lock(&ub_mutex); +- ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem); ++ ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, usermem); + mutex_unlock(&ub_mutex); + + return ret; +diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c +index 079c088..5d7a934 100644 +--- a/drivers/block/virtio_blk.c ++++ b/drivers/block/virtio_blk.c +@@ -236,8 +236,8 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, + if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI)) + return -ENOTTY; + +- return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, +- (void __user *)data); ++ return scsi_cmd_blk_ioctl(bdev, mode, cmd, ++ (void __user *)data); + } + + /* We provide getgeo only to please some old bootloader/partitioning tools */ +diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c +index f997c27..cedb231 100644 +--- a/drivers/cdrom/cdrom.c ++++ b/drivers/cdrom/cdrom.c +@@ -2747,12 +2747,11 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev, + { + void __user *argp = (void __user *)arg; + int ret; +- struct gendisk *disk = bdev->bd_disk; + + /* + * Try the generic SCSI command ioctl's first. + */ +- ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp); ++ ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); + if (ret != -ENOTTY) + return ret; + +diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c +index d267b7a..a22ca84 100644 +--- a/drivers/ide/ide-floppy_ioctl.c ++++ b/drivers/ide/ide-floppy_ioctl.c +@@ -292,8 +292,7 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev, + * and CDROM_SEND_PACKET (legacy) ioctls + */ + if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND) +- err = scsi_cmd_ioctl(bdev->bd_disk->queue, bdev->bd_disk, +- mode, cmd, argp); ++ err = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); + + if (err == -ENOTTY) + err = generic_ide_ioctl(drive, bdev, cmd, arg); +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index 953773c..c88885d 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -1095,7 +1095,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, + error = scsi_ioctl(sdp, cmd, p); + break; + default: +- error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p); ++ error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p); + if (error != -ENOTTY) + break; + error = scsi_ioctl(sdp, cmd, p); +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index 5e30b45..aa829a4 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -675,6 +675,8 @@ extern int blk_insert_cloned_request(struct request_queue *q, + struct request *rq); + extern void blk_delay_queue(struct request_queue *, unsigned long); + extern void blk_recount_segments(struct request_queue *, struct bio *); ++extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t, ++ unsigned int, void __user *); + extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t, + unsigned int, void __user *); + extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t, +-- +1.7.7.5 + diff --git a/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch b/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch new file mode 100644 index 000000000..942e2a007 --- /dev/null +++ b/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch @@ -0,0 +1,165 @@ +From e773daff833c61e0ce22d62b7d1bb7b82f4222d0 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 16 Jan 2012 17:12:59 +0100 +Subject: [PATCH 2/3] block: fail SCSI passthrough ioctls on partition devices + +Linux allows executing the SG_IO ioctl on a partition or LVM volume, and +will pass the command to the underlying block device. This is +well-known, but it is also a large security problem when (via Unix +permissions, ACLs, SELinux or a combination thereof) a program or user +needs to be granted access only to part of the disk. + +This patch lets partitions forward a small set of harmless ioctls; +others are logged with printk so that we can see which ioctls are +actually sent. In my tests only CDROM_GET_CAPABILITY actually occurred. +Of course it was being sent to a (partition on a) hard disk, so it would +have failed with ENOTTY and the patch isn't changing anything in +practice. Still, I'm treating it specially to avoid spamming the logs. + +In principle, this restriction should include programs running with +CAP_SYS_RAWIO. If for example I let a program access /dev/sda2 and +/dev/sdb, it still should not be able to read/write outside the +boundaries of /dev/sda2 independent of the capabilities. However, for +now programs with CAP_SYS_RAWIO will still be allowed to send the +ioctls. Their actions will still be logged. + +This patch does not affect the non-libata IDE driver. That driver +however already tests for bd != bd->bd_contains before issuing some +ioctl; it could be restricted further to forbid these ioctls even for +programs running with CAP_SYS_ADMIN/CAP_SYS_RAWIO. + +[ Cherry picked from 3ed4e7ba4be8c72051d87dcb2dec279d97a18d41 + + Changes with respect to 3.3: return -ENOTTY from scsi_verify_blk_ioctl + and -ENOIOCTLCMD from sd_compat_ioctl. ] + +Cc: stable@kernel.org +Cc: linux-scsi@vger.kernel.org +Cc: Jens Axboe +Cc: James Bottomley +Signed-off-by: Paolo Bonzini +[ Make it also print the command name when warning - Linus ] +Signed-off-by: Linus Torvalds +--- + block/scsi_ioctl.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ + drivers/scsi/sd.c | 11 +++++++++-- + include/linux/blkdev.h | 1 + + 3 files changed, 55 insertions(+), 2 deletions(-) + +diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c +index 57ac937..5ef1f4c 100644 +--- a/block/scsi_ioctl.c ++++ b/block/scsi_ioctl.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -691,9 +692,53 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod + } + EXPORT_SYMBOL(scsi_cmd_ioctl); + ++int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd) ++{ ++ if (bd && bd == bd->bd_contains) ++ return 0; ++ ++ /* Actually none of these is particularly useful on a partition, ++ * but they are safe. ++ */ ++ switch (cmd) { ++ case SCSI_IOCTL_GET_IDLUN: ++ case SCSI_IOCTL_GET_BUS_NUMBER: ++ case SCSI_IOCTL_GET_PCI: ++ case SCSI_IOCTL_PROBE_HOST: ++ case SG_GET_VERSION_NUM: ++ case SG_SET_TIMEOUT: ++ case SG_GET_TIMEOUT: ++ case SG_GET_RESERVED_SIZE: ++ case SG_SET_RESERVED_SIZE: ++ case SG_EMULATED_HOST: ++ return 0; ++ case CDROM_GET_CAPABILITY: ++ /* Keep this until we remove the printk below. udev sends it ++ * and we do not want to spam dmesg about it. CD-ROMs do ++ * not have partitions, so we get here only for disks. ++ */ ++ return -ENOTTY; ++ default: ++ break; ++ } ++ ++ /* In particular, rule out all resets and host-specific ioctls. */ ++ printk_ratelimited(KERN_WARNING ++ "%s: sending ioctl %x to a partition!\n", current->comm, cmd); ++ ++ return capable(CAP_SYS_RAWIO) ? 0 : -ENOTTY; ++} ++EXPORT_SYMBOL(scsi_verify_blk_ioctl); ++ + int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode, + unsigned int cmd, void __user *arg) + { ++ int ret; ++ ++ ret = scsi_verify_blk_ioctl(bd, cmd); ++ if (ret < 0) ++ return ret; ++ + return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg); + } + EXPORT_SYMBOL(scsi_cmd_blk_ioctl); +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index c88885d..7d8b5d8 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -1073,6 +1073,10 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, + SCSI_LOG_IOCTL(1, printk("sd_ioctl: disk=%s, cmd=0x%x\n", + disk->disk_name, cmd)); + ++ error = scsi_verify_blk_ioctl(bdev, cmd); ++ if (error < 0) ++ return error; ++ + /* + * If we are in the middle of error recovery, don't let anyone + * else try and use this device. Also, if error recovery fails, it +@@ -1265,6 +1269,11 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) + { + struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device; ++ int ret; ++ ++ ret = scsi_verify_blk_ioctl(bdev, cmd); ++ if (ret < 0) ++ return -ENOIOCTLCMD; + + /* + * If we are in the middle of error recovery, don't let anyone +@@ -1276,8 +1285,6 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, + return -ENODEV; + + if (sdev->host->hostt->compat_ioctl) { +- int ret; +- + ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg); + + return ret; +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index aa829a4..8b7a19e 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -675,6 +675,7 @@ extern int blk_insert_cloned_request(struct request_queue *q, + struct request *rq); + extern void blk_delay_queue(struct request_queue *, unsigned long); + extern void blk_recount_segments(struct request_queue *, struct bio *); ++extern int scsi_verify_blk_ioctl(struct block_device *, unsigned int); + extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t, + unsigned int, void __user *); + extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t, +-- +1.7.7.5 + diff --git a/03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch b/03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch new file mode 100644 index 000000000..129edd974 --- /dev/null +++ b/03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch @@ -0,0 +1,91 @@ +From bf50a5715cac3b85f3bd33f184f7c031debabe0b Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 16 Jan 2012 17:13:00 +0100 +Subject: [PATCH 3/3] dm: do not forward ioctls from logical volumes to the + underlying device + +A logical volume can map to just part of underlying physical volume. +In this case, it must be treated like a partition. + +Based on a patch from Alasdair G Kergon. + +[ Cherry picked from 95113a17a2a1eb06151dc698dca9bcc4a29e4fbb ] + +Cc: stable@kernel.org +Cc: Alasdair G Kergon +Cc: dm-devel@redhat.com +Cc: linux-scsi@vger.kernel.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Linus Torvalds +--- + drivers/md/dm-flakey.c | 11 ++++++++++- + drivers/md/dm-linear.c | 12 +++++++++++- + drivers/md/dm-mpath.c | 6 ++++++ + 3 files changed, 27 insertions(+), 2 deletions(-) + +diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c +index f84c080..9fb18c1 100644 +--- a/drivers/md/dm-flakey.c ++++ b/drivers/md/dm-flakey.c +@@ -368,8 +368,17 @@ static int flakey_status(struct dm_target *ti, status_type_t type, + static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg) + { + struct flakey_c *fc = ti->private; ++ struct dm_dev *dev = fc->dev; ++ int r = 0; + +- return __blkdev_driver_ioctl(fc->dev->bdev, fc->dev->mode, cmd, arg); ++ /* ++ * Only pass ioctls through if the device sizes match exactly. ++ */ ++ if (fc->start || ++ ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) ++ r = scsi_verify_blk_ioctl(NULL, cmd); ++ ++ return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg); + } + + static int flakey_merge(struct dm_target *ti, struct bvec_merge_data *bvm, +diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c +index 3921e3b..9728839 100644 +--- a/drivers/md/dm-linear.c ++++ b/drivers/md/dm-linear.c +@@ -116,7 +116,17 @@ static int linear_ioctl(struct dm_target *ti, unsigned int cmd, + unsigned long arg) + { + struct linear_c *lc = (struct linear_c *) ti->private; +- return __blkdev_driver_ioctl(lc->dev->bdev, lc->dev->mode, cmd, arg); ++ struct dm_dev *dev = lc->dev; ++ int r = 0; ++ ++ /* ++ * Only pass ioctls through if the device sizes match exactly. ++ */ ++ if (lc->start || ++ ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) ++ r = scsi_verify_blk_ioctl(NULL, cmd); ++ ++ return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg); + } + + static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm, +diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c +index 5e0090e..801d92d 100644 +--- a/drivers/md/dm-mpath.c ++++ b/drivers/md/dm-mpath.c +@@ -1520,6 +1520,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, + + spin_unlock_irqrestore(&m->lock, flags); + ++ /* ++ * Only pass ioctls through if the device sizes match exactly. ++ */ ++ if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) ++ r = scsi_verify_blk_ioctl(NULL, cmd); ++ + return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); + } + +-- +1.7.7.5 + diff --git a/kernel.spec b/kernel.spec index 2fdc0c137..617fb1815 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -744,6 +744,11 @@ Patch21075: KVM-x86-fix-missing-checks-in-syscall-emulation.patch #rhbz 728740 Patch21076: rtl8192cu-Fix-WARNING-on-suspend-resume.patch +Patch21077: 01-block-add-and-use-scsi_blk_cmd_ioctl.patch +Patch21078: 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch +Patch21079: 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch + + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1381,6 +1386,11 @@ ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch #rhbz 728740 ApplyPatch rtl8192cu-Fix-WARNING-on-suspend-resume.patch +#rhbz 769911 +ApplyPatch 01-block-add-and-use-scsi_blk_cmd_ioctl.patch +ApplyPatch 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch +ApplyPatch 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch + # END OF PATCH APPLICATIONS %endif @@ -2028,6 +2038,9 @@ fi # and build. %changelog +* Tue Jan 17 2012 Josh Boyer +- CVE-2011-4127 possible privilege escalation via SG_IO ioctl (rhbz 769911) + * Sun Jan 15 2012 Josh Boyer - Avoid packaging symlinks for kernel-doc files (rhbz 767351) From 304903f42df1235d78c4f04265de3a1fc5026f31 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 18 Jan 2012 10:08:53 -0500 Subject: [PATCH 280/397] CVE-2012-0056 proc: clean up and fix /proc//mem (rhbz 782681) --- kernel.spec | 9 + ...ean-up-and-fix-proc-pid-mem-handling.patch | 268 ++++++++++++++++++ 2 files changed, 277 insertions(+) create mode 100644 proc-clean-up-and-fix-proc-pid-mem-handling.patch diff --git a/kernel.spec b/kernel.spec index 617fb1815..3e1be7bb5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -748,6 +748,9 @@ Patch21077: 01-block-add-and-use-scsi_blk_cmd_ioctl.patch Patch21078: 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch Patch21079: 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch +#rhbz 782681 +Patch21085: proc-clean-up-and-fix-proc-pid-mem-handling.patch + %endif @@ -1391,6 +1394,9 @@ ApplyPatch 01-block-add-and-use-scsi_blk_cmd_ioctl.patch ApplyPatch 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch ApplyPatch 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch +#rhbz 782681 +ApplyPatch proc-clean-up-and-fix-proc-pid-mem-handling.patch + # END OF PATCH APPLICATIONS %endif @@ -2038,6 +2044,9 @@ fi # and build. %changelog +* Wed Jan 18 2012 Josh Boyer +- CVE-2012-0056 proc: clean up and fix /proc//mem (rhbz 782681) + * Tue Jan 17 2012 Josh Boyer - CVE-2011-4127 possible privilege escalation via SG_IO ioctl (rhbz 769911) diff --git a/proc-clean-up-and-fix-proc-pid-mem-handling.patch b/proc-clean-up-and-fix-proc-pid-mem-handling.patch new file mode 100644 index 000000000..c793475d2 --- /dev/null +++ b/proc-clean-up-and-fix-proc-pid-mem-handling.patch @@ -0,0 +1,268 @@ +From e268337dfe26dfc7efd422a804dbb27977a3cccc Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Tue, 17 Jan 2012 15:21:19 -0800 +Subject: [PATCH] proc: clean up and fix /proc//mem handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Jüri Aedla reported that the /proc//mem handling really isn't very +robust, and it also doesn't match the permission checking of any of the +other related files. + +This changes it to do the permission checks at open time, and instead of +tracking the process, it tracks the VM at the time of the open. That +simplifies the code a lot, but does mean that if you hold the file +descriptor open over an execve(), you'll continue to read from the _old_ +VM. + +That is different from our previous behavior, but much simpler. If +somebody actually finds a load where this matters, we'll need to revert +this commit. + +I suspect that nobody will ever notice - because the process mapping +addresses will also have changed as part of the execve. So you cannot +actually usefully access the fd across a VM change simply because all +the offsets for IO would have changed too. + +Reported-by: Jüri Aedla +Cc: Al Viro +Signed-off-by: Linus Torvalds +--- + fs/proc/base.c | 145 +++++++++++++++----------------------------------------- + 1 files changed, 39 insertions(+), 106 deletions(-) + +diff --git a/fs/proc/base.c b/fs/proc/base.c +index 5485a53..662ddf2 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -198,65 +198,7 @@ static int proc_root_link(struct dentry *dentry, struct path *path) + return result; + } + +-static struct mm_struct *__check_mem_permission(struct task_struct *task) +-{ +- struct mm_struct *mm; +- +- mm = get_task_mm(task); +- if (!mm) +- return ERR_PTR(-EINVAL); +- +- /* +- * A task can always look at itself, in case it chooses +- * to use system calls instead of load instructions. +- */ +- if (task == current) +- return mm; +- +- /* +- * If current is actively ptrace'ing, and would also be +- * permitted to freshly attach with ptrace now, permit it. +- */ +- if (task_is_stopped_or_traced(task)) { +- int match; +- rcu_read_lock(); +- match = (ptrace_parent(task) == current); +- rcu_read_unlock(); +- if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH)) +- return mm; +- } +- +- /* +- * No one else is allowed. +- */ +- mmput(mm); +- return ERR_PTR(-EPERM); +-} +- +-/* +- * If current may access user memory in @task return a reference to the +- * corresponding mm, otherwise ERR_PTR. +- */ +-static struct mm_struct *check_mem_permission(struct task_struct *task) +-{ +- struct mm_struct *mm; +- int err; +- +- /* +- * Avoid racing if task exec's as we might get a new mm but validate +- * against old credentials. +- */ +- err = mutex_lock_killable(&task->signal->cred_guard_mutex); +- if (err) +- return ERR_PTR(err); +- +- mm = __check_mem_permission(task); +- mutex_unlock(&task->signal->cred_guard_mutex); +- +- return mm; +-} +- +-struct mm_struct *mm_for_maps(struct task_struct *task) ++static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) + { + struct mm_struct *mm; + int err; +@@ -267,7 +209,7 @@ struct mm_struct *mm_for_maps(struct task_struct *task) + + mm = get_task_mm(task); + if (mm && mm != current->mm && +- !ptrace_may_access(task, PTRACE_MODE_READ)) { ++ !ptrace_may_access(task, mode)) { + mmput(mm); + mm = ERR_PTR(-EACCES); + } +@@ -276,6 +218,11 @@ struct mm_struct *mm_for_maps(struct task_struct *task) + return mm; + } + ++struct mm_struct *mm_for_maps(struct task_struct *task) ++{ ++ return mm_access(task, PTRACE_MODE_READ); ++} ++ + static int proc_pid_cmdline(struct task_struct *task, char * buffer) + { + int res = 0; +@@ -752,38 +699,39 @@ static const struct file_operations proc_single_file_operations = { + + static int mem_open(struct inode* inode, struct file* file) + { +- file->private_data = (void*)((long)current->self_exec_id); ++ struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); ++ struct mm_struct *mm; ++ ++ if (!task) ++ return -ESRCH; ++ ++ mm = mm_access(task, PTRACE_MODE_ATTACH); ++ put_task_struct(task); ++ ++ if (IS_ERR(mm)) ++ return PTR_ERR(mm); ++ + /* OK to pass negative loff_t, we can catch out-of-range */ + file->f_mode |= FMODE_UNSIGNED_OFFSET; ++ file->private_data = mm; ++ + return 0; + } + + static ssize_t mem_read(struct file * file, char __user * buf, + size_t count, loff_t *ppos) + { +- struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); ++ int ret; + char *page; + unsigned long src = *ppos; +- int ret = -ESRCH; +- struct mm_struct *mm; ++ struct mm_struct *mm = file->private_data; + +- if (!task) +- goto out_no_task; ++ if (!mm) ++ return 0; + +- ret = -ENOMEM; + page = (char *)__get_free_page(GFP_TEMPORARY); + if (!page) +- goto out; +- +- mm = check_mem_permission(task); +- ret = PTR_ERR(mm); +- if (IS_ERR(mm)) +- goto out_free; +- +- ret = -EIO; +- +- if (file->private_data != (void*)((long)current->self_exec_id)) +- goto out_put; ++ return -ENOMEM; + + ret = 0; + +@@ -810,13 +758,7 @@ static ssize_t mem_read(struct file * file, char __user * buf, + } + *ppos = src; + +-out_put: +- mmput(mm); +-out_free: + free_page((unsigned long) page); +-out: +- put_task_struct(task); +-out_no_task: + return ret; + } + +@@ -825,27 +767,15 @@ static ssize_t mem_write(struct file * file, const char __user *buf, + { + int copied; + char *page; +- struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); + unsigned long dst = *ppos; +- struct mm_struct *mm; ++ struct mm_struct *mm = file->private_data; + +- copied = -ESRCH; +- if (!task) +- goto out_no_task; ++ if (!mm) ++ return 0; + +- copied = -ENOMEM; + page = (char *)__get_free_page(GFP_TEMPORARY); + if (!page) +- goto out_task; +- +- mm = check_mem_permission(task); +- copied = PTR_ERR(mm); +- if (IS_ERR(mm)) +- goto out_free; +- +- copied = -EIO; +- if (file->private_data != (void *)((long)current->self_exec_id)) +- goto out_mm; ++ return -ENOMEM; + + copied = 0; + while (count > 0) { +@@ -869,13 +799,7 @@ static ssize_t mem_write(struct file * file, const char __user *buf, + } + *ppos = dst; + +-out_mm: +- mmput(mm); +-out_free: + free_page((unsigned long) page); +-out_task: +- put_task_struct(task); +-out_no_task: + return copied; + } + +@@ -895,11 +819,20 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig) + return file->f_pos; + } + ++static int mem_release(struct inode *inode, struct file *file) ++{ ++ struct mm_struct *mm = file->private_data; ++ ++ mmput(mm); ++ return 0; ++} ++ + static const struct file_operations proc_mem_operations = { + .llseek = mem_lseek, + .read = mem_read, + .write = mem_write, + .open = mem_open, ++ .release = mem_release, + }; + + static ssize_t environ_read(struct file *file, char __user *buf, +-- +1.7.7.5 + From e76e70cc41889fe6546ee43e96abfb7d47e78925 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Wed, 18 Jan 2012 09:16:57 -0600 Subject: [PATCH 281/397] build perf on armv7hl --- kernel.spec | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel.spec b/kernel.spec index 3e1be7bb5..3be1c083a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -354,6 +354,9 @@ Summary: The Linux kernel %define with_up 0 %define with_perf 0 %endif +%ifarch armv7hl +%define with_perf 1 +%endif # we only build headers on the base arm arches # just like we used to only build them on i386 for x86 %ifnarch armv5tel armv7hl @@ -2044,6 +2047,9 @@ fi # and build. %changelog +* Wed Jan 18 2012 Dennis Gilmore +- build perf on armv7hl + * Wed Jan 18 2012 Josh Boyer - CVE-2012-0056 proc: clean up and fix /proc//mem (rhbz 782681) From cd4ffd10e875541da001be96059e2fff331a6235 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 18 Jan 2012 10:23:39 -0500 Subject: [PATCH 282/397] loop: prevent information leak after failed read (rhbz 782687) --- kernel.spec | 6 +++ ...t-information-leak-after-failed-read.patch | 41 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 loop-prevent-information-leak-after-failed-read.patch diff --git a/kernel.spec b/kernel.spec index 3be1c083a..b5d2f86e2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -754,6 +754,8 @@ Patch21079: 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch #rhbz 782681 Patch21085: proc-clean-up-and-fix-proc-pid-mem-handling.patch +#rhbz 782687 +Patch21086: loop-prevent-information-leak-after-failed-read.patch %endif @@ -1400,6 +1402,9 @@ ApplyPatch 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch #rhbz 782681 ApplyPatch proc-clean-up-and-fix-proc-pid-mem-handling.patch +#rhbz 782687 +ApplyPatch loop-prevent-information-leak-after-failed-read.patch + # END OF PATCH APPLICATIONS %endif @@ -2052,6 +2057,7 @@ fi * Wed Jan 18 2012 Josh Boyer - CVE-2012-0056 proc: clean up and fix /proc//mem (rhbz 782681) +- loop: prevent information leak after failed read (rhbz 782687) * Tue Jan 17 2012 Josh Boyer - CVE-2011-4127 possible privilege escalation via SG_IO ioctl (rhbz 769911) diff --git a/loop-prevent-information-leak-after-failed-read.patch b/loop-prevent-information-leak-after-failed-read.patch new file mode 100644 index 000000000..040a234c3 --- /dev/null +++ b/loop-prevent-information-leak-after-failed-read.patch @@ -0,0 +1,41 @@ +From 3bb9068278ea524581237abadd41377a14717e7d Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Wed, 16 Nov 2011 09:21:48 +0100 +Subject: [PATCH] loop: prevent information leak after failed read + +If read was not fully successful we have to fail whole bio to prevent +information leak of old pages + +##Testcase_begin +dd if=/dev/zero of=./file bs=1M count=1 +losetup /dev/loop0 ./file -o 4096 +truncate -s 0 ./file +# OOps loop offset is now beyond i_size, so read will silently fail. +# So bio's pages would not be cleared, may which result in information leak. +hexdump -C /dev/loop0 +##testcase_end + +Signed-off-by: Dmitry Monakhov +Signed-off-by: Andrew Morton +Signed-off-by: Jens Axboe +--- + drivers/block/loop.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index 3d80682..0d56739 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -372,7 +372,8 @@ do_lo_receive(struct loop_device *lo, + + if (retval < 0) + return retval; +- ++ if (retval != bvec->bv_len) ++ return -EIO; + return 0; + } + +-- +1.7.7.5 + From 7655e85b7412b2b28bb14b29a581e316d8028836 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 18 Jan 2012 11:45:38 -0500 Subject: [PATCH 283/397] Update to Linux 3.1.10 --- KVM-fix-device-assignment-permissions.patch | 206 ------------------ ...tarting-PIT-timers-in-the-absence-of.patch | 69 ------ ...eck-if-acpi-already-handle-backlight.patch | 31 --- kernel.spec | 31 +-- ...include-bitmap-in-nfsv4_get_acl_data.patch | 118 ---------- sources | 2 +- 6 files changed, 6 insertions(+), 451 deletions(-) delete mode 100644 KVM-fix-device-assignment-permissions.patch delete mode 100644 KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch delete mode 100644 ideapad-Check-if-acpi-already-handle-backlight.patch delete mode 100644 nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch diff --git a/KVM-fix-device-assignment-permissions.patch b/KVM-fix-device-assignment-permissions.patch deleted file mode 100644 index 208948200..000000000 --- a/KVM-fix-device-assignment-permissions.patch +++ /dev/null @@ -1,206 +0,0 @@ -From 423873736b78f549fbfa2f715f2e4de7e6c5e1e9 Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Tue, 20 Dec 2011 21:59:03 -0700 -Subject: [PATCH 1/2] KVM: Remove ability to assign a device without iommu - support - -This option has no users and it exposes a security hole that we -can allow devices to be assigned without iommu protection. Make -KVM_DEV_ASSIGN_ENABLE_IOMMU a mandatory option. - -Signed-off-by: Alex Williamson -Signed-off-by: Marcelo Tosatti ---- - virt/kvm/assigned-dev.c | 18 +++++++++--------- - 1 files changed, 9 insertions(+), 9 deletions(-) - -diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c -index 3ad0925..a251a28 100644 ---- a/virt/kvm/assigned-dev.c -+++ b/virt/kvm/assigned-dev.c -@@ -487,6 +487,9 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, - struct kvm_assigned_dev_kernel *match; - struct pci_dev *dev; - -+ if (!(assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU)) -+ return -EINVAL; -+ - mutex_lock(&kvm->lock); - idx = srcu_read_lock(&kvm->srcu); - -@@ -544,16 +547,14 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, - - list_add(&match->list, &kvm->arch.assigned_dev_head); - -- if (assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) { -- if (!kvm->arch.iommu_domain) { -- r = kvm_iommu_map_guest(kvm); -- if (r) -- goto out_list_del; -- } -- r = kvm_assign_device(kvm, match); -+ if (!kvm->arch.iommu_domain) { -+ r = kvm_iommu_map_guest(kvm); - if (r) - goto out_list_del; - } -+ r = kvm_assign_device(kvm, match); -+ if (r) -+ goto out_list_del; - - out: - srcu_read_unlock(&kvm->srcu, idx); -@@ -593,8 +594,7 @@ static int kvm_vm_ioctl_deassign_device(struct kvm *kvm, - goto out; - } - -- if (match->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) -- kvm_deassign_device(kvm, match); -+ kvm_deassign_device(kvm, match); - - kvm_free_assigned_device(kvm, match); - --- -1.7.7.5 - - -From 3d27e23b17010c668db311140b17bbbb70c78fb9 Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Tue, 20 Dec 2011 21:59:09 -0700 -Subject: [PATCH 2/2] KVM: Device assignment permission checks - -Only allow KVM device assignment to attach to devices which: - - - Are not bridges - - Have BAR resources (assume others are special devices) - - The user has permissions to use - -Assigning a bridge is a configuration error, it's not supported, and -typically doesn't result in the behavior the user is expecting anyway. -Devices without BAR resources are typically chipset components that -also don't have host drivers. We don't want users to hold such devices -captive or cause system problems by fencing them off into an iommu -domain. We determine "permission to use" by testing whether the user -has access to the PCI sysfs resource files. By default a normal user -will not have access to these files, so it provides a good indication -that an administration agent has granted the user access to the device. - -[Yang Bai: add missing #include] -[avi: fix comment style] - -Signed-off-by: Alex Williamson -Signed-off-by: Yang Bai -Signed-off-by: Marcelo Tosatti ---- - virt/kvm/assigned-dev.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++ - 1 files changed, 75 insertions(+), 0 deletions(-) - -diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c -index a251a28..758e3b3 100644 ---- a/virt/kvm/assigned-dev.c -+++ b/virt/kvm/assigned-dev.c -@@ -17,6 +17,8 @@ - #include - #include - #include -+#include -+#include - #include "irq.h" - - static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head, -@@ -480,12 +482,73 @@ out: - return r; - } - -+/* -+ * We want to test whether the caller has been granted permissions to -+ * use this device. To be able to configure and control the device, -+ * the user needs access to PCI configuration space and BAR resources. -+ * These are accessed through PCI sysfs. PCI config space is often -+ * passed to the process calling this ioctl via file descriptor, so we -+ * can't rely on access to that file. We can check for permissions -+ * on each of the BAR resource files, which is a pretty clear -+ * indicator that the user has been granted access to the device. -+ */ -+static int probe_sysfs_permissions(struct pci_dev *dev) -+{ -+#ifdef CONFIG_SYSFS -+ int i; -+ bool bar_found = false; -+ -+ for (i = PCI_STD_RESOURCES; i <= PCI_STD_RESOURCE_END; i++) { -+ char *kpath, *syspath; -+ struct path path; -+ struct inode *inode; -+ int r; -+ -+ if (!pci_resource_len(dev, i)) -+ continue; -+ -+ kpath = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); -+ if (!kpath) -+ return -ENOMEM; -+ -+ /* Per sysfs-rules, sysfs is always at /sys */ -+ syspath = kasprintf(GFP_KERNEL, "/sys%s/resource%d", kpath, i); -+ kfree(kpath); -+ if (!syspath) -+ return -ENOMEM; -+ -+ r = kern_path(syspath, LOOKUP_FOLLOW, &path); -+ kfree(syspath); -+ if (r) -+ return r; -+ -+ inode = path.dentry->d_inode; -+ -+ r = inode_permission(inode, MAY_READ | MAY_WRITE | MAY_ACCESS); -+ path_put(&path); -+ if (r) -+ return r; -+ -+ bar_found = true; -+ } -+ -+ /* If no resources, probably something special */ -+ if (!bar_found) -+ return -EPERM; -+ -+ return 0; -+#else -+ return -EINVAL; /* No way to control the device without sysfs */ -+#endif -+} -+ - static int kvm_vm_ioctl_assign_device(struct kvm *kvm, - struct kvm_assigned_pci_dev *assigned_dev) - { - int r = 0, idx; - struct kvm_assigned_dev_kernel *match; - struct pci_dev *dev; -+ u8 header_type; - - if (!(assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU)) - return -EINVAL; -@@ -516,6 +579,18 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, - r = -EINVAL; - goto out_free; - } -+ -+ /* Don't allow bridges to be assigned */ -+ pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); -+ if ((header_type & PCI_HEADER_TYPE) != PCI_HEADER_TYPE_NORMAL) { -+ r = -EPERM; -+ goto out_put; -+ } -+ -+ r = probe_sysfs_permissions(dev); -+ if (r) -+ goto out_put; -+ - if (pci_enable_device(dev)) { - printk(KERN_INFO "%s: Could not enable PCI device\n", __func__); - r = -EBUSY; --- -1.7.7.5 - diff --git a/KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch b/KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch deleted file mode 100644 index 07ef3e71b..000000000 --- a/KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0924ab2cfa98b1ece26c033d696651fd62896c69 Mon Sep 17 00:00:00 2001 -From: Jan Kiszka -Date: Wed, 14 Dec 2011 19:25:13 +0100 -Subject: [PATCH] KVM: x86: Prevent starting PIT timers in the absence of - irqchip support - -User space may create the PIT and forgets about setting up the irqchips. -In that case, firing PIT IRQs will crash the host: - -BUG: unable to handle kernel NULL pointer dereference at 0000000000000128 -IP: [] kvm_set_irq+0x30/0x170 [kvm] -... -Call Trace: - [] pit_do_work+0x51/0xd0 [kvm] - [] process_one_work+0x111/0x4d0 - [] worker_thread+0x152/0x340 - [] kthread+0x7e/0x90 - [] kernel_thread_helper+0x4/0x10 - -Prevent this by checking the irqchip mode before starting a timer. We -can't deny creating the PIT if the irqchips aren't set up yet as -current user land expects this order to work. - -Signed-off-by: Jan Kiszka -Signed-off-by: Marcelo Tosatti ---- - arch/x86/kvm/i8254.c | 10 +++++++--- - 1 files changed, 7 insertions(+), 3 deletions(-) - -diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c -index 76e3f1c..405f262 100644 ---- a/arch/x86/kvm/i8254.c -+++ b/arch/x86/kvm/i8254.c -@@ -338,11 +338,15 @@ static enum hrtimer_restart pit_timer_fn(struct hrtimer *data) - return HRTIMER_NORESTART; - } - --static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period) -+static void create_pit_timer(struct kvm *kvm, u32 val, int is_period) - { -+ struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state; - struct kvm_timer *pt = &ps->pit_timer; - s64 interval; - -+ if (!irqchip_in_kernel(kvm)) -+ return; -+ - interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ); - - pr_debug("create pit timer, interval is %llu nsec\n", interval); -@@ -394,13 +398,13 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val) - /* FIXME: enhance mode 4 precision */ - case 4: - if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)) { -- create_pit_timer(ps, val, 0); -+ create_pit_timer(kvm, val, 0); - } - break; - case 2: - case 3: - if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)){ -- create_pit_timer(ps, val, 1); -+ create_pit_timer(kvm, val, 1); - } - break; - default: --- -1.7.6.2 - diff --git a/ideapad-Check-if-acpi-already-handle-backlight.patch b/ideapad-Check-if-acpi-already-handle-backlight.patch deleted file mode 100644 index 713e005d8..000000000 --- a/ideapad-Check-if-acpi-already-handle-backlight.patch +++ /dev/null @@ -1,31 +0,0 @@ -From d4afc7754a60b885b63ef23fd194984e2d53a4e6 Mon Sep 17 00:00:00 2001 -From: Rene Bollford -Date: Sun, 23 Oct 2011 09:56:42 +0200 -Subject: [PATCH] [PATCH] ideapad: Check if acpi already handle backlight - power to avoid a page fault - -This patch avoid a page fault in the ideapad-laptop extras when -turning the backlight power on or off. - -Signed-off-by: Rene Bolldorf -Signed-off-by: Matthew Garrett ---- - drivers/platform/x86/ideapad-laptop.c | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) - -diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c -index 0c59541..0d94eec 100644 ---- a/drivers/platform/x86/ideapad-laptop.c -+++ b/drivers/platform/x86/ideapad-laptop.c -@@ -493,6 +493,8 @@ static void ideapad_backlight_notify_power(struct ideapad_private *priv) - unsigned long power; - struct backlight_device *blightdev = priv->blightdev; - -+ if (!blightdev) -+ return; - if (read_ec_data(ideapad_handle, 0x18, &power)) - return; - blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; --- -1.7.6.4 - diff --git a/kernel.spec b/kernel.spec index b5d2f86e2..296c370c6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 4 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # Do we have a -stable update to apply? -%define stable_update 9 +%define stable_update 10 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -651,9 +651,6 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 -#rhbz 753236 -Patch4000: nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch - # patches headed upstream Patch12010: add-appleir-usb-driver.patch @@ -694,9 +691,6 @@ Patch21040: x86-code-dump-fix-truncation.patch #rhbz 728607 Patch21060: elantech.patch -#rhbz 748210 -Patch21061: ideapad-Check-if-acpi-already-handle-backlight.patch - #backport brcm80211 from 3.2-rc1 Patch21090: brcm80211.patch Patch21091: bcma-brcmsmac-compat.patch @@ -725,12 +719,6 @@ Patch21048: b44-Use-dev_kfree_skb_irq-in-b44_tx.patch #rhbz 771006 Patch21050: thp-reduce-khugepaged-freezing-latency.patch -#rhbz 770102 -Patch21055: KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch - -#rhbz 770096 -Patch21056: KVM-fix-device-assignment-permissions.patch - #rhbz 770233 Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch @@ -1204,7 +1192,6 @@ ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # eCryptfs # NFSv4 -ApplyPatch nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch # USB @@ -1341,9 +1328,6 @@ ApplyPatch x86-code-dump-fix-truncation.patch #rhbz 728607 ApplyPatch elantech.patch -#rhbz 748210 -ApplyPatch ideapad-Check-if-acpi-already-handle-backlight.patch - #backport brcm80211 from 3.2-rc1 ApplyPatch brcm80211.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 @@ -1373,20 +1357,12 @@ ApplyPatch b44-Use-dev_kfree_skb_irq-in-b44_tx.patch #rhbz 771006 ApplyPatch thp-reduce-khugepaged-freezing-latency.patch -#rhbz 770102 -ApplyPatch KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch - #rhbz 770233 ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch -#rhbz 770096 -ApplyPatch KVM-fix-device-assignment-permissions.patch - ApplyPatch ext4-Fix-error-handling-on-inode-bitmap-corruption.patch ApplyPatch ext3-Fix-error-handling-on-inode-bitmap-corruption.patch -ApplyPatch mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch - #rhbz 773392 ApplyPatch KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch @@ -2052,6 +2028,9 @@ fi # and build. %changelog +* Wed Jan 18 2012 Josh Boyer 2.6.41.10-1 +- Linux 3.1.10 + * Wed Jan 18 2012 Dennis Gilmore - build perf on armv7hl diff --git a/nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch b/nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch deleted file mode 100644 index 1b795e97f..000000000 --- a/nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch +++ /dev/null @@ -1,118 +0,0 @@ -From: Andy Adamson - -The NFSv4 bitmap size is unbounded: a server can return an arbitrary -sized bitmap in an FATTR4_WORD0_ACL request. Replace using the -nfs4_fattr_bitmap_maxsz as a guess to the maximum bitmask returned by a server -with the inclusion of the bitmap (xdr length plus bitmasks) and the acl data -xdr length to the (cached) acl page data. - -This is a general solution to commit e5012d1f "NFSv4.1: update -nfs4_fattr_bitmap_maxsz" and fixes hitting a BUG_ON in xdr_shrink_bufhead -when getting ACLs. - -Cc:stable@xxxxxxxxxx -Signed-off-by: Andy Adamson ---- - fs/nfs/nfs4proc.c | 20 ++++++++++++++++++-- - fs/nfs/nfs4xdr.c | 15 ++++++++++++--- - 2 files changed, 30 insertions(+), 5 deletions(-) - -diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c -index deb88d9..97014dd 100644 ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -3671,6 +3671,22 @@ static void nfs4_zap_acl_attr(struct inode *inode) - nfs4_set_cached_acl(inode, NULL); - } - -+/* -+ * The bitmap xdr length, bitmasks, and the attr xdr length are stored in -+ * the acl cache to handle variable length bitmasks. Just copy the acl data. -+ */ -+static void nfs4_copy_acl(char *buf, char *acl_data, size_t acl_len) -+{ -+ __be32 *q, *p = (__be32 *)acl_data; -+ int32_t len; -+ -+ len = be32_to_cpup(p); /* number of bitmasks */ -+ len += 2; /* add words for bitmap and attr xdr len */ -+ q = p + len; -+ len = len << 2; /* convert to bytes for acl_len math */ -+ memcpy(buf, (char *)q, acl_len - len); -+} -+ - static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_t buflen) - { - struct nfs_inode *nfsi = NFS_I(inode); -@@ -3688,7 +3704,7 @@ static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_ - ret = -ERANGE; /* see getxattr(2) man page */ - if (acl->len > buflen) - goto out; -- memcpy(buf, acl->data, acl->len); -+ nfs4_copy_acl(buf, acl->data, acl->len); - out_len: - ret = acl->len; - out: -@@ -3763,7 +3779,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu - if (res.acl_len > buflen) - goto out_free; - if (localpage) -- memcpy(buf, resp_buf, res.acl_len); -+ nfs4_copy_acl(buf, resp_buf, res.acl_len); - } - ret = res.acl_len; - out_free: -diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c -index f9fd96d..9c07380 100644 ---- a/fs/nfs/nfs4xdr.c -+++ b/fs/nfs/nfs4xdr.c -@@ -2513,7 +2513,7 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, - encode_compound_hdr(xdr, req, &hdr); - encode_sequence(xdr, &args->seq_args, &hdr); - encode_putfh(xdr, args->fh, &hdr); -- replen = hdr.replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1; -+ replen = hdr.replen + op_decode_hdr_maxsz + 1; - encode_getattr_two(xdr, FATTR4_WORD0_ACL, 0, &hdr); - - xdr_inline_pages(&req->rq_rcv_buf, replen << 2, -@@ -4955,7 +4955,7 @@ decode_restorefh(struct xdr_stream *xdr) - static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, - size_t *acl_len) - { -- __be32 *savep; -+ __be32 *savep, *bm_p; - uint32_t attrlen, - bitmap[3] = {0}; - struct kvec *iov = req->rq_rcv_buf.head; -@@ -4964,6 +4964,7 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, - *acl_len = 0; - if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) - goto out; -+ bm_p = xdr->p; - if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) - goto out; - if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) -@@ -4972,12 +4973,20 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, - if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) - return -EIO; - if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { -- size_t hdrlen; -+ size_t hdrlen, len; - u32 recvd; - -+ /*The bitmap (xdr len + bitmasks) and the attr xdr len words -+ * are stored with the acl data to handle the problem of -+ * variable length bitmasks.*/ -+ xdr->p = bm_p; -+ len = be32_to_cpup(bm_p); -+ len += 2; /* add bitmap and attr xdr len words */ -+ - /* We ignore &savep and don't do consistency checks on - * the attr length. Let userspace figure it out.... */ - hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; -+ attrlen += len << 2; /* attrlen is in bytes */ - recvd = req->rq_rcv_buf.len - hdrlen; - if (attrlen > recvd) { - dprintk("NFS: server cheating in getattr" --- -1.7.6.4 diff --git a/sources b/sources index 7bd2ca37c..030427a02 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -fae6176f187628bcc5b330cdadc60f9e patch-3.1.9.bz2 +a8e1c25a93a685ec2a1c3a808715fe9d patch-3.1.10.bz2 From 64fa2d2b43420ca4e9f3762dc6da93a9324009f1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 18 Jan 2012 13:22:40 -0500 Subject: [PATCH 284/397] /proc/pid/* information leak (rhbz 782686) --- kernel.spec | 11 + ...pointer-deref-in-proc_pid_permission.patch | 44 +++ ...fs-add-hidepid-and-gid-mount-options.patch | 342 ++++++++++++++++++ procfs-parse-mount-options.patch | 173 +++++++++ 4 files changed, 570 insertions(+) create mode 100644 proc-fix-null-pointer-deref-in-proc_pid_permission.patch create mode 100644 procfs-add-hidepid-and-gid-mount-options.patch create mode 100644 procfs-parse-mount-options.patch diff --git a/kernel.spec b/kernel.spec index 296c370c6..3c954b145 100644 --- a/kernel.spec +++ b/kernel.spec @@ -739,6 +739,11 @@ Patch21077: 01-block-add-and-use-scsi_blk_cmd_ioctl.patch Patch21078: 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch Patch21079: 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch +#rhbz 782686 +Patch21082: procfs-parse-mount-options.patch +Patch21083: procfs-add-hidepid-and-gid-mount-options.patch +Patch21084: proc-fix-null-pointer-deref-in-proc_pid_permission.patch + #rhbz 782681 Patch21085: proc-clean-up-and-fix-proc-pid-mem-handling.patch @@ -1375,6 +1380,11 @@ ApplyPatch 01-block-add-and-use-scsi_blk_cmd_ioctl.patch ApplyPatch 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch ApplyPatch 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch +#rhbz 782686 +ApplyPatch procfs-parse-mount-options.patch +ApplyPatch procfs-add-hidepid-and-gid-mount-options.patch +ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch + #rhbz 782681 ApplyPatch proc-clean-up-and-fix-proc-pid-mem-handling.patch @@ -2030,6 +2040,7 @@ fi %changelog * Wed Jan 18 2012 Josh Boyer 2.6.41.10-1 - Linux 3.1.10 +- /proc/pid/* information leak (rhbz 782686) * Wed Jan 18 2012 Dennis Gilmore - build perf on armv7hl diff --git a/proc-fix-null-pointer-deref-in-proc_pid_permission.patch b/proc-fix-null-pointer-deref-in-proc_pid_permission.patch new file mode 100644 index 000000000..62d2fb21a --- /dev/null +++ b/proc-fix-null-pointer-deref-in-proc_pid_permission.patch @@ -0,0 +1,44 @@ +From a2ef990ab5a6705a356d146dd773a3b359787497 Mon Sep 17 00:00:00 2001 +From: Xiaotian Feng +Date: Thu, 12 Jan 2012 17:17:08 -0800 +Subject: [PATCH] proc: fix null pointer deref in proc_pid_permission() + +get_proc_task() can fail to search the task and return NULL, +put_task_struct() will then bomb the kernel with following oops: + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 + IP: [] proc_pid_permission+0x64/0xe0 + PGD 112075067 PUD 112814067 PMD 0 + Oops: 0002 [#1] PREEMPT SMP + +This is a regression introduced by commit 0499680a ("procfs: add hidepid= +and gid= mount options"). The kernel should return -ESRCH if +get_proc_task() failed. + +Signed-off-by: Xiaotian Feng +Cc: Al Viro +Cc: Vasiliy Kulikov +Cc: Stephen Wilson +Acked-by: David Rientjes +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + fs/proc/base.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/fs/proc/base.c b/fs/proc/base.c +index 8173dfd..5485a53 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -654,6 +654,8 @@ static int proc_pid_permission(struct inode *inode, int mask) + bool has_perms; + + task = get_proc_task(inode); ++ if (!task) ++ return -ESRCH; + has_perms = has_pid_permissions(pid, task, 1); + put_task_struct(task); + +-- +1.7.7.5 + diff --git a/procfs-add-hidepid-and-gid-mount-options.patch b/procfs-add-hidepid-and-gid-mount-options.patch new file mode 100644 index 000000000..24156b0dc --- /dev/null +++ b/procfs-add-hidepid-and-gid-mount-options.patch @@ -0,0 +1,342 @@ +From 0499680a42141d86417a8fbaa8c8db806bea1201 Mon Sep 17 00:00:00 2001 +From: Vasiliy Kulikov +Date: Tue, 10 Jan 2012 15:11:31 -0800 +Subject: [PATCH] procfs: add hidepid= and gid= mount options + +Add support for mount options to restrict access to /proc/PID/ +directories. The default backward-compatible "relaxed" behaviour is left +untouched. + +The first mount option is called "hidepid" and its value defines how much +info about processes we want to be available for non-owners: + +hidepid=0 (default) means the old behavior - anybody may read all +world-readable /proc/PID/* files. + +hidepid=1 means users may not access any /proc// directories, but +their own. Sensitive files like cmdline, sched*, status are now protected +against other users. As permission checking done in proc_pid_permission() +and files' permissions are left untouched, programs expecting specific +files' modes are not confused. + +hidepid=2 means hidepid=1 plus all /proc/PID/ will be invisible to other +users. It doesn't mean that it hides whether a process exists (it can be +learned by other means, e.g. by kill -0 $PID), but it hides process' euid +and egid. It compicates intruder's task of gathering info about running +processes, whether some daemon runs with elevated privileges, whether +another user runs some sensitive program, whether other users run any +program at all, etc. + +gid=XXX defines a group that will be able to gather all processes' info +(as in hidepid=0 mode). This group should be used instead of putting +nonroot user in sudoers file or something. However, untrusted users (like +daemons, etc.) which are not supposed to monitor the tasks in the whole +system should not be added to the group. + +hidepid=1 or higher is designed to restrict access to procfs files, which +might reveal some sensitive private information like precise keystrokes +timings: + +http://www.openwall.com/lists/oss-security/2011/11/05/3 + +hidepid=1/2 doesn't break monitoring userspace tools. ps, top, pgrep, and +conky gracefully handle EPERM/ENOENT and behave as if the current user is +the only user running processes. pstree shows the process subtree which +contains "pstree" process. + +Note: the patch doesn't deal with setuid/setgid issues of keeping +preopened descriptors of procfs files (like +https://lkml.org/lkml/2011/2/7/368). We rely on that the leaked +information like the scheduling counters of setuid apps doesn't threaten +anybody's privacy - only the user started the setuid program may read the +counters. + +Signed-off-by: Vasiliy Kulikov +Cc: Alexey Dobriyan +Cc: Al Viro +Cc: Randy Dunlap +Cc: "H. Peter Anvin" +Cc: Greg KH +Cc: Theodore Tso +Cc: Alan Cox +Cc: James Morris +Cc: Oleg Nesterov +Cc: Hugh Dickins +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + Documentation/filesystems/proc.txt | 39 ++++++++++++++++++++ + fs/proc/base.c | 69 +++++++++++++++++++++++++++++++++++- + fs/proc/inode.c | 8 ++++ + fs/proc/root.c | 21 +++++++++-- + include/linux/pid_namespace.h | 2 + + 5 files changed, 135 insertions(+), 4 deletions(-) + +diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt +index 0ec91f0..12fee13 100644 +--- a/Documentation/filesystems/proc.txt ++++ b/Documentation/filesystems/proc.txt +@@ -41,6 +41,8 @@ Table of Contents + 3.5 /proc//mountinfo - Information about mounts + 3.6 /proc//comm & /proc//task//comm + ++ 4 Configuring procfs ++ 4.1 Mount options + + ------------------------------------------------------------------------------ + Preface +@@ -1542,3 +1544,40 @@ a task to set its own or one of its thread siblings comm value. The comm value + is limited in size compared to the cmdline value, so writing anything longer + then the kernel's TASK_COMM_LEN (currently 16 chars) will result in a truncated + comm value. ++ ++ ++------------------------------------------------------------------------------ ++Configuring procfs ++------------------------------------------------------------------------------ ++ ++4.1 Mount options ++--------------------- ++ ++The following mount options are supported: ++ ++ hidepid= Set /proc// access mode. ++ gid= Set the group authorized to learn processes information. ++ ++hidepid=0 means classic mode - everybody may access all /proc// directories ++(default). ++ ++hidepid=1 means users may not access any /proc// directories but their ++own. Sensitive files like cmdline, sched*, status are now protected against ++other users. This makes it impossible to learn whether any user runs ++specific program (given the program doesn't reveal itself by its behaviour). ++As an additional bonus, as /proc//cmdline is unaccessible for other users, ++poorly written programs passing sensitive information via program arguments are ++now protected against local eavesdroppers. ++ ++hidepid=2 means hidepid=1 plus all /proc// will be fully invisible to other ++users. It doesn't mean that it hides a fact whether a process with a specific ++pid value exists (it can be learned by other means, e.g. by "kill -0 $PID"), ++but it hides process' uid and gid, which may be learned by stat()'ing ++/proc// otherwise. It greatly complicates an intruder's task of gathering ++information about running processes, whether some daemon runs with elevated ++privileges, whether other user runs some sensitive program, whether other users ++run any program at all, etc. ++ ++gid= defines a group authorized to learn processes information otherwise ++prohibited by hidepid=. If you use some daemon like identd which needs to learn ++information about processes information, just add identd to this group. +diff --git a/fs/proc/base.c b/fs/proc/base.c +index 4d755fe..8173dfd 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -631,6 +631,50 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr) + return 0; + } + ++/* ++ * May current process learn task's sched/cmdline info (for hide_pid_min=1) ++ * or euid/egid (for hide_pid_min=2)? ++ */ ++static bool has_pid_permissions(struct pid_namespace *pid, ++ struct task_struct *task, ++ int hide_pid_min) ++{ ++ if (pid->hide_pid < hide_pid_min) ++ return true; ++ if (in_group_p(pid->pid_gid)) ++ return true; ++ return ptrace_may_access(task, PTRACE_MODE_READ); ++} ++ ++ ++static int proc_pid_permission(struct inode *inode, int mask) ++{ ++ struct pid_namespace *pid = inode->i_sb->s_fs_info; ++ struct task_struct *task; ++ bool has_perms; ++ ++ task = get_proc_task(inode); ++ has_perms = has_pid_permissions(pid, task, 1); ++ put_task_struct(task); ++ ++ if (!has_perms) { ++ if (pid->hide_pid == 2) { ++ /* ++ * Let's make getdents(), stat(), and open() ++ * consistent with each other. If a process ++ * may not stat() a file, it shouldn't be seen ++ * in procfs at all. ++ */ ++ return -ENOENT; ++ } ++ ++ return -EPERM; ++ } ++ return generic_permission(inode, mask); ++} ++ ++ ++ + static const struct inode_operations proc_def_inode_operations = { + .setattr = proc_setattr, + }; +@@ -1615,6 +1659,7 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) + struct inode *inode = dentry->d_inode; + struct task_struct *task; + const struct cred *cred; ++ struct pid_namespace *pid = dentry->d_sb->s_fs_info; + + generic_fillattr(inode, stat); + +@@ -1623,6 +1668,14 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) + stat->gid = 0; + task = pid_task(proc_pid(inode), PIDTYPE_PID); + if (task) { ++ if (!has_pid_permissions(pid, task, 2)) { ++ rcu_read_unlock(); ++ /* ++ * This doesn't prevent learning whether PID exists, ++ * it only makes getattr() consistent with readdir(). ++ */ ++ return -ENOENT; ++ } + if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || + task_dumpable(task)) { + cred = __task_cred(task); +@@ -3119,6 +3172,7 @@ static const struct inode_operations proc_tgid_base_inode_operations = { + .lookup = proc_tgid_base_lookup, + .getattr = pid_getattr, + .setattr = proc_setattr, ++ .permission = proc_pid_permission, + }; + + static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid) +@@ -3322,6 +3376,12 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi + proc_pid_instantiate, iter.task, NULL); + } + ++static int fake_filldir(void *buf, const char *name, int namelen, ++ loff_t offset, u64 ino, unsigned d_type) ++{ ++ return 0; ++} ++ + /* for the /proc/ directory itself, after non-process stuff has been done */ + int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) + { +@@ -3329,6 +3389,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) + struct task_struct *reaper; + struct tgid_iter iter; + struct pid_namespace *ns; ++ filldir_t __filldir; + + if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET) + goto out_no_task; +@@ -3350,8 +3411,13 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) + for (iter = next_tgid(ns, iter); + iter.task; + iter.tgid += 1, iter = next_tgid(ns, iter)) { ++ if (has_pid_permissions(ns, iter.task, 2)) ++ __filldir = filldir; ++ else ++ __filldir = fake_filldir; ++ + filp->f_pos = iter.tgid + TGID_OFFSET; +- if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) { ++ if (proc_pid_fill_cache(filp, dirent, __filldir, iter) < 0) { + put_task_struct(iter.task); + goto out; + } +@@ -3686,6 +3752,7 @@ static const struct inode_operations proc_task_inode_operations = { + .lookup = proc_task_lookup, + .getattr = proc_task_getattr, + .setattr = proc_setattr, ++ .permission = proc_pid_permission, + }; + + static const struct file_operations proc_task_operations = { +diff --git a/fs/proc/inode.c b/fs/proc/inode.c +index 27c762f..84fd323 100644 +--- a/fs/proc/inode.c ++++ b/fs/proc/inode.c +@@ -106,6 +106,14 @@ void __init proc_init_inodecache(void) + + static int proc_show_options(struct seq_file *seq, struct dentry *root) + { ++ struct super_block *sb = root->d_sb; ++ struct pid_namespace *pid = sb->s_fs_info; ++ ++ if (pid->pid_gid) ++ seq_printf(seq, ",gid=%lu", (unsigned long)pid->pid_gid); ++ if (pid->hide_pid != 0) ++ seq_printf(seq, ",hidepid=%u", pid->hide_pid); ++ + return 0; + } + +diff --git a/fs/proc/root.c b/fs/proc/root.c +index 6a8ac1d..46a15d8 100644 +--- a/fs/proc/root.c ++++ b/fs/proc/root.c +@@ -38,10 +38,12 @@ static int proc_set_super(struct super_block *sb, void *data) + } + + enum { +- Opt_err, ++ Opt_gid, Opt_hidepid, Opt_err, + }; + + static const match_table_t tokens = { ++ {Opt_hidepid, "hidepid=%u"}, ++ {Opt_gid, "gid=%u"}, + {Opt_err, NULL}, + }; + +@@ -49,8 +51,7 @@ static int proc_parse_options(char *options, struct pid_namespace *pid) + { + char *p; + substring_t args[MAX_OPT_ARGS]; +- +- pr_debug("proc: options = %s\n", options); ++ int option; + + if (!options) + return 1; +@@ -63,6 +64,20 @@ static int proc_parse_options(char *options, struct pid_namespace *pid) + args[0].to = args[0].from = 0; + token = match_token(p, tokens, args); + switch (token) { ++ case Opt_gid: ++ if (match_int(&args[0], &option)) ++ return 0; ++ pid->pid_gid = option; ++ break; ++ case Opt_hidepid: ++ if (match_int(&args[0], &option)) ++ return 0; ++ if (option < 0 || option > 2) { ++ pr_err("proc: hidepid value must be between 0 and 2.\n"); ++ return 0; ++ } ++ pid->hide_pid = option; ++ break; + default: + pr_err("proc: unrecognized mount option \"%s\" " + "or missing value\n", p); +diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h +index 38d1032..e7cf666 100644 +--- a/include/linux/pid_namespace.h ++++ b/include/linux/pid_namespace.h +@@ -30,6 +30,8 @@ struct pid_namespace { + #ifdef CONFIG_BSD_PROCESS_ACCT + struct bsd_acct_struct *bacct; + #endif ++ gid_t pid_gid; ++ int hide_pid; + }; + + extern struct pid_namespace init_pid_ns; +-- +1.7.7.5 + diff --git a/procfs-parse-mount-options.patch b/procfs-parse-mount-options.patch new file mode 100644 index 000000000..99684c4bd --- /dev/null +++ b/procfs-parse-mount-options.patch @@ -0,0 +1,173 @@ +From 97412950b10e64f347aec4a9b759395c2465adf6 Mon Sep 17 00:00:00 2001 +From: Vasiliy Kulikov +Date: Tue, 10 Jan 2012 15:11:27 -0800 +Subject: [PATCH] procfs: parse mount options + +Add support for procfs mount options. Actual mount options are coming in +the next patches. + +Signed-off-by: Vasiliy Kulikov +Cc: Alexey Dobriyan +Cc: Al Viro +Cc: Randy Dunlap +Cc: "H. Peter Anvin" +Cc: Greg KH +Cc: Theodore Tso +Cc: Alan Cox +Cc: James Morris +Cc: Oleg Nesterov +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + fs/proc/inode.c | 10 +++++++++ + fs/proc/internal.h | 1 + + fs/proc/root.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 64 insertions(+), 2 deletions(-) + +diff --git a/fs/proc/inode.c b/fs/proc/inode.c +index 51a1766..27c762f 100644 +--- a/fs/proc/inode.c ++++ b/fs/proc/inode.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -17,7 +18,9 @@ + #include + #include + #include ++#include + #include ++#include + + #include + #include +@@ -101,12 +104,19 @@ void __init proc_init_inodecache(void) + init_once); + } + ++static int proc_show_options(struct seq_file *seq, struct dentry *root) ++{ ++ return 0; ++} ++ + static const struct super_operations proc_sops = { + .alloc_inode = proc_alloc_inode, + .destroy_inode = proc_destroy_inode, + .drop_inode = generic_delete_inode, + .evict_inode = proc_evict_inode, + .statfs = simple_statfs, ++ .remount_fs = proc_remount, ++ .show_options = proc_show_options, + }; + + static void __pde_users_dec(struct proc_dir_entry *pde) +diff --git a/fs/proc/internal.h b/fs/proc/internal.h +index 7838e5c..2925775 100644 +--- a/fs/proc/internal.h ++++ b/fs/proc/internal.h +@@ -117,6 +117,7 @@ void pde_put(struct proc_dir_entry *pde); + + int proc_fill_super(struct super_block *); + struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *); ++int proc_remount(struct super_block *sb, int *flags, char *data); + + /* + * These are generic /proc routines that use the internal +diff --git a/fs/proc/root.c b/fs/proc/root.c +index 03102d9..6a8ac1d 100644 +--- a/fs/proc/root.c ++++ b/fs/proc/root.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #include "internal.h" + +@@ -36,6 +37,48 @@ static int proc_set_super(struct super_block *sb, void *data) + return err; + } + ++enum { ++ Opt_err, ++}; ++ ++static const match_table_t tokens = { ++ {Opt_err, NULL}, ++}; ++ ++static int proc_parse_options(char *options, struct pid_namespace *pid) ++{ ++ char *p; ++ substring_t args[MAX_OPT_ARGS]; ++ ++ pr_debug("proc: options = %s\n", options); ++ ++ if (!options) ++ return 1; ++ ++ while ((p = strsep(&options, ",")) != NULL) { ++ int token; ++ if (!*p) ++ continue; ++ ++ args[0].to = args[0].from = 0; ++ token = match_token(p, tokens, args); ++ switch (token) { ++ default: ++ pr_err("proc: unrecognized mount option \"%s\" " ++ "or missing value\n", p); ++ return 0; ++ } ++ } ++ ++ return 1; ++} ++ ++int proc_remount(struct super_block *sb, int *flags, char *data) ++{ ++ struct pid_namespace *pid = sb->s_fs_info; ++ return !proc_parse_options(data, pid); ++} ++ + static struct dentry *proc_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) + { +@@ -43,11 +86,15 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, + struct super_block *sb; + struct pid_namespace *ns; + struct proc_inode *ei; ++ char *options; + +- if (flags & MS_KERNMOUNT) ++ if (flags & MS_KERNMOUNT) { + ns = (struct pid_namespace *)data; +- else ++ options = NULL; ++ } else { + ns = current->nsproxy->pid_ns; ++ options = data; ++ } + + sb = sget(fs_type, proc_test_super, proc_set_super, ns); + if (IS_ERR(sb)) +@@ -55,6 +102,10 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, + + if (!sb->s_root) { + sb->s_flags = flags; ++ if (!proc_parse_options(options, ns)) { ++ deactivate_locked_super(sb); ++ return ERR_PTR(-EINVAL); ++ } + err = proc_fill_super(sb); + if (err) { + deactivate_locked_super(sb); +-- +1.7.7.5 + From 386367acf48761b078762d7bd51d2d42ed391cb5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 18 Jan 2012 20:00:25 -0500 Subject: [PATCH 285/397] Fix broken procfs backport (rhbz 782961) --- kernel.spec | 5 ++++- procfs-add-hidepid-and-gid-mount-options.patch | 4 ++-- procfs-parse-mount-options.patch | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/kernel.spec b/kernel.spec index 3c954b145..5db1b31a4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -2038,6 +2038,9 @@ fi # and build. %changelog +* Wed Jan 18 2012 Josh Boyer 2.6.41.10-2 +- Fix broken procfs backport (rhbz 782961) + * Wed Jan 18 2012 Josh Boyer 2.6.41.10-1 - Linux 3.1.10 - /proc/pid/* information leak (rhbz 782686) diff --git a/procfs-add-hidepid-and-gid-mount-options.patch b/procfs-add-hidepid-and-gid-mount-options.patch index 24156b0dc..803f77d4c 100644 --- a/procfs-add-hidepid-and-gid-mount-options.patch +++ b/procfs-add-hidepid-and-gid-mount-options.patch @@ -262,9 +262,9 @@ index 27c762f..84fd323 100644 +++ b/fs/proc/inode.c @@ -106,6 +106,14 @@ void __init proc_init_inodecache(void) - static int proc_show_options(struct seq_file *seq, struct dentry *root) + static int proc_show_options(struct seq_file *seq, struct vfsmount *vfs) { -+ struct super_block *sb = root->d_sb; ++ struct super_block *sb = vfs->mnt_sb; + struct pid_namespace *pid = sb->s_fs_info; + + if (pid->pid_gid) diff --git a/procfs-parse-mount-options.patch b/procfs-parse-mount-options.patch index 99684c4bd..0187a1d44 100644 --- a/procfs-parse-mount-options.patch +++ b/procfs-parse-mount-options.patch @@ -50,7 +50,7 @@ index 51a1766..27c762f 100644 init_once); } -+static int proc_show_options(struct seq_file *seq, struct dentry *root) ++static int proc_show_options(struct seq_file *seq, struct vfsmount *vfs) +{ + return 0; +} From c6aa69ef87656955409a3d7461c8b751dff6175b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 20 Jan 2012 09:41:43 -0500 Subject: [PATCH 286/397] Put patches in numerical order again Josh's brain can't cope with random ordering. FIGHT THE CHAOS. --- kernel.spec | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/kernel.spec b/kernel.spec index 5db1b31a4..a08db415f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -688,25 +688,6 @@ Patch21031: benet-remove-bogus-unlikely-on-vlan-check.patch Patch21040: x86-code-dump-fix-truncation.patch -#rhbz 728607 -Patch21060: elantech.patch - -#backport brcm80211 from 3.2-rc1 -Patch21090: brcm80211.patch -Patch21091: bcma-brcmsmac-compat.patch - -# rhbz 754907 -Patch21100: cciss-fix-irqf-shared.patch -Patch21101: hpsa-add-irqf-shared.patch - -#rhbz 731365 -Patch21220: mac80211_offchannel_rework_revert.patch - -Patch21225: pci-Rework-ASPM-disable-code.patch - -#rhbz #757839 -Patch21230: net-sky2-88e8059-fix-link-speed.patch - #rhbz 717735 Patch21045: nfs-client-freezer.patch @@ -719,6 +700,9 @@ Patch21048: b44-Use-dev_kfree_skb_irq-in-b44_tx.patch #rhbz 771006 Patch21050: thp-reduce-khugepaged-freezing-latency.patch +#rhbz 728607 +Patch21060: elantech.patch + #rhbz 770233 Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch @@ -750,6 +734,22 @@ Patch21085: proc-clean-up-and-fix-proc-pid-mem-handling.patch #rhbz 782687 Patch21086: loop-prevent-information-leak-after-failed-read.patch +#backport brcm80211 from 3.2-rc1 +Patch21090: brcm80211.patch +Patch21091: bcma-brcmsmac-compat.patch + +# rhbz 754907 +Patch21100: cciss-fix-irqf-shared.patch +Patch21101: hpsa-add-irqf-shared.patch + +#rhbz 731365 +Patch21220: mac80211_offchannel_rework_revert.patch + +Patch21225: pci-Rework-ASPM-disable-code.patch + +#rhbz #757839 +Patch21230: net-sky2-88e8059-fix-link-speed.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root From 11fe6a0fc7d13790b690495673bf2d95371b3ede Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 20 Jan 2012 09:44:37 -0500 Subject: [PATCH 287/397] Add mac80211 deauth fix pointed out by Stanislaw Gruszka --- kernel.spec | 7 + ...1-fix-work-removal-on-deauth-request.patch | 154 ++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 mac80211-fix-work-removal-on-deauth-request.patch diff --git a/kernel.spec b/kernel.spec index a08db415f..bb7caacf9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -747,6 +747,8 @@ Patch21220: mac80211_offchannel_rework_revert.patch Patch21225: pci-Rework-ASPM-disable-code.patch +Patch21227: mac80211-fix-work-removal-on-deauth-request.patch + #rhbz #757839 Patch21230: net-sky2-88e8059-fix-link-speed.patch @@ -1347,6 +1349,8 @@ ApplyPatch mac80211_offchannel_rework_revert.patch ApplyPatch pci-Rework-ASPM-disable-code.patch +ApplyPatch mac80211-fix-work-removal-on-deauth-request.patch + #rhbz #757839 ApplyPatch net-sky2-88e8059-fix-link-speed.patch @@ -2038,6 +2042,9 @@ fi # and build. %changelog +* Fri Jan 20 2012 Josh Boyer +- Add mac80211 deauth fix pointed out by Stanislaw Gruszka + * Wed Jan 18 2012 Josh Boyer 2.6.41.10-2 - Fix broken procfs backport (rhbz 782961) diff --git a/mac80211-fix-work-removal-on-deauth-request.patch b/mac80211-fix-work-removal-on-deauth-request.patch new file mode 100644 index 000000000..60b91d3cf --- /dev/null +++ b/mac80211-fix-work-removal-on-deauth-request.patch @@ -0,0 +1,154 @@ +Path: news.gmane.org!not-for-mail +From: Johannes Berg +Newsgroups: gmane.linux.kernel.wireless.general +Subject: [PATCH 3.3] mac80211: fix work removal on deauth request +Date: Wed, 18 Jan 2012 14:10:25 +0100 +Lines: 107 +Approved: news@gmane.org +Message-ID: <1326892225.4778.5.camel@jlt3.sipsolutions.net> +NNTP-Posting-Host: lo.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 7bit +X-Trace: dough.gmane.org 1326892249 18013 80.91.229.12 (18 Jan 2012 13:10:49 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Wed, 18 Jan 2012 13:10:49 +0000 (UTC) +Cc: linux-wireless , + Pontus Fuchs +To: John Linville +Original-X-From: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Wed Jan 18 14:10:44 2012 +Return-path: +Envelope-to: glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1RnVHo-00044l-Aq + for glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Wed, 18 Jan 2012 14:10:44 +0100 +Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand + id S1757410Ab2ARNK3 (ORCPT + ); + Wed, 18 Jan 2012 08:10:29 -0500 +Original-Received: from he.sipsolutions.net ([78.46.109.217]:45023 "EHLO + sipsolutions.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1754365Ab2ARNK2 (ORCPT + ); + Wed, 18 Jan 2012 08:10:28 -0500 +Original-Received: by sipsolutions.net with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) + (Exim 4.77) + (envelope-from ) + id 1RnVHW-0004hf-Lx; Wed, 18 Jan 2012 14:10:26 +0100 +X-Mailer: Evolution 2.30.3 +Original-Sender: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Xref: news.gmane.org gmane.linux.kernel.wireless.general:84095 +Archived-At: + +From: Johannes Berg + +When deauth is requested while an auth or assoc +work item is in progress, we currently delete it +without regard for any state it might need to +clean up. Fix it by cleaning up for those items. + +In the case Pontus found, the problem manifested +itself as such: + +authenticate with 00:23:69:aa:dd:7b (try 1) +authenticated +failed to insert Dummy STA entry for the AP (error -17) +deauthenticating from 00:23:69:aa:dd:7b by local choice (reason=2) + +It could also happen differently if the driver +uses the tx_sync callback. + +We can't just call the ->done() method of the work +items because that will lock up due to the locking +in cfg80211. This fix isn't very clean, but that +seems acceptable since I have patches pending to +remove this code completely. + +Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Reported-by: Pontus Fuchs +Tested-by: Pontus Fuchs +Signed-off-by: Johannes Berg +--- + net/mac80211/mlme.c | 38 +++++++++++++++++++++++++++----------- + 1 file changed, 27 insertions(+), 11 deletions(-) + +--- a/net/mac80211/mlme.c 2012-01-18 14:04:33.000000000 +0100 ++++ b/net/mac80211/mlme.c 2012-01-18 14:04:34.000000000 +0100 +@@ -2750,7 +2750,6 @@ int ieee80211_mgd_deauth(struct ieee8021 + { + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; +- struct ieee80211_work *wk; + u8 bssid[ETH_ALEN]; + bool assoc_bss = false; + +@@ -2763,30 +2762,47 @@ int ieee80211_mgd_deauth(struct ieee8021 + assoc_bss = true; + } else { + bool not_auth_yet = false; ++ struct ieee80211_work *tmp, *wk = NULL; + + mutex_unlock(&ifmgd->mtx); + + mutex_lock(&local->mtx); +- list_for_each_entry(wk, &local->work_list, list) { +- if (wk->sdata != sdata) ++ list_for_each_entry(tmp, &local->work_list, list) { ++ if (tmp->sdata != sdata) + continue; + +- if (wk->type != IEEE80211_WORK_DIRECT_PROBE && +- wk->type != IEEE80211_WORK_AUTH && +- wk->type != IEEE80211_WORK_ASSOC && +- wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) ++ if (tmp->type != IEEE80211_WORK_DIRECT_PROBE && ++ tmp->type != IEEE80211_WORK_AUTH && ++ tmp->type != IEEE80211_WORK_ASSOC && ++ tmp->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) + continue; + +- if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN)) ++ if (memcmp(req->bss->bssid, tmp->filter_ta, ETH_ALEN)) + continue; + +- not_auth_yet = wk->type == IEEE80211_WORK_DIRECT_PROBE; +- list_del_rcu(&wk->list); +- free_work(wk); ++ not_auth_yet = tmp->type == IEEE80211_WORK_DIRECT_PROBE; ++ list_del_rcu(&tmp->list); ++ synchronize_rcu(); ++ wk = tmp; + break; + } + mutex_unlock(&local->mtx); + ++ if (wk && wk->type == IEEE80211_WORK_ASSOC) { ++ /* clean up dummy sta & TX sync */ ++ sta_info_destroy_addr(wk->sdata, wk->filter_ta); ++ if (wk->assoc.synced) ++ drv_finish_tx_sync(local, wk->sdata, ++ wk->filter_ta, ++ IEEE80211_TX_SYNC_ASSOC); ++ } else if (wk && wk->type == IEEE80211_WORK_AUTH) { ++ if (wk->probe_auth.synced) ++ drv_finish_tx_sync(local, wk->sdata, ++ wk->filter_ta, ++ IEEE80211_TX_SYNC_AUTH); ++ } ++ kfree(wk); ++ + /* + * If somebody requests authentication and we haven't + * sent out an auth frame yet there's no need to send + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + From c0e19331fbfeac8e333b1ed570514ebb687c265c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 23 Jan 2012 09:41:28 -0500 Subject: [PATCH 288/397] Fix NULL pointer dereference in sym53c8xx module (rhbz 781625) --- ...ix-NULL-pointer-dereference-in-slave.patch | 35 +++++++++++++++++++ kernel.spec | 9 +++++ 2 files changed, 44 insertions(+) create mode 100644 SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch diff --git a/SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch b/SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch new file mode 100644 index 000000000..369012744 --- /dev/null +++ b/SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch @@ -0,0 +1,35 @@ +From cced5041ed5a2d1352186510944b0ddfbdbe4c0b Mon Sep 17 00:00:00 2001 +From: Stratos Psomadakis +Date: Sun, 4 Dec 2011 02:23:54 +0200 +Subject: [PATCH] [SCSI] sym53c8xx: Fix NULL pointer dereference in + slave_destroy + +sym53c8xx_slave_destroy unconditionally assumes that sym53c8xx_slave_alloc has +succesesfully allocated a sym_lcb. This can lead to a NULL pointer dereference +(exposed by commit 4e6c82b). + +Signed-off-by: Stratos Psomadakis +Cc: stable@vger.kernel.org +Signed-off-by: James Bottomley +--- + drivers/scsi/sym53c8xx_2/sym_glue.c | 4 ++++ + 1 files changed, 4 insertions(+), 0 deletions(-) + +diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c +index b4543f5..36d1ed7 100644 +--- a/drivers/scsi/sym53c8xx_2/sym_glue.c ++++ b/drivers/scsi/sym53c8xx_2/sym_glue.c +@@ -839,6 +839,10 @@ static void sym53c8xx_slave_destroy(struct scsi_device *sdev) + struct sym_lcb *lp = sym_lp(tp, sdev->lun); + unsigned long flags; + ++ /* if slave_alloc returned before allocating a sym_lcb, return */ ++ if (!lp) ++ return; ++ + spin_lock_irqsave(np->s.host->host_lock, flags); + + if (lp->busy_itlq || lp->busy_itl) { +-- +1.7.7.5 + diff --git a/kernel.spec b/kernel.spec index bb7caacf9..07761f6cc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -749,6 +749,9 @@ Patch21225: pci-Rework-ASPM-disable-code.patch Patch21227: mac80211-fix-work-removal-on-deauth-request.patch +#rhbz 781625 +Patch21228: SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch + #rhbz #757839 Patch21230: net-sky2-88e8059-fix-link-speed.patch @@ -1395,6 +1398,9 @@ ApplyPatch proc-clean-up-and-fix-proc-pid-mem-handling.patch #rhbz 782687 ApplyPatch loop-prevent-information-leak-after-failed-read.patch +#rhbz 781625 +ApplyPatch SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch + # END OF PATCH APPLICATIONS %endif @@ -2042,6 +2048,9 @@ fi # and build. %changelog +* Mon Jan 23 2012 Josh Boyer +- Fix NULL pointer dereference in sym53c8xx module (rhbz 781625) + * Fri Jan 20 2012 Josh Boyer - Add mac80211 deauth fix pointed out by Stanislaw Gruszka From b25c4b32fc1952323f6ddbe104d7d92d128a4bf9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 23 Jan 2012 10:13:34 -0500 Subject: [PATCH 289/397] Bump for build --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 07761f6cc..9d2d7da07 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -2048,7 +2048,7 @@ fi # and build. %changelog -* Mon Jan 23 2012 Josh Boyer +* Mon Jan 23 2012 Josh Boyer 2.6.41.10-3 - Fix NULL pointer dereference in sym53c8xx module (rhbz 781625) * Fri Jan 20 2012 Josh Boyer From 8c3a2d06dc1aec56f0b0bff92e81df4c512b8aa6 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 30 Jan 2012 12:01:31 -0500 Subject: [PATCH 290/397] Rebase to 3.2.2 --- .gitignore | 1 + ...direct-reclaim-for-higher-order-allo.patch | 54 - ...-compaction-if-compaction-can-procee.patch | 81 - 01-block-add-and-use-scsi_blk_cmd_ioctl.patch | 166 - ...passthrough-ioctls-on-partition-devs.patch | 165 - ...wd-ioctls-from-LVs-to-underlying-dev.patch | 91 - Bluetooth-Add-support-for-BCM20702A0.patch | 15 - ...m-Set-input-bits-before-registration.patch | 131 - ...ix-NULL-pointer-dereference-in-slave.patch | 35 - add-appleir-usb-driver.patch | 701 - alps.patch | 243 +- arm-tegra-usb-no-reset.patch | 29 - b44-Use-dev_kfree_skb_irq-in-b44_tx.patch | 62 - bcma-brcmsmac-compat.patch | 35 - ...r-vlan-pkts-not-received-in-promisco.patch | 63 - ...-remove-bogus-unlikely-on-vlan-check.patch | 39 - brcm80211.patch | 97238 ---------------- cciss-fix-irqf-shared.patch | 39 - config-arm-generic | 14 + config-arm-imx | 3 + config-arm-omap-generic | 22 + config-arm-tegra | 7 + config-debug | 5 +- config-generic | 1035 +- config-nodebug | 5 +- config-powerpc-generic | 97 +- config-powerpc32-generic | 64 +- config-powerpc64 | 69 +- config-s390x | 2 + config-sparc64-generic | 14 +- config-x86-32-generic | 9 +- config-x86-generic | 25 +- config-x86_64-generic | 15 +- drm-i915-sdvo-lvds-is-digital.patch | 83 - drm-lower-severity-radeon-lockup.diff | 13 - drm-nouveau-updates.patch | 8526 -- elantech.patch | 2180 - epoll-limit-paths.patch | 8 +- ...ort-check-none-nocheck-mount-options.patch | 51 + ...block-device-if-fsync-called-on-part.patch | 106 + hvcs_pi_buf_alloc.patch | 43 - kernel.spec | 170 +- linux-2.6-32bit-mmap-exec-randomization.patch | 27 +- linux-2.6-debug-taint-vm.patch | 51 - linux-2.6-e1000-ich9-montevina.patch | 28 +- linux-2.6-i386-nx-emulation.patch | 22 - linux-2.6-intel-iommu-igfx.patch | 35 +- ...t-information-leak-after-failed-read.patch | 41 - mac80211_offchannel_rework_revert.patch | 594 - media-dib0700-correct-error-message.patch | 103 - ...onous-compaction-for-THP-allocations.patch | 115 - msi-irq-sysfs-warning.patch | 87 + net-sky2-88e8059-fix-link-speed.patch | 42 - nfs-client-freezer.patch | 112 +- ...ean-up-and-fix-proc-pid-mem-handling.patch | 268 - rcu-avoid-just-onlined-cpu-resched.patch | 47 - rcu-reintroduce-missing-calls.patch | 632 + rcutree-avoid-false-quiescent-states.patch | 67 - ...ds_sock_lock-BH-rather-than-IRQ-safe.patch | 116 + rtl8192cu-Fix-WARNING-on-suspend-resume.patch | 54 +- samsung-laptop-brightness-fixes-3.2.patch | 238 - sources | 4 +- sysfs-msi-irq-per-device.patch | 239 + thp-reduce-khugepaged-freezing-latency.patch | 54 - tpm_tis-delay-after-aborting-cmd.patch | 17 + udlfb-bind-framebuffer-to-interface.patch | 33 - utrace.patch | 1652 +- x86-code-dump-fix-truncation.patch | 73 - 68 files changed, 2823 insertions(+), 113682 deletions(-) delete mode 100644 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch delete mode 100644 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch delete mode 100644 01-block-add-and-use-scsi_blk_cmd_ioctl.patch delete mode 100644 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch delete mode 100644 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch delete mode 100644 Bluetooth-Add-support-for-BCM20702A0.patch delete mode 100644 HID-wacom-Set-input-bits-before-registration.patch delete mode 100644 SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch delete mode 100644 add-appleir-usb-driver.patch delete mode 100644 arm-tegra-usb-no-reset.patch delete mode 100644 b44-Use-dev_kfree_skb_irq-in-b44_tx.patch delete mode 100644 bcma-brcmsmac-compat.patch delete mode 100644 be2net-non-member-vlan-pkts-not-received-in-promisco.patch delete mode 100644 benet-remove-bogus-unlikely-on-vlan-check.patch delete mode 100644 brcm80211.patch delete mode 100644 cciss-fix-irqf-shared.patch delete mode 100644 drm-i915-sdvo-lvds-is-digital.patch delete mode 100644 drm-lower-severity-radeon-lockup.diff delete mode 100644 elantech.patch create mode 100644 ext4-Support-check-none-nocheck-mount-options.patch create mode 100644 fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch delete mode 100644 hvcs_pi_buf_alloc.patch delete mode 100644 linux-2.6-debug-taint-vm.patch delete mode 100644 loop-prevent-information-leak-after-failed-read.patch delete mode 100644 mac80211_offchannel_rework_revert.patch delete mode 100644 media-dib0700-correct-error-message.patch delete mode 100644 mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch create mode 100644 msi-irq-sysfs-warning.patch delete mode 100644 net-sky2-88e8059-fix-link-speed.patch delete mode 100644 proc-clean-up-and-fix-proc-pid-mem-handling.patch delete mode 100644 rcu-avoid-just-onlined-cpu-resched.patch create mode 100644 rcu-reintroduce-missing-calls.patch delete mode 100644 rcutree-avoid-false-quiescent-states.patch create mode 100644 rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch delete mode 100644 samsung-laptop-brightness-fixes-3.2.patch create mode 100644 sysfs-msi-irq-per-device.patch delete mode 100644 thp-reduce-khugepaged-freezing-latency.patch create mode 100644 tpm_tis-delay-after-aborting-cmd.patch delete mode 100644 udlfb-bind-framebuffer-to-interface.patch delete mode 100644 x86-code-dump-fix-truncation.patch diff --git a/.gitignore b/.gitignore index edb6bec0a..a23ef2db8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ clog +*.xz *.bz2 *.rpm *.orig diff --git a/0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch b/0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch deleted file mode 100644 index 77777f012..000000000 --- a/0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 6b7025ea927d290a59d2772828435c1893f0267f Mon Sep 17 00:00:00 2001 -From: Rik van Riel -Date: Fri, 7 Oct 2011 16:17:22 +0100 -Subject: [PATCH 1/2] mm: vmscan: Limit direct reclaim for higher order - allocations - -When suffering from memory fragmentation due to unfreeable pages, -THP page faults will repeatedly try to compact memory. Due to the -unfreeable pages, compaction fails. - -Needless to say, at that point page reclaim also fails to create -free contiguous 2MB areas. However, that doesn't stop the current -code from trying, over and over again, and freeing a minimum of 4MB -(2UL << sc->order pages) at every single invocation. - -This resulted in my 12GB system having 2-3GB free memory, a -corresponding amount of used swap and very sluggish response times. - -This can be avoided by having the direct reclaim code not reclaim from -zones that already have plenty of free memory available for compaction. - -If compaction still fails due to unmovable memory, doing additional -reclaim will only hurt the system, not help. - -Signed-off-by: Rik van Riel -Signed-off-by: Mel Gorman ---- - mm/vmscan.c | 10 ++++++++++ - 1 files changed, 10 insertions(+), 0 deletions(-) - -diff --git a/mm/vmscan.c b/mm/vmscan.c -index 6072d74..8c03534 100644 ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -2022,6 +2022,16 @@ static void shrink_zones(int priority, struct zonelist *zonelist, - continue; - if (zone->all_unreclaimable && priority != DEF_PRIORITY) - continue; /* Let kswapd poll it */ -+ if (COMPACTION_BUILD) { -+ /* -+ * If we already have plenty of memory free -+ * for compaction, don't free any more. -+ */ -+ if (sc->order > PAGE_ALLOC_COSTLY_ORDER && -+ (compaction_suitable(zone, sc->order) || -+ compaction_deferred(zone))) -+ continue; -+ } - /* - * This steals pages from memory cgroups over softlimit - * and returns the number of reclaimed pages and --- -1.7.6.4 - diff --git a/0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch b/0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch deleted file mode 100644 index e74b64d91..000000000 --- a/0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch +++ /dev/null @@ -1,81 +0,0 @@ -From c01043c9aa51a63bd01c60e53494ca4a7e994542 Mon Sep 17 00:00:00 2001 -From: Mel Gorman -Date: Fri, 7 Oct 2011 16:17:23 +0100 -Subject: [PATCH 2/2] mm: Abort reclaim/compaction if compaction can proceed - -If compaction can proceed, shrink_zones() stops doing any work but -the callers still shrink_slab(), raises the priority and potentially -sleeps. This patch aborts direct reclaim/compaction entirely if -compaction can proceed. - -Signed-off-by: Mel Gorman ---- - mm/vmscan.c | 20 ++++++++++++++++---- - 1 files changed, 16 insertions(+), 4 deletions(-) - -diff --git a/mm/vmscan.c b/mm/vmscan.c -index 8c03534..b295a38 100644 ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -2000,14 +2000,19 @@ restart: - * - * If a zone is deemed to be full of pinned pages then just give it a light - * scan then give up on it. -+ * -+ * This function returns true if a zone is being reclaimed for a costly -+ * high-order allocation and compaction is either ready to begin or deferred. -+ * This indicates to the caller that it should retry the allocation or fail. - */ --static void shrink_zones(int priority, struct zonelist *zonelist, -+static bool shrink_zones(int priority, struct zonelist *zonelist, - struct scan_control *sc) - { - struct zoneref *z; - struct zone *zone; - unsigned long nr_soft_reclaimed; - unsigned long nr_soft_scanned; -+ bool should_abort_reclaim = false; - - for_each_zone_zonelist_nodemask(zone, z, zonelist, - gfp_zone(sc->gfp_mask), sc->nodemask) { -@@ -2025,12 +2030,15 @@ static void shrink_zones(int priority, struct zonelist *zonelist, - if (COMPACTION_BUILD) { - /* - * If we already have plenty of memory free -- * for compaction, don't free any more. -+ * for compaction in this zone , don't free any -+ * more. - */ - if (sc->order > PAGE_ALLOC_COSTLY_ORDER && - (compaction_suitable(zone, sc->order) || -- compaction_deferred(zone))) -+ compaction_deferred(zone))) { -+ should_abort_reclaim = true; - continue; -+ } - } - /* - * This steals pages from memory cgroups over softlimit -@@ -2049,6 +2057,8 @@ static void shrink_zones(int priority, struct zonelist *zonelist, - - shrink_zone(priority, zone, sc); - } -+ -+ return should_abort_reclaim; - } - - static bool zone_reclaimable(struct zone *zone) -@@ -2113,7 +2123,9 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, - sc->nr_scanned = 0; - if (!priority) - disable_swap_token(sc->mem_cgroup); -- shrink_zones(priority, zonelist, sc); -+ if (shrink_zones(priority, zonelist, sc)) -+ break; -+ - /* - * Don't shrink slabs when reclaiming memory from - * over limit cgroups --- -1.7.6.4 - diff --git a/01-block-add-and-use-scsi_blk_cmd_ioctl.patch b/01-block-add-and-use-scsi_blk_cmd_ioctl.patch deleted file mode 100644 index fdf4c5039..000000000 --- a/01-block-add-and-use-scsi_blk_cmd_ioctl.patch +++ /dev/null @@ -1,166 +0,0 @@ -From 6051b3759d3d4b70d33a7be70ab6b86ed3559224 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 16 Jan 2012 17:12:58 +0100 -Subject: [PATCH 1/3] block: add and use scsi_blk_cmd_ioctl - -Introduce a wrapper around scsi_cmd_ioctl that takes a block device. - -The function will then be enhanced to detect partition block devices -and, in that case, subject the ioctls to whitelisting. - -[ Cherry picked from 6ad62f051ef784a48a6103af289f91b5c472e955 ] - -Cc: stable@kernel.org -Cc: linux-scsi@vger.kernel.org -Cc: Jens Axboe -Cc: James Bottomley -Signed-off-by: Paolo Bonzini -Signed-off-by: Linus Torvalds ---- - block/scsi_ioctl.c | 7 +++++++ - drivers/block/cciss.c | 6 +++--- - drivers/block/ub.c | 3 +-- - drivers/block/virtio_blk.c | 4 ++-- - drivers/cdrom/cdrom.c | 3 +-- - drivers/ide/ide-floppy_ioctl.c | 3 +-- - drivers/scsi/sd.c | 2 +- - include/linux/blkdev.h | 2 ++ - 8 files changed, 18 insertions(+), 12 deletions(-) - -diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c -index 4f4230b..57ac937 100644 ---- a/block/scsi_ioctl.c -+++ b/block/scsi_ioctl.c -@@ -691,6 +691,13 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod - } - EXPORT_SYMBOL(scsi_cmd_ioctl); - -+int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode, -+ unsigned int cmd, void __user *arg) -+{ -+ return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg); -+} -+EXPORT_SYMBOL(scsi_cmd_blk_ioctl); -+ - static int __init blk_scsi_ioctl_init(void) - { - blk_set_cmd_filter_defaults(&blk_default_cmd_filter); -diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c -index c2f9b3e..1dab802 100644 ---- a/drivers/block/cciss.c -+++ b/drivers/block/cciss.c -@@ -1716,7 +1716,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, - case CCISS_BIG_PASSTHRU: - return cciss_bigpassthru(h, argp); - -- /* scsi_cmd_ioctl handles these, below, though some are not */ -+ /* scsi_cmd_blk_ioctl handles these, below, though some are not */ - /* very meaningful for cciss. SG_IO is the main one people want. */ - - case SG_GET_VERSION_NUM: -@@ -1727,9 +1727,9 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, - case SG_EMULATED_HOST: - case SG_IO: - case SCSI_IOCTL_SEND_COMMAND: -- return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp); -+ return scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); - -- /* scsi_cmd_ioctl would normally handle these, below, but */ -+ /* scsi_cmd_blk_ioctl would normally handle these, below, but */ - /* they aren't a good fit for cciss, as CD-ROMs are */ - /* not supported, and we don't have any bus/target/lun */ - /* which we present to the kernel. */ -diff --git a/drivers/block/ub.c b/drivers/block/ub.c -index 0e376d4..7333b9e 100644 ---- a/drivers/block/ub.c -+++ b/drivers/block/ub.c -@@ -1744,12 +1744,11 @@ static int ub_bd_release(struct gendisk *disk, fmode_t mode) - static int ub_bd_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) - { -- struct gendisk *disk = bdev->bd_disk; - void __user *usermem = (void __user *) arg; - int ret; - - mutex_lock(&ub_mutex); -- ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem); -+ ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, usermem); - mutex_unlock(&ub_mutex); - - return ret; -diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c -index 079c088..5d7a934 100644 ---- a/drivers/block/virtio_blk.c -+++ b/drivers/block/virtio_blk.c -@@ -236,8 +236,8 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, - if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI)) - return -ENOTTY; - -- return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, -- (void __user *)data); -+ return scsi_cmd_blk_ioctl(bdev, mode, cmd, -+ (void __user *)data); - } - - /* We provide getgeo only to please some old bootloader/partitioning tools */ -diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c -index f997c27..cedb231 100644 ---- a/drivers/cdrom/cdrom.c -+++ b/drivers/cdrom/cdrom.c -@@ -2747,12 +2747,11 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev, - { - void __user *argp = (void __user *)arg; - int ret; -- struct gendisk *disk = bdev->bd_disk; - - /* - * Try the generic SCSI command ioctl's first. - */ -- ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp); -+ ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); - if (ret != -ENOTTY) - return ret; - -diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c -index d267b7a..a22ca84 100644 ---- a/drivers/ide/ide-floppy_ioctl.c -+++ b/drivers/ide/ide-floppy_ioctl.c -@@ -292,8 +292,7 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev, - * and CDROM_SEND_PACKET (legacy) ioctls - */ - if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND) -- err = scsi_cmd_ioctl(bdev->bd_disk->queue, bdev->bd_disk, -- mode, cmd, argp); -+ err = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); - - if (err == -ENOTTY) - err = generic_ide_ioctl(drive, bdev, cmd, arg); -diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c -index 953773c..c88885d 100644 ---- a/drivers/scsi/sd.c -+++ b/drivers/scsi/sd.c -@@ -1095,7 +1095,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, - error = scsi_ioctl(sdp, cmd, p); - break; - default: -- error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p); -+ error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p); - if (error != -ENOTTY) - break; - error = scsi_ioctl(sdp, cmd, p); -diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h -index 5e30b45..aa829a4 100644 ---- a/include/linux/blkdev.h -+++ b/include/linux/blkdev.h -@@ -675,6 +675,8 @@ extern int blk_insert_cloned_request(struct request_queue *q, - struct request *rq); - extern void blk_delay_queue(struct request_queue *, unsigned long); - extern void blk_recount_segments(struct request_queue *, struct bio *); -+extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t, -+ unsigned int, void __user *); - extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t, - unsigned int, void __user *); - extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t, --- -1.7.7.5 - diff --git a/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch b/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch deleted file mode 100644 index 942e2a007..000000000 --- a/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch +++ /dev/null @@ -1,165 +0,0 @@ -From e773daff833c61e0ce22d62b7d1bb7b82f4222d0 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 16 Jan 2012 17:12:59 +0100 -Subject: [PATCH 2/3] block: fail SCSI passthrough ioctls on partition devices - -Linux allows executing the SG_IO ioctl on a partition or LVM volume, and -will pass the command to the underlying block device. This is -well-known, but it is also a large security problem when (via Unix -permissions, ACLs, SELinux or a combination thereof) a program or user -needs to be granted access only to part of the disk. - -This patch lets partitions forward a small set of harmless ioctls; -others are logged with printk so that we can see which ioctls are -actually sent. In my tests only CDROM_GET_CAPABILITY actually occurred. -Of course it was being sent to a (partition on a) hard disk, so it would -have failed with ENOTTY and the patch isn't changing anything in -practice. Still, I'm treating it specially to avoid spamming the logs. - -In principle, this restriction should include programs running with -CAP_SYS_RAWIO. If for example I let a program access /dev/sda2 and -/dev/sdb, it still should not be able to read/write outside the -boundaries of /dev/sda2 independent of the capabilities. However, for -now programs with CAP_SYS_RAWIO will still be allowed to send the -ioctls. Their actions will still be logged. - -This patch does not affect the non-libata IDE driver. That driver -however already tests for bd != bd->bd_contains before issuing some -ioctl; it could be restricted further to forbid these ioctls even for -programs running with CAP_SYS_ADMIN/CAP_SYS_RAWIO. - -[ Cherry picked from 3ed4e7ba4be8c72051d87dcb2dec279d97a18d41 - - Changes with respect to 3.3: return -ENOTTY from scsi_verify_blk_ioctl - and -ENOIOCTLCMD from sd_compat_ioctl. ] - -Cc: stable@kernel.org -Cc: linux-scsi@vger.kernel.org -Cc: Jens Axboe -Cc: James Bottomley -Signed-off-by: Paolo Bonzini -[ Make it also print the command name when warning - Linus ] -Signed-off-by: Linus Torvalds ---- - block/scsi_ioctl.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ - drivers/scsi/sd.c | 11 +++++++++-- - include/linux/blkdev.h | 1 + - 3 files changed, 55 insertions(+), 2 deletions(-) - -diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c -index 57ac937..5ef1f4c 100644 ---- a/block/scsi_ioctl.c -+++ b/block/scsi_ioctl.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -691,9 +692,53 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod - } - EXPORT_SYMBOL(scsi_cmd_ioctl); - -+int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd) -+{ -+ if (bd && bd == bd->bd_contains) -+ return 0; -+ -+ /* Actually none of these is particularly useful on a partition, -+ * but they are safe. -+ */ -+ switch (cmd) { -+ case SCSI_IOCTL_GET_IDLUN: -+ case SCSI_IOCTL_GET_BUS_NUMBER: -+ case SCSI_IOCTL_GET_PCI: -+ case SCSI_IOCTL_PROBE_HOST: -+ case SG_GET_VERSION_NUM: -+ case SG_SET_TIMEOUT: -+ case SG_GET_TIMEOUT: -+ case SG_GET_RESERVED_SIZE: -+ case SG_SET_RESERVED_SIZE: -+ case SG_EMULATED_HOST: -+ return 0; -+ case CDROM_GET_CAPABILITY: -+ /* Keep this until we remove the printk below. udev sends it -+ * and we do not want to spam dmesg about it. CD-ROMs do -+ * not have partitions, so we get here only for disks. -+ */ -+ return -ENOTTY; -+ default: -+ break; -+ } -+ -+ /* In particular, rule out all resets and host-specific ioctls. */ -+ printk_ratelimited(KERN_WARNING -+ "%s: sending ioctl %x to a partition!\n", current->comm, cmd); -+ -+ return capable(CAP_SYS_RAWIO) ? 0 : -ENOTTY; -+} -+EXPORT_SYMBOL(scsi_verify_blk_ioctl); -+ - int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode, - unsigned int cmd, void __user *arg) - { -+ int ret; -+ -+ ret = scsi_verify_blk_ioctl(bd, cmd); -+ if (ret < 0) -+ return ret; -+ - return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg); - } - EXPORT_SYMBOL(scsi_cmd_blk_ioctl); -diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c -index c88885d..7d8b5d8 100644 ---- a/drivers/scsi/sd.c -+++ b/drivers/scsi/sd.c -@@ -1073,6 +1073,10 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, - SCSI_LOG_IOCTL(1, printk("sd_ioctl: disk=%s, cmd=0x%x\n", - disk->disk_name, cmd)); - -+ error = scsi_verify_blk_ioctl(bdev, cmd); -+ if (error < 0) -+ return error; -+ - /* - * If we are in the middle of error recovery, don't let anyone - * else try and use this device. Also, if error recovery fails, it -@@ -1265,6 +1269,11 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) - { - struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device; -+ int ret; -+ -+ ret = scsi_verify_blk_ioctl(bdev, cmd); -+ if (ret < 0) -+ return -ENOIOCTLCMD; - - /* - * If we are in the middle of error recovery, don't let anyone -@@ -1276,8 +1285,6 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, - return -ENODEV; - - if (sdev->host->hostt->compat_ioctl) { -- int ret; -- - ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg); - - return ret; -diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h -index aa829a4..8b7a19e 100644 ---- a/include/linux/blkdev.h -+++ b/include/linux/blkdev.h -@@ -675,6 +675,7 @@ extern int blk_insert_cloned_request(struct request_queue *q, - struct request *rq); - extern void blk_delay_queue(struct request_queue *, unsigned long); - extern void blk_recount_segments(struct request_queue *, struct bio *); -+extern int scsi_verify_blk_ioctl(struct block_device *, unsigned int); - extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t, - unsigned int, void __user *); - extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t, --- -1.7.7.5 - diff --git a/03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch b/03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch deleted file mode 100644 index 129edd974..000000000 --- a/03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch +++ /dev/null @@ -1,91 +0,0 @@ -From bf50a5715cac3b85f3bd33f184f7c031debabe0b Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 16 Jan 2012 17:13:00 +0100 -Subject: [PATCH 3/3] dm: do not forward ioctls from logical volumes to the - underlying device - -A logical volume can map to just part of underlying physical volume. -In this case, it must be treated like a partition. - -Based on a patch from Alasdair G Kergon. - -[ Cherry picked from 95113a17a2a1eb06151dc698dca9bcc4a29e4fbb ] - -Cc: stable@kernel.org -Cc: Alasdair G Kergon -Cc: dm-devel@redhat.com -Cc: linux-scsi@vger.kernel.org -Signed-off-by: Paolo Bonzini -Signed-off-by: Linus Torvalds ---- - drivers/md/dm-flakey.c | 11 ++++++++++- - drivers/md/dm-linear.c | 12 +++++++++++- - drivers/md/dm-mpath.c | 6 ++++++ - 3 files changed, 27 insertions(+), 2 deletions(-) - -diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c -index f84c080..9fb18c1 100644 ---- a/drivers/md/dm-flakey.c -+++ b/drivers/md/dm-flakey.c -@@ -368,8 +368,17 @@ static int flakey_status(struct dm_target *ti, status_type_t type, - static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg) - { - struct flakey_c *fc = ti->private; -+ struct dm_dev *dev = fc->dev; -+ int r = 0; - -- return __blkdev_driver_ioctl(fc->dev->bdev, fc->dev->mode, cmd, arg); -+ /* -+ * Only pass ioctls through if the device sizes match exactly. -+ */ -+ if (fc->start || -+ ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) -+ r = scsi_verify_blk_ioctl(NULL, cmd); -+ -+ return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg); - } - - static int flakey_merge(struct dm_target *ti, struct bvec_merge_data *bvm, -diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c -index 3921e3b..9728839 100644 ---- a/drivers/md/dm-linear.c -+++ b/drivers/md/dm-linear.c -@@ -116,7 +116,17 @@ static int linear_ioctl(struct dm_target *ti, unsigned int cmd, - unsigned long arg) - { - struct linear_c *lc = (struct linear_c *) ti->private; -- return __blkdev_driver_ioctl(lc->dev->bdev, lc->dev->mode, cmd, arg); -+ struct dm_dev *dev = lc->dev; -+ int r = 0; -+ -+ /* -+ * Only pass ioctls through if the device sizes match exactly. -+ */ -+ if (lc->start || -+ ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) -+ r = scsi_verify_blk_ioctl(NULL, cmd); -+ -+ return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg); - } - - static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm, -diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c -index 5e0090e..801d92d 100644 ---- a/drivers/md/dm-mpath.c -+++ b/drivers/md/dm-mpath.c -@@ -1520,6 +1520,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, - - spin_unlock_irqrestore(&m->lock, flags); - -+ /* -+ * Only pass ioctls through if the device sizes match exactly. -+ */ -+ if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) -+ r = scsi_verify_blk_ioctl(NULL, cmd); -+ - return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); - } - --- -1.7.7.5 - diff --git a/Bluetooth-Add-support-for-BCM20702A0.patch b/Bluetooth-Add-support-for-BCM20702A0.patch deleted file mode 100644 index 1e579342c..000000000 --- a/Bluetooth-Add-support-for-BCM20702A0.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c -index f9b7260..28a5876 100644 ---- a/drivers/bluetooth/btusb.c -+++ b/drivers/bluetooth/btusb.c -@@ -100,6 +100,10 @@ static struct usb_device_id btusb_table[] = { - /* Canyon CN-BTU1 with HID interfaces */ - { USB_DEVICE(0x0c10, 0x0000) }, - -+ /* Broadcom BCM20702A0 */ -+ { USB_DEVICE(0x0a5c, 0x21e3) }, -+ { USB_DEVICE(0x413c, 0x8197) }, -+ - { } /* Terminating entry */ - }; - diff --git a/HID-wacom-Set-input-bits-before-registration.patch b/HID-wacom-Set-input-bits-before-registration.patch deleted file mode 100644 index 3cd178631..000000000 --- a/HID-wacom-Set-input-bits-before-registration.patch +++ /dev/null @@ -1,131 +0,0 @@ -From b28ae436288861916de0019a81b9817366fe35a9 Mon Sep 17 00:00:00 2001 -From: David Herrmann -Date: Sat, 8 Oct 2011 23:20:17 +0200 -Subject: [PATCH] HID: wacom: Set input bits before registration - -We shouldn't change the event flags of input devices after they get registered. -Otherwise, udev will not get notified of these flags and cannot setup the -devices properly. -This fixes the probing to set the input event flags on the input_mapped callback -instead of the probe function. - -Reported-by: Bastien Nocera -Signed-off-by: David Herrmann -Tested-by: Bastien Nocera -Signed-off-by: Bastien Nocera -Signed-off-by: Jiri Kosina ---- - drivers/hid/hid-wacom.c | 80 +++++++++++++++++++++++++--------------------- - 1 files changed, 43 insertions(+), 37 deletions(-) - -diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c -index 72ca689..1492728 100644 ---- a/drivers/hid/hid-wacom.c -+++ b/drivers/hid/hid-wacom.c -@@ -304,11 +304,51 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, - return 1; - } - -+static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, -+ struct hid_field *field, struct hid_usage *usage, unsigned long **bit, -+ int *max) -+{ -+ struct input_dev *input = hi->input; -+ -+ __set_bit(INPUT_PROP_POINTER, input->propbit); -+ -+ /* Basics */ -+ input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); -+ -+ __set_bit(REL_WHEEL, input->relbit); -+ -+ __set_bit(BTN_TOOL_PEN, input->keybit); -+ __set_bit(BTN_TOUCH, input->keybit); -+ __set_bit(BTN_STYLUS, input->keybit); -+ __set_bit(BTN_STYLUS2, input->keybit); -+ __set_bit(BTN_LEFT, input->keybit); -+ __set_bit(BTN_RIGHT, input->keybit); -+ __set_bit(BTN_MIDDLE, input->keybit); -+ -+ /* Pad */ -+ input->evbit[0] |= BIT(EV_MSC); -+ -+ __set_bit(MSC_SERIAL, input->mscbit); -+ -+ __set_bit(BTN_0, input->keybit); -+ __set_bit(BTN_1, input->keybit); -+ __set_bit(BTN_TOOL_FINGER, input->keybit); -+ -+ /* Distance, rubber and mouse */ -+ __set_bit(BTN_TOOL_RUBBER, input->keybit); -+ __set_bit(BTN_TOOL_MOUSE, input->keybit); -+ -+ input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); -+ input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); -+ input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); -+ input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); -+ -+ return 0; -+} -+ - static int wacom_probe(struct hid_device *hdev, - const struct hid_device_id *id) - { -- struct hid_input *hidinput; -- struct input_dev *input; - struct wacom_data *wdata; - int ret; - -@@ -370,41 +410,6 @@ static int wacom_probe(struct hid_device *hdev, - goto err_ac; - } - #endif -- hidinput = list_entry(hdev->inputs.next, struct hid_input, list); -- input = hidinput->input; -- -- __set_bit(INPUT_PROP_POINTER, input->propbit); -- -- /* Basics */ -- input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); -- -- __set_bit(REL_WHEEL, input->relbit); -- -- __set_bit(BTN_TOOL_PEN, input->keybit); -- __set_bit(BTN_TOUCH, input->keybit); -- __set_bit(BTN_STYLUS, input->keybit); -- __set_bit(BTN_STYLUS2, input->keybit); -- __set_bit(BTN_LEFT, input->keybit); -- __set_bit(BTN_RIGHT, input->keybit); -- __set_bit(BTN_MIDDLE, input->keybit); -- -- /* Pad */ -- input->evbit[0] |= BIT(EV_MSC); -- -- __set_bit(MSC_SERIAL, input->mscbit); -- -- __set_bit(BTN_0, input->keybit); -- __set_bit(BTN_1, input->keybit); -- __set_bit(BTN_TOOL_FINGER, input->keybit); -- -- /* Distance, rubber and mouse */ -- __set_bit(BTN_TOOL_RUBBER, input->keybit); -- __set_bit(BTN_TOOL_MOUSE, input->keybit); -- -- input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); -- input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); -- input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); -- input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); - - return 0; - -@@ -448,6 +453,7 @@ static struct hid_driver wacom_driver = { - .probe = wacom_probe, - .remove = wacom_remove, - .raw_event = wacom_raw_event, -+ .input_mapped = wacom_input_mapped, - }; - - static int __init wacom_init(void) --- -1.7.7.1 - diff --git a/SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch b/SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch deleted file mode 100644 index 369012744..000000000 --- a/SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch +++ /dev/null @@ -1,35 +0,0 @@ -From cced5041ed5a2d1352186510944b0ddfbdbe4c0b Mon Sep 17 00:00:00 2001 -From: Stratos Psomadakis -Date: Sun, 4 Dec 2011 02:23:54 +0200 -Subject: [PATCH] [SCSI] sym53c8xx: Fix NULL pointer dereference in - slave_destroy - -sym53c8xx_slave_destroy unconditionally assumes that sym53c8xx_slave_alloc has -succesesfully allocated a sym_lcb. This can lead to a NULL pointer dereference -(exposed by commit 4e6c82b). - -Signed-off-by: Stratos Psomadakis -Cc: stable@vger.kernel.org -Signed-off-by: James Bottomley ---- - drivers/scsi/sym53c8xx_2/sym_glue.c | 4 ++++ - 1 files changed, 4 insertions(+), 0 deletions(-) - -diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c -index b4543f5..36d1ed7 100644 ---- a/drivers/scsi/sym53c8xx_2/sym_glue.c -+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c -@@ -839,6 +839,10 @@ static void sym53c8xx_slave_destroy(struct scsi_device *sdev) - struct sym_lcb *lp = sym_lp(tp, sdev->lun); - unsigned long flags; - -+ /* if slave_alloc returned before allocating a sym_lcb, return */ -+ if (!lp) -+ return; -+ - spin_lock_irqsave(np->s.host->host_lock, flags); - - if (lp->busy_itlq || lp->busy_itl) { --- -1.7.7.5 - diff --git a/add-appleir-usb-driver.patch b/add-appleir-usb-driver.patch deleted file mode 100644 index 0ab0ed6f4..000000000 --- a/add-appleir-usb-driver.patch +++ /dev/null @@ -1,701 +0,0 @@ -From e11e9e78799a7641fe0dc5289f35f2604a4b71a3 Mon Sep 17 00:00:00 2001 -From: Bastien Nocera -Date: Sun, 17 Jan 2010 00:40:15 +0000 -Subject: [PATCH] Input: add appleir USB driver - -This driver was originally written by James McKenzie, updated by -Greg Kroah-Hartman, further updated by myself, with suspend support -added. - -More recent versions of the IR receiver are also supported through -a patch by Alex Karpenko. The patch also adds support for the 2nd -and 5th generation of the controller, and the menu key on newer -brushed metal remotes. - -Tested on a MacbookAir1,1 - -Signed-off-by: Bastien Nocera ---- - Documentation/input/appleir.txt | 46 ++++ - drivers/hid/hid-apple.c | 4 - - drivers/hid/hid-core.c | 7 +- - drivers/hid/hid-ids.h | 5 +- - drivers/input/misc/Kconfig | 13 + - drivers/input/misc/Makefile | 1 + - drivers/input/misc/appleir.c | 519 +++++++++++++++++++++++++++++++++++++++ - 7 files changed, 588 insertions(+), 7 deletions(-) - create mode 100644 Documentation/input/appleir.txt - create mode 100644 drivers/input/misc/appleir.c - -diff --git a/Documentation/input/appleir.txt b/Documentation/input/appleir.txt -new file mode 100644 -index 0000000..db637fb ---- /dev/null -+++ b/Documentation/input/appleir.txt -@@ -0,0 +1,46 @@ -+Apple IR receiver Driver (appleir) -+---------------------------------- -+ Copyright (C) 2009 Bastien Nocera -+ -+The appleir driver is a kernel input driver to handle Apple's IR -+receivers (and associated remotes) in the kernel. -+ -+The driver is an input driver which only handles "official" remotes -+as built and sold by Apple. -+ -+Authors -+------- -+ -+James McKenzie (original driver) -+Alex Karpenko (05ac:8242 support) -+Greg Kroah-Hartman (cleanups and original submission) -+Bastien Nocera (further cleanups, brushed metal "enter" -+button support and suspend support) -+ -+Supported hardware -+------------------ -+ -+- All Apple laptops and desktops from 2005 onwards, except: -+ - the unibody Macbook (2009) -+ - Mac Pro (all versions) -+- Apple TV (all revisions prior to September 2010) -+ -+The remote will only support the 6 (old white) or 7 (brushed metal) buttons -+of the remotes as sold by Apple. See the next section if you want to use -+other remotes or want to use lirc with the device instead of the kernel driver. -+ -+Using lirc (native) instead of the kernel driver -+------------------------------------------------ -+ -+First, you will need to disable the kernel driver for the receiver. -+ -+This can be achieved by passing quirks to the usbhid driver. -+The quirk line would be: -+usbhid.quirks=0x05ac:0x8242:0x40000010 -+ -+With 0x05ac being the vendor ID (Apple, you shouldn't need to change this) -+With 0x8242 being the product ID (check the output of lsusb for your hardware) -+And 0x10 being "HID_QUIRK_HIDDEV_FORCE" and 0x40000000 being "HID_QUIRK_NO_IGNORE" -+ -+This should force the creation of a hiddev device for the receiver, and -+make it usable under lirc. -diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c -index bba05d0..0059d5a 100644 ---- a/drivers/hid/hid-apple.c -+++ b/drivers/hid/hid-apple.c -@@ -361,10 +361,6 @@ static void apple_remove(struct hid_device *hdev) - } - - static const struct hid_device_id apple_devices[] = { -- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL), -- .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT }, -- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4), -- .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE), - .driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL }, - -diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c -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[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, USB_DEVICE_ID_ACTIONSTAR_1011) }, -- { 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) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) }, -@@ -1577,6 +1575,11 @@ static const struct hid_device_id hid_ignore_list[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)}, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)}, - { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, -diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h -index 11af537..360a5ca 100644 ---- a/drivers/hid/hid-ids.h -+++ b/drivers/hid/hid-ids.h -@@ -100,8 +100,11 @@ - #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b - #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a - #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b --#define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241 -+#define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 -+#define USB_DEVICE_ID_APPLE_IRCONTROL2 0x1440 -+#define USB_DEVICE_ID_APPLE_IRCONTROL3 0x8241 - #define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242 -+#define USB_DEVICE_ID_APPLE_IRCONTROL5 0x8243 - - #define USB_VENDOR_ID_ASUS 0x0486 - #define USB_DEVICE_ID_ASUS_T91MT 0x0185 -diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig -index 60de906..2f2f2e7 100644 ---- a/drivers/input/misc/Kconfig -+++ b/drivers/input/misc/Kconfig - help - Say Y here if you need accelerometer to work in polling mode. - -+config INPUT_APPLEIR -+ tristate "Apple infrared receiver (built in)" -+ depends on USB_ARCH_HAS_HCD -+ select USB -+ help -+ Say Y here if you want to use a Apple infrared remote control. All -+ the Apple computers from 2005 onwards include such a port, except -+ the unibody Macbook (2009), and Mac Pros. This receiver is also -+ used in the Apple TV set-top box prior to the 2010 model. -+ -+ To compile this driver as a module, choose M here: the module will -+ be called appleir. -+ - config INPUT_POWERMATE - tristate "Griffin PowerMate and Contour Jog support" - depends on USB_ARCH_HAS_HCD -diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile -index 1fe1f6c..d5ef2b9 100644 ---- a/drivers/input/misc/Makefile -+++ b/drivers/input/misc/Makefile -@@ -13,6 +13,7 @@ obj-$(CONFIG_INPUT_ADXL34X) += adxl34x.o - obj-$(CONFIG_INPUT_ADXL34X_I2C) += adxl34x-i2c.o - obj-$(CONFIG_INPUT_ADXL34X_SPI) += adxl34x-spi.o - obj-$(CONFIG_INPUT_APANEL) += apanel.o -+obj-$(CONFIG_INPUT_APPLEIR) += appleir.o - obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o - obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o - obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o -diff --git a/drivers/input/misc/appleir.c b/drivers/input/misc/appleir.c -new file mode 100644 -index 0000000..3817a3c ---- /dev/null -+++ b/drivers/input/misc/appleir.c -@@ -0,0 +1,519 @@ -+/* -+ * appleir: USB driver for the apple ir device -+ * -+ * Original driver written by James McKenzie -+ * Ported to recent 2.6 kernel versions by Greg Kroah-Hartman -+ * -+ * Copyright (C) 2006 James McKenzie -+ * Copyright (C) 2008 Greg Kroah-Hartman -+ * Copyright (C) 2008 Novell Inc. -+ * -+ * 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. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_VERSION "v1.2" -+#define DRIVER_AUTHOR "James McKenzie" -+#define DRIVER_DESC "Apple infrared receiver driver" -+#define DRIVER_LICENSE "GPL" -+ -+MODULE_AUTHOR(DRIVER_AUTHOR); -+MODULE_DESCRIPTION(DRIVER_DESC); -+MODULE_LICENSE(DRIVER_LICENSE); -+ -+#define USB_VENDOR_ID_APPLE 0x05ac -+#define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 -+#define USB_DEVICE_ID_APPLE_IRCONTROL2 0x1440 -+#define USB_DEVICE_ID_APPLE_IRCONTROL3 0x8241 -+#define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242 -+#define USB_DEVICE_ID_APPLE_IRCONTROL5 0x8243 -+ -+#define URB_SIZE 32 -+ -+#define MAX_KEYS 9 -+#define MAX_KEYS_MASK (MAX_KEYS - 1) -+ -+#define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) -+ -+static int debug; -+module_param(debug, int, 0644); -+MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); -+ -+/* I have two devices both of which report the following */ -+/* 25 87 ee 83 0a + */ -+/* 25 87 ee 83 0c - */ -+/* 25 87 ee 83 09 << */ -+/* 25 87 ee 83 06 >> */ -+/* 25 87 ee 83 05 >" */ -+/* 25 87 ee 83 03 menu */ -+/* 26 00 00 00 00 for key repeat*/ -+ -+/* Thomas Glanzmann reports the following responses */ -+/* 25 87 ee ca 0b + */ -+/* 25 87 ee ca 0d - */ -+/* 25 87 ee ca 08 << */ -+/* 25 87 ee ca 07 >> */ -+/* 25 87 ee ca 04 >" */ -+/* 25 87 ee ca 02 menu */ -+/* 26 00 00 00 00 for key repeat*/ -+/* He also observes the following event sometimes */ -+/* sent after a key is release, which I interpret */ -+/* as a flat battery message */ -+/* 25 87 e0 ca 06 flat battery */ -+ -+/* Alexandre Karpenko reports the following responses for Device ID 0x8242 */ -+/* 25 87 ee 47 0b + */ -+/* 25 87 ee 47 0d - */ -+/* 25 87 ee 47 08 << */ -+/* 25 87 ee 47 07 >> */ -+/* 25 87 ee 47 04 >" */ -+/* 25 87 ee 47 02 menu */ -+/* 26 87 ee 47 ** for key repeat (** is the code of the key being held) */ -+ -+/* Bastien Nocera's "new" remote */ -+/* 25 87 ee 91 5f followed by -+ * 25 87 ee 91 05 gives you >" -+ * -+ * 25 87 ee 91 5c followed by -+ * 25 87 ee 91 05 gives you the middle button */ -+ -+static const unsigned short appleir_key_table[] = { -+ KEY_RESERVED, -+ KEY_MENU, -+ KEY_PLAYPAUSE, -+ KEY_FORWARD, -+ KEY_BACK, -+ KEY_VOLUMEUP, -+ KEY_VOLUMEDOWN, -+ KEY_ENTER, -+ KEY_RESERVED, -+}; -+ -+struct appleir { -+ struct input_dev *input_dev; -+ unsigned short keymap[ARRAY_SIZE(appleir_key_table)]; -+ u8 *data; -+ dma_addr_t dma_buf; -+ struct usb_device *usbdev; -+ unsigned int flags; -+ struct urb *urb; -+ struct timer_list key_up_timer; -+ int current_key; -+ int prev_key_idx; -+ char phys[32]; -+}; -+ -+static DEFINE_MUTEX(appleir_mutex); -+ -+enum { -+ APPLEIR_OPENED = 0x1, -+ APPLEIR_SUSPENDED = 0x2, -+}; -+ -+static struct usb_device_id appleir_ids[] = { -+ { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) }, -+ { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) }, -+ { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) }, -+ { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, -+ { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) }, -+ {} -+}; -+MODULE_DEVICE_TABLE(usb, appleir_ids); -+ -+static void dump_packet(struct appleir *appleir, char *msg, u8 *data, int len) -+{ -+ int i; -+ -+ printk(KERN_ERR "appleir: %s (%d bytes)", msg, len); -+ -+ for (i = 0; i < len; ++i) -+ printk(" %02x", data[i]); -+ printk(" (should be command %d)\n", (data[4] >> 1) & MAX_KEYS_MASK); -+} -+ -+static int get_key(int data) -+{ -+ switch (data) { -+ case 0x02: -+ case 0x03: -+ /* menu */ -+ return 1; -+ case 0x04: -+ case 0x05: -+ /* >" */ -+ return 2; -+ case 0x06: -+ case 0x07: -+ /* >> */ -+ return 3; -+ case 0x08: -+ case 0x09: -+ /* << */ -+ return 4; -+ case 0x0a: -+ case 0x0b: -+ /* + */ -+ return 5; -+ case 0x0c: -+ case 0x0d: -+ /* - */ -+ return 6; -+ case 0x5c: -+ /* Middle button, on newer remotes, -+ * part of a 2 packet-command */ -+ return -7; -+ default: -+ return -1; -+ } -+} -+ -+static void key_up(struct appleir *appleir, int key) -+{ -+ dbginfo(&appleir->input_dev->dev, "key %d up\n", key); -+ input_report_key(appleir->input_dev, key, 0); -+ input_sync(appleir->input_dev); -+} -+ -+static void key_down(struct appleir *appleir, int key) -+{ -+ dbginfo(&appleir->input_dev->dev, "key %d down\n", key); -+ input_report_key(appleir->input_dev, key, 1); -+ input_sync(appleir->input_dev); -+} -+ -+static void battery_flat(struct appleir *appleir) -+{ -+ dev_err(&appleir->input_dev->dev, "possible flat battery?\n"); -+} -+ -+static void key_up_tick(unsigned long data) -+{ -+ struct appleir *appleir = (struct appleir *)data; -+ -+ if (appleir->current_key) { -+ key_up(appleir, appleir->current_key); -+ appleir->current_key = 0; -+ } -+} -+ -+static void new_data(struct appleir *appleir, u8 *data, int len) -+{ -+ static const u8 keydown[] = { 0x25, 0x87, 0xee }; -+ static const u8 keyrepeat[] = { 0x26, }; -+ static const u8 flatbattery[] = { 0x25, 0x87, 0xe0 }; -+ -+ if (debug) -+ dump_packet(appleir, "received", data, len); -+ -+ if (len != 5) -+ return; -+ -+ if (!memcmp(data, keydown, sizeof(keydown))) { -+ int index; -+ -+ /* If we already have a key down, take it up before marking -+ this one down */ -+ if (appleir->current_key) -+ key_up(appleir, appleir->current_key); -+ -+ /* Handle dual packet commands */ -+ if (appleir->prev_key_idx > 0) -+ index = appleir->prev_key_idx; -+ else -+ index = get_key(data[4]); -+ -+ if (index > 0) { -+ appleir->current_key = appleir->keymap[index]; -+ -+ key_down(appleir, appleir->current_key); -+ /* Remote doesn't do key up, either pull them up, in the test -+ above, or here set a timer which pulls them up after 1/8 s */ -+ mod_timer(&appleir->key_up_timer, jiffies + HZ / 8); -+ appleir->prev_key_idx = 0; -+ return; -+ } else if (index == -7) { -+ /* Remember key for next packet */ -+ appleir->prev_key_idx = 0 - index; -+ return; -+ } -+ } -+ -+ appleir->prev_key_idx = 0; -+ -+ if (!memcmp(data, keyrepeat, sizeof(keyrepeat))) { -+ key_down(appleir, appleir->current_key); -+ /* Remote doesn't do key up, either pull them up, in the test -+ above, or here set a timer which pulls them up after 1/8 s */ -+ mod_timer(&appleir->key_up_timer, jiffies + HZ / 8); -+ return; -+ } -+ -+ if (!memcmp(data, flatbattery, sizeof(flatbattery))) { -+ battery_flat(appleir); -+ /* Fall through */ -+ } -+ -+ dump_packet(appleir, "unknown packet", data, len); -+} -+ -+static void appleir_urb(struct urb *urb) -+{ -+ struct appleir *appleir = urb->context; -+ int status = urb->status; -+ int retval; -+ -+ switch (status) { -+ case 0: -+ new_data(appleir, urb->transfer_buffer, urb->actual_length); -+ break; -+ case -ECONNRESET: -+ case -ENOENT: -+ case -ESHUTDOWN: -+ /* This urb is terminated, clean up */ -+ dbginfo(&appleir->input_dev->dev, "%s - urb shutting down with status: %d", __func__, -+ urb->status); -+ return; -+ default: -+ dbginfo(&appleir->input_dev->dev, "%s - nonzero urb status received: %d", __func__, -+ urb->status); -+ } -+ -+ retval = usb_submit_urb(urb, GFP_ATOMIC); -+ if (retval) -+ err("%s - usb_submit_urb failed with result %d", __func__, -+ retval); -+} -+ -+static int appleir_open(struct input_dev *dev) -+{ -+ struct appleir *appleir = input_get_drvdata(dev); -+ struct usb_interface *intf = usb_ifnum_to_if(appleir->usbdev, 0); -+ int r; -+ -+ r = usb_autopm_get_interface(intf); -+ if (r) { -+ dev_err(&intf->dev, -+ "%s(): usb_autopm_get_interface() = %d\n", __func__, r); -+ return r; -+ } -+ -+ mutex_lock(&appleir_mutex); -+ -+ if (usb_submit_urb(appleir->urb, GFP_ATOMIC)) { -+ r = -EIO; -+ goto fail; -+ } -+ -+ appleir->flags |= APPLEIR_OPENED; -+ -+ mutex_unlock(&appleir_mutex); -+ -+ usb_autopm_put_interface(intf); -+ -+ return 0; -+fail: -+ mutex_unlock(&appleir_mutex); -+ usb_autopm_put_interface(intf); -+ return r; -+} -+ -+static void appleir_close(struct input_dev *dev) -+{ -+ struct appleir *appleir = input_get_drvdata(dev); -+ -+ mutex_lock(&appleir_mutex); -+ -+ if (!(appleir->flags & APPLEIR_SUSPENDED)) { -+ usb_kill_urb(appleir->urb); -+ del_timer_sync(&appleir->key_up_timer); -+ } -+ -+ appleir->flags &= ~APPLEIR_OPENED; -+ -+ mutex_unlock(&appleir_mutex); -+} -+ -+static int appleir_probe(struct usb_interface *intf, -+ const struct usb_device_id *id) -+{ -+ struct usb_device *dev = interface_to_usbdev(intf); -+ struct usb_endpoint_descriptor *endpoint; -+ struct appleir *appleir = NULL; -+ struct input_dev *input_dev; -+ int retval = -ENOMEM; -+ int i; -+ -+ appleir = kzalloc(sizeof(struct appleir), GFP_KERNEL); -+ if (!appleir) -+ goto allocfail; -+ -+ appleir->data = usb_alloc_coherent(dev, URB_SIZE, GFP_KERNEL, -+ &appleir->dma_buf); -+ if (!appleir->data) -+ goto usbfail; -+ -+ appleir->urb = usb_alloc_urb(0, GFP_KERNEL); -+ if (!appleir->urb) -+ goto urbfail; -+ -+ appleir->usbdev = dev; -+ -+ input_dev = input_allocate_device(); -+ if (!input_dev) -+ goto inputfail; -+ -+ appleir->input_dev = input_dev; -+ -+ usb_make_path(dev, appleir->phys, sizeof(appleir->phys)); -+ strlcpy(appleir->phys, "/input0", sizeof(appleir->phys)); -+ -+ input_dev->name = "Apple Infrared Remote Controller"; -+ input_dev->phys = appleir->phys; -+ usb_to_input_id(dev, &input_dev->id); -+ input_dev->dev.parent = &intf->dev; -+ input_dev->keycode = appleir->keymap; -+ input_dev->keycodesize = sizeof(unsigned short); -+ input_dev->keycodemax = ARRAY_SIZE(appleir->keymap); -+ -+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); -+ -+ memcpy(appleir->keymap, appleir_key_table, sizeof(appleir->keymap)); -+ for (i = 0; i < ARRAY_SIZE(appleir_key_table); i++) -+ set_bit(appleir->keymap[i], input_dev->keybit); -+ clear_bit(KEY_RESERVED, input_dev->keybit); -+ -+ input_set_drvdata(input_dev, appleir); -+ input_dev->open = appleir_open; -+ input_dev->close = appleir_close; -+ -+ endpoint = &intf->cur_altsetting->endpoint[0].desc; -+ -+ usb_fill_int_urb(appleir->urb, dev, -+ usb_rcvintpipe(dev, endpoint->bEndpointAddress), -+ appleir->data, 8, -+ appleir_urb, appleir, endpoint->bInterval); -+ -+ appleir->urb->transfer_dma = appleir->dma_buf; -+ appleir->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; -+ -+ setup_timer(&appleir->key_up_timer, -+ key_up_tick, (unsigned long) appleir); -+ -+ retval = input_register_device(appleir->input_dev); -+ if (retval) -+ goto inputfail; -+ -+ usb_set_intfdata(intf, appleir); -+ -+ return 0; -+ -+inputfail: -+ input_free_device(appleir->input_dev); -+ -+urbfail: -+ usb_free_urb(appleir->urb); -+ -+usbfail: -+ usb_free_coherent(dev, URB_SIZE, appleir->data, -+ appleir->dma_buf); -+ -+allocfail: -+ kfree(appleir); -+ -+ return retval; -+} -+ -+static void appleir_disconnect(struct usb_interface *intf) -+{ -+ struct appleir *appleir = usb_get_intfdata(intf); -+ -+ usb_set_intfdata(intf, NULL); -+ input_unregister_device(appleir->input_dev); -+ usb_free_urb(appleir->urb); -+ usb_free_coherent(interface_to_usbdev(intf), URB_SIZE, -+ appleir->data, appleir->dma_buf); -+ kfree(appleir); -+} -+ -+static int appleir_suspend(struct usb_interface *interface, -+ pm_message_t message) -+{ -+ struct appleir *appleir = usb_get_intfdata(interface); -+ -+ mutex_lock(&appleir_mutex); -+ if (appleir->flags & APPLEIR_OPENED) -+ usb_kill_urb(appleir->urb); -+ -+ appleir->flags |= APPLEIR_SUSPENDED; -+ -+ mutex_unlock(&appleir_mutex); -+ -+ return 0; -+} -+ -+static int appleir_resume(struct usb_interface *interface) -+{ -+ struct appleir *appleir; -+ int r = 0; -+ -+ appleir = usb_get_intfdata(interface); -+ -+ mutex_lock(&appleir_mutex); -+ if (appleir->flags & APPLEIR_OPENED) { -+ struct usb_endpoint_descriptor *endpoint; -+ -+ endpoint = &interface->cur_altsetting->endpoint[0].desc; -+ usb_fill_int_urb(appleir->urb, appleir->usbdev, -+ usb_rcvintpipe(appleir->usbdev, endpoint->bEndpointAddress), -+ appleir->data, 8, -+ appleir_urb, appleir, endpoint->bInterval); -+ appleir->urb->transfer_dma = appleir->dma_buf; -+ appleir->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; -+ -+ /* And reset the USB device */ -+ if (usb_submit_urb(appleir->urb, GFP_ATOMIC)) -+ r = -EIO; -+ } -+ -+ appleir->flags &= ~APPLEIR_SUSPENDED; -+ -+ mutex_unlock(&appleir_mutex); -+ -+ return r; -+} -+ -+static struct usb_driver appleir_driver = { -+ .name = "appleir", -+ .probe = appleir_probe, -+ .disconnect = appleir_disconnect, -+ .suspend = appleir_suspend, -+ .resume = appleir_resume, -+ .reset_resume = appleir_resume, -+ .id_table = appleir_ids, -+}; -+ -+static int __init appleir_init(void) -+{ -+ return usb_register(&appleir_driver); -+} -+ -+static void __exit appleir_exit(void) -+{ -+ usb_deregister(&appleir_driver); -+} -+ -+module_init(appleir_init); -+module_exit(appleir_exit); --- -1.7.2.2 - diff --git a/alps.patch b/alps.patch index e76dc5477..331716d3b 100644 --- a/alps.patch +++ b/alps.patch @@ -1,7 +1,7 @@ -From ed11aa781242216bc72f1cd7d757a4f40be10329 Mon Sep 17 00:00:00 2001 +From d4b347b29b4d14647c7394f7167bf6785dc98e50 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Mon, 7 Nov 2011 19:53:15 -0800 -Subject: [PATCH 1/7] Input: ALPS - move protocol information to Documentation +Subject: [PATCH 1/6] Input: ALPS - move protocol information to Documentation In preparation for new protocol support, move the protocol information currently documented in alps.c to @@ -99,10 +99,10 @@ index 0000000..ab5478f + byte 7: 0 y6 y5 y4 y3 y2 y1 y0 + byte 8: 0 z6 z5 z4 z3 z2 z1 z0 diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 99d5876..ad15e7c 100644 +index 003587c..19d0943 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c -@@ -74,42 +74,7 @@ static const struct alps_model_info alps_model_data[] = { +@@ -67,42 +67,7 @@ static const struct alps_model_info alps_model_data[] = { * isn't valid per PS/2 spec. */ @@ -150,10 +150,10 @@ index 99d5876..ad15e7c 100644 1.7.7.3 -From 27b8ed51ee660e9a59cf325d6339f38b216fbb31 Mon Sep 17 00:00:00 2001 +From fa629ef5222193214da9a2b3c94369f79353bec9 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Mon, 7 Nov 2011 19:53:24 -0800 -Subject: [PATCH 2/7] Input: ALPS - add protocol version field in +Subject: [PATCH 2/6] Input: ALPS - add protocol version field in alps_model_info In preparation for adding support for more ALPS protocol versions, @@ -164,28 +164,24 @@ version 1 and version 2, repsectively. Signed-off-by: Seth Forshee Acked-by: Chase Douglas Signed-off-by: Dmitry Torokhov - -Conflicts: - - drivers/input/mouse/alps.c --- drivers/input/mouse/alps.c | 47 +++++++++++++++++++++---------------------- drivers/input/mouse/alps.h | 4 +++ 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index ad15e7c..572cb21 100644 +index 19d0943..77b776d 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c -@@ -30,7 +30,6 @@ - #define dbg(format, arg...) do {} while (0) - #endif +@@ -23,7 +23,6 @@ + #include "psmouse.h" + #include "alps.h" -#define ALPS_OLDPROTO 0x01 /* old style input */ #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ #define ALPS_PASS 0x04 /* device has a pass-through port */ -@@ -42,30 +41,30 @@ +@@ -35,30 +34,30 @@ 6-byte ALPS packet */ static const struct alps_model_info alps_model_data[] = { @@ -238,7 +234,7 @@ index ad15e7c..572cb21 100644 }; /* -@@ -119,7 +118,7 @@ static void alps_process_packet(struct psmouse *psmouse) +@@ -112,7 +111,7 @@ static void alps_process_packet(struct psmouse *psmouse) int x, y, z, ges, fin, left, right, middle; int back = 0, forward = 0; @@ -268,10 +264,10 @@ index 904ed8b..4ce9bba 100644 1.7.7.3 -From dfab9d3e073f2a58e4ba3837a726e9a0e33ea5df Mon Sep 17 00:00:00 2001 +From b46615fe9215214ac00e26d35fc54dbe1c510803 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Mon, 7 Nov 2011 19:53:30 -0800 -Subject: [PATCH 3/7] Input: ALPS - remove assumptions about packet size +Subject: [PATCH 3/6] Input: ALPS - remove assumptions about packet size In preparation for version 4 protocol support, which has 8-byte data packets, remove all hard-coded assumptions about packet size @@ -285,10 +281,10 @@ Signed-off-by: Dmitry Torokhov 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 572cb21..f699698 100644 +index 77b776d..44a0a71 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c -@@ -315,7 +315,7 @@ static void alps_flush_packet(unsigned long data) +@@ -308,7 +308,7 @@ static void alps_flush_packet(unsigned long data) serio_pause_rx(psmouse->ps2dev.serio); @@ -297,7 +293,7 @@ index 572cb21..f699698 100644 /* * We did not any more data in reasonable amount of time. -@@ -365,15 +365,15 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) +@@ -359,8 +359,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) return PSMOUSE_BAD_DATA; } @@ -306,8 +302,9 @@ index 572cb21..f699698 100644 + /* Bytes 2 - pktsize should have 0 in the highest bit */ + if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { - dbg("refusing packet[%i] = %x\n", - psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]); + psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", + psmouse->pktcnt - 1, +@@ -368,7 +368,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) return PSMOUSE_BAD_DATA; } @@ -316,7 +313,7 @@ index 572cb21..f699698 100644 alps_process_packet(psmouse); return PSMOUSE_FULL_PACKET; } -@@ -531,7 +531,7 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) +@@ -529,7 +529,7 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) static int alps_poll(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; @@ -329,10 +326,10 @@ index 572cb21..f699698 100644 1.7.7.3 -From 35f17ba201d7a8b8adc59811effafe62a331fd9e Mon Sep 17 00:00:00 2001 +From 25bded7cd60fa460e520e9f819bd06f4c5cb53f0 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Mon, 7 Nov 2011 19:53:36 -0800 -Subject: [PATCH 4/7] Input: ALPS - add support for protocol versions 3 and 4 +Subject: [PATCH 4/6] Input: ALPS - add support for protocol versions 3 and 4 This patch adds support for two ALPS touchpad protocols not supported currently by the driver, which I am arbitrarily naming @@ -345,23 +342,19 @@ of the v3 protocol. Signed-off-by: Seth Forshee Acked-by: Chase Douglas Signed-off-by: Dmitry Torokhov - -Conflicts: - - drivers/input/mouse/alps.c --- - drivers/input/mouse/alps.c | 790 +++++++++++++++++++++++++++++++++++++++-- + drivers/input/mouse/alps.c | 791 +++++++++++++++++++++++++++++++++++++++-- drivers/input/mouse/alps.h | 14 + drivers/input/mouse/psmouse.h | 1 + - 3 files changed, 767 insertions(+), 38 deletions(-) + 3 files changed, 768 insertions(+), 38 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index f699698..b2bc8ca 100644 +index 44a0a71..a0248fd 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c -@@ -30,6 +30,49 @@ - #define dbg(format, arg...) do {} while (0) - #endif +@@ -23,6 +23,50 @@ + #include "psmouse.h" + #include "alps.h" +/* + * Definitions for ALPS version 3 and 4 command mode protocol @@ -405,11 +398,12 @@ index f699698..b2bc8ca 100644 + { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ + { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ +}; ++ + #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ #define ALPS_PASS 0x04 /* device has a pass-through port */ -@@ -41,30 +84,33 @@ +@@ -34,30 +78,33 @@ 6-byte ALPS packet */ static const struct alps_model_info alps_model_data[] = { @@ -465,7 +459,7 @@ index f699698..b2bc8ca 100644 }; /* -@@ -108,7 +154,7 @@ static void alps_report_buttons(struct psmouse *psmouse, +@@ -101,7 +148,7 @@ static void alps_report_buttons(struct psmouse *psmouse, input_sync(dev2); } @@ -474,7 +468,7 @@ index f699698..b2bc8ca 100644 { struct alps_data *priv = psmouse->private; const struct alps_model_info *model = priv->i; -@@ -210,6 +256,224 @@ static void alps_process_packet(struct psmouse *psmouse) +@@ -203,6 +250,224 @@ static void alps_process_packet(struct psmouse *psmouse) input_sync(dev); } @@ -699,7 +693,7 @@ index f699698..b2bc8ca 100644 static void alps_report_bare_ps2_packet(struct psmouse *psmouse, unsigned char packet[], bool report_buttons) -@@ -381,11 +645,127 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) +@@ -376,11 +641,127 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) return PSMOUSE_GOOD_DATA; } @@ -827,7 +821,7 @@ index f699698..b2bc8ca 100644 int i; /* -@@ -431,12 +811,41 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int +@@ -428,12 +809,41 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version = (param[0] << 8) | (param[1] << 4) | i; } @@ -873,7 +867,7 @@ index f699698..b2bc8ca 100644 } /* -@@ -444,7 +853,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int +@@ -441,7 +851,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int * subsequent commands. It looks like glidepad is behind stickpointer, * I'd thought it would be other way around... */ @@ -882,7 +876,7 @@ index f699698..b2bc8ca 100644 { struct ps2dev *ps2dev = &psmouse->ps2dev; int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; -@@ -461,7 +870,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) +@@ -458,7 +868,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) return 0; } @@ -891,7 +885,7 @@ index f699698..b2bc8ca 100644 { struct ps2dev *ps2dev = &psmouse->ps2dev; -@@ -535,13 +944,13 @@ static int alps_poll(struct psmouse *psmouse) +@@ -533,13 +943,13 @@ static int alps_poll(struct psmouse *psmouse) bool poll_failed; if (priv->i->flags & ALPS_PASS) @@ -907,7 +901,7 @@ index f699698..b2bc8ca 100644 if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) return -1; -@@ -558,13 +967,13 @@ static int alps_poll(struct psmouse *psmouse) +@@ -556,13 +966,13 @@ static int alps_poll(struct psmouse *psmouse) return 0; } @@ -923,13 +917,13 @@ index f699698..b2bc8ca 100644 return -1; } -@@ -573,13 +982,13 @@ static int alps_hw_init(struct psmouse *psmouse) +@@ -571,13 +981,13 @@ static int alps_hw_init(struct psmouse *psmouse) return -1; } - if (alps_absolute_mode(psmouse)) { + if (alps_absolute_mode_v1_v2(psmouse)) { - printk(KERN_ERR "alps.c: Failed to enable absolute mode\n"); + psmouse_err(psmouse, "Failed to enable absolute mode\n"); return -1; } @@ -939,7 +933,7 @@ index f699698..b2bc8ca 100644 return -1; } -@@ -592,6 +1001,297 @@ static int alps_hw_init(struct psmouse *psmouse) +@@ -590,6 +1000,297 @@ static int alps_hw_init(struct psmouse *psmouse) return 0; } @@ -1237,7 +1231,7 @@ index f699698..b2bc8ca 100644 static int alps_reconnect(struct psmouse *psmouse) { const struct alps_model_info *model; -@@ -632,6 +1332,8 @@ int alps_init(struct psmouse *psmouse) +@@ -630,6 +1331,8 @@ int alps_init(struct psmouse *psmouse) psmouse->private = priv; @@ -1246,7 +1240,7 @@ index f699698..b2bc8ca 100644 model = alps_get_model(psmouse, &version); if (!model) goto init_fail; -@@ -659,8 +1361,20 @@ int alps_init(struct psmouse *psmouse) +@@ -657,8 +1360,20 @@ int alps_init(struct psmouse *psmouse) BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); @@ -1269,7 +1263,7 @@ index f699698..b2bc8ca 100644 input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); if (model->flags & ALPS_WHEEL) { -@@ -703,7 +1417,7 @@ int alps_init(struct psmouse *psmouse) +@@ -701,7 +1416,7 @@ int alps_init(struct psmouse *psmouse) psmouse->poll = alps_poll; psmouse->disconnect = alps_disconnect; psmouse->reconnect = alps_reconnect; @@ -1320,7 +1314,7 @@ index 4ce9bba..62db7f4 100644 int alps_detect(struct psmouse *psmouse, bool set_properties); int alps_init(struct psmouse *psmouse); diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h -index 593e910..c2b5aa6 100644 +index 9b84b0c..11a9c6c 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -8,6 +8,7 @@ @@ -1335,10 +1329,10 @@ index 593e910..c2b5aa6 100644 1.7.7.3 -From 8a2d5b12d0a47daf178a842ca009eaf344033cf8 Mon Sep 17 00:00:00 2001 +From 01ce661fc83005947dc958a5739c153843af8a73 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Mon, 7 Nov 2011 19:54:13 -0800 -Subject: [PATCH 5/7] Input: ALPS - add semi-MT support for v3 protocol +Subject: [PATCH 5/6] Input: ALPS - add semi-MT support for v3 protocol Signed-off-by: Seth Forshee Acked-by: Chase Douglas @@ -1349,7 +1343,7 @@ Signed-off-by: Dmitry Torokhov 2 files changed, 215 insertions(+), 19 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index b2bc8ca..15383e1 100644 +index a0248fd..bd87380 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -17,6 +17,7 @@ @@ -1360,7 +1354,7 @@ index b2bc8ca..15383e1 100644 #include #include -@@ -33,6 +34,12 @@ +@@ -26,6 +27,12 @@ /* * Definitions for ALPS version 3 and 4 command mode protocol */ @@ -1373,7 +1367,7 @@ index b2bc8ca..15383e1 100644 #define ALPS_CMD_NIBBLE_10 0x01f2 static const struct alps_nibble_commands alps_v3_nibble_commands[] = { -@@ -256,6 +263,137 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) +@@ -250,6 +257,137 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) input_sync(dev); } @@ -1511,7 +1505,7 @@ index b2bc8ca..15383e1 100644 static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; -@@ -324,16 +462,17 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) +@@ -318,16 +456,17 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) struct input_dev *dev2 = priv->dev2; int x, y, z; int left, right, middle; @@ -1535,7 +1529,7 @@ index b2bc8ca..15383e1 100644 /* * Sometimes a position packet will indicate a multi-packet * sequence, but then what follows is another position -@@ -341,18 +480,49 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) +@@ -335,18 +474,49 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) * position packet as usual. */ if (packet[0] & 0x40) { @@ -1591,7 +1585,7 @@ index b2bc8ca..15383e1 100644 left = packet[3] & 0x01; right = packet[3] & 0x02; -@@ -372,22 +542,38 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) +@@ -366,22 +536,38 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) if (x && y && !z) return; @@ -1635,7 +1629,7 @@ index b2bc8ca..15383e1 100644 input_sync(dev); if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { -@@ -1369,9 +1555,18 @@ int alps_init(struct psmouse *psmouse) +@@ -1368,9 +1554,18 @@ int alps_init(struct psmouse *psmouse) input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); break; case ALPS_PROTO_V3: @@ -1672,10 +1666,10 @@ index 62db7f4..a00a4ab 100644 1.7.7.3 -From 281688737cb83dd113cfab809b2c78841451ba32 Mon Sep 17 00:00:00 2001 +From 7cf801cfc0774b777aa6861cf4a43a90b112b1ed Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Mon, 7 Nov 2011 19:54:35 -0800 -Subject: [PATCH 6/7] Input: ALPS - add documentation for protocol versions 3 +Subject: [PATCH 6/6] Input: ALPS - add documentation for protocol versions 3 and 4 Also converts from using "old" and "new" to describe the already-known @@ -1865,126 +1859,3 @@ index ab5478f..f274c28 100644 -- 1.7.7.3 - -From 8114d422321fa6bb724a03faf25b101868d6e03d Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Mon, 12 Dec 2011 15:12:00 -0500 -Subject: [PATCH 7/7] Revert psmouse_* print format changes from the - backported patches. Sigh - -Signed-off-by: Josh Boyer ---- - drivers/input/mouse/alps.c | 29 ++++++++++++----------------- - 1 files changed, 12 insertions(+), 17 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 15383e1..4925a63 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -403,7 +403,7 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) - - /* Sanity check packet */ - if (!(packet[0] & 0x40)) { -- psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n"); -+ dbg("Bad trackstick packet, discarding\n"); - return; - } - -@@ -922,13 +922,12 @@ static int alps_enter_command_mode(struct psmouse *psmouse, - ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || - ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { -- psmouse_err(psmouse, "failed to enter command mode\n"); -+ printk(KERN_ERR "alps.c: failed to enter command mode\n"); - return -1; - } - - if (param[0] != 0x88 && param[1] != 0x07) { -- psmouse_dbg(psmouse, -- "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", -+ dbg("unknown response while entering command mode: %2.2x %2.2x %2.2x\n", - param[0], param[1], param[2]); - return -1; - } -@@ -1012,8 +1011,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int - */ - model = NULL; - if (alps_enter_command_mode(psmouse, param)) { -- psmouse_warn(psmouse, -- "touchpad failed to enter command mode\n"); -+ printk(KERN_WARNING "alps.c: touchpad failed to enter command mode\n"); - } else { - for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { - if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && -@@ -1025,8 +1023,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int - alps_exit_command_mode(psmouse); - - if (!model) -- psmouse_dbg(psmouse, -- "Unknown command mode response %2.2x\n", -+ dbg("Unknown command mode response %2.2x\n", - param[0]); - } - } -@@ -1263,10 +1260,9 @@ static int alps_hw_init_v3(struct psmouse *psmouse) - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { -- psmouse_warn(psmouse, "trackstick E7 report failed\n"); -+ printk(KERN_WARNING "alps.c: trackstick E7 report failed\n"); - } else { -- psmouse_dbg(psmouse, -- "trackstick E7 report: %2.2x %2.2x %2.2x\n", -+ dbg("trackstick E7 report: %2.2x %2.2x %2.2x\n", - param[0], param[1], param[2]); - - /* -@@ -1280,8 +1276,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - alps_command_mode_send_nibble(psmouse, 0x9) || - alps_command_mode_send_nibble(psmouse, 0x4)) { -- psmouse_err(psmouse, -- "Error sending magic E6 sequence\n"); -+ printk(KERN_ERR "alps.c: Error sending magic E6 sequence\n"); - goto error_passthrough; - } - } -@@ -1293,7 +1288,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) - } - - if (alps_absolute_mode_v3(psmouse)) { -- psmouse_err(psmouse, "Failed to enter absolute mode\n"); -+ printk(KERN_ERR "alps.c: Failed to enter absolute mode\n"); - goto error; - } - -@@ -1343,7 +1338,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) - param[0] = 0x64; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { -- psmouse_err(psmouse, "Failed to enable data reporting\n"); -+ printk(KERN_ERR "alps.c: Failed to enable data reporting\n"); - return -1; - } - -@@ -1392,7 +1387,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse) - goto error; - - if (alps_absolute_mode_v4(psmouse)) { -- psmouse_err(psmouse, "Failed to enter absolute mode\n"); -+ printk(KERN_ERR "alps.c: Failed to enter absolute mode\n"); - goto error; - } - -@@ -1440,7 +1435,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse) - param[0] = 0x64; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { -- psmouse_err(psmouse, "Failed to enable data reporting\n"); -+ printk(KERN_ERR "alps.c: Failed to enable data reporting\n"); - return -1; - } - --- -1.7.7.3 - diff --git a/arm-tegra-usb-no-reset.patch b/arm-tegra-usb-no-reset.patch deleted file mode 100644 index 2cb028eb8..000000000 --- a/arm-tegra-usb-no-reset.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 6b0cbdfaf589e6f39ab7588ed1047d1a55224eb9 Mon Sep 17 00:00:00 2001 -From: Mike Rapoport -Date: Mon, 11 Apr 2011 10:33:20 +0300 -Subject: [PATCH] BUGFIX: don't allow disconnection of USB-SATA on TrimSlice - ---- - drivers/usb/core/hub.c | 7 +++++++ - 1 files changed, 7 insertions(+), 0 deletions(-) - -diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index 566c183..74b5165 100644 ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -3263,6 +3263,13 @@ static void hub_events(void) - (u16) hub->change_bits[0], - (u16) hub->event_bits[0]); - -+ /* Don't disconnect USB-SATA on TrimSlice */ -+ if (strcmp(dev_name(hdev->bus->controller), "tegra-ehci.0") == 0) { -+ if ((hdev->state == 7) && (hub->change_bits[0] == 0) && -+ (hub->event_bits[0] == 0x2)) -+ hub->event_bits[0] = 0; -+ } -+ - /* Lock the device, then check to see if we were - * disconnected while waiting for the lock to succeed. */ - usb_lock_device(hdev); --- -1.7.6 diff --git a/b44-Use-dev_kfree_skb_irq-in-b44_tx.patch b/b44-Use-dev_kfree_skb_irq-in-b44_tx.patch deleted file mode 100644 index ff50bd534..000000000 --- a/b44-Use-dev_kfree_skb_irq-in-b44_tx.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 15ac2b08a2fd0f4aacbe8ae39788252fea6fbe63 Mon Sep 17 00:00:00 2001 -From: Xander Hover -Date: Wed, 23 Nov 2011 16:40:31 -0500 -Subject: [PATCH] b44: Use dev_kfree_skb_irq() in b44_tx() - -Reported issues when using dev_kfree_skb() on UP systems and -systems with low numbers of cores. dev_kfree_skb_irq() will -properly save IRQ state before freeing the skb. - -Tested on 3.1.1 and 3.2_rc2 - -Example of reproducible trace of kernel 3.1.1 -------------[ cut here ]------------ - WARNING: at kernel/softirq.c:159 local_bh_enable+0x32/0x79() - ... - Pid: 0, comm: swapper Not tainted 3.1.1-gentoo #1 - Call Trace: - [] warn_slowpath_common+0x65/0x7a - [] ? local_bh_enable+0x32/0x79 - [] warn_slowpath_null+0xf/0x13 - [] local_bh_enable+0x32/0x79 - [] destroy_conntrack+0x7c/0x9b - [] nf_conntrack_destroy+0x1f/0x26 - [] skb_release_head_state+0x74/0x83 - [] __kfree_skb+0xb/0x6b - [] consume_skb+0x24/0x26 - [] b44_poll+0xaa/0x449 - [] net_rx_action+0x3f/0xea - [] __do_softirq+0x5f/0xd5 - [] ? local_bh_enable+0x79/0x79 - [] ? irq_exit+0x34/0x8d - [] ? do_IRQ+0x74/0x87 - [] ? common_interrupt+0x29/0x30 - [] ? default_idle+0x29/0x3e - [] ? cpu_idle+0x2f/0x5d - [] ? rest_init+0x79/0x7b - [] ? start_kernel+0x297/0x29c - [] ? i386_start_kernel+0xb0/0xb7 - ---[ end trace 583f33bb1aa207a9 ]--- - -Signed-off-by: Xander Hover -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/broadcom/b44.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/b44.c b/drivers/net/b44.c -index 4cf835d..3fb66d0 100644 ---- a/drivers/net/b44.c -+++ b/drivers/net/b44.c -@@ -608,7 +608,7 @@ static void b44_tx(struct b44 *bp) - skb->len, - DMA_TO_DEVICE); - rp->skb = NULL; -- dev_kfree_skb(skb); -+ dev_kfree_skb_irq(skb); - } - - bp->tx_cons = cons; --- -1.7.7.4 - diff --git a/bcma-brcmsmac-compat.patch b/bcma-brcmsmac-compat.patch deleted file mode 100644 index e16e5b0c5..000000000 --- a/bcma-brcmsmac-compat.patch +++ /dev/null @@ -1,35 +0,0 @@ -Simple patch to remove the overlap between the bcma (i.e. b43) driver -and the brcmsmac driver. David Woodhouse -confirmed that this patch restores functionality of bcm4331 devices. - --- John W. Linville - -diff -up linux-3.1.x86_64/drivers/bcma/host_pci.c.orig linux-3.1.x86_64/drivers/bcma/host_pci.c ---- linux-3.1.x86_64/drivers/bcma/host_pci.c.orig 2011-11-10 11:41:26.829742757 -0500 -+++ linux-3.1.x86_64/drivers/bcma/host_pci.c 2011-11-10 11:41:22.884792078 -0500 -@@ -225,11 +225,13 @@ static void bcma_host_pci_remove(struct - } - - static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { -- { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, -+#if 0 /* Not in Fedora... */ -+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, -+#endif - { 0, }, - }; - MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl); -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig 2011-11-10 11:42:31.764930961 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig 2011-11-10 11:42:33.613907846 -0500 -@@ -5,7 +5,6 @@ config BRCMSMAC - tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" - depends on PCI - depends on MAC80211 -- depends on BCMA=n - select BRCMUTIL - select FW_LOADER - select CRC_CCITT diff --git a/be2net-non-member-vlan-pkts-not-received-in-promisco.patch b/be2net-non-member-vlan-pkts-not-received-in-promisco.patch deleted file mode 100644 index 866473efd..000000000 --- a/be2net-non-member-vlan-pkts-not-received-in-promisco.patch +++ /dev/null @@ -1,63 +0,0 @@ -From c0e64ef4899df4cedc872871e54e2c069d29e519 Mon Sep 17 00:00:00 2001 -From: Sathya Perla -Date: Tue, 2 Aug 2011 19:57:43 +0000 -Subject: [PATCH] be2net: non-member vlan pkts not received in promiscous mode - -While configuring promiscous mode, explicitly set the -VLAN_PROMISCOUS bit to make this happen. When switching off -promiscous mode, re-program the vids. - -Signed-off-by: Xavier Selvin -Signed-off-by: Sathya Perla -Signed-off-by: David S. Miller ---- - drivers/net/benet/be_cmds.c | 6 ++++-- - drivers/net/benet/be_main.c | 7 +++++++ - 2 files changed, 11 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c -index 1c25dbd..73fd949 100644 ---- a/drivers/net/benet/be_cmds.c -+++ b/drivers/net/benet/be_cmds.c -@@ -1586,9 +1586,11 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, bool en) - OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req)); - - req->if_id = cpu_to_le32(adapter->if_handle); -- req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS); -+ req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS -+ | BE_IF_FLAGS_VLAN_PROMISCUOUS); - if (en) -- req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS); -+ req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS -+ | BE_IF_FLAGS_VLAN_PROMISCUOUS); - - sge->pa_hi = cpu_to_le32(upper_32_bits(promiscous_cmd.dma)); - sge->pa_lo = cpu_to_le32(promiscous_cmd.dma & 0xFFFFFFFF); -diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c -index 3b2c5e6..32a5b11 100644 ---- a/drivers/net/benet/be_main.c -+++ b/drivers/net/benet/be_main.c -@@ -728,6 +728,10 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num) - status = be_cmd_vlan_config(adapter, if_handle, vtag, 1, 1, 0); - } - -+ /* No need to further configure vids if in promiscuous mode */ -+ if (adapter->promiscuous) -+ return 0; -+ - if (adapter->vlans_added <= adapter->max_vlans) { - /* Construct VLAN Table to give to HW */ - for (i = 0; i < VLAN_N_VID; i++) { -@@ -787,6 +791,9 @@ static void be_set_multicast_list(struct net_device *netdev) - if (adapter->promiscuous) { - adapter->promiscuous = false; - be_cmd_promiscuous_config(adapter, false); -+ -+ if (adapter->vlans_added) -+ be_vid_config(adapter, false, 0); - } - - /* Enable multicast promisc if num configured exceeds what we support */ --- -1.7.6.4 - diff --git a/benet-remove-bogus-unlikely-on-vlan-check.patch b/benet-remove-bogus-unlikely-on-vlan-check.patch deleted file mode 100644 index 08c00817e..000000000 --- a/benet-remove-bogus-unlikely-on-vlan-check.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 82f15998fafe683add83f7a11b2e25f919b3cd2d Mon Sep 17 00:00:00 2001 -From: Jiri Pirko -Date: Tue, 25 Oct 2011 13:47:16 -0400 -Subject: [PATCH] benet: remove bogus "unlikely" on vlan check - -Use of unlikely in this place is wrong. Remove it. - -Signed-off-by: Jiri Pirko -Signed-off-by: David S. Miller -Backported-by: Josh Boyer ---- - drivers/net/benet/be_main.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c -index c411bb1..6df0c7e 100644 ---- a/drivers/net/benet/be_main.c -+++ b/drivers/net/benet/be_main.c -@@ -1192,7 +1192,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, - skb->rxhash = rxcp->rss_hash; - - -- if (unlikely(rxcp->vlanf)) -+ if (rxcp->vlanf) - __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag); - - netif_receive_skb(skb); -@@ -1249,7 +1249,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, - if (adapter->netdev->features & NETIF_F_RXHASH) - skb->rxhash = rxcp->rss_hash; - -- if (unlikely(rxcp->vlanf)) -+ if (rxcp->vlanf) - __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag); - - napi_gro_frags(&eq_obj->napi); --- -1.7.6.4 - diff --git a/brcm80211.patch b/brcm80211.patch deleted file mode 100644 index 7c6d42e76..000000000 --- a/brcm80211.patch +++ /dev/null @@ -1,97238 +0,0 @@ -This patch represents the state of the brcm80211 driver as of 3.2-rc2, -plus a couple of one-line changes required to make it build on a 3.1 -base kernel. - -Obviously, this patch should be dropped completely when rebasing to the -final 3.2 kernel from upstream. - --- John W. Linville - -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h.orig 2011-11-09 13:46:58.225800883 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h 2011-11-09 13:47:16.977566455 -0500 -@@ -0,0 +1,32 @@ -+/* -+ * Copyright (c) 2011 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _bcmchip_h_ -+#define _bcmchip_h_ -+ -+/* bcm4329 */ -+/* SDIO device core, ID 0x829 */ -+#define BCM4329_CORE_BUS_BASE 0x18011000 -+/* internal memory core, ID 0x80e */ -+#define BCM4329_CORE_SOCRAM_BASE 0x18003000 -+/* ARM Cortex M3 core, ID 0x82a */ -+#define BCM4329_CORE_ARM_BASE 0x18002000 -+#define BCM4329_RAMSIZE 0x48000 -+/* firmware name */ -+#define BCM4329_FW_NAME "brcm/bcm4329-fullmac-4.bin" -+#define BCM4329_NV_NAME "brcm/bcm4329-fullmac-4.txt" -+ -+#endif /* _bcmchip_h_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c.orig 2011-11-09 13:46:58.226800871 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c 2011-11-09 13:47:16.978566442 -0500 -@@ -0,0 +1,371 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+/* ****************** SDIO CARD Interface Functions **************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include "dhd.h" -+#include "dhd_bus.h" -+#include "dhd_dbg.h" -+#include "sdio_host.h" -+ -+#define SDIOH_API_ACCESS_RETRY_LIMIT 2 -+ -+static void brcmf_sdioh_irqhandler(struct sdio_func *func) -+{ -+ struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev); -+ -+ brcmf_dbg(TRACE, "***IRQHandler\n"); -+ -+ sdio_release_host(func); -+ -+ brcmf_sdbrcm_isr(sdiodev->bus); -+ -+ sdio_claim_host(func); -+} -+ -+int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev) -+{ -+ brcmf_dbg(TRACE, "Entering\n"); -+ -+ sdio_claim_host(sdiodev->func[1]); -+ sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler); -+ sdio_release_host(sdiodev->func[1]); -+ -+ return 0; -+} -+ -+int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev) -+{ -+ brcmf_dbg(TRACE, "Entering\n"); -+ -+ sdio_claim_host(sdiodev->func[1]); -+ sdio_release_irq(sdiodev->func[1]); -+ sdio_release_host(sdiodev->func[1]); -+ -+ return 0; -+} -+ -+u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr, -+ int *err) -+{ -+ int status; -+ s32 retry = 0; -+ u8 data = 0; -+ -+ do { -+ if (retry) /* wait for 1 ms till bus get settled down */ -+ udelay(1000); -+ status = brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, fnc_num, -+ addr, (u8 *) &data); -+ } while (status != 0 -+ && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); -+ if (err) -+ *err = status; -+ -+ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n", -+ fnc_num, addr, data); -+ -+ return data; -+} -+ -+void -+brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr, -+ u8 data, int *err) -+{ -+ int status; -+ s32 retry = 0; -+ -+ do { -+ if (retry) /* wait for 1 ms till bus get settled down */ -+ udelay(1000); -+ status = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, fnc_num, -+ addr, (u8 *) &data); -+ } while (status != 0 -+ && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); -+ if (err) -+ *err = status; -+ -+ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n", -+ fnc_num, addr, data); -+} -+ -+int -+brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) -+{ -+ int err = 0; -+ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, -+ (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err); -+ if (!err) -+ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_SBADDRMID, -+ (address >> 16) & SBSDIO_SBADDRMID_MASK, -+ &err); -+ if (!err) -+ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_SBADDRHIGH, -+ (address >> 24) & SBSDIO_SBADDRHIGH_MASK, -+ &err); -+ -+ return err; -+} -+ -+u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size) -+{ -+ int status; -+ u32 word = 0; -+ uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; -+ -+ brcmf_dbg(INFO, "fun = 1, addr = 0x%x\n", addr); -+ -+ if (bar0 != sdiodev->sbwad) { -+ if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0)) -+ return 0xFFFFFFFF; -+ -+ sdiodev->sbwad = bar0; -+ } -+ -+ addr &= SBSDIO_SB_OFT_ADDR_MASK; -+ if (size == 4) -+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; -+ -+ status = brcmf_sdioh_request_word(sdiodev, SDIOH_READ, SDIO_FUNC_1, -+ addr, &word, size); -+ -+ sdiodev->regfail = (status != 0); -+ -+ brcmf_dbg(INFO, "u32data = 0x%x\n", word); -+ -+ /* if ok, return appropriately masked word */ -+ if (status == 0) { -+ switch (size) { -+ case sizeof(u8): -+ return word & 0xff; -+ case sizeof(u16): -+ return word & 0xffff; -+ case sizeof(u32): -+ return word; -+ default: -+ sdiodev->regfail = true; -+ -+ } -+ } -+ -+ /* otherwise, bad sdio access or invalid size */ -+ brcmf_dbg(ERROR, "error reading addr 0x%04x size %d\n", addr, size); -+ return 0xFFFFFFFF; -+} -+ -+u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size, -+ u32 data) -+{ -+ int status; -+ uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; -+ int err = 0; -+ -+ brcmf_dbg(INFO, "fun = 1, addr = 0x%x, uint%ddata = 0x%x\n", -+ addr, size * 8, data); -+ -+ if (bar0 != sdiodev->sbwad) { -+ err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); -+ if (err) -+ return err; -+ -+ sdiodev->sbwad = bar0; -+ } -+ -+ addr &= SBSDIO_SB_OFT_ADDR_MASK; -+ if (size == 4) -+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; -+ status = -+ brcmf_sdioh_request_word(sdiodev, SDIOH_WRITE, SDIO_FUNC_1, -+ addr, &data, size); -+ sdiodev->regfail = (status != 0); -+ -+ if (status == 0) -+ return 0; -+ -+ brcmf_dbg(ERROR, "error writing 0x%08x to addr 0x%04x size %d\n", -+ data, addr, size); -+ return 0xFFFFFFFF; -+} -+ -+bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev) -+{ -+ return sdiodev->regfail; -+} -+ -+int -+brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, -+ uint flags, -+ u8 *buf, uint nbytes, struct sk_buff *pkt) -+{ -+ int status; -+ uint incr_fix; -+ uint width; -+ uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; -+ int err = 0; -+ -+ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes); -+ -+ /* Async not implemented yet */ -+ if (flags & SDIO_REQ_ASYNC) -+ return -ENOTSUPP; -+ -+ if (bar0 != sdiodev->sbwad) { -+ err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); -+ if (err) -+ return err; -+ -+ sdiodev->sbwad = bar0; -+ } -+ -+ addr &= SBSDIO_SB_OFT_ADDR_MASK; -+ -+ incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; -+ width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; -+ if (width == 4) -+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; -+ -+ status = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ, -+ fn, addr, width, nbytes, buf, pkt); -+ -+ return status; -+} -+ -+int -+brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, -+ uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt) -+{ -+ uint incr_fix; -+ uint width; -+ uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; -+ int err = 0; -+ -+ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes); -+ -+ /* Async not implemented yet */ -+ if (flags & SDIO_REQ_ASYNC) -+ return -ENOTSUPP; -+ -+ if (bar0 != sdiodev->sbwad) { -+ err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); -+ if (err) -+ return err; -+ -+ sdiodev->sbwad = bar0; -+ } -+ -+ addr &= SBSDIO_SB_OFT_ADDR_MASK; -+ -+ incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; -+ width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; -+ if (width == 4) -+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; -+ -+ return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn, -+ addr, width, nbytes, buf, pkt); -+} -+ -+int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr, -+ u8 *buf, uint nbytes) -+{ -+ addr &= SBSDIO_SB_OFT_ADDR_MASK; -+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; -+ -+ return brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC, -+ (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1, -+ addr, 4, nbytes, buf, NULL); -+} -+ -+int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn) -+{ -+ char t_func = (char)fn; -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* issue abort cmd52 command through F0 */ -+ brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0, -+ SDIO_CCCR_ABORT, &t_func); -+ -+ brcmf_dbg(TRACE, "Exit\n"); -+ return 0; -+} -+ -+int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) -+{ -+ u32 regs = 0; -+ int ret = 0; -+ -+ ret = brcmf_sdioh_attach(sdiodev); -+ if (ret) -+ goto out; -+ -+ regs = SI_ENUM_BASE; -+ -+ /* Report the BAR, to fix if needed */ -+ sdiodev->sbwad = SI_ENUM_BASE; -+ -+ /* try to attach to the target device */ -+ sdiodev->bus = brcmf_sdbrcm_probe(0, 0, 0, 0, regs, sdiodev); -+ if (!sdiodev->bus) { -+ brcmf_dbg(ERROR, "device attach failed\n"); -+ ret = -ENODEV; -+ goto out; -+ } -+ -+out: -+ if (ret) -+ brcmf_sdio_remove(sdiodev); -+ -+ return ret; -+} -+EXPORT_SYMBOL(brcmf_sdio_probe); -+ -+int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev) -+{ -+ if (sdiodev->bus) { -+ brcmf_sdbrcm_disconnect(sdiodev->bus); -+ sdiodev->bus = NULL; -+ } -+ -+ brcmf_sdioh_detach(sdiodev); -+ -+ sdiodev->sbwad = 0; -+ -+ return 0; -+} -+EXPORT_SYMBOL(brcmf_sdio_remove); -+ -+void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable) -+{ -+ if (enable) -+ brcmf_sdbrcm_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS); -+ else -+ brcmf_sdbrcm_wd_timer(sdiodev->bus, 0); -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c.orig 2011-11-09 13:46:58.228800847 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c 2011-11-09 13:47:16.980566416 -0500 -@@ -0,0 +1,626 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* request_irq() */ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include "sdio_host.h" -+#include "dhd.h" -+#include "dhd_dbg.h" -+#include "wl_cfg80211.h" -+ -+#define SDIO_VENDOR_ID_BROADCOM 0x02d0 -+ -+#define DMA_ALIGN_MASK 0x03 -+ -+#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 -+ -+#define SDIO_FUNC1_BLOCKSIZE 64 -+#define SDIO_FUNC2_BLOCKSIZE 512 -+ -+/* devices we support, null terminated */ -+static const struct sdio_device_id brcmf_sdmmc_ids[] = { -+ {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, -+ { /* end: all zeroes */ }, -+}; -+MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); -+ -+static bool -+brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev) -+{ -+ bool is_err = false; -+#ifdef CONFIG_PM_SLEEP -+ is_err = atomic_read(&sdiodev->suspend); -+#endif -+ return is_err; -+} -+ -+static void -+brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, wait_queue_head_t *wq) -+{ -+#ifdef CONFIG_PM_SLEEP -+ int retry = 0; -+ while (atomic_read(&sdiodev->suspend) && retry++ != 30) -+ wait_event_timeout(*wq, false, HZ/100); -+#endif -+} -+ -+static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, -+ uint regaddr, u8 *byte) -+{ -+ struct sdio_func *sdfunc = sdiodev->func[0]; -+ int err_ret; -+ -+ /* -+ * Can only directly write to some F0 registers. -+ * Handle F2 enable/disable and Abort command -+ * as a special case. -+ */ -+ if (regaddr == SDIO_CCCR_IOEx) { -+ sdfunc = sdiodev->func[2]; -+ if (sdfunc) { -+ sdio_claim_host(sdfunc); -+ if (*byte & SDIO_FUNC_ENABLE_2) { -+ /* Enable Function 2 */ -+ err_ret = sdio_enable_func(sdfunc); -+ if (err_ret) -+ brcmf_dbg(ERROR, -+ "enable F2 failed:%d\n", -+ err_ret); -+ } else { -+ /* Disable Function 2 */ -+ err_ret = sdio_disable_func(sdfunc); -+ if (err_ret) -+ brcmf_dbg(ERROR, -+ "Disable F2 failed:%d\n", -+ err_ret); -+ } -+ sdio_release_host(sdfunc); -+ } -+ } else if (regaddr == SDIO_CCCR_ABORT) { -+ sdio_claim_host(sdfunc); -+ sdio_writeb(sdfunc, *byte, regaddr, &err_ret); -+ sdio_release_host(sdfunc); -+ } else if (regaddr < 0xF0) { -+ brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr); -+ err_ret = -EPERM; -+ } else { -+ sdio_claim_host(sdfunc); -+ sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret); -+ sdio_release_host(sdfunc); -+ } -+ -+ return err_ret; -+} -+ -+int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, -+ uint regaddr, u8 *byte) -+{ -+ int err_ret; -+ -+ brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr); -+ -+ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait); -+ if (brcmf_pm_resume_error(sdiodev)) -+ return -EIO; -+ -+ if (rw && func == 0) { -+ /* handle F0 separately */ -+ err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte); -+ } else { -+ sdio_claim_host(sdiodev->func[func]); -+ if (rw) /* CMD52 Write */ -+ sdio_writeb(sdiodev->func[func], *byte, regaddr, -+ &err_ret); -+ else if (func == 0) { -+ *byte = sdio_f0_readb(sdiodev->func[func], regaddr, -+ &err_ret); -+ } else { -+ *byte = sdio_readb(sdiodev->func[func], regaddr, -+ &err_ret); -+ } -+ sdio_release_host(sdiodev->func[func]); -+ } -+ -+ if (err_ret) -+ brcmf_dbg(ERROR, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", -+ rw ? "write" : "read", func, regaddr, *byte, err_ret); -+ -+ return err_ret; -+} -+ -+int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, -+ uint rw, uint func, uint addr, u32 *word, -+ uint nbytes) -+{ -+ int err_ret = -EIO; -+ -+ if (func == 0) { -+ brcmf_dbg(ERROR, "Only CMD52 allowed to F0\n"); -+ return -EINVAL; -+ } -+ -+ brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", -+ rw, func, addr, nbytes); -+ -+ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); -+ if (brcmf_pm_resume_error(sdiodev)) -+ return -EIO; -+ /* Claim host controller */ -+ sdio_claim_host(sdiodev->func[func]); -+ -+ if (rw) { /* CMD52 Write */ -+ if (nbytes == 4) -+ sdio_writel(sdiodev->func[func], *word, addr, -+ &err_ret); -+ else if (nbytes == 2) -+ sdio_writew(sdiodev->func[func], (*word & 0xFFFF), -+ addr, &err_ret); -+ else -+ brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes); -+ } else { /* CMD52 Read */ -+ if (nbytes == 4) -+ *word = sdio_readl(sdiodev->func[func], addr, &err_ret); -+ else if (nbytes == 2) -+ *word = sdio_readw(sdiodev->func[func], addr, -+ &err_ret) & 0xFFFF; -+ else -+ brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes); -+ } -+ -+ /* Release host controller */ -+ sdio_release_host(sdiodev->func[func]); -+ -+ if (err_ret) -+ brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n", -+ rw ? "write" : "read", err_ret); -+ -+ return err_ret; -+} -+ -+static int -+brcmf_sdioh_request_packet(struct brcmf_sdio_dev *sdiodev, uint fix_inc, -+ uint write, uint func, uint addr, -+ struct sk_buff *pkt) -+{ -+ bool fifo = (fix_inc == SDIOH_DATA_FIX); -+ u32 SGCount = 0; -+ int err_ret = 0; -+ -+ struct sk_buff *pnext; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_packet_wait); -+ if (brcmf_pm_resume_error(sdiodev)) -+ return -EIO; -+ -+ /* Claim host controller */ -+ sdio_claim_host(sdiodev->func[func]); -+ for (pnext = pkt; pnext; pnext = pnext->next) { -+ uint pkt_len = pnext->len; -+ pkt_len += 3; -+ pkt_len &= 0xFFFFFFFC; -+ -+ if ((write) && (!fifo)) { -+ err_ret = sdio_memcpy_toio(sdiodev->func[func], addr, -+ ((u8 *) (pnext->data)), -+ pkt_len); -+ } else if (write) { -+ err_ret = sdio_memcpy_toio(sdiodev->func[func], addr, -+ ((u8 *) (pnext->data)), -+ pkt_len); -+ } else if (fifo) { -+ err_ret = sdio_readsb(sdiodev->func[func], -+ ((u8 *) (pnext->data)), -+ addr, pkt_len); -+ } else { -+ err_ret = sdio_memcpy_fromio(sdiodev->func[func], -+ ((u8 *) (pnext->data)), -+ addr, pkt_len); -+ } -+ -+ if (err_ret) { -+ brcmf_dbg(ERROR, "%s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n", -+ write ? "TX" : "RX", pnext, SGCount, addr, -+ pkt_len, err_ret); -+ } else { -+ brcmf_dbg(TRACE, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n", -+ write ? "TX" : "RX", pnext, SGCount, addr, -+ pkt_len); -+ } -+ -+ if (!fifo) -+ addr += pkt_len; -+ SGCount++; -+ -+ } -+ -+ /* Release host controller */ -+ sdio_release_host(sdiodev->func[func]); -+ -+ brcmf_dbg(TRACE, "Exit\n"); -+ return err_ret; -+} -+ -+/* -+ * This function takes a buffer or packet, and fixes everything up -+ * so that in the end, a DMA-able packet is created. -+ * -+ * A buffer does not have an associated packet pointer, -+ * and may or may not be aligned. -+ * A packet may consist of a single packet, or a packet chain. -+ * If it is a packet chain, then all the packets in the chain -+ * must be properly aligned. -+ * -+ * If the packet data is not aligned, then there may only be -+ * one packet, and in this case, it is copied to a new -+ * aligned packet. -+ * -+ */ -+int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, -+ uint fix_inc, uint write, uint func, uint addr, -+ uint reg_width, uint buflen_u, u8 *buffer, -+ struct sk_buff *pkt) -+{ -+ int Status; -+ struct sk_buff *mypkt = NULL; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); -+ if (brcmf_pm_resume_error(sdiodev)) -+ return -EIO; -+ /* Case 1: we don't have a packet. */ -+ if (pkt == NULL) { -+ brcmf_dbg(DATA, "Creating new %s Packet, len=%d\n", -+ write ? "TX" : "RX", buflen_u); -+ mypkt = brcmu_pkt_buf_get_skb(buflen_u); -+ if (!mypkt) { -+ brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n", -+ buflen_u); -+ return -EIO; -+ } -+ -+ /* For a write, copy the buffer data into the packet. */ -+ if (write) -+ memcpy(mypkt->data, buffer, buflen_u); -+ -+ Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write, -+ func, addr, mypkt); -+ -+ /* For a read, copy the packet data back to the buffer. */ -+ if (!write) -+ memcpy(buffer, mypkt->data, buflen_u); -+ -+ brcmu_pkt_buf_free_skb(mypkt); -+ } else if (((ulong) (pkt->data) & DMA_ALIGN_MASK) != 0) { -+ /* -+ * Case 2: We have a packet, but it is unaligned. -+ * In this case, we cannot have a chain (pkt->next == NULL) -+ */ -+ brcmf_dbg(DATA, "Creating aligned %s Packet, len=%d\n", -+ write ? "TX" : "RX", pkt->len); -+ mypkt = brcmu_pkt_buf_get_skb(pkt->len); -+ if (!mypkt) { -+ brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n", -+ pkt->len); -+ return -EIO; -+ } -+ -+ /* For a write, copy the buffer data into the packet. */ -+ if (write) -+ memcpy(mypkt->data, pkt->data, pkt->len); -+ -+ Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write, -+ func, addr, mypkt); -+ -+ /* For a read, copy the packet data back to the buffer. */ -+ if (!write) -+ memcpy(pkt->data, mypkt->data, mypkt->len); -+ -+ brcmu_pkt_buf_free_skb(mypkt); -+ } else { /* case 3: We have a packet and -+ it is aligned. */ -+ brcmf_dbg(DATA, "Aligned %s Packet, direct DMA\n", -+ write ? "Tx" : "Rx"); -+ Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write, -+ func, addr, pkt); -+ } -+ -+ return Status; -+} -+ -+/* Read client card reg */ -+static int -+brcmf_sdioh_card_regread(struct brcmf_sdio_dev *sdiodev, int func, u32 regaddr, -+ int regsize, u32 *data) -+{ -+ -+ if ((func == 0) || (regsize == 1)) { -+ u8 temp = 0; -+ -+ brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, func, regaddr, -+ &temp); -+ *data = temp; -+ *data &= 0xff; -+ brcmf_dbg(DATA, "byte read data=0x%02x\n", *data); -+ } else { -+ brcmf_sdioh_request_word(sdiodev, SDIOH_READ, func, regaddr, -+ data, regsize); -+ if (regsize == 2) -+ *data &= 0xffff; -+ -+ brcmf_dbg(DATA, "word read data=0x%08x\n", *data); -+ } -+ -+ return SUCCESS; -+} -+ -+static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr) -+{ -+ /* read 24 bits and return valid 17 bit addr */ -+ int i; -+ u32 scratch, regdata; -+ __le32 scratch_le; -+ u8 *ptr = (u8 *)&scratch_le; -+ -+ for (i = 0; i < 3; i++) { -+ if ((brcmf_sdioh_card_regread(sdiodev, 0, regaddr, 1, -+ ®data)) != SUCCESS) -+ brcmf_dbg(ERROR, "Can't read!\n"); -+ -+ *ptr++ = (u8) regdata; -+ regaddr++; -+ } -+ -+ /* Only the lower 17-bits are valid */ -+ scratch = le32_to_cpu(scratch_le); -+ scratch &= 0x0001FFFF; -+ return scratch; -+} -+ -+static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev) -+{ -+ int err_ret; -+ u32 fbraddr; -+ u8 func; -+ -+ brcmf_dbg(TRACE, "\n"); -+ -+ /* Get the Card's common CIS address */ -+ sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev, -+ SDIO_CCCR_CIS); -+ brcmf_dbg(INFO, "Card's Common CIS Ptr = 0x%x\n", -+ sdiodev->func_cis_ptr[0]); -+ -+ /* Get the Card's function CIS (for each function) */ -+ for (fbraddr = SDIO_FBR_BASE(1), func = 1; -+ func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { -+ sdiodev->func_cis_ptr[func] = -+ brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr); -+ brcmf_dbg(INFO, "Function %d CIS Ptr = 0x%x\n", -+ func, sdiodev->func_cis_ptr[func]); -+ } -+ -+ /* Enable Function 1 */ -+ sdio_claim_host(sdiodev->func[1]); -+ err_ret = sdio_enable_func(sdiodev->func[1]); -+ sdio_release_host(sdiodev->func[1]); -+ if (err_ret) -+ brcmf_dbg(ERROR, "Failed to enable F1 Err: 0x%08x\n", err_ret); -+ -+ return false; -+} -+ -+/* -+ * Public entry points & extern's -+ */ -+int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev) -+{ -+ int err_ret = 0; -+ -+ brcmf_dbg(TRACE, "\n"); -+ -+ sdiodev->num_funcs = 2; -+ -+ sdio_claim_host(sdiodev->func[1]); -+ err_ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE); -+ sdio_release_host(sdiodev->func[1]); -+ if (err_ret) { -+ brcmf_dbg(ERROR, "Failed to set F1 blocksize\n"); -+ goto out; -+ } -+ -+ sdio_claim_host(sdiodev->func[2]); -+ err_ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE); -+ sdio_release_host(sdiodev->func[2]); -+ if (err_ret) { -+ brcmf_dbg(ERROR, "Failed to set F2 blocksize\n"); -+ goto out; -+ } -+ -+ brcmf_sdioh_enablefuncs(sdiodev); -+ -+out: -+ brcmf_dbg(TRACE, "Done\n"); -+ return err_ret; -+} -+ -+void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev) -+{ -+ brcmf_dbg(TRACE, "\n"); -+ -+ /* Disable Function 2 */ -+ sdio_claim_host(sdiodev->func[2]); -+ sdio_disable_func(sdiodev->func[2]); -+ sdio_release_host(sdiodev->func[2]); -+ -+ /* Disable Function 1 */ -+ sdio_claim_host(sdiodev->func[1]); -+ sdio_disable_func(sdiodev->func[1]); -+ sdio_release_host(sdiodev->func[1]); -+ -+} -+ -+static int brcmf_ops_sdio_probe(struct sdio_func *func, -+ const struct sdio_device_id *id) -+{ -+ int ret = 0; -+ struct brcmf_sdio_dev *sdiodev; -+ brcmf_dbg(TRACE, "Enter\n"); -+ brcmf_dbg(TRACE, "func->class=%x\n", func->class); -+ brcmf_dbg(TRACE, "sdio_vendor: 0x%04x\n", func->vendor); -+ brcmf_dbg(TRACE, "sdio_device: 0x%04x\n", func->device); -+ brcmf_dbg(TRACE, "Function#: 0x%04x\n", func->num); -+ -+ if (func->num == 1) { -+ if (dev_get_drvdata(&func->card->dev)) { -+ brcmf_dbg(ERROR, "card private drvdata occupied\n"); -+ return -ENXIO; -+ } -+ sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL); -+ if (!sdiodev) -+ return -ENOMEM; -+ sdiodev->func[0] = func->card->sdio_func[0]; -+ sdiodev->func[1] = func; -+ dev_set_drvdata(&func->card->dev, sdiodev); -+ -+ atomic_set(&sdiodev->suspend, false); -+ init_waitqueue_head(&sdiodev->request_byte_wait); -+ init_waitqueue_head(&sdiodev->request_word_wait); -+ init_waitqueue_head(&sdiodev->request_packet_wait); -+ init_waitqueue_head(&sdiodev->request_buffer_wait); -+ } -+ -+ if (func->num == 2) { -+ sdiodev = dev_get_drvdata(&func->card->dev); -+ if ((!sdiodev) || (sdiodev->func[1]->card != func->card)) -+ return -ENODEV; -+ sdiodev->func[2] = func; -+ -+ brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n"); -+ ret = brcmf_sdio_probe(sdiodev); -+ } -+ -+ return ret; -+} -+ -+static void brcmf_ops_sdio_remove(struct sdio_func *func) -+{ -+ struct brcmf_sdio_dev *sdiodev; -+ brcmf_dbg(TRACE, "Enter\n"); -+ brcmf_dbg(INFO, "func->class=%x\n", func->class); -+ brcmf_dbg(INFO, "sdio_vendor: 0x%04x\n", func->vendor); -+ brcmf_dbg(INFO, "sdio_device: 0x%04x\n", func->device); -+ brcmf_dbg(INFO, "Function#: 0x%04x\n", func->num); -+ -+ if (func->num == 2) { -+ sdiodev = dev_get_drvdata(&func->card->dev); -+ brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n"); -+ brcmf_sdio_remove(sdiodev); -+ dev_set_drvdata(&func->card->dev, NULL); -+ kfree(sdiodev); -+ } -+} -+ -+#ifdef CONFIG_PM_SLEEP -+static int brcmf_sdio_suspend(struct device *dev) -+{ -+ mmc_pm_flag_t sdio_flags; -+ struct brcmf_sdio_dev *sdiodev; -+ struct sdio_func *func = dev_to_sdio_func(dev); -+ int ret = 0; -+ -+ brcmf_dbg(TRACE, "\n"); -+ -+ sdiodev = dev_get_drvdata(&func->card->dev); -+ -+ atomic_set(&sdiodev->suspend, true); -+ -+ sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]); -+ if (!(sdio_flags & MMC_PM_KEEP_POWER)) { -+ brcmf_dbg(ERROR, "Host can't keep power while suspended\n"); -+ return -EINVAL; -+ } -+ -+ ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER); -+ if (ret) { -+ brcmf_dbg(ERROR, "Failed to set pm_flags\n"); -+ return ret; -+ } -+ -+ brcmf_sdio_wdtmr_enable(sdiodev, false); -+ -+ return ret; -+} -+ -+static int brcmf_sdio_resume(struct device *dev) -+{ -+ struct brcmf_sdio_dev *sdiodev; -+ struct sdio_func *func = dev_to_sdio_func(dev); -+ -+ sdiodev = dev_get_drvdata(&func->card->dev); -+ brcmf_sdio_wdtmr_enable(sdiodev, true); -+ atomic_set(&sdiodev->suspend, false); -+ return 0; -+} -+ -+static const struct dev_pm_ops brcmf_sdio_pm_ops = { -+ .suspend = brcmf_sdio_suspend, -+ .resume = brcmf_sdio_resume, -+}; -+#endif /* CONFIG_PM_SLEEP */ -+ -+static struct sdio_driver brcmf_sdmmc_driver = { -+ .probe = brcmf_ops_sdio_probe, -+ .remove = brcmf_ops_sdio_remove, -+ .name = "brcmfmac", -+ .id_table = brcmf_sdmmc_ids, -+#ifdef CONFIG_PM_SLEEP -+ .drv = { -+ .pm = &brcmf_sdio_pm_ops, -+ }, -+#endif /* CONFIG_PM_SLEEP */ -+}; -+ -+/* bus register interface */ -+int brcmf_bus_register(void) -+{ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ return sdio_register_driver(&brcmf_sdmmc_driver); -+} -+ -+void brcmf_bus_unregister(void) -+{ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ sdio_unregister_driver(&brcmf_sdmmc_driver); -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h.orig 2011-11-09 13:46:58.229800834 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h 2011-11-09 13:47:16.980566416 -0500 -@@ -0,0 +1,57 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCMF_BUS_H_ -+#define _BRCMF_BUS_H_ -+ -+/* Packet alignment for most efficient SDIO (can change based on platform) */ -+#define BRCMF_SDALIGN (1 << 6) -+ -+/* watchdog polling interval in ms */ -+#define BRCMF_WD_POLL_MS 10 -+ -+/* -+ * Exported from brcmf bus module (brcmf_usb, brcmf_sdio) -+ */ -+ -+/* Indicate (dis)interest in finding dongles. */ -+extern int brcmf_bus_register(void); -+extern void brcmf_bus_unregister(void); -+ -+/* obtain linux device object providing bus function */ -+extern struct device *brcmf_bus_get_device(struct brcmf_bus *bus); -+ -+/* Stop bus module: clear pending frames, disable data flow */ -+extern void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus); -+ -+/* Initialize bus module: prepare for communication w/dongle */ -+extern int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr); -+ -+/* Send a data frame to the dongle. Callee disposes of txp. */ -+extern int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *txp); -+ -+/* Send/receive a control message to/from the dongle. -+ * Expects caller to enforce a single outstanding transaction. -+ */ -+extern int -+brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen); -+ -+extern int -+brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen); -+ -+extern void brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick); -+ -+#endif /* _BRCMF_BUS_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c.orig 2011-11-09 13:46:58.230800821 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c 2011-11-09 13:47:16.981566403 -0500 -@@ -0,0 +1,498 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/******************************************************************************* -+ * Communicates with the dongle by using dcmd codes. -+ * For certain dcmd codes, the dongle interprets string data from the host. -+ ******************************************************************************/ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "dhd.h" -+#include "dhd_proto.h" -+#include "dhd_bus.h" -+#include "dhd_dbg.h" -+ -+struct brcmf_proto_cdc_dcmd { -+ __le32 cmd; /* dongle command value */ -+ __le32 len; /* lower 16: output buflen; -+ * upper 16: input buflen (excludes header) */ -+ __le32 flags; /* flag defns given below */ -+ __le32 status; /* status code returned from the device */ -+}; -+ -+/* Max valid buffer size that can be sent to the dongle */ -+#define CDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN) -+ -+/* CDC flag definitions */ -+#define CDC_DCMD_ERROR 0x01 /* 1=cmd failed */ -+#define CDC_DCMD_SET 0x02 /* 0=get, 1=set cmd */ -+#define CDC_DCMD_IF_MASK 0xF000 /* I/F index */ -+#define CDC_DCMD_IF_SHIFT 12 -+#define CDC_DCMD_ID_MASK 0xFFFF0000 /* id an cmd pairing */ -+#define CDC_DCMD_ID_SHIFT 16 /* ID Mask shift bits */ -+#define CDC_DCMD_ID(flags) \ -+ (((flags) & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT) -+ -+/* -+ * BDC header - Broadcom specific extension of CDC. -+ * Used on data packets to convey priority across USB. -+ */ -+#define BDC_HEADER_LEN 4 -+#define BDC_PROTO_VER 1 /* Protocol version */ -+#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ -+#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ -+#define BDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */ -+#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */ -+#define BDC_PRIORITY_MASK 0x7 -+#define BDC_FLAG2_IF_MASK 0x0f /* packet rx interface in APSTA */ -+#define BDC_FLAG2_IF_SHIFT 0 -+ -+#define BDC_GET_IF_IDX(hdr) \ -+ ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT)) -+#define BDC_SET_IF_IDX(hdr, idx) \ -+ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \ -+ ((idx) << BDC_FLAG2_IF_SHIFT))) -+ -+struct brcmf_proto_bdc_header { -+ u8 flags; -+ u8 priority; /* 802.1d Priority, 4:7 flow control info for usb */ -+ u8 flags2; -+ u8 rssi; -+}; -+ -+ -+#define RETRIES 2 /* # of retries to retrieve matching dcmd response */ -+#define BUS_HEADER_LEN (16+BRCMF_SDALIGN) /* Must be atleast SDPCM_RESERVE -+ * (amount of header tha might be added) -+ * plus any space that might be needed -+ * for alignment padding. -+ */ -+#define ROUND_UP_MARGIN 2048 /* Biggest SDIO block size possible for -+ * round off at the end of buffer -+ */ -+ -+struct brcmf_proto { -+ u16 reqid; -+ u8 pending; -+ u32 lastcmd; -+ u8 bus_header[BUS_HEADER_LEN]; -+ struct brcmf_proto_cdc_dcmd msg; -+ unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN]; -+}; -+ -+static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr) -+{ -+ struct brcmf_proto *prot = drvr->prot; -+ int len = le32_to_cpu(prot->msg.len) + -+ sizeof(struct brcmf_proto_cdc_dcmd); -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* NOTE : cdc->msg.len holds the desired length of the buffer to be -+ * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area -+ * is actually sent to the dongle -+ */ -+ if (len > CDC_MAX_MSG_SIZE) -+ len = CDC_MAX_MSG_SIZE; -+ -+ /* Send request */ -+ return brcmf_sdbrcm_bus_txctl(drvr->bus, (unsigned char *)&prot->msg, -+ len); -+} -+ -+static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) -+{ -+ int ret; -+ struct brcmf_proto *prot = drvr->prot; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ do { -+ ret = brcmf_sdbrcm_bus_rxctl(drvr->bus, -+ (unsigned char *)&prot->msg, -+ len + sizeof(struct brcmf_proto_cdc_dcmd)); -+ if (ret < 0) -+ break; -+ } while (CDC_DCMD_ID(le32_to_cpu(prot->msg.flags)) != id); -+ -+ return ret; -+} -+ -+int -+brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, -+ void *buf, uint len) -+{ -+ struct brcmf_proto *prot = drvr->prot; -+ struct brcmf_proto_cdc_dcmd *msg = &prot->msg; -+ void *info; -+ int ret = 0, retries = 0; -+ u32 id, flags; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ brcmf_dbg(CTL, "cmd %d len %d\n", cmd, len); -+ -+ /* Respond "bcmerror" and "bcmerrorstr" with local cache */ -+ if (cmd == BRCMF_C_GET_VAR && buf) { -+ if (!strcmp((char *)buf, "bcmerrorstr")) { -+ strncpy((char *)buf, "bcm_error", -+ BCME_STRLEN); -+ goto done; -+ } else if (!strcmp((char *)buf, "bcmerror")) { -+ *(int *)buf = drvr->dongle_error; -+ goto done; -+ } -+ } -+ -+ memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); -+ -+ msg->cmd = cpu_to_le32(cmd); -+ msg->len = cpu_to_le32(len); -+ flags = (++prot->reqid << CDC_DCMD_ID_SHIFT); -+ flags = (flags & ~CDC_DCMD_IF_MASK) | -+ (ifidx << CDC_DCMD_IF_SHIFT); -+ msg->flags = cpu_to_le32(flags); -+ -+ if (buf) -+ memcpy(prot->buf, buf, len); -+ -+ ret = brcmf_proto_cdc_msg(drvr); -+ if (ret < 0) { -+ brcmf_dbg(ERROR, "brcmf_proto_cdc_msg failed w/status %d\n", -+ ret); -+ goto done; -+ } -+ -+retry: -+ /* wait for interrupt and get first fragment */ -+ ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len); -+ if (ret < 0) -+ goto done; -+ -+ flags = le32_to_cpu(msg->flags); -+ id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT; -+ -+ if ((id < prot->reqid) && (++retries < RETRIES)) -+ goto retry; -+ if (id != prot->reqid) { -+ brcmf_dbg(ERROR, "%s: unexpected request id %d (expected %d)\n", -+ brcmf_ifname(drvr, ifidx), id, prot->reqid); -+ ret = -EINVAL; -+ goto done; -+ } -+ -+ /* Check info buffer */ -+ info = (void *)&msg[1]; -+ -+ /* Copy info buffer */ -+ if (buf) { -+ if (ret < (int)len) -+ len = ret; -+ memcpy(buf, info, len); -+ } -+ -+ /* Check the ERROR flag */ -+ if (flags & CDC_DCMD_ERROR) { -+ ret = le32_to_cpu(msg->status); -+ /* Cache error from dongle */ -+ drvr->dongle_error = ret; -+ } -+ -+done: -+ return ret; -+} -+ -+int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, -+ void *buf, uint len) -+{ -+ struct brcmf_proto *prot = drvr->prot; -+ struct brcmf_proto_cdc_dcmd *msg = &prot->msg; -+ int ret = 0; -+ u32 flags, id; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ brcmf_dbg(CTL, "cmd %d len %d\n", cmd, len); -+ -+ memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); -+ -+ msg->cmd = cpu_to_le32(cmd); -+ msg->len = cpu_to_le32(len); -+ flags = (++prot->reqid << CDC_DCMD_ID_SHIFT) | CDC_DCMD_SET; -+ flags = (flags & ~CDC_DCMD_IF_MASK) | -+ (ifidx << CDC_DCMD_IF_SHIFT); -+ msg->flags = cpu_to_le32(flags); -+ -+ if (buf) -+ memcpy(prot->buf, buf, len); -+ -+ ret = brcmf_proto_cdc_msg(drvr); -+ if (ret < 0) -+ goto done; -+ -+ ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len); -+ if (ret < 0) -+ goto done; -+ -+ flags = le32_to_cpu(msg->flags); -+ id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT; -+ -+ if (id != prot->reqid) { -+ brcmf_dbg(ERROR, "%s: unexpected request id %d (expected %d)\n", -+ brcmf_ifname(drvr, ifidx), id, prot->reqid); -+ ret = -EINVAL; -+ goto done; -+ } -+ -+ /* Check the ERROR flag */ -+ if (flags & CDC_DCMD_ERROR) { -+ ret = le32_to_cpu(msg->status); -+ /* Cache error from dongle */ -+ drvr->dongle_error = ret; -+ } -+ -+done: -+ return ret; -+} -+ -+int -+brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, struct brcmf_dcmd *dcmd, -+ int len) -+{ -+ struct brcmf_proto *prot = drvr->prot; -+ int ret = -1; -+ -+ if (drvr->busstate == BRCMF_BUS_DOWN) { -+ brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n"); -+ return ret; -+ } -+ brcmf_os_proto_block(drvr); -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ if (len > BRCMF_DCMD_MAXLEN) -+ goto done; -+ -+ if (prot->pending == true) { -+ brcmf_dbg(TRACE, "CDC packet is pending!!!! cmd=0x%x (%lu) lastcmd=0x%x (%lu)\n", -+ dcmd->cmd, (unsigned long)dcmd->cmd, prot->lastcmd, -+ (unsigned long)prot->lastcmd); -+ if (dcmd->cmd == BRCMF_C_SET_VAR || -+ dcmd->cmd == BRCMF_C_GET_VAR) -+ brcmf_dbg(TRACE, "iovar cmd=%s\n", (char *)dcmd->buf); -+ -+ goto done; -+ } -+ -+ prot->pending = true; -+ prot->lastcmd = dcmd->cmd; -+ if (dcmd->set) -+ ret = brcmf_proto_cdc_set_dcmd(drvr, ifidx, dcmd->cmd, -+ dcmd->buf, len); -+ else { -+ ret = brcmf_proto_cdc_query_dcmd(drvr, ifidx, dcmd->cmd, -+ dcmd->buf, len); -+ if (ret > 0) -+ dcmd->used = ret - -+ sizeof(struct brcmf_proto_cdc_dcmd); -+ } -+ -+ if (ret >= 0) -+ ret = 0; -+ else { -+ struct brcmf_proto_cdc_dcmd *msg = &prot->msg; -+ /* len == needed when set/query fails from dongle */ -+ dcmd->needed = le32_to_cpu(msg->len); -+ } -+ -+ /* Intercept the wme_dp dongle cmd here */ -+ if (!ret && dcmd->cmd == BRCMF_C_SET_VAR && -+ !strcmp(dcmd->buf, "wme_dp")) { -+ int slen; -+ __le32 val = 0; -+ -+ slen = strlen("wme_dp") + 1; -+ if (len >= (int)(slen + sizeof(int))) -+ memcpy(&val, (char *)dcmd->buf + slen, sizeof(int)); -+ drvr->wme_dp = (u8) le32_to_cpu(val); -+ } -+ -+ prot->pending = false; -+ -+done: -+ brcmf_os_proto_unblock(drvr); -+ -+ return ret; -+} -+ -+static bool pkt_sum_needed(struct sk_buff *skb) -+{ -+ return skb->ip_summed == CHECKSUM_PARTIAL; -+} -+ -+static void pkt_set_sum_good(struct sk_buff *skb, bool x) -+{ -+ skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE); -+} -+ -+void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, -+ struct sk_buff *pktbuf) -+{ -+ struct brcmf_proto_bdc_header *h; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* Push BDC header used to convey priority for buses that don't */ -+ -+ skb_push(pktbuf, BDC_HEADER_LEN); -+ -+ h = (struct brcmf_proto_bdc_header *)(pktbuf->data); -+ -+ h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); -+ if (pkt_sum_needed(pktbuf)) -+ h->flags |= BDC_FLAG_SUM_NEEDED; -+ -+ h->priority = (pktbuf->priority & BDC_PRIORITY_MASK); -+ h->flags2 = 0; -+ h->rssi = 0; -+ BDC_SET_IF_IDX(h, ifidx); -+} -+ -+int brcmf_proto_hdrpull(struct brcmf_pub *drvr, int *ifidx, -+ struct sk_buff *pktbuf) -+{ -+ struct brcmf_proto_bdc_header *h; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* Pop BDC header used to convey priority for buses that don't */ -+ -+ if (pktbuf->len < BDC_HEADER_LEN) { -+ brcmf_dbg(ERROR, "rx data too short (%d < %d)\n", -+ pktbuf->len, BDC_HEADER_LEN); -+ return -EBADE; -+ } -+ -+ h = (struct brcmf_proto_bdc_header *)(pktbuf->data); -+ -+ *ifidx = BDC_GET_IF_IDX(h); -+ if (*ifidx >= BRCMF_MAX_IFS) { -+ brcmf_dbg(ERROR, "rx data ifnum out of range (%d)\n", *ifidx); -+ return -EBADE; -+ } -+ -+ if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) != -+ BDC_PROTO_VER) { -+ brcmf_dbg(ERROR, "%s: non-BDC packet received, flags 0x%x\n", -+ brcmf_ifname(drvr, *ifidx), h->flags); -+ return -EBADE; -+ } -+ -+ if (h->flags & BDC_FLAG_SUM_GOOD) { -+ brcmf_dbg(INFO, "%s: BDC packet received with good rx-csum, flags 0x%x\n", -+ brcmf_ifname(drvr, *ifidx), h->flags); -+ pkt_set_sum_good(pktbuf, true); -+ } -+ -+ pktbuf->priority = h->priority & BDC_PRIORITY_MASK; -+ -+ skb_pull(pktbuf, BDC_HEADER_LEN); -+ -+ return 0; -+} -+ -+int brcmf_proto_attach(struct brcmf_pub *drvr) -+{ -+ struct brcmf_proto *cdc; -+ -+ cdc = kzalloc(sizeof(struct brcmf_proto), GFP_ATOMIC); -+ if (!cdc) -+ goto fail; -+ -+ /* ensure that the msg buf directly follows the cdc msg struct */ -+ if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) { -+ brcmf_dbg(ERROR, "struct brcmf_proto is not correctly defined\n"); -+ goto fail; -+ } -+ -+ drvr->prot = cdc; -+ drvr->hdrlen += BDC_HEADER_LEN; -+ drvr->maxctl = BRCMF_DCMD_MAXLEN + -+ sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN; -+ return 0; -+ -+fail: -+ kfree(cdc); -+ return -ENOMEM; -+} -+ -+/* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */ -+void brcmf_proto_detach(struct brcmf_pub *drvr) -+{ -+ kfree(drvr->prot); -+ drvr->prot = NULL; -+} -+ -+void brcmf_proto_dstats(struct brcmf_pub *drvr) -+{ -+ /* No stats from dongle added yet, copy bus stats */ -+ drvr->dstats.tx_packets = drvr->tx_packets; -+ drvr->dstats.tx_errors = drvr->tx_errors; -+ drvr->dstats.rx_packets = drvr->rx_packets; -+ drvr->dstats.rx_errors = drvr->rx_errors; -+ drvr->dstats.rx_dropped = drvr->rx_dropped; -+ drvr->dstats.multicast = drvr->rx_multicast; -+ return; -+} -+ -+int brcmf_proto_init(struct brcmf_pub *drvr) -+{ -+ int ret = 0; -+ char buf[128]; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ brcmf_os_proto_block(drvr); -+ -+ /* Get the device MAC address */ -+ strcpy(buf, "cur_etheraddr"); -+ ret = brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, -+ buf, sizeof(buf)); -+ if (ret < 0) { -+ brcmf_os_proto_unblock(drvr); -+ return ret; -+ } -+ memcpy(drvr->mac, buf, ETH_ALEN); -+ -+ brcmf_os_proto_unblock(drvr); -+ -+ ret = brcmf_c_preinit_dcmds(drvr); -+ -+ /* Always assumes wl for now */ -+ drvr->iswl = true; -+ -+ return ret; -+} -+ -+void brcmf_proto_stop(struct brcmf_pub *drvr) -+{ -+ /* Nothing to do for CDC */ -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c.orig 2011-11-09 13:46:58.230800821 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c 2011-11-09 13:47:16.981566403 -0500 -@@ -0,0 +1,895 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "dhd.h" -+#include "dhd_bus.h" -+#include "dhd_proto.h" -+#include "dhd_dbg.h" -+ -+#define BRCM_OUI "\x00\x10\x18" -+#define DOT11_OUI_LEN 3 -+#define BCMILCP_BCM_SUBTYPE_EVENT 1 -+#define PKTFILTER_BUF_SIZE 2048 -+#define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */ -+ -+int brcmf_msg_level; -+ -+#define MSGTRACE_VERSION 1 -+ -+#define BRCMF_PKT_FILTER_FIXED_LEN offsetof(struct brcmf_pkt_filter_le, u) -+#define BRCMF_PKT_FILTER_PATTERN_FIXED_LEN \ -+ offsetof(struct brcmf_pkt_filter_pattern_le, mask_and_pattern) -+ -+#ifdef BCMDBG -+static const char brcmf_version[] = -+ "Dongle Host Driver, version " BRCMF_VERSION_STR "\nCompiled on " -+ __DATE__ " at " __TIME__; -+#else -+static const char brcmf_version[] = -+ "Dongle Host Driver, version " BRCMF_VERSION_STR; -+#endif -+ -+/* Message trace header */ -+struct msgtrace_hdr { -+ u8 version; -+ u8 spare; -+ __be16 len; /* Len of the trace */ -+ __be32 seqnum; /* Sequence number of message. Useful -+ * if the messsage has been lost -+ * because of DMA error or a bus reset -+ * (ex: SDIO Func2) -+ */ -+ __be32 discarded_bytes; /* Number of discarded bytes because of -+ trace overflow */ -+ __be32 discarded_printf; /* Number of discarded printf -+ because of trace overflow */ -+} __packed; -+ -+ -+uint -+brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) -+{ -+ uint len; -+ -+ len = strlen(name) + 1; -+ -+ if ((len + datalen) > buflen) -+ return 0; -+ -+ strncpy(buf, name, buflen); -+ -+ /* append data onto the end of the name string */ -+ memcpy(&buf[len], data, datalen); -+ len += datalen; -+ -+ return len; -+} -+ -+void brcmf_c_init(void) -+{ -+ /* Init global variables at run-time, not as part of the declaration. -+ * This is required to support init/de-init of the driver. -+ * Initialization -+ * of globals as part of the declaration results in non-deterministic -+ * behaviour since the value of the globals may be different on the -+ * first time that the driver is initialized vs subsequent -+ * initializations. -+ */ -+ brcmf_msg_level = BRCMF_ERROR_VAL; -+} -+ -+bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q, -+ struct sk_buff *pkt, int prec) -+{ -+ struct sk_buff *p; -+ int eprec = -1; /* precedence to evict from */ -+ bool discard_oldest; -+ -+ /* Fast case, precedence queue is not full and we are also not -+ * exceeding total queue length -+ */ -+ if (!pktq_pfull(q, prec) && !pktq_full(q)) { -+ brcmu_pktq_penq(q, prec, pkt); -+ return true; -+ } -+ -+ /* Determine precedence from which to evict packet, if any */ -+ if (pktq_pfull(q, prec)) -+ eprec = prec; -+ else if (pktq_full(q)) { -+ p = brcmu_pktq_peek_tail(q, &eprec); -+ if (eprec > prec) -+ return false; -+ } -+ -+ /* Evict if needed */ -+ if (eprec >= 0) { -+ /* Detect queueing to unconfigured precedence */ -+ discard_oldest = ac_bitmap_tst(drvr->wme_dp, eprec); -+ if (eprec == prec && !discard_oldest) -+ return false; /* refuse newer (incoming) packet */ -+ /* Evict packet according to discard policy */ -+ p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) : -+ brcmu_pktq_pdeq_tail(q, eprec); -+ if (p == NULL) -+ brcmf_dbg(ERROR, "brcmu_pktq_penq() failed, oldest %d\n", -+ discard_oldest); -+ -+ brcmu_pkt_buf_free_skb(p); -+ } -+ -+ /* Enqueue */ -+ p = brcmu_pktq_penq(q, prec, pkt); -+ if (p == NULL) -+ brcmf_dbg(ERROR, "brcmu_pktq_penq() failed\n"); -+ -+ return p != NULL; -+} -+ -+#ifdef BCMDBG -+static void -+brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data) -+{ -+ uint i, status, reason; -+ bool group = false, flush_txq = false, link = false; -+ char *auth_str, *event_name; -+ unsigned char *buf; -+ char err_msg[256], eabuf[ETHER_ADDR_STR_LEN]; -+ static struct { -+ uint event; -+ char *event_name; -+ } event_names[] = { -+ { -+ BRCMF_E_SET_SSID, "SET_SSID"}, { -+ BRCMF_E_JOIN, "JOIN"}, { -+ BRCMF_E_START, "START"}, { -+ BRCMF_E_AUTH, "AUTH"}, { -+ BRCMF_E_AUTH_IND, "AUTH_IND"}, { -+ BRCMF_E_DEAUTH, "DEAUTH"}, { -+ BRCMF_E_DEAUTH_IND, "DEAUTH_IND"}, { -+ BRCMF_E_ASSOC, "ASSOC"}, { -+ BRCMF_E_ASSOC_IND, "ASSOC_IND"}, { -+ BRCMF_E_REASSOC, "REASSOC"}, { -+ BRCMF_E_REASSOC_IND, "REASSOC_IND"}, { -+ BRCMF_E_DISASSOC, "DISASSOC"}, { -+ BRCMF_E_DISASSOC_IND, "DISASSOC_IND"}, { -+ BRCMF_E_QUIET_START, "START_QUIET"}, { -+ BRCMF_E_QUIET_END, "END_QUIET"}, { -+ BRCMF_E_BEACON_RX, "BEACON_RX"}, { -+ BRCMF_E_LINK, "LINK"}, { -+ BRCMF_E_MIC_ERROR, "MIC_ERROR"}, { -+ BRCMF_E_NDIS_LINK, "NDIS_LINK"}, { -+ BRCMF_E_ROAM, "ROAM"}, { -+ BRCMF_E_TXFAIL, "TXFAIL"}, { -+ BRCMF_E_PMKID_CACHE, "PMKID_CACHE"}, { -+ BRCMF_E_RETROGRADE_TSF, "RETROGRADE_TSF"}, { -+ BRCMF_E_PRUNE, "PRUNE"}, { -+ BRCMF_E_AUTOAUTH, "AUTOAUTH"}, { -+ BRCMF_E_EAPOL_MSG, "EAPOL_MSG"}, { -+ BRCMF_E_SCAN_COMPLETE, "SCAN_COMPLETE"}, { -+ BRCMF_E_ADDTS_IND, "ADDTS_IND"}, { -+ BRCMF_E_DELTS_IND, "DELTS_IND"}, { -+ BRCMF_E_BCNSENT_IND, "BCNSENT_IND"}, { -+ BRCMF_E_BCNRX_MSG, "BCNRX_MSG"}, { -+ BRCMF_E_BCNLOST_MSG, "BCNLOST_MSG"}, { -+ BRCMF_E_ROAM_PREP, "ROAM_PREP"}, { -+ BRCMF_E_PFN_NET_FOUND, "PNO_NET_FOUND"}, { -+ BRCMF_E_PFN_NET_LOST, "PNO_NET_LOST"}, { -+ BRCMF_E_RESET_COMPLETE, "RESET_COMPLETE"}, { -+ BRCMF_E_JOIN_START, "JOIN_START"}, { -+ BRCMF_E_ROAM_START, "ROAM_START"}, { -+ BRCMF_E_ASSOC_START, "ASSOC_START"}, { -+ BRCMF_E_IBSS_ASSOC, "IBSS_ASSOC"}, { -+ BRCMF_E_RADIO, "RADIO"}, { -+ BRCMF_E_PSM_WATCHDOG, "PSM_WATCHDOG"}, { -+ BRCMF_E_PROBREQ_MSG, "PROBREQ_MSG"}, { -+ BRCMF_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND"}, { -+ BRCMF_E_PSK_SUP, "PSK_SUP"}, { -+ BRCMF_E_COUNTRY_CODE_CHANGED, "COUNTRY_CODE_CHANGED"}, { -+ BRCMF_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME"}, { -+ BRCMF_E_ICV_ERROR, "ICV_ERROR"}, { -+ BRCMF_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR"}, { -+ BRCMF_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR"}, { -+ BRCMF_E_TRACE, "TRACE"}, { -+ BRCMF_E_ACTION_FRAME, "ACTION FRAME"}, { -+ BRCMF_E_ACTION_FRAME_COMPLETE, "ACTION FRAME TX COMPLETE"}, { -+ BRCMF_E_IF, "IF"}, { -+ BRCMF_E_RSSI, "RSSI"}, { -+ BRCMF_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"} -+ }; -+ uint event_type, flags, auth_type, datalen; -+ static u32 seqnum_prev; -+ struct msgtrace_hdr hdr; -+ u32 nblost; -+ char *s, *p; -+ -+ event_type = be32_to_cpu(event->event_type); -+ flags = be16_to_cpu(event->flags); -+ status = be32_to_cpu(event->status); -+ reason = be32_to_cpu(event->reason); -+ auth_type = be32_to_cpu(event->auth_type); -+ datalen = be32_to_cpu(event->datalen); -+ /* debug dump of event messages */ -+ sprintf(eabuf, "%pM", event->addr); -+ -+ event_name = "UNKNOWN"; -+ for (i = 0; i < ARRAY_SIZE(event_names); i++) { -+ if (event_names[i].event == event_type) -+ event_name = event_names[i].event_name; -+ } -+ -+ brcmf_dbg(EVENT, "EVENT: %s, event ID = %d\n", event_name, event_type); -+ brcmf_dbg(EVENT, "flags 0x%04x, status %d, reason %d, auth_type %d MAC %s\n", -+ flags, status, reason, auth_type, eabuf); -+ -+ if (flags & BRCMF_EVENT_MSG_LINK) -+ link = true; -+ if (flags & BRCMF_EVENT_MSG_GROUP) -+ group = true; -+ if (flags & BRCMF_EVENT_MSG_FLUSHTXQ) -+ flush_txq = true; -+ -+ switch (event_type) { -+ case BRCMF_E_START: -+ case BRCMF_E_DEAUTH: -+ case BRCMF_E_DISASSOC: -+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf); -+ break; -+ -+ case BRCMF_E_ASSOC_IND: -+ case BRCMF_E_REASSOC_IND: -+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf); -+ break; -+ -+ case BRCMF_E_ASSOC: -+ case BRCMF_E_REASSOC: -+ if (status == BRCMF_E_STATUS_SUCCESS) -+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, SUCCESS\n", -+ event_name, eabuf); -+ else if (status == BRCMF_E_STATUS_TIMEOUT) -+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, TIMEOUT\n", -+ event_name, eabuf); -+ else if (status == BRCMF_E_STATUS_FAIL) -+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, FAILURE, reason %d\n", -+ event_name, eabuf, (int)reason); -+ else -+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, unexpected status %d\n", -+ event_name, eabuf, (int)status); -+ break; -+ -+ case BRCMF_E_DEAUTH_IND: -+ case BRCMF_E_DISASSOC_IND: -+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, reason %d\n", -+ event_name, eabuf, (int)reason); -+ break; -+ -+ case BRCMF_E_AUTH: -+ case BRCMF_E_AUTH_IND: -+ if (auth_type == WLAN_AUTH_OPEN) -+ auth_str = "Open System"; -+ else if (auth_type == WLAN_AUTH_SHARED_KEY) -+ auth_str = "Shared Key"; -+ else { -+ sprintf(err_msg, "AUTH unknown: %d", (int)auth_type); -+ auth_str = err_msg; -+ } -+ if (event_type == BRCMF_E_AUTH_IND) -+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s\n", -+ event_name, eabuf, auth_str); -+ else if (status == BRCMF_E_STATUS_SUCCESS) -+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, SUCCESS\n", -+ event_name, eabuf, auth_str); -+ else if (status == BRCMF_E_STATUS_TIMEOUT) -+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, TIMEOUT\n", -+ event_name, eabuf, auth_str); -+ else if (status == BRCMF_E_STATUS_FAIL) { -+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, FAILURE, reason %d\n", -+ event_name, eabuf, auth_str, (int)reason); -+ } -+ -+ break; -+ -+ case BRCMF_E_JOIN: -+ case BRCMF_E_ROAM: -+ case BRCMF_E_SET_SSID: -+ if (status == BRCMF_E_STATUS_SUCCESS) -+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", -+ event_name, eabuf); -+ else if (status == BRCMF_E_STATUS_FAIL) -+ brcmf_dbg(EVENT, "MACEVENT: %s, failed\n", event_name); -+ else if (status == BRCMF_E_STATUS_NO_NETWORKS) -+ brcmf_dbg(EVENT, "MACEVENT: %s, no networks found\n", -+ event_name); -+ else -+ brcmf_dbg(EVENT, "MACEVENT: %s, unexpected status %d\n", -+ event_name, (int)status); -+ break; -+ -+ case BRCMF_E_BEACON_RX: -+ if (status == BRCMF_E_STATUS_SUCCESS) -+ brcmf_dbg(EVENT, "MACEVENT: %s, SUCCESS\n", event_name); -+ else if (status == BRCMF_E_STATUS_FAIL) -+ brcmf_dbg(EVENT, "MACEVENT: %s, FAIL\n", event_name); -+ else -+ brcmf_dbg(EVENT, "MACEVENT: %s, status %d\n", -+ event_name, status); -+ break; -+ -+ case BRCMF_E_LINK: -+ brcmf_dbg(EVENT, "MACEVENT: %s %s\n", -+ event_name, link ? "UP" : "DOWN"); -+ break; -+ -+ case BRCMF_E_MIC_ERROR: -+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, Group %d, Flush %d\n", -+ event_name, eabuf, group, flush_txq); -+ break; -+ -+ case BRCMF_E_ICV_ERROR: -+ case BRCMF_E_UNICAST_DECODE_ERROR: -+ case BRCMF_E_MULTICAST_DECODE_ERROR: -+ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf); -+ break; -+ -+ case BRCMF_E_TXFAIL: -+ brcmf_dbg(EVENT, "MACEVENT: %s, RA %s\n", event_name, eabuf); -+ break; -+ -+ case BRCMF_E_SCAN_COMPLETE: -+ case BRCMF_E_PMKID_CACHE: -+ brcmf_dbg(EVENT, "MACEVENT: %s\n", event_name); -+ break; -+ -+ case BRCMF_E_PFN_NET_FOUND: -+ case BRCMF_E_PFN_NET_LOST: -+ case BRCMF_E_PFN_SCAN_COMPLETE: -+ brcmf_dbg(EVENT, "PNOEVENT: %s\n", event_name); -+ break; -+ -+ case BRCMF_E_PSK_SUP: -+ case BRCMF_E_PRUNE: -+ brcmf_dbg(EVENT, "MACEVENT: %s, status %d, reason %d\n", -+ event_name, (int)status, (int)reason); -+ break; -+ -+ case BRCMF_E_TRACE: -+ buf = (unsigned char *) event_data; -+ memcpy(&hdr, buf, sizeof(struct msgtrace_hdr)); -+ -+ if (hdr.version != MSGTRACE_VERSION) { -+ brcmf_dbg(ERROR, -+ "MACEVENT: %s [unsupported version --> brcmf" -+ " version:%d dongle version:%d]\n", -+ event_name, MSGTRACE_VERSION, hdr.version); -+ /* Reset datalen to avoid display below */ -+ datalen = 0; -+ break; -+ } -+ -+ /* There are 2 bytes available at the end of data */ -+ *(buf + sizeof(struct msgtrace_hdr) -+ + be16_to_cpu(hdr.len)) = '\0'; -+ -+ if (be32_to_cpu(hdr.discarded_bytes) -+ || be32_to_cpu(hdr.discarded_printf)) -+ brcmf_dbg(ERROR, -+ "WLC_E_TRACE: [Discarded traces in dongle -->" -+ " discarded_bytes %d discarded_printf %d]\n", -+ be32_to_cpu(hdr.discarded_bytes), -+ be32_to_cpu(hdr.discarded_printf)); -+ -+ nblost = be32_to_cpu(hdr.seqnum) - seqnum_prev - 1; -+ if (nblost > 0) -+ brcmf_dbg(ERROR, "WLC_E_TRACE: [Event lost --> seqnum " -+ " %d nblost %d\n", be32_to_cpu(hdr.seqnum), -+ nblost); -+ seqnum_prev = be32_to_cpu(hdr.seqnum); -+ -+ /* Display the trace buffer. Advance from \n to \n to -+ * avoid display big -+ * printf (issue with Linux printk ) -+ */ -+ p = (char *)&buf[sizeof(struct msgtrace_hdr)]; -+ while ((s = strstr(p, "\n")) != NULL) { -+ *s = '\0'; -+ printk(KERN_DEBUG"%s\n", p); -+ p = s + 1; -+ } -+ printk(KERN_DEBUG "%s\n", p); -+ -+ /* Reset datalen to avoid display below */ -+ datalen = 0; -+ break; -+ -+ case BRCMF_E_RSSI: -+ brcmf_dbg(EVENT, "MACEVENT: %s %d\n", -+ event_name, be32_to_cpu(*((__be32 *)event_data))); -+ break; -+ -+ default: -+ brcmf_dbg(EVENT, -+ "MACEVENT: %s %d, MAC %s, status %d, reason %d, " -+ "auth %d\n", event_name, event_type, eabuf, -+ (int)status, (int)reason, (int)auth_type); -+ break; -+ } -+ -+ /* show any appended data */ -+ if (datalen) { -+ buf = (unsigned char *) event_data; -+ brcmf_dbg(EVENT, " data (%d) : ", datalen); -+ for (i = 0; i < datalen; i++) -+ brcmf_dbg(EVENT, " 0x%02x ", *buf++); -+ brcmf_dbg(EVENT, "\n"); -+ } -+} -+#endif /* BCMDBG */ -+ -+int -+brcmf_c_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata, -+ struct brcmf_event_msg *event, void **data_ptr) -+{ -+ /* check whether packet is a BRCM event pkt */ -+ struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata; -+ struct brcmf_if_event *ifevent; -+ char *event_data; -+ u32 type, status; -+ u16 flags; -+ int evlen; -+ -+ if (memcmp(BRCM_OUI, &pvt_data->hdr.oui[0], DOT11_OUI_LEN)) { -+ brcmf_dbg(ERROR, "mismatched OUI, bailing\n"); -+ return -EBADE; -+ } -+ -+ /* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */ -+ if (get_unaligned_be16(&pvt_data->hdr.usr_subtype) != -+ BCMILCP_BCM_SUBTYPE_EVENT) { -+ brcmf_dbg(ERROR, "mismatched subtype, bailing\n"); -+ return -EBADE; -+ } -+ -+ *data_ptr = &pvt_data[1]; -+ event_data = *data_ptr; -+ -+ /* memcpy since BRCM event pkt may be unaligned. */ -+ memcpy(event, &pvt_data->msg, sizeof(struct brcmf_event_msg)); -+ -+ type = get_unaligned_be32(&event->event_type); -+ flags = get_unaligned_be16(&event->flags); -+ status = get_unaligned_be32(&event->status); -+ evlen = get_unaligned_be32(&event->datalen) + -+ sizeof(struct brcmf_event); -+ -+ switch (type) { -+ case BRCMF_E_IF: -+ ifevent = (struct brcmf_if_event *) event_data; -+ brcmf_dbg(TRACE, "if event\n"); -+ -+ if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) { -+ if (ifevent->action == BRCMF_E_IF_ADD) -+ brcmf_add_if(drvr_priv, ifevent->ifidx, NULL, -+ event->ifname, -+ pvt_data->eth.h_dest, -+ ifevent->flags, ifevent->bssidx); -+ else -+ brcmf_del_if(drvr_priv, ifevent->ifidx); -+ } else { -+ brcmf_dbg(ERROR, "Invalid ifidx %d for %s\n", -+ ifevent->ifidx, event->ifname); -+ } -+ -+ /* send up the if event: btamp user needs it */ -+ *ifidx = brcmf_ifname2idx(drvr_priv, event->ifname); -+ break; -+ -+ /* These are what external supplicant/authenticator wants */ -+ case BRCMF_E_LINK: -+ case BRCMF_E_ASSOC_IND: -+ case BRCMF_E_REASSOC_IND: -+ case BRCMF_E_DISASSOC_IND: -+ case BRCMF_E_MIC_ERROR: -+ default: -+ /* Fall through: this should get _everything_ */ -+ -+ *ifidx = brcmf_ifname2idx(drvr_priv, event->ifname); -+ brcmf_dbg(TRACE, "MAC event %d, flags %x, status %x\n", -+ type, flags, status); -+ -+ /* put it back to BRCMF_E_NDIS_LINK */ -+ if (type == BRCMF_E_NDIS_LINK) { -+ u32 temp1; -+ __be32 temp2; -+ -+ temp1 = get_unaligned_be32(&event->event_type); -+ brcmf_dbg(TRACE, "Converted to WLC_E_LINK type %d\n", -+ temp1); -+ -+ temp2 = cpu_to_be32(BRCMF_E_NDIS_LINK); -+ memcpy((void *)(&pvt_data->msg.event_type), &temp2, -+ sizeof(pvt_data->msg.event_type)); -+ } -+ break; -+ } -+ -+#ifdef BCMDBG -+ brcmf_c_show_host_event(event, event_data); -+#endif /* BCMDBG */ -+ -+ return 0; -+} -+ -+/* Convert user's input in hex pattern to byte-size mask */ -+static int brcmf_c_pattern_atoh(char *src, char *dst) -+{ -+ int i; -+ if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) { -+ brcmf_dbg(ERROR, "Mask invalid format. Needs to start with 0x\n"); -+ return -EINVAL; -+ } -+ src = src + 2; /* Skip past 0x */ -+ if (strlen(src) % 2 != 0) { -+ brcmf_dbg(ERROR, "Mask invalid format. Length must be even.\n"); -+ return -EINVAL; -+ } -+ for (i = 0; *src != '\0'; i++) { -+ unsigned long res; -+ char num[3]; -+ strncpy(num, src, 2); -+ num[2] = '\0'; -+ if (kstrtoul(num, 16, &res)) -+ return -EINVAL; -+ dst[i] = (u8)res; -+ src += 2; -+ } -+ return i; -+} -+ -+void -+brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable, -+ int master_mode) -+{ -+ unsigned long res; -+ char *argv[8]; -+ int i = 0; -+ const char *str; -+ int buf_len; -+ int str_len; -+ char *arg_save = NULL, *arg_org = NULL; -+ int rc; -+ char buf[128]; -+ struct brcmf_pkt_filter_enable_le enable_parm; -+ struct brcmf_pkt_filter_enable_le *pkt_filterp; -+ __le32 mmode_le; -+ -+ arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC); -+ if (!arg_save) -+ goto fail; -+ -+ arg_org = arg_save; -+ memcpy(arg_save, arg, strlen(arg) + 1); -+ -+ argv[i] = strsep(&arg_save, " "); -+ -+ i = 0; -+ if (NULL == argv[i]) { -+ brcmf_dbg(ERROR, "No args provided\n"); -+ goto fail; -+ } -+ -+ str = "pkt_filter_enable"; -+ str_len = strlen(str); -+ strncpy(buf, str, str_len); -+ buf[str_len] = '\0'; -+ buf_len = str_len + 1; -+ -+ pkt_filterp = (struct brcmf_pkt_filter_enable_le *) (buf + str_len + 1); -+ -+ /* Parse packet filter id. */ -+ enable_parm.id = 0; -+ if (!kstrtoul(argv[i], 0, &res)) -+ enable_parm.id = cpu_to_le32((u32)res); -+ -+ /* Parse enable/disable value. */ -+ enable_parm.enable = cpu_to_le32(enable); -+ -+ buf_len += sizeof(enable_parm); -+ memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm)); -+ -+ /* Enable/disable the specified filter. */ -+ rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len); -+ rc = rc >= 0 ? 0 : rc; -+ if (rc) -+ brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n", -+ arg, rc); -+ else -+ brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg); -+ -+ /* Contorl the master mode */ -+ mmode_le = cpu_to_le32(master_mode); -+ brcmf_c_mkiovar("pkt_filter_mode", (char *)&mmode_le, 4, buf, -+ sizeof(buf)); -+ rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, -+ sizeof(buf)); -+ rc = rc >= 0 ? 0 : rc; -+ if (rc) -+ brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n", -+ arg, rc); -+ -+fail: -+ kfree(arg_org); -+} -+ -+void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg) -+{ -+ const char *str; -+ struct brcmf_pkt_filter_le pkt_filter; -+ struct brcmf_pkt_filter_le *pkt_filterp; -+ unsigned long res; -+ int buf_len; -+ int str_len; -+ int rc; -+ u32 mask_size; -+ u32 pattern_size; -+ char *argv[8], *buf = NULL; -+ int i = 0; -+ char *arg_save = NULL, *arg_org = NULL; -+ -+ arg_save = kstrdup(arg, GFP_ATOMIC); -+ if (!arg_save) -+ goto fail; -+ -+ arg_org = arg_save; -+ -+ buf = kmalloc(PKTFILTER_BUF_SIZE, GFP_ATOMIC); -+ if (!buf) -+ goto fail; -+ -+ argv[i] = strsep(&arg_save, " "); -+ while (argv[i++]) -+ argv[i] = strsep(&arg_save, " "); -+ -+ i = 0; -+ if (NULL == argv[i]) { -+ brcmf_dbg(ERROR, "No args provided\n"); -+ goto fail; -+ } -+ -+ str = "pkt_filter_add"; -+ strcpy(buf, str); -+ str_len = strlen(str); -+ buf_len = str_len + 1; -+ -+ pkt_filterp = (struct brcmf_pkt_filter_le *) (buf + str_len + 1); -+ -+ /* Parse packet filter id. */ -+ pkt_filter.id = 0; -+ if (!kstrtoul(argv[i], 0, &res)) -+ pkt_filter.id = cpu_to_le32((u32)res); -+ -+ if (NULL == argv[++i]) { -+ brcmf_dbg(ERROR, "Polarity not provided\n"); -+ goto fail; -+ } -+ -+ /* Parse filter polarity. */ -+ pkt_filter.negate_match = 0; -+ if (!kstrtoul(argv[i], 0, &res)) -+ pkt_filter.negate_match = cpu_to_le32((u32)res); -+ -+ if (NULL == argv[++i]) { -+ brcmf_dbg(ERROR, "Filter type not provided\n"); -+ goto fail; -+ } -+ -+ /* Parse filter type. */ -+ pkt_filter.type = 0; -+ if (!kstrtoul(argv[i], 0, &res)) -+ pkt_filter.type = cpu_to_le32((u32)res); -+ -+ if (NULL == argv[++i]) { -+ brcmf_dbg(ERROR, "Offset not provided\n"); -+ goto fail; -+ } -+ -+ /* Parse pattern filter offset. */ -+ pkt_filter.u.pattern.offset = 0; -+ if (!kstrtoul(argv[i], 0, &res)) -+ pkt_filter.u.pattern.offset = cpu_to_le32((u32)res); -+ -+ if (NULL == argv[++i]) { -+ brcmf_dbg(ERROR, "Bitmask not provided\n"); -+ goto fail; -+ } -+ -+ /* Parse pattern filter mask. */ -+ mask_size = -+ brcmf_c_pattern_atoh -+ (argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern); -+ -+ if (NULL == argv[++i]) { -+ brcmf_dbg(ERROR, "Pattern not provided\n"); -+ goto fail; -+ } -+ -+ /* Parse pattern filter pattern. */ -+ pattern_size = -+ brcmf_c_pattern_atoh(argv[i], -+ (char *)&pkt_filterp->u.pattern. -+ mask_and_pattern[mask_size]); -+ -+ if (mask_size != pattern_size) { -+ brcmf_dbg(ERROR, "Mask and pattern not the same size\n"); -+ goto fail; -+ } -+ -+ pkt_filter.u.pattern.size_bytes = cpu_to_le32(mask_size); -+ buf_len += BRCMF_PKT_FILTER_FIXED_LEN; -+ buf_len += (BRCMF_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size); -+ -+ /* Keep-alive attributes are set in local -+ * variable (keep_alive_pkt), and -+ ** then memcpy'ed into buffer (keep_alive_pktp) since there is no -+ ** guarantee that the buffer is properly aligned. -+ */ -+ memcpy((char *)pkt_filterp, -+ &pkt_filter, -+ BRCMF_PKT_FILTER_FIXED_LEN + BRCMF_PKT_FILTER_PATTERN_FIXED_LEN); -+ -+ rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len); -+ rc = rc >= 0 ? 0 : rc; -+ -+ if (rc) -+ brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n", -+ arg, rc); -+ else -+ brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg); -+ -+fail: -+ kfree(arg_org); -+ -+ kfree(buf); -+} -+ -+static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode) -+{ -+ char iovbuf[32]; -+ int retcode; -+ -+ brcmf_c_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf)); -+ retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, -+ iovbuf, sizeof(iovbuf)); -+ retcode = retcode >= 0 ? 0 : retcode; -+ if (retcode) -+ brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, retcode = %d\n", -+ arp_mode, retcode); -+ else -+ brcmf_dbg(TRACE, "successfully set ARP offload mode to 0x%x\n", -+ arp_mode); -+} -+ -+static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable) -+{ -+ char iovbuf[32]; -+ int retcode; -+ -+ brcmf_c_mkiovar("arpoe", (char *)&arp_enable, 4, -+ iovbuf, sizeof(iovbuf)); -+ retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, -+ iovbuf, sizeof(iovbuf)); -+ retcode = retcode >= 0 ? 0 : retcode; -+ if (retcode) -+ brcmf_dbg(TRACE, "failed to enable ARP offload to %d, retcode = %d\n", -+ arp_enable, retcode); -+ else -+ brcmf_dbg(TRACE, "successfully enabled ARP offload to %d\n", -+ arp_enable); -+} -+ -+int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) -+{ -+ char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for -+ "event_msgs" + '\0' + bitvec */ -+ uint up = 0; -+ char buf[128], *ptr; -+ u32 dongle_align = BRCMF_SDALIGN; -+ u32 glom = 0; -+ u32 roaming = 1; -+ uint bcn_timeout = 3; -+ int scan_assoc_time = 40; -+ int scan_unassoc_time = 40; -+ int i; -+ -+ brcmf_os_proto_block(drvr); -+ -+ /* Set Country code */ -+ if (drvr->country_code[0] != 0) { -+ if (brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_COUNTRY, -+ drvr->country_code, -+ sizeof(drvr->country_code)) < 0) -+ brcmf_dbg(ERROR, "country code setting failed\n"); -+ } -+ -+ /* query for 'ver' to get version info from firmware */ -+ memset(buf, 0, sizeof(buf)); -+ ptr = buf; -+ brcmf_c_mkiovar("ver", NULL, 0, buf, sizeof(buf)); -+ brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, buf, sizeof(buf)); -+ strsep(&ptr, "\n"); -+ /* Print fw version info */ -+ brcmf_dbg(ERROR, "Firmware version = %s\n", buf); -+ -+ /* Match Host and Dongle rx alignment */ -+ brcmf_c_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, -+ sizeof(iovbuf)); -+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, -+ sizeof(iovbuf)); -+ -+ /* disable glom option per default */ -+ brcmf_c_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); -+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, -+ sizeof(iovbuf)); -+ -+ /* Setup timeout if Beacons are lost and roam is off to report -+ link down */ -+ brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, -+ sizeof(iovbuf)); -+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, -+ sizeof(iovbuf)); -+ -+ /* Enable/Disable build-in roaming to allowed ext supplicant to take -+ of romaing */ -+ brcmf_c_mkiovar("roam_off", (char *)&roaming, 4, -+ iovbuf, sizeof(iovbuf)); -+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, -+ sizeof(iovbuf)); -+ -+ /* Force STA UP */ -+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_UP, (char *)&up, sizeof(up)); -+ -+ /* Setup event_msgs */ -+ brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN, -+ iovbuf, sizeof(iovbuf)); -+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, -+ sizeof(iovbuf)); -+ -+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME, -+ (char *)&scan_assoc_time, sizeof(scan_assoc_time)); -+ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME, -+ (char *)&scan_unassoc_time, sizeof(scan_unassoc_time)); -+ -+ /* Set and enable ARP offload feature */ -+ brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE); -+ brcmf_c_arp_offload_enable(drvr, true); -+ -+ /* Set up pkt filter */ -+ for (i = 0; i < drvr->pktfilter_count; i++) { -+ brcmf_c_pktfilter_offload_set(drvr, drvr->pktfilter[i]); -+ brcmf_c_pktfilter_offload_enable(drvr, drvr->pktfilter[i], -+ 0, true); -+ } -+ -+ brcmf_os_proto_unblock(drvr); -+ -+ return 0; -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h.orig 2011-11-09 13:46:58.231800808 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h 2011-11-09 13:47:16.981566403 -0500 -@@ -0,0 +1,58 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCMF_DBG_H_ -+#define _BRCMF_DBG_H_ -+ -+#if defined(BCMDBG) -+ -+#define brcmf_dbg(level, fmt, ...) \ -+do { \ -+ if (BRCMF_ERROR_VAL == BRCMF_##level##_VAL) { \ -+ if (brcmf_msg_level & BRCMF_##level##_VAL) { \ -+ if (net_ratelimit()) \ -+ printk(KERN_DEBUG "%s: " fmt, \ -+ __func__, ##__VA_ARGS__); \ -+ } \ -+ } else { \ -+ if (brcmf_msg_level & BRCMF_##level##_VAL) { \ -+ printk(KERN_DEBUG "%s: " fmt, \ -+ __func__, ##__VA_ARGS__); \ -+ } \ -+ } \ -+} while (0) -+ -+#define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL) -+#define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL) -+#define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL) -+#define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL) -+#define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL) -+ -+#else /* (defined BCMDBG) || (defined BCMDBG) */ -+ -+#define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__) -+ -+#define BRCMF_DATA_ON() 0 -+#define BRCMF_CTL_ON() 0 -+#define BRCMF_HDRS_ON() 0 -+#define BRCMF_BYTES_ON() 0 -+#define BRCMF_GLOM_ON() 0 -+ -+#endif /* defined(BCMDBG) */ -+ -+extern int brcmf_msg_level; -+ -+#endif /* _BRCMF_DBG_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd.h.orig 2011-11-09 13:46:58.231800808 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd.h 2011-11-09 13:47:16.982566390 -0500 -@@ -0,0 +1,776 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/**************** -+ * Common types * -+ */ -+ -+#ifndef _BRCMF_H_ -+#define _BRCMF_H_ -+ -+#define BRCMF_VERSION_STR "4.218.248.5" -+ -+/******************************************************************************* -+ * IO codes that are interpreted by dongle firmware -+ ******************************************************************************/ -+#define BRCMF_C_UP 2 -+#define BRCMF_C_SET_PROMISC 10 -+#define BRCMF_C_GET_RATE 12 -+#define BRCMF_C_GET_INFRA 19 -+#define BRCMF_C_SET_INFRA 20 -+#define BRCMF_C_GET_AUTH 21 -+#define BRCMF_C_SET_AUTH 22 -+#define BRCMF_C_GET_BSSID 23 -+#define BRCMF_C_GET_SSID 25 -+#define BRCMF_C_SET_SSID 26 -+#define BRCMF_C_GET_CHANNEL 29 -+#define BRCMF_C_GET_SRL 31 -+#define BRCMF_C_GET_LRL 33 -+#define BRCMF_C_GET_RADIO 37 -+#define BRCMF_C_SET_RADIO 38 -+#define BRCMF_C_GET_PHYTYPE 39 -+#define BRCMF_C_SET_KEY 45 -+#define BRCMF_C_SET_PASSIVE_SCAN 49 -+#define BRCMF_C_SCAN 50 -+#define BRCMF_C_SCAN_RESULTS 51 -+#define BRCMF_C_DISASSOC 52 -+#define BRCMF_C_REASSOC 53 -+#define BRCMF_C_SET_ROAM_TRIGGER 55 -+#define BRCMF_C_SET_ROAM_DELTA 57 -+#define BRCMF_C_GET_DTIMPRD 77 -+#define BRCMF_C_SET_COUNTRY 84 -+#define BRCMF_C_GET_PM 85 -+#define BRCMF_C_SET_PM 86 -+#define BRCMF_C_GET_AP 117 -+#define BRCMF_C_SET_AP 118 -+#define BRCMF_C_GET_RSSI 127 -+#define BRCMF_C_GET_WSEC 133 -+#define BRCMF_C_SET_WSEC 134 -+#define BRCMF_C_GET_PHY_NOISE 135 -+#define BRCMF_C_GET_BSS_INFO 136 -+#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 -+#define BRCMF_C_SET_SCAN_UNASSOC_TIME 187 -+#define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201 -+#define BRCMF_C_GET_VALID_CHANNELS 217 -+#define BRCMF_C_GET_KEY_PRIMARY 235 -+#define BRCMF_C_SET_KEY_PRIMARY 236 -+#define BRCMF_C_SET_SCAN_PASSIVE_TIME 258 -+#define BRCMF_C_GET_VAR 262 -+#define BRCMF_C_SET_VAR 263 -+ -+/* phy types (returned by WLC_GET_PHYTPE) */ -+#define WLC_PHY_TYPE_A 0 -+#define WLC_PHY_TYPE_B 1 -+#define WLC_PHY_TYPE_G 2 -+#define WLC_PHY_TYPE_N 4 -+#define WLC_PHY_TYPE_LP 5 -+#define WLC_PHY_TYPE_SSN 6 -+#define WLC_PHY_TYPE_HT 7 -+#define WLC_PHY_TYPE_LCN 8 -+#define WLC_PHY_TYPE_NULL 0xf -+ -+#define BRCMF_EVENTING_MASK_LEN 16 -+ -+#define TOE_TX_CSUM_OL 0x00000001 -+#define TOE_RX_CSUM_OL 0x00000002 -+ -+#define BRCMF_BSS_INFO_VERSION 108 /* current ver of brcmf_bss_info struct */ -+ -+/* size of brcmf_scan_params not including variable length array */ -+#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64 -+ -+/* masks for channel and ssid count */ -+#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff -+#define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16 -+ -+#define BRCMF_SCAN_ACTION_START 1 -+#define BRCMF_SCAN_ACTION_CONTINUE 2 -+#define WL_SCAN_ACTION_ABORT 3 -+ -+#define BRCMF_ISCAN_REQ_VERSION 1 -+ -+/* brcmf_iscan_results status values */ -+#define BRCMF_SCAN_RESULTS_SUCCESS 0 -+#define BRCMF_SCAN_RESULTS_PARTIAL 1 -+#define BRCMF_SCAN_RESULTS_PENDING 2 -+#define BRCMF_SCAN_RESULTS_ABORTED 3 -+#define BRCMF_SCAN_RESULTS_NO_MEM 4 -+ -+/* Indicates this key is using soft encrypt */ -+#define WL_SOFT_KEY (1 << 0) -+/* primary (ie tx) key */ -+#define BRCMF_PRIMARY_KEY (1 << 1) -+/* Reserved for backward compat */ -+#define WL_KF_RES_4 (1 << 4) -+/* Reserved for backward compat */ -+#define WL_KF_RES_5 (1 << 5) -+/* Indicates a group key for a IBSS PEER */ -+#define WL_IBSS_PEER_GROUP_KEY (1 << 6) -+ -+/* For supporting multiple interfaces */ -+#define BRCMF_MAX_IFS 16 -+#define BRCMF_DEL_IF -0xe -+#define BRCMF_BAD_IF -0xf -+ -+#define DOT11_BSSTYPE_ANY 2 -+#define DOT11_MAX_DEFAULT_KEYS 4 -+ -+#define BRCMF_EVENT_MSG_LINK 0x01 -+#define BRCMF_EVENT_MSG_FLUSHTXQ 0x02 -+#define BRCMF_EVENT_MSG_GROUP 0x04 -+ -+struct brcmf_event_msg { -+ __be16 version; -+ __be16 flags; -+ __be32 event_type; -+ __be32 status; -+ __be32 reason; -+ __be32 auth_type; -+ __be32 datalen; -+ u8 addr[ETH_ALEN]; -+ char ifname[IFNAMSIZ]; -+} __packed; -+ -+struct brcm_ethhdr { -+ u16 subtype; -+ u16 length; -+ u8 version; -+ u8 oui[3]; -+ u16 usr_subtype; -+} __packed; -+ -+struct brcmf_event { -+ struct ethhdr eth; -+ struct brcm_ethhdr hdr; -+ struct brcmf_event_msg msg; -+} __packed; -+ -+struct dngl_stats { -+ unsigned long rx_packets; /* total packets received */ -+ unsigned long tx_packets; /* total packets transmitted */ -+ unsigned long rx_bytes; /* total bytes received */ -+ unsigned long tx_bytes; /* total bytes transmitted */ -+ unsigned long rx_errors; /* bad packets received */ -+ unsigned long tx_errors; /* packet transmit problems */ -+ unsigned long rx_dropped; /* packets dropped by dongle */ -+ unsigned long tx_dropped; /* packets dropped by dongle */ -+ unsigned long multicast; /* multicast packets received */ -+}; -+ -+/* event codes sent by the dongle to this driver */ -+#define BRCMF_E_SET_SSID 0 -+#define BRCMF_E_JOIN 1 -+#define BRCMF_E_START 2 -+#define BRCMF_E_AUTH 3 -+#define BRCMF_E_AUTH_IND 4 -+#define BRCMF_E_DEAUTH 5 -+#define BRCMF_E_DEAUTH_IND 6 -+#define BRCMF_E_ASSOC 7 -+#define BRCMF_E_ASSOC_IND 8 -+#define BRCMF_E_REASSOC 9 -+#define BRCMF_E_REASSOC_IND 10 -+#define BRCMF_E_DISASSOC 11 -+#define BRCMF_E_DISASSOC_IND 12 -+#define BRCMF_E_QUIET_START 13 -+#define BRCMF_E_QUIET_END 14 -+#define BRCMF_E_BEACON_RX 15 -+#define BRCMF_E_LINK 16 -+#define BRCMF_E_MIC_ERROR 17 -+#define BRCMF_E_NDIS_LINK 18 -+#define BRCMF_E_ROAM 19 -+#define BRCMF_E_TXFAIL 20 -+#define BRCMF_E_PMKID_CACHE 21 -+#define BRCMF_E_RETROGRADE_TSF 22 -+#define BRCMF_E_PRUNE 23 -+#define BRCMF_E_AUTOAUTH 24 -+#define BRCMF_E_EAPOL_MSG 25 -+#define BRCMF_E_SCAN_COMPLETE 26 -+#define BRCMF_E_ADDTS_IND 27 -+#define BRCMF_E_DELTS_IND 28 -+#define BRCMF_E_BCNSENT_IND 29 -+#define BRCMF_E_BCNRX_MSG 30 -+#define BRCMF_E_BCNLOST_MSG 31 -+#define BRCMF_E_ROAM_PREP 32 -+#define BRCMF_E_PFN_NET_FOUND 33 -+#define BRCMF_E_PFN_NET_LOST 34 -+#define BRCMF_E_RESET_COMPLETE 35 -+#define BRCMF_E_JOIN_START 36 -+#define BRCMF_E_ROAM_START 37 -+#define BRCMF_E_ASSOC_START 38 -+#define BRCMF_E_IBSS_ASSOC 39 -+#define BRCMF_E_RADIO 40 -+#define BRCMF_E_PSM_WATCHDOG 41 -+#define BRCMF_E_PROBREQ_MSG 44 -+#define BRCMF_E_SCAN_CONFIRM_IND 45 -+#define BRCMF_E_PSK_SUP 46 -+#define BRCMF_E_COUNTRY_CODE_CHANGED 47 -+#define BRCMF_E_EXCEEDED_MEDIUM_TIME 48 -+#define BRCMF_E_ICV_ERROR 49 -+#define BRCMF_E_UNICAST_DECODE_ERROR 50 -+#define BRCMF_E_MULTICAST_DECODE_ERROR 51 -+#define BRCMF_E_TRACE 52 -+#define BRCMF_E_IF 54 -+#define BRCMF_E_RSSI 56 -+#define BRCMF_E_PFN_SCAN_COMPLETE 57 -+#define BRCMF_E_EXTLOG_MSG 58 -+#define BRCMF_E_ACTION_FRAME 59 -+#define BRCMF_E_ACTION_FRAME_COMPLETE 60 -+#define BRCMF_E_PRE_ASSOC_IND 61 -+#define BRCMF_E_PRE_REASSOC_IND 62 -+#define BRCMF_E_CHANNEL_ADOPTED 63 -+#define BRCMF_E_AP_STARTED 64 -+#define BRCMF_E_DFS_AP_STOP 65 -+#define BRCMF_E_DFS_AP_RESUME 66 -+#define BRCMF_E_RESERVED1 67 -+#define BRCMF_E_RESERVED2 68 -+#define BRCMF_E_ESCAN_RESULT 69 -+#define BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70 -+#define BRCMF_E_DCS_REQUEST 73 -+ -+#define BRCMF_E_FIFO_CREDIT_MAP 74 -+ -+#define BRCMF_E_LAST 75 -+ -+#define BRCMF_E_STATUS_SUCCESS 0 -+#define BRCMF_E_STATUS_FAIL 1 -+#define BRCMF_E_STATUS_TIMEOUT 2 -+#define BRCMF_E_STATUS_NO_NETWORKS 3 -+#define BRCMF_E_STATUS_ABORT 4 -+#define BRCMF_E_STATUS_NO_ACK 5 -+#define BRCMF_E_STATUS_UNSOLICITED 6 -+#define BRCMF_E_STATUS_ATTEMPT 7 -+#define BRCMF_E_STATUS_PARTIAL 8 -+#define BRCMF_E_STATUS_NEWSCAN 9 -+#define BRCMF_E_STATUS_NEWASSOC 10 -+#define BRCMF_E_STATUS_11HQUIET 11 -+#define BRCMF_E_STATUS_SUPPRESS 12 -+#define BRCMF_E_STATUS_NOCHANS 13 -+#define BRCMF_E_STATUS_CS_ABORT 15 -+#define BRCMF_E_STATUS_ERROR 16 -+ -+#define BRCMF_E_REASON_INITIAL_ASSOC 0 -+#define BRCMF_E_REASON_LOW_RSSI 1 -+#define BRCMF_E_REASON_DEAUTH 2 -+#define BRCMF_E_REASON_DISASSOC 3 -+#define BRCMF_E_REASON_BCNS_LOST 4 -+#define BRCMF_E_REASON_MINTXRATE 9 -+#define BRCMF_E_REASON_TXFAIL 10 -+ -+#define BRCMF_E_REASON_FAST_ROAM_FAILED 5 -+#define BRCMF_E_REASON_DIRECTED_ROAM 6 -+#define BRCMF_E_REASON_TSPEC_REJECTED 7 -+#define BRCMF_E_REASON_BETTER_AP 8 -+ -+#define BRCMF_E_PRUNE_ENCR_MISMATCH 1 -+#define BRCMF_E_PRUNE_BCAST_BSSID 2 -+#define BRCMF_E_PRUNE_MAC_DENY 3 -+#define BRCMF_E_PRUNE_MAC_NA 4 -+#define BRCMF_E_PRUNE_REG_PASSV 5 -+#define BRCMF_E_PRUNE_SPCT_MGMT 6 -+#define BRCMF_E_PRUNE_RADAR 7 -+#define BRCMF_E_RSN_MISMATCH 8 -+#define BRCMF_E_PRUNE_NO_COMMON_RATES 9 -+#define BRCMF_E_PRUNE_BASIC_RATES 10 -+#define BRCMF_E_PRUNE_CIPHER_NA 12 -+#define BRCMF_E_PRUNE_KNOWN_STA 13 -+#define BRCMF_E_PRUNE_WDS_PEER 15 -+#define BRCMF_E_PRUNE_QBSS_LOAD 16 -+#define BRCMF_E_PRUNE_HOME_AP 17 -+ -+#define BRCMF_E_SUP_OTHER 0 -+#define BRCMF_E_SUP_DECRYPT_KEY_DATA 1 -+#define BRCMF_E_SUP_BAD_UCAST_WEP128 2 -+#define BRCMF_E_SUP_BAD_UCAST_WEP40 3 -+#define BRCMF_E_SUP_UNSUP_KEY_LEN 4 -+#define BRCMF_E_SUP_PW_KEY_CIPHER 5 -+#define BRCMF_E_SUP_MSG3_TOO_MANY_IE 6 -+#define BRCMF_E_SUP_MSG3_IE_MISMATCH 7 -+#define BRCMF_E_SUP_NO_INSTALL_FLAG 8 -+#define BRCMF_E_SUP_MSG3_NO_GTK 9 -+#define BRCMF_E_SUP_GRP_KEY_CIPHER 10 -+#define BRCMF_E_SUP_GRP_MSG1_NO_GTK 11 -+#define BRCMF_E_SUP_GTK_DECRYPT_FAIL 12 -+#define BRCMF_E_SUP_SEND_FAIL 13 -+#define BRCMF_E_SUP_DEAUTH 14 -+ -+#define BRCMF_E_IF_ADD 1 -+#define BRCMF_E_IF_DEL 2 -+#define BRCMF_E_IF_CHANGE 3 -+ -+#define BRCMF_E_IF_ROLE_STA 0 -+#define BRCMF_E_IF_ROLE_AP 1 -+#define BRCMF_E_IF_ROLE_WDS 2 -+ -+#define BRCMF_E_LINK_BCN_LOSS 1 -+#define BRCMF_E_LINK_DISASSOC 2 -+#define BRCMF_E_LINK_ASSOC_REC 3 -+#define BRCMF_E_LINK_BSSCFG_DIS 4 -+ -+/* The level of bus communication with the dongle */ -+enum brcmf_bus_state { -+ BRCMF_BUS_DOWN, /* Not ready for frame transfers */ -+ BRCMF_BUS_LOAD, /* Download access only (CPU reset) */ -+ BRCMF_BUS_DATA /* Ready for frame transfers */ -+}; -+ -+/* Pattern matching filter. Specifies an offset within received packets to -+ * start matching, the pattern to match, the size of the pattern, and a bitmask -+ * that indicates which bits within the pattern should be matched. -+ */ -+struct brcmf_pkt_filter_pattern_le { -+ /* -+ * Offset within received packet to start pattern matching. -+ * Offset '0' is the first byte of the ethernet header. -+ */ -+ __le32 offset; -+ /* Size of the pattern. Bitmask must be the same size.*/ -+ __le32 size_bytes; -+ /* -+ * Variable length mask and pattern data. mask starts at offset 0. -+ * Pattern immediately follows mask. -+ */ -+ u8 mask_and_pattern[1]; -+}; -+ -+/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */ -+struct brcmf_pkt_filter_le { -+ __le32 id; /* Unique filter id, specified by app. */ -+ __le32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */ -+ __le32 negate_match; /* Negate the result of filter matches */ -+ union { /* Filter definitions */ -+ struct brcmf_pkt_filter_pattern_le pattern; /* Filter pattern */ -+ } u; -+}; -+ -+/* IOVAR "pkt_filter_enable" parameter. */ -+struct brcmf_pkt_filter_enable_le { -+ __le32 id; /* Unique filter id */ -+ __le32 enable; /* Enable/disable bool */ -+}; -+ -+/* BSS info structure -+ * Applications MUST CHECK ie_offset field and length field to access IEs and -+ * next bss_info structure in a vector (in struct brcmf_scan_results) -+ */ -+struct brcmf_bss_info { -+ __le32 version; /* version field */ -+ __le32 length; /* byte length of data in this record, -+ * starting at version and including IEs -+ */ -+ u8 BSSID[ETH_ALEN]; -+ __le16 beacon_period; /* units are Kusec */ -+ __le16 capability; /* Capability information */ -+ u8 SSID_len; -+ u8 SSID[32]; -+ struct { -+ __le32 count; /* # rates in this set */ -+ u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ -+ } rateset; /* supported rates */ -+ __le16 chanspec; /* chanspec for bss */ -+ __le16 atim_window; /* units are Kusec */ -+ u8 dtim_period; /* DTIM period */ -+ __le16 RSSI; /* receive signal strength (in dBm) */ -+ s8 phy_noise; /* noise (in dBm) */ -+ -+ u8 n_cap; /* BSS is 802.11N Capable */ -+ /* 802.11N BSS Capabilities (based on HT_CAP_*): */ -+ __le32 nbss_cap; -+ u8 ctl_ch; /* 802.11N BSS control channel number */ -+ __le32 reserved32[1]; /* Reserved for expansion of BSS properties */ -+ u8 flags; /* flags */ -+ u8 reserved[3]; /* Reserved for expansion of BSS properties */ -+ u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ -+ -+ __le16 ie_offset; /* offset at which IEs start, from beginning */ -+ __le32 ie_length; /* byte length of Information Elements */ -+ __le16 SNR; /* average SNR of during frame reception */ -+ /* Add new fields here */ -+ /* variable length Information Elements */ -+}; -+ -+struct brcm_rateset_le { -+ /* # rates in this set */ -+ __le32 count; -+ /* rates in 500kbps units w/hi bit set if basic */ -+ u8 rates[WL_NUMRATES]; -+}; -+ -+struct brcmf_ssid { -+ u32 SSID_len; -+ unsigned char SSID[32]; -+}; -+ -+struct brcmf_ssid_le { -+ __le32 SSID_len; -+ unsigned char SSID[32]; -+}; -+ -+struct brcmf_scan_params_le { -+ struct brcmf_ssid_le ssid_le; /* default: {0, ""} */ -+ u8 bssid[ETH_ALEN]; /* default: bcast */ -+ s8 bss_type; /* default: any, -+ * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT -+ */ -+ u8 scan_type; /* flags, 0 use default */ -+ __le32 nprobes; /* -1 use default, number of probes per channel */ -+ __le32 active_time; /* -1 use default, dwell time per channel for -+ * active scanning -+ */ -+ __le32 passive_time; /* -1 use default, dwell time per channel -+ * for passive scanning -+ */ -+ __le32 home_time; /* -1 use default, dwell time for the -+ * home channel between channel scans -+ */ -+ __le32 channel_num; /* count of channels and ssids that follow -+ * -+ * low half is count of channels in -+ * channel_list, 0 means default (use all -+ * available channels) -+ * -+ * high half is entries in struct brcmf_ssid -+ * array that follows channel_list, aligned for -+ * s32 (4 bytes) meaning an odd channel count -+ * implies a 2-byte pad between end of -+ * channel_list and first ssid -+ * -+ * if ssid count is zero, single ssid in the -+ * fixed parameter portion is assumed, otherwise -+ * ssid in the fixed portion is ignored -+ */ -+ __le16 channel_list[1]; /* list of chanspecs */ -+}; -+ -+/* incremental scan struct */ -+struct brcmf_iscan_params_le { -+ __le32 version; -+ __le16 action; -+ __le16 scan_duration; -+ struct brcmf_scan_params_le params_le; -+}; -+ -+struct brcmf_scan_results { -+ u32 buflen; -+ u32 version; -+ u32 count; -+ struct brcmf_bss_info bss_info[1]; -+}; -+ -+struct brcmf_scan_results_le { -+ __le32 buflen; -+ __le32 version; -+ __le32 count; -+ struct brcmf_bss_info bss_info[1]; -+}; -+ -+/* used for association with a specific BSSID and chanspec list */ -+struct brcmf_assoc_params_le { -+ /* 00:00:00:00:00:00: broadcast scan */ -+ u8 bssid[ETH_ALEN]; -+ /* 0: all available channels, otherwise count of chanspecs in -+ * chanspec_list */ -+ __le32 chanspec_num; -+ /* list of chanspecs */ -+ __le16 chanspec_list[1]; -+}; -+ -+/* used for join with or without a specific bssid and channel list */ -+struct brcmf_join_params { -+ struct brcmf_ssid_le ssid_le; -+ struct brcmf_assoc_params_le params_le; -+}; -+ -+/* size of brcmf_scan_results not including variable length array */ -+#define BRCMF_SCAN_RESULTS_FIXED_SIZE \ -+ (sizeof(struct brcmf_scan_results) - sizeof(struct brcmf_bss_info)) -+ -+/* incremental scan results struct */ -+struct brcmf_iscan_results { -+ union { -+ u32 status; -+ __le32 status_le; -+ }; -+ union { -+ struct brcmf_scan_results results; -+ struct brcmf_scan_results_le results_le; -+ }; -+}; -+ -+/* size of brcmf_iscan_results not including variable length array */ -+#define BRCMF_ISCAN_RESULTS_FIXED_SIZE \ -+ (BRCMF_SCAN_RESULTS_FIXED_SIZE + \ -+ offsetof(struct brcmf_iscan_results, results)) -+ -+struct brcmf_wsec_key { -+ u32 index; /* key index */ -+ u32 len; /* key length */ -+ u8 data[WLAN_MAX_KEY_LEN]; /* key data */ -+ u32 pad_1[18]; -+ u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ -+ u32 flags; /* misc flags */ -+ u32 pad_2[3]; -+ u32 iv_initialized; /* has IV been initialized already? */ -+ u32 pad_3; -+ /* Rx IV */ -+ struct { -+ u32 hi; /* upper 32 bits of IV */ -+ u16 lo; /* lower 16 bits of IV */ -+ } rxiv; -+ u32 pad_4[2]; -+ u8 ea[ETH_ALEN]; /* per station */ -+}; -+ -+/* -+ * dongle requires same struct as above but with fields in little endian order -+ */ -+struct brcmf_wsec_key_le { -+ __le32 index; /* key index */ -+ __le32 len; /* key length */ -+ u8 data[WLAN_MAX_KEY_LEN]; /* key data */ -+ __le32 pad_1[18]; -+ __le32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ -+ __le32 flags; /* misc flags */ -+ __le32 pad_2[3]; -+ __le32 iv_initialized; /* has IV been initialized already? */ -+ __le32 pad_3; -+ /* Rx IV */ -+ struct { -+ __le32 hi; /* upper 32 bits of IV */ -+ __le16 lo; /* lower 16 bits of IV */ -+ } rxiv; -+ __le32 pad_4[2]; -+ u8 ea[ETH_ALEN]; /* per station */ -+}; -+ -+/* Used to get specific STA parameters */ -+struct brcmf_scb_val_le { -+ __le32 val; -+ u8 ea[ETH_ALEN]; -+}; -+ -+/* channel encoding */ -+struct brcmf_channel_info_le { -+ __le32 hw_channel; -+ __le32 target_channel; -+ __le32 scan_channel; -+}; -+ -+/* Bus independent dongle command */ -+struct brcmf_dcmd { -+ uint cmd; /* common dongle cmd definition */ -+ void *buf; /* pointer to user buffer */ -+ uint len; /* length of user buffer */ -+ u8 set; /* get or set request (optional) */ -+ uint used; /* bytes read or written (optional) */ -+ uint needed; /* bytes needed (optional) */ -+}; -+ -+/* Forward decls for struct brcmf_pub (see below) */ -+struct brcmf_bus; /* device bus info */ -+struct brcmf_proto; /* device communication protocol info */ -+struct brcmf_info; /* device driver info */ -+struct brcmf_cfg80211_dev; /* cfg80211 device info */ -+ -+/* Common structure for module and instance linkage */ -+struct brcmf_pub { -+ /* Linkage ponters */ -+ struct brcmf_bus *bus; -+ struct brcmf_proto *prot; -+ struct brcmf_info *info; -+ struct brcmf_cfg80211_dev *config; -+ -+ /* Internal brcmf items */ -+ bool up; /* Driver up/down (to OS) */ -+ bool txoff; /* Transmit flow-controlled */ -+ enum brcmf_bus_state busstate; -+ uint hdrlen; /* Total BRCMF header length (proto + bus) */ -+ uint maxctl; /* Max size rxctl request from proto to bus */ -+ uint rxsz; /* Rx buffer size bus module should use */ -+ u8 wme_dp; /* wme discard priority */ -+ -+ /* Dongle media info */ -+ bool iswl; /* Dongle-resident driver is wl */ -+ unsigned long drv_version; /* Version of dongle-resident driver */ -+ u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */ -+ struct dngl_stats dstats; /* Stats for dongle-based data */ -+ -+ /* Additional stats for the bus level */ -+ -+ /* Data packets sent to dongle */ -+ unsigned long tx_packets; -+ /* Multicast data packets sent to dongle */ -+ unsigned long tx_multicast; -+ /* Errors in sending data to dongle */ -+ unsigned long tx_errors; -+ /* Control packets sent to dongle */ -+ unsigned long tx_ctlpkts; -+ /* Errors sending control frames to dongle */ -+ unsigned long tx_ctlerrs; -+ /* Packets sent up the network interface */ -+ unsigned long rx_packets; -+ /* Multicast packets sent up the network interface */ -+ unsigned long rx_multicast; -+ /* Errors processing rx data packets */ -+ unsigned long rx_errors; -+ /* Control frames processed from dongle */ -+ unsigned long rx_ctlpkts; -+ -+ /* Errors in processing rx control frames */ -+ unsigned long rx_ctlerrs; -+ /* Packets dropped locally (no memory) */ -+ unsigned long rx_dropped; -+ /* Packets flushed due to unscheduled sendup thread */ -+ unsigned long rx_flushed; -+ /* Number of times dpc scheduled by watchdog timer */ -+ unsigned long wd_dpc_sched; -+ -+ /* Number of packets where header read-ahead was used. */ -+ unsigned long rx_readahead_cnt; -+ /* Number of tx packets we had to realloc for headroom */ -+ unsigned long tx_realloc; -+ /* Number of flow control pkts recvd */ -+ unsigned long fc_packets; -+ -+ /* Last error return */ -+ int bcmerror; -+ uint tickcnt; -+ -+ /* Last error from dongle */ -+ int dongle_error; -+ -+ /* Suspend disable flag flag */ -+ int suspend_disable_flag; /* "1" to disable all extra powersaving -+ during suspend */ -+ int in_suspend; /* flag set to 1 when early suspend called */ -+ int dtim_skip; /* dtim skip , default 0 means wake each dtim */ -+ -+ /* Pkt filter defination */ -+ char *pktfilter[100]; -+ int pktfilter_count; -+ -+ u8 country_code[BRCM_CNTRY_BUF_SZ]; -+ char eventmask[BRCMF_EVENTING_MASK_LEN]; -+ -+}; -+ -+struct brcmf_if_event { -+ u8 ifidx; -+ u8 action; -+ u8 flags; -+ u8 bssidx; -+}; -+ -+struct bcmevent_name { -+ uint event; -+ const char *name; -+}; -+ -+extern const struct bcmevent_name bcmevent_names[]; -+ -+extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen, -+ char *buf, uint len); -+ -+/* Indication from bus module regarding presence/insertion of dongle. -+ * Return struct brcmf_pub pointer, used as handle to OS module in later calls. -+ * Returned structure should have bus and prot pointers filled in. -+ * bus_hdrlen specifies required headroom for bus module header. -+ */ -+extern struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, -+ uint bus_hdrlen); -+extern int brcmf_net_attach(struct brcmf_pub *drvr, int idx); -+extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev); -+ -+extern s32 brcmf_exec_dcmd(struct net_device *dev, u32 cmd, void *arg, u32 len); -+ -+/* Indication from bus module regarding removal/absence of dongle */ -+extern void brcmf_detach(struct brcmf_pub *drvr); -+ -+/* Indication from bus module to change flow-control state */ -+extern void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool on); -+ -+extern bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q, -+ struct sk_buff *pkt, int prec); -+ -+/* Receive frame for delivery to OS. Callee disposes of rxp. */ -+extern void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, -+ struct sk_buff *rxp, int numpkt); -+ -+/* Return pointer to interface name */ -+extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx); -+ -+/* Notify tx completion */ -+extern void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, -+ bool success); -+ -+/* Query dongle */ -+extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, -+ uint cmd, void *buf, uint len); -+ -+/* OS independent layer functions */ -+extern int brcmf_os_proto_block(struct brcmf_pub *drvr); -+extern int brcmf_os_proto_unblock(struct brcmf_pub *drvr); -+#ifdef BCMDBG -+extern int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size); -+#endif /* BCMDBG */ -+ -+extern int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name); -+extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx, -+ void *pktdata, struct brcmf_event_msg *, -+ void **data_ptr); -+ -+extern void brcmf_c_init(void); -+ -+extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, -+ struct net_device *ndev, char *name, u8 *mac_addr, -+ u32 flags, u8 bssidx); -+extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx); -+ -+/* Send packet to dongle via data channel */ -+extern int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx,\ -+ struct sk_buff *pkt); -+ -+extern int brcmf_bus_start(struct brcmf_pub *drvr); -+ -+extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg); -+extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, -+ int enable, int master_mode); -+ -+#define BRCMF_DCMD_SMLEN 256 /* "small" cmd buffer required */ -+#define BRCMF_DCMD_MEDLEN 1536 /* "med" cmd buffer required */ -+#define BRCMF_DCMD_MAXLEN 8192 /* max length cmd buffer required */ -+ -+/* message levels */ -+#define BRCMF_ERROR_VAL 0x0001 -+#define BRCMF_TRACE_VAL 0x0002 -+#define BRCMF_INFO_VAL 0x0004 -+#define BRCMF_DATA_VAL 0x0008 -+#define BRCMF_CTL_VAL 0x0010 -+#define BRCMF_TIMER_VAL 0x0020 -+#define BRCMF_HDRS_VAL 0x0040 -+#define BRCMF_BYTES_VAL 0x0080 -+#define BRCMF_INTR_VAL 0x0100 -+#define BRCMF_GLOM_VAL 0x0400 -+#define BRCMF_EVENT_VAL 0x0800 -+#define BRCMF_BTA_VAL 0x1000 -+#define BRCMF_ISCAN_VAL 0x2000 -+ -+/* Enter idle immediately (no timeout) */ -+#define BRCMF_IDLE_IMMEDIATE (-1) -+#define BRCMF_IDLE_ACTIVE 0 /* Do not request any SD clock change -+ when idle */ -+#define BRCMF_IDLE_INTERVAL 1 -+ -+#endif /* _BRCMF_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c.orig 2011-11-09 13:46:58.232800795 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c 2011-11-09 13:47:16.983566378 -0500 -@@ -0,0 +1,1356 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dhd.h" -+#include "dhd_bus.h" -+#include "dhd_proto.h" -+#include "dhd_dbg.h" -+#include "wl_cfg80211.h" -+#include "bcmchip.h" -+ -+MODULE_AUTHOR("Broadcom Corporation"); -+MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac driver."); -+MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards"); -+MODULE_LICENSE("Dual BSD/GPL"); -+ -+ -+/* Interface control information */ -+struct brcmf_if { -+ struct brcmf_info *info; /* back pointer to brcmf_info */ -+ /* OS/stack specifics */ -+ struct net_device *ndev; -+ struct net_device_stats stats; -+ int idx; /* iface idx in dongle */ -+ int state; /* interface state */ -+ u8 mac_addr[ETH_ALEN]; /* assigned MAC address */ -+}; -+ -+/* Local private structure (extension of pub) */ -+struct brcmf_info { -+ struct brcmf_pub pub; -+ -+ /* OS/stack specifics */ -+ struct brcmf_if *iflist[BRCMF_MAX_IFS]; -+ -+ struct mutex proto_block; -+ -+ struct work_struct setmacaddr_work; -+ struct work_struct multicast_work; -+ u8 macvalue[ETH_ALEN]; -+ atomic_t pend_8021x_cnt; -+}; -+ -+/* Error bits */ -+module_param(brcmf_msg_level, int, 0); -+ -+ -+static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *ndev) -+{ -+ int i = 0; -+ -+ while (i < BRCMF_MAX_IFS) { -+ if (drvr_priv->iflist[i] && drvr_priv->iflist[i]->ndev == ndev) -+ return i; -+ i++; -+ } -+ -+ return BRCMF_BAD_IF; -+} -+ -+int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name) -+{ -+ int i = BRCMF_MAX_IFS; -+ struct brcmf_if *ifp; -+ -+ if (name == NULL || *name == '\0') -+ return 0; -+ -+ while (--i > 0) { -+ ifp = drvr_priv->iflist[i]; -+ if (ifp && !strncmp(ifp->ndev->name, name, IFNAMSIZ)) -+ break; -+ } -+ -+ brcmf_dbg(TRACE, "return idx %d for \"%s\"\n", i, name); -+ -+ return i; /* default - the primary interface */ -+} -+ -+char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx) -+{ -+ struct brcmf_info *drvr_priv = drvr->info; -+ -+ if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { -+ brcmf_dbg(ERROR, "ifidx %d out of range\n", ifidx); -+ return ""; -+ } -+ -+ if (drvr_priv->iflist[ifidx] == NULL) { -+ brcmf_dbg(ERROR, "null i/f %d\n", ifidx); -+ return ""; -+ } -+ -+ if (drvr_priv->iflist[ifidx]->ndev) -+ return drvr_priv->iflist[ifidx]->ndev->name; -+ -+ return ""; -+} -+ -+static void _brcmf_set_multicast_list(struct work_struct *work) -+{ -+ struct net_device *ndev; -+ struct netdev_hw_addr *ha; -+ u32 dcmd_value, cnt; -+ __le32 cnt_le; -+ __le32 dcmd_le_value; -+ -+ struct brcmf_dcmd dcmd; -+ char *buf, *bufp; -+ uint buflen; -+ int ret; -+ -+ struct brcmf_info *drvr_priv = container_of(work, struct brcmf_info, -+ multicast_work); -+ -+ ndev = drvr_priv->iflist[0]->ndev; -+ cnt = netdev_mc_count(ndev); -+ -+ /* Determine initial value of allmulti flag */ -+ dcmd_value = (ndev->flags & IFF_ALLMULTI) ? true : false; -+ -+ /* Send down the multicast list first. */ -+ -+ buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETH_ALEN); -+ bufp = buf = kmalloc(buflen, GFP_ATOMIC); -+ if (!bufp) -+ return; -+ -+ strcpy(bufp, "mcast_list"); -+ bufp += strlen("mcast_list") + 1; -+ -+ cnt_le = cpu_to_le32(cnt); -+ memcpy(bufp, &cnt_le, sizeof(cnt)); -+ bufp += sizeof(cnt_le); -+ -+ netdev_for_each_mc_addr(ha, ndev) { -+ if (!cnt) -+ break; -+ memcpy(bufp, ha->addr, ETH_ALEN); -+ bufp += ETH_ALEN; -+ cnt--; -+ } -+ -+ memset(&dcmd, 0, sizeof(dcmd)); -+ dcmd.cmd = BRCMF_C_SET_VAR; -+ dcmd.buf = buf; -+ dcmd.len = buflen; -+ dcmd.set = true; -+ -+ ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len); -+ if (ret < 0) { -+ brcmf_dbg(ERROR, "%s: set mcast_list failed, cnt %d\n", -+ brcmf_ifname(&drvr_priv->pub, 0), cnt); -+ dcmd_value = cnt ? true : dcmd_value; -+ } -+ -+ kfree(buf); -+ -+ /* Now send the allmulti setting. This is based on the setting in the -+ * net_device flags, but might be modified above to be turned on if we -+ * were trying to set some addresses and dongle rejected it... -+ */ -+ -+ buflen = sizeof("allmulti") + sizeof(dcmd_value); -+ buf = kmalloc(buflen, GFP_ATOMIC); -+ if (!buf) -+ return; -+ -+ dcmd_le_value = cpu_to_le32(dcmd_value); -+ -+ if (!brcmf_c_mkiovar -+ ("allmulti", (void *)&dcmd_le_value, -+ sizeof(dcmd_le_value), buf, buflen)) { -+ brcmf_dbg(ERROR, "%s: mkiovar failed for allmulti, datalen %d buflen %u\n", -+ brcmf_ifname(&drvr_priv->pub, 0), -+ (int)sizeof(dcmd_value), buflen); -+ kfree(buf); -+ return; -+ } -+ -+ memset(&dcmd, 0, sizeof(dcmd)); -+ dcmd.cmd = BRCMF_C_SET_VAR; -+ dcmd.buf = buf; -+ dcmd.len = buflen; -+ dcmd.set = true; -+ -+ ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len); -+ if (ret < 0) { -+ brcmf_dbg(ERROR, "%s: set allmulti %d failed\n", -+ brcmf_ifname(&drvr_priv->pub, 0), -+ le32_to_cpu(dcmd_le_value)); -+ } -+ -+ kfree(buf); -+ -+ /* Finally, pick up the PROMISC flag as well, like the NIC -+ driver does */ -+ -+ dcmd_value = (ndev->flags & IFF_PROMISC) ? true : false; -+ dcmd_le_value = cpu_to_le32(dcmd_value); -+ -+ memset(&dcmd, 0, sizeof(dcmd)); -+ dcmd.cmd = BRCMF_C_SET_PROMISC; -+ dcmd.buf = &dcmd_le_value; -+ dcmd.len = sizeof(dcmd_le_value); -+ dcmd.set = true; -+ -+ ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len); -+ if (ret < 0) { -+ brcmf_dbg(ERROR, "%s: set promisc %d failed\n", -+ brcmf_ifname(&drvr_priv->pub, 0), -+ le32_to_cpu(dcmd_le_value)); -+ } -+} -+ -+static void -+_brcmf_set_mac_address(struct work_struct *work) -+{ -+ char buf[32]; -+ struct brcmf_dcmd dcmd; -+ int ret; -+ -+ struct brcmf_info *drvr_priv = container_of(work, struct brcmf_info, -+ setmacaddr_work); -+ -+ brcmf_dbg(TRACE, "enter\n"); -+ if (!brcmf_c_mkiovar("cur_etheraddr", (char *)drvr_priv->macvalue, -+ ETH_ALEN, buf, 32)) { -+ brcmf_dbg(ERROR, "%s: mkiovar failed for cur_etheraddr\n", -+ brcmf_ifname(&drvr_priv->pub, 0)); -+ return; -+ } -+ memset(&dcmd, 0, sizeof(dcmd)); -+ dcmd.cmd = BRCMF_C_SET_VAR; -+ dcmd.buf = buf; -+ dcmd.len = 32; -+ dcmd.set = true; -+ -+ ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len); -+ if (ret < 0) -+ brcmf_dbg(ERROR, "%s: set cur_etheraddr failed\n", -+ brcmf_ifname(&drvr_priv->pub, 0)); -+ else -+ memcpy(drvr_priv->iflist[0]->ndev->dev_addr, -+ drvr_priv->macvalue, ETH_ALEN); -+ -+ return; -+} -+ -+static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr) -+{ -+ struct brcmf_info *drvr_priv = *(struct brcmf_info **) -+ netdev_priv(ndev); -+ struct sockaddr *sa = (struct sockaddr *)addr; -+ int ifidx; -+ -+ ifidx = brcmf_net2idx(drvr_priv, ndev); -+ if (ifidx == BRCMF_BAD_IF) -+ return -1; -+ -+ memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN); -+ schedule_work(&drvr_priv->setmacaddr_work); -+ return 0; -+} -+ -+static void brcmf_netdev_set_multicast_list(struct net_device *ndev) -+{ -+ struct brcmf_info *drvr_priv = *(struct brcmf_info **) -+ netdev_priv(ndev); -+ int ifidx; -+ -+ ifidx = brcmf_net2idx(drvr_priv, ndev); -+ if (ifidx == BRCMF_BAD_IF) -+ return; -+ -+ schedule_work(&drvr_priv->multicast_work); -+} -+ -+int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf) -+{ -+ struct brcmf_info *drvr_priv = drvr->info; -+ -+ /* Reject if down */ -+ if (!drvr->up || (drvr->busstate == BRCMF_BUS_DOWN)) -+ return -ENODEV; -+ -+ /* Update multicast statistic */ -+ if (pktbuf->len >= ETH_ALEN) { -+ u8 *pktdata = (u8 *) (pktbuf->data); -+ struct ethhdr *eh = (struct ethhdr *)pktdata; -+ -+ if (is_multicast_ether_addr(eh->h_dest)) -+ drvr->tx_multicast++; -+ if (ntohs(eh->h_proto) == ETH_P_PAE) -+ atomic_inc(&drvr_priv->pend_8021x_cnt); -+ } -+ -+ /* If the protocol uses a data header, apply it */ -+ brcmf_proto_hdrpush(drvr, ifidx, pktbuf); -+ -+ /* Use bus module to send data frame */ -+ return brcmf_sdbrcm_bus_txdata(drvr->bus, pktbuf); -+} -+ -+static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) -+{ -+ int ret; -+ struct brcmf_info *drvr_priv = *(struct brcmf_info **) -+ netdev_priv(ndev); -+ int ifidx; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* Reject if down */ -+ if (!drvr_priv->pub.up || (drvr_priv->pub.busstate == BRCMF_BUS_DOWN)) { -+ brcmf_dbg(ERROR, "xmit rejected pub.up=%d busstate=%d\n", -+ drvr_priv->pub.up, drvr_priv->pub.busstate); -+ netif_stop_queue(ndev); -+ return -ENODEV; -+ } -+ -+ ifidx = brcmf_net2idx(drvr_priv, ndev); -+ if (ifidx == BRCMF_BAD_IF) { -+ brcmf_dbg(ERROR, "bad ifidx %d\n", ifidx); -+ netif_stop_queue(ndev); -+ return -ENODEV; -+ } -+ -+ /* Make sure there's enough room for any header */ -+ if (skb_headroom(skb) < drvr_priv->pub.hdrlen) { -+ struct sk_buff *skb2; -+ -+ brcmf_dbg(INFO, "%s: insufficient headroom\n", -+ brcmf_ifname(&drvr_priv->pub, ifidx)); -+ drvr_priv->pub.tx_realloc++; -+ skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen); -+ dev_kfree_skb(skb); -+ skb = skb2; -+ if (skb == NULL) { -+ brcmf_dbg(ERROR, "%s: skb_realloc_headroom failed\n", -+ brcmf_ifname(&drvr_priv->pub, ifidx)); -+ ret = -ENOMEM; -+ goto done; -+ } -+ } -+ -+ ret = brcmf_sendpkt(&drvr_priv->pub, ifidx, skb); -+ -+done: -+ if (ret) -+ drvr_priv->pub.dstats.tx_dropped++; -+ else -+ drvr_priv->pub.tx_packets++; -+ -+ /* Return ok: we always eat the packet */ -+ return 0; -+} -+ -+void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool state) -+{ -+ struct net_device *ndev; -+ struct brcmf_info *drvr_priv = drvr->info; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ drvr->txoff = state; -+ ndev = drvr_priv->iflist[ifidx]->ndev; -+ if (state == ON) -+ netif_stop_queue(ndev); -+ else -+ netif_wake_queue(ndev); -+} -+ -+static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, -+ void *pktdata, struct brcmf_event_msg *event, -+ void **data) -+{ -+ int bcmerror = 0; -+ -+ bcmerror = brcmf_c_host_event(drvr_priv, ifidx, pktdata, event, data); -+ if (bcmerror != 0) -+ return bcmerror; -+ -+ if (drvr_priv->iflist[*ifidx]->ndev) -+ brcmf_cfg80211_event(drvr_priv->iflist[*ifidx]->ndev, -+ event, *data); -+ -+ return bcmerror; -+} -+ -+void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb, -+ int numpkt) -+{ -+ struct brcmf_info *drvr_priv = drvr->info; -+ unsigned char *eth; -+ uint len; -+ void *data; -+ struct sk_buff *pnext, *save_pktbuf; -+ int i; -+ struct brcmf_if *ifp; -+ struct brcmf_event_msg event; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ save_pktbuf = skb; -+ -+ for (i = 0; skb && i < numpkt; i++, skb = pnext) { -+ -+ pnext = skb->next; -+ skb->next = NULL; -+ -+ /* Get the protocol, maintain skb around eth_type_trans() -+ * The main reason for this hack is for the limitation of -+ * Linux 2.4 where 'eth_type_trans' uses the -+ * 'net->hard_header_len' -+ * to perform skb_pull inside vs ETH_HLEN. Since to avoid -+ * coping of the packet coming from the network stack to add -+ * BDC, Hardware header etc, during network interface -+ * registration -+ * we set the 'net->hard_header_len' to ETH_HLEN + extra space -+ * required -+ * for BDC, Hardware header etc. and not just the ETH_HLEN -+ */ -+ eth = skb->data; -+ len = skb->len; -+ -+ ifp = drvr_priv->iflist[ifidx]; -+ if (ifp == NULL) -+ ifp = drvr_priv->iflist[0]; -+ -+ skb->dev = ifp->ndev; -+ skb->protocol = eth_type_trans(skb, skb->dev); -+ -+ if (skb->pkt_type == PACKET_MULTICAST) -+ drvr_priv->pub.rx_multicast++; -+ -+ skb->data = eth; -+ skb->len = len; -+ -+ /* Strip header, count, deliver upward */ -+ skb_pull(skb, ETH_HLEN); -+ -+ /* Process special event packets and then discard them */ -+ if (ntohs(skb->protocol) == ETH_P_LINK_CTL) -+ brcmf_host_event(drvr_priv, &ifidx, -+ skb_mac_header(skb), -+ &event, &data); -+ -+ if (drvr_priv->iflist[ifidx] && -+ !drvr_priv->iflist[ifidx]->state) -+ ifp = drvr_priv->iflist[ifidx]; -+ -+ if (ifp->ndev) -+ ifp->ndev->last_rx = jiffies; -+ -+ drvr->dstats.rx_bytes += skb->len; -+ drvr->rx_packets++; /* Local count */ -+ -+ if (in_interrupt()) -+ netif_rx(skb); -+ else -+ /* If the receive is not processed inside an ISR, -+ * the softirqd must be woken explicitly to service -+ * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled -+ * by netif_rx_ni(), but in earlier kernels, we need -+ * to do it manually. -+ */ -+ netif_rx_ni(skb); -+ } -+} -+ -+void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, bool success) -+{ -+ uint ifidx; -+ struct brcmf_info *drvr_priv = drvr->info; -+ struct ethhdr *eh; -+ u16 type; -+ -+ brcmf_proto_hdrpull(drvr, &ifidx, txp); -+ -+ eh = (struct ethhdr *)(txp->data); -+ type = ntohs(eh->h_proto); -+ -+ if (type == ETH_P_PAE) -+ atomic_dec(&drvr_priv->pend_8021x_cnt); -+ -+} -+ -+static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) -+{ -+ struct brcmf_info *drvr_priv = *(struct brcmf_info **) -+ netdev_priv(ndev); -+ struct brcmf_if *ifp; -+ int ifidx; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ ifidx = brcmf_net2idx(drvr_priv, ndev); -+ if (ifidx == BRCMF_BAD_IF) -+ return NULL; -+ -+ ifp = drvr_priv->iflist[ifidx]; -+ -+ if (drvr_priv->pub.up) -+ /* Use the protocol to get dongle stats */ -+ brcmf_proto_dstats(&drvr_priv->pub); -+ -+ /* Copy dongle stats to net device stats */ -+ ifp->stats.rx_packets = drvr_priv->pub.dstats.rx_packets; -+ ifp->stats.tx_packets = drvr_priv->pub.dstats.tx_packets; -+ ifp->stats.rx_bytes = drvr_priv->pub.dstats.rx_bytes; -+ ifp->stats.tx_bytes = drvr_priv->pub.dstats.tx_bytes; -+ ifp->stats.rx_errors = drvr_priv->pub.dstats.rx_errors; -+ ifp->stats.tx_errors = drvr_priv->pub.dstats.tx_errors; -+ ifp->stats.rx_dropped = drvr_priv->pub.dstats.rx_dropped; -+ ifp->stats.tx_dropped = drvr_priv->pub.dstats.tx_dropped; -+ ifp->stats.multicast = drvr_priv->pub.dstats.multicast; -+ -+ return &ifp->stats; -+} -+ -+/* Retrieve current toe component enables, which are kept -+ as a bitmap in toe_ol iovar */ -+static int brcmf_toe_get(struct brcmf_info *drvr_priv, int ifidx, u32 *toe_ol) -+{ -+ struct brcmf_dcmd dcmd; -+ __le32 toe_le; -+ char buf[32]; -+ int ret; -+ -+ memset(&dcmd, 0, sizeof(dcmd)); -+ -+ dcmd.cmd = BRCMF_C_GET_VAR; -+ dcmd.buf = buf; -+ dcmd.len = (uint) sizeof(buf); -+ dcmd.set = false; -+ -+ strcpy(buf, "toe_ol"); -+ ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len); -+ if (ret < 0) { -+ /* Check for older dongle image that doesn't support toe_ol */ -+ if (ret == -EIO) { -+ brcmf_dbg(ERROR, "%s: toe not supported by device\n", -+ brcmf_ifname(&drvr_priv->pub, ifidx)); -+ return -EOPNOTSUPP; -+ } -+ -+ brcmf_dbg(INFO, "%s: could not get toe_ol: ret=%d\n", -+ brcmf_ifname(&drvr_priv->pub, ifidx), ret); -+ return ret; -+ } -+ -+ memcpy(&toe_le, buf, sizeof(u32)); -+ *toe_ol = le32_to_cpu(toe_le); -+ return 0; -+} -+ -+/* Set current toe component enables in toe_ol iovar, -+ and set toe global enable iovar */ -+static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol) -+{ -+ struct brcmf_dcmd dcmd; -+ char buf[32]; -+ int ret; -+ __le32 toe_le = cpu_to_le32(toe_ol); -+ -+ memset(&dcmd, 0, sizeof(dcmd)); -+ -+ dcmd.cmd = BRCMF_C_SET_VAR; -+ dcmd.buf = buf; -+ dcmd.len = (uint) sizeof(buf); -+ dcmd.set = true; -+ -+ /* Set toe_ol as requested */ -+ strcpy(buf, "toe_ol"); -+ memcpy(&buf[sizeof("toe_ol")], &toe_le, sizeof(u32)); -+ -+ ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len); -+ if (ret < 0) { -+ brcmf_dbg(ERROR, "%s: could not set toe_ol: ret=%d\n", -+ brcmf_ifname(&drvr_priv->pub, ifidx), ret); -+ return ret; -+ } -+ -+ /* Enable toe globally only if any components are enabled. */ -+ toe_le = cpu_to_le32(toe_ol != 0); -+ -+ strcpy(buf, "toe"); -+ memcpy(&buf[sizeof("toe")], &toe_le, sizeof(u32)); -+ -+ ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len); -+ if (ret < 0) { -+ brcmf_dbg(ERROR, "%s: could not set toe: ret=%d\n", -+ brcmf_ifname(&drvr_priv->pub, ifidx), ret); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static void brcmf_ethtool_get_drvinfo(struct net_device *ndev, -+ struct ethtool_drvinfo *info) -+{ -+ struct brcmf_info *drvr_priv = *(struct brcmf_info **) -+ netdev_priv(ndev); -+ -+ sprintf(info->driver, KBUILD_MODNAME); -+ sprintf(info->version, "%lu", drvr_priv->pub.drv_version); -+ sprintf(info->fw_version, "%s", BCM4329_FW_NAME); -+ sprintf(info->bus_info, "%s", -+ dev_name(brcmf_bus_get_device(drvr_priv->pub.bus))); -+} -+ -+static struct ethtool_ops brcmf_ethtool_ops = { -+ .get_drvinfo = brcmf_ethtool_get_drvinfo -+}; -+ -+static int brcmf_ethtool(struct brcmf_info *drvr_priv, void __user *uaddr) -+{ -+ struct ethtool_drvinfo info; -+ char drvname[sizeof(info.driver)]; -+ u32 cmd; -+ struct ethtool_value edata; -+ u32 toe_cmpnt, csum_dir; -+ int ret; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* all ethtool calls start with a cmd word */ -+ if (copy_from_user(&cmd, uaddr, sizeof(u32))) -+ return -EFAULT; -+ -+ switch (cmd) { -+ case ETHTOOL_GDRVINFO: -+ /* Copy out any request driver name */ -+ if (copy_from_user(&info, uaddr, sizeof(info))) -+ return -EFAULT; -+ strncpy(drvname, info.driver, sizeof(info.driver)); -+ drvname[sizeof(info.driver) - 1] = '\0'; -+ -+ /* clear struct for return */ -+ memset(&info, 0, sizeof(info)); -+ info.cmd = cmd; -+ -+ /* if requested, identify ourselves */ -+ if (strcmp(drvname, "?dhd") == 0) { -+ sprintf(info.driver, "dhd"); -+ strcpy(info.version, BRCMF_VERSION_STR); -+ } -+ -+ /* otherwise, require dongle to be up */ -+ else if (!drvr_priv->pub.up) { -+ brcmf_dbg(ERROR, "dongle is not up\n"); -+ return -ENODEV; -+ } -+ -+ /* finally, report dongle driver type */ -+ else if (drvr_priv->pub.iswl) -+ sprintf(info.driver, "wl"); -+ else -+ sprintf(info.driver, "xx"); -+ -+ sprintf(info.version, "%lu", drvr_priv->pub.drv_version); -+ if (copy_to_user(uaddr, &info, sizeof(info))) -+ return -EFAULT; -+ brcmf_dbg(CTL, "given %*s, returning %s\n", -+ (int)sizeof(drvname), drvname, info.driver); -+ break; -+ -+ /* Get toe offload components from dongle */ -+ case ETHTOOL_GRXCSUM: -+ case ETHTOOL_GTXCSUM: -+ ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt); -+ if (ret < 0) -+ return ret; -+ -+ csum_dir = -+ (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL; -+ -+ edata.cmd = cmd; -+ edata.data = (toe_cmpnt & csum_dir) ? 1 : 0; -+ -+ if (copy_to_user(uaddr, &edata, sizeof(edata))) -+ return -EFAULT; -+ break; -+ -+ /* Set toe offload components in dongle */ -+ case ETHTOOL_SRXCSUM: -+ case ETHTOOL_STXCSUM: -+ if (copy_from_user(&edata, uaddr, sizeof(edata))) -+ return -EFAULT; -+ -+ /* Read the current settings, update and write back */ -+ ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt); -+ if (ret < 0) -+ return ret; -+ -+ csum_dir = -+ (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL; -+ -+ if (edata.data != 0) -+ toe_cmpnt |= csum_dir; -+ else -+ toe_cmpnt &= ~csum_dir; -+ -+ ret = brcmf_toe_set(drvr_priv, 0, toe_cmpnt); -+ if (ret < 0) -+ return ret; -+ -+ /* If setting TX checksum mode, tell Linux the new mode */ -+ if (cmd == ETHTOOL_STXCSUM) { -+ if (edata.data) -+ drvr_priv->iflist[0]->ndev->features |= -+ NETIF_F_IP_CSUM; -+ else -+ drvr_priv->iflist[0]->ndev->features &= -+ ~NETIF_F_IP_CSUM; -+ } -+ -+ break; -+ -+ default: -+ return -EOPNOTSUPP; -+ } -+ -+ return 0; -+} -+ -+static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr, -+ int cmd) -+{ -+ struct brcmf_info *drvr_priv = *(struct brcmf_info **) -+ netdev_priv(ndev); -+ int ifidx; -+ -+ ifidx = brcmf_net2idx(drvr_priv, ndev); -+ brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifidx, cmd); -+ -+ if (ifidx == BRCMF_BAD_IF) -+ return -1; -+ -+ if (cmd == SIOCETHTOOL) -+ return brcmf_ethtool(drvr_priv, ifr->ifr_data); -+ -+ return -EOPNOTSUPP; -+} -+ -+/* called only from within this driver. Sends a command to the dongle. */ -+s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len) -+{ -+ struct brcmf_dcmd dcmd; -+ s32 err = 0; -+ int buflen = 0; -+ bool is_set_key_cmd; -+ struct brcmf_info *drvr_priv = *(struct brcmf_info **) -+ netdev_priv(ndev); -+ int ifidx; -+ -+ memset(&dcmd, 0, sizeof(dcmd)); -+ dcmd.cmd = cmd; -+ dcmd.buf = arg; -+ dcmd.len = len; -+ -+ ifidx = brcmf_net2idx(drvr_priv, ndev); -+ -+ if (dcmd.buf != NULL) -+ buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN); -+ -+ /* send to dongle (must be up, and wl) */ -+ if ((drvr_priv->pub.busstate != BRCMF_BUS_DATA)) { -+ brcmf_dbg(ERROR, "DONGLE_DOWN\n"); -+ err = -EIO; -+ goto done; -+ } -+ -+ if (!drvr_priv->pub.iswl) { -+ err = -EIO; -+ goto done; -+ } -+ -+ /* -+ * Intercept BRCMF_C_SET_KEY CMD - serialize M4 send and -+ * set key CMD to prevent M4 encryption. -+ */ -+ is_set_key_cmd = ((dcmd.cmd == BRCMF_C_SET_KEY) || -+ ((dcmd.cmd == BRCMF_C_SET_VAR) && -+ !(strncmp("wsec_key", dcmd.buf, 9))) || -+ ((dcmd.cmd == BRCMF_C_SET_VAR) && -+ !(strncmp("bsscfg:wsec_key", dcmd.buf, 15)))); -+ if (is_set_key_cmd) -+ brcmf_netdev_wait_pend8021x(ndev); -+ -+ err = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, buflen); -+ -+done: -+ if (err > 0) -+ err = 0; -+ -+ return err; -+} -+ -+static int brcmf_netdev_stop(struct net_device *ndev) -+{ -+ struct brcmf_pub *drvr = *(struct brcmf_pub **) netdev_priv(ndev); -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ brcmf_cfg80211_down(drvr->config); -+ if (drvr->up == 0) -+ return 0; -+ -+ /* Set state and stop OS transmissions */ -+ drvr->up = 0; -+ netif_stop_queue(ndev); -+ -+ return 0; -+} -+ -+static int brcmf_netdev_open(struct net_device *ndev) -+{ -+ struct brcmf_info *drvr_priv = *(struct brcmf_info **) -+ netdev_priv(ndev); -+ u32 toe_ol; -+ int ifidx = brcmf_net2idx(drvr_priv, ndev); -+ s32 ret = 0; -+ -+ brcmf_dbg(TRACE, "ifidx %d\n", ifidx); -+ -+ if (ifidx == 0) { /* do it only for primary eth0 */ -+ -+ /* try to bring up bus */ -+ ret = brcmf_bus_start(&drvr_priv->pub); -+ if (ret != 0) { -+ brcmf_dbg(ERROR, "failed with code %d\n", ret); -+ return -1; -+ } -+ atomic_set(&drvr_priv->pend_8021x_cnt, 0); -+ -+ memcpy(ndev->dev_addr, drvr_priv->pub.mac, ETH_ALEN); -+ -+ /* Get current TOE mode from dongle */ -+ if (brcmf_toe_get(drvr_priv, ifidx, &toe_ol) >= 0 -+ && (toe_ol & TOE_TX_CSUM_OL) != 0) -+ drvr_priv->iflist[ifidx]->ndev->features |= -+ NETIF_F_IP_CSUM; -+ else -+ drvr_priv->iflist[ifidx]->ndev->features &= -+ ~NETIF_F_IP_CSUM; -+ } -+ /* Allow transmit calls */ -+ netif_start_queue(ndev); -+ drvr_priv->pub.up = 1; -+ if (brcmf_cfg80211_up(drvr_priv->pub.config)) { -+ brcmf_dbg(ERROR, "failed to bring up cfg80211\n"); -+ return -1; -+ } -+ -+ return ret; -+} -+ -+int -+brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, struct net_device *ndev, -+ char *name, u8 *mac_addr, u32 flags, u8 bssidx) -+{ -+ struct brcmf_if *ifp; -+ int ret = 0, err = 0; -+ -+ brcmf_dbg(TRACE, "idx %d, handle->%p\n", ifidx, ndev); -+ -+ ifp = drvr_priv->iflist[ifidx]; -+ if (!ifp) { -+ ifp = kmalloc(sizeof(struct brcmf_if), GFP_ATOMIC); -+ if (!ifp) -+ return -ENOMEM; -+ } -+ -+ memset(ifp, 0, sizeof(struct brcmf_if)); -+ ifp->info = drvr_priv; -+ drvr_priv->iflist[ifidx] = ifp; -+ if (mac_addr != NULL) -+ memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN); -+ -+ if (ndev == NULL) { -+ ifp->state = BRCMF_E_IF_ADD; -+ ifp->idx = ifidx; -+ /* -+ * Delete the existing interface before overwriting it -+ * in case we missed the BRCMF_E_IF_DEL event. -+ */ -+ if (ifp->ndev != NULL) { -+ brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n", -+ ifp->ndev->name); -+ netif_stop_queue(ifp->ndev); -+ unregister_netdev(ifp->ndev); -+ free_netdev(ifp->ndev); -+ } -+ -+ /* Allocate netdev, including space for private structure */ -+ ifp->ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d", -+ ether_setup); -+ if (!ifp->ndev) { -+ brcmf_dbg(ERROR, "OOM - alloc_netdev\n"); -+ ret = -ENOMEM; -+ } -+ -+ if (ret == 0) { -+ memcpy(netdev_priv(ifp->ndev), &drvr_priv, -+ sizeof(drvr_priv)); -+ err = brcmf_net_attach(&drvr_priv->pub, ifp->idx); -+ if (err != 0) { -+ brcmf_dbg(ERROR, "brcmf_net_attach failed, err %d\n", -+ err); -+ ret = -EOPNOTSUPP; -+ } else { -+ brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n", -+ current->pid, ifp->ndev->name); -+ ifp->state = 0; -+ } -+ } -+ -+ if (ret < 0) { -+ if (ifp->ndev) -+ free_netdev(ifp->ndev); -+ -+ drvr_priv->iflist[ifp->idx] = NULL; -+ kfree(ifp); -+ } -+ } else -+ ifp->ndev = ndev; -+ -+ return 0; -+} -+ -+void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx) -+{ -+ struct brcmf_if *ifp; -+ -+ brcmf_dbg(TRACE, "idx %d\n", ifidx); -+ -+ ifp = drvr_priv->iflist[ifidx]; -+ if (!ifp) { -+ brcmf_dbg(ERROR, "Null interface\n"); -+ return; -+ } -+ -+ ifp->state = BRCMF_E_IF_DEL; -+ ifp->idx = ifidx; -+ if (ifp->ndev != NULL) { -+ netif_stop_queue(ifp->ndev); -+ unregister_netdev(ifp->ndev); -+ free_netdev(ifp->ndev); -+ drvr_priv->iflist[ifidx] = NULL; -+ kfree(ifp); -+ } -+} -+ -+struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen) -+{ -+ struct brcmf_info *drvr_priv = NULL; -+ struct net_device *ndev; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* Allocate netdev, including space for private structure */ -+ ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d", ether_setup); -+ if (!ndev) { -+ brcmf_dbg(ERROR, "OOM - alloc_netdev\n"); -+ goto fail; -+ } -+ -+ /* Allocate primary brcmf_info */ -+ drvr_priv = kzalloc(sizeof(struct brcmf_info), GFP_ATOMIC); -+ if (!drvr_priv) -+ goto fail; -+ -+ /* -+ * Save the brcmf_info into the priv -+ */ -+ memcpy(netdev_priv(ndev), &drvr_priv, sizeof(drvr_priv)); -+ -+ if (brcmf_add_if(drvr_priv, 0, ndev, ndev->name, NULL, 0, 0) == -+ BRCMF_BAD_IF) -+ goto fail; -+ -+ ndev->netdev_ops = NULL; -+ mutex_init(&drvr_priv->proto_block); -+ -+ /* Link to info module */ -+ drvr_priv->pub.info = drvr_priv; -+ -+ /* Link to bus module */ -+ drvr_priv->pub.bus = bus; -+ drvr_priv->pub.hdrlen = bus_hdrlen; -+ -+ /* Attach and link in the protocol */ -+ if (brcmf_proto_attach(&drvr_priv->pub) != 0) { -+ brcmf_dbg(ERROR, "brcmf_prot_attach failed\n"); -+ goto fail; -+ } -+ -+ /* Attach and link in the cfg80211 */ -+ drvr_priv->pub.config = -+ brcmf_cfg80211_attach(ndev, -+ brcmf_bus_get_device(bus), -+ &drvr_priv->pub); -+ if (drvr_priv->pub.config == NULL) { -+ brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n"); -+ goto fail; -+ } -+ -+ INIT_WORK(&drvr_priv->setmacaddr_work, _brcmf_set_mac_address); -+ INIT_WORK(&drvr_priv->multicast_work, _brcmf_set_multicast_list); -+ -+ /* -+ * Save the brcmf_info into the priv -+ */ -+ memcpy(netdev_priv(ndev), &drvr_priv, sizeof(drvr_priv)); -+ -+ return &drvr_priv->pub; -+ -+fail: -+ if (ndev) -+ free_netdev(ndev); -+ if (drvr_priv) -+ brcmf_detach(&drvr_priv->pub); -+ -+ return NULL; -+} -+ -+int brcmf_bus_start(struct brcmf_pub *drvr) -+{ -+ int ret = -1; -+ struct brcmf_info *drvr_priv = drvr->info; -+ /* Room for "event_msgs" + '\0' + bitvec */ -+ char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; -+ -+ brcmf_dbg(TRACE, "\n"); -+ -+ /* Bring up the bus */ -+ ret = brcmf_sdbrcm_bus_init(&drvr_priv->pub); -+ if (ret != 0) { -+ brcmf_dbg(ERROR, "brcmf_sdbrcm_bus_init failed %d\n", ret); -+ return ret; -+ } -+ -+ /* If bus is not ready, can't come up */ -+ if (drvr_priv->pub.busstate != BRCMF_BUS_DATA) { -+ brcmf_dbg(ERROR, "failed bus is not ready\n"); -+ return -ENODEV; -+ } -+ -+ brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN, -+ iovbuf, sizeof(iovbuf)); -+ brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, iovbuf, -+ sizeof(iovbuf)); -+ memcpy(drvr->eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN); -+ -+ setbit(drvr->eventmask, BRCMF_E_SET_SSID); -+ setbit(drvr->eventmask, BRCMF_E_PRUNE); -+ setbit(drvr->eventmask, BRCMF_E_AUTH); -+ setbit(drvr->eventmask, BRCMF_E_REASSOC); -+ setbit(drvr->eventmask, BRCMF_E_REASSOC_IND); -+ setbit(drvr->eventmask, BRCMF_E_DEAUTH_IND); -+ setbit(drvr->eventmask, BRCMF_E_DISASSOC_IND); -+ setbit(drvr->eventmask, BRCMF_E_DISASSOC); -+ setbit(drvr->eventmask, BRCMF_E_JOIN); -+ setbit(drvr->eventmask, BRCMF_E_ASSOC_IND); -+ setbit(drvr->eventmask, BRCMF_E_PSK_SUP); -+ setbit(drvr->eventmask, BRCMF_E_LINK); -+ setbit(drvr->eventmask, BRCMF_E_NDIS_LINK); -+ setbit(drvr->eventmask, BRCMF_E_MIC_ERROR); -+ setbit(drvr->eventmask, BRCMF_E_PMKID_CACHE); -+ setbit(drvr->eventmask, BRCMF_E_TXFAIL); -+ setbit(drvr->eventmask, BRCMF_E_JOIN_START); -+ setbit(drvr->eventmask, BRCMF_E_SCAN_COMPLETE); -+ -+/* enable dongle roaming event */ -+ -+ drvr->pktfilter_count = 1; -+ /* Setup filter to allow only unicast */ -+ drvr->pktfilter[0] = "100 0 0 0 0x01 0x00"; -+ -+ /* Bus is ready, do any protocol initialization */ -+ ret = brcmf_proto_init(&drvr_priv->pub); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+ -+static struct net_device_ops brcmf_netdev_ops_pri = { -+ .ndo_open = brcmf_netdev_open, -+ .ndo_stop = brcmf_netdev_stop, -+ .ndo_get_stats = brcmf_netdev_get_stats, -+ .ndo_do_ioctl = brcmf_netdev_ioctl_entry, -+ .ndo_start_xmit = brcmf_netdev_start_xmit, -+ .ndo_set_mac_address = brcmf_netdev_set_mac_address, -+ .ndo_set_rx_mode = brcmf_netdev_set_multicast_list -+}; -+ -+int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx) -+{ -+ struct brcmf_info *drvr_priv = drvr->info; -+ struct net_device *ndev; -+ u8 temp_addr[ETH_ALEN] = { -+ 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33}; -+ -+ brcmf_dbg(TRACE, "ifidx %d\n", ifidx); -+ -+ ndev = drvr_priv->iflist[ifidx]->ndev; -+ ndev->netdev_ops = &brcmf_netdev_ops_pri; -+ -+ /* -+ * We have to use the primary MAC for virtual interfaces -+ */ -+ if (ifidx != 0) { -+ /* for virtual interfaces use the primary MAC */ -+ memcpy(temp_addr, drvr_priv->pub.mac, ETH_ALEN); -+ -+ } -+ -+ if (ifidx == 1) { -+ brcmf_dbg(TRACE, "ACCESS POINT MAC:\n"); -+ /* ACCESSPOINT INTERFACE CASE */ -+ temp_addr[0] |= 0X02; /* set bit 2 , -+ - Locally Administered address */ -+ -+ } -+ ndev->hard_header_len = ETH_HLEN + drvr_priv->pub.hdrlen; -+ ndev->ethtool_ops = &brcmf_ethtool_ops; -+ -+ drvr_priv->pub.rxsz = ndev->mtu + ndev->hard_header_len + -+ drvr_priv->pub.hdrlen; -+ -+ memcpy(ndev->dev_addr, temp_addr, ETH_ALEN); -+ -+ if (register_netdev(ndev) != 0) { -+ brcmf_dbg(ERROR, "couldn't register the net device\n"); -+ goto fail; -+ } -+ -+ brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); -+ -+ return 0; -+ -+fail: -+ ndev->netdev_ops = NULL; -+ return -EBADE; -+} -+ -+static void brcmf_bus_detach(struct brcmf_pub *drvr) -+{ -+ struct brcmf_info *drvr_priv; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ if (drvr) { -+ drvr_priv = drvr->info; -+ if (drvr_priv) { -+ /* Stop the protocol module */ -+ brcmf_proto_stop(&drvr_priv->pub); -+ -+ /* Stop the bus module */ -+ brcmf_sdbrcm_bus_stop(drvr_priv->pub.bus); -+ } -+ } -+} -+ -+void brcmf_detach(struct brcmf_pub *drvr) -+{ -+ struct brcmf_info *drvr_priv; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ if (drvr) { -+ drvr_priv = drvr->info; -+ if (drvr_priv) { -+ struct brcmf_if *ifp; -+ int i; -+ -+ for (i = 1; i < BRCMF_MAX_IFS; i++) -+ if (drvr_priv->iflist[i]) -+ brcmf_del_if(drvr_priv, i); -+ -+ ifp = drvr_priv->iflist[0]; -+ if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) { -+ rtnl_lock(); -+ brcmf_netdev_stop(ifp->ndev); -+ rtnl_unlock(); -+ unregister_netdev(ifp->ndev); -+ } -+ -+ cancel_work_sync(&drvr_priv->setmacaddr_work); -+ cancel_work_sync(&drvr_priv->multicast_work); -+ -+ brcmf_bus_detach(drvr); -+ -+ if (drvr->prot) -+ brcmf_proto_detach(drvr); -+ -+ brcmf_cfg80211_detach(drvr->config); -+ -+ free_netdev(ifp->ndev); -+ kfree(ifp); -+ kfree(drvr_priv); -+ } -+ } -+} -+ -+static void __exit brcmf_module_cleanup(void) -+{ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ brcmf_bus_unregister(); -+} -+ -+static int __init brcmf_module_init(void) -+{ -+ int error; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ error = brcmf_bus_register(); -+ -+ if (error) { -+ brcmf_dbg(ERROR, "brcmf_bus_register failed\n"); -+ goto failed; -+ } -+ return 0; -+ -+failed: -+ return -EINVAL; -+} -+ -+module_init(brcmf_module_init); -+module_exit(brcmf_module_cleanup); -+ -+int brcmf_os_proto_block(struct brcmf_pub *drvr) -+{ -+ struct brcmf_info *drvr_priv = drvr->info; -+ -+ if (drvr_priv) { -+ mutex_lock(&drvr_priv->proto_block); -+ return 1; -+ } -+ return 0; -+} -+ -+int brcmf_os_proto_unblock(struct brcmf_pub *drvr) -+{ -+ struct brcmf_info *drvr_priv = drvr->info; -+ -+ if (drvr_priv) { -+ mutex_unlock(&drvr_priv->proto_block); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv) -+{ -+ return atomic_read(&drvr_priv->pend_8021x_cnt); -+} -+ -+#define MAX_WAIT_FOR_8021X_TX 10 -+ -+int brcmf_netdev_wait_pend8021x(struct net_device *ndev) -+{ -+ struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(ndev); -+ int timeout = 10 * HZ / 1000; -+ int ntimes = MAX_WAIT_FOR_8021X_TX; -+ int pend = brcmf_get_pend_8021x_cnt(drvr_priv); -+ -+ while (ntimes && pend) { -+ if (pend) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(timeout); -+ set_current_state(TASK_RUNNING); -+ ntimes--; -+ } -+ pend = brcmf_get_pend_8021x_cnt(drvr_priv); -+ } -+ return pend; -+} -+ -+#ifdef BCMDBG -+int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size) -+{ -+ int ret = 0; -+ struct file *fp; -+ mm_segment_t old_fs; -+ loff_t pos = 0; -+ -+ /* change to KERNEL_DS address limit */ -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ -+ /* open file to write */ -+ fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640); -+ if (!fp) { -+ brcmf_dbg(ERROR, "open file error\n"); -+ ret = -1; -+ goto exit; -+ } -+ -+ /* Write buf to file */ -+ fp->f_op->write(fp, (char __user *)buf, size, &pos); -+ -+exit: -+ /* free buf before return */ -+ kfree(buf); -+ /* close file before return */ -+ if (fp) -+ filp_close(fp, current->files); -+ /* restore previous address limit */ -+ set_fs(old_fs); -+ -+ return ret; -+} -+#endif /* BCMDBG */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h.orig 2011-11-09 13:46:58.232800795 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h 2011-11-09 13:47:16.983566378 -0500 -@@ -0,0 +1,60 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCMF_PROTO_H_ -+#define _BRCMF_PROTO_H_ -+ -+/* -+ * Exported from the brcmf protocol module (brcmf_cdc) -+ */ -+ -+/* Linkage, sets prot link and updates hdrlen in pub */ -+extern int brcmf_proto_attach(struct brcmf_pub *drvr); -+ -+/* Unlink, frees allocated protocol memory (including brcmf_proto) */ -+extern void brcmf_proto_detach(struct brcmf_pub *drvr); -+ -+/* Initialize protocol: sync w/dongle state. -+ * Sets dongle media info (iswl, drv_version, mac address). -+ */ -+extern int brcmf_proto_init(struct brcmf_pub *drvr); -+ -+/* Stop protocol: sync w/dongle state. */ -+extern void brcmf_proto_stop(struct brcmf_pub *drvr); -+ -+/* Add any protocol-specific data header. -+ * Caller must reserve prot_hdrlen prepend space. -+ */ -+extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, -+ struct sk_buff *txp); -+ -+/* Remove any protocol-specific data header. */ -+extern int brcmf_proto_hdrpull(struct brcmf_pub *, int *ifidx, -+ struct sk_buff *rxp); -+ -+/* Use protocol to issue command to dongle */ -+extern int brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, -+ struct brcmf_dcmd *dcmd, int len); -+ -+/* Update local copy of dongle statistics */ -+extern void brcmf_proto_dstats(struct brcmf_pub *drvr); -+ -+extern int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr); -+ -+extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, -+ uint cmd, void *buf, uint len); -+ -+#endif /* _BRCMF_PROTO_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c.orig 2011-11-09 13:46:58.235800758 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c 2011-11-09 13:47:16.986566342 -0500 -@@ -0,0 +1,4591 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "sdio_host.h" -+ -+#define DCMD_RESP_TIMEOUT 2000 /* In milli second */ -+ -+#ifdef BCMDBG -+ -+#define BRCMF_TRAP_INFO_SIZE 80 -+ -+#define CBUF_LEN (128) -+ -+struct rte_log_le { -+ __le32 buf; /* Can't be pointer on (64-bit) hosts */ -+ __le32 buf_size; -+ __le32 idx; -+ char *_buf_compat; /* Redundant pointer for backward compat. */ -+}; -+ -+struct rte_console { -+ /* Virtual UART -+ * When there is no UART (e.g. Quickturn), -+ * the host should write a complete -+ * input line directly into cbuf and then write -+ * the length into vcons_in. -+ * This may also be used when there is a real UART -+ * (at risk of conflicting with -+ * the real UART). vcons_out is currently unused. -+ */ -+ uint vcons_in; -+ uint vcons_out; -+ -+ /* Output (logging) buffer -+ * Console output is written to a ring buffer log_buf at index log_idx. -+ * The host may read the output when it sees log_idx advance. -+ * Output will be lost if the output wraps around faster than the host -+ * polls. -+ */ -+ struct rte_log_le log_le; -+ -+ /* Console input line buffer -+ * Characters are read one at a time into cbuf -+ * until is received, then -+ * the buffer is processed as a command line. -+ * Also used for virtual UART. -+ */ -+ uint cbuf_idx; -+ char cbuf[CBUF_LEN]; -+}; -+ -+#endif /* BCMDBG */ -+#include -+ -+#include "dhd.h" -+#include "dhd_bus.h" -+#include "dhd_proto.h" -+#include "dhd_dbg.h" -+#include -+ -+#define TXQLEN 2048 /* bulk tx queue length */ -+#define TXHI (TXQLEN - 256) /* turn on flow control above TXHI */ -+#define TXLOW (TXHI - 256) /* turn off flow control below TXLOW */ -+#define PRIOMASK 7 -+ -+#define TXRETRIES 2 /* # of retries for tx frames */ -+ -+#define BRCMF_RXBOUND 50 /* Default for max rx frames in -+ one scheduling */ -+ -+#define BRCMF_TXBOUND 20 /* Default for max tx frames in -+ one scheduling */ -+ -+#define BRCMF_TXMINMAX 1 /* Max tx frames if rx still pending */ -+ -+#define MEMBLOCK 2048 /* Block size used for downloading -+ of dongle image */ -+#define MAX_DATA_BUF (32 * 1024) /* Must be large enough to hold -+ biggest possible glom */ -+ -+#define BRCMF_FIRSTREAD (1 << 6) -+ -+ -+/* SBSDIO_DEVICE_CTL */ -+ -+/* 1: device will assert busy signal when receiving CMD53 */ -+#define SBSDIO_DEVCTL_SETBUSY 0x01 -+/* 1: assertion of sdio interrupt is synchronous to the sdio clock */ -+#define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02 -+/* 1: mask all interrupts to host except the chipActive (rev 8) */ -+#define SBSDIO_DEVCTL_CA_INT_ONLY 0x04 -+/* 1: isolate internal sdio signals, put external pads in tri-state; requires -+ * sdio bus power cycle to clear (rev 9) */ -+#define SBSDIO_DEVCTL_PADS_ISO 0x08 -+/* Force SD->SB reset mapping (rev 11) */ -+#define SBSDIO_DEVCTL_SB_RST_CTL 0x30 -+/* Determined by CoreControl bit */ -+#define SBSDIO_DEVCTL_RST_CORECTL 0x00 -+/* Force backplane reset */ -+#define SBSDIO_DEVCTL_RST_BPRESET 0x10 -+/* Force no backplane reset */ -+#define SBSDIO_DEVCTL_RST_NOBPRESET 0x20 -+ -+/* SBSDIO_FUNC1_CHIPCLKCSR */ -+ -+/* Force ALP request to backplane */ -+#define SBSDIO_FORCE_ALP 0x01 -+/* Force HT request to backplane */ -+#define SBSDIO_FORCE_HT 0x02 -+/* Force ILP request to backplane */ -+#define SBSDIO_FORCE_ILP 0x04 -+/* Make ALP ready (power up xtal) */ -+#define SBSDIO_ALP_AVAIL_REQ 0x08 -+/* Make HT ready (power up PLL) */ -+#define SBSDIO_HT_AVAIL_REQ 0x10 -+/* Squelch clock requests from HW */ -+#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20 -+/* Status: ALP is ready */ -+#define SBSDIO_ALP_AVAIL 0x40 -+/* Status: HT is ready */ -+#define SBSDIO_HT_AVAIL 0x80 -+ -+#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL) -+#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS) -+#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS) -+#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval)) -+ -+#define SBSDIO_CLKAV(regval, alponly) \ -+ (SBSDIO_ALPAV(regval) && (alponly ? 1 : SBSDIO_HTAV(regval))) -+ -+/* direct(mapped) cis space */ -+ -+/* MAPPED common CIS address */ -+#define SBSDIO_CIS_BASE_COMMON 0x1000 -+/* maximum bytes in one CIS */ -+#define SBSDIO_CIS_SIZE_LIMIT 0x200 -+/* cis offset addr is < 17 bits */ -+#define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF -+ -+/* manfid tuple length, include tuple, link bytes */ -+#define SBSDIO_CIS_MANFID_TUPLE_LEN 6 -+ -+/* intstatus */ -+#define I_SMB_SW0 (1 << 0) /* To SB Mail S/W interrupt 0 */ -+#define I_SMB_SW1 (1 << 1) /* To SB Mail S/W interrupt 1 */ -+#define I_SMB_SW2 (1 << 2) /* To SB Mail S/W interrupt 2 */ -+#define I_SMB_SW3 (1 << 3) /* To SB Mail S/W interrupt 3 */ -+#define I_SMB_SW_MASK 0x0000000f /* To SB Mail S/W interrupts mask */ -+#define I_SMB_SW_SHIFT 0 /* To SB Mail S/W interrupts shift */ -+#define I_HMB_SW0 (1 << 4) /* To Host Mail S/W interrupt 0 */ -+#define I_HMB_SW1 (1 << 5) /* To Host Mail S/W interrupt 1 */ -+#define I_HMB_SW2 (1 << 6) /* To Host Mail S/W interrupt 2 */ -+#define I_HMB_SW3 (1 << 7) /* To Host Mail S/W interrupt 3 */ -+#define I_HMB_SW_MASK 0x000000f0 /* To Host Mail S/W interrupts mask */ -+#define I_HMB_SW_SHIFT 4 /* To Host Mail S/W interrupts shift */ -+#define I_WR_OOSYNC (1 << 8) /* Write Frame Out Of Sync */ -+#define I_RD_OOSYNC (1 << 9) /* Read Frame Out Of Sync */ -+#define I_PC (1 << 10) /* descriptor error */ -+#define I_PD (1 << 11) /* data error */ -+#define I_DE (1 << 12) /* Descriptor protocol Error */ -+#define I_RU (1 << 13) /* Receive descriptor Underflow */ -+#define I_RO (1 << 14) /* Receive fifo Overflow */ -+#define I_XU (1 << 15) /* Transmit fifo Underflow */ -+#define I_RI (1 << 16) /* Receive Interrupt */ -+#define I_BUSPWR (1 << 17) /* SDIO Bus Power Change (rev 9) */ -+#define I_XMTDATA_AVAIL (1 << 23) /* bits in fifo */ -+#define I_XI (1 << 24) /* Transmit Interrupt */ -+#define I_RF_TERM (1 << 25) /* Read Frame Terminate */ -+#define I_WF_TERM (1 << 26) /* Write Frame Terminate */ -+#define I_PCMCIA_XU (1 << 27) /* PCMCIA Transmit FIFO Underflow */ -+#define I_SBINT (1 << 28) /* sbintstatus Interrupt */ -+#define I_CHIPACTIVE (1 << 29) /* chip from doze to active state */ -+#define I_SRESET (1 << 30) /* CCCR RES interrupt */ -+#define I_IOE2 (1U << 31) /* CCCR IOE2 Bit Changed */ -+#define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU) -+#define I_DMA (I_RI | I_XI | I_ERRORS) -+ -+/* corecontrol */ -+#define CC_CISRDY (1 << 0) /* CIS Ready */ -+#define CC_BPRESEN (1 << 1) /* CCCR RES signal */ -+#define CC_F2RDY (1 << 2) /* set CCCR IOR2 bit */ -+#define CC_CLRPADSISO (1 << 3) /* clear SDIO pads isolation */ -+#define CC_XMTDATAAVAIL_MODE (1 << 4) -+#define CC_XMTDATAAVAIL_CTRL (1 << 5) -+ -+/* SDA_FRAMECTRL */ -+#define SFC_RF_TERM (1 << 0) /* Read Frame Terminate */ -+#define SFC_WF_TERM (1 << 1) /* Write Frame Terminate */ -+#define SFC_CRC4WOOS (1 << 2) /* CRC error for write out of sync */ -+#define SFC_ABORTALL (1 << 3) /* Abort all in-progress frames */ -+ -+/* HW frame tag */ -+#define SDPCM_FRAMETAG_LEN 4 /* 2 bytes len, 2 bytes check val */ -+ -+/* Total length of frame header for dongle protocol */ -+#define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN) -+#define SDPCM_RESERVE (SDPCM_HDRLEN + BRCMF_SDALIGN) -+ -+/* -+ * Software allocation of To SB Mailbox resources -+ */ -+ -+/* tosbmailbox bits corresponding to intstatus bits */ -+#define SMB_NAK (1 << 0) /* Frame NAK */ -+#define SMB_INT_ACK (1 << 1) /* Host Interrupt ACK */ -+#define SMB_USE_OOB (1 << 2) /* Use OOB Wakeup */ -+#define SMB_DEV_INT (1 << 3) /* Miscellaneous Interrupt */ -+ -+/* tosbmailboxdata */ -+#define SMB_DATA_VERSION_SHIFT 16 /* host protocol version */ -+ -+/* -+ * Software allocation of To Host Mailbox resources -+ */ -+ -+/* intstatus bits */ -+#define I_HMB_FC_STATE I_HMB_SW0 /* Flow Control State */ -+#define I_HMB_FC_CHANGE I_HMB_SW1 /* Flow Control State Changed */ -+#define I_HMB_FRAME_IND I_HMB_SW2 /* Frame Indication */ -+#define I_HMB_HOST_INT I_HMB_SW3 /* Miscellaneous Interrupt */ -+ -+/* tohostmailboxdata */ -+#define HMB_DATA_NAKHANDLED 1 /* retransmit NAK'd frame */ -+#define HMB_DATA_DEVREADY 2 /* talk to host after enable */ -+#define HMB_DATA_FC 4 /* per prio flowcontrol update flag */ -+#define HMB_DATA_FWREADY 8 /* fw ready for protocol activity */ -+ -+#define HMB_DATA_FCDATA_MASK 0xff000000 -+#define HMB_DATA_FCDATA_SHIFT 24 -+ -+#define HMB_DATA_VERSION_MASK 0x00ff0000 -+#define HMB_DATA_VERSION_SHIFT 16 -+ -+/* -+ * Software-defined protocol header -+ */ -+ -+/* Current protocol version */ -+#define SDPCM_PROT_VERSION 4 -+ -+/* SW frame header */ -+#define SDPCM_PACKET_SEQUENCE(p) (((u8 *)p)[0] & 0xff) -+ -+#define SDPCM_CHANNEL_MASK 0x00000f00 -+#define SDPCM_CHANNEL_SHIFT 8 -+#define SDPCM_PACKET_CHANNEL(p) (((u8 *)p)[1] & 0x0f) -+ -+#define SDPCM_NEXTLEN_OFFSET 2 -+ -+/* Data Offset from SOF (HW Tag, SW Tag, Pad) */ -+#define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */ -+#define SDPCM_DOFFSET_VALUE(p) (((u8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff) -+#define SDPCM_DOFFSET_MASK 0xff000000 -+#define SDPCM_DOFFSET_SHIFT 24 -+#define SDPCM_FCMASK_OFFSET 4 /* Flow control */ -+#define SDPCM_FCMASK_VALUE(p) (((u8 *)p)[SDPCM_FCMASK_OFFSET] & 0xff) -+#define SDPCM_WINDOW_OFFSET 5 /* Credit based fc */ -+#define SDPCM_WINDOW_VALUE(p) (((u8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff) -+ -+#define SDPCM_SWHEADER_LEN 8 /* SW header is 64 bits */ -+ -+/* logical channel numbers */ -+#define SDPCM_CONTROL_CHANNEL 0 /* Control channel Id */ -+#define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication Channel Id */ -+#define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv Channel Id */ -+#define SDPCM_GLOM_CHANNEL 3 /* For coalesced packets */ -+#define SDPCM_TEST_CHANNEL 15 /* Reserved for test/debug packets */ -+ -+#define SDPCM_SEQUENCE_WRAP 256 /* wrap-around val for 8bit frame seq */ -+ -+#define SDPCM_GLOMDESC(p) (((u8 *)p)[1] & 0x80) -+ -+/* -+ * Shared structure between dongle and the host. -+ * The structure contains pointers to trap or assert information. -+ */ -+#define SDPCM_SHARED_VERSION 0x0002 -+#define SDPCM_SHARED_VERSION_MASK 0x00FF -+#define SDPCM_SHARED_ASSERT_BUILT 0x0100 -+#define SDPCM_SHARED_ASSERT 0x0200 -+#define SDPCM_SHARED_TRAP 0x0400 -+ -+/* Space for header read, limit for data packets */ -+#define MAX_HDR_READ (1 << 6) -+#define MAX_RX_DATASZ 2048 -+ -+/* Maximum milliseconds to wait for F2 to come up */ -+#define BRCMF_WAIT_F2RDY 3000 -+ -+/* Bump up limit on waiting for HT to account for first startup; -+ * if the image is doing a CRC calculation before programming the PMU -+ * for HT availability, it could take a couple hundred ms more, so -+ * max out at a 1 second (1000000us). -+ */ -+#undef PMU_MAX_TRANSITION_DLY -+#define PMU_MAX_TRANSITION_DLY 1000000 -+ -+/* Value for ChipClockCSR during initial setup */ -+#define BRCMF_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | \ -+ SBSDIO_ALP_AVAIL_REQ) -+ -+/* Flags for SDH calls */ -+#define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED) -+ -+/* sbimstate */ -+#define SBIM_IBE 0x20000 /* inbanderror */ -+#define SBIM_TO 0x40000 /* timeout */ -+#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */ -+#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */ -+ -+/* sbtmstatelow */ -+ -+/* reset */ -+#define SBTML_RESET 0x0001 -+/* reject field */ -+#define SBTML_REJ_MASK 0x0006 -+/* reject */ -+#define SBTML_REJ 0x0002 -+/* temporary reject, for error recovery */ -+#define SBTML_TMPREJ 0x0004 -+ -+/* Shift to locate the SI control flags in sbtml */ -+#define SBTML_SICF_SHIFT 16 -+ -+/* sbtmstatehigh */ -+#define SBTMH_SERR 0x0001 /* serror */ -+#define SBTMH_INT 0x0002 /* interrupt */ -+#define SBTMH_BUSY 0x0004 /* busy */ -+#define SBTMH_TO 0x0020 /* timeout (sonics >= 2.3) */ -+ -+/* Shift to locate the SI status flags in sbtmh */ -+#define SBTMH_SISF_SHIFT 16 -+ -+/* sbidlow */ -+#define SBIDL_INIT 0x80 /* initiator */ -+ -+/* sbidhigh */ -+#define SBIDH_RC_MASK 0x000f /* revision code */ -+#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */ -+#define SBIDH_RCE_SHIFT 8 -+#define SBCOREREV(sbidh) \ -+ ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | \ -+ ((sbidh) & SBIDH_RC_MASK)) -+#define SBIDH_CC_MASK 0x8ff0 /* core code */ -+#define SBIDH_CC_SHIFT 4 -+#define SBIDH_VC_MASK 0xffff0000 /* vendor code */ -+#define SBIDH_VC_SHIFT 16 -+ -+/* -+ * Conversion of 802.1D priority to precedence level -+ */ -+static uint prio2prec(u32 prio) -+{ -+ return (prio == PRIO_8021D_NONE || prio == PRIO_8021D_BE) ? -+ (prio^2) : prio; -+} -+ -+/* -+ * Core reg address translation. -+ * Both macro's returns a 32 bits byte address on the backplane bus. -+ */ -+#define CORE_CC_REG(base, field) \ -+ (base + offsetof(struct chipcregs, field)) -+#define CORE_BUS_REG(base, field) \ -+ (base + offsetof(struct sdpcmd_regs, field)) -+#define CORE_SB(base, field) \ -+ (base + SBCONFIGOFF + offsetof(struct sbconfig, field)) -+ -+/* core registers */ -+struct sdpcmd_regs { -+ u32 corecontrol; /* 0x00, rev8 */ -+ u32 corestatus; /* rev8 */ -+ u32 PAD[1]; -+ u32 biststatus; /* rev8 */ -+ -+ /* PCMCIA access */ -+ u16 pcmciamesportaladdr; /* 0x010, rev8 */ -+ u16 PAD[1]; -+ u16 pcmciamesportalmask; /* rev8 */ -+ u16 PAD[1]; -+ u16 pcmciawrframebc; /* rev8 */ -+ u16 PAD[1]; -+ u16 pcmciaunderflowtimer; /* rev8 */ -+ u16 PAD[1]; -+ -+ /* interrupt */ -+ u32 intstatus; /* 0x020, rev8 */ -+ u32 hostintmask; /* rev8 */ -+ u32 intmask; /* rev8 */ -+ u32 sbintstatus; /* rev8 */ -+ u32 sbintmask; /* rev8 */ -+ u32 funcintmask; /* rev4 */ -+ u32 PAD[2]; -+ u32 tosbmailbox; /* 0x040, rev8 */ -+ u32 tohostmailbox; /* rev8 */ -+ u32 tosbmailboxdata; /* rev8 */ -+ u32 tohostmailboxdata; /* rev8 */ -+ -+ /* synchronized access to registers in SDIO clock domain */ -+ u32 sdioaccess; /* 0x050, rev8 */ -+ u32 PAD[3]; -+ -+ /* PCMCIA frame control */ -+ u8 pcmciaframectrl; /* 0x060, rev8 */ -+ u8 PAD[3]; -+ u8 pcmciawatermark; /* rev8 */ -+ u8 PAD[155]; -+ -+ /* interrupt batching control */ -+ u32 intrcvlazy; /* 0x100, rev8 */ -+ u32 PAD[3]; -+ -+ /* counters */ -+ u32 cmd52rd; /* 0x110, rev8 */ -+ u32 cmd52wr; /* rev8 */ -+ u32 cmd53rd; /* rev8 */ -+ u32 cmd53wr; /* rev8 */ -+ u32 abort; /* rev8 */ -+ u32 datacrcerror; /* rev8 */ -+ u32 rdoutofsync; /* rev8 */ -+ u32 wroutofsync; /* rev8 */ -+ u32 writebusy; /* rev8 */ -+ u32 readwait; /* rev8 */ -+ u32 readterm; /* rev8 */ -+ u32 writeterm; /* rev8 */ -+ u32 PAD[40]; -+ u32 clockctlstatus; /* rev8 */ -+ u32 PAD[7]; -+ -+ u32 PAD[128]; /* DMA engines */ -+ -+ /* SDIO/PCMCIA CIS region */ -+ char cis[512]; /* 0x400-0x5ff, rev6 */ -+ -+ /* PCMCIA function control registers */ -+ char pcmciafcr[256]; /* 0x600-6ff, rev6 */ -+ u16 PAD[55]; -+ -+ /* PCMCIA backplane access */ -+ u16 backplanecsr; /* 0x76E, rev6 */ -+ u16 backplaneaddr0; /* rev6 */ -+ u16 backplaneaddr1; /* rev6 */ -+ u16 backplaneaddr2; /* rev6 */ -+ u16 backplaneaddr3; /* rev6 */ -+ u16 backplanedata0; /* rev6 */ -+ u16 backplanedata1; /* rev6 */ -+ u16 backplanedata2; /* rev6 */ -+ u16 backplanedata3; /* rev6 */ -+ u16 PAD[31]; -+ -+ /* sprom "size" & "blank" info */ -+ u16 spromstatus; /* 0x7BE, rev2 */ -+ u32 PAD[464]; -+ -+ u16 PAD[0x80]; -+}; -+ -+#ifdef BCMDBG -+/* Device console log buffer state */ -+struct brcmf_console { -+ uint count; /* Poll interval msec counter */ -+ uint log_addr; /* Log struct address (fixed) */ -+ struct rte_log_le log_le; /* Log struct (host copy) */ -+ uint bufsize; /* Size of log buffer */ -+ u8 *buf; /* Log buffer (host copy) */ -+ uint last; /* Last buffer read index */ -+}; -+#endif /* BCMDBG */ -+ -+struct sdpcm_shared { -+ u32 flags; -+ u32 trap_addr; -+ u32 assert_exp_addr; -+ u32 assert_file_addr; -+ u32 assert_line; -+ u32 console_addr; /* Address of struct rte_console */ -+ u32 msgtrace_addr; -+ u8 tag[32]; -+}; -+ -+struct sdpcm_shared_le { -+ __le32 flags; -+ __le32 trap_addr; -+ __le32 assert_exp_addr; -+ __le32 assert_file_addr; -+ __le32 assert_line; -+ __le32 console_addr; /* Address of struct rte_console */ -+ __le32 msgtrace_addr; -+ u8 tag[32]; -+}; -+ -+ -+/* misc chip info needed by some of the routines */ -+struct chip_info { -+ u32 chip; -+ u32 chiprev; -+ u32 cccorebase; -+ u32 ccrev; -+ u32 cccaps; -+ u32 buscorebase; /* 32 bits backplane bus address */ -+ u32 buscorerev; -+ u32 buscoretype; -+ u32 ramcorebase; -+ u32 armcorebase; -+ u32 pmurev; -+ u32 ramsize; -+}; -+ -+/* Private data for SDIO bus interaction */ -+struct brcmf_bus { -+ struct brcmf_pub *drvr; -+ -+ struct brcmf_sdio_dev *sdiodev; /* sdio device handler */ -+ struct chip_info *ci; /* Chip info struct */ -+ char *vars; /* Variables (from CIS and/or other) */ -+ uint varsz; /* Size of variables buffer */ -+ -+ u32 ramsize; /* Size of RAM in SOCRAM (bytes) */ -+ -+ u32 hostintmask; /* Copy of Host Interrupt Mask */ -+ u32 intstatus; /* Intstatus bits (events) pending */ -+ bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */ -+ bool fcstate; /* State of dongle flow-control */ -+ -+ uint blocksize; /* Block size of SDIO transfers */ -+ uint roundup; /* Max roundup limit */ -+ -+ struct pktq txq; /* Queue length used for flow-control */ -+ u8 flowcontrol; /* per prio flow control bitmask */ -+ u8 tx_seq; /* Transmit sequence number (next) */ -+ u8 tx_max; /* Maximum transmit sequence allowed */ -+ -+ u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN]; -+ u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ -+ u16 nextlen; /* Next Read Len from last header */ -+ u8 rx_seq; /* Receive sequence number (expected) */ -+ bool rxskip; /* Skip receive (awaiting NAK ACK) */ -+ -+ uint rxbound; /* Rx frames to read before resched */ -+ uint txbound; /* Tx frames to send before resched */ -+ uint txminmax; -+ -+ struct sk_buff *glomd; /* Packet containing glomming descriptor */ -+ struct sk_buff *glom; /* Packet chain for glommed superframe */ -+ uint glomerr; /* Glom packet read errors */ -+ -+ u8 *rxbuf; /* Buffer for receiving control packets */ -+ uint rxblen; /* Allocated length of rxbuf */ -+ u8 *rxctl; /* Aligned pointer into rxbuf */ -+ u8 *databuf; /* Buffer for receiving big glom packet */ -+ u8 *dataptr; /* Aligned pointer into databuf */ -+ uint rxlen; /* Length of valid data in buffer */ -+ -+ u8 sdpcm_ver; /* Bus protocol reported by dongle */ -+ -+ bool intr; /* Use interrupts */ -+ bool poll; /* Use polling */ -+ bool ipend; /* Device interrupt is pending */ -+ uint intrcount; /* Count of device interrupt callbacks */ -+ uint lastintrs; /* Count as of last watchdog timer */ -+ uint spurious; /* Count of spurious interrupts */ -+ uint pollrate; /* Ticks between device polls */ -+ uint polltick; /* Tick counter */ -+ uint pollcnt; /* Count of active polls */ -+ -+#ifdef BCMDBG -+ uint console_interval; -+ struct brcmf_console console; /* Console output polling support */ -+ uint console_addr; /* Console address from shared struct */ -+#endif /* BCMDBG */ -+ -+ uint regfails; /* Count of R_REG failures */ -+ -+ uint clkstate; /* State of sd and backplane clock(s) */ -+ bool activity; /* Activity flag for clock down */ -+ s32 idletime; /* Control for activity timeout */ -+ s32 idlecount; /* Activity timeout counter */ -+ s32 idleclock; /* How to set bus driver when idle */ -+ s32 sd_rxchain; -+ bool use_rxchain; /* If brcmf should use PKT chains */ -+ bool sleeping; /* Is SDIO bus sleeping? */ -+ bool rxflow_mode; /* Rx flow control mode */ -+ bool rxflow; /* Is rx flow control on */ -+ bool alp_only; /* Don't use HT clock (ALP only) */ -+/* Field to decide if rx of control frames happen in rxbuf or lb-pool */ -+ bool usebufpool; -+ -+ /* Some additional counters */ -+ uint tx_sderrs; /* Count of tx attempts with sd errors */ -+ uint fcqueued; /* Tx packets that got queued */ -+ uint rxrtx; /* Count of rtx requests (NAK to dongle) */ -+ uint rx_toolong; /* Receive frames too long to receive */ -+ uint rxc_errors; /* SDIO errors when reading control frames */ -+ uint rx_hdrfail; /* SDIO errors on header reads */ -+ uint rx_badhdr; /* Bad received headers (roosync?) */ -+ uint rx_badseq; /* Mismatched rx sequence number */ -+ uint fc_rcvd; /* Number of flow-control events received */ -+ uint fc_xoff; /* Number which turned on flow-control */ -+ uint fc_xon; /* Number which turned off flow-control */ -+ uint rxglomfail; /* Failed deglom attempts */ -+ uint rxglomframes; /* Number of glom frames (superframes) */ -+ uint rxglompkts; /* Number of packets from glom frames */ -+ uint f2rxhdrs; /* Number of header reads */ -+ uint f2rxdata; /* Number of frame data reads */ -+ uint f2txdata; /* Number of f2 frame writes */ -+ uint f1regdata; /* Number of f1 register accesses */ -+ -+ u8 *ctrl_frame_buf; -+ u32 ctrl_frame_len; -+ bool ctrl_frame_stat; -+ -+ spinlock_t txqlock; -+ wait_queue_head_t ctrl_wait; -+ wait_queue_head_t dcmd_resp_wait; -+ -+ struct timer_list timer; -+ struct completion watchdog_wait; -+ struct task_struct *watchdog_tsk; -+ bool wd_timer_valid; -+ uint save_ms; -+ -+ struct task_struct *dpc_tsk; -+ struct completion dpc_wait; -+ -+ struct semaphore sdsem; -+ -+ const char *fw_name; -+ const struct firmware *firmware; -+ const char *nv_name; -+ u32 fw_ptr; -+}; -+ -+struct sbconfig { -+ u32 PAD[2]; -+ u32 sbipsflag; /* initiator port ocp slave flag */ -+ u32 PAD[3]; -+ u32 sbtpsflag; /* target port ocp slave flag */ -+ u32 PAD[11]; -+ u32 sbtmerrloga; /* (sonics >= 2.3) */ -+ u32 PAD; -+ u32 sbtmerrlog; /* (sonics >= 2.3) */ -+ u32 PAD[3]; -+ u32 sbadmatch3; /* address match3 */ -+ u32 PAD; -+ u32 sbadmatch2; /* address match2 */ -+ u32 PAD; -+ u32 sbadmatch1; /* address match1 */ -+ u32 PAD[7]; -+ u32 sbimstate; /* initiator agent state */ -+ u32 sbintvec; /* interrupt mask */ -+ u32 sbtmstatelow; /* target state */ -+ u32 sbtmstatehigh; /* target state */ -+ u32 sbbwa0; /* bandwidth allocation table0 */ -+ u32 PAD; -+ u32 sbimconfiglow; /* initiator configuration */ -+ u32 sbimconfighigh; /* initiator configuration */ -+ u32 sbadmatch0; /* address match0 */ -+ u32 PAD; -+ u32 sbtmconfiglow; /* target configuration */ -+ u32 sbtmconfighigh; /* target configuration */ -+ u32 sbbconfig; /* broadcast configuration */ -+ u32 PAD; -+ u32 sbbstate; /* broadcast state */ -+ u32 PAD[3]; -+ u32 sbactcnfg; /* activate configuration */ -+ u32 PAD[3]; -+ u32 sbflagst; /* current sbflags */ -+ u32 PAD[3]; -+ u32 sbidlow; /* identification */ -+ u32 sbidhigh; /* identification */ -+}; -+ -+/* clkstate */ -+#define CLK_NONE 0 -+#define CLK_SDONLY 1 -+#define CLK_PENDING 2 /* Not used yet */ -+#define CLK_AVAIL 3 -+ -+#ifdef BCMDBG -+static int qcount[NUMPRIO]; -+static int tx_packets[NUMPRIO]; -+#endif /* BCMDBG */ -+ -+#define SDIO_DRIVE_STRENGTH 6 /* in milliamps */ -+ -+#define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL) -+ -+/* Retry count for register access failures */ -+static const uint retry_limit = 2; -+ -+/* Limit on rounding up frames */ -+static const uint max_roundup = 512; -+ -+#define ALIGNMENT 4 -+ -+static void pkt_align(struct sk_buff *p, int len, int align) -+{ -+ uint datalign; -+ datalign = (unsigned long)(p->data); -+ datalign = roundup(datalign, (align)) - datalign; -+ if (datalign) -+ skb_pull(p, datalign); -+ __skb_trim(p, len); -+} -+ -+/* To check if there's window offered */ -+static bool data_ok(struct brcmf_bus *bus) -+{ -+ return (u8)(bus->tx_max - bus->tx_seq) != 0 && -+ ((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0; -+} -+ -+/* -+ * Reads a register in the SDIO hardware block. This block occupies a series of -+ * adresses on the 32 bit backplane bus. -+ */ -+static void -+r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar) -+{ -+ *retryvar = 0; -+ do { -+ *regvar = brcmf_sdcard_reg_read(bus->sdiodev, -+ bus->ci->buscorebase + reg_offset, sizeof(u32)); -+ } while (brcmf_sdcard_regfail(bus->sdiodev) && -+ (++(*retryvar) <= retry_limit)); -+ if (*retryvar) { -+ bus->regfails += (*retryvar-1); -+ if (*retryvar > retry_limit) { -+ brcmf_dbg(ERROR, "FAILED READ %Xh\n", reg_offset); -+ *regvar = 0; -+ } -+ } -+} -+ -+static void -+w_sdreg32(struct brcmf_bus *bus, u32 regval, u32 reg_offset, u32 *retryvar) -+{ -+ *retryvar = 0; -+ do { -+ brcmf_sdcard_reg_write(bus->sdiodev, -+ bus->ci->buscorebase + reg_offset, -+ sizeof(u32), regval); -+ } while (brcmf_sdcard_regfail(bus->sdiodev) && -+ (++(*retryvar) <= retry_limit)); -+ if (*retryvar) { -+ bus->regfails += (*retryvar-1); -+ if (*retryvar > retry_limit) -+ brcmf_dbg(ERROR, "FAILED REGISTER WRITE %Xh\n", -+ reg_offset); -+ } -+} -+ -+#define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND) -+ -+#define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) -+ -+/* Packet free applicable unconditionally for sdio and sdspi. -+ * Conditional if bufpool was present for gspi bus. -+ */ -+static void brcmf_sdbrcm_pktfree2(struct brcmf_bus *bus, struct sk_buff *pkt) -+{ -+ if (bus->usebufpool) -+ brcmu_pkt_buf_free_skb(pkt); -+} -+ -+/* Turn backplane clock on or off */ -+static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok) -+{ -+ int err; -+ u8 clkctl, clkreq, devctl; -+ unsigned long timeout; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ clkctl = 0; -+ -+ if (on) { -+ /* Request HT Avail */ -+ clkreq = -+ bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; -+ -+ if ((bus->ci->chip == BCM4329_CHIP_ID) -+ && (bus->ci->chiprev == 0)) -+ clkreq |= SBSDIO_FORCE_ALP; -+ -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); -+ if (err) { -+ brcmf_dbg(ERROR, "HT Avail request error: %d\n", err); -+ return -EBADE; -+ } -+ -+ if (pendok && ((bus->ci->buscoretype == PCMCIA_CORE_ID) -+ && (bus->ci->buscorerev == 9))) { -+ u32 dummy, retries; -+ r_sdreg32(bus, &dummy, -+ offsetof(struct sdpcmd_regs, clockctlstatus), -+ &retries); -+ } -+ -+ /* Check current status */ -+ clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, &err); -+ if (err) { -+ brcmf_dbg(ERROR, "HT Avail read error: %d\n", err); -+ return -EBADE; -+ } -+ -+ /* Go to pending and await interrupt if appropriate */ -+ if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { -+ /* Allow only clock-available interrupt */ -+ devctl = brcmf_sdcard_cfg_read(bus->sdiodev, -+ SDIO_FUNC_1, -+ SBSDIO_DEVICE_CTL, &err); -+ if (err) { -+ brcmf_dbg(ERROR, "Devctl error setting CA: %d\n", -+ err); -+ return -EBADE; -+ } -+ -+ devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_DEVICE_CTL, devctl, &err); -+ brcmf_dbg(INFO, "CLKCTL: set PENDING\n"); -+ bus->clkstate = CLK_PENDING; -+ -+ return 0; -+ } else if (bus->clkstate == CLK_PENDING) { -+ /* Cancel CA-only interrupt filter */ -+ devctl = -+ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_DEVICE_CTL, &err); -+ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_DEVICE_CTL, devctl, &err); -+ } -+ -+ /* Otherwise, wait here (polling) for HT Avail */ -+ timeout = jiffies + -+ msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000); -+ while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { -+ clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, -+ SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, -+ &err); -+ if (time_after(jiffies, timeout)) -+ break; -+ else -+ usleep_range(5000, 10000); -+ } -+ if (err) { -+ brcmf_dbg(ERROR, "HT Avail request error: %d\n", err); -+ return -EBADE; -+ } -+ if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { -+ brcmf_dbg(ERROR, "HT Avail timeout (%d): clkctl 0x%02x\n", -+ PMU_MAX_TRANSITION_DLY, clkctl); -+ return -EBADE; -+ } -+ -+ /* Mark clock available */ -+ bus->clkstate = CLK_AVAIL; -+ brcmf_dbg(INFO, "CLKCTL: turned ON\n"); -+ -+#if defined(BCMDBG) -+ if (bus->alp_only != true) { -+ if (SBSDIO_ALPONLY(clkctl)) -+ brcmf_dbg(ERROR, "HT Clock should be on\n"); -+ } -+#endif /* defined (BCMDBG) */ -+ -+ bus->activity = true; -+ } else { -+ clkreq = 0; -+ -+ if (bus->clkstate == CLK_PENDING) { -+ /* Cancel CA-only interrupt filter */ -+ devctl = brcmf_sdcard_cfg_read(bus->sdiodev, -+ SDIO_FUNC_1, -+ SBSDIO_DEVICE_CTL, &err); -+ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_DEVICE_CTL, devctl, &err); -+ } -+ -+ bus->clkstate = CLK_SDONLY; -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); -+ brcmf_dbg(INFO, "CLKCTL: turned OFF\n"); -+ if (err) { -+ brcmf_dbg(ERROR, "Failed access turning clock off: %d\n", -+ err); -+ return -EBADE; -+ } -+ } -+ return 0; -+} -+ -+/* Change idle/active SD state */ -+static int brcmf_sdbrcm_sdclk(struct brcmf_bus *bus, bool on) -+{ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ if (on) -+ bus->clkstate = CLK_SDONLY; -+ else -+ bus->clkstate = CLK_NONE; -+ -+ return 0; -+} -+ -+/* Transition SD and backplane clock readiness */ -+static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok) -+{ -+#ifdef BCMDBG -+ uint oldstate = bus->clkstate; -+#endif /* BCMDBG */ -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* Early exit if we're already there */ -+ if (bus->clkstate == target) { -+ if (target == CLK_AVAIL) { -+ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); -+ bus->activity = true; -+ } -+ return 0; -+ } -+ -+ switch (target) { -+ case CLK_AVAIL: -+ /* Make sure SD clock is available */ -+ if (bus->clkstate == CLK_NONE) -+ brcmf_sdbrcm_sdclk(bus, true); -+ /* Now request HT Avail on the backplane */ -+ brcmf_sdbrcm_htclk(bus, true, pendok); -+ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); -+ bus->activity = true; -+ break; -+ -+ case CLK_SDONLY: -+ /* Remove HT request, or bring up SD clock */ -+ if (bus->clkstate == CLK_NONE) -+ brcmf_sdbrcm_sdclk(bus, true); -+ else if (bus->clkstate == CLK_AVAIL) -+ brcmf_sdbrcm_htclk(bus, false, false); -+ else -+ brcmf_dbg(ERROR, "request for %d -> %d\n", -+ bus->clkstate, target); -+ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); -+ break; -+ -+ case CLK_NONE: -+ /* Make sure to remove HT request */ -+ if (bus->clkstate == CLK_AVAIL) -+ brcmf_sdbrcm_htclk(bus, false, false); -+ /* Now remove the SD clock */ -+ brcmf_sdbrcm_sdclk(bus, false); -+ brcmf_sdbrcm_wd_timer(bus, 0); -+ break; -+ } -+#ifdef BCMDBG -+ brcmf_dbg(INFO, "%d -> %d\n", oldstate, bus->clkstate); -+#endif /* BCMDBG */ -+ -+ return 0; -+} -+ -+static int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep) -+{ -+ uint retries = 0; -+ -+ brcmf_dbg(INFO, "request %s (currently %s)\n", -+ sleep ? "SLEEP" : "WAKE", -+ bus->sleeping ? "SLEEP" : "WAKE"); -+ -+ /* Done if we're already in the requested state */ -+ if (sleep == bus->sleeping) -+ return 0; -+ -+ /* Going to sleep: set the alarm and turn off the lights... */ -+ if (sleep) { -+ /* Don't sleep if something is pending */ -+ if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq)) -+ return -EBUSY; -+ -+ /* Make sure the controller has the bus up */ -+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); -+ -+ /* Tell device to start using OOB wakeup */ -+ w_sdreg32(bus, SMB_USE_OOB, -+ offsetof(struct sdpcmd_regs, tosbmailbox), &retries); -+ if (retries > retry_limit) -+ brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"); -+ -+ /* Turn off our contribution to the HT clock request */ -+ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); -+ -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, -+ SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); -+ -+ /* Isolate the bus */ -+ if (bus->ci->chip != BCM4329_CHIP_ID) { -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_DEVICE_CTL, -+ SBSDIO_DEVCTL_PADS_ISO, NULL); -+ } -+ -+ /* Change state */ -+ bus->sleeping = true; -+ -+ } else { -+ /* Waking up: bus power up is ok, set local state */ -+ -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); -+ -+ /* Force pad isolation off if possible -+ (in case power never toggled) */ -+ if ((bus->ci->buscoretype == PCMCIA_CORE_ID) -+ && (bus->ci->buscorerev >= 10)) -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_DEVICE_CTL, 0, NULL); -+ -+ /* Make sure the controller has the bus up */ -+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); -+ -+ /* Send misc interrupt to indicate OOB not needed */ -+ w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, tosbmailboxdata), -+ &retries); -+ if (retries <= retry_limit) -+ w_sdreg32(bus, SMB_DEV_INT, -+ offsetof(struct sdpcmd_regs, tosbmailbox), -+ &retries); -+ -+ if (retries > retry_limit) -+ brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"); -+ -+ /* Make sure we have SD bus access */ -+ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); -+ -+ /* Change state */ -+ bus->sleeping = false; -+ } -+ -+ return 0; -+} -+ -+static void bus_wake(struct brcmf_bus *bus) -+{ -+ if (bus->sleeping) -+ brcmf_sdbrcm_bussleep(bus, false); -+} -+ -+static u32 brcmf_sdbrcm_hostmail(struct brcmf_bus *bus) -+{ -+ u32 intstatus = 0; -+ u32 hmb_data; -+ u8 fcbits; -+ uint retries = 0; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* Read mailbox data and ack that we did so */ -+ r_sdreg32(bus, &hmb_data, -+ offsetof(struct sdpcmd_regs, tohostmailboxdata), &retries); -+ -+ if (retries <= retry_limit) -+ w_sdreg32(bus, SMB_INT_ACK, -+ offsetof(struct sdpcmd_regs, tosbmailbox), &retries); -+ bus->f1regdata += 2; -+ -+ /* Dongle recomposed rx frames, accept them again */ -+ if (hmb_data & HMB_DATA_NAKHANDLED) { -+ brcmf_dbg(INFO, "Dongle reports NAK handled, expect rtx of %d\n", -+ bus->rx_seq); -+ if (!bus->rxskip) -+ brcmf_dbg(ERROR, "unexpected NAKHANDLED!\n"); -+ -+ bus->rxskip = false; -+ intstatus |= I_HMB_FRAME_IND; -+ } -+ -+ /* -+ * DEVREADY does not occur with gSPI. -+ */ -+ if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) { -+ bus->sdpcm_ver = -+ (hmb_data & HMB_DATA_VERSION_MASK) >> -+ HMB_DATA_VERSION_SHIFT; -+ if (bus->sdpcm_ver != SDPCM_PROT_VERSION) -+ brcmf_dbg(ERROR, "Version mismatch, dongle reports %d, " -+ "expecting %d\n", -+ bus->sdpcm_ver, SDPCM_PROT_VERSION); -+ else -+ brcmf_dbg(INFO, "Dongle ready, protocol version %d\n", -+ bus->sdpcm_ver); -+ } -+ -+ /* -+ * Flow Control has been moved into the RX headers and this out of band -+ * method isn't used any more. -+ * remaining backward compatible with older dongles. -+ */ -+ if (hmb_data & HMB_DATA_FC) { -+ fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >> -+ HMB_DATA_FCDATA_SHIFT; -+ -+ if (fcbits & ~bus->flowcontrol) -+ bus->fc_xoff++; -+ -+ if (bus->flowcontrol & ~fcbits) -+ bus->fc_xon++; -+ -+ bus->fc_rcvd++; -+ bus->flowcontrol = fcbits; -+ } -+ -+ /* Shouldn't be any others */ -+ if (hmb_data & ~(HMB_DATA_DEVREADY | -+ HMB_DATA_NAKHANDLED | -+ HMB_DATA_FC | -+ HMB_DATA_FWREADY | -+ HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK)) -+ brcmf_dbg(ERROR, "Unknown mailbox data content: 0x%02x\n", -+ hmb_data); -+ -+ return intstatus; -+} -+ -+static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx) -+{ -+ uint retries = 0; -+ u16 lastrbc; -+ u8 hi, lo; -+ int err; -+ -+ brcmf_dbg(ERROR, "%sterminate frame%s\n", -+ abort ? "abort command, " : "", -+ rtx ? ", send NAK" : ""); -+ -+ if (abort) -+ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); -+ -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_FRAMECTRL, -+ SFC_RF_TERM, &err); -+ bus->f1regdata++; -+ -+ /* Wait until the packet has been flushed (device/FIFO stable) */ -+ for (lastrbc = retries = 0xffff; retries > 0; retries--) { -+ hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_RFRAMEBCHI, NULL); -+ lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_RFRAMEBCLO, NULL); -+ bus->f1regdata += 2; -+ -+ if ((hi == 0) && (lo == 0)) -+ break; -+ -+ if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) { -+ brcmf_dbg(ERROR, "count growing: last 0x%04x now 0x%04x\n", -+ lastrbc, (hi << 8) + lo); -+ } -+ lastrbc = (hi << 8) + lo; -+ } -+ -+ if (!retries) -+ brcmf_dbg(ERROR, "count never zeroed: last 0x%04x\n", lastrbc); -+ else -+ brcmf_dbg(INFO, "flush took %d iterations\n", 0xffff - retries); -+ -+ if (rtx) { -+ bus->rxrtx++; -+ w_sdreg32(bus, SMB_NAK, -+ offsetof(struct sdpcmd_regs, tosbmailbox), &retries); -+ -+ bus->f1regdata++; -+ if (retries <= retry_limit) -+ bus->rxskip = true; -+ } -+ -+ /* Clear partial in any case */ -+ bus->nextlen = 0; -+ -+ /* If we can't reach the device, signal failure */ -+ if (err || brcmf_sdcard_regfail(bus->sdiodev)) -+ bus->drvr->busstate = BRCMF_BUS_DOWN; -+} -+ -+static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq) -+{ -+ u16 dlen, totlen; -+ u8 *dptr, num = 0; -+ -+ u16 sublen, check; -+ struct sk_buff *pfirst, *plast, *pnext, *save_pfirst; -+ -+ int errcode; -+ u8 chan, seq, doff, sfdoff; -+ u8 txmax; -+ -+ int ifidx = 0; -+ bool usechain = bus->use_rxchain; -+ -+ /* If packets, issue read(s) and send up packet chain */ -+ /* Return sequence numbers consumed? */ -+ -+ brcmf_dbg(TRACE, "start: glomd %p glom %p\n", bus->glomd, bus->glom); -+ -+ /* If there's a descriptor, generate the packet chain */ -+ if (bus->glomd) { -+ pfirst = plast = pnext = NULL; -+ dlen = (u16) (bus->glomd->len); -+ dptr = bus->glomd->data; -+ if (!dlen || (dlen & 1)) { -+ brcmf_dbg(ERROR, "bad glomd len(%d), ignore descriptor\n", -+ dlen); -+ dlen = 0; -+ } -+ -+ for (totlen = num = 0; dlen; num++) { -+ /* Get (and move past) next length */ -+ sublen = get_unaligned_le16(dptr); -+ dlen -= sizeof(u16); -+ dptr += sizeof(u16); -+ if ((sublen < SDPCM_HDRLEN) || -+ ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) { -+ brcmf_dbg(ERROR, "descriptor len %d bad: %d\n", -+ num, sublen); -+ pnext = NULL; -+ break; -+ } -+ if (sublen % BRCMF_SDALIGN) { -+ brcmf_dbg(ERROR, "sublen %d not multiple of %d\n", -+ sublen, BRCMF_SDALIGN); -+ usechain = false; -+ } -+ totlen += sublen; -+ -+ /* For last frame, adjust read len so total -+ is a block multiple */ -+ if (!dlen) { -+ sublen += -+ (roundup(totlen, bus->blocksize) - totlen); -+ totlen = roundup(totlen, bus->blocksize); -+ } -+ -+ /* Allocate/chain packet for next subframe */ -+ pnext = brcmu_pkt_buf_get_skb(sublen + BRCMF_SDALIGN); -+ if (pnext == NULL) { -+ brcmf_dbg(ERROR, "bcm_pkt_buf_get_skb failed, num %d len %d\n", -+ num, sublen); -+ break; -+ } -+ if (!pfirst) { -+ pfirst = plast = pnext; -+ } else { -+ plast->next = pnext; -+ plast = pnext; -+ } -+ -+ /* Adhere to start alignment requirements */ -+ pkt_align(pnext, sublen, BRCMF_SDALIGN); -+ } -+ -+ /* If all allocations succeeded, save packet chain -+ in bus structure */ -+ if (pnext) { -+ brcmf_dbg(GLOM, "allocated %d-byte packet chain for %d subframes\n", -+ totlen, num); -+ if (BRCMF_GLOM_ON() && bus->nextlen && -+ totlen != bus->nextlen) { -+ brcmf_dbg(GLOM, "glomdesc mismatch: nextlen %d glomdesc %d rxseq %d\n", -+ bus->nextlen, totlen, rxseq); -+ } -+ bus->glom = pfirst; -+ pfirst = pnext = NULL; -+ } else { -+ if (pfirst) -+ brcmu_pkt_buf_free_skb(pfirst); -+ bus->glom = NULL; -+ num = 0; -+ } -+ -+ /* Done with descriptor packet */ -+ brcmu_pkt_buf_free_skb(bus->glomd); -+ bus->glomd = NULL; -+ bus->nextlen = 0; -+ } -+ -+ /* Ok -- either we just generated a packet chain, -+ or had one from before */ -+ if (bus->glom) { -+ if (BRCMF_GLOM_ON()) { -+ brcmf_dbg(GLOM, "try superframe read, packet chain:\n"); -+ for (pnext = bus->glom; pnext; pnext = pnext->next) { -+ brcmf_dbg(GLOM, " %p: %p len 0x%04x (%d)\n", -+ pnext, (u8 *) (pnext->data), -+ pnext->len, pnext->len); -+ } -+ } -+ -+ pfirst = bus->glom; -+ dlen = (u16) brcmu_pkttotlen(pfirst); -+ -+ /* Do an SDIO read for the superframe. Configurable iovar to -+ * read directly into the chained packet, or allocate a large -+ * packet and and copy into the chain. -+ */ -+ if (usechain) { -+ errcode = brcmf_sdcard_recv_buf(bus->sdiodev, -+ bus->sdiodev->sbwad, -+ SDIO_FUNC_2, -+ F2SYNC, (u8 *) pfirst->data, dlen, -+ pfirst); -+ } else if (bus->dataptr) { -+ errcode = brcmf_sdcard_recv_buf(bus->sdiodev, -+ bus->sdiodev->sbwad, -+ SDIO_FUNC_2, -+ F2SYNC, bus->dataptr, dlen, -+ NULL); -+ sublen = (u16) brcmu_pktfrombuf(pfirst, 0, dlen, -+ bus->dataptr); -+ if (sublen != dlen) { -+ brcmf_dbg(ERROR, "FAILED TO COPY, dlen %d sublen %d\n", -+ dlen, sublen); -+ errcode = -1; -+ } -+ pnext = NULL; -+ } else { -+ brcmf_dbg(ERROR, "COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", -+ dlen); -+ errcode = -1; -+ } -+ bus->f2rxdata++; -+ -+ /* On failure, kill the superframe, allow a couple retries */ -+ if (errcode < 0) { -+ brcmf_dbg(ERROR, "glom read of %d bytes failed: %d\n", -+ dlen, errcode); -+ bus->drvr->rx_errors++; -+ -+ if (bus->glomerr++ < 3) { -+ brcmf_sdbrcm_rxfail(bus, true, true); -+ } else { -+ bus->glomerr = 0; -+ brcmf_sdbrcm_rxfail(bus, true, false); -+ brcmu_pkt_buf_free_skb(bus->glom); -+ bus->rxglomfail++; -+ bus->glom = NULL; -+ } -+ return 0; -+ } -+#ifdef BCMDBG -+ if (BRCMF_GLOM_ON()) { -+ printk(KERN_DEBUG "SUPERFRAME:\n"); -+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, -+ pfirst->data, min_t(int, pfirst->len, 48)); -+ } -+#endif -+ -+ /* Validate the superframe header */ -+ dptr = (u8 *) (pfirst->data); -+ sublen = get_unaligned_le16(dptr); -+ check = get_unaligned_le16(dptr + sizeof(u16)); -+ -+ chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); -+ seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); -+ bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; -+ if ((bus->nextlen << 4) > MAX_RX_DATASZ) { -+ brcmf_dbg(INFO, "nextlen too large (%d) seq %d\n", -+ bus->nextlen, seq); -+ bus->nextlen = 0; -+ } -+ doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); -+ txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); -+ -+ errcode = 0; -+ if ((u16)~(sublen ^ check)) { -+ brcmf_dbg(ERROR, "(superframe): HW hdr error: len/check 0x%04x/0x%04x\n", -+ sublen, check); -+ errcode = -1; -+ } else if (roundup(sublen, bus->blocksize) != dlen) { -+ brcmf_dbg(ERROR, "(superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n", -+ sublen, roundup(sublen, bus->blocksize), -+ dlen); -+ errcode = -1; -+ } else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) != -+ SDPCM_GLOM_CHANNEL) { -+ brcmf_dbg(ERROR, "(superframe): bad channel %d\n", -+ SDPCM_PACKET_CHANNEL( -+ &dptr[SDPCM_FRAMETAG_LEN])); -+ errcode = -1; -+ } else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) { -+ brcmf_dbg(ERROR, "(superframe): got 2nd descriptor?\n"); -+ errcode = -1; -+ } else if ((doff < SDPCM_HDRLEN) || -+ (doff > (pfirst->len - SDPCM_HDRLEN))) { -+ brcmf_dbg(ERROR, "(superframe): Bad data offset %d: HW %d pkt %d min %d\n", -+ doff, sublen, pfirst->len, SDPCM_HDRLEN); -+ errcode = -1; -+ } -+ -+ /* Check sequence number of superframe SW header */ -+ if (rxseq != seq) { -+ brcmf_dbg(INFO, "(superframe) rx_seq %d, expected %d\n", -+ seq, rxseq); -+ bus->rx_badseq++; -+ rxseq = seq; -+ } -+ -+ /* Check window for sanity */ -+ if ((u8) (txmax - bus->tx_seq) > 0x40) { -+ brcmf_dbg(ERROR, "unlikely tx max %d with tx_seq %d\n", -+ txmax, bus->tx_seq); -+ txmax = bus->tx_seq + 2; -+ } -+ bus->tx_max = txmax; -+ -+ /* Remove superframe header, remember offset */ -+ skb_pull(pfirst, doff); -+ sfdoff = doff; -+ -+ /* Validate all the subframe headers */ -+ for (num = 0, pnext = pfirst; pnext && !errcode; -+ num++, pnext = pnext->next) { -+ dptr = (u8 *) (pnext->data); -+ dlen = (u16) (pnext->len); -+ sublen = get_unaligned_le16(dptr); -+ check = get_unaligned_le16(dptr + sizeof(u16)); -+ chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); -+ doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); -+#ifdef BCMDBG -+ if (BRCMF_GLOM_ON()) { -+ printk(KERN_DEBUG "subframe:\n"); -+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, -+ dptr, 32); -+ } -+#endif -+ -+ if ((u16)~(sublen ^ check)) { -+ brcmf_dbg(ERROR, "(subframe %d): HW hdr error: len/check 0x%04x/0x%04x\n", -+ num, sublen, check); -+ errcode = -1; -+ } else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) { -+ brcmf_dbg(ERROR, "(subframe %d): length mismatch: len 0x%04x, expect 0x%04x\n", -+ num, sublen, dlen); -+ errcode = -1; -+ } else if ((chan != SDPCM_DATA_CHANNEL) && -+ (chan != SDPCM_EVENT_CHANNEL)) { -+ brcmf_dbg(ERROR, "(subframe %d): bad channel %d\n", -+ num, chan); -+ errcode = -1; -+ } else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) { -+ brcmf_dbg(ERROR, "(subframe %d): Bad data offset %d: HW %d min %d\n", -+ num, doff, sublen, SDPCM_HDRLEN); -+ errcode = -1; -+ } -+ } -+ -+ if (errcode) { -+ /* Terminate frame on error, request -+ a couple retries */ -+ if (bus->glomerr++ < 3) { -+ /* Restore superframe header space */ -+ skb_push(pfirst, sfdoff); -+ brcmf_sdbrcm_rxfail(bus, true, true); -+ } else { -+ bus->glomerr = 0; -+ brcmf_sdbrcm_rxfail(bus, true, false); -+ brcmu_pkt_buf_free_skb(bus->glom); -+ bus->rxglomfail++; -+ bus->glom = NULL; -+ } -+ bus->nextlen = 0; -+ return 0; -+ } -+ -+ /* Basic SD framing looks ok - process each packet (header) */ -+ save_pfirst = pfirst; -+ bus->glom = NULL; -+ plast = NULL; -+ -+ for (num = 0; pfirst; rxseq++, pfirst = pnext) { -+ pnext = pfirst->next; -+ pfirst->next = NULL; -+ -+ dptr = (u8 *) (pfirst->data); -+ sublen = get_unaligned_le16(dptr); -+ chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); -+ seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); -+ doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); -+ -+ brcmf_dbg(GLOM, "Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n", -+ num, pfirst, pfirst->data, -+ pfirst->len, sublen, chan, seq); -+ -+ /* precondition: chan == SDPCM_DATA_CHANNEL || -+ chan == SDPCM_EVENT_CHANNEL */ -+ -+ if (rxseq != seq) { -+ brcmf_dbg(GLOM, "rx_seq %d, expected %d\n", -+ seq, rxseq); -+ bus->rx_badseq++; -+ rxseq = seq; -+ } -+#ifdef BCMDBG -+ if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) { -+ printk(KERN_DEBUG "Rx Subframe Data:\n"); -+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, -+ dptr, dlen); -+ } -+#endif -+ -+ __skb_trim(pfirst, sublen); -+ skb_pull(pfirst, doff); -+ -+ if (pfirst->len == 0) { -+ brcmu_pkt_buf_free_skb(pfirst); -+ if (plast) -+ plast->next = pnext; -+ else -+ save_pfirst = pnext; -+ -+ continue; -+ } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, -+ pfirst) != 0) { -+ brcmf_dbg(ERROR, "rx protocol error\n"); -+ bus->drvr->rx_errors++; -+ brcmu_pkt_buf_free_skb(pfirst); -+ if (plast) -+ plast->next = pnext; -+ else -+ save_pfirst = pnext; -+ -+ continue; -+ } -+ -+ /* this packet will go up, link back into -+ chain and count it */ -+ pfirst->next = pnext; -+ plast = pfirst; -+ num++; -+ -+#ifdef BCMDBG -+ if (BRCMF_GLOM_ON()) { -+ brcmf_dbg(GLOM, "subframe %d to stack, %p (%p/%d) nxt/lnk %p/%p\n", -+ num, pfirst, pfirst->data, -+ pfirst->len, pfirst->next, -+ pfirst->prev); -+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, -+ pfirst->data, -+ min_t(int, pfirst->len, 32)); -+ } -+#endif /* BCMDBG */ -+ } -+ if (num) { -+ up(&bus->sdsem); -+ brcmf_rx_frame(bus->drvr, ifidx, save_pfirst, num); -+ down(&bus->sdsem); -+ } -+ -+ bus->rxglomframes++; -+ bus->rxglompkts += num; -+ } -+ return num; -+} -+ -+static int brcmf_sdbrcm_dcmd_resp_wait(struct brcmf_bus *bus, uint *condition, -+ bool *pending) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ int timeout = msecs_to_jiffies(DCMD_RESP_TIMEOUT); -+ -+ /* Wait until control frame is available */ -+ add_wait_queue(&bus->dcmd_resp_wait, &wait); -+ set_current_state(TASK_INTERRUPTIBLE); -+ -+ while (!(*condition) && (!signal_pending(current) && timeout)) -+ timeout = schedule_timeout(timeout); -+ -+ if (signal_pending(current)) -+ *pending = true; -+ -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&bus->dcmd_resp_wait, &wait); -+ -+ return timeout; -+} -+ -+static int brcmf_sdbrcm_dcmd_resp_wake(struct brcmf_bus *bus) -+{ -+ if (waitqueue_active(&bus->dcmd_resp_wait)) -+ wake_up_interruptible(&bus->dcmd_resp_wait); -+ -+ return 0; -+} -+static void -+brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff) -+{ -+ uint rdlen, pad; -+ -+ int sdret; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* Set rxctl for frame (w/optional alignment) */ -+ bus->rxctl = bus->rxbuf; -+ bus->rxctl += BRCMF_FIRSTREAD; -+ pad = ((unsigned long)bus->rxctl % BRCMF_SDALIGN); -+ if (pad) -+ bus->rxctl += (BRCMF_SDALIGN - pad); -+ bus->rxctl -= BRCMF_FIRSTREAD; -+ -+ /* Copy the already-read portion over */ -+ memcpy(bus->rxctl, hdr, BRCMF_FIRSTREAD); -+ if (len <= BRCMF_FIRSTREAD) -+ goto gotpkt; -+ -+ /* Raise rdlen to next SDIO block to avoid tail command */ -+ rdlen = len - BRCMF_FIRSTREAD; -+ if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) { -+ pad = bus->blocksize - (rdlen % bus->blocksize); -+ if ((pad <= bus->roundup) && (pad < bus->blocksize) && -+ ((len + pad) < bus->drvr->maxctl)) -+ rdlen += pad; -+ } else if (rdlen % BRCMF_SDALIGN) { -+ rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN); -+ } -+ -+ /* Satisfy length-alignment requirements */ -+ if (rdlen & (ALIGNMENT - 1)) -+ rdlen = roundup(rdlen, ALIGNMENT); -+ -+ /* Drop if the read is too big or it exceeds our maximum */ -+ if ((rdlen + BRCMF_FIRSTREAD) > bus->drvr->maxctl) { -+ brcmf_dbg(ERROR, "%d-byte control read exceeds %d-byte buffer\n", -+ rdlen, bus->drvr->maxctl); -+ bus->drvr->rx_errors++; -+ brcmf_sdbrcm_rxfail(bus, false, false); -+ goto done; -+ } -+ -+ if ((len - doff) > bus->drvr->maxctl) { -+ brcmf_dbg(ERROR, "%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n", -+ len, len - doff, bus->drvr->maxctl); -+ bus->drvr->rx_errors++; -+ bus->rx_toolong++; -+ brcmf_sdbrcm_rxfail(bus, false, false); -+ goto done; -+ } -+ -+ /* Read remainder of frame body into the rxctl buffer */ -+ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, -+ bus->sdiodev->sbwad, -+ SDIO_FUNC_2, -+ F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen, -+ NULL); -+ bus->f2rxdata++; -+ -+ /* Control frame failures need retransmission */ -+ if (sdret < 0) { -+ brcmf_dbg(ERROR, "read %d control bytes failed: %d\n", -+ rdlen, sdret); -+ bus->rxc_errors++; -+ brcmf_sdbrcm_rxfail(bus, true, true); -+ goto done; -+ } -+ -+gotpkt: -+ -+#ifdef BCMDBG -+ if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) { -+ printk(KERN_DEBUG "RxCtrl:\n"); -+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, bus->rxctl, len); -+ } -+#endif -+ -+ /* Point to valid data and indicate its length */ -+ bus->rxctl += doff; -+ bus->rxlen = len - doff; -+ -+done: -+ /* Awake any waiters */ -+ brcmf_sdbrcm_dcmd_resp_wake(bus); -+} -+ -+/* Pad read to blocksize for efficiency */ -+static void brcmf_pad(struct brcmf_bus *bus, u16 *pad, u16 *rdlen) -+{ -+ if (bus->roundup && bus->blocksize && *rdlen > bus->blocksize) { -+ *pad = bus->blocksize - (*rdlen % bus->blocksize); -+ if (*pad <= bus->roundup && *pad < bus->blocksize && -+ *rdlen + *pad + BRCMF_FIRSTREAD < MAX_RX_DATASZ) -+ *rdlen += *pad; -+ } else if (*rdlen % BRCMF_SDALIGN) { -+ *rdlen += BRCMF_SDALIGN - (*rdlen % BRCMF_SDALIGN); -+ } -+} -+ -+static void -+brcmf_alloc_pkt_and_read(struct brcmf_bus *bus, u16 rdlen, -+ struct sk_buff **pkt, u8 **rxbuf) -+{ -+ int sdret; /* Return code from calls */ -+ -+ *pkt = brcmu_pkt_buf_get_skb(rdlen + BRCMF_SDALIGN); -+ if (*pkt == NULL) -+ return; -+ -+ pkt_align(*pkt, rdlen, BRCMF_SDALIGN); -+ *rxbuf = (u8 *) ((*pkt)->data); -+ /* Read the entire frame */ -+ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, -+ SDIO_FUNC_2, F2SYNC, -+ *rxbuf, rdlen, *pkt); -+ bus->f2rxdata++; -+ -+ if (sdret < 0) { -+ brcmf_dbg(ERROR, "(nextlen): read %d bytes failed: %d\n", -+ rdlen, sdret); -+ brcmu_pkt_buf_free_skb(*pkt); -+ bus->drvr->rx_errors++; -+ /* Force retry w/normal header read. -+ * Don't attempt NAK for -+ * gSPI -+ */ -+ brcmf_sdbrcm_rxfail(bus, true, true); -+ *pkt = NULL; -+ } -+} -+ -+/* Checks the header */ -+static int -+brcmf_check_rxbuf(struct brcmf_bus *bus, struct sk_buff *pkt, u8 *rxbuf, -+ u8 rxseq, u16 nextlen, u16 *len) -+{ -+ u16 check; -+ bool len_consistent; /* Result of comparing readahead len and -+ len from hw-hdr */ -+ -+ memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN); -+ -+ /* Extract hardware header fields */ -+ *len = get_unaligned_le16(bus->rxhdr); -+ check = get_unaligned_le16(bus->rxhdr + sizeof(u16)); -+ -+ /* All zeros means readahead info was bad */ -+ if (!(*len | check)) { -+ brcmf_dbg(INFO, "(nextlen): read zeros in HW header???\n"); -+ goto fail; -+ } -+ -+ /* Validate check bytes */ -+ if ((u16)~(*len ^ check)) { -+ brcmf_dbg(ERROR, "(nextlen): HW hdr error: nextlen/len/check 0x%04x/0x%04x/0x%04x\n", -+ nextlen, *len, check); -+ bus->rx_badhdr++; -+ brcmf_sdbrcm_rxfail(bus, false, false); -+ goto fail; -+ } -+ -+ /* Validate frame length */ -+ if (*len < SDPCM_HDRLEN) { -+ brcmf_dbg(ERROR, "(nextlen): HW hdr length invalid: %d\n", -+ *len); -+ goto fail; -+ } -+ -+ /* Check for consistency with readahead info */ -+ len_consistent = (nextlen != (roundup(*len, 16) >> 4)); -+ if (len_consistent) { -+ /* Mismatch, force retry w/normal -+ header (may be >4K) */ -+ brcmf_dbg(ERROR, "(nextlen): mismatch, nextlen %d len %d rnd %d; expected rxseq %d\n", -+ nextlen, *len, roundup(*len, 16), -+ rxseq); -+ brcmf_sdbrcm_rxfail(bus, true, true); -+ goto fail; -+ } -+ -+ return 0; -+ -+fail: -+ brcmf_sdbrcm_pktfree2(bus, pkt); -+ return -EINVAL; -+} -+ -+/* Return true if there may be more frames to read */ -+static uint -+brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished) -+{ -+ u16 len, check; /* Extracted hardware header fields */ -+ u8 chan, seq, doff; /* Extracted software header fields */ -+ u8 fcbits; /* Extracted fcbits from software header */ -+ -+ struct sk_buff *pkt; /* Packet for event or data frames */ -+ u16 pad; /* Number of pad bytes to read */ -+ u16 rdlen; /* Total number of bytes to read */ -+ u8 rxseq; /* Next sequence number to expect */ -+ uint rxleft = 0; /* Remaining number of frames allowed */ -+ int sdret; /* Return code from calls */ -+ u8 txmax; /* Maximum tx sequence offered */ -+ u8 *rxbuf; -+ int ifidx = 0; -+ uint rxcount = 0; /* Total frames read */ -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* Not finished unless we encounter no more frames indication */ -+ *finished = false; -+ -+ for (rxseq = bus->rx_seq, rxleft = maxframes; -+ !bus->rxskip && rxleft && bus->drvr->busstate != BRCMF_BUS_DOWN; -+ rxseq++, rxleft--) { -+ -+ /* Handle glomming separately */ -+ if (bus->glom || bus->glomd) { -+ u8 cnt; -+ brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n", -+ bus->glomd, bus->glom); -+ cnt = brcmf_sdbrcm_rxglom(bus, rxseq); -+ brcmf_dbg(GLOM, "rxglom returned %d\n", cnt); -+ rxseq += cnt - 1; -+ rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1; -+ continue; -+ } -+ -+ /* Try doing single read if we can */ -+ if (bus->nextlen) { -+ u16 nextlen = bus->nextlen; -+ bus->nextlen = 0; -+ -+ rdlen = len = nextlen << 4; -+ brcmf_pad(bus, &pad, &rdlen); -+ -+ /* -+ * After the frame is received we have to -+ * distinguish whether it is data -+ * or non-data frame. -+ */ -+ brcmf_alloc_pkt_and_read(bus, rdlen, &pkt, &rxbuf); -+ if (pkt == NULL) { -+ /* Give up on data, request rtx of events */ -+ brcmf_dbg(ERROR, "(nextlen): brcmf_alloc_pkt_and_read failed: len %d rdlen %d expected rxseq %d\n", -+ len, rdlen, rxseq); -+ continue; -+ } -+ -+ if (brcmf_check_rxbuf(bus, pkt, rxbuf, rxseq, nextlen, -+ &len) < 0) -+ continue; -+ -+ /* Extract software header fields */ -+ chan = SDPCM_PACKET_CHANNEL( -+ &bus->rxhdr[SDPCM_FRAMETAG_LEN]); -+ seq = SDPCM_PACKET_SEQUENCE( -+ &bus->rxhdr[SDPCM_FRAMETAG_LEN]); -+ doff = SDPCM_DOFFSET_VALUE( -+ &bus->rxhdr[SDPCM_FRAMETAG_LEN]); -+ txmax = SDPCM_WINDOW_VALUE( -+ &bus->rxhdr[SDPCM_FRAMETAG_LEN]); -+ -+ bus->nextlen = -+ bus->rxhdr[SDPCM_FRAMETAG_LEN + -+ SDPCM_NEXTLEN_OFFSET]; -+ if ((bus->nextlen << 4) > MAX_RX_DATASZ) { -+ brcmf_dbg(INFO, "(nextlen): got frame w/nextlen too large (%d), seq %d\n", -+ bus->nextlen, seq); -+ bus->nextlen = 0; -+ } -+ -+ bus->drvr->rx_readahead_cnt++; -+ -+ /* Handle Flow Control */ -+ fcbits = SDPCM_FCMASK_VALUE( -+ &bus->rxhdr[SDPCM_FRAMETAG_LEN]); -+ -+ if (bus->flowcontrol != fcbits) { -+ if (~bus->flowcontrol & fcbits) -+ bus->fc_xoff++; -+ -+ if (bus->flowcontrol & ~fcbits) -+ bus->fc_xon++; -+ -+ bus->fc_rcvd++; -+ bus->flowcontrol = fcbits; -+ } -+ -+ /* Check and update sequence number */ -+ if (rxseq != seq) { -+ brcmf_dbg(INFO, "(nextlen): rx_seq %d, expected %d\n", -+ seq, rxseq); -+ bus->rx_badseq++; -+ rxseq = seq; -+ } -+ -+ /* Check window for sanity */ -+ if ((u8) (txmax - bus->tx_seq) > 0x40) { -+ brcmf_dbg(ERROR, "got unlikely tx max %d with tx_seq %d\n", -+ txmax, bus->tx_seq); -+ txmax = bus->tx_seq + 2; -+ } -+ bus->tx_max = txmax; -+ -+#ifdef BCMDBG -+ if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) { -+ printk(KERN_DEBUG "Rx Data:\n"); -+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, -+ rxbuf, len); -+ } else if (BRCMF_HDRS_ON()) { -+ printk(KERN_DEBUG "RxHdr:\n"); -+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, -+ bus->rxhdr, SDPCM_HDRLEN); -+ } -+#endif -+ -+ if (chan == SDPCM_CONTROL_CHANNEL) { -+ brcmf_dbg(ERROR, "(nextlen): readahead on control packet %d?\n", -+ seq); -+ /* Force retry w/normal header read */ -+ bus->nextlen = 0; -+ brcmf_sdbrcm_rxfail(bus, false, true); -+ brcmf_sdbrcm_pktfree2(bus, pkt); -+ continue; -+ } -+ -+ /* Validate data offset */ -+ if ((doff < SDPCM_HDRLEN) || (doff > len)) { -+ brcmf_dbg(ERROR, "(nextlen): bad data offset %d: HW len %d min %d\n", -+ doff, len, SDPCM_HDRLEN); -+ brcmf_sdbrcm_rxfail(bus, false, false); -+ brcmf_sdbrcm_pktfree2(bus, pkt); -+ continue; -+ } -+ -+ /* All done with this one -- now deliver the packet */ -+ goto deliver; -+ } -+ -+ /* Read frame header (hardware and software) */ -+ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, -+ SDIO_FUNC_2, F2SYNC, bus->rxhdr, -+ BRCMF_FIRSTREAD, NULL); -+ bus->f2rxhdrs++; -+ -+ if (sdret < 0) { -+ brcmf_dbg(ERROR, "RXHEADER FAILED: %d\n", sdret); -+ bus->rx_hdrfail++; -+ brcmf_sdbrcm_rxfail(bus, true, true); -+ continue; -+ } -+#ifdef BCMDBG -+ if (BRCMF_BYTES_ON() || BRCMF_HDRS_ON()) { -+ printk(KERN_DEBUG "RxHdr:\n"); -+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, -+ bus->rxhdr, SDPCM_HDRLEN); -+ } -+#endif -+ -+ /* Extract hardware header fields */ -+ len = get_unaligned_le16(bus->rxhdr); -+ check = get_unaligned_le16(bus->rxhdr + sizeof(u16)); -+ -+ /* All zeros means no more frames */ -+ if (!(len | check)) { -+ *finished = true; -+ break; -+ } -+ -+ /* Validate check bytes */ -+ if ((u16) ~(len ^ check)) { -+ brcmf_dbg(ERROR, "HW hdr err: len/check 0x%04x/0x%04x\n", -+ len, check); -+ bus->rx_badhdr++; -+ brcmf_sdbrcm_rxfail(bus, false, false); -+ continue; -+ } -+ -+ /* Validate frame length */ -+ if (len < SDPCM_HDRLEN) { -+ brcmf_dbg(ERROR, "HW hdr length invalid: %d\n", len); -+ continue; -+ } -+ -+ /* Extract software header fields */ -+ chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); -+ seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); -+ doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); -+ txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); -+ -+ /* Validate data offset */ -+ if ((doff < SDPCM_HDRLEN) || (doff > len)) { -+ brcmf_dbg(ERROR, "Bad data offset %d: HW len %d, min %d seq %d\n", -+ doff, len, SDPCM_HDRLEN, seq); -+ bus->rx_badhdr++; -+ brcmf_sdbrcm_rxfail(bus, false, false); -+ continue; -+ } -+ -+ /* Save the readahead length if there is one */ -+ bus->nextlen = -+ bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; -+ if ((bus->nextlen << 4) > MAX_RX_DATASZ) { -+ brcmf_dbg(INFO, "(nextlen): got frame w/nextlen too large (%d), seq %d\n", -+ bus->nextlen, seq); -+ bus->nextlen = 0; -+ } -+ -+ /* Handle Flow Control */ -+ fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); -+ -+ if (bus->flowcontrol != fcbits) { -+ if (~bus->flowcontrol & fcbits) -+ bus->fc_xoff++; -+ -+ if (bus->flowcontrol & ~fcbits) -+ bus->fc_xon++; -+ -+ bus->fc_rcvd++; -+ bus->flowcontrol = fcbits; -+ } -+ -+ /* Check and update sequence number */ -+ if (rxseq != seq) { -+ brcmf_dbg(INFO, "rx_seq %d, expected %d\n", seq, rxseq); -+ bus->rx_badseq++; -+ rxseq = seq; -+ } -+ -+ /* Check window for sanity */ -+ if ((u8) (txmax - bus->tx_seq) > 0x40) { -+ brcmf_dbg(ERROR, "unlikely tx max %d with tx_seq %d\n", -+ txmax, bus->tx_seq); -+ txmax = bus->tx_seq + 2; -+ } -+ bus->tx_max = txmax; -+ -+ /* Call a separate function for control frames */ -+ if (chan == SDPCM_CONTROL_CHANNEL) { -+ brcmf_sdbrcm_read_control(bus, bus->rxhdr, len, doff); -+ continue; -+ } -+ -+ /* precondition: chan is either SDPCM_DATA_CHANNEL, -+ SDPCM_EVENT_CHANNEL, SDPCM_TEST_CHANNEL or -+ SDPCM_GLOM_CHANNEL */ -+ -+ /* Length to read */ -+ rdlen = (len > BRCMF_FIRSTREAD) ? (len - BRCMF_FIRSTREAD) : 0; -+ -+ /* May pad read to blocksize for efficiency */ -+ if (bus->roundup && bus->blocksize && -+ (rdlen > bus->blocksize)) { -+ pad = bus->blocksize - (rdlen % bus->blocksize); -+ if ((pad <= bus->roundup) && (pad < bus->blocksize) && -+ ((rdlen + pad + BRCMF_FIRSTREAD) < MAX_RX_DATASZ)) -+ rdlen += pad; -+ } else if (rdlen % BRCMF_SDALIGN) { -+ rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN); -+ } -+ -+ /* Satisfy length-alignment requirements */ -+ if (rdlen & (ALIGNMENT - 1)) -+ rdlen = roundup(rdlen, ALIGNMENT); -+ -+ if ((rdlen + BRCMF_FIRSTREAD) > MAX_RX_DATASZ) { -+ /* Too long -- skip this frame */ -+ brcmf_dbg(ERROR, "too long: len %d rdlen %d\n", -+ len, rdlen); -+ bus->drvr->rx_errors++; -+ bus->rx_toolong++; -+ brcmf_sdbrcm_rxfail(bus, false, false); -+ continue; -+ } -+ -+ pkt = brcmu_pkt_buf_get_skb(rdlen + -+ BRCMF_FIRSTREAD + BRCMF_SDALIGN); -+ if (!pkt) { -+ /* Give up on data, request rtx of events */ -+ brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: rdlen %d chan %d\n", -+ rdlen, chan); -+ bus->drvr->rx_dropped++; -+ brcmf_sdbrcm_rxfail(bus, false, RETRYCHAN(chan)); -+ continue; -+ } -+ -+ /* Leave room for what we already read, and align remainder */ -+ skb_pull(pkt, BRCMF_FIRSTREAD); -+ pkt_align(pkt, rdlen, BRCMF_SDALIGN); -+ -+ /* Read the remaining frame data */ -+ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, -+ SDIO_FUNC_2, F2SYNC, ((u8 *) (pkt->data)), -+ rdlen, pkt); -+ bus->f2rxdata++; -+ -+ if (sdret < 0) { -+ brcmf_dbg(ERROR, "read %d %s bytes failed: %d\n", rdlen, -+ ((chan == SDPCM_EVENT_CHANNEL) ? "event" -+ : ((chan == SDPCM_DATA_CHANNEL) ? "data" -+ : "test")), sdret); -+ brcmu_pkt_buf_free_skb(pkt); -+ bus->drvr->rx_errors++; -+ brcmf_sdbrcm_rxfail(bus, true, RETRYCHAN(chan)); -+ continue; -+ } -+ -+ /* Copy the already-read portion */ -+ skb_push(pkt, BRCMF_FIRSTREAD); -+ memcpy(pkt->data, bus->rxhdr, BRCMF_FIRSTREAD); -+ -+#ifdef BCMDBG -+ if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) { -+ printk(KERN_DEBUG "Rx Data:\n"); -+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, -+ pkt->data, len); -+ } -+#endif -+ -+deliver: -+ /* Save superframe descriptor and allocate packet frame */ -+ if (chan == SDPCM_GLOM_CHANNEL) { -+ if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) { -+ brcmf_dbg(GLOM, "glom descriptor, %d bytes:\n", -+ len); -+#ifdef BCMDBG -+ if (BRCMF_GLOM_ON()) { -+ printk(KERN_DEBUG "Glom Data:\n"); -+ print_hex_dump_bytes("", -+ DUMP_PREFIX_OFFSET, -+ pkt->data, len); -+ } -+#endif -+ __skb_trim(pkt, len); -+ skb_pull(pkt, SDPCM_HDRLEN); -+ bus->glomd = pkt; -+ } else { -+ brcmf_dbg(ERROR, "%s: glom superframe w/o " -+ "descriptor!\n", __func__); -+ brcmf_sdbrcm_rxfail(bus, false, false); -+ } -+ continue; -+ } -+ -+ /* Fill in packet len and prio, deliver upward */ -+ __skb_trim(pkt, len); -+ skb_pull(pkt, doff); -+ -+ if (pkt->len == 0) { -+ brcmu_pkt_buf_free_skb(pkt); -+ continue; -+ } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, pkt) != 0) { -+ brcmf_dbg(ERROR, "rx protocol error\n"); -+ brcmu_pkt_buf_free_skb(pkt); -+ bus->drvr->rx_errors++; -+ continue; -+ } -+ -+ /* Unlock during rx call */ -+ up(&bus->sdsem); -+ brcmf_rx_frame(bus->drvr, ifidx, pkt, 1); -+ down(&bus->sdsem); -+ } -+ rxcount = maxframes - rxleft; -+#ifdef BCMDBG -+ /* Message if we hit the limit */ -+ if (!rxleft) -+ brcmf_dbg(DATA, "hit rx limit of %d frames\n", -+ maxframes); -+ else -+#endif /* BCMDBG */ -+ brcmf_dbg(DATA, "processed %d frames\n", rxcount); -+ /* Back off rxseq if awaiting rtx, update rx_seq */ -+ if (bus->rxskip) -+ rxseq--; -+ bus->rx_seq = rxseq; -+ -+ return rxcount; -+} -+ -+static int -+brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn, uint flags, -+ u8 *buf, uint nbytes, struct sk_buff *pkt) -+{ -+ return brcmf_sdcard_send_buf -+ (bus->sdiodev, addr, fn, flags, buf, nbytes, pkt); -+} -+ -+static void -+brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar) -+{ -+ up(&bus->sdsem); -+ wait_event_interruptible_timeout(bus->ctrl_wait, -+ (*lockvar == false), HZ * 2); -+ down(&bus->sdsem); -+ return; -+} -+ -+static void -+brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus) -+{ -+ if (waitqueue_active(&bus->ctrl_wait)) -+ wake_up_interruptible(&bus->ctrl_wait); -+ return; -+} -+ -+/* Writes a HW/SW header into the packet and sends it. */ -+/* Assumes: (a) header space already there, (b) caller holds lock */ -+static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt, -+ uint chan, bool free_pkt) -+{ -+ int ret; -+ u8 *frame; -+ u16 len, pad = 0; -+ u32 swheader; -+ struct sk_buff *new; -+ int i; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ frame = (u8 *) (pkt->data); -+ -+ /* Add alignment padding, allocate new packet if needed */ -+ pad = ((unsigned long)frame % BRCMF_SDALIGN); -+ if (pad) { -+ if (skb_headroom(pkt) < pad) { -+ brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n", -+ skb_headroom(pkt), pad); -+ bus->drvr->tx_realloc++; -+ new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN); -+ if (!new) { -+ brcmf_dbg(ERROR, "couldn't allocate new %d-byte packet\n", -+ pkt->len + BRCMF_SDALIGN); -+ ret = -ENOMEM; -+ goto done; -+ } -+ -+ pkt_align(new, pkt->len, BRCMF_SDALIGN); -+ memcpy(new->data, pkt->data, pkt->len); -+ if (free_pkt) -+ brcmu_pkt_buf_free_skb(pkt); -+ /* free the pkt if canned one is not used */ -+ free_pkt = true; -+ pkt = new; -+ frame = (u8 *) (pkt->data); -+ /* precondition: (frame % BRCMF_SDALIGN) == 0) */ -+ pad = 0; -+ } else { -+ skb_push(pkt, pad); -+ frame = (u8 *) (pkt->data); -+ /* precondition: pad + SDPCM_HDRLEN <= pkt->len */ -+ memset(frame, 0, pad + SDPCM_HDRLEN); -+ } -+ } -+ /* precondition: pad < BRCMF_SDALIGN */ -+ -+ /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ -+ len = (u16) (pkt->len); -+ *(__le16 *) frame = cpu_to_le16(len); -+ *(((__le16 *) frame) + 1) = cpu_to_le16(~len); -+ -+ /* Software tag: channel, sequence number, data offset */ -+ swheader = -+ ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq | -+ (((pad + -+ SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); -+ -+ put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN); -+ put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); -+ -+#ifdef BCMDBG -+ tx_packets[pkt->priority]++; -+ if (BRCMF_BYTES_ON() && -+ (((BRCMF_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) || -+ (BRCMF_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) { -+ printk(KERN_DEBUG "Tx Frame:\n"); -+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, frame, len); -+ } else if (BRCMF_HDRS_ON()) { -+ printk(KERN_DEBUG "TxHdr:\n"); -+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, -+ frame, min_t(u16, len, 16)); -+ } -+#endif -+ -+ /* Raise len to next SDIO block to eliminate tail command */ -+ if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { -+ u16 pad = bus->blocksize - (len % bus->blocksize); -+ if ((pad <= bus->roundup) && (pad < bus->blocksize)) -+ len += pad; -+ } else if (len % BRCMF_SDALIGN) { -+ len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN); -+ } -+ -+ /* Some controllers have trouble with odd bytes -- round to even */ -+ if (len & (ALIGNMENT - 1)) -+ len = roundup(len, ALIGNMENT); -+ -+ ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad, -+ SDIO_FUNC_2, F2SYNC, frame, -+ len, pkt); -+ bus->f2txdata++; -+ -+ if (ret < 0) { -+ /* On failure, abort the command and terminate the frame */ -+ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", -+ ret); -+ bus->tx_sderrs++; -+ -+ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, -+ NULL); -+ bus->f1regdata++; -+ -+ for (i = 0; i < 3; i++) { -+ u8 hi, lo; -+ hi = brcmf_sdcard_cfg_read(bus->sdiodev, -+ SDIO_FUNC_1, -+ SBSDIO_FUNC1_WFRAMEBCHI, -+ NULL); -+ lo = brcmf_sdcard_cfg_read(bus->sdiodev, -+ SDIO_FUNC_1, -+ SBSDIO_FUNC1_WFRAMEBCLO, -+ NULL); -+ bus->f1regdata += 2; -+ if ((hi == 0) && (lo == 0)) -+ break; -+ } -+ -+ } -+ if (ret == 0) -+ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; -+ -+done: -+ /* restore pkt buffer pointer before calling tx complete routine */ -+ skb_pull(pkt, SDPCM_HDRLEN + pad); -+ up(&bus->sdsem); -+ brcmf_txcomplete(bus->drvr, pkt, ret != 0); -+ down(&bus->sdsem); -+ -+ if (free_pkt) -+ brcmu_pkt_buf_free_skb(pkt); -+ -+ return ret; -+} -+ -+static uint brcmf_sdbrcm_sendfromq(struct brcmf_bus *bus, uint maxframes) -+{ -+ struct sk_buff *pkt; -+ u32 intstatus = 0; -+ uint retries = 0; -+ int ret = 0, prec_out; -+ uint cnt = 0; -+ uint datalen; -+ u8 tx_prec_map; -+ -+ struct brcmf_pub *drvr = bus->drvr; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ tx_prec_map = ~bus->flowcontrol; -+ -+ /* Send frames until the limit or some other event */ -+ for (cnt = 0; (cnt < maxframes) && data_ok(bus); cnt++) { -+ spin_lock_bh(&bus->txqlock); -+ pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out); -+ if (pkt == NULL) { -+ spin_unlock_bh(&bus->txqlock); -+ break; -+ } -+ spin_unlock_bh(&bus->txqlock); -+ datalen = pkt->len - SDPCM_HDRLEN; -+ -+ ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true); -+ if (ret) -+ bus->drvr->tx_errors++; -+ else -+ bus->drvr->dstats.tx_bytes += datalen; -+ -+ /* In poll mode, need to check for other events */ -+ if (!bus->intr && cnt) { -+ /* Check device status, signal pending interrupt */ -+ r_sdreg32(bus, &intstatus, -+ offsetof(struct sdpcmd_regs, intstatus), -+ &retries); -+ bus->f2txdata++; -+ if (brcmf_sdcard_regfail(bus->sdiodev)) -+ break; -+ if (intstatus & bus->hostintmask) -+ bus->ipend = true; -+ } -+ } -+ -+ /* Deflow-control stack if needed */ -+ if (drvr->up && (drvr->busstate == BRCMF_BUS_DATA) && -+ drvr->txoff && (pktq_len(&bus->txq) < TXLOW)) -+ brcmf_txflowcontrol(drvr, 0, OFF); -+ -+ return cnt; -+} -+ -+static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus) -+{ -+ u32 intstatus, newstatus = 0; -+ uint retries = 0; -+ uint rxlimit = bus->rxbound; /* Rx frames to read before resched */ -+ uint txlimit = bus->txbound; /* Tx frames to send before resched */ -+ uint framecnt = 0; /* Temporary counter of tx/rx frames */ -+ bool rxdone = true; /* Flag for no more read data */ -+ bool resched = false; /* Flag indicating resched wanted */ -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* Start with leftover status bits */ -+ intstatus = bus->intstatus; -+ -+ down(&bus->sdsem); -+ -+ /* If waiting for HTAVAIL, check status */ -+ if (bus->clkstate == CLK_PENDING) { -+ int err; -+ u8 clkctl, devctl = 0; -+ -+#ifdef BCMDBG -+ /* Check for inconsistent device control */ -+ devctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_DEVICE_CTL, &err); -+ if (err) { -+ brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", err); -+ bus->drvr->busstate = BRCMF_BUS_DOWN; -+ } -+#endif /* BCMDBG */ -+ -+ /* Read CSR, if clock on switch to AVAIL, else ignore */ -+ clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, &err); -+ if (err) { -+ brcmf_dbg(ERROR, "error reading CSR: %d\n", -+ err); -+ bus->drvr->busstate = BRCMF_BUS_DOWN; -+ } -+ -+ brcmf_dbg(INFO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", -+ devctl, clkctl); -+ -+ if (SBSDIO_HTAV(clkctl)) { -+ devctl = brcmf_sdcard_cfg_read(bus->sdiodev, -+ SDIO_FUNC_1, -+ SBSDIO_DEVICE_CTL, &err); -+ if (err) { -+ brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", -+ err); -+ bus->drvr->busstate = BRCMF_BUS_DOWN; -+ } -+ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_DEVICE_CTL, devctl, &err); -+ if (err) { -+ brcmf_dbg(ERROR, "error writing DEVCTL: %d\n", -+ err); -+ bus->drvr->busstate = BRCMF_BUS_DOWN; -+ } -+ bus->clkstate = CLK_AVAIL; -+ } else { -+ goto clkwait; -+ } -+ } -+ -+ bus_wake(bus); -+ -+ /* Make sure backplane clock is on */ -+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true); -+ if (bus->clkstate == CLK_PENDING) -+ goto clkwait; -+ -+ /* Pending interrupt indicates new device status */ -+ if (bus->ipend) { -+ bus->ipend = false; -+ r_sdreg32(bus, &newstatus, -+ offsetof(struct sdpcmd_regs, intstatus), &retries); -+ bus->f1regdata++; -+ if (brcmf_sdcard_regfail(bus->sdiodev)) -+ newstatus = 0; -+ newstatus &= bus->hostintmask; -+ bus->fcstate = !!(newstatus & I_HMB_FC_STATE); -+ if (newstatus) { -+ w_sdreg32(bus, newstatus, -+ offsetof(struct sdpcmd_regs, intstatus), -+ &retries); -+ bus->f1regdata++; -+ } -+ } -+ -+ /* Merge new bits with previous */ -+ intstatus |= newstatus; -+ bus->intstatus = 0; -+ -+ /* Handle flow-control change: read new state in case our ack -+ * crossed another change interrupt. If change still set, assume -+ * FC ON for safety, let next loop through do the debounce. -+ */ -+ if (intstatus & I_HMB_FC_CHANGE) { -+ intstatus &= ~I_HMB_FC_CHANGE; -+ w_sdreg32(bus, I_HMB_FC_CHANGE, -+ offsetof(struct sdpcmd_regs, intstatus), &retries); -+ -+ r_sdreg32(bus, &newstatus, -+ offsetof(struct sdpcmd_regs, intstatus), &retries); -+ bus->f1regdata += 2; -+ bus->fcstate = -+ !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)); -+ intstatus |= (newstatus & bus->hostintmask); -+ } -+ -+ /* Handle host mailbox indication */ -+ if (intstatus & I_HMB_HOST_INT) { -+ intstatus &= ~I_HMB_HOST_INT; -+ intstatus |= brcmf_sdbrcm_hostmail(bus); -+ } -+ -+ /* Generally don't ask for these, can get CRC errors... */ -+ if (intstatus & I_WR_OOSYNC) { -+ brcmf_dbg(ERROR, "Dongle reports WR_OOSYNC\n"); -+ intstatus &= ~I_WR_OOSYNC; -+ } -+ -+ if (intstatus & I_RD_OOSYNC) { -+ brcmf_dbg(ERROR, "Dongle reports RD_OOSYNC\n"); -+ intstatus &= ~I_RD_OOSYNC; -+ } -+ -+ if (intstatus & I_SBINT) { -+ brcmf_dbg(ERROR, "Dongle reports SBINT\n"); -+ intstatus &= ~I_SBINT; -+ } -+ -+ /* Would be active due to wake-wlan in gSPI */ -+ if (intstatus & I_CHIPACTIVE) { -+ brcmf_dbg(INFO, "Dongle reports CHIPACTIVE\n"); -+ intstatus &= ~I_CHIPACTIVE; -+ } -+ -+ /* Ignore frame indications if rxskip is set */ -+ if (bus->rxskip) -+ intstatus &= ~I_HMB_FRAME_IND; -+ -+ /* On frame indication, read available frames */ -+ if (PKT_AVAILABLE()) { -+ framecnt = brcmf_sdbrcm_readframes(bus, rxlimit, &rxdone); -+ if (rxdone || bus->rxskip) -+ intstatus &= ~I_HMB_FRAME_IND; -+ rxlimit -= min(framecnt, rxlimit); -+ } -+ -+ /* Keep still-pending events for next scheduling */ -+ bus->intstatus = intstatus; -+ -+clkwait: -+ if (data_ok(bus) && bus->ctrl_frame_stat && -+ (bus->clkstate == CLK_AVAIL)) { -+ int ret, i; -+ -+ ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad, -+ SDIO_FUNC_2, F2SYNC, (u8 *) bus->ctrl_frame_buf, -+ (u32) bus->ctrl_frame_len, NULL); -+ -+ if (ret < 0) { -+ /* On failure, abort the command and -+ terminate the frame */ -+ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", -+ ret); -+ bus->tx_sderrs++; -+ -+ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); -+ -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, -+ NULL); -+ bus->f1regdata++; -+ -+ for (i = 0; i < 3; i++) { -+ u8 hi, lo; -+ hi = brcmf_sdcard_cfg_read(bus->sdiodev, -+ SDIO_FUNC_1, -+ SBSDIO_FUNC1_WFRAMEBCHI, -+ NULL); -+ lo = brcmf_sdcard_cfg_read(bus->sdiodev, -+ SDIO_FUNC_1, -+ SBSDIO_FUNC1_WFRAMEBCLO, -+ NULL); -+ bus->f1regdata += 2; -+ if ((hi == 0) && (lo == 0)) -+ break; -+ } -+ -+ } -+ if (ret == 0) -+ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; -+ -+ brcmf_dbg(INFO, "Return_dpc value is : %d\n", ret); -+ bus->ctrl_frame_stat = false; -+ brcmf_sdbrcm_wait_event_wakeup(bus); -+ } -+ /* Send queued frames (limit 1 if rx may still be pending) */ -+ else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate && -+ brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit -+ && data_ok(bus)) { -+ framecnt = rxdone ? txlimit : min(txlimit, bus->txminmax); -+ framecnt = brcmf_sdbrcm_sendfromq(bus, framecnt); -+ txlimit -= framecnt; -+ } -+ -+ /* Resched if events or tx frames are pending, -+ else await next interrupt */ -+ /* On failed register access, all bets are off: -+ no resched or interrupts */ -+ if ((bus->drvr->busstate == BRCMF_BUS_DOWN) || -+ brcmf_sdcard_regfail(bus->sdiodev)) { -+ brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation %d\n", -+ brcmf_sdcard_regfail(bus->sdiodev)); -+ bus->drvr->busstate = BRCMF_BUS_DOWN; -+ bus->intstatus = 0; -+ } else if (bus->clkstate == CLK_PENDING) { -+ brcmf_dbg(INFO, "rescheduled due to CLK_PENDING awaiting I_CHIPACTIVE interrupt\n"); -+ resched = true; -+ } else if (bus->intstatus || bus->ipend || -+ (!bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) -+ && data_ok(bus)) || PKT_AVAILABLE()) { -+ resched = true; -+ } -+ -+ bus->dpc_sched = resched; -+ -+ /* If we're done for now, turn off clock request. */ -+ if ((bus->clkstate != CLK_PENDING) -+ && bus->idletime == BRCMF_IDLE_IMMEDIATE) { -+ bus->activity = false; -+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); -+ } -+ -+ up(&bus->sdsem); -+ -+ return resched; -+} -+ -+static int brcmf_sdbrcm_dpc_thread(void *data) -+{ -+ struct brcmf_bus *bus = (struct brcmf_bus *) data; -+ -+ allow_signal(SIGTERM); -+ /* Run until signal received */ -+ while (1) { -+ if (kthread_should_stop()) -+ break; -+ if (!wait_for_completion_interruptible(&bus->dpc_wait)) { -+ /* Call bus dpc unless it indicated down -+ (then clean stop) */ -+ if (bus->drvr->busstate != BRCMF_BUS_DOWN) { -+ if (brcmf_sdbrcm_dpc(bus)) -+ complete(&bus->dpc_wait); -+ } else { -+ /* after stopping the bus, exit thread */ -+ brcmf_sdbrcm_bus_stop(bus); -+ bus->dpc_tsk = NULL; -+ break; -+ } -+ } else -+ break; -+ } -+ return 0; -+} -+ -+int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt) -+{ -+ int ret = -EBADE; -+ uint datalen, prec; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ datalen = pkt->len; -+ -+ /* Add space for the header */ -+ skb_push(pkt, SDPCM_HDRLEN); -+ /* precondition: IS_ALIGNED((unsigned long)(pkt->data), 2) */ -+ -+ prec = prio2prec((pkt->priority & PRIOMASK)); -+ -+ /* Check for existing queue, current flow-control, -+ pending event, or pending clock */ -+ brcmf_dbg(TRACE, "deferring pktq len %d\n", pktq_len(&bus->txq)); -+ bus->fcqueued++; -+ -+ /* Priority based enq */ -+ spin_lock_bh(&bus->txqlock); -+ if (brcmf_c_prec_enq(bus->drvr, &bus->txq, pkt, prec) == false) { -+ skb_pull(pkt, SDPCM_HDRLEN); -+ brcmf_txcomplete(bus->drvr, pkt, false); -+ brcmu_pkt_buf_free_skb(pkt); -+ brcmf_dbg(ERROR, "out of bus->txq !!!\n"); -+ ret = -ENOSR; -+ } else { -+ ret = 0; -+ } -+ spin_unlock_bh(&bus->txqlock); -+ -+ if (pktq_len(&bus->txq) >= TXHI) -+ brcmf_txflowcontrol(bus->drvr, 0, ON); -+ -+#ifdef BCMDBG -+ if (pktq_plen(&bus->txq, prec) > qcount[prec]) -+ qcount[prec] = pktq_plen(&bus->txq, prec); -+#endif -+ /* Schedule DPC if needed to send queued packet(s) */ -+ if (!bus->dpc_sched) { -+ bus->dpc_sched = true; -+ if (bus->dpc_tsk) -+ complete(&bus->dpc_wait); -+ } -+ -+ return ret; -+} -+ -+static int -+brcmf_sdbrcm_membytes(struct brcmf_bus *bus, bool write, u32 address, u8 *data, -+ uint size) -+{ -+ int bcmerror = 0; -+ u32 sdaddr; -+ uint dsize; -+ -+ /* Determine initial transfer parameters */ -+ sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK; -+ if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK) -+ dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr); -+ else -+ dsize = size; -+ -+ /* Set the backplane window to include the start address */ -+ bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address); -+ if (bcmerror) { -+ brcmf_dbg(ERROR, "window change failed\n"); -+ goto xfer_done; -+ } -+ -+ /* Do the transfer(s) */ -+ while (size) { -+ brcmf_dbg(INFO, "%s %d bytes at offset 0x%08x in window 0x%08x\n", -+ write ? "write" : "read", dsize, -+ sdaddr, address & SBSDIO_SBWINDOW_MASK); -+ bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write, -+ sdaddr, data, dsize); -+ if (bcmerror) { -+ brcmf_dbg(ERROR, "membytes transfer failed\n"); -+ break; -+ } -+ -+ /* Adjust for next transfer (if any) */ -+ size -= dsize; -+ if (size) { -+ data += dsize; -+ address += dsize; -+ bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, -+ address); -+ if (bcmerror) { -+ brcmf_dbg(ERROR, "window change failed\n"); -+ break; -+ } -+ sdaddr = 0; -+ dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size); -+ } -+ } -+ -+xfer_done: -+ /* Return the window to backplane enumeration space for core access */ -+ if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, bus->sdiodev->sbwad)) -+ brcmf_dbg(ERROR, "FAILED to set window back to 0x%x\n", -+ bus->sdiodev->sbwad); -+ -+ return bcmerror; -+} -+ -+#ifdef BCMDBG -+#define CONSOLE_LINE_MAX 192 -+ -+static int brcmf_sdbrcm_readconsole(struct brcmf_bus *bus) -+{ -+ struct brcmf_console *c = &bus->console; -+ u8 line[CONSOLE_LINE_MAX], ch; -+ u32 n, idx, addr; -+ int rv; -+ -+ /* Don't do anything until FWREADY updates console address */ -+ if (bus->console_addr == 0) -+ return 0; -+ -+ /* Read console log struct */ -+ addr = bus->console_addr + offsetof(struct rte_console, log_le); -+ rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&c->log_le, -+ sizeof(c->log_le)); -+ if (rv < 0) -+ return rv; -+ -+ /* Allocate console buffer (one time only) */ -+ if (c->buf == NULL) { -+ c->bufsize = le32_to_cpu(c->log_le.buf_size); -+ c->buf = kmalloc(c->bufsize, GFP_ATOMIC); -+ if (c->buf == NULL) -+ return -ENOMEM; -+ } -+ -+ idx = le32_to_cpu(c->log_le.idx); -+ -+ /* Protect against corrupt value */ -+ if (idx > c->bufsize) -+ return -EBADE; -+ -+ /* Skip reading the console buffer if the index pointer -+ has not moved */ -+ if (idx == c->last) -+ return 0; -+ -+ /* Read the console buffer */ -+ addr = le32_to_cpu(c->log_le.buf); -+ rv = brcmf_sdbrcm_membytes(bus, false, addr, c->buf, c->bufsize); -+ if (rv < 0) -+ return rv; -+ -+ while (c->last != idx) { -+ for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) { -+ if (c->last == idx) { -+ /* This would output a partial line. -+ * Instead, back up -+ * the buffer pointer and output this -+ * line next time around. -+ */ -+ if (c->last >= n) -+ c->last -= n; -+ else -+ c->last = c->bufsize - n; -+ goto break2; -+ } -+ ch = c->buf[c->last]; -+ c->last = (c->last + 1) % c->bufsize; -+ if (ch == '\n') -+ break; -+ line[n] = ch; -+ } -+ -+ if (n > 0) { -+ if (line[n - 1] == '\r') -+ n--; -+ line[n] = 0; -+ printk(KERN_DEBUG "CONSOLE: %s\n", line); -+ } -+ } -+break2: -+ -+ return 0; -+} -+#endif /* BCMDBG */ -+ -+static int brcmf_tx_frame(struct brcmf_bus *bus, u8 *frame, u16 len) -+{ -+ int i; -+ int ret; -+ -+ bus->ctrl_frame_stat = false; -+ ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad, -+ SDIO_FUNC_2, F2SYNC, frame, len, NULL); -+ -+ if (ret < 0) { -+ /* On failure, abort the command and terminate the frame */ -+ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", -+ ret); -+ bus->tx_sderrs++; -+ -+ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); -+ -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_FRAMECTRL, -+ SFC_WF_TERM, NULL); -+ bus->f1regdata++; -+ -+ for (i = 0; i < 3; i++) { -+ u8 hi, lo; -+ hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_WFRAMEBCHI, -+ NULL); -+ lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_WFRAMEBCLO, -+ NULL); -+ bus->f1regdata += 2; -+ if (hi == 0 && lo == 0) -+ break; -+ } -+ return ret; -+ } -+ -+ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; -+ -+ return ret; -+} -+ -+int -+brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) -+{ -+ u8 *frame; -+ u16 len; -+ u32 swheader; -+ uint retries = 0; -+ u8 doff = 0; -+ int ret = -1; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* Back the pointer to make a room for bus header */ -+ frame = msg - SDPCM_HDRLEN; -+ len = (msglen += SDPCM_HDRLEN); -+ -+ /* Add alignment padding (optional for ctl frames) */ -+ doff = ((unsigned long)frame % BRCMF_SDALIGN); -+ if (doff) { -+ frame -= doff; -+ len += doff; -+ msglen += doff; -+ memset(frame, 0, doff + SDPCM_HDRLEN); -+ } -+ /* precondition: doff < BRCMF_SDALIGN */ -+ doff += SDPCM_HDRLEN; -+ -+ /* Round send length to next SDIO block */ -+ if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { -+ u16 pad = bus->blocksize - (len % bus->blocksize); -+ if ((pad <= bus->roundup) && (pad < bus->blocksize)) -+ len += pad; -+ } else if (len % BRCMF_SDALIGN) { -+ len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN); -+ } -+ -+ /* Satisfy length-alignment requirements */ -+ if (len & (ALIGNMENT - 1)) -+ len = roundup(len, ALIGNMENT); -+ -+ /* precondition: IS_ALIGNED((unsigned long)frame, 2) */ -+ -+ /* Need to lock here to protect txseq and SDIO tx calls */ -+ down(&bus->sdsem); -+ -+ bus_wake(bus); -+ -+ /* Make sure backplane clock is on */ -+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); -+ -+ /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ -+ *(__le16 *) frame = cpu_to_le16((u16) msglen); -+ *(((__le16 *) frame) + 1) = cpu_to_le16(~msglen); -+ -+ /* Software tag: channel, sequence number, data offset */ -+ swheader = -+ ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & -+ SDPCM_CHANNEL_MASK) -+ | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) & -+ SDPCM_DOFFSET_MASK); -+ put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN); -+ put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); -+ -+ if (!data_ok(bus)) { -+ brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n", -+ bus->tx_max, bus->tx_seq); -+ bus->ctrl_frame_stat = true; -+ /* Send from dpc */ -+ bus->ctrl_frame_buf = frame; -+ bus->ctrl_frame_len = len; -+ -+ brcmf_sdbrcm_wait_for_event(bus, &bus->ctrl_frame_stat); -+ -+ if (bus->ctrl_frame_stat == false) { -+ brcmf_dbg(INFO, "ctrl_frame_stat == false\n"); -+ ret = 0; -+ } else { -+ brcmf_dbg(INFO, "ctrl_frame_stat == true\n"); -+ ret = -1; -+ } -+ } -+ -+ if (ret == -1) { -+#ifdef BCMDBG -+ if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) { -+ printk(KERN_DEBUG "Tx Frame:\n"); -+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, -+ frame, len); -+ } else if (BRCMF_HDRS_ON()) { -+ printk(KERN_DEBUG "TxHdr:\n"); -+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, -+ frame, min_t(u16, len, 16)); -+ } -+#endif -+ -+ do { -+ ret = brcmf_tx_frame(bus, frame, len); -+ } while (ret < 0 && retries++ < TXRETRIES); -+ } -+ -+ if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) { -+ bus->activity = false; -+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); -+ } -+ -+ up(&bus->sdsem); -+ -+ if (ret) -+ bus->drvr->tx_ctlerrs++; -+ else -+ bus->drvr->tx_ctlpkts++; -+ -+ return ret ? -EIO : 0; -+} -+ -+int -+brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) -+{ -+ int timeleft; -+ uint rxlen = 0; -+ bool pending; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* Wait until control frame is available */ -+ timeleft = brcmf_sdbrcm_dcmd_resp_wait(bus, &bus->rxlen, &pending); -+ -+ down(&bus->sdsem); -+ rxlen = bus->rxlen; -+ memcpy(msg, bus->rxctl, min(msglen, rxlen)); -+ bus->rxlen = 0; -+ up(&bus->sdsem); -+ -+ if (rxlen) { -+ brcmf_dbg(CTL, "resumed on rxctl frame, got %d expected %d\n", -+ rxlen, msglen); -+ } else if (timeleft == 0) { -+ brcmf_dbg(ERROR, "resumed on timeout\n"); -+ } else if (pending == true) { -+ brcmf_dbg(CTL, "cancelled\n"); -+ return -ERESTARTSYS; -+ } else { -+ brcmf_dbg(CTL, "resumed for unknown reason?\n"); -+ } -+ -+ if (rxlen) -+ bus->drvr->rx_ctlpkts++; -+ else -+ bus->drvr->rx_ctlerrs++; -+ -+ return rxlen ? (int)rxlen : -ETIMEDOUT; -+} -+ -+static int brcmf_sdbrcm_downloadvars(struct brcmf_bus *bus, void *arg, int len) -+{ -+ int bcmerror = 0; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* Basic sanity checks */ -+ if (bus->drvr->up) { -+ bcmerror = -EISCONN; -+ goto err; -+ } -+ if (!len) { -+ bcmerror = -EOVERFLOW; -+ goto err; -+ } -+ -+ /* Free the old ones and replace with passed variables */ -+ kfree(bus->vars); -+ -+ bus->vars = kmalloc(len, GFP_ATOMIC); -+ bus->varsz = bus->vars ? len : 0; -+ if (bus->vars == NULL) { -+ bcmerror = -ENOMEM; -+ goto err; -+ } -+ -+ /* Copy the passed variables, which should include the -+ terminating double-null */ -+ memcpy(bus->vars, arg, bus->varsz); -+err: -+ return bcmerror; -+} -+ -+static int brcmf_sdbrcm_write_vars(struct brcmf_bus *bus) -+{ -+ int bcmerror = 0; -+ u32 varsize; -+ u32 varaddr; -+ u8 *vbuffer; -+ u32 varsizew; -+ __le32 varsizew_le; -+#ifdef BCMDBG -+ char *nvram_ularray; -+#endif /* BCMDBG */ -+ -+ /* Even if there are no vars are to be written, we still -+ need to set the ramsize. */ -+ varsize = bus->varsz ? roundup(bus->varsz, 4) : 0; -+ varaddr = (bus->ramsize - 4) - varsize; -+ -+ if (bus->vars) { -+ vbuffer = kzalloc(varsize, GFP_ATOMIC); -+ if (!vbuffer) -+ return -ENOMEM; -+ -+ memcpy(vbuffer, bus->vars, bus->varsz); -+ -+ /* Write the vars list */ -+ bcmerror = -+ brcmf_sdbrcm_membytes(bus, true, varaddr, vbuffer, varsize); -+#ifdef BCMDBG -+ /* Verify NVRAM bytes */ -+ brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n", varsize); -+ nvram_ularray = kmalloc(varsize, GFP_ATOMIC); -+ if (!nvram_ularray) -+ return -ENOMEM; -+ -+ /* Upload image to verify downloaded contents. */ -+ memset(nvram_ularray, 0xaa, varsize); -+ -+ /* Read the vars list to temp buffer for comparison */ -+ bcmerror = -+ brcmf_sdbrcm_membytes(bus, false, varaddr, nvram_ularray, -+ varsize); -+ if (bcmerror) { -+ brcmf_dbg(ERROR, "error %d on reading %d nvram bytes at 0x%08x\n", -+ bcmerror, varsize, varaddr); -+ } -+ /* Compare the org NVRAM with the one read from RAM */ -+ if (memcmp(vbuffer, nvram_ularray, varsize)) -+ brcmf_dbg(ERROR, "Downloaded NVRAM image is corrupted\n"); -+ else -+ brcmf_dbg(ERROR, "Download/Upload/Compare of NVRAM ok\n"); -+ -+ kfree(nvram_ularray); -+#endif /* BCMDBG */ -+ -+ kfree(vbuffer); -+ } -+ -+ /* adjust to the user specified RAM */ -+ brcmf_dbg(INFO, "Physical memory size: %d\n", bus->ramsize); -+ brcmf_dbg(INFO, "Vars are at %d, orig varsize is %d\n", -+ varaddr, varsize); -+ varsize = ((bus->ramsize - 4) - varaddr); -+ -+ /* -+ * Determine the length token: -+ * Varsize, converted to words, in lower 16-bits, checksum -+ * in upper 16-bits. -+ */ -+ if (bcmerror) { -+ varsizew = 0; -+ varsizew_le = cpu_to_le32(0); -+ } else { -+ varsizew = varsize / 4; -+ varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF); -+ varsizew_le = cpu_to_le32(varsizew); -+ } -+ -+ brcmf_dbg(INFO, "New varsize is %d, length token=0x%08x\n", -+ varsize, varsizew); -+ -+ /* Write the length token to the last word */ -+ bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->ramsize - 4), -+ (u8 *)&varsizew_le, 4); -+ -+ return bcmerror; -+} -+ -+static void -+brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_dev *sdiodev, u32 corebase) -+{ -+ u32 regdata; -+ -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(corebase, sbtmstatelow), 4); -+ if (regdata & SBTML_RESET) -+ return; -+ -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(corebase, sbtmstatelow), 4); -+ if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) { -+ /* -+ * set target reject and spin until busy is clear -+ * (preserve core-specific bits) -+ */ -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(corebase, sbtmstatelow), 4); -+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), -+ 4, regdata | SBTML_REJ); -+ -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(corebase, sbtmstatelow), 4); -+ udelay(1); -+ SPINWAIT((brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(corebase, sbtmstatehigh), 4) & -+ SBTMH_BUSY), 100000); -+ -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(corebase, sbtmstatehigh), 4); -+ if (regdata & SBTMH_BUSY) -+ brcmf_dbg(ERROR, "ARM core still busy\n"); -+ -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(corebase, sbidlow), 4); -+ if (regdata & SBIDL_INIT) { -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(corebase, sbimstate), 4) | -+ SBIM_RJ; -+ brcmf_sdcard_reg_write(sdiodev, -+ CORE_SB(corebase, sbimstate), 4, -+ regdata); -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(corebase, sbimstate), 4); -+ udelay(1); -+ SPINWAIT((brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(corebase, sbimstate), 4) & -+ SBIM_BY), 100000); -+ } -+ -+ /* set reset and reject while enabling the clocks */ -+ brcmf_sdcard_reg_write(sdiodev, -+ CORE_SB(corebase, sbtmstatelow), 4, -+ (((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | -+ SBTML_REJ | SBTML_RESET)); -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(corebase, sbtmstatelow), 4); -+ udelay(10); -+ -+ /* clear the initiator reject bit */ -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(corebase, sbidlow), 4); -+ if (regdata & SBIDL_INIT) { -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(corebase, sbimstate), 4) & -+ ~SBIM_RJ; -+ brcmf_sdcard_reg_write(sdiodev, -+ CORE_SB(corebase, sbimstate), 4, -+ regdata); -+ } -+ } -+ -+ /* leave reset and reject asserted */ -+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4, -+ (SBTML_REJ | SBTML_RESET)); -+ udelay(1); -+} -+ -+static void -+brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_dev *sdiodev, u32 corebase) -+{ -+ u32 regdata; -+ -+ /* -+ * Must do the disable sequence first to work for -+ * arbitrary current core state. -+ */ -+ brcmf_sdbrcm_chip_disablecore(sdiodev, corebase); -+ -+ /* -+ * Now do the initialization sequence. -+ * set reset while enabling the clock and -+ * forcing them on throughout the core -+ */ -+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4, -+ ((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | -+ SBTML_RESET); -+ udelay(1); -+ -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(corebase, sbtmstatehigh), 4); -+ if (regdata & SBTMH_SERR) -+ brcmf_sdcard_reg_write(sdiodev, -+ CORE_SB(corebase, sbtmstatehigh), 4, 0); -+ -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(corebase, sbimstate), 4); -+ if (regdata & (SBIM_IBE | SBIM_TO)) -+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbimstate), 4, -+ regdata & ~(SBIM_IBE | SBIM_TO)); -+ -+ /* clear reset and allow it to propagate throughout the core */ -+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4, -+ (SICF_FGC << SBTML_SICF_SHIFT) | -+ (SICF_CLOCK_EN << SBTML_SICF_SHIFT)); -+ udelay(1); -+ -+ /* leave clock enabled */ -+ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4, -+ (SICF_CLOCK_EN << SBTML_SICF_SHIFT)); -+ udelay(1); -+} -+ -+static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter) -+{ -+ uint retries; -+ u32 regdata; -+ int bcmerror = 0; -+ -+ /* To enter download state, disable ARM and reset SOCRAM. -+ * To exit download state, simply reset ARM (default is RAM boot). -+ */ -+ if (enter) { -+ bus->alp_only = true; -+ -+ brcmf_sdbrcm_chip_disablecore(bus->sdiodev, -+ bus->ci->armcorebase); -+ -+ brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->ramcorebase); -+ -+ /* Clear the top bit of memory */ -+ if (bus->ramsize) { -+ u32 zeros = 0; -+ brcmf_sdbrcm_membytes(bus, true, bus->ramsize - 4, -+ (u8 *)&zeros, 4); -+ } -+ } else { -+ regdata = brcmf_sdcard_reg_read(bus->sdiodev, -+ CORE_SB(bus->ci->ramcorebase, sbtmstatelow), 4); -+ regdata &= (SBTML_RESET | SBTML_REJ_MASK | -+ (SICF_CLOCK_EN << SBTML_SICF_SHIFT)); -+ if ((SICF_CLOCK_EN << SBTML_SICF_SHIFT) != regdata) { -+ brcmf_dbg(ERROR, "SOCRAM core is down after reset?\n"); -+ bcmerror = -EBADE; -+ goto fail; -+ } -+ -+ bcmerror = brcmf_sdbrcm_write_vars(bus); -+ if (bcmerror) { -+ brcmf_dbg(ERROR, "no vars written to RAM\n"); -+ bcmerror = 0; -+ } -+ -+ w_sdreg32(bus, 0xFFFFFFFF, -+ offsetof(struct sdpcmd_regs, intstatus), &retries); -+ -+ brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->armcorebase); -+ -+ /* Allow HT Clock now that the ARM is running. */ -+ bus->alp_only = false; -+ -+ bus->drvr->busstate = BRCMF_BUS_LOAD; -+ } -+fail: -+ return bcmerror; -+} -+ -+static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus) -+{ -+ if (bus->firmware->size < bus->fw_ptr + len) -+ len = bus->firmware->size - bus->fw_ptr; -+ -+ memcpy(buf, &bus->firmware->data[bus->fw_ptr], len); -+ bus->fw_ptr += len; -+ return len; -+} -+ -+MODULE_FIRMWARE(BCM4329_FW_NAME); -+MODULE_FIRMWARE(BCM4329_NV_NAME); -+ -+static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus) -+{ -+ int offset = 0; -+ uint len; -+ u8 *memblock = NULL, *memptr; -+ int ret; -+ -+ brcmf_dbg(INFO, "Enter\n"); -+ -+ bus->fw_name = BCM4329_FW_NAME; -+ ret = request_firmware(&bus->firmware, bus->fw_name, -+ &bus->sdiodev->func[2]->dev); -+ if (ret) { -+ brcmf_dbg(ERROR, "Fail to request firmware %d\n", ret); -+ return ret; -+ } -+ bus->fw_ptr = 0; -+ -+ memptr = memblock = kmalloc(MEMBLOCK + BRCMF_SDALIGN, GFP_ATOMIC); -+ if (memblock == NULL) { -+ ret = -ENOMEM; -+ goto err; -+ } -+ if ((u32)(unsigned long)memblock % BRCMF_SDALIGN) -+ memptr += (BRCMF_SDALIGN - -+ ((u32)(unsigned long)memblock % BRCMF_SDALIGN)); -+ -+ /* Download image */ -+ while ((len = -+ brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus))) { -+ ret = brcmf_sdbrcm_membytes(bus, true, offset, memptr, len); -+ if (ret) { -+ brcmf_dbg(ERROR, "error %d on writing %d membytes at 0x%08x\n", -+ ret, MEMBLOCK, offset); -+ goto err; -+ } -+ -+ offset += MEMBLOCK; -+ } -+ -+err: -+ kfree(memblock); -+ -+ release_firmware(bus->firmware); -+ bus->fw_ptr = 0; -+ -+ return ret; -+} -+ -+/* -+ * ProcessVars:Takes a buffer of "=\n" lines read from a file -+ * and ending in a NUL. -+ * Removes carriage returns, empty lines, comment lines, and converts -+ * newlines to NULs. -+ * Shortens buffer as needed and pads with NULs. End of buffer is marked -+ * by two NULs. -+*/ -+ -+static uint brcmf_process_nvram_vars(char *varbuf, uint len) -+{ -+ char *dp; -+ bool findNewline; -+ int column; -+ uint buf_len, n; -+ -+ dp = varbuf; -+ -+ findNewline = false; -+ column = 0; -+ -+ for (n = 0; n < len; n++) { -+ if (varbuf[n] == 0) -+ break; -+ if (varbuf[n] == '\r') -+ continue; -+ if (findNewline && varbuf[n] != '\n') -+ continue; -+ findNewline = false; -+ if (varbuf[n] == '#') { -+ findNewline = true; -+ continue; -+ } -+ if (varbuf[n] == '\n') { -+ if (column == 0) -+ continue; -+ *dp++ = 0; -+ column = 0; -+ continue; -+ } -+ *dp++ = varbuf[n]; -+ column++; -+ } -+ buf_len = dp - varbuf; -+ -+ while (dp < varbuf + n) -+ *dp++ = 0; -+ -+ return buf_len; -+} -+ -+static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus) -+{ -+ uint len; -+ char *memblock = NULL; -+ char *bufp; -+ int ret; -+ -+ bus->nv_name = BCM4329_NV_NAME; -+ ret = request_firmware(&bus->firmware, bus->nv_name, -+ &bus->sdiodev->func[2]->dev); -+ if (ret) { -+ brcmf_dbg(ERROR, "Fail to request nvram %d\n", ret); -+ return ret; -+ } -+ bus->fw_ptr = 0; -+ -+ memblock = kmalloc(MEMBLOCK, GFP_ATOMIC); -+ if (memblock == NULL) { -+ ret = -ENOMEM; -+ goto err; -+ } -+ -+ len = brcmf_sdbrcm_get_image(memblock, MEMBLOCK, bus); -+ -+ if (len > 0 && len < MEMBLOCK) { -+ bufp = (char *)memblock; -+ bufp[len] = 0; -+ len = brcmf_process_nvram_vars(bufp, len); -+ bufp += len; -+ *bufp++ = 0; -+ if (len) -+ ret = brcmf_sdbrcm_downloadvars(bus, memblock, len + 1); -+ if (ret) -+ brcmf_dbg(ERROR, "error downloading vars: %d\n", ret); -+ } else { -+ brcmf_dbg(ERROR, "error reading nvram file: %d\n", len); -+ ret = -EIO; -+ } -+ -+err: -+ kfree(memblock); -+ -+ release_firmware(bus->firmware); -+ bus->fw_ptr = 0; -+ -+ return ret; -+} -+ -+static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus) -+{ -+ int bcmerror = -1; -+ -+ /* Keep arm in reset */ -+ if (brcmf_sdbrcm_download_state(bus, true)) { -+ brcmf_dbg(ERROR, "error placing ARM core in reset\n"); -+ goto err; -+ } -+ -+ /* External image takes precedence if specified */ -+ if (brcmf_sdbrcm_download_code_file(bus)) { -+ brcmf_dbg(ERROR, "dongle image file download failed\n"); -+ goto err; -+ } -+ -+ /* External nvram takes precedence if specified */ -+ if (brcmf_sdbrcm_download_nvram(bus)) -+ brcmf_dbg(ERROR, "dongle nvram file download failed\n"); -+ -+ /* Take arm out of reset */ -+ if (brcmf_sdbrcm_download_state(bus, false)) { -+ brcmf_dbg(ERROR, "error getting out of ARM core reset\n"); -+ goto err; -+ } -+ -+ bcmerror = 0; -+ -+err: -+ return bcmerror; -+} -+ -+static bool -+brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus) -+{ -+ bool ret; -+ -+ /* Download the firmware */ -+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); -+ -+ ret = _brcmf_sdbrcm_download_firmware(bus) == 0; -+ -+ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); -+ -+ return ret; -+} -+ -+void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus) -+{ -+ u32 local_hostintmask; -+ u8 saveclk; -+ uint retries; -+ int err; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ if (bus->watchdog_tsk) { -+ send_sig(SIGTERM, bus->watchdog_tsk, 1); -+ kthread_stop(bus->watchdog_tsk); -+ bus->watchdog_tsk = NULL; -+ } -+ -+ if (bus->dpc_tsk && bus->dpc_tsk != current) { -+ send_sig(SIGTERM, bus->dpc_tsk, 1); -+ kthread_stop(bus->dpc_tsk); -+ bus->dpc_tsk = NULL; -+ } -+ -+ down(&bus->sdsem); -+ -+ bus_wake(bus); -+ -+ /* Enable clock for device interrupts */ -+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); -+ -+ /* Disable and clear interrupts at the chip level also */ -+ w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask), &retries); -+ local_hostintmask = bus->hostintmask; -+ bus->hostintmask = 0; -+ -+ /* Change our idea of bus state */ -+ bus->drvr->busstate = BRCMF_BUS_DOWN; -+ -+ /* Force clocks on backplane to be sure F2 interrupt propagates */ -+ saveclk = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, &err); -+ if (!err) { -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, -+ (saveclk | SBSDIO_FORCE_HT), &err); -+ } -+ if (err) -+ brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err); -+ -+ /* Turn off the bus (F2), free any pending packets */ -+ brcmf_dbg(INTR, "disable SDIO interrupts\n"); -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, -+ SDIO_FUNC_ENABLE_1, NULL); -+ -+ /* Clear any pending interrupts now that F2 is disabled */ -+ w_sdreg32(bus, local_hostintmask, -+ offsetof(struct sdpcmd_regs, intstatus), &retries); -+ -+ /* Turn off the backplane clock (only) */ -+ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); -+ -+ /* Clear the data packet queues */ -+ brcmu_pktq_flush(&bus->txq, true, NULL, NULL); -+ -+ /* Clear any held glomming stuff */ -+ if (bus->glomd) -+ brcmu_pkt_buf_free_skb(bus->glomd); -+ -+ if (bus->glom) -+ brcmu_pkt_buf_free_skb(bus->glom); -+ -+ bus->glom = bus->glomd = NULL; -+ -+ /* Clear rx control and wake any waiters */ -+ bus->rxlen = 0; -+ brcmf_sdbrcm_dcmd_resp_wake(bus); -+ -+ /* Reset some F2 state stuff */ -+ bus->rxskip = false; -+ bus->tx_seq = bus->rx_seq = 0; -+ -+ up(&bus->sdsem); -+} -+ -+int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr) -+{ -+ struct brcmf_bus *bus = drvr->bus; -+ unsigned long timeout; -+ uint retries = 0; -+ u8 ready, enable; -+ int err, ret = 0; -+ u8 saveclk; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* try to download image and nvram to the dongle */ -+ if (drvr->busstate == BRCMF_BUS_DOWN) { -+ if (!(brcmf_sdbrcm_download_firmware(bus))) -+ return -1; -+ } -+ -+ if (!bus->drvr) -+ return 0; -+ -+ /* Start the watchdog timer */ -+ bus->drvr->tickcnt = 0; -+ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); -+ -+ down(&bus->sdsem); -+ -+ /* Make sure backplane clock is on, needed to generate F2 interrupt */ -+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); -+ if (bus->clkstate != CLK_AVAIL) -+ goto exit; -+ -+ /* Force clocks on backplane to be sure F2 interrupt propagates */ -+ saveclk = -+ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, &err); -+ if (!err) { -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, -+ (saveclk | SBSDIO_FORCE_HT), &err); -+ } -+ if (err) { -+ brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err); -+ goto exit; -+ } -+ -+ /* Enable function 2 (frame transfers) */ -+ w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, -+ offsetof(struct sdpcmd_regs, tosbmailboxdata), &retries); -+ enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2); -+ -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, -+ enable, NULL); -+ -+ timeout = jiffies + msecs_to_jiffies(BRCMF_WAIT_F2RDY); -+ ready = 0; -+ while (enable != ready) { -+ ready = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_0, -+ SDIO_CCCR_IORx, NULL); -+ if (time_after(jiffies, timeout)) -+ break; -+ else if (time_after(jiffies, timeout - BRCMF_WAIT_F2RDY + 50)) -+ /* prevent busy waiting if it takes too long */ -+ msleep_interruptible(20); -+ } -+ -+ brcmf_dbg(INFO, "enable 0x%02x, ready 0x%02x\n", enable, ready); -+ -+ /* If F2 successfully enabled, set core and enable interrupts */ -+ if (ready == enable) { -+ /* Set up the interrupt mask and enable interrupts */ -+ bus->hostintmask = HOSTINTMASK; -+ w_sdreg32(bus, bus->hostintmask, -+ offsetof(struct sdpcmd_regs, hostintmask), &retries); -+ -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_WATERMARK, 8, &err); -+ -+ /* Set bus state according to enable result */ -+ drvr->busstate = BRCMF_BUS_DATA; -+ } -+ -+ else { -+ /* Disable F2 again */ -+ enable = SDIO_FUNC_ENABLE_1; -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, -+ SDIO_CCCR_IOEx, enable, NULL); -+ } -+ -+ /* Restore previous clock setting */ -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); -+ -+ /* If we didn't come up, turn off backplane clock */ -+ if (drvr->busstate != BRCMF_BUS_DATA) -+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); -+ -+exit: -+ up(&bus->sdsem); -+ -+ return ret; -+} -+ -+void brcmf_sdbrcm_isr(void *arg) -+{ -+ struct brcmf_bus *bus = (struct brcmf_bus *) arg; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ if (!bus) { -+ brcmf_dbg(ERROR, "bus is null pointer, exiting\n"); -+ return; -+ } -+ -+ if (bus->drvr->busstate == BRCMF_BUS_DOWN) { -+ brcmf_dbg(ERROR, "bus is down. we have nothing to do\n"); -+ return; -+ } -+ /* Count the interrupt call */ -+ bus->intrcount++; -+ bus->ipend = true; -+ -+ /* Shouldn't get this interrupt if we're sleeping? */ -+ if (bus->sleeping) { -+ brcmf_dbg(ERROR, "INTERRUPT WHILE SLEEPING??\n"); -+ return; -+ } -+ -+ /* Disable additional interrupts (is this needed now)? */ -+ if (!bus->intr) -+ brcmf_dbg(ERROR, "isr w/o interrupt configured!\n"); -+ -+ bus->dpc_sched = true; -+ if (bus->dpc_tsk) -+ complete(&bus->dpc_wait); -+} -+ -+static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr) -+{ -+ struct brcmf_bus *bus; -+ -+ brcmf_dbg(TIMER, "Enter\n"); -+ -+ bus = drvr->bus; -+ -+ /* Ignore the timer if simulating bus down */ -+ if (bus->sleeping) -+ return false; -+ -+ down(&bus->sdsem); -+ -+ /* Poll period: check device if appropriate. */ -+ if (bus->poll && (++bus->polltick >= bus->pollrate)) { -+ u32 intstatus = 0; -+ -+ /* Reset poll tick */ -+ bus->polltick = 0; -+ -+ /* Check device if no interrupts */ -+ if (!bus->intr || (bus->intrcount == bus->lastintrs)) { -+ -+ if (!bus->dpc_sched) { -+ u8 devpend; -+ devpend = brcmf_sdcard_cfg_read(bus->sdiodev, -+ SDIO_FUNC_0, SDIO_CCCR_INTx, -+ NULL); -+ intstatus = -+ devpend & (INTR_STATUS_FUNC1 | -+ INTR_STATUS_FUNC2); -+ } -+ -+ /* If there is something, make like the ISR and -+ schedule the DPC */ -+ if (intstatus) { -+ bus->pollcnt++; -+ bus->ipend = true; -+ -+ bus->dpc_sched = true; -+ if (bus->dpc_tsk) -+ complete(&bus->dpc_wait); -+ } -+ } -+ -+ /* Update interrupt tracking */ -+ bus->lastintrs = bus->intrcount; -+ } -+#ifdef BCMDBG -+ /* Poll for console output periodically */ -+ if (drvr->busstate == BRCMF_BUS_DATA && bus->console_interval != 0) { -+ bus->console.count += BRCMF_WD_POLL_MS; -+ if (bus->console.count >= bus->console_interval) { -+ bus->console.count -= bus->console_interval; -+ /* Make sure backplane clock is on */ -+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); -+ if (brcmf_sdbrcm_readconsole(bus) < 0) -+ /* stop on error */ -+ bus->console_interval = 0; -+ } -+ } -+#endif /* BCMDBG */ -+ -+ /* On idle timeout clear activity flag and/or turn off clock */ -+ if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { -+ if (++bus->idlecount >= bus->idletime) { -+ bus->idlecount = 0; -+ if (bus->activity) { -+ bus->activity = false; -+ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); -+ } else { -+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); -+ } -+ } -+ } -+ -+ up(&bus->sdsem); -+ -+ return bus->ipend; -+} -+ -+static bool brcmf_sdbrcm_chipmatch(u16 chipid) -+{ -+ if (chipid == BCM4329_CHIP_ID) -+ return true; -+ return false; -+} -+ -+static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus) -+{ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ kfree(bus->rxbuf); -+ bus->rxctl = bus->rxbuf = NULL; -+ bus->rxlen = 0; -+ -+ kfree(bus->databuf); -+ bus->databuf = NULL; -+} -+ -+static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus) -+{ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ if (bus->drvr->maxctl) { -+ bus->rxblen = -+ roundup((bus->drvr->maxctl + SDPCM_HDRLEN), -+ ALIGNMENT) + BRCMF_SDALIGN; -+ bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC); -+ if (!(bus->rxbuf)) -+ goto fail; -+ } -+ -+ /* Allocate buffer to receive glomed packet */ -+ bus->databuf = kmalloc(MAX_DATA_BUF, GFP_ATOMIC); -+ if (!(bus->databuf)) { -+ /* release rxbuf which was already located as above */ -+ if (!bus->rxblen) -+ kfree(bus->rxbuf); -+ goto fail; -+ } -+ -+ /* Align the buffer */ -+ if ((unsigned long)bus->databuf % BRCMF_SDALIGN) -+ bus->dataptr = bus->databuf + (BRCMF_SDALIGN - -+ ((unsigned long)bus->databuf % BRCMF_SDALIGN)); -+ else -+ bus->dataptr = bus->databuf; -+ -+ return true; -+ -+fail: -+ return false; -+} -+ -+/* SDIO Pad drive strength to select value mappings */ -+struct sdiod_drive_str { -+ u8 strength; /* Pad Drive Strength in mA */ -+ u8 sel; /* Chip-specific select value */ -+}; -+ -+/* SDIO Drive Strength to sel value table for PMU Rev 1 */ -+static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = { -+ { -+ 4, 0x2}, { -+ 2, 0x3}, { -+ 1, 0x0}, { -+ 0, 0x0} -+ }; -+ -+/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */ -+static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = { -+ { -+ 12, 0x7}, { -+ 10, 0x6}, { -+ 8, 0x5}, { -+ 6, 0x4}, { -+ 4, 0x2}, { -+ 2, 0x1}, { -+ 0, 0x0} -+ }; -+ -+/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */ -+static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = { -+ { -+ 32, 0x7}, { -+ 26, 0x6}, { -+ 22, 0x5}, { -+ 16, 0x4}, { -+ 12, 0x3}, { -+ 8, 0x2}, { -+ 4, 0x1}, { -+ 0, 0x0} -+ }; -+ -+#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) -+ -+static char *brcmf_chipname(uint chipid, char *buf, uint len) -+{ -+ const char *fmt; -+ -+ fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x"; -+ snprintf(buf, len, fmt, chipid); -+ return buf; -+} -+ -+static void brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus, -+ u32 drivestrength) { -+ struct sdiod_drive_str *str_tab = NULL; -+ u32 str_mask = 0; -+ u32 str_shift = 0; -+ char chn[8]; -+ -+ if (!(bus->ci->cccaps & CC_CAP_PMU)) -+ return; -+ -+ switch (SDIOD_DRVSTR_KEY(bus->ci->chip, bus->ci->pmurev)) { -+ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1): -+ str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1; -+ str_mask = 0x30000000; -+ str_shift = 28; -+ break; -+ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2): -+ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3): -+ str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2; -+ str_mask = 0x00003800; -+ str_shift = 11; -+ break; -+ case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8): -+ str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3; -+ str_mask = 0x00003800; -+ str_shift = 11; -+ break; -+ default: -+ brcmf_dbg(ERROR, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", -+ brcmf_chipname(bus->ci->chip, chn, 8), -+ bus->ci->chiprev, bus->ci->pmurev); -+ break; -+ } -+ -+ if (str_tab != NULL) { -+ u32 drivestrength_sel = 0; -+ u32 cc_data_temp; -+ int i; -+ -+ for (i = 0; str_tab[i].strength != 0; i++) { -+ if (drivestrength >= str_tab[i].strength) { -+ drivestrength_sel = str_tab[i].sel; -+ break; -+ } -+ } -+ -+ brcmf_sdcard_reg_write(bus->sdiodev, -+ CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), -+ 4, 1); -+ cc_data_temp = brcmf_sdcard_reg_read(bus->sdiodev, -+ CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), 4); -+ cc_data_temp &= ~str_mask; -+ drivestrength_sel <<= str_shift; -+ cc_data_temp |= drivestrength_sel; -+ brcmf_sdcard_reg_write(bus->sdiodev, -+ CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), -+ 4, cc_data_temp); -+ -+ brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n", -+ drivestrength, cc_data_temp); -+ } -+} -+ -+static int -+brcmf_sdbrcm_chip_recognition(struct brcmf_sdio_dev *sdiodev, -+ struct chip_info *ci, u32 regs) -+{ -+ u32 regdata; -+ -+ /* -+ * Get CC core rev -+ * Chipid is assume to be at offset 0 from regs arg -+ * For different chiptypes or old sdio hosts w/o chipcommon, -+ * other ways of recognition should be added here. -+ */ -+ ci->cccorebase = regs; -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_CC_REG(ci->cccorebase, chipid), 4); -+ ci->chip = regdata & CID_ID_MASK; -+ ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; -+ -+ brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev); -+ -+ /* Address of cores for new chips should be added here */ -+ switch (ci->chip) { -+ case BCM4329_CHIP_ID: -+ ci->buscorebase = BCM4329_CORE_BUS_BASE; -+ ci->ramcorebase = BCM4329_CORE_SOCRAM_BASE; -+ ci->armcorebase = BCM4329_CORE_ARM_BASE; -+ ci->ramsize = BCM4329_RAMSIZE; -+ break; -+ default: -+ brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip); -+ return -ENODEV; -+ } -+ -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(ci->cccorebase, sbidhigh), 4); -+ ci->ccrev = SBCOREREV(regdata); -+ -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_CC_REG(ci->cccorebase, pmucapabilities), 4); -+ ci->pmurev = regdata & PCAP_REV_MASK; -+ -+ regdata = brcmf_sdcard_reg_read(sdiodev, -+ CORE_SB(ci->buscorebase, sbidhigh), 4); -+ ci->buscorerev = SBCOREREV(regdata); -+ ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT; -+ -+ brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n", -+ ci->ccrev, ci->pmurev, ci->buscorerev, ci->buscoretype); -+ -+ /* get chipcommon capabilites */ -+ ci->cccaps = brcmf_sdcard_reg_read(sdiodev, -+ CORE_CC_REG(ci->cccorebase, capabilities), 4); -+ -+ return 0; -+} -+ -+static int -+brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs) -+{ -+ struct chip_info *ci; -+ int err; -+ u8 clkval, clkset; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* alloc chip_info_t */ -+ ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC); -+ if (NULL == ci) -+ return -ENOMEM; -+ -+ /* bus/core/clk setup for register access */ -+ /* Try forcing SDIO core to do ALPAvail request only */ -+ clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); -+ if (err) { -+ brcmf_dbg(ERROR, "error writing for HT off\n"); -+ goto fail; -+ } -+ -+ /* If register supported, wait for ALPAvail and then force ALP */ -+ /* This may take up to 15 milliseconds */ -+ clkval = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, NULL); -+ if ((clkval & ~SBSDIO_AVBITS) == clkset) { -+ SPINWAIT(((clkval = -+ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, -+ NULL)), -+ !SBSDIO_ALPAV(clkval)), -+ PMU_MAX_TRANSITION_DLY); -+ if (!SBSDIO_ALPAV(clkval)) { -+ brcmf_dbg(ERROR, "timeout on ALPAV wait, clkval 0x%02x\n", -+ clkval); -+ err = -EBUSY; -+ goto fail; -+ } -+ clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | -+ SBSDIO_FORCE_ALP; -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, -+ clkset, &err); -+ udelay(65); -+ } else { -+ brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n", -+ clkset, clkval); -+ err = -EACCES; -+ goto fail; -+ } -+ -+ /* Also, disable the extra SDIO pull-ups */ -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); -+ -+ err = brcmf_sdbrcm_chip_recognition(bus->sdiodev, ci, regs); -+ if (err) -+ goto fail; -+ -+ /* -+ * Make sure any on-chip ARM is off (in case strapping is wrong), -+ * or downloaded code was already running. -+ */ -+ brcmf_sdbrcm_chip_disablecore(bus->sdiodev, ci->armcorebase); -+ -+ brcmf_sdcard_reg_write(bus->sdiodev, -+ CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0); -+ brcmf_sdcard_reg_write(bus->sdiodev, -+ CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0); -+ -+ /* Disable F2 to clear any intermediate frame state on the dongle */ -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, -+ SDIO_FUNC_ENABLE_1, NULL); -+ -+ /* WAR: cmd52 backplane read so core HW will drop ALPReq */ -+ clkval = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, -+ 0, NULL); -+ -+ /* Done with backplane-dependent accesses, can drop clock... */ -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); -+ -+ bus->ci = ci; -+ return 0; -+fail: -+ bus->ci = NULL; -+ kfree(ci); -+ return err; -+} -+ -+static bool -+brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva) -+{ -+ u8 clkctl = 0; -+ int err = 0; -+ int reg_addr; -+ u32 reg_val; -+ -+ bus->alp_only = true; -+ -+ /* Return the window to backplane enumeration space for core access */ -+ if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, SI_ENUM_BASE)) -+ brcmf_dbg(ERROR, "FAILED to return to SI_ENUM_BASE\n"); -+ -+#ifdef BCMDBG -+ printk(KERN_DEBUG "F1 signature read @0x18000000=0x%4x\n", -+ brcmf_sdcard_reg_read(bus->sdiodev, SI_ENUM_BASE, 4)); -+ -+#endif /* BCMDBG */ -+ -+ /* -+ * Force PLL off until brcmf_sdbrcm_chip_attach() -+ * programs PLL control regs -+ */ -+ -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, -+ BRCMF_INIT_CLKCTL1, &err); -+ if (!err) -+ clkctl = -+ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, &err); -+ -+ if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) { -+ brcmf_dbg(ERROR, "ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n", -+ err, BRCMF_INIT_CLKCTL1, clkctl); -+ goto fail; -+ } -+ -+ if (brcmf_sdbrcm_chip_attach(bus, regsva)) { -+ brcmf_dbg(ERROR, "brcmf_sdbrcm_chip_attach failed!\n"); -+ goto fail; -+ } -+ -+ if (!brcmf_sdbrcm_chipmatch((u16) bus->ci->chip)) { -+ brcmf_dbg(ERROR, "unsupported chip: 0x%04x\n", bus->ci->chip); -+ goto fail; -+ } -+ -+ brcmf_sdbrcm_sdiod_drive_strength_init(bus, SDIO_DRIVE_STRENGTH); -+ -+ /* Get info on the ARM and SOCRAM cores... */ -+ brcmf_sdcard_reg_read(bus->sdiodev, -+ CORE_SB(bus->ci->armcorebase, sbidhigh), 4); -+ bus->ramsize = bus->ci->ramsize; -+ if (!(bus->ramsize)) { -+ brcmf_dbg(ERROR, "failed to find SOCRAM memory!\n"); -+ goto fail; -+ } -+ -+ /* Set core control so an SDIO reset does a backplane reset */ -+ reg_addr = bus->ci->buscorebase + -+ offsetof(struct sdpcmd_regs, corecontrol); -+ reg_val = brcmf_sdcard_reg_read(bus->sdiodev, reg_addr, sizeof(u32)); -+ brcmf_sdcard_reg_write(bus->sdiodev, reg_addr, sizeof(u32), -+ reg_val | CC_BPRESEN); -+ -+ brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN); -+ -+ /* Locate an appropriately-aligned portion of hdrbuf */ -+ bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0], -+ BRCMF_SDALIGN); -+ -+ /* Set the poll and/or interrupt flags */ -+ bus->intr = true; -+ bus->poll = false; -+ if (bus->poll) -+ bus->pollrate = 1; -+ -+ return true; -+ -+fail: -+ return false; -+} -+ -+static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus) -+{ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* Disable F2 to clear any intermediate frame state on the dongle */ -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, -+ SDIO_FUNC_ENABLE_1, NULL); -+ -+ bus->drvr->busstate = BRCMF_BUS_DOWN; -+ bus->sleeping = false; -+ bus->rxflow = false; -+ -+ /* Done with backplane-dependent accesses, can drop clock... */ -+ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, -+ SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); -+ -+ /* ...and initialize clock/power states */ -+ bus->clkstate = CLK_SDONLY; -+ bus->idletime = BRCMF_IDLE_INTERVAL; -+ bus->idleclock = BRCMF_IDLE_ACTIVE; -+ -+ /* Query the F2 block size, set roundup accordingly */ -+ bus->blocksize = bus->sdiodev->func[2]->cur_blksize; -+ bus->roundup = min(max_roundup, bus->blocksize); -+ -+ /* bus module does not support packet chaining */ -+ bus->use_rxchain = false; -+ bus->sd_rxchain = false; -+ -+ return true; -+} -+ -+static int -+brcmf_sdbrcm_watchdog_thread(void *data) -+{ -+ struct brcmf_bus *bus = (struct brcmf_bus *)data; -+ -+ allow_signal(SIGTERM); -+ /* Run until signal received */ -+ while (1) { -+ if (kthread_should_stop()) -+ break; -+ if (!wait_for_completion_interruptible(&bus->watchdog_wait)) { -+ brcmf_sdbrcm_bus_watchdog(bus->drvr); -+ /* Count the tick for reference */ -+ bus->drvr->tickcnt++; -+ } else -+ break; -+ } -+ return 0; -+} -+ -+static void -+brcmf_sdbrcm_watchdog(unsigned long data) -+{ -+ struct brcmf_bus *bus = (struct brcmf_bus *)data; -+ -+ if (bus->watchdog_tsk) { -+ complete(&bus->watchdog_wait); -+ /* Reschedule the watchdog */ -+ if (bus->wd_timer_valid) -+ mod_timer(&bus->timer, -+ jiffies + BRCMF_WD_POLL_MS * HZ / 1000); -+ } -+} -+ -+static void -+brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus) -+{ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ kfree(bus->ci); -+ bus->ci = NULL; -+} -+ -+static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus) -+{ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ if (bus->ci) { -+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); -+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); -+ brcmf_sdbrcm_chip_detach(bus); -+ if (bus->vars && bus->varsz) -+ kfree(bus->vars); -+ bus->vars = NULL; -+ } -+ -+ brcmf_dbg(TRACE, "Disconnected\n"); -+} -+ -+/* Detach and free everything */ -+static void brcmf_sdbrcm_release(struct brcmf_bus *bus) -+{ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ if (bus) { -+ /* De-register interrupt handler */ -+ brcmf_sdcard_intr_dereg(bus->sdiodev); -+ -+ if (bus->drvr) { -+ brcmf_detach(bus->drvr); -+ brcmf_sdbrcm_release_dongle(bus); -+ bus->drvr = NULL; -+ } -+ -+ brcmf_sdbrcm_release_malloc(bus); -+ -+ kfree(bus); -+ } -+ -+ brcmf_dbg(TRACE, "Disconnected\n"); -+} -+ -+void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype, -+ u32 regsva, struct brcmf_sdio_dev *sdiodev) -+{ -+ int ret; -+ struct brcmf_bus *bus; -+ -+ /* Init global variables at run-time, not as part of the declaration. -+ * This is required to support init/de-init of the driver. -+ * Initialization -+ * of globals as part of the declaration results in non-deterministic -+ * behavior since the value of the globals may be different on the -+ * first time that the driver is initialized vs subsequent -+ * initializations. -+ */ -+ brcmf_c_init(); -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ /* We make an assumption about address window mappings: -+ * regsva == SI_ENUM_BASE*/ -+ -+ /* Allocate private bus interface state */ -+ bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC); -+ if (!bus) -+ goto fail; -+ -+ bus->sdiodev = sdiodev; -+ sdiodev->bus = bus; -+ bus->txbound = BRCMF_TXBOUND; -+ bus->rxbound = BRCMF_RXBOUND; -+ bus->txminmax = BRCMF_TXMINMAX; -+ bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1; -+ bus->usebufpool = false; /* Use bufpool if allocated, -+ else use locally malloced rxbuf */ -+ -+ /* attempt to attach to the dongle */ -+ if (!(brcmf_sdbrcm_probe_attach(bus, regsva))) { -+ brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_attach failed\n"); -+ goto fail; -+ } -+ -+ spin_lock_init(&bus->txqlock); -+ init_waitqueue_head(&bus->ctrl_wait); -+ init_waitqueue_head(&bus->dcmd_resp_wait); -+ -+ /* Set up the watchdog timer */ -+ init_timer(&bus->timer); -+ bus->timer.data = (unsigned long)bus; -+ bus->timer.function = brcmf_sdbrcm_watchdog; -+ -+ /* Initialize thread based operation and lock */ -+ sema_init(&bus->sdsem, 1); -+ -+ /* Initialize watchdog thread */ -+ init_completion(&bus->watchdog_wait); -+ bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread, -+ bus, "brcmf_watchdog"); -+ if (IS_ERR(bus->watchdog_tsk)) { -+ printk(KERN_WARNING -+ "brcmf_watchdog thread failed to start\n"); -+ bus->watchdog_tsk = NULL; -+ } -+ /* Initialize DPC thread */ -+ init_completion(&bus->dpc_wait); -+ bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread, -+ bus, "brcmf_dpc"); -+ if (IS_ERR(bus->dpc_tsk)) { -+ printk(KERN_WARNING -+ "brcmf_dpc thread failed to start\n"); -+ bus->dpc_tsk = NULL; -+ } -+ -+ /* Attach to the brcmf/OS/network interface */ -+ bus->drvr = brcmf_attach(bus, SDPCM_RESERVE); -+ if (!bus->drvr) { -+ brcmf_dbg(ERROR, "brcmf_attach failed\n"); -+ goto fail; -+ } -+ -+ /* Allocate buffers */ -+ if (!(brcmf_sdbrcm_probe_malloc(bus))) { -+ brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_malloc failed\n"); -+ goto fail; -+ } -+ -+ if (!(brcmf_sdbrcm_probe_init(bus))) { -+ brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_init failed\n"); -+ goto fail; -+ } -+ -+ /* Register interrupt callback, but mask it (not operational yet). */ -+ brcmf_dbg(INTR, "disable SDIO interrupts (not interested yet)\n"); -+ ret = brcmf_sdcard_intr_reg(bus->sdiodev); -+ if (ret != 0) { -+ brcmf_dbg(ERROR, "FAILED: sdcard_intr_reg returned %d\n", ret); -+ goto fail; -+ } -+ brcmf_dbg(INTR, "registered SDIO interrupt function ok\n"); -+ -+ brcmf_dbg(INFO, "completed!!\n"); -+ -+ /* if firmware path present try to download and bring up bus */ -+ ret = brcmf_bus_start(bus->drvr); -+ if (ret != 0) { -+ if (ret == -ENOLINK) { -+ brcmf_dbg(ERROR, "dongle is not responding\n"); -+ goto fail; -+ } -+ } -+ /* Ok, have the per-port tell the stack we're open for business */ -+ if (brcmf_net_attach(bus->drvr, 0) != 0) { -+ brcmf_dbg(ERROR, "Net attach failed!!\n"); -+ goto fail; -+ } -+ -+ return bus; -+ -+fail: -+ brcmf_sdbrcm_release(bus); -+ return NULL; -+} -+ -+void brcmf_sdbrcm_disconnect(void *ptr) -+{ -+ struct brcmf_bus *bus = (struct brcmf_bus *)ptr; -+ -+ brcmf_dbg(TRACE, "Enter\n"); -+ -+ if (bus) -+ brcmf_sdbrcm_release(bus); -+ -+ brcmf_dbg(TRACE, "Disconnected\n"); -+} -+ -+struct device *brcmf_bus_get_device(struct brcmf_bus *bus) -+{ -+ return &bus->sdiodev->func[2]->dev; -+} -+ -+void -+brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick) -+{ -+ /* don't start the wd until fw is loaded */ -+ if (bus->drvr->busstate == BRCMF_BUS_DOWN) -+ return; -+ -+ /* Totally stop the timer */ -+ if (!wdtick && bus->wd_timer_valid == true) { -+ del_timer_sync(&bus->timer); -+ bus->wd_timer_valid = false; -+ bus->save_ms = wdtick; -+ return; -+ } -+ -+ if (wdtick) { -+ if (bus->save_ms != BRCMF_WD_POLL_MS) { -+ if (bus->wd_timer_valid == true) -+ /* Stop timer and restart at new value */ -+ del_timer_sync(&bus->timer); -+ -+ /* Create timer again when watchdog period is -+ dynamically changed or in the first instance -+ */ -+ bus->timer.expires = -+ jiffies + BRCMF_WD_POLL_MS * HZ / 1000; -+ add_timer(&bus->timer); -+ -+ } else { -+ /* Re arm the timer, at last watchdog period */ -+ mod_timer(&bus->timer, -+ jiffies + BRCMF_WD_POLL_MS * HZ / 1000); -+ } -+ -+ bus->wd_timer_valid = true; -+ bus->save_ms = wdtick; -+ } -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/Makefile.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/Makefile ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/Makefile.orig 2011-11-09 13:46:58.235800758 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/Makefile 2011-11-09 13:47:16.986566342 -0500 -@@ -0,0 +1,33 @@ -+# -+# Makefile fragment for Broadcom 802.11n Networking Device Driver -+# -+# Copyright (c) 2010 Broadcom Corporation -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ -+ccflags-y += \ -+ -Idrivers/net/wireless/brcm80211/brcmfmac \ -+ -Idrivers/net/wireless/brcm80211/include -+ -+DHDOFILES = \ -+ wl_cfg80211.o \ -+ dhd_cdc.o \ -+ dhd_common.o \ -+ dhd_sdio.o \ -+ dhd_linux.o \ -+ bcmsdh.o \ -+ bcmsdh_sdmmc.o -+ -+obj-$(CONFIG_BRCMFMAC) += brcmfmac.o -+brcmfmac-objs += $(DHDOFILES) -+ccflags-y += -D__CHECK_ENDIAN__ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h.orig 2011-11-09 13:46:58.235800758 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h 2011-11-09 13:47:16.987566330 -0500 -@@ -0,0 +1,252 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_SDH_H_ -+#define _BRCM_SDH_H_ -+ -+#include -+ -+#define SDIO_FUNC_0 0 -+#define SDIO_FUNC_1 1 -+#define SDIO_FUNC_2 2 -+ -+#define SDIOD_FBR_SIZE 0x100 -+ -+/* io_en */ -+#define SDIO_FUNC_ENABLE_1 0x02 -+#define SDIO_FUNC_ENABLE_2 0x04 -+ -+/* io_rdys */ -+#define SDIO_FUNC_READY_1 0x02 -+#define SDIO_FUNC_READY_2 0x04 -+ -+/* intr_status */ -+#define INTR_STATUS_FUNC1 0x2 -+#define INTR_STATUS_FUNC2 0x4 -+ -+/* Maximum number of I/O funcs */ -+#define SDIOD_MAX_IOFUNCS 7 -+ -+/* as of sdiod rev 0, supports 3 functions */ -+#define SBSDIO_NUM_FUNCTION 3 -+ -+/* function 1 miscellaneous registers */ -+ -+/* sprom command and status */ -+#define SBSDIO_SPROM_CS 0x10000 -+/* sprom info register */ -+#define SBSDIO_SPROM_INFO 0x10001 -+/* sprom indirect access data byte 0 */ -+#define SBSDIO_SPROM_DATA_LOW 0x10002 -+/* sprom indirect access data byte 1 */ -+#define SBSDIO_SPROM_DATA_HIGH 0x10003 -+/* sprom indirect access addr byte 0 */ -+#define SBSDIO_SPROM_ADDR_LOW 0x10004 -+/* sprom indirect access addr byte 0 */ -+#define SBSDIO_SPROM_ADDR_HIGH 0x10005 -+/* xtal_pu (gpio) output */ -+#define SBSDIO_CHIP_CTRL_DATA 0x10006 -+/* xtal_pu (gpio) enable */ -+#define SBSDIO_CHIP_CTRL_EN 0x10007 -+/* rev < 7, watermark for sdio device */ -+#define SBSDIO_WATERMARK 0x10008 -+/* control busy signal generation */ -+#define SBSDIO_DEVICE_CTL 0x10009 -+ -+/* SB Address Window Low (b15) */ -+#define SBSDIO_FUNC1_SBADDRLOW 0x1000A -+/* SB Address Window Mid (b23:b16) */ -+#define SBSDIO_FUNC1_SBADDRMID 0x1000B -+/* SB Address Window High (b31:b24) */ -+#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C -+/* Frame Control (frame term/abort) */ -+#define SBSDIO_FUNC1_FRAMECTRL 0x1000D -+/* ChipClockCSR (ALP/HT ctl/status) */ -+#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E -+/* SdioPullUp (on cmd, d0-d2) */ -+#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F -+/* Write Frame Byte Count Low */ -+#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019 -+/* Write Frame Byte Count High */ -+#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A -+/* Read Frame Byte Count Low */ -+#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B -+/* Read Frame Byte Count High */ -+#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C -+ -+#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */ -+#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */ -+ -+/* function 1 OCP space */ -+ -+/* sb offset addr is <= 15 bits, 32k */ -+#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF -+#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000 -+/* with b15, maps to 32-bit SB access */ -+#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 -+ -+/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */ -+ -+#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */ -+#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */ -+#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */ -+/* Address bits from SBADDR regs */ -+#define SBSDIO_SBWINDOW_MASK 0xffff8000 -+ -+#define SDIOH_READ 0 /* Read request */ -+#define SDIOH_WRITE 1 /* Write request */ -+ -+#define SDIOH_DATA_FIX 0 /* Fixed addressing */ -+#define SDIOH_DATA_INC 1 /* Incremental addressing */ -+ -+/* internal return code */ -+#define SUCCESS 0 -+#define ERROR 1 -+ -+struct brcmf_sdreg { -+ int func; -+ int offset; -+ int value; -+}; -+ -+struct brcmf_sdio_dev { -+ struct sdio_func *func[SDIO_MAX_FUNCS]; -+ u8 num_funcs; /* Supported funcs on client */ -+ u32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; -+ u32 sbwad; /* Save backplane window address */ -+ bool regfail; /* status of last reg_r/w call */ -+ void *bus; -+ atomic_t suspend; /* suspend flag */ -+ wait_queue_head_t request_byte_wait; -+ wait_queue_head_t request_word_wait; -+ wait_queue_head_t request_packet_wait; -+ wait_queue_head_t request_buffer_wait; -+ -+}; -+ -+/* Register/deregister device interrupt handler. */ -+extern int -+brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev); -+ -+extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev); -+ -+/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface). -+ * fn: function number -+ * addr: unmodified SDIO-space address -+ * data: data byte to write -+ * err: pointer to error code (or NULL) -+ */ -+extern u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint func, -+ u32 addr, int *err); -+extern void brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint func, -+ u32 addr, u8 data, int *err); -+ -+/* Synchronous access to device (client) core registers via CMD53 to F1. -+ * addr: backplane address (i.e. >= regsva from attach) -+ * size: register width in bytes (2 or 4) -+ * data: data for register write -+ */ -+extern u32 -+brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size); -+ -+extern u32 -+brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size, -+ u32 data); -+ -+/* Indicate if last reg read/write failed */ -+extern bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev); -+ -+/* Buffer transfer to/from device (client) core via cmd53. -+ * fn: function number -+ * addr: backplane address (i.e. >= regsva from attach) -+ * flags: backplane width, address increment, sync/async -+ * buf: pointer to memory data buffer -+ * nbytes: number of bytes to transfer to/from buf -+ * pkt: pointer to packet associated with buf (if any) -+ * complete: callback function for command completion (async only) -+ * handle: handle for completion callback (first arg in callback) -+ * Returns 0 or error code. -+ * NOTE: Async operation is not currently supported. -+ */ -+extern int -+brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, -+ uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt); -+extern int -+brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, -+ uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt); -+ -+/* Flags bits */ -+ -+/* Four-byte target (backplane) width (vs. two-byte) */ -+#define SDIO_REQ_4BYTE 0x1 -+/* Fixed address (FIFO) (vs. incrementing address) */ -+#define SDIO_REQ_FIXED 0x2 -+/* Async request (vs. sync request) */ -+#define SDIO_REQ_ASYNC 0x4 -+ -+/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only). -+ * rw: read or write (0/1) -+ * addr: direct SDIO address -+ * buf: pointer to memory data buffer -+ * nbytes: number of bytes to transfer to/from buf -+ * Returns 0 or error code. -+ */ -+extern int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, -+ u32 addr, u8 *buf, uint nbytes); -+ -+/* Issue an abort to the specified function */ -+extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn); -+ -+/* platform specific/high level functions */ -+extern int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev); -+extern int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev); -+ -+extern int brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, -+ u32 address); -+ -+/* attach, return handler on success, NULL if failed. -+ * The handler shall be provided by all subsequent calls. No local cache -+ * cfghdl points to the starting address of pci device mapped memory -+ */ -+extern int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev); -+extern void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev); -+ -+/* read or write one byte using cmd52 */ -+extern int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, -+ uint fnc, uint addr, u8 *byte); -+ -+/* read or write 2/4 bytes using cmd53 */ -+extern int -+brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, -+ uint rw, uint fnc, uint addr, -+ u32 *word, uint nbyte); -+ -+/* read or write any buffer using cmd53 */ -+extern int -+brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, -+ uint fix_inc, uint rw, uint fnc_num, -+ u32 addr, uint regwidth, -+ u32 buflen, u8 *buffer, struct sk_buff *pkt); -+ -+/* Watchdog timer interface for pm ops */ -+extern void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, -+ bool enable); -+ -+extern void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype, -+ u32 regsva, struct brcmf_sdio_dev *sdiodev); -+extern void brcmf_sdbrcm_disconnect(void *ptr); -+extern void brcmf_sdbrcm_isr(void *arg); -+#endif /* _BRCM_SDH_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c.orig 2011-11-09 13:46:58.237800734 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c 2011-11-09 13:47:16.989566304 -0500 -@@ -0,0 +1,3868 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include "dhd.h" -+#include "wl_cfg80211.h" -+ -+#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \ -+ (sizeof(struct brcmf_assoc_params_le) - sizeof(u16)) -+ -+static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255}; -+ -+static u32 brcmf_dbg_level = WL_DBG_ERR; -+ -+static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data) -+{ -+ dev->driver_data = data; -+} -+ -+static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev) -+{ -+ void *data = NULL; -+ -+ if (dev) -+ data = dev->driver_data; -+ return data; -+} -+ -+static -+struct brcmf_cfg80211_priv *brcmf_priv_get(struct brcmf_cfg80211_dev *cfg_dev) -+{ -+ struct brcmf_cfg80211_iface *ci = brcmf_get_drvdata(cfg_dev); -+ return ci->cfg_priv; -+} -+ -+static bool check_sys_up(struct wiphy *wiphy) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) { -+ WL_INFO("device is not ready : status (%d)\n", -+ (int)cfg_priv->status); -+ return false; -+ } -+ return true; -+} -+ -+#define CHAN2G(_channel, _freq, _flags) { \ -+ .band = IEEE80211_BAND_2GHZ, \ -+ .center_freq = (_freq), \ -+ .hw_value = (_channel), \ -+ .flags = (_flags), \ -+ .max_antenna_gain = 0, \ -+ .max_power = 30, \ -+} -+ -+#define CHAN5G(_channel, _flags) { \ -+ .band = IEEE80211_BAND_5GHZ, \ -+ .center_freq = 5000 + (5 * (_channel)), \ -+ .hw_value = (_channel), \ -+ .flags = (_flags), \ -+ .max_antenna_gain = 0, \ -+ .max_power = 30, \ -+} -+ -+#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2) -+#define RATETAB_ENT(_rateid, _flags) \ -+ { \ -+ .bitrate = RATE_TO_BASE100KBPS(_rateid), \ -+ .hw_value = (_rateid), \ -+ .flags = (_flags), \ -+ } -+ -+static struct ieee80211_rate __wl_rates[] = { -+ RATETAB_ENT(BRCM_RATE_1M, 0), -+ RATETAB_ENT(BRCM_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE), -+ RATETAB_ENT(BRCM_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE), -+ RATETAB_ENT(BRCM_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE), -+ RATETAB_ENT(BRCM_RATE_6M, 0), -+ RATETAB_ENT(BRCM_RATE_9M, 0), -+ RATETAB_ENT(BRCM_RATE_12M, 0), -+ RATETAB_ENT(BRCM_RATE_18M, 0), -+ RATETAB_ENT(BRCM_RATE_24M, 0), -+ RATETAB_ENT(BRCM_RATE_36M, 0), -+ RATETAB_ENT(BRCM_RATE_48M, 0), -+ RATETAB_ENT(BRCM_RATE_54M, 0), -+}; -+ -+#define wl_a_rates (__wl_rates + 4) -+#define wl_a_rates_size 8 -+#define wl_g_rates (__wl_rates + 0) -+#define wl_g_rates_size 12 -+ -+static struct ieee80211_channel __wl_2ghz_channels[] = { -+ CHAN2G(1, 2412, 0), -+ CHAN2G(2, 2417, 0), -+ CHAN2G(3, 2422, 0), -+ CHAN2G(4, 2427, 0), -+ CHAN2G(5, 2432, 0), -+ CHAN2G(6, 2437, 0), -+ CHAN2G(7, 2442, 0), -+ CHAN2G(8, 2447, 0), -+ CHAN2G(9, 2452, 0), -+ CHAN2G(10, 2457, 0), -+ CHAN2G(11, 2462, 0), -+ CHAN2G(12, 2467, 0), -+ CHAN2G(13, 2472, 0), -+ CHAN2G(14, 2484, 0), -+}; -+ -+static struct ieee80211_channel __wl_5ghz_a_channels[] = { -+ CHAN5G(34, 0), CHAN5G(36, 0), -+ CHAN5G(38, 0), CHAN5G(40, 0), -+ CHAN5G(42, 0), CHAN5G(44, 0), -+ CHAN5G(46, 0), CHAN5G(48, 0), -+ CHAN5G(52, 0), CHAN5G(56, 0), -+ CHAN5G(60, 0), CHAN5G(64, 0), -+ CHAN5G(100, 0), CHAN5G(104, 0), -+ CHAN5G(108, 0), CHAN5G(112, 0), -+ CHAN5G(116, 0), CHAN5G(120, 0), -+ CHAN5G(124, 0), CHAN5G(128, 0), -+ CHAN5G(132, 0), CHAN5G(136, 0), -+ CHAN5G(140, 0), CHAN5G(149, 0), -+ CHAN5G(153, 0), CHAN5G(157, 0), -+ CHAN5G(161, 0), CHAN5G(165, 0), -+ CHAN5G(184, 0), CHAN5G(188, 0), -+ CHAN5G(192, 0), CHAN5G(196, 0), -+ CHAN5G(200, 0), CHAN5G(204, 0), -+ CHAN5G(208, 0), CHAN5G(212, 0), -+ CHAN5G(216, 0), -+}; -+ -+static struct ieee80211_channel __wl_5ghz_n_channels[] = { -+ CHAN5G(32, 0), CHAN5G(34, 0), -+ CHAN5G(36, 0), CHAN5G(38, 0), -+ CHAN5G(40, 0), CHAN5G(42, 0), -+ CHAN5G(44, 0), CHAN5G(46, 0), -+ CHAN5G(48, 0), CHAN5G(50, 0), -+ CHAN5G(52, 0), CHAN5G(54, 0), -+ CHAN5G(56, 0), CHAN5G(58, 0), -+ CHAN5G(60, 0), CHAN5G(62, 0), -+ CHAN5G(64, 0), CHAN5G(66, 0), -+ CHAN5G(68, 0), CHAN5G(70, 0), -+ CHAN5G(72, 0), CHAN5G(74, 0), -+ CHAN5G(76, 0), CHAN5G(78, 0), -+ CHAN5G(80, 0), CHAN5G(82, 0), -+ CHAN5G(84, 0), CHAN5G(86, 0), -+ CHAN5G(88, 0), CHAN5G(90, 0), -+ CHAN5G(92, 0), CHAN5G(94, 0), -+ CHAN5G(96, 0), CHAN5G(98, 0), -+ CHAN5G(100, 0), CHAN5G(102, 0), -+ CHAN5G(104, 0), CHAN5G(106, 0), -+ CHAN5G(108, 0), CHAN5G(110, 0), -+ CHAN5G(112, 0), CHAN5G(114, 0), -+ CHAN5G(116, 0), CHAN5G(118, 0), -+ CHAN5G(120, 0), CHAN5G(122, 0), -+ CHAN5G(124, 0), CHAN5G(126, 0), -+ CHAN5G(128, 0), CHAN5G(130, 0), -+ CHAN5G(132, 0), CHAN5G(134, 0), -+ CHAN5G(136, 0), CHAN5G(138, 0), -+ CHAN5G(140, 0), CHAN5G(142, 0), -+ CHAN5G(144, 0), CHAN5G(145, 0), -+ CHAN5G(146, 0), CHAN5G(147, 0), -+ CHAN5G(148, 0), CHAN5G(149, 0), -+ CHAN5G(150, 0), CHAN5G(151, 0), -+ CHAN5G(152, 0), CHAN5G(153, 0), -+ CHAN5G(154, 0), CHAN5G(155, 0), -+ CHAN5G(156, 0), CHAN5G(157, 0), -+ CHAN5G(158, 0), CHAN5G(159, 0), -+ CHAN5G(160, 0), CHAN5G(161, 0), -+ CHAN5G(162, 0), CHAN5G(163, 0), -+ CHAN5G(164, 0), CHAN5G(165, 0), -+ CHAN5G(166, 0), CHAN5G(168, 0), -+ CHAN5G(170, 0), CHAN5G(172, 0), -+ CHAN5G(174, 0), CHAN5G(176, 0), -+ CHAN5G(178, 0), CHAN5G(180, 0), -+ CHAN5G(182, 0), CHAN5G(184, 0), -+ CHAN5G(186, 0), CHAN5G(188, 0), -+ CHAN5G(190, 0), CHAN5G(192, 0), -+ CHAN5G(194, 0), CHAN5G(196, 0), -+ CHAN5G(198, 0), CHAN5G(200, 0), -+ CHAN5G(202, 0), CHAN5G(204, 0), -+ CHAN5G(206, 0), CHAN5G(208, 0), -+ CHAN5G(210, 0), CHAN5G(212, 0), -+ CHAN5G(214, 0), CHAN5G(216, 0), -+ CHAN5G(218, 0), CHAN5G(220, 0), -+ CHAN5G(222, 0), CHAN5G(224, 0), -+ CHAN5G(226, 0), CHAN5G(228, 0), -+}; -+ -+static struct ieee80211_supported_band __wl_band_2ghz = { -+ .band = IEEE80211_BAND_2GHZ, -+ .channels = __wl_2ghz_channels, -+ .n_channels = ARRAY_SIZE(__wl_2ghz_channels), -+ .bitrates = wl_g_rates, -+ .n_bitrates = wl_g_rates_size, -+}; -+ -+static struct ieee80211_supported_band __wl_band_5ghz_a = { -+ .band = IEEE80211_BAND_5GHZ, -+ .channels = __wl_5ghz_a_channels, -+ .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels), -+ .bitrates = wl_a_rates, -+ .n_bitrates = wl_a_rates_size, -+}; -+ -+static struct ieee80211_supported_band __wl_band_5ghz_n = { -+ .band = IEEE80211_BAND_5GHZ, -+ .channels = __wl_5ghz_n_channels, -+ .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels), -+ .bitrates = wl_a_rates, -+ .n_bitrates = wl_a_rates_size, -+}; -+ -+static const u32 __wl_cipher_suites[] = { -+ WLAN_CIPHER_SUITE_WEP40, -+ WLAN_CIPHER_SUITE_WEP104, -+ WLAN_CIPHER_SUITE_TKIP, -+ WLAN_CIPHER_SUITE_CCMP, -+ WLAN_CIPHER_SUITE_AES_CMAC, -+}; -+ -+/* tag_ID/length/value_buffer tuple */ -+struct brcmf_tlv { -+ u8 id; -+ u8 len; -+ u8 data[1]; -+}; -+ -+/* Quarter dBm units to mW -+ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 -+ * Table is offset so the last entry is largest mW value that fits in -+ * a u16. -+ */ -+ -+#define QDBM_OFFSET 153 /* Offset for first entry */ -+#define QDBM_TABLE_LEN 40 /* Table size */ -+ -+/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. -+ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 -+ */ -+#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */ -+ -+/* Largest mW value that will round down to the last table entry, -+ * QDBM_OFFSET + QDBM_TABLE_LEN-1. -+ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + -+ * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. -+ */ -+#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ -+ -+static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = { -+/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ -+/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, -+/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, -+/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, -+/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, -+/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 -+}; -+ -+static u16 brcmf_qdbm_to_mw(u8 qdbm) -+{ -+ uint factor = 1; -+ int idx = qdbm - QDBM_OFFSET; -+ -+ if (idx >= QDBM_TABLE_LEN) -+ /* clamp to max u16 mW value */ -+ return 0xFFFF; -+ -+ /* scale the qdBm index up to the range of the table 0-40 -+ * where an offset of 40 qdBm equals a factor of 10 mW. -+ */ -+ while (idx < 0) { -+ idx += 40; -+ factor *= 10; -+ } -+ -+ /* return the mW value scaled down to the correct factor of 10, -+ * adding in factor/2 to get proper rounding. -+ */ -+ return (nqdBm_to_mW_map[idx] + factor / 2) / factor; -+} -+ -+static u8 brcmf_mw_to_qdbm(u16 mw) -+{ -+ u8 qdbm; -+ int offset; -+ uint mw_uint = mw; -+ uint boundary; -+ -+ /* handle boundary case */ -+ if (mw_uint <= 1) -+ return 0; -+ -+ offset = QDBM_OFFSET; -+ -+ /* move mw into the range of the table */ -+ while (mw_uint < QDBM_TABLE_LOW_BOUND) { -+ mw_uint *= 10; -+ offset -= 40; -+ } -+ -+ for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) { -+ boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] - -+ nqdBm_to_mW_map[qdbm]) / 2; -+ if (mw_uint < boundary) -+ break; -+ } -+ -+ qdbm += (u8) offset; -+ -+ return qdbm; -+} -+ -+/* function for reading/writing a single u32 from/to the dongle */ -+static int -+brcmf_exec_dcmd_u32(struct net_device *ndev, u32 cmd, u32 *par) -+{ -+ int err; -+ __le32 par_le = cpu_to_le32(*par); -+ -+ err = brcmf_exec_dcmd(ndev, cmd, &par_le, sizeof(__le32)); -+ *par = le32_to_cpu(par_le); -+ -+ return err; -+} -+ -+static void convert_key_from_CPU(struct brcmf_wsec_key *key, -+ struct brcmf_wsec_key_le *key_le) -+{ -+ key_le->index = cpu_to_le32(key->index); -+ key_le->len = cpu_to_le32(key->len); -+ key_le->algo = cpu_to_le32(key->algo); -+ key_le->flags = cpu_to_le32(key->flags); -+ key_le->rxiv.hi = cpu_to_le32(key->rxiv.hi); -+ key_le->rxiv.lo = cpu_to_le16(key->rxiv.lo); -+ key_le->iv_initialized = cpu_to_le32(key->iv_initialized); -+ memcpy(key_le->data, key->data, sizeof(key->data)); -+ memcpy(key_le->ea, key->ea, sizeof(key->ea)); -+} -+ -+static int send_key_to_dongle(struct net_device *ndev, -+ struct brcmf_wsec_key *key) -+{ -+ int err; -+ struct brcmf_wsec_key_le key_le; -+ -+ convert_key_from_CPU(key, &key_le); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le, sizeof(key_le)); -+ if (err) -+ WL_ERR("WLC_SET_KEY error (%d)\n", err); -+ return err; -+} -+ -+static s32 -+brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, -+ enum nl80211_iftype type, u32 *flags, -+ struct vif_params *params) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ struct wireless_dev *wdev; -+ s32 infra = 0; -+ s32 err = 0; -+ -+ WL_TRACE("Enter\n"); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ switch (type) { -+ case NL80211_IFTYPE_MONITOR: -+ case NL80211_IFTYPE_WDS: -+ WL_ERR("type (%d) : currently we do not support this type\n", -+ type); -+ return -EOPNOTSUPP; -+ case NL80211_IFTYPE_ADHOC: -+ cfg_priv->conf->mode = WL_MODE_IBSS; -+ infra = 0; -+ break; -+ case NL80211_IFTYPE_STATION: -+ cfg_priv->conf->mode = WL_MODE_BSS; -+ infra = 1; -+ break; -+ default: -+ err = -EINVAL; -+ goto done; -+ } -+ -+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); -+ if (err) { -+ WL_ERR("WLC_SET_INFRA error (%d)\n", err); -+ err = -EAGAIN; -+ } else { -+ wdev = ndev->ieee80211_ptr; -+ wdev->iftype = type; -+ } -+ -+ WL_INFO("IF Type = %s\n", -+ (cfg_priv->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra"); -+ -+done: -+ WL_TRACE("Exit\n"); -+ -+ return err; -+} -+ -+static s32 brcmf_dev_intvar_set(struct net_device *ndev, s8 *name, s32 val) -+{ -+ s8 buf[BRCMF_DCMD_SMLEN]; -+ u32 len; -+ s32 err = 0; -+ __le32 val_le; -+ -+ val_le = cpu_to_le32(val); -+ len = brcmf_c_mkiovar(name, (char *)(&val_le), sizeof(val_le), buf, -+ sizeof(buf)); -+ BUG_ON(!len); -+ -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len); -+ if (err) -+ WL_ERR("error (%d)\n", err); -+ -+ return err; -+} -+ -+static s32 -+brcmf_dev_intvar_get(struct net_device *ndev, s8 *name, s32 *retval) -+{ -+ union { -+ s8 buf[BRCMF_DCMD_SMLEN]; -+ __le32 val; -+ } var; -+ u32 len; -+ u32 data_null; -+ s32 err = 0; -+ -+ len = -+ brcmf_c_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), -+ sizeof(var.buf)); -+ BUG_ON(!len); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, &var, len); -+ if (err) -+ WL_ERR("error (%d)\n", err); -+ -+ *retval = le32_to_cpu(var.val); -+ -+ return err; -+} -+ -+static void brcmf_set_mpc(struct net_device *ndev, int mpc) -+{ -+ s32 err = 0; -+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); -+ -+ if (test_bit(WL_STATUS_READY, &cfg_priv->status)) { -+ err = brcmf_dev_intvar_set(ndev, "mpc", mpc); -+ if (err) { -+ WL_ERR("fail to set mpc\n"); -+ return; -+ } -+ WL_INFO("MPC : %d\n", mpc); -+ } -+} -+ -+static void wl_iscan_prep(struct brcmf_scan_params_le *params_le, -+ struct brcmf_ssid *ssid) -+{ -+ memcpy(params_le->bssid, ether_bcast, ETH_ALEN); -+ params_le->bss_type = DOT11_BSSTYPE_ANY; -+ params_le->scan_type = 0; -+ params_le->channel_num = 0; -+ params_le->nprobes = cpu_to_le32(-1); -+ params_le->active_time = cpu_to_le32(-1); -+ params_le->passive_time = cpu_to_le32(-1); -+ params_le->home_time = cpu_to_le32(-1); -+ if (ssid && ssid->SSID_len) -+ memcpy(¶ms_le->ssid_le, ssid, sizeof(struct brcmf_ssid)); -+} -+ -+static s32 -+brcmf_dev_iovar_setbuf(struct net_device *ndev, s8 * iovar, void *param, -+ s32 paramlen, void *bufptr, s32 buflen) -+{ -+ s32 iolen; -+ -+ iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen); -+ BUG_ON(!iolen); -+ -+ return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, bufptr, iolen); -+} -+ -+static s32 -+brcmf_dev_iovar_getbuf(struct net_device *ndev, s8 * iovar, void *param, -+ s32 paramlen, void *bufptr, s32 buflen) -+{ -+ s32 iolen; -+ -+ iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen); -+ BUG_ON(!iolen); -+ -+ return brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, bufptr, buflen); -+} -+ -+static s32 -+brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan, -+ struct brcmf_ssid *ssid, u16 action) -+{ -+ s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE + -+ offsetof(struct brcmf_iscan_params_le, params_le); -+ struct brcmf_iscan_params_le *params; -+ s32 err = 0; -+ -+ if (ssid && ssid->SSID_len) -+ params_size += sizeof(struct brcmf_ssid); -+ params = kzalloc(params_size, GFP_KERNEL); -+ if (!params) -+ return -ENOMEM; -+ BUG_ON(params_size >= BRCMF_DCMD_SMLEN); -+ -+ wl_iscan_prep(¶ms->params_le, ssid); -+ -+ params->version = cpu_to_le32(BRCMF_ISCAN_REQ_VERSION); -+ params->action = cpu_to_le16(action); -+ params->scan_duration = cpu_to_le16(0); -+ -+ err = brcmf_dev_iovar_setbuf(iscan->ndev, "iscan", params, params_size, -+ iscan->dcmd_buf, BRCMF_DCMD_SMLEN); -+ if (err) { -+ if (err == -EBUSY) -+ WL_INFO("system busy : iscan canceled\n"); -+ else -+ WL_ERR("error (%d)\n", err); -+ } -+ -+ kfree(params); -+ return err; -+} -+ -+static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); -+ struct net_device *ndev = cfg_to_ndev(cfg_priv); -+ struct brcmf_ssid ssid; -+ __le32 passive_scan; -+ s32 err = 0; -+ -+ /* Broadcast scan by default */ -+ memset(&ssid, 0, sizeof(ssid)); -+ -+ iscan->state = WL_ISCAN_STATE_SCANING; -+ -+ passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1); -+ err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN, -+ &passive_scan, sizeof(passive_scan)); -+ if (err) { -+ WL_ERR("error (%d)\n", err); -+ return err; -+ } -+ brcmf_set_mpc(ndev, 0); -+ cfg_priv->iscan_kickstart = true; -+ err = brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START); -+ if (err) { -+ brcmf_set_mpc(ndev, 1); -+ cfg_priv->iscan_kickstart = false; -+ return err; -+ } -+ mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); -+ iscan->timer_on = 1; -+ return err; -+} -+ -+static s32 -+__brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, -+ struct cfg80211_scan_request *request, -+ struct cfg80211_ssid *this_ssid) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); -+ struct cfg80211_ssid *ssids; -+ struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int; -+ __le32 passive_scan; -+ bool iscan_req; -+ bool spec_scan; -+ s32 err = 0; -+ u32 SSID_len; -+ -+ if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { -+ WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status); -+ return -EAGAIN; -+ } -+ if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) { -+ WL_ERR("Scanning being aborted : status (%lu)\n", -+ cfg_priv->status); -+ return -EAGAIN; -+ } -+ if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) { -+ WL_ERR("Connecting : status (%lu)\n", -+ cfg_priv->status); -+ return -EAGAIN; -+ } -+ -+ iscan_req = false; -+ spec_scan = false; -+ if (request) { -+ /* scan bss */ -+ ssids = request->ssids; -+ if (cfg_priv->iscan_on && (!ssids || !ssids->ssid_len)) -+ iscan_req = true; -+ } else { -+ /* scan in ibss */ -+ /* we don't do iscan in ibss */ -+ ssids = this_ssid; -+ } -+ -+ cfg_priv->scan_request = request; -+ set_bit(WL_STATUS_SCANNING, &cfg_priv->status); -+ if (iscan_req) { -+ err = brcmf_do_iscan(cfg_priv); -+ if (!err) -+ return err; -+ else -+ goto scan_out; -+ } else { -+ WL_SCAN("ssid \"%s\", ssid_len (%d)\n", -+ ssids->ssid, ssids->ssid_len); -+ memset(&sr->ssid_le, 0, sizeof(sr->ssid_le)); -+ SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len); -+ sr->ssid_le.SSID_len = cpu_to_le32(0); -+ if (SSID_len) { -+ memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len); -+ sr->ssid_le.SSID_len = cpu_to_le32(SSID_len); -+ spec_scan = true; -+ } else { -+ WL_SCAN("Broadcast scan\n"); -+ } -+ -+ passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN, -+ &passive_scan, sizeof(passive_scan)); -+ if (err) { -+ WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err); -+ goto scan_out; -+ } -+ brcmf_set_mpc(ndev, 0); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le, -+ sizeof(sr->ssid_le)); -+ if (err) { -+ if (err == -EBUSY) -+ WL_INFO("system busy : scan for \"%s\" " -+ "canceled\n", sr->ssid_le.SSID); -+ else -+ WL_ERR("WLC_SCAN error (%d)\n", err); -+ -+ brcmf_set_mpc(ndev, 1); -+ goto scan_out; -+ } -+ } -+ -+ return 0; -+ -+scan_out: -+ clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); -+ cfg_priv->scan_request = NULL; -+ return err; -+} -+ -+static s32 -+brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, -+ struct cfg80211_scan_request *request) -+{ -+ s32 err = 0; -+ -+ WL_TRACE("Enter\n"); -+ -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ err = __brcmf_cfg80211_scan(wiphy, ndev, request, NULL); -+ if (err) -+ WL_ERR("scan error (%d)\n", err); -+ -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold) -+{ -+ s32 err = 0; -+ -+ err = brcmf_dev_intvar_set(ndev, "rtsthresh", rts_threshold); -+ if (err) -+ WL_ERR("Error (%d)\n", err); -+ -+ return err; -+} -+ -+static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold) -+{ -+ s32 err = 0; -+ -+ err = brcmf_dev_intvar_set(ndev, "fragthresh", frag_threshold); -+ if (err) -+ WL_ERR("Error (%d)\n", err); -+ -+ return err; -+} -+ -+static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l) -+{ -+ s32 err = 0; -+ u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL); -+ -+ err = brcmf_exec_dcmd_u32(ndev, cmd, &retry); -+ if (err) { -+ WL_ERR("cmd (%d) , error (%d)\n", cmd, err); -+ return err; -+ } -+ return err; -+} -+ -+static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ struct net_device *ndev = cfg_to_ndev(cfg_priv); -+ s32 err = 0; -+ -+ WL_TRACE("Enter\n"); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ if (changed & WIPHY_PARAM_RTS_THRESHOLD && -+ (cfg_priv->conf->rts_threshold != wiphy->rts_threshold)) { -+ cfg_priv->conf->rts_threshold = wiphy->rts_threshold; -+ err = brcmf_set_rts(ndev, cfg_priv->conf->rts_threshold); -+ if (!err) -+ goto done; -+ } -+ if (changed & WIPHY_PARAM_FRAG_THRESHOLD && -+ (cfg_priv->conf->frag_threshold != wiphy->frag_threshold)) { -+ cfg_priv->conf->frag_threshold = wiphy->frag_threshold; -+ err = brcmf_set_frag(ndev, cfg_priv->conf->frag_threshold); -+ if (!err) -+ goto done; -+ } -+ if (changed & WIPHY_PARAM_RETRY_LONG -+ && (cfg_priv->conf->retry_long != wiphy->retry_long)) { -+ cfg_priv->conf->retry_long = wiphy->retry_long; -+ err = brcmf_set_retry(ndev, cfg_priv->conf->retry_long, true); -+ if (!err) -+ goto done; -+ } -+ if (changed & WIPHY_PARAM_RETRY_SHORT -+ && (cfg_priv->conf->retry_short != wiphy->retry_short)) { -+ cfg_priv->conf->retry_short = wiphy->retry_short; -+ err = brcmf_set_retry(ndev, cfg_priv->conf->retry_short, false); -+ if (!err) -+ goto done; -+ } -+ -+done: -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item) -+{ -+ switch (item) { -+ case WL_PROF_SEC: -+ return &cfg_priv->profile->sec; -+ case WL_PROF_BSSID: -+ return &cfg_priv->profile->bssid; -+ case WL_PROF_SSID: -+ return &cfg_priv->profile->ssid; -+ } -+ WL_ERR("invalid item (%d)\n", item); -+ return NULL; -+} -+ -+static s32 -+brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv, -+ const struct brcmf_event_msg *e, void *data, s32 item) -+{ -+ s32 err = 0; -+ struct brcmf_ssid *ssid; -+ -+ switch (item) { -+ case WL_PROF_SSID: -+ ssid = (struct brcmf_ssid *) data; -+ memset(cfg_priv->profile->ssid.SSID, 0, -+ sizeof(cfg_priv->profile->ssid.SSID)); -+ memcpy(cfg_priv->profile->ssid.SSID, -+ ssid->SSID, ssid->SSID_len); -+ cfg_priv->profile->ssid.SSID_len = ssid->SSID_len; -+ break; -+ case WL_PROF_BSSID: -+ if (data) -+ memcpy(cfg_priv->profile->bssid, data, ETH_ALEN); -+ else -+ memset(cfg_priv->profile->bssid, 0, ETH_ALEN); -+ break; -+ case WL_PROF_SEC: -+ memcpy(&cfg_priv->profile->sec, data, -+ sizeof(cfg_priv->profile->sec)); -+ break; -+ case WL_PROF_BEACONINT: -+ cfg_priv->profile->beacon_interval = *(u16 *)data; -+ break; -+ case WL_PROF_DTIMPERIOD: -+ cfg_priv->profile->dtim_period = *(u8 *)data; -+ break; -+ default: -+ WL_ERR("unsupported item (%d)\n", item); -+ err = -EOPNOTSUPP; -+ break; -+ } -+ -+ return err; -+} -+ -+static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof) -+{ -+ memset(prof, 0, sizeof(*prof)); -+} -+ -+static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params, -+ size_t *join_params_size) -+{ -+ u16 chanspec = 0; -+ -+ if (ch != 0) { -+ if (ch <= CH_MAX_2G_CHANNEL) -+ chanspec |= WL_CHANSPEC_BAND_2G; -+ else -+ chanspec |= WL_CHANSPEC_BAND_5G; -+ -+ chanspec |= WL_CHANSPEC_BW_20; -+ chanspec |= WL_CHANSPEC_CTL_SB_NONE; -+ -+ *join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE + -+ sizeof(u16); -+ -+ chanspec |= (ch & WL_CHANSPEC_CHAN_MASK); -+ join_params->params_le.chanspec_list[0] = cpu_to_le16(chanspec); -+ join_params->params_le.chanspec_num = cpu_to_le32(1); -+ -+ WL_CONN("join_params->params.chanspec_list[0]= %#X," -+ "channel %d, chanspec %#X\n", -+ chanspec, ch, chanspec); -+ } -+} -+ -+static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct net_device *ndev = NULL; -+ s32 err = 0; -+ -+ WL_TRACE("Enter\n"); -+ -+ if (cfg_priv->link_up) { -+ ndev = cfg_to_ndev(cfg_priv); -+ WL_INFO("Call WLC_DISASSOC to stop excess roaming\n "); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, NULL, 0); -+ if (err) -+ WL_ERR("WLC_DISASSOC failed (%d)\n", err); -+ cfg_priv->link_up = false; -+ } -+ WL_TRACE("Exit\n"); -+} -+ -+static s32 -+brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, -+ struct cfg80211_ibss_params *params) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ struct brcmf_join_params join_params; -+ size_t join_params_size = 0; -+ s32 err = 0; -+ s32 wsec = 0; -+ s32 bcnprd; -+ struct brcmf_ssid ssid; -+ -+ WL_TRACE("Enter\n"); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ if (params->ssid) -+ WL_CONN("SSID: %s\n", params->ssid); -+ else { -+ WL_CONN("SSID: NULL, Not supported\n"); -+ return -EOPNOTSUPP; -+ } -+ -+ set_bit(WL_STATUS_CONNECTING, &cfg_priv->status); -+ -+ if (params->bssid) -+ WL_CONN("BSSID: %02X %02X %02X %02X %02X %02X\n", -+ params->bssid[0], params->bssid[1], params->bssid[2], -+ params->bssid[3], params->bssid[4], params->bssid[5]); -+ else -+ WL_CONN("No BSSID specified\n"); -+ -+ if (params->channel) -+ WL_CONN("channel: %d\n", params->channel->center_freq); -+ else -+ WL_CONN("no channel specified\n"); -+ -+ if (params->channel_fixed) -+ WL_CONN("fixed channel required\n"); -+ else -+ WL_CONN("no fixed channel required\n"); -+ -+ if (params->ie && params->ie_len) -+ WL_CONN("ie len: %d\n", params->ie_len); -+ else -+ WL_CONN("no ie specified\n"); -+ -+ if (params->beacon_interval) -+ WL_CONN("beacon interval: %d\n", params->beacon_interval); -+ else -+ WL_CONN("no beacon interval specified\n"); -+ -+ if (params->basic_rates) -+ WL_CONN("basic rates: %08X\n", params->basic_rates); -+ else -+ WL_CONN("no basic rates specified\n"); -+ -+ if (params->privacy) -+ WL_CONN("privacy required\n"); -+ else -+ WL_CONN("no privacy required\n"); -+ -+ /* Configure Privacy for starter */ -+ if (params->privacy) -+ wsec |= WEP_ENABLED; -+ -+ err = brcmf_dev_intvar_set(ndev, "wsec", wsec); -+ if (err) { -+ WL_ERR("wsec failed (%d)\n", err); -+ goto done; -+ } -+ -+ /* Configure Beacon Interval for starter */ -+ if (params->beacon_interval) -+ bcnprd = params->beacon_interval; -+ else -+ bcnprd = 100; -+ -+ err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_BCNPRD, &bcnprd); -+ if (err) { -+ WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err); -+ goto done; -+ } -+ -+ /* Configure required join parameter */ -+ memset(&join_params, 0, sizeof(struct brcmf_join_params)); -+ -+ /* SSID */ -+ ssid.SSID_len = min_t(u32, params->ssid_len, 32); -+ memcpy(ssid.SSID, params->ssid, ssid.SSID_len); -+ memcpy(join_params.ssid_le.SSID, params->ssid, ssid.SSID_len); -+ join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len); -+ join_params_size = sizeof(join_params.ssid_le); -+ brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID); -+ -+ /* BSSID */ -+ if (params->bssid) { -+ memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN); -+ join_params_size = sizeof(join_params.ssid_le) + -+ BRCMF_ASSOC_PARAMS_FIXED_SIZE; -+ } else { -+ memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN); -+ } -+ -+ brcmf_update_prof(cfg_priv, NULL, -+ &join_params.params_le.bssid, WL_PROF_BSSID); -+ -+ /* Channel */ -+ if (params->channel) { -+ u32 target_channel; -+ -+ cfg_priv->channel = -+ ieee80211_frequency_to_channel( -+ params->channel->center_freq); -+ if (params->channel_fixed) { -+ /* adding chanspec */ -+ brcmf_ch_to_chanspec(cfg_priv->channel, -+ &join_params, &join_params_size); -+ } -+ -+ /* set channel for starter */ -+ target_channel = cfg_priv->channel; -+ err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_CHANNEL, -+ &target_channel); -+ if (err) { -+ WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err); -+ goto done; -+ } -+ } else -+ cfg_priv->channel = 0; -+ -+ cfg_priv->ibss_starter = false; -+ -+ -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, -+ &join_params, join_params_size); -+ if (err) { -+ WL_ERR("WLC_SET_SSID failed (%d)\n", err); -+ goto done; -+ } -+ -+done: -+ if (err) -+ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 -+brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ s32 err = 0; -+ -+ WL_TRACE("Enter\n"); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ brcmf_link_down(cfg_priv); -+ -+ WL_TRACE("Exit\n"); -+ -+ return err; -+} -+ -+static s32 brcmf_set_wpa_version(struct net_device *ndev, -+ struct cfg80211_connect_params *sme) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); -+ struct brcmf_cfg80211_security *sec; -+ s32 val = 0; -+ s32 err = 0; -+ -+ if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) -+ val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED; -+ else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) -+ val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; -+ else -+ val = WPA_AUTH_DISABLED; -+ WL_CONN("setting wpa_auth to 0x%0x\n", val); -+ err = brcmf_dev_intvar_set(ndev, "wpa_auth", val); -+ if (err) { -+ WL_ERR("set wpa_auth failed (%d)\n", err); -+ return err; -+ } -+ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); -+ sec->wpa_versions = sme->crypto.wpa_versions; -+ return err; -+} -+ -+static s32 brcmf_set_auth_type(struct net_device *ndev, -+ struct cfg80211_connect_params *sme) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); -+ struct brcmf_cfg80211_security *sec; -+ s32 val = 0; -+ s32 err = 0; -+ -+ switch (sme->auth_type) { -+ case NL80211_AUTHTYPE_OPEN_SYSTEM: -+ val = 0; -+ WL_CONN("open system\n"); -+ break; -+ case NL80211_AUTHTYPE_SHARED_KEY: -+ val = 1; -+ WL_CONN("shared key\n"); -+ break; -+ case NL80211_AUTHTYPE_AUTOMATIC: -+ val = 2; -+ WL_CONN("automatic\n"); -+ break; -+ case NL80211_AUTHTYPE_NETWORK_EAP: -+ WL_CONN("network eap\n"); -+ default: -+ val = 2; -+ WL_ERR("invalid auth type (%d)\n", sme->auth_type); -+ break; -+ } -+ -+ err = brcmf_dev_intvar_set(ndev, "auth", val); -+ if (err) { -+ WL_ERR("set auth failed (%d)\n", err); -+ return err; -+ } -+ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); -+ sec->auth_type = sme->auth_type; -+ return err; -+} -+ -+static s32 -+brcmf_set_set_cipher(struct net_device *ndev, -+ struct cfg80211_connect_params *sme) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); -+ struct brcmf_cfg80211_security *sec; -+ s32 pval = 0; -+ s32 gval = 0; -+ s32 err = 0; -+ -+ if (sme->crypto.n_ciphers_pairwise) { -+ switch (sme->crypto.ciphers_pairwise[0]) { -+ case WLAN_CIPHER_SUITE_WEP40: -+ case WLAN_CIPHER_SUITE_WEP104: -+ pval = WEP_ENABLED; -+ break; -+ case WLAN_CIPHER_SUITE_TKIP: -+ pval = TKIP_ENABLED; -+ break; -+ case WLAN_CIPHER_SUITE_CCMP: -+ pval = AES_ENABLED; -+ break; -+ case WLAN_CIPHER_SUITE_AES_CMAC: -+ pval = AES_ENABLED; -+ break; -+ default: -+ WL_ERR("invalid cipher pairwise (%d)\n", -+ sme->crypto.ciphers_pairwise[0]); -+ return -EINVAL; -+ } -+ } -+ if (sme->crypto.cipher_group) { -+ switch (sme->crypto.cipher_group) { -+ case WLAN_CIPHER_SUITE_WEP40: -+ case WLAN_CIPHER_SUITE_WEP104: -+ gval = WEP_ENABLED; -+ break; -+ case WLAN_CIPHER_SUITE_TKIP: -+ gval = TKIP_ENABLED; -+ break; -+ case WLAN_CIPHER_SUITE_CCMP: -+ gval = AES_ENABLED; -+ break; -+ case WLAN_CIPHER_SUITE_AES_CMAC: -+ gval = AES_ENABLED; -+ break; -+ default: -+ WL_ERR("invalid cipher group (%d)\n", -+ sme->crypto.cipher_group); -+ return -EINVAL; -+ } -+ } -+ -+ WL_CONN("pval (%d) gval (%d)\n", pval, gval); -+ err = brcmf_dev_intvar_set(ndev, "wsec", pval | gval); -+ if (err) { -+ WL_ERR("error (%d)\n", err); -+ return err; -+ } -+ -+ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); -+ sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0]; -+ sec->cipher_group = sme->crypto.cipher_group; -+ -+ return err; -+} -+ -+static s32 -+brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); -+ struct brcmf_cfg80211_security *sec; -+ s32 val = 0; -+ s32 err = 0; -+ -+ if (sme->crypto.n_akm_suites) { -+ err = brcmf_dev_intvar_get(ndev, "wpa_auth", &val); -+ if (err) { -+ WL_ERR("could not get wpa_auth (%d)\n", err); -+ return err; -+ } -+ if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { -+ switch (sme->crypto.akm_suites[0]) { -+ case WLAN_AKM_SUITE_8021X: -+ val = WPA_AUTH_UNSPECIFIED; -+ break; -+ case WLAN_AKM_SUITE_PSK: -+ val = WPA_AUTH_PSK; -+ break; -+ default: -+ WL_ERR("invalid cipher group (%d)\n", -+ sme->crypto.cipher_group); -+ return -EINVAL; -+ } -+ } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { -+ switch (sme->crypto.akm_suites[0]) { -+ case WLAN_AKM_SUITE_8021X: -+ val = WPA2_AUTH_UNSPECIFIED; -+ break; -+ case WLAN_AKM_SUITE_PSK: -+ val = WPA2_AUTH_PSK; -+ break; -+ default: -+ WL_ERR("invalid cipher group (%d)\n", -+ sme->crypto.cipher_group); -+ return -EINVAL; -+ } -+ } -+ -+ WL_CONN("setting wpa_auth to %d\n", val); -+ err = brcmf_dev_intvar_set(ndev, "wpa_auth", val); -+ if (err) { -+ WL_ERR("could not set wpa_auth (%d)\n", err); -+ return err; -+ } -+ } -+ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); -+ sec->wpa_auth = sme->crypto.akm_suites[0]; -+ -+ return err; -+} -+ -+static s32 -+brcmf_set_wep_sharedkey(struct net_device *ndev, -+ struct cfg80211_connect_params *sme) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); -+ struct brcmf_cfg80211_security *sec; -+ struct brcmf_wsec_key key; -+ s32 val; -+ s32 err = 0; -+ -+ WL_CONN("key len (%d)\n", sme->key_len); -+ -+ if (sme->key_len == 0) -+ return 0; -+ -+ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); -+ WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n", -+ sec->wpa_versions, sec->cipher_pairwise); -+ -+ if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) -+ return 0; -+ -+ if (sec->cipher_pairwise & -+ (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104)) { -+ memset(&key, 0, sizeof(key)); -+ key.len = (u32) sme->key_len; -+ key.index = (u32) sme->key_idx; -+ if (key.len > sizeof(key.data)) { -+ WL_ERR("Too long key length (%u)\n", key.len); -+ return -EINVAL; -+ } -+ memcpy(key.data, sme->key, key.len); -+ key.flags = BRCMF_PRIMARY_KEY; -+ switch (sec->cipher_pairwise) { -+ case WLAN_CIPHER_SUITE_WEP40: -+ key.algo = CRYPTO_ALGO_WEP1; -+ break; -+ case WLAN_CIPHER_SUITE_WEP104: -+ key.algo = CRYPTO_ALGO_WEP128; -+ break; -+ default: -+ WL_ERR("Invalid algorithm (%d)\n", -+ sme->crypto.ciphers_pairwise[0]); -+ return -EINVAL; -+ } -+ /* Set the new key/index */ -+ WL_CONN("key length (%d) key index (%d) algo (%d)\n", -+ key.len, key.index, key.algo); -+ WL_CONN("key \"%s\"\n", key.data); -+ err = send_key_to_dongle(ndev, &key); -+ if (err) -+ return err; -+ -+ if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) { -+ WL_CONN("set auth_type to shared key\n"); -+ val = 1; /* shared key */ -+ err = brcmf_dev_intvar_set(ndev, "auth", val); -+ if (err) { -+ WL_ERR("set auth failed (%d)\n", err); -+ return err; -+ } -+ } -+ } -+ return err; -+} -+ -+static s32 -+brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, -+ struct cfg80211_connect_params *sme) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ struct ieee80211_channel *chan = sme->channel; -+ struct brcmf_join_params join_params; -+ size_t join_params_size; -+ struct brcmf_ssid ssid; -+ -+ s32 err = 0; -+ -+ WL_TRACE("Enter\n"); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ if (!sme->ssid) { -+ WL_ERR("Invalid ssid\n"); -+ return -EOPNOTSUPP; -+ } -+ -+ set_bit(WL_STATUS_CONNECTING, &cfg_priv->status); -+ -+ if (chan) { -+ cfg_priv->channel = -+ ieee80211_frequency_to_channel(chan->center_freq); -+ WL_CONN("channel (%d), center_req (%d)\n", -+ cfg_priv->channel, chan->center_freq); -+ } else -+ cfg_priv->channel = 0; -+ -+ WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len); -+ -+ err = brcmf_set_wpa_version(ndev, sme); -+ if (err) { -+ WL_ERR("wl_set_wpa_version failed (%d)\n", err); -+ goto done; -+ } -+ -+ err = brcmf_set_auth_type(ndev, sme); -+ if (err) { -+ WL_ERR("wl_set_auth_type failed (%d)\n", err); -+ goto done; -+ } -+ -+ err = brcmf_set_set_cipher(ndev, sme); -+ if (err) { -+ WL_ERR("wl_set_set_cipher failed (%d)\n", err); -+ goto done; -+ } -+ -+ err = brcmf_set_key_mgmt(ndev, sme); -+ if (err) { -+ WL_ERR("wl_set_key_mgmt failed (%d)\n", err); -+ goto done; -+ } -+ -+ err = brcmf_set_wep_sharedkey(ndev, sme); -+ if (err) { -+ WL_ERR("brcmf_set_wep_sharedkey failed (%d)\n", err); -+ goto done; -+ } -+ -+ memset(&join_params, 0, sizeof(join_params)); -+ join_params_size = sizeof(join_params.ssid_le); -+ -+ ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), sme->ssid_len); -+ memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid.SSID_len); -+ memcpy(&ssid.SSID, sme->ssid, ssid.SSID_len); -+ join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len); -+ brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID); -+ -+ memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN); -+ -+ if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN) -+ WL_CONN("ssid \"%s\", len (%d)\n", -+ ssid.SSID, ssid.SSID_len); -+ -+ brcmf_ch_to_chanspec(cfg_priv->channel, -+ &join_params, &join_params_size); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, -+ &join_params, join_params_size); -+ if (err) -+ WL_ERR("WLC_SET_SSID failed (%d)\n", err); -+ -+done: -+ if (err) -+ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 -+brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, -+ u16 reason_code) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ struct brcmf_scb_val_le scbval; -+ s32 err = 0; -+ -+ WL_TRACE("Enter. Reason code = %d\n", reason_code); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ clear_bit(WL_STATUS_CONNECTED, &cfg_priv->status); -+ -+ memcpy(&scbval.ea, brcmf_read_prof(cfg_priv, WL_PROF_BSSID), ETH_ALEN); -+ scbval.val = cpu_to_le32(reason_code); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, &scbval, -+ sizeof(struct brcmf_scb_val_le)); -+ if (err) -+ WL_ERR("error (%d)\n", err); -+ -+ cfg_priv->link_up = false; -+ -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 -+brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, -+ enum nl80211_tx_power_setting type, s32 dbm) -+{ -+ -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ struct net_device *ndev = cfg_to_ndev(cfg_priv); -+ u16 txpwrmw; -+ s32 err = 0; -+ s32 disable = 0; -+ -+ WL_TRACE("Enter\n"); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ switch (type) { -+ case NL80211_TX_POWER_AUTOMATIC: -+ break; -+ case NL80211_TX_POWER_LIMITED: -+ if (dbm < 0) { -+ WL_ERR("TX_POWER_LIMITED - dbm is negative\n"); -+ err = -EINVAL; -+ goto done; -+ } -+ break; -+ case NL80211_TX_POWER_FIXED: -+ if (dbm < 0) { -+ WL_ERR("TX_POWER_FIXED - dbm is negative\n"); -+ err = -EINVAL; -+ goto done; -+ } -+ break; -+ } -+ /* Make sure radio is off or on as far as software is concerned */ -+ disable = WL_RADIO_SW_DISABLE << 16; -+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_RADIO, &disable); -+ if (err) -+ WL_ERR("WLC_SET_RADIO error (%d)\n", err); -+ -+ if (dbm > 0xffff) -+ txpwrmw = 0xffff; -+ else -+ txpwrmw = (u16) dbm; -+ err = brcmf_dev_intvar_set(ndev, "qtxpower", -+ (s32) (brcmf_mw_to_qdbm(txpwrmw))); -+ if (err) -+ WL_ERR("qtxpower error (%d)\n", err); -+ cfg_priv->conf->tx_power = dbm; -+ -+done: -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ struct net_device *ndev = cfg_to_ndev(cfg_priv); -+ s32 txpwrdbm; -+ u8 result; -+ s32 err = 0; -+ -+ WL_TRACE("Enter\n"); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ err = brcmf_dev_intvar_get(ndev, "qtxpower", &txpwrdbm); -+ if (err) { -+ WL_ERR("error (%d)\n", err); -+ goto done; -+ } -+ -+ result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE); -+ *dbm = (s32) brcmf_qdbm_to_mw(result); -+ -+done: -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 -+brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, -+ u8 key_idx, bool unicast, bool multicast) -+{ -+ u32 index; -+ u32 wsec; -+ s32 err = 0; -+ -+ WL_TRACE("Enter\n"); -+ WL_CONN("key index (%d)\n", key_idx); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec); -+ if (err) { -+ WL_ERR("WLC_GET_WSEC error (%d)\n", err); -+ goto done; -+ } -+ -+ if (wsec & WEP_ENABLED) { -+ /* Just select a new current key */ -+ index = key_idx; -+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_KEY_PRIMARY, -+ &index); -+ if (err) -+ WL_ERR("error (%d)\n", err); -+ } -+done: -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 -+brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, -+ u8 key_idx, const u8 *mac_addr, struct key_params *params) -+{ -+ struct brcmf_wsec_key key; -+ struct brcmf_wsec_key_le key_le; -+ s32 err = 0; -+ -+ memset(&key, 0, sizeof(key)); -+ key.index = (u32) key_idx; -+ /* Instead of bcast for ea address for default wep keys, -+ driver needs it to be Null */ -+ if (!is_multicast_ether_addr(mac_addr)) -+ memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN); -+ key.len = (u32) params->key_len; -+ /* check for key index change */ -+ if (key.len == 0) { -+ /* key delete */ -+ err = send_key_to_dongle(ndev, &key); -+ if (err) -+ return err; -+ } else { -+ if (key.len > sizeof(key.data)) { -+ WL_ERR("Invalid key length (%d)\n", key.len); -+ return -EINVAL; -+ } -+ -+ WL_CONN("Setting the key index %d\n", key.index); -+ memcpy(key.data, params->key, key.len); -+ -+ if (params->cipher == WLAN_CIPHER_SUITE_TKIP) { -+ u8 keybuf[8]; -+ memcpy(keybuf, &key.data[24], sizeof(keybuf)); -+ memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); -+ memcpy(&key.data[16], keybuf, sizeof(keybuf)); -+ } -+ -+ /* if IW_ENCODE_EXT_RX_SEQ_VALID set */ -+ if (params->seq && params->seq_len == 6) { -+ /* rx iv */ -+ u8 *ivptr; -+ ivptr = (u8 *) params->seq; -+ key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) | -+ (ivptr[3] << 8) | ivptr[2]; -+ key.rxiv.lo = (ivptr[1] << 8) | ivptr[0]; -+ key.iv_initialized = true; -+ } -+ -+ switch (params->cipher) { -+ case WLAN_CIPHER_SUITE_WEP40: -+ key.algo = CRYPTO_ALGO_WEP1; -+ WL_CONN("WLAN_CIPHER_SUITE_WEP40\n"); -+ break; -+ case WLAN_CIPHER_SUITE_WEP104: -+ key.algo = CRYPTO_ALGO_WEP128; -+ WL_CONN("WLAN_CIPHER_SUITE_WEP104\n"); -+ break; -+ case WLAN_CIPHER_SUITE_TKIP: -+ key.algo = CRYPTO_ALGO_TKIP; -+ WL_CONN("WLAN_CIPHER_SUITE_TKIP\n"); -+ break; -+ case WLAN_CIPHER_SUITE_AES_CMAC: -+ key.algo = CRYPTO_ALGO_AES_CCM; -+ WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n"); -+ break; -+ case WLAN_CIPHER_SUITE_CCMP: -+ key.algo = CRYPTO_ALGO_AES_CCM; -+ WL_CONN("WLAN_CIPHER_SUITE_CCMP\n"); -+ break; -+ default: -+ WL_ERR("Invalid cipher (0x%x)\n", params->cipher); -+ return -EINVAL; -+ } -+ convert_key_from_CPU(&key, &key_le); -+ -+ brcmf_netdev_wait_pend8021x(ndev); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le, -+ sizeof(key_le)); -+ if (err) { -+ WL_ERR("WLC_SET_KEY error (%d)\n", err); -+ return err; -+ } -+ } -+ return err; -+} -+ -+static s32 -+brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, -+ u8 key_idx, bool pairwise, const u8 *mac_addr, -+ struct key_params *params) -+{ -+ struct brcmf_wsec_key key; -+ s32 val; -+ s32 wsec; -+ s32 err = 0; -+ u8 keybuf[8]; -+ -+ WL_TRACE("Enter\n"); -+ WL_CONN("key index (%d)\n", key_idx); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ if (mac_addr) { -+ WL_TRACE("Exit"); -+ return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params); -+ } -+ memset(&key, 0, sizeof(key)); -+ -+ key.len = (u32) params->key_len; -+ key.index = (u32) key_idx; -+ -+ if (key.len > sizeof(key.data)) { -+ WL_ERR("Too long key length (%u)\n", key.len); -+ err = -EINVAL; -+ goto done; -+ } -+ memcpy(key.data, params->key, key.len); -+ -+ key.flags = BRCMF_PRIMARY_KEY; -+ switch (params->cipher) { -+ case WLAN_CIPHER_SUITE_WEP40: -+ key.algo = CRYPTO_ALGO_WEP1; -+ WL_CONN("WLAN_CIPHER_SUITE_WEP40\n"); -+ break; -+ case WLAN_CIPHER_SUITE_WEP104: -+ key.algo = CRYPTO_ALGO_WEP128; -+ WL_CONN("WLAN_CIPHER_SUITE_WEP104\n"); -+ break; -+ case WLAN_CIPHER_SUITE_TKIP: -+ memcpy(keybuf, &key.data[24], sizeof(keybuf)); -+ memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); -+ memcpy(&key.data[16], keybuf, sizeof(keybuf)); -+ key.algo = CRYPTO_ALGO_TKIP; -+ WL_CONN("WLAN_CIPHER_SUITE_TKIP\n"); -+ break; -+ case WLAN_CIPHER_SUITE_AES_CMAC: -+ key.algo = CRYPTO_ALGO_AES_CCM; -+ WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n"); -+ break; -+ case WLAN_CIPHER_SUITE_CCMP: -+ key.algo = CRYPTO_ALGO_AES_CCM; -+ WL_CONN("WLAN_CIPHER_SUITE_CCMP\n"); -+ break; -+ default: -+ WL_ERR("Invalid cipher (0x%x)\n", params->cipher); -+ err = -EINVAL; -+ goto done; -+ } -+ -+ err = send_key_to_dongle(ndev, &key); /* Set the new key/index */ -+ if (err) -+ goto done; -+ -+ val = WEP_ENABLED; -+ err = brcmf_dev_intvar_get(ndev, "wsec", &wsec); -+ if (err) { -+ WL_ERR("get wsec error (%d)\n", err); -+ goto done; -+ } -+ wsec &= ~(WEP_ENABLED); -+ wsec |= val; -+ err = brcmf_dev_intvar_set(ndev, "wsec", wsec); -+ if (err) { -+ WL_ERR("set wsec error (%d)\n", err); -+ goto done; -+ } -+ -+ val = 1; /* assume shared key. otherwise 0 */ -+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val); -+ if (err) -+ WL_ERR("WLC_SET_AUTH error (%d)\n", err); -+done: -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 -+brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, -+ u8 key_idx, bool pairwise, const u8 *mac_addr) -+{ -+ struct brcmf_wsec_key key; -+ s32 err = 0; -+ s32 val; -+ s32 wsec; -+ -+ WL_TRACE("Enter\n"); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ memset(&key, 0, sizeof(key)); -+ -+ key.index = (u32) key_idx; -+ key.flags = BRCMF_PRIMARY_KEY; -+ key.algo = CRYPTO_ALGO_OFF; -+ -+ WL_CONN("key index (%d)\n", key_idx); -+ -+ /* Set the new key/index */ -+ err = send_key_to_dongle(ndev, &key); -+ if (err) { -+ if (err == -EINVAL) { -+ if (key.index >= DOT11_MAX_DEFAULT_KEYS) -+ /* we ignore this key index in this case */ -+ WL_ERR("invalid key index (%d)\n", key_idx); -+ } -+ /* Ignore this error, may happen during DISASSOC */ -+ err = -EAGAIN; -+ goto done; -+ } -+ -+ val = 0; -+ err = brcmf_dev_intvar_get(ndev, "wsec", &wsec); -+ if (err) { -+ WL_ERR("get wsec error (%d)\n", err); -+ /* Ignore this error, may happen during DISASSOC */ -+ err = -EAGAIN; -+ goto done; -+ } -+ wsec &= ~(WEP_ENABLED); -+ wsec |= val; -+ err = brcmf_dev_intvar_set(ndev, "wsec", wsec); -+ if (err) { -+ WL_ERR("set wsec error (%d)\n", err); -+ /* Ignore this error, may happen during DISASSOC */ -+ err = -EAGAIN; -+ goto done; -+ } -+ -+ val = 0; /* assume open key. otherwise 1 */ -+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val); -+ if (err) { -+ WL_ERR("WLC_SET_AUTH error (%d)\n", err); -+ /* Ignore this error, may happen during DISASSOC */ -+ err = -EAGAIN; -+ } -+done: -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 -+brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, -+ u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie, -+ void (*callback) (void *cookie, struct key_params * params)) -+{ -+ struct key_params params; -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ struct brcmf_cfg80211_security *sec; -+ s32 wsec; -+ s32 err = 0; -+ -+ WL_TRACE("Enter\n"); -+ WL_CONN("key index (%d)\n", key_idx); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ memset(¶ms, 0, sizeof(params)); -+ -+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec); -+ if (err) { -+ WL_ERR("WLC_GET_WSEC error (%d)\n", err); -+ /* Ignore this error, may happen during DISASSOC */ -+ err = -EAGAIN; -+ goto done; -+ } -+ switch (wsec) { -+ case WEP_ENABLED: -+ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); -+ if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) { -+ params.cipher = WLAN_CIPHER_SUITE_WEP40; -+ WL_CONN("WLAN_CIPHER_SUITE_WEP40\n"); -+ } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) { -+ params.cipher = WLAN_CIPHER_SUITE_WEP104; -+ WL_CONN("WLAN_CIPHER_SUITE_WEP104\n"); -+ } -+ break; -+ case TKIP_ENABLED: -+ params.cipher = WLAN_CIPHER_SUITE_TKIP; -+ WL_CONN("WLAN_CIPHER_SUITE_TKIP\n"); -+ break; -+ case AES_ENABLED: -+ params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; -+ WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n"); -+ break; -+ default: -+ WL_ERR("Invalid algo (0x%x)\n", wsec); -+ err = -EINVAL; -+ goto done; -+ } -+ callback(cookie, ¶ms); -+ -+done: -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 -+brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, -+ struct net_device *ndev, u8 key_idx) -+{ -+ WL_INFO("Not supported\n"); -+ -+ return -EOPNOTSUPP; -+} -+ -+static s32 -+brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, -+ u8 *mac, struct station_info *sinfo) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ struct brcmf_scb_val_le scb_val; -+ int rssi; -+ s32 rate; -+ s32 err = 0; -+ u8 *bssid = brcmf_read_prof(cfg_priv, WL_PROF_BSSID); -+ -+ WL_TRACE("Enter\n"); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ if (memcmp(mac, bssid, ETH_ALEN)) { -+ WL_ERR("Wrong Mac address cfg_mac-%X:%X:%X:%X:%X:%X" -+ "wl_bssid-%X:%X:%X:%X:%X:%X\n", -+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], -+ bssid[0], bssid[1], bssid[2], bssid[3], -+ bssid[4], bssid[5]); -+ err = -ENOENT; -+ goto done; -+ } -+ -+ /* Report the current tx rate */ -+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate); -+ if (err) { -+ WL_ERR("Could not get rate (%d)\n", err); -+ } else { -+ sinfo->filled |= STATION_INFO_TX_BITRATE; -+ sinfo->txrate.legacy = rate * 5; -+ WL_CONN("Rate %d Mbps\n", rate / 2); -+ } -+ -+ if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) { -+ scb_val.val = cpu_to_le32(0); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val, -+ sizeof(struct brcmf_scb_val_le)); -+ if (err) -+ WL_ERR("Could not get rssi (%d)\n", err); -+ -+ rssi = le32_to_cpu(scb_val.val); -+ sinfo->filled |= STATION_INFO_SIGNAL; -+ sinfo->signal = rssi; -+ WL_CONN("RSSI %d dBm\n", rssi); -+ } -+ -+done: -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 -+brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, -+ bool enabled, s32 timeout) -+{ -+ s32 pm; -+ s32 err = 0; -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ -+ WL_TRACE("Enter\n"); -+ -+ /* -+ * Powersave enable/disable request is coming from the -+ * cfg80211 even before the interface is up. In that -+ * scenario, driver will be storing the power save -+ * preference in cfg_priv struct to apply this to -+ * FW later while initializing the dongle -+ */ -+ cfg_priv->pwr_save = enabled; -+ if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) { -+ -+ WL_INFO("Device is not ready," -+ "storing the value in cfg_priv struct\n"); -+ goto done; -+ } -+ -+ pm = enabled ? PM_FAST : PM_OFF; -+ WL_INFO("power save %s\n", (pm ? "enabled" : "disabled")); -+ -+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &pm); -+ if (err) { -+ if (err == -ENODEV) -+ WL_ERR("net_device is not ready yet\n"); -+ else -+ WL_ERR("error (%d)\n", err); -+ } -+done: -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 -+brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev, -+ const u8 *addr, -+ const struct cfg80211_bitrate_mask *mask) -+{ -+ struct brcm_rateset_le rateset_le; -+ s32 rate; -+ s32 val; -+ s32 err_bg; -+ s32 err_a; -+ u32 legacy; -+ s32 err = 0; -+ -+ WL_TRACE("Enter\n"); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ /* addr param is always NULL. ignore it */ -+ /* Get current rateset */ -+ err = brcmf_exec_dcmd(ndev, BRCM_GET_CURR_RATESET, &rateset_le, -+ sizeof(rateset_le)); -+ if (err) { -+ WL_ERR("could not get current rateset (%d)\n", err); -+ goto done; -+ } -+ -+ legacy = ffs(mask->control[IEEE80211_BAND_2GHZ].legacy & 0xFFFF); -+ if (!legacy) -+ legacy = ffs(mask->control[IEEE80211_BAND_5GHZ].legacy & -+ 0xFFFF); -+ -+ val = wl_g_rates[legacy - 1].bitrate * 100000; -+ -+ if (val < le32_to_cpu(rateset_le.count)) -+ /* Select rate by rateset index */ -+ rate = rateset_le.rates[val] & 0x7f; -+ else -+ /* Specified rate in bps */ -+ rate = val / 500000; -+ -+ WL_CONN("rate %d mbps\n", rate / 2); -+ -+ /* -+ * -+ * Set rate override, -+ * Since the is a/b/g-blind, both a/bg_rate are enforced. -+ */ -+ err_bg = brcmf_dev_intvar_set(ndev, "bg_rate", rate); -+ err_a = brcmf_dev_intvar_set(ndev, "a_rate", rate); -+ if (err_bg && err_a) { -+ WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a); -+ err = err_bg | err_a; -+ } -+ -+done: -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv, -+ struct brcmf_bss_info *bi) -+{ -+ struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); -+ struct ieee80211_channel *notify_channel; -+ struct cfg80211_bss *bss; -+ struct ieee80211_supported_band *band; -+ s32 err = 0; -+ u16 channel; -+ u32 freq; -+ u64 notify_timestamp; -+ u16 notify_capability; -+ u16 notify_interval; -+ u8 *notify_ie; -+ size_t notify_ielen; -+ s32 notify_signal; -+ -+ if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) { -+ WL_ERR("Bss info is larger than buffer. Discarding\n"); -+ return 0; -+ } -+ -+ channel = bi->ctl_ch ? bi->ctl_ch : -+ CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); -+ -+ if (channel <= CH_MAX_2G_CHANNEL) -+ band = wiphy->bands[IEEE80211_BAND_2GHZ]; -+ else -+ band = wiphy->bands[IEEE80211_BAND_5GHZ]; -+ -+ freq = ieee80211_channel_to_frequency(channel, band->band); -+ notify_channel = ieee80211_get_channel(wiphy, freq); -+ -+ notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */ -+ notify_capability = le16_to_cpu(bi->capability); -+ notify_interval = le16_to_cpu(bi->beacon_period); -+ notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset); -+ notify_ielen = le32_to_cpu(bi->ie_length); -+ notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100; -+ -+ WL_CONN("bssid: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", -+ bi->BSSID[0], bi->BSSID[1], bi->BSSID[2], -+ bi->BSSID[3], bi->BSSID[4], bi->BSSID[5]); -+ WL_CONN("Channel: %d(%d)\n", channel, freq); -+ WL_CONN("Capability: %X\n", notify_capability); -+ WL_CONN("Beacon interval: %d\n", notify_interval); -+ WL_CONN("Signal: %d\n", notify_signal); -+ WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp); -+ -+ bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID, -+ notify_timestamp, notify_capability, notify_interval, notify_ie, -+ notify_ielen, notify_signal, GFP_KERNEL); -+ -+ if (!bss) { -+ WL_ERR("cfg80211_inform_bss_frame error\n"); -+ return -EINVAL; -+ } -+ -+ return err; -+} -+ -+static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct brcmf_scan_results *bss_list; -+ struct brcmf_bss_info *bi = NULL; /* must be initialized */ -+ s32 err = 0; -+ int i; -+ -+ bss_list = cfg_priv->bss_list; -+ if (bss_list->version != BRCMF_BSS_INFO_VERSION) { -+ WL_ERR("Version %d != WL_BSS_INFO_VERSION\n", -+ bss_list->version); -+ return -EOPNOTSUPP; -+ } -+ WL_SCAN("scanned AP count (%d)\n", bss_list->count); -+ for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) { -+ bi = next_bss(bss_list, bi); -+ err = brcmf_inform_single_bss(cfg_priv, bi); -+ if (err) -+ break; -+ } -+ return err; -+} -+ -+static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv, -+ struct net_device *ndev, const u8 *bssid) -+{ -+ struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); -+ struct ieee80211_channel *notify_channel; -+ struct brcmf_bss_info *bi = NULL; -+ struct ieee80211_supported_band *band; -+ u8 *buf = NULL; -+ s32 err = 0; -+ u16 channel; -+ u32 freq; -+ u64 notify_timestamp; -+ u16 notify_capability; -+ u16 notify_interval; -+ u8 *notify_ie; -+ size_t notify_ielen; -+ s32 notify_signal; -+ -+ WL_TRACE("Enter\n"); -+ -+ buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); -+ if (buf == NULL) { -+ err = -ENOMEM; -+ goto CleanUp; -+ } -+ -+ *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX); -+ -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX); -+ if (err) { -+ WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err); -+ goto CleanUp; -+ } -+ -+ bi = (struct brcmf_bss_info *)(buf + 4); -+ -+ channel = bi->ctl_ch ? bi->ctl_ch : -+ CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); -+ -+ if (channel <= CH_MAX_2G_CHANNEL) -+ band = wiphy->bands[IEEE80211_BAND_2GHZ]; -+ else -+ band = wiphy->bands[IEEE80211_BAND_5GHZ]; -+ -+ freq = ieee80211_channel_to_frequency(channel, band->band); -+ notify_channel = ieee80211_get_channel(wiphy, freq); -+ -+ notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */ -+ notify_capability = le16_to_cpu(bi->capability); -+ notify_interval = le16_to_cpu(bi->beacon_period); -+ notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset); -+ notify_ielen = le32_to_cpu(bi->ie_length); -+ notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100; -+ -+ WL_CONN("channel: %d(%d)\n", channel, freq); -+ WL_CONN("capability: %X\n", notify_capability); -+ WL_CONN("beacon interval: %d\n", notify_interval); -+ WL_CONN("signal: %d\n", notify_signal); -+ WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp); -+ -+ cfg80211_inform_bss(wiphy, notify_channel, bssid, -+ notify_timestamp, notify_capability, notify_interval, -+ notify_ie, notify_ielen, notify_signal, GFP_KERNEL); -+ -+CleanUp: -+ -+ kfree(buf); -+ -+ WL_TRACE("Exit\n"); -+ -+ return err; -+} -+ -+static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ return cfg_priv->conf->mode == WL_MODE_IBSS; -+} -+ -+/* -+ * Traverse a string of 1-byte tag/1-byte length/variable-length value -+ * triples, returning a pointer to the substring whose first element -+ * matches tag -+ */ -+static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key) -+{ -+ struct brcmf_tlv *elt; -+ int totlen; -+ -+ elt = (struct brcmf_tlv *) buf; -+ totlen = buflen; -+ -+ /* find tagged parameter */ -+ while (totlen >= 2) { -+ int len = elt->len; -+ -+ /* validate remaining totlen */ -+ if ((elt->id == key) && (totlen >= (len + 2))) -+ return elt; -+ -+ elt = (struct brcmf_tlv *) ((u8 *) elt + (len + 2)); -+ totlen -= (len + 2); -+ } -+ -+ return NULL; -+} -+ -+static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct brcmf_bss_info *bi; -+ struct brcmf_ssid *ssid; -+ struct brcmf_tlv *tim; -+ u16 beacon_interval; -+ u8 dtim_period; -+ size_t ie_len; -+ u8 *ie; -+ s32 err = 0; -+ -+ WL_TRACE("Enter\n"); -+ if (brcmf_is_ibssmode(cfg_priv)) -+ return err; -+ -+ ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg_priv, WL_PROF_SSID); -+ -+ *(__le32 *)cfg_priv->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX); -+ err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_GET_BSS_INFO, -+ cfg_priv->extra_buf, WL_EXTRA_BUF_MAX); -+ if (err) { -+ WL_ERR("Could not get bss info %d\n", err); -+ goto update_bss_info_out; -+ } -+ -+ bi = (struct brcmf_bss_info *)(cfg_priv->extra_buf + 4); -+ err = brcmf_inform_single_bss(cfg_priv, bi); -+ if (err) -+ goto update_bss_info_out; -+ -+ ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset); -+ ie_len = le32_to_cpu(bi->ie_length); -+ beacon_interval = le16_to_cpu(bi->beacon_period); -+ -+ tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM); -+ if (tim) -+ dtim_period = tim->data[1]; -+ else { -+ /* -+ * active scan was done so we could not get dtim -+ * information out of probe response. -+ * so we speficially query dtim information to dongle. -+ */ -+ u32 var; -+ err = brcmf_dev_intvar_get(cfg_to_ndev(cfg_priv), -+ "dtim_assoc", &var); -+ if (err) { -+ WL_ERR("wl dtim_assoc failed (%d)\n", err); -+ goto update_bss_info_out; -+ } -+ dtim_period = (u8)var; -+ } -+ -+ brcmf_update_prof(cfg_priv, NULL, &beacon_interval, WL_PROF_BEACONINT); -+ brcmf_update_prof(cfg_priv, NULL, &dtim_period, WL_PROF_DTIMPERIOD); -+ -+update_bss_info_out: -+ WL_TRACE("Exit"); -+ return err; -+} -+ -+static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); -+ struct brcmf_ssid ssid; -+ -+ if (cfg_priv->iscan_on) { -+ iscan->state = WL_ISCAN_STATE_IDLE; -+ -+ if (iscan->timer_on) { -+ del_timer_sync(&iscan->timer); -+ iscan->timer_on = 0; -+ } -+ -+ cancel_work_sync(&iscan->work); -+ -+ /* Abort iscan running in FW */ -+ memset(&ssid, 0, sizeof(ssid)); -+ brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT); -+ } -+} -+ -+static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan, -+ bool aborted) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan); -+ struct net_device *ndev = cfg_to_ndev(cfg_priv); -+ -+ if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { -+ WL_ERR("Scan complete while device not scanning\n"); -+ return; -+ } -+ if (cfg_priv->scan_request) { -+ WL_SCAN("ISCAN Completed scan: %s\n", -+ aborted ? "Aborted" : "Done"); -+ cfg80211_scan_done(cfg_priv->scan_request, aborted); -+ brcmf_set_mpc(ndev, 1); -+ cfg_priv->scan_request = NULL; -+ } -+ cfg_priv->iscan_kickstart = false; -+} -+ -+static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan) -+{ -+ if (iscan->state != WL_ISCAN_STATE_IDLE) { -+ WL_SCAN("wake up iscan\n"); -+ schedule_work(&iscan->work); -+ return 0; -+ } -+ -+ return -EIO; -+} -+ -+static s32 -+brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status, -+ struct brcmf_scan_results **bss_list) -+{ -+ struct brcmf_iscan_results list; -+ struct brcmf_scan_results *results; -+ struct brcmf_scan_results_le *results_le; -+ struct brcmf_iscan_results *list_buf; -+ s32 err = 0; -+ -+ memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX); -+ list_buf = (struct brcmf_iscan_results *)iscan->scan_buf; -+ results = &list_buf->results; -+ results_le = &list_buf->results_le; -+ results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE; -+ results->version = 0; -+ results->count = 0; -+ -+ memset(&list, 0, sizeof(list)); -+ list.results_le.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX); -+ err = brcmf_dev_iovar_getbuf(iscan->ndev, "iscanresults", &list, -+ BRCMF_ISCAN_RESULTS_FIXED_SIZE, -+ iscan->scan_buf, WL_ISCAN_BUF_MAX); -+ if (err) { -+ WL_ERR("error (%d)\n", err); -+ return err; -+ } -+ results->buflen = le32_to_cpu(results_le->buflen); -+ results->version = le32_to_cpu(results_le->version); -+ results->count = le32_to_cpu(results_le->count); -+ WL_SCAN("results->count = %d\n", results_le->count); -+ WL_SCAN("results->buflen = %d\n", results_le->buflen); -+ *status = le32_to_cpu(list_buf->status_le); -+ WL_SCAN("status = %d\n", *status); -+ *bss_list = results; -+ -+ return err; -+} -+ -+static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; -+ s32 err = 0; -+ -+ iscan->state = WL_ISCAN_STATE_IDLE; -+ brcmf_inform_bss(cfg_priv); -+ brcmf_notify_iscan_complete(iscan, false); -+ -+ return err; -+} -+ -+static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; -+ s32 err = 0; -+ -+ /* Reschedule the timer */ -+ mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); -+ iscan->timer_on = 1; -+ -+ return err; -+} -+ -+static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; -+ s32 err = 0; -+ -+ brcmf_inform_bss(cfg_priv); -+ brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE); -+ /* Reschedule the timer */ -+ mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); -+ iscan->timer_on = 1; -+ -+ return err; -+} -+ -+static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; -+ s32 err = 0; -+ -+ iscan->state = WL_ISCAN_STATE_IDLE; -+ brcmf_notify_iscan_complete(iscan, true); -+ -+ return err; -+} -+ -+static void brcmf_cfg80211_iscan_handler(struct work_struct *work) -+{ -+ struct brcmf_cfg80211_iscan_ctrl *iscan = -+ container_of(work, struct brcmf_cfg80211_iscan_ctrl, -+ work); -+ struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan); -+ struct brcmf_cfg80211_iscan_eloop *el = &iscan->el; -+ u32 status = BRCMF_SCAN_RESULTS_PARTIAL; -+ -+ if (iscan->timer_on) { -+ del_timer_sync(&iscan->timer); -+ iscan->timer_on = 0; -+ } -+ -+ if (brcmf_get_iscan_results(iscan, &status, &cfg_priv->bss_list)) { -+ status = BRCMF_SCAN_RESULTS_ABORTED; -+ WL_ERR("Abort iscan\n"); -+ } -+ -+ el->handler[status](cfg_priv); -+} -+ -+static void brcmf_iscan_timer(unsigned long data) -+{ -+ struct brcmf_cfg80211_iscan_ctrl *iscan = -+ (struct brcmf_cfg80211_iscan_ctrl *)data; -+ -+ if (iscan) { -+ iscan->timer_on = 0; -+ WL_SCAN("timer expired\n"); -+ brcmf_wakeup_iscan(iscan); -+ } -+} -+ -+static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); -+ -+ if (cfg_priv->iscan_on) { -+ iscan->state = WL_ISCAN_STATE_IDLE; -+ INIT_WORK(&iscan->work, brcmf_cfg80211_iscan_handler); -+ } -+ -+ return 0; -+} -+ -+static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el) -+{ -+ memset(el, 0, sizeof(*el)); -+ el->handler[BRCMF_SCAN_RESULTS_SUCCESS] = brcmf_iscan_done; -+ el->handler[BRCMF_SCAN_RESULTS_PARTIAL] = brcmf_iscan_inprogress; -+ el->handler[BRCMF_SCAN_RESULTS_PENDING] = brcmf_iscan_pending; -+ el->handler[BRCMF_SCAN_RESULTS_ABORTED] = brcmf_iscan_aborted; -+ el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted; -+} -+ -+static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); -+ int err = 0; -+ -+ if (cfg_priv->iscan_on) { -+ iscan->ndev = cfg_to_ndev(cfg_priv); -+ brcmf_init_iscan_eloop(&iscan->el); -+ iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS; -+ init_timer(&iscan->timer); -+ iscan->timer.data = (unsigned long) iscan; -+ iscan->timer.function = brcmf_iscan_timer; -+ err = brcmf_invoke_iscan(cfg_priv); -+ if (!err) -+ iscan->data = cfg_priv; -+ } -+ -+ return err; -+} -+ -+static void brcmf_delay(u32 ms) -+{ -+ if (ms < 1000 / HZ) { -+ cond_resched(); -+ mdelay(ms); -+ } else { -+ msleep(ms); -+ } -+} -+ -+static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ -+ /* -+ * Check for WL_STATUS_READY before any function call which -+ * could result is bus access. Don't block the resume for -+ * any driver error conditions -+ */ -+ WL_TRACE("Enter\n"); -+ -+ if (test_bit(WL_STATUS_READY, &cfg_priv->status)) -+ brcmf_invoke_iscan(wiphy_to_cfg(wiphy)); -+ -+ WL_TRACE("Exit\n"); -+ return 0; -+} -+ -+static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, -+ struct cfg80211_wowlan *wow) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ struct net_device *ndev = cfg_to_ndev(cfg_priv); -+ -+ WL_TRACE("Enter\n"); -+ -+ /* -+ * Check for WL_STATUS_READY before any function call which -+ * could result is bus access. Don't block the suspend for -+ * any driver error conditions -+ */ -+ -+ /* -+ * While going to suspend if associated with AP disassociate -+ * from AP to save power while system is in suspended state -+ */ -+ if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) || -+ test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) && -+ test_bit(WL_STATUS_READY, &cfg_priv->status)) { -+ WL_INFO("Disassociating from AP" -+ " while entering suspend state\n"); -+ brcmf_link_down(cfg_priv); -+ -+ /* -+ * Make sure WPA_Supplicant receives all the event -+ * generated due to DISASSOC call to the fw to keep -+ * the state fw and WPA_Supplicant state consistent -+ */ -+ brcmf_delay(500); -+ } -+ -+ set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); -+ if (test_bit(WL_STATUS_READY, &cfg_priv->status)) -+ brcmf_term_iscan(cfg_priv); -+ -+ if (cfg_priv->scan_request) { -+ /* Indidate scan abort to cfg80211 layer */ -+ WL_INFO("Terminating scan in progress\n"); -+ cfg80211_scan_done(cfg_priv->scan_request, true); -+ cfg_priv->scan_request = NULL; -+ } -+ clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); -+ clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); -+ -+ /* Turn off watchdog timer */ -+ if (test_bit(WL_STATUS_READY, &cfg_priv->status)) { -+ WL_INFO("Enable MPC\n"); -+ brcmf_set_mpc(ndev, 1); -+ } -+ -+ WL_TRACE("Exit\n"); -+ -+ return 0; -+} -+ -+static __used s32 -+brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); -+ u32 buflen; -+ -+ buflen = brcmf_c_mkiovar(name, buf, len, cfg_priv->dcmd_buf, -+ WL_DCMD_LEN_MAX); -+ BUG_ON(!buflen); -+ -+ return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg_priv->dcmd_buf, -+ buflen); -+} -+ -+static s32 -+brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf, -+ s32 buf_len) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); -+ u32 len; -+ s32 err = 0; -+ -+ len = brcmf_c_mkiovar(name, NULL, 0, cfg_priv->dcmd_buf, -+ WL_DCMD_LEN_MAX); -+ BUG_ON(!len); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg_priv->dcmd_buf, -+ WL_DCMD_LEN_MAX); -+ if (err) { -+ WL_ERR("error (%d)\n", err); -+ return err; -+ } -+ memcpy(buf, cfg_priv->dcmd_buf, buf_len); -+ -+ return err; -+} -+ -+static __used s32 -+brcmf_update_pmklist(struct net_device *ndev, -+ struct brcmf_cfg80211_pmk_list *pmk_list, s32 err) -+{ -+ int i, j; -+ int pmkid_len; -+ -+ pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid); -+ -+ WL_CONN("No of elements %d\n", pmkid_len); -+ for (i = 0; i < pmkid_len; i++) { -+ WL_CONN("PMKID[%d]: %pM =\n", i, -+ &pmk_list->pmkids.pmkid[i].BSSID); -+ for (j = 0; j < WLAN_PMKID_LEN; j++) -+ WL_CONN("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]); -+ } -+ -+ if (!err) -+ brcmf_dev_bufvar_set(ndev, "pmkid_info", (char *)pmk_list, -+ sizeof(*pmk_list)); -+ -+ return err; -+} -+ -+static s32 -+brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, -+ struct cfg80211_pmksa *pmksa) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ struct pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids; -+ s32 err = 0; -+ int i; -+ int pmkid_len; -+ -+ WL_TRACE("Enter\n"); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ pmkid_len = le32_to_cpu(pmkids->npmkid); -+ for (i = 0; i < pmkid_len; i++) -+ if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN)) -+ break; -+ if (i < WL_NUM_PMKIDS_MAX) { -+ memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN); -+ memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN); -+ if (i == pmkid_len) { -+ pmkid_len++; -+ pmkids->npmkid = cpu_to_le32(pmkid_len); -+ } -+ } else -+ err = -EINVAL; -+ -+ WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n", -+ pmkids->pmkid[pmkid_len].BSSID); -+ for (i = 0; i < WLAN_PMKID_LEN; i++) -+ WL_CONN("%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]); -+ -+ err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err); -+ -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 -+brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, -+ struct cfg80211_pmksa *pmksa) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ struct pmkid_list pmkid; -+ s32 err = 0; -+ int i, pmkid_len; -+ -+ WL_TRACE("Enter\n"); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN); -+ memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN); -+ -+ WL_CONN("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n", -+ &pmkid.pmkid[0].BSSID); -+ for (i = 0; i < WLAN_PMKID_LEN; i++) -+ WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]); -+ -+ pmkid_len = le32_to_cpu(cfg_priv->pmk_list->pmkids.npmkid); -+ for (i = 0; i < pmkid_len; i++) -+ if (!memcmp -+ (pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID, -+ ETH_ALEN)) -+ break; -+ -+ if ((pmkid_len > 0) -+ && (i < pmkid_len)) { -+ memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0, -+ sizeof(struct pmkid)); -+ for (; i < (pmkid_len - 1); i++) { -+ memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID, -+ &cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID, -+ ETH_ALEN); -+ memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].PMKID, -+ &cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID, -+ WLAN_PMKID_LEN); -+ } -+ cfg_priv->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1); -+ } else -+ err = -EINVAL; -+ -+ err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err); -+ -+ WL_TRACE("Exit\n"); -+ return err; -+ -+} -+ -+static s32 -+brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); -+ s32 err = 0; -+ -+ WL_TRACE("Enter\n"); -+ if (!check_sys_up(wiphy)) -+ return -EIO; -+ -+ memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list)); -+ err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err); -+ -+ WL_TRACE("Exit\n"); -+ return err; -+ -+} -+ -+static struct cfg80211_ops wl_cfg80211_ops = { -+ .change_virtual_intf = brcmf_cfg80211_change_iface, -+ .scan = brcmf_cfg80211_scan, -+ .set_wiphy_params = brcmf_cfg80211_set_wiphy_params, -+ .join_ibss = brcmf_cfg80211_join_ibss, -+ .leave_ibss = brcmf_cfg80211_leave_ibss, -+ .get_station = brcmf_cfg80211_get_station, -+ .set_tx_power = brcmf_cfg80211_set_tx_power, -+ .get_tx_power = brcmf_cfg80211_get_tx_power, -+ .add_key = brcmf_cfg80211_add_key, -+ .del_key = brcmf_cfg80211_del_key, -+ .get_key = brcmf_cfg80211_get_key, -+ .set_default_key = brcmf_cfg80211_config_default_key, -+ .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key, -+ .set_power_mgmt = brcmf_cfg80211_set_power_mgmt, -+ .set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask, -+ .connect = brcmf_cfg80211_connect, -+ .disconnect = brcmf_cfg80211_disconnect, -+ .suspend = brcmf_cfg80211_suspend, -+ .resume = brcmf_cfg80211_resume, -+ .set_pmksa = brcmf_cfg80211_set_pmksa, -+ .del_pmksa = brcmf_cfg80211_del_pmksa, -+ .flush_pmksa = brcmf_cfg80211_flush_pmksa -+}; -+ -+static s32 brcmf_mode_to_nl80211_iftype(s32 mode) -+{ -+ s32 err = 0; -+ -+ switch (mode) { -+ case WL_MODE_BSS: -+ return NL80211_IFTYPE_STATION; -+ case WL_MODE_IBSS: -+ return NL80211_IFTYPE_ADHOC; -+ default: -+ return NL80211_IFTYPE_UNSPECIFIED; -+ } -+ -+ return err; -+} -+ -+static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface, -+ struct device *ndev) -+{ -+ struct wireless_dev *wdev; -+ s32 err = 0; -+ -+ wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); -+ if (!wdev) -+ return ERR_PTR(-ENOMEM); -+ -+ wdev->wiphy = -+ wiphy_new(&wl_cfg80211_ops, -+ sizeof(struct brcmf_cfg80211_priv) + sizeof_iface); -+ if (!wdev->wiphy) { -+ WL_ERR("Couldn not allocate wiphy device\n"); -+ err = -ENOMEM; -+ goto wiphy_new_out; -+ } -+ set_wiphy_dev(wdev->wiphy, ndev); -+ wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; -+ wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; -+ wdev->wiphy->interface_modes = -+ BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); -+ wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; -+ wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set -+ * it as 11a by default. -+ * This will be updated with -+ * 11n phy tables in -+ * "ifconfig up" -+ * if phy has 11n capability -+ */ -+ wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; -+ wdev->wiphy->cipher_suites = __wl_cipher_suites; -+ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); -+ wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power -+ * save mode -+ * by default -+ */ -+ err = wiphy_register(wdev->wiphy); -+ if (err < 0) { -+ WL_ERR("Couldn not register wiphy device (%d)\n", err); -+ goto wiphy_register_out; -+ } -+ return wdev; -+ -+wiphy_register_out: -+ wiphy_free(wdev->wiphy); -+ -+wiphy_new_out: -+ kfree(wdev); -+ -+ return ERR_PTR(err); -+} -+ -+static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct wireless_dev *wdev = cfg_priv->wdev; -+ -+ if (!wdev) { -+ WL_ERR("wdev is invalid\n"); -+ return; -+ } -+ wiphy_unregister(wdev->wiphy); -+ wiphy_free(wdev->wiphy); -+ kfree(wdev); -+ cfg_priv->wdev = NULL; -+} -+ -+static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv, -+ const struct brcmf_event_msg *e) -+{ -+ u32 event = be32_to_cpu(e->event_type); -+ u32 status = be32_to_cpu(e->status); -+ -+ if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) { -+ WL_CONN("Processing set ssid\n"); -+ cfg_priv->link_up = true; -+ return true; -+ } -+ -+ return false; -+} -+ -+static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv, -+ const struct brcmf_event_msg *e) -+{ -+ u32 event = be32_to_cpu(e->event_type); -+ u16 flags = be16_to_cpu(e->flags); -+ -+ if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) { -+ WL_CONN("Processing link down\n"); -+ return true; -+ } -+ return false; -+} -+ -+static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv, -+ const struct brcmf_event_msg *e) -+{ -+ u32 event = be32_to_cpu(e->event_type); -+ u32 status = be32_to_cpu(e->status); -+ -+ if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) { -+ WL_CONN("Processing Link %s & no network found\n", -+ be16_to_cpu(e->flags) & BRCMF_EVENT_MSG_LINK ? -+ "up" : "down"); -+ return true; -+ } -+ -+ if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) { -+ WL_CONN("Processing connecting & no network found\n"); -+ return true; -+ } -+ -+ return false; -+} -+ -+static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); -+ -+ kfree(conn_info->req_ie); -+ conn_info->req_ie = NULL; -+ conn_info->req_ie_len = 0; -+ kfree(conn_info->resp_ie); -+ conn_info->resp_ie = NULL; -+ conn_info->resp_ie_len = 0; -+} -+ -+static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct net_device *ndev = cfg_to_ndev(cfg_priv); -+ struct brcmf_cfg80211_assoc_ielen_le *assoc_info; -+ struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); -+ u32 req_len; -+ u32 resp_len; -+ s32 err = 0; -+ -+ brcmf_clear_assoc_ies(cfg_priv); -+ -+ err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg_priv->extra_buf, -+ WL_ASSOC_INFO_MAX); -+ if (err) { -+ WL_ERR("could not get assoc info (%d)\n", err); -+ return err; -+ } -+ assoc_info = -+ (struct brcmf_cfg80211_assoc_ielen_le *)cfg_priv->extra_buf; -+ req_len = le32_to_cpu(assoc_info->req_len); -+ resp_len = le32_to_cpu(assoc_info->resp_len); -+ if (req_len) { -+ err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies", -+ cfg_priv->extra_buf, -+ WL_ASSOC_INFO_MAX); -+ if (err) { -+ WL_ERR("could not get assoc req (%d)\n", err); -+ return err; -+ } -+ conn_info->req_ie_len = req_len; -+ conn_info->req_ie = -+ kmemdup(cfg_priv->extra_buf, conn_info->req_ie_len, -+ GFP_KERNEL); -+ } else { -+ conn_info->req_ie_len = 0; -+ conn_info->req_ie = NULL; -+ } -+ if (resp_len) { -+ err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies", -+ cfg_priv->extra_buf, -+ WL_ASSOC_INFO_MAX); -+ if (err) { -+ WL_ERR("could not get assoc resp (%d)\n", err); -+ return err; -+ } -+ conn_info->resp_ie_len = resp_len; -+ conn_info->resp_ie = -+ kmemdup(cfg_priv->extra_buf, conn_info->resp_ie_len, -+ GFP_KERNEL); -+ } else { -+ conn_info->resp_ie_len = 0; -+ conn_info->resp_ie = NULL; -+ } -+ WL_CONN("req len (%d) resp len (%d)\n", -+ conn_info->req_ie_len, conn_info->resp_ie_len); -+ -+ return err; -+} -+ -+static s32 -+brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv, -+ struct net_device *ndev, -+ const struct brcmf_event_msg *e) -+{ -+ struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); -+ struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); -+ struct brcmf_channel_info_le channel_le; -+ struct ieee80211_channel *notify_channel; -+ struct ieee80211_supported_band *band; -+ u32 freq; -+ s32 err = 0; -+ u32 target_channel; -+ -+ WL_TRACE("Enter\n"); -+ -+ brcmf_get_assoc_ies(cfg_priv); -+ brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID); -+ brcmf_update_bss_info(cfg_priv); -+ -+ brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le, -+ sizeof(channel_le)); -+ -+ target_channel = le32_to_cpu(channel_le.target_channel); -+ WL_CONN("Roamed to channel %d\n", target_channel); -+ -+ if (target_channel <= CH_MAX_2G_CHANNEL) -+ band = wiphy->bands[IEEE80211_BAND_2GHZ]; -+ else -+ band = wiphy->bands[IEEE80211_BAND_5GHZ]; -+ -+ freq = ieee80211_channel_to_frequency(target_channel, band->band); -+ notify_channel = ieee80211_get_channel(wiphy, freq); -+ -+ cfg80211_roamed(ndev, notify_channel, -+ (u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID), -+ conn_info->req_ie, conn_info->req_ie_len, -+ conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); -+ WL_CONN("Report roaming result\n"); -+ -+ set_bit(WL_STATUS_CONNECTED, &cfg_priv->status); -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 -+brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv, -+ struct net_device *ndev, const struct brcmf_event_msg *e, -+ bool completed) -+{ -+ struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); -+ s32 err = 0; -+ -+ WL_TRACE("Enter\n"); -+ -+ if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) { -+ if (completed) { -+ brcmf_get_assoc_ies(cfg_priv); -+ brcmf_update_prof(cfg_priv, NULL, &e->addr, -+ WL_PROF_BSSID); -+ brcmf_update_bss_info(cfg_priv); -+ } -+ cfg80211_connect_result(ndev, -+ (u8 *)brcmf_read_prof(cfg_priv, -+ WL_PROF_BSSID), -+ conn_info->req_ie, -+ conn_info->req_ie_len, -+ conn_info->resp_ie, -+ conn_info->resp_ie_len, -+ completed ? WLAN_STATUS_SUCCESS : -+ WLAN_STATUS_AUTH_TIMEOUT, -+ GFP_KERNEL); -+ if (completed) -+ set_bit(WL_STATUS_CONNECTED, &cfg_priv->status); -+ WL_CONN("Report connect result - connection %s\n", -+ completed ? "succeeded" : "failed"); -+ } -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 -+brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv, -+ struct net_device *ndev, -+ const struct brcmf_event_msg *e, void *data) -+{ -+ s32 err = 0; -+ -+ if (brcmf_is_linkup(cfg_priv, e)) { -+ WL_CONN("Linkup\n"); -+ if (brcmf_is_ibssmode(cfg_priv)) { -+ brcmf_update_prof(cfg_priv, NULL, (void *)e->addr, -+ WL_PROF_BSSID); -+ wl_inform_ibss(cfg_priv, ndev, e->addr); -+ cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL); -+ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); -+ set_bit(WL_STATUS_CONNECTED, &cfg_priv->status); -+ } else -+ brcmf_bss_connect_done(cfg_priv, ndev, e, true); -+ } else if (brcmf_is_linkdown(cfg_priv, e)) { -+ WL_CONN("Linkdown\n"); -+ if (brcmf_is_ibssmode(cfg_priv)) { -+ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); -+ if (test_and_clear_bit(WL_STATUS_CONNECTED, -+ &cfg_priv->status)) -+ brcmf_link_down(cfg_priv); -+ } else { -+ brcmf_bss_connect_done(cfg_priv, ndev, e, false); -+ if (test_and_clear_bit(WL_STATUS_CONNECTED, -+ &cfg_priv->status)) { -+ cfg80211_disconnected(ndev, 0, NULL, 0, -+ GFP_KERNEL); -+ brcmf_link_down(cfg_priv); -+ } -+ } -+ brcmf_init_prof(cfg_priv->profile); -+ } else if (brcmf_is_nonetwork(cfg_priv, e)) { -+ if (brcmf_is_ibssmode(cfg_priv)) -+ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); -+ else -+ brcmf_bss_connect_done(cfg_priv, ndev, e, false); -+ } -+ -+ return err; -+} -+ -+static s32 -+brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv, -+ struct net_device *ndev, -+ const struct brcmf_event_msg *e, void *data) -+{ -+ s32 err = 0; -+ u32 event = be32_to_cpu(e->event_type); -+ u32 status = be32_to_cpu(e->status); -+ -+ if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) { -+ if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) -+ brcmf_bss_roaming_done(cfg_priv, ndev, e); -+ else -+ brcmf_bss_connect_done(cfg_priv, ndev, e, true); -+ } -+ -+ return err; -+} -+ -+static s32 -+brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv, -+ struct net_device *ndev, -+ const struct brcmf_event_msg *e, void *data) -+{ -+ u16 flags = be16_to_cpu(e->flags); -+ enum nl80211_key_type key_type; -+ -+ if (flags & BRCMF_EVENT_MSG_GROUP) -+ key_type = NL80211_KEYTYPE_GROUP; -+ else -+ key_type = NL80211_KEYTYPE_PAIRWISE; -+ -+ cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1, -+ NULL, GFP_KERNEL); -+ -+ return 0; -+} -+ -+static s32 -+brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv, -+ struct net_device *ndev, -+ const struct brcmf_event_msg *e, void *data) -+{ -+ struct brcmf_channel_info_le channel_inform_le; -+ struct brcmf_scan_results_le *bss_list_le; -+ u32 len = WL_SCAN_BUF_MAX; -+ s32 err = 0; -+ bool scan_abort = false; -+ u32 scan_channel; -+ -+ WL_TRACE("Enter\n"); -+ -+ if (cfg_priv->iscan_on && cfg_priv->iscan_kickstart) { -+ WL_TRACE("Exit\n"); -+ return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv)); -+ } -+ -+ if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { -+ WL_ERR("Scan complete while device not scanning\n"); -+ scan_abort = true; -+ err = -EINVAL; -+ goto scan_done_out; -+ } -+ -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_inform_le, -+ sizeof(channel_inform_le)); -+ if (err) { -+ WL_ERR("scan busy (%d)\n", err); -+ scan_abort = true; -+ goto scan_done_out; -+ } -+ scan_channel = le32_to_cpu(channel_inform_le.scan_channel); -+ if (scan_channel) -+ WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel); -+ cfg_priv->bss_list = cfg_priv->scan_results; -+ bss_list_le = (struct brcmf_scan_results_le *) cfg_priv->bss_list; -+ -+ memset(cfg_priv->scan_results, 0, len); -+ bss_list_le->buflen = cpu_to_le32(len); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS, -+ cfg_priv->scan_results, len); -+ if (err) { -+ WL_ERR("%s Scan_results error (%d)\n", ndev->name, err); -+ err = -EINVAL; -+ scan_abort = true; -+ goto scan_done_out; -+ } -+ cfg_priv->scan_results->buflen = le32_to_cpu(bss_list_le->buflen); -+ cfg_priv->scan_results->version = le32_to_cpu(bss_list_le->version); -+ cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count); -+ -+ err = brcmf_inform_bss(cfg_priv); -+ if (err) { -+ scan_abort = true; -+ goto scan_done_out; -+ } -+ -+scan_done_out: -+ if (cfg_priv->scan_request) { -+ WL_SCAN("calling cfg80211_scan_done\n"); -+ cfg80211_scan_done(cfg_priv->scan_request, scan_abort); -+ brcmf_set_mpc(ndev, 1); -+ cfg_priv->scan_request = NULL; -+ } -+ -+ WL_TRACE("Exit\n"); -+ -+ return err; -+} -+ -+static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf) -+{ -+ conf->mode = (u32)-1; -+ conf->frag_threshold = (u32)-1; -+ conf->rts_threshold = (u32)-1; -+ conf->retry_short = (u32)-1; -+ conf->retry_long = (u32)-1; -+ conf->tx_power = -1; -+} -+ -+static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el) -+{ -+ memset(el, 0, sizeof(*el)); -+ el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status; -+ el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status; -+ el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status; -+ el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status; -+ el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status; -+} -+ -+static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ kfree(cfg_priv->scan_results); -+ cfg_priv->scan_results = NULL; -+ kfree(cfg_priv->bss_info); -+ cfg_priv->bss_info = NULL; -+ kfree(cfg_priv->conf); -+ cfg_priv->conf = NULL; -+ kfree(cfg_priv->profile); -+ cfg_priv->profile = NULL; -+ kfree(cfg_priv->scan_req_int); -+ cfg_priv->scan_req_int = NULL; -+ kfree(cfg_priv->dcmd_buf); -+ cfg_priv->dcmd_buf = NULL; -+ kfree(cfg_priv->extra_buf); -+ cfg_priv->extra_buf = NULL; -+ kfree(cfg_priv->iscan); -+ cfg_priv->iscan = NULL; -+ kfree(cfg_priv->pmk_list); -+ cfg_priv->pmk_list = NULL; -+} -+ -+static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL); -+ if (!cfg_priv->scan_results) -+ goto init_priv_mem_out; -+ cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL); -+ if (!cfg_priv->conf) -+ goto init_priv_mem_out; -+ cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL); -+ if (!cfg_priv->profile) -+ goto init_priv_mem_out; -+ cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); -+ if (!cfg_priv->bss_info) -+ goto init_priv_mem_out; -+ cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int), -+ GFP_KERNEL); -+ if (!cfg_priv->scan_req_int) -+ goto init_priv_mem_out; -+ cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL); -+ if (!cfg_priv->dcmd_buf) -+ goto init_priv_mem_out; -+ cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); -+ if (!cfg_priv->extra_buf) -+ goto init_priv_mem_out; -+ cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL); -+ if (!cfg_priv->iscan) -+ goto init_priv_mem_out; -+ cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL); -+ if (!cfg_priv->pmk_list) -+ goto init_priv_mem_out; -+ -+ return 0; -+ -+init_priv_mem_out: -+ brcmf_deinit_priv_mem(cfg_priv); -+ -+ return -ENOMEM; -+} -+ -+/* -+* retrieve first queued event from head -+*/ -+ -+static struct brcmf_cfg80211_event_q *brcmf_deq_event( -+ struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct brcmf_cfg80211_event_q *e = NULL; -+ -+ spin_lock_irq(&cfg_priv->evt_q_lock); -+ if (!list_empty(&cfg_priv->evt_q_list)) { -+ e = list_first_entry(&cfg_priv->evt_q_list, -+ struct brcmf_cfg80211_event_q, evt_q_list); -+ list_del(&e->evt_q_list); -+ } -+ spin_unlock_irq(&cfg_priv->evt_q_lock); -+ -+ return e; -+} -+ -+/* -+** push event to tail of the queue -+*/ -+ -+static s32 -+brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event, -+ const struct brcmf_event_msg *msg) -+{ -+ struct brcmf_cfg80211_event_q *e; -+ s32 err = 0; -+ -+ e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_KERNEL); -+ if (!e) -+ return -ENOMEM; -+ -+ e->etype = event; -+ memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg)); -+ -+ spin_lock_irq(&cfg_priv->evt_q_lock); -+ list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list); -+ spin_unlock_irq(&cfg_priv->evt_q_lock); -+ -+ return err; -+} -+ -+static void brcmf_put_event(struct brcmf_cfg80211_event_q *e) -+{ -+ kfree(e); -+} -+ -+static void brcmf_cfg80211_event_handler(struct work_struct *work) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv = -+ container_of(work, struct brcmf_cfg80211_priv, -+ event_work); -+ struct brcmf_cfg80211_event_q *e; -+ -+ e = brcmf_deq_event(cfg_priv); -+ if (unlikely(!e)) { -+ WL_ERR("event queue empty...\n"); -+ return; -+ } -+ -+ do { -+ WL_INFO("event type (%d)\n", e->etype); -+ if (cfg_priv->el.handler[e->etype]) -+ cfg_priv->el.handler[e->etype](cfg_priv, -+ cfg_to_ndev(cfg_priv), -+ &e->emsg, e->edata); -+ else -+ WL_INFO("Unknown Event (%d): ignoring\n", e->etype); -+ brcmf_put_event(e); -+ } while ((e = brcmf_deq_event(cfg_priv))); -+ -+} -+ -+static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ spin_lock_init(&cfg_priv->evt_q_lock); -+ INIT_LIST_HEAD(&cfg_priv->evt_q_list); -+} -+ -+static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct brcmf_cfg80211_event_q *e; -+ -+ spin_lock_irq(&cfg_priv->evt_q_lock); -+ while (!list_empty(&cfg_priv->evt_q_list)) { -+ e = list_first_entry(&cfg_priv->evt_q_list, -+ struct brcmf_cfg80211_event_q, evt_q_list); -+ list_del(&e->evt_q_list); -+ kfree(e); -+ } -+ spin_unlock_irq(&cfg_priv->evt_q_lock); -+} -+ -+static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ s32 err = 0; -+ -+ cfg_priv->scan_request = NULL; -+ cfg_priv->pwr_save = true; -+ cfg_priv->iscan_on = true; /* iscan on & off switch. -+ we enable iscan per default */ -+ cfg_priv->roam_on = true; /* roam on & off switch. -+ we enable roam per default */ -+ -+ cfg_priv->iscan_kickstart = false; -+ cfg_priv->active_scan = true; /* we do active scan for -+ specific scan per default */ -+ cfg_priv->dongle_up = false; /* dongle is not up yet */ -+ brcmf_init_eq(cfg_priv); -+ err = brcmf_init_priv_mem(cfg_priv); -+ if (err) -+ return err; -+ INIT_WORK(&cfg_priv->event_work, brcmf_cfg80211_event_handler); -+ brcmf_init_eloop_handler(&cfg_priv->el); -+ mutex_init(&cfg_priv->usr_sync); -+ err = brcmf_init_iscan(cfg_priv); -+ if (err) -+ return err; -+ brcmf_init_conf(cfg_priv->conf); -+ brcmf_init_prof(cfg_priv->profile); -+ brcmf_link_down(cfg_priv); -+ -+ return err; -+} -+ -+static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ cancel_work_sync(&cfg_priv->event_work); -+ cfg_priv->dongle_up = false; /* dongle down */ -+ brcmf_flush_eq(cfg_priv); -+ brcmf_link_down(cfg_priv); -+ brcmf_term_iscan(cfg_priv); -+ brcmf_deinit_priv_mem(cfg_priv); -+} -+ -+struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, -+ struct device *busdev, -+ void *data) -+{ -+ struct wireless_dev *wdev; -+ struct brcmf_cfg80211_priv *cfg_priv; -+ struct brcmf_cfg80211_iface *ci; -+ struct brcmf_cfg80211_dev *cfg_dev; -+ s32 err = 0; -+ -+ if (!ndev) { -+ WL_ERR("ndev is invalid\n"); -+ return NULL; -+ } -+ cfg_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL); -+ if (!cfg_dev) -+ return NULL; -+ -+ wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface), busdev); -+ if (IS_ERR(wdev)) { -+ kfree(cfg_dev); -+ return NULL; -+ } -+ -+ wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS); -+ cfg_priv = wdev_to_cfg(wdev); -+ cfg_priv->wdev = wdev; -+ cfg_priv->pub = data; -+ ci = (struct brcmf_cfg80211_iface *)&cfg_priv->ci; -+ ci->cfg_priv = cfg_priv; -+ ndev->ieee80211_ptr = wdev; -+ SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); -+ wdev->netdev = ndev; -+ err = wl_init_priv(cfg_priv); -+ if (err) { -+ WL_ERR("Failed to init iwm_priv (%d)\n", err); -+ goto cfg80211_attach_out; -+ } -+ brcmf_set_drvdata(cfg_dev, ci); -+ -+ return cfg_dev; -+ -+cfg80211_attach_out: -+ brcmf_free_wdev(cfg_priv); -+ kfree(cfg_dev); -+ return NULL; -+} -+ -+void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg_dev) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv; -+ -+ cfg_priv = brcmf_priv_get(cfg_dev); -+ -+ wl_deinit_priv(cfg_priv); -+ brcmf_free_wdev(cfg_priv); -+ brcmf_set_drvdata(cfg_dev, NULL); -+ kfree(cfg_dev); -+} -+ -+void -+brcmf_cfg80211_event(struct net_device *ndev, -+ const struct brcmf_event_msg *e, void *data) -+{ -+ u32 event_type = be32_to_cpu(e->event_type); -+ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); -+ -+ if (!brcmf_enq_event(cfg_priv, event_type, e)) -+ schedule_work(&cfg_priv->event_work); -+} -+ -+static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype) -+{ -+ s32 infra = 0; -+ s32 err = 0; -+ -+ switch (iftype) { -+ case NL80211_IFTYPE_MONITOR: -+ case NL80211_IFTYPE_WDS: -+ WL_ERR("type (%d) : currently we do not support this mode\n", -+ iftype); -+ err = -EINVAL; -+ return err; -+ case NL80211_IFTYPE_ADHOC: -+ infra = 0; -+ break; -+ case NL80211_IFTYPE_STATION: -+ infra = 1; -+ break; -+ default: -+ err = -EINVAL; -+ WL_ERR("invalid type (%d)\n", iftype); -+ return err; -+ } -+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); -+ if (err) { -+ WL_ERR("WLC_SET_INFRA error (%d)\n", err); -+ return err; -+ } -+ -+ return 0; -+} -+ -+static s32 brcmf_dongle_eventmsg(struct net_device *ndev) -+{ -+ /* Room for "event_msgs" + '\0' + bitvec */ -+ s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; -+ s8 eventmask[BRCMF_EVENTING_MASK_LEN]; -+ s32 err = 0; -+ -+ WL_TRACE("Enter\n"); -+ -+ /* Setup event_msgs */ -+ brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, -+ iovbuf, sizeof(iovbuf)); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf)); -+ if (err) { -+ WL_ERR("Get event_msgs error (%d)\n", err); -+ goto dongle_eventmsg_out; -+ } -+ memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN); -+ -+ setbit(eventmask, BRCMF_E_SET_SSID); -+ setbit(eventmask, BRCMF_E_ROAM); -+ setbit(eventmask, BRCMF_E_PRUNE); -+ setbit(eventmask, BRCMF_E_AUTH); -+ setbit(eventmask, BRCMF_E_REASSOC); -+ setbit(eventmask, BRCMF_E_REASSOC_IND); -+ setbit(eventmask, BRCMF_E_DEAUTH_IND); -+ setbit(eventmask, BRCMF_E_DISASSOC_IND); -+ setbit(eventmask, BRCMF_E_DISASSOC); -+ setbit(eventmask, BRCMF_E_JOIN); -+ setbit(eventmask, BRCMF_E_ASSOC_IND); -+ setbit(eventmask, BRCMF_E_PSK_SUP); -+ setbit(eventmask, BRCMF_E_LINK); -+ setbit(eventmask, BRCMF_E_NDIS_LINK); -+ setbit(eventmask, BRCMF_E_MIC_ERROR); -+ setbit(eventmask, BRCMF_E_PMKID_CACHE); -+ setbit(eventmask, BRCMF_E_TXFAIL); -+ setbit(eventmask, BRCMF_E_JOIN_START); -+ setbit(eventmask, BRCMF_E_SCAN_COMPLETE); -+ -+ brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, -+ iovbuf, sizeof(iovbuf)); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); -+ if (err) { -+ WL_ERR("Set event_msgs error (%d)\n", err); -+ goto dongle_eventmsg_out; -+ } -+ -+dongle_eventmsg_out: -+ WL_TRACE("Exit\n"); -+ return err; -+} -+ -+static s32 -+brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) -+{ -+ s8 iovbuf[32]; -+ s32 err = 0; -+ __le32 roamtrigger[2]; -+ __le32 roam_delta[2]; -+ __le32 bcn_to_le; -+ __le32 roamvar_le; -+ -+ /* -+ * Setup timeout if Beacons are lost and roam is -+ * off to report link down -+ */ -+ if (roamvar) { -+ bcn_to_le = cpu_to_le32(bcn_timeout); -+ brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_to_le, -+ sizeof(bcn_to_le), iovbuf, sizeof(iovbuf)); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, -+ iovbuf, sizeof(iovbuf)); -+ if (err) { -+ WL_ERR("bcn_timeout error (%d)\n", err); -+ goto dongle_rom_out; -+ } -+ } -+ -+ /* -+ * Enable/Disable built-in roaming to allow supplicant -+ * to take care of roaming -+ */ -+ WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On"); -+ roamvar_le = cpu_to_le32(roamvar); -+ brcmf_c_mkiovar("roam_off", (char *)&roamvar_le, -+ sizeof(roamvar_le), iovbuf, sizeof(iovbuf)); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); -+ if (err) { -+ WL_ERR("roam_off error (%d)\n", err); -+ goto dongle_rom_out; -+ } -+ -+ roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL); -+ roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_TRIGGER, -+ (void *)roamtrigger, sizeof(roamtrigger)); -+ if (err) { -+ WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err); -+ goto dongle_rom_out; -+ } -+ -+ roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA); -+ roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL); -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_DELTA, -+ (void *)roam_delta, sizeof(roam_delta)); -+ if (err) { -+ WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err); -+ goto dongle_rom_out; -+ } -+ -+dongle_rom_out: -+ return err; -+} -+ -+static s32 -+brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, -+ s32 scan_unassoc_time, s32 scan_passive_time) -+{ -+ s32 err = 0; -+ __le32 scan_assoc_tm_le = cpu_to_le32(scan_assoc_time); -+ __le32 scan_unassoc_tm_le = cpu_to_le32(scan_unassoc_time); -+ __le32 scan_passive_tm_le = cpu_to_le32(scan_passive_time); -+ -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME, -+ &scan_assoc_tm_le, sizeof(scan_assoc_tm_le)); -+ if (err) { -+ if (err == -EOPNOTSUPP) -+ WL_INFO("Scan assoc time is not supported\n"); -+ else -+ WL_ERR("Scan assoc time error (%d)\n", err); -+ goto dongle_scantime_out; -+ } -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME, -+ &scan_unassoc_tm_le, sizeof(scan_unassoc_tm_le)); -+ if (err) { -+ if (err == -EOPNOTSUPP) -+ WL_INFO("Scan unassoc time is not supported\n"); -+ else -+ WL_ERR("Scan unassoc time error (%d)\n", err); -+ goto dongle_scantime_out; -+ } -+ -+ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME, -+ &scan_passive_tm_le, sizeof(scan_passive_tm_le)); -+ if (err) { -+ if (err == -EOPNOTSUPP) -+ WL_INFO("Scan passive time is not supported\n"); -+ else -+ WL_ERR("Scan passive time error (%d)\n", err); -+ goto dongle_scantime_out; -+ } -+ -+dongle_scantime_out: -+ return err; -+} -+ -+static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct wiphy *wiphy; -+ s32 phy_list; -+ s8 phy; -+ s32 err = 0; -+ -+ err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST, -+ &phy_list, sizeof(phy_list)); -+ if (err) { -+ WL_ERR("error (%d)\n", err); -+ return err; -+ } -+ -+ phy = ((char *)&phy_list)[1]; -+ WL_INFO("%c phy\n", phy); -+ if (phy == 'n' || phy == 'a') { -+ wiphy = cfg_to_wiphy(cfg_priv); -+ wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n; -+ } -+ -+ return err; -+} -+ -+static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ return wl_update_wiphybands(cfg_priv); -+} -+ -+static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ struct net_device *ndev; -+ struct wireless_dev *wdev; -+ s32 power_mode; -+ s32 err = 0; -+ -+ if (cfg_priv->dongle_up) -+ return err; -+ -+ ndev = cfg_to_ndev(cfg_priv); -+ wdev = ndev->ieee80211_ptr; -+ -+ brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME, -+ WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME); -+ -+ err = brcmf_dongle_eventmsg(ndev); -+ if (err) -+ goto default_conf_out; -+ -+ power_mode = cfg_priv->pwr_save ? PM_FAST : PM_OFF; -+ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode); -+ if (err) -+ goto default_conf_out; -+ WL_INFO("power save set to %s\n", -+ (power_mode ? "enabled" : "disabled")); -+ -+ err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1), -+ WL_BEACON_TIMEOUT); -+ if (err) -+ goto default_conf_out; -+ err = brcmf_dongle_mode(ndev, wdev->iftype); -+ if (err && err != -EINPROGRESS) -+ goto default_conf_out; -+ err = brcmf_dongle_probecap(cfg_priv); -+ if (err) -+ goto default_conf_out; -+ -+ /* -EINPROGRESS: Call commit handler */ -+ -+default_conf_out: -+ -+ cfg_priv->dongle_up = true; -+ -+ return err; -+ -+} -+ -+static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ char buf[10+IFNAMSIZ]; -+ struct dentry *fd; -+ s32 err = 0; -+ -+ sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name); -+ cfg_priv->debugfsdir = debugfs_create_dir(buf, -+ cfg_to_wiphy(cfg_priv)->debugfsdir); -+ -+ fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir, -+ (u16 *)&cfg_priv->profile->beacon_interval); -+ if (!fd) { -+ err = -ENOMEM; -+ goto err_out; -+ } -+ -+ fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir, -+ (u8 *)&cfg_priv->profile->dtim_period); -+ if (!fd) { -+ err = -ENOMEM; -+ goto err_out; -+ } -+ -+err_out: -+ return err; -+} -+ -+static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ debugfs_remove_recursive(cfg_priv->debugfsdir); -+ cfg_priv->debugfsdir = NULL; -+} -+ -+static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ s32 err = 0; -+ -+ set_bit(WL_STATUS_READY, &cfg_priv->status); -+ -+ brcmf_debugfs_add_netdev_params(cfg_priv); -+ -+ err = brcmf_config_dongle(cfg_priv); -+ if (err) -+ return err; -+ -+ brcmf_invoke_iscan(cfg_priv); -+ -+ return err; -+} -+ -+static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv) -+{ -+ /* -+ * While going down, if associated with AP disassociate -+ * from AP to save power -+ */ -+ if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) || -+ test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) && -+ test_bit(WL_STATUS_READY, &cfg_priv->status)) { -+ WL_INFO("Disassociating from AP"); -+ brcmf_link_down(cfg_priv); -+ -+ /* Make sure WPA_Supplicant receives all the event -+ generated due to DISASSOC call to the fw to keep -+ the state fw and WPA_Supplicant state consistent -+ */ -+ brcmf_delay(500); -+ } -+ -+ set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); -+ brcmf_term_iscan(cfg_priv); -+ if (cfg_priv->scan_request) { -+ cfg80211_scan_done(cfg_priv->scan_request, true); -+ /* May need to perform this to cover rmmod */ -+ /* wl_set_mpc(cfg_to_ndev(wl), 1); */ -+ cfg_priv->scan_request = NULL; -+ } -+ clear_bit(WL_STATUS_READY, &cfg_priv->status); -+ clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); -+ clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); -+ -+ brcmf_debugfs_remove_netdev(cfg_priv); -+ -+ return 0; -+} -+ -+s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv; -+ s32 err = 0; -+ -+ cfg_priv = brcmf_priv_get(cfg_dev); -+ mutex_lock(&cfg_priv->usr_sync); -+ err = __brcmf_cfg80211_up(cfg_priv); -+ mutex_unlock(&cfg_priv->usr_sync); -+ -+ return err; -+} -+ -+s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev) -+{ -+ struct brcmf_cfg80211_priv *cfg_priv; -+ s32 err = 0; -+ -+ cfg_priv = brcmf_priv_get(cfg_dev); -+ mutex_lock(&cfg_priv->usr_sync); -+ err = __brcmf_cfg80211_down(cfg_priv); -+ mutex_unlock(&cfg_priv->usr_sync); -+ -+ return err; -+} -+ -+static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv, -+ u8 t, u8 l, u8 *v) -+{ -+ struct brcmf_cfg80211_ie *ie = &cfg_priv->ie; -+ s32 err = 0; -+ -+ if (ie->offset + l + 2 > WL_TLV_INFO_MAX) { -+ WL_ERR("ei crosses buffer boundary\n"); -+ return -ENOSPC; -+ } -+ ie->buf[ie->offset] = t; -+ ie->buf[ie->offset + 1] = l; -+ memcpy(&ie->buf[ie->offset + 2], v, l); -+ ie->offset += l + 2; -+ -+ return err; -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h.orig 2011-11-09 13:46:58.238800722 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h 2011-11-09 13:47:16.989566304 -0500 -@@ -0,0 +1,375 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _wl_cfg80211_h_ -+#define _wl_cfg80211_h_ -+ -+struct brcmf_cfg80211_conf; -+struct brcmf_cfg80211_iface; -+struct brcmf_cfg80211_priv; -+struct brcmf_cfg80211_security; -+struct brcmf_cfg80211_ibss; -+ -+#define WL_DBG_NONE 0 -+#define WL_DBG_CONN (1 << 5) -+#define WL_DBG_SCAN (1 << 4) -+#define WL_DBG_TRACE (1 << 3) -+#define WL_DBG_INFO (1 << 1) -+#define WL_DBG_ERR (1 << 0) -+#define WL_DBG_MASK ((WL_DBG_INFO | WL_DBG_ERR | WL_DBG_TRACE) | \ -+ (WL_DBG_SCAN) | (WL_DBG_CONN)) -+ -+#define WL_ERR(fmt, args...) \ -+do { \ -+ if (brcmf_dbg_level & WL_DBG_ERR) { \ -+ if (net_ratelimit()) { \ -+ printk(KERN_ERR "ERROR @%s : " fmt, \ -+ __func__, ##args); \ -+ } \ -+ } \ -+} while (0) -+ -+#if (defined BCMDBG) -+#define WL_INFO(fmt, args...) \ -+do { \ -+ if (brcmf_dbg_level & WL_DBG_INFO) { \ -+ if (net_ratelimit()) { \ -+ printk(KERN_ERR "INFO @%s : " fmt, \ -+ __func__, ##args); \ -+ } \ -+ } \ -+} while (0) -+ -+#define WL_TRACE(fmt, args...) \ -+do { \ -+ if (brcmf_dbg_level & WL_DBG_TRACE) { \ -+ if (net_ratelimit()) { \ -+ printk(KERN_ERR "TRACE @%s : " fmt, \ -+ __func__, ##args); \ -+ } \ -+ } \ -+} while (0) -+ -+#define WL_SCAN(fmt, args...) \ -+do { \ -+ if (brcmf_dbg_level & WL_DBG_SCAN) { \ -+ if (net_ratelimit()) { \ -+ printk(KERN_ERR "SCAN @%s : " fmt, \ -+ __func__, ##args); \ -+ } \ -+ } \ -+} while (0) -+ -+#define WL_CONN(fmt, args...) \ -+do { \ -+ if (brcmf_dbg_level & WL_DBG_CONN) { \ -+ if (net_ratelimit()) { \ -+ printk(KERN_ERR "CONN @%s : " fmt, \ -+ __func__, ##args); \ -+ } \ -+ } \ -+} while (0) -+ -+#else /* (defined BCMDBG) */ -+#define WL_INFO(fmt, args...) -+#define WL_TRACE(fmt, args...) -+#define WL_SCAN(fmt, args...) -+#define WL_CONN(fmt, args...) -+#endif /* (defined BCMDBG) */ -+ -+#define WL_NUM_SCAN_MAX 1 -+#define WL_NUM_PMKIDS_MAX MAXPMKID /* will be used -+ * for 2.6.33 kernel -+ * or later -+ */ -+#define WL_SCAN_BUF_MAX (1024 * 8) -+#define WL_TLV_INFO_MAX 1024 -+#define WL_BSS_INFO_MAX 2048 -+#define WL_ASSOC_INFO_MAX 512 /* -+ * needs to grab assoc info from dongle to -+ * report it to cfg80211 through "connect" -+ * event -+ */ -+#define WL_DCMD_LEN_MAX 1024 -+#define WL_EXTRA_BUF_MAX 2048 -+#define WL_ISCAN_BUF_MAX 2048 /* -+ * the buf length can be BRCMF_DCMD_MAXLEN -+ * to reduce iteration -+ */ -+#define WL_ISCAN_TIMER_INTERVAL_MS 3000 -+#define WL_SCAN_ERSULTS_LAST (BRCMF_SCAN_RESULTS_NO_MEM+1) -+#define WL_AP_MAX 256 /* virtually unlimitted as long -+ * as kernel memory allows -+ */ -+ -+#define WL_ROAM_TRIGGER_LEVEL -75 -+#define WL_ROAM_DELTA 20 -+#define WL_BEACON_TIMEOUT 3 -+ -+#define WL_SCAN_CHANNEL_TIME 40 -+#define WL_SCAN_UNASSOC_TIME 40 -+#define WL_SCAN_PASSIVE_TIME 120 -+ -+/* dongle status */ -+enum wl_status { -+ WL_STATUS_READY, -+ WL_STATUS_SCANNING, -+ WL_STATUS_SCAN_ABORTING, -+ WL_STATUS_CONNECTING, -+ WL_STATUS_CONNECTED -+}; -+ -+/* wi-fi mode */ -+enum wl_mode { -+ WL_MODE_BSS, -+ WL_MODE_IBSS, -+ WL_MODE_AP -+}; -+ -+/* dongle profile list */ -+enum wl_prof_list { -+ WL_PROF_MODE, -+ WL_PROF_SSID, -+ WL_PROF_SEC, -+ WL_PROF_IBSS, -+ WL_PROF_BAND, -+ WL_PROF_BSSID, -+ WL_PROF_ACT, -+ WL_PROF_BEACONINT, -+ WL_PROF_DTIMPERIOD -+}; -+ -+/* dongle iscan state */ -+enum wl_iscan_state { -+ WL_ISCAN_STATE_IDLE, -+ WL_ISCAN_STATE_SCANING -+}; -+ -+/* dongle configuration */ -+struct brcmf_cfg80211_conf { -+ u32 mode; /* adhoc , infrastructure or ap */ -+ u32 frag_threshold; -+ u32 rts_threshold; -+ u32 retry_short; -+ u32 retry_long; -+ s32 tx_power; -+ struct ieee80211_channel channel; -+}; -+ -+/* cfg80211 main event loop */ -+struct brcmf_cfg80211_event_loop { -+ s32(*handler[BRCMF_E_LAST]) (struct brcmf_cfg80211_priv *cfg_priv, -+ struct net_device *ndev, -+ const struct brcmf_event_msg *e, -+ void *data); -+}; -+ -+/* representing interface of cfg80211 plane */ -+struct brcmf_cfg80211_iface { -+ struct brcmf_cfg80211_priv *cfg_priv; -+}; -+ -+struct brcmf_cfg80211_dev { -+ void *driver_data; /* to store cfg80211 object information */ -+}; -+ -+/* basic structure of scan request */ -+struct brcmf_cfg80211_scan_req { -+ struct brcmf_ssid_le ssid_le; -+}; -+ -+/* basic structure of information element */ -+struct brcmf_cfg80211_ie { -+ u16 offset; -+ u8 buf[WL_TLV_INFO_MAX]; -+}; -+ -+/* event queue for cfg80211 main event */ -+struct brcmf_cfg80211_event_q { -+ struct list_head evt_q_list; -+ u32 etype; -+ struct brcmf_event_msg emsg; -+ s8 edata[1]; -+}; -+ -+/* security information with currently associated ap */ -+struct brcmf_cfg80211_security { -+ u32 wpa_versions; -+ u32 auth_type; -+ u32 cipher_pairwise; -+ u32 cipher_group; -+ u32 wpa_auth; -+}; -+ -+/* ibss information for currently joined ibss network */ -+struct brcmf_cfg80211_ibss { -+ u8 beacon_interval; /* in millisecond */ -+ u8 atim; /* in millisecond */ -+ s8 join_only; -+ u8 band; -+ u8 channel; -+}; -+ -+/* dongle profile */ -+struct brcmf_cfg80211_profile { -+ u32 mode; -+ struct brcmf_ssid ssid; -+ u8 bssid[ETH_ALEN]; -+ u16 beacon_interval; -+ u8 dtim_period; -+ struct brcmf_cfg80211_security sec; -+ struct brcmf_cfg80211_ibss ibss; -+ s32 band; -+}; -+ -+/* dongle iscan event loop */ -+struct brcmf_cfg80211_iscan_eloop { -+ s32 (*handler[WL_SCAN_ERSULTS_LAST]) -+ (struct brcmf_cfg80211_priv *cfg_priv); -+}; -+ -+/* dongle iscan controller */ -+struct brcmf_cfg80211_iscan_ctrl { -+ struct net_device *ndev; -+ struct timer_list timer; -+ u32 timer_ms; -+ u32 timer_on; -+ s32 state; -+ struct work_struct work; -+ struct brcmf_cfg80211_iscan_eloop el; -+ void *data; -+ s8 dcmd_buf[BRCMF_DCMD_SMLEN]; -+ s8 scan_buf[WL_ISCAN_BUF_MAX]; -+}; -+ -+/* association inform */ -+struct brcmf_cfg80211_connect_info { -+ u8 *req_ie; -+ s32 req_ie_len; -+ u8 *resp_ie; -+ s32 resp_ie_len; -+}; -+ -+/* assoc ie length */ -+struct brcmf_cfg80211_assoc_ielen_le { -+ __le32 req_len; -+ __le32 resp_len; -+}; -+ -+/* wpa2 pmk list */ -+struct brcmf_cfg80211_pmk_list { -+ struct pmkid_list pmkids; -+ struct pmkid foo[MAXPMKID - 1]; -+}; -+ -+/* dongle private data of cfg80211 interface */ -+struct brcmf_cfg80211_priv { -+ struct wireless_dev *wdev; /* representing wl cfg80211 device */ -+ struct brcmf_cfg80211_conf *conf; /* dongle configuration */ -+ struct cfg80211_scan_request *scan_request; /* scan request -+ object */ -+ struct brcmf_cfg80211_event_loop el; /* main event loop */ -+ struct list_head evt_q_list; /* used for event queue */ -+ spinlock_t evt_q_lock; /* for event queue synchronization */ -+ struct mutex usr_sync; /* maily for dongle up/down synchronization */ -+ struct brcmf_scan_results *bss_list; /* bss_list holding scanned -+ ap information */ -+ struct brcmf_scan_results *scan_results; -+ struct brcmf_cfg80211_scan_req *scan_req_int; /* scan request object -+ for internal purpose */ -+ struct wl_cfg80211_bss_info *bss_info; /* bss information for -+ cfg80211 layer */ -+ struct brcmf_cfg80211_ie ie; /* information element object for -+ internal purpose */ -+ struct brcmf_cfg80211_profile *profile; /* holding dongle profile */ -+ struct brcmf_cfg80211_iscan_ctrl *iscan; /* iscan controller */ -+ struct brcmf_cfg80211_connect_info conn_info; /* association info */ -+ struct brcmf_cfg80211_pmk_list *pmk_list; /* wpa2 pmk list */ -+ struct work_struct event_work; /* event handler work struct */ -+ unsigned long status; /* current dongle status */ -+ void *pub; -+ u32 channel; /* current channel */ -+ bool iscan_on; /* iscan on/off switch */ -+ bool iscan_kickstart; /* indicate iscan already started */ -+ bool active_scan; /* current scan mode */ -+ bool ibss_starter; /* indicates this sta is ibss starter */ -+ bool link_up; /* link/connection up flag */ -+ bool pwr_save; /* indicate whether dongle to support -+ power save mode */ -+ bool dongle_up; /* indicate whether dongle up or not */ -+ bool roam_on; /* on/off switch for dongle self-roaming */ -+ bool scan_tried; /* indicates if first scan attempted */ -+ u8 *dcmd_buf; /* dcmd buffer */ -+ u8 *extra_buf; /* maily to grab assoc information */ -+ struct dentry *debugfsdir; -+ u8 ci[0] __aligned(NETDEV_ALIGN); -+}; -+ -+static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_priv *w) -+{ -+ return w->wdev->wiphy; -+} -+ -+static inline struct brcmf_cfg80211_priv *wiphy_to_cfg(struct wiphy *w) -+{ -+ return (struct brcmf_cfg80211_priv *)(wiphy_priv(w)); -+} -+ -+static inline struct brcmf_cfg80211_priv *wdev_to_cfg(struct wireless_dev *wd) -+{ -+ return (struct brcmf_cfg80211_priv *)(wdev_priv(wd)); -+} -+ -+static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_priv *cfg) -+{ -+ return cfg->wdev->netdev; -+} -+ -+static inline struct brcmf_cfg80211_priv *ndev_to_cfg(struct net_device *ndev) -+{ -+ return wdev_to_cfg(ndev->ieee80211_ptr); -+} -+ -+#define iscan_to_cfg(i) ((struct brcmf_cfg80211_priv *)(i->data)) -+#define cfg_to_iscan(w) (w->iscan) -+ -+static inline struct -+brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_priv *cfg) -+{ -+ return &cfg->conn_info; -+} -+ -+static inline struct brcmf_bss_info *next_bss(struct brcmf_scan_results *list, -+ struct brcmf_bss_info *bss) -+{ -+ return bss = bss ? -+ (struct brcmf_bss_info *)((unsigned long)bss + -+ le32_to_cpu(bss->length)) : -+ list->bss_info; -+} -+ -+extern struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, -+ struct device *busdev, -+ void *data); -+extern void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg); -+ -+/* event handler from dongle */ -+extern void brcmf_cfg80211_event(struct net_device *ndev, -+ const struct brcmf_event_msg *e, void *data); -+extern s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev); -+extern s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev); -+ -+#endif /* _wl_cfg80211_h_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c.orig 2011-11-09 13:46:58.239800709 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c 2011-11-09 13:47:16.991566278 -0500 -@@ -0,0 +1,2079 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ * -+ * File contents: support functions for PCI/PCIe -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include "types.h" -+#include "pub.h" -+#include "pmu.h" -+#include "srom.h" -+#include "nicpci.h" -+#include "aiutils.h" -+ -+/* slow_clk_ctl */ -+ /* slow clock source mask */ -+#define SCC_SS_MASK 0x00000007 -+ /* source of slow clock is LPO */ -+#define SCC_SS_LPO 0x00000000 -+ /* source of slow clock is crystal */ -+#define SCC_SS_XTAL 0x00000001 -+ /* source of slow clock is PCI */ -+#define SCC_SS_PCI 0x00000002 -+ /* LPOFreqSel, 1: 160Khz, 0: 32KHz */ -+#define SCC_LF 0x00000200 -+ /* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */ -+#define SCC_LP 0x00000400 -+ /* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */ -+#define SCC_FS 0x00000800 -+ /* IgnorePllOffReq, 1/0: -+ * power logic ignores/honors PLL clock disable requests from core -+ */ -+#define SCC_IP 0x00001000 -+ /* XtalControlEn, 1/0: -+ * power logic does/doesn't disable crystal when appropriate -+ */ -+#define SCC_XC 0x00002000 -+ /* XtalPU (RO), 1/0: crystal running/disabled */ -+#define SCC_XP 0x00004000 -+ /* ClockDivider (SlowClk = 1/(4+divisor)) */ -+#define SCC_CD_MASK 0xffff0000 -+#define SCC_CD_SHIFT 16 -+ -+/* system_clk_ctl */ -+ /* ILPen: Enable Idle Low Power */ -+#define SYCC_IE 0x00000001 -+ /* ALPen: Enable Active Low Power */ -+#define SYCC_AE 0x00000002 -+ /* ForcePLLOn */ -+#define SYCC_FP 0x00000004 -+ /* Force ALP (or HT if ALPen is not set */ -+#define SYCC_AR 0x00000008 -+ /* Force HT */ -+#define SYCC_HR 0x00000010 -+ /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */ -+#define SYCC_CD_MASK 0xffff0000 -+#define SYCC_CD_SHIFT 16 -+ -+#define CST4329_SPROM_OTP_SEL_MASK 0x00000003 -+ /* OTP is powered up, use def. CIS, no SPROM */ -+#define CST4329_DEFCIS_SEL 0 -+ /* OTP is powered up, SPROM is present */ -+#define CST4329_SPROM_SEL 1 -+ /* OTP is powered up, no SPROM */ -+#define CST4329_OTP_SEL 2 -+ /* OTP is powered down, SPROM is present */ -+#define CST4329_OTP_PWRDN 3 -+ -+#define CST4329_SPI_SDIO_MODE_MASK 0x00000004 -+#define CST4329_SPI_SDIO_MODE_SHIFT 2 -+ -+/* 43224 chip-specific ChipControl register bits */ -+#define CCTRL43224_GPIO_TOGGLE 0x8000 -+ /* 12 mA drive strength */ -+#define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 -+ /* 12 mA drive strength for later 43224s */ -+#define CCTRL_43224B0_12MA_LED_DRIVE 0xF0 -+ -+/* 43236 Chip specific ChipStatus register bits */ -+#define CST43236_SFLASH_MASK 0x00000040 -+#define CST43236_OTP_MASK 0x00000080 -+#define CST43236_HSIC_MASK 0x00000100 /* USB/HSIC */ -+#define CST43236_BP_CLK 0x00000200 /* 120/96Mbps */ -+#define CST43236_BOOT_MASK 0x00001800 -+#define CST43236_BOOT_SHIFT 11 -+#define CST43236_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ -+#define CST43236_BOOT_FROM_ROM 1 /* boot from ROM */ -+#define CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */ -+#define CST43236_BOOT_FROM_INVALID 3 -+ -+/* 4331 chip-specific ChipControl register bits */ -+ /* 0 disable */ -+#define CCTRL4331_BT_COEXIST (1<<0) -+ /* 0 SECI is disabled (JTAG functional) */ -+#define CCTRL4331_SECI (1<<1) -+ /* 0 disable */ -+#define CCTRL4331_EXT_LNA (1<<2) -+ /* sprom/gpio13-15 mux */ -+#define CCTRL4331_SPROM_GPIO13_15 (1<<3) -+ /* 0 ext pa disable, 1 ext pa enabled */ -+#define CCTRL4331_EXTPA_EN (1<<4) -+ /* set drive out GPIO_CLK on sprom_cs pin */ -+#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) -+ /* use sprom_cs pin as PCIE mdio interface */ -+#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) -+ /* aband extpa will be at gpio2/5 and sprom_dout */ -+#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) -+ /* override core control on pipe_AuxClkEnable */ -+#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) -+ /* override core control on pipe_AuxPowerDown */ -+#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) -+ /* pcie_auxclkenable */ -+#define CCTRL4331_PCIE_AUXCLKEN (1<<10) -+ /* pcie_pipe_pllpowerdown */ -+#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) -+ /* enable bt_shd0 at gpio4 */ -+#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) -+ /* enable bt_shd1 at gpio5 */ -+#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) -+ -+/* 4331 Chip specific ChipStatus register bits */ -+ /* crystal frequency 20/40Mhz */ -+#define CST4331_XTAL_FREQ 0x00000001 -+#define CST4331_SPROM_PRESENT 0x00000002 -+#define CST4331_OTP_PRESENT 0x00000004 -+#define CST4331_LDO_RF 0x00000008 -+#define CST4331_LDO_PAR 0x00000010 -+ -+/* 4319 chip-specific ChipStatus register bits */ -+#define CST4319_SPI_CPULESSUSB 0x00000001 -+#define CST4319_SPI_CLK_POL 0x00000002 -+#define CST4319_SPI_CLK_PH 0x00000008 -+ /* gpio [7:6], SDIO CIS selection */ -+#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0 -+#define CST4319_SPROM_OTP_SEL_SHIFT 6 -+ /* use default CIS, OTP is powered up */ -+#define CST4319_DEFCIS_SEL 0x00000000 -+ /* use SPROM, OTP is powered up */ -+#define CST4319_SPROM_SEL 0x00000040 -+ /* use OTP, OTP is powered up */ -+#define CST4319_OTP_SEL 0x00000080 -+ /* use SPROM, OTP is powered down */ -+#define CST4319_OTP_PWRDN 0x000000c0 -+ /* gpio [8], sdio/usb mode */ -+#define CST4319_SDIO_USB_MODE 0x00000100 -+#define CST4319_REMAP_SEL_MASK 0x00000600 -+#define CST4319_ILPDIV_EN 0x00000800 -+#define CST4319_XTAL_PD_POL 0x00001000 -+#define CST4319_LPO_SEL 0x00002000 -+#define CST4319_RES_INIT_MODE 0x0000c000 -+ /* PALDO is configured with external PNP */ -+#define CST4319_PALDO_EXTPNP 0x00010000 -+#define CST4319_CBUCK_MODE_MASK 0x00060000 -+#define CST4319_CBUCK_MODE_BURST 0x00020000 -+#define CST4319_CBUCK_MODE_LPBURST 0x00060000 -+#define CST4319_RCAL_VALID 0x01000000 -+#define CST4319_RCAL_VALUE_MASK 0x3e000000 -+#define CST4319_RCAL_VALUE_SHIFT 25 -+ -+/* 4336 chip-specific ChipStatus register bits */ -+#define CST4336_SPI_MODE_MASK 0x00000001 -+#define CST4336_SPROM_PRESENT 0x00000002 -+#define CST4336_OTP_PRESENT 0x00000004 -+#define CST4336_ARMREMAP_0 0x00000008 -+#define CST4336_ILPDIV_EN_MASK 0x00000010 -+#define CST4336_ILPDIV_EN_SHIFT 4 -+#define CST4336_XTAL_PD_POL_MASK 0x00000020 -+#define CST4336_XTAL_PD_POL_SHIFT 5 -+#define CST4336_LPO_SEL_MASK 0x00000040 -+#define CST4336_LPO_SEL_SHIFT 6 -+#define CST4336_RES_INIT_MODE_MASK 0x00000180 -+#define CST4336_RES_INIT_MODE_SHIFT 7 -+#define CST4336_CBUCK_MODE_MASK 0x00000600 -+#define CST4336_CBUCK_MODE_SHIFT 9 -+ -+/* 4313 chip-specific ChipStatus register bits */ -+#define CST4313_SPROM_PRESENT 1 -+#define CST4313_OTP_PRESENT 2 -+#define CST4313_SPROM_OTP_SEL_MASK 0x00000002 -+#define CST4313_SPROM_OTP_SEL_SHIFT 0 -+ -+/* 4313 Chip specific ChipControl register bits */ -+ /* 12 mA drive strengh for later 4313 */ -+#define CCTRL_4313_12MA_LED_DRIVE 0x00000007 -+ -+/* Manufacturer Ids */ -+#define MFGID_ARM 0x43b -+#define MFGID_BRCM 0x4bf -+#define MFGID_MIPS 0x4a7 -+ -+/* Enumeration ROM registers */ -+#define ER_EROMENTRY 0x000 -+#define ER_REMAPCONTROL 0xe00 -+#define ER_REMAPSELECT 0xe04 -+#define ER_MASTERSELECT 0xe10 -+#define ER_ITCR 0xf00 -+#define ER_ITIP 0xf04 -+ -+/* Erom entries */ -+#define ER_TAG 0xe -+#define ER_TAG1 0x6 -+#define ER_VALID 1 -+#define ER_CI 0 -+#define ER_MP 2 -+#define ER_ADD 4 -+#define ER_END 0xe -+#define ER_BAD 0xffffffff -+ -+/* EROM CompIdentA */ -+#define CIA_MFG_MASK 0xfff00000 -+#define CIA_MFG_SHIFT 20 -+#define CIA_CID_MASK 0x000fff00 -+#define CIA_CID_SHIFT 8 -+#define CIA_CCL_MASK 0x000000f0 -+#define CIA_CCL_SHIFT 4 -+ -+/* EROM CompIdentB */ -+#define CIB_REV_MASK 0xff000000 -+#define CIB_REV_SHIFT 24 -+#define CIB_NSW_MASK 0x00f80000 -+#define CIB_NSW_SHIFT 19 -+#define CIB_NMW_MASK 0x0007c000 -+#define CIB_NMW_SHIFT 14 -+#define CIB_NSP_MASK 0x00003e00 -+#define CIB_NSP_SHIFT 9 -+#define CIB_NMP_MASK 0x000001f0 -+#define CIB_NMP_SHIFT 4 -+ -+/* EROM AddrDesc */ -+#define AD_ADDR_MASK 0xfffff000 -+#define AD_SP_MASK 0x00000f00 -+#define AD_SP_SHIFT 8 -+#define AD_ST_MASK 0x000000c0 -+#define AD_ST_SHIFT 6 -+#define AD_ST_SLAVE 0x00000000 -+#define AD_ST_BRIDGE 0x00000040 -+#define AD_ST_SWRAP 0x00000080 -+#define AD_ST_MWRAP 0x000000c0 -+#define AD_SZ_MASK 0x00000030 -+#define AD_SZ_SHIFT 4 -+#define AD_SZ_4K 0x00000000 -+#define AD_SZ_8K 0x00000010 -+#define AD_SZ_16K 0x00000020 -+#define AD_SZ_SZD 0x00000030 -+#define AD_AG32 0x00000008 -+#define AD_ADDR_ALIGN 0x00000fff -+#define AD_SZ_BASE 0x00001000 /* 4KB */ -+ -+/* EROM SizeDesc */ -+#define SD_SZ_MASK 0xfffff000 -+#define SD_SG32 0x00000008 -+#define SD_SZ_ALIGN 0x00000fff -+ -+/* PCI config space bit 4 for 4306c0 slow clock source */ -+#define PCI_CFG_GPIO_SCS 0x10 -+/* PCI config space GPIO 14 for Xtal power-up */ -+#define PCI_CFG_GPIO_XTAL 0x40 -+/* PCI config space GPIO 15 for PLL power-down */ -+#define PCI_CFG_GPIO_PLL 0x80 -+ -+/* power control defines */ -+#define PLL_DELAY 150 /* us pll on delay */ -+#define FREF_DELAY 200 /* us fref change delay */ -+#define XTAL_ON_DELAY 1000 /* us crystal power-on delay */ -+ -+/* resetctrl */ -+#define AIRC_RESET 1 -+ -+#define NOREV -1 /* Invalid rev */ -+ -+/* GPIO Based LED powersave defines */ -+#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */ -+#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */ -+ -+/* When Srom support present, fields in sromcontrol */ -+#define SRC_START 0x80000000 -+#define SRC_BUSY 0x80000000 -+#define SRC_OPCODE 0x60000000 -+#define SRC_OP_READ 0x00000000 -+#define SRC_OP_WRITE 0x20000000 -+#define SRC_OP_WRDIS 0x40000000 -+#define SRC_OP_WREN 0x60000000 -+#define SRC_OTPSEL 0x00000010 -+#define SRC_LOCK 0x00000008 -+#define SRC_SIZE_MASK 0x00000006 -+#define SRC_SIZE_1K 0x00000000 -+#define SRC_SIZE_4K 0x00000002 -+#define SRC_SIZE_16K 0x00000004 -+#define SRC_SIZE_SHIFT 1 -+#define SRC_PRESENT 0x00000001 -+ -+/* External PA enable mask */ -+#define GPIO_CTRL_EPA_EN_MASK 0x40 -+ -+#define DEFAULT_GPIOTIMERVAL \ -+ ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME) -+ -+#define BADIDX (SI_MAXCORES + 1) -+ -+/* Newer chips can access PCI/PCIE and CC core without requiring to change -+ * PCI BAR0 WIN -+ */ -+#define SI_FAST(si) (((si)->pub.buscoretype == PCIE_CORE_ID) || \ -+ (((si)->pub.buscoretype == PCI_CORE_ID) && \ -+ (si)->pub.buscorerev >= 13)) -+ -+#define CCREGS_FAST(si) (((char __iomem *)((si)->curmap) + \ -+ PCI_16KB0_CCREGS_OFFSET)) -+ -+#define IS_SIM(chippkg) \ -+ ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) -+ -+/* -+ * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts -+ * before after core switching to avoid invalid register accesss inside ISR. -+ */ -+#define INTR_OFF(si, intr_val) \ -+ if ((si)->intrsoff_fn && \ -+ (si)->coreid[(si)->curidx] == (si)->dev_coreid) \ -+ intr_val = (*(si)->intrsoff_fn)((si)->intr_arg) -+ -+#define INTR_RESTORE(si, intr_val) \ -+ if ((si)->intrsrestore_fn && \ -+ (si)->coreid[(si)->curidx] == (si)->dev_coreid) \ -+ (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val) -+ -+#define PCI(si) ((si)->pub.buscoretype == PCI_CORE_ID) -+#define PCIE(si) ((si)->pub.buscoretype == PCIE_CORE_ID) -+ -+#define PCI_FORCEHT(si) (PCIE(si) && (si->pub.chip == BCM4716_CHIP_ID)) -+ -+#ifdef BCMDBG -+#define SI_MSG(args) printk args -+#else -+#define SI_MSG(args) -+#endif /* BCMDBG */ -+ -+#define GOODCOREADDR(x, b) \ -+ (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ -+ IS_ALIGNED((x), SI_CORE_SIZE)) -+ -+#define PCIEREGS(si) ((__iomem char *)((si)->curmap) + \ -+ PCI_16KB0_PCIREGS_OFFSET) -+ -+struct aidmp { -+ u32 oobselina30; /* 0x000 */ -+ u32 oobselina74; /* 0x004 */ -+ u32 PAD[6]; -+ u32 oobselinb30; /* 0x020 */ -+ u32 oobselinb74; /* 0x024 */ -+ u32 PAD[6]; -+ u32 oobselinc30; /* 0x040 */ -+ u32 oobselinc74; /* 0x044 */ -+ u32 PAD[6]; -+ u32 oobselind30; /* 0x060 */ -+ u32 oobselind74; /* 0x064 */ -+ u32 PAD[38]; -+ u32 oobselouta30; /* 0x100 */ -+ u32 oobselouta74; /* 0x104 */ -+ u32 PAD[6]; -+ u32 oobseloutb30; /* 0x120 */ -+ u32 oobseloutb74; /* 0x124 */ -+ u32 PAD[6]; -+ u32 oobseloutc30; /* 0x140 */ -+ u32 oobseloutc74; /* 0x144 */ -+ u32 PAD[6]; -+ u32 oobseloutd30; /* 0x160 */ -+ u32 oobseloutd74; /* 0x164 */ -+ u32 PAD[38]; -+ u32 oobsynca; /* 0x200 */ -+ u32 oobseloutaen; /* 0x204 */ -+ u32 PAD[6]; -+ u32 oobsyncb; /* 0x220 */ -+ u32 oobseloutben; /* 0x224 */ -+ u32 PAD[6]; -+ u32 oobsyncc; /* 0x240 */ -+ u32 oobseloutcen; /* 0x244 */ -+ u32 PAD[6]; -+ u32 oobsyncd; /* 0x260 */ -+ u32 oobseloutden; /* 0x264 */ -+ u32 PAD[38]; -+ u32 oobaextwidth; /* 0x300 */ -+ u32 oobainwidth; /* 0x304 */ -+ u32 oobaoutwidth; /* 0x308 */ -+ u32 PAD[5]; -+ u32 oobbextwidth; /* 0x320 */ -+ u32 oobbinwidth; /* 0x324 */ -+ u32 oobboutwidth; /* 0x328 */ -+ u32 PAD[5]; -+ u32 oobcextwidth; /* 0x340 */ -+ u32 oobcinwidth; /* 0x344 */ -+ u32 oobcoutwidth; /* 0x348 */ -+ u32 PAD[5]; -+ u32 oobdextwidth; /* 0x360 */ -+ u32 oobdinwidth; /* 0x364 */ -+ u32 oobdoutwidth; /* 0x368 */ -+ u32 PAD[37]; -+ u32 ioctrlset; /* 0x400 */ -+ u32 ioctrlclear; /* 0x404 */ -+ u32 ioctrl; /* 0x408 */ -+ u32 PAD[61]; -+ u32 iostatus; /* 0x500 */ -+ u32 PAD[127]; -+ u32 ioctrlwidth; /* 0x700 */ -+ u32 iostatuswidth; /* 0x704 */ -+ u32 PAD[62]; -+ u32 resetctrl; /* 0x800 */ -+ u32 resetstatus; /* 0x804 */ -+ u32 resetreadid; /* 0x808 */ -+ u32 resetwriteid; /* 0x80c */ -+ u32 PAD[60]; -+ u32 errlogctrl; /* 0x900 */ -+ u32 errlogdone; /* 0x904 */ -+ u32 errlogstatus; /* 0x908 */ -+ u32 errlogaddrlo; /* 0x90c */ -+ u32 errlogaddrhi; /* 0x910 */ -+ u32 errlogid; /* 0x914 */ -+ u32 errloguser; /* 0x918 */ -+ u32 errlogflags; /* 0x91c */ -+ u32 PAD[56]; -+ u32 intstatus; /* 0xa00 */ -+ u32 PAD[127]; -+ u32 config; /* 0xe00 */ -+ u32 PAD[63]; -+ u32 itcr; /* 0xf00 */ -+ u32 PAD[3]; -+ u32 itipooba; /* 0xf10 */ -+ u32 itipoobb; /* 0xf14 */ -+ u32 itipoobc; /* 0xf18 */ -+ u32 itipoobd; /* 0xf1c */ -+ u32 PAD[4]; -+ u32 itipoobaout; /* 0xf30 */ -+ u32 itipoobbout; /* 0xf34 */ -+ u32 itipoobcout; /* 0xf38 */ -+ u32 itipoobdout; /* 0xf3c */ -+ u32 PAD[4]; -+ u32 itopooba; /* 0xf50 */ -+ u32 itopoobb; /* 0xf54 */ -+ u32 itopoobc; /* 0xf58 */ -+ u32 itopoobd; /* 0xf5c */ -+ u32 PAD[4]; -+ u32 itopoobain; /* 0xf70 */ -+ u32 itopoobbin; /* 0xf74 */ -+ u32 itopoobcin; /* 0xf78 */ -+ u32 itopoobdin; /* 0xf7c */ -+ u32 PAD[4]; -+ u32 itopreset; /* 0xf90 */ -+ u32 PAD[15]; -+ u32 peripherialid4; /* 0xfd0 */ -+ u32 peripherialid5; /* 0xfd4 */ -+ u32 peripherialid6; /* 0xfd8 */ -+ u32 peripherialid7; /* 0xfdc */ -+ u32 peripherialid0; /* 0xfe0 */ -+ u32 peripherialid1; /* 0xfe4 */ -+ u32 peripherialid2; /* 0xfe8 */ -+ u32 peripherialid3; /* 0xfec */ -+ u32 componentid0; /* 0xff0 */ -+ u32 componentid1; /* 0xff4 */ -+ u32 componentid2; /* 0xff8 */ -+ u32 componentid3; /* 0xffc */ -+}; -+ -+/* EROM parsing */ -+ -+static u32 -+get_erom_ent(struct si_pub *sih, u32 __iomem **eromptr, u32 mask, u32 match) -+{ -+ u32 ent; -+ uint inv = 0, nom = 0; -+ -+ while (true) { -+ ent = R_REG(*eromptr); -+ (*eromptr)++; -+ -+ if (mask == 0) -+ break; -+ -+ if ((ent & ER_VALID) == 0) { -+ inv++; -+ continue; -+ } -+ -+ if (ent == (ER_END | ER_VALID)) -+ break; -+ -+ if ((ent & mask) == match) -+ break; -+ -+ nom++; -+ } -+ -+ return ent; -+} -+ -+static u32 -+get_asd(struct si_pub *sih, u32 __iomem **eromptr, uint sp, uint ad, uint st, -+ u32 *addrl, u32 *addrh, u32 *sizel, u32 *sizeh) -+{ -+ u32 asd, sz, szd; -+ -+ asd = get_erom_ent(sih, eromptr, ER_VALID, ER_VALID); -+ if (((asd & ER_TAG1) != ER_ADD) || -+ (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) || -+ ((asd & AD_ST_MASK) != st)) { -+ /* This is not what we want, "push" it back */ -+ (*eromptr)--; -+ return 0; -+ } -+ *addrl = asd & AD_ADDR_MASK; -+ if (asd & AD_AG32) -+ *addrh = get_erom_ent(sih, eromptr, 0, 0); -+ else -+ *addrh = 0; -+ *sizeh = 0; -+ sz = asd & AD_SZ_MASK; -+ if (sz == AD_SZ_SZD) { -+ szd = get_erom_ent(sih, eromptr, 0, 0); -+ *sizel = szd & SD_SZ_MASK; -+ if (szd & SD_SG32) -+ *sizeh = get_erom_ent(sih, eromptr, 0, 0); -+ } else -+ *sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT); -+ -+ return asd; -+} -+ -+static void ai_hwfixup(struct si_info *sii) -+{ -+} -+ -+/* parse the enumeration rom to identify all cores */ -+static void ai_scan(struct si_pub *sih, struct chipcregs __iomem *cc) -+{ -+ struct si_info *sii = (struct si_info *)sih; -+ -+ u32 erombase; -+ u32 __iomem *eromptr, *eromlim; -+ void __iomem *regs = cc; -+ -+ erombase = R_REG(&cc->eromptr); -+ -+ /* Set wrappers address */ -+ sii->curwrap = (void *)((unsigned long)cc + SI_CORE_SIZE); -+ -+ /* Now point the window at the erom */ -+ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, erombase); -+ eromptr = regs; -+ eromlim = eromptr + (ER_REMAPCONTROL / sizeof(u32)); -+ -+ while (eromptr < eromlim) { -+ u32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp; -+ u32 mpd, asd, addrl, addrh, sizel, sizeh; -+ u32 __iomem *base; -+ uint i, j, idx; -+ bool br; -+ -+ br = false; -+ -+ /* Grok a component */ -+ cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI); -+ if (cia == (ER_END | ER_VALID)) { -+ /* Found END of erom */ -+ ai_hwfixup(sii); -+ return; -+ } -+ base = eromptr - 1; -+ cib = get_erom_ent(sih, &eromptr, 0, 0); -+ -+ if ((cib & ER_TAG) != ER_CI) { -+ /* CIA not followed by CIB */ -+ goto error; -+ } -+ -+ cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT; -+ mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT; -+ crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT; -+ nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT; -+ nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT; -+ nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; -+ nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; -+ -+ if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0)) -+ continue; -+ if ((nmw + nsw == 0)) { -+ /* A component which is not a core */ -+ if (cid == OOB_ROUTER_CORE_ID) { -+ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, -+ &addrl, &addrh, &sizel, &sizeh); -+ if (asd != 0) -+ sii->oob_router = addrl; -+ } -+ continue; -+ } -+ -+ idx = sii->numcores; -+/* sii->eromptr[idx] = base; */ -+ sii->cia[idx] = cia; -+ sii->cib[idx] = cib; -+ sii->coreid[idx] = cid; -+ -+ for (i = 0; i < nmp; i++) { -+ mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); -+ if ((mpd & ER_TAG) != ER_MP) { -+ /* Not enough MP entries for component */ -+ goto error; -+ } -+ } -+ -+ /* First Slave Address Descriptor should be port 0: -+ * the main register space for the core -+ */ -+ asd = -+ get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, -+ &sizel, &sizeh); -+ if (asd == 0) { -+ /* Try again to see if it is a bridge */ -+ asd = -+ get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, -+ &addrh, &sizel, &sizeh); -+ if (asd != 0) -+ br = true; -+ else if ((addrh != 0) || (sizeh != 0) -+ || (sizel != SI_CORE_SIZE)) { -+ /* First Slave ASD for core malformed */ -+ goto error; -+ } -+ } -+ sii->coresba[idx] = addrl; -+ sii->coresba_size[idx] = sizel; -+ /* Get any more ASDs in port 0 */ -+ j = 1; -+ do { -+ asd = -+ get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, -+ &addrh, &sizel, &sizeh); -+ if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE)) { -+ sii->coresba2[idx] = addrl; -+ sii->coresba2_size[idx] = sizel; -+ } -+ j++; -+ } while (asd != 0); -+ -+ /* Go through the ASDs for other slave ports */ -+ for (i = 1; i < nsp; i++) { -+ j = 0; -+ do { -+ asd = -+ get_asd(sih, &eromptr, i, j++, AD_ST_SLAVE, -+ &addrl, &addrh, &sizel, &sizeh); -+ } while (asd != 0); -+ if (j == 0) { -+ /* SP has no address descriptors */ -+ goto error; -+ } -+ } -+ -+ /* Now get master wrappers */ -+ for (i = 0; i < nmw; i++) { -+ asd = -+ get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, -+ &addrh, &sizel, &sizeh); -+ if (asd == 0) { -+ /* Missing descriptor for MW */ -+ goto error; -+ } -+ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { -+ /* Master wrapper %d is not 4KB */ -+ goto error; -+ } -+ if (i == 0) -+ sii->wrapba[idx] = addrl; -+ } -+ -+ /* And finally slave wrappers */ -+ for (i = 0; i < nsw; i++) { -+ uint fwp = (nsp == 1) ? 0 : 1; -+ asd = -+ get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP, -+ &addrl, &addrh, &sizel, &sizeh); -+ if (asd == 0) { -+ /* Missing descriptor for SW */ -+ goto error; -+ } -+ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { -+ /* Slave wrapper is not 4KB */ -+ goto error; -+ } -+ if ((nmw == 0) && (i == 0)) -+ sii->wrapba[idx] = addrl; -+ } -+ -+ /* Don't record bridges */ -+ if (br) -+ continue; -+ -+ /* Done with core */ -+ sii->numcores++; -+ } -+ -+ error: -+ /* Reached end of erom without finding END */ -+ sii->numcores = 0; -+ return; -+} -+ -+/* -+ * This function changes the logical "focus" to the indicated core. -+ * Return the current core's virtual address. Since each core starts with the -+ * same set of registers (BIST, clock control, etc), the returned address -+ * contains the first register of this 'common' register block (not to be -+ * confused with 'common core'). -+ */ -+void __iomem *ai_setcoreidx(struct si_pub *sih, uint coreidx) -+{ -+ struct si_info *sii = (struct si_info *)sih; -+ u32 addr = sii->coresba[coreidx]; -+ u32 wrap = sii->wrapba[coreidx]; -+ -+ if (coreidx >= sii->numcores) -+ return NULL; -+ -+ /* point bar0 window */ -+ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, addr); -+ /* point bar0 2nd 4KB window */ -+ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN2, wrap); -+ sii->curidx = coreidx; -+ -+ return sii->curmap; -+} -+ -+/* Return the number of address spaces in current core */ -+int ai_numaddrspaces(struct si_pub *sih) -+{ -+ return 2; -+} -+ -+/* Return the address of the nth address space in the current core */ -+u32 ai_addrspace(struct si_pub *sih, uint asidx) -+{ -+ struct si_info *sii; -+ uint cidx; -+ -+ sii = (struct si_info *)sih; -+ cidx = sii->curidx; -+ -+ if (asidx == 0) -+ return sii->coresba[cidx]; -+ else if (asidx == 1) -+ return sii->coresba2[cidx]; -+ else { -+ /* Need to parse the erom again to find addr space */ -+ return 0; -+ } -+} -+ -+/* Return the size of the nth address space in the current core */ -+u32 ai_addrspacesize(struct si_pub *sih, uint asidx) -+{ -+ struct si_info *sii; -+ uint cidx; -+ -+ sii = (struct si_info *)sih; -+ cidx = sii->curidx; -+ -+ if (asidx == 0) -+ return sii->coresba_size[cidx]; -+ else if (asidx == 1) -+ return sii->coresba2_size[cidx]; -+ else { -+ /* Need to parse the erom again to find addr */ -+ return 0; -+ } -+} -+ -+uint ai_flag(struct si_pub *sih) -+{ -+ struct si_info *sii; -+ struct aidmp *ai; -+ -+ sii = (struct si_info *)sih; -+ ai = sii->curwrap; -+ -+ return R_REG(&ai->oobselouta30) & 0x1f; -+} -+ -+void ai_setint(struct si_pub *sih, int siflag) -+{ -+} -+ -+uint ai_corevendor(struct si_pub *sih) -+{ -+ struct si_info *sii; -+ u32 cia; -+ -+ sii = (struct si_info *)sih; -+ cia = sii->cia[sii->curidx]; -+ return (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT; -+} -+ -+uint ai_corerev(struct si_pub *sih) -+{ -+ struct si_info *sii; -+ u32 cib; -+ -+ sii = (struct si_info *)sih; -+ cib = sii->cib[sii->curidx]; -+ return (cib & CIB_REV_MASK) >> CIB_REV_SHIFT; -+} -+ -+bool ai_iscoreup(struct si_pub *sih) -+{ -+ struct si_info *sii; -+ struct aidmp *ai; -+ -+ sii = (struct si_info *)sih; -+ ai = sii->curwrap; -+ -+ return (((R_REG(&ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) == -+ SICF_CLOCK_EN) -+ && ((R_REG(&ai->resetctrl) & AIRC_RESET) == 0)); -+} -+ -+void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val) -+{ -+ struct si_info *sii; -+ struct aidmp *ai; -+ u32 w; -+ -+ sii = (struct si_info *)sih; -+ -+ ai = sii->curwrap; -+ -+ if (mask || val) { -+ w = ((R_REG(&ai->ioctrl) & ~mask) | val); -+ W_REG(&ai->ioctrl, w); -+ } -+} -+ -+u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val) -+{ -+ struct si_info *sii; -+ struct aidmp *ai; -+ u32 w; -+ -+ sii = (struct si_info *)sih; -+ ai = sii->curwrap; -+ -+ if (mask || val) { -+ w = ((R_REG(&ai->ioctrl) & ~mask) | val); -+ W_REG(&ai->ioctrl, w); -+ } -+ -+ return R_REG(&ai->ioctrl); -+} -+ -+/* return true if PCIE capability exists in the pci config space */ -+static bool ai_ispcie(struct si_info *sii) -+{ -+ u8 cap_ptr; -+ -+ cap_ptr = -+ pcicore_find_pci_capability(sii->pbus, PCI_CAP_ID_EXP, NULL, -+ NULL); -+ if (!cap_ptr) -+ return false; -+ -+ return true; -+} -+ -+static bool ai_buscore_prep(struct si_info *sii) -+{ -+ /* kludge to enable the clock on the 4306 which lacks a slowclock */ -+ if (!ai_ispcie(sii)) -+ ai_clkctl_xtal(&sii->pub, XTAL | PLL, ON); -+ return true; -+} -+ -+u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val) -+{ -+ struct si_info *sii; -+ struct aidmp *ai; -+ u32 w; -+ -+ sii = (struct si_info *)sih; -+ ai = sii->curwrap; -+ -+ if (mask || val) { -+ w = ((R_REG(&ai->iostatus) & ~mask) | val); -+ W_REG(&ai->iostatus, w); -+ } -+ -+ return R_REG(&ai->iostatus); -+} -+ -+static bool -+ai_buscore_setup(struct si_info *sii, u32 savewin, uint *origidx) -+{ -+ bool pci, pcie; -+ uint i; -+ uint pciidx, pcieidx, pcirev, pcierev; -+ struct chipcregs __iomem *cc; -+ -+ cc = ai_setcoreidx(&sii->pub, SI_CC_IDX); -+ -+ /* get chipcommon rev */ -+ sii->pub.ccrev = (int)ai_corerev(&sii->pub); -+ -+ /* get chipcommon chipstatus */ -+ if (sii->pub.ccrev >= 11) -+ sii->pub.chipst = R_REG(&cc->chipstatus); -+ -+ /* get chipcommon capabilites */ -+ sii->pub.cccaps = R_REG(&cc->capabilities); -+ /* get chipcommon extended capabilities */ -+ -+ if (sii->pub.ccrev >= 35) -+ sii->pub.cccaps_ext = R_REG(&cc->capabilities_ext); -+ -+ /* get pmu rev and caps */ -+ if (sii->pub.cccaps & CC_CAP_PMU) { -+ sii->pub.pmucaps = R_REG(&cc->pmucapabilities); -+ sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; -+ } -+ -+ /* figure out bus/orignal core idx */ -+ sii->pub.buscoretype = NODEV_CORE_ID; -+ sii->pub.buscorerev = NOREV; -+ sii->pub.buscoreidx = BADIDX; -+ -+ pci = pcie = false; -+ pcirev = pcierev = NOREV; -+ pciidx = pcieidx = BADIDX; -+ -+ for (i = 0; i < sii->numcores; i++) { -+ uint cid, crev; -+ -+ ai_setcoreidx(&sii->pub, i); -+ cid = ai_coreid(&sii->pub); -+ crev = ai_corerev(&sii->pub); -+ -+ if (cid == PCI_CORE_ID) { -+ pciidx = i; -+ pcirev = crev; -+ pci = true; -+ } else if (cid == PCIE_CORE_ID) { -+ pcieidx = i; -+ pcierev = crev; -+ pcie = true; -+ } -+ -+ /* find the core idx before entering this func. */ -+ if ((savewin && (savewin == sii->coresba[i])) || -+ (cc == sii->regs[i])) -+ *origidx = i; -+ } -+ -+ if (pci && pcie) { -+ if (ai_ispcie(sii)) -+ pci = false; -+ else -+ pcie = false; -+ } -+ if (pci) { -+ sii->pub.buscoretype = PCI_CORE_ID; -+ sii->pub.buscorerev = pcirev; -+ sii->pub.buscoreidx = pciidx; -+ } else if (pcie) { -+ sii->pub.buscoretype = PCIE_CORE_ID; -+ sii->pub.buscorerev = pcierev; -+ sii->pub.buscoreidx = pcieidx; -+ } -+ -+ /* fixup necessary chip/core configurations */ -+ if (SI_FAST(sii)) { -+ if (!sii->pch) { -+ sii->pch = pcicore_init(&sii->pub, sii->pbus, -+ (__iomem void *)PCIEREGS(sii)); -+ if (sii->pch == NULL) -+ return false; -+ } -+ } -+ if (ai_pci_fixcfg(&sii->pub)) { -+ /* si_doattach: si_pci_fixcfg failed */ -+ return false; -+ } -+ -+ /* return to the original core */ -+ ai_setcoreidx(&sii->pub, *origidx); -+ -+ return true; -+} -+ -+/* -+ * get boardtype and boardrev -+ */ -+static __used void ai_nvram_process(struct si_info *sii) -+{ -+ uint w = 0; -+ -+ /* do a pci config read to get subsystem id and subvendor id */ -+ pci_read_config_dword(sii->pbus, PCI_SUBSYSTEM_VENDOR_ID, &w); -+ -+ sii->pub.boardvendor = w & 0xffff; -+ sii->pub.boardtype = (w >> 16) & 0xffff; -+ sii->pub.boardflags = getintvar(&sii->pub, BRCMS_SROM_BOARDFLAGS); -+} -+ -+static struct si_info *ai_doattach(struct si_info *sii, -+ void __iomem *regs, struct pci_dev *pbus) -+{ -+ struct si_pub *sih = &sii->pub; -+ u32 w, savewin; -+ struct chipcregs __iomem *cc; -+ uint socitype; -+ uint origidx; -+ -+ memset((unsigned char *) sii, 0, sizeof(struct si_info)); -+ -+ savewin = 0; -+ -+ sih->buscoreidx = BADIDX; -+ -+ sii->curmap = regs; -+ sii->pbus = pbus; -+ -+ /* find Chipcommon address */ -+ pci_read_config_dword(sii->pbus, PCI_BAR0_WIN, &savewin); -+ if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) -+ savewin = SI_ENUM_BASE; -+ -+ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, -+ SI_ENUM_BASE); -+ cc = (struct chipcregs __iomem *) regs; -+ -+ /* bus/core/clk setup for register access */ -+ if (!ai_buscore_prep(sii)) -+ return NULL; -+ -+ /* -+ * ChipID recognition. -+ * We assume we can read chipid at offset 0 from the regs arg. -+ * If we add other chiptypes (or if we need to support old sdio -+ * hosts w/o chipcommon), some way of recognizing them needs to -+ * be added here. -+ */ -+ w = R_REG(&cc->chipid); -+ socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; -+ /* Might as wll fill in chip id rev & pkg */ -+ sih->chip = w & CID_ID_MASK; -+ sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; -+ sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; -+ -+ sih->issim = false; -+ -+ /* scan for cores */ -+ if (socitype == SOCI_AI) { -+ SI_MSG(("Found chip type AI (0x%08x)\n", w)); -+ /* pass chipc address instead of original core base */ -+ ai_scan(&sii->pub, cc); -+ } else { -+ /* Found chip of unknown type */ -+ return NULL; -+ } -+ /* no cores found, bail out */ -+ if (sii->numcores == 0) -+ return NULL; -+ -+ /* bus/core/clk setup */ -+ origidx = SI_CC_IDX; -+ if (!ai_buscore_setup(sii, savewin, &origidx)) -+ goto exit; -+ -+ /* Init nvram from sprom/otp if they exist */ -+ if (srom_var_init(&sii->pub, cc)) -+ goto exit; -+ -+ ai_nvram_process(sii); -+ -+ /* === NVRAM, clock is ready === */ -+ cc = (struct chipcregs __iomem *) ai_setcore(sih, CC_CORE_ID, 0); -+ W_REG(&cc->gpiopullup, 0); -+ W_REG(&cc->gpiopulldown, 0); -+ ai_setcoreidx(sih, origidx); -+ -+ /* PMU specific initializations */ -+ if (sih->cccaps & CC_CAP_PMU) { -+ u32 xtalfreq; -+ si_pmu_init(sih); -+ si_pmu_chip_init(sih); -+ -+ xtalfreq = si_pmu_measure_alpclk(sih); -+ si_pmu_pll_init(sih, xtalfreq); -+ si_pmu_res_init(sih); -+ si_pmu_swreg_init(sih); -+ } -+ -+ /* setup the GPIO based LED powersave register */ -+ w = getintvar(sih, BRCMS_SROM_LEDDC); -+ if (w == 0) -+ w = DEFAULT_GPIOTIMERVAL; -+ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, gpiotimerval), -+ ~0, w); -+ -+ if (PCIE(sii)) -+ pcicore_attach(sii->pch, SI_DOATTACH); -+ -+ if (sih->chip == BCM43224_CHIP_ID) { -+ /* -+ * enable 12 mA drive strenth for 43224 and -+ * set chipControl register bit 15 -+ */ -+ if (sih->chiprev == 0) { -+ SI_MSG(("Applying 43224A0 WARs\n")); -+ ai_corereg(sih, SI_CC_IDX, -+ offsetof(struct chipcregs, chipcontrol), -+ CCTRL43224_GPIO_TOGGLE, -+ CCTRL43224_GPIO_TOGGLE); -+ si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE, -+ CCTRL_43224A0_12MA_LED_DRIVE); -+ } -+ if (sih->chiprev >= 1) { -+ SI_MSG(("Applying 43224B0+ WARs\n")); -+ si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE, -+ CCTRL_43224B0_12MA_LED_DRIVE); -+ } -+ } -+ -+ if (sih->chip == BCM4313_CHIP_ID) { -+ /* -+ * enable 12 mA drive strenth for 4313 and -+ * set chipControl register bit 1 -+ */ -+ SI_MSG(("Applying 4313 WARs\n")); -+ si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE, -+ CCTRL_4313_12MA_LED_DRIVE); -+ } -+ -+ return sii; -+ -+ exit: -+ if (sii->pch) -+ pcicore_deinit(sii->pch); -+ sii->pch = NULL; -+ -+ return NULL; -+} -+ -+/* -+ * Allocate a si handle. -+ * devid - pci device id (used to determine chip#) -+ * osh - opaque OS handle -+ * regs - virtual address of initial core registers -+ */ -+struct si_pub * -+ai_attach(void __iomem *regs, struct pci_dev *sdh) -+{ -+ struct si_info *sii; -+ -+ /* alloc struct si_info */ -+ sii = kmalloc(sizeof(struct si_info), GFP_ATOMIC); -+ if (sii == NULL) -+ return NULL; -+ -+ if (ai_doattach(sii, regs, sdh) == NULL) { -+ kfree(sii); -+ return NULL; -+ } -+ -+ return (struct si_pub *) sii; -+} -+ -+/* may be called with core in reset */ -+void ai_detach(struct si_pub *sih) -+{ -+ struct si_info *sii; -+ -+ struct si_pub *si_local = NULL; -+ memcpy(&si_local, &sih, sizeof(struct si_pub **)); -+ -+ sii = (struct si_info *)sih; -+ -+ if (sii == NULL) -+ return; -+ -+ if (sii->pch) -+ pcicore_deinit(sii->pch); -+ sii->pch = NULL; -+ -+ srom_free_vars(sih); -+ kfree(sii); -+} -+ -+/* register driver interrupt disabling and restoring callback functions */ -+void -+ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn, -+ void *intrsrestore_fn, -+ void *intrsenabled_fn, void *intr_arg) -+{ -+ struct si_info *sii; -+ -+ sii = (struct si_info *)sih; -+ sii->intr_arg = intr_arg; -+ sii->intrsoff_fn = (u32 (*)(void *)) intrsoff_fn; -+ sii->intrsrestore_fn = (void (*) (void *, u32)) intrsrestore_fn; -+ sii->intrsenabled_fn = (bool (*)(void *)) intrsenabled_fn; -+ /* save current core id. when this function called, the current core -+ * must be the core which provides driver functions(il, et, wl, etc.) -+ */ -+ sii->dev_coreid = sii->coreid[sii->curidx]; -+} -+ -+void ai_deregister_intr_callback(struct si_pub *sih) -+{ -+ struct si_info *sii; -+ -+ sii = (struct si_info *)sih; -+ sii->intrsoff_fn = NULL; -+} -+ -+uint ai_coreid(struct si_pub *sih) -+{ -+ struct si_info *sii; -+ -+ sii = (struct si_info *)sih; -+ return sii->coreid[sii->curidx]; -+} -+ -+uint ai_coreidx(struct si_pub *sih) -+{ -+ struct si_info *sii; -+ -+ sii = (struct si_info *)sih; -+ return sii->curidx; -+} -+ -+bool ai_backplane64(struct si_pub *sih) -+{ -+ return (sih->cccaps & CC_CAP_BKPLN64) != 0; -+} -+ -+/* return index of coreid or BADIDX if not found */ -+uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit) -+{ -+ struct si_info *sii; -+ uint found; -+ uint i; -+ -+ sii = (struct si_info *)sih; -+ -+ found = 0; -+ -+ for (i = 0; i < sii->numcores; i++) -+ if (sii->coreid[i] == coreid) { -+ if (found == coreunit) -+ return i; -+ found++; -+ } -+ -+ return BADIDX; -+} -+ -+/* -+ * This function changes logical "focus" to the indicated core; -+ * must be called with interrupts off. -+ * Moreover, callers should keep interrupts off during switching -+ * out of and back to d11 core. -+ */ -+void __iomem *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit) -+{ -+ uint idx; -+ -+ idx = ai_findcoreidx(sih, coreid, coreunit); -+ if (idx >= SI_MAXCORES) -+ return NULL; -+ -+ return ai_setcoreidx(sih, idx); -+} -+ -+/* Turn off interrupt as required by ai_setcore, before switch core */ -+void __iomem *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx, -+ uint *intr_val) -+{ -+ void __iomem *cc; -+ struct si_info *sii; -+ -+ sii = (struct si_info *)sih; -+ -+ if (SI_FAST(sii)) { -+ /* Overloading the origidx variable to remember the coreid, -+ * this works because the core ids cannot be confused with -+ * core indices. -+ */ -+ *origidx = coreid; -+ if (coreid == CC_CORE_ID) -+ return CCREGS_FAST(sii); -+ else if (coreid == sih->buscoretype) -+ return PCIEREGS(sii); -+ } -+ INTR_OFF(sii, *intr_val); -+ *origidx = sii->curidx; -+ cc = ai_setcore(sih, coreid, 0); -+ return cc; -+} -+ -+/* restore coreidx and restore interrupt */ -+void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val) -+{ -+ struct si_info *sii; -+ -+ sii = (struct si_info *)sih; -+ if (SI_FAST(sii) -+ && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype))) -+ return; -+ -+ ai_setcoreidx(sih, coreid); -+ INTR_RESTORE(sii, intr_val); -+} -+ -+void ai_write_wrapperreg(struct si_pub *sih, u32 offset, u32 val) -+{ -+ struct si_info *sii = (struct si_info *)sih; -+ u32 *w = (u32 *) sii->curwrap; -+ W_REG(w + (offset / 4), val); -+ return; -+} -+ -+/* -+ * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set -+ * operation, switch back to the original core, and return the new value. -+ * -+ * When using the silicon backplane, no fiddling with interrupts or core -+ * switches is needed. -+ * -+ * Also, when using pci/pcie, we can optimize away the core switching for pci -+ * registers and (on newer pci cores) chipcommon registers. -+ */ -+uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask, -+ uint val) -+{ -+ uint origidx = 0; -+ u32 __iomem *r = NULL; -+ uint w; -+ uint intr_val = 0; -+ bool fast = false; -+ struct si_info *sii; -+ -+ sii = (struct si_info *)sih; -+ -+ if (coreidx >= SI_MAXCORES) -+ return 0; -+ -+ /* -+ * If pci/pcie, we can get at pci/pcie regs -+ * and on newer cores to chipc -+ */ -+ if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) { -+ /* Chipc registers are mapped at 12KB */ -+ fast = true; -+ r = (u32 __iomem *)((__iomem char *)sii->curmap + -+ PCI_16KB0_CCREGS_OFFSET + regoff); -+ } else if (sii->pub.buscoreidx == coreidx) { -+ /* -+ * pci registers are at either in the last 2KB of -+ * an 8KB window or, in pcie and pci rev 13 at 8KB -+ */ -+ fast = true; -+ if (SI_FAST(sii)) -+ r = (u32 __iomem *)((__iomem char *)sii->curmap + -+ PCI_16KB0_PCIREGS_OFFSET + regoff); -+ else -+ r = (u32 __iomem *)((__iomem char *)sii->curmap + -+ ((regoff >= SBCONFIGOFF) ? -+ PCI_BAR0_PCISBR_OFFSET : -+ PCI_BAR0_PCIREGS_OFFSET) + regoff); -+ } -+ -+ if (!fast) { -+ INTR_OFF(sii, intr_val); -+ -+ /* save current core index */ -+ origidx = ai_coreidx(&sii->pub); -+ -+ /* switch core */ -+ r = (u32 __iomem *) ((unsigned char __iomem *) -+ ai_setcoreidx(&sii->pub, coreidx) + regoff); -+ } -+ -+ /* mask and set */ -+ if (mask || val) { -+ w = (R_REG(r) & ~mask) | val; -+ W_REG(r, w); -+ } -+ -+ /* readback */ -+ w = R_REG(r); -+ -+ if (!fast) { -+ /* restore core index */ -+ if (origidx != coreidx) -+ ai_setcoreidx(&sii->pub, origidx); -+ -+ INTR_RESTORE(sii, intr_val); -+ } -+ -+ return w; -+} -+ -+void ai_core_disable(struct si_pub *sih, u32 bits) -+{ -+ struct si_info *sii; -+ u32 dummy; -+ struct aidmp *ai; -+ -+ sii = (struct si_info *)sih; -+ -+ ai = sii->curwrap; -+ -+ /* if core is already in reset, just return */ -+ if (R_REG(&ai->resetctrl) & AIRC_RESET) -+ return; -+ -+ W_REG(&ai->ioctrl, bits); -+ dummy = R_REG(&ai->ioctrl); -+ udelay(10); -+ -+ W_REG(&ai->resetctrl, AIRC_RESET); -+ udelay(1); -+} -+ -+/* reset and re-enable a core -+ * inputs: -+ * bits - core specific bits that are set during and after reset sequence -+ * resetbits - core specific bits that are set only during reset sequence -+ */ -+void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits) -+{ -+ struct si_info *sii; -+ struct aidmp *ai; -+ u32 dummy; -+ -+ sii = (struct si_info *)sih; -+ ai = sii->curwrap; -+ -+ /* -+ * Must do the disable sequence first to work -+ * for arbitrary current core state. -+ */ -+ ai_core_disable(sih, (bits | resetbits)); -+ -+ /* -+ * Now do the initialization sequence. -+ */ -+ W_REG(&ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN)); -+ dummy = R_REG(&ai->ioctrl); -+ W_REG(&ai->resetctrl, 0); -+ udelay(1); -+ -+ W_REG(&ai->ioctrl, (bits | SICF_CLOCK_EN)); -+ dummy = R_REG(&ai->ioctrl); -+ udelay(1); -+} -+ -+/* return the slow clock source - LPO, XTAL, or PCI */ -+static uint ai_slowclk_src(struct si_info *sii) -+{ -+ struct chipcregs __iomem *cc; -+ u32 val; -+ -+ if (sii->pub.ccrev < 6) { -+ pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, -+ &val); -+ if (val & PCI_CFG_GPIO_SCS) -+ return SCC_SS_PCI; -+ return SCC_SS_XTAL; -+ } else if (sii->pub.ccrev < 10) { -+ cc = (struct chipcregs __iomem *) -+ ai_setcoreidx(&sii->pub, sii->curidx); -+ return R_REG(&cc->slow_clk_ctl) & SCC_SS_MASK; -+ } else /* Insta-clock */ -+ return SCC_SS_XTAL; -+} -+ -+/* -+* return the ILP (slowclock) min or max frequency -+* precondition: we've established the chip has dynamic clk control -+*/ -+static uint ai_slowclk_freq(struct si_info *sii, bool max_freq, -+ struct chipcregs __iomem *cc) -+{ -+ u32 slowclk; -+ uint div; -+ -+ slowclk = ai_slowclk_src(sii); -+ if (sii->pub.ccrev < 6) { -+ if (slowclk == SCC_SS_PCI) -+ return max_freq ? (PCIMAXFREQ / 64) -+ : (PCIMINFREQ / 64); -+ else -+ return max_freq ? (XTALMAXFREQ / 32) -+ : (XTALMINFREQ / 32); -+ } else if (sii->pub.ccrev < 10) { -+ div = 4 * -+ (((R_REG(&cc->slow_clk_ctl) & SCC_CD_MASK) >> -+ SCC_CD_SHIFT) + 1); -+ if (slowclk == SCC_SS_LPO) -+ return max_freq ? LPOMAXFREQ : LPOMINFREQ; -+ else if (slowclk == SCC_SS_XTAL) -+ return max_freq ? (XTALMAXFREQ / div) -+ : (XTALMINFREQ / div); -+ else if (slowclk == SCC_SS_PCI) -+ return max_freq ? (PCIMAXFREQ / div) -+ : (PCIMINFREQ / div); -+ } else { -+ /* Chipc rev 10 is InstaClock */ -+ div = R_REG(&cc->system_clk_ctl) >> SYCC_CD_SHIFT; -+ div = 4 * (div + 1); -+ return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div); -+ } -+ return 0; -+} -+ -+static void -+ai_clkctl_setdelay(struct si_info *sii, struct chipcregs __iomem *cc) -+{ -+ uint slowmaxfreq, pll_delay, slowclk; -+ uint pll_on_delay, fref_sel_delay; -+ -+ pll_delay = PLL_DELAY; -+ -+ /* -+ * If the slow clock is not sourced by the xtal then -+ * add the xtal_on_delay since the xtal will also be -+ * powered down by dynamic clk control logic. -+ */ -+ -+ slowclk = ai_slowclk_src(sii); -+ if (slowclk != SCC_SS_XTAL) -+ pll_delay += XTAL_ON_DELAY; -+ -+ /* Starting with 4318 it is ILP that is used for the delays */ -+ slowmaxfreq = -+ ai_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? false : true, cc); -+ -+ pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; -+ fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; -+ -+ W_REG(&cc->pll_on_delay, pll_on_delay); -+ W_REG(&cc->fref_sel_delay, fref_sel_delay); -+} -+ -+/* initialize power control delay registers */ -+void ai_clkctl_init(struct si_pub *sih) -+{ -+ struct si_info *sii; -+ uint origidx = 0; -+ struct chipcregs __iomem *cc; -+ bool fast; -+ -+ if (!(sih->cccaps & CC_CAP_PWR_CTL)) -+ return; -+ -+ sii = (struct si_info *)sih; -+ fast = SI_FAST(sii); -+ if (!fast) { -+ origidx = sii->curidx; -+ cc = (struct chipcregs __iomem *) -+ ai_setcore(sih, CC_CORE_ID, 0); -+ if (cc == NULL) -+ return; -+ } else { -+ cc = (struct chipcregs __iomem *) CCREGS_FAST(sii); -+ if (cc == NULL) -+ return; -+ } -+ -+ /* set all Instaclk chip ILP to 1 MHz */ -+ if (sih->ccrev >= 10) -+ SET_REG(&cc->system_clk_ctl, SYCC_CD_MASK, -+ (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); -+ -+ ai_clkctl_setdelay(sii, cc); -+ -+ if (!fast) -+ ai_setcoreidx(sih, origidx); -+} -+ -+/* -+ * return the value suitable for writing to the -+ * dot11 core FAST_PWRUP_DELAY register -+ */ -+u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih) -+{ -+ struct si_info *sii; -+ uint origidx = 0; -+ struct chipcregs __iomem *cc; -+ uint slowminfreq; -+ u16 fpdelay; -+ uint intr_val = 0; -+ bool fast; -+ -+ sii = (struct si_info *)sih; -+ if (sih->cccaps & CC_CAP_PMU) { -+ INTR_OFF(sii, intr_val); -+ fpdelay = si_pmu_fast_pwrup_delay(sih); -+ INTR_RESTORE(sii, intr_val); -+ return fpdelay; -+ } -+ -+ if (!(sih->cccaps & CC_CAP_PWR_CTL)) -+ return 0; -+ -+ fast = SI_FAST(sii); -+ fpdelay = 0; -+ if (!fast) { -+ origidx = sii->curidx; -+ INTR_OFF(sii, intr_val); -+ cc = (struct chipcregs __iomem *) -+ ai_setcore(sih, CC_CORE_ID, 0); -+ if (cc == NULL) -+ goto done; -+ } else { -+ cc = (struct chipcregs __iomem *) CCREGS_FAST(sii); -+ if (cc == NULL) -+ goto done; -+ } -+ -+ slowminfreq = ai_slowclk_freq(sii, false, cc); -+ fpdelay = (((R_REG(&cc->pll_on_delay) + 2) * 1000000) + -+ (slowminfreq - 1)) / slowminfreq; -+ -+ done: -+ if (!fast) { -+ ai_setcoreidx(sih, origidx); -+ INTR_RESTORE(sii, intr_val); -+ } -+ return fpdelay; -+} -+ -+/* turn primary xtal and/or pll off/on */ -+int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on) -+{ -+ struct si_info *sii; -+ u32 in, out, outen; -+ -+ sii = (struct si_info *)sih; -+ -+ /* pcie core doesn't have any mapping to control the xtal pu */ -+ if (PCIE(sii)) -+ return -1; -+ -+ pci_read_config_dword(sii->pbus, PCI_GPIO_IN, &in); -+ pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, &out); -+ pci_read_config_dword(sii->pbus, PCI_GPIO_OUTEN, &outen); -+ -+ /* -+ * Avoid glitching the clock if GPRS is already using it. -+ * We can't actually read the state of the PLLPD so we infer it -+ * by the value of XTAL_PU which *is* readable via gpioin. -+ */ -+ if (on && (in & PCI_CFG_GPIO_XTAL)) -+ return 0; -+ -+ if (what & XTAL) -+ outen |= PCI_CFG_GPIO_XTAL; -+ if (what & PLL) -+ outen |= PCI_CFG_GPIO_PLL; -+ -+ if (on) { -+ /* turn primary xtal on */ -+ if (what & XTAL) { -+ out |= PCI_CFG_GPIO_XTAL; -+ if (what & PLL) -+ out |= PCI_CFG_GPIO_PLL; -+ pci_write_config_dword(sii->pbus, -+ PCI_GPIO_OUT, out); -+ pci_write_config_dword(sii->pbus, -+ PCI_GPIO_OUTEN, outen); -+ udelay(XTAL_ON_DELAY); -+ } -+ -+ /* turn pll on */ -+ if (what & PLL) { -+ out &= ~PCI_CFG_GPIO_PLL; -+ pci_write_config_dword(sii->pbus, -+ PCI_GPIO_OUT, out); -+ mdelay(2); -+ } -+ } else { -+ if (what & XTAL) -+ out &= ~PCI_CFG_GPIO_XTAL; -+ if (what & PLL) -+ out |= PCI_CFG_GPIO_PLL; -+ pci_write_config_dword(sii->pbus, -+ PCI_GPIO_OUT, out); -+ pci_write_config_dword(sii->pbus, -+ PCI_GPIO_OUTEN, outen); -+ } -+ -+ return 0; -+} -+ -+/* clk control mechanism through chipcommon, no policy checking */ -+static bool _ai_clkctl_cc(struct si_info *sii, uint mode) -+{ -+ uint origidx = 0; -+ struct chipcregs __iomem *cc; -+ u32 scc; -+ uint intr_val = 0; -+ bool fast = SI_FAST(sii); -+ -+ /* chipcommon cores prior to rev6 don't support dynamic clock control */ -+ if (sii->pub.ccrev < 6) -+ return false; -+ -+ if (!fast) { -+ INTR_OFF(sii, intr_val); -+ origidx = sii->curidx; -+ cc = (struct chipcregs __iomem *) -+ ai_setcore(&sii->pub, CC_CORE_ID, 0); -+ } else { -+ cc = (struct chipcregs __iomem *) CCREGS_FAST(sii); -+ if (cc == NULL) -+ goto done; -+ } -+ -+ if (!(sii->pub.cccaps & CC_CAP_PWR_CTL) && (sii->pub.ccrev < 20)) -+ goto done; -+ -+ switch (mode) { -+ case CLK_FAST: /* FORCEHT, fast (pll) clock */ -+ if (sii->pub.ccrev < 10) { -+ /* -+ * don't forget to force xtal back -+ * on before we clear SCC_DYN_XTAL.. -+ */ -+ ai_clkctl_xtal(&sii->pub, XTAL, ON); -+ SET_REG(&cc->slow_clk_ctl, -+ (SCC_XC | SCC_FS | SCC_IP), SCC_IP); -+ } else if (sii->pub.ccrev < 20) { -+ OR_REG(&cc->system_clk_ctl, SYCC_HR); -+ } else { -+ OR_REG(&cc->clk_ctl_st, CCS_FORCEHT); -+ } -+ -+ /* wait for the PLL */ -+ if (sii->pub.cccaps & CC_CAP_PMU) { -+ u32 htavail = CCS_HTAVAIL; -+ SPINWAIT(((R_REG(&cc->clk_ctl_st) & htavail) -+ == 0), PMU_MAX_TRANSITION_DLY); -+ } else { -+ udelay(PLL_DELAY); -+ } -+ break; -+ -+ case CLK_DYNAMIC: /* enable dynamic clock control */ -+ if (sii->pub.ccrev < 10) { -+ scc = R_REG(&cc->slow_clk_ctl); -+ scc &= ~(SCC_FS | SCC_IP | SCC_XC); -+ if ((scc & SCC_SS_MASK) != SCC_SS_XTAL) -+ scc |= SCC_XC; -+ W_REG(&cc->slow_clk_ctl, scc); -+ -+ /* -+ * for dynamic control, we have to -+ * release our xtal_pu "force on" -+ */ -+ if (scc & SCC_XC) -+ ai_clkctl_xtal(&sii->pub, XTAL, OFF); -+ } else if (sii->pub.ccrev < 20) { -+ /* Instaclock */ -+ AND_REG(&cc->system_clk_ctl, ~SYCC_HR); -+ } else { -+ AND_REG(&cc->clk_ctl_st, ~CCS_FORCEHT); -+ } -+ break; -+ -+ default: -+ break; -+ } -+ -+ done: -+ if (!fast) { -+ ai_setcoreidx(&sii->pub, origidx); -+ INTR_RESTORE(sii, intr_val); -+ } -+ return mode == CLK_FAST; -+} -+ -+/* -+ * clock control policy function throught chipcommon -+ * -+ * set dynamic clk control mode (forceslow, forcefast, dynamic) -+ * returns true if we are forcing fast clock -+ * this is a wrapper over the next internal function -+ * to allow flexible policy settings for outside caller -+ */ -+bool ai_clkctl_cc(struct si_pub *sih, uint mode) -+{ -+ struct si_info *sii; -+ -+ sii = (struct si_info *)sih; -+ -+ /* chipcommon cores prior to rev6 don't support dynamic clock control */ -+ if (sih->ccrev < 6) -+ return false; -+ -+ if (PCI_FORCEHT(sii)) -+ return mode == CLK_FAST; -+ -+ return _ai_clkctl_cc(sii, mode); -+} -+ -+/* Build device path */ -+int ai_devpath(struct si_pub *sih, char *path, int size) -+{ -+ int slen; -+ -+ if (!path || size <= 0) -+ return -1; -+ -+ slen = snprintf(path, (size_t) size, "pci/%u/%u/", -+ ((struct si_info *)sih)->pbus->bus->number, -+ PCI_SLOT(((struct pci_dev *) -+ (((struct si_info *)(sih))->pbus))->devfn)); -+ -+ if (slen < 0 || slen >= size) { -+ path[0] = '\0'; -+ return -1; -+ } -+ -+ return 0; -+} -+ -+void ai_pci_up(struct si_pub *sih) -+{ -+ struct si_info *sii; -+ -+ sii = (struct si_info *)sih; -+ -+ if (PCI_FORCEHT(sii)) -+ _ai_clkctl_cc(sii, CLK_FAST); -+ -+ if (PCIE(sii)) -+ pcicore_up(sii->pch, SI_PCIUP); -+ -+} -+ -+/* Unconfigure and/or apply various WARs when system is going to sleep mode */ -+void ai_pci_sleep(struct si_pub *sih) -+{ -+ struct si_info *sii; -+ -+ sii = (struct si_info *)sih; -+ -+ pcicore_sleep(sii->pch); -+} -+ -+/* Unconfigure and/or apply various WARs when going down */ -+void ai_pci_down(struct si_pub *sih) -+{ -+ struct si_info *sii; -+ -+ sii = (struct si_info *)sih; -+ -+ /* release FORCEHT since chip is going to "down" state */ -+ if (PCI_FORCEHT(sii)) -+ _ai_clkctl_cc(sii, CLK_DYNAMIC); -+ -+ pcicore_down(sii->pch, SI_PCIDOWN); -+} -+ -+/* -+ * Configure the pci core for pci client (NIC) action -+ * coremask is the bitvec of cores by index to be enabled. -+ */ -+void ai_pci_setup(struct si_pub *sih, uint coremask) -+{ -+ struct si_info *sii; -+ struct sbpciregs __iomem *regs = NULL; -+ u32 siflag = 0, w; -+ uint idx = 0; -+ -+ sii = (struct si_info *)sih; -+ -+ if (PCI(sii)) { -+ /* get current core index */ -+ idx = sii->curidx; -+ -+ /* we interrupt on this backplane flag number */ -+ siflag = ai_flag(sih); -+ -+ /* switch over to pci core */ -+ regs = ai_setcoreidx(sih, sii->pub.buscoreidx); -+ } -+ -+ /* -+ * Enable sb->pci interrupts. Assume -+ * PCI rev 2.3 support was added in pci core rev 6 and things changed.. -+ */ -+ if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) { -+ /* pci config write to set this core bit in PCIIntMask */ -+ pci_read_config_dword(sii->pbus, PCI_INT_MASK, &w); -+ w |= (coremask << PCI_SBIM_SHIFT); -+ pci_write_config_dword(sii->pbus, PCI_INT_MASK, w); -+ } else { -+ /* set sbintvec bit for our flag number */ -+ ai_setint(sih, siflag); -+ } -+ -+ if (PCI(sii)) { -+ pcicore_pci_setup(sii->pch, regs); -+ -+ /* switch back to previous core */ -+ ai_setcoreidx(sih, idx); -+ } -+} -+ -+/* -+ * Fixup SROMless PCI device's configuration. -+ * The current core may be changed upon return. -+ */ -+int ai_pci_fixcfg(struct si_pub *sih) -+{ -+ uint origidx; -+ void __iomem *regs = NULL; -+ struct si_info *sii = (struct si_info *)sih; -+ -+ /* Fixup PI in SROM shadow area to enable the correct PCI core access */ -+ /* save the current index */ -+ origidx = ai_coreidx(&sii->pub); -+ -+ /* check 'pi' is correct and fix it if not */ -+ regs = ai_setcore(&sii->pub, sii->pub.buscoretype, 0); -+ if (sii->pub.buscoretype == PCIE_CORE_ID) -+ pcicore_fixcfg_pcie(sii->pch, -+ (struct sbpcieregs __iomem *)regs); -+ else if (sii->pub.buscoretype == PCI_CORE_ID) -+ pcicore_fixcfg_pci(sii->pch, (struct sbpciregs __iomem *)regs); -+ -+ /* restore the original index */ -+ ai_setcoreidx(&sii->pub, origidx); -+ -+ pcicore_hwup(sii->pch); -+ return 0; -+} -+ -+/* mask&set gpiocontrol bits */ -+u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, u8 priority) -+{ -+ uint regoff; -+ -+ regoff = offsetof(struct chipcregs, gpiocontrol); -+ return ai_corereg(sih, SI_CC_IDX, regoff, mask, val); -+} -+ -+void ai_chipcontrl_epa4331(struct si_pub *sih, bool on) -+{ -+ struct si_info *sii; -+ struct chipcregs __iomem *cc; -+ uint origidx; -+ u32 val; -+ -+ sii = (struct si_info *)sih; -+ origidx = ai_coreidx(sih); -+ -+ cc = (struct chipcregs __iomem *) ai_setcore(sih, CC_CORE_ID, 0); -+ -+ val = R_REG(&cc->chipcontrol); -+ -+ if (on) { -+ if (sih->chippkg == 9 || sih->chippkg == 0xb) -+ /* Ext PA Controls for 4331 12x9 Package */ -+ W_REG(&cc->chipcontrol, val | -+ CCTRL4331_EXTPA_EN | -+ CCTRL4331_EXTPA_ON_GPIO2_5); -+ else -+ /* Ext PA Controls for 4331 12x12 Package */ -+ W_REG(&cc->chipcontrol, -+ val | CCTRL4331_EXTPA_EN); -+ } else { -+ val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); -+ W_REG(&cc->chipcontrol, val); -+ } -+ -+ ai_setcoreidx(sih, origidx); -+} -+ -+/* Enable BT-COEX & Ex-PA for 4313 */ -+void ai_epa_4313war(struct si_pub *sih) -+{ -+ struct si_info *sii; -+ struct chipcregs __iomem *cc; -+ uint origidx; -+ -+ sii = (struct si_info *)sih; -+ origidx = ai_coreidx(sih); -+ -+ cc = ai_setcore(sih, CC_CORE_ID, 0); -+ -+ /* EPA Fix */ -+ W_REG(&cc->gpiocontrol, -+ R_REG(&cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK); -+ -+ ai_setcoreidx(sih, origidx); -+} -+ -+/* check if the device is removed */ -+bool ai_deviceremoved(struct si_pub *sih) -+{ -+ u32 w; -+ struct si_info *sii; -+ -+ sii = (struct si_info *)sih; -+ -+ pci_read_config_dword(sii->pbus, PCI_VENDOR_ID, &w); -+ if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM) -+ return true; -+ -+ return false; -+} -+ -+bool ai_is_sprom_available(struct si_pub *sih) -+{ -+ if (sih->ccrev >= 31) { -+ struct si_info *sii; -+ uint origidx; -+ struct chipcregs __iomem *cc; -+ u32 sromctrl; -+ -+ if ((sih->cccaps & CC_CAP_SROM) == 0) -+ return false; -+ -+ sii = (struct si_info *)sih; -+ origidx = sii->curidx; -+ cc = ai_setcoreidx(sih, SI_CC_IDX); -+ sromctrl = R_REG(&cc->sromcontrol); -+ ai_setcoreidx(sih, origidx); -+ return sromctrl & SRC_PRESENT; -+ } -+ -+ switch (sih->chip) { -+ case BCM4313_CHIP_ID: -+ return (sih->chipst & CST4313_SPROM_PRESENT) != 0; -+ default: -+ return true; -+ } -+} -+ -+bool ai_is_otp_disabled(struct si_pub *sih) -+{ -+ switch (sih->chip) { -+ case BCM4313_CHIP_ID: -+ return (sih->chipst & CST4313_OTP_PRESENT) == 0; -+ /* These chips always have their OTP on */ -+ case BCM43224_CHIP_ID: -+ case BCM43225_CHIP_ID: -+ default: -+ return false; -+ } -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h.orig 2011-11-09 13:46:58.239800709 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h 2011-11-09 13:47:16.991566278 -0500 -@@ -0,0 +1,378 @@ -+/* -+ * Copyright (c) 2011 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_AIUTILS_H_ -+#define _BRCM_AIUTILS_H_ -+ -+#include "types.h" -+ -+/* -+ * SOC Interconnect Address Map. -+ * All regions may not exist on all chips. -+ */ -+/* each core gets 4Kbytes for registers */ -+#define SI_CORE_SIZE 0x1000 -+/* -+ * Max cores (this is arbitrary, for software -+ * convenience and could be changed if we -+ * make any larger chips -+ */ -+#define SI_MAXCORES 16 -+ -+/* Client Mode sb2pcitranslation2 size in bytes */ -+#define SI_PCI_DMA_SZ 0x40000000 -+ -+/* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */ -+#define SI_PCIE_DMA_H32 0x80000000 -+ -+/* core codes */ -+#define NODEV_CORE_ID 0x700 /* Invalid coreid */ -+#define CC_CORE_ID 0x800 /* chipcommon core */ -+#define ILINE20_CORE_ID 0x801 /* iline20 core */ -+#define SRAM_CORE_ID 0x802 /* sram core */ -+#define SDRAM_CORE_ID 0x803 /* sdram core */ -+#define PCI_CORE_ID 0x804 /* pci core */ -+#define MIPS_CORE_ID 0x805 /* mips core */ -+#define ENET_CORE_ID 0x806 /* enet mac core */ -+#define CODEC_CORE_ID 0x807 /* v90 codec core */ -+#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */ -+#define ADSL_CORE_ID 0x809 /* ADSL core */ -+#define ILINE100_CORE_ID 0x80a /* iline100 core */ -+#define IPSEC_CORE_ID 0x80b /* ipsec core */ -+#define UTOPIA_CORE_ID 0x80c /* utopia core */ -+#define PCMCIA_CORE_ID 0x80d /* pcmcia core */ -+#define SOCRAM_CORE_ID 0x80e /* internal memory core */ -+#define MEMC_CORE_ID 0x80f /* memc sdram core */ -+#define OFDM_CORE_ID 0x810 /* OFDM phy core */ -+#define EXTIF_CORE_ID 0x811 /* external interface core */ -+#define D11_CORE_ID 0x812 /* 802.11 MAC core */ -+#define APHY_CORE_ID 0x813 /* 802.11a phy core */ -+#define BPHY_CORE_ID 0x814 /* 802.11b phy core */ -+#define GPHY_CORE_ID 0x815 /* 802.11g phy core */ -+#define MIPS33_CORE_ID 0x816 /* mips3302 core */ -+#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */ -+#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */ -+#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */ -+#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */ -+#define SDIOH_CORE_ID 0x81b /* sdio host core */ -+#define ROBO_CORE_ID 0x81c /* roboswitch core */ -+#define ATA100_CORE_ID 0x81d /* parallel ATA core */ -+#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */ -+#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */ -+#define PCIE_CORE_ID 0x820 /* pci express core */ -+#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */ -+#define SRAMC_CORE_ID 0x822 /* SRAM controller core */ -+#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */ -+#define ARM11_CORE_ID 0x824 /* ARM 1176 core */ -+#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */ -+#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */ -+#define PMU_CORE_ID 0x827 /* PMU core */ -+#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */ -+#define SDIOD_CORE_ID 0x829 /* SDIO device core */ -+#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */ -+#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */ -+#define MIPS74K_CORE_ID 0x82c /* mips 74k core */ -+#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ -+#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */ -+#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */ -+#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */ -+#define SC_CORE_ID 0x831 /* shared common core */ -+#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */ -+#define SPIH_CORE_ID 0x833 /* SPI host core */ -+#define I2S_CORE_ID 0x834 /* I2S core */ -+#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */ -+#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */ -+#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */ -+#define DEF_AI_COMP 0xfff /* Default component, in ai chips it -+ * maps all unused address ranges -+ */ -+ -+/* chipcommon being the first core: */ -+#define SI_CC_IDX 0 -+ -+/* SOC Interconnect types (aka chip types) */ -+#define SOCI_AI 1 -+ -+/* Common core control flags */ -+#define SICF_BIST_EN 0x8000 -+#define SICF_PME_EN 0x4000 -+#define SICF_CORE_BITS 0x3ffc -+#define SICF_FGC 0x0002 -+#define SICF_CLOCK_EN 0x0001 -+ -+/* Common core status flags */ -+#define SISF_BIST_DONE 0x8000 -+#define SISF_BIST_ERROR 0x4000 -+#define SISF_GATED_CLK 0x2000 -+#define SISF_DMA64 0x1000 -+#define SISF_CORE_BITS 0x0fff -+ -+/* A register that is common to all cores to -+ * communicate w/PMU regarding clock control. -+ */ -+#define SI_CLK_CTL_ST 0x1e0 /* clock control and status */ -+ -+/* clk_ctl_st register */ -+#define CCS_FORCEALP 0x00000001 /* force ALP request */ -+#define CCS_FORCEHT 0x00000002 /* force HT request */ -+#define CCS_FORCEILP 0x00000004 /* force ILP request */ -+#define CCS_ALPAREQ 0x00000008 /* ALP Avail Request */ -+#define CCS_HTAREQ 0x00000010 /* HT Avail Request */ -+#define CCS_FORCEHWREQOFF 0x00000020 /* Force HW Clock Request Off */ -+#define CCS_ERSRC_REQ_MASK 0x00000700 /* external resource requests */ -+#define CCS_ERSRC_REQ_SHIFT 8 -+#define CCS_ALPAVAIL 0x00010000 /* ALP is available */ -+#define CCS_HTAVAIL 0x00020000 /* HT is available */ -+#define CCS_BP_ON_APL 0x00040000 /* RO: running on ALP clock */ -+#define CCS_BP_ON_HT 0x00080000 /* RO: running on HT clock */ -+#define CCS_ERSRC_STS_MASK 0x07000000 /* external resource status */ -+#define CCS_ERSRC_STS_SHIFT 24 -+ -+/* HT avail in chipc and pcmcia on 4328a0 */ -+#define CCS0_HTAVAIL 0x00010000 -+/* ALP avail in chipc and pcmcia on 4328a0 */ -+#define CCS0_ALPAVAIL 0x00020000 -+ -+/* Not really related to SOC Interconnect, but a couple of software -+ * conventions for the use the flash space: -+ */ -+ -+/* Minumum amount of flash we support */ -+#define FLASH_MIN 0x00020000 /* Minimum flash size */ -+ -+#define CC_SROM_OTP 0x800 /* SROM/OTP address space */ -+ -+/* gpiotimerval */ -+#define GPIO_ONTIME_SHIFT 16 -+ -+/* Fields in clkdiv */ -+#define CLKD_OTP 0x000f0000 -+#define CLKD_OTP_SHIFT 16 -+ -+/* Package IDs */ -+#define BCM4717_PKG_ID 9 /* 4717 package id */ -+#define BCM4718_PKG_ID 10 /* 4718 package id */ -+#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */ -+ -+/* these are router chips */ -+#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */ -+#define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */ -+#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */ -+ -+/* dynamic clock control defines */ -+#define LPOMINFREQ 25000 /* low power oscillator min */ -+#define LPOMAXFREQ 43000 /* low power oscillator max */ -+#define XTALMINFREQ 19800000 /* 20 MHz - 1% */ -+#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */ -+#define PCIMINFREQ 25000000 /* 25 MHz */ -+#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */ -+ -+#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ -+#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ -+ -+/* clkctl xtal what flags */ -+#define XTAL 0x1 /* primary crystal oscillator (2050) */ -+#define PLL 0x2 /* main chip pll */ -+ -+/* clkctl clk mode */ -+#define CLK_FAST 0 /* force fast (pll) clock */ -+#define CLK_DYNAMIC 2 /* enable dynamic clock control */ -+ -+/* GPIO usage priorities */ -+#define GPIO_DRV_PRIORITY 0 /* Driver */ -+#define GPIO_APP_PRIORITY 1 /* Application */ -+#define GPIO_HI_PRIORITY 2 /* Highest priority. Ignore GPIO -+ * reservation -+ */ -+ -+/* GPIO pull up/down */ -+#define GPIO_PULLUP 0 -+#define GPIO_PULLDN 1 -+ -+/* GPIO event regtype */ -+#define GPIO_REGEVT 0 /* GPIO register event */ -+#define GPIO_REGEVT_INTMSK 1 /* GPIO register event int mask */ -+#define GPIO_REGEVT_INTPOL 2 /* GPIO register event int polarity */ -+ -+/* device path */ -+#define SI_DEVPATH_BUFSZ 16 /* min buffer size in bytes */ -+ -+/* SI routine enumeration: to be used by update function with multiple hooks */ -+#define SI_DOATTACH 1 -+#define SI_PCIDOWN 2 -+#define SI_PCIUP 3 -+ -+/* -+ * Data structure to export all chip specific common variables -+ * public (read-only) portion of aiutils handle returned by si_attach() -+ */ -+struct si_pub { -+ uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */ -+ uint buscorerev; /* buscore rev */ -+ uint buscoreidx; /* buscore index */ -+ int ccrev; /* chip common core rev */ -+ u32 cccaps; /* chip common capabilities */ -+ u32 cccaps_ext; /* chip common capabilities extension */ -+ int pmurev; /* pmu core rev */ -+ u32 pmucaps; /* pmu capabilities */ -+ uint boardtype; /* board type */ -+ uint boardvendor; /* board vendor */ -+ uint boardflags; /* board flags */ -+ uint boardflags2; /* board flags2 */ -+ uint chip; /* chip number */ -+ uint chiprev; /* chip revision */ -+ uint chippkg; /* chip package option */ -+ u32 chipst; /* chip status */ -+ bool issim; /* chip is in simulation or emulation */ -+ uint socirev; /* SOC interconnect rev */ -+ bool pci_pr32414; -+ -+}; -+ -+struct pci_dev; -+ -+struct gpioh_item { -+ void *arg; -+ bool level; -+ void (*handler) (u32 stat, void *arg); -+ u32 event; -+ struct gpioh_item *next; -+}; -+ -+/* misc si info needed by some of the routines */ -+struct si_info { -+ struct si_pub pub; /* back plane public state (must be first) */ -+ struct pci_dev *pbus; /* handle to pci bus */ -+ uint dev_coreid; /* the core provides driver functions */ -+ void *intr_arg; /* interrupt callback function arg */ -+ u32 (*intrsoff_fn) (void *intr_arg); /* turns chip interrupts off */ -+ /* restore chip interrupts */ -+ void (*intrsrestore_fn) (void *intr_arg, u32 arg); -+ /* check if interrupts are enabled */ -+ bool (*intrsenabled_fn) (void *intr_arg); -+ -+ struct pcicore_info *pch; /* PCI/E core handle */ -+ -+ struct list_head var_list; /* list of srom variables */ -+ -+ void __iomem *curmap; /* current regs va */ -+ void __iomem *regs[SI_MAXCORES]; /* other regs va */ -+ -+ uint curidx; /* current core index */ -+ uint numcores; /* # discovered cores */ -+ uint coreid[SI_MAXCORES]; /* id of each core */ -+ u32 coresba[SI_MAXCORES]; /* backplane address of each core */ -+ void *regs2[SI_MAXCORES]; /* 2nd virtual address per core (usbh20) */ -+ u32 coresba2[SI_MAXCORES]; /* 2nd phys address per core (usbh20) */ -+ u32 coresba_size[SI_MAXCORES]; /* backplane address space size */ -+ u32 coresba2_size[SI_MAXCORES]; /* second address space size */ -+ -+ void *curwrap; /* current wrapper va */ -+ void *wrappers[SI_MAXCORES]; /* other cores wrapper va */ -+ u32 wrapba[SI_MAXCORES]; /* address of controlling wrapper */ -+ -+ u32 cia[SI_MAXCORES]; /* erom cia entry for each core */ -+ u32 cib[SI_MAXCORES]; /* erom cia entry for each core */ -+ u32 oob_router; /* oob router registers for axi */ -+}; -+ -+/* -+ * Many of the routines below take an 'sih' handle as their first arg. -+ * Allocate this by calling si_attach(). Free it by calling si_detach(). -+ * At any one time, the sih is logically focused on one particular si core -+ * (the "current core"). -+ * Use si_setcore() or si_setcoreidx() to change the association to another core -+ */ -+ -+ -+/* AMBA Interconnect exported externs */ -+extern uint ai_flag(struct si_pub *sih); -+extern void ai_setint(struct si_pub *sih, int siflag); -+extern uint ai_coreidx(struct si_pub *sih); -+extern uint ai_corevendor(struct si_pub *sih); -+extern uint ai_corerev(struct si_pub *sih); -+extern bool ai_iscoreup(struct si_pub *sih); -+extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val); -+extern void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val); -+extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val); -+extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask, -+ uint val); -+extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits); -+extern void ai_core_disable(struct si_pub *sih, u32 bits); -+extern int ai_numaddrspaces(struct si_pub *sih); -+extern u32 ai_addrspace(struct si_pub *sih, uint asidx); -+extern u32 ai_addrspacesize(struct si_pub *sih, uint asidx); -+extern void ai_write_wrap_reg(struct si_pub *sih, u32 offset, u32 val); -+ -+/* === exported functions === */ -+extern struct si_pub *ai_attach(void __iomem *regs, struct pci_dev *sdh); -+extern void ai_detach(struct si_pub *sih); -+extern uint ai_coreid(struct si_pub *sih); -+extern uint ai_corerev(struct si_pub *sih); -+extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask, -+ uint val); -+extern void ai_write_wrapperreg(struct si_pub *sih, u32 offset, u32 val); -+extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val); -+extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val); -+extern bool ai_iscoreup(struct si_pub *sih); -+extern uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit); -+extern void __iomem *ai_setcoreidx(struct si_pub *sih, uint coreidx); -+extern void __iomem *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit); -+extern void __iomem *ai_switch_core(struct si_pub *sih, uint coreid, -+ uint *origidx, uint *intr_val); -+extern void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val); -+extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits); -+extern void ai_core_disable(struct si_pub *sih, u32 bits); -+extern u32 ai_alp_clock(struct si_pub *sih); -+extern u32 ai_ilp_clock(struct si_pub *sih); -+extern void ai_pci_setup(struct si_pub *sih, uint coremask); -+extern void ai_setint(struct si_pub *sih, int siflag); -+extern bool ai_backplane64(struct si_pub *sih); -+extern void ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn, -+ void *intrsrestore_fn, -+ void *intrsenabled_fn, void *intr_arg); -+extern void ai_deregister_intr_callback(struct si_pub *sih); -+extern void ai_clkctl_init(struct si_pub *sih); -+extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih); -+extern bool ai_clkctl_cc(struct si_pub *sih, uint mode); -+extern int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on); -+extern bool ai_deviceremoved(struct si_pub *sih); -+extern u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, -+ u8 priority); -+ -+/* OTP status */ -+extern bool ai_is_otp_disabled(struct si_pub *sih); -+ -+/* SPROM availability */ -+extern bool ai_is_sprom_available(struct si_pub *sih); -+ -+/* -+ * Build device path. Path size must be >= SI_DEVPATH_BUFSZ. -+ * The returned path is NULL terminated and has trailing '/'. -+ * Return 0 on success, nonzero otherwise. -+ */ -+extern int ai_devpath(struct si_pub *sih, char *path, int size); -+ -+extern void ai_pci_sleep(struct si_pub *sih); -+extern void ai_pci_down(struct si_pub *sih); -+extern void ai_pci_up(struct si_pub *sih); -+extern int ai_pci_fixcfg(struct si_pub *sih); -+ -+extern void ai_chipcontrl_epa4331(struct si_pub *sih, bool on); -+/* Enable Ex-PA for 4313 */ -+extern void ai_epa_4313war(struct si_pub *sih); -+ -+#endif /* _BRCM_AIUTILS_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c.orig 2011-11-09 13:46:58.240800696 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c 2011-11-09 13:47:16.992566265 -0500 -@@ -0,0 +1,1241 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+#include -+ -+#include "rate.h" -+#include "scb.h" -+#include "phy/phy_hal.h" -+#include "antsel.h" -+#include "main.h" -+#include "ampdu.h" -+ -+/* max number of mpdus in an ampdu */ -+#define AMPDU_MAX_MPDU 32 -+/* max number of mpdus in an ampdu to a legacy */ -+#define AMPDU_NUM_MPDU_LEGACY 16 -+/* max Tx ba window size (in pdu) */ -+#define AMPDU_TX_BA_MAX_WSIZE 64 -+/* default Tx ba window size (in pdu) */ -+#define AMPDU_TX_BA_DEF_WSIZE 64 -+/* default Rx ba window size (in pdu) */ -+#define AMPDU_RX_BA_DEF_WSIZE 64 -+/* max Rx ba window size (in pdu) */ -+#define AMPDU_RX_BA_MAX_WSIZE 64 -+/* max dur of tx ampdu (in msec) */ -+#define AMPDU_MAX_DUR 5 -+/* default tx retry limit */ -+#define AMPDU_DEF_RETRY_LIMIT 5 -+/* default tx retry limit at reg rate */ -+#define AMPDU_DEF_RR_RETRY_LIMIT 2 -+/* default weight of ampdu in txfifo */ -+#define AMPDU_DEF_TXPKT_WEIGHT 2 -+/* default ffpld reserved bytes */ -+#define AMPDU_DEF_FFPLD_RSVD 2048 -+/* # of inis to be freed on detach */ -+#define AMPDU_INI_FREE 10 -+/* max # of mpdus released at a time */ -+#define AMPDU_SCB_MAX_RELEASE 20 -+ -+#define NUM_FFPLD_FIFO 4 /* number of fifo concerned by pre-loading */ -+#define FFPLD_TX_MAX_UNFL 200 /* default value of the average number of ampdu -+ * without underflows -+ */ -+#define FFPLD_MPDU_SIZE 1800 /* estimate of maximum mpdu size */ -+#define FFPLD_MAX_MCS 23 /* we don't deal with mcs 32 */ -+#define FFPLD_PLD_INCR 1000 /* increments in bytes */ -+#define FFPLD_MAX_AMPDU_CNT 5000 /* maximum number of ampdu we -+ * accumulate between resets. -+ */ -+ -+#define AMPDU_DELIMITER_LEN 4 -+ -+/* max allowed number of mpdus in an ampdu (2 streams) */ -+#define AMPDU_NUM_MPDU 16 -+ -+#define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE) -+ -+/* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */ -+#define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\ -+ AMPDU_DELIMITER_LEN + 3\ -+ + DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN) -+ -+/* modulo add/sub, bound = 2^k */ -+#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1)) -+#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1)) -+ -+/* structure to hold tx fifo information and pre-loading state -+ * counters specific to tx underflows of ampdus -+ * some counters might be redundant with the ones in wlc or ampdu structures. -+ * This allows to maintain a specific state independently of -+ * how often and/or when the wlc counters are updated. -+ * -+ * ampdu_pld_size: number of bytes to be pre-loaded -+ * mcs2ampdu_table: per-mcs max # of mpdus in an ampdu -+ * prev_txfunfl: num of underflows last read from the HW macstats counter -+ * accum_txfunfl: num of underflows since we modified pld params -+ * accum_txampdu: num of tx ampdu since we modified pld params -+ * prev_txampdu: previous reading of tx ampdu -+ * dmaxferrate: estimated dma avg xfer rate in kbits/sec -+ */ -+struct brcms_fifo_info { -+ u16 ampdu_pld_size; -+ u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1]; -+ u16 prev_txfunfl; -+ u32 accum_txfunfl; -+ u32 accum_txampdu; -+ u32 prev_txampdu; -+ u32 dmaxferrate; -+}; -+ -+/* AMPDU module specific state -+ * -+ * wlc: pointer to main wlc structure -+ * scb_handle: scb cubby handle to retrieve data from scb -+ * ini_enable: per-tid initiator enable/disable of ampdu -+ * ba_tx_wsize: Tx ba window size (in pdu) -+ * ba_rx_wsize: Rx ba window size (in pdu) -+ * retry_limit: mpdu transmit retry limit -+ * rr_retry_limit: mpdu transmit retry limit at regular rate -+ * retry_limit_tid: per-tid mpdu transmit retry limit -+ * rr_retry_limit_tid: per-tid mpdu transmit retry limit at regular rate -+ * mpdu_density: min mpdu spacing (0-7) ==> 2^(x-1)/8 usec -+ * max_pdu: max pdus allowed in ampdu -+ * dur: max duration of an ampdu (in msec) -+ * txpkt_weight: weight of ampdu in txfifo; reduces rate lag -+ * rx_factor: maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes -+ * ffpld_rsvd: number of bytes to reserve for preload -+ * max_txlen: max size of ampdu per mcs, bw and sgi -+ * mfbr: enable multiple fallback rate -+ * tx_max_funl: underflows should be kept such that -+ * (tx_max_funfl*underflows) < tx frames -+ * fifo_tb: table of fifo infos -+ */ -+struct ampdu_info { -+ struct brcms_c_info *wlc; -+ int scb_handle; -+ u8 ini_enable[AMPDU_MAX_SCB_TID]; -+ u8 ba_tx_wsize; -+ u8 ba_rx_wsize; -+ u8 retry_limit; -+ u8 rr_retry_limit; -+ u8 retry_limit_tid[AMPDU_MAX_SCB_TID]; -+ u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID]; -+ u8 mpdu_density; -+ s8 max_pdu; -+ u8 dur; -+ u8 txpkt_weight; -+ u8 rx_factor; -+ u32 ffpld_rsvd; -+ u32 max_txlen[MCS_TABLE_SIZE][2][2]; -+ bool mfbr; -+ u32 tx_max_funl; -+ struct brcms_fifo_info fifo_tb[NUM_FFPLD_FIFO]; -+}; -+ -+/* used for flushing ampdu packets */ -+struct cb_del_ampdu_pars { -+ struct ieee80211_sta *sta; -+ u16 tid; -+}; -+ -+static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur) -+{ -+ u32 rate, mcs; -+ -+ for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) { -+ /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */ -+ /* 20MHz, No SGI */ -+ rate = mcs_2_rate(mcs, false, false); -+ ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3; -+ /* 40 MHz, No SGI */ -+ rate = mcs_2_rate(mcs, true, false); -+ ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3; -+ /* 20MHz, SGI */ -+ rate = mcs_2_rate(mcs, false, true); -+ ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3; -+ /* 40 MHz, SGI */ -+ rate = mcs_2_rate(mcs, true, true); -+ ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3; -+ } -+} -+ -+static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu) -+{ -+ if (BRCMS_PHY_11N_CAP(ampdu->wlc->band)) -+ return true; -+ else -+ return false; -+} -+ -+static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on) -+{ -+ struct brcms_c_info *wlc = ampdu->wlc; -+ -+ wlc->pub->_ampdu = false; -+ -+ if (on) { -+ if (!(wlc->pub->_n_enab & SUPPORT_11N)) { -+ wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not " -+ "nmode enabled\n", wlc->pub->unit); -+ return -ENOTSUPP; -+ } -+ if (!brcms_c_ampdu_cap(ampdu)) { -+ wiphy_err(ampdu->wlc->wiphy, "wl%d: device not " -+ "ampdu capable\n", wlc->pub->unit); -+ return -ENOTSUPP; -+ } -+ wlc->pub->_ampdu = on; -+ } -+ -+ return 0; -+} -+ -+static void brcms_c_ffpld_init(struct ampdu_info *ampdu) -+{ -+ int i, j; -+ struct brcms_fifo_info *fifo; -+ -+ for (j = 0; j < NUM_FFPLD_FIFO; j++) { -+ fifo = (ampdu->fifo_tb + j); -+ fifo->ampdu_pld_size = 0; -+ for (i = 0; i <= FFPLD_MAX_MCS; i++) -+ fifo->mcs2ampdu_table[i] = 255; -+ fifo->dmaxferrate = 0; -+ fifo->accum_txampdu = 0; -+ fifo->prev_txfunfl = 0; -+ fifo->accum_txfunfl = 0; -+ -+ } -+} -+ -+struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc) -+{ -+ struct ampdu_info *ampdu; -+ int i; -+ -+ ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC); -+ if (!ampdu) -+ return NULL; -+ -+ ampdu->wlc = wlc; -+ -+ for (i = 0; i < AMPDU_MAX_SCB_TID; i++) -+ ampdu->ini_enable[i] = true; -+ /* Disable ampdu for VO by default */ -+ ampdu->ini_enable[PRIO_8021D_VO] = false; -+ ampdu->ini_enable[PRIO_8021D_NC] = false; -+ -+ /* Disable ampdu for BK by default since not enough fifo space */ -+ ampdu->ini_enable[PRIO_8021D_NONE] = false; -+ ampdu->ini_enable[PRIO_8021D_BK] = false; -+ -+ ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE; -+ ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE; -+ ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY; -+ ampdu->max_pdu = AUTO; -+ ampdu->dur = AMPDU_MAX_DUR; -+ ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT; -+ -+ ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD; -+ /* -+ * bump max ampdu rcv size to 64k for all 11n -+ * devices except 4321A0 and 4321A1 -+ */ -+ if (BRCMS_ISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2)) -+ ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K; -+ else -+ ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K; -+ ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT; -+ ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT; -+ -+ for (i = 0; i < AMPDU_MAX_SCB_TID; i++) { -+ ampdu->retry_limit_tid[i] = ampdu->retry_limit; -+ ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit; -+ } -+ -+ brcms_c_scb_ampdu_update_max_txlen(ampdu, ampdu->dur); -+ ampdu->mfbr = false; -+ /* try to set ampdu to the default value */ -+ brcms_c_ampdu_set(ampdu, wlc->pub->_ampdu); -+ -+ ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL; -+ brcms_c_ffpld_init(ampdu); -+ -+ return ampdu; -+} -+ -+void brcms_c_ampdu_detach(struct ampdu_info *ampdu) -+{ -+ kfree(ampdu); -+} -+ -+static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu, -+ struct scb *scb) -+{ -+ struct scb_ampdu *scb_ampdu = &scb->scb_ampdu; -+ int i; -+ -+ scb_ampdu->max_pdu = AMPDU_NUM_MPDU; -+ -+ /* go back to legacy size if some preloading is occurring */ -+ for (i = 0; i < NUM_FFPLD_FIFO; i++) { -+ if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR) -+ scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY; -+ } -+ -+ /* apply user override */ -+ if (ampdu->max_pdu != AUTO) -+ scb_ampdu->max_pdu = (u8) ampdu->max_pdu; -+ -+ scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, -+ AMPDU_SCB_MAX_RELEASE); -+ -+ if (scb_ampdu->max_rx_ampdu_bytes) -+ scb_ampdu->release = min_t(u8, scb_ampdu->release, -+ scb_ampdu->max_rx_ampdu_bytes / 1600); -+ -+ scb_ampdu->release = min(scb_ampdu->release, -+ ampdu->fifo_tb[TX_AC_BE_FIFO]. -+ mcs2ampdu_table[FFPLD_MAX_MCS]); -+} -+ -+static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu) -+{ -+ brcms_c_scb_ampdu_update_config(ampdu, &du->wlc->pri_scb); -+} -+ -+static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f) -+{ -+ int i; -+ u32 phy_rate, dma_rate, tmp; -+ u8 max_mpdu; -+ struct brcms_fifo_info *fifo = (ampdu->fifo_tb + f); -+ -+ /* recompute the dma rate */ -+ /* note : we divide/multiply by 100 to avoid integer overflows */ -+ max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], -+ AMPDU_NUM_MPDU_LEGACY); -+ phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false); -+ dma_rate = -+ (((phy_rate / 100) * -+ (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size)) -+ / (max_mpdu * FFPLD_MPDU_SIZE)) * 100; -+ fifo->dmaxferrate = dma_rate; -+ -+ /* fill up the mcs2ampdu table; do not recalc the last mcs */ -+ dma_rate = dma_rate >> 7; -+ for (i = 0; i < FFPLD_MAX_MCS; i++) { -+ /* shifting to keep it within integer range */ -+ phy_rate = mcs_2_rate(i, true, false) >> 7; -+ if (phy_rate > dma_rate) { -+ tmp = ((fifo->ampdu_pld_size * phy_rate) / -+ ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1; -+ tmp = min_t(u32, tmp, 255); -+ fifo->mcs2ampdu_table[i] = (u8) tmp; -+ } -+ } -+} -+ -+/* evaluate the dma transfer rate using the tx underflows as feedback. -+ * If necessary, increase tx fifo preloading. If not enough, -+ * decrease maximum ampdu size for each mcs till underflows stop -+ * Return 1 if pre-loading not active, -1 if not an underflow event, -+ * 0 if pre-loading module took care of the event. -+ */ -+static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid) -+{ -+ struct ampdu_info *ampdu = wlc->ampdu; -+ u32 phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false); -+ u32 txunfl_ratio; -+ u8 max_mpdu; -+ u32 current_ampdu_cnt = 0; -+ u16 max_pld_size; -+ u32 new_txunfl; -+ struct brcms_fifo_info *fifo = (ampdu->fifo_tb + fid); -+ uint xmtfifo_sz; -+ u16 cur_txunfl; -+ -+ /* return if we got here for a different reason than underflows */ -+ cur_txunfl = brcms_b_read_shm(wlc->hw, -+ M_UCODE_MACSTAT + -+ offsetof(struct macstat, txfunfl[fid])); -+ new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl); -+ if (new_txunfl == 0) { -+ BCMMSG(wlc->wiphy, "TX status FRAG set but no tx underflows\n"); -+ return -1; -+ } -+ fifo->prev_txfunfl = cur_txunfl; -+ -+ if (!ampdu->tx_max_funl) -+ return 1; -+ -+ /* check if fifo is big enough */ -+ if (brcms_b_xmtfifo_sz_get(wlc->hw, fid, &xmtfifo_sz)) -+ return -1; -+ -+ if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd) -+ return 1; -+ -+ max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd; -+ fifo->accum_txfunfl += new_txunfl; -+ -+ /* we need to wait for at least 10 underflows */ -+ if (fifo->accum_txfunfl < 10) -+ return 0; -+ -+ BCMMSG(wlc->wiphy, "ampdu_count %d tx_underflows %d\n", -+ current_ampdu_cnt, fifo->accum_txfunfl); -+ -+ /* -+ compute the current ratio of tx unfl per ampdu. -+ When the current ampdu count becomes too -+ big while the ratio remains small, we reset -+ the current count in order to not -+ introduce too big of a latency in detecting a -+ large amount of tx underflows later. -+ */ -+ -+ txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl; -+ -+ if (txunfl_ratio > ampdu->tx_max_funl) { -+ if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) -+ fifo->accum_txfunfl = 0; -+ -+ return 0; -+ } -+ max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], -+ AMPDU_NUM_MPDU_LEGACY); -+ -+ /* In case max value max_pdu is already lower than -+ the fifo depth, there is nothing more we can do. -+ */ -+ -+ if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) { -+ fifo->accum_txfunfl = 0; -+ return 0; -+ } -+ -+ if (fifo->ampdu_pld_size < max_pld_size) { -+ -+ /* increment by TX_FIFO_PLD_INC bytes */ -+ fifo->ampdu_pld_size += FFPLD_PLD_INCR; -+ if (fifo->ampdu_pld_size > max_pld_size) -+ fifo->ampdu_pld_size = max_pld_size; -+ -+ /* update scb release size */ -+ brcms_c_scb_ampdu_update_config_all(ampdu); -+ -+ /* -+ * compute a new dma xfer rate for max_mpdu @ max mcs. -+ * This is the minimum dma rate that can achieve no -+ * underflow condition for the current mpdu size. -+ * -+ * note : we divide/multiply by 100 to avoid integer overflows -+ */ -+ fifo->dmaxferrate = -+ (((phy_rate / 100) * -+ (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size)) -+ / (max_mpdu * FFPLD_MPDU_SIZE)) * 100; -+ -+ BCMMSG(wlc->wiphy, "DMA estimated transfer rate %d; " -+ "pre-load size %d\n", -+ fifo->dmaxferrate, fifo->ampdu_pld_size); -+ } else { -+ -+ /* decrease ampdu size */ -+ if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) { -+ if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255) -+ fifo->mcs2ampdu_table[FFPLD_MAX_MCS] = -+ AMPDU_NUM_MPDU_LEGACY - 1; -+ else -+ fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1; -+ -+ /* recompute the table */ -+ brcms_c_ffpld_calc_mcs2ampdu_table(ampdu, fid); -+ -+ /* update scb release size */ -+ brcms_c_scb_ampdu_update_config_all(ampdu); -+ } -+ } -+ fifo->accum_txfunfl = 0; -+ return 0; -+} -+ -+void -+brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, -+ u8 ba_wsize, /* negotiated ba window size (in pdu) */ -+ uint max_rx_ampdu_bytes) /* from ht_cap in beacon */ -+{ -+ struct scb_ampdu *scb_ampdu; -+ struct scb_ampdu_tid_ini *ini; -+ struct ampdu_info *ampdu = wlc->ampdu; -+ struct scb *scb = &wlc->pri_scb; -+ scb_ampdu = &scb->scb_ampdu; -+ -+ if (!ampdu->ini_enable[tid]) { -+ wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n", -+ __func__, tid); -+ return; -+ } -+ -+ ini = &scb_ampdu->ini[tid]; -+ ini->tid = tid; -+ ini->scb = scb_ampdu->scb; -+ ini->ba_wsize = ba_wsize; -+ scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes; -+} -+ -+int -+brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi, -+ struct sk_buff **pdu, int prec) -+{ -+ struct brcms_c_info *wlc; -+ struct sk_buff *p, *pkt[AMPDU_MAX_MPDU]; -+ u8 tid, ndelim; -+ int err = 0; -+ u8 preamble_type = BRCMS_GF_PREAMBLE; -+ u8 fbr_preamble_type = BRCMS_GF_PREAMBLE; -+ u8 rts_preamble_type = BRCMS_LONG_PREAMBLE; -+ u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE; -+ -+ bool rr = true, fbr = false; -+ uint i, count = 0, fifo, seg_cnt = 0; -+ u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0; -+ u32 ampdu_len, max_ampdu_bytes = 0; -+ struct d11txh *txh = NULL; -+ u8 *plcp; -+ struct ieee80211_hdr *h; -+ struct scb *scb; -+ struct scb_ampdu *scb_ampdu; -+ struct scb_ampdu_tid_ini *ini; -+ u8 mcs = 0; -+ bool use_rts = false, use_cts = false; -+ u32 rspec = 0, rspec_fallback = 0; -+ u32 rts_rspec = 0, rts_rspec_fallback = 0; -+ u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ; -+ struct ieee80211_rts *rts; -+ u8 rr_retry_limit; -+ struct brcms_fifo_info *f; -+ bool fbr_iscck; -+ struct ieee80211_tx_info *tx_info; -+ u16 qlen; -+ struct wiphy *wiphy; -+ -+ wlc = ampdu->wlc; -+ wiphy = wlc->wiphy; -+ p = *pdu; -+ -+ tid = (u8) (p->priority); -+ -+ f = ampdu->fifo_tb + prio2fifo[tid]; -+ -+ scb = &wlc->pri_scb; -+ scb_ampdu = &scb->scb_ampdu; -+ ini = &scb_ampdu->ini[tid]; -+ -+ /* Let pressure continue to build ... */ -+ qlen = pktq_plen(&qi->q, prec); -+ if (ini->tx_in_transit > 0 && -+ qlen < min(scb_ampdu->max_pdu, ini->ba_wsize)) -+ /* Collect multiple MPDU's to be sent in the next AMPDU */ -+ return -EBUSY; -+ -+ /* at this point we intend to transmit an AMPDU */ -+ rr_retry_limit = ampdu->rr_retry_limit_tid[tid]; -+ ampdu_len = 0; -+ dma_len = 0; -+ while (p) { -+ struct ieee80211_tx_rate *txrate; -+ -+ tx_info = IEEE80211_SKB_CB(p); -+ txrate = tx_info->status.rates; -+ -+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { -+ err = brcms_c_prep_pdu(wlc, p, &fifo); -+ } else { -+ wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__); -+ *pdu = NULL; -+ err = 0; -+ break; -+ } -+ -+ if (err) { -+ if (err == -EBUSY) { -+ wiphy_err(wiphy, "wl%d: sendampdu: " -+ "prep_xdu retry; seq 0x%x\n", -+ wlc->pub->unit, seq); -+ *pdu = p; -+ break; -+ } -+ -+ /* error in the packet; reject it */ -+ wiphy_err(wiphy, "wl%d: sendampdu: prep_xdu " -+ "rejected; seq 0x%x\n", wlc->pub->unit, seq); -+ *pdu = NULL; -+ break; -+ } -+ -+ /* pkt is good to be aggregated */ -+ txh = (struct d11txh *) p->data; -+ plcp = (u8 *) (txh + 1); -+ h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN); -+ seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT; -+ index = TX_SEQ_TO_INDEX(seq); -+ -+ /* check mcl fields and test whether it can be agg'd */ -+ mcl = le16_to_cpu(txh->MacTxControlLow); -+ mcl &= ~TXC_AMPDU_MASK; -+ fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3); -+ txh->PreloadSize = 0; /* always default to 0 */ -+ -+ /* Handle retry limits */ -+ if (txrate[0].count <= rr_retry_limit) { -+ txrate[0].count++; -+ rr = true; -+ fbr = false; -+ } else { -+ fbr = true; -+ rr = false; -+ txrate[1].count++; -+ } -+ -+ /* extract the length info */ -+ len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) -+ : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback); -+ -+ /* retrieve null delimiter count */ -+ ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM]; -+ seg_cnt += 1; -+ -+ BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n", -+ wlc->pub->unit, count, len); -+ -+ /* -+ * aggregateable mpdu. For ucode/hw agg, -+ * test whether need to break or change the epoch -+ */ -+ if (count == 0) { -+ mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT); -+ /* refill the bits since might be a retx mpdu */ -+ mcl |= TXC_STARTMSDU; -+ rts = (struct ieee80211_rts *)&txh->rts_frame; -+ -+ if (ieee80211_is_rts(rts->frame_control)) { -+ mcl |= TXC_SENDRTS; -+ use_rts = true; -+ } -+ if (ieee80211_is_cts(rts->frame_control)) { -+ mcl |= TXC_SENDCTS; -+ use_cts = true; -+ } -+ } else { -+ mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT); -+ mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS); -+ } -+ -+ len = roundup(len, 4); -+ ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN); -+ -+ dma_len += (u16) brcmu_pkttotlen(p); -+ -+ BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d" -+ " seg_cnt %d null delim %d\n", -+ wlc->pub->unit, ampdu_len, seg_cnt, ndelim); -+ -+ txh->MacTxControlLow = cpu_to_le16(mcl); -+ -+ /* this packet is added */ -+ pkt[count++] = p; -+ -+ /* patch the first MPDU */ -+ if (count == 1) { -+ u8 plcp0, plcp3, is40, sgi; -+ struct ieee80211_sta *sta; -+ -+ sta = tx_info->control.sta; -+ -+ if (rr) { -+ plcp0 = plcp[0]; -+ plcp3 = plcp[3]; -+ } else { -+ plcp0 = txh->FragPLCPFallback[0]; -+ plcp3 = txh->FragPLCPFallback[3]; -+ -+ } -+ is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0; -+ sgi = plcp3_issgi(plcp3) ? 1 : 0; -+ mcs = plcp0 & ~MIMO_PLCP_40MHZ; -+ max_ampdu_bytes = -+ min(scb_ampdu->max_rx_ampdu_bytes, -+ ampdu->max_txlen[mcs][is40][sgi]); -+ -+ if (is40) -+ mimo_ctlchbw = -+ CHSPEC_SB_UPPER(wlc_phy_chanspec_get( -+ wlc->band->pi)) -+ ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ; -+ -+ /* rebuild the rspec and rspec_fallback */ -+ rspec = RSPEC_MIMORATE; -+ rspec |= plcp[0] & ~MIMO_PLCP_40MHZ; -+ if (plcp[0] & MIMO_PLCP_40MHZ) -+ rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT); -+ -+ if (fbr_iscck) /* CCK */ -+ rspec_fallback = cck_rspec(cck_phy2mac_rate -+ (txh->FragPLCPFallback[0])); -+ else { /* MIMO */ -+ rspec_fallback = RSPEC_MIMORATE; -+ rspec_fallback |= -+ txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ; -+ if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ) -+ rspec_fallback |= -+ (PHY_TXC1_BW_40MHZ << -+ RSPEC_BW_SHIFT); -+ } -+ -+ if (use_rts || use_cts) { -+ rts_rspec = -+ brcms_c_rspec_to_rts_rspec(wlc, -+ rspec, false, mimo_ctlchbw); -+ rts_rspec_fallback = -+ brcms_c_rspec_to_rts_rspec(wlc, -+ rspec_fallback, false, mimo_ctlchbw); -+ } -+ } -+ -+ /* if (first mpdu for host agg) */ -+ /* test whether to add more */ -+ if ((mcs_2_rate(mcs, true, false) >= f->dmaxferrate) && -+ (count == f->mcs2ampdu_table[mcs])) { -+ BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping" -+ " ampdu at %d for mcs %d\n", -+ wlc->pub->unit, count, mcs); -+ break; -+ } -+ -+ if (count == scb_ampdu->max_pdu) -+ break; -+ -+ /* -+ * check to see if the next pkt is -+ * a candidate for aggregation -+ */ -+ p = pktq_ppeek(&qi->q, prec); -+ /* tx_info must be checked with current p */ -+ tx_info = IEEE80211_SKB_CB(p); -+ -+ if (p) { -+ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && -+ ((u8) (p->priority) == tid)) { -+ -+ plen = brcmu_pkttotlen(p) + -+ AMPDU_MAX_MPDU_OVERHEAD; -+ plen = max(scb_ampdu->min_len, plen); -+ -+ if ((plen + ampdu_len) > max_ampdu_bytes) { -+ p = NULL; -+ continue; -+ } -+ -+ /* -+ * check if there are enough -+ * descriptors available -+ */ -+ if (*wlc->core->txavail[fifo] <= seg_cnt + 1) { -+ wiphy_err(wiphy, "%s: No fifo space " -+ "!!\n", __func__); -+ p = NULL; -+ continue; -+ } -+ p = brcmu_pktq_pdeq(&qi->q, prec); -+ } else { -+ p = NULL; -+ } -+ } -+ } /* end while(p) */ -+ -+ ini->tx_in_transit += count; -+ -+ if (count) { -+ /* patch up the last txh */ -+ txh = (struct d11txh *) pkt[count - 1]->data; -+ mcl = le16_to_cpu(txh->MacTxControlLow); -+ mcl &= ~TXC_AMPDU_MASK; -+ mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT); -+ txh->MacTxControlLow = cpu_to_le16(mcl); -+ -+ /* remove the null delimiter after last mpdu */ -+ ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM]; -+ txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0; -+ ampdu_len -= ndelim * AMPDU_DELIMITER_LEN; -+ -+ /* remove the pad len from last mpdu */ -+ fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0); -+ len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) -+ : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback); -+ ampdu_len -= roundup(len, 4) - len; -+ -+ /* patch up the first txh & plcp */ -+ txh = (struct d11txh *) pkt[0]->data; -+ plcp = (u8 *) (txh + 1); -+ -+ BRCMS_SET_MIMO_PLCP_LEN(plcp, ampdu_len); -+ /* mark plcp to indicate ampdu */ -+ BRCMS_SET_MIMO_PLCP_AMPDU(plcp); -+ -+ /* reset the mixed mode header durations */ -+ if (txh->MModeLen) { -+ u16 mmodelen = -+ brcms_c_calc_lsig_len(wlc, rspec, ampdu_len); -+ txh->MModeLen = cpu_to_le16(mmodelen); -+ preamble_type = BRCMS_MM_PREAMBLE; -+ } -+ if (txh->MModeFbrLen) { -+ u16 mmfbrlen = -+ brcms_c_calc_lsig_len(wlc, rspec_fallback, -+ ampdu_len); -+ txh->MModeFbrLen = cpu_to_le16(mmfbrlen); -+ fbr_preamble_type = BRCMS_MM_PREAMBLE; -+ } -+ -+ /* set the preload length */ -+ if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) { -+ dma_len = min(dma_len, f->ampdu_pld_size); -+ txh->PreloadSize = cpu_to_le16(dma_len); -+ } else -+ txh->PreloadSize = 0; -+ -+ mch = le16_to_cpu(txh->MacTxControlHigh); -+ -+ /* update RTS dur fields */ -+ if (use_rts || use_cts) { -+ u16 durid; -+ rts = (struct ieee80211_rts *)&txh->rts_frame; -+ if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) == -+ TXC_PREAMBLE_RTS_MAIN_SHORT) -+ rts_preamble_type = BRCMS_SHORT_PREAMBLE; -+ -+ if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) == -+ TXC_PREAMBLE_RTS_FB_SHORT) -+ rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE; -+ -+ durid = -+ brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec, -+ rspec, rts_preamble_type, -+ preamble_type, ampdu_len, -+ true); -+ rts->duration = cpu_to_le16(durid); -+ durid = brcms_c_compute_rtscts_dur(wlc, use_cts, -+ rts_rspec_fallback, -+ rspec_fallback, -+ rts_fbr_preamble_type, -+ fbr_preamble_type, -+ ampdu_len, true); -+ txh->RTSDurFallback = cpu_to_le16(durid); -+ /* set TxFesTimeNormal */ -+ txh->TxFesTimeNormal = rts->duration; -+ /* set fallback rate version of TxFesTimeNormal */ -+ txh->TxFesTimeFallback = txh->RTSDurFallback; -+ } -+ -+ /* set flag and plcp for fallback rate */ -+ if (fbr) { -+ mch |= TXC_AMPDU_FBR; -+ txh->MacTxControlHigh = cpu_to_le16(mch); -+ BRCMS_SET_MIMO_PLCP_AMPDU(plcp); -+ BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback); -+ } -+ -+ BCMMSG(wlc->wiphy, "wl%d: count %d ampdu_len %d\n", -+ wlc->pub->unit, count, ampdu_len); -+ -+ /* inform rate_sel if it this is a rate probe pkt */ -+ frameid = le16_to_cpu(txh->TxFrameID); -+ if (frameid & TXFID_RATE_PROBE_MASK) -+ wiphy_err(wiphy, "%s: XXX what to do with " -+ "TXFID_RATE_PROBE_MASK!?\n", __func__); -+ -+ for (i = 0; i < count; i++) -+ brcms_c_txfifo(wlc, fifo, pkt[i], i == (count - 1), -+ ampdu->txpkt_weight); -+ -+ } -+ /* endif (count) */ -+ return err; -+} -+ -+static void -+brcms_c_ampdu_rate_status(struct brcms_c_info *wlc, -+ struct ieee80211_tx_info *tx_info, -+ struct tx_status *txs, u8 mcs) -+{ -+ struct ieee80211_tx_rate *txrate = tx_info->status.rates; -+ int i; -+ -+ /* clear the rest of the rates */ -+ for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) { -+ txrate[i].idx = -1; -+ txrate[i].count = 0; -+ } -+} -+ -+static void -+brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, -+ struct sk_buff *p, struct tx_status *txs, -+ u32 s1, u32 s2) -+{ -+ struct scb_ampdu *scb_ampdu; -+ struct brcms_c_info *wlc = ampdu->wlc; -+ struct scb_ampdu_tid_ini *ini; -+ u8 bitmap[8], queue, tid; -+ struct d11txh *txh; -+ u8 *plcp; -+ struct ieee80211_hdr *h; -+ u16 seq, start_seq = 0, bindex, index, mcl; -+ u8 mcs = 0; -+ bool ba_recd = false, ack_recd = false; -+ u8 suc_mpdu = 0, tot_mpdu = 0; -+ uint supr_status; -+ bool update_rate = true, retry = true, tx_error = false; -+ u16 mimoantsel = 0; -+ u8 antselid = 0; -+ u8 retry_limit, rr_retry_limit; -+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p); -+ struct wiphy *wiphy = wlc->wiphy; -+ -+#ifdef BCMDBG -+ u8 hole[AMPDU_MAX_MPDU]; -+ memset(hole, 0, sizeof(hole)); -+#endif -+ -+ scb_ampdu = &scb->scb_ampdu; -+ tid = (u8) (p->priority); -+ -+ ini = &scb_ampdu->ini[tid]; -+ retry_limit = ampdu->retry_limit_tid[tid]; -+ rr_retry_limit = ampdu->rr_retry_limit_tid[tid]; -+ memset(bitmap, 0, sizeof(bitmap)); -+ queue = txs->frameid & TXFID_QUEUE_MASK; -+ supr_status = txs->status & TX_STATUS_SUPR_MASK; -+ -+ if (txs->status & TX_STATUS_ACK_RCV) { -+ if (TX_STATUS_SUPR_UF == supr_status) -+ update_rate = false; -+ -+ WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE)); -+ start_seq = txs->sequence >> SEQNUM_SHIFT; -+ bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >> -+ TX_STATUS_BA_BMAP03_SHIFT; -+ -+ WARN_ON(s1 & TX_STATUS_INTERMEDIATE); -+ WARN_ON(!(s1 & TX_STATUS_AMPDU)); -+ -+ bitmap[0] |= -+ (s1 & TX_STATUS_BA_BMAP47_MASK) << -+ TX_STATUS_BA_BMAP47_SHIFT; -+ bitmap[1] = (s1 >> 8) & 0xff; -+ bitmap[2] = (s1 >> 16) & 0xff; -+ bitmap[3] = (s1 >> 24) & 0xff; -+ -+ bitmap[4] = s2 & 0xff; -+ bitmap[5] = (s2 >> 8) & 0xff; -+ bitmap[6] = (s2 >> 16) & 0xff; -+ bitmap[7] = (s2 >> 24) & 0xff; -+ -+ ba_recd = true; -+ } else { -+ if (supr_status) { -+ update_rate = false; -+ if (supr_status == TX_STATUS_SUPR_BADCH) { -+ wiphy_err(wiphy, "%s: Pkt tx suppressed, " -+ "illegal channel possibly %d\n", -+ __func__, CHSPEC_CHANNEL( -+ wlc->default_bss->chanspec)); -+ } else { -+ if (supr_status != TX_STATUS_SUPR_FRAG) -+ wiphy_err(wiphy, "%s:" -+ "supr_status 0x%x\n", -+ __func__, supr_status); -+ } -+ /* no need to retry for badch; will fail again */ -+ if (supr_status == TX_STATUS_SUPR_BADCH || -+ supr_status == TX_STATUS_SUPR_EXPTIME) { -+ retry = false; -+ } else if (supr_status == TX_STATUS_SUPR_EXPTIME) { -+ /* TX underflow: -+ * try tuning pre-loading or ampdu size -+ */ -+ } else if (supr_status == TX_STATUS_SUPR_FRAG) { -+ /* -+ * if there were underflows, but pre-loading -+ * is not active, notify rate adaptation. -+ */ -+ if (brcms_c_ffpld_check_txfunfl(wlc, -+ prio2fifo[tid]) > 0) -+ tx_error = true; -+ } -+ } else if (txs->phyerr) { -+ update_rate = false; -+ wiphy_err(wiphy, "wl%d: ampdu tx phy " -+ "error (0x%x)\n", wlc->pub->unit, -+ txs->phyerr); -+ -+ if (brcm_msg_level & LOG_ERROR_VAL) { -+ brcmu_prpkt("txpkt (AMPDU)", p); -+ brcms_c_print_txdesc((struct d11txh *) p->data); -+ } -+ brcms_c_print_txstatus(txs); -+ } -+ } -+ -+ /* loop through all pkts and retry if not acked */ -+ while (p) { -+ tx_info = IEEE80211_SKB_CB(p); -+ txh = (struct d11txh *) p->data; -+ mcl = le16_to_cpu(txh->MacTxControlLow); -+ plcp = (u8 *) (txh + 1); -+ h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN); -+ seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT; -+ -+ if (tot_mpdu == 0) { -+ mcs = plcp[0] & MIMO_PLCP_MCS_MASK; -+ mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel); -+ } -+ -+ index = TX_SEQ_TO_INDEX(seq); -+ ack_recd = false; -+ if (ba_recd) { -+ bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX); -+ BCMMSG(wlc->wiphy, "tid %d seq %d," -+ " start_seq %d, bindex %d set %d, index %d\n", -+ tid, seq, start_seq, bindex, -+ isset(bitmap, bindex), index); -+ /* if acked then clear bit and free packet */ -+ if ((bindex < AMPDU_TX_BA_MAX_WSIZE) -+ && isset(bitmap, bindex)) { -+ ini->tx_in_transit--; -+ ini->txretry[index] = 0; -+ -+ /* -+ * ampdu_ack_len: -+ * number of acked aggregated frames -+ */ -+ /* ampdu_len: number of aggregated frames */ -+ brcms_c_ampdu_rate_status(wlc, tx_info, txs, -+ mcs); -+ tx_info->flags |= IEEE80211_TX_STAT_ACK; -+ tx_info->flags |= IEEE80211_TX_STAT_AMPDU; -+ tx_info->status.ampdu_ack_len = -+ tx_info->status.ampdu_len = 1; -+ -+ skb_pull(p, D11_PHY_HDR_LEN); -+ skb_pull(p, D11_TXH_LEN); -+ -+ ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, -+ p); -+ ack_recd = true; -+ suc_mpdu++; -+ } -+ } -+ /* either retransmit or send bar if ack not recd */ -+ if (!ack_recd) { -+ struct ieee80211_tx_rate *txrate = -+ tx_info->status.rates; -+ if (retry && (txrate[0].count < (int)retry_limit)) { -+ ini->txretry[index]++; -+ ini->tx_in_transit--; -+ /* -+ * Use high prededence for retransmit to -+ * give some punch -+ */ -+ /* brcms_c_txq_enq(wlc, scb, p, -+ * BRCMS_PRIO_TO_PREC(tid)); */ -+ brcms_c_txq_enq(wlc, scb, p, -+ BRCMS_PRIO_TO_HI_PREC(tid)); -+ } else { -+ /* Retry timeout */ -+ ini->tx_in_transit--; -+ ieee80211_tx_info_clear_status(tx_info); -+ tx_info->status.ampdu_ack_len = 0; -+ tx_info->status.ampdu_len = 1; -+ tx_info->flags |= -+ IEEE80211_TX_STAT_AMPDU_NO_BACK; -+ skb_pull(p, D11_PHY_HDR_LEN); -+ skb_pull(p, D11_TXH_LEN); -+ wiphy_err(wiphy, "%s: BA Timeout, seq %d, in_" -+ "transit %d\n", "AMPDU status", seq, -+ ini->tx_in_transit); -+ ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, -+ p); -+ } -+ } -+ tot_mpdu++; -+ -+ /* break out if last packet of ampdu */ -+ if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) == -+ TXC_AMPDU_LAST) -+ break; -+ -+ p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED); -+ } -+ brcms_c_send_q(wlc); -+ -+ /* update rate state */ -+ antselid = brcms_c_antsel_antsel2id(wlc->asi, mimoantsel); -+ -+ brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight); -+} -+ -+void -+brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb, -+ struct sk_buff *p, struct tx_status *txs) -+{ -+ struct scb_ampdu *scb_ampdu; -+ struct brcms_c_info *wlc = ampdu->wlc; -+ struct scb_ampdu_tid_ini *ini; -+ u32 s1 = 0, s2 = 0; -+ struct ieee80211_tx_info *tx_info; -+ -+ tx_info = IEEE80211_SKB_CB(p); -+ -+ /* BMAC_NOTE: For the split driver, second level txstatus comes later -+ * So if the ACK was received then wait for the second level else just -+ * call the first one -+ */ -+ if (txs->status & TX_STATUS_ACK_RCV) { -+ u8 status_delay = 0; -+ -+ /* wait till the next 8 bytes of txstatus is available */ -+ while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) { -+ udelay(1); -+ status_delay++; -+ if (status_delay > 10) -+ return; /* error condition */ -+ } -+ -+ s2 = R_REG(&wlc->regs->frmtxstatus2); -+ } -+ -+ if (scb) { -+ scb_ampdu = &scb->scb_ampdu; -+ ini = &scb_ampdu->ini[p->priority]; -+ brcms_c_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2); -+ } else { -+ /* loop through all pkts and free */ -+ u8 queue = txs->frameid & TXFID_QUEUE_MASK; -+ struct d11txh *txh; -+ u16 mcl; -+ while (p) { -+ tx_info = IEEE80211_SKB_CB(p); -+ txh = (struct d11txh *) p->data; -+ mcl = le16_to_cpu(txh->MacTxControlLow); -+ brcmu_pkt_buf_free_skb(p); -+ /* break out if last packet of ampdu */ -+ if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) == -+ TXC_AMPDU_LAST) -+ break; -+ p = dma_getnexttxp(wlc->hw->di[queue], -+ DMA_RANGE_TRANSMITTED); -+ } -+ brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight); -+ } -+} -+ -+void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc) -+{ -+ char template[T_RAM_ACCESS_SZ * 2]; -+ -+ /* driver needs to write the ta in the template; ta is at offset 16 */ -+ memset(template, 0, sizeof(template)); -+ memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN); -+ brcms_b_write_template_ram(wlc->hw, (T_BA_TPL_BASE + 16), -+ (T_RAM_ACCESS_SZ * 2), -+ template); -+} -+ -+bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid) -+{ -+ return wlc->ampdu->ini_enable[tid]; -+} -+ -+void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu) -+{ -+ struct brcms_c_info *wlc = ampdu->wlc; -+ -+ /* -+ * Extend ucode internal watchdog timer to -+ * match larger received frames -+ */ -+ if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) == -+ IEEE80211_HT_MAX_AMPDU_64K) { -+ brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX); -+ brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX); -+ } else { -+ brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF); -+ brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF); -+ } -+} -+ -+/* -+ * callback function that helps flushing ampdu packets from a priority queue -+ */ -+static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a) -+{ -+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu); -+ struct cb_del_ampdu_pars *ampdu_pars = -+ (struct cb_del_ampdu_pars *)arg_a; -+ bool rc; -+ -+ rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false; -+ rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL || -+ tx_info->control.sta == ampdu_pars->sta); -+ rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid); -+ return rc; -+} -+ -+/* -+ * callback function that helps invalidating ampdu packets in a DMA queue -+ */ -+static void dma_cb_fn_ampdu(void *txi, void *arg_a) -+{ -+ struct ieee80211_sta *sta = arg_a; -+ struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi; -+ -+ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && -+ (tx_info->control.sta == sta || sta == NULL)) -+ tx_info->control.sta = NULL; -+} -+ -+/* -+ * When a remote party is no longer available for ampdu communication, any -+ * pending tx ampdu packets in the driver have to be flushed. -+ */ -+void brcms_c_ampdu_flush(struct brcms_c_info *wlc, -+ struct ieee80211_sta *sta, u16 tid) -+{ -+ struct brcms_txq_info *qi = wlc->pkt_queue; -+ struct pktq *pq = &qi->q; -+ int prec; -+ struct cb_del_ampdu_pars ampdu_pars; -+ -+ ampdu_pars.sta = sta; -+ ampdu_pars.tid = tid; -+ for (prec = 0; prec < pq->num_prec; prec++) -+ brcmu_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt, -+ (void *)&du_pars); -+ brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu); -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h.orig 2011-11-09 13:46:58.240800696 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h 2011-11-09 13:47:16.992566265 -0500 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_AMPDU_H_ -+#define _BRCM_AMPDU_H_ -+ -+extern struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc); -+extern void brcms_c_ampdu_detach(struct ampdu_info *ampdu); -+extern int brcms_c_sendampdu(struct ampdu_info *ampdu, -+ struct brcms_txq_info *qi, -+ struct sk_buff **aggp, int prec); -+extern void brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb, -+ struct sk_buff *p, struct tx_status *txs); -+extern void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc); -+extern void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu); -+ -+#endif /* _BRCM_AMPDU_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.c.orig 2011-11-09 13:46:58.240800696 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.c 2011-11-09 13:47:16.992566265 -0500 -@@ -0,0 +1,307 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+ -+#include "types.h" -+#include "main.h" -+#include "phy_shim.h" -+#include "antsel.h" -+ -+#define ANT_SELCFG_AUTO 0x80 /* bit indicates antenna sel AUTO */ -+#define ANT_SELCFG_MASK 0x33 /* antenna configuration mask */ -+#define ANT_SELCFG_TX_UNICAST 0 /* unicast tx antenna configuration */ -+#define ANT_SELCFG_RX_UNICAST 1 /* unicast rx antenna configuration */ -+#define ANT_SELCFG_TX_DEF 2 /* default tx antenna configuration */ -+#define ANT_SELCFG_RX_DEF 3 /* default rx antenna configuration */ -+ -+/* useful macros */ -+#define BRCMS_ANTSEL_11N_0(ant) ((((ant) & ANT_SELCFG_MASK) >> 4) & 0xf) -+#define BRCMS_ANTSEL_11N_1(ant) (((ant) & ANT_SELCFG_MASK) & 0xf) -+#define BRCMS_ANTIDX_11N(ant) (((BRCMS_ANTSEL_11N_0(ant)) << 2) +\ -+ (BRCMS_ANTSEL_11N_1(ant))) -+#define BRCMS_ANT_ISAUTO_11N(ant) (((ant) & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO) -+#define BRCMS_ANTSEL_11N(ant) ((ant) & ANT_SELCFG_MASK) -+ -+/* antenna switch */ -+/* defines for no boardlevel antenna diversity */ -+#define ANT_SELCFG_DEF_2x2 0x01 /* default antenna configuration */ -+ -+/* 2x3 antdiv defines and tables for GPIO communication */ -+#define ANT_SELCFG_NUM_2x3 3 -+#define ANT_SELCFG_DEF_2x3 0x01 /* default antenna configuration */ -+ -+/* 2x4 antdiv rev4 defines and tables for GPIO communication */ -+#define ANT_SELCFG_NUM_2x4 4 -+#define ANT_SELCFG_DEF_2x4 0x02 /* default antenna configuration */ -+ -+static const u16 mimo_2x4_div_antselpat_tbl[] = { -+ 0, 0, 0x9, 0xa, /* ant0: 0 ant1: 2,3 */ -+ 0, 0, 0x5, 0x6, /* ant0: 1 ant1: 2,3 */ -+ 0, 0, 0, 0, /* n.a. */ -+ 0, 0, 0, 0 /* n.a. */ -+}; -+ -+static const u8 mimo_2x4_div_antselid_tbl[16] = { -+ 0, 0, 0, 0, 0, 2, 3, 0, -+ 0, 0, 1, 0, 0, 0, 0, 0 /* pat to antselid */ -+}; -+ -+static const u16 mimo_2x3_div_antselpat_tbl[] = { -+ 16, 0, 1, 16, /* ant0: 0 ant1: 1,2 */ -+ 16, 16, 16, 16, /* n.a. */ -+ 16, 2, 16, 16, /* ant0: 2 ant1: 1 */ -+ 16, 16, 16, 16 /* n.a. */ -+}; -+ -+static const u8 mimo_2x3_div_antselid_tbl[16] = { -+ 0, 1, 2, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0 /* pat to antselid */ -+}; -+ -+/* boardlevel antenna selection: init antenna selection structure */ -+static void -+brcms_c_antsel_init_cfg(struct antsel_info *asi, struct brcms_antselcfg *antsel, -+ bool auto_sel) -+{ -+ if (asi->antsel_type == ANTSEL_2x3) { -+ u8 antcfg_def = ANT_SELCFG_DEF_2x3 | -+ ((asi->antsel_avail && auto_sel) ? ANT_SELCFG_AUTO : 0); -+ antsel->ant_config[ANT_SELCFG_TX_DEF] = antcfg_def; -+ antsel->ant_config[ANT_SELCFG_TX_UNICAST] = antcfg_def; -+ antsel->ant_config[ANT_SELCFG_RX_DEF] = antcfg_def; -+ antsel->ant_config[ANT_SELCFG_RX_UNICAST] = antcfg_def; -+ antsel->num_antcfg = ANT_SELCFG_NUM_2x3; -+ -+ } else if (asi->antsel_type == ANTSEL_2x4) { -+ -+ antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x4; -+ antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x4; -+ antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x4; -+ antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x4; -+ antsel->num_antcfg = ANT_SELCFG_NUM_2x4; -+ -+ } else { /* no antenna selection available */ -+ -+ antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x2; -+ antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x2; -+ antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x2; -+ antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x2; -+ antsel->num_antcfg = 0; -+ } -+} -+ -+struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) -+{ -+ struct antsel_info *asi; -+ struct si_pub *sih = wlc->hw->sih; -+ -+ asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC); -+ if (!asi) -+ return NULL; -+ -+ asi->wlc = wlc; -+ asi->pub = wlc->pub; -+ asi->antsel_type = ANTSEL_NA; -+ asi->antsel_avail = false; -+ asi->antsel_antswitch = (u8) getintvar(sih, BRCMS_SROM_ANTSWITCH); -+ -+ if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) { -+ switch (asi->antsel_antswitch) { -+ case ANTSWITCH_TYPE_1: -+ case ANTSWITCH_TYPE_2: -+ case ANTSWITCH_TYPE_3: -+ /* 4321/2 board with 2x3 switch logic */ -+ asi->antsel_type = ANTSEL_2x3; -+ /* Antenna selection availability */ -+ if (((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) || -+ ((u16) getintvar(sih, BRCMS_SROM_AA5G) == 7)) { -+ asi->antsel_avail = true; -+ } else if ( -+ (u16) getintvar(sih, BRCMS_SROM_AA2G) == 3 || -+ (u16) getintvar(sih, BRCMS_SROM_AA5G) == 3) { -+ asi->antsel_avail = false; -+ } else { -+ asi->antsel_avail = false; -+ wiphy_err(wlc->wiphy, "antsel_attach: 2o3 " -+ "board cfg invalid\n"); -+ } -+ -+ break; -+ default: -+ break; -+ } -+ } else if ((asi->pub->sromrev == 4) && -+ ((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) && -+ ((u16) getintvar(sih, BRCMS_SROM_AA5G) == 0)) { -+ /* hack to match old 4321CB2 cards with 2of3 antenna switch */ -+ asi->antsel_type = ANTSEL_2x3; -+ asi->antsel_avail = true; -+ } else if (asi->pub->boardflags2 & BFL2_2X4_DIV) { -+ asi->antsel_type = ANTSEL_2x4; -+ asi->antsel_avail = true; -+ } -+ -+ /* Set the antenna selection type for the low driver */ -+ brcms_b_antsel_type_set(wlc->hw, asi->antsel_type); -+ -+ /* Init (auto/manual) antenna selection */ -+ brcms_c_antsel_init_cfg(asi, &asi->antcfg_11n, true); -+ brcms_c_antsel_init_cfg(asi, &asi->antcfg_cur, true); -+ -+ return asi; -+} -+ -+void brcms_c_antsel_detach(struct antsel_info *asi) -+{ -+ kfree(asi); -+} -+ -+/* -+ * boardlevel antenna selection: -+ * convert ant_cfg to mimo_antsel (ucode interface) -+ */ -+static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg) -+{ -+ u8 idx = BRCMS_ANTIDX_11N(BRCMS_ANTSEL_11N(ant_cfg)); -+ u16 mimo_antsel = 0; -+ -+ if (asi->antsel_type == ANTSEL_2x4) { -+ /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */ -+ mimo_antsel = (mimo_2x4_div_antselpat_tbl[idx] & 0xf); -+ return mimo_antsel; -+ -+ } else if (asi->antsel_type == ANTSEL_2x3) { -+ /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */ -+ mimo_antsel = (mimo_2x3_div_antselpat_tbl[idx] & 0xf); -+ return mimo_antsel; -+ } -+ -+ return mimo_antsel; -+} -+ -+/* boardlevel antenna selection: ucode interface control */ -+static int brcms_c_antsel_cfgupd(struct antsel_info *asi, -+ struct brcms_antselcfg *antsel) -+{ -+ struct brcms_c_info *wlc = asi->wlc; -+ u8 ant_cfg; -+ u16 mimo_antsel; -+ -+ /* 1) Update TX antconfig for all frames that are not unicast data -+ * (aka default TX) -+ */ -+ ant_cfg = antsel->ant_config[ANT_SELCFG_TX_DEF]; -+ mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg); -+ brcms_b_write_shm(wlc->hw, M_MIMO_ANTSEL_TXDFLT, mimo_antsel); -+ /* -+ * Update driver stats for currently selected -+ * default tx/rx antenna config -+ */ -+ asi->antcfg_cur.ant_config[ANT_SELCFG_TX_DEF] = ant_cfg; -+ -+ /* 2) Update RX antconfig for all frames that are not unicast data -+ * (aka default RX) -+ */ -+ ant_cfg = antsel->ant_config[ANT_SELCFG_RX_DEF]; -+ mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg); -+ brcms_b_write_shm(wlc->hw, M_MIMO_ANTSEL_RXDFLT, mimo_antsel); -+ /* -+ * Update driver stats for currently selected -+ * default tx/rx antenna config -+ */ -+ asi->antcfg_cur.ant_config[ANT_SELCFG_RX_DEF] = ant_cfg; -+ -+ return 0; -+} -+ -+void brcms_c_antsel_init(struct antsel_info *asi) -+{ -+ if ((asi->antsel_type == ANTSEL_2x3) || -+ (asi->antsel_type == ANTSEL_2x4)) -+ brcms_c_antsel_cfgupd(asi, &asi->antcfg_11n); -+} -+ -+/* boardlevel antenna selection: convert id to ant_cfg */ -+static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id) -+{ -+ u8 antcfg = ANT_SELCFG_DEF_2x2; -+ -+ if (asi->antsel_type == ANTSEL_2x4) { -+ /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */ -+ antcfg = (((id & 0x2) << 3) | ((id & 0x1) + 2)); -+ return antcfg; -+ -+ } else if (asi->antsel_type == ANTSEL_2x3) { -+ /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */ -+ antcfg = (((id & 0x02) << 4) | ((id & 0x1) + 1)); -+ return antcfg; -+ } -+ -+ return antcfg; -+} -+ -+void -+brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef, bool sel, -+ u8 antselid, u8 fbantselid, u8 *antcfg, -+ u8 *fbantcfg) -+{ -+ u8 ant; -+ -+ /* if use default, assign it and return */ -+ if (usedef) { -+ *antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_DEF]; -+ *fbantcfg = *antcfg; -+ return; -+ } -+ -+ if (!sel) { -+ *antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST]; -+ *fbantcfg = *antcfg; -+ -+ } else { -+ ant = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST]; -+ if ((ant & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO) { -+ *antcfg = brcms_c_antsel_id2antcfg(asi, antselid); -+ *fbantcfg = brcms_c_antsel_id2antcfg(asi, fbantselid); -+ } else { -+ *antcfg = -+ asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST]; -+ *fbantcfg = *antcfg; -+ } -+ } -+ return; -+} -+ -+/* boardlevel antenna selection: convert mimo_antsel (ucode interface) to id */ -+u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel) -+{ -+ u8 antselid = 0; -+ -+ if (asi->antsel_type == ANTSEL_2x4) { -+ /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */ -+ antselid = mimo_2x4_div_antselid_tbl[(antsel & 0xf)]; -+ return antselid; -+ -+ } else if (asi->antsel_type == ANTSEL_2x3) { -+ /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */ -+ antselid = mimo_2x3_div_antselid_tbl[(antsel & 0xf)]; -+ return antselid; -+ } -+ -+ return antselid; -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.h.orig 2011-11-09 13:46:58.241800683 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.h 2011-11-09 13:47:16.993566253 -0500 -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_ANTSEL_H_ -+#define _BRCM_ANTSEL_H_ -+ -+extern struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc); -+extern void brcms_c_antsel_detach(struct antsel_info *asi); -+extern void brcms_c_antsel_init(struct antsel_info *asi); -+extern void brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef, -+ bool sel, -+ u8 id, u8 fbid, u8 *antcfg, -+ u8 *fbantcfg); -+extern u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel); -+ -+#endif /* _BRCM_ANTSEL_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.c.orig 2011-11-09 13:46:58.241800683 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.c 2011-11-09 13:47:16.993566253 -0500 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (c) 2011 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include /* bug in tracepoint.h, it should include this */ -+ -+#ifndef __CHECKER__ -+#include "mac80211_if.h" -+#define CREATE_TRACE_POINTS -+#include "brcms_trace_events.h" -+#endif -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h.orig 2011-11-09 13:46:58.241800683 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h 2011-11-09 13:47:16.993566253 -0500 -@@ -0,0 +1,92 @@ -+/* -+ * Copyright (c) 2011 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#undef TRACE_SYSTEM -+#define TRACE_SYSTEM brcmsmac -+ -+#if !defined(__TRACE_BRCMSMAC_H) || defined(TRACE_HEADER_MULTI_READ) -+ -+#define __TRACE_BRCMSMAC_H -+ -+#include -+#include "mac80211_if.h" -+ -+#ifndef CONFIG_BRCMDBG -+#undef TRACE_EVENT -+#define TRACE_EVENT(name, proto, ...) \ -+static inline void trace_ ## name(proto) {} -+#endif -+ -+/* -+ * We define a tracepoint, its arguments, its printk format and its -+ * 'fast binary record' layout. -+ */ -+TRACE_EVENT(brcms_timer, -+ /* TPPROTO is the prototype of the function called by this tracepoint */ -+ TP_PROTO(struct brcms_timer *t), -+ /* -+ * TPARGS(firstarg, p) are the parameters names, same as found in the -+ * prototype. -+ */ -+ TP_ARGS(t), -+ /* -+ * Fast binary tracing: define the trace record via TP_STRUCT__entry(). -+ * You can think about it like a regular C structure local variable -+ * definition. -+ */ -+ TP_STRUCT__entry( -+ __field(uint, ms) -+ __field(uint, set) -+ __field(uint, periodic) -+ ), -+ TP_fast_assign( -+ __entry->ms = t->ms; -+ __entry->set = t->set; -+ __entry->periodic = t->periodic; -+ ), -+ TP_printk( -+ "ms=%u set=%u periodic=%u", -+ __entry->ms, __entry->set, __entry->periodic -+ ) -+); -+ -+TRACE_EVENT(brcms_dpc, -+ TP_PROTO(unsigned long data), -+ TP_ARGS(data), -+ TP_STRUCT__entry( -+ __field(unsigned long, data) -+ ), -+ TP_fast_assign( -+ __entry->data = data; -+ ), -+ TP_printk( -+ "data=%p", -+ (void *)__entry->data -+ ) -+); -+ -+#endif /* __TRACE_BRCMSMAC_H */ -+ -+#ifdef CONFIG_BRCMDBG -+ -+#undef TRACE_INCLUDE_PATH -+#define TRACE_INCLUDE_PATH . -+#undef TRACE_INCLUDE_FILE -+#define TRACE_INCLUDE_FILE brcms_trace_events -+ -+#include -+ -+#endif /* CONFIG_BRCMDBG */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.c.orig 2011-11-09 13:46:58.242800670 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.c 2011-11-09 13:47:16.994566241 -0500 -@@ -0,0 +1,1591 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+ -+#include -+#include "pub.h" -+#include "phy/phy_hal.h" -+#include "main.h" -+#include "stf.h" -+#include "channel.h" -+ -+/* QDB() macro takes a dB value and converts to a quarter dB value */ -+#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR) -+ -+#define LOCALE_CHAN_01_11 (1<<0) -+#define LOCALE_CHAN_12_13 (1<<1) -+#define LOCALE_CHAN_14 (1<<2) -+#define LOCALE_SET_5G_LOW_JP1 (1<<3) /* 34-48, step 2 */ -+#define LOCALE_SET_5G_LOW_JP2 (1<<4) /* 34-46, step 4 */ -+#define LOCALE_SET_5G_LOW1 (1<<5) /* 36-48, step 4 */ -+#define LOCALE_SET_5G_LOW2 (1<<6) /* 52 */ -+#define LOCALE_SET_5G_LOW3 (1<<7) /* 56-64, step 4 */ -+#define LOCALE_SET_5G_MID1 (1<<8) /* 100-116, step 4 */ -+#define LOCALE_SET_5G_MID2 (1<<9) /* 120-124, step 4 */ -+#define LOCALE_SET_5G_MID3 (1<<10) /* 128 */ -+#define LOCALE_SET_5G_HIGH1 (1<<11) /* 132-140, step 4 */ -+#define LOCALE_SET_5G_HIGH2 (1<<12) /* 149-161, step 4 */ -+#define LOCALE_SET_5G_HIGH3 (1<<13) /* 165 */ -+#define LOCALE_CHAN_52_140_ALL (1<<14) -+#define LOCALE_SET_5G_HIGH4 (1<<15) /* 184-216 */ -+ -+#define LOCALE_CHAN_36_64 (LOCALE_SET_5G_LOW1 | \ -+ LOCALE_SET_5G_LOW2 | \ -+ LOCALE_SET_5G_LOW3) -+#define LOCALE_CHAN_52_64 (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3) -+#define LOCALE_CHAN_100_124 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2) -+#define LOCALE_CHAN_100_140 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | \ -+ LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1) -+#define LOCALE_CHAN_149_165 (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3) -+#define LOCALE_CHAN_184_216 LOCALE_SET_5G_HIGH4 -+ -+#define LOCALE_CHAN_01_14 (LOCALE_CHAN_01_11 | \ -+ LOCALE_CHAN_12_13 | \ -+ LOCALE_CHAN_14) -+ -+#define LOCALE_RADAR_SET_NONE 0 -+#define LOCALE_RADAR_SET_1 1 -+ -+#define LOCALE_RESTRICTED_NONE 0 -+#define LOCALE_RESTRICTED_SET_2G_SHORT 1 -+#define LOCALE_RESTRICTED_CHAN_165 2 -+#define LOCALE_CHAN_ALL_5G 3 -+#define LOCALE_RESTRICTED_JAPAN_LEGACY 4 -+#define LOCALE_RESTRICTED_11D_2G 5 -+#define LOCALE_RESTRICTED_11D_5G 6 -+#define LOCALE_RESTRICTED_LOW_HI 7 -+#define LOCALE_RESTRICTED_12_13_14 8 -+ -+#define LOCALE_2G_IDX_i 0 -+#define LOCALE_5G_IDX_11 0 -+#define LOCALE_MIMO_IDX_bn 0 -+#define LOCALE_MIMO_IDX_11n 0 -+ -+/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */ -+#define BRCMS_MAXPWR_TBL_SIZE 6 -+/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */ -+#define BRCMS_MAXPWR_MIMO_TBL_SIZE 14 -+ -+/* power level in group of 2.4GHz band channels: -+ * maxpwr[0] - CCK channels [1] -+ * maxpwr[1] - CCK channels [2-10] -+ * maxpwr[2] - CCK channels [11-14] -+ * maxpwr[3] - OFDM channels [1] -+ * maxpwr[4] - OFDM channels [2-10] -+ * maxpwr[5] - OFDM channels [11-14] -+ */ -+ -+/* maxpwr mapping to 5GHz band channels: -+ * maxpwr[0] - channels [34-48] -+ * maxpwr[1] - channels [52-60] -+ * maxpwr[2] - channels [62-64] -+ * maxpwr[3] - channels [100-140] -+ * maxpwr[4] - channels [149-165] -+ */ -+#define BAND_5G_PWR_LVLS 5 /* 5 power levels for 5G */ -+ -+#define LC(id) LOCALE_MIMO_IDX_ ## id -+ -+#define LC_2G(id) LOCALE_2G_IDX_ ## id -+ -+#define LC_5G(id) LOCALE_5G_IDX_ ## id -+ -+#define LOCALES(band2, band5, mimo2, mimo5) \ -+ {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)} -+ -+/* macro to get 2.4 GHz channel group index for tx power */ -+#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2)) -+#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5)) -+ -+/* macro to get 5 GHz channel group index for tx power */ -+#define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \ -+ (((c) < 62) ? 1 : \ -+ (((c) < 100) ? 2 : \ -+ (((c) < 149) ? 3 : 4)))) -+ -+#define ISDFS_EU(fl) (((fl) & BRCMS_DFS_EU) == BRCMS_DFS_EU) -+ -+struct brcms_cm_band { -+ /* struct locale_info flags */ -+ u8 locale_flags; -+ /* List of valid channels in the country */ -+ struct brcms_chanvec valid_channels; -+ /* List of restricted use channels */ -+ const struct brcms_chanvec *restricted_channels; -+ /* List of radar sensitive channels */ -+ const struct brcms_chanvec *radar_channels; -+ u8 PAD[8]; -+}; -+ -+ /* locale per-channel tx power limits for MIMO frames -+ * maxpwr arrays are index by channel for 2.4 GHz limits, and -+ * by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel) -+ */ -+struct locale_mimo_info { -+ /* tx 20 MHz power limits, qdBm units */ -+ s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE]; -+ /* tx 40 MHz power limits, qdBm units */ -+ s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE]; -+ u8 flags; -+}; -+ -+/* Country names and abbreviations with locale defined from ISO 3166 */ -+struct country_info { -+ const u8 locale_2G; /* 2.4G band locale */ -+ const u8 locale_5G; /* 5G band locale */ -+ const u8 locale_mimo_2G; /* 2.4G mimo info */ -+ const u8 locale_mimo_5G; /* 5G mimo info */ -+}; -+ -+struct brcms_cm_info { -+ struct brcms_pub *pub; -+ struct brcms_c_info *wlc; -+ char srom_ccode[BRCM_CNTRY_BUF_SZ]; /* Country Code in SROM */ -+ uint srom_regrev; /* Regulatory Rev for the SROM ccode */ -+ const struct country_info *country; /* current country def */ -+ char ccode[BRCM_CNTRY_BUF_SZ]; /* current internal Country Code */ -+ uint regrev; /* current Regulatory Revision */ -+ char country_abbrev[BRCM_CNTRY_BUF_SZ]; /* current advertised ccode */ -+ /* per-band state (one per phy/radio) */ -+ struct brcms_cm_band bandstate[MAXBANDS]; -+ /* quiet channels currently for radar sensitivity or 11h support */ -+ /* channels on which we cannot transmit */ -+ struct brcms_chanvec quiet_channels; -+}; -+ -+/* locale channel and power info. */ -+struct locale_info { -+ u32 valid_channels; -+ /* List of radar sensitive channels */ -+ u8 radar_channels; -+ /* List of channels used only if APs are detected */ -+ u8 restricted_channels; -+ /* Max tx pwr in qdBm for each sub-band */ -+ s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE]; -+ /* Country IE advertised max tx pwr in dBm per sub-band */ -+ s8 pub_maxpwr[BAND_5G_PWR_LVLS]; -+ u8 flags; -+}; -+ -+/* Regulatory Matrix Spreadsheet (CLM) MIMO v3.7.9 */ -+ -+/* -+ * Some common channel sets -+ */ -+ -+/* No channels */ -+static const struct brcms_chanvec chanvec_none = { -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+/* All 2.4 GHz HW channels */ -+static const struct brcms_chanvec chanvec_all_2G = { -+ {0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+/* All 5 GHz HW channels */ -+static const struct brcms_chanvec chanvec_all_5G = { -+ {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x11, 0x11, -+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, -+ 0x11, 0x11, 0x20, 0x22, 0x22, 0x00, 0x00, 0x11, -+ 0x11, 0x11, 0x11, 0x01} -+}; -+ -+/* -+ * Radar channel sets -+ */ -+ -+/* Channels 52 - 64, 100 - 140 */ -+static const struct brcms_chanvec radar_set1 = { -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, /* 52 - 60 */ -+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, /* 64, 100 - 124 */ -+ 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 - 140 */ -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+/* -+ * Restricted channel sets -+ */ -+ -+/* Channels 34, 38, 42, 46 */ -+static const struct brcms_chanvec restricted_set_japan_legacy = { -+ {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+/* Channels 12, 13 */ -+static const struct brcms_chanvec restricted_set_2g_short = { -+ {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+/* Channel 165 */ -+static const struct brcms_chanvec restricted_chan_165 = { -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+/* Channels 36 - 48 & 149 - 165 */ -+static const struct brcms_chanvec restricted_low_hi = { -+ {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x20, 0x22, 0x22, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+/* Channels 12 - 14 */ -+static const struct brcms_chanvec restricted_set_12_13_14 = { -+ {0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+/* global memory to provide working buffer for expanded locale */ -+ -+static const struct brcms_chanvec *g_table_radar_set[] = { -+ &chanvec_none, -+ &radar_set1 -+}; -+ -+static const struct brcms_chanvec *g_table_restricted_chan[] = { -+ &chanvec_none, /* restricted_set_none */ -+ &restricted_set_2g_short, -+ &restricted_chan_165, -+ &chanvec_all_5G, -+ &restricted_set_japan_legacy, -+ &chanvec_all_2G, /* restricted_set_11d_2G */ -+ &chanvec_all_5G, /* restricted_set_11d_5G */ -+ &restricted_low_hi, -+ &restricted_set_12_13_14 -+}; -+ -+static const struct brcms_chanvec locale_2g_01_11 = { -+ {0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+static const struct brcms_chanvec locale_2g_12_13 = { -+ {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+static const struct brcms_chanvec locale_2g_14 = { -+ {0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+static const struct brcms_chanvec locale_5g_LOW_JP1 = { -+ {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+static const struct brcms_chanvec locale_5g_LOW_JP2 = { -+ {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+static const struct brcms_chanvec locale_5g_LOW1 = { -+ {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+static const struct brcms_chanvec locale_5g_LOW2 = { -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+static const struct brcms_chanvec locale_5g_LOW3 = { -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, -+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+static const struct brcms_chanvec locale_5g_MID1 = { -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+static const struct brcms_chanvec locale_5g_MID2 = { -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+static const struct brcms_chanvec locale_5g_MID3 = { -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+static const struct brcms_chanvec locale_5g_HIGH1 = { -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+static const struct brcms_chanvec locale_5g_HIGH2 = { -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x20, 0x22, 0x02, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+static const struct brcms_chanvec locale_5g_HIGH3 = { -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+static const struct brcms_chanvec locale_5g_52_140_ALL = { -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, -+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, -+ 0x11, 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00} -+}; -+ -+static const struct brcms_chanvec locale_5g_HIGH4 = { -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, -+ 0x11, 0x11, 0x11, 0x11} -+}; -+ -+static const struct brcms_chanvec *g_table_locale_base[] = { -+ &locale_2g_01_11, -+ &locale_2g_12_13, -+ &locale_2g_14, -+ &locale_5g_LOW_JP1, -+ &locale_5g_LOW_JP2, -+ &locale_5g_LOW1, -+ &locale_5g_LOW2, -+ &locale_5g_LOW3, -+ &locale_5g_MID1, -+ &locale_5g_MID2, -+ &locale_5g_MID3, -+ &locale_5g_HIGH1, -+ &locale_5g_HIGH2, -+ &locale_5g_HIGH3, -+ &locale_5g_52_140_ALL, -+ &locale_5g_HIGH4 -+}; -+ -+static void brcms_c_locale_add_channels(struct brcms_chanvec *target, -+ const struct brcms_chanvec *channels) -+{ -+ u8 i; -+ for (i = 0; i < sizeof(struct brcms_chanvec); i++) -+ target->vec[i] |= channels->vec[i]; -+} -+ -+static void brcms_c_locale_get_channels(const struct locale_info *locale, -+ struct brcms_chanvec *channels) -+{ -+ u8 i; -+ -+ memset(channels, 0, sizeof(struct brcms_chanvec)); -+ -+ for (i = 0; i < ARRAY_SIZE(g_table_locale_base); i++) { -+ if (locale->valid_channels & (1 << i)) -+ brcms_c_locale_add_channels(channels, -+ g_table_locale_base[i]); -+ } -+} -+ -+/* -+ * Locale Definitions - 2.4 GHz -+ */ -+static const struct locale_info locale_i = { /* locale i. channel 1 - 13 */ -+ LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13, -+ LOCALE_RADAR_SET_NONE, -+ LOCALE_RESTRICTED_SET_2G_SHORT, -+ {QDB(19), QDB(19), QDB(19), -+ QDB(19), QDB(19), QDB(19)}, -+ {20, 20, 20, 0}, -+ BRCMS_EIRP -+}; -+ -+/* -+ * Locale Definitions - 5 GHz -+ */ -+static const struct locale_info locale_11 = { -+ /* locale 11. channel 36 - 48, 52 - 64, 100 - 140, 149 - 165 */ -+ LOCALE_CHAN_36_64 | LOCALE_CHAN_100_140 | LOCALE_CHAN_149_165, -+ LOCALE_RADAR_SET_1, -+ LOCALE_RESTRICTED_NONE, -+ {QDB(21), QDB(21), QDB(21), QDB(21), QDB(21)}, -+ {23, 23, 23, 30, 30}, -+ BRCMS_EIRP | BRCMS_DFS_EU -+}; -+ -+static const struct locale_info *g_locale_2g_table[] = { -+ &locale_i -+}; -+ -+static const struct locale_info *g_locale_5g_table[] = { -+ &locale_11 -+}; -+ -+/* -+ * MIMO Locale Definitions - 2.4 GHz -+ */ -+static const struct locale_mimo_info locale_bn = { -+ {QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), -+ QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), -+ QDB(13), QDB(13), QDB(13)}, -+ {0, 0, QDB(13), QDB(13), QDB(13), -+ QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), -+ QDB(13), 0, 0}, -+ 0 -+}; -+ -+static const struct locale_mimo_info *g_mimo_2g_table[] = { -+ &locale_bn -+}; -+ -+/* -+ * MIMO Locale Definitions - 5 GHz -+ */ -+static const struct locale_mimo_info locale_11n = { -+ { /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)}, -+ {QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)}, -+ 0 -+}; -+ -+static const struct locale_mimo_info *g_mimo_5g_table[] = { -+ &locale_11n -+}; -+ -+static const struct { -+ char abbrev[BRCM_CNTRY_BUF_SZ]; /* country abbreviation */ -+ struct country_info country; -+} cntry_locales[] = { -+ { -+ "X2", LOCALES(i, 11, bn, 11n)}, /* Worldwide RoW 2 */ -+}; -+ -+#ifdef SUPPORT_40MHZ -+/* 20MHz channel info for 40MHz pairing support */ -+struct chan20_info { -+ u8 sb; -+ u8 adj_sbs; -+}; -+ -+/* indicates adjacent channels that are allowed for a 40 Mhz channel and -+ * those that permitted by the HT -+ */ -+struct chan20_info chan20_info[] = { -+ /* 11b/11g */ -+/* 0 */ {1, (CH_UPPER_SB | CH_EWA_VALID)}, -+/* 1 */ {2, (CH_UPPER_SB | CH_EWA_VALID)}, -+/* 2 */ {3, (CH_UPPER_SB | CH_EWA_VALID)}, -+/* 3 */ {4, (CH_UPPER_SB | CH_EWA_VALID)}, -+/* 4 */ {5, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, -+/* 5 */ {6, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, -+/* 6 */ {7, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, -+/* 7 */ {8, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, -+/* 8 */ {9, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, -+/* 9 */ {10, (CH_LOWER_SB | CH_EWA_VALID)}, -+/* 10 */ {11, (CH_LOWER_SB | CH_EWA_VALID)}, -+/* 11 */ {12, (CH_LOWER_SB)}, -+/* 12 */ {13, (CH_LOWER_SB)}, -+/* 13 */ {14, (CH_LOWER_SB)}, -+ -+/* 11a japan high */ -+/* 14 */ {34, (CH_UPPER_SB)}, -+/* 15 */ {38, (CH_LOWER_SB)}, -+/* 16 */ {42, (CH_LOWER_SB)}, -+/* 17 */ {46, (CH_LOWER_SB)}, -+ -+/* 11a usa low */ -+/* 18 */ {36, (CH_UPPER_SB | CH_EWA_VALID)}, -+/* 19 */ {40, (CH_LOWER_SB | CH_EWA_VALID)}, -+/* 20 */ {44, (CH_UPPER_SB | CH_EWA_VALID)}, -+/* 21 */ {48, (CH_LOWER_SB | CH_EWA_VALID)}, -+/* 22 */ {52, (CH_UPPER_SB | CH_EWA_VALID)}, -+/* 23 */ {56, (CH_LOWER_SB | CH_EWA_VALID)}, -+/* 24 */ {60, (CH_UPPER_SB | CH_EWA_VALID)}, -+/* 25 */ {64, (CH_LOWER_SB | CH_EWA_VALID)}, -+ -+/* 11a Europe */ -+/* 26 */ {100, (CH_UPPER_SB | CH_EWA_VALID)}, -+/* 27 */ {104, (CH_LOWER_SB | CH_EWA_VALID)}, -+/* 28 */ {108, (CH_UPPER_SB | CH_EWA_VALID)}, -+/* 29 */ {112, (CH_LOWER_SB | CH_EWA_VALID)}, -+/* 30 */ {116, (CH_UPPER_SB | CH_EWA_VALID)}, -+/* 31 */ {120, (CH_LOWER_SB | CH_EWA_VALID)}, -+/* 32 */ {124, (CH_UPPER_SB | CH_EWA_VALID)}, -+/* 33 */ {128, (CH_LOWER_SB | CH_EWA_VALID)}, -+/* 34 */ {132, (CH_UPPER_SB | CH_EWA_VALID)}, -+/* 35 */ {136, (CH_LOWER_SB | CH_EWA_VALID)}, -+/* 36 */ {140, (CH_LOWER_SB)}, -+ -+/* 11a usa high, ref5 only */ -+/* The 0x80 bit in pdiv means these are REF5, other entries are REF20 */ -+/* 37 */ {149, (CH_UPPER_SB | CH_EWA_VALID)}, -+/* 38 */ {153, (CH_LOWER_SB | CH_EWA_VALID)}, -+/* 39 */ {157, (CH_UPPER_SB | CH_EWA_VALID)}, -+/* 40 */ {161, (CH_LOWER_SB | CH_EWA_VALID)}, -+/* 41 */ {165, (CH_LOWER_SB)}, -+ -+/* 11a japan */ -+/* 42 */ {184, (CH_UPPER_SB)}, -+/* 43 */ {188, (CH_LOWER_SB)}, -+/* 44 */ {192, (CH_UPPER_SB)}, -+/* 45 */ {196, (CH_LOWER_SB)}, -+/* 46 */ {200, (CH_UPPER_SB)}, -+/* 47 */ {204, (CH_LOWER_SB)}, -+/* 48 */ {208, (CH_UPPER_SB)}, -+/* 49 */ {212, (CH_LOWER_SB)}, -+/* 50 */ {216, (CH_LOWER_SB)} -+}; -+#endif /* SUPPORT_40MHZ */ -+ -+static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx) -+{ -+ if (locale_idx >= ARRAY_SIZE(g_locale_2g_table)) -+ return NULL; /* error condition */ -+ -+ return g_locale_2g_table[locale_idx]; -+} -+ -+static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx) -+{ -+ if (locale_idx >= ARRAY_SIZE(g_locale_5g_table)) -+ return NULL; /* error condition */ -+ -+ return g_locale_5g_table[locale_idx]; -+} -+ -+static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx) -+{ -+ if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table)) -+ return NULL; -+ -+ return g_mimo_2g_table[locale_idx]; -+} -+ -+static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx) -+{ -+ if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table)) -+ return NULL; -+ -+ return g_mimo_5g_table[locale_idx]; -+} -+ -+static int -+brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm, const char *ccode, -+ char *mapped_ccode, uint *mapped_regrev) -+{ -+ return false; -+} -+ -+/* Lookup a country info structure from a null terminated country -+ * abbreviation and regrev directly with no translation. -+ */ -+static const struct country_info * -+brcms_c_country_lookup_direct(const char *ccode, uint regrev) -+{ -+ uint size, i; -+ -+ /* Should just return 0 for single locale driver. */ -+ /* Keep it this way in case we add more locales. (for now anyway) */ -+ -+ /* -+ * all other country def arrays are for regrev == 0, so if -+ * regrev is non-zero, fail -+ */ -+ if (regrev > 0) -+ return NULL; -+ -+ /* find matched table entry from country code */ -+ size = ARRAY_SIZE(cntry_locales); -+ for (i = 0; i < size; i++) { -+ if (strcmp(ccode, cntry_locales[i].abbrev) == 0) -+ return &cntry_locales[i].country; -+ } -+ return NULL; -+} -+ -+static const struct country_info * -+brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, const char *ccode, -+ char *mapped_ccode, uint *mapped_regrev) -+{ -+ struct brcms_c_info *wlc = wlc_cm->wlc; -+ const struct country_info *country; -+ uint srom_regrev = wlc_cm->srom_regrev; -+ const char *srom_ccode = wlc_cm->srom_ccode; -+ int mapped; -+ -+ /* check for currently supported ccode size */ -+ if (strlen(ccode) > (BRCM_CNTRY_BUF_SZ - 1)) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: ccode \"%s\" too long for " -+ "match\n", wlc->pub->unit, __func__, ccode); -+ return NULL; -+ } -+ -+ /* default mapping is the given ccode and regrev 0 */ -+ strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ); -+ *mapped_regrev = 0; -+ -+ /* If the desired country code matches the srom country code, -+ * then the mapped country is the srom regulatory rev. -+ * Otherwise look for an aggregate mapping. -+ */ -+ if (!strcmp(srom_ccode, ccode)) { -+ *mapped_regrev = srom_regrev; -+ mapped = 0; -+ wiphy_err(wlc->wiphy, "srom_code == ccode %s\n", __func__); -+ } else { -+ mapped = -+ brcms_c_country_aggregate_map(wlc_cm, ccode, mapped_ccode, -+ mapped_regrev); -+ } -+ -+ /* find the matching built-in country definition */ -+ country = brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev); -+ -+ /* if there is not an exact rev match, default to rev zero */ -+ if (country == NULL && *mapped_regrev != 0) { -+ *mapped_regrev = 0; -+ country = -+ brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev); -+ } -+ -+ return country; -+} -+ -+/* Lookup a country info structure from a null terminated country code -+ * The lookup is case sensitive. -+ */ -+static const struct country_info * -+brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode) -+{ -+ const struct country_info *country; -+ char mapped_ccode[BRCM_CNTRY_BUF_SZ]; -+ uint mapped_regrev; -+ -+ /* -+ * map the country code to a built-in country code, regrev, and -+ * country_info struct -+ */ -+ country = brcms_c_countrycode_map(wlc->cmi, ccode, mapped_ccode, -+ &mapped_regrev); -+ -+ return country; -+} -+ -+/* -+ * reset the quiet channels vector to the union -+ * of the restricted and radar channel sets -+ */ -+static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm) -+{ -+ struct brcms_c_info *wlc = wlc_cm->wlc; -+ uint i, j; -+ struct brcms_band *band; -+ const struct brcms_chanvec *chanvec; -+ -+ memset(&wlc_cm->quiet_channels, 0, sizeof(struct brcms_chanvec)); -+ -+ band = wlc->band; -+ for (i = 0; i < wlc->pub->_nbands; -+ i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) { -+ -+ /* initialize quiet channels for restricted channels */ -+ chanvec = wlc_cm->bandstate[band->bandunit].restricted_channels; -+ for (j = 0; j < sizeof(struct brcms_chanvec); j++) -+ wlc_cm->quiet_channels.vec[j] |= chanvec->vec[j]; -+ -+ } -+} -+ -+/* Is the channel valid for the current locale and current band? */ -+static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val) -+{ -+ struct brcms_c_info *wlc = wlc_cm->wlc; -+ -+ return ((val < MAXCHANNEL) && -+ isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec, -+ val)); -+} -+ -+/* Is the channel valid for the current locale and specified band? */ -+static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm, -+ uint bandunit, uint val) -+{ -+ return ((val < MAXCHANNEL) -+ && isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val)); -+} -+ -+/* Is the channel valid for the current locale? (but don't consider channels not -+ * available due to bandlocking) -+ */ -+static bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val) -+{ -+ struct brcms_c_info *wlc = wlc_cm->wlc; -+ -+ return brcms_c_valid_channel20(wlc->cmi, val) || -+ (!wlc->bandlocked -+ && brcms_c_valid_channel20_in_band(wlc->cmi, -+ OTHERBANDUNIT(wlc), val)); -+} -+ -+/* JP, J1 - J10 are Japan ccodes */ -+static bool brcms_c_japan_ccode(const char *ccode) -+{ -+ return (ccode[0] == 'J' && -+ (ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9'))); -+} -+ -+/* Returns true if currently set country is Japan or variant */ -+static bool brcms_c_japan(struct brcms_c_info *wlc) -+{ -+ return brcms_c_japan_ccode(wlc->cmi->country_abbrev); -+} -+ -+static void -+brcms_c_channel_min_txpower_limits_with_local_constraint( -+ struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr, -+ u8 local_constraint_qdbm) -+{ -+ int j; -+ -+ /* CCK Rates */ -+ for (j = 0; j < WL_TX_POWER_CCK_NUM; j++) -+ txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm); -+ -+ /* 20 MHz Legacy OFDM SISO */ -+ for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++) -+ txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm); -+ -+ /* 20 MHz Legacy OFDM CDD */ -+ for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) -+ txpwr->ofdm_cdd[j] = -+ min(txpwr->ofdm_cdd[j], local_constraint_qdbm); -+ -+ /* 40 MHz Legacy OFDM SISO */ -+ for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) -+ txpwr->ofdm_40_siso[j] = -+ min(txpwr->ofdm_40_siso[j], local_constraint_qdbm); -+ -+ /* 40 MHz Legacy OFDM CDD */ -+ for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) -+ txpwr->ofdm_40_cdd[j] = -+ min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm); -+ -+ /* 20MHz MCS 0-7 SISO */ -+ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) -+ txpwr->mcs_20_siso[j] = -+ min(txpwr->mcs_20_siso[j], local_constraint_qdbm); -+ -+ /* 20MHz MCS 0-7 CDD */ -+ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) -+ txpwr->mcs_20_cdd[j] = -+ min(txpwr->mcs_20_cdd[j], local_constraint_qdbm); -+ -+ /* 20MHz MCS 0-7 STBC */ -+ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) -+ txpwr->mcs_20_stbc[j] = -+ min(txpwr->mcs_20_stbc[j], local_constraint_qdbm); -+ -+ /* 20MHz MCS 8-15 MIMO */ -+ for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++) -+ txpwr->mcs_20_mimo[j] = -+ min(txpwr->mcs_20_mimo[j], local_constraint_qdbm); -+ -+ /* 40MHz MCS 0-7 SISO */ -+ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) -+ txpwr->mcs_40_siso[j] = -+ min(txpwr->mcs_40_siso[j], local_constraint_qdbm); -+ -+ /* 40MHz MCS 0-7 CDD */ -+ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) -+ txpwr->mcs_40_cdd[j] = -+ min(txpwr->mcs_40_cdd[j], local_constraint_qdbm); -+ -+ /* 40MHz MCS 0-7 STBC */ -+ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) -+ txpwr->mcs_40_stbc[j] = -+ min(txpwr->mcs_40_stbc[j], local_constraint_qdbm); -+ -+ /* 40MHz MCS 8-15 MIMO */ -+ for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++) -+ txpwr->mcs_40_mimo[j] = -+ min(txpwr->mcs_40_mimo[j], local_constraint_qdbm); -+ -+ /* 40MHz MCS 32 */ -+ txpwr->mcs32 = min(txpwr->mcs32, local_constraint_qdbm); -+ -+} -+ -+/* Update the radio state (enable/disable) and tx power targets -+ * based on a new set of channel/regulatory information -+ */ -+static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm) -+{ -+ struct brcms_c_info *wlc = wlc_cm->wlc; -+ uint chan; -+ struct txpwr_limits txpwr; -+ -+ /* search for the existence of any valid channel */ -+ for (chan = 0; chan < MAXCHANNEL; chan++) { -+ if (brcms_c_valid_channel20_db(wlc->cmi, chan)) -+ break; -+ } -+ if (chan == MAXCHANNEL) -+ chan = INVCHANNEL; -+ -+ /* -+ * based on the channel search above, set or -+ * clear WL_RADIO_COUNTRY_DISABLE. -+ */ -+ if (chan == INVCHANNEL) { -+ /* -+ * country/locale with no valid channels, set -+ * the radio disable bit -+ */ -+ mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); -+ wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" " -+ "nbands %d bandlocked %d\n", wlc->pub->unit, -+ __func__, wlc_cm->country_abbrev, wlc->pub->_nbands, -+ wlc->bandlocked); -+ } else if (mboolisset(wlc->pub->radio_disabled, -+ WL_RADIO_COUNTRY_DISABLE)) { -+ /* -+ * country/locale with valid channel, clear -+ * the radio disable bit -+ */ -+ mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); -+ } -+ -+ /* -+ * Now that the country abbreviation is set, if the radio supports 2G, -+ * then set channel 14 restrictions based on the new locale. -+ */ -+ if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G) -+ wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi, -+ brcms_c_japan(wlc) ? true : -+ false); -+ -+ if (wlc->pub->up && chan != INVCHANNEL) { -+ brcms_c_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr); -+ brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm, -+ &txpwr, BRCMS_TXPWR_MAX); -+ wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec); -+ } -+} -+ -+static int -+brcms_c_channels_init(struct brcms_cm_info *wlc_cm, -+ const struct country_info *country) -+{ -+ struct brcms_c_info *wlc = wlc_cm->wlc; -+ uint i, j; -+ struct brcms_band *band; -+ const struct locale_info *li; -+ struct brcms_chanvec sup_chan; -+ const struct locale_mimo_info *li_mimo; -+ -+ band = wlc->band; -+ for (i = 0; i < wlc->pub->_nbands; -+ i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) { -+ -+ li = (band->bandtype == BRCM_BAND_5G) ? -+ brcms_c_get_locale_5g(country->locale_5G) : -+ brcms_c_get_locale_2g(country->locale_2G); -+ wlc_cm->bandstate[band->bandunit].locale_flags = li->flags; -+ li_mimo = (band->bandtype == BRCM_BAND_5G) ? -+ brcms_c_get_mimo_5g(country->locale_mimo_5G) : -+ brcms_c_get_mimo_2g(country->locale_mimo_2G); -+ -+ /* merge the mimo non-mimo locale flags */ -+ wlc_cm->bandstate[band->bandunit].locale_flags |= -+ li_mimo->flags; -+ -+ wlc_cm->bandstate[band->bandunit].restricted_channels = -+ g_table_restricted_chan[li->restricted_channels]; -+ wlc_cm->bandstate[band->bandunit].radar_channels = -+ g_table_radar_set[li->radar_channels]; -+ -+ /* -+ * set the channel availability, masking out the channels -+ * that may not be supported on this phy. -+ */ -+ wlc_phy_chanspec_band_validch(band->pi, band->bandtype, -+ &sup_chan); -+ brcms_c_locale_get_channels(li, -+ &wlc_cm->bandstate[band->bandunit]. -+ valid_channels); -+ for (j = 0; j < sizeof(struct brcms_chanvec); j++) -+ wlc_cm->bandstate[band->bandunit].valid_channels. -+ vec[j] &= sup_chan.vec[j]; -+ } -+ -+ brcms_c_quiet_channels_reset(wlc_cm); -+ brcms_c_channels_commit(wlc_cm); -+ -+ return 0; -+} -+ -+/* -+ * set the driver's current country and regulatory information -+ * using a country code as the source. Look up built in country -+ * information found with the country code. -+ */ -+static void -+brcms_c_set_country_common(struct brcms_cm_info *wlc_cm, -+ const char *country_abbrev, -+ const char *ccode, uint regrev, -+ const struct country_info *country) -+{ -+ const struct locale_info *locale; -+ struct brcms_c_info *wlc = wlc_cm->wlc; -+ char prev_country_abbrev[BRCM_CNTRY_BUF_SZ]; -+ -+ /* save current country state */ -+ wlc_cm->country = country; -+ -+ memset(&prev_country_abbrev, 0, BRCM_CNTRY_BUF_SZ); -+ strncpy(prev_country_abbrev, wlc_cm->country_abbrev, -+ BRCM_CNTRY_BUF_SZ - 1); -+ -+ strncpy(wlc_cm->country_abbrev, country_abbrev, BRCM_CNTRY_BUF_SZ - 1); -+ strncpy(wlc_cm->ccode, ccode, BRCM_CNTRY_BUF_SZ - 1); -+ wlc_cm->regrev = regrev; -+ -+ if ((wlc->pub->_n_enab & SUPPORT_11N) != -+ wlc->protection->nmode_user) -+ brcms_c_set_nmode(wlc); -+ -+ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]); -+ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]); -+ /* set or restore gmode as required by regulatory */ -+ locale = brcms_c_get_locale_2g(country->locale_2G); -+ if (locale && (locale->flags & BRCMS_NO_OFDM)) -+ brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false); -+ else -+ brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); -+ -+ brcms_c_channels_init(wlc_cm, country); -+ -+ return; -+} -+ -+static int -+brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm, -+ const char *country_abbrev, -+ const char *ccode, int regrev) -+{ -+ const struct country_info *country; -+ char mapped_ccode[BRCM_CNTRY_BUF_SZ]; -+ uint mapped_regrev; -+ -+ /* if regrev is -1, lookup the mapped country code, -+ * otherwise use the ccode and regrev directly -+ */ -+ if (regrev == -1) { -+ /* -+ * map the country code to a built-in country -+ * code, regrev, and country_info -+ */ -+ country = -+ brcms_c_countrycode_map(wlc_cm, ccode, mapped_ccode, -+ &mapped_regrev); -+ } else { -+ /* find the matching built-in country definition */ -+ country = brcms_c_country_lookup_direct(ccode, regrev); -+ strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ); -+ mapped_regrev = regrev; -+ } -+ -+ if (country == NULL) -+ return -EINVAL; -+ -+ /* set the driver state for the country */ -+ brcms_c_set_country_common(wlc_cm, country_abbrev, mapped_ccode, -+ mapped_regrev, country); -+ -+ return 0; -+} -+ -+/* -+ * set the driver's current country and regulatory information using -+ * a country code as the source. Lookup built in country information -+ * found with the country code. -+ */ -+static int -+brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm, const char *ccode) -+{ -+ char country_abbrev[BRCM_CNTRY_BUF_SZ]; -+ strncpy(country_abbrev, ccode, BRCM_CNTRY_BUF_SZ); -+ return brcms_c_set_countrycode_rev(wlc_cm, country_abbrev, ccode, -1); -+} -+ -+struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc) -+{ -+ struct brcms_cm_info *wlc_cm; -+ char country_abbrev[BRCM_CNTRY_BUF_SZ]; -+ const struct country_info *country; -+ struct brcms_pub *pub = wlc->pub; -+ char *ccode; -+ -+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); -+ -+ wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC); -+ if (wlc_cm == NULL) -+ return NULL; -+ wlc_cm->pub = pub; -+ wlc_cm->wlc = wlc; -+ wlc->cmi = wlc_cm; -+ -+ /* store the country code for passing up as a regulatory hint */ -+ ccode = getvar(wlc->hw->sih, BRCMS_SROM_CCODE); -+ if (ccode) -+ strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1); -+ -+ /* -+ * internal country information which must match -+ * regulatory constraints in firmware -+ */ -+ memset(country_abbrev, 0, BRCM_CNTRY_BUF_SZ); -+ strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1); -+ country = brcms_c_country_lookup(wlc, country_abbrev); -+ -+ /* save default country for exiting 11d regulatory mode */ -+ strncpy(wlc->country_default, country_abbrev, BRCM_CNTRY_BUF_SZ - 1); -+ -+ /* initialize autocountry_default to driver default */ -+ strncpy(wlc->autocountry_default, "X2", BRCM_CNTRY_BUF_SZ - 1); -+ -+ brcms_c_set_countrycode(wlc_cm, country_abbrev); -+ -+ return wlc_cm; -+} -+ -+void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm) -+{ -+ kfree(wlc_cm); -+} -+ -+u8 -+brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm, -+ uint bandunit) -+{ -+ return wlc_cm->bandstate[bandunit].locale_flags; -+} -+ -+static bool -+brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, u16 chspec) -+{ -+ return (wlc_cm->wlc->pub->_n_enab & SUPPORT_11N) && -+ CHSPEC_IS40(chspec) ? -+ (isset(wlc_cm->quiet_channels.vec, -+ lower_20_sb(CHSPEC_CHANNEL(chspec))) || -+ isset(wlc_cm->quiet_channels.vec, -+ upper_20_sb(CHSPEC_CHANNEL(chspec)))) : -+ isset(wlc_cm->quiet_channels.vec, CHSPEC_CHANNEL(chspec)); -+} -+ -+void -+brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, -+ u8 local_constraint_qdbm) -+{ -+ struct brcms_c_info *wlc = wlc_cm->wlc; -+ struct txpwr_limits txpwr; -+ -+ brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr); -+ -+ brcms_c_channel_min_txpower_limits_with_local_constraint( -+ wlc_cm, &txpwr, local_constraint_qdbm -+ ); -+ -+ brcms_b_set_chanspec(wlc->hw, chanspec, -+ (brcms_c_quiet_chanspec(wlc_cm, chanspec) != 0), -+ &txpwr); -+} -+ -+#ifdef POWER_DBG -+static void wlc_phy_txpower_limits_dump(struct txpwr_limits *txpwr) -+{ -+ int i; -+ char buf[80]; -+ char fraction[4][4] = { " ", ".25", ".5 ", ".75" }; -+ -+ sprintf(buf, "CCK "); -+ for (i = 0; i < BRCMS_NUM_RATES_CCK; i++) -+ sprintf(buf[strlen(buf)], " %2d%s", -+ txpwr->cck[i] / BRCMS_TXPWR_DB_FACTOR, -+ fraction[txpwr->cck[i] % BRCMS_TXPWR_DB_FACTOR]); -+ printk(KERN_DEBUG "%s\n", buf); -+ -+ sprintf(buf, "20 MHz OFDM SISO "); -+ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) -+ sprintf(buf[strlen(buf)], " %2d%s", -+ txpwr->ofdm[i] / BRCMS_TXPWR_DB_FACTOR, -+ fraction[txpwr->ofdm[i] % BRCMS_TXPWR_DB_FACTOR]); -+ printk(KERN_DEBUG "%s\n", buf); -+ -+ sprintf(buf, "20 MHz OFDM CDD "); -+ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) -+ sprintf(buf[strlen(buf)], " %2d%s", -+ txpwr->ofdm_cdd[i] / BRCMS_TXPWR_DB_FACTOR, -+ fraction[txpwr->ofdm_cdd[i] % BRCMS_TXPWR_DB_FACTOR]); -+ printk(KERN_DEBUG "%s\n", buf); -+ -+ sprintf(buf, "40 MHz OFDM SISO "); -+ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) -+ sprintf(buf[strlen(buf)], " %2d%s", -+ txpwr->ofdm_40_siso[i] / BRCMS_TXPWR_DB_FACTOR, -+ fraction[txpwr->ofdm_40_siso[i] % -+ BRCMS_TXPWR_DB_FACTOR]); -+ printk(KERN_DEBUG "%s\n", buf); -+ -+ sprintf(buf, "40 MHz OFDM CDD "); -+ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) -+ sprintf(buf[strlen(buf)], " %2d%s", -+ txpwr->ofdm_40_cdd[i] / BRCMS_TXPWR_DB_FACTOR, -+ fraction[txpwr->ofdm_40_cdd[i] % -+ BRCMS_TXPWR_DB_FACTOR]); -+ printk(KERN_DEBUG "%s\n", buf); -+ -+ sprintf(buf, "20 MHz MCS0-7 SISO "); -+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) -+ sprintf(buf[strlen(buf)], " %2d%s", -+ txpwr->mcs_20_siso[i] / BRCMS_TXPWR_DB_FACTOR, -+ fraction[txpwr->mcs_20_siso[i] % -+ BRCMS_TXPWR_DB_FACTOR]); -+ printk(KERN_DEBUG "%s\n", buf); -+ -+ sprintf(buf, "20 MHz MCS0-7 CDD "); -+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) -+ sprintf(buf[strlen(buf)], " %2d%s", -+ txpwr->mcs_20_cdd[i] / BRCMS_TXPWR_DB_FACTOR, -+ fraction[txpwr->mcs_20_cdd[i] % -+ BRCMS_TXPWR_DB_FACTOR]); -+ printk(KERN_DEBUG "%s\n", buf); -+ -+ sprintf(buf, "20 MHz MCS0-7 STBC "); -+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) -+ sprintf(buf[strlen(buf)], " %2d%s", -+ txpwr->mcs_20_stbc[i] / BRCMS_TXPWR_DB_FACTOR, -+ fraction[txpwr->mcs_20_stbc[i] % -+ BRCMS_TXPWR_DB_FACTOR]); -+ printk(KERN_DEBUG "%s\n", buf); -+ -+ sprintf(buf, "20 MHz MCS8-15 SDM "); -+ for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) -+ sprintf(buf[strlen(buf)], " %2d%s", -+ txpwr->mcs_20_mimo[i] / BRCMS_TXPWR_DB_FACTOR, -+ fraction[txpwr->mcs_20_mimo[i] % -+ BRCMS_TXPWR_DB_FACTOR]); -+ printk(KERN_DEBUG "%s\n", buf); -+ -+ sprintf(buf, "40 MHz MCS0-7 SISO "); -+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) -+ sprintf(buf[strlen(buf)], " %2d%s", -+ txpwr->mcs_40_siso[i] / BRCMS_TXPWR_DB_FACTOR, -+ fraction[txpwr->mcs_40_siso[i] % -+ BRCMS_TXPWR_DB_FACTOR]); -+ printk(KERN_DEBUG "%s\n", buf); -+ -+ sprintf(buf, "40 MHz MCS0-7 CDD "); -+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) -+ sprintf(buf[strlen(buf)], " %2d%s", -+ txpwr->mcs_40_cdd[i] / BRCMS_TXPWR_DB_FACTOR, -+ fraction[txpwr->mcs_40_cdd[i] % -+ BRCMS_TXPWR_DB_FACTOR]); -+ printk(KERN_DEBUG "%s\n", buf); -+ -+ sprintf(buf, "40 MHz MCS0-7 STBC "); -+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) -+ sprintf(buf[strlen(buf)], " %2d%s", -+ txpwr->mcs_40_stbc[i] / BRCMS_TXPWR_DB_FACTOR, -+ fraction[txpwr->mcs_40_stbc[i] % -+ BRCMS_TXPWR_DB_FACTOR]); -+ printk(KERN_DEBUG "%s\n", buf); -+ -+ sprintf(buf, "40 MHz MCS8-15 SDM "); -+ for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) -+ sprintf(buf[strlen(buf)], " %2d%s", -+ txpwr->mcs_40_mimo[i] / BRCMS_TXPWR_DB_FACTOR, -+ fraction[txpwr->mcs_40_mimo[i] % -+ BRCMS_TXPWR_DB_FACTOR]); -+ } -+ printk(KERN_DEBUG "%s\n", buf); -+ -+ printk(KERN_DEBUG "MCS32 %2d%s\n", -+ txpwr->mcs32 / BRCMS_TXPWR_DB_FACTOR, -+ fraction[txpwr->mcs32 % BRCMS_TXPWR_DB_FACTOR]); -+} -+#endif /* POWER_DBG */ -+ -+void -+brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, -+ struct txpwr_limits *txpwr) -+{ -+ struct brcms_c_info *wlc = wlc_cm->wlc; -+ uint i; -+ uint chan; -+ int maxpwr; -+ int delta; -+ const struct country_info *country; -+ struct brcms_band *band; -+ const struct locale_info *li; -+ int conducted_max = BRCMS_TXPWR_MAX; -+ int conducted_ofdm_max = BRCMS_TXPWR_MAX; -+ const struct locale_mimo_info *li_mimo; -+ int maxpwr20, maxpwr40; -+ int maxpwr_idx; -+ uint j; -+ -+ memset(txpwr, 0, sizeof(struct txpwr_limits)); -+ -+ if (!brcms_c_valid_chanspec_db(wlc_cm, chanspec)) { -+ country = brcms_c_country_lookup(wlc, wlc->autocountry_default); -+ if (country == NULL) -+ return; -+ } else { -+ country = wlc_cm->country; -+ } -+ -+ chan = CHSPEC_CHANNEL(chanspec); -+ band = wlc->bandstate[chspec_bandunit(chanspec)]; -+ li = (band->bandtype == BRCM_BAND_5G) ? -+ brcms_c_get_locale_5g(country->locale_5G) : -+ brcms_c_get_locale_2g(country->locale_2G); -+ -+ li_mimo = (band->bandtype == BRCM_BAND_5G) ? -+ brcms_c_get_mimo_5g(country->locale_mimo_5G) : -+ brcms_c_get_mimo_2g(country->locale_mimo_2G); -+ -+ if (li->flags & BRCMS_EIRP) { -+ delta = band->antgain; -+ } else { -+ delta = 0; -+ if (band->antgain > QDB(6)) -+ delta = band->antgain - QDB(6); /* Excess over 6 dB */ -+ } -+ -+ if (li == &locale_i) { -+ conducted_max = QDB(22); -+ conducted_ofdm_max = QDB(22); -+ } -+ -+ /* CCK txpwr limits for 2.4G band */ -+ if (band->bandtype == BRCM_BAND_2G) { -+ maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_CCK(chan)]; -+ -+ maxpwr = maxpwr - delta; -+ maxpwr = max(maxpwr, 0); -+ maxpwr = min(maxpwr, conducted_max); -+ -+ for (i = 0; i < BRCMS_NUM_RATES_CCK; i++) -+ txpwr->cck[i] = (u8) maxpwr; -+ } -+ -+ /* OFDM txpwr limits for 2.4G or 5G bands */ -+ if (band->bandtype == BRCM_BAND_2G) -+ maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)]; -+ else -+ maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)]; -+ -+ maxpwr = maxpwr - delta; -+ maxpwr = max(maxpwr, 0); -+ maxpwr = min(maxpwr, conducted_ofdm_max); -+ -+ /* Keep OFDM lmit below CCK limit */ -+ if (band->bandtype == BRCM_BAND_2G) -+ maxpwr = min_t(int, maxpwr, txpwr->cck[0]); -+ -+ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) -+ txpwr->ofdm[i] = (u8) maxpwr; -+ -+ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) { -+ /* -+ * OFDM 40 MHz SISO has the same power as the corresponding -+ * MCS0-7 rate unless overriden by the locale specific code. -+ * We set this value to 0 as a flag (presumably 0 dBm isn't -+ * a possibility) and then copy the MCS0-7 value to the 40 MHz -+ * value if it wasn't explicitly set. -+ */ -+ txpwr->ofdm_40_siso[i] = 0; -+ -+ txpwr->ofdm_cdd[i] = (u8) maxpwr; -+ -+ txpwr->ofdm_40_cdd[i] = 0; -+ } -+ -+ /* MIMO/HT specific limits */ -+ if (li_mimo->flags & BRCMS_EIRP) { -+ delta = band->antgain; -+ } else { -+ delta = 0; -+ if (band->antgain > QDB(6)) -+ delta = band->antgain - QDB(6); /* Excess over 6 dB */ -+ } -+ -+ if (band->bandtype == BRCM_BAND_2G) -+ maxpwr_idx = (chan - 1); -+ else -+ maxpwr_idx = CHANNEL_POWER_IDX_5G(chan); -+ -+ maxpwr20 = li_mimo->maxpwr20[maxpwr_idx]; -+ maxpwr40 = li_mimo->maxpwr40[maxpwr_idx]; -+ -+ maxpwr20 = maxpwr20 - delta; -+ maxpwr20 = max(maxpwr20, 0); -+ maxpwr40 = maxpwr40 - delta; -+ maxpwr40 = max(maxpwr40, 0); -+ -+ /* Fill in the MCS 0-7 (SISO) rates */ -+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { -+ -+ /* -+ * 20 MHz has the same power as the corresponding OFDM rate -+ * unless overriden by the locale specific code. -+ */ -+ txpwr->mcs_20_siso[i] = txpwr->ofdm[i]; -+ txpwr->mcs_40_siso[i] = 0; -+ } -+ -+ /* Fill in the MCS 0-7 CDD rates */ -+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { -+ txpwr->mcs_20_cdd[i] = (u8) maxpwr20; -+ txpwr->mcs_40_cdd[i] = (u8) maxpwr40; -+ } -+ -+ /* -+ * These locales have SISO expressed in the -+ * table and override CDD later -+ */ -+ if (li_mimo == &locale_bn) { -+ if (li_mimo == &locale_bn) { -+ maxpwr20 = QDB(16); -+ maxpwr40 = 0; -+ -+ if (chan >= 3 && chan <= 11) -+ maxpwr40 = QDB(16); -+ } -+ -+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { -+ txpwr->mcs_20_siso[i] = (u8) maxpwr20; -+ txpwr->mcs_40_siso[i] = (u8) maxpwr40; -+ } -+ } -+ -+ /* Fill in the MCS 0-7 STBC rates */ -+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { -+ txpwr->mcs_20_stbc[i] = 0; -+ txpwr->mcs_40_stbc[i] = 0; -+ } -+ -+ /* Fill in the MCS 8-15 SDM rates */ -+ for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) { -+ txpwr->mcs_20_mimo[i] = (u8) maxpwr20; -+ txpwr->mcs_40_mimo[i] = (u8) maxpwr40; -+ } -+ -+ /* Fill in MCS32 */ -+ txpwr->mcs32 = (u8) maxpwr40; -+ -+ for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) { -+ if (txpwr->ofdm_40_cdd[i] == 0) -+ txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j]; -+ if (i == 0) { -+ i = i + 1; -+ if (txpwr->ofdm_40_cdd[i] == 0) -+ txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j]; -+ } -+ } -+ -+ /* -+ * Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO -+ * value if it wasn't provided explicitly. -+ */ -+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { -+ if (txpwr->mcs_40_siso[i] == 0) -+ txpwr->mcs_40_siso[i] = txpwr->mcs_40_cdd[i]; -+ } -+ -+ for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) { -+ if (txpwr->ofdm_40_siso[i] == 0) -+ txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j]; -+ if (i == 0) { -+ i = i + 1; -+ if (txpwr->ofdm_40_siso[i] == 0) -+ txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j]; -+ } -+ } -+ -+ /* -+ * Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding -+ * STBC values if they weren't provided explicitly. -+ */ -+ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { -+ if (txpwr->mcs_20_stbc[i] == 0) -+ txpwr->mcs_20_stbc[i] = txpwr->mcs_20_cdd[i]; -+ -+ if (txpwr->mcs_40_stbc[i] == 0) -+ txpwr->mcs_40_stbc[i] = txpwr->mcs_40_cdd[i]; -+ } -+ -+#ifdef POWER_DBG -+ wlc_phy_txpower_limits_dump(txpwr); -+#endif -+ return; -+} -+ -+/* -+ * Verify the chanspec is using a legal set of parameters, i.e. that the -+ * chanspec specified a band, bw, ctl_sb and channel and that the -+ * combination could be legal given any set of circumstances. -+ * RETURNS: true is the chanspec is malformed, false if it looks good. -+ */ -+static bool brcms_c_chspec_malformed(u16 chanspec) -+{ -+ /* must be 2G or 5G band */ -+ if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec)) -+ return true; -+ /* must be 20 or 40 bandwidth */ -+ if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec)) -+ return true; -+ -+ /* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */ -+ if (CHSPEC_IS20(chanspec)) { -+ if (!CHSPEC_SB_NONE(chanspec)) -+ return true; -+ } else if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) { -+ return true; -+ } -+ -+ return false; -+} -+ -+/* -+ * Validate the chanspec for this locale, for 40MHZ we need to also -+ * check that the sidebands are valid 20MZH channels in this locale -+ * and they are also a legal HT combination -+ */ -+static bool -+brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec, -+ bool dualband) -+{ -+ struct brcms_c_info *wlc = wlc_cm->wlc; -+ u8 channel = CHSPEC_CHANNEL(chspec); -+ -+ /* check the chanspec */ -+ if (brcms_c_chspec_malformed(chspec)) { -+ wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n", -+ wlc->pub->unit, chspec); -+ return false; -+ } -+ -+ if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) != -+ chspec_bandunit(chspec)) -+ return false; -+ -+ /* Check a 20Mhz channel */ -+ if (CHSPEC_IS20(chspec)) { -+ if (dualband) -+ return brcms_c_valid_channel20_db(wlc_cm->wlc->cmi, -+ channel); -+ else -+ return brcms_c_valid_channel20(wlc_cm->wlc->cmi, -+ channel); -+ } -+#ifdef SUPPORT_40MHZ -+ /* -+ * We know we are now checking a 40MHZ channel, so we should -+ * only be here for NPHYS -+ */ -+ if (BRCMS_ISNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) { -+ u8 upper_sideband = 0, idx; -+ u8 num_ch20_entries = -+ sizeof(chan20_info) / sizeof(struct chan20_info); -+ -+ if (!VALID_40CHANSPEC_IN_BAND(wlc, chspec_bandunit(chspec))) -+ return false; -+ -+ if (dualband) { -+ if (!brcms_c_valid_channel20_db(wlc->cmi, -+ lower_20_sb(channel)) || -+ !brcms_c_valid_channel20_db(wlc->cmi, -+ upper_20_sb(channel))) -+ return false; -+ } else { -+ if (!brcms_c_valid_channel20(wlc->cmi, -+ lower_20_sb(channel)) || -+ !brcms_c_valid_channel20(wlc->cmi, -+ upper_20_sb(channel))) -+ return false; -+ } -+ -+ /* find the lower sideband info in the sideband array */ -+ for (idx = 0; idx < num_ch20_entries; idx++) { -+ if (chan20_info[idx].sb == lower_20_sb(channel)) -+ upper_sideband = chan20_info[idx].adj_sbs; -+ } -+ /* check that the lower sideband allows an upper sideband */ -+ if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) == -+ (CH_UPPER_SB | CH_EWA_VALID)) -+ return true; -+ return false; -+ } -+#endif /* 40 MHZ */ -+ -+ return false; -+} -+ -+bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec) -+{ -+ return brcms_c_valid_chanspec_ext(wlc_cm, chspec, true); -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.h.orig 2011-11-09 13:46:58.242800670 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.h 2011-11-09 13:47:16.994566241 -0500 -@@ -0,0 +1,53 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_CHANNEL_H_ -+#define _BRCM_CHANNEL_H_ -+ -+/* conversion for phy txpwr calculations that use .25 dB units */ -+#define BRCMS_TXPWR_DB_FACTOR 4 -+ -+/* bits for locale_info flags */ -+#define BRCMS_PEAK_CONDUCTED 0x00 /* Peak for locals */ -+#define BRCMS_EIRP 0x01 /* Flag for EIRP */ -+#define BRCMS_DFS_TPC 0x02 /* Flag for DFS TPC */ -+#define BRCMS_NO_OFDM 0x04 /* Flag for No OFDM */ -+#define BRCMS_NO_40MHZ 0x08 /* Flag for No MIMO 40MHz */ -+#define BRCMS_NO_MIMO 0x10 /* Flag for No MIMO, 20 or 40 MHz */ -+#define BRCMS_RADAR_TYPE_EU 0x20 /* Flag for EU */ -+#define BRCMS_DFS_FCC BRCMS_DFS_TPC /* Flag for DFS FCC */ -+ -+#define BRCMS_DFS_EU (BRCMS_DFS_TPC | BRCMS_RADAR_TYPE_EU) /* Flag for DFS EU */ -+ -+extern struct brcms_cm_info * -+brcms_c_channel_mgr_attach(struct brcms_c_info *wlc); -+ -+extern void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm); -+ -+extern u8 brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm, -+ uint bandunit); -+ -+extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, -+ u16 chspec); -+ -+extern void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, -+ u16 chanspec, -+ struct txpwr_limits *txpwr); -+extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, -+ u16 chanspec, -+ u8 local_constraint_qdbm); -+ -+#endif /* _WLC_CHANNEL_H */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/d11.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/d11.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/d11.h.orig 2011-11-09 13:46:58.243800657 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/d11.h 2011-11-09 13:47:16.996566217 -0500 -@@ -0,0 +1,1898 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_D11_H_ -+#define _BRCM_D11_H_ -+ -+#include -+ -+#include -+#include "pub.h" -+#include "dma.h" -+ -+/* RX FIFO numbers */ -+#define RX_FIFO 0 /* data and ctl frames */ -+#define RX_TXSTATUS_FIFO 3 /* RX fifo for tx status packages */ -+ -+/* TX FIFO numbers using WME Access Category */ -+#define TX_AC_BK_FIFO 0 /* Background TX FIFO */ -+#define TX_AC_BE_FIFO 1 /* Best-Effort TX FIFO */ -+#define TX_AC_VI_FIFO 2 /* Video TX FIFO */ -+#define TX_AC_VO_FIFO 3 /* Voice TX FIFO */ -+#define TX_BCMC_FIFO 4 /* Broadcast/Multicast TX FIFO */ -+#define TX_ATIM_FIFO 5 /* TX fifo for ATIM window info */ -+ -+/* Addr is byte address used by SW; offset is word offset used by uCode */ -+ -+/* Per AC TX limit settings */ -+#define M_AC_TXLMT_BASE_ADDR (0x180 * 2) -+#define M_AC_TXLMT_ADDR(_ac) (M_AC_TXLMT_BASE_ADDR + (2 * (_ac))) -+ -+/* Legacy TX FIFO numbers */ -+#define TX_DATA_FIFO TX_AC_BE_FIFO -+#define TX_CTL_FIFO TX_AC_VO_FIFO -+ -+#define WL_RSSI_ANT_MAX 4 /* max possible rx antennas */ -+ -+struct intctrlregs { -+ u32 intstatus; -+ u32 intmask; -+}; -+ -+/* PIO structure, -+ * support two PIO format: 2 bytes access and 4 bytes access -+ * basic FIFO register set is per channel(transmit or receive) -+ * a pair of channels is defined for convenience -+ */ -+/* 2byte-wide pio register set per channel(xmt or rcv) */ -+struct pio2regs { -+ u16 fifocontrol; -+ u16 fifodata; -+ u16 fifofree; /* only valid in xmt channel, not in rcv channel */ -+ u16 PAD; -+}; -+ -+/* a pair of pio channels(tx and rx) */ -+struct pio2regp { -+ struct pio2regs tx; -+ struct pio2regs rx; -+}; -+ -+/* 4byte-wide pio register set per channel(xmt or rcv) */ -+struct pio4regs { -+ u32 fifocontrol; -+ u32 fifodata; -+}; -+ -+/* a pair of pio channels(tx and rx) */ -+struct pio4regp { -+ struct pio4regs tx; -+ struct pio4regs rx; -+}; -+ -+/* read: 32-bit register that can be read as 32-bit or as 2 16-bit -+ * write: only low 16b-it half can be written -+ */ -+union pmqreg { -+ u32 pmqhostdata; /* read only! */ -+ struct { -+ u16 pmqctrlstatus; /* read/write */ -+ u16 PAD; -+ } w; -+}; -+ -+struct fifo64 { -+ struct dma64regs dmaxmt; /* dma tx */ -+ struct pio4regs piotx; /* pio tx */ -+ struct dma64regs dmarcv; /* dma rx */ -+ struct pio4regs piorx; /* pio rx */ -+}; -+ -+/* -+ * Host Interface Registers -+ */ -+struct d11regs { -+ /* Device Control ("semi-standard host registers") */ -+ u32 PAD[3]; /* 0x0 - 0x8 */ -+ u32 biststatus; /* 0xC */ -+ u32 biststatus2; /* 0x10 */ -+ u32 PAD; /* 0x14 */ -+ u32 gptimer; /* 0x18 */ -+ u32 usectimer; /* 0x1c *//* for corerev >= 26 */ -+ -+ /* Interrupt Control *//* 0x20 */ -+ struct intctrlregs intctrlregs[8]; -+ -+ u32 PAD[40]; /* 0x60 - 0xFC */ -+ -+ u32 intrcvlazy[4]; /* 0x100 - 0x10C */ -+ -+ u32 PAD[4]; /* 0x110 - 0x11c */ -+ -+ u32 maccontrol; /* 0x120 */ -+ u32 maccommand; /* 0x124 */ -+ u32 macintstatus; /* 0x128 */ -+ u32 macintmask; /* 0x12C */ -+ -+ /* Transmit Template Access */ -+ u32 tplatewrptr; /* 0x130 */ -+ u32 tplatewrdata; /* 0x134 */ -+ u32 PAD[2]; /* 0x138 - 0x13C */ -+ -+ /* PMQ registers */ -+ union pmqreg pmqreg; /* 0x140 */ -+ u32 pmqpatl; /* 0x144 */ -+ u32 pmqpath; /* 0x148 */ -+ u32 PAD; /* 0x14C */ -+ -+ u32 chnstatus; /* 0x150 */ -+ u32 psmdebug; /* 0x154 */ -+ u32 phydebug; /* 0x158 */ -+ u32 machwcap; /* 0x15C */ -+ -+ /* Extended Internal Objects */ -+ u32 objaddr; /* 0x160 */ -+ u32 objdata; /* 0x164 */ -+ u32 PAD[2]; /* 0x168 - 0x16c */ -+ -+ u32 frmtxstatus; /* 0x170 */ -+ u32 frmtxstatus2; /* 0x174 */ -+ u32 PAD[2]; /* 0x178 - 0x17c */ -+ -+ /* TSF host access */ -+ u32 tsf_timerlow; /* 0x180 */ -+ u32 tsf_timerhigh; /* 0x184 */ -+ u32 tsf_cfprep; /* 0x188 */ -+ u32 tsf_cfpstart; /* 0x18c */ -+ u32 tsf_cfpmaxdur32; /* 0x190 */ -+ u32 PAD[3]; /* 0x194 - 0x19c */ -+ -+ u32 maccontrol1; /* 0x1a0 */ -+ u32 machwcap1; /* 0x1a4 */ -+ u32 PAD[14]; /* 0x1a8 - 0x1dc */ -+ -+ /* Clock control and hardware workarounds*/ -+ u32 clk_ctl_st; /* 0x1e0 */ -+ u32 hw_war; -+ u32 d11_phypllctl; /* the phypll request/avail bits are -+ * moved to clk_ctl_st -+ */ -+ u32 PAD[5]; /* 0x1ec - 0x1fc */ -+ -+ /* 0x200-0x37F dma/pio registers */ -+ struct fifo64 fifo64regs[6]; -+ -+ /* FIFO diagnostic port access */ -+ struct dma32diag dmafifo; /* 0x380 - 0x38C */ -+ -+ u32 aggfifocnt; /* 0x390 */ -+ u32 aggfifodata; /* 0x394 */ -+ u32 PAD[16]; /* 0x398 - 0x3d4 */ -+ u16 radioregaddr; /* 0x3d8 */ -+ u16 radioregdata; /* 0x3da */ -+ -+ /* -+ * time delay between the change on rf disable input and -+ * radio shutdown -+ */ -+ u32 rfdisabledly; /* 0x3DC */ -+ -+ /* PHY register access */ -+ u16 phyversion; /* 0x3e0 - 0x0 */ -+ u16 phybbconfig; /* 0x3e2 - 0x1 */ -+ u16 phyadcbias; /* 0x3e4 - 0x2 Bphy only */ -+ u16 phyanacore; /* 0x3e6 - 0x3 pwwrdwn on aphy */ -+ u16 phyrxstatus0; /* 0x3e8 - 0x4 */ -+ u16 phyrxstatus1; /* 0x3ea - 0x5 */ -+ u16 phycrsth; /* 0x3ec - 0x6 */ -+ u16 phytxerror; /* 0x3ee - 0x7 */ -+ u16 phychannel; /* 0x3f0 - 0x8 */ -+ u16 PAD[1]; /* 0x3f2 - 0x9 */ -+ u16 phytest; /* 0x3f4 - 0xa */ -+ u16 phy4waddr; /* 0x3f6 - 0xb */ -+ u16 phy4wdatahi; /* 0x3f8 - 0xc */ -+ u16 phy4wdatalo; /* 0x3fa - 0xd */ -+ u16 phyregaddr; /* 0x3fc - 0xe */ -+ u16 phyregdata; /* 0x3fe - 0xf */ -+ -+ /* IHR *//* 0x400 - 0x7FE */ -+ -+ /* RXE Block */ -+ u16 PAD[3]; /* 0x400 - 0x406 */ -+ u16 rcv_fifo_ctl; /* 0x406 */ -+ u16 PAD; /* 0x408 - 0x40a */ -+ u16 rcv_frm_cnt; /* 0x40a */ -+ u16 PAD[4]; /* 0x40a - 0x414 */ -+ u16 rssi; /* 0x414 */ -+ u16 PAD[5]; /* 0x414 - 0x420 */ -+ u16 rcm_ctl; /* 0x420 */ -+ u16 rcm_mat_data; /* 0x422 */ -+ u16 rcm_mat_mask; /* 0x424 */ -+ u16 rcm_mat_dly; /* 0x426 */ -+ u16 rcm_cond_mask_l; /* 0x428 */ -+ u16 rcm_cond_mask_h; /* 0x42A */ -+ u16 rcm_cond_dly; /* 0x42C */ -+ u16 PAD[1]; /* 0x42E */ -+ u16 ext_ihr_addr; /* 0x430 */ -+ u16 ext_ihr_data; /* 0x432 */ -+ u16 rxe_phyrs_2; /* 0x434 */ -+ u16 rxe_phyrs_3; /* 0x436 */ -+ u16 phy_mode; /* 0x438 */ -+ u16 rcmta_ctl; /* 0x43a */ -+ u16 rcmta_size; /* 0x43c */ -+ u16 rcmta_addr0; /* 0x43e */ -+ u16 rcmta_addr1; /* 0x440 */ -+ u16 rcmta_addr2; /* 0x442 */ -+ u16 PAD[30]; /* 0x444 - 0x480 */ -+ -+ /* PSM Block *//* 0x480 - 0x500 */ -+ -+ u16 PAD; /* 0x480 */ -+ u16 psm_maccontrol_h; /* 0x482 */ -+ u16 psm_macintstatus_l; /* 0x484 */ -+ u16 psm_macintstatus_h; /* 0x486 */ -+ u16 psm_macintmask_l; /* 0x488 */ -+ u16 psm_macintmask_h; /* 0x48A */ -+ u16 PAD; /* 0x48C */ -+ u16 psm_maccommand; /* 0x48E */ -+ u16 psm_brc; /* 0x490 */ -+ u16 psm_phy_hdr_param; /* 0x492 */ -+ u16 psm_postcard; /* 0x494 */ -+ u16 psm_pcard_loc_l; /* 0x496 */ -+ u16 psm_pcard_loc_h; /* 0x498 */ -+ u16 psm_gpio_in; /* 0x49A */ -+ u16 psm_gpio_out; /* 0x49C */ -+ u16 psm_gpio_oe; /* 0x49E */ -+ -+ u16 psm_bred_0; /* 0x4A0 */ -+ u16 psm_bred_1; /* 0x4A2 */ -+ u16 psm_bred_2; /* 0x4A4 */ -+ u16 psm_bred_3; /* 0x4A6 */ -+ u16 psm_brcl_0; /* 0x4A8 */ -+ u16 psm_brcl_1; /* 0x4AA */ -+ u16 psm_brcl_2; /* 0x4AC */ -+ u16 psm_brcl_3; /* 0x4AE */ -+ u16 psm_brpo_0; /* 0x4B0 */ -+ u16 psm_brpo_1; /* 0x4B2 */ -+ u16 psm_brpo_2; /* 0x4B4 */ -+ u16 psm_brpo_3; /* 0x4B6 */ -+ u16 psm_brwk_0; /* 0x4B8 */ -+ u16 psm_brwk_1; /* 0x4BA */ -+ u16 psm_brwk_2; /* 0x4BC */ -+ u16 psm_brwk_3; /* 0x4BE */ -+ -+ u16 psm_base_0; /* 0x4C0 */ -+ u16 psm_base_1; /* 0x4C2 */ -+ u16 psm_base_2; /* 0x4C4 */ -+ u16 psm_base_3; /* 0x4C6 */ -+ u16 psm_base_4; /* 0x4C8 */ -+ u16 psm_base_5; /* 0x4CA */ -+ u16 psm_base_6; /* 0x4CC */ -+ u16 psm_pc_reg_0; /* 0x4CE */ -+ u16 psm_pc_reg_1; /* 0x4D0 */ -+ u16 psm_pc_reg_2; /* 0x4D2 */ -+ u16 psm_pc_reg_3; /* 0x4D4 */ -+ u16 PAD[0xD]; /* 0x4D6 - 0x4DE */ -+ u16 psm_corectlsts; /* 0x4f0 *//* Corerev >= 13 */ -+ u16 PAD[0x7]; /* 0x4f2 - 0x4fE */ -+ -+ /* TXE0 Block *//* 0x500 - 0x580 */ -+ u16 txe_ctl; /* 0x500 */ -+ u16 txe_aux; /* 0x502 */ -+ u16 txe_ts_loc; /* 0x504 */ -+ u16 txe_time_out; /* 0x506 */ -+ u16 txe_wm_0; /* 0x508 */ -+ u16 txe_wm_1; /* 0x50A */ -+ u16 txe_phyctl; /* 0x50C */ -+ u16 txe_status; /* 0x50E */ -+ u16 txe_mmplcp0; /* 0x510 */ -+ u16 txe_mmplcp1; /* 0x512 */ -+ u16 txe_phyctl1; /* 0x514 */ -+ -+ u16 PAD[0x05]; /* 0x510 - 0x51E */ -+ -+ /* Transmit control */ -+ u16 xmtfifodef; /* 0x520 */ -+ u16 xmtfifo_frame_cnt; /* 0x522 *//* Corerev >= 16 */ -+ u16 xmtfifo_byte_cnt; /* 0x524 *//* Corerev >= 16 */ -+ u16 xmtfifo_head; /* 0x526 *//* Corerev >= 16 */ -+ u16 xmtfifo_rd_ptr; /* 0x528 *//* Corerev >= 16 */ -+ u16 xmtfifo_wr_ptr; /* 0x52A *//* Corerev >= 16 */ -+ u16 xmtfifodef1; /* 0x52C *//* Corerev >= 16 */ -+ -+ u16 PAD[0x09]; /* 0x52E - 0x53E */ -+ -+ u16 xmtfifocmd; /* 0x540 */ -+ u16 xmtfifoflush; /* 0x542 */ -+ u16 xmtfifothresh; /* 0x544 */ -+ u16 xmtfifordy; /* 0x546 */ -+ u16 xmtfifoprirdy; /* 0x548 */ -+ u16 xmtfiforqpri; /* 0x54A */ -+ u16 xmttplatetxptr; /* 0x54C */ -+ u16 PAD; /* 0x54E */ -+ u16 xmttplateptr; /* 0x550 */ -+ u16 smpl_clct_strptr; /* 0x552 *//* Corerev >= 22 */ -+ u16 smpl_clct_stpptr; /* 0x554 *//* Corerev >= 22 */ -+ u16 smpl_clct_curptr; /* 0x556 *//* Corerev >= 22 */ -+ u16 PAD[0x04]; /* 0x558 - 0x55E */ -+ u16 xmttplatedatalo; /* 0x560 */ -+ u16 xmttplatedatahi; /* 0x562 */ -+ -+ u16 PAD[2]; /* 0x564 - 0x566 */ -+ -+ u16 xmtsel; /* 0x568 */ -+ u16 xmttxcnt; /* 0x56A */ -+ u16 xmttxshmaddr; /* 0x56C */ -+ -+ u16 PAD[0x09]; /* 0x56E - 0x57E */ -+ -+ /* TXE1 Block */ -+ u16 PAD[0x40]; /* 0x580 - 0x5FE */ -+ -+ /* TSF Block */ -+ u16 PAD[0X02]; /* 0x600 - 0x602 */ -+ u16 tsf_cfpstrt_l; /* 0x604 */ -+ u16 tsf_cfpstrt_h; /* 0x606 */ -+ u16 PAD[0X05]; /* 0x608 - 0x610 */ -+ u16 tsf_cfppretbtt; /* 0x612 */ -+ u16 PAD[0XD]; /* 0x614 - 0x62C */ -+ u16 tsf_clk_frac_l; /* 0x62E */ -+ u16 tsf_clk_frac_h; /* 0x630 */ -+ u16 PAD[0X14]; /* 0x632 - 0x658 */ -+ u16 tsf_random; /* 0x65A */ -+ u16 PAD[0x05]; /* 0x65C - 0x664 */ -+ /* GPTimer 2 registers */ -+ u16 tsf_gpt2_stat; /* 0x666 */ -+ u16 tsf_gpt2_ctr_l; /* 0x668 */ -+ u16 tsf_gpt2_ctr_h; /* 0x66A */ -+ u16 tsf_gpt2_val_l; /* 0x66C */ -+ u16 tsf_gpt2_val_h; /* 0x66E */ -+ u16 tsf_gptall_stat; /* 0x670 */ -+ u16 PAD[0x07]; /* 0x672 - 0x67E */ -+ -+ /* IFS Block */ -+ u16 ifs_sifs_rx_tx_tx; /* 0x680 */ -+ u16 ifs_sifs_nav_tx; /* 0x682 */ -+ u16 ifs_slot; /* 0x684 */ -+ u16 PAD; /* 0x686 */ -+ u16 ifs_ctl; /* 0x688 */ -+ u16 PAD[0x3]; /* 0x68a - 0x68F */ -+ u16 ifsstat; /* 0x690 */ -+ u16 ifsmedbusyctl; /* 0x692 */ -+ u16 iftxdur; /* 0x694 */ -+ u16 PAD[0x3]; /* 0x696 - 0x69b */ -+ /* EDCF support in dot11macs */ -+ u16 ifs_aifsn; /* 0x69c */ -+ u16 ifs_ctl1; /* 0x69e */ -+ -+ /* slow clock registers */ -+ u16 scc_ctl; /* 0x6a0 */ -+ u16 scc_timer_l; /* 0x6a2 */ -+ u16 scc_timer_h; /* 0x6a4 */ -+ u16 scc_frac; /* 0x6a6 */ -+ u16 scc_fastpwrup_dly; /* 0x6a8 */ -+ u16 scc_per; /* 0x6aa */ -+ u16 scc_per_frac; /* 0x6ac */ -+ u16 scc_cal_timer_l; /* 0x6ae */ -+ u16 scc_cal_timer_h; /* 0x6b0 */ -+ u16 PAD; /* 0x6b2 */ -+ -+ u16 PAD[0x26]; -+ -+ /* NAV Block */ -+ u16 nav_ctl; /* 0x700 */ -+ u16 navstat; /* 0x702 */ -+ u16 PAD[0x3e]; /* 0x702 - 0x77E */ -+ -+ /* WEP/PMQ Block *//* 0x780 - 0x7FE */ -+ u16 PAD[0x20]; /* 0x780 - 0x7BE */ -+ -+ u16 wepctl; /* 0x7C0 */ -+ u16 wepivloc; /* 0x7C2 */ -+ u16 wepivkey; /* 0x7C4 */ -+ u16 wepwkey; /* 0x7C6 */ -+ -+ u16 PAD[4]; /* 0x7C8 - 0x7CE */ -+ u16 pcmctl; /* 0X7D0 */ -+ u16 pcmstat; /* 0X7D2 */ -+ u16 PAD[6]; /* 0x7D4 - 0x7DE */ -+ -+ u16 pmqctl; /* 0x7E0 */ -+ u16 pmqstatus; /* 0x7E2 */ -+ u16 pmqpat0; /* 0x7E4 */ -+ u16 pmqpat1; /* 0x7E6 */ -+ u16 pmqpat2; /* 0x7E8 */ -+ -+ u16 pmqdat; /* 0x7EA */ -+ u16 pmqdator; /* 0x7EC */ -+ u16 pmqhst; /* 0x7EE */ -+ u16 pmqpath0; /* 0x7F0 */ -+ u16 pmqpath1; /* 0x7F2 */ -+ u16 pmqpath2; /* 0x7F4 */ -+ u16 pmqdath; /* 0x7F6 */ -+ -+ u16 PAD[0x04]; /* 0x7F8 - 0x7FE */ -+ -+ /* SHM *//* 0x800 - 0xEFE */ -+ u16 PAD[0x380]; /* 0x800 - 0xEFE */ -+}; -+ -+#define PIHR_BASE 0x0400 /* byte address of packed IHR region */ -+ -+/* biststatus */ -+#define BT_DONE (1U << 31) /* bist done */ -+#define BT_B2S (1 << 30) /* bist2 ram summary bit */ -+ -+/* intstatus and intmask */ -+#define I_PC (1 << 10) /* pci descriptor error */ -+#define I_PD (1 << 11) /* pci data error */ -+#define I_DE (1 << 12) /* descriptor protocol error */ -+#define I_RU (1 << 13) /* receive descriptor underflow */ -+#define I_RO (1 << 14) /* receive fifo overflow */ -+#define I_XU (1 << 15) /* transmit fifo underflow */ -+#define I_RI (1 << 16) /* receive interrupt */ -+#define I_XI (1 << 24) /* transmit interrupt */ -+ -+/* interrupt receive lazy */ -+#define IRL_TO_MASK 0x00ffffff /* timeout */ -+#define IRL_FC_MASK 0xff000000 /* frame count */ -+#define IRL_FC_SHIFT 24 /* frame count */ -+ -+/*== maccontrol register ==*/ -+#define MCTL_GMODE (1U << 31) -+#define MCTL_DISCARD_PMQ (1 << 30) -+#define MCTL_WAKE (1 << 26) -+#define MCTL_HPS (1 << 25) -+#define MCTL_PROMISC (1 << 24) -+#define MCTL_KEEPBADFCS (1 << 23) -+#define MCTL_KEEPCONTROL (1 << 22) -+#define MCTL_PHYLOCK (1 << 21) -+#define MCTL_BCNS_PROMISC (1 << 20) -+#define MCTL_LOCK_RADIO (1 << 19) -+#define MCTL_AP (1 << 18) -+#define MCTL_INFRA (1 << 17) -+#define MCTL_BIGEND (1 << 16) -+#define MCTL_GPOUT_SEL_MASK (3 << 14) -+#define MCTL_GPOUT_SEL_SHIFT 14 -+#define MCTL_EN_PSMDBG (1 << 13) -+#define MCTL_IHR_EN (1 << 10) -+#define MCTL_SHM_UPPER (1 << 9) -+#define MCTL_SHM_EN (1 << 8) -+#define MCTL_PSM_JMP_0 (1 << 2) -+#define MCTL_PSM_RUN (1 << 1) -+#define MCTL_EN_MAC (1 << 0) -+ -+/*== maccommand register ==*/ -+#define MCMD_BCN0VLD (1 << 0) -+#define MCMD_BCN1VLD (1 << 1) -+#define MCMD_DIRFRMQVAL (1 << 2) -+#define MCMD_CCA (1 << 3) -+#define MCMD_BG_NOISE (1 << 4) -+#define MCMD_SKIP_SHMINIT (1 << 5) /* only used for simulation */ -+#define MCMD_SAMPLECOLL MCMD_SKIP_SHMINIT /* reuse for sample collect */ -+ -+/*== macintstatus/macintmask ==*/ -+/* gracefully suspended */ -+#define MI_MACSSPNDD (1 << 0) -+/* beacon template available */ -+#define MI_BCNTPL (1 << 1) -+/* TBTT indication */ -+#define MI_TBTT (1 << 2) -+/* beacon successfully tx'd */ -+#define MI_BCNSUCCESS (1 << 3) -+/* beacon canceled (IBSS) */ -+#define MI_BCNCANCLD (1 << 4) -+/* end of ATIM-window (IBSS) */ -+#define MI_ATIMWINEND (1 << 5) -+/* PMQ entries available */ -+#define MI_PMQ (1 << 6) -+/* non-specific gen-stat bits that are set by PSM */ -+#define MI_NSPECGEN_0 (1 << 7) -+/* non-specific gen-stat bits that are set by PSM */ -+#define MI_NSPECGEN_1 (1 << 8) -+/* MAC level Tx error */ -+#define MI_MACTXERR (1 << 9) -+/* non-specific gen-stat bits that are set by PSM */ -+#define MI_NSPECGEN_3 (1 << 10) -+/* PHY Tx error */ -+#define MI_PHYTXERR (1 << 11) -+/* Power Management Event */ -+#define MI_PME (1 << 12) -+/* General-purpose timer0 */ -+#define MI_GP0 (1 << 13) -+/* General-purpose timer1 */ -+#define MI_GP1 (1 << 14) -+/* (ORed) DMA-interrupts */ -+#define MI_DMAINT (1 << 15) -+/* MAC has completed a TX FIFO Suspend/Flush */ -+#define MI_TXSTOP (1 << 16) -+/* MAC has completed a CCA measurement */ -+#define MI_CCA (1 << 17) -+/* MAC has collected background noise samples */ -+#define MI_BG_NOISE (1 << 18) -+/* MBSS DTIM TBTT indication */ -+#define MI_DTIM_TBTT (1 << 19) -+/* Probe response queue needs attention */ -+#define MI_PRQ (1 << 20) -+/* Radio/PHY has been powered back up. */ -+#define MI_PWRUP (1 << 21) -+#define MI_RESERVED3 (1 << 22) -+#define MI_RESERVED2 (1 << 23) -+#define MI_RESERVED1 (1 << 25) -+/* MAC detected change on RF Disable input*/ -+#define MI_RFDISABLE (1 << 28) -+/* MAC has completed a TX */ -+#define MI_TFS (1 << 29) -+/* A phy status change wrt G mode */ -+#define MI_PHYCHANGED (1 << 30) -+/* general purpose timeout */ -+#define MI_TO (1U << 31) -+ -+/* Mac capabilities registers */ -+/*== machwcap ==*/ -+#define MCAP_TKIPMIC 0x80000000 /* TKIP MIC hardware present */ -+ -+/*== pmqhost data ==*/ -+/* data entry of head pmq entry */ -+#define PMQH_DATA_MASK 0xffff0000 -+/* PM entry for BSS config */ -+#define PMQH_BSSCFG 0x00100000 -+/* PM Mode OFF: power save off */ -+#define PMQH_PMOFF 0x00010000 -+/* PM Mode ON: power save on */ -+#define PMQH_PMON 0x00020000 -+/* Dis-associated or De-authenticated */ -+#define PMQH_DASAT 0x00040000 -+/* ATIM not acknowledged */ -+#define PMQH_ATIMFAIL 0x00080000 -+/* delete head entry */ -+#define PMQH_DEL_ENTRY 0x00000001 -+/* delete head entry to cur read pointer -1 */ -+#define PMQH_DEL_MULT 0x00000002 -+/* pmq overflow indication */ -+#define PMQH_OFLO 0x00000004 -+/* entries are present in pmq */ -+#define PMQH_NOT_EMPTY 0x00000008 -+ -+/*== phydebug ==*/ -+/* phy is asserting carrier sense */ -+#define PDBG_CRS (1 << 0) -+/* phy is taking xmit byte from mac this cycle */ -+#define PDBG_TXA (1 << 1) -+/* mac is instructing the phy to transmit a frame */ -+#define PDBG_TXF (1 << 2) -+/* phy is signalling a transmit Error to the mac */ -+#define PDBG_TXE (1 << 3) -+/* phy detected the end of a valid frame preamble */ -+#define PDBG_RXF (1 << 4) -+/* phy detected the end of a valid PLCP header */ -+#define PDBG_RXS (1 << 5) -+/* rx start not asserted */ -+#define PDBG_RXFRG (1 << 6) -+/* mac is taking receive byte from phy this cycle */ -+#define PDBG_RXV (1 << 7) -+/* RF portion of the radio is disabled */ -+#define PDBG_RFD (1 << 16) -+ -+/*== objaddr register ==*/ -+#define OBJADDR_SEL_MASK 0x000F0000 -+#define OBJADDR_UCM_SEL 0x00000000 -+#define OBJADDR_SHM_SEL 0x00010000 -+#define OBJADDR_SCR_SEL 0x00020000 -+#define OBJADDR_IHR_SEL 0x00030000 -+#define OBJADDR_RCMTA_SEL 0x00040000 -+#define OBJADDR_SRCHM_SEL 0x00060000 -+#define OBJADDR_WINC 0x01000000 -+#define OBJADDR_RINC 0x02000000 -+#define OBJADDR_AUTO_INC 0x03000000 -+ -+#define WEP_PCMADDR 0x07d4 -+#define WEP_PCMDATA 0x07d6 -+ -+/*== frmtxstatus ==*/ -+#define TXS_V (1 << 0) /* valid bit */ -+#define TXS_STATUS_MASK 0xffff -+#define TXS_FID_MASK 0xffff0000 -+#define TXS_FID_SHIFT 16 -+ -+/*== frmtxstatus2 ==*/ -+#define TXS_SEQ_MASK 0xffff -+#define TXS_PTX_MASK 0xff0000 -+#define TXS_PTX_SHIFT 16 -+#define TXS_MU_MASK 0x01000000 -+#define TXS_MU_SHIFT 24 -+ -+/*== clk_ctl_st ==*/ -+#define CCS_ERSRC_REQ_D11PLL 0x00000100 /* d11 core pll request */ -+#define CCS_ERSRC_REQ_PHYPLL 0x00000200 /* PHY pll request */ -+#define CCS_ERSRC_AVAIL_D11PLL 0x01000000 /* d11 core pll available */ -+#define CCS_ERSRC_AVAIL_PHYPLL 0x02000000 /* PHY pll available */ -+ -+/* HT Cloclk Ctrl and Clock Avail for 4313 */ -+#define CCS_ERSRC_REQ_HT 0x00000010 /* HT avail request */ -+#define CCS_ERSRC_AVAIL_HT 0x00020000 /* HT clock available */ -+ -+/* tsf_cfprep register */ -+#define CFPREP_CBI_MASK 0xffffffc0 -+#define CFPREP_CBI_SHIFT 6 -+#define CFPREP_CFPP 0x00000001 -+ -+/* tx fifo sizes values are in terms of 256 byte blocks */ -+#define TXFIFOCMD_RESET_MASK (1 << 15) /* reset */ -+#define TXFIFOCMD_FIFOSEL_SHIFT 8 /* fifo */ -+#define TXFIFO_FIFOTOP_SHIFT 8 /* fifo start */ -+ -+#define TXFIFO_START_BLK16 65 /* Base address + 32 * 512 B/P */ -+#define TXFIFO_START_BLK 6 /* Base address + 6 * 256 B */ -+#define TXFIFO_SIZE_UNIT 256 /* one unit corresponds to 256 bytes */ -+#define MBSS16_TEMPLMEM_MINBLKS 65 /* one unit corresponds to 256 bytes */ -+ -+/*== phy versions (PhyVersion:Revision field) ==*/ -+/* analog block version */ -+#define PV_AV_MASK 0xf000 -+/* analog block version bitfield offset */ -+#define PV_AV_SHIFT 12 -+/* phy type */ -+#define PV_PT_MASK 0x0f00 -+/* phy type bitfield offset */ -+#define PV_PT_SHIFT 8 -+/* phy version */ -+#define PV_PV_MASK 0x000f -+#define PHY_TYPE(v) ((v & PV_PT_MASK) >> PV_PT_SHIFT) -+ -+/*== phy types (PhyVersion:PhyType field) ==*/ -+#define PHY_TYPE_N 4 /* N-Phy value */ -+#define PHY_TYPE_SSN 6 /* SSLPN-Phy value */ -+#define PHY_TYPE_LCN 8 /* LCN-Phy value */ -+#define PHY_TYPE_LCNXN 9 /* LCNXN-Phy value */ -+#define PHY_TYPE_NULL 0xf /* Invalid Phy value */ -+ -+/*== analog types (PhyVersion:AnalogType field) ==*/ -+#define ANA_11N_013 5 -+ -+/* 802.11a PLCP header def */ -+struct ofdm_phy_hdr { -+ u8 rlpt[3]; /* rate, length, parity, tail */ -+ u16 service; -+ u8 pad; -+} __packed; -+ -+#define D11A_PHY_HDR_GRATE(phdr) ((phdr)->rlpt[0] & 0x0f) -+#define D11A_PHY_HDR_GRES(phdr) (((phdr)->rlpt[0] >> 4) & 0x01) -+#define D11A_PHY_HDR_GLENGTH(phdr) (((u32 *)((phdr)->rlpt) >> 5) & 0x0fff) -+#define D11A_PHY_HDR_GPARITY(phdr) (((phdr)->rlpt[3] >> 1) & 0x01) -+#define D11A_PHY_HDR_GTAIL(phdr) (((phdr)->rlpt[3] >> 2) & 0x3f) -+ -+/* rate encoded per 802.11a-1999 sec 17.3.4.1 */ -+#define D11A_PHY_HDR_SRATE(phdr, rate) \ -+ ((phdr)->rlpt[0] = ((phdr)->rlpt[0] & 0xf0) | ((rate) & 0xf)) -+/* set reserved field to zero */ -+#define D11A_PHY_HDR_SRES(phdr) ((phdr)->rlpt[0] &= 0xef) -+/* length is number of octets in PSDU */ -+#define D11A_PHY_HDR_SLENGTH(phdr, length) \ -+ (*(u32 *)((phdr)->rlpt) = *(u32 *)((phdr)->rlpt) | \ -+ (((length) & 0x0fff) << 5)) -+/* set the tail to all zeros */ -+#define D11A_PHY_HDR_STAIL(phdr) ((phdr)->rlpt[3] &= 0x03) -+ -+#define D11A_PHY_HDR_LEN_L 3 /* low-rate part of PLCP header */ -+#define D11A_PHY_HDR_LEN_R 2 /* high-rate part of PLCP header */ -+ -+#define D11A_PHY_TX_DELAY (2) /* 2.1 usec */ -+ -+#define D11A_PHY_HDR_TIME (4) /* low-rate part of PLCP header */ -+#define D11A_PHY_PRE_TIME (16) -+#define D11A_PHY_PREHDR_TIME (D11A_PHY_PRE_TIME + D11A_PHY_HDR_TIME) -+ -+/* 802.11b PLCP header def */ -+struct cck_phy_hdr { -+ u8 signal; -+ u8 service; -+ u16 length; -+ u16 crc; -+} __packed; -+ -+#define D11B_PHY_HDR_LEN 6 -+ -+#define D11B_PHY_TX_DELAY (3) /* 3.4 usec */ -+ -+#define D11B_PHY_LHDR_TIME (D11B_PHY_HDR_LEN << 3) -+#define D11B_PHY_LPRE_TIME (144) -+#define D11B_PHY_LPREHDR_TIME (D11B_PHY_LPRE_TIME + D11B_PHY_LHDR_TIME) -+ -+#define D11B_PHY_SHDR_TIME (D11B_PHY_LHDR_TIME >> 1) -+#define D11B_PHY_SPRE_TIME (D11B_PHY_LPRE_TIME >> 1) -+#define D11B_PHY_SPREHDR_TIME (D11B_PHY_SPRE_TIME + D11B_PHY_SHDR_TIME) -+ -+#define D11B_PLCP_SIGNAL_LOCKED (1 << 2) -+#define D11B_PLCP_SIGNAL_LE (1 << 7) -+ -+#define MIMO_PLCP_MCS_MASK 0x7f /* mcs index */ -+#define MIMO_PLCP_40MHZ 0x80 /* 40 Hz frame */ -+#define MIMO_PLCP_AMPDU 0x08 /* ampdu */ -+ -+#define BRCMS_GET_CCK_PLCP_LEN(plcp) (plcp[4] + (plcp[5] << 8)) -+#define BRCMS_GET_MIMO_PLCP_LEN(plcp) (plcp[1] + (plcp[2] << 8)) -+#define BRCMS_SET_MIMO_PLCP_LEN(plcp, len) \ -+ do { \ -+ plcp[1] = len & 0xff; \ -+ plcp[2] = ((len >> 8) & 0xff); \ -+ } while (0); -+ -+#define BRCMS_SET_MIMO_PLCP_AMPDU(plcp) (plcp[3] |= MIMO_PLCP_AMPDU) -+#define BRCMS_CLR_MIMO_PLCP_AMPDU(plcp) (plcp[3] &= ~MIMO_PLCP_AMPDU) -+#define BRCMS_IS_MIMO_PLCP_AMPDU(plcp) (plcp[3] & MIMO_PLCP_AMPDU) -+ -+/* -+ * The dot11a PLCP header is 5 bytes. To simplify the software (so that we -+ * don't need e.g. different tx DMA headers for 11a and 11b), the PLCP header -+ * has padding added in the ucode. -+ */ -+#define D11_PHY_HDR_LEN 6 -+ -+/* TX DMA buffer header */ -+struct d11txh { -+ __le16 MacTxControlLow; /* 0x0 */ -+ __le16 MacTxControlHigh; /* 0x1 */ -+ __le16 MacFrameControl; /* 0x2 */ -+ __le16 TxFesTimeNormal; /* 0x3 */ -+ __le16 PhyTxControlWord; /* 0x4 */ -+ __le16 PhyTxControlWord_1; /* 0x5 */ -+ __le16 PhyTxControlWord_1_Fbr; /* 0x6 */ -+ __le16 PhyTxControlWord_1_Rts; /* 0x7 */ -+ __le16 PhyTxControlWord_1_FbrRts; /* 0x8 */ -+ __le16 MainRates; /* 0x9 */ -+ __le16 XtraFrameTypes; /* 0xa */ -+ u8 IV[16]; /* 0x0b - 0x12 */ -+ u8 TxFrameRA[6]; /* 0x13 - 0x15 */ -+ __le16 TxFesTimeFallback; /* 0x16 */ -+ u8 RTSPLCPFallback[6]; /* 0x17 - 0x19 */ -+ __le16 RTSDurFallback; /* 0x1a */ -+ u8 FragPLCPFallback[6]; /* 0x1b - 1d */ -+ __le16 FragDurFallback; /* 0x1e */ -+ __le16 MModeLen; /* 0x1f */ -+ __le16 MModeFbrLen; /* 0x20 */ -+ __le16 TstampLow; /* 0x21 */ -+ __le16 TstampHigh; /* 0x22 */ -+ __le16 ABI_MimoAntSel; /* 0x23 */ -+ __le16 PreloadSize; /* 0x24 */ -+ __le16 AmpduSeqCtl; /* 0x25 */ -+ __le16 TxFrameID; /* 0x26 */ -+ __le16 TxStatus; /* 0x27 */ -+ __le16 MaxNMpdus; /* 0x28 */ -+ __le16 MaxABytes_MRT; /* 0x29 */ -+ __le16 MaxABytes_FBR; /* 0x2a */ -+ __le16 MinMBytes; /* 0x2b */ -+ u8 RTSPhyHeader[D11_PHY_HDR_LEN]; /* 0x2c - 0x2e */ -+ struct ieee80211_rts rts_frame; /* 0x2f - 0x36 */ -+ u16 PAD; /* 0x37 */ -+} __packed; -+ -+#define D11_TXH_LEN 112 /* bytes */ -+ -+/* Frame Types */ -+#define FT_CCK 0 -+#define FT_OFDM 1 -+#define FT_HT 2 -+#define FT_N 3 -+ -+/* -+ * Position of MPDU inside A-MPDU; indicated with bits 10:9 -+ * of MacTxControlLow -+ */ -+#define TXC_AMPDU_SHIFT 9 /* shift for ampdu settings */ -+#define TXC_AMPDU_NONE 0 /* Regular MPDU, not an A-MPDU */ -+#define TXC_AMPDU_FIRST 1 /* first MPDU of an A-MPDU */ -+#define TXC_AMPDU_MIDDLE 2 /* intermediate MPDU of an A-MPDU */ -+#define TXC_AMPDU_LAST 3 /* last (or single) MPDU of an A-MPDU */ -+ -+/*== MacTxControlLow ==*/ -+#define TXC_AMIC 0x8000 -+#define TXC_SENDCTS 0x0800 -+#define TXC_AMPDU_MASK 0x0600 -+#define TXC_BW_40 0x0100 -+#define TXC_FREQBAND_5G 0x0080 -+#define TXC_DFCS 0x0040 -+#define TXC_IGNOREPMQ 0x0020 -+#define TXC_HWSEQ 0x0010 -+#define TXC_STARTMSDU 0x0008 -+#define TXC_SENDRTS 0x0004 -+#define TXC_LONGFRAME 0x0002 -+#define TXC_IMMEDACK 0x0001 -+ -+/*== MacTxControlHigh ==*/ -+/* RTS fallback preamble type 1 = SHORT 0 = LONG */ -+#define TXC_PREAMBLE_RTS_FB_SHORT 0x8000 -+/* RTS main rate preamble type 1 = SHORT 0 = LONG */ -+#define TXC_PREAMBLE_RTS_MAIN_SHORT 0x4000 -+/* -+ * Main fallback rate preamble type -+ * 1 = SHORT for OFDM/GF for MIMO -+ * 0 = LONG for CCK/MM for MIMO -+ */ -+#define TXC_PREAMBLE_DATA_FB_SHORT 0x2000 -+ -+/* TXC_PREAMBLE_DATA_MAIN is in PhyTxControl bit 5 */ -+/* use fallback rate for this AMPDU */ -+#define TXC_AMPDU_FBR 0x1000 -+#define TXC_SECKEY_MASK 0x0FF0 -+#define TXC_SECKEY_SHIFT 4 -+/* Use alternate txpwr defined at loc. M_ALT_TXPWR_IDX */ -+#define TXC_ALT_TXPWR 0x0008 -+#define TXC_SECTYPE_MASK 0x0007 -+#define TXC_SECTYPE_SHIFT 0 -+ -+/* Null delimiter for Fallback rate */ -+#define AMPDU_FBR_NULL_DELIM 5 /* Location of Null delimiter count for AMPDU */ -+ -+/* PhyTxControl for Mimophy */ -+#define PHY_TXC_PWR_MASK 0xFC00 -+#define PHY_TXC_PWR_SHIFT 10 -+#define PHY_TXC_ANT_MASK 0x03C0 /* bit 6, 7, 8, 9 */ -+#define PHY_TXC_ANT_SHIFT 6 -+#define PHY_TXC_ANT_0_1 0x00C0 /* auto, last rx */ -+#define PHY_TXC_LCNPHY_ANT_LAST 0x0000 -+#define PHY_TXC_ANT_3 0x0200 /* virtual antenna 3 */ -+#define PHY_TXC_ANT_2 0x0100 /* virtual antenna 2 */ -+#define PHY_TXC_ANT_1 0x0080 /* virtual antenna 1 */ -+#define PHY_TXC_ANT_0 0x0040 /* virtual antenna 0 */ -+#define PHY_TXC_SHORT_HDR 0x0010 -+ -+#define PHY_TXC_OLD_ANT_0 0x0000 -+#define PHY_TXC_OLD_ANT_1 0x0100 -+#define PHY_TXC_OLD_ANT_LAST 0x0300 -+ -+/* PhyTxControl_1 for Mimophy */ -+#define PHY_TXC1_BW_MASK 0x0007 -+#define PHY_TXC1_BW_10MHZ 0 -+#define PHY_TXC1_BW_10MHZ_UP 1 -+#define PHY_TXC1_BW_20MHZ 2 -+#define PHY_TXC1_BW_20MHZ_UP 3 -+#define PHY_TXC1_BW_40MHZ 4 -+#define PHY_TXC1_BW_40MHZ_DUP 5 -+#define PHY_TXC1_MODE_SHIFT 3 -+#define PHY_TXC1_MODE_MASK 0x0038 -+#define PHY_TXC1_MODE_SISO 0 -+#define PHY_TXC1_MODE_CDD 1 -+#define PHY_TXC1_MODE_STBC 2 -+#define PHY_TXC1_MODE_SDM 3 -+ -+/* PhyTxControl for HTphy that are different from Mimophy */ -+#define PHY_TXC_HTANT_MASK 0x3fC0 /* bits 6-13 */ -+ -+/* XtraFrameTypes */ -+#define XFTS_RTS_FT_SHIFT 2 -+#define XFTS_FBRRTS_FT_SHIFT 4 -+#define XFTS_CHANNEL_SHIFT 8 -+ -+/* Antenna diversity bit in ant_wr_settle */ -+#define PHY_AWS_ANTDIV 0x2000 -+ -+/* IFS ctl */ -+#define IFS_USEEDCF (1 << 2) -+ -+/* IFS ctl1 */ -+#define IFS_CTL1_EDCRS (1 << 3) -+#define IFS_CTL1_EDCRS_20L (1 << 4) -+#define IFS_CTL1_EDCRS_40 (1 << 5) -+ -+/* ABI_MimoAntSel */ -+#define ABI_MAS_ADDR_BMP_IDX_MASK 0x0f00 -+#define ABI_MAS_ADDR_BMP_IDX_SHIFT 8 -+#define ABI_MAS_FBR_ANT_PTN_MASK 0x00f0 -+#define ABI_MAS_FBR_ANT_PTN_SHIFT 4 -+#define ABI_MAS_MRT_ANT_PTN_MASK 0x000f -+ -+/* tx status packet */ -+struct tx_status { -+ u16 framelen; -+ u16 PAD; -+ u16 frameid; -+ u16 status; -+ u16 lasttxtime; -+ u16 sequence; -+ u16 phyerr; -+ u16 ackphyrxsh; -+} __packed; -+ -+#define TXSTATUS_LEN 16 -+ -+/* status field bit definitions */ -+#define TX_STATUS_FRM_RTX_MASK 0xF000 -+#define TX_STATUS_FRM_RTX_SHIFT 12 -+#define TX_STATUS_RTS_RTX_MASK 0x0F00 -+#define TX_STATUS_RTS_RTX_SHIFT 8 -+#define TX_STATUS_MASK 0x00FE -+#define TX_STATUS_PMINDCTD (1 << 7) /* PM mode indicated to AP */ -+#define TX_STATUS_INTERMEDIATE (1 << 6) /* intermediate or 1st ampdu pkg */ -+#define TX_STATUS_AMPDU (1 << 5) /* AMPDU status */ -+#define TX_STATUS_SUPR_MASK 0x1C /* suppress status bits (4:2) */ -+#define TX_STATUS_SUPR_SHIFT 2 -+#define TX_STATUS_ACK_RCV (1 << 1) /* ACK received */ -+#define TX_STATUS_VALID (1 << 0) /* Tx status valid */ -+#define TX_STATUS_NO_ACK 0 -+ -+/* suppress status reason codes */ -+#define TX_STATUS_SUPR_PMQ (1 << 2) /* PMQ entry */ -+#define TX_STATUS_SUPR_FLUSH (2 << 2) /* flush request */ -+#define TX_STATUS_SUPR_FRAG (3 << 2) /* previous frag failure */ -+#define TX_STATUS_SUPR_TBTT (3 << 2) /* SHARED: Probe resp supr for TBTT */ -+#define TX_STATUS_SUPR_BADCH (4 << 2) /* channel mismatch */ -+#define TX_STATUS_SUPR_EXPTIME (5 << 2) /* lifetime expiry */ -+#define TX_STATUS_SUPR_UF (6 << 2) /* underflow */ -+ -+/* Unexpected tx status for rate update */ -+#define TX_STATUS_UNEXP(status) \ -+ ((((status) & TX_STATUS_INTERMEDIATE) != 0) && \ -+ TX_STATUS_UNEXP_AMPDU(status)) -+ -+/* Unexpected tx status for A-MPDU rate update */ -+#define TX_STATUS_UNEXP_AMPDU(status) \ -+ ((((status) & TX_STATUS_SUPR_MASK) != 0) && \ -+ (((status) & TX_STATUS_SUPR_MASK) != TX_STATUS_SUPR_EXPTIME)) -+ -+#define TX_STATUS_BA_BMAP03_MASK 0xF000 /* ba bitmap 0:3 in 1st pkg */ -+#define TX_STATUS_BA_BMAP03_SHIFT 12 /* ba bitmap 0:3 in 1st pkg */ -+#define TX_STATUS_BA_BMAP47_MASK 0x001E /* ba bitmap 4:7 in 2nd pkg */ -+#define TX_STATUS_BA_BMAP47_SHIFT 3 /* ba bitmap 4:7 in 2nd pkg */ -+ -+/* RXE (Receive Engine) */ -+ -+/* RCM_CTL */ -+#define RCM_INC_MASK_H 0x0080 -+#define RCM_INC_MASK_L 0x0040 -+#define RCM_INC_DATA 0x0020 -+#define RCM_INDEX_MASK 0x001F -+#define RCM_SIZE 15 -+ -+#define RCM_MAC_OFFSET 0 /* current MAC address */ -+#define RCM_BSSID_OFFSET 3 /* current BSSID address */ -+#define RCM_F_BSSID_0_OFFSET 6 /* foreign BSS CFP tracking */ -+#define RCM_F_BSSID_1_OFFSET 9 /* foreign BSS CFP tracking */ -+#define RCM_F_BSSID_2_OFFSET 12 /* foreign BSS CFP tracking */ -+ -+#define RCM_WEP_TA0_OFFSET 16 -+#define RCM_WEP_TA1_OFFSET 19 -+#define RCM_WEP_TA2_OFFSET 22 -+#define RCM_WEP_TA3_OFFSET 25 -+ -+/* PSM Block */ -+ -+/* psm_phy_hdr_param bits */ -+#define MAC_PHY_RESET 1 -+#define MAC_PHY_CLOCK_EN 2 -+#define MAC_PHY_FORCE_CLK 4 -+ -+/* WEP Block */ -+ -+/* WEP_WKEY */ -+#define WKEY_START (1 << 8) -+#define WKEY_SEL_MASK 0x1F -+ -+/* WEP data formats */ -+ -+/* the number of RCMTA entries */ -+#define RCMTA_SIZE 50 -+ -+#define M_ADDR_BMP_BLK (0x37e * 2) -+#define M_ADDR_BMP_BLK_SZ 12 -+ -+#define ADDR_BMP_RA (1 << 0) /* Receiver Address (RA) */ -+#define ADDR_BMP_TA (1 << 1) /* Transmitter Address (TA) */ -+#define ADDR_BMP_BSSID (1 << 2) /* BSSID */ -+#define ADDR_BMP_AP (1 << 3) /* Infra-BSS Access Point */ -+#define ADDR_BMP_STA (1 << 4) /* Infra-BSS Station */ -+#define ADDR_BMP_RESERVED1 (1 << 5) -+#define ADDR_BMP_RESERVED2 (1 << 6) -+#define ADDR_BMP_RESERVED3 (1 << 7) -+#define ADDR_BMP_BSS_IDX_MASK (3 << 8) /* BSS control block index */ -+#define ADDR_BMP_BSS_IDX_SHIFT 8 -+ -+#define WSEC_MAX_RCMTA_KEYS 54 -+ -+/* max keys in M_TKMICKEYS_BLK */ -+#define WSEC_MAX_TKMIC_ENGINE_KEYS 12 /* 8 + 4 default */ -+ -+/* max RXE match registers */ -+#define WSEC_MAX_RXE_KEYS 4 -+ -+/* SECKINDXALGO (Security Key Index & Algorithm Block) word format */ -+/* SKL (Security Key Lookup) */ -+#define SKL_ALGO_MASK 0x0007 -+#define SKL_ALGO_SHIFT 0 -+#define SKL_KEYID_MASK 0x0008 -+#define SKL_KEYID_SHIFT 3 -+#define SKL_INDEX_MASK 0x03F0 -+#define SKL_INDEX_SHIFT 4 -+#define SKL_GRP_ALGO_MASK 0x1c00 -+#define SKL_GRP_ALGO_SHIFT 10 -+ -+/* additional bits defined for IBSS group key support */ -+#define SKL_IBSS_INDEX_MASK 0x01F0 -+#define SKL_IBSS_INDEX_SHIFT 4 -+#define SKL_IBSS_KEYID1_MASK 0x0600 -+#define SKL_IBSS_KEYID1_SHIFT 9 -+#define SKL_IBSS_KEYID2_MASK 0x1800 -+#define SKL_IBSS_KEYID2_SHIFT 11 -+#define SKL_IBSS_KEYALGO_MASK 0xE000 -+#define SKL_IBSS_KEYALGO_SHIFT 13 -+ -+#define WSEC_MODE_OFF 0 -+#define WSEC_MODE_HW 1 -+#define WSEC_MODE_SW 2 -+ -+#define WSEC_ALGO_OFF 0 -+#define WSEC_ALGO_WEP1 1 -+#define WSEC_ALGO_TKIP 2 -+#define WSEC_ALGO_AES 3 -+#define WSEC_ALGO_WEP128 4 -+#define WSEC_ALGO_AES_LEGACY 5 -+#define WSEC_ALGO_NALG 6 -+ -+#define AES_MODE_NONE 0 -+#define AES_MODE_CCM 1 -+ -+/* WEP_CTL (Rev 0) */ -+#define WECR0_KEYREG_SHIFT 0 -+#define WECR0_KEYREG_MASK 0x7 -+#define WECR0_DECRYPT (1 << 3) -+#define WECR0_IVINLINE (1 << 4) -+#define WECR0_WEPALG_SHIFT 5 -+#define WECR0_WEPALG_MASK (0x7 << 5) -+#define WECR0_WKEYSEL_SHIFT 8 -+#define WECR0_WKEYSEL_MASK (0x7 << 8) -+#define WECR0_WKEYSTART (1 << 11) -+#define WECR0_WEPINIT (1 << 14) -+#define WECR0_ICVERR (1 << 15) -+ -+/* Frame template map byte offsets */ -+#define T_ACTS_TPL_BASE (0) -+#define T_NULL_TPL_BASE (0xc * 2) -+#define T_QNULL_TPL_BASE (0x1c * 2) -+#define T_RR_TPL_BASE (0x2c * 2) -+#define T_BCN0_TPL_BASE (0x34 * 2) -+#define T_PRS_TPL_BASE (0x134 * 2) -+#define T_BCN1_TPL_BASE (0x234 * 2) -+#define T_TX_FIFO_TXRAM_BASE (T_ACTS_TPL_BASE + \ -+ (TXFIFO_START_BLK * TXFIFO_SIZE_UNIT)) -+ -+#define T_BA_TPL_BASE T_QNULL_TPL_BASE /* template area for BA */ -+ -+#define T_RAM_ACCESS_SZ 4 /* template ram is 4 byte access only */ -+ -+/* Shared Mem byte offsets */ -+ -+/* Location where the ucode expects the corerev */ -+#define M_MACHW_VER (0x00b * 2) -+ -+/* Location where the ucode expects the MAC capabilities */ -+#define M_MACHW_CAP_L (0x060 * 2) -+#define M_MACHW_CAP_H (0x061 * 2) -+ -+/* WME shared memory */ -+#define M_EDCF_STATUS_OFF (0x007 * 2) -+#define M_TXF_CUR_INDEX (0x018 * 2) -+#define M_EDCF_QINFO (0x120 * 2) -+ -+/* PS-mode related parameters */ -+#define M_DOT11_SLOT (0x008 * 2) -+#define M_DOT11_DTIMPERIOD (0x009 * 2) -+#define M_NOSLPZNATDTIM (0x026 * 2) -+ -+/* Beacon-related parameters */ -+#define M_BCN0_FRM_BYTESZ (0x00c * 2) /* Bcn 0 template length */ -+#define M_BCN1_FRM_BYTESZ (0x00d * 2) /* Bcn 1 template length */ -+#define M_BCN_TXTSF_OFFSET (0x00e * 2) -+#define M_TIMBPOS_INBEACON (0x00f * 2) -+#define M_SFRMTXCNTFBRTHSD (0x022 * 2) -+#define M_LFRMTXCNTFBRTHSD (0x023 * 2) -+#define M_BCN_PCTLWD (0x02a * 2) -+#define M_BCN_LI (0x05b * 2) /* beacon listen interval */ -+ -+/* MAX Rx Frame len */ -+#define M_MAXRXFRM_LEN (0x010 * 2) -+ -+/* ACK/CTS related params */ -+#define M_RSP_PCTLWD (0x011 * 2) -+ -+/* Hardware Power Control */ -+#define M_TXPWR_N (0x012 * 2) -+#define M_TXPWR_TARGET (0x013 * 2) -+#define M_TXPWR_MAX (0x014 * 2) -+#define M_TXPWR_CUR (0x019 * 2) -+ -+/* Rx-related parameters */ -+#define M_RX_PAD_DATA_OFFSET (0x01a * 2) -+ -+/* WEP Shared mem data */ -+#define M_SEC_DEFIVLOC (0x01e * 2) -+#define M_SEC_VALNUMSOFTMCHTA (0x01f * 2) -+#define M_PHYVER (0x028 * 2) -+#define M_PHYTYPE (0x029 * 2) -+#define M_SECRXKEYS_PTR (0x02b * 2) -+#define M_TKMICKEYS_PTR (0x059 * 2) -+#define M_SECKINDXALGO_BLK (0x2ea * 2) -+#define M_SECKINDXALGO_BLK_SZ 54 -+#define M_SECPSMRXTAMCH_BLK (0x2fa * 2) -+#define M_TKIP_TSC_TTAK (0x18c * 2) -+#define D11_MAX_KEY_SIZE 16 -+ -+#define M_MAX_ANTCNT (0x02e * 2) /* antenna swap threshold */ -+ -+/* Probe response related parameters */ -+#define M_SSIDLEN (0x024 * 2) -+#define M_PRB_RESP_FRM_LEN (0x025 * 2) -+#define M_PRS_MAXTIME (0x03a * 2) -+#define M_SSID (0xb0 * 2) -+#define M_CTXPRS_BLK (0xc0 * 2) -+#define C_CTX_PCTLWD_POS (0x4 * 2) -+ -+/* Delta between OFDM and CCK power in CCK power boost mode */ -+#define M_OFDM_OFFSET (0x027 * 2) -+ -+/* TSSI for last 4 11b/g CCK packets transmitted */ -+#define M_B_TSSI_0 (0x02c * 2) -+#define M_B_TSSI_1 (0x02d * 2) -+ -+/* Host flags to turn on ucode options */ -+#define M_HOST_FLAGS1 (0x02f * 2) -+#define M_HOST_FLAGS2 (0x030 * 2) -+#define M_HOST_FLAGS3 (0x031 * 2) -+#define M_HOST_FLAGS4 (0x03c * 2) -+#define M_HOST_FLAGS5 (0x06a * 2) -+#define M_HOST_FLAGS_SZ 16 -+ -+#define M_RADAR_REG (0x033 * 2) -+ -+/* TSSI for last 4 11a OFDM packets transmitted */ -+#define M_A_TSSI_0 (0x034 * 2) -+#define M_A_TSSI_1 (0x035 * 2) -+ -+/* noise interference measurement */ -+#define M_NOISE_IF_COUNT (0x034 * 2) -+#define M_NOISE_IF_TIMEOUT (0x035 * 2) -+ -+#define M_RF_RX_SP_REG1 (0x036 * 2) -+ -+/* TSSI for last 4 11g OFDM packets transmitted */ -+#define M_G_TSSI_0 (0x038 * 2) -+#define M_G_TSSI_1 (0x039 * 2) -+ -+/* Background noise measure */ -+#define M_JSSI_0 (0x44 * 2) -+#define M_JSSI_1 (0x45 * 2) -+#define M_JSSI_AUX (0x46 * 2) -+ -+#define M_CUR_2050_RADIOCODE (0x47 * 2) -+ -+/* TX fifo sizes */ -+#define M_FIFOSIZE0 (0x4c * 2) -+#define M_FIFOSIZE1 (0x4d * 2) -+#define M_FIFOSIZE2 (0x4e * 2) -+#define M_FIFOSIZE3 (0x4f * 2) -+#define D11_MAX_TX_FRMS 32 /* max frames allowed in tx fifo */ -+ -+/* Current channel number plus upper bits */ -+#define M_CURCHANNEL (0x50 * 2) -+#define D11_CURCHANNEL_5G 0x0100; -+#define D11_CURCHANNEL_40 0x0200; -+#define D11_CURCHANNEL_MAX 0x00FF; -+ -+/* last posted frameid on the bcmc fifo */ -+#define M_BCMC_FID (0x54 * 2) -+#define INVALIDFID 0xffff -+ -+/* extended beacon phyctl bytes for 11N */ -+#define M_BCN_PCTL1WD (0x058 * 2) -+ -+/* idle busy ratio to duty_cycle requirement */ -+#define M_TX_IDLE_BUSY_RATIO_X_16_CCK (0x52 * 2) -+#define M_TX_IDLE_BUSY_RATIO_X_16_OFDM (0x5A * 2) -+ -+/* CW RSSI for LCNPHY */ -+#define M_LCN_RSSI_0 0x1332 -+#define M_LCN_RSSI_1 0x1338 -+#define M_LCN_RSSI_2 0x133e -+#define M_LCN_RSSI_3 0x1344 -+ -+/* SNR for LCNPHY */ -+#define M_LCN_SNR_A_0 0x1334 -+#define M_LCN_SNR_B_0 0x1336 -+ -+#define M_LCN_SNR_A_1 0x133a -+#define M_LCN_SNR_B_1 0x133c -+ -+#define M_LCN_SNR_A_2 0x1340 -+#define M_LCN_SNR_B_2 0x1342 -+ -+#define M_LCN_SNR_A_3 0x1346 -+#define M_LCN_SNR_B_3 0x1348 -+ -+#define M_LCN_LAST_RESET (81*2) -+#define M_LCN_LAST_LOC (63*2) -+#define M_LCNPHY_RESET_STATUS (4902) -+#define M_LCNPHY_DSC_TIME (0x98d*2) -+#define M_LCNPHY_RESET_CNT_DSC (0x98b*2) -+#define M_LCNPHY_RESET_CNT (0x98c*2) -+ -+/* Rate table offsets */ -+#define M_RT_DIRMAP_A (0xe0 * 2) -+#define M_RT_BBRSMAP_A (0xf0 * 2) -+#define M_RT_DIRMAP_B (0x100 * 2) -+#define M_RT_BBRSMAP_B (0x110 * 2) -+ -+/* Rate table entry offsets */ -+#define M_RT_PRS_PLCP_POS 10 -+#define M_RT_PRS_DUR_POS 16 -+#define M_RT_OFDM_PCTL1_POS 18 -+ -+#define M_20IN40_IQ (0x380 * 2) -+ -+/* SHM locations where ucode stores the current power index */ -+#define M_CURR_IDX1 (0x384 * 2) -+#define M_CURR_IDX2 (0x387 * 2) -+ -+#define M_BSCALE_ANT0 (0x5e * 2) -+#define M_BSCALE_ANT1 (0x5f * 2) -+ -+/* Antenna Diversity Testing */ -+#define M_MIMO_ANTSEL_RXDFLT (0x63 * 2) -+#define M_ANTSEL_CLKDIV (0x61 * 2) -+#define M_MIMO_ANTSEL_TXDFLT (0x64 * 2) -+ -+#define M_MIMO_MAXSYM (0x5d * 2) -+#define MIMO_MAXSYM_DEF 0x8000 /* 32k */ -+#define MIMO_MAXSYM_MAX 0xffff /* 64k */ -+ -+#define M_WATCHDOG_8TU (0x1e * 2) -+#define WATCHDOG_8TU_DEF 5 -+#define WATCHDOG_8TU_MAX 10 -+ -+/* Manufacturing Test Variables */ -+/* PER test mode */ -+#define M_PKTENG_CTRL (0x6c * 2) -+/* IFS for TX mode */ -+#define M_PKTENG_IFS (0x6d * 2) -+/* Lower word of tx frmcnt/rx lostcnt */ -+#define M_PKTENG_FRMCNT_LO (0x6e * 2) -+/* Upper word of tx frmcnt/rx lostcnt */ -+#define M_PKTENG_FRMCNT_HI (0x6f * 2) -+ -+/* Index variation in vbat ripple */ -+#define M_LCN_PWR_IDX_MAX (0x67 * 2) /* highest index read by ucode */ -+#define M_LCN_PWR_IDX_MIN (0x66 * 2) /* lowest index read by ucode */ -+ -+/* M_PKTENG_CTRL bit definitions */ -+#define M_PKTENG_MODE_TX 0x0001 -+#define M_PKTENG_MODE_TX_RIFS 0x0004 -+#define M_PKTENG_MODE_TX_CTS 0x0008 -+#define M_PKTENG_MODE_RX 0x0002 -+#define M_PKTENG_MODE_RX_WITH_ACK 0x0402 -+#define M_PKTENG_MODE_MASK 0x0003 -+/* TX frames indicated in the frmcnt reg */ -+#define M_PKTENG_FRMCNT_VLD 0x0100 -+ -+/* Sample Collect parameters (bitmap and type) */ -+/* Trigger bitmap for sample collect */ -+#define M_SMPL_COL_BMP (0x37d * 2) -+/* Sample collect type */ -+#define M_SMPL_COL_CTL (0x3b2 * 2) -+ -+#define ANTSEL_CLKDIV_4MHZ 6 -+#define MIMO_ANTSEL_BUSY 0x4000 /* bit 14 (busy) */ -+#define MIMO_ANTSEL_SEL 0x8000 /* bit 15 write the value */ -+#define MIMO_ANTSEL_WAIT 50 /* 50us wait */ -+#define MIMO_ANTSEL_OVERRIDE 0x8000 /* flag */ -+ -+struct shm_acparams { -+ u16 txop; -+ u16 cwmin; -+ u16 cwmax; -+ u16 cwcur; -+ u16 aifs; -+ u16 bslots; -+ u16 reggap; -+ u16 status; -+ u16 rsvd[8]; -+} __packed; -+#define M_EDCF_QLEN (16 * 2) -+ -+#define WME_STATUS_NEWAC (1 << 8) -+ -+/* M_HOST_FLAGS */ -+#define MHFMAX 5 /* Number of valid hostflag half-word (u16) */ -+#define MHF1 0 /* Hostflag 1 index */ -+#define MHF2 1 /* Hostflag 2 index */ -+#define MHF3 2 /* Hostflag 3 index */ -+#define MHF4 3 /* Hostflag 4 index */ -+#define MHF5 4 /* Hostflag 5 index */ -+ -+/* Flags in M_HOST_FLAGS */ -+/* Enable ucode antenna diversity help */ -+#define MHF1_ANTDIV 0x0001 -+/* Enable EDCF access control */ -+#define MHF1_EDCF 0x0100 -+#define MHF1_IQSWAP_WAR 0x0200 -+/* Disable Slow clock request, for corerev < 11 */ -+#define MHF1_FORCEFASTCLK 0x0400 -+ -+/* Flags in M_HOST_FLAGS2 */ -+ -+/* Flush BCMC FIFO immediately */ -+#define MHF2_TXBCMC_NOW 0x0040 -+/* Enable ucode/hw power control */ -+#define MHF2_HWPWRCTL 0x0080 -+#define MHF2_NPHY40MHZ_WAR 0x0800 -+ -+/* Flags in M_HOST_FLAGS3 */ -+/* enabled mimo antenna selection */ -+#define MHF3_ANTSEL_EN 0x0001 -+/* antenna selection mode: 0: 2x3, 1: 2x4 */ -+#define MHF3_ANTSEL_MODE 0x0002 -+#define MHF3_RESERVED1 0x0004 -+#define MHF3_RESERVED2 0x0008 -+#define MHF3_NPHY_MLADV_WAR 0x0010 -+ -+/* Flags in M_HOST_FLAGS4 */ -+/* force bphy Tx on core 0 (board level WAR) */ -+#define MHF4_BPHY_TXCORE0 0x0080 -+/* for 4313A0 FEM boards */ -+#define MHF4_EXTPA_ENABLE 0x4000 -+ -+/* Flags in M_HOST_FLAGS5 */ -+#define MHF5_4313_GPIOCTRL 0x0001 -+#define MHF5_RESERVED1 0x0002 -+#define MHF5_RESERVED2 0x0004 -+/* Radio power setting for ucode */ -+#define M_RADIO_PWR (0x32 * 2) -+ -+/* phy noise recorded by ucode right after tx */ -+#define M_PHY_NOISE (0x037 * 2) -+#define PHY_NOISE_MASK 0x00ff -+ -+/* -+ * Receive Frame Data Header for 802.11b DCF-only frames -+ * -+ * RxFrameSize: Actual byte length of the frame data received -+ * PAD: padding (not used) -+ * PhyRxStatus_0: PhyRxStatus 15:0 -+ * PhyRxStatus_1: PhyRxStatus 31:16 -+ * PhyRxStatus_2: PhyRxStatus 47:32 -+ * PhyRxStatus_3: PhyRxStatus 63:48 -+ * PhyRxStatus_4: PhyRxStatus 79:64 -+ * PhyRxStatus_5: PhyRxStatus 95:80 -+ * RxStatus1: MAC Rx Status -+ * RxStatus2: extended MAC Rx status -+ * RxTSFTime: RxTSFTime time of first MAC symbol + M_PHY_PLCPRX_DLY -+ * RxChan: gain code, channel radio code, and phy type -+ */ -+struct d11rxhdr_le { -+ __le16 RxFrameSize; -+ u16 PAD; -+ __le16 PhyRxStatus_0; -+ __le16 PhyRxStatus_1; -+ __le16 PhyRxStatus_2; -+ __le16 PhyRxStatus_3; -+ __le16 PhyRxStatus_4; -+ __le16 PhyRxStatus_5; -+ __le16 RxStatus1; -+ __le16 RxStatus2; -+ __le16 RxTSFTime; -+ __le16 RxChan; -+} __packed; -+ -+struct d11rxhdr { -+ u16 RxFrameSize; -+ u16 PAD; -+ u16 PhyRxStatus_0; -+ u16 PhyRxStatus_1; -+ u16 PhyRxStatus_2; -+ u16 PhyRxStatus_3; -+ u16 PhyRxStatus_4; -+ u16 PhyRxStatus_5; -+ u16 RxStatus1; -+ u16 RxStatus2; -+ u16 RxTSFTime; -+ u16 RxChan; -+} __packed; -+ -+/* PhyRxStatus_0: */ -+/* NPHY only: CCK, OFDM, preN, N */ -+#define PRXS0_FT_MASK 0x0003 -+/* NPHY only: clip count adjustment steps by AGC */ -+#define PRXS0_CLIP_MASK 0x000C -+#define PRXS0_CLIP_SHIFT 2 -+/* PHY received a frame with unsupported rate */ -+#define PRXS0_UNSRATE 0x0010 -+/* GPHY: rx ant, NPHY: upper sideband */ -+#define PRXS0_RXANT_UPSUBBAND 0x0020 -+/* CCK frame only: lost crs during cck frame reception */ -+#define PRXS0_LCRS 0x0040 -+/* Short Preamble */ -+#define PRXS0_SHORTH 0x0080 -+/* PLCP violation */ -+#define PRXS0_PLCPFV 0x0100 -+/* PLCP header integrity check failed */ -+#define PRXS0_PLCPHCF 0x0200 -+/* legacy PHY gain control */ -+#define PRXS0_GAIN_CTL 0x4000 -+/* NPHY: Antennas used for received frame, bitmask */ -+#define PRXS0_ANTSEL_MASK 0xF000 -+#define PRXS0_ANTSEL_SHIFT 0x12 -+ -+/* subfield PRXS0_FT_MASK */ -+#define PRXS0_CCK 0x0000 -+/* valid only for G phy, use rxh->RxChan for A phy */ -+#define PRXS0_OFDM 0x0001 -+#define PRXS0_PREN 0x0002 -+#define PRXS0_STDN 0x0003 -+ -+/* subfield PRXS0_ANTSEL_MASK */ -+#define PRXS0_ANTSEL_0 0x0 /* antenna 0 is used */ -+#define PRXS0_ANTSEL_1 0x2 /* antenna 1 is used */ -+#define PRXS0_ANTSEL_2 0x4 /* antenna 2 is used */ -+#define PRXS0_ANTSEL_3 0x8 /* antenna 3 is used */ -+ -+/* PhyRxStatus_1: */ -+#define PRXS1_JSSI_MASK 0x00FF -+#define PRXS1_JSSI_SHIFT 0 -+#define PRXS1_SQ_MASK 0xFF00 -+#define PRXS1_SQ_SHIFT 8 -+ -+/* nphy PhyRxStatus_1: */ -+#define PRXS1_nphy_PWR0_MASK 0x00FF -+#define PRXS1_nphy_PWR1_MASK 0xFF00 -+ -+/* HTPHY Rx Status defines */ -+/* htphy PhyRxStatus_0: those bit are overlapped with PhyRxStatus_0 */ -+#define PRXS0_BAND 0x0400 /* 0 = 2.4G, 1 = 5G */ -+#define PRXS0_RSVD 0x0800 /* reserved; set to 0 */ -+#define PRXS0_UNUSED 0xF000 /* unused and not defined; set to 0 */ -+ -+/* htphy PhyRxStatus_1: */ -+/* core enables for {3..0}, 0=disabled, 1=enabled */ -+#define PRXS1_HTPHY_CORE_MASK 0x000F -+/* antenna configation */ -+#define PRXS1_HTPHY_ANTCFG_MASK 0x00F0 -+/* Mixmode PLCP Length low byte mask */ -+#define PRXS1_HTPHY_MMPLCPLenL_MASK 0xFF00 -+ -+/* htphy PhyRxStatus_2: */ -+/* Mixmode PLCP Length high byte maskw */ -+#define PRXS2_HTPHY_MMPLCPLenH_MASK 0x000F -+/* Mixmode PLCP rate mask */ -+#define PRXS2_HTPHY_MMPLCH_RATE_MASK 0x00F0 -+/* Rx power on core 0 */ -+#define PRXS2_HTPHY_RXPWR_ANT0 0xFF00 -+ -+/* htphy PhyRxStatus_3: */ -+/* Rx power on core 1 */ -+#define PRXS3_HTPHY_RXPWR_ANT1 0x00FF -+/* Rx power on core 2 */ -+#define PRXS3_HTPHY_RXPWR_ANT2 0xFF00 -+ -+/* htphy PhyRxStatus_4: */ -+/* Rx power on core 3 */ -+#define PRXS4_HTPHY_RXPWR_ANT3 0x00FF -+/* Coarse frequency offset */ -+#define PRXS4_HTPHY_CFO 0xFF00 -+ -+/* htphy PhyRxStatus_5: */ -+/* Fine frequency offset */ -+#define PRXS5_HTPHY_FFO 0x00FF -+/* Advance Retard */ -+#define PRXS5_HTPHY_AR 0xFF00 -+ -+#define HTPHY_MMPLCPLen(rxs) \ -+ ((((rxs)->PhyRxStatus_1 & PRXS1_HTPHY_MMPLCPLenL_MASK) >> 8) | \ -+ (((rxs)->PhyRxStatus_2 & PRXS2_HTPHY_MMPLCPLenH_MASK) << 8)) -+/* Get Rx power on core 0 */ -+#define HTPHY_RXPWR_ANT0(rxs) \ -+ ((((rxs)->PhyRxStatus_2) & PRXS2_HTPHY_RXPWR_ANT0) >> 8) -+/* Get Rx power on core 1 */ -+#define HTPHY_RXPWR_ANT1(rxs) \ -+ (((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT1) -+/* Get Rx power on core 2 */ -+#define HTPHY_RXPWR_ANT2(rxs) \ -+ ((((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT2) >> 8) -+ -+/* ucode RxStatus1: */ -+#define RXS_BCNSENT 0x8000 -+#define RXS_SECKINDX_MASK 0x07e0 -+#define RXS_SECKINDX_SHIFT 5 -+#define RXS_DECERR (1 << 4) -+#define RXS_DECATMPT (1 << 3) -+/* PAD bytes to make IP data 4 bytes aligned */ -+#define RXS_PBPRES (1 << 2) -+#define RXS_RESPFRAMETX (1 << 1) -+#define RXS_FCSERR (1 << 0) -+ -+/* ucode RxStatus2: */ -+#define RXS_AMSDU_MASK 1 -+#define RXS_AGGTYPE_MASK 0x6 -+#define RXS_AGGTYPE_SHIFT 1 -+#define RXS_PHYRXST_VALID (1 << 8) -+#define RXS_RXANT_MASK 0x3 -+#define RXS_RXANT_SHIFT 12 -+ -+/* RxChan */ -+#define RXS_CHAN_40 0x1000 -+#define RXS_CHAN_5G 0x0800 -+#define RXS_CHAN_ID_MASK 0x07f8 -+#define RXS_CHAN_ID_SHIFT 3 -+#define RXS_CHAN_PHYTYPE_MASK 0x0007 -+#define RXS_CHAN_PHYTYPE_SHIFT 0 -+ -+/* Index of attenuations used during ucode power control. */ -+#define M_PWRIND_BLKS (0x184 * 2) -+#define M_PWRIND_MAP0 (M_PWRIND_BLKS + 0x0) -+#define M_PWRIND_MAP1 (M_PWRIND_BLKS + 0x2) -+#define M_PWRIND_MAP2 (M_PWRIND_BLKS + 0x4) -+#define M_PWRIND_MAP3 (M_PWRIND_BLKS + 0x6) -+/* M_PWRIND_MAP(core) macro */ -+#define M_PWRIND_MAP(core) (M_PWRIND_BLKS + ((core)<<1)) -+ -+/* PSM SHM variable offsets */ -+#define M_PSM_SOFT_REGS 0x0 -+#define M_BOM_REV_MAJOR (M_PSM_SOFT_REGS + 0x0) -+#define M_BOM_REV_MINOR (M_PSM_SOFT_REGS + 0x2) -+#define M_UCODE_DBGST (M_PSM_SOFT_REGS + 0x40) /* ucode debug status code */ -+#define M_UCODE_MACSTAT (M_PSM_SOFT_REGS + 0xE0) /* macstat counters */ -+ -+#define M_AGING_THRSH (0x3e * 2) /* max time waiting for medium before tx */ -+#define M_MBURST_SIZE (0x40 * 2) /* max frames in a frameburst */ -+#define M_MBURST_TXOP (0x41 * 2) /* max frameburst TXOP in unit of us */ -+#define M_SYNTHPU_DLY (0x4a * 2) /* pre-wakeup for synthpu, default: 500 */ -+#define M_PRETBTT (0x4b * 2) -+ -+/* offset to the target txpwr */ -+#define M_ALT_TXPWR_IDX (M_PSM_SOFT_REGS + (0x3b * 2)) -+#define M_PHY_TX_FLT_PTR (M_PSM_SOFT_REGS + (0x3d * 2)) -+#define M_CTS_DURATION (M_PSM_SOFT_REGS + (0x5c * 2)) -+#define M_LP_RCCAL_OVR (M_PSM_SOFT_REGS + (0x6b * 2)) -+ -+/* PKTENG Rx Stats Block */ -+#define M_RXSTATS_BLK_PTR (M_PSM_SOFT_REGS + (0x65 * 2)) -+ -+/* ucode debug status codes */ -+/* not valid really */ -+#define DBGST_INACTIVE 0 -+/* after zeroing SHM, before suspending at init */ -+#define DBGST_INIT 1 -+/* "normal" state */ -+#define DBGST_ACTIVE 2 -+/* suspended */ -+#define DBGST_SUSPENDED 3 -+/* asleep (PS mode) */ -+#define DBGST_ASLEEP 4 -+ -+/* Scratch Reg defs */ -+enum _ePsmScratchPadRegDefinitions { -+ S_RSV0 = 0, -+ S_RSV1, -+ S_RSV2, -+ -+ /* offset 0x03: scratch registers for Dot11-contants */ -+ S_DOT11_CWMIN, /* CW-minimum */ -+ S_DOT11_CWMAX, /* CW-maximum */ -+ S_DOT11_CWCUR, /* CW-current */ -+ S_DOT11_SRC_LMT, /* short retry count limit */ -+ S_DOT11_LRC_LMT, /* long retry count limit */ -+ S_DOT11_DTIMCOUNT, /* DTIM-count */ -+ -+ /* offset 0x09: Tx-side scratch registers */ -+ S_SEQ_NUM, /* hardware sequence number reg */ -+ S_SEQ_NUM_FRAG, /* seq num for frags (at the start of MSDU) */ -+ S_FRMRETX_CNT, /* frame retx count */ -+ S_SSRC, /* Station short retry count */ -+ S_SLRC, /* Station long retry count */ -+ S_EXP_RSP, /* Expected response frame */ -+ S_OLD_BREM, /* Remaining backoff ctr */ -+ S_OLD_CWWIN, /* saved-off CW-cur */ -+ S_TXECTL, /* TXE-Ctl word constructed in scr-pad */ -+ S_CTXTST, /* frm type-subtype as read from Tx-descr */ -+ -+ /* offset 0x13: Rx-side scratch registers */ -+ S_RXTST, /* Type and subtype in Rxframe */ -+ -+ /* Global state register */ -+ S_STREG, /* state storage actual bit maps below */ -+ -+ S_TXPWR_SUM, /* Tx power control: accumulator */ -+ S_TXPWR_ITER, /* Tx power control: iteration */ -+ S_RX_FRMTYPE, /* Rate and PHY type for frames */ -+ S_THIS_AGG, /* Size of this AGG (A-MSDU) */ -+ -+ S_KEYINDX, -+ S_RXFRMLEN, /* Receive MPDU length in bytes */ -+ -+ /* offset 0x1B: Receive TSF time stored in SCR */ -+ S_RXTSFTMRVAL_WD3, /* TSF value at the start of rx */ -+ S_RXTSFTMRVAL_WD2, /* TSF value at the start of rx */ -+ S_RXTSFTMRVAL_WD1, /* TSF value at the start of rx */ -+ S_RXTSFTMRVAL_WD0, /* TSF value at the start of rx */ -+ S_RXSSN, /* Received start seq number for A-MPDU BA */ -+ S_RXQOSFLD, /* Rx-QoS field (if present) */ -+ -+ /* offset 0x21: Scratch pad regs used in microcode as temp storage */ -+ S_TMP0, /* stmp0 */ -+ S_TMP1, /* stmp1 */ -+ S_TMP2, /* stmp2 */ -+ S_TMP3, /* stmp3 */ -+ S_TMP4, /* stmp4 */ -+ S_TMP5, /* stmp5 */ -+ S_PRQPENALTY_CTR, /* Probe response queue penalty counter */ -+ S_ANTCNT, /* unsuccessful attempts on current ant. */ -+ S_SYMBOL, /* flag for possible symbol ctl frames */ -+ S_RXTP, /* rx frame type */ -+ S_STREG2, /* extra state storage */ -+ S_STREG3, /* even more extra state storage */ -+ S_STREG4, /* ... */ -+ S_STREG5, /* remember to initialize it to zero */ -+ -+ S_ADJPWR_IDX, -+ S_CUR_PTR, /* Temp pointer for A-MPDU re-Tx SHM table */ -+ S_REVID4, /* 0x33 */ -+ S_INDX, /* 0x34 */ -+ S_ADDR0, /* 0x35 */ -+ S_ADDR1, /* 0x36 */ -+ S_ADDR2, /* 0x37 */ -+ S_ADDR3, /* 0x38 */ -+ S_ADDR4, /* 0x39 */ -+ S_ADDR5, /* 0x3A */ -+ S_TMP6, /* 0x3B */ -+ S_KEYINDX_BU, /* Backup for Key index */ -+ S_MFGTEST_TMP0, /* Temp regs used for RX test calculations */ -+ S_RXESN, /* Received end sequence number for A-MPDU BA */ -+ S_STREG6, /* 0x3F */ -+}; -+ -+#define S_BEACON_INDX S_OLD_BREM -+#define S_PRS_INDX S_OLD_CWWIN -+#define S_PHYTYPE S_SSRC -+#define S_PHYVER S_SLRC -+ -+/* IHR SLOW_CTRL values */ -+#define SLOW_CTRL_PDE (1 << 0) -+#define SLOW_CTRL_FD (1 << 8) -+ -+/* ucode mac statistic counters in shared memory */ -+struct macstat { -+ u16 txallfrm; /* 0x80 */ -+ u16 txrtsfrm; /* 0x82 */ -+ u16 txctsfrm; /* 0x84 */ -+ u16 txackfrm; /* 0x86 */ -+ u16 txdnlfrm; /* 0x88 */ -+ u16 txbcnfrm; /* 0x8a */ -+ u16 txfunfl[8]; /* 0x8c - 0x9b */ -+ u16 txtplunfl; /* 0x9c */ -+ u16 txphyerr; /* 0x9e */ -+ u16 pktengrxducast; /* 0xa0 */ -+ u16 pktengrxdmcast; /* 0xa2 */ -+ u16 rxfrmtoolong; /* 0xa4 */ -+ u16 rxfrmtooshrt; /* 0xa6 */ -+ u16 rxinvmachdr; /* 0xa8 */ -+ u16 rxbadfcs; /* 0xaa */ -+ u16 rxbadplcp; /* 0xac */ -+ u16 rxcrsglitch; /* 0xae */ -+ u16 rxstrt; /* 0xb0 */ -+ u16 rxdfrmucastmbss; /* 0xb2 */ -+ u16 rxmfrmucastmbss; /* 0xb4 */ -+ u16 rxcfrmucast; /* 0xb6 */ -+ u16 rxrtsucast; /* 0xb8 */ -+ u16 rxctsucast; /* 0xba */ -+ u16 rxackucast; /* 0xbc */ -+ u16 rxdfrmocast; /* 0xbe */ -+ u16 rxmfrmocast; /* 0xc0 */ -+ u16 rxcfrmocast; /* 0xc2 */ -+ u16 rxrtsocast; /* 0xc4 */ -+ u16 rxctsocast; /* 0xc6 */ -+ u16 rxdfrmmcast; /* 0xc8 */ -+ u16 rxmfrmmcast; /* 0xca */ -+ u16 rxcfrmmcast; /* 0xcc */ -+ u16 rxbeaconmbss; /* 0xce */ -+ u16 rxdfrmucastobss; /* 0xd0 */ -+ u16 rxbeaconobss; /* 0xd2 */ -+ u16 rxrsptmout; /* 0xd4 */ -+ u16 bcntxcancl; /* 0xd6 */ -+ u16 PAD; -+ u16 rxf0ovfl; /* 0xda */ -+ u16 rxf1ovfl; /* 0xdc */ -+ u16 rxf2ovfl; /* 0xde */ -+ u16 txsfovfl; /* 0xe0 */ -+ u16 pmqovfl; /* 0xe2 */ -+ u16 rxcgprqfrm; /* 0xe4 */ -+ u16 rxcgprsqovfl; /* 0xe6 */ -+ u16 txcgprsfail; /* 0xe8 */ -+ u16 txcgprssuc; /* 0xea */ -+ u16 prs_timeout; /* 0xec */ -+ u16 rxnack; -+ u16 frmscons; -+ u16 txnack; -+ u16 txglitch_nack; -+ u16 txburst; /* 0xf6 # tx bursts */ -+ u16 bphy_rxcrsglitch; /* bphy rx crs glitch */ -+ u16 phywatchdog; /* 0xfa # of phy watchdog events */ -+ u16 PAD; -+ u16 bphy_badplcp; /* bphy bad plcp */ -+}; -+ -+/* dot11 core-specific control flags */ -+#define SICF_PCLKE 0x0004 /* PHY clock enable */ -+#define SICF_PRST 0x0008 /* PHY reset */ -+#define SICF_MPCLKE 0x0010 /* MAC PHY clockcontrol enable */ -+#define SICF_FREF 0x0020 /* PLL FreqRefSelect */ -+/* NOTE: the following bw bits only apply when the core is attached -+ * to a NPHY -+ */ -+#define SICF_BWMASK 0x00c0 /* phy clock mask (b6 & b7) */ -+#define SICF_BW40 0x0080 /* 40MHz BW (160MHz phyclk) */ -+#define SICF_BW20 0x0040 /* 20MHz BW (80MHz phyclk) */ -+#define SICF_BW10 0x0000 /* 10MHz BW (40MHz phyclk) */ -+#define SICF_GMODE 0x2000 /* gmode enable */ -+ -+/* dot11 core-specific status flags */ -+#define SISF_2G_PHY 0x0001 /* 2.4G capable phy */ -+#define SISF_5G_PHY 0x0002 /* 5G capable phy */ -+#define SISF_FCLKA 0x0004 /* FastClkAvailable */ -+#define SISF_DB_PHY 0x0008 /* Dualband phy */ -+ -+/* === End of MAC reg, Beginning of PHY(b/a/g/n) reg === */ -+/* radio and LPPHY regs are separated */ -+ -+#define BPHY_REG_OFT_BASE 0x0 -+/* offsets for indirect access to bphy registers */ -+#define BPHY_BB_CONFIG 0x01 -+#define BPHY_ADCBIAS 0x02 -+#define BPHY_ANACORE 0x03 -+#define BPHY_PHYCRSTH 0x06 -+#define BPHY_TEST 0x0a -+#define BPHY_PA_TX_TO 0x10 -+#define BPHY_SYNTH_DC_TO 0x11 -+#define BPHY_PA_TX_TIME_UP 0x12 -+#define BPHY_RX_FLTR_TIME_UP 0x13 -+#define BPHY_TX_POWER_OVERRIDE 0x14 -+#define BPHY_RF_OVERRIDE 0x15 -+#define BPHY_RF_TR_LOOKUP1 0x16 -+#define BPHY_RF_TR_LOOKUP2 0x17 -+#define BPHY_COEFFS 0x18 -+#define BPHY_PLL_OUT 0x19 -+#define BPHY_REFRESH_MAIN 0x1a -+#define BPHY_REFRESH_TO0 0x1b -+#define BPHY_REFRESH_TO1 0x1c -+#define BPHY_RSSI_TRESH 0x20 -+#define BPHY_IQ_TRESH_HH 0x21 -+#define BPHY_IQ_TRESH_H 0x22 -+#define BPHY_IQ_TRESH_L 0x23 -+#define BPHY_IQ_TRESH_LL 0x24 -+#define BPHY_GAIN 0x25 -+#define BPHY_LNA_GAIN_RANGE 0x26 -+#define BPHY_JSSI 0x27 -+#define BPHY_TSSI_CTL 0x28 -+#define BPHY_TSSI 0x29 -+#define BPHY_TR_LOSS_CTL 0x2a -+#define BPHY_LO_LEAKAGE 0x2b -+#define BPHY_LO_RSSI_ACC 0x2c -+#define BPHY_LO_IQMAG_ACC 0x2d -+#define BPHY_TX_DC_OFF1 0x2e -+#define BPHY_TX_DC_OFF2 0x2f -+#define BPHY_PEAK_CNT_THRESH 0x30 -+#define BPHY_FREQ_OFFSET 0x31 -+#define BPHY_DIVERSITY_CTL 0x32 -+#define BPHY_PEAK_ENERGY_LO 0x33 -+#define BPHY_PEAK_ENERGY_HI 0x34 -+#define BPHY_SYNC_CTL 0x35 -+#define BPHY_TX_PWR_CTRL 0x36 -+#define BPHY_TX_EST_PWR 0x37 -+#define BPHY_STEP 0x38 -+#define BPHY_WARMUP 0x39 -+#define BPHY_LMS_CFF_READ 0x3a -+#define BPHY_LMS_COEFF_I 0x3b -+#define BPHY_LMS_COEFF_Q 0x3c -+#define BPHY_SIG_POW 0x3d -+#define BPHY_RFDC_CANCEL_CTL 0x3e -+#define BPHY_HDR_TYPE 0x40 -+#define BPHY_SFD_TO 0x41 -+#define BPHY_SFD_CTL 0x42 -+#define BPHY_DEBUG 0x43 -+#define BPHY_RX_DELAY_COMP 0x44 -+#define BPHY_CRS_DROP_TO 0x45 -+#define BPHY_SHORT_SFD_NZEROS 0x46 -+#define BPHY_DSSS_COEFF1 0x48 -+#define BPHY_DSSS_COEFF2 0x49 -+#define BPHY_CCK_COEFF1 0x4a -+#define BPHY_CCK_COEFF2 0x4b -+#define BPHY_TR_CORR 0x4c -+#define BPHY_ANGLE_SCALE 0x4d -+#define BPHY_TX_PWR_BASE_IDX 0x4e -+#define BPHY_OPTIONAL_MODES2 0x4f -+#define BPHY_CCK_LMS_STEP 0x50 -+#define BPHY_BYPASS 0x51 -+#define BPHY_CCK_DELAY_LONG 0x52 -+#define BPHY_CCK_DELAY_SHORT 0x53 -+#define BPHY_PPROC_CHAN_DELAY 0x54 -+#define BPHY_DDFS_ENABLE 0x58 -+#define BPHY_PHASE_SCALE 0x59 -+#define BPHY_FREQ_CONTROL 0x5a -+#define BPHY_LNA_GAIN_RANGE_10 0x5b -+#define BPHY_LNA_GAIN_RANGE_32 0x5c -+#define BPHY_OPTIONAL_MODES 0x5d -+#define BPHY_RX_STATUS2 0x5e -+#define BPHY_RX_STATUS3 0x5f -+#define BPHY_DAC_CONTROL 0x60 -+#define BPHY_ANA11G_FILT_CTRL 0x62 -+#define BPHY_REFRESH_CTRL 0x64 -+#define BPHY_RF_OVERRIDE2 0x65 -+#define BPHY_SPUR_CANCEL_CTRL 0x66 -+#define BPHY_FINE_DIGIGAIN_CTRL 0x67 -+#define BPHY_RSSI_LUT 0x88 -+#define BPHY_RSSI_LUT_END 0xa7 -+#define BPHY_TSSI_LUT 0xa8 -+#define BPHY_TSSI_LUT_END 0xc7 -+#define BPHY_TSSI2PWR_LUT 0x380 -+#define BPHY_TSSI2PWR_LUT_END 0x39f -+#define BPHY_LOCOMP_LUT 0x3a0 -+#define BPHY_LOCOMP_LUT_END 0x3bf -+#define BPHY_TXGAIN_LUT 0x3c0 -+#define BPHY_TXGAIN_LUT_END 0x3ff -+ -+/* Bits in BB_CONFIG: */ -+#define PHY_BBC_ANT_MASK 0x0180 -+#define PHY_BBC_ANT_SHIFT 7 -+#define BB_DARWIN 0x1000 -+#define BBCFG_RESETCCA 0x4000 -+#define BBCFG_RESETRX 0x8000 -+ -+/* Bits in phytest(0x0a): */ -+#define TST_DDFS 0x2000 -+#define TST_TXFILT1 0x0800 -+#define TST_UNSCRAM 0x0400 -+#define TST_CARR_SUPP 0x0200 -+#define TST_DC_COMP_LOOP 0x0100 -+#define TST_LOOPBACK 0x0080 -+#define TST_TXFILT0 0x0040 -+#define TST_TXTEST_ENABLE 0x0020 -+#define TST_TXTEST_RATE 0x0018 -+#define TST_TXTEST_PHASE 0x0007 -+ -+/* phytest txTestRate values */ -+#define TST_TXTEST_RATE_1MBPS 0 -+#define TST_TXTEST_RATE_2MBPS 1 -+#define TST_TXTEST_RATE_5_5MBPS 2 -+#define TST_TXTEST_RATE_11MBPS 3 -+#define TST_TXTEST_RATE_SHIFT 3 -+ -+#define SHM_BYT_CNT 0x2 /* IHR location */ -+#define MAX_BYT_CNT 0x600 /* Maximum frame len */ -+ -+struct d11cnt { -+ u32 txfrag; -+ u32 txmulti; -+ u32 txfail; -+ u32 txretry; -+ u32 txretrie; -+ u32 rxdup; -+ u32 txrts; -+ u32 txnocts; -+ u32 txnoack; -+ u32 rxfrag; -+ u32 rxmulti; -+ u32 rxcrc; -+ u32 txfrmsnt; -+ u32 rxundec; -+}; -+ -+#endif /* _BRCM_D11_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.c.orig 2011-11-09 13:46:58.244800645 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.c 2011-11-09 13:47:16.997566205 -0500 -@@ -0,0 +1,1425 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include "types.h" -+#include "dma.h" -+ -+/* -+ * DMA hardware requires each descriptor ring to be 8kB aligned, and fit within -+ * a contiguous 8kB physical address. -+ */ -+#define D64RINGALIGN_BITS 13 -+#define D64MAXRINGSZ (1 << D64RINGALIGN_BITS) -+#define D64RINGALIGN (1 << D64RINGALIGN_BITS) -+ -+#define D64MAXDD (D64MAXRINGSZ / sizeof(struct dma64desc)) -+ -+/* transmit channel control */ -+#define D64_XC_XE 0x00000001 /* transmit enable */ -+#define D64_XC_SE 0x00000002 /* transmit suspend request */ -+#define D64_XC_LE 0x00000004 /* loopback enable */ -+#define D64_XC_FL 0x00000010 /* flush request */ -+#define D64_XC_PD 0x00000800 /* parity check disable */ -+#define D64_XC_AE 0x00030000 /* address extension bits */ -+#define D64_XC_AE_SHIFT 16 -+ -+/* transmit descriptor table pointer */ -+#define D64_XP_LD_MASK 0x00000fff /* last valid descriptor */ -+ -+/* transmit channel status */ -+#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */ -+#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */ -+#define D64_XS0_XS_SHIFT 28 -+#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */ -+#define D64_XS0_XS_ACTIVE 0x10000000 /* active */ -+#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */ -+#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */ -+#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */ -+ -+#define D64_XS1_AD_MASK 0x00001fff /* active descriptor */ -+#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */ -+#define D64_XS1_XE_SHIFT 28 -+#define D64_XS1_XE_NOERR 0x00000000 /* no error */ -+#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */ -+#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */ -+#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */ -+#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */ -+#define D64_XS1_XE_COREE 0x50000000 /* core error */ -+ -+/* receive channel control */ -+/* receive enable */ -+#define D64_RC_RE 0x00000001 -+/* receive frame offset */ -+#define D64_RC_RO_MASK 0x000000fe -+#define D64_RC_RO_SHIFT 1 -+/* direct fifo receive (pio) mode */ -+#define D64_RC_FM 0x00000100 -+/* separate rx header descriptor enable */ -+#define D64_RC_SH 0x00000200 -+/* overflow continue */ -+#define D64_RC_OC 0x00000400 -+/* parity check disable */ -+#define D64_RC_PD 0x00000800 -+/* address extension bits */ -+#define D64_RC_AE 0x00030000 -+#define D64_RC_AE_SHIFT 16 -+ -+/* flags for dma controller */ -+/* partity enable */ -+#define DMA_CTRL_PEN (1 << 0) -+/* rx overflow continue */ -+#define DMA_CTRL_ROC (1 << 1) -+/* allow rx scatter to multiple descriptors */ -+#define DMA_CTRL_RXMULTI (1 << 2) -+/* Unframed Rx/Tx data */ -+#define DMA_CTRL_UNFRAMED (1 << 3) -+ -+/* receive descriptor table pointer */ -+#define D64_RP_LD_MASK 0x00000fff /* last valid descriptor */ -+ -+/* receive channel status */ -+#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */ -+#define D64_RS0_RS_MASK 0xf0000000 /* receive state */ -+#define D64_RS0_RS_SHIFT 28 -+#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */ -+#define D64_RS0_RS_ACTIVE 0x10000000 /* active */ -+#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */ -+#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */ -+#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */ -+ -+#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */ -+#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */ -+#define D64_RS1_RE_SHIFT 28 -+#define D64_RS1_RE_NOERR 0x00000000 /* no error */ -+#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */ -+#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */ -+#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */ -+#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */ -+#define D64_RS1_RE_COREE 0x50000000 /* core error */ -+ -+/* fifoaddr */ -+#define D64_FA_OFF_MASK 0xffff /* offset */ -+#define D64_FA_SEL_MASK 0xf0000 /* select */ -+#define D64_FA_SEL_SHIFT 16 -+#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */ -+#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */ -+#define D64_FA_SEL_RDD 0x40000 /* receive dma data */ -+#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */ -+#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */ -+#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */ -+#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */ -+#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */ -+#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */ -+#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */ -+ -+/* descriptor control flags 1 */ -+#define D64_CTRL_COREFLAGS 0x0ff00000 /* core specific flags */ -+#define D64_CTRL1_EOT ((u32)1 << 28) /* end of descriptor table */ -+#define D64_CTRL1_IOC ((u32)1 << 29) /* interrupt on completion */ -+#define D64_CTRL1_EOF ((u32)1 << 30) /* end of frame */ -+#define D64_CTRL1_SOF ((u32)1 << 31) /* start of frame */ -+ -+/* descriptor control flags 2 */ -+/* buffer byte count. real data len must <= 16KB */ -+#define D64_CTRL2_BC_MASK 0x00007fff -+/* address extension bits */ -+#define D64_CTRL2_AE 0x00030000 -+#define D64_CTRL2_AE_SHIFT 16 -+/* parity bit */ -+#define D64_CTRL2_PARITY 0x00040000 -+ -+/* control flags in the range [27:20] are core-specific and not defined here */ -+#define D64_CTRL_CORE_MASK 0x0ff00000 -+ -+#define D64_RX_FRM_STS_LEN 0x0000ffff /* frame length mask */ -+#define D64_RX_FRM_STS_OVFL 0x00800000 /* RxOverFlow */ -+#define D64_RX_FRM_STS_DSCRCNT 0x0f000000 /* no. of descriptors used - 1 */ -+#define D64_RX_FRM_STS_DATATYPE 0xf0000000 /* core-dependent data type */ -+ -+/* -+ * packet headroom necessary to accommodate the largest header -+ * in the system, (i.e TXOFF). By doing, we avoid the need to -+ * allocate an extra buffer for the header when bridging to WL. -+ * There is a compile time check in wlc.c which ensure that this -+ * value is at least as big as TXOFF. This value is used in -+ * dma_rxfill(). -+ */ -+ -+#define BCMEXTRAHDROOM 172 -+ -+/* debug/trace */ -+#ifdef BCMDBG -+#define DMA_ERROR(args) \ -+ do { \ -+ if (!(*di->msg_level & 1)) \ -+ ; \ -+ else \ -+ printk args; \ -+ } while (0) -+#define DMA_TRACE(args) \ -+ do { \ -+ if (!(*di->msg_level & 2)) \ -+ ; \ -+ else \ -+ printk args; \ -+ } while (0) -+#else -+#define DMA_ERROR(args) -+#define DMA_TRACE(args) -+#endif /* BCMDBG */ -+ -+#define DMA_NONE(args) -+ -+#define MAXNAMEL 8 /* 8 char names */ -+ -+/* macros to convert between byte offsets and indexes */ -+#define B2I(bytes, type) ((bytes) / sizeof(type)) -+#define I2B(index, type) ((index) * sizeof(type)) -+ -+#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */ -+#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */ -+ -+#define PCI64ADDR_HIGH 0x80000000 /* address[63] */ -+#define PCI64ADDR_HIGH_SHIFT 31 /* address[63] */ -+ -+/* -+ * DMA Descriptor -+ * Descriptors are only read by the hardware, never written back. -+ */ -+struct dma64desc { -+ __le32 ctrl1; /* misc control bits & bufcount */ -+ __le32 ctrl2; /* buffer count and address extension */ -+ __le32 addrlow; /* memory address of the date buffer, bits 31:0 */ -+ __le32 addrhigh; /* memory address of the date buffer, bits 63:32 */ -+}; -+ -+/* dma engine software state */ -+struct dma_info { -+ struct dma_pub dma; /* exported structure */ -+ uint *msg_level; /* message level pointer */ -+ char name[MAXNAMEL]; /* callers name for diag msgs */ -+ -+ struct pci_dev *pbus; /* bus handle */ -+ -+ bool dma64; /* this dma engine is operating in 64-bit mode */ -+ bool addrext; /* this dma engine supports DmaExtendedAddrChanges */ -+ -+ /* 64-bit dma tx engine registers */ -+ struct dma64regs __iomem *d64txregs; -+ /* 64-bit dma rx engine registers */ -+ struct dma64regs __iomem *d64rxregs; -+ /* pointer to dma64 tx descriptor ring */ -+ struct dma64desc *txd64; -+ /* pointer to dma64 rx descriptor ring */ -+ struct dma64desc *rxd64; -+ -+ u16 dmadesc_align; /* alignment requirement for dma descriptors */ -+ -+ u16 ntxd; /* # tx descriptors tunable */ -+ u16 txin; /* index of next descriptor to reclaim */ -+ u16 txout; /* index of next descriptor to post */ -+ /* pointer to parallel array of pointers to packets */ -+ struct sk_buff **txp; -+ /* Aligned physical address of descriptor ring */ -+ dma_addr_t txdpa; -+ /* Original physical address of descriptor ring */ -+ dma_addr_t txdpaorig; -+ u16 txdalign; /* #bytes added to alloc'd mem to align txd */ -+ u32 txdalloc; /* #bytes allocated for the ring */ -+ u32 xmtptrbase; /* When using unaligned descriptors, the ptr register -+ * is not just an index, it needs all 13 bits to be -+ * an offset from the addr register. -+ */ -+ -+ u16 nrxd; /* # rx descriptors tunable */ -+ u16 rxin; /* index of next descriptor to reclaim */ -+ u16 rxout; /* index of next descriptor to post */ -+ /* pointer to parallel array of pointers to packets */ -+ struct sk_buff **rxp; -+ /* Aligned physical address of descriptor ring */ -+ dma_addr_t rxdpa; -+ /* Original physical address of descriptor ring */ -+ dma_addr_t rxdpaorig; -+ u16 rxdalign; /* #bytes added to alloc'd mem to align rxd */ -+ u32 rxdalloc; /* #bytes allocated for the ring */ -+ u32 rcvptrbase; /* Base for ptr reg when using unaligned descriptors */ -+ -+ /* tunables */ -+ unsigned int rxbufsize; /* rx buffer size in bytes, not including -+ * the extra headroom -+ */ -+ uint rxextrahdrroom; /* extra rx headroom, reverseved to assist upper -+ * stack, e.g. some rx pkt buffers will be -+ * bridged to tx side without byte copying. -+ * The extra headroom needs to be large enough -+ * to fit txheader needs. Some dongle driver may -+ * not need it. -+ */ -+ uint nrxpost; /* # rx buffers to keep posted */ -+ unsigned int rxoffset; /* rxcontrol offset */ -+ /* add to get dma address of descriptor ring, low 32 bits */ -+ uint ddoffsetlow; -+ /* high 32 bits */ -+ uint ddoffsethigh; -+ /* add to get dma address of data buffer, low 32 bits */ -+ uint dataoffsetlow; -+ /* high 32 bits */ -+ uint dataoffsethigh; -+ /* descriptor base need to be aligned or not */ -+ bool aligndesc_4k; -+}; -+ -+/* -+ * default dma message level (if input msg_level -+ * pointer is null in dma_attach()) -+ */ -+static uint dma_msg_level; -+ -+/* Check for odd number of 1's */ -+static u32 parity32(__le32 data) -+{ -+ /* no swap needed for counting 1's */ -+ u32 par_data = *(u32 *)&data; -+ -+ par_data ^= par_data >> 16; -+ par_data ^= par_data >> 8; -+ par_data ^= par_data >> 4; -+ par_data ^= par_data >> 2; -+ par_data ^= par_data >> 1; -+ -+ return par_data & 1; -+} -+ -+static bool dma64_dd_parity(struct dma64desc *dd) -+{ -+ return parity32(dd->addrlow ^ dd->addrhigh ^ dd->ctrl1 ^ dd->ctrl2); -+} -+ -+/* descriptor bumping functions */ -+ -+static uint xxd(uint x, uint n) -+{ -+ return x & (n - 1); /* faster than %, but n must be power of 2 */ -+} -+ -+static uint txd(struct dma_info *di, uint x) -+{ -+ return xxd(x, di->ntxd); -+} -+ -+static uint rxd(struct dma_info *di, uint x) -+{ -+ return xxd(x, di->nrxd); -+} -+ -+static uint nexttxd(struct dma_info *di, uint i) -+{ -+ return txd(di, i + 1); -+} -+ -+static uint prevtxd(struct dma_info *di, uint i) -+{ -+ return txd(di, i - 1); -+} -+ -+static uint nextrxd(struct dma_info *di, uint i) -+{ -+ return txd(di, i + 1); -+} -+ -+static uint ntxdactive(struct dma_info *di, uint h, uint t) -+{ -+ return txd(di, t-h); -+} -+ -+static uint nrxdactive(struct dma_info *di, uint h, uint t) -+{ -+ return rxd(di, t-h); -+} -+ -+static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags) -+{ -+ uint dmactrlflags = di->dma.dmactrlflags; -+ -+ if (di == NULL) { -+ DMA_ERROR(("%s: _dma_ctrlflags: NULL dma handle\n", di->name)); -+ return 0; -+ } -+ -+ dmactrlflags &= ~mask; -+ dmactrlflags |= flags; -+ -+ /* If trying to enable parity, check if parity is actually supported */ -+ if (dmactrlflags & DMA_CTRL_PEN) { -+ u32 control; -+ -+ control = R_REG(&di->d64txregs->control); -+ W_REG(&di->d64txregs->control, -+ control | D64_XC_PD); -+ if (R_REG(&di->d64txregs->control) & D64_XC_PD) -+ /* We *can* disable it so it is supported, -+ * restore control register -+ */ -+ W_REG(&di->d64txregs->control, -+ control); -+ else -+ /* Not supported, don't allow it to be enabled */ -+ dmactrlflags &= ~DMA_CTRL_PEN; -+ } -+ -+ di->dma.dmactrlflags = dmactrlflags; -+ -+ return dmactrlflags; -+} -+ -+static bool _dma64_addrext(struct dma64regs __iomem *dma64regs) -+{ -+ u32 w; -+ OR_REG(&dma64regs->control, D64_XC_AE); -+ w = R_REG(&dma64regs->control); -+ AND_REG(&dma64regs->control, ~D64_XC_AE); -+ return (w & D64_XC_AE) == D64_XC_AE; -+} -+ -+/* -+ * return true if this dma engine supports DmaExtendedAddrChanges, -+ * otherwise false -+ */ -+static bool _dma_isaddrext(struct dma_info *di) -+{ -+ /* DMA64 supports full 32- or 64-bit operation. AE is always valid */ -+ -+ /* not all tx or rx channel are available */ -+ if (di->d64txregs != NULL) { -+ if (!_dma64_addrext(di->d64txregs)) -+ DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have " -+ "AE set\n", di->name)); -+ return true; -+ } else if (di->d64rxregs != NULL) { -+ if (!_dma64_addrext(di->d64rxregs)) -+ DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have " -+ "AE set\n", di->name)); -+ return true; -+ } -+ -+ return false; -+} -+ -+static bool _dma_descriptor_align(struct dma_info *di) -+{ -+ u32 addrl; -+ -+ /* Check to see if the descriptors need to be aligned on 4K/8K or not */ -+ if (di->d64txregs != NULL) { -+ W_REG(&di->d64txregs->addrlow, 0xff0); -+ addrl = R_REG(&di->d64txregs->addrlow); -+ if (addrl != 0) -+ return false; -+ } else if (di->d64rxregs != NULL) { -+ W_REG(&di->d64rxregs->addrlow, 0xff0); -+ addrl = R_REG(&di->d64rxregs->addrlow); -+ if (addrl != 0) -+ return false; -+ } -+ return true; -+} -+ -+/* -+ * Descriptor table must start at the DMA hardware dictated alignment, so -+ * allocated memory must be large enough to support this requirement. -+ */ -+static void *dma_alloc_consistent(struct pci_dev *pdev, uint size, -+ u16 align_bits, uint *alloced, -+ dma_addr_t *pap) -+{ -+ if (align_bits) { -+ u16 align = (1 << align_bits); -+ if (!IS_ALIGNED(PAGE_SIZE, align)) -+ size += align; -+ *alloced = size; -+ } -+ return pci_alloc_consistent(pdev, size, pap); -+} -+ -+static -+u8 dma_align_sizetobits(uint size) -+{ -+ u8 bitpos = 0; -+ while (size >>= 1) -+ bitpos++; -+ return bitpos; -+} -+ -+/* This function ensures that the DMA descriptor ring will not get allocated -+ * across Page boundary. If the allocation is done across the page boundary -+ * at the first time, then it is freed and the allocation is done at -+ * descriptor ring size aligned location. This will ensure that the ring will -+ * not cross page boundary -+ */ -+static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size, -+ u16 *alignbits, uint *alloced, -+ dma_addr_t *descpa) -+{ -+ void *va; -+ u32 desc_strtaddr; -+ u32 alignbytes = 1 << *alignbits; -+ -+ va = dma_alloc_consistent(di->pbus, size, *alignbits, alloced, descpa); -+ -+ if (NULL == va) -+ return NULL; -+ -+ desc_strtaddr = (u32) roundup((unsigned long)va, alignbytes); -+ if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr -+ & boundary)) { -+ *alignbits = dma_align_sizetobits(size); -+ pci_free_consistent(di->pbus, size, va, *descpa); -+ va = dma_alloc_consistent(di->pbus, size, *alignbits, -+ alloced, descpa); -+ } -+ return va; -+} -+ -+static bool dma64_alloc(struct dma_info *di, uint direction) -+{ -+ u16 size; -+ uint ddlen; -+ void *va; -+ uint alloced = 0; -+ u16 align; -+ u16 align_bits; -+ -+ ddlen = sizeof(struct dma64desc); -+ -+ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); -+ align_bits = di->dmadesc_align; -+ align = (1 << align_bits); -+ -+ if (direction == DMA_TX) { -+ va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits, -+ &alloced, &di->txdpaorig); -+ if (va == NULL) { -+ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd)" -+ " failed\n", di->name)); -+ return false; -+ } -+ align = (1 << align_bits); -+ di->txd64 = (struct dma64desc *) -+ roundup((unsigned long)va, align); -+ di->txdalign = (uint) ((s8 *)di->txd64 - (s8 *) va); -+ di->txdpa = di->txdpaorig + di->txdalign; -+ di->txdalloc = alloced; -+ } else { -+ va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits, -+ &alloced, &di->rxdpaorig); -+ if (va == NULL) { -+ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd)" -+ " failed\n", di->name)); -+ return false; -+ } -+ align = (1 << align_bits); -+ di->rxd64 = (struct dma64desc *) -+ roundup((unsigned long)va, align); -+ di->rxdalign = (uint) ((s8 *)di->rxd64 - (s8 *) va); -+ di->rxdpa = di->rxdpaorig + di->rxdalign; -+ di->rxdalloc = alloced; -+ } -+ -+ return true; -+} -+ -+static bool _dma_alloc(struct dma_info *di, uint direction) -+{ -+ return dma64_alloc(di, direction); -+} -+ -+struct dma_pub *dma_attach(char *name, struct si_pub *sih, -+ void __iomem *dmaregstx, void __iomem *dmaregsrx, -+ uint ntxd, uint nrxd, -+ uint rxbufsize, int rxextheadroom, -+ uint nrxpost, uint rxoffset, uint *msg_level) -+{ -+ struct dma_info *di; -+ uint size; -+ -+ /* allocate private info structure */ -+ di = kzalloc(sizeof(struct dma_info), GFP_ATOMIC); -+ if (di == NULL) -+ return NULL; -+ -+ di->msg_level = msg_level ? msg_level : &dma_msg_level; -+ -+ -+ di->dma64 = ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64); -+ -+ /* init dma reg pointer */ -+ di->d64txregs = (struct dma64regs __iomem *) dmaregstx; -+ di->d64rxregs = (struct dma64regs __iomem *) dmaregsrx; -+ -+ /* -+ * Default flags (which can be changed by the driver calling -+ * dma_ctrlflags before enable): For backwards compatibility -+ * both Rx Overflow Continue and Parity are DISABLED. -+ */ -+ _dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0); -+ -+ DMA_TRACE(("%s: dma_attach: %s flags 0x%x ntxd %d nrxd %d " -+ "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d " -+ "dmaregstx %p dmaregsrx %p\n", name, "DMA64", -+ di->dma.dmactrlflags, ntxd, nrxd, rxbufsize, -+ rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx)); -+ -+ /* make a private copy of our callers name */ -+ strncpy(di->name, name, MAXNAMEL); -+ di->name[MAXNAMEL - 1] = '\0'; -+ -+ di->pbus = ((struct si_info *)sih)->pbus; -+ -+ /* save tunables */ -+ di->ntxd = (u16) ntxd; -+ di->nrxd = (u16) nrxd; -+ -+ /* the actual dma size doesn't include the extra headroom */ -+ di->rxextrahdrroom = -+ (rxextheadroom == -1) ? BCMEXTRAHDROOM : rxextheadroom; -+ if (rxbufsize > BCMEXTRAHDROOM) -+ di->rxbufsize = (u16) (rxbufsize - di->rxextrahdrroom); -+ else -+ di->rxbufsize = (u16) rxbufsize; -+ -+ di->nrxpost = (u16) nrxpost; -+ di->rxoffset = (u8) rxoffset; -+ -+ /* -+ * figure out the DMA physical address offset for dd and data -+ * PCI/PCIE: they map silicon backplace address to zero -+ * based memory, need offset -+ * Other bus: use zero SI_BUS BIGENDIAN kludge: use sdram -+ * swapped region for data buffer, not descriptor -+ */ -+ di->ddoffsetlow = 0; -+ di->dataoffsetlow = 0; -+ /* add offset for pcie with DMA64 bus */ -+ di->ddoffsetlow = 0; -+ di->ddoffsethigh = SI_PCIE_DMA_H32; -+ di->dataoffsetlow = di->ddoffsetlow; -+ di->dataoffsethigh = di->ddoffsethigh; -+ /* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */ -+ if ((ai_coreid(sih) == SDIOD_CORE_ID) -+ && ((ai_corerev(sih) > 0) && (ai_corerev(sih) <= 2))) -+ di->addrext = 0; -+ else if ((ai_coreid(sih) == I2S_CORE_ID) && -+ ((ai_corerev(sih) == 0) || (ai_corerev(sih) == 1))) -+ di->addrext = 0; -+ else -+ di->addrext = _dma_isaddrext(di); -+ -+ /* does the descriptor need to be aligned and if yes, on 4K/8K or not */ -+ di->aligndesc_4k = _dma_descriptor_align(di); -+ if (di->aligndesc_4k) { -+ di->dmadesc_align = D64RINGALIGN_BITS; -+ if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) -+ /* for smaller dd table, HW relax alignment reqmnt */ -+ di->dmadesc_align = D64RINGALIGN_BITS - 1; -+ } else { -+ di->dmadesc_align = 4; /* 16 byte alignment */ -+ } -+ -+ DMA_NONE(("DMA descriptor align_needed %d, align %d\n", -+ di->aligndesc_4k, di->dmadesc_align)); -+ -+ /* allocate tx packet pointer vector */ -+ if (ntxd) { -+ size = ntxd * sizeof(void *); -+ di->txp = kzalloc(size, GFP_ATOMIC); -+ if (di->txp == NULL) -+ goto fail; -+ } -+ -+ /* allocate rx packet pointer vector */ -+ if (nrxd) { -+ size = nrxd * sizeof(void *); -+ di->rxp = kzalloc(size, GFP_ATOMIC); -+ if (di->rxp == NULL) -+ goto fail; -+ } -+ -+ /* -+ * allocate transmit descriptor ring, only need ntxd descriptors -+ * but it must be aligned -+ */ -+ if (ntxd) { -+ if (!_dma_alloc(di, DMA_TX)) -+ goto fail; -+ } -+ -+ /* -+ * allocate receive descriptor ring, only need nrxd descriptors -+ * but it must be aligned -+ */ -+ if (nrxd) { -+ if (!_dma_alloc(di, DMA_RX)) -+ goto fail; -+ } -+ -+ if ((di->ddoffsetlow != 0) && !di->addrext) { -+ if (di->txdpa > SI_PCI_DMA_SZ) { -+ DMA_ERROR(("%s: dma_attach: txdpa 0x%x: addrext not " -+ "supported\n", di->name, (u32)di->txdpa)); -+ goto fail; -+ } -+ if (di->rxdpa > SI_PCI_DMA_SZ) { -+ DMA_ERROR(("%s: dma_attach: rxdpa 0x%x: addrext not " -+ "supported\n", di->name, (u32)di->rxdpa)); -+ goto fail; -+ } -+ } -+ -+ DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x " -+ "dataoffsethigh " "0x%x addrext %d\n", di->ddoffsetlow, -+ di->ddoffsethigh, di->dataoffsetlow, di->dataoffsethigh, -+ di->addrext)); -+ -+ return (struct dma_pub *) di; -+ -+ fail: -+ dma_detach((struct dma_pub *)di); -+ return NULL; -+} -+ -+static inline void -+dma64_dd_upd(struct dma_info *di, struct dma64desc *ddring, -+ dma_addr_t pa, uint outidx, u32 *flags, u32 bufcount) -+{ -+ u32 ctrl2 = bufcount & D64_CTRL2_BC_MASK; -+ -+ /* PCI bus with big(>1G) physical address, use address extension */ -+ if ((di->dataoffsetlow == 0) || !(pa & PCI32ADDR_HIGH)) { -+ ddring[outidx].addrlow = cpu_to_le32(pa + di->dataoffsetlow); -+ ddring[outidx].addrhigh = cpu_to_le32(di->dataoffsethigh); -+ ddring[outidx].ctrl1 = cpu_to_le32(*flags); -+ ddring[outidx].ctrl2 = cpu_to_le32(ctrl2); -+ } else { -+ /* address extension for 32-bit PCI */ -+ u32 ae; -+ -+ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; -+ pa &= ~PCI32ADDR_HIGH; -+ -+ ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE; -+ ddring[outidx].addrlow = cpu_to_le32(pa + di->dataoffsetlow); -+ ddring[outidx].addrhigh = cpu_to_le32(di->dataoffsethigh); -+ ddring[outidx].ctrl1 = cpu_to_le32(*flags); -+ ddring[outidx].ctrl2 = cpu_to_le32(ctrl2); -+ } -+ if (di->dma.dmactrlflags & DMA_CTRL_PEN) { -+ if (dma64_dd_parity(&ddring[outidx])) -+ ddring[outidx].ctrl2 = -+ cpu_to_le32(ctrl2 | D64_CTRL2_PARITY); -+ } -+} -+ -+/* !! may be called with core in reset */ -+void dma_detach(struct dma_pub *pub) -+{ -+ struct dma_info *di = (struct dma_info *)pub; -+ -+ DMA_TRACE(("%s: dma_detach\n", di->name)); -+ -+ /* free dma descriptor rings */ -+ if (di->txd64) -+ pci_free_consistent(di->pbus, di->txdalloc, -+ ((s8 *)di->txd64 - di->txdalign), -+ (di->txdpaorig)); -+ if (di->rxd64) -+ pci_free_consistent(di->pbus, di->rxdalloc, -+ ((s8 *)di->rxd64 - di->rxdalign), -+ (di->rxdpaorig)); -+ -+ /* free packet pointer vectors */ -+ kfree(di->txp); -+ kfree(di->rxp); -+ -+ /* free our private info structure */ -+ kfree(di); -+ -+} -+ -+/* initialize descriptor table base address */ -+static void -+_dma_ddtable_init(struct dma_info *di, uint direction, dma_addr_t pa) -+{ -+ if (!di->aligndesc_4k) { -+ if (direction == DMA_TX) -+ di->xmtptrbase = pa; -+ else -+ di->rcvptrbase = pa; -+ } -+ -+ if ((di->ddoffsetlow == 0) -+ || !(pa & PCI32ADDR_HIGH)) { -+ if (direction == DMA_TX) { -+ W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow); -+ W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh); -+ } else { -+ W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow); -+ W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh); -+ } -+ } else { -+ /* DMA64 32bits address extension */ -+ u32 ae; -+ -+ /* shift the high bit(s) from pa to ae */ -+ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; -+ pa &= ~PCI32ADDR_HIGH; -+ -+ if (direction == DMA_TX) { -+ W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow); -+ W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh); -+ SET_REG(&di->d64txregs->control, -+ D64_XC_AE, (ae << D64_XC_AE_SHIFT)); -+ } else { -+ W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow); -+ W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh); -+ SET_REG(&di->d64rxregs->control, -+ D64_RC_AE, (ae << D64_RC_AE_SHIFT)); -+ } -+ } -+} -+ -+static void _dma_rxenable(struct dma_info *di) -+{ -+ uint dmactrlflags = di->dma.dmactrlflags; -+ u32 control; -+ -+ DMA_TRACE(("%s: dma_rxenable\n", di->name)); -+ -+ control = -+ (R_REG(&di->d64rxregs->control) & D64_RC_AE) | -+ D64_RC_RE; -+ -+ if ((dmactrlflags & DMA_CTRL_PEN) == 0) -+ control |= D64_RC_PD; -+ -+ if (dmactrlflags & DMA_CTRL_ROC) -+ control |= D64_RC_OC; -+ -+ W_REG(&di->d64rxregs->control, -+ ((di->rxoffset << D64_RC_RO_SHIFT) | control)); -+} -+ -+void dma_rxinit(struct dma_pub *pub) -+{ -+ struct dma_info *di = (struct dma_info *)pub; -+ -+ DMA_TRACE(("%s: dma_rxinit\n", di->name)); -+ -+ if (di->nrxd == 0) -+ return; -+ -+ di->rxin = di->rxout = 0; -+ -+ /* clear rx descriptor ring */ -+ memset(di->rxd64, '\0', di->nrxd * sizeof(struct dma64desc)); -+ -+ /* DMA engine with out alignment requirement requires table to be inited -+ * before enabling the engine -+ */ -+ if (!di->aligndesc_4k) -+ _dma_ddtable_init(di, DMA_RX, di->rxdpa); -+ -+ _dma_rxenable(di); -+ -+ if (di->aligndesc_4k) -+ _dma_ddtable_init(di, DMA_RX, di->rxdpa); -+} -+ -+static struct sk_buff *dma64_getnextrxp(struct dma_info *di, bool forceall) -+{ -+ uint i, curr; -+ struct sk_buff *rxp; -+ dma_addr_t pa; -+ -+ i = di->rxin; -+ -+ /* return if no packets posted */ -+ if (i == di->rxout) -+ return NULL; -+ -+ curr = -+ B2I(((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) - -+ di->rcvptrbase) & D64_RS0_CD_MASK, struct dma64desc); -+ -+ /* ignore curr if forceall */ -+ if (!forceall && (i == curr)) -+ return NULL; -+ -+ /* get the packet pointer that corresponds to the rx descriptor */ -+ rxp = di->rxp[i]; -+ di->rxp[i] = NULL; -+ -+ pa = le32_to_cpu(di->rxd64[i].addrlow) - di->dataoffsetlow; -+ -+ /* clear this packet from the descriptor ring */ -+ pci_unmap_single(di->pbus, pa, di->rxbufsize, PCI_DMA_FROMDEVICE); -+ -+ di->rxd64[i].addrlow = cpu_to_le32(0xdeadbeef); -+ di->rxd64[i].addrhigh = cpu_to_le32(0xdeadbeef); -+ -+ di->rxin = nextrxd(di, i); -+ -+ return rxp; -+} -+ -+static struct sk_buff *_dma_getnextrxp(struct dma_info *di, bool forceall) -+{ -+ if (di->nrxd == 0) -+ return NULL; -+ -+ return dma64_getnextrxp(di, forceall); -+} -+ -+/* -+ * !! rx entry routine -+ * returns a pointer to the next frame received, or NULL if there are no more -+ * if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is -+ * supported with pkts chain -+ * otherwise, it's treated as giant pkt and will be tossed. -+ * The DMA scattering starts with normal DMA header, followed by first -+ * buffer data. After it reaches the max size of buffer, the data continues -+ * in next DMA descriptor buffer WITHOUT DMA header -+ */ -+struct sk_buff *dma_rx(struct dma_pub *pub) -+{ -+ struct dma_info *di = (struct dma_info *)pub; -+ struct sk_buff *p, *head, *tail; -+ uint len; -+ uint pkt_len; -+ int resid = 0; -+ -+ next_frame: -+ head = _dma_getnextrxp(di, false); -+ if (head == NULL) -+ return NULL; -+ -+ len = le16_to_cpu(*(__le16 *) (head->data)); -+ DMA_TRACE(("%s: dma_rx len %d\n", di->name, len)); -+ dma_spin_for_len(len, head); -+ -+ /* set actual length */ -+ pkt_len = min((di->rxoffset + len), di->rxbufsize); -+ __skb_trim(head, pkt_len); -+ resid = len - (di->rxbufsize - di->rxoffset); -+ -+ /* check for single or multi-buffer rx */ -+ if (resid > 0) { -+ tail = head; -+ while ((resid > 0) && (p = _dma_getnextrxp(di, false))) { -+ tail->next = p; -+ pkt_len = min_t(uint, resid, di->rxbufsize); -+ __skb_trim(p, pkt_len); -+ -+ tail = p; -+ resid -= di->rxbufsize; -+ } -+ -+#ifdef BCMDBG -+ if (resid > 0) { -+ uint cur; -+ cur = -+ B2I(((R_REG(&di->d64rxregs->status0) & -+ D64_RS0_CD_MASK) - -+ di->rcvptrbase) & D64_RS0_CD_MASK, -+ struct dma64desc); -+ DMA_ERROR(("dma_rx, rxin %d rxout %d, hw_curr %d\n", -+ di->rxin, di->rxout, cur)); -+ } -+#endif /* BCMDBG */ -+ -+ if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) { -+ DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n", -+ di->name, len)); -+ brcmu_pkt_buf_free_skb(head); -+ di->dma.rxgiants++; -+ goto next_frame; -+ } -+ } -+ -+ return head; -+} -+ -+static bool dma64_rxidle(struct dma_info *di) -+{ -+ DMA_TRACE(("%s: dma_rxidle\n", di->name)); -+ -+ if (di->nrxd == 0) -+ return true; -+ -+ return ((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) == -+ (R_REG(&di->d64rxregs->ptr) & D64_RS0_CD_MASK)); -+} -+ -+/* -+ * post receive buffers -+ * return false is refill failed completely and ring is empty this will stall -+ * the rx dma and user might want to call rxfill again asap. This unlikely -+ * happens on memory-rich NIC, but often on memory-constrained dongle -+ */ -+bool dma_rxfill(struct dma_pub *pub) -+{ -+ struct dma_info *di = (struct dma_info *)pub; -+ struct sk_buff *p; -+ u16 rxin, rxout; -+ u32 flags = 0; -+ uint n; -+ uint i; -+ dma_addr_t pa; -+ uint extra_offset = 0; -+ bool ring_empty; -+ -+ ring_empty = false; -+ -+ /* -+ * Determine how many receive buffers we're lacking -+ * from the full complement, allocate, initialize, -+ * and post them, then update the chip rx lastdscr. -+ */ -+ -+ rxin = di->rxin; -+ rxout = di->rxout; -+ -+ n = di->nrxpost - nrxdactive(di, rxin, rxout); -+ -+ DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n)); -+ -+ if (di->rxbufsize > BCMEXTRAHDROOM) -+ extra_offset = di->rxextrahdrroom; -+ -+ for (i = 0; i < n; i++) { -+ /* -+ * the di->rxbufsize doesn't include the extra headroom, -+ * we need to add it to the size to be allocated -+ */ -+ p = brcmu_pkt_buf_get_skb(di->rxbufsize + extra_offset); -+ -+ if (p == NULL) { -+ DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n", -+ di->name)); -+ if (i == 0 && dma64_rxidle(di)) { -+ DMA_ERROR(("%s: rxfill64: ring is empty !\n", -+ di->name)); -+ ring_empty = true; -+ } -+ di->dma.rxnobuf++; -+ break; -+ } -+ /* reserve an extra headroom, if applicable */ -+ if (extra_offset) -+ skb_pull(p, extra_offset); -+ -+ /* Do a cached write instead of uncached write since DMA_MAP -+ * will flush the cache. -+ */ -+ *(u32 *) (p->data) = 0; -+ -+ pa = pci_map_single(di->pbus, p->data, -+ di->rxbufsize, PCI_DMA_FROMDEVICE); -+ -+ /* save the free packet pointer */ -+ di->rxp[rxout] = p; -+ -+ /* reset flags for each descriptor */ -+ flags = 0; -+ if (rxout == (di->nrxd - 1)) -+ flags = D64_CTRL1_EOT; -+ -+ dma64_dd_upd(di, di->rxd64, pa, rxout, &flags, -+ di->rxbufsize); -+ rxout = nextrxd(di, rxout); -+ } -+ -+ di->rxout = rxout; -+ -+ /* update the chip lastdscr pointer */ -+ W_REG(&di->d64rxregs->ptr, -+ di->rcvptrbase + I2B(rxout, struct dma64desc)); -+ -+ return ring_empty; -+} -+ -+void dma_rxreclaim(struct dma_pub *pub) -+{ -+ struct dma_info *di = (struct dma_info *)pub; -+ struct sk_buff *p; -+ -+ DMA_TRACE(("%s: dma_rxreclaim\n", di->name)); -+ -+ while ((p = _dma_getnextrxp(di, true))) -+ brcmu_pkt_buf_free_skb(p); -+} -+ -+void dma_counterreset(struct dma_pub *pub) -+{ -+ /* reset all software counters */ -+ pub->rxgiants = 0; -+ pub->rxnobuf = 0; -+ pub->txnobuf = 0; -+} -+ -+/* get the address of the var in order to change later */ -+unsigned long dma_getvar(struct dma_pub *pub, const char *name) -+{ -+ struct dma_info *di = (struct dma_info *)pub; -+ -+ if (!strcmp(name, "&txavail")) -+ return (unsigned long)&(di->dma.txavail); -+ return 0; -+} -+ -+/* 64-bit DMA functions */ -+ -+void dma_txinit(struct dma_pub *pub) -+{ -+ struct dma_info *di = (struct dma_info *)pub; -+ u32 control = D64_XC_XE; -+ -+ DMA_TRACE(("%s: dma_txinit\n", di->name)); -+ -+ if (di->ntxd == 0) -+ return; -+ -+ di->txin = di->txout = 0; -+ di->dma.txavail = di->ntxd - 1; -+ -+ /* clear tx descriptor ring */ -+ memset(di->txd64, '\0', (di->ntxd * sizeof(struct dma64desc))); -+ -+ /* DMA engine with out alignment requirement requires table to be inited -+ * before enabling the engine -+ */ -+ if (!di->aligndesc_4k) -+ _dma_ddtable_init(di, DMA_TX, di->txdpa); -+ -+ if ((di->dma.dmactrlflags & DMA_CTRL_PEN) == 0) -+ control |= D64_XC_PD; -+ OR_REG(&di->d64txregs->control, control); -+ -+ /* DMA engine with alignment requirement requires table to be inited -+ * before enabling the engine -+ */ -+ if (di->aligndesc_4k) -+ _dma_ddtable_init(di, DMA_TX, di->txdpa); -+} -+ -+void dma_txsuspend(struct dma_pub *pub) -+{ -+ struct dma_info *di = (struct dma_info *)pub; -+ -+ DMA_TRACE(("%s: dma_txsuspend\n", di->name)); -+ -+ if (di->ntxd == 0) -+ return; -+ -+ OR_REG(&di->d64txregs->control, D64_XC_SE); -+} -+ -+void dma_txresume(struct dma_pub *pub) -+{ -+ struct dma_info *di = (struct dma_info *)pub; -+ -+ DMA_TRACE(("%s: dma_txresume\n", di->name)); -+ -+ if (di->ntxd == 0) -+ return; -+ -+ AND_REG(&di->d64txregs->control, ~D64_XC_SE); -+} -+ -+bool dma_txsuspended(struct dma_pub *pub) -+{ -+ struct dma_info *di = (struct dma_info *)pub; -+ -+ return (di->ntxd == 0) || -+ ((R_REG(&di->d64txregs->control) & D64_XC_SE) == -+ D64_XC_SE); -+} -+ -+void dma_txreclaim(struct dma_pub *pub, enum txd_range range) -+{ -+ struct dma_info *di = (struct dma_info *)pub; -+ struct sk_buff *p; -+ -+ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, -+ (range == DMA_RANGE_ALL) ? "all" : -+ ((range == -+ DMA_RANGE_TRANSMITTED) ? "transmitted" : -+ "transferred"))); -+ -+ if (di->txin == di->txout) -+ return; -+ -+ while ((p = dma_getnexttxp(pub, range))) { -+ /* For unframed data, we don't have any packets to free */ -+ if (!(di->dma.dmactrlflags & DMA_CTRL_UNFRAMED)) -+ brcmu_pkt_buf_free_skb(p); -+ } -+} -+ -+bool dma_txreset(struct dma_pub *pub) -+{ -+ struct dma_info *di = (struct dma_info *)pub; -+ u32 status; -+ -+ if (di->ntxd == 0) -+ return true; -+ -+ /* suspend tx DMA first */ -+ W_REG(&di->d64txregs->control, D64_XC_SE); -+ SPINWAIT(((status = -+ (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK)) -+ != D64_XS0_XS_DISABLED) && (status != D64_XS0_XS_IDLE) -+ && (status != D64_XS0_XS_STOPPED), 10000); -+ -+ W_REG(&di->d64txregs->control, 0); -+ SPINWAIT(((status = -+ (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK)) -+ != D64_XS0_XS_DISABLED), 10000); -+ -+ /* wait for the last transaction to complete */ -+ udelay(300); -+ -+ return status == D64_XS0_XS_DISABLED; -+} -+ -+bool dma_rxreset(struct dma_pub *pub) -+{ -+ struct dma_info *di = (struct dma_info *)pub; -+ u32 status; -+ -+ if (di->nrxd == 0) -+ return true; -+ -+ W_REG(&di->d64rxregs->control, 0); -+ SPINWAIT(((status = -+ (R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK)) -+ != D64_RS0_RS_DISABLED), 10000); -+ -+ return status == D64_RS0_RS_DISABLED; -+} -+ -+/* -+ * !! tx entry routine -+ * WARNING: call must check the return value for error. -+ * the error(toss frames) could be fatal and cause many subsequent hard -+ * to debug problems -+ */ -+int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit) -+{ -+ struct dma_info *di = (struct dma_info *)pub; -+ struct sk_buff *p, *next; -+ unsigned char *data; -+ uint len; -+ u16 txout; -+ u32 flags = 0; -+ dma_addr_t pa; -+ -+ DMA_TRACE(("%s: dma_txfast\n", di->name)); -+ -+ txout = di->txout; -+ -+ /* -+ * Walk the chain of packet buffers -+ * allocating and initializing transmit descriptor entries. -+ */ -+ for (p = p0; p; p = next) { -+ data = p->data; -+ len = p->len; -+ next = p->next; -+ -+ /* return nonzero if out of tx descriptors */ -+ if (nexttxd(di, txout) == di->txin) -+ goto outoftxd; -+ -+ if (len == 0) -+ continue; -+ -+ /* get physical address of buffer start */ -+ pa = pci_map_single(di->pbus, data, len, PCI_DMA_TODEVICE); -+ -+ flags = 0; -+ if (p == p0) -+ flags |= D64_CTRL1_SOF; -+ -+ /* With a DMA segment list, Descriptor table is filled -+ * using the segment list instead of looping over -+ * buffers in multi-chain DMA. Therefore, EOF for SGLIST -+ * is when end of segment list is reached. -+ */ -+ if (next == NULL) -+ flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF); -+ if (txout == (di->ntxd - 1)) -+ flags |= D64_CTRL1_EOT; -+ -+ dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); -+ -+ txout = nexttxd(di, txout); -+ } -+ -+ /* if last txd eof not set, fix it */ -+ if (!(flags & D64_CTRL1_EOF)) -+ di->txd64[prevtxd(di, txout)].ctrl1 = -+ cpu_to_le32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF); -+ -+ /* save the packet */ -+ di->txp[prevtxd(di, txout)] = p0; -+ -+ /* bump the tx descriptor index */ -+ di->txout = txout; -+ -+ /* kick the chip */ -+ if (commit) -+ W_REG(&di->d64txregs->ptr, -+ di->xmtptrbase + I2B(txout, struct dma64desc)); -+ -+ /* tx flow control */ -+ di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1; -+ -+ return 0; -+ -+ outoftxd: -+ DMA_ERROR(("%s: dma_txfast: out of txds !!!\n", di->name)); -+ brcmu_pkt_buf_free_skb(p0); -+ di->dma.txavail = 0; -+ di->dma.txnobuf++; -+ return -1; -+} -+ -+/* -+ * Reclaim next completed txd (txds if using chained buffers) in the range -+ * specified and return associated packet. -+ * If range is DMA_RANGE_TRANSMITTED, reclaim descriptors that have be -+ * transmitted as noted by the hardware "CurrDescr" pointer. -+ * If range is DMA_RANGE_TRANSFERED, reclaim descriptors that have be -+ * transferred by the DMA as noted by the hardware "ActiveDescr" pointer. -+ * If range is DMA_RANGE_ALL, reclaim all txd(s) posted to the ring and -+ * return associated packet regardless of the value of hardware pointers. -+ */ -+struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range) -+{ -+ struct dma_info *di = (struct dma_info *)pub; -+ u16 start, end, i; -+ u16 active_desc; -+ struct sk_buff *txp; -+ -+ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, -+ (range == DMA_RANGE_ALL) ? "all" : -+ ((range == -+ DMA_RANGE_TRANSMITTED) ? "transmitted" : -+ "transferred"))); -+ -+ if (di->ntxd == 0) -+ return NULL; -+ -+ txp = NULL; -+ -+ start = di->txin; -+ if (range == DMA_RANGE_ALL) -+ end = di->txout; -+ else { -+ struct dma64regs __iomem *dregs = di->d64txregs; -+ -+ end = (u16) (B2I(((R_REG(&dregs->status0) & -+ D64_XS0_CD_MASK) - -+ di->xmtptrbase) & D64_XS0_CD_MASK, -+ struct dma64desc)); -+ -+ if (range == DMA_RANGE_TRANSFERED) { -+ active_desc = -+ (u16) (R_REG(&dregs->status1) & -+ D64_XS1_AD_MASK); -+ active_desc = -+ (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK; -+ active_desc = B2I(active_desc, struct dma64desc); -+ if (end != active_desc) -+ end = prevtxd(di, active_desc); -+ } -+ } -+ -+ if ((start == 0) && (end > di->txout)) -+ goto bogus; -+ -+ for (i = start; i != end && !txp; i = nexttxd(di, i)) { -+ dma_addr_t pa; -+ uint size; -+ -+ pa = le32_to_cpu(di->txd64[i].addrlow) - di->dataoffsetlow; -+ -+ size = -+ (le32_to_cpu(di->txd64[i].ctrl2) & -+ D64_CTRL2_BC_MASK); -+ -+ di->txd64[i].addrlow = cpu_to_le32(0xdeadbeef); -+ di->txd64[i].addrhigh = cpu_to_le32(0xdeadbeef); -+ -+ txp = di->txp[i]; -+ di->txp[i] = NULL; -+ -+ pci_unmap_single(di->pbus, pa, size, PCI_DMA_TODEVICE); -+ } -+ -+ di->txin = i; -+ -+ /* tx flow control */ -+ di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1; -+ -+ return txp; -+ -+ bogus: -+ DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d " -+ "force %d\n", start, end, di->txout, forceall)); -+ return NULL; -+} -+ -+/* -+ * Mac80211 initiated actions sometimes require packets in the DMA queue to be -+ * modified. The modified portion of the packet is not under control of the DMA -+ * engine. This function calls a caller-supplied function for each packet in -+ * the caller specified dma chain. -+ */ -+void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc) -+ (void *pkt, void *arg_a), void *arg_a) -+{ -+ struct dma_info *di = (struct dma_info *) dmah; -+ uint i = di->txin; -+ uint end = di->txout; -+ struct sk_buff *skb; -+ struct ieee80211_tx_info *tx_info; -+ -+ while (i != end) { -+ skb = (struct sk_buff *)di->txp[i]; -+ if (skb != NULL) { -+ tx_info = (struct ieee80211_tx_info *)skb->cb; -+ (callback_fnc)(tx_info, arg_a); -+ } -+ i = nexttxd(di, i); -+ } -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.h.orig 2011-11-09 13:46:58.244800645 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.h 2011-11-09 13:47:16.997566205 -0500 -@@ -0,0 +1,120 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_DMA_H_ -+#define _BRCM_DMA_H_ -+ -+#include -+#include "types.h" /* forward structure declarations */ -+ -+/* map/unmap direction */ -+#define DMA_TX 1 /* TX direction for DMA */ -+#define DMA_RX 2 /* RX direction for DMA */ -+ -+/* DMA structure: -+ * support two DMA engines: 32 bits address or 64 bit addressing -+ * basic DMA register set is per channel(transmit or receive) -+ * a pair of channels is defined for convenience -+ */ -+ -+/* 32 bits addressing */ -+ -+struct dma32diag { /* diag access */ -+ u32 fifoaddr; /* diag address */ -+ u32 fifodatalow; /* low 32bits of data */ -+ u32 fifodatahigh; /* high 32bits of data */ -+ u32 pad; /* reserved */ -+}; -+ -+/* 64 bits addressing */ -+ -+/* dma registers per channel(xmt or rcv) */ -+struct dma64regs { -+ u32 control; /* enable, et al */ -+ u32 ptr; /* last descriptor posted to chip */ -+ u32 addrlow; /* desc ring base address low 32-bits (8K aligned) */ -+ u32 addrhigh; /* desc ring base address bits 63:32 (8K aligned) */ -+ u32 status0; /* current descriptor, xmt state */ -+ u32 status1; /* active descriptor, xmt error */ -+}; -+ -+/* range param for dma_getnexttxp() and dma_txreclaim */ -+enum txd_range { -+ DMA_RANGE_ALL = 1, -+ DMA_RANGE_TRANSMITTED, -+ DMA_RANGE_TRANSFERED -+}; -+ -+/* -+ * Exported data structure (read-only) -+ */ -+/* export structure */ -+struct dma_pub { -+ uint txavail; /* # free tx descriptors */ -+ uint dmactrlflags; /* dma control flags */ -+ -+ /* rx error counters */ -+ uint rxgiants; /* rx giant frames */ -+ uint rxnobuf; /* rx out of dma descriptors */ -+ /* tx error counters */ -+ uint txnobuf; /* tx out of dma descriptors */ -+}; -+ -+extern struct dma_pub *dma_attach(char *name, struct si_pub *sih, -+ void __iomem *dmaregstx, void __iomem *dmaregsrx, -+ uint ntxd, uint nrxd, -+ uint rxbufsize, int rxextheadroom, -+ uint nrxpost, uint rxoffset, uint *msg_level); -+ -+void dma_rxinit(struct dma_pub *pub); -+struct sk_buff *dma_rx(struct dma_pub *pub); -+bool dma_rxfill(struct dma_pub *pub); -+bool dma_rxreset(struct dma_pub *pub); -+bool dma_txreset(struct dma_pub *pub); -+void dma_txinit(struct dma_pub *pub); -+int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit); -+void dma_txsuspend(struct dma_pub *pub); -+bool dma_txsuspended(struct dma_pub *pub); -+void dma_txresume(struct dma_pub *pub); -+void dma_txreclaim(struct dma_pub *pub, enum txd_range range); -+void dma_rxreclaim(struct dma_pub *pub); -+void dma_detach(struct dma_pub *pub); -+unsigned long dma_getvar(struct dma_pub *pub, const char *name); -+struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range); -+void dma_counterreset(struct dma_pub *pub); -+ -+void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc) -+ (void *pkt, void *arg_a), void *arg_a); -+ -+/* -+ * DMA(Bug) on bcm47xx chips seems to declare that the packet is ready, but -+ * the packet length is not updated yet (by DMA) on the expected time. -+ * Workaround is to hold processor till DMA updates the length, and stay off -+ * the bus to allow DMA update the length in buffer -+ */ -+static inline void dma_spin_for_len(uint len, struct sk_buff *head) -+{ -+#if defined(CONFIG_BCM47XX) -+ if (!len) { -+ while (!(len = *(u16 *) KSEG1ADDR(head->data))) -+ udelay(1); -+ -+ *(u16 *) (head->data) = cpu_to_le16((u16) len); -+ } -+#endif /* defined(CONFIG_BCM47XX) */ -+} -+ -+#endif /* _BRCM_DMA_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c.orig 2011-11-09 13:46:58.245800633 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c 2011-11-09 13:47:16.998566192 -0500 -@@ -0,0 +1,1697 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#define __UNDEF_NO_VERSION__ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "nicpci.h" -+#include "phy/phy_int.h" -+#include "d11.h" -+#include "channel.h" -+#include "scb.h" -+#include "pub.h" -+#include "ucode_loader.h" -+#include "mac80211_if.h" -+#include "main.h" -+ -+#define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ -+ -+/* Flags we support */ -+#define MAC_FILTERS (FIF_PROMISC_IN_BSS | \ -+ FIF_ALLMULTI | \ -+ FIF_FCSFAIL | \ -+ FIF_PLCPFAIL | \ -+ FIF_CONTROL | \ -+ FIF_OTHER_BSS | \ -+ FIF_BCN_PRBRESP_PROMISC) -+ -+#define CHAN2GHZ(channel, freqency, chflags) { \ -+ .band = IEEE80211_BAND_2GHZ, \ -+ .center_freq = (freqency), \ -+ .hw_value = (channel), \ -+ .flags = chflags, \ -+ .max_antenna_gain = 0, \ -+ .max_power = 19, \ -+} -+ -+#define CHAN5GHZ(channel, chflags) { \ -+ .band = IEEE80211_BAND_5GHZ, \ -+ .center_freq = 5000 + 5*(channel), \ -+ .hw_value = (channel), \ -+ .flags = chflags, \ -+ .max_antenna_gain = 0, \ -+ .max_power = 21, \ -+} -+ -+#define RATE(rate100m, _flags) { \ -+ .bitrate = (rate100m), \ -+ .flags = (_flags), \ -+ .hw_value = (rate100m / 5), \ -+} -+ -+struct firmware_hdr { -+ __le32 offset; -+ __le32 len; -+ __le32 idx; -+}; -+ -+static const char * const brcms_firmwares[MAX_FW_IMAGES] = { -+ "brcm/bcm43xx", -+ NULL -+}; -+ -+static int n_adapters_found; -+ -+MODULE_AUTHOR("Broadcom Corporation"); -+MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver."); -+MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards"); -+MODULE_LICENSE("Dual BSD/GPL"); -+ -+/* recognized PCI IDs */ -+static DEFINE_PCI_DEVICE_TABLE(brcms_pci_id_table) = { -+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, /* 43225 2G */ -+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, /* 43224 DUAL */ -+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, /* 4313 DUAL */ -+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, /* 43224 Ven */ -+ {0} -+}; -+ -+MODULE_DEVICE_TABLE(pci, brcms_pci_id_table); -+ -+#ifdef BCMDBG -+static int msglevel = 0xdeadbeef; -+module_param(msglevel, int, 0); -+#endif /* BCMDBG */ -+ -+static struct ieee80211_channel brcms_2ghz_chantable[] = { -+ CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS), -+ CHAN2GHZ(2, 2417, IEEE80211_CHAN_NO_HT40MINUS), -+ CHAN2GHZ(3, 2422, IEEE80211_CHAN_NO_HT40MINUS), -+ CHAN2GHZ(4, 2427, IEEE80211_CHAN_NO_HT40MINUS), -+ CHAN2GHZ(5, 2432, 0), -+ CHAN2GHZ(6, 2437, 0), -+ CHAN2GHZ(7, 2442, 0), -+ CHAN2GHZ(8, 2447, IEEE80211_CHAN_NO_HT40PLUS), -+ CHAN2GHZ(9, 2452, IEEE80211_CHAN_NO_HT40PLUS), -+ CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS), -+ CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS), -+ CHAN2GHZ(12, 2467, -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_NO_HT40PLUS), -+ CHAN2GHZ(13, 2472, -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_NO_HT40PLUS), -+ CHAN2GHZ(14, 2484, -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) -+}; -+ -+static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = { -+ /* UNII-1 */ -+ CHAN5GHZ(36, IEEE80211_CHAN_NO_HT40MINUS), -+ CHAN5GHZ(40, IEEE80211_CHAN_NO_HT40PLUS), -+ CHAN5GHZ(44, IEEE80211_CHAN_NO_HT40MINUS), -+ CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS), -+ /* UNII-2 */ -+ CHAN5GHZ(52, -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), -+ CHAN5GHZ(56, -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), -+ CHAN5GHZ(60, -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), -+ CHAN5GHZ(64, -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), -+ /* MID */ -+ CHAN5GHZ(100, -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), -+ CHAN5GHZ(104, -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), -+ CHAN5GHZ(108, -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), -+ CHAN5GHZ(112, -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), -+ CHAN5GHZ(116, -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), -+ CHAN5GHZ(120, -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), -+ CHAN5GHZ(124, -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), -+ CHAN5GHZ(128, -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), -+ CHAN5GHZ(132, -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), -+ CHAN5GHZ(136, -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), -+ CHAN5GHZ(140, -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS | -+ IEEE80211_CHAN_NO_HT40MINUS), -+ /* UNII-3 */ -+ CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS), -+ CHAN5GHZ(153, IEEE80211_CHAN_NO_HT40PLUS), -+ CHAN5GHZ(157, IEEE80211_CHAN_NO_HT40MINUS), -+ CHAN5GHZ(161, IEEE80211_CHAN_NO_HT40PLUS), -+ CHAN5GHZ(165, IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) -+}; -+ -+/* -+ * The rate table is used for both 2.4G and 5G rates. The -+ * latter being a subset as it does not support CCK rates. -+ */ -+static struct ieee80211_rate legacy_ratetable[] = { -+ RATE(10, 0), -+ RATE(20, IEEE80211_RATE_SHORT_PREAMBLE), -+ RATE(55, IEEE80211_RATE_SHORT_PREAMBLE), -+ RATE(110, IEEE80211_RATE_SHORT_PREAMBLE), -+ RATE(60, 0), -+ RATE(90, 0), -+ RATE(120, 0), -+ RATE(180, 0), -+ RATE(240, 0), -+ RATE(360, 0), -+ RATE(480, 0), -+ RATE(540, 0), -+}; -+ -+static const struct ieee80211_supported_band brcms_band_2GHz_nphy_template = { -+ .band = IEEE80211_BAND_2GHZ, -+ .channels = brcms_2ghz_chantable, -+ .n_channels = ARRAY_SIZE(brcms_2ghz_chantable), -+ .bitrates = legacy_ratetable, -+ .n_bitrates = ARRAY_SIZE(legacy_ratetable), -+ .ht_cap = { -+ /* from include/linux/ieee80211.h */ -+ .cap = IEEE80211_HT_CAP_GRN_FLD | -+ IEEE80211_HT_CAP_SGI_20 | -+ IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT, -+ .ht_supported = true, -+ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, -+ .ampdu_density = AMPDU_DEF_MPDU_DENSITY, -+ .mcs = { -+ /* placeholders for now */ -+ .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}, -+ .rx_highest = cpu_to_le16(500), -+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED} -+ } -+}; -+ -+static const struct ieee80211_supported_band brcms_band_5GHz_nphy_template = { -+ .band = IEEE80211_BAND_5GHZ, -+ .channels = brcms_5ghz_nphy_chantable, -+ .n_channels = ARRAY_SIZE(brcms_5ghz_nphy_chantable), -+ .bitrates = legacy_ratetable + BRCMS_LEGACY_5G_RATE_OFFSET, -+ .n_bitrates = ARRAY_SIZE(legacy_ratetable) - -+ BRCMS_LEGACY_5G_RATE_OFFSET, -+ .ht_cap = { -+ .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | -+ IEEE80211_HT_CAP_SGI_40 | -+ IEEE80211_HT_CAP_40MHZ_INTOLERANT, /* No 40 mhz yet */ -+ .ht_supported = true, -+ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, -+ .ampdu_density = AMPDU_DEF_MPDU_DENSITY, -+ .mcs = { -+ /* placeholders for now */ -+ .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}, -+ .rx_highest = cpu_to_le16(500), -+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED} -+ } -+}; -+ -+/* flags the given rate in rateset as requested */ -+static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br) -+{ -+ u32 i; -+ -+ for (i = 0; i < rs->count; i++) { -+ if (rate != (rs->rates[i] & 0x7f)) -+ continue; -+ -+ if (is_br) -+ rs->rates[i] |= BRCMS_RATE_FLAG; -+ else -+ rs->rates[i] &= BRCMS_RATE_MASK; -+ return; -+ } -+} -+ -+static void brcms_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -+{ -+ struct brcms_info *wl = hw->priv; -+ -+ spin_lock_bh(&wl->lock); -+ if (!wl->pub->up) { -+ wiphy_err(wl->wiphy, "ops->tx called while down\n"); -+ kfree_skb(skb); -+ goto done; -+ } -+ brcms_c_sendpkt_mac80211(wl->wlc, skb, hw); -+ done: -+ spin_unlock_bh(&wl->lock); -+} -+ -+static int brcms_ops_start(struct ieee80211_hw *hw) -+{ -+ struct brcms_info *wl = hw->priv; -+ bool blocked; -+ -+ ieee80211_wake_queues(hw); -+ spin_lock_bh(&wl->lock); -+ blocked = brcms_rfkill_set_hw_state(wl); -+ spin_unlock_bh(&wl->lock); -+ if (!blocked) -+ wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); -+ -+ return 0; -+} -+ -+static void brcms_ops_stop(struct ieee80211_hw *hw) -+{ -+ ieee80211_stop_queues(hw); -+} -+ -+static int -+brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -+{ -+ struct brcms_info *wl; -+ int err; -+ -+ /* Just STA for now */ -+ if (vif->type != NL80211_IFTYPE_AP && -+ vif->type != NL80211_IFTYPE_MESH_POINT && -+ vif->type != NL80211_IFTYPE_STATION && -+ vif->type != NL80211_IFTYPE_WDS && -+ vif->type != NL80211_IFTYPE_ADHOC) { -+ wiphy_err(hw->wiphy, "%s: Attempt to add type %d, only" -+ " STA for now\n", __func__, vif->type); -+ return -EOPNOTSUPP; -+ } -+ -+ wl = hw->priv; -+ spin_lock_bh(&wl->lock); -+ if (!wl->pub->up) -+ err = brcms_up(wl); -+ else -+ err = -ENODEV; -+ spin_unlock_bh(&wl->lock); -+ -+ if (err != 0) -+ wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__, -+ err); -+ -+ return err; -+} -+ -+static void -+brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -+{ -+ struct brcms_info *wl; -+ -+ wl = hw->priv; -+ -+ /* put driver in down state */ -+ spin_lock_bh(&wl->lock); -+ brcms_down(wl); -+ spin_unlock_bh(&wl->lock); -+} -+ -+static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed) -+{ -+ struct ieee80211_conf *conf = &hw->conf; -+ struct brcms_info *wl = hw->priv; -+ int err = 0; -+ int new_int; -+ struct wiphy *wiphy = hw->wiphy; -+ -+ spin_lock_bh(&wl->lock); -+ if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { -+ brcms_c_set_beacon_listen_interval(wl->wlc, -+ conf->listen_interval); -+ } -+ if (changed & IEEE80211_CONF_CHANGE_MONITOR) -+ wiphy_err(wiphy, "%s: change monitor mode: %s (implement)\n", -+ __func__, conf->flags & IEEE80211_CONF_MONITOR ? -+ "true" : "false"); -+ if (changed & IEEE80211_CONF_CHANGE_PS) -+ wiphy_err(wiphy, "%s: change power-save mode: %s (implement)\n", -+ __func__, conf->flags & IEEE80211_CONF_PS ? -+ "true" : "false"); -+ -+ if (changed & IEEE80211_CONF_CHANGE_POWER) { -+ err = brcms_c_set_tx_power(wl->wlc, conf->power_level); -+ if (err < 0) { -+ wiphy_err(wiphy, "%s: Error setting power_level\n", -+ __func__); -+ goto config_out; -+ } -+ new_int = brcms_c_get_tx_power(wl->wlc); -+ if (new_int != conf->power_level) -+ wiphy_err(wiphy, "%s: Power level req != actual, %d %d" -+ "\n", __func__, conf->power_level, -+ new_int); -+ } -+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { -+ if (conf->channel_type == NL80211_CHAN_HT20 || -+ conf->channel_type == NL80211_CHAN_NO_HT) -+ err = brcms_c_set_channel(wl->wlc, -+ conf->channel->hw_value); -+ else -+ err = -ENOTSUPP; -+ } -+ if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) -+ err = brcms_c_set_rate_limit(wl->wlc, -+ conf->short_frame_max_tx_count, -+ conf->long_frame_max_tx_count); -+ -+ config_out: -+ spin_unlock_bh(&wl->lock); -+ return err; -+} -+ -+static void -+brcms_ops_bss_info_changed(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ struct ieee80211_bss_conf *info, u32 changed) -+{ -+ struct brcms_info *wl = hw->priv; -+ struct wiphy *wiphy = hw->wiphy; -+ -+ if (changed & BSS_CHANGED_ASSOC) { -+ /* association status changed (associated/disassociated) -+ * also implies a change in the AID. -+ */ -+ wiphy_err(wiphy, "%s: %s: %sassociated\n", KBUILD_MODNAME, -+ __func__, info->assoc ? "" : "dis"); -+ spin_lock_bh(&wl->lock); -+ brcms_c_associate_upd(wl->wlc, info->assoc); -+ spin_unlock_bh(&wl->lock); -+ } -+ if (changed & BSS_CHANGED_ERP_SLOT) { -+ s8 val; -+ -+ /* slot timing changed */ -+ if (info->use_short_slot) -+ val = 1; -+ else -+ val = 0; -+ spin_lock_bh(&wl->lock); -+ brcms_c_set_shortslot_override(wl->wlc, val); -+ spin_unlock_bh(&wl->lock); -+ } -+ -+ if (changed & BSS_CHANGED_HT) { -+ /* 802.11n parameters changed */ -+ u16 mode = info->ht_operation_mode; -+ -+ spin_lock_bh(&wl->lock); -+ brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_CFG, -+ mode & IEEE80211_HT_OP_MODE_PROTECTION); -+ brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_NONGF, -+ mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); -+ brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_OBSS, -+ mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT); -+ spin_unlock_bh(&wl->lock); -+ } -+ if (changed & BSS_CHANGED_BASIC_RATES) { -+ struct ieee80211_supported_band *bi; -+ u32 br_mask, i; -+ u16 rate; -+ struct brcm_rateset rs; -+ int error; -+ -+ /* retrieve the current rates */ -+ spin_lock_bh(&wl->lock); -+ brcms_c_get_current_rateset(wl->wlc, &rs); -+ spin_unlock_bh(&wl->lock); -+ -+ br_mask = info->basic_rates; -+ bi = hw->wiphy->bands[brcms_c_get_curband(wl->wlc)]; -+ for (i = 0; i < bi->n_bitrates; i++) { -+ /* convert to internal rate value */ -+ rate = (bi->bitrates[i].bitrate << 1) / 10; -+ -+ /* set/clear basic rate flag */ -+ brcms_set_basic_rate(&rs, rate, br_mask & 1); -+ br_mask >>= 1; -+ } -+ -+ /* update the rate set */ -+ spin_lock_bh(&wl->lock); -+ error = brcms_c_set_rateset(wl->wlc, &rs); -+ spin_unlock_bh(&wl->lock); -+ if (error) -+ wiphy_err(wiphy, "changing basic rates failed: %d\n", -+ error); -+ } -+ if (changed & BSS_CHANGED_BEACON_INT) { -+ /* Beacon interval changed */ -+ spin_lock_bh(&wl->lock); -+ brcms_c_set_beacon_period(wl->wlc, info->beacon_int); -+ spin_unlock_bh(&wl->lock); -+ } -+ if (changed & BSS_CHANGED_BSSID) { -+ /* BSSID changed, for whatever reason (IBSS and managed mode) */ -+ spin_lock_bh(&wl->lock); -+ brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid); -+ spin_unlock_bh(&wl->lock); -+ } -+ if (changed & BSS_CHANGED_BEACON) -+ /* Beacon data changed, retrieve new beacon (beaconing modes) */ -+ wiphy_err(wiphy, "%s: beacon changed\n", __func__); -+ -+ if (changed & BSS_CHANGED_BEACON_ENABLED) { -+ /* Beaconing should be enabled/disabled (beaconing modes) */ -+ wiphy_err(wiphy, "%s: Beacon enabled: %s\n", __func__, -+ info->enable_beacon ? "true" : "false"); -+ } -+ -+ if (changed & BSS_CHANGED_CQM) { -+ /* Connection quality monitor config changed */ -+ wiphy_err(wiphy, "%s: cqm change: threshold %d, hys %d " -+ " (implement)\n", __func__, info->cqm_rssi_thold, -+ info->cqm_rssi_hyst); -+ } -+ -+ if (changed & BSS_CHANGED_IBSS) { -+ /* IBSS join status changed */ -+ wiphy_err(wiphy, "%s: IBSS joined: %s (implement)\n", __func__, -+ info->ibss_joined ? "true" : "false"); -+ } -+ -+ if (changed & BSS_CHANGED_ARP_FILTER) { -+ /* Hardware ARP filter address list or state changed */ -+ wiphy_err(wiphy, "%s: arp filtering: enabled %s, count %d" -+ " (implement)\n", __func__, info->arp_filter_enabled ? -+ "true" : "false", info->arp_addr_cnt); -+ } -+ -+ if (changed & BSS_CHANGED_QOS) { -+ /* -+ * QoS for this association was enabled/disabled. -+ * Note that it is only ever disabled for station mode. -+ */ -+ wiphy_err(wiphy, "%s: qos enabled: %s (implement)\n", __func__, -+ info->qos ? "true" : "false"); -+ } -+ return; -+} -+ -+static void -+brcms_ops_configure_filter(struct ieee80211_hw *hw, -+ unsigned int changed_flags, -+ unsigned int *total_flags, u64 multicast) -+{ -+ struct brcms_info *wl = hw->priv; -+ struct wiphy *wiphy = hw->wiphy; -+ -+ changed_flags &= MAC_FILTERS; -+ *total_flags &= MAC_FILTERS; -+ if (changed_flags & FIF_PROMISC_IN_BSS) -+ wiphy_err(wiphy, "FIF_PROMISC_IN_BSS\n"); -+ if (changed_flags & FIF_ALLMULTI) -+ wiphy_err(wiphy, "FIF_ALLMULTI\n"); -+ if (changed_flags & FIF_FCSFAIL) -+ wiphy_err(wiphy, "FIF_FCSFAIL\n"); -+ if (changed_flags & FIF_PLCPFAIL) -+ wiphy_err(wiphy, "FIF_PLCPFAIL\n"); -+ if (changed_flags & FIF_CONTROL) -+ wiphy_err(wiphy, "FIF_CONTROL\n"); -+ if (changed_flags & FIF_OTHER_BSS) -+ wiphy_err(wiphy, "FIF_OTHER_BSS\n"); -+ if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { -+ spin_lock_bh(&wl->lock); -+ if (*total_flags & FIF_BCN_PRBRESP_PROMISC) { -+ wl->pub->mac80211_state |= MAC80211_PROMISC_BCNS; -+ brcms_c_mac_bcn_promisc_change(wl->wlc, 1); -+ } else { -+ brcms_c_mac_bcn_promisc_change(wl->wlc, 0); -+ wl->pub->mac80211_state &= ~MAC80211_PROMISC_BCNS; -+ } -+ spin_unlock_bh(&wl->lock); -+ } -+ return; -+} -+ -+static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw) -+{ -+ struct brcms_info *wl = hw->priv; -+ spin_lock_bh(&wl->lock); -+ brcms_c_scan_start(wl->wlc); -+ spin_unlock_bh(&wl->lock); -+ return; -+} -+ -+static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw) -+{ -+ struct brcms_info *wl = hw->priv; -+ spin_lock_bh(&wl->lock); -+ brcms_c_scan_stop(wl->wlc); -+ spin_unlock_bh(&wl->lock); -+ return; -+} -+ -+static int -+brcms_ops_conf_tx(struct ieee80211_hw *hw, u16 queue, -+ const struct ieee80211_tx_queue_params *params) -+{ -+ struct brcms_info *wl = hw->priv; -+ -+ spin_lock_bh(&wl->lock); -+ brcms_c_wme_setparams(wl->wlc, queue, params, true); -+ spin_unlock_bh(&wl->lock); -+ -+ return 0; -+} -+ -+static int -+brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, -+ struct ieee80211_sta *sta) -+{ -+ struct brcms_info *wl = hw->priv; -+ struct scb *scb = &wl->wlc->pri_scb; -+ -+ brcms_c_init_scb(scb); -+ -+ wl->pub->global_ampdu = &(scb->scb_ampdu); -+ wl->pub->global_ampdu->scb = scb; -+ wl->pub->global_ampdu->max_pdu = 16; -+ -+ sta->ht_cap.ht_supported = true; -+ sta->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; -+ sta->ht_cap.ampdu_density = AMPDU_DEF_MPDU_DENSITY; -+ sta->ht_cap.cap = IEEE80211_HT_CAP_GRN_FLD | -+ IEEE80211_HT_CAP_SGI_20 | -+ IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT; -+ -+ /* -+ * minstrel_ht initiates addBA on our behalf by calling -+ * ieee80211_start_tx_ba_session() -+ */ -+ return 0; -+} -+ -+static int -+brcms_ops_ampdu_action(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ enum ieee80211_ampdu_mlme_action action, -+ struct ieee80211_sta *sta, u16 tid, u16 *ssn, -+ u8 buf_size) -+{ -+ struct brcms_info *wl = hw->priv; -+ struct scb *scb = &wl->wlc->pri_scb; -+ int status; -+ -+ if (WARN_ON(scb->magic != SCB_MAGIC)) -+ return -EIDRM; -+ switch (action) { -+ case IEEE80211_AMPDU_RX_START: -+ break; -+ case IEEE80211_AMPDU_RX_STOP: -+ break; -+ case IEEE80211_AMPDU_TX_START: -+ spin_lock_bh(&wl->lock); -+ status = brcms_c_aggregatable(wl->wlc, tid); -+ spin_unlock_bh(&wl->lock); -+ if (!status) { -+ wiphy_err(wl->wiphy, "START: tid %d is not agg\'able\n", -+ tid); -+ return -EINVAL; -+ } -+ ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); -+ break; -+ -+ case IEEE80211_AMPDU_TX_STOP: -+ spin_lock_bh(&wl->lock); -+ brcms_c_ampdu_flush(wl->wlc, sta, tid); -+ spin_unlock_bh(&wl->lock); -+ ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); -+ break; -+ case IEEE80211_AMPDU_TX_OPERATIONAL: -+ /* -+ * BA window size from ADDBA response ('buf_size') defines how -+ * many outstanding MPDUs are allowed for the BA stream by -+ * recipient and traffic class. 'ampdu_factor' gives maximum -+ * AMPDU size. -+ */ -+ spin_lock_bh(&wl->lock); -+ brcms_c_ampdu_tx_operational(wl->wlc, tid, buf_size, -+ (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + -+ sta->ht_cap.ampdu_factor)) - 1); -+ spin_unlock_bh(&wl->lock); -+ /* Power save wakeup */ -+ break; -+ default: -+ wiphy_err(wl->wiphy, "%s: Invalid command, ignoring\n", -+ __func__); -+ } -+ -+ return 0; -+} -+ -+static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw) -+{ -+ struct brcms_info *wl = hw->priv; -+ bool blocked; -+ -+ spin_lock_bh(&wl->lock); -+ blocked = brcms_c_check_radio_disabled(wl->wlc); -+ spin_unlock_bh(&wl->lock); -+ -+ wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked); -+} -+ -+static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop) -+{ -+ struct brcms_info *wl = hw->priv; -+ -+ no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false"); -+ -+ /* wait for packet queue and dma fifos to run empty */ -+ spin_lock_bh(&wl->lock); -+ brcms_c_wait_for_tx_completion(wl->wlc, drop); -+ spin_unlock_bh(&wl->lock); -+} -+ -+static const struct ieee80211_ops brcms_ops = { -+ .tx = brcms_ops_tx, -+ .start = brcms_ops_start, -+ .stop = brcms_ops_stop, -+ .add_interface = brcms_ops_add_interface, -+ .remove_interface = brcms_ops_remove_interface, -+ .config = brcms_ops_config, -+ .bss_info_changed = brcms_ops_bss_info_changed, -+ .configure_filter = brcms_ops_configure_filter, -+ .sw_scan_start = brcms_ops_sw_scan_start, -+ .sw_scan_complete = brcms_ops_sw_scan_complete, -+ .conf_tx = brcms_ops_conf_tx, -+ .sta_add = brcms_ops_sta_add, -+ .ampdu_action = brcms_ops_ampdu_action, -+ .rfkill_poll = brcms_ops_rfkill_poll, -+ .flush = brcms_ops_flush, -+}; -+ -+/* -+ * is called in brcms_pci_probe() context, therefore no locking required. -+ */ -+static int brcms_set_hint(struct brcms_info *wl, char *abbrev) -+{ -+ return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev); -+} -+ -+void brcms_dpc(unsigned long data) -+{ -+ struct brcms_info *wl; -+ -+ wl = (struct brcms_info *) data; -+ -+ spin_lock_bh(&wl->lock); -+ -+ /* call the common second level interrupt handler */ -+ if (wl->pub->up) { -+ if (wl->resched) { -+ unsigned long flags; -+ -+ spin_lock_irqsave(&wl->isr_lock, flags); -+ brcms_c_intrsupd(wl->wlc); -+ spin_unlock_irqrestore(&wl->isr_lock, flags); -+ } -+ -+ wl->resched = brcms_c_dpc(wl->wlc, true); -+ } -+ -+ /* brcms_c_dpc() may bring the driver down */ -+ if (!wl->pub->up) -+ goto done; -+ -+ /* re-schedule dpc */ -+ if (wl->resched) -+ tasklet_schedule(&wl->tasklet); -+ else -+ /* re-enable interrupts */ -+ brcms_intrson(wl); -+ -+ done: -+ spin_unlock_bh(&wl->lock); -+} -+ -+/* -+ * Precondition: Since this function is called in brcms_pci_probe() context, -+ * no locking is required. -+ */ -+static int brcms_request_fw(struct brcms_info *wl, struct pci_dev *pdev) -+{ -+ int status; -+ struct device *device = &pdev->dev; -+ char fw_name[100]; -+ int i; -+ -+ memset(&wl->fw, 0, sizeof(struct brcms_firmware)); -+ for (i = 0; i < MAX_FW_IMAGES; i++) { -+ if (brcms_firmwares[i] == NULL) -+ break; -+ sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i], -+ UCODE_LOADER_API_VER); -+ status = request_firmware(&wl->fw.fw_bin[i], fw_name, device); -+ if (status) { -+ wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n", -+ KBUILD_MODNAME, fw_name); -+ return status; -+ } -+ sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i], -+ UCODE_LOADER_API_VER); -+ status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device); -+ if (status) { -+ wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n", -+ KBUILD_MODNAME, fw_name); -+ return status; -+ } -+ wl->fw.hdr_num_entries[i] = -+ wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr)); -+ } -+ wl->fw.fw_cnt = i; -+ return brcms_ucode_data_init(wl, &wl->ucode); -+} -+ -+/* -+ * Precondition: Since this function is called in brcms_pci_probe() context, -+ * no locking is required. -+ */ -+static void brcms_release_fw(struct brcms_info *wl) -+{ -+ int i; -+ for (i = 0; i < MAX_FW_IMAGES; i++) { -+ release_firmware(wl->fw.fw_bin[i]); -+ release_firmware(wl->fw.fw_hdr[i]); -+ } -+} -+ -+/** -+ * This function frees the WL per-device resources. -+ * -+ * This function frees resources owned by the WL device pointed to -+ * by the wl parameter. -+ * -+ * precondition: can both be called locked and unlocked -+ * -+ */ -+static void brcms_free(struct brcms_info *wl) -+{ -+ struct brcms_timer *t, *next; -+ -+ /* free ucode data */ -+ if (wl->fw.fw_cnt) -+ brcms_ucode_data_free(&wl->ucode); -+ if (wl->irq) -+ free_irq(wl->irq, wl); -+ -+ /* kill dpc */ -+ tasklet_kill(&wl->tasklet); -+ -+ if (wl->pub) -+ brcms_c_module_unregister(wl->pub, "linux", wl); -+ -+ /* free common resources */ -+ if (wl->wlc) { -+ brcms_c_detach(wl->wlc); -+ wl->wlc = NULL; -+ wl->pub = NULL; -+ } -+ -+ /* virtual interface deletion is deferred so we cannot spinwait */ -+ -+ /* wait for all pending callbacks to complete */ -+ while (atomic_read(&wl->callbacks) > 0) -+ schedule(); -+ -+ /* free timers */ -+ for (t = wl->timers; t; t = next) { -+ next = t->next; -+#ifdef BCMDBG -+ kfree(t->name); -+#endif -+ kfree(t); -+ } -+ -+ /* -+ * unregister_netdev() calls get_stats() which may read chip -+ * registers so we cannot unmap the chip registers until -+ * after calling unregister_netdev() . -+ */ -+ if (wl->regsva) -+ iounmap(wl->regsva); -+ -+ wl->regsva = NULL; -+} -+ -+/* -+* called from both kernel as from this kernel module. -+* precondition: perimeter lock is not acquired. -+*/ -+static void brcms_remove(struct pci_dev *pdev) -+{ -+ struct brcms_info *wl; -+ struct ieee80211_hw *hw; -+ int status; -+ -+ hw = pci_get_drvdata(pdev); -+ wl = hw->priv; -+ if (!wl) { -+ pr_err("wl: brcms_remove: pci_get_drvdata failed\n"); -+ return; -+ } -+ -+ spin_lock_bh(&wl->lock); -+ status = brcms_c_chipmatch(pdev->vendor, pdev->device); -+ spin_unlock_bh(&wl->lock); -+ if (!status) { -+ wiphy_err(wl->wiphy, "wl: brcms_remove: chipmatch " -+ "failed\n"); -+ return; -+ } -+ if (wl->wlc) { -+ wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); -+ wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); -+ ieee80211_unregister_hw(hw); -+ spin_lock_bh(&wl->lock); -+ brcms_down(wl); -+ spin_unlock_bh(&wl->lock); -+ } -+ pci_disable_device(pdev); -+ -+ brcms_free(wl); -+ -+ pci_set_drvdata(pdev, NULL); -+ ieee80211_free_hw(hw); -+} -+ -+static irqreturn_t brcms_isr(int irq, void *dev_id) -+{ -+ struct brcms_info *wl; -+ bool ours, wantdpc; -+ -+ wl = (struct brcms_info *) dev_id; -+ -+ spin_lock(&wl->isr_lock); -+ -+ /* call common first level interrupt handler */ -+ ours = brcms_c_isr(wl->wlc, &wantdpc); -+ if (ours) { -+ /* if more to do... */ -+ if (wantdpc) { -+ -+ /* ...and call the second level interrupt handler */ -+ /* schedule dpc */ -+ tasklet_schedule(&wl->tasklet); -+ } -+ } -+ -+ spin_unlock(&wl->isr_lock); -+ -+ return IRQ_RETVAL(ours); -+} -+ -+/* -+ * is called in brcms_pci_probe() context, therefore no locking required. -+ */ -+static int ieee_hw_rate_init(struct ieee80211_hw *hw) -+{ -+ struct brcms_info *wl = hw->priv; -+ struct brcms_c_info *wlc = wl->wlc; -+ struct ieee80211_supported_band *band; -+ int has_5g = 0; -+ u16 phy_type; -+ -+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; -+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; -+ -+ phy_type = brcms_c_get_phy_type(wl->wlc, 0); -+ if (phy_type == PHY_TYPE_N || phy_type == PHY_TYPE_LCN) { -+ band = &wlc->bandstate[BAND_2G_INDEX]->band; -+ *band = brcms_band_2GHz_nphy_template; -+ if (phy_type == PHY_TYPE_LCN) { -+ /* Single stream */ -+ band->ht_cap.mcs.rx_mask[1] = 0; -+ band->ht_cap.mcs.rx_highest = cpu_to_le16(72); -+ } -+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band; -+ } else { -+ return -EPERM; -+ } -+ -+ /* Assume all bands use the same phy. True for 11n devices. */ -+ if (wl->pub->_nbands > 1) { -+ has_5g++; -+ if (phy_type == PHY_TYPE_N || phy_type == PHY_TYPE_LCN) { -+ band = &wlc->bandstate[BAND_5G_INDEX]->band; -+ *band = brcms_band_5GHz_nphy_template; -+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band; -+ } else { -+ return -EPERM; -+ } -+ } -+ return 0; -+} -+ -+/* -+ * is called in brcms_pci_probe() context, therefore no locking required. -+ */ -+static int ieee_hw_init(struct ieee80211_hw *hw) -+{ -+ hw->flags = IEEE80211_HW_SIGNAL_DBM -+ /* | IEEE80211_HW_CONNECTION_MONITOR What is this? */ -+ | IEEE80211_HW_REPORTS_TX_ACK_STATUS -+ | IEEE80211_HW_AMPDU_AGGREGATION; -+ -+ hw->extra_tx_headroom = brcms_c_get_header_len(); -+ hw->queues = N_TX_QUEUES; -+ hw->max_rates = 2; /* Primary rate and 1 fallback rate */ -+ -+ /* channel change time is dependent on chip and band */ -+ hw->channel_change_time = 7 * 1000; -+ hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); -+ -+ hw->rate_control_algorithm = "minstrel_ht"; -+ -+ hw->sta_data_size = 0; -+ return ieee_hw_rate_init(hw); -+} -+ -+/** -+ * attach to the WL device. -+ * -+ * Attach to the WL device identified by vendor and device parameters. -+ * regs is a host accessible memory address pointing to WL device registers. -+ * -+ * brcms_attach is not defined as static because in the case where no bus -+ * is defined, wl_attach will never be called, and thus, gcc will issue -+ * a warning that this function is defined but not used if we declare -+ * it as static. -+ * -+ * -+ * is called in brcms_pci_probe() context, therefore no locking required. -+ */ -+static struct brcms_info *brcms_attach(u16 vendor, u16 device, -+ resource_size_t regs, -+ struct pci_dev *btparam, uint irq) -+{ -+ struct brcms_info *wl = NULL; -+ int unit, err; -+ struct ieee80211_hw *hw; -+ u8 perm[ETH_ALEN]; -+ -+ unit = n_adapters_found; -+ err = 0; -+ -+ if (unit < 0) -+ return NULL; -+ -+ /* allocate private info */ -+ hw = pci_get_drvdata(btparam); /* btparam == pdev */ -+ if (hw != NULL) -+ wl = hw->priv; -+ if (WARN_ON(hw == NULL) || WARN_ON(wl == NULL)) -+ return NULL; -+ wl->wiphy = hw->wiphy; -+ -+ atomic_set(&wl->callbacks, 0); -+ -+ /* setup the bottom half handler */ -+ tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl); -+ -+ wl->regsva = ioremap_nocache(regs, PCI_BAR0_WINSZ); -+ if (wl->regsva == NULL) { -+ wiphy_err(wl->wiphy, "wl%d: ioremap() failed\n", unit); -+ goto fail; -+ } -+ spin_lock_init(&wl->lock); -+ spin_lock_init(&wl->isr_lock); -+ -+ /* prepare ucode */ -+ if (brcms_request_fw(wl, btparam) < 0) { -+ wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in " -+ "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm"); -+ brcms_release_fw(wl); -+ brcms_remove(btparam); -+ return NULL; -+ } -+ -+ /* common load-time initialization */ -+ wl->wlc = brcms_c_attach(wl, vendor, device, unit, false, -+ wl->regsva, btparam, &err); -+ brcms_release_fw(wl); -+ if (!wl->wlc) { -+ wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n", -+ KBUILD_MODNAME, err); -+ goto fail; -+ } -+ wl->pub = brcms_c_pub(wl->wlc); -+ -+ wl->pub->ieee_hw = hw; -+ -+ /* disable mpc */ -+ brcms_c_set_radio_mpc(wl->wlc, false); -+ -+ /* register our interrupt handler */ -+ if (request_irq(irq, brcms_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) { -+ wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit); -+ goto fail; -+ } -+ wl->irq = irq; -+ -+ /* register module */ -+ brcms_c_module_register(wl->pub, "linux", wl, NULL); -+ -+ if (ieee_hw_init(hw)) { -+ wiphy_err(wl->wiphy, "wl%d: %s: ieee_hw_init failed!\n", unit, -+ __func__); -+ goto fail; -+ } -+ -+ memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN); -+ if (WARN_ON(!is_valid_ether_addr(perm))) -+ goto fail; -+ SET_IEEE80211_PERM_ADDR(hw, perm); -+ -+ err = ieee80211_register_hw(hw); -+ if (err) -+ wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status" -+ "%d\n", __func__, err); -+ -+ if (wl->pub->srom_ccode[0]) -+ err = brcms_set_hint(wl, wl->pub->srom_ccode); -+ else -+ err = brcms_set_hint(wl, "US"); -+ if (err) -+ wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n", -+ __func__, err); -+ -+ n_adapters_found++; -+ return wl; -+ -+fail: -+ brcms_free(wl); -+ return NULL; -+} -+ -+ -+ -+/** -+ * determines if a device is a WL device, and if so, attaches it. -+ * -+ * This function determines if a device pointed to by pdev is a WL device, -+ * and if so, performs a brcms_attach() on it. -+ * -+ * Perimeter lock is initialized in the course of this function. -+ */ -+static int __devinit -+brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -+{ -+ int rc; -+ struct brcms_info *wl; -+ struct ieee80211_hw *hw; -+ u32 val; -+ -+ dev_info(&pdev->dev, "bus %d slot %d func %d irq %d\n", -+ pdev->bus->number, PCI_SLOT(pdev->devfn), -+ PCI_FUNC(pdev->devfn), pdev->irq); -+ -+ if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) || -+ ((pdev->device != 0x0576) && -+ ((pdev->device & 0xff00) != 0x4300) && -+ ((pdev->device & 0xff00) != 0x4700) && -+ ((pdev->device < 43000) || (pdev->device > 43999)))) -+ return -ENODEV; -+ -+ rc = pci_enable_device(pdev); -+ if (rc) { -+ pr_err("%s: Cannot enable device %d-%d_%d\n", -+ __func__, pdev->bus->number, PCI_SLOT(pdev->devfn), -+ PCI_FUNC(pdev->devfn)); -+ return -ENODEV; -+ } -+ pci_set_master(pdev); -+ -+ pci_read_config_dword(pdev, 0x40, &val); -+ if ((val & 0x0000ff00) != 0) -+ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); -+ -+ hw = ieee80211_alloc_hw(sizeof(struct brcms_info), &brcms_ops); -+ if (!hw) { -+ pr_err("%s: ieee80211_alloc_hw failed\n", __func__); -+ return -ENOMEM; -+ } -+ -+ SET_IEEE80211_DEV(hw, &pdev->dev); -+ -+ pci_set_drvdata(pdev, hw); -+ -+ memset(hw->priv, 0, sizeof(*wl)); -+ -+ wl = brcms_attach(pdev->vendor, pdev->device, -+ pci_resource_start(pdev, 0), pdev, -+ pdev->irq); -+ -+ if (!wl) { -+ pr_err("%s: %s: brcms_attach failed!\n", KBUILD_MODNAME, -+ __func__); -+ return -ENODEV; -+ } -+ return 0; -+} -+ -+static int brcms_suspend(struct pci_dev *pdev, pm_message_t state) -+{ -+ struct brcms_info *wl; -+ struct ieee80211_hw *hw; -+ -+ hw = pci_get_drvdata(pdev); -+ wl = hw->priv; -+ if (!wl) { -+ wiphy_err(wl->wiphy, -+ "brcms_suspend: pci_get_drvdata failed\n"); -+ return -ENODEV; -+ } -+ -+ /* only need to flag hw is down for proper resume */ -+ spin_lock_bh(&wl->lock); -+ wl->pub->hw_up = false; -+ spin_unlock_bh(&wl->lock); -+ -+ pci_save_state(pdev); -+ pci_disable_device(pdev); -+ return pci_set_power_state(pdev, PCI_D3hot); -+} -+ -+static int brcms_resume(struct pci_dev *pdev) -+{ -+ struct brcms_info *wl; -+ struct ieee80211_hw *hw; -+ int err = 0; -+ u32 val; -+ -+ hw = pci_get_drvdata(pdev); -+ wl = hw->priv; -+ if (!wl) { -+ wiphy_err(wl->wiphy, -+ "wl: brcms_resume: pci_get_drvdata failed\n"); -+ return -ENODEV; -+ } -+ -+ err = pci_set_power_state(pdev, PCI_D0); -+ if (err) -+ return err; -+ -+ pci_restore_state(pdev); -+ -+ err = pci_enable_device(pdev); -+ if (err) -+ return err; -+ -+ pci_set_master(pdev); -+ -+ pci_read_config_dword(pdev, 0x40, &val); -+ if ((val & 0x0000ff00) != 0) -+ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); -+ -+ /* -+ * done. driver will be put in up state -+ * in brcms_ops_add_interface() call. -+ */ -+ return err; -+} -+ -+static struct pci_driver brcms_pci_driver = { -+ .name = KBUILD_MODNAME, -+ .probe = brcms_pci_probe, -+ .suspend = brcms_suspend, -+ .resume = brcms_resume, -+ .remove = __devexit_p(brcms_remove), -+ .id_table = brcms_pci_id_table, -+}; -+ -+/** -+ * This is the main entry point for the WL driver. -+ * -+ * This function determines if a device pointed to by pdev is a WL device, -+ * and if so, performs a brcms_attach() on it. -+ * -+ */ -+static int __init brcms_module_init(void) -+{ -+ int error = -ENODEV; -+ -+#ifdef BCMDBG -+ if (msglevel != 0xdeadbeef) -+ brcm_msg_level = msglevel; -+#endif /* BCMDBG */ -+ -+ error = pci_register_driver(&brcms_pci_driver); -+ if (!error) -+ return 0; -+ -+ -+ -+ return error; -+} -+ -+/** -+ * This function unloads the WL driver from the system. -+ * -+ * This function unconditionally unloads the WL driver module from the -+ * system. -+ * -+ */ -+static void __exit brcms_module_exit(void) -+{ -+ pci_unregister_driver(&brcms_pci_driver); -+ -+} -+ -+module_init(brcms_module_init); -+module_exit(brcms_module_exit); -+ -+/* -+ * precondition: perimeter lock has been acquired -+ */ -+void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif, -+ bool state, int prio) -+{ -+ wiphy_err(wl->wiphy, "Shouldn't be here %s\n", __func__); -+} -+ -+/* -+ * precondition: perimeter lock has been acquired -+ */ -+void brcms_init(struct brcms_info *wl) -+{ -+ BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit); -+ brcms_reset(wl); -+ -+ brcms_c_init(wl->wlc); -+} -+ -+/* -+ * precondition: perimeter lock has been acquired -+ */ -+uint brcms_reset(struct brcms_info *wl) -+{ -+ BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit); -+ brcms_c_reset(wl->wlc); -+ -+ /* dpc will not be rescheduled */ -+ wl->resched = 0; -+ -+ return 0; -+} -+ -+/* -+ * These are interrupt on/off entry points. Disable interrupts -+ * during interrupt state transition. -+ */ -+void brcms_intrson(struct brcms_info *wl) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&wl->isr_lock, flags); -+ brcms_c_intrson(wl->wlc); -+ spin_unlock_irqrestore(&wl->isr_lock, flags); -+} -+ -+u32 brcms_intrsoff(struct brcms_info *wl) -+{ -+ unsigned long flags; -+ u32 status; -+ -+ spin_lock_irqsave(&wl->isr_lock, flags); -+ status = brcms_c_intrsoff(wl->wlc); -+ spin_unlock_irqrestore(&wl->isr_lock, flags); -+ return status; -+} -+ -+void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&wl->isr_lock, flags); -+ brcms_c_intrsrestore(wl->wlc, macintmask); -+ spin_unlock_irqrestore(&wl->isr_lock, flags); -+} -+ -+/* -+ * precondition: perimeter lock has been acquired -+ */ -+int brcms_up(struct brcms_info *wl) -+{ -+ int error = 0; -+ -+ if (wl->pub->up) -+ return 0; -+ -+ error = brcms_c_up(wl->wlc); -+ -+ return error; -+} -+ -+/* -+ * precondition: perimeter lock has been acquired -+ */ -+void brcms_down(struct brcms_info *wl) -+{ -+ uint callbacks, ret_val = 0; -+ -+ /* call common down function */ -+ ret_val = brcms_c_down(wl->wlc); -+ callbacks = atomic_read(&wl->callbacks) - ret_val; -+ -+ /* wait for down callbacks to complete */ -+ spin_unlock_bh(&wl->lock); -+ -+ /* For HIGH_only driver, it's important to actually schedule other work, -+ * not just spin wait since everything runs at schedule level -+ */ -+ SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000); -+ -+ spin_lock_bh(&wl->lock); -+} -+ -+/* -+* precondition: perimeter lock is not acquired -+ */ -+static void _brcms_timer(struct work_struct *work) -+{ -+ struct brcms_timer *t = container_of(work, struct brcms_timer, -+ dly_wrk.work); -+ -+ spin_lock_bh(&t->wl->lock); -+ -+ if (t->set) { -+ if (t->periodic) { -+ atomic_inc(&t->wl->callbacks); -+ ieee80211_queue_delayed_work(t->wl->pub->ieee_hw, -+ &t->dly_wrk, -+ msecs_to_jiffies(t->ms)); -+ } else { -+ t->set = false; -+ } -+ -+ t->fn(t->arg); -+ } -+ -+ atomic_dec(&t->wl->callbacks); -+ -+ spin_unlock_bh(&t->wl->lock); -+} -+ -+/* -+ * Adds a timer to the list. Caller supplies a timer function. -+ * Is called from wlc. -+ * -+ * precondition: perimeter lock has been acquired -+ */ -+struct brcms_timer *brcms_init_timer(struct brcms_info *wl, -+ void (*fn) (void *arg), -+ void *arg, const char *name) -+{ -+ struct brcms_timer *t; -+ -+ t = kzalloc(sizeof(struct brcms_timer), GFP_ATOMIC); -+ if (!t) -+ return NULL; -+ -+ INIT_DELAYED_WORK(&t->dly_wrk, _brcms_timer); -+ t->wl = wl; -+ t->fn = fn; -+ t->arg = arg; -+ t->next = wl->timers; -+ wl->timers = t; -+ -+#ifdef BCMDBG -+ t->name = kmalloc(strlen(name) + 1, GFP_ATOMIC); -+ if (t->name) -+ strcpy(t->name, name); -+#endif -+ -+ return t; -+} -+ -+/* -+ * adds only the kernel timer since it's going to be more accurate -+ * as well as it's easier to make it periodic -+ * -+ * precondition: perimeter lock has been acquired -+ */ -+void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic) -+{ -+ struct ieee80211_hw *hw = t->wl->pub->ieee_hw; -+ -+#ifdef BCMDBG -+ if (t->set) -+ wiphy_err(hw->wiphy, "%s: Already set. Name: %s, per %d\n", -+ __func__, t->name, periodic); -+#endif -+ t->ms = ms; -+ t->periodic = (bool) periodic; -+ t->set = true; -+ -+ atomic_inc(&t->wl->callbacks); -+ -+ ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms)); -+} -+ -+/* -+ * return true if timer successfully deleted, false if still pending -+ * -+ * precondition: perimeter lock has been acquired -+ */ -+bool brcms_del_timer(struct brcms_timer *t) -+{ -+ if (t->set) { -+ t->set = false; -+ if (!cancel_delayed_work(&t->dly_wrk)) -+ return false; -+ -+ atomic_dec(&t->wl->callbacks); -+ } -+ -+ return true; -+} -+ -+/* -+ * precondition: perimeter lock has been acquired -+ */ -+void brcms_free_timer(struct brcms_timer *t) -+{ -+ struct brcms_info *wl = t->wl; -+ struct brcms_timer *tmp; -+ -+ /* delete the timer in case it is active */ -+ brcms_del_timer(t); -+ -+ if (wl->timers == t) { -+ wl->timers = wl->timers->next; -+#ifdef BCMDBG -+ kfree(t->name); -+#endif -+ kfree(t); -+ return; -+ -+ } -+ -+ tmp = wl->timers; -+ while (tmp) { -+ if (tmp->next == t) { -+ tmp->next = t->next; -+#ifdef BCMDBG -+ kfree(t->name); -+#endif -+ kfree(t); -+ return; -+ } -+ tmp = tmp->next; -+ } -+ -+} -+ -+/* -+ * precondition: perimeter lock has been acquired -+ */ -+int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx) -+{ -+ int i, entry; -+ const u8 *pdata; -+ struct firmware_hdr *hdr; -+ for (i = 0; i < wl->fw.fw_cnt; i++) { -+ hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data; -+ for (entry = 0; entry < wl->fw.hdr_num_entries[i]; -+ entry++, hdr++) { -+ u32 len = le32_to_cpu(hdr->len); -+ if (le32_to_cpu(hdr->idx) == idx) { -+ pdata = wl->fw.fw_bin[i]->data + -+ le32_to_cpu(hdr->offset); -+ *pbuf = kmalloc(len, GFP_ATOMIC); -+ if (*pbuf == NULL) -+ goto fail; -+ -+ memcpy(*pbuf, pdata, len); -+ return 0; -+ } -+ } -+ } -+ wiphy_err(wl->wiphy, "ERROR: ucode buf tag:%d can not be found!\n", -+ idx); -+ *pbuf = NULL; -+fail: -+ return -ENODATA; -+} -+ -+/* -+ * Precondition: Since this function is called in brcms_pci_probe() context, -+ * no locking is required. -+ */ -+int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx) -+{ -+ int i, entry; -+ const u8 *pdata; -+ struct firmware_hdr *hdr; -+ for (i = 0; i < wl->fw.fw_cnt; i++) { -+ hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data; -+ for (entry = 0; entry < wl->fw.hdr_num_entries[i]; -+ entry++, hdr++) { -+ if (le32_to_cpu(hdr->idx) == idx) { -+ pdata = wl->fw.fw_bin[i]->data + -+ le32_to_cpu(hdr->offset); -+ if (le32_to_cpu(hdr->len) != 4) { -+ wiphy_err(wl->wiphy, -+ "ERROR: fw hdr len\n"); -+ return -ENOMSG; -+ } -+ *n_bytes = le32_to_cpu(*((__le32 *) pdata)); -+ return 0; -+ } -+ } -+ } -+ wiphy_err(wl->wiphy, "ERROR: ucode tag:%d can not be found!\n", idx); -+ return -ENOMSG; -+} -+ -+/* -+ * precondition: can both be called locked and unlocked -+ */ -+void brcms_ucode_free_buf(void *p) -+{ -+ kfree(p); -+} -+ -+/* -+ * checks validity of all firmware images loaded from user space -+ * -+ * Precondition: Since this function is called in brcms_pci_probe() context, -+ * no locking is required. -+ */ -+int brcms_check_firmwares(struct brcms_info *wl) -+{ -+ int i; -+ int entry; -+ int rc = 0; -+ const struct firmware *fw; -+ const struct firmware *fw_hdr; -+ struct firmware_hdr *ucode_hdr; -+ for (i = 0; i < MAX_FW_IMAGES && rc == 0; i++) { -+ fw = wl->fw.fw_bin[i]; -+ fw_hdr = wl->fw.fw_hdr[i]; -+ if (fw == NULL && fw_hdr == NULL) { -+ break; -+ } else if (fw == NULL || fw_hdr == NULL) { -+ wiphy_err(wl->wiphy, "%s: invalid bin/hdr fw\n", -+ __func__); -+ rc = -EBADF; -+ } else if (fw_hdr->size % sizeof(struct firmware_hdr)) { -+ wiphy_err(wl->wiphy, "%s: non integral fw hdr file " -+ "size %zu/%zu\n", __func__, fw_hdr->size, -+ sizeof(struct firmware_hdr)); -+ rc = -EBADF; -+ } else if (fw->size < MIN_FW_SIZE || fw->size > MAX_FW_SIZE) { -+ wiphy_err(wl->wiphy, "%s: out of bounds fw file size " -+ "%zu\n", __func__, fw->size); -+ rc = -EBADF; -+ } else { -+ /* check if ucode section overruns firmware image */ -+ ucode_hdr = (struct firmware_hdr *)fw_hdr->data; -+ for (entry = 0; entry < wl->fw.hdr_num_entries[i] && -+ !rc; entry++, ucode_hdr++) { -+ if (le32_to_cpu(ucode_hdr->offset) + -+ le32_to_cpu(ucode_hdr->len) > -+ fw->size) { -+ wiphy_err(wl->wiphy, -+ "%s: conflicting bin/hdr\n", -+ __func__); -+ rc = -EBADF; -+ } -+ } -+ } -+ } -+ if (rc == 0 && wl->fw.fw_cnt != i) { -+ wiphy_err(wl->wiphy, "%s: invalid fw_cnt=%d\n", __func__, -+ wl->fw.fw_cnt); -+ rc = -EBADF; -+ } -+ return rc; -+} -+ -+/* -+ * precondition: perimeter lock has been acquired -+ */ -+bool brcms_rfkill_set_hw_state(struct brcms_info *wl) -+{ -+ bool blocked = brcms_c_check_radio_disabled(wl->wlc); -+ -+ spin_unlock_bh(&wl->lock); -+ wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked); -+ if (blocked) -+ wiphy_rfkill_start_polling(wl->pub->ieee_hw->wiphy); -+ spin_lock_bh(&wl->lock); -+ return blocked; -+} -+ -+/* -+ * precondition: perimeter lock has been acquired -+ */ -+void brcms_msleep(struct brcms_info *wl, uint ms) -+{ -+ spin_unlock_bh(&wl->lock); -+ msleep(ms); -+ spin_lock_bh(&wl->lock); -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h.orig 2011-11-09 13:46:58.246800621 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h 2011-11-09 13:47:16.998566192 -0500 -@@ -0,0 +1,108 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_MAC80211_IF_H_ -+#define _BRCM_MAC80211_IF_H_ -+ -+#include -+#include -+#include -+ -+#include "ucode_loader.h" -+/* -+ * Starting index for 5G rates in the -+ * legacy rate table. -+ */ -+#define BRCMS_LEGACY_5G_RATE_OFFSET 4 -+ -+/* softmac ioctl definitions */ -+#define BRCMS_SET_SHORTSLOT_OVERRIDE 146 -+ -+struct brcms_timer { -+ struct delayed_work dly_wrk; -+ struct brcms_info *wl; -+ void (*fn) (void *); /* function called upon expiration */ -+ void *arg; /* fixed argument provided to called function */ -+ uint ms; -+ bool periodic; -+ bool set; /* indicates if timer is active */ -+ struct brcms_timer *next; /* for freeing on unload */ -+#ifdef BCMDBG -+ char *name; /* Description of the timer */ -+#endif -+}; -+ -+struct brcms_if { -+ uint subunit; /* WDS/BSS unit */ -+ struct pci_dev *pci_dev; -+}; -+ -+#define MAX_FW_IMAGES 4 -+struct brcms_firmware { -+ u32 fw_cnt; -+ const struct firmware *fw_bin[MAX_FW_IMAGES]; -+ const struct firmware *fw_hdr[MAX_FW_IMAGES]; -+ u32 hdr_num_entries[MAX_FW_IMAGES]; -+}; -+ -+struct brcms_info { -+ struct brcms_pub *pub; /* pointer to public wlc state */ -+ struct brcms_c_info *wlc; /* pointer to private common data */ -+ u32 magic; -+ -+ int irq; -+ -+ spinlock_t lock; /* per-device perimeter lock */ -+ spinlock_t isr_lock; /* per-device ISR synchronization lock */ -+ -+ /* regsva for unmap in brcms_free() */ -+ void __iomem *regsva; /* opaque chip registers virtual address */ -+ -+ /* timer related fields */ -+ atomic_t callbacks; /* # outstanding callback functions */ -+ struct brcms_timer *timers; /* timer cleanup queue */ -+ -+ struct tasklet_struct tasklet; /* dpc tasklet */ -+ bool resched; /* dpc needs to be and is rescheduled */ -+ struct brcms_firmware fw; -+ struct wiphy *wiphy; -+ struct brcms_ucode ucode; -+}; -+ -+/* misc callbacks */ -+extern void brcms_init(struct brcms_info *wl); -+extern uint brcms_reset(struct brcms_info *wl); -+extern void brcms_intrson(struct brcms_info *wl); -+extern u32 brcms_intrsoff(struct brcms_info *wl); -+extern void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask); -+extern int brcms_up(struct brcms_info *wl); -+extern void brcms_down(struct brcms_info *wl); -+extern void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif, -+ bool state, int prio); -+extern bool brcms_rfkill_set_hw_state(struct brcms_info *wl); -+ -+/* timer functions */ -+extern struct brcms_timer *brcms_init_timer(struct brcms_info *wl, -+ void (*fn) (void *arg), void *arg, -+ const char *name); -+extern void brcms_free_timer(struct brcms_timer *timer); -+extern void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic); -+extern bool brcms_del_timer(struct brcms_timer *timer); -+extern void brcms_msleep(struct brcms_info *wl, uint ms); -+extern void brcms_dpc(unsigned long data); -+extern void brcms_timer(struct brcms_timer *t); -+ -+#endif /* _BRCM_MAC80211_IF_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.c.orig 2011-11-09 13:46:58.250800570 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.c 2011-11-09 13:47:17.004566116 -0500 -@@ -0,0 +1,8775 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "rate.h" -+#include "scb.h" -+#include "phy/phy_hal.h" -+#include "channel.h" -+#include "antsel.h" -+#include "stf.h" -+#include "ampdu.h" -+#include "mac80211_if.h" -+#include "ucode_loader.h" -+#include "main.h" -+ -+/* -+ * Indication for txflowcontrol that all priority bits in -+ * TXQ_STOP_FOR_PRIOFC_MASK are to be considered. -+ */ -+#define ALLPRIO -1 -+ -+/* -+ * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL. -+ */ -+#define SSID_FMT_BUF_LEN ((4 * IEEE80211_MAX_SSID_LEN) + 1) -+ -+/* watchdog timer, in unit of ms */ -+#define TIMER_INTERVAL_WATCHDOG 1000 -+/* radio monitor timer, in unit of ms */ -+#define TIMER_INTERVAL_RADIOCHK 800 -+ -+/* Max MPC timeout, in unit of watchdog */ -+#ifndef BRCMS_MPC_MAX_DELAYCNT -+#define BRCMS_MPC_MAX_DELAYCNT 10 -+#endif -+ -+/* Min MPC timeout, in unit of watchdog */ -+#define BRCMS_MPC_MIN_DELAYCNT 1 -+#define BRCMS_MPC_THRESHOLD 3 /* MPC count threshold level */ -+ -+/* beacon interval, in unit of 1024TU */ -+#define BEACON_INTERVAL_DEFAULT 100 -+/* DTIM interval, in unit of beacon interval */ -+#define DTIM_INTERVAL_DEFAULT 3 -+ -+/* Scale down delays to accommodate QT slow speed */ -+/* beacon interval, in unit of 1024TU */ -+#define BEACON_INTERVAL_DEF_QT 20 -+/* DTIM interval, in unit of beacon interval */ -+#define DTIM_INTERVAL_DEF_QT 1 -+ -+#define TBTT_ALIGN_LEEWAY_US 100 /* min leeway before first TBTT in us */ -+ -+/* n-mode support capability */ -+/* 2x2 includes both 1x1 & 2x2 devices -+ * reserved #define 2 for future when we want to separate 1x1 & 2x2 and -+ * control it independently -+ */ -+#define WL_11N_2x2 1 -+#define WL_11N_3x3 3 -+#define WL_11N_4x4 4 -+ -+/* define 11n feature disable flags */ -+#define WLFEATURE_DISABLE_11N 0x00000001 -+#define WLFEATURE_DISABLE_11N_STBC_TX 0x00000002 -+#define WLFEATURE_DISABLE_11N_STBC_RX 0x00000004 -+#define WLFEATURE_DISABLE_11N_SGI_TX 0x00000008 -+#define WLFEATURE_DISABLE_11N_SGI_RX 0x00000010 -+#define WLFEATURE_DISABLE_11N_AMPDU_TX 0x00000020 -+#define WLFEATURE_DISABLE_11N_AMPDU_RX 0x00000040 -+#define WLFEATURE_DISABLE_11N_GF 0x00000080 -+ -+#define EDCF_ACI_MASK 0x60 -+#define EDCF_ACI_SHIFT 5 -+#define EDCF_ECWMIN_MASK 0x0f -+#define EDCF_ECWMAX_SHIFT 4 -+#define EDCF_AIFSN_MASK 0x0f -+#define EDCF_AIFSN_MAX 15 -+#define EDCF_ECWMAX_MASK 0xf0 -+ -+#define EDCF_AC_BE_TXOP_STA 0x0000 -+#define EDCF_AC_BK_TXOP_STA 0x0000 -+#define EDCF_AC_VO_ACI_STA 0x62 -+#define EDCF_AC_VO_ECW_STA 0x32 -+#define EDCF_AC_VI_ACI_STA 0x42 -+#define EDCF_AC_VI_ECW_STA 0x43 -+#define EDCF_AC_BK_ECW_STA 0xA4 -+#define EDCF_AC_VI_TXOP_STA 0x005e -+#define EDCF_AC_VO_TXOP_STA 0x002f -+#define EDCF_AC_BE_ACI_STA 0x03 -+#define EDCF_AC_BE_ECW_STA 0xA4 -+#define EDCF_AC_BK_ACI_STA 0x27 -+#define EDCF_AC_VO_TXOP_AP 0x002f -+ -+#define EDCF_TXOP2USEC(txop) ((txop) << 5) -+#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1) -+ -+#define APHY_SYMBOL_TIME 4 -+#define APHY_PREAMBLE_TIME 16 -+#define APHY_SIGNAL_TIME 4 -+#define APHY_SIFS_TIME 16 -+#define APHY_SERVICE_NBITS 16 -+#define APHY_TAIL_NBITS 6 -+#define BPHY_SIFS_TIME 10 -+#define BPHY_PLCP_SHORT_TIME 96 -+ -+#define PREN_PREAMBLE 24 -+#define PREN_MM_EXT 12 -+#define PREN_PREAMBLE_EXT 4 -+ -+#define DOT11_MAC_HDR_LEN 24 -+#define DOT11_ACK_LEN 10 -+#define DOT11_BA_LEN 4 -+#define DOT11_OFDM_SIGNAL_EXTENSION 6 -+#define DOT11_MIN_FRAG_LEN 256 -+#define DOT11_RTS_LEN 16 -+#define DOT11_CTS_LEN 10 -+#define DOT11_BA_BITMAP_LEN 128 -+#define DOT11_MIN_BEACON_PERIOD 1 -+#define DOT11_MAX_BEACON_PERIOD 0xFFFF -+#define DOT11_MAXNUMFRAGS 16 -+#define DOT11_MAX_FRAG_LEN 2346 -+ -+#define BPHY_PLCP_TIME 192 -+#define RIFS_11N_TIME 2 -+ -+#define WME_VER 1 -+#define WME_SUBTYPE_PARAM_IE 1 -+#define WME_TYPE 2 -+#define WME_OUI "\x00\x50\xf2" -+ -+#define AC_BE 0 -+#define AC_BK 1 -+#define AC_VI 2 -+#define AC_VO 3 -+ -+#define BCN_TMPL_LEN 512 /* length of the BCN template area */ -+ -+/* brcms_bss_info flag bit values */ -+#define BRCMS_BSS_HT 0x0020 /* BSS is HT (MIMO) capable */ -+ -+/* Flags used in brcms_c_txq_info.stopped */ -+/* per prio flow control bits */ -+#define TXQ_STOP_FOR_PRIOFC_MASK 0x000000FF -+/* stop txq enqueue for packet drain */ -+#define TXQ_STOP_FOR_PKT_DRAIN 0x00000100 -+/* stop txq enqueue for ampdu flow control */ -+#define TXQ_STOP_FOR_AMPDU_FLOW_CNTRL 0x00000200 -+ -+#define BRCMS_HWRXOFF 38 /* chip rx buffer offset */ -+ -+/* Find basic rate for a given rate */ -+static u8 brcms_basic_rate(struct brcms_c_info *wlc, u32 rspec) -+{ -+ if (is_mcs_rate(rspec)) -+ return wlc->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK] -+ .leg_ofdm]; -+ return wlc->band->basic_rate[rspec & RSPEC_RATE_MASK]; -+} -+ -+static u16 frametype(u32 rspec, u8 mimoframe) -+{ -+ if (is_mcs_rate(rspec)) -+ return mimoframe; -+ return is_cck_rate(rspec) ? FT_CCK : FT_OFDM; -+} -+ -+/* rfdisable delay timer 500 ms, runs of ALP clock */ -+#define RFDISABLE_DEFAULT 10000000 -+ -+#define BRCMS_TEMPSENSE_PERIOD 10 /* 10 second timeout */ -+ -+/* precedences numbers for wlc queues. These are twice as may levels as -+ * 802.1D priorities. -+ * Odd numbers are used for HI priority traffic at same precedence levels -+ * These constants are used ONLY by wlc_prio2prec_map. Do not use them -+ * elsewhere. -+ */ -+#define _BRCMS_PREC_NONE 0 /* None = - */ -+#define _BRCMS_PREC_BK 2 /* BK - Background */ -+#define _BRCMS_PREC_BE 4 /* BE - Best-effort */ -+#define _BRCMS_PREC_EE 6 /* EE - Excellent-effort */ -+#define _BRCMS_PREC_CL 8 /* CL - Controlled Load */ -+#define _BRCMS_PREC_VI 10 /* Vi - Video */ -+#define _BRCMS_PREC_VO 12 /* Vo - Voice */ -+#define _BRCMS_PREC_NC 14 /* NC - Network Control */ -+ -+/* The BSS is generating beacons in HW */ -+#define BRCMS_BSSCFG_HW_BCN 0x20 -+ -+#define SYNTHPU_DLY_APHY_US 3700 /* a phy synthpu_dly time in us */ -+#define SYNTHPU_DLY_BPHY_US 1050 /* b/g phy synthpu_dly time in us */ -+#define SYNTHPU_DLY_NPHY_US 2048 /* n phy REV3 synthpu_dly time in us */ -+#define SYNTHPU_DLY_LPPHY_US 300 /* lpphy synthpu_dly time in us */ -+ -+#define SYNTHPU_DLY_PHY_US_QT 100 /* QT synthpu_dly time in us */ -+ -+#define ANTCNT 10 /* vanilla M_MAX_ANTCNT value */ -+ -+/* Per-AC retry limit register definitions; uses defs.h bitfield macros */ -+#define EDCF_SHORT_S 0 -+#define EDCF_SFB_S 4 -+#define EDCF_LONG_S 8 -+#define EDCF_LFB_S 12 -+#define EDCF_SHORT_M BITFIELD_MASK(4) -+#define EDCF_SFB_M BITFIELD_MASK(4) -+#define EDCF_LONG_M BITFIELD_MASK(4) -+#define EDCF_LFB_M BITFIELD_MASK(4) -+ -+#define RETRY_SHORT_DEF 7 /* Default Short retry Limit */ -+#define RETRY_SHORT_MAX 255 /* Maximum Short retry Limit */ -+#define RETRY_LONG_DEF 4 /* Default Long retry count */ -+#define RETRY_SHORT_FB 3 /* Short count for fallback rate */ -+#define RETRY_LONG_FB 2 /* Long count for fallback rate */ -+ -+#define APHY_CWMIN 15 -+#define PHY_CWMAX 1023 -+ -+#define EDCF_AIFSN_MIN 1 -+ -+#define FRAGNUM_MASK 0xF -+ -+#define APHY_SLOT_TIME 9 -+#define BPHY_SLOT_TIME 20 -+ -+#define WL_SPURAVOID_OFF 0 -+#define WL_SPURAVOID_ON1 1 -+#define WL_SPURAVOID_ON2 2 -+ -+/* invalid core flags, use the saved coreflags */ -+#define BRCMS_USE_COREFLAGS 0xffffffff -+ -+/* values for PLCPHdr_override */ -+#define BRCMS_PLCP_AUTO -1 -+#define BRCMS_PLCP_SHORT 0 -+#define BRCMS_PLCP_LONG 1 -+ -+/* values for g_protection_override and n_protection_override */ -+#define BRCMS_PROTECTION_AUTO -1 -+#define BRCMS_PROTECTION_OFF 0 -+#define BRCMS_PROTECTION_ON 1 -+#define BRCMS_PROTECTION_MMHDR_ONLY 2 -+#define BRCMS_PROTECTION_CTS_ONLY 3 -+ -+/* values for g_protection_control and n_protection_control */ -+#define BRCMS_PROTECTION_CTL_OFF 0 -+#define BRCMS_PROTECTION_CTL_LOCAL 1 -+#define BRCMS_PROTECTION_CTL_OVERLAP 2 -+ -+/* values for n_protection */ -+#define BRCMS_N_PROTECTION_OFF 0 -+#define BRCMS_N_PROTECTION_OPTIONAL 1 -+#define BRCMS_N_PROTECTION_20IN40 2 -+#define BRCMS_N_PROTECTION_MIXEDMODE 3 -+ -+/* values for band specific 40MHz capabilities */ -+#define BRCMS_N_BW_20ALL 0 -+#define BRCMS_N_BW_40ALL 1 -+#define BRCMS_N_BW_20IN2G_40IN5G 2 -+ -+/* bitflags for SGI support (sgi_rx iovar) */ -+#define BRCMS_N_SGI_20 0x01 -+#define BRCMS_N_SGI_40 0x02 -+ -+/* defines used by the nrate iovar */ -+/* MSC in use,indicates b0-6 holds an mcs */ -+#define NRATE_MCS_INUSE 0x00000080 -+/* rate/mcs value */ -+#define NRATE_RATE_MASK 0x0000007f -+/* stf mode mask: siso, cdd, stbc, sdm */ -+#define NRATE_STF_MASK 0x0000ff00 -+/* stf mode shift */ -+#define NRATE_STF_SHIFT 8 -+/* bit indicates override both rate & mode */ -+#define NRATE_OVERRIDE 0x80000000 -+/* bit indicate to override mcs only */ -+#define NRATE_OVERRIDE_MCS_ONLY 0x40000000 -+#define NRATE_SGI_MASK 0x00800000 /* sgi mode */ -+#define NRATE_SGI_SHIFT 23 /* sgi mode */ -+#define NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */ -+#define NRATE_LDPC_SHIFT 22 /* ldpc shift */ -+ -+#define NRATE_STF_SISO 0 /* stf mode SISO */ -+#define NRATE_STF_CDD 1 /* stf mode CDD */ -+#define NRATE_STF_STBC 2 /* stf mode STBC */ -+#define NRATE_STF_SDM 3 /* stf mode SDM */ -+ -+#define MAX_DMA_SEGS 4 -+ -+/* Max # of entries in Tx FIFO based on 4kb page size */ -+#define NTXD 256 -+/* Max # of entries in Rx FIFO based on 4kb page size */ -+#define NRXD 256 -+ -+/* try to keep this # rbufs posted to the chip */ -+#define NRXBUFPOST 32 -+ -+/* data msg txq hiwat mark */ -+#define BRCMS_DATAHIWAT 50 -+ -+/* bounded rx loops */ -+#define RXBND 8 /* max # frames to process in brcms_c_recv() */ -+#define TXSBND 8 /* max # tx status to process in wlc_txstatus() */ -+ -+/* -+ * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL. -+ */ -+#define SSID_FMT_BUF_LEN ((4 * IEEE80211_MAX_SSID_LEN) + 1) -+ -+/* brcmu_format_flags() bit description structure */ -+struct brcms_c_bit_desc { -+ u32 bit; -+ const char *name; -+}; -+ -+/* -+ * The following table lists the buffer memory allocated to xmt fifos in HW. -+ * the size is in units of 256bytes(one block), total size is HW dependent -+ * ucode has default fifo partition, sw can overwrite if necessary -+ * -+ * This is documented in twiki under the topic UcodeTxFifo. Please ensure -+ * the twiki is updated before making changes. -+ */ -+ -+/* Starting corerev for the fifo size table */ -+#define XMTFIFOTBL_STARTREV 20 -+ -+struct d11init { -+ __le16 addr; -+ __le16 size; -+ __le32 value; -+}; -+ -+struct edcf_acparam { -+ u8 ACI; -+ u8 ECW; -+ u16 TXOP; -+} __packed; -+ -+const u8 prio2fifo[NUMPRIO] = { -+ TX_AC_BE_FIFO, /* 0 BE AC_BE Best Effort */ -+ TX_AC_BK_FIFO, /* 1 BK AC_BK Background */ -+ TX_AC_BK_FIFO, /* 2 -- AC_BK Background */ -+ TX_AC_BE_FIFO, /* 3 EE AC_BE Best Effort */ -+ TX_AC_VI_FIFO, /* 4 CL AC_VI Video */ -+ TX_AC_VI_FIFO, /* 5 VI AC_VI Video */ -+ TX_AC_VO_FIFO, /* 6 VO AC_VO Voice */ -+ TX_AC_VO_FIFO /* 7 NC AC_VO Voice */ -+}; -+ -+/* debug/trace */ -+uint brcm_msg_level = -+#if defined(BCMDBG) -+ LOG_ERROR_VAL; -+#else -+ 0; -+#endif /* BCMDBG */ -+ -+/* TX FIFO number to WME/802.1E Access Category */ -+static const u8 wme_fifo2ac[] = { AC_BK, AC_BE, AC_VI, AC_VO, AC_BE, AC_BE }; -+ -+/* WME/802.1E Access Category to TX FIFO number */ -+static const u8 wme_ac2fifo[] = { 1, 0, 2, 3 }; -+ -+/* 802.1D Priority to precedence queue mapping */ -+const u8 wlc_prio2prec_map[] = { -+ _BRCMS_PREC_BE, /* 0 BE - Best-effort */ -+ _BRCMS_PREC_BK, /* 1 BK - Background */ -+ _BRCMS_PREC_NONE, /* 2 None = - */ -+ _BRCMS_PREC_EE, /* 3 EE - Excellent-effort */ -+ _BRCMS_PREC_CL, /* 4 CL - Controlled Load */ -+ _BRCMS_PREC_VI, /* 5 Vi - Video */ -+ _BRCMS_PREC_VO, /* 6 Vo - Voice */ -+ _BRCMS_PREC_NC, /* 7 NC - Network Control */ -+}; -+ -+static const u16 xmtfifo_sz[][NFIFO] = { -+ /* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */ -+ {20, 192, 192, 21, 17, 5}, -+ /* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */ -+ {9, 58, 22, 14, 14, 5}, -+ /* corerev 22: 5120, 49152, 49152, 5376, 4352, 1280 */ -+ {20, 192, 192, 21, 17, 5}, -+ /* corerev 23: 5120, 49152, 49152, 5376, 4352, 1280 */ -+ {20, 192, 192, 21, 17, 5}, -+ /* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */ -+ {9, 58, 22, 14, 14, 5}, -+}; -+ -+static const u8 acbitmap2maxprio[] = { -+ PRIO_8021D_BE, PRIO_8021D_BE, PRIO_8021D_BK, PRIO_8021D_BK, -+ PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, -+ PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, -+ PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO -+}; -+ -+#ifdef BCMDBG -+static const char * const fifo_names[] = { -+ "AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" }; -+#else -+static const char fifo_names[6][0]; -+#endif -+ -+#ifdef BCMDBG -+/* pointer to most recently allocated wl/wlc */ -+static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL); -+#endif -+ -+/* currently the best mechanism for determining SIFS is the band in use */ -+static u16 get_sifs(struct brcms_band *band) -+{ -+ return band->bandtype == BRCM_BAND_5G ? APHY_SIFS_TIME : -+ BPHY_SIFS_TIME; -+} -+ -+/* -+ * Detect Card removed. -+ * Even checking an sbconfig register read will not false trigger when the core -+ * is in reset it breaks CF address mechanism. Accessing gphy phyversion will -+ * cause SB error if aphy is in reset on 4306B0-DB. Need a simple accessible -+ * reg with fixed 0/1 pattern (some platforms return all 0). -+ * If clocks are present, call the sb routine which will figure out if the -+ * device is removed. -+ */ -+static bool brcms_deviceremoved(struct brcms_c_info *wlc) -+{ -+ if (!wlc->hw->clk) -+ return ai_deviceremoved(wlc->hw->sih); -+ return (R_REG(&wlc->hw->regs->maccontrol) & -+ (MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN; -+} -+ -+/* sum the individual fifo tx pending packet counts */ -+static s16 brcms_txpktpendtot(struct brcms_c_info *wlc) -+{ -+ return wlc->core->txpktpend[0] + wlc->core->txpktpend[1] + -+ wlc->core->txpktpend[2] + wlc->core->txpktpend[3]; -+} -+ -+static bool brcms_is_mband_unlocked(struct brcms_c_info *wlc) -+{ -+ return wlc->pub->_nbands > 1 && !wlc->bandlocked; -+} -+ -+static int brcms_chspec_bw(u16 chanspec) -+{ -+ if (CHSPEC_IS40(chanspec)) -+ return BRCMS_40_MHZ; -+ if (CHSPEC_IS20(chanspec)) -+ return BRCMS_20_MHZ; -+ -+ return BRCMS_10_MHZ; -+} -+ -+/* -+ * return true if Minimum Power Consumption should -+ * be entered, false otherwise -+ */ -+static bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc) -+{ -+ return false; -+} -+ -+static bool brcms_c_ismpc(struct brcms_c_info *wlc) -+{ -+ return (wlc->mpc_delay_off == 0) && (brcms_c_is_non_delay_mpc(wlc)); -+} -+ -+static void brcms_c_bsscfg_mfree(struct brcms_bss_cfg *cfg) -+{ -+ if (cfg == NULL) -+ return; -+ -+ kfree(cfg->current_bss); -+ kfree(cfg); -+} -+ -+static void brcms_c_detach_mfree(struct brcms_c_info *wlc) -+{ -+ if (wlc == NULL) -+ return; -+ -+ brcms_c_bsscfg_mfree(wlc->bsscfg); -+ kfree(wlc->pub); -+ kfree(wlc->modulecb); -+ kfree(wlc->default_bss); -+ kfree(wlc->protection); -+ kfree(wlc->stf); -+ kfree(wlc->bandstate[0]); -+ kfree(wlc->corestate->macstat_snapshot); -+ kfree(wlc->corestate); -+ kfree(wlc->hw->bandstate[0]); -+ kfree(wlc->hw); -+ -+ /* free the wlc */ -+ kfree(wlc); -+ wlc = NULL; -+} -+ -+static struct brcms_bss_cfg *brcms_c_bsscfg_malloc(uint unit) -+{ -+ struct brcms_bss_cfg *cfg; -+ -+ cfg = kzalloc(sizeof(struct brcms_bss_cfg), GFP_ATOMIC); -+ if (cfg == NULL) -+ goto fail; -+ -+ cfg->current_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC); -+ if (cfg->current_bss == NULL) -+ goto fail; -+ -+ return cfg; -+ -+ fail: -+ brcms_c_bsscfg_mfree(cfg); -+ return NULL; -+} -+ -+static struct brcms_c_info * -+brcms_c_attach_malloc(uint unit, uint *err, uint devid) -+{ -+ struct brcms_c_info *wlc; -+ -+ wlc = kzalloc(sizeof(struct brcms_c_info), GFP_ATOMIC); -+ if (wlc == NULL) { -+ *err = 1002; -+ goto fail; -+ } -+ -+ /* allocate struct brcms_c_pub state structure */ -+ wlc->pub = kzalloc(sizeof(struct brcms_pub), GFP_ATOMIC); -+ if (wlc->pub == NULL) { -+ *err = 1003; -+ goto fail; -+ } -+ wlc->pub->wlc = wlc; -+ -+ /* allocate struct brcms_hardware state structure */ -+ -+ wlc->hw = kzalloc(sizeof(struct brcms_hardware), GFP_ATOMIC); -+ if (wlc->hw == NULL) { -+ *err = 1005; -+ goto fail; -+ } -+ wlc->hw->wlc = wlc; -+ -+ wlc->hw->bandstate[0] = -+ kzalloc(sizeof(struct brcms_hw_band) * MAXBANDS, GFP_ATOMIC); -+ if (wlc->hw->bandstate[0] == NULL) { -+ *err = 1006; -+ goto fail; -+ } else { -+ int i; -+ -+ for (i = 1; i < MAXBANDS; i++) -+ wlc->hw->bandstate[i] = (struct brcms_hw_band *) -+ ((unsigned long)wlc->hw->bandstate[0] + -+ (sizeof(struct brcms_hw_band) * i)); -+ } -+ -+ wlc->modulecb = -+ kzalloc(sizeof(struct modulecb) * BRCMS_MAXMODULES, GFP_ATOMIC); -+ if (wlc->modulecb == NULL) { -+ *err = 1009; -+ goto fail; -+ } -+ -+ wlc->default_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC); -+ if (wlc->default_bss == NULL) { -+ *err = 1010; -+ goto fail; -+ } -+ -+ wlc->bsscfg = brcms_c_bsscfg_malloc(unit); -+ if (wlc->bsscfg == NULL) { -+ *err = 1011; -+ goto fail; -+ } -+ -+ wlc->protection = kzalloc(sizeof(struct brcms_protection), -+ GFP_ATOMIC); -+ if (wlc->protection == NULL) { -+ *err = 1016; -+ goto fail; -+ } -+ -+ wlc->stf = kzalloc(sizeof(struct brcms_stf), GFP_ATOMIC); -+ if (wlc->stf == NULL) { -+ *err = 1017; -+ goto fail; -+ } -+ -+ wlc->bandstate[0] = -+ kzalloc(sizeof(struct brcms_band)*MAXBANDS, GFP_ATOMIC); -+ if (wlc->bandstate[0] == NULL) { -+ *err = 1025; -+ goto fail; -+ } else { -+ int i; -+ -+ for (i = 1; i < MAXBANDS; i++) -+ wlc->bandstate[i] = (struct brcms_band *) -+ ((unsigned long)wlc->bandstate[0] -+ + (sizeof(struct brcms_band)*i)); -+ } -+ -+ wlc->corestate = kzalloc(sizeof(struct brcms_core), GFP_ATOMIC); -+ if (wlc->corestate == NULL) { -+ *err = 1026; -+ goto fail; -+ } -+ -+ wlc->corestate->macstat_snapshot = -+ kzalloc(sizeof(struct macstat), GFP_ATOMIC); -+ if (wlc->corestate->macstat_snapshot == NULL) { -+ *err = 1027; -+ goto fail; -+ } -+ -+ return wlc; -+ -+ fail: -+ brcms_c_detach_mfree(wlc); -+ return NULL; -+} -+ -+/* -+ * Update the slot timing for standard 11b/g (20us slots) -+ * or shortslot 11g (9us slots) -+ * The PSM needs to be suspended for this call. -+ */ -+static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw, -+ bool shortslot) -+{ -+ struct d11regs __iomem *regs; -+ -+ regs = wlc_hw->regs; -+ -+ if (shortslot) { -+ /* 11g short slot: 11a timing */ -+ W_REG(®s->ifs_slot, 0x0207); /* APHY_SLOT_TIME */ -+ brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME); -+ } else { -+ /* 11g long slot: 11b timing */ -+ W_REG(®s->ifs_slot, 0x0212); /* BPHY_SLOT_TIME */ -+ brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME); -+ } -+} -+ -+/* -+ * calculate frame duration of a given rate and length, return -+ * time in usec unit -+ */ -+uint -+brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec, -+ u8 preamble_type, uint mac_len) -+{ -+ uint nsyms, dur = 0, Ndps, kNdps; -+ uint rate = rspec2rate(ratespec); -+ -+ if (rate == 0) { -+ wiphy_err(wlc->wiphy, "wl%d: WAR: using rate of 1 mbps\n", -+ wlc->pub->unit); -+ rate = BRCM_RATE_1M; -+ } -+ -+ BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, len%d\n", -+ wlc->pub->unit, ratespec, preamble_type, mac_len); -+ -+ if (is_mcs_rate(ratespec)) { -+ uint mcs = ratespec & RSPEC_RATE_MASK; -+ int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec); -+ -+ dur = PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT); -+ if (preamble_type == BRCMS_MM_PREAMBLE) -+ dur += PREN_MM_EXT; -+ /* 1000Ndbps = kbps * 4 */ -+ kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec), -+ rspec_issgi(ratespec)) * 4; -+ -+ if (rspec_stc(ratespec) == 0) -+ nsyms = -+ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + -+ APHY_TAIL_NBITS) * 1000, kNdps); -+ else -+ /* STBC needs to have even number of symbols */ -+ nsyms = -+ 2 * -+ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + -+ APHY_TAIL_NBITS) * 1000, 2 * kNdps); -+ -+ dur += APHY_SYMBOL_TIME * nsyms; -+ if (wlc->band->bandtype == BRCM_BAND_2G) -+ dur += DOT11_OFDM_SIGNAL_EXTENSION; -+ } else if (is_ofdm_rate(rate)) { -+ dur = APHY_PREAMBLE_TIME; -+ dur += APHY_SIGNAL_TIME; -+ /* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */ -+ Ndps = rate * 2; -+ /* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */ -+ nsyms = -+ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS), -+ Ndps); -+ dur += APHY_SYMBOL_TIME * nsyms; -+ if (wlc->band->bandtype == BRCM_BAND_2G) -+ dur += DOT11_OFDM_SIGNAL_EXTENSION; -+ } else { -+ /* -+ * calc # bits * 2 so factor of 2 in rate (1/2 mbps) -+ * will divide out -+ */ -+ mac_len = mac_len * 8 * 2; -+ /* calc ceiling of bits/rate = microseconds of air time */ -+ dur = (mac_len + rate - 1) / rate; -+ if (preamble_type & BRCMS_SHORT_PREAMBLE) -+ dur += BPHY_PLCP_SHORT_TIME; -+ else -+ dur += BPHY_PLCP_TIME; -+ } -+ return dur; -+} -+ -+static void brcms_c_write_inits(struct brcms_hardware *wlc_hw, -+ const struct d11init *inits) -+{ -+ int i; -+ u8 __iomem *base; -+ u8 __iomem *addr; -+ u16 size; -+ u32 value; -+ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ base = (u8 __iomem *)wlc_hw->regs; -+ -+ for (i = 0; inits[i].addr != cpu_to_le16(0xffff); i++) { -+ size = le16_to_cpu(inits[i].size); -+ addr = base + le16_to_cpu(inits[i].addr); -+ value = le32_to_cpu(inits[i].value); -+ if (size == 2) -+ W_REG((u16 __iomem *)addr, value); -+ else if (size == 4) -+ W_REG((u32 __iomem *)addr, value); -+ else -+ break; -+ } -+} -+ -+static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs) -+{ -+ u8 idx; -+ u16 addr[] = { -+ M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4, -+ M_HOST_FLAGS5 -+ }; -+ -+ for (idx = 0; idx < MHFMAX; idx++) -+ brcms_b_write_shm(wlc_hw, addr[idx], mhfs[idx]); -+} -+ -+static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw) -+{ -+ struct wiphy *wiphy = wlc_hw->wlc->wiphy; -+ struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode; -+ -+ /* init microcode host flags */ -+ brcms_c_write_mhf(wlc_hw, wlc_hw->band->mhfs); -+ -+ /* do band-specific ucode IHR, SHM, and SCR inits */ -+ if (D11REV_IS(wlc_hw->corerev, 23)) { -+ if (BRCMS_ISNPHY(wlc_hw->band)) -+ brcms_c_write_inits(wlc_hw, ucode->d11n0bsinitvals16); -+ else -+ wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" -+ " %d\n", __func__, wlc_hw->unit, -+ wlc_hw->corerev); -+ } else { -+ if (D11REV_IS(wlc_hw->corerev, 24)) { -+ if (BRCMS_ISLCNPHY(wlc_hw->band)) -+ brcms_c_write_inits(wlc_hw, -+ ucode->d11lcn0bsinitvals24); -+ else -+ wiphy_err(wiphy, "%s: wl%d: unsupported phy in" -+ " core rev %d\n", __func__, -+ wlc_hw->unit, wlc_hw->corerev); -+ } else { -+ wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n", -+ __func__, wlc_hw->unit, wlc_hw->corerev); -+ } -+ } -+} -+ -+static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk) -+{ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk); -+ -+ wlc_hw->phyclk = clk; -+ -+ if (OFF == clk) { /* clear gmode bit, put phy into reset */ -+ -+ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE), -+ (SICF_PRST | SICF_FGC)); -+ udelay(1); -+ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST); -+ udelay(1); -+ -+ } else { /* take phy out of reset */ -+ -+ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC); -+ udelay(1); -+ ai_core_cflags(wlc_hw->sih, (SICF_FGC), 0); -+ udelay(1); -+ -+ } -+} -+ -+/* low-level band switch utility routine */ -+static void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit) -+{ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, -+ bandunit); -+ -+ wlc_hw->band = wlc_hw->bandstate[bandunit]; -+ -+ /* -+ * BMAC_NOTE: -+ * until we eliminate need for wlc->band refs in low level code -+ */ -+ wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit]; -+ -+ /* set gmode core flag */ -+ if (wlc_hw->sbclk && !wlc_hw->noreset) -+ ai_core_cflags(wlc_hw->sih, SICF_GMODE, -+ ((bandunit == 0) ? SICF_GMODE : 0)); -+} -+ -+/* switch to new band but leave it inactive */ -+static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit) -+{ -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ u32 macintmask; -+ -+ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0); -+ -+ /* disable interrupts */ -+ macintmask = brcms_intrsoff(wlc->wl); -+ -+ /* radio off */ -+ wlc_phy_switch_radio(wlc_hw->band->pi, OFF); -+ -+ brcms_b_core_phy_clk(wlc_hw, OFF); -+ -+ brcms_c_setxband(wlc_hw, bandunit); -+ -+ return macintmask; -+} -+ -+/* process an individual struct tx_status */ -+static bool -+brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs) -+{ -+ struct sk_buff *p; -+ uint queue; -+ struct d11txh *txh; -+ struct scb *scb = NULL; -+ bool free_pdu; -+ int tx_rts, tx_frame_count, tx_rts_count; -+ uint totlen, supr_status; -+ bool lastframe; -+ struct ieee80211_hdr *h; -+ u16 mcl; -+ struct ieee80211_tx_info *tx_info; -+ struct ieee80211_tx_rate *txrate; -+ int i; -+ -+ /* discard intermediate indications for ucode with one legitimate case: -+ * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, -+ * but the subsequent tx of DATA failed. so it will start rts/cts -+ * from the beginning (resetting the rts transmission count) -+ */ -+ if (!(txs->status & TX_STATUS_AMPDU) -+ && (txs->status & TX_STATUS_INTERMEDIATE)) { -+ wiphy_err(wlc->wiphy, "%s: INTERMEDIATE but not AMPDU\n", -+ __func__); -+ return false; -+ } -+ -+ queue = txs->frameid & TXFID_QUEUE_MASK; -+ if (queue >= NFIFO) { -+ p = NULL; -+ goto fatal; -+ } -+ -+ p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED); -+ if (p == NULL) -+ goto fatal; -+ -+ txh = (struct d11txh *) (p->data); -+ mcl = le16_to_cpu(txh->MacTxControlLow); -+ -+ if (txs->phyerr) { -+ if (brcm_msg_level & LOG_ERROR_VAL) { -+ wiphy_err(wlc->wiphy, "phyerr 0x%x, rate 0x%x\n", -+ txs->phyerr, txh->MainRates); -+ brcms_c_print_txdesc(txh); -+ } -+ brcms_c_print_txstatus(txs); -+ } -+ -+ if (txs->frameid != le16_to_cpu(txh->TxFrameID)) -+ goto fatal; -+ tx_info = IEEE80211_SKB_CB(p); -+ h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN); -+ -+ if (tx_info->control.sta) -+ scb = &wlc->pri_scb; -+ -+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { -+ brcms_c_ampdu_dotxstatus(wlc->ampdu, scb, p, txs); -+ return false; -+ } -+ -+ supr_status = txs->status & TX_STATUS_SUPR_MASK; -+ if (supr_status == TX_STATUS_SUPR_BADCH) -+ BCMMSG(wlc->wiphy, -+ "%s: Pkt tx suppressed, possibly channel %d\n", -+ __func__, CHSPEC_CHANNEL(wlc->default_bss->chanspec)); -+ -+ tx_rts = le16_to_cpu(txh->MacTxControlLow) & TXC_SENDRTS; -+ tx_frame_count = -+ (txs->status & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT; -+ tx_rts_count = -+ (txs->status & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT; -+ -+ lastframe = !ieee80211_has_morefrags(h->frame_control); -+ -+ if (!lastframe) { -+ wiphy_err(wlc->wiphy, "Not last frame!\n"); -+ } else { -+ /* -+ * Set information to be consumed by Minstrel ht. -+ * -+ * The "fallback limit" is the number of tx attempts a given -+ * MPDU is sent at the "primary" rate. Tx attempts beyond that -+ * limit are sent at the "secondary" rate. -+ * A 'short frame' does not exceed RTS treshold. -+ */ -+ u16 sfbl, /* Short Frame Rate Fallback Limit */ -+ lfbl, /* Long Frame Rate Fallback Limit */ -+ fbl; -+ -+ if (queue < AC_COUNT) { -+ sfbl = GFIELD(wlc->wme_retries[wme_fifo2ac[queue]], -+ EDCF_SFB); -+ lfbl = GFIELD(wlc->wme_retries[wme_fifo2ac[queue]], -+ EDCF_LFB); -+ } else { -+ sfbl = wlc->SFBL; -+ lfbl = wlc->LFBL; -+ } -+ -+ txrate = tx_info->status.rates; -+ if (txrate[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) -+ fbl = lfbl; -+ else -+ fbl = sfbl; -+ -+ ieee80211_tx_info_clear_status(tx_info); -+ -+ if ((tx_frame_count > fbl) && (txrate[1].idx >= 0)) { -+ /* -+ * rate selection requested a fallback rate -+ * and we used it -+ */ -+ txrate[0].count = fbl; -+ txrate[1].count = tx_frame_count - fbl; -+ } else { -+ /* -+ * rate selection did not request fallback rate, or -+ * we didn't need it -+ */ -+ txrate[0].count = tx_frame_count; -+ /* -+ * rc80211_minstrel.c:minstrel_tx_status() expects -+ * unused rates to be marked with idx = -1 -+ */ -+ txrate[1].idx = -1; -+ txrate[1].count = 0; -+ } -+ -+ /* clear the rest of the rates */ -+ for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) { -+ txrate[i].idx = -1; -+ txrate[i].count = 0; -+ } -+ -+ if (txs->status & TX_STATUS_ACK_RCV) -+ tx_info->flags |= IEEE80211_TX_STAT_ACK; -+ } -+ -+ totlen = brcmu_pkttotlen(p); -+ free_pdu = true; -+ -+ brcms_c_txfifo_complete(wlc, queue, 1); -+ -+ if (lastframe) { -+ p->next = NULL; -+ p->prev = NULL; -+ /* remove PLCP & Broadcom tx descriptor header */ -+ skb_pull(p, D11_PHY_HDR_LEN); -+ skb_pull(p, D11_TXH_LEN); -+ ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, p); -+ } else { -+ wiphy_err(wlc->wiphy, "%s: Not last frame => not calling " -+ "tx_status\n", __func__); -+ } -+ -+ return false; -+ -+ fatal: -+ if (p) -+ brcmu_pkt_buf_free_skb(p); -+ -+ return true; -+ -+} -+ -+/* process tx completion events in BMAC -+ * Return true if more tx status need to be processed. false otherwise. -+ */ -+static bool -+brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) -+{ -+ bool morepending = false; -+ struct brcms_c_info *wlc = wlc_hw->wlc; -+ struct d11regs __iomem *regs; -+ struct tx_status txstatus, *txs; -+ u32 s1, s2; -+ uint n = 0; -+ /* -+ * Param 'max_tx_num' indicates max. # tx status to process before -+ * break out. -+ */ -+ uint max_tx_num = bound ? TXSBND : -1; -+ -+ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ txs = &txstatus; -+ regs = wlc_hw->regs; -+ *fatal = false; -+ while (!(*fatal) -+ && (s1 = R_REG(®s->frmtxstatus)) & TXS_V) { -+ -+ if (s1 == 0xffffffff) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", -+ wlc_hw->unit, __func__); -+ return morepending; -+ } -+ -+ s2 = R_REG(®s->frmtxstatus2); -+ -+ txs->status = s1 & TXS_STATUS_MASK; -+ txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT; -+ txs->sequence = s2 & TXS_SEQ_MASK; -+ txs->phyerr = (s2 & TXS_PTX_MASK) >> TXS_PTX_SHIFT; -+ txs->lasttxtime = 0; -+ -+ *fatal = brcms_c_dotxstatus(wlc_hw->wlc, txs); -+ -+ /* !give others some time to run! */ -+ if (++n >= max_tx_num) -+ break; -+ } -+ -+ if (*fatal) -+ return 0; -+ -+ if (n >= max_tx_num) -+ morepending = true; -+ -+ if (!pktq_empty(&wlc->pkt_queue->q)) -+ brcms_c_send_q(wlc); -+ -+ return morepending; -+} -+ -+static void brcms_c_tbtt(struct brcms_c_info *wlc) -+{ -+ if (!wlc->bsscfg->BSS) -+ /* -+ * DirFrmQ is now valid...defer setting until end -+ * of ATIM window -+ */ -+ wlc->qvalid |= MCMD_DIRFRMQVAL; -+} -+ -+/* set initial host flags value */ -+static void -+brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init) -+{ -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ -+ memset(mhfs, 0, MHFMAX * sizeof(u16)); -+ -+ mhfs[MHF2] |= mhf2_init; -+ -+ /* prohibit use of slowclock on multifunction boards */ -+ if (wlc_hw->boardflags & BFL_NOPLLDOWN) -+ mhfs[MHF1] |= MHF1_FORCEFASTCLK; -+ -+ if (BRCMS_ISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 2)) { -+ mhfs[MHF2] |= MHF2_NPHY40MHZ_WAR; -+ mhfs[MHF1] |= MHF1_IQSWAP_WAR; -+ } -+} -+ -+static struct dma64regs __iomem * -+dmareg(struct brcms_hardware *hw, uint direction, uint fifonum) -+{ -+ if (direction == DMA_TX) -+ return &(hw->regs->fifo64regs[fifonum].dmaxmt); -+ return &(hw->regs->fifo64regs[fifonum].dmarcv); -+} -+ -+static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme) -+{ -+ uint i; -+ char name[8]; -+ /* -+ * ucode host flag 2 needed for pio mode, independent of band and fifo -+ */ -+ u16 pio_mhf2 = 0; -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ uint unit = wlc_hw->unit; -+ struct wiphy *wiphy = wlc->wiphy; -+ -+ /* name and offsets for dma_attach */ -+ snprintf(name, sizeof(name), "wl%d", unit); -+ -+ if (wlc_hw->di[0] == NULL) { /* Init FIFOs */ -+ int dma_attach_err = 0; -+ -+ /* -+ * FIFO 0 -+ * TX: TX_AC_BK_FIFO (TX AC Background data packets) -+ * RX: RX_FIFO (RX data packets) -+ */ -+ wlc_hw->di[0] = dma_attach(name, wlc_hw->sih, -+ (wme ? dmareg(wlc_hw, DMA_TX, 0) : -+ NULL), dmareg(wlc_hw, DMA_RX, 0), -+ (wme ? NTXD : 0), NRXD, -+ RXBUFSZ, -1, NRXBUFPOST, -+ BRCMS_HWRXOFF, &brcm_msg_level); -+ dma_attach_err |= (NULL == wlc_hw->di[0]); -+ -+ /* -+ * FIFO 1 -+ * TX: TX_AC_BE_FIFO (TX AC Best-Effort data packets) -+ * (legacy) TX_DATA_FIFO (TX data packets) -+ * RX: UNUSED -+ */ -+ wlc_hw->di[1] = dma_attach(name, wlc_hw->sih, -+ dmareg(wlc_hw, DMA_TX, 1), NULL, -+ NTXD, 0, 0, -1, 0, 0, -+ &brcm_msg_level); -+ dma_attach_err |= (NULL == wlc_hw->di[1]); -+ -+ /* -+ * FIFO 2 -+ * TX: TX_AC_VI_FIFO (TX AC Video data packets) -+ * RX: UNUSED -+ */ -+ wlc_hw->di[2] = dma_attach(name, wlc_hw->sih, -+ dmareg(wlc_hw, DMA_TX, 2), NULL, -+ NTXD, 0, 0, -1, 0, 0, -+ &brcm_msg_level); -+ dma_attach_err |= (NULL == wlc_hw->di[2]); -+ /* -+ * FIFO 3 -+ * TX: TX_AC_VO_FIFO (TX AC Voice data packets) -+ * (legacy) TX_CTL_FIFO (TX control & mgmt packets) -+ */ -+ wlc_hw->di[3] = dma_attach(name, wlc_hw->sih, -+ dmareg(wlc_hw, DMA_TX, 3), -+ NULL, NTXD, 0, 0, -1, -+ 0, 0, &brcm_msg_level); -+ dma_attach_err |= (NULL == wlc_hw->di[3]); -+/* Cleaner to leave this as if with AP defined */ -+ -+ if (dma_attach_err) { -+ wiphy_err(wiphy, "wl%d: wlc_attach: dma_attach failed" -+ "\n", unit); -+ return false; -+ } -+ -+ /* get pointer to dma engine tx flow control variable */ -+ for (i = 0; i < NFIFO; i++) -+ if (wlc_hw->di[i]) -+ wlc_hw->txavail[i] = -+ (uint *) dma_getvar(wlc_hw->di[i], -+ "&txavail"); -+ } -+ -+ /* initial ucode host flags */ -+ brcms_c_mhfdef(wlc, wlc_hw->band->mhfs, pio_mhf2); -+ -+ return true; -+} -+ -+static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw) -+{ -+ uint j; -+ -+ for (j = 0; j < NFIFO; j++) { -+ if (wlc_hw->di[j]) { -+ dma_detach(wlc_hw->di[j]); -+ wlc_hw->di[j] = NULL; -+ } -+ } -+} -+ -+/* -+ * Initialize brcms_c_info default values ... -+ * may get overrides later in this function -+ * BMAC_NOTES, move low out and resolve the dangling ones -+ */ -+static void brcms_b_info_init(struct brcms_hardware *wlc_hw) -+{ -+ struct brcms_c_info *wlc = wlc_hw->wlc; -+ -+ /* set default sw macintmask value */ -+ wlc->defmacintmask = DEF_MACINTMASK; -+ -+ /* various 802.11g modes */ -+ wlc_hw->shortslot = false; -+ -+ wlc_hw->SFBL = RETRY_SHORT_FB; -+ wlc_hw->LFBL = RETRY_LONG_FB; -+ -+ /* default mac retry limits */ -+ wlc_hw->SRL = RETRY_SHORT_DEF; -+ wlc_hw->LRL = RETRY_LONG_DEF; -+ wlc_hw->chanspec = ch20mhz_chspec(1); -+} -+ -+static void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw) -+{ -+ /* delay before first read of ucode state */ -+ udelay(40); -+ -+ /* wait until ucode is no longer asleep */ -+ SPINWAIT((brcms_b_read_shm(wlc_hw, M_UCODE_DBGST) == -+ DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly); -+} -+ -+/* control chip clock to save power, enable dynamic clock or force fast clock */ -+static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode) -+{ -+ if (wlc_hw->sih->cccaps & CC_CAP_PMU) { -+ /* new chips with PMU, CCS_FORCEHT will distribute the HT clock -+ * on backplane, but mac core will still run on ALP(not HT) when -+ * it enters powersave mode, which means the FCA bit may not be -+ * set. Should wakeup mac if driver wants it to run on HT. -+ */ -+ -+ if (wlc_hw->clk) { -+ if (mode == CLK_FAST) { -+ OR_REG(&wlc_hw->regs->clk_ctl_st, -+ CCS_FORCEHT); -+ -+ udelay(64); -+ -+ SPINWAIT(((R_REG -+ (&wlc_hw->regs-> -+ clk_ctl_st) & CCS_HTAVAIL) == 0), -+ PMU_MAX_TRANSITION_DLY); -+ WARN_ON(!(R_REG -+ (&wlc_hw->regs-> -+ clk_ctl_st) & CCS_HTAVAIL)); -+ } else { -+ if ((wlc_hw->sih->pmurev == 0) && -+ (R_REG -+ (&wlc_hw->regs-> -+ clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ))) -+ SPINWAIT(((R_REG -+ (&wlc_hw->regs-> -+ clk_ctl_st) & CCS_HTAVAIL) -+ == 0), -+ PMU_MAX_TRANSITION_DLY); -+ AND_REG(&wlc_hw->regs->clk_ctl_st, -+ ~CCS_FORCEHT); -+ } -+ } -+ wlc_hw->forcefastclk = (mode == CLK_FAST); -+ } else { -+ -+ /* old chips w/o PMU, force HT through cc, -+ * then use FCA to verify mac is running fast clock -+ */ -+ -+ wlc_hw->forcefastclk = ai_clkctl_cc(wlc_hw->sih, mode); -+ -+ /* check fast clock is available (if core is not in reset) */ -+ if (wlc_hw->forcefastclk && wlc_hw->clk) -+ WARN_ON(!(ai_core_sflags(wlc_hw->sih, 0, 0) & -+ SISF_FCLKA)); -+ -+ /* -+ * keep the ucode wake bit on if forcefastclk is on since we -+ * do not want ucode to put us back to slow clock when it dozes -+ * for PM mode. Code below matches the wake override bit with -+ * current forcefastclk state. Only setting bit in wake_override -+ * instead of waking ucode immediately since old code had this -+ * behavior. Older code set wlc->forcefastclk but only had the -+ * wake happen if the wakup_ucode work (protected by an up -+ * check) was executed just below. -+ */ -+ if (wlc_hw->forcefastclk) -+ mboolset(wlc_hw->wake_override, -+ BRCMS_WAKE_OVERRIDE_FORCEFAST); -+ else -+ mboolclr(wlc_hw->wake_override, -+ BRCMS_WAKE_OVERRIDE_FORCEFAST); -+ } -+} -+ -+/* set or clear ucode host flag bits -+ * it has an optimization for no-change write -+ * it only writes through shared memory when the core has clock; -+ * pre-CLK changes should use wlc_write_mhf to get around the optimization -+ * -+ * -+ * bands values are: BRCM_BAND_AUTO <--- Current band only -+ * BRCM_BAND_5G <--- 5G band only -+ * BRCM_BAND_2G <--- 2G band only -+ * BRCM_BAND_ALL <--- All bands -+ */ -+void -+brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val, -+ int bands) -+{ -+ u16 save; -+ u16 addr[MHFMAX] = { -+ M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4, -+ M_HOST_FLAGS5 -+ }; -+ struct brcms_hw_band *band; -+ -+ if ((val & ~mask) || idx >= MHFMAX) -+ return; /* error condition */ -+ -+ switch (bands) { -+ /* Current band only or all bands, -+ * then set the band to current band -+ */ -+ case BRCM_BAND_AUTO: -+ case BRCM_BAND_ALL: -+ band = wlc_hw->band; -+ break; -+ case BRCM_BAND_5G: -+ band = wlc_hw->bandstate[BAND_5G_INDEX]; -+ break; -+ case BRCM_BAND_2G: -+ band = wlc_hw->bandstate[BAND_2G_INDEX]; -+ break; -+ default: -+ band = NULL; /* error condition */ -+ } -+ -+ if (band) { -+ save = band->mhfs[idx]; -+ band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val; -+ -+ /* optimization: only write through if changed, and -+ * changed band is the current band -+ */ -+ if (wlc_hw->clk && (band->mhfs[idx] != save) -+ && (band == wlc_hw->band)) -+ brcms_b_write_shm(wlc_hw, addr[idx], -+ (u16) band->mhfs[idx]); -+ } -+ -+ if (bands == BRCM_BAND_ALL) { -+ wlc_hw->bandstate[0]->mhfs[idx] = -+ (wlc_hw->bandstate[0]->mhfs[idx] & ~mask) | val; -+ wlc_hw->bandstate[1]->mhfs[idx] = -+ (wlc_hw->bandstate[1]->mhfs[idx] & ~mask) | val; -+ } -+} -+ -+/* set the maccontrol register to desired reset state and -+ * initialize the sw cache of the register -+ */ -+static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw) -+{ -+ /* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */ -+ wlc_hw->maccontrol = 0; -+ wlc_hw->suspended_fifos = 0; -+ wlc_hw->wake_override = 0; -+ wlc_hw->mute_override = 0; -+ brcms_b_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE); -+} -+ -+/* -+ * write the software state of maccontrol and -+ * overrides to the maccontrol register -+ */ -+static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw) -+{ -+ u32 maccontrol = wlc_hw->maccontrol; -+ -+ /* OR in the wake bit if overridden */ -+ if (wlc_hw->wake_override) -+ maccontrol |= MCTL_WAKE; -+ -+ /* set AP and INFRA bits for mute if needed */ -+ if (wlc_hw->mute_override) { -+ maccontrol &= ~(MCTL_AP); -+ maccontrol |= MCTL_INFRA; -+ } -+ -+ W_REG(&wlc_hw->regs->maccontrol, maccontrol); -+} -+ -+/* set or clear maccontrol bits */ -+void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val) -+{ -+ u32 maccontrol; -+ u32 new_maccontrol; -+ -+ if (val & ~mask) -+ return; /* error condition */ -+ maccontrol = wlc_hw->maccontrol; -+ new_maccontrol = (maccontrol & ~mask) | val; -+ -+ /* if the new maccontrol value is the same as the old, nothing to do */ -+ if (new_maccontrol == maccontrol) -+ return; -+ -+ /* something changed, cache the new value */ -+ wlc_hw->maccontrol = new_maccontrol; -+ -+ /* write the new values with overrides applied */ -+ brcms_c_mctrl_write(wlc_hw); -+} -+ -+void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw, -+ u32 override_bit) -+{ -+ if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) { -+ mboolset(wlc_hw->wake_override, override_bit); -+ return; -+ } -+ -+ mboolset(wlc_hw->wake_override, override_bit); -+ -+ brcms_c_mctrl_write(wlc_hw); -+ brcms_b_wait_for_wake(wlc_hw); -+} -+ -+void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw, -+ u32 override_bit) -+{ -+ mboolclr(wlc_hw->wake_override, override_bit); -+ -+ if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) -+ return; -+ -+ brcms_c_mctrl_write(wlc_hw); -+} -+ -+/* When driver needs ucode to stop beaconing, it has to make sure that -+ * MCTL_AP is clear and MCTL_INFRA is set -+ * Mode MCTL_AP MCTL_INFRA -+ * AP 1 1 -+ * STA 0 1 <--- This will ensure no beacons -+ * IBSS 0 0 -+ */ -+static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw) -+{ -+ wlc_hw->mute_override = 1; -+ -+ /* if maccontrol already has AP == 0 and INFRA == 1 without this -+ * override, then there is no change to write -+ */ -+ if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA) -+ return; -+ -+ brcms_c_mctrl_write(wlc_hw); -+} -+ -+/* Clear the override on AP and INFRA bits */ -+static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw) -+{ -+ if (wlc_hw->mute_override == 0) -+ return; -+ -+ wlc_hw->mute_override = 0; -+ -+ /* if maccontrol already has AP == 0 and INFRA == 1 without this -+ * override, then there is no change to write -+ */ -+ if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA) -+ return; -+ -+ brcms_c_mctrl_write(wlc_hw); -+} -+ -+/* -+ * Write a MAC address to the given match reg offset in the RXE match engine. -+ */ -+static void -+brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset, -+ const u8 *addr) -+{ -+ struct d11regs __iomem *regs; -+ u16 mac_l; -+ u16 mac_m; -+ u16 mac_h; -+ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n", -+ wlc_hw->unit); -+ -+ regs = wlc_hw->regs; -+ mac_l = addr[0] | (addr[1] << 8); -+ mac_m = addr[2] | (addr[3] << 8); -+ mac_h = addr[4] | (addr[5] << 8); -+ -+ /* enter the MAC addr into the RXE match registers */ -+ W_REG(®s->rcm_ctl, RCM_INC_DATA | match_reg_offset); -+ W_REG(®s->rcm_mat_data, mac_l); -+ W_REG(®s->rcm_mat_data, mac_m); -+ W_REG(®s->rcm_mat_data, mac_h); -+ -+} -+ -+void -+brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len, -+ void *buf) -+{ -+ struct d11regs __iomem *regs; -+ u32 word; -+ __le32 word_le; -+ __be32 word_be; -+ bool be_bit; -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ regs = wlc_hw->regs; -+ W_REG(®s->tplatewrptr, offset); -+ -+ /* if MCTL_BIGEND bit set in mac control register, -+ * the chip swaps data in fifo, as well as data in -+ * template ram -+ */ -+ be_bit = (R_REG(®s->maccontrol) & MCTL_BIGEND) != 0; -+ -+ while (len > 0) { -+ memcpy(&word, buf, sizeof(u32)); -+ -+ if (be_bit) { -+ word_be = cpu_to_be32(word); -+ word = *(u32 *)&word_be; -+ } else { -+ word_le = cpu_to_le32(word); -+ word = *(u32 *)&word_le; -+ } -+ -+ W_REG(®s->tplatewrdata, word); -+ -+ buf = (u8 *) buf + sizeof(u32); -+ len -= sizeof(u32); -+ } -+} -+ -+static void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin) -+{ -+ wlc_hw->band->CWmin = newmin; -+ -+ W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN); -+ (void)R_REG(&wlc_hw->regs->objaddr); -+ W_REG(&wlc_hw->regs->objdata, newmin); -+} -+ -+static void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax) -+{ -+ wlc_hw->band->CWmax = newmax; -+ -+ W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX); -+ (void)R_REG(&wlc_hw->regs->objaddr); -+ W_REG(&wlc_hw->regs->objdata, newmax); -+} -+ -+void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw) -+{ -+ bool fastclk; -+ -+ /* request FAST clock if not on */ -+ fastclk = wlc_hw->forcefastclk; -+ if (!fastclk) -+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); -+ -+ wlc_phy_bw_state_set(wlc_hw->band->pi, bw); -+ -+ brcms_b_phy_reset(wlc_hw); -+ wlc_phy_init(wlc_hw->band->pi, wlc_phy_chanspec_get(wlc_hw->band->pi)); -+ -+ /* restore the clk */ -+ if (!fastclk) -+ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); -+} -+ -+static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw) -+{ -+ u16 v; -+ struct brcms_c_info *wlc = wlc_hw->wlc; -+ /* update SYNTHPU_DLY */ -+ -+ if (BRCMS_ISLCNPHY(wlc->band)) -+ v = SYNTHPU_DLY_LPPHY_US; -+ else if (BRCMS_ISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3))) -+ v = SYNTHPU_DLY_NPHY_US; -+ else -+ v = SYNTHPU_DLY_BPHY_US; -+ -+ brcms_b_write_shm(wlc_hw, M_SYNTHPU_DLY, v); -+} -+ -+static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw) -+{ -+ u16 phyctl; -+ u16 phytxant = wlc_hw->bmac_phytxant; -+ u16 mask = PHY_TXC_ANT_MASK; -+ -+ /* set the Probe Response frame phy control word */ -+ phyctl = brcms_b_read_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS); -+ phyctl = (phyctl & ~mask) | phytxant; -+ brcms_b_write_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS, phyctl); -+ -+ /* set the Response (ACK/CTS) frame phy control word */ -+ phyctl = brcms_b_read_shm(wlc_hw, M_RSP_PCTLWD); -+ phyctl = (phyctl & ~mask) | phytxant; -+ brcms_b_write_shm(wlc_hw, M_RSP_PCTLWD, phyctl); -+} -+ -+static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw, -+ u8 rate) -+{ -+ uint i; -+ u8 plcp_rate = 0; -+ struct plcp_signal_rate_lookup { -+ u8 rate; -+ u8 signal_rate; -+ }; -+ /* OFDM RATE sub-field of PLCP SIGNAL field, per 802.11 sec 17.3.4.1 */ -+ const struct plcp_signal_rate_lookup rate_lookup[] = { -+ {BRCM_RATE_6M, 0xB}, -+ {BRCM_RATE_9M, 0xF}, -+ {BRCM_RATE_12M, 0xA}, -+ {BRCM_RATE_18M, 0xE}, -+ {BRCM_RATE_24M, 0x9}, -+ {BRCM_RATE_36M, 0xD}, -+ {BRCM_RATE_48M, 0x8}, -+ {BRCM_RATE_54M, 0xC} -+ }; -+ -+ for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) { -+ if (rate == rate_lookup[i].rate) { -+ plcp_rate = rate_lookup[i].signal_rate; -+ break; -+ } -+ } -+ -+ /* Find the SHM pointer to the rate table entry by looking in the -+ * Direct-map Table -+ */ -+ return 2 * brcms_b_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2)); -+} -+ -+static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw) -+{ -+ u8 rate; -+ u8 rates[8] = { -+ BRCM_RATE_6M, BRCM_RATE_9M, BRCM_RATE_12M, BRCM_RATE_18M, -+ BRCM_RATE_24M, BRCM_RATE_36M, BRCM_RATE_48M, BRCM_RATE_54M -+ }; -+ u16 entry_ptr; -+ u16 pctl1; -+ uint i; -+ -+ if (!BRCMS_PHY_11N_CAP(wlc_hw->band)) -+ return; -+ -+ /* walk the phy rate table and update the entries */ -+ for (i = 0; i < ARRAY_SIZE(rates); i++) { -+ rate = rates[i]; -+ -+ entry_ptr = brcms_b_ofdm_ratetable_offset(wlc_hw, rate); -+ -+ /* read the SHM Rate Table entry OFDM PCTL1 values */ -+ pctl1 = -+ brcms_b_read_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS); -+ -+ /* modify the value */ -+ pctl1 &= ~PHY_TXC1_MODE_MASK; -+ pctl1 |= (wlc_hw->hw_stf_ss_opmode << PHY_TXC1_MODE_SHIFT); -+ -+ /* Update the SHM Rate Table entry OFDM PCTL1 values */ -+ brcms_b_write_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS, -+ pctl1); -+ } -+} -+ -+/* band-specific init */ -+static void brcms_b_bsinit(struct brcms_c_info *wlc, u16 chanspec) -+{ -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ -+ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, -+ wlc_hw->band->bandunit); -+ -+ brcms_c_ucode_bsinit(wlc_hw); -+ -+ wlc_phy_init(wlc_hw->band->pi, chanspec); -+ -+ brcms_c_ucode_txant_set(wlc_hw); -+ -+ /* -+ * cwmin is band-specific, update hardware -+ * with value for current band -+ */ -+ brcms_b_set_cwmin(wlc_hw, wlc_hw->band->CWmin); -+ brcms_b_set_cwmax(wlc_hw, wlc_hw->band->CWmax); -+ -+ brcms_b_update_slot_timing(wlc_hw, -+ wlc_hw->band->bandtype == BRCM_BAND_5G ? -+ true : wlc_hw->shortslot); -+ -+ /* write phytype and phyvers */ -+ brcms_b_write_shm(wlc_hw, M_PHYTYPE, (u16) wlc_hw->band->phytype); -+ brcms_b_write_shm(wlc_hw, M_PHYVER, (u16) wlc_hw->band->phyrev); -+ -+ /* -+ * initialize the txphyctl1 rate table since -+ * shmem is shared between bands -+ */ -+ brcms_upd_ofdm_pctl1_table(wlc_hw); -+ -+ brcms_b_upd_synthpu(wlc_hw); -+} -+ -+/* Perform a soft reset of the PHY PLL */ -+void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw) -+{ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ ai_corereg(wlc_hw->sih, SI_CC_IDX, -+ offsetof(struct chipcregs, chipcontrol_addr), ~0, 0); -+ udelay(1); -+ ai_corereg(wlc_hw->sih, SI_CC_IDX, -+ offsetof(struct chipcregs, chipcontrol_data), 0x4, 0); -+ udelay(1); -+ ai_corereg(wlc_hw->sih, SI_CC_IDX, -+ offsetof(struct chipcregs, chipcontrol_data), 0x4, 4); -+ udelay(1); -+ ai_corereg(wlc_hw->sih, SI_CC_IDX, -+ offsetof(struct chipcregs, chipcontrol_data), 0x4, 0); -+ udelay(1); -+} -+ -+/* light way to turn on phy clock without reset for NPHY only -+ * refer to brcms_b_core_phy_clk for full version -+ */ -+void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk) -+{ -+ /* support(necessary for NPHY and HYPHY) only */ -+ if (!BRCMS_ISNPHY(wlc_hw->band)) -+ return; -+ -+ if (ON == clk) -+ ai_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC); -+ else -+ ai_core_cflags(wlc_hw->sih, SICF_FGC, 0); -+ -+} -+ -+void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk) -+{ -+ if (ON == clk) -+ ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE); -+ else -+ ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0); -+} -+ -+void brcms_b_phy_reset(struct brcms_hardware *wlc_hw) -+{ -+ struct brcms_phy_pub *pih = wlc_hw->band->pi; -+ u32 phy_bw_clkbits; -+ bool phy_in_reset = false; -+ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ if (pih == NULL) -+ return; -+ -+ phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi); -+ -+ /* Specific reset sequence required for NPHY rev 3 and 4 */ -+ if (BRCMS_ISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) && -+ NREV_LE(wlc_hw->band->phyrev, 4)) { -+ /* Set the PHY bandwidth */ -+ ai_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits); -+ -+ udelay(1); -+ -+ /* Perform a soft reset of the PHY PLL */ -+ brcms_b_core_phypll_reset(wlc_hw); -+ -+ /* reset the PHY */ -+ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE), -+ (SICF_PRST | SICF_PCLKE)); -+ phy_in_reset = true; -+ } else { -+ ai_core_cflags(wlc_hw->sih, -+ (SICF_PRST | SICF_PCLKE | SICF_BWMASK), -+ (SICF_PRST | SICF_PCLKE | phy_bw_clkbits)); -+ } -+ -+ udelay(2); -+ brcms_b_core_phy_clk(wlc_hw, ON); -+ -+ if (pih) -+ wlc_phy_anacore(pih, ON); -+} -+ -+/* switch to and initialize new band */ -+static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit, -+ u16 chanspec) { -+ struct brcms_c_info *wlc = wlc_hw->wlc; -+ u32 macintmask; -+ -+ /* Enable the d11 core before accessing it */ -+ if (!ai_iscoreup(wlc_hw->sih)) { -+ ai_core_reset(wlc_hw->sih, 0, 0); -+ brcms_c_mctrl_reset(wlc_hw); -+ } -+ -+ macintmask = brcms_c_setband_inact(wlc, bandunit); -+ -+ if (!wlc_hw->up) -+ return; -+ -+ brcms_b_core_phy_clk(wlc_hw, ON); -+ -+ /* band-specific initializations */ -+ brcms_b_bsinit(wlc, chanspec); -+ -+ /* -+ * If there are any pending software interrupt bits, -+ * then replace these with a harmless nonzero value -+ * so brcms_c_dpc() will re-enable interrupts when done. -+ */ -+ if (wlc->macintstatus) -+ wlc->macintstatus = MI_DMAINT; -+ -+ /* restore macintmask */ -+ brcms_intrsrestore(wlc->wl, macintmask); -+ -+ /* ucode should still be suspended.. */ -+ WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0); -+} -+ -+static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw) -+{ -+ -+ /* reject unsupported corerev */ -+ if (!CONF_HAS(D11CONF, wlc_hw->corerev)) { -+ wiphy_err(wlc_hw->wlc->wiphy, "unsupported core rev %d\n", -+ wlc_hw->corerev); -+ return false; -+ } -+ -+ return true; -+} -+ -+/* Validate some board info parameters */ -+static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw) -+{ -+ uint boardrev = wlc_hw->boardrev; -+ -+ /* 4 bits each for board type, major, minor, and tiny version */ -+ uint brt = (boardrev & 0xf000) >> 12; -+ uint b0 = (boardrev & 0xf00) >> 8; -+ uint b1 = (boardrev & 0xf0) >> 4; -+ uint b2 = boardrev & 0xf; -+ -+ /* voards from other vendors are always considered valid */ -+ if (wlc_hw->sih->boardvendor != PCI_VENDOR_ID_BROADCOM) -+ return true; -+ -+ /* do some boardrev sanity checks when boardvendor is Broadcom */ -+ if (boardrev == 0) -+ return false; -+ -+ if (boardrev <= 0xff) -+ return true; -+ -+ if ((brt > 2) || (brt == 0) || (b0 > 9) || (b0 == 0) || (b1 > 9) -+ || (b2 > 9)) -+ return false; -+ -+ return true; -+} -+ -+static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw) -+{ -+ enum brcms_srom_id var_id = BRCMS_SROM_MACADDR; -+ char *macaddr; -+ -+ /* If macaddr exists, use it (Sromrev4, CIS, ...). */ -+ macaddr = getvar(wlc_hw->sih, var_id); -+ if (macaddr != NULL) -+ return macaddr; -+ -+ if (wlc_hw->_nbands > 1) -+ var_id = BRCMS_SROM_ET1MACADDR; -+ else -+ var_id = BRCMS_SROM_IL0MACADDR; -+ -+ macaddr = getvar(wlc_hw->sih, var_id); -+ if (macaddr == NULL) -+ wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_get_macaddr: macaddr " -+ "getvar(%d) not found\n", wlc_hw->unit, var_id); -+ -+ return macaddr; -+} -+ -+/* power both the pll and external oscillator on/off */ -+static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want) -+{ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: want %d\n", wlc_hw->unit, want); -+ -+ /* -+ * dont power down if plldown is false or -+ * we must poll hw radio disable -+ */ -+ if (!want && wlc_hw->pllreq) -+ return; -+ -+ if (wlc_hw->sih) -+ ai_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want); -+ -+ wlc_hw->sbclk = want; -+ if (!wlc_hw->sbclk) { -+ wlc_hw->clk = false; -+ if (wlc_hw->band && wlc_hw->band->pi) -+ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); -+ } -+} -+ -+/* -+ * Return true if radio is disabled, otherwise false. -+ * hw radio disable signal is an external pin, users activate it asynchronously -+ * this function could be called when driver is down and w/o clock -+ * it operates on different registers depending on corerev and boardflag. -+ */ -+static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw) -+{ -+ bool v, clk, xtal; -+ u32 resetbits = 0, flags = 0; -+ -+ xtal = wlc_hw->sbclk; -+ if (!xtal) -+ brcms_b_xtal(wlc_hw, ON); -+ -+ /* may need to take core out of reset first */ -+ clk = wlc_hw->clk; -+ if (!clk) { -+ /* -+ * mac no longer enables phyclk automatically when driver -+ * accesses phyreg throughput mac. This can be skipped since -+ * only mac reg is accessed below -+ */ -+ flags |= SICF_PCLKE; -+ -+ /* -+ * AI chip doesn't restore bar0win2 on -+ * hibernation/resume, need sw fixup -+ */ -+ if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || -+ (wlc_hw->sih->chip == BCM43225_CHIP_ID)) -+ wlc_hw->regs = (struct d11regs __iomem *) -+ ai_setcore(wlc_hw->sih, D11_CORE_ID, 0); -+ ai_core_reset(wlc_hw->sih, flags, resetbits); -+ brcms_c_mctrl_reset(wlc_hw); -+ } -+ -+ v = ((R_REG(&wlc_hw->regs->phydebug) & PDBG_RFD) != 0); -+ -+ /* put core back into reset */ -+ if (!clk) -+ ai_core_disable(wlc_hw->sih, 0); -+ -+ if (!xtal) -+ brcms_b_xtal(wlc_hw, OFF); -+ -+ return v; -+} -+ -+static bool wlc_dma_rxreset(struct brcms_hardware *wlc_hw, uint fifo) -+{ -+ struct dma_pub *di = wlc_hw->di[fifo]; -+ return dma_rxreset(di); -+} -+ -+/* d11 core reset -+ * ensure fask clock during reset -+ * reset dma -+ * reset d11(out of reset) -+ * reset phy(out of reset) -+ * clear software macintstatus for fresh new start -+ * one testing hack wlc_hw->noreset will bypass the d11/phy reset -+ */ -+void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) -+{ -+ struct d11regs __iomem *regs; -+ uint i; -+ bool fastclk; -+ u32 resetbits = 0; -+ -+ if (flags == BRCMS_USE_COREFLAGS) -+ flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0); -+ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ regs = wlc_hw->regs; -+ -+ /* request FAST clock if not on */ -+ fastclk = wlc_hw->forcefastclk; -+ if (!fastclk) -+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); -+ -+ /* reset the dma engines except first time thru */ -+ if (ai_iscoreup(wlc_hw->sih)) { -+ for (i = 0; i < NFIFO; i++) -+ if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i]))) -+ wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: " -+ "dma_txreset[%d]: cannot stop dma\n", -+ wlc_hw->unit, __func__, i); -+ -+ if ((wlc_hw->di[RX_FIFO]) -+ && (!wlc_dma_rxreset(wlc_hw, RX_FIFO))) -+ wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: dma_rxreset" -+ "[%d]: cannot stop dma\n", -+ wlc_hw->unit, __func__, RX_FIFO); -+ } -+ /* if noreset, just stop the psm and return */ -+ if (wlc_hw->noreset) { -+ wlc_hw->wlc->macintstatus = 0; /* skip wl_dpc after down */ -+ brcms_b_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0); -+ return; -+ } -+ -+ /* -+ * mac no longer enables phyclk automatically when driver accesses -+ * phyreg throughput mac, AND phy_reset is skipped at early stage when -+ * band->pi is invalid. need to enable PHY CLK -+ */ -+ flags |= SICF_PCLKE; -+ -+ /* -+ * reset the core -+ * In chips with PMU, the fastclk request goes through d11 core -+ * reg 0x1e0, which is cleared by the core_reset. have to re-request it. -+ * -+ * This adds some delay and we can optimize it by also requesting -+ * fastclk through chipcommon during this period if necessary. But -+ * that has to work coordinate with other driver like mips/arm since -+ * they may touch chipcommon as well. -+ */ -+ wlc_hw->clk = false; -+ ai_core_reset(wlc_hw->sih, flags, resetbits); -+ wlc_hw->clk = true; -+ if (wlc_hw->band && wlc_hw->band->pi) -+ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true); -+ -+ brcms_c_mctrl_reset(wlc_hw); -+ -+ if (wlc_hw->sih->cccaps & CC_CAP_PMU) -+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); -+ -+ brcms_b_phy_reset(wlc_hw); -+ -+ /* turn on PHY_PLL */ -+ brcms_b_core_phypll_ctl(wlc_hw, true); -+ -+ /* clear sw intstatus */ -+ wlc_hw->wlc->macintstatus = 0; -+ -+ /* restore the clk setting */ -+ if (!fastclk) -+ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); -+} -+ -+/* txfifo sizes needs to be modified(increased) since the newer cores -+ * have more memory. -+ */ -+static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw) -+{ -+ struct d11regs __iomem *regs = wlc_hw->regs; -+ u16 fifo_nu; -+ u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk; -+ u16 txfifo_def, txfifo_def1; -+ u16 txfifo_cmd; -+ -+ /* tx fifos start at TXFIFO_START_BLK from the Base address */ -+ txfifo_startblk = TXFIFO_START_BLK; -+ -+ /* sequence of operations: reset fifo, set fifo size, reset fifo */ -+ for (fifo_nu = 0; fifo_nu < NFIFO; fifo_nu++) { -+ -+ txfifo_endblk = txfifo_startblk + wlc_hw->xmtfifo_sz[fifo_nu]; -+ txfifo_def = (txfifo_startblk & 0xff) | -+ (((txfifo_endblk - 1) & 0xff) << TXFIFO_FIFOTOP_SHIFT); -+ txfifo_def1 = ((txfifo_startblk >> 8) & 0x1) | -+ ((((txfifo_endblk - -+ 1) >> 8) & 0x1) << TXFIFO_FIFOTOP_SHIFT); -+ txfifo_cmd = -+ TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT); -+ -+ W_REG(®s->xmtfifocmd, txfifo_cmd); -+ W_REG(®s->xmtfifodef, txfifo_def); -+ W_REG(®s->xmtfifodef1, txfifo_def1); -+ -+ W_REG(®s->xmtfifocmd, txfifo_cmd); -+ -+ txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu]; -+ } -+ /* -+ * need to propagate to shm location to be in sync since ucode/hw won't -+ * do this -+ */ -+ brcms_b_write_shm(wlc_hw, M_FIFOSIZE0, -+ wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]); -+ brcms_b_write_shm(wlc_hw, M_FIFOSIZE1, -+ wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]); -+ brcms_b_write_shm(wlc_hw, M_FIFOSIZE2, -+ ((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw-> -+ xmtfifo_sz[TX_AC_BK_FIFO])); -+ brcms_b_write_shm(wlc_hw, M_FIFOSIZE3, -+ ((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw-> -+ xmtfifo_sz[TX_BCMC_FIFO])); -+} -+ -+/* This function is used for changing the tsf frac register -+ * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz -+ * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz -+ * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz -+ * HTPHY Formula is 2^26/freq(MHz) e.g. -+ * For spuron2 - 126MHz -> 2^26/126 = 532610.0 -+ * - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082 -+ * For spuron: 123MHz -> 2^26/123 = 545600.5 -+ * - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341 -+ * For spur off: 120MHz -> 2^26/120 = 559240.5 -+ * - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889 -+ */ -+ -+void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode) -+{ -+ struct d11regs __iomem *regs = wlc_hw->regs; -+ -+ if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || -+ (wlc_hw->sih->chip == BCM43225_CHIP_ID)) { -+ if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */ -+ W_REG(®s->tsf_clk_frac_l, 0x2082); -+ W_REG(®s->tsf_clk_frac_h, 0x8); -+ } else if (spurmode == WL_SPURAVOID_ON1) { /* 123Mhz */ -+ W_REG(®s->tsf_clk_frac_l, 0x5341); -+ W_REG(®s->tsf_clk_frac_h, 0x8); -+ } else { /* 120Mhz */ -+ W_REG(®s->tsf_clk_frac_l, 0x8889); -+ W_REG(®s->tsf_clk_frac_h, 0x8); -+ } -+ } else if (BRCMS_ISLCNPHY(wlc_hw->band)) { -+ if (spurmode == WL_SPURAVOID_ON1) { /* 82Mhz */ -+ W_REG(®s->tsf_clk_frac_l, 0x7CE0); -+ W_REG(®s->tsf_clk_frac_h, 0xC); -+ } else { /* 80Mhz */ -+ W_REG(®s->tsf_clk_frac_l, 0xCCCD); -+ W_REG(®s->tsf_clk_frac_h, 0xC); -+ } -+ } -+} -+ -+/* Initialize GPIOs that are controlled by D11 core */ -+static void brcms_c_gpio_init(struct brcms_c_info *wlc) -+{ -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ struct d11regs __iomem *regs; -+ u32 gc, gm; -+ -+ regs = wlc_hw->regs; -+ -+ /* use GPIO select 0 to get all gpio signals from the gpio out reg */ -+ brcms_b_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0); -+ -+ /* -+ * Common GPIO setup: -+ * G0 = LED 0 = WLAN Activity -+ * G1 = LED 1 = WLAN 2.4 GHz Radio State -+ * G2 = LED 2 = WLAN 5 GHz Radio State -+ * G4 = radio disable input (HI enabled, LO disabled) -+ */ -+ -+ gc = gm = 0; -+ -+ /* Allocate GPIOs for mimo antenna diversity feature */ -+ if (wlc_hw->antsel_type == ANTSEL_2x3) { -+ /* Enable antenna diversity, use 2x3 mode */ -+ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN, -+ MHF3_ANTSEL_EN, BRCM_BAND_ALL); -+ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, -+ MHF3_ANTSEL_MODE, BRCM_BAND_ALL); -+ -+ /* init superswitch control */ -+ wlc_phy_antsel_init(wlc_hw->band->pi, false); -+ -+ } else if (wlc_hw->antsel_type == ANTSEL_2x4) { -+ gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13); -+ /* -+ * The board itself is powered by these GPIOs -+ * (when not sending pattern) so set them high -+ */ -+ OR_REG(®s->psm_gpio_oe, -+ (BOARD_GPIO_12 | BOARD_GPIO_13)); -+ OR_REG(®s->psm_gpio_out, -+ (BOARD_GPIO_12 | BOARD_GPIO_13)); -+ -+ /* Enable antenna diversity, use 2x4 mode */ -+ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN, -+ MHF3_ANTSEL_EN, BRCM_BAND_ALL); -+ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, 0, -+ BRCM_BAND_ALL); -+ -+ /* Configure the desired clock to be 4Mhz */ -+ brcms_b_write_shm(wlc_hw, M_ANTSEL_CLKDIV, -+ ANTSEL_CLKDIV_4MHZ); -+ } -+ -+ /* -+ * gpio 9 controls the PA. ucode is responsible -+ * for wiggling out and oe -+ */ -+ if (wlc_hw->boardflags & BFL_PACTRL) -+ gm |= gc |= BOARD_GPIO_PACTRL; -+ -+ /* apply to gpiocontrol register */ -+ ai_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY); -+} -+ -+static void brcms_ucode_write(struct brcms_hardware *wlc_hw, -+ const __le32 ucode[], const size_t nbytes) -+{ -+ struct d11regs __iomem *regs = wlc_hw->regs; -+ uint i; -+ uint count; -+ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ count = (nbytes / sizeof(u32)); -+ -+ W_REG(®s->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL)); -+ (void)R_REG(®s->objaddr); -+ for (i = 0; i < count; i++) -+ W_REG(®s->objdata, le32_to_cpu(ucode[i])); -+ -+} -+ -+static void brcms_ucode_download(struct brcms_hardware *wlc_hw) -+{ -+ struct brcms_c_info *wlc; -+ struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode; -+ -+ wlc = wlc_hw->wlc; -+ -+ if (wlc_hw->ucode_loaded) -+ return; -+ -+ if (D11REV_IS(wlc_hw->corerev, 23)) { -+ if (BRCMS_ISNPHY(wlc_hw->band)) { -+ brcms_ucode_write(wlc_hw, ucode->bcm43xx_16_mimo, -+ ucode->bcm43xx_16_mimosz); -+ wlc_hw->ucode_loaded = true; -+ } else -+ wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in " -+ "corerev %d\n", -+ __func__, wlc_hw->unit, wlc_hw->corerev); -+ } else if (D11REV_IS(wlc_hw->corerev, 24)) { -+ if (BRCMS_ISLCNPHY(wlc_hw->band)) { -+ brcms_ucode_write(wlc_hw, ucode->bcm43xx_24_lcn, -+ ucode->bcm43xx_24_lcnsz); -+ wlc_hw->ucode_loaded = true; -+ } else { -+ wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in " -+ "corerev %d\n", -+ __func__, wlc_hw->unit, wlc_hw->corerev); -+ } -+ } -+} -+ -+void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant) -+{ -+ /* update sw state */ -+ wlc_hw->bmac_phytxant = phytxant; -+ -+ /* push to ucode if up */ -+ if (!wlc_hw->up) -+ return; -+ brcms_c_ucode_txant_set(wlc_hw); -+ -+} -+ -+u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw) -+{ -+ return (u16) wlc_hw->wlc->stf->txant; -+} -+ -+void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type) -+{ -+ wlc_hw->antsel_type = antsel_type; -+ -+ /* Update the antsel type for phy module to use */ -+ wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type); -+} -+ -+static void brcms_c_fatal_error(struct brcms_c_info *wlc) -+{ -+ wiphy_err(wlc->wiphy, "wl%d: fatal error, reinitializing\n", -+ wlc->pub->unit); -+ brcms_init(wlc->wl); -+} -+ -+static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw) -+{ -+ bool fatal = false; -+ uint unit; -+ uint intstatus, idx; -+ struct d11regs __iomem *regs = wlc_hw->regs; -+ struct wiphy *wiphy = wlc_hw->wlc->wiphy; -+ -+ unit = wlc_hw->unit; -+ -+ for (idx = 0; idx < NFIFO; idx++) { -+ /* read intstatus register and ignore any non-error bits */ -+ intstatus = -+ R_REG(®s->intctrlregs[idx].intstatus) & I_ERRORS; -+ if (!intstatus) -+ continue; -+ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: intstatus%d 0x%x\n", -+ unit, idx, intstatus); -+ -+ if (intstatus & I_RO) { -+ wiphy_err(wiphy, "wl%d: fifo %d: receive fifo " -+ "overflow\n", unit, idx); -+ fatal = true; -+ } -+ -+ if (intstatus & I_PC) { -+ wiphy_err(wiphy, "wl%d: fifo %d: descriptor error\n", -+ unit, idx); -+ fatal = true; -+ } -+ -+ if (intstatus & I_PD) { -+ wiphy_err(wiphy, "wl%d: fifo %d: data error\n", unit, -+ idx); -+ fatal = true; -+ } -+ -+ if (intstatus & I_DE) { -+ wiphy_err(wiphy, "wl%d: fifo %d: descriptor protocol " -+ "error\n", unit, idx); -+ fatal = true; -+ } -+ -+ if (intstatus & I_RU) -+ wiphy_err(wiphy, "wl%d: fifo %d: receive descriptor " -+ "underflow\n", idx, unit); -+ -+ if (intstatus & I_XU) { -+ wiphy_err(wiphy, "wl%d: fifo %d: transmit fifo " -+ "underflow\n", idx, unit); -+ fatal = true; -+ } -+ -+ if (fatal) { -+ brcms_c_fatal_error(wlc_hw->wlc); /* big hammer */ -+ break; -+ } else -+ W_REG(®s->intctrlregs[idx].intstatus, -+ intstatus); -+ } -+} -+ -+void brcms_c_intrson(struct brcms_c_info *wlc) -+{ -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ wlc->macintmask = wlc->defmacintmask; -+ W_REG(&wlc_hw->regs->macintmask, wlc->macintmask); -+} -+ -+/* -+ * callback for siutils.c, which has only wlc handler, no wl they both check -+ * up, not only because there is no need to off/restore d11 interrupt but also -+ * because per-port code may require sync with valid interrupt. -+ */ -+static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc) -+{ -+ if (!wlc->hw->up) -+ return 0; -+ -+ return brcms_intrsoff(wlc->wl); -+} -+ -+static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask) -+{ -+ if (!wlc->hw->up) -+ return; -+ -+ brcms_intrsrestore(wlc->wl, macintmask); -+} -+ -+u32 brcms_c_intrsoff(struct brcms_c_info *wlc) -+{ -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ u32 macintmask; -+ -+ if (!wlc_hw->clk) -+ return 0; -+ -+ macintmask = wlc->macintmask; /* isr can still happen */ -+ -+ W_REG(&wlc_hw->regs->macintmask, 0); -+ (void)R_REG(&wlc_hw->regs->macintmask); /* sync readback */ -+ udelay(1); /* ensure int line is no longer driven */ -+ wlc->macintmask = 0; -+ -+ /* return previous macintmask; resolve race between us and our isr */ -+ return wlc->macintstatus ? 0 : macintmask; -+} -+ -+void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask) -+{ -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ if (!wlc_hw->clk) -+ return; -+ -+ wlc->macintmask = macintmask; -+ W_REG(&wlc_hw->regs->macintmask, wlc->macintmask); -+} -+ -+static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw, -+ uint tx_fifo) -+{ -+ u8 fifo = 1 << tx_fifo; -+ -+ /* Two clients of this code, 11h Quiet period and scanning. */ -+ -+ /* only suspend if not already suspended */ -+ if ((wlc_hw->suspended_fifos & fifo) == fifo) -+ return; -+ -+ /* force the core awake only if not already */ -+ if (wlc_hw->suspended_fifos == 0) -+ brcms_c_ucode_wake_override_set(wlc_hw, -+ BRCMS_WAKE_OVERRIDE_TXFIFO); -+ -+ wlc_hw->suspended_fifos |= fifo; -+ -+ if (wlc_hw->di[tx_fifo]) { -+ /* -+ * Suspending AMPDU transmissions in the middle can cause -+ * underflow which may result in mismatch between ucode and -+ * driver so suspend the mac before suspending the FIFO -+ */ -+ if (BRCMS_PHY_11N_CAP(wlc_hw->band)) -+ brcms_c_suspend_mac_and_wait(wlc_hw->wlc); -+ -+ dma_txsuspend(wlc_hw->di[tx_fifo]); -+ -+ if (BRCMS_PHY_11N_CAP(wlc_hw->band)) -+ brcms_c_enable_mac(wlc_hw->wlc); -+ } -+} -+ -+static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw, -+ uint tx_fifo) -+{ -+ /* BMAC_NOTE: BRCMS_TX_FIFO_ENAB is done in brcms_c_dpc() for DMA case -+ * but need to be done here for PIO otherwise the watchdog will catch -+ * the inconsistency and fire -+ */ -+ /* Two clients of this code, 11h Quiet period and scanning. */ -+ if (wlc_hw->di[tx_fifo]) -+ dma_txresume(wlc_hw->di[tx_fifo]); -+ -+ /* allow core to sleep again */ -+ if (wlc_hw->suspended_fifos == 0) -+ return; -+ else { -+ wlc_hw->suspended_fifos &= ~(1 << tx_fifo); -+ if (wlc_hw->suspended_fifos == 0) -+ brcms_c_ucode_wake_override_clear(wlc_hw, -+ BRCMS_WAKE_OVERRIDE_TXFIFO); -+ } -+} -+ -+static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool on, u32 flags) -+{ -+ static const u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; -+ -+ if (on) { -+ /* suspend tx fifos */ -+ brcms_b_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO); -+ brcms_b_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO); -+ brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_BK_FIFO); -+ brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO); -+ -+ /* zero the address match register so we do not send ACKs */ -+ brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, -+ null_ether_addr); -+ } else { -+ /* resume tx fifos */ -+ brcms_b_tx_fifo_resume(wlc_hw, TX_DATA_FIFO); -+ brcms_b_tx_fifo_resume(wlc_hw, TX_CTL_FIFO); -+ brcms_b_tx_fifo_resume(wlc_hw, TX_AC_BK_FIFO); -+ brcms_b_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO); -+ -+ /* Restore address */ -+ brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, -+ wlc_hw->etheraddr); -+ } -+ -+ wlc_phy_mute_upd(wlc_hw->band->pi, on, flags); -+ -+ if (on) -+ brcms_c_ucode_mute_override_set(wlc_hw); -+ else -+ brcms_c_ucode_mute_override_clear(wlc_hw); -+} -+ -+/* -+ * Read and clear macintmask and macintstatus and intstatus registers. -+ * This routine should be called with interrupts off -+ * Return: -+ * -1 if brcms_deviceremoved(wlc) evaluates to true; -+ * 0 if the interrupt is not for us, or we are in some special cases; -+ * device interrupt status bits otherwise. -+ */ -+static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr) -+{ -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ struct d11regs __iomem *regs = wlc_hw->regs; -+ u32 macintstatus; -+ -+ /* macintstatus includes a DMA interrupt summary bit */ -+ macintstatus = R_REG(®s->macintstatus); -+ -+ BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit, -+ macintstatus); -+ -+ /* detect cardbus removed, in power down(suspend) and in reset */ -+ if (brcms_deviceremoved(wlc)) -+ return -1; -+ -+ /* brcms_deviceremoved() succeeds even when the core is still resetting, -+ * handle that case here. -+ */ -+ if (macintstatus == 0xffffffff) -+ return 0; -+ -+ /* defer unsolicited interrupts */ -+ macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask); -+ -+ /* if not for us */ -+ if (macintstatus == 0) -+ return 0; -+ -+ /* interrupts are already turned off for CFE build -+ * Caution: For CFE Turning off the interrupts again has some undesired -+ * consequences -+ */ -+ /* turn off the interrupts */ -+ W_REG(®s->macintmask, 0); -+ (void)R_REG(®s->macintmask); /* sync readback */ -+ wlc->macintmask = 0; -+ -+ /* clear device interrupts */ -+ W_REG(®s->macintstatus, macintstatus); -+ -+ /* MI_DMAINT is indication of non-zero intstatus */ -+ if (macintstatus & MI_DMAINT) -+ /* -+ * only fifo interrupt enabled is I_RI in -+ * RX_FIFO. If MI_DMAINT is set, assume it -+ * is set and clear the interrupt. -+ */ -+ W_REG(®s->intctrlregs[RX_FIFO].intstatus, -+ DEF_RXINTMASK); -+ -+ return macintstatus; -+} -+ -+/* Update wlc->macintstatus and wlc->intstatus[]. */ -+/* Return true if they are updated successfully. false otherwise */ -+bool brcms_c_intrsupd(struct brcms_c_info *wlc) -+{ -+ u32 macintstatus; -+ -+ /* read and clear macintstatus and intstatus registers */ -+ macintstatus = wlc_intstatus(wlc, false); -+ -+ /* device is removed */ -+ if (macintstatus == 0xffffffff) -+ return false; -+ -+ /* update interrupt status in software */ -+ wlc->macintstatus |= macintstatus; -+ -+ return true; -+} -+ -+/* -+ * First-level interrupt processing. -+ * Return true if this was our interrupt, false otherwise. -+ * *wantdpc will be set to true if further brcms_c_dpc() processing is required, -+ * false otherwise. -+ */ -+bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc) -+{ -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ u32 macintstatus; -+ -+ *wantdpc = false; -+ -+ if (!wlc_hw->up || !wlc->macintmask) -+ return false; -+ -+ /* read and clear macintstatus and intstatus registers */ -+ macintstatus = wlc_intstatus(wlc, true); -+ -+ if (macintstatus == 0xffffffff) -+ wiphy_err(wlc->wiphy, "DEVICEREMOVED detected in the ISR code" -+ " path\n"); -+ -+ /* it is not for us */ -+ if (macintstatus == 0) -+ return false; -+ -+ *wantdpc = true; -+ -+ /* save interrupt status bits */ -+ wlc->macintstatus = macintstatus; -+ -+ return true; -+ -+} -+ -+void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc) -+{ -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ struct d11regs __iomem *regs = wlc_hw->regs; -+ u32 mc, mi; -+ struct wiphy *wiphy = wlc->wiphy; -+ -+ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, -+ wlc_hw->band->bandunit); -+ -+ /* -+ * Track overlapping suspend requests -+ */ -+ wlc_hw->mac_suspend_depth++; -+ if (wlc_hw->mac_suspend_depth > 1) -+ return; -+ -+ /* force the core awake */ -+ brcms_c_ucode_wake_override_set(wlc_hw, BRCMS_WAKE_OVERRIDE_MACSUSPEND); -+ -+ mc = R_REG(®s->maccontrol); -+ -+ if (mc == 0xffffffff) { -+ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, -+ __func__); -+ brcms_down(wlc->wl); -+ return; -+ } -+ WARN_ON(mc & MCTL_PSM_JMP_0); -+ WARN_ON(!(mc & MCTL_PSM_RUN)); -+ WARN_ON(!(mc & MCTL_EN_MAC)); -+ -+ mi = R_REG(®s->macintstatus); -+ if (mi == 0xffffffff) { -+ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, -+ __func__); -+ brcms_down(wlc->wl); -+ return; -+ } -+ WARN_ON(mi & MI_MACSSPNDD); -+ -+ brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, 0); -+ -+ SPINWAIT(!(R_REG(®s->macintstatus) & MI_MACSSPNDD), -+ BRCMS_MAX_MAC_SUSPEND); -+ -+ if (!(R_REG(®s->macintstatus) & MI_MACSSPNDD)) { -+ wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS" -+ " and MI_MACSSPNDD is still not on.\n", -+ wlc_hw->unit, BRCMS_MAX_MAC_SUSPEND); -+ wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, " -+ "psm_brc 0x%04x\n", wlc_hw->unit, -+ R_REG(®s->psmdebug), -+ R_REG(®s->phydebug), -+ R_REG(®s->psm_brc)); -+ } -+ -+ mc = R_REG(®s->maccontrol); -+ if (mc == 0xffffffff) { -+ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, -+ __func__); -+ brcms_down(wlc->wl); -+ return; -+ } -+ WARN_ON(mc & MCTL_PSM_JMP_0); -+ WARN_ON(!(mc & MCTL_PSM_RUN)); -+ WARN_ON(mc & MCTL_EN_MAC); -+} -+ -+void brcms_c_enable_mac(struct brcms_c_info *wlc) -+{ -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ struct d11regs __iomem *regs = wlc_hw->regs; -+ u32 mc, mi; -+ -+ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, -+ wlc->band->bandunit); -+ -+ /* -+ * Track overlapping suspend requests -+ */ -+ wlc_hw->mac_suspend_depth--; -+ if (wlc_hw->mac_suspend_depth > 0) -+ return; -+ -+ mc = R_REG(®s->maccontrol); -+ WARN_ON(mc & MCTL_PSM_JMP_0); -+ WARN_ON(mc & MCTL_EN_MAC); -+ WARN_ON(!(mc & MCTL_PSM_RUN)); -+ -+ brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC); -+ W_REG(®s->macintstatus, MI_MACSSPNDD); -+ -+ mc = R_REG(®s->maccontrol); -+ WARN_ON(mc & MCTL_PSM_JMP_0); -+ WARN_ON(!(mc & MCTL_EN_MAC)); -+ WARN_ON(!(mc & MCTL_PSM_RUN)); -+ -+ mi = R_REG(®s->macintstatus); -+ WARN_ON(mi & MI_MACSSPNDD); -+ -+ brcms_c_ucode_wake_override_clear(wlc_hw, -+ BRCMS_WAKE_OVERRIDE_MACSUSPEND); -+} -+ -+void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode) -+{ -+ wlc_hw->hw_stf_ss_opmode = stf_mode; -+ -+ if (wlc_hw->clk) -+ brcms_upd_ofdm_pctl1_table(wlc_hw); -+} -+ -+static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw) -+{ -+ struct d11regs __iomem *regs; -+ u32 w, val; -+ struct wiphy *wiphy = wlc_hw->wlc->wiphy; -+ -+ BCMMSG(wiphy, "wl%d\n", wlc_hw->unit); -+ -+ regs = wlc_hw->regs; -+ -+ /* Validate dchip register access */ -+ -+ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); -+ (void)R_REG(®s->objaddr); -+ w = R_REG(®s->objdata); -+ -+ /* Can we write and read back a 32bit register? */ -+ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); -+ (void)R_REG(®s->objaddr); -+ W_REG(®s->objdata, (u32) 0xaa5555aa); -+ -+ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); -+ (void)R_REG(®s->objaddr); -+ val = R_REG(®s->objdata); -+ if (val != (u32) 0xaa5555aa) { -+ wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, " -+ "expected 0xaa5555aa\n", wlc_hw->unit, val); -+ return false; -+ } -+ -+ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); -+ (void)R_REG(®s->objaddr); -+ W_REG(®s->objdata, (u32) 0x55aaaa55); -+ -+ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); -+ (void)R_REG(®s->objaddr); -+ val = R_REG(®s->objdata); -+ if (val != (u32) 0x55aaaa55) { -+ wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, " -+ "expected 0x55aaaa55\n", wlc_hw->unit, val); -+ return false; -+ } -+ -+ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); -+ (void)R_REG(®s->objaddr); -+ W_REG(®s->objdata, w); -+ -+ /* clear CFPStart */ -+ W_REG(®s->tsf_cfpstart, 0); -+ -+ w = R_REG(®s->maccontrol); -+ if ((w != (MCTL_IHR_EN | MCTL_WAKE)) && -+ (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) { -+ wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = " -+ "0x%x, expected 0x%x or 0x%x\n", wlc_hw->unit, w, -+ (MCTL_IHR_EN | MCTL_WAKE), -+ (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE)); -+ return false; -+ } -+ -+ return true; -+} -+ -+#define PHYPLL_WAIT_US 100000 -+ -+void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on) -+{ -+ struct d11regs __iomem *regs; -+ u32 tmp; -+ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ tmp = 0; -+ regs = wlc_hw->regs; -+ -+ if (on) { -+ if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) { -+ OR_REG(®s->clk_ctl_st, -+ (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL | -+ CCS_ERSRC_REQ_PHYPLL)); -+ SPINWAIT((R_REG(®s->clk_ctl_st) & -+ (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT), -+ PHYPLL_WAIT_US); -+ -+ tmp = R_REG(®s->clk_ctl_st); -+ if ((tmp & (CCS_ERSRC_AVAIL_HT)) != -+ (CCS_ERSRC_AVAIL_HT)) -+ wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY" -+ " PLL failed\n", __func__); -+ } else { -+ OR_REG(®s->clk_ctl_st, -+ (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL)); -+ SPINWAIT((R_REG(®s->clk_ctl_st) & -+ (CCS_ERSRC_AVAIL_D11PLL | -+ CCS_ERSRC_AVAIL_PHYPLL)) != -+ (CCS_ERSRC_AVAIL_D11PLL | -+ CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US); -+ -+ tmp = R_REG(®s->clk_ctl_st); -+ if ((tmp & -+ (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) -+ != -+ (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) -+ wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on " -+ "PHY PLL failed\n", __func__); -+ } -+ } else { -+ /* -+ * Since the PLL may be shared, other cores can still -+ * be requesting it; so we'll deassert the request but -+ * not wait for status to comply. -+ */ -+ AND_REG(®s->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL); -+ tmp = R_REG(®s->clk_ctl_st); -+ } -+} -+ -+static void brcms_c_coredisable(struct brcms_hardware *wlc_hw) -+{ -+ bool dev_gone; -+ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ dev_gone = brcms_deviceremoved(wlc_hw->wlc); -+ -+ if (dev_gone) -+ return; -+ -+ if (wlc_hw->noreset) -+ return; -+ -+ /* radio off */ -+ wlc_phy_switch_radio(wlc_hw->band->pi, OFF); -+ -+ /* turn off analog core */ -+ wlc_phy_anacore(wlc_hw->band->pi, OFF); -+ -+ /* turn off PHYPLL to save power */ -+ brcms_b_core_phypll_ctl(wlc_hw, false); -+ -+ wlc_hw->clk = false; -+ ai_core_disable(wlc_hw->sih, 0); -+ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); -+} -+ -+static void brcms_c_flushqueues(struct brcms_c_info *wlc) -+{ -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ uint i; -+ -+ /* free any posted tx packets */ -+ for (i = 0; i < NFIFO; i++) -+ if (wlc_hw->di[i]) { -+ dma_txreclaim(wlc_hw->di[i], DMA_RANGE_ALL); -+ wlc->core->txpktpend[i] = 0; -+ BCMMSG(wlc->wiphy, "pktpend fifo %d clrd\n", i); -+ } -+ -+ /* free any posted rx packets */ -+ dma_rxreclaim(wlc_hw->di[RX_FIFO]); -+} -+ -+static u16 -+brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel) -+{ -+ struct d11regs __iomem *regs = wlc_hw->regs; -+ u16 __iomem *objdata_lo = (u16 __iomem *)®s->objdata; -+ u16 __iomem *objdata_hi = objdata_lo + 1; -+ u16 v; -+ -+ W_REG(®s->objaddr, sel | (offset >> 2)); -+ (void)R_REG(®s->objaddr); -+ if (offset & 2) -+ v = R_REG(objdata_hi); -+ else -+ v = R_REG(objdata_lo); -+ -+ return v; -+} -+ -+static void -+brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, u16 v, -+ u32 sel) -+{ -+ struct d11regs __iomem *regs = wlc_hw->regs; -+ u16 __iomem *objdata_lo = (u16 __iomem *)®s->objdata; -+ u16 __iomem *objdata_hi = objdata_lo + 1; -+ -+ W_REG(®s->objaddr, sel | (offset >> 2)); -+ (void)R_REG(®s->objaddr); -+ if (offset & 2) -+ W_REG(objdata_hi, v); -+ else -+ W_REG(objdata_lo, v); -+} -+ -+/* -+ * Read a single u16 from shared memory. -+ * SHM 'offset' needs to be an even address -+ */ -+u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset) -+{ -+ return brcms_b_read_objmem(wlc_hw, offset, OBJADDR_SHM_SEL); -+} -+ -+/* -+ * Write a single u16 to shared memory. -+ * SHM 'offset' needs to be an even address -+ */ -+void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, u16 v) -+{ -+ brcms_b_write_objmem(wlc_hw, offset, v, OBJADDR_SHM_SEL); -+} -+ -+/* -+ * Copy a buffer to shared memory of specified type . -+ * SHM 'offset' needs to be an even address and -+ * Buffer length 'len' must be an even number of bytes -+ * 'sel' selects the type of memory -+ */ -+void -+brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, uint offset, -+ const void *buf, int len, u32 sel) -+{ -+ u16 v; -+ const u8 *p = (const u8 *)buf; -+ int i; -+ -+ if (len <= 0 || (offset & 1) || (len & 1)) -+ return; -+ -+ for (i = 0; i < len; i += 2) { -+ v = p[i] | (p[i + 1] << 8); -+ brcms_b_write_objmem(wlc_hw, offset + i, v, sel); -+ } -+} -+ -+/* -+ * Copy a piece of shared memory of specified type to a buffer . -+ * SHM 'offset' needs to be an even address and -+ * Buffer length 'len' must be an even number of bytes -+ * 'sel' selects the type of memory -+ */ -+void -+brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, void *buf, -+ int len, u32 sel) -+{ -+ u16 v; -+ u8 *p = (u8 *) buf; -+ int i; -+ -+ if (len <= 0 || (offset & 1) || (len & 1)) -+ return; -+ -+ for (i = 0; i < len; i += 2) { -+ v = brcms_b_read_objmem(wlc_hw, offset + i, sel); -+ p[i] = v & 0xFF; -+ p[i + 1] = (v >> 8) & 0xFF; -+ } -+} -+ -+/* Copy a buffer to shared memory. -+ * SHM 'offset' needs to be an even address and -+ * Buffer length 'len' must be an even number of bytes -+ */ -+static void brcms_c_copyto_shm(struct brcms_c_info *wlc, uint offset, -+ const void *buf, int len) -+{ -+ brcms_b_copyto_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL); -+} -+ -+static void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw, -+ u16 SRL, u16 LRL) -+{ -+ wlc_hw->SRL = SRL; -+ wlc_hw->LRL = LRL; -+ -+ /* write retry limit to SCR, shouldn't need to suspend */ -+ if (wlc_hw->up) { -+ W_REG(&wlc_hw->regs->objaddr, -+ OBJADDR_SCR_SEL | S_DOT11_SRC_LMT); -+ (void)R_REG(&wlc_hw->regs->objaddr); -+ W_REG(&wlc_hw->regs->objdata, wlc_hw->SRL); -+ W_REG(&wlc_hw->regs->objaddr, -+ OBJADDR_SCR_SEL | S_DOT11_LRC_LMT); -+ (void)R_REG(&wlc_hw->regs->objaddr); -+ W_REG(&wlc_hw->regs->objdata, wlc_hw->LRL); -+ } -+} -+ -+static void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set, u32 req_bit) -+{ -+ if (set) { -+ if (mboolisset(wlc_hw->pllreq, req_bit)) -+ return; -+ -+ mboolset(wlc_hw->pllreq, req_bit); -+ -+ if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) { -+ if (!wlc_hw->sbclk) -+ brcms_b_xtal(wlc_hw, ON); -+ } -+ } else { -+ if (!mboolisset(wlc_hw->pllreq, req_bit)) -+ return; -+ -+ mboolclr(wlc_hw->pllreq, req_bit); -+ -+ if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) { -+ if (wlc_hw->sbclk) -+ brcms_b_xtal(wlc_hw, OFF); -+ } -+ } -+} -+ -+static void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail) -+{ -+ wlc_hw->antsel_avail = antsel_avail; -+} -+ -+/* -+ * conditions under which the PM bit should be set in outgoing frames -+ * and STAY_AWAKE is meaningful -+ */ -+static bool brcms_c_ps_allowed(struct brcms_c_info *wlc) -+{ -+ struct brcms_bss_cfg *cfg = wlc->bsscfg; -+ -+ /* disallow PS when one of the following global conditions meets */ -+ if (!wlc->pub->associated) -+ return false; -+ -+ /* disallow PS when one of these meets when not scanning */ -+ if (wlc->monitor) -+ return false; -+ -+ if (cfg->associated) { -+ /* -+ * disallow PS when one of the following -+ * bsscfg specific conditions meets -+ */ -+ if (!cfg->BSS) -+ return false; -+ -+ return false; -+ } -+ -+ return true; -+} -+ -+static void brcms_c_statsupd(struct brcms_c_info *wlc) -+{ -+ int i; -+ struct macstat macstats; -+#ifdef BCMDBG -+ u16 delta; -+ u16 rxf0ovfl; -+ u16 txfunfl[NFIFO]; -+#endif /* BCMDBG */ -+ -+ /* if driver down, make no sense to update stats */ -+ if (!wlc->pub->up) -+ return; -+ -+#ifdef BCMDBG -+ /* save last rx fifo 0 overflow count */ -+ rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl; -+ -+ /* save last tx fifo underflow count */ -+ for (i = 0; i < NFIFO; i++) -+ txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i]; -+#endif /* BCMDBG */ -+ -+ /* Read mac stats from contiguous shared memory */ -+ brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, &macstats, -+ sizeof(struct macstat), OBJADDR_SHM_SEL); -+ -+#ifdef BCMDBG -+ /* check for rx fifo 0 overflow */ -+ delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl); -+ if (delta) -+ wiphy_err(wlc->wiphy, "wl%d: %u rx fifo 0 overflows!\n", -+ wlc->pub->unit, delta); -+ -+ /* check for tx fifo underflows */ -+ for (i = 0; i < NFIFO; i++) { -+ delta = -+ (u16) (wlc->core->macstat_snapshot->txfunfl[i] - -+ txfunfl[i]); -+ if (delta) -+ wiphy_err(wlc->wiphy, "wl%d: %u tx fifo %d underflows!" -+ "\n", wlc->pub->unit, delta, i); -+ } -+#endif /* BCMDBG */ -+ -+ /* merge counters from dma module */ -+ for (i = 0; i < NFIFO; i++) { -+ if (wlc->hw->di[i]) -+ dma_counterreset(wlc->hw->di[i]); -+ } -+} -+ -+static void brcms_b_reset(struct brcms_hardware *wlc_hw) -+{ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ /* reset the core */ -+ if (!brcms_deviceremoved(wlc_hw->wlc)) -+ brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); -+ -+ /* purge the dma rings */ -+ brcms_c_flushqueues(wlc_hw->wlc); -+} -+ -+void brcms_c_reset(struct brcms_c_info *wlc) -+{ -+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); -+ -+ /* slurp up hw mac counters before core reset */ -+ brcms_c_statsupd(wlc); -+ -+ /* reset our snapshot of macstat counters */ -+ memset((char *)wlc->core->macstat_snapshot, 0, -+ sizeof(struct macstat)); -+ -+ brcms_b_reset(wlc->hw); -+} -+ -+/* Return the channel the driver should initialize during brcms_c_init. -+ * the channel may have to be changed from the currently configured channel -+ * if other configurations are in conflict (bandlocked, 11n mode disabled, -+ * invalid channel for current country, etc.) -+ */ -+static u16 brcms_c_init_chanspec(struct brcms_c_info *wlc) -+{ -+ u16 chanspec = -+ 1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE | -+ WL_CHANSPEC_BAND_2G; -+ -+ return chanspec; -+} -+ -+void brcms_c_init_scb(struct scb *scb) -+{ -+ int i; -+ -+ memset(scb, 0, sizeof(struct scb)); -+ scb->flags = SCB_WMECAP | SCB_HTCAP; -+ for (i = 0; i < NUMPRIO; i++) { -+ scb->seqnum[i] = 0; -+ scb->seqctl[i] = 0xFFFF; -+ } -+ -+ scb->seqctl_nonqos = 0xFFFF; -+ scb->magic = SCB_MAGIC; -+} -+ -+/* d11 core init -+ * reset PSM -+ * download ucode/PCM -+ * let ucode run to suspended -+ * download ucode inits -+ * config other core registers -+ * init dma -+ */ -+static void brcms_b_coreinit(struct brcms_c_info *wlc) -+{ -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ struct d11regs __iomem *regs; -+ u32 sflags; -+ uint bcnint_us; -+ uint i = 0; -+ bool fifosz_fixup = false; -+ int err = 0; -+ u16 buf[NFIFO]; -+ struct wiphy *wiphy = wlc->wiphy; -+ struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode; -+ -+ regs = wlc_hw->regs; -+ -+ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ /* reset PSM */ -+ brcms_b_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE)); -+ -+ brcms_ucode_download(wlc_hw); -+ /* -+ * FIFOSZ fixup. driver wants to controls the fifo allocation. -+ */ -+ fifosz_fixup = true; -+ -+ /* let the PSM run to the suspended state, set mode to BSS STA */ -+ W_REG(®s->macintstatus, -1); -+ brcms_b_mctrl(wlc_hw, ~0, -+ (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE)); -+ -+ /* wait for ucode to self-suspend after auto-init */ -+ SPINWAIT(((R_REG(®s->macintstatus) & MI_MACSSPNDD) == 0), -+ 1000 * 1000); -+ if ((R_REG(®s->macintstatus) & MI_MACSSPNDD) == 0) -+ wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-" -+ "suspend!\n", wlc_hw->unit); -+ -+ brcms_c_gpio_init(wlc); -+ -+ sflags = ai_core_sflags(wlc_hw->sih, 0, 0); -+ -+ if (D11REV_IS(wlc_hw->corerev, 23)) { -+ if (BRCMS_ISNPHY(wlc_hw->band)) -+ brcms_c_write_inits(wlc_hw, ucode->d11n0initvals16); -+ else -+ wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" -+ " %d\n", __func__, wlc_hw->unit, -+ wlc_hw->corerev); -+ } else if (D11REV_IS(wlc_hw->corerev, 24)) { -+ if (BRCMS_ISLCNPHY(wlc_hw->band)) -+ brcms_c_write_inits(wlc_hw, ucode->d11lcn0initvals24); -+ else -+ wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" -+ " %d\n", __func__, wlc_hw->unit, -+ wlc_hw->corerev); -+ } else { -+ wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n", -+ __func__, wlc_hw->unit, wlc_hw->corerev); -+ } -+ -+ /* For old ucode, txfifo sizes needs to be modified(increased) */ -+ if (fifosz_fixup == true) -+ brcms_b_corerev_fifofixup(wlc_hw); -+ -+ /* check txfifo allocations match between ucode and driver */ -+ buf[TX_AC_BE_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE0); -+ if (buf[TX_AC_BE_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]) { -+ i = TX_AC_BE_FIFO; -+ err = -1; -+ } -+ buf[TX_AC_VI_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE1); -+ if (buf[TX_AC_VI_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]) { -+ i = TX_AC_VI_FIFO; -+ err = -1; -+ } -+ buf[TX_AC_BK_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE2); -+ buf[TX_AC_VO_FIFO] = (buf[TX_AC_BK_FIFO] >> 8) & 0xff; -+ buf[TX_AC_BK_FIFO] &= 0xff; -+ if (buf[TX_AC_BK_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BK_FIFO]) { -+ i = TX_AC_BK_FIFO; -+ err = -1; -+ } -+ if (buf[TX_AC_VO_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO]) { -+ i = TX_AC_VO_FIFO; -+ err = -1; -+ } -+ buf[TX_BCMC_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE3); -+ buf[TX_ATIM_FIFO] = (buf[TX_BCMC_FIFO] >> 8) & 0xff; -+ buf[TX_BCMC_FIFO] &= 0xff; -+ if (buf[TX_BCMC_FIFO] != wlc_hw->xmtfifo_sz[TX_BCMC_FIFO]) { -+ i = TX_BCMC_FIFO; -+ err = -1; -+ } -+ if (buf[TX_ATIM_FIFO] != wlc_hw->xmtfifo_sz[TX_ATIM_FIFO]) { -+ i = TX_ATIM_FIFO; -+ err = -1; -+ } -+ if (err != 0) -+ wiphy_err(wiphy, "wlc_coreinit: txfifo mismatch: ucode size %d" -+ " driver size %d index %d\n", buf[i], -+ wlc_hw->xmtfifo_sz[i], i); -+ -+ /* make sure we can still talk to the mac */ -+ WARN_ON(R_REG(®s->maccontrol) == 0xffffffff); -+ -+ /* band-specific inits done by wlc_bsinit() */ -+ -+ /* Set up frame burst size and antenna swap threshold init values */ -+ brcms_b_write_shm(wlc_hw, M_MBURST_SIZE, MAXTXFRAMEBURST); -+ brcms_b_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT); -+ -+ /* enable one rx interrupt per received frame */ -+ W_REG(®s->intrcvlazy[0], (1 << IRL_FC_SHIFT)); -+ -+ /* set the station mode (BSS STA) */ -+ brcms_b_mctrl(wlc_hw, -+ (MCTL_INFRA | MCTL_DISCARD_PMQ | MCTL_AP), -+ (MCTL_INFRA | MCTL_DISCARD_PMQ)); -+ -+ /* set up Beacon interval */ -+ bcnint_us = 0x8000 << 10; -+ W_REG(®s->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT)); -+ W_REG(®s->tsf_cfpstart, bcnint_us); -+ W_REG(®s->macintstatus, MI_GP1); -+ -+ /* write interrupt mask */ -+ W_REG(®s->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK); -+ -+ /* allow the MAC to control the PHY clock (dynamic on/off) */ -+ brcms_b_macphyclk_set(wlc_hw, ON); -+ -+ /* program dynamic clock control fast powerup delay register */ -+ wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih); -+ W_REG(®s->scc_fastpwrup_dly, wlc->fastpwrup_dly); -+ -+ /* tell the ucode the corerev */ -+ brcms_b_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev); -+ -+ /* tell the ucode MAC capabilities */ -+ brcms_b_write_shm(wlc_hw, M_MACHW_CAP_L, -+ (u16) (wlc_hw->machwcap & 0xffff)); -+ brcms_b_write_shm(wlc_hw, M_MACHW_CAP_H, -+ (u16) ((wlc_hw-> -+ machwcap >> 16) & 0xffff)); -+ -+ /* write retry limits to SCR, this done after PSM init */ -+ W_REG(®s->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT); -+ (void)R_REG(®s->objaddr); -+ W_REG(®s->objdata, wlc_hw->SRL); -+ W_REG(®s->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT); -+ (void)R_REG(®s->objaddr); -+ W_REG(®s->objdata, wlc_hw->LRL); -+ -+ /* write rate fallback retry limits */ -+ brcms_b_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL); -+ brcms_b_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL); -+ -+ AND_REG(®s->ifs_ctl, 0x0FFF); -+ W_REG(®s->ifs_aifsn, EDCF_AIFSN_MIN); -+ -+ /* init the tx dma engines */ -+ for (i = 0; i < NFIFO; i++) { -+ if (wlc_hw->di[i]) -+ dma_txinit(wlc_hw->di[i]); -+ } -+ -+ /* init the rx dma engine(s) and post receive buffers */ -+ dma_rxinit(wlc_hw->di[RX_FIFO]); -+ dma_rxfill(wlc_hw->di[RX_FIFO]); -+} -+ -+void -+static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec, -+ bool mute) { -+ u32 macintmask; -+ bool fastclk; -+ struct brcms_c_info *wlc = wlc_hw->wlc; -+ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ /* request FAST clock if not on */ -+ fastclk = wlc_hw->forcefastclk; -+ if (!fastclk) -+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); -+ -+ /* disable interrupts */ -+ macintmask = brcms_intrsoff(wlc->wl); -+ -+ /* set up the specified band and chanspec */ -+ brcms_c_setxband(wlc_hw, chspec_bandunit(chanspec)); -+ wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec); -+ -+ /* do one-time phy inits and calibration */ -+ wlc_phy_cal_init(wlc_hw->band->pi); -+ -+ /* core-specific initialization */ -+ brcms_b_coreinit(wlc); -+ -+ /* suspend the tx fifos and mute the phy for preism cac time */ -+ if (mute) -+ brcms_b_mute(wlc_hw, ON, PHY_MUTE_FOR_PREISM); -+ -+ /* band-specific inits */ -+ brcms_b_bsinit(wlc, chanspec); -+ -+ /* restore macintmask */ -+ brcms_intrsrestore(wlc->wl, macintmask); -+ -+ /* seed wake_override with BRCMS_WAKE_OVERRIDE_MACSUSPEND since the mac -+ * is suspended and brcms_c_enable_mac() will clear this override bit. -+ */ -+ mboolset(wlc_hw->wake_override, BRCMS_WAKE_OVERRIDE_MACSUSPEND); -+ -+ /* -+ * initialize mac_suspend_depth to 1 to match ucode -+ * initial suspended state -+ */ -+ wlc_hw->mac_suspend_depth = 1; -+ -+ /* restore the clk */ -+ if (!fastclk) -+ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); -+} -+ -+static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc, -+ u16 chanspec) -+{ -+ /* Save our copy of the chanspec */ -+ wlc->chanspec = chanspec; -+ -+ /* Set the chanspec and power limits for this locale */ -+ brcms_c_channel_set_chanspec(wlc->cmi, chanspec, BRCMS_TXPWR_MAX); -+ -+ if (wlc->stf->ss_algosel_auto) -+ brcms_c_stf_ss_algo_channel_get(wlc, &wlc->stf->ss_algo_channel, -+ chanspec); -+ -+ brcms_c_stf_ss_update(wlc, wlc->band); -+} -+ -+static void -+brcms_default_rateset(struct brcms_c_info *wlc, struct brcms_c_rateset *rs) -+{ -+ brcms_c_rateset_default(rs, NULL, wlc->band->phytype, -+ wlc->band->bandtype, false, BRCMS_RATE_MASK_FULL, -+ (bool) (wlc->pub->_n_enab & SUPPORT_11N), -+ brcms_chspec_bw(wlc->default_bss->chanspec), -+ wlc->stf->txstreams); -+} -+ -+/* derive wlc->band->basic_rate[] table from 'rateset' */ -+static void brcms_c_rate_lookup_init(struct brcms_c_info *wlc, -+ struct brcms_c_rateset *rateset) -+{ -+ u8 rate; -+ u8 mandatory; -+ u8 cck_basic = 0; -+ u8 ofdm_basic = 0; -+ u8 *br = wlc->band->basic_rate; -+ uint i; -+ -+ /* incoming rates are in 500kbps units as in 802.11 Supported Rates */ -+ memset(br, 0, BRCM_MAXRATE + 1); -+ -+ /* For each basic rate in the rates list, make an entry in the -+ * best basic lookup. -+ */ -+ for (i = 0; i < rateset->count; i++) { -+ /* only make an entry for a basic rate */ -+ if (!(rateset->rates[i] & BRCMS_RATE_FLAG)) -+ continue; -+ -+ /* mask off basic bit */ -+ rate = (rateset->rates[i] & BRCMS_RATE_MASK); -+ -+ if (rate > BRCM_MAXRATE) { -+ wiphy_err(wlc->wiphy, "brcms_c_rate_lookup_init: " -+ "invalid rate 0x%X in rate set\n", -+ rateset->rates[i]); -+ continue; -+ } -+ -+ br[rate] = rate; -+ } -+ -+ /* The rate lookup table now has non-zero entries for each -+ * basic rate, equal to the basic rate: br[basicN] = basicN -+ * -+ * To look up the best basic rate corresponding to any -+ * particular rate, code can use the basic_rate table -+ * like this -+ * -+ * basic_rate = wlc->band->basic_rate[tx_rate] -+ * -+ * Make sure there is a best basic rate entry for -+ * every rate by walking up the table from low rates -+ * to high, filling in holes in the lookup table -+ */ -+ -+ for (i = 0; i < wlc->band->hw_rateset.count; i++) { -+ rate = wlc->band->hw_rateset.rates[i]; -+ -+ if (br[rate] != 0) { -+ /* This rate is a basic rate. -+ * Keep track of the best basic rate so far by -+ * modulation type. -+ */ -+ if (is_ofdm_rate(rate)) -+ ofdm_basic = rate; -+ else -+ cck_basic = rate; -+ -+ continue; -+ } -+ -+ /* This rate is not a basic rate so figure out the -+ * best basic rate less than this rate and fill in -+ * the hole in the table -+ */ -+ -+ br[rate] = is_ofdm_rate(rate) ? ofdm_basic : cck_basic; -+ -+ if (br[rate] != 0) -+ continue; -+ -+ if (is_ofdm_rate(rate)) { -+ /* -+ * In 11g and 11a, the OFDM mandatory rates -+ * are 6, 12, and 24 Mbps -+ */ -+ if (rate >= BRCM_RATE_24M) -+ mandatory = BRCM_RATE_24M; -+ else if (rate >= BRCM_RATE_12M) -+ mandatory = BRCM_RATE_12M; -+ else -+ mandatory = BRCM_RATE_6M; -+ } else { -+ /* In 11b, all CCK rates are mandatory 1 - 11 Mbps */ -+ mandatory = rate; -+ } -+ -+ br[rate] = mandatory; -+ } -+} -+ -+static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc, -+ u16 chanspec) -+{ -+ struct brcms_c_rateset default_rateset; -+ uint parkband; -+ uint i, band_order[2]; -+ -+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); -+ /* -+ * We might have been bandlocked during down and the chip -+ * power-cycled (hibernate). Figure out the right band to park on -+ */ -+ if (wlc->bandlocked || wlc->pub->_nbands == 1) { -+ /* updated in brcms_c_bandlock() */ -+ parkband = wlc->band->bandunit; -+ band_order[0] = band_order[1] = parkband; -+ } else { -+ /* park on the band of the specified chanspec */ -+ parkband = chspec_bandunit(chanspec); -+ -+ /* order so that parkband initialize last */ -+ band_order[0] = parkband ^ 1; -+ band_order[1] = parkband; -+ } -+ -+ /* make each band operational, software state init */ -+ for (i = 0; i < wlc->pub->_nbands; i++) { -+ uint j = band_order[i]; -+ -+ wlc->band = wlc->bandstate[j]; -+ -+ brcms_default_rateset(wlc, &default_rateset); -+ -+ /* fill in hw_rate */ -+ brcms_c_rateset_filter(&default_rateset, &wlc->band->hw_rateset, -+ false, BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK, -+ (bool) (wlc->pub->_n_enab & SUPPORT_11N)); -+ -+ /* init basic rate lookup */ -+ brcms_c_rate_lookup_init(wlc, &default_rateset); -+ } -+ -+ /* sync up phy/radio chanspec */ -+ brcms_c_set_phy_chanspec(wlc, chanspec); -+} -+ -+static void brcms_c_mac_bcn_promisc(struct brcms_c_info *wlc) -+{ -+ if (wlc->bcnmisc_monitor) -+ brcms_b_mctrl(wlc->hw, MCTL_BCNS_PROMISC, MCTL_BCNS_PROMISC); -+ else -+ brcms_b_mctrl(wlc->hw, MCTL_BCNS_PROMISC, 0); -+} -+ -+void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc, bool promisc) -+{ -+ wlc->bcnmisc_monitor = promisc; -+ brcms_c_mac_bcn_promisc(wlc); -+} -+ -+/* set or clear maccontrol bits MCTL_PROMISC and MCTL_KEEPCONTROL */ -+static void brcms_c_mac_promisc(struct brcms_c_info *wlc) -+{ -+ u32 promisc_bits = 0; -+ -+ /* -+ * promiscuous mode just sets MCTL_PROMISC -+ * Note: APs get all BSS traffic without the need to set -+ * the MCTL_PROMISC bit since all BSS data traffic is -+ * directed at the AP -+ */ -+ if (wlc->pub->promisc) -+ promisc_bits |= MCTL_PROMISC; -+ -+ /* monitor mode needs both MCTL_PROMISC and MCTL_KEEPCONTROL -+ * Note: monitor mode also needs MCTL_BCNS_PROMISC, but that is -+ * handled in brcms_c_mac_bcn_promisc() -+ */ -+ if (wlc->monitor) -+ promisc_bits |= MCTL_PROMISC | MCTL_KEEPCONTROL; -+ -+ brcms_b_mctrl(wlc->hw, MCTL_PROMISC | MCTL_KEEPCONTROL, promisc_bits); -+} -+ -+/* -+ * ucode, hwmac update -+ * Channel dependent updates for ucode and hw -+ */ -+static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc) -+{ -+ /* enable or disable any active IBSSs depending on whether or not -+ * we are on the home channel -+ */ -+ if (wlc->home_chanspec == wlc_phy_chanspec_get(wlc->band->pi)) { -+ if (wlc->pub->associated) { -+ /* -+ * BMAC_NOTE: This is something that should be fixed -+ * in ucode inits. I think that the ucode inits set -+ * up the bcn templates and shm values with a bogus -+ * beacon. This should not be done in the inits. If -+ * ucode needs to set up a beacon for testing, the -+ * test routines should write it down, not expect the -+ * inits to populate a bogus beacon. -+ */ -+ if (BRCMS_PHY_11N_CAP(wlc->band)) -+ brcms_b_write_shm(wlc->hw, -+ M_BCN_TXTSF_OFFSET, 0); -+ } -+ } else { -+ /* disable an active IBSS if we are not on the home channel */ -+ } -+ -+ /* update the various promisc bits */ -+ brcms_c_mac_bcn_promisc(wlc); -+ brcms_c_mac_promisc(wlc); -+} -+ -+static void brcms_c_write_rate_shm(struct brcms_c_info *wlc, u8 rate, -+ u8 basic_rate) -+{ -+ u8 phy_rate, index; -+ u8 basic_phy_rate, basic_index; -+ u16 dir_table, basic_table; -+ u16 basic_ptr; -+ -+ /* Shared memory address for the table we are reading */ -+ dir_table = is_ofdm_rate(basic_rate) ? M_RT_DIRMAP_A : M_RT_DIRMAP_B; -+ -+ /* Shared memory address for the table we are writing */ -+ basic_table = is_ofdm_rate(rate) ? M_RT_BBRSMAP_A : M_RT_BBRSMAP_B; -+ -+ /* -+ * for a given rate, the LS-nibble of the PLCP SIGNAL field is -+ * the index into the rate table. -+ */ -+ phy_rate = rate_info[rate] & BRCMS_RATE_MASK; -+ basic_phy_rate = rate_info[basic_rate] & BRCMS_RATE_MASK; -+ index = phy_rate & 0xf; -+ basic_index = basic_phy_rate & 0xf; -+ -+ /* Find the SHM pointer to the ACK rate entry by looking in the -+ * Direct-map Table -+ */ -+ basic_ptr = brcms_b_read_shm(wlc->hw, (dir_table + basic_index * 2)); -+ -+ /* Update the SHM BSS-basic-rate-set mapping table with the pointer -+ * to the correct basic rate for the given incoming rate -+ */ -+ brcms_b_write_shm(wlc->hw, (basic_table + index * 2), basic_ptr); -+} -+ -+static const struct brcms_c_rateset * -+brcms_c_rateset_get_hwrs(struct brcms_c_info *wlc) -+{ -+ const struct brcms_c_rateset *rs_dflt; -+ -+ if (BRCMS_PHY_11N_CAP(wlc->band)) { -+ if (wlc->band->bandtype == BRCM_BAND_5G) -+ rs_dflt = &ofdm_mimo_rates; -+ else -+ rs_dflt = &cck_ofdm_mimo_rates; -+ } else if (wlc->band->gmode) -+ rs_dflt = &cck_ofdm_rates; -+ else -+ rs_dflt = &cck_rates; -+ -+ return rs_dflt; -+} -+ -+static void brcms_c_set_ratetable(struct brcms_c_info *wlc) -+{ -+ const struct brcms_c_rateset *rs_dflt; -+ struct brcms_c_rateset rs; -+ u8 rate, basic_rate; -+ uint i; -+ -+ rs_dflt = brcms_c_rateset_get_hwrs(wlc); -+ -+ brcms_c_rateset_copy(rs_dflt, &rs); -+ brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams); -+ -+ /* walk the phy rate table and update SHM basic rate lookup table */ -+ for (i = 0; i < rs.count; i++) { -+ rate = rs.rates[i] & BRCMS_RATE_MASK; -+ -+ /* for a given rate brcms_basic_rate returns the rate at -+ * which a response ACK/CTS should be sent. -+ */ -+ basic_rate = brcms_basic_rate(wlc, rate); -+ if (basic_rate == 0) -+ /* This should only happen if we are using a -+ * restricted rateset. -+ */ -+ basic_rate = rs.rates[0] & BRCMS_RATE_MASK; -+ -+ brcms_c_write_rate_shm(wlc, rate, basic_rate); -+ } -+} -+ -+/* band-specific init */ -+static void brcms_c_bsinit(struct brcms_c_info *wlc) -+{ -+ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", -+ wlc->pub->unit, wlc->band->bandunit); -+ -+ /* write ucode ACK/CTS rate table */ -+ brcms_c_set_ratetable(wlc); -+ -+ /* update some band specific mac configuration */ -+ brcms_c_ucode_mac_upd(wlc); -+ -+ /* init antenna selection */ -+ brcms_c_antsel_init(wlc->asi); -+ -+} -+ -+/* formula: IDLE_BUSY_RATIO_X_16 = (100-duty_cycle)/duty_cycle*16 */ -+static int -+brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM, -+ bool writeToShm) -+{ -+ int idle_busy_ratio_x_16 = 0; -+ uint offset = -+ isOFDM ? M_TX_IDLE_BUSY_RATIO_X_16_OFDM : -+ M_TX_IDLE_BUSY_RATIO_X_16_CCK; -+ if (duty_cycle > 100 || duty_cycle < 0) { -+ wiphy_err(wlc->wiphy, "wl%d: duty cycle value off limit\n", -+ wlc->pub->unit); -+ return -EINVAL; -+ } -+ if (duty_cycle) -+ idle_busy_ratio_x_16 = (100 - duty_cycle) * 16 / duty_cycle; -+ /* Only write to shared memory when wl is up */ -+ if (writeToShm) -+ brcms_b_write_shm(wlc->hw, offset, (u16) idle_busy_ratio_x_16); -+ -+ if (isOFDM) -+ wlc->tx_duty_cycle_ofdm = (u16) duty_cycle; -+ else -+ wlc->tx_duty_cycle_cck = (u16) duty_cycle; -+ -+ return 0; -+} -+ -+/* -+ * Initialize the base precedence map for dequeueing -+ * from txq based on WME settings -+ */ -+static void brcms_c_tx_prec_map_init(struct brcms_c_info *wlc) -+{ -+ wlc->tx_prec_map = BRCMS_PREC_BMP_ALL; -+ memset(wlc->fifo2prec_map, 0, NFIFO * sizeof(u16)); -+ -+ wlc->fifo2prec_map[TX_AC_BK_FIFO] = BRCMS_PREC_BMP_AC_BK; -+ wlc->fifo2prec_map[TX_AC_BE_FIFO] = BRCMS_PREC_BMP_AC_BE; -+ wlc->fifo2prec_map[TX_AC_VI_FIFO] = BRCMS_PREC_BMP_AC_VI; -+ wlc->fifo2prec_map[TX_AC_VO_FIFO] = BRCMS_PREC_BMP_AC_VO; -+} -+ -+static void -+brcms_c_txflowcontrol_signal(struct brcms_c_info *wlc, -+ struct brcms_txq_info *qi, bool on, int prio) -+{ -+ /* transmit flowcontrol is not yet implemented */ -+} -+ -+static void brcms_c_txflowcontrol_reset(struct brcms_c_info *wlc) -+{ -+ struct brcms_txq_info *qi; -+ -+ for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) { -+ if (qi->stopped) { -+ brcms_c_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO); -+ qi->stopped = 0; -+ } -+ } -+} -+ -+/* push sw hps and wake state through hardware */ -+static void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc) -+{ -+ u32 v1, v2; -+ bool hps; -+ bool awake_before; -+ -+ hps = brcms_c_ps_allowed(wlc); -+ -+ BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps); -+ -+ v1 = R_REG(&wlc->regs->maccontrol); -+ v2 = MCTL_WAKE; -+ if (hps) -+ v2 |= MCTL_HPS; -+ -+ brcms_b_mctrl(wlc->hw, MCTL_WAKE | MCTL_HPS, v2); -+ -+ awake_before = ((v1 & MCTL_WAKE) || ((v1 & MCTL_HPS) == 0)); -+ -+ if (!awake_before) -+ brcms_b_wait_for_wake(wlc->hw); -+} -+ -+/* -+ * Write this BSS config's MAC address to core. -+ * Updates RXE match engine. -+ */ -+static int brcms_c_set_mac(struct brcms_bss_cfg *bsscfg) -+{ -+ int err = 0; -+ struct brcms_c_info *wlc = bsscfg->wlc; -+ -+ /* enter the MAC addr into the RXE match registers */ -+ brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, bsscfg->cur_etheraddr); -+ -+ brcms_c_ampdu_macaddr_upd(wlc); -+ -+ return err; -+} -+ -+/* Write the BSS config's BSSID address to core (set_bssid in d11procs.tcl). -+ * Updates RXE match engine. -+ */ -+static void brcms_c_set_bssid(struct brcms_bss_cfg *bsscfg) -+{ -+ /* we need to update BSSID in RXE match registers */ -+ brcms_c_set_addrmatch(bsscfg->wlc, RCM_BSSID_OFFSET, bsscfg->BSSID); -+} -+ -+static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot) -+{ -+ wlc_hw->shortslot = shortslot; -+ -+ if (wlc_hw->band->bandtype == BRCM_BAND_2G && wlc_hw->up) { -+ brcms_c_suspend_mac_and_wait(wlc_hw->wlc); -+ brcms_b_update_slot_timing(wlc_hw, shortslot); -+ brcms_c_enable_mac(wlc_hw->wlc); -+ } -+} -+ -+/* -+ * Suspend the the MAC and update the slot timing -+ * for standard 11b/g (20us slots) or shortslot 11g (9us slots). -+ */ -+static void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot) -+{ -+ /* use the override if it is set */ -+ if (wlc->shortslot_override != BRCMS_SHORTSLOT_AUTO) -+ shortslot = (wlc->shortslot_override == BRCMS_SHORTSLOT_ON); -+ -+ if (wlc->shortslot == shortslot) -+ return; -+ -+ wlc->shortslot = shortslot; -+ -+ brcms_b_set_shortslot(wlc->hw, shortslot); -+} -+ -+static void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec) -+{ -+ if (wlc->home_chanspec != chanspec) { -+ wlc->home_chanspec = chanspec; -+ -+ if (wlc->bsscfg->associated) -+ wlc->bsscfg->current_bss->chanspec = chanspec; -+ } -+} -+ -+void -+brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec, -+ bool mute, struct txpwr_limits *txpwr) -+{ -+ uint bandunit; -+ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: 0x%x\n", wlc_hw->unit, chanspec); -+ -+ wlc_hw->chanspec = chanspec; -+ -+ /* Switch bands if necessary */ -+ if (wlc_hw->_nbands > 1) { -+ bandunit = chspec_bandunit(chanspec); -+ if (wlc_hw->band->bandunit != bandunit) { -+ /* brcms_b_setband disables other bandunit, -+ * use light band switch if not up yet -+ */ -+ if (wlc_hw->up) { -+ wlc_phy_chanspec_radio_set(wlc_hw-> -+ bandstate[bandunit]-> -+ pi, chanspec); -+ brcms_b_setband(wlc_hw, bandunit, chanspec); -+ } else { -+ brcms_c_setxband(wlc_hw, bandunit); -+ } -+ } -+ } -+ -+ wlc_phy_initcal_enable(wlc_hw->band->pi, !mute); -+ -+ if (!wlc_hw->up) { -+ if (wlc_hw->clk) -+ wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, -+ chanspec); -+ wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec); -+ } else { -+ wlc_phy_chanspec_set(wlc_hw->band->pi, chanspec); -+ wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec); -+ -+ /* Update muting of the channel */ -+ brcms_b_mute(wlc_hw, mute, 0); -+ } -+} -+ -+/* switch to and initialize new band */ -+static void brcms_c_setband(struct brcms_c_info *wlc, -+ uint bandunit) -+{ -+ wlc->band = wlc->bandstate[bandunit]; -+ -+ if (!wlc->pub->up) -+ return; -+ -+ /* wait for at least one beacon before entering sleeping state */ -+ brcms_c_set_ps_ctrl(wlc); -+ -+ /* band-specific initializations */ -+ brcms_c_bsinit(wlc); -+} -+ -+static void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec) -+{ -+ uint bandunit; -+ bool switchband = false; -+ u16 old_chanspec = wlc->chanspec; -+ -+ if (!brcms_c_valid_chanspec_db(wlc->cmi, chanspec)) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: Bad channel %d\n", -+ wlc->pub->unit, __func__, CHSPEC_CHANNEL(chanspec)); -+ return; -+ } -+ -+ /* Switch bands if necessary */ -+ if (wlc->pub->_nbands > 1) { -+ bandunit = chspec_bandunit(chanspec); -+ if (wlc->band->bandunit != bandunit || wlc->bandinit_pending) { -+ switchband = true; -+ if (wlc->bandlocked) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: chspec %d " -+ "band is locked!\n", -+ wlc->pub->unit, __func__, -+ CHSPEC_CHANNEL(chanspec)); -+ return; -+ } -+ /* -+ * should the setband call come after the -+ * brcms_b_chanspec() ? if the setband updates -+ * (brcms_c_bsinit) use low level calls to inspect and -+ * set state, the state inspected may be from the wrong -+ * band, or the following brcms_b_set_chanspec() may -+ * undo the work. -+ */ -+ brcms_c_setband(wlc, bandunit); -+ } -+ } -+ -+ /* sync up phy/radio chanspec */ -+ brcms_c_set_phy_chanspec(wlc, chanspec); -+ -+ /* init antenna selection */ -+ if (brcms_chspec_bw(old_chanspec) != brcms_chspec_bw(chanspec)) { -+ brcms_c_antsel_init(wlc->asi); -+ -+ /* Fix the hardware rateset based on bw. -+ * Mainly add MCS32 for 40Mhz, remove MCS 32 for 20Mhz -+ */ -+ brcms_c_rateset_bw_mcs_filter(&wlc->band->hw_rateset, -+ wlc->band->mimo_cap_40 ? brcms_chspec_bw(chanspec) : 0); -+ } -+ -+ /* update some mac configuration since chanspec changed */ -+ brcms_c_ucode_mac_upd(wlc); -+} -+ -+/* -+ * This function changes the phytxctl for beacon based on current -+ * beacon ratespec AND txant setting as per this table: -+ * ratespec CCK ant = wlc->stf->txant -+ * OFDM ant = 3 -+ */ -+void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, -+ u32 bcn_rspec) -+{ -+ u16 phyctl; -+ u16 phytxant = wlc->stf->phytxant; -+ u16 mask = PHY_TXC_ANT_MASK; -+ -+ /* for non-siso rates or default setting, use the available chains */ -+ if (BRCMS_PHY_11N_CAP(wlc->band)) -+ phytxant = brcms_c_stf_phytxchain_sel(wlc, bcn_rspec); -+ -+ phyctl = brcms_b_read_shm(wlc->hw, M_BCN_PCTLWD); -+ phyctl = (phyctl & ~mask) | phytxant; -+ brcms_b_write_shm(wlc->hw, M_BCN_PCTLWD, phyctl); -+} -+ -+/* -+ * centralized protection config change function to simplify debugging, no -+ * consistency checking this should be called only on changes to avoid overhead -+ * in periodic function -+ */ -+void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val) -+{ -+ BCMMSG(wlc->wiphy, "idx %d, val %d\n", idx, val); -+ -+ switch (idx) { -+ case BRCMS_PROT_G_SPEC: -+ wlc->protection->_g = (bool) val; -+ break; -+ case BRCMS_PROT_G_OVR: -+ wlc->protection->g_override = (s8) val; -+ break; -+ case BRCMS_PROT_G_USER: -+ wlc->protection->gmode_user = (u8) val; -+ break; -+ case BRCMS_PROT_OVERLAP: -+ wlc->protection->overlap = (s8) val; -+ break; -+ case BRCMS_PROT_N_USER: -+ wlc->protection->nmode_user = (s8) val; -+ break; -+ case BRCMS_PROT_N_CFG: -+ wlc->protection->n_cfg = (s8) val; -+ break; -+ case BRCMS_PROT_N_CFG_OVR: -+ wlc->protection->n_cfg_override = (s8) val; -+ break; -+ case BRCMS_PROT_N_NONGF: -+ wlc->protection->nongf = (bool) val; -+ break; -+ case BRCMS_PROT_N_NONGF_OVR: -+ wlc->protection->nongf_override = (s8) val; -+ break; -+ case BRCMS_PROT_N_PAM_OVR: -+ wlc->protection->n_pam_override = (s8) val; -+ break; -+ case BRCMS_PROT_N_OBSS: -+ wlc->protection->n_obss = (bool) val; -+ break; -+ -+ default: -+ break; -+ } -+ -+} -+ -+static void brcms_c_ht_update_sgi_rx(struct brcms_c_info *wlc, int val) -+{ -+ if (wlc->pub->up) { -+ brcms_c_update_beacon(wlc); -+ brcms_c_update_probe_resp(wlc, true); -+ } -+} -+ -+static void brcms_c_ht_update_ldpc(struct brcms_c_info *wlc, s8 val) -+{ -+ wlc->stf->ldpc = val; -+ -+ if (wlc->pub->up) { -+ brcms_c_update_beacon(wlc); -+ brcms_c_update_probe_resp(wlc, true); -+ wlc_phy_ldpc_override_set(wlc->band->pi, (val ? true : false)); -+ } -+} -+ -+void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci, -+ const struct ieee80211_tx_queue_params *params, -+ bool suspend) -+{ -+ int i; -+ struct shm_acparams acp_shm; -+ u16 *shm_entry; -+ -+ /* Only apply params if the core is out of reset and has clocks */ -+ if (!wlc->clk) { -+ wiphy_err(wlc->wiphy, "wl%d: %s : no-clock\n", wlc->pub->unit, -+ __func__); -+ return; -+ } -+ -+ memset((char *)&acp_shm, 0, sizeof(struct shm_acparams)); -+ /* fill in shm ac params struct */ -+ acp_shm.txop = params->txop; -+ /* convert from units of 32us to us for ucode */ -+ wlc->edcf_txop[aci & 0x3] = acp_shm.txop = -+ EDCF_TXOP2USEC(acp_shm.txop); -+ acp_shm.aifs = (params->aifs & EDCF_AIFSN_MASK); -+ -+ if (aci == AC_VI && acp_shm.txop == 0 -+ && acp_shm.aifs < EDCF_AIFSN_MAX) -+ acp_shm.aifs++; -+ -+ if (acp_shm.aifs < EDCF_AIFSN_MIN -+ || acp_shm.aifs > EDCF_AIFSN_MAX) { -+ wiphy_err(wlc->wiphy, "wl%d: edcf_setparams: bad " -+ "aifs %d\n", wlc->pub->unit, acp_shm.aifs); -+ } else { -+ acp_shm.cwmin = params->cw_min; -+ acp_shm.cwmax = params->cw_max; -+ acp_shm.cwcur = acp_shm.cwmin; -+ acp_shm.bslots = -+ R_REG(&wlc->regs->tsf_random) & acp_shm.cwcur; -+ acp_shm.reggap = acp_shm.bslots + acp_shm.aifs; -+ /* Indicate the new params to the ucode */ -+ acp_shm.status = brcms_b_read_shm(wlc->hw, (M_EDCF_QINFO + -+ wme_ac2fifo[aci] * -+ M_EDCF_QLEN + -+ M_EDCF_STATUS_OFF)); -+ acp_shm.status |= WME_STATUS_NEWAC; -+ -+ /* Fill in shm acparam table */ -+ shm_entry = (u16 *) &acp_shm; -+ for (i = 0; i < (int)sizeof(struct shm_acparams); i += 2) -+ brcms_b_write_shm(wlc->hw, -+ M_EDCF_QINFO + -+ wme_ac2fifo[aci] * M_EDCF_QLEN + i, -+ *shm_entry++); -+ } -+ -+ if (suspend) { -+ brcms_c_suspend_mac_and_wait(wlc); -+ brcms_c_enable_mac(wlc); -+ } -+} -+ -+void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend) -+{ -+ u16 aci; -+ int i_ac; -+ struct ieee80211_tx_queue_params txq_pars; -+ static const struct edcf_acparam default_edcf_acparams[] = { -+ {EDCF_AC_BE_ACI_STA, EDCF_AC_BE_ECW_STA, EDCF_AC_BE_TXOP_STA}, -+ {EDCF_AC_BK_ACI_STA, EDCF_AC_BK_ECW_STA, EDCF_AC_BK_TXOP_STA}, -+ {EDCF_AC_VI_ACI_STA, EDCF_AC_VI_ECW_STA, EDCF_AC_VI_TXOP_STA}, -+ {EDCF_AC_VO_ACI_STA, EDCF_AC_VO_ECW_STA, EDCF_AC_VO_TXOP_STA} -+ }; /* ucode needs these parameters during its initialization */ -+ const struct edcf_acparam *edcf_acp = &default_edcf_acparams[0]; -+ -+ for (i_ac = 0; i_ac < AC_COUNT; i_ac++, edcf_acp++) { -+ /* find out which ac this set of params applies to */ -+ aci = (edcf_acp->ACI & EDCF_ACI_MASK) >> EDCF_ACI_SHIFT; -+ -+ /* fill in shm ac params struct */ -+ txq_pars.txop = edcf_acp->TXOP; -+ txq_pars.aifs = edcf_acp->ACI; -+ -+ /* CWmin = 2^(ECWmin) - 1 */ -+ txq_pars.cw_min = EDCF_ECW2CW(edcf_acp->ECW & EDCF_ECWMIN_MASK); -+ /* CWmax = 2^(ECWmax) - 1 */ -+ txq_pars.cw_max = EDCF_ECW2CW((edcf_acp->ECW & EDCF_ECWMAX_MASK) -+ >> EDCF_ECWMAX_SHIFT); -+ brcms_c_wme_setparams(wlc, aci, &txq_pars, suspend); -+ } -+ -+ if (suspend) { -+ brcms_c_suspend_mac_and_wait(wlc); -+ brcms_c_enable_mac(wlc); -+ } -+} -+ -+/* maintain LED behavior in down state */ -+static void brcms_c_down_led_upd(struct brcms_c_info *wlc) -+{ -+ /* -+ * maintain LEDs while in down state, turn on sbclk if -+ * not available yet. Turn on sbclk if necessary -+ */ -+ brcms_b_pllreq(wlc->hw, true, BRCMS_PLLREQ_FLIP); -+ brcms_b_pllreq(wlc->hw, false, BRCMS_PLLREQ_FLIP); -+} -+ -+static void brcms_c_radio_monitor_start(struct brcms_c_info *wlc) -+{ -+ /* Don't start the timer if HWRADIO feature is disabled */ -+ if (wlc->radio_monitor) -+ return; -+ -+ wlc->radio_monitor = true; -+ brcms_b_pllreq(wlc->hw, true, BRCMS_PLLREQ_RADIO_MON); -+ brcms_add_timer(wlc->radio_timer, TIMER_INTERVAL_RADIOCHK, true); -+} -+ -+static void brcms_c_radio_disable(struct brcms_c_info *wlc) -+{ -+ if (!wlc->pub->up) { -+ brcms_c_down_led_upd(wlc); -+ return; -+ } -+ -+ brcms_c_radio_monitor_start(wlc); -+ brcms_down(wlc->wl); -+} -+ -+static void brcms_c_radio_enable(struct brcms_c_info *wlc) -+{ -+ if (wlc->pub->up) -+ return; -+ -+ if (brcms_deviceremoved(wlc)) -+ return; -+ -+ brcms_up(wlc->wl); -+} -+ -+static bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc) -+{ -+ if (!wlc->radio_monitor) -+ return true; -+ -+ wlc->radio_monitor = false; -+ brcms_b_pllreq(wlc->hw, false, BRCMS_PLLREQ_RADIO_MON); -+ return brcms_del_timer(wlc->radio_timer); -+} -+ -+/* read hwdisable state and propagate to wlc flag */ -+static void brcms_c_radio_hwdisable_upd(struct brcms_c_info *wlc) -+{ -+ if (wlc->pub->hw_off) -+ return; -+ -+ if (brcms_b_radio_read_hwdisabled(wlc->hw)) -+ mboolset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE); -+ else -+ mboolclr(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE); -+} -+ -+/* -+ * centralized radio disable/enable function, -+ * invoke radio enable/disable after updating hwradio status -+ */ -+static void brcms_c_radio_upd(struct brcms_c_info *wlc) -+{ -+ if (wlc->pub->radio_disabled) -+ brcms_c_radio_disable(wlc); -+ else -+ brcms_c_radio_enable(wlc); -+} -+ -+/* update hwradio status and return it */ -+bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc) -+{ -+ brcms_c_radio_hwdisable_upd(wlc); -+ -+ return mboolisset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE) ? -+ true : false; -+} -+ -+/* periodical query hw radio button while driver is "down" */ -+static void brcms_c_radio_timer(void *arg) -+{ -+ struct brcms_c_info *wlc = (struct brcms_c_info *) arg; -+ -+ if (brcms_deviceremoved(wlc)) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit, -+ __func__); -+ brcms_down(wlc->wl); -+ return; -+ } -+ -+ /* cap mpc off count */ -+ if (wlc->mpc_offcnt < BRCMS_MPC_MAX_DELAYCNT) -+ wlc->mpc_offcnt++; -+ -+ brcms_c_radio_hwdisable_upd(wlc); -+ brcms_c_radio_upd(wlc); -+} -+ -+/* common low-level watchdog code */ -+static void brcms_b_watchdog(void *arg) -+{ -+ struct brcms_c_info *wlc = (struct brcms_c_info *) arg; -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ -+ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ if (!wlc_hw->up) -+ return; -+ -+ /* increment second count */ -+ wlc_hw->now++; -+ -+ /* Check for FIFO error interrupts */ -+ brcms_b_fifoerrors(wlc_hw); -+ -+ /* make sure RX dma has buffers */ -+ dma_rxfill(wlc->hw->di[RX_FIFO]); -+ -+ wlc_phy_watchdog(wlc_hw->band->pi); -+} -+ -+static void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc) -+{ -+ bool mpc_radio, radio_state; -+ -+ /* -+ * Clear the WL_RADIO_MPC_DISABLE bit when mpc feature is disabled -+ * in case the WL_RADIO_MPC_DISABLE bit was set. Stop the radio -+ * monitor also when WL_RADIO_MPC_DISABLE is the only reason that -+ * the radio is going down. -+ */ -+ if (!wlc->mpc) { -+ if (!wlc->pub->radio_disabled) -+ return; -+ mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE); -+ brcms_c_radio_upd(wlc); -+ if (!wlc->pub->radio_disabled) -+ brcms_c_radio_monitor_stop(wlc); -+ return; -+ } -+ -+ /* -+ * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in -+ * wlc->pub->radio_disabled to go ON, always call radio_upd -+ * synchronously to go OFF, postpone radio_upd to later when -+ * context is safe(e.g. watchdog) -+ */ -+ radio_state = -+ (mboolisset(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE) ? OFF : -+ ON); -+ mpc_radio = (brcms_c_ismpc(wlc) == true) ? OFF : ON; -+ -+ if (radio_state == ON && mpc_radio == OFF) -+ wlc->mpc_delay_off = wlc->mpc_dlycnt; -+ else if (radio_state == OFF && mpc_radio == ON) { -+ mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE); -+ brcms_c_radio_upd(wlc); -+ if (wlc->mpc_offcnt < BRCMS_MPC_THRESHOLD) -+ wlc->mpc_dlycnt = BRCMS_MPC_MAX_DELAYCNT; -+ else -+ wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT; -+ } -+ /* -+ * Below logic is meant to capture the transition from mpc off -+ * to mpc on for reasons other than wlc->mpc_delay_off keeping -+ * the mpc off. In that case reset wlc->mpc_delay_off to -+ * wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off -+ */ -+ if ((wlc->prev_non_delay_mpc == false) && -+ (brcms_c_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off) -+ wlc->mpc_delay_off = wlc->mpc_dlycnt; -+ -+ wlc->prev_non_delay_mpc = brcms_c_is_non_delay_mpc(wlc); -+} -+ -+/* common watchdog code */ -+static void brcms_c_watchdog(void *arg) -+{ -+ struct brcms_c_info *wlc = (struct brcms_c_info *) arg; -+ -+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); -+ -+ if (!wlc->pub->up) -+ return; -+ -+ if (brcms_deviceremoved(wlc)) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit, -+ __func__); -+ brcms_down(wlc->wl); -+ return; -+ } -+ -+ /* increment second count */ -+ wlc->pub->now++; -+ -+ /* delay radio disable */ -+ if (wlc->mpc_delay_off) { -+ if (--wlc->mpc_delay_off == 0) { -+ mboolset(wlc->pub->radio_disabled, -+ WL_RADIO_MPC_DISABLE); -+ if (wlc->mpc && brcms_c_ismpc(wlc)) -+ wlc->mpc_offcnt = 0; -+ } -+ } -+ -+ /* mpc sync */ -+ brcms_c_radio_mpc_upd(wlc); -+ /* radio sync: sw/hw/mpc --> radio_disable/radio_enable */ -+ brcms_c_radio_hwdisable_upd(wlc); -+ brcms_c_radio_upd(wlc); -+ /* if radio is disable, driver may be down, quit here */ -+ if (wlc->pub->radio_disabled) -+ return; -+ -+ brcms_b_watchdog(wlc); -+ -+ /* -+ * occasionally sample mac stat counters to -+ * detect 16-bit counter wrap -+ */ -+ if ((wlc->pub->now % SW_TIMER_MAC_STAT_UPD) == 0) -+ brcms_c_statsupd(wlc); -+ -+ if (BRCMS_ISNPHY(wlc->band) && -+ ((wlc->pub->now - wlc->tempsense_lasttime) >= -+ BRCMS_TEMPSENSE_PERIOD)) { -+ wlc->tempsense_lasttime = wlc->pub->now; -+ brcms_c_tempsense_upd(wlc); -+ } -+} -+ -+static void brcms_c_watchdog_by_timer(void *arg) -+{ -+ brcms_c_watchdog(arg); -+} -+ -+static bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit) -+{ -+ wlc->wdtimer = brcms_init_timer(wlc->wl, brcms_c_watchdog_by_timer, -+ wlc, "watchdog"); -+ if (!wlc->wdtimer) { -+ wiphy_err(wlc->wiphy, "wl%d: wl_init_timer for wdtimer " -+ "failed\n", unit); -+ goto fail; -+ } -+ -+ wlc->radio_timer = brcms_init_timer(wlc->wl, brcms_c_radio_timer, -+ wlc, "radio"); -+ if (!wlc->radio_timer) { -+ wiphy_err(wlc->wiphy, "wl%d: wl_init_timer for radio_timer " -+ "failed\n", unit); -+ goto fail; -+ } -+ -+ return true; -+ -+ fail: -+ return false; -+} -+ -+/* -+ * Initialize brcms_c_info default values ... -+ * may get overrides later in this function -+ */ -+static void brcms_c_info_init(struct brcms_c_info *wlc, int unit) -+{ -+ int i; -+ -+ /* Save our copy of the chanspec */ -+ wlc->chanspec = ch20mhz_chspec(1); -+ -+ /* various 802.11g modes */ -+ wlc->shortslot = false; -+ wlc->shortslot_override = BRCMS_SHORTSLOT_AUTO; -+ -+ brcms_c_protection_upd(wlc, BRCMS_PROT_G_OVR, BRCMS_PROTECTION_AUTO); -+ brcms_c_protection_upd(wlc, BRCMS_PROT_G_SPEC, false); -+ -+ brcms_c_protection_upd(wlc, BRCMS_PROT_N_CFG_OVR, -+ BRCMS_PROTECTION_AUTO); -+ brcms_c_protection_upd(wlc, BRCMS_PROT_N_CFG, BRCMS_N_PROTECTION_OFF); -+ brcms_c_protection_upd(wlc, BRCMS_PROT_N_NONGF_OVR, -+ BRCMS_PROTECTION_AUTO); -+ brcms_c_protection_upd(wlc, BRCMS_PROT_N_NONGF, false); -+ brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR, AUTO); -+ -+ brcms_c_protection_upd(wlc, BRCMS_PROT_OVERLAP, -+ BRCMS_PROTECTION_CTL_OVERLAP); -+ -+ /* 802.11g draft 4.0 NonERP elt advertisement */ -+ wlc->include_legacy_erp = true; -+ -+ wlc->stf->ant_rx_ovr = ANT_RX_DIV_DEF; -+ wlc->stf->txant = ANT_TX_DEF; -+ -+ wlc->prb_resp_timeout = BRCMS_PRB_RESP_TIMEOUT; -+ -+ wlc->usr_fragthresh = DOT11_DEFAULT_FRAG_LEN; -+ for (i = 0; i < NFIFO; i++) -+ wlc->fragthresh[i] = DOT11_DEFAULT_FRAG_LEN; -+ wlc->RTSThresh = DOT11_DEFAULT_RTS_LEN; -+ -+ /* default rate fallback retry limits */ -+ wlc->SFBL = RETRY_SHORT_FB; -+ wlc->LFBL = RETRY_LONG_FB; -+ -+ /* default mac retry limits */ -+ wlc->SRL = RETRY_SHORT_DEF; -+ wlc->LRL = RETRY_LONG_DEF; -+ -+ /* WME QoS mode is Auto by default */ -+ wlc->pub->_ampdu = AMPDU_AGG_HOST; -+ wlc->pub->bcmerror = 0; -+ -+ /* initialize mpc delay */ -+ wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT; -+} -+ -+static uint brcms_c_attach_module(struct brcms_c_info *wlc) -+{ -+ uint err = 0; -+ uint unit; -+ unit = wlc->pub->unit; -+ -+ wlc->asi = brcms_c_antsel_attach(wlc); -+ if (wlc->asi == NULL) { -+ wiphy_err(wlc->wiphy, "wl%d: attach: antsel_attach " -+ "failed\n", unit); -+ err = 44; -+ goto fail; -+ } -+ -+ wlc->ampdu = brcms_c_ampdu_attach(wlc); -+ if (wlc->ampdu == NULL) { -+ wiphy_err(wlc->wiphy, "wl%d: attach: ampdu_attach " -+ "failed\n", unit); -+ err = 50; -+ goto fail; -+ } -+ -+ if ((brcms_c_stf_attach(wlc) != 0)) { -+ wiphy_err(wlc->wiphy, "wl%d: attach: stf_attach " -+ "failed\n", unit); -+ err = 68; -+ goto fail; -+ } -+ fail: -+ return err; -+} -+ -+struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc) -+{ -+ return wlc->pub; -+} -+ -+/* low level attach -+ * run backplane attach, init nvram -+ * run phy attach -+ * initialize software state for each core and band -+ * put the whole chip in reset(driver down state), no clock -+ */ -+static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, -+ uint unit, bool piomode, void __iomem *regsva, -+ struct pci_dev *btparam) -+{ -+ struct brcms_hardware *wlc_hw; -+ struct d11regs __iomem *regs; -+ char *macaddr = NULL; -+ uint err = 0; -+ uint j; -+ bool wme = false; -+ struct shared_phy_params sha_params; -+ struct wiphy *wiphy = wlc->wiphy; -+ -+ BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, vendor, -+ device); -+ -+ wme = true; -+ -+ wlc_hw = wlc->hw; -+ wlc_hw->wlc = wlc; -+ wlc_hw->unit = unit; -+ wlc_hw->band = wlc_hw->bandstate[0]; -+ wlc_hw->_piomode = piomode; -+ -+ /* populate struct brcms_hardware with default values */ -+ brcms_b_info_init(wlc_hw); -+ -+ /* -+ * Do the hardware portion of the attach. Also initialize software -+ * state that depends on the particular hardware we are running. -+ */ -+ wlc_hw->sih = ai_attach(regsva, btparam); -+ if (wlc_hw->sih == NULL) { -+ wiphy_err(wiphy, "wl%d: brcms_b_attach: si_attach failed\n", -+ unit); -+ err = 11; -+ goto fail; -+ } -+ -+ /* verify again the device is supported */ -+ if (!brcms_c_chipmatch(vendor, device)) { -+ wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported " -+ "vendor/device (0x%x/0x%x)\n", -+ unit, vendor, device); -+ err = 12; -+ goto fail; -+ } -+ -+ wlc_hw->vendorid = vendor; -+ wlc_hw->deviceid = device; -+ -+ /* set bar0 window to point at D11 core */ -+ wlc_hw->regs = (struct d11regs __iomem *) -+ ai_setcore(wlc_hw->sih, D11_CORE_ID, 0); -+ wlc_hw->corerev = ai_corerev(wlc_hw->sih); -+ -+ regs = wlc_hw->regs; -+ -+ wlc->regs = wlc_hw->regs; -+ -+ /* validate chip, chiprev and corerev */ -+ if (!brcms_c_isgoodchip(wlc_hw)) { -+ err = 13; -+ goto fail; -+ } -+ -+ /* initialize power control registers */ -+ ai_clkctl_init(wlc_hw->sih); -+ -+ /* request fastclock and force fastclock for the rest of attach -+ * bring the d11 core out of reset. -+ * For PMU chips, the first wlc_clkctl_clk is no-op since core-clk -+ * is still false; But it will be called again inside wlc_corereset, -+ * after d11 is out of reset. -+ */ -+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); -+ brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); -+ -+ if (!brcms_b_validate_chip_access(wlc_hw)) { -+ wiphy_err(wiphy, "wl%d: brcms_b_attach: validate_chip_access " -+ "failed\n", unit); -+ err = 14; -+ goto fail; -+ } -+ -+ /* get the board rev, used just below */ -+ j = getintvar(wlc_hw->sih, BRCMS_SROM_BOARDREV); -+ /* promote srom boardrev of 0xFF to 1 */ -+ if (j == BOARDREV_PROMOTABLE) -+ j = BOARDREV_PROMOTED; -+ wlc_hw->boardrev = (u16) j; -+ if (!brcms_c_validboardtype(wlc_hw)) { -+ wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported Broadcom " -+ "board type (0x%x)" " or revision level (0x%x)\n", -+ unit, wlc_hw->sih->boardtype, wlc_hw->boardrev); -+ err = 15; -+ goto fail; -+ } -+ wlc_hw->sromrev = (u8) getintvar(wlc_hw->sih, BRCMS_SROM_REV); -+ wlc_hw->boardflags = (u32) getintvar(wlc_hw->sih, -+ BRCMS_SROM_BOARDFLAGS); -+ wlc_hw->boardflags2 = (u32) getintvar(wlc_hw->sih, -+ BRCMS_SROM_BOARDFLAGS2); -+ -+ if (wlc_hw->boardflags & BFL_NOPLLDOWN) -+ brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED); -+ -+ /* check device id(srom, nvram etc.) to set bands */ -+ if (wlc_hw->deviceid == BCM43224_D11N_ID || -+ wlc_hw->deviceid == BCM43224_D11N_ID_VEN1) -+ /* Dualband boards */ -+ wlc_hw->_nbands = 2; -+ else -+ wlc_hw->_nbands = 1; -+ -+ if ((wlc_hw->sih->chip == BCM43225_CHIP_ID)) -+ wlc_hw->_nbands = 1; -+ -+ /* BMAC_NOTE: remove init of pub values when brcms_c_attach() -+ * unconditionally does the init of these values -+ */ -+ wlc->vendorid = wlc_hw->vendorid; -+ wlc->deviceid = wlc_hw->deviceid; -+ wlc->pub->sih = wlc_hw->sih; -+ wlc->pub->corerev = wlc_hw->corerev; -+ wlc->pub->sromrev = wlc_hw->sromrev; -+ wlc->pub->boardrev = wlc_hw->boardrev; -+ wlc->pub->boardflags = wlc_hw->boardflags; -+ wlc->pub->boardflags2 = wlc_hw->boardflags2; -+ wlc->pub->_nbands = wlc_hw->_nbands; -+ -+ wlc_hw->physhim = wlc_phy_shim_attach(wlc_hw, wlc->wl, wlc); -+ -+ if (wlc_hw->physhim == NULL) { -+ wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_shim_attach " -+ "failed\n", unit); -+ err = 25; -+ goto fail; -+ } -+ -+ /* pass all the parameters to wlc_phy_shared_attach in one struct */ -+ sha_params.sih = wlc_hw->sih; -+ sha_params.physhim = wlc_hw->physhim; -+ sha_params.unit = unit; -+ sha_params.corerev = wlc_hw->corerev; -+ sha_params.vid = wlc_hw->vendorid; -+ sha_params.did = wlc_hw->deviceid; -+ sha_params.chip = wlc_hw->sih->chip; -+ sha_params.chiprev = wlc_hw->sih->chiprev; -+ sha_params.chippkg = wlc_hw->sih->chippkg; -+ sha_params.sromrev = wlc_hw->sromrev; -+ sha_params.boardtype = wlc_hw->sih->boardtype; -+ sha_params.boardrev = wlc_hw->boardrev; -+ sha_params.boardvendor = wlc_hw->sih->boardvendor; -+ sha_params.boardflags = wlc_hw->boardflags; -+ sha_params.boardflags2 = wlc_hw->boardflags2; -+ sha_params.buscorerev = wlc_hw->sih->buscorerev; -+ -+ /* alloc and save pointer to shared phy state area */ -+ wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params); -+ if (!wlc_hw->phy_sh) { -+ err = 16; -+ goto fail; -+ } -+ -+ /* initialize software state for each core and band */ -+ for (j = 0; j < wlc_hw->_nbands; j++) { -+ /* -+ * band0 is always 2.4Ghz -+ * band1, if present, is 5Ghz -+ */ -+ -+ brcms_c_setxband(wlc_hw, j); -+ -+ wlc_hw->band->bandunit = j; -+ wlc_hw->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G; -+ wlc->band->bandunit = j; -+ wlc->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G; -+ wlc->core->coreidx = ai_coreidx(wlc_hw->sih); -+ -+ wlc_hw->machwcap = R_REG(®s->machwcap); -+ wlc_hw->machwcap_backup = wlc_hw->machwcap; -+ -+ /* init tx fifo size */ -+ wlc_hw->xmtfifo_sz = -+ xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)]; -+ -+ /* Get a phy for this band */ -+ wlc_hw->band->pi = -+ wlc_phy_attach(wlc_hw->phy_sh, regs, -+ wlc_hw->band->bandtype, -+ wlc->wiphy); -+ if (wlc_hw->band->pi == NULL) { -+ wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_" -+ "attach failed\n", unit); -+ err = 17; -+ goto fail; -+ } -+ -+ wlc_phy_machwcap_set(wlc_hw->band->pi, wlc_hw->machwcap); -+ -+ wlc_phy_get_phyversion(wlc_hw->band->pi, &wlc_hw->band->phytype, -+ &wlc_hw->band->phyrev, -+ &wlc_hw->band->radioid, -+ &wlc_hw->band->radiorev); -+ wlc_hw->band->abgphy_encore = -+ wlc_phy_get_encore(wlc_hw->band->pi); -+ wlc->band->abgphy_encore = wlc_phy_get_encore(wlc_hw->band->pi); -+ wlc_hw->band->core_flags = -+ wlc_phy_get_coreflags(wlc_hw->band->pi); -+ -+ /* verify good phy_type & supported phy revision */ -+ if (BRCMS_ISNPHY(wlc_hw->band)) { -+ if (NCONF_HAS(wlc_hw->band->phyrev)) -+ goto good_phy; -+ else -+ goto bad_phy; -+ } else if (BRCMS_ISLCNPHY(wlc_hw->band)) { -+ if (LCNCONF_HAS(wlc_hw->band->phyrev)) -+ goto good_phy; -+ else -+ goto bad_phy; -+ } else { -+ bad_phy: -+ wiphy_err(wiphy, "wl%d: brcms_b_attach: unsupported " -+ "phy type/rev (%d/%d)\n", unit, -+ wlc_hw->band->phytype, wlc_hw->band->phyrev); -+ err = 18; -+ goto fail; -+ } -+ -+ good_phy: -+ /* -+ * BMAC_NOTE: wlc->band->pi should not be set below and should -+ * be done in the high level attach. However we can not make -+ * that change until all low level access is changed to -+ * wlc_hw->band->pi. Instead do the wlc->band->pi init below, -+ * keeping wlc_hw->band->pi as well for incremental update of -+ * low level fns, and cut over low only init when all fns -+ * updated. -+ */ -+ wlc->band->pi = wlc_hw->band->pi; -+ wlc->band->phytype = wlc_hw->band->phytype; -+ wlc->band->phyrev = wlc_hw->band->phyrev; -+ wlc->band->radioid = wlc_hw->band->radioid; -+ wlc->band->radiorev = wlc_hw->band->radiorev; -+ -+ /* default contention windows size limits */ -+ wlc_hw->band->CWmin = APHY_CWMIN; -+ wlc_hw->band->CWmax = PHY_CWMAX; -+ -+ if (!brcms_b_attach_dmapio(wlc, j, wme)) { -+ err = 19; -+ goto fail; -+ } -+ } -+ -+ /* disable core to match driver "down" state */ -+ brcms_c_coredisable(wlc_hw); -+ -+ /* Match driver "down" state */ -+ ai_pci_down(wlc_hw->sih); -+ -+ /* register sb interrupt callback functions */ -+ ai_register_intr_callback(wlc_hw->sih, (void *)brcms_c_wlintrsoff, -+ (void *)brcms_c_wlintrsrestore, NULL, wlc); -+ -+ /* turn off pll and xtal to match driver "down" state */ -+ brcms_b_xtal(wlc_hw, OFF); -+ -+ /* ******************************************************************* -+ * The hardware is in the DOWN state at this point. D11 core -+ * or cores are in reset with clocks off, and the board PLLs -+ * are off if possible. -+ * -+ * Beyond this point, wlc->sbclk == false and chip registers -+ * should not be touched. -+ ********************************************************************* -+ */ -+ -+ /* init etheraddr state variables */ -+ macaddr = brcms_c_get_macaddr(wlc_hw); -+ if (macaddr == NULL) { -+ wiphy_err(wiphy, "wl%d: brcms_b_attach: macaddr not found\n", -+ unit); -+ err = 21; -+ goto fail; -+ } -+ if (!mac_pton(macaddr, wlc_hw->etheraddr) || -+ is_broadcast_ether_addr(wlc_hw->etheraddr) || -+ is_zero_ether_addr(wlc_hw->etheraddr)) { -+ wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr %s\n", -+ unit, macaddr); -+ err = 22; -+ goto fail; -+ } -+ -+ BCMMSG(wlc->wiphy, -+ "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n", -+ wlc_hw->deviceid, wlc_hw->_nbands, -+ wlc_hw->sih->boardtype, macaddr); -+ -+ return err; -+ -+ fail: -+ wiphy_err(wiphy, "wl%d: brcms_b_attach: failed with err %d\n", unit, -+ err); -+ return err; -+} -+ -+static void brcms_c_attach_antgain_init(struct brcms_c_info *wlc) -+{ -+ uint unit; -+ unit = wlc->pub->unit; -+ -+ if ((wlc->band->antgain == -1) && (wlc->pub->sromrev == 1)) { -+ /* default antenna gain for srom rev 1 is 2 dBm (8 qdbm) */ -+ wlc->band->antgain = 8; -+ } else if (wlc->band->antgain == -1) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in" -+ " srom, using 2dB\n", unit, __func__); -+ wlc->band->antgain = 8; -+ } else { -+ s8 gain, fract; -+ /* Older sroms specified gain in whole dbm only. In order -+ * be able to specify qdbm granularity and remain backward -+ * compatible the whole dbms are now encoded in only -+ * low 6 bits and remaining qdbms are encoded in the hi 2 bits. -+ * 6 bit signed number ranges from -32 - 31. -+ * -+ * Examples: -+ * 0x1 = 1 db, -+ * 0xc1 = 1.75 db (1 + 3 quarters), -+ * 0x3f = -1 (-1 + 0 quarters), -+ * 0x7f = -.75 (-1 + 1 quarters) = -3 qdbm. -+ * 0xbf = -.50 (-1 + 2 quarters) = -2 qdbm. -+ */ -+ gain = wlc->band->antgain & 0x3f; -+ gain <<= 2; /* Sign extend */ -+ gain >>= 2; -+ fract = (wlc->band->antgain & 0xc0) >> 6; -+ wlc->band->antgain = 4 * gain + fract; -+ } -+} -+ -+static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc) -+{ -+ int aa; -+ uint unit; -+ int bandtype; -+ struct si_pub *sih = wlc->hw->sih; -+ -+ unit = wlc->pub->unit; -+ bandtype = wlc->band->bandtype; -+ -+ /* get antennas available */ -+ if (bandtype == BRCM_BAND_5G) -+ aa = (s8) getintvar(sih, BRCMS_SROM_AA5G); -+ else -+ aa = (s8) getintvar(sih, BRCMS_SROM_AA2G); -+ -+ if ((aa < 1) || (aa > 15)) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in" -+ " srom (0x%x), using 3\n", unit, __func__, aa); -+ aa = 3; -+ } -+ -+ /* reset the defaults if we have a single antenna */ -+ if (aa == 1) { -+ wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_0; -+ wlc->stf->txant = ANT_TX_FORCE_0; -+ } else if (aa == 2) { -+ wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_1; -+ wlc->stf->txant = ANT_TX_FORCE_1; -+ } else { -+ } -+ -+ /* Compute Antenna Gain */ -+ if (bandtype == BRCM_BAND_5G) -+ wlc->band->antgain = (s8) getintvar(sih, BRCMS_SROM_AG1); -+ else -+ wlc->band->antgain = (s8) getintvar(sih, BRCMS_SROM_AG0); -+ -+ brcms_c_attach_antgain_init(wlc); -+ -+ return true; -+} -+ -+static void brcms_c_bss_default_init(struct brcms_c_info *wlc) -+{ -+ u16 chanspec; -+ struct brcms_band *band; -+ struct brcms_bss_info *bi = wlc->default_bss; -+ -+ /* init default and target BSS with some sane initial values */ -+ memset((char *)(bi), 0, sizeof(struct brcms_bss_info)); -+ bi->beacon_period = BEACON_INTERVAL_DEFAULT; -+ -+ /* fill the default channel as the first valid channel -+ * starting from the 2G channels -+ */ -+ chanspec = ch20mhz_chspec(1); -+ wlc->home_chanspec = bi->chanspec = chanspec; -+ -+ /* find the band of our default channel */ -+ band = wlc->band; -+ if (wlc->pub->_nbands > 1 && -+ band->bandunit != chspec_bandunit(chanspec)) -+ band = wlc->bandstate[OTHERBANDUNIT(wlc)]; -+ -+ /* init bss rates to the band specific default rate set */ -+ brcms_c_rateset_default(&bi->rateset, NULL, band->phytype, -+ band->bandtype, false, BRCMS_RATE_MASK_FULL, -+ (bool) (wlc->pub->_n_enab & SUPPORT_11N), -+ brcms_chspec_bw(chanspec), wlc->stf->txstreams); -+ -+ if (wlc->pub->_n_enab & SUPPORT_11N) -+ bi->flags |= BRCMS_BSS_HT; -+} -+ -+static struct brcms_txq_info *brcms_c_txq_alloc(struct brcms_c_info *wlc) -+{ -+ struct brcms_txq_info *qi, *p; -+ -+ qi = kzalloc(sizeof(struct brcms_txq_info), GFP_ATOMIC); -+ if (qi != NULL) { -+ /* -+ * Have enough room for control packets along with HI watermark -+ * Also, add room to txq for total psq packets if all the SCBs -+ * leave PS mode. The watermark for flowcontrol to OS packets -+ * will remain the same -+ */ -+ brcmu_pktq_init(&qi->q, BRCMS_PREC_COUNT, -+ 2 * BRCMS_DATAHIWAT + PKTQ_LEN_DEFAULT); -+ -+ /* add this queue to the the global list */ -+ p = wlc->tx_queues; -+ if (p == NULL) { -+ wlc->tx_queues = qi; -+ } else { -+ while (p->next != NULL) -+ p = p->next; -+ p->next = qi; -+ } -+ } -+ return qi; -+} -+ -+static void brcms_c_txq_free(struct brcms_c_info *wlc, -+ struct brcms_txq_info *qi) -+{ -+ struct brcms_txq_info *p; -+ -+ if (qi == NULL) -+ return; -+ -+ /* remove the queue from the linked list */ -+ p = wlc->tx_queues; -+ if (p == qi) -+ wlc->tx_queues = p->next; -+ else { -+ while (p != NULL && p->next != qi) -+ p = p->next; -+ if (p != NULL) -+ p->next = p->next->next; -+ } -+ -+ kfree(qi); -+} -+ -+static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap) -+{ -+ uint i; -+ struct brcms_band *band; -+ -+ for (i = 0; i < wlc->pub->_nbands; i++) { -+ band = wlc->bandstate[i]; -+ if (band->bandtype == BRCM_BAND_5G) { -+ if ((bwcap == BRCMS_N_BW_40ALL) -+ || (bwcap == BRCMS_N_BW_20IN2G_40IN5G)) -+ band->mimo_cap_40 = true; -+ else -+ band->mimo_cap_40 = false; -+ } else { -+ if (bwcap == BRCMS_N_BW_40ALL) -+ band->mimo_cap_40 = true; -+ else -+ band->mimo_cap_40 = false; -+ } -+ } -+} -+ -+static void brcms_c_timers_deinit(struct brcms_c_info *wlc) -+{ -+ /* free timer state */ -+ if (wlc->wdtimer) { -+ brcms_free_timer(wlc->wdtimer); -+ wlc->wdtimer = NULL; -+ } -+ if (wlc->radio_timer) { -+ brcms_free_timer(wlc->radio_timer); -+ wlc->radio_timer = NULL; -+ } -+} -+ -+static void brcms_c_detach_module(struct brcms_c_info *wlc) -+{ -+ if (wlc->asi) { -+ brcms_c_antsel_detach(wlc->asi); -+ wlc->asi = NULL; -+ } -+ -+ if (wlc->ampdu) { -+ brcms_c_ampdu_detach(wlc->ampdu); -+ wlc->ampdu = NULL; -+ } -+ -+ brcms_c_stf_detach(wlc); -+} -+ -+/* -+ * low level detach -+ */ -+static int brcms_b_detach(struct brcms_c_info *wlc) -+{ -+ uint i; -+ struct brcms_hw_band *band; -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ int callbacks; -+ -+ callbacks = 0; -+ -+ if (wlc_hw->sih) { -+ /* -+ * detach interrupt sync mechanism since interrupt is disabled -+ * and per-port interrupt object may has been freed. this must -+ * be done before sb core switch -+ */ -+ ai_deregister_intr_callback(wlc_hw->sih); -+ ai_pci_sleep(wlc_hw->sih); -+ } -+ -+ brcms_b_detach_dmapio(wlc_hw); -+ -+ band = wlc_hw->band; -+ for (i = 0; i < wlc_hw->_nbands; i++) { -+ if (band->pi) { -+ /* Detach this band's phy */ -+ wlc_phy_detach(band->pi); -+ band->pi = NULL; -+ } -+ band = wlc_hw->bandstate[OTHERBANDUNIT(wlc)]; -+ } -+ -+ /* Free shared phy state */ -+ kfree(wlc_hw->phy_sh); -+ -+ wlc_phy_shim_detach(wlc_hw->physhim); -+ -+ if (wlc_hw->sih) { -+ ai_detach(wlc_hw->sih); -+ wlc_hw->sih = NULL; -+ } -+ -+ return callbacks; -+ -+} -+ -+/* -+ * Return a count of the number of driver callbacks still pending. -+ * -+ * General policy is that brcms_c_detach can only dealloc/free software states. -+ * It can NOT touch hardware registers since the d11core may be in reset and -+ * clock may not be available. -+ * One exception is sb register access, which is possible if crystal is turned -+ * on after "down" state, driver should avoid software timer with the exception -+ * of radio_monitor. -+ */ -+uint brcms_c_detach(struct brcms_c_info *wlc) -+{ -+ uint callbacks = 0; -+ -+ if (wlc == NULL) -+ return 0; -+ -+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); -+ -+ callbacks += brcms_b_detach(wlc); -+ -+ /* delete software timers */ -+ if (!brcms_c_radio_monitor_stop(wlc)) -+ callbacks++; -+ -+ brcms_c_channel_mgr_detach(wlc->cmi); -+ -+ brcms_c_timers_deinit(wlc); -+ -+ brcms_c_detach_module(wlc); -+ -+ -+ while (wlc->tx_queues != NULL) -+ brcms_c_txq_free(wlc, wlc->tx_queues); -+ -+ brcms_c_detach_mfree(wlc); -+ return callbacks; -+} -+ -+/* update state that depends on the current value of "ap" */ -+static void brcms_c_ap_upd(struct brcms_c_info *wlc) -+{ -+ /* STA-BSS; short capable */ -+ wlc->PLCPHdr_override = BRCMS_PLCP_SHORT; -+ -+ /* fixup mpc */ -+ wlc->mpc = true; -+} -+ -+/* Initialize just the hardware when coming out of POR or S3/S5 system states */ -+static void brcms_b_hw_up(struct brcms_hardware *wlc_hw) -+{ -+ if (wlc_hw->wlc->pub->hw_up) -+ return; -+ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ /* -+ * Enable pll and xtal, initialize the power control registers, -+ * and force fastclock for the remainder of brcms_c_up(). -+ */ -+ brcms_b_xtal(wlc_hw, ON); -+ ai_clkctl_init(wlc_hw->sih); -+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); -+ -+ ai_pci_fixcfg(wlc_hw->sih); -+ -+ /* -+ * AI chip doesn't restore bar0win2 on -+ * hibernation/resume, need sw fixup -+ */ -+ if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || -+ (wlc_hw->sih->chip == BCM43225_CHIP_ID)) -+ wlc_hw->regs = (struct d11regs __iomem *) -+ ai_setcore(wlc_hw->sih, D11_CORE_ID, 0); -+ -+ /* -+ * Inform phy that a POR reset has occurred so -+ * it does a complete phy init -+ */ -+ wlc_phy_por_inform(wlc_hw->band->pi); -+ -+ wlc_hw->ucode_loaded = false; -+ wlc_hw->wlc->pub->hw_up = true; -+ -+ if ((wlc_hw->boardflags & BFL_FEM) -+ && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) { -+ if (! -+ (wlc_hw->boardrev >= 0x1250 -+ && (wlc_hw->boardflags & BFL_FEM_BT))) -+ ai_epa_4313war(wlc_hw->sih); -+ } -+} -+ -+static int brcms_b_up_prep(struct brcms_hardware *wlc_hw) -+{ -+ uint coremask; -+ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ /* -+ * Enable pll and xtal, initialize the power control registers, -+ * and force fastclock for the remainder of brcms_c_up(). -+ */ -+ brcms_b_xtal(wlc_hw, ON); -+ ai_clkctl_init(wlc_hw->sih); -+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); -+ -+ /* -+ * Configure pci/pcmcia here instead of in brcms_c_attach() -+ * to allow mfg hotswap: down, hotswap (chip power cycle), up. -+ */ -+ coremask = (1 << wlc_hw->wlc->core->coreidx); -+ -+ ai_pci_setup(wlc_hw->sih, coremask); -+ -+ /* -+ * Need to read the hwradio status here to cover the case where the -+ * system is loaded with the hw radio disabled. We do not want to -+ * bring the driver up in this case. -+ */ -+ if (brcms_b_radio_read_hwdisabled(wlc_hw)) { -+ /* put SB PCI in down state again */ -+ ai_pci_down(wlc_hw->sih); -+ brcms_b_xtal(wlc_hw, OFF); -+ return -ENOMEDIUM; -+ } -+ -+ ai_pci_up(wlc_hw->sih); -+ -+ /* reset the d11 core */ -+ brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); -+ -+ return 0; -+} -+ -+static int brcms_b_up_finish(struct brcms_hardware *wlc_hw) -+{ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ wlc_hw->up = true; -+ wlc_phy_hw_state_upd(wlc_hw->band->pi, true); -+ -+ /* FULLY enable dynamic power control and d11 core interrupt */ -+ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); -+ brcms_intrson(wlc_hw->wlc->wl); -+ return 0; -+} -+ -+/* -+ * Write WME tunable parameters for retransmit/max rate -+ * from wlc struct to ucode -+ */ -+static void brcms_c_wme_retries_write(struct brcms_c_info *wlc) -+{ -+ int ac; -+ -+ /* Need clock to do this */ -+ if (!wlc->clk) -+ return; -+ -+ for (ac = 0; ac < AC_COUNT; ac++) -+ brcms_b_write_shm(wlc->hw, M_AC_TXLMT_ADDR(ac), -+ wlc->wme_retries[ac]); -+} -+ -+/* make interface operational */ -+int brcms_c_up(struct brcms_c_info *wlc) -+{ -+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); -+ -+ /* HW is turned off so don't try to access it */ -+ if (wlc->pub->hw_off || brcms_deviceremoved(wlc)) -+ return -ENOMEDIUM; -+ -+ if (!wlc->pub->hw_up) { -+ brcms_b_hw_up(wlc->hw); -+ wlc->pub->hw_up = true; -+ } -+ -+ if ((wlc->pub->boardflags & BFL_FEM) -+ && (wlc->pub->sih->chip == BCM4313_CHIP_ID)) { -+ if (wlc->pub->boardrev >= 0x1250 -+ && (wlc->pub->boardflags & BFL_FEM_BT)) -+ brcms_b_mhf(wlc->hw, MHF5, MHF5_4313_GPIOCTRL, -+ MHF5_4313_GPIOCTRL, BRCM_BAND_ALL); -+ else -+ brcms_b_mhf(wlc->hw, MHF4, MHF4_EXTPA_ENABLE, -+ MHF4_EXTPA_ENABLE, BRCM_BAND_ALL); -+ } -+ -+ /* -+ * Need to read the hwradio status here to cover the case where the -+ * system is loaded with the hw radio disabled. We do not want to bring -+ * the driver up in this case. If radio is disabled, abort up, lower -+ * power, start radio timer and return 0(for NDIS) don't call -+ * radio_update to avoid looping brcms_c_up. -+ * -+ * brcms_b_up_prep() returns either 0 or -BCME_RADIOOFF only -+ */ -+ if (!wlc->pub->radio_disabled) { -+ int status = brcms_b_up_prep(wlc->hw); -+ if (status == -ENOMEDIUM) { -+ if (!mboolisset -+ (wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE)) { -+ struct brcms_bss_cfg *bsscfg = wlc->bsscfg; -+ mboolset(wlc->pub->radio_disabled, -+ WL_RADIO_HW_DISABLE); -+ -+ if (bsscfg->enable && bsscfg->BSS) -+ wiphy_err(wlc->wiphy, "wl%d: up" -+ ": rfdisable -> " -+ "bsscfg_disable()\n", -+ wlc->pub->unit); -+ } -+ } -+ } -+ -+ if (wlc->pub->radio_disabled) { -+ brcms_c_radio_monitor_start(wlc); -+ return 0; -+ } -+ -+ /* brcms_b_up_prep has done brcms_c_corereset(). so clk is on, set it */ -+ wlc->clk = true; -+ -+ brcms_c_radio_monitor_stop(wlc); -+ -+ /* Set EDCF hostflags */ -+ brcms_b_mhf(wlc->hw, MHF1, MHF1_EDCF, MHF1_EDCF, BRCM_BAND_ALL); -+ -+ brcms_init(wlc->wl); -+ wlc->pub->up = true; -+ -+ if (wlc->bandinit_pending) { -+ brcms_c_suspend_mac_and_wait(wlc); -+ brcms_c_set_chanspec(wlc, wlc->default_bss->chanspec); -+ wlc->bandinit_pending = false; -+ brcms_c_enable_mac(wlc); -+ } -+ -+ brcms_b_up_finish(wlc->hw); -+ -+ /* Program the TX wme params with the current settings */ -+ brcms_c_wme_retries_write(wlc); -+ -+ /* start one second watchdog timer */ -+ brcms_add_timer(wlc->wdtimer, TIMER_INTERVAL_WATCHDOG, true); -+ wlc->WDarmed = true; -+ -+ /* ensure antenna config is up to date */ -+ brcms_c_stf_phy_txant_upd(wlc); -+ /* ensure LDPC config is in sync */ -+ brcms_c_ht_update_ldpc(wlc, wlc->stf->ldpc); -+ -+ return 0; -+} -+ -+static uint brcms_c_down_del_timer(struct brcms_c_info *wlc) -+{ -+ uint callbacks = 0; -+ -+ return callbacks; -+} -+ -+static int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw) -+{ -+ bool dev_gone; -+ uint callbacks = 0; -+ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ if (!wlc_hw->up) -+ return callbacks; -+ -+ dev_gone = brcms_deviceremoved(wlc_hw->wlc); -+ -+ /* disable interrupts */ -+ if (dev_gone) -+ wlc_hw->wlc->macintmask = 0; -+ else { -+ /* now disable interrupts */ -+ brcms_intrsoff(wlc_hw->wlc->wl); -+ -+ /* ensure we're running on the pll clock again */ -+ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); -+ } -+ /* down phy at the last of this stage */ -+ callbacks += wlc_phy_down(wlc_hw->band->pi); -+ -+ return callbacks; -+} -+ -+static int brcms_b_down_finish(struct brcms_hardware *wlc_hw) -+{ -+ uint callbacks = 0; -+ bool dev_gone; -+ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ -+ if (!wlc_hw->up) -+ return callbacks; -+ -+ wlc_hw->up = false; -+ wlc_phy_hw_state_upd(wlc_hw->band->pi, false); -+ -+ dev_gone = brcms_deviceremoved(wlc_hw->wlc); -+ -+ if (dev_gone) { -+ wlc_hw->sbclk = false; -+ wlc_hw->clk = false; -+ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); -+ -+ /* reclaim any posted packets */ -+ brcms_c_flushqueues(wlc_hw->wlc); -+ } else { -+ -+ /* Reset and disable the core */ -+ if (ai_iscoreup(wlc_hw->sih)) { -+ if (R_REG(&wlc_hw->regs->maccontrol) & -+ MCTL_EN_MAC) -+ brcms_c_suspend_mac_and_wait(wlc_hw->wlc); -+ callbacks += brcms_reset(wlc_hw->wlc->wl); -+ brcms_c_coredisable(wlc_hw); -+ } -+ -+ /* turn off primary xtal and pll */ -+ if (!wlc_hw->noreset) { -+ ai_pci_down(wlc_hw->sih); -+ brcms_b_xtal(wlc_hw, OFF); -+ } -+ } -+ -+ return callbacks; -+} -+ -+/* -+ * Mark the interface nonoperational, stop the software mechanisms, -+ * disable the hardware, free any transient buffer state. -+ * Return a count of the number of driver callbacks still pending. -+ */ -+uint brcms_c_down(struct brcms_c_info *wlc) -+{ -+ -+ uint callbacks = 0; -+ int i; -+ bool dev_gone = false; -+ struct brcms_txq_info *qi; -+ -+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); -+ -+ /* check if we are already in the going down path */ -+ if (wlc->going_down) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: Driver going down so return" -+ "\n", wlc->pub->unit, __func__); -+ return 0; -+ } -+ if (!wlc->pub->up) -+ return callbacks; -+ -+ /* in between, mpc could try to bring down again.. */ -+ wlc->going_down = true; -+ -+ callbacks += brcms_b_bmac_down_prep(wlc->hw); -+ -+ dev_gone = brcms_deviceremoved(wlc); -+ -+ /* Call any registered down handlers */ -+ for (i = 0; i < BRCMS_MAXMODULES; i++) { -+ if (wlc->modulecb[i].down_fn) -+ callbacks += -+ wlc->modulecb[i].down_fn(wlc->modulecb[i].hdl); -+ } -+ -+ /* cancel the watchdog timer */ -+ if (wlc->WDarmed) { -+ if (!brcms_del_timer(wlc->wdtimer)) -+ callbacks++; -+ wlc->WDarmed = false; -+ } -+ /* cancel all other timers */ -+ callbacks += brcms_c_down_del_timer(wlc); -+ -+ wlc->pub->up = false; -+ -+ wlc_phy_mute_upd(wlc->band->pi, false, PHY_MUTE_ALL); -+ -+ /* clear txq flow control */ -+ brcms_c_txflowcontrol_reset(wlc); -+ -+ /* flush tx queues */ -+ for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) -+ brcmu_pktq_flush(&qi->q, true, NULL, NULL); -+ -+ callbacks += brcms_b_down_finish(wlc->hw); -+ -+ /* brcms_b_down_finish has done brcms_c_coredisable(). so clk is off */ -+ wlc->clk = false; -+ -+ wlc->going_down = false; -+ return callbacks; -+} -+ -+/* Set the current gmode configuration */ -+int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config) -+{ -+ int ret = 0; -+ uint i; -+ struct brcms_c_rateset rs; -+ /* Default to 54g Auto */ -+ /* Advertise and use shortslot (-1/0/1 Auto/Off/On) */ -+ s8 shortslot = BRCMS_SHORTSLOT_AUTO; -+ bool shortslot_restrict = false; /* Restrict association to stations -+ * that support shortslot -+ */ -+ bool ofdm_basic = false; /* Make 6, 12, and 24 basic rates */ -+ /* Advertise and use short preambles (-1/0/1 Auto/Off/On) */ -+ int preamble = BRCMS_PLCP_LONG; -+ bool preamble_restrict = false; /* Restrict association to stations -+ * that support short preambles -+ */ -+ struct brcms_band *band; -+ -+ /* if N-support is enabled, allow Gmode set as long as requested -+ * Gmode is not GMODE_LEGACY_B -+ */ -+ if ((wlc->pub->_n_enab & SUPPORT_11N) && gmode == GMODE_LEGACY_B) -+ return -ENOTSUPP; -+ -+ /* verify that we are dealing with 2G band and grab the band pointer */ -+ if (wlc->band->bandtype == BRCM_BAND_2G) -+ band = wlc->band; -+ else if ((wlc->pub->_nbands > 1) && -+ (wlc->bandstate[OTHERBANDUNIT(wlc)]->bandtype == BRCM_BAND_2G)) -+ band = wlc->bandstate[OTHERBANDUNIT(wlc)]; -+ else -+ return -EINVAL; -+ -+ /* Legacy or bust when no OFDM is supported by regulatory */ -+ if ((brcms_c_channel_locale_flags_in_band(wlc->cmi, band->bandunit) & -+ BRCMS_NO_OFDM) && (gmode != GMODE_LEGACY_B)) -+ return -EINVAL; -+ -+ /* update configuration value */ -+ if (config == true) -+ brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode); -+ -+ /* Clear rateset override */ -+ memset(&rs, 0, sizeof(struct brcms_c_rateset)); -+ -+ switch (gmode) { -+ case GMODE_LEGACY_B: -+ shortslot = BRCMS_SHORTSLOT_OFF; -+ brcms_c_rateset_copy(&gphy_legacy_rates, &rs); -+ -+ break; -+ -+ case GMODE_LRS: -+ break; -+ -+ case GMODE_AUTO: -+ /* Accept defaults */ -+ break; -+ -+ case GMODE_ONLY: -+ ofdm_basic = true; -+ preamble = BRCMS_PLCP_SHORT; -+ preamble_restrict = true; -+ break; -+ -+ case GMODE_PERFORMANCE: -+ shortslot = BRCMS_SHORTSLOT_ON; -+ shortslot_restrict = true; -+ ofdm_basic = true; -+ preamble = BRCMS_PLCP_SHORT; -+ preamble_restrict = true; -+ break; -+ -+ default: -+ /* Error */ -+ wiphy_err(wlc->wiphy, "wl%d: %s: invalid gmode %d\n", -+ wlc->pub->unit, __func__, gmode); -+ return -ENOTSUPP; -+ } -+ -+ band->gmode = gmode; -+ -+ wlc->shortslot_override = shortslot; -+ -+ /* Use the default 11g rateset */ -+ if (!rs.count) -+ brcms_c_rateset_copy(&cck_ofdm_rates, &rs); -+ -+ if (ofdm_basic) { -+ for (i = 0; i < rs.count; i++) { -+ if (rs.rates[i] == BRCM_RATE_6M -+ || rs.rates[i] == BRCM_RATE_12M -+ || rs.rates[i] == BRCM_RATE_24M) -+ rs.rates[i] |= BRCMS_RATE_FLAG; -+ } -+ } -+ -+ /* Set default bss rateset */ -+ wlc->default_bss->rateset.count = rs.count; -+ memcpy(wlc->default_bss->rateset.rates, rs.rates, -+ sizeof(wlc->default_bss->rateset.rates)); -+ -+ return ret; -+} -+ -+int brcms_c_set_nmode(struct brcms_c_info *wlc) -+{ -+ uint i; -+ s32 nmode = AUTO; -+ -+ if (wlc->stf->txstreams == WL_11N_3x3) -+ nmode = WL_11N_3x3; -+ else -+ nmode = WL_11N_2x2; -+ -+ /* force GMODE_AUTO if NMODE is ON */ -+ brcms_c_set_gmode(wlc, GMODE_AUTO, true); -+ if (nmode == WL_11N_3x3) -+ wlc->pub->_n_enab = SUPPORT_HT; -+ else -+ wlc->pub->_n_enab = SUPPORT_11N; -+ wlc->default_bss->flags |= BRCMS_BSS_HT; -+ /* add the mcs rates to the default and hw ratesets */ -+ brcms_c_rateset_mcs_build(&wlc->default_bss->rateset, -+ wlc->stf->txstreams); -+ for (i = 0; i < wlc->pub->_nbands; i++) -+ memcpy(wlc->bandstate[i]->hw_rateset.mcs, -+ wlc->default_bss->rateset.mcs, MCSSET_LEN); -+ -+ return 0; -+} -+ -+static int -+brcms_c_set_internal_rateset(struct brcms_c_info *wlc, -+ struct brcms_c_rateset *rs_arg) -+{ -+ struct brcms_c_rateset rs, new; -+ uint bandunit; -+ -+ memcpy(&rs, rs_arg, sizeof(struct brcms_c_rateset)); -+ -+ /* check for bad count value */ -+ if ((rs.count == 0) || (rs.count > BRCMS_NUMRATES)) -+ return -EINVAL; -+ -+ /* try the current band */ -+ bandunit = wlc->band->bandunit; -+ memcpy(&new, &rs, sizeof(struct brcms_c_rateset)); -+ if (brcms_c_rate_hwrs_filter_sort_validate -+ (&new, &wlc->bandstate[bandunit]->hw_rateset, true, -+ wlc->stf->txstreams)) -+ goto good; -+ -+ /* try the other band */ -+ if (brcms_is_mband_unlocked(wlc)) { -+ bandunit = OTHERBANDUNIT(wlc); -+ memcpy(&new, &rs, sizeof(struct brcms_c_rateset)); -+ if (brcms_c_rate_hwrs_filter_sort_validate(&new, -+ &wlc-> -+ bandstate[bandunit]-> -+ hw_rateset, true, -+ wlc->stf->txstreams)) -+ goto good; -+ } -+ -+ return -EBADE; -+ -+ good: -+ /* apply new rateset */ -+ memcpy(&wlc->default_bss->rateset, &new, -+ sizeof(struct brcms_c_rateset)); -+ memcpy(&wlc->bandstate[bandunit]->defrateset, &new, -+ sizeof(struct brcms_c_rateset)); -+ return 0; -+} -+ -+static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc) -+{ -+ u8 r; -+ bool war = false; -+ -+ if (wlc->bsscfg->associated) -+ r = wlc->bsscfg->current_bss->rateset.rates[0]; -+ else -+ r = wlc->default_bss->rateset.rates[0]; -+ -+ wlc_phy_ofdm_rateset_war(wlc->band->pi, war); -+} -+ -+int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel) -+{ -+ u16 chspec = ch20mhz_chspec(channel); -+ -+ if (channel < 0 || channel > MAXCHANNEL) -+ return -EINVAL; -+ -+ if (!brcms_c_valid_chanspec_db(wlc->cmi, chspec)) -+ return -EINVAL; -+ -+ -+ if (!wlc->pub->up && brcms_is_mband_unlocked(wlc)) { -+ if (wlc->band->bandunit != chspec_bandunit(chspec)) -+ wlc->bandinit_pending = true; -+ else -+ wlc->bandinit_pending = false; -+ } -+ -+ wlc->default_bss->chanspec = chspec; -+ /* brcms_c_BSSinit() will sanitize the rateset before -+ * using it.. */ -+ if (wlc->pub->up && (wlc_phy_chanspec_get(wlc->band->pi) != chspec)) { -+ brcms_c_set_home_chanspec(wlc, chspec); -+ brcms_c_suspend_mac_and_wait(wlc); -+ brcms_c_set_chanspec(wlc, chspec); -+ brcms_c_enable_mac(wlc); -+ } -+ return 0; -+} -+ -+int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl) -+{ -+ int ac; -+ -+ if (srl < 1 || srl > RETRY_SHORT_MAX || -+ lrl < 1 || lrl > RETRY_SHORT_MAX) -+ return -EINVAL; -+ -+ wlc->SRL = srl; -+ wlc->LRL = lrl; -+ -+ brcms_b_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL); -+ -+ for (ac = 0; ac < AC_COUNT; ac++) { -+ wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], -+ EDCF_SHORT, wlc->SRL); -+ wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], -+ EDCF_LONG, wlc->LRL); -+ } -+ brcms_c_wme_retries_write(wlc); -+ -+ return 0; -+} -+ -+void brcms_c_get_current_rateset(struct brcms_c_info *wlc, -+ struct brcm_rateset *currs) -+{ -+ struct brcms_c_rateset *rs; -+ -+ if (wlc->pub->associated) -+ rs = &wlc->bsscfg->current_bss->rateset; -+ else -+ rs = &wlc->default_bss->rateset; -+ -+ /* Copy only legacy rateset section */ -+ currs->count = rs->count; -+ memcpy(&currs->rates, &rs->rates, rs->count); -+} -+ -+int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs) -+{ -+ struct brcms_c_rateset internal_rs; -+ int bcmerror; -+ -+ if (rs->count > BRCMS_NUMRATES) -+ return -ENOBUFS; -+ -+ memset(&internal_rs, 0, sizeof(struct brcms_c_rateset)); -+ -+ /* Copy only legacy rateset section */ -+ internal_rs.count = rs->count; -+ memcpy(&internal_rs.rates, &rs->rates, internal_rs.count); -+ -+ /* merge rateset coming in with the current mcsset */ -+ if (wlc->pub->_n_enab & SUPPORT_11N) { -+ struct brcms_bss_info *mcsset_bss; -+ if (wlc->bsscfg->associated) -+ mcsset_bss = wlc->bsscfg->current_bss; -+ else -+ mcsset_bss = wlc->default_bss; -+ memcpy(internal_rs.mcs, &mcsset_bss->rateset.mcs[0], -+ MCSSET_LEN); -+ } -+ -+ bcmerror = brcms_c_set_internal_rateset(wlc, &internal_rs); -+ if (!bcmerror) -+ brcms_c_ofdm_rateset_war(wlc); -+ -+ return bcmerror; -+} -+ -+int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period) -+{ -+ if (period < DOT11_MIN_BEACON_PERIOD || -+ period > DOT11_MAX_BEACON_PERIOD) -+ return -EINVAL; -+ -+ wlc->default_bss->beacon_period = period; -+ return 0; -+} -+ -+u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx) -+{ -+ return wlc->band->phytype; -+} -+ -+void brcms_c_set_shortslot_override(struct brcms_c_info *wlc, s8 sslot_override) -+{ -+ wlc->shortslot_override = sslot_override; -+ -+ /* -+ * shortslot is an 11g feature, so no more work if we are -+ * currently on the 5G band -+ */ -+ if (wlc->band->bandtype == BRCM_BAND_5G) -+ return; -+ -+ if (wlc->pub->up && wlc->pub->associated) { -+ /* let watchdog or beacon processing update shortslot */ -+ } else if (wlc->pub->up) { -+ /* unassociated shortslot is off */ -+ brcms_c_switch_shortslot(wlc, false); -+ } else { -+ /* driver is down, so just update the brcms_c_info -+ * value */ -+ if (wlc->shortslot_override == BRCMS_SHORTSLOT_AUTO) -+ wlc->shortslot = false; -+ else -+ wlc->shortslot = -+ (wlc->shortslot_override == -+ BRCMS_SHORTSLOT_ON); -+ } -+} -+ -+/* -+ * register watchdog and down handlers. -+ */ -+int brcms_c_module_register(struct brcms_pub *pub, -+ const char *name, struct brcms_info *hdl, -+ int (*d_fn)(void *handle)) -+{ -+ struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc; -+ int i; -+ -+ /* find an empty entry and just add, no duplication check! */ -+ for (i = 0; i < BRCMS_MAXMODULES; i++) { -+ if (wlc->modulecb[i].name[0] == '\0') { -+ strncpy(wlc->modulecb[i].name, name, -+ sizeof(wlc->modulecb[i].name) - 1); -+ wlc->modulecb[i].hdl = hdl; -+ wlc->modulecb[i].down_fn = d_fn; -+ return 0; -+ } -+ } -+ -+ return -ENOSR; -+} -+ -+/* unregister module callbacks */ -+int brcms_c_module_unregister(struct brcms_pub *pub, const char *name, -+ struct brcms_info *hdl) -+{ -+ struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc; -+ int i; -+ -+ if (wlc == NULL) -+ return -ENODATA; -+ -+ for (i = 0; i < BRCMS_MAXMODULES; i++) { -+ if (!strcmp(wlc->modulecb[i].name, name) && -+ (wlc->modulecb[i].hdl == hdl)) { -+ memset(&wlc->modulecb[i], 0, sizeof(struct modulecb)); -+ return 0; -+ } -+ } -+ -+ /* table not found! */ -+ return -ENODATA; -+} -+ -+#ifdef BCMDBG -+static const char * const supr_reason[] = { -+ "None", "PMQ Entry", "Flush request", -+ "Previous frag failure", "Channel mismatch", -+ "Lifetime Expiry", "Underflow" -+}; -+ -+static void brcms_c_print_txs_status(u16 s) -+{ -+ printk(KERN_DEBUG "[15:12] %d frame attempts\n", -+ (s & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT); -+ printk(KERN_DEBUG " [11:8] %d rts attempts\n", -+ (s & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT); -+ printk(KERN_DEBUG " [7] %d PM mode indicated\n", -+ ((s & TX_STATUS_PMINDCTD) ? 1 : 0)); -+ printk(KERN_DEBUG " [6] %d intermediate status\n", -+ ((s & TX_STATUS_INTERMEDIATE) ? 1 : 0)); -+ printk(KERN_DEBUG " [5] %d AMPDU\n", -+ (s & TX_STATUS_AMPDU) ? 1 : 0); -+ printk(KERN_DEBUG " [4:2] %d Frame Suppressed Reason (%s)\n", -+ ((s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT), -+ supr_reason[(s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT]); -+ printk(KERN_DEBUG " [1] %d acked\n", -+ ((s & TX_STATUS_ACK_RCV) ? 1 : 0)); -+} -+#endif /* BCMDBG */ -+ -+void brcms_c_print_txstatus(struct tx_status *txs) -+{ -+#if defined(BCMDBG) -+ u16 s = txs->status; -+ u16 ackphyrxsh = txs->ackphyrxsh; -+ -+ printk(KERN_DEBUG "\ntxpkt (MPDU) Complete\n"); -+ -+ printk(KERN_DEBUG "FrameID: %04x ", txs->frameid); -+ printk(KERN_DEBUG "TxStatus: %04x", s); -+ printk(KERN_DEBUG "\n"); -+ -+ brcms_c_print_txs_status(s); -+ -+ printk(KERN_DEBUG "LastTxTime: %04x ", txs->lasttxtime); -+ printk(KERN_DEBUG "Seq: %04x ", txs->sequence); -+ printk(KERN_DEBUG "PHYTxStatus: %04x ", txs->phyerr); -+ printk(KERN_DEBUG "RxAckRSSI: %04x ", -+ (ackphyrxsh & PRXS1_JSSI_MASK) >> PRXS1_JSSI_SHIFT); -+ printk(KERN_DEBUG "RxAckSQ: %04x", -+ (ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT); -+ printk(KERN_DEBUG "\n"); -+#endif /* defined(BCMDBG) */ -+} -+ -+bool brcms_c_chipmatch(u16 vendor, u16 device) -+{ -+ if (vendor != PCI_VENDOR_ID_BROADCOM) { -+ pr_err("chipmatch: unknown vendor id %04x\n", vendor); -+ return false; -+ } -+ -+ if (device == BCM43224_D11N_ID_VEN1) -+ return true; -+ if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID)) -+ return true; -+ if (device == BCM4313_D11N2G_ID) -+ return true; -+ if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID)) -+ return true; -+ -+ pr_err("chipmatch: unknown device id %04x\n", device); -+ return false; -+} -+ -+#if defined(BCMDBG) -+void brcms_c_print_txdesc(struct d11txh *txh) -+{ -+ u16 mtcl = le16_to_cpu(txh->MacTxControlLow); -+ u16 mtch = le16_to_cpu(txh->MacTxControlHigh); -+ u16 mfc = le16_to_cpu(txh->MacFrameControl); -+ u16 tfest = le16_to_cpu(txh->TxFesTimeNormal); -+ u16 ptcw = le16_to_cpu(txh->PhyTxControlWord); -+ u16 ptcw_1 = le16_to_cpu(txh->PhyTxControlWord_1); -+ u16 ptcw_1_Fbr = le16_to_cpu(txh->PhyTxControlWord_1_Fbr); -+ u16 ptcw_1_Rts = le16_to_cpu(txh->PhyTxControlWord_1_Rts); -+ u16 ptcw_1_FbrRts = le16_to_cpu(txh->PhyTxControlWord_1_FbrRts); -+ u16 mainrates = le16_to_cpu(txh->MainRates); -+ u16 xtraft = le16_to_cpu(txh->XtraFrameTypes); -+ u8 *iv = txh->IV; -+ u8 *ra = txh->TxFrameRA; -+ u16 tfestfb = le16_to_cpu(txh->TxFesTimeFallback); -+ u8 *rtspfb = txh->RTSPLCPFallback; -+ u16 rtsdfb = le16_to_cpu(txh->RTSDurFallback); -+ u8 *fragpfb = txh->FragPLCPFallback; -+ u16 fragdfb = le16_to_cpu(txh->FragDurFallback); -+ u16 mmodelen = le16_to_cpu(txh->MModeLen); -+ u16 mmodefbrlen = le16_to_cpu(txh->MModeFbrLen); -+ u16 tfid = le16_to_cpu(txh->TxFrameID); -+ u16 txs = le16_to_cpu(txh->TxStatus); -+ u16 mnmpdu = le16_to_cpu(txh->MaxNMpdus); -+ u16 mabyte = le16_to_cpu(txh->MaxABytes_MRT); -+ u16 mabyte_f = le16_to_cpu(txh->MaxABytes_FBR); -+ u16 mmbyte = le16_to_cpu(txh->MinMBytes); -+ -+ u8 *rtsph = txh->RTSPhyHeader; -+ struct ieee80211_rts rts = txh->rts_frame; -+ char hexbuf[256]; -+ -+ /* add plcp header along with txh descriptor */ -+ printk(KERN_DEBUG "Raw TxDesc + plcp header:\n"); -+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, -+ txh, sizeof(struct d11txh) + 48); -+ -+ printk(KERN_DEBUG "TxCtlLow: %04x ", mtcl); -+ printk(KERN_DEBUG "TxCtlHigh: %04x ", mtch); -+ printk(KERN_DEBUG "FC: %04x ", mfc); -+ printk(KERN_DEBUG "FES Time: %04x\n", tfest); -+ printk(KERN_DEBUG "PhyCtl: %04x%s ", ptcw, -+ (ptcw & PHY_TXC_SHORT_HDR) ? " short" : ""); -+ printk(KERN_DEBUG "PhyCtl_1: %04x ", ptcw_1); -+ printk(KERN_DEBUG "PhyCtl_1_Fbr: %04x\n", ptcw_1_Fbr); -+ printk(KERN_DEBUG "PhyCtl_1_Rts: %04x ", ptcw_1_Rts); -+ printk(KERN_DEBUG "PhyCtl_1_Fbr_Rts: %04x\n", ptcw_1_FbrRts); -+ printk(KERN_DEBUG "MainRates: %04x ", mainrates); -+ printk(KERN_DEBUG "XtraFrameTypes: %04x ", xtraft); -+ printk(KERN_DEBUG "\n"); -+ -+ brcmu_format_hex(hexbuf, iv, sizeof(txh->IV)); -+ printk(KERN_DEBUG "SecIV: %s\n", hexbuf); -+ brcmu_format_hex(hexbuf, ra, sizeof(txh->TxFrameRA)); -+ printk(KERN_DEBUG "RA: %s\n", hexbuf); -+ -+ printk(KERN_DEBUG "Fb FES Time: %04x ", tfestfb); -+ brcmu_format_hex(hexbuf, rtspfb, sizeof(txh->RTSPLCPFallback)); -+ printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf); -+ printk(KERN_DEBUG "RTS DUR: %04x ", rtsdfb); -+ brcmu_format_hex(hexbuf, fragpfb, sizeof(txh->FragPLCPFallback)); -+ printk(KERN_DEBUG "PLCP: %s ", hexbuf); -+ printk(KERN_DEBUG "DUR: %04x", fragdfb); -+ printk(KERN_DEBUG "\n"); -+ -+ printk(KERN_DEBUG "MModeLen: %04x ", mmodelen); -+ printk(KERN_DEBUG "MModeFbrLen: %04x\n", mmodefbrlen); -+ -+ printk(KERN_DEBUG "FrameID: %04x\n", tfid); -+ printk(KERN_DEBUG "TxStatus: %04x\n", txs); -+ -+ printk(KERN_DEBUG "MaxNumMpdu: %04x\n", mnmpdu); -+ printk(KERN_DEBUG "MaxAggbyte: %04x\n", mabyte); -+ printk(KERN_DEBUG "MaxAggbyte_fb: %04x\n", mabyte_f); -+ printk(KERN_DEBUG "MinByte: %04x\n", mmbyte); -+ -+ brcmu_format_hex(hexbuf, rtsph, sizeof(txh->RTSPhyHeader)); -+ printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf); -+ brcmu_format_hex(hexbuf, (u8 *) &rts, sizeof(txh->rts_frame)); -+ printk(KERN_DEBUG "RTS Frame: %s", hexbuf); -+ printk(KERN_DEBUG "\n"); -+} -+#endif /* defined(BCMDBG) */ -+ -+#if defined(BCMDBG) -+int -+brcms_c_format_flags(const struct brcms_c_bit_desc *bd, u32 flags, char *buf, -+ int len) -+{ -+ int i; -+ char *p = buf; -+ char hexstr[16]; -+ int slen = 0, nlen = 0; -+ u32 bit; -+ const char *name; -+ -+ if (len < 2 || !buf) -+ return 0; -+ -+ buf[0] = '\0'; -+ -+ for (i = 0; flags != 0; i++) { -+ bit = bd[i].bit; -+ name = bd[i].name; -+ if (bit == 0 && flags != 0) { -+ /* print any unnamed bits */ -+ snprintf(hexstr, 16, "0x%X", flags); -+ name = hexstr; -+ flags = 0; /* exit loop */ -+ } else if ((flags & bit) == 0) -+ continue; -+ flags &= ~bit; -+ nlen = strlen(name); -+ slen += nlen; -+ /* count btwn flag space */ -+ if (flags != 0) -+ slen += 1; -+ /* need NULL char as well */ -+ if (len <= slen) -+ break; -+ /* copy NULL char but don't count it */ -+ strncpy(p, name, nlen + 1); -+ p += nlen; -+ /* copy btwn flag space and NULL char */ -+ if (flags != 0) -+ p += snprintf(p, 2, " "); -+ len -= slen; -+ } -+ -+ /* indicate the str was too short */ -+ if (flags != 0) { -+ if (len < 2) -+ p -= 2 - len; /* overwrite last char */ -+ p += snprintf(p, 2, ">"); -+ } -+ -+ return (int)(p - buf); -+} -+#endif /* defined(BCMDBG) */ -+ -+#if defined(BCMDBG) -+void brcms_c_print_rxh(struct d11rxhdr *rxh) -+{ -+ u16 len = rxh->RxFrameSize; -+ u16 phystatus_0 = rxh->PhyRxStatus_0; -+ u16 phystatus_1 = rxh->PhyRxStatus_1; -+ u16 phystatus_2 = rxh->PhyRxStatus_2; -+ u16 phystatus_3 = rxh->PhyRxStatus_3; -+ u16 macstatus1 = rxh->RxStatus1; -+ u16 macstatus2 = rxh->RxStatus2; -+ char flagstr[64]; -+ char lenbuf[20]; -+ static const struct brcms_c_bit_desc macstat_flags[] = { -+ {RXS_FCSERR, "FCSErr"}, -+ {RXS_RESPFRAMETX, "Reply"}, -+ {RXS_PBPRES, "PADDING"}, -+ {RXS_DECATMPT, "DeCr"}, -+ {RXS_DECERR, "DeCrErr"}, -+ {RXS_BCNSENT, "Bcn"}, -+ {0, NULL} -+ }; -+ -+ printk(KERN_DEBUG "Raw RxDesc:\n"); -+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, rxh, -+ sizeof(struct d11rxhdr)); -+ -+ brcms_c_format_flags(macstat_flags, macstatus1, flagstr, 64); -+ -+ snprintf(lenbuf, sizeof(lenbuf), "0x%x", len); -+ -+ printk(KERN_DEBUG "RxFrameSize: %6s (%d)%s\n", lenbuf, len, -+ (rxh->PhyRxStatus_0 & PRXS0_SHORTH) ? " short preamble" : ""); -+ printk(KERN_DEBUG "RxPHYStatus: %04x %04x %04x %04x\n", -+ phystatus_0, phystatus_1, phystatus_2, phystatus_3); -+ printk(KERN_DEBUG "RxMACStatus: %x %s\n", macstatus1, flagstr); -+ printk(KERN_DEBUG "RXMACaggtype: %x\n", -+ (macstatus2 & RXS_AGGTYPE_MASK)); -+ printk(KERN_DEBUG "RxTSFTime: %04x\n", rxh->RxTSFTime); -+} -+#endif /* defined(BCMDBG) */ -+ -+u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate) -+{ -+ u16 table_ptr; -+ u8 phy_rate, index; -+ -+ /* get the phy specific rate encoding for the PLCP SIGNAL field */ -+ if (is_ofdm_rate(rate)) -+ table_ptr = M_RT_DIRMAP_A; -+ else -+ table_ptr = M_RT_DIRMAP_B; -+ -+ /* for a given rate, the LS-nibble of the PLCP SIGNAL field is -+ * the index into the rate table. -+ */ -+ phy_rate = rate_info[rate] & BRCMS_RATE_MASK; -+ index = phy_rate & 0xf; -+ -+ /* Find the SHM pointer to the rate table entry by looking in the -+ * Direct-map Table -+ */ -+ return 2 * brcms_b_read_shm(wlc_hw, table_ptr + (index * 2)); -+} -+ -+static bool -+brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q, -+ struct sk_buff *pkt, int prec, bool head) -+{ -+ struct sk_buff *p; -+ int eprec = -1; /* precedence to evict from */ -+ -+ /* Determine precedence from which to evict packet, if any */ -+ if (pktq_pfull(q, prec)) -+ eprec = prec; -+ else if (pktq_full(q)) { -+ p = brcmu_pktq_peek_tail(q, &eprec); -+ if (eprec > prec) { -+ wiphy_err(wlc->wiphy, "%s: Failing: eprec %d > prec %d" -+ "\n", __func__, eprec, prec); -+ return false; -+ } -+ } -+ -+ /* Evict if needed */ -+ if (eprec >= 0) { -+ bool discard_oldest; -+ -+ discard_oldest = ac_bitmap_tst(0, eprec); -+ -+ /* Refuse newer packet unless configured to discard oldest */ -+ if (eprec == prec && !discard_oldest) { -+ wiphy_err(wlc->wiphy, "%s: No where to go, prec == %d" -+ "\n", __func__, prec); -+ return false; -+ } -+ -+ /* Evict packet according to discard policy */ -+ p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) : -+ brcmu_pktq_pdeq_tail(q, eprec); -+ brcmu_pkt_buf_free_skb(p); -+ } -+ -+ /* Enqueue */ -+ if (head) -+ p = brcmu_pktq_penq_head(q, prec, pkt); -+ else -+ p = brcmu_pktq_penq(q, prec, pkt); -+ -+ return true; -+} -+ -+/* -+ * Attempts to queue a packet onto a multiple-precedence queue, -+ * if necessary evicting a lower precedence packet from the queue. -+ * -+ * 'prec' is the precedence number that has already been mapped -+ * from the packet priority. -+ * -+ * Returns true if packet consumed (queued), false if not. -+ */ -+static bool brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q, -+ struct sk_buff *pkt, int prec) -+{ -+ return brcms_c_prec_enq_head(wlc, q, pkt, prec, false); -+} -+ -+void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb, -+ struct sk_buff *sdu, uint prec) -+{ -+ struct brcms_txq_info *qi = wlc->pkt_queue; /* Check me */ -+ struct pktq *q = &qi->q; -+ int prio; -+ -+ prio = sdu->priority; -+ -+ if (!brcms_c_prec_enq(wlc, q, sdu, prec)) { -+ /* -+ * we might hit this condtion in case -+ * packet flooding from mac80211 stack -+ */ -+ brcmu_pkt_buf_free_skb(sdu); -+ } -+} -+ -+/* -+ * bcmc_fid_generate: -+ * Generate frame ID for a BCMC packet. The frag field is not used -+ * for MC frames so is used as part of the sequence number. -+ */ -+static inline u16 -+bcmc_fid_generate(struct brcms_c_info *wlc, struct brcms_bss_cfg *bsscfg, -+ struct d11txh *txh) -+{ -+ u16 frameid; -+ -+ frameid = le16_to_cpu(txh->TxFrameID) & ~(TXFID_SEQ_MASK | -+ TXFID_QUEUE_MASK); -+ frameid |= -+ (((wlc-> -+ mc_fid_counter++) << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) | -+ TX_BCMC_FIFO; -+ -+ return frameid; -+} -+ -+static uint -+brcms_c_calc_ack_time(struct brcms_c_info *wlc, u32 rspec, -+ u8 preamble_type) -+{ -+ uint dur = 0; -+ -+ BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d\n", -+ wlc->pub->unit, rspec, preamble_type); -+ /* -+ * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that -+ * is less than or equal to the rate of the immediately previous -+ * frame in the FES -+ */ -+ rspec = brcms_basic_rate(wlc, rspec); -+ /* ACK frame len == 14 == 2(fc) + 2(dur) + 6(ra) + 4(fcs) */ -+ dur = -+ brcms_c_calc_frame_time(wlc, rspec, preamble_type, -+ (DOT11_ACK_LEN + FCS_LEN)); -+ return dur; -+} -+ -+static uint -+brcms_c_calc_cts_time(struct brcms_c_info *wlc, u32 rspec, -+ u8 preamble_type) -+{ -+ BCMMSG(wlc->wiphy, "wl%d: ratespec 0x%x, preamble_type %d\n", -+ wlc->pub->unit, rspec, preamble_type); -+ return brcms_c_calc_ack_time(wlc, rspec, preamble_type); -+} -+ -+static uint -+brcms_c_calc_ba_time(struct brcms_c_info *wlc, u32 rspec, -+ u8 preamble_type) -+{ -+ BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, " -+ "preamble_type %d\n", wlc->pub->unit, rspec, preamble_type); -+ /* -+ * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that -+ * is less than or equal to the rate of the immediately previous -+ * frame in the FES -+ */ -+ rspec = brcms_basic_rate(wlc, rspec); -+ /* BA len == 32 == 16(ctl hdr) + 4(ba len) + 8(bitmap) + 4(fcs) */ -+ return brcms_c_calc_frame_time(wlc, rspec, preamble_type, -+ (DOT11_BA_LEN + DOT11_BA_BITMAP_LEN + -+ FCS_LEN)); -+} -+ -+/* brcms_c_compute_frame_dur() -+ * -+ * Calculate the 802.11 MAC header DUR field for MPDU -+ * DUR for a single frame = 1 SIFS + 1 ACK -+ * DUR for a frame with following frags = 3 SIFS + 2 ACK + next frag time -+ * -+ * rate MPDU rate in unit of 500kbps -+ * next_frag_len next MPDU length in bytes -+ * preamble_type use short/GF or long/MM PLCP header -+ */ -+static u16 -+brcms_c_compute_frame_dur(struct brcms_c_info *wlc, u32 rate, -+ u8 preamble_type, uint next_frag_len) -+{ -+ u16 dur, sifs; -+ -+ sifs = get_sifs(wlc->band); -+ -+ dur = sifs; -+ dur += (u16) brcms_c_calc_ack_time(wlc, rate, preamble_type); -+ -+ if (next_frag_len) { -+ /* Double the current DUR to get 2 SIFS + 2 ACKs */ -+ dur *= 2; -+ /* add another SIFS and the frag time */ -+ dur += sifs; -+ dur += -+ (u16) brcms_c_calc_frame_time(wlc, rate, preamble_type, -+ next_frag_len); -+ } -+ return dur; -+} -+ -+/* The opposite of brcms_c_calc_frame_time */ -+static uint -+brcms_c_calc_frame_len(struct brcms_c_info *wlc, u32 ratespec, -+ u8 preamble_type, uint dur) -+{ -+ uint nsyms, mac_len, Ndps, kNdps; -+ uint rate = rspec2rate(ratespec); -+ -+ BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, dur %d\n", -+ wlc->pub->unit, ratespec, preamble_type, dur); -+ -+ if (is_mcs_rate(ratespec)) { -+ uint mcs = ratespec & RSPEC_RATE_MASK; -+ int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec); -+ dur -= PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT); -+ /* payload calculation matches that of regular ofdm */ -+ if (wlc->band->bandtype == BRCM_BAND_2G) -+ dur -= DOT11_OFDM_SIGNAL_EXTENSION; -+ /* kNdbps = kbps * 4 */ -+ kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec), -+ rspec_issgi(ratespec)) * 4; -+ nsyms = dur / APHY_SYMBOL_TIME; -+ mac_len = -+ ((nsyms * kNdps) - -+ ((APHY_SERVICE_NBITS + APHY_TAIL_NBITS) * 1000)) / 8000; -+ } else if (is_ofdm_rate(ratespec)) { -+ dur -= APHY_PREAMBLE_TIME; -+ dur -= APHY_SIGNAL_TIME; -+ /* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */ -+ Ndps = rate * 2; -+ nsyms = dur / APHY_SYMBOL_TIME; -+ mac_len = -+ ((nsyms * Ndps) - -+ (APHY_SERVICE_NBITS + APHY_TAIL_NBITS)) / 8; -+ } else { -+ if (preamble_type & BRCMS_SHORT_PREAMBLE) -+ dur -= BPHY_PLCP_SHORT_TIME; -+ else -+ dur -= BPHY_PLCP_TIME; -+ mac_len = dur * rate; -+ /* divide out factor of 2 in rate (1/2 mbps) */ -+ mac_len = mac_len / 8 / 2; -+ } -+ return mac_len; -+} -+ -+/* -+ * Return true if the specified rate is supported by the specified band. -+ * BRCM_BAND_AUTO indicates the current band. -+ */ -+static bool brcms_c_valid_rate(struct brcms_c_info *wlc, u32 rspec, int band, -+ bool verbose) -+{ -+ struct brcms_c_rateset *hw_rateset; -+ uint i; -+ -+ if ((band == BRCM_BAND_AUTO) || (band == wlc->band->bandtype)) -+ hw_rateset = &wlc->band->hw_rateset; -+ else if (wlc->pub->_nbands > 1) -+ hw_rateset = &wlc->bandstate[OTHERBANDUNIT(wlc)]->hw_rateset; -+ else -+ /* other band specified and we are a single band device */ -+ return false; -+ -+ /* check if this is a mimo rate */ -+ if (is_mcs_rate(rspec)) { -+ if ((rspec & RSPEC_RATE_MASK) >= MCS_TABLE_SIZE) -+ goto error; -+ -+ return isset(hw_rateset->mcs, (rspec & RSPEC_RATE_MASK)); -+ } -+ -+ for (i = 0; i < hw_rateset->count; i++) -+ if (hw_rateset->rates[i] == rspec2rate(rspec)) -+ return true; -+ error: -+ if (verbose) -+ wiphy_err(wlc->wiphy, "wl%d: valid_rate: rate spec 0x%x " -+ "not in hw_rateset\n", wlc->pub->unit, rspec); -+ -+ return false; -+} -+ -+static u32 -+mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band, -+ u32 int_val) -+{ -+ u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT; -+ u8 rate = int_val & NRATE_RATE_MASK; -+ u32 rspec; -+ bool ismcs = ((int_val & NRATE_MCS_INUSE) == NRATE_MCS_INUSE); -+ bool issgi = ((int_val & NRATE_SGI_MASK) >> NRATE_SGI_SHIFT); -+ bool override_mcs_only = ((int_val & NRATE_OVERRIDE_MCS_ONLY) -+ == NRATE_OVERRIDE_MCS_ONLY); -+ int bcmerror = 0; -+ -+ if (!ismcs) -+ return (u32) rate; -+ -+ /* validate the combination of rate/mcs/stf is allowed */ -+ if ((wlc->pub->_n_enab & SUPPORT_11N) && ismcs) { -+ /* mcs only allowed when nmode */ -+ if (stf > PHY_TXC1_MODE_SDM) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid stf\n", -+ wlc->pub->unit, __func__); -+ bcmerror = -EINVAL; -+ goto done; -+ } -+ -+ /* mcs 32 is a special case, DUP mode 40 only */ -+ if (rate == 32) { -+ if (!CHSPEC_IS40(wlc->home_chanspec) || -+ ((stf != PHY_TXC1_MODE_SISO) -+ && (stf != PHY_TXC1_MODE_CDD))) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid mcs " -+ "32\n", wlc->pub->unit, __func__); -+ bcmerror = -EINVAL; -+ goto done; -+ } -+ /* mcs > 7 must use stf SDM */ -+ } else if (rate > HIGHEST_SINGLE_STREAM_MCS) { -+ /* mcs > 7 must use stf SDM */ -+ if (stf != PHY_TXC1_MODE_SDM) { -+ BCMMSG(wlc->wiphy, "wl%d: enabling " -+ "SDM mode for mcs %d\n", -+ wlc->pub->unit, rate); -+ stf = PHY_TXC1_MODE_SDM; -+ } -+ } else { -+ /* -+ * MCS 0-7 may use SISO, CDD, and for -+ * phy_rev >= 3 STBC -+ */ -+ if ((stf > PHY_TXC1_MODE_STBC) || -+ (!BRCMS_STBC_CAP_PHY(wlc) -+ && (stf == PHY_TXC1_MODE_STBC))) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid STBC" -+ "\n", wlc->pub->unit, __func__); -+ bcmerror = -EINVAL; -+ goto done; -+ } -+ } -+ } else if (is_ofdm_rate(rate)) { -+ if ((stf != PHY_TXC1_MODE_CDD) && (stf != PHY_TXC1_MODE_SISO)) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid OFDM\n", -+ wlc->pub->unit, __func__); -+ bcmerror = -EINVAL; -+ goto done; -+ } -+ } else if (is_cck_rate(rate)) { -+ if ((cur_band->bandtype != BRCM_BAND_2G) -+ || (stf != PHY_TXC1_MODE_SISO)) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid CCK\n", -+ wlc->pub->unit, __func__); -+ bcmerror = -EINVAL; -+ goto done; -+ } -+ } else { -+ wiphy_err(wlc->wiphy, "wl%d: %s: Unknown rate type\n", -+ wlc->pub->unit, __func__); -+ bcmerror = -EINVAL; -+ goto done; -+ } -+ /* make sure multiple antennae are available for non-siso rates */ -+ if ((stf != PHY_TXC1_MODE_SISO) && (wlc->stf->txstreams == 1)) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: SISO antenna but !SISO " -+ "request\n", wlc->pub->unit, __func__); -+ bcmerror = -EINVAL; -+ goto done; -+ } -+ -+ rspec = rate; -+ if (ismcs) { -+ rspec |= RSPEC_MIMORATE; -+ /* For STBC populate the STC field of the ratespec */ -+ if (stf == PHY_TXC1_MODE_STBC) { -+ u8 stc; -+ stc = 1; /* Nss for single stream is always 1 */ -+ rspec |= (stc << RSPEC_STC_SHIFT); -+ } -+ } -+ -+ rspec |= (stf << RSPEC_STF_SHIFT); -+ -+ if (override_mcs_only) -+ rspec |= RSPEC_OVERRIDE_MCS_ONLY; -+ -+ if (issgi) -+ rspec |= RSPEC_SHORT_GI; -+ -+ if ((rate != 0) -+ && !brcms_c_valid_rate(wlc, rspec, cur_band->bandtype, true)) -+ return rate; -+ -+ return rspec; -+done: -+ return rate; -+} -+ -+/* -+ * Compute PLCP, but only requires actual rate and length of pkt. -+ * Rate is given in the driver standard multiple of 500 kbps. -+ * le is set for 11 Mbps rate if necessary. -+ * Broken out for PRQ. -+ */ -+ -+static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500, -+ uint length, u8 *plcp) -+{ -+ u16 usec = 0; -+ u8 le = 0; -+ -+ switch (rate_500) { -+ case BRCM_RATE_1M: -+ usec = length << 3; -+ break; -+ case BRCM_RATE_2M: -+ usec = length << 2; -+ break; -+ case BRCM_RATE_5M5: -+ usec = (length << 4) / 11; -+ if ((length << 4) - (usec * 11) > 0) -+ usec++; -+ break; -+ case BRCM_RATE_11M: -+ usec = (length << 3) / 11; -+ if ((length << 3) - (usec * 11) > 0) { -+ usec++; -+ if ((usec * 11) - (length << 3) >= 8) -+ le = D11B_PLCP_SIGNAL_LE; -+ } -+ break; -+ -+ default: -+ wiphy_err(wlc->wiphy, -+ "brcms_c_cck_plcp_set: unsupported rate %d\n", -+ rate_500); -+ rate_500 = BRCM_RATE_1M; -+ usec = length << 3; -+ break; -+ } -+ /* PLCP signal byte */ -+ plcp[0] = rate_500 * 5; /* r (500kbps) * 5 == r (100kbps) */ -+ /* PLCP service byte */ -+ plcp[1] = (u8) (le | D11B_PLCP_SIGNAL_LOCKED); -+ /* PLCP length u16, little endian */ -+ plcp[2] = usec & 0xff; -+ plcp[3] = (usec >> 8) & 0xff; -+ /* PLCP CRC16 */ -+ plcp[4] = 0; -+ plcp[5] = 0; -+} -+ -+/* Rate: 802.11 rate code, length: PSDU length in octets */ -+static void brcms_c_compute_mimo_plcp(u32 rspec, uint length, u8 *plcp) -+{ -+ u8 mcs = (u8) (rspec & RSPEC_RATE_MASK); -+ plcp[0] = mcs; -+ if (rspec_is40mhz(rspec) || (mcs == 32)) -+ plcp[0] |= MIMO_PLCP_40MHZ; -+ BRCMS_SET_MIMO_PLCP_LEN(plcp, length); -+ plcp[3] = rspec_mimoplcp3(rspec); /* rspec already holds this byte */ -+ plcp[3] |= 0x7; /* set smoothing, not sounding ppdu & reserved */ -+ plcp[4] = 0; /* number of extension spatial streams bit 0 & 1 */ -+ plcp[5] = 0; -+} -+ -+/* Rate: 802.11 rate code, length: PSDU length in octets */ -+static void -+brcms_c_compute_ofdm_plcp(u32 rspec, u32 length, u8 *plcp) -+{ -+ u8 rate_signal; -+ u32 tmp = 0; -+ int rate = rspec2rate(rspec); -+ -+ /* -+ * encode rate per 802.11a-1999 sec 17.3.4.1, with lsb -+ * transmitted first -+ */ -+ rate_signal = rate_info[rate] & BRCMS_RATE_MASK; -+ memset(plcp, 0, D11_PHY_HDR_LEN); -+ D11A_PHY_HDR_SRATE((struct ofdm_phy_hdr *) plcp, rate_signal); -+ -+ tmp = (length & 0xfff) << 5; -+ plcp[2] |= (tmp >> 16) & 0xff; -+ plcp[1] |= (tmp >> 8) & 0xff; -+ plcp[0] |= tmp & 0xff; -+} -+ -+/* Rate: 802.11 rate code, length: PSDU length in octets */ -+static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, u32 rspec, -+ uint length, u8 *plcp) -+{ -+ int rate = rspec2rate(rspec); -+ -+ brcms_c_cck_plcp_set(wlc, rate, length, plcp); -+} -+ -+static void -+brcms_c_compute_plcp(struct brcms_c_info *wlc, u32 rspec, -+ uint length, u8 *plcp) -+{ -+ if (is_mcs_rate(rspec)) -+ brcms_c_compute_mimo_plcp(rspec, length, plcp); -+ else if (is_ofdm_rate(rspec)) -+ brcms_c_compute_ofdm_plcp(rspec, length, plcp); -+ else -+ brcms_c_compute_cck_plcp(wlc, rspec, length, plcp); -+} -+ -+/* brcms_c_compute_rtscts_dur() -+ * -+ * Calculate the 802.11 MAC header DUR field for an RTS or CTS frame -+ * DUR for normal RTS/CTS w/ frame = 3 SIFS + 1 CTS + next frame time + 1 ACK -+ * DUR for CTS-TO-SELF w/ frame = 2 SIFS + next frame time + 1 ACK -+ * -+ * cts cts-to-self or rts/cts -+ * rts_rate rts or cts rate in unit of 500kbps -+ * rate next MPDU rate in unit of 500kbps -+ * frame_len next MPDU frame length in bytes -+ */ -+u16 -+brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only, -+ u32 rts_rate, -+ u32 frame_rate, u8 rts_preamble_type, -+ u8 frame_preamble_type, uint frame_len, bool ba) -+{ -+ u16 dur, sifs; -+ -+ sifs = get_sifs(wlc->band); -+ -+ if (!cts_only) { -+ /* RTS/CTS */ -+ dur = 3 * sifs; -+ dur += -+ (u16) brcms_c_calc_cts_time(wlc, rts_rate, -+ rts_preamble_type); -+ } else { -+ /* CTS-TO-SELF */ -+ dur = 2 * sifs; -+ } -+ -+ dur += -+ (u16) brcms_c_calc_frame_time(wlc, frame_rate, frame_preamble_type, -+ frame_len); -+ if (ba) -+ dur += -+ (u16) brcms_c_calc_ba_time(wlc, frame_rate, -+ BRCMS_SHORT_PREAMBLE); -+ else -+ dur += -+ (u16) brcms_c_calc_ack_time(wlc, frame_rate, -+ frame_preamble_type); -+ return dur; -+} -+ -+static u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec) -+{ -+ u16 phyctl1 = 0; -+ u16 bw; -+ -+ if (BRCMS_ISLCNPHY(wlc->band)) { -+ bw = PHY_TXC1_BW_20MHZ; -+ } else { -+ bw = rspec_get_bw(rspec); -+ /* 10Mhz is not supported yet */ -+ if (bw < PHY_TXC1_BW_20MHZ) { -+ wiphy_err(wlc->wiphy, "phytxctl1_calc: bw %d is " -+ "not supported yet, set to 20L\n", bw); -+ bw = PHY_TXC1_BW_20MHZ; -+ } -+ } -+ -+ if (is_mcs_rate(rspec)) { -+ uint mcs = rspec & RSPEC_RATE_MASK; -+ -+ /* bw, stf, coding-type is part of rspec_phytxbyte2 returns */ -+ phyctl1 = rspec_phytxbyte2(rspec); -+ /* set the upper byte of phyctl1 */ -+ phyctl1 |= (mcs_table[mcs].tx_phy_ctl3 << 8); -+ } else if (is_cck_rate(rspec) && !BRCMS_ISLCNPHY(wlc->band) -+ && !BRCMS_ISSSLPNPHY(wlc->band)) { -+ /* -+ * In CCK mode LPPHY overloads OFDM Modulation bits with CCK -+ * Data Rate. Eventually MIMOPHY would also be converted to -+ * this format -+ */ -+ /* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */ -+ phyctl1 = (bw | (rspec_stf(rspec) << PHY_TXC1_MODE_SHIFT)); -+ } else { /* legacy OFDM/CCK */ -+ s16 phycfg; -+ /* get the phyctl byte from rate phycfg table */ -+ phycfg = brcms_c_rate_legacy_phyctl(rspec2rate(rspec)); -+ if (phycfg == -1) { -+ wiphy_err(wlc->wiphy, "phytxctl1_calc: wrong " -+ "legacy OFDM/CCK rate\n"); -+ phycfg = 0; -+ } -+ /* set the upper byte of phyctl1 */ -+ phyctl1 = -+ (bw | (phycfg << 8) | -+ (rspec_stf(rspec) << PHY_TXC1_MODE_SHIFT)); -+ } -+ return phyctl1; -+} -+ -+/* -+ * Add struct d11txh, struct cck_phy_hdr. -+ * -+ * 'p' data must start with 802.11 MAC header -+ * 'p' must allow enough bytes of local headers to be "pushed" onto the packet -+ * -+ * headroom == D11_PHY_HDR_LEN + D11_TXH_LEN (D11_TXH_LEN is now 104 bytes) -+ * -+ */ -+static u16 -+brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, -+ struct sk_buff *p, struct scb *scb, uint frag, -+ uint nfrags, uint queue, uint next_frag_len) -+{ -+ struct ieee80211_hdr *h; -+ struct d11txh *txh; -+ u8 *plcp, plcp_fallback[D11_PHY_HDR_LEN]; -+ int len, phylen, rts_phylen; -+ u16 mch, phyctl, xfts, mainrates; -+ u16 seq = 0, mcl = 0, status = 0, frameid = 0; -+ u32 rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M }; -+ u32 rts_rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M }; -+ bool use_rts = false; -+ bool use_cts = false; -+ bool use_rifs = false; -+ bool short_preamble[2] = { false, false }; -+ u8 preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE }; -+ u8 rts_preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE }; -+ u8 *rts_plcp, rts_plcp_fallback[D11_PHY_HDR_LEN]; -+ struct ieee80211_rts *rts = NULL; -+ bool qos; -+ uint ac; -+ bool hwtkmic = false; -+ u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ; -+#define ANTCFG_NONE 0xFF -+ u8 antcfg = ANTCFG_NONE; -+ u8 fbantcfg = ANTCFG_NONE; -+ uint phyctl1_stf = 0; -+ u16 durid = 0; -+ struct ieee80211_tx_rate *txrate[2]; -+ int k; -+ struct ieee80211_tx_info *tx_info; -+ bool is_mcs; -+ u16 mimo_txbw; -+ u8 mimo_preamble_type; -+ -+ /* locate 802.11 MAC header */ -+ h = (struct ieee80211_hdr *)(p->data); -+ qos = ieee80211_is_data_qos(h->frame_control); -+ -+ /* compute length of frame in bytes for use in PLCP computations */ -+ len = brcmu_pkttotlen(p); -+ phylen = len + FCS_LEN; -+ -+ /* Get tx_info */ -+ tx_info = IEEE80211_SKB_CB(p); -+ -+ /* add PLCP */ -+ plcp = skb_push(p, D11_PHY_HDR_LEN); -+ -+ /* add Broadcom tx descriptor header */ -+ txh = (struct d11txh *) skb_push(p, D11_TXH_LEN); -+ memset(txh, 0, D11_TXH_LEN); -+ -+ /* setup frameid */ -+ if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { -+ /* non-AP STA should never use BCMC queue */ -+ if (queue == TX_BCMC_FIFO) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: ASSERT queue == " -+ "TX_BCMC!\n", wlc->pub->unit, __func__); -+ frameid = bcmc_fid_generate(wlc, NULL, txh); -+ } else { -+ /* Increment the counter for first fragment */ -+ if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) -+ scb->seqnum[p->priority]++; -+ -+ /* extract fragment number from frame first */ -+ seq = le16_to_cpu(h->seq_ctrl) & FRAGNUM_MASK; -+ seq |= (scb->seqnum[p->priority] << SEQNUM_SHIFT); -+ h->seq_ctrl = cpu_to_le16(seq); -+ -+ frameid = ((seq << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) | -+ (queue & TXFID_QUEUE_MASK); -+ } -+ } -+ frameid |= queue & TXFID_QUEUE_MASK; -+ -+ /* set the ignpmq bit for all pkts tx'd in PS mode and for beacons */ -+ if (ieee80211_is_beacon(h->frame_control)) -+ mcl |= TXC_IGNOREPMQ; -+ -+ txrate[0] = tx_info->control.rates; -+ txrate[1] = txrate[0] + 1; -+ -+ /* -+ * if rate control algorithm didn't give us a fallback -+ * rate, use the primary rate -+ */ -+ if (txrate[1]->idx < 0) -+ txrate[1] = txrate[0]; -+ -+ for (k = 0; k < hw->max_rates; k++) { -+ is_mcs = txrate[k]->flags & IEEE80211_TX_RC_MCS ? true : false; -+ if (!is_mcs) { -+ if ((txrate[k]->idx >= 0) -+ && (txrate[k]->idx < -+ hw->wiphy->bands[tx_info->band]->n_bitrates)) { -+ rspec[k] = -+ hw->wiphy->bands[tx_info->band]-> -+ bitrates[txrate[k]->idx].hw_value; -+ short_preamble[k] = -+ txrate[k]-> -+ flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE ? -+ true : false; -+ } else { -+ rspec[k] = BRCM_RATE_1M; -+ } -+ } else { -+ rspec[k] = mac80211_wlc_set_nrate(wlc, wlc->band, -+ NRATE_MCS_INUSE | txrate[k]->idx); -+ } -+ -+ /* -+ * Currently only support same setting for primay and -+ * fallback rates. Unify flags for each rate into a -+ * single value for the frame -+ */ -+ use_rts |= -+ txrate[k]-> -+ flags & IEEE80211_TX_RC_USE_RTS_CTS ? true : false; -+ use_cts |= -+ txrate[k]-> -+ flags & IEEE80211_TX_RC_USE_CTS_PROTECT ? true : false; -+ -+ -+ /* -+ * (1) RATE: -+ * determine and validate primary rate -+ * and fallback rates -+ */ -+ if (!rspec_active(rspec[k])) { -+ rspec[k] = BRCM_RATE_1M; -+ } else { -+ if (!is_multicast_ether_addr(h->addr1)) { -+ /* set tx antenna config */ -+ brcms_c_antsel_antcfg_get(wlc->asi, false, -+ false, 0, 0, &antcfg, &fbantcfg); -+ } -+ } -+ } -+ -+ phyctl1_stf = wlc->stf->ss_opmode; -+ -+ if (wlc->pub->_n_enab & SUPPORT_11N) { -+ for (k = 0; k < hw->max_rates; k++) { -+ /* -+ * apply siso/cdd to single stream mcs's or ofdm -+ * if rspec is auto selected -+ */ -+ if (((is_mcs_rate(rspec[k]) && -+ is_single_stream(rspec[k] & RSPEC_RATE_MASK)) || -+ is_ofdm_rate(rspec[k])) -+ && ((rspec[k] & RSPEC_OVERRIDE_MCS_ONLY) -+ || !(rspec[k] & RSPEC_OVERRIDE))) { -+ rspec[k] &= ~(RSPEC_STF_MASK | RSPEC_STC_MASK); -+ -+ /* For SISO MCS use STBC if possible */ -+ if (is_mcs_rate(rspec[k]) -+ && BRCMS_STF_SS_STBC_TX(wlc, scb)) { -+ u8 stc; -+ -+ /* Nss for single stream is always 1 */ -+ stc = 1; -+ rspec[k] |= (PHY_TXC1_MODE_STBC << -+ RSPEC_STF_SHIFT) | -+ (stc << RSPEC_STC_SHIFT); -+ } else -+ rspec[k] |= -+ (phyctl1_stf << RSPEC_STF_SHIFT); -+ } -+ -+ /* -+ * Is the phy configured to use 40MHZ frames? If -+ * so then pick the desired txbw -+ */ -+ if (brcms_chspec_bw(wlc->chanspec) == BRCMS_40_MHZ) { -+ /* default txbw is 20in40 SB */ -+ mimo_ctlchbw = mimo_txbw = -+ CHSPEC_SB_UPPER(wlc_phy_chanspec_get( -+ wlc->band->pi)) -+ ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ; -+ -+ if (is_mcs_rate(rspec[k])) { -+ /* mcs 32 must be 40b/w DUP */ -+ if ((rspec[k] & RSPEC_RATE_MASK) -+ == 32) { -+ mimo_txbw = -+ PHY_TXC1_BW_40MHZ_DUP; -+ /* use override */ -+ } else if (wlc->mimo_40txbw != AUTO) -+ mimo_txbw = wlc->mimo_40txbw; -+ /* else check if dst is using 40 Mhz */ -+ else if (scb->flags & SCB_IS40) -+ mimo_txbw = PHY_TXC1_BW_40MHZ; -+ } else if (is_ofdm_rate(rspec[k])) { -+ if (wlc->ofdm_40txbw != AUTO) -+ mimo_txbw = wlc->ofdm_40txbw; -+ } else if (wlc->cck_40txbw != AUTO) { -+ mimo_txbw = wlc->cck_40txbw; -+ } -+ } else { -+ /* -+ * mcs32 is 40 b/w only. -+ * This is possible for probe packets on -+ * a STA during SCAN -+ */ -+ if ((rspec[k] & RSPEC_RATE_MASK) == 32) -+ /* mcs 0 */ -+ rspec[k] = RSPEC_MIMORATE; -+ -+ mimo_txbw = PHY_TXC1_BW_20MHZ; -+ } -+ -+ /* Set channel width */ -+ rspec[k] &= ~RSPEC_BW_MASK; -+ if ((k == 0) || ((k > 0) && is_mcs_rate(rspec[k]))) -+ rspec[k] |= (mimo_txbw << RSPEC_BW_SHIFT); -+ else -+ rspec[k] |= (mimo_ctlchbw << RSPEC_BW_SHIFT); -+ -+ /* Disable short GI, not supported yet */ -+ rspec[k] &= ~RSPEC_SHORT_GI; -+ -+ mimo_preamble_type = BRCMS_MM_PREAMBLE; -+ if (txrate[k]->flags & IEEE80211_TX_RC_GREEN_FIELD) -+ mimo_preamble_type = BRCMS_GF_PREAMBLE; -+ -+ if ((txrate[k]->flags & IEEE80211_TX_RC_MCS) -+ && (!is_mcs_rate(rspec[k]))) { -+ wiphy_err(wlc->wiphy, "wl%d: %s: IEEE80211_TX_" -+ "RC_MCS != is_mcs_rate(rspec)\n", -+ wlc->pub->unit, __func__); -+ } -+ -+ if (is_mcs_rate(rspec[k])) { -+ preamble_type[k] = mimo_preamble_type; -+ -+ /* -+ * if SGI is selected, then forced mm -+ * for single stream -+ */ -+ if ((rspec[k] & RSPEC_SHORT_GI) -+ && is_single_stream(rspec[k] & -+ RSPEC_RATE_MASK)) -+ preamble_type[k] = BRCMS_MM_PREAMBLE; -+ } -+ -+ /* should be better conditionalized */ -+ if (!is_mcs_rate(rspec[0]) -+ && (tx_info->control.rates[0]. -+ flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)) -+ preamble_type[k] = BRCMS_SHORT_PREAMBLE; -+ } -+ } else { -+ for (k = 0; k < hw->max_rates; k++) { -+ /* Set ctrlchbw as 20Mhz */ -+ rspec[k] &= ~RSPEC_BW_MASK; -+ rspec[k] |= (PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT); -+ -+ /* for nphy, stf of ofdm frames must follow policies */ -+ if (BRCMS_ISNPHY(wlc->band) && is_ofdm_rate(rspec[k])) { -+ rspec[k] &= ~RSPEC_STF_MASK; -+ rspec[k] |= phyctl1_stf << RSPEC_STF_SHIFT; -+ } -+ } -+ } -+ -+ /* Reset these for use with AMPDU's */ -+ txrate[0]->count = 0; -+ txrate[1]->count = 0; -+ -+ /* (2) PROTECTION, may change rspec */ -+ if ((ieee80211_is_data(h->frame_control) || -+ ieee80211_is_mgmt(h->frame_control)) && -+ (phylen > wlc->RTSThresh) && !is_multicast_ether_addr(h->addr1)) -+ use_rts = true; -+ -+ /* (3) PLCP: determine PLCP header and MAC duration, -+ * fill struct d11txh */ -+ brcms_c_compute_plcp(wlc, rspec[0], phylen, plcp); -+ brcms_c_compute_plcp(wlc, rspec[1], phylen, plcp_fallback); -+ memcpy(&txh->FragPLCPFallback, -+ plcp_fallback, sizeof(txh->FragPLCPFallback)); -+ -+ /* Length field now put in CCK FBR CRC field */ -+ if (is_cck_rate(rspec[1])) { -+ txh->FragPLCPFallback[4] = phylen & 0xff; -+ txh->FragPLCPFallback[5] = (phylen & 0xff00) >> 8; -+ } -+ -+ /* MIMO-RATE: need validation ?? */ -+ mainrates = is_ofdm_rate(rspec[0]) ? -+ D11A_PHY_HDR_GRATE((struct ofdm_phy_hdr *) plcp) : -+ plcp[0]; -+ -+ /* DUR field for main rate */ -+ if (!ieee80211_is_pspoll(h->frame_control) && -+ !is_multicast_ether_addr(h->addr1) && !use_rifs) { -+ durid = -+ brcms_c_compute_frame_dur(wlc, rspec[0], preamble_type[0], -+ next_frag_len); -+ h->duration_id = cpu_to_le16(durid); -+ } else if (use_rifs) { -+ /* NAV protect to end of next max packet size */ -+ durid = -+ (u16) brcms_c_calc_frame_time(wlc, rspec[0], -+ preamble_type[0], -+ DOT11_MAX_FRAG_LEN); -+ durid += RIFS_11N_TIME; -+ h->duration_id = cpu_to_le16(durid); -+ } -+ -+ /* DUR field for fallback rate */ -+ if (ieee80211_is_pspoll(h->frame_control)) -+ txh->FragDurFallback = h->duration_id; -+ else if (is_multicast_ether_addr(h->addr1) || use_rifs) -+ txh->FragDurFallback = 0; -+ else { -+ durid = brcms_c_compute_frame_dur(wlc, rspec[1], -+ preamble_type[1], next_frag_len); -+ txh->FragDurFallback = cpu_to_le16(durid); -+ } -+ -+ /* (4) MAC-HDR: MacTxControlLow */ -+ if (frag == 0) -+ mcl |= TXC_STARTMSDU; -+ -+ if (!is_multicast_ether_addr(h->addr1)) -+ mcl |= TXC_IMMEDACK; -+ -+ if (wlc->band->bandtype == BRCM_BAND_5G) -+ mcl |= TXC_FREQBAND_5G; -+ -+ if (CHSPEC_IS40(wlc_phy_chanspec_get(wlc->band->pi))) -+ mcl |= TXC_BW_40; -+ -+ /* set AMIC bit if using hardware TKIP MIC */ -+ if (hwtkmic) -+ mcl |= TXC_AMIC; -+ -+ txh->MacTxControlLow = cpu_to_le16(mcl); -+ -+ /* MacTxControlHigh */ -+ mch = 0; -+ -+ /* Set fallback rate preamble type */ -+ if ((preamble_type[1] == BRCMS_SHORT_PREAMBLE) || -+ (preamble_type[1] == BRCMS_GF_PREAMBLE)) { -+ if (rspec2rate(rspec[1]) != BRCM_RATE_1M) -+ mch |= TXC_PREAMBLE_DATA_FB_SHORT; -+ } -+ -+ /* MacFrameControl */ -+ memcpy(&txh->MacFrameControl, &h->frame_control, sizeof(u16)); -+ txh->TxFesTimeNormal = cpu_to_le16(0); -+ -+ txh->TxFesTimeFallback = cpu_to_le16(0); -+ -+ /* TxFrameRA */ -+ memcpy(&txh->TxFrameRA, &h->addr1, ETH_ALEN); -+ -+ /* TxFrameID */ -+ txh->TxFrameID = cpu_to_le16(frameid); -+ -+ /* -+ * TxStatus, Note the case of recreating the first frag of a suppressed -+ * frame then we may need to reset the retry cnt's via the status reg -+ */ -+ txh->TxStatus = cpu_to_le16(status); -+ -+ /* -+ * extra fields for ucode AMPDU aggregation, the new fields are added to -+ * the END of previous structure so that it's compatible in driver. -+ */ -+ txh->MaxNMpdus = cpu_to_le16(0); -+ txh->MaxABytes_MRT = cpu_to_le16(0); -+ txh->MaxABytes_FBR = cpu_to_le16(0); -+ txh->MinMBytes = cpu_to_le16(0); -+ -+ /* (5) RTS/CTS: determine RTS/CTS PLCP header and MAC duration, -+ * furnish struct d11txh */ -+ /* RTS PLCP header and RTS frame */ -+ if (use_rts || use_cts) { -+ if (use_rts && use_cts) -+ use_cts = false; -+ -+ for (k = 0; k < 2; k++) { -+ rts_rspec[k] = brcms_c_rspec_to_rts_rspec(wlc, rspec[k], -+ false, -+ mimo_ctlchbw); -+ } -+ -+ if (!is_ofdm_rate(rts_rspec[0]) && -+ !((rspec2rate(rts_rspec[0]) == BRCM_RATE_1M) || -+ (wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) { -+ rts_preamble_type[0] = BRCMS_SHORT_PREAMBLE; -+ mch |= TXC_PREAMBLE_RTS_MAIN_SHORT; -+ } -+ -+ if (!is_ofdm_rate(rts_rspec[1]) && -+ !((rspec2rate(rts_rspec[1]) == BRCM_RATE_1M) || -+ (wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) { -+ rts_preamble_type[1] = BRCMS_SHORT_PREAMBLE; -+ mch |= TXC_PREAMBLE_RTS_FB_SHORT; -+ } -+ -+ /* RTS/CTS additions to MacTxControlLow */ -+ if (use_cts) { -+ txh->MacTxControlLow |= cpu_to_le16(TXC_SENDCTS); -+ } else { -+ txh->MacTxControlLow |= cpu_to_le16(TXC_SENDRTS); -+ txh->MacTxControlLow |= cpu_to_le16(TXC_LONGFRAME); -+ } -+ -+ /* RTS PLCP header */ -+ rts_plcp = txh->RTSPhyHeader; -+ if (use_cts) -+ rts_phylen = DOT11_CTS_LEN + FCS_LEN; -+ else -+ rts_phylen = DOT11_RTS_LEN + FCS_LEN; -+ -+ brcms_c_compute_plcp(wlc, rts_rspec[0], rts_phylen, rts_plcp); -+ -+ /* fallback rate version of RTS PLCP header */ -+ brcms_c_compute_plcp(wlc, rts_rspec[1], rts_phylen, -+ rts_plcp_fallback); -+ memcpy(&txh->RTSPLCPFallback, rts_plcp_fallback, -+ sizeof(txh->RTSPLCPFallback)); -+ -+ /* RTS frame fields... */ -+ rts = (struct ieee80211_rts *)&txh->rts_frame; -+ -+ durid = brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec[0], -+ rspec[0], rts_preamble_type[0], -+ preamble_type[0], phylen, false); -+ rts->duration = cpu_to_le16(durid); -+ /* fallback rate version of RTS DUR field */ -+ durid = brcms_c_compute_rtscts_dur(wlc, use_cts, -+ rts_rspec[1], rspec[1], -+ rts_preamble_type[1], -+ preamble_type[1], phylen, false); -+ txh->RTSDurFallback = cpu_to_le16(durid); -+ -+ if (use_cts) { -+ rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | -+ IEEE80211_STYPE_CTS); -+ -+ memcpy(&rts->ra, &h->addr2, ETH_ALEN); -+ } else { -+ rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | -+ IEEE80211_STYPE_RTS); -+ -+ memcpy(&rts->ra, &h->addr1, 2 * ETH_ALEN); -+ } -+ -+ /* mainrate -+ * low 8 bits: main frag rate/mcs, -+ * high 8 bits: rts/cts rate/mcs -+ */ -+ mainrates |= (is_ofdm_rate(rts_rspec[0]) ? -+ D11A_PHY_HDR_GRATE( -+ (struct ofdm_phy_hdr *) rts_plcp) : -+ rts_plcp[0]) << 8; -+ } else { -+ memset((char *)txh->RTSPhyHeader, 0, D11_PHY_HDR_LEN); -+ memset((char *)&txh->rts_frame, 0, -+ sizeof(struct ieee80211_rts)); -+ memset((char *)txh->RTSPLCPFallback, 0, -+ sizeof(txh->RTSPLCPFallback)); -+ txh->RTSDurFallback = 0; -+ } -+ -+#ifdef SUPPORT_40MHZ -+ /* add null delimiter count */ -+ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && is_mcs_rate(rspec)) -+ txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = -+ brcm_c_ampdu_null_delim_cnt(wlc->ampdu, scb, rspec, phylen); -+ -+#endif -+ -+ /* -+ * Now that RTS/RTS FB preamble types are updated, write -+ * the final value -+ */ -+ txh->MacTxControlHigh = cpu_to_le16(mch); -+ -+ /* -+ * MainRates (both the rts and frag plcp rates have -+ * been calculated now) -+ */ -+ txh->MainRates = cpu_to_le16(mainrates); -+ -+ /* XtraFrameTypes */ -+ xfts = frametype(rspec[1], wlc->mimoft); -+ xfts |= (frametype(rts_rspec[0], wlc->mimoft) << XFTS_RTS_FT_SHIFT); -+ xfts |= (frametype(rts_rspec[1], wlc->mimoft) << XFTS_FBRRTS_FT_SHIFT); -+ xfts |= CHSPEC_CHANNEL(wlc_phy_chanspec_get(wlc->band->pi)) << -+ XFTS_CHANNEL_SHIFT; -+ txh->XtraFrameTypes = cpu_to_le16(xfts); -+ -+ /* PhyTxControlWord */ -+ phyctl = frametype(rspec[0], wlc->mimoft); -+ if ((preamble_type[0] == BRCMS_SHORT_PREAMBLE) || -+ (preamble_type[0] == BRCMS_GF_PREAMBLE)) { -+ if (rspec2rate(rspec[0]) != BRCM_RATE_1M) -+ phyctl |= PHY_TXC_SHORT_HDR; -+ } -+ -+ /* phytxant is properly bit shifted */ -+ phyctl |= brcms_c_stf_d11hdrs_phyctl_txant(wlc, rspec[0]); -+ txh->PhyTxControlWord = cpu_to_le16(phyctl); -+ -+ /* PhyTxControlWord_1 */ -+ if (BRCMS_PHY_11N_CAP(wlc->band)) { -+ u16 phyctl1 = 0; -+ -+ phyctl1 = brcms_c_phytxctl1_calc(wlc, rspec[0]); -+ txh->PhyTxControlWord_1 = cpu_to_le16(phyctl1); -+ phyctl1 = brcms_c_phytxctl1_calc(wlc, rspec[1]); -+ txh->PhyTxControlWord_1_Fbr = cpu_to_le16(phyctl1); -+ -+ if (use_rts || use_cts) { -+ phyctl1 = brcms_c_phytxctl1_calc(wlc, rts_rspec[0]); -+ txh->PhyTxControlWord_1_Rts = cpu_to_le16(phyctl1); -+ phyctl1 = brcms_c_phytxctl1_calc(wlc, rts_rspec[1]); -+ txh->PhyTxControlWord_1_FbrRts = cpu_to_le16(phyctl1); -+ } -+ -+ /* -+ * For mcs frames, if mixedmode(overloaded with long preamble) -+ * is going to be set, fill in non-zero MModeLen and/or -+ * MModeFbrLen it will be unnecessary if they are separated -+ */ -+ if (is_mcs_rate(rspec[0]) && -+ (preamble_type[0] == BRCMS_MM_PREAMBLE)) { -+ u16 mmodelen = -+ brcms_c_calc_lsig_len(wlc, rspec[0], phylen); -+ txh->MModeLen = cpu_to_le16(mmodelen); -+ } -+ -+ if (is_mcs_rate(rspec[1]) && -+ (preamble_type[1] == BRCMS_MM_PREAMBLE)) { -+ u16 mmodefbrlen = -+ brcms_c_calc_lsig_len(wlc, rspec[1], phylen); -+ txh->MModeFbrLen = cpu_to_le16(mmodefbrlen); -+ } -+ } -+ -+ ac = skb_get_queue_mapping(p); -+ if ((scb->flags & SCB_WMECAP) && qos && wlc->edcf_txop[ac]) { -+ uint frag_dur, dur, dur_fallback; -+ -+ /* WME: Update TXOP threshold */ -+ if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) && frag == 0) { -+ frag_dur = -+ brcms_c_calc_frame_time(wlc, rspec[0], -+ preamble_type[0], phylen); -+ -+ if (rts) { -+ /* 1 RTS or CTS-to-self frame */ -+ dur = -+ brcms_c_calc_cts_time(wlc, rts_rspec[0], -+ rts_preamble_type[0]); -+ dur_fallback = -+ brcms_c_calc_cts_time(wlc, rts_rspec[1], -+ rts_preamble_type[1]); -+ /* (SIFS + CTS) + SIFS + frame + SIFS + ACK */ -+ dur += le16_to_cpu(rts->duration); -+ dur_fallback += -+ le16_to_cpu(txh->RTSDurFallback); -+ } else if (use_rifs) { -+ dur = frag_dur; -+ dur_fallback = 0; -+ } else { -+ /* frame + SIFS + ACK */ -+ dur = frag_dur; -+ dur += -+ brcms_c_compute_frame_dur(wlc, rspec[0], -+ preamble_type[0], 0); -+ -+ dur_fallback = -+ brcms_c_calc_frame_time(wlc, rspec[1], -+ preamble_type[1], -+ phylen); -+ dur_fallback += -+ brcms_c_compute_frame_dur(wlc, rspec[1], -+ preamble_type[1], 0); -+ } -+ /* NEED to set TxFesTimeNormal (hard) */ -+ txh->TxFesTimeNormal = cpu_to_le16((u16) dur); -+ /* -+ * NEED to set fallback rate version of -+ * TxFesTimeNormal (hard) -+ */ -+ txh->TxFesTimeFallback = -+ cpu_to_le16((u16) dur_fallback); -+ -+ /* -+ * update txop byte threshold (txop minus intraframe -+ * overhead) -+ */ -+ if (wlc->edcf_txop[ac] >= (dur - frag_dur)) { -+ uint newfragthresh; -+ -+ newfragthresh = -+ brcms_c_calc_frame_len(wlc, -+ rspec[0], preamble_type[0], -+ (wlc->edcf_txop[ac] - -+ (dur - frag_dur))); -+ /* range bound the fragthreshold */ -+ if (newfragthresh < DOT11_MIN_FRAG_LEN) -+ newfragthresh = -+ DOT11_MIN_FRAG_LEN; -+ else if (newfragthresh > -+ wlc->usr_fragthresh) -+ newfragthresh = -+ wlc->usr_fragthresh; -+ /* update the fragthresh and do txc update */ -+ if (wlc->fragthresh[queue] != -+ (u16) newfragthresh) -+ wlc->fragthresh[queue] = -+ (u16) newfragthresh; -+ } else { -+ wiphy_err(wlc->wiphy, "wl%d: %s txop invalid " -+ "for rate %d\n", -+ wlc->pub->unit, fifo_names[queue], -+ rspec2rate(rspec[0])); -+ } -+ -+ if (dur > wlc->edcf_txop[ac]) -+ wiphy_err(wlc->wiphy, "wl%d: %s: %s txop " -+ "exceeded phylen %d/%d dur %d/%d\n", -+ wlc->pub->unit, __func__, -+ fifo_names[queue], -+ phylen, wlc->fragthresh[queue], -+ dur, wlc->edcf_txop[ac]); -+ } -+ } -+ -+ return 0; -+} -+ -+void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu, -+ struct ieee80211_hw *hw) -+{ -+ u8 prio; -+ uint fifo; -+ struct scb *scb = &wlc->pri_scb; -+ struct ieee80211_hdr *d11_header = (struct ieee80211_hdr *)(sdu->data); -+ -+ /* -+ * 802.11 standard requires management traffic -+ * to go at highest priority -+ */ -+ prio = ieee80211_is_data(d11_header->frame_control) ? sdu->priority : -+ MAXPRIO; -+ fifo = prio2fifo[prio]; -+ if (brcms_c_d11hdrs_mac80211(wlc, hw, sdu, scb, 0, 1, fifo, 0)) -+ return; -+ brcms_c_txq_enq(wlc, scb, sdu, BRCMS_PRIO_TO_PREC(prio)); -+ brcms_c_send_q(wlc); -+} -+ -+void brcms_c_send_q(struct brcms_c_info *wlc) -+{ -+ struct sk_buff *pkt[DOT11_MAXNUMFRAGS]; -+ int prec; -+ u16 prec_map; -+ int err = 0, i, count; -+ uint fifo; -+ struct brcms_txq_info *qi = wlc->pkt_queue; -+ struct pktq *q = &qi->q; -+ struct ieee80211_tx_info *tx_info; -+ -+ prec_map = wlc->tx_prec_map; -+ -+ /* Send all the enq'd pkts that we can. -+ * Dequeue packets with precedence with empty HW fifo only -+ */ -+ while (prec_map && (pkt[0] = brcmu_pktq_mdeq(q, prec_map, &prec))) { -+ tx_info = IEEE80211_SKB_CB(pkt[0]); -+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { -+ err = brcms_c_sendampdu(wlc->ampdu, qi, pkt, prec); -+ } else { -+ count = 1; -+ err = brcms_c_prep_pdu(wlc, pkt[0], &fifo); -+ if (!err) { -+ for (i = 0; i < count; i++) -+ brcms_c_txfifo(wlc, fifo, pkt[i], true, -+ 1); -+ } -+ } -+ -+ if (err == -EBUSY) { -+ brcmu_pktq_penq_head(q, prec, pkt[0]); -+ /* -+ * If send failed due to any other reason than a -+ * change in HW FIFO condition, quit. Otherwise, -+ * read the new prec_map! -+ */ -+ if (prec_map == wlc->tx_prec_map) -+ break; -+ prec_map = wlc->tx_prec_map; -+ } -+ } -+} -+ -+void -+brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p, -+ bool commit, s8 txpktpend) -+{ -+ u16 frameid = INVALIDFID; -+ struct d11txh *txh; -+ -+ txh = (struct d11txh *) (p->data); -+ -+ /* When a BC/MC frame is being committed to the BCMC fifo -+ * via DMA (NOT PIO), update ucode or BSS info as appropriate. -+ */ -+ if (fifo == TX_BCMC_FIFO) -+ frameid = le16_to_cpu(txh->TxFrameID); -+ -+ /* -+ * Bump up pending count for if not using rpc. If rpc is -+ * used, this will be handled in brcms_b_txfifo() -+ */ -+ if (commit) { -+ wlc->core->txpktpend[fifo] += txpktpend; -+ BCMMSG(wlc->wiphy, "pktpend inc %d to %d\n", -+ txpktpend, wlc->core->txpktpend[fifo]); -+ } -+ -+ /* Commit BCMC sequence number in the SHM frame ID location */ -+ if (frameid != INVALIDFID) { -+ /* -+ * To inform the ucode of the last mcast frame posted -+ * so that it can clear moredata bit -+ */ -+ brcms_b_write_shm(wlc->hw, M_BCMC_FID, frameid); -+ } -+ -+ if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0) -+ wiphy_err(wlc->wiphy, "txfifo: fatal, toss frames !!!\n"); -+} -+ -+u32 -+brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec, -+ bool use_rspec, u16 mimo_ctlchbw) -+{ -+ u32 rts_rspec = 0; -+ -+ if (use_rspec) -+ /* use frame rate as rts rate */ -+ rts_rspec = rspec; -+ else if (wlc->band->gmode && wlc->protection->_g && !is_cck_rate(rspec)) -+ /* Use 11Mbps as the g protection RTS target rate and fallback. -+ * Use the brcms_basic_rate() lookup to find the best basic rate -+ * under the target in case 11 Mbps is not Basic. -+ * 6 and 9 Mbps are not usually selected by rate selection, but -+ * even if the OFDM rate we are protecting is 6 or 9 Mbps, 11 -+ * is more robust. -+ */ -+ rts_rspec = brcms_basic_rate(wlc, BRCM_RATE_11M); -+ else -+ /* calculate RTS rate and fallback rate based on the frame rate -+ * RTS must be sent at a basic rate since it is a -+ * control frame, sec 9.6 of 802.11 spec -+ */ -+ rts_rspec = brcms_basic_rate(wlc, rspec); -+ -+ if (BRCMS_PHY_11N_CAP(wlc->band)) { -+ /* set rts txbw to correct side band */ -+ rts_rspec &= ~RSPEC_BW_MASK; -+ -+ /* -+ * if rspec/rspec_fallback is 40MHz, then send RTS on both -+ * 20MHz channel (DUP), otherwise send RTS on control channel -+ */ -+ if (rspec_is40mhz(rspec) && !is_cck_rate(rts_rspec)) -+ rts_rspec |= (PHY_TXC1_BW_40MHZ_DUP << RSPEC_BW_SHIFT); -+ else -+ rts_rspec |= (mimo_ctlchbw << RSPEC_BW_SHIFT); -+ -+ /* pick siso/cdd as default for ofdm */ -+ if (is_ofdm_rate(rts_rspec)) { -+ rts_rspec &= ~RSPEC_STF_MASK; -+ rts_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT); -+ } -+ } -+ return rts_rspec; -+} -+ -+void -+brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, s8 txpktpend) -+{ -+ wlc->core->txpktpend[fifo] -= txpktpend; -+ BCMMSG(wlc->wiphy, "pktpend dec %d to %d\n", txpktpend, -+ wlc->core->txpktpend[fifo]); -+ -+ /* There is more room; mark precedences related to this FIFO sendable */ -+ wlc->tx_prec_map |= wlc->fifo2prec_map[fifo]; -+ -+ /* figure out which bsscfg is being worked on... */ -+} -+ -+/* Update beacon listen interval in shared memory */ -+static void brcms_c_bcn_li_upd(struct brcms_c_info *wlc) -+{ -+ /* wake up every DTIM is the default */ -+ if (wlc->bcn_li_dtim == 1) -+ brcms_b_write_shm(wlc->hw, M_BCN_LI, 0); -+ else -+ brcms_b_write_shm(wlc->hw, M_BCN_LI, -+ (wlc->bcn_li_dtim << 8) | wlc->bcn_li_bcn); -+} -+ -+static void -+brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr, -+ u32 *tsf_h_ptr) -+{ -+ struct d11regs __iomem *regs = wlc_hw->regs; -+ -+ /* read the tsf timer low, then high to get an atomic read */ -+ *tsf_l_ptr = R_REG(®s->tsf_timerlow); -+ *tsf_h_ptr = R_REG(®s->tsf_timerhigh); -+} -+ -+/* -+ * recover 64bit TSF value from the 16bit TSF value in the rx header -+ * given the assumption that the TSF passed in header is within 65ms -+ * of the current tsf. -+ * -+ * 6 5 4 4 3 2 1 -+ * 3.......6.......8.......0.......2.......4.......6.......8......0 -+ * |<---------- tsf_h ----------->||<--- tsf_l -->||<-RxTSFTime ->| -+ * -+ * The RxTSFTime are the lowest 16 bits and provided by the ucode. The -+ * tsf_l is filled in by brcms_b_recv, which is done earlier in the -+ * receive call sequence after rx interrupt. Only the higher 16 bits -+ * are used. Finally, the tsf_h is read from the tsf register. -+ */ -+static u64 brcms_c_recover_tsf64(struct brcms_c_info *wlc, -+ struct d11rxhdr *rxh) -+{ -+ u32 tsf_h, tsf_l; -+ u16 rx_tsf_0_15, rx_tsf_16_31; -+ -+ brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h); -+ -+ rx_tsf_16_31 = (u16)(tsf_l >> 16); -+ rx_tsf_0_15 = rxh->RxTSFTime; -+ -+ /* -+ * a greater tsf time indicates the low 16 bits of -+ * tsf_l wrapped, so decrement the high 16 bits. -+ */ -+ if ((u16)tsf_l < rx_tsf_0_15) { -+ rx_tsf_16_31 -= 1; -+ if (rx_tsf_16_31 == 0xffff) -+ tsf_h -= 1; -+ } -+ -+ return ((u64)tsf_h << 32) | (((u32)rx_tsf_16_31 << 16) + rx_tsf_0_15); -+} -+ -+static void -+prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh, -+ struct sk_buff *p, -+ struct ieee80211_rx_status *rx_status) -+{ -+ int preamble; -+ int channel; -+ u32 rspec; -+ unsigned char *plcp; -+ -+ /* fill in TSF and flag its presence */ -+ rx_status->mactime = brcms_c_recover_tsf64(wlc, rxh); -+ rx_status->flag |= RX_FLAG_MACTIME_MPDU; -+ -+ channel = BRCMS_CHAN_CHANNEL(rxh->RxChan); -+ -+ if (channel > 14) { -+ rx_status->band = IEEE80211_BAND_5GHZ; -+ rx_status->freq = ieee80211_ofdm_chan_to_freq( -+ WF_CHAN_FACTOR_5_G/2, channel); -+ -+ } else { -+ rx_status->band = IEEE80211_BAND_2GHZ; -+ rx_status->freq = ieee80211_dsss_chan_to_freq(channel); -+ } -+ -+ rx_status->signal = wlc_phy_rssi_compute(wlc->hw->band->pi, rxh); -+ -+ /* noise */ -+ /* qual */ -+ rx_status->antenna = -+ (rxh->PhyRxStatus_0 & PRXS0_RXANT_UPSUBBAND) ? 1 : 0; -+ -+ plcp = p->data; -+ -+ rspec = brcms_c_compute_rspec(rxh, plcp); -+ if (is_mcs_rate(rspec)) { -+ rx_status->rate_idx = rspec & RSPEC_RATE_MASK; -+ rx_status->flag |= RX_FLAG_HT; -+ if (rspec_is40mhz(rspec)) -+ rx_status->flag |= RX_FLAG_40MHZ; -+ } else { -+ switch (rspec2rate(rspec)) { -+ case BRCM_RATE_1M: -+ rx_status->rate_idx = 0; -+ break; -+ case BRCM_RATE_2M: -+ rx_status->rate_idx = 1; -+ break; -+ case BRCM_RATE_5M5: -+ rx_status->rate_idx = 2; -+ break; -+ case BRCM_RATE_11M: -+ rx_status->rate_idx = 3; -+ break; -+ case BRCM_RATE_6M: -+ rx_status->rate_idx = 4; -+ break; -+ case BRCM_RATE_9M: -+ rx_status->rate_idx = 5; -+ break; -+ case BRCM_RATE_12M: -+ rx_status->rate_idx = 6; -+ break; -+ case BRCM_RATE_18M: -+ rx_status->rate_idx = 7; -+ break; -+ case BRCM_RATE_24M: -+ rx_status->rate_idx = 8; -+ break; -+ case BRCM_RATE_36M: -+ rx_status->rate_idx = 9; -+ break; -+ case BRCM_RATE_48M: -+ rx_status->rate_idx = 10; -+ break; -+ case BRCM_RATE_54M: -+ rx_status->rate_idx = 11; -+ break; -+ default: -+ wiphy_err(wlc->wiphy, "%s: Unknown rate\n", __func__); -+ } -+ -+ /* -+ * For 5GHz, we should decrease the index as it is -+ * a subset of the 2.4G rates. See bitrates field -+ * of brcms_band_5GHz_nphy (in mac80211_if.c). -+ */ -+ if (rx_status->band == IEEE80211_BAND_5GHZ) -+ rx_status->rate_idx -= BRCMS_LEGACY_5G_RATE_OFFSET; -+ -+ /* Determine short preamble and rate_idx */ -+ preamble = 0; -+ if (is_cck_rate(rspec)) { -+ if (rxh->PhyRxStatus_0 & PRXS0_SHORTH) -+ rx_status->flag |= RX_FLAG_SHORTPRE; -+ } else if (is_ofdm_rate(rspec)) { -+ rx_status->flag |= RX_FLAG_SHORTPRE; -+ } else { -+ wiphy_err(wlc->wiphy, "%s: Unknown modulation\n", -+ __func__); -+ } -+ } -+ -+ if (plcp3_issgi(plcp[3])) -+ rx_status->flag |= RX_FLAG_SHORT_GI; -+ -+ if (rxh->RxStatus1 & RXS_DECERR) { -+ rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC; -+ wiphy_err(wlc->wiphy, "%s: RX_FLAG_FAILED_PLCP_CRC\n", -+ __func__); -+ } -+ if (rxh->RxStatus1 & RXS_FCSERR) { -+ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; -+ wiphy_err(wlc->wiphy, "%s: RX_FLAG_FAILED_FCS_CRC\n", -+ __func__); -+ } -+} -+ -+static void -+brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh, -+ struct sk_buff *p) -+{ -+ int len_mpdu; -+ struct ieee80211_rx_status rx_status; -+ -+ memset(&rx_status, 0, sizeof(rx_status)); -+ prep_mac80211_status(wlc, rxh, p, &rx_status); -+ -+ /* mac header+body length, exclude CRC and plcp header */ -+ len_mpdu = p->len - D11_PHY_HDR_LEN - FCS_LEN; -+ skb_pull(p, D11_PHY_HDR_LEN); -+ __skb_trim(p, len_mpdu); -+ -+ memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status)); -+ ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p); -+} -+ -+/* calculate frame duration for Mixed-mode L-SIG spoofing, return -+ * number of bytes goes in the length field -+ * -+ * Formula given by HT PHY Spec v 1.13 -+ * len = 3(nsyms + nstream + 3) - 3 -+ */ -+u16 -+brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, -+ uint mac_len) -+{ -+ uint nsyms, len = 0, kNdps; -+ -+ BCMMSG(wlc->wiphy, "wl%d: rate %d, len%d\n", -+ wlc->pub->unit, rspec2rate(ratespec), mac_len); -+ -+ if (is_mcs_rate(ratespec)) { -+ uint mcs = ratespec & RSPEC_RATE_MASK; -+ int tot_streams = (mcs_2_txstreams(mcs) + 1) + -+ rspec_stc(ratespec); -+ -+ /* -+ * the payload duration calculation matches that -+ * of regular ofdm -+ */ -+ /* 1000Ndbps = kbps * 4 */ -+ kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec), -+ rspec_issgi(ratespec)) * 4; -+ -+ if (rspec_stc(ratespec) == 0) -+ nsyms = -+ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + -+ APHY_TAIL_NBITS) * 1000, kNdps); -+ else -+ /* STBC needs to have even number of symbols */ -+ nsyms = -+ 2 * -+ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + -+ APHY_TAIL_NBITS) * 1000, 2 * kNdps); -+ -+ /* (+3) account for HT-SIG(2) and HT-STF(1) */ -+ nsyms += (tot_streams + 3); -+ /* -+ * 3 bytes/symbol @ legacy 6Mbps rate -+ * (-3) excluding service bits and tail bits -+ */ -+ len = (3 * nsyms) - 3; -+ } -+ -+ return (u16) len; -+} -+ -+static void -+brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len) -+{ -+ const struct brcms_c_rateset *rs_dflt; -+ struct brcms_c_rateset rs; -+ u8 rate; -+ u16 entry_ptr; -+ u8 plcp[D11_PHY_HDR_LEN]; -+ u16 dur, sifs; -+ uint i; -+ -+ sifs = get_sifs(wlc->band); -+ -+ rs_dflt = brcms_c_rateset_get_hwrs(wlc); -+ -+ brcms_c_rateset_copy(rs_dflt, &rs); -+ brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams); -+ -+ /* -+ * walk the phy rate table and update MAC core SHM -+ * basic rate table entries -+ */ -+ for (i = 0; i < rs.count; i++) { -+ rate = rs.rates[i] & BRCMS_RATE_MASK; -+ -+ entry_ptr = brcms_b_rate_shm_offset(wlc->hw, rate); -+ -+ /* Calculate the Probe Response PLCP for the given rate */ -+ brcms_c_compute_plcp(wlc, rate, frame_len, plcp); -+ -+ /* -+ * Calculate the duration of the Probe Response -+ * frame plus SIFS for the MAC -+ */ -+ dur = (u16) brcms_c_calc_frame_time(wlc, rate, -+ BRCMS_LONG_PREAMBLE, frame_len); -+ dur += sifs; -+ -+ /* Update the SHM Rate Table entry Probe Response values */ -+ brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_PLCP_POS, -+ (u16) (plcp[0] + (plcp[1] << 8))); -+ brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_PLCP_POS + 2, -+ (u16) (plcp[2] + (plcp[3] << 8))); -+ brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_DUR_POS, dur); -+ } -+} -+ -+/* Max buffering needed for beacon template/prb resp template is 142 bytes. -+ * -+ * PLCP header is 6 bytes. -+ * 802.11 A3 header is 24 bytes. -+ * Max beacon frame body template length is 112 bytes. -+ * Max probe resp frame body template length is 110 bytes. -+ * -+ * *len on input contains the max length of the packet available. -+ * -+ * The *len value is set to the number of bytes in buf used, and starts -+ * with the PLCP and included up to, but not including, the 4 byte FCS. -+ */ -+static void -+brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type, -+ u32 bcn_rspec, -+ struct brcms_bss_cfg *cfg, u16 *buf, int *len) -+{ -+ static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255}; -+ struct cck_phy_hdr *plcp; -+ struct ieee80211_mgmt *h; -+ int hdr_len, body_len; -+ -+ hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN; -+ -+ /* calc buffer size provided for frame body */ -+ body_len = *len - hdr_len; -+ /* return actual size */ -+ *len = hdr_len + body_len; -+ -+ /* format PHY and MAC headers */ -+ memset((char *)buf, 0, hdr_len); -+ -+ plcp = (struct cck_phy_hdr *) buf; -+ -+ /* -+ * PLCP for Probe Response frames are filled in from -+ * core's rate table -+ */ -+ if (type == IEEE80211_STYPE_BEACON) -+ /* fill in PLCP */ -+ brcms_c_compute_plcp(wlc, bcn_rspec, -+ (DOT11_MAC_HDR_LEN + body_len + FCS_LEN), -+ (u8 *) plcp); -+ -+ /* "Regular" and 16 MBSS but not for 4 MBSS */ -+ /* Update the phytxctl for the beacon based on the rspec */ -+ brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec); -+ -+ h = (struct ieee80211_mgmt *)&plcp[1]; -+ -+ /* fill in 802.11 header */ -+ h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type); -+ -+ /* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */ -+ /* A1 filled in by MAC for prb resp, broadcast for bcn */ -+ if (type == IEEE80211_STYPE_BEACON) -+ memcpy(&h->da, ðer_bcast, ETH_ALEN); -+ memcpy(&h->sa, &cfg->cur_etheraddr, ETH_ALEN); -+ memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN); -+ -+ /* SEQ filled in by MAC */ -+} -+ -+int brcms_c_get_header_len(void) -+{ -+ return TXOFF; -+} -+ -+/* -+ * Update all beacons for the system. -+ */ -+void brcms_c_update_beacon(struct brcms_c_info *wlc) -+{ -+ struct brcms_bss_cfg *bsscfg = wlc->bsscfg; -+ -+ if (bsscfg->up && !bsscfg->BSS) -+ /* Clear the soft intmask */ -+ wlc->defmacintmask &= ~MI_BCNTPL; -+} -+ -+/* Write ssid into shared memory */ -+static void -+brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg) -+{ -+ u8 *ssidptr = cfg->SSID; -+ u16 base = M_SSID; -+ u8 ssidbuf[IEEE80211_MAX_SSID_LEN]; -+ -+ /* padding the ssid with zero and copy it into shm */ -+ memset(ssidbuf, 0, IEEE80211_MAX_SSID_LEN); -+ memcpy(ssidbuf, ssidptr, cfg->SSID_len); -+ -+ brcms_c_copyto_shm(wlc, base, ssidbuf, IEEE80211_MAX_SSID_LEN); -+ brcms_b_write_shm(wlc->hw, M_SSIDLEN, (u16) cfg->SSID_len); -+} -+ -+static void -+brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, -+ struct brcms_bss_cfg *cfg, -+ bool suspend) -+{ -+ u16 prb_resp[BCN_TMPL_LEN / 2]; -+ int len = BCN_TMPL_LEN; -+ -+ /* -+ * write the probe response to hardware, or save in -+ * the config structure -+ */ -+ -+ /* create the probe response template */ -+ brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0, -+ cfg, prb_resp, &len); -+ -+ if (suspend) -+ brcms_c_suspend_mac_and_wait(wlc); -+ -+ /* write the probe response into the template region */ -+ brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE, -+ (len + 3) & ~3, prb_resp); -+ -+ /* write the length of the probe response frame (+PLCP/-FCS) */ -+ brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len); -+ -+ /* write the SSID and SSID length */ -+ brcms_c_shm_ssid_upd(wlc, cfg); -+ -+ /* -+ * Write PLCP headers and durations for probe response frames -+ * at all rates. Use the actual frame length covered by the -+ * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table() -+ * by subtracting the PLCP len and adding the FCS. -+ */ -+ len += (-D11_PHY_HDR_LEN + FCS_LEN); -+ brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len); -+ -+ if (suspend) -+ brcms_c_enable_mac(wlc); -+} -+ -+void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend) -+{ -+ struct brcms_bss_cfg *bsscfg = wlc->bsscfg; -+ -+ /* update AP or IBSS probe responses */ -+ if (bsscfg->up && !bsscfg->BSS) -+ brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend); -+} -+ -+/* prepares pdu for transmission. returns BCM error codes */ -+int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu, uint *fifop) -+{ -+ uint fifo; -+ struct d11txh *txh; -+ struct ieee80211_hdr *h; -+ struct scb *scb; -+ -+ txh = (struct d11txh *) (pdu->data); -+ h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN); -+ -+ /* get the pkt queue info. This was put at brcms_c_sendctl or -+ * brcms_c_send for PDU */ -+ fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK; -+ -+ scb = NULL; -+ -+ *fifop = fifo; -+ -+ /* return if insufficient dma resources */ -+ if (*wlc->core->txavail[fifo] < MAX_DMA_SEGS) { -+ /* Mark precedences related to this FIFO, unsendable */ -+ /* A fifo is full. Clear precedences related to that FIFO */ -+ wlc->tx_prec_map &= ~(wlc->fifo2prec_map[fifo]); -+ return -EBUSY; -+ } -+ return 0; -+} -+ -+int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, -+ uint *blocks) -+{ -+ if (fifo >= NFIFO) -+ return -EINVAL; -+ -+ *blocks = wlc_hw->xmtfifo_sz[fifo]; -+ -+ return 0; -+} -+ -+void -+brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset, -+ const u8 *addr) -+{ -+ brcms_b_set_addrmatch(wlc->hw, match_reg_offset, addr); -+ if (match_reg_offset == RCM_BSSID_OFFSET) -+ memcpy(wlc->bsscfg->BSSID, addr, ETH_ALEN); -+} -+ -+/* -+ * Flag 'scan in progress' to withhold dynamic phy calibration -+ */ -+void brcms_c_scan_start(struct brcms_c_info *wlc) -+{ -+ wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, true); -+} -+ -+void brcms_c_scan_stop(struct brcms_c_info *wlc) -+{ -+ wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, false); -+} -+ -+void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state) -+{ -+ wlc->pub->associated = state; -+ wlc->bsscfg->associated = state; -+} -+ -+/* -+ * When a remote STA/AP is removed by Mac80211, or when it can no longer accept -+ * AMPDU traffic, packets pending in hardware have to be invalidated so that -+ * when later on hardware releases them, they can be handled appropriately. -+ */ -+void brcms_c_inval_dma_pkts(struct brcms_hardware *hw, -+ struct ieee80211_sta *sta, -+ void (*dma_callback_fn)) -+{ -+ struct dma_pub *dmah; -+ int i; -+ for (i = 0; i < NFIFO; i++) { -+ dmah = hw->di[i]; -+ if (dmah != NULL) -+ dma_walk_packets(dmah, dma_callback_fn, sta); -+ } -+} -+ -+int brcms_c_get_curband(struct brcms_c_info *wlc) -+{ -+ return wlc->band->bandunit; -+} -+ -+void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop) -+{ -+ /* flush packet queue when requested */ -+ if (drop) -+ brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL); -+ -+ /* wait for queue and DMA fifos to run dry */ -+ while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0) -+ brcms_msleep(wlc->wl, 1); -+} -+ -+void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval) -+{ -+ wlc->bcn_li_bcn = interval; -+ if (wlc->pub->up) -+ brcms_c_bcn_li_upd(wlc); -+} -+ -+int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr) -+{ -+ uint qdbm; -+ -+ /* Remove override bit and clip to max qdbm value */ -+ qdbm = min_t(uint, txpwr * BRCMS_TXPWR_DB_FACTOR, 0xff); -+ return wlc_phy_txpower_set(wlc->band->pi, qdbm, false); -+} -+ -+int brcms_c_get_tx_power(struct brcms_c_info *wlc) -+{ -+ uint qdbm; -+ bool override; -+ -+ wlc_phy_txpower_get(wlc->band->pi, &qdbm, &override); -+ -+ /* Return qdbm units */ -+ return (int)(qdbm / BRCMS_TXPWR_DB_FACTOR); -+} -+ -+void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc) -+{ -+ wlc->mpc = mpc; -+ brcms_c_radio_mpc_upd(wlc); -+} -+ -+/* Process received frames */ -+/* -+ * Return true if more frames need to be processed. false otherwise. -+ * Param 'bound' indicates max. # frames to process before break out. -+ */ -+static void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p) -+{ -+ struct d11rxhdr *rxh; -+ struct ieee80211_hdr *h; -+ uint len; -+ bool is_amsdu; -+ -+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); -+ -+ /* frame starts with rxhdr */ -+ rxh = (struct d11rxhdr *) (p->data); -+ -+ /* strip off rxhdr */ -+ skb_pull(p, BRCMS_HWRXOFF); -+ -+ /* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */ -+ if (rxh->RxStatus1 & RXS_PBPRES) { -+ if (p->len < 2) { -+ wiphy_err(wlc->wiphy, "wl%d: recv: rcvd runt of " -+ "len %d\n", wlc->pub->unit, p->len); -+ goto toss; -+ } -+ skb_pull(p, 2); -+ } -+ -+ h = (struct ieee80211_hdr *)(p->data + D11_PHY_HDR_LEN); -+ len = p->len; -+ -+ if (rxh->RxStatus1 & RXS_FCSERR) { -+ if (wlc->pub->mac80211_state & MAC80211_PROMISC_BCNS) { -+ wiphy_err(wlc->wiphy, "FCSERR while scanning******* -" -+ " tossing\n"); -+ goto toss; -+ } else { -+ wiphy_err(wlc->wiphy, "RCSERR!!!\n"); -+ goto toss; -+ } -+ } -+ -+ /* check received pkt has at least frame control field */ -+ if (len < D11_PHY_HDR_LEN + sizeof(h->frame_control)) -+ goto toss; -+ -+ /* not supporting A-MSDU */ -+ is_amsdu = rxh->RxStatus2 & RXS_AMSDU_MASK; -+ if (is_amsdu) -+ goto toss; -+ -+ brcms_c_recvctl(wlc, rxh, p); -+ return; -+ -+ toss: -+ brcmu_pkt_buf_free_skb(p); -+} -+ -+/* Process received frames */ -+/* -+ * Return true if more frames need to be processed. false otherwise. -+ * Param 'bound' indicates max. # frames to process before break out. -+ */ -+static bool -+brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound) -+{ -+ struct sk_buff *p; -+ struct sk_buff *head = NULL; -+ struct sk_buff *tail = NULL; -+ uint n = 0; -+ uint bound_limit = bound ? RXBND : -1; -+ -+ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); -+ /* gather received frames */ -+ while ((p = dma_rx(wlc_hw->di[fifo]))) { -+ -+ if (!tail) -+ head = tail = p; -+ else { -+ tail->prev = p; -+ tail = p; -+ } -+ -+ /* !give others some time to run! */ -+ if (++n >= bound_limit) -+ break; -+ } -+ -+ /* post more rbufs */ -+ dma_rxfill(wlc_hw->di[fifo]); -+ -+ /* process each frame */ -+ while ((p = head) != NULL) { -+ struct d11rxhdr_le *rxh_le; -+ struct d11rxhdr *rxh; -+ head = head->prev; -+ p->prev = NULL; -+ -+ rxh_le = (struct d11rxhdr_le *)p->data; -+ rxh = (struct d11rxhdr *)p->data; -+ -+ /* fixup rx header endianness */ -+ rxh->RxFrameSize = le16_to_cpu(rxh_le->RxFrameSize); -+ rxh->PhyRxStatus_0 = le16_to_cpu(rxh_le->PhyRxStatus_0); -+ rxh->PhyRxStatus_1 = le16_to_cpu(rxh_le->PhyRxStatus_1); -+ rxh->PhyRxStatus_2 = le16_to_cpu(rxh_le->PhyRxStatus_2); -+ rxh->PhyRxStatus_3 = le16_to_cpu(rxh_le->PhyRxStatus_3); -+ rxh->PhyRxStatus_4 = le16_to_cpu(rxh_le->PhyRxStatus_4); -+ rxh->PhyRxStatus_5 = le16_to_cpu(rxh_le->PhyRxStatus_5); -+ rxh->RxStatus1 = le16_to_cpu(rxh_le->RxStatus1); -+ rxh->RxStatus2 = le16_to_cpu(rxh_le->RxStatus2); -+ rxh->RxTSFTime = le16_to_cpu(rxh_le->RxTSFTime); -+ rxh->RxChan = le16_to_cpu(rxh_le->RxChan); -+ -+ brcms_c_recv(wlc_hw->wlc, p); -+ } -+ -+ return n >= bound_limit; -+} -+ -+/* second-level interrupt processing -+ * Return true if another dpc needs to be re-scheduled. false otherwise. -+ * Param 'bounded' indicates if applicable loops should be bounded. -+ */ -+bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) -+{ -+ u32 macintstatus; -+ struct brcms_hardware *wlc_hw = wlc->hw; -+ struct d11regs __iomem *regs = wlc_hw->regs; -+ struct wiphy *wiphy = wlc->wiphy; -+ -+ if (brcms_deviceremoved(wlc)) { -+ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, -+ __func__); -+ brcms_down(wlc->wl); -+ return false; -+ } -+ -+ /* grab and clear the saved software intstatus bits */ -+ macintstatus = wlc->macintstatus; -+ wlc->macintstatus = 0; -+ -+ BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n", -+ wlc_hw->unit, macintstatus); -+ -+ WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */ -+ -+ /* tx status */ -+ if (macintstatus & MI_TFS) { -+ bool fatal; -+ if (brcms_b_txstatus(wlc->hw, bounded, &fatal)) -+ wlc->macintstatus |= MI_TFS; -+ if (fatal) { -+ wiphy_err(wiphy, "MI_TFS: fatal\n"); -+ goto fatal; -+ } -+ } -+ -+ if (macintstatus & (MI_TBTT | MI_DTIM_TBTT)) -+ brcms_c_tbtt(wlc); -+ -+ /* ATIM window end */ -+ if (macintstatus & MI_ATIMWINEND) { -+ BCMMSG(wlc->wiphy, "end of ATIM window\n"); -+ OR_REG(®s->maccommand, wlc->qvalid); -+ wlc->qvalid = 0; -+ } -+ -+ /* -+ * received data or control frame, MI_DMAINT is -+ * indication of RX_FIFO interrupt -+ */ -+ if (macintstatus & MI_DMAINT) -+ if (brcms_b_recv(wlc_hw, RX_FIFO, bounded)) -+ wlc->macintstatus |= MI_DMAINT; -+ -+ /* noise sample collected */ -+ if (macintstatus & MI_BG_NOISE) -+ wlc_phy_noise_sample_intr(wlc_hw->band->pi); -+ -+ if (macintstatus & MI_GP0) { -+ wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d " -+ "(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now); -+ -+ printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n", -+ __func__, wlc_hw->sih->chip, -+ wlc_hw->sih->chiprev); -+ /* big hammer */ -+ brcms_init(wlc->wl); -+ } -+ -+ /* gptimer timeout */ -+ if (macintstatus & MI_TO) -+ W_REG(®s->gptimer, 0); -+ -+ if (macintstatus & MI_RFDISABLE) { -+ BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the" -+ " RF Disable Input\n", wlc_hw->unit); -+ brcms_rfkill_set_hw_state(wlc->wl); -+ } -+ -+ /* send any enq'd tx packets. Just makes sure to jump start tx */ -+ if (!pktq_empty(&wlc->pkt_queue->q)) -+ brcms_c_send_q(wlc); -+ -+ /* it isn't done and needs to be resched if macintstatus is non-zero */ -+ return wlc->macintstatus != 0; -+ -+ fatal: -+ brcms_init(wlc->wl); -+ return wlc->macintstatus != 0; -+} -+ -+void brcms_c_init(struct brcms_c_info *wlc) -+{ -+ struct d11regs __iomem *regs; -+ u16 chanspec; -+ bool mute = false; -+ -+ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); -+ -+ regs = wlc->regs; -+ -+ /* -+ * This will happen if a big-hammer was executed. In -+ * that case, we want to go back to the channel that -+ * we were on and not new channel -+ */ -+ if (wlc->pub->associated) -+ chanspec = wlc->home_chanspec; -+ else -+ chanspec = brcms_c_init_chanspec(wlc); -+ -+ brcms_b_init(wlc->hw, chanspec, mute); -+ -+ /* update beacon listen interval */ -+ brcms_c_bcn_li_upd(wlc); -+ -+ /* write ethernet address to core */ -+ brcms_c_set_mac(wlc->bsscfg); -+ brcms_c_set_bssid(wlc->bsscfg); -+ -+ /* Update tsf_cfprep if associated and up */ -+ if (wlc->pub->associated && wlc->bsscfg->up) { -+ u32 bi; -+ -+ /* get beacon period and convert to uS */ -+ bi = wlc->bsscfg->current_bss->beacon_period << 10; -+ /* -+ * update since init path would reset -+ * to default value -+ */ -+ W_REG(®s->tsf_cfprep, -+ (bi << CFPREP_CBI_SHIFT)); -+ -+ /* Update maccontrol PM related bits */ -+ brcms_c_set_ps_ctrl(wlc); -+ } -+ -+ brcms_c_bandinit_ordered(wlc, chanspec); -+ -+ /* init probe response timeout */ -+ brcms_b_write_shm(wlc->hw, M_PRS_MAXTIME, wlc->prb_resp_timeout); -+ -+ /* init max burst txop (framebursting) */ -+ brcms_b_write_shm(wlc->hw, M_MBURST_TXOP, -+ (wlc-> -+ _rifs ? (EDCF_AC_VO_TXOP_AP << 5) : MAXFRAMEBURST_TXOP)); -+ -+ /* initialize maximum allowed duty cycle */ -+ brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_ofdm, true, true); -+ brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_cck, false, true); -+ -+ /* -+ * Update some shared memory locations related to -+ * max AMPDU size allowed to received -+ */ -+ brcms_c_ampdu_shm_upd(wlc->ampdu); -+ -+ /* band-specific inits */ -+ brcms_c_bsinit(wlc); -+ -+ /* Enable EDCF mode (while the MAC is suspended) */ -+ OR_REG(®s->ifs_ctl, IFS_USEEDCF); -+ brcms_c_edcf_setparams(wlc, false); -+ -+ /* Init precedence maps for empty FIFOs */ -+ brcms_c_tx_prec_map_init(wlc); -+ -+ /* read the ucode version if we have not yet done so */ -+ if (wlc->ucode_rev == 0) { -+ wlc->ucode_rev = -+ brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR) << NBITS(u16); -+ wlc->ucode_rev |= brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR); -+ } -+ -+ /* ..now really unleash hell (allow the MAC out of suspend) */ -+ brcms_c_enable_mac(wlc); -+ -+ /* clear tx flow control */ -+ brcms_c_txflowcontrol_reset(wlc); -+ -+ /* enable the RF Disable Delay timer */ -+ W_REG(&wlc->regs->rfdisabledly, RFDISABLE_DEFAULT); -+ -+ /* initialize mpc delay */ -+ wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT; -+ -+ /* -+ * Initialize WME parameters; if they haven't been set by some other -+ * mechanism (IOVar, etc) then read them from the hardware. -+ */ -+ if (GFIELD(wlc->wme_retries[0], EDCF_SHORT) == 0) { -+ /* Uninitialized; read from HW */ -+ int ac; -+ -+ for (ac = 0; ac < AC_COUNT; ac++) -+ wlc->wme_retries[ac] = -+ brcms_b_read_shm(wlc->hw, M_AC_TXLMT_ADDR(ac)); -+ } -+} -+ -+/* -+ * The common driver entry routine. Error codes should be unique -+ */ -+struct brcms_c_info * -+brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit, -+ bool piomode, void __iomem *regsva, struct pci_dev *btparam, -+ uint *perr) -+{ -+ struct brcms_c_info *wlc; -+ uint err = 0; -+ uint i, j; -+ struct brcms_pub *pub; -+ -+ /* allocate struct brcms_c_info state and its substructures */ -+ wlc = (struct brcms_c_info *) brcms_c_attach_malloc(unit, &err, device); -+ if (wlc == NULL) -+ goto fail; -+ wlc->wiphy = wl->wiphy; -+ pub = wlc->pub; -+ -+#if defined(BCMDBG) -+ wlc_info_dbg = wlc; -+#endif -+ -+ wlc->band = wlc->bandstate[0]; -+ wlc->core = wlc->corestate; -+ wlc->wl = wl; -+ pub->unit = unit; -+ pub->_piomode = piomode; -+ wlc->bandinit_pending = false; -+ -+ /* populate struct brcms_c_info with default values */ -+ brcms_c_info_init(wlc, unit); -+ -+ /* update sta/ap related parameters */ -+ brcms_c_ap_upd(wlc); -+ -+ /* -+ * low level attach steps(all hw accesses go -+ * inside, no more in rest of the attach) -+ */ -+ err = brcms_b_attach(wlc, vendor, device, unit, piomode, regsva, -+ btparam); -+ if (err) -+ goto fail; -+ -+ brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR, OFF); -+ -+ pub->phy_11ncapable = BRCMS_PHY_11N_CAP(wlc->band); -+ -+ /* disable allowed duty cycle */ -+ wlc->tx_duty_cycle_ofdm = 0; -+ wlc->tx_duty_cycle_cck = 0; -+ -+ brcms_c_stf_phy_chain_calc(wlc); -+ -+ /* txchain 1: txant 0, txchain 2: txant 1 */ -+ if (BRCMS_ISNPHY(wlc->band) && (wlc->stf->txstreams == 1)) -+ wlc->stf->txant = wlc->stf->hw_txchain - 1; -+ -+ /* push to BMAC driver */ -+ wlc_phy_stf_chain_init(wlc->band->pi, wlc->stf->hw_txchain, -+ wlc->stf->hw_rxchain); -+ -+ /* pull up some info resulting from the low attach */ -+ for (i = 0; i < NFIFO; i++) -+ wlc->core->txavail[i] = wlc->hw->txavail[i]; -+ -+ memcpy(&wlc->perm_etheraddr, &wlc->hw->etheraddr, ETH_ALEN); -+ memcpy(&pub->cur_etheraddr, &wlc->hw->etheraddr, ETH_ALEN); -+ -+ for (j = 0; j < wlc->pub->_nbands; j++) { -+ wlc->band = wlc->bandstate[j]; -+ -+ if (!brcms_c_attach_stf_ant_init(wlc)) { -+ err = 24; -+ goto fail; -+ } -+ -+ /* default contention windows size limits */ -+ wlc->band->CWmin = APHY_CWMIN; -+ wlc->band->CWmax = PHY_CWMAX; -+ -+ /* init gmode value */ -+ if (wlc->band->bandtype == BRCM_BAND_2G) { -+ wlc->band->gmode = GMODE_AUTO; -+ brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, -+ wlc->band->gmode); -+ } -+ -+ /* init _n_enab supported mode */ -+ if (BRCMS_PHY_11N_CAP(wlc->band)) { -+ pub->_n_enab = SUPPORT_11N; -+ brcms_c_protection_upd(wlc, BRCMS_PROT_N_USER, -+ ((pub->_n_enab == -+ SUPPORT_11N) ? WL_11N_2x2 : -+ WL_11N_3x3)); -+ } -+ -+ /* init per-band default rateset, depend on band->gmode */ -+ brcms_default_rateset(wlc, &wlc->band->defrateset); -+ -+ /* fill in hw_rateset */ -+ brcms_c_rateset_filter(&wlc->band->defrateset, -+ &wlc->band->hw_rateset, false, -+ BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK, -+ (bool) (wlc->pub->_n_enab & SUPPORT_11N)); -+ } -+ -+ /* -+ * update antenna config due to -+ * wlc->stf->txant/txchain/ant_rx_ovr change -+ */ -+ brcms_c_stf_phy_txant_upd(wlc); -+ -+ /* attach each modules */ -+ err = brcms_c_attach_module(wlc); -+ if (err != 0) -+ goto fail; -+ -+ if (!brcms_c_timers_init(wlc, unit)) { -+ wiphy_err(wl->wiphy, "wl%d: %s: init_timer failed\n", unit, -+ __func__); -+ err = 32; -+ goto fail; -+ } -+ -+ /* depend on rateset, gmode */ -+ wlc->cmi = brcms_c_channel_mgr_attach(wlc); -+ if (!wlc->cmi) { -+ wiphy_err(wl->wiphy, "wl%d: %s: channel_mgr_attach failed" -+ "\n", unit, __func__); -+ err = 33; -+ goto fail; -+ } -+ -+ /* init default when all parameters are ready, i.e. ->rateset */ -+ brcms_c_bss_default_init(wlc); -+ -+ /* -+ * Complete the wlc default state initializations.. -+ */ -+ -+ /* allocate our initial queue */ -+ wlc->pkt_queue = brcms_c_txq_alloc(wlc); -+ if (wlc->pkt_queue == NULL) { -+ wiphy_err(wl->wiphy, "wl%d: %s: failed to malloc tx queue\n", -+ unit, __func__); -+ err = 100; -+ goto fail; -+ } -+ -+ wlc->bsscfg->wlc = wlc; -+ -+ wlc->mimoft = FT_HT; -+ wlc->mimo_40txbw = AUTO; -+ wlc->ofdm_40txbw = AUTO; -+ wlc->cck_40txbw = AUTO; -+ brcms_c_update_mimo_band_bwcap(wlc, BRCMS_N_BW_20IN2G_40IN5G); -+ -+ /* Set default values of SGI */ -+ if (BRCMS_SGI_CAP_PHY(wlc)) { -+ brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 | -+ BRCMS_N_SGI_40)); -+ } else if (BRCMS_ISSSLPNPHY(wlc->band)) { -+ brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 | -+ BRCMS_N_SGI_40)); -+ } else { -+ brcms_c_ht_update_sgi_rx(wlc, 0); -+ } -+ -+ /* initialize radio_mpc_disable according to wlc->mpc */ -+ brcms_c_radio_mpc_upd(wlc); -+ brcms_b_antsel_set(wlc->hw, wlc->asi->antsel_avail); -+ -+ if (perr) -+ *perr = 0; -+ -+ return wlc; -+ -+ fail: -+ wiphy_err(wl->wiphy, "wl%d: %s: failed with err %d\n", -+ unit, __func__, err); -+ if (wlc) -+ brcms_c_detach(wlc); -+ -+ if (perr) -+ *perr = err; -+ return NULL; -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.h.orig 2011-11-09 13:46:58.251800557 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.h 2011-11-09 13:47:17.004566116 -0500 -@@ -0,0 +1,735 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_MAIN_H_ -+#define _BRCM_MAIN_H_ -+ -+#include -+ -+#include -+#include "types.h" -+#include "d11.h" -+#include "scb.h" -+ -+#define INVCHANNEL 255 /* invalid channel */ -+ -+/* max # brcms_c_module_register() calls */ -+#define BRCMS_MAXMODULES 22 -+ -+#define SEQNUM_SHIFT 4 -+#define SEQNUM_MAX 0x1000 -+ -+#define NTXRATE 64 /* # tx MPDUs rate is reported for */ -+ -+/* Maximum wait time for a MAC suspend */ -+/* uS: 83mS is max packet time (64KB ampdu @ 6Mbps) */ -+#define BRCMS_MAX_MAC_SUSPEND 83000 -+ -+/* responses for probe requests older that this are tossed, zero to disable */ -+#define BRCMS_PRB_RESP_TIMEOUT 0 /* Disable probe response timeout */ -+ -+/* transmit buffer max headroom for protocol headers */ -+#define TXOFF (D11_TXH_LEN + D11_PHY_HDR_LEN) -+ -+#define AC_COUNT 4 -+ -+/* Macros for doing definition and get/set of bitfields -+ * Usage example, e.g. a three-bit field (bits 4-6): -+ * #define _M BITFIELD_MASK(3) -+ * #define _S 4 -+ * ... -+ * regval = R_REG(osh, ®s->regfoo); -+ * field = GFIELD(regval, ); -+ * regval = SFIELD(regval, , 1); -+ * W_REG(osh, ®s->regfoo, regval); -+ */ -+#define BITFIELD_MASK(width) \ -+ (((unsigned)1 << (width)) - 1) -+#define GFIELD(val, field) \ -+ (((val) >> field ## _S) & field ## _M) -+#define SFIELD(val, field, bits) \ -+ (((val) & (~(field ## _M << field ## _S))) | \ -+ ((unsigned)(bits) << field ## _S)) -+ -+#define SW_TIMER_MAC_STAT_UPD 30 /* periodic MAC stats update */ -+ -+/* max # supported core revisions (0 .. MAXCOREREV - 1) */ -+#define MAXCOREREV 28 -+ -+/* Double check that unsupported cores are not enabled */ -+#if CONF_MSK(D11CONF, 0x4f) || CONF_GE(D11CONF, MAXCOREREV) -+#error "Configuration for D11CONF includes unsupported versions." -+#endif /* Bad versions */ -+ -+/* values for shortslot_override */ -+#define BRCMS_SHORTSLOT_AUTO -1 /* Driver will manage Shortslot setting */ -+#define BRCMS_SHORTSLOT_OFF 0 /* Turn off short slot */ -+#define BRCMS_SHORTSLOT_ON 1 /* Turn on short slot */ -+ -+/* value for short/long and mixmode/greenfield preamble */ -+#define BRCMS_LONG_PREAMBLE (0) -+#define BRCMS_SHORT_PREAMBLE (1 << 0) -+#define BRCMS_GF_PREAMBLE (1 << 1) -+#define BRCMS_MM_PREAMBLE (1 << 2) -+#define BRCMS_IS_MIMO_PREAMBLE(_pre) (((_pre) == BRCMS_GF_PREAMBLE) || \ -+ ((_pre) == BRCMS_MM_PREAMBLE)) -+ -+/* TxFrameID */ -+/* seq and frag bits: SEQNUM_SHIFT, FRAGNUM_MASK (802.11.h) */ -+/* rate epoch bits: TXFID_RATE_SHIFT, TXFID_RATE_MASK ((wlc_rate.c) */ -+#define TXFID_QUEUE_MASK 0x0007 /* Bits 0-2 */ -+#define TXFID_SEQ_MASK 0x7FE0 /* Bits 5-15 */ -+#define TXFID_SEQ_SHIFT 5 /* Number of bit shifts */ -+#define TXFID_RATE_PROBE_MASK 0x8000 /* Bit 15 for rate probe */ -+#define TXFID_RATE_MASK 0x0018 /* Mask for bits 3 and 4 */ -+#define TXFID_RATE_SHIFT 3 /* Shift 3 bits for rate mask */ -+ -+/* promote boardrev */ -+#define BOARDREV_PROMOTABLE 0xFF /* from */ -+#define BOARDREV_PROMOTED 1 /* to */ -+ -+#define DATA_BLOCK_TX_SUPR (1 << 4) -+ -+/* 802.1D Priority to TX FIFO number for wme */ -+extern const u8 prio2fifo[]; -+ -+/* Ucode MCTL_WAKE override bits */ -+#define BRCMS_WAKE_OVERRIDE_CLKCTL 0x01 -+#define BRCMS_WAKE_OVERRIDE_PHYREG 0x02 -+#define BRCMS_WAKE_OVERRIDE_MACSUSPEND 0x04 -+#define BRCMS_WAKE_OVERRIDE_TXFIFO 0x08 -+#define BRCMS_WAKE_OVERRIDE_FORCEFAST 0x10 -+ -+/* stuff pulled in from wlc.c */ -+ -+/* Interrupt bit error summary. Don't include I_RU: we refill DMA at other -+ * times; and if we run out, constant I_RU interrupts may cause lockup. We -+ * will still get error counts from rx0ovfl. -+ */ -+#define I_ERRORS (I_PC | I_PD | I_DE | I_RO | I_XU) -+/* default software intmasks */ -+#define DEF_RXINTMASK (I_RI) /* enable rx int on rxfifo only */ -+#define DEF_MACINTMASK (MI_TXSTOP | MI_TBTT | MI_ATIMWINEND | MI_PMQ | \ -+ MI_PHYTXERR | MI_DMAINT | MI_TFS | MI_BG_NOISE | \ -+ MI_CCA | MI_TO | MI_GP0 | MI_RFDISABLE | MI_PWRUP) -+ -+#define MAXTXPKTS 6 /* max # pkts pending */ -+ -+/* frameburst */ -+#define MAXTXFRAMEBURST 8 /* vanilla xpress mode: max frames/burst */ -+#define MAXFRAMEBURST_TXOP 10000 /* Frameburst TXOP in usec */ -+ -+#define NFIFO 6 /* # tx/rx fifopairs */ -+ -+/* PLL requests */ -+ -+/* pll is shared on old chips */ -+#define BRCMS_PLLREQ_SHARED 0x1 -+/* hold pll for radio monitor register checking */ -+#define BRCMS_PLLREQ_RADIO_MON 0x2 -+/* hold/release pll for some short operation */ -+#define BRCMS_PLLREQ_FLIP 0x4 -+ -+#define CHANNEL_BANDUNIT(wlc, ch) \ -+ (((ch) <= CH_MAX_2G_CHANNEL) ? BAND_2G_INDEX : BAND_5G_INDEX) -+ -+#define OTHERBANDUNIT(wlc) \ -+ ((uint)((wlc)->band->bandunit ? BAND_2G_INDEX : BAND_5G_INDEX)) -+ -+/* -+ * 802.11 protection information -+ * -+ * _g: use g spec protection, driver internal. -+ * g_override: override for use of g spec protection. -+ * gmode_user: user config gmode, operating band->gmode is different. -+ * overlap: Overlap BSS/IBSS protection for both 11g and 11n. -+ * nmode_user: user config nmode, operating pub->nmode is different. -+ * n_cfg: use OFDM protection on MIMO frames. -+ * n_cfg_override: override for use of N protection. -+ * nongf: non-GF present protection. -+ * nongf_override: override for use of GF protection. -+ * n_pam_override: override for preamble: MM or GF. -+ * n_obss: indicated OBSS Non-HT STA present. -+*/ -+struct brcms_protection { -+ bool _g; -+ s8 g_override; -+ u8 gmode_user; -+ s8 overlap; -+ s8 nmode_user; -+ s8 n_cfg; -+ s8 n_cfg_override; -+ bool nongf; -+ s8 nongf_override; -+ s8 n_pam_override; -+ bool n_obss; -+}; -+ -+/* -+ * anything affecting the single/dual streams/antenna operation -+ * -+ * hw_txchain: HW txchain bitmap cfg. -+ * txchain: txchain bitmap being used. -+ * txstreams: number of txchains being used. -+ * hw_rxchain: HW rxchain bitmap cfg. -+ * rxchain: rxchain bitmap being used. -+ * rxstreams: number of rxchains being used. -+ * ant_rx_ovr: rx antenna override. -+ * txant: userTx antenna setting. -+ * phytxant: phyTx antenna setting in txheader. -+ * ss_opmode: singlestream Operational mode, 0:siso; 1:cdd. -+ * ss_algosel_auto: if true, use wlc->stf->ss_algo_channel; -+ * else use wlc->band->stf->ss_mode_band. -+ * ss_algo_channel: ss based on per-channel algo: 0: SISO, 1: CDD 2: STBC. -+ * rxchain_restore_delay: delay time to restore default rxchain. -+ * ldpc: AUTO/ON/OFF ldpc cap supported. -+ * txcore[MAX_STREAMS_SUPPORTED + 1]: bitmap of selected core for each Nsts. -+ * spatial_policy: -+ */ -+struct brcms_stf { -+ u8 hw_txchain; -+ u8 txchain; -+ u8 txstreams; -+ u8 hw_rxchain; -+ u8 rxchain; -+ u8 rxstreams; -+ u8 ant_rx_ovr; -+ s8 txant; -+ u16 phytxant; -+ u8 ss_opmode; -+ bool ss_algosel_auto; -+ u16 ss_algo_channel; -+ u8 rxchain_restore_delay; -+ s8 ldpc; -+ u8 txcore[MAX_STREAMS_SUPPORTED + 1]; -+ s8 spatial_policy; -+}; -+ -+#define BRCMS_STF_SS_STBC_TX(wlc, scb) \ -+ (((wlc)->stf->txstreams > 1) && (((wlc)->band->band_stf_stbc_tx == ON) \ -+ || (((scb)->flags & SCB_STBCCAP) && \ -+ (wlc)->band->band_stf_stbc_tx == AUTO && \ -+ isset(&((wlc)->stf->ss_algo_channel), PHY_TXC1_MODE_STBC)))) -+ -+#define BRCMS_STBC_CAP_PHY(wlc) (BRCMS_ISNPHY(wlc->band) && \ -+ NREV_GE(wlc->band->phyrev, 3)) -+ -+#define BRCMS_SGI_CAP_PHY(wlc) ((BRCMS_ISNPHY(wlc->band) && \ -+ NREV_GE(wlc->band->phyrev, 3)) || \ -+ BRCMS_ISLCNPHY(wlc->band)) -+ -+#define BRCMS_CHAN_PHYTYPE(x) (((x) & RXS_CHAN_PHYTYPE_MASK) \ -+ >> RXS_CHAN_PHYTYPE_SHIFT) -+#define BRCMS_CHAN_CHANNEL(x) (((x) & RXS_CHAN_ID_MASK) \ -+ >> RXS_CHAN_ID_SHIFT) -+ -+/* -+ * core state (mac) -+ */ -+struct brcms_core { -+ uint coreidx; /* # sb enumerated core */ -+ -+ /* fifo */ -+ uint *txavail[NFIFO]; /* # tx descriptors available */ -+ s16 txpktpend[NFIFO]; /* tx admission control */ -+ -+ struct macstat *macstat_snapshot; /* mac hw prev read values */ -+}; -+ -+/* -+ * band state (phy+ana+radio) -+ */ -+struct brcms_band { -+ int bandtype; /* BRCM_BAND_2G, BRCM_BAND_5G */ -+ uint bandunit; /* bandstate[] index */ -+ -+ u16 phytype; /* phytype */ -+ u16 phyrev; -+ u16 radioid; -+ u16 radiorev; -+ struct brcms_phy_pub *pi; /* pointer to phy specific information */ -+ bool abgphy_encore; -+ -+ u8 gmode; /* currently active gmode */ -+ -+ struct scb *hwrs_scb; /* permanent scb for hw rateset */ -+ -+ /* band-specific copy of default_bss.rateset */ -+ struct brcms_c_rateset defrateset; -+ -+ u8 band_stf_ss_mode; /* Configured STF type, 0:siso; 1:cdd */ -+ s8 band_stf_stbc_tx; /* STBC TX 0:off; 1:force on; -1:auto */ -+ /* rates supported by chip (phy-specific) */ -+ struct brcms_c_rateset hw_rateset; -+ u8 basic_rate[BRCM_MAXRATE + 1]; /* basic rates indexed by rate */ -+ bool mimo_cap_40; /* 40 MHz cap enabled on this band */ -+ s8 antgain; /* antenna gain from srom */ -+ -+ u16 CWmin; /* minimum size of contention window, in unit of aSlotTime */ -+ u16 CWmax; /* maximum size of contention window, in unit of aSlotTime */ -+ struct ieee80211_supported_band band; -+}; -+ -+/* module control blocks */ -+struct modulecb { -+ /* module name : NULL indicates empty array member */ -+ char name[32]; -+ /* handle passed when handler 'doiovar' is called */ -+ struct brcms_info *hdl; -+ -+ int (*down_fn)(void *handle); /* down handler. Note: the int returned -+ * by the down function is a count of the -+ * number of timers that could not be -+ * freed. -+ */ -+ -+}; -+ -+struct brcms_hw_band { -+ int bandtype; /* BRCM_BAND_2G, BRCM_BAND_5G */ -+ uint bandunit; /* bandstate[] index */ -+ u16 mhfs[MHFMAX]; /* MHF array shadow */ -+ u8 bandhw_stf_ss_mode; /* HW configured STF type, 0:siso; 1:cdd */ -+ u16 CWmin; -+ u16 CWmax; -+ u32 core_flags; -+ -+ u16 phytype; /* phytype */ -+ u16 phyrev; -+ u16 radioid; -+ u16 radiorev; -+ struct brcms_phy_pub *pi; /* pointer to phy specific information */ -+ bool abgphy_encore; -+}; -+ -+struct brcms_hardware { -+ bool _piomode; /* true if pio mode */ -+ struct brcms_c_info *wlc; -+ -+ /* fifo */ -+ struct dma_pub *di[NFIFO]; /* dma handles, per fifo */ -+ -+ uint unit; /* device instance number */ -+ -+ /* version info */ -+ u16 vendorid; /* PCI vendor id */ -+ u16 deviceid; /* PCI device id */ -+ uint corerev; /* core revision */ -+ u8 sromrev; /* version # of the srom */ -+ u16 boardrev; /* version # of particular board */ -+ u32 boardflags; /* Board specific flags from srom */ -+ u32 boardflags2; /* More board flags if sromrev >= 4 */ -+ u32 machwcap; /* MAC capabilities */ -+ u32 machwcap_backup; /* backup of machwcap */ -+ -+ struct si_pub *sih; /* SI handle (cookie for siutils calls) */ -+ struct d11regs __iomem *regs; /* pointer to device registers */ -+ struct phy_shim_info *physhim; /* phy shim layer handler */ -+ struct shared_phy *phy_sh; /* pointer to shared phy state */ -+ struct brcms_hw_band *band;/* pointer to active per-band state */ -+ /* band state per phy/radio */ -+ struct brcms_hw_band *bandstate[MAXBANDS]; -+ u16 bmac_phytxant; /* cache of high phytxant state */ -+ bool shortslot; /* currently using 11g ShortSlot timing */ -+ u16 SRL; /* 802.11 dot11ShortRetryLimit */ -+ u16 LRL; /* 802.11 dot11LongRetryLimit */ -+ u16 SFBL; /* Short Frame Rate Fallback Limit */ -+ u16 LFBL; /* Long Frame Rate Fallback Limit */ -+ -+ bool up; /* d11 hardware up and running */ -+ uint now; /* # elapsed seconds */ -+ uint _nbands; /* # bands supported */ -+ u16 chanspec; /* bmac chanspec shadow */ -+ -+ uint *txavail[NFIFO]; /* # tx descriptors available */ -+ const u16 *xmtfifo_sz; /* fifo size in 256B for each xmt fifo */ -+ -+ u32 pllreq; /* pll requests to keep PLL on */ -+ -+ u8 suspended_fifos; /* Which TX fifo to remain awake for */ -+ u32 maccontrol; /* Cached value of maccontrol */ -+ uint mac_suspend_depth; /* current depth of mac_suspend levels */ -+ u32 wake_override; /* bit flags to force MAC to WAKE mode */ -+ u32 mute_override; /* Prevent ucode from sending beacons */ -+ u8 etheraddr[ETH_ALEN]; /* currently configured ethernet address */ -+ bool noreset; /* true= do not reset hw, used by WLC_OUT */ -+ bool forcefastclk; /* true if h/w is forcing to use fast clk */ -+ bool clk; /* core is out of reset and has clock */ -+ bool sbclk; /* sb has clock */ -+ bool phyclk; /* phy is out of reset and has clock */ -+ -+ bool ucode_loaded; /* true after ucode downloaded */ -+ -+ -+ u8 hw_stf_ss_opmode; /* STF single stream operation mode */ -+ u8 antsel_type; /* Type of boardlevel mimo antenna switch-logic -+ * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board -+ */ -+ u32 antsel_avail; /* -+ * put struct antsel_info here if more info is -+ * needed -+ */ -+}; -+ -+/* TX Queue information -+ * -+ * Each flow of traffic out of the device has a TX Queue with independent -+ * flow control. Several interfaces may be associated with a single TX Queue -+ * if they belong to the same flow of traffic from the device. For multi-channel -+ * operation there are independent TX Queues for each channel. -+ */ -+struct brcms_txq_info { -+ struct brcms_txq_info *next; -+ struct pktq q; -+ uint stopped; /* tx flow control bits */ -+}; -+ -+/* -+ * Principal common driver data structure. -+ * -+ * pub: pointer to driver public state. -+ * wl: pointer to specific private state. -+ * regs: pointer to device registers. -+ * hw: HW related state. -+ * clkreq_override: setting for clkreq for PCIE : Auto, 0, 1. -+ * fastpwrup_dly: time in us needed to bring up d11 fast clock. -+ * macintstatus: bit channel between isr and dpc. -+ * macintmask: sw runtime master macintmask value. -+ * defmacintmask: default "on" macintmask value. -+ * clk: core is out of reset and has clock. -+ * core: pointer to active io core. -+ * band: pointer to active per-band state. -+ * corestate: per-core state (one per hw core). -+ * bandstate: per-band state (one per phy/radio). -+ * qvalid: DirFrmQValid and BcMcFrmQValid. -+ * ampdu: ampdu module handler. -+ * asi: antsel module handler. -+ * cmi: channel manager module handler. -+ * vendorid: PCI vendor id. -+ * deviceid: PCI device id. -+ * ucode_rev: microcode revision. -+ * machwcap: MAC capabilities, BMAC shadow. -+ * perm_etheraddr: original sprom local ethernet address. -+ * bandlocked: disable auto multi-band switching. -+ * bandinit_pending: track band init in auto band. -+ * radio_monitor: radio timer is running. -+ * going_down: down path intermediate variable. -+ * mpc: enable minimum power consumption. -+ * mpc_dlycnt: # of watchdog cnt before turn disable radio. -+ * mpc_offcnt: # of watchdog cnt that radio is disabled. -+ * mpc_delay_off: delay radio disable by # of watchdog cnt. -+ * prev_non_delay_mpc: prev state brcms_c_is_non_delay_mpc. -+ * wdtimer: timer for watchdog routine. -+ * radio_timer: timer for hw radio button monitor routine. -+ * monitor: monitor (MPDU sniffing) mode. -+ * bcnmisc_monitor: bcns promisc mode override for monitor. -+ * _rifs: enable per-packet rifs. -+ * bcn_li_bcn: beacon listen interval in # beacons. -+ * bcn_li_dtim: beacon listen interval in # dtims. -+ * WDarmed: watchdog timer is armed. -+ * WDlast: last time wlc_watchdog() was called. -+ * edcf_txop[AC_COUNT]: current txop for each ac. -+ * wme_retries: per-AC retry limits. -+ * tx_prec_map: Precedence map based on HW FIFO space. -+ * fifo2prec_map[NFIFO]: pointer to fifo2_prec map based on WME. -+ * bsscfg: set of BSS configurations, idx 0 is default and always valid. -+ * cfg: the primary bsscfg (can be AP or STA). -+ * tx_queues: common TX Queue list. -+ * modulecb: -+ * mimoft: SIGN or 11N. -+ * cck_40txbw: 11N, cck tx b/w override when in 40MHZ mode. -+ * ofdm_40txbw: 11N, ofdm tx b/w override when in 40MHZ mode. -+ * mimo_40txbw: 11N, mimo tx b/w override when in 40MHZ mode. -+ * default_bss: configured BSS parameters. -+ * mc_fid_counter: BC/MC FIFO frame ID counter. -+ * country_default: saved country for leaving 802.11d auto-country mode. -+ * autocountry_default: initial country for 802.11d auto-country mode. -+ * prb_resp_timeout: do not send prb resp if request older -+ * than this, 0 = disable. -+ * home_chanspec: shared home chanspec. -+ * chanspec: target operational channel. -+ * usr_fragthresh: user configured fragmentation threshold. -+ * fragthresh[NFIFO]: per-fifo fragmentation thresholds. -+ * RTSThresh: 802.11 dot11RTSThreshold. -+ * SRL: 802.11 dot11ShortRetryLimit. -+ * LRL: 802.11 dot11LongRetryLimit. -+ * SFBL: Short Frame Rate Fallback Limit. -+ * LFBL: Long Frame Rate Fallback Limit. -+ * shortslot: currently using 11g ShortSlot timing. -+ * shortslot_override: 11g ShortSlot override. -+ * include_legacy_erp: include Legacy ERP info elt ID 47 as well as g ID 42. -+ * PLCPHdr_override: 802.11b Preamble Type override. -+ * stf: -+ * bcn_rspec: save bcn ratespec purpose. -+ * tempsense_lasttime; -+ * tx_duty_cycle_ofdm: maximum allowed duty cycle for OFDM. -+ * tx_duty_cycle_cck: maximum allowed duty cycle for CCK. -+ * pkt_queue: txq for transmit packets. -+ * wiphy: -+ * pri_scb: primary Station Control Block -+ */ -+struct brcms_c_info { -+ struct brcms_pub *pub; -+ struct brcms_info *wl; -+ struct d11regs __iomem *regs; -+ struct brcms_hardware *hw; -+ -+ /* clock */ -+ u16 fastpwrup_dly; -+ -+ /* interrupt */ -+ u32 macintstatus; -+ u32 macintmask; -+ u32 defmacintmask; -+ -+ bool clk; -+ -+ /* multiband */ -+ struct brcms_core *core; -+ struct brcms_band *band; -+ struct brcms_core *corestate; -+ struct brcms_band *bandstate[MAXBANDS]; -+ -+ /* packet queue */ -+ uint qvalid; -+ -+ struct ampdu_info *ampdu; -+ struct antsel_info *asi; -+ struct brcms_cm_info *cmi; -+ -+ u16 vendorid; -+ u16 deviceid; -+ uint ucode_rev; -+ -+ u8 perm_etheraddr[ETH_ALEN]; -+ -+ bool bandlocked; -+ bool bandinit_pending; -+ -+ bool radio_monitor; -+ bool going_down; -+ -+ bool mpc; -+ u8 mpc_dlycnt; -+ u8 mpc_offcnt; -+ u8 mpc_delay_off; -+ u8 prev_non_delay_mpc; -+ -+ struct brcms_timer *wdtimer; -+ struct brcms_timer *radio_timer; -+ -+ /* promiscuous */ -+ bool monitor; -+ bool bcnmisc_monitor; -+ -+ /* driver feature */ -+ bool _rifs; -+ -+ /* AP-STA synchronization, power save */ -+ u8 bcn_li_bcn; -+ u8 bcn_li_dtim; -+ -+ bool WDarmed; -+ u32 WDlast; -+ -+ /* WME */ -+ u16 edcf_txop[AC_COUNT]; -+ -+ u16 wme_retries[AC_COUNT]; -+ u16 tx_prec_map; -+ u16 fifo2prec_map[NFIFO]; -+ -+ struct brcms_bss_cfg *bsscfg; -+ -+ /* tx queue */ -+ struct brcms_txq_info *tx_queues; -+ -+ struct modulecb *modulecb; -+ -+ u8 mimoft; -+ s8 cck_40txbw; -+ s8 ofdm_40txbw; -+ s8 mimo_40txbw; -+ -+ struct brcms_bss_info *default_bss; -+ -+ u16 mc_fid_counter; -+ -+ char country_default[BRCM_CNTRY_BUF_SZ]; -+ char autocountry_default[BRCM_CNTRY_BUF_SZ]; -+ u16 prb_resp_timeout; -+ -+ u16 home_chanspec; -+ -+ /* PHY parameters */ -+ u16 chanspec; -+ u16 usr_fragthresh; -+ u16 fragthresh[NFIFO]; -+ u16 RTSThresh; -+ u16 SRL; -+ u16 LRL; -+ u16 SFBL; -+ u16 LFBL; -+ -+ /* network config */ -+ bool shortslot; -+ s8 shortslot_override; -+ bool include_legacy_erp; -+ -+ struct brcms_protection *protection; -+ s8 PLCPHdr_override; -+ -+ struct brcms_stf *stf; -+ -+ u32 bcn_rspec; -+ -+ uint tempsense_lasttime; -+ -+ u16 tx_duty_cycle_ofdm; -+ u16 tx_duty_cycle_cck; -+ -+ struct brcms_txq_info *pkt_queue; -+ struct wiphy *wiphy; -+ struct scb pri_scb; -+}; -+ -+/* antsel module specific state */ -+struct antsel_info { -+ struct brcms_c_info *wlc; /* pointer to main wlc structure */ -+ struct brcms_pub *pub; /* pointer to public fn */ -+ u8 antsel_type; /* Type of boardlevel mimo antenna switch-logic -+ * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board -+ */ -+ u8 antsel_antswitch; /* board level antenna switch type */ -+ bool antsel_avail; /* Ant selection availability (SROM based) */ -+ struct brcms_antselcfg antcfg_11n; /* antenna configuration */ -+ struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */ -+}; -+ -+/* -+ * BSS configuration state -+ * -+ * wlc: wlc to which this bsscfg belongs to. -+ * up: is this configuration up operational -+ * enable: is this configuration enabled -+ * associated: is BSS in ASSOCIATED state -+ * BSS: infraustructure or adhoc -+ * SSID_len: the length of SSID -+ * SSID: SSID string -+ * -+ * -+ * BSSID: BSSID (associated) -+ * cur_etheraddr: h/w address -+ * flags: BSSCFG flags; see below -+ * -+ * current_bss: BSS parms in ASSOCIATED state -+ * -+ * -+ * ID: 'unique' ID of this bsscfg, assigned at bsscfg allocation -+ */ -+struct brcms_bss_cfg { -+ struct brcms_c_info *wlc; -+ bool up; -+ bool enable; -+ bool associated; -+ bool BSS; -+ u8 SSID_len; -+ u8 SSID[IEEE80211_MAX_SSID_LEN]; -+ u8 BSSID[ETH_ALEN]; -+ u8 cur_etheraddr[ETH_ALEN]; -+ struct brcms_bss_info *current_bss; -+}; -+ -+extern void brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, -+ struct sk_buff *p, -+ bool commit, s8 txpktpend); -+extern void brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, -+ s8 txpktpend); -+extern void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb, -+ struct sk_buff *sdu, uint prec); -+extern void brcms_c_print_txstatus(struct tx_status *txs); -+extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, -+ uint *blocks); -+ -+#if defined(BCMDBG) -+extern void brcms_c_print_txdesc(struct d11txh *txh); -+#else -+#define brcms_c_print_txdesc(a) -+#endif -+ -+extern int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config); -+extern void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc, -+ bool promisc); -+extern void brcms_c_send_q(struct brcms_c_info *wlc); -+extern int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu, -+ uint *fifo); -+extern u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, -+ uint mac_len); -+extern u32 brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, -+ u32 rspec, -+ bool use_rspec, u16 mimo_ctlchbw); -+extern u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only, -+ u32 rts_rate, -+ u32 frame_rate, -+ u8 rts_preamble_type, -+ u8 frame_preamble_type, uint frame_len, -+ bool ba); -+extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw, -+ struct ieee80211_sta *sta, -+ void (*dma_callback_fn)); -+extern void brcms_c_update_beacon(struct brcms_c_info *wlc); -+extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend); -+extern int brcms_c_set_nmode(struct brcms_c_info *wlc); -+extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, -+ u32 bcn_rate); -+extern void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, -+ u8 antsel_type); -+extern void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, -+ u16 chanspec, -+ bool mute, struct txpwr_limits *txpwr); -+extern void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, -+ u16 v); -+extern u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset); -+extern void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, -+ u16 val, int bands); -+extern void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags); -+extern void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val); -+extern void brcms_b_phy_reset(struct brcms_hardware *wlc_hw); -+extern void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw); -+extern void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw); -+extern void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw, -+ u32 override_bit); -+extern void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw, -+ u32 override_bit); -+extern void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, -+ int offset, int len, void *buf); -+extern u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate); -+extern void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, -+ uint offset, const void *buf, int len, -+ u32 sel); -+extern void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, -+ void *buf, int len, u32 sel); -+extern void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode); -+extern u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw); -+extern void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk); -+extern void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk); -+extern void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on); -+extern void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant); -+extern void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, -+ u8 stf_mode); -+extern void brcms_c_init_scb(struct scb *scb); -+ -+#endif /* _BRCM_MAIN_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/Makefile.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/Makefile ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/Makefile.orig 2011-11-09 13:46:58.251800557 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/Makefile 2011-11-09 13:47:17.005566104 -0500 -@@ -0,0 +1,51 @@ -+# -+# Makefile fragment for Broadcom 802.11n Networking Device Driver -+# -+# Copyright (c) 2010 Broadcom Corporation -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ -+ccflags-y := \ -+ -D__CHECK_ENDIAN__ \ -+ -Idrivers/net/wireless/brcm80211/brcmsmac \ -+ -Idrivers/net/wireless/brcm80211/brcmsmac/phy \ -+ -Idrivers/net/wireless/brcm80211/include -+ -+BRCMSMAC_OFILES := \ -+ mac80211_if.o \ -+ ucode_loader.o \ -+ ampdu.o \ -+ antsel.o \ -+ channel.o \ -+ main.o \ -+ phy_shim.o \ -+ pmu.o \ -+ rate.o \ -+ stf.o \ -+ aiutils.o \ -+ phy/phy_cmn.o \ -+ phy/phy_lcn.o \ -+ phy/phy_n.o \ -+ phy/phytbl_lcn.o \ -+ phy/phytbl_n.o \ -+ phy/phy_qmath.o \ -+ otp.o \ -+ srom.o \ -+ dma.o \ -+ nicpci.o \ -+ brcms_trace_events.o -+ -+MODULEPFX := brcmsmac -+ -+obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o -+$(MODULEPFX)-objs = $(BRCMSMAC_OFILES) -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c.orig 2011-11-09 13:46:58.252800545 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c 2011-11-09 13:47:17.005566104 -0500 -@@ -0,0 +1,835 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include "aiutils.h" -+#include "pub.h" -+#include "nicpci.h" -+ -+/* SPROM offsets */ -+#define SRSH_ASPM_OFFSET 4 /* word 4 */ -+#define SRSH_ASPM_ENB 0x18 /* bit 3, 4 */ -+#define SRSH_ASPM_L1_ENB 0x10 /* bit 4 */ -+#define SRSH_ASPM_L0s_ENB 0x8 /* bit 3 */ -+ -+#define SRSH_PCIE_MISC_CONFIG 5 /* word 5 */ -+#define SRSH_L23READY_EXIT_NOPERST 0x8000 /* bit 15 */ -+#define SRSH_CLKREQ_OFFSET_REV5 20 /* word 20 for srom rev <= 5 */ -+#define SRSH_CLKREQ_ENB 0x0800 /* bit 11 */ -+#define SRSH_BD_OFFSET 6 /* word 6 */ -+ -+/* chipcontrol */ -+#define CHIPCTRL_4321_PLL_DOWN 0x800000/* serdes PLL down override */ -+ -+/* MDIO control */ -+#define MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */ -+#define MDIOCTL_DIVISOR_VAL 0x2 -+#define MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */ -+#define MDIOCTL_ACCESS_DONE 0x100 /* Transaction complete */ -+ -+/* MDIO Data */ -+#define MDIODATA_MASK 0x0000ffff /* data 2 bytes */ -+#define MDIODATA_TA 0x00020000 /* Turnaround */ -+ -+#define MDIODATA_REGADDR_SHF 18 /* Regaddr shift */ -+#define MDIODATA_REGADDR_MASK 0x007c0000 /* Regaddr Mask */ -+#define MDIODATA_DEVADDR_SHF 23 /* Physmedia devaddr shift */ -+#define MDIODATA_DEVADDR_MASK 0x0f800000 -+ /* Physmedia devaddr Mask */ -+ -+/* MDIO Data for older revisions < 10 */ -+#define MDIODATA_REGADDR_SHF_OLD 18 /* Regaddr shift */ -+#define MDIODATA_REGADDR_MASK_OLD 0x003c0000 -+ /* Regaddr Mask */ -+#define MDIODATA_DEVADDR_SHF_OLD 22 /* Physmedia devaddr shift */ -+#define MDIODATA_DEVADDR_MASK_OLD 0x0fc00000 -+ /* Physmedia devaddr Mask */ -+ -+/* Transactions flags */ -+#define MDIODATA_WRITE 0x10000000 -+#define MDIODATA_READ 0x20000000 -+#define MDIODATA_START 0x40000000 -+ -+#define MDIODATA_DEV_ADDR 0x0 /* dev address for serdes */ -+#define MDIODATA_BLK_ADDR 0x1F /* blk address for serdes */ -+ -+/* serdes regs (rev < 10) */ -+#define MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */ -+#define MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */ -+#define MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */ -+ -+/* SERDES RX registers */ -+#define SERDES_RX_CTRL 1 /* Rx cntrl */ -+#define SERDES_RX_TIMER1 2 /* Rx Timer1 */ -+#define SERDES_RX_CDR 6 /* CDR */ -+#define SERDES_RX_CDRBW 7 /* CDR BW */ -+/* SERDES RX control register */ -+#define SERDES_RX_CTRL_FORCE 0x80 /* rxpolarity_force */ -+#define SERDES_RX_CTRL_POLARITY 0x40 /* rxpolarity_value */ -+ -+/* SERDES PLL registers */ -+#define SERDES_PLL_CTRL 1 /* PLL control reg */ -+#define PLL_CTRL_FREQDET_EN 0x4000 /* bit 14 is FREQDET on */ -+ -+/* Linkcontrol reg offset in PCIE Cap */ -+#define PCIE_CAP_LINKCTRL_OFFSET 16 /* offset in pcie cap */ -+#define PCIE_CAP_LCREG_ASPML0s 0x01 /* ASPM L0s in linkctrl */ -+#define PCIE_CAP_LCREG_ASPML1 0x02 /* ASPM L1 in linkctrl */ -+#define PCIE_CLKREQ_ENAB 0x100 /* CLKREQ Enab in linkctrl */ -+ -+#define PCIE_ASPM_ENAB 3 /* ASPM L0s & L1 in linkctrl */ -+#define PCIE_ASPM_L1_ENAB 2 /* ASPM L0s & L1 in linkctrl */ -+#define PCIE_ASPM_L0s_ENAB 1 /* ASPM L0s & L1 in linkctrl */ -+#define PCIE_ASPM_DISAB 0 /* ASPM L0s & L1 in linkctrl */ -+ -+/* Power management threshold */ -+#define PCIE_L1THRESHOLDTIME_MASK 0xFF00 /* bits 8 - 15 */ -+#define PCIE_L1THRESHOLDTIME_SHIFT 8 /* PCIE_L1THRESHOLDTIME_SHIFT */ -+#define PCIE_L1THRESHOLD_WARVAL 0x72 /* WAR value */ -+#define PCIE_ASPMTIMER_EXTEND 0x01000000 -+ /* > rev7: -+ * enable extend ASPM timer -+ */ -+ -+/* different register spaces to access thru pcie indirect access */ -+#define PCIE_CONFIGREGS 1 /* Access to config space */ -+#define PCIE_PCIEREGS 2 /* Access to pcie registers */ -+ -+/* PCIE protocol PHY diagnostic registers */ -+#define PCIE_PLP_STATUSREG 0x204 /* Status */ -+ -+/* Status reg PCIE_PLP_STATUSREG */ -+#define PCIE_PLP_POLARITYINV_STAT 0x10 -+ -+/* PCIE protocol DLLP diagnostic registers */ -+#define PCIE_DLLP_LCREG 0x100 /* Link Control */ -+#define PCIE_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold */ -+ -+/* PCIE protocol TLP diagnostic registers */ -+#define PCIE_TLP_WORKAROUNDSREG 0x004 /* TLP Workarounds */ -+ -+/* Sonics to PCI translation types */ -+#define SBTOPCI_PREF 0x4 /* prefetch enable */ -+#define SBTOPCI_BURST 0x8 /* burst enable */ -+#define SBTOPCI_RC_READMULTI 0x20 /* memory read multiple */ -+ -+#define PCI_CLKRUN_DSBL 0x8000 /* Bit 15 forceClkrun */ -+ -+/* PCI core index in SROM shadow area */ -+#define SRSH_PI_OFFSET 0 /* first word */ -+#define SRSH_PI_MASK 0xf000 /* bit 15:12 */ -+#define SRSH_PI_SHIFT 12 /* bit 15:12 */ -+ -+/* Sonics side: PCI core and host control registers */ -+struct sbpciregs { -+ u32 control; /* PCI control */ -+ u32 PAD[3]; -+ u32 arbcontrol; /* PCI arbiter control */ -+ u32 clkrun; /* Clkrun Control (>=rev11) */ -+ u32 PAD[2]; -+ u32 intstatus; /* Interrupt status */ -+ u32 intmask; /* Interrupt mask */ -+ u32 sbtopcimailbox; /* Sonics to PCI mailbox */ -+ u32 PAD[9]; -+ u32 bcastaddr; /* Sonics broadcast address */ -+ u32 bcastdata; /* Sonics broadcast data */ -+ u32 PAD[2]; -+ u32 gpioin; /* ro: gpio input (>=rev2) */ -+ u32 gpioout; /* rw: gpio output (>=rev2) */ -+ u32 gpioouten; /* rw: gpio output enable (>= rev2) */ -+ u32 gpiocontrol; /* rw: gpio control (>= rev2) */ -+ u32 PAD[36]; -+ u32 sbtopci0; /* Sonics to PCI translation 0 */ -+ u32 sbtopci1; /* Sonics to PCI translation 1 */ -+ u32 sbtopci2; /* Sonics to PCI translation 2 */ -+ u32 PAD[189]; -+ u32 pcicfg[4][64]; /* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */ -+ u16 sprom[36]; /* SPROM shadow Area */ -+ u32 PAD[46]; -+}; -+ -+/* SB side: PCIE core and host control registers */ -+struct sbpcieregs { -+ u32 control; /* host mode only */ -+ u32 PAD[2]; -+ u32 biststatus; /* bist Status: 0x00C */ -+ u32 gpiosel; /* PCIE gpio sel: 0x010 */ -+ u32 gpioouten; /* PCIE gpio outen: 0x14 */ -+ u32 PAD[2]; -+ u32 intstatus; /* Interrupt status: 0x20 */ -+ u32 intmask; /* Interrupt mask: 0x24 */ -+ u32 sbtopcimailbox; /* sb to pcie mailbox: 0x028 */ -+ u32 PAD[53]; -+ u32 sbtopcie0; /* sb to pcie translation 0: 0x100 */ -+ u32 sbtopcie1; /* sb to pcie translation 1: 0x104 */ -+ u32 sbtopcie2; /* sb to pcie translation 2: 0x108 */ -+ u32 PAD[5]; -+ -+ /* pcie core supports in direct access to config space */ -+ u32 configaddr; /* pcie config space access: Address field: 0x120 */ -+ u32 configdata; /* pcie config space access: Data field: 0x124 */ -+ -+ /* mdio access to serdes */ -+ u32 mdiocontrol; /* controls the mdio access: 0x128 */ -+ u32 mdiodata; /* Data to the mdio access: 0x12c */ -+ -+ /* pcie protocol phy/dllp/tlp register indirect access mechanism */ -+ u32 pcieindaddr; /* indirect access to -+ * the internal register: 0x130 -+ */ -+ u32 pcieinddata; /* Data to/from the internal regsiter: 0x134 */ -+ -+ u32 clkreqenctrl; /* >= rev 6, Clkreq rdma control : 0x138 */ -+ u32 PAD[177]; -+ u32 pciecfg[4][64]; /* 0x400 - 0x7FF, PCIE Cfg Space */ -+ u16 sprom[64]; /* SPROM shadow Area */ -+}; -+ -+struct pcicore_info { -+ union { -+ struct sbpcieregs __iomem *pcieregs; -+ struct sbpciregs __iomem *pciregs; -+ } regs; /* Memory mapped register to the core */ -+ -+ struct si_pub *sih; /* System interconnect handle */ -+ struct pci_dev *dev; -+ u8 pciecap_lcreg_offset;/* PCIE capability LCreg offset -+ * in the config space -+ */ -+ bool pcie_pr42767; -+ u8 pcie_polarity; -+ u8 pcie_war_aspm_ovr; /* Override ASPM/Clkreq settings */ -+ -+ u8 pmecap_offset; /* PM Capability offset in the config space */ -+ bool pmecap; /* Capable of generating PME */ -+}; -+ -+#define PCIE_ASPM(sih) \ -+ (((sih)->buscoretype == PCIE_CORE_ID) && \ -+ (((sih)->buscorerev >= 3) && \ -+ ((sih)->buscorerev <= 5))) -+ -+ -+/* delay needed between the mdio control/ mdiodata register data access */ -+static void pr28829_delay(void) -+{ -+ udelay(10); -+} -+ -+/* Initialize the PCI core. -+ * It's caller's responsibility to make sure that this is done only once -+ */ -+struct pcicore_info *pcicore_init(struct si_pub *sih, struct pci_dev *pdev, -+ void __iomem *regs) -+{ -+ struct pcicore_info *pi; -+ -+ /* alloc struct pcicore_info */ -+ pi = kzalloc(sizeof(struct pcicore_info), GFP_ATOMIC); -+ if (pi == NULL) -+ return NULL; -+ -+ pi->sih = sih; -+ pi->dev = pdev; -+ -+ if (sih->buscoretype == PCIE_CORE_ID) { -+ u8 cap_ptr; -+ pi->regs.pcieregs = regs; -+ cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP, -+ NULL, NULL); -+ pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET; -+ } else -+ pi->regs.pciregs = regs; -+ -+ return pi; -+} -+ -+void pcicore_deinit(struct pcicore_info *pch) -+{ -+ kfree(pch); -+} -+ -+/* return cap_offset if requested capability exists in the PCI config space */ -+/* Note that it's caller's responsibility to make sure it's a pci bus */ -+u8 -+pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id, -+ unsigned char *buf, u32 *buflen) -+{ -+ u8 cap_id; -+ u8 cap_ptr = 0; -+ u32 bufsize; -+ u8 byte_val; -+ -+ /* check for Header type 0 */ -+ pci_read_config_byte(dev, PCI_HEADER_TYPE, &byte_val); -+ if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL) -+ goto end; -+ -+ /* check if the capability pointer field exists */ -+ pci_read_config_byte(dev, PCI_STATUS, &byte_val); -+ if (!(byte_val & PCI_STATUS_CAP_LIST)) -+ goto end; -+ -+ pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &cap_ptr); -+ /* check if the capability pointer is 0x00 */ -+ if (cap_ptr == 0x00) -+ goto end; -+ -+ /* loop thru the capability list -+ * and see if the pcie capability exists -+ */ -+ -+ pci_read_config_byte(dev, cap_ptr, &cap_id); -+ -+ while (cap_id != req_cap_id) { -+ pci_read_config_byte(dev, cap_ptr + 1, &cap_ptr); -+ if (cap_ptr == 0x00) -+ break; -+ pci_read_config_byte(dev, cap_ptr, &cap_id); -+ } -+ if (cap_id != req_cap_id) -+ goto end; -+ -+ /* found the caller requested capability */ -+ if (buf != NULL && buflen != NULL) { -+ u8 cap_data; -+ -+ bufsize = *buflen; -+ if (!bufsize) -+ goto end; -+ *buflen = 0; -+ /* copy the capability data excluding cap ID and next ptr */ -+ cap_data = cap_ptr + 2; -+ if ((bufsize + cap_data) > PCI_SZPCR) -+ bufsize = PCI_SZPCR - cap_data; -+ *buflen = bufsize; -+ while (bufsize--) { -+ pci_read_config_byte(dev, cap_data, buf); -+ cap_data++; -+ buf++; -+ } -+ } -+end: -+ return cap_ptr; -+} -+ -+/* ***** Register Access API */ -+static uint -+pcie_readreg(struct sbpcieregs __iomem *pcieregs, uint addrtype, uint offset) -+{ -+ uint retval = 0xFFFFFFFF; -+ -+ switch (addrtype) { -+ case PCIE_CONFIGREGS: -+ W_REG(&pcieregs->configaddr, offset); -+ (void)R_REG((&pcieregs->configaddr)); -+ retval = R_REG(&pcieregs->configdata); -+ break; -+ case PCIE_PCIEREGS: -+ W_REG(&pcieregs->pcieindaddr, offset); -+ (void)R_REG(&pcieregs->pcieindaddr); -+ retval = R_REG(&pcieregs->pcieinddata); -+ break; -+ } -+ -+ return retval; -+} -+ -+static uint pcie_writereg(struct sbpcieregs __iomem *pcieregs, uint addrtype, -+ uint offset, uint val) -+{ -+ switch (addrtype) { -+ case PCIE_CONFIGREGS: -+ W_REG((&pcieregs->configaddr), offset); -+ W_REG((&pcieregs->configdata), val); -+ break; -+ case PCIE_PCIEREGS: -+ W_REG((&pcieregs->pcieindaddr), offset); -+ W_REG((&pcieregs->pcieinddata), val); -+ break; -+ default: -+ break; -+ } -+ return 0; -+} -+ -+static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk) -+{ -+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; -+ uint mdiodata, i = 0; -+ uint pcie_serdes_spinwait = 200; -+ -+ mdiodata = (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | -+ (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | -+ (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) | -+ (blk << 4)); -+ W_REG(&pcieregs->mdiodata, mdiodata); -+ -+ pr28829_delay(); -+ /* retry till the transaction is complete */ -+ while (i < pcie_serdes_spinwait) { -+ if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) -+ break; -+ -+ udelay(1000); -+ i++; -+ } -+ -+ if (i >= pcie_serdes_spinwait) -+ return false; -+ -+ return true; -+} -+ -+static int -+pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write, -+ uint *val) -+{ -+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; -+ uint mdiodata; -+ uint i = 0; -+ uint pcie_serdes_spinwait = 10; -+ -+ /* enable mdio access to SERDES */ -+ W_REG(&pcieregs->mdiocontrol, MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); -+ -+ if (pi->sih->buscorerev >= 10) { -+ /* new serdes is slower in rw, -+ * using two layers of reg address mapping -+ */ -+ if (!pcie_mdiosetblock(pi, physmedia)) -+ return 1; -+ mdiodata = ((MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | -+ (regaddr << MDIODATA_REGADDR_SHF)); -+ pcie_serdes_spinwait *= 20; -+ } else { -+ mdiodata = ((physmedia << MDIODATA_DEVADDR_SHF_OLD) | -+ (regaddr << MDIODATA_REGADDR_SHF_OLD)); -+ } -+ -+ if (!write) -+ mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA); -+ else -+ mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | -+ *val); -+ -+ W_REG(&pcieregs->mdiodata, mdiodata); -+ -+ pr28829_delay(); -+ -+ /* retry till the transaction is complete */ -+ while (i < pcie_serdes_spinwait) { -+ if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) { -+ if (!write) { -+ pr28829_delay(); -+ *val = (R_REG(&pcieregs->mdiodata) & -+ MDIODATA_MASK); -+ } -+ /* Disable mdio access to SERDES */ -+ W_REG(&pcieregs->mdiocontrol, 0); -+ return 0; -+ } -+ udelay(1000); -+ i++; -+ } -+ -+ /* Timed out. Disable mdio access to SERDES. */ -+ W_REG(&pcieregs->mdiocontrol, 0); -+ return 1; -+} -+ -+/* use the mdio interface to read from mdio slaves */ -+static int -+pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint regaddr, -+ uint *regval) -+{ -+ return pcie_mdioop(pi, physmedia, regaddr, false, regval); -+} -+ -+/* use the mdio interface to write to mdio slaves */ -+static int -+pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint regaddr, uint val) -+{ -+ return pcie_mdioop(pi, physmedia, regaddr, true, &val); -+} -+ -+/* ***** Support functions ***** */ -+static u8 pcie_clkreq(struct pcicore_info *pi, u32 mask, u32 val) -+{ -+ u32 reg_val; -+ u8 offset; -+ -+ offset = pi->pciecap_lcreg_offset; -+ if (!offset) -+ return 0; -+ -+ pci_read_config_dword(pi->dev, offset, ®_val); -+ /* set operation */ -+ if (mask) { -+ if (val) -+ reg_val |= PCIE_CLKREQ_ENAB; -+ else -+ reg_val &= ~PCIE_CLKREQ_ENAB; -+ pci_write_config_dword(pi->dev, offset, reg_val); -+ pci_read_config_dword(pi->dev, offset, ®_val); -+ } -+ if (reg_val & PCIE_CLKREQ_ENAB) -+ return 1; -+ else -+ return 0; -+} -+ -+static void pcie_extendL1timer(struct pcicore_info *pi, bool extend) -+{ -+ u32 w; -+ struct si_pub *sih = pi->sih; -+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; -+ -+ if (sih->buscoretype != PCIE_CORE_ID || sih->buscorerev < 7) -+ return; -+ -+ w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); -+ if (extend) -+ w |= PCIE_ASPMTIMER_EXTEND; -+ else -+ w &= ~PCIE_ASPMTIMER_EXTEND; -+ pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w); -+ w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); -+} -+ -+/* centralized clkreq control policy */ -+static void pcie_clkreq_upd(struct pcicore_info *pi, uint state) -+{ -+ struct si_pub *sih = pi->sih; -+ -+ switch (state) { -+ case SI_DOATTACH: -+ if (PCIE_ASPM(sih)) -+ pcie_clkreq(pi, 1, 0); -+ break; -+ case SI_PCIDOWN: -+ if (sih->buscorerev == 6) { /* turn on serdes PLL down */ -+ ai_corereg(sih, SI_CC_IDX, -+ offsetof(struct chipcregs, chipcontrol_addr), -+ ~0, 0); -+ ai_corereg(sih, SI_CC_IDX, -+ offsetof(struct chipcregs, chipcontrol_data), -+ ~0x40, 0); -+ } else if (pi->pcie_pr42767) { -+ pcie_clkreq(pi, 1, 1); -+ } -+ break; -+ case SI_PCIUP: -+ if (sih->buscorerev == 6) { /* turn off serdes PLL down */ -+ ai_corereg(sih, SI_CC_IDX, -+ offsetof(struct chipcregs, chipcontrol_addr), -+ ~0, 0); -+ ai_corereg(sih, SI_CC_IDX, -+ offsetof(struct chipcregs, chipcontrol_data), -+ ~0x40, 0x40); -+ } else if (PCIE_ASPM(sih)) { /* disable clkreq */ -+ pcie_clkreq(pi, 1, 0); -+ } -+ break; -+ } -+} -+ -+/* ***** PCI core WARs ***** */ -+/* Done only once at attach time */ -+static void pcie_war_polarity(struct pcicore_info *pi) -+{ -+ u32 w; -+ -+ if (pi->pcie_polarity != 0) -+ return; -+ -+ w = pcie_readreg(pi->regs.pcieregs, PCIE_PCIEREGS, PCIE_PLP_STATUSREG); -+ -+ /* Detect the current polarity at attach and force that polarity and -+ * disable changing the polarity -+ */ -+ if ((w & PCIE_PLP_POLARITYINV_STAT) == 0) -+ pi->pcie_polarity = SERDES_RX_CTRL_FORCE; -+ else -+ pi->pcie_polarity = (SERDES_RX_CTRL_FORCE | -+ SERDES_RX_CTRL_POLARITY); -+} -+ -+/* enable ASPM and CLKREQ if srom doesn't have it */ -+/* Needs to happen when update to shadow SROM is needed -+ * : Coming out of 'standby'/'hibernate' -+ * : If pcie_war_aspm_ovr state changed -+ */ -+static void pcie_war_aspm_clkreq(struct pcicore_info *pi) -+{ -+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; -+ struct si_pub *sih = pi->sih; -+ u16 val16; -+ u16 __iomem *reg16; -+ u32 w; -+ -+ if (!PCIE_ASPM(sih)) -+ return; -+ -+ /* bypass this on QT or VSIM */ -+ reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET]; -+ val16 = R_REG(reg16); -+ -+ val16 &= ~SRSH_ASPM_ENB; -+ if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB) -+ val16 |= SRSH_ASPM_ENB; -+ else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L1_ENAB) -+ val16 |= SRSH_ASPM_L1_ENB; -+ else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB) -+ val16 |= SRSH_ASPM_L0s_ENB; -+ -+ W_REG(reg16, val16); -+ -+ pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w); -+ w &= ~PCIE_ASPM_ENAB; -+ w |= pi->pcie_war_aspm_ovr; -+ pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w); -+ -+ reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET_REV5]; -+ val16 = R_REG(reg16); -+ -+ if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) { -+ val16 |= SRSH_CLKREQ_ENB; -+ pi->pcie_pr42767 = true; -+ } else -+ val16 &= ~SRSH_CLKREQ_ENB; -+ -+ W_REG(reg16, val16); -+} -+ -+/* Apply the polarity determined at the start */ -+/* Needs to happen when coming out of 'standby'/'hibernate' */ -+static void pcie_war_serdes(struct pcicore_info *pi) -+{ -+ u32 w = 0; -+ -+ if (pi->pcie_polarity != 0) -+ pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CTRL, -+ pi->pcie_polarity); -+ -+ pcie_mdioread(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w); -+ if (w & PLL_CTRL_FREQDET_EN) { -+ w &= ~PLL_CTRL_FREQDET_EN; -+ pcie_mdiowrite(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w); -+ } -+} -+ -+/* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */ -+/* Needs to happen when coming out of 'standby'/'hibernate' */ -+static void pcie_misc_config_fixup(struct pcicore_info *pi) -+{ -+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; -+ u16 val16; -+ u16 __iomem *reg16; -+ -+ reg16 = &pcieregs->sprom[SRSH_PCIE_MISC_CONFIG]; -+ val16 = R_REG(reg16); -+ -+ if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) { -+ val16 |= SRSH_L23READY_EXIT_NOPERST; -+ W_REG(reg16, val16); -+ } -+} -+ -+/* quick hack for testing */ -+/* Needs to happen when coming out of 'standby'/'hibernate' */ -+static void pcie_war_noplldown(struct pcicore_info *pi) -+{ -+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; -+ u16 __iomem *reg16; -+ -+ /* turn off serdes PLL down */ -+ ai_corereg(pi->sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol), -+ CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN); -+ -+ /* clear srom shadow backdoor */ -+ reg16 = &pcieregs->sprom[SRSH_BD_OFFSET]; -+ W_REG(reg16, 0); -+} -+ -+/* Needs to happen when coming out of 'standby'/'hibernate' */ -+static void pcie_war_pci_setup(struct pcicore_info *pi) -+{ -+ struct si_pub *sih = pi->sih; -+ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; -+ u32 w; -+ -+ if (sih->buscorerev == 0 || sih->buscorerev == 1) { -+ w = pcie_readreg(pcieregs, PCIE_PCIEREGS, -+ PCIE_TLP_WORKAROUNDSREG); -+ w |= 0x8; -+ pcie_writereg(pcieregs, PCIE_PCIEREGS, -+ PCIE_TLP_WORKAROUNDSREG, w); -+ } -+ -+ if (sih->buscorerev == 1) { -+ w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG); -+ w |= 0x40; -+ pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w); -+ } -+ -+ if (sih->buscorerev == 0) { -+ pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128); -+ pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100); -+ pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466); -+ } else if (PCIE_ASPM(sih)) { -+ /* Change the L1 threshold for better performance */ -+ w = pcie_readreg(pcieregs, PCIE_PCIEREGS, -+ PCIE_DLLP_PMTHRESHREG); -+ w &= ~PCIE_L1THRESHOLDTIME_MASK; -+ w |= PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT; -+ pcie_writereg(pcieregs, PCIE_PCIEREGS, -+ PCIE_DLLP_PMTHRESHREG, w); -+ -+ pcie_war_serdes(pi); -+ -+ pcie_war_aspm_clkreq(pi); -+ } else if (pi->sih->buscorerev == 7) -+ pcie_war_noplldown(pi); -+ -+ /* Note that the fix is actually in the SROM, -+ * that's why this is open-ended -+ */ -+ if (pi->sih->buscorerev >= 6) -+ pcie_misc_config_fixup(pi); -+} -+ -+/* ***** Functions called during driver state changes ***** */ -+void pcicore_attach(struct pcicore_info *pi, int state) -+{ -+ struct si_pub *sih = pi->sih; -+ u32 bfl2 = (u32)getintvar(sih, BRCMS_SROM_BOARDFLAGS2); -+ -+ /* Determine if this board needs override */ -+ if (PCIE_ASPM(sih)) { -+ if (bfl2 & BFL2_PCIEWAR_OVR) -+ pi->pcie_war_aspm_ovr = PCIE_ASPM_DISAB; -+ else -+ pi->pcie_war_aspm_ovr = PCIE_ASPM_ENAB; -+ } -+ -+ /* These need to happen in this order only */ -+ pcie_war_polarity(pi); -+ -+ pcie_war_serdes(pi); -+ -+ pcie_war_aspm_clkreq(pi); -+ -+ pcie_clkreq_upd(pi, state); -+ -+} -+ -+void pcicore_hwup(struct pcicore_info *pi) -+{ -+ if (!pi || pi->sih->buscoretype != PCIE_CORE_ID) -+ return; -+ -+ pcie_war_pci_setup(pi); -+} -+ -+void pcicore_up(struct pcicore_info *pi, int state) -+{ -+ if (!pi || pi->sih->buscoretype != PCIE_CORE_ID) -+ return; -+ -+ /* Restore L1 timer for better performance */ -+ pcie_extendL1timer(pi, true); -+ -+ pcie_clkreq_upd(pi, state); -+} -+ -+/* When the device is going to enter D3 state -+ * (or the system is going to enter S3/S4 states) -+ */ -+void pcicore_sleep(struct pcicore_info *pi) -+{ -+ u32 w; -+ -+ if (!pi || !PCIE_ASPM(pi->sih)) -+ return; -+ -+ pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w); -+ w &= ~PCIE_CAP_LCREG_ASPML1; -+ pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w); -+ -+ pi->pcie_pr42767 = false; -+} -+ -+void pcicore_down(struct pcicore_info *pi, int state) -+{ -+ if (!pi || pi->sih->buscoretype != PCIE_CORE_ID) -+ return; -+ -+ pcie_clkreq_upd(pi, state); -+ -+ /* Reduce L1 timer for better power savings */ -+ pcie_extendL1timer(pi, false); -+} -+ -+/* precondition: current core is sii->buscoretype */ -+static void pcicore_fixcfg(struct pcicore_info *pi, u16 __iomem *reg16) -+{ -+ struct si_info *sii = (struct si_info *)(pi->sih); -+ u16 val16; -+ uint pciidx; -+ -+ pciidx = ai_coreidx(&sii->pub); -+ val16 = R_REG(reg16); -+ if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16)pciidx) { -+ val16 = (u16)(pciidx << SRSH_PI_SHIFT) | -+ (val16 & ~SRSH_PI_MASK); -+ W_REG(reg16, val16); -+ } -+} -+ -+void -+pcicore_fixcfg_pci(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs) -+{ -+ pcicore_fixcfg(pi, &pciregs->sprom[SRSH_PI_OFFSET]); -+} -+ -+void pcicore_fixcfg_pcie(struct pcicore_info *pi, -+ struct sbpcieregs __iomem *pcieregs) -+{ -+ pcicore_fixcfg(pi, &pcieregs->sprom[SRSH_PI_OFFSET]); -+} -+ -+/* precondition: current core is pci core */ -+void -+pcicore_pci_setup(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs) -+{ -+ u32 w; -+ -+ OR_REG(&pciregs->sbtopci2, SBTOPCI_PREF | SBTOPCI_BURST); -+ -+ if (((struct si_info *)(pi->sih))->pub.buscorerev >= 11) { -+ OR_REG(&pciregs->sbtopci2, SBTOPCI_RC_READMULTI); -+ w = R_REG(&pciregs->clkrun); -+ W_REG(&pciregs->clkrun, w | PCI_CLKRUN_DSBL); -+ w = R_REG(&pciregs->clkrun); -+ } -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h.orig 2011-11-09 13:46:58.252800545 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h 2011-11-09 13:47:17.005566104 -0500 -@@ -0,0 +1,82 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_NICPCI_H_ -+#define _BRCM_NICPCI_H_ -+ -+#include "types.h" -+ -+/* PCI configuration address space size */ -+#define PCI_SZPCR 256 -+ -+/* Brcm PCI configuration registers */ -+/* backplane address space accessed by BAR0 */ -+#define PCI_BAR0_WIN 0x80 -+/* sprom property control */ -+#define PCI_SPROM_CONTROL 0x88 -+/* mask of PCI and other cores interrupts */ -+#define PCI_INT_MASK 0x94 -+/* backplane core interrupt mask bits offset */ -+#define PCI_SBIM_SHIFT 8 -+/* backplane address space accessed by second 4KB of BAR0 */ -+#define PCI_BAR0_WIN2 0xac -+/* pci config space gpio input (>=rev3) */ -+#define PCI_GPIO_IN 0xb0 -+/* pci config space gpio output (>=rev3) */ -+#define PCI_GPIO_OUT 0xb4 -+/* pci config space gpio output enable (>=rev3) */ -+#define PCI_GPIO_OUTEN 0xb8 -+ -+/* bar0 + 4K accesses external sprom */ -+#define PCI_BAR0_SPROM_OFFSET (4 * 1024) -+/* bar0 + 6K accesses pci core registers */ -+#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) -+/* -+ * pci core SB registers are at the end of the -+ * 8KB window, so their address is the "regular" -+ * address plus 4K -+ */ -+#define PCI_BAR0_PCISBR_OFFSET (4 * 1024) -+/* bar0 window size Match with corerev 13 */ -+#define PCI_BAR0_WINSZ (16 * 1024) -+/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */ -+/* bar0 + 8K accesses pci/pcie core registers */ -+#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024) -+/* bar0 + 12K accesses chipc core registers */ -+#define PCI_16KB0_CCREGS_OFFSET (12 * 1024) -+ -+struct sbpciregs; -+struct sbpcieregs; -+ -+extern struct pcicore_info *pcicore_init(struct si_pub *sih, -+ struct pci_dev *pdev, -+ void __iomem *regs); -+extern void pcicore_deinit(struct pcicore_info *pch); -+extern void pcicore_attach(struct pcicore_info *pch, int state); -+extern void pcicore_hwup(struct pcicore_info *pch); -+extern void pcicore_up(struct pcicore_info *pch, int state); -+extern void pcicore_sleep(struct pcicore_info *pch); -+extern void pcicore_down(struct pcicore_info *pch, int state); -+extern u8 pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id, -+ unsigned char *buf, u32 *buflen); -+extern void pcicore_fixcfg_pci(struct pcicore_info *pch, -+ struct sbpciregs __iomem *pciregs); -+extern void pcicore_fixcfg_pcie(struct pcicore_info *pch, -+ struct sbpcieregs __iomem *pciregs); -+extern void pcicore_pci_setup(struct pcicore_info *pch, -+ struct sbpciregs __iomem *pciregs); -+ -+#endif /* _BRCM_NICPCI_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.c.orig 2011-11-09 13:46:58.252800545 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.c 2011-11-09 13:47:17.006566092 -0500 -@@ -0,0 +1,426 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include "aiutils.h" -+#include "otp.h" -+ -+#define OTPS_GUP_MASK 0x00000f00 -+#define OTPS_GUP_SHIFT 8 -+/* h/w subregion is programmed */ -+#define OTPS_GUP_HW 0x00000100 -+/* s/w subregion is programmed */ -+#define OTPS_GUP_SW 0x00000200 -+/* chipid/pkgopt subregion is programmed */ -+#define OTPS_GUP_CI 0x00000400 -+/* fuse subregion is programmed */ -+#define OTPS_GUP_FUSE 0x00000800 -+ -+/* Fields in otpprog in rev >= 21 */ -+#define OTPP_COL_MASK 0x000000ff -+#define OTPP_COL_SHIFT 0 -+#define OTPP_ROW_MASK 0x0000ff00 -+#define OTPP_ROW_SHIFT 8 -+#define OTPP_OC_MASK 0x0f000000 -+#define OTPP_OC_SHIFT 24 -+#define OTPP_READERR 0x10000000 -+#define OTPP_VALUE_MASK 0x20000000 -+#define OTPP_VALUE_SHIFT 29 -+#define OTPP_START_BUSY 0x80000000 -+#define OTPP_READ 0x40000000 -+ -+/* Opcodes for OTPP_OC field */ -+#define OTPPOC_READ 0 -+#define OTPPOC_BIT_PROG 1 -+#define OTPPOC_VERIFY 3 -+#define OTPPOC_INIT 4 -+#define OTPPOC_SET 5 -+#define OTPPOC_RESET 6 -+#define OTPPOC_OCST 7 -+#define OTPPOC_ROW_LOCK 8 -+#define OTPPOC_PRESCN_TEST 9 -+ -+#define OTPTYPE_IPX(ccrev) ((ccrev) == 21 || (ccrev) >= 23) -+ -+#define OTPP_TRIES 10000000 /* # of tries for OTPP */ -+ -+#define MAXNUMRDES 9 /* Maximum OTP redundancy entries */ -+ -+/* Fixed size subregions sizes in words */ -+#define OTPGU_CI_SZ 2 -+ -+struct otpinfo; -+ -+/* OTP function struct */ -+struct otp_fn_s { -+ int (*init)(struct si_pub *sih, struct otpinfo *oi); -+ int (*read_region)(struct otpinfo *oi, int region, u16 *data, -+ uint *wlen); -+}; -+ -+struct otpinfo { -+ uint ccrev; /* chipc revision */ -+ const struct otp_fn_s *fn; /* OTP functions */ -+ struct si_pub *sih; /* Saved sb handle */ -+ -+ /* IPX OTP section */ -+ u16 wsize; /* Size of otp in words */ -+ u16 rows; /* Geometry */ -+ u16 cols; /* Geometry */ -+ u32 status; /* Flag bits (lock/prog/rv). -+ * (Reflected only when OTP is power cycled) -+ */ -+ u16 hwbase; /* hardware subregion offset */ -+ u16 hwlim; /* hardware subregion boundary */ -+ u16 swbase; /* software subregion offset */ -+ u16 swlim; /* software subregion boundary */ -+ u16 fbase; /* fuse subregion offset */ -+ u16 flim; /* fuse subregion boundary */ -+ int otpgu_base; /* offset to General Use Region */ -+}; -+ -+/* OTP layout */ -+/* CC revs 21, 24 and 27 OTP General Use Region word offset */ -+#define REVA4_OTPGU_BASE 12 -+ -+/* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */ -+#define REVB8_OTPGU_BASE 20 -+ -+/* CC rev 36 OTP General Use Region word offset */ -+#define REV36_OTPGU_BASE 12 -+ -+/* Subregion word offsets in General Use region */ -+#define OTPGU_HSB_OFF 0 -+#define OTPGU_SFB_OFF 1 -+#define OTPGU_CI_OFF 2 -+#define OTPGU_P_OFF 3 -+#define OTPGU_SROM_OFF 4 -+ -+/* Flag bit offsets in General Use region */ -+#define OTPGU_HWP_OFF 60 -+#define OTPGU_SWP_OFF 61 -+#define OTPGU_CIP_OFF 62 -+#define OTPGU_FUSEP_OFF 63 -+#define OTPGU_CIP_MSK 0x4000 -+#define OTPGU_P_MSK 0xf000 -+#define OTPGU_P_SHIFT (OTPGU_HWP_OFF % 16) -+ -+/* OTP Size */ -+#define OTP_SZ_FU_324 ((roundup(324, 8))/8) /* 324 bits */ -+#define OTP_SZ_FU_288 (288/8) /* 288 bits */ -+#define OTP_SZ_FU_216 (216/8) /* 216 bits */ -+#define OTP_SZ_FU_72 (72/8) /* 72 bits */ -+#define OTP_SZ_CHECKSUM (16/8) /* 16 bits */ -+#define OTP4315_SWREG_SZ 178 /* 178 bytes */ -+#define OTP_SZ_FU_144 (144/8) /* 144 bits */ -+ -+static u16 -+ipxotp_otpr(struct otpinfo *oi, struct chipcregs __iomem *cc, uint wn) -+{ -+ return R_REG(&cc->sromotp[wn]); -+} -+ -+/* -+ * Calculate max HW/SW region byte size by subtracting fuse region -+ * and checksum size, osizew is oi->wsize (OTP size - GU size) in words -+ */ -+static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew) -+{ -+ int ret = 0; -+ -+ switch (sih->chip) { -+ case BCM43224_CHIP_ID: -+ case BCM43225_CHIP_ID: -+ ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM; -+ break; -+ case BCM4313_CHIP_ID: -+ ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM; -+ break; -+ default: -+ break; /* Don't know about this chip */ -+ } -+ -+ return ret; -+} -+ -+static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc) -+{ -+ uint k; -+ u32 otpp, st; -+ -+ /* -+ * record word offset of General Use Region -+ * for various chipcommon revs -+ */ -+ if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24 -+ || oi->sih->ccrev == 27) { -+ oi->otpgu_base = REVA4_OTPGU_BASE; -+ } else if (oi->sih->ccrev == 36) { -+ /* -+ * OTP size greater than equal to 2KB (128 words), -+ * otpgu_base is similar to rev23 -+ */ -+ if (oi->wsize >= 128) -+ oi->otpgu_base = REVB8_OTPGU_BASE; -+ else -+ oi->otpgu_base = REV36_OTPGU_BASE; -+ } else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) { -+ oi->otpgu_base = REVB8_OTPGU_BASE; -+ } -+ -+ /* First issue an init command so the status is up to date */ -+ otpp = -+ OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK); -+ -+ W_REG(&cc->otpprog, otpp); -+ for (k = 0; -+ ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY) -+ && (k < OTPP_TRIES); k++) -+ ; -+ if (k >= OTPP_TRIES) -+ return; -+ -+ /* Read OTP lock bits and subregion programmed indication bits */ -+ oi->status = R_REG(&cc->otpstatus); -+ -+ if ((oi->sih->chip == BCM43224_CHIP_ID) -+ || (oi->sih->chip == BCM43225_CHIP_ID)) { -+ u32 p_bits; -+ p_bits = -+ (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) & -+ OTPGU_P_MSK) -+ >> OTPGU_P_SHIFT; -+ oi->status |= (p_bits << OTPS_GUP_SHIFT); -+ } -+ -+ /* -+ * h/w region base and fuse region limit are fixed to -+ * the top and the bottom of the general use region. -+ * Everything else can be flexible. -+ */ -+ oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF; -+ oi->hwlim = oi->wsize; -+ if (oi->status & OTPS_GUP_HW) { -+ oi->hwlim = -+ ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16; -+ oi->swbase = oi->hwlim; -+ } else -+ oi->swbase = oi->hwbase; -+ -+ /* subtract fuse and checksum from beginning */ -+ oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2; -+ -+ if (oi->status & OTPS_GUP_SW) { -+ oi->swlim = -+ ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16; -+ oi->fbase = oi->swlim; -+ } else -+ oi->fbase = oi->swbase; -+ -+ oi->flim = oi->wsize; -+} -+ -+static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi) -+{ -+ uint idx; -+ struct chipcregs __iomem *cc; -+ -+ /* Make sure we're running IPX OTP */ -+ if (!OTPTYPE_IPX(sih->ccrev)) -+ return -EBADE; -+ -+ /* Make sure OTP is not disabled */ -+ if (ai_is_otp_disabled(sih)) -+ return -EBADE; -+ -+ /* Check for otp size */ -+ switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) { -+ case 0: -+ /* Nothing there */ -+ return -EBADE; -+ case 1: /* 32x64 */ -+ oi->rows = 32; -+ oi->cols = 64; -+ oi->wsize = 128; -+ break; -+ case 2: /* 64x64 */ -+ oi->rows = 64; -+ oi->cols = 64; -+ oi->wsize = 256; -+ break; -+ case 5: /* 96x64 */ -+ oi->rows = 96; -+ oi->cols = 64; -+ oi->wsize = 384; -+ break; -+ case 7: /* 16x64 *//* 1024 bits */ -+ oi->rows = 16; -+ oi->cols = 64; -+ oi->wsize = 64; -+ break; -+ default: -+ /* Don't know the geometry */ -+ return -EBADE; -+ } -+ -+ /* Retrieve OTP region info */ -+ idx = ai_coreidx(sih); -+ cc = ai_setcoreidx(sih, SI_CC_IDX); -+ -+ _ipxotp_init(oi, cc); -+ -+ ai_setcoreidx(sih, idx); -+ -+ return 0; -+} -+ -+static int -+ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen) -+{ -+ uint idx; -+ struct chipcregs __iomem *cc; -+ uint base, i, sz; -+ -+ /* Validate region selection */ -+ switch (region) { -+ case OTP_HW_RGN: -+ sz = (uint) oi->hwlim - oi->hwbase; -+ if (!(oi->status & OTPS_GUP_HW)) { -+ *wlen = sz; -+ return -ENODATA; -+ } -+ if (*wlen < sz) { -+ *wlen = sz; -+ return -EOVERFLOW; -+ } -+ base = oi->hwbase; -+ break; -+ case OTP_SW_RGN: -+ sz = ((uint) oi->swlim - oi->swbase); -+ if (!(oi->status & OTPS_GUP_SW)) { -+ *wlen = sz; -+ return -ENODATA; -+ } -+ if (*wlen < sz) { -+ *wlen = sz; -+ return -EOVERFLOW; -+ } -+ base = oi->swbase; -+ break; -+ case OTP_CI_RGN: -+ sz = OTPGU_CI_SZ; -+ if (!(oi->status & OTPS_GUP_CI)) { -+ *wlen = sz; -+ return -ENODATA; -+ } -+ if (*wlen < sz) { -+ *wlen = sz; -+ return -EOVERFLOW; -+ } -+ base = oi->otpgu_base + OTPGU_CI_OFF; -+ break; -+ case OTP_FUSE_RGN: -+ sz = (uint) oi->flim - oi->fbase; -+ if (!(oi->status & OTPS_GUP_FUSE)) { -+ *wlen = sz; -+ return -ENODATA; -+ } -+ if (*wlen < sz) { -+ *wlen = sz; -+ return -EOVERFLOW; -+ } -+ base = oi->fbase; -+ break; -+ case OTP_ALL_RGN: -+ sz = ((uint) oi->flim - oi->hwbase); -+ if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) { -+ *wlen = sz; -+ return -ENODATA; -+ } -+ if (*wlen < sz) { -+ *wlen = sz; -+ return -EOVERFLOW; -+ } -+ base = oi->hwbase; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ idx = ai_coreidx(oi->sih); -+ cc = ai_setcoreidx(oi->sih, SI_CC_IDX); -+ -+ /* Read the data */ -+ for (i = 0; i < sz; i++) -+ data[i] = ipxotp_otpr(oi, cc, base + i); -+ -+ ai_setcoreidx(oi->sih, idx); -+ *wlen = sz; -+ return 0; -+} -+ -+static const struct otp_fn_s ipxotp_fn = { -+ (int (*)(struct si_pub *, struct otpinfo *)) ipxotp_init, -+ (int (*)(struct otpinfo *, int, u16 *, uint *)) ipxotp_read_region, -+}; -+ -+static int otp_init(struct si_pub *sih, struct otpinfo *oi) -+{ -+ -+ int ret; -+ -+ memset(oi, 0, sizeof(struct otpinfo)); -+ -+ oi->ccrev = sih->ccrev; -+ -+ if (OTPTYPE_IPX(oi->ccrev)) -+ oi->fn = &ipxotp_fn; -+ -+ if (oi->fn == NULL) -+ return -EBADE; -+ -+ oi->sih = sih; -+ -+ ret = (oi->fn->init) (sih, oi); -+ -+ return ret; -+} -+ -+int -+otp_read_region(struct si_pub *sih, int region, u16 *data, uint *wlen) { -+ struct otpinfo otpinfo; -+ struct otpinfo *oi = &otpinfo; -+ int err = 0; -+ -+ if (ai_is_otp_disabled(sih)) { -+ err = -EPERM; -+ goto out; -+ } -+ -+ err = otp_init(sih, oi); -+ if (err) -+ goto out; -+ -+ err = ((oi)->fn->read_region)(oi, region, data, wlen); -+ -+ out: -+ return err; -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.h.orig 2011-11-09 13:46:58.252800545 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.h 2011-11-09 13:47:17.006566092 -0500 -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_OTP_H_ -+#define _BRCM_OTP_H_ -+ -+#include "types.h" -+ -+/* OTP regions */ -+#define OTP_HW_RGN 1 -+#define OTP_SW_RGN 2 -+#define OTP_CI_RGN 4 -+#define OTP_FUSE_RGN 8 -+/* From h/w region to end of OTP including checksum */ -+#define OTP_ALL_RGN 0xf -+ -+/* OTP Size */ -+#define OTP_SZ_MAX (6144/8) /* maximum bytes in one CIS */ -+ -+extern int otp_read_region(struct si_pub *sih, int region, u16 *data, -+ uint *wlen); -+ -+#endif /* _BRCM_OTP_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c.orig 2011-11-09 13:46:58.254800521 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c 2011-11-09 13:47:17.008566067 -0500 -@@ -0,0 +1,2988 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include "phy_hal.h" -+#include "phy_int.h" -+#include "phy_radio.h" -+#include "phy_lcn.h" -+#include "phyreg_n.h" -+ -+#define VALID_N_RADIO(radioid) ((radioid == BCM2055_ID) || \ -+ (radioid == BCM2056_ID) || \ -+ (radioid == BCM2057_ID)) -+ -+#define VALID_LCN_RADIO(radioid) (radioid == BCM2064_ID) -+ -+#define VALID_RADIO(pi, radioid) ( \ -+ (ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \ -+ (ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false)) -+ -+/* basic mux operation - can be optimized on several architectures */ -+#define MUX(pred, true, false) ((pred) ? (true) : (false)) -+ -+/* modulo inc/dec - assumes x E [0, bound - 1] */ -+#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1) -+ -+/* modulo inc/dec, bound = 2^k */ -+#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1)) -+#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1)) -+ -+struct chan_info_basic { -+ u16 chan; -+ u16 freq; -+}; -+ -+static const struct chan_info_basic chan_info_all[] = { -+ {1, 2412}, -+ {2, 2417}, -+ {3, 2422}, -+ {4, 2427}, -+ {5, 2432}, -+ {6, 2437}, -+ {7, 2442}, -+ {8, 2447}, -+ {9, 2452}, -+ {10, 2457}, -+ {11, 2462}, -+ {12, 2467}, -+ {13, 2472}, -+ {14, 2484}, -+ -+ {34, 5170}, -+ {38, 5190}, -+ {42, 5210}, -+ {46, 5230}, -+ -+ {36, 5180}, -+ {40, 5200}, -+ {44, 5220}, -+ {48, 5240}, -+ {52, 5260}, -+ {56, 5280}, -+ {60, 5300}, -+ {64, 5320}, -+ -+ {100, 5500}, -+ {104, 5520}, -+ {108, 5540}, -+ {112, 5560}, -+ {116, 5580}, -+ {120, 5600}, -+ {124, 5620}, -+ {128, 5640}, -+ {132, 5660}, -+ {136, 5680}, -+ {140, 5700}, -+ -+ {149, 5745}, -+ {153, 5765}, -+ {157, 5785}, -+ {161, 5805}, -+ {165, 5825}, -+ -+ {184, 4920}, -+ {188, 4940}, -+ {192, 4960}, -+ {196, 4980}, -+ {200, 5000}, -+ {204, 5020}, -+ {208, 5040}, -+ {212, 5060}, -+ {216, 50800} -+}; -+ -+const u8 ofdm_rate_lookup[] = { -+ -+ BRCM_RATE_48M, -+ BRCM_RATE_24M, -+ BRCM_RATE_12M, -+ BRCM_RATE_6M, -+ BRCM_RATE_54M, -+ BRCM_RATE_36M, -+ BRCM_RATE_18M, -+ BRCM_RATE_9M -+}; -+ -+#define PHY_WREG_LIMIT 24 -+ -+void wlc_phyreg_enter(struct brcms_phy_pub *pih) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ wlapi_bmac_ucode_wake_override_phyreg_set(pi->sh->physhim); -+} -+ -+void wlc_phyreg_exit(struct brcms_phy_pub *pih) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ wlapi_bmac_ucode_wake_override_phyreg_clear(pi->sh->physhim); -+} -+ -+void wlc_radioreg_enter(struct brcms_phy_pub *pih) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, MCTL_LOCK_RADIO); -+ -+ udelay(10); -+} -+ -+void wlc_radioreg_exit(struct brcms_phy_pub *pih) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ u16 dummy; -+ -+ dummy = R_REG(&pi->regs->phyversion); -+ pi->phy_wreg = 0; -+ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, 0); -+} -+ -+u16 read_radio_reg(struct brcms_phy *pi, u16 addr) -+{ -+ u16 data; -+ -+ if ((addr == RADIO_IDCODE)) -+ return 0xffff; -+ -+ switch (pi->pubpi.phy_type) { -+ case PHY_TYPE_N: -+ if (!CONF_HAS(PHYTYPE, PHY_TYPE_N)) -+ break; -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ addr |= RADIO_2057_READ_OFF; -+ else -+ addr |= RADIO_2055_READ_OFF; -+ break; -+ -+ case PHY_TYPE_LCN: -+ if (!CONF_HAS(PHYTYPE, PHY_TYPE_LCN)) -+ break; -+ addr |= RADIO_2064_READ_OFF; -+ break; -+ -+ default: -+ break; -+ } -+ -+ if ((D11REV_GE(pi->sh->corerev, 24)) || -+ (D11REV_IS(pi->sh->corerev, 22) -+ && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { -+ W_REG_FLUSH(&pi->regs->radioregaddr, addr); -+ data = R_REG(&pi->regs->radioregdata); -+ } else { -+ W_REG_FLUSH(&pi->regs->phy4waddr, addr); -+ -+#ifdef __ARM_ARCH_4T__ -+ __asm__(" .align 4 "); -+ __asm__(" nop "); -+ data = R_REG(&pi->regs->phy4wdatalo); -+#else -+ data = R_REG(&pi->regs->phy4wdatalo); -+#endif -+ -+ } -+ pi->phy_wreg = 0; -+ -+ return data; -+} -+ -+void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) -+{ -+ if ((D11REV_GE(pi->sh->corerev, 24)) || -+ (D11REV_IS(pi->sh->corerev, 22) -+ && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { -+ -+ W_REG_FLUSH(&pi->regs->radioregaddr, addr); -+ W_REG(&pi->regs->radioregdata, val); -+ } else { -+ W_REG_FLUSH(&pi->regs->phy4waddr, addr); -+ W_REG(&pi->regs->phy4wdatalo, val); -+ } -+ -+ if (++pi->phy_wreg >= pi->phy_wreg_limit) { -+ (void)R_REG(&pi->regs->maccontrol); -+ pi->phy_wreg = 0; -+ } -+} -+ -+static u32 read_radio_id(struct brcms_phy *pi) -+{ -+ u32 id; -+ -+ if (D11REV_GE(pi->sh->corerev, 24)) { -+ u32 b0, b1, b2; -+ -+ W_REG_FLUSH(&pi->regs->radioregaddr, 0); -+ b0 = (u32) R_REG(&pi->regs->radioregdata); -+ W_REG_FLUSH(&pi->regs->radioregaddr, 1); -+ b1 = (u32) R_REG(&pi->regs->radioregdata); -+ W_REG_FLUSH(&pi->regs->radioregaddr, 2); -+ b2 = (u32) R_REG(&pi->regs->radioregdata); -+ -+ id = ((b0 & 0xf) << 28) | (((b2 << 8) | b1) << 12) | ((b0 >> 4) -+ & 0xf); -+ } else { -+ W_REG_FLUSH(&pi->regs->phy4waddr, RADIO_IDCODE); -+ id = (u32) R_REG(&pi->regs->phy4wdatalo); -+ id |= (u32) R_REG(&pi->regs->phy4wdatahi) << 16; -+ } -+ pi->phy_wreg = 0; -+ return id; -+} -+ -+void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) -+{ -+ u16 rval; -+ -+ rval = read_radio_reg(pi, addr); -+ write_radio_reg(pi, addr, (rval & val)); -+} -+ -+void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) -+{ -+ u16 rval; -+ -+ rval = read_radio_reg(pi, addr); -+ write_radio_reg(pi, addr, (rval | val)); -+} -+ -+void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask) -+{ -+ u16 rval; -+ -+ rval = read_radio_reg(pi, addr); -+ write_radio_reg(pi, addr, (rval ^ mask)); -+} -+ -+void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val) -+{ -+ u16 rval; -+ -+ rval = read_radio_reg(pi, addr); -+ write_radio_reg(pi, addr, (rval & ~mask) | (val & mask)); -+} -+ -+void write_phy_channel_reg(struct brcms_phy *pi, uint val) -+{ -+ W_REG(&pi->regs->phychannel, val); -+} -+ -+u16 read_phy_reg(struct brcms_phy *pi, u16 addr) -+{ -+ struct d11regs __iomem *regs; -+ -+ regs = pi->regs; -+ -+ W_REG_FLUSH(®s->phyregaddr, addr); -+ -+ pi->phy_wreg = 0; -+ return R_REG(®s->phyregdata); -+} -+ -+void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) -+{ -+ struct d11regs __iomem *regs; -+ -+ regs = pi->regs; -+ -+#ifdef CONFIG_BCM47XX -+ W_REG_FLUSH(®s->phyregaddr, addr); -+ W_REG(®s->phyregdata, val); -+ if (addr == 0x72) -+ (void)R_REG(®s->phyregdata); -+#else -+ W_REG((u32 __iomem *)(®s->phyregaddr), addr | (val << 16)); -+ if (++pi->phy_wreg >= pi->phy_wreg_limit) { -+ pi->phy_wreg = 0; -+ (void)R_REG(®s->phyversion); -+ } -+#endif -+} -+ -+void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) -+{ -+ struct d11regs __iomem *regs; -+ -+ regs = pi->regs; -+ -+ W_REG_FLUSH(®s->phyregaddr, addr); -+ -+ W_REG(®s->phyregdata, (R_REG(®s->phyregdata) & val)); -+ pi->phy_wreg = 0; -+} -+ -+void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) -+{ -+ struct d11regs __iomem *regs; -+ -+ regs = pi->regs; -+ -+ W_REG_FLUSH(®s->phyregaddr, addr); -+ -+ W_REG(®s->phyregdata, (R_REG(®s->phyregdata) | val)); -+ pi->phy_wreg = 0; -+} -+ -+void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val) -+{ -+ struct d11regs __iomem *regs; -+ -+ regs = pi->regs; -+ -+ W_REG_FLUSH(®s->phyregaddr, addr); -+ -+ W_REG(®s->phyregdata, -+ ((R_REG(®s->phyregdata) & ~mask) | (val & mask))); -+ pi->phy_wreg = 0; -+} -+ -+static void wlc_set_phy_uninitted(struct brcms_phy *pi) -+{ -+ int i, j; -+ -+ pi->initialized = false; -+ -+ pi->tx_vos = 0xffff; -+ pi->nrssi_table_delta = 0x7fffffff; -+ pi->rc_cal = 0xffff; -+ pi->mintxbias = 0xffff; -+ pi->txpwridx = -1; -+ if (ISNPHY(pi)) { -+ pi->phy_spuravoid = SPURAVOID_DISABLE; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3) -+ && NREV_LT(pi->pubpi.phy_rev, 7)) -+ pi->phy_spuravoid = SPURAVOID_AUTO; -+ -+ pi->nphy_papd_skip = 0; -+ pi->nphy_papd_epsilon_offset[0] = 0xf588; -+ pi->nphy_papd_epsilon_offset[1] = 0xf588; -+ pi->nphy_txpwr_idx[0] = 128; -+ pi->nphy_txpwr_idx[1] = 128; -+ pi->nphy_txpwrindex[0].index_internal = 40; -+ pi->nphy_txpwrindex[1].index_internal = 40; -+ pi->phy_pabias = 0; -+ } else { -+ pi->phy_spuravoid = SPURAVOID_AUTO; -+ } -+ pi->radiopwr = 0xffff; -+ for (i = 0; i < STATIC_NUM_RF; i++) { -+ for (j = 0; j < STATIC_NUM_BB; j++) -+ pi->stats_11b_txpower[i][j] = -1; -+ } -+} -+ -+struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp) -+{ -+ struct shared_phy *sh; -+ -+ sh = kzalloc(sizeof(struct shared_phy), GFP_ATOMIC); -+ if (sh == NULL) -+ return NULL; -+ -+ sh->sih = shp->sih; -+ sh->physhim = shp->physhim; -+ sh->unit = shp->unit; -+ sh->corerev = shp->corerev; -+ -+ sh->vid = shp->vid; -+ sh->did = shp->did; -+ sh->chip = shp->chip; -+ sh->chiprev = shp->chiprev; -+ sh->chippkg = shp->chippkg; -+ sh->sromrev = shp->sromrev; -+ sh->boardtype = shp->boardtype; -+ sh->boardrev = shp->boardrev; -+ sh->boardvendor = shp->boardvendor; -+ sh->boardflags = shp->boardflags; -+ sh->boardflags2 = shp->boardflags2; -+ sh->buscorerev = shp->buscorerev; -+ -+ sh->fast_timer = PHY_SW_TIMER_FAST; -+ sh->slow_timer = PHY_SW_TIMER_SLOW; -+ sh->glacial_timer = PHY_SW_TIMER_GLACIAL; -+ -+ sh->rssi_mode = RSSI_ANT_MERGE_MAX; -+ -+ return sh; -+} -+ -+static void wlc_phy_timercb_phycal(struct brcms_phy *pi) -+{ -+ uint delay = 5; -+ -+ if (PHY_PERICAL_MPHASE_PENDING(pi)) { -+ if (!pi->sh->up) { -+ wlc_phy_cal_perical_mphase_reset(pi); -+ return; -+ } -+ -+ if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)) { -+ -+ delay = 1000; -+ wlc_phy_cal_perical_mphase_restart(pi); -+ } else -+ wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO); -+ wlapi_add_timer(pi->phycal_timer, delay, 0); -+ return; -+ } -+ -+} -+ -+static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi) -+{ -+ u32 ver; -+ -+ ver = read_radio_id(pi); -+ -+ return ver; -+} -+ -+struct brcms_phy_pub * -+wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs, -+ int bandtype, struct wiphy *wiphy) -+{ -+ struct brcms_phy *pi; -+ u32 sflags = 0; -+ uint phyversion; -+ u32 idcode; -+ int i; -+ -+ if (D11REV_IS(sh->corerev, 4)) -+ sflags = SISF_2G_PHY | SISF_5G_PHY; -+ else -+ sflags = ai_core_sflags(sh->sih, 0, 0); -+ -+ if (bandtype == BRCM_BAND_5G) { -+ if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0) -+ return NULL; -+ } -+ -+ pi = sh->phy_head; -+ if ((sflags & SISF_DB_PHY) && pi) { -+ wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags); -+ pi->refcnt++; -+ return &pi->pubpi_ro; -+ } -+ -+ pi = kzalloc(sizeof(struct brcms_phy), GFP_ATOMIC); -+ if (pi == NULL) -+ return NULL; -+ pi->wiphy = wiphy; -+ pi->regs = regs; -+ pi->sh = sh; -+ pi->phy_init_por = true; -+ pi->phy_wreg_limit = PHY_WREG_LIMIT; -+ -+ pi->txpwr_percent = 100; -+ -+ pi->do_initcal = true; -+ -+ pi->phycal_tempdelta = 0; -+ -+ if (bandtype == BRCM_BAND_2G && (sflags & SISF_2G_PHY)) -+ pi->pubpi.coreflags = SICF_GMODE; -+ -+ wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags); -+ phyversion = R_REG(&pi->regs->phyversion); -+ -+ pi->pubpi.phy_type = PHY_TYPE(phyversion); -+ pi->pubpi.phy_rev = phyversion & PV_PV_MASK; -+ -+ if (pi->pubpi.phy_type == PHY_TYPE_LCNXN) { -+ pi->pubpi.phy_type = PHY_TYPE_N; -+ pi->pubpi.phy_rev += LCNXN_BASEREV; -+ } -+ pi->pubpi.phy_corenum = PHY_CORE_NUM_2; -+ pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT; -+ -+ if (!pi->pubpi.phy_type == PHY_TYPE_N && -+ !pi->pubpi.phy_type == PHY_TYPE_LCN) -+ goto err; -+ -+ if (bandtype == BRCM_BAND_5G) { -+ if (!ISNPHY(pi)) -+ goto err; -+ } else if (!ISNPHY(pi) && !ISLCNPHY(pi)) { -+ goto err; -+ } -+ -+ wlc_phy_anacore((struct brcms_phy_pub *) pi, ON); -+ -+ idcode = wlc_phy_get_radio_ver(pi); -+ pi->pubpi.radioid = -+ (idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT; -+ pi->pubpi.radiorev = -+ (idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT; -+ pi->pubpi.radiover = -+ (idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT; -+ if (!VALID_RADIO(pi, pi->pubpi.radioid)) -+ goto err; -+ -+ wlc_phy_switch_radio((struct brcms_phy_pub *) pi, OFF); -+ -+ wlc_set_phy_uninitted(pi); -+ -+ pi->bw = WL_CHANSPEC_BW_20; -+ pi->radio_chanspec = (bandtype == BRCM_BAND_2G) ? -+ ch20mhz_chspec(1) : ch20mhz_chspec(36); -+ -+ pi->rxiq_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY; -+ pi->rxiq_antsel = ANT_RX_DIV_DEF; -+ -+ pi->watchdog_override = true; -+ -+ pi->cal_type_override = PHY_PERICAL_AUTO; -+ -+ pi->nphy_saved_noisevars.bufcount = 0; -+ -+ if (ISNPHY(pi)) -+ pi->min_txpower = PHY_TXPWR_MIN_NPHY; -+ else -+ pi->min_txpower = PHY_TXPWR_MIN; -+ -+ pi->sh->phyrxchain = 0x3; -+ -+ pi->rx2tx_biasentry = -1; -+ -+ pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP; -+ pi->phy_txcore_enable_temp = -+ PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP; -+ pi->phy_tempsense_offset = 0; -+ pi->phy_txcore_heatedup = false; -+ -+ pi->nphy_lastcal_temp = -50; -+ -+ pi->phynoise_polling = true; -+ if (ISNPHY(pi) || ISLCNPHY(pi)) -+ pi->phynoise_polling = false; -+ -+ for (i = 0; i < TXP_NUM_RATES; i++) { -+ pi->txpwr_limit[i] = BRCMS_TXPWR_MAX; -+ pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX; -+ pi->tx_user_target[i] = BRCMS_TXPWR_MAX; -+ } -+ -+ pi->radiopwr_override = RADIOPWR_OVERRIDE_DEF; -+ -+ pi->user_txpwr_at_rfport = false; -+ -+ if (ISNPHY(pi)) { -+ -+ pi->phycal_timer = wlapi_init_timer(pi->sh->physhim, -+ wlc_phy_timercb_phycal, -+ pi, "phycal"); -+ if (!pi->phycal_timer) -+ goto err; -+ -+ if (!wlc_phy_attach_nphy(pi)) -+ goto err; -+ -+ } else if (ISLCNPHY(pi)) { -+ if (!wlc_phy_attach_lcnphy(pi)) -+ goto err; -+ -+ } -+ -+ pi->refcnt++; -+ pi->next = pi->sh->phy_head; -+ sh->phy_head = pi; -+ -+ memcpy(&pi->pubpi_ro, &pi->pubpi, sizeof(struct brcms_phy_pub)); -+ -+ return &pi->pubpi_ro; -+ -+err: -+ kfree(pi); -+ return NULL; -+} -+ -+void wlc_phy_detach(struct brcms_phy_pub *pih) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ if (pih) { -+ if (--pi->refcnt) -+ return; -+ -+ if (pi->phycal_timer) { -+ wlapi_free_timer(pi->phycal_timer); -+ pi->phycal_timer = NULL; -+ } -+ -+ if (pi->sh->phy_head == pi) -+ pi->sh->phy_head = pi->next; -+ else if (pi->sh->phy_head->next == pi) -+ pi->sh->phy_head->next = NULL; -+ -+ if (pi->pi_fptr.detach) -+ (pi->pi_fptr.detach)(pi); -+ -+ kfree(pi); -+ } -+} -+ -+bool -+wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype, u16 *phyrev, -+ u16 *radioid, u16 *radiover) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ *phytype = (u16) pi->pubpi.phy_type; -+ *phyrev = (u16) pi->pubpi.phy_rev; -+ *radioid = pi->pubpi.radioid; -+ *radiover = pi->pubpi.radiorev; -+ -+ return true; -+} -+ -+bool wlc_phy_get_encore(struct brcms_phy_pub *pih) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ return pi->pubpi.abgphy_encore; -+} -+ -+u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ return pi->pubpi.coreflags; -+} -+ -+void wlc_phy_anacore(struct brcms_phy_pub *pih, bool on) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ if (ISNPHY(pi)) { -+ if (on) { -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ write_phy_reg(pi, 0xa6, 0x0d); -+ write_phy_reg(pi, 0x8f, 0x0); -+ write_phy_reg(pi, 0xa7, 0x0d); -+ write_phy_reg(pi, 0xa5, 0x0); -+ } else { -+ write_phy_reg(pi, 0xa5, 0x0); -+ } -+ } else { -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ write_phy_reg(pi, 0x8f, 0x07ff); -+ write_phy_reg(pi, 0xa6, 0x0fd); -+ write_phy_reg(pi, 0xa5, 0x07ff); -+ write_phy_reg(pi, 0xa7, 0x0fd); -+ } else { -+ write_phy_reg(pi, 0xa5, 0x7fff); -+ } -+ } -+ } else if (ISLCNPHY(pi)) { -+ if (on) { -+ and_phy_reg(pi, 0x43b, -+ ~((0x1 << 0) | (0x1 << 1) | (0x1 << 2))); -+ } else { -+ or_phy_reg(pi, 0x43c, -+ (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); -+ or_phy_reg(pi, 0x43b, -+ (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); -+ } -+ } -+} -+ -+u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ u32 phy_bw_clkbits = 0; -+ -+ if (pi && (ISNPHY(pi) || ISLCNPHY(pi))) { -+ switch (pi->bw) { -+ case WL_CHANSPEC_BW_10: -+ phy_bw_clkbits = SICF_BW10; -+ break; -+ case WL_CHANSPEC_BW_20: -+ phy_bw_clkbits = SICF_BW20; -+ break; -+ case WL_CHANSPEC_BW_40: -+ phy_bw_clkbits = SICF_BW40; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ return phy_bw_clkbits; -+} -+ -+void wlc_phy_por_inform(struct brcms_phy_pub *ppi) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ pi->phy_init_por = true; -+} -+ -+void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ pi->edcrs_threshold_lock = lock; -+ -+ write_phy_reg(pi, 0x22c, 0x46b); -+ write_phy_reg(pi, 0x22d, 0x46b); -+ write_phy_reg(pi, 0x22e, 0x3c0); -+ write_phy_reg(pi, 0x22f, 0x3c0); -+} -+ -+void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ pi->do_initcal = initcal; -+} -+ -+void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *pih, bool newstate) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ if (!pi || !pi->sh) -+ return; -+ -+ pi->sh->clk = newstate; -+} -+ -+void wlc_phy_hw_state_upd(struct brcms_phy_pub *pih, bool newstate) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ if (!pi || !pi->sh) -+ return; -+ -+ pi->sh->up = newstate; -+} -+ -+void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec) -+{ -+ u32 mc; -+ void (*phy_init)(struct brcms_phy *) = NULL; -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ if (pi->init_in_progress) -+ return; -+ -+ pi->init_in_progress = true; -+ -+ pi->radio_chanspec = chanspec; -+ -+ mc = R_REG(&pi->regs->maccontrol); -+ if (WARN(mc & MCTL_EN_MAC, "HW error MAC running on init")) -+ return; -+ -+ if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) -+ pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC; -+ -+ if (WARN(!(ai_core_sflags(pi->sh->sih, 0, 0) & SISF_FCLKA), -+ "HW error SISF_FCLKA\n")) -+ return; -+ -+ phy_init = pi->pi_fptr.init; -+ -+ if (phy_init == NULL) -+ return; -+ -+ wlc_phy_anacore(pih, ON); -+ -+ if (CHSPEC_BW(pi->radio_chanspec) != pi->bw) -+ wlapi_bmac_bw_set(pi->sh->physhim, -+ CHSPEC_BW(pi->radio_chanspec)); -+ -+ pi->nphy_gain_boost = true; -+ -+ wlc_phy_switch_radio((struct brcms_phy_pub *) pi, ON); -+ -+ (*phy_init)(pi); -+ -+ pi->phy_init_por = false; -+ -+ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) -+ wlc_phy_do_dummy_tx(pi, true, OFF); -+ -+ if (!(ISNPHY(pi))) -+ wlc_phy_txpower_update_shm(pi); -+ -+ wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, pi->sh->rx_antdiv); -+ -+ pi->init_in_progress = false; -+} -+ -+void wlc_phy_cal_init(struct brcms_phy_pub *pih) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ void (*cal_init)(struct brcms_phy *) = NULL; -+ -+ if (WARN((R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) != 0, -+ "HW error: MAC enabled during phy cal\n")) -+ return; -+ -+ if (!pi->initialized) { -+ cal_init = pi->pi_fptr.calinit; -+ if (cal_init) -+ (*cal_init)(pi); -+ -+ pi->initialized = true; -+ } -+} -+ -+int wlc_phy_down(struct brcms_phy_pub *pih) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ int callbacks = 0; -+ -+ if (pi->phycal_timer -+ && !wlapi_del_timer(pi->phycal_timer)) -+ callbacks++; -+ -+ pi->nphy_iqcal_chanspec_2G = 0; -+ pi->nphy_iqcal_chanspec_5G = 0; -+ -+ return callbacks; -+} -+ -+void -+wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset, -+ u16 tblAddr, u16 tblDataHi, u16 tblDataLo) -+{ -+ write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset); -+ -+ pi->tbl_data_hi = tblDataHi; -+ pi->tbl_data_lo = tblDataLo; -+ -+ if (pi->sh->chip == BCM43224_CHIP_ID && -+ pi->sh->chiprev == 1) { -+ pi->tbl_addr = tblAddr; -+ pi->tbl_save_id = tbl_id; -+ pi->tbl_save_offset = tbl_offset; -+ } -+} -+ -+void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val) -+{ -+ if ((pi->sh->chip == BCM43224_CHIP_ID) && -+ (pi->sh->chiprev == 1) && -+ (pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) { -+ read_phy_reg(pi, pi->tbl_data_lo); -+ -+ write_phy_reg(pi, pi->tbl_addr, -+ (pi->tbl_save_id << 10) | pi->tbl_save_offset); -+ pi->tbl_save_offset++; -+ } -+ -+ if (width == 32) { -+ write_phy_reg(pi, pi->tbl_data_hi, (u16) (val >> 16)); -+ write_phy_reg(pi, pi->tbl_data_lo, (u16) val); -+ } else { -+ write_phy_reg(pi, pi->tbl_data_lo, (u16) val); -+ } -+} -+ -+void -+wlc_phy_write_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info, -+ u16 tblAddr, u16 tblDataHi, u16 tblDataLo) -+{ -+ uint idx; -+ uint tbl_id = ptbl_info->tbl_id; -+ uint tbl_offset = ptbl_info->tbl_offset; -+ uint tbl_width = ptbl_info->tbl_width; -+ const u8 *ptbl_8b = (const u8 *)ptbl_info->tbl_ptr; -+ const u16 *ptbl_16b = (const u16 *)ptbl_info->tbl_ptr; -+ const u32 *ptbl_32b = (const u32 *)ptbl_info->tbl_ptr; -+ -+ write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset); -+ -+ for (idx = 0; idx < ptbl_info->tbl_len; idx++) { -+ -+ if ((pi->sh->chip == BCM43224_CHIP_ID) && -+ (pi->sh->chiprev == 1) && -+ (tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) { -+ read_phy_reg(pi, tblDataLo); -+ -+ write_phy_reg(pi, tblAddr, -+ (tbl_id << 10) | (tbl_offset + idx)); -+ } -+ -+ if (tbl_width == 32) { -+ write_phy_reg(pi, tblDataHi, -+ (u16) (ptbl_32b[idx] >> 16)); -+ write_phy_reg(pi, tblDataLo, (u16) ptbl_32b[idx]); -+ } else if (tbl_width == 16) { -+ write_phy_reg(pi, tblDataLo, ptbl_16b[idx]); -+ } else { -+ write_phy_reg(pi, tblDataLo, ptbl_8b[idx]); -+ } -+ } -+} -+ -+void -+wlc_phy_read_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info, -+ u16 tblAddr, u16 tblDataHi, u16 tblDataLo) -+{ -+ uint idx; -+ uint tbl_id = ptbl_info->tbl_id; -+ uint tbl_offset = ptbl_info->tbl_offset; -+ uint tbl_width = ptbl_info->tbl_width; -+ u8 *ptbl_8b = (u8 *)ptbl_info->tbl_ptr; -+ u16 *ptbl_16b = (u16 *)ptbl_info->tbl_ptr; -+ u32 *ptbl_32b = (u32 *)ptbl_info->tbl_ptr; -+ -+ write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset); -+ -+ for (idx = 0; idx < ptbl_info->tbl_len; idx++) { -+ -+ if ((pi->sh->chip == BCM43224_CHIP_ID) && -+ (pi->sh->chiprev == 1)) { -+ (void)read_phy_reg(pi, tblDataLo); -+ -+ write_phy_reg(pi, tblAddr, -+ (tbl_id << 10) | (tbl_offset + idx)); -+ } -+ -+ if (tbl_width == 32) { -+ ptbl_32b[idx] = read_phy_reg(pi, tblDataLo); -+ ptbl_32b[idx] |= (read_phy_reg(pi, tblDataHi) << 16); -+ } else if (tbl_width == 16) { -+ ptbl_16b[idx] = read_phy_reg(pi, tblDataLo); -+ } else { -+ ptbl_8b[idx] = (u8) read_phy_reg(pi, tblDataLo); -+ } -+ } -+} -+ -+uint -+wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi, -+ struct radio_20xx_regs *radioregs) -+{ -+ uint i = 0; -+ -+ do { -+ if (radioregs[i].do_init) -+ write_radio_reg(pi, radioregs[i].address, -+ (u16) radioregs[i].init); -+ -+ i++; -+ } while (radioregs[i].address != 0xffff); -+ -+ return i; -+} -+ -+uint -+wlc_phy_init_radio_regs(struct brcms_phy *pi, -+ const struct radio_regs *radioregs, -+ u16 core_offset) -+{ -+ uint i = 0; -+ uint count = 0; -+ -+ do { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ if (radioregs[i].do_init_a) { -+ write_radio_reg(pi, -+ radioregs[i]. -+ address | core_offset, -+ (u16) radioregs[i].init_a); -+ if (ISNPHY(pi) && (++count % 4 == 0)) -+ BRCMS_PHY_WAR_PR51571(pi); -+ } -+ } else { -+ if (radioregs[i].do_init_g) { -+ write_radio_reg(pi, -+ radioregs[i]. -+ address | core_offset, -+ (u16) radioregs[i].init_g); -+ if (ISNPHY(pi) && (++count % 4 == 0)) -+ BRCMS_PHY_WAR_PR51571(pi); -+ } -+ } -+ -+ i++; -+ } while (radioregs[i].address != 0xffff); -+ -+ return i; -+} -+ -+void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on) -+{ -+#define DUMMY_PKT_LEN 20 -+ struct d11regs __iomem *regs = pi->regs; -+ int i, count; -+ u8 ofdmpkt[DUMMY_PKT_LEN] = { -+ 0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 -+ }; -+ u8 cckpkt[DUMMY_PKT_LEN] = { -+ 0x6e, 0x84, 0x0b, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 -+ }; -+ u32 *dummypkt; -+ -+ dummypkt = (u32 *) (ofdm ? ofdmpkt : cckpkt); -+ wlapi_bmac_write_template_ram(pi->sh->physhim, 0, DUMMY_PKT_LEN, -+ dummypkt); -+ -+ W_REG(®s->xmtsel, 0); -+ -+ if (D11REV_GE(pi->sh->corerev, 11)) -+ W_REG(®s->wepctl, 0x100); -+ else -+ W_REG(®s->wepctl, 0); -+ -+ W_REG(®s->txe_phyctl, (ofdm ? 1 : 0) | PHY_TXC_ANT_0); -+ if (ISNPHY(pi) || ISLCNPHY(pi)) -+ W_REG(®s->txe_phyctl1, 0x1A02); -+ -+ W_REG(®s->txe_wm_0, 0); -+ W_REG(®s->txe_wm_1, 0); -+ -+ W_REG(®s->xmttplatetxptr, 0); -+ W_REG(®s->xmttxcnt, DUMMY_PKT_LEN); -+ -+ W_REG(®s->xmtsel, ((8 << 8) | (1 << 5) | (1 << 2) | 2)); -+ -+ W_REG(®s->txe_ctl, 0); -+ -+ if (!pa_on) { -+ if (ISNPHY(pi)) -+ wlc_phy_pa_override_nphy(pi, OFF); -+ } -+ -+ if (ISNPHY(pi) || ISLCNPHY(pi)) -+ W_REG(®s->txe_aux, 0xD0); -+ else -+ W_REG(®s->txe_aux, ((1 << 5) | (1 << 4))); -+ -+ (void)R_REG(®s->txe_aux); -+ -+ i = 0; -+ count = ofdm ? 30 : 250; -+ while ((i++ < count) -+ && (R_REG(®s->txe_status) & (1 << 7))) -+ udelay(10); -+ -+ i = 0; -+ -+ while ((i++ < 10) -+ && ((R_REG(®s->txe_status) & (1 << 10)) == 0)) -+ udelay(10); -+ -+ i = 0; -+ -+ while ((i++ < 10) && ((R_REG(®s->ifsstat) & (1 << 8)))) -+ udelay(10); -+ -+ if (!pa_on) { -+ if (ISNPHY(pi)) -+ wlc_phy_pa_override_nphy(pi, ON); -+ } -+} -+ -+void wlc_phy_hold_upd(struct brcms_phy_pub *pih, u32 id, bool set) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ if (set) -+ mboolset(pi->measure_hold, id); -+ else -+ mboolclr(pi->measure_hold, id); -+ -+ return; -+} -+ -+void wlc_phy_mute_upd(struct brcms_phy_pub *pih, bool mute, u32 flags) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ if (mute) -+ mboolset(pi->measure_hold, PHY_HOLD_FOR_MUTE); -+ else -+ mboolclr(pi->measure_hold, PHY_HOLD_FOR_MUTE); -+ -+ if (!mute && (flags & PHY_MUTE_FOR_PREISM)) -+ pi->nphy_perical_last = pi->sh->now - pi->sh->glacial_timer; -+ return; -+} -+ -+void wlc_phy_clear_tssi(struct brcms_phy_pub *pih) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ if (ISNPHY(pi)) { -+ return; -+ } else { -+ wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_0, NULL_TSSI_W); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_1, NULL_TSSI_W); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_0, NULL_TSSI_W); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_1, NULL_TSSI_W); -+ } -+} -+ -+static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi) -+{ -+ return false; -+} -+ -+void wlc_phy_switch_radio(struct brcms_phy_pub *pih, bool on) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ (void)R_REG(&pi->regs->maccontrol); -+ -+ if (ISNPHY(pi)) { -+ wlc_phy_switch_radio_nphy(pi, on); -+ } else if (ISLCNPHY(pi)) { -+ if (on) { -+ and_phy_reg(pi, 0x44c, -+ ~((0x1 << 8) | -+ (0x1 << 9) | -+ (0x1 << 10) | (0x1 << 11) | (0x1 << 12))); -+ and_phy_reg(pi, 0x4b0, ~((0x1 << 3) | (0x1 << 11))); -+ and_phy_reg(pi, 0x4f9, ~(0x1 << 3)); -+ } else { -+ and_phy_reg(pi, 0x44d, -+ ~((0x1 << 10) | -+ (0x1 << 11) | -+ (0x1 << 12) | (0x1 << 13) | (0x1 << 14))); -+ or_phy_reg(pi, 0x44c, -+ (0x1 << 8) | -+ (0x1 << 9) | -+ (0x1 << 10) | (0x1 << 11) | (0x1 << 12)); -+ -+ and_phy_reg(pi, 0x4b7, ~((0x7f << 8))); -+ and_phy_reg(pi, 0x4b1, ~((0x1 << 13))); -+ or_phy_reg(pi, 0x4b0, (0x1 << 3) | (0x1 << 11)); -+ and_phy_reg(pi, 0x4fa, ~((0x1 << 3))); -+ or_phy_reg(pi, 0x4f9, (0x1 << 3)); -+ } -+ } -+} -+ -+u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ return pi->bw; -+} -+ -+void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ pi->bw = bw; -+} -+ -+void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, u16 newch) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ pi->radio_chanspec = newch; -+ -+} -+ -+u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ return pi->radio_chanspec; -+} -+ -+void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, u16 chanspec) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ u16 m_cur_channel; -+ void (*chanspec_set)(struct brcms_phy *, u16) = NULL; -+ m_cur_channel = CHSPEC_CHANNEL(chanspec); -+ if (CHSPEC_IS5G(chanspec)) -+ m_cur_channel |= D11_CURCHANNEL_5G; -+ if (CHSPEC_IS40(chanspec)) -+ m_cur_channel |= D11_CURCHANNEL_40; -+ wlapi_bmac_write_shm(pi->sh->physhim, M_CURCHANNEL, m_cur_channel); -+ -+ chanspec_set = pi->pi_fptr.chanset; -+ if (chanspec_set) -+ (*chanspec_set)(pi, chanspec); -+ -+} -+ -+int wlc_phy_chanspec_freq2bandrange_lpssn(uint freq) -+{ -+ int range = -1; -+ -+ if (freq < 2500) -+ range = WL_CHAN_FREQ_RANGE_2G; -+ else if (freq <= 5320) -+ range = WL_CHAN_FREQ_RANGE_5GL; -+ else if (freq <= 5700) -+ range = WL_CHAN_FREQ_RANGE_5GM; -+ else -+ range = WL_CHAN_FREQ_RANGE_5GH; -+ -+ return range; -+} -+ -+int wlc_phy_chanspec_bandrange_get(struct brcms_phy *pi, u16 chanspec) -+{ -+ int range = -1; -+ uint channel = CHSPEC_CHANNEL(chanspec); -+ uint freq = wlc_phy_channel2freq(channel); -+ -+ if (ISNPHY(pi)) -+ range = wlc_phy_get_chan_freq_range_nphy(pi, channel); -+ else if (ISLCNPHY(pi)) -+ range = wlc_phy_chanspec_freq2bandrange_lpssn(freq); -+ -+ return range; -+} -+ -+void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi, -+ bool wide_filter) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ pi->channel_14_wide_filter = wide_filter; -+ -+} -+ -+int wlc_phy_channel2freq(uint channel) -+{ -+ uint i; -+ -+ for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) -+ if (chan_info_all[i].chan == channel) -+ return chan_info_all[i].freq; -+ return 0; -+} -+ -+void -+wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band, -+ struct brcms_chanvec *channels) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ uint i; -+ uint channel; -+ -+ memset(channels, 0, sizeof(struct brcms_chanvec)); -+ -+ for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) { -+ channel = chan_info_all[i].chan; -+ -+ if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM) -+ && (channel <= LAST_REF5_CHANNUM)) -+ continue; -+ -+ if ((band == BRCM_BAND_2G && channel <= CH_MAX_2G_CHANNEL) || -+ (band == BRCM_BAND_5G && channel > CH_MAX_2G_CHANNEL)) -+ setbit(channels->vec, channel); -+ } -+} -+ -+u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ uint i; -+ uint channel; -+ u16 chspec; -+ -+ for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) { -+ channel = chan_info_all[i].chan; -+ -+ if (ISNPHY(pi) && pi->bw == WL_CHANSPEC_BW_40) { -+ uint j; -+ -+ for (j = 0; j < ARRAY_SIZE(chan_info_all); j++) { -+ if (chan_info_all[j].chan == -+ channel + CH_10MHZ_APART) -+ break; -+ } -+ -+ if (j == ARRAY_SIZE(chan_info_all)) -+ continue; -+ -+ channel = upper_20_sb(channel); -+ chspec = channel | WL_CHANSPEC_BW_40 | -+ WL_CHANSPEC_CTL_SB_LOWER; -+ if (band == BRCM_BAND_2G) -+ chspec |= WL_CHANSPEC_BAND_2G; -+ else -+ chspec |= WL_CHANSPEC_BAND_5G; -+ } else -+ chspec = ch20mhz_chspec(channel); -+ -+ if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM) -+ && (channel <= LAST_REF5_CHANNUM)) -+ continue; -+ -+ if ((band == BRCM_BAND_2G && channel <= CH_MAX_2G_CHANNEL) || -+ (band == BRCM_BAND_5G && channel > CH_MAX_2G_CHANNEL)) -+ return chspec; -+ } -+ -+ return (u16) INVCHANSPEC; -+} -+ -+int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ *qdbm = pi->tx_user_target[0]; -+ if (override != NULL) -+ *override = pi->txpwroverride; -+ return 0; -+} -+ -+void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi, -+ struct txpwr_limits *txpwr) -+{ -+ bool mac_enabled = false; -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ memcpy(&pi->tx_user_target[TXP_FIRST_CCK], -+ &txpwr->cck[0], BRCMS_NUM_RATES_CCK); -+ -+ memcpy(&pi->tx_user_target[TXP_FIRST_OFDM], -+ &txpwr->ofdm[0], BRCMS_NUM_RATES_OFDM); -+ memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_20_CDD], -+ &txpwr->ofdm_cdd[0], BRCMS_NUM_RATES_OFDM); -+ -+ memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_SISO], -+ &txpwr->ofdm_40_siso[0], BRCMS_NUM_RATES_OFDM); -+ memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_CDD], -+ &txpwr->ofdm_40_cdd[0], BRCMS_NUM_RATES_OFDM); -+ -+ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SISO], -+ &txpwr->mcs_20_siso[0], BRCMS_NUM_RATES_MCS_1_STREAM); -+ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_CDD], -+ &txpwr->mcs_20_cdd[0], BRCMS_NUM_RATES_MCS_1_STREAM); -+ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_STBC], -+ &txpwr->mcs_20_stbc[0], BRCMS_NUM_RATES_MCS_1_STREAM); -+ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SDM], -+ &txpwr->mcs_20_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM); -+ -+ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SISO], -+ &txpwr->mcs_40_siso[0], BRCMS_NUM_RATES_MCS_1_STREAM); -+ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_CDD], -+ &txpwr->mcs_40_cdd[0], BRCMS_NUM_RATES_MCS_1_STREAM); -+ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_STBC], -+ &txpwr->mcs_40_stbc[0], BRCMS_NUM_RATES_MCS_1_STREAM); -+ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SDM], -+ &txpwr->mcs_40_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM); -+ -+ if (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) -+ mac_enabled = true; -+ -+ if (mac_enabled) -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ -+ wlc_phy_txpower_recalc_target(pi); -+ wlc_phy_cal_txpower_recalc_sw(pi); -+ -+ if (mac_enabled) -+ wlapi_enable_mac(pi->sh->physhim); -+} -+ -+int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ int i; -+ -+ if (qdbm > 127) -+ return -EINVAL; -+ -+ for (i = 0; i < TXP_NUM_RATES; i++) -+ pi->tx_user_target[i] = (u8) qdbm; -+ -+ pi->txpwroverride = false; -+ -+ if (pi->sh->up) { -+ if (!SCAN_INPROG_PHY(pi)) { -+ bool suspend; -+ -+ suspend = (0 == (R_REG(&pi->regs->maccontrol) & -+ MCTL_EN_MAC)); -+ -+ if (!suspend) -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ -+ wlc_phy_txpower_recalc_target(pi); -+ wlc_phy_cal_txpower_recalc_sw(pi); -+ -+ if (!suspend) -+ wlapi_enable_mac(pi->sh->physhim); -+ } -+ } -+ return 0; -+} -+ -+void -+wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint channel, u8 *min_pwr, -+ u8 *max_pwr, int txp_rate_idx) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ uint i; -+ -+ *min_pwr = pi->min_txpower * BRCMS_TXPWR_DB_FACTOR; -+ -+ if (ISNPHY(pi)) { -+ if (txp_rate_idx < 0) -+ txp_rate_idx = TXP_FIRST_CCK; -+ wlc_phy_txpower_sromlimit_get_nphy(pi, channel, max_pwr, -+ (u8) txp_rate_idx); -+ -+ } else if ((channel <= CH_MAX_2G_CHANNEL)) { -+ if (txp_rate_idx < 0) -+ txp_rate_idx = TXP_FIRST_CCK; -+ *max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx]; -+ } else { -+ -+ *max_pwr = BRCMS_TXPWR_MAX; -+ -+ if (txp_rate_idx < 0) -+ txp_rate_idx = TXP_FIRST_OFDM; -+ -+ for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) { -+ if (channel == chan_info_all[i].chan) -+ break; -+ } -+ -+ if (pi->hwtxpwr) { -+ *max_pwr = pi->hwtxpwr[i]; -+ } else { -+ -+ if ((i >= FIRST_MID_5G_CHAN) && (i <= LAST_MID_5G_CHAN)) -+ *max_pwr = -+ pi->tx_srom_max_rate_5g_mid[txp_rate_idx]; -+ if ((i >= FIRST_HIGH_5G_CHAN) -+ && (i <= LAST_HIGH_5G_CHAN)) -+ *max_pwr = -+ pi->tx_srom_max_rate_5g_hi[txp_rate_idx]; -+ if ((i >= FIRST_LOW_5G_CHAN) && (i <= LAST_LOW_5G_CHAN)) -+ *max_pwr = -+ pi->tx_srom_max_rate_5g_low[txp_rate_idx]; -+ } -+ } -+} -+ -+void -+wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, uint chan, -+ u8 *max_txpwr, u8 *min_txpwr) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ u8 tx_pwr_max = 0; -+ u8 tx_pwr_min = 255; -+ u8 max_num_rate; -+ u8 maxtxpwr, mintxpwr, rate, pactrl; -+ -+ pactrl = 0; -+ -+ max_num_rate = ISNPHY(pi) ? TXP_NUM_RATES : -+ ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 + -+ 1) : (TXP_LAST_OFDM + 1); -+ -+ for (rate = 0; rate < max_num_rate; rate++) { -+ -+ wlc_phy_txpower_sromlimit(ppi, chan, &mintxpwr, &maxtxpwr, -+ rate); -+ -+ maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0; -+ -+ maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0; -+ -+ tx_pwr_max = max(tx_pwr_max, maxtxpwr); -+ tx_pwr_min = min(tx_pwr_min, maxtxpwr); -+ } -+ *max_txpwr = tx_pwr_max; -+ *min_txpwr = tx_pwr_min; -+} -+ -+void -+wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi, uint bandunit, -+ s32 *max_pwr, s32 *min_pwr, u32 *step_pwr) -+{ -+ return; -+} -+ -+u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ return pi->tx_power_min; -+} -+ -+u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ return pi->tx_power_max; -+} -+ -+static s8 wlc_phy_env_measure_vbat(struct brcms_phy *pi) -+{ -+ if (ISLCNPHY(pi)) -+ return wlc_lcnphy_vbatsense(pi, 0); -+ else -+ return 0; -+} -+ -+static s8 wlc_phy_env_measure_temperature(struct brcms_phy *pi) -+{ -+ if (ISLCNPHY(pi)) -+ return wlc_lcnphy_tempsense_degree(pi, 0); -+ else -+ return 0; -+} -+ -+static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy *pi, u32 band) -+{ -+ u8 i; -+ s8 temp, vbat; -+ -+ for (i = 0; i < TXP_NUM_RATES; i++) -+ pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX; -+ -+ vbat = wlc_phy_env_measure_vbat(pi); -+ temp = wlc_phy_env_measure_temperature(pi); -+ -+} -+ -+static s8 -+wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band, -+ u8 rate) -+{ -+ s8 offset = 0; -+ -+ if (!pi->user_txpwr_at_rfport) -+ return offset; -+ return offset; -+} -+ -+void wlc_phy_txpower_recalc_target(struct brcms_phy *pi) -+{ -+ u8 maxtxpwr, mintxpwr, rate, pactrl; -+ uint target_chan; -+ u8 tx_pwr_target[TXP_NUM_RATES]; -+ u8 tx_pwr_max = 0; -+ u8 tx_pwr_min = 255; -+ u8 tx_pwr_max_rate_ind = 0; -+ u8 max_num_rate; -+ u8 start_rate = 0; -+ u16 chspec; -+ u32 band = CHSPEC2BAND(pi->radio_chanspec); -+ void (*txpwr_recalc_fn)(struct brcms_phy *) = NULL; -+ -+ chspec = pi->radio_chanspec; -+ if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) -+ target_chan = CHSPEC_CHANNEL(chspec); -+ else if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) -+ target_chan = upper_20_sb(CHSPEC_CHANNEL(chspec)); -+ else -+ target_chan = lower_20_sb(CHSPEC_CHANNEL(chspec)); -+ -+ pactrl = 0; -+ if (ISLCNPHY(pi)) { -+ u32 offset_mcs, i; -+ -+ if (CHSPEC_IS40(pi->radio_chanspec)) { -+ offset_mcs = pi->mcs40_po; -+ for (i = TXP_FIRST_SISO_MCS_20; -+ i <= TXP_LAST_SISO_MCS_20; i++) { -+ pi->tx_srom_max_rate_2g[i - 8] = -+ pi->tx_srom_max_2g - -+ ((offset_mcs & 0xf) * 2); -+ offset_mcs >>= 4; -+ } -+ } else { -+ offset_mcs = pi->mcs20_po; -+ for (i = TXP_FIRST_SISO_MCS_20; -+ i <= TXP_LAST_SISO_MCS_20; i++) { -+ pi->tx_srom_max_rate_2g[i - 8] = -+ pi->tx_srom_max_2g - -+ ((offset_mcs & 0xf) * 2); -+ offset_mcs >>= 4; -+ } -+ } -+ } -+ -+ max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : -+ ((ISLCNPHY(pi)) ? -+ (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1))); -+ -+ wlc_phy_upd_env_txpwr_rate_limits(pi, band); -+ -+ for (rate = start_rate; rate < max_num_rate; rate++) { -+ -+ tx_pwr_target[rate] = pi->tx_user_target[rate]; -+ -+ if (pi->user_txpwr_at_rfport) -+ tx_pwr_target[rate] += -+ wlc_user_txpwr_antport_to_rfport(pi, -+ target_chan, -+ band, -+ rate); -+ -+ wlc_phy_txpower_sromlimit((struct brcms_phy_pub *) pi, -+ target_chan, -+ &mintxpwr, &maxtxpwr, rate); -+ -+ maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]); -+ -+ maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0; -+ -+ maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0; -+ -+ maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]); -+ -+ if (pi->txpwr_percent <= 100) -+ maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100; -+ -+ tx_pwr_target[rate] = max(maxtxpwr, mintxpwr); -+ -+ tx_pwr_target[rate] = -+ min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]); -+ -+ if (tx_pwr_target[rate] > tx_pwr_max) -+ tx_pwr_max_rate_ind = rate; -+ -+ tx_pwr_max = max(tx_pwr_max, tx_pwr_target[rate]); -+ tx_pwr_min = min(tx_pwr_min, tx_pwr_target[rate]); -+ } -+ -+ memset(pi->tx_power_offset, 0, sizeof(pi->tx_power_offset)); -+ pi->tx_power_max = tx_pwr_max; -+ pi->tx_power_min = tx_pwr_min; -+ pi->tx_power_max_rate_ind = tx_pwr_max_rate_ind; -+ for (rate = 0; rate < max_num_rate; rate++) { -+ -+ pi->tx_power_target[rate] = tx_pwr_target[rate]; -+ -+ if (!pi->hwpwrctrl || ISNPHY(pi)) -+ pi->tx_power_offset[rate] = -+ pi->tx_power_max - pi->tx_power_target[rate]; -+ else -+ pi->tx_power_offset[rate] = -+ pi->tx_power_target[rate] - pi->tx_power_min; -+ } -+ -+ txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc; -+ if (txpwr_recalc_fn) -+ (*txpwr_recalc_fn)(pi); -+} -+ -+static void -+wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr, -+ u16 chanspec) -+{ -+ u8 tmp_txpwr_limit[2 * BRCMS_NUM_RATES_OFDM]; -+ u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL; -+ int rate_start_index = 0, rate1, rate2, k; -+ -+ for (rate1 = WL_TX_POWER_CCK_FIRST, rate2 = 0; -+ rate2 < WL_TX_POWER_CCK_NUM; rate1++, rate2++) -+ pi->txpwr_limit[rate1] = txpwr->cck[rate2]; -+ -+ for (rate1 = WL_TX_POWER_OFDM_FIRST, rate2 = 0; -+ rate2 < WL_TX_POWER_OFDM_NUM; rate1++, rate2++) -+ pi->txpwr_limit[rate1] = txpwr->ofdm[rate2]; -+ -+ if (ISNPHY(pi)) { -+ -+ for (k = 0; k < 4; k++) { -+ switch (k) { -+ case 0: -+ -+ txpwr_ptr1 = txpwr->mcs_20_siso; -+ txpwr_ptr2 = txpwr->ofdm; -+ rate_start_index = WL_TX_POWER_OFDM_FIRST; -+ break; -+ case 1: -+ -+ txpwr_ptr1 = txpwr->mcs_20_cdd; -+ txpwr_ptr2 = txpwr->ofdm_cdd; -+ rate_start_index = WL_TX_POWER_OFDM20_CDD_FIRST; -+ break; -+ case 2: -+ -+ txpwr_ptr1 = txpwr->mcs_40_siso; -+ txpwr_ptr2 = txpwr->ofdm_40_siso; -+ rate_start_index = -+ WL_TX_POWER_OFDM40_SISO_FIRST; -+ break; -+ case 3: -+ -+ txpwr_ptr1 = txpwr->mcs_40_cdd; -+ txpwr_ptr2 = txpwr->ofdm_40_cdd; -+ rate_start_index = WL_TX_POWER_OFDM40_CDD_FIRST; -+ break; -+ } -+ -+ for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; -+ rate2++) { -+ tmp_txpwr_limit[rate2] = 0; -+ tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] = -+ txpwr_ptr1[rate2]; -+ } -+ wlc_phy_mcs_to_ofdm_powers_nphy( -+ tmp_txpwr_limit, 0, -+ BRCMS_NUM_RATES_OFDM - -+ 1, BRCMS_NUM_RATES_OFDM); -+ for (rate1 = rate_start_index, rate2 = 0; -+ rate2 < BRCMS_NUM_RATES_OFDM; rate1++, rate2++) -+ pi->txpwr_limit[rate1] = -+ min(txpwr_ptr2[rate2], -+ tmp_txpwr_limit[rate2]); -+ } -+ -+ for (k = 0; k < 4; k++) { -+ switch (k) { -+ case 0: -+ -+ txpwr_ptr1 = txpwr->ofdm; -+ txpwr_ptr2 = txpwr->mcs_20_siso; -+ rate_start_index = WL_TX_POWER_MCS20_SISO_FIRST; -+ break; -+ case 1: -+ -+ txpwr_ptr1 = txpwr->ofdm_cdd; -+ txpwr_ptr2 = txpwr->mcs_20_cdd; -+ rate_start_index = WL_TX_POWER_MCS20_CDD_FIRST; -+ break; -+ case 2: -+ -+ txpwr_ptr1 = txpwr->ofdm_40_siso; -+ txpwr_ptr2 = txpwr->mcs_40_siso; -+ rate_start_index = WL_TX_POWER_MCS40_SISO_FIRST; -+ break; -+ case 3: -+ -+ txpwr_ptr1 = txpwr->ofdm_40_cdd; -+ txpwr_ptr2 = txpwr->mcs_40_cdd; -+ rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST; -+ break; -+ } -+ for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; -+ rate2++) { -+ tmp_txpwr_limit[rate2] = 0; -+ tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] = -+ txpwr_ptr1[rate2]; -+ } -+ wlc_phy_ofdm_to_mcs_powers_nphy( -+ tmp_txpwr_limit, 0, -+ BRCMS_NUM_RATES_OFDM - -+ 1, BRCMS_NUM_RATES_OFDM); -+ for (rate1 = rate_start_index, rate2 = 0; -+ rate2 < BRCMS_NUM_RATES_MCS_1_STREAM; -+ rate1++, rate2++) -+ pi->txpwr_limit[rate1] = -+ min(txpwr_ptr2[rate2], -+ tmp_txpwr_limit[rate2]); -+ } -+ -+ for (k = 0; k < 2; k++) { -+ switch (k) { -+ case 0: -+ -+ rate_start_index = WL_TX_POWER_MCS20_STBC_FIRST; -+ txpwr_ptr1 = txpwr->mcs_20_stbc; -+ break; -+ case 1: -+ -+ rate_start_index = WL_TX_POWER_MCS40_STBC_FIRST; -+ txpwr_ptr1 = txpwr->mcs_40_stbc; -+ break; -+ } -+ for (rate1 = rate_start_index, rate2 = 0; -+ rate2 < BRCMS_NUM_RATES_MCS_1_STREAM; -+ rate1++, rate2++) -+ pi->txpwr_limit[rate1] = txpwr_ptr1[rate2]; -+ } -+ -+ for (k = 0; k < 2; k++) { -+ switch (k) { -+ case 0: -+ -+ rate_start_index = WL_TX_POWER_MCS20_SDM_FIRST; -+ txpwr_ptr1 = txpwr->mcs_20_mimo; -+ break; -+ case 1: -+ -+ rate_start_index = WL_TX_POWER_MCS40_SDM_FIRST; -+ txpwr_ptr1 = txpwr->mcs_40_mimo; -+ break; -+ } -+ for (rate1 = rate_start_index, rate2 = 0; -+ rate2 < BRCMS_NUM_RATES_MCS_2_STREAM; -+ rate1++, rate2++) -+ pi->txpwr_limit[rate1] = txpwr_ptr1[rate2]; -+ } -+ -+ pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32; -+ -+ pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] = -+ min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST], -+ pi->txpwr_limit[WL_TX_POWER_MCS_32]); -+ pi->txpwr_limit[WL_TX_POWER_MCS_32] = -+ pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST]; -+ } -+} -+ -+void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, u8 txpwr_percent) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ pi->txpwr_percent = txpwr_percent; -+} -+ -+void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ pi->sh->machwcap = machwcap; -+} -+ -+void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ u16 rxc; -+ rxc = 0; -+ -+ if (start_end == ON) { -+ if (!ISNPHY(pi)) -+ return; -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 3) -+ || NREV_IS(pi->pubpi.phy_rev, 4)) { -+ W_REG(&pi->regs->phyregaddr, 0xa0); -+ (void)R_REG(&pi->regs->phyregaddr); -+ rxc = R_REG(&pi->regs->phyregdata); -+ W_REG(&pi->regs->phyregdata, -+ (0x1 << 15) | rxc); -+ } -+ } else { -+ if (NREV_IS(pi->pubpi.phy_rev, 3) -+ || NREV_IS(pi->pubpi.phy_rev, 4)) { -+ W_REG(&pi->regs->phyregaddr, 0xa0); -+ (void)R_REG(&pi->regs->phyregaddr); -+ W_REG(&pi->regs->phyregdata, rxc); -+ } -+ -+ wlc_phy_por_inform(ppi); -+ } -+} -+ -+void -+wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *txpwr, -+ u16 chanspec) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ wlc_phy_txpower_reg_limit_calc(pi, txpwr, chanspec); -+ -+ if (ISLCNPHY(pi)) { -+ int i, j; -+ for (i = TXP_FIRST_OFDM_20_CDD, j = 0; -+ j < BRCMS_NUM_RATES_MCS_1_STREAM; i++, j++) { -+ if (txpwr->mcs_20_siso[j]) -+ pi->txpwr_limit[i] = txpwr->mcs_20_siso[j]; -+ else -+ pi->txpwr_limit[i] = txpwr->ofdm[j]; -+ } -+ } -+ -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ -+ wlc_phy_txpower_recalc_target(pi); -+ wlc_phy_cal_txpower_recalc_sw(pi); -+ wlapi_enable_mac(pi->sh->physhim); -+} -+ -+void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ pi->ofdm_rateset_war = war; -+} -+ -+void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ pi->bf_preempt_4306 = bf_preempt; -+} -+ -+void wlc_phy_txpower_update_shm(struct brcms_phy *pi) -+{ -+ int j; -+ if (ISNPHY(pi)) -+ return; -+ -+ if (!pi->sh->clk) -+ return; -+ -+ if (pi->hwpwrctrl) { -+ u16 offset; -+ -+ wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_MAX, 63); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_N, -+ 1 << NUM_TSSI_FRAMES); -+ -+ wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_TARGET, -+ pi->tx_power_min << NUM_TSSI_FRAMES); -+ -+ wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_CUR, -+ pi->hwpwr_txcur); -+ -+ for (j = TXP_FIRST_OFDM; j <= TXP_LAST_OFDM; j++) { -+ const u8 ucode_ofdm_rates[] = { -+ 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c -+ }; -+ offset = wlapi_bmac_rate_shm_offset( -+ pi->sh->physhim, -+ ucode_ofdm_rates[j - TXP_FIRST_OFDM]); -+ wlapi_bmac_write_shm(pi->sh->physhim, offset + 6, -+ pi->tx_power_offset[j]); -+ wlapi_bmac_write_shm(pi->sh->physhim, offset + 14, -+ -(pi->tx_power_offset[j] / 2)); -+ } -+ -+ wlapi_bmac_mhf(pi->sh->physhim, MHF2, MHF2_HWPWRCTL, -+ MHF2_HWPWRCTL, BRCM_BAND_ALL); -+ } else { -+ int i; -+ -+ for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) -+ pi->tx_power_offset[i] = -+ (u8) roundup(pi->tx_power_offset[i], 8); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET, -+ (u16) -+ ((pi->tx_power_offset[TXP_FIRST_OFDM] -+ + 7) >> 3)); -+ } -+} -+ -+bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ if (ISNPHY(pi)) -+ return pi->nphy_txpwrctrl; -+ else -+ return pi->hwpwrctrl; -+} -+ -+void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ bool suspend; -+ -+ if (!pi->hwpwrctrl_capable) -+ return; -+ -+ pi->hwpwrctrl = hwpwrctrl; -+ pi->nphy_txpwrctrl = hwpwrctrl; -+ pi->txpwrctrl = hwpwrctrl; -+ -+ if (ISNPHY(pi)) { -+ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); -+ if (!suspend) -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ -+ wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl); -+ if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) -+ wlc_phy_txpwr_fixpower_nphy(pi); -+ else -+ mod_phy_reg(pi, 0x1e7, (0x7f << 0), -+ pi->saved_txpwr_idx); -+ -+ if (!suspend) -+ wlapi_enable_mac(pi->sh->physhim); -+ } -+} -+ -+void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi) -+{ -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ pi->ipa2g_on = (pi->srom_fem2g.extpagain == 2); -+ pi->ipa5g_on = (pi->srom_fem5g.extpagain == 2); -+ } else { -+ pi->ipa2g_on = false; -+ pi->ipa5g_on = false; -+ } -+} -+ -+static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi) -+{ -+ s16 tx0_status, tx1_status; -+ u16 estPower1, estPower2; -+ u8 pwr0, pwr1, adj_pwr0, adj_pwr1; -+ u32 est_pwr; -+ -+ estPower1 = read_phy_reg(pi, 0x118); -+ estPower2 = read_phy_reg(pi, 0x119); -+ -+ if ((estPower1 & (0x1 << 8)) == (0x1 << 8)) -+ pwr0 = (u8) (estPower1 & (0xff << 0)) >> 0; -+ else -+ pwr0 = 0x80; -+ -+ if ((estPower2 & (0x1 << 8)) == (0x1 << 8)) -+ pwr1 = (u8) (estPower2 & (0xff << 0)) >> 0; -+ else -+ pwr1 = 0x80; -+ -+ tx0_status = read_phy_reg(pi, 0x1ed); -+ tx1_status = read_phy_reg(pi, 0x1ee); -+ -+ if ((tx0_status & (0x1 << 15)) == (0x1 << 15)) -+ adj_pwr0 = (u8) (tx0_status & (0xff << 0)) >> 0; -+ else -+ adj_pwr0 = 0x80; -+ if ((tx1_status & (0x1 << 15)) == (0x1 << 15)) -+ adj_pwr1 = (u8) (tx1_status & (0xff << 0)) >> 0; -+ else -+ adj_pwr1 = 0x80; -+ -+ est_pwr = (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) | -+ adj_pwr1); -+ -+ return est_pwr; -+} -+ -+void -+wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, struct tx_power *power, -+ uint channel) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ uint rate, num_rates; -+ u8 min_pwr, max_pwr; -+ -+#if WL_TX_POWER_RATES != TXP_NUM_RATES -+#error "struct tx_power out of sync with this fn" -+#endif -+ -+ if (ISNPHY(pi)) { -+ power->rf_cores = 2; -+ power->flags |= (WL_TX_POWER_F_MIMO); -+ if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON) -+ power->flags |= -+ (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW); -+ } else if (ISLCNPHY(pi)) { -+ power->rf_cores = 1; -+ power->flags |= (WL_TX_POWER_F_SISO); -+ if (pi->radiopwr_override == RADIOPWR_OVERRIDE_DEF) -+ power->flags |= WL_TX_POWER_F_ENABLED; -+ if (pi->hwpwrctrl) -+ power->flags |= WL_TX_POWER_F_HW; -+ } -+ -+ num_rates = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : -+ ((ISLCNPHY(pi)) ? -+ (TXP_LAST_OFDM_20_CDD + 1) : (TXP_LAST_OFDM + 1))); -+ -+ for (rate = 0; rate < num_rates; rate++) { -+ power->user_limit[rate] = pi->tx_user_target[rate]; -+ wlc_phy_txpower_sromlimit(ppi, channel, &min_pwr, &max_pwr, -+ rate); -+ power->board_limit[rate] = (u8) max_pwr; -+ power->target[rate] = pi->tx_power_target[rate]; -+ } -+ -+ if (ISNPHY(pi)) { -+ u32 est_pout; -+ -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ wlc_phyreg_enter((struct brcms_phy_pub *) pi); -+ est_pout = wlc_phy_txpower_est_power_nphy(pi); -+ wlc_phyreg_exit((struct brcms_phy_pub *) pi); -+ wlapi_enable_mac(pi->sh->physhim); -+ -+ power->est_Pout[0] = (est_pout >> 8) & 0xff; -+ power->est_Pout[1] = est_pout & 0xff; -+ -+ power->est_Pout_act[0] = est_pout >> 24; -+ power->est_Pout_act[1] = (est_pout >> 16) & 0xff; -+ -+ if (power->est_Pout[0] == 0x80) -+ power->est_Pout[0] = 0; -+ if (power->est_Pout[1] == 0x80) -+ power->est_Pout[1] = 0; -+ -+ if (power->est_Pout_act[0] == 0x80) -+ power->est_Pout_act[0] = 0; -+ if (power->est_Pout_act[1] == 0x80) -+ power->est_Pout_act[1] = 0; -+ -+ power->est_Pout_cck = 0; -+ -+ power->tx_power_max[0] = pi->tx_power_max; -+ power->tx_power_max[1] = pi->tx_power_max; -+ -+ power->tx_power_max_rate_ind[0] = pi->tx_power_max_rate_ind; -+ power->tx_power_max_rate_ind[1] = pi->tx_power_max_rate_ind; -+ } else if (pi->hwpwrctrl && pi->sh->up) { -+ -+ wlc_phyreg_enter(ppi); -+ if (ISLCNPHY(pi)) { -+ -+ power->tx_power_max[0] = pi->tx_power_max; -+ power->tx_power_max[1] = pi->tx_power_max; -+ -+ power->tx_power_max_rate_ind[0] = -+ pi->tx_power_max_rate_ind; -+ power->tx_power_max_rate_ind[1] = -+ pi->tx_power_max_rate_ind; -+ -+ if (wlc_phy_tpc_isenabled_lcnphy(pi)) -+ power->flags |= -+ (WL_TX_POWER_F_HW | -+ WL_TX_POWER_F_ENABLED); -+ else -+ power->flags &= -+ ~(WL_TX_POWER_F_HW | -+ WL_TX_POWER_F_ENABLED); -+ -+ wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0], -+ (s8 *) &power->est_Pout_cck); -+ } -+ wlc_phyreg_exit(ppi); -+ } -+} -+ -+void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ pi->antsel_type = antsel_type; -+} -+ -+bool wlc_phy_test_ison(struct brcms_phy_pub *ppi) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ return pi->phytest_on; -+} -+ -+void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ bool suspend; -+ -+ pi->sh->rx_antdiv = val; -+ -+ if (!(ISNPHY(pi) && D11REV_IS(pi->sh->corerev, 16))) { -+ if (val > ANT_RX_DIV_FORCE_1) -+ wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, -+ MHF1_ANTDIV, BRCM_BAND_ALL); -+ else -+ wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, 0, -+ BRCM_BAND_ALL); -+ } -+ -+ if (ISNPHY(pi)) -+ return; -+ -+ if (!pi->sh->clk) -+ return; -+ -+ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); -+ if (!suspend) -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ -+ if (ISLCNPHY(pi)) { -+ if (val > ANT_RX_DIV_FORCE_1) { -+ mod_phy_reg(pi, 0x410, (0x1 << 1), 0x01 << 1); -+ mod_phy_reg(pi, 0x410, -+ (0x1 << 0), -+ ((ANT_RX_DIV_START_1 == val) ? 1 : 0) << 0); -+ } else { -+ mod_phy_reg(pi, 0x410, (0x1 << 1), 0x00 << 1); -+ mod_phy_reg(pi, 0x410, (0x1 << 0), (u16) val << 0); -+ } -+ } -+ -+ if (!suspend) -+ wlapi_enable_mac(pi->sh->physhim); -+ -+ return; -+} -+ -+static bool -+wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr, s8 *pwr_ant) -+{ -+ s8 cmplx_pwr_dbm[PHY_CORE_MAX]; -+ u8 i; -+ -+ memset((u8 *) cmplx_pwr_dbm, 0, sizeof(cmplx_pwr_dbm)); -+ wlc_phy_compute_dB(cmplx_pwr, cmplx_pwr_dbm, pi->pubpi.phy_corenum); -+ -+ for (i = 0; i < pi->pubpi.phy_corenum; i++) { -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) -+ cmplx_pwr_dbm[i] += (s8) PHY_NOISE_OFFSETFACT_4322; -+ else -+ -+ cmplx_pwr_dbm[i] += (s8) (16 - (15) * 3 - 70); -+ } -+ -+ for (i = 0; i < pi->pubpi.phy_corenum; i++) { -+ pi->nphy_noise_win[i][pi->nphy_noise_index] = cmplx_pwr_dbm[i]; -+ pwr_ant[i] = cmplx_pwr_dbm[i]; -+ } -+ pi->nphy_noise_index = -+ MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ); -+ return true; -+} -+ -+static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm) -+{ -+ if (!pi->phynoise_state) -+ return; -+ -+ if (pi->phynoise_state & PHY_NOISE_STATE_MON) { -+ if (pi->phynoise_chan_watchdog == channel) { -+ pi->sh->phy_noise_window[pi->sh->phy_noise_index] = -+ noise_dbm; -+ pi->sh->phy_noise_index = -+ MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ); -+ } -+ pi->phynoise_state &= ~PHY_NOISE_STATE_MON; -+ } -+ -+ if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL) -+ pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL; -+ -+} -+ -+static s8 wlc_phy_noise_read_shmem(struct brcms_phy *pi) -+{ -+ u32 cmplx_pwr[PHY_CORE_MAX]; -+ s8 noise_dbm_ant[PHY_CORE_MAX]; -+ u16 lo, hi; -+ u32 cmplx_pwr_tot = 0; -+ s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; -+ u8 idx, core; -+ -+ memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr)); -+ memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant)); -+ -+ for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2, -+ core++) { -+ lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx)); -+ hi = wlapi_bmac_read_shm(pi->sh->physhim, -+ M_PWRIND_MAP(idx + 1)); -+ cmplx_pwr[core] = (hi << 16) + lo; -+ cmplx_pwr_tot += cmplx_pwr[core]; -+ if (cmplx_pwr[core] == 0) -+ noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY; -+ else -+ cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE; -+ } -+ -+ if (cmplx_pwr_tot != 0) -+ wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant); -+ -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ pi->nphy_noise_win[core][pi->nphy_noise_index] = -+ noise_dbm_ant[core]; -+ -+ if (noise_dbm_ant[core] > noise_dbm) -+ noise_dbm = noise_dbm_ant[core]; -+ } -+ pi->nphy_noise_index = -+ MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ); -+ -+ return noise_dbm; -+ -+} -+ -+void wlc_phy_noise_sample_intr(struct brcms_phy_pub *pih) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ u16 jssi_aux; -+ u8 channel = 0; -+ s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; -+ -+ if (ISLCNPHY(pi)) { -+ u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1; -+ u16 lo, hi; -+ s32 pwr_offset_dB, gain_dB; -+ u16 status_0, status_1; -+ -+ jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX); -+ channel = jssi_aux & D11_CURCHANNEL_MAX; -+ -+ lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0); -+ hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1); -+ cmplx_pwr0 = (hi << 16) + lo; -+ -+ lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2); -+ hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3); -+ cmplx_pwr1 = (hi << 16) + lo; -+ cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6; -+ -+ status_0 = 0x44; -+ status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0); -+ if ((cmplx_pwr > 0 && cmplx_pwr < 500) -+ && ((status_1 & 0xc000) == 0x4000)) { -+ -+ wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm, -+ pi->pubpi.phy_corenum); -+ pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF); -+ if (pwr_offset_dB > 127) -+ pwr_offset_dB -= 256; -+ -+ noise_dbm += (s8) (pwr_offset_dB - 30); -+ -+ gain_dB = (status_0 & 0x1ff); -+ noise_dbm -= (s8) (gain_dB); -+ } else { -+ noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY; -+ } -+ } else if (ISNPHY(pi)) { -+ -+ jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX); -+ channel = jssi_aux & D11_CURCHANNEL_MAX; -+ -+ noise_dbm = wlc_phy_noise_read_shmem(pi); -+ } -+ -+ wlc_phy_noise_cb(pi, channel, noise_dbm); -+ -+} -+ -+static void -+wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; -+ bool sampling_in_progress = (pi->phynoise_state != 0); -+ bool wait_for_intr = true; -+ -+ switch (reason) { -+ case PHY_NOISE_SAMPLE_MON: -+ pi->phynoise_chan_watchdog = ch; -+ pi->phynoise_state |= PHY_NOISE_STATE_MON; -+ break; -+ -+ case PHY_NOISE_SAMPLE_EXTERNAL: -+ pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL; -+ break; -+ -+ default: -+ break; -+ } -+ -+ if (sampling_in_progress) -+ return; -+ -+ pi->phynoise_now = pi->sh->now; -+ -+ if (pi->phy_fixed_noise) { -+ if (ISNPHY(pi)) { -+ pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] = -+ PHY_NOISE_FIXED_VAL_NPHY; -+ pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] = -+ PHY_NOISE_FIXED_VAL_NPHY; -+ pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index, -+ PHY_NOISE_WINDOW_SZ); -+ noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; -+ } else { -+ noise_dbm = PHY_NOISE_FIXED_VAL; -+ } -+ -+ wait_for_intr = false; -+ goto done; -+ } -+ -+ if (ISLCNPHY(pi)) { -+ if (!pi->phynoise_polling -+ || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) { -+ wlapi_bmac_write_shm(pi->sh->physhim, M_JSSI_0, 0); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0); -+ -+ OR_REG(&pi->regs->maccommand, -+ MCMD_BG_NOISE); -+ } else { -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ wlc_lcnphy_deaf_mode(pi, (bool) 0); -+ noise_dbm = (s8) wlc_lcnphy_rx_signal_power(pi, 20); -+ wlc_lcnphy_deaf_mode(pi, (bool) 1); -+ wlapi_enable_mac(pi->sh->physhim); -+ wait_for_intr = false; -+ } -+ } else if (ISNPHY(pi)) { -+ if (!pi->phynoise_polling -+ || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) { -+ -+ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0); -+ -+ OR_REG(&pi->regs->maccommand, -+ MCMD_BG_NOISE); -+ } else { -+ struct phy_iq_est est[PHY_CORE_MAX]; -+ u32 cmplx_pwr[PHY_CORE_MAX]; -+ s8 noise_dbm_ant[PHY_CORE_MAX]; -+ u16 log_num_samps, num_samps, classif_state = 0; -+ u8 wait_time = 32; -+ u8 wait_crs = 0; -+ u8 i; -+ -+ memset((u8 *) est, 0, sizeof(est)); -+ memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr)); -+ memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant)); -+ -+ log_num_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY; -+ num_samps = 1 << log_num_samps; -+ -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ classif_state = wlc_phy_classifier_nphy(pi, 0, 0); -+ wlc_phy_classifier_nphy(pi, 3, 0); -+ wlc_phy_rx_iq_est_nphy(pi, est, num_samps, wait_time, -+ wait_crs); -+ wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state); -+ wlapi_enable_mac(pi->sh->physhim); -+ -+ for (i = 0; i < pi->pubpi.phy_corenum; i++) -+ cmplx_pwr[i] = (est[i].i_pwr + est[i].q_pwr) >> -+ log_num_samps; -+ -+ wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant); -+ -+ for (i = 0; i < pi->pubpi.phy_corenum; i++) { -+ pi->nphy_noise_win[i][pi->nphy_noise_index] = -+ noise_dbm_ant[i]; -+ -+ if (noise_dbm_ant[i] > noise_dbm) -+ noise_dbm = noise_dbm_ant[i]; -+ } -+ pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index, -+ PHY_NOISE_WINDOW_SZ); -+ -+ wait_for_intr = false; -+ } -+ } -+ -+done: -+ -+ if (!wait_for_intr) -+ wlc_phy_noise_cb(pi, ch, noise_dbm); -+ -+} -+ -+void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *pih) -+{ -+ u8 channel; -+ -+ channel = CHSPEC_CHANNEL(wlc_phy_chanspec_get(pih)); -+ -+ wlc_phy_noise_sample_request(pih, PHY_NOISE_SAMPLE_EXTERNAL, channel); -+} -+ -+static const s8 lcnphy_gain_index_offset_for_pkt_rssi[] = { -+ 8, -+ 8, -+ 8, -+ 8, -+ 8, -+ 8, -+ 8, -+ 9, -+ 10, -+ 8, -+ 8, -+ 7, -+ 7, -+ 1, -+ 2, -+ 2, -+ 2, -+ 2, -+ 2, -+ 2, -+ 2, -+ 2, -+ 2, -+ 2, -+ 2, -+ 2, -+ 2, -+ 2, -+ 2, -+ 2, -+ 2, -+ 2, -+ 1, -+ 1, -+ 0, -+ 0, -+ 0, -+ 0 -+}; -+ -+void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core) -+{ -+ u8 msb, secondmsb, i; -+ u32 tmp; -+ -+ for (i = 0; i < core; i++) { -+ secondmsb = 0; -+ tmp = cmplx_pwr[i]; -+ msb = fls(tmp); -+ if (msb) -+ secondmsb = (u8) ((tmp >> (--msb - 1)) & 1); -+ p_cmplx_pwr_dB[i] = (s8) (3 * msb + 2 * secondmsb); -+ } -+} -+ -+int wlc_phy_rssi_compute(struct brcms_phy_pub *pih, -+ struct d11rxhdr *rxh) -+{ -+ int rssi = rxh->PhyRxStatus_1 & PRXS1_JSSI_MASK; -+ uint radioid = pih->radioid; -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ if ((pi->sh->corerev >= 11) -+ && !(rxh->RxStatus2 & RXS_PHYRXST_VALID)) { -+ rssi = BRCMS_RSSI_INVALID; -+ goto end; -+ } -+ -+ if (ISLCNPHY(pi)) { -+ u8 gidx = (rxh->PhyRxStatus_2 & 0xFC00) >> 10; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ if (rssi > 127) -+ rssi -= 256; -+ -+ rssi = rssi + lcnphy_gain_index_offset_for_pkt_rssi[gidx]; -+ if ((rssi > -46) && (gidx > 18)) -+ rssi = rssi + 7; -+ -+ rssi = rssi + pi_lcn->lcnphy_pkteng_rssi_slope; -+ -+ rssi = rssi + 2; -+ -+ } -+ -+ if (ISLCNPHY(pi)) { -+ if (rssi > 127) -+ rssi -= 256; -+ } else if (radioid == BCM2055_ID || radioid == BCM2056_ID -+ || radioid == BCM2057_ID) { -+ rssi = wlc_phy_rssi_compute_nphy(pi, rxh); -+ } -+ -+end: -+ return rssi; -+} -+ -+void wlc_phy_freqtrack_start(struct brcms_phy_pub *pih) -+{ -+ return; -+} -+ -+void wlc_phy_freqtrack_end(struct brcms_phy_pub *pih) -+{ -+ return; -+} -+ -+void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag) -+{ -+ struct brcms_phy *pi; -+ pi = (struct brcms_phy *) ppi; -+ -+ if (ISLCNPHY(pi)) -+ wlc_lcnphy_deaf_mode(pi, true); -+ else if (ISNPHY(pi)) -+ wlc_nphy_deaf_mode(pi, true); -+} -+ -+void wlc_phy_watchdog(struct brcms_phy_pub *pih) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ bool delay_phy_cal = false; -+ pi->sh->now++; -+ -+ if (!pi->watchdog_override) -+ return; -+ -+ if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi))) -+ wlc_phy_noise_sample_request((struct brcms_phy_pub *) pi, -+ PHY_NOISE_SAMPLE_MON, -+ CHSPEC_CHANNEL(pi-> -+ radio_chanspec)); -+ -+ if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5) -+ pi->phynoise_state = 0; -+ -+ if ((!pi->phycal_txpower) || -+ ((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) { -+ -+ if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi)) -+ pi->phycal_txpower = pi->sh->now; -+ } -+ -+ if ((SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) -+ || ASSOC_INPROG_PHY(pi))) -+ return; -+ -+ if (ISNPHY(pi) && !pi->disable_percal && !delay_phy_cal) { -+ -+ if ((pi->nphy_perical != PHY_PERICAL_DISABLE) && -+ (pi->nphy_perical != PHY_PERICAL_MANUAL) && -+ ((pi->sh->now - pi->nphy_perical_last) >= -+ pi->sh->glacial_timer)) -+ wlc_phy_cal_perical((struct brcms_phy_pub *) pi, -+ PHY_PERICAL_WATCHDOG); -+ -+ wlc_phy_txpwr_papd_cal_nphy(pi); -+ } -+ -+ if (ISLCNPHY(pi)) { -+ if (pi->phy_forcecal || -+ ((pi->sh->now - pi->phy_lastcal) >= -+ pi->sh->glacial_timer)) { -+ if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi))) -+ wlc_lcnphy_calib_modes( -+ pi, -+ LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL); -+ if (! -+ (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) -+ || ASSOC_INPROG_PHY(pi) -+ || pi->carrier_suppr_disable -+ || pi->disable_percal)) -+ wlc_lcnphy_calib_modes(pi, -+ PHY_PERICAL_WATCHDOG); -+ } -+ } -+} -+ -+void wlc_phy_BSSinit(struct brcms_phy_pub *pih, bool bonlyap, int rssi) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ uint i; -+ uint k; -+ -+ for (i = 0; i < MA_WINDOW_SZ; i++) -+ pi->sh->phy_noise_window[i] = (s8) (rssi & 0xff); -+ if (ISLCNPHY(pi)) { -+ for (i = 0; i < MA_WINDOW_SZ; i++) -+ pi->sh->phy_noise_window[i] = -+ PHY_NOISE_FIXED_VAL_LCNPHY; -+ } -+ pi->sh->phy_noise_index = 0; -+ -+ for (i = 0; i < PHY_NOISE_WINDOW_SZ; i++) { -+ for (k = WL_ANT_IDX_1; k < WL_ANT_RX_MAX; k++) -+ pi->nphy_noise_win[k][i] = PHY_NOISE_FIXED_VAL_NPHY; -+ } -+ pi->nphy_noise_index = 0; -+} -+ -+void -+wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag) -+{ -+ *eps_imag = (epsilon >> 13); -+ if (*eps_imag > 0xfff) -+ *eps_imag -= 0x2000; -+ -+ *eps_real = (epsilon & 0x1fff); -+ if (*eps_real > 0xfff) -+ *eps_real -= 0x2000; -+} -+ -+void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi) -+{ -+ wlapi_del_timer(pi->phycal_timer); -+ -+ pi->cal_type_override = PHY_PERICAL_AUTO; -+ pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE; -+ pi->mphase_txcal_cmdidx = 0; -+} -+ -+static void -+wlc_phy_cal_perical_mphase_schedule(struct brcms_phy *pi, uint delay) -+{ -+ -+ if ((pi->nphy_perical != PHY_PERICAL_MPHASE) && -+ (pi->nphy_perical != PHY_PERICAL_MANUAL)) -+ return; -+ -+ wlapi_del_timer(pi->phycal_timer); -+ -+ pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT; -+ wlapi_add_timer(pi->phycal_timer, delay, 0); -+} -+ -+void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason) -+{ -+ s16 nphy_currtemp = 0; -+ s16 delta_temp = 0; -+ bool do_periodic_cal = true; -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ if (!ISNPHY(pi)) -+ return; -+ -+ if ((pi->nphy_perical == PHY_PERICAL_DISABLE) || -+ (pi->nphy_perical == PHY_PERICAL_MANUAL)) -+ return; -+ -+ switch (reason) { -+ case PHY_PERICAL_DRIVERUP: -+ break; -+ -+ case PHY_PERICAL_PHYINIT: -+ if (pi->nphy_perical == PHY_PERICAL_MPHASE) { -+ if (PHY_PERICAL_MPHASE_PENDING(pi)) -+ wlc_phy_cal_perical_mphase_reset(pi); -+ -+ wlc_phy_cal_perical_mphase_schedule( -+ pi, -+ PHY_PERICAL_INIT_DELAY); -+ } -+ break; -+ -+ case PHY_PERICAL_JOIN_BSS: -+ case PHY_PERICAL_START_IBSS: -+ case PHY_PERICAL_UP_BSS: -+ if ((pi->nphy_perical == PHY_PERICAL_MPHASE) && -+ PHY_PERICAL_MPHASE_PENDING(pi)) -+ wlc_phy_cal_perical_mphase_reset(pi); -+ -+ pi->first_cal_after_assoc = true; -+ -+ pi->cal_type_override = PHY_PERICAL_FULL; -+ -+ if (pi->phycal_tempdelta) -+ pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi); -+ -+ wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL); -+ break; -+ -+ case PHY_PERICAL_WATCHDOG: -+ if (pi->phycal_tempdelta) { -+ nphy_currtemp = wlc_phy_tempsense_nphy(pi); -+ delta_temp = -+ (nphy_currtemp > pi->nphy_lastcal_temp) ? -+ nphy_currtemp - pi->nphy_lastcal_temp : -+ pi->nphy_lastcal_temp - nphy_currtemp; -+ -+ if ((delta_temp < (s16) pi->phycal_tempdelta) && -+ (pi->nphy_txiqlocal_chanspec == -+ pi->radio_chanspec)) -+ do_periodic_cal = false; -+ else -+ pi->nphy_lastcal_temp = nphy_currtemp; -+ } -+ -+ if (do_periodic_cal) { -+ if (pi->nphy_perical == PHY_PERICAL_MPHASE) { -+ if (!PHY_PERICAL_MPHASE_PENDING(pi)) -+ wlc_phy_cal_perical_mphase_schedule( -+ pi, -+ PHY_PERICAL_WDOG_DELAY); -+ } else if (pi->nphy_perical == PHY_PERICAL_SPHASE) -+ wlc_phy_cal_perical_nphy_run(pi, -+ PHY_PERICAL_AUTO); -+ } -+ break; -+ default: -+ break; -+ } -+} -+ -+void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi) -+{ -+ pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT; -+ pi->mphase_txcal_cmdidx = 0; -+} -+ -+u8 wlc_phy_nbits(s32 value) -+{ -+ s32 abs_val; -+ u8 nbits = 0; -+ -+ abs_val = abs(value); -+ while ((abs_val >> nbits) > 0) -+ nbits++; -+ -+ return nbits; -+} -+ -+void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ pi->sh->hw_phytxchain = txchain; -+ pi->sh->hw_phyrxchain = rxchain; -+ pi->sh->phytxchain = txchain; -+ pi->sh->phyrxchain = rxchain; -+ pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain); -+} -+ -+void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ pi->sh->phytxchain = txchain; -+ -+ if (ISNPHY(pi)) -+ wlc_phy_rxcore_setstate_nphy(pih, rxchain); -+ -+ pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain); -+} -+ -+void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, u8 *rxchain) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ *txchain = pi->sh->phytxchain; -+ *rxchain = pi->sh->phyrxchain; -+} -+ -+u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih) -+{ -+ s16 nphy_currtemp; -+ u8 active_bitmap; -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ active_bitmap = (pi->phy_txcore_heatedup) ? 0x31 : 0x33; -+ -+ if (!pi->watchdog_override) -+ return active_bitmap; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 6)) { -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ nphy_currtemp = wlc_phy_tempsense_nphy(pi); -+ wlapi_enable_mac(pi->sh->physhim); -+ -+ if (!pi->phy_txcore_heatedup) { -+ if (nphy_currtemp >= pi->phy_txcore_disable_temp) { -+ active_bitmap &= 0xFD; -+ pi->phy_txcore_heatedup = true; -+ } -+ } else { -+ if (nphy_currtemp <= pi->phy_txcore_enable_temp) { -+ active_bitmap |= 0x2; -+ pi->phy_txcore_heatedup = false; -+ } -+ } -+ } -+ -+ return active_bitmap; -+} -+ -+s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, u16 chanspec) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ u8 siso_mcs_id, cdd_mcs_id; -+ -+ siso_mcs_id = -+ (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO : -+ TXP_FIRST_MCS_20_SISO; -+ cdd_mcs_id = -+ (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD : -+ TXP_FIRST_MCS_20_CDD; -+ -+ if (pi->tx_power_target[siso_mcs_id] > -+ (pi->tx_power_target[cdd_mcs_id] + 12)) -+ return PHY_TXC1_MODE_SISO; -+ else -+ return PHY_TXC1_MODE_CDD; -+} -+ -+const u8 *wlc_phy_get_ofdm_rate_lookup(void) -+{ -+ return ofdm_rate_lookup; -+} -+ -+void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode) -+{ -+ if ((pi->sh->chip == BCM4313_CHIP_ID) && -+ (pi->sh->boardflags & BFL_FEM)) { -+ if (mode) { -+ u16 txant = 0; -+ txant = wlapi_bmac_get_txant(pi->sh->physhim); -+ if (txant == 1) { -+ mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2); -+ -+ mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2); -+ -+ } -+ ai_corereg(pi->sh->sih, SI_CC_IDX, -+ offsetof(struct chipcregs, gpiocontrol), -+ ~0x0, 0x0); -+ ai_corereg(pi->sh->sih, SI_CC_IDX, -+ offsetof(struct chipcregs, gpioout), 0x40, -+ 0x40); -+ ai_corereg(pi->sh->sih, SI_CC_IDX, -+ offsetof(struct chipcregs, gpioouten), 0x40, -+ 0x40); -+ } else { -+ mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2); -+ -+ mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2); -+ -+ ai_corereg(pi->sh->sih, SI_CC_IDX, -+ offsetof(struct chipcregs, gpioout), 0x40, -+ 0x00); -+ ai_corereg(pi->sh->sih, SI_CC_IDX, -+ offsetof(struct chipcregs, gpioouten), 0x40, -+ 0x0); -+ ai_corereg(pi->sh->sih, SI_CC_IDX, -+ offsetof(struct chipcregs, gpiocontrol), -+ ~0x0, 0x40); -+ } -+ } -+} -+ -+void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool ldpc) -+{ -+ return; -+} -+ -+void -+wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, s8 *ofdmoffset) -+{ -+ *cckoffset = 0; -+ *ofdmoffset = 0; -+} -+ -+s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, u16 chanspec) -+{ -+ -+ return rssi; -+} -+ -+bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *ppi) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ if (ISNPHY(pi)) -+ return wlc_phy_n_txpower_ipa_ison(pi); -+ else -+ return 0; -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h.orig 2011-11-09 13:46:58.254800521 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h 2011-11-09 13:47:17.008566067 -0500 -@@ -0,0 +1,301 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * phy_hal.h: functionality exported from the phy to higher layers -+ */ -+ -+#ifndef _BRCM_PHY_HAL_H_ -+#define _BRCM_PHY_HAL_H_ -+ -+#include -+#include -+#include -+ -+#define IDCODE_VER_MASK 0x0000000f -+#define IDCODE_VER_SHIFT 0 -+#define IDCODE_MFG_MASK 0x00000fff -+#define IDCODE_MFG_SHIFT 0 -+#define IDCODE_ID_MASK 0x0ffff000 -+#define IDCODE_ID_SHIFT 12 -+#define IDCODE_REV_MASK 0xf0000000 -+#define IDCODE_REV_SHIFT 28 -+ -+#define NORADIO_ID 0xe4f5 -+#define NORADIO_IDCODE 0x4e4f5246 -+ -+#define BCM2055_ID 0x2055 -+#define BCM2055_IDCODE 0x02055000 -+#define BCM2055A0_IDCODE 0x1205517f -+ -+#define BCM2056_ID 0x2056 -+#define BCM2056_IDCODE 0x02056000 -+#define BCM2056A0_IDCODE 0x1205617f -+ -+#define BCM2057_ID 0x2057 -+#define BCM2057_IDCODE 0x02057000 -+#define BCM2057A0_IDCODE 0x1205717f -+ -+#define BCM2064_ID 0x2064 -+#define BCM2064_IDCODE 0x02064000 -+#define BCM2064A0_IDCODE 0x0206417f -+ -+#define PHY_TPC_HW_OFF false -+#define PHY_TPC_HW_ON true -+ -+#define PHY_PERICAL_DRIVERUP 1 -+#define PHY_PERICAL_WATCHDOG 2 -+#define PHY_PERICAL_PHYINIT 3 -+#define PHY_PERICAL_JOIN_BSS 4 -+#define PHY_PERICAL_START_IBSS 5 -+#define PHY_PERICAL_UP_BSS 6 -+#define PHY_PERICAL_CHAN 7 -+#define PHY_FULLCAL 8 -+ -+#define PHY_PERICAL_DISABLE 0 -+#define PHY_PERICAL_SPHASE 1 -+#define PHY_PERICAL_MPHASE 2 -+#define PHY_PERICAL_MANUAL 3 -+ -+#define PHY_HOLD_FOR_ASSOC 1 -+#define PHY_HOLD_FOR_SCAN 2 -+#define PHY_HOLD_FOR_RM 4 -+#define PHY_HOLD_FOR_PLT 8 -+#define PHY_HOLD_FOR_MUTE 16 -+#define PHY_HOLD_FOR_NOT_ASSOC 0x20 -+ -+#define PHY_MUTE_FOR_PREISM 1 -+#define PHY_MUTE_ALL 0xffffffff -+ -+#define PHY_NOISE_FIXED_VAL (-95) -+#define PHY_NOISE_FIXED_VAL_NPHY (-92) -+#define PHY_NOISE_FIXED_VAL_LCNPHY (-92) -+ -+#define PHY_MODE_CAL 0x0002 -+#define PHY_MODE_NOISEM 0x0004 -+ -+#define BRCMS_TXPWR_DB_FACTOR 4 -+ -+/* a large TX Power as an init value to factor out of min() calculations, -+ * keep low enough to fit in an s8, units are .25 dBm -+ */ -+#define BRCMS_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */ -+ -+#define BRCMS_NUM_RATES_CCK 4 -+#define BRCMS_NUM_RATES_OFDM 8 -+#define BRCMS_NUM_RATES_MCS_1_STREAM 8 -+#define BRCMS_NUM_RATES_MCS_2_STREAM 8 -+#define BRCMS_NUM_RATES_MCS_3_STREAM 8 -+#define BRCMS_NUM_RATES_MCS_4_STREAM 8 -+ -+#define BRCMS_RSSI_INVALID 0 /* invalid RSSI value */ -+ -+struct d11regs; -+struct phy_shim_info; -+ -+struct txpwr_limits { -+ u8 cck[BRCMS_NUM_RATES_CCK]; -+ u8 ofdm[BRCMS_NUM_RATES_OFDM]; -+ -+ u8 ofdm_cdd[BRCMS_NUM_RATES_OFDM]; -+ -+ u8 ofdm_40_siso[BRCMS_NUM_RATES_OFDM]; -+ u8 ofdm_40_cdd[BRCMS_NUM_RATES_OFDM]; -+ -+ u8 mcs_20_siso[BRCMS_NUM_RATES_MCS_1_STREAM]; -+ u8 mcs_20_cdd[BRCMS_NUM_RATES_MCS_1_STREAM]; -+ u8 mcs_20_stbc[BRCMS_NUM_RATES_MCS_1_STREAM]; -+ u8 mcs_20_mimo[BRCMS_NUM_RATES_MCS_2_STREAM]; -+ -+ u8 mcs_40_siso[BRCMS_NUM_RATES_MCS_1_STREAM]; -+ u8 mcs_40_cdd[BRCMS_NUM_RATES_MCS_1_STREAM]; -+ u8 mcs_40_stbc[BRCMS_NUM_RATES_MCS_1_STREAM]; -+ u8 mcs_40_mimo[BRCMS_NUM_RATES_MCS_2_STREAM]; -+ u8 mcs32; -+}; -+ -+struct tx_power { -+ u32 flags; -+ u16 chanspec; /* txpwr report for this channel */ -+ u16 local_chanspec; /* channel on which we are associated */ -+ u8 local_max; /* local max according to the AP */ -+ u8 local_constraint; /* local constraint according to the AP */ -+ s8 antgain[2]; /* Ant gain for each band - from SROM */ -+ u8 rf_cores; /* count of RF Cores being reported */ -+ u8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ -+ u8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain -+ * without adjustment */ -+ u8 est_Pout_cck; /* Latest CCK tx power out estimate */ -+ u8 tx_power_max[4]; /* Maximum target power among all rates */ -+ /* Index of the rate with the max target power */ -+ u8 tx_power_max_rate_ind[4]; -+ /* User limit */ -+ u8 user_limit[WL_TX_POWER_RATES]; -+ /* Regulatory power limit */ -+ u8 reg_limit[WL_TX_POWER_RATES]; -+ /* Max power board can support (SROM) */ -+ u8 board_limit[WL_TX_POWER_RATES]; -+ /* Latest target power */ -+ u8 target[WL_TX_POWER_RATES]; -+}; -+ -+struct tx_inst_power { -+ u8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ -+ u8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ -+}; -+ -+struct brcms_chanvec { -+ u8 vec[MAXCHANNEL / NBBY]; -+}; -+ -+struct shared_phy_params { -+ struct si_pub *sih; -+ struct phy_shim_info *physhim; -+ uint unit; -+ uint corerev; -+ uint buscorerev; -+ u16 vid; -+ u16 did; -+ uint chip; -+ uint chiprev; -+ uint chippkg; -+ uint sromrev; -+ uint boardtype; -+ uint boardrev; -+ uint boardvendor; -+ u32 boardflags; -+ u32 boardflags2; -+}; -+ -+ -+extern struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp); -+extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh, -+ struct d11regs __iomem *regs, -+ int bandtype, struct wiphy *wiphy); -+extern void wlc_phy_detach(struct brcms_phy_pub *ppi); -+ -+extern bool wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype, -+ u16 *phyrev, u16 *radioid, -+ u16 *radiover); -+extern bool wlc_phy_get_encore(struct brcms_phy_pub *pih); -+extern u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih); -+ -+extern void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *ppi, bool newstate); -+extern void wlc_phy_hw_state_upd(struct brcms_phy_pub *ppi, bool newstate); -+extern void wlc_phy_init(struct brcms_phy_pub *ppi, u16 chanspec); -+extern void wlc_phy_watchdog(struct brcms_phy_pub *ppi); -+extern int wlc_phy_down(struct brcms_phy_pub *ppi); -+extern u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih); -+extern void wlc_phy_cal_init(struct brcms_phy_pub *ppi); -+extern void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init); -+ -+extern void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, -+ u16 chanspec); -+extern u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi); -+extern void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, -+ u16 newch); -+extern u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi); -+extern void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw); -+ -+extern int wlc_phy_rssi_compute(struct brcms_phy_pub *pih, -+ struct d11rxhdr *rxh); -+extern void wlc_phy_por_inform(struct brcms_phy_pub *ppi); -+extern void wlc_phy_noise_sample_intr(struct brcms_phy_pub *ppi); -+extern bool wlc_phy_bist_check_phy(struct brcms_phy_pub *ppi); -+ -+extern void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag); -+ -+extern void wlc_phy_switch_radio(struct brcms_phy_pub *ppi, bool on); -+extern void wlc_phy_anacore(struct brcms_phy_pub *ppi, bool on); -+ -+ -+extern void wlc_phy_BSSinit(struct brcms_phy_pub *ppi, bool bonlyap, int rssi); -+ -+extern void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi, -+ bool wide_filter); -+extern void wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band, -+ struct brcms_chanvec *channels); -+extern u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, -+ uint band); -+ -+extern void wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint chan, -+ u8 *_min_, u8 *_max_, int rate); -+extern void wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, -+ uint chan, u8 *_max_, u8 *_min_); -+extern void wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi, -+ uint band, s32 *, s32 *, u32 *); -+extern void wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, -+ struct txpwr_limits *, -+ u16 chanspec); -+extern int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, -+ bool *override); -+extern int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, -+ bool override); -+extern void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi, -+ struct txpwr_limits *); -+extern bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi); -+extern void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, -+ bool hwpwrctrl); -+extern u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi); -+extern u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi); -+extern bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *pih); -+ -+extern void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, -+ u8 rxchain); -+extern void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, -+ u8 rxchain); -+extern void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, -+ u8 *rxchain); -+extern u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih); -+extern s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, -+ u16 chanspec); -+extern void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool val); -+ -+extern void wlc_phy_cal_perical(struct brcms_phy_pub *ppi, u8 reason); -+extern void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *ppi); -+extern void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock); -+extern void wlc_phy_cal_papd_recal(struct brcms_phy_pub *ppi); -+ -+extern void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val); -+extern void wlc_phy_clear_tssi(struct brcms_phy_pub *ppi); -+extern void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, u32 id, bool val); -+extern void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, u32 flags); -+ -+extern void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type); -+ -+extern void wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, -+ struct tx_power *power, uint channel); -+ -+extern void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal); -+extern bool wlc_phy_test_ison(struct brcms_phy_pub *ppi); -+extern void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, -+ u8 txpwr_percent); -+extern void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war); -+extern void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, -+ bool bf_preempt); -+extern void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap); -+ -+extern void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end); -+ -+extern void wlc_phy_freqtrack_start(struct brcms_phy_pub *ppi); -+extern void wlc_phy_freqtrack_end(struct brcms_phy_pub *ppi); -+ -+extern const u8 *wlc_phy_get_ofdm_rate_lookup(void); -+ -+extern s8 wlc_phy_get_tx_power_offset_by_mcs(struct brcms_phy_pub *ppi, -+ u8 mcs_offset); -+extern s8 wlc_phy_get_tx_power_offset(struct brcms_phy_pub *ppi, u8 tbl_offset); -+#endif /* _BRCM_PHY_HAL_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h.orig 2011-11-09 13:46:58.255800509 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h 2011-11-09 13:47:17.009566054 -0500 -@@ -0,0 +1,1169 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_PHY_INT_H_ -+#define _BRCM_PHY_INT_H_ -+ -+#include -+#include -+#include -+ -+#define PHY_VERSION { 1, 82, 8, 0 } -+ -+#define LCNXN_BASEREV 16 -+ -+struct phy_shim_info; -+ -+struct brcms_phy_srom_fem { -+ /* TSSI positive slope, 1: positive, 0: negative */ -+ u8 tssipos; -+ /* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */ -+ u8 extpagain; -+ /* support 32 combinations of different Pdet dynamic ranges */ -+ u8 pdetrange; -+ /* TR switch isolation */ -+ u8 triso; -+ /* antswctrl lookup table configuration: 32 possible choices */ -+ u8 antswctrllut; -+}; -+ -+#define ISNPHY(pi) PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_N) -+#define ISLCNPHY(pi) PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_LCN) -+ -+#define PHY_GET_RFATTN(rfgain) ((rfgain) & 0x0f) -+#define PHY_GET_PADMIX(rfgain) (((rfgain) & 0x10) >> 4) -+#define PHY_GET_RFGAINID(rfattn, padmix, width) ((rfattn) + ((padmix)*(width))) -+#define PHY_SAT(x, n) ((x) > ((1<<((n)-1))-1) ? ((1<<((n)-1))-1) : \ -+ ((x) < -(1<<((n)-1)) ? -(1<<((n)-1)) : (x))) -+#define PHY_SHIFT_ROUND(x, n) ((x) >= 0 ? ((x)+(1<<((n)-1)))>>(n) : (x)>>(n)) -+#define PHY_HW_ROUND(x, s) ((x >> s) + ((x >> (s-1)) & (s != 0))) -+ -+#define CH_5G_GROUP 3 -+#define A_LOW_CHANS 0 -+#define A_MID_CHANS 1 -+#define A_HIGH_CHANS 2 -+#define CH_2G_GROUP 1 -+#define G_ALL_CHANS 0 -+ -+#define FIRST_REF5_CHANNUM 149 -+#define LAST_REF5_CHANNUM 165 -+#define FIRST_5G_CHAN 14 -+#define LAST_5G_CHAN 50 -+#define FIRST_MID_5G_CHAN 14 -+#define LAST_MID_5G_CHAN 35 -+#define FIRST_HIGH_5G_CHAN 36 -+#define LAST_HIGH_5G_CHAN 41 -+#define FIRST_LOW_5G_CHAN 42 -+#define LAST_LOW_5G_CHAN 50 -+ -+#define BASE_LOW_5G_CHAN 4900 -+#define BASE_MID_5G_CHAN 5100 -+#define BASE_HIGH_5G_CHAN 5500 -+ -+#define CHAN5G_FREQ(chan) (5000 + chan*5) -+#define CHAN2G_FREQ(chan) (2407 + chan*5) -+ -+#define TXP_FIRST_CCK 0 -+#define TXP_LAST_CCK 3 -+#define TXP_FIRST_OFDM 4 -+#define TXP_LAST_OFDM 11 -+#define TXP_FIRST_OFDM_20_CDD 12 -+#define TXP_LAST_OFDM_20_CDD 19 -+#define TXP_FIRST_MCS_20_SISO 20 -+#define TXP_LAST_MCS_20_SISO 27 -+#define TXP_FIRST_MCS_20_CDD 28 -+#define TXP_LAST_MCS_20_CDD 35 -+#define TXP_FIRST_MCS_20_STBC 36 -+#define TXP_LAST_MCS_20_STBC 43 -+#define TXP_FIRST_MCS_20_SDM 44 -+#define TXP_LAST_MCS_20_SDM 51 -+#define TXP_FIRST_OFDM_40_SISO 52 -+#define TXP_LAST_OFDM_40_SISO 59 -+#define TXP_FIRST_OFDM_40_CDD 60 -+#define TXP_LAST_OFDM_40_CDD 67 -+#define TXP_FIRST_MCS_40_SISO 68 -+#define TXP_LAST_MCS_40_SISO 75 -+#define TXP_FIRST_MCS_40_CDD 76 -+#define TXP_LAST_MCS_40_CDD 83 -+#define TXP_FIRST_MCS_40_STBC 84 -+#define TXP_LAST_MCS_40_STBC 91 -+#define TXP_FIRST_MCS_40_SDM 92 -+#define TXP_LAST_MCS_40_SDM 99 -+#define TXP_MCS_32 100 -+#define TXP_NUM_RATES 101 -+#define ADJ_PWR_TBL_LEN 84 -+ -+#define TXP_FIRST_SISO_MCS_20 20 -+#define TXP_LAST_SISO_MCS_20 27 -+ -+#define PHY_CORE_NUM_1 1 -+#define PHY_CORE_NUM_2 2 -+#define PHY_CORE_NUM_3 3 -+#define PHY_CORE_NUM_4 4 -+#define PHY_CORE_MAX PHY_CORE_NUM_4 -+#define PHY_CORE_0 0 -+#define PHY_CORE_1 1 -+#define PHY_CORE_2 2 -+#define PHY_CORE_3 3 -+ -+#define MA_WINDOW_SZ 8 -+ -+#define PHY_NOISE_SAMPLE_MON 1 -+#define PHY_NOISE_SAMPLE_EXTERNAL 2 -+#define PHY_NOISE_WINDOW_SZ 16 -+#define PHY_NOISE_GLITCH_INIT_MA 10 -+#define PHY_NOISE_GLITCH_INIT_MA_BADPlCP 10 -+#define PHY_NOISE_STATE_MON 0x1 -+#define PHY_NOISE_STATE_EXTERNAL 0x2 -+#define PHY_NOISE_SAMPLE_LOG_NUM_NPHY 10 -+#define PHY_NOISE_SAMPLE_LOG_NUM_UCODE 9 -+ -+#define PHY_NOISE_OFFSETFACT_4322 (-103) -+#define PHY_NOISE_MA_WINDOW_SZ 2 -+ -+#define PHY_RSSI_TABLE_SIZE 64 -+#define RSSI_ANT_MERGE_MAX 0 -+#define RSSI_ANT_MERGE_MIN 1 -+#define RSSI_ANT_MERGE_AVG 2 -+ -+#define PHY_TSSI_TABLE_SIZE 64 -+#define APHY_TSSI_TABLE_SIZE 256 -+#define TX_GAIN_TABLE_LENGTH 64 -+#define DEFAULT_11A_TXP_IDX 24 -+#define NUM_TSSI_FRAMES 4 -+#define NULL_TSSI 0x7f -+#define NULL_TSSI_W 0x7f7f -+ -+#define PHY_PAPD_EPS_TBL_SIZE_LCNPHY 64 -+ -+#define LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL 9 -+ -+#define PHY_TXPWR_MIN 10 -+#define PHY_TXPWR_MIN_NPHY 8 -+#define RADIOPWR_OVERRIDE_DEF (-1) -+ -+#define PWRTBL_NUM_COEFF 3 -+ -+#define SPURAVOID_DISABLE 0 -+#define SPURAVOID_AUTO 1 -+#define SPURAVOID_FORCEON 2 -+#define SPURAVOID_FORCEON2 3 -+ -+#define PHY_SW_TIMER_FAST 15 -+#define PHY_SW_TIMER_SLOW 60 -+#define PHY_SW_TIMER_GLACIAL 120 -+ -+#define PHY_PERICAL_AUTO 0 -+#define PHY_PERICAL_FULL 1 -+#define PHY_PERICAL_PARTIAL 2 -+ -+#define PHY_PERICAL_NODELAY 0 -+#define PHY_PERICAL_INIT_DELAY 5 -+#define PHY_PERICAL_ASSOC_DELAY 5 -+#define PHY_PERICAL_WDOG_DELAY 5 -+ -+#define MPHASE_TXCAL_NUMCMDS 2 -+ -+#define PHY_PERICAL_MPHASE_PENDING(pi) \ -+ (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_IDLE) -+ -+enum { -+ MPHASE_CAL_STATE_IDLE = 0, -+ MPHASE_CAL_STATE_INIT = 1, -+ MPHASE_CAL_STATE_TXPHASE0, -+ MPHASE_CAL_STATE_TXPHASE1, -+ MPHASE_CAL_STATE_TXPHASE2, -+ MPHASE_CAL_STATE_TXPHASE3, -+ MPHASE_CAL_STATE_TXPHASE4, -+ MPHASE_CAL_STATE_TXPHASE5, -+ MPHASE_CAL_STATE_PAPDCAL, -+ MPHASE_CAL_STATE_RXCAL, -+ MPHASE_CAL_STATE_RSSICAL, -+ MPHASE_CAL_STATE_IDLETSSI -+}; -+ -+enum phy_cal_mode { -+ CAL_FULL, -+ CAL_RECAL, -+ CAL_CURRECAL, -+ CAL_DIGCAL, -+ CAL_GCTRL, -+ CAL_SOFT, -+ CAL_DIGLO -+}; -+ -+#define RDR_NTIERS 1 -+#define RDR_TIER_SIZE 64 -+#define RDR_LIST_SIZE (512/3) -+#define RDR_EPOCH_SIZE 40 -+#define RDR_NANTENNAS 2 -+#define RDR_NTIER_SIZE RDR_LIST_SIZE -+#define RDR_LP_BUFFER_SIZE 64 -+#define LP_LEN_HIS_SIZE 10 -+ -+#define STATIC_NUM_RF 32 -+#define STATIC_NUM_BB 9 -+ -+#define BB_MULT_MASK 0x0000ffff -+#define BB_MULT_VALID_MASK 0x80000000 -+ -+#define CORDIC_AG 39797 -+#define CORDIC_NI 18 -+#define FIXED(X) ((s32)((X) << 16)) -+ -+#define FLOAT(X) \ -+ (((X) >= 0) ? ((((X) >> 15) + 1) >> 1) : -((((-(X)) >> 15) + 1) >> 1)) -+ -+#define PHY_CHAIN_TX_DISABLE_TEMP 115 -+#define PHY_HYSTERESIS_DELTATEMP 5 -+ -+#define SCAN_INPROG_PHY(pi) \ -+ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN)) -+ -+#define PLT_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_PLT)) -+ -+#define ASSOC_INPROG_PHY(pi) \ -+ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_ASSOC)) -+ -+#define SCAN_RM_IN_PROGRESS(pi) \ -+ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN | PHY_HOLD_FOR_RM)) -+ -+#define PHY_MUTED(pi) \ -+ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_MUTE)) -+ -+#define PUB_NOT_ASSOC(pi) \ -+ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_NOT_ASSOC)) -+ -+struct phy_table_info { -+ uint table; -+ int q; -+ uint max; -+}; -+ -+struct phytbl_info { -+ const void *tbl_ptr; -+ u32 tbl_len; -+ u32 tbl_id; -+ u32 tbl_offset; -+ u32 tbl_width; -+}; -+ -+struct interference_info { -+ u8 curr_home_channel; -+ u16 crsminpwrthld_40_stored; -+ u16 crsminpwrthld_20L_stored; -+ u16 crsminpwrthld_20U_stored; -+ u16 init_gain_code_core1_stored; -+ u16 init_gain_code_core2_stored; -+ u16 init_gain_codeb_core1_stored; -+ u16 init_gain_codeb_core2_stored; -+ u16 init_gain_table_stored[4]; -+ -+ u16 clip1_hi_gain_code_core1_stored; -+ u16 clip1_hi_gain_code_core2_stored; -+ u16 clip1_hi_gain_codeb_core1_stored; -+ u16 clip1_hi_gain_codeb_core2_stored; -+ u16 nb_clip_thresh_core1_stored; -+ u16 nb_clip_thresh_core2_stored; -+ u16 init_ofdmlna2gainchange_stored[4]; -+ u16 init_ccklna2gainchange_stored[4]; -+ u16 clip1_lo_gain_code_core1_stored; -+ u16 clip1_lo_gain_code_core2_stored; -+ u16 clip1_lo_gain_codeb_core1_stored; -+ u16 clip1_lo_gain_codeb_core2_stored; -+ u16 w1_clip_thresh_core1_stored; -+ u16 w1_clip_thresh_core2_stored; -+ u16 radio_2056_core1_rssi_gain_stored; -+ u16 radio_2056_core2_rssi_gain_stored; -+ u16 energy_drop_timeout_len_stored; -+ -+ u16 ed_crs40_assertthld0_stored; -+ u16 ed_crs40_assertthld1_stored; -+ u16 ed_crs40_deassertthld0_stored; -+ u16 ed_crs40_deassertthld1_stored; -+ u16 ed_crs20L_assertthld0_stored; -+ u16 ed_crs20L_assertthld1_stored; -+ u16 ed_crs20L_deassertthld0_stored; -+ u16 ed_crs20L_deassertthld1_stored; -+ u16 ed_crs20U_assertthld0_stored; -+ u16 ed_crs20U_assertthld1_stored; -+ u16 ed_crs20U_deassertthld0_stored; -+ u16 ed_crs20U_deassertthld1_stored; -+ -+ u16 badplcp_ma; -+ u16 badplcp_ma_previous; -+ u16 badplcp_ma_total; -+ u16 badplcp_ma_list[MA_WINDOW_SZ]; -+ int badplcp_ma_index; -+ s16 pre_badplcp_cnt; -+ s16 bphy_pre_badplcp_cnt; -+ -+ u16 init_gain_core1; -+ u16 init_gain_core2; -+ u16 init_gainb_core1; -+ u16 init_gainb_core2; -+ u16 init_gain_rfseq[4]; -+ -+ u16 crsminpwr0; -+ u16 crsminpwrl0; -+ u16 crsminpwru0; -+ -+ s16 crsminpwr_index; -+ -+ u16 radio_2057_core1_rssi_wb1a_gc_stored; -+ u16 radio_2057_core2_rssi_wb1a_gc_stored; -+ u16 radio_2057_core1_rssi_wb1g_gc_stored; -+ u16 radio_2057_core2_rssi_wb1g_gc_stored; -+ u16 radio_2057_core1_rssi_wb2_gc_stored; -+ u16 radio_2057_core2_rssi_wb2_gc_stored; -+ u16 radio_2057_core1_rssi_nb_gc_stored; -+ u16 radio_2057_core2_rssi_nb_gc_stored; -+}; -+ -+struct aci_save_gphy { -+ u16 rc_cal_ovr; -+ u16 phycrsth1; -+ u16 phycrsth2; -+ u16 init_n1p1_gain; -+ u16 p1_p2_gain; -+ u16 n1_n2_gain; -+ u16 n1_p1_gain; -+ u16 div_search_gain; -+ u16 div_p1_p2_gain; -+ u16 div_search_gn_change; -+ u16 table_7_2; -+ u16 table_7_3; -+ u16 cckshbits_gnref; -+ u16 clip_thresh; -+ u16 clip2_thresh; -+ u16 clip3_thresh; -+ u16 clip_p2_thresh; -+ u16 clip_pwdn_thresh; -+ u16 clip_n1p1_thresh; -+ u16 clip_n1_pwdn_thresh; -+ u16 bbconfig; -+ u16 cthr_sthr_shdin; -+ u16 energy; -+ u16 clip_p1_p2_thresh; -+ u16 threshold; -+ u16 reg15; -+ u16 reg16; -+ u16 reg17; -+ u16 div_srch_idx; -+ u16 div_srch_p1_p2; -+ u16 div_srch_gn_back; -+ u16 ant_dwell; -+ u16 ant_wr_settle; -+}; -+ -+struct lo_complex_abgphy_info { -+ s8 i; -+ s8 q; -+}; -+ -+struct nphy_iq_comp { -+ s16 a0; -+ s16 b0; -+ s16 a1; -+ s16 b1; -+}; -+ -+struct nphy_txpwrindex { -+ s8 index; -+ s8 index_internal; -+ s8 index_internal_save; -+ u16 AfectrlOverride; -+ u16 AfeCtrlDacGain; -+ u16 rad_gain; -+ u8 bbmult; -+ u16 iqcomp_a; -+ u16 iqcomp_b; -+ u16 locomp; -+}; -+ -+struct txiqcal_cache { -+ -+ u16 txcal_coeffs_2G[8]; -+ u16 txcal_radio_regs_2G[8]; -+ struct nphy_iq_comp rxcal_coeffs_2G; -+ -+ u16 txcal_coeffs_5G[8]; -+ u16 txcal_radio_regs_5G[8]; -+ struct nphy_iq_comp rxcal_coeffs_5G; -+}; -+ -+struct nphy_pwrctrl { -+ s8 max_pwr_2g; -+ s8 idle_targ_2g; -+ s16 pwrdet_2g_a1; -+ s16 pwrdet_2g_b0; -+ s16 pwrdet_2g_b1; -+ s8 max_pwr_5gm; -+ s8 idle_targ_5gm; -+ s8 max_pwr_5gh; -+ s8 max_pwr_5gl; -+ s16 pwrdet_5gm_a1; -+ s16 pwrdet_5gm_b0; -+ s16 pwrdet_5gm_b1; -+ s16 pwrdet_5gl_a1; -+ s16 pwrdet_5gl_b0; -+ s16 pwrdet_5gl_b1; -+ s16 pwrdet_5gh_a1; -+ s16 pwrdet_5gh_b0; -+ s16 pwrdet_5gh_b1; -+ s8 idle_targ_5gl; -+ s8 idle_targ_5gh; -+ s8 idle_tssi_2g; -+ s8 idle_tssi_5g; -+ s8 idle_tssi; -+ s16 a1; -+ s16 b0; -+ s16 b1; -+}; -+ -+struct nphy_txgains { -+ u16 txlpf[2]; -+ u16 txgm[2]; -+ u16 pga[2]; -+ u16 pad[2]; -+ u16 ipa[2]; -+}; -+ -+#define PHY_NOISEVAR_BUFSIZE 10 -+ -+struct nphy_noisevar_buf { -+ int bufcount; -+ int tone_id[PHY_NOISEVAR_BUFSIZE]; -+ u32 noise_vars[PHY_NOISEVAR_BUFSIZE]; -+ u32 min_noise_vars[PHY_NOISEVAR_BUFSIZE]; -+}; -+ -+struct rssical_cache { -+ u16 rssical_radio_regs_2G[2]; -+ u16 rssical_phyregs_2G[12]; -+ -+ u16 rssical_radio_regs_5G[2]; -+ u16 rssical_phyregs_5G[12]; -+}; -+ -+struct lcnphy_cal_results { -+ -+ u16 txiqlocal_a; -+ u16 txiqlocal_b; -+ u16 txiqlocal_didq; -+ u8 txiqlocal_ei0; -+ u8 txiqlocal_eq0; -+ u8 txiqlocal_fi0; -+ u8 txiqlocal_fq0; -+ -+ u16 txiqlocal_bestcoeffs[11]; -+ u16 txiqlocal_bestcoeffs_valid; -+ -+ u32 papd_eps_tbl[PHY_PAPD_EPS_TBL_SIZE_LCNPHY]; -+ u16 analog_gain_ref; -+ u16 lut_begin; -+ u16 lut_end; -+ u16 lut_step; -+ u16 rxcompdbm; -+ u16 papdctrl; -+ u16 sslpnCalibClkEnCtrl; -+ -+ u16 rxiqcal_coeff_a0; -+ u16 rxiqcal_coeff_b0; -+}; -+ -+struct shared_phy { -+ struct brcms_phy *phy_head; -+ uint unit; -+ struct si_pub *sih; -+ struct phy_shim_info *physhim; -+ uint corerev; -+ u32 machwcap; -+ bool up; -+ bool clk; -+ uint now; -+ u16 vid; -+ u16 did; -+ uint chip; -+ uint chiprev; -+ uint chippkg; -+ uint sromrev; -+ uint boardtype; -+ uint boardrev; -+ uint boardvendor; -+ u32 boardflags; -+ u32 boardflags2; -+ uint buscorerev; -+ uint fast_timer; -+ uint slow_timer; -+ uint glacial_timer; -+ u8 rx_antdiv; -+ s8 phy_noise_window[MA_WINDOW_SZ]; -+ uint phy_noise_index; -+ u8 hw_phytxchain; -+ u8 hw_phyrxchain; -+ u8 phytxchain; -+ u8 phyrxchain; -+ u8 rssi_mode; -+ bool _rifs_phy; -+}; -+ -+struct brcms_phy_pub { -+ uint phy_type; -+ uint phy_rev; -+ u8 phy_corenum; -+ u16 radioid; -+ u8 radiorev; -+ u8 radiover; -+ -+ uint coreflags; -+ uint ana_rev; -+ bool abgphy_encore; -+}; -+ -+struct phy_func_ptr { -+ void (*init)(struct brcms_phy *); -+ void (*calinit)(struct brcms_phy *); -+ void (*chanset)(struct brcms_phy *, u16 chanspec); -+ void (*txpwrrecalc)(struct brcms_phy *); -+ int (*longtrn)(struct brcms_phy *, int); -+ void (*txiqccget)(struct brcms_phy *, u16 *, u16 *); -+ void (*txiqccset)(struct brcms_phy *, u16, u16); -+ u16 (*txloccget)(struct brcms_phy *); -+ void (*radioloftget)(struct brcms_phy *, u8 *, u8 *, u8 *, u8 *); -+ void (*carrsuppr)(struct brcms_phy *); -+ s32 (*rxsigpwr)(struct brcms_phy *, s32); -+ void (*detach)(struct brcms_phy *); -+}; -+ -+struct brcms_phy { -+ struct brcms_phy_pub pubpi_ro; -+ struct shared_phy *sh; -+ struct phy_func_ptr pi_fptr; -+ -+ union { -+ struct brcms_phy_lcnphy *pi_lcnphy; -+ } u; -+ bool user_txpwr_at_rfport; -+ -+ struct d11regs __iomem *regs; -+ struct brcms_phy *next; -+ struct brcms_phy_pub pubpi; -+ -+ bool do_initcal; -+ bool phytest_on; -+ bool ofdm_rateset_war; -+ bool bf_preempt_4306; -+ u16 radio_chanspec; -+ u8 antsel_type; -+ u16 bw; -+ u8 txpwr_percent; -+ bool phy_init_por; -+ -+ bool init_in_progress; -+ bool initialized; -+ bool sbtml_gm; -+ uint refcnt; -+ bool watchdog_override; -+ u8 phynoise_state; -+ uint phynoise_now; -+ int phynoise_chan_watchdog; -+ bool phynoise_polling; -+ bool disable_percal; -+ u32 measure_hold; -+ -+ s16 txpa_2g[PWRTBL_NUM_COEFF]; -+ s16 txpa_2g_low_temp[PWRTBL_NUM_COEFF]; -+ s16 txpa_2g_high_temp[PWRTBL_NUM_COEFF]; -+ s16 txpa_5g_low[PWRTBL_NUM_COEFF]; -+ s16 txpa_5g_mid[PWRTBL_NUM_COEFF]; -+ s16 txpa_5g_hi[PWRTBL_NUM_COEFF]; -+ -+ u8 tx_srom_max_2g; -+ u8 tx_srom_max_5g_low; -+ u8 tx_srom_max_5g_mid; -+ u8 tx_srom_max_5g_hi; -+ u8 tx_srom_max_rate_2g[TXP_NUM_RATES]; -+ u8 tx_srom_max_rate_5g_low[TXP_NUM_RATES]; -+ u8 tx_srom_max_rate_5g_mid[TXP_NUM_RATES]; -+ u8 tx_srom_max_rate_5g_hi[TXP_NUM_RATES]; -+ u8 tx_user_target[TXP_NUM_RATES]; -+ s8 tx_power_offset[TXP_NUM_RATES]; -+ u8 tx_power_target[TXP_NUM_RATES]; -+ -+ struct brcms_phy_srom_fem srom_fem2g; -+ struct brcms_phy_srom_fem srom_fem5g; -+ -+ u8 tx_power_max; -+ u8 tx_power_max_rate_ind; -+ bool hwpwrctrl; -+ u8 nphy_txpwrctrl; -+ s8 nphy_txrx_chain; -+ bool phy_5g_pwrgain; -+ -+ u16 phy_wreg; -+ u16 phy_wreg_limit; -+ -+ s8 n_preamble_override; -+ u8 antswitch; -+ u8 aa2g, aa5g; -+ -+ s8 idle_tssi[CH_5G_GROUP]; -+ s8 target_idle_tssi; -+ s8 txpwr_est_Pout; -+ u8 tx_power_min; -+ u8 txpwr_limit[TXP_NUM_RATES]; -+ u8 txpwr_env_limit[TXP_NUM_RATES]; -+ u8 adj_pwr_tbl_nphy[ADJ_PWR_TBL_LEN]; -+ -+ bool channel_14_wide_filter; -+ -+ bool txpwroverride; -+ bool txpwridx_override_aphy; -+ s16 radiopwr_override; -+ u16 hwpwr_txcur; -+ u8 saved_txpwr_idx; -+ -+ bool edcrs_threshold_lock; -+ -+ u32 tr_R_gain_val; -+ u32 tr_T_gain_val; -+ -+ s16 ofdm_analog_filt_bw_override; -+ s16 cck_analog_filt_bw_override; -+ s16 ofdm_rccal_override; -+ s16 cck_rccal_override; -+ u16 extlna_type; -+ -+ uint interference_mode_crs_time; -+ u16 crsglitch_prev; -+ bool interference_mode_crs; -+ -+ u32 phy_tx_tone_freq; -+ uint phy_lastcal; -+ bool phy_forcecal; -+ bool phy_fixed_noise; -+ u32 xtalfreq; -+ u8 pdiv; -+ s8 carrier_suppr_disable; -+ -+ bool phy_bphy_evm; -+ bool phy_bphy_rfcs; -+ s8 phy_scraminit; -+ u8 phy_gpiosel; -+ -+ s16 phy_txcore_disable_temp; -+ s16 phy_txcore_enable_temp; -+ s8 phy_tempsense_offset; -+ bool phy_txcore_heatedup; -+ -+ u16 radiopwr; -+ u16 bb_atten; -+ u16 txctl1; -+ -+ u16 mintxbias; -+ u16 mintxmag; -+ struct lo_complex_abgphy_info gphy_locomp_iq -+ [STATIC_NUM_RF][STATIC_NUM_BB]; -+ s8 stats_11b_txpower[STATIC_NUM_RF][STATIC_NUM_BB]; -+ u16 gain_table[TX_GAIN_TABLE_LENGTH]; -+ bool loopback_gain; -+ s16 max_lpback_gain_hdB; -+ s16 trsw_rx_gain_hdB; -+ u8 power_vec[8]; -+ -+ u16 rc_cal; -+ int nrssi_table_delta; -+ int nrssi_slope_scale; -+ int nrssi_slope_offset; -+ int min_rssi; -+ int max_rssi; -+ -+ s8 txpwridx; -+ u8 min_txpower; -+ -+ u8 a_band_high_disable; -+ -+ u16 tx_vos; -+ u16 global_tx_bb_dc_bias_loft; -+ -+ int rf_max; -+ int bb_max; -+ int rf_list_size; -+ int bb_list_size; -+ u16 *rf_attn_list; -+ u16 *bb_attn_list; -+ u16 padmix_mask; -+ u16 padmix_reg; -+ u16 *txmag_list; -+ uint txmag_len; -+ bool txmag_enable; -+ -+ s8 *a_tssi_to_dbm; -+ s8 *m_tssi_to_dbm; -+ s8 *l_tssi_to_dbm; -+ s8 *h_tssi_to_dbm; -+ u8 *hwtxpwr; -+ -+ u16 freqtrack_saved_regs[2]; -+ int cur_interference_mode; -+ bool hwpwrctrl_capable; -+ bool temppwrctrl_capable; -+ -+ uint phycal_nslope; -+ uint phycal_noffset; -+ uint phycal_mlo; -+ uint phycal_txpower; -+ -+ u8 phy_aa2g; -+ -+ bool nphy_tableloaded; -+ s8 nphy_rssisel; -+ u32 nphy_bb_mult_save; -+ u16 nphy_txiqlocal_bestc[11]; -+ bool nphy_txiqlocal_coeffsvalid; -+ struct nphy_txpwrindex nphy_txpwrindex[PHY_CORE_NUM_2]; -+ struct nphy_pwrctrl nphy_pwrctrl_info[PHY_CORE_NUM_2]; -+ u16 cck2gpo; -+ u32 ofdm2gpo; -+ u32 ofdm5gpo; -+ u32 ofdm5glpo; -+ u32 ofdm5ghpo; -+ u8 bw402gpo; -+ u8 bw405gpo; -+ u8 bw405glpo; -+ u8 bw405ghpo; -+ u8 cdd2gpo; -+ u8 cdd5gpo; -+ u8 cdd5glpo; -+ u8 cdd5ghpo; -+ u8 stbc2gpo; -+ u8 stbc5gpo; -+ u8 stbc5glpo; -+ u8 stbc5ghpo; -+ u8 bwdup2gpo; -+ u8 bwdup5gpo; -+ u8 bwdup5glpo; -+ u8 bwdup5ghpo; -+ u16 mcs2gpo[8]; -+ u16 mcs5gpo[8]; -+ u16 mcs5glpo[8]; -+ u16 mcs5ghpo[8]; -+ u32 nphy_rxcalparams; -+ -+ u8 phy_spuravoid; -+ bool phy_isspuravoid; -+ -+ u8 phy_pabias; -+ u8 nphy_papd_skip; -+ u8 nphy_tssi_slope; -+ -+ s16 nphy_noise_win[PHY_CORE_MAX][PHY_NOISE_WINDOW_SZ]; -+ u8 nphy_noise_index; -+ -+ u8 nphy_txpid2g[PHY_CORE_NUM_2]; -+ u8 nphy_txpid5g[PHY_CORE_NUM_2]; -+ u8 nphy_txpid5gl[PHY_CORE_NUM_2]; -+ u8 nphy_txpid5gh[PHY_CORE_NUM_2]; -+ -+ bool nphy_gain_boost; -+ bool nphy_elna_gain_config; -+ u16 old_bphy_test; -+ u16 old_bphy_testcontrol; -+ -+ bool phyhang_avoid; -+ -+ bool rssical_nphy; -+ u8 nphy_perical; -+ uint nphy_perical_last; -+ u8 cal_type_override; -+ u8 mphase_cal_phase_id; -+ u8 mphase_txcal_cmdidx; -+ u8 mphase_txcal_numcmds; -+ u16 mphase_txcal_bestcoeffs[11]; -+ u16 nphy_txiqlocal_chanspec; -+ u16 nphy_iqcal_chanspec_2G; -+ u16 nphy_iqcal_chanspec_5G; -+ u16 nphy_rssical_chanspec_2G; -+ u16 nphy_rssical_chanspec_5G; -+ struct wlapi_timer *phycal_timer; -+ bool use_int_tx_iqlo_cal_nphy; -+ bool internal_tx_iqlo_cal_tapoff_intpa_nphy; -+ s16 nphy_lastcal_temp; -+ -+ struct txiqcal_cache calibration_cache; -+ struct rssical_cache rssical_cache; -+ -+ u8 nphy_txpwr_idx[2]; -+ u8 nphy_papd_cal_type; -+ uint nphy_papd_last_cal; -+ u16 nphy_papd_tx_gain_at_last_cal[2]; -+ u8 nphy_papd_cal_gain_index[2]; -+ s16 nphy_papd_epsilon_offset[2]; -+ bool nphy_papd_recal_enable; -+ u32 nphy_papd_recal_counter; -+ bool nphy_force_papd_cal; -+ bool nphy_papdcomp; -+ bool ipa2g_on; -+ bool ipa5g_on; -+ -+ u16 classifier_state; -+ u16 clip_state[2]; -+ uint nphy_deaf_count; -+ u8 rxiq_samps; -+ u8 rxiq_antsel; -+ -+ u16 rfctrlIntc1_save; -+ u16 rfctrlIntc2_save; -+ bool first_cal_after_assoc; -+ u16 tx_rx_cal_radio_saveregs[22]; -+ u16 tx_rx_cal_phy_saveregs[15]; -+ -+ u8 nphy_cal_orig_pwr_idx[2]; -+ u8 nphy_txcal_pwr_idx[2]; -+ u8 nphy_rxcal_pwr_idx[2]; -+ u16 nphy_cal_orig_tx_gain[2]; -+ struct nphy_txgains nphy_cal_target_gain; -+ u16 nphy_txcal_bbmult; -+ u16 nphy_gmval; -+ -+ u16 nphy_saved_bbconf; -+ -+ bool nphy_gband_spurwar_en; -+ bool nphy_gband_spurwar2_en; -+ bool nphy_aband_spurwar_en; -+ u16 nphy_rccal_value; -+ u16 nphy_crsminpwr[3]; -+ struct nphy_noisevar_buf nphy_saved_noisevars; -+ bool nphy_anarxlpf_adjusted; -+ bool nphy_crsminpwr_adjusted; -+ bool nphy_noisevars_adjusted; -+ -+ bool nphy_rxcal_active; -+ u16 radar_percal_mask; -+ bool dfs_lp_buffer_nphy; -+ -+ u16 nphy_fineclockgatecontrol; -+ -+ s8 rx2tx_biasentry; -+ -+ u16 crsminpwr0; -+ u16 crsminpwrl0; -+ u16 crsminpwru0; -+ s16 noise_crsminpwr_index; -+ u16 init_gain_core1; -+ u16 init_gain_core2; -+ u16 init_gainb_core1; -+ u16 init_gainb_core2; -+ u8 aci_noise_curr_channel; -+ u16 init_gain_rfseq[4]; -+ -+ bool radio_is_on; -+ -+ bool nphy_sample_play_lpf_bw_ctl_ovr; -+ -+ u16 tbl_data_hi; -+ u16 tbl_data_lo; -+ u16 tbl_addr; -+ -+ uint tbl_save_id; -+ uint tbl_save_offset; -+ -+ u8 txpwrctrl; -+ s8 txpwrindex[PHY_CORE_MAX]; -+ -+ u8 phycal_tempdelta; -+ u32 mcs20_po; -+ u32 mcs40_po; -+ struct wiphy *wiphy; -+}; -+ -+struct cs32 { -+ s32 q; -+ s32 i; -+}; -+ -+struct radio_regs { -+ u16 address; -+ u32 init_a; -+ u32 init_g; -+ u8 do_init_a; -+ u8 do_init_g; -+}; -+ -+struct radio_20xx_regs { -+ u16 address; -+ u8 init; -+ u8 do_init; -+}; -+ -+struct lcnphy_radio_regs { -+ u16 address; -+ u8 init_a; -+ u8 init_g; -+ u8 do_init_a; -+ u8 do_init_g; -+}; -+ -+extern u16 read_phy_reg(struct brcms_phy *pi, u16 addr); -+extern void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val); -+extern void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val); -+extern void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val); -+extern void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val); -+ -+extern u16 read_radio_reg(struct brcms_phy *pi, u16 addr); -+extern void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val); -+extern void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val); -+extern void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, -+ u16 val); -+extern void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask); -+ -+extern void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val); -+ -+extern void wlc_phyreg_enter(struct brcms_phy_pub *pih); -+extern void wlc_phyreg_exit(struct brcms_phy_pub *pih); -+extern void wlc_radioreg_enter(struct brcms_phy_pub *pih); -+extern void wlc_radioreg_exit(struct brcms_phy_pub *pih); -+ -+extern void wlc_phy_read_table(struct brcms_phy *pi, -+ const struct phytbl_info *ptbl_info, -+ u16 tblAddr, u16 tblDataHi, -+ u16 tblDatalo); -+extern void wlc_phy_write_table(struct brcms_phy *pi, -+ const struct phytbl_info *ptbl_info, -+ u16 tblAddr, u16 tblDataHi, u16 tblDatalo); -+extern void wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, -+ uint tbl_offset, u16 tblAddr, u16 tblDataHi, -+ u16 tblDataLo); -+extern void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val); -+ -+extern void write_phy_channel_reg(struct brcms_phy *pi, uint val); -+extern void wlc_phy_txpower_update_shm(struct brcms_phy *pi); -+ -+extern u8 wlc_phy_nbits(s32 value); -+extern void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_dB, u8 core); -+ -+extern uint wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi, -+ struct radio_20xx_regs *radioregs); -+extern uint wlc_phy_init_radio_regs(struct brcms_phy *pi, -+ const struct radio_regs *radioregs, -+ u16 core_offset); -+ -+extern void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi); -+ -+extern void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on); -+extern void wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, -+ s32 *eps_imag); -+ -+extern void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi); -+extern void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi); -+ -+extern bool wlc_phy_attach_nphy(struct brcms_phy *pi); -+extern bool wlc_phy_attach_lcnphy(struct brcms_phy *pi); -+ -+extern void wlc_phy_detach_lcnphy(struct brcms_phy *pi); -+ -+extern void wlc_phy_init_nphy(struct brcms_phy *pi); -+extern void wlc_phy_init_lcnphy(struct brcms_phy *pi); -+ -+extern void wlc_phy_cal_init_nphy(struct brcms_phy *pi); -+extern void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi); -+ -+extern void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, -+ u16 chanspec); -+extern void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, -+ u16 chanspec); -+extern void wlc_phy_chanspec_set_fixup_lcnphy(struct brcms_phy *pi, -+ u16 chanspec); -+extern int wlc_phy_channel2freq(uint channel); -+extern int wlc_phy_chanspec_freq2bandrange_lpssn(uint); -+extern int wlc_phy_chanspec_bandrange_get(struct brcms_phy *, u16 chanspec); -+ -+extern void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode); -+extern s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi); -+ -+extern void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi); -+extern void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi); -+extern void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi); -+ -+extern void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index); -+extern void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable); -+extern void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi); -+extern void wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, -+ u16 max_val, bool iqcalmode); -+ -+extern void wlc_phy_txpower_sromlimit_get_nphy(struct brcms_phy *pi, uint chan, -+ u8 *max_pwr, u8 rate_id); -+extern void wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start, -+ u8 rate_mcs_end, -+ u8 rate_ofdm_start); -+extern void wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power, -+ u8 rate_ofdm_start, -+ u8 rate_ofdm_end, -+ u8 rate_mcs_start); -+ -+extern u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode); -+extern s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode); -+extern s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode); -+extern s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode); -+extern void wlc_phy_carrier_suppress_lcnphy(struct brcms_phy *pi); -+extern void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel); -+extern void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode); -+extern void wlc_2064_vco_cal(struct brcms_phy *pi); -+ -+extern void wlc_phy_txpower_recalc_target(struct brcms_phy *pi); -+ -+#define LCNPHY_TBL_ID_PAPDCOMPDELTATBL 0x18 -+#define LCNPHY_TX_POWER_TABLE_SIZE 128 -+#define LCNPHY_MAX_TX_POWER_INDEX (LCNPHY_TX_POWER_TABLE_SIZE - 1) -+#define LCNPHY_TBL_ID_TXPWRCTL 0x07 -+#define LCNPHY_TX_PWR_CTRL_OFF 0 -+#define LCNPHY_TX_PWR_CTRL_SW (0x1 << 15) -+#define LCNPHY_TX_PWR_CTRL_HW ((0x1 << 15) | \ -+ (0x1 << 14) | \ -+ (0x1 << 13)) -+ -+#define LCNPHY_TX_PWR_CTRL_TEMPBASED 0xE001 -+ -+extern void wlc_lcnphy_write_table(struct brcms_phy *pi, -+ const struct phytbl_info *pti); -+extern void wlc_lcnphy_read_table(struct brcms_phy *pi, -+ struct phytbl_info *pti); -+extern void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b); -+extern void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq); -+extern void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b); -+extern u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi); -+extern void wlc_lcnphy_get_radio_loft(struct brcms_phy *pi, u8 *ei0, -+ u8 *eq0, u8 *fi0, u8 *fq0); -+extern void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode); -+extern void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode); -+extern bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi); -+extern void wlc_lcnphy_tx_pwr_update_npt(struct brcms_phy *pi); -+extern s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1); -+extern void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, -+ s8 *cck_pwr); -+extern void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi); -+ -+extern s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index); -+ -+#define NPHY_MAX_HPVGA1_INDEX 10 -+#define NPHY_DEF_HPVGA1_INDEXLIMIT 7 -+ -+struct phy_iq_est { -+ s32 iq_prod; -+ u32 i_pwr; -+ u32 q_pwr; -+}; -+ -+extern void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi, -+ bool enable); -+extern void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode); -+ -+#define wlc_phy_write_table_nphy(pi, pti) \ -+ wlc_phy_write_table(pi, pti, 0x72, 0x74, 0x73) -+ -+#define wlc_phy_read_table_nphy(pi, pti) \ -+ wlc_phy_read_table(pi, pti, 0x72, 0x74, 0x73) -+ -+#define wlc_nphy_table_addr(pi, id, off) \ -+ wlc_phy_table_addr((pi), (id), (off), 0x72, 0x74, 0x73) -+ -+#define wlc_nphy_table_data_write(pi, w, v) \ -+ wlc_phy_table_data_write((pi), (w), (v)) -+ -+extern void wlc_phy_table_read_nphy(struct brcms_phy *pi, u32, u32 l, u32 o, -+ u32 w, void *d); -+extern void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32, -+ u32, const void *); -+ -+#define PHY_IPA(pi) \ -+ ((pi->ipa2g_on && CHSPEC_IS2G(pi->radio_chanspec)) || \ -+ (pi->ipa5g_on && CHSPEC_IS5G(pi->radio_chanspec))) -+ -+#define BRCMS_PHY_WAR_PR51571(pi) \ -+ if (NREV_LT((pi)->pubpi.phy_rev, 3)) \ -+ (void)R_REG(&(pi)->regs->maccontrol) -+ -+extern void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype); -+extern void wlc_phy_aci_reset_nphy(struct brcms_phy *pi); -+extern void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en); -+ -+extern u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint chan); -+extern void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on); -+ -+extern void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi); -+ -+extern void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd); -+extern s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi); -+ -+extern u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val); -+ -+extern void wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est, -+ u16 num_samps, u8 wait_time, -+ u8 wait_for_crs); -+ -+extern void wlc_phy_rx_iq_coeffs_nphy(struct brcms_phy *pi, u8 write, -+ struct nphy_iq_comp *comp); -+extern void wlc_phy_aci_and_noise_reduction_nphy(struct brcms_phy *pi); -+ -+extern void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, -+ u8 rxcore_bitmask); -+extern u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih); -+ -+extern void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type); -+extern void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi); -+extern void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi); -+extern void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi); -+extern u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi); -+ -+extern struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi); -+extern int wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, -+ struct nphy_txgains target_gain, -+ bool full, bool m); -+extern int wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi, -+ struct nphy_txgains target_gain, -+ u8 type, bool d); -+extern void wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, -+ s8 txpwrindex, bool res); -+extern void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core, u8 rssi_type); -+extern int wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, -+ s32 *rssi_buf, u8 nsamps); -+extern void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi); -+extern int wlc_phy_aci_scan_nphy(struct brcms_phy *pi); -+extern void wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, -+ s32 dBm_targetpower, bool debug); -+extern int wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, -+ u8 mode, u8, bool); -+extern void wlc_phy_stopplayback_nphy(struct brcms_phy *pi); -+extern void wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, -+ u8 num_samps); -+extern void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi); -+ -+extern int wlc_phy_rssi_compute_nphy(struct brcms_phy *pi, -+ struct d11rxhdr *rxh); -+ -+#define NPHY_TESTPATTERN_BPHY_EVM 0 -+#define NPHY_TESTPATTERN_BPHY_RFCS 1 -+ -+extern void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs); -+ -+void wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, -+ s8 *ofdmoffset); -+extern s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, -+ u16 chanspec); -+ -+extern bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pih); -+#endif /* _BRCM_PHY_INT_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c.orig 2011-11-09 13:46:58.257800483 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c 2011-11-09 13:47:17.012566015 -0500 -@@ -0,0 +1,5154 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include "phy_qmath.h" -+#include "phy_hal.h" -+#include "phy_radio.h" -+#include "phytbl_lcn.h" -+#include "phy_lcn.h" -+ -+#define PLL_2064_NDIV 90 -+#define PLL_2064_LOW_END_VCO 3000 -+#define PLL_2064_LOW_END_KVCO 27 -+#define PLL_2064_HIGH_END_VCO 4200 -+#define PLL_2064_HIGH_END_KVCO 68 -+#define PLL_2064_LOOP_BW_DOUBLER 200 -+#define PLL_2064_D30_DOUBLER 10500 -+#define PLL_2064_LOOP_BW 260 -+#define PLL_2064_D30 8000 -+#define PLL_2064_CAL_REF_TO 8 -+#define PLL_2064_MHZ 1000000 -+#define PLL_2064_OPEN_LOOP_DELAY 5 -+ -+#define TEMPSENSE 1 -+#define VBATSENSE 2 -+ -+#define NOISE_IF_UPD_CHK_INTERVAL 1 -+#define NOISE_IF_UPD_RST_INTERVAL 60 -+#define NOISE_IF_UPD_THRESHOLD_CNT 1 -+#define NOISE_IF_UPD_TRHRESHOLD 50 -+#define NOISE_IF_UPD_TIMEOUT 1000 -+#define NOISE_IF_OFF 0 -+#define NOISE_IF_CHK 1 -+#define NOISE_IF_ON 2 -+ -+#define PAPD_BLANKING_PROFILE 3 -+#define PAPD2LUT 0 -+#define PAPD_CORR_NORM 0 -+#define PAPD_BLANKING_THRESHOLD 0 -+#define PAPD_STOP_AFTER_LAST_UPDATE 0 -+ -+#define LCN_TARGET_PWR 60 -+ -+#define LCN_VBAT_OFFSET_433X 34649679 -+#define LCN_VBAT_SLOPE_433X 8258032 -+ -+#define LCN_VBAT_SCALE_NOM 53 -+#define LCN_VBAT_SCALE_DEN 432 -+ -+#define LCN_TEMPSENSE_OFFSET 80812 -+#define LCN_TEMPSENSE_DEN 2647 -+ -+#define LCN_BW_LMT 200 -+#define LCN_CUR_LMT 1250 -+#define LCN_MULT 1 -+#define LCN_VCO_DIV 30 -+#define LCN_OFFSET 680 -+#define LCN_FACT 490 -+#define LCN_CUR_DIV 2640 -+ -+#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT \ -+ (0 + 8) -+#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK \ -+ (0x7f << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT) -+ -+#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT \ -+ (0 + 8) -+#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK \ -+ (0x7f << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT) -+ -+#define wlc_lcnphy_enable_tx_gain_override(pi) \ -+ wlc_lcnphy_set_tx_gain_override(pi, true) -+#define wlc_lcnphy_disable_tx_gain_override(pi) \ -+ wlc_lcnphy_set_tx_gain_override(pi, false) -+ -+#define wlc_lcnphy_iqcal_active(pi) \ -+ (read_phy_reg((pi), 0x451) & \ -+ ((0x1 << 15) | (0x1 << 14))) -+ -+#define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13)) -+#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \ -+ (pi->temppwrctrl_capable) -+#define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \ -+ (pi->hwpwrctrl_capable) -+ -+#define SWCTRL_BT_TX 0x18 -+#define SWCTRL_OVR_DISABLE 0x40 -+ -+#define AFE_CLK_INIT_MODE_TXRX2X 1 -+#define AFE_CLK_INIT_MODE_PAPD 0 -+ -+#define LCNPHY_TBL_ID_IQLOCAL 0x00 -+ -+#define LCNPHY_TBL_ID_RFSEQ 0x08 -+#define LCNPHY_TBL_ID_GAIN_IDX 0x0d -+#define LCNPHY_TBL_ID_SW_CTRL 0x0f -+#define LCNPHY_TBL_ID_GAIN_TBL 0x12 -+#define LCNPHY_TBL_ID_SPUR 0x14 -+#define LCNPHY_TBL_ID_SAMPLEPLAY 0x15 -+#define LCNPHY_TBL_ID_SAMPLEPLAY1 0x16 -+ -+#define LCNPHY_TX_PWR_CTRL_RATE_OFFSET 832 -+#define LCNPHY_TX_PWR_CTRL_MAC_OFFSET 128 -+#define LCNPHY_TX_PWR_CTRL_GAIN_OFFSET 192 -+#define LCNPHY_TX_PWR_CTRL_IQ_OFFSET 320 -+#define LCNPHY_TX_PWR_CTRL_LO_OFFSET 448 -+#define LCNPHY_TX_PWR_CTRL_PWR_OFFSET 576 -+ -+#define LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313 140 -+ -+#define LCNPHY_TX_PWR_CTRL_START_NPT 1 -+#define LCNPHY_TX_PWR_CTRL_MAX_NPT 7 -+ -+#define LCNPHY_NOISE_SAMPLES_DEFAULT 5000 -+ -+#define LCNPHY_ACI_DETECT_START 1 -+#define LCNPHY_ACI_DETECT_PROGRESS 2 -+#define LCNPHY_ACI_DETECT_STOP 3 -+ -+#define LCNPHY_ACI_CRSHIFRMLO_TRSH 100 -+#define LCNPHY_ACI_GLITCH_TRSH 2000 -+#define LCNPHY_ACI_TMOUT 250 -+#define LCNPHY_ACI_DETECT_TIMEOUT 2 -+#define LCNPHY_ACI_START_DELAY 0 -+ -+#define wlc_lcnphy_tx_gain_override_enabled(pi) \ -+ (0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6))) -+ -+#define wlc_lcnphy_total_tx_frames(pi) \ -+ wlapi_bmac_read_shm((pi)->sh->physhim, M_UCODE_MACSTAT + \ -+ offsetof(struct macstat, txallfrm)) -+ -+struct lcnphy_txgains { -+ u16 gm_gain; -+ u16 pga_gain; -+ u16 pad_gain; -+ u16 dac_gain; -+}; -+ -+enum lcnphy_cal_mode { -+ LCNPHY_CAL_FULL, -+ LCNPHY_CAL_RECAL, -+ LCNPHY_CAL_CURRECAL, -+ LCNPHY_CAL_DIGCAL, -+ LCNPHY_CAL_GCTRL -+}; -+ -+struct lcnphy_rx_iqcomp { -+ u8 chan; -+ s16 a; -+ s16 b; -+}; -+ -+struct lcnphy_spb_tone { -+ s16 re; -+ s16 im; -+}; -+ -+struct lcnphy_unsign16_struct { -+ u16 re; -+ u16 im; -+}; -+ -+struct lcnphy_iq_est { -+ u32 iq_prod; -+ u32 i_pwr; -+ u32 q_pwr; -+}; -+ -+struct lcnphy_sfo_cfg { -+ u16 ptcentreTs20; -+ u16 ptcentreFactor; -+}; -+ -+enum lcnphy_papd_cal_type { -+ LCNPHY_PAPD_CAL_CW, -+ LCNPHY_PAPD_CAL_OFDM -+}; -+ -+typedef u16 iqcal_gain_params_lcnphy[9]; -+ -+static const iqcal_gain_params_lcnphy tbl_iqcal_gainparams_lcnphy_2G[] = { -+ {0, 0, 0, 0, 0, 0, 0, 0, 0}, -+}; -+ -+static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = { -+ tbl_iqcal_gainparams_lcnphy_2G, -+}; -+ -+static const u16 iqcal_gainparams_numgains_lcnphy[1] = { -+ sizeof(tbl_iqcal_gainparams_lcnphy_2G) / -+ sizeof(*tbl_iqcal_gainparams_lcnphy_2G), -+}; -+ -+static const struct lcnphy_sfo_cfg lcnphy_sfo_cfg[] = { -+ {965, 1087}, -+ {967, 1085}, -+ {969, 1082}, -+ {971, 1080}, -+ {973, 1078}, -+ {975, 1076}, -+ {977, 1073}, -+ {979, 1071}, -+ {981, 1069}, -+ {983, 1067}, -+ {985, 1065}, -+ {987, 1063}, -+ {989, 1060}, -+ {994, 1055} -+}; -+ -+static const -+u16 lcnphy_iqcal_loft_gainladder[] = { -+ ((2 << 8) | 0), -+ ((3 << 8) | 0), -+ ((4 << 8) | 0), -+ ((6 << 8) | 0), -+ ((8 << 8) | 0), -+ ((11 << 8) | 0), -+ ((16 << 8) | 0), -+ ((16 << 8) | 1), -+ ((16 << 8) | 2), -+ ((16 << 8) | 3), -+ ((16 << 8) | 4), -+ ((16 << 8) | 5), -+ ((16 << 8) | 6), -+ ((16 << 8) | 7), -+ ((23 << 8) | 7), -+ ((32 << 8) | 7), -+ ((45 << 8) | 7), -+ ((64 << 8) | 7), -+ ((91 << 8) | 7), -+ ((128 << 8) | 7) -+}; -+ -+static const -+u16 lcnphy_iqcal_ir_gainladder[] = { -+ ((1 << 8) | 0), -+ ((2 << 8) | 0), -+ ((4 << 8) | 0), -+ ((6 << 8) | 0), -+ ((8 << 8) | 0), -+ ((11 << 8) | 0), -+ ((16 << 8) | 0), -+ ((23 << 8) | 0), -+ ((32 << 8) | 0), -+ ((45 << 8) | 0), -+ ((64 << 8) | 0), -+ ((64 << 8) | 1), -+ ((64 << 8) | 2), -+ ((64 << 8) | 3), -+ ((64 << 8) | 4), -+ ((64 << 8) | 5), -+ ((64 << 8) | 6), -+ ((64 << 8) | 7), -+ ((91 << 8) | 7), -+ ((128 << 8) | 7) -+}; -+ -+static const -+struct lcnphy_spb_tone lcnphy_spb_tone_3750[] = { -+ {88, 0}, -+ {73, 49}, -+ {34, 81}, -+ {-17, 86}, -+ {-62, 62}, -+ {-86, 17}, -+ {-81, -34}, -+ {-49, -73}, -+ {0, -88}, -+ {49, -73}, -+ {81, -34}, -+ {86, 17}, -+ {62, 62}, -+ {17, 86}, -+ {-34, 81}, -+ {-73, 49}, -+ {-88, 0}, -+ {-73, -49}, -+ {-34, -81}, -+ {17, -86}, -+ {62, -62}, -+ {86, -17}, -+ {81, 34}, -+ {49, 73}, -+ {0, 88}, -+ {-49, 73}, -+ {-81, 34}, -+ {-86, -17}, -+ {-62, -62}, -+ {-17, -86}, -+ {34, -81}, -+ {73, -49}, -+}; -+ -+static const -+u16 iqlo_loopback_rf_regs[20] = { -+ RADIO_2064_REG036, -+ RADIO_2064_REG11A, -+ RADIO_2064_REG03A, -+ RADIO_2064_REG025, -+ RADIO_2064_REG028, -+ RADIO_2064_REG005, -+ RADIO_2064_REG112, -+ RADIO_2064_REG0FF, -+ RADIO_2064_REG11F, -+ RADIO_2064_REG00B, -+ RADIO_2064_REG113, -+ RADIO_2064_REG007, -+ RADIO_2064_REG0FC, -+ RADIO_2064_REG0FD, -+ RADIO_2064_REG012, -+ RADIO_2064_REG057, -+ RADIO_2064_REG059, -+ RADIO_2064_REG05C, -+ RADIO_2064_REG078, -+ RADIO_2064_REG092, -+}; -+ -+static const -+u16 tempsense_phy_regs[14] = { -+ 0x503, -+ 0x4a4, -+ 0x4d0, -+ 0x4d9, -+ 0x4da, -+ 0x4a6, -+ 0x938, -+ 0x939, -+ 0x4d8, -+ 0x4d0, -+ 0x4d7, -+ 0x4a5, -+ 0x40d, -+ 0x4a2, -+}; -+ -+static const -+u16 rxiq_cal_rf_reg[11] = { -+ RADIO_2064_REG098, -+ RADIO_2064_REG116, -+ RADIO_2064_REG12C, -+ RADIO_2064_REG06A, -+ RADIO_2064_REG00B, -+ RADIO_2064_REG01B, -+ RADIO_2064_REG113, -+ RADIO_2064_REG01D, -+ RADIO_2064_REG114, -+ RADIO_2064_REG02E, -+ RADIO_2064_REG12A, -+}; -+ -+static const -+struct lcnphy_rx_iqcomp lcnphy_rx_iqcomp_table_rev0[] = { -+ {1, 0, 0}, -+ {2, 0, 0}, -+ {3, 0, 0}, -+ {4, 0, 0}, -+ {5, 0, 0}, -+ {6, 0, 0}, -+ {7, 0, 0}, -+ {8, 0, 0}, -+ {9, 0, 0}, -+ {10, 0, 0}, -+ {11, 0, 0}, -+ {12, 0, 0}, -+ {13, 0, 0}, -+ {14, 0, 0}, -+ {34, 0, 0}, -+ {38, 0, 0}, -+ {42, 0, 0}, -+ {46, 0, 0}, -+ {36, 0, 0}, -+ {40, 0, 0}, -+ {44, 0, 0}, -+ {48, 0, 0}, -+ {52, 0, 0}, -+ {56, 0, 0}, -+ {60, 0, 0}, -+ {64, 0, 0}, -+ {100, 0, 0}, -+ {104, 0, 0}, -+ {108, 0, 0}, -+ {112, 0, 0}, -+ {116, 0, 0}, -+ {120, 0, 0}, -+ {124, 0, 0}, -+ {128, 0, 0}, -+ {132, 0, 0}, -+ {136, 0, 0}, -+ {140, 0, 0}, -+ {149, 0, 0}, -+ {153, 0, 0}, -+ {157, 0, 0}, -+ {161, 0, 0}, -+ {165, 0, 0}, -+ {184, 0, 0}, -+ {188, 0, 0}, -+ {192, 0, 0}, -+ {196, 0, 0}, -+ {200, 0, 0}, -+ {204, 0, 0}, -+ {208, 0, 0}, -+ {212, 0, 0}, -+ {216, 0, 0}, -+}; -+ -+static const u32 lcnphy_23bitgaincode_table[] = { -+ 0x200100, -+ 0x200200, -+ 0x200004, -+ 0x200014, -+ 0x200024, -+ 0x200034, -+ 0x200134, -+ 0x200234, -+ 0x200334, -+ 0x200434, -+ 0x200037, -+ 0x200137, -+ 0x200237, -+ 0x200337, -+ 0x200437, -+ 0x000035, -+ 0x000135, -+ 0x000235, -+ 0x000037, -+ 0x000137, -+ 0x000237, -+ 0x000337, -+ 0x00013f, -+ 0x00023f, -+ 0x00033f, -+ 0x00034f, -+ 0x00044f, -+ 0x00144f, -+ 0x00244f, -+ 0x00254f, -+ 0x00354f, -+ 0x00454f, -+ 0x00464f, -+ 0x01464f, -+ 0x02464f, -+ 0x03464f, -+ 0x04464f, -+}; -+ -+static const s8 lcnphy_gain_table[] = { -+ -16, -+ -13, -+ 10, -+ 7, -+ 4, -+ 0, -+ 3, -+ 6, -+ 9, -+ 12, -+ 15, -+ 18, -+ 21, -+ 24, -+ 27, -+ 30, -+ 33, -+ 36, -+ 39, -+ 42, -+ 45, -+ 48, -+ 50, -+ 53, -+ 56, -+ 59, -+ 62, -+ 65, -+ 68, -+ 71, -+ 74, -+ 77, -+ 80, -+ 83, -+ 86, -+ 89, -+ 92, -+}; -+ -+static const s8 lcnphy_gain_index_offset_for_rssi[] = { -+ 7, -+ 7, -+ 7, -+ 7, -+ 7, -+ 7, -+ 7, -+ 8, -+ 7, -+ 7, -+ 6, -+ 7, -+ 7, -+ 4, -+ 4, -+ 4, -+ 4, -+ 4, -+ 4, -+ 4, -+ 4, -+ 3, -+ 3, -+ 3, -+ 3, -+ 3, -+ 3, -+ 4, -+ 2, -+ 2, -+ 2, -+ 2, -+ 2, -+ 2, -+ -1, -+ -2, -+ -2, -+ -2 -+}; -+ -+struct chan_info_2064_lcnphy { -+ uint chan; -+ uint freq; -+ u8 logen_buftune; -+ u8 logen_rccr_tx; -+ u8 txrf_mix_tune_ctrl; -+ u8 pa_input_tune_g; -+ u8 logen_rccr_rx; -+ u8 pa_rxrf_lna1_freq_tune; -+ u8 pa_rxrf_lna2_freq_tune; -+ u8 rxrf_rxrf_spare1; -+}; -+ -+static const struct chan_info_2064_lcnphy chan_info_2064_lcnphy[] = { -+ {1, 2412, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, -+ {2, 2417, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, -+ {3, 2422, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, -+ {4, 2427, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, -+ {5, 2432, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, -+ {6, 2437, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, -+ {7, 2442, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, -+ {8, 2447, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, -+ {9, 2452, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, -+ {10, 2457, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, -+ {11, 2462, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, -+ {12, 2467, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, -+ {13, 2472, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, -+ {14, 2484, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, -+}; -+ -+static const struct lcnphy_radio_regs lcnphy_radio_regs_2064[] = { -+ {0x00, 0, 0, 0, 0}, -+ {0x01, 0x64, 0x64, 0, 0}, -+ {0x02, 0x20, 0x20, 0, 0}, -+ {0x03, 0x66, 0x66, 0, 0}, -+ {0x04, 0xf8, 0xf8, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0x10, 0x10, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0, 0, 0, 0}, -+ {0x0A, 0x37, 0x37, 0, 0}, -+ {0x0B, 0x6, 0x6, 0, 0}, -+ {0x0C, 0x55, 0x55, 0, 0}, -+ {0x0D, 0x8b, 0x8b, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0x5, 0x5, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0xe, 0xe, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0xb, 0xb, 0, 0}, -+ {0x14, 0x2, 0x2, 0, 0}, -+ {0x15, 0x12, 0x12, 0, 0}, -+ {0x16, 0x12, 0x12, 0, 0}, -+ {0x17, 0xc, 0xc, 0, 0}, -+ {0x18, 0xc, 0xc, 0, 0}, -+ {0x19, 0xc, 0xc, 0, 0}, -+ {0x1A, 0x8, 0x8, 0, 0}, -+ {0x1B, 0x2, 0x2, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0x1, 0x1, 0, 0}, -+ {0x1E, 0x12, 0x12, 0, 0}, -+ {0x1F, 0x6e, 0x6e, 0, 0}, -+ {0x20, 0x2, 0x2, 0, 0}, -+ {0x21, 0x23, 0x23, 0, 0}, -+ {0x22, 0x8, 0x8, 0, 0}, -+ {0x23, 0, 0, 0, 0}, -+ {0x24, 0, 0, 0, 0}, -+ {0x25, 0xc, 0xc, 0, 0}, -+ {0x26, 0x33, 0x33, 0, 0}, -+ {0x27, 0x55, 0x55, 0, 0}, -+ {0x28, 0, 0, 0, 0}, -+ {0x29, 0x30, 0x30, 0, 0}, -+ {0x2A, 0xb, 0xb, 0, 0}, -+ {0x2B, 0x1b, 0x1b, 0, 0}, -+ {0x2C, 0x3, 0x3, 0, 0}, -+ {0x2D, 0x1b, 0x1b, 0, 0}, -+ {0x2E, 0, 0, 0, 0}, -+ {0x2F, 0x20, 0x20, 0, 0}, -+ {0x30, 0xa, 0xa, 0, 0}, -+ {0x31, 0, 0, 0, 0}, -+ {0x32, 0x62, 0x62, 0, 0}, -+ {0x33, 0x19, 0x19, 0, 0}, -+ {0x34, 0x33, 0x33, 0, 0}, -+ {0x35, 0x77, 0x77, 0, 0}, -+ {0x36, 0, 0, 0, 0}, -+ {0x37, 0x70, 0x70, 0, 0}, -+ {0x38, 0x3, 0x3, 0, 0}, -+ {0x39, 0xf, 0xf, 0, 0}, -+ {0x3A, 0x6, 0x6, 0, 0}, -+ {0x3B, 0xcf, 0xcf, 0, 0}, -+ {0x3C, 0x1a, 0x1a, 0, 0}, -+ {0x3D, 0x6, 0x6, 0, 0}, -+ {0x3E, 0x42, 0x42, 0, 0}, -+ {0x3F, 0, 0, 0, 0}, -+ {0x40, 0xfb, 0xfb, 0, 0}, -+ {0x41, 0x9a, 0x9a, 0, 0}, -+ {0x42, 0x7a, 0x7a, 0, 0}, -+ {0x43, 0x29, 0x29, 0, 0}, -+ {0x44, 0, 0, 0, 0}, -+ {0x45, 0x8, 0x8, 0, 0}, -+ {0x46, 0xce, 0xce, 0, 0}, -+ {0x47, 0x27, 0x27, 0, 0}, -+ {0x48, 0x62, 0x62, 0, 0}, -+ {0x49, 0x6, 0x6, 0, 0}, -+ {0x4A, 0x58, 0x58, 0, 0}, -+ {0x4B, 0xf7, 0xf7, 0, 0}, -+ {0x4C, 0, 0, 0, 0}, -+ {0x4D, 0xb3, 0xb3, 0, 0}, -+ {0x4E, 0, 0, 0, 0}, -+ {0x4F, 0x2, 0x2, 0, 0}, -+ {0x50, 0, 0, 0, 0}, -+ {0x51, 0x9, 0x9, 0, 0}, -+ {0x52, 0x5, 0x5, 0, 0}, -+ {0x53, 0x17, 0x17, 0, 0}, -+ {0x54, 0x38, 0x38, 0, 0}, -+ {0x55, 0, 0, 0, 0}, -+ {0x56, 0, 0, 0, 0}, -+ {0x57, 0xb, 0xb, 0, 0}, -+ {0x58, 0, 0, 0, 0}, -+ {0x59, 0, 0, 0, 0}, -+ {0x5A, 0, 0, 0, 0}, -+ {0x5B, 0, 0, 0, 0}, -+ {0x5C, 0, 0, 0, 0}, -+ {0x5D, 0, 0, 0, 0}, -+ {0x5E, 0x88, 0x88, 0, 0}, -+ {0x5F, 0xcc, 0xcc, 0, 0}, -+ {0x60, 0x74, 0x74, 0, 0}, -+ {0x61, 0x74, 0x74, 0, 0}, -+ {0x62, 0x74, 0x74, 0, 0}, -+ {0x63, 0x44, 0x44, 0, 0}, -+ {0x64, 0x77, 0x77, 0, 0}, -+ {0x65, 0x44, 0x44, 0, 0}, -+ {0x66, 0x77, 0x77, 0, 0}, -+ {0x67, 0x55, 0x55, 0, 0}, -+ {0x68, 0x77, 0x77, 0, 0}, -+ {0x69, 0x77, 0x77, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0x7f, 0x7f, 0, 0}, -+ {0x6C, 0x8, 0x8, 0, 0}, -+ {0x6D, 0, 0, 0, 0}, -+ {0x6E, 0x88, 0x88, 0, 0}, -+ {0x6F, 0x66, 0x66, 0, 0}, -+ {0x70, 0x66, 0x66, 0, 0}, -+ {0x71, 0x28, 0x28, 0, 0}, -+ {0x72, 0x55, 0x55, 0, 0}, -+ {0x73, 0x4, 0x4, 0, 0}, -+ {0x74, 0, 0, 0, 0}, -+ {0x75, 0, 0, 0, 0}, -+ {0x76, 0, 0, 0, 0}, -+ {0x77, 0x1, 0x1, 0, 0}, -+ {0x78, 0xd6, 0xd6, 0, 0}, -+ {0x79, 0, 0, 0, 0}, -+ {0x7A, 0, 0, 0, 0}, -+ {0x7B, 0, 0, 0, 0}, -+ {0x7C, 0, 0, 0, 0}, -+ {0x7D, 0, 0, 0, 0}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0xb4, 0xb4, 0, 0}, -+ {0x84, 0x1, 0x1, 0, 0}, -+ {0x85, 0x20, 0x20, 0, 0}, -+ {0x86, 0x5, 0x5, 0, 0}, -+ {0x87, 0xff, 0xff, 0, 0}, -+ {0x88, 0x7, 0x7, 0, 0}, -+ {0x89, 0x77, 0x77, 0, 0}, -+ {0x8A, 0x77, 0x77, 0, 0}, -+ {0x8B, 0x77, 0x77, 0, 0}, -+ {0x8C, 0x77, 0x77, 0, 0}, -+ {0x8D, 0x8, 0x8, 0, 0}, -+ {0x8E, 0xa, 0xa, 0, 0}, -+ {0x8F, 0x8, 0x8, 0, 0}, -+ {0x90, 0x18, 0x18, 0, 0}, -+ {0x91, 0x5, 0x5, 0, 0}, -+ {0x92, 0x1f, 0x1f, 0, 0}, -+ {0x93, 0x10, 0x10, 0, 0}, -+ {0x94, 0x3, 0x3, 0, 0}, -+ {0x95, 0, 0, 0, 0}, -+ {0x96, 0, 0, 0, 0}, -+ {0x97, 0xaa, 0xaa, 0, 0}, -+ {0x98, 0, 0, 0, 0}, -+ {0x99, 0x23, 0x23, 0, 0}, -+ {0x9A, 0x7, 0x7, 0, 0}, -+ {0x9B, 0xf, 0xf, 0, 0}, -+ {0x9C, 0x10, 0x10, 0, 0}, -+ {0x9D, 0x3, 0x3, 0, 0}, -+ {0x9E, 0x4, 0x4, 0, 0}, -+ {0x9F, 0x20, 0x20, 0, 0}, -+ {0xA0, 0, 0, 0, 0}, -+ {0xA1, 0, 0, 0, 0}, -+ {0xA2, 0, 0, 0, 0}, -+ {0xA3, 0, 0, 0, 0}, -+ {0xA4, 0x1, 0x1, 0, 0}, -+ {0xA5, 0x77, 0x77, 0, 0}, -+ {0xA6, 0x77, 0x77, 0, 0}, -+ {0xA7, 0x77, 0x77, 0, 0}, -+ {0xA8, 0x77, 0x77, 0, 0}, -+ {0xA9, 0x8c, 0x8c, 0, 0}, -+ {0xAA, 0x88, 0x88, 0, 0}, -+ {0xAB, 0x78, 0x78, 0, 0}, -+ {0xAC, 0x57, 0x57, 0, 0}, -+ {0xAD, 0x88, 0x88, 0, 0}, -+ {0xAE, 0, 0, 0, 0}, -+ {0xAF, 0x8, 0x8, 0, 0}, -+ {0xB0, 0x88, 0x88, 0, 0}, -+ {0xB1, 0, 0, 0, 0}, -+ {0xB2, 0x1b, 0x1b, 0, 0}, -+ {0xB3, 0x3, 0x3, 0, 0}, -+ {0xB4, 0x24, 0x24, 0, 0}, -+ {0xB5, 0x3, 0x3, 0, 0}, -+ {0xB6, 0x1b, 0x1b, 0, 0}, -+ {0xB7, 0x24, 0x24, 0, 0}, -+ {0xB8, 0x3, 0x3, 0, 0}, -+ {0xB9, 0, 0, 0, 0}, -+ {0xBA, 0xaa, 0xaa, 0, 0}, -+ {0xBB, 0, 0, 0, 0}, -+ {0xBC, 0x4, 0x4, 0, 0}, -+ {0xBD, 0, 0, 0, 0}, -+ {0xBE, 0x8, 0x8, 0, 0}, -+ {0xBF, 0x11, 0x11, 0, 0}, -+ {0xC0, 0, 0, 0, 0}, -+ {0xC1, 0, 0, 0, 0}, -+ {0xC2, 0x62, 0x62, 0, 0}, -+ {0xC3, 0x1e, 0x1e, 0, 0}, -+ {0xC4, 0x33, 0x33, 0, 0}, -+ {0xC5, 0x37, 0x37, 0, 0}, -+ {0xC6, 0, 0, 0, 0}, -+ {0xC7, 0x70, 0x70, 0, 0}, -+ {0xC8, 0x1e, 0x1e, 0, 0}, -+ {0xC9, 0x6, 0x6, 0, 0}, -+ {0xCA, 0x4, 0x4, 0, 0}, -+ {0xCB, 0x2f, 0x2f, 0, 0}, -+ {0xCC, 0xf, 0xf, 0, 0}, -+ {0xCD, 0, 0, 0, 0}, -+ {0xCE, 0xff, 0xff, 0, 0}, -+ {0xCF, 0x8, 0x8, 0, 0}, -+ {0xD0, 0x3f, 0x3f, 0, 0}, -+ {0xD1, 0x3f, 0x3f, 0, 0}, -+ {0xD2, 0x3f, 0x3f, 0, 0}, -+ {0xD3, 0, 0, 0, 0}, -+ {0xD4, 0, 0, 0, 0}, -+ {0xD5, 0, 0, 0, 0}, -+ {0xD6, 0xcc, 0xcc, 0, 0}, -+ {0xD7, 0, 0, 0, 0}, -+ {0xD8, 0x8, 0x8, 0, 0}, -+ {0xD9, 0x8, 0x8, 0, 0}, -+ {0xDA, 0x8, 0x8, 0, 0}, -+ {0xDB, 0x11, 0x11, 0, 0}, -+ {0xDC, 0, 0, 0, 0}, -+ {0xDD, 0x87, 0x87, 0, 0}, -+ {0xDE, 0x88, 0x88, 0, 0}, -+ {0xDF, 0x8, 0x8, 0, 0}, -+ {0xE0, 0x8, 0x8, 0, 0}, -+ {0xE1, 0x8, 0x8, 0, 0}, -+ {0xE2, 0, 0, 0, 0}, -+ {0xE3, 0, 0, 0, 0}, -+ {0xE4, 0, 0, 0, 0}, -+ {0xE5, 0xf5, 0xf5, 0, 0}, -+ {0xE6, 0x30, 0x30, 0, 0}, -+ {0xE7, 0x1, 0x1, 0, 0}, -+ {0xE8, 0, 0, 0, 0}, -+ {0xE9, 0xff, 0xff, 0, 0}, -+ {0xEA, 0, 0, 0, 0}, -+ {0xEB, 0, 0, 0, 0}, -+ {0xEC, 0x22, 0x22, 0, 0}, -+ {0xED, 0, 0, 0, 0}, -+ {0xEE, 0, 0, 0, 0}, -+ {0xEF, 0, 0, 0, 0}, -+ {0xF0, 0x3, 0x3, 0, 0}, -+ {0xF1, 0x1, 0x1, 0, 0}, -+ {0xF2, 0, 0, 0, 0}, -+ {0xF3, 0, 0, 0, 0}, -+ {0xF4, 0, 0, 0, 0}, -+ {0xF5, 0, 0, 0, 0}, -+ {0xF6, 0, 0, 0, 0}, -+ {0xF7, 0x6, 0x6, 0, 0}, -+ {0xF8, 0, 0, 0, 0}, -+ {0xF9, 0, 0, 0, 0}, -+ {0xFA, 0x40, 0x40, 0, 0}, -+ {0xFB, 0, 0, 0, 0}, -+ {0xFC, 0x1, 0x1, 0, 0}, -+ {0xFD, 0x80, 0x80, 0, 0}, -+ {0xFE, 0x2, 0x2, 0, 0}, -+ {0xFF, 0x10, 0x10, 0, 0}, -+ {0x100, 0x2, 0x2, 0, 0}, -+ {0x101, 0x1e, 0x1e, 0, 0}, -+ {0x102, 0x1e, 0x1e, 0, 0}, -+ {0x103, 0, 0, 0, 0}, -+ {0x104, 0x1f, 0x1f, 0, 0}, -+ {0x105, 0, 0x8, 0, 1}, -+ {0x106, 0x2a, 0x2a, 0, 0}, -+ {0x107, 0xf, 0xf, 0, 0}, -+ {0x108, 0, 0, 0, 0}, -+ {0x109, 0, 0, 0, 0}, -+ {0x10A, 0, 0, 0, 0}, -+ {0x10B, 0, 0, 0, 0}, -+ {0x10C, 0, 0, 0, 0}, -+ {0x10D, 0, 0, 0, 0}, -+ {0x10E, 0, 0, 0, 0}, -+ {0x10F, 0, 0, 0, 0}, -+ {0x110, 0, 0, 0, 0}, -+ {0x111, 0, 0, 0, 0}, -+ {0x112, 0, 0, 0, 0}, -+ {0x113, 0, 0, 0, 0}, -+ {0x114, 0, 0, 0, 0}, -+ {0x115, 0, 0, 0, 0}, -+ {0x116, 0, 0, 0, 0}, -+ {0x117, 0, 0, 0, 0}, -+ {0x118, 0, 0, 0, 0}, -+ {0x119, 0, 0, 0, 0}, -+ {0x11A, 0, 0, 0, 0}, -+ {0x11B, 0, 0, 0, 0}, -+ {0x11C, 0x1, 0x1, 0, 0}, -+ {0x11D, 0, 0, 0, 0}, -+ {0x11E, 0, 0, 0, 0}, -+ {0x11F, 0, 0, 0, 0}, -+ {0x120, 0, 0, 0, 0}, -+ {0x121, 0, 0, 0, 0}, -+ {0x122, 0x80, 0x80, 0, 0}, -+ {0x123, 0, 0, 0, 0}, -+ {0x124, 0xf8, 0xf8, 0, 0}, -+ {0x125, 0, 0, 0, 0}, -+ {0x126, 0, 0, 0, 0}, -+ {0x127, 0, 0, 0, 0}, -+ {0x128, 0, 0, 0, 0}, -+ {0x129, 0, 0, 0, 0}, -+ {0x12A, 0, 0, 0, 0}, -+ {0x12B, 0, 0, 0, 0}, -+ {0x12C, 0, 0, 0, 0}, -+ {0x12D, 0, 0, 0, 0}, -+ {0x12E, 0, 0, 0, 0}, -+ {0x12F, 0, 0, 0, 0}, -+ {0x130, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0} -+}; -+ -+#define LCNPHY_NUM_DIG_FILT_COEFFS 16 -+#define LCNPHY_NUM_TX_DIG_FILTERS_CCK 13 -+ -+static const u16 LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK] -+ [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = { -+ {0, 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778, 1582, 64, -+ 128, 64,}, -+ {1, 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608, 1863, 93, -+ 167, 93,}, -+ {2, 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192, 778, 1582, 64, -+ 128, 64,}, -+ {3, 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205, 754, 1760, -+ 170, 340, 170,}, -+ {20, 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205, 767, 1760, -+ 256, 185, 256,}, -+ {21, 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205, 767, 1760, -+ 256, 273, 256,}, -+ {22, 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205, 767, 1760, -+ 256, 352, 256,}, -+ {23, 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205, 767, 1760, -+ 128, 233, 128,}, -+ {24, 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766, 1760, 256, -+ 1881, 256,}, -+ {25, 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765, 1760, 256, -+ 1881, 256,}, -+ {26, 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614, 1864, 128, -+ 384, 288,}, -+ {27, 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576, 613, 1864, -+ 128, 384, 288,}, -+ {30, 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205, 754, 1760, -+ 170, 340, 170,}, -+}; -+ -+#define LCNPHY_NUM_TX_DIG_FILTERS_OFDM 3 -+static const u16 LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM] -+ [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = { -+ {0, 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0, 0x0, -+ 0x278, 0xfea0, 0x80, 0x100, 0x80,}, -+ {1, 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50, -+ 750, 0xFE2B, 212, 0xFFCE, 212,}, -+ {2, 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748, -+ 0xFEF2, 128, 0xFFE2, 128} -+}; -+ -+#define wlc_lcnphy_set_start_tx_pwr_idx(pi, idx) \ -+ mod_phy_reg(pi, 0x4a4, \ -+ (0x1ff << 0), \ -+ (u16)(idx) << 0) -+ -+#define wlc_lcnphy_set_tx_pwr_npt(pi, npt) \ -+ mod_phy_reg(pi, 0x4a5, \ -+ (0x7 << 8), \ -+ (u16)(npt) << 8) -+ -+#define wlc_lcnphy_get_tx_pwr_ctrl(pi) \ -+ (read_phy_reg((pi), 0x4a4) & \ -+ ((0x1 << 15) | \ -+ (0x1 << 14) | \ -+ (0x1 << 13))) -+ -+#define wlc_lcnphy_get_tx_pwr_npt(pi) \ -+ ((read_phy_reg(pi, 0x4a5) & \ -+ (0x7 << 8)) >> \ -+ 8) -+ -+#define wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) \ -+ (read_phy_reg(pi, 0x473) & 0x1ff) -+ -+#define wlc_lcnphy_get_target_tx_pwr(pi) \ -+ ((read_phy_reg(pi, 0x4a7) & \ -+ (0xff << 0)) >> \ -+ 0) -+ -+#define wlc_lcnphy_set_target_tx_pwr(pi, target) \ -+ mod_phy_reg(pi, 0x4a7, \ -+ (0xff << 0), \ -+ (u16)(target) << 0) -+ -+#define wlc_radio_2064_rcal_done(pi) \ -+ (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20)) -+ -+#define tempsense_done(pi) \ -+ (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000)) -+ -+#define LCNPHY_IQLOCC_READ(val) \ -+ ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f))) -+ -+#define FIXED_TXPWR 78 -+#define LCNPHY_TEMPSENSE(val) ((s16)((val > 255) ? (val - 512) : val)) -+ -+void wlc_lcnphy_write_table(struct brcms_phy *pi, const struct phytbl_info *pti) -+{ -+ wlc_phy_write_table(pi, pti, 0x455, 0x457, 0x456); -+} -+ -+void wlc_lcnphy_read_table(struct brcms_phy *pi, struct phytbl_info *pti) -+{ -+ wlc_phy_read_table(pi, pti, 0x455, 0x457, 0x456); -+} -+ -+static void -+wlc_lcnphy_common_read_table(struct brcms_phy *pi, u32 tbl_id, -+ const u16 *tbl_ptr, u32 tbl_len, -+ u32 tbl_width, u32 tbl_offset) -+{ -+ struct phytbl_info tab; -+ tab.tbl_id = tbl_id; -+ tab.tbl_ptr = tbl_ptr; -+ tab.tbl_len = tbl_len; -+ tab.tbl_width = tbl_width; -+ tab.tbl_offset = tbl_offset; -+ wlc_lcnphy_read_table(pi, &tab); -+} -+ -+static void -+wlc_lcnphy_common_write_table(struct brcms_phy *pi, u32 tbl_id, -+ const u16 *tbl_ptr, u32 tbl_len, -+ u32 tbl_width, u32 tbl_offset) -+{ -+ -+ struct phytbl_info tab; -+ tab.tbl_id = tbl_id; -+ tab.tbl_ptr = tbl_ptr; -+ tab.tbl_len = tbl_len; -+ tab.tbl_width = tbl_width; -+ tab.tbl_offset = tbl_offset; -+ wlc_lcnphy_write_table(pi, &tab); -+} -+ -+static u32 -+wlc_lcnphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision) -+{ -+ u32 quotient, remainder, roundup, rbit; -+ -+ quotient = dividend / divisor; -+ remainder = dividend % divisor; -+ rbit = divisor & 1; -+ roundup = (divisor >> 1) + rbit; -+ -+ while (precision--) { -+ quotient <<= 1; -+ if (remainder >= roundup) { -+ quotient++; -+ remainder = ((remainder - roundup) << 1) + rbit; -+ } else { -+ remainder <<= 1; -+ } -+ } -+ -+ if (remainder >= roundup) -+ quotient++; -+ -+ return quotient; -+} -+ -+static int wlc_lcnphy_calc_floor(s16 coeff_x, int type) -+{ -+ int k; -+ k = 0; -+ if (type == 0) { -+ if (coeff_x < 0) -+ k = (coeff_x - 1) / 2; -+ else -+ k = coeff_x / 2; -+ } -+ -+ if (type == 1) { -+ if ((coeff_x + 1) < 0) -+ k = (coeff_x) / 2; -+ else -+ k = (coeff_x + 1) / 2; -+ } -+ return k; -+} -+ -+static void -+wlc_lcnphy_get_tx_gain(struct brcms_phy *pi, struct lcnphy_txgains *gains) -+{ -+ u16 dac_gain, rfgain0, rfgain1; -+ -+ dac_gain = read_phy_reg(pi, 0x439) >> 0; -+ gains->dac_gain = (dac_gain & 0x380) >> 7; -+ -+ rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0; -+ rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0; -+ -+ gains->gm_gain = rfgain0 & 0xff; -+ gains->pga_gain = (rfgain0 >> 8) & 0xff; -+ gains->pad_gain = rfgain1 & 0xff; -+} -+ -+ -+static void wlc_lcnphy_set_dac_gain(struct brcms_phy *pi, u16 dac_gain) -+{ -+ u16 dac_ctrl; -+ -+ dac_ctrl = (read_phy_reg(pi, 0x439) >> 0); -+ dac_ctrl = dac_ctrl & 0xc7f; -+ dac_ctrl = dac_ctrl | (dac_gain << 7); -+ mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0); -+ -+} -+ -+static void wlc_lcnphy_set_tx_gain_override(struct brcms_phy *pi, bool bEnable) -+{ -+ u16 bit = bEnable ? 1 : 0; -+ -+ mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7); -+ -+ mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14); -+ -+ mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6); -+} -+ -+static void -+wlc_lcnphy_rx_gain_override_enable(struct brcms_phy *pi, bool enable) -+{ -+ u16 ebit = enable ? 1 : 0; -+ -+ mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8); -+ -+ mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0); -+ -+ if (LCNREV_LT(pi->pubpi.phy_rev, 2)) { -+ mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4); -+ mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6); -+ mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5); -+ mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6); -+ } else { -+ mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12); -+ mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13); -+ mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5); -+ } -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10); -+ mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3); -+ } -+} -+ -+static void -+wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi, -+ u16 trsw, -+ u16 ext_lna, -+ u16 biq2, -+ u16 biq1, -+ u16 tia, u16 lna2, u16 lna1) -+{ -+ u16 gain0_15, gain16_19; -+ -+ gain16_19 = biq2 & 0xf; -+ gain0_15 = ((biq1 & 0xf) << 12) | -+ ((tia & 0xf) << 8) | -+ ((lna2 & 0x3) << 6) | -+ ((lna2 & -+ 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0); -+ -+ mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0); -+ mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0); -+ mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11); -+ -+ if (LCNREV_LT(pi->pubpi.phy_rev, 2)) { -+ mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9); -+ mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10); -+ } else { -+ mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10); -+ -+ mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15); -+ -+ mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9); -+ } -+ -+ mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0); -+ -+} -+ -+static void wlc_lcnphy_set_trsw_override(struct brcms_phy *pi, bool tx, bool rx) -+{ -+ -+ mod_phy_reg(pi, 0x44d, -+ (0x1 << 1) | -+ (0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0)); -+ -+ or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0)); -+} -+ -+static void wlc_lcnphy_clear_trsw_override(struct brcms_phy *pi) -+{ -+ -+ and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0))); -+} -+ -+static void wlc_lcnphy_set_rx_iq_comp(struct brcms_phy *pi, u16 a, u16 b) -+{ -+ mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0); -+ -+ mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0); -+ -+ mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0); -+ -+ mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0); -+ -+ mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0); -+ -+ mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0); -+ -+} -+ -+static bool -+wlc_lcnphy_rx_iq_est(struct brcms_phy *pi, -+ u16 num_samps, -+ u8 wait_time, struct lcnphy_iq_est *iq_est) -+{ -+ int wait_count = 0; -+ bool result = true; -+ u8 phybw40; -+ phybw40 = CHSPEC_IS40(pi->radio_chanspec); -+ -+ mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5); -+ -+ mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3); -+ -+ mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0); -+ -+ mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0); -+ -+ mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8); -+ -+ mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9); -+ -+ while (read_phy_reg(pi, 0x481) & (0x1 << 9)) { -+ -+ if (wait_count > (10 * 500)) { -+ result = false; -+ goto cleanup; -+ } -+ udelay(100); -+ wait_count++; -+ } -+ -+ iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) | -+ (u32) read_phy_reg(pi, 0x484); -+ iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) | -+ (u32) read_phy_reg(pi, 0x486); -+ iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) | -+ (u32) read_phy_reg(pi, 0x488); -+ -+cleanup: -+ mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3); -+ -+ mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5); -+ -+ return result; -+} -+ -+static bool wlc_lcnphy_calc_rx_iq_comp(struct brcms_phy *pi, u16 num_samps) -+{ -+#define LCNPHY_MIN_RXIQ_PWR 2 -+ bool result; -+ u16 a0_new, b0_new; -+ struct lcnphy_iq_est iq_est = { 0, 0, 0 }; -+ s32 a, b, temp; -+ s16 iq_nbits, qq_nbits, arsh, brsh; -+ s32 iq; -+ u32 ii, qq; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0); -+ b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0); -+ mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2); -+ -+ mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6); -+ -+ wlc_lcnphy_set_rx_iq_comp(pi, 0, 0); -+ -+ result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est); -+ if (!result) -+ goto cleanup; -+ -+ iq = (s32) iq_est.iq_prod; -+ ii = iq_est.i_pwr; -+ qq = iq_est.q_pwr; -+ -+ if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) { -+ result = false; -+ goto cleanup; -+ } -+ -+ iq_nbits = wlc_phy_nbits(iq); -+ qq_nbits = wlc_phy_nbits(qq); -+ -+ arsh = 10 - (30 - iq_nbits); -+ if (arsh >= 0) { -+ a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); -+ temp = (s32) (ii >> arsh); -+ if (temp == 0) -+ return false; -+ } else { -+ a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); -+ temp = (s32) (ii << -arsh); -+ if (temp == 0) -+ return false; -+ } -+ a /= temp; -+ brsh = qq_nbits - 31 + 20; -+ if (brsh >= 0) { -+ b = (qq << (31 - qq_nbits)); -+ temp = (s32) (ii >> brsh); -+ if (temp == 0) -+ return false; -+ } else { -+ b = (qq << (31 - qq_nbits)); -+ temp = (s32) (ii << -brsh); -+ if (temp == 0) -+ return false; -+ } -+ b /= temp; -+ b -= a * a; -+ b = (s32) int_sqrt((unsigned long) b); -+ b -= (1 << 10); -+ a0_new = (u16) (a & 0x3ff); -+ b0_new = (u16) (b & 0x3ff); -+cleanup: -+ -+ wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new); -+ -+ mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0); -+ -+ mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3); -+ -+ pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new; -+ pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new; -+ -+ return result; -+} -+ -+static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples) -+{ -+ struct lcnphy_iq_est iq_est = { 0, 0, 0 }; -+ -+ if (!wlc_lcnphy_rx_iq_est(pi, nsamples, 32, &iq_est)) -+ return 0; -+ return (iq_est.i_pwr + iq_est.q_pwr) / nsamples; -+} -+ -+static bool -+wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, -+ const struct lcnphy_rx_iqcomp *iqcomp, -+ int iqcomp_sz, bool tx_switch, bool rx_switch, int module, -+ int tx_gain_idx) -+{ -+ struct lcnphy_txgains old_gains; -+ u16 tx_pwr_ctrl; -+ u8 tx_gain_index_old = 0; -+ bool result = false, tx_gain_override_old = false; -+ u16 i, Core1TxControl_old, RFOverride0_old, -+ RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old, -+ rfoverride3_old, rfoverride3val_old, rfoverride4_old, -+ rfoverride4val_old, afectrlovr_old, afectrlovrval_old; -+ int tia_gain; -+ u32 received_power, rx_pwr_threshold; -+ u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl; -+ u16 values_to_save[11]; -+ s16 *ptr; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC); -+ if (NULL == ptr) -+ return false; -+ if (module == 2) { -+ while (iqcomp_sz--) { -+ if (iqcomp[iqcomp_sz].chan == -+ CHSPEC_CHANNEL(pi->radio_chanspec)) { -+ wlc_lcnphy_set_rx_iq_comp(pi, -+ (u16) -+ iqcomp[iqcomp_sz].a, -+ (u16) -+ iqcomp[iqcomp_sz].b); -+ result = true; -+ break; -+ } -+ } -+ goto cal_done; -+ } -+ -+ if (module == 1) { -+ -+ tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); -+ -+ for (i = 0; i < 11; i++) -+ values_to_save[i] = -+ read_radio_reg(pi, rxiq_cal_rf_reg[i]); -+ Core1TxControl_old = read_phy_reg(pi, 0x631); -+ -+ or_phy_reg(pi, 0x631, 0x0015); -+ -+ RFOverride0_old = read_phy_reg(pi, 0x44c); -+ RFOverrideVal0_old = read_phy_reg(pi, 0x44d); -+ rfoverride2_old = read_phy_reg(pi, 0x4b0); -+ rfoverride2val_old = read_phy_reg(pi, 0x4b1); -+ rfoverride3_old = read_phy_reg(pi, 0x4f9); -+ rfoverride3val_old = read_phy_reg(pi, 0x4fa); -+ rfoverride4_old = read_phy_reg(pi, 0x938); -+ rfoverride4val_old = read_phy_reg(pi, 0x939); -+ afectrlovr_old = read_phy_reg(pi, 0x43b); -+ afectrlovrval_old = read_phy_reg(pi, 0x43c); -+ old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); -+ old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); -+ -+ tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); -+ if (tx_gain_override_old) { -+ wlc_lcnphy_get_tx_gain(pi, &old_gains); -+ tx_gain_index_old = pi_lcn->lcnphy_current_index; -+ } -+ -+ wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx); -+ -+ mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); -+ mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0); -+ -+ mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); -+ mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); -+ -+ write_radio_reg(pi, RADIO_2064_REG116, 0x06); -+ write_radio_reg(pi, RADIO_2064_REG12C, 0x07); -+ write_radio_reg(pi, RADIO_2064_REG06A, 0xd3); -+ write_radio_reg(pi, RADIO_2064_REG098, 0x03); -+ write_radio_reg(pi, RADIO_2064_REG00B, 0x7); -+ mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4); -+ write_radio_reg(pi, RADIO_2064_REG01D, 0x01); -+ write_radio_reg(pi, RADIO_2064_REG114, 0x01); -+ write_radio_reg(pi, RADIO_2064_REG02E, 0x10); -+ write_radio_reg(pi, RADIO_2064_REG12A, 0x08); -+ -+ mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0); -+ mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0); -+ mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1); -+ mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1); -+ mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2); -+ mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2); -+ mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3); -+ mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3); -+ mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5); -+ mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5); -+ -+ mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0); -+ mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0); -+ -+ wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0); -+ write_phy_reg(pi, 0x6da, 0xffff); -+ or_phy_reg(pi, 0x6db, 0x3); -+ wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch); -+ wlc_lcnphy_rx_gain_override_enable(pi, true); -+ -+ tia_gain = 8; -+ rx_pwr_threshold = 950; -+ while (tia_gain > 0) { -+ tia_gain -= 1; -+ wlc_lcnphy_set_rx_gain_by_distribution(pi, -+ 0, 0, 2, 2, -+ (u16) -+ tia_gain, 1, 0); -+ udelay(500); -+ -+ received_power = -+ wlc_lcnphy_measure_digital_power(pi, 2000); -+ if (received_power < rx_pwr_threshold) -+ break; -+ } -+ result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff); -+ -+ wlc_lcnphy_stop_tx_tone(pi); -+ -+ write_phy_reg(pi, 0x631, Core1TxControl_old); -+ -+ write_phy_reg(pi, 0x44c, RFOverrideVal0_old); -+ write_phy_reg(pi, 0x44d, RFOverrideVal0_old); -+ write_phy_reg(pi, 0x4b0, rfoverride2_old); -+ write_phy_reg(pi, 0x4b1, rfoverride2val_old); -+ write_phy_reg(pi, 0x4f9, rfoverride3_old); -+ write_phy_reg(pi, 0x4fa, rfoverride3val_old); -+ write_phy_reg(pi, 0x938, rfoverride4_old); -+ write_phy_reg(pi, 0x939, rfoverride4val_old); -+ write_phy_reg(pi, 0x43b, afectrlovr_old); -+ write_phy_reg(pi, 0x43c, afectrlovrval_old); -+ write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); -+ write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl); -+ -+ wlc_lcnphy_clear_trsw_override(pi); -+ -+ mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2); -+ -+ for (i = 0; i < 11; i++) -+ write_radio_reg(pi, rxiq_cal_rf_reg[i], -+ values_to_save[i]); -+ -+ if (tx_gain_override_old) -+ wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old); -+ else -+ wlc_lcnphy_disable_tx_gain_override(pi); -+ -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl); -+ wlc_lcnphy_rx_gain_override_enable(pi, false); -+ } -+ -+cal_done: -+ kfree(ptr); -+ return result; -+} -+ -+s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi) -+{ -+ s8 index; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ if (txpwrctrl_off(pi)) -+ index = pi_lcn->lcnphy_current_index; -+ else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) -+ index = (s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on( -+ pi) / 2); -+ else -+ index = pi_lcn->lcnphy_current_index; -+ return index; -+} -+ -+void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel) -+{ -+ u16 afectrlovr, afectrlovrval; -+ afectrlovr = read_phy_reg(pi, 0x43b); -+ afectrlovrval = read_phy_reg(pi, 0x43c); -+ if (channel != 0) { -+ mod_phy_reg(pi, 0x43b, (0x1 << 1), (1) << 1); -+ -+ mod_phy_reg(pi, 0x43c, (0x1 << 1), (0) << 1); -+ -+ mod_phy_reg(pi, 0x43b, (0x1 << 4), (1) << 4); -+ -+ mod_phy_reg(pi, 0x43c, (0x1 << 6), (0) << 6); -+ -+ write_phy_reg(pi, 0x44b, 0xffff); -+ wlc_lcnphy_tx_pu(pi, 1); -+ -+ mod_phy_reg(pi, 0x634, (0xff << 8), (0) << 8); -+ -+ or_phy_reg(pi, 0x6da, 0x0080); -+ -+ or_phy_reg(pi, 0x00a, 0x228); -+ } else { -+ and_phy_reg(pi, 0x00a, ~(0x228)); -+ -+ and_phy_reg(pi, 0x6da, 0xFF7F); -+ write_phy_reg(pi, 0x43b, afectrlovr); -+ write_phy_reg(pi, 0x43c, afectrlovrval); -+ } -+} -+ -+static void wlc_lcnphy_toggle_afe_pwdn(struct brcms_phy *pi) -+{ -+ u16 save_AfeCtrlOvrVal, save_AfeCtrlOvr; -+ -+ save_AfeCtrlOvrVal = read_phy_reg(pi, 0x43c); -+ save_AfeCtrlOvr = read_phy_reg(pi, 0x43b); -+ -+ write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal | 0x1); -+ write_phy_reg(pi, 0x43b, save_AfeCtrlOvr | 0x1); -+ -+ write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal & 0xfffe); -+ write_phy_reg(pi, 0x43b, save_AfeCtrlOvr & 0xfffe); -+ -+ write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal); -+ write_phy_reg(pi, 0x43b, save_AfeCtrlOvr); -+} -+ -+static void -+wlc_lcnphy_txrx_spur_avoidance_mode(struct brcms_phy *pi, bool enable) -+{ -+ if (enable) { -+ write_phy_reg(pi, 0x942, 0x7); -+ write_phy_reg(pi, 0x93b, ((1 << 13) + 23)); -+ write_phy_reg(pi, 0x93c, ((1 << 13) + 1989)); -+ -+ write_phy_reg(pi, 0x44a, 0x084); -+ write_phy_reg(pi, 0x44a, 0x080); -+ write_phy_reg(pi, 0x6d3, 0x2222); -+ write_phy_reg(pi, 0x6d3, 0x2220); -+ } else { -+ write_phy_reg(pi, 0x942, 0x0); -+ write_phy_reg(pi, 0x93b, ((0 << 13) + 23)); -+ write_phy_reg(pi, 0x93c, ((0 << 13) + 1989)); -+ } -+ wlapi_switch_macfreq(pi->sh->physhim, enable); -+} -+ -+static void -+wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec) -+{ -+ u8 channel = CHSPEC_CHANNEL(chanspec); -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ if (channel == 14) -+ mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8); -+ else -+ mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8); -+ -+ pi_lcn->lcnphy_bandedge_corr = 2; -+ if (channel == 1) -+ pi_lcn->lcnphy_bandedge_corr = 4; -+ -+ if (channel == 1 || channel == 2 || channel == 3 || -+ channel == 4 || channel == 9 || -+ channel == 10 || channel == 11 || channel == 12) { -+ si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04); -+ si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0); -+ si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0); -+ -+ si_pmu_pllupd(pi->sh->sih); -+ write_phy_reg(pi, 0x942, 0); -+ wlc_lcnphy_txrx_spur_avoidance_mode(pi, false); -+ pi_lcn->lcnphy_spurmod = 0; -+ mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8); -+ -+ write_phy_reg(pi, 0x425, 0x5907); -+ } else { -+ si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04); -+ si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333); -+ si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820); -+ -+ si_pmu_pllupd(pi->sh->sih); -+ write_phy_reg(pi, 0x942, 0); -+ wlc_lcnphy_txrx_spur_avoidance_mode(pi, true); -+ -+ pi_lcn->lcnphy_spurmod = 0; -+ mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8); -+ -+ write_phy_reg(pi, 0x425, 0x590a); -+ } -+ -+ or_phy_reg(pi, 0x44a, 0x44); -+ write_phy_reg(pi, 0x44a, 0x80); -+} -+ -+static void -+wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel) -+{ -+ uint i; -+ const struct chan_info_2064_lcnphy *ci; -+ u8 rfpll_doubler = 0; -+ u8 pll_pwrup, pll_pwrup_ovr; -+ s32 qFxtal, qFref, qFvco, qFcal; -+ u8 d15, d16, f16, e44, e45; -+ u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div; -+ u16 loop_bw, d30, setCount; -+ -+ u8 h29, h28_ten, e30, h30_ten, cp_current; -+ u16 g30, d28; -+ -+ ci = &chan_info_2064_lcnphy[0]; -+ rfpll_doubler = 1; -+ -+ mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2); -+ -+ write_radio_reg(pi, RADIO_2064_REG09E, 0xf); -+ if (!rfpll_doubler) { -+ loop_bw = PLL_2064_LOOP_BW; -+ d30 = PLL_2064_D30; -+ } else { -+ loop_bw = PLL_2064_LOOP_BW_DOUBLER; -+ d30 = PLL_2064_D30_DOUBLER; -+ } -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++) -+ if (chan_info_2064_lcnphy[i].chan == channel) -+ break; -+ -+ if (i >= ARRAY_SIZE(chan_info_2064_lcnphy)) -+ return; -+ -+ ci = &chan_info_2064_lcnphy[i]; -+ } -+ -+ write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune); -+ -+ mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx); -+ -+ mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl); -+ -+ mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g); -+ -+ mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2, -+ (ci->logen_rccr_rx) << 2); -+ -+ mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune); -+ -+ mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4, -+ (ci->pa_rxrf_lna2_freq_tune) << 4); -+ -+ write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1); -+ -+ pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044); -+ pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B); -+ -+ or_radio_reg(pi, RADIO_2064_REG044, 0x07); -+ -+ or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1); -+ e44 = 0; -+ e45 = 0; -+ -+ fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq); -+ if (pi->xtalfreq > 26000000) -+ e44 = 1; -+ if (pi->xtalfreq > 52000000) -+ e45 = 1; -+ if (e44 == 0) -+ fcal_div = 1; -+ else if (e45 == 0) -+ fcal_div = 2; -+ else -+ fcal_div = 4; -+ fvco3 = (ci->freq * 3); -+ fref3 = 2 * fpfd; -+ -+ qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16); -+ qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16); -+ qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ; -+ qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16); -+ -+ write_radio_reg(pi, RADIO_2064_REG04F, 0x02); -+ -+ d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1; -+ write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2))); -+ write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5); -+ -+ d16 = (qFcal * 8 / (d15 + 1)) - 1; -+ write_radio_reg(pi, RADIO_2064_REG051, d16); -+ -+ f16 = ((d16 + 1) * (d15 + 1)) / qFcal; -+ setCount = f16 * 3 * (ci->freq) / 32 - 1; -+ mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0), -+ (u8) (setCount >> 8)); -+ -+ or_radio_reg(pi, RADIO_2064_REG053, 0x10); -+ write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff)); -+ -+ div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4; -+ -+ div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4; -+ while (div_frac >= fref3) { -+ div_int++; -+ div_frac -= fref3; -+ } -+ div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20); -+ -+ mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0), -+ (u8) (div_int >> 4)); -+ mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4), -+ (u8) (div_int << 4)); -+ mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0), -+ (u8) (div_frac >> 16)); -+ write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff); -+ write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff); -+ -+ write_radio_reg(pi, RADIO_2064_REG040, 0xfb); -+ -+ write_radio_reg(pi, RADIO_2064_REG041, 0x9A); -+ write_radio_reg(pi, RADIO_2064_REG042, 0xA3); -+ write_radio_reg(pi, RADIO_2064_REG043, 0x0C); -+ -+ h29 = LCN_BW_LMT / loop_bw; -+ d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) * -+ (fvco3 / 2 - PLL_2064_LOW_END_VCO)) / -+ (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO)) -+ + PLL_2064_LOW_END_KVCO; -+ h28_ten = (d28 * 10) / LCN_VCO_DIV; -+ e30 = (d30 - LCN_OFFSET) / LCN_FACT; -+ g30 = LCN_OFFSET + (e30 * LCN_FACT); -+ h30_ten = (g30 * 10) / LCN_CUR_DIV; -+ cp_current = ((LCN_CUR_LMT * h29 * LCN_MULT * 100) / h28_ten) / h30_ten; -+ mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current); -+ -+ if (channel >= 1 && channel <= 5) -+ write_radio_reg(pi, RADIO_2064_REG03C, 0x8); -+ else -+ write_radio_reg(pi, RADIO_2064_REG03C, 0x7); -+ write_radio_reg(pi, RADIO_2064_REG03D, 0x3); -+ -+ mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c); -+ udelay(1); -+ -+ wlc_2064_vco_cal(pi); -+ -+ write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup); -+ write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr); -+ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { -+ write_radio_reg(pi, RADIO_2064_REG038, 3); -+ write_radio_reg(pi, RADIO_2064_REG091, 7); -+ } -+} -+ -+static int -+wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type) -+{ -+ s16 filt_index = -1; -+ int j; -+ -+ u16 addr[] = { -+ 0x910, -+ 0x91e, -+ 0x91f, -+ 0x924, -+ 0x925, -+ 0x926, -+ 0x920, -+ 0x921, -+ 0x927, -+ 0x928, -+ 0x929, -+ 0x922, -+ 0x923, -+ 0x930, -+ 0x931, -+ 0x932 -+ }; -+ -+ u16 addr_ofdm[] = { -+ 0x90f, -+ 0x900, -+ 0x901, -+ 0x906, -+ 0x907, -+ 0x908, -+ 0x902, -+ 0x903, -+ 0x909, -+ 0x90a, -+ 0x90b, -+ 0x904, -+ 0x905, -+ 0x90c, -+ 0x90d, -+ 0x90e -+ }; -+ -+ if (!is_ofdm) { -+ for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) { -+ if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) { -+ filt_index = (s16) j; -+ break; -+ } -+ } -+ -+ if (filt_index != -1) { -+ for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) -+ write_phy_reg(pi, addr[j], -+ LCNPHY_txdigfiltcoeffs_cck -+ [filt_index][j + 1]); -+ } -+ } else { -+ for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) { -+ if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) { -+ filt_index = (s16) j; -+ break; -+ } -+ } -+ -+ if (filt_index != -1) { -+ for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) -+ write_phy_reg(pi, addr_ofdm[j], -+ LCNPHY_txdigfiltcoeffs_ofdm -+ [filt_index][j + 1]); -+ } -+ } -+ -+ return (filt_index != -1) ? 0 : -1; -+} -+ -+void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec) -+{ -+ u8 channel = CHSPEC_CHANNEL(chanspec); -+ -+ wlc_phy_chanspec_radio_set((struct brcms_phy_pub *) pi, chanspec); -+ -+ wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec); -+ -+ or_phy_reg(pi, 0x44a, 0x44); -+ write_phy_reg(pi, 0x44a, 0x80); -+ -+ wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel); -+ udelay(1000); -+ -+ wlc_lcnphy_toggle_afe_pwdn(pi); -+ -+ write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20); -+ write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor); -+ -+ if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) { -+ mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8); -+ -+ wlc_lcnphy_load_tx_iir_filter(pi, false, 3); -+ } else { -+ mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8); -+ -+ wlc_lcnphy_load_tx_iir_filter(pi, false, 2); -+ } -+ -+ wlc_lcnphy_load_tx_iir_filter(pi, true, 0); -+ -+ mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3); -+ -+} -+ -+static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi) -+{ -+ u16 pa_gain; -+ -+ pa_gain = (read_phy_reg(pi, 0x4fb) & -+ LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >> -+ LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT; -+ -+ return pa_gain; -+} -+ -+static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi, -+ struct lcnphy_txgains *target_gains) -+{ -+ u16 pa_gain = wlc_lcnphy_get_pa_gain(pi); -+ -+ mod_phy_reg( -+ pi, 0x4b5, -+ (0xffff << 0), -+ ((target_gains->gm_gain) | -+ (target_gains->pga_gain << 8)) << -+ 0); -+ mod_phy_reg(pi, 0x4fb, -+ (0x7fff << 0), -+ ((target_gains->pad_gain) | (pa_gain << 8)) << 0); -+ -+ mod_phy_reg( -+ pi, 0x4fc, -+ (0xffff << 0), -+ ((target_gains->gm_gain) | -+ (target_gains->pga_gain << 8)) << -+ 0); -+ mod_phy_reg(pi, 0x4fd, -+ (0x7fff << 0), -+ ((target_gains->pad_gain) | (pa_gain << 8)) << 0); -+ -+ wlc_lcnphy_set_dac_gain(pi, target_gains->dac_gain); -+ -+ wlc_lcnphy_enable_tx_gain_override(pi); -+} -+ -+static void wlc_lcnphy_set_bbmult(struct brcms_phy *pi, u8 m0) -+{ -+ u16 m0m1 = (u16) m0 << 8; -+ struct phytbl_info tab; -+ -+ tab.tbl_ptr = &m0m1; -+ tab.tbl_len = 1; -+ tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; -+ tab.tbl_offset = 87; -+ tab.tbl_width = 16; -+ wlc_lcnphy_write_table(pi, &tab); -+} -+ -+static void wlc_lcnphy_clear_tx_power_offsets(struct brcms_phy *pi) -+{ -+ u32 data_buf[64]; -+ struct phytbl_info tab; -+ -+ memset(data_buf, 0, sizeof(data_buf)); -+ -+ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; -+ tab.tbl_width = 32; -+ tab.tbl_ptr = data_buf; -+ -+ if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { -+ -+ tab.tbl_len = 30; -+ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET; -+ wlc_lcnphy_write_table(pi, &tab); -+ } -+ -+ tab.tbl_len = 64; -+ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_MAC_OFFSET; -+ wlc_lcnphy_write_table(pi, &tab); -+} -+ -+enum lcnphy_tssi_mode { -+ LCNPHY_TSSI_PRE_PA, -+ LCNPHY_TSSI_POST_PA, -+ LCNPHY_TSSI_EXT -+}; -+ -+static void -+wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos) -+{ -+ mod_phy_reg(pi, 0x4d7, (0x1 << 0), (0x1) << 0); -+ -+ mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1) << 6); -+ -+ if (LCNPHY_TSSI_POST_PA == pos) { -+ mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0) << 2); -+ -+ mod_phy_reg(pi, 0x4d9, (0x1 << 3), (1) << 3); -+ -+ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { -+ mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); -+ } else { -+ mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1); -+ mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); -+ } -+ } else { -+ mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2); -+ -+ mod_phy_reg(pi, 0x4d9, (0x1 << 3), (0) << 3); -+ -+ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { -+ mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); -+ } else { -+ mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0); -+ mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); -+ } -+ } -+ mod_phy_reg(pi, 0x637, (0x3 << 14), (0) << 14); -+ -+ if (LCNPHY_TSSI_EXT == pos) { -+ write_radio_reg(pi, RADIO_2064_REG07F, 1); -+ mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 0x2); -+ mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 0x1 << 7); -+ mod_radio_reg(pi, RADIO_2064_REG028, 0x1f, 0x3); -+ } -+} -+ -+static u16 wlc_lcnphy_rfseq_tbl_adc_pwrup(struct brcms_phy *pi) -+{ -+ u16 N1, N2, N3, N4, N5, N6, N; -+ N1 = ((read_phy_reg(pi, 0x4a5) & (0xff << 0)) -+ >> 0); -+ N2 = 1 << ((read_phy_reg(pi, 0x4a5) & (0x7 << 12)) -+ >> 12); -+ N3 = ((read_phy_reg(pi, 0x40d) & (0xff << 0)) -+ >> 0); -+ N4 = 1 << ((read_phy_reg(pi, 0x40d) & (0x7 << 8)) -+ >> 8); -+ N5 = ((read_phy_reg(pi, 0x4a2) & (0xff << 0)) -+ >> 0); -+ N6 = 1 << ((read_phy_reg(pi, 0x4a2) & (0x7 << 8)) -+ >> 8); -+ N = 2 * (N1 + N2 + N3 + N4 + 2 * (N5 + N6)) + 80; -+ if (N < 1600) -+ N = 1600; -+ return N; -+} -+ -+static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi) -+{ -+ u16 auxpga_vmid, auxpga_vmid_temp, auxpga_gain_temp; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ auxpga_vmid = (2 << 8) | -+ (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf; -+ auxpga_vmid_temp = (2 << 8) | (8 << 4) | 4; -+ auxpga_gain_temp = 2; -+ -+ mod_phy_reg(pi, 0x4d8, (0x1 << 0), (0) << 0); -+ -+ mod_phy_reg(pi, 0x4d8, (0x1 << 1), (0) << 1); -+ -+ mod_phy_reg(pi, 0x4d7, (0x1 << 3), (0) << 3); -+ -+ mod_phy_reg(pi, 0x4db, -+ (0x3ff << 0) | -+ (0x7 << 12), -+ (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12)); -+ -+ mod_phy_reg(pi, 0x4dc, -+ (0x3ff << 0) | -+ (0x7 << 12), -+ (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12)); -+ -+ mod_phy_reg(pi, 0x40a, -+ (0x3ff << 0) | -+ (0x7 << 12), -+ (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12)); -+ -+ mod_phy_reg(pi, 0x40b, -+ (0x3ff << 0) | -+ (0x7 << 12), -+ (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12)); -+ -+ mod_phy_reg(pi, 0x40c, -+ (0x3ff << 0) | -+ (0x7 << 12), -+ (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12)); -+ -+ mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5)); -+} -+ -+static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) -+{ -+ struct phytbl_info tab; -+ u32 rfseq, ind; -+ -+ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; -+ tab.tbl_width = 32; -+ tab.tbl_ptr = &ind; -+ tab.tbl_len = 1; -+ tab.tbl_offset = 0; -+ for (ind = 0; ind < 128; ind++) { -+ wlc_lcnphy_write_table(pi, &tab); -+ tab.tbl_offset++; -+ } -+ tab.tbl_offset = 704; -+ for (ind = 0; ind < 128; ind++) { -+ wlc_lcnphy_write_table(pi, &tab); -+ tab.tbl_offset++; -+ } -+ mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0); -+ -+ mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2); -+ -+ mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4); -+ -+ wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT); -+ mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14); -+ -+ mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15); -+ -+ mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5); -+ -+ mod_phy_reg(pi, 0x4a4, (0x1ff << 0), (0) << 0); -+ -+ mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0); -+ -+ mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12); -+ -+ mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8); -+ -+ mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0); -+ -+ mod_phy_reg(pi, 0x40d, (0x7 << 8), (4) << 8); -+ -+ mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0); -+ -+ mod_phy_reg(pi, 0x4a2, (0x7 << 8), (4) << 8); -+ -+ mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (0) << 6); -+ -+ mod_phy_reg(pi, 0x4a8, (0xff << 0), (0x1) << 0); -+ -+ wlc_lcnphy_clear_tx_power_offsets(pi); -+ -+ mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15); -+ -+ mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (0xff) << 0); -+ -+ mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0); -+ -+ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { -+ mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe); -+ mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); -+ } else { -+ mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1); -+ mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3); -+ } -+ -+ write_radio_reg(pi, RADIO_2064_REG025, 0xc); -+ -+ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { -+ mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1); -+ } else { -+ if (CHSPEC_IS2G(pi->radio_chanspec)) -+ mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1); -+ else -+ mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 0 << 1); -+ } -+ -+ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) -+ mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1); -+ else -+ mod_radio_reg(pi, RADIO_2064_REG03A, 0x4, 1 << 2); -+ -+ mod_radio_reg(pi, RADIO_2064_REG11A, 0x1, 1 << 0); -+ -+ mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 1 << 3); -+ -+ if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) -+ mod_phy_reg(pi, 0x4d7, -+ (0x1 << 3) | (0x7 << 12), 0 << 3 | 2 << 12); -+ -+ rfseq = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi); -+ tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; -+ tab.tbl_width = 16; -+ tab.tbl_ptr = &rfseq; -+ tab.tbl_len = 1; -+ tab.tbl_offset = 6; -+ wlc_lcnphy_write_table(pi, &tab); -+ -+ mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2); -+ -+ mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2); -+ -+ mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12); -+ -+ mod_phy_reg(pi, 0x4d7, (0x1 << 2), (1) << 2); -+ -+ mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8); -+ -+ wlc_lcnphy_pwrctrl_rssiparams(pi); -+} -+ -+void wlc_lcnphy_tx_pwr_update_npt(struct brcms_phy *pi) -+{ -+ u16 tx_cnt, tx_total, npt; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ tx_total = wlc_lcnphy_total_tx_frames(pi); -+ tx_cnt = tx_total - pi_lcn->lcnphy_tssi_tx_cnt; -+ npt = wlc_lcnphy_get_tx_pwr_npt(pi); -+ -+ if (tx_cnt > (1 << npt)) { -+ -+ pi_lcn->lcnphy_tssi_tx_cnt = tx_total; -+ -+ pi_lcn->lcnphy_tssi_idx = wlc_lcnphy_get_current_tx_pwr_idx(pi); -+ pi_lcn->lcnphy_tssi_npt = npt; -+ -+ } -+} -+ -+s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1) -+{ -+ s32 a, b, p; -+ -+ a = 32768 + (a1 * tssi); -+ b = (1024 * b0) + (64 * b1 * tssi); -+ p = ((2 * b) + a) / (2 * a); -+ -+ return p; -+} -+ -+static void wlc_lcnphy_txpower_reset_npt(struct brcms_phy *pi) -+{ -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) -+ return; -+ -+ pi_lcn->lcnphy_tssi_idx = LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313; -+ pi_lcn->lcnphy_tssi_npt = LCNPHY_TX_PWR_CTRL_START_NPT; -+} -+ -+void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi) -+{ -+ struct phytbl_info tab; -+ u32 rate_table[BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM + -+ BRCMS_NUM_RATES_MCS_1_STREAM]; -+ uint i, j; -+ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) -+ return; -+ -+ for (i = 0, j = 0; i < ARRAY_SIZE(rate_table); i++, j++) { -+ -+ if (i == BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM) -+ j = TXP_FIRST_MCS_20_SISO; -+ -+ rate_table[i] = (u32) ((s32) (-pi->tx_power_offset[j])); -+ } -+ -+ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; -+ tab.tbl_width = 32; -+ tab.tbl_len = ARRAY_SIZE(rate_table); -+ tab.tbl_ptr = rate_table; -+ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET; -+ wlc_lcnphy_write_table(pi, &tab); -+ -+ if (wlc_lcnphy_get_target_tx_pwr(pi) != pi->tx_power_min) { -+ wlc_lcnphy_set_target_tx_pwr(pi, pi->tx_power_min); -+ -+ wlc_lcnphy_txpower_reset_npt(pi); -+ } -+} -+ -+static void wlc_lcnphy_set_tx_pwr_soft_ctrl(struct brcms_phy *pi, s8 index) -+{ -+ u32 cck_offset[4] = { 22, 22, 22, 22 }; -+ u32 ofdm_offset, reg_offset_cck; -+ int i; -+ u16 index2; -+ struct phytbl_info tab; -+ -+ if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) -+ return; -+ -+ mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14); -+ -+ mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x0) << 14); -+ -+ or_phy_reg(pi, 0x6da, 0x0040); -+ -+ reg_offset_cck = 0; -+ for (i = 0; i < 4; i++) -+ cck_offset[i] -= reg_offset_cck; -+ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; -+ tab.tbl_width = 32; -+ tab.tbl_len = 4; -+ tab.tbl_ptr = cck_offset; -+ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET; -+ wlc_lcnphy_write_table(pi, &tab); -+ ofdm_offset = 0; -+ tab.tbl_len = 1; -+ tab.tbl_ptr = &ofdm_offset; -+ for (i = 836; i < 862; i++) { -+ tab.tbl_offset = i; -+ wlc_lcnphy_write_table(pi, &tab); -+ } -+ -+ mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0x1) << 15); -+ -+ mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14); -+ -+ mod_phy_reg(pi, 0x4a4, (0x1 << 13), (0x1) << 13); -+ -+ mod_phy_reg(pi, 0x4b0, (0x1 << 7), (0) << 7); -+ -+ mod_phy_reg(pi, 0x43b, (0x1 << 6), (0) << 6); -+ -+ mod_phy_reg(pi, 0x4a9, (0x1 << 15), (1) << 15); -+ -+ index2 = (u16) (index * 2); -+ mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0); -+ -+ mod_phy_reg(pi, 0x6a3, (0x1 << 4), (0) << 4); -+ -+} -+ -+static s8 wlc_lcnphy_tempcompensated_txpwrctrl(struct brcms_phy *pi) -+{ -+ s8 index, delta_brd, delta_temp, new_index, tempcorrx; -+ s16 manp, meas_temp, temp_diff; -+ bool neg = 0; -+ u16 temp; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) -+ return pi_lcn->lcnphy_current_index; -+ -+ index = FIXED_TXPWR; -+ -+ if (pi_lcn->lcnphy_tempsense_slope == 0) -+ return index; -+ -+ temp = (u16) wlc_lcnphy_tempsense(pi, 0); -+ meas_temp = LCNPHY_TEMPSENSE(temp); -+ -+ if (pi->tx_power_min != 0) -+ delta_brd = (pi_lcn->lcnphy_measPower - pi->tx_power_min); -+ else -+ delta_brd = 0; -+ -+ manp = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_rawtempsense); -+ temp_diff = manp - meas_temp; -+ if (temp_diff < 0) { -+ neg = 1; -+ temp_diff = -temp_diff; -+ } -+ -+ delta_temp = (s8) wlc_lcnphy_qdiv_roundup((u32) (temp_diff * 192), -+ (u32) (pi_lcn-> -+ lcnphy_tempsense_slope -+ * 10), 0); -+ if (neg) -+ delta_temp = -delta_temp; -+ -+ if (pi_lcn->lcnphy_tempsense_option == 3 -+ && LCNREV_IS(pi->pubpi.phy_rev, 0)) -+ delta_temp = 0; -+ if (pi_lcn->lcnphy_tempcorrx > 31) -+ tempcorrx = (s8) (pi_lcn->lcnphy_tempcorrx - 64); -+ else -+ tempcorrx = (s8) pi_lcn->lcnphy_tempcorrx; -+ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) -+ tempcorrx = 4; -+ new_index = -+ index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr; -+ new_index += tempcorrx; -+ -+ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) -+ index = 127; -+ -+ if (new_index < 0 || new_index > 126) -+ return index; -+ -+ return new_index; -+} -+ -+static u16 wlc_lcnphy_set_tx_pwr_ctrl_mode(struct brcms_phy *pi, u16 mode) -+{ -+ -+ u16 current_mode = mode; -+ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && -+ mode == LCNPHY_TX_PWR_CTRL_HW) -+ current_mode = LCNPHY_TX_PWR_CTRL_TEMPBASED; -+ if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) && -+ mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) -+ current_mode = LCNPHY_TX_PWR_CTRL_HW; -+ return current_mode; -+} -+ -+void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode) -+{ -+ u16 old_mode = wlc_lcnphy_get_tx_pwr_ctrl(pi); -+ s8 index; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, mode); -+ old_mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, old_mode); -+ -+ mod_phy_reg(pi, 0x6da, (0x1 << 6), -+ ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 1 : 0) << 6); -+ -+ mod_phy_reg(pi, 0x6a3, (0x1 << 4), -+ ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 0 : 1) << 4); -+ -+ if (old_mode != mode) { -+ if (LCNPHY_TX_PWR_CTRL_HW == old_mode) { -+ -+ wlc_lcnphy_tx_pwr_update_npt(pi); -+ -+ wlc_lcnphy_clear_tx_power_offsets(pi); -+ } -+ if (LCNPHY_TX_PWR_CTRL_HW == mode) { -+ -+ wlc_lcnphy_txpower_recalc_target(pi); -+ -+ wlc_lcnphy_set_start_tx_pwr_idx(pi, -+ pi_lcn-> -+ lcnphy_tssi_idx); -+ wlc_lcnphy_set_tx_pwr_npt(pi, pi_lcn->lcnphy_tssi_npt); -+ mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0); -+ -+ pi_lcn->lcnphy_tssi_tx_cnt = -+ wlc_lcnphy_total_tx_frames(pi); -+ -+ wlc_lcnphy_disable_tx_gain_override(pi); -+ pi_lcn->lcnphy_tx_power_idx_override = -1; -+ } else -+ wlc_lcnphy_enable_tx_gain_override(pi); -+ -+ mod_phy_reg(pi, 0x4a4, -+ ((0x1 << 15) | (0x1 << 14) | (0x1 << 13)), mode); -+ if (mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) { -+ index = wlc_lcnphy_tempcompensated_txpwrctrl(pi); -+ wlc_lcnphy_set_tx_pwr_soft_ctrl(pi, index); -+ pi_lcn->lcnphy_current_index = (s8) -+ ((read_phy_reg(pi, -+ 0x4a9) & -+ 0xFF) / 2); -+ } -+ } -+} -+ -+static void -+wlc_lcnphy_tx_iqlo_loopback(struct brcms_phy *pi, u16 *values_to_save) -+{ -+ u16 vmid; -+ int i; -+ for (i = 0; i < 20; i++) -+ values_to_save[i] = -+ read_radio_reg(pi, iqlo_loopback_rf_regs[i]); -+ -+ mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12); -+ mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14); -+ -+ mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11); -+ mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13); -+ -+ mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); -+ mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); -+ -+ mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0); -+ mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0); -+ -+ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) -+ and_radio_reg(pi, RADIO_2064_REG03A, 0xFD); -+ else -+ and_radio_reg(pi, RADIO_2064_REG03A, 0xF9); -+ or_radio_reg(pi, RADIO_2064_REG11A, 0x1); -+ -+ or_radio_reg(pi, RADIO_2064_REG036, 0x01); -+ or_radio_reg(pi, RADIO_2064_REG11A, 0x18); -+ udelay(20); -+ -+ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) -+ mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0); -+ else -+ or_radio_reg(pi, RADIO_2064_REG03A, 1); -+ } else { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) -+ mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1); -+ else -+ or_radio_reg(pi, RADIO_2064_REG03A, 0x3); -+ } -+ -+ udelay(20); -+ -+ write_radio_reg(pi, RADIO_2064_REG025, 0xF); -+ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) -+ mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4); -+ else -+ mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6); -+ } else { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) -+ mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1); -+ else -+ mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1); -+ } -+ -+ udelay(20); -+ -+ write_radio_reg(pi, RADIO_2064_REG005, 0x8); -+ or_radio_reg(pi, RADIO_2064_REG112, 0x80); -+ udelay(20); -+ -+ or_radio_reg(pi, RADIO_2064_REG0FF, 0x10); -+ or_radio_reg(pi, RADIO_2064_REG11F, 0x44); -+ udelay(20); -+ -+ or_radio_reg(pi, RADIO_2064_REG00B, 0x7); -+ or_radio_reg(pi, RADIO_2064_REG113, 0x10); -+ udelay(20); -+ -+ write_radio_reg(pi, RADIO_2064_REG007, 0x1); -+ udelay(20); -+ -+ vmid = 0x2A6; -+ mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3); -+ write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff)); -+ or_radio_reg(pi, RADIO_2064_REG11F, 0x44); -+ udelay(20); -+ -+ or_radio_reg(pi, RADIO_2064_REG0FF, 0x10); -+ udelay(20); -+ write_radio_reg(pi, RADIO_2064_REG012, 0x02); -+ or_radio_reg(pi, RADIO_2064_REG112, 0x06); -+ write_radio_reg(pi, RADIO_2064_REG036, 0x11); -+ write_radio_reg(pi, RADIO_2064_REG059, 0xcc); -+ write_radio_reg(pi, RADIO_2064_REG05C, 0x2e); -+ write_radio_reg(pi, RADIO_2064_REG078, 0xd7); -+ write_radio_reg(pi, RADIO_2064_REG092, 0x15); -+} -+ -+static bool wlc_lcnphy_iqcal_wait(struct brcms_phy *pi) -+{ -+ uint delay_count = 0; -+ -+ while (wlc_lcnphy_iqcal_active(pi)) { -+ udelay(100); -+ delay_count++; -+ -+ if (delay_count > (10 * 500)) -+ break; -+ } -+ -+ return (0 == wlc_lcnphy_iqcal_active(pi)); -+} -+ -+static void -+wlc_lcnphy_tx_iqlo_loopback_cleanup(struct brcms_phy *pi, u16 *values_to_save) -+{ -+ int i; -+ -+ and_phy_reg(pi, 0x44c, 0x0 >> 11); -+ -+ and_phy_reg(pi, 0x43b, 0xC); -+ -+ for (i = 0; i < 20; i++) -+ write_radio_reg(pi, iqlo_loopback_rf_regs[i], -+ values_to_save[i]); -+} -+ -+static void -+wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi, -+ struct lcnphy_txgains *target_gains, -+ enum lcnphy_cal_mode cal_mode, bool keep_tone) -+{ -+ -+ struct lcnphy_txgains cal_gains, temp_gains; -+ u16 hash; -+ u8 band_idx; -+ int j; -+ u16 ncorr_override[5]; -+ u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, -+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}; -+ -+ u16 commands_fullcal[] = { -+ 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 -+ }; -+ -+ u16 commands_recal[] = { -+ 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 -+ }; -+ -+ u16 command_nums_fullcal[] = { -+ 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 -+ }; -+ -+ u16 command_nums_recal[] = { -+ 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 -+ }; -+ u16 *command_nums = command_nums_fullcal; -+ -+ u16 *start_coeffs = NULL, *cal_cmds = NULL, cal_type, diq_start; -+ u16 tx_pwr_ctrl_old, save_txpwrctrlrfctrl2; -+ u16 save_sslpnCalibClkEnCtrl, save_sslpnRxFeClkEnCtrl; -+ bool tx_gain_override_old; -+ struct lcnphy_txgains old_gains; -+ uint i, n_cal_cmds = 0, n_cal_start = 0; -+ u16 *values_to_save; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ values_to_save = kmalloc(sizeof(u16) * 20, GFP_ATOMIC); -+ if (NULL == values_to_save) -+ return; -+ -+ save_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); -+ save_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); -+ -+ or_phy_reg(pi, 0x6da, 0x40); -+ or_phy_reg(pi, 0x6db, 0x3); -+ -+ switch (cal_mode) { -+ case LCNPHY_CAL_FULL: -+ start_coeffs = syst_coeffs; -+ cal_cmds = commands_fullcal; -+ n_cal_cmds = ARRAY_SIZE(commands_fullcal); -+ break; -+ -+ case LCNPHY_CAL_RECAL: -+ start_coeffs = syst_coeffs; -+ cal_cmds = commands_recal; -+ n_cal_cmds = ARRAY_SIZE(commands_recal); -+ command_nums = command_nums_recal; -+ break; -+ -+ default: -+ break; -+ } -+ -+ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, -+ start_coeffs, 11, 16, 64); -+ -+ write_phy_reg(pi, 0x6da, 0xffff); -+ mod_phy_reg(pi, 0x503, (0x1 << 3), (1) << 3); -+ -+ tx_pwr_ctrl_old = wlc_lcnphy_get_tx_pwr_ctrl(pi); -+ -+ mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12); -+ -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); -+ -+ save_txpwrctrlrfctrl2 = read_phy_reg(pi, 0x4db); -+ -+ mod_phy_reg(pi, 0x4db, (0x3ff << 0), (0x2a6) << 0); -+ -+ mod_phy_reg(pi, 0x4db, (0x7 << 12), (2) << 12); -+ -+ wlc_lcnphy_tx_iqlo_loopback(pi, values_to_save); -+ -+ tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); -+ if (tx_gain_override_old) -+ wlc_lcnphy_get_tx_gain(pi, &old_gains); -+ -+ if (!target_gains) { -+ if (!tx_gain_override_old) -+ wlc_lcnphy_set_tx_pwr_by_index(pi, -+ pi_lcn->lcnphy_tssi_idx); -+ wlc_lcnphy_get_tx_gain(pi, &temp_gains); -+ target_gains = &temp_gains; -+ } -+ -+ hash = (target_gains->gm_gain << 8) | -+ (target_gains->pga_gain << 4) | (target_gains->pad_gain); -+ -+ band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0); -+ -+ cal_gains = *target_gains; -+ memset(ncorr_override, 0, sizeof(ncorr_override)); -+ for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) { -+ if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) { -+ cal_gains.gm_gain = -+ tbl_iqcal_gainparams_lcnphy[band_idx][j][1]; -+ cal_gains.pga_gain = -+ tbl_iqcal_gainparams_lcnphy[band_idx][j][2]; -+ cal_gains.pad_gain = -+ tbl_iqcal_gainparams_lcnphy[band_idx][j][3]; -+ memcpy(ncorr_override, -+ &tbl_iqcal_gainparams_lcnphy[band_idx][j][3], -+ sizeof(ncorr_override)); -+ break; -+ } -+ } -+ -+ wlc_lcnphy_set_tx_gain(pi, &cal_gains); -+ -+ write_phy_reg(pi, 0x453, 0xaa9); -+ write_phy_reg(pi, 0x93d, 0xc0); -+ -+ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, -+ lcnphy_iqcal_loft_gainladder, -+ ARRAY_SIZE(lcnphy_iqcal_loft_gainladder), -+ 16, 0); -+ -+ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, -+ lcnphy_iqcal_ir_gainladder, -+ ARRAY_SIZE( -+ lcnphy_iqcal_ir_gainladder), 16, -+ 32); -+ -+ if (pi->phy_tx_tone_freq) { -+ -+ wlc_lcnphy_stop_tx_tone(pi); -+ udelay(5); -+ wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1); -+ } else { -+ wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1); -+ } -+ -+ write_phy_reg(pi, 0x6da, 0xffff); -+ -+ for (i = n_cal_start; i < n_cal_cmds; i++) { -+ u16 zero_diq = 0; -+ u16 best_coeffs[11]; -+ u16 command_num; -+ -+ cal_type = (cal_cmds[i] & 0x0f00) >> 8; -+ -+ command_num = command_nums[i]; -+ if (ncorr_override[cal_type]) -+ command_num = -+ ncorr_override[cal_type] << 8 | (command_num & -+ 0xff); -+ -+ write_phy_reg(pi, 0x452, command_num); -+ -+ if ((cal_type == 3) || (cal_type == 4)) { -+ wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, -+ &diq_start, 1, 16, 69); -+ -+ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, -+ &zero_diq, 1, 16, 69); -+ } -+ -+ write_phy_reg(pi, 0x451, cal_cmds[i]); -+ -+ if (!wlc_lcnphy_iqcal_wait(pi)) -+ goto cleanup; -+ -+ wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, -+ best_coeffs, -+ ARRAY_SIZE(best_coeffs), 16, 96); -+ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, -+ best_coeffs, -+ ARRAY_SIZE(best_coeffs), 16, 64); -+ -+ if ((cal_type == 3) || (cal_type == 4)) -+ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, -+ &diq_start, 1, 16, 69); -+ wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, -+ pi_lcn->lcnphy_cal_results. -+ txiqlocal_bestcoeffs, -+ ARRAY_SIZE(pi_lcn-> -+ lcnphy_cal_results. -+ txiqlocal_bestcoeffs), -+ 16, 96); -+ } -+ -+ wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, -+ pi_lcn->lcnphy_cal_results. -+ txiqlocal_bestcoeffs, -+ ARRAY_SIZE(pi_lcn->lcnphy_cal_results. -+ txiqlocal_bestcoeffs), 16, 96); -+ pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid = true; -+ -+ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, -+ &pi_lcn->lcnphy_cal_results. -+ txiqlocal_bestcoeffs[0], 4, 16, 80); -+ -+ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, -+ &pi_lcn->lcnphy_cal_results. -+ txiqlocal_bestcoeffs[5], 2, 16, 85); -+ -+cleanup: -+ wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, values_to_save); -+ kfree(values_to_save); -+ -+ if (!keep_tone) -+ wlc_lcnphy_stop_tx_tone(pi); -+ -+ write_phy_reg(pi, 0x4db, save_txpwrctrlrfctrl2); -+ -+ write_phy_reg(pi, 0x453, 0); -+ -+ if (tx_gain_override_old) -+ wlc_lcnphy_set_tx_gain(pi, &old_gains); -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl_old); -+ -+ write_phy_reg(pi, 0x6da, save_sslpnCalibClkEnCtrl); -+ write_phy_reg(pi, 0x6db, save_sslpnRxFeClkEnCtrl); -+ -+} -+ -+static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) -+{ -+ bool suspend, tx_gain_override_old; -+ struct lcnphy_txgains old_gains; -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ u16 idleTssi, idleTssi0_2C, idleTssi0_OB, idleTssi0_regvalue_OB, -+ idleTssi0_regvalue_2C; -+ u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); -+ u16 SAVE_lpfgain = read_radio_reg(pi, RADIO_2064_REG112); -+ u16 SAVE_jtag_bb_afe_switch = -+ read_radio_reg(pi, RADIO_2064_REG007) & 1; -+ u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10; -+ u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4; -+ idleTssi = read_phy_reg(pi, 0x4ab); -+ suspend = -+ (0 == -+ (R_REG(&((struct brcms_phy *) pi)->regs->maccontrol) & -+ MCTL_EN_MAC)); -+ if (!suspend) -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); -+ -+ tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); -+ wlc_lcnphy_get_tx_gain(pi, &old_gains); -+ -+ wlc_lcnphy_enable_tx_gain_override(pi); -+ wlc_lcnphy_set_tx_pwr_by_index(pi, 127); -+ write_radio_reg(pi, RADIO_2064_REG112, 0x6); -+ mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 1); -+ mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4); -+ mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2); -+ wlc_lcnphy_tssi_setup(pi); -+ wlc_phy_do_dummy_tx(pi, true, OFF); -+ idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0)) -+ >> 0); -+ -+ idleTssi0_2C = ((read_phy_reg(pi, 0x63e) & (0x1ff << 0)) -+ >> 0); -+ -+ if (idleTssi0_2C >= 256) -+ idleTssi0_OB = idleTssi0_2C - 256; -+ else -+ idleTssi0_OB = idleTssi0_2C + 256; -+ -+ idleTssi0_regvalue_OB = idleTssi0_OB; -+ if (idleTssi0_regvalue_OB >= 256) -+ idleTssi0_regvalue_2C = idleTssi0_regvalue_OB - 256; -+ else -+ idleTssi0_regvalue_2C = idleTssi0_regvalue_OB + 256; -+ mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (idleTssi0_regvalue_2C) << 0); -+ -+ mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12); -+ -+ wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old); -+ wlc_lcnphy_set_tx_gain(pi, &old_gains); -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); -+ -+ write_radio_reg(pi, RADIO_2064_REG112, SAVE_lpfgain); -+ mod_radio_reg(pi, RADIO_2064_REG007, 0x1, SAVE_jtag_bb_afe_switch); -+ mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, SAVE_jtag_auxpga); -+ mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, SAVE_iqadc_aux_en); -+ mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1 << 7); -+ if (!suspend) -+ wlapi_enable_mac(pi->sh->physhim); -+} -+ -+static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode) -+{ -+ bool suspend; -+ u16 save_txpwrCtrlEn; -+ u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain; -+ u16 auxpga_vmid; -+ struct phytbl_info tab; -+ u32 val; -+ u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025, -+ save_reg112; -+ u16 values_to_save[14]; -+ s8 index; -+ int i; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ udelay(999); -+ -+ save_reg007 = (u8) read_radio_reg(pi, RADIO_2064_REG007); -+ save_reg0FF = (u8) read_radio_reg(pi, RADIO_2064_REG0FF); -+ save_reg11F = (u8) read_radio_reg(pi, RADIO_2064_REG11F); -+ save_reg005 = (u8) read_radio_reg(pi, RADIO_2064_REG005); -+ save_reg025 = (u8) read_radio_reg(pi, RADIO_2064_REG025); -+ save_reg112 = (u8) read_radio_reg(pi, RADIO_2064_REG112); -+ -+ for (i = 0; i < 14; i++) -+ values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]); -+ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); -+ if (!suspend) -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4); -+ -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); -+ index = pi_lcn->lcnphy_current_index; -+ wlc_lcnphy_set_tx_pwr_by_index(pi, 127); -+ mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 0x1); -+ mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 0x1 << 4); -+ mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0x1 << 2); -+ mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0); -+ -+ mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2); -+ -+ mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14); -+ -+ mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0) << 15); -+ -+ mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5); -+ -+ mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0); -+ -+ mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12); -+ -+ mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8); -+ -+ mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0); -+ -+ mod_phy_reg(pi, 0x40d, (0x7 << 8), (6) << 8); -+ -+ mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0); -+ -+ mod_phy_reg(pi, 0x4a2, (0x7 << 8), (6) << 8); -+ -+ mod_phy_reg(pi, 0x4d9, (0x7 << 4), (2) << 4); -+ -+ mod_phy_reg(pi, 0x4d9, (0x7 << 8), (3) << 8); -+ -+ mod_phy_reg(pi, 0x4d9, (0x7 << 12), (1) << 12); -+ -+ mod_phy_reg(pi, 0x4da, (0x1 << 12), (0) << 12); -+ -+ mod_phy_reg(pi, 0x4da, (0x1 << 13), (1) << 13); -+ -+ mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15); -+ -+ write_radio_reg(pi, RADIO_2064_REG025, 0xC); -+ -+ mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 0x1 << 3); -+ -+ mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2); -+ -+ mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2); -+ -+ mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12); -+ -+ val = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi); -+ tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; -+ tab.tbl_width = 16; -+ tab.tbl_len = 1; -+ tab.tbl_ptr = &val; -+ tab.tbl_offset = 6; -+ wlc_lcnphy_write_table(pi, &tab); -+ if (mode == TEMPSENSE) { -+ mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3); -+ -+ mod_phy_reg(pi, 0x4d7, (0x7 << 12), (1) << 12); -+ -+ auxpga_vmidcourse = 8; -+ auxpga_vmidfine = 0x4; -+ auxpga_gain = 2; -+ mod_radio_reg(pi, RADIO_2064_REG082, 0x20, 1 << 5); -+ } else { -+ mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3); -+ -+ mod_phy_reg(pi, 0x4d7, (0x7 << 12), (3) << 12); -+ -+ auxpga_vmidcourse = 7; -+ auxpga_vmidfine = 0xa; -+ auxpga_gain = 2; -+ } -+ auxpga_vmid = -+ (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine); -+ mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0); -+ -+ mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2); -+ -+ mod_phy_reg(pi, 0x4d8, (0x1 << 1), (1) << 1); -+ -+ mod_phy_reg(pi, 0x4d8, (0x7 << 12), (auxpga_gain) << 12); -+ -+ mod_phy_reg(pi, 0x4d0, (0x1 << 5), (1) << 5); -+ -+ write_radio_reg(pi, RADIO_2064_REG112, 0x6); -+ -+ wlc_phy_do_dummy_tx(pi, true, OFF); -+ if (!tempsense_done(pi)) -+ udelay(10); -+ -+ write_radio_reg(pi, RADIO_2064_REG007, (u16) save_reg007); -+ write_radio_reg(pi, RADIO_2064_REG0FF, (u16) save_reg0FF); -+ write_radio_reg(pi, RADIO_2064_REG11F, (u16) save_reg11F); -+ write_radio_reg(pi, RADIO_2064_REG005, (u16) save_reg005); -+ write_radio_reg(pi, RADIO_2064_REG025, (u16) save_reg025); -+ write_radio_reg(pi, RADIO_2064_REG112, (u16) save_reg112); -+ for (i = 0; i < 14; i++) -+ write_phy_reg(pi, tempsense_phy_regs[i], values_to_save[i]); -+ wlc_lcnphy_set_tx_pwr_by_index(pi, (int)index); -+ -+ write_radio_reg(pi, 0x4a4, save_txpwrCtrlEn); -+ if (!suspend) -+ wlapi_enable_mac(pi->sh->physhim); -+ udelay(999); -+} -+ -+static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi) -+{ -+ struct lcnphy_txgains tx_gains; -+ u8 bbmult; -+ struct phytbl_info tab; -+ s32 a1, b0, b1; -+ s32 tssi, pwr, maxtargetpwr, mintargetpwr; -+ bool suspend; -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ -+ suspend = -+ (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); -+ if (!suspend) -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ -+ if (!pi->hwpwrctrl_capable) { -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ tx_gains.gm_gain = 4; -+ tx_gains.pga_gain = 12; -+ tx_gains.pad_gain = 12; -+ tx_gains.dac_gain = 0; -+ -+ bbmult = 150; -+ } else { -+ tx_gains.gm_gain = 7; -+ tx_gains.pga_gain = 15; -+ tx_gains.pad_gain = 14; -+ tx_gains.dac_gain = 0; -+ -+ bbmult = 150; -+ } -+ wlc_lcnphy_set_tx_gain(pi, &tx_gains); -+ wlc_lcnphy_set_bbmult(pi, bbmult); -+ wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); -+ } else { -+ -+ wlc_lcnphy_idle_tssi_est(ppi); -+ -+ wlc_lcnphy_clear_tx_power_offsets(pi); -+ -+ b0 = pi->txpa_2g[0]; -+ b1 = pi->txpa_2g[1]; -+ a1 = pi->txpa_2g[2]; -+ maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1); -+ mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1); -+ -+ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; -+ tab.tbl_width = 32; -+ tab.tbl_ptr = &pwr; -+ tab.tbl_len = 1; -+ tab.tbl_offset = 0; -+ for (tssi = 0; tssi < 128; tssi++) { -+ pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1); -+ -+ pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr; -+ wlc_lcnphy_write_table(pi, &tab); -+ tab.tbl_offset++; -+ } -+ -+ mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7); -+ -+ write_phy_reg(pi, 0x4a8, 10); -+ -+ wlc_lcnphy_set_target_tx_pwr(pi, LCN_TARGET_PWR); -+ -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW); -+ } -+ if (!suspend) -+ wlapi_enable_mac(pi->sh->physhim); -+} -+ -+static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi) -+{ -+ u16 m0m1; -+ struct phytbl_info tab; -+ -+ tab.tbl_ptr = &m0m1; -+ tab.tbl_len = 1; -+ tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; -+ tab.tbl_offset = 87; -+ tab.tbl_width = 16; -+ wlc_lcnphy_read_table(pi, &tab); -+ -+ return (u8) ((m0m1 & 0xff00) >> 8); -+} -+ -+static void wlc_lcnphy_set_pa_gain(struct brcms_phy *pi, u16 gain) -+{ -+ mod_phy_reg(pi, 0x4fb, -+ LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK, -+ gain << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT); -+ mod_phy_reg(pi, 0x4fd, -+ LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK, -+ gain << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT); -+} -+ -+void -+wlc_lcnphy_get_radio_loft(struct brcms_phy *pi, -+ u8 *ei0, u8 *eq0, u8 *fi0, u8 *fq0) -+{ -+ *ei0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG089)); -+ *eq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08A)); -+ *fi0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08B)); -+ *fq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08C)); -+} -+ -+void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b) -+{ -+ struct phytbl_info tab; -+ u16 iqcc[2]; -+ -+ iqcc[0] = a; -+ iqcc[1] = b; -+ -+ tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; -+ tab.tbl_width = 16; -+ tab.tbl_ptr = iqcc; -+ tab.tbl_len = 2; -+ tab.tbl_offset = 80; -+ wlc_lcnphy_write_table(pi, &tab); -+} -+ -+void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq) -+{ -+ struct phytbl_info tab; -+ -+ tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; -+ tab.tbl_width = 16; -+ tab.tbl_ptr = &didq; -+ tab.tbl_len = 1; -+ tab.tbl_offset = 85; -+ wlc_lcnphy_write_table(pi, &tab); -+} -+ -+void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index) -+{ -+ struct phytbl_info tab; -+ u16 a, b; -+ u8 bb_mult; -+ u32 bbmultiqcomp, txgain, locoeffs, rfpower; -+ struct lcnphy_txgains gains; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ pi_lcn->lcnphy_tx_power_idx_override = (s8) index; -+ pi_lcn->lcnphy_current_index = (u8) index; -+ -+ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; -+ tab.tbl_width = 32; -+ tab.tbl_len = 1; -+ -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); -+ -+ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index; -+ tab.tbl_ptr = &bbmultiqcomp; -+ wlc_lcnphy_read_table(pi, &tab); -+ -+ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index; -+ tab.tbl_width = 32; -+ tab.tbl_ptr = &txgain; -+ wlc_lcnphy_read_table(pi, &tab); -+ -+ gains.gm_gain = (u16) (txgain & 0xff); -+ gains.pga_gain = (u16) (txgain >> 8) & 0xff; -+ gains.pad_gain = (u16) (txgain >> 16) & 0xff; -+ gains.dac_gain = (u16) (bbmultiqcomp >> 28) & 0x07; -+ wlc_lcnphy_set_tx_gain(pi, &gains); -+ wlc_lcnphy_set_pa_gain(pi, (u16) (txgain >> 24) & 0x7f); -+ -+ bb_mult = (u8) ((bbmultiqcomp >> 20) & 0xff); -+ wlc_lcnphy_set_bbmult(pi, bb_mult); -+ -+ wlc_lcnphy_enable_tx_gain_override(pi); -+ -+ if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { -+ -+ a = (u16) ((bbmultiqcomp >> 10) & 0x3ff); -+ b = (u16) (bbmultiqcomp & 0x3ff); -+ wlc_lcnphy_set_tx_iqcc(pi, a, b); -+ -+ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + index; -+ tab.tbl_ptr = &locoeffs; -+ wlc_lcnphy_read_table(pi, &tab); -+ -+ wlc_lcnphy_set_tx_locc(pi, (u16) locoeffs); -+ -+ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index; -+ tab.tbl_ptr = &rfpower; -+ wlc_lcnphy_read_table(pi, &tab); -+ mod_phy_reg(pi, 0x6a6, (0x1fff << 0), (rfpower * 8) << 0); -+ -+ } -+} -+ -+static void wlc_lcnphy_clear_papd_comptable(struct brcms_phy *pi) -+{ -+ u32 j; -+ struct phytbl_info tab; -+ u32 temp_offset[128]; -+ tab.tbl_ptr = temp_offset; -+ tab.tbl_len = 128; -+ tab.tbl_id = LCNPHY_TBL_ID_PAPDCOMPDELTATBL; -+ tab.tbl_width = 32; -+ tab.tbl_offset = 0; -+ -+ memset(temp_offset, 0, sizeof(temp_offset)); -+ for (j = 1; j < 128; j += 2) -+ temp_offset[j] = 0x80000; -+ -+ wlc_lcnphy_write_table(pi, &tab); -+ return; -+} -+ -+void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable) -+{ -+ if (!bEnable) { -+ -+ and_phy_reg(pi, 0x43b, ~(u16) ((0x1 << 1) | (0x1 << 4))); -+ -+ mod_phy_reg(pi, 0x43c, (0x1 << 1), 1 << 1); -+ -+ and_phy_reg(pi, 0x44c, -+ ~(u16) ((0x1 << 3) | -+ (0x1 << 5) | -+ (0x1 << 12) | -+ (0x1 << 0) | (0x1 << 1) | (0x1 << 2))); -+ -+ and_phy_reg(pi, 0x44d, -+ ~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14))); -+ mod_phy_reg(pi, 0x44d, (0x1 << 2), 1 << 2); -+ -+ mod_phy_reg(pi, 0x44d, (0x1 << 1) | (0x1 << 0), (0x1 << 0)); -+ -+ and_phy_reg(pi, 0x4f9, -+ ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2))); -+ -+ and_phy_reg(pi, 0x4fa, -+ ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2))); -+ } else { -+ -+ mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); -+ mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); -+ -+ mod_phy_reg(pi, 0x43b, (0x1 << 4), 1 << 4); -+ mod_phy_reg(pi, 0x43c, (0x1 << 6), 0 << 6); -+ -+ mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12); -+ mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14); -+ -+ wlc_lcnphy_set_trsw_override(pi, true, false); -+ -+ mod_phy_reg(pi, 0x44d, (0x1 << 2), 0 << 2); -+ mod_phy_reg(pi, 0x44c, (0x1 << 2), 1 << 2); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ -+ mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3); -+ mod_phy_reg(pi, 0x44d, (0x1 << 3), 1 << 3); -+ -+ mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5); -+ mod_phy_reg(pi, 0x44d, (0x1 << 5), 0 << 5); -+ -+ mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1); -+ mod_phy_reg(pi, 0x4fa, (0x1 << 1), 1 << 1); -+ -+ mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2); -+ mod_phy_reg(pi, 0x4fa, (0x1 << 2), 1 << 2); -+ -+ mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); -+ mod_phy_reg(pi, 0x4fa, (0x1 << 0), 1 << 0); -+ } else { -+ -+ mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3); -+ mod_phy_reg(pi, 0x44d, (0x1 << 3), 0 << 3); -+ -+ mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5); -+ mod_phy_reg(pi, 0x44d, (0x1 << 5), 1 << 5); -+ -+ mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1); -+ mod_phy_reg(pi, 0x4fa, (0x1 << 1), 0 << 1); -+ -+ mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2); -+ mod_phy_reg(pi, 0x4fa, (0x1 << 2), 0 << 2); -+ -+ mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); -+ mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0); -+ } -+ } -+} -+ -+static void -+wlc_lcnphy_run_samples(struct brcms_phy *pi, -+ u16 num_samps, -+ u16 num_loops, u16 wait, bool iqcalmode) -+{ -+ -+ or_phy_reg(pi, 0x6da, 0x8080); -+ -+ mod_phy_reg(pi, 0x642, (0x7f << 0), (num_samps - 1) << 0); -+ if (num_loops != 0xffff) -+ num_loops--; -+ mod_phy_reg(pi, 0x640, (0xffff << 0), num_loops << 0); -+ -+ mod_phy_reg(pi, 0x641, (0xffff << 0), wait << 0); -+ -+ if (iqcalmode) { -+ -+ and_phy_reg(pi, 0x453, (u16) ~(0x1 << 15)); -+ or_phy_reg(pi, 0x453, (0x1 << 15)); -+ } else { -+ write_phy_reg(pi, 0x63f, 1); -+ wlc_lcnphy_tx_pu(pi, 1); -+ } -+ -+ or_radio_reg(pi, RADIO_2064_REG112, 0x6); -+} -+ -+void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode) -+{ -+ -+ u8 phybw40; -+ phybw40 = CHSPEC_IS40(pi->radio_chanspec); -+ -+ if (LCNREV_LT(pi->pubpi.phy_rev, 2)) { -+ mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5); -+ mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9); -+ } else { -+ mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5); -+ mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9); -+ } -+ -+ if (phybw40 == 0) { -+ mod_phy_reg((pi), 0x410, -+ (0x1 << 6) | -+ (0x1 << 5), -+ ((CHSPEC_IS2G( -+ pi->radio_chanspec)) ? (!mode) : 0) << -+ 6 | (!mode) << 5); -+ mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7); -+ } -+} -+ -+void -+wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val, -+ bool iqcalmode) -+{ -+ u8 phy_bw; -+ u16 num_samps, t, k; -+ u32 bw; -+ s32 theta = 0, rot = 0; -+ struct cordic_iq tone_samp; -+ u32 data_buf[64]; -+ u16 i_samp, q_samp; -+ struct phytbl_info tab; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ pi->phy_tx_tone_freq = f_kHz; -+ -+ wlc_lcnphy_deaf_mode(pi, true); -+ -+ phy_bw = 40; -+ if (pi_lcn->lcnphy_spurmod) { -+ write_phy_reg(pi, 0x942, 0x2); -+ write_phy_reg(pi, 0x93b, 0x0); -+ write_phy_reg(pi, 0x93c, 0x0); -+ wlc_lcnphy_txrx_spur_avoidance_mode(pi, false); -+ } -+ -+ if (f_kHz) { -+ k = 1; -+ do { -+ bw = phy_bw * 1000 * k; -+ num_samps = bw / abs(f_kHz); -+ k++; -+ } while ((num_samps * (u32) (abs(f_kHz))) != bw); -+ } else -+ num_samps = 2; -+ -+ rot = ((f_kHz * 36) / phy_bw) / 100; -+ theta = 0; -+ -+ for (t = 0; t < num_samps; t++) { -+ -+ tone_samp = cordic_calc_iq(theta); -+ -+ theta += rot; -+ -+ i_samp = (u16) (FLOAT(tone_samp.i * max_val) & 0x3ff); -+ q_samp = (u16) (FLOAT(tone_samp.q * max_val) & 0x3ff); -+ data_buf[t] = (i_samp << 10) | q_samp; -+ } -+ -+ mod_phy_reg(pi, 0x6d6, (0x3 << 0), 0 << 0); -+ -+ mod_phy_reg(pi, 0x6da, (0x1 << 3), 1 << 3); -+ -+ tab.tbl_ptr = data_buf; -+ tab.tbl_len = num_samps; -+ tab.tbl_id = LCNPHY_TBL_ID_SAMPLEPLAY; -+ tab.tbl_offset = 0; -+ tab.tbl_width = 32; -+ wlc_lcnphy_write_table(pi, &tab); -+ -+ wlc_lcnphy_run_samples(pi, num_samps, 0xffff, 0, iqcalmode); -+} -+ -+void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi) -+{ -+ s16 playback_status; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ pi->phy_tx_tone_freq = 0; -+ if (pi_lcn->lcnphy_spurmod) { -+ write_phy_reg(pi, 0x942, 0x7); -+ write_phy_reg(pi, 0x93b, 0x2017); -+ write_phy_reg(pi, 0x93c, 0x27c5); -+ wlc_lcnphy_txrx_spur_avoidance_mode(pi, true); -+ } -+ -+ playback_status = read_phy_reg(pi, 0x644); -+ if (playback_status & (0x1 << 0)) { -+ wlc_lcnphy_tx_pu(pi, 0); -+ mod_phy_reg(pi, 0x63f, (0x1 << 1), 1 << 1); -+ } else if (playback_status & (0x1 << 1)) -+ mod_phy_reg(pi, 0x453, (0x1 << 15), 0 << 15); -+ -+ mod_phy_reg(pi, 0x6d6, (0x3 << 0), 1 << 0); -+ -+ mod_phy_reg(pi, 0x6da, (0x1 << 3), 0 << 3); -+ -+ mod_phy_reg(pi, 0x6da, (0x1 << 7), 0 << 7); -+ -+ and_radio_reg(pi, RADIO_2064_REG112, 0xFFF9); -+ -+ wlc_lcnphy_deaf_mode(pi, false); -+} -+ -+static void -+wlc_lcnphy_set_cc(struct brcms_phy *pi, int cal_type, s16 coeff_x, s16 coeff_y) -+{ -+ u16 di0dq0; -+ u16 x, y, data_rf; -+ int k; -+ switch (cal_type) { -+ case 0: -+ wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y); -+ break; -+ case 2: -+ di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff); -+ wlc_lcnphy_set_tx_locc(pi, di0dq0); -+ break; -+ case 3: -+ k = wlc_lcnphy_calc_floor(coeff_x, 0); -+ y = 8 + k; -+ k = wlc_lcnphy_calc_floor(coeff_x, 1); -+ x = 8 - k; -+ data_rf = (x * 16 + y); -+ write_radio_reg(pi, RADIO_2064_REG089, data_rf); -+ k = wlc_lcnphy_calc_floor(coeff_y, 0); -+ y = 8 + k; -+ k = wlc_lcnphy_calc_floor(coeff_y, 1); -+ x = 8 - k; -+ data_rf = (x * 16 + y); -+ write_radio_reg(pi, RADIO_2064_REG08A, data_rf); -+ break; -+ case 4: -+ k = wlc_lcnphy_calc_floor(coeff_x, 0); -+ y = 8 + k; -+ k = wlc_lcnphy_calc_floor(coeff_x, 1); -+ x = 8 - k; -+ data_rf = (x * 16 + y); -+ write_radio_reg(pi, RADIO_2064_REG08B, data_rf); -+ k = wlc_lcnphy_calc_floor(coeff_y, 0); -+ y = 8 + k; -+ k = wlc_lcnphy_calc_floor(coeff_y, 1); -+ x = 8 - k; -+ data_rf = (x * 16 + y); -+ write_radio_reg(pi, RADIO_2064_REG08C, data_rf); -+ break; -+ } -+} -+ -+static struct lcnphy_unsign16_struct -+wlc_lcnphy_get_cc(struct brcms_phy *pi, int cal_type) -+{ -+ u16 a, b, didq; -+ u8 di0, dq0, ei, eq, fi, fq; -+ struct lcnphy_unsign16_struct cc; -+ cc.re = 0; -+ cc.im = 0; -+ switch (cal_type) { -+ case 0: -+ wlc_lcnphy_get_tx_iqcc(pi, &a, &b); -+ cc.re = a; -+ cc.im = b; -+ break; -+ case 2: -+ didq = wlc_lcnphy_get_tx_locc(pi); -+ di0 = (((didq & 0xff00) << 16) >> 24); -+ dq0 = (((didq & 0x00ff) << 24) >> 24); -+ cc.re = (u16) di0; -+ cc.im = (u16) dq0; -+ break; -+ case 3: -+ wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq); -+ cc.re = (u16) ei; -+ cc.im = (u16) eq; -+ break; -+ case 4: -+ wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq); -+ cc.re = (u16) fi; -+ cc.im = (u16) fq; -+ break; -+ } -+ return cc; -+} -+ -+static void -+wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh, -+ s16 *ptr, int mode) -+{ -+ u32 curval1, curval2, stpptr, curptr, strptr, val; -+ u16 sslpnCalibClkEnCtrl, timer; -+ u16 old_sslpnCalibClkEnCtrl; -+ s16 imag, real; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ timer = 0; -+ old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); -+ -+ curval1 = R_REG(&pi->regs->psm_corectlsts); -+ ptr[130] = 0; -+ W_REG(&pi->regs->psm_corectlsts, ((1 << 6) | curval1)); -+ -+ W_REG(&pi->regs->smpl_clct_strptr, 0x7E00); -+ W_REG(&pi->regs->smpl_clct_stpptr, 0x8000); -+ udelay(20); -+ curval2 = R_REG(&pi->regs->psm_phy_hdr_param); -+ W_REG(&pi->regs->psm_phy_hdr_param, curval2 | 0x30); -+ -+ write_phy_reg(pi, 0x555, 0x0); -+ write_phy_reg(pi, 0x5a6, 0x5); -+ -+ write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6)); -+ write_phy_reg(pi, 0x5cf, 3); -+ write_phy_reg(pi, 0x5a5, 0x3); -+ write_phy_reg(pi, 0x583, 0x0); -+ write_phy_reg(pi, 0x584, 0x0); -+ write_phy_reg(pi, 0x585, 0x0fff); -+ write_phy_reg(pi, 0x586, 0x0000); -+ -+ write_phy_reg(pi, 0x580, 0x4501); -+ -+ sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); -+ write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008)); -+ stpptr = R_REG(&pi->regs->smpl_clct_stpptr); -+ curptr = R_REG(&pi->regs->smpl_clct_curptr); -+ do { -+ udelay(10); -+ curptr = R_REG(&pi->regs->smpl_clct_curptr); -+ timer++; -+ } while ((curptr != stpptr) && (timer < 500)); -+ -+ W_REG(&pi->regs->psm_phy_hdr_param, 0x2); -+ strptr = 0x7E00; -+ W_REG(&pi->regs->tplatewrptr, strptr); -+ while (strptr < 0x8000) { -+ val = R_REG(&pi->regs->tplatewrdata); -+ imag = ((val >> 16) & 0x3ff); -+ real = ((val) & 0x3ff); -+ if (imag > 511) -+ imag -= 1024; -+ -+ if (real > 511) -+ real -= 1024; -+ -+ if (pi_lcn->lcnphy_iqcal_swp_dis) -+ ptr[(strptr - 0x7E00) / 4] = real; -+ else -+ ptr[(strptr - 0x7E00) / 4] = imag; -+ -+ if (clip_detect_algo) { -+ if (imag > thresh || imag < -thresh) { -+ strptr = 0x8000; -+ ptr[130] = 1; -+ } -+ } -+ -+ strptr += 4; -+ } -+ -+ write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); -+ W_REG(&pi->regs->psm_phy_hdr_param, curval2); -+ W_REG(&pi->regs->psm_corectlsts, curval1); -+} -+ -+static void -+wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels, -+ int step_size_lg2) -+{ -+ const struct lcnphy_spb_tone *phy_c1; -+ struct lcnphy_spb_tone phy_c2; -+ struct lcnphy_unsign16_struct phy_c3; -+ int phy_c4, phy_c5, k, l, j, phy_c6; -+ u16 phy_c7, phy_c8, phy_c9; -+ s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16; -+ s16 *ptr, phy_c17; -+ s32 phy_c18, phy_c19; -+ u32 phy_c20, phy_c21; -+ bool phy_c22, phy_c23, phy_c24, phy_c25; -+ u16 phy_c26, phy_c27; -+ u16 phy_c28, phy_c29, phy_c30; -+ u16 phy_c31; -+ u16 *phy_c32; -+ phy_c21 = 0; -+ phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0; -+ ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC); -+ if (NULL == ptr) -+ return; -+ -+ phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC); -+ if (NULL == phy_c32) { -+ kfree(ptr); -+ return; -+ } -+ phy_c26 = read_phy_reg(pi, 0x6da); -+ phy_c27 = read_phy_reg(pi, 0x6db); -+ phy_c31 = read_radio_reg(pi, RADIO_2064_REG026); -+ write_phy_reg(pi, 0x93d, 0xC0); -+ -+ wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0); -+ write_phy_reg(pi, 0x6da, 0xffff); -+ or_phy_reg(pi, 0x6db, 0x3); -+ -+ wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32); -+ udelay(500); -+ phy_c28 = read_phy_reg(pi, 0x938); -+ phy_c29 = read_phy_reg(pi, 0x4d7); -+ phy_c30 = read_phy_reg(pi, 0x4d8); -+ or_phy_reg(pi, 0x938, 0x1 << 2); -+ or_phy_reg(pi, 0x4d7, 0x1 << 2); -+ or_phy_reg(pi, 0x4d7, 0x1 << 3); -+ mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12); -+ or_phy_reg(pi, 0x4d8, 1 << 0); -+ or_phy_reg(pi, 0x4d8, 1 << 1); -+ mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2); -+ mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12); -+ phy_c1 = &lcnphy_spb_tone_3750[0]; -+ phy_c4 = 32; -+ -+ if (num_levels == 0) { -+ if (cal_type != 0) -+ num_levels = 4; -+ else -+ num_levels = 9; -+ } -+ if (step_size_lg2 == 0) { -+ if (cal_type != 0) -+ step_size_lg2 = 3; -+ else -+ step_size_lg2 = 8; -+ } -+ -+ phy_c7 = (1 << step_size_lg2); -+ phy_c3 = wlc_lcnphy_get_cc(pi, cal_type); -+ phy_c15 = (s16) phy_c3.re; -+ phy_c16 = (s16) phy_c3.im; -+ if (cal_type == 2) { -+ if (phy_c3.re > 127) -+ phy_c15 = phy_c3.re - 256; -+ if (phy_c3.im > 127) -+ phy_c16 = phy_c3.im - 256; -+ } -+ wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16); -+ udelay(20); -+ for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) { -+ phy_c23 = 1; -+ phy_c22 = 0; -+ switch (cal_type) { -+ case 0: -+ phy_c10 = 511; -+ break; -+ case 2: -+ phy_c10 = 127; -+ break; -+ case 3: -+ phy_c10 = 15; -+ break; -+ case 4: -+ phy_c10 = 15; -+ break; -+ } -+ -+ phy_c9 = read_phy_reg(pi, 0x93d); -+ phy_c9 = 2 * phy_c9; -+ phy_c24 = 0; -+ phy_c5 = 7; -+ phy_c25 = 1; -+ while (1) { -+ write_radio_reg(pi, RADIO_2064_REG026, -+ (phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4)); -+ udelay(50); -+ phy_c22 = 0; -+ ptr[130] = 0; -+ wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2); -+ if (ptr[130] == 1) -+ phy_c22 = 1; -+ if (phy_c22) -+ phy_c5 -= 1; -+ if ((phy_c22 != phy_c24) && (!phy_c25)) -+ break; -+ if (!phy_c22) -+ phy_c5 += 1; -+ if (phy_c5 <= 0 || phy_c5 >= 7) -+ break; -+ phy_c24 = phy_c22; -+ phy_c25 = 0; -+ } -+ -+ if (phy_c5 < 0) -+ phy_c5 = 0; -+ else if (phy_c5 > 7) -+ phy_c5 = 7; -+ -+ for (k = -phy_c7; k <= phy_c7; k += phy_c7) { -+ for (l = -phy_c7; l <= phy_c7; l += phy_c7) { -+ phy_c11 = phy_c15 + k; -+ phy_c12 = phy_c16 + l; -+ -+ if (phy_c11 < -phy_c10) -+ phy_c11 = -phy_c10; -+ else if (phy_c11 > phy_c10) -+ phy_c11 = phy_c10; -+ if (phy_c12 < -phy_c10) -+ phy_c12 = -phy_c10; -+ else if (phy_c12 > phy_c10) -+ phy_c12 = phy_c10; -+ wlc_lcnphy_set_cc(pi, cal_type, phy_c11, -+ phy_c12); -+ udelay(20); -+ wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2); -+ -+ phy_c18 = 0; -+ phy_c19 = 0; -+ for (j = 0; j < 128; j++) { -+ if (cal_type != 0) -+ phy_c6 = j % phy_c4; -+ else -+ phy_c6 = (2 * j) % phy_c4; -+ -+ phy_c2.re = phy_c1[phy_c6].re; -+ phy_c2.im = phy_c1[phy_c6].im; -+ phy_c17 = ptr[j]; -+ phy_c18 = phy_c18 + phy_c17 * phy_c2.re; -+ phy_c19 = phy_c19 + phy_c17 * phy_c2.im; -+ } -+ -+ phy_c18 = phy_c18 >> 10; -+ phy_c19 = phy_c19 >> 10; -+ phy_c20 = ((phy_c18 * phy_c18) + -+ (phy_c19 * phy_c19)); -+ -+ if (phy_c23 || phy_c20 < phy_c21) { -+ phy_c21 = phy_c20; -+ phy_c13 = phy_c11; -+ phy_c14 = phy_c12; -+ } -+ phy_c23 = 0; -+ } -+ } -+ phy_c23 = 1; -+ phy_c15 = phy_c13; -+ phy_c16 = phy_c14; -+ phy_c7 = phy_c7 >> 1; -+ wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16); -+ udelay(20); -+ } -+ goto cleanup; -+cleanup: -+ wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32); -+ wlc_lcnphy_stop_tx_tone(pi); -+ write_phy_reg(pi, 0x6da, phy_c26); -+ write_phy_reg(pi, 0x6db, phy_c27); -+ write_phy_reg(pi, 0x938, phy_c28); -+ write_phy_reg(pi, 0x4d7, phy_c29); -+ write_phy_reg(pi, 0x4d8, phy_c30); -+ write_radio_reg(pi, RADIO_2064_REG026, phy_c31); -+ -+ kfree(phy_c32); -+ kfree(ptr); -+} -+ -+void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b) -+{ -+ u16 iqcc[2]; -+ struct phytbl_info tab; -+ -+ tab.tbl_ptr = iqcc; -+ tab.tbl_len = 2; -+ tab.tbl_id = 0; -+ tab.tbl_offset = 80; -+ tab.tbl_width = 16; -+ wlc_lcnphy_read_table(pi, &tab); -+ -+ *a = iqcc[0]; -+ *b = iqcc[1]; -+} -+ -+static void wlc_lcnphy_tx_iqlo_soft_cal_full(struct brcms_phy *pi) -+{ -+ struct lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4; -+ -+ wlc_lcnphy_set_cc(pi, 0, 0, 0); -+ wlc_lcnphy_set_cc(pi, 2, 0, 0); -+ wlc_lcnphy_set_cc(pi, 3, 0, 0); -+ wlc_lcnphy_set_cc(pi, 4, 0, 0); -+ -+ wlc_lcnphy_a1(pi, 4, 0, 0); -+ wlc_lcnphy_a1(pi, 3, 0, 0); -+ wlc_lcnphy_a1(pi, 2, 3, 2); -+ wlc_lcnphy_a1(pi, 0, 5, 8); -+ wlc_lcnphy_a1(pi, 2, 2, 1); -+ wlc_lcnphy_a1(pi, 0, 4, 3); -+ -+ iqcc0 = wlc_lcnphy_get_cc(pi, 0); -+ locc2 = wlc_lcnphy_get_cc(pi, 2); -+ locc3 = wlc_lcnphy_get_cc(pi, 3); -+ locc4 = wlc_lcnphy_get_cc(pi, 4); -+} -+ -+u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi) -+{ -+ struct phytbl_info tab; -+ u16 didq; -+ -+ tab.tbl_id = 0; -+ tab.tbl_width = 16; -+ tab.tbl_ptr = &didq; -+ tab.tbl_len = 1; -+ tab.tbl_offset = 85; -+ wlc_lcnphy_read_table(pi, &tab); -+ -+ return didq; -+} -+ -+static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi) -+{ -+ -+ struct lcnphy_txgains target_gains, old_gains; -+ u8 save_bb_mult; -+ u16 a, b, didq, save_pa_gain = 0; -+ uint idx, SAVE_txpwrindex = 0xFF; -+ u32 val; -+ u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); -+ struct phytbl_info tab; -+ u8 ei0, eq0, fi0, fq0; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ wlc_lcnphy_get_tx_gain(pi, &old_gains); -+ save_pa_gain = wlc_lcnphy_get_pa_gain(pi); -+ -+ save_bb_mult = wlc_lcnphy_get_bbmult(pi); -+ -+ if (SAVE_txpwrctrl == LCNPHY_TX_PWR_CTRL_OFF) -+ SAVE_txpwrindex = wlc_lcnphy_get_current_tx_pwr_idx(pi); -+ -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); -+ -+ target_gains.gm_gain = 7; -+ target_gains.pga_gain = 0; -+ target_gains.pad_gain = 21; -+ target_gains.dac_gain = 0; -+ wlc_lcnphy_set_tx_gain(pi, &target_gains); -+ wlc_lcnphy_set_tx_pwr_by_index(pi, 16); -+ -+ if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) { -+ -+ wlc_lcnphy_set_tx_pwr_by_index(pi, 30); -+ -+ wlc_lcnphy_tx_iqlo_cal(pi, &target_gains, -+ (pi_lcn-> -+ lcnphy_recal ? LCNPHY_CAL_RECAL : -+ LCNPHY_CAL_FULL), false); -+ } else { -+ wlc_lcnphy_tx_iqlo_soft_cal_full(pi); -+ } -+ -+ wlc_lcnphy_get_radio_loft(pi, &ei0, &eq0, &fi0, &fq0); -+ if ((abs((s8) fi0) == 15) && (abs((s8) fq0) == 15)) { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ target_gains.gm_gain = 255; -+ target_gains.pga_gain = 255; -+ target_gains.pad_gain = 0xf0; -+ target_gains.dac_gain = 0; -+ } else { -+ target_gains.gm_gain = 7; -+ target_gains.pga_gain = 45; -+ target_gains.pad_gain = 186; -+ target_gains.dac_gain = 0; -+ } -+ -+ if (LCNREV_IS(pi->pubpi.phy_rev, 1) -+ || pi_lcn->lcnphy_hw_iqcal_en) { -+ -+ target_gains.pga_gain = 0; -+ target_gains.pad_gain = 30; -+ wlc_lcnphy_set_tx_pwr_by_index(pi, 16); -+ wlc_lcnphy_tx_iqlo_cal(pi, &target_gains, -+ LCNPHY_CAL_FULL, false); -+ } else { -+ wlc_lcnphy_tx_iqlo_soft_cal_full(pi); -+ } -+ } -+ -+ wlc_lcnphy_get_tx_iqcc(pi, &a, &b); -+ -+ didq = wlc_lcnphy_get_tx_locc(pi); -+ -+ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; -+ tab.tbl_width = 32; -+ tab.tbl_ptr = &val; -+ -+ tab.tbl_len = 1; -+ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET; -+ -+ for (idx = 0; idx < 128; idx++) { -+ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + idx; -+ -+ wlc_lcnphy_read_table(pi, &tab); -+ val = (val & 0xfff00000) | -+ ((u32) (a & 0x3FF) << 10) | (b & 0x3ff); -+ wlc_lcnphy_write_table(pi, &tab); -+ -+ val = didq; -+ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + idx; -+ wlc_lcnphy_write_table(pi, &tab); -+ } -+ -+ pi_lcn->lcnphy_cal_results.txiqlocal_a = a; -+ pi_lcn->lcnphy_cal_results.txiqlocal_b = b; -+ pi_lcn->lcnphy_cal_results.txiqlocal_didq = didq; -+ pi_lcn->lcnphy_cal_results.txiqlocal_ei0 = ei0; -+ pi_lcn->lcnphy_cal_results.txiqlocal_eq0 = eq0; -+ pi_lcn->lcnphy_cal_results.txiqlocal_fi0 = fi0; -+ pi_lcn->lcnphy_cal_results.txiqlocal_fq0 = fq0; -+ -+ wlc_lcnphy_set_bbmult(pi, save_bb_mult); -+ wlc_lcnphy_set_pa_gain(pi, save_pa_gain); -+ wlc_lcnphy_set_tx_gain(pi, &old_gains); -+ -+ if (SAVE_txpwrctrl != LCNPHY_TX_PWR_CTRL_OFF) -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); -+ else -+ wlc_lcnphy_set_tx_pwr_by_index(pi, SAVE_txpwrindex); -+} -+ -+s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode) -+{ -+ u16 tempsenseval1, tempsenseval2; -+ s16 avg = 0; -+ bool suspend = 0; -+ -+ if (mode == 1) { -+ suspend = -+ (0 == -+ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); -+ if (!suspend) -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); -+ } -+ tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF; -+ tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF; -+ -+ if (tempsenseval1 > 255) -+ avg = (s16) (tempsenseval1 - 512); -+ else -+ avg = (s16) tempsenseval1; -+ -+ if (tempsenseval2 > 255) -+ avg += (s16) (tempsenseval2 - 512); -+ else -+ avg += (s16) tempsenseval2; -+ -+ avg /= 2; -+ -+ if (mode == 1) { -+ -+ mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14); -+ -+ udelay(100); -+ mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14); -+ -+ if (!suspend) -+ wlapi_enable_mac(pi->sh->physhim); -+ } -+ return avg; -+} -+ -+u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode) -+{ -+ u16 tempsenseval1, tempsenseval2; -+ s32 avg = 0; -+ bool suspend = 0; -+ u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ if (mode == 1) { -+ suspend = -+ (0 == -+ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); -+ if (!suspend) -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); -+ } -+ tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF; -+ tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF; -+ -+ if (tempsenseval1 > 255) -+ avg = (int)(tempsenseval1 - 512); -+ else -+ avg = (int)tempsenseval1; -+ -+ if (pi_lcn->lcnphy_tempsense_option == 1 || pi->hwpwrctrl_capable) { -+ if (tempsenseval2 > 255) -+ avg = (int)(avg - tempsenseval2 + 512); -+ else -+ avg = (int)(avg - tempsenseval2); -+ } else { -+ if (tempsenseval2 > 255) -+ avg = (int)(avg + tempsenseval2 - 512); -+ else -+ avg = (int)(avg + tempsenseval2); -+ avg = avg / 2; -+ } -+ if (avg < 0) -+ avg = avg + 512; -+ -+ if (pi_lcn->lcnphy_tempsense_option == 2) -+ avg = tempsenseval1; -+ -+ if (mode) -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); -+ -+ if (mode == 1) { -+ -+ mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14); -+ -+ udelay(100); -+ mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14); -+ -+ if (!suspend) -+ wlapi_enable_mac(pi->sh->physhim); -+ } -+ return (u16) avg; -+} -+ -+s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode) -+{ -+ s32 degree = wlc_lcnphy_tempsense_new(pi, mode); -+ degree = -+ ((degree << -+ 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1)) -+ / LCN_TEMPSENSE_DEN; -+ return (s8) degree; -+} -+ -+s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode) -+{ -+ u16 vbatsenseval; -+ s32 avg = 0; -+ bool suspend = 0; -+ -+ if (mode == 1) { -+ suspend = -+ (0 == -+ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); -+ if (!suspend) -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE); -+ } -+ -+ vbatsenseval = read_phy_reg(pi, 0x475) & 0x1FF; -+ -+ if (vbatsenseval > 255) -+ avg = (s32) (vbatsenseval - 512); -+ else -+ avg = (s32) vbatsenseval; -+ -+ avg = (avg * LCN_VBAT_SCALE_NOM + -+ (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN; -+ -+ if (mode == 1) { -+ if (!suspend) -+ wlapi_enable_mac(pi->sh->physhim); -+ } -+ return (s8) avg; -+} -+ -+static void wlc_lcnphy_afe_clk_init(struct brcms_phy *pi, u8 mode) -+{ -+ u8 phybw40; -+ phybw40 = CHSPEC_IS40(pi->radio_chanspec); -+ -+ mod_phy_reg(pi, 0x6d1, (0x1 << 7), (1) << 7); -+ -+ if (((mode == AFE_CLK_INIT_MODE_PAPD) && (phybw40 == 0)) || -+ (mode == AFE_CLK_INIT_MODE_TXRX2X)) -+ write_phy_reg(pi, 0x6d0, 0x7); -+ -+ wlc_lcnphy_toggle_afe_pwdn(pi); -+} -+ -+static void wlc_lcnphy_temp_adj(struct brcms_phy *pi) -+{ -+} -+ -+static void wlc_lcnphy_glacial_timer_based_cal(struct brcms_phy *pi) -+{ -+ bool suspend; -+ s8 index; -+ u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ suspend = -+ (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); -+ if (!suspend) -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ wlc_lcnphy_deaf_mode(pi, true); -+ pi->phy_lastcal = pi->sh->now; -+ pi->phy_forcecal = false; -+ index = pi_lcn->lcnphy_current_index; -+ -+ wlc_lcnphy_txpwrtbl_iqlo_cal(pi); -+ -+ wlc_lcnphy_set_tx_pwr_by_index(pi, index); -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl); -+ wlc_lcnphy_deaf_mode(pi, false); -+ if (!suspend) -+ wlapi_enable_mac(pi->sh->physhim); -+ -+} -+ -+static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi) -+{ -+ bool suspend, full_cal; -+ const struct lcnphy_rx_iqcomp *rx_iqcomp; -+ int rx_iqcomp_sz; -+ u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); -+ s8 index; -+ struct phytbl_info tab; -+ s32 a1, b0, b1; -+ s32 tssi, pwr, maxtargetpwr, mintargetpwr; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ pi->phy_lastcal = pi->sh->now; -+ pi->phy_forcecal = false; -+ full_cal = -+ (pi_lcn->lcnphy_full_cal_channel != -+ CHSPEC_CHANNEL(pi->radio_chanspec)); -+ pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec); -+ index = pi_lcn->lcnphy_current_index; -+ -+ suspend = -+ (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); -+ if (!suspend) { -+ wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000); -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ } -+ -+ wlc_lcnphy_deaf_mode(pi, true); -+ -+ wlc_lcnphy_txpwrtbl_iqlo_cal(pi); -+ -+ rx_iqcomp = lcnphy_rx_iqcomp_table_rev0; -+ rx_iqcomp_sz = ARRAY_SIZE(lcnphy_rx_iqcomp_table_rev0); -+ -+ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) -+ wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 40); -+ else -+ wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 127); -+ -+ if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) { -+ -+ wlc_lcnphy_idle_tssi_est((struct brcms_phy_pub *) pi); -+ -+ b0 = pi->txpa_2g[0]; -+ b1 = pi->txpa_2g[1]; -+ a1 = pi->txpa_2g[2]; -+ maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1); -+ mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1); -+ -+ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; -+ tab.tbl_width = 32; -+ tab.tbl_ptr = &pwr; -+ tab.tbl_len = 1; -+ tab.tbl_offset = 0; -+ for (tssi = 0; tssi < 128; tssi++) { -+ pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1); -+ pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr; -+ wlc_lcnphy_write_table(pi, &tab); -+ tab.tbl_offset++; -+ } -+ } -+ -+ wlc_lcnphy_set_tx_pwr_by_index(pi, index); -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl); -+ wlc_lcnphy_deaf_mode(pi, false); -+ if (!suspend) -+ wlapi_enable_mac(pi->sh->physhim); -+} -+ -+void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode) -+{ -+ u16 temp_new; -+ int temp1, temp2, temp_diff; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ switch (mode) { -+ case PHY_PERICAL_CHAN: -+ break; -+ case PHY_FULLCAL: -+ wlc_lcnphy_periodic_cal(pi); -+ break; -+ case PHY_PERICAL_PHYINIT: -+ wlc_lcnphy_periodic_cal(pi); -+ break; -+ case PHY_PERICAL_WATCHDOG: -+ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { -+ temp_new = wlc_lcnphy_tempsense(pi, 0); -+ temp1 = LCNPHY_TEMPSENSE(temp_new); -+ temp2 = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_cal_temper); -+ temp_diff = temp1 - temp2; -+ if ((pi_lcn->lcnphy_cal_counter > 90) || -+ (temp_diff > 60) || (temp_diff < -60)) { -+ wlc_lcnphy_glacial_timer_based_cal(pi); -+ wlc_2064_vco_cal(pi); -+ pi_lcn->lcnphy_cal_temper = temp_new; -+ pi_lcn->lcnphy_cal_counter = 0; -+ } else -+ pi_lcn->lcnphy_cal_counter++; -+ } -+ break; -+ case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL: -+ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) -+ wlc_lcnphy_tx_power_adjustment( -+ (struct brcms_phy_pub *) pi); -+ break; -+ } -+} -+ -+void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, s8 *cck_pwr) -+{ -+ s8 cck_offset; -+ u16 status; -+ status = (read_phy_reg(pi, 0x4ab)); -+ if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) && -+ (status & (0x1 << 15))) { -+ *ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0)) -+ >> 0) >> 1); -+ -+ if (wlc_phy_tpc_isenabled_lcnphy(pi)) -+ cck_offset = pi->tx_power_offset[TXP_FIRST_CCK]; -+ else -+ cck_offset = 0; -+ -+ *cck_pwr = *ofdm_pwr + cck_offset; -+ } else { -+ *cck_pwr = 0; -+ *ofdm_pwr = 0; -+ } -+} -+ -+void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi) -+{ -+ return; -+ -+} -+ -+void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi) -+{ -+ s8 index; -+ u16 index2; -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); -+ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && -+ SAVE_txpwrctrl) { -+ index = wlc_lcnphy_tempcompensated_txpwrctrl(pi); -+ index2 = (u16) (index * 2); -+ mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0); -+ -+ pi_lcn->lcnphy_current_index = -+ (s8)((read_phy_reg(pi, 0x4a9) & 0xFF) / 2); -+ } -+} -+ -+static void -+wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi, -+ const struct lcnphy_tx_gain_tbl_entry *gain_table) -+{ -+ u32 j; -+ struct phytbl_info tab; -+ u32 val; -+ u16 pa_gain; -+ u16 gm_gain; -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) -+ pa_gain = 0x70; -+ else -+ pa_gain = 0x70; -+ -+ if (pi->sh->boardflags & BFL_FEM) -+ pa_gain = 0x10; -+ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; -+ tab.tbl_width = 32; -+ tab.tbl_len = 1; -+ tab.tbl_ptr = &val; -+ -+ for (j = 0; j < 128; j++) { -+ gm_gain = gain_table[j].gm; -+ val = (((u32) pa_gain << 24) | -+ (gain_table[j].pad << 16) | -+ (gain_table[j].pga << 8) | gm_gain); -+ -+ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + j; -+ wlc_lcnphy_write_table(pi, &tab); -+ -+ val = (gain_table[j].dac << 28) | (gain_table[j].bb_mult << 20); -+ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + j; -+ wlc_lcnphy_write_table(pi, &tab); -+ } -+} -+ -+static void wlc_lcnphy_load_rfpower(struct brcms_phy *pi) -+{ -+ struct phytbl_info tab; -+ u32 val, bbmult, rfgain; -+ u8 index; -+ u8 scale_factor = 1; -+ s16 temp, temp1, temp2, qQ, qQ1, qQ2, shift; -+ -+ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; -+ tab.tbl_width = 32; -+ tab.tbl_len = 1; -+ -+ for (index = 0; index < 128; index++) { -+ tab.tbl_ptr = &bbmult; -+ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index; -+ wlc_lcnphy_read_table(pi, &tab); -+ bbmult = bbmult >> 20; -+ -+ tab.tbl_ptr = &rfgain; -+ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index; -+ wlc_lcnphy_read_table(pi, &tab); -+ -+ qm_log10((s32) (bbmult), 0, &temp1, &qQ1); -+ qm_log10((s32) (1 << 6), 0, &temp2, &qQ2); -+ -+ if (qQ1 < qQ2) { -+ temp2 = qm_shr16(temp2, qQ2 - qQ1); -+ qQ = qQ1; -+ } else { -+ temp1 = qm_shr16(temp1, qQ1 - qQ2); -+ qQ = qQ2; -+ } -+ temp = qm_sub16(temp1, temp2); -+ -+ if (qQ >= 4) -+ shift = qQ - 4; -+ else -+ shift = 4 - qQ; -+ -+ val = (((index << shift) + (5 * temp) + -+ (1 << (scale_factor + shift - 3))) >> (scale_factor + -+ shift - 2)); -+ -+ tab.tbl_ptr = &val; -+ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index; -+ wlc_lcnphy_write_table(pi, &tab); -+ } -+} -+ -+static void wlc_lcnphy_bu_tweaks(struct brcms_phy *pi) -+{ -+ or_phy_reg(pi, 0x805, 0x1); -+ -+ mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0); -+ -+ mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0); -+ -+ write_phy_reg(pi, 0x414, 0x1e10); -+ write_phy_reg(pi, 0x415, 0x0640); -+ -+ mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8); -+ -+ or_phy_reg(pi, 0x44a, 0x44); -+ write_phy_reg(pi, 0x44a, 0x80); -+ mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0); -+ -+ mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0); -+ -+ if (!(pi->sh->boardrev < 0x1204)) -+ mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0); -+ -+ write_phy_reg(pi, 0x7d6, 0x0902); -+ mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0); -+ -+ mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4); -+ -+ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { -+ mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0); -+ -+ mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0); -+ -+ mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0); -+ -+ mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0); -+ -+ mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2); -+ -+ mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4); -+ mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0); -+ mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90); -+ mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2); -+ mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0); -+ -+ mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2); -+ -+ wlc_lcnphy_clear_tx_power_offsets(pi); -+ mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6); -+ -+ } -+} -+ -+static void wlc_lcnphy_rcal(struct brcms_phy *pi) -+{ -+ u8 rcal_value; -+ -+ and_radio_reg(pi, RADIO_2064_REG05B, 0xfD); -+ -+ or_radio_reg(pi, RADIO_2064_REG004, 0x40); -+ or_radio_reg(pi, RADIO_2064_REG120, 0x10); -+ -+ or_radio_reg(pi, RADIO_2064_REG078, 0x80); -+ or_radio_reg(pi, RADIO_2064_REG129, 0x02); -+ -+ or_radio_reg(pi, RADIO_2064_REG057, 0x01); -+ -+ or_radio_reg(pi, RADIO_2064_REG05B, 0x02); -+ mdelay(5); -+ SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000); -+ -+ if (wlc_radio_2064_rcal_done(pi)) { -+ rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C); -+ rcal_value = rcal_value & 0x1f; -+ } -+ -+ and_radio_reg(pi, RADIO_2064_REG05B, 0xfD); -+ -+ and_radio_reg(pi, RADIO_2064_REG057, 0xFE); -+} -+ -+static void wlc_lcnphy_rc_cal(struct brcms_phy *pi) -+{ -+ u8 dflt_rc_cal_val; -+ u16 flt_val; -+ -+ dflt_rc_cal_val = 7; -+ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) -+ dflt_rc_cal_val = 11; -+ flt_val = -+ (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) | -+ (dflt_rc_cal_val); -+ write_phy_reg(pi, 0x933, flt_val); -+ write_phy_reg(pi, 0x934, flt_val); -+ write_phy_reg(pi, 0x935, flt_val); -+ write_phy_reg(pi, 0x936, flt_val); -+ write_phy_reg(pi, 0x937, (flt_val & 0x1FF)); -+ -+ return; -+} -+ -+static void wlc_radio_2064_init(struct brcms_phy *pi) -+{ -+ u32 i; -+ const struct lcnphy_radio_regs *lcnphyregs = NULL; -+ -+ lcnphyregs = lcnphy_radio_regs_2064; -+ -+ for (i = 0; lcnphyregs[i].address != 0xffff; i++) -+ if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a) -+ write_radio_reg(pi, -+ ((lcnphyregs[i].address & 0x3fff) | -+ RADIO_DEFAULT_CORE), -+ (u16) lcnphyregs[i].init_a); -+ else if (lcnphyregs[i].do_init_g) -+ write_radio_reg(pi, -+ ((lcnphyregs[i].address & 0x3fff) | -+ RADIO_DEFAULT_CORE), -+ (u16) lcnphyregs[i].init_g); -+ -+ write_radio_reg(pi, RADIO_2064_REG032, 0x62); -+ write_radio_reg(pi, RADIO_2064_REG033, 0x19); -+ -+ write_radio_reg(pi, RADIO_2064_REG090, 0x10); -+ -+ write_radio_reg(pi, RADIO_2064_REG010, 0x00); -+ -+ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { -+ -+ write_radio_reg(pi, RADIO_2064_REG060, 0x7f); -+ write_radio_reg(pi, RADIO_2064_REG061, 0x72); -+ write_radio_reg(pi, RADIO_2064_REG062, 0x7f); -+ } -+ -+ write_radio_reg(pi, RADIO_2064_REG01D, 0x02); -+ write_radio_reg(pi, RADIO_2064_REG01E, 0x06); -+ -+ mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0); -+ -+ mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3); -+ -+ mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6); -+ -+ mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9); -+ -+ mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12); -+ -+ write_phy_reg(pi, 0x4ea, 0x4688); -+ -+ mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0); -+ -+ mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6); -+ -+ mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0); -+ -+ wlc_lcnphy_set_tx_locc(pi, 0); -+ -+ wlc_lcnphy_rcal(pi); -+ -+ wlc_lcnphy_rc_cal(pi); -+} -+ -+static void wlc_lcnphy_radio_init(struct brcms_phy *pi) -+{ -+ wlc_radio_2064_init(pi); -+} -+ -+static void wlc_lcnphy_tbl_init(struct brcms_phy *pi) -+{ -+ uint idx; -+ u8 phybw40; -+ struct phytbl_info tab; -+ u32 val; -+ -+ phybw40 = CHSPEC_IS40(pi->radio_chanspec); -+ -+ for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++) -+ wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]); -+ -+ if (pi->sh->boardflags & BFL_FEM_BT) { -+ tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; -+ tab.tbl_width = 16; -+ tab.tbl_ptr = &val; -+ tab.tbl_len = 1; -+ val = 100; -+ tab.tbl_offset = 4; -+ wlc_lcnphy_write_table(pi, &tab); -+ } -+ -+ tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; -+ tab.tbl_width = 16; -+ tab.tbl_ptr = &val; -+ tab.tbl_len = 1; -+ -+ val = 114; -+ tab.tbl_offset = 0; -+ wlc_lcnphy_write_table(pi, &tab); -+ -+ val = 130; -+ tab.tbl_offset = 1; -+ wlc_lcnphy_write_table(pi, &tab); -+ -+ val = 6; -+ tab.tbl_offset = 8; -+ wlc_lcnphy_write_table(pi, &tab); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if (pi->sh->boardflags & BFL_FEM) -+ wlc_lcnphy_load_tx_gain_table( -+ pi, -+ dot11lcnphy_2GHz_extPA_gaintable_rev0); -+ else -+ wlc_lcnphy_load_tx_gain_table( -+ pi, -+ dot11lcnphy_2GHz_gaintable_rev0); -+ } -+ -+ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { -+ const struct phytbl_info *tb; -+ int l; -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ l = dot11lcnphytbl_rx_gain_info_2G_rev2_sz; -+ if (pi->sh->boardflags & BFL_EXTLNA) -+ tb = dot11lcnphytbl_rx_gain_info_extlna_2G_rev2; -+ else -+ tb = dot11lcnphytbl_rx_gain_info_2G_rev2; -+ } else { -+ l = dot11lcnphytbl_rx_gain_info_5G_rev2_sz; -+ if (pi->sh->boardflags & BFL_EXTLNA_5GHz) -+ tb = dot11lcnphytbl_rx_gain_info_extlna_5G_rev2; -+ else -+ tb = dot11lcnphytbl_rx_gain_info_5G_rev2; -+ } -+ -+ for (idx = 0; idx < l; idx++) -+ wlc_lcnphy_write_table(pi, &tb[idx]); -+ } -+ -+ if ((pi->sh->boardflags & BFL_FEM) -+ && !(pi->sh->boardflags & BFL_FEM_BT)) -+ wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa); -+ else if (pi->sh->boardflags & BFL_FEM_BT) { -+ if (pi->sh->boardrev < 0x1250) -+ wlc_lcnphy_write_table( -+ pi, -+ &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa); -+ else -+ wlc_lcnphy_write_table( -+ pi, -+ &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250); -+ } else -+ wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313); -+ -+ wlc_lcnphy_load_rfpower(pi); -+ -+ wlc_lcnphy_clear_papd_comptable(pi); -+} -+ -+static void wlc_lcnphy_rev0_baseband_init(struct brcms_phy *pi) -+{ -+ u16 afectrl1; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ write_radio_reg(pi, RADIO_2064_REG11C, 0x0); -+ -+ write_phy_reg(pi, 0x43b, 0x0); -+ write_phy_reg(pi, 0x43c, 0x0); -+ write_phy_reg(pi, 0x44c, 0x0); -+ write_phy_reg(pi, 0x4e6, 0x0); -+ write_phy_reg(pi, 0x4f9, 0x0); -+ write_phy_reg(pi, 0x4b0, 0x0); -+ write_phy_reg(pi, 0x938, 0x0); -+ write_phy_reg(pi, 0x4b0, 0x0); -+ write_phy_reg(pi, 0x44e, 0); -+ -+ or_phy_reg(pi, 0x567, 0x03); -+ -+ or_phy_reg(pi, 0x44a, 0x44); -+ write_phy_reg(pi, 0x44a, 0x80); -+ -+ if (!(pi->sh->boardflags & BFL_FEM)) -+ wlc_lcnphy_set_tx_pwr_by_index(pi, 52); -+ -+ if (0) { -+ afectrl1 = 0; -+ afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) | -+ (pi_lcn->lcnphy_rssi_vc << 4) | -+ (pi_lcn->lcnphy_rssi_gs << 10)); -+ write_phy_reg(pi, 0x43e, afectrl1); -+ } -+ -+ mod_phy_reg(pi, 0x634, (0xff << 0), 0xC << 0); -+ if (pi->sh->boardflags & BFL_FEM) { -+ mod_phy_reg(pi, 0x634, (0xff << 0), 0xA << 0); -+ -+ write_phy_reg(pi, 0x910, 0x1); -+ } -+ -+ mod_phy_reg(pi, 0x448, (0x3 << 8), 1 << 8); -+ mod_phy_reg(pi, 0x608, (0xff << 0), 0x17 << 0); -+ mod_phy_reg(pi, 0x604, (0x7ff << 0), 0x3EA << 0); -+ -+} -+ -+static void wlc_lcnphy_rev2_baseband_init(struct brcms_phy *pi) -+{ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0); -+ mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8); -+ } -+} -+ -+static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi) -+{ -+ s16 temp; -+ struct phytbl_info tab; -+ u32 tableBuffer[2]; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ temp = (s16) read_phy_reg(pi, 0x4df); -+ pi_lcn->lcnphy_ofdmgainidxtableoffset = (temp & (0xff << 0)) >> 0; -+ -+ if (pi_lcn->lcnphy_ofdmgainidxtableoffset > 127) -+ pi_lcn->lcnphy_ofdmgainidxtableoffset -= 256; -+ -+ pi_lcn->lcnphy_dsssgainidxtableoffset = (temp & (0xff << 8)) >> 8; -+ -+ if (pi_lcn->lcnphy_dsssgainidxtableoffset > 127) -+ pi_lcn->lcnphy_dsssgainidxtableoffset -= 256; -+ -+ tab.tbl_ptr = tableBuffer; -+ tab.tbl_len = 2; -+ tab.tbl_id = 17; -+ tab.tbl_offset = 59; -+ tab.tbl_width = 32; -+ wlc_lcnphy_read_table(pi, &tab); -+ -+ if (tableBuffer[0] > 63) -+ tableBuffer[0] -= 128; -+ pi_lcn->lcnphy_tr_R_gain_val = tableBuffer[0]; -+ -+ if (tableBuffer[1] > 63) -+ tableBuffer[1] -= 128; -+ pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1]; -+ -+ temp = (s16) (read_phy_reg(pi, 0x434) & (0xff << 0)); -+ if (temp > 127) -+ temp -= 256; -+ pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp; -+ -+ pi_lcn->lcnphy_Med_Low_Gain_db = -+ (read_phy_reg(pi, 0x424) & (0xff << 8)) >> 8; -+ pi_lcn->lcnphy_Very_Low_Gain_db = -+ (read_phy_reg(pi, 0x425) & (0xff << 0)) >> 0; -+ -+ tab.tbl_ptr = tableBuffer; -+ tab.tbl_len = 2; -+ tab.tbl_id = LCNPHY_TBL_ID_GAIN_IDX; -+ tab.tbl_offset = 28; -+ tab.tbl_width = 32; -+ wlc_lcnphy_read_table(pi, &tab); -+ -+ pi_lcn->lcnphy_gain_idx_14_lowword = tableBuffer[0]; -+ pi_lcn->lcnphy_gain_idx_14_hiword = tableBuffer[1]; -+ -+} -+ -+static void wlc_lcnphy_baseband_init(struct brcms_phy *pi) -+{ -+ -+ wlc_lcnphy_tbl_init(pi); -+ wlc_lcnphy_rev0_baseband_init(pi); -+ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) -+ wlc_lcnphy_rev2_baseband_init(pi); -+ wlc_lcnphy_bu_tweaks(pi); -+} -+ -+void wlc_phy_init_lcnphy(struct brcms_phy *pi) -+{ -+ u8 phybw40; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ phybw40 = CHSPEC_IS40(pi->radio_chanspec); -+ -+ pi_lcn->lcnphy_cal_counter = 0; -+ pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense; -+ -+ or_phy_reg(pi, 0x44a, 0x80); -+ and_phy_reg(pi, 0x44a, 0x7f); -+ -+ wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X); -+ -+ write_phy_reg(pi, 0x60a, 160); -+ -+ write_phy_reg(pi, 0x46a, 25); -+ -+ wlc_lcnphy_baseband_init(pi); -+ -+ wlc_lcnphy_radio_init(pi); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) -+ wlc_lcnphy_tx_pwr_ctrl_init((struct brcms_phy_pub *) pi); -+ -+ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec); -+ -+ si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9); -+ -+ si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD); -+ -+ if ((pi->sh->boardflags & BFL_FEM) -+ && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) -+ wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR); -+ -+ wlc_lcnphy_agc_temp_init(pi); -+ -+ wlc_lcnphy_temp_adj(pi); -+ -+ mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14); -+ -+ udelay(100); -+ mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14); -+ -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW); -+ pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT; -+ wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT); -+} -+ -+static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) -+{ -+ s8 txpwr = 0; -+ int i; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ struct phy_shim_info *shim = pi->sh->physhim; -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ u16 cckpo = 0; -+ u32 offset_ofdm, offset_mcs; -+ -+ pi_lcn->lcnphy_tr_isolation_mid = -+ (u8)wlapi_getintvar(shim, BRCMS_SROM_TRISO2G); -+ -+ pi_lcn->lcnphy_rx_power_offset = -+ (u8)wlapi_getintvar(shim, BRCMS_SROM_RXPO2G); -+ -+ pi->txpa_2g[0] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B0); -+ pi->txpa_2g[1] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B1); -+ pi->txpa_2g[2] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B2); -+ -+ pi_lcn->lcnphy_rssi_vf = -+ (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMF2G); -+ pi_lcn->lcnphy_rssi_vc = -+ (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMC2G); -+ pi_lcn->lcnphy_rssi_gs = -+ (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISAV2G); -+ -+ pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf; -+ pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc; -+ pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs; -+ -+ pi_lcn->lcnphy_rssi_vf_hightemp = pi_lcn->lcnphy_rssi_vf; -+ pi_lcn->lcnphy_rssi_vc_hightemp = pi_lcn->lcnphy_rssi_vc; -+ pi_lcn->lcnphy_rssi_gs_hightemp = pi_lcn->lcnphy_rssi_gs; -+ -+ txpwr = (s8)wlapi_getintvar(shim, BRCMS_SROM_MAXP2GA0); -+ pi->tx_srom_max_2g = txpwr; -+ -+ for (i = 0; i < PWRTBL_NUM_COEFF; i++) { -+ pi->txpa_2g_low_temp[i] = pi->txpa_2g[i]; -+ pi->txpa_2g_high_temp[i] = pi->txpa_2g[i]; -+ } -+ -+ cckpo = (u16)wlapi_getintvar(shim, BRCMS_SROM_CCK2GPO); -+ offset_ofdm = (u32)wlapi_getintvar(shim, BRCMS_SROM_OFDM2GPO); -+ if (cckpo) { -+ uint max_pwr_chan = txpwr; -+ -+ for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) { -+ pi->tx_srom_max_rate_2g[i] = -+ max_pwr_chan - ((cckpo & 0xf) * 2); -+ cckpo >>= 4; -+ } -+ -+ for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) { -+ pi->tx_srom_max_rate_2g[i] = -+ max_pwr_chan - -+ ((offset_ofdm & 0xf) * 2); -+ offset_ofdm >>= 4; -+ } -+ } else { -+ u8 opo = 0; -+ -+ opo = (u8)wlapi_getintvar(shim, BRCMS_SROM_OPO); -+ -+ for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) -+ pi->tx_srom_max_rate_2g[i] = txpwr; -+ -+ for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) { -+ pi->tx_srom_max_rate_2g[i] = txpwr - -+ ((offset_ofdm & 0xf) * 2); -+ offset_ofdm >>= 4; -+ } -+ offset_mcs = -+ wlapi_getintvar(shim, -+ BRCMS_SROM_MCS2GPO1) << 16; -+ offset_mcs |= -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS2GPO0); -+ pi_lcn->lcnphy_mcs20_po = offset_mcs; -+ for (i = TXP_FIRST_SISO_MCS_20; -+ i <= TXP_LAST_SISO_MCS_20; i++) { -+ pi->tx_srom_max_rate_2g[i] = -+ txpwr - ((offset_mcs & 0xf) * 2); -+ offset_mcs >>= 4; -+ } -+ } -+ -+ pi_lcn->lcnphy_rawtempsense = -+ (u16)wlapi_getintvar(shim, BRCMS_SROM_RAWTEMPSENSE); -+ pi_lcn->lcnphy_measPower = -+ (u8)wlapi_getintvar(shim, BRCMS_SROM_MEASPOWER); -+ pi_lcn->lcnphy_tempsense_slope = -+ (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_SLOPE); -+ pi_lcn->lcnphy_hw_iqcal_en = -+ (bool)wlapi_getintvar(shim, BRCMS_SROM_HW_IQCAL_EN); -+ pi_lcn->lcnphy_iqcal_swp_dis = -+ (bool)wlapi_getintvar(shim, BRCMS_SROM_IQCAL_SWP_DIS); -+ pi_lcn->lcnphy_tempcorrx = -+ (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPCORRX); -+ pi_lcn->lcnphy_tempsense_option = -+ (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_OPTION); -+ pi_lcn->lcnphy_freqoffset_corr = -+ (u8)wlapi_getintvar(shim, BRCMS_SROM_FREQOFFSET_CORR); -+ if ((u8)wlapi_getintvar(shim, BRCMS_SROM_AA2G) > 1) -+ wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, -+ (u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G)); -+ } -+ pi_lcn->lcnphy_cck_dig_filt_type = -1; -+ -+ return true; -+} -+ -+void wlc_2064_vco_cal(struct brcms_phy *pi) -+{ -+ u8 calnrst; -+ -+ mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 1 << 3); -+ calnrst = (u8) read_radio_reg(pi, RADIO_2064_REG056) & 0xf8; -+ write_radio_reg(pi, RADIO_2064_REG056, calnrst); -+ udelay(1); -+ write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x03); -+ udelay(1); -+ write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x07); -+ udelay(300); -+ mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 0); -+} -+ -+bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi) -+{ -+ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) -+ return 0; -+ else -+ return (LCNPHY_TX_PWR_CTRL_HW == -+ wlc_lcnphy_get_tx_pwr_ctrl((pi))); -+} -+ -+void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi) -+{ -+ u16 pwr_ctrl; -+ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { -+ wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL); -+ } else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) { -+ pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); -+ wlc_lcnphy_txpower_recalc_target(pi); -+ wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl); -+ } -+} -+ -+void wlc_phy_detach_lcnphy(struct brcms_phy *pi) -+{ -+ kfree(pi->u.pi_lcnphy); -+} -+ -+bool wlc_phy_attach_lcnphy(struct brcms_phy *pi) -+{ -+ struct brcms_phy_lcnphy *pi_lcn; -+ -+ pi->u.pi_lcnphy = kzalloc(sizeof(struct brcms_phy_lcnphy), GFP_ATOMIC); -+ if (pi->u.pi_lcnphy == NULL) -+ return false; -+ -+ pi_lcn = pi->u.pi_lcnphy; -+ -+ if (0 == (pi->sh->boardflags & BFL_NOPA)) { -+ pi->hwpwrctrl = true; -+ pi->hwpwrctrl_capable = true; -+ } -+ -+ pi->xtalfreq = si_pmu_alp_clock(pi->sh->sih); -+ pi_lcn->lcnphy_papd_rxGnCtrl_init = 0; -+ -+ pi->pi_fptr.init = wlc_phy_init_lcnphy; -+ pi->pi_fptr.calinit = wlc_phy_cal_init_lcnphy; -+ pi->pi_fptr.chanset = wlc_phy_chanspec_set_lcnphy; -+ pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_lcnphy; -+ pi->pi_fptr.txiqccget = wlc_lcnphy_get_tx_iqcc; -+ pi->pi_fptr.txiqccset = wlc_lcnphy_set_tx_iqcc; -+ pi->pi_fptr.txloccget = wlc_lcnphy_get_tx_locc; -+ pi->pi_fptr.radioloftget = wlc_lcnphy_get_radio_loft; -+ pi->pi_fptr.detach = wlc_phy_detach_lcnphy; -+ -+ if (!wlc_phy_txpwr_srom_read_lcnphy(pi)) -+ return false; -+ -+ if ((pi->sh->boardflags & BFL_FEM) && -+ (LCNREV_IS(pi->pubpi.phy_rev, 1))) { -+ if (pi_lcn->lcnphy_tempsense_option == 3) { -+ pi->hwpwrctrl = true; -+ pi->hwpwrctrl_capable = true; -+ pi->temppwrctrl_capable = false; -+ } else { -+ pi->hwpwrctrl = false; -+ pi->hwpwrctrl_capable = false; -+ pi->temppwrctrl_capable = true; -+ } -+ } -+ -+ return true; -+} -+ -+static void wlc_lcnphy_set_rx_gain(struct brcms_phy *pi, u32 gain) -+{ -+ u16 trsw, ext_lna, lna1, lna2, tia, biq0, biq1, gain0_15, gain16_19; -+ -+ trsw = (gain & ((u32) 1 << 28)) ? 0 : 1; -+ ext_lna = (u16) (gain >> 29) & 0x01; -+ lna1 = (u16) (gain >> 0) & 0x0f; -+ lna2 = (u16) (gain >> 4) & 0x0f; -+ tia = (u16) (gain >> 8) & 0xf; -+ biq0 = (u16) (gain >> 12) & 0xf; -+ biq1 = (u16) (gain >> 16) & 0xf; -+ -+ gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) | -+ ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) | -+ ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12)); -+ gain16_19 = biq1; -+ -+ mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0); -+ mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9); -+ mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10); -+ mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0); -+ mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11); -+ mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3); -+ } -+ wlc_lcnphy_rx_gain_override_enable(pi, true); -+} -+ -+static u32 wlc_lcnphy_get_receive_power(struct brcms_phy *pi, s32 *gain_index) -+{ -+ u32 received_power = 0; -+ s32 max_index = 0; -+ u32 gain_code = 0; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ max_index = 36; -+ if (*gain_index >= 0) -+ gain_code = lcnphy_23bitgaincode_table[*gain_index]; -+ -+ if (-1 == *gain_index) { -+ *gain_index = 0; -+ while ((*gain_index <= (s32) max_index) -+ && (received_power < 700)) { -+ wlc_lcnphy_set_rx_gain(pi, -+ lcnphy_23bitgaincode_table -+ [*gain_index]); -+ received_power = -+ wlc_lcnphy_measure_digital_power( -+ pi, -+ pi_lcn-> -+ lcnphy_noise_samples); -+ (*gain_index)++; -+ } -+ (*gain_index)--; -+ } else { -+ wlc_lcnphy_set_rx_gain(pi, gain_code); -+ received_power = -+ wlc_lcnphy_measure_digital_power(pi, -+ pi_lcn-> -+ lcnphy_noise_samples); -+ } -+ -+ return received_power; -+} -+ -+s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index) -+{ -+ s32 gain = 0; -+ s32 nominal_power_db; -+ s32 log_val, gain_mismatch, desired_gain, input_power_offset_db, -+ input_power_db; -+ s32 received_power, temperature; -+ u32 power; -+ u32 msb1, msb2, val1, val2, diff1, diff2; -+ uint freq; -+ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; -+ -+ received_power = wlc_lcnphy_get_receive_power(pi, &gain_index); -+ -+ gain = lcnphy_gain_table[gain_index]; -+ -+ nominal_power_db = read_phy_reg(pi, 0x425) >> 8; -+ -+ power = (received_power * 16); -+ msb1 = ffs(power) - 1; -+ msb2 = msb1 + 1; -+ val1 = 1 << msb1; -+ val2 = 1 << msb2; -+ diff1 = (power - val1); -+ diff2 = (val2 - power); -+ if (diff1 < diff2) -+ log_val = msb1; -+ else -+ log_val = msb2; -+ -+ log_val = log_val * 3; -+ -+ gain_mismatch = (nominal_power_db / 2) - (log_val); -+ -+ desired_gain = gain + gain_mismatch; -+ -+ input_power_offset_db = read_phy_reg(pi, 0x434) & 0xFF; -+ -+ if (input_power_offset_db > 127) -+ input_power_offset_db -= 256; -+ -+ input_power_db = input_power_offset_db - desired_gain; -+ -+ input_power_db = -+ input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index]; -+ -+ freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec)); -+ if ((freq > 2427) && (freq <= 2467)) -+ input_power_db = input_power_db - 1; -+ -+ temperature = pi_lcn->lcnphy_lastsensed_temperature; -+ -+ if ((temperature - 15) < -30) -+ input_power_db = -+ input_power_db + -+ (((temperature - 10 - 25) * 286) >> 12) - -+ 7; -+ else if ((temperature - 15) < 4) -+ input_power_db = -+ input_power_db + -+ (((temperature - 10 - 25) * 286) >> 12) - -+ 3; -+ else -+ input_power_db = input_power_db + -+ (((temperature - 10 - 25) * 286) >> 12); -+ -+ wlc_lcnphy_rx_gain_override_enable(pi, 0); -+ -+ return input_power_db; -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.h.orig 2011-11-09 13:46:58.258800470 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.h 2011-11-09 13:47:17.012566015 -0500 -@@ -0,0 +1,121 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_PHY_LCN_H_ -+#define _BRCM_PHY_LCN_H_ -+ -+#include -+ -+struct brcms_phy_lcnphy { -+ int lcnphy_txrf_sp_9_override; -+ u8 lcnphy_full_cal_channel; -+ u8 lcnphy_cal_counter; -+ u16 lcnphy_cal_temper; -+ bool lcnphy_recal; -+ -+ u8 lcnphy_rc_cap; -+ u32 lcnphy_mcs20_po; -+ -+ u8 lcnphy_tr_isolation_mid; -+ u8 lcnphy_tr_isolation_low; -+ u8 lcnphy_tr_isolation_hi; -+ -+ u8 lcnphy_bx_arch; -+ u8 lcnphy_rx_power_offset; -+ u8 lcnphy_rssi_vf; -+ u8 lcnphy_rssi_vc; -+ u8 lcnphy_rssi_gs; -+ u8 lcnphy_tssi_val; -+ u8 lcnphy_rssi_vf_lowtemp; -+ u8 lcnphy_rssi_vc_lowtemp; -+ u8 lcnphy_rssi_gs_lowtemp; -+ -+ u8 lcnphy_rssi_vf_hightemp; -+ u8 lcnphy_rssi_vc_hightemp; -+ u8 lcnphy_rssi_gs_hightemp; -+ -+ s16 lcnphy_pa0b0; -+ s16 lcnphy_pa0b1; -+ s16 lcnphy_pa0b2; -+ -+ u16 lcnphy_rawtempsense; -+ u8 lcnphy_measPower; -+ u8 lcnphy_tempsense_slope; -+ u8 lcnphy_freqoffset_corr; -+ u8 lcnphy_tempsense_option; -+ u8 lcnphy_tempcorrx; -+ bool lcnphy_iqcal_swp_dis; -+ bool lcnphy_hw_iqcal_en; -+ uint lcnphy_bandedge_corr; -+ bool lcnphy_spurmod; -+ u16 lcnphy_tssi_tx_cnt; -+ u16 lcnphy_tssi_idx; -+ u16 lcnphy_tssi_npt; -+ -+ u16 lcnphy_target_tx_freq; -+ s8 lcnphy_tx_power_idx_override; -+ u16 lcnphy_noise_samples; -+ -+ u32 lcnphy_papdRxGnIdx; -+ u32 lcnphy_papd_rxGnCtrl_init; -+ -+ u32 lcnphy_gain_idx_14_lowword; -+ u32 lcnphy_gain_idx_14_hiword; -+ u32 lcnphy_gain_idx_27_lowword; -+ u32 lcnphy_gain_idx_27_hiword; -+ s16 lcnphy_ofdmgainidxtableoffset; -+ s16 lcnphy_dsssgainidxtableoffset; -+ u32 lcnphy_tr_R_gain_val; -+ u32 lcnphy_tr_T_gain_val; -+ s8 lcnphy_input_pwr_offset_db; -+ u16 lcnphy_Med_Low_Gain_db; -+ u16 lcnphy_Very_Low_Gain_db; -+ s8 lcnphy_lastsensed_temperature; -+ s8 lcnphy_pkteng_rssi_slope; -+ u8 lcnphy_saved_tx_user_target[TXP_NUM_RATES]; -+ u8 lcnphy_volt_winner; -+ u8 lcnphy_volt_low; -+ u8 lcnphy_54_48_36_24mbps_backoff; -+ u8 lcnphy_11n_backoff; -+ u8 lcnphy_lowerofdm; -+ u8 lcnphy_cck; -+ u8 lcnphy_psat_2pt3_detected; -+ s32 lcnphy_lowest_Re_div_Im; -+ s8 lcnphy_final_papd_cal_idx; -+ u16 lcnphy_extstxctrl4; -+ u16 lcnphy_extstxctrl0; -+ u16 lcnphy_extstxctrl1; -+ s16 lcnphy_cck_dig_filt_type; -+ s16 lcnphy_ofdm_dig_filt_type; -+ struct lcnphy_cal_results lcnphy_cal_results; -+ -+ u8 lcnphy_psat_pwr; -+ u8 lcnphy_psat_indx; -+ s32 lcnphy_min_phase; -+ u8 lcnphy_final_idx; -+ u8 lcnphy_start_idx; -+ u8 lcnphy_current_index; -+ u16 lcnphy_logen_buf_1; -+ u16 lcnphy_local_ovr_2; -+ u16 lcnphy_local_oval_6; -+ u16 lcnphy_local_oval_5; -+ u16 lcnphy_logen_mixer_1; -+ -+ u8 lcnphy_aci_stat; -+ uint lcnphy_aci_start_time; -+ s8 lcnphy_tx_power_offset[TXP_NUM_RATES]; -+}; -+#endif /* _BRCM_PHY_LCN_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c.orig 2011-11-09 13:46:58.275800257 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c 2011-11-09 13:47:17.032565765 -0500 -@@ -0,0 +1,28876 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "phy_int.h" -+#include "phy_hal.h" -+#include "phy_radio.h" -+#include "phyreg_n.h" -+#include "phytbl_n.h" -+ -+#define READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name) \ -+ read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \ -+ ((core == PHY_CORE_0) ? \ -+ radio_type##_##jspace##0 : \ -+ radio_type##_##jspace##1)) -+ -+#define WRITE_RADIO_REG2(pi, radio_type, jspace, core, reg_name, value) \ -+ write_radio_reg(pi, radio_type##_##jspace##_##reg_name | \ -+ ((core == PHY_CORE_0) ? \ -+ radio_type##_##jspace##0 : \ -+ radio_type##_##jspace##1), value) -+ -+#define WRITE_RADIO_SYN(pi, radio_type, reg_name, value) \ -+ write_radio_reg(pi, radio_type##_##SYN##_##reg_name, value) -+ -+#define READ_RADIO_REG3(pi, radio_type, jspace, core, reg_name) \ -+ read_radio_reg(pi, ((core == PHY_CORE_0) ? \ -+ radio_type##_##jspace##0##_##reg_name : \ -+ radio_type##_##jspace##1##_##reg_name)) -+ -+#define WRITE_RADIO_REG3(pi, radio_type, jspace, core, reg_name, value) \ -+ write_radio_reg(pi, ((core == PHY_CORE_0) ? \ -+ radio_type##_##jspace##0##_##reg_name : \ -+ radio_type##_##jspace##1##_##reg_name), \ -+ value) -+ -+#define READ_RADIO_REG4(pi, radio_type, jspace, core, reg_name) \ -+ read_radio_reg(pi, ((core == PHY_CORE_0) ? \ -+ radio_type##_##reg_name##_##jspace##0 : \ -+ radio_type##_##reg_name##_##jspace##1)) -+ -+#define WRITE_RADIO_REG4(pi, radio_type, jspace, core, reg_name, value) \ -+ write_radio_reg(pi, ((core == PHY_CORE_0) ? \ -+ radio_type##_##reg_name##_##jspace##0 : \ -+ radio_type##_##reg_name##_##jspace##1), \ -+ value) -+ -+#define NPHY_ACI_MAX_UNDETECT_WINDOW_SZ 40 -+#define NPHY_ACI_CHANNEL_DELTA 5 -+#define NPHY_ACI_CHANNEL_SKIP 4 -+#define NPHY_ACI_40MHZ_CHANNEL_DELTA 6 -+#define NPHY_ACI_40MHZ_CHANNEL_SKIP 5 -+#define NPHY_ACI_40MHZ_CHANNEL_DELTA_GE_REV3 6 -+#define NPHY_ACI_40MHZ_CHANNEL_SKIP_GE_REV3 5 -+#define NPHY_ACI_CHANNEL_DELTA_GE_REV3 4 -+#define NPHY_ACI_CHANNEL_SKIP_GE_REV3 3 -+ -+#define NPHY_NOISE_NOASSOC_GLITCH_TH_UP 2 -+ -+#define NPHY_NOISE_NOASSOC_GLITCH_TH_DN 8 -+ -+#define NPHY_NOISE_ASSOC_GLITCH_TH_UP 2 -+ -+#define NPHY_NOISE_ASSOC_GLITCH_TH_DN 8 -+ -+#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_UP 2 -+ -+#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_DN 8 -+ -+#define NPHY_NOISE_NOASSOC_ENTER_TH 400 -+ -+#define NPHY_NOISE_ASSOC_ENTER_TH 400 -+ -+#define NPHY_NOISE_ASSOC_RX_GLITCH_BADPLCP_ENTER_TH 400 -+ -+#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX 44 -+#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX_REV_7 56 -+ -+#define NPHY_NOISE_NOASSOC_CRSIDX_INCR 16 -+ -+#define NPHY_NOISE_ASSOC_CRSIDX_INCR 8 -+ -+#define NPHY_IS_SROM_REINTERPRET NREV_GE(pi->pubpi.phy_rev, 5) -+ -+#define NPHY_RSSICAL_MAXREAD 31 -+ -+#define NPHY_RSSICAL_NPOLL 8 -+#define NPHY_RSSICAL_MAXD (1<<20) -+#define NPHY_MIN_RXIQ_PWR 2 -+ -+#define NPHY_RSSICAL_W1_TARGET 25 -+#define NPHY_RSSICAL_W2_TARGET NPHY_RSSICAL_W1_TARGET -+#define NPHY_RSSICAL_NB_TARGET 0 -+ -+#define NPHY_RSSICAL_W1_TARGET_REV3 29 -+#define NPHY_RSSICAL_W2_TARGET_REV3 NPHY_RSSICAL_W1_TARGET_REV3 -+ -+#define NPHY_CALSANITY_RSSI_NB_MAX_POS 9 -+#define NPHY_CALSANITY_RSSI_NB_MAX_NEG -9 -+#define NPHY_CALSANITY_RSSI_W1_MAX_POS 12 -+#define NPHY_CALSANITY_RSSI_W1_MAX_NEG (NPHY_RSSICAL_W1_TARGET - \ -+ NPHY_RSSICAL_MAXREAD) -+#define NPHY_CALSANITY_RSSI_W2_MAX_POS NPHY_CALSANITY_RSSI_W1_MAX_POS -+#define NPHY_CALSANITY_RSSI_W2_MAX_NEG (NPHY_RSSICAL_W2_TARGET - \ -+ NPHY_RSSICAL_MAXREAD) -+#define NPHY_RSSI_SXT(x) ((s8) (-((x) & 0x20) + ((x) & 0x1f))) -+#define NPHY_RSSI_NB_VIOL(x) (((x) > NPHY_CALSANITY_RSSI_NB_MAX_POS) || \ -+ ((x) < NPHY_CALSANITY_RSSI_NB_MAX_NEG)) -+#define NPHY_RSSI_W1_VIOL(x) (((x) > NPHY_CALSANITY_RSSI_W1_MAX_POS) || \ -+ ((x) < NPHY_CALSANITY_RSSI_W1_MAX_NEG)) -+#define NPHY_RSSI_W2_VIOL(x) (((x) > NPHY_CALSANITY_RSSI_W2_MAX_POS) || \ -+ ((x) < NPHY_CALSANITY_RSSI_W2_MAX_NEG)) -+ -+#define NPHY_IQCAL_NUMGAINS 9 -+#define NPHY_N_GCTL 0x66 -+ -+#define NPHY_PAPD_EPS_TBL_SIZE 64 -+#define NPHY_PAPD_SCL_TBL_SIZE 64 -+#define NPHY_NUM_DIG_FILT_COEFFS 15 -+ -+#define NPHY_PAPD_COMP_OFF 0 -+#define NPHY_PAPD_COMP_ON 1 -+ -+#define NPHY_SROM_TEMPSHIFT 32 -+#define NPHY_SROM_MAXTEMPOFFSET 16 -+#define NPHY_SROM_MINTEMPOFFSET -16 -+ -+#define NPHY_CAL_MAXTEMPDELTA 64 -+ -+#define NPHY_NOISEVAR_TBLLEN40 256 -+#define NPHY_NOISEVAR_TBLLEN20 128 -+ -+#define NPHY_ANARXLPFBW_REDUCTIONFACT 7 -+ -+#define NPHY_ADJUSTED_MINCRSPOWER 0x1e -+ -+/* 5357 Chip specific ChipControl register bits */ -+#define CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */ -+#define CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */ -+ -+#define NPHY_CAL_TSSISAMPS 64 -+#define NPHY_TEST_TONE_FREQ_40MHz 4000 -+#define NPHY_TEST_TONE_FREQ_20MHz 2500 -+ -+#define MAX_205x_RCAL_WAITLOOPS 10000 -+ -+#define NPHY_RXCAL_TONEAMP 181 -+#define NPHY_RXCAL_TONEFREQ_40MHz 4000 -+#define NPHY_RXCAL_TONEFREQ_20MHz 2000 -+ -+#define TXFILT_SHAPING_OFDM20 0 -+#define TXFILT_SHAPING_OFDM40 1 -+#define TXFILT_SHAPING_CCK 2 -+#define TXFILT_DEFAULT_OFDM20 3 -+#define TXFILT_DEFAULT_OFDM40 4 -+ -+struct nphy_iqcal_params { -+ u16 txlpf; -+ u16 txgm; -+ u16 pga; -+ u16 pad; -+ u16 ipa; -+ u16 cal_gain; -+ u16 ncorr[5]; -+}; -+ -+struct nphy_txiqcal_ladder { -+ u8 percent; -+ u8 g_env; -+}; -+ -+struct nphy_ipa_txcalgains { -+ struct nphy_txgains gains; -+ bool useindex; -+ u8 index; -+}; -+ -+struct nphy_papd_restore_state { -+ u16 fbmix[2]; -+ u16 vga_master[2]; -+ u16 intpa_master[2]; -+ u16 afectrl[2]; -+ u16 afeoverride[2]; -+ u16 pwrup[2]; -+ u16 atten[2]; -+ u16 mm; -+}; -+ -+struct nphy_ipa_txrxgain { -+ u16 hpvga; -+ u16 lpf_biq1; -+ u16 lpf_biq0; -+ u16 lna2; -+ u16 lna1; -+ s8 txpwrindex; -+}; -+ -+#define NPHY_IPA_RXCAL_MAXGAININDEX (6 - 1) -+ -+static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz[] = { -+ {0, 0, 0, 0, 0, 100}, -+ {0, 0, 0, 0, 0, 50}, -+ {0, 0, 0, 0, 0, -1}, -+ {0, 0, 0, 3, 0, -1}, -+ {0, 0, 3, 3, 0, -1}, -+ {0, 2, 3, 3, 0, -1} -+}; -+ -+static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz[] = { -+ {0, 0, 0, 0, 0, 128}, -+ {0, 0, 0, 0, 0, 70}, -+ {0, 0, 0, 0, 0, 20}, -+ {0, 0, 0, 3, 0, 20}, -+ {0, 0, 3, 3, 0, 20}, -+ {0, 2, 3, 3, 0, 20} -+}; -+ -+static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz_rev7[] = { -+ {0, 0, 0, 0, 0, 100}, -+ {0, 0, 0, 0, 0, 50}, -+ {0, 0, 0, 0, 0, -1}, -+ {0, 0, 0, 3, 0, -1}, -+ {0, 0, 3, 3, 0, -1}, -+ {0, 0, 5, 3, 0, -1} -+}; -+ -+static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz_rev7[] = { -+ {0, 0, 0, 0, 0, 10}, -+ {0, 0, 0, 1, 0, 10}, -+ {0, 0, 1, 2, 0, 10}, -+ {0, 0, 1, 3, 0, 10}, -+ {0, 0, 4, 3, 0, 10}, -+ {0, 0, 6, 3, 0, 10} -+}; -+ -+enum { -+ NPHY_RXCAL_GAIN_INIT = 0, -+ NPHY_RXCAL_GAIN_UP, -+ NPHY_RXCAL_GAIN_DOWN -+}; -+ -+#define wlc_phy_get_papd_nphy(pi) \ -+ (read_phy_reg((pi), 0x1e7) & \ -+ ((0x1 << 15) | \ -+ (0x1 << 14) | \ -+ (0x1 << 13))) -+ -+static const u16 NPHY_IPA_REV4_txdigi_filtcoeffs[][NPHY_NUM_DIG_FILT_COEFFS] = { -+ {-377, 137, -407, 208, -1527, 956, 93, 186, 93, -+ 230, -44, 230, 201, -191, 201}, -+ {-77, 20, -98, 49, -93, 60, 56, 111, 56, 26, -5, -+ 26, 34, -32, 34}, -+ {-360, 164, -376, 164, -1533, 576, 308, -314, 308, -+ 121, -73, 121, 91, 124, 91}, -+ {-295, 200, -363, 142, -1391, 826, 151, 301, 151, -+ 151, 301, 151, 602, -752, 602}, -+ {-92, 58, -96, 49, -104, 44, 17, 35, 17, -+ 12, 25, 12, 13, 27, 13}, -+ {-375, 136, -399, 209, -1479, 949, 130, 260, 130, -+ 230, -44, 230, 201, -191, 201}, -+ {0xed9, 0xc8, 0xe95, 0x8e, 0xa91, 0x33a, 0x97, 0x12d, 0x97, -+ 0x97, 0x12d, 0x97, 0x25a, 0xd10, 0x25a} -+}; -+ -+struct chan_info_nphy_2055 { -+ u16 chan; -+ u16 freq; -+ uint unknown; -+ u8 RF_pll_ref; -+ u8 RF_rf_pll_mod1; -+ u8 RF_rf_pll_mod0; -+ u8 RF_vco_cap_tail; -+ u8 RF_vco_cal1; -+ u8 RF_vco_cal2; -+ u8 RF_pll_lf_c1; -+ u8 RF_pll_lf_r1; -+ u8 RF_pll_lf_c2; -+ u8 RF_lgbuf_cen_buf; -+ u8 RF_lgen_tune1; -+ u8 RF_lgen_tune2; -+ u8 RF_core1_lgbuf_a_tune; -+ u8 RF_core1_lgbuf_g_tune; -+ u8 RF_core1_rxrf_reg1; -+ u8 RF_core1_tx_pga_pad_tn; -+ u8 RF_core1_tx_mx_bgtrim; -+ u8 RF_core2_lgbuf_a_tune; -+ u8 RF_core2_lgbuf_g_tune; -+ u8 RF_core2_rxrf_reg1; -+ u8 RF_core2_tx_pga_pad_tn; -+ u8 RF_core2_tx_mx_bgtrim; -+ u16 PHY_BW1a; -+ u16 PHY_BW2; -+ u16 PHY_BW3; -+ u16 PHY_BW4; -+ u16 PHY_BW5; -+ u16 PHY_BW6; -+}; -+ -+struct chan_info_nphy_radio205x { -+ u16 chan; -+ u16 freq; -+ u8 RF_SYN_pll_vcocal1; -+ u8 RF_SYN_pll_vcocal2; -+ u8 RF_SYN_pll_refdiv; -+ u8 RF_SYN_pll_mmd2; -+ u8 RF_SYN_pll_mmd1; -+ u8 RF_SYN_pll_loopfilter1; -+ u8 RF_SYN_pll_loopfilter2; -+ u8 RF_SYN_pll_loopfilter3; -+ u8 RF_SYN_pll_loopfilter4; -+ u8 RF_SYN_pll_loopfilter5; -+ u8 RF_SYN_reserved_addr27; -+ u8 RF_SYN_reserved_addr28; -+ u8 RF_SYN_reserved_addr29; -+ u8 RF_SYN_logen_VCOBUF1; -+ u8 RF_SYN_logen_MIXER2; -+ u8 RF_SYN_logen_BUF3; -+ u8 RF_SYN_logen_BUF4; -+ u8 RF_RX0_lnaa_tune; -+ u8 RF_RX0_lnag_tune; -+ u8 RF_TX0_intpaa_boost_tune; -+ u8 RF_TX0_intpag_boost_tune; -+ u8 RF_TX0_pada_boost_tune; -+ u8 RF_TX0_padg_boost_tune; -+ u8 RF_TX0_pgaa_boost_tune; -+ u8 RF_TX0_pgag_boost_tune; -+ u8 RF_TX0_mixa_boost_tune; -+ u8 RF_TX0_mixg_boost_tune; -+ u8 RF_RX1_lnaa_tune; -+ u8 RF_RX1_lnag_tune; -+ u8 RF_TX1_intpaa_boost_tune; -+ u8 RF_TX1_intpag_boost_tune; -+ u8 RF_TX1_pada_boost_tune; -+ u8 RF_TX1_padg_boost_tune; -+ u8 RF_TX1_pgaa_boost_tune; -+ u8 RF_TX1_pgag_boost_tune; -+ u8 RF_TX1_mixa_boost_tune; -+ u8 RF_TX1_mixg_boost_tune; -+ u16 PHY_BW1a; -+ u16 PHY_BW2; -+ u16 PHY_BW3; -+ u16 PHY_BW4; -+ u16 PHY_BW5; -+ u16 PHY_BW6; -+}; -+ -+struct chan_info_nphy_radio2057 { -+ u16 chan; -+ u16 freq; -+ u8 RF_vcocal_countval0; -+ u8 RF_vcocal_countval1; -+ u8 RF_rfpll_refmaster_sparextalsize; -+ u8 RF_rfpll_loopfilter_r1; -+ u8 RF_rfpll_loopfilter_c2; -+ u8 RF_rfpll_loopfilter_c1; -+ u8 RF_cp_kpd_idac; -+ u8 RF_rfpll_mmd0; -+ u8 RF_rfpll_mmd1; -+ u8 RF_vcobuf_tune; -+ u8 RF_logen_mx2g_tune; -+ u8 RF_logen_mx5g_tune; -+ u8 RF_logen_indbuf2g_tune; -+ u8 RF_logen_indbuf5g_tune; -+ u8 RF_txmix2g_tune_boost_pu_core0; -+ u8 RF_pad2g_tune_pus_core0; -+ u8 RF_pga_boost_tune_core0; -+ u8 RF_txmix5g_boost_tune_core0; -+ u8 RF_pad5g_tune_misc_pus_core0; -+ u8 RF_lna2g_tune_core0; -+ u8 RF_lna5g_tune_core0; -+ u8 RF_txmix2g_tune_boost_pu_core1; -+ u8 RF_pad2g_tune_pus_core1; -+ u8 RF_pga_boost_tune_core1; -+ u8 RF_txmix5g_boost_tune_core1; -+ u8 RF_pad5g_tune_misc_pus_core1; -+ u8 RF_lna2g_tune_core1; -+ u8 RF_lna5g_tune_core1; -+ u16 PHY_BW1a; -+ u16 PHY_BW2; -+ u16 PHY_BW3; -+ u16 PHY_BW4; -+ u16 PHY_BW5; -+ u16 PHY_BW6; -+}; -+ -+struct chan_info_nphy_radio2057_rev5 { -+ u16 chan; -+ u16 freq; -+ u8 RF_vcocal_countval0; -+ u8 RF_vcocal_countval1; -+ u8 RF_rfpll_refmaster_sparextalsize; -+ u8 RF_rfpll_loopfilter_r1; -+ u8 RF_rfpll_loopfilter_c2; -+ u8 RF_rfpll_loopfilter_c1; -+ u8 RF_cp_kpd_idac; -+ u8 RF_rfpll_mmd0; -+ u8 RF_rfpll_mmd1; -+ u8 RF_vcobuf_tune; -+ u8 RF_logen_mx2g_tune; -+ u8 RF_logen_indbuf2g_tune; -+ u8 RF_txmix2g_tune_boost_pu_core0; -+ u8 RF_pad2g_tune_pus_core0; -+ u8 RF_lna2g_tune_core0; -+ u8 RF_txmix2g_tune_boost_pu_core1; -+ u8 RF_pad2g_tune_pus_core1; -+ u8 RF_lna2g_tune_core1; -+ u16 PHY_BW1a; -+ u16 PHY_BW2; -+ u16 PHY_BW3; -+ u16 PHY_BW4; -+ u16 PHY_BW5; -+ u16 PHY_BW6; -+}; -+ -+struct nphy_sfo_cfg { -+ u16 PHY_BW1a; -+ u16 PHY_BW2; -+ u16 PHY_BW3; -+ u16 PHY_BW4; -+ u16 PHY_BW5; -+ u16 PHY_BW6; -+}; -+ -+static const struct chan_info_nphy_2055 chan_info_nphy_2055[] = { -+ { -+ 184, 4920, 3280, 0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A, -+ 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, -+ 0x0F, 0x8F, 0x7B4, 0x7B0, 0x7AC, 0x214, 0x215, 0x216}, -+ { -+ 186, 4930, 3287, 0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A, -+ 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, -+ 0x0F, 0x8F, 0x7B8, 0x7B4, 0x7B0, 0x213, 0x214, 0x215}, -+ { -+ 188, 4940, 3293, 0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A, -+ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, -+ 0x0F, 0x8F, 0x7BC, 0x7B8, 0x7B4, 0x212, 0x213, 0x214}, -+ { -+ 190, 4950, 3300, 0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A, -+ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, -+ 0x0F, 0x8F, 0x7C0, 0x7BC, 0x7B8, 0x211, 0x212, 0x213}, -+ { -+ 192, 4960, 3307, 0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A, -+ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, -+ 0x0F, 0x8F, 0x7C4, 0x7C0, 0x7BC, 0x20F, 0x211, 0x212}, -+ { -+ 194, 4970, 3313, 0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A, -+ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, -+ 0x0F, 0x8F, 0x7C8, 0x7C4, 0x7C0, 0x20E, 0x20F, 0x211}, -+ { -+ 196, 4980, 3320, 0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A, -+ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, -+ 0x0F, 0x8F, 0x7CC, 0x7C8, 0x7C4, 0x20D, 0x20E, 0x20F}, -+ { -+ 198, 4990, 3327, 0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A, -+ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, -+ 0x0F, 0x8F, 0x7D0, 0x7CC, 0x7C8, 0x20C, 0x20D, 0x20E}, -+ { -+ 200, 5000, 3333, 0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A, -+ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, -+ 0x0F, 0x8F, 0x7D4, 0x7D0, 0x7CC, 0x20B, 0x20C, 0x20D}, -+ { -+ 202, 5010, 3340, 0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A, -+ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, -+ 0x0F, 0x8F, 0x7D8, 0x7D4, 0x7D0, 0x20A, 0x20B, 0x20C}, -+ { -+ 204, 5020, 3347, 0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A, -+ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, -+ 0x0F, 0x8F, 0x7DC, 0x7D8, 0x7D4, 0x209, 0x20A, 0x20B}, -+ { -+ 206, 5030, 3353, 0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A, -+ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, -+ 0x0F, 0x8F, 0x7E0, 0x7DC, 0x7D8, 0x208, 0x209, 0x20A}, -+ { -+ 208, 5040, 3360, 0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A, -+ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, -+ 0x0F, 0x8F, 0x7E4, 0x7E0, 0x7DC, 0x207, 0x208, 0x209}, -+ { -+ 210, 5050, 3367, 0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A, -+ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, -+ 0x0F, 0x8F, 0x7E8, 0x7E4, 0x7E0, 0x206, 0x207, 0x208}, -+ { -+ 212, 5060, 3373, 0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A, -+ 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E, -+ 0x0F, 0x8E, 0x7EC, 0x7E8, 0x7E4, 0x205, 0x206, 0x207}, -+ { -+ 214, 5070, 3380, 0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A, -+ 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E, -+ 0x0F, 0x8E, 0x7F0, 0x7EC, 0x7E8, 0x204, 0x205, 0x206}, -+ { -+ 216, 5080, 3387, 0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A, -+ 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E, -+ 0x0F, 0x8D, 0x7F4, 0x7F0, 0x7EC, 0x203, 0x204, 0x205}, -+ { -+ 218, 5090, 3393, 0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A, -+ 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E, -+ 0x0F, 0x8D, 0x7F8, 0x7F4, 0x7F0, 0x202, 0x203, 0x204}, -+ { -+ 220, 5100, 3400, 0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A, -+ 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D, -+ 0x0F, 0x8D, 0x7FC, 0x7F8, 0x7F4, 0x201, 0x202, 0x203}, -+ { -+ 222, 5110, 3407, 0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A, -+ 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D, -+ 0x0F, 0x8D, 0x800, 0x7FC, 0x7F8, 0x200, 0x201, 0x202}, -+ { -+ 224, 5120, 3413, 0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A, -+ 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D, -+ 0x0F, 0x8C, 0x804, 0x800, 0x7FC, 0x1FF, 0x200, 0x201}, -+ { -+ 226, 5130, 3420, 0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A, -+ 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D, -+ 0x0F, 0x8C, 0x808, 0x804, 0x800, 0x1FE, 0x1FF, 0x200}, -+ { -+ 228, 5140, 3427, 0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A, -+ 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E, 0x8B, 0xDD, 0x00, 0x0C, -+ 0x0E, 0x8B, 0x80C, 0x808, 0x804, 0x1FD, 0x1FE, 0x1FF}, -+ { -+ 32, 5160, 3440, 0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A, -+ 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B, -+ 0x0D, 0x8A, 0x814, 0x810, 0x80C, 0x1FB, 0x1FC, 0x1FD}, -+ { -+ 34, 5170, 3447, 0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A, -+ 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B, -+ 0x0D, 0x8A, 0x818, 0x814, 0x810, 0x1FA, 0x1FB, 0x1FC}, -+ { -+ 36, 5180, 3453, 0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A, -+ 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B, -+ 0x0C, 0x89, 0x81C, 0x818, 0x814, 0x1F9, 0x1FA, 0x1FB}, -+ { -+ 38, 5190, 3460, 0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A, -+ 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B, -+ 0x0C, 0x89, 0x820, 0x81C, 0x818, 0x1F8, 0x1F9, 0x1FA}, -+ { -+ 40, 5200, 3467, 0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A, -+ 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A, -+ 0x0B, 0x89, 0x824, 0x820, 0x81C, 0x1F7, 0x1F8, 0x1F9}, -+ { -+ 42, 5210, 3473, 0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A, -+ 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A, -+ 0x0B, 0x89, 0x828, 0x824, 0x820, 0x1F6, 0x1F7, 0x1F8}, -+ { -+ 44, 5220, 3480, 0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A, -+ 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09, -+ 0x0A, 0x88, 0x82C, 0x828, 0x824, 0x1F5, 0x1F6, 0x1F7}, -+ { -+ 46, 5230, 3487, 0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A, -+ 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09, -+ 0x0A, 0x88, 0x830, 0x82C, 0x828, 0x1F4, 0x1F5, 0x1F6}, -+ { -+ 48, 5240, 3493, 0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A, -+ 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09, -+ 0x0A, 0x87, 0x834, 0x830, 0x82C, 0x1F3, 0x1F4, 0x1F5}, -+ { -+ 50, 5250, 3500, 0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A, -+ 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09, -+ 0x0A, 0x87, 0x838, 0x834, 0x830, 0x1F2, 0x1F3, 0x1F4}, -+ { -+ 52, 5260, 3507, 0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A, -+ 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08, -+ 0x09, 0x87, 0x83C, 0x838, 0x834, 0x1F1, 0x1F2, 0x1F3}, -+ { -+ 54, 5270, 3513, 0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A, -+ 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08, -+ 0x09, 0x87, 0x840, 0x83C, 0x838, 0x1F0, 0x1F1, 0x1F2}, -+ { -+ 56, 5280, 3520, 0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A, -+ 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08, -+ 0x08, 0x86, 0x844, 0x840, 0x83C, 0x1F0, 0x1F0, 0x1F1}, -+ { -+ 58, 5290, 3527, 0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A, -+ 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08, -+ 0x08, 0x86, 0x848, 0x844, 0x840, 0x1EF, 0x1F0, 0x1F0}, -+ { -+ 60, 5300, 3533, 0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A, -+ 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08, -+ 0x07, 0x85, 0x84C, 0x848, 0x844, 0x1EE, 0x1EF, 0x1F0}, -+ { -+ 62, 5310, 3540, 0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A, -+ 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08, -+ 0x07, 0x85, 0x850, 0x84C, 0x848, 0x1ED, 0x1EE, 0x1EF}, -+ { -+ 64, 5320, 3547, 0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A, -+ 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07, -+ 0x07, 0x84, 0x854, 0x850, 0x84C, 0x1EC, 0x1ED, 0x1EE}, -+ { -+ 66, 5330, 3553, 0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A, -+ 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07, -+ 0x07, 0x84, 0x858, 0x854, 0x850, 0x1EB, 0x1EC, 0x1ED}, -+ { -+ 68, 5340, 3560, 0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A, -+ 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07, -+ 0x06, 0x84, 0x85C, 0x858, 0x854, 0x1EA, 0x1EB, 0x1EC}, -+ { -+ 70, 5350, 3567, 0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A, -+ 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07, -+ 0x06, 0x84, 0x860, 0x85C, 0x858, 0x1E9, 0x1EA, 0x1EB}, -+ { -+ 72, 5360, 3573, 0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A, -+ 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06, -+ 0x05, 0x83, 0x864, 0x860, 0x85C, 0x1E8, 0x1E9, 0x1EA}, -+ { -+ 74, 5370, 3580, 0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A, -+ 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06, -+ 0x05, 0x83, 0x868, 0x864, 0x860, 0x1E7, 0x1E8, 0x1E9}, -+ { -+ 76, 5380, 3587, 0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A, -+ 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06, -+ 0x04, 0x82, 0x86C, 0x868, 0x864, 0x1E6, 0x1E7, 0x1E8}, -+ { -+ 78, 5390, 3593, 0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A, -+ 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06, -+ 0x04, 0x82, 0x870, 0x86C, 0x868, 0x1E5, 0x1E6, 0x1E7}, -+ { -+ 80, 5400, 3600, 0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A, -+ 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05, -+ 0x04, 0x81, 0x874, 0x870, 0x86C, 0x1E5, 0x1E5, 0x1E6}, -+ { -+ 82, 5410, 3607, 0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A, -+ 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05, -+ 0x04, 0x81, 0x878, 0x874, 0x870, 0x1E4, 0x1E5, 0x1E5}, -+ { -+ 84, 5420, 3613, 0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A, -+ 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05, -+ 0x03, 0x80, 0x87C, 0x878, 0x874, 0x1E3, 0x1E4, 0x1E5}, -+ { -+ 86, 5430, 3620, 0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A, -+ 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05, -+ 0x03, 0x80, 0x880, 0x87C, 0x878, 0x1E2, 0x1E3, 0x1E4}, -+ { -+ 88, 5440, 3627, 0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A, -+ 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04, -+ 0x02, 0x80, 0x884, 0x880, 0x87C, 0x1E1, 0x1E2, 0x1E3}, -+ { -+ 90, 5450, 3633, 0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A, -+ 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04, -+ 0x02, 0x80, 0x888, 0x884, 0x880, 0x1E0, 0x1E1, 0x1E2}, -+ { -+ 92, 5460, 3640, 0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A, -+ 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04, -+ 0x01, 0x80, 0x88C, 0x888, 0x884, 0x1DF, 0x1E0, 0x1E1}, -+ { -+ 94, 5470, 3647, 0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A, -+ 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04, -+ 0x01, 0x80, 0x890, 0x88C, 0x888, 0x1DE, 0x1DF, 0x1E0}, -+ { -+ 96, 5480, 3653, 0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A, -+ 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, -+ 0x00, 0x80, 0x894, 0x890, 0x88C, 0x1DD, 0x1DE, 0x1DF}, -+ { -+ 98, 5490, 3660, 0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A, -+ 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, -+ 0x00, 0x80, 0x898, 0x894, 0x890, 0x1DD, 0x1DD, 0x1DE}, -+ { -+ 100, 5500, 3667, 0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A, -+ 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, -+ 0x00, 0x80, 0x89C, 0x898, 0x894, 0x1DC, 0x1DD, 0x1DD}, -+ { -+ 102, 5510, 3673, 0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A, -+ 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, -+ 0x00, 0x80, 0x8A0, 0x89C, 0x898, 0x1DB, 0x1DC, 0x1DD}, -+ { -+ 104, 5520, 3680, 0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A, -+ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, -+ 0x00, 0x80, 0x8A4, 0x8A0, 0x89C, 0x1DA, 0x1DB, 0x1DC}, -+ { -+ 106, 5530, 3687, 0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A, -+ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, -+ 0x00, 0x80, 0x8A8, 0x8A4, 0x8A0, 0x1D9, 0x1DA, 0x1DB}, -+ { -+ 108, 5540, 3693, 0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A, -+ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, -+ 0x00, 0x80, 0x8AC, 0x8A8, 0x8A4, 0x1D8, 0x1D9, 0x1DA}, -+ { -+ 110, 5550, 3700, 0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A, -+ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, -+ 0x00, 0x80, 0x8B0, 0x8AC, 0x8A8, 0x1D7, 0x1D8, 0x1D9}, -+ { -+ 112, 5560, 3707, 0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A, -+ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, -+ 0x00, 0x80, 0x8B4, 0x8B0, 0x8AC, 0x1D7, 0x1D7, 0x1D8}, -+ { -+ 114, 5570, 3713, 0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A, -+ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, -+ 0x00, 0x80, 0x8B8, 0x8B4, 0x8B0, 0x1D6, 0x1D7, 0x1D7}, -+ { -+ 116, 5580, 3720, 0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A, -+ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, -+ 0x00, 0x80, 0x8BC, 0x8B8, 0x8B4, 0x1D5, 0x1D6, 0x1D7}, -+ { -+ 118, 5590, 3727, 0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A, -+ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, -+ 0x00, 0x80, 0x8C0, 0x8BC, 0x8B8, 0x1D4, 0x1D5, 0x1D6}, -+ { -+ 120, 5600, 3733, 0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A, -+ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01, -+ 0x00, 0x80, 0x8C4, 0x8C0, 0x8BC, 0x1D3, 0x1D4, 0x1D5}, -+ { -+ 122, 5610, 3740, 0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A, -+ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01, -+ 0x00, 0x80, 0x8C8, 0x8C4, 0x8C0, 0x1D2, 0x1D3, 0x1D4}, -+ { -+ 124, 5620, 3747, 0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A, -+ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, -+ 0x00, 0x80, 0x8CC, 0x8C8, 0x8C4, 0x1D2, 0x1D2, 0x1D3}, -+ { -+ 126, 5630, 3753, 0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A, -+ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, -+ 0x00, 0x80, 0x8D0, 0x8CC, 0x8C8, 0x1D1, 0x1D2, 0x1D2}, -+ { -+ 128, 5640, 3760, 0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x8D4, 0x8D0, 0x8CC, 0x1D0, 0x1D1, 0x1D2}, -+ { -+ 130, 5650, 3767, 0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x8D8, 0x8D4, 0x8D0, 0x1CF, 0x1D0, 0x1D1}, -+ { -+ 132, 5660, 3773, 0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x8DC, 0x8D8, 0x8D4, 0x1CE, 0x1CF, 0x1D0}, -+ { -+ 134, 5670, 3780, 0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x8E0, 0x8DC, 0x8D8, 0x1CE, 0x1CE, 0x1CF}, -+ { -+ 136, 5680, 3787, 0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x8E4, 0x8E0, 0x8DC, 0x1CD, 0x1CE, 0x1CE}, -+ { -+ 138, 5690, 3793, 0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x8E8, 0x8E4, 0x8E0, 0x1CC, 0x1CD, 0x1CE}, -+ { -+ 140, 5700, 3800, 0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x8EC, 0x8E8, 0x8E4, 0x1CB, 0x1CC, 0x1CD}, -+ { -+ 142, 5710, 3807, 0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x8F0, 0x8EC, 0x8E8, 0x1CA, 0x1CB, 0x1CC}, -+ { -+ 144, 5720, 3813, 0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x8F4, 0x8F0, 0x8EC, 0x1C9, 0x1CA, 0x1CB}, -+ { -+ 145, 5725, 3817, 0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x8F6, 0x8F2, 0x8EE, 0x1C9, 0x1CA, 0x1CB}, -+ { -+ 146, 5730, 3820, 0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x8F8, 0x8F4, 0x8F0, 0x1C9, 0x1C9, 0x1CA}, -+ { -+ 147, 5735, 3823, 0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x8FA, 0x8F6, 0x8F2, 0x1C8, 0x1C9, 0x1CA}, -+ { -+ 148, 5740, 3827, 0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x8FC, 0x8F8, 0x8F4, 0x1C8, 0x1C9, 0x1C9}, -+ { -+ 149, 5745, 3830, 0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x8FE, 0x8FA, 0x8F6, 0x1C8, 0x1C8, 0x1C9}, -+ { -+ 150, 5750, 3833, 0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x900, 0x8FC, 0x8F8, 0x1C7, 0x1C8, 0x1C9}, -+ { -+ 151, 5755, 3837, 0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x902, 0x8FE, 0x8FA, 0x1C7, 0x1C8, 0x1C8}, -+ { -+ 152, 5760, 3840, 0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x904, 0x900, 0x8FC, 0x1C6, 0x1C7, 0x1C8}, -+ { -+ 153, 5765, 3843, 0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x906, 0x902, 0x8FE, 0x1C6, 0x1C7, 0x1C8}, -+ { -+ 154, 5770, 3847, 0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x908, 0x904, 0x900, 0x1C6, 0x1C6, 0x1C7}, -+ { -+ 155, 5775, 3850, 0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x90A, 0x906, 0x902, 0x1C5, 0x1C6, 0x1C7}, -+ { -+ 156, 5780, 3853, 0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x90C, 0x908, 0x904, 0x1C5, 0x1C6, 0x1C6}, -+ { -+ 157, 5785, 3857, 0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x90E, 0x90A, 0x906, 0x1C4, 0x1C5, 0x1C6}, -+ { -+ 158, 5790, 3860, 0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x910, 0x90C, 0x908, 0x1C4, 0x1C5, 0x1C6}, -+ { -+ 159, 5795, 3863, 0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x912, 0x90E, 0x90A, 0x1C4, 0x1C4, 0x1C5}, -+ { -+ 160, 5800, 3867, 0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x914, 0x910, 0x90C, 0x1C3, 0x1C4, 0x1C5}, -+ { -+ 161, 5805, 3870, 0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x916, 0x912, 0x90E, 0x1C3, 0x1C4, 0x1C4}, -+ { -+ 162, 5810, 3873, 0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x918, 0x914, 0x910, 0x1C2, 0x1C3, 0x1C4}, -+ { -+ 163, 5815, 3877, 0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x91A, 0x916, 0x912, 0x1C2, 0x1C3, 0x1C4}, -+ { -+ 164, 5820, 3880, 0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x91C, 0x918, 0x914, 0x1C2, 0x1C2, 0x1C3}, -+ { -+ 165, 5825, 3883, 0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x91E, 0x91A, 0x916, 0x1C1, 0x1C2, 0x1C3}, -+ { -+ 166, 5830, 3887, 0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x920, 0x91C, 0x918, 0x1C1, 0x1C2, 0x1C2}, -+ { -+ 168, 5840, 3893, 0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x924, 0x920, 0x91C, 0x1C0, 0x1C1, 0x1C2}, -+ { -+ 170, 5850, 3900, 0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x928, 0x924, 0x920, 0x1BF, 0x1C0, 0x1C1}, -+ { -+ 172, 5860, 3907, 0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x92C, 0x928, 0x924, 0x1BF, 0x1BF, 0x1C0}, -+ { -+ 174, 5870, 3913, 0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x930, 0x92C, 0x928, 0x1BE, 0x1BF, 0x1BF}, -+ { -+ 176, 5880, 3920, 0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x934, 0x930, 0x92C, 0x1BD, 0x1BE, 0x1BF}, -+ { -+ 178, 5890, 3927, 0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x938, 0x934, 0x930, 0x1BC, 0x1BD, 0x1BE}, -+ { -+ 180, 5900, 3933, 0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x93C, 0x938, 0x934, 0x1BC, 0x1BC, 0x1BD}, -+ { -+ 182, 5910, 3940, 0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A, -+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -+ 0x00, 0x80, 0x940, 0x93C, 0x938, 0x1BB, 0x1BC, 0x1BC}, -+ { -+ 1, 2412, 3216, 0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15, -+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C, 0x80, 0xFF, 0x88, 0x0D, -+ 0x0C, 0x80, 0x3C9, 0x3C5, 0x3C1, 0x43A, 0x43F, 0x443}, -+ { -+ 2, 2417, 3223, 0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15, -+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B, 0x80, 0xFF, 0x88, 0x0C, -+ 0x0B, 0x80, 0x3CB, 0x3C7, 0x3C3, 0x438, 0x43D, 0x441}, -+ { -+ 3, 2422, 3229, 0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15, -+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C, -+ 0x0A, 0x80, 0x3CD, 0x3C9, 0x3C5, 0x436, 0x43A, 0x43F}, -+ { -+ 4, 2427, 3236, 0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15, -+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C, -+ 0x0A, 0x80, 0x3CF, 0x3CB, 0x3C7, 0x434, 0x438, 0x43D}, -+ { -+ 5, 2432, 3243, 0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15, -+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09, 0x80, 0xFF, 0x88, 0x0C, -+ 0x09, 0x80, 0x3D1, 0x3CD, 0x3C9, 0x431, 0x436, 0x43A}, -+ { -+ 6, 2437, 3249, 0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15, -+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08, 0x80, 0xFF, 0x88, 0x0B, -+ 0x08, 0x80, 0x3D3, 0x3CF, 0x3CB, 0x42F, 0x434, 0x438}, -+ { -+ 7, 2442, 3256, 0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15, -+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07, 0x80, 0xFF, 0x88, 0x0A, -+ 0x07, 0x80, 0x3D5, 0x3D1, 0x3CD, 0x42D, 0x431, 0x436}, -+ { -+ 8, 2447, 3263, 0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15, -+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06, 0x80, 0xFF, 0x88, 0x0A, -+ 0x06, 0x80, 0x3D7, 0x3D3, 0x3CF, 0x42B, 0x42F, 0x434}, -+ { -+ 9, 2452, 3269, 0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15, -+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06, 0x80, 0xFF, 0x88, 0x09, -+ 0x06, 0x80, 0x3D9, 0x3D5, 0x3D1, 0x429, 0x42D, 0x431}, -+ { -+ 10, 2457, 3276, 0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15, -+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05, 0x80, 0xFF, 0x88, 0x08, -+ 0x05, 0x80, 0x3DB, 0x3D7, 0x3D3, 0x427, 0x42B, 0x42F}, -+ { -+ 11, 2462, 3283, 0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15, -+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04, 0x80, 0xFF, 0x88, 0x08, -+ 0x04, 0x80, 0x3DD, 0x3D9, 0x3D5, 0x424, 0x429, 0x42D}, -+ { -+ 12, 2467, 3289, 0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15, -+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03, 0x80, 0xFF, 0x88, 0x08, -+ 0x03, 0x80, 0x3DF, 0x3DB, 0x3D7, 0x422, 0x427, 0x42B}, -+ { -+ 13, 2472, 3296, 0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15, -+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03, 0x80, 0xFF, 0x88, 0x07, -+ 0x03, 0x80, 0x3E1, 0x3DD, 0x3D9, 0x420, 0x424, 0x429}, -+ { -+ 14, 2484, 3312, 0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15, -+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01, 0x80, 0xFF, 0x88, 0x07, -+ 0x01, 0x80, 0x3E6, 0x3E2, 0x3DE, 0x41B, 0x41F, 0x424} -+}; -+ -+static const struct chan_info_nphy_radio205x chan_info_nphyrev3_2056[] = { -+ { -+ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, -+ { -+ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, -+ { -+ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, -+ { -+ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, -+ { -+ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, -+ { -+ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, -+ { -+ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, -+ { -+ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, -+ { -+ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, -+ { -+ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, -+ { -+ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, -+ { -+ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, -+ { -+ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, -+ { -+ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, -+ { -+ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, -+ { -+ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, -+ { -+ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, -+ { -+ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, -+ { -+ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xff, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, -+ { -+ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xfc, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, -+ { -+ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xfc, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, -+ { -+ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xfc, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, -+ { -+ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xfc, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, -+ { -+ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xfc, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, -+ { -+ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xfc, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, -+ { -+ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xfc, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, -+ { -+ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xfc, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, -+ { -+ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, -+ { -+ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, -+ { -+ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, -+ { -+ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, -+ { -+ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, -+ { -+ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, -+ { -+ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, -+ { -+ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, -+ { -+ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, -+ { -+ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, -+ { -+ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xfc, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, -+ { -+ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, -+ { -+ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, -+ { -+ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, -+ { -+ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, -+ { -+ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, -+ { -+ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, -+ { -+ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, -+ { -+ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, -+ { -+ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x05, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, -+ { -+ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, -+ 0x00, 0xfa, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, -+ { -+ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, -+ 0x00, 0xfa, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, -+ { -+ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, -+ 0x00, 0xfa, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, -+ { -+ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, -+ 0x00, 0xfa, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, -+ { -+ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, -+ 0x00, 0xfa, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, -+ { -+ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, -+ 0x00, 0xfa, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, -+ { -+ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, -+ 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, -+ { -+ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, -+ 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, -+ { -+ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, -+ 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, -+ { -+ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, -+ 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, -+ { -+ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf8, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, -+ { -+ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf8, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, -+ { -+ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf8, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, -+ { -+ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf8, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, -+ { -+ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf8, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, -+ { -+ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf8, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, -+ { -+ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf8, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, -+ { -+ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf8, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, -+ { -+ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf8, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, -+ { -+ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf8, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, -+ { -+ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf8, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, -+ { -+ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf8, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, -+ { -+ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf8, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, -+ { -+ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf8, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, -+ { -+ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf8, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, -+ { -+ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf8, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, -+ { -+ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf6, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, -+ { -+ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf6, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, -+ { -+ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf6, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, -+ { -+ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf6, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, -+ { -+ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf6, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, -+ { -+ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, -+ { -+ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, -+ { -+ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, -+ { -+ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, -+ { -+ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, -+ { -+ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, -+ { -+ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, -+ { -+ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, -+ { -+ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, -+ { -+ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, -+ { -+ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, -+ { -+ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, -+ { -+ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, -+ { -+ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, -+ { -+ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, -+ { -+ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, -+ { -+ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, -+ { -+ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, -+ { -+ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, -+ { -+ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, -+ { -+ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, -+ { -+ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, -+ { -+ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, -+ { -+ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, -+ { -+ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, -+ { -+ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf4, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, -+ { -+ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf2, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf2, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, -+ { -+ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf2, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, -+ { -+ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf2, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, -+ { -+ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, -+ 0x00, 0xf2, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, -+ { -+ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x05, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05, -+ 0x00, 0xf2, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, -+ { -+ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x05, 0x00, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05, -+ 0x00, 0xf2, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, -+ { -+ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0f, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, -+ { -+ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0f, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, -+ { -+ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0f, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, -+ { -+ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x05, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfd, 0x00, 0x05, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0f, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, -+ { -+ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x05, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfb, 0x00, 0x05, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0f, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, -+ { -+ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x05, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x05, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0f, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, -+ { -+ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x05, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x05, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0f, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, -+ { -+ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x05, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf7, 0x00, 0x05, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0f, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, -+ { -+ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x05, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf6, 0x00, 0x05, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0f, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, -+ { -+ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x05, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf5, 0x00, 0x05, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0d, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, -+ { -+ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x05, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0d, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, -+ { -+ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x05, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf3, 0x00, 0x05, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0d, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, -+ { -+ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x05, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0d, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, -+ { -+ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x05, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf0, 0x00, 0x05, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0d, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} -+}; -+ -+static const struct chan_info_nphy_radio205x chan_info_nphyrev4_2056_A1[] = { -+ { -+ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, -+ { -+ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, -+ { -+ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, -+ { -+ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, -+ { -+ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, -+ { -+ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, -+ { -+ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, -+ { -+ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, -+ { -+ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, -+ { -+ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, -+ { -+ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, -+ { -+ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, -+ { -+ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, -+ { -+ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, -+ { -+ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, -+ { -+ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, -+ { -+ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, -+ { -+ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, -+ { -+ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfe, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, -+ { -+ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfe, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, -+ { -+ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfe, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, -+ { -+ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfe, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, -+ { -+ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfe, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, -+ { -+ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfe, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, -+ { -+ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfe, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, -+ { -+ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfe, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, -+ { -+ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfe, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, -+ { -+ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0a, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, -+ { -+ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, -+ { -+ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, -+ { -+ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, -+ { -+ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, -+ { -+ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, -+ { -+ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, -+ { -+ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, -+ { -+ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, -+ { -+ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, -+ { -+ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfa, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, -+ { -+ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, -+ { -+ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, -+ { -+ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, -+ { -+ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, -+ { -+ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, -+ { -+ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, -+ { -+ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, -+ { -+ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, -+ { -+ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x08, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, -+ { -+ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xf8, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, -+ { -+ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xf8, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, -+ { -+ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xf8, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, -+ { -+ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xf8, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, -+ { -+ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xf8, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, -+ { -+ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xf8, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, -+ { -+ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, -+ { -+ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, -+ { -+ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, -+ { -+ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x07, 0x00, 0x7f, -+ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, -+ 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, -+ { -+ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x5c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, -+ 0x00, 0xf6, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, -+ { -+ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, -+ 0x00, 0xf6, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, -+ { -+ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, -+ 0x00, 0xf6, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, -+ { -+ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, -+ 0x00, 0xf6, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, -+ { -+ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, -+ 0x00, 0xf6, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, -+ { -+ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, -+ 0x00, 0xf6, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, -+ { -+ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, -+ 0x00, 0xf6, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, -+ { -+ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, -+ 0x00, 0xf6, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, -+ { -+ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, -+ 0x00, 0xf6, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, -+ { -+ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f, -+ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, -+ 0x00, 0xf6, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, -+ { -+ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xf4, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, -+ { -+ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xf4, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, -+ { -+ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xf4, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, -+ { -+ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xf4, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, -+ { -+ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xf4, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, -+ { -+ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xf4, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, -+ { -+ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xf4, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, -+ { -+ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xf4, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, -+ { -+ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xf4, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, -+ { -+ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x04, 0x00, 0x7f, -+ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, -+ 0x00, 0xf4, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, -+ { -+ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, -+ { -+ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, -+ { -+ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, -+ { -+ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, -+ { -+ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, -+ { -+ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, -+ { -+ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, -+ { -+ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, -+ { -+ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, -+ { -+ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, -+ { -+ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, -+ { -+ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, -+ { -+ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, -+ { -+ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, -+ { -+ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, -+ { -+ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, -+ { -+ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, -+ { -+ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, -+ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, -+ 0x00, 0xf2, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, -+ { -+ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xf0, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, -+ { -+ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xf0, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, -+ { -+ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xf0, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, -+ { -+ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xf0, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, -+ { -+ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xf0, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, -+ { -+ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xf0, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, -+ { -+ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xf0, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, -+ { -+ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xf0, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, -+ { -+ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xf0, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, -+ { -+ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xf0, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, -+ { -+ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xf0, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, -+ { -+ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xf0, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, -+ { -+ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, -+ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, -+ 0x00, 0xf0, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, -+ { -+ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf0, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, -+ { -+ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, -+ 0x00, 0x07, 0x00, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07, -+ 0x00, 0xf0, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, -+ { -+ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0e, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, -+ { -+ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0e, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, -+ { -+ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0e, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, -+ { -+ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x04, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfd, 0x00, 0x04, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0e, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, -+ { -+ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x04, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfb, 0x00, 0x04, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0e, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, -+ { -+ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0e, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, -+ { -+ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x04, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf8, 0x00, 0x04, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0e, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, -+ { -+ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x04, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf7, 0x00, 0x04, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0e, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, -+ { -+ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0e, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, -+ { -+ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x04, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf5, 0x00, 0x04, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0e, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, -+ { -+ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x04, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0e, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, -+ { -+ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x04, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf3, 0x00, 0x04, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0e, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, -+ { -+ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x04, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0e, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, -+ { -+ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x04, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0e, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} -+}; -+ -+static const struct chan_info_nphy_radio205x chan_info_nphyrev5_2056v5[] = { -+ { -+ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, -+ 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, -+ { -+ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, -+ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, -+ { -+ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, -+ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, -+ { -+ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, -+ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, -+ { -+ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, -+ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, -+ { -+ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, -+ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, -+ { -+ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, -+ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, -+ { -+ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, -+ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, -+ { -+ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, -+ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, -+ { -+ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, -+ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, -+ { -+ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, -+ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, -+ { -+ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, -+ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, -+ { -+ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, -+ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, -+ { -+ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, -+ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, -+ { -+ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70, -+ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, -+ { -+ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70, -+ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, -+ { -+ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, -+ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, -+ { -+ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, -+ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, -+ { -+ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, -+ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, -+ { -+ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, -+ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, -+ { -+ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, -+ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, -+ { -+ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70, -+ 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, -+ { -+ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, -+ 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, -+ { -+ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, -+ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09, -+ 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, -+ { -+ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70, -+ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, -+ 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, -+ { -+ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, -+ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, -+ 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, -+ { -+ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, -+ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, -+ 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, -+ { -+ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, -+ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, -+ 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, -+ { -+ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, -+ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, -+ 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, -+ { -+ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, -+ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, -+ 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, -+ { -+ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xea, 0x00, 0x06, 0x00, 0x70, -+ 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08, -+ 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, -+ { -+ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70, -+ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, -+ 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, -+ { -+ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70, -+ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, -+ 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, -+ { -+ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xd9, 0x00, 0x05, 0x00, 0x70, -+ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, -+ 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, -+ { -+ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xd8, 0x00, 0x04, 0x00, 0x70, -+ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, -+ 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, -+ { -+ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, -+ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, -+ 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, -+ { -+ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, -+ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, -+ 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, -+ { -+ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, -+ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, -+ 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, -+ { -+ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, -+ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, -+ 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, -+ { -+ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb8, 0x00, 0x04, 0x00, 0x70, -+ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, -+ 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, -+ { -+ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x04, 0x00, 0x70, -+ 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, -+ 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, -+ { -+ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07, -+ 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, -+ { -+ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa7, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, -+ 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, -+ { -+ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, -+ 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, -+ { -+ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, -+ 0x00, 0x5b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, -+ { -+ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x96, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, -+ 0x00, 0x5a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, -+ { -+ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x95, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, -+ 0x00, 0x5a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, -+ { -+ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, -+ 0x00, 0x5a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, -+ { -+ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, -+ 0x00, 0x5a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, -+ { -+ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, -+ 0x00, 0x5a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, -+ { -+ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x85, 0x00, 0x02, 0x00, 0x70, -+ 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, -+ 0x00, 0x59, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, -+ { -+ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, -+ 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, -+ 0x00, 0x59, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, -+ { -+ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, -+ 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, -+ 0x00, 0x59, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, -+ { -+ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, -+ 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04, -+ 0x00, 0x69, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, -+ { -+ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x74, 0x00, 0x01, 0x00, 0x70, -+ 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, -+ 0x00, 0x69, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, -+ { -+ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70, -+ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, -+ { -+ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70, -+ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, -+ { -+ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, -+ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, -+ 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, -+ { -+ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, -+ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, -+ 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, -+ { -+ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, -+ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, -+ 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, -+ { -+ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x63, 0x00, 0x01, 0x00, 0x70, -+ 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03, -+ 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, -+ { -+ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, -+ 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, -+ { -+ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, -+ 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, -+ { -+ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, -+ 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, -+ { -+ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, -+ 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, -+ { -+ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, -+ 0x00, 0x76, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, -+ { -+ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x51, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, -+ 0x00, 0x76, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, -+ { -+ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, -+ 0x00, 0x76, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, -+ { -+ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, -+ 0x00, 0x76, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, -+ { -+ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, -+ 0x00, 0x76, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, -+ { -+ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, -+ 0x00, 0x76, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, -+ { -+ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, -+ 0x00, 0x75, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, -+ { -+ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x75, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, -+ { -+ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x75, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, -+ { -+ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x74, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, -+ { -+ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x74, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, -+ { -+ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x74, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, -+ { -+ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x74, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, -+ { -+ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x74, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, -+ { -+ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x74, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, -+ { -+ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x74, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, -+ { -+ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x84, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, -+ { -+ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x83, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, -+ { -+ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x83, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, -+ { -+ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x83, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, -+ { -+ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x83, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, -+ { -+ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x83, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, -+ { -+ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x83, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, -+ { -+ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x82, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, -+ { -+ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x82, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, -+ { -+ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x82, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, -+ { -+ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x82, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, -+ { -+ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x82, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, -+ { -+ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x82, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, -+ { -+ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x82, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, -+ { -+ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x82, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, -+ { -+ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x82, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, -+ { -+ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x82, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, -+ { -+ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x82, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, -+ { -+ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x82, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, -+ { -+ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x82, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, -+ { -+ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x72, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, -+ { -+ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x72, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, -+ { -+ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x72, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, -+ { -+ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x72, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, -+ { -+ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x71, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, -+ { -+ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x71, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, -+ { -+ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x71, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, -+ { -+ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x71, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, -+ { -+ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x71, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, -+ { -+ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, -+ { -+ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, -+ { -+ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, -+ { -+ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, -+ { -+ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, -+ { -+ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, -+ { -+ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, -+ { -+ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x08, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, -+ { -+ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x07, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, -+ { -+ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x06, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, -+ { -+ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x05, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, -+ { -+ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, -+ { -+ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x03, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, -+ { -+ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} -+}; -+ -+static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v6[] = { -+ { -+ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, -+ { -+ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, -+ { -+ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, -+ { -+ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, -+ { -+ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, -+ { -+ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, -+ { -+ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, -+ { -+ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, -+ { -+ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, -+ { -+ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, -+ { -+ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, -+ { -+ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, -+ { -+ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, -+ { -+ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, -+ { -+ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, -+ { -+ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, -+ { -+ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, -+ { -+ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, -+ { -+ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, -+ { -+ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, -+ { -+ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, -+ { -+ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, -+ { -+ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, -+ { -+ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, -+ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, -+ { -+ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, -+ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, -+ { -+ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, -+ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, -+ { -+ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, -+ { -+ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, -+ { -+ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, -+ { -+ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, -+ { -+ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, -+ { -+ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, -+ { -+ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, -+ { -+ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, -+ { -+ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, -+ { -+ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, -+ { -+ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, -+ { -+ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, -+ { -+ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, -+ { -+ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, -+ { -+ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, -+ { -+ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, -+ { -+ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, -+ { -+ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, -+ { -+ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, -+ { -+ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, -+ { -+ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, -+ { -+ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, -+ { -+ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, -+ { -+ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, -+ { -+ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, -+ { -+ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, -+ { -+ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, -+ { -+ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, -+ { -+ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, -+ { -+ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, -+ { -+ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, -+ { -+ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, -+ { -+ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, -+ { -+ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, -+ { -+ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, -+ { -+ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, -+ { -+ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, -+ { -+ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, -+ { -+ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, -+ { -+ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, -+ 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, -+ { -+ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, -+ 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, -+ { -+ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, -+ 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, -+ { -+ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, -+ 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, -+ { -+ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, -+ 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, -+ { -+ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, -+ 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, -+ { -+ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, -+ 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, -+ { -+ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, -+ 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, -+ { -+ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, -+ { -+ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, -+ { -+ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, -+ { -+ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, -+ { -+ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, -+ { -+ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, -+ { -+ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, -+ { -+ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, -+ { -+ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, -+ { -+ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, -+ { -+ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, -+ { -+ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, -+ { -+ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, -+ { -+ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, -+ { -+ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, -+ { -+ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, -+ { -+ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, -+ { -+ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, -+ { -+ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, -+ { -+ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, -+ { -+ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, -+ { -+ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, -+ { -+ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, -+ { -+ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, -+ { -+ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, -+ { -+ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, -+ { -+ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, -+ { -+ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, -+ { -+ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, -+ { -+ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, -+ { -+ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, -+ { -+ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, -+ { -+ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, -+ { -+ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, -+ { -+ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, -+ { -+ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, -+ { -+ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, -+ { -+ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, -+ { -+ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, -+ { -+ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, -+ { -+ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, -+ { -+ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, -+ { -+ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, -+ { -+ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, -+ { -+ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, -+ { -+ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, -+ { -+ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, -+ { -+ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, -+ { -+ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, -+ { -+ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, -+ { -+ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} -+}; -+ -+static const struct chan_info_nphy_radio205x chan_info_nphyrev5n6_2056v7[] = { -+ { -+ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, -+ 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, -+ { -+ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, -+ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, -+ { -+ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, -+ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, -+ { -+ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, -+ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, -+ { -+ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, -+ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, -+ { -+ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, -+ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, -+ { -+ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, -+ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, -+ { -+ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, -+ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, -+ { -+ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, -+ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, -+ { -+ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, -+ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, -+ { -+ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, -+ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, -+ { -+ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, -+ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, -+ { -+ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, -+ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, -+ { -+ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, -+ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, -+ { -+ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70, -+ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, -+ { -+ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70, -+ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, -+ { -+ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, -+ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, -+ { -+ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, -+ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, -+ { -+ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, -+ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, -+ { -+ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, -+ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, -+ { -+ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, -+ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, -+ { -+ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70, -+ 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, -+ { -+ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, -+ 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, -+ { -+ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, -+ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09, -+ 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, -+ { -+ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70, -+ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, -+ 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, -+ { -+ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, -+ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, -+ 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, -+ { -+ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, -+ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, -+ 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, -+ { -+ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, -+ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, -+ 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, -+ { -+ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, -+ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, -+ 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, -+ { -+ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xfa, 0x00, 0x06, 0x00, 0x70, -+ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, -+ 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, -+ { -+ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xea, 0x00, 0x06, 0x00, 0x70, -+ 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08, -+ 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, -+ { -+ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xe9, 0x00, 0x05, 0x00, 0x70, -+ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, -+ 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, -+ { -+ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xe9, 0x00, 0x05, 0x00, 0x70, -+ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, -+ 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, -+ { -+ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xd9, 0x00, 0x05, 0x00, 0x70, -+ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, -+ 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, -+ { -+ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xd8, 0x00, 0x04, 0x00, 0x70, -+ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, -+ 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, -+ { -+ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, -+ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, -+ 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, -+ { -+ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, -+ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, -+ 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, -+ { -+ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, -+ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, -+ 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, -+ { -+ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, -+ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, -+ 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, -+ { -+ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb8, 0x00, 0x04, 0x00, 0x70, -+ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, -+ 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, -+ { -+ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xb7, 0x00, 0x04, 0x00, 0x70, -+ 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, -+ 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, -+ { -+ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xb7, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07, -+ 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, -+ { -+ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa7, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, -+ 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, -+ { -+ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, -+ 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, -+ { -+ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, -+ 0x00, 0x7b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, -+ { -+ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x96, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, -+ 0x00, 0x7a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, -+ { -+ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, -+ 0x00, 0x7a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, -+ { -+ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, -+ 0x00, 0x7a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, -+ { -+ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x95, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, -+ 0x00, 0x7a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, -+ { -+ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x95, 0x00, 0x03, 0x00, 0x70, -+ 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, -+ 0x00, 0x7a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, -+ { -+ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x85, 0x00, 0x02, 0x00, 0x70, -+ 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, -+ 0x00, 0x79, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, -+ { -+ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x70, -+ 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, -+ 0x00, 0x79, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, -+ { -+ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70, -+ 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, -+ 0x00, 0x79, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, -+ { -+ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70, -+ 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04, -+ 0x00, 0x79, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, -+ { -+ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x74, 0x00, 0x01, 0x00, 0x70, -+ 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, -+ 0x00, 0x79, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, -+ { -+ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, -+ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, -+ 0x00, 0x78, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, -+ { -+ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x01, 0x00, 0x70, -+ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, -+ 0x00, 0x78, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, -+ { -+ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70, -+ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, -+ 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, -+ { -+ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70, -+ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, -+ 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, -+ { -+ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x01, 0x00, 0x70, -+ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, -+ 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, -+ { -+ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x63, 0x00, 0x01, 0x00, 0x70, -+ 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03, -+ 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, -+ { -+ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x62, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, -+ 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, -+ { -+ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, -+ 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, -+ { -+ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, -+ 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, -+ { -+ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x52, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, -+ 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, -+ { -+ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x52, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, -+ 0x00, 0x86, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, -+ { -+ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, -+ 0x00, 0x86, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, -+ { -+ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, -+ 0x00, 0x86, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, -+ { -+ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, -+ 0x00, 0x86, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, -+ { -+ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, -+ 0x00, 0x86, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, -+ { -+ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, -+ 0x00, 0x86, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, -+ { -+ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x51, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, -+ 0x00, 0x85, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, -+ { -+ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x85, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, -+ { -+ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x85, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, -+ { -+ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x84, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, -+ { -+ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x84, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, -+ { -+ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x94, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, -+ { -+ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x94, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, -+ { -+ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x94, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, -+ { -+ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x94, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, -+ { -+ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x94, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, -+ { -+ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, -+ 0x00, 0x94, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, -+ { -+ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x93, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, -+ { -+ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x93, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, -+ { -+ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x93, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, -+ { -+ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x93, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, -+ { -+ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x30, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x93, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, -+ { -+ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x93, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, -+ { -+ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, -+ { -+ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, -+ { -+ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, -+ { -+ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, -+ { -+ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, -+ { -+ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, -+ { -+ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, -+ { -+ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, -+ { -+ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, -+ { -+ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, -+ { -+ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, -+ { -+ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, -+ { -+ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, -+ { -+ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, -+ { -+ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, -+ { -+ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, -+ { -+ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x92, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, -+ { -+ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x91, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, -+ { -+ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x91, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, -+ { -+ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x91, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, -+ { -+ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x91, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, -+ { -+ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, -+ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, -+ 0x00, 0x91, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, -+ { -+ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, -+ { -+ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, -+ { -+ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, -+ { -+ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, -+ { -+ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, -+ { -+ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x76, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, -+ { -+ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x66, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, -+ { -+ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x55, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, -+ { -+ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, -+ { -+ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, -+ { -+ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, -+ { -+ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x22, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, -+ { -+ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, -+ { -+ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} -+}; -+ -+static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v8[] = { -+ { -+ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, -+ { -+ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, -+ { -+ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, -+ { -+ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, -+ { -+ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, -+ { -+ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, -+ { -+ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, -+ { -+ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, -+ { -+ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, -+ { -+ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, -+ { -+ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, -+ { -+ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, -+ { -+ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, -+ { -+ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, -+ { -+ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, -+ { -+ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, -+ { -+ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, -+ { -+ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, -+ { -+ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, -+ { -+ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, -+ { -+ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, -+ { -+ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, -+ { -+ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, -+ { -+ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, -+ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, -+ { -+ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, -+ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, -+ { -+ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, -+ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, -+ { -+ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, -+ { -+ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, -+ { -+ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, -+ { -+ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, -+ { -+ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, -+ { -+ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, -+ { -+ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, -+ { -+ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, -+ { -+ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, -+ { -+ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, -+ { -+ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, -+ { -+ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, -+ { -+ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, -+ { -+ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, -+ { -+ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, -+ { -+ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, -+ { -+ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, -+ { -+ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, -+ { -+ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, -+ { -+ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, -+ { -+ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, -+ { -+ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, -+ { -+ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, -+ { -+ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, -+ { -+ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, -+ { -+ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, -+ { -+ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, -+ { -+ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, -+ { -+ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, -+ { -+ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, -+ { -+ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, -+ { -+ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, -+ { -+ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, -+ { -+ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, -+ { -+ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, -+ { -+ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, -+ { -+ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, -+ { -+ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, -+ { -+ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, -+ { -+ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, -+ 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, -+ { -+ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, -+ 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, -+ { -+ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, -+ 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, -+ { -+ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, -+ 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, -+ { -+ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, -+ 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, -+ { -+ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, -+ 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, -+ { -+ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, -+ 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, -+ { -+ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, -+ 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, -+ { -+ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, -+ { -+ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, -+ { -+ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, -+ { -+ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, -+ { -+ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, -+ { -+ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, -+ { -+ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, -+ { -+ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, -+ { -+ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, -+ { -+ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, -+ { -+ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, -+ { -+ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, -+ { -+ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, -+ { -+ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, -+ { -+ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, -+ { -+ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, -+ { -+ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, -+ { -+ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, -+ { -+ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, -+ { -+ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, -+ { -+ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, -+ { -+ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, -+ { -+ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, -+ { -+ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, -+ { -+ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, -+ { -+ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, -+ { -+ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, -+ { -+ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, -+ { -+ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, -+ { -+ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, -+ { -+ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, -+ { -+ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, -+ { -+ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, -+ { -+ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, -+ { -+ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, -+ { -+ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, -+ { -+ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, -+ { -+ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, -+ { -+ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, -+ { -+ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, -+ { -+ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, -+ { -+ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, -+ { -+ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, -+ { -+ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, -+ { -+ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, -+ { -+ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, -+ { -+ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, -+ { -+ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, -+ { -+ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, -+ { -+ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, -+ { -+ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, -+ 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} -+}; -+ -+static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v11[] = { -+ { -+ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, -+ { -+ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, -+ { -+ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, -+ { -+ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, -+ { -+ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, -+ { -+ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, -+ { -+ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, -+ { -+ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, -+ { -+ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, -+ { -+ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, -+ { -+ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, -+ { -+ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, -+ { -+ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, -+ { -+ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, -+ { -+ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, -+ { -+ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, -+ { -+ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, -+ { -+ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, -+ { -+ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, -+ { -+ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, -+ { -+ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, -+ { -+ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, -+ { -+ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, -+ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, -+ 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, -+ { -+ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, -+ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, -+ { -+ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, -+ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, -+ { -+ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, -+ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e, -+ 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, -+ { -+ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, -+ { -+ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, -+ { -+ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, -+ { -+ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, -+ { -+ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, -+ { -+ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, -+ { -+ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, -+ { -+ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, -+ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d, -+ 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, -+ { -+ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, -+ { -+ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, -+ { -+ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, -+ { -+ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, -+ { -+ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, -+ { -+ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, -+ 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, -+ { -+ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, -+ { -+ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, -+ { -+ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, -+ 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, -+ { -+ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, -+ { -+ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, -+ { -+ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, -+ { -+ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, -+ { -+ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, -+ { -+ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, -+ { -+ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, -+ { -+ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, -+ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, -+ 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, -+ { -+ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, -+ { -+ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, -+ { -+ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, -+ { -+ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, -+ { -+ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, -+ { -+ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, -+ { -+ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, -+ { -+ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, -+ { -+ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, -+ { -+ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, -+ { -+ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, -+ { -+ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, -+ { -+ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, -+ { -+ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, -+ 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, -+ { -+ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, -+ 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, -+ { -+ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, -+ 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, -+ { -+ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, -+ 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, -+ { -+ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, -+ 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, -+ { -+ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, -+ 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, -+ { -+ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, -+ 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, -+ { -+ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, -+ 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, -+ { -+ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, -+ 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, -+ { -+ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, -+ { -+ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, -+ { -+ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, -+ { -+ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, -+ { -+ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, -+ { -+ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, -+ { -+ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, -+ { -+ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x05, 0x05, 0x02, 0x15, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, -+ { -+ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, -+ { -+ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x05, 0x05, 0x02, 0x15, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, -+ { -+ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, -+ { -+ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x05, 0x05, 0x02, 0x15, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, -+ 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, -+ { -+ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, -+ { -+ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x05, 0x05, 0x02, 0x15, 0x01, -+ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, -+ { -+ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, -+ { -+ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x05, 0x05, 0x02, 0x15, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, -+ { -+ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, -+ { -+ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x05, 0x05, 0x02, 0x15, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, -+ { -+ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, -+ { -+ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x05, 0x05, 0x02, 0x15, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, -+ { -+ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, -+ { -+ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x05, 0x05, 0x02, 0x15, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, -+ { -+ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, -+ { -+ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x05, 0x05, 0x02, 0x15, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, -+ { -+ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, -+ { -+ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x05, 0x05, 0x02, 0x15, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, -+ { -+ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, -+ { -+ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x05, 0x05, 0x02, 0x15, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, -+ { -+ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, -+ 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, -+ { -+ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, -+ { -+ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, -+ { -+ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, -+ { -+ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, -+ { -+ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, -+ { -+ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, -+ { -+ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, -+ { -+ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x02, 0x0c, 0x01, -+ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, -+ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, -+ 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, -+ { -+ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x06, 0x06, 0x04, 0x2b, 0x01, -+ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, -+ { -+ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x06, 0x06, 0x04, 0x2b, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, -+ { -+ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x06, 0x06, 0x04, 0x2b, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, -+ { -+ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x06, 0x06, 0x04, 0x2b, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, -+ { -+ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x06, 0x06, 0x04, 0x2b, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, -+ { -+ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x06, 0x06, 0x04, 0x2b, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, -+ { -+ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x06, 0x06, 0x04, 0x2b, 0x01, -+ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, -+ { -+ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x06, 0x06, 0x04, 0x2b, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, -+ { -+ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x06, 0x06, 0x04, 0x2b, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, -+ { -+ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x06, 0x06, 0x04, 0x2b, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, -+ { -+ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x06, 0x06, 0x04, 0x2b, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, -+ { -+ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x06, 0x06, 0x04, 0x2b, 0x01, -+ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, -+ { -+ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x06, 0x06, 0x04, 0x2b, 0x01, -+ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, -+ { -+ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x06, 0x06, 0x04, 0x2b, 0x01, -+ 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, -+ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, -+ 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} -+}; -+ -+static const struct chan_info_nphy_radio2057 chan_info_nphyrev7_2057_rev4[] = { -+ { -+ 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, -+ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b4, 0x07b0, 0x07ac, 0x0214, -+ 0x0215, -+ 0x0216, -+ }, -+ { -+ 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, -+ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b8, 0x07b4, 0x07b0, 0x0213, -+ 0x0214, -+ 0x0215, -+ }, -+ { -+ 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, -+ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07bc, 0x07b8, 0x07b4, 0x0212, -+ 0x0213, -+ 0x0214, -+ }, -+ { -+ 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, -+ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c0, 0x07bc, 0x07b8, 0x0211, -+ 0x0212, -+ 0x0213, -+ }, -+ { -+ 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, -+ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c4, 0x07c0, 0x07bc, 0x020f, -+ 0x0211, -+ 0x0212, -+ }, -+ { -+ 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, -+ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c8, 0x07c4, 0x07c0, 0x020e, -+ 0x020f, -+ 0x0211, -+ }, -+ { -+ 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, -+ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07cc, 0x07c8, 0x07c4, 0x020d, -+ 0x020e, -+ 0x020f, -+ }, -+ { -+ 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, -+ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d0, 0x07cc, 0x07c8, 0x020c, -+ 0x020d, -+ 0x020e, -+ }, -+ { -+ 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, -+ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d4, 0x07d0, 0x07cc, 0x020b, -+ 0x020c, -+ 0x020d, -+ }, -+ { -+ 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, -+ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d8, 0x07d4, 0x07d0, 0x020a, -+ 0x020b, -+ 0x020c, -+ }, -+ { -+ 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, -+ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07dc, 0x07d8, 0x07d4, 0x0209, -+ 0x020a, -+ 0x020b, -+ }, -+ { -+ 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, -+ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e0, 0x07dc, 0x07d8, 0x0208, -+ 0x0209, -+ 0x020a, -+ }, -+ { -+ 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, -+ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e4, 0x07e0, 0x07dc, 0x0207, -+ 0x0208, -+ 0x0209, -+ }, -+ { -+ 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, -+ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e8, 0x07e4, 0x07e0, 0x0206, -+ 0x0207, -+ 0x0208, -+ }, -+ { -+ 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x00, -+ 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x07ec, 0x07e8, 0x07e4, 0x0205, -+ 0x0206, -+ 0x0207, -+ }, -+ { -+ 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00, -+ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f0, 0x07ec, 0x07e8, 0x0204, -+ 0x0205, -+ 0x0206, -+ }, -+ { -+ 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00, -+ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f4, 0x07f0, 0x07ec, 0x0203, -+ 0x0204, -+ 0x0205, -+ }, -+ { -+ 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07f8, 0x07f4, 0x07f0, 0x0202, -+ 0x0203, -+ 0x0204, -+ }, -+ { -+ 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07fc, 0x07f8, 0x07f4, 0x0201, -+ 0x0202, -+ 0x0203, -+ }, -+ { -+ 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0800, 0x07fc, 0x07f8, 0x0200, -+ 0x0201, -+ 0x0202, -+ }, -+ { -+ 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0804, 0x0800, 0x07fc, 0x01ff, -+ 0x0200, -+ 0x0201, -+ }, -+ { -+ 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0808, 0x0804, 0x0800, 0x01fe, -+ 0x01ff, -+ 0x0200, -+ }, -+ { -+ 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x080c, 0x0808, 0x0804, 0x01fd, -+ 0x01fe, -+ 0x01ff, -+ }, -+ { -+ 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0814, 0x0810, 0x080c, 0x01fb, -+ 0x01fc, -+ 0x01fd, -+ }, -+ { -+ 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0818, 0x0814, 0x0810, 0x01fa, -+ 0x01fb, -+ 0x01fc, -+ }, -+ { -+ 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x081c, 0x0818, 0x0814, 0x01f9, -+ 0x01fa, -+ 0x01fb, -+ }, -+ { -+ 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0820, 0x081c, 0x0818, 0x01f8, -+ 0x01f9, -+ 0x01fa, -+ }, -+ { -+ 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0824, 0x0820, 0x081c, 0x01f7, -+ 0x01f8, -+ 0x01f9, -+ }, -+ { -+ 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0828, 0x0824, 0x0820, 0x01f6, -+ 0x01f7, -+ 0x01f8, -+ }, -+ { -+ 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x082c, 0x0828, 0x0824, 0x01f5, -+ 0x01f6, -+ 0x01f7, -+ }, -+ { -+ 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0830, 0x082c, 0x0828, 0x01f4, -+ 0x01f5, -+ 0x01f6, -+ }, -+ { -+ 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0834, 0x0830, 0x082c, 0x01f3, -+ 0x01f4, -+ 0x01f5, -+ }, -+ { -+ 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0838, 0x0834, 0x0830, 0x01f2, -+ 0x01f3, -+ 0x01f4, -+ }, -+ { -+ 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x083c, 0x0838, 0x0834, 0x01f1, -+ 0x01f2, -+ 0x01f3, -+ }, -+ { -+ 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00, -+ 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x0840, 0x083c, 0x0838, 0x01f0, -+ 0x01f1, -+ 0x01f2, -+ }, -+ { -+ 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00, -+ 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0844, 0x0840, 0x083c, 0x01f0, -+ 0x01f0, -+ 0x01f1, -+ }, -+ { -+ 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00, -+ 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0848, 0x0844, 0x0840, 0x01ef, -+ 0x01f0, -+ 0x01f0, -+ }, -+ { -+ 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00, -+ 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x084c, 0x0848, 0x0844, 0x01ee, -+ 0x01ef, -+ 0x01f0, -+ }, -+ { -+ 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00, -+ 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0850, 0x084c, 0x0848, 0x01ed, -+ 0x01ee, -+ 0x01ef, -+ }, -+ { -+ 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00, -+ 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0854, 0x0850, 0x084c, 0x01ec, -+ 0x01ed, -+ 0x01ee, -+ }, -+ { -+ 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00, -+ 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0858, 0x0854, 0x0850, 0x01eb, -+ 0x01ec, -+ 0x01ed, -+ }, -+ { -+ 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x00, -+ 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x085c, 0x0858, 0x0854, 0x01ea, -+ 0x01eb, -+ 0x01ec, -+ }, -+ { -+ 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00, -+ 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0860, 0x085c, 0x0858, 0x01e9, -+ 0x01ea, -+ 0x01eb, -+ }, -+ { -+ 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00, -+ 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0864, 0x0860, 0x085c, 0x01e8, -+ 0x01e9, -+ 0x01ea, -+ }, -+ { -+ 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00, -+ 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0868, 0x0864, 0x0860, 0x01e7, -+ 0x01e8, -+ 0x01e9, -+ }, -+ { -+ 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00, -+ 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x086c, 0x0868, 0x0864, 0x01e6, -+ 0x01e7, -+ 0x01e8, -+ }, -+ { -+ 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x00, -+ 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x0870, 0x086c, 0x0868, 0x01e5, -+ 0x01e6, -+ 0x01e7, -+ }, -+ { -+ 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00, -+ 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0874, 0x0870, 0x086c, 0x01e5, -+ 0x01e5, -+ 0x01e6, -+ }, -+ { -+ 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00, -+ 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0878, 0x0874, 0x0870, 0x01e4, -+ 0x01e5, -+ 0x01e5, -+ }, -+ { -+ 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x00, -+ 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x087c, 0x0878, 0x0874, 0x01e3, -+ 0x01e4, -+ 0x01e5, -+ }, -+ { -+ 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00, -+ 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0880, 0x087c, 0x0878, 0x01e2, -+ 0x01e3, -+ 0x01e4, -+ }, -+ { -+ 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00, -+ 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0884, 0x0880, 0x087c, 0x01e1, -+ 0x01e2, -+ 0x01e3, -+ }, -+ { -+ 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00, -+ 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0888, 0x0884, 0x0880, 0x01e0, -+ 0x01e1, -+ 0x01e2, -+ }, -+ { -+ 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x00, -+ 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x088c, 0x0888, 0x0884, 0x01df, -+ 0x01e0, -+ 0x01e1, -+ }, -+ { -+ 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x00, -+ 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x0890, 0x088c, 0x0888, 0x01de, -+ 0x01df, -+ 0x01e0, -+ }, -+ { -+ 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00, -+ 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0894, 0x0890, 0x088c, 0x01dd, -+ 0x01de, -+ 0x01df, -+ }, -+ { -+ 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00, -+ 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0898, 0x0894, 0x0890, 0x01dd, -+ 0x01dd, -+ 0x01de, -+ }, -+ { -+ 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00, -+ 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x089c, 0x0898, 0x0894, 0x01dc, -+ 0x01dd, -+ 0x01dd, -+ }, -+ { -+ 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00, -+ 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x08a0, 0x089c, 0x0898, 0x01db, -+ 0x01dc, -+ 0x01dd, -+ }, -+ { -+ 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00, -+ 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a4, 0x08a0, 0x089c, 0x01da, -+ 0x01db, -+ 0x01dc, -+ }, -+ { -+ 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00, -+ 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a8, 0x08a4, 0x08a0, 0x01d9, -+ 0x01da, -+ 0x01db, -+ }, -+ { -+ 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00, -+ 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08ac, 0x08a8, 0x08a4, 0x01d8, -+ 0x01d9, -+ 0x01da, -+ }, -+ { -+ 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00, -+ 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b0, 0x08ac, 0x08a8, 0x01d7, -+ 0x01d8, -+ 0x01d9, -+ }, -+ { -+ 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00, -+ 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b4, 0x08b0, 0x08ac, 0x01d7, -+ 0x01d7, -+ 0x01d8, -+ }, -+ { -+ 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00, -+ 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b8, 0x08b4, 0x08b0, 0x01d6, -+ 0x01d7, -+ 0x01d7, -+ }, -+ { -+ 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x00, -+ 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x08bc, 0x08b8, 0x08b4, 0x01d5, -+ 0x01d6, -+ 0x01d7, -+ }, -+ { -+ 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x00, -+ 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x08c0, 0x08bc, 0x08b8, 0x01d4, -+ 0x01d5, -+ 0x01d6, -+ }, -+ { -+ 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x00, -+ 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x08c4, 0x08c0, 0x08bc, 0x01d3, -+ 0x01d4, -+ 0x01d5, -+ }, -+ { -+ 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00, -+ 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08c8, 0x08c4, 0x08c0, 0x01d2, -+ 0x01d3, -+ 0x01d4, -+ }, -+ { -+ 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00, -+ 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08cc, 0x08c8, 0x08c4, 0x01d2, -+ 0x01d2, -+ 0x01d3, -+ }, -+ { -+ 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00, -+ 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d0, 0x08cc, 0x08c8, 0x01d1, -+ 0x01d2, -+ 0x01d2, -+ }, -+ { -+ 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00, -+ 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d4, 0x08d0, 0x08cc, 0x01d0, -+ 0x01d1, -+ 0x01d2, -+ }, -+ { -+ 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00, -+ 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08d8, 0x08d4, 0x08d0, 0x01cf, -+ 0x01d0, -+ 0x01d1, -+ }, -+ { -+ 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00, -+ 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08dc, 0x08d8, 0x08d4, 0x01ce, -+ 0x01cf, -+ 0x01d0, -+ }, -+ { -+ 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x00, -+ 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, -+ 0x01ce, -+ 0x01cf, -+ }, -+ { -+ 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00, -+ 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, -+ 0x01ce, -+ 0x01ce, -+ }, -+ { -+ 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00, -+ 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, -+ 0x01cd, -+ 0x01ce, -+ }, -+ { -+ 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00, -+ 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, -+ 0x01cc, -+ 0x01cd, -+ }, -+ { -+ 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00, -+ 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, -+ 0x01cb, -+ 0x01cc, -+ }, -+ { -+ 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00, -+ 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, -+ 0x01ca, -+ 0x01cb, -+ }, -+ { -+ 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x00, -+ 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, -+ 0x01ca, -+ 0x01cb, -+ }, -+ { -+ 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, -+ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, -+ 0x01c9, -+ 0x01ca, -+ }, -+ { -+ 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, -+ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, -+ 0x01c9, -+ 0x01ca, -+ }, -+ { -+ 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, -+ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, -+ 0x01c9, -+ 0x01c9, -+ }, -+ { -+ 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, -+ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, -+ 0x01c8, -+ 0x01c9, -+ }, -+ { -+ 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, -+ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, -+ 0x01c8, -+ 0x01c9, -+ }, -+ { -+ 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, -+ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, -+ 0x01c8, -+ 0x01c8, -+ }, -+ { -+ 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, -+ 0x01c7, -+ 0x01c8, -+ }, -+ { -+ 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, -+ 0x01c7, -+ 0x01c8, -+ }, -+ { -+ 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, -+ 0x01c6, -+ 0x01c7, -+ }, -+ { -+ 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, -+ 0x01c6, -+ 0x01c7, -+ }, -+ { -+ 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, -+ 0x01c6, -+ 0x01c6, -+ }, -+ { -+ 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, -+ 0x01c5, -+ 0x01c6, -+ }, -+ { -+ 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, -+ 0x01c5, -+ 0x01c6, -+ }, -+ { -+ 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, -+ 0x01c4, -+ 0x01c5, -+ }, -+ { -+ 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, -+ 0x01c4, -+ 0x01c5, -+ }, -+ { -+ 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, -+ 0x01c4, -+ 0x01c4, -+ }, -+ { -+ 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, -+ 0x01c3, -+ 0x01c4, -+ }, -+ { -+ 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, -+ 0x01c3, -+ 0x01c4, -+ }, -+ { -+ 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, -+ 0x01c2, -+ 0x01c3, -+ }, -+ { -+ 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, -+ 0x01c2, -+ 0x01c3, -+ }, -+ { -+ 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, -+ 0x01c2, -+ 0x01c2, -+ }, -+ { -+ 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, -+ 0x01c1, -+ 0x01c2, -+ }, -+ { -+ 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04, -+ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, -+ 0x01c0, -+ 0x01c1, -+ }, -+ { -+ 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04, -+ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, -+ 0x01bf, -+ 0x01c0, -+ }, -+ { -+ 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04, -+ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, -+ 0x01bf, -+ 0x01bf, -+ }, -+ { -+ 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03, -+ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, -+ 0x01be, -+ 0x01bf, -+ }, -+ { -+ 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03, -+ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, -+ 0x01bd, -+ 0x01be, -+ }, -+ { -+ 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03, -+ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, -+ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, -+ 0x01bc, -+ 0x01bd, -+ }, -+ { -+ 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f, -+ 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71, -+ 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a, -+ 0x043f, -+ 0x0443, -+ }, -+ { -+ 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f, -+ 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71, -+ 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438, -+ 0x043d, -+ 0x0441, -+ }, -+ { -+ 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f, -+ 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71, -+ 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436, -+ 0x043a, -+ 0x043f, -+ }, -+ { -+ 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f, -+ 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71, -+ 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434, -+ 0x0438, -+ 0x043d, -+ }, -+ { -+ 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f, -+ 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51, -+ 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431, -+ 0x0436, -+ 0x043a, -+ }, -+ { -+ 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f, -+ 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51, -+ 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f, -+ 0x0434, -+ 0x0438, -+ }, -+ { -+ 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f, -+ 0x07, 0x00, 0x07, 0x00, 0x51, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d, -+ 0x0431, -+ 0x0436, -+ }, -+ { -+ 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f, -+ 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b, -+ 0x042f, -+ 0x0434, -+ }, -+ { -+ 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f, -+ 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429, -+ 0x042d, -+ 0x0431, -+ }, -+ { -+ 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f, -+ 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31, -+ 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427, -+ 0x042b, -+ 0x042f, -+ }, -+ { -+ 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f, -+ 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31, -+ 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424, -+ 0x0429, -+ 0x042d, -+ }, -+ { -+ 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f, -+ 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11, -+ 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422, -+ 0x0427, -+ 0x042b, -+ }, -+ { -+ 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f, -+ 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11, -+ 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420, -+ 0x0424, -+ 0x0429, -+ }, -+ { -+ 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f, -+ 0x04, 0x00, 0x04, 0x00, 0x11, 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x11, -+ 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b, -+ 0x041f, -+ 0x0424} -+}; -+ -+static const struct chan_info_nphy_radio2057_rev5 -+chan_info_nphyrev8_2057_rev5[] = { -+ { -+ 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d, -+ 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1, -+ 0x043a, 0x043f, 0x0443}, -+ { -+ 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d, -+ 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3, -+ 0x0438, 0x043d, 0x0441}, -+ { -+ 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d, -+ 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5, -+ 0x0436, 0x043a, 0x043f}, -+ { -+ 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c, -+ 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7, -+ 0x0434, 0x0438, 0x043d}, -+ { -+ 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c, -+ 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9, -+ 0x0431, 0x0436, 0x043a}, -+ { -+ 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c, -+ 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb, -+ 0x042f, 0x0434, 0x0438}, -+ { -+ 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b, -+ 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd, -+ 0x042d, 0x0431, 0x0436}, -+ { -+ 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b, -+ 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf, -+ 0x042b, 0x042f, 0x0434}, -+ { -+ 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b, -+ 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1, -+ 0x0429, 0x042d, 0x0431}, -+ { -+ 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b, -+ 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3, -+ 0x0427, 0x042b, 0x042f}, -+ { -+ 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b, -+ 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5, -+ 0x0424, 0x0429, 0x042d}, -+ { -+ 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b, -+ 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7, -+ 0x0422, 0x0427, 0x042b}, -+ { -+ 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a, -+ 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9, -+ 0x0420, 0x0424, 0x0429}, -+ { -+ 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a, -+ 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de, -+ 0x041b, 0x041f, 0x0424} -+}; -+ -+static const struct chan_info_nphy_radio2057_rev5 -+chan_info_nphyrev9_2057_rev5v1[] = { -+ { -+ 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d, -+ 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1, -+ 0x043a, 0x043f, 0x0443}, -+ { -+ 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d, -+ 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3, -+ 0x0438, 0x043d, 0x0441}, -+ { -+ 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d, -+ 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5, -+ 0x0436, 0x043a, 0x043f}, -+ { -+ 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c, -+ 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7, -+ 0x0434, 0x0438, 0x043d}, -+ { -+ 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c, -+ 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9, -+ 0x0431, 0x0436, 0x043a}, -+ { -+ 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c, -+ 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb, -+ 0x042f, 0x0434, 0x0438}, -+ { -+ 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b, -+ 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd, -+ 0x042d, 0x0431, 0x0436}, -+ { -+ 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b, -+ 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf, -+ 0x042b, 0x042f, 0x0434}, -+ { -+ 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b, -+ 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1, -+ 0x0429, 0x042d, 0x0431}, -+ { -+ 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b, -+ 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3, -+ 0x0427, 0x042b, 0x042f}, -+ { -+ 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b, -+ 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5, -+ 0x0424, 0x0429, 0x042d}, -+ { -+ 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b, -+ 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7, -+ 0x0422, 0x0427, 0x042b}, -+ { -+ 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a, -+ 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9, -+ 0x0420, 0x0424, 0x0429}, -+ { -+ 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a, -+ 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de, -+ 0x041b, 0x041f, 0x0424} -+}; -+ -+static const struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev7[] = { -+ { -+ 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b4, 0x07b0, 0x07ac, 0x0214, -+ 0x0215, -+ 0x0216}, -+ { -+ 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213, -+ 0x0214, -+ 0x0215}, -+ { -+ 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212, -+ 0x0213, -+ 0x0214}, -+ { -+ 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211, -+ 0x0212, -+ 0x0213}, -+ { -+ 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f, -+ 0x0211, -+ 0x0212}, -+ { -+ 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e, -+ 0x020f, -+ 0x0211}, -+ { -+ 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d, -+ 0x020e, -+ 0x020f}, -+ { -+ 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c, -+ 0x020d, -+ 0x020e}, -+ { -+ 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b, -+ 0x020c, -+ 0x020d}, -+ { -+ 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a, -+ 0x020b, -+ 0x020c}, -+ { -+ 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209, -+ 0x020a, -+ 0x020b}, -+ { -+ 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208, -+ 0x0209, -+ 0x020a}, -+ { -+ 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207, -+ 0x0208, -+ 0x0209}, -+ { -+ 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206, -+ 0x0207, -+ 0x0208}, -+ { -+ 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205, -+ 0x0206, -+ 0x0207}, -+ { -+ 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204, -+ 0x0205, -+ 0x0206}, -+ { -+ 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203, -+ 0x0204, -+ 0x0205}, -+ { -+ 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202, -+ 0x0203, -+ 0x0204}, -+ { -+ 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201, -+ 0x0202, -+ 0x0203}, -+ { -+ 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200, -+ 0x0201, -+ 0x0202}, -+ { -+ 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff, -+ 0x0200, -+ 0x0201}, -+ { -+ 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe, -+ 0x01ff, -+ 0x0200}, -+ { -+ 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd, -+ 0x01fe, -+ 0x01ff}, -+ { -+ 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb, -+ 0x01fc, -+ 0x01fd}, -+ { -+ 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa, -+ 0x01fb, -+ 0x01fc}, -+ { -+ 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9, -+ 0x01fa, -+ 0x01fb}, -+ { -+ 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8, -+ 0x01f9, -+ 0x01fa}, -+ { -+ 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7, -+ 0x01f8, -+ 0x01f9}, -+ { -+ 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6, -+ 0x01f7, -+ 0x01f8}, -+ { -+ 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5, -+ 0x01f6, -+ 0x01f7}, -+ { -+ 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4, -+ 0x01f5, -+ 0x01f6}, -+ { -+ 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3, -+ 0x01f4, -+ 0x01f5}, -+ { -+ 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2, -+ 0x01f3, -+ 0x01f4}, -+ { -+ 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1, -+ 0x01f2, -+ 0x01f3}, -+ { -+ 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0, -+ 0x01f1, -+ 0x01f2}, -+ { -+ 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0, -+ 0x01f0, -+ 0x01f1}, -+ { -+ 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef, -+ 0x01f0, -+ 0x01f0}, -+ { -+ 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee, -+ 0x01ef, -+ 0x01f0}, -+ { -+ 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed, -+ 0x01ee, -+ 0x01ef}, -+ { -+ 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec, -+ 0x01ed, -+ 0x01ee}, -+ { -+ 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb, -+ 0x01ec, -+ 0x01ed}, -+ { -+ 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea, -+ 0x01eb, -+ 0x01ec}, -+ { -+ 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9, -+ 0x01ea, -+ 0x01eb}, -+ { -+ 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8, -+ 0x01e9, -+ 0x01ea}, -+ { -+ 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7, -+ 0x01e8, -+ 0x01e9}, -+ { -+ 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6, -+ 0x01e7, -+ 0x01e8}, -+ { -+ 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5, -+ 0x01e6, -+ 0x01e7}, -+ { -+ 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5, -+ 0x01e5, -+ 0x01e6}, -+ { -+ 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4, -+ 0x01e5, -+ 0x01e5}, -+ { -+ 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3, -+ 0x01e4, -+ 0x01e5}, -+ { -+ 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2, -+ 0x01e3, -+ 0x01e4}, -+ { -+ 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1, -+ 0x01e2, -+ 0x01e3}, -+ { -+ 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0, -+ 0x01e1, -+ 0x01e2}, -+ { -+ 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df, -+ 0x01e0, -+ 0x01e1}, -+ { -+ 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de, -+ 0x01df, -+ 0x01e0}, -+ { -+ 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd, -+ 0x01de, -+ 0x01df}, -+ { -+ 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd, -+ 0x01dd, -+ 0x01de}, -+ { -+ 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc, -+ 0x01dd, -+ 0x01dd}, -+ { -+ 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db, -+ 0x01dc, -+ 0x01dd}, -+ { -+ 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da, -+ 0x01db, -+ 0x01dc}, -+ { -+ 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9, -+ 0x01da, -+ 0x01db}, -+ { -+ 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8, -+ 0x01d9, -+ 0x01da}, -+ { -+ 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7, -+ 0x01d8, -+ 0x01d9}, -+ { -+ 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7, -+ 0x01d7, -+ 0x01d8}, -+ { -+ 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6, -+ 0x01d7, -+ 0x01d7}, -+ { -+ 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5, -+ 0x01d6, -+ 0x01d7}, -+ { -+ 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4, -+ 0x01d5, -+ 0x01d6}, -+ { -+ 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3, -+ 0x01d4, -+ 0x01d5}, -+ { -+ 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2, -+ 0x01d3, -+ 0x01d4}, -+ { -+ 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2, -+ 0x01d2, -+ 0x01d3}, -+ { -+ 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1, -+ 0x01d2, -+ 0x01d2}, -+ { -+ 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0, -+ 0x01d1, -+ 0x01d2}, -+ { -+ 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf, -+ 0x01d0, -+ 0x01d1}, -+ { -+ 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce, -+ 0x01cf, -+ 0x01d0}, -+ { -+ 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce, -+ 0x01ce, -+ 0x01cf}, -+ { -+ 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd, -+ 0x01ce, -+ 0x01ce}, -+ { -+ 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc, -+ 0x01cd, -+ 0x01ce}, -+ { -+ 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb, -+ 0x01cc, -+ 0x01cd}, -+ { -+ 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca, -+ 0x01cb, -+ 0x01cc}, -+ { -+ 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9, -+ 0x01ca, -+ 0x01cb}, -+ { -+ 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9, -+ 0x01ca, -+ 0x01cb}, -+ { -+ 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9, -+ 0x01c9, -+ 0x01ca}, -+ { -+ 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8, -+ 0x01c9, -+ 0x01ca}, -+ { -+ 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8, -+ 0x01c9, -+ 0x01c9}, -+ { -+ 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8, -+ 0x01c8, -+ 0x01c9}, -+ { -+ 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, -+ 0x01c8, -+ 0x01c9}, -+ { -+ 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, -+ 0x01c8, -+ 0x01c8}, -+ { -+ 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, -+ 0x01c7, -+ 0x01c8}, -+ { -+ 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, -+ 0x01c7, -+ 0x01c8}, -+ { -+ 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, -+ 0x01c6, -+ 0x01c7}, -+ { -+ 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, -+ 0x01c6, -+ 0x01c7}, -+ { -+ 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, -+ 0x01c6, -+ 0x01c6}, -+ { -+ 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, -+ 0x01c5, -+ 0x01c6}, -+ { -+ 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, -+ 0x01c5, -+ 0x01c6}, -+ { -+ 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, -+ 0x01c4, -+ 0x01c5}, -+ { -+ 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, -+ 0x01c4, -+ 0x01c5}, -+ { -+ 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, -+ 0x01c4, -+ 0x01c4}, -+ { -+ 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, -+ 0x01c3, -+ 0x01c4}, -+ { -+ 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, -+ 0x01c3, -+ 0x01c4}, -+ { -+ 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, -+ 0x01c2, -+ 0x01c3}, -+ { -+ 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, -+ 0x01c2, -+ 0x01c3}, -+ { -+ 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, -+ 0x01c2, -+ 0x01c2}, -+ { -+ 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, -+ 0x01c1, -+ 0x01c2}, -+ { -+ 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04, -+ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, -+ 0x01c0, -+ 0x01c1}, -+ { -+ 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04, -+ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, -+ 0x01bf, -+ 0x01c0}, -+ { -+ 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04, -+ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, -+ 0x01bf, -+ 0x01bf}, -+ { -+ 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03, -+ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, -+ 0x01be, -+ 0x01bf}, -+ { -+ 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03, -+ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, -+ 0x01bd, -+ 0x01be}, -+ { -+ 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03, -+ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, -+ 0x01bc, -+ 0x01bd}, -+ { -+ 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f, -+ 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a, -+ 0x043f, -+ 0x0443}, -+ { -+ 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f, -+ 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438, -+ 0x043d, -+ 0x0441}, -+ { -+ 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f, -+ 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436, -+ 0x043a, -+ 0x043f}, -+ { -+ 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f, -+ 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434, -+ 0x0438, -+ 0x043d}, -+ { -+ 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f, -+ 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431, -+ 0x0436, -+ 0x043a}, -+ { -+ 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f, -+ 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f, -+ 0x0434, -+ 0x0438}, -+ { -+ 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f, -+ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d, -+ 0x0431, -+ 0x0436}, -+ { -+ 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f, -+ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b, -+ 0x042f, -+ 0x0434}, -+ { -+ 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f, -+ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429, -+ 0x042d, -+ 0x0431}, -+ { -+ 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f, -+ 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427, -+ 0x042b, -+ 0x042f}, -+ { -+ 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f, -+ 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424, -+ 0x0429, -+ 0x042d}, -+ { -+ 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f, -+ 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422, -+ 0x0427, -+ 0x042b}, -+ { -+ 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f, -+ 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420, -+ 0x0424, -+ 0x0429}, -+ { -+ 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f, -+ 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b, -+ 0x041f, -+ 0x0424} -+}; -+ -+static const struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev8[] = { -+ { -+ 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213, -+ 0x0214, -+ 0x0215}, -+ { -+ 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212, -+ 0x0213, -+ 0x0214}, -+ { -+ 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211, -+ 0x0212, -+ 0x0213}, -+ { -+ 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f, -+ 0x0211, -+ 0x0212}, -+ { -+ 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e, -+ 0x020f, -+ 0x0211}, -+ { -+ 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d, -+ 0x020e, -+ 0x020f}, -+ { -+ 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c, -+ 0x020d, -+ 0x020e}, -+ { -+ 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b, -+ 0x020c, -+ 0x020d}, -+ { -+ 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f, -+ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a, -+ 0x020b, -+ 0x020c}, -+ { -+ 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209, -+ 0x020a, -+ 0x020b}, -+ { -+ 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208, -+ 0x0209, -+ 0x020a}, -+ { -+ 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207, -+ 0x0208, -+ 0x0209}, -+ { -+ 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206, -+ 0x0207, -+ 0x0208}, -+ { -+ 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205, -+ 0x0206, -+ 0x0207}, -+ { -+ 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204, -+ 0x0205, -+ 0x0206}, -+ { -+ 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203, -+ 0x0204, -+ 0x0205}, -+ { -+ 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e, -+ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, -+ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202, -+ 0x0203, -+ 0x0204}, -+ { -+ 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201, -+ 0x0202, -+ 0x0203}, -+ { -+ 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200, -+ 0x0201, -+ 0x0202}, -+ { -+ 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff, -+ 0x0200, -+ 0x0201}, -+ { -+ 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe, -+ 0x01ff, -+ 0x0200}, -+ { -+ 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd, -+ 0x01fe, -+ 0x01ff}, -+ { -+ 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb, -+ 0x01fc, -+ 0x01fd}, -+ { -+ 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d, -+ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa, -+ 0x01fb, -+ 0x01fc}, -+ { -+ 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9, -+ 0x01fa, -+ 0x01fb}, -+ { -+ 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, -+ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8, -+ 0x01f9, -+ 0x01fa}, -+ { -+ 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7, -+ 0x01f8, -+ 0x01f9}, -+ { -+ 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6, -+ 0x01f7, -+ 0x01f8}, -+ { -+ 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5, -+ 0x01f6, -+ 0x01f7}, -+ { -+ 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4, -+ 0x01f5, -+ 0x01f6}, -+ { -+ 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3, -+ 0x01f4, -+ 0x01f5}, -+ { -+ 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c, -+ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2, -+ 0x01f3, -+ 0x01f4}, -+ { -+ 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1, -+ 0x01f2, -+ 0x01f3}, -+ { -+ 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0, -+ 0x01f1, -+ 0x01f2}, -+ { -+ 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0, -+ 0x01f0, -+ 0x01f1}, -+ { -+ 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, -+ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef, -+ 0x01f0, -+ 0x01f0}, -+ { -+ 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee, -+ 0x01ef, -+ 0x01f0}, -+ { -+ 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed, -+ 0x01ee, -+ 0x01ef}, -+ { -+ 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec, -+ 0x01ed, -+ 0x01ee}, -+ { -+ 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b, -+ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb, -+ 0x01ec, -+ 0x01ed}, -+ { -+ 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea, -+ 0x01eb, -+ 0x01ec}, -+ { -+ 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9, -+ 0x01ea, -+ 0x01eb}, -+ { -+ 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8, -+ 0x01e9, -+ 0x01ea}, -+ { -+ 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7, -+ 0x01e8, -+ 0x01e9}, -+ { -+ 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6, -+ 0x01e7, -+ 0x01e8}, -+ { -+ 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, -+ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5, -+ 0x01e6, -+ 0x01e7}, -+ { -+ 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5, -+ 0x01e5, -+ 0x01e6}, -+ { -+ 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a, -+ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4, -+ 0x01e5, -+ 0x01e5}, -+ { -+ 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3, -+ 0x01e4, -+ 0x01e5}, -+ { -+ 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2, -+ 0x01e3, -+ 0x01e4}, -+ { -+ 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1, -+ 0x01e2, -+ 0x01e3}, -+ { -+ 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0, -+ 0x01e1, -+ 0x01e2}, -+ { -+ 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df, -+ 0x01e0, -+ 0x01e1}, -+ { -+ 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de, -+ 0x01df, -+ 0x01e0}, -+ { -+ 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd, -+ 0x01de, -+ 0x01df}, -+ { -+ 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, -+ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd, -+ 0x01dd, -+ 0x01de}, -+ { -+ 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc, -+ 0x01dd, -+ 0x01dd}, -+ { -+ 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09, -+ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db, -+ 0x01dc, -+ 0x01dd}, -+ { -+ 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da, -+ 0x01db, -+ 0x01dc}, -+ { -+ 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9, -+ 0x01da, -+ 0x01db}, -+ { -+ 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8, -+ 0x01d9, -+ 0x01da}, -+ { -+ 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7, -+ 0x01d8, -+ 0x01d9}, -+ { -+ 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7, -+ 0x01d7, -+ 0x01d8}, -+ { -+ 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6, -+ 0x01d7, -+ 0x01d7}, -+ { -+ 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5, -+ 0x01d6, -+ 0x01d7}, -+ { -+ 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, -+ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4, -+ 0x01d5, -+ 0x01d6}, -+ { -+ 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3, -+ 0x01d4, -+ 0x01d5}, -+ { -+ 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08, -+ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2, -+ 0x01d3, -+ 0x01d4}, -+ { -+ 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2, -+ 0x01d2, -+ 0x01d3}, -+ { -+ 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1, -+ 0x01d2, -+ 0x01d2}, -+ { -+ 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0, -+ 0x01d1, -+ 0x01d2}, -+ { -+ 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf, -+ 0x01d0, -+ 0x01d1}, -+ { -+ 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce, -+ 0x01cf, -+ 0x01d0}, -+ { -+ 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce, -+ 0x01ce, -+ 0x01cf}, -+ { -+ 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd, -+ 0x01ce, -+ 0x01ce}, -+ { -+ 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00, -+ 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc, -+ 0x01cd, -+ 0x01ce}, -+ { -+ 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb, -+ 0x01cc, -+ 0x01cd}, -+ { -+ 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca, -+ 0x01cb, -+ 0x01cc}, -+ { -+ 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07, -+ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9, -+ 0x01ca, -+ 0x01cb}, -+ { -+ 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9, -+ 0x01ca, -+ 0x01cb}, -+ { -+ 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9, -+ 0x01c9, -+ 0x01ca}, -+ { -+ 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8, -+ 0x01c9, -+ 0x01ca}, -+ { -+ 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8, -+ 0x01c9, -+ 0x01c9}, -+ { -+ 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8, -+ 0x01c8, -+ 0x01c9}, -+ { -+ 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, -+ 0x01c8, -+ 0x01c9}, -+ { -+ 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, -+ 0x01c8, -+ 0x01c8}, -+ { -+ 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, -+ 0x01c7, -+ 0x01c8}, -+ { -+ 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, -+ 0x01c7, -+ 0x01c8}, -+ { -+ 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, -+ 0x01c6, -+ 0x01c7}, -+ { -+ 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, -+ 0x01c6, -+ 0x01c7}, -+ { -+ 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06, -+ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, -+ 0x01c6, -+ 0x01c6}, -+ { -+ 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, -+ 0x01c5, -+ 0x01c6}, -+ { -+ 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, -+ 0x01c5, -+ 0x01c6}, -+ { -+ 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, -+ 0x01c4, -+ 0x01c5}, -+ { -+ 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, -+ 0x01c4, -+ 0x01c5}, -+ { -+ 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, -+ 0x01c4, -+ 0x01c4}, -+ { -+ 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, -+ 0x01c3, -+ 0x01c4}, -+ { -+ 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, -+ 0x01c3, -+ 0x01c4}, -+ { -+ 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, -+ 0x01c2, -+ 0x01c3}, -+ { -+ 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, -+ 0x01c2, -+ 0x01c3}, -+ { -+ 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, -+ 0x01c2, -+ 0x01c2}, -+ { -+ 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05, -+ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, -+ 0x01c1, -+ 0x01c2}, -+ { -+ 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04, -+ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, -+ 0x01c0, -+ 0x01c1}, -+ { -+ 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04, -+ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, -+ 0x01bf, -+ 0x01c0}, -+ { -+ 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04, -+ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, -+ 0x01bf, -+ 0x01bf}, -+ { -+ 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03, -+ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, -+ 0x01be, -+ 0x01bf}, -+ { -+ 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03, -+ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, -+ 0x01bd, -+ 0x01be}, -+ { -+ 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03, -+ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, -+ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, -+ 0x01bc, -+ 0x01bd}, -+ { -+ 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f, -+ 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a, -+ 0x043f, -+ 0x0443}, -+ { -+ 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f, -+ 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438, -+ 0x043d, -+ 0x0441}, -+ { -+ 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f, -+ 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436, -+ 0x043a, -+ 0x043f}, -+ { -+ 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f, -+ 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434, -+ 0x0438, -+ 0x043d}, -+ { -+ 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f, -+ 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431, -+ 0x0436, -+ 0x043a}, -+ { -+ 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f, -+ 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f, -+ 0x0434, -+ 0x0438}, -+ { -+ 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f, -+ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d, -+ 0x0431, -+ 0x0436}, -+ { -+ 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f, -+ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b, -+ 0x042f, -+ 0x0434}, -+ { -+ 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f, -+ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429, -+ 0x042d, -+ 0x0431}, -+ { -+ 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f, -+ 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427, -+ 0x042b, -+ 0x042f}, -+ { -+ 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f, -+ 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424, -+ 0x0429, -+ 0x042d}, -+ { -+ 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f, -+ 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422, -+ 0x0427, -+ 0x042b}, -+ { -+ 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f, -+ 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420, -+ 0x0424, -+ 0x0429}, -+ { -+ 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f, -+ 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61, -+ 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b, -+ 0x041f, -+ 0x0424} -+}; -+ -+static struct radio_regs regs_2055[] = { -+ {0x02, 0x80, 0x80, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0x27, 0x27, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0x27, 0x27, 0, 0}, -+ {0x07, 0x7f, 0x7f, 1, 1}, -+ {0x08, 0x7, 0x7, 1, 1}, -+ {0x09, 0x7f, 0x7f, 1, 1}, -+ {0x0A, 0x7, 0x7, 1, 1}, -+ {0x0B, 0x15, 0x15, 0, 0}, -+ {0x0C, 0x15, 0x15, 0, 0}, -+ {0x0D, 0x4f, 0x4f, 1, 1}, -+ {0x0E, 0x5, 0x5, 1, 1}, -+ {0x0F, 0x4f, 0x4f, 1, 1}, -+ {0x10, 0x5, 0x5, 1, 1}, -+ {0x11, 0xd0, 0xd0, 0, 0}, -+ {0x12, 0x2, 0x2, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0x40, 0x40, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0xc0, 0xc0, 0, 0}, -+ {0x1E, 0xff, 0xff, 0, 0}, -+ {0x1F, 0xc0, 0xc0, 0, 0}, -+ {0x20, 0xff, 0xff, 0, 0}, -+ {0x21, 0xc0, 0xc0, 0, 0}, -+ {0x22, 0, 0, 0, 0}, -+ {0x23, 0x2c, 0x2c, 0, 0}, -+ {0x24, 0, 0, 0, 0}, -+ {0x25, 0, 0, 0, 0}, -+ {0x26, 0, 0, 0, 0}, -+ {0x27, 0, 0, 0, 0}, -+ {0x28, 0, 0, 0, 0}, -+ {0x29, 0, 0, 0, 0}, -+ {0x2A, 0, 0, 0, 0}, -+ {0x2B, 0, 0, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0xa4, 0xa4, 0, 0}, -+ {0x2E, 0x38, 0x38, 0, 0}, -+ {0x2F, 0, 0, 0, 0}, -+ {0x30, 0x4, 0x4, 1, 1}, -+ {0x31, 0, 0, 0, 0}, -+ {0x32, 0xa, 0xa, 0, 0}, -+ {0x33, 0x87, 0x87, 0, 0}, -+ {0x34, 0x9, 0x9, 0, 0}, -+ {0x35, 0x70, 0x70, 0, 0}, -+ {0x36, 0x11, 0x11, 0, 0}, -+ {0x37, 0x18, 0x18, 1, 1}, -+ {0x38, 0x6, 0x6, 0, 0}, -+ {0x39, 0x4, 0x4, 1, 1}, -+ {0x3A, 0x6, 0x6, 0, 0}, -+ {0x3B, 0x9e, 0x9e, 0, 0}, -+ {0x3C, 0x9, 0x9, 0, 0}, -+ {0x3D, 0xc8, 0xc8, 1, 1}, -+ {0x3E, 0x88, 0x88, 0, 0}, -+ {0x3F, 0, 0, 0, 0}, -+ {0x40, 0, 0, 0, 0}, -+ {0x41, 0, 0, 0, 0}, -+ {0x42, 0x1, 0x1, 0, 0}, -+ {0x43, 0x2, 0x2, 0, 0}, -+ {0x44, 0x96, 0x96, 0, 0}, -+ {0x45, 0x3e, 0x3e, 0, 0}, -+ {0x46, 0x3e, 0x3e, 0, 0}, -+ {0x47, 0x13, 0x13, 0, 0}, -+ {0x48, 0x2, 0x2, 0, 0}, -+ {0x49, 0x15, 0x15, 0, 0}, -+ {0x4A, 0x7, 0x7, 0, 0}, -+ {0x4B, 0, 0, 0, 0}, -+ {0x4C, 0, 0, 0, 0}, -+ {0x4D, 0, 0, 0, 0}, -+ {0x4E, 0, 0, 0, 0}, -+ {0x4F, 0, 0, 0, 0}, -+ {0x50, 0x8, 0x8, 0, 0}, -+ {0x51, 0x8, 0x8, 0, 0}, -+ {0x52, 0x6, 0x6, 0, 0}, -+ {0x53, 0x84, 0x84, 1, 1}, -+ {0x54, 0xc3, 0xc3, 0, 0}, -+ {0x55, 0x8f, 0x8f, 0, 0}, -+ {0x56, 0xff, 0xff, 0, 0}, -+ {0x57, 0xff, 0xff, 0, 0}, -+ {0x58, 0x88, 0x88, 0, 0}, -+ {0x59, 0x88, 0x88, 0, 0}, -+ {0x5A, 0, 0, 0, 0}, -+ {0x5B, 0xcc, 0xcc, 0, 0}, -+ {0x5C, 0x6, 0x6, 0, 0}, -+ {0x5D, 0x80, 0x80, 0, 0}, -+ {0x5E, 0x80, 0x80, 0, 0}, -+ {0x5F, 0xf8, 0xf8, 0, 0}, -+ {0x60, 0x88, 0x88, 0, 0}, -+ {0x61, 0x88, 0x88, 0, 0}, -+ {0x62, 0x88, 0x8, 1, 1}, -+ {0x63, 0x88, 0x88, 0, 0}, -+ {0x64, 0, 0, 0, 0}, -+ {0x65, 0x1, 0x1, 1, 1}, -+ {0x66, 0x8a, 0x8a, 0, 0}, -+ {0x67, 0x8, 0x8, 0, 0}, -+ {0x68, 0x83, 0x83, 0, 0}, -+ {0x69, 0x6, 0x6, 0, 0}, -+ {0x6A, 0xa0, 0xa0, 0, 0}, -+ {0x6B, 0xa, 0xa, 0, 0}, -+ {0x6C, 0x87, 0x87, 1, 1}, -+ {0x6D, 0x2a, 0x2a, 0, 0}, -+ {0x6E, 0x2a, 0x2a, 0, 0}, -+ {0x6F, 0x2a, 0x2a, 0, 0}, -+ {0x70, 0x2a, 0x2a, 0, 0}, -+ {0x71, 0x18, 0x18, 0, 0}, -+ {0x72, 0x6a, 0x6a, 1, 1}, -+ {0x73, 0xab, 0xab, 1, 1}, -+ {0x74, 0x13, 0x13, 1, 1}, -+ {0x75, 0xc1, 0xc1, 1, 1}, -+ {0x76, 0xaa, 0xaa, 1, 1}, -+ {0x77, 0x87, 0x87, 1, 1}, -+ {0x78, 0, 0, 0, 0}, -+ {0x79, 0x6, 0x6, 0, 0}, -+ {0x7A, 0x7, 0x7, 0, 0}, -+ {0x7B, 0x7, 0x7, 0, 0}, -+ {0x7C, 0x15, 0x15, 0, 0}, -+ {0x7D, 0x55, 0x55, 0, 0}, -+ {0x7E, 0x97, 0x97, 1, 1}, -+ {0x7F, 0x8, 0x8, 0, 0}, -+ {0x80, 0x14, 0x14, 1, 1}, -+ {0x81, 0x33, 0x33, 0, 0}, -+ {0x82, 0x88, 0x88, 0, 0}, -+ {0x83, 0x6, 0x6, 0, 0}, -+ {0x84, 0x3, 0x3, 1, 1}, -+ {0x85, 0xa, 0xa, 0, 0}, -+ {0x86, 0x3, 0x3, 1, 1}, -+ {0x87, 0x2a, 0x2a, 0, 0}, -+ {0x88, 0xa4, 0xa4, 0, 0}, -+ {0x89, 0x18, 0x18, 0, 0}, -+ {0x8A, 0x28, 0x28, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0x4a, 0x4a, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0xf8, 0xf8, 0, 0}, -+ {0x8F, 0x88, 0x88, 0, 0}, -+ {0x90, 0x88, 0x88, 0, 0}, -+ {0x91, 0x88, 0x8, 1, 1}, -+ {0x92, 0x88, 0x88, 0, 0}, -+ {0x93, 0, 0, 0, 0}, -+ {0x94, 0x1, 0x1, 1, 1}, -+ {0x95, 0x8a, 0x8a, 0, 0}, -+ {0x96, 0x8, 0x8, 0, 0}, -+ {0x97, 0x83, 0x83, 0, 0}, -+ {0x98, 0x6, 0x6, 0, 0}, -+ {0x99, 0xa0, 0xa0, 0, 0}, -+ {0x9A, 0xa, 0xa, 0, 0}, -+ {0x9B, 0x87, 0x87, 1, 1}, -+ {0x9C, 0x2a, 0x2a, 0, 0}, -+ {0x9D, 0x2a, 0x2a, 0, 0}, -+ {0x9E, 0x2a, 0x2a, 0, 0}, -+ {0x9F, 0x2a, 0x2a, 0, 0}, -+ {0xA0, 0x18, 0x18, 0, 0}, -+ {0xA1, 0x6a, 0x6a, 1, 1}, -+ {0xA2, 0xab, 0xab, 1, 1}, -+ {0xA3, 0x13, 0x13, 1, 1}, -+ {0xA4, 0xc1, 0xc1, 1, 1}, -+ {0xA5, 0xaa, 0xaa, 1, 1}, -+ {0xA6, 0x87, 0x87, 1, 1}, -+ {0xA7, 0, 0, 0, 0}, -+ {0xA8, 0x6, 0x6, 0, 0}, -+ {0xA9, 0x7, 0x7, 0, 0}, -+ {0xAA, 0x7, 0x7, 0, 0}, -+ {0xAB, 0x15, 0x15, 0, 0}, -+ {0xAC, 0x55, 0x55, 0, 0}, -+ {0xAD, 0x97, 0x97, 1, 1}, -+ {0xAE, 0x8, 0x8, 0, 0}, -+ {0xAF, 0x14, 0x14, 1, 1}, -+ {0xB0, 0x33, 0x33, 0, 0}, -+ {0xB1, 0x88, 0x88, 0, 0}, -+ {0xB2, 0x6, 0x6, 0, 0}, -+ {0xB3, 0x3, 0x3, 1, 1}, -+ {0xB4, 0xa, 0xa, 0, 0}, -+ {0xB5, 0x3, 0x3, 1, 1}, -+ {0xB6, 0x2a, 0x2a, 0, 0}, -+ {0xB7, 0xa4, 0xa4, 0, 0}, -+ {0xB8, 0x18, 0x18, 0, 0}, -+ {0xB9, 0x28, 0x28, 0, 0}, -+ {0xBA, 0, 0, 0, 0}, -+ {0xBB, 0x4a, 0x4a, 0, 0}, -+ {0xBC, 0, 0, 0, 0}, -+ {0xBD, 0x71, 0x71, 0, 0}, -+ {0xBE, 0x72, 0x72, 0, 0}, -+ {0xBF, 0x73, 0x73, 0, 0}, -+ {0xC0, 0x74, 0x74, 0, 0}, -+ {0xC1, 0x75, 0x75, 0, 0}, -+ {0xC2, 0x76, 0x76, 0, 0}, -+ {0xC3, 0x77, 0x77, 0, 0}, -+ {0xC4, 0x78, 0x78, 0, 0}, -+ {0xC5, 0x79, 0x79, 0, 0}, -+ {0xC6, 0x7a, 0x7a, 0, 0}, -+ {0xC7, 0, 0, 0, 0}, -+ {0xC8, 0, 0, 0, 0}, -+ {0xC9, 0, 0, 0, 0}, -+ {0xCA, 0, 0, 0, 0}, -+ {0xCB, 0, 0, 0, 0}, -+ {0xCC, 0, 0, 0, 0}, -+ {0xCD, 0, 0, 0, 0}, -+ {0xCE, 0x6, 0x6, 0, 0}, -+ {0xCF, 0, 0, 0, 0}, -+ {0xD0, 0, 0, 0, 0}, -+ {0xD1, 0x18, 0x18, 0, 0}, -+ {0xD2, 0x88, 0x88, 0, 0}, -+ {0xD3, 0, 0, 0, 0}, -+ {0xD4, 0, 0, 0, 0}, -+ {0xD5, 0, 0, 0, 0}, -+ {0xD6, 0, 0, 0, 0}, -+ {0xD7, 0, 0, 0, 0}, -+ {0xD8, 0, 0, 0, 0}, -+ {0xD9, 0, 0, 0, 0}, -+ {0xDA, 0x6, 0x6, 0, 0}, -+ {0xDB, 0, 0, 0, 0}, -+ {0xDC, 0, 0, 0, 0}, -+ {0xDD, 0x18, 0x18, 0, 0}, -+ {0xDE, 0x88, 0x88, 0, 0}, -+ {0xDF, 0, 0, 0, 0}, -+ {0xE0, 0, 0, 0, 0}, -+ {0xE1, 0, 0, 0, 0}, -+ {0xE2, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0}, -+}; -+ -+static struct radio_regs regs_SYN_2056[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0x1, 0x1, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0, 0, 0, 0}, -+ {0x21, 0, 0, 0, 0}, -+ {0x22, 0x60, 0x60, 0, 0}, -+ {0x23, 0x6, 0x6, 0, 0}, -+ {0x24, 0xc, 0xc, 0, 0}, -+ {0x25, 0, 0, 0, 0}, -+ {0x26, 0, 0, 0, 0}, -+ {0x27, 0, 0, 0, 0}, -+ {0x28, 0x1, 0x1, 0, 0}, -+ {0x29, 0, 0, 0, 0}, -+ {0x2A, 0, 0, 0, 0}, -+ {0x2B, 0, 0, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0, 0, 0, 0}, -+ {0x2E, 0xd, 0xd, 0, 0}, -+ {0x2F, 0x1f, 0x1f, 0, 0}, -+ {0x30, 0x15, 0x15, 0, 0}, -+ {0x31, 0xf, 0xf, 0, 0}, -+ {0x32, 0, 0, 0, 0}, -+ {0x33, 0, 0, 0, 0}, -+ {0x34, 0, 0, 0, 0}, -+ {0x35, 0, 0, 0, 0}, -+ {0x36, 0, 0, 0, 0}, -+ {0x37, 0, 0, 0, 0}, -+ {0x38, 0, 0, 0, 0}, -+ {0x39, 0, 0, 0, 0}, -+ {0x3A, 0, 0, 0, 0}, -+ {0x3B, 0, 0, 0, 0}, -+ {0x3C, 0x13, 0x13, 0, 0}, -+ {0x3D, 0xf, 0xf, 0, 0}, -+ {0x3E, 0x18, 0x18, 0, 0}, -+ {0x3F, 0, 0, 0, 0}, -+ {0x40, 0, 0, 0, 0}, -+ {0x41, 0x20, 0x20, 0, 0}, -+ {0x42, 0x20, 0x20, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x77, 0x77, 0, 0}, -+ {0x45, 0x7, 0x7, 0, 0}, -+ {0x46, 0x1, 0x1, 0, 0}, -+ {0x47, 0x4, 0x4, 0, 0}, -+ {0x48, 0xf, 0xf, 0, 0}, -+ {0x49, 0x30, 0x30, 0, 0}, -+ {0x4A, 0x32, 0x32, 0, 0}, -+ {0x4B, 0xd, 0xd, 0, 0}, -+ {0x4C, 0xd, 0xd, 0, 0}, -+ {0x4D, 0x4, 0x4, 0, 0}, -+ {0x4E, 0x6, 0x6, 0, 0}, -+ {0x4F, 0x1, 0x1, 0, 0}, -+ {0x50, 0x1c, 0x1c, 0, 0}, -+ {0x51, 0x2, 0x2, 0, 0}, -+ {0x52, 0x2, 0x2, 0, 0}, -+ {0x53, 0xf7, 0xf7, 1, 1}, -+ {0x54, 0xb4, 0xb4, 0, 0}, -+ {0x55, 0xd2, 0xd2, 0, 0}, -+ {0x56, 0, 0, 0, 0}, -+ {0x57, 0, 0, 0, 0}, -+ {0x58, 0x4, 0x4, 0, 0}, -+ {0x59, 0x96, 0x96, 0, 0}, -+ {0x5A, 0x3e, 0x3e, 0, 0}, -+ {0x5B, 0x3e, 0x3e, 0, 0}, -+ {0x5C, 0x13, 0x13, 0, 0}, -+ {0x5D, 0x2, 0x2, 0, 0}, -+ {0x5E, 0, 0, 0, 0}, -+ {0x5F, 0x7, 0x7, 0, 0}, -+ {0x60, 0x7, 0x7, 1, 1}, -+ {0x61, 0x8, 0x8, 0, 0}, -+ {0x62, 0x3, 0x3, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0, 0, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 0, 0}, -+ {0x68, 0x40, 0x40, 0, 0}, -+ {0x69, 0, 0, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0, 0, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0x1, 0x1, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0x60, 0x60, 0, 0}, -+ {0x71, 0x66, 0x66, 0, 0}, -+ {0x72, 0xc, 0xc, 0, 0}, -+ {0x73, 0x66, 0x66, 0, 0}, -+ {0x74, 0x8f, 0x8f, 1, 1}, -+ {0x75, 0, 0, 0, 0}, -+ {0x76, 0xcc, 0xcc, 0, 0}, -+ {0x77, 0x1, 0x1, 0, 0}, -+ {0x78, 0x66, 0x66, 0, 0}, -+ {0x79, 0x66, 0x66, 0, 0}, -+ {0x7A, 0, 0, 0, 0}, -+ {0x7B, 0, 0, 0, 0}, -+ {0x7C, 0, 0, 0, 0}, -+ {0x7D, 0, 0, 0, 0}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0xff, 0xff, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0, 0, 0, 0}, -+ {0x94, 0, 0, 0, 0}, -+ {0x95, 0, 0, 0, 0}, -+ {0x96, 0, 0, 0, 0}, -+ {0x97, 0, 0, 0, 0}, -+ {0x98, 0, 0, 0, 0}, -+ {0x99, 0, 0, 0, 0}, -+ {0x9A, 0, 0, 0, 0}, -+ {0x9B, 0, 0, 0, 0}, -+ {0x9C, 0, 0, 0, 0}, -+ {0x9D, 0, 0, 0, 0}, -+ {0x9E, 0, 0, 0, 0}, -+ {0x9F, 0x6, 0x6, 0, 0}, -+ {0xA0, 0x66, 0x66, 0, 0}, -+ {0xA1, 0x66, 0x66, 0, 0}, -+ {0xA2, 0x66, 0x66, 0, 0}, -+ {0xA3, 0x66, 0x66, 0, 0}, -+ {0xA4, 0x66, 0x66, 0, 0}, -+ {0xA5, 0x66, 0x66, 0, 0}, -+ {0xA6, 0x66, 0x66, 0, 0}, -+ {0xA7, 0x66, 0x66, 0, 0}, -+ {0xA8, 0x66, 0x66, 0, 0}, -+ {0xA9, 0x66, 0x66, 0, 0}, -+ {0xAA, 0x66, 0x66, 0, 0}, -+ {0xAB, 0x66, 0x66, 0, 0}, -+ {0xAC, 0x66, 0x66, 0, 0}, -+ {0xAD, 0x66, 0x66, 0, 0}, -+ {0xAE, 0x66, 0x66, 0, 0}, -+ {0xAF, 0x66, 0x66, 0, 0}, -+ {0xB0, 0x66, 0x66, 0, 0}, -+ {0xB1, 0x66, 0x66, 0, 0}, -+ {0xB2, 0x66, 0x66, 0, 0}, -+ {0xB3, 0xa, 0xa, 0, 0}, -+ {0xB4, 0, 0, 0, 0}, -+ {0xB5, 0, 0, 0, 0}, -+ {0xB6, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0} -+}; -+ -+static struct radio_regs regs_TX_2056[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0, 0, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0, 0, 0, 0}, -+ {0x21, 0x88, 0x88, 0, 0}, -+ {0x22, 0x88, 0x88, 0, 0}, -+ {0x23, 0x88, 0x88, 0, 0}, -+ {0x24, 0x88, 0x88, 0, 0}, -+ {0x25, 0xc, 0xc, 0, 0}, -+ {0x26, 0, 0, 0, 0}, -+ {0x27, 0x3, 0x3, 0, 0}, -+ {0x28, 0, 0, 0, 0}, -+ {0x29, 0x3, 0x3, 0, 0}, -+ {0x2A, 0x37, 0x37, 0, 0}, -+ {0x2B, 0x3, 0x3, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0, 0, 0, 0}, -+ {0x2E, 0x1, 0x1, 0, 0}, -+ {0x2F, 0x1, 0x1, 0, 0}, -+ {0x30, 0, 0, 0, 0}, -+ {0x31, 0, 0, 0, 0}, -+ {0x32, 0, 0, 0, 0}, -+ {0x33, 0x11, 0x11, 0, 0}, -+ {0x34, 0x11, 0x11, 0, 0}, -+ {0x35, 0, 0, 0, 0}, -+ {0x36, 0, 0, 0, 0}, -+ {0x37, 0x3, 0x3, 0, 0}, -+ {0x38, 0xf, 0xf, 0, 0}, -+ {0x39, 0, 0, 0, 0}, -+ {0x3A, 0x2d, 0x2d, 0, 0}, -+ {0x3B, 0, 0, 0, 0}, -+ {0x3C, 0x6e, 0x6e, 0, 0}, -+ {0x3D, 0xf0, 0xf0, 1, 1}, -+ {0x3E, 0, 0, 0, 0}, -+ {0x3F, 0, 0, 0, 0}, -+ {0x40, 0, 0, 0, 0}, -+ {0x41, 0x3, 0x3, 0, 0}, -+ {0x42, 0x3, 0x3, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x1e, 0x1e, 0, 0}, -+ {0x45, 0, 0, 0, 0}, -+ {0x46, 0x6e, 0x6e, 0, 0}, -+ {0x47, 0xf0, 0xf0, 1, 1}, -+ {0x48, 0, 0, 0, 0}, -+ {0x49, 0x2, 0x2, 0, 0}, -+ {0x4A, 0xff, 0xff, 1, 1}, -+ {0x4B, 0xc, 0xc, 0, 0}, -+ {0x4C, 0, 0, 0, 0}, -+ {0x4D, 0x38, 0x38, 0, 0}, -+ {0x4E, 0x70, 0x70, 1, 1}, -+ {0x4F, 0x2, 0x2, 0, 0}, -+ {0x50, 0x88, 0x88, 0, 0}, -+ {0x51, 0xc, 0xc, 0, 0}, -+ {0x52, 0, 0, 0, 0}, -+ {0x53, 0x8, 0x8, 0, 0}, -+ {0x54, 0x70, 0x70, 1, 1}, -+ {0x55, 0x2, 0x2, 0, 0}, -+ {0x56, 0xff, 0xff, 1, 1}, -+ {0x57, 0, 0, 0, 0}, -+ {0x58, 0x83, 0x83, 0, 0}, -+ {0x59, 0x77, 0x77, 1, 1}, -+ {0x5A, 0, 0, 0, 0}, -+ {0x5B, 0x2, 0x2, 0, 0}, -+ {0x5C, 0x88, 0x88, 0, 0}, -+ {0x5D, 0, 0, 0, 0}, -+ {0x5E, 0x8, 0x8, 0, 0}, -+ {0x5F, 0x77, 0x77, 1, 1}, -+ {0x60, 0x1, 0x1, 0, 0}, -+ {0x61, 0, 0, 0, 0}, -+ {0x62, 0x7, 0x7, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0x7, 0x7, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0x74, 0x74, 1, 1}, -+ {0x68, 0, 0, 0, 0}, -+ {0x69, 0xa, 0xa, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0, 0, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0, 0, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0, 0, 0, 0}, -+ {0x71, 0x2, 0x2, 0, 0}, -+ {0x72, 0, 0, 0, 0}, -+ {0x73, 0, 0, 0, 0}, -+ {0x74, 0xe, 0xe, 0, 0}, -+ {0x75, 0xe, 0xe, 0, 0}, -+ {0x76, 0xe, 0xe, 0, 0}, -+ {0x77, 0x13, 0x13, 0, 0}, -+ {0x78, 0x13, 0x13, 0, 0}, -+ {0x79, 0x1b, 0x1b, 0, 0}, -+ {0x7A, 0x1b, 0x1b, 0, 0}, -+ {0x7B, 0x55, 0x55, 0, 0}, -+ {0x7C, 0x5b, 0x5b, 0, 0}, -+ {0x7D, 0, 0, 0, 0}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0, 0, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0} -+}; -+ -+static struct radio_regs regs_RX_2056[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0, 0, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0x3, 0x3, 0, 0}, -+ {0x21, 0, 0, 0, 0}, -+ {0x22, 0, 0, 0, 0}, -+ {0x23, 0x90, 0x90, 0, 0}, -+ {0x24, 0x55, 0x55, 0, 0}, -+ {0x25, 0x15, 0x15, 0, 0}, -+ {0x26, 0x5, 0x5, 0, 0}, -+ {0x27, 0x15, 0x15, 0, 0}, -+ {0x28, 0x5, 0x5, 0, 0}, -+ {0x29, 0x20, 0x20, 0, 0}, -+ {0x2A, 0x11, 0x11, 0, 0}, -+ {0x2B, 0x90, 0x90, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0x88, 0x88, 0, 0}, -+ {0x2E, 0x32, 0x32, 0, 0}, -+ {0x2F, 0x77, 0x77, 0, 0}, -+ {0x30, 0x17, 0x17, 1, 1}, -+ {0x31, 0xff, 0xff, 1, 1}, -+ {0x32, 0x20, 0x20, 0, 0}, -+ {0x33, 0, 0, 0, 0}, -+ {0x34, 0x88, 0x88, 0, 0}, -+ {0x35, 0x32, 0x32, 0, 0}, -+ {0x36, 0x77, 0x77, 0, 0}, -+ {0x37, 0x17, 0x17, 1, 1}, -+ {0x38, 0xf0, 0xf0, 1, 1}, -+ {0x39, 0x20, 0x20, 0, 0}, -+ {0x3A, 0x8, 0x8, 0, 0}, -+ {0x3B, 0x99, 0x99, 0, 0}, -+ {0x3C, 0, 0, 0, 0}, -+ {0x3D, 0x44, 0x44, 1, 1}, -+ {0x3E, 0, 0, 0, 0}, -+ {0x3F, 0x44, 0x44, 0, 0}, -+ {0x40, 0xf, 0xf, 1, 1}, -+ {0x41, 0x6, 0x6, 0, 0}, -+ {0x42, 0x4, 0x4, 0, 0}, -+ {0x43, 0x50, 0x50, 1, 1}, -+ {0x44, 0x8, 0x8, 0, 0}, -+ {0x45, 0x99, 0x99, 0, 0}, -+ {0x46, 0, 0, 0, 0}, -+ {0x47, 0x11, 0x11, 0, 0}, -+ {0x48, 0, 0, 0, 0}, -+ {0x49, 0x44, 0x44, 0, 0}, -+ {0x4A, 0x7, 0x7, 0, 0}, -+ {0x4B, 0x6, 0x6, 0, 0}, -+ {0x4C, 0x4, 0x4, 0, 0}, -+ {0x4D, 0, 0, 0, 0}, -+ {0x4E, 0, 0, 0, 0}, -+ {0x4F, 0x66, 0x66, 0, 0}, -+ {0x50, 0x66, 0x66, 0, 0}, -+ {0x51, 0x57, 0x57, 0, 0}, -+ {0x52, 0x57, 0x57, 0, 0}, -+ {0x53, 0x44, 0x44, 0, 0}, -+ {0x54, 0, 0, 0, 0}, -+ {0x55, 0, 0, 0, 0}, -+ {0x56, 0x8, 0x8, 0, 0}, -+ {0x57, 0x8, 0x8, 0, 0}, -+ {0x58, 0x7, 0x7, 0, 0}, -+ {0x59, 0x22, 0x22, 0, 0}, -+ {0x5A, 0x22, 0x22, 0, 0}, -+ {0x5B, 0x2, 0x2, 0, 0}, -+ {0x5C, 0x23, 0x23, 0, 0}, -+ {0x5D, 0x7, 0x7, 0, 0}, -+ {0x5E, 0x55, 0x55, 0, 0}, -+ {0x5F, 0x23, 0x23, 0, 0}, -+ {0x60, 0x41, 0x41, 0, 0}, -+ {0x61, 0x1, 0x1, 0, 0}, -+ {0x62, 0xa, 0xa, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0, 0, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 0, 0}, -+ {0x68, 0, 0, 0, 0}, -+ {0x69, 0, 0, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0xc, 0xc, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0, 0, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0, 0, 0, 0}, -+ {0x71, 0, 0, 0, 0}, -+ {0x72, 0x22, 0x22, 0, 0}, -+ {0x73, 0x22, 0x22, 0, 0}, -+ {0x74, 0x2, 0x2, 0, 0}, -+ {0x75, 0xa, 0xa, 0, 0}, -+ {0x76, 0x1, 0x1, 0, 0}, -+ {0x77, 0x22, 0x22, 0, 0}, -+ {0x78, 0x30, 0x30, 0, 0}, -+ {0x79, 0, 0, 0, 0}, -+ {0x7A, 0, 0, 0, 0}, -+ {0x7B, 0, 0, 0, 0}, -+ {0x7C, 0, 0, 0, 0}, -+ {0x7D, 0, 0, 0, 0}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0, 0, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0, 0, 0, 0}, -+ {0x94, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0} -+}; -+ -+static struct radio_regs regs_SYN_2056_A1[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0x1, 0x1, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0, 0, 0, 0}, -+ {0x21, 0, 0, 0, 0}, -+ {0x22, 0x60, 0x60, 0, 0}, -+ {0x23, 0x6, 0x6, 0, 0}, -+ {0x24, 0xc, 0xc, 0, 0}, -+ {0x25, 0, 0, 0, 0}, -+ {0x26, 0, 0, 0, 0}, -+ {0x27, 0, 0, 0, 0}, -+ {0x28, 0x1, 0x1, 0, 0}, -+ {0x29, 0, 0, 0, 0}, -+ {0x2A, 0, 0, 0, 0}, -+ {0x2B, 0, 0, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0, 0, 0, 0}, -+ {0x2E, 0xd, 0xd, 0, 0}, -+ {0x2F, 0x1f, 0x1f, 0, 0}, -+ {0x30, 0x15, 0x15, 0, 0}, -+ {0x31, 0xf, 0xf, 0, 0}, -+ {0x32, 0, 0, 0, 0}, -+ {0x33, 0, 0, 0, 0}, -+ {0x34, 0, 0, 0, 0}, -+ {0x35, 0, 0, 0, 0}, -+ {0x36, 0, 0, 0, 0}, -+ {0x37, 0, 0, 0, 0}, -+ {0x38, 0, 0, 0, 0}, -+ {0x39, 0, 0, 0, 0}, -+ {0x3A, 0, 0, 0, 0}, -+ {0x3B, 0, 0, 0, 0}, -+ {0x3C, 0x13, 0x13, 0, 0}, -+ {0x3D, 0xf, 0xf, 0, 0}, -+ {0x3E, 0x18, 0x18, 0, 0}, -+ {0x3F, 0, 0, 0, 0}, -+ {0x40, 0, 0, 0, 0}, -+ {0x41, 0x20, 0x20, 0, 0}, -+ {0x42, 0x20, 0x20, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x77, 0x77, 0, 0}, -+ {0x45, 0x7, 0x7, 0, 0}, -+ {0x46, 0x1, 0x1, 0, 0}, -+ {0x47, 0x4, 0x4, 0, 0}, -+ {0x48, 0xf, 0xf, 0, 0}, -+ {0x49, 0x30, 0x30, 0, 0}, -+ {0x4A, 0x32, 0x32, 0, 0}, -+ {0x4B, 0xd, 0xd, 0, 0}, -+ {0x4C, 0xd, 0xd, 0, 0}, -+ {0x4D, 0x4, 0x4, 0, 0}, -+ {0x4E, 0x6, 0x6, 0, 0}, -+ {0x4F, 0x1, 0x1, 0, 0}, -+ {0x50, 0x1c, 0x1c, 0, 0}, -+ {0x51, 0x2, 0x2, 0, 0}, -+ {0x52, 0x2, 0x2, 0, 0}, -+ {0x53, 0xf7, 0xf7, 1, 1}, -+ {0x54, 0xb4, 0xb4, 0, 0}, -+ {0x55, 0xd2, 0xd2, 0, 0}, -+ {0x56, 0, 0, 0, 0}, -+ {0x57, 0, 0, 0, 0}, -+ {0x58, 0x4, 0x4, 0, 0}, -+ {0x59, 0x96, 0x96, 0, 0}, -+ {0x5A, 0x3e, 0x3e, 0, 0}, -+ {0x5B, 0x3e, 0x3e, 0, 0}, -+ {0x5C, 0x13, 0x13, 0, 0}, -+ {0x5D, 0x2, 0x2, 0, 0}, -+ {0x5E, 0, 0, 0, 0}, -+ {0x5F, 0x7, 0x7, 0, 0}, -+ {0x60, 0x7, 0x7, 1, 1}, -+ {0x61, 0x8, 0x8, 0, 0}, -+ {0x62, 0x3, 0x3, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0, 0, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 0, 0}, -+ {0x68, 0x40, 0x40, 0, 0}, -+ {0x69, 0, 0, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0, 0, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0x1, 0x1, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0x60, 0x60, 0, 0}, -+ {0x71, 0x66, 0x66, 0, 0}, -+ {0x72, 0xc, 0xc, 0, 0}, -+ {0x73, 0x66, 0x66, 0, 0}, -+ {0x74, 0x8f, 0x8f, 1, 1}, -+ {0x75, 0, 0, 0, 0}, -+ {0x76, 0xcc, 0xcc, 0, 0}, -+ {0x77, 0x1, 0x1, 0, 0}, -+ {0x78, 0x66, 0x66, 0, 0}, -+ {0x79, 0x66, 0x66, 0, 0}, -+ {0x7A, 0, 0, 0, 0}, -+ {0x7B, 0, 0, 0, 0}, -+ {0x7C, 0, 0, 0, 0}, -+ {0x7D, 0, 0, 0, 0}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0xff, 0xff, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0, 0, 0, 0}, -+ {0x94, 0, 0, 0, 0}, -+ {0x95, 0, 0, 0, 0}, -+ {0x96, 0, 0, 0, 0}, -+ {0x97, 0, 0, 0, 0}, -+ {0x98, 0, 0, 0, 0}, -+ {0x99, 0, 0, 0, 0}, -+ {0x9A, 0, 0, 0, 0}, -+ {0x9B, 0, 0, 0, 0}, -+ {0x9C, 0, 0, 0, 0}, -+ {0x9D, 0, 0, 0, 0}, -+ {0x9E, 0, 0, 0, 0}, -+ {0x9F, 0x6, 0x6, 0, 0}, -+ {0xA0, 0x66, 0x66, 0, 0}, -+ {0xA1, 0x66, 0x66, 0, 0}, -+ {0xA2, 0x66, 0x66, 0, 0}, -+ {0xA3, 0x66, 0x66, 0, 0}, -+ {0xA4, 0x66, 0x66, 0, 0}, -+ {0xA5, 0x66, 0x66, 0, 0}, -+ {0xA6, 0x66, 0x66, 0, 0}, -+ {0xA7, 0x66, 0x66, 0, 0}, -+ {0xA8, 0x66, 0x66, 0, 0}, -+ {0xA9, 0x66, 0x66, 0, 0}, -+ {0xAA, 0x66, 0x66, 0, 0}, -+ {0xAB, 0x66, 0x66, 0, 0}, -+ {0xAC, 0x66, 0x66, 0, 0}, -+ {0xAD, 0x66, 0x66, 0, 0}, -+ {0xAE, 0x66, 0x66, 0, 0}, -+ {0xAF, 0x66, 0x66, 0, 0}, -+ {0xB0, 0x66, 0x66, 0, 0}, -+ {0xB1, 0x66, 0x66, 0, 0}, -+ {0xB2, 0x66, 0x66, 0, 0}, -+ {0xB3, 0xa, 0xa, 0, 0}, -+ {0xB4, 0, 0, 0, 0}, -+ {0xB5, 0, 0, 0, 0}, -+ {0xB6, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0} -+}; -+ -+static struct radio_regs regs_TX_2056_A1[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0, 0, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0, 0, 0, 0}, -+ {0x21, 0x88, 0x88, 0, 0}, -+ {0x22, 0x88, 0x88, 0, 0}, -+ {0x23, 0x88, 0x88, 0, 0}, -+ {0x24, 0x88, 0x88, 0, 0}, -+ {0x25, 0xc, 0xc, 0, 0}, -+ {0x26, 0, 0, 0, 0}, -+ {0x27, 0x3, 0x3, 0, 0}, -+ {0x28, 0, 0, 0, 0}, -+ {0x29, 0x3, 0x3, 0, 0}, -+ {0x2A, 0x37, 0x37, 0, 0}, -+ {0x2B, 0x3, 0x3, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0, 0, 0, 0}, -+ {0x2E, 0x1, 0x1, 0, 0}, -+ {0x2F, 0x1, 0x1, 0, 0}, -+ {0x30, 0, 0, 0, 0}, -+ {0x31, 0, 0, 0, 0}, -+ {0x32, 0, 0, 0, 0}, -+ {0x33, 0x11, 0x11, 0, 0}, -+ {0x34, 0x11, 0x11, 0, 0}, -+ {0x35, 0, 0, 0, 0}, -+ {0x36, 0, 0, 0, 0}, -+ {0x37, 0x3, 0x3, 0, 0}, -+ {0x38, 0xf, 0xf, 0, 0}, -+ {0x39, 0, 0, 0, 0}, -+ {0x3A, 0x2d, 0x2d, 0, 0}, -+ {0x3B, 0, 0, 0, 0}, -+ {0x3C, 0x6e, 0x6e, 0, 0}, -+ {0x3D, 0xf0, 0xf0, 1, 1}, -+ {0x3E, 0, 0, 0, 0}, -+ {0x3F, 0, 0, 0, 0}, -+ {0x40, 0, 0, 0, 0}, -+ {0x41, 0x3, 0x3, 0, 0}, -+ {0x42, 0x3, 0x3, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x1e, 0x1e, 0, 0}, -+ {0x45, 0, 0, 0, 0}, -+ {0x46, 0x6e, 0x6e, 0, 0}, -+ {0x47, 0xf0, 0xf0, 1, 1}, -+ {0x48, 0, 0, 0, 0}, -+ {0x49, 0x2, 0x2, 0, 0}, -+ {0x4A, 0xff, 0xff, 1, 1}, -+ {0x4B, 0xc, 0xc, 0, 0}, -+ {0x4C, 0, 0, 0, 0}, -+ {0x4D, 0x38, 0x38, 0, 0}, -+ {0x4E, 0x70, 0x70, 1, 1}, -+ {0x4F, 0x2, 0x2, 0, 0}, -+ {0x50, 0x88, 0x88, 0, 0}, -+ {0x51, 0xc, 0xc, 0, 0}, -+ {0x52, 0, 0, 0, 0}, -+ {0x53, 0x8, 0x8, 0, 0}, -+ {0x54, 0x70, 0x70, 1, 1}, -+ {0x55, 0x2, 0x2, 0, 0}, -+ {0x56, 0xff, 0xff, 1, 1}, -+ {0x57, 0, 0, 0, 0}, -+ {0x58, 0x83, 0x83, 0, 0}, -+ {0x59, 0x77, 0x77, 1, 1}, -+ {0x5A, 0, 0, 0, 0}, -+ {0x5B, 0x2, 0x2, 0, 0}, -+ {0x5C, 0x88, 0x88, 0, 0}, -+ {0x5D, 0, 0, 0, 0}, -+ {0x5E, 0x8, 0x8, 0, 0}, -+ {0x5F, 0x77, 0x77, 1, 1}, -+ {0x60, 0x1, 0x1, 0, 0}, -+ {0x61, 0, 0, 0, 0}, -+ {0x62, 0x7, 0x7, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0x7, 0x7, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0x72, 0x72, 1, 1}, -+ {0x68, 0, 0, 0, 0}, -+ {0x69, 0xa, 0xa, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0, 0, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0, 0, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0, 0, 0, 0}, -+ {0x71, 0x2, 0x2, 0, 0}, -+ {0x72, 0, 0, 0, 0}, -+ {0x73, 0, 0, 0, 0}, -+ {0x74, 0xe, 0xe, 0, 0}, -+ {0x75, 0xe, 0xe, 0, 0}, -+ {0x76, 0xe, 0xe, 0, 0}, -+ {0x77, 0x13, 0x13, 0, 0}, -+ {0x78, 0x13, 0x13, 0, 0}, -+ {0x79, 0x1b, 0x1b, 0, 0}, -+ {0x7A, 0x1b, 0x1b, 0, 0}, -+ {0x7B, 0x55, 0x55, 0, 0}, -+ {0x7C, 0x5b, 0x5b, 0, 0}, -+ {0x7D, 0, 0, 0, 0}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0, 0, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0} -+}; -+ -+static struct radio_regs regs_RX_2056_A1[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0, 0, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0x3, 0x3, 0, 0}, -+ {0x21, 0, 0, 0, 0}, -+ {0x22, 0, 0, 0, 0}, -+ {0x23, 0x90, 0x90, 0, 0}, -+ {0x24, 0x55, 0x55, 0, 0}, -+ {0x25, 0x15, 0x15, 0, 0}, -+ {0x26, 0x5, 0x5, 0, 0}, -+ {0x27, 0x15, 0x15, 0, 0}, -+ {0x28, 0x5, 0x5, 0, 0}, -+ {0x29, 0x20, 0x20, 0, 0}, -+ {0x2A, 0x11, 0x11, 0, 0}, -+ {0x2B, 0x90, 0x90, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0x88, 0x88, 0, 0}, -+ {0x2E, 0x32, 0x32, 0, 0}, -+ {0x2F, 0x77, 0x77, 0, 0}, -+ {0x30, 0x17, 0x17, 1, 1}, -+ {0x31, 0xff, 0xff, 1, 1}, -+ {0x32, 0x20, 0x20, 0, 0}, -+ {0x33, 0, 0, 0, 0}, -+ {0x34, 0x88, 0x88, 0, 0}, -+ {0x35, 0x32, 0x32, 0, 0}, -+ {0x36, 0x77, 0x77, 0, 0}, -+ {0x37, 0x17, 0x17, 1, 1}, -+ {0x38, 0xf0, 0xf0, 1, 1}, -+ {0x39, 0x20, 0x20, 0, 0}, -+ {0x3A, 0x8, 0x8, 0, 0}, -+ {0x3B, 0x55, 0x55, 1, 1}, -+ {0x3C, 0, 0, 0, 0}, -+ {0x3D, 0x44, 0x44, 1, 1}, -+ {0x3E, 0, 0, 0, 0}, -+ {0x3F, 0x44, 0x44, 0, 0}, -+ {0x40, 0xf, 0xf, 1, 1}, -+ {0x41, 0x6, 0x6, 0, 0}, -+ {0x42, 0x4, 0x4, 0, 0}, -+ {0x43, 0x50, 0x50, 1, 1}, -+ {0x44, 0x8, 0x8, 0, 0}, -+ {0x45, 0x55, 0x55, 1, 1}, -+ {0x46, 0, 0, 0, 0}, -+ {0x47, 0x11, 0x11, 0, 0}, -+ {0x48, 0, 0, 0, 0}, -+ {0x49, 0x44, 0x44, 0, 0}, -+ {0x4A, 0x7, 0x7, 0, 0}, -+ {0x4B, 0x6, 0x6, 0, 0}, -+ {0x4C, 0x4, 0x4, 0, 0}, -+ {0x4D, 0, 0, 0, 0}, -+ {0x4E, 0, 0, 0, 0}, -+ {0x4F, 0x26, 0x26, 1, 1}, -+ {0x50, 0x26, 0x26, 1, 1}, -+ {0x51, 0xf, 0xf, 1, 1}, -+ {0x52, 0xf, 0xf, 1, 1}, -+ {0x53, 0x44, 0x44, 0, 0}, -+ {0x54, 0, 0, 0, 0}, -+ {0x55, 0, 0, 0, 0}, -+ {0x56, 0x8, 0x8, 0, 0}, -+ {0x57, 0x8, 0x8, 0, 0}, -+ {0x58, 0x7, 0x7, 0, 0}, -+ {0x59, 0x22, 0x22, 0, 0}, -+ {0x5A, 0x22, 0x22, 0, 0}, -+ {0x5B, 0x2, 0x2, 0, 0}, -+ {0x5C, 0x2f, 0x2f, 1, 1}, -+ {0x5D, 0x7, 0x7, 0, 0}, -+ {0x5E, 0x55, 0x55, 0, 0}, -+ {0x5F, 0x23, 0x23, 0, 0}, -+ {0x60, 0x41, 0x41, 0, 0}, -+ {0x61, 0x1, 0x1, 0, 0}, -+ {0x62, 0xa, 0xa, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0, 0, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 0, 0}, -+ {0x68, 0, 0, 0, 0}, -+ {0x69, 0, 0, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0xc, 0xc, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0, 0, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0, 0, 0, 0}, -+ {0x71, 0, 0, 0, 0}, -+ {0x72, 0x22, 0x22, 0, 0}, -+ {0x73, 0x22, 0x22, 0, 0}, -+ {0x74, 0, 0, 1, 1}, -+ {0x75, 0xa, 0xa, 0, 0}, -+ {0x76, 0x1, 0x1, 0, 0}, -+ {0x77, 0x22, 0x22, 0, 0}, -+ {0x78, 0x30, 0x30, 0, 0}, -+ {0x79, 0, 0, 0, 0}, -+ {0x7A, 0, 0, 0, 0}, -+ {0x7B, 0, 0, 0, 0}, -+ {0x7C, 0, 0, 0, 0}, -+ {0x7D, 0, 0, 0, 0}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0, 0, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0, 0, 0, 0}, -+ {0x94, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0} -+}; -+ -+static struct radio_regs regs_SYN_2056_rev5[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0x1, 0x1, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0, 0, 0, 0}, -+ {0x21, 0, 0, 0, 0}, -+ {0x22, 0x60, 0x60, 0, 0}, -+ {0x23, 0x6, 0x6, 0, 0}, -+ {0x24, 0xc, 0xc, 0, 0}, -+ {0x25, 0, 0, 0, 0}, -+ {0x26, 0, 0, 0, 0}, -+ {0x27, 0, 0, 0, 0}, -+ {0x28, 0x1, 0x1, 0, 0}, -+ {0x29, 0, 0, 0, 0}, -+ {0x2A, 0, 0, 0, 0}, -+ {0x2B, 0, 0, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0, 0, 0, 0}, -+ {0x2E, 0, 0, 0, 0}, -+ {0x2F, 0x1f, 0x1f, 0, 0}, -+ {0x30, 0x15, 0x15, 0, 0}, -+ {0x31, 0xf, 0xf, 0, 0}, -+ {0x32, 0, 0, 0, 0}, -+ {0x33, 0, 0, 0, 0}, -+ {0x34, 0, 0, 0, 0}, -+ {0x35, 0, 0, 0, 0}, -+ {0x36, 0, 0, 0, 0}, -+ {0x37, 0, 0, 0, 0}, -+ {0x38, 0, 0, 0, 0}, -+ {0x39, 0, 0, 0, 0}, -+ {0x3A, 0, 0, 0, 0}, -+ {0x3B, 0, 0, 0, 0}, -+ {0x3C, 0x13, 0x13, 0, 0}, -+ {0x3D, 0xf, 0xf, 0, 0}, -+ {0x3E, 0x18, 0x18, 0, 0}, -+ {0x3F, 0, 0, 0, 0}, -+ {0x40, 0, 0, 0, 0}, -+ {0x41, 0x20, 0x20, 0, 0}, -+ {0x42, 0x20, 0x20, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x77, 0x77, 0, 0}, -+ {0x45, 0x7, 0x7, 0, 0}, -+ {0x46, 0x1, 0x1, 0, 0}, -+ {0x47, 0x4, 0x4, 0, 0}, -+ {0x48, 0xf, 0xf, 0, 0}, -+ {0x49, 0x30, 0x30, 0, 0}, -+ {0x4A, 0x32, 0x32, 0, 0}, -+ {0x4B, 0xd, 0xd, 0, 0}, -+ {0x4C, 0xd, 0xd, 0, 0}, -+ {0x4D, 0x4, 0x4, 0, 0}, -+ {0x4E, 0x6, 0x6, 0, 0}, -+ {0x4F, 0x1, 0x1, 0, 0}, -+ {0x50, 0x1c, 0x1c, 0, 0}, -+ {0x51, 0x2, 0x2, 0, 0}, -+ {0x52, 0x2, 0x2, 0, 0}, -+ {0x53, 0xf7, 0xf7, 1, 1}, -+ {0x54, 0xb4, 0xb4, 0, 0}, -+ {0x55, 0xd2, 0xd2, 0, 0}, -+ {0x56, 0, 0, 0, 0}, -+ {0x57, 0, 0, 0, 0}, -+ {0x58, 0x4, 0x4, 0, 0}, -+ {0x59, 0x96, 0x96, 0, 0}, -+ {0x5A, 0x3e, 0x3e, 0, 0}, -+ {0x5B, 0x3e, 0x3e, 0, 0}, -+ {0x5C, 0x13, 0x13, 0, 0}, -+ {0x5D, 0x2, 0x2, 0, 0}, -+ {0x5E, 0, 0, 0, 0}, -+ {0x5F, 0x7, 0x7, 0, 0}, -+ {0x60, 0x7, 0x7, 1, 1}, -+ {0x61, 0x8, 0x8, 0, 0}, -+ {0x62, 0x3, 0x3, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0, 0, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 0, 0}, -+ {0x68, 0x40, 0x40, 0, 0}, -+ {0x69, 0, 0, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0, 0, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0x1, 0x1, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0x60, 0x60, 0, 0}, -+ {0x71, 0x66, 0x66, 0, 0}, -+ {0x72, 0xc, 0xc, 0, 0}, -+ {0x73, 0x66, 0x66, 0, 0}, -+ {0x74, 0x8f, 0x8f, 1, 1}, -+ {0x75, 0, 0, 0, 0}, -+ {0x76, 0xcc, 0xcc, 0, 0}, -+ {0x77, 0x1, 0x1, 0, 0}, -+ {0x78, 0x66, 0x66, 0, 0}, -+ {0x79, 0x66, 0x66, 0, 0}, -+ {0x7A, 0, 0, 0, 0}, -+ {0x7B, 0, 0, 0, 0}, -+ {0x7C, 0, 0, 0, 0}, -+ {0x7D, 0, 0, 0, 0}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0xff, 0xff, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0, 0, 0, 0}, -+ {0x94, 0, 0, 0, 0}, -+ {0x95, 0, 0, 0, 0}, -+ {0x96, 0, 0, 0, 0}, -+ {0x97, 0, 0, 0, 0}, -+ {0x98, 0, 0, 0, 0}, -+ {0x99, 0, 0, 0, 0}, -+ {0x9A, 0, 0, 0, 0}, -+ {0x9B, 0, 0, 0, 0}, -+ {0x9C, 0, 0, 0, 0}, -+ {0x9D, 0, 0, 0, 0}, -+ {0x9E, 0, 0, 0, 0}, -+ {0x9F, 0x6, 0x6, 0, 0}, -+ {0xA0, 0x66, 0x66, 0, 0}, -+ {0xA1, 0x66, 0x66, 0, 0}, -+ {0xA2, 0x66, 0x66, 0, 0}, -+ {0xA3, 0x66, 0x66, 0, 0}, -+ {0xA4, 0x66, 0x66, 0, 0}, -+ {0xA5, 0x66, 0x66, 0, 0}, -+ {0xA6, 0x66, 0x66, 0, 0}, -+ {0xA7, 0x66, 0x66, 0, 0}, -+ {0xA8, 0x66, 0x66, 0, 0}, -+ {0xA9, 0x66, 0x66, 0, 0}, -+ {0xAA, 0x66, 0x66, 0, 0}, -+ {0xAB, 0x66, 0x66, 0, 0}, -+ {0xAC, 0x66, 0x66, 0, 0}, -+ {0xAD, 0x66, 0x66, 0, 0}, -+ {0xAE, 0x66, 0x66, 0, 0}, -+ {0xAF, 0x66, 0x66, 0, 0}, -+ {0xB0, 0x66, 0x66, 0, 0}, -+ {0xB1, 0x66, 0x66, 0, 0}, -+ {0xB2, 0x66, 0x66, 0, 0}, -+ {0xB3, 0xa, 0xa, 0, 0}, -+ {0xB4, 0, 0, 0, 0}, -+ {0xB5, 0, 0, 0, 0}, -+ {0xB6, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0} -+}; -+ -+static struct radio_regs regs_TX_2056_rev5[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0, 0, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0, 0, 0, 0}, -+ {0x21, 0x88, 0x88, 0, 0}, -+ {0x22, 0x88, 0x88, 0, 0}, -+ {0x23, 0x88, 0x88, 0, 0}, -+ {0x24, 0x88, 0x88, 0, 0}, -+ {0x25, 0xc, 0xc, 0, 0}, -+ {0x26, 0, 0, 0, 0}, -+ {0x27, 0x3, 0x3, 0, 0}, -+ {0x28, 0, 0, 0, 0}, -+ {0x29, 0x3, 0x3, 0, 0}, -+ {0x2A, 0x37, 0x37, 0, 0}, -+ {0x2B, 0x3, 0x3, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0, 0, 0, 0}, -+ {0x2E, 0x1, 0x1, 0, 0}, -+ {0x2F, 0x1, 0x1, 0, 0}, -+ {0x30, 0, 0, 0, 0}, -+ {0x31, 0, 0, 0, 0}, -+ {0x32, 0, 0, 0, 0}, -+ {0x33, 0x11, 0x11, 0, 0}, -+ {0x34, 0x11, 0x11, 0, 0}, -+ {0x35, 0, 0, 0, 0}, -+ {0x36, 0, 0, 0, 0}, -+ {0x37, 0x3, 0x3, 0, 0}, -+ {0x38, 0xf, 0xf, 0, 0}, -+ {0x39, 0, 0, 0, 0}, -+ {0x3A, 0x2d, 0x2d, 0, 0}, -+ {0x3B, 0, 0, 0, 0}, -+ {0x3C, 0x6e, 0x6e, 0, 0}, -+ {0x3D, 0xf0, 0xf0, 1, 1}, -+ {0x3E, 0, 0, 0, 0}, -+ {0x3F, 0, 0, 0, 0}, -+ {0x40, 0, 0, 0, 0}, -+ {0x41, 0x3, 0x3, 0, 0}, -+ {0x42, 0x3, 0x3, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x1e, 0x1e, 0, 0}, -+ {0x45, 0, 0, 0, 0}, -+ {0x46, 0x6e, 0x6e, 0, 0}, -+ {0x47, 0xf0, 0xf0, 1, 1}, -+ {0x48, 0, 0, 0, 0}, -+ {0x49, 0x2, 0x2, 0, 0}, -+ {0x4A, 0xff, 0xff, 1, 1}, -+ {0x4B, 0xc, 0xc, 0, 0}, -+ {0x4C, 0, 0, 0, 0}, -+ {0x4D, 0x38, 0x38, 0, 0}, -+ {0x4E, 0x70, 0x70, 1, 1}, -+ {0x4F, 0x2, 0x2, 0, 0}, -+ {0x50, 0x88, 0x88, 0, 0}, -+ {0x51, 0xc, 0xc, 0, 0}, -+ {0x52, 0, 0, 0, 0}, -+ {0x53, 0x8, 0x8, 0, 0}, -+ {0x54, 0x70, 0x70, 1, 1}, -+ {0x55, 0x2, 0x2, 0, 0}, -+ {0x56, 0xff, 0xff, 1, 1}, -+ {0x57, 0, 0, 0, 0}, -+ {0x58, 0x83, 0x83, 0, 0}, -+ {0x59, 0x77, 0x77, 1, 1}, -+ {0x5A, 0, 0, 0, 0}, -+ {0x5B, 0x2, 0x2, 0, 0}, -+ {0x5C, 0x88, 0x88, 0, 0}, -+ {0x5D, 0, 0, 0, 0}, -+ {0x5E, 0x8, 0x8, 0, 0}, -+ {0x5F, 0x77, 0x77, 1, 1}, -+ {0x60, 0x1, 0x1, 0, 0}, -+ {0x61, 0, 0, 0, 0}, -+ {0x62, 0x7, 0x7, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0x7, 0x7, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 1, 1}, -+ {0x68, 0, 0, 0, 0}, -+ {0x69, 0xa, 0xa, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0, 0, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0, 0, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0, 0, 0, 0}, -+ {0x71, 0x2, 0x2, 0, 0}, -+ {0x72, 0, 0, 0, 0}, -+ {0x73, 0, 0, 0, 0}, -+ {0x74, 0xe, 0xe, 0, 0}, -+ {0x75, 0xe, 0xe, 0, 0}, -+ {0x76, 0xe, 0xe, 0, 0}, -+ {0x77, 0x13, 0x13, 0, 0}, -+ {0x78, 0x13, 0x13, 0, 0}, -+ {0x79, 0x1b, 0x1b, 0, 0}, -+ {0x7A, 0x1b, 0x1b, 0, 0}, -+ {0x7B, 0x55, 0x55, 0, 0}, -+ {0x7C, 0x5b, 0x5b, 0, 0}, -+ {0x7D, 0, 0, 0, 0}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0, 0, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0x70, 0x70, 0, 0}, -+ {0x94, 0x70, 0x70, 0, 0}, -+ {0x95, 0x71, 0x71, 1, 1}, -+ {0x96, 0x71, 0x71, 1, 1}, -+ {0x97, 0x72, 0x72, 1, 1}, -+ {0x98, 0x73, 0x73, 1, 1}, -+ {0x99, 0x74, 0x74, 1, 1}, -+ {0x9A, 0x75, 0x75, 1, 1}, -+ {0xFFFF, 0, 0, 0, 0} -+}; -+ -+static struct radio_regs regs_RX_2056_rev5[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0, 0, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0x3, 0x3, 0, 0}, -+ {0x21, 0, 0, 0, 0}, -+ {0x22, 0, 0, 0, 0}, -+ {0x23, 0x90, 0x90, 0, 0}, -+ {0x24, 0x55, 0x55, 0, 0}, -+ {0x25, 0x15, 0x15, 0, 0}, -+ {0x26, 0x5, 0x5, 0, 0}, -+ {0x27, 0x15, 0x15, 0, 0}, -+ {0x28, 0x5, 0x5, 0, 0}, -+ {0x29, 0x20, 0x20, 0, 0}, -+ {0x2A, 0x11, 0x11, 0, 0}, -+ {0x2B, 0x90, 0x90, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0x88, 0x88, 0, 0}, -+ {0x2E, 0x32, 0x32, 0, 0}, -+ {0x2F, 0x77, 0x77, 0, 0}, -+ {0x30, 0x17, 0x17, 1, 1}, -+ {0x31, 0xff, 0xff, 1, 1}, -+ {0x32, 0x20, 0x20, 0, 0}, -+ {0x33, 0, 0, 0, 0}, -+ {0x34, 0x88, 0x88, 0, 0}, -+ {0x35, 0x32, 0x32, 0, 0}, -+ {0x36, 0x77, 0x77, 0, 0}, -+ {0x37, 0x17, 0x17, 1, 1}, -+ {0x38, 0xf0, 0xf0, 1, 1}, -+ {0x39, 0x20, 0x20, 0, 0}, -+ {0x3A, 0x8, 0x8, 0, 0}, -+ {0x3B, 0x55, 0x55, 1, 1}, -+ {0x3C, 0, 0, 0, 0}, -+ {0x3D, 0x88, 0x88, 1, 1}, -+ {0x3E, 0, 0, 0, 0}, -+ {0x3F, 0, 0, 1, 1}, -+ {0x40, 0x7, 0x7, 1, 1}, -+ {0x41, 0x6, 0x6, 0, 0}, -+ {0x42, 0x4, 0x4, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x8, 0x8, 0, 0}, -+ {0x45, 0x55, 0x55, 1, 1}, -+ {0x46, 0, 0, 0, 0}, -+ {0x47, 0x11, 0x11, 0, 0}, -+ {0x48, 0, 0, 0, 0}, -+ {0x49, 0, 0, 1, 1}, -+ {0x4A, 0x7, 0x7, 0, 0}, -+ {0x4B, 0x6, 0x6, 0, 0}, -+ {0x4C, 0x4, 0x4, 0, 0}, -+ {0x4D, 0, 0, 0, 0}, -+ {0x4E, 0, 0, 0, 0}, -+ {0x4F, 0x26, 0x26, 1, 1}, -+ {0x50, 0x26, 0x26, 1, 1}, -+ {0x51, 0xf, 0xf, 1, 1}, -+ {0x52, 0xf, 0xf, 1, 1}, -+ {0x53, 0x44, 0x44, 0, 0}, -+ {0x54, 0, 0, 0, 0}, -+ {0x55, 0, 0, 0, 0}, -+ {0x56, 0x8, 0x8, 0, 0}, -+ {0x57, 0x8, 0x8, 0, 0}, -+ {0x58, 0x7, 0x7, 0, 0}, -+ {0x59, 0x22, 0x22, 0, 0}, -+ {0x5A, 0x22, 0x22, 0, 0}, -+ {0x5B, 0x2, 0x2, 0, 0}, -+ {0x5C, 0x4, 0x4, 1, 1}, -+ {0x5D, 0x7, 0x7, 0, 0}, -+ {0x5E, 0x55, 0x55, 0, 0}, -+ {0x5F, 0x23, 0x23, 0, 0}, -+ {0x60, 0x41, 0x41, 0, 0}, -+ {0x61, 0x1, 0x1, 0, 0}, -+ {0x62, 0xa, 0xa, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0, 0, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 0, 0}, -+ {0x68, 0, 0, 0, 0}, -+ {0x69, 0, 0, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0xc, 0xc, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0, 0, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0, 0, 0, 0}, -+ {0x71, 0, 0, 0, 0}, -+ {0x72, 0x22, 0x22, 0, 0}, -+ {0x73, 0x22, 0x22, 0, 0}, -+ {0x74, 0, 0, 1, 1}, -+ {0x75, 0xa, 0xa, 0, 0}, -+ {0x76, 0x1, 0x1, 0, 0}, -+ {0x77, 0x22, 0x22, 0, 0}, -+ {0x78, 0x30, 0x30, 0, 0}, -+ {0x79, 0, 0, 0, 0}, -+ {0x7A, 0, 0, 0, 0}, -+ {0x7B, 0, 0, 0, 0}, -+ {0x7C, 0, 0, 0, 0}, -+ {0x7D, 0, 0, 0, 0}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0, 0, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0, 0, 0, 0}, -+ {0x94, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0} -+}; -+ -+static struct radio_regs regs_SYN_2056_rev6[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0x1, 0x1, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0, 0, 0, 0}, -+ {0x21, 0, 0, 0, 0}, -+ {0x22, 0x60, 0x60, 0, 0}, -+ {0x23, 0x6, 0x6, 0, 0}, -+ {0x24, 0xc, 0xc, 0, 0}, -+ {0x25, 0, 0, 0, 0}, -+ {0x26, 0, 0, 0, 0}, -+ {0x27, 0, 0, 0, 0}, -+ {0x28, 0x1, 0x1, 0, 0}, -+ {0x29, 0, 0, 0, 0}, -+ {0x2A, 0, 0, 0, 0}, -+ {0x2B, 0, 0, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0, 0, 0, 0}, -+ {0x2E, 0, 0, 0, 0}, -+ {0x2F, 0x1f, 0x1f, 0, 0}, -+ {0x30, 0x15, 0x15, 0, 0}, -+ {0x31, 0xf, 0xf, 0, 0}, -+ {0x32, 0, 0, 0, 0}, -+ {0x33, 0, 0, 0, 0}, -+ {0x34, 0, 0, 0, 0}, -+ {0x35, 0, 0, 0, 0}, -+ {0x36, 0, 0, 0, 0}, -+ {0x37, 0, 0, 0, 0}, -+ {0x38, 0, 0, 0, 0}, -+ {0x39, 0, 0, 0, 0}, -+ {0x3A, 0, 0, 0, 0}, -+ {0x3B, 0, 0, 0, 0}, -+ {0x3C, 0x13, 0x13, 0, 0}, -+ {0x3D, 0xf, 0xf, 0, 0}, -+ {0x3E, 0x18, 0x18, 0, 0}, -+ {0x3F, 0, 0, 0, 0}, -+ {0x40, 0, 0, 0, 0}, -+ {0x41, 0x20, 0x20, 0, 0}, -+ {0x42, 0x20, 0x20, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x77, 0x77, 0, 0}, -+ {0x45, 0x7, 0x7, 0, 0}, -+ {0x46, 0x1, 0x1, 0, 0}, -+ {0x47, 0x4, 0x4, 0, 0}, -+ {0x48, 0xf, 0xf, 0, 0}, -+ {0x49, 0x30, 0x30, 0, 0}, -+ {0x4A, 0x32, 0x32, 0, 0}, -+ {0x4B, 0xd, 0xd, 0, 0}, -+ {0x4C, 0xd, 0xd, 0, 0}, -+ {0x4D, 0x4, 0x4, 0, 0}, -+ {0x4E, 0x6, 0x6, 0, 0}, -+ {0x4F, 0x1, 0x1, 0, 0}, -+ {0x50, 0x1c, 0x1c, 0, 0}, -+ {0x51, 0x2, 0x2, 0, 0}, -+ {0x52, 0x2, 0x2, 0, 0}, -+ {0x53, 0xf7, 0xf7, 1, 1}, -+ {0x54, 0xb4, 0xb4, 0, 0}, -+ {0x55, 0xd2, 0xd2, 0, 0}, -+ {0x56, 0, 0, 0, 0}, -+ {0x57, 0, 0, 0, 0}, -+ {0x58, 0x4, 0x4, 0, 0}, -+ {0x59, 0x96, 0x96, 0, 0}, -+ {0x5A, 0x3e, 0x3e, 0, 0}, -+ {0x5B, 0x3e, 0x3e, 0, 0}, -+ {0x5C, 0x13, 0x13, 0, 0}, -+ {0x5D, 0x2, 0x2, 0, 0}, -+ {0x5E, 0, 0, 0, 0}, -+ {0x5F, 0x7, 0x7, 0, 0}, -+ {0x60, 0x7, 0x7, 1, 1}, -+ {0x61, 0x8, 0x8, 0, 0}, -+ {0x62, 0x3, 0x3, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0, 0, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 0, 0}, -+ {0x68, 0x40, 0x40, 0, 0}, -+ {0x69, 0, 0, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0, 0, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0x1, 0x1, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0x60, 0x60, 0, 0}, -+ {0x71, 0x66, 0x66, 0, 0}, -+ {0x72, 0xc, 0xc, 0, 0}, -+ {0x73, 0x66, 0x66, 0, 0}, -+ {0x74, 0x8f, 0x8f, 1, 1}, -+ {0x75, 0, 0, 0, 0}, -+ {0x76, 0xcc, 0xcc, 0, 0}, -+ {0x77, 0x1, 0x1, 0, 0}, -+ {0x78, 0x66, 0x66, 0, 0}, -+ {0x79, 0x66, 0x66, 0, 0}, -+ {0x7A, 0, 0, 0, 0}, -+ {0x7B, 0, 0, 0, 0}, -+ {0x7C, 0, 0, 0, 0}, -+ {0x7D, 0, 0, 0, 0}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0xff, 0xff, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0, 0, 0, 0}, -+ {0x94, 0, 0, 0, 0}, -+ {0x95, 0, 0, 0, 0}, -+ {0x96, 0, 0, 0, 0}, -+ {0x97, 0, 0, 0, 0}, -+ {0x98, 0, 0, 0, 0}, -+ {0x99, 0, 0, 0, 0}, -+ {0x9A, 0, 0, 0, 0}, -+ {0x9B, 0, 0, 0, 0}, -+ {0x9C, 0, 0, 0, 0}, -+ {0x9D, 0, 0, 0, 0}, -+ {0x9E, 0, 0, 0, 0}, -+ {0x9F, 0x6, 0x6, 0, 0}, -+ {0xA0, 0x66, 0x66, 0, 0}, -+ {0xA1, 0x66, 0x66, 0, 0}, -+ {0xA2, 0x66, 0x66, 0, 0}, -+ {0xA3, 0x66, 0x66, 0, 0}, -+ {0xA4, 0x66, 0x66, 0, 0}, -+ {0xA5, 0x66, 0x66, 0, 0}, -+ {0xA6, 0x66, 0x66, 0, 0}, -+ {0xA7, 0x66, 0x66, 0, 0}, -+ {0xA8, 0x66, 0x66, 0, 0}, -+ {0xA9, 0x66, 0x66, 0, 0}, -+ {0xAA, 0x66, 0x66, 0, 0}, -+ {0xAB, 0x66, 0x66, 0, 0}, -+ {0xAC, 0x66, 0x66, 0, 0}, -+ {0xAD, 0x66, 0x66, 0, 0}, -+ {0xAE, 0x66, 0x66, 0, 0}, -+ {0xAF, 0x66, 0x66, 0, 0}, -+ {0xB0, 0x66, 0x66, 0, 0}, -+ {0xB1, 0x66, 0x66, 0, 0}, -+ {0xB2, 0x66, 0x66, 0, 0}, -+ {0xB3, 0xa, 0xa, 0, 0}, -+ {0xB4, 0, 0, 0, 0}, -+ {0xB5, 0, 0, 0, 0}, -+ {0xB6, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0} -+}; -+ -+static struct radio_regs regs_TX_2056_rev6[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0, 0, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0, 0, 0, 0}, -+ {0x21, 0x88, 0x88, 0, 0}, -+ {0x22, 0x88, 0x88, 0, 0}, -+ {0x23, 0x88, 0x88, 0, 0}, -+ {0x24, 0x88, 0x88, 0, 0}, -+ {0x25, 0xc, 0xc, 0, 0}, -+ {0x26, 0, 0, 0, 0}, -+ {0x27, 0x3, 0x3, 0, 0}, -+ {0x28, 0, 0, 0, 0}, -+ {0x29, 0x3, 0x3, 0, 0}, -+ {0x2A, 0x37, 0x37, 0, 0}, -+ {0x2B, 0x3, 0x3, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0, 0, 0, 0}, -+ {0x2E, 0x1, 0x1, 0, 0}, -+ {0x2F, 0x1, 0x1, 0, 0}, -+ {0x30, 0, 0, 0, 0}, -+ {0x31, 0, 0, 0, 0}, -+ {0x32, 0, 0, 0, 0}, -+ {0x33, 0x11, 0x11, 0, 0}, -+ {0x34, 0xee, 0xee, 1, 1}, -+ {0x35, 0, 0, 0, 0}, -+ {0x36, 0, 0, 0, 0}, -+ {0x37, 0x3, 0x3, 0, 0}, -+ {0x38, 0x50, 0x50, 1, 1}, -+ {0x39, 0, 0, 0, 0}, -+ {0x3A, 0x50, 0x50, 1, 1}, -+ {0x3B, 0, 0, 0, 0}, -+ {0x3C, 0x6e, 0x6e, 0, 0}, -+ {0x3D, 0xf0, 0xf0, 1, 1}, -+ {0x3E, 0, 0, 0, 0}, -+ {0x3F, 0, 0, 0, 0}, -+ {0x40, 0, 0, 0, 0}, -+ {0x41, 0x3, 0x3, 0, 0}, -+ {0x42, 0x3, 0x3, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x1e, 0x1e, 0, 0}, -+ {0x45, 0, 0, 0, 0}, -+ {0x46, 0x6e, 0x6e, 0, 0}, -+ {0x47, 0xf0, 0xf0, 1, 1}, -+ {0x48, 0, 0, 0, 0}, -+ {0x49, 0x2, 0x2, 0, 0}, -+ {0x4A, 0xff, 0xff, 1, 1}, -+ {0x4B, 0xc, 0xc, 0, 0}, -+ {0x4C, 0, 0, 0, 0}, -+ {0x4D, 0x38, 0x38, 0, 0}, -+ {0x4E, 0x70, 0x70, 1, 1}, -+ {0x4F, 0x2, 0x2, 0, 0}, -+ {0x50, 0x88, 0x88, 0, 0}, -+ {0x51, 0xc, 0xc, 0, 0}, -+ {0x52, 0, 0, 0, 0}, -+ {0x53, 0x8, 0x8, 0, 0}, -+ {0x54, 0x70, 0x70, 1, 1}, -+ {0x55, 0x2, 0x2, 0, 0}, -+ {0x56, 0xff, 0xff, 1, 1}, -+ {0x57, 0, 0, 0, 0}, -+ {0x58, 0x83, 0x83, 0, 0}, -+ {0x59, 0x77, 0x77, 1, 1}, -+ {0x5A, 0, 0, 0, 0}, -+ {0x5B, 0x2, 0x2, 0, 0}, -+ {0x5C, 0x88, 0x88, 0, 0}, -+ {0x5D, 0, 0, 0, 0}, -+ {0x5E, 0x8, 0x8, 0, 0}, -+ {0x5F, 0x77, 0x77, 1, 1}, -+ {0x60, 0x1, 0x1, 0, 0}, -+ {0x61, 0, 0, 0, 0}, -+ {0x62, 0x7, 0x7, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0x7, 0x7, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 1, 1}, -+ {0x68, 0, 0, 0, 0}, -+ {0x69, 0xa, 0xa, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0, 0, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0, 0, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0, 0, 0, 0}, -+ {0x71, 0x2, 0x2, 0, 0}, -+ {0x72, 0, 0, 0, 0}, -+ {0x73, 0, 0, 0, 0}, -+ {0x74, 0xe, 0xe, 0, 0}, -+ {0x75, 0xe, 0xe, 0, 0}, -+ {0x76, 0xe, 0xe, 0, 0}, -+ {0x77, 0x13, 0x13, 0, 0}, -+ {0x78, 0x13, 0x13, 0, 0}, -+ {0x79, 0x1b, 0x1b, 0, 0}, -+ {0x7A, 0x1b, 0x1b, 0, 0}, -+ {0x7B, 0x55, 0x55, 0, 0}, -+ {0x7C, 0x5b, 0x5b, 0, 0}, -+ {0x7D, 0x30, 0x30, 1, 1}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0, 0, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0x70, 0x70, 0, 0}, -+ {0x94, 0x70, 0x70, 0, 0}, -+ {0x95, 0x70, 0x70, 0, 0}, -+ {0x96, 0x70, 0x70, 0, 0}, -+ {0x97, 0x70, 0x70, 0, 0}, -+ {0x98, 0x70, 0x70, 0, 0}, -+ {0x99, 0x70, 0x70, 0, 0}, -+ {0x9A, 0x70, 0x70, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0} -+}; -+ -+static struct radio_regs regs_RX_2056_rev6[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0, 0, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0x3, 0x3, 0, 0}, -+ {0x21, 0, 0, 0, 0}, -+ {0x22, 0, 0, 0, 0}, -+ {0x23, 0x90, 0x90, 0, 0}, -+ {0x24, 0x55, 0x55, 0, 0}, -+ {0x25, 0x15, 0x15, 0, 0}, -+ {0x26, 0x5, 0x5, 0, 0}, -+ {0x27, 0x15, 0x15, 0, 0}, -+ {0x28, 0x5, 0x5, 0, 0}, -+ {0x29, 0x20, 0x20, 0, 0}, -+ {0x2A, 0x11, 0x11, 0, 0}, -+ {0x2B, 0x90, 0x90, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0x88, 0x88, 0, 0}, -+ {0x2E, 0x32, 0x32, 0, 0}, -+ {0x2F, 0x77, 0x77, 0, 0}, -+ {0x30, 0x17, 0x17, 1, 1}, -+ {0x31, 0xff, 0xff, 1, 1}, -+ {0x32, 0x20, 0x20, 0, 0}, -+ {0x33, 0, 0, 0, 0}, -+ {0x34, 0x88, 0x88, 0, 0}, -+ {0x35, 0x32, 0x32, 0, 0}, -+ {0x36, 0x77, 0x77, 0, 0}, -+ {0x37, 0x17, 0x17, 1, 1}, -+ {0x38, 0xf0, 0xf0, 1, 1}, -+ {0x39, 0x20, 0x20, 0, 0}, -+ {0x3A, 0x8, 0x8, 0, 0}, -+ {0x3B, 0x55, 0x55, 1, 1}, -+ {0x3C, 0, 0, 0, 0}, -+ {0x3D, 0x88, 0x88, 1, 1}, -+ {0x3E, 0, 0, 0, 0}, -+ {0x3F, 0x44, 0x44, 0, 0}, -+ {0x40, 0x7, 0x7, 1, 1}, -+ {0x41, 0x6, 0x6, 0, 0}, -+ {0x42, 0x4, 0x4, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x8, 0x8, 0, 0}, -+ {0x45, 0x55, 0x55, 1, 1}, -+ {0x46, 0, 0, 0, 0}, -+ {0x47, 0x11, 0x11, 0, 0}, -+ {0x48, 0, 0, 0, 0}, -+ {0x49, 0x44, 0x44, 0, 0}, -+ {0x4A, 0x7, 0x7, 0, 0}, -+ {0x4B, 0x6, 0x6, 0, 0}, -+ {0x4C, 0x4, 0x4, 0, 0}, -+ {0x4D, 0, 0, 0, 0}, -+ {0x4E, 0, 0, 0, 0}, -+ {0x4F, 0x26, 0x26, 1, 1}, -+ {0x50, 0x26, 0x26, 1, 1}, -+ {0x51, 0xf, 0xf, 1, 1}, -+ {0x52, 0xf, 0xf, 1, 1}, -+ {0x53, 0x44, 0x44, 0, 0}, -+ {0x54, 0, 0, 0, 0}, -+ {0x55, 0, 0, 0, 0}, -+ {0x56, 0x8, 0x8, 0, 0}, -+ {0x57, 0x8, 0x8, 0, 0}, -+ {0x58, 0x7, 0x7, 0, 0}, -+ {0x59, 0x22, 0x22, 0, 0}, -+ {0x5A, 0x22, 0x22, 0, 0}, -+ {0x5B, 0x2, 0x2, 0, 0}, -+ {0x5C, 0x4, 0x4, 1, 1}, -+ {0x5D, 0x7, 0x7, 0, 0}, -+ {0x5E, 0x55, 0x55, 0, 0}, -+ {0x5F, 0x23, 0x23, 0, 0}, -+ {0x60, 0x41, 0x41, 0, 0}, -+ {0x61, 0x1, 0x1, 0, 0}, -+ {0x62, 0xa, 0xa, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0, 0, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 0, 0}, -+ {0x68, 0, 0, 0, 0}, -+ {0x69, 0, 0, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0xc, 0xc, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0, 0, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0, 0, 0, 0}, -+ {0x71, 0, 0, 0, 0}, -+ {0x72, 0x22, 0x22, 0, 0}, -+ {0x73, 0x22, 0x22, 0, 0}, -+ {0x74, 0, 0, 1, 1}, -+ {0x75, 0xa, 0xa, 0, 0}, -+ {0x76, 0x1, 0x1, 0, 0}, -+ {0x77, 0x22, 0x22, 0, 0}, -+ {0x78, 0x30, 0x30, 0, 0}, -+ {0x79, 0, 0, 0, 0}, -+ {0x7A, 0, 0, 0, 0}, -+ {0x7B, 0, 0, 0, 0}, -+ {0x7C, 0, 0, 0, 0}, -+ {0x7D, 0x5, 0x5, 1, 1}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0, 0, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0, 0, 0, 0}, -+ {0x94, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0} -+}; -+ -+static struct radio_regs regs_SYN_2056_rev7[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0x1, 0x1, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0, 0, 0, 0}, -+ {0x21, 0, 0, 0, 0}, -+ {0x22, 0x60, 0x60, 0, 0}, -+ {0x23, 0x6, 0x6, 0, 0}, -+ {0x24, 0xc, 0xc, 0, 0}, -+ {0x25, 0, 0, 0, 0}, -+ {0x26, 0, 0, 0, 0}, -+ {0x27, 0, 0, 0, 0}, -+ {0x28, 0x1, 0x1, 0, 0}, -+ {0x29, 0, 0, 0, 0}, -+ {0x2A, 0, 0, 0, 0}, -+ {0x2B, 0, 0, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0, 0, 0, 0}, -+ {0x2E, 0, 0, 0, 0}, -+ {0x2F, 0x1f, 0x1f, 0, 0}, -+ {0x30, 0x15, 0x15, 0, 0}, -+ {0x31, 0xf, 0xf, 0, 0}, -+ {0x32, 0, 0, 0, 0}, -+ {0x33, 0, 0, 0, 0}, -+ {0x34, 0, 0, 0, 0}, -+ {0x35, 0, 0, 0, 0}, -+ {0x36, 0, 0, 0, 0}, -+ {0x37, 0, 0, 0, 0}, -+ {0x38, 0, 0, 0, 0}, -+ {0x39, 0, 0, 0, 0}, -+ {0x3A, 0, 0, 0, 0}, -+ {0x3B, 0, 0, 0, 0}, -+ {0x3C, 0x13, 0x13, 0, 0}, -+ {0x3D, 0xf, 0xf, 0, 0}, -+ {0x3E, 0x18, 0x18, 0, 0}, -+ {0x3F, 0, 0, 0, 0}, -+ {0x40, 0, 0, 0, 0}, -+ {0x41, 0x20, 0x20, 0, 0}, -+ {0x42, 0x20, 0x20, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x77, 0x77, 0, 0}, -+ {0x45, 0x7, 0x7, 0, 0}, -+ {0x46, 0x1, 0x1, 0, 0}, -+ {0x47, 0x4, 0x4, 0, 0}, -+ {0x48, 0xf, 0xf, 0, 0}, -+ {0x49, 0x30, 0x30, 0, 0}, -+ {0x4A, 0x32, 0x32, 0, 0}, -+ {0x4B, 0xd, 0xd, 0, 0}, -+ {0x4C, 0xd, 0xd, 0, 0}, -+ {0x4D, 0x4, 0x4, 0, 0}, -+ {0x4E, 0x6, 0x6, 0, 0}, -+ {0x4F, 0x1, 0x1, 0, 0}, -+ {0x50, 0x1c, 0x1c, 0, 0}, -+ {0x51, 0x2, 0x2, 0, 0}, -+ {0x52, 0x2, 0x2, 0, 0}, -+ {0x53, 0xf7, 0xf7, 1, 1}, -+ {0x54, 0xb4, 0xb4, 0, 0}, -+ {0x55, 0xd2, 0xd2, 0, 0}, -+ {0x56, 0, 0, 0, 0}, -+ {0x57, 0, 0, 0, 0}, -+ {0x58, 0x4, 0x4, 0, 0}, -+ {0x59, 0x96, 0x96, 0, 0}, -+ {0x5A, 0x3e, 0x3e, 0, 0}, -+ {0x5B, 0x3e, 0x3e, 0, 0}, -+ {0x5C, 0x13, 0x13, 0, 0}, -+ {0x5D, 0x2, 0x2, 0, 0}, -+ {0x5E, 0, 0, 0, 0}, -+ {0x5F, 0x7, 0x7, 0, 0}, -+ {0x60, 0x7, 0x7, 1, 1}, -+ {0x61, 0x8, 0x8, 0, 0}, -+ {0x62, 0x3, 0x3, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0, 0, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 0, 0}, -+ {0x68, 0x40, 0x40, 0, 0}, -+ {0x69, 0, 0, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0, 0, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0x1, 0x1, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0x60, 0x60, 0, 0}, -+ {0x71, 0x66, 0x66, 0, 0}, -+ {0x72, 0xc, 0xc, 0, 0}, -+ {0x73, 0x66, 0x66, 0, 0}, -+ {0x74, 0x8f, 0x8f, 1, 1}, -+ {0x75, 0, 0, 0, 0}, -+ {0x76, 0xcc, 0xcc, 0, 0}, -+ {0x77, 0x1, 0x1, 0, 0}, -+ {0x78, 0x66, 0x66, 0, 0}, -+ {0x79, 0x66, 0x66, 0, 0}, -+ {0x7A, 0, 0, 0, 0}, -+ {0x7B, 0, 0, 0, 0}, -+ {0x7C, 0, 0, 0, 0}, -+ {0x7D, 0, 0, 0, 0}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0xff, 0xff, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0, 0, 0, 0}, -+ {0x94, 0, 0, 0, 0}, -+ {0x95, 0, 0, 0, 0}, -+ {0x96, 0, 0, 0, 0}, -+ {0x97, 0, 0, 0, 0}, -+ {0x98, 0, 0, 0, 0}, -+ {0x99, 0, 0, 0, 0}, -+ {0x9A, 0, 0, 0, 0}, -+ {0x9B, 0, 0, 0, 0}, -+ {0x9C, 0, 0, 0, 0}, -+ {0x9D, 0, 0, 0, 0}, -+ {0x9E, 0, 0, 0, 0}, -+ {0x9F, 0x6, 0x6, 0, 0}, -+ {0xA0, 0x66, 0x66, 0, 0}, -+ {0xA1, 0x66, 0x66, 0, 0}, -+ {0xA2, 0x66, 0x66, 0, 0}, -+ {0xA3, 0x66, 0x66, 0, 0}, -+ {0xA4, 0x66, 0x66, 0, 0}, -+ {0xA5, 0x66, 0x66, 0, 0}, -+ {0xA6, 0x66, 0x66, 0, 0}, -+ {0xA7, 0x66, 0x66, 0, 0}, -+ {0xA8, 0x66, 0x66, 0, 0}, -+ {0xA9, 0x66, 0x66, 0, 0}, -+ {0xAA, 0x66, 0x66, 0, 0}, -+ {0xAB, 0x66, 0x66, 0, 0}, -+ {0xAC, 0x66, 0x66, 0, 0}, -+ {0xAD, 0x66, 0x66, 0, 0}, -+ {0xAE, 0x66, 0x66, 0, 0}, -+ {0xAF, 0x66, 0x66, 0, 0}, -+ {0xB0, 0x66, 0x66, 0, 0}, -+ {0xB1, 0x66, 0x66, 0, 0}, -+ {0xB2, 0x66, 0x66, 0, 0}, -+ {0xB3, 0xa, 0xa, 0, 0}, -+ {0xB4, 0, 0, 0, 0}, -+ {0xB5, 0, 0, 0, 0}, -+ {0xB6, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0}, -+}; -+ -+static struct radio_regs regs_TX_2056_rev7[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0, 0, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0, 0, 0, 0}, -+ {0x21, 0x88, 0x88, 0, 0}, -+ {0x22, 0x88, 0x88, 0, 0}, -+ {0x23, 0x88, 0x88, 0, 0}, -+ {0x24, 0x88, 0x88, 0, 0}, -+ {0x25, 0xc, 0xc, 0, 0}, -+ {0x26, 0, 0, 0, 0}, -+ {0x27, 0x3, 0x3, 0, 0}, -+ {0x28, 0, 0, 0, 0}, -+ {0x29, 0x3, 0x3, 0, 0}, -+ {0x2A, 0x37, 0x37, 0, 0}, -+ {0x2B, 0x3, 0x3, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0, 0, 0, 0}, -+ {0x2E, 0x1, 0x1, 0, 0}, -+ {0x2F, 0x1, 0x1, 0, 0}, -+ {0x30, 0, 0, 0, 0}, -+ {0x31, 0, 0, 0, 0}, -+ {0x32, 0, 0, 0, 0}, -+ {0x33, 0x11, 0x11, 0, 0}, -+ {0x34, 0xee, 0xee, 1, 1}, -+ {0x35, 0, 0, 0, 0}, -+ {0x36, 0, 0, 0, 0}, -+ {0x37, 0x3, 0x3, 0, 0}, -+ {0x38, 0x50, 0x50, 1, 1}, -+ {0x39, 0, 0, 0, 0}, -+ {0x3A, 0x50, 0x50, 1, 1}, -+ {0x3B, 0, 0, 0, 0}, -+ {0x3C, 0x6e, 0x6e, 0, 0}, -+ {0x3D, 0xf0, 0xf0, 1, 1}, -+ {0x3E, 0, 0, 0, 0}, -+ {0x3F, 0, 0, 0, 0}, -+ {0x40, 0, 0, 0, 0}, -+ {0x41, 0x3, 0x3, 0, 0}, -+ {0x42, 0x3, 0x3, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x1e, 0x1e, 0, 0}, -+ {0x45, 0, 0, 0, 0}, -+ {0x46, 0x6e, 0x6e, 0, 0}, -+ {0x47, 0xf0, 0xf0, 1, 1}, -+ {0x48, 0, 0, 0, 0}, -+ {0x49, 0x2, 0x2, 0, 0}, -+ {0x4A, 0xff, 0xff, 1, 1}, -+ {0x4B, 0xc, 0xc, 0, 0}, -+ {0x4C, 0, 0, 0, 0}, -+ {0x4D, 0x38, 0x38, 0, 0}, -+ {0x4E, 0x70, 0x70, 1, 1}, -+ {0x4F, 0x2, 0x2, 0, 0}, -+ {0x50, 0x88, 0x88, 0, 0}, -+ {0x51, 0xc, 0xc, 0, 0}, -+ {0x52, 0, 0, 0, 0}, -+ {0x53, 0x8, 0x8, 0, 0}, -+ {0x54, 0x70, 0x70, 1, 1}, -+ {0x55, 0x2, 0x2, 0, 0}, -+ {0x56, 0xff, 0xff, 1, 1}, -+ {0x57, 0, 0, 0, 0}, -+ {0x58, 0x83, 0x83, 0, 0}, -+ {0x59, 0x77, 0x77, 1, 1}, -+ {0x5A, 0, 0, 0, 0}, -+ {0x5B, 0x2, 0x2, 0, 0}, -+ {0x5C, 0x88, 0x88, 0, 0}, -+ {0x5D, 0, 0, 0, 0}, -+ {0x5E, 0x8, 0x8, 0, 0}, -+ {0x5F, 0x77, 0x77, 1, 1}, -+ {0x60, 0x1, 0x1, 0, 0}, -+ {0x61, 0, 0, 0, 0}, -+ {0x62, 0x7, 0x7, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0x7, 0x7, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 1, 1}, -+ {0x68, 0, 0, 0, 0}, -+ {0x69, 0xa, 0xa, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0, 0, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0, 0, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0, 0, 0, 0}, -+ {0x71, 0x2, 0x2, 0, 0}, -+ {0x72, 0, 0, 0, 0}, -+ {0x73, 0, 0, 0, 0}, -+ {0x74, 0xe, 0xe, 0, 0}, -+ {0x75, 0xe, 0xe, 0, 0}, -+ {0x76, 0xe, 0xe, 0, 0}, -+ {0x77, 0x13, 0x13, 0, 0}, -+ {0x78, 0x13, 0x13, 0, 0}, -+ {0x79, 0x1b, 0x1b, 0, 0}, -+ {0x7A, 0x1b, 0x1b, 0, 0}, -+ {0x7B, 0x55, 0x55, 0, 0}, -+ {0x7C, 0x5b, 0x5b, 0, 0}, -+ {0x7D, 0x30, 0x30, 1, 1}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0, 0, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0x70, 0x70, 0, 0}, -+ {0x94, 0x70, 0x70, 0, 0}, -+ {0x95, 0x71, 0x71, 1, 1}, -+ {0x96, 0x71, 0x71, 1, 1}, -+ {0x97, 0x72, 0x72, 1, 1}, -+ {0x98, 0x73, 0x73, 1, 1}, -+ {0x99, 0x74, 0x74, 1, 1}, -+ {0x9A, 0x75, 0x75, 1, 1}, -+ {0xFFFF, 0, 0, 0, 0}, -+}; -+ -+static struct radio_regs regs_RX_2056_rev7[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0, 0, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0x3, 0x3, 0, 0}, -+ {0x21, 0, 0, 0, 0}, -+ {0x22, 0, 0, 0, 0}, -+ {0x23, 0x90, 0x90, 0, 0}, -+ {0x24, 0x55, 0x55, 0, 0}, -+ {0x25, 0x15, 0x15, 0, 0}, -+ {0x26, 0x5, 0x5, 0, 0}, -+ {0x27, 0x15, 0x15, 0, 0}, -+ {0x28, 0x5, 0x5, 0, 0}, -+ {0x29, 0x20, 0x20, 0, 0}, -+ {0x2A, 0x11, 0x11, 0, 0}, -+ {0x2B, 0x90, 0x90, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0x88, 0x88, 0, 0}, -+ {0x2E, 0x32, 0x32, 0, 0}, -+ {0x2F, 0x77, 0x77, 0, 0}, -+ {0x30, 0x17, 0x17, 1, 1}, -+ {0x31, 0xff, 0xff, 1, 1}, -+ {0x32, 0x20, 0x20, 0, 0}, -+ {0x33, 0, 0, 0, 0}, -+ {0x34, 0x88, 0x88, 0, 0}, -+ {0x35, 0x32, 0x32, 0, 0}, -+ {0x36, 0x77, 0x77, 0, 0}, -+ {0x37, 0x17, 0x17, 1, 1}, -+ {0x38, 0xf0, 0xf0, 1, 1}, -+ {0x39, 0x20, 0x20, 0, 0}, -+ {0x3A, 0x8, 0x8, 0, 0}, -+ {0x3B, 0x55, 0x55, 1, 1}, -+ {0x3C, 0, 0, 0, 0}, -+ {0x3D, 0x88, 0x88, 1, 1}, -+ {0x3E, 0, 0, 0, 0}, -+ {0x3F, 0, 0, 1, 1}, -+ {0x40, 0x7, 0x7, 1, 1}, -+ {0x41, 0x6, 0x6, 0, 0}, -+ {0x42, 0x4, 0x4, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x8, 0x8, 0, 0}, -+ {0x45, 0x55, 0x55, 1, 1}, -+ {0x46, 0, 0, 0, 0}, -+ {0x47, 0x11, 0x11, 0, 0}, -+ {0x48, 0, 0, 0, 0}, -+ {0x49, 0, 0, 1, 1}, -+ {0x4A, 0x7, 0x7, 0, 0}, -+ {0x4B, 0x6, 0x6, 0, 0}, -+ {0x4C, 0x4, 0x4, 0, 0}, -+ {0x4D, 0, 0, 0, 0}, -+ {0x4E, 0, 0, 0, 0}, -+ {0x4F, 0x26, 0x26, 1, 1}, -+ {0x50, 0x26, 0x26, 1, 1}, -+ {0x51, 0xf, 0xf, 1, 1}, -+ {0x52, 0xf, 0xf, 1, 1}, -+ {0x53, 0x44, 0x44, 0, 0}, -+ {0x54, 0, 0, 0, 0}, -+ {0x55, 0, 0, 0, 0}, -+ {0x56, 0x8, 0x8, 0, 0}, -+ {0x57, 0x8, 0x8, 0, 0}, -+ {0x58, 0x7, 0x7, 0, 0}, -+ {0x59, 0x22, 0x22, 0, 0}, -+ {0x5A, 0x22, 0x22, 0, 0}, -+ {0x5B, 0x2, 0x2, 0, 0}, -+ {0x5C, 0x4, 0x4, 1, 1}, -+ {0x5D, 0x7, 0x7, 0, 0}, -+ {0x5E, 0x55, 0x55, 0, 0}, -+ {0x5F, 0x23, 0x23, 0, 0}, -+ {0x60, 0x41, 0x41, 0, 0}, -+ {0x61, 0x1, 0x1, 0, 0}, -+ {0x62, 0xa, 0xa, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0, 0, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 0, 0}, -+ {0x68, 0, 0, 0, 0}, -+ {0x69, 0, 0, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0xc, 0xc, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0, 0, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0, 0, 0, 0}, -+ {0x71, 0, 0, 0, 0}, -+ {0x72, 0x22, 0x22, 0, 0}, -+ {0x73, 0x22, 0x22, 0, 0}, -+ {0x74, 0, 0, 1, 1}, -+ {0x75, 0xa, 0xa, 0, 0}, -+ {0x76, 0x1, 0x1, 0, 0}, -+ {0x77, 0x22, 0x22, 0, 0}, -+ {0x78, 0x30, 0x30, 0, 0}, -+ {0x79, 0, 0, 0, 0}, -+ {0x7A, 0, 0, 0, 0}, -+ {0x7B, 0, 0, 0, 0}, -+ {0x7C, 0, 0, 0, 0}, -+ {0x7D, 0, 0, 0, 0}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0, 0, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0, 0, 0, 0}, -+ {0x94, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0}, -+}; -+ -+static struct radio_regs regs_SYN_2056_rev8[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0x1, 0x1, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0, 0, 0, 0}, -+ {0x21, 0, 0, 0, 0}, -+ {0x22, 0x60, 0x60, 0, 0}, -+ {0x23, 0x6, 0x6, 0, 0}, -+ {0x24, 0xc, 0xc, 0, 0}, -+ {0x25, 0, 0, 0, 0}, -+ {0x26, 0, 0, 0, 0}, -+ {0x27, 0, 0, 0, 0}, -+ {0x28, 0x1, 0x1, 0, 0}, -+ {0x29, 0, 0, 0, 0}, -+ {0x2A, 0, 0, 0, 0}, -+ {0x2B, 0, 0, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0, 0, 0, 0}, -+ {0x2E, 0, 0, 0, 0}, -+ {0x2F, 0x1f, 0x1f, 0, 0}, -+ {0x30, 0x15, 0x15, 0, 0}, -+ {0x31, 0xf, 0xf, 0, 0}, -+ {0x32, 0, 0, 0, 0}, -+ {0x33, 0, 0, 0, 0}, -+ {0x34, 0, 0, 0, 0}, -+ {0x35, 0, 0, 0, 0}, -+ {0x36, 0, 0, 0, 0}, -+ {0x37, 0, 0, 0, 0}, -+ {0x38, 0, 0, 0, 0}, -+ {0x39, 0, 0, 0, 0}, -+ {0x3A, 0, 0, 0, 0}, -+ {0x3B, 0, 0, 0, 0}, -+ {0x3C, 0x13, 0x13, 0, 0}, -+ {0x3D, 0xf, 0xf, 0, 0}, -+ {0x3E, 0x18, 0x18, 0, 0}, -+ {0x3F, 0, 0, 0, 0}, -+ {0x40, 0, 0, 0, 0}, -+ {0x41, 0x20, 0x20, 0, 0}, -+ {0x42, 0x20, 0x20, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x77, 0x77, 0, 0}, -+ {0x45, 0x7, 0x7, 0, 0}, -+ {0x46, 0x1, 0x1, 0, 0}, -+ {0x47, 0x4, 0x4, 0, 0}, -+ {0x48, 0xf, 0xf, 0, 0}, -+ {0x49, 0x30, 0x30, 0, 0}, -+ {0x4A, 0x32, 0x32, 0, 0}, -+ {0x4B, 0xd, 0xd, 0, 0}, -+ {0x4C, 0xd, 0xd, 0, 0}, -+ {0x4D, 0x4, 0x4, 0, 0}, -+ {0x4E, 0x6, 0x6, 0, 0}, -+ {0x4F, 0x1, 0x1, 0, 0}, -+ {0x50, 0x1c, 0x1c, 0, 0}, -+ {0x51, 0x2, 0x2, 0, 0}, -+ {0x52, 0x2, 0x2, 0, 0}, -+ {0x53, 0xf7, 0xf7, 1, 1}, -+ {0x54, 0xb4, 0xb4, 0, 0}, -+ {0x55, 0xd2, 0xd2, 0, 0}, -+ {0x56, 0, 0, 0, 0}, -+ {0x57, 0, 0, 0, 0}, -+ {0x58, 0x4, 0x4, 0, 0}, -+ {0x59, 0x96, 0x96, 0, 0}, -+ {0x5A, 0x3e, 0x3e, 0, 0}, -+ {0x5B, 0x3e, 0x3e, 0, 0}, -+ {0x5C, 0x13, 0x13, 0, 0}, -+ {0x5D, 0x2, 0x2, 0, 0}, -+ {0x5E, 0, 0, 0, 0}, -+ {0x5F, 0x7, 0x7, 0, 0}, -+ {0x60, 0x7, 0x7, 1, 1}, -+ {0x61, 0x8, 0x8, 0, 0}, -+ {0x62, 0x3, 0x3, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0, 0, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 0, 0}, -+ {0x68, 0x40, 0x40, 0, 0}, -+ {0x69, 0, 0, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0, 0, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0x1, 0x1, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0x60, 0x60, 0, 0}, -+ {0x71, 0x66, 0x66, 0, 0}, -+ {0x72, 0xc, 0xc, 0, 0}, -+ {0x73, 0x66, 0x66, 0, 0}, -+ {0x74, 0x8f, 0x8f, 1, 1}, -+ {0x75, 0, 0, 0, 0}, -+ {0x76, 0xcc, 0xcc, 0, 0}, -+ {0x77, 0x1, 0x1, 0, 0}, -+ {0x78, 0x66, 0x66, 0, 0}, -+ {0x79, 0x66, 0x66, 0, 0}, -+ {0x7A, 0, 0, 0, 0}, -+ {0x7B, 0, 0, 0, 0}, -+ {0x7C, 0, 0, 0, 0}, -+ {0x7D, 0, 0, 0, 0}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0xff, 0xff, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0, 0, 0, 0}, -+ {0x94, 0, 0, 0, 0}, -+ {0x95, 0, 0, 0, 0}, -+ {0x96, 0, 0, 0, 0}, -+ {0x97, 0, 0, 0, 0}, -+ {0x98, 0, 0, 0, 0}, -+ {0x99, 0, 0, 0, 0}, -+ {0x9A, 0, 0, 0, 0}, -+ {0x9B, 0, 0, 0, 0}, -+ {0x9C, 0, 0, 0, 0}, -+ {0x9D, 0, 0, 0, 0}, -+ {0x9E, 0, 0, 0, 0}, -+ {0x9F, 0x6, 0x6, 0, 0}, -+ {0xA0, 0x66, 0x66, 0, 0}, -+ {0xA1, 0x66, 0x66, 0, 0}, -+ {0xA2, 0x66, 0x66, 0, 0}, -+ {0xA3, 0x66, 0x66, 0, 0}, -+ {0xA4, 0x66, 0x66, 0, 0}, -+ {0xA5, 0x66, 0x66, 0, 0}, -+ {0xA6, 0x66, 0x66, 0, 0}, -+ {0xA7, 0x66, 0x66, 0, 0}, -+ {0xA8, 0x66, 0x66, 0, 0}, -+ {0xA9, 0x66, 0x66, 0, 0}, -+ {0xAA, 0x66, 0x66, 0, 0}, -+ {0xAB, 0x66, 0x66, 0, 0}, -+ {0xAC, 0x66, 0x66, 0, 0}, -+ {0xAD, 0x66, 0x66, 0, 0}, -+ {0xAE, 0x66, 0x66, 0, 0}, -+ {0xAF, 0x66, 0x66, 0, 0}, -+ {0xB0, 0x66, 0x66, 0, 0}, -+ {0xB1, 0x66, 0x66, 0, 0}, -+ {0xB2, 0x66, 0x66, 0, 0}, -+ {0xB3, 0xa, 0xa, 0, 0}, -+ {0xB4, 0, 0, 0, 0}, -+ {0xB5, 0, 0, 0, 0}, -+ {0xB6, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0}, -+}; -+ -+static struct radio_regs regs_TX_2056_rev8[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0, 0, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0, 0, 0, 0}, -+ {0x21, 0x88, 0x88, 0, 0}, -+ {0x22, 0x88, 0x88, 0, 0}, -+ {0x23, 0x88, 0x88, 0, 0}, -+ {0x24, 0x88, 0x88, 0, 0}, -+ {0x25, 0xc, 0xc, 0, 0}, -+ {0x26, 0, 0, 0, 0}, -+ {0x27, 0x3, 0x3, 0, 0}, -+ {0x28, 0, 0, 0, 0}, -+ {0x29, 0x3, 0x3, 0, 0}, -+ {0x2A, 0x37, 0x37, 0, 0}, -+ {0x2B, 0x3, 0x3, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0, 0, 0, 0}, -+ {0x2E, 0x1, 0x1, 0, 0}, -+ {0x2F, 0x1, 0x1, 0, 0}, -+ {0x30, 0, 0, 0, 0}, -+ {0x31, 0, 0, 0, 0}, -+ {0x32, 0, 0, 0, 0}, -+ {0x33, 0x11, 0x11, 0, 0}, -+ {0x34, 0xee, 0xee, 1, 1}, -+ {0x35, 0, 0, 0, 0}, -+ {0x36, 0, 0, 0, 0}, -+ {0x37, 0x3, 0x3, 0, 0}, -+ {0x38, 0x50, 0x50, 1, 1}, -+ {0x39, 0, 0, 0, 0}, -+ {0x3A, 0x50, 0x50, 1, 1}, -+ {0x3B, 0, 0, 0, 0}, -+ {0x3C, 0x6e, 0x6e, 0, 0}, -+ {0x3D, 0xf0, 0xf0, 1, 1}, -+ {0x3E, 0, 0, 0, 0}, -+ {0x3F, 0, 0, 0, 0}, -+ {0x40, 0, 0, 0, 0}, -+ {0x41, 0x3, 0x3, 0, 0}, -+ {0x42, 0x3, 0x3, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x1e, 0x1e, 0, 0}, -+ {0x45, 0, 0, 0, 0}, -+ {0x46, 0x6e, 0x6e, 0, 0}, -+ {0x47, 0xf0, 0xf0, 1, 1}, -+ {0x48, 0, 0, 0, 0}, -+ {0x49, 0x2, 0x2, 0, 0}, -+ {0x4A, 0xff, 0xff, 1, 1}, -+ {0x4B, 0xc, 0xc, 0, 0}, -+ {0x4C, 0, 0, 0, 0}, -+ {0x4D, 0x38, 0x38, 0, 0}, -+ {0x4E, 0x70, 0x70, 1, 1}, -+ {0x4F, 0x2, 0x2, 0, 0}, -+ {0x50, 0x88, 0x88, 0, 0}, -+ {0x51, 0xc, 0xc, 0, 0}, -+ {0x52, 0, 0, 0, 0}, -+ {0x53, 0x8, 0x8, 0, 0}, -+ {0x54, 0x70, 0x70, 1, 1}, -+ {0x55, 0x2, 0x2, 0, 0}, -+ {0x56, 0xff, 0xff, 1, 1}, -+ {0x57, 0, 0, 0, 0}, -+ {0x58, 0x83, 0x83, 0, 0}, -+ {0x59, 0x77, 0x77, 1, 1}, -+ {0x5A, 0, 0, 0, 0}, -+ {0x5B, 0x2, 0x2, 0, 0}, -+ {0x5C, 0x88, 0x88, 0, 0}, -+ {0x5D, 0, 0, 0, 0}, -+ {0x5E, 0x8, 0x8, 0, 0}, -+ {0x5F, 0x77, 0x77, 1, 1}, -+ {0x60, 0x1, 0x1, 0, 0}, -+ {0x61, 0, 0, 0, 0}, -+ {0x62, 0x7, 0x7, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0x7, 0x7, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 1, 1}, -+ {0x68, 0, 0, 0, 0}, -+ {0x69, 0xa, 0xa, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0, 0, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0, 0, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0, 0, 0, 0}, -+ {0x71, 0x2, 0x2, 0, 0}, -+ {0x72, 0, 0, 0, 0}, -+ {0x73, 0, 0, 0, 0}, -+ {0x74, 0xe, 0xe, 0, 0}, -+ {0x75, 0xe, 0xe, 0, 0}, -+ {0x76, 0xe, 0xe, 0, 0}, -+ {0x77, 0x13, 0x13, 0, 0}, -+ {0x78, 0x13, 0x13, 0, 0}, -+ {0x79, 0x1b, 0x1b, 0, 0}, -+ {0x7A, 0x1b, 0x1b, 0, 0}, -+ {0x7B, 0x55, 0x55, 0, 0}, -+ {0x7C, 0x5b, 0x5b, 0, 0}, -+ {0x7D, 0x30, 0x30, 1, 1}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0, 0, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0x70, 0x70, 0, 0}, -+ {0x94, 0x70, 0x70, 0, 0}, -+ {0x95, 0x70, 0x70, 0, 0}, -+ {0x96, 0x70, 0x70, 0, 0}, -+ {0x97, 0x70, 0x70, 0, 0}, -+ {0x98, 0x70, 0x70, 0, 0}, -+ {0x99, 0x70, 0x70, 0, 0}, -+ {0x9A, 0x70, 0x70, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0}, -+}; -+ -+static struct radio_regs regs_RX_2056_rev8[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0, 0, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0x3, 0x3, 0, 0}, -+ {0x21, 0, 0, 0, 0}, -+ {0x22, 0, 0, 0, 0}, -+ {0x23, 0x90, 0x90, 0, 0}, -+ {0x24, 0x55, 0x55, 0, 0}, -+ {0x25, 0x15, 0x15, 0, 0}, -+ {0x26, 0x5, 0x5, 0, 0}, -+ {0x27, 0x15, 0x15, 0, 0}, -+ {0x28, 0x5, 0x5, 0, 0}, -+ {0x29, 0x20, 0x20, 0, 0}, -+ {0x2A, 0x11, 0x11, 0, 0}, -+ {0x2B, 0x90, 0x90, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0x88, 0x88, 0, 0}, -+ {0x2E, 0x32, 0x32, 0, 0}, -+ {0x2F, 0x77, 0x77, 0, 0}, -+ {0x30, 0x17, 0x17, 1, 1}, -+ {0x31, 0xff, 0xff, 1, 1}, -+ {0x32, 0x20, 0x20, 0, 0}, -+ {0x33, 0, 0, 0, 0}, -+ {0x34, 0x88, 0x88, 0, 0}, -+ {0x35, 0x32, 0x32, 0, 0}, -+ {0x36, 0x77, 0x77, 0, 0}, -+ {0x37, 0x17, 0x17, 1, 1}, -+ {0x38, 0xf0, 0xf0, 1, 1}, -+ {0x39, 0x20, 0x20, 0, 0}, -+ {0x3A, 0x8, 0x8, 0, 0}, -+ {0x3B, 0x55, 0x55, 1, 1}, -+ {0x3C, 0, 0, 0, 0}, -+ {0x3D, 0x88, 0x88, 1, 1}, -+ {0x3E, 0, 0, 0, 0}, -+ {0x3F, 0x44, 0x44, 0, 0}, -+ {0x40, 0x7, 0x7, 1, 1}, -+ {0x41, 0x6, 0x6, 0, 0}, -+ {0x42, 0x4, 0x4, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x8, 0x8, 0, 0}, -+ {0x45, 0x55, 0x55, 1, 1}, -+ {0x46, 0, 0, 0, 0}, -+ {0x47, 0x11, 0x11, 0, 0}, -+ {0x48, 0, 0, 0, 0}, -+ {0x49, 0x44, 0x44, 0, 0}, -+ {0x4A, 0x7, 0x7, 0, 0}, -+ {0x4B, 0x6, 0x6, 0, 0}, -+ {0x4C, 0x4, 0x4, 0, 0}, -+ {0x4D, 0, 0, 0, 0}, -+ {0x4E, 0, 0, 0, 0}, -+ {0x4F, 0x26, 0x26, 1, 1}, -+ {0x50, 0x26, 0x26, 1, 1}, -+ {0x51, 0xf, 0xf, 1, 1}, -+ {0x52, 0xf, 0xf, 1, 1}, -+ {0x53, 0x44, 0x44, 0, 0}, -+ {0x54, 0, 0, 0, 0}, -+ {0x55, 0, 0, 0, 0}, -+ {0x56, 0x8, 0x8, 0, 0}, -+ {0x57, 0x8, 0x8, 0, 0}, -+ {0x58, 0x7, 0x7, 0, 0}, -+ {0x59, 0x22, 0x22, 0, 0}, -+ {0x5A, 0x22, 0x22, 0, 0}, -+ {0x5B, 0x2, 0x2, 0, 0}, -+ {0x5C, 0x4, 0x4, 1, 1}, -+ {0x5D, 0x7, 0x7, 0, 0}, -+ {0x5E, 0x55, 0x55, 0, 0}, -+ {0x5F, 0x23, 0x23, 0, 0}, -+ {0x60, 0x41, 0x41, 0, 0}, -+ {0x61, 0x1, 0x1, 0, 0}, -+ {0x62, 0xa, 0xa, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0, 0, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 0, 0}, -+ {0x68, 0, 0, 0, 0}, -+ {0x69, 0, 0, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0xc, 0xc, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0, 0, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0, 0, 0, 0}, -+ {0x71, 0, 0, 0, 0}, -+ {0x72, 0x22, 0x22, 0, 0}, -+ {0x73, 0x22, 0x22, 0, 0}, -+ {0x74, 0, 0, 1, 1}, -+ {0x75, 0xa, 0xa, 0, 0}, -+ {0x76, 0x1, 0x1, 0, 0}, -+ {0x77, 0x22, 0x22, 0, 0}, -+ {0x78, 0x30, 0x30, 0, 0}, -+ {0x79, 0, 0, 0, 0}, -+ {0x7A, 0, 0, 0, 0}, -+ {0x7B, 0, 0, 0, 0}, -+ {0x7C, 0, 0, 0, 0}, -+ {0x7D, 0x5, 0x5, 1, 1}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0, 0, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0, 0, 0, 0}, -+ {0x94, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0}, -+}; -+ -+static const struct radio_regs regs_SYN_2056_rev11[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0x1, 0x1, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0, 0, 0, 0}, -+ {0x21, 0, 0, 0, 0}, -+ {0x22, 0x60, 0x60, 0, 0}, -+ {0x23, 0x6, 0x6, 0, 0}, -+ {0x24, 0xc, 0xc, 0, 0}, -+ {0x25, 0, 0, 0, 0}, -+ {0x26, 0, 0, 0, 0}, -+ {0x27, 0, 0, 0, 0}, -+ {0x28, 0x1, 0x1, 0, 0}, -+ {0x29, 0, 0, 0, 0}, -+ {0x2A, 0, 0, 0, 0}, -+ {0x2B, 0, 0, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0, 0, 0, 0}, -+ {0x2E, 0, 0, 0, 0}, -+ {0x2F, 0x1f, 0x1f, 0, 0}, -+ {0x30, 0x15, 0x15, 0, 0}, -+ {0x31, 0xf, 0xf, 0, 0}, -+ {0x32, 0, 0, 0, 0}, -+ {0x33, 0, 0, 0, 0}, -+ {0x34, 0, 0, 0, 0}, -+ {0x35, 0, 0, 0, 0}, -+ {0x36, 0, 0, 0, 0}, -+ {0x37, 0, 0, 0, 0}, -+ {0x38, 0, 0, 0, 0}, -+ {0x39, 0, 0, 0, 0}, -+ {0x3A, 0, 0, 0, 0}, -+ {0x3B, 0, 0, 0, 0}, -+ {0x3C, 0x13, 0x13, 0, 0}, -+ {0x3D, 0xf, 0xf, 0, 0}, -+ {0x3E, 0x18, 0x18, 0, 0}, -+ {0x3F, 0, 0, 0, 0}, -+ {0x40, 0, 0, 0, 0}, -+ {0x41, 0x20, 0x20, 0, 0}, -+ {0x42, 0x20, 0x20, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x77, 0x77, 0, 0}, -+ {0x45, 0x7, 0x7, 0, 0}, -+ {0x46, 0x1, 0x1, 0, 0}, -+ {0x47, 0x6, 0x6, 1, 1}, -+ {0x48, 0xf, 0xf, 0, 0}, -+ {0x49, 0x3f, 0x3f, 1, 1}, -+ {0x4A, 0x32, 0x32, 0, 0}, -+ {0x4B, 0x6, 0x6, 1, 1}, -+ {0x4C, 0x6, 0x6, 1, 1}, -+ {0x4D, 0x4, 0x4, 0, 0}, -+ {0x4E, 0x2b, 0x2b, 1, 1}, -+ {0x4F, 0x1, 0x1, 0, 0}, -+ {0x50, 0x1c, 0x1c, 0, 0}, -+ {0x51, 0x2, 0x2, 0, 0}, -+ {0x52, 0x2, 0x2, 0, 0}, -+ {0x53, 0xf7, 0xf7, 1, 1}, -+ {0x54, 0xb4, 0xb4, 0, 0}, -+ {0x55, 0xd2, 0xd2, 0, 0}, -+ {0x56, 0, 0, 0, 0}, -+ {0x57, 0, 0, 0, 0}, -+ {0x58, 0x4, 0x4, 0, 0}, -+ {0x59, 0x96, 0x96, 0, 0}, -+ {0x5A, 0x3e, 0x3e, 0, 0}, -+ {0x5B, 0x3e, 0x3e, 0, 0}, -+ {0x5C, 0x13, 0x13, 0, 0}, -+ {0x5D, 0x2, 0x2, 0, 0}, -+ {0x5E, 0, 0, 0, 0}, -+ {0x5F, 0x7, 0x7, 0, 0}, -+ {0x60, 0x7, 0x7, 1, 1}, -+ {0x61, 0x8, 0x8, 0, 0}, -+ {0x62, 0x3, 0x3, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0, 0, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 0, 0}, -+ {0x68, 0x40, 0x40, 0, 0}, -+ {0x69, 0, 0, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0, 0, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0x1, 0x1, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0x60, 0x60, 0, 0}, -+ {0x71, 0x66, 0x66, 0, 0}, -+ {0x72, 0xc, 0xc, 0, 0}, -+ {0x73, 0x66, 0x66, 0, 0}, -+ {0x74, 0x8f, 0x8f, 1, 1}, -+ {0x75, 0, 0, 0, 0}, -+ {0x76, 0xcc, 0xcc, 0, 0}, -+ {0x77, 0x1, 0x1, 0, 0}, -+ {0x78, 0x66, 0x66, 0, 0}, -+ {0x79, 0x66, 0x66, 0, 0}, -+ {0x7A, 0, 0, 0, 0}, -+ {0x7B, 0, 0, 0, 0}, -+ {0x7C, 0, 0, 0, 0}, -+ {0x7D, 0, 0, 0, 0}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0xff, 0xff, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0, 0, 0, 0}, -+ {0x94, 0, 0, 0, 0}, -+ {0x95, 0, 0, 0, 0}, -+ {0x96, 0, 0, 0, 0}, -+ {0x97, 0, 0, 0, 0}, -+ {0x98, 0, 0, 0, 0}, -+ {0x99, 0, 0, 0, 0}, -+ {0x9A, 0, 0, 0, 0}, -+ {0x9B, 0, 0, 0, 0}, -+ {0x9C, 0, 0, 0, 0}, -+ {0x9D, 0, 0, 0, 0}, -+ {0x9E, 0, 0, 0, 0}, -+ {0x9F, 0x6, 0x6, 0, 0}, -+ {0xA0, 0x66, 0x66, 0, 0}, -+ {0xA1, 0x66, 0x66, 0, 0}, -+ {0xA2, 0x66, 0x66, 0, 0}, -+ {0xA3, 0x66, 0x66, 0, 0}, -+ {0xA4, 0x66, 0x66, 0, 0}, -+ {0xA5, 0x66, 0x66, 0, 0}, -+ {0xA6, 0x66, 0x66, 0, 0}, -+ {0xA7, 0x66, 0x66, 0, 0}, -+ {0xA8, 0x66, 0x66, 0, 0}, -+ {0xA9, 0x66, 0x66, 0, 0}, -+ {0xAA, 0x66, 0x66, 0, 0}, -+ {0xAB, 0x66, 0x66, 0, 0}, -+ {0xAC, 0x66, 0x66, 0, 0}, -+ {0xAD, 0x66, 0x66, 0, 0}, -+ {0xAE, 0x66, 0x66, 0, 0}, -+ {0xAF, 0x66, 0x66, 0, 0}, -+ {0xB0, 0x66, 0x66, 0, 0}, -+ {0xB1, 0x66, 0x66, 0, 0}, -+ {0xB2, 0x66, 0x66, 0, 0}, -+ {0xB3, 0xa, 0xa, 0, 0}, -+ {0xB4, 0, 0, 0, 0}, -+ {0xB5, 0, 0, 0, 0}, -+ {0xB6, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0}, -+}; -+ -+static const struct radio_regs regs_TX_2056_rev11[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0, 0, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0, 0, 0, 0}, -+ {0x21, 0x88, 0x88, 0, 0}, -+ {0x22, 0x88, 0x88, 0, 0}, -+ {0x23, 0x88, 0x88, 0, 0}, -+ {0x24, 0x88, 0x88, 0, 0}, -+ {0x25, 0xc, 0xc, 0, 0}, -+ {0x26, 0, 0, 0, 0}, -+ {0x27, 0x3, 0x3, 0, 0}, -+ {0x28, 0, 0, 0, 0}, -+ {0x29, 0x3, 0x3, 0, 0}, -+ {0x2A, 0x37, 0x37, 0, 0}, -+ {0x2B, 0x3, 0x3, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0, 0, 0, 0}, -+ {0x2E, 0x1, 0x1, 0, 0}, -+ {0x2F, 0x1, 0x1, 0, 0}, -+ {0x30, 0, 0, 0, 0}, -+ {0x31, 0, 0, 0, 0}, -+ {0x32, 0, 0, 0, 0}, -+ {0x33, 0x11, 0x11, 0, 0}, -+ {0x34, 0xee, 0xee, 1, 1}, -+ {0x35, 0, 0, 0, 0}, -+ {0x36, 0, 0, 0, 0}, -+ {0x37, 0x3, 0x3, 0, 0}, -+ {0x38, 0x50, 0x50, 1, 1}, -+ {0x39, 0, 0, 0, 0}, -+ {0x3A, 0x50, 0x50, 1, 1}, -+ {0x3B, 0, 0, 0, 0}, -+ {0x3C, 0x6e, 0x6e, 0, 0}, -+ {0x3D, 0xf0, 0xf0, 1, 1}, -+ {0x3E, 0, 0, 0, 0}, -+ {0x3F, 0, 0, 0, 0}, -+ {0x40, 0, 0, 0, 0}, -+ {0x41, 0x3, 0x3, 0, 0}, -+ {0x42, 0x3, 0x3, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x1e, 0x1e, 0, 0}, -+ {0x45, 0, 0, 0, 0}, -+ {0x46, 0x6e, 0x6e, 0, 0}, -+ {0x47, 0xf0, 0xf0, 1, 1}, -+ {0x48, 0, 0, 0, 0}, -+ {0x49, 0x2, 0x2, 0, 0}, -+ {0x4A, 0xff, 0xff, 1, 1}, -+ {0x4B, 0xc, 0xc, 0, 0}, -+ {0x4C, 0, 0, 0, 0}, -+ {0x4D, 0x38, 0x38, 0, 0}, -+ {0x4E, 0x70, 0x70, 1, 1}, -+ {0x4F, 0x2, 0x2, 0, 0}, -+ {0x50, 0x88, 0x88, 0, 0}, -+ {0x51, 0xc, 0xc, 0, 0}, -+ {0x52, 0, 0, 0, 0}, -+ {0x53, 0x8, 0x8, 0, 0}, -+ {0x54, 0x70, 0x70, 1, 1}, -+ {0x55, 0x2, 0x2, 0, 0}, -+ {0x56, 0xff, 0xff, 1, 1}, -+ {0x57, 0, 0, 0, 0}, -+ {0x58, 0x83, 0x83, 0, 0}, -+ {0x59, 0x77, 0x77, 1, 1}, -+ {0x5A, 0, 0, 0, 0}, -+ {0x5B, 0x2, 0x2, 0, 0}, -+ {0x5C, 0x88, 0x88, 0, 0}, -+ {0x5D, 0, 0, 0, 0}, -+ {0x5E, 0x8, 0x8, 0, 0}, -+ {0x5F, 0x77, 0x77, 1, 1}, -+ {0x60, 0x1, 0x1, 0, 0}, -+ {0x61, 0, 0, 0, 0}, -+ {0x62, 0x7, 0x7, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0x7, 0x7, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 1, 1}, -+ {0x68, 0, 0, 0, 0}, -+ {0x69, 0xa, 0xa, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0, 0, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0, 0, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0, 0, 0, 0}, -+ {0x71, 0x2, 0x2, 0, 0}, -+ {0x72, 0, 0, 0, 0}, -+ {0x73, 0, 0, 0, 0}, -+ {0x74, 0xe, 0xe, 0, 0}, -+ {0x75, 0xe, 0xe, 0, 0}, -+ {0x76, 0xe, 0xe, 0, 0}, -+ {0x77, 0x13, 0x13, 0, 0}, -+ {0x78, 0x13, 0x13, 0, 0}, -+ {0x79, 0x1b, 0x1b, 0, 0}, -+ {0x7A, 0x1b, 0x1b, 0, 0}, -+ {0x7B, 0x55, 0x55, 0, 0}, -+ {0x7C, 0x5b, 0x5b, 0, 0}, -+ {0x7D, 0x30, 0x30, 1, 1}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0, 0, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0x70, 0x70, 0, 0}, -+ {0x94, 0x70, 0x70, 0, 0}, -+ {0x95, 0x70, 0x70, 0, 0}, -+ {0x96, 0x70, 0x70, 0, 0}, -+ {0x97, 0x70, 0x70, 0, 0}, -+ {0x98, 0x70, 0x70, 0, 0}, -+ {0x99, 0x70, 0x70, 0, 0}, -+ {0x9A, 0x70, 0x70, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0}, -+}; -+ -+static const struct radio_regs regs_RX_2056_rev11[] = { -+ {0x02, 0, 0, 0, 0}, -+ {0x03, 0, 0, 0, 0}, -+ {0x04, 0, 0, 0, 0}, -+ {0x05, 0, 0, 0, 0}, -+ {0x06, 0, 0, 0, 0}, -+ {0x07, 0, 0, 0, 0}, -+ {0x08, 0, 0, 0, 0}, -+ {0x09, 0, 0, 0, 0}, -+ {0x0A, 0, 0, 0, 0}, -+ {0x0B, 0, 0, 0, 0}, -+ {0x0C, 0, 0, 0, 0}, -+ {0x0D, 0, 0, 0, 0}, -+ {0x0E, 0, 0, 0, 0}, -+ {0x0F, 0, 0, 0, 0}, -+ {0x10, 0, 0, 0, 0}, -+ {0x11, 0, 0, 0, 0}, -+ {0x12, 0, 0, 0, 0}, -+ {0x13, 0, 0, 0, 0}, -+ {0x14, 0, 0, 0, 0}, -+ {0x15, 0, 0, 0, 0}, -+ {0x16, 0, 0, 0, 0}, -+ {0x17, 0, 0, 0, 0}, -+ {0x18, 0, 0, 0, 0}, -+ {0x19, 0, 0, 0, 0}, -+ {0x1A, 0, 0, 0, 0}, -+ {0x1B, 0, 0, 0, 0}, -+ {0x1C, 0, 0, 0, 0}, -+ {0x1D, 0, 0, 0, 0}, -+ {0x1E, 0, 0, 0, 0}, -+ {0x1F, 0, 0, 0, 0}, -+ {0x20, 0x3, 0x3, 0, 0}, -+ {0x21, 0, 0, 0, 0}, -+ {0x22, 0, 0, 0, 0}, -+ {0x23, 0x90, 0x90, 0, 0}, -+ {0x24, 0x55, 0x55, 0, 0}, -+ {0x25, 0x15, 0x15, 0, 0}, -+ {0x26, 0x5, 0x5, 0, 0}, -+ {0x27, 0x15, 0x15, 0, 0}, -+ {0x28, 0x5, 0x5, 0, 0}, -+ {0x29, 0x20, 0x20, 0, 0}, -+ {0x2A, 0x11, 0x11, 0, 0}, -+ {0x2B, 0x90, 0x90, 0, 0}, -+ {0x2C, 0, 0, 0, 0}, -+ {0x2D, 0x88, 0x88, 0, 0}, -+ {0x2E, 0x32, 0x32, 0, 0}, -+ {0x2F, 0x77, 0x77, 0, 0}, -+ {0x30, 0x17, 0x17, 1, 1}, -+ {0x31, 0xff, 0xff, 1, 1}, -+ {0x32, 0x20, 0x20, 0, 0}, -+ {0x33, 0, 0, 0, 0}, -+ {0x34, 0x88, 0x88, 0, 0}, -+ {0x35, 0x32, 0x32, 0, 0}, -+ {0x36, 0x77, 0x77, 0, 0}, -+ {0x37, 0x17, 0x17, 1, 1}, -+ {0x38, 0xf0, 0xf0, 1, 1}, -+ {0x39, 0x20, 0x20, 0, 0}, -+ {0x3A, 0x8, 0x8, 0, 0}, -+ {0x3B, 0x55, 0x55, 1, 1}, -+ {0x3C, 0, 0, 0, 0}, -+ {0x3D, 0x88, 0x88, 1, 1}, -+ {0x3E, 0, 0, 0, 0}, -+ {0x3F, 0x44, 0x44, 0, 0}, -+ {0x40, 0x7, 0x7, 1, 1}, -+ {0x41, 0x6, 0x6, 0, 0}, -+ {0x42, 0x4, 0x4, 0, 0}, -+ {0x43, 0, 0, 0, 0}, -+ {0x44, 0x8, 0x8, 0, 0}, -+ {0x45, 0x55, 0x55, 1, 1}, -+ {0x46, 0, 0, 0, 0}, -+ {0x47, 0x11, 0x11, 0, 0}, -+ {0x48, 0, 0, 0, 0}, -+ {0x49, 0x44, 0x44, 0, 0}, -+ {0x4A, 0x7, 0x7, 0, 0}, -+ {0x4B, 0x6, 0x6, 0, 0}, -+ {0x4C, 0x4, 0x4, 0, 0}, -+ {0x4D, 0, 0, 0, 0}, -+ {0x4E, 0, 0, 0, 0}, -+ {0x4F, 0x26, 0x26, 1, 1}, -+ {0x50, 0x26, 0x26, 1, 1}, -+ {0x51, 0xf, 0xf, 1, 1}, -+ {0x52, 0xf, 0xf, 1, 1}, -+ {0x53, 0x44, 0x44, 0, 0}, -+ {0x54, 0, 0, 0, 0}, -+ {0x55, 0, 0, 0, 0}, -+ {0x56, 0x8, 0x8, 0, 0}, -+ {0x57, 0x8, 0x8, 0, 0}, -+ {0x58, 0x7, 0x7, 0, 0}, -+ {0x59, 0x22, 0x22, 0, 0}, -+ {0x5A, 0x22, 0x22, 0, 0}, -+ {0x5B, 0x2, 0x2, 0, 0}, -+ {0x5C, 0x4, 0x4, 1, 1}, -+ {0x5D, 0x7, 0x7, 0, 0}, -+ {0x5E, 0x55, 0x55, 0, 0}, -+ {0x5F, 0x23, 0x23, 0, 0}, -+ {0x60, 0x41, 0x41, 0, 0}, -+ {0x61, 0x1, 0x1, 0, 0}, -+ {0x62, 0xa, 0xa, 0, 0}, -+ {0x63, 0, 0, 0, 0}, -+ {0x64, 0, 0, 0, 0}, -+ {0x65, 0, 0, 0, 0}, -+ {0x66, 0, 0, 0, 0}, -+ {0x67, 0, 0, 0, 0}, -+ {0x68, 0, 0, 0, 0}, -+ {0x69, 0, 0, 0, 0}, -+ {0x6A, 0, 0, 0, 0}, -+ {0x6B, 0xc, 0xc, 0, 0}, -+ {0x6C, 0, 0, 0, 0}, -+ {0x6D, 0, 0, 0, 0}, -+ {0x6E, 0, 0, 0, 0}, -+ {0x6F, 0, 0, 0, 0}, -+ {0x70, 0, 0, 0, 0}, -+ {0x71, 0, 0, 0, 0}, -+ {0x72, 0x22, 0x22, 0, 0}, -+ {0x73, 0x22, 0x22, 0, 0}, -+ {0x74, 0, 0, 1, 1}, -+ {0x75, 0xa, 0xa, 0, 0}, -+ {0x76, 0x1, 0x1, 0, 0}, -+ {0x77, 0x22, 0x22, 0, 0}, -+ {0x78, 0x30, 0x30, 0, 0}, -+ {0x79, 0, 0, 0, 0}, -+ {0x7A, 0, 0, 0, 0}, -+ {0x7B, 0, 0, 0, 0}, -+ {0x7C, 0, 0, 0, 0}, -+ {0x7D, 0x5, 0x5, 1, 1}, -+ {0x7E, 0, 0, 0, 0}, -+ {0x7F, 0, 0, 0, 0}, -+ {0x80, 0, 0, 0, 0}, -+ {0x81, 0, 0, 0, 0}, -+ {0x82, 0, 0, 0, 0}, -+ {0x83, 0, 0, 0, 0}, -+ {0x84, 0, 0, 0, 0}, -+ {0x85, 0, 0, 0, 0}, -+ {0x86, 0, 0, 0, 0}, -+ {0x87, 0, 0, 0, 0}, -+ {0x88, 0, 0, 0, 0}, -+ {0x89, 0, 0, 0, 0}, -+ {0x8A, 0, 0, 0, 0}, -+ {0x8B, 0, 0, 0, 0}, -+ {0x8C, 0, 0, 0, 0}, -+ {0x8D, 0, 0, 0, 0}, -+ {0x8E, 0, 0, 0, 0}, -+ {0x8F, 0, 0, 0, 0}, -+ {0x90, 0, 0, 0, 0}, -+ {0x91, 0, 0, 0, 0}, -+ {0x92, 0, 0, 0, 0}, -+ {0x93, 0, 0, 0, 0}, -+ {0x94, 0, 0, 0, 0}, -+ {0xFFFF, 0, 0, 0, 0}, -+}; -+ -+static struct radio_20xx_regs regs_2057_rev4[] = { -+ {0x00, 0x84, 0}, -+ {0x01, 0, 0}, -+ {0x02, 0x60, 0}, -+ {0x03, 0x1f, 0}, -+ {0x04, 0x4, 0}, -+ {0x05, 0x2, 0}, -+ {0x06, 0x1, 0}, -+ {0x07, 0x1, 0}, -+ {0x08, 0x1, 0}, -+ {0x09, 0x69, 0}, -+ {0x0A, 0x66, 0}, -+ {0x0B, 0x6, 0}, -+ {0x0C, 0x18, 0}, -+ {0x0D, 0x3, 0}, -+ {0x0E, 0x20, 1}, -+ {0x0F, 0x20, 0}, -+ {0x10, 0, 0}, -+ {0x11, 0x7c, 0}, -+ {0x12, 0x42, 0}, -+ {0x13, 0xbd, 0}, -+ {0x14, 0x7, 0}, -+ {0x15, 0xf7, 0}, -+ {0x16, 0x8, 0}, -+ {0x17, 0x17, 0}, -+ {0x18, 0x7, 0}, -+ {0x19, 0, 0}, -+ {0x1A, 0x2, 0}, -+ {0x1B, 0x13, 0}, -+ {0x1C, 0x3e, 0}, -+ {0x1D, 0x3e, 0}, -+ {0x1E, 0x96, 0}, -+ {0x1F, 0x4, 0}, -+ {0x20, 0, 0}, -+ {0x21, 0, 0}, -+ {0x22, 0x17, 0}, -+ {0x23, 0x4, 0}, -+ {0x24, 0x1, 0}, -+ {0x25, 0x6, 0}, -+ {0x26, 0x4, 0}, -+ {0x27, 0xd, 0}, -+ {0x28, 0xd, 0}, -+ {0x29, 0x30, 0}, -+ {0x2A, 0x32, 0}, -+ {0x2B, 0x8, 0}, -+ {0x2C, 0x1c, 0}, -+ {0x2D, 0x2, 0}, -+ {0x2E, 0x4, 0}, -+ {0x2F, 0x7f, 0}, -+ {0x30, 0x27, 0}, -+ {0x31, 0, 1}, -+ {0x32, 0, 1}, -+ {0x33, 0, 1}, -+ {0x34, 0, 0}, -+ {0x35, 0x26, 1}, -+ {0x36, 0x18, 0}, -+ {0x37, 0x7, 0}, -+ {0x38, 0x66, 0}, -+ {0x39, 0x66, 0}, -+ {0x3A, 0x66, 0}, -+ {0x3B, 0x66, 0}, -+ {0x3C, 0xff, 1}, -+ {0x3D, 0xff, 1}, -+ {0x3E, 0xff, 1}, -+ {0x3F, 0xff, 1}, -+ {0x40, 0x16, 0}, -+ {0x41, 0x7, 0}, -+ {0x42, 0x19, 0}, -+ {0x43, 0x7, 0}, -+ {0x44, 0x6, 0}, -+ {0x45, 0x3, 0}, -+ {0x46, 0x1, 0}, -+ {0x47, 0x7, 0}, -+ {0x48, 0x33, 0}, -+ {0x49, 0x5, 0}, -+ {0x4A, 0x77, 0}, -+ {0x4B, 0x66, 0}, -+ {0x4C, 0x66, 0}, -+ {0x4D, 0, 0}, -+ {0x4E, 0x4, 0}, -+ {0x4F, 0xc, 0}, -+ {0x50, 0, 0}, -+ {0x51, 0x75, 0}, -+ {0x56, 0x7, 0}, -+ {0x57, 0, 0}, -+ {0x58, 0, 0}, -+ {0x59, 0xa8, 0}, -+ {0x5A, 0, 0}, -+ {0x5B, 0x1f, 0}, -+ {0x5C, 0x30, 0}, -+ {0x5D, 0x1, 0}, -+ {0x5E, 0x30, 0}, -+ {0x5F, 0x70, 0}, -+ {0x60, 0, 0}, -+ {0x61, 0, 0}, -+ {0x62, 0x33, 1}, -+ {0x63, 0x19, 0}, -+ {0x64, 0x62, 0}, -+ {0x65, 0, 0}, -+ {0x66, 0x11, 0}, -+ {0x69, 0, 0}, -+ {0x6A, 0x7e, 0}, -+ {0x6B, 0x3f, 0}, -+ {0x6C, 0x7f, 0}, -+ {0x6D, 0x78, 0}, -+ {0x6E, 0xc8, 0}, -+ {0x6F, 0x88, 0}, -+ {0x70, 0x8, 0}, -+ {0x71, 0xf, 0}, -+ {0x72, 0xbc, 0}, -+ {0x73, 0x8, 0}, -+ {0x74, 0x60, 0}, -+ {0x75, 0x1e, 0}, -+ {0x76, 0x70, 0}, -+ {0x77, 0, 0}, -+ {0x78, 0, 0}, -+ {0x79, 0, 0}, -+ {0x7A, 0x33, 0}, -+ {0x7B, 0x1e, 0}, -+ {0x7C, 0x62, 0}, -+ {0x7D, 0x11, 0}, -+ {0x80, 0x3c, 0}, -+ {0x81, 0x9c, 0}, -+ {0x82, 0xa, 0}, -+ {0x83, 0x9d, 0}, -+ {0x84, 0xa, 0}, -+ {0x85, 0, 0}, -+ {0x86, 0x40, 0}, -+ {0x87, 0x40, 0}, -+ {0x88, 0x88, 0}, -+ {0x89, 0x10, 0}, -+ {0x8A, 0xf0, 1}, -+ {0x8B, 0x10, 1}, -+ {0x8C, 0xf0, 1}, -+ {0x8D, 0, 0}, -+ {0x8E, 0, 0}, -+ {0x8F, 0x10, 0}, -+ {0x90, 0x55, 0}, -+ {0x91, 0x3f, 1}, -+ {0x92, 0x36, 1}, -+ {0x93, 0, 0}, -+ {0x94, 0, 0}, -+ {0x95, 0, 0}, -+ {0x96, 0x87, 0}, -+ {0x97, 0x11, 0}, -+ {0x98, 0, 0}, -+ {0x99, 0x33, 0}, -+ {0x9A, 0x88, 0}, -+ {0x9B, 0, 0}, -+ {0x9C, 0x87, 0}, -+ {0x9D, 0x11, 0}, -+ {0x9E, 0, 0}, -+ {0x9F, 0x33, 0}, -+ {0xA0, 0x88, 0}, -+ {0xA1, 0xe1, 0}, -+ {0xA2, 0x3f, 0}, -+ {0xA3, 0x44, 0}, -+ {0xA4, 0x8c, 1}, -+ {0xA5, 0x6d, 0}, -+ {0xA6, 0x22, 0}, -+ {0xA7, 0xbe, 0}, -+ {0xA8, 0x55, 1}, -+ {0xA9, 0xc, 0}, -+ {0xAA, 0xc, 0}, -+ {0xAB, 0xaa, 0}, -+ {0xAC, 0x2, 0}, -+ {0xAD, 0, 0}, -+ {0xAE, 0x10, 0}, -+ {0xAF, 0x1, 1}, -+ {0xB0, 0, 0}, -+ {0xB1, 0, 0}, -+ {0xB2, 0x80, 0}, -+ {0xB3, 0x60, 0}, -+ {0xB4, 0x44, 0}, -+ {0xB5, 0x55, 0}, -+ {0xB6, 0x1, 0}, -+ {0xB7, 0x55, 0}, -+ {0xB8, 0x1, 0}, -+ {0xB9, 0x5, 0}, -+ {0xBA, 0x55, 0}, -+ {0xBB, 0x55, 0}, -+ {0xC1, 0, 0}, -+ {0xC2, 0, 0}, -+ {0xC3, 0, 0}, -+ {0xC4, 0, 0}, -+ {0xC5, 0, 0}, -+ {0xC6, 0, 0}, -+ {0xC7, 0, 0}, -+ {0xC8, 0, 0}, -+ {0xC9, 0, 0}, -+ {0xCA, 0, 0}, -+ {0xCB, 0, 0}, -+ {0xCC, 0, 0}, -+ {0xCD, 0, 0}, -+ {0xCE, 0x5e, 0}, -+ {0xCF, 0xc, 0}, -+ {0xD0, 0xc, 0}, -+ {0xD1, 0xc, 0}, -+ {0xD2, 0, 0}, -+ {0xD3, 0x2b, 0}, -+ {0xD4, 0xc, 0}, -+ {0xD5, 0, 0}, -+ {0xD6, 0x75, 0}, -+ {0xDB, 0x7, 0}, -+ {0xDC, 0, 0}, -+ {0xDD, 0, 0}, -+ {0xDE, 0xa8, 0}, -+ {0xDF, 0, 0}, -+ {0xE0, 0x1f, 0}, -+ {0xE1, 0x30, 0}, -+ {0xE2, 0x1, 0}, -+ {0xE3, 0x30, 0}, -+ {0xE4, 0x70, 0}, -+ {0xE5, 0, 0}, -+ {0xE6, 0, 0}, -+ {0xE7, 0x33, 0}, -+ {0xE8, 0x19, 0}, -+ {0xE9, 0x62, 0}, -+ {0xEA, 0, 0}, -+ {0xEB, 0x11, 0}, -+ {0xEE, 0, 0}, -+ {0xEF, 0x7e, 0}, -+ {0xF0, 0x3f, 0}, -+ {0xF1, 0x7f, 0}, -+ {0xF2, 0x78, 0}, -+ {0xF3, 0xc8, 0}, -+ {0xF4, 0x88, 0}, -+ {0xF5, 0x8, 0}, -+ {0xF6, 0xf, 0}, -+ {0xF7, 0xbc, 0}, -+ {0xF8, 0x8, 0}, -+ {0xF9, 0x60, 0}, -+ {0xFA, 0x1e, 0}, -+ {0xFB, 0x70, 0}, -+ {0xFC, 0, 0}, -+ {0xFD, 0, 0}, -+ {0xFE, 0, 0}, -+ {0xFF, 0x33, 0}, -+ {0x100, 0x1e, 0}, -+ {0x101, 0x62, 0}, -+ {0x102, 0x11, 0}, -+ {0x105, 0x3c, 0}, -+ {0x106, 0x9c, 0}, -+ {0x107, 0xa, 0}, -+ {0x108, 0x9d, 0}, -+ {0x109, 0xa, 0}, -+ {0x10A, 0, 0}, -+ {0x10B, 0x40, 0}, -+ {0x10C, 0x40, 0}, -+ {0x10D, 0x88, 0}, -+ {0x10E, 0x10, 0}, -+ {0x10F, 0xf0, 1}, -+ {0x110, 0x10, 1}, -+ {0x111, 0xf0, 1}, -+ {0x112, 0, 0}, -+ {0x113, 0, 0}, -+ {0x114, 0x10, 0}, -+ {0x115, 0x55, 0}, -+ {0x116, 0x3f, 1}, -+ {0x117, 0x36, 1}, -+ {0x118, 0, 0}, -+ {0x119, 0, 0}, -+ {0x11A, 0, 0}, -+ {0x11B, 0x87, 0}, -+ {0x11C, 0x11, 0}, -+ {0x11D, 0, 0}, -+ {0x11E, 0x33, 0}, -+ {0x11F, 0x88, 0}, -+ {0x120, 0, 0}, -+ {0x121, 0x87, 0}, -+ {0x122, 0x11, 0}, -+ {0x123, 0, 0}, -+ {0x124, 0x33, 0}, -+ {0x125, 0x88, 0}, -+ {0x126, 0xe1, 0}, -+ {0x127, 0x3f, 0}, -+ {0x128, 0x44, 0}, -+ {0x129, 0x8c, 1}, -+ {0x12A, 0x6d, 0}, -+ {0x12B, 0x22, 0}, -+ {0x12C, 0xbe, 0}, -+ {0x12D, 0x55, 1}, -+ {0x12E, 0xc, 0}, -+ {0x12F, 0xc, 0}, -+ {0x130, 0xaa, 0}, -+ {0x131, 0x2, 0}, -+ {0x132, 0, 0}, -+ {0x133, 0x10, 0}, -+ {0x134, 0x1, 1}, -+ {0x135, 0, 0}, -+ {0x136, 0, 0}, -+ {0x137, 0x80, 0}, -+ {0x138, 0x60, 0}, -+ {0x139, 0x44, 0}, -+ {0x13A, 0x55, 0}, -+ {0x13B, 0x1, 0}, -+ {0x13C, 0x55, 0}, -+ {0x13D, 0x1, 0}, -+ {0x13E, 0x5, 0}, -+ {0x13F, 0x55, 0}, -+ {0x140, 0x55, 0}, -+ {0x146, 0, 0}, -+ {0x147, 0, 0}, -+ {0x148, 0, 0}, -+ {0x149, 0, 0}, -+ {0x14A, 0, 0}, -+ {0x14B, 0, 0}, -+ {0x14C, 0, 0}, -+ {0x14D, 0, 0}, -+ {0x14E, 0, 0}, -+ {0x14F, 0, 0}, -+ {0x150, 0, 0}, -+ {0x151, 0, 0}, -+ {0x152, 0, 0}, -+ {0x153, 0, 0}, -+ {0x154, 0xc, 0}, -+ {0x155, 0xc, 0}, -+ {0x156, 0xc, 0}, -+ {0x157, 0, 0}, -+ {0x158, 0x2b, 0}, -+ {0x159, 0x84, 0}, -+ {0x15A, 0x15, 0}, -+ {0x15B, 0xf, 0}, -+ {0x15C, 0, 0}, -+ {0x15D, 0, 0}, -+ {0x15E, 0, 1}, -+ {0x15F, 0, 1}, -+ {0x160, 0, 1}, -+ {0x161, 0, 1}, -+ {0x162, 0, 1}, -+ {0x163, 0, 1}, -+ {0x164, 0, 0}, -+ {0x165, 0, 0}, -+ {0x166, 0, 0}, -+ {0x167, 0, 0}, -+ {0x168, 0, 0}, -+ {0x169, 0x2, 1}, -+ {0x16A, 0, 1}, -+ {0x16B, 0, 1}, -+ {0x16C, 0, 1}, -+ {0x16D, 0, 0}, -+ {0x170, 0, 0}, -+ {0x171, 0x77, 0}, -+ {0x172, 0x77, 0}, -+ {0x173, 0x77, 0}, -+ {0x174, 0x77, 0}, -+ {0x175, 0, 0}, -+ {0x176, 0x3, 0}, -+ {0x177, 0x37, 0}, -+ {0x178, 0x3, 0}, -+ {0x179, 0, 0}, -+ {0x17A, 0x21, 0}, -+ {0x17B, 0x21, 0}, -+ {0x17C, 0, 0}, -+ {0x17D, 0xaa, 0}, -+ {0x17E, 0, 0}, -+ {0x17F, 0xaa, 0}, -+ {0x180, 0, 0}, -+ {0x190, 0, 0}, -+ {0x191, 0x77, 0}, -+ {0x192, 0x77, 0}, -+ {0x193, 0x77, 0}, -+ {0x194, 0x77, 0}, -+ {0x195, 0, 0}, -+ {0x196, 0x3, 0}, -+ {0x197, 0x37, 0}, -+ {0x198, 0x3, 0}, -+ {0x199, 0, 0}, -+ {0x19A, 0x21, 0}, -+ {0x19B, 0x21, 0}, -+ {0x19C, 0, 0}, -+ {0x19D, 0xaa, 0}, -+ {0x19E, 0, 0}, -+ {0x19F, 0xaa, 0}, -+ {0x1A0, 0, 0}, -+ {0x1A1, 0x2, 0}, -+ {0x1A2, 0xf, 0}, -+ {0x1A3, 0xf, 0}, -+ {0x1A4, 0, 1}, -+ {0x1A5, 0, 1}, -+ {0x1A6, 0, 1}, -+ {0x1A7, 0x2, 0}, -+ {0x1A8, 0xf, 0}, -+ {0x1A9, 0xf, 0}, -+ {0x1AA, 0, 1}, -+ {0x1AB, 0, 1}, -+ {0x1AC, 0, 1}, -+ {0xFFFF, 0, 0}, -+}; -+ -+static struct radio_20xx_regs regs_2057_rev5[] = { -+ {0x00, 0, 1}, -+ {0x01, 0x57, 1}, -+ {0x02, 0x20, 1}, -+ {0x03, 0x1f, 0}, -+ {0x04, 0x4, 0}, -+ {0x05, 0x2, 0}, -+ {0x06, 0x1, 0}, -+ {0x07, 0x1, 0}, -+ {0x08, 0x1, 0}, -+ {0x09, 0x69, 0}, -+ {0x0A, 0x66, 0}, -+ {0x0B, 0x6, 0}, -+ {0x0C, 0x18, 0}, -+ {0x0D, 0x3, 0}, -+ {0x0E, 0x20, 0}, -+ {0x0F, 0x20, 0}, -+ {0x10, 0, 0}, -+ {0x11, 0x7c, 0}, -+ {0x12, 0x42, 0}, -+ {0x13, 0xbd, 0}, -+ {0x14, 0x7, 0}, -+ {0x15, 0x87, 0}, -+ {0x16, 0x8, 0}, -+ {0x17, 0x17, 0}, -+ {0x18, 0x7, 0}, -+ {0x19, 0, 0}, -+ {0x1A, 0x2, 0}, -+ {0x1B, 0x13, 0}, -+ {0x1C, 0x3e, 0}, -+ {0x1D, 0x3e, 0}, -+ {0x1E, 0x96, 0}, -+ {0x1F, 0x4, 0}, -+ {0x20, 0, 0}, -+ {0x21, 0, 0}, -+ {0x22, 0x17, 0}, -+ {0x23, 0x6, 1}, -+ {0x24, 0x1, 0}, -+ {0x25, 0x6, 0}, -+ {0x26, 0x4, 0}, -+ {0x27, 0xd, 0}, -+ {0x28, 0xd, 0}, -+ {0x29, 0x30, 0}, -+ {0x2A, 0x32, 0}, -+ {0x2B, 0x8, 0}, -+ {0x2C, 0x1c, 0}, -+ {0x2D, 0x2, 0}, -+ {0x2E, 0x4, 0}, -+ {0x2F, 0x7f, 0}, -+ {0x30, 0x27, 0}, -+ {0x31, 0, 1}, -+ {0x32, 0, 1}, -+ {0x33, 0, 1}, -+ {0x34, 0, 0}, -+ {0x35, 0x20, 0}, -+ {0x36, 0x18, 0}, -+ {0x37, 0x7, 0}, -+ {0x38, 0x66, 0}, -+ {0x39, 0x66, 0}, -+ {0x3C, 0xff, 0}, -+ {0x3D, 0xff, 0}, -+ {0x40, 0x16, 0}, -+ {0x41, 0x7, 0}, -+ {0x45, 0x3, 0}, -+ {0x46, 0x1, 0}, -+ {0x47, 0x7, 0}, -+ {0x4B, 0x66, 0}, -+ {0x4C, 0x66, 0}, -+ {0x4D, 0, 0}, -+ {0x4E, 0x4, 0}, -+ {0x4F, 0xc, 0}, -+ {0x50, 0, 0}, -+ {0x51, 0x70, 1}, -+ {0x56, 0x7, 0}, -+ {0x57, 0, 0}, -+ {0x58, 0, 0}, -+ {0x59, 0x88, 1}, -+ {0x5A, 0, 0}, -+ {0x5B, 0x1f, 0}, -+ {0x5C, 0x20, 1}, -+ {0x5D, 0x1, 0}, -+ {0x5E, 0x30, 0}, -+ {0x5F, 0x70, 0}, -+ {0x60, 0, 0}, -+ {0x61, 0, 0}, -+ {0x62, 0x33, 1}, -+ {0x63, 0xf, 1}, -+ {0x64, 0xf, 1}, -+ {0x65, 0, 0}, -+ {0x66, 0x11, 0}, -+ {0x80, 0x3c, 0}, -+ {0x81, 0x1, 1}, -+ {0x82, 0xa, 0}, -+ {0x85, 0, 0}, -+ {0x86, 0x40, 0}, -+ {0x87, 0x40, 0}, -+ {0x88, 0x88, 0}, -+ {0x89, 0x10, 0}, -+ {0x8A, 0xf0, 0}, -+ {0x8B, 0x10, 0}, -+ {0x8C, 0xf0, 0}, -+ {0x8F, 0x10, 0}, -+ {0x90, 0x55, 0}, -+ {0x91, 0x3f, 1}, -+ {0x92, 0x36, 1}, -+ {0x93, 0, 0}, -+ {0x94, 0, 0}, -+ {0x95, 0, 0}, -+ {0x96, 0x87, 0}, -+ {0x97, 0x11, 0}, -+ {0x98, 0, 0}, -+ {0x99, 0x33, 0}, -+ {0x9A, 0x88, 0}, -+ {0xA1, 0x20, 1}, -+ {0xA2, 0x3f, 0}, -+ {0xA3, 0x44, 0}, -+ {0xA4, 0x8c, 0}, -+ {0xA5, 0x6c, 0}, -+ {0xA6, 0x22, 0}, -+ {0xA7, 0xbe, 0}, -+ {0xA8, 0x55, 0}, -+ {0xAA, 0xc, 0}, -+ {0xAB, 0xaa, 0}, -+ {0xAC, 0x2, 0}, -+ {0xAD, 0, 0}, -+ {0xAE, 0x10, 0}, -+ {0xAF, 0x1, 0}, -+ {0xB0, 0, 0}, -+ {0xB1, 0, 0}, -+ {0xB2, 0x80, 0}, -+ {0xB3, 0x60, 0}, -+ {0xB4, 0x44, 0}, -+ {0xB5, 0x55, 0}, -+ {0xB6, 0x1, 0}, -+ {0xB7, 0x55, 0}, -+ {0xB8, 0x1, 0}, -+ {0xB9, 0x5, 0}, -+ {0xBA, 0x55, 0}, -+ {0xBB, 0x55, 0}, -+ {0xC3, 0, 0}, -+ {0xC4, 0, 0}, -+ {0xC5, 0, 0}, -+ {0xC6, 0, 0}, -+ {0xC7, 0, 0}, -+ {0xC8, 0, 0}, -+ {0xC9, 0, 0}, -+ {0xCA, 0, 0}, -+ {0xCB, 0, 0}, -+ {0xCD, 0, 0}, -+ {0xCE, 0x5e, 0}, -+ {0xCF, 0xc, 0}, -+ {0xD0, 0xc, 0}, -+ {0xD1, 0xc, 0}, -+ {0xD2, 0, 0}, -+ {0xD3, 0x2b, 0}, -+ {0xD4, 0xc, 0}, -+ {0xD5, 0, 0}, -+ {0xD6, 0x70, 1}, -+ {0xDB, 0x7, 0}, -+ {0xDC, 0, 0}, -+ {0xDD, 0, 0}, -+ {0xDE, 0x88, 1}, -+ {0xDF, 0, 0}, -+ {0xE0, 0x1f, 0}, -+ {0xE1, 0x20, 1}, -+ {0xE2, 0x1, 0}, -+ {0xE3, 0x30, 0}, -+ {0xE4, 0x70, 0}, -+ {0xE5, 0, 0}, -+ {0xE6, 0, 0}, -+ {0xE7, 0x33, 0}, -+ {0xE8, 0xf, 1}, -+ {0xE9, 0xf, 1}, -+ {0xEA, 0, 0}, -+ {0xEB, 0x11, 0}, -+ {0x105, 0x3c, 0}, -+ {0x106, 0x1, 1}, -+ {0x107, 0xa, 0}, -+ {0x10A, 0, 0}, -+ {0x10B, 0x40, 0}, -+ {0x10C, 0x40, 0}, -+ {0x10D, 0x88, 0}, -+ {0x10E, 0x10, 0}, -+ {0x10F, 0xf0, 0}, -+ {0x110, 0x10, 0}, -+ {0x111, 0xf0, 0}, -+ {0x114, 0x10, 0}, -+ {0x115, 0x55, 0}, -+ {0x116, 0x3f, 1}, -+ {0x117, 0x36, 1}, -+ {0x118, 0, 0}, -+ {0x119, 0, 0}, -+ {0x11A, 0, 0}, -+ {0x11B, 0x87, 0}, -+ {0x11C, 0x11, 0}, -+ {0x11D, 0, 0}, -+ {0x11E, 0x33, 0}, -+ {0x11F, 0x88, 0}, -+ {0x126, 0x20, 1}, -+ {0x127, 0x3f, 0}, -+ {0x128, 0x44, 0}, -+ {0x129, 0x8c, 0}, -+ {0x12A, 0x6c, 0}, -+ {0x12B, 0x22, 0}, -+ {0x12C, 0xbe, 0}, -+ {0x12D, 0x55, 0}, -+ {0x12F, 0xc, 0}, -+ {0x130, 0xaa, 0}, -+ {0x131, 0x2, 0}, -+ {0x132, 0, 0}, -+ {0x133, 0x10, 0}, -+ {0x134, 0x1, 0}, -+ {0x135, 0, 0}, -+ {0x136, 0, 0}, -+ {0x137, 0x80, 0}, -+ {0x138, 0x60, 0}, -+ {0x139, 0x44, 0}, -+ {0x13A, 0x55, 0}, -+ {0x13B, 0x1, 0}, -+ {0x13C, 0x55, 0}, -+ {0x13D, 0x1, 0}, -+ {0x13E, 0x5, 0}, -+ {0x13F, 0x55, 0}, -+ {0x140, 0x55, 0}, -+ {0x148, 0, 0}, -+ {0x149, 0, 0}, -+ {0x14A, 0, 0}, -+ {0x14B, 0, 0}, -+ {0x14C, 0, 0}, -+ {0x14D, 0, 0}, -+ {0x14E, 0, 0}, -+ {0x14F, 0, 0}, -+ {0x150, 0, 0}, -+ {0x154, 0xc, 0}, -+ {0x155, 0xc, 0}, -+ {0x156, 0xc, 0}, -+ {0x157, 0, 0}, -+ {0x158, 0x2b, 0}, -+ {0x159, 0x84, 0}, -+ {0x15A, 0x15, 0}, -+ {0x15B, 0xf, 0}, -+ {0x15C, 0, 0}, -+ {0x15D, 0, 0}, -+ {0x15E, 0, 1}, -+ {0x15F, 0, 1}, -+ {0x160, 0, 1}, -+ {0x161, 0, 1}, -+ {0x162, 0, 1}, -+ {0x163, 0, 1}, -+ {0x164, 0, 0}, -+ {0x165, 0, 0}, -+ {0x166, 0, 0}, -+ {0x167, 0, 0}, -+ {0x168, 0, 0}, -+ {0x169, 0, 0}, -+ {0x16A, 0, 1}, -+ {0x16B, 0, 1}, -+ {0x16C, 0, 1}, -+ {0x16D, 0, 0}, -+ {0x170, 0, 0}, -+ {0x171, 0x77, 0}, -+ {0x172, 0x77, 0}, -+ {0x173, 0x77, 0}, -+ {0x174, 0x77, 0}, -+ {0x175, 0, 0}, -+ {0x176, 0x3, 0}, -+ {0x177, 0x37, 0}, -+ {0x178, 0x3, 0}, -+ {0x179, 0, 0}, -+ {0x17B, 0x21, 0}, -+ {0x17C, 0, 0}, -+ {0x17D, 0xaa, 0}, -+ {0x17E, 0, 0}, -+ {0x190, 0, 0}, -+ {0x191, 0x77, 0}, -+ {0x192, 0x77, 0}, -+ {0x193, 0x77, 0}, -+ {0x194, 0x77, 0}, -+ {0x195, 0, 0}, -+ {0x196, 0x3, 0}, -+ {0x197, 0x37, 0}, -+ {0x198, 0x3, 0}, -+ {0x199, 0, 0}, -+ {0x19B, 0x21, 0}, -+ {0x19C, 0, 0}, -+ {0x19D, 0xaa, 0}, -+ {0x19E, 0, 0}, -+ {0x1A1, 0x2, 0}, -+ {0x1A2, 0xf, 0}, -+ {0x1A3, 0xf, 0}, -+ {0x1A4, 0, 1}, -+ {0x1A5, 0, 1}, -+ {0x1A6, 0, 1}, -+ {0x1A7, 0x2, 0}, -+ {0x1A8, 0xf, 0}, -+ {0x1A9, 0xf, 0}, -+ {0x1AA, 0, 1}, -+ {0x1AB, 0, 1}, -+ {0x1AC, 0, 1}, -+ {0x1AD, 0x84, 0}, -+ {0x1AE, 0x60, 0}, -+ {0x1AF, 0x47, 0}, -+ {0x1B0, 0x47, 0}, -+ {0x1B1, 0, 0}, -+ {0x1B2, 0, 0}, -+ {0x1B3, 0, 0}, -+ {0x1B4, 0, 0}, -+ {0x1B5, 0, 0}, -+ {0x1B6, 0, 0}, -+ {0x1B7, 0xc, 1}, -+ {0x1B8, 0, 0}, -+ {0x1B9, 0, 0}, -+ {0x1BA, 0, 0}, -+ {0x1BB, 0, 0}, -+ {0x1BC, 0, 0}, -+ {0x1BD, 0, 0}, -+ {0x1BE, 0, 0}, -+ {0x1BF, 0, 0}, -+ {0x1C0, 0, 0}, -+ {0x1C1, 0x1, 1}, -+ {0x1C2, 0x80, 1}, -+ {0x1C3, 0, 0}, -+ {0x1C4, 0, 0}, -+ {0x1C5, 0, 0}, -+ {0x1C6, 0, 0}, -+ {0x1C7, 0, 0}, -+ {0x1C8, 0, 0}, -+ {0x1C9, 0, 0}, -+ {0x1CA, 0, 0}, -+ {0xFFFF, 0, 0} -+}; -+ -+static struct radio_20xx_regs regs_2057_rev5v1[] = { -+ {0x00, 0x15, 1}, -+ {0x01, 0x57, 1}, -+ {0x02, 0x20, 1}, -+ {0x03, 0x1f, 0}, -+ {0x04, 0x4, 0}, -+ {0x05, 0x2, 0}, -+ {0x06, 0x1, 0}, -+ {0x07, 0x1, 0}, -+ {0x08, 0x1, 0}, -+ {0x09, 0x69, 0}, -+ {0x0A, 0x66, 0}, -+ {0x0B, 0x6, 0}, -+ {0x0C, 0x18, 0}, -+ {0x0D, 0x3, 0}, -+ {0x0E, 0x20, 0}, -+ {0x0F, 0x20, 0}, -+ {0x10, 0, 0}, -+ {0x11, 0x7c, 0}, -+ {0x12, 0x42, 0}, -+ {0x13, 0xbd, 0}, -+ {0x14, 0x7, 0}, -+ {0x15, 0x87, 0}, -+ {0x16, 0x8, 0}, -+ {0x17, 0x17, 0}, -+ {0x18, 0x7, 0}, -+ {0x19, 0, 0}, -+ {0x1A, 0x2, 0}, -+ {0x1B, 0x13, 0}, -+ {0x1C, 0x3e, 0}, -+ {0x1D, 0x3e, 0}, -+ {0x1E, 0x96, 0}, -+ {0x1F, 0x4, 0}, -+ {0x20, 0, 0}, -+ {0x21, 0, 0}, -+ {0x22, 0x17, 0}, -+ {0x23, 0x6, 1}, -+ {0x24, 0x1, 0}, -+ {0x25, 0x6, 0}, -+ {0x26, 0x4, 0}, -+ {0x27, 0xd, 0}, -+ {0x28, 0xd, 0}, -+ {0x29, 0x30, 0}, -+ {0x2A, 0x32, 0}, -+ {0x2B, 0x8, 0}, -+ {0x2C, 0x1c, 0}, -+ {0x2D, 0x2, 0}, -+ {0x2E, 0x4, 0}, -+ {0x2F, 0x7f, 0}, -+ {0x30, 0x27, 0}, -+ {0x31, 0, 1}, -+ {0x32, 0, 1}, -+ {0x33, 0, 1}, -+ {0x34, 0, 0}, -+ {0x35, 0x20, 0}, -+ {0x36, 0x18, 0}, -+ {0x37, 0x7, 0}, -+ {0x38, 0x66, 0}, -+ {0x39, 0x66, 0}, -+ {0x3C, 0xff, 0}, -+ {0x3D, 0xff, 0}, -+ {0x40, 0x16, 0}, -+ {0x41, 0x7, 0}, -+ {0x45, 0x3, 0}, -+ {0x46, 0x1, 0}, -+ {0x47, 0x7, 0}, -+ {0x4B, 0x66, 0}, -+ {0x4C, 0x66, 0}, -+ {0x4D, 0, 0}, -+ {0x4E, 0x4, 0}, -+ {0x4F, 0xc, 0}, -+ {0x50, 0, 0}, -+ {0x51, 0x70, 1}, -+ {0x56, 0x7, 0}, -+ {0x57, 0, 0}, -+ {0x58, 0, 0}, -+ {0x59, 0x88, 1}, -+ {0x5A, 0, 0}, -+ {0x5B, 0x1f, 0}, -+ {0x5C, 0x20, 1}, -+ {0x5D, 0x1, 0}, -+ {0x5E, 0x30, 0}, -+ {0x5F, 0x70, 0}, -+ {0x60, 0, 0}, -+ {0x61, 0, 0}, -+ {0x62, 0x33, 1}, -+ {0x63, 0xf, 1}, -+ {0x64, 0xf, 1}, -+ {0x65, 0, 0}, -+ {0x66, 0x11, 0}, -+ {0x80, 0x3c, 0}, -+ {0x81, 0x1, 1}, -+ {0x82, 0xa, 0}, -+ {0x85, 0, 0}, -+ {0x86, 0x40, 0}, -+ {0x87, 0x40, 0}, -+ {0x88, 0x88, 0}, -+ {0x89, 0x10, 0}, -+ {0x8A, 0xf0, 0}, -+ {0x8B, 0x10, 0}, -+ {0x8C, 0xf0, 0}, -+ {0x8F, 0x10, 0}, -+ {0x90, 0x55, 0}, -+ {0x91, 0x3f, 1}, -+ {0x92, 0x36, 1}, -+ {0x93, 0, 0}, -+ {0x94, 0, 0}, -+ {0x95, 0, 0}, -+ {0x96, 0x87, 0}, -+ {0x97, 0x11, 0}, -+ {0x98, 0, 0}, -+ {0x99, 0x33, 0}, -+ {0x9A, 0x88, 0}, -+ {0xA1, 0x20, 1}, -+ {0xA2, 0x3f, 0}, -+ {0xA3, 0x44, 0}, -+ {0xA4, 0x8c, 0}, -+ {0xA5, 0x6c, 0}, -+ {0xA6, 0x22, 0}, -+ {0xA7, 0xbe, 0}, -+ {0xA8, 0x55, 0}, -+ {0xAA, 0xc, 0}, -+ {0xAB, 0xaa, 0}, -+ {0xAC, 0x2, 0}, -+ {0xAD, 0, 0}, -+ {0xAE, 0x10, 0}, -+ {0xAF, 0x1, 0}, -+ {0xB0, 0, 0}, -+ {0xB1, 0, 0}, -+ {0xB2, 0x80, 0}, -+ {0xB3, 0x60, 0}, -+ {0xB4, 0x44, 0}, -+ {0xB5, 0x55, 0}, -+ {0xB6, 0x1, 0}, -+ {0xB7, 0x55, 0}, -+ {0xB8, 0x1, 0}, -+ {0xB9, 0x5, 0}, -+ {0xBA, 0x55, 0}, -+ {0xBB, 0x55, 0}, -+ {0xC3, 0, 0}, -+ {0xC4, 0, 0}, -+ {0xC5, 0, 0}, -+ {0xC6, 0, 0}, -+ {0xC7, 0, 0}, -+ {0xC8, 0, 0}, -+ {0xC9, 0x1, 1}, -+ {0xCA, 0, 0}, -+ {0xCB, 0, 0}, -+ {0xCD, 0, 0}, -+ {0xCE, 0x5e, 0}, -+ {0xCF, 0xc, 0}, -+ {0xD0, 0xc, 0}, -+ {0xD1, 0xc, 0}, -+ {0xD2, 0, 0}, -+ {0xD3, 0x2b, 0}, -+ {0xD4, 0xc, 0}, -+ {0xD5, 0, 0}, -+ {0xD6, 0x70, 1}, -+ {0xDB, 0x7, 0}, -+ {0xDC, 0, 0}, -+ {0xDD, 0, 0}, -+ {0xDE, 0x88, 1}, -+ {0xDF, 0, 0}, -+ {0xE0, 0x1f, 0}, -+ {0xE1, 0x20, 1}, -+ {0xE2, 0x1, 0}, -+ {0xE3, 0x30, 0}, -+ {0xE4, 0x70, 0}, -+ {0xE5, 0, 0}, -+ {0xE6, 0, 0}, -+ {0xE7, 0x33, 0}, -+ {0xE8, 0xf, 1}, -+ {0xE9, 0xf, 1}, -+ {0xEA, 0, 0}, -+ {0xEB, 0x11, 0}, -+ {0x105, 0x3c, 0}, -+ {0x106, 0x1, 1}, -+ {0x107, 0xa, 0}, -+ {0x10A, 0, 0}, -+ {0x10B, 0x40, 0}, -+ {0x10C, 0x40, 0}, -+ {0x10D, 0x88, 0}, -+ {0x10E, 0x10, 0}, -+ {0x10F, 0xf0, 0}, -+ {0x110, 0x10, 0}, -+ {0x111, 0xf0, 0}, -+ {0x114, 0x10, 0}, -+ {0x115, 0x55, 0}, -+ {0x116, 0x3f, 1}, -+ {0x117, 0x36, 1}, -+ {0x118, 0, 0}, -+ {0x119, 0, 0}, -+ {0x11A, 0, 0}, -+ {0x11B, 0x87, 0}, -+ {0x11C, 0x11, 0}, -+ {0x11D, 0, 0}, -+ {0x11E, 0x33, 0}, -+ {0x11F, 0x88, 0}, -+ {0x126, 0x20, 1}, -+ {0x127, 0x3f, 0}, -+ {0x128, 0x44, 0}, -+ {0x129, 0x8c, 0}, -+ {0x12A, 0x6c, 0}, -+ {0x12B, 0x22, 0}, -+ {0x12C, 0xbe, 0}, -+ {0x12D, 0x55, 0}, -+ {0x12F, 0xc, 0}, -+ {0x130, 0xaa, 0}, -+ {0x131, 0x2, 0}, -+ {0x132, 0, 0}, -+ {0x133, 0x10, 0}, -+ {0x134, 0x1, 0}, -+ {0x135, 0, 0}, -+ {0x136, 0, 0}, -+ {0x137, 0x80, 0}, -+ {0x138, 0x60, 0}, -+ {0x139, 0x44, 0}, -+ {0x13A, 0x55, 0}, -+ {0x13B, 0x1, 0}, -+ {0x13C, 0x55, 0}, -+ {0x13D, 0x1, 0}, -+ {0x13E, 0x5, 0}, -+ {0x13F, 0x55, 0}, -+ {0x140, 0x55, 0}, -+ {0x148, 0, 0}, -+ {0x149, 0, 0}, -+ {0x14A, 0, 0}, -+ {0x14B, 0, 0}, -+ {0x14C, 0, 0}, -+ {0x14D, 0, 0}, -+ {0x14E, 0x1, 1}, -+ {0x14F, 0, 0}, -+ {0x150, 0, 0}, -+ {0x154, 0xc, 0}, -+ {0x155, 0xc, 0}, -+ {0x156, 0xc, 0}, -+ {0x157, 0, 0}, -+ {0x158, 0x2b, 0}, -+ {0x159, 0x84, 0}, -+ {0x15A, 0x15, 0}, -+ {0x15B, 0xf, 0}, -+ {0x15C, 0, 0}, -+ {0x15D, 0, 0}, -+ {0x15E, 0, 1}, -+ {0x15F, 0, 1}, -+ {0x160, 0, 1}, -+ {0x161, 0, 1}, -+ {0x162, 0, 1}, -+ {0x163, 0, 1}, -+ {0x164, 0, 0}, -+ {0x165, 0, 0}, -+ {0x166, 0, 0}, -+ {0x167, 0, 0}, -+ {0x168, 0, 0}, -+ {0x169, 0, 0}, -+ {0x16A, 0, 1}, -+ {0x16B, 0, 1}, -+ {0x16C, 0, 1}, -+ {0x16D, 0, 0}, -+ {0x170, 0, 0}, -+ {0x171, 0x77, 0}, -+ {0x172, 0x77, 0}, -+ {0x173, 0x77, 0}, -+ {0x174, 0x77, 0}, -+ {0x175, 0, 0}, -+ {0x176, 0x3, 0}, -+ {0x177, 0x37, 0}, -+ {0x178, 0x3, 0}, -+ {0x179, 0, 0}, -+ {0x17B, 0x21, 0}, -+ {0x17C, 0, 0}, -+ {0x17D, 0xaa, 0}, -+ {0x17E, 0, 0}, -+ {0x190, 0, 0}, -+ {0x191, 0x77, 0}, -+ {0x192, 0x77, 0}, -+ {0x193, 0x77, 0}, -+ {0x194, 0x77, 0}, -+ {0x195, 0, 0}, -+ {0x196, 0x3, 0}, -+ {0x197, 0x37, 0}, -+ {0x198, 0x3, 0}, -+ {0x199, 0, 0}, -+ {0x19B, 0x21, 0}, -+ {0x19C, 0, 0}, -+ {0x19D, 0xaa, 0}, -+ {0x19E, 0, 0}, -+ {0x1A1, 0x2, 0}, -+ {0x1A2, 0xf, 0}, -+ {0x1A3, 0xf, 0}, -+ {0x1A4, 0, 1}, -+ {0x1A5, 0, 1}, -+ {0x1A6, 0, 1}, -+ {0x1A7, 0x2, 0}, -+ {0x1A8, 0xf, 0}, -+ {0x1A9, 0xf, 0}, -+ {0x1AA, 0, 1}, -+ {0x1AB, 0, 1}, -+ {0x1AC, 0, 1}, -+ {0x1AD, 0x84, 0}, -+ {0x1AE, 0x60, 0}, -+ {0x1AF, 0x47, 0}, -+ {0x1B0, 0x47, 0}, -+ {0x1B1, 0, 0}, -+ {0x1B2, 0, 0}, -+ {0x1B3, 0, 0}, -+ {0x1B4, 0, 0}, -+ {0x1B5, 0, 0}, -+ {0x1B6, 0, 0}, -+ {0x1B7, 0xc, 1}, -+ {0x1B8, 0, 0}, -+ {0x1B9, 0, 0}, -+ {0x1BA, 0, 0}, -+ {0x1BB, 0, 0}, -+ {0x1BC, 0, 0}, -+ {0x1BD, 0, 0}, -+ {0x1BE, 0, 0}, -+ {0x1BF, 0, 0}, -+ {0x1C0, 0, 0}, -+ {0x1C1, 0x1, 1}, -+ {0x1C2, 0x80, 1}, -+ {0x1C3, 0, 0}, -+ {0x1C4, 0, 0}, -+ {0x1C5, 0, 0}, -+ {0x1C6, 0, 0}, -+ {0x1C7, 0, 0}, -+ {0x1C8, 0, 0}, -+ {0x1C9, 0, 0}, -+ {0x1CA, 0, 0}, -+ {0xFFFF, 0, 0} -+}; -+ -+static struct radio_20xx_regs regs_2057_rev7[] = { -+ {0x00, 0, 1}, -+ {0x01, 0x57, 1}, -+ {0x02, 0x20, 1}, -+ {0x03, 0x1f, 0}, -+ {0x04, 0x4, 0}, -+ {0x05, 0x2, 0}, -+ {0x06, 0x1, 0}, -+ {0x07, 0x1, 0}, -+ {0x08, 0x1, 0}, -+ {0x09, 0x69, 0}, -+ {0x0A, 0x66, 0}, -+ {0x0B, 0x6, 0}, -+ {0x0C, 0x18, 0}, -+ {0x0D, 0x3, 0}, -+ {0x0E, 0x20, 0}, -+ {0x0F, 0x20, 0}, -+ {0x10, 0, 0}, -+ {0x11, 0x7c, 0}, -+ {0x12, 0x42, 0}, -+ {0x13, 0xbd, 0}, -+ {0x14, 0x7, 0}, -+ {0x15, 0x87, 0}, -+ {0x16, 0x8, 0}, -+ {0x17, 0x17, 0}, -+ {0x18, 0x7, 0}, -+ {0x19, 0, 0}, -+ {0x1A, 0x2, 0}, -+ {0x1B, 0x13, 0}, -+ {0x1C, 0x3e, 0}, -+ {0x1D, 0x3e, 0}, -+ {0x1E, 0x96, 0}, -+ {0x1F, 0x4, 0}, -+ {0x20, 0, 0}, -+ {0x21, 0, 0}, -+ {0x22, 0x17, 0}, -+ {0x23, 0x6, 0}, -+ {0x24, 0x1, 0}, -+ {0x25, 0x6, 0}, -+ {0x26, 0x4, 0}, -+ {0x27, 0xd, 0}, -+ {0x28, 0xd, 0}, -+ {0x29, 0x30, 0}, -+ {0x2A, 0x32, 0}, -+ {0x2B, 0x8, 0}, -+ {0x2C, 0x1c, 0}, -+ {0x2D, 0x2, 0}, -+ {0x2E, 0x4, 0}, -+ {0x2F, 0x7f, 0}, -+ {0x30, 0x27, 0}, -+ {0x31, 0, 1}, -+ {0x32, 0, 1}, -+ {0x33, 0, 1}, -+ {0x34, 0, 0}, -+ {0x35, 0x20, 0}, -+ {0x36, 0x18, 0}, -+ {0x37, 0x7, 0}, -+ {0x38, 0x66, 0}, -+ {0x39, 0x66, 0}, -+ {0x3A, 0x66, 0}, -+ {0x3B, 0x66, 0}, -+ {0x3C, 0xff, 0}, -+ {0x3D, 0xff, 0}, -+ {0x3E, 0xff, 0}, -+ {0x3F, 0xff, 0}, -+ {0x40, 0x16, 0}, -+ {0x41, 0x7, 0}, -+ {0x42, 0x19, 0}, -+ {0x43, 0x7, 0}, -+ {0x44, 0x6, 0}, -+ {0x45, 0x3, 0}, -+ {0x46, 0x1, 0}, -+ {0x47, 0x7, 0}, -+ {0x48, 0x33, 0}, -+ {0x49, 0x5, 0}, -+ {0x4A, 0x77, 0}, -+ {0x4B, 0x66, 0}, -+ {0x4C, 0x66, 0}, -+ {0x4D, 0, 0}, -+ {0x4E, 0x4, 0}, -+ {0x4F, 0xc, 0}, -+ {0x50, 0, 0}, -+ {0x51, 0x70, 1}, -+ {0x56, 0x7, 0}, -+ {0x57, 0, 0}, -+ {0x58, 0, 0}, -+ {0x59, 0x88, 1}, -+ {0x5A, 0, 0}, -+ {0x5B, 0x1f, 0}, -+ {0x5C, 0x20, 1}, -+ {0x5D, 0x1, 0}, -+ {0x5E, 0x30, 0}, -+ {0x5F, 0x70, 0}, -+ {0x60, 0, 0}, -+ {0x61, 0, 0}, -+ {0x62, 0x33, 1}, -+ {0x63, 0xf, 1}, -+ {0x64, 0x13, 1}, -+ {0x65, 0, 0}, -+ {0x66, 0xee, 1}, -+ {0x69, 0, 0}, -+ {0x6A, 0x7e, 0}, -+ {0x6B, 0x3f, 0}, -+ {0x6C, 0x7f, 0}, -+ {0x6D, 0x78, 0}, -+ {0x6E, 0x58, 1}, -+ {0x6F, 0x88, 0}, -+ {0x70, 0x8, 0}, -+ {0x71, 0xf, 0}, -+ {0x72, 0xbc, 0}, -+ {0x73, 0x8, 0}, -+ {0x74, 0x60, 0}, -+ {0x75, 0x13, 1}, -+ {0x76, 0x70, 0}, -+ {0x77, 0, 0}, -+ {0x78, 0, 0}, -+ {0x79, 0, 0}, -+ {0x7A, 0x33, 0}, -+ {0x7B, 0x13, 1}, -+ {0x7C, 0x14, 1}, -+ {0x7D, 0xee, 1}, -+ {0x80, 0x3c, 0}, -+ {0x81, 0x1, 1}, -+ {0x82, 0xa, 0}, -+ {0x83, 0x9d, 0}, -+ {0x84, 0xa, 0}, -+ {0x85, 0, 0}, -+ {0x86, 0x40, 0}, -+ {0x87, 0x40, 0}, -+ {0x88, 0x88, 0}, -+ {0x89, 0x10, 0}, -+ {0x8A, 0xf0, 0}, -+ {0x8B, 0x10, 0}, -+ {0x8C, 0xf0, 0}, -+ {0x8D, 0, 0}, -+ {0x8E, 0, 0}, -+ {0x8F, 0x10, 0}, -+ {0x90, 0x55, 0}, -+ {0x91, 0x3f, 1}, -+ {0x92, 0x36, 1}, -+ {0x93, 0, 0}, -+ {0x94, 0, 0}, -+ {0x95, 0, 0}, -+ {0x96, 0x87, 0}, -+ {0x97, 0x11, 0}, -+ {0x98, 0, 0}, -+ {0x99, 0x33, 0}, -+ {0x9A, 0x88, 0}, -+ {0x9B, 0, 0}, -+ {0x9C, 0x87, 0}, -+ {0x9D, 0x11, 0}, -+ {0x9E, 0, 0}, -+ {0x9F, 0x33, 0}, -+ {0xA0, 0x88, 0}, -+ {0xA1, 0x20, 1}, -+ {0xA2, 0x3f, 0}, -+ {0xA3, 0x44, 0}, -+ {0xA4, 0x8c, 0}, -+ {0xA5, 0x6c, 0}, -+ {0xA6, 0x22, 0}, -+ {0xA7, 0xbe, 0}, -+ {0xA8, 0x55, 0}, -+ {0xAA, 0xc, 0}, -+ {0xAB, 0xaa, 0}, -+ {0xAC, 0x2, 0}, -+ {0xAD, 0, 0}, -+ {0xAE, 0x10, 0}, -+ {0xAF, 0x1, 0}, -+ {0xB0, 0, 0}, -+ {0xB1, 0, 0}, -+ {0xB2, 0x80, 0}, -+ {0xB3, 0x60, 0}, -+ {0xB4, 0x44, 0}, -+ {0xB5, 0x55, 0}, -+ {0xB6, 0x1, 0}, -+ {0xB7, 0x55, 0}, -+ {0xB8, 0x1, 0}, -+ {0xB9, 0x5, 0}, -+ {0xBA, 0x55, 0}, -+ {0xBB, 0x55, 0}, -+ {0xC1, 0, 0}, -+ {0xC2, 0, 0}, -+ {0xC3, 0, 0}, -+ {0xC4, 0, 0}, -+ {0xC5, 0, 0}, -+ {0xC6, 0, 0}, -+ {0xC7, 0, 0}, -+ {0xC8, 0, 0}, -+ {0xC9, 0, 0}, -+ {0xCA, 0, 0}, -+ {0xCB, 0, 0}, -+ {0xCC, 0, 0}, -+ {0xCD, 0, 0}, -+ {0xCE, 0x5e, 0}, -+ {0xCF, 0xc, 0}, -+ {0xD0, 0xc, 0}, -+ {0xD1, 0xc, 0}, -+ {0xD2, 0, 0}, -+ {0xD3, 0x2b, 0}, -+ {0xD4, 0xc, 0}, -+ {0xD5, 0, 0}, -+ {0xD6, 0x70, 1}, -+ {0xDB, 0x7, 0}, -+ {0xDC, 0, 0}, -+ {0xDD, 0, 0}, -+ {0xDE, 0x88, 1}, -+ {0xDF, 0, 0}, -+ {0xE0, 0x1f, 0}, -+ {0xE1, 0x20, 1}, -+ {0xE2, 0x1, 0}, -+ {0xE3, 0x30, 0}, -+ {0xE4, 0x70, 0}, -+ {0xE5, 0, 0}, -+ {0xE6, 0, 0}, -+ {0xE7, 0x33, 0}, -+ {0xE8, 0xf, 1}, -+ {0xE9, 0x13, 1}, -+ {0xEA, 0, 0}, -+ {0xEB, 0xee, 1}, -+ {0xEE, 0, 0}, -+ {0xEF, 0x7e, 0}, -+ {0xF0, 0x3f, 0}, -+ {0xF1, 0x7f, 0}, -+ {0xF2, 0x78, 0}, -+ {0xF3, 0x58, 1}, -+ {0xF4, 0x88, 0}, -+ {0xF5, 0x8, 0}, -+ {0xF6, 0xf, 0}, -+ {0xF7, 0xbc, 0}, -+ {0xF8, 0x8, 0}, -+ {0xF9, 0x60, 0}, -+ {0xFA, 0x13, 1}, -+ {0xFB, 0x70, 0}, -+ {0xFC, 0, 0}, -+ {0xFD, 0, 0}, -+ {0xFE, 0, 0}, -+ {0xFF, 0x33, 0}, -+ {0x100, 0x13, 1}, -+ {0x101, 0x14, 1}, -+ {0x102, 0xee, 1}, -+ {0x105, 0x3c, 0}, -+ {0x106, 0x1, 1}, -+ {0x107, 0xa, 0}, -+ {0x108, 0x9d, 0}, -+ {0x109, 0xa, 0}, -+ {0x10A, 0, 0}, -+ {0x10B, 0x40, 0}, -+ {0x10C, 0x40, 0}, -+ {0x10D, 0x88, 0}, -+ {0x10E, 0x10, 0}, -+ {0x10F, 0xf0, 0}, -+ {0x110, 0x10, 0}, -+ {0x111, 0xf0, 0}, -+ {0x112, 0, 0}, -+ {0x113, 0, 0}, -+ {0x114, 0x10, 0}, -+ {0x115, 0x55, 0}, -+ {0x116, 0x3f, 1}, -+ {0x117, 0x36, 1}, -+ {0x118, 0, 0}, -+ {0x119, 0, 0}, -+ {0x11A, 0, 0}, -+ {0x11B, 0x87, 0}, -+ {0x11C, 0x11, 0}, -+ {0x11D, 0, 0}, -+ {0x11E, 0x33, 0}, -+ {0x11F, 0x88, 0}, -+ {0x120, 0, 0}, -+ {0x121, 0x87, 0}, -+ {0x122, 0x11, 0}, -+ {0x123, 0, 0}, -+ {0x124, 0x33, 0}, -+ {0x125, 0x88, 0}, -+ {0x126, 0x20, 1}, -+ {0x127, 0x3f, 0}, -+ {0x128, 0x44, 0}, -+ {0x129, 0x8c, 0}, -+ {0x12A, 0x6c, 0}, -+ {0x12B, 0x22, 0}, -+ {0x12C, 0xbe, 0}, -+ {0x12D, 0x55, 0}, -+ {0x12F, 0xc, 0}, -+ {0x130, 0xaa, 0}, -+ {0x131, 0x2, 0}, -+ {0x132, 0, 0}, -+ {0x133, 0x10, 0}, -+ {0x134, 0x1, 0}, -+ {0x135, 0, 0}, -+ {0x136, 0, 0}, -+ {0x137, 0x80, 0}, -+ {0x138, 0x60, 0}, -+ {0x139, 0x44, 0}, -+ {0x13A, 0x55, 0}, -+ {0x13B, 0x1, 0}, -+ {0x13C, 0x55, 0}, -+ {0x13D, 0x1, 0}, -+ {0x13E, 0x5, 0}, -+ {0x13F, 0x55, 0}, -+ {0x140, 0x55, 0}, -+ {0x146, 0, 0}, -+ {0x147, 0, 0}, -+ {0x148, 0, 0}, -+ {0x149, 0, 0}, -+ {0x14A, 0, 0}, -+ {0x14B, 0, 0}, -+ {0x14C, 0, 0}, -+ {0x14D, 0, 0}, -+ {0x14E, 0, 0}, -+ {0x14F, 0, 0}, -+ {0x150, 0, 0}, -+ {0x151, 0, 0}, -+ {0x154, 0xc, 0}, -+ {0x155, 0xc, 0}, -+ {0x156, 0xc, 0}, -+ {0x157, 0, 0}, -+ {0x158, 0x2b, 0}, -+ {0x159, 0x84, 0}, -+ {0x15A, 0x15, 0}, -+ {0x15B, 0xf, 0}, -+ {0x15C, 0, 0}, -+ {0x15D, 0, 0}, -+ {0x15E, 0, 1}, -+ {0x15F, 0, 1}, -+ {0x160, 0, 1}, -+ {0x161, 0, 1}, -+ {0x162, 0, 1}, -+ {0x163, 0, 1}, -+ {0x164, 0, 0}, -+ {0x165, 0, 0}, -+ {0x166, 0, 0}, -+ {0x167, 0, 0}, -+ {0x168, 0, 0}, -+ {0x169, 0, 0}, -+ {0x16A, 0, 1}, -+ {0x16B, 0, 1}, -+ {0x16C, 0, 1}, -+ {0x16D, 0, 0}, -+ {0x170, 0, 0}, -+ {0x171, 0x77, 0}, -+ {0x172, 0x77, 0}, -+ {0x173, 0x77, 0}, -+ {0x174, 0x77, 0}, -+ {0x175, 0, 0}, -+ {0x176, 0x3, 0}, -+ {0x177, 0x37, 0}, -+ {0x178, 0x3, 0}, -+ {0x179, 0, 0}, -+ {0x17A, 0x21, 0}, -+ {0x17B, 0x21, 0}, -+ {0x17C, 0, 0}, -+ {0x17D, 0xaa, 0}, -+ {0x17E, 0, 0}, -+ {0x17F, 0xaa, 0}, -+ {0x180, 0, 0}, -+ {0x190, 0, 0}, -+ {0x191, 0x77, 0}, -+ {0x192, 0x77, 0}, -+ {0x193, 0x77, 0}, -+ {0x194, 0x77, 0}, -+ {0x195, 0, 0}, -+ {0x196, 0x3, 0}, -+ {0x197, 0x37, 0}, -+ {0x198, 0x3, 0}, -+ {0x199, 0, 0}, -+ {0x19A, 0x21, 0}, -+ {0x19B, 0x21, 0}, -+ {0x19C, 0, 0}, -+ {0x19D, 0xaa, 0}, -+ {0x19E, 0, 0}, -+ {0x19F, 0xaa, 0}, -+ {0x1A0, 0, 0}, -+ {0x1A1, 0x2, 0}, -+ {0x1A2, 0xf, 0}, -+ {0x1A3, 0xf, 0}, -+ {0x1A4, 0, 1}, -+ {0x1A5, 0, 1}, -+ {0x1A6, 0, 1}, -+ {0x1A7, 0x2, 0}, -+ {0x1A8, 0xf, 0}, -+ {0x1A9, 0xf, 0}, -+ {0x1AA, 0, 1}, -+ {0x1AB, 0, 1}, -+ {0x1AC, 0, 1}, -+ {0x1AD, 0x84, 0}, -+ {0x1AE, 0x60, 0}, -+ {0x1AF, 0x47, 0}, -+ {0x1B0, 0x47, 0}, -+ {0x1B1, 0, 0}, -+ {0x1B2, 0, 0}, -+ {0x1B3, 0, 0}, -+ {0x1B4, 0, 0}, -+ {0x1B5, 0, 0}, -+ {0x1B6, 0, 0}, -+ {0x1B7, 0x5, 1}, -+ {0x1B8, 0, 0}, -+ {0x1B9, 0, 0}, -+ {0x1BA, 0, 0}, -+ {0x1BB, 0, 0}, -+ {0x1BC, 0, 0}, -+ {0x1BD, 0, 0}, -+ {0x1BE, 0, 0}, -+ {0x1BF, 0, 0}, -+ {0x1C0, 0, 0}, -+ {0x1C1, 0, 0}, -+ {0x1C2, 0xa0, 1}, -+ {0x1C3, 0, 0}, -+ {0x1C4, 0, 0}, -+ {0x1C5, 0, 0}, -+ {0x1C6, 0, 0}, -+ {0x1C7, 0, 0}, -+ {0x1C8, 0, 0}, -+ {0x1C9, 0, 0}, -+ {0x1CA, 0, 0}, -+ {0xFFFF, 0, 0} -+}; -+ -+static struct radio_20xx_regs regs_2057_rev8[] = { -+ {0x00, 0x8, 1}, -+ {0x01, 0x57, 1}, -+ {0x02, 0x20, 1}, -+ {0x03, 0x1f, 0}, -+ {0x04, 0x4, 0}, -+ {0x05, 0x2, 0}, -+ {0x06, 0x1, 0}, -+ {0x07, 0x1, 0}, -+ {0x08, 0x1, 0}, -+ {0x09, 0x69, 0}, -+ {0x0A, 0x66, 0}, -+ {0x0B, 0x6, 0}, -+ {0x0C, 0x18, 0}, -+ {0x0D, 0x3, 0}, -+ {0x0E, 0x20, 0}, -+ {0x0F, 0x20, 0}, -+ {0x10, 0, 0}, -+ {0x11, 0x7c, 0}, -+ {0x12, 0x42, 0}, -+ {0x13, 0xbd, 0}, -+ {0x14, 0x7, 0}, -+ {0x15, 0x87, 0}, -+ {0x16, 0x8, 0}, -+ {0x17, 0x17, 0}, -+ {0x18, 0x7, 0}, -+ {0x19, 0, 0}, -+ {0x1A, 0x2, 0}, -+ {0x1B, 0x13, 0}, -+ {0x1C, 0x3e, 0}, -+ {0x1D, 0x3e, 0}, -+ {0x1E, 0x96, 0}, -+ {0x1F, 0x4, 0}, -+ {0x20, 0, 0}, -+ {0x21, 0, 0}, -+ {0x22, 0x17, 0}, -+ {0x23, 0x6, 0}, -+ {0x24, 0x1, 0}, -+ {0x25, 0x6, 0}, -+ {0x26, 0x4, 0}, -+ {0x27, 0xd, 0}, -+ {0x28, 0xd, 0}, -+ {0x29, 0x30, 0}, -+ {0x2A, 0x32, 0}, -+ {0x2B, 0x8, 0}, -+ {0x2C, 0x1c, 0}, -+ {0x2D, 0x2, 0}, -+ {0x2E, 0x4, 0}, -+ {0x2F, 0x7f, 0}, -+ {0x30, 0x27, 0}, -+ {0x31, 0, 1}, -+ {0x32, 0, 1}, -+ {0x33, 0, 1}, -+ {0x34, 0, 0}, -+ {0x35, 0x20, 0}, -+ {0x36, 0x18, 0}, -+ {0x37, 0x7, 0}, -+ {0x38, 0x66, 0}, -+ {0x39, 0x66, 0}, -+ {0x3A, 0x66, 0}, -+ {0x3B, 0x66, 0}, -+ {0x3C, 0xff, 0}, -+ {0x3D, 0xff, 0}, -+ {0x3E, 0xff, 0}, -+ {0x3F, 0xff, 0}, -+ {0x40, 0x16, 0}, -+ {0x41, 0x7, 0}, -+ {0x42, 0x19, 0}, -+ {0x43, 0x7, 0}, -+ {0x44, 0x6, 0}, -+ {0x45, 0x3, 0}, -+ {0x46, 0x1, 0}, -+ {0x47, 0x7, 0}, -+ {0x48, 0x33, 0}, -+ {0x49, 0x5, 0}, -+ {0x4A, 0x77, 0}, -+ {0x4B, 0x66, 0}, -+ {0x4C, 0x66, 0}, -+ {0x4D, 0, 0}, -+ {0x4E, 0x4, 0}, -+ {0x4F, 0xc, 0}, -+ {0x50, 0, 0}, -+ {0x51, 0x70, 1}, -+ {0x56, 0x7, 0}, -+ {0x57, 0, 0}, -+ {0x58, 0, 0}, -+ {0x59, 0x88, 1}, -+ {0x5A, 0, 0}, -+ {0x5B, 0x1f, 0}, -+ {0x5C, 0x20, 1}, -+ {0x5D, 0x1, 0}, -+ {0x5E, 0x30, 0}, -+ {0x5F, 0x70, 0}, -+ {0x60, 0, 0}, -+ {0x61, 0, 0}, -+ {0x62, 0x33, 1}, -+ {0x63, 0xf, 1}, -+ {0x64, 0xf, 1}, -+ {0x65, 0, 0}, -+ {0x66, 0x11, 0}, -+ {0x69, 0, 0}, -+ {0x6A, 0x7e, 0}, -+ {0x6B, 0x3f, 0}, -+ {0x6C, 0x7f, 0}, -+ {0x6D, 0x78, 0}, -+ {0x6E, 0x58, 1}, -+ {0x6F, 0x88, 0}, -+ {0x70, 0x8, 0}, -+ {0x71, 0xf, 0}, -+ {0x72, 0xbc, 0}, -+ {0x73, 0x8, 0}, -+ {0x74, 0x60, 0}, -+ {0x75, 0x13, 1}, -+ {0x76, 0x70, 0}, -+ {0x77, 0, 0}, -+ {0x78, 0, 0}, -+ {0x79, 0, 0}, -+ {0x7A, 0x33, 0}, -+ {0x7B, 0x13, 1}, -+ {0x7C, 0xf, 1}, -+ {0x7D, 0xee, 1}, -+ {0x80, 0x3c, 0}, -+ {0x81, 0x1, 1}, -+ {0x82, 0xa, 0}, -+ {0x83, 0x9d, 0}, -+ {0x84, 0xa, 0}, -+ {0x85, 0, 0}, -+ {0x86, 0x40, 0}, -+ {0x87, 0x40, 0}, -+ {0x88, 0x88, 0}, -+ {0x89, 0x10, 0}, -+ {0x8A, 0xf0, 0}, -+ {0x8B, 0x10, 0}, -+ {0x8C, 0xf0, 0}, -+ {0x8D, 0, 0}, -+ {0x8E, 0, 0}, -+ {0x8F, 0x10, 0}, -+ {0x90, 0x55, 0}, -+ {0x91, 0x3f, 1}, -+ {0x92, 0x36, 1}, -+ {0x93, 0, 0}, -+ {0x94, 0, 0}, -+ {0x95, 0, 0}, -+ {0x96, 0x87, 0}, -+ {0x97, 0x11, 0}, -+ {0x98, 0, 0}, -+ {0x99, 0x33, 0}, -+ {0x9A, 0x88, 0}, -+ {0x9B, 0, 0}, -+ {0x9C, 0x87, 0}, -+ {0x9D, 0x11, 0}, -+ {0x9E, 0, 0}, -+ {0x9F, 0x33, 0}, -+ {0xA0, 0x88, 0}, -+ {0xA1, 0x20, 1}, -+ {0xA2, 0x3f, 0}, -+ {0xA3, 0x44, 0}, -+ {0xA4, 0x8c, 0}, -+ {0xA5, 0x6c, 0}, -+ {0xA6, 0x22, 0}, -+ {0xA7, 0xbe, 0}, -+ {0xA8, 0x55, 0}, -+ {0xAA, 0xc, 0}, -+ {0xAB, 0xaa, 0}, -+ {0xAC, 0x2, 0}, -+ {0xAD, 0, 0}, -+ {0xAE, 0x10, 0}, -+ {0xAF, 0x1, 0}, -+ {0xB0, 0, 0}, -+ {0xB1, 0, 0}, -+ {0xB2, 0x80, 0}, -+ {0xB3, 0x60, 0}, -+ {0xB4, 0x44, 0}, -+ {0xB5, 0x55, 0}, -+ {0xB6, 0x1, 0}, -+ {0xB7, 0x55, 0}, -+ {0xB8, 0x1, 0}, -+ {0xB9, 0x5, 0}, -+ {0xBA, 0x55, 0}, -+ {0xBB, 0x55, 0}, -+ {0xC1, 0, 0}, -+ {0xC2, 0, 0}, -+ {0xC3, 0, 0}, -+ {0xC4, 0, 0}, -+ {0xC5, 0, 0}, -+ {0xC6, 0, 0}, -+ {0xC7, 0, 0}, -+ {0xC8, 0, 0}, -+ {0xC9, 0x1, 1}, -+ {0xCA, 0, 0}, -+ {0xCB, 0, 0}, -+ {0xCC, 0, 0}, -+ {0xCD, 0, 0}, -+ {0xCE, 0x5e, 0}, -+ {0xCF, 0xc, 0}, -+ {0xD0, 0xc, 0}, -+ {0xD1, 0xc, 0}, -+ {0xD2, 0, 0}, -+ {0xD3, 0x2b, 0}, -+ {0xD4, 0xc, 0}, -+ {0xD5, 0, 0}, -+ {0xD6, 0x70, 1}, -+ {0xDB, 0x7, 0}, -+ {0xDC, 0, 0}, -+ {0xDD, 0, 0}, -+ {0xDE, 0x88, 1}, -+ {0xDF, 0, 0}, -+ {0xE0, 0x1f, 0}, -+ {0xE1, 0x20, 1}, -+ {0xE2, 0x1, 0}, -+ {0xE3, 0x30, 0}, -+ {0xE4, 0x70, 0}, -+ {0xE5, 0, 0}, -+ {0xE6, 0, 0}, -+ {0xE7, 0x33, 0}, -+ {0xE8, 0xf, 1}, -+ {0xE9, 0xf, 1}, -+ {0xEA, 0, 0}, -+ {0xEB, 0x11, 0}, -+ {0xEE, 0, 0}, -+ {0xEF, 0x7e, 0}, -+ {0xF0, 0x3f, 0}, -+ {0xF1, 0x7f, 0}, -+ {0xF2, 0x78, 0}, -+ {0xF3, 0x58, 1}, -+ {0xF4, 0x88, 0}, -+ {0xF5, 0x8, 0}, -+ {0xF6, 0xf, 0}, -+ {0xF7, 0xbc, 0}, -+ {0xF8, 0x8, 0}, -+ {0xF9, 0x60, 0}, -+ {0xFA, 0x13, 1}, -+ {0xFB, 0x70, 0}, -+ {0xFC, 0, 0}, -+ {0xFD, 0, 0}, -+ {0xFE, 0, 0}, -+ {0xFF, 0x33, 0}, -+ {0x100, 0x13, 1}, -+ {0x101, 0xf, 1}, -+ {0x102, 0xee, 1}, -+ {0x105, 0x3c, 0}, -+ {0x106, 0x1, 1}, -+ {0x107, 0xa, 0}, -+ {0x108, 0x9d, 0}, -+ {0x109, 0xa, 0}, -+ {0x10A, 0, 0}, -+ {0x10B, 0x40, 0}, -+ {0x10C, 0x40, 0}, -+ {0x10D, 0x88, 0}, -+ {0x10E, 0x10, 0}, -+ {0x10F, 0xf0, 0}, -+ {0x110, 0x10, 0}, -+ {0x111, 0xf0, 0}, -+ {0x112, 0, 0}, -+ {0x113, 0, 0}, -+ {0x114, 0x10, 0}, -+ {0x115, 0x55, 0}, -+ {0x116, 0x3f, 1}, -+ {0x117, 0x36, 1}, -+ {0x118, 0, 0}, -+ {0x119, 0, 0}, -+ {0x11A, 0, 0}, -+ {0x11B, 0x87, 0}, -+ {0x11C, 0x11, 0}, -+ {0x11D, 0, 0}, -+ {0x11E, 0x33, 0}, -+ {0x11F, 0x88, 0}, -+ {0x120, 0, 0}, -+ {0x121, 0x87, 0}, -+ {0x122, 0x11, 0}, -+ {0x123, 0, 0}, -+ {0x124, 0x33, 0}, -+ {0x125, 0x88, 0}, -+ {0x126, 0x20, 1}, -+ {0x127, 0x3f, 0}, -+ {0x128, 0x44, 0}, -+ {0x129, 0x8c, 0}, -+ {0x12A, 0x6c, 0}, -+ {0x12B, 0x22, 0}, -+ {0x12C, 0xbe, 0}, -+ {0x12D, 0x55, 0}, -+ {0x12F, 0xc, 0}, -+ {0x130, 0xaa, 0}, -+ {0x131, 0x2, 0}, -+ {0x132, 0, 0}, -+ {0x133, 0x10, 0}, -+ {0x134, 0x1, 0}, -+ {0x135, 0, 0}, -+ {0x136, 0, 0}, -+ {0x137, 0x80, 0}, -+ {0x138, 0x60, 0}, -+ {0x139, 0x44, 0}, -+ {0x13A, 0x55, 0}, -+ {0x13B, 0x1, 0}, -+ {0x13C, 0x55, 0}, -+ {0x13D, 0x1, 0}, -+ {0x13E, 0x5, 0}, -+ {0x13F, 0x55, 0}, -+ {0x140, 0x55, 0}, -+ {0x146, 0, 0}, -+ {0x147, 0, 0}, -+ {0x148, 0, 0}, -+ {0x149, 0, 0}, -+ {0x14A, 0, 0}, -+ {0x14B, 0, 0}, -+ {0x14C, 0, 0}, -+ {0x14D, 0, 0}, -+ {0x14E, 0x1, 1}, -+ {0x14F, 0, 0}, -+ {0x150, 0, 0}, -+ {0x151, 0, 0}, -+ {0x154, 0xc, 0}, -+ {0x155, 0xc, 0}, -+ {0x156, 0xc, 0}, -+ {0x157, 0, 0}, -+ {0x158, 0x2b, 0}, -+ {0x159, 0x84, 0}, -+ {0x15A, 0x15, 0}, -+ {0x15B, 0xf, 0}, -+ {0x15C, 0, 0}, -+ {0x15D, 0, 0}, -+ {0x15E, 0, 1}, -+ {0x15F, 0, 1}, -+ {0x160, 0, 1}, -+ {0x161, 0, 1}, -+ {0x162, 0, 1}, -+ {0x163, 0, 1}, -+ {0x164, 0, 0}, -+ {0x165, 0, 0}, -+ {0x166, 0, 0}, -+ {0x167, 0, 0}, -+ {0x168, 0, 0}, -+ {0x169, 0, 0}, -+ {0x16A, 0, 1}, -+ {0x16B, 0, 1}, -+ {0x16C, 0, 1}, -+ {0x16D, 0, 0}, -+ {0x170, 0, 0}, -+ {0x171, 0x77, 0}, -+ {0x172, 0x77, 0}, -+ {0x173, 0x77, 0}, -+ {0x174, 0x77, 0}, -+ {0x175, 0, 0}, -+ {0x176, 0x3, 0}, -+ {0x177, 0x37, 0}, -+ {0x178, 0x3, 0}, -+ {0x179, 0, 0}, -+ {0x17A, 0x21, 0}, -+ {0x17B, 0x21, 0}, -+ {0x17C, 0, 0}, -+ {0x17D, 0xaa, 0}, -+ {0x17E, 0, 0}, -+ {0x17F, 0xaa, 0}, -+ {0x180, 0, 0}, -+ {0x190, 0, 0}, -+ {0x191, 0x77, 0}, -+ {0x192, 0x77, 0}, -+ {0x193, 0x77, 0}, -+ {0x194, 0x77, 0}, -+ {0x195, 0, 0}, -+ {0x196, 0x3, 0}, -+ {0x197, 0x37, 0}, -+ {0x198, 0x3, 0}, -+ {0x199, 0, 0}, -+ {0x19A, 0x21, 0}, -+ {0x19B, 0x21, 0}, -+ {0x19C, 0, 0}, -+ {0x19D, 0xaa, 0}, -+ {0x19E, 0, 0}, -+ {0x19F, 0xaa, 0}, -+ {0x1A0, 0, 0}, -+ {0x1A1, 0x2, 0}, -+ {0x1A2, 0xf, 0}, -+ {0x1A3, 0xf, 0}, -+ {0x1A4, 0, 1}, -+ {0x1A5, 0, 1}, -+ {0x1A6, 0, 1}, -+ {0x1A7, 0x2, 0}, -+ {0x1A8, 0xf, 0}, -+ {0x1A9, 0xf, 0}, -+ {0x1AA, 0, 1}, -+ {0x1AB, 0, 1}, -+ {0x1AC, 0, 1}, -+ {0x1AD, 0x84, 0}, -+ {0x1AE, 0x60, 0}, -+ {0x1AF, 0x47, 0}, -+ {0x1B0, 0x47, 0}, -+ {0x1B1, 0, 0}, -+ {0x1B2, 0, 0}, -+ {0x1B3, 0, 0}, -+ {0x1B4, 0, 0}, -+ {0x1B5, 0, 0}, -+ {0x1B6, 0, 0}, -+ {0x1B7, 0x5, 1}, -+ {0x1B8, 0, 0}, -+ {0x1B9, 0, 0}, -+ {0x1BA, 0, 0}, -+ {0x1BB, 0, 0}, -+ {0x1BC, 0, 0}, -+ {0x1BD, 0, 0}, -+ {0x1BE, 0, 0}, -+ {0x1BF, 0, 0}, -+ {0x1C0, 0, 0}, -+ {0x1C1, 0, 0}, -+ {0x1C2, 0xa0, 1}, -+ {0x1C3, 0, 0}, -+ {0x1C4, 0, 0}, -+ {0x1C5, 0, 0}, -+ {0x1C6, 0, 0}, -+ {0x1C7, 0, 0}, -+ {0x1C8, 0, 0}, -+ {0x1C9, 0, 0}, -+ {0x1CA, 0, 0}, -+ {0xFFFF, 0, 0} -+}; -+ -+static s16 nphy_def_lnagains[] = { -2, 10, 19, 25 }; -+ -+static s32 nphy_lnagain_est0[] = { -315, 40370 }; -+static s32 nphy_lnagain_est1[] = { -224, 23242 }; -+ -+static const u16 tbl_iqcal_gainparams_nphy[2][NPHY_IQCAL_NUMGAINS][8] = { -+ { -+ {0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69}, -+ {0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69}, -+ {0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68}, -+ {0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67}, -+ {0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66}, -+ {0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65}, -+ {0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65}, -+ {0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65}, -+ {0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65} -+ }, -+ { -+ {0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79}, -+ {0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79}, -+ {0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79}, -+ {0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78}, -+ {0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78}, -+ {0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78}, -+ {0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78}, -+ {0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78}, -+ {0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78} -+ } -+}; -+ -+static const u32 nphy_tpc_txgain[] = { -+ 0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42, -+ 0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44, -+ 0x03c82a42, 0x03c82944, 0x03c82942, 0x03c82844, -+ 0x03c82842, 0x03c42b44, 0x03c42b42, 0x03c42a44, -+ 0x03c42a42, 0x03c42944, 0x03c42942, 0x03c42844, -+ 0x03c42842, 0x03c42744, 0x03c42742, 0x03c42644, -+ 0x03c42642, 0x03c42544, 0x03c42542, 0x03c42444, -+ 0x03c42442, 0x03c02b44, 0x03c02b42, 0x03c02a44, -+ 0x03c02a42, 0x03c02944, 0x03c02942, 0x03c02844, -+ 0x03c02842, 0x03c02744, 0x03c02742, 0x03b02b44, -+ 0x03b02b42, 0x03b02a44, 0x03b02a42, 0x03b02944, -+ 0x03b02942, 0x03b02844, 0x03b02842, 0x03b02744, -+ 0x03b02742, 0x03b02644, 0x03b02642, 0x03b02544, -+ 0x03b02542, 0x03a02b44, 0x03a02b42, 0x03a02a44, -+ 0x03a02a42, 0x03a02944, 0x03a02942, 0x03a02844, -+ 0x03a02842, 0x03a02744, 0x03a02742, 0x03902b44, -+ 0x03902b42, 0x03902a44, 0x03902a42, 0x03902944, -+ 0x03902942, 0x03902844, 0x03902842, 0x03902744, -+ 0x03902742, 0x03902644, 0x03902642, 0x03902544, -+ 0x03902542, 0x03802b44, 0x03802b42, 0x03802a44, -+ 0x03802a42, 0x03802944, 0x03802942, 0x03802844, -+ 0x03802842, 0x03802744, 0x03802742, 0x03802644, -+ 0x03802642, 0x03802544, 0x03802542, 0x03802444, -+ 0x03802442, 0x03802344, 0x03802342, 0x03802244, -+ 0x03802242, 0x03802144, 0x03802142, 0x03802044, -+ 0x03802042, 0x03801f44, 0x03801f42, 0x03801e44, -+ 0x03801e42, 0x03801d44, 0x03801d42, 0x03801c44, -+ 0x03801c42, 0x03801b44, 0x03801b42, 0x03801a44, -+ 0x03801a42, 0x03801944, 0x03801942, 0x03801844, -+ 0x03801842, 0x03801744, 0x03801742, 0x03801644, -+ 0x03801642, 0x03801544, 0x03801542, 0x03801444, -+ 0x03801442, 0x03801344, 0x03801342, 0x00002b00 -+}; -+ -+static const u16 nphy_tpc_loscale[] = { -+ 256, 256, 271, 271, 287, 256, 256, 271, -+ 271, 287, 287, 304, 304, 256, 256, 271, -+ 271, 287, 287, 304, 304, 322, 322, 341, -+ 341, 362, 362, 383, 383, 256, 256, 271, -+ 271, 287, 287, 304, 304, 322, 322, 256, -+ 256, 271, 271, 287, 287, 304, 304, 322, -+ 322, 341, 341, 362, 362, 256, 256, 271, -+ 271, 287, 287, 304, 304, 322, 322, 256, -+ 256, 271, 271, 287, 287, 304, 304, 322, -+ 322, 341, 341, 362, 362, 256, 256, 271, -+ 271, 287, 287, 304, 304, 322, 322, 341, -+ 341, 362, 362, 383, 383, 406, 406, 430, -+ 430, 455, 455, 482, 482, 511, 511, 541, -+ 541, 573, 573, 607, 607, 643, 643, 681, -+ 681, 722, 722, 764, 764, 810, 810, 858, -+ 858, 908, 908, 962, 962, 1019, 1019, 256 -+}; -+ -+static u32 nphy_tpc_txgain_ipa[] = { -+ 0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029, -+ 0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025, -+ 0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029, -+ 0x5ef70028, 0x5ef70027, 0x5ef70026, 0x5ef70025, -+ 0x5df7002d, 0x5df7002b, 0x5df7002a, 0x5df70029, -+ 0x5df70028, 0x5df70027, 0x5df70026, 0x5df70025, -+ 0x5cf7002d, 0x5cf7002b, 0x5cf7002a, 0x5cf70029, -+ 0x5cf70028, 0x5cf70027, 0x5cf70026, 0x5cf70025, -+ 0x5bf7002d, 0x5bf7002b, 0x5bf7002a, 0x5bf70029, -+ 0x5bf70028, 0x5bf70027, 0x5bf70026, 0x5bf70025, -+ 0x5af7002d, 0x5af7002b, 0x5af7002a, 0x5af70029, -+ 0x5af70028, 0x5af70027, 0x5af70026, 0x5af70025, -+ 0x59f7002d, 0x59f7002b, 0x59f7002a, 0x59f70029, -+ 0x59f70028, 0x59f70027, 0x59f70026, 0x59f70025, -+ 0x58f7002d, 0x58f7002b, 0x58f7002a, 0x58f70029, -+ 0x58f70028, 0x58f70027, 0x58f70026, 0x58f70025, -+ 0x57f7002d, 0x57f7002b, 0x57f7002a, 0x57f70029, -+ 0x57f70028, 0x57f70027, 0x57f70026, 0x57f70025, -+ 0x56f7002d, 0x56f7002b, 0x56f7002a, 0x56f70029, -+ 0x56f70028, 0x56f70027, 0x56f70026, 0x56f70025, -+ 0x55f7002d, 0x55f7002b, 0x55f7002a, 0x55f70029, -+ 0x55f70028, 0x55f70027, 0x55f70026, 0x55f70025, -+ 0x54f7002d, 0x54f7002b, 0x54f7002a, 0x54f70029, -+ 0x54f70028, 0x54f70027, 0x54f70026, 0x54f70025, -+ 0x53f7002d, 0x53f7002b, 0x53f7002a, 0x53f70029, -+ 0x53f70028, 0x53f70027, 0x53f70026, 0x53f70025, -+ 0x52f7002d, 0x52f7002b, 0x52f7002a, 0x52f70029, -+ 0x52f70028, 0x52f70027, 0x52f70026, 0x52f70025, -+ 0x51f7002d, 0x51f7002b, 0x51f7002a, 0x51f70029, -+ 0x51f70028, 0x51f70027, 0x51f70026, 0x51f70025, -+ 0x50f7002d, 0x50f7002b, 0x50f7002a, 0x50f70029, -+ 0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025 -+}; -+ -+static u32 nphy_tpc_txgain_ipa_rev5[] = { -+ 0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029, -+ 0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025, -+ 0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029, -+ 0x1ef70028, 0x1ef70027, 0x1ef70026, 0x1ef70025, -+ 0x1df7002d, 0x1df7002b, 0x1df7002a, 0x1df70029, -+ 0x1df70028, 0x1df70027, 0x1df70026, 0x1df70025, -+ 0x1cf7002d, 0x1cf7002b, 0x1cf7002a, 0x1cf70029, -+ 0x1cf70028, 0x1cf70027, 0x1cf70026, 0x1cf70025, -+ 0x1bf7002d, 0x1bf7002b, 0x1bf7002a, 0x1bf70029, -+ 0x1bf70028, 0x1bf70027, 0x1bf70026, 0x1bf70025, -+ 0x1af7002d, 0x1af7002b, 0x1af7002a, 0x1af70029, -+ 0x1af70028, 0x1af70027, 0x1af70026, 0x1af70025, -+ 0x19f7002d, 0x19f7002b, 0x19f7002a, 0x19f70029, -+ 0x19f70028, 0x19f70027, 0x19f70026, 0x19f70025, -+ 0x18f7002d, 0x18f7002b, 0x18f7002a, 0x18f70029, -+ 0x18f70028, 0x18f70027, 0x18f70026, 0x18f70025, -+ 0x17f7002d, 0x17f7002b, 0x17f7002a, 0x17f70029, -+ 0x17f70028, 0x17f70027, 0x17f70026, 0x17f70025, -+ 0x16f7002d, 0x16f7002b, 0x16f7002a, 0x16f70029, -+ 0x16f70028, 0x16f70027, 0x16f70026, 0x16f70025, -+ 0x15f7002d, 0x15f7002b, 0x15f7002a, 0x15f70029, -+ 0x15f70028, 0x15f70027, 0x15f70026, 0x15f70025, -+ 0x14f7002d, 0x14f7002b, 0x14f7002a, 0x14f70029, -+ 0x14f70028, 0x14f70027, 0x14f70026, 0x14f70025, -+ 0x13f7002d, 0x13f7002b, 0x13f7002a, 0x13f70029, -+ 0x13f70028, 0x13f70027, 0x13f70026, 0x13f70025, -+ 0x12f7002d, 0x12f7002b, 0x12f7002a, 0x12f70029, -+ 0x12f70028, 0x12f70027, 0x12f70026, 0x12f70025, -+ 0x11f7002d, 0x11f7002b, 0x11f7002a, 0x11f70029, -+ 0x11f70028, 0x11f70027, 0x11f70026, 0x11f70025, -+ 0x10f7002d, 0x10f7002b, 0x10f7002a, 0x10f70029, -+ 0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025 -+}; -+ -+static u32 nphy_tpc_txgain_ipa_rev6[] = { -+ 0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029, -+ 0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025, -+ 0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029, -+ 0x0ef70028, 0x0ef70027, 0x0ef70026, 0x0ef70025, -+ 0x0df7002d, 0x0df7002b, 0x0df7002a, 0x0df70029, -+ 0x0df70028, 0x0df70027, 0x0df70026, 0x0df70025, -+ 0x0cf7002d, 0x0cf7002b, 0x0cf7002a, 0x0cf70029, -+ 0x0cf70028, 0x0cf70027, 0x0cf70026, 0x0cf70025, -+ 0x0bf7002d, 0x0bf7002b, 0x0bf7002a, 0x0bf70029, -+ 0x0bf70028, 0x0bf70027, 0x0bf70026, 0x0bf70025, -+ 0x0af7002d, 0x0af7002b, 0x0af7002a, 0x0af70029, -+ 0x0af70028, 0x0af70027, 0x0af70026, 0x0af70025, -+ 0x09f7002d, 0x09f7002b, 0x09f7002a, 0x09f70029, -+ 0x09f70028, 0x09f70027, 0x09f70026, 0x09f70025, -+ 0x08f7002d, 0x08f7002b, 0x08f7002a, 0x08f70029, -+ 0x08f70028, 0x08f70027, 0x08f70026, 0x08f70025, -+ 0x07f7002d, 0x07f7002b, 0x07f7002a, 0x07f70029, -+ 0x07f70028, 0x07f70027, 0x07f70026, 0x07f70025, -+ 0x06f7002d, 0x06f7002b, 0x06f7002a, 0x06f70029, -+ 0x06f70028, 0x06f70027, 0x06f70026, 0x06f70025, -+ 0x05f7002d, 0x05f7002b, 0x05f7002a, 0x05f70029, -+ 0x05f70028, 0x05f70027, 0x05f70026, 0x05f70025, -+ 0x04f7002d, 0x04f7002b, 0x04f7002a, 0x04f70029, -+ 0x04f70028, 0x04f70027, 0x04f70026, 0x04f70025, -+ 0x03f7002d, 0x03f7002b, 0x03f7002a, 0x03f70029, -+ 0x03f70028, 0x03f70027, 0x03f70026, 0x03f70025, -+ 0x02f7002d, 0x02f7002b, 0x02f7002a, 0x02f70029, -+ 0x02f70028, 0x02f70027, 0x02f70026, 0x02f70025, -+ 0x01f7002d, 0x01f7002b, 0x01f7002a, 0x01f70029, -+ 0x01f70028, 0x01f70027, 0x01f70026, 0x01f70025, -+ 0x00f7002d, 0x00f7002b, 0x00f7002a, 0x00f70029, -+ 0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025 -+}; -+ -+static u32 nphy_tpc_txgain_ipa_2g_2057rev3[] = { -+ 0x70ff0040, 0x70f7003e, 0x70ef003b, 0x70e70039, -+ 0x70df0037, 0x70d70036, 0x70cf0033, 0x70c70032, -+ 0x70bf0031, 0x70b7002f, 0x70af002e, 0x70a7002d, -+ 0x709f002d, 0x7097002c, 0x708f002c, 0x7087002c, -+ 0x707f002b, 0x7077002c, 0x706f002c, 0x7067002d, -+ 0x705f002e, 0x705f002b, 0x705f0029, 0x7057002a, -+ 0x70570028, 0x704f002a, 0x7047002c, 0x7047002a, -+ 0x70470028, 0x70470026, 0x70470024, 0x70470022, -+ 0x7047001f, 0x70370027, 0x70370024, 0x70370022, -+ 0x70370020, 0x7037001f, 0x7037001d, 0x7037001b, -+ 0x7037001a, 0x70370018, 0x70370017, 0x7027001e, -+ 0x7027001d, 0x7027001a, 0x701f0024, 0x701f0022, -+ 0x701f0020, 0x701f001f, 0x701f001d, 0x701f001b, -+ 0x701f001a, 0x701f0018, 0x701f0017, 0x701f0015, -+ 0x701f0014, 0x701f0013, 0x701f0012, 0x701f0011, -+ 0x70170019, 0x70170018, 0x70170016, 0x70170015, -+ 0x70170014, 0x70170013, 0x70170012, 0x70170010, -+ 0x70170010, 0x7017000f, 0x700f001d, 0x700f001b, -+ 0x700f001a, 0x700f0018, 0x700f0017, 0x700f0015, -+ 0x700f0015, 0x700f0013, 0x700f0013, 0x700f0011, -+ 0x700f0010, 0x700f0010, 0x700f000f, 0x700f000e, -+ 0x700f000d, 0x700f000c, 0x700f000b, 0x700f000b, -+ 0x700f000b, 0x700f000a, 0x700f0009, 0x700f0009, -+ 0x700f0009, 0x700f0008, 0x700f0007, 0x700f0007, -+ 0x700f0006, 0x700f0006, 0x700f0006, 0x700f0006, -+ 0x700f0005, 0x700f0005, 0x700f0005, 0x700f0004, -+ 0x700f0004, 0x700f0004, 0x700f0004, 0x700f0004, -+ 0x700f0004, 0x700f0003, 0x700f0003, 0x700f0003, -+ 0x700f0003, 0x700f0002, 0x700f0002, 0x700f0002, -+ 0x700f0002, 0x700f0002, 0x700f0002, 0x700f0001, -+ 0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001, -+ 0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001 -+}; -+ -+static u32 nphy_tpc_txgain_ipa_2g_2057rev4n6[] = { -+ 0xf0ff0040, 0xf0f7003e, 0xf0ef003b, 0xf0e70039, -+ 0xf0df0037, 0xf0d70036, 0xf0cf0033, 0xf0c70032, -+ 0xf0bf0031, 0xf0b7002f, 0xf0af002e, 0xf0a7002d, -+ 0xf09f002d, 0xf097002c, 0xf08f002c, 0xf087002c, -+ 0xf07f002b, 0xf077002c, 0xf06f002c, 0xf067002d, -+ 0xf05f002e, 0xf05f002b, 0xf05f0029, 0xf057002a, -+ 0xf0570028, 0xf04f002a, 0xf047002c, 0xf047002a, -+ 0xf0470028, 0xf0470026, 0xf0470024, 0xf0470022, -+ 0xf047001f, 0xf0370027, 0xf0370024, 0xf0370022, -+ 0xf0370020, 0xf037001f, 0xf037001d, 0xf037001b, -+ 0xf037001a, 0xf0370018, 0xf0370017, 0xf027001e, -+ 0xf027001d, 0xf027001a, 0xf01f0024, 0xf01f0022, -+ 0xf01f0020, 0xf01f001f, 0xf01f001d, 0xf01f001b, -+ 0xf01f001a, 0xf01f0018, 0xf01f0017, 0xf01f0015, -+ 0xf01f0014, 0xf01f0013, 0xf01f0012, 0xf01f0011, -+ 0xf0170019, 0xf0170018, 0xf0170016, 0xf0170015, -+ 0xf0170014, 0xf0170013, 0xf0170012, 0xf0170010, -+ 0xf0170010, 0xf017000f, 0xf00f001d, 0xf00f001b, -+ 0xf00f001a, 0xf00f0018, 0xf00f0017, 0xf00f0015, -+ 0xf00f0015, 0xf00f0013, 0xf00f0013, 0xf00f0011, -+ 0xf00f0010, 0xf00f0010, 0xf00f000f, 0xf00f000e, -+ 0xf00f000d, 0xf00f000c, 0xf00f000b, 0xf00f000b, -+ 0xf00f000b, 0xf00f000a, 0xf00f0009, 0xf00f0009, -+ 0xf00f0009, 0xf00f0008, 0xf00f0007, 0xf00f0007, -+ 0xf00f0006, 0xf00f0006, 0xf00f0006, 0xf00f0006, -+ 0xf00f0005, 0xf00f0005, 0xf00f0005, 0xf00f0004, -+ 0xf00f0004, 0xf00f0004, 0xf00f0004, 0xf00f0004, -+ 0xf00f0004, 0xf00f0003, 0xf00f0003, 0xf00f0003, -+ 0xf00f0003, 0xf00f0002, 0xf00f0002, 0xf00f0002, -+ 0xf00f0002, 0xf00f0002, 0xf00f0002, 0xf00f0001, -+ 0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001, -+ 0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001 -+}; -+ -+static u32 nphy_tpc_txgain_ipa_2g_2057rev5[] = { -+ 0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e, -+ 0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033, -+ 0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e, -+ 0x3067002e, 0x305f002f, 0x30570030, 0x3057002d, -+ 0x304f002e, 0x30470031, 0x3047002e, 0x3047002c, -+ 0x30470029, 0x303f002c, 0x303f0029, 0x3037002d, -+ 0x3037002a, 0x30370028, 0x302f002c, 0x302f002a, -+ 0x302f0028, 0x302f0026, 0x3027002c, 0x30270029, -+ 0x30270027, 0x30270025, 0x30270023, 0x301f002c, -+ 0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024, -+ 0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b, -+ 0x30170028, 0x30170026, 0x30170024, 0x30170022, -+ 0x30170020, 0x3017001e, 0x3017001d, 0x3017001b, -+ 0x3017001a, 0x30170018, 0x30170017, 0x30170015, -+ 0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024, -+ 0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d, -+ 0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017, -+ 0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215, -+ 0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715 -+}; -+ -+static u32 nphy_tpc_txgain_ipa_2g_2057rev7[] = { -+ 0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e, -+ 0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033, -+ 0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e, -+ 0x3067002e, 0x305f002f, 0x30570030, 0x3057002d, -+ 0x304f002e, 0x30470031, 0x3047002e, 0x3047002c, -+ 0x30470029, 0x303f002c, 0x303f0029, 0x3037002d, -+ 0x3037002a, 0x30370028, 0x302f002c, 0x302f002a, -+ 0x302f0028, 0x302f0026, 0x3027002c, 0x30270029, -+ 0x30270027, 0x30270025, 0x30270023, 0x301f002c, -+ 0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024, -+ 0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b, -+ 0x30170028, 0x30170026, 0x30170024, 0x30170022, -+ 0x30170020, 0x3017001e, 0x3017001d, 0x3017001b, -+ 0x3017001a, 0x30170018, 0x30170017, 0x30170015, -+ 0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024, -+ 0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d, -+ 0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017, -+ 0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215, -+ 0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, -+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715 -+}; -+ -+static u32 nphy_tpc_txgain_ipa_5g[] = { -+ 0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031, -+ 0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b, -+ 0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027, -+ 0x7ff70026, 0x7ff70024, 0x7ff70023, 0x7ff70022, -+ 0x7ef70028, 0x7ef70027, 0x7ef70026, 0x7ef70025, -+ 0x7ef70024, 0x7ef70023, 0x7df70028, 0x7df70027, -+ 0x7df70026, 0x7df70025, 0x7df70024, 0x7df70023, -+ 0x7df70022, 0x7cf70029, 0x7cf70028, 0x7cf70027, -+ 0x7cf70026, 0x7cf70025, 0x7cf70023, 0x7cf70022, -+ 0x7bf70029, 0x7bf70028, 0x7bf70026, 0x7bf70025, -+ 0x7bf70024, 0x7bf70023, 0x7bf70022, 0x7bf70021, -+ 0x7af70029, 0x7af70028, 0x7af70027, 0x7af70026, -+ 0x7af70025, 0x7af70024, 0x7af70023, 0x7af70022, -+ 0x79f70029, 0x79f70028, 0x79f70027, 0x79f70026, -+ 0x79f70025, 0x79f70024, 0x79f70023, 0x79f70022, -+ 0x78f70029, 0x78f70028, 0x78f70027, 0x78f70026, -+ 0x78f70025, 0x78f70024, 0x78f70023, 0x78f70022, -+ 0x77f70029, 0x77f70028, 0x77f70027, 0x77f70026, -+ 0x77f70025, 0x77f70024, 0x77f70023, 0x77f70022, -+ 0x76f70029, 0x76f70028, 0x76f70027, 0x76f70026, -+ 0x76f70024, 0x76f70023, 0x76f70022, 0x76f70021, -+ 0x75f70029, 0x75f70028, 0x75f70027, 0x75f70026, -+ 0x75f70025, 0x75f70024, 0x75f70023, 0x74f70029, -+ 0x74f70028, 0x74f70026, 0x74f70025, 0x74f70024, -+ 0x74f70023, 0x74f70022, 0x73f70029, 0x73f70027, -+ 0x73f70026, 0x73f70025, 0x73f70024, 0x73f70023, -+ 0x73f70022, 0x72f70028, 0x72f70027, 0x72f70026, -+ 0x72f70025, 0x72f70024, 0x72f70023, 0x72f70022, -+ 0x71f70028, 0x71f70027, 0x71f70026, 0x71f70025, -+ 0x71f70024, 0x71f70023, 0x70f70028, 0x70f70027, -+ 0x70f70026, 0x70f70024, 0x70f70023, 0x70f70022, -+ 0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f -+}; -+ -+static u32 nphy_tpc_txgain_ipa_5g_2057[] = { -+ 0x7f7f0044, 0x7f7f0040, 0x7f7f003c, 0x7f7f0039, -+ 0x7f7f0036, 0x7e7f003c, 0x7e7f0038, 0x7e7f0035, -+ 0x7d7f003c, 0x7d7f0039, 0x7d7f0036, 0x7d7f0033, -+ 0x7c7f003b, 0x7c7f0037, 0x7c7f0034, 0x7b7f003a, -+ 0x7b7f0036, 0x7b7f0033, 0x7a7f003c, 0x7a7f0039, -+ 0x7a7f0036, 0x7a7f0033, 0x797f003b, 0x797f0038, -+ 0x797f0035, 0x797f0032, 0x787f003b, 0x787f0038, -+ 0x787f0035, 0x787f0032, 0x777f003a, 0x777f0037, -+ 0x777f0034, 0x777f0031, 0x767f003a, 0x767f0036, -+ 0x767f0033, 0x767f0031, 0x757f003a, 0x757f0037, -+ 0x757f0034, 0x747f003c, 0x747f0039, 0x747f0036, -+ 0x747f0033, 0x737f003b, 0x737f0038, 0x737f0035, -+ 0x737f0032, 0x727f0039, 0x727f0036, 0x727f0033, -+ 0x727f0030, 0x717f003a, 0x717f0037, 0x717f0034, -+ 0x707f003b, 0x707f0038, 0x707f0035, 0x707f0032, -+ 0x707f002f, 0x707f002d, 0x707f002a, 0x707f0028, -+ 0x707f0025, 0x707f0023, 0x707f0021, 0x707f0020, -+ 0x707f001e, 0x707f001c, 0x707f001b, 0x707f0019, -+ 0x707f0018, 0x707f0016, 0x707f0015, 0x707f0014, -+ 0x707f0013, 0x707f0012, 0x707f0011, 0x707f0010, -+ 0x707f000f, 0x707f000e, 0x707f000d, 0x707f000d, -+ 0x707f000c, 0x707f000b, 0x707f000b, 0x707f000a, -+ 0x707f0009, 0x707f0009, 0x707f0008, 0x707f0008, -+ 0x707f0007, 0x707f0007, 0x707f0007, 0x707f0006, -+ 0x707f0006, 0x707f0006, 0x707f0005, 0x707f0005, -+ 0x707f0005, 0x707f0004, 0x707f0004, 0x707f0004, -+ 0x707f0004, 0x707f0004, 0x707f0003, 0x707f0003, -+ 0x707f0003, 0x707f0003, 0x707f0003, 0x707f0003, -+ 0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002, -+ 0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002, -+ 0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001, -+ 0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001 -+}; -+ -+static u32 nphy_tpc_txgain_ipa_5g_2057rev7[] = { -+ 0x6f7f0031, 0x6f7f002e, 0x6f7f002c, 0x6f7f002a, -+ 0x6f7f0027, 0x6e7f002e, 0x6e7f002c, 0x6e7f002a, -+ 0x6d7f0030, 0x6d7f002d, 0x6d7f002a, 0x6d7f0028, -+ 0x6c7f0030, 0x6c7f002d, 0x6c7f002b, 0x6b7f002e, -+ 0x6b7f002c, 0x6b7f002a, 0x6b7f0027, 0x6a7f002e, -+ 0x6a7f002c, 0x6a7f002a, 0x697f0030, 0x697f002e, -+ 0x697f002b, 0x697f0029, 0x687f002f, 0x687f002d, -+ 0x687f002a, 0x687f0027, 0x677f002f, 0x677f002d, -+ 0x677f002a, 0x667f0031, 0x667f002e, 0x667f002c, -+ 0x667f002a, 0x657f0030, 0x657f002e, 0x657f002b, -+ 0x657f0029, 0x647f0030, 0x647f002d, 0x647f002b, -+ 0x647f0029, 0x637f002f, 0x637f002d, 0x637f002a, -+ 0x627f0030, 0x627f002d, 0x627f002b, 0x627f0029, -+ 0x617f0030, 0x617f002e, 0x617f002b, 0x617f0029, -+ 0x607f002f, 0x607f002d, 0x607f002a, 0x607f0027, -+ 0x607f0026, 0x607f0023, 0x607f0021, 0x607f0020, -+ 0x607f001e, 0x607f001c, 0x607f001a, 0x607f0019, -+ 0x607f0018, 0x607f0016, 0x607f0015, 0x607f0014, -+ 0x607f0012, 0x607f0012, 0x607f0011, 0x607f000f, -+ 0x607f000f, 0x607f000e, 0x607f000d, 0x607f000c, -+ 0x607f000c, 0x607f000b, 0x607f000b, 0x607f000a, -+ 0x607f0009, 0x607f0009, 0x607f0008, 0x607f0008, -+ 0x607f0008, 0x607f0007, 0x607f0007, 0x607f0006, -+ 0x607f0006, 0x607f0005, 0x607f0005, 0x607f0005, -+ 0x607f0005, 0x607f0005, 0x607f0004, 0x607f0004, -+ 0x607f0004, 0x607f0004, 0x607f0003, 0x607f0003, -+ 0x607f0003, 0x607f0003, 0x607f0002, 0x607f0002, -+ 0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002, -+ 0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002, -+ 0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002, -+ 0x607f0002, 0x607f0001, 0x607f0001, 0x607f0001, -+ 0x607f0001, 0x607f0001, 0x607f0001, 0x607f0001 -+}; -+ -+static s8 nphy_papd_pga_gain_delta_ipa_2g[] = { -+ -114, -108, -98, -91, -84, -78, -70, -62, -+ -54, -46, -39, -31, -23, -15, -8, 0 -+}; -+ -+static s8 nphy_papd_pga_gain_delta_ipa_5g[] = { -+ -100, -95, -89, -83, -77, -70, -63, -56, -+ -48, -41, -33, -25, -19, -12, -6, 0 -+}; -+ -+static s16 nphy_papd_padgain_dlt_2g_2057rev3n4[] = { -+ -159, -113, -86, -72, -62, -54, -48, -43, -+ -39, -35, -31, -28, -25, -23, -20, -18, -+ -17, -15, -13, -11, -10, -8, -7, -6, -+ -5, -4, -3, -3, -2, -1, -1, 0 -+}; -+ -+static s16 nphy_papd_padgain_dlt_2g_2057rev5[] = { -+ -109, -109, -82, -68, -58, -50, -44, -39, -+ -35, -31, -28, -26, -23, -21, -19, -17, -+ -16, -14, -13, -11, -10, -9, -8, -7, -+ -5, -5, -4, -3, -2, -1, -1, 0 -+}; -+ -+static s16 nphy_papd_padgain_dlt_2g_2057rev7[] = { -+ -122, -122, -95, -80, -69, -61, -54, -49, -+ -43, -39, -35, -32, -28, -26, -23, -21, -+ -18, -16, -15, -13, -11, -10, -8, -7, -+ -6, -5, -4, -3, -2, -1, -1, 0 -+}; -+ -+static s8 nphy_papd_pgagain_dlt_5g_2057[] = { -+ -107, -101, -92, -85, -78, -71, -62, -55, -+ -47, -39, -32, -24, -19, -12, -6, 0 -+}; -+ -+static s8 nphy_papd_pgagain_dlt_5g_2057rev7[] = { -+ -110, -104, -95, -88, -81, -74, -66, -58, -+ -50, -44, -36, -28, -23, -15, -8, 0 -+}; -+ -+static u8 pad_gain_codes_used_2057rev5[] = { -+ 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, -+ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 -+}; -+ -+static u8 pad_gain_codes_used_2057rev7[] = { -+ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, -+ 5, 4, 3, 2, 1 -+}; -+ -+static u8 pad_all_gain_codes_2057[] = { -+ 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, -+ 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, -+ 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, -+ 1, 0 -+}; -+ -+static u8 pga_all_gain_codes_2057[] = { -+ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 -+}; -+ -+static u32 nphy_papd_scaltbl[] = { -+ 0x0ae2002f, 0x0a3b0032, 0x09a70035, 0x09220038, -+ 0x0887003c, 0x081f003f, 0x07a20043, 0x07340047, -+ 0x06d2004b, 0x067a004f, 0x06170054, 0x05bf0059, -+ 0x0571005e, 0x051e0064, 0x04d3006a, 0x04910070, -+ 0x044c0077, 0x040f007e, 0x03d90085, 0x03a1008d, -+ 0x036f0095, 0x033d009e, 0x030b00a8, 0x02e000b2, -+ 0x02b900bc, 0x029200c7, 0x026d00d3, 0x024900e0, -+ 0x022900ed, 0x020a00fb, 0x01ec010a, 0x01d0011a, -+ 0x01b7012a, 0x019e013c, 0x0187014f, 0x01720162, -+ 0x015d0177, 0x0149018e, 0x013701a5, 0x012601be, -+ 0x011501d9, 0x010501f5, 0x00f70212, 0x00e90232, -+ 0x00dc0253, 0x00d00276, 0x00c4029c, 0x00b902c3, -+ 0x00af02ed, 0x00a5031a, 0x009c0349, 0x0093037a, -+ 0x008b03af, 0x008303e7, 0x007c0422, 0x00750461, -+ 0x006e04a3, 0x006804ea, 0x00620534, 0x005d0583, -+ 0x005805d7, 0x0053062f, 0x004e068d, 0x004a06f1 -+}; -+ -+static u32 nphy_tpc_txgain_rev3[] = { -+ 0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e, -+ 0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037, -+ 0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e, -+ 0x1e41003c, 0x1e41003b, 0x1e410039, 0x1e410037, -+ 0x1d410044, 0x1d410042, 0x1d410040, 0x1d41003e, -+ 0x1d41003c, 0x1d41003b, 0x1d410039, 0x1d410037, -+ 0x1c410044, 0x1c410042, 0x1c410040, 0x1c41003e, -+ 0x1c41003c, 0x1c41003b, 0x1c410039, 0x1c410037, -+ 0x1b410044, 0x1b410042, 0x1b410040, 0x1b41003e, -+ 0x1b41003c, 0x1b41003b, 0x1b410039, 0x1b410037, -+ 0x1a410044, 0x1a410042, 0x1a410040, 0x1a41003e, -+ 0x1a41003c, 0x1a41003b, 0x1a410039, 0x1a410037, -+ 0x19410044, 0x19410042, 0x19410040, 0x1941003e, -+ 0x1941003c, 0x1941003b, 0x19410039, 0x19410037, -+ 0x18410044, 0x18410042, 0x18410040, 0x1841003e, -+ 0x1841003c, 0x1841003b, 0x18410039, 0x18410037, -+ 0x17410044, 0x17410042, 0x17410040, 0x1741003e, -+ 0x1741003c, 0x1741003b, 0x17410039, 0x17410037, -+ 0x16410044, 0x16410042, 0x16410040, 0x1641003e, -+ 0x1641003c, 0x1641003b, 0x16410039, 0x16410037, -+ 0x15410044, 0x15410042, 0x15410040, 0x1541003e, -+ 0x1541003c, 0x1541003b, 0x15410039, 0x15410037, -+ 0x14410044, 0x14410042, 0x14410040, 0x1441003e, -+ 0x1441003c, 0x1441003b, 0x14410039, 0x14410037, -+ 0x13410044, 0x13410042, 0x13410040, 0x1341003e, -+ 0x1341003c, 0x1341003b, 0x13410039, 0x13410037, -+ 0x12410044, 0x12410042, 0x12410040, 0x1241003e, -+ 0x1241003c, 0x1241003b, 0x12410039, 0x12410037, -+ 0x11410044, 0x11410042, 0x11410040, 0x1141003e, -+ 0x1141003c, 0x1141003b, 0x11410039, 0x11410037, -+ 0x10410044, 0x10410042, 0x10410040, 0x1041003e, -+ 0x1041003c, 0x1041003b, 0x10410039, 0x10410037 -+}; -+ -+static u32 nphy_tpc_txgain_HiPwrEPA[] = { -+ 0x0f410044, 0x0f410042, 0x0f410040, 0x0f41003e, -+ 0x0f41003c, 0x0f41003b, 0x0f410039, 0x0f410037, -+ 0x0e410044, 0x0e410042, 0x0e410040, 0x0e41003e, -+ 0x0e41003c, 0x0e41003b, 0x0e410039, 0x0e410037, -+ 0x0d410044, 0x0d410042, 0x0d410040, 0x0d41003e, -+ 0x0d41003c, 0x0d41003b, 0x0d410039, 0x0d410037, -+ 0x0c410044, 0x0c410042, 0x0c410040, 0x0c41003e, -+ 0x0c41003c, 0x0c41003b, 0x0c410039, 0x0c410037, -+ 0x0b410044, 0x0b410042, 0x0b410040, 0x0b41003e, -+ 0x0b41003c, 0x0b41003b, 0x0b410039, 0x0b410037, -+ 0x0a410044, 0x0a410042, 0x0a410040, 0x0a41003e, -+ 0x0a41003c, 0x0a41003b, 0x0a410039, 0x0a410037, -+ 0x09410044, 0x09410042, 0x09410040, 0x0941003e, -+ 0x0941003c, 0x0941003b, 0x09410039, 0x09410037, -+ 0x08410044, 0x08410042, 0x08410040, 0x0841003e, -+ 0x0841003c, 0x0841003b, 0x08410039, 0x08410037, -+ 0x07410044, 0x07410042, 0x07410040, 0x0741003e, -+ 0x0741003c, 0x0741003b, 0x07410039, 0x07410037, -+ 0x06410044, 0x06410042, 0x06410040, 0x0641003e, -+ 0x0641003c, 0x0641003b, 0x06410039, 0x06410037, -+ 0x05410044, 0x05410042, 0x05410040, 0x0541003e, -+ 0x0541003c, 0x0541003b, 0x05410039, 0x05410037, -+ 0x04410044, 0x04410042, 0x04410040, 0x0441003e, -+ 0x0441003c, 0x0441003b, 0x04410039, 0x04410037, -+ 0x03410044, 0x03410042, 0x03410040, 0x0341003e, -+ 0x0341003c, 0x0341003b, 0x03410039, 0x03410037, -+ 0x02410044, 0x02410042, 0x02410040, 0x0241003e, -+ 0x0241003c, 0x0241003b, 0x02410039, 0x02410037, -+ 0x01410044, 0x01410042, 0x01410040, 0x0141003e, -+ 0x0141003c, 0x0141003b, 0x01410039, 0x01410037, -+ 0x00410044, 0x00410042, 0x00410040, 0x0041003e, -+ 0x0041003c, 0x0041003b, 0x00410039, 0x00410037 -+}; -+ -+static u32 nphy_tpc_txgain_epa_2057rev3[] = { -+ 0x80f90040, 0x80e10040, 0x80e1003c, 0x80c9003d, -+ 0x80b9003c, 0x80a9003d, 0x80a1003c, 0x8099003b, -+ 0x8091003b, 0x8089003a, 0x8081003a, 0x80790039, -+ 0x80710039, 0x8069003a, 0x8061003b, 0x8059003d, -+ 0x8051003f, 0x80490042, 0x8049003e, 0x8049003b, -+ 0x8041003e, 0x8041003b, 0x8039003e, 0x8039003b, -+ 0x80390038, 0x80390035, 0x8031003a, 0x80310036, -+ 0x80310033, 0x8029003a, 0x80290037, 0x80290034, -+ 0x80290031, 0x80210039, 0x80210036, 0x80210033, -+ 0x80210030, 0x8019003c, 0x80190039, 0x80190036, -+ 0x80190033, 0x80190030, 0x8019002d, 0x8019002b, -+ 0x80190028, 0x8011003a, 0x80110036, 0x80110033, -+ 0x80110030, 0x8011002e, 0x8011002b, 0x80110029, -+ 0x80110027, 0x80110024, 0x80110022, 0x80110020, -+ 0x8011001f, 0x8011001d, 0x8009003a, 0x80090037, -+ 0x80090034, 0x80090031, 0x8009002e, 0x8009002c, -+ 0x80090029, 0x80090027, 0x80090025, 0x80090023, -+ 0x80090021, 0x8009001f, 0x8009001d, 0x8009011d, -+ 0x8009021d, 0x8009031d, 0x8009041d, 0x8009051d, -+ 0x8009061d, 0x8009071d, 0x8009071d, 0x8009071d, -+ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, -+ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, -+ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, -+ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, -+ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, -+ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, -+ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, -+ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, -+ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, -+ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, -+ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, -+ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d -+}; -+ -+static u32 nphy_tpc_txgain_epa_2057rev5[] = { -+ 0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d, -+ 0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b, -+ 0x1091003b, 0x1089003a, 0x1081003a, 0x10790039, -+ 0x10710039, 0x1069003a, 0x1061003b, 0x1059003d, -+ 0x1051003f, 0x10490042, 0x1049003e, 0x1049003b, -+ 0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b, -+ 0x10390038, 0x10390035, 0x1031003a, 0x10310036, -+ 0x10310033, 0x1029003a, 0x10290037, 0x10290034, -+ 0x10290031, 0x10210039, 0x10210036, 0x10210033, -+ 0x10210030, 0x1019003c, 0x10190039, 0x10190036, -+ 0x10190033, 0x10190030, 0x1019002d, 0x1019002b, -+ 0x10190028, 0x1011003a, 0x10110036, 0x10110033, -+ 0x10110030, 0x1011002e, 0x1011002b, 0x10110029, -+ 0x10110027, 0x10110024, 0x10110022, 0x10110020, -+ 0x1011001f, 0x1011001d, 0x1009003a, 0x10090037, -+ 0x10090034, 0x10090031, 0x1009002e, 0x1009002c, -+ 0x10090029, 0x10090027, 0x10090025, 0x10090023, -+ 0x10090021, 0x1009001f, 0x1009001d, 0x1009001b, -+ 0x1009001a, 0x10090018, 0x10090017, 0x10090016, -+ 0x10090015, 0x10090013, 0x10090012, 0x10090011, -+ 0x10090010, 0x1009000f, 0x1009000f, 0x1009000e, -+ 0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b, -+ 0x1009000a, 0x1009000a, 0x10090009, 0x10090009, -+ 0x10090008, 0x10090008, 0x10090007, 0x10090007, -+ 0x10090007, 0x10090006, 0x10090006, 0x10090005, -+ 0x10090005, 0x10090005, 0x10090005, 0x10090004, -+ 0x10090004, 0x10090004, 0x10090004, 0x10090003, -+ 0x10090003, 0x10090003, 0x10090003, 0x10090003, -+ 0x10090003, 0x10090002, 0x10090002, 0x10090002, -+ 0x10090002, 0x10090002, 0x10090002, 0x10090002, -+ 0x10090002, 0x10090002, 0x10090001, 0x10090001, -+ 0x10090001, 0x10090001, 0x10090001, 0x10090001 -+}; -+ -+static u32 nphy_tpc_5GHz_txgain_rev3[] = { -+ 0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e, -+ 0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037, -+ 0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e, -+ 0xcef7003c, 0xcef7003b, 0xcef70039, 0xcef70037, -+ 0xcdf70044, 0xcdf70042, 0xcdf70040, 0xcdf7003e, -+ 0xcdf7003c, 0xcdf7003b, 0xcdf70039, 0xcdf70037, -+ 0xccf70044, 0xccf70042, 0xccf70040, 0xccf7003e, -+ 0xccf7003c, 0xccf7003b, 0xccf70039, 0xccf70037, -+ 0xcbf70044, 0xcbf70042, 0xcbf70040, 0xcbf7003e, -+ 0xcbf7003c, 0xcbf7003b, 0xcbf70039, 0xcbf70037, -+ 0xcaf70044, 0xcaf70042, 0xcaf70040, 0xcaf7003e, -+ 0xcaf7003c, 0xcaf7003b, 0xcaf70039, 0xcaf70037, -+ 0xc9f70044, 0xc9f70042, 0xc9f70040, 0xc9f7003e, -+ 0xc9f7003c, 0xc9f7003b, 0xc9f70039, 0xc9f70037, -+ 0xc8f70044, 0xc8f70042, 0xc8f70040, 0xc8f7003e, -+ 0xc8f7003c, 0xc8f7003b, 0xc8f70039, 0xc8f70037, -+ 0xc7f70044, 0xc7f70042, 0xc7f70040, 0xc7f7003e, -+ 0xc7f7003c, 0xc7f7003b, 0xc7f70039, 0xc7f70037, -+ 0xc6f70044, 0xc6f70042, 0xc6f70040, 0xc6f7003e, -+ 0xc6f7003c, 0xc6f7003b, 0xc6f70039, 0xc6f70037, -+ 0xc5f70044, 0xc5f70042, 0xc5f70040, 0xc5f7003e, -+ 0xc5f7003c, 0xc5f7003b, 0xc5f70039, 0xc5f70037, -+ 0xc4f70044, 0xc4f70042, 0xc4f70040, 0xc4f7003e, -+ 0xc4f7003c, 0xc4f7003b, 0xc4f70039, 0xc4f70037, -+ 0xc3f70044, 0xc3f70042, 0xc3f70040, 0xc3f7003e, -+ 0xc3f7003c, 0xc3f7003b, 0xc3f70039, 0xc3f70037, -+ 0xc2f70044, 0xc2f70042, 0xc2f70040, 0xc2f7003e, -+ 0xc2f7003c, 0xc2f7003b, 0xc2f70039, 0xc2f70037, -+ 0xc1f70044, 0xc1f70042, 0xc1f70040, 0xc1f7003e, -+ 0xc1f7003c, 0xc1f7003b, 0xc1f70039, 0xc1f70037, -+ 0xc0f70044, 0xc0f70042, 0xc0f70040, 0xc0f7003e, -+ 0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037 -+}; -+ -+static u32 nphy_tpc_5GHz_txgain_rev4[] = { -+ 0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e, -+ 0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037, -+ 0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e, -+ 0x2ef2003c, 0x2ef2003b, 0x2ef20039, 0x2ef20037, -+ 0x2df20044, 0x2df20042, 0x2df20040, 0x2df2003e, -+ 0x2df2003c, 0x2df2003b, 0x2df20039, 0x2df20037, -+ 0x2cf20044, 0x2cf20042, 0x2cf20040, 0x2cf2003e, -+ 0x2cf2003c, 0x2cf2003b, 0x2cf20039, 0x2cf20037, -+ 0x2bf20044, 0x2bf20042, 0x2bf20040, 0x2bf2003e, -+ 0x2bf2003c, 0x2bf2003b, 0x2bf20039, 0x2bf20037, -+ 0x2af20044, 0x2af20042, 0x2af20040, 0x2af2003e, -+ 0x2af2003c, 0x2af2003b, 0x2af20039, 0x2af20037, -+ 0x29f20044, 0x29f20042, 0x29f20040, 0x29f2003e, -+ 0x29f2003c, 0x29f2003b, 0x29f20039, 0x29f20037, -+ 0x28f20044, 0x28f20042, 0x28f20040, 0x28f2003e, -+ 0x28f2003c, 0x28f2003b, 0x28f20039, 0x28f20037, -+ 0x27f20044, 0x27f20042, 0x27f20040, 0x27f2003e, -+ 0x27f2003c, 0x27f2003b, 0x27f20039, 0x27f20037, -+ 0x26f20044, 0x26f20042, 0x26f20040, 0x26f2003e, -+ 0x26f2003c, 0x26f2003b, 0x26f20039, 0x26f20037, -+ 0x25f20044, 0x25f20042, 0x25f20040, 0x25f2003e, -+ 0x25f2003c, 0x25f2003b, 0x25f20039, 0x25f20037, -+ 0x24f20044, 0x24f20042, 0x24f20040, 0x24f2003e, -+ 0x24f2003c, 0x24f2003b, 0x24f20039, 0x24f20038, -+ 0x23f20041, 0x23f20040, 0x23f2003f, 0x23f2003e, -+ 0x23f2003c, 0x23f2003b, 0x23f20039, 0x23f20037, -+ 0x22f20044, 0x22f20042, 0x22f20040, 0x22f2003e, -+ 0x22f2003c, 0x22f2003b, 0x22f20039, 0x22f20037, -+ 0x21f20044, 0x21f20042, 0x21f20040, 0x21f2003e, -+ 0x21f2003c, 0x21f2003b, 0x21f20039, 0x21f20037, -+ 0x20d20043, 0x20d20041, 0x20d2003e, 0x20d2003c, -+ 0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034 -+}; -+ -+static u32 nphy_tpc_5GHz_txgain_rev5[] = { -+ 0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044, -+ 0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c, -+ 0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e, -+ 0x0e62003c, 0x0e62003d, 0x0e62003b, 0x0e62003a, -+ 0x0d620043, 0x0d620041, 0x0d620040, 0x0d62003e, -+ 0x0d62003d, 0x0d62003c, 0x0d62003b, 0x0d62003a, -+ 0x0c620041, 0x0c620040, 0x0c62003f, 0x0c62003e, -+ 0x0c62003c, 0x0c62003b, 0x0c620039, 0x0c620037, -+ 0x0b620046, 0x0b620044, 0x0b620042, 0x0b620040, -+ 0x0b62003e, 0x0b62003c, 0x0b62003b, 0x0b62003a, -+ 0x0a620041, 0x0a620040, 0x0a62003e, 0x0a62003c, -+ 0x0a62003b, 0x0a62003a, 0x0a620039, 0x0a620038, -+ 0x0962003e, 0x0962003d, 0x0962003c, 0x0962003b, -+ 0x09620039, 0x09620037, 0x09620035, 0x09620033, -+ 0x08620044, 0x08620042, 0x08620040, 0x0862003e, -+ 0x0862003c, 0x0862003b, 0x0862003a, 0x08620039, -+ 0x07620043, 0x07620042, 0x07620040, 0x0762003f, -+ 0x0762003d, 0x0762003b, 0x0762003a, 0x07620039, -+ 0x0662003e, 0x0662003d, 0x0662003c, 0x0662003b, -+ 0x06620039, 0x06620037, 0x06620035, 0x06620033, -+ 0x05620046, 0x05620044, 0x05620042, 0x05620040, -+ 0x0562003e, 0x0562003c, 0x0562003b, 0x05620039, -+ 0x04620044, 0x04620042, 0x04620040, 0x0462003e, -+ 0x0462003c, 0x0462003b, 0x04620039, 0x04620038, -+ 0x0362003c, 0x0362003b, 0x0362003a, 0x03620039, -+ 0x03620038, 0x03620037, 0x03620035, 0x03620033, -+ 0x0262004c, 0x0262004a, 0x02620048, 0x02620047, -+ 0x02620046, 0x02620044, 0x02620043, 0x02620042, -+ 0x0162004a, 0x01620048, 0x01620046, 0x01620044, -+ 0x01620043, 0x01620042, 0x01620041, 0x01620040, -+ 0x00620042, 0x00620040, 0x0062003e, 0x0062003c, -+ 0x0062003b, 0x00620039, 0x00620037, 0x00620035 -+}; -+ -+static u32 nphy_tpc_5GHz_txgain_HiPwrEPA[] = { -+ 0x2ff10044, 0x2ff10042, 0x2ff10040, 0x2ff1003e, -+ 0x2ff1003c, 0x2ff1003b, 0x2ff10039, 0x2ff10037, -+ 0x2ef10044, 0x2ef10042, 0x2ef10040, 0x2ef1003e, -+ 0x2ef1003c, 0x2ef1003b, 0x2ef10039, 0x2ef10037, -+ 0x2df10044, 0x2df10042, 0x2df10040, 0x2df1003e, -+ 0x2df1003c, 0x2df1003b, 0x2df10039, 0x2df10037, -+ 0x2cf10044, 0x2cf10042, 0x2cf10040, 0x2cf1003e, -+ 0x2cf1003c, 0x2cf1003b, 0x2cf10039, 0x2cf10037, -+ 0x2bf10044, 0x2bf10042, 0x2bf10040, 0x2bf1003e, -+ 0x2bf1003c, 0x2bf1003b, 0x2bf10039, 0x2bf10037, -+ 0x2af10044, 0x2af10042, 0x2af10040, 0x2af1003e, -+ 0x2af1003c, 0x2af1003b, 0x2af10039, 0x2af10037, -+ 0x29f10044, 0x29f10042, 0x29f10040, 0x29f1003e, -+ 0x29f1003c, 0x29f1003b, 0x29f10039, 0x29f10037, -+ 0x28f10044, 0x28f10042, 0x28f10040, 0x28f1003e, -+ 0x28f1003c, 0x28f1003b, 0x28f10039, 0x28f10037, -+ 0x27f10044, 0x27f10042, 0x27f10040, 0x27f1003e, -+ 0x27f1003c, 0x27f1003b, 0x27f10039, 0x27f10037, -+ 0x26f10044, 0x26f10042, 0x26f10040, 0x26f1003e, -+ 0x26f1003c, 0x26f1003b, 0x26f10039, 0x26f10037, -+ 0x25f10044, 0x25f10042, 0x25f10040, 0x25f1003e, -+ 0x25f1003c, 0x25f1003b, 0x25f10039, 0x25f10037, -+ 0x24f10044, 0x24f10042, 0x24f10040, 0x24f1003e, -+ 0x24f1003c, 0x24f1003b, 0x24f10039, 0x24f10038, -+ 0x23f10041, 0x23f10040, 0x23f1003f, 0x23f1003e, -+ 0x23f1003c, 0x23f1003b, 0x23f10039, 0x23f10037, -+ 0x22f10044, 0x22f10042, 0x22f10040, 0x22f1003e, -+ 0x22f1003c, 0x22f1003b, 0x22f10039, 0x22f10037, -+ 0x21f10044, 0x21f10042, 0x21f10040, 0x21f1003e, -+ 0x21f1003c, 0x21f1003b, 0x21f10039, 0x21f10037, -+ 0x20d10043, 0x20d10041, 0x20d1003e, 0x20d1003c, -+ 0x20d1003a, 0x20d10038, 0x20d10036, 0x20d10034 -+}; -+ -+static u8 ant_sw_ctrl_tbl_rev8_2o3[] = { 0x14, 0x18 }; -+static u8 ant_sw_ctrl_tbl_rev8[] = { 0x4, 0x8, 0x4, 0x8, 0x11, 0x12 }; -+static u8 ant_sw_ctrl_tbl_rev8_2057v7_core0[] = { -+ 0x09, 0x0a, 0x15, 0x16, 0x09, 0x0a -+}; -+static u8 ant_sw_ctrl_tbl_rev8_2057v7_core1[] = { -+ 0x09, 0x0a, 0x09, 0x0a, 0x15, 0x16 -+}; -+ -+bool wlc_phy_bist_check_phy(struct brcms_phy_pub *pih) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ u32 phybist0, phybist1, phybist2, phybist3, phybist4; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 16)) -+ return true; -+ -+ phybist0 = read_phy_reg(pi, 0x0e); -+ phybist1 = read_phy_reg(pi, 0x0f); -+ phybist2 = read_phy_reg(pi, 0xea); -+ phybist3 = read_phy_reg(pi, 0xeb); -+ phybist4 = read_phy_reg(pi, 0x156); -+ -+ if ((phybist0 == 0) && (phybist1 == 0x4000) && (phybist2 == 0x1fe0) && -+ (phybist3 == 0) && (phybist4 == 0)) -+ return true; -+ -+ return false; -+} -+ -+static void wlc_phy_bphy_init_nphy(struct brcms_phy *pi) -+{ -+ u16 addr, val; -+ -+ val = 0x1e1f; -+ for (addr = (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT); -+ addr <= (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT_END); addr++) { -+ write_phy_reg(pi, addr, val); -+ if (addr == (NPHY_TO_BPHY_OFF + 0x97)) -+ val = 0x3e3f; -+ else -+ val -= 0x0202; -+ } -+ -+ write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_STEP, 0x668); -+} -+ -+void -+wlc_phy_table_write_nphy(struct brcms_phy *pi, u32 id, u32 len, u32 offset, -+ u32 width, const void *data) -+{ -+ struct phytbl_info tbl; -+ -+ tbl.tbl_id = id; -+ tbl.tbl_len = len; -+ tbl.tbl_offset = offset; -+ tbl.tbl_width = width; -+ tbl.tbl_ptr = data; -+ wlc_phy_write_table_nphy(pi, &tbl); -+} -+ -+void -+wlc_phy_table_read_nphy(struct brcms_phy *pi, u32 id, u32 len, u32 offset, -+ u32 width, void *data) -+{ -+ struct phytbl_info tbl; -+ -+ tbl.tbl_id = id; -+ tbl.tbl_len = len; -+ tbl.tbl_offset = offset; -+ tbl.tbl_width = width; -+ tbl.tbl_ptr = data; -+ wlc_phy_read_table_nphy(pi, &tbl); -+} -+ -+static void -+wlc_phy_static_table_download_nphy(struct brcms_phy *pi) -+{ -+ uint idx; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 16)) { -+ for (idx = 0; idx < mimophytbl_info_sz_rev16; idx++) -+ wlc_phy_write_table_nphy(pi, -+ &mimophytbl_info_rev16[idx]); -+ } else if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ for (idx = 0; idx < mimophytbl_info_sz_rev7; idx++) -+ wlc_phy_write_table_nphy(pi, -+ &mimophytbl_info_rev7[idx]); -+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ for (idx = 0; idx < mimophytbl_info_sz_rev3; idx++) -+ wlc_phy_write_table_nphy(pi, -+ &mimophytbl_info_rev3[idx]); -+ } else { -+ for (idx = 0; idx < mimophytbl_info_sz_rev0; idx++) -+ wlc_phy_write_table_nphy(pi, -+ &mimophytbl_info_rev0[idx]); -+ } -+} -+ -+static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi) -+{ -+ uint idx = 0; -+ u8 antswctrllut; -+ -+ if (pi->phy_init_por) -+ wlc_phy_static_table_download_nphy(pi); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ? -+ pi->srom_fem2g.antswctrllut : pi->srom_fem5g. -+ antswctrllut; -+ -+ switch (antswctrllut) { -+ case 0: -+ -+ break; -+ -+ case 1: -+ -+ if (pi->aa2g == 7) -+ wlc_phy_table_write_nphy( -+ pi, -+ NPHY_TBL_ID_ANTSWCTRLLUT, -+ 2, 0x21, 8, -+ &ant_sw_ctrl_tbl_rev8_2o3[0]); -+ else -+ wlc_phy_table_write_nphy( -+ pi, -+ NPHY_TBL_ID_ANTSWCTRLLUT, -+ 2, 0x21, 8, -+ &ant_sw_ctrl_tbl_rev8 -+ [0]); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, -+ 2, 0x25, 8, -+ &ant_sw_ctrl_tbl_rev8[2]); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, -+ 2, 0x29, 8, -+ &ant_sw_ctrl_tbl_rev8[4]); -+ break; -+ -+ case 2: -+ -+ wlc_phy_table_write_nphy( -+ pi, NPHY_TBL_ID_ANTSWCTRLLUT, -+ 2, 0x1, 8, -+ &ant_sw_ctrl_tbl_rev8_2057v7_core0[0]); -+ wlc_phy_table_write_nphy( -+ pi, NPHY_TBL_ID_ANTSWCTRLLUT, -+ 2, 0x5, 8, -+ &ant_sw_ctrl_tbl_rev8_2057v7_core0[2]); -+ wlc_phy_table_write_nphy( -+ pi, NPHY_TBL_ID_ANTSWCTRLLUT, -+ 2, 0x9, 8, -+ &ant_sw_ctrl_tbl_rev8_2057v7_core0[4]); -+ -+ wlc_phy_table_write_nphy( -+ pi, NPHY_TBL_ID_ANTSWCTRLLUT, -+ 2, 0x21, 8, -+ &ant_sw_ctrl_tbl_rev8_2057v7_core1[0]); -+ wlc_phy_table_write_nphy( -+ pi, NPHY_TBL_ID_ANTSWCTRLLUT, -+ 2, 0x25, 8, -+ &ant_sw_ctrl_tbl_rev8_2057v7_core1[2]); -+ wlc_phy_table_write_nphy( -+ pi, NPHY_TBL_ID_ANTSWCTRLLUT, -+ 2, 0x29, 8, -+ &ant_sw_ctrl_tbl_rev8_2057v7_core1[4]); -+ break; -+ -+ default: -+ break; -+ } -+ -+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ for (idx = 0; idx < mimophytbl_info_sz_rev3_volatile; idx++) { -+ -+ if (idx == ANT_SWCTRL_TBL_REV3_IDX) { -+ antswctrllut = -+ CHSPEC_IS2G(pi->radio_chanspec) ? -+ pi->srom_fem2g.antswctrllut : -+ pi->srom_fem5g.antswctrllut; -+ switch (antswctrllut) { -+ case 0: -+ wlc_phy_write_table_nphy( -+ pi, -+ &mimophytbl_info_rev3_volatile -+ [idx]); -+ break; -+ case 1: -+ wlc_phy_write_table_nphy( -+ pi, -+ &mimophytbl_info_rev3_volatile1 -+ [idx]); -+ break; -+ case 2: -+ wlc_phy_write_table_nphy( -+ pi, -+ &mimophytbl_info_rev3_volatile2 -+ [idx]); -+ break; -+ case 3: -+ wlc_phy_write_table_nphy( -+ pi, -+ &mimophytbl_info_rev3_volatile3 -+ [idx]); -+ break; -+ default: -+ break; -+ } -+ } else { -+ wlc_phy_write_table_nphy( -+ pi, -+ &mimophytbl_info_rev3_volatile[idx]); -+ } -+ } -+ } else { -+ for (idx = 0; idx < mimophytbl_info_sz_rev0_volatile; idx++) -+ wlc_phy_write_table_nphy(pi, -+ &mimophytbl_info_rev0_volatile -+ [idx]); -+ } -+} -+ -+static void -+wlc_phy_write_txmacreg_nphy(struct brcms_phy *pi, u16 holdoff, u16 delay) -+{ -+ write_phy_reg(pi, 0x77, holdoff); -+ write_phy_reg(pi, 0xb4, delay); -+} -+ -+void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs) -+{ -+ u16 holdoff, delay; -+ -+ if (rifs) { -+ -+ holdoff = 0x10; -+ delay = 0x258; -+ } else { -+ -+ holdoff = 0x15; -+ delay = 0x320; -+ } -+ -+ wlc_phy_write_txmacreg_nphy(pi, holdoff, delay); -+ -+ if (pi && pi->sh && (pi->sh->_rifs_phy != rifs)) -+ pi->sh->_rifs_phy = rifs; -+} -+ -+static void wlc_phy_txpwrctrl_config_nphy(struct brcms_phy *pi) -+{ -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ pi->nphy_txpwrctrl = PHY_TPC_HW_ON; -+ pi->phy_5g_pwrgain = true; -+ return; -+ } -+ -+ pi->nphy_txpwrctrl = PHY_TPC_HW_OFF; -+ pi->phy_5g_pwrgain = false; -+ -+ if ((pi->sh->boardflags2 & BFL2_TXPWRCTRL_EN) && -+ NREV_GE(pi->pubpi.phy_rev, 2) && (pi->sh->sromrev >= 4)) -+ pi->nphy_txpwrctrl = PHY_TPC_HW_ON; -+ else if ((pi->sh->sromrev >= 4) -+ && (pi->sh->boardflags2 & BFL2_5G_PWRGAIN)) -+ pi->phy_5g_pwrgain = true; -+} -+ -+static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi) -+{ -+ u16 bw40po, cddpo, stbcpo, bwduppo; -+ uint band_num; -+ struct phy_shim_info *shim = pi->sh->physhim; -+ -+ if (pi->sh->sromrev >= 9) -+ return; -+ -+ bw40po = (u16) wlapi_getintvar(shim, BRCMS_SROM_BW40PO); -+ pi->bw402gpo = bw40po & 0xf; -+ pi->bw405gpo = (bw40po & 0xf0) >> 4; -+ pi->bw405glpo = (bw40po & 0xf00) >> 8; -+ pi->bw405ghpo = (bw40po & 0xf000) >> 12; -+ -+ cddpo = (u16) wlapi_getintvar(shim, BRCMS_SROM_CDDPO); -+ pi->cdd2gpo = cddpo & 0xf; -+ pi->cdd5gpo = (cddpo & 0xf0) >> 4; -+ pi->cdd5glpo = (cddpo & 0xf00) >> 8; -+ pi->cdd5ghpo = (cddpo & 0xf000) >> 12; -+ -+ stbcpo = (u16) wlapi_getintvar(shim, BRCMS_SROM_STBCPO); -+ pi->stbc2gpo = stbcpo & 0xf; -+ pi->stbc5gpo = (stbcpo & 0xf0) >> 4; -+ pi->stbc5glpo = (stbcpo & 0xf00) >> 8; -+ pi->stbc5ghpo = (stbcpo & 0xf000) >> 12; -+ -+ bwduppo = (u16) wlapi_getintvar(shim, BRCMS_SROM_BWDUPPO); -+ pi->bwdup2gpo = bwduppo & 0xf; -+ pi->bwdup5gpo = (bwduppo & 0xf0) >> 4; -+ pi->bwdup5glpo = (bwduppo & 0xf00) >> 8; -+ pi->bwdup5ghpo = (bwduppo & 0xf000) >> 12; -+ -+ for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); -+ band_num++) { -+ switch (band_num) { -+ case 0: -+ -+ pi->nphy_txpid2g[PHY_CORE_0] = -+ (u8) wlapi_getintvar(shim, -+ BRCMS_SROM_TXPID2GA0); -+ pi->nphy_txpid2g[PHY_CORE_1] = -+ (u8) wlapi_getintvar(shim, -+ BRCMS_SROM_TXPID2GA1); -+ pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g = -+ (s8) wlapi_getintvar(shim, -+ BRCMS_SROM_MAXP2GA0); -+ pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g = -+ (s8) wlapi_getintvar(shim, -+ BRCMS_SROM_MAXP2GA1); -+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA2GW0A0); -+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA2GW0A1); -+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA2GW1A0); -+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA2GW1A1); -+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA2GW2A0); -+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA2GW2A1); -+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g = -+ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT2GA0); -+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g = -+ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT2GA1); -+ -+ pi->cck2gpo = (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_CCK2GPO); -+ -+ pi->ofdm2gpo = -+ (u32) wlapi_getintvar(shim, -+ BRCMS_SROM_OFDM2GPO); -+ -+ pi->mcs2gpo[0] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS2GPO0); -+ pi->mcs2gpo[1] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS2GPO1); -+ pi->mcs2gpo[2] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS2GPO2); -+ pi->mcs2gpo[3] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS2GPO3); -+ pi->mcs2gpo[4] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS2GPO4); -+ pi->mcs2gpo[5] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS2GPO5); -+ pi->mcs2gpo[6] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS2GPO6); -+ pi->mcs2gpo[7] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS2GPO7); -+ break; -+ case 1: -+ -+ pi->nphy_txpid5g[PHY_CORE_0] = -+ (u8) wlapi_getintvar(shim, -+ BRCMS_SROM_TXPID5GA0); -+ pi->nphy_txpid5g[PHY_CORE_1] = -+ (u8) wlapi_getintvar(shim, -+ BRCMS_SROM_TXPID5GA1); -+ pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm = -+ (s8) wlapi_getintvar(shim, BRCMS_SROM_MAXP5GA0); -+ pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm = -+ (s8) wlapi_getintvar(shim, -+ BRCMS_SROM_MAXP5GA1); -+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GW0A0); -+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GW0A1); -+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GW1A0); -+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GW1A1); -+ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GW2A0); -+ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GW2A1); -+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm = -+ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT5GA0); -+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm = -+ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT5GA1); -+ -+ pi->ofdm5gpo = -+ (u32) wlapi_getintvar(shim, -+ BRCMS_SROM_OFDM5GPO); -+ -+ pi->mcs5gpo[0] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GPO0); -+ pi->mcs5gpo[1] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GPO1); -+ pi->mcs5gpo[2] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GPO2); -+ pi->mcs5gpo[3] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GPO3); -+ pi->mcs5gpo[4] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GPO4); -+ pi->mcs5gpo[5] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GPO5); -+ pi->mcs5gpo[6] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GPO6); -+ pi->mcs5gpo[7] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GPO7); -+ break; -+ case 2: -+ -+ pi->nphy_txpid5gl[0] = -+ (u8) wlapi_getintvar(shim, -+ BRCMS_SROM_TXPID5GLA0); -+ pi->nphy_txpid5gl[1] = -+ (u8) wlapi_getintvar(shim, -+ BRCMS_SROM_TXPID5GLA1); -+ pi->nphy_pwrctrl_info[0].max_pwr_5gl = -+ (s8) wlapi_getintvar(shim, -+ BRCMS_SROM_MAXP5GLA0); -+ pi->nphy_pwrctrl_info[1].max_pwr_5gl = -+ (s8) wlapi_getintvar(shim, -+ BRCMS_SROM_MAXP5GLA1); -+ pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GLW0A0); -+ pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GLW0A1); -+ pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GLW1A0); -+ pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GLW1A1); -+ pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GLW2A0); -+ pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GLW2A1); -+ pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0; -+ pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0; -+ -+ pi->ofdm5glpo = -+ (u32) wlapi_getintvar(shim, -+ BRCMS_SROM_OFDM5GLPO); -+ -+ pi->mcs5glpo[0] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GLPO0); -+ pi->mcs5glpo[1] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GLPO1); -+ pi->mcs5glpo[2] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GLPO2); -+ pi->mcs5glpo[3] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GLPO3); -+ pi->mcs5glpo[4] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GLPO4); -+ pi->mcs5glpo[5] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GLPO5); -+ pi->mcs5glpo[6] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GLPO6); -+ pi->mcs5glpo[7] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GLPO7); -+ break; -+ case 3: -+ -+ pi->nphy_txpid5gh[0] = -+ (u8) wlapi_getintvar(shim, -+ BRCMS_SROM_TXPID5GHA0); -+ pi->nphy_txpid5gh[1] = -+ (u8) wlapi_getintvar(shim, -+ BRCMS_SROM_TXPID5GHA1); -+ pi->nphy_pwrctrl_info[0].max_pwr_5gh = -+ (s8) wlapi_getintvar(shim, -+ BRCMS_SROM_MAXP5GHA0); -+ pi->nphy_pwrctrl_info[1].max_pwr_5gh = -+ (s8) wlapi_getintvar(shim, -+ BRCMS_SROM_MAXP5GHA1); -+ pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GHW0A0); -+ pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GHW0A1); -+ pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GHW1A0); -+ pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GHW1A1); -+ pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GHW2A0); -+ pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 = -+ (s16) wlapi_getintvar(shim, -+ BRCMS_SROM_PA5GHW2A1); -+ pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0; -+ pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0; -+ -+ pi->ofdm5ghpo = -+ (u32) wlapi_getintvar(shim, -+ BRCMS_SROM_OFDM5GHPO); -+ -+ pi->mcs5ghpo[0] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GHPO0); -+ pi->mcs5ghpo[1] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GHPO1); -+ pi->mcs5ghpo[2] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GHPO2); -+ pi->mcs5ghpo[3] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GHPO3); -+ pi->mcs5ghpo[4] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GHPO4); -+ pi->mcs5ghpo[5] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GHPO5); -+ pi->mcs5ghpo[6] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GHPO6); -+ pi->mcs5ghpo[7] = -+ (u16) wlapi_getintvar(shim, -+ BRCMS_SROM_MCS5GHPO7); -+ break; -+ } -+ } -+ -+ wlc_phy_txpwr_apply_nphy(pi); -+} -+ -+static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi) -+{ -+ struct phy_shim_info *shim = pi->sh->physhim; -+ -+ pi->antswitch = (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWITCH); -+ pi->aa2g = (u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G); -+ pi->aa5g = (u8) wlapi_getintvar(shim, BRCMS_SROM_AA5G); -+ -+ pi->srom_fem2g.tssipos = (u8) wlapi_getintvar(shim, -+ BRCMS_SROM_TSSIPOS2G); -+ pi->srom_fem2g.extpagain = (u8) wlapi_getintvar(shim, -+ BRCMS_SROM_EXTPAGAIN2G); -+ pi->srom_fem2g.pdetrange = (u8) wlapi_getintvar(shim, -+ BRCMS_SROM_PDETRANGE2G); -+ pi->srom_fem2g.triso = (u8) wlapi_getintvar(shim, BRCMS_SROM_TRISO2G); -+ pi->srom_fem2g.antswctrllut = -+ (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL2G); -+ -+ pi->srom_fem5g.tssipos = (u8) wlapi_getintvar(shim, -+ BRCMS_SROM_TSSIPOS5G); -+ pi->srom_fem5g.extpagain = (u8) wlapi_getintvar(shim, -+ BRCMS_SROM_EXTPAGAIN5G); -+ pi->srom_fem5g.pdetrange = (u8) wlapi_getintvar(shim, -+ BRCMS_SROM_PDETRANGE5G); -+ pi->srom_fem5g.triso = (u8) wlapi_getintvar(shim, BRCMS_SROM_TRISO5G); -+ if (wlapi_getvar(shim, BRCMS_SROM_ANTSWCTL5G)) -+ pi->srom_fem5g.antswctrllut = -+ (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL5G); -+ else -+ pi->srom_fem5g.antswctrllut = -+ (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL2G); -+ -+ wlc_phy_txpower_ipa_upd(pi); -+ -+ pi->phy_txcore_disable_temp = -+ (s16) wlapi_getintvar(shim, BRCMS_SROM_TEMPTHRESH); -+ if (pi->phy_txcore_disable_temp == 0) -+ pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP; -+ -+ pi->phy_tempsense_offset = (s8) wlapi_getintvar(shim, -+ BRCMS_SROM_TEMPOFFSET); -+ if (pi->phy_tempsense_offset != 0) { -+ if (pi->phy_tempsense_offset > -+ (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET)) -+ pi->phy_tempsense_offset = NPHY_SROM_MAXTEMPOFFSET; -+ else if (pi->phy_tempsense_offset < (NPHY_SROM_TEMPSHIFT + -+ NPHY_SROM_MINTEMPOFFSET)) -+ pi->phy_tempsense_offset = NPHY_SROM_MINTEMPOFFSET; -+ else -+ pi->phy_tempsense_offset -= NPHY_SROM_TEMPSHIFT; -+ } -+ -+ pi->phy_txcore_enable_temp = -+ pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP; -+ -+ pi->phycal_tempdelta = -+ (u8) wlapi_getintvar(shim, BRCMS_SROM_PHYCAL_TEMPDELTA); -+ if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA) -+ pi->phycal_tempdelta = 0; -+ -+ wlc_phy_txpwr_srom_read_ppr_nphy(pi); -+ -+ return true; -+} -+ -+bool wlc_phy_attach_nphy(struct brcms_phy *pi) -+{ -+ uint i; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 6)) -+ pi->phyhang_avoid = true; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) { -+ pi->nphy_gband_spurwar_en = true; -+ if (pi->sh->boardflags2 & BFL2_SPUR_WAR) -+ pi->nphy_aband_spurwar_en = true; -+ } -+ if (NREV_GE(pi->pubpi.phy_rev, 6) && NREV_LT(pi->pubpi.phy_rev, 7)) { -+ if (pi->sh->boardflags2 & BFL2_2G_SPUR_WAR) -+ pi->nphy_gband_spurwar2_en = true; -+ } -+ -+ pi->n_preamble_override = AUTO; -+ if (NREV_IS(pi->pubpi.phy_rev, 3) || NREV_IS(pi->pubpi.phy_rev, 4)) -+ pi->n_preamble_override = BRCMS_N_PREAMBLE_MIXEDMODE; -+ -+ pi->nphy_txrx_chain = AUTO; -+ pi->phy_scraminit = AUTO; -+ -+ pi->nphy_rxcalparams = 0x010100B5; -+ -+ pi->nphy_perical = PHY_PERICAL_MPHASE; -+ pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE; -+ pi->mphase_txcal_numcmds = MPHASE_TXCAL_NUMCMDS; -+ -+ pi->nphy_gain_boost = true; -+ pi->nphy_elna_gain_config = false; -+ pi->radio_is_on = false; -+ -+ for (i = 0; i < pi->pubpi.phy_corenum; i++) -+ pi->nphy_txpwrindex[i].index = AUTO; -+ -+ wlc_phy_txpwrctrl_config_nphy(pi); -+ if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON) -+ pi->hwpwrctrl_capable = true; -+ -+ pi->pi_fptr.init = wlc_phy_init_nphy; -+ pi->pi_fptr.calinit = wlc_phy_cal_init_nphy; -+ pi->pi_fptr.chanset = wlc_phy_chanspec_set_nphy; -+ pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_nphy; -+ -+ if (!wlc_phy_txpwr_srom_read_nphy(pi)) -+ return false; -+ -+ return true; -+} -+ -+static s32 get_rf_pwr_offset(struct brcms_phy *pi, s16 pga_gn, s16 pad_gn) -+{ -+ s32 rfpwr_offset = 0; -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if ((pi->pubpi.radiorev == 3) || -+ (pi->pubpi.radiorev == 4) || -+ (pi->pubpi.radiorev == 6)) -+ rfpwr_offset = (s16) -+ nphy_papd_padgain_dlt_2g_2057rev3n4 -+ [pad_gn]; -+ else if (pi->pubpi.radiorev == 5) -+ rfpwr_offset = (s16) -+ nphy_papd_padgain_dlt_2g_2057rev5 -+ [pad_gn]; -+ else if ((pi->pubpi.radiorev == 7) -+ || (pi->pubpi.radiorev == -+ 8)) -+ rfpwr_offset = (s16) -+ nphy_papd_padgain_dlt_2g_2057rev7 -+ [pad_gn]; -+ } else { -+ if ((pi->pubpi.radiorev == 3) || -+ (pi->pubpi.radiorev == 4) || -+ (pi->pubpi.radiorev == 6)) -+ rfpwr_offset = (s16) -+ nphy_papd_pgagain_dlt_5g_2057 -+ [pga_gn]; -+ else if ((pi->pubpi.radiorev == 7) -+ || (pi->pubpi.radiorev == -+ 8)) -+ rfpwr_offset = (s16) -+ nphy_papd_pgagain_dlt_5g_2057rev7 -+ [pga_gn]; -+ } -+ return rfpwr_offset; -+} -+ -+static void wlc_phy_update_mimoconfig_nphy(struct brcms_phy *pi, s32 preamble) -+{ -+ bool gf_preamble = false; -+ u16 val; -+ -+ if (preamble == BRCMS_N_PREAMBLE_GF) -+ gf_preamble = true; -+ -+ val = read_phy_reg(pi, 0xed); -+ -+ val |= RX_GF_MM_AUTO; -+ val &= ~RX_GF_OR_MM; -+ if (gf_preamble) -+ val |= RX_GF_OR_MM; -+ -+ write_phy_reg(pi, 0xed, val); -+} -+ -+static void wlc_phy_ipa_set_tx_digi_filts_nphy(struct brcms_phy *pi) -+{ -+ int j, type; -+ u16 addr_offset[] = { 0x186, 0x195, 0x2c5}; -+ -+ for (type = 0; type < 3; type++) { -+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) -+ write_phy_reg(pi, addr_offset[type] + j, -+ NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]); -+ } -+ -+ if (pi->bw == WL_CHANSPEC_BW_40) { -+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) -+ write_phy_reg(pi, 0x186 + j, -+ NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]); -+ } else { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) -+ write_phy_reg(pi, 0x186 + j, -+ NPHY_IPA_REV4_txdigi_filtcoeffs[5][j]); -+ } -+ -+ if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) { -+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) -+ write_phy_reg(pi, 0x2c5 + j, -+ NPHY_IPA_REV4_txdigi_filtcoeffs[6][j]); -+ } -+ } -+} -+ -+static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi) -+{ -+ int j; -+ -+ if (pi->bw == WL_CHANSPEC_BW_40) { -+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) -+ write_phy_reg(pi, 0x195 + j, -+ NPHY_IPA_REV4_txdigi_filtcoeffs[4][j]); -+ } else { -+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) -+ write_phy_reg(pi, 0x186 + j, -+ NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]); -+ } -+} -+ -+static void -+wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *events, u8 *dlys, -+ u8 len) -+{ -+ u32 t1_offset, t2_offset; -+ u8 ctr; -+ u8 end_event = -+ NREV_GE(pi->pubpi.phy_rev, -+ 3) ? NPHY_REV3_RFSEQ_CMD_END : NPHY_RFSEQ_CMD_END; -+ u8 end_dly = 1; -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ t1_offset = cmd << 4; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t1_offset, 8, -+ events); -+ t2_offset = t1_offset + 0x080; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t2_offset, 8, -+ dlys); -+ -+ for (ctr = len; ctr < 16; ctr++) { -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, -+ t1_offset + ctr, 8, &end_event); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, -+ t2_offset + ctr, 8, &end_dly); -+ } -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+} -+ -+static u16 wlc_phy_read_lpf_bw_ctl_nphy(struct brcms_phy *pi, u16 offset) -+{ -+ u16 lpf_bw_ctl_val = 0; -+ u16 rx2tx_lpf_rc_lut_offset = 0; -+ -+ if (offset == 0) { -+ if (CHSPEC_IS40(pi->radio_chanspec)) -+ rx2tx_lpf_rc_lut_offset = 0x159; -+ else -+ rx2tx_lpf_rc_lut_offset = 0x154; -+ } else { -+ rx2tx_lpf_rc_lut_offset = offset; -+ } -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, -+ (u32) rx2tx_lpf_rc_lut_offset, 16, -+ &lpf_bw_ctl_val); -+ -+ lpf_bw_ctl_val = lpf_bw_ctl_val & 0x7; -+ -+ return lpf_bw_ctl_val; -+} -+ -+static void -+wlc_phy_rfctrl_override_nphy_rev7(struct brcms_phy *pi, u16 field, u16 value, -+ u8 core_mask, u8 off, u8 override_id) -+{ -+ u8 core_num; -+ u16 addr = 0, en_addr = 0, val_addr = 0, en_mask = 0, val_mask = 0; -+ u8 val_shift = 0; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ en_mask = field; -+ for (core_num = 0; core_num < 2; core_num++) { -+ if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID0) { -+ -+ switch (field) { -+ case (0x1 << 2): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7a : -+ 0x7d; -+ val_mask = (0x1 << 1); -+ val_shift = 1; -+ break; -+ case (0x1 << 3): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7a : -+ 0x7d; -+ val_mask = (0x1 << 2); -+ val_shift = 2; -+ break; -+ case (0x1 << 4): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7a : -+ 0x7d; -+ val_mask = (0x1 << 4); -+ val_shift = 4; -+ break; -+ case (0x1 << 5): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7a : -+ 0x7d; -+ val_mask = (0x1 << 5); -+ val_shift = 5; -+ break; -+ case (0x1 << 6): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7a : -+ 0x7d; -+ val_mask = (0x1 << 6); -+ val_shift = 6; -+ break; -+ case (0x1 << 7): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7a : -+ 0x7d; -+ val_mask = (0x1 << 7); -+ val_shift = 7; -+ break; -+ case (0x1 << 10): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0xf8 : -+ 0xfa; -+ val_mask = (0x7 << 4); -+ val_shift = 4; -+ break; -+ case (0x1 << 11): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7b : -+ 0x7e; -+ val_mask = (0xffff << 0); -+ val_shift = 0; -+ break; -+ case (0x1 << 12): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7c : -+ 0x7f; -+ val_mask = (0xffff << 0); -+ val_shift = 0; -+ break; -+ case (0x3 << 13): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x348 : -+ 0x349; -+ val_mask = (0xff << 0); -+ val_shift = 0; -+ break; -+ case (0x1 << 13): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x348 : -+ 0x349; -+ val_mask = (0xf << 0); -+ val_shift = 0; -+ break; -+ default: -+ addr = 0xffff; -+ break; -+ } -+ } else if (override_id == -+ NPHY_REV7_RFCTRLOVERRIDE_ID1) { -+ -+ switch (field) { -+ case (0x1 << 1): -+ en_addr = (core_num == 0) ? 0x342 : -+ 0x343; -+ val_addr = (core_num == 0) ? 0x340 : -+ 0x341; -+ val_mask = (0x1 << 1); -+ val_shift = 1; -+ break; -+ case (0x1 << 3): -+ en_addr = (core_num == 0) ? 0x342 : -+ 0x343; -+ val_addr = (core_num == 0) ? 0x340 : -+ 0x341; -+ val_mask = (0x1 << 3); -+ val_shift = 3; -+ break; -+ case (0x1 << 5): -+ en_addr = (core_num == 0) ? 0x342 : -+ 0x343; -+ val_addr = (core_num == 0) ? 0x340 : -+ 0x341; -+ val_mask = (0x1 << 5); -+ val_shift = 5; -+ break; -+ case (0x1 << 4): -+ en_addr = (core_num == 0) ? 0x342 : -+ 0x343; -+ val_addr = (core_num == 0) ? 0x340 : -+ 0x341; -+ val_mask = (0x1 << 4); -+ val_shift = 4; -+ break; -+ case (0x1 << 2): -+ -+ en_addr = (core_num == 0) ? 0x342 : -+ 0x343; -+ val_addr = (core_num == 0) ? 0x340 : -+ 0x341; -+ val_mask = (0x1 << 2); -+ val_shift = 2; -+ break; -+ case (0x1 << 7): -+ -+ en_addr = (core_num == 0) ? 0x342 : -+ 0x343; -+ val_addr = (core_num == 0) ? 0x340 : -+ 0x341; -+ val_mask = (0x7 << 8); -+ val_shift = 8; -+ break; -+ case (0x1 << 11): -+ en_addr = (core_num == 0) ? 0x342 : -+ 0x343; -+ val_addr = (core_num == 0) ? 0x340 : -+ 0x341; -+ val_mask = (0x1 << 14); -+ val_shift = 14; -+ break; -+ case (0x1 << 10): -+ en_addr = (core_num == 0) ? 0x342 : -+ 0x343; -+ val_addr = (core_num == 0) ? 0x340 : -+ 0x341; -+ val_mask = (0x1 << 13); -+ val_shift = 13; -+ break; -+ case (0x1 << 9): -+ en_addr = (core_num == 0) ? 0x342 : -+ 0x343; -+ val_addr = (core_num == 0) ? 0x340 : -+ 0x341; -+ val_mask = (0x1 << 12); -+ val_shift = 12; -+ break; -+ case (0x1 << 8): -+ en_addr = (core_num == 0) ? 0x342 : -+ 0x343; -+ val_addr = (core_num == 0) ? 0x340 : -+ 0x341; -+ val_mask = (0x1 << 11); -+ val_shift = 11; -+ break; -+ case (0x1 << 6): -+ en_addr = (core_num == 0) ? 0x342 : -+ 0x343; -+ val_addr = (core_num == 0) ? 0x340 : -+ 0x341; -+ val_mask = (0x1 << 6); -+ val_shift = 6; -+ break; -+ case (0x1 << 0): -+ en_addr = (core_num == 0) ? 0x342 : -+ 0x343; -+ val_addr = (core_num == 0) ? 0x340 : -+ 0x341; -+ val_mask = (0x1 << 0); -+ val_shift = 0; -+ break; -+ default: -+ addr = 0xffff; -+ break; -+ } -+ } else if (override_id == -+ NPHY_REV7_RFCTRLOVERRIDE_ID2) { -+ -+ switch (field) { -+ case (0x1 << 3): -+ en_addr = (core_num == 0) ? 0x346 : -+ 0x347; -+ val_addr = (core_num == 0) ? 0x344 : -+ 0x345; -+ val_mask = (0x1 << 3); -+ val_shift = 3; -+ break; -+ case (0x1 << 1): -+ en_addr = (core_num == 0) ? 0x346 : -+ 0x347; -+ val_addr = (core_num == 0) ? 0x344 : -+ 0x345; -+ val_mask = (0x1 << 1); -+ val_shift = 1; -+ break; -+ case (0x1 << 0): -+ en_addr = (core_num == 0) ? 0x346 : -+ 0x347; -+ val_addr = (core_num == 0) ? 0x344 : -+ 0x345; -+ val_mask = (0x1 << 0); -+ val_shift = 0; -+ break; -+ case (0x1 << 2): -+ en_addr = (core_num == 0) ? 0x346 : -+ 0x347; -+ val_addr = (core_num == 0) ? 0x344 : -+ 0x345; -+ val_mask = (0x1 << 2); -+ val_shift = 2; -+ break; -+ case (0x1 << 4): -+ en_addr = (core_num == 0) ? 0x346 : -+ 0x347; -+ val_addr = (core_num == 0) ? 0x344 : -+ 0x345; -+ val_mask = (0x1 << 4); -+ val_shift = 4; -+ break; -+ default: -+ addr = 0xffff; -+ break; -+ } -+ } -+ -+ if (off) { -+ and_phy_reg(pi, en_addr, ~en_mask); -+ and_phy_reg(pi, val_addr, ~val_mask); -+ } else { -+ -+ if ((core_mask == 0) -+ || (core_mask & (1 << core_num))) { -+ or_phy_reg(pi, en_addr, en_mask); -+ -+ if (addr != 0xffff) -+ mod_phy_reg(pi, val_addr, -+ val_mask, -+ (value << -+ val_shift)); -+ } -+ } -+ } -+ } -+} -+ -+static void wlc_phy_adjust_lnagaintbl_nphy(struct brcms_phy *pi) -+{ -+ uint core; -+ int ctr; -+ s16 gain_delta[2]; -+ u8 curr_channel; -+ u16 minmax_gain[2]; -+ u16 regval[4]; -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ if (pi->nphy_gain_boost) { -+ if ((CHSPEC_IS2G(pi->radio_chanspec))) { -+ -+ gain_delta[0] = 6; -+ gain_delta[1] = 6; -+ } else { -+ -+ curr_channel = CHSPEC_CHANNEL(pi->radio_chanspec); -+ gain_delta[0] = -+ (s16) -+ PHY_HW_ROUND(((nphy_lnagain_est0[0] * -+ curr_channel) + -+ nphy_lnagain_est0[1]), 13); -+ gain_delta[1] = -+ (s16) -+ PHY_HW_ROUND(((nphy_lnagain_est1[0] * -+ curr_channel) + -+ nphy_lnagain_est1[1]), 13); -+ } -+ } else { -+ -+ gain_delta[0] = 0; -+ gain_delta[1] = 0; -+ } -+ -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ if (pi->nphy_elna_gain_config) { -+ -+ regval[0] = nphy_def_lnagains[2] + gain_delta[core]; -+ regval[1] = nphy_def_lnagains[3] + gain_delta[core]; -+ regval[2] = nphy_def_lnagains[3] + gain_delta[core]; -+ regval[3] = nphy_def_lnagains[3] + gain_delta[core]; -+ } else { -+ for (ctr = 0; ctr < 4; ctr++) -+ regval[ctr] = -+ nphy_def_lnagains[ctr] + -+ gain_delta[core]; -+ } -+ wlc_phy_table_write_nphy(pi, core, 4, 8, 16, regval); -+ -+ minmax_gain[core] = -+ (u16) (nphy_def_lnagains[2] + gain_delta[core] + 4); -+ } -+ -+ mod_phy_reg(pi, 0x1e, (0xff << 0), (minmax_gain[0] << 0)); -+ mod_phy_reg(pi, 0x34, (0xff << 0), (minmax_gain[1] << 0)); -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+} -+ -+static void -+wlc_phy_war_force_trsw_to_R_cliplo_nphy(struct brcms_phy *pi, u8 core) -+{ -+ if (core == PHY_CORE_0) { -+ write_phy_reg(pi, 0x38, 0x4); -+ if (CHSPEC_IS2G(pi->radio_chanspec)) -+ write_phy_reg(pi, 0x37, 0x0060); -+ else -+ write_phy_reg(pi, 0x37, 0x1080); -+ } else if (core == PHY_CORE_1) { -+ write_phy_reg(pi, 0x2ae, 0x4); -+ if (CHSPEC_IS2G(pi->radio_chanspec)) -+ write_phy_reg(pi, 0x2ad, 0x0060); -+ else -+ write_phy_reg(pi, 0x2ad, 0x1080); -+ } -+} -+ -+static void wlc_phy_war_txchain_upd_nphy(struct brcms_phy *pi, u8 txchain) -+{ -+ u8 txchain0, txchain1; -+ -+ txchain0 = txchain & 0x1; -+ txchain1 = (txchain & 0x2) >> 1; -+ if (!txchain0) -+ wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0); -+ -+ if (!txchain1) -+ wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1); -+} -+ -+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi) -+{ -+ s8 lna1_gain_db[] = { 8, 13, 17, 22 }; -+ s8 lna2_gain_db[] = { -2, 7, 11, 15 }; -+ s8 tia_gain_db[] = { -4, -1, 2, 5, 5, 5, 5, 5, 5, 5 }; -+ s8 tia_gainbits[] = { -+ 0x0, 0x01, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }; -+ -+ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13)); -+ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13)); -+ -+ mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0)); -+ -+ mod_phy_reg(pi, 0x283, (0xff << 0), (0x3c << 0)); -+ mod_phy_reg(pi, 0x280, (0xff << 0), (0x3c << 0)); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x8, 8, -+ lna1_gain_db); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x8, 8, -+ lna1_gain_db); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, 8, -+ lna2_gain_db); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, 8, -+ lna2_gain_db); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8, -+ tia_gain_db); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8, -+ tia_gain_db); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8, -+ tia_gainbits); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8, -+ tia_gainbits); -+ -+ write_phy_reg(pi, 0x37, 0x74); -+ write_phy_reg(pi, 0x2ad, 0x74); -+ write_phy_reg(pi, 0x38, 0x18); -+ write_phy_reg(pi, 0x2ae, 0x18); -+ -+ write_phy_reg(pi, 0x2b, 0xe8); -+ write_phy_reg(pi, 0x41, 0xe8); -+ -+ if (CHSPEC_IS20(pi->radio_chanspec)) { -+ -+ mod_phy_reg(pi, 0x300, (0x3f << 0), (0x12 << 0)); -+ mod_phy_reg(pi, 0x301, (0x3f << 0), (0x12 << 0)); -+ } else { -+ -+ mod_phy_reg(pi, 0x300, (0x3f << 0), (0x10 << 0)); -+ mod_phy_reg(pi, 0x301, (0x3f << 0), (0x10 << 0)); -+ } -+} -+ -+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) -+{ -+ u16 currband; -+ s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 }; -+ s8 *lna1_gain_db = NULL; -+ s8 *lna1_gain_db_2 = NULL; -+ s8 *lna2_gain_db = NULL; -+ s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 }; -+ s8 *tia_gain_db; -+ s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 }; -+ s8 *tia_gainbits; -+ u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f }; -+ u16 *rfseq_init_gain; -+ u16 init_gaincode; -+ u16 clip1hi_gaincode; -+ u16 clip1md_gaincode = 0; -+ u16 clip1md_gaincode_B; -+ u16 clip1lo_gaincode; -+ u16 clip1lo_gaincode_B; -+ u8 crsminl_th = 0; -+ u8 crsminu_th; -+ u16 nbclip_th = 0; -+ u8 w1clip_th; -+ u16 freq; -+ s8 nvar_baseline_offset0 = 0, nvar_baseline_offset1 = 0; -+ u8 chg_nbclip_th = 0; -+ -+ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13)); -+ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13)); -+ -+ currband = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; -+ if (currband == 0) { -+ -+ lna1_gain_db = lna1G_gain_db_rev7; -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8, -+ lna1_gain_db); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8, -+ lna1_gain_db); -+ -+ mod_phy_reg(pi, 0x283, (0xff << 0), (0x40 << 0)); -+ -+ if (CHSPEC_IS40(pi->radio_chanspec)) { -+ mod_phy_reg(pi, 0x280, (0xff << 0), (0x3e << 0)); -+ mod_phy_reg(pi, 0x283, (0xff << 0), (0x3e << 0)); -+ } -+ -+ mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0)); -+ -+ if (CHSPEC_IS20(pi->radio_chanspec)) { -+ mod_phy_reg(pi, 0x300, (0x3f << 0), (13 << 0)); -+ mod_phy_reg(pi, 0x301, (0x3f << 0), (13 << 0)); -+ } -+ } else { -+ -+ init_gaincode = 0x9e; -+ clip1hi_gaincode = 0x9e; -+ clip1md_gaincode_B = 0x24; -+ clip1lo_gaincode = 0x8a; -+ clip1lo_gaincode_B = 8; -+ rfseq_init_gain = rfseqA_init_gain_rev7; -+ -+ tia_gain_db = tiaA_gain_db_rev7; -+ tia_gainbits = tiaA_gainbits_rev7; -+ -+ freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec)); -+ if (CHSPEC_IS20(pi->radio_chanspec)) { -+ -+ w1clip_th = 25; -+ clip1md_gaincode = 0x82; -+ -+ if ((freq <= 5080) || (freq == 5825)) { -+ -+ s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 }; -+ s8 lna1A_gain_db_2_rev7[] = { -+ 11, 17, 22, 25}; -+ s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; -+ -+ crsminu_th = 0x3e; -+ lna1_gain_db = lna1A_gain_db_rev7; -+ lna1_gain_db_2 = lna1A_gain_db_2_rev7; -+ lna2_gain_db = lna2A_gain_db_rev7; -+ } else if ((freq >= 5500) && (freq <= 5700)) { -+ -+ s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 }; -+ s8 lna1A_gain_db_2_rev7[] = { -+ 12, 18, 22, 26}; -+ s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 }; -+ -+ crsminu_th = 0x45; -+ clip1md_gaincode_B = 0x14; -+ nbclip_th = 0xff; -+ chg_nbclip_th = 1; -+ lna1_gain_db = lna1A_gain_db_rev7; -+ lna1_gain_db_2 = lna1A_gain_db_2_rev7; -+ lna2_gain_db = lna2A_gain_db_rev7; -+ } else { -+ -+ s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 }; -+ s8 lna1A_gain_db_2_rev7[] = { -+ 12, 18, 22, 26}; -+ s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; -+ -+ crsminu_th = 0x41; -+ lna1_gain_db = lna1A_gain_db_rev7; -+ lna1_gain_db_2 = lna1A_gain_db_2_rev7; -+ lna2_gain_db = lna2A_gain_db_rev7; -+ } -+ -+ if (freq <= 4920) { -+ nvar_baseline_offset0 = 5; -+ nvar_baseline_offset1 = 5; -+ } else if ((freq > 4920) && (freq <= 5320)) { -+ nvar_baseline_offset0 = 3; -+ nvar_baseline_offset1 = 5; -+ } else if ((freq > 5320) && (freq <= 5700)) { -+ nvar_baseline_offset0 = 3; -+ nvar_baseline_offset1 = 2; -+ } else { -+ nvar_baseline_offset0 = 4; -+ nvar_baseline_offset1 = 0; -+ } -+ } else { -+ -+ crsminu_th = 0x3a; -+ crsminl_th = 0x3a; -+ w1clip_th = 20; -+ -+ if ((freq >= 4920) && (freq <= 5320)) { -+ nvar_baseline_offset0 = 4; -+ nvar_baseline_offset1 = 5; -+ } else if ((freq > 5320) && (freq <= 5550)) { -+ nvar_baseline_offset0 = 4; -+ nvar_baseline_offset1 = 2; -+ } else { -+ nvar_baseline_offset0 = 5; -+ nvar_baseline_offset1 = 3; -+ } -+ } -+ -+ write_phy_reg(pi, 0x20, init_gaincode); -+ write_phy_reg(pi, 0x2a7, init_gaincode); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, -+ pi->pubpi.phy_corenum, 0x106, 16, -+ rfseq_init_gain); -+ -+ write_phy_reg(pi, 0x22, clip1hi_gaincode); -+ write_phy_reg(pi, 0x2a9, clip1hi_gaincode); -+ -+ write_phy_reg(pi, 0x36, clip1md_gaincode_B); -+ write_phy_reg(pi, 0x2ac, clip1md_gaincode_B); -+ -+ write_phy_reg(pi, 0x37, clip1lo_gaincode); -+ write_phy_reg(pi, 0x2ad, clip1lo_gaincode); -+ write_phy_reg(pi, 0x38, clip1lo_gaincode_B); -+ write_phy_reg(pi, 0x2ae, clip1lo_gaincode_B); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8, -+ tia_gain_db); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8, -+ tia_gain_db); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8, -+ tia_gainbits); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8, -+ tia_gainbits); -+ -+ mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0)); -+ -+ if (chg_nbclip_th == 1) { -+ write_phy_reg(pi, 0x2b, nbclip_th); -+ write_phy_reg(pi, 0x41, nbclip_th); -+ } -+ -+ mod_phy_reg(pi, 0x300, (0x3f << 0), (w1clip_th << 0)); -+ mod_phy_reg(pi, 0x301, (0x3f << 0), (w1clip_th << 0)); -+ -+ mod_phy_reg(pi, 0x2e4, -+ (0x3f << 0), (nvar_baseline_offset0 << 0)); -+ -+ mod_phy_reg(pi, 0x2e4, -+ (0x3f << 6), (nvar_baseline_offset1 << 6)); -+ -+ if (CHSPEC_IS20(pi->radio_chanspec)) { -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8, -+ lna1_gain_db); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8, -+ lna1_gain_db_2); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, -+ 8, lna2_gain_db); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, -+ 8, lna2_gain_db); -+ -+ write_phy_reg(pi, 0x24, clip1md_gaincode); -+ write_phy_reg(pi, 0x2ab, clip1md_gaincode); -+ } else { -+ mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0)); -+ } -+ } -+} -+ -+static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) -+{ -+ u16 w1th, hpf_code, currband; -+ int ctr; -+ u8 rfseq_updategainu_events[] = { -+ NPHY_RFSEQ_CMD_RX_GAIN, -+ NPHY_RFSEQ_CMD_CLR_HIQ_DIS, -+ NPHY_RFSEQ_CMD_SET_HPF_BW -+ }; -+ u8 rfseq_updategainu_dlys[] = { 10, 30, 1 }; -+ s8 lna1G_gain_db[] = { 7, 11, 16, 23 }; -+ s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 }; -+ s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 }; -+ s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 }; -+ s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 }; -+ s8 lna1A_gain_db[] = { 7, 11, 17, 23 }; -+ s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 }; -+ s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 }; -+ s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 }; -+ s8 *lna1_gain_db = NULL; -+ s8 lna2G_gain_db[] = { -5, 6, 10, 14 }; -+ s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 }; -+ s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 }; -+ s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 }; -+ s8 lna2A_gain_db[] = { -6, 2, 6, 10 }; -+ s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 }; -+ s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 }; -+ s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 }; -+ s8 *lna2_gain_db = NULL; -+ s8 tiaG_gain_db[] = { -+ 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A }; -+ s8 tiaA_gain_db[] = { -+ 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 }; -+ s8 tiaA_gain_db_rev4[] = { -+ 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; -+ s8 tiaA_gain_db_rev5[] = { -+ 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; -+ s8 tiaA_gain_db_rev6[] = { -+ 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; -+ s8 *tia_gain_db; -+ s8 tiaG_gainbits[] = { -+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }; -+ s8 tiaA_gainbits[] = { -+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 }; -+ s8 tiaA_gainbits_rev4[] = { -+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; -+ s8 tiaA_gainbits_rev5[] = { -+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; -+ s8 tiaA_gainbits_rev6[] = { -+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; -+ s8 *tia_gainbits; -+ s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 }; -+ s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 }; -+ u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f }; -+ u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f }; -+ u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f }; -+ u16 rfseqG_init_gain_rev5_elna[] = { -+ 0x013f, 0x013f, 0x013f, 0x013f }; -+ u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f }; -+ u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f }; -+ u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f }; -+ u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f }; -+ u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f }; -+ u16 rfseqA_init_gain_rev4_elna[] = { -+ 0x314f, 0x314f, 0x314f, 0x314f }; -+ u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f }; -+ u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f }; -+ u16 *rfseq_init_gain; -+ u16 initG_gaincode = 0x627e; -+ u16 initG_gaincode_rev4 = 0x527e; -+ u16 initG_gaincode_rev5 = 0x427e; -+ u16 initG_gaincode_rev5_elna = 0x027e; -+ u16 initG_gaincode_rev6 = 0x527e; -+ u16 initG_gaincode_rev6_224B0 = 0x427e; -+ u16 initG_gaincode_rev6_elna = 0x127e; -+ u16 initA_gaincode = 0x52de; -+ u16 initA_gaincode_rev4 = 0x629e; -+ u16 initA_gaincode_rev4_elna = 0x329e; -+ u16 initA_gaincode_rev5 = 0x729e; -+ u16 initA_gaincode_rev6 = 0x729e; -+ u16 init_gaincode; -+ u16 clip1hiG_gaincode = 0x107e; -+ u16 clip1hiG_gaincode_rev4 = 0x007e; -+ u16 clip1hiG_gaincode_rev5 = 0x1076; -+ u16 clip1hiG_gaincode_rev6 = 0x007e; -+ u16 clip1hiA_gaincode = 0x00de; -+ u16 clip1hiA_gaincode_rev4 = 0x029e; -+ u16 clip1hiA_gaincode_rev5 = 0x029e; -+ u16 clip1hiA_gaincode_rev6 = 0x029e; -+ u16 clip1hi_gaincode; -+ u16 clip1mdG_gaincode = 0x0066; -+ u16 clip1mdA_gaincode = 0x00ca; -+ u16 clip1mdA_gaincode_rev4 = 0x1084; -+ u16 clip1mdA_gaincode_rev5 = 0x2084; -+ u16 clip1mdA_gaincode_rev6 = 0x2084; -+ u16 clip1md_gaincode = 0; -+ u16 clip1loG_gaincode = 0x0074; -+ u16 clip1loG_gaincode_rev5[] = { -+ 0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c -+ }; -+ u16 clip1loG_gaincode_rev6[] = { -+ 0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e -+ }; -+ u16 clip1loG_gaincode_rev6_224B0 = 0x1074; -+ u16 clip1loA_gaincode = 0x00cc; -+ u16 clip1loA_gaincode_rev4 = 0x0086; -+ u16 clip1loA_gaincode_rev5 = 0x2086; -+ u16 clip1loA_gaincode_rev6 = 0x2086; -+ u16 clip1lo_gaincode; -+ u8 crsminG_th = 0x18; -+ u8 crsminG_th_rev5 = 0x18; -+ u8 crsminG_th_rev6 = 0x18; -+ u8 crsminA_th = 0x1e; -+ u8 crsminA_th_rev4 = 0x24; -+ u8 crsminA_th_rev5 = 0x24; -+ u8 crsminA_th_rev6 = 0x24; -+ u8 crsmin_th; -+ u8 crsminlG_th = 0x18; -+ u8 crsminlG_th_rev5 = 0x18; -+ u8 crsminlG_th_rev6 = 0x18; -+ u8 crsminlA_th = 0x1e; -+ u8 crsminlA_th_rev4 = 0x24; -+ u8 crsminlA_th_rev5 = 0x24; -+ u8 crsminlA_th_rev6 = 0x24; -+ u8 crsminl_th = 0; -+ u8 crsminuG_th = 0x18; -+ u8 crsminuG_th_rev5 = 0x18; -+ u8 crsminuG_th_rev6 = 0x18; -+ u8 crsminuA_th = 0x1e; -+ u8 crsminuA_th_rev4 = 0x24; -+ u8 crsminuA_th_rev5 = 0x24; -+ u8 crsminuA_th_rev6 = 0x24; -+ u8 crsminuA_th_rev6_224B0 = 0x2d; -+ u8 crsminu_th; -+ u16 nbclipG_th = 0x20d; -+ u16 nbclipG_th_rev4 = 0x1a1; -+ u16 nbclipG_th_rev5 = 0x1d0; -+ u16 nbclipG_th_rev6 = 0x1d0; -+ u16 nbclipA_th = 0x1a1; -+ u16 nbclipA_th_rev4 = 0x107; -+ u16 nbclipA_th_rev5 = 0x0a9; -+ u16 nbclipA_th_rev6 = 0x0f0; -+ u16 nbclip_th = 0; -+ u8 w1clipG_th = 5; -+ u8 w1clipG_th_rev5 = 9; -+ u8 w1clipG_th_rev6 = 5; -+ u8 w1clipA_th = 25, w1clip_th; -+ u8 rssi_gain_default = 0x50; -+ u8 rssiG_gain_rev6_224B0 = 0x50; -+ u8 rssiA_gain_rev5 = 0x90; -+ u8 rssiA_gain_rev6 = 0x90; -+ u8 rssi_gain; -+ u16 regval[21]; -+ u8 triso; -+ -+ triso = (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.triso : -+ pi->srom_fem2g.triso; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ if (pi->pubpi.radiorev == 5) { -+ wlc_phy_workarounds_nphy_gainctrl_2057_rev5(pi); -+ } else if (pi->pubpi.radiorev == 7) { -+ wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi); -+ -+ mod_phy_reg(pi, 0x283, (0xff << 0), (0x44 << 0)); -+ mod_phy_reg(pi, 0x280, (0xff << 0), (0x44 << 0)); -+ -+ } else if ((pi->pubpi.radiorev == 3) -+ || (pi->pubpi.radiorev == 8)) { -+ wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi); -+ -+ if (pi->pubpi.radiorev == 8) { -+ mod_phy_reg(pi, 0x283, -+ (0xff << 0), (0x44 << 0)); -+ mod_phy_reg(pi, 0x280, -+ (0xff << 0), (0x44 << 0)); -+ } -+ } else { -+ wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi); -+ } -+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ -+ mod_phy_reg(pi, 0xa0, (0x1 << 6), (1 << 6)); -+ -+ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13)); -+ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13)); -+ -+ currband = -+ read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; -+ if (currband == 0) { -+ if (NREV_GE(pi->pubpi.phy_rev, 6)) { -+ if (pi->pubpi.radiorev == 11) { -+ lna1_gain_db = lna1G_gain_db_rev6_224B0; -+ lna2_gain_db = lna2G_gain_db_rev6_224B0; -+ rfseq_init_gain = -+ rfseqG_init_gain_rev6_224B0; -+ init_gaincode = -+ initG_gaincode_rev6_224B0; -+ clip1hi_gaincode = -+ clip1hiG_gaincode_rev6; -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev6_224B0; -+ nbclip_th = nbclipG_th_rev6; -+ w1clip_th = w1clipG_th_rev6; -+ crsmin_th = crsminG_th_rev6; -+ crsminl_th = crsminlG_th_rev6; -+ crsminu_th = crsminuG_th_rev6; -+ rssi_gain = rssiG_gain_rev6_224B0; -+ } else { -+ lna1_gain_db = lna1G_gain_db_rev6; -+ lna2_gain_db = lna2G_gain_db_rev6; -+ if (pi->sh->boardflags & BFL_EXTLNA) { -+ -+ rfseq_init_gain = -+ rfseqG_init_gain_rev6_elna; -+ init_gaincode = -+ initG_gaincode_rev6_elna; -+ } else { -+ rfseq_init_gain = -+ rfseqG_init_gain_rev6; -+ init_gaincode = -+ initG_gaincode_rev6; -+ } -+ clip1hi_gaincode = -+ clip1hiG_gaincode_rev6; -+ switch (triso) { -+ case 0: -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev6 -+ [0]; -+ break; -+ case 1: -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev6 -+ [1]; -+ break; -+ case 2: -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev6 -+ [2]; -+ break; -+ case 3: -+ default: -+ -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev6 -+ [3]; -+ break; -+ case 4: -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev6 -+ [4]; -+ break; -+ case 5: -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev6 -+ [5]; -+ break; -+ case 6: -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev6 -+ [6]; -+ break; -+ case 7: -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev6 -+ [7]; -+ break; -+ } -+ nbclip_th = nbclipG_th_rev6; -+ w1clip_th = w1clipG_th_rev6; -+ crsmin_th = crsminG_th_rev6; -+ crsminl_th = crsminlG_th_rev6; -+ crsminu_th = crsminuG_th_rev6; -+ rssi_gain = rssi_gain_default; -+ } -+ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { -+ lna1_gain_db = lna1G_gain_db_rev5; -+ lna2_gain_db = lna2G_gain_db_rev5; -+ if (pi->sh->boardflags & BFL_EXTLNA) { -+ -+ rfseq_init_gain = -+ rfseqG_init_gain_rev5_elna; -+ init_gaincode = -+ initG_gaincode_rev5_elna; -+ } else { -+ rfseq_init_gain = rfseqG_init_gain_rev5; -+ init_gaincode = initG_gaincode_rev5; -+ } -+ clip1hi_gaincode = clip1hiG_gaincode_rev5; -+ switch (triso) { -+ case 0: -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev5[0]; -+ break; -+ case 1: -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev5[1]; -+ break; -+ case 2: -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev5[2]; -+ break; -+ case 3: -+ -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev5[3]; -+ break; -+ case 4: -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev5[4]; -+ break; -+ case 5: -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev5[5]; -+ break; -+ case 6: -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev5[6]; -+ break; -+ case 7: -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev5[7]; -+ break; -+ default: -+ clip1lo_gaincode = -+ clip1loG_gaincode_rev5[3]; -+ break; -+ } -+ nbclip_th = nbclipG_th_rev5; -+ w1clip_th = w1clipG_th_rev5; -+ crsmin_th = crsminG_th_rev5; -+ crsminl_th = crsminlG_th_rev5; -+ crsminu_th = crsminuG_th_rev5; -+ rssi_gain = rssi_gain_default; -+ } else if (NREV_IS(pi->pubpi.phy_rev, 4)) { -+ lna1_gain_db = lna1G_gain_db_rev4; -+ lna2_gain_db = lna2G_gain_db; -+ rfseq_init_gain = rfseqG_init_gain_rev4; -+ init_gaincode = initG_gaincode_rev4; -+ clip1hi_gaincode = clip1hiG_gaincode_rev4; -+ clip1lo_gaincode = clip1loG_gaincode; -+ nbclip_th = nbclipG_th_rev4; -+ w1clip_th = w1clipG_th; -+ crsmin_th = crsminG_th; -+ crsminl_th = crsminlG_th; -+ crsminu_th = crsminuG_th; -+ rssi_gain = rssi_gain_default; -+ } else { -+ lna1_gain_db = lna1G_gain_db; -+ lna2_gain_db = lna2G_gain_db; -+ rfseq_init_gain = rfseqG_init_gain; -+ init_gaincode = initG_gaincode; -+ clip1hi_gaincode = clip1hiG_gaincode; -+ clip1lo_gaincode = clip1loG_gaincode; -+ nbclip_th = nbclipG_th; -+ w1clip_th = w1clipG_th; -+ crsmin_th = crsminG_th; -+ crsminl_th = crsminlG_th; -+ crsminu_th = crsminuG_th; -+ rssi_gain = rssi_gain_default; -+ } -+ tia_gain_db = tiaG_gain_db; -+ tia_gainbits = tiaG_gainbits; -+ clip1md_gaincode = clip1mdG_gaincode; -+ } else { -+ if (NREV_GE(pi->pubpi.phy_rev, 6)) { -+ lna1_gain_db = lna1A_gain_db_rev6; -+ lna2_gain_db = lna2A_gain_db_rev6; -+ tia_gain_db = tiaA_gain_db_rev6; -+ tia_gainbits = tiaA_gainbits_rev6; -+ rfseq_init_gain = rfseqA_init_gain_rev6; -+ init_gaincode = initA_gaincode_rev6; -+ clip1hi_gaincode = clip1hiA_gaincode_rev6; -+ clip1md_gaincode = clip1mdA_gaincode_rev6; -+ clip1lo_gaincode = clip1loA_gaincode_rev6; -+ crsmin_th = crsminA_th_rev6; -+ crsminl_th = crsminlA_th_rev6; -+ if ((pi->pubpi.radiorev == 11) && -+ (CHSPEC_IS40(pi->radio_chanspec) == 0)) -+ crsminu_th = crsminuA_th_rev6_224B0; -+ else -+ crsminu_th = crsminuA_th_rev6; -+ -+ nbclip_th = nbclipA_th_rev6; -+ rssi_gain = rssiA_gain_rev6; -+ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { -+ lna1_gain_db = lna1A_gain_db_rev5; -+ lna2_gain_db = lna2A_gain_db_rev5; -+ tia_gain_db = tiaA_gain_db_rev5; -+ tia_gainbits = tiaA_gainbits_rev5; -+ rfseq_init_gain = rfseqA_init_gain_rev5; -+ init_gaincode = initA_gaincode_rev5; -+ clip1hi_gaincode = clip1hiA_gaincode_rev5; -+ clip1md_gaincode = clip1mdA_gaincode_rev5; -+ clip1lo_gaincode = clip1loA_gaincode_rev5; -+ crsmin_th = crsminA_th_rev5; -+ crsminl_th = crsminlA_th_rev5; -+ crsminu_th = crsminuA_th_rev5; -+ nbclip_th = nbclipA_th_rev5; -+ rssi_gain = rssiA_gain_rev5; -+ } else if (NREV_IS(pi->pubpi.phy_rev, 4)) { -+ lna1_gain_db = lna1A_gain_db_rev4; -+ lna2_gain_db = lna2A_gain_db_rev4; -+ tia_gain_db = tiaA_gain_db_rev4; -+ tia_gainbits = tiaA_gainbits_rev4; -+ if (pi->sh->boardflags & BFL_EXTLNA_5GHz) { -+ -+ rfseq_init_gain = -+ rfseqA_init_gain_rev4_elna; -+ init_gaincode = -+ initA_gaincode_rev4_elna; -+ } else { -+ rfseq_init_gain = rfseqA_init_gain_rev4; -+ init_gaincode = initA_gaincode_rev4; -+ } -+ clip1hi_gaincode = clip1hiA_gaincode_rev4; -+ clip1md_gaincode = clip1mdA_gaincode_rev4; -+ clip1lo_gaincode = clip1loA_gaincode_rev4; -+ crsmin_th = crsminA_th_rev4; -+ crsminl_th = crsminlA_th_rev4; -+ crsminu_th = crsminuA_th_rev4; -+ nbclip_th = nbclipA_th_rev4; -+ rssi_gain = rssi_gain_default; -+ } else { -+ lna1_gain_db = lna1A_gain_db; -+ lna2_gain_db = lna2A_gain_db; -+ tia_gain_db = tiaA_gain_db; -+ tia_gainbits = tiaA_gainbits; -+ rfseq_init_gain = rfseqA_init_gain; -+ init_gaincode = initA_gaincode; -+ clip1hi_gaincode = clip1hiA_gaincode; -+ clip1md_gaincode = clip1mdA_gaincode; -+ clip1lo_gaincode = clip1loA_gaincode; -+ crsmin_th = crsminA_th; -+ crsminl_th = crsminlA_th; -+ crsminu_th = crsminuA_th; -+ nbclip_th = nbclipA_th; -+ rssi_gain = rssi_gain_default; -+ } -+ w1clip_th = w1clipA_th; -+ } -+ -+ write_radio_reg(pi, -+ (RADIO_2056_RX_BIASPOLE_LNAG1_IDAC | -+ RADIO_2056_RX0), 0x17); -+ write_radio_reg(pi, -+ (RADIO_2056_RX_BIASPOLE_LNAG1_IDAC | -+ RADIO_2056_RX1), 0x17); -+ -+ write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX0), -+ 0xf0); -+ write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX1), -+ 0xf0); -+ -+ write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX0), -+ 0x0); -+ write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX1), -+ 0x0); -+ -+ write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX0), -+ rssi_gain); -+ write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX1), -+ rssi_gain); -+ -+ write_radio_reg(pi, -+ (RADIO_2056_RX_BIASPOLE_LNAA1_IDAC | -+ RADIO_2056_RX0), 0x17); -+ write_radio_reg(pi, -+ (RADIO_2056_RX_BIASPOLE_LNAA1_IDAC | -+ RADIO_2056_RX1), 0x17); -+ -+ write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX0), -+ 0xFF); -+ write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX1), -+ 0xFF); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, -+ 8, lna1_gain_db); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, -+ 8, lna1_gain_db); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, -+ 8, lna2_gain_db); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, -+ 8, lna2_gain_db); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, -+ 8, tia_gain_db); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, -+ 8, tia_gain_db); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, -+ 8, tia_gainbits); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, -+ 8, tia_gainbits); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 6, 0x40, -+ 8, &lpf_gain_db); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 6, 0x40, -+ 8, &lpf_gain_db); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 6, 0x40, -+ 8, &lpf_gainbits); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 6, 0x40, -+ 8, &lpf_gainbits); -+ -+ write_phy_reg(pi, 0x20, init_gaincode); -+ write_phy_reg(pi, 0x2a7, init_gaincode); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, -+ pi->pubpi.phy_corenum, 0x106, 16, -+ rfseq_init_gain); -+ -+ write_phy_reg(pi, 0x22, clip1hi_gaincode); -+ write_phy_reg(pi, 0x2a9, clip1hi_gaincode); -+ -+ write_phy_reg(pi, 0x24, clip1md_gaincode); -+ write_phy_reg(pi, 0x2ab, clip1md_gaincode); -+ -+ write_phy_reg(pi, 0x37, clip1lo_gaincode); -+ write_phy_reg(pi, 0x2ad, clip1lo_gaincode); -+ -+ mod_phy_reg(pi, 0x27d, (0xff << 0), (crsmin_th << 0)); -+ mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0)); -+ mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0)); -+ -+ write_phy_reg(pi, 0x2b, nbclip_th); -+ write_phy_reg(pi, 0x41, nbclip_th); -+ -+ mod_phy_reg(pi, 0x27, (0x3f << 0), (w1clip_th << 0)); -+ mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1clip_th << 0)); -+ -+ write_phy_reg(pi, 0x150, 0x809c); -+ -+ } else { -+ -+ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13)); -+ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13)); -+ -+ write_phy_reg(pi, 0x2b, 0x84); -+ write_phy_reg(pi, 0x41, 0x84); -+ -+ if (CHSPEC_IS20(pi->radio_chanspec)) { -+ write_phy_reg(pi, 0x6b, 0x2b); -+ write_phy_reg(pi, 0x6c, 0x2b); -+ write_phy_reg(pi, 0x6d, 0x9); -+ write_phy_reg(pi, 0x6e, 0x9); -+ } -+ -+ w1th = NPHY_RSSICAL_W1_TARGET - 4; -+ mod_phy_reg(pi, 0x27, (0x3f << 0), (w1th << 0)); -+ mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1th << 0)); -+ -+ if (CHSPEC_IS20(pi->radio_chanspec)) { -+ mod_phy_reg(pi, 0x1c, (0x1f << 0), (0x1 << 0)); -+ mod_phy_reg(pi, 0x32, (0x1f << 0), (0x1 << 0)); -+ -+ mod_phy_reg(pi, 0x1d, (0x1f << 0), (0x1 << 0)); -+ mod_phy_reg(pi, 0x33, (0x1f << 0), (0x1 << 0)); -+ } -+ -+ write_phy_reg(pi, 0x150, 0x809c); -+ -+ if (pi->nphy_gain_boost) -+ if ((CHSPEC_IS2G(pi->radio_chanspec)) && -+ (CHSPEC_IS40(pi->radio_chanspec))) -+ hpf_code = 4; -+ else -+ hpf_code = 5; -+ else if (CHSPEC_IS40(pi->radio_chanspec)) -+ hpf_code = 6; -+ else -+ hpf_code = 7; -+ -+ mod_phy_reg(pi, 0x20, (0x1f << 7), (hpf_code << 7)); -+ mod_phy_reg(pi, 0x36, (0x1f << 7), (hpf_code << 7)); -+ -+ for (ctr = 0; ctr < 4; ctr++) -+ regval[ctr] = (hpf_code << 8) | 0x7c; -+ wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval); -+ -+ wlc_phy_adjust_lnagaintbl_nphy(pi); -+ -+ if (pi->nphy_elna_gain_config) { -+ regval[0] = 0; -+ regval[1] = 1; -+ regval[2] = 1; -+ regval[3] = 1; -+ wlc_phy_table_write_nphy(pi, 2, 4, 8, 16, regval); -+ wlc_phy_table_write_nphy(pi, 3, 4, 8, 16, regval); -+ -+ for (ctr = 0; ctr < 4; ctr++) -+ regval[ctr] = (hpf_code << 8) | 0x74; -+ wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval); -+ } -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 2)) { -+ for (ctr = 0; ctr < 21; ctr++) -+ regval[ctr] = 3 * ctr; -+ wlc_phy_table_write_nphy(pi, 0, 21, 32, 16, regval); -+ wlc_phy_table_write_nphy(pi, 1, 21, 32, 16, regval); -+ -+ for (ctr = 0; ctr < 21; ctr++) -+ regval[ctr] = (u16) ctr; -+ wlc_phy_table_write_nphy(pi, 2, 21, 32, 16, regval); -+ wlc_phy_table_write_nphy(pi, 3, 21, 32, 16, regval); -+ } -+ -+ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_UPDATEGAINU, -+ rfseq_updategainu_events, -+ rfseq_updategainu_dlys, -+ sizeof(rfseq_updategainu_events) / -+ sizeof(rfseq_updategainu_events[0])); -+ -+ mod_phy_reg(pi, 0x153, (0xff << 8), (90 << 8)); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) -+ mod_phy_reg(pi, -+ (NPHY_TO_BPHY_OFF + BPHY_OPTIONAL_MODES), -+ 0x7f, 0x4); -+ } -+} -+ -+static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) -+{ -+ u8 rfseq_rx2tx_events[] = { -+ NPHY_RFSEQ_CMD_NOP, -+ NPHY_RFSEQ_CMD_RXG_FBW, -+ NPHY_RFSEQ_CMD_TR_SWITCH, -+ NPHY_RFSEQ_CMD_CLR_HIQ_DIS, -+ NPHY_RFSEQ_CMD_RXPD_TXPD, -+ NPHY_RFSEQ_CMD_TX_GAIN, -+ NPHY_RFSEQ_CMD_EXT_PA -+ }; -+ u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 }; -+ u8 rfseq_tx2rx_events[] = { -+ NPHY_RFSEQ_CMD_NOP, -+ NPHY_RFSEQ_CMD_EXT_PA, -+ NPHY_RFSEQ_CMD_TX_GAIN, -+ NPHY_RFSEQ_CMD_RXPD_TXPD, -+ NPHY_RFSEQ_CMD_TR_SWITCH, -+ NPHY_RFSEQ_CMD_RXG_FBW, -+ NPHY_RFSEQ_CMD_CLR_HIQ_DIS -+ }; -+ u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 }; -+ u8 rfseq_tx2rx_events_rev3[] = { -+ NPHY_REV3_RFSEQ_CMD_EXT_PA, -+ NPHY_REV3_RFSEQ_CMD_INT_PA_PU, -+ NPHY_REV3_RFSEQ_CMD_TX_GAIN, -+ NPHY_REV3_RFSEQ_CMD_RXPD_TXPD, -+ NPHY_REV3_RFSEQ_CMD_TR_SWITCH, -+ NPHY_REV3_RFSEQ_CMD_RXG_FBW, -+ NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, -+ NPHY_REV3_RFSEQ_CMD_END -+ }; -+ u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 }; -+ u8 rfseq_rx2tx_events_rev3[] = { -+ NPHY_REV3_RFSEQ_CMD_NOP, -+ NPHY_REV3_RFSEQ_CMD_RXG_FBW, -+ NPHY_REV3_RFSEQ_CMD_TR_SWITCH, -+ NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, -+ NPHY_REV3_RFSEQ_CMD_RXPD_TXPD, -+ NPHY_REV3_RFSEQ_CMD_TX_GAIN, -+ NPHY_REV3_RFSEQ_CMD_INT_PA_PU, -+ NPHY_REV3_RFSEQ_CMD_EXT_PA, -+ NPHY_REV3_RFSEQ_CMD_END -+ }; -+ u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 }; -+ -+ u8 rfseq_rx2tx_events_rev3_ipa[] = { -+ NPHY_REV3_RFSEQ_CMD_NOP, -+ NPHY_REV3_RFSEQ_CMD_RXG_FBW, -+ NPHY_REV3_RFSEQ_CMD_TR_SWITCH, -+ NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, -+ NPHY_REV3_RFSEQ_CMD_RXPD_TXPD, -+ NPHY_REV3_RFSEQ_CMD_TX_GAIN, -+ NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS, -+ NPHY_REV3_RFSEQ_CMD_INT_PA_PU, -+ NPHY_REV3_RFSEQ_CMD_END -+ }; -+ u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; -+ u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f }; -+ -+ s16 alpha0, alpha1, alpha2; -+ s16 beta0, beta1, beta2; -+ u32 leg_data_weights, ht_data_weights, nss1_data_weights, -+ stbc_data_weights; -+ u8 chan_freq_range = 0; -+ u16 dac_control = 0x0002; -+ u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 }; -+ u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 }; -+ u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 }; -+ u16 aux_adc_vmid_rev3[] = { 0xa2, 0xb4, 0xb4, 0x89 }; -+ u16 *aux_adc_vmid; -+ u16 aux_adc_gain_rev7[] = { 0x02, 0x02, 0x02, 0x02 }; -+ u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 }; -+ u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 }; -+ u16 *aux_adc_gain; -+ u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 }; -+ u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 }; -+ s32 min_nvar_val = 0x18d; -+ s32 min_nvar_offset_6mbps = 20; -+ u8 pdetrange; -+ u8 triso; -+ u16 regval; -+ u16 afectrl_adc_ctrl1_rev7 = 0x20; -+ u16 afectrl_adc_ctrl2_rev7 = 0x0; -+ u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77; -+ u16 rfseq_tx2rx_lpf_h_hpc_rev7 = 0x77; -+ u16 rfseq_pktgn_lpf_h_hpc_rev7 = 0x77; -+ u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 }; -+ u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; -+ u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; -+ u16 ipalvlshift_3p3_war_en = 0; -+ u16 rccal_bcap_val, rccal_scap_val; -+ u16 rccal_tx20_11b_bcap = 0; -+ u16 rccal_tx20_11b_scap = 0; -+ u16 rccal_tx20_11n_bcap = 0; -+ u16 rccal_tx20_11n_scap = 0; -+ u16 rccal_tx40_11n_bcap = 0; -+ u16 rccal_tx40_11n_scap = 0; -+ u16 rx2tx_lpf_rc_lut_tx20_11b = 0; -+ u16 rx2tx_lpf_rc_lut_tx20_11n = 0; -+ u16 rx2tx_lpf_rc_lut_tx40_11n = 0; -+ u16 tx_lpf_bw_ofdm_20mhz = 0; -+ u16 tx_lpf_bw_ofdm_40mhz = 0; -+ u16 tx_lpf_bw_11b = 0; -+ u16 ipa2g_mainbias, ipa2g_casconv, ipa2g_biasfilt; -+ u16 txgm_idac_bleed = 0; -+ bool rccal_ovrd = false; -+ u16 freq; -+ int coreNum; -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) -+ wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 0); -+ else -+ wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 1); -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ or_phy_reg(pi, 0xb1, NPHY_IQFlip_ADC1 | NPHY_IQFlip_ADC2); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 7)) { -+ mod_phy_reg(pi, 0x221, (0x1 << 4), (1 << 4)); -+ -+ mod_phy_reg(pi, 0x160, (0x7f << 0), (32 << 0)); -+ mod_phy_reg(pi, 0x160, (0x7f << 8), (39 << 8)); -+ mod_phy_reg(pi, 0x161, (0x7f << 0), (46 << 0)); -+ mod_phy_reg(pi, 0x161, (0x7f << 8), (51 << 8)); -+ mod_phy_reg(pi, 0x162, (0x7f << 0), (55 << 0)); -+ mod_phy_reg(pi, 0x162, (0x7f << 8), (58 << 8)); -+ mod_phy_reg(pi, 0x163, (0x7f << 0), (60 << 0)); -+ mod_phy_reg(pi, 0x163, (0x7f << 8), (62 << 8)); -+ mod_phy_reg(pi, 0x164, (0x7f << 0), (62 << 0)); -+ mod_phy_reg(pi, 0x164, (0x7f << 8), (63 << 8)); -+ mod_phy_reg(pi, 0x165, (0x7f << 0), (63 << 0)); -+ mod_phy_reg(pi, 0x165, (0x7f << 8), (64 << 8)); -+ mod_phy_reg(pi, 0x166, (0x7f << 0), (64 << 0)); -+ mod_phy_reg(pi, 0x166, (0x7f << 8), (64 << 8)); -+ mod_phy_reg(pi, 0x167, (0x7f << 0), (64 << 0)); -+ mod_phy_reg(pi, 0x167, (0x7f << 8), (64 << 8)); -+ } -+ -+ if (NREV_LE(pi->pubpi.phy_rev, 8)) { -+ write_phy_reg(pi, 0x23f, 0x1b0); -+ write_phy_reg(pi, 0x240, 0x1b0); -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 8)) -+ mod_phy_reg(pi, 0xbd, (0xff << 0), (114 << 0)); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16, -+ &dac_control); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16, -+ &dac_control); -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, -+ 1, 0, 32, &leg_data_weights); -+ leg_data_weights = leg_data_weights & 0xffffff; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, -+ 1, 0, 32, &leg_data_weights); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, -+ 2, 0x15e, 16, -+ rfseq_rx2tx_dacbufpu_rev7); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x16e, 16, -+ rfseq_rx2tx_dacbufpu_rev7); -+ -+ if (PHY_IPA(pi)) -+ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, -+ rfseq_rx2tx_events_rev3_ipa, -+ rfseq_rx2tx_dlys_rev3_ipa, -+ sizeof -+ (rfseq_rx2tx_events_rev3_ipa) / -+ sizeof -+ (rfseq_rx2tx_events_rev3_ipa -+ [0])); -+ -+ mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14)); -+ mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14)); -+ -+ tx_lpf_bw_ofdm_20mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x154); -+ tx_lpf_bw_ofdm_40mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x159); -+ tx_lpf_bw_11b = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x152); -+ -+ if (PHY_IPA(pi)) { -+ -+ if (((pi->pubpi.radiorev == 5) -+ && (CHSPEC_IS40(pi->radio_chanspec) == 1)) -+ || (pi->pubpi.radiorev == 7) -+ || (pi->pubpi.radiorev == 8)) { -+ -+ rccal_bcap_val = -+ read_radio_reg( -+ pi, -+ RADIO_2057_RCCAL_BCAP_VAL); -+ rccal_scap_val = -+ read_radio_reg( -+ pi, -+ RADIO_2057_RCCAL_SCAP_VAL); -+ -+ rccal_tx20_11b_bcap = rccal_bcap_val; -+ rccal_tx20_11b_scap = rccal_scap_val; -+ -+ if ((pi->pubpi.radiorev == 5) && -+ (CHSPEC_IS40(pi->radio_chanspec) == 1)) { -+ -+ rccal_tx20_11n_bcap = rccal_bcap_val; -+ rccal_tx20_11n_scap = rccal_scap_val; -+ rccal_tx40_11n_bcap = 0xc; -+ rccal_tx40_11n_scap = 0xc; -+ -+ rccal_ovrd = true; -+ -+ } else if ((pi->pubpi.radiorev == 7) -+ || (pi->pubpi.radiorev == 8)) { -+ -+ tx_lpf_bw_ofdm_20mhz = 4; -+ tx_lpf_bw_11b = 1; -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ rccal_tx20_11n_bcap = 0xc; -+ rccal_tx20_11n_scap = 0xc; -+ rccal_tx40_11n_bcap = 0xa; -+ rccal_tx40_11n_scap = 0xa; -+ } else { -+ rccal_tx20_11n_bcap = 0x14; -+ rccal_tx20_11n_scap = 0x14; -+ rccal_tx40_11n_bcap = 0xf; -+ rccal_tx40_11n_scap = 0xf; -+ } -+ -+ rccal_ovrd = true; -+ } -+ } -+ -+ } else { -+ -+ if (pi->pubpi.radiorev == 5) { -+ -+ tx_lpf_bw_ofdm_20mhz = 1; -+ tx_lpf_bw_ofdm_40mhz = 3; -+ -+ rccal_bcap_val = -+ read_radio_reg( -+ pi, -+ RADIO_2057_RCCAL_BCAP_VAL); -+ rccal_scap_val = -+ read_radio_reg( -+ pi, -+ RADIO_2057_RCCAL_SCAP_VAL); -+ -+ rccal_tx20_11b_bcap = rccal_bcap_val; -+ rccal_tx20_11b_scap = rccal_scap_val; -+ -+ rccal_tx20_11n_bcap = 0x13; -+ rccal_tx20_11n_scap = 0x11; -+ rccal_tx40_11n_bcap = 0x13; -+ rccal_tx40_11n_scap = 0x11; -+ -+ rccal_ovrd = true; -+ } -+ } -+ -+ if (rccal_ovrd) { -+ -+ rx2tx_lpf_rc_lut_tx20_11b = -+ (rccal_tx20_11b_bcap << 8) | -+ (rccal_tx20_11b_scap << 3) | -+ tx_lpf_bw_11b; -+ rx2tx_lpf_rc_lut_tx20_11n = -+ (rccal_tx20_11n_bcap << 8) | -+ (rccal_tx20_11n_scap << 3) | -+ tx_lpf_bw_ofdm_20mhz; -+ rx2tx_lpf_rc_lut_tx40_11n = -+ (rccal_tx40_11n_bcap << 8) | -+ (rccal_tx40_11n_scap << 3) | -+ tx_lpf_bw_ofdm_40mhz; -+ -+ for (coreNum = 0; coreNum <= 1; coreNum++) { -+ wlc_phy_table_write_nphy( -+ pi, NPHY_TBL_ID_RFSEQ, -+ 1, -+ 0x152 + coreNum * 0x10, -+ 16, -+ &rx2tx_lpf_rc_lut_tx20_11b); -+ wlc_phy_table_write_nphy( -+ pi, NPHY_TBL_ID_RFSEQ, -+ 1, -+ 0x153 + coreNum * 0x10, -+ 16, -+ &rx2tx_lpf_rc_lut_tx20_11n); -+ wlc_phy_table_write_nphy( -+ pi, NPHY_TBL_ID_RFSEQ, -+ 1, -+ 0x154 + coreNum * 0x10, -+ 16, -+ &rx2tx_lpf_rc_lut_tx20_11n); -+ wlc_phy_table_write_nphy( -+ pi, NPHY_TBL_ID_RFSEQ, -+ 1, -+ 0x155 + coreNum * 0x10, -+ 16, -+ &rx2tx_lpf_rc_lut_tx40_11n); -+ wlc_phy_table_write_nphy( -+ pi, NPHY_TBL_ID_RFSEQ, -+ 1, -+ 0x156 + coreNum * 0x10, -+ 16, -+ &rx2tx_lpf_rc_lut_tx40_11n); -+ wlc_phy_table_write_nphy( -+ pi, NPHY_TBL_ID_RFSEQ, -+ 1, -+ 0x157 + coreNum * 0x10, -+ 16, -+ &rx2tx_lpf_rc_lut_tx40_11n); -+ wlc_phy_table_write_nphy( -+ pi, NPHY_TBL_ID_RFSEQ, -+ 1, -+ 0x158 + coreNum * 0x10, -+ 16, -+ &rx2tx_lpf_rc_lut_tx40_11n); -+ wlc_phy_table_write_nphy( -+ pi, NPHY_TBL_ID_RFSEQ, -+ 1, -+ 0x159 + coreNum * 0x10, -+ 16, -+ &rx2tx_lpf_rc_lut_tx40_11n); -+ } -+ -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 4), -+ 1, 0x3, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID2); -+ } -+ -+ write_phy_reg(pi, 0x32f, 0x3); -+ -+ if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 2), -+ 1, 0x3, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ -+ if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) || -+ (pi->pubpi.radiorev == 6)) { -+ if ((pi->sh->sromrev >= 8) -+ && (pi->sh->boardflags2 & BFL2_IPALVLSHIFT_3P3)) -+ ipalvlshift_3p3_war_en = 1; -+ -+ if (ipalvlshift_3p3_war_en) { -+ write_radio_reg(pi, RADIO_2057_GPAIO_CONFIG, -+ 0x5); -+ write_radio_reg(pi, RADIO_2057_GPAIO_SEL1, -+ 0x30); -+ write_radio_reg(pi, RADIO_2057_GPAIO_SEL0, 0x0); -+ or_radio_reg(pi, -+ RADIO_2057_RXTXBIAS_CONFIG_CORE0, -+ 0x1); -+ or_radio_reg(pi, -+ RADIO_2057_RXTXBIAS_CONFIG_CORE1, -+ 0x1); -+ -+ ipa2g_mainbias = 0x1f; -+ -+ ipa2g_casconv = 0x6f; -+ -+ ipa2g_biasfilt = 0xaa; -+ } else { -+ -+ ipa2g_mainbias = 0x2b; -+ -+ ipa2g_casconv = 0x7f; -+ -+ ipa2g_biasfilt = 0xee; -+ } -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ for (coreNum = 0; coreNum <= 1; coreNum++) { -+ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, -+ coreNum, IPA2G_IMAIN, -+ ipa2g_mainbias); -+ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, -+ coreNum, IPA2G_CASCONV, -+ ipa2g_casconv); -+ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, -+ coreNum, -+ IPA2G_BIAS_FILTER, -+ ipa2g_biasfilt); -+ } -+ } -+ } -+ -+ if (PHY_IPA(pi)) { -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if ((pi->pubpi.radiorev == 3) -+ || (pi->pubpi.radiorev == 4) -+ || (pi->pubpi.radiorev == 6)) -+ txgm_idac_bleed = 0x7f; -+ -+ for (coreNum = 0; coreNum <= 1; coreNum++) { -+ if (txgm_idac_bleed != 0) -+ WRITE_RADIO_REG4( -+ pi, RADIO_2057, -+ CORE, coreNum, -+ TXGM_IDAC_BLEED, -+ txgm_idac_bleed); -+ } -+ -+ if (pi->pubpi.radiorev == 5) { -+ -+ for (coreNum = 0; coreNum <= 1; -+ coreNum++) { -+ WRITE_RADIO_REG4(pi, RADIO_2057, -+ CORE, coreNum, -+ IPA2G_CASCONV, -+ 0x13); -+ WRITE_RADIO_REG4(pi, RADIO_2057, -+ CORE, coreNum, -+ IPA2G_IMAIN, -+ 0x1f); -+ WRITE_RADIO_REG4( -+ pi, RADIO_2057, -+ CORE, coreNum, -+ IPA2G_BIAS_FILTER, -+ 0xee); -+ WRITE_RADIO_REG4(pi, RADIO_2057, -+ CORE, coreNum, -+ PAD2G_IDACS, -+ 0x8a); -+ WRITE_RADIO_REG4( -+ pi, RADIO_2057, -+ CORE, coreNum, -+ PAD_BIAS_FILTER_BWS, -+ 0x3e); -+ } -+ -+ } else if ((pi->pubpi.radiorev == 7) -+ || (pi->pubpi.radiorev == 8)) { -+ -+ if (CHSPEC_IS40(pi->radio_chanspec) == -+ 0) { -+ WRITE_RADIO_REG4(pi, RADIO_2057, -+ CORE, 0, -+ IPA2G_IMAIN, -+ 0x14); -+ WRITE_RADIO_REG4(pi, RADIO_2057, -+ CORE, 1, -+ IPA2G_IMAIN, -+ 0x12); -+ } else { -+ WRITE_RADIO_REG4(pi, RADIO_2057, -+ CORE, 0, -+ IPA2G_IMAIN, -+ 0x16); -+ WRITE_RADIO_REG4(pi, RADIO_2057, -+ CORE, 1, -+ IPA2G_IMAIN, -+ 0x16); -+ } -+ } -+ -+ } else { -+ freq = CHAN5G_FREQ(CHSPEC_CHANNEL( -+ pi->radio_chanspec)); -+ if (((freq >= 5180) && (freq <= 5230)) -+ || ((freq >= 5745) && (freq <= 5805))) { -+ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, -+ 0, IPA5G_BIAS_FILTER, -+ 0xff); -+ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, -+ 1, IPA5G_BIAS_FILTER, -+ 0xff); -+ } -+ } -+ } else { -+ -+ if (pi->pubpi.radiorev != 5) { -+ for (coreNum = 0; coreNum <= 1; coreNum++) { -+ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, -+ coreNum, -+ TXMIX2G_TUNE_BOOST_PU, -+ 0x61); -+ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, -+ coreNum, -+ TXGM_IDAC_BLEED, 0x70); -+ } -+ } -+ } -+ -+ if (pi->pubpi.radiorev == 4) { -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, -+ 0x05, 16, -+ &afectrl_adc_ctrl1_rev7); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, -+ 0x15, 16, -+ &afectrl_adc_ctrl1_rev7); -+ -+ for (coreNum = 0; coreNum <= 1; coreNum++) { -+ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, -+ AFE_VCM_CAL_MASTER, 0x0); -+ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, -+ AFE_SET_VCM_I, 0x3f); -+ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, -+ AFE_SET_VCM_Q, 0x3f); -+ } -+ } else { -+ mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2)); -+ mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2)); -+ mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2)); -+ mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2)); -+ -+ mod_phy_reg(pi, 0xa6, (0x1 << 0), 0); -+ mod_phy_reg(pi, 0x8f, (0x1 << 0), (0x1 << 0)); -+ mod_phy_reg(pi, 0xa7, (0x1 << 0), 0); -+ mod_phy_reg(pi, 0xa5, (0x1 << 0), (0x1 << 0)); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, -+ 0x05, 16, -+ &afectrl_adc_ctrl2_rev7); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, -+ 0x15, 16, -+ &afectrl_adc_ctrl2_rev7); -+ -+ mod_phy_reg(pi, 0xa6, (0x1 << 2), 0); -+ mod_phy_reg(pi, 0x8f, (0x1 << 2), 0); -+ mod_phy_reg(pi, 0xa7, (0x1 << 2), 0); -+ mod_phy_reg(pi, 0xa5, (0x1 << 2), 0); -+ } -+ -+ write_phy_reg(pi, 0x6a, 0x2); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 256, 32, -+ &min_nvar_offset_6mbps); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x138, 16, -+ &rfseq_pktgn_lpf_hpc_rev7); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x141, 16, -+ &rfseq_pktgn_lpf_h_hpc_rev7); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 3, 0x133, 16, -+ &rfseq_htpktgn_lpf_hpc_rev7); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x146, 16, -+ &rfseq_cckpktgn_lpf_hpc_rev7); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x123, 16, -+ &rfseq_tx2rx_lpf_h_hpc_rev7); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x12A, 16, -+ &rfseq_rx2tx_lpf_h_hpc_rev7); -+ -+ if (CHSPEC_IS40(pi->radio_chanspec) == 0) { -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, -+ 32, &min_nvar_val); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, -+ 127, 32, &min_nvar_val); -+ } else { -+ min_nvar_val = noise_var_tbl_rev7[3]; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, -+ 32, &min_nvar_val); -+ -+ min_nvar_val = noise_var_tbl_rev7[127]; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, -+ 127, 32, &min_nvar_val); -+ } -+ -+ wlc_phy_workarounds_nphy_gainctrl(pi); -+ -+ pdetrange = -+ (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. -+ pdetrange : pi->srom_fem2g.pdetrange; -+ -+ if (pdetrange == 0) { -+ chan_freq_range = -+ wlc_phy_get_chan_freq_range_nphy(pi, 0); -+ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { -+ aux_adc_vmid_rev7_core0[3] = 0x70; -+ aux_adc_vmid_rev7_core1[3] = 0x70; -+ aux_adc_gain_rev7[3] = 2; -+ } else { -+ aux_adc_vmid_rev7_core0[3] = 0x80; -+ aux_adc_vmid_rev7_core1[3] = 0x80; -+ aux_adc_gain_rev7[3] = 3; -+ } -+ } else if (pdetrange == 1) { -+ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { -+ aux_adc_vmid_rev7_core0[3] = 0x7c; -+ aux_adc_vmid_rev7_core1[3] = 0x7c; -+ aux_adc_gain_rev7[3] = 2; -+ } else { -+ aux_adc_vmid_rev7_core0[3] = 0x8c; -+ aux_adc_vmid_rev7_core1[3] = 0x8c; -+ aux_adc_gain_rev7[3] = 1; -+ } -+ } else if (pdetrange == 2) { -+ if (pi->pubpi.radioid == BCM2057_ID) { -+ if ((pi->pubpi.radiorev == 5) -+ || (pi->pubpi.radiorev == 7) -+ || (pi->pubpi.radiorev == 8)) { -+ if (chan_freq_range == -+ WL_CHAN_FREQ_RANGE_2G) { -+ aux_adc_vmid_rev7_core0[3] = -+ 0x8c; -+ aux_adc_vmid_rev7_core1[3] = -+ 0x8c; -+ aux_adc_gain_rev7[3] = 0; -+ } else { -+ aux_adc_vmid_rev7_core0[3] = -+ 0x96; -+ aux_adc_vmid_rev7_core1[3] = -+ 0x96; -+ aux_adc_gain_rev7[3] = 0; -+ } -+ } -+ } -+ -+ } else if (pdetrange == 3) { -+ if (chan_freq_range == WL_CHAN_FREQ_RANGE_2G) { -+ aux_adc_vmid_rev7_core0[3] = 0x89; -+ aux_adc_vmid_rev7_core1[3] = 0x89; -+ aux_adc_gain_rev7[3] = 0; -+ } -+ -+ } else if (pdetrange == 5) { -+ -+ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { -+ aux_adc_vmid_rev7_core0[3] = 0x80; -+ aux_adc_vmid_rev7_core1[3] = 0x80; -+ aux_adc_gain_rev7[3] = 3; -+ } else { -+ aux_adc_vmid_rev7_core0[3] = 0x70; -+ aux_adc_vmid_rev7_core1[3] = 0x70; -+ aux_adc_gain_rev7[3] = 2; -+ } -+ } -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x08, 16, -+ &aux_adc_vmid_rev7_core0); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x18, 16, -+ &aux_adc_vmid_rev7_core1); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x0c, 16, -+ &aux_adc_gain_rev7); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x1c, 16, -+ &aux_adc_gain_rev7); -+ -+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ -+ write_phy_reg(pi, 0x23f, 0x1f8); -+ write_phy_reg(pi, 0x240, 0x1f8); -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, -+ 1, 0, 32, &leg_data_weights); -+ leg_data_weights = leg_data_weights & 0xffffff; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, -+ 1, 0, 32, &leg_data_weights); -+ -+ alpha0 = 293; -+ alpha1 = 435; -+ alpha2 = 261; -+ beta0 = 366; -+ beta1 = 205; -+ beta2 = 32; -+ write_phy_reg(pi, 0x145, alpha0); -+ write_phy_reg(pi, 0x146, alpha1); -+ write_phy_reg(pi, 0x147, alpha2); -+ write_phy_reg(pi, 0x148, beta0); -+ write_phy_reg(pi, 0x149, beta1); -+ write_phy_reg(pi, 0x14a, beta2); -+ -+ write_phy_reg(pi, 0x38, 0xC); -+ write_phy_reg(pi, 0x2ae, 0xC); -+ -+ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, -+ rfseq_tx2rx_events_rev3, -+ rfseq_tx2rx_dlys_rev3, -+ sizeof(rfseq_tx2rx_events_rev3) / -+ sizeof(rfseq_tx2rx_events_rev3[0])); -+ -+ if (PHY_IPA(pi)) -+ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, -+ rfseq_rx2tx_events_rev3_ipa, -+ rfseq_rx2tx_dlys_rev3_ipa, -+ sizeof -+ (rfseq_rx2tx_events_rev3_ipa) / -+ sizeof -+ (rfseq_rx2tx_events_rev3_ipa -+ [0])); -+ -+ if ((pi->sh->hw_phyrxchain != 0x3) && -+ (pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) { -+ -+ if (PHY_IPA(pi)) { -+ rfseq_rx2tx_dlys_rev3[5] = 59; -+ rfseq_rx2tx_dlys_rev3[6] = 1; -+ rfseq_rx2tx_events_rev3[7] = -+ NPHY_REV3_RFSEQ_CMD_END; -+ } -+ -+ wlc_phy_set_rfseq_nphy( -+ pi, NPHY_RFSEQ_RX2TX, -+ rfseq_rx2tx_events_rev3, -+ rfseq_rx2tx_dlys_rev3, -+ sizeof(rfseq_rx2tx_events_rev3) / -+ sizeof(rfseq_rx2tx_events_rev3[0])); -+ } -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) -+ write_phy_reg(pi, 0x6a, 0x2); -+ else -+ write_phy_reg(pi, 0x6a, 0x9c40); -+ -+ mod_phy_reg(pi, 0x294, (0xf << 8), (7 << 8)); -+ -+ if (CHSPEC_IS40(pi->radio_chanspec) == 0) { -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, -+ 32, &min_nvar_val); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, -+ 127, 32, &min_nvar_val); -+ } else { -+ min_nvar_val = noise_var_tbl_rev3[3]; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, -+ 32, &min_nvar_val); -+ -+ min_nvar_val = noise_var_tbl_rev3[127]; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, -+ 127, 32, &min_nvar_val); -+ } -+ -+ wlc_phy_workarounds_nphy_gainctrl(pi); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16, -+ &dac_control); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16, -+ &dac_control); -+ -+ pdetrange = -+ (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. -+ pdetrange : pi->srom_fem2g.pdetrange; -+ -+ if (pdetrange == 0) { -+ if (NREV_GE(pi->pubpi.phy_rev, 4)) { -+ aux_adc_vmid = aux_adc_vmid_rev4; -+ aux_adc_gain = aux_adc_gain_rev4; -+ } else { -+ aux_adc_vmid = aux_adc_vmid_rev3; -+ aux_adc_gain = aux_adc_gain_rev3; -+ } -+ chan_freq_range = -+ wlc_phy_get_chan_freq_range_nphy(pi, 0); -+ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { -+ switch (chan_freq_range) { -+ case WL_CHAN_FREQ_RANGE_5GL: -+ aux_adc_vmid[3] = 0x89; -+ aux_adc_gain[3] = 0; -+ break; -+ case WL_CHAN_FREQ_RANGE_5GM: -+ aux_adc_vmid[3] = 0x89; -+ aux_adc_gain[3] = 0; -+ break; -+ case WL_CHAN_FREQ_RANGE_5GH: -+ aux_adc_vmid[3] = 0x89; -+ aux_adc_gain[3] = 0; -+ break; -+ default: -+ break; -+ } -+ } -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, -+ 0x08, 16, aux_adc_vmid); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, -+ 0x18, 16, aux_adc_vmid); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, -+ 0x0c, 16, aux_adc_gain); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, -+ 0x1c, 16, aux_adc_gain); -+ } else if (pdetrange == 1) { -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, -+ 0x08, 16, sk_adc_vmid); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, -+ 0x18, 16, sk_adc_vmid); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, -+ 0x0c, 16, sk_adc_gain); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, -+ 0x1c, 16, sk_adc_gain); -+ } else if (pdetrange == 2) { -+ -+ u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x74 }; -+ u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x04 }; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 6)) { -+ chan_freq_range = -+ wlc_phy_get_chan_freq_range_nphy(pi, 0); -+ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { -+ bcm_adc_vmid[3] = 0x8e; -+ bcm_adc_gain[3] = 0x03; -+ } else { -+ bcm_adc_vmid[3] = 0x94; -+ bcm_adc_gain[3] = 0x03; -+ } -+ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { -+ bcm_adc_vmid[3] = 0x84; -+ bcm_adc_gain[3] = 0x02; -+ } -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, -+ 0x08, 16, bcm_adc_vmid); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, -+ 0x18, 16, bcm_adc_vmid); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, -+ 0x0c, 16, bcm_adc_gain); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, -+ 0x1c, 16, bcm_adc_gain); -+ } else if (pdetrange == 3) { -+ chan_freq_range = -+ wlc_phy_get_chan_freq_range_nphy(pi, 0); -+ if ((NREV_GE(pi->pubpi.phy_rev, 4)) -+ && (chan_freq_range == WL_CHAN_FREQ_RANGE_2G)) { -+ -+ u16 auxadc_vmid[] = { -+ 0xa2, 0xb4, 0xb4, 0x270 -+ }; -+ u16 auxadc_gain[] = { -+ 0x02, 0x02, 0x02, 0x00 -+ }; -+ -+ wlc_phy_table_write_nphy(pi, -+ NPHY_TBL_ID_AFECTRL, 4, -+ 0x08, 16, auxadc_vmid); -+ wlc_phy_table_write_nphy(pi, -+ NPHY_TBL_ID_AFECTRL, 4, -+ 0x18, 16, auxadc_vmid); -+ wlc_phy_table_write_nphy(pi, -+ NPHY_TBL_ID_AFECTRL, 4, -+ 0x0c, 16, auxadc_gain); -+ wlc_phy_table_write_nphy(pi, -+ NPHY_TBL_ID_AFECTRL, 4, -+ 0x1c, 16, auxadc_gain); -+ } -+ } else if ((pdetrange == 4) || (pdetrange == 5)) { -+ u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x0 }; -+ u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x0 }; -+ u16 Vmid[2], Av[2]; -+ -+ chan_freq_range = -+ wlc_phy_get_chan_freq_range_nphy(pi, 0); -+ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { -+ Vmid[0] = (pdetrange == 4) ? 0x8e : 0x89; -+ Vmid[1] = (pdetrange == 4) ? 0x96 : 0x89; -+ Av[0] = (pdetrange == 4) ? 2 : 0; -+ Av[1] = (pdetrange == 4) ? 2 : 0; -+ } else { -+ Vmid[0] = (pdetrange == 4) ? 0x89 : 0x74; -+ Vmid[1] = (pdetrange == 4) ? 0x8b : 0x70; -+ Av[0] = (pdetrange == 4) ? 2 : 0; -+ Av[1] = (pdetrange == 4) ? 2 : 0; -+ } -+ -+ bcm_adc_vmid[3] = Vmid[0]; -+ bcm_adc_gain[3] = Av[0]; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, -+ 0x08, 16, bcm_adc_vmid); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, -+ 0x0c, 16, bcm_adc_gain); -+ -+ bcm_adc_vmid[3] = Vmid[1]; -+ bcm_adc_gain[3] = Av[1]; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, -+ 0x18, 16, bcm_adc_vmid); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, -+ 0x1c, 16, bcm_adc_gain); -+ } -+ -+ write_radio_reg(pi, -+ (RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX0), -+ 0x0); -+ write_radio_reg(pi, -+ (RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX1), -+ 0x0); -+ -+ write_radio_reg(pi, -+ (RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX0), -+ 0x6); -+ write_radio_reg(pi, -+ (RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX1), -+ 0x6); -+ -+ write_radio_reg(pi, -+ (RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX0), -+ 0x7); -+ write_radio_reg(pi, -+ (RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX1), -+ 0x7); -+ -+ write_radio_reg(pi, -+ (RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX0), -+ 0x88); -+ write_radio_reg(pi, -+ (RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX1), -+ 0x88); -+ -+ write_radio_reg(pi, -+ (RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX0), -+ 0x0); -+ write_radio_reg(pi, -+ (RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX1), -+ 0x0); -+ -+ write_radio_reg(pi, -+ (RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX0), -+ 0x0); -+ write_radio_reg(pi, -+ (RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX1), -+ 0x0); -+ -+ triso = -+ (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. -+ triso : pi->srom_fem2g.triso; -+ if (triso == 7) { -+ wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0); -+ wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1); -+ } -+ -+ wlc_phy_war_txchain_upd_nphy(pi, pi->sh->hw_phytxchain); -+ -+ if (((pi->sh->boardflags2 & BFL2_APLL_WAR) && -+ (CHSPEC_IS5G(pi->radio_chanspec))) || -+ (((pi->sh->boardflags2 & BFL2_GPLL_WAR) || -+ (pi->sh->boardflags2 & BFL2_GPLL_WAR2)) && -+ (CHSPEC_IS2G(pi->radio_chanspec)))) { -+ nss1_data_weights = 0x00088888; -+ ht_data_weights = 0x00088888; -+ stbc_data_weights = 0x00088888; -+ } else { -+ nss1_data_weights = 0x88888888; -+ ht_data_weights = 0x88888888; -+ stbc_data_weights = 0x88888888; -+ } -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, -+ 1, 1, 32, &nss1_data_weights); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, -+ 1, 2, 32, &ht_data_weights); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, -+ 1, 3, 32, &stbc_data_weights); -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 4)) { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ write_radio_reg(pi, -+ RADIO_2056_TX_GMBB_IDAC | -+ RADIO_2056_TX0, 0x70); -+ write_radio_reg(pi, -+ RADIO_2056_TX_GMBB_IDAC | -+ RADIO_2056_TX1, 0x70); -+ } -+ } -+ -+ if (!pi->edcrs_threshold_lock) { -+ write_phy_reg(pi, 0x224, 0x3eb); -+ write_phy_reg(pi, 0x225, 0x3eb); -+ write_phy_reg(pi, 0x226, 0x341); -+ write_phy_reg(pi, 0x227, 0x341); -+ write_phy_reg(pi, 0x228, 0x42b); -+ write_phy_reg(pi, 0x229, 0x42b); -+ write_phy_reg(pi, 0x22a, 0x381); -+ write_phy_reg(pi, 0x22b, 0x381); -+ write_phy_reg(pi, 0x22c, 0x42b); -+ write_phy_reg(pi, 0x22d, 0x42b); -+ write_phy_reg(pi, 0x22e, 0x381); -+ write_phy_reg(pi, 0x22f, 0x381); -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 6)) { -+ -+ if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK) -+ wlapi_bmac_mhf(pi->sh->physhim, MHF4, -+ MHF4_BPHY_TXCORE0, -+ MHF4_BPHY_TXCORE0, BRCM_BAND_ALL); -+ } -+ } else { -+ -+ if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD || -+ (pi->sh->boardtype == 0x8b)) { -+ uint i; -+ u8 war_dlys[] = { 1, 6, 6, 2, 4, 20, 1 }; -+ for (i = 0; i < ARRAY_SIZE(rfseq_rx2tx_dlys); i++) -+ rfseq_rx2tx_dlys[i] = war_dlys[i]; -+ } -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec) && pi->phy_5g_pwrgain) { -+ and_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0xf7); -+ and_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0xf7); -+ } else { -+ or_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0x8); -+ or_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0x8); -+ } -+ -+ regval = 0x000a; -+ wlc_phy_table_write_nphy(pi, 8, 1, 0, 16, ®val); -+ wlc_phy_table_write_nphy(pi, 8, 1, 0x10, 16, ®val); -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 3)) { -+ regval = 0xcdaa; -+ wlc_phy_table_write_nphy(pi, 8, 1, 0x02, 16, ®val); -+ wlc_phy_table_write_nphy(pi, 8, 1, 0x12, 16, ®val); -+ } -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 2)) { -+ regval = 0x0000; -+ wlc_phy_table_write_nphy(pi, 8, 1, 0x08, 16, ®val); -+ wlc_phy_table_write_nphy(pi, 8, 1, 0x18, 16, ®val); -+ -+ regval = 0x7aab; -+ wlc_phy_table_write_nphy(pi, 8, 1, 0x07, 16, ®val); -+ wlc_phy_table_write_nphy(pi, 8, 1, 0x17, 16, ®val); -+ -+ regval = 0x0800; -+ wlc_phy_table_write_nphy(pi, 8, 1, 0x06, 16, ®val); -+ wlc_phy_table_write_nphy(pi, 8, 1, 0x16, 16, ®val); -+ } -+ -+ write_phy_reg(pi, 0xf8, 0x02d8); -+ write_phy_reg(pi, 0xf9, 0x0301); -+ write_phy_reg(pi, 0xfa, 0x02d8); -+ write_phy_reg(pi, 0xfb, 0x0301); -+ -+ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events, -+ rfseq_rx2tx_dlys, -+ sizeof(rfseq_rx2tx_events) / -+ sizeof(rfseq_rx2tx_events[0])); -+ -+ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, rfseq_tx2rx_events, -+ rfseq_tx2rx_dlys, -+ sizeof(rfseq_tx2rx_events) / -+ sizeof(rfseq_tx2rx_events[0])); -+ -+ wlc_phy_workarounds_nphy_gainctrl(pi); -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 2)) { -+ -+ if (read_phy_reg(pi, 0xa0) & NPHY_MLenable) -+ wlapi_bmac_mhf(pi->sh->physhim, MHF3, -+ MHF3_NPHY_MLADV_WAR, -+ MHF3_NPHY_MLADV_WAR, -+ BRCM_BAND_ALL); -+ -+ } else if (NREV_IS(pi->pubpi.phy_rev, 2)) { -+ write_phy_reg(pi, 0x1e3, 0x0); -+ write_phy_reg(pi, 0x1e4, 0x0); -+ } -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 2)) -+ mod_phy_reg(pi, 0x90, (0x1 << 7), 0); -+ -+ alpha0 = 293; -+ alpha1 = 435; -+ alpha2 = 261; -+ beta0 = 366; -+ beta1 = 205; -+ beta2 = 32; -+ write_phy_reg(pi, 0x145, alpha0); -+ write_phy_reg(pi, 0x146, alpha1); -+ write_phy_reg(pi, 0x147, alpha2); -+ write_phy_reg(pi, 0x148, beta0); -+ write_phy_reg(pi, 0x149, beta1); -+ write_phy_reg(pi, 0x14a, beta2); -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 3)) { -+ mod_phy_reg(pi, 0x142, (0xf << 12), 0); -+ -+ write_phy_reg(pi, 0x192, 0xb5); -+ write_phy_reg(pi, 0x193, 0xa4); -+ write_phy_reg(pi, 0x194, 0x0); -+ } -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 2)) -+ mod_phy_reg(pi, 0x221, -+ NPHY_FORCESIG_DECODEGATEDCLKS, -+ NPHY_FORCESIG_DECODEGATEDCLKS); -+ } -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+} -+ -+static void wlc_phy_extpa_set_tx_digi_filts_nphy(struct brcms_phy *pi) -+{ -+ int j, type = 2; -+ u16 addr_offset = 0x2c5; -+ -+ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) -+ write_phy_reg(pi, addr_offset + j, -+ NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]); -+} -+ -+static void wlc_phy_clip_det_nphy(struct brcms_phy *pi, u8 write, u16 *vals) -+{ -+ -+ if (write == 0) { -+ vals[0] = read_phy_reg(pi, 0x2c); -+ vals[1] = read_phy_reg(pi, 0x42); -+ } else { -+ write_phy_reg(pi, 0x2c, vals[0]); -+ write_phy_reg(pi, 0x42, vals[1]); -+ } -+} -+ -+static void wlc_phy_ipa_internal_tssi_setup_nphy(struct brcms_phy *pi) -+{ -+ u8 core; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TX_SSI_MASTER, 0x5); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TX_SSI_MUX, 0xe); -+ -+ if (pi->pubpi.radiorev != 5) -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, -+ core, TSSIA, 0); -+ -+ if (!NREV_IS(pi->pubpi.phy_rev, 7)) -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, -+ core, TSSIG, 0x1); -+ else -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, -+ core, TSSIG, 0x31); -+ } else { -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TX_SSI_MASTER, 0x9); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TX_SSI_MUX, 0xc); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TSSIG, 0); -+ -+ if (pi->pubpi.radiorev != 5) { -+ if (!NREV_IS(pi->pubpi.phy_rev, 7)) -+ WRITE_RADIO_REG3(pi, RADIO_2057, -+ TX, core, -+ TSSIA, 0x1); -+ else -+ WRITE_RADIO_REG3(pi, RADIO_2057, -+ TX, core, -+ TSSIA, 0x31); -+ } -+ } -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG, -+ 0); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC, -+ 0); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM, -+ 0x3); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1, -+ 0x0); -+ } -+ } else { -+ WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR31, -+ (CHSPEC_IS2G(pi->radio_chanspec)) ? 0x128 : -+ 0x80); -+ WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR30, 0x0); -+ WRITE_RADIO_SYN(pi, RADIO_2056, GPIO_MASTER1, 0x29); -+ -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_VCM_HG, -+ 0x0); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_IDAC, -+ 0x0); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_VCM, -+ 0x3); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TX_AMP_DET, -+ 0x0); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC1, -+ 0x8); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC2, -+ 0x0); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC3, -+ 0x0); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ TX_SSI_MASTER, 0x5); -+ -+ if (pi->pubpi.radiorev != 5) -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, -+ core, TSSIA, 0x0); -+ if (NREV_GE(pi->pubpi.phy_rev, 5)) -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, -+ core, TSSIG, 0x31); -+ else -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, -+ core, TSSIG, 0x11); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ TX_SSI_MUX, 0xe); -+ } else { -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ TX_SSI_MASTER, 0x9); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ TSSIA, 0x31); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ TSSIG, 0x0); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ TX_SSI_MUX, 0xc); -+ } -+ } -+ } -+} -+ -+static void -+wlc_phy_rfctrl_override_nphy(struct brcms_phy *pi, u16 field, u16 value, -+ u8 core_mask, u8 off) -+{ -+ u8 core_num; -+ u16 addr = 0, mask = 0, en_addr = 0, val_addr = 0, en_mask = -+ 0, val_mask = 0; -+ u8 shift = 0, val_shift = 0; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) { -+ -+ en_mask = field; -+ for (core_num = 0; core_num < 2; core_num++) { -+ -+ switch (field) { -+ case (0x1 << 1): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7a : 0x7d; -+ val_mask = (0x1 << 0); -+ val_shift = 0; -+ break; -+ case (0x1 << 2): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7a : 0x7d; -+ val_mask = (0x1 << 1); -+ val_shift = 1; -+ break; -+ case (0x1 << 3): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7a : 0x7d; -+ val_mask = (0x1 << 2); -+ val_shift = 2; -+ break; -+ case (0x1 << 4): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7a : 0x7d; -+ val_mask = (0x1 << 4); -+ val_shift = 4; -+ break; -+ case (0x1 << 5): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7a : 0x7d; -+ val_mask = (0x1 << 5); -+ val_shift = 5; -+ break; -+ case (0x1 << 6): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7a : 0x7d; -+ val_mask = (0x1 << 6); -+ val_shift = 6; -+ break; -+ case (0x1 << 7): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7a : 0x7d; -+ val_mask = (0x1 << 7); -+ val_shift = 7; -+ break; -+ case (0x1 << 8): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7a : 0x7d; -+ val_mask = (0x7 << 8); -+ val_shift = 8; -+ break; -+ case (0x1 << 11): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7a : 0x7d; -+ val_mask = (0x7 << 13); -+ val_shift = 13; -+ break; -+ -+ case (0x1 << 9): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0xf8 : 0xfa; -+ val_mask = (0x7 << 0); -+ val_shift = 0; -+ break; -+ -+ case (0x1 << 10): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0xf8 : 0xfa; -+ val_mask = (0x7 << 4); -+ val_shift = 4; -+ break; -+ -+ case (0x1 << 12): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7b : 0x7e; -+ val_mask = (0xffff << 0); -+ val_shift = 0; -+ break; -+ case (0x1 << 13): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0x7c : 0x7f; -+ val_mask = (0xffff << 0); -+ val_shift = 0; -+ break; -+ case (0x1 << 14): -+ en_addr = (core_num == 0) ? 0xe7 : 0xec; -+ val_addr = (core_num == 0) ? 0xf9 : 0xfb; -+ val_mask = (0x3 << 6); -+ val_shift = 6; -+ break; -+ case (0x1 << 0): -+ en_addr = (core_num == 0) ? 0xe5 : 0xe6; -+ val_addr = (core_num == 0) ? 0xf9 : 0xfb; -+ val_mask = (0x1 << 15); -+ val_shift = 15; -+ break; -+ default: -+ addr = 0xffff; -+ break; -+ } -+ -+ if (off) { -+ and_phy_reg(pi, en_addr, ~en_mask); -+ and_phy_reg(pi, val_addr, ~val_mask); -+ } else { -+ -+ if ((core_mask == 0) -+ || (core_mask & (1 << core_num))) { -+ or_phy_reg(pi, en_addr, en_mask); -+ -+ if (addr != 0xffff) -+ mod_phy_reg(pi, val_addr, -+ val_mask, -+ (value << -+ val_shift)); -+ } -+ } -+ } -+ } else { -+ -+ if (off) { -+ and_phy_reg(pi, 0xec, ~field); -+ value = 0x0; -+ } else { -+ or_phy_reg(pi, 0xec, field); -+ } -+ -+ for (core_num = 0; core_num < 2; core_num++) { -+ -+ switch (field) { -+ case (0x1 << 1): -+ case (0x1 << 9): -+ case (0x1 << 12): -+ case (0x1 << 13): -+ case (0x1 << 14): -+ addr = 0x78; -+ -+ core_mask = 0x1; -+ break; -+ case (0x1 << 2): -+ case (0x1 << 3): -+ case (0x1 << 4): -+ case (0x1 << 5): -+ case (0x1 << 6): -+ case (0x1 << 7): -+ case (0x1 << 8): -+ addr = (core_num == 0) ? 0x7a : 0x7d; -+ break; -+ case (0x1 << 10): -+ addr = (core_num == 0) ? 0x7b : 0x7e; -+ break; -+ case (0x1 << 11): -+ addr = (core_num == 0) ? 0x7c : 0x7f; -+ break; -+ default: -+ addr = 0xffff; -+ } -+ -+ switch (field) { -+ case (0x1 << 1): -+ mask = (0x7 << 3); -+ shift = 3; -+ break; -+ case (0x1 << 9): -+ mask = (0x1 << 2); -+ shift = 2; -+ break; -+ case (0x1 << 12): -+ mask = (0x1 << 8); -+ shift = 8; -+ break; -+ case (0x1 << 13): -+ mask = (0x1 << 9); -+ shift = 9; -+ break; -+ case (0x1 << 14): -+ mask = (0xf << 12); -+ shift = 12; -+ break; -+ case (0x1 << 2): -+ mask = (0x1 << 0); -+ shift = 0; -+ break; -+ case (0x1 << 3): -+ mask = (0x1 << 1); -+ shift = 1; -+ break; -+ case (0x1 << 4): -+ mask = (0x1 << 2); -+ shift = 2; -+ break; -+ case (0x1 << 5): -+ mask = (0x3 << 4); -+ shift = 4; -+ break; -+ case (0x1 << 6): -+ mask = (0x3 << 6); -+ shift = 6; -+ break; -+ case (0x1 << 7): -+ mask = (0x1 << 8); -+ shift = 8; -+ break; -+ case (0x1 << 8): -+ mask = (0x1 << 9); -+ shift = 9; -+ break; -+ case (0x1 << 10): -+ mask = 0x1fff; -+ shift = 0x0; -+ break; -+ case (0x1 << 11): -+ mask = 0x1fff; -+ shift = 0x0; -+ break; -+ default: -+ mask = 0x0; -+ shift = 0x0; -+ break; -+ } -+ -+ if ((addr != 0xffff) && (core_mask & (1 << core_num))) -+ mod_phy_reg(pi, addr, mask, (value << shift)); -+ } -+ -+ or_phy_reg(pi, 0xec, (0x1 << 0)); -+ or_phy_reg(pi, 0x78, (0x1 << 0)); -+ udelay(1); -+ and_phy_reg(pi, 0xec, ~(0x1 << 0)); -+ } -+} -+ -+static void wlc_phy_txpwrctrl_idle_tssi_nphy(struct brcms_phy *pi) -+{ -+ s32 rssi_buf[4]; -+ s32 int_val; -+ -+ if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) || PHY_MUTED(pi)) -+ -+ return; -+ -+ if (PHY_IPA(pi)) -+ wlc_phy_ipa_internal_tssi_setup_nphy(pi); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), -+ 0, 0x3, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ else if (NREV_GE(pi->pubpi.phy_rev, 3)) -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 0); -+ -+ wlc_phy_stopplayback_nphy(pi); -+ -+ wlc_phy_tx_tone_nphy(pi, 4000, 0, 0, 0, false); -+ -+ udelay(20); -+ int_val = -+ wlc_phy_poll_rssi_nphy(pi, (u8) NPHY_RSSI_SEL_TSSI_2G, rssi_buf, -+ 1); -+ wlc_phy_stopplayback_nphy(pi); -+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, 0); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), -+ 0, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ else if (NREV_GE(pi->pubpi.phy_rev, 3)) -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 1); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ -+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g = -+ (u8) ((int_val >> 24) & 0xff); -+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g = -+ (u8) ((int_val >> 24) & 0xff); -+ -+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g = -+ (u8) ((int_val >> 8) & 0xff); -+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g = -+ (u8) ((int_val >> 8) & 0xff); -+ } else { -+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g = -+ (u8) ((int_val >> 24) & 0xff); -+ -+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g = -+ (u8) ((int_val >> 8) & 0xff); -+ -+ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g = -+ (u8) ((int_val >> 16) & 0xff); -+ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g = -+ (u8) ((int_val) & 0xff); -+ } -+ -+} -+ -+static void wlc_phy_txpwr_limit_to_tbl_nphy(struct brcms_phy *pi) -+{ -+ u8 idx, idx2, i, delta_ind; -+ -+ for (idx = TXP_FIRST_CCK; idx <= TXP_LAST_CCK; idx++) -+ pi->adj_pwr_tbl_nphy[idx] = pi->tx_power_offset[idx]; -+ -+ for (i = 0; i < 4; i++) { -+ idx2 = 0; -+ -+ delta_ind = 0; -+ -+ switch (i) { -+ case 0: -+ -+ if (CHSPEC_IS40(pi->radio_chanspec) -+ && NPHY_IS_SROM_REINTERPRET) { -+ idx = TXP_FIRST_MCS_40_SISO; -+ } else { -+ idx = (CHSPEC_IS40(pi->radio_chanspec)) ? -+ TXP_FIRST_OFDM_40_SISO : TXP_FIRST_OFDM; -+ delta_ind = 1; -+ } -+ break; -+ -+ case 1: -+ -+ idx = (CHSPEC_IS40(pi->radio_chanspec)) ? -+ TXP_FIRST_MCS_40_CDD : TXP_FIRST_MCS_20_CDD; -+ break; -+ -+ case 2: -+ -+ idx = (CHSPEC_IS40(pi->radio_chanspec)) ? -+ TXP_FIRST_MCS_40_STBC : TXP_FIRST_MCS_20_STBC; -+ break; -+ -+ case 3: -+ -+ idx = (CHSPEC_IS40(pi->radio_chanspec)) ? -+ TXP_FIRST_MCS_40_SDM : TXP_FIRST_MCS_20_SDM; -+ break; -+ } -+ -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx]; -+ idx = idx + delta_ind; -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx]; -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx]; -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx++]; -+ -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx++]; -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx]; -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx]; -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx++]; -+ -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx++]; -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx]; -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx]; -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx++]; -+ -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx]; -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx++]; -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx]; -+ idx = idx + 1 - delta_ind; -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx]; -+ -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx]; -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx]; -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx]; -+ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = -+ pi->tx_power_offset[idx]; -+ } -+} -+ -+static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) -+{ -+ u32 idx; -+ s16 a1[2], b0[2], b1[2]; -+ s8 target_pwr_qtrdbm[2]; -+ s32 num, den, pwr_est; -+ u8 chan_freq_range; -+ u8 idle_tssi[2]; -+ u32 tbl_id, tbl_len, tbl_offset; -+ u32 regval[64]; -+ u8 core; -+ -+ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) { -+ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK); -+ (void)R_REG(&pi->regs->maccontrol); -+ udelay(1); -+ } -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ or_phy_reg(pi, 0x122, (0x1 << 0)); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) -+ and_phy_reg(pi, 0x1e7, (u16) (~(0x1 << 15))); -+ else -+ or_phy_reg(pi, 0x1e7, (0x1 << 15)); -+ -+ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) -+ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0); -+ -+ if (pi->sh->sromrev < 4) { -+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g; -+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g; -+ target_pwr_qtrdbm[0] = 13 * 4; -+ target_pwr_qtrdbm[1] = 13 * 4; -+ a1[0] = -424; -+ a1[1] = -424; -+ b0[0] = 5612; -+ b0[1] = 5612; -+ b1[1] = -1393; -+ b1[0] = -1393; -+ } else { -+ -+ chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0); -+ switch (chan_freq_range) { -+ case WL_CHAN_FREQ_RANGE_2G: -+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g; -+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g; -+ target_pwr_qtrdbm[0] = -+ pi->nphy_pwrctrl_info[0].max_pwr_2g; -+ target_pwr_qtrdbm[1] = -+ pi->nphy_pwrctrl_info[1].max_pwr_2g; -+ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_a1; -+ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_a1; -+ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b0; -+ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b0; -+ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b1; -+ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b1; -+ break; -+ case WL_CHAN_FREQ_RANGE_5GL: -+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; -+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; -+ target_pwr_qtrdbm[0] = -+ pi->nphy_pwrctrl_info[0].max_pwr_5gl; -+ target_pwr_qtrdbm[1] = -+ pi->nphy_pwrctrl_info[1].max_pwr_5gl; -+ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1; -+ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1; -+ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0; -+ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0; -+ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1; -+ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1; -+ break; -+ case WL_CHAN_FREQ_RANGE_5GM: -+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; -+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; -+ target_pwr_qtrdbm[0] = -+ pi->nphy_pwrctrl_info[0].max_pwr_5gm; -+ target_pwr_qtrdbm[1] = -+ pi->nphy_pwrctrl_info[1].max_pwr_5gm; -+ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_a1; -+ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_a1; -+ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b0; -+ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b0; -+ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b1; -+ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b1; -+ break; -+ case WL_CHAN_FREQ_RANGE_5GH: -+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; -+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; -+ target_pwr_qtrdbm[0] = -+ pi->nphy_pwrctrl_info[0].max_pwr_5gh; -+ target_pwr_qtrdbm[1] = -+ pi->nphy_pwrctrl_info[1].max_pwr_5gh; -+ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1; -+ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1; -+ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0; -+ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0; -+ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1; -+ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1; -+ break; -+ default: -+ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g; -+ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g; -+ target_pwr_qtrdbm[0] = 13 * 4; -+ target_pwr_qtrdbm[1] = 13 * 4; -+ a1[0] = -424; -+ a1[1] = -424; -+ b0[0] = 5612; -+ b0[1] = 5612; -+ b1[1] = -1393; -+ b1[0] = -1393; -+ break; -+ } -+ } -+ -+ target_pwr_qtrdbm[0] = (s8) pi->tx_power_max; -+ target_pwr_qtrdbm[1] = (s8) pi->tx_power_max; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ if (pi->srom_fem2g.tssipos) -+ or_phy_reg(pi, 0x1e9, (0x1 << 14)); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ for (core = 0; core <= 1; core++) { -+ if (PHY_IPA(pi)) { -+ if (CHSPEC_IS2G(pi->radio_chanspec)) -+ WRITE_RADIO_REG3(pi, RADIO_2057, -+ TX, core, -+ TX_SSI_MUX, -+ 0xe); -+ else -+ WRITE_RADIO_REG3(pi, RADIO_2057, -+ TX, core, -+ TX_SSI_MUX, -+ 0xc); -+ } -+ } -+ } else { -+ if (PHY_IPA(pi)) { -+ -+ write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX | -+ RADIO_2056_TX0, -+ (CHSPEC_IS5G -+ (pi->radio_chanspec)) ? -+ 0xc : 0xe); -+ write_radio_reg(pi, -+ RADIO_2056_TX_TX_SSI_MUX | -+ RADIO_2056_TX1, -+ (CHSPEC_IS5G -+ (pi->radio_chanspec)) ? -+ 0xc : 0xe); -+ } else { -+ -+ write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX | -+ RADIO_2056_TX0, 0x11); -+ write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX | -+ RADIO_2056_TX1, 0x11); -+ } -+ } -+ } -+ -+ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) { -+ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK); -+ (void)R_REG(&pi->regs->maccontrol); -+ udelay(1); -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ mod_phy_reg(pi, 0x1e7, (0x7f << 0), -+ (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0)); -+ else -+ mod_phy_reg(pi, 0x1e7, (0x7f << 0), -+ (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0)); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ mod_phy_reg(pi, 0x222, (0xff << 0), -+ (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0)); -+ else if (NREV_GT(pi->pubpi.phy_rev, 1)) -+ mod_phy_reg(pi, 0x222, (0xff << 0), -+ (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0)); -+ -+ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) -+ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0); -+ -+ write_phy_reg(pi, 0x1e8, (0x3 << 8) | (240 << 0)); -+ -+ write_phy_reg(pi, 0x1e9, -+ (1 << 15) | (idle_tssi[0] << 0) | (idle_tssi[1] << 8)); -+ -+ write_phy_reg(pi, 0x1ea, -+ (target_pwr_qtrdbm[0] << 0) | -+ (target_pwr_qtrdbm[1] << 8)); -+ -+ tbl_len = 64; -+ tbl_offset = 0; -+ for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL; -+ tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) { -+ -+ for (idx = 0; idx < tbl_len; idx++) { -+ num = 8 * -+ (16 * b0[tbl_id - 26] + b1[tbl_id - 26] * idx); -+ den = 32768 + a1[tbl_id - 26] * idx; -+ pwr_est = max(((4 * num + den / 2) / den), -8); -+ if (NREV_LT(pi->pubpi.phy_rev, 3)) { -+ if (idx <= -+ (uint) (31 - idle_tssi[tbl_id - 26] + 1)) -+ pwr_est = -+ max(pwr_est, -+ target_pwr_qtrdbm -+ [tbl_id - 26] + 1); -+ } -+ regval[idx] = (u32) pwr_est; -+ } -+ wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32, -+ regval); -+ } -+ -+ wlc_phy_txpwr_limit_to_tbl_nphy(pi); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64, 8, -+ pi->adj_pwr_tbl_nphy); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64, 8, -+ pi->adj_pwr_tbl_nphy); -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+} -+ -+static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi) -+{ -+ u32 *tx_pwrctrl_tbl = NULL; -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ if ((pi->pubpi.radiorev == 4) -+ || (pi->pubpi.radiorev == 6)) -+ tx_pwrctrl_tbl = -+ nphy_tpc_txgain_ipa_2g_2057rev4n6; -+ else if (pi->pubpi.radiorev == 3) -+ tx_pwrctrl_tbl = -+ nphy_tpc_txgain_ipa_2g_2057rev3; -+ else if (pi->pubpi.radiorev == 5) -+ tx_pwrctrl_tbl = -+ nphy_tpc_txgain_ipa_2g_2057rev5; -+ else if ((pi->pubpi.radiorev == 7) -+ || (pi->pubpi.radiorev == 8)) -+ tx_pwrctrl_tbl = -+ nphy_tpc_txgain_ipa_2g_2057rev7; -+ } else if (NREV_IS(pi->pubpi.phy_rev, 6)) { -+ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6; -+ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { -+ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5; -+ } else { -+ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa; -+ } -+ } else { -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ if ((pi->pubpi.radiorev == 3) || -+ (pi->pubpi.radiorev == 4) || -+ (pi->pubpi.radiorev == 6)) -+ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g_2057; -+ else if ((pi->pubpi.radiorev == 7) -+ || (pi->pubpi.radiorev == 8)) -+ tx_pwrctrl_tbl = -+ nphy_tpc_txgain_ipa_5g_2057rev7; -+ } else { -+ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g; -+ } -+ } -+ -+ return tx_pwrctrl_tbl; -+} -+ -+static void wlc_phy_restore_rssical_nphy(struct brcms_phy *pi) -+{ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if (pi->nphy_rssical_chanspec_2G == 0) -+ return; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0, -+ RADIO_2057_VCM_MASK, -+ pi->rssical_cache. -+ rssical_radio_regs_2G[0]); -+ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1, -+ RADIO_2057_VCM_MASK, -+ pi->rssical_cache. -+ rssical_radio_regs_2G[1]); -+ } else { -+ mod_radio_reg(pi, -+ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0, -+ RADIO_2056_VCM_MASK, -+ pi->rssical_cache. -+ rssical_radio_regs_2G[0]); -+ mod_radio_reg(pi, -+ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1, -+ RADIO_2056_VCM_MASK, -+ pi->rssical_cache. -+ rssical_radio_regs_2G[1]); -+ } -+ -+ write_phy_reg(pi, 0x1a6, -+ pi->rssical_cache.rssical_phyregs_2G[0]); -+ write_phy_reg(pi, 0x1ac, -+ pi->rssical_cache.rssical_phyregs_2G[1]); -+ write_phy_reg(pi, 0x1b2, -+ pi->rssical_cache.rssical_phyregs_2G[2]); -+ write_phy_reg(pi, 0x1b8, -+ pi->rssical_cache.rssical_phyregs_2G[3]); -+ write_phy_reg(pi, 0x1a4, -+ pi->rssical_cache.rssical_phyregs_2G[4]); -+ write_phy_reg(pi, 0x1aa, -+ pi->rssical_cache.rssical_phyregs_2G[5]); -+ write_phy_reg(pi, 0x1b0, -+ pi->rssical_cache.rssical_phyregs_2G[6]); -+ write_phy_reg(pi, 0x1b6, -+ pi->rssical_cache.rssical_phyregs_2G[7]); -+ write_phy_reg(pi, 0x1a5, -+ pi->rssical_cache.rssical_phyregs_2G[8]); -+ write_phy_reg(pi, 0x1ab, -+ pi->rssical_cache.rssical_phyregs_2G[9]); -+ write_phy_reg(pi, 0x1b1, -+ pi->rssical_cache.rssical_phyregs_2G[10]); -+ write_phy_reg(pi, 0x1b7, -+ pi->rssical_cache.rssical_phyregs_2G[11]); -+ -+ } else { -+ if (pi->nphy_rssical_chanspec_5G == 0) -+ return; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0, -+ RADIO_2057_VCM_MASK, -+ pi->rssical_cache. -+ rssical_radio_regs_5G[0]); -+ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1, -+ RADIO_2057_VCM_MASK, -+ pi->rssical_cache. -+ rssical_radio_regs_5G[1]); -+ } else { -+ mod_radio_reg(pi, -+ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0, -+ RADIO_2056_VCM_MASK, -+ pi->rssical_cache. -+ rssical_radio_regs_5G[0]); -+ mod_radio_reg(pi, -+ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1, -+ RADIO_2056_VCM_MASK, -+ pi->rssical_cache. -+ rssical_radio_regs_5G[1]); -+ } -+ -+ write_phy_reg(pi, 0x1a6, -+ pi->rssical_cache.rssical_phyregs_5G[0]); -+ write_phy_reg(pi, 0x1ac, -+ pi->rssical_cache.rssical_phyregs_5G[1]); -+ write_phy_reg(pi, 0x1b2, -+ pi->rssical_cache.rssical_phyregs_5G[2]); -+ write_phy_reg(pi, 0x1b8, -+ pi->rssical_cache.rssical_phyregs_5G[3]); -+ write_phy_reg(pi, 0x1a4, -+ pi->rssical_cache.rssical_phyregs_5G[4]); -+ write_phy_reg(pi, 0x1aa, -+ pi->rssical_cache.rssical_phyregs_5G[5]); -+ write_phy_reg(pi, 0x1b0, -+ pi->rssical_cache.rssical_phyregs_5G[6]); -+ write_phy_reg(pi, 0x1b6, -+ pi->rssical_cache.rssical_phyregs_5G[7]); -+ write_phy_reg(pi, 0x1a5, -+ pi->rssical_cache.rssical_phyregs_5G[8]); -+ write_phy_reg(pi, 0x1ab, -+ pi->rssical_cache.rssical_phyregs_5G[9]); -+ write_phy_reg(pi, 0x1b1, -+ pi->rssical_cache.rssical_phyregs_5G[10]); -+ write_phy_reg(pi, 0x1b7, -+ pi->rssical_cache.rssical_phyregs_5G[11]); -+ } -+} -+ -+static void wlc_phy_internal_cal_txgain_nphy(struct brcms_phy *pi) -+{ -+ u16 txcal_gain[2]; -+ -+ pi->nphy_txcal_pwr_idx[0] = pi->nphy_cal_orig_pwr_idx[0]; -+ pi->nphy_txcal_pwr_idx[1] = pi->nphy_cal_orig_pwr_idx[0]; -+ wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true); -+ wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true); -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, -+ txcal_gain); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F40; -+ txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F40; -+ } else { -+ txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F60; -+ txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F60; -+ } -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, -+ txcal_gain); -+} -+ -+static void wlc_phy_precal_txgain_nphy(struct brcms_phy *pi) -+{ -+ bool save_bbmult = false; -+ u8 txcal_index_2057_rev5n7 = 0; -+ u8 txcal_index_2057_rev3n4n6 = 10; -+ -+ if (pi->use_int_tx_iqlo_cal_nphy) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ if ((pi->pubpi.radiorev == 3) || -+ (pi->pubpi.radiorev == 4) || -+ (pi->pubpi.radiorev == 6)) { -+ -+ pi->nphy_txcal_pwr_idx[0] = -+ txcal_index_2057_rev3n4n6; -+ pi->nphy_txcal_pwr_idx[1] = -+ txcal_index_2057_rev3n4n6; -+ wlc_phy_txpwr_index_nphy( -+ pi, 3, -+ txcal_index_2057_rev3n4n6, -+ false); -+ } else { -+ -+ pi->nphy_txcal_pwr_idx[0] = -+ txcal_index_2057_rev5n7; -+ pi->nphy_txcal_pwr_idx[1] = -+ txcal_index_2057_rev5n7; -+ wlc_phy_txpwr_index_nphy( -+ pi, 3, -+ txcal_index_2057_rev5n7, -+ false); -+ } -+ save_bbmult = true; -+ -+ } else if (NREV_LT(pi->pubpi.phy_rev, 5)) { -+ wlc_phy_cal_txgainctrl_nphy(pi, 11, false); -+ if (pi->sh->hw_phytxchain != 3) { -+ pi->nphy_txcal_pwr_idx[1] = -+ pi->nphy_txcal_pwr_idx[0]; -+ wlc_phy_txpwr_index_nphy(pi, 3, -+ pi-> -+ nphy_txcal_pwr_idx[0], -+ true); -+ save_bbmult = true; -+ } -+ -+ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { -+ if (PHY_IPA(pi)) { -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ wlc_phy_cal_txgainctrl_nphy(pi, 12, -+ false); -+ } else { -+ pi->nphy_txcal_pwr_idx[0] = 80; -+ pi->nphy_txcal_pwr_idx[1] = 80; -+ wlc_phy_txpwr_index_nphy(pi, 3, 80, -+ false); -+ save_bbmult = true; -+ } -+ } else { -+ wlc_phy_internal_cal_txgain_nphy(pi); -+ save_bbmult = true; -+ } -+ -+ } else if (NREV_IS(pi->pubpi.phy_rev, 6)) { -+ if (PHY_IPA(pi)) { -+ if (CHSPEC_IS2G(pi->radio_chanspec)) -+ wlc_phy_cal_txgainctrl_nphy(pi, 12, -+ false); -+ else -+ wlc_phy_cal_txgainctrl_nphy(pi, 14, -+ false); -+ } else { -+ wlc_phy_internal_cal_txgain_nphy(pi); -+ save_bbmult = true; -+ } -+ } -+ -+ } else { -+ wlc_phy_cal_txgainctrl_nphy(pi, 10, false); -+ } -+ -+ if (save_bbmult) -+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, -+ &pi->nphy_txcal_bbmult); -+} -+ -+static void -+wlc_phy_rfctrlintc_override_nphy(struct brcms_phy *pi, u8 field, u16 value, -+ u8 core_code) -+{ -+ u16 mask; -+ u16 val; -+ u8 core; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ if (core_code == RADIO_MIMO_CORESEL_CORE1 -+ && core == PHY_CORE_1) -+ continue; -+ else if (core_code == RADIO_MIMO_CORESEL_CORE2 -+ && core == PHY_CORE_0) -+ continue; -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 7)) { -+ -+ mask = (0x1 << 10); -+ val = 1 << 10; -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 : -+ 0x92, mask, val); -+ } -+ -+ if (field == NPHY_RfctrlIntc_override_OFF) { -+ -+ write_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 : -+ 0x92, 0); -+ -+ wlc_phy_force_rfseq_nphy(pi, -+ NPHY_RFSEQ_RESET2RX); -+ } else if (field == NPHY_RfctrlIntc_override_TRSW) { -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ mask = (0x1 << 6) | (0x1 << 7); -+ -+ val = value << 6; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 : 0x92, -+ mask, val); -+ -+ or_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 : 0x92, -+ (0x1 << 10)); -+ -+ and_phy_reg(pi, 0x2ff, (u16) -+ ~(0x3 << 14)); -+ or_phy_reg(pi, 0x2ff, (0x1 << 13)); -+ or_phy_reg(pi, 0x2ff, (0x1 << 0)); -+ } else { -+ -+ mask = (0x1 << 6) | -+ (0x1 << 7) | -+ (0x1 << 8) | (0x1 << 9); -+ val = value << 6; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 : 0x92, -+ mask, val); -+ -+ mask = (0x1 << 0); -+ val = 1 << 0; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0xe7 : 0xec, -+ mask, val); -+ -+ mask = (core == PHY_CORE_0) ? -+ (0x1 << 0) : (0x1 << 1); -+ val = 1 << ((core == PHY_CORE_0) ? -+ 0 : 1); -+ mod_phy_reg(pi, 0x78, mask, val); -+ -+ SPINWAIT(((read_phy_reg(pi, 0x78) & val) -+ != 0), 10000); -+ if (WARN(read_phy_reg(pi, 0x78) & val, -+ "HW error: override failed")) -+ return; -+ -+ mask = (0x1 << 0); -+ val = 0 << 0; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0xe7 : 0xec, -+ mask, val); -+ } -+ } else if (field == NPHY_RfctrlIntc_override_PA) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ mask = (0x1 << 4) | (0x1 << 5); -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) -+ val = value << 5; -+ else -+ val = value << 4; -+ -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 : 0x92, -+ mask, val); -+ -+ or_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 : 0x92, -+ (0x1 << 12)); -+ } else { -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ mask = (0x1 << 5); -+ val = value << 5; -+ } else { -+ mask = (0x1 << 4); -+ val = value << 4; -+ } -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 : 0x92, -+ mask, val); -+ } -+ } else if (field == -+ NPHY_RfctrlIntc_override_EXT_LNA_PU) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ -+ mask = (0x1 << 0); -+ val = value << 0; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 -+ : 0x92, mask, val); -+ -+ mask = (0x1 << 2); -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 -+ : 0x92, mask, 0); -+ } else { -+ -+ mask = (0x1 << 2); -+ val = value << 2; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 -+ : 0x92, mask, val); -+ -+ mask = (0x1 << 0); -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 -+ : 0x92, mask, 0); -+ } -+ -+ mask = (0x1 << 11); -+ val = 1 << 11; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 : 0x92, -+ mask, val); -+ } else { -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ mask = (0x1 << 0); -+ val = value << 0; -+ } else { -+ mask = (0x1 << 2); -+ val = value << 2; -+ } -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 : 0x92, -+ mask, val); -+ } -+ } else if (field == -+ NPHY_RfctrlIntc_override_EXT_LNA_GAIN) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ -+ mask = (0x1 << 1); -+ val = value << 1; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 -+ : 0x92, mask, val); -+ -+ mask = (0x1 << 3); -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 -+ : 0x92, mask, 0); -+ } else { -+ -+ mask = (0x1 << 3); -+ val = value << 3; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 -+ : 0x92, mask, val); -+ -+ mask = (0x1 << 1); -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 -+ : 0x92, mask, 0); -+ } -+ -+ mask = (0x1 << 11); -+ val = 1 << 11; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 : 0x92, -+ mask, val); -+ } else { -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ mask = (0x1 << 1); -+ val = value << 1; -+ } else { -+ mask = (0x1 << 3); -+ val = value << 3; -+ } -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x91 : 0x92, -+ mask, val); -+ } -+ } -+ } -+ } -+} -+ -+void -+wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, s32 dBm_targetpower, -+ bool debug) -+{ -+ int gainctrl_loopidx; -+ uint core; -+ u16 m0m1, curr_m0m1; -+ s32 delta_power; -+ s32 txpwrindex; -+ s32 qdBm_power[2]; -+ u16 orig_BBConfig; -+ u16 phy_saveregs[4]; -+ u32 freq_test; -+ u16 ampl_test = 250; -+ uint stepsize; -+ bool phyhang_avoid_state = false; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ stepsize = 2; -+ else -+ stepsize = 1; -+ -+ if (CHSPEC_IS40(pi->radio_chanspec)) -+ freq_test = 5000; -+ else -+ freq_test = 2500; -+ -+ wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true); -+ wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true); -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ phyhang_avoid_state = pi->phyhang_avoid; -+ pi->phyhang_avoid = false; -+ -+ phy_saveregs[0] = read_phy_reg(pi, 0x91); -+ phy_saveregs[1] = read_phy_reg(pi, 0x92); -+ phy_saveregs[2] = read_phy_reg(pi, 0xe7); -+ phy_saveregs[3] = read_phy_reg(pi, 0xec); -+ wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 1, -+ RADIO_MIMO_CORESEL_CORE1 | -+ RADIO_MIMO_CORESEL_CORE2); -+ -+ if (!debug) { -+ wlc_phy_rfctrlintc_override_nphy(pi, -+ NPHY_RfctrlIntc_override_TRSW, -+ 0x2, RADIO_MIMO_CORESEL_CORE1); -+ wlc_phy_rfctrlintc_override_nphy(pi, -+ NPHY_RfctrlIntc_override_TRSW, -+ 0x8, RADIO_MIMO_CORESEL_CORE2); -+ } else { -+ wlc_phy_rfctrlintc_override_nphy(pi, -+ NPHY_RfctrlIntc_override_TRSW, -+ 0x1, RADIO_MIMO_CORESEL_CORE1); -+ wlc_phy_rfctrlintc_override_nphy(pi, -+ NPHY_RfctrlIntc_override_TRSW, -+ 0x7, RADIO_MIMO_CORESEL_CORE2); -+ } -+ -+ orig_BBConfig = read_phy_reg(pi, 0x01); -+ mod_phy_reg(pi, 0x01, (0x1 << 15), 0); -+ -+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1); -+ -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ txpwrindex = (s32) pi->nphy_cal_orig_pwr_idx[core]; -+ -+ for (gainctrl_loopidx = 0; gainctrl_loopidx < 2; -+ gainctrl_loopidx++) { -+ wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0, -+ false); -+ -+ if (core == PHY_CORE_0) -+ curr_m0m1 = m0m1 & 0xff00; -+ else -+ curr_m0m1 = m0m1 & 0x00ff; -+ -+ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &curr_m0m1); -+ wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &curr_m0m1); -+ -+ udelay(50); -+ -+ wlc_phy_est_tonepwr_nphy(pi, qdBm_power, -+ NPHY_CAL_TSSISAMPS); -+ -+ pi->nphy_bb_mult_save = 0; -+ wlc_phy_stopplayback_nphy(pi); -+ -+ delta_power = (dBm_targetpower * 4) - qdBm_power[core]; -+ -+ txpwrindex -= stepsize * delta_power; -+ if (txpwrindex < 0) -+ txpwrindex = 0; -+ else if (txpwrindex > 127) -+ txpwrindex = 127; -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ if (NREV_IS(pi->pubpi.phy_rev, 4) && -+ (pi->srom_fem5g.extpagain == 3)) { -+ if (txpwrindex < 30) -+ txpwrindex = 30; -+ } -+ } else { -+ if (NREV_GE(pi->pubpi.phy_rev, 5) && -+ (pi->srom_fem2g.extpagain == 3)) { -+ if (txpwrindex < 50) -+ txpwrindex = 50; -+ } -+ } -+ -+ wlc_phy_txpwr_index_nphy(pi, (1 << core), -+ (u8) txpwrindex, true); -+ } -+ -+ pi->nphy_txcal_pwr_idx[core] = (u8) txpwrindex; -+ -+ if (debug) { -+ u16 radio_gain; -+ u16 dbg_m0m1; -+ -+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &dbg_m0m1); -+ -+ wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0, -+ false); -+ -+ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &dbg_m0m1); -+ wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &dbg_m0m1); -+ -+ udelay(100); -+ -+ wlc_phy_est_tonepwr_nphy(pi, qdBm_power, -+ NPHY_CAL_TSSISAMPS); -+ -+ wlc_phy_table_read_nphy(pi, 7, 1, (0x110 + core), 16, -+ &radio_gain); -+ -+ mdelay(4000); -+ pi->nphy_bb_mult_save = 0; -+ wlc_phy_stopplayback_nphy(pi); -+ } -+ } -+ -+ wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_txcal_pwr_idx[0], true); -+ wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_txcal_pwr_idx[1], true); -+ -+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &pi->nphy_txcal_bbmult); -+ -+ write_phy_reg(pi, 0x01, orig_BBConfig); -+ -+ write_phy_reg(pi, 0x91, phy_saveregs[0]); -+ write_phy_reg(pi, 0x92, phy_saveregs[1]); -+ write_phy_reg(pi, 0xe7, phy_saveregs[2]); -+ write_phy_reg(pi, 0xec, phy_saveregs[3]); -+ -+ pi->phyhang_avoid = phyhang_avoid_state; -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+} -+ -+static void wlc_phy_savecal_nphy(struct brcms_phy *pi) -+{ -+ void *tbl_ptr; -+ int coreNum; -+ u16 *txcal_radio_regs = NULL; -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ -+ wlc_phy_rx_iq_coeffs_nphy(pi, 0, -+ &pi->calibration_cache. -+ rxcal_coeffs_2G); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ txcal_radio_regs = -+ pi->calibration_cache.txcal_radio_regs_2G; -+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ -+ pi->calibration_cache.txcal_radio_regs_2G[0] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_LOFT_FINE_I | -+ RADIO_2056_TX0); -+ pi->calibration_cache.txcal_radio_regs_2G[1] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_LOFT_FINE_Q | -+ RADIO_2056_TX0); -+ pi->calibration_cache.txcal_radio_regs_2G[2] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_LOFT_FINE_I | -+ RADIO_2056_TX1); -+ pi->calibration_cache.txcal_radio_regs_2G[3] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_LOFT_FINE_Q | -+ RADIO_2056_TX1); -+ -+ pi->calibration_cache.txcal_radio_regs_2G[4] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_LOFT_COARSE_I | -+ RADIO_2056_TX0); -+ pi->calibration_cache.txcal_radio_regs_2G[5] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_LOFT_COARSE_Q | -+ RADIO_2056_TX0); -+ pi->calibration_cache.txcal_radio_regs_2G[6] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_LOFT_COARSE_I | -+ RADIO_2056_TX1); -+ pi->calibration_cache.txcal_radio_regs_2G[7] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_LOFT_COARSE_Q | -+ RADIO_2056_TX1); -+ } else { -+ pi->calibration_cache.txcal_radio_regs_2G[0] = -+ read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL); -+ pi->calibration_cache.txcal_radio_regs_2G[1] = -+ read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL); -+ pi->calibration_cache.txcal_radio_regs_2G[2] = -+ read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM); -+ pi->calibration_cache.txcal_radio_regs_2G[3] = -+ read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM); -+ } -+ -+ pi->nphy_iqcal_chanspec_2G = pi->radio_chanspec; -+ tbl_ptr = pi->calibration_cache.txcal_coeffs_2G; -+ } else { -+ -+ wlc_phy_rx_iq_coeffs_nphy(pi, 0, -+ &pi->calibration_cache. -+ rxcal_coeffs_5G); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ txcal_radio_regs = -+ pi->calibration_cache.txcal_radio_regs_5G; -+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ -+ pi->calibration_cache.txcal_radio_regs_5G[0] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_LOFT_FINE_I | -+ RADIO_2056_TX0); -+ pi->calibration_cache.txcal_radio_regs_5G[1] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_LOFT_FINE_Q | -+ RADIO_2056_TX0); -+ pi->calibration_cache.txcal_radio_regs_5G[2] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_LOFT_FINE_I | -+ RADIO_2056_TX1); -+ pi->calibration_cache.txcal_radio_regs_5G[3] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_LOFT_FINE_Q | -+ RADIO_2056_TX1); -+ -+ pi->calibration_cache.txcal_radio_regs_5G[4] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_LOFT_COARSE_I | -+ RADIO_2056_TX0); -+ pi->calibration_cache.txcal_radio_regs_5G[5] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_LOFT_COARSE_Q | -+ RADIO_2056_TX0); -+ pi->calibration_cache.txcal_radio_regs_5G[6] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_LOFT_COARSE_I | -+ RADIO_2056_TX1); -+ pi->calibration_cache.txcal_radio_regs_5G[7] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_LOFT_COARSE_Q | -+ RADIO_2056_TX1); -+ } else { -+ pi->calibration_cache.txcal_radio_regs_5G[0] = -+ read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL); -+ pi->calibration_cache.txcal_radio_regs_5G[1] = -+ read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL); -+ pi->calibration_cache.txcal_radio_regs_5G[2] = -+ read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM); -+ pi->calibration_cache.txcal_radio_regs_5G[3] = -+ read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM); -+ } -+ -+ pi->nphy_iqcal_chanspec_5G = pi->radio_chanspec; -+ tbl_ptr = pi->calibration_cache.txcal_coeffs_5G; -+ } -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ for (coreNum = 0; coreNum <= 1; coreNum++) { -+ -+ txcal_radio_regs[2 * coreNum] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, -+ LOFT_FINE_I); -+ txcal_radio_regs[2 * coreNum + 1] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, -+ LOFT_FINE_Q); -+ -+ txcal_radio_regs[2 * coreNum + 4] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, -+ LOFT_COARSE_I); -+ txcal_radio_regs[2 * coreNum + 5] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, -+ LOFT_COARSE_Q); -+ } -+ } -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 8, 80, 16, tbl_ptr); -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+} -+ -+static void wlc_phy_tx_iq_war_nphy(struct brcms_phy *pi) -+{ -+ struct nphy_iq_comp tx_comp; -+ -+ wlc_phy_table_read_nphy(pi, 15, 4, 0x50, 16, &tx_comp); -+ -+ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ, tx_comp.a0); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 2, tx_comp.b0); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 4, tx_comp.a1); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 6, tx_comp.b1); -+} -+ -+static void wlc_phy_restorecal_nphy(struct brcms_phy *pi) -+{ -+ u16 *loft_comp; -+ u16 txcal_coeffs_bphy[4]; -+ u16 *tbl_ptr; -+ int coreNum; -+ u16 *txcal_radio_regs = NULL; -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if (pi->nphy_iqcal_chanspec_2G == 0) -+ return; -+ -+ tbl_ptr = pi->calibration_cache.txcal_coeffs_2G; -+ loft_comp = &pi->calibration_cache.txcal_coeffs_2G[5]; -+ } else { -+ if (pi->nphy_iqcal_chanspec_5G == 0) -+ return; -+ -+ tbl_ptr = pi->calibration_cache.txcal_coeffs_5G; -+ loft_comp = &pi->calibration_cache.txcal_coeffs_5G[5]; -+ } -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, 16, tbl_ptr); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ txcal_coeffs_bphy[0] = tbl_ptr[0]; -+ txcal_coeffs_bphy[1] = tbl_ptr[1]; -+ txcal_coeffs_bphy[2] = tbl_ptr[2]; -+ txcal_coeffs_bphy[3] = tbl_ptr[3]; -+ } else { -+ txcal_coeffs_bphy[0] = 0; -+ txcal_coeffs_bphy[1] = 0; -+ txcal_coeffs_bphy[2] = 0; -+ txcal_coeffs_bphy[3] = 0; -+ } -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, 16, -+ txcal_coeffs_bphy); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, 16, loft_comp); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, 16, loft_comp); -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 2)) -+ wlc_phy_tx_iq_war_nphy(pi); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ txcal_radio_regs = -+ pi->calibration_cache.txcal_radio_regs_2G; -+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_LOFT_FINE_I | -+ RADIO_2056_TX0, -+ pi->calibration_cache. -+ txcal_radio_regs_2G[0]); -+ write_radio_reg(pi, -+ RADIO_2056_TX_LOFT_FINE_Q | -+ RADIO_2056_TX0, -+ pi->calibration_cache. -+ txcal_radio_regs_2G[1]); -+ write_radio_reg(pi, -+ RADIO_2056_TX_LOFT_FINE_I | -+ RADIO_2056_TX1, -+ pi->calibration_cache. -+ txcal_radio_regs_2G[2]); -+ write_radio_reg(pi, -+ RADIO_2056_TX_LOFT_FINE_Q | -+ RADIO_2056_TX1, -+ pi->calibration_cache. -+ txcal_radio_regs_2G[3]); -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_LOFT_COARSE_I | -+ RADIO_2056_TX0, -+ pi->calibration_cache. -+ txcal_radio_regs_2G[4]); -+ write_radio_reg(pi, -+ RADIO_2056_TX_LOFT_COARSE_Q | -+ RADIO_2056_TX0, -+ pi->calibration_cache. -+ txcal_radio_regs_2G[5]); -+ write_radio_reg(pi, -+ RADIO_2056_TX_LOFT_COARSE_I | -+ RADIO_2056_TX1, -+ pi->calibration_cache. -+ txcal_radio_regs_2G[6]); -+ write_radio_reg(pi, -+ RADIO_2056_TX_LOFT_COARSE_Q | -+ RADIO_2056_TX1, -+ pi->calibration_cache. -+ txcal_radio_regs_2G[7]); -+ } else { -+ write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL, -+ pi->calibration_cache. -+ txcal_radio_regs_2G[0]); -+ write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL, -+ pi->calibration_cache. -+ txcal_radio_regs_2G[1]); -+ write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, -+ pi->calibration_cache. -+ txcal_radio_regs_2G[2]); -+ write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, -+ pi->calibration_cache. -+ txcal_radio_regs_2G[3]); -+ } -+ -+ wlc_phy_rx_iq_coeffs_nphy(pi, 1, -+ &pi->calibration_cache. -+ rxcal_coeffs_2G); -+ } else { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ txcal_radio_regs = -+ pi->calibration_cache.txcal_radio_regs_5G; -+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_LOFT_FINE_I | -+ RADIO_2056_TX0, -+ pi->calibration_cache. -+ txcal_radio_regs_5G[0]); -+ write_radio_reg(pi, -+ RADIO_2056_TX_LOFT_FINE_Q | -+ RADIO_2056_TX0, -+ pi->calibration_cache. -+ txcal_radio_regs_5G[1]); -+ write_radio_reg(pi, -+ RADIO_2056_TX_LOFT_FINE_I | -+ RADIO_2056_TX1, -+ pi->calibration_cache. -+ txcal_radio_regs_5G[2]); -+ write_radio_reg(pi, -+ RADIO_2056_TX_LOFT_FINE_Q | -+ RADIO_2056_TX1, -+ pi->calibration_cache. -+ txcal_radio_regs_5G[3]); -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_LOFT_COARSE_I | -+ RADIO_2056_TX0, -+ pi->calibration_cache. -+ txcal_radio_regs_5G[4]); -+ write_radio_reg(pi, -+ RADIO_2056_TX_LOFT_COARSE_Q | -+ RADIO_2056_TX0, -+ pi->calibration_cache. -+ txcal_radio_regs_5G[5]); -+ write_radio_reg(pi, -+ RADIO_2056_TX_LOFT_COARSE_I | -+ RADIO_2056_TX1, -+ pi->calibration_cache. -+ txcal_radio_regs_5G[6]); -+ write_radio_reg(pi, -+ RADIO_2056_TX_LOFT_COARSE_Q | -+ RADIO_2056_TX1, -+ pi->calibration_cache. -+ txcal_radio_regs_5G[7]); -+ } else { -+ write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL, -+ pi->calibration_cache. -+ txcal_radio_regs_5G[0]); -+ write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL, -+ pi->calibration_cache. -+ txcal_radio_regs_5G[1]); -+ write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, -+ pi->calibration_cache. -+ txcal_radio_regs_5G[2]); -+ write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, -+ pi->calibration_cache. -+ txcal_radio_regs_5G[3]); -+ } -+ -+ wlc_phy_rx_iq_coeffs_nphy(pi, 1, -+ &pi->calibration_cache. -+ rxcal_coeffs_5G); -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ for (coreNum = 0; coreNum <= 1; coreNum++) { -+ -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum, -+ LOFT_FINE_I, -+ txcal_radio_regs[2 * coreNum]); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum, -+ LOFT_FINE_Q, -+ txcal_radio_regs[2 * coreNum + 1]); -+ -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum, -+ LOFT_COARSE_I, -+ txcal_radio_regs[2 * coreNum + 4]); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum, -+ LOFT_COARSE_Q, -+ txcal_radio_regs[2 * coreNum + 5]); -+ } -+ } -+} -+ -+static void wlc_phy_txpwrctrl_coeff_setup_nphy(struct brcms_phy *pi) -+{ -+ u32 idx; -+ u16 iqloCalbuf[7]; -+ u32 iqcomp, locomp, curr_locomp; -+ s8 locomp_i, locomp_q; -+ s8 curr_locomp_i, curr_locomp_q; -+ u32 tbl_id, tbl_len, tbl_offset; -+ u32 regval[128]; -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ wlc_phy_table_read_nphy(pi, 15, 7, 80, 16, iqloCalbuf); -+ -+ tbl_len = 128; -+ tbl_offset = 320; -+ for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL; -+ tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) { -+ iqcomp = -+ (tbl_id == -+ 26) ? (((u32) (iqloCalbuf[0] & 0x3ff)) << 10) | -+ (iqloCalbuf[1] & 0x3ff) -+ : (((u32) (iqloCalbuf[2] & 0x3ff)) << 10) | -+ (iqloCalbuf[3] & 0x3ff); -+ -+ for (idx = 0; idx < tbl_len; idx++) -+ regval[idx] = iqcomp; -+ wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32, -+ regval); -+ } -+ -+ tbl_offset = 448; -+ for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL; -+ tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) { -+ -+ locomp = -+ (u32) ((tbl_id == 26) ? iqloCalbuf[5] : iqloCalbuf[6]); -+ locomp_i = (s8) ((locomp >> 8) & 0xff); -+ locomp_q = (s8) ((locomp) & 0xff); -+ for (idx = 0; idx < tbl_len; idx++) { -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ curr_locomp_i = locomp_i; -+ curr_locomp_q = locomp_q; -+ } else { -+ curr_locomp_i = (s8) ((locomp_i * -+ nphy_tpc_loscale[idx] + -+ 128) >> 8); -+ curr_locomp_q = -+ (s8) ((locomp_q * -+ nphy_tpc_loscale[idx] + -+ 128) >> 8); -+ } -+ curr_locomp = (u32) ((curr_locomp_i & 0xff) << 8); -+ curr_locomp |= (u32) (curr_locomp_q & 0xff); -+ regval[idx] = curr_locomp; -+ } -+ wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32, -+ regval); -+ } -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 2)) { -+ -+ wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX1, 0xFFFF); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX2, 0xFFFF); -+ } -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+} -+ -+static void wlc_phy_txlpfbw_nphy(struct brcms_phy *pi) -+{ -+ u8 tx_lpf_bw = 0; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) { -+ if (CHSPEC_IS40(pi->radio_chanspec)) -+ tx_lpf_bw = 3; -+ else -+ tx_lpf_bw = 1; -+ -+ if (PHY_IPA(pi)) { -+ if (CHSPEC_IS40(pi->radio_chanspec)) -+ tx_lpf_bw = 5; -+ else -+ tx_lpf_bw = 4; -+ } -+ -+ write_phy_reg(pi, 0xe8, -+ (tx_lpf_bw << 0) | -+ (tx_lpf_bw << 3) | -+ (tx_lpf_bw << 6) | (tx_lpf_bw << 9)); -+ -+ if (PHY_IPA(pi)) { -+ -+ if (CHSPEC_IS40(pi->radio_chanspec)) -+ tx_lpf_bw = 4; -+ else -+ tx_lpf_bw = 1; -+ -+ write_phy_reg(pi, 0xe9, -+ (tx_lpf_bw << 0) | -+ (tx_lpf_bw << 3) | -+ (tx_lpf_bw << 6) | (tx_lpf_bw << 9)); -+ } -+ } -+} -+ -+static void -+wlc_phy_adjust_rx_analpfbw_nphy(struct brcms_phy *pi, u16 reduction_factr) -+{ -+ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) { -+ if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) && -+ CHSPEC_IS40(pi->radio_chanspec)) { -+ if (!pi->nphy_anarxlpf_adjusted) { -+ write_radio_reg(pi, -+ (RADIO_2056_RX_RXLPF_RCCAL_LPC | -+ RADIO_2056_RX0), -+ ((pi->nphy_rccal_value + -+ reduction_factr) | 0x80)); -+ -+ pi->nphy_anarxlpf_adjusted = true; -+ } -+ } else { -+ if (pi->nphy_anarxlpf_adjusted) { -+ write_radio_reg(pi, -+ (RADIO_2056_RX_RXLPF_RCCAL_LPC | -+ RADIO_2056_RX0), -+ (pi->nphy_rccal_value | 0x80)); -+ -+ pi->nphy_anarxlpf_adjusted = false; -+ } -+ } -+ } -+} -+ -+static void -+wlc_phy_adjust_min_noisevar_nphy(struct brcms_phy *pi, int ntones, -+ int *tone_id_buf, u32 *noise_var_buf) -+{ -+ int i; -+ u32 offset; -+ int tone_id; -+ int tbllen = -+ CHSPEC_IS40(pi->radio_chanspec) ? -+ NPHY_NOISEVAR_TBLLEN40 : NPHY_NOISEVAR_TBLLEN20; -+ -+ if (pi->nphy_noisevars_adjusted) { -+ for (i = 0; i < pi->nphy_saved_noisevars.bufcount; i++) { -+ tone_id = pi->nphy_saved_noisevars.tone_id[i]; -+ offset = (tone_id >= 0) ? -+ ((tone_id * -+ 2) + 1) : (tbllen + (tone_id * 2) + 1); -+ wlc_phy_table_write_nphy( -+ pi, NPHY_TBL_ID_NOISEVAR, 1, -+ offset, 32, -+ &pi->nphy_saved_noisevars.min_noise_vars[i]); -+ } -+ -+ pi->nphy_saved_noisevars.bufcount = 0; -+ pi->nphy_noisevars_adjusted = false; -+ } -+ -+ if ((noise_var_buf != NULL) && (tone_id_buf != NULL)) { -+ pi->nphy_saved_noisevars.bufcount = 0; -+ -+ for (i = 0; i < ntones; i++) { -+ tone_id = tone_id_buf[i]; -+ offset = (tone_id >= 0) ? -+ ((tone_id * 2) + 1) : -+ (tbllen + (tone_id * 2) + 1); -+ pi->nphy_saved_noisevars.tone_id[i] = tone_id; -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, -+ offset, 32, -+ &pi->nphy_saved_noisevars. -+ min_noise_vars[i]); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, -+ offset, 32, &noise_var_buf[i]); -+ pi->nphy_saved_noisevars.bufcount++; -+ } -+ -+ pi->nphy_noisevars_adjusted = true; -+ } -+} -+ -+static void wlc_phy_adjust_crsminpwr_nphy(struct brcms_phy *pi, u8 minpwr) -+{ -+ u16 regval; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) && -+ CHSPEC_IS40(pi->radio_chanspec)) { -+ if (!pi->nphy_crsminpwr_adjusted) { -+ regval = read_phy_reg(pi, 0x27d); -+ pi->nphy_crsminpwr[0] = regval & 0xff; -+ regval &= 0xff00; -+ regval |= (u16) minpwr; -+ write_phy_reg(pi, 0x27d, regval); -+ -+ regval = read_phy_reg(pi, 0x280); -+ pi->nphy_crsminpwr[1] = regval & 0xff; -+ regval &= 0xff00; -+ regval |= (u16) minpwr; -+ write_phy_reg(pi, 0x280, regval); -+ -+ regval = read_phy_reg(pi, 0x283); -+ pi->nphy_crsminpwr[2] = regval & 0xff; -+ regval &= 0xff00; -+ regval |= (u16) minpwr; -+ write_phy_reg(pi, 0x283, regval); -+ -+ pi->nphy_crsminpwr_adjusted = true; -+ } -+ } else { -+ if (pi->nphy_crsminpwr_adjusted) { -+ regval = read_phy_reg(pi, 0x27d); -+ regval &= 0xff00; -+ regval |= pi->nphy_crsminpwr[0]; -+ write_phy_reg(pi, 0x27d, regval); -+ -+ regval = read_phy_reg(pi, 0x280); -+ regval &= 0xff00; -+ regval |= pi->nphy_crsminpwr[1]; -+ write_phy_reg(pi, 0x280, regval); -+ -+ regval = read_phy_reg(pi, 0x283); -+ regval &= 0xff00; -+ regval |= pi->nphy_crsminpwr[2]; -+ write_phy_reg(pi, 0x283, regval); -+ -+ pi->nphy_crsminpwr_adjusted = false; -+ } -+ } -+ } -+} -+ -+static void wlc_phy_spurwar_nphy(struct brcms_phy *pi) -+{ -+ u16 cur_channel = 0; -+ int nphy_adj_tone_id_buf[] = { 57, 58 }; -+ u32 nphy_adj_noise_var_buf[] = { 0x3ff, 0x3ff }; -+ bool isAdjustNoiseVar = false; -+ uint numTonesAdjust = 0; -+ u32 tempval = 0; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ cur_channel = CHSPEC_CHANNEL(pi->radio_chanspec); -+ -+ if (pi->nphy_gband_spurwar_en) { -+ -+ wlc_phy_adjust_rx_analpfbw_nphy( -+ pi, -+ NPHY_ANARXLPFBW_REDUCTIONFACT); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if ((cur_channel == 11) -+ && CHSPEC_IS40(pi->radio_chanspec)) -+ wlc_phy_adjust_min_noisevar_nphy( -+ pi, 2, -+ nphy_adj_tone_id_buf, -+ nphy_adj_noise_var_buf); -+ else -+ wlc_phy_adjust_min_noisevar_nphy(pi, 0, -+ NULL, -+ NULL); -+ } -+ -+ wlc_phy_adjust_crsminpwr_nphy(pi, -+ NPHY_ADJUSTED_MINCRSPOWER); -+ } -+ -+ if ((pi->nphy_gband_spurwar2_en) -+ && CHSPEC_IS2G(pi->radio_chanspec)) { -+ -+ if (CHSPEC_IS40(pi->radio_chanspec)) { -+ switch (cur_channel) { -+ case 3: -+ nphy_adj_tone_id_buf[0] = 57; -+ nphy_adj_tone_id_buf[1] = 58; -+ nphy_adj_noise_var_buf[0] = 0x22f; -+ nphy_adj_noise_var_buf[1] = 0x25f; -+ isAdjustNoiseVar = true; -+ break; -+ case 4: -+ nphy_adj_tone_id_buf[0] = 41; -+ nphy_adj_tone_id_buf[1] = 42; -+ nphy_adj_noise_var_buf[0] = 0x22f; -+ nphy_adj_noise_var_buf[1] = 0x25f; -+ isAdjustNoiseVar = true; -+ break; -+ case 5: -+ nphy_adj_tone_id_buf[0] = 25; -+ nphy_adj_tone_id_buf[1] = 26; -+ nphy_adj_noise_var_buf[0] = 0x24f; -+ nphy_adj_noise_var_buf[1] = 0x25f; -+ isAdjustNoiseVar = true; -+ break; -+ case 6: -+ nphy_adj_tone_id_buf[0] = 9; -+ nphy_adj_tone_id_buf[1] = 10; -+ nphy_adj_noise_var_buf[0] = 0x22f; -+ nphy_adj_noise_var_buf[1] = 0x24f; -+ isAdjustNoiseVar = true; -+ break; -+ case 7: -+ nphy_adj_tone_id_buf[0] = 121; -+ nphy_adj_tone_id_buf[1] = 122; -+ nphy_adj_noise_var_buf[0] = 0x18f; -+ nphy_adj_noise_var_buf[1] = 0x24f; -+ isAdjustNoiseVar = true; -+ break; -+ case 8: -+ nphy_adj_tone_id_buf[0] = 105; -+ nphy_adj_tone_id_buf[1] = 106; -+ nphy_adj_noise_var_buf[0] = 0x22f; -+ nphy_adj_noise_var_buf[1] = 0x25f; -+ isAdjustNoiseVar = true; -+ break; -+ case 9: -+ nphy_adj_tone_id_buf[0] = 89; -+ nphy_adj_tone_id_buf[1] = 90; -+ nphy_adj_noise_var_buf[0] = 0x22f; -+ nphy_adj_noise_var_buf[1] = 0x24f; -+ isAdjustNoiseVar = true; -+ break; -+ case 10: -+ nphy_adj_tone_id_buf[0] = 73; -+ nphy_adj_tone_id_buf[1] = 74; -+ nphy_adj_noise_var_buf[0] = 0x22f; -+ nphy_adj_noise_var_buf[1] = 0x24f; -+ isAdjustNoiseVar = true; -+ break; -+ default: -+ isAdjustNoiseVar = false; -+ break; -+ } -+ } -+ -+ if (isAdjustNoiseVar) { -+ numTonesAdjust = sizeof(nphy_adj_tone_id_buf) / -+ sizeof(nphy_adj_tone_id_buf[0]); -+ -+ wlc_phy_adjust_min_noisevar_nphy( -+ pi, -+ numTonesAdjust, -+ nphy_adj_tone_id_buf, -+ nphy_adj_noise_var_buf); -+ -+ tempval = 0; -+ -+ } else { -+ wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL, -+ NULL); -+ } -+ } -+ -+ if ((pi->nphy_aband_spurwar_en) && -+ (CHSPEC_IS5G(pi->radio_chanspec))) { -+ switch (cur_channel) { -+ case 54: -+ nphy_adj_tone_id_buf[0] = 32; -+ nphy_adj_noise_var_buf[0] = 0x25f; -+ break; -+ case 38: -+ case 102: -+ case 118: -+ nphy_adj_tone_id_buf[0] = 0; -+ nphy_adj_noise_var_buf[0] = 0x0; -+ break; -+ case 134: -+ nphy_adj_tone_id_buf[0] = 32; -+ nphy_adj_noise_var_buf[0] = 0x21f; -+ break; -+ case 151: -+ nphy_adj_tone_id_buf[0] = 16; -+ nphy_adj_noise_var_buf[0] = 0x23f; -+ break; -+ case 153: -+ case 161: -+ nphy_adj_tone_id_buf[0] = 48; -+ nphy_adj_noise_var_buf[0] = 0x23f; -+ break; -+ default: -+ nphy_adj_tone_id_buf[0] = 0; -+ nphy_adj_noise_var_buf[0] = 0x0; -+ break; -+ } -+ -+ if (nphy_adj_tone_id_buf[0] -+ && nphy_adj_noise_var_buf[0]) -+ wlc_phy_adjust_min_noisevar_nphy( -+ pi, 1, -+ nphy_adj_tone_id_buf, -+ nphy_adj_noise_var_buf); -+ else -+ wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL, -+ NULL); -+ } -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+ } -+} -+ -+void wlc_phy_init_nphy(struct brcms_phy *pi) -+{ -+ u16 val; -+ u16 clip1_ths[2]; -+ struct nphy_txgains target_gain; -+ u8 tx_pwr_ctrl_state; -+ bool do_nphy_cal = false; -+ uint core; -+ uint origidx, intr_val; -+ struct d11regs __iomem *regs; -+ u32 d11_clk_ctl_st; -+ bool do_rssi_cal = false; -+ -+ core = 0; -+ -+ if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) -+ pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC; -+ -+ if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) && -+ ((pi->sh->chippkg == BCM4717_PKG_ID) || -+ (pi->sh->chippkg == BCM4718_PKG_ID))) { -+ if ((pi->sh->boardflags & BFL_EXTLNA) && -+ (CHSPEC_IS2G(pi->radio_chanspec))) -+ ai_corereg(pi->sh->sih, SI_CC_IDX, -+ offsetof(struct chipcregs, chipcontrol), -+ 0x40, 0x40); -+ } -+ -+ if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) && -+ CHSPEC_IS40(pi->radio_chanspec)) { -+ -+ regs = (struct d11regs __iomem *) -+ ai_switch_core(pi->sh->sih, -+ D11_CORE_ID, &origidx, -+ &intr_val); -+ d11_clk_ctl_st = R_REG(®s->clk_ctl_st); -+ AND_REG(®s->clk_ctl_st, -+ ~(CCS_FORCEHT | CCS_HTAREQ)); -+ -+ W_REG(®s->clk_ctl_st, d11_clk_ctl_st); -+ -+ ai_restore_core(pi->sh->sih, origidx, intr_val); -+ } -+ -+ pi->use_int_tx_iqlo_cal_nphy = -+ (PHY_IPA(pi) || -+ (NREV_GE(pi->pubpi.phy_rev, 7) || -+ (NREV_GE(pi->pubpi.phy_rev, 5) -+ && pi->sh->boardflags2 & BFL2_INTERNDET_TXIQCAL))); -+ -+ pi->internal_tx_iqlo_cal_tapoff_intpa_nphy = false; -+ -+ pi->nphy_deaf_count = 0; -+ -+ wlc_phy_tbl_init_nphy(pi); -+ -+ pi->nphy_crsminpwr_adjusted = false; -+ pi->nphy_noisevars_adjusted = false; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ write_phy_reg(pi, 0xe7, 0); -+ write_phy_reg(pi, 0xec, 0); -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ write_phy_reg(pi, 0x342, 0); -+ write_phy_reg(pi, 0x343, 0); -+ write_phy_reg(pi, 0x346, 0); -+ write_phy_reg(pi, 0x347, 0); -+ } -+ write_phy_reg(pi, 0xe5, 0); -+ write_phy_reg(pi, 0xe6, 0); -+ } else { -+ write_phy_reg(pi, 0xec, 0); -+ } -+ -+ write_phy_reg(pi, 0x91, 0); -+ write_phy_reg(pi, 0x92, 0); -+ if (NREV_LT(pi->pubpi.phy_rev, 6)) { -+ write_phy_reg(pi, 0x93, 0); -+ write_phy_reg(pi, 0x94, 0); -+ } -+ -+ and_phy_reg(pi, 0xa1, ~3); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ write_phy_reg(pi, 0x8f, 0); -+ write_phy_reg(pi, 0xa5, 0); -+ } else { -+ write_phy_reg(pi, 0xa5, 0); -+ } -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 2)) -+ mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b); -+ else if (NREV_LT(pi->pubpi.phy_rev, 2)) -+ mod_phy_reg(pi, 0xdc, 0x00ff, 0x40); -+ -+ write_phy_reg(pi, 0x203, 32); -+ write_phy_reg(pi, 0x201, 32); -+ -+ if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD) -+ write_phy_reg(pi, 0x20d, 160); -+ else -+ write_phy_reg(pi, 0x20d, 184); -+ -+ write_phy_reg(pi, 0x13a, 200); -+ -+ write_phy_reg(pi, 0x70, 80); -+ -+ write_phy_reg(pi, 0x1ff, 48); -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 8)) -+ wlc_phy_update_mimoconfig_nphy(pi, pi->n_preamble_override); -+ -+ wlc_phy_stf_chain_upd_nphy(pi); -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 2)) { -+ write_phy_reg(pi, 0x180, 0xaa8); -+ write_phy_reg(pi, 0x181, 0x9a4); -+ } -+ -+ if (PHY_IPA(pi)) { -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 0), (1) << 0); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x298 : -+ 0x29c, (0x1ff << 7), -+ (pi->nphy_papd_epsilon_offset[core]) << 7); -+ -+ } -+ -+ wlc_phy_ipa_set_tx_digi_filts_nphy(pi); -+ } else if (NREV_GE(pi->pubpi.phy_rev, 5)) { -+ wlc_phy_extpa_set_tx_digi_filts_nphy(pi); -+ } -+ -+ wlc_phy_workarounds_nphy(pi); -+ -+ wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON); -+ -+ val = read_phy_reg(pi, 0x01); -+ write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA); -+ write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA)); -+ wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF); -+ -+ wlapi_bmac_macphyclk_set(pi->sh->physhim, ON); -+ -+ wlc_phy_pa_override_nphy(pi, OFF); -+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX); -+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); -+ wlc_phy_pa_override_nphy(pi, ON); -+ -+ wlc_phy_classifier_nphy(pi, 0, 0); -+ wlc_phy_clip_det_nphy(pi, 0, clip1_ths); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) -+ wlc_phy_bphy_init_nphy(pi); -+ -+ tx_pwr_ctrl_state = pi->nphy_txpwrctrl; -+ wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF); -+ -+ wlc_phy_txpwr_fixpower_nphy(pi); -+ -+ wlc_phy_txpwrctrl_idle_tssi_nphy(pi); -+ -+ wlc_phy_txpwrctrl_pwr_setup_nphy(pi); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ u32 *tx_pwrctrl_tbl = NULL; -+ u16 idx; -+ s16 pga_gn = 0; -+ s16 pad_gn = 0; -+ s32 rfpwr_offset; -+ -+ if (PHY_IPA(pi)) { -+ tx_pwrctrl_tbl = wlc_phy_get_ipa_gaintbl_nphy(pi); -+ } else { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ if (NREV_IS(pi->pubpi.phy_rev, 3)) -+ tx_pwrctrl_tbl = -+ nphy_tpc_5GHz_txgain_rev3; -+ else if (NREV_IS(pi->pubpi.phy_rev, 4)) -+ tx_pwrctrl_tbl = -+ (pi->srom_fem5g.extpagain == -+ 3) ? -+ nphy_tpc_5GHz_txgain_HiPwrEPA : -+ nphy_tpc_5GHz_txgain_rev4; -+ else -+ tx_pwrctrl_tbl = -+ nphy_tpc_5GHz_txgain_rev5; -+ } else { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ if (pi->pubpi.radiorev == 5) -+ tx_pwrctrl_tbl = -+ nphy_tpc_txgain_epa_2057rev5; -+ else if (pi->pubpi.radiorev == 3) -+ tx_pwrctrl_tbl = -+ nphy_tpc_txgain_epa_2057rev3; -+ } else { -+ if (NREV_GE(pi->pubpi.phy_rev, 5) && -+ (pi->srom_fem2g.extpagain == 3)) -+ tx_pwrctrl_tbl = -+ nphy_tpc_txgain_HiPwrEPA; -+ else -+ tx_pwrctrl_tbl = -+ nphy_tpc_txgain_rev3; -+ } -+ } -+ } -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128, -+ 192, 32, tx_pwrctrl_tbl); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128, -+ 192, 32, tx_pwrctrl_tbl); -+ -+ pi->nphy_gmval = (u16) ((*tx_pwrctrl_tbl >> 16) & 0x7000); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ for (idx = 0; idx < 128; idx++) { -+ pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf; -+ pad_gn = (tx_pwrctrl_tbl[idx] >> 19) & 0x1f; -+ rfpwr_offset = get_rf_pwr_offset(pi, pga_gn, -+ pad_gn); -+ wlc_phy_table_write_nphy( -+ pi, -+ NPHY_TBL_ID_CORE1TXPWRCTL, -+ 1, 576 + idx, 32, -+ &rfpwr_offset); -+ wlc_phy_table_write_nphy( -+ pi, -+ NPHY_TBL_ID_CORE2TXPWRCTL, -+ 1, 576 + idx, 32, -+ &rfpwr_offset); -+ } -+ } else { -+ -+ for (idx = 0; idx < 128; idx++) { -+ pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf; -+ if (CHSPEC_IS2G(pi->radio_chanspec)) -+ rfpwr_offset = (s16) -+ nphy_papd_pga_gain_delta_ipa_2g -+ [pga_gn]; -+ else -+ rfpwr_offset = (s16) -+ nphy_papd_pga_gain_delta_ipa_5g -+ [pga_gn]; -+ -+ wlc_phy_table_write_nphy( -+ pi, -+ NPHY_TBL_ID_CORE1TXPWRCTL, -+ 1, 576 + idx, 32, -+ &rfpwr_offset); -+ wlc_phy_table_write_nphy( -+ pi, -+ NPHY_TBL_ID_CORE2TXPWRCTL, -+ 1, 576 + idx, 32, -+ &rfpwr_offset); -+ } -+ -+ } -+ } else { -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128, -+ 192, 32, nphy_tpc_txgain); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128, -+ 192, 32, nphy_tpc_txgain); -+ } -+ -+ if (pi->sh->phyrxchain != 0x3) -+ wlc_phy_rxcore_setstate_nphy((struct brcms_phy_pub *) pi, -+ pi->sh->phyrxchain); -+ -+ if (PHY_PERICAL_MPHASE_PENDING(pi)) -+ wlc_phy_cal_perical_mphase_restart(pi); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ do_rssi_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ? -+ (pi->nphy_rssical_chanspec_2G == 0) : -+ (pi->nphy_rssical_chanspec_5G == 0); -+ -+ if (do_rssi_cal) -+ wlc_phy_rssi_cal_nphy(pi); -+ else -+ wlc_phy_restore_rssical_nphy(pi); -+ } else { -+ wlc_phy_rssi_cal_nphy(pi); -+ } -+ -+ if (!SCAN_RM_IN_PROGRESS(pi)) -+ do_nphy_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ? -+ (pi->nphy_iqcal_chanspec_2G == 0) : -+ (pi->nphy_iqcal_chanspec_5G == 0); -+ -+ if (!pi->do_initcal) -+ do_nphy_cal = false; -+ -+ if (do_nphy_cal) { -+ -+ target_gain = wlc_phy_get_tx_gain_nphy(pi); -+ -+ if (pi->antsel_type == ANTSEL_2x3) -+ wlc_phy_antsel_init((struct brcms_phy_pub *) pi, -+ true); -+ -+ if (pi->nphy_perical != PHY_PERICAL_MPHASE) { -+ wlc_phy_rssi_cal_nphy(pi); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ pi->nphy_cal_orig_pwr_idx[0] = -+ pi->nphy_txpwrindex[PHY_CORE_0] -+ . -+ index_internal; -+ pi->nphy_cal_orig_pwr_idx[1] = -+ pi->nphy_txpwrindex[PHY_CORE_1] -+ . -+ index_internal; -+ -+ wlc_phy_precal_txgain_nphy(pi); -+ target_gain = -+ wlc_phy_get_tx_gain_nphy(pi); -+ } -+ -+ if (wlc_phy_cal_txiqlo_nphy -+ (pi, target_gain, true, -+ false) == 0) { -+ if (wlc_phy_cal_rxiq_nphy -+ (pi, target_gain, 2, -+ false) == 0) -+ wlc_phy_savecal_nphy(pi); -+ -+ } -+ } else if (pi->mphase_cal_phase_id == -+ MPHASE_CAL_STATE_IDLE) { -+ wlc_phy_cal_perical((struct brcms_phy_pub *) pi, -+ PHY_PERICAL_PHYINIT); -+ } -+ } else { -+ wlc_phy_restorecal_nphy(pi); -+ } -+ -+ wlc_phy_txpwrctrl_coeff_setup_nphy(pi); -+ -+ wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state); -+ -+ wlc_phy_nphy_tkip_rifs_war(pi, pi->sh->_rifs_phy); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LE(pi->pubpi.phy_rev, 6)) -+ -+ write_phy_reg(pi, 0x70, 50); -+ -+ wlc_phy_txlpfbw_nphy(pi); -+ -+ wlc_phy_spurwar_nphy(pi); -+ -+} -+ -+static void wlc_phy_resetcca_nphy(struct brcms_phy *pi) -+{ -+ u16 val; -+ -+ wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON); -+ -+ val = read_phy_reg(pi, 0x01); -+ write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA); -+ udelay(1); -+ write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA)); -+ -+ wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF); -+ -+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); -+} -+ -+void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en) -+{ -+ u16 rfctrlintc_override_val; -+ -+ if (!en) { -+ -+ pi->rfctrlIntc1_save = read_phy_reg(pi, 0x91); -+ pi->rfctrlIntc2_save = read_phy_reg(pi, 0x92); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ rfctrlintc_override_val = 0x1480; -+ else if (NREV_GE(pi->pubpi.phy_rev, 3)) -+ rfctrlintc_override_val = -+ CHSPEC_IS5G(pi->radio_chanspec) ? 0x600 : 0x480; -+ else -+ rfctrlintc_override_val = -+ CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120; -+ -+ write_phy_reg(pi, 0x91, rfctrlintc_override_val); -+ write_phy_reg(pi, 0x92, rfctrlintc_override_val); -+ } else { -+ write_phy_reg(pi, 0x91, pi->rfctrlIntc1_save); -+ write_phy_reg(pi, 0x92, pi->rfctrlIntc2_save); -+ } -+ -+} -+ -+void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi) -+{ -+ -+ u16 txrx_chain = -+ (NPHY_RfseqCoreActv_TxRxChain0 | NPHY_RfseqCoreActv_TxRxChain1); -+ bool CoreActv_override = false; -+ -+ if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN0) { -+ txrx_chain = NPHY_RfseqCoreActv_TxRxChain0; -+ CoreActv_override = true; -+ -+ if (NREV_LE(pi->pubpi.phy_rev, 2)) -+ and_phy_reg(pi, 0xa0, ~0x20); -+ } else if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN1) { -+ txrx_chain = NPHY_RfseqCoreActv_TxRxChain1; -+ CoreActv_override = true; -+ -+ if (NREV_LE(pi->pubpi.phy_rev, 2)) -+ or_phy_reg(pi, 0xa0, 0x20); -+ } -+ -+ mod_phy_reg(pi, 0xa2, ((0xf << 0) | (0xf << 4)), txrx_chain); -+ -+ if (CoreActv_override) { -+ pi->nphy_perical = PHY_PERICAL_DISABLE; -+ or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override); -+ } else { -+ pi->nphy_perical = PHY_PERICAL_MPHASE; -+ and_phy_reg(pi, 0xa1, ~NPHY_RfseqMode_CoreActv_override); -+ } -+} -+ -+void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask) -+{ -+ u16 regval; -+ u16 tbl_buf[16]; -+ uint i; -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ u16 tbl_opcode; -+ bool suspend; -+ -+ pi->sh->phyrxchain = rxcore_bitmask; -+ -+ if (!pi->sh->clk) -+ return; -+ -+ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); -+ if (!suspend) -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ regval = read_phy_reg(pi, 0xa2); -+ regval &= ~(0xf << 4); -+ regval |= ((u16) (rxcore_bitmask & 0x3)) << 4; -+ write_phy_reg(pi, 0xa2, regval); -+ -+ if ((rxcore_bitmask & 0x3) != 0x3) { -+ -+ write_phy_reg(pi, 0x20e, 1); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ if (pi->rx2tx_biasentry == -1) { -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, -+ ARRAY_SIZE(tbl_buf), 80, -+ 16, tbl_buf); -+ -+ for (i = 0; i < ARRAY_SIZE(tbl_buf); i++) { -+ if (tbl_buf[i] == -+ NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS) { -+ pi->rx2tx_biasentry = (u8) i; -+ tbl_opcode = -+ NPHY_REV3_RFSEQ_CMD_NOP; -+ wlc_phy_table_write_nphy( -+ pi, -+ NPHY_TBL_ID_RFSEQ, -+ 1, i, -+ 16, -+ &tbl_opcode); -+ break; -+ } else if (tbl_buf[i] == -+ NPHY_REV3_RFSEQ_CMD_END) -+ break; -+ } -+ } -+ } -+ } else { -+ -+ write_phy_reg(pi, 0x20e, 30); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ if (pi->rx2tx_biasentry != -1) { -+ tbl_opcode = NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, -+ 1, pi->rx2tx_biasentry, -+ 16, &tbl_opcode); -+ pi->rx2tx_biasentry = -1; -+ } -+ } -+ } -+ -+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+ -+ if (!suspend) -+ wlapi_enable_mac(pi->sh->physhim); -+} -+ -+u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih) -+{ -+ u16 regval, rxen_bits; -+ struct brcms_phy *pi = (struct brcms_phy *) pih; -+ -+ regval = read_phy_reg(pi, 0xa2); -+ rxen_bits = (regval >> 4) & 0xf; -+ -+ return (u8) rxen_bits; -+} -+ -+bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pi) -+{ -+ return PHY_IPA(pi); -+} -+ -+void wlc_phy_cal_init_nphy(struct brcms_phy *pi) -+{ -+} -+ -+static void wlc_phy_radio_preinit_205x(struct brcms_phy *pi) -+{ -+ -+ and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU); -+ and_phy_reg(pi, 0x78, RFCC_OE_POR_FORCE); -+ -+ or_phy_reg(pi, 0x78, ~RFCC_OE_POR_FORCE); -+ or_phy_reg(pi, 0x78, RFCC_CHIP0_PU); -+ -+} -+ -+static void wlc_phy_radio_init_2057(struct brcms_phy *pi) -+{ -+ struct radio_20xx_regs *regs_2057_ptr = NULL; -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 7)) { -+ regs_2057_ptr = regs_2057_rev4; -+ } else if (NREV_IS(pi->pubpi.phy_rev, 8) -+ || NREV_IS(pi->pubpi.phy_rev, 9)) { -+ switch (pi->pubpi.radiorev) { -+ case 5: -+ -+ if (pi->pubpi.radiover == 0x0) -+ regs_2057_ptr = regs_2057_rev5; -+ else if (pi->pubpi.radiover == 0x1) -+ regs_2057_ptr = regs_2057_rev5v1; -+ else -+ break; -+ -+ case 7: -+ -+ regs_2057_ptr = regs_2057_rev7; -+ break; -+ -+ case 8: -+ -+ regs_2057_ptr = regs_2057_rev8; -+ break; -+ -+ default: -+ break; -+ } -+ } -+ -+ wlc_phy_init_radio_regs_allbands(pi, regs_2057_ptr); -+} -+ -+static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi) -+{ -+ u16 rcal_reg = 0; -+ int i; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ if (pi->pubpi.radiorev == 5) { -+ -+ and_phy_reg(pi, 0x342, ~(0x1 << 1)); -+ -+ udelay(10); -+ -+ mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x1); -+ mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2, -+ 0x1); -+ } -+ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x1); -+ -+ udelay(10); -+ -+ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x3, 0x3); -+ -+ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { -+ rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS); -+ if (rcal_reg & 0x1) -+ break; -+ -+ udelay(100); -+ } -+ -+ if (WARN(i == MAX_205x_RCAL_WAITLOOPS, -+ "HW error: radio calib2")) -+ return 0; -+ -+ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x2, 0x0); -+ -+ rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS) & 0x3e; -+ -+ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x0); -+ if (pi->pubpi.radiorev == 5) { -+ -+ mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x0); -+ mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2, -+ 0x0); -+ } -+ -+ if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) { -+ -+ mod_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x3c, -+ rcal_reg); -+ mod_radio_reg(pi, RADIO_2057_BANDGAP_RCAL_TRIM, 0xf0, -+ rcal_reg << 2); -+ } -+ -+ } else if (NREV_IS(pi->pubpi.phy_rev, 3)) { -+ u16 savereg; -+ -+ savereg = -+ read_radio_reg( -+ pi, -+ RADIO_2056_SYN_PLL_MAST2 | -+ RADIO_2056_SYN); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN, -+ savereg | 0x7); -+ udelay(10); -+ -+ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN, -+ 0x1); -+ udelay(10); -+ -+ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN, -+ 0x9); -+ -+ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { -+ rcal_reg = read_radio_reg( -+ pi, -+ RADIO_2056_SYN_RCAL_CODE_OUT | -+ RADIO_2056_SYN); -+ if (rcal_reg & 0x80) -+ break; -+ -+ udelay(100); -+ } -+ -+ if (WARN(i == MAX_205x_RCAL_WAITLOOPS, -+ "HW error: radio calib3")) -+ return 0; -+ -+ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN, -+ 0x1); -+ -+ rcal_reg = -+ read_radio_reg(pi, -+ RADIO_2056_SYN_RCAL_CODE_OUT | -+ RADIO_2056_SYN); -+ -+ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN, -+ 0x0); -+ -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN, -+ savereg); -+ -+ return rcal_reg & 0x1f; -+ } -+ return rcal_reg & 0x3e; -+} -+ -+static u16 wlc_phy_radio2057_rccal(struct brcms_phy *pi) -+{ -+ u16 rccal_valid; -+ int i; -+ bool chip43226_6362A0; -+ -+ chip43226_6362A0 = ((pi->pubpi.radiorev == 3) -+ || (pi->pubpi.radiorev == 4) -+ || (pi->pubpi.radiorev == 6)); -+ -+ rccal_valid = 0; -+ if (chip43226_6362A0) { -+ write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x61); -+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xc0); -+ } else { -+ write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x61); -+ -+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xe9); -+ } -+ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e); -+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55); -+ -+ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { -+ rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP); -+ if (rccal_valid & 0x2) -+ break; -+ -+ udelay(500); -+ } -+ -+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15); -+ -+ rccal_valid = 0; -+ if (chip43226_6362A0) { -+ write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x69); -+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0); -+ } else { -+ write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x69); -+ -+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xd5); -+ } -+ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e); -+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55); -+ -+ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { -+ rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP); -+ if (rccal_valid & 0x2) -+ break; -+ -+ udelay(500); -+ } -+ -+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15); -+ -+ rccal_valid = 0; -+ if (chip43226_6362A0) { -+ write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x73); -+ -+ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x28); -+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0); -+ } else { -+ write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x73); -+ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e); -+ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0x99); -+ } -+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55); -+ -+ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { -+ rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP); -+ if (rccal_valid & 0x2) -+ break; -+ -+ udelay(500); -+ } -+ -+ if (WARN(!(rccal_valid & 0x2), "HW error: radio calib4")) -+ return 0; -+ -+ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15); -+ -+ return rccal_valid; -+} -+ -+static void wlc_phy_radio_postinit_2057(struct brcms_phy *pi) -+{ -+ -+ mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x1, 0x1); -+ -+ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x78); -+ mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x80); -+ mdelay(2); -+ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x0); -+ mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x0); -+ -+ if (pi->phy_init_por) { -+ wlc_phy_radio205x_rcal(pi); -+ wlc_phy_radio2057_rccal(pi); -+ } -+ -+ mod_radio_reg(pi, RADIO_2057_RFPLL_MASTER, 0x8, 0x0); -+} -+ -+static void wlc_phy_radio_init_2056(struct brcms_phy *pi) -+{ -+ const struct radio_regs *regs_SYN_2056_ptr = NULL; -+ const struct radio_regs *regs_TX_2056_ptr = NULL; -+ const struct radio_regs *regs_RX_2056_ptr = NULL; -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 3)) { -+ regs_SYN_2056_ptr = regs_SYN_2056; -+ regs_TX_2056_ptr = regs_TX_2056; -+ regs_RX_2056_ptr = regs_RX_2056; -+ } else if (NREV_IS(pi->pubpi.phy_rev, 4)) { -+ regs_SYN_2056_ptr = regs_SYN_2056_A1; -+ regs_TX_2056_ptr = regs_TX_2056_A1; -+ regs_RX_2056_ptr = regs_RX_2056_A1; -+ } else { -+ switch (pi->pubpi.radiorev) { -+ case 5: -+ regs_SYN_2056_ptr = regs_SYN_2056_rev5; -+ regs_TX_2056_ptr = regs_TX_2056_rev5; -+ regs_RX_2056_ptr = regs_RX_2056_rev5; -+ break; -+ -+ case 6: -+ regs_SYN_2056_ptr = regs_SYN_2056_rev6; -+ regs_TX_2056_ptr = regs_TX_2056_rev6; -+ regs_RX_2056_ptr = regs_RX_2056_rev6; -+ break; -+ -+ case 7: -+ case 9: -+ regs_SYN_2056_ptr = regs_SYN_2056_rev7; -+ regs_TX_2056_ptr = regs_TX_2056_rev7; -+ regs_RX_2056_ptr = regs_RX_2056_rev7; -+ break; -+ -+ case 8: -+ regs_SYN_2056_ptr = regs_SYN_2056_rev8; -+ regs_TX_2056_ptr = regs_TX_2056_rev8; -+ regs_RX_2056_ptr = regs_RX_2056_rev8; -+ break; -+ -+ case 11: -+ regs_SYN_2056_ptr = regs_SYN_2056_rev11; -+ regs_TX_2056_ptr = regs_TX_2056_rev11; -+ regs_RX_2056_ptr = regs_RX_2056_rev11; -+ break; -+ -+ default: -+ break; -+ } -+ } -+ -+ wlc_phy_init_radio_regs(pi, regs_SYN_2056_ptr, (u16) RADIO_2056_SYN); -+ -+ wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX0); -+ -+ wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX1); -+ -+ wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX0); -+ -+ wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX1); -+} -+ -+static void wlc_phy_radio_postinit_2056(struct brcms_phy *pi) -+{ -+ mod_radio_reg(pi, RADIO_2056_SYN_COM_CTRL, 0xb, 0xb); -+ -+ mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x2); -+ mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x2); -+ udelay(1000); -+ mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x0); -+ -+ if ((pi->sh->boardflags2 & BFL2_LEGACY) -+ || (pi->sh->boardflags2 & BFL2_XTALBUFOUTEN)) -+ mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xf4, 0x0); -+ else -+ mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xfc, 0x0); -+ -+ mod_radio_reg(pi, RADIO_2056_SYN_RCCAL_CTRL0, 0x1, 0x0); -+ -+ if (pi->phy_init_por) -+ wlc_phy_radio205x_rcal(pi); -+} -+ -+static void wlc_phy_radio_preinit_2055(struct brcms_phy *pi) -+{ -+ -+ and_phy_reg(pi, 0x78, ~RFCC_POR_FORCE); -+ or_phy_reg(pi, 0x78, RFCC_CHIP0_PU | RFCC_OE_POR_FORCE); -+ -+ or_phy_reg(pi, 0x78, RFCC_POR_FORCE); -+} -+ -+static void wlc_phy_radio_init_2055(struct brcms_phy *pi) -+{ -+ wlc_phy_init_radio_regs(pi, regs_2055, RADIO_DEFAULT_CORE); -+} -+ -+static void wlc_phy_radio_postinit_2055(struct brcms_phy *pi) -+{ -+ -+ and_radio_reg(pi, RADIO_2055_MASTER_CNTRL1, -+ ~(RADIO_2055_JTAGCTRL_MASK | RADIO_2055_JTAGSYNC_MASK)); -+ -+ if (((pi->sh->sromrev >= 4) -+ && !(pi->sh->boardflags2 & BFL2_RXBB_INT_REG_DIS)) -+ || ((pi->sh->sromrev < 4))) { -+ and_radio_reg(pi, RADIO_2055_CORE1_RXBB_REGULATOR, 0x7F); -+ and_radio_reg(pi, RADIO_2055_CORE2_RXBB_REGULATOR, 0x7F); -+ } -+ -+ mod_radio_reg(pi, RADIO_2055_RRCCAL_N_OPT_SEL, 0x3F, 0x2C); -+ write_radio_reg(pi, RADIO_2055_CAL_MISC, 0x3C); -+ -+ and_radio_reg(pi, RADIO_2055_CAL_MISC, -+ ~(RADIO_2055_RRCAL_START | RADIO_2055_RRCAL_RST_N)); -+ -+ or_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL, RADIO_2055_CAL_LPO_ENABLE); -+ -+ or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_RST_N); -+ -+ udelay(1000); -+ -+ or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_START); -+ -+ SPINWAIT(((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) & -+ RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE), 2000); -+ -+ if (WARN((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) & -+ RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE, -+ "HW error: radio calibration1\n")) -+ return; -+ -+ and_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL, -+ ~(RADIO_2055_CAL_LPO_ENABLE)); -+ -+ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec); -+ -+ write_radio_reg(pi, RADIO_2055_CORE1_RXBB_LPF, 9); -+ write_radio_reg(pi, RADIO_2055_CORE2_RXBB_LPF, 9); -+ -+ write_radio_reg(pi, RADIO_2055_CORE1_RXBB_MIDAC_HIPAS, 0x83); -+ write_radio_reg(pi, RADIO_2055_CORE2_RXBB_MIDAC_HIPAS, 0x83); -+ -+ mod_radio_reg(pi, RADIO_2055_CORE1_LNA_GAINBST, -+ RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE); -+ mod_radio_reg(pi, RADIO_2055_CORE2_LNA_GAINBST, -+ RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE); -+ if (pi->nphy_gain_boost) { -+ and_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1, -+ ~(RADIO_2055_GAINBST_DISABLE)); -+ and_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1, -+ ~(RADIO_2055_GAINBST_DISABLE)); -+ } else { -+ or_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1, -+ RADIO_2055_GAINBST_DISABLE); -+ or_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1, -+ RADIO_2055_GAINBST_DISABLE); -+ } -+ -+ udelay(2); -+} -+ -+void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on) -+{ -+ if (on) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ if (!pi->radio_is_on) { -+ wlc_phy_radio_preinit_205x(pi); -+ wlc_phy_radio_init_2057(pi); -+ wlc_phy_radio_postinit_2057(pi); -+ } -+ -+ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, -+ pi->radio_chanspec); -+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ wlc_phy_radio_preinit_205x(pi); -+ wlc_phy_radio_init_2056(pi); -+ wlc_phy_radio_postinit_2056(pi); -+ -+ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, -+ pi->radio_chanspec); -+ } else { -+ wlc_phy_radio_preinit_2055(pi); -+ wlc_phy_radio_init_2055(pi); -+ wlc_phy_radio_postinit_2055(pi); -+ } -+ -+ pi->radio_is_on = true; -+ -+ } else { -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3) -+ && NREV_LT(pi->pubpi.phy_rev, 7)) { -+ and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU); -+ mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x0); -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_PADA_BOOST_TUNE | -+ RADIO_2056_TX0, 0); -+ write_radio_reg(pi, -+ RADIO_2056_TX_PADG_BOOST_TUNE | -+ RADIO_2056_TX0, 0); -+ write_radio_reg(pi, -+ RADIO_2056_TX_PGAA_BOOST_TUNE | -+ RADIO_2056_TX0, 0); -+ write_radio_reg(pi, -+ RADIO_2056_TX_PGAG_BOOST_TUNE | -+ RADIO_2056_TX0, 0); -+ mod_radio_reg(pi, -+ RADIO_2056_TX_MIXA_BOOST_TUNE | -+ RADIO_2056_TX0, 0xf0, 0); -+ write_radio_reg(pi, -+ RADIO_2056_TX_MIXG_BOOST_TUNE | -+ RADIO_2056_TX0, 0); -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_PADA_BOOST_TUNE | -+ RADIO_2056_TX1, 0); -+ write_radio_reg(pi, -+ RADIO_2056_TX_PADG_BOOST_TUNE | -+ RADIO_2056_TX1, 0); -+ write_radio_reg(pi, -+ RADIO_2056_TX_PGAA_BOOST_TUNE | -+ RADIO_2056_TX1, 0); -+ write_radio_reg(pi, -+ RADIO_2056_TX_PGAG_BOOST_TUNE | -+ RADIO_2056_TX1, 0); -+ mod_radio_reg(pi, -+ RADIO_2056_TX_MIXA_BOOST_TUNE | -+ RADIO_2056_TX1, 0xf0, 0); -+ write_radio_reg(pi, -+ RADIO_2056_TX_MIXG_BOOST_TUNE | -+ RADIO_2056_TX1, 0); -+ -+ pi->radio_is_on = false; -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 8)) { -+ and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU); -+ pi->radio_is_on = false; -+ } -+ -+ } -+} -+ -+static bool -+wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f, -+ const struct chan_info_nphy_radio2057 **t0, -+ const struct chan_info_nphy_radio205x **t1, -+ const struct chan_info_nphy_radio2057_rev5 **t2, -+ const struct chan_info_nphy_2055 **t3) -+{ -+ uint i; -+ const struct chan_info_nphy_radio2057 *chan_info_tbl_p_0 = NULL; -+ const struct chan_info_nphy_radio205x *chan_info_tbl_p_1 = NULL; -+ const struct chan_info_nphy_radio2057_rev5 *chan_info_tbl_p_2 = NULL; -+ u32 tbl_len = 0; -+ -+ int freq = 0; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 7)) { -+ -+ chan_info_tbl_p_0 = chan_info_nphyrev7_2057_rev4; -+ tbl_len = ARRAY_SIZE(chan_info_nphyrev7_2057_rev4); -+ -+ } else if (NREV_IS(pi->pubpi.phy_rev, 8) -+ || NREV_IS(pi->pubpi.phy_rev, 9)) { -+ switch (pi->pubpi.radiorev) { -+ -+ case 5: -+ -+ if (pi->pubpi.radiover == 0x0) { -+ -+ chan_info_tbl_p_2 = -+ chan_info_nphyrev8_2057_rev5; -+ tbl_len = ARRAY_SIZE( -+ chan_info_nphyrev8_2057_rev5); -+ -+ } else if (pi->pubpi.radiover == 0x1) { -+ -+ chan_info_tbl_p_2 = -+ chan_info_nphyrev9_2057_rev5v1; -+ tbl_len = ARRAY_SIZE( -+ chan_info_nphyrev9_2057_rev5v1); -+ -+ } -+ break; -+ -+ case 7: -+ chan_info_tbl_p_0 = -+ chan_info_nphyrev8_2057_rev7; -+ tbl_len = ARRAY_SIZE( -+ chan_info_nphyrev8_2057_rev7); -+ break; -+ -+ case 8: -+ chan_info_tbl_p_0 = -+ chan_info_nphyrev8_2057_rev8; -+ tbl_len = ARRAY_SIZE( -+ chan_info_nphyrev8_2057_rev8); -+ break; -+ -+ default: -+ break; -+ } -+ } else if (NREV_IS(pi->pubpi.phy_rev, 16)) { -+ -+ chan_info_tbl_p_0 = chan_info_nphyrev8_2057_rev8; -+ tbl_len = ARRAY_SIZE(chan_info_nphyrev8_2057_rev8); -+ } else { -+ goto fail; -+ } -+ -+ for (i = 0; i < tbl_len; i++) { -+ if (pi->pubpi.radiorev == 5) { -+ -+ if (chan_info_tbl_p_2[i].chan == channel) -+ break; -+ } else { -+ -+ if (chan_info_tbl_p_0[i].chan == channel) -+ break; -+ } -+ } -+ -+ if (i >= tbl_len) -+ goto fail; -+ -+ if (pi->pubpi.radiorev == 5) { -+ *t2 = &chan_info_tbl_p_2[i]; -+ freq = chan_info_tbl_p_2[i].freq; -+ } else { -+ *t0 = &chan_info_tbl_p_0[i]; -+ freq = chan_info_tbl_p_0[i].freq; -+ } -+ -+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ if (NREV_IS(pi->pubpi.phy_rev, 3)) { -+ chan_info_tbl_p_1 = chan_info_nphyrev3_2056; -+ tbl_len = ARRAY_SIZE(chan_info_nphyrev3_2056); -+ } else if (NREV_IS(pi->pubpi.phy_rev, 4)) { -+ chan_info_tbl_p_1 = chan_info_nphyrev4_2056_A1; -+ tbl_len = ARRAY_SIZE(chan_info_nphyrev4_2056_A1); -+ } else if (NREV_IS(pi->pubpi.phy_rev, 5) -+ || NREV_IS(pi->pubpi.phy_rev, 6)) { -+ switch (pi->pubpi.radiorev) { -+ case 5: -+ chan_info_tbl_p_1 = chan_info_nphyrev5_2056v5; -+ tbl_len = ARRAY_SIZE(chan_info_nphyrev5_2056v5); -+ break; -+ case 6: -+ chan_info_tbl_p_1 = chan_info_nphyrev6_2056v6; -+ tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v6); -+ break; -+ case 7: -+ case 9: -+ chan_info_tbl_p_1 = chan_info_nphyrev5n6_2056v7; -+ tbl_len = -+ ARRAY_SIZE(chan_info_nphyrev5n6_2056v7); -+ break; -+ case 8: -+ chan_info_tbl_p_1 = chan_info_nphyrev6_2056v8; -+ tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v8); -+ break; -+ case 11: -+ chan_info_tbl_p_1 = chan_info_nphyrev6_2056v11; -+ tbl_len = ARRAY_SIZE( -+ chan_info_nphyrev6_2056v11); -+ break; -+ default: -+ break; -+ } -+ } -+ -+ for (i = 0; i < tbl_len; i++) { -+ if (chan_info_tbl_p_1[i].chan == channel) -+ break; -+ } -+ -+ if (i >= tbl_len) -+ goto fail; -+ -+ *t1 = &chan_info_tbl_p_1[i]; -+ freq = chan_info_tbl_p_1[i].freq; -+ -+ } else { -+ for (i = 0; i < ARRAY_SIZE(chan_info_nphy_2055); i++) -+ if (chan_info_nphy_2055[i].chan == channel) -+ break; -+ -+ if (i >= ARRAY_SIZE(chan_info_nphy_2055)) -+ goto fail; -+ -+ *t3 = &chan_info_nphy_2055[i]; -+ freq = chan_info_nphy_2055[i].freq; -+ } -+ -+ *f = freq; -+ return true; -+ -+fail: -+ *f = WL_CHAN_FREQ_RANGE_2G; -+ return false; -+} -+ -+u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint channel) -+{ -+ int freq; -+ const struct chan_info_nphy_radio2057 *t0 = NULL; -+ const struct chan_info_nphy_radio205x *t1 = NULL; -+ const struct chan_info_nphy_radio2057_rev5 *t2 = NULL; -+ const struct chan_info_nphy_2055 *t3 = NULL; -+ -+ if (channel == 0) -+ channel = CHSPEC_CHANNEL(pi->radio_chanspec); -+ -+ wlc_phy_chan2freq_nphy(pi, channel, &freq, &t0, &t1, &t2, &t3); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) -+ return WL_CHAN_FREQ_RANGE_2G; -+ -+ if ((freq >= BASE_LOW_5G_CHAN) && (freq < BASE_MID_5G_CHAN)) -+ return WL_CHAN_FREQ_RANGE_5GL; -+ else if ((freq >= BASE_MID_5G_CHAN) && (freq < BASE_HIGH_5G_CHAN)) -+ return WL_CHAN_FREQ_RANGE_5GM; -+ else -+ return WL_CHAN_FREQ_RANGE_5GH; -+} -+ -+static void -+wlc_phy_chanspec_radio2055_setup(struct brcms_phy *pi, -+ const struct chan_info_nphy_2055 *ci) -+{ -+ -+ write_radio_reg(pi, RADIO_2055_PLL_REF, ci->RF_pll_ref); -+ write_radio_reg(pi, RADIO_2055_RF_PLL_MOD0, ci->RF_rf_pll_mod0); -+ write_radio_reg(pi, RADIO_2055_RF_PLL_MOD1, ci->RF_rf_pll_mod1); -+ write_radio_reg(pi, RADIO_2055_VCO_CAP_TAIL, ci->RF_vco_cap_tail); -+ -+ BRCMS_PHY_WAR_PR51571(pi); -+ -+ write_radio_reg(pi, RADIO_2055_VCO_CAL1, ci->RF_vco_cal1); -+ write_radio_reg(pi, RADIO_2055_VCO_CAL2, ci->RF_vco_cal2); -+ write_radio_reg(pi, RADIO_2055_PLL_LF_C1, ci->RF_pll_lf_c1); -+ write_radio_reg(pi, RADIO_2055_PLL_LF_R1, ci->RF_pll_lf_r1); -+ -+ BRCMS_PHY_WAR_PR51571(pi); -+ -+ write_radio_reg(pi, RADIO_2055_PLL_LF_C2, ci->RF_pll_lf_c2); -+ write_radio_reg(pi, RADIO_2055_LGBUF_CEN_BUF, ci->RF_lgbuf_cen_buf); -+ write_radio_reg(pi, RADIO_2055_LGEN_TUNE1, ci->RF_lgen_tune1); -+ write_radio_reg(pi, RADIO_2055_LGEN_TUNE2, ci->RF_lgen_tune2); -+ -+ BRCMS_PHY_WAR_PR51571(pi); -+ -+ write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_A_TUNE, -+ ci->RF_core1_lgbuf_a_tune); -+ write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_G_TUNE, -+ ci->RF_core1_lgbuf_g_tune); -+ write_radio_reg(pi, RADIO_2055_CORE1_RXRF_REG1, ci->RF_core1_rxrf_reg1); -+ write_radio_reg(pi, RADIO_2055_CORE1_TX_PGA_PAD_TN, -+ ci->RF_core1_tx_pga_pad_tn); -+ -+ BRCMS_PHY_WAR_PR51571(pi); -+ -+ write_radio_reg(pi, RADIO_2055_CORE1_TX_MX_BGTRIM, -+ ci->RF_core1_tx_mx_bgtrim); -+ write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_A_TUNE, -+ ci->RF_core2_lgbuf_a_tune); -+ write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_G_TUNE, -+ ci->RF_core2_lgbuf_g_tune); -+ write_radio_reg(pi, RADIO_2055_CORE2_RXRF_REG1, ci->RF_core2_rxrf_reg1); -+ -+ BRCMS_PHY_WAR_PR51571(pi); -+ -+ write_radio_reg(pi, RADIO_2055_CORE2_TX_PGA_PAD_TN, -+ ci->RF_core2_tx_pga_pad_tn); -+ write_radio_reg(pi, RADIO_2055_CORE2_TX_MX_BGTRIM, -+ ci->RF_core2_tx_mx_bgtrim); -+ -+ udelay(50); -+ -+ write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x05); -+ write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x45); -+ -+ BRCMS_PHY_WAR_PR51571(pi); -+ -+ write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x65); -+ -+ udelay(300); -+} -+ -+static void -+wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi, -+ const struct chan_info_nphy_radio205x *ci) -+{ -+ const struct radio_regs *regs_SYN_2056_ptr = NULL; -+ -+ write_radio_reg(pi, -+ RADIO_2056_SYN_PLL_VCOCAL1 | RADIO_2056_SYN, -+ ci->RF_SYN_pll_vcocal1); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL2 | RADIO_2056_SYN, -+ ci->RF_SYN_pll_vcocal2); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_REFDIV | RADIO_2056_SYN, -+ ci->RF_SYN_pll_refdiv); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD2 | RADIO_2056_SYN, -+ ci->RF_SYN_pll_mmd2); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD1 | RADIO_2056_SYN, -+ ci->RF_SYN_pll_mmd1); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN, -+ ci->RF_SYN_pll_loopfilter1); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN, -+ ci->RF_SYN_pll_loopfilter2); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER3 | RADIO_2056_SYN, -+ ci->RF_SYN_pll_loopfilter3); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN, -+ ci->RF_SYN_pll_loopfilter4); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER5 | RADIO_2056_SYN, -+ ci->RF_SYN_pll_loopfilter5); -+ write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR27 | RADIO_2056_SYN, -+ ci->RF_SYN_reserved_addr27); -+ write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR28 | RADIO_2056_SYN, -+ ci->RF_SYN_reserved_addr28); -+ write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR29 | RADIO_2056_SYN, -+ ci->RF_SYN_reserved_addr29); -+ write_radio_reg(pi, RADIO_2056_SYN_LOGEN_VCOBUF1 | RADIO_2056_SYN, -+ ci->RF_SYN_logen_VCOBUF1); -+ write_radio_reg(pi, RADIO_2056_SYN_LOGEN_MIXER2 | RADIO_2056_SYN, -+ ci->RF_SYN_logen_MIXER2); -+ write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF3 | RADIO_2056_SYN, -+ ci->RF_SYN_logen_BUF3); -+ write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF4 | RADIO_2056_SYN, -+ ci->RF_SYN_logen_BUF4); -+ -+ write_radio_reg(pi, -+ RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX0, -+ ci->RF_RX0_lnaa_tune); -+ write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX0, -+ ci->RF_RX0_lnag_tune); -+ write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX0, -+ ci->RF_TX0_intpaa_boost_tune); -+ write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX0, -+ ci->RF_TX0_intpag_boost_tune); -+ write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX0, -+ ci->RF_TX0_pada_boost_tune); -+ write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX0, -+ ci->RF_TX0_padg_boost_tune); -+ write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX0, -+ ci->RF_TX0_pgaa_boost_tune); -+ write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX0, -+ ci->RF_TX0_pgag_boost_tune); -+ write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX0, -+ ci->RF_TX0_mixa_boost_tune); -+ write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX0, -+ ci->RF_TX0_mixg_boost_tune); -+ -+ write_radio_reg(pi, -+ RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX1, -+ ci->RF_RX1_lnaa_tune); -+ write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX1, -+ ci->RF_RX1_lnag_tune); -+ write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX1, -+ ci->RF_TX1_intpaa_boost_tune); -+ write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX1, -+ ci->RF_TX1_intpag_boost_tune); -+ write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX1, -+ ci->RF_TX1_pada_boost_tune); -+ write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX1, -+ ci->RF_TX1_padg_boost_tune); -+ write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX1, -+ ci->RF_TX1_pgaa_boost_tune); -+ write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX1, -+ ci->RF_TX1_pgag_boost_tune); -+ write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX1, -+ ci->RF_TX1_mixa_boost_tune); -+ write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX1, -+ ci->RF_TX1_mixg_boost_tune); -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 3)) -+ regs_SYN_2056_ptr = regs_SYN_2056; -+ else if (NREV_IS(pi->pubpi.phy_rev, 4)) -+ regs_SYN_2056_ptr = regs_SYN_2056_A1; -+ else { -+ switch (pi->pubpi.radiorev) { -+ case 5: -+ regs_SYN_2056_ptr = regs_SYN_2056_rev5; -+ break; -+ case 6: -+ regs_SYN_2056_ptr = regs_SYN_2056_rev6; -+ break; -+ case 7: -+ case 9: -+ regs_SYN_2056_ptr = regs_SYN_2056_rev7; -+ break; -+ case 8: -+ regs_SYN_2056_ptr = regs_SYN_2056_rev8; -+ break; -+ case 11: -+ regs_SYN_2056_ptr = regs_SYN_2056_rev11; -+ break; -+ } -+ } -+ if (CHSPEC_IS2G(pi->radio_chanspec)) -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | -+ RADIO_2056_SYN, -+ (u16) regs_SYN_2056_ptr[0x49 - 2].init_g); -+ else -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | -+ RADIO_2056_SYN, -+ (u16) regs_SYN_2056_ptr[0x49 - 2].init_a); -+ -+ if (pi->sh->boardflags2 & BFL2_GPLL_WAR) { -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 | -+ RADIO_2056_SYN, 0x1f); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | -+ RADIO_2056_SYN, 0x1f); -+ -+ write_radio_reg(pi, -+ RADIO_2056_SYN_PLL_LOOPFILTER4 | -+ RADIO_2056_SYN, 0xb); -+ write_radio_reg(pi, -+ RADIO_2056_SYN_PLL_CP2 | -+ RADIO_2056_SYN, 0x14); -+ } -+ } -+ -+ if ((pi->sh->boardflags2 & BFL2_GPLL_WAR2) && -+ (CHSPEC_IS2G(pi->radio_chanspec))) { -+ write_radio_reg(pi, -+ RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN, -+ 0x1f); -+ write_radio_reg(pi, -+ RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN, -+ 0x1f); -+ write_radio_reg(pi, -+ RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN, -+ 0xb); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | RADIO_2056_SYN, -+ 0x20); -+ } -+ -+ if (pi->sh->boardflags2 & BFL2_APLL_WAR) { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 | -+ RADIO_2056_SYN, 0x1f); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | -+ RADIO_2056_SYN, 0x1f); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 | -+ RADIO_2056_SYN, 0x5); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | -+ RADIO_2056_SYN, 0xc); -+ } -+ } -+ -+ if (PHY_IPA(pi) && CHSPEC_IS2G(pi->radio_chanspec)) { -+ u16 pag_boost_tune; -+ u16 padg_boost_tune; -+ u16 pgag_boost_tune; -+ u16 mixg_boost_tune; -+ u16 bias, cascbias; -+ uint core; -+ -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 5)) { -+ -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ PADG_IDAC, 0xcc); -+ -+ bias = 0x25; -+ cascbias = 0x20; -+ -+ if ((pi->sh->chip == -+ BCM43224_CHIP_ID) -+ || (pi->sh->chip == -+ BCM43225_CHIP_ID)) { -+ if (pi->sh->chippkg == -+ BCM43224_FAB_SMIC) { -+ bias = 0x2a; -+ cascbias = 0x38; -+ } -+ } -+ -+ pag_boost_tune = 0x4; -+ pgag_boost_tune = 0x03; -+ padg_boost_tune = 0x77; -+ mixg_boost_tune = 0x65; -+ -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAG_IMAIN_STAT, bias); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAG_IAUX_STAT, bias); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAG_CASCBIAS, cascbias); -+ -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAG_BOOST_TUNE, -+ pag_boost_tune); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ PGAG_BOOST_TUNE, -+ pgag_boost_tune); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ PADG_BOOST_TUNE, -+ padg_boost_tune); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ MIXG_BOOST_TUNE, -+ mixg_boost_tune); -+ } else { -+ -+ bias = (pi->bw == WL_CHANSPEC_BW_40) ? -+ 0x40 : 0x20; -+ -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAG_IMAIN_STAT, bias); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAG_IAUX_STAT, bias); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAG_CASCBIAS, 0x30); -+ } -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, PA_SPARE1, -+ 0xee); -+ } -+ } -+ -+ if (PHY_IPA(pi) && NREV_IS(pi->pubpi.phy_rev, 6) -+ && CHSPEC_IS5G(pi->radio_chanspec)) { -+ u16 paa_boost_tune; -+ u16 pada_boost_tune; -+ u16 pgaa_boost_tune; -+ u16 mixa_boost_tune; -+ u16 freq, pabias, cascbias; -+ uint core; -+ -+ freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec)); -+ -+ if (freq < 5150) { -+ -+ paa_boost_tune = 0xa; -+ pada_boost_tune = 0x77; -+ pgaa_boost_tune = 0xf; -+ mixa_boost_tune = 0xf; -+ } else if (freq < 5340) { -+ -+ paa_boost_tune = 0x8; -+ pada_boost_tune = 0x77; -+ pgaa_boost_tune = 0xfb; -+ mixa_boost_tune = 0xf; -+ } else if (freq < 5650) { -+ -+ paa_boost_tune = 0x0; -+ pada_boost_tune = 0x77; -+ pgaa_boost_tune = 0xb; -+ mixa_boost_tune = 0xf; -+ } else { -+ -+ paa_boost_tune = 0x0; -+ pada_boost_tune = 0x77; -+ if (freq != 5825) -+ pgaa_boost_tune = -(int)(freq - 18) / 36 + 168; -+ else -+ pgaa_boost_tune = 6; -+ -+ mixa_boost_tune = 0xf; -+ } -+ -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAA_BOOST_TUNE, paa_boost_tune); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ PADA_BOOST_TUNE, pada_boost_tune); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ PGAA_BOOST_TUNE, pgaa_boost_tune); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ MIXA_BOOST_TUNE, mixa_boost_tune); -+ -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ TXSPARE1, 0x30); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ PA_SPARE2, 0xee); -+ -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ PADA_CASCBIAS, 0x3); -+ -+ cascbias = 0x30; -+ -+ if ((pi->sh->chip == BCM43224_CHIP_ID) || -+ (pi->sh->chip == BCM43225_CHIP_ID)) { -+ if (pi->sh->chippkg == BCM43224_FAB_SMIC) -+ cascbias = 0x35; -+ } -+ -+ pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias; -+ -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAA_IAUX_STAT, pabias); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAA_IMAIN_STAT, pabias); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAA_CASCBIAS, cascbias); -+ } -+ } -+ -+ udelay(50); -+ -+ wlc_phy_radio205x_vcocal_nphy(pi); -+} -+ -+void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi) -+{ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x0); -+ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04, 0x0); -+ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04, -+ (1 << 2)); -+ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x01); -+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL12, 0x0); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x18); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38); -+ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x39); -+ } -+ -+ udelay(300); -+} -+ -+static void -+wlc_phy_chanspec_radio2057_setup( -+ struct brcms_phy *pi, -+ const struct chan_info_nphy_radio2057 *ci, -+ const struct chan_info_nphy_radio2057_rev5 * -+ ci2) -+{ -+ int coreNum; -+ u16 txmix2g_tune_boost_pu = 0; -+ u16 pad2g_tune_pus = 0; -+ -+ if (pi->pubpi.radiorev == 5) { -+ -+ write_radio_reg(pi, -+ RADIO_2057_VCOCAL_COUNTVAL0, -+ ci2->RF_vcocal_countval0); -+ write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1, -+ ci2->RF_vcocal_countval1); -+ write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE, -+ ci2->RF_rfpll_refmaster_sparextalsize); -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, -+ ci2->RF_rfpll_loopfilter_r1); -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, -+ ci2->RF_rfpll_loopfilter_c2); -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, -+ ci2->RF_rfpll_loopfilter_c1); -+ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, -+ ci2->RF_cp_kpd_idac); -+ write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci2->RF_rfpll_mmd0); -+ write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci2->RF_rfpll_mmd1); -+ write_radio_reg(pi, -+ RADIO_2057_VCOBUF_TUNE, ci2->RF_vcobuf_tune); -+ write_radio_reg(pi, -+ RADIO_2057_LOGEN_MX2G_TUNE, -+ ci2->RF_logen_mx2g_tune); -+ write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE, -+ ci2->RF_logen_indbuf2g_tune); -+ -+ write_radio_reg(pi, -+ RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0, -+ ci2->RF_txmix2g_tune_boost_pu_core0); -+ write_radio_reg(pi, -+ RADIO_2057_PAD2G_TUNE_PUS_CORE0, -+ ci2->RF_pad2g_tune_pus_core0); -+ write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0, -+ ci2->RF_lna2g_tune_core0); -+ -+ write_radio_reg(pi, -+ RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1, -+ ci2->RF_txmix2g_tune_boost_pu_core1); -+ write_radio_reg(pi, -+ RADIO_2057_PAD2G_TUNE_PUS_CORE1, -+ ci2->RF_pad2g_tune_pus_core1); -+ write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1, -+ ci2->RF_lna2g_tune_core1); -+ -+ } else { -+ -+ write_radio_reg(pi, -+ RADIO_2057_VCOCAL_COUNTVAL0, -+ ci->RF_vcocal_countval0); -+ write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1, -+ ci->RF_vcocal_countval1); -+ write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE, -+ ci->RF_rfpll_refmaster_sparextalsize); -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, -+ ci->RF_rfpll_loopfilter_r1); -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, -+ ci->RF_rfpll_loopfilter_c2); -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, -+ ci->RF_rfpll_loopfilter_c1); -+ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, ci->RF_cp_kpd_idac); -+ write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci->RF_rfpll_mmd0); -+ write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci->RF_rfpll_mmd1); -+ write_radio_reg(pi, RADIO_2057_VCOBUF_TUNE, ci->RF_vcobuf_tune); -+ write_radio_reg(pi, -+ RADIO_2057_LOGEN_MX2G_TUNE, -+ ci->RF_logen_mx2g_tune); -+ write_radio_reg(pi, RADIO_2057_LOGEN_MX5G_TUNE, -+ ci->RF_logen_mx5g_tune); -+ write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE, -+ ci->RF_logen_indbuf2g_tune); -+ write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF5G_TUNE, -+ ci->RF_logen_indbuf5g_tune); -+ -+ write_radio_reg(pi, -+ RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0, -+ ci->RF_txmix2g_tune_boost_pu_core0); -+ write_radio_reg(pi, -+ RADIO_2057_PAD2G_TUNE_PUS_CORE0, -+ ci->RF_pad2g_tune_pus_core0); -+ write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE0, -+ ci->RF_pga_boost_tune_core0); -+ write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0, -+ ci->RF_txmix5g_boost_tune_core0); -+ write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0, -+ ci->RF_pad5g_tune_misc_pus_core0); -+ write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0, -+ ci->RF_lna2g_tune_core0); -+ write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE0, -+ ci->RF_lna5g_tune_core0); -+ -+ write_radio_reg(pi, -+ RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1, -+ ci->RF_txmix2g_tune_boost_pu_core1); -+ write_radio_reg(pi, -+ RADIO_2057_PAD2G_TUNE_PUS_CORE1, -+ ci->RF_pad2g_tune_pus_core1); -+ write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE1, -+ ci->RF_pga_boost_tune_core1); -+ write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1, -+ ci->RF_txmix5g_boost_tune_core1); -+ write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1, -+ ci->RF_pad5g_tune_misc_pus_core1); -+ write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1, -+ ci->RF_lna2g_tune_core1); -+ write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE1, -+ ci->RF_lna5g_tune_core1); -+ } -+ -+ if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) { -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, -+ 0x3f); -+ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f); -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, -+ 0x8); -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, -+ 0x8); -+ } else { -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, -+ 0x1f); -+ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f); -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, -+ 0x8); -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, -+ 0x8); -+ } -+ } else if ((pi->pubpi.radiorev == 5) || (pi->pubpi.radiorev == 7) || -+ (pi->pubpi.radiorev == 8)) { -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, -+ 0x1b); -+ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x30); -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, -+ 0xa); -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, -+ 0xa); -+ } else { -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, -+ 0x1f); -+ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f); -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, -+ 0x8); -+ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, -+ 0x8); -+ } -+ -+ } -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if (PHY_IPA(pi)) { -+ if (pi->pubpi.radiorev == 3) -+ txmix2g_tune_boost_pu = 0x6b; -+ -+ if (pi->pubpi.radiorev == 5) -+ pad2g_tune_pus = 0x73; -+ -+ } else { -+ if (pi->pubpi.radiorev != 5) { -+ pad2g_tune_pus = 0x3; -+ -+ txmix2g_tune_boost_pu = 0x61; -+ } -+ } -+ -+ for (coreNum = 0; coreNum <= 1; coreNum++) { -+ -+ if (txmix2g_tune_boost_pu != 0) -+ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, -+ TXMIX2G_TUNE_BOOST_PU, -+ txmix2g_tune_boost_pu); -+ -+ if (pad2g_tune_pus != 0) -+ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, -+ PAD2G_TUNE_PUS, -+ pad2g_tune_pus); -+ } -+ } -+ -+ udelay(50); -+ -+ wlc_phy_radio205x_vcocal_nphy(pi); -+} -+ -+static void -+wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, -+ const struct nphy_sfo_cfg *ci) -+{ -+ u16 val; -+ -+ val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; -+ if (CHSPEC_IS5G(chanspec) && !val) { -+ -+ val = R_REG(&pi->regs->psm_phy_hdr_param); -+ W_REG(&pi->regs->psm_phy_hdr_param, -+ (val | MAC_PHY_FORCE_CLK)); -+ -+ or_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG), -+ (BBCFG_RESETCCA | BBCFG_RESETRX)); -+ -+ W_REG(&pi->regs->psm_phy_hdr_param, val); -+ -+ or_phy_reg(pi, 0x09, NPHY_BandControl_currentBand); -+ } else if (!CHSPEC_IS5G(chanspec) && val) { -+ -+ and_phy_reg(pi, 0x09, ~NPHY_BandControl_currentBand); -+ -+ val = R_REG(&pi->regs->psm_phy_hdr_param); -+ W_REG(&pi->regs->psm_phy_hdr_param, -+ (val | MAC_PHY_FORCE_CLK)); -+ -+ and_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG), -+ (u16) (~(BBCFG_RESETCCA | BBCFG_RESETRX))); -+ -+ W_REG(&pi->regs->psm_phy_hdr_param, val); -+ } -+ -+ write_phy_reg(pi, 0x1ce, ci->PHY_BW1a); -+ write_phy_reg(pi, 0x1cf, ci->PHY_BW2); -+ write_phy_reg(pi, 0x1d0, ci->PHY_BW3); -+ -+ write_phy_reg(pi, 0x1d1, ci->PHY_BW4); -+ write_phy_reg(pi, 0x1d2, ci->PHY_BW5); -+ write_phy_reg(pi, 0x1d3, ci->PHY_BW6); -+ -+ if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) { -+ wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en, 0); -+ -+ or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, 0x800); -+ } else { -+ wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en, -+ NPHY_ClassifierCtrl_ofdm_en); -+ -+ if (CHSPEC_IS2G(chanspec)) -+ and_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, ~0x840); -+ } -+ -+ if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) -+ wlc_phy_txpwr_fixpower_nphy(pi); -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 3)) -+ wlc_phy_adjust_lnagaintbl_nphy(pi); -+ -+ wlc_phy_txlpfbw_nphy(pi); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3) -+ && (pi->phy_spuravoid != SPURAVOID_DISABLE)) { -+ u8 spuravoid = 0; -+ -+ val = CHSPEC_CHANNEL(chanspec); -+ if (!CHSPEC_IS40(pi->radio_chanspec)) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ if ((val == 13) || (val == 14) || (val == 153)) -+ spuravoid = 1; -+ } else if (((val >= 5) && (val <= 8)) || (val == 13) -+ || (val == 14)) { -+ spuravoid = 1; -+ } -+ } else if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ if (val == 54) -+ spuravoid = 1; -+ } else { -+ if (pi->nphy_aband_spurwar_en && -+ ((val == 38) || (val == 102) -+ || (val == 118))) -+ spuravoid = 1; -+ } -+ -+ if (pi->phy_spuravoid == SPURAVOID_FORCEON) -+ spuravoid = 1; -+ -+ wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false); -+ si_pmu_spuravoid(pi->sh->sih, spuravoid); -+ wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true); -+ -+ if ((pi->sh->chip == BCM43224_CHIP_ID) || -+ (pi->sh->chip == BCM43225_CHIP_ID)) { -+ -+ if (spuravoid == 1) { -+ -+ W_REG(&pi->regs->tsf_clk_frac_l, -+ 0x5341); -+ W_REG(&pi->regs->tsf_clk_frac_h, -+ 0x8); -+ } else { -+ -+ W_REG(&pi->regs->tsf_clk_frac_l, -+ 0x8889); -+ W_REG(&pi->regs->tsf_clk_frac_h, -+ 0x8); -+ } -+ } -+ -+ wlapi_bmac_core_phypll_reset(pi->sh->physhim); -+ -+ mod_phy_reg(pi, 0x01, (0x1 << 15), -+ ((spuravoid > 0) ? (0x1 << 15) : 0)); -+ -+ wlc_phy_resetcca_nphy(pi); -+ -+ pi->phy_isspuravoid = (spuravoid > 0); -+ } -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 7)) -+ write_phy_reg(pi, 0x17e, 0x3830); -+ -+ wlc_phy_spurwar_nphy(pi); -+} -+ -+void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, u16 chanspec) -+{ -+ int freq; -+ const struct chan_info_nphy_radio2057 *t0 = NULL; -+ const struct chan_info_nphy_radio205x *t1 = NULL; -+ const struct chan_info_nphy_radio2057_rev5 *t2 = NULL; -+ const struct chan_info_nphy_2055 *t3 = NULL; -+ -+ if (!wlc_phy_chan2freq_nphy -+ (pi, CHSPEC_CHANNEL(chanspec), &freq, &t0, &t1, &t2, &t3)) -+ return; -+ -+ wlc_phy_chanspec_radio_set((struct brcms_phy_pub *) pi, chanspec); -+ -+ if (CHSPEC_BW(chanspec) != pi->bw) -+ wlapi_bmac_bw_set(pi->sh->physhim, CHSPEC_BW(chanspec)); -+ -+ if (CHSPEC_IS40(chanspec)) { -+ if (CHSPEC_SB_UPPER(chanspec)) { -+ or_phy_reg(pi, 0xa0, BPHY_BAND_SEL_UP20); -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ or_phy_reg(pi, 0x310, PRIM_SEL_UP20); -+ } else { -+ and_phy_reg(pi, 0xa0, ~BPHY_BAND_SEL_UP20); -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ and_phy_reg(pi, 0x310, -+ (~PRIM_SEL_UP20 & 0xffff)); -+ } -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ if ((pi->pubpi.radiorev <= 4) -+ || (pi->pubpi.radiorev == 6)) { -+ mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE0, -+ 0x2, -+ (CHSPEC_IS5G(chanspec) ? (1 << 1) -+ : 0)); -+ mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE1, -+ 0x2, -+ (CHSPEC_IS5G(chanspec) ? (1 << 1) -+ : 0)); -+ } -+ -+ wlc_phy_chanspec_radio2057_setup(pi, t0, t2); -+ wlc_phy_chanspec_nphy_setup(pi, chanspec, -+ (pi->pubpi.radiorev == 5) ? -+ (const struct nphy_sfo_cfg *)&(t2->PHY_BW1a) : -+ (const struct nphy_sfo_cfg *)&(t0->PHY_BW1a)); -+ -+ } else { -+ -+ mod_radio_reg(pi, -+ RADIO_2056_SYN_COM_CTRL | RADIO_2056_SYN, -+ 0x4, -+ (CHSPEC_IS5G(chanspec) ? (0x1 << 2) : 0)); -+ wlc_phy_chanspec_radio2056_setup(pi, t1); -+ -+ wlc_phy_chanspec_nphy_setup(pi, chanspec, -+ (const struct nphy_sfo_cfg *) &(t1->PHY_BW1a)); -+ } -+ -+ } else { -+ -+ mod_radio_reg(pi, RADIO_2055_MASTER_CNTRL1, 0x70, -+ (CHSPEC_IS5G(chanspec) ? (0x02 << 4) -+ : (0x05 << 4))); -+ -+ wlc_phy_chanspec_radio2055_setup(pi, t3); -+ wlc_phy_chanspec_nphy_setup(pi, chanspec, -+ (const struct nphy_sfo_cfg *) -+ &(t3->PHY_BW1a)); -+ } -+ -+} -+ -+void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init) -+{ -+ struct brcms_phy *pi = (struct brcms_phy *) ppi; -+ u16 mask = 0xfc00; -+ u32 mc = 0; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ return; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ u16 v0 = 0x211, v1 = 0x222, v2 = 0x144, v3 = 0x188; -+ -+ if (lut_init == false) -+ return; -+ -+ if (pi->srom_fem2g.antswctrllut == 0) { -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, -+ 1, 0x02, 16, &v0); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, -+ 1, 0x03, 16, &v1); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, -+ 1, 0x08, 16, &v2); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, -+ 1, 0x0C, 16, &v3); -+ } -+ -+ if (pi->srom_fem5g.antswctrllut == 0) { -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, -+ 1, 0x12, 16, &v0); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, -+ 1, 0x13, 16, &v1); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, -+ 1, 0x18, 16, &v2); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, -+ 1, 0x1C, 16, &v3); -+ } -+ } else { -+ -+ write_phy_reg(pi, 0xc8, 0x0); -+ write_phy_reg(pi, 0xc9, 0x0); -+ -+ ai_gpiocontrol(pi->sh->sih, mask, mask, GPIO_DRV_PRIORITY); -+ -+ mc = R_REG(&pi->regs->maccontrol); -+ mc &= ~MCTL_GPOUT_SEL_MASK; -+ W_REG(&pi->regs->maccontrol, mc); -+ -+ OR_REG(&pi->regs->psm_gpio_oe, mask); -+ -+ AND_REG(&pi->regs->psm_gpio_out, ~mask); -+ -+ if (lut_init) { -+ write_phy_reg(pi, 0xf8, 0x02d8); -+ write_phy_reg(pi, 0xf9, 0x0301); -+ write_phy_reg(pi, 0xfa, 0x02d8); -+ write_phy_reg(pi, 0xfb, 0x0301); -+ } -+ } -+} -+ -+u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val) -+{ -+ u16 curr_ctl, new_ctl; -+ bool suspended = false; -+ -+ if (D11REV_IS(pi->sh->corerev, 16)) { -+ suspended = -+ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ? -+ false : true; -+ if (!suspended) -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ } -+ -+ curr_ctl = read_phy_reg(pi, 0xb0) & (0x7 << 0); -+ -+ new_ctl = (curr_ctl & (~mask)) | (val & mask); -+ -+ mod_phy_reg(pi, 0xb0, (0x7 << 0), new_ctl); -+ -+ if (D11REV_IS(pi->sh->corerev, 16) && !suspended) -+ wlapi_enable_mac(pi->sh->physhim); -+ -+ return new_ctl; -+} -+ -+void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd) -+{ -+ u16 trigger_mask, status_mask; -+ u16 orig_RfseqCoreActv; -+ -+ switch (cmd) { -+ case NPHY_RFSEQ_RX2TX: -+ trigger_mask = NPHY_RfseqTrigger_rx2tx; -+ status_mask = NPHY_RfseqStatus_rx2tx; -+ break; -+ case NPHY_RFSEQ_TX2RX: -+ trigger_mask = NPHY_RfseqTrigger_tx2rx; -+ status_mask = NPHY_RfseqStatus_tx2rx; -+ break; -+ case NPHY_RFSEQ_RESET2RX: -+ trigger_mask = NPHY_RfseqTrigger_reset2rx; -+ status_mask = NPHY_RfseqStatus_reset2rx; -+ break; -+ case NPHY_RFSEQ_UPDATEGAINH: -+ trigger_mask = NPHY_RfseqTrigger_updategainh; -+ status_mask = NPHY_RfseqStatus_updategainh; -+ break; -+ case NPHY_RFSEQ_UPDATEGAINL: -+ trigger_mask = NPHY_RfseqTrigger_updategainl; -+ status_mask = NPHY_RfseqStatus_updategainl; -+ break; -+ case NPHY_RFSEQ_UPDATEGAINU: -+ trigger_mask = NPHY_RfseqTrigger_updategainu; -+ status_mask = NPHY_RfseqStatus_updategainu; -+ break; -+ default: -+ return; -+ } -+ -+ orig_RfseqCoreActv = read_phy_reg(pi, 0xa1); -+ or_phy_reg(pi, 0xa1, -+ (NPHY_RfseqMode_CoreActv_override | -+ NPHY_RfseqMode_Trigger_override)); -+ or_phy_reg(pi, 0xa3, trigger_mask); -+ SPINWAIT((read_phy_reg(pi, 0xa4) & status_mask), 200000); -+ write_phy_reg(pi, 0xa1, orig_RfseqCoreActv); -+ WARN(read_phy_reg(pi, 0xa4) & status_mask, "HW error in rf"); -+} -+ -+static void -+wlc_phy_rfctrl_override_1tomany_nphy(struct brcms_phy *pi, u16 cmd, u16 value, -+ u8 core_mask, u8 off) -+{ -+ u16 rfmxgain = 0, lpfgain = 0; -+ u16 tgain = 0; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ switch (cmd) { -+ case NPHY_REV7_RfctrlOverride_cmd_rxrf_pu: -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 5), -+ value, core_mask, off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 4), value, -+ core_mask, off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 3), value, -+ core_mask, off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ break; -+ case NPHY_REV7_RfctrlOverride_cmd_rx_pu: -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 2), -+ value, core_mask, off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 1), value, -+ core_mask, off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 0), value, -+ core_mask, off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 1), value, -+ core_mask, off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID2); -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 11), 0, -+ core_mask, off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ break; -+ case NPHY_REV7_RfctrlOverride_cmd_tx_pu: -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 2), -+ value, core_mask, off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 1), value, -+ core_mask, off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 0), value, -+ core_mask, off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID2); -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 2), value, -+ core_mask, off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID2); -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 11), 1, -+ core_mask, off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ break; -+ case NPHY_REV7_RfctrlOverride_cmd_rxgain: -+ rfmxgain = value & 0x000ff; -+ lpfgain = value & 0x0ff00; -+ lpfgain = lpfgain >> 8; -+ -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 11), -+ rfmxgain, core_mask, -+ off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x3 << 13), -+ lpfgain, core_mask, -+ off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ break; -+ case NPHY_REV7_RfctrlOverride_cmd_txgain: -+ tgain = value & 0x7fff; -+ lpfgain = value & 0x8000; -+ lpfgain = lpfgain >> 14; -+ -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 12), -+ tgain, core_mask, off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 13), -+ lpfgain, core_mask, -+ off, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ break; -+ } -+ } -+} -+ -+static void -+wlc_phy_scale_offset_rssi_nphy(struct brcms_phy *pi, u16 scale, s8 offset, -+ u8 coresel, u8 rail, u8 rssi_type) -+{ -+ u16 valuetostuff; -+ -+ offset = (offset > NPHY_RSSICAL_MAXREAD) ? -+ NPHY_RSSICAL_MAXREAD : offset; -+ offset = (offset < (-NPHY_RSSICAL_MAXREAD - 1)) ? -+ -NPHY_RSSICAL_MAXREAD - 1 : offset; -+ -+ valuetostuff = ((scale & 0x3f) << 8) | (offset & 0x3f); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) -+ write_phy_reg(pi, 0x1a6, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) -+ write_phy_reg(pi, 0x1ac, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) -+ write_phy_reg(pi, 0x1b2, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) -+ write_phy_reg(pi, 0x1b8, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) -+ write_phy_reg(pi, 0x1a4, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) -+ write_phy_reg(pi, 0x1aa, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) -+ write_phy_reg(pi, 0x1b0, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) -+ write_phy_reg(pi, 0x1b6, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) -+ write_phy_reg(pi, 0x1a5, valuetostuff); -+ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) -+ write_phy_reg(pi, 0x1ab, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) -+ write_phy_reg(pi, 0x1b1, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) -+ write_phy_reg(pi, 0x1b7, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) -+ write_phy_reg(pi, 0x1a7, valuetostuff); -+ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) -+ write_phy_reg(pi, 0x1ad, valuetostuff); -+ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) -+ write_phy_reg(pi, 0x1b3, valuetostuff); -+ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) -+ write_phy_reg(pi, 0x1b9, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) -+ write_phy_reg(pi, 0x1a8, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) -+ write_phy_reg(pi, 0x1ae, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) -+ write_phy_reg(pi, 0x1b4, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) -+ write_phy_reg(pi, 0x1ba, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) -+ write_phy_reg(pi, 0x1a9, valuetostuff); -+ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) -+ write_phy_reg(pi, 0x1b5, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) -+ write_phy_reg(pi, 0x1af, valuetostuff); -+ -+ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || -+ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && -+ (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) -+ write_phy_reg(pi, 0x1bb, valuetostuff); -+} -+ -+static void brcms_phy_wr_tx_mux(struct brcms_phy *pi, u8 core) -+{ -+ if (PHY_IPA(pi)) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ write_radio_reg(pi, -+ ((core == PHY_CORE_0) ? -+ RADIO_2057_TX0_TX_SSI_MUX : -+ RADIO_2057_TX1_TX_SSI_MUX), -+ (CHSPEC_IS5G(pi->radio_chanspec) ? -+ 0xc : 0xe)); -+ else -+ write_radio_reg(pi, -+ RADIO_2056_TX_TX_SSI_MUX | -+ ((core == PHY_CORE_0) ? -+ RADIO_2056_TX0 : RADIO_2056_TX1), -+ (CHSPEC_IS5G(pi->radio_chanspec) ? -+ 0xc : 0xe)); -+ } else { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ write_radio_reg(pi, -+ ((core == PHY_CORE_0) ? -+ RADIO_2057_TX0_TX_SSI_MUX : -+ RADIO_2057_TX1_TX_SSI_MUX), -+ 0x11); -+ -+ if (pi->pubpi.radioid == BCM2057_ID) -+ write_radio_reg(pi, -+ RADIO_2057_IQTEST_SEL_PU, 0x1); -+ -+ } else { -+ write_radio_reg(pi, -+ RADIO_2056_TX_TX_SSI_MUX | -+ ((core == PHY_CORE_0) ? -+ RADIO_2056_TX0 : RADIO_2056_TX1), -+ 0x11); -+ } -+ } -+} -+ -+void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type) -+{ -+ u16 mask, val; -+ u16 afectrlovr_rssi_val, rfctrlcmd_rxen_val, rfctrlcmd_coresel_val, -+ startseq; -+ u16 rfctrlovr_rssi_val, rfctrlovr_rxen_val, rfctrlovr_coresel_val, -+ rfctrlovr_trigger_val; -+ u16 afectrlovr_rssi_mask, rfctrlcmd_mask, rfctrlovr_mask; -+ u16 rfctrlcmd_val, rfctrlovr_val; -+ u8 core; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ if (core_code == RADIO_MIMO_CORESEL_OFF) { -+ mod_phy_reg(pi, 0x8f, (0x1 << 9), 0); -+ mod_phy_reg(pi, 0xa5, (0x1 << 9), 0); -+ -+ mod_phy_reg(pi, 0xa6, (0x3 << 8), 0); -+ mod_phy_reg(pi, 0xa7, (0x3 << 8), 0); -+ -+ mod_phy_reg(pi, 0xe5, (0x1 << 5), 0); -+ mod_phy_reg(pi, 0xe6, (0x1 << 5), 0); -+ -+ mask = (0x1 << 2) | -+ (0x1 << 3) | (0x1 << 4) | (0x1 << 5); -+ mod_phy_reg(pi, 0xf9, mask, 0); -+ mod_phy_reg(pi, 0xfb, mask, 0); -+ -+ } else { -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ if (core_code == RADIO_MIMO_CORESEL_CORE1 -+ && core == PHY_CORE_1) -+ continue; -+ else if (core_code == RADIO_MIMO_CORESEL_CORE2 -+ && core == PHY_CORE_0) -+ continue; -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? -+ 0x8f : 0xa5, (0x1 << 9), 1 << 9); -+ -+ if (rssi_type == NPHY_RSSI_SEL_W1 || -+ rssi_type == NPHY_RSSI_SEL_W2 || -+ rssi_type == NPHY_RSSI_SEL_NB) { -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0xa6 : 0xa7, -+ (0x3 << 8), 0); -+ -+ mask = (0x1 << 2) | -+ (0x1 << 3) | -+ (0x1 << 4) | (0x1 << 5); -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0xf9 : 0xfb, -+ mask, 0); -+ -+ if (rssi_type == NPHY_RSSI_SEL_W1) { -+ if (CHSPEC_IS5G( -+ pi->radio_chanspec)) { -+ mask = (0x1 << 2); -+ val = 1 << 2; -+ } else { -+ mask = (0x1 << 3); -+ val = 1 << 3; -+ } -+ } else if (rssi_type == -+ NPHY_RSSI_SEL_W2) { -+ mask = (0x1 << 4); -+ val = 1 << 4; -+ } else { -+ mask = (0x1 << 5); -+ val = 1 << 5; -+ } -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0xf9 : 0xfb, -+ mask, val); -+ -+ mask = (0x1 << 5); -+ val = 1 << 5; -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? -+ 0xe5 : 0xe6, mask, val); -+ } else { -+ if (rssi_type == NPHY_RSSI_SEL_TBD) { -+ mask = (0x3 << 8); -+ val = 1 << 8; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0xa6 -+ : 0xa7, mask, val); -+ mask = (0x3 << 10); -+ val = 1 << 10; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0xa6 -+ : 0xa7, mask, val); -+ } else if (rssi_type == -+ NPHY_RSSI_SEL_IQ) { -+ mask = (0x3 << 8); -+ val = 2 << 8; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0xa6 -+ : 0xa7, mask, val); -+ mask = (0x3 << 10); -+ val = 2 << 10; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0xa6 -+ : 0xa7, mask, val); -+ } else { -+ mask = (0x3 << 8); -+ val = 3 << 8; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0xa6 -+ : 0xa7, mask, val); -+ mask = (0x3 << 10); -+ val = 3 << 10; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0xa6 -+ : 0xa7, mask, val); -+ brcms_phy_wr_tx_mux(pi, core); -+ afectrlovr_rssi_val = 1 << 9; -+ mod_phy_reg(pi, -+ (core == -+ PHY_CORE_0) ? 0x8f -+ : 0xa5, (0x1 << 9), -+ afectrlovr_rssi_val); -+ } -+ } -+ } -+ } -+ } else { -+ -+ if ((rssi_type == NPHY_RSSI_SEL_W1) || -+ (rssi_type == NPHY_RSSI_SEL_W2) || -+ (rssi_type == NPHY_RSSI_SEL_NB)) -+ val = 0x0; -+ else if (rssi_type == NPHY_RSSI_SEL_TBD) -+ val = 0x1; -+ else if (rssi_type == NPHY_RSSI_SEL_IQ) -+ val = 0x2; -+ else -+ val = 0x3; -+ -+ mask = ((0x3 << 12) | (0x3 << 14)); -+ val = (val << 12) | (val << 14); -+ mod_phy_reg(pi, 0xa6, mask, val); -+ mod_phy_reg(pi, 0xa7, mask, val); -+ -+ if ((rssi_type == NPHY_RSSI_SEL_W1) || -+ (rssi_type == NPHY_RSSI_SEL_W2) || -+ (rssi_type == NPHY_RSSI_SEL_NB)) { -+ if (rssi_type == NPHY_RSSI_SEL_W1) -+ val = 0x1; -+ if (rssi_type == NPHY_RSSI_SEL_W2) -+ val = 0x2; -+ if (rssi_type == NPHY_RSSI_SEL_NB) -+ val = 0x3; -+ -+ mask = (0x3 << 4); -+ val = (val << 4); -+ mod_phy_reg(pi, 0x7a, mask, val); -+ mod_phy_reg(pi, 0x7d, mask, val); -+ } -+ -+ if (core_code == RADIO_MIMO_CORESEL_OFF) { -+ afectrlovr_rssi_val = 0; -+ rfctrlcmd_rxen_val = 0; -+ rfctrlcmd_coresel_val = 0; -+ rfctrlovr_rssi_val = 0; -+ rfctrlovr_rxen_val = 0; -+ rfctrlovr_coresel_val = 0; -+ rfctrlovr_trigger_val = 0; -+ startseq = 0; -+ } else { -+ afectrlovr_rssi_val = 1; -+ rfctrlcmd_rxen_val = 1; -+ rfctrlcmd_coresel_val = core_code; -+ rfctrlovr_rssi_val = 1; -+ rfctrlovr_rxen_val = 1; -+ rfctrlovr_coresel_val = 1; -+ rfctrlovr_trigger_val = 1; -+ startseq = 1; -+ } -+ -+ afectrlovr_rssi_mask = ((0x1 << 12) | (0x1 << 13)); -+ afectrlovr_rssi_val = (afectrlovr_rssi_val << -+ 12) | (afectrlovr_rssi_val << 13); -+ mod_phy_reg(pi, 0xa5, afectrlovr_rssi_mask, -+ afectrlovr_rssi_val); -+ -+ if ((rssi_type == NPHY_RSSI_SEL_W1) || -+ (rssi_type == NPHY_RSSI_SEL_W2) || -+ (rssi_type == NPHY_RSSI_SEL_NB)) { -+ rfctrlcmd_mask = ((0x1 << 8) | (0x7 << 3)); -+ rfctrlcmd_val = (rfctrlcmd_rxen_val << 8) | -+ (rfctrlcmd_coresel_val << 3); -+ -+ rfctrlovr_mask = ((0x1 << 5) | -+ (0x1 << 12) | -+ (0x1 << 1) | (0x1 << 0)); -+ rfctrlovr_val = (rfctrlovr_rssi_val << -+ 5) | -+ (rfctrlovr_rxen_val << 12) | -+ (rfctrlovr_coresel_val << 1) | -+ (rfctrlovr_trigger_val << 0); -+ -+ mod_phy_reg(pi, 0x78, rfctrlcmd_mask, rfctrlcmd_val); -+ mod_phy_reg(pi, 0xec, rfctrlovr_mask, rfctrlovr_val); -+ -+ mod_phy_reg(pi, 0x78, (0x1 << 0), (startseq << 0)); -+ udelay(20); -+ -+ mod_phy_reg(pi, 0xec, (0x1 << 0), 0); -+ } -+ } -+} -+ -+int -+wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, s32 *rssi_buf, -+ u8 nsamps) -+{ -+ s16 rssi0, rssi1; -+ u16 afectrlCore1_save = 0; -+ u16 afectrlCore2_save = 0; -+ u16 afectrlOverride1_save = 0; -+ u16 afectrlOverride2_save = 0; -+ u16 rfctrlOverrideAux0_save = 0; -+ u16 rfctrlOverrideAux1_save = 0; -+ u16 rfctrlMiscReg1_save = 0; -+ u16 rfctrlMiscReg2_save = 0; -+ u16 rfctrlcmd_save = 0; -+ u16 rfctrloverride_save = 0; -+ u16 rfctrlrssiothers1_save = 0; -+ u16 rfctrlrssiothers2_save = 0; -+ s8 tmp_buf[4]; -+ u8 ctr = 0, samp = 0; -+ s32 rssi_out_val; -+ u16 gpiosel_orig; -+ -+ afectrlCore1_save = read_phy_reg(pi, 0xa6); -+ afectrlCore2_save = read_phy_reg(pi, 0xa7); -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ rfctrlMiscReg1_save = read_phy_reg(pi, 0xf9); -+ rfctrlMiscReg2_save = read_phy_reg(pi, 0xfb); -+ afectrlOverride1_save = read_phy_reg(pi, 0x8f); -+ afectrlOverride2_save = read_phy_reg(pi, 0xa5); -+ rfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5); -+ rfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6); -+ } else { -+ afectrlOverride1_save = read_phy_reg(pi, 0xa5); -+ rfctrlcmd_save = read_phy_reg(pi, 0x78); -+ rfctrloverride_save = read_phy_reg(pi, 0xec); -+ rfctrlrssiothers1_save = read_phy_reg(pi, 0x7a); -+ rfctrlrssiothers2_save = read_phy_reg(pi, 0x7d); -+ } -+ -+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type); -+ -+ gpiosel_orig = read_phy_reg(pi, 0xca); -+ if (NREV_LT(pi->pubpi.phy_rev, 2)) -+ write_phy_reg(pi, 0xca, 5); -+ -+ for (ctr = 0; ctr < 4; ctr++) -+ rssi_buf[ctr] = 0; -+ -+ for (samp = 0; samp < nsamps; samp++) { -+ if (NREV_LT(pi->pubpi.phy_rev, 2)) { -+ rssi0 = read_phy_reg(pi, 0x1c9); -+ rssi1 = read_phy_reg(pi, 0x1ca); -+ } else { -+ rssi0 = read_phy_reg(pi, 0x219); -+ rssi1 = read_phy_reg(pi, 0x21a); -+ } -+ -+ ctr = 0; -+ tmp_buf[ctr++] = ((s8) ((rssi0 & 0x3f) << 2)) >> 2; -+ tmp_buf[ctr++] = ((s8) (((rssi0 >> 8) & 0x3f) << 2)) >> 2; -+ tmp_buf[ctr++] = ((s8) ((rssi1 & 0x3f) << 2)) >> 2; -+ tmp_buf[ctr++] = ((s8) (((rssi1 >> 8) & 0x3f) << 2)) >> 2; -+ -+ for (ctr = 0; ctr < 4; ctr++) -+ rssi_buf[ctr] += tmp_buf[ctr]; -+ -+ } -+ -+ rssi_out_val = rssi_buf[3] & 0xff; -+ rssi_out_val |= (rssi_buf[2] & 0xff) << 8; -+ rssi_out_val |= (rssi_buf[1] & 0xff) << 16; -+ rssi_out_val |= (rssi_buf[0] & 0xff) << 24; -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 2)) -+ write_phy_reg(pi, 0xca, gpiosel_orig); -+ -+ write_phy_reg(pi, 0xa6, afectrlCore1_save); -+ write_phy_reg(pi, 0xa7, afectrlCore2_save); -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ write_phy_reg(pi, 0xf9, rfctrlMiscReg1_save); -+ write_phy_reg(pi, 0xfb, rfctrlMiscReg2_save); -+ write_phy_reg(pi, 0x8f, afectrlOverride1_save); -+ write_phy_reg(pi, 0xa5, afectrlOverride2_save); -+ write_phy_reg(pi, 0xe5, rfctrlOverrideAux0_save); -+ write_phy_reg(pi, 0xe6, rfctrlOverrideAux1_save); -+ } else { -+ write_phy_reg(pi, 0xa5, afectrlOverride1_save); -+ write_phy_reg(pi, 0x78, rfctrlcmd_save); -+ write_phy_reg(pi, 0xec, rfctrloverride_save); -+ write_phy_reg(pi, 0x7a, rfctrlrssiothers1_save); -+ write_phy_reg(pi, 0x7d, rfctrlrssiothers2_save); -+ } -+ -+ return rssi_out_val; -+} -+ -+s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi) -+{ -+ u16 core1_txrf_iqcal1_save, core1_txrf_iqcal2_save; -+ u16 core2_txrf_iqcal1_save, core2_txrf_iqcal2_save; -+ u16 pwrdet_rxtx_core1_save; -+ u16 pwrdet_rxtx_core2_save; -+ u16 afectrlCore1_save; -+ u16 afectrlCore2_save; -+ u16 afectrlOverride_save; -+ u16 afectrlOverride2_save; -+ u16 pd_pll_ts_save; -+ u16 gpioSel_save; -+ s32 radio_temp[4]; -+ s32 radio_temp2[4]; -+ u16 syn_tempprocsense_save; -+ s16 offset = 0; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ u16 auxADC_Vmid, auxADC_Av, auxADC_Vmid_save, auxADC_Av_save; -+ u16 auxADC_rssi_ctrlL_save, auxADC_rssi_ctrlH_save; -+ u16 auxADC_rssi_ctrlL, auxADC_rssi_ctrlH; -+ s32 auxADC_Vl; -+ u16 RfctrlOverride5_save, RfctrlOverride6_save; -+ u16 RfctrlMiscReg5_save, RfctrlMiscReg6_save; -+ u16 RSSIMultCoef0QPowerDet_save; -+ u16 tempsense_Rcal; -+ -+ syn_tempprocsense_save = -+ read_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG); -+ -+ afectrlCore1_save = read_phy_reg(pi, 0xa6); -+ afectrlCore2_save = read_phy_reg(pi, 0xa7); -+ afectrlOverride_save = read_phy_reg(pi, 0x8f); -+ afectrlOverride2_save = read_phy_reg(pi, 0xa5); -+ RSSIMultCoef0QPowerDet_save = read_phy_reg(pi, 0x1ae); -+ RfctrlOverride5_save = read_phy_reg(pi, 0x346); -+ RfctrlOverride6_save = read_phy_reg(pi, 0x347); -+ RfctrlMiscReg5_save = read_phy_reg(pi, 0x344); -+ RfctrlMiscReg6_save = read_phy_reg(pi, 0x345); -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16, -+ &auxADC_Vmid_save); -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16, -+ &auxADC_Av_save); -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16, -+ &auxADC_rssi_ctrlL_save); -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16, -+ &auxADC_rssi_ctrlH_save); -+ -+ write_phy_reg(pi, 0x1ae, 0x0); -+ -+ auxADC_rssi_ctrlL = 0x0; -+ auxADC_rssi_ctrlH = 0x20; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16, -+ &auxADC_rssi_ctrlL); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16, -+ &auxADC_rssi_ctrlH); -+ -+ tempsense_Rcal = syn_tempprocsense_save & 0x1c; -+ -+ write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, -+ tempsense_Rcal | 0x01); -+ -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), -+ 1, 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID2); -+ mod_phy_reg(pi, 0xa6, (0x1 << 7), 0); -+ mod_phy_reg(pi, 0xa7, (0x1 << 7), 0); -+ mod_phy_reg(pi, 0x8f, (0x1 << 7), (0x1 << 7)); -+ mod_phy_reg(pi, 0xa5, (0x1 << 7), (0x1 << 7)); -+ -+ mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2)); -+ mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2)); -+ mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2)); -+ mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2)); -+ udelay(5); -+ mod_phy_reg(pi, 0xa6, (0x1 << 2), 0); -+ mod_phy_reg(pi, 0xa7, (0x1 << 2), 0); -+ mod_phy_reg(pi, 0xa6, (0x1 << 3), 0); -+ mod_phy_reg(pi, 0xa7, (0x1 << 3), 0); -+ mod_phy_reg(pi, 0x8f, (0x1 << 3), (0x1 << 3)); -+ mod_phy_reg(pi, 0xa5, (0x1 << 3), (0x1 << 3)); -+ mod_phy_reg(pi, 0xa6, (0x1 << 6), 0); -+ mod_phy_reg(pi, 0xa7, (0x1 << 6), 0); -+ mod_phy_reg(pi, 0x8f, (0x1 << 6), (0x1 << 6)); -+ mod_phy_reg(pi, 0xa5, (0x1 << 6), (0x1 << 6)); -+ -+ auxADC_Vmid = 0xA3; -+ auxADC_Av = 0x0; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16, -+ &auxADC_Vmid); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16, -+ &auxADC_Av); -+ -+ udelay(3); -+ -+ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1); -+ write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, -+ tempsense_Rcal | 0x03); -+ -+ udelay(5); -+ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1); -+ -+ auxADC_Av = 0x7; -+ if (radio_temp[1] + radio_temp2[1] < -30) { -+ auxADC_Vmid = 0x45; -+ auxADC_Vl = 263; -+ } else if (radio_temp[1] + radio_temp2[1] < -9) { -+ auxADC_Vmid = 0x200; -+ auxADC_Vl = 467; -+ } else if (radio_temp[1] + radio_temp2[1] < 11) { -+ auxADC_Vmid = 0x266; -+ auxADC_Vl = 634; -+ } else { -+ auxADC_Vmid = 0x2D5; -+ auxADC_Vl = 816; -+ } -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16, -+ &auxADC_Vmid); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16, -+ &auxADC_Av); -+ -+ udelay(3); -+ -+ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1); -+ write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, -+ tempsense_Rcal | 0x01); -+ -+ udelay(5); -+ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1); -+ -+ write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, -+ syn_tempprocsense_save); -+ -+ write_phy_reg(pi, 0xa6, afectrlCore1_save); -+ write_phy_reg(pi, 0xa7, afectrlCore2_save); -+ write_phy_reg(pi, 0x8f, afectrlOverride_save); -+ write_phy_reg(pi, 0xa5, afectrlOverride2_save); -+ write_phy_reg(pi, 0x1ae, RSSIMultCoef0QPowerDet_save); -+ write_phy_reg(pi, 0x346, RfctrlOverride5_save); -+ write_phy_reg(pi, 0x347, RfctrlOverride6_save); -+ write_phy_reg(pi, 0x344, RfctrlMiscReg5_save); -+ write_phy_reg(pi, 0x345, RfctrlMiscReg5_save); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16, -+ &auxADC_Vmid_save); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16, -+ &auxADC_Av_save); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16, -+ &auxADC_rssi_ctrlL_save); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16, -+ &auxADC_rssi_ctrlH_save); -+ -+ radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1]) -+ + 82 * (auxADC_Vl) - 28861 + -+ 128) / 256; -+ -+ offset = (s16) pi->phy_tempsense_offset; -+ -+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ syn_tempprocsense_save = -+ read_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE); -+ -+ afectrlCore1_save = read_phy_reg(pi, 0xa6); -+ afectrlCore2_save = read_phy_reg(pi, 0xa7); -+ afectrlOverride_save = read_phy_reg(pi, 0x8f); -+ afectrlOverride2_save = read_phy_reg(pi, 0xa5); -+ gpioSel_save = read_phy_reg(pi, 0xca); -+ -+ write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01); -+ -+ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1); -+ if (NREV_LT(pi->pubpi.phy_rev, 7)) -+ write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x05); -+ -+ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1); -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x01); -+ else -+ write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01); -+ -+ radio_temp[0] = -+ (126 * (radio_temp[1] + radio_temp2[1]) + 3987) / 64; -+ -+ write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, -+ syn_tempprocsense_save); -+ -+ write_phy_reg(pi, 0xca, gpioSel_save); -+ write_phy_reg(pi, 0xa6, afectrlCore1_save); -+ write_phy_reg(pi, 0xa7, afectrlCore2_save); -+ write_phy_reg(pi, 0x8f, afectrlOverride_save); -+ write_phy_reg(pi, 0xa5, afectrlOverride2_save); -+ -+ offset = (s16) pi->phy_tempsense_offset; -+ } else { -+ -+ pwrdet_rxtx_core1_save = -+ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1); -+ pwrdet_rxtx_core2_save = -+ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2); -+ core1_txrf_iqcal1_save = -+ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1); -+ core1_txrf_iqcal2_save = -+ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2); -+ core2_txrf_iqcal1_save = -+ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1); -+ core2_txrf_iqcal2_save = -+ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2); -+ pd_pll_ts_save = read_radio_reg(pi, RADIO_2055_PD_PLL_TS); -+ -+ afectrlCore1_save = read_phy_reg(pi, 0xa6); -+ afectrlCore2_save = read_phy_reg(pi, 0xa7); -+ afectrlOverride_save = read_phy_reg(pi, 0xa5); -+ gpioSel_save = read_phy_reg(pi, 0xca); -+ -+ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x01); -+ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x01); -+ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x08); -+ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x08); -+ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04); -+ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04); -+ write_radio_reg(pi, RADIO_2055_PD_PLL_TS, 0x00); -+ -+ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1); -+ xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80); -+ -+ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1); -+ xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80); -+ -+ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1); -+ xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80); -+ -+ radio_temp[0] = (radio_temp[0] + radio_temp2[0]); -+ radio_temp[1] = (radio_temp[1] + radio_temp2[1]); -+ radio_temp[2] = (radio_temp[2] + radio_temp2[2]); -+ radio_temp[3] = (radio_temp[3] + radio_temp2[3]); -+ -+ radio_temp[0] = -+ (radio_temp[0] + radio_temp[1] + radio_temp[2] + -+ radio_temp[3]); -+ -+ radio_temp[0] = -+ (radio_temp[0] + -+ (8 * 32)) * (950 - 350) / 63 + (350 * 8); -+ -+ radio_temp[0] = (radio_temp[0] - (8 * 420)) / 38; -+ -+ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, -+ pwrdet_rxtx_core1_save); -+ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, -+ pwrdet_rxtx_core2_save); -+ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, -+ core1_txrf_iqcal1_save); -+ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, -+ core2_txrf_iqcal1_save); -+ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, -+ core1_txrf_iqcal2_save); -+ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, -+ core2_txrf_iqcal2_save); -+ write_radio_reg(pi, RADIO_2055_PD_PLL_TS, pd_pll_ts_save); -+ -+ write_phy_reg(pi, 0xca, gpioSel_save); -+ write_phy_reg(pi, 0xa6, afectrlCore1_save); -+ write_phy_reg(pi, 0xa7, afectrlCore2_save); -+ write_phy_reg(pi, 0xa5, afectrlOverride_save); -+ } -+ -+ return (s16) radio_temp[0] + offset; -+} -+ -+static void -+wlc_phy_set_rssi_2055_vcm(struct brcms_phy *pi, u8 rssi_type, u8 *vcm_buf) -+{ -+ u8 core; -+ -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ if (rssi_type == NPHY_RSSI_SEL_NB) { -+ if (core == PHY_CORE_0) { -+ mod_radio_reg(pi, -+ RADIO_2055_CORE1_B0_NBRSSI_VCM, -+ RADIO_2055_NBRSSI_VCM_I_MASK, -+ vcm_buf[2 * -+ core] << -+ RADIO_2055_NBRSSI_VCM_I_SHIFT); -+ mod_radio_reg(pi, -+ RADIO_2055_CORE1_RXBB_RSSI_CTRL5, -+ RADIO_2055_NBRSSI_VCM_Q_MASK, -+ vcm_buf[2 * core + -+ 1] << -+ RADIO_2055_NBRSSI_VCM_Q_SHIFT); -+ } else { -+ mod_radio_reg(pi, -+ RADIO_2055_CORE2_B0_NBRSSI_VCM, -+ RADIO_2055_NBRSSI_VCM_I_MASK, -+ vcm_buf[2 * -+ core] << -+ RADIO_2055_NBRSSI_VCM_I_SHIFT); -+ mod_radio_reg(pi, -+ RADIO_2055_CORE2_RXBB_RSSI_CTRL5, -+ RADIO_2055_NBRSSI_VCM_Q_MASK, -+ vcm_buf[2 * core + -+ 1] << -+ RADIO_2055_NBRSSI_VCM_Q_SHIFT); -+ } -+ } else { -+ if (core == PHY_CORE_0) -+ mod_radio_reg(pi, -+ RADIO_2055_CORE1_RXBB_RSSI_CTRL5, -+ RADIO_2055_WBRSSI_VCM_IQ_MASK, -+ vcm_buf[2 * -+ core] << -+ RADIO_2055_WBRSSI_VCM_IQ_SHIFT); -+ else -+ mod_radio_reg(pi, -+ RADIO_2055_CORE2_RXBB_RSSI_CTRL5, -+ RADIO_2055_WBRSSI_VCM_IQ_MASK, -+ vcm_buf[2 * -+ core] << -+ RADIO_2055_WBRSSI_VCM_IQ_SHIFT); -+ } -+ } -+} -+ -+static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi) -+{ -+ u16 classif_state; -+ u16 clip_state[2]; -+ u16 clip_off[] = { 0xffff, 0xffff }; -+ s32 target_code; -+ u8 vcm, min_vcm; -+ u8 vcm_final = 0; -+ u8 result_idx; -+ s32 poll_results[8][4] = { -+ {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} -+ }; -+ s32 poll_result_core[4] = { 0, 0, 0, 0 }; -+ s32 min_d = NPHY_RSSICAL_MAXD, curr_d; -+ s32 fine_digital_offset[4]; -+ s32 poll_results_min[4] = { 0, 0, 0, 0 }; -+ s32 min_poll; -+ u8 vcm_level_max; -+ u8 core; -+ u8 wb_cnt; -+ u8 rssi_type; -+ u16 NPHY_Rfctrlintc1_save, NPHY_Rfctrlintc2_save; -+ u16 NPHY_AfectrlOverride1_save, NPHY_AfectrlOverride2_save; -+ u16 NPHY_AfectrlCore1_save, NPHY_AfectrlCore2_save; -+ u16 NPHY_RfctrlOverride0_save, NPHY_RfctrlOverride1_save; -+ u16 NPHY_RfctrlOverrideAux0_save, NPHY_RfctrlOverrideAux1_save; -+ u16 NPHY_RfctrlCmd_save; -+ u16 NPHY_RfctrlMiscReg1_save, NPHY_RfctrlMiscReg2_save; -+ u16 NPHY_RfctrlRSSIOTHERS1_save, NPHY_RfctrlRSSIOTHERS2_save; -+ u8 rxcore_state; -+ u16 NPHY_REV7_RfctrlOverride3_save, NPHY_REV7_RfctrlOverride4_save; -+ u16 NPHY_REV7_RfctrlOverride5_save, NPHY_REV7_RfctrlOverride6_save; -+ u16 NPHY_REV7_RfctrlMiscReg3_save, NPHY_REV7_RfctrlMiscReg4_save; -+ u16 NPHY_REV7_RfctrlMiscReg5_save, NPHY_REV7_RfctrlMiscReg6_save; -+ -+ NPHY_REV7_RfctrlOverride3_save = -+ NPHY_REV7_RfctrlOverride4_save = -+ NPHY_REV7_RfctrlOverride5_save = -+ NPHY_REV7_RfctrlOverride6_save = -+ NPHY_REV7_RfctrlMiscReg3_save = -+ NPHY_REV7_RfctrlMiscReg4_save = -+ NPHY_REV7_RfctrlMiscReg5_save = -+ NPHY_REV7_RfctrlMiscReg6_save = 0; -+ -+ classif_state = wlc_phy_classifier_nphy(pi, 0, 0); -+ wlc_phy_classifier_nphy(pi, (0x7 << 0), 4); -+ wlc_phy_clip_det_nphy(pi, 0, clip_state); -+ wlc_phy_clip_det_nphy(pi, 1, clip_off); -+ -+ NPHY_Rfctrlintc1_save = read_phy_reg(pi, 0x91); -+ NPHY_Rfctrlintc2_save = read_phy_reg(pi, 0x92); -+ NPHY_AfectrlOverride1_save = read_phy_reg(pi, 0x8f); -+ NPHY_AfectrlOverride2_save = read_phy_reg(pi, 0xa5); -+ NPHY_AfectrlCore1_save = read_phy_reg(pi, 0xa6); -+ NPHY_AfectrlCore2_save = read_phy_reg(pi, 0xa7); -+ NPHY_RfctrlOverride0_save = read_phy_reg(pi, 0xe7); -+ NPHY_RfctrlOverride1_save = read_phy_reg(pi, 0xec); -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ NPHY_REV7_RfctrlOverride3_save = read_phy_reg(pi, 0x342); -+ NPHY_REV7_RfctrlOverride4_save = read_phy_reg(pi, 0x343); -+ NPHY_REV7_RfctrlOverride5_save = read_phy_reg(pi, 0x346); -+ NPHY_REV7_RfctrlOverride6_save = read_phy_reg(pi, 0x347); -+ } -+ NPHY_RfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5); -+ NPHY_RfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6); -+ NPHY_RfctrlCmd_save = read_phy_reg(pi, 0x78); -+ NPHY_RfctrlMiscReg1_save = read_phy_reg(pi, 0xf9); -+ NPHY_RfctrlMiscReg2_save = read_phy_reg(pi, 0xfb); -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ NPHY_REV7_RfctrlMiscReg3_save = read_phy_reg(pi, 0x340); -+ NPHY_REV7_RfctrlMiscReg4_save = read_phy_reg(pi, 0x341); -+ NPHY_REV7_RfctrlMiscReg5_save = read_phy_reg(pi, 0x344); -+ NPHY_REV7_RfctrlMiscReg6_save = read_phy_reg(pi, 0x345); -+ } -+ NPHY_RfctrlRSSIOTHERS1_save = read_phy_reg(pi, 0x7a); -+ NPHY_RfctrlRSSIOTHERS2_save = read_phy_reg(pi, 0x7d); -+ -+ wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_OFF, 0, -+ RADIO_MIMO_CORESEL_ALLRXTX); -+ wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_TRSW, 1, -+ RADIO_MIMO_CORESEL_ALLRXTX); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ wlc_phy_rfctrl_override_1tomany_nphy( -+ pi, -+ NPHY_REV7_RfctrlOverride_cmd_rxrf_pu, -+ 0, 0, 0); -+ else -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0, 0); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ wlc_phy_rfctrl_override_1tomany_nphy( -+ pi, -+ NPHY_REV7_RfctrlOverride_cmd_rx_pu, -+ 1, 0, 0); -+ else -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0, 0); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), -+ 1, 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 6), 1, 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ } else { -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 7), 1, 0, 0); -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 6), 1, 0, 0); -+ } -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 5), -+ 0, 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 4), 1, 0, -+ 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ } else { -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 0, 0, 0); -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 1, 0, 0); -+ } -+ -+ } else { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 4), -+ 0, 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 5), 1, 0, -+ 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ } else { -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 0, 0, 0); -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 1, 0, 0); -+ } -+ } -+ -+ rxcore_state = wlc_phy_rxcore_getstate_nphy( -+ (struct brcms_phy_pub *) pi); -+ -+ vcm_level_max = 8; -+ -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ -+ if ((rxcore_state & (1 << core)) == 0) -+ continue; -+ -+ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, -+ core == -+ PHY_CORE_0 ? -+ RADIO_MIMO_CORESEL_CORE1 : -+ RADIO_MIMO_CORESEL_CORE2, -+ NPHY_RAIL_I, NPHY_RSSI_SEL_NB); -+ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, -+ core == -+ PHY_CORE_0 ? -+ RADIO_MIMO_CORESEL_CORE1 : -+ RADIO_MIMO_CORESEL_CORE2, -+ NPHY_RAIL_Q, NPHY_RSSI_SEL_NB); -+ -+ for (vcm = 0; vcm < vcm_level_max; vcm++) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ mod_radio_reg(pi, (core == PHY_CORE_0) ? -+ RADIO_2057_NB_MASTER_CORE0 : -+ RADIO_2057_NB_MASTER_CORE1, -+ RADIO_2057_VCM_MASK, vcm); -+ else -+ mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC | -+ ((core == -+ PHY_CORE_0) ? RADIO_2056_RX0 : -+ RADIO_2056_RX1), -+ RADIO_2056_VCM_MASK, -+ vcm << RADIO_2056_RSSI_VCM_SHIFT); -+ -+ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_NB, -+ &poll_results[vcm][0], -+ NPHY_RSSICAL_NPOLL); -+ } -+ -+ for (result_idx = 0; result_idx < 4; result_idx++) { -+ if ((core == result_idx / 2) && -+ (result_idx % 2 == 0)) { -+ -+ min_d = NPHY_RSSICAL_MAXD; -+ min_vcm = 0; -+ min_poll = -+ NPHY_RSSICAL_MAXREAD * -+ NPHY_RSSICAL_NPOLL + 1; -+ for (vcm = 0; vcm < vcm_level_max; vcm++) { -+ curr_d = -+ poll_results[vcm][result_idx] * -+ poll_results[vcm][result_idx] + -+ poll_results[vcm][result_idx + -+ 1] * -+ poll_results[vcm][result_idx + -+ 1]; -+ if (curr_d < min_d) { -+ min_d = curr_d; -+ min_vcm = vcm; -+ } -+ if (poll_results[vcm][result_idx] < -+ min_poll) -+ min_poll = -+ poll_results[vcm] -+ [result_idx]; -+ } -+ vcm_final = min_vcm; -+ poll_results_min[result_idx] = min_poll; -+ } -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ mod_radio_reg(pi, (core == PHY_CORE_0) ? -+ RADIO_2057_NB_MASTER_CORE0 : -+ RADIO_2057_NB_MASTER_CORE1, -+ RADIO_2057_VCM_MASK, vcm_final); -+ else -+ mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC | -+ ((core == -+ PHY_CORE_0) ? RADIO_2056_RX0 : -+ RADIO_2056_RX1), RADIO_2056_VCM_MASK, -+ vcm_final << RADIO_2056_RSSI_VCM_SHIFT); -+ -+ for (result_idx = 0; result_idx < 4; result_idx++) { -+ if (core == result_idx / 2) { -+ fine_digital_offset[result_idx] = -+ (NPHY_RSSICAL_NB_TARGET * -+ NPHY_RSSICAL_NPOLL) - -+ poll_results[vcm_final][result_idx]; -+ if (fine_digital_offset[result_idx] < 0) { -+ fine_digital_offset[result_idx] = -+ abs(fine_digital_offset -+ [result_idx]); -+ fine_digital_offset[result_idx] += -+ (NPHY_RSSICAL_NPOLL / 2); -+ fine_digital_offset[result_idx] /= -+ NPHY_RSSICAL_NPOLL; -+ fine_digital_offset[result_idx] = -+ -fine_digital_offset[ -+ result_idx]; -+ } else { -+ fine_digital_offset[result_idx] += -+ (NPHY_RSSICAL_NPOLL / 2); -+ fine_digital_offset[result_idx] /= -+ NPHY_RSSICAL_NPOLL; -+ } -+ -+ if (poll_results_min[result_idx] == -+ NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) -+ fine_digital_offset[result_idx] = -+ (NPHY_RSSICAL_NB_TARGET - -+ NPHY_RSSICAL_MAXREAD - 1); -+ -+ wlc_phy_scale_offset_rssi_nphy( -+ pi, 0x0, -+ (s8) -+ fine_digital_offset -+ [result_idx], -+ (result_idx / 2 == 0) ? -+ RADIO_MIMO_CORESEL_CORE1 : -+ RADIO_MIMO_CORESEL_CORE2, -+ (result_idx % 2 == 0) ? -+ NPHY_RAIL_I : NPHY_RAIL_Q, -+ NPHY_RSSI_SEL_NB); -+ } -+ } -+ -+ } -+ -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ -+ if ((rxcore_state & (1 << core)) == 0) -+ continue; -+ -+ for (wb_cnt = 0; wb_cnt < 2; wb_cnt++) { -+ if (wb_cnt == 0) { -+ rssi_type = NPHY_RSSI_SEL_W1; -+ target_code = NPHY_RSSICAL_W1_TARGET_REV3; -+ } else { -+ rssi_type = NPHY_RSSI_SEL_W2; -+ target_code = NPHY_RSSICAL_W2_TARGET_REV3; -+ } -+ -+ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, -+ core == -+ PHY_CORE_0 ? -+ RADIO_MIMO_CORESEL_CORE1 -+ : -+ RADIO_MIMO_CORESEL_CORE2, -+ NPHY_RAIL_I, rssi_type); -+ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, -+ core == -+ PHY_CORE_0 ? -+ RADIO_MIMO_CORESEL_CORE1 -+ : -+ RADIO_MIMO_CORESEL_CORE2, -+ NPHY_RAIL_Q, rssi_type); -+ -+ wlc_phy_poll_rssi_nphy(pi, rssi_type, poll_result_core, -+ NPHY_RSSICAL_NPOLL); -+ -+ for (result_idx = 0; result_idx < 4; result_idx++) { -+ if (core == result_idx / 2) { -+ fine_digital_offset[result_idx] = -+ (target_code * -+ NPHY_RSSICAL_NPOLL) - -+ poll_result_core[result_idx]; -+ if (fine_digital_offset[result_idx] < -+ 0) { -+ fine_digital_offset[result_idx] -+ = abs( -+ fine_digital_offset -+ [result_idx]); -+ fine_digital_offset[result_idx] -+ += (NPHY_RSSICAL_NPOLL -+ / 2); -+ fine_digital_offset[result_idx] -+ /= NPHY_RSSICAL_NPOLL; -+ fine_digital_offset[result_idx] -+ = -fine_digital_offset -+ [result_idx]; -+ } else { -+ fine_digital_offset[result_idx] -+ += (NPHY_RSSICAL_NPOLL -+ / 2); -+ fine_digital_offset[result_idx] -+ /= NPHY_RSSICAL_NPOLL; -+ } -+ -+ wlc_phy_scale_offset_rssi_nphy( -+ pi, 0x0, -+ (s8) -+ fine_digital_offset -+ [core * -+ 2], -+ (core == PHY_CORE_0) ? -+ RADIO_MIMO_CORESEL_CORE1 : -+ RADIO_MIMO_CORESEL_CORE2, -+ (result_idx % 2 == 0) ? -+ NPHY_RAIL_I : -+ NPHY_RAIL_Q, -+ rssi_type); -+ } -+ } -+ -+ } -+ } -+ -+ write_phy_reg(pi, 0x91, NPHY_Rfctrlintc1_save); -+ write_phy_reg(pi, 0x92, NPHY_Rfctrlintc2_save); -+ -+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); -+ -+ mod_phy_reg(pi, 0xe7, (0x1 << 0), 1 << 0); -+ mod_phy_reg(pi, 0x78, (0x1 << 0), 1 << 0); -+ mod_phy_reg(pi, 0xe7, (0x1 << 0), 0); -+ -+ mod_phy_reg(pi, 0xec, (0x1 << 0), 1 << 0); -+ mod_phy_reg(pi, 0x78, (0x1 << 1), 1 << 1); -+ mod_phy_reg(pi, 0xec, (0x1 << 0), 0); -+ -+ write_phy_reg(pi, 0x8f, NPHY_AfectrlOverride1_save); -+ write_phy_reg(pi, 0xa5, NPHY_AfectrlOverride2_save); -+ write_phy_reg(pi, 0xa6, NPHY_AfectrlCore1_save); -+ write_phy_reg(pi, 0xa7, NPHY_AfectrlCore2_save); -+ write_phy_reg(pi, 0xe7, NPHY_RfctrlOverride0_save); -+ write_phy_reg(pi, 0xec, NPHY_RfctrlOverride1_save); -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ write_phy_reg(pi, 0x342, NPHY_REV7_RfctrlOverride3_save); -+ write_phy_reg(pi, 0x343, NPHY_REV7_RfctrlOverride4_save); -+ write_phy_reg(pi, 0x346, NPHY_REV7_RfctrlOverride5_save); -+ write_phy_reg(pi, 0x347, NPHY_REV7_RfctrlOverride6_save); -+ } -+ write_phy_reg(pi, 0xe5, NPHY_RfctrlOverrideAux0_save); -+ write_phy_reg(pi, 0xe6, NPHY_RfctrlOverrideAux1_save); -+ write_phy_reg(pi, 0x78, NPHY_RfctrlCmd_save); -+ write_phy_reg(pi, 0xf9, NPHY_RfctrlMiscReg1_save); -+ write_phy_reg(pi, 0xfb, NPHY_RfctrlMiscReg2_save); -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ write_phy_reg(pi, 0x340, NPHY_REV7_RfctrlMiscReg3_save); -+ write_phy_reg(pi, 0x341, NPHY_REV7_RfctrlMiscReg4_save); -+ write_phy_reg(pi, 0x344, NPHY_REV7_RfctrlMiscReg5_save); -+ write_phy_reg(pi, 0x345, NPHY_REV7_RfctrlMiscReg6_save); -+ } -+ write_phy_reg(pi, 0x7a, NPHY_RfctrlRSSIOTHERS1_save); -+ write_phy_reg(pi, 0x7d, NPHY_RfctrlRSSIOTHERS2_save); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ pi->rssical_cache.rssical_radio_regs_2G[0] = -+ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0); -+ pi->rssical_cache.rssical_radio_regs_2G[1] = -+ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1); -+ } else { -+ pi->rssical_cache.rssical_radio_regs_2G[0] = -+ read_radio_reg(pi, -+ RADIO_2056_RX_RSSI_MISC | -+ RADIO_2056_RX0); -+ pi->rssical_cache.rssical_radio_regs_2G[1] = -+ read_radio_reg(pi, -+ RADIO_2056_RX_RSSI_MISC | -+ RADIO_2056_RX1); -+ } -+ -+ pi->rssical_cache.rssical_phyregs_2G[0] = -+ read_phy_reg(pi, 0x1a6); -+ pi->rssical_cache.rssical_phyregs_2G[1] = -+ read_phy_reg(pi, 0x1ac); -+ pi->rssical_cache.rssical_phyregs_2G[2] = -+ read_phy_reg(pi, 0x1b2); -+ pi->rssical_cache.rssical_phyregs_2G[3] = -+ read_phy_reg(pi, 0x1b8); -+ pi->rssical_cache.rssical_phyregs_2G[4] = -+ read_phy_reg(pi, 0x1a4); -+ pi->rssical_cache.rssical_phyregs_2G[5] = -+ read_phy_reg(pi, 0x1aa); -+ pi->rssical_cache.rssical_phyregs_2G[6] = -+ read_phy_reg(pi, 0x1b0); -+ pi->rssical_cache.rssical_phyregs_2G[7] = -+ read_phy_reg(pi, 0x1b6); -+ pi->rssical_cache.rssical_phyregs_2G[8] = -+ read_phy_reg(pi, 0x1a5); -+ pi->rssical_cache.rssical_phyregs_2G[9] = -+ read_phy_reg(pi, 0x1ab); -+ pi->rssical_cache.rssical_phyregs_2G[10] = -+ read_phy_reg(pi, 0x1b1); -+ pi->rssical_cache.rssical_phyregs_2G[11] = -+ read_phy_reg(pi, 0x1b7); -+ -+ pi->nphy_rssical_chanspec_2G = pi->radio_chanspec; -+ } else { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ pi->rssical_cache.rssical_radio_regs_5G[0] = -+ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0); -+ pi->rssical_cache.rssical_radio_regs_5G[1] = -+ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1); -+ } else { -+ pi->rssical_cache.rssical_radio_regs_5G[0] = -+ read_radio_reg(pi, -+ RADIO_2056_RX_RSSI_MISC | -+ RADIO_2056_RX0); -+ pi->rssical_cache.rssical_radio_regs_5G[1] = -+ read_radio_reg(pi, -+ RADIO_2056_RX_RSSI_MISC | -+ RADIO_2056_RX1); -+ } -+ -+ pi->rssical_cache.rssical_phyregs_5G[0] = -+ read_phy_reg(pi, 0x1a6); -+ pi->rssical_cache.rssical_phyregs_5G[1] = -+ read_phy_reg(pi, 0x1ac); -+ pi->rssical_cache.rssical_phyregs_5G[2] = -+ read_phy_reg(pi, 0x1b2); -+ pi->rssical_cache.rssical_phyregs_5G[3] = -+ read_phy_reg(pi, 0x1b8); -+ pi->rssical_cache.rssical_phyregs_5G[4] = -+ read_phy_reg(pi, 0x1a4); -+ pi->rssical_cache.rssical_phyregs_5G[5] = -+ read_phy_reg(pi, 0x1aa); -+ pi->rssical_cache.rssical_phyregs_5G[6] = -+ read_phy_reg(pi, 0x1b0); -+ pi->rssical_cache.rssical_phyregs_5G[7] = -+ read_phy_reg(pi, 0x1b6); -+ pi->rssical_cache.rssical_phyregs_5G[8] = -+ read_phy_reg(pi, 0x1a5); -+ pi->rssical_cache.rssical_phyregs_5G[9] = -+ read_phy_reg(pi, 0x1ab); -+ pi->rssical_cache.rssical_phyregs_5G[10] = -+ read_phy_reg(pi, 0x1b1); -+ pi->rssical_cache.rssical_phyregs_5G[11] = -+ read_phy_reg(pi, 0x1b7); -+ -+ pi->nphy_rssical_chanspec_5G = pi->radio_chanspec; -+ } -+ -+ wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state); -+ wlc_phy_clip_det_nphy(pi, 1, clip_state); -+} -+ -+static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type) -+{ -+ s32 target_code; -+ u16 classif_state; -+ u16 clip_state[2]; -+ u16 rssi_ctrl_state[2], pd_state[2]; -+ u16 rfctrlintc_state[2], rfpdcorerxtx_state[2]; -+ u16 rfctrlintc_override_val; -+ u16 clip_off[] = { 0xffff, 0xffff }; -+ u16 rf_pd_val, pd_mask, rssi_ctrl_mask; -+ u8 vcm, min_vcm, vcm_tmp[4]; -+ u8 vcm_final[4] = { 0, 0, 0, 0 }; -+ u8 result_idx, ctr; -+ s32 poll_results[4][4] = { -+ {0, 0, 0, 0}, -+ {0, 0, 0, 0}, -+ {0, 0, 0, 0}, -+ {0, 0, 0, 0} -+ }; -+ s32 poll_miniq[4][2] = { -+ {0, 0}, -+ {0, 0}, -+ {0, 0}, -+ {0, 0} -+ }; -+ s32 min_d, curr_d; -+ s32 fine_digital_offset[4]; -+ s32 poll_results_min[4] = { 0, 0, 0, 0 }; -+ s32 min_poll; -+ -+ switch (rssi_type) { -+ case NPHY_RSSI_SEL_NB: -+ target_code = NPHY_RSSICAL_NB_TARGET; -+ break; -+ case NPHY_RSSI_SEL_W1: -+ target_code = NPHY_RSSICAL_W1_TARGET; -+ break; -+ case NPHY_RSSI_SEL_W2: -+ target_code = NPHY_RSSICAL_W2_TARGET; -+ break; -+ default: -+ return; -+ break; -+ } -+ -+ classif_state = wlc_phy_classifier_nphy(pi, 0, 0); -+ wlc_phy_classifier_nphy(pi, (0x7 << 0), 4); -+ wlc_phy_clip_det_nphy(pi, 0, clip_state); -+ wlc_phy_clip_det_nphy(pi, 1, clip_off); -+ -+ rf_pd_val = (rssi_type == NPHY_RSSI_SEL_NB) ? 0x6 : 0x4; -+ rfctrlintc_override_val = -+ CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 : 0x110; -+ -+ rfctrlintc_state[0] = read_phy_reg(pi, 0x91); -+ rfpdcorerxtx_state[0] = read_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX); -+ write_phy_reg(pi, 0x91, rfctrlintc_override_val); -+ write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rf_pd_val); -+ -+ rfctrlintc_state[1] = read_phy_reg(pi, 0x92); -+ rfpdcorerxtx_state[1] = read_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX); -+ write_phy_reg(pi, 0x92, rfctrlintc_override_val); -+ write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rf_pd_val); -+ -+ pd_mask = RADIO_2055_NBRSSI_PD | RADIO_2055_WBRSSI_G1_PD | -+ RADIO_2055_WBRSSI_G2_PD; -+ pd_state[0] = -+ read_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC) & pd_mask; -+ pd_state[1] = -+ read_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC) & pd_mask; -+ mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, 0); -+ mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, 0); -+ rssi_ctrl_mask = RADIO_2055_NBRSSI_SEL | RADIO_2055_WBRSSI_G1_SEL | -+ RADIO_2055_WBRSSI_G2_SEL; -+ rssi_ctrl_state[0] = -+ read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE1) & rssi_ctrl_mask; -+ rssi_ctrl_state[1] = -+ read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE2) & rssi_ctrl_mask; -+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type); -+ -+ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX, -+ NPHY_RAIL_I, rssi_type); -+ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX, -+ NPHY_RAIL_Q, rssi_type); -+ -+ for (vcm = 0; vcm < 4; vcm++) { -+ -+ vcm_tmp[0] = vcm_tmp[1] = vcm_tmp[2] = vcm_tmp[3] = vcm; -+ if (rssi_type != NPHY_RSSI_SEL_W2) -+ wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_tmp); -+ -+ wlc_phy_poll_rssi_nphy(pi, rssi_type, &poll_results[vcm][0], -+ NPHY_RSSICAL_NPOLL); -+ -+ if ((rssi_type == NPHY_RSSI_SEL_W1) -+ || (rssi_type == NPHY_RSSI_SEL_W2)) { -+ for (ctr = 0; ctr < 2; ctr++) -+ poll_miniq[vcm][ctr] = -+ min(poll_results[vcm][ctr * 2 + 0], -+ poll_results[vcm][ctr * 2 + 1]); -+ } -+ } -+ -+ for (result_idx = 0; result_idx < 4; result_idx++) { -+ min_d = NPHY_RSSICAL_MAXD; -+ min_vcm = 0; -+ min_poll = NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL + 1; -+ for (vcm = 0; vcm < 4; vcm++) { -+ curr_d = abs(((rssi_type == NPHY_RSSI_SEL_NB) ? -+ poll_results[vcm][result_idx] : -+ poll_miniq[vcm][result_idx / 2]) - -+ (target_code * NPHY_RSSICAL_NPOLL)); -+ if (curr_d < min_d) { -+ min_d = curr_d; -+ min_vcm = vcm; -+ } -+ if (poll_results[vcm][result_idx] < min_poll) -+ min_poll = poll_results[vcm][result_idx]; -+ } -+ vcm_final[result_idx] = min_vcm; -+ poll_results_min[result_idx] = min_poll; -+ } -+ -+ if (rssi_type != NPHY_RSSI_SEL_W2) -+ wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_final); -+ -+ for (result_idx = 0; result_idx < 4; result_idx++) { -+ fine_digital_offset[result_idx] = -+ (target_code * NPHY_RSSICAL_NPOLL) - -+ poll_results[vcm_final[result_idx]][result_idx]; -+ if (fine_digital_offset[result_idx] < 0) { -+ fine_digital_offset[result_idx] = -+ abs(fine_digital_offset[result_idx]); -+ fine_digital_offset[result_idx] += -+ (NPHY_RSSICAL_NPOLL / 2); -+ fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL; -+ fine_digital_offset[result_idx] = -+ -fine_digital_offset[result_idx]; -+ } else { -+ fine_digital_offset[result_idx] += -+ (NPHY_RSSICAL_NPOLL / 2); -+ fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL; -+ } -+ -+ if (poll_results_min[result_idx] == -+ NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) -+ fine_digital_offset[result_idx] = -+ (target_code - NPHY_RSSICAL_MAXREAD - 1); -+ -+ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, -+ (s8) -+ fine_digital_offset[result_idx], -+ (result_idx / 2 == -+ 0) ? RADIO_MIMO_CORESEL_CORE1 : -+ RADIO_MIMO_CORESEL_CORE2, -+ (result_idx % 2 == -+ 0) ? NPHY_RAIL_I : NPHY_RAIL_Q, -+ rssi_type); -+ } -+ -+ mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, pd_state[0]); -+ mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, pd_state[1]); -+ if (rssi_ctrl_state[0] == RADIO_2055_NBRSSI_SEL) -+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1, -+ NPHY_RSSI_SEL_NB); -+ else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G1_SEL) -+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1, -+ NPHY_RSSI_SEL_W1); -+ else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G2_SEL) -+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1, -+ NPHY_RSSI_SEL_W2); -+ else -+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1, -+ NPHY_RSSI_SEL_W2); -+ if (rssi_ctrl_state[1] == RADIO_2055_NBRSSI_SEL) -+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2, -+ NPHY_RSSI_SEL_NB); -+ else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G1_SEL) -+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2, -+ NPHY_RSSI_SEL_W1); -+ else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G2_SEL) -+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2, -+ NPHY_RSSI_SEL_W2); -+ else -+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2, -+ NPHY_RSSI_SEL_W2); -+ -+ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, rssi_type); -+ -+ write_phy_reg(pi, 0x91, rfctrlintc_state[0]); -+ write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rfpdcorerxtx_state[0]); -+ write_phy_reg(pi, 0x92, rfctrlintc_state[1]); -+ write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rfpdcorerxtx_state[1]); -+ -+ wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state); -+ wlc_phy_clip_det_nphy(pi, 1, clip_state); -+ -+ wlc_phy_resetcca_nphy(pi); -+} -+ -+void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi) -+{ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ wlc_phy_rssi_cal_nphy_rev3(pi); -+ } else { -+ wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_NB); -+ wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W1); -+ wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W2); -+ } -+} -+ -+int -+wlc_phy_rssi_compute_nphy(struct brcms_phy *pi, struct d11rxhdr *rxh) -+{ -+ s16 rxpwr, rxpwr0, rxpwr1; -+ s16 phyRx0_l, phyRx2_l; -+ -+ rxpwr = 0; -+ rxpwr0 = rxh->PhyRxStatus_1 & PRXS1_nphy_PWR0_MASK; -+ rxpwr1 = (rxh->PhyRxStatus_1 & PRXS1_nphy_PWR1_MASK) >> 8; -+ -+ if (rxpwr0 > 127) -+ rxpwr0 -= 256; -+ if (rxpwr1 > 127) -+ rxpwr1 -= 256; -+ -+ phyRx0_l = rxh->PhyRxStatus_0 & 0x00ff; -+ phyRx2_l = rxh->PhyRxStatus_2 & 0x00ff; -+ if (phyRx2_l > 127) -+ phyRx2_l -= 256; -+ -+ if (((rxpwr0 == 16) || (rxpwr0 == 32))) { -+ rxpwr0 = rxpwr1; -+ rxpwr1 = phyRx2_l; -+ } -+ -+ if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MAX) -+ rxpwr = (rxpwr0 > rxpwr1) ? rxpwr0 : rxpwr1; -+ else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MIN) -+ rxpwr = (rxpwr0 < rxpwr1) ? rxpwr0 : rxpwr1; -+ else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_AVG) -+ rxpwr = (rxpwr0 + rxpwr1) >> 1; -+ -+ return rxpwr; -+} -+ -+static void -+wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, struct cordic_iq *tone_buf, -+ u16 num_samps) -+{ -+ u16 t; -+ u32 *data_buf = NULL; -+ -+ data_buf = kmalloc(sizeof(u32) * num_samps, GFP_ATOMIC); -+ if (data_buf == NULL) -+ return; -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ for (t = 0; t < num_samps; t++) -+ data_buf[t] = ((((unsigned int)tone_buf[t].i) & 0x3ff) << 10) | -+ (((unsigned int)tone_buf[t].q) & 0x3ff); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SAMPLEPLAY, num_samps, 0, 32, -+ data_buf); -+ -+ kfree(data_buf); -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+} -+ -+static u16 -+wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, -+ u8 dac_test_mode) -+{ -+ u8 phy_bw, is_phybw40; -+ u16 num_samps, t, spur; -+ s32 theta = 0, rot = 0; -+ u32 tbl_len; -+ struct cordic_iq *tone_buf = NULL; -+ -+ is_phybw40 = CHSPEC_IS40(pi->radio_chanspec); -+ phy_bw = (is_phybw40 == 1) ? 40 : 20; -+ tbl_len = (phy_bw << 3); -+ -+ if (dac_test_mode == 1) { -+ spur = read_phy_reg(pi, 0x01); -+ spur = (spur >> 15) & 1; -+ phy_bw = (spur == 1) ? 82 : 80; -+ phy_bw = (is_phybw40 == 1) ? (phy_bw << 1) : phy_bw; -+ -+ tbl_len = (phy_bw << 1); -+ } -+ -+ tone_buf = kmalloc(sizeof(struct cordic_iq) * tbl_len, GFP_ATOMIC); -+ if (tone_buf == NULL) -+ return 0; -+ -+ num_samps = (u16) tbl_len; -+ rot = ((f_kHz * 36) / phy_bw) / 100; -+ theta = 0; -+ -+ for (t = 0; t < num_samps; t++) { -+ -+ tone_buf[t] = cordic_calc_iq(theta); -+ -+ theta += rot; -+ -+ tone_buf[t].q = (s32) FLOAT(tone_buf[t].q * max_val); -+ tone_buf[t].i = (s32) FLOAT(tone_buf[t].i * max_val); -+ } -+ -+ wlc_phy_loadsampletable_nphy(pi, tone_buf, num_samps); -+ -+ kfree(tone_buf); -+ -+ return num_samps; -+} -+ -+static void -+wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops, -+ u16 wait, u8 iqmode, u8 dac_test_mode, -+ bool modify_bbmult) -+{ -+ u16 bb_mult; -+ u8 phy_bw, sample_cmd; -+ u16 orig_RfseqCoreActv; -+ u16 lpf_bw_ctl_override3, lpf_bw_ctl_override4, lpf_bw_ctl_miscreg3, -+ lpf_bw_ctl_miscreg4; -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ phy_bw = 20; -+ if (CHSPEC_IS40(pi->radio_chanspec)) -+ phy_bw = 40; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ lpf_bw_ctl_override3 = read_phy_reg(pi, 0x342) & (0x1 << 7); -+ lpf_bw_ctl_override4 = read_phy_reg(pi, 0x343) & (0x1 << 7); -+ if (lpf_bw_ctl_override3 | lpf_bw_ctl_override4) { -+ lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) & -+ (0x7 << 8); -+ lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) & -+ (0x7 << 8); -+ } else { -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, -+ (0x1 << 7), -+ wlc_phy_read_lpf_bw_ctl_nphy -+ (pi, -+ 0), 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ -+ pi->nphy_sample_play_lpf_bw_ctl_ovr = true; -+ -+ lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) & -+ (0x7 << 8); -+ lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) & -+ (0x7 << 8); -+ } -+ } -+ -+ if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) == 0) { -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16, -+ &bb_mult); -+ pi->nphy_bb_mult_save = -+ BB_MULT_VALID_MASK | (bb_mult & BB_MULT_MASK); -+ } -+ -+ if (modify_bbmult) { -+ bb_mult = (phy_bw == 20) ? 100 : 71; -+ bb_mult = (bb_mult << 8) + bb_mult; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16, -+ &bb_mult); -+ } -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+ -+ write_phy_reg(pi, 0xc6, num_samps - 1); -+ -+ if (loops != 0xffff) -+ write_phy_reg(pi, 0xc4, loops - 1); -+ else -+ write_phy_reg(pi, 0xc4, loops); -+ -+ write_phy_reg(pi, 0xc5, wait); -+ -+ orig_RfseqCoreActv = read_phy_reg(pi, 0xa1); -+ or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override); -+ if (iqmode) { -+ -+ and_phy_reg(pi, 0xc2, 0x7FFF); -+ -+ or_phy_reg(pi, 0xc2, 0x8000); -+ } else { -+ -+ sample_cmd = (dac_test_mode == 1) ? 0x5 : 0x1; -+ write_phy_reg(pi, 0xc3, sample_cmd); -+ } -+ -+ SPINWAIT(((read_phy_reg(pi, 0xa4) & 0x1) == 1), 1000); -+ -+ write_phy_reg(pi, 0xa1, orig_RfseqCoreActv); -+} -+ -+int -+wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, -+ u8 iqmode, u8 dac_test_mode, bool modify_bbmult) -+{ -+ u16 num_samps; -+ u16 loops = 0xffff; -+ u16 wait = 0; -+ -+ num_samps = wlc_phy_gen_load_samples_nphy(pi, f_kHz, max_val, -+ dac_test_mode); -+ if (num_samps == 0) -+ return -EBADE; -+ -+ wlc_phy_runsamples_nphy(pi, num_samps, loops, wait, iqmode, -+ dac_test_mode, modify_bbmult); -+ -+ return 0; -+} -+ -+void wlc_phy_stopplayback_nphy(struct brcms_phy *pi) -+{ -+ u16 playback_status; -+ u16 bb_mult; -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ playback_status = read_phy_reg(pi, 0xc7); -+ if (playback_status & 0x1) -+ or_phy_reg(pi, 0xc3, NPHY_sampleCmd_STOP); -+ else if (playback_status & 0x2) -+ and_phy_reg(pi, 0xc2, -+ (u16) ~NPHY_iqloCalCmdGctl_IQLO_CAL_EN); -+ -+ and_phy_reg(pi, 0xc3, (u16) ~(0x1 << 2)); -+ -+ if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) != 0) { -+ -+ bb_mult = pi->nphy_bb_mult_save & BB_MULT_MASK; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16, -+ &bb_mult); -+ -+ pi->nphy_bb_mult_save = 0; -+ } -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 7) || NREV_GE(pi->pubpi.phy_rev, 8)) { -+ if (pi->nphy_sample_play_lpf_bw_ctl_ovr) { -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, -+ (0x1 << 7), -+ 0, 0, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ pi->nphy_sample_play_lpf_bw_ctl_ovr = false; -+ } -+ } -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+} -+ -+static u32 *brcms_phy_get_tx_pwrctrl_tbl(struct brcms_phy *pi) -+{ -+ u32 *tx_pwrctrl_tbl = NULL; -+ uint phyrev = pi->pubpi.phy_rev; -+ -+ if (PHY_IPA(pi)) { -+ tx_pwrctrl_tbl = -+ wlc_phy_get_ipa_gaintbl_nphy(pi); -+ } else { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ if (NREV_IS(phyrev, 3)) -+ tx_pwrctrl_tbl = nphy_tpc_5GHz_txgain_rev3; -+ else if (NREV_IS(phyrev, 4)) -+ tx_pwrctrl_tbl = -+ (pi->srom_fem5g.extpagain == 3) ? -+ nphy_tpc_5GHz_txgain_HiPwrEPA : -+ nphy_tpc_5GHz_txgain_rev4; -+ else -+ tx_pwrctrl_tbl = nphy_tpc_5GHz_txgain_rev5; -+ } else { -+ if (NREV_GE(phyrev, 7)) { -+ if (pi->pubpi.radiorev == 3) -+ tx_pwrctrl_tbl = -+ nphy_tpc_txgain_epa_2057rev3; -+ else if (pi->pubpi.radiorev == 5) -+ tx_pwrctrl_tbl = -+ nphy_tpc_txgain_epa_2057rev5; -+ } else { -+ if (NREV_GE(phyrev, 5) && -+ (pi->srom_fem2g.extpagain == 3)) -+ tx_pwrctrl_tbl = -+ nphy_tpc_txgain_HiPwrEPA; -+ else -+ tx_pwrctrl_tbl = -+ nphy_tpc_txgain_rev3; -+ } -+ } -+ } -+ return tx_pwrctrl_tbl; -+} -+ -+struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi) -+{ -+ u16 base_idx[2], curr_gain[2]; -+ u8 core_no; -+ struct nphy_txgains target_gain; -+ u32 *tx_pwrctrl_tbl = NULL; -+ -+ if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) { -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, -+ curr_gain); -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+ -+ for (core_no = 0; core_no < 2; core_no++) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ target_gain.ipa[core_no] = -+ curr_gain[core_no] & 0x0007; -+ target_gain.pad[core_no] = -+ ((curr_gain[core_no] & 0x00F8) >> 3); -+ target_gain.pga[core_no] = -+ ((curr_gain[core_no] & 0x0F00) >> 8); -+ target_gain.txgm[core_no] = -+ ((curr_gain[core_no] & 0x7000) >> 12); -+ target_gain.txlpf[core_no] = -+ ((curr_gain[core_no] & 0x8000) >> 15); -+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ target_gain.ipa[core_no] = -+ curr_gain[core_no] & 0x000F; -+ target_gain.pad[core_no] = -+ ((curr_gain[core_no] & 0x00F0) >> 4); -+ target_gain.pga[core_no] = -+ ((curr_gain[core_no] & 0x0F00) >> 8); -+ target_gain.txgm[core_no] = -+ ((curr_gain[core_no] & 0x7000) >> 12); -+ } else { -+ target_gain.ipa[core_no] = -+ curr_gain[core_no] & 0x0003; -+ target_gain.pad[core_no] = -+ ((curr_gain[core_no] & 0x000C) >> 2); -+ target_gain.pga[core_no] = -+ ((curr_gain[core_no] & 0x0070) >> 4); -+ target_gain.txgm[core_no] = -+ ((curr_gain[core_no] & 0x0380) >> 7); -+ } -+ } -+ } else { -+ uint phyrev = pi->pubpi.phy_rev; -+ -+ base_idx[0] = (read_phy_reg(pi, 0x1ed) >> 8) & 0x7f; -+ base_idx[1] = (read_phy_reg(pi, 0x1ee) >> 8) & 0x7f; -+ for (core_no = 0; core_no < 2; core_no++) { -+ if (NREV_GE(phyrev, 3)) { -+ tx_pwrctrl_tbl = -+ brcms_phy_get_tx_pwrctrl_tbl(pi); -+ if (NREV_GE(phyrev, 7)) { -+ target_gain.ipa[core_no] = -+ (tx_pwrctrl_tbl -+ [base_idx[core_no]] -+ >> 16) & 0x7; -+ target_gain.pad[core_no] = -+ (tx_pwrctrl_tbl -+ [base_idx[core_no]] -+ >> 19) & 0x1f; -+ target_gain.pga[core_no] = -+ (tx_pwrctrl_tbl -+ [base_idx[core_no]] -+ >> 24) & 0xf; -+ target_gain.txgm[core_no] = -+ (tx_pwrctrl_tbl -+ [base_idx[core_no]] -+ >> 28) & 0x7; -+ target_gain.txlpf[core_no] = -+ (tx_pwrctrl_tbl -+ [base_idx[core_no]] -+ >> 31) & 0x1; -+ } else { -+ target_gain.ipa[core_no] = -+ (tx_pwrctrl_tbl -+ [base_idx[core_no]] -+ >> 16) & 0xf; -+ target_gain.pad[core_no] = -+ (tx_pwrctrl_tbl -+ [base_idx[core_no]] -+ >> 20) & 0xf; -+ target_gain.pga[core_no] = -+ (tx_pwrctrl_tbl -+ [base_idx[core_no]] -+ >> 24) & 0xf; -+ target_gain.txgm[core_no] = -+ (tx_pwrctrl_tbl -+ [base_idx[core_no]] -+ >> 28) & 0x7; -+ } -+ } else { -+ target_gain.ipa[core_no] = -+ (nphy_tpc_txgain[base_idx[core_no]] >> -+ 16) & 0x3; -+ target_gain.pad[core_no] = -+ (nphy_tpc_txgain[base_idx[core_no]] >> -+ 18) & 0x3; -+ target_gain.pga[core_no] = -+ (nphy_tpc_txgain[base_idx[core_no]] >> -+ 20) & 0x7; -+ target_gain.txgm[core_no] = -+ (nphy_tpc_txgain[base_idx[core_no]] >> -+ 23) & 0x7; -+ } -+ } -+ } -+ -+ return target_gain; -+} -+ -+static void -+wlc_phy_iqcal_gainparams_nphy(struct brcms_phy *pi, u16 core_no, -+ struct nphy_txgains target_gain, -+ struct nphy_iqcal_params *params) -+{ -+ u8 k; -+ int idx; -+ u16 gain_index; -+ u8 band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ params->txlpf = target_gain.txlpf[core_no]; -+ -+ params->txgm = target_gain.txgm[core_no]; -+ params->pga = target_gain.pga[core_no]; -+ params->pad = target_gain.pad[core_no]; -+ params->ipa = target_gain.ipa[core_no]; -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ params->cal_gain = -+ ((params->txlpf << 15) | (params->txgm << 12) | -+ (params->pga << 8) | -+ (params->pad << 3) | (params->ipa)); -+ else -+ params->cal_gain = -+ ((params->txgm << 12) | (params->pga << 8) | -+ (params->pad << 4) | (params->ipa)); -+ -+ params->ncorr[0] = 0x79; -+ params->ncorr[1] = 0x79; -+ params->ncorr[2] = 0x79; -+ params->ncorr[3] = 0x79; -+ params->ncorr[4] = 0x79; -+ } else { -+ -+ gain_index = ((target_gain.pad[core_no] << 0) | -+ (target_gain.pga[core_no] << 4) | -+ (target_gain.txgm[core_no] << 8)); -+ -+ idx = -1; -+ for (k = 0; k < NPHY_IQCAL_NUMGAINS; k++) { -+ if (tbl_iqcal_gainparams_nphy[band_idx][k][0] == -+ gain_index) { -+ idx = k; -+ break; -+ } -+ } -+ -+ params->txgm = tbl_iqcal_gainparams_nphy[band_idx][k][1]; -+ params->pga = tbl_iqcal_gainparams_nphy[band_idx][k][2]; -+ params->pad = tbl_iqcal_gainparams_nphy[band_idx][k][3]; -+ params->cal_gain = ((params->txgm << 7) | (params->pga << 4) | -+ (params->pad << 2)); -+ params->ncorr[0] = tbl_iqcal_gainparams_nphy[band_idx][k][4]; -+ params->ncorr[1] = tbl_iqcal_gainparams_nphy[band_idx][k][5]; -+ params->ncorr[2] = tbl_iqcal_gainparams_nphy[band_idx][k][6]; -+ params->ncorr[3] = tbl_iqcal_gainparams_nphy[band_idx][k][7]; -+ } -+} -+ -+static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi) -+{ -+ u16 jtag_core, core; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ for (core = 0; core <= 1; core++) { -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TX_SSI_MASTER); -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, core, -+ IQCAL_VCM_HG); -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, core, -+ IQCAL_IDAC); -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TSSI_VCM); -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] = 0; -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TX_SSI_MUX); -+ -+ if (pi->pubpi.radiorev != 5) -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, -+ core, -+ TSSIA); -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG); -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TSSI_MISC1); -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TX_SSI_MASTER, 0x0a); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ IQCAL_VCM_HG, 0x43); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ IQCAL_IDAC, 0x55); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TSSI_VCM, 0x00); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TSSIG, 0x00); -+ if (pi->use_int_tx_iqlo_cal_nphy) { -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, -+ core, TX_SSI_MUX, 0x4); -+ if (!(pi-> -+ internal_tx_iqlo_cal_tapoff_intpa_nphy)) -+ WRITE_RADIO_REG3(pi, RADIO_2057, -+ TX, core, -+ TSSIA, 0x31); -+ else -+ WRITE_RADIO_REG3(pi, RADIO_2057, -+ TX, core, -+ TSSIA, 0x21); -+ } -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TSSI_MISC1, 0x00); -+ } else { -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TX_SSI_MASTER, 0x06); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ IQCAL_VCM_HG, 0x43); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ IQCAL_IDAC, 0x55); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TSSI_VCM, 0x00); -+ -+ if (pi->pubpi.radiorev != 5) -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, -+ core, TSSIA, 0x00); -+ if (pi->use_int_tx_iqlo_cal_nphy) { -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, -+ core, TX_SSI_MUX, -+ 0x06); -+ if (!(pi-> -+ internal_tx_iqlo_cal_tapoff_intpa_nphy)) -+ WRITE_RADIO_REG3(pi, RADIO_2057, -+ TX, core, -+ TSSIG, 0x31); -+ else -+ WRITE_RADIO_REG3(pi, RADIO_2057, -+ TX, core, -+ TSSIG, 0x21); -+ } -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TSSI_MISC1, 0x00); -+ } -+ } -+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ -+ for (core = 0; core <= 1; core++) { -+ jtag_core = -+ (core == -+ PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1; -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_TX_SSI_MASTER | -+ jtag_core); -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_IQCAL_VCM_HG | -+ jtag_core); -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_IQCAL_IDAC | -+ jtag_core); -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] = -+ read_radio_reg( -+ pi, -+ RADIO_2056_TX_TSSI_VCM | -+ jtag_core); -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_TX_AMP_DET | -+ jtag_core); -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_TX_SSI_MUX | -+ jtag_core); -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_TSSIA | jtag_core); -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_TSSIG | jtag_core); -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_TSSI_MISC1 | -+ jtag_core); -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 9] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_TSSI_MISC2 | -+ jtag_core); -+ -+ pi->tx_rx_cal_radio_saveregs[(core * 11) + 10] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_TSSI_MISC3 | -+ jtag_core); -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ write_radio_reg(pi, -+ RADIO_2056_TX_TX_SSI_MASTER | -+ jtag_core, 0x0a); -+ write_radio_reg(pi, -+ RADIO_2056_TX_IQCAL_VCM_HG | -+ jtag_core, 0x40); -+ write_radio_reg(pi, -+ RADIO_2056_TX_IQCAL_IDAC | -+ jtag_core, 0x55); -+ write_radio_reg(pi, -+ RADIO_2056_TX_TSSI_VCM | -+ jtag_core, 0x00); -+ write_radio_reg(pi, -+ RADIO_2056_TX_TX_AMP_DET | -+ jtag_core, 0x00); -+ -+ if (PHY_IPA(pi)) { -+ write_radio_reg( -+ pi, -+ RADIO_2056_TX_TX_SSI_MUX -+ | jtag_core, 0x4); -+ write_radio_reg(pi, -+ RADIO_2056_TX_TSSIA | -+ jtag_core, 0x1); -+ } else { -+ write_radio_reg( -+ pi, -+ RADIO_2056_TX_TX_SSI_MUX -+ | jtag_core, 0x00); -+ write_radio_reg(pi, -+ RADIO_2056_TX_TSSIA | -+ jtag_core, 0x2f); -+ } -+ write_radio_reg(pi, -+ RADIO_2056_TX_TSSIG | jtag_core, -+ 0x00); -+ write_radio_reg(pi, -+ RADIO_2056_TX_TSSI_MISC1 | -+ jtag_core, 0x00); -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_TSSI_MISC2 | -+ jtag_core, 0x00); -+ write_radio_reg(pi, -+ RADIO_2056_TX_TSSI_MISC3 | -+ jtag_core, 0x00); -+ } else { -+ write_radio_reg(pi, -+ RADIO_2056_TX_TX_SSI_MASTER | -+ jtag_core, 0x06); -+ write_radio_reg(pi, -+ RADIO_2056_TX_IQCAL_VCM_HG | -+ jtag_core, 0x40); -+ write_radio_reg(pi, -+ RADIO_2056_TX_IQCAL_IDAC | -+ jtag_core, 0x55); -+ write_radio_reg(pi, -+ RADIO_2056_TX_TSSI_VCM | -+ jtag_core, 0x00); -+ write_radio_reg(pi, -+ RADIO_2056_TX_TX_AMP_DET | -+ jtag_core, 0x00); -+ write_radio_reg(pi, -+ RADIO_2056_TX_TSSIA | jtag_core, -+ 0x00); -+ -+ if (PHY_IPA(pi)) { -+ -+ write_radio_reg( -+ pi, -+ RADIO_2056_TX_TX_SSI_MUX -+ | jtag_core, 0x06); -+ if (NREV_LT(pi->pubpi.phy_rev, 5)) -+ write_radio_reg( -+ pi, -+ RADIO_2056_TX_TSSIG -+ | jtag_core, -+ 0x11); -+ else -+ write_radio_reg( -+ pi, -+ RADIO_2056_TX_TSSIG -+ | jtag_core, -+ 0x1); -+ } else { -+ write_radio_reg( -+ pi, -+ RADIO_2056_TX_TX_SSI_MUX -+ | jtag_core, 0x00); -+ write_radio_reg(pi, -+ RADIO_2056_TX_TSSIG | -+ jtag_core, 0x20); -+ } -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_TSSI_MISC1 | -+ jtag_core, 0x00); -+ write_radio_reg(pi, -+ RADIO_2056_TX_TSSI_MISC2 | -+ jtag_core, 0x00); -+ write_radio_reg(pi, -+ RADIO_2056_TX_TSSI_MISC3 | -+ jtag_core, 0x00); -+ } -+ } -+ } else { -+ -+ pi->tx_rx_cal_radio_saveregs[0] = -+ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1); -+ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x29); -+ pi->tx_rx_cal_radio_saveregs[1] = -+ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2); -+ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x54); -+ -+ pi->tx_rx_cal_radio_saveregs[2] = -+ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1); -+ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x29); -+ pi->tx_rx_cal_radio_saveregs[3] = -+ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2); -+ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x54); -+ -+ pi->tx_rx_cal_radio_saveregs[4] = -+ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1); -+ pi->tx_rx_cal_radio_saveregs[5] = -+ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2); -+ -+ if ((read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand) == -+ 0) { -+ -+ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04); -+ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04); -+ } else { -+ -+ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x20); -+ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x20); -+ } -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 2)) { -+ -+ or_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0x20); -+ or_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0x20); -+ } else { -+ -+ and_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0xdf); -+ and_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0xdf); -+ } -+ } -+} -+ -+static void wlc_phy_txcal_radio_cleanup_nphy(struct brcms_phy *pi) -+{ -+ u16 jtag_core, core; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ for (core = 0; core <= 1; core++) { -+ -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TX_SSI_MASTER, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 0]); -+ -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 1]); -+ -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 2]); -+ -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 3]); -+ -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TX_SSI_MUX, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 5]); -+ -+ if (pi->pubpi.radiorev != 5) -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TSSIA, -+ pi->tx_rx_cal_radio_saveregs -+ [(core * 11) + 6]); -+ -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 7]); -+ -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 8]); -+ } -+ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ for (core = 0; core <= 1; core++) { -+ jtag_core = (core == PHY_CORE_0) ? -+ RADIO_2056_TX0 : RADIO_2056_TX1; -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_TX_SSI_MASTER | jtag_core, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 0]); -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_IQCAL_VCM_HG | jtag_core, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 1]); -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_IQCAL_IDAC | jtag_core, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 2]); -+ -+ write_radio_reg(pi, RADIO_2056_TX_TSSI_VCM | jtag_core, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 3]); -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_TX_AMP_DET | jtag_core, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 4]); -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_TX_SSI_MUX | jtag_core, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 5]); -+ -+ write_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 6]); -+ -+ write_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 7]); -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_TSSI_MISC1 | jtag_core, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 8]); -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_TSSI_MISC2 | jtag_core, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 9]); -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_TSSI_MISC3 | jtag_core, -+ pi-> -+ tx_rx_cal_radio_saveregs[(core * 11) + -+ 10]); -+ } -+ } else { -+ -+ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, -+ pi->tx_rx_cal_radio_saveregs[0]); -+ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, -+ pi->tx_rx_cal_radio_saveregs[1]); -+ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, -+ pi->tx_rx_cal_radio_saveregs[2]); -+ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, -+ pi->tx_rx_cal_radio_saveregs[3]); -+ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, -+ pi->tx_rx_cal_radio_saveregs[4]); -+ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, -+ pi->tx_rx_cal_radio_saveregs[5]); -+ } -+} -+ -+static void wlc_phy_txcal_physetup_nphy(struct brcms_phy *pi) -+{ -+ u16 val, mask; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6); -+ pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7); -+ -+ mask = ((0x3 << 8) | (0x3 << 10)); -+ val = (0x2 << 8); -+ val |= (0x2 << 10); -+ mod_phy_reg(pi, 0xa6, mask, val); -+ mod_phy_reg(pi, 0xa7, mask, val); -+ -+ val = read_phy_reg(pi, 0x8f); -+ pi->tx_rx_cal_phy_saveregs[2] = val; -+ val |= ((0x1 << 9) | (0x1 << 10)); -+ write_phy_reg(pi, 0x8f, val); -+ -+ val = read_phy_reg(pi, 0xa5); -+ pi->tx_rx_cal_phy_saveregs[3] = val; -+ val |= ((0x1 << 9) | (0x1 << 10)); -+ write_phy_reg(pi, 0xa5, val); -+ -+ pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x01); -+ mod_phy_reg(pi, 0x01, (0x1 << 15), 0); -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16, -+ &val); -+ pi->tx_rx_cal_phy_saveregs[5] = val; -+ val = 0; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16, -+ &val); -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16, -+ &val); -+ pi->tx_rx_cal_phy_saveregs[6] = val; -+ val = 0; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16, -+ &val); -+ -+ pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0x91); -+ pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0x92); -+ -+ if (!(pi->use_int_tx_iqlo_cal_nphy)) -+ wlc_phy_rfctrlintc_override_nphy( -+ pi, -+ NPHY_RfctrlIntc_override_PA, -+ 1, -+ RADIO_MIMO_CORESEL_CORE1 -+ | -+ RADIO_MIMO_CORESEL_CORE2); -+ else -+ wlc_phy_rfctrlintc_override_nphy( -+ pi, -+ NPHY_RfctrlIntc_override_PA, -+ 0, -+ RADIO_MIMO_CORESEL_CORE1 -+ | -+ RADIO_MIMO_CORESEL_CORE2); -+ -+ wlc_phy_rfctrlintc_override_nphy(pi, -+ NPHY_RfctrlIntc_override_TRSW, -+ 0x2, RADIO_MIMO_CORESEL_CORE1); -+ wlc_phy_rfctrlintc_override_nphy(pi, -+ NPHY_RfctrlIntc_override_TRSW, -+ 0x8, RADIO_MIMO_CORESEL_CORE2); -+ -+ pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297); -+ pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b); -+ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 0), (0) << 0); -+ -+ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 0), (0) << 0); -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 7) -+ || NREV_GE(pi->pubpi.phy_rev, 8)) -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 7), -+ wlc_phy_read_lpf_bw_ctl_nphy -+ (pi, -+ 0), 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ -+ if (pi->use_int_tx_iqlo_cal_nphy -+ && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) { -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 7)) { -+ -+ mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4, -+ 1 << 4); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ mod_radio_reg( -+ pi, -+ RADIO_2057_PAD2G_TUNE_PUS_CORE0, -+ 1, 0); -+ mod_radio_reg( -+ pi, -+ RADIO_2057_PAD2G_TUNE_PUS_CORE1, -+ 1, 0); -+ } else { -+ mod_radio_reg( -+ pi, -+ RADIO_2057_IPA5G_CASCOFFV_PU_CORE0, -+ 1, 0); -+ mod_radio_reg( -+ pi, -+ RADIO_2057_IPA5G_CASCOFFV_PU_CORE1, -+ 1, 0); -+ } -+ } else if (NREV_GE(pi->pubpi.phy_rev, 8)) { -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, -+ (0x1 << 3), 0, -+ 0x3, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ } -+ } -+ } else { -+ pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6); -+ pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7); -+ -+ mask = ((0x3 << 12) | (0x3 << 14)); -+ val = (0x2 << 12); -+ val |= (0x2 << 14); -+ mod_phy_reg(pi, 0xa6, mask, val); -+ mod_phy_reg(pi, 0xa7, mask, val); -+ -+ val = read_phy_reg(pi, 0xa5); -+ pi->tx_rx_cal_phy_saveregs[2] = val; -+ val |= ((0x1 << 12) | (0x1 << 13)); -+ write_phy_reg(pi, 0xa5, val); -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16, -+ &val); -+ pi->tx_rx_cal_phy_saveregs[3] = val; -+ val |= 0x2000; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16, -+ &val); -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16, -+ &val); -+ pi->tx_rx_cal_phy_saveregs[4] = val; -+ val |= 0x2000; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16, -+ &val); -+ -+ pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x91); -+ pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x92); -+ val = CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120; -+ write_phy_reg(pi, 0x91, val); -+ write_phy_reg(pi, 0x92, val); -+ } -+} -+ -+static void wlc_phy_txcal_phycleanup_nphy(struct brcms_phy *pi) -+{ -+ u16 mask; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ write_phy_reg(pi, 0xa6, pi->tx_rx_cal_phy_saveregs[0]); -+ write_phy_reg(pi, 0xa7, pi->tx_rx_cal_phy_saveregs[1]); -+ write_phy_reg(pi, 0x8f, pi->tx_rx_cal_phy_saveregs[2]); -+ write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[3]); -+ write_phy_reg(pi, 0x01, pi->tx_rx_cal_phy_saveregs[4]); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16, -+ &pi->tx_rx_cal_phy_saveregs[5]); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16, -+ &pi->tx_rx_cal_phy_saveregs[6]); -+ -+ write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[7]); -+ write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[8]); -+ -+ write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]); -+ write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]); -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 7) -+ || NREV_GE(pi->pubpi.phy_rev, 8)) -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 7), 0, 0, -+ 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ -+ wlc_phy_resetcca_nphy(pi); -+ -+ if (pi->use_int_tx_iqlo_cal_nphy -+ && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) { -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 7)) { -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ mod_radio_reg( -+ pi, -+ RADIO_2057_PAD2G_TUNE_PUS_CORE0, -+ 1, 1); -+ mod_radio_reg( -+ pi, -+ RADIO_2057_PAD2G_TUNE_PUS_CORE1, -+ 1, 1); -+ } else { -+ mod_radio_reg( -+ pi, -+ RADIO_2057_IPA5G_CASCOFFV_PU_CORE0, -+ 1, 1); -+ mod_radio_reg( -+ pi, -+ RADIO_2057_IPA5G_CASCOFFV_PU_CORE1, -+ 1, 1); -+ } -+ -+ mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4, -+ 0); -+ } else if (NREV_GE(pi->pubpi.phy_rev, 8)) { -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, -+ (0x1 << 3), 0, -+ 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ } -+ } -+ } else { -+ mask = ((0x3 << 12) | (0x3 << 14)); -+ mod_phy_reg(pi, 0xa6, mask, pi->tx_rx_cal_phy_saveregs[0]); -+ mod_phy_reg(pi, 0xa7, mask, pi->tx_rx_cal_phy_saveregs[1]); -+ write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[2]); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16, -+ &pi->tx_rx_cal_phy_saveregs[3]); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16, -+ &pi->tx_rx_cal_phy_saveregs[4]); -+ -+ write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[5]); -+ write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[6]); -+ } -+} -+ -+void -+wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, u8 num_samps) -+{ -+ u16 tssi_reg; -+ s32 temp, pwrindex[2]; -+ s32 idle_tssi[2]; -+ s32 rssi_buf[4]; -+ s32 tssival[2]; -+ u8 tssi_type; -+ -+ tssi_reg = read_phy_reg(pi, 0x1e9); -+ -+ temp = (s32) (tssi_reg & 0x3f); -+ idle_tssi[0] = (temp <= 31) ? temp : (temp - 64); -+ -+ temp = (s32) ((tssi_reg >> 8) & 0x3f); -+ idle_tssi[1] = (temp <= 31) ? temp : (temp - 64); -+ -+ tssi_type = -+ CHSPEC_IS5G(pi->radio_chanspec) ? -+ (u8)NPHY_RSSI_SEL_TSSI_5G : (u8)NPHY_RSSI_SEL_TSSI_2G; -+ -+ wlc_phy_poll_rssi_nphy(pi, tssi_type, rssi_buf, num_samps); -+ -+ tssival[0] = rssi_buf[0] / ((s32) num_samps); -+ tssival[1] = rssi_buf[2] / ((s32) num_samps); -+ -+ pwrindex[0] = idle_tssi[0] - tssival[0] + 64; -+ pwrindex[1] = idle_tssi[1] - tssival[1] + 64; -+ -+ if (pwrindex[0] < 0) -+ pwrindex[0] = 0; -+ else if (pwrindex[0] > 63) -+ pwrindex[0] = 63; -+ -+ if (pwrindex[1] < 0) -+ pwrindex[1] = 0; -+ else if (pwrindex[1] > 63) -+ pwrindex[1] = 63; -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 1, -+ (u32) pwrindex[0], 32, &qdBm_pwrbuf[0]); -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 1, -+ (u32) pwrindex[1], 32, &qdBm_pwrbuf[1]); -+} -+ -+static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core) -+{ -+ int index; -+ u32 bbmult_scale; -+ u16 bbmult; -+ u16 tblentry; -+ -+ struct nphy_txiqcal_ladder ladder_lo[] = { -+ {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0}, -+ {25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5}, -+ {25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7} -+ }; -+ -+ struct nphy_txiqcal_ladder ladder_iq[] = { -+ {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0}, -+ {25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1}, -+ {100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7} -+ }; -+ -+ bbmult = (core == PHY_CORE_0) ? -+ ((pi->nphy_txcal_bbmult >> 8) & 0xff) : -+ (pi->nphy_txcal_bbmult & 0xff); -+ -+ for (index = 0; index < 18; index++) { -+ bbmult_scale = ladder_lo[index].percent * bbmult; -+ bbmult_scale /= 100; -+ -+ tblentry = -+ ((bbmult_scale & 0xff) << 8) | ladder_lo[index].g_env; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index, 16, -+ &tblentry); -+ -+ bbmult_scale = ladder_iq[index].percent * bbmult; -+ bbmult_scale /= 100; -+ -+ tblentry = -+ ((bbmult_scale & 0xff) << 8) | ladder_iq[index].g_env; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index + 32, -+ 16, &tblentry); -+ } -+} -+ -+static u8 wlc_phy_txpwr_idx_cur_get_nphy(struct brcms_phy *pi, u8 core) -+{ -+ u16 tmp; -+ tmp = read_phy_reg(pi, ((core == PHY_CORE_0) ? 0x1ed : 0x1ee)); -+ -+ tmp = (tmp & (0x7f << 8)) >> 8; -+ return (u8) tmp; -+} -+ -+static void -+wlc_phy_txpwr_idx_cur_set_nphy(struct brcms_phy *pi, u8 idx0, u8 idx1) -+{ -+ mod_phy_reg(pi, 0x1e7, (0x7f << 0), idx0); -+ -+ if (NREV_GT(pi->pubpi.phy_rev, 1)) -+ mod_phy_reg(pi, 0x222, (0xff << 0), idx1); -+} -+ -+static u16 wlc_phy_ipa_get_bbmult_nphy(struct brcms_phy *pi) -+{ -+ u16 m0m1; -+ -+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1); -+ -+ return m0m1; -+} -+ -+static void wlc_phy_ipa_set_bbmult_nphy(struct brcms_phy *pi, u8 m0, u8 m1) -+{ -+ u16 m0m1 = (u16) ((m0 << 8) | m1); -+ -+ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m0m1); -+ wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &m0m1); -+} -+ -+static void -+wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi, -+ struct nphy_papd_restore_state *state, u8 core) -+{ -+ s32 tone_freq; -+ u8 off_core; -+ u16 mixgain = 0; -+ -+ off_core = core ^ 0x1; -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 7) -+ || NREV_GE(pi->pubpi.phy_rev, 8)) -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 7), -+ wlc_phy_read_lpf_bw_ctl_nphy -+ (pi, -+ 0), 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if (pi->pubpi.radiorev == 5) -+ mixgain = (core == 0) ? 0x20 : 0x00; -+ else if ((pi->pubpi.radiorev == 7) -+ || (pi->pubpi.radiorev == 8)) -+ mixgain = 0x00; -+ else if ((pi->pubpi.radiorev <= 4) -+ || (pi->pubpi.radiorev == 6)) -+ mixgain = 0x00; -+ } else { -+ if ((pi->pubpi.radiorev == 4) || -+ (pi->pubpi.radiorev == 6)) -+ mixgain = 0x50; -+ else if ((pi->pubpi.radiorev == 3) -+ || (pi->pubpi.radiorev == 7) -+ || (pi->pubpi.radiorev == 8)) -+ mixgain = 0x0; -+ } -+ -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), -+ mixgain, (1 << core), 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ -+ wlc_phy_rfctrl_override_1tomany_nphy( -+ pi, -+ NPHY_REV7_RfctrlOverride_cmd_tx_pu, -+ 1, (1 << core), 0); -+ wlc_phy_rfctrl_override_1tomany_nphy( -+ pi, -+ NPHY_REV7_RfctrlOverride_cmd_tx_pu, -+ 0, (1 << off_core), 0); -+ -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), -+ 0, 0x3, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, -+ (1 << core), 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, -+ (1 << core), 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, -+ (1 << core), 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID2); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0, -+ (1 << core), 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1, -+ (1 << core), 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0, -+ (1 << core), 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1, -+ (1 << core), 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), -+ 0, (1 << core), 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0, -+ (1 << core), 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ -+ state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ? -+ 0xa6 : 0xa7); -+ state->afeoverride[core] = -+ read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5); -+ state->afectrl[off_core] = -+ read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa7 : 0xa6); -+ state->afeoverride[off_core] = -+ read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa5 : 0x8f); -+ -+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7), -+ (0x1 << 2), 0); -+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f : -+ 0xa5), (0x1 << 2), (0x1 << 2)); -+ -+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa7 : 0xa6), -+ (0x1 << 2), (0x1 << 2)); -+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa5 : -+ 0x8f), (0x1 << 2), (0x1 << 2)); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ state->pwrup[core] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TXRXCOUPLE_2G_PWRUP); -+ state->atten[core] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TXRXCOUPLE_2G_ATTEN); -+ state->pwrup[off_core] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, -+ TXRXCOUPLE_2G_PWRUP); -+ state->atten[off_core] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, -+ TXRXCOUPLE_2G_ATTEN); -+ -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TXRXCOUPLE_2G_PWRUP, 0xc); -+ -+ if ((pi->pubpi.radiorev == 3) || -+ (pi->pubpi.radiorev == 4) || -+ (pi->pubpi.radiorev == 6)) -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TXRXCOUPLE_2G_ATTEN, 0xf0); -+ else if (pi->pubpi.radiorev == 5) -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TXRXCOUPLE_2G_ATTEN, -+ (core == 0) ? 0xf7 : 0xf2); -+ else if ((pi->pubpi.radiorev == 7) -+ || (pi->pubpi.radiorev == 8)) -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TXRXCOUPLE_2G_ATTEN, 0xf0); -+ -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core, -+ TXRXCOUPLE_2G_PWRUP, 0x0); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core, -+ TXRXCOUPLE_2G_ATTEN, 0xff); -+ } else { -+ state->pwrup[core] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TXRXCOUPLE_5G_PWRUP); -+ state->atten[core] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TXRXCOUPLE_5G_ATTEN); -+ state->pwrup[off_core] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, -+ TXRXCOUPLE_5G_PWRUP); -+ state->atten[off_core] = -+ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, -+ TXRXCOUPLE_5G_ATTEN); -+ -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TXRXCOUPLE_5G_PWRUP, 0xc); -+ -+ if ((pi->pubpi.radiorev == 7) -+ || (pi->pubpi.radiorev == 8)) -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TXRXCOUPLE_5G_ATTEN, 0xf4); -+ -+ else -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TXRXCOUPLE_5G_ATTEN, 0xf0); -+ -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core, -+ TXRXCOUPLE_5G_PWRUP, 0x0); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core, -+ TXRXCOUPLE_5G_ATTEN, 0xff); -+ } -+ -+ tone_freq = 4000; -+ -+ wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x1 << 13), (1) << 13); -+ -+ mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_OFF) << 0); -+ -+ mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x1 << 13), (0) << 13); -+ -+ } else { -+ -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 0); -+ -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0, 0); -+ -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 0); -+ -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 1, 0x3, 0); -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0x3, 0); -+ -+ state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ? -+ 0xa6 : 0xa7); -+ state->afeoverride[core] = -+ read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5); -+ -+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7), -+ (0x1 << 0) | (0x1 << 1) | (0x1 << 2), 0); -+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f : -+ 0xa5), -+ (0x1 << 0) | -+ (0x1 << 1) | -+ (0x1 << 2), (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); -+ -+ state->vga_master[core] = -+ READ_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER); -+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, 0x2b); -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ state->fbmix[core] = -+ READ_RADIO_REG2(pi, RADIO_2056, RX, core, -+ TXFBMIX_G); -+ state->intpa_master[core] = -+ READ_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAG_MASTER); -+ -+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_G, -+ 0x03); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAG_MASTER, 0x04); -+ } else { -+ state->fbmix[core] = -+ READ_RADIO_REG2(pi, RADIO_2056, RX, core, -+ TXFBMIX_A); -+ state->intpa_master[core] = -+ READ_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAA_MASTER); -+ -+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_A, -+ 0x03); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAA_MASTER, 0x04); -+ -+ } -+ -+ tone_freq = 4000; -+ -+ wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 0), (1) << 0); -+ -+ mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 0), (0) << 0); -+ -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0); -+ } -+} -+ -+static void -+wlc_phy_papd_cal_cleanup_nphy(struct brcms_phy *pi, -+ struct nphy_papd_restore_state *state) -+{ -+ u8 core; -+ -+ wlc_phy_stopplayback_nphy(pi); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TXRXCOUPLE_2G_PWRUP, 0); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TXRXCOUPLE_2G_ATTEN, -+ state->atten[core]); -+ } else { -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TXRXCOUPLE_5G_PWRUP, 0); -+ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, -+ TXRXCOUPLE_5G_ATTEN, -+ state->atten[core]); -+ } -+ } -+ -+ if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 2), -+ 1, 0x3, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ else -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 2), -+ 0, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), -+ 0, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID2); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 0, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID2); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 0, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), 0, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID2); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0, 0x3, 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ -+ write_phy_reg(pi, (core == PHY_CORE_0) ? -+ 0xa6 : 0xa7, state->afectrl[core]); -+ write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : -+ 0xa5, state->afeoverride[core]); -+ } -+ -+ wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff, -+ (state->mm & 0xff)); -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 7) -+ || NREV_GE(pi->pubpi.phy_rev, 8)) -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, (0x1 << 7), 0, 0, -+ 1, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ } else { -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1); -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 0x3, 1); -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 1); -+ -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 0, 0x3, 1); -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 0, 0x3, 1); -+ -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ -+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, -+ state->vga_master[core]); -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, -+ TXFBMIX_G, state->fbmix[core]); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAG_MASTER, -+ state->intpa_master[core]); -+ } else { -+ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, -+ TXFBMIX_A, state->fbmix[core]); -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, -+ INTPAA_MASTER, -+ state->intpa_master[core]); -+ } -+ -+ write_phy_reg(pi, (core == PHY_CORE_0) ? -+ 0xa6 : 0xa7, state->afectrl[core]); -+ write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : -+ 0xa5, state->afeoverride[core]); -+ } -+ -+ wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff, -+ (state->mm & 0xff)); -+ -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 1); -+ } -+} -+ -+static void -+wlc_phy_a1_nphy(struct brcms_phy *pi, u8 core, u32 winsz, u32 start, -+ u32 end) -+{ -+ u32 *buf, *src, *dst, sz; -+ -+ sz = end - start + 1; -+ -+ buf = kmalloc(2 * sizeof(u32) * NPHY_PAPD_EPS_TBL_SIZE, GFP_ATOMIC); -+ if (NULL == buf) -+ return; -+ -+ src = buf; -+ dst = buf + NPHY_PAPD_EPS_TBL_SIZE; -+ -+ wlc_phy_table_read_nphy(pi, -+ (core == -+ PHY_CORE_0 ? NPHY_TBL_ID_EPSILONTBL0 : -+ NPHY_TBL_ID_EPSILONTBL1), -+ NPHY_PAPD_EPS_TBL_SIZE, 0, 32, src); -+ -+ do { -+ u32 phy_a1, phy_a2; -+ s32 phy_a3, phy_a4, phy_a5, phy_a6, phy_a7; -+ -+ phy_a1 = end - min(end, (winsz >> 1)); -+ phy_a2 = min_t(u32, NPHY_PAPD_EPS_TBL_SIZE - 1, -+ end + (winsz >> 1)); -+ phy_a3 = phy_a2 - phy_a1 + 1; -+ phy_a6 = 0; -+ phy_a7 = 0; -+ -+ do { -+ wlc_phy_papd_decode_epsilon(src[phy_a2], &phy_a4, -+ &phy_a5); -+ phy_a6 += phy_a4; -+ phy_a7 += phy_a5; -+ } while (phy_a2-- != phy_a1); -+ -+ phy_a6 /= phy_a3; -+ phy_a7 /= phy_a3; -+ dst[end] = ((u32) phy_a7 << 13) | ((u32) phy_a6 & 0x1fff); -+ } while (end-- != start); -+ -+ wlc_phy_table_write_nphy(pi, -+ (core == -+ PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 : -+ NPHY_TBL_ID_EPSILONTBL1, sz, start, 32, dst); -+ -+ kfree(buf); -+} -+ -+static void -+wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains, -+ enum phy_cal_mode cal_mode, u8 core) -+{ -+ u16 phy_a1, phy_a2, phy_a3; -+ u16 phy_a4, phy_a5; -+ bool phy_a6; -+ u8 phy_a7, m[2]; -+ u32 phy_a8 = 0; -+ struct nphy_txgains phy_a9; -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 3)) -+ return; -+ -+ phy_a7 = (core == PHY_CORE_0) ? 1 : 0; -+ -+ phy_a6 = ((cal_mode == CAL_GCTRL) -+ || (cal_mode == CAL_SOFT)) ? true : false; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ phy_a9 = wlc_phy_get_tx_gain_nphy(pi); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) -+ phy_a5 = ((phy_a9.txlpf[core] << 15) | -+ (phy_a9.txgm[core] << 12) | -+ (phy_a9.pga[core] << 8) | -+ (txgains->gains.pad[core] << 3) | -+ (phy_a9.ipa[core])); -+ else -+ phy_a5 = ((phy_a9.txlpf[core] << 15) | -+ (phy_a9.txgm[core] << 12) | -+ (txgains->gains.pga[core] << 8) | -+ (phy_a9.pad[core] << 3) | (phy_a9.ipa[core])); -+ -+ wlc_phy_rfctrl_override_1tomany_nphy( -+ pi, -+ NPHY_REV7_RfctrlOverride_cmd_txgain, -+ phy_a5, (1 << core), 0); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if ((pi->pubpi.radiorev <= 4) -+ || (pi->pubpi.radiorev == 6)) -+ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? -+ 60 : 79; -+ else -+ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? -+ 45 : 64; -+ } else { -+ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 75 : 107; -+ } -+ -+ m[phy_a7] = 0; -+ wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]); -+ -+ phy_a2 = 63; -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if ((pi->pubpi.radiorev == 4) -+ || (pi->pubpi.radiorev == 6)) { -+ phy_a1 = 30; -+ phy_a3 = 30; -+ } else { -+ phy_a1 = 25; -+ phy_a3 = 25; -+ } -+ } else { -+ if ((pi->pubpi.radiorev == 5) -+ || (pi->pubpi.radiorev == 7) -+ || (pi->pubpi.radiorev == 8)) { -+ phy_a1 = 25; -+ phy_a3 = 25; -+ } else { -+ phy_a1 = 35; -+ phy_a3 = 35; -+ } -+ } -+ -+ if (cal_mode == CAL_GCTRL) { -+ if ((pi->pubpi.radiorev == 5) -+ && (CHSPEC_IS2G(pi->radio_chanspec))) -+ phy_a1 = 55; -+ else if (((pi->pubpi.radiorev == 7) && -+ (CHSPEC_IS2G(pi->radio_chanspec))) || -+ ((pi->pubpi.radiorev == 8) && -+ (CHSPEC_IS2G(pi->radio_chanspec)))) -+ phy_a1 = 60; -+ else -+ phy_a1 = 63; -+ -+ } else if ((cal_mode != CAL_FULL) && (cal_mode != CAL_SOFT)) { -+ -+ phy_a1 = 35; -+ phy_a3 = 35; -+ } -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 0), (1) << 0); -+ -+ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 0), (0) << 0); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x1 << 13), (1) << 13); -+ -+ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x1 << 13), (0) << 13); -+ -+ write_phy_reg(pi, 0x2a1, 0x80); -+ write_phy_reg(pi, 0x2a2, 0x100); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x7 << 4), (11) << 4); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x7 << 8), (11) << 8); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x7 << 0), (0x3) << 0); -+ -+ write_phy_reg(pi, 0x2e5, 0x20); -+ -+ mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0); -+ -+ mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0); -+ -+ mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8); -+ -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), -+ 1, ((core == 0) ? 1 : 2), 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), -+ 0, ((core == 0) ? 2 : 1), 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ -+ write_phy_reg(pi, 0x2be, 1); -+ SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000); -+ -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), -+ 0, 0x3, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ -+ wlc_phy_table_write_nphy(pi, -+ (core == -+ PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 -+ : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3, -+ 32, &phy_a8); -+ -+ if (cal_mode != CAL_GCTRL) { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) -+ wlc_phy_a1_nphy(pi, core, 5, 0, 35); -+ } -+ -+ wlc_phy_rfctrl_override_1tomany_nphy( -+ pi, -+ NPHY_REV7_RfctrlOverride_cmd_txgain, -+ phy_a5, (1 << core), 1); -+ -+ } else { -+ -+ if (txgains) { -+ if (txgains->useindex) { -+ phy_a4 = 15 - ((txgains->index) >> 3); -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if (NREV_GE(pi->pubpi.phy_rev, 6)) -+ phy_a5 = 0x00f7 | (phy_a4 << 8); -+ -+ else -+ if (NREV_IS(pi->pubpi.phy_rev, 5)) -+ phy_a5 = 0x10f7 | (phy_a4 << 8); -+ else -+ phy_a5 = 0x50f7 | (phy_a4 << 8); -+ } else { -+ phy_a5 = 0x70f7 | (phy_a4 << 8); -+ } -+ wlc_phy_rfctrl_override_nphy(pi, -+ (0x1 << 13), -+ phy_a5, -+ (1 << core), 0); -+ } else { -+ wlc_phy_rfctrl_override_nphy(pi, -+ (0x1 << 13), -+ 0x5bf7, -+ (1 << core), 0); -+ } -+ } -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) -+ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 45 : 64; -+ else -+ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 75 : 107; -+ -+ m[phy_a7] = 0; -+ wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]); -+ -+ phy_a2 = 63; -+ -+ if (cal_mode == CAL_FULL) { -+ phy_a1 = 25; -+ phy_a3 = 25; -+ } else if (cal_mode == CAL_SOFT) { -+ phy_a1 = 25; -+ phy_a3 = 25; -+ } else if (cal_mode == CAL_GCTRL) { -+ phy_a1 = 63; -+ phy_a3 = 25; -+ } else { -+ -+ phy_a1 = 25; -+ phy_a3 = 25; -+ } -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 0), (1) << 0); -+ -+ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 0), (0) << 0); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 6)) { -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x1 << 13), (1) << 13); -+ -+ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x1 << 13), (0) << 13); -+ -+ write_phy_reg(pi, 0x2a1, 0x20); -+ write_phy_reg(pi, 0x2a2, 0x60); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0xf << 4), (9) << 4); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0xf << 8), (9) << 8); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0xf << 0), (0x2) << 0); -+ -+ write_phy_reg(pi, 0x2e5, 0x20); -+ } else { -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x1 << 11), (1) << 11); -+ -+ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x1 << 11), (0) << 11); -+ -+ write_phy_reg(pi, 0x2a1, 0x80); -+ write_phy_reg(pi, 0x2a2, 0x600); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x7 << 4), (0) << 4); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x7 << 8), (0) << 8); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x7 << 0), (0x3) << 0); -+ -+ mod_phy_reg(pi, 0x2a0, (0x3f << 8), (0x20) << 8); -+ -+ } -+ -+ mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0); -+ -+ mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0); -+ -+ mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8); -+ -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0x3, 0); -+ -+ write_phy_reg(pi, 0x2be, 1); -+ SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000); -+ -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0); -+ -+ wlc_phy_table_write_nphy(pi, -+ (core == -+ PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 -+ : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3, -+ 32, &phy_a8); -+ -+ if (cal_mode != CAL_GCTRL) -+ wlc_phy_a1_nphy(pi, core, 5, 0, 40); -+ } -+} -+ -+static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core) -+{ -+ int phy_a1; -+ int phy_a2; -+ bool phy_a3; -+ struct nphy_ipa_txcalgains phy_a4; -+ bool phy_a5 = false; -+ bool phy_a6 = true; -+ s32 phy_a7, phy_a8; -+ u32 phy_a9; -+ int phy_a10; -+ bool phy_a11 = false; -+ int phy_a12; -+ u8 phy_a13 = 0; -+ u8 phy_a14; -+ u8 *phy_a15 = NULL; -+ -+ phy_a4.useindex = true; -+ phy_a12 = start_gain; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ phy_a2 = 20; -+ phy_a1 = 1; -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if (pi->pubpi.radiorev == 5) { -+ -+ phy_a15 = pad_gain_codes_used_2057rev5; -+ phy_a13 = -+ sizeof(pad_gain_codes_used_2057rev5) / -+ sizeof(pad_gain_codes_used_2057rev5 -+ [0]) - 1; -+ -+ } else if ((pi->pubpi.radiorev == 7) -+ || (pi->pubpi.radiorev == 8)) { -+ -+ phy_a15 = pad_gain_codes_used_2057rev7; -+ phy_a13 = -+ sizeof(pad_gain_codes_used_2057rev7) / -+ sizeof(pad_gain_codes_used_2057rev7 -+ [0]) - 1; -+ -+ } else { -+ -+ phy_a15 = pad_all_gain_codes_2057; -+ phy_a13 = sizeof(pad_all_gain_codes_2057) / -+ sizeof(pad_all_gain_codes_2057[0]) - -+ 1; -+ } -+ -+ } else { -+ -+ phy_a15 = pga_all_gain_codes_2057; -+ phy_a13 = sizeof(pga_all_gain_codes_2057) / -+ sizeof(pga_all_gain_codes_2057[0]) - 1; -+ } -+ -+ phy_a14 = 0; -+ -+ for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) { -+ if (CHSPEC_IS2G(pi->radio_chanspec)) -+ phy_a4.gains.pad[core] = -+ (u16) phy_a15[phy_a12]; -+ else -+ phy_a4.gains.pga[core] = -+ (u16) phy_a15[phy_a12]; -+ -+ wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core); -+ -+ wlc_phy_table_read_nphy(pi, -+ (core == -+ PHY_CORE_0 ? -+ NPHY_TBL_ID_EPSILONTBL0 : -+ NPHY_TBL_ID_EPSILONTBL1), 1, -+ 63, 32, &phy_a9); -+ -+ wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8); -+ -+ phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) || -+ (phy_a8 == 4095) || (phy_a8 == -4096)); -+ -+ if (!phy_a6 && (phy_a3 != phy_a5)) { -+ if (!phy_a3) -+ phy_a12 -= (u8) phy_a1; -+ -+ phy_a11 = true; -+ break; -+ } -+ -+ if (phy_a3) -+ phy_a12 += (u8) phy_a1; -+ else -+ phy_a12 -= (u8) phy_a1; -+ -+ if ((phy_a12 < phy_a14) || (phy_a12 > phy_a13)) { -+ if (phy_a12 < phy_a14) -+ phy_a12 = phy_a14; -+ else -+ phy_a12 = phy_a13; -+ -+ phy_a11 = true; -+ break; -+ } -+ -+ phy_a6 = false; -+ phy_a5 = phy_a3; -+ } -+ -+ } else { -+ phy_a2 = 10; -+ phy_a1 = 8; -+ for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) { -+ phy_a4.index = (u8) phy_a12; -+ wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core); -+ -+ wlc_phy_table_read_nphy(pi, -+ (core == -+ PHY_CORE_0 ? -+ NPHY_TBL_ID_EPSILONTBL0 : -+ NPHY_TBL_ID_EPSILONTBL1), 1, -+ 63, 32, &phy_a9); -+ -+ wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8); -+ -+ phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) || -+ (phy_a8 == 4095) || (phy_a8 == -4096)); -+ -+ if (!phy_a6 && (phy_a3 != phy_a5)) { -+ if (!phy_a3) -+ phy_a12 -= (u8) phy_a1; -+ -+ phy_a11 = true; -+ break; -+ } -+ -+ if (phy_a3) -+ phy_a12 += (u8) phy_a1; -+ else -+ phy_a12 -= (u8) phy_a1; -+ -+ if ((phy_a12 < 0) || (phy_a12 > 127)) { -+ if (phy_a12 < 0) -+ phy_a12 = 0; -+ else -+ phy_a12 = 127; -+ -+ phy_a11 = true; -+ break; -+ } -+ -+ phy_a6 = false; -+ phy_a5 = phy_a3; -+ } -+ -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ return (u8) phy_a15[phy_a12]; -+ else -+ return (u8) phy_a12; -+ -+} -+ -+static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal) -+{ -+ struct nphy_ipa_txcalgains phy_b1[2]; -+ struct nphy_papd_restore_state phy_b2; -+ bool phy_b3; -+ u8 phy_b4; -+ u8 phy_b5; -+ s16 phy_b6, phy_b7, phy_b8; -+ u16 phy_b9; -+ s16 phy_b10, phy_b11, phy_b12; -+ -+ phy_b11 = 0; -+ phy_b12 = 0; -+ phy_b7 = 0; -+ phy_b8 = 0; -+ phy_b6 = 0; -+ -+ if (pi->nphy_papd_skip == 1) -+ return; -+ -+ phy_b3 = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); -+ if (!phy_b3) -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ pi->nphy_force_papd_cal = false; -+ -+ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) -+ pi->nphy_papd_tx_gain_at_last_cal[phy_b5] = -+ wlc_phy_txpwr_idx_cur_get_nphy(pi, phy_b5); -+ -+ pi->nphy_papd_last_cal = pi->sh->now; -+ pi->nphy_papd_recal_counter++; -+ -+ phy_b4 = pi->nphy_txpwrctrl; -+ wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL0, 64, 0, 32, -+ nphy_papd_scaltbl); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL1, 64, 0, 32, -+ nphy_papd_scaltbl); -+ -+ phy_b9 = read_phy_reg(pi, 0x01); -+ mod_phy_reg(pi, 0x01, (0x1 << 15), 0); -+ -+ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) { -+ s32 i, val = 0; -+ for (i = 0; i < 64; i++) -+ wlc_phy_table_write_nphy(pi, -+ ((phy_b5 == -+ PHY_CORE_0) ? -+ NPHY_TBL_ID_EPSILONTBL0 : -+ NPHY_TBL_ID_EPSILONTBL1), 1, -+ i, 32, &val); -+ } -+ -+ wlc_phy_ipa_restore_tx_digi_filts_nphy(pi); -+ -+ phy_b2.mm = wlc_phy_ipa_get_bbmult_nphy(pi); -+ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) { -+ wlc_phy_papd_cal_setup_nphy(pi, &phy_b2, phy_b5); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if ((pi->pubpi.radiorev == 3) -+ || (pi->pubpi.radiorev == 4) -+ || (pi->pubpi.radiorev == 6)) { -+ pi->nphy_papd_cal_gain_index[phy_b5] = -+ 23; -+ } else if (pi->pubpi.radiorev == 5) { -+ pi->nphy_papd_cal_gain_index[phy_b5] = -+ 0; -+ pi->nphy_papd_cal_gain_index[phy_b5] = -+ wlc_phy_a3_nphy( -+ pi, -+ pi-> -+ nphy_papd_cal_gain_index -+ [phy_b5], -+ phy_b5); -+ -+ } else if ((pi->pubpi.radiorev == 7) -+ || (pi->pubpi.radiorev == 8)) { -+ -+ pi->nphy_papd_cal_gain_index[phy_b5] = -+ 0; -+ pi->nphy_papd_cal_gain_index[phy_b5] = -+ wlc_phy_a3_nphy( -+ pi, -+ pi-> -+ nphy_papd_cal_gain_index -+ [phy_b5], -+ phy_b5); -+ -+ } -+ -+ phy_b1[phy_b5].gains.pad[phy_b5] = -+ pi->nphy_papd_cal_gain_index[phy_b5]; -+ -+ } else { -+ pi->nphy_papd_cal_gain_index[phy_b5] = 0; -+ pi->nphy_papd_cal_gain_index[phy_b5] = -+ wlc_phy_a3_nphy( -+ pi, -+ pi-> -+ nphy_papd_cal_gain_index -+ [phy_b5], phy_b5); -+ phy_b1[phy_b5].gains.pga[phy_b5] = -+ pi->nphy_papd_cal_gain_index[phy_b5]; -+ } -+ } else { -+ phy_b1[phy_b5].useindex = true; -+ phy_b1[phy_b5].index = 16; -+ phy_b1[phy_b5].index = -+ wlc_phy_a3_nphy(pi, phy_b1[phy_b5].index, -+ phy_b5); -+ -+ pi->nphy_papd_cal_gain_index[phy_b5] = -+ 15 - ((phy_b1[phy_b5].index) >> 3); -+ } -+ -+ switch (pi->nphy_papd_cal_type) { -+ case 0: -+ wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_FULL, phy_b5); -+ break; -+ case 1: -+ wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_SOFT, phy_b5); -+ break; -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2); -+ } -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 7)) -+ wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2); -+ -+ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) { -+ int eps_offset = 0; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ if (pi->pubpi.radiorev == 3) -+ eps_offset = -2; -+ else if (pi->pubpi.radiorev == 5) -+ eps_offset = 3; -+ else -+ eps_offset = -1; -+ } else { -+ eps_offset = 2; -+ } -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ phy_b8 = phy_b1[phy_b5].gains.pad[phy_b5]; -+ phy_b10 = 0; -+ if ((pi->pubpi.radiorev == 3) || -+ (pi->pubpi.radiorev == 4) || -+ (pi->pubpi.radiorev == 6)) { -+ phy_b12 = -( -+ nphy_papd_padgain_dlt_2g_2057rev3n4 -+ [phy_b8] + 1) / 2; -+ phy_b10 = -1; -+ } else if (pi->pubpi.radiorev == 5) { -+ phy_b12 = -( -+ nphy_papd_padgain_dlt_2g_2057rev5 -+ [phy_b8] + 1) / 2; -+ } else if ((pi->pubpi.radiorev == 7) || -+ (pi->pubpi.radiorev == 8)) { -+ phy_b12 = -( -+ nphy_papd_padgain_dlt_2g_2057rev7 -+ [phy_b8] + 1) / 2; -+ } -+ } else { -+ phy_b7 = phy_b1[phy_b5].gains.pga[phy_b5]; -+ if ((pi->pubpi.radiorev == 3) || -+ (pi->pubpi.radiorev == 4) || -+ (pi->pubpi.radiorev == 6)) -+ phy_b11 = -+ -(nphy_papd_pgagain_dlt_5g_2057 -+ [phy_b7] -+ + 1) / 2; -+ else if ((pi->pubpi.radiorev == 7) -+ || (pi->pubpi.radiorev == 8)) -+ phy_b11 = -( -+ nphy_papd_pgagain_dlt_5g_2057rev7 -+ [phy_b7] + 1) / 2; -+ -+ phy_b10 = -9; -+ } -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) -+ phy_b6 = -+ -60 + 27 + eps_offset + phy_b12 + -+ phy_b10; -+ else -+ phy_b6 = -+ -60 + 27 + eps_offset + phy_b11 + -+ phy_b10; -+ -+ mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 : -+ 0x29c, (0x1ff << 7), (phy_b6) << 7); -+ -+ pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6; -+ } else { -+ if (NREV_LT(pi->pubpi.phy_rev, 5)) -+ eps_offset = 4; -+ else -+ eps_offset = 2; -+ -+ phy_b7 = 15 - ((phy_b1[phy_b5].index) >> 3); -+ -+ if (CHSPEC_IS2G(pi->radio_chanspec)) { -+ phy_b11 = -+ -(nphy_papd_pga_gain_delta_ipa_2g[ -+ phy_b7] + -+ 1) / 2; -+ phy_b10 = 0; -+ } else { -+ phy_b11 = -+ -(nphy_papd_pga_gain_delta_ipa_5g[ -+ phy_b7] + -+ 1) / 2; -+ phy_b10 = -9; -+ } -+ -+ phy_b6 = -60 + 27 + eps_offset + phy_b11 + phy_b10; -+ -+ mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 : -+ 0x29c, (0x1ff << 7), (phy_b6) << 7); -+ -+ pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6; -+ } -+ } -+ -+ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0); -+ -+ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 6)) { -+ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x1 << 13), (0) << 13); -+ -+ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x1 << 13), (0) << 13); -+ -+ } else { -+ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x1 << 11), (0) << 11); -+ -+ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 : -+ 0x2a4, (0x1 << 11), (0) << 11); -+ -+ } -+ pi->nphy_papdcomp = NPHY_PAPD_COMP_ON; -+ -+ write_phy_reg(pi, 0x01, phy_b9); -+ -+ wlc_phy_ipa_set_tx_digi_filts_nphy(pi); -+ -+ wlc_phy_txpwrctrl_enable_nphy(pi, phy_b4); -+ if (phy_b4 == PHY_TPC_HW_OFF) { -+ wlc_phy_txpwr_index_nphy(pi, (1 << 0), -+ (s8) (pi->nphy_txpwrindex[0]. -+ index_internal), false); -+ wlc_phy_txpwr_index_nphy(pi, (1 << 1), -+ (s8) (pi->nphy_txpwrindex[1]. -+ index_internal), false); -+ } -+ -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+ -+ if (!phy_b3) -+ wlapi_enable_mac(pi->sh->physhim); -+} -+ -+void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype) -+{ -+ struct nphy_txgains target_gain; -+ u8 tx_pwr_ctrl_state; -+ bool fullcal = true; -+ bool restore_tx_gain = false; -+ bool mphase; -+ -+ if (PHY_MUTED(pi)) -+ return; -+ -+ if (caltype == PHY_PERICAL_AUTO) -+ fullcal = (pi->radio_chanspec != pi->nphy_txiqlocal_chanspec); -+ else if (caltype == PHY_PERICAL_PARTIAL) -+ fullcal = false; -+ -+ if (pi->cal_type_override != PHY_PERICAL_AUTO) -+ fullcal = -+ (pi->cal_type_override == -+ PHY_PERICAL_FULL) ? true : false; -+ -+ if ((pi->mphase_cal_phase_id > MPHASE_CAL_STATE_INIT)) { -+ if (pi->nphy_txiqlocal_chanspec != pi->radio_chanspec) -+ wlc_phy_cal_perical_mphase_restart(pi); -+ } -+ -+ if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_RXCAL)) -+ wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000); -+ -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ -+ wlc_phyreg_enter((struct brcms_phy_pub *) pi); -+ -+ if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_IDLE) || -+ (pi->mphase_cal_phase_id == MPHASE_CAL_STATE_INIT)) { -+ pi->nphy_cal_orig_pwr_idx[0] = -+ (u8) ((read_phy_reg(pi, 0x1ed) >> 8) & 0x7f); -+ pi->nphy_cal_orig_pwr_idx[1] = -+ (u8) ((read_phy_reg(pi, 0x1ee) >> 8) & 0x7f); -+ -+ if (pi->nphy_txpwrctrl != PHY_TPC_HW_OFF) { -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, -+ 0x110, 16, -+ pi->nphy_cal_orig_tx_gain); -+ } else { -+ pi->nphy_cal_orig_tx_gain[0] = 0; -+ pi->nphy_cal_orig_tx_gain[1] = 0; -+ } -+ } -+ target_gain = wlc_phy_get_tx_gain_nphy(pi); -+ tx_pwr_ctrl_state = pi->nphy_txpwrctrl; -+ wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF); -+ -+ if (pi->antsel_type == ANTSEL_2x3) -+ wlc_phy_antsel_init((struct brcms_phy_pub *) pi, true); -+ -+ mphase = (pi->mphase_cal_phase_id != MPHASE_CAL_STATE_IDLE); -+ if (!mphase) { -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ wlc_phy_precal_txgain_nphy(pi); -+ pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi); -+ restore_tx_gain = true; -+ -+ target_gain = pi->nphy_cal_target_gain; -+ } -+ if (0 == -+ wlc_phy_cal_txiqlo_nphy(pi, target_gain, fullcal, -+ mphase)) { -+ if (PHY_IPA(pi)) -+ wlc_phy_a4(pi, true); -+ -+ wlc_phyreg_exit((struct brcms_phy_pub *) pi); -+ wlapi_enable_mac(pi->sh->physhim); -+ wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, -+ 10000); -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ wlc_phyreg_enter((struct brcms_phy_pub *) pi); -+ -+ if (0 == wlc_phy_cal_rxiq_nphy(pi, target_gain, -+ (pi->first_cal_after_assoc || -+ (pi->cal_type_override == -+ PHY_PERICAL_FULL)) ? 2 : 0, false)) { -+ wlc_phy_savecal_nphy(pi); -+ -+ wlc_phy_txpwrctrl_coeff_setup_nphy(pi); -+ -+ pi->nphy_perical_last = pi->sh->now; -+ } -+ } -+ if (caltype != PHY_PERICAL_AUTO) -+ wlc_phy_rssi_cal_nphy(pi); -+ -+ if (pi->first_cal_after_assoc -+ || (pi->cal_type_override == PHY_PERICAL_FULL)) { -+ pi->first_cal_after_assoc = false; -+ wlc_phy_txpwrctrl_idle_tssi_nphy(pi); -+ wlc_phy_txpwrctrl_pwr_setup_nphy(pi); -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) -+ wlc_phy_radio205x_vcocal_nphy(pi); -+ } else { -+ switch (pi->mphase_cal_phase_id) { -+ case MPHASE_CAL_STATE_INIT: -+ pi->nphy_perical_last = pi->sh->now; -+ pi->nphy_txiqlocal_chanspec = pi->radio_chanspec; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) -+ wlc_phy_precal_txgain_nphy(pi); -+ -+ pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi); -+ pi->mphase_cal_phase_id++; -+ break; -+ -+ case MPHASE_CAL_STATE_TXPHASE0: -+ case MPHASE_CAL_STATE_TXPHASE1: -+ case MPHASE_CAL_STATE_TXPHASE2: -+ case MPHASE_CAL_STATE_TXPHASE3: -+ case MPHASE_CAL_STATE_TXPHASE4: -+ case MPHASE_CAL_STATE_TXPHASE5: -+ if ((pi->radar_percal_mask & 0x10) != 0) -+ pi->nphy_rxcal_active = true; -+ -+ if (wlc_phy_cal_txiqlo_nphy -+ (pi, pi->nphy_cal_target_gain, fullcal, -+ true) != 0) { -+ -+ wlc_phy_cal_perical_mphase_reset(pi); -+ break; -+ } -+ -+ if (NREV_LE(pi->pubpi.phy_rev, 2) && -+ (pi->mphase_cal_phase_id == -+ MPHASE_CAL_STATE_TXPHASE4)) -+ pi->mphase_cal_phase_id += 2; -+ else -+ pi->mphase_cal_phase_id++; -+ break; -+ -+ case MPHASE_CAL_STATE_PAPDCAL: -+ if ((pi->radar_percal_mask & 0x2) != 0) -+ pi->nphy_rxcal_active = true; -+ -+ if (PHY_IPA(pi)) -+ wlc_phy_a4(pi, true); -+ -+ pi->mphase_cal_phase_id++; -+ break; -+ -+ case MPHASE_CAL_STATE_RXCAL: -+ if ((pi->radar_percal_mask & 0x1) != 0) -+ pi->nphy_rxcal_active = true; -+ if (wlc_phy_cal_rxiq_nphy(pi, target_gain, -+ (pi->first_cal_after_assoc || -+ (pi->cal_type_override == -+ PHY_PERICAL_FULL)) ? 2 : 0, -+ false) == 0) -+ wlc_phy_savecal_nphy(pi); -+ -+ pi->mphase_cal_phase_id++; -+ break; -+ -+ case MPHASE_CAL_STATE_RSSICAL: -+ if ((pi->radar_percal_mask & 0x4) != 0) -+ pi->nphy_rxcal_active = true; -+ wlc_phy_txpwrctrl_coeff_setup_nphy(pi); -+ wlc_phy_rssi_cal_nphy(pi); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) -+ wlc_phy_radio205x_vcocal_nphy(pi); -+ -+ restore_tx_gain = true; -+ -+ if (pi->first_cal_after_assoc) -+ pi->mphase_cal_phase_id++; -+ else -+ wlc_phy_cal_perical_mphase_reset(pi); -+ -+ break; -+ -+ case MPHASE_CAL_STATE_IDLETSSI: -+ if ((pi->radar_percal_mask & 0x8) != 0) -+ pi->nphy_rxcal_active = true; -+ -+ if (pi->first_cal_after_assoc) { -+ pi->first_cal_after_assoc = false; -+ wlc_phy_txpwrctrl_idle_tssi_nphy(pi); -+ wlc_phy_txpwrctrl_pwr_setup_nphy(pi); -+ } -+ -+ wlc_phy_cal_perical_mphase_reset(pi); -+ break; -+ -+ default: -+ wlc_phy_cal_perical_mphase_reset(pi); -+ break; -+ } -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ if (restore_tx_gain) { -+ if (tx_pwr_ctrl_state != PHY_TPC_HW_OFF) { -+ -+ wlc_phy_txpwr_index_nphy(pi, 1, -+ pi-> -+ nphy_cal_orig_pwr_idx -+ [0], false); -+ wlc_phy_txpwr_index_nphy(pi, 2, -+ pi-> -+ nphy_cal_orig_pwr_idx -+ [1], false); -+ -+ pi->nphy_txpwrindex[0].index = -1; -+ pi->nphy_txpwrindex[1].index = -1; -+ } else { -+ wlc_phy_txpwr_index_nphy(pi, (1 << 0), -+ (s8) (pi-> -+ nphy_txpwrindex -+ [0]. -+ index_internal), -+ false); -+ wlc_phy_txpwr_index_nphy(pi, (1 << 1), -+ (s8) (pi-> -+ nphy_txpwrindex -+ [1]. -+ index_internal), -+ false); -+ } -+ } -+ } -+ -+ wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state); -+ wlc_phyreg_exit((struct brcms_phy_pub *) pi); -+ wlapi_enable_mac(pi->sh->physhim); -+} -+ -+int -+wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, -+ bool fullcal, bool mphase) -+{ -+ u16 val; -+ u16 tbl_buf[11]; -+ u8 cal_cnt; -+ u16 cal_cmd; -+ u8 num_cals, max_cal_cmds; -+ u16 core_no, cal_type; -+ u16 diq_start = 0; -+ u8 phy_bw; -+ u16 max_val; -+ u16 tone_freq; -+ u16 gain_save[2]; -+ u16 cal_gain[2]; -+ struct nphy_iqcal_params cal_params[2]; -+ u32 tbl_len; -+ void *tbl_ptr; -+ bool ladder_updated[2]; -+ u8 mphase_cal_lastphase = 0; -+ int bcmerror = 0; -+ bool phyhang_avoid_state = false; -+ -+ u16 tbl_tx_iqlo_cal_loft_ladder_20[] = { -+ 0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901, -+ 0x1902, -+ 0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607, -+ 0x6407 -+ }; -+ -+ u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = { -+ 0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400, -+ 0x3200, -+ 0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406, -+ 0x6407 -+ }; -+ -+ u16 tbl_tx_iqlo_cal_loft_ladder_40[] = { -+ 0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201, -+ 0x1202, -+ 0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207, -+ 0x4707 -+ }; -+ -+ u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = { -+ 0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900, -+ 0x2300, -+ 0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706, -+ 0x4707 -+ }; -+ -+ u16 tbl_tx_iqlo_cal_startcoefs[] = { -+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, -+ 0x0000 -+ }; -+ -+ u16 tbl_tx_iqlo_cal_cmds_fullcal[] = { -+ 0x8123, 0x8264, 0x8086, 0x8245, 0x8056, -+ 0x9123, 0x9264, 0x9086, 0x9245, 0x9056 -+ }; -+ -+ u16 tbl_tx_iqlo_cal_cmds_recal[] = { -+ 0x8101, 0x8253, 0x8053, 0x8234, 0x8034, -+ 0x9101, 0x9253, 0x9053, 0x9234, 0x9034 -+ }; -+ -+ u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = { -+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, -+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, -+ 0x0000 -+ }; -+ -+ u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { -+ 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234, -+ 0x9434, 0x9334, 0x9084, 0x9267, 0x9056, 0x9234 -+ }; -+ -+ u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = { -+ 0x8423, 0x8323, 0x8073, 0x8256, 0x8045, 0x8223, -+ 0x9423, 0x9323, 0x9073, 0x9256, 0x9045, 0x9223 -+ }; -+ -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 4)) { -+ phyhang_avoid_state = pi->phyhang_avoid; -+ pi->phyhang_avoid = false; -+ } -+ -+ if (CHSPEC_IS40(pi->radio_chanspec)) -+ phy_bw = 40; -+ else -+ phy_bw = 20; -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save); -+ -+ for (core_no = 0; core_no <= 1; core_no++) { -+ wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain, -+ &cal_params[core_no]); -+ cal_gain[core_no] = cal_params[core_no].cal_gain; -+ } -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain); -+ -+ wlc_phy_txcal_radio_setup_nphy(pi); -+ -+ wlc_phy_txcal_physetup_nphy(pi); -+ -+ ladder_updated[0] = ladder_updated[1] = false; -+ if (!(NREV_GE(pi->pubpi.phy_rev, 6) || -+ (NREV_IS(pi->pubpi.phy_rev, 5) && PHY_IPA(pi) -+ && (CHSPEC_IS2G(pi->radio_chanspec))))) { -+ -+ if (phy_bw == 40) { -+ tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_40; -+ tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_40); -+ } else { -+ tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_20; -+ tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_20); -+ } -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 0, -+ 16, tbl_ptr); -+ -+ if (phy_bw == 40) { -+ tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_40; -+ tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_40); -+ } else { -+ tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_20; -+ tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_20); -+ } -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 32, -+ 16, tbl_ptr); -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ write_phy_reg(pi, 0xc2, 0x8ad9); -+ else -+ write_phy_reg(pi, 0xc2, 0x8aa9); -+ -+ max_val = 250; -+ tone_freq = (phy_bw == 20) ? 2500 : 5000; -+ -+ if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) { -+ wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff, 0, 1, 0, false); -+ bcmerror = 0; -+ } else { -+ bcmerror = -+ wlc_phy_tx_tone_nphy(pi, tone_freq, max_val, 1, 0, -+ false); -+ } -+ -+ if (bcmerror == 0) { -+ -+ if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) { -+ tbl_ptr = pi->mphase_txcal_bestcoeffs; -+ tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs); -+ if (NREV_LT(pi->pubpi.phy_rev, 3)) -+ tbl_len -= 2; -+ } else { -+ if ((!fullcal) && (pi->nphy_txiqlocal_coeffsvalid)) { -+ -+ tbl_ptr = pi->nphy_txiqlocal_bestc; -+ tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc); -+ if (NREV_LT(pi->pubpi.phy_rev, 3)) -+ tbl_len -= 2; -+ } else { -+ -+ fullcal = true; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ tbl_ptr = -+ tbl_tx_iqlo_cal_startcoefs_nphyrev3; -+ tbl_len = ARRAY_SIZE( -+ tbl_tx_iqlo_cal_startcoefs_nphyrev3); -+ } else { -+ tbl_ptr = tbl_tx_iqlo_cal_startcoefs; -+ tbl_len = ARRAY_SIZE( -+ tbl_tx_iqlo_cal_startcoefs); -+ } -+ } -+ } -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 64, -+ 16, tbl_ptr); -+ -+ if (fullcal) { -+ max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ? -+ ARRAY_SIZE( -+ tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3) : -+ ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal); -+ } else { -+ max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ? -+ ARRAY_SIZE( -+ tbl_tx_iqlo_cal_cmds_recal_nphyrev3) : -+ ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal); -+ } -+ -+ if (mphase) { -+ cal_cnt = pi->mphase_txcal_cmdidx; -+ if ((cal_cnt + pi->mphase_txcal_numcmds) < max_cal_cmds) -+ num_cals = cal_cnt + pi->mphase_txcal_numcmds; -+ else -+ num_cals = max_cal_cmds; -+ } else { -+ cal_cnt = 0; -+ num_cals = max_cal_cmds; -+ } -+ -+ for (; cal_cnt < num_cals; cal_cnt++) { -+ -+ if (fullcal) { -+ cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ? -+ tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3 -+ [cal_cnt] : -+ tbl_tx_iqlo_cal_cmds_fullcal[cal_cnt]; -+ } else { -+ cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ? -+ tbl_tx_iqlo_cal_cmds_recal_nphyrev3[ -+ cal_cnt] -+ : tbl_tx_iqlo_cal_cmds_recal[cal_cnt]; -+ } -+ -+ core_no = ((cal_cmd & 0x3000) >> 12); -+ cal_type = ((cal_cmd & 0x0F00) >> 8); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 6) || -+ (NREV_IS(pi->pubpi.phy_rev, 5) && -+ PHY_IPA(pi) -+ && (CHSPEC_IS2G(pi->radio_chanspec)))) { -+ if (!ladder_updated[core_no]) { -+ wlc_phy_update_txcal_ladder_nphy( -+ pi, -+ core_no); -+ ladder_updated[core_no] = true; -+ } -+ } -+ -+ val = -+ (cal_params[core_no]. -+ ncorr[cal_type] << 8) | NPHY_N_GCTL; -+ write_phy_reg(pi, 0xc1, val); -+ -+ if ((cal_type == 1) || (cal_type == 3) -+ || (cal_type == 4)) { -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, -+ 1, 69 + core_no, 16, -+ tbl_buf); -+ -+ diq_start = tbl_buf[0]; -+ -+ tbl_buf[0] = 0; -+ wlc_phy_table_write_nphy(pi, -+ NPHY_TBL_ID_IQLOCAL, 1, -+ 69 + core_no, 16, -+ tbl_buf); -+ } -+ -+ write_phy_reg(pi, 0xc0, cal_cmd); -+ -+ SPINWAIT(((read_phy_reg(pi, 0xc0) & 0xc000) != 0), -+ 20000); -+ if (WARN(read_phy_reg(pi, 0xc0) & 0xc000, -+ "HW error: txiq calib")) -+ return -EIO; -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, -+ tbl_len, 96, 16, tbl_buf); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, -+ tbl_len, 64, 16, tbl_buf); -+ -+ if ((cal_type == 1) || (cal_type == 3) -+ || (cal_type == 4)) { -+ -+ tbl_buf[0] = diq_start; -+ -+ } -+ -+ } -+ -+ if (mphase) { -+ pi->mphase_txcal_cmdidx = num_cals; -+ if (pi->mphase_txcal_cmdidx >= max_cal_cmds) -+ pi->mphase_txcal_cmdidx = 0; -+ } -+ -+ mphase_cal_lastphase = -+ (NREV_LE(pi->pubpi.phy_rev, 2)) ? -+ MPHASE_CAL_STATE_TXPHASE4 : MPHASE_CAL_STATE_TXPHASE5; -+ -+ if (!mphase -+ || (pi->mphase_cal_phase_id == mphase_cal_lastphase)) { -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 96, -+ 16, tbl_buf); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, -+ 16, tbl_buf); -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 2)) { -+ -+ tbl_buf[0] = 0; -+ tbl_buf[1] = 0; -+ tbl_buf[2] = 0; -+ tbl_buf[3] = 0; -+ -+ } -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, -+ 16, tbl_buf); -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 101, -+ 16, tbl_buf); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, -+ 16, tbl_buf); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, -+ 16, tbl_buf); -+ -+ tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc); -+ if (NREV_LT(pi->pubpi.phy_rev, 3)) -+ tbl_len -= 2; -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, -+ tbl_len, 96, 16, -+ pi->nphy_txiqlocal_bestc); -+ -+ pi->nphy_txiqlocal_coeffsvalid = true; -+ pi->nphy_txiqlocal_chanspec = pi->radio_chanspec; -+ } else { -+ tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs); -+ if (NREV_LT(pi->pubpi.phy_rev, 3)) -+ tbl_len -= 2; -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, -+ tbl_len, 96, 16, -+ pi->mphase_txcal_bestcoeffs); -+ } -+ -+ wlc_phy_stopplayback_nphy(pi); -+ -+ write_phy_reg(pi, 0xc2, 0x0000); -+ -+ } -+ -+ wlc_phy_txcal_phycleanup_nphy(pi); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, -+ gain_save); -+ -+ wlc_phy_txcal_radio_cleanup_nphy(pi); -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 2)) { -+ if (!mphase -+ || (pi->mphase_cal_phase_id == mphase_cal_lastphase)) -+ wlc_phy_tx_iq_war_nphy(pi); -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 4)) -+ pi->phyhang_avoid = phyhang_avoid_state; -+ -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+ -+ return bcmerror; -+} -+ -+static void wlc_phy_reapply_txcal_coeffs_nphy(struct brcms_phy *pi) -+{ -+ u16 tbl_buf[7]; -+ -+ if ((pi->nphy_txiqlocal_chanspec == pi->radio_chanspec) && -+ (pi->nphy_txiqlocal_coeffsvalid)) { -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, -+ ARRAY_SIZE(tbl_buf), 80, 16, tbl_buf); -+ -+ if ((pi->nphy_txiqlocal_bestc[0] != tbl_buf[0]) || -+ (pi->nphy_txiqlocal_bestc[1] != tbl_buf[1]) || -+ (pi->nphy_txiqlocal_bestc[2] != tbl_buf[2]) || -+ (pi->nphy_txiqlocal_bestc[3] != tbl_buf[3])) { -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, -+ 16, pi->nphy_txiqlocal_bestc); -+ -+ tbl_buf[0] = 0; -+ tbl_buf[1] = 0; -+ tbl_buf[2] = 0; -+ tbl_buf[3] = 0; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, -+ 16, tbl_buf); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, -+ 16, -+ &pi->nphy_txiqlocal_bestc[5]); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, -+ 16, -+ &pi->nphy_txiqlocal_bestc[5]); -+ } -+ } -+} -+ -+void -+wlc_phy_rx_iq_coeffs_nphy(struct brcms_phy *pi, u8 write, -+ struct nphy_iq_comp *pcomp) -+{ -+ if (write) { -+ write_phy_reg(pi, 0x9a, pcomp->a0); -+ write_phy_reg(pi, 0x9b, pcomp->b0); -+ write_phy_reg(pi, 0x9c, pcomp->a1); -+ write_phy_reg(pi, 0x9d, pcomp->b1); -+ } else { -+ pcomp->a0 = read_phy_reg(pi, 0x9a); -+ pcomp->b0 = read_phy_reg(pi, 0x9b); -+ pcomp->a1 = read_phy_reg(pi, 0x9c); -+ pcomp->b1 = read_phy_reg(pi, 0x9d); -+ } -+} -+ -+void -+wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est, -+ u16 num_samps, u8 wait_time, u8 wait_for_crs) -+{ -+ u8 core; -+ -+ write_phy_reg(pi, 0x12b, num_samps); -+ mod_phy_reg(pi, 0x12a, (0xff << 0), (wait_time << 0)); -+ mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqMode, -+ (wait_for_crs) ? NPHY_IqestCmd_iqMode : 0); -+ -+ mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqstart, NPHY_IqestCmd_iqstart); -+ -+ SPINWAIT(((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) != 0), -+ 10000); -+ if (WARN(read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart, -+ "HW error: rxiq est")) -+ return; -+ -+ if ((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) == 0) { -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ est[core].i_pwr = -+ (read_phy_reg(pi, -+ NPHY_IqestipwrAccHi(core)) << 16) -+ | read_phy_reg(pi, NPHY_IqestipwrAccLo(core)); -+ est[core].q_pwr = -+ (read_phy_reg(pi, -+ NPHY_IqestqpwrAccHi(core)) << 16) -+ | read_phy_reg(pi, NPHY_IqestqpwrAccLo(core)); -+ est[core].iq_prod = -+ (read_phy_reg(pi, -+ NPHY_IqestIqAccHi(core)) << 16) | -+ read_phy_reg(pi, NPHY_IqestIqAccLo(core)); -+ } -+ } -+} -+ -+#define CAL_RETRY_CNT 2 -+static void wlc_phy_calc_rx_iq_comp_nphy(struct brcms_phy *pi, u8 core_mask) -+{ -+ u8 curr_core; -+ struct phy_iq_est est[PHY_CORE_MAX]; -+ struct nphy_iq_comp old_comp, new_comp; -+ s32 iq = 0; -+ u32 ii = 0, qq = 0; -+ s16 iq_nbits, qq_nbits, brsh, arsh; -+ s32 a, b, temp; -+ int bcmerror = 0; -+ uint cal_retry = 0; -+ -+ if (core_mask == 0x0) -+ return; -+ -+ wlc_phy_rx_iq_coeffs_nphy(pi, 0, &old_comp); -+ new_comp.a0 = new_comp.b0 = new_comp.a1 = new_comp.b1 = 0x0; -+ wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp); -+ -+cal_try: -+ wlc_phy_rx_iq_est_nphy(pi, est, 0x4000, 32, 0); -+ -+ new_comp = old_comp; -+ -+ for (curr_core = 0; curr_core < pi->pubpi.phy_corenum; curr_core++) { -+ -+ if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) { -+ iq = est[curr_core].iq_prod; -+ ii = est[curr_core].i_pwr; -+ qq = est[curr_core].q_pwr; -+ } else if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) { -+ iq = est[curr_core].iq_prod; -+ ii = est[curr_core].i_pwr; -+ qq = est[curr_core].q_pwr; -+ } else { -+ continue; -+ } -+ -+ if ((ii + qq) < NPHY_MIN_RXIQ_PWR) { -+ bcmerror = -EBADE; -+ break; -+ } -+ -+ iq_nbits = wlc_phy_nbits(iq); -+ qq_nbits = wlc_phy_nbits(qq); -+ -+ arsh = 10 - (30 - iq_nbits); -+ if (arsh >= 0) { -+ a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); -+ temp = (s32) (ii >> arsh); -+ if (temp == 0) { -+ bcmerror = -EBADE; -+ break; -+ } -+ } else { -+ a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); -+ temp = (s32) (ii << -arsh); -+ if (temp == 0) { -+ bcmerror = -EBADE; -+ break; -+ } -+ } -+ -+ a /= temp; -+ -+ brsh = qq_nbits - 31 + 20; -+ if (brsh >= 0) { -+ b = (qq << (31 - qq_nbits)); -+ temp = (s32) (ii >> brsh); -+ if (temp == 0) { -+ bcmerror = -EBADE; -+ break; -+ } -+ } else { -+ b = (qq << (31 - qq_nbits)); -+ temp = (s32) (ii << -brsh); -+ if (temp == 0) { -+ bcmerror = -EBADE; -+ break; -+ } -+ } -+ b /= temp; -+ b -= a * a; -+ b = (s32) int_sqrt((unsigned long) b); -+ b -= (1 << 10); -+ -+ if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) { -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ new_comp.a0 = (s16) a & 0x3ff; -+ new_comp.b0 = (s16) b & 0x3ff; -+ } else { -+ -+ new_comp.a0 = (s16) b & 0x3ff; -+ new_comp.b0 = (s16) a & 0x3ff; -+ } -+ } -+ if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) { -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ new_comp.a1 = (s16) a & 0x3ff; -+ new_comp.b1 = (s16) b & 0x3ff; -+ } else { -+ -+ new_comp.a1 = (s16) b & 0x3ff; -+ new_comp.b1 = (s16) a & 0x3ff; -+ } -+ } -+ } -+ -+ if (bcmerror != 0) { -+ printk(KERN_DEBUG "%s: Failed, cnt = %d\n", __func__, -+ cal_retry); -+ -+ if (cal_retry < CAL_RETRY_CNT) { -+ cal_retry++; -+ goto cal_try; -+ } -+ -+ new_comp = old_comp; -+ } -+ -+ wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp); -+} -+ -+static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core) -+{ -+ u16 offtune_val; -+ u16 bias_g = 0; -+ u16 bias_a = 0; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ if (rx_core == PHY_CORE_0) { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ pi->tx_rx_cal_radio_saveregs[0] = -+ read_radio_reg(pi, -+ RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP); -+ pi->tx_rx_cal_radio_saveregs[1] = -+ read_radio_reg(pi, -+ RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN); -+ -+ write_radio_reg(pi, -+ RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP, -+ 0x3); -+ write_radio_reg(pi, -+ RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN, -+ 0xaf); -+ -+ } else { -+ pi->tx_rx_cal_radio_saveregs[0] = -+ read_radio_reg(pi, -+ RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP); -+ pi->tx_rx_cal_radio_saveregs[1] = -+ read_radio_reg(pi, -+ RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN); -+ -+ write_radio_reg( -+ pi, -+ RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP, -+ 0x3); -+ write_radio_reg( -+ pi, -+ RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN, -+ 0x7f); -+ } -+ -+ } else { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ pi->tx_rx_cal_radio_saveregs[0] = -+ read_radio_reg(pi, -+ RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP); -+ pi->tx_rx_cal_radio_saveregs[1] = -+ read_radio_reg(pi, -+ RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN); -+ -+ write_radio_reg( -+ pi, -+ RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP, -+ 0x3); -+ write_radio_reg( -+ pi, -+ RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN, -+ 0xaf); -+ -+ } else { -+ pi->tx_rx_cal_radio_saveregs[0] = -+ read_radio_reg(pi, -+ RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP); -+ pi->tx_rx_cal_radio_saveregs[1] = -+ read_radio_reg(pi, -+ RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN); -+ -+ write_radio_reg(pi, -+ RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP, -+ 0x3); -+ write_radio_reg(pi, -+ RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN, -+ 0x7f); -+ } -+ } -+ -+ } else { -+ if (rx_core == PHY_CORE_0) { -+ pi->tx_rx_cal_radio_saveregs[0] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_RXIQCAL_TXMUX | -+ RADIO_2056_TX1); -+ pi->tx_rx_cal_radio_saveregs[1] = -+ read_radio_reg(pi, -+ RADIO_2056_RX_RXIQCAL_RXMUX | -+ RADIO_2056_RX0); -+ -+ if (pi->pubpi.radiorev >= 5) { -+ pi->tx_rx_cal_radio_saveregs[2] = -+ read_radio_reg(pi, -+ RADIO_2056_RX_RXSPARE2 | -+ RADIO_2056_RX0); -+ pi->tx_rx_cal_radio_saveregs[3] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_TXSPARE2 | -+ RADIO_2056_TX1); -+ } -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ -+ if (pi->pubpi.radiorev >= 5) { -+ pi->tx_rx_cal_radio_saveregs[4] = -+ read_radio_reg(pi, -+ RADIO_2056_RX_LNAA_MASTER -+ | RADIO_2056_RX0); -+ -+ write_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAA_MASTER -+ | RADIO_2056_RX0, 0x40); -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_TXSPARE2 | -+ RADIO_2056_TX1, bias_a); -+ -+ write_radio_reg(pi, -+ RADIO_2056_RX_RXSPARE2 | -+ RADIO_2056_RX0, bias_a); -+ } else { -+ pi->tx_rx_cal_radio_saveregs[4] = -+ read_radio_reg(pi, -+ RADIO_2056_RX_LNAA_TUNE -+ | RADIO_2056_RX0); -+ -+ offtune_val = -+ (pi->tx_rx_cal_radio_saveregs -+ [2] & 0xF0) >> 8; -+ offtune_val = -+ (offtune_val <= 0x7) ? 0xF : 0; -+ -+ mod_radio_reg(pi, -+ RADIO_2056_RX_LNAA_TUNE | -+ RADIO_2056_RX0, 0xF0, -+ (offtune_val << 8)); -+ } -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_RXIQCAL_TXMUX | -+ RADIO_2056_TX1, 0x9); -+ write_radio_reg(pi, -+ RADIO_2056_RX_RXIQCAL_RXMUX | -+ RADIO_2056_RX0, 0x9); -+ } else { -+ if (pi->pubpi.radiorev >= 5) { -+ pi->tx_rx_cal_radio_saveregs[4] = -+ read_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAG_MASTER -+ | RADIO_2056_RX0); -+ -+ write_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAG_MASTER -+ | RADIO_2056_RX0, 0x40); -+ -+ write_radio_reg( -+ pi, -+ RADIO_2056_TX_TXSPARE2 -+ | -+ RADIO_2056_TX1, bias_g); -+ -+ write_radio_reg( -+ pi, -+ RADIO_2056_RX_RXSPARE2 -+ | -+ RADIO_2056_RX0, bias_g); -+ -+ } else { -+ pi->tx_rx_cal_radio_saveregs[4] = -+ read_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAG_TUNE -+ | RADIO_2056_RX0); -+ -+ offtune_val = -+ (pi-> -+ tx_rx_cal_radio_saveregs[2] & -+ 0xF0) >> 8; -+ offtune_val = -+ (offtune_val <= 0x7) ? 0xF : 0; -+ -+ mod_radio_reg(pi, -+ RADIO_2056_RX_LNAG_TUNE | -+ RADIO_2056_RX0, 0xF0, -+ (offtune_val << 8)); -+ } -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_RXIQCAL_TXMUX | -+ RADIO_2056_TX1, 0x6); -+ write_radio_reg(pi, -+ RADIO_2056_RX_RXIQCAL_RXMUX | -+ RADIO_2056_RX0, 0x6); -+ } -+ -+ } else { -+ pi->tx_rx_cal_radio_saveregs[0] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_RXIQCAL_TXMUX | -+ RADIO_2056_TX0); -+ pi->tx_rx_cal_radio_saveregs[1] = -+ read_radio_reg(pi, -+ RADIO_2056_RX_RXIQCAL_RXMUX | -+ RADIO_2056_RX1); -+ -+ if (pi->pubpi.radiorev >= 5) { -+ pi->tx_rx_cal_radio_saveregs[2] = -+ read_radio_reg(pi, -+ RADIO_2056_RX_RXSPARE2 | -+ RADIO_2056_RX1); -+ pi->tx_rx_cal_radio_saveregs[3] = -+ read_radio_reg(pi, -+ RADIO_2056_TX_TXSPARE2 | -+ RADIO_2056_TX0); -+ } -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ -+ if (pi->pubpi.radiorev >= 5) { -+ pi->tx_rx_cal_radio_saveregs[4] = -+ read_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAA_MASTER -+ | RADIO_2056_RX1); -+ -+ write_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAA_MASTER | -+ RADIO_2056_RX1, 0x40); -+ -+ write_radio_reg( -+ pi, -+ RADIO_2056_TX_TXSPARE2 -+ | -+ RADIO_2056_TX0, bias_a); -+ -+ write_radio_reg( -+ pi, -+ RADIO_2056_RX_RXSPARE2 -+ | -+ RADIO_2056_RX1, bias_a); -+ } else { -+ pi->tx_rx_cal_radio_saveregs[4] = -+ read_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAA_TUNE -+ | RADIO_2056_RX1); -+ -+ offtune_val = -+ (pi-> -+ tx_rx_cal_radio_saveregs[2] & -+ 0xF0) >> 8; -+ offtune_val = -+ (offtune_val <= 0x7) ? 0xF : 0; -+ -+ mod_radio_reg(pi, -+ RADIO_2056_RX_LNAA_TUNE | -+ RADIO_2056_RX1, 0xF0, -+ (offtune_val << 8)); -+ } -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_RXIQCAL_TXMUX | -+ RADIO_2056_TX0, 0x9); -+ write_radio_reg(pi, -+ RADIO_2056_RX_RXIQCAL_RXMUX | -+ RADIO_2056_RX1, 0x9); -+ } else { -+ if (pi->pubpi.radiorev >= 5) { -+ pi->tx_rx_cal_radio_saveregs[4] = -+ read_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAG_MASTER -+ | RADIO_2056_RX1); -+ -+ write_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAG_MASTER -+ | RADIO_2056_RX1, 0x40); -+ -+ write_radio_reg( -+ pi, -+ RADIO_2056_TX_TXSPARE2 -+ | -+ RADIO_2056_TX0, bias_g); -+ -+ write_radio_reg( -+ pi, -+ RADIO_2056_RX_RXSPARE2 -+ | -+ RADIO_2056_RX1, bias_g); -+ } else { -+ pi->tx_rx_cal_radio_saveregs[4] = -+ read_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAG_TUNE -+ | RADIO_2056_RX1); -+ -+ offtune_val = -+ (pi-> -+ tx_rx_cal_radio_saveregs[2] & -+ 0xF0) >> 8; -+ offtune_val = -+ (offtune_val <= 0x7) ? 0xF : 0; -+ -+ mod_radio_reg(pi, -+ RADIO_2056_RX_LNAG_TUNE | -+ RADIO_2056_RX1, 0xF0, -+ (offtune_val << 8)); -+ } -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_RXIQCAL_TXMUX | -+ RADIO_2056_TX0, 0x6); -+ write_radio_reg(pi, -+ RADIO_2056_RX_RXIQCAL_RXMUX | -+ RADIO_2056_RX1, 0x6); -+ } -+ } -+ } -+} -+ -+static void wlc_phy_rxcal_radio_cleanup_nphy(struct brcms_phy *pi, u8 rx_core) -+{ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ if (rx_core == PHY_CORE_0) { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ write_radio_reg( -+ pi, -+ RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP, -+ pi-> -+ tx_rx_cal_radio_saveregs[0]); -+ write_radio_reg( -+ pi, -+ RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN, -+ pi-> -+ tx_rx_cal_radio_saveregs[1]); -+ -+ } else { -+ write_radio_reg( -+ pi, -+ RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP, -+ pi-> -+ tx_rx_cal_radio_saveregs[0]); -+ write_radio_reg( -+ pi, -+ RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN, -+ pi-> -+ tx_rx_cal_radio_saveregs[1]); -+ } -+ -+ } else { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ write_radio_reg( -+ pi, -+ RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP, -+ pi-> -+ tx_rx_cal_radio_saveregs[0]); -+ write_radio_reg( -+ pi, -+ RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN, -+ pi-> -+ tx_rx_cal_radio_saveregs[1]); -+ -+ } else { -+ write_radio_reg( -+ pi, -+ RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP, -+ pi-> -+ tx_rx_cal_radio_saveregs[0]); -+ write_radio_reg( -+ pi, -+ RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN, -+ pi-> -+ tx_rx_cal_radio_saveregs[1]); -+ } -+ } -+ -+ } else { -+ if (rx_core == PHY_CORE_0) { -+ write_radio_reg(pi, -+ RADIO_2056_TX_RXIQCAL_TXMUX | -+ RADIO_2056_TX1, -+ pi->tx_rx_cal_radio_saveregs[0]); -+ -+ write_radio_reg(pi, -+ RADIO_2056_RX_RXIQCAL_RXMUX | -+ RADIO_2056_RX0, -+ pi->tx_rx_cal_radio_saveregs[1]); -+ -+ if (pi->pubpi.radiorev >= 5) { -+ write_radio_reg(pi, -+ RADIO_2056_RX_RXSPARE2 | -+ RADIO_2056_RX0, -+ pi-> -+ tx_rx_cal_radio_saveregs[2]); -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_TXSPARE2 | -+ RADIO_2056_TX1, -+ pi-> -+ tx_rx_cal_radio_saveregs[3]); -+ } -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ if (pi->pubpi.radiorev >= 5) -+ write_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAA_MASTER -+ | RADIO_2056_RX0, -+ pi-> -+ tx_rx_cal_radio_saveregs -+ [4]); -+ else -+ write_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAA_TUNE -+ | RADIO_2056_RX0, -+ pi-> -+ tx_rx_cal_radio_saveregs -+ [4]); -+ } else { -+ if (pi->pubpi.radiorev >= 5) -+ write_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAG_MASTER -+ | RADIO_2056_RX0, -+ pi-> -+ tx_rx_cal_radio_saveregs -+ [4]); -+ else -+ write_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAG_TUNE -+ | RADIO_2056_RX0, -+ pi-> -+ tx_rx_cal_radio_saveregs -+ [4]); -+ } -+ -+ } else { -+ write_radio_reg(pi, -+ RADIO_2056_TX_RXIQCAL_TXMUX | -+ RADIO_2056_TX0, -+ pi->tx_rx_cal_radio_saveregs[0]); -+ -+ write_radio_reg(pi, -+ RADIO_2056_RX_RXIQCAL_RXMUX | -+ RADIO_2056_RX1, -+ pi->tx_rx_cal_radio_saveregs[1]); -+ -+ if (pi->pubpi.radiorev >= 5) { -+ write_radio_reg(pi, -+ RADIO_2056_RX_RXSPARE2 | -+ RADIO_2056_RX1, -+ pi-> -+ tx_rx_cal_radio_saveregs[2]); -+ -+ write_radio_reg(pi, -+ RADIO_2056_TX_TXSPARE2 | -+ RADIO_2056_TX0, -+ pi-> -+ tx_rx_cal_radio_saveregs[3]); -+ } -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ if (pi->pubpi.radiorev >= 5) -+ write_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAA_MASTER -+ | RADIO_2056_RX1, -+ pi-> -+ tx_rx_cal_radio_saveregs -+ [4]); -+ else -+ write_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAA_TUNE -+ | RADIO_2056_RX1, -+ pi-> -+ tx_rx_cal_radio_saveregs -+ [4]); -+ } else { -+ if (pi->pubpi.radiorev >= 5) -+ write_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAG_MASTER -+ | RADIO_2056_RX1, -+ pi-> -+ tx_rx_cal_radio_saveregs -+ [4]); -+ else -+ write_radio_reg( -+ pi, -+ RADIO_2056_RX_LNAG_TUNE -+ | RADIO_2056_RX1, -+ pi-> -+ tx_rx_cal_radio_saveregs -+ [4]); -+ } -+ } -+ } -+} -+ -+static void wlc_phy_rxcal_physetup_nphy(struct brcms_phy *pi, u8 rx_core) -+{ -+ u8 tx_core; -+ u16 rx_antval, tx_antval; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ tx_core = rx_core; -+ else -+ tx_core = (rx_core == PHY_CORE_0) ? 1 : 0; -+ -+ pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa2); -+ pi->tx_rx_cal_phy_saveregs[1] = -+ read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7); -+ pi->tx_rx_cal_phy_saveregs[2] = -+ read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5); -+ pi->tx_rx_cal_phy_saveregs[3] = read_phy_reg(pi, 0x91); -+ pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x92); -+ pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x7a); -+ pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x7d); -+ pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0xe7); -+ pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0xec); -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ pi->tx_rx_cal_phy_saveregs[11] = read_phy_reg(pi, 0x342); -+ pi->tx_rx_cal_phy_saveregs[12] = read_phy_reg(pi, 0x343); -+ pi->tx_rx_cal_phy_saveregs[13] = read_phy_reg(pi, 0x346); -+ pi->tx_rx_cal_phy_saveregs[14] = read_phy_reg(pi, 0x347); -+ } -+ -+ pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297); -+ pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b); -+ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 0), (0) << 0); -+ -+ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 0), (0) << 0); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0); -+ -+ mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << (1 - rx_core)) << 12); -+ -+ } else { -+ -+ mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12); -+ mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0); -+ mod_phy_reg(pi, 0xa2, (0xf << 4), (1 << rx_core) << 4); -+ mod_phy_reg(pi, 0xa2, (0xf << 8), (1 << rx_core) << 8); -+ } -+ -+ mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7), (0x1 << 2), 0); -+ mod_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5, -+ (0x1 << 2), (0x1 << 2)); -+ if (NREV_LT(pi->pubpi.phy_rev, 7)) { -+ mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7), -+ (0x1 << 0) | (0x1 << 1), 0); -+ mod_phy_reg(pi, (rx_core == PHY_CORE_0) ? -+ 0x8f : 0xa5, -+ (0x1 << 0) | (0x1 << 1), (0x1 << 0) | (0x1 << 1)); -+ } -+ -+ wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 0, -+ RADIO_MIMO_CORESEL_CORE1 | -+ RADIO_MIMO_CORESEL_CORE2); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), -+ 0, 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID0); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 0, 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 1, 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 1, 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID2); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ if (CHSPEC_IS40(pi->radio_chanspec)) -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, -+ (0x1 << 7), -+ 2, 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ else -+ wlc_phy_rfctrl_override_nphy_rev7( -+ pi, -+ (0x1 << 7), -+ 0, 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), -+ 0, 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0, 0, -+ NPHY_REV7_RFCTRLOVERRIDE_ID1); -+ } else { -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 3, 0); -+ } -+ -+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ -+ wlc_phy_rfctrlintc_override_nphy(pi, -+ NPHY_RfctrlIntc_override_TRSW, -+ 0x1, rx_core + 1); -+ } else { -+ -+ if (rx_core == PHY_CORE_0) { -+ rx_antval = 0x1; -+ tx_antval = 0x8; -+ } else { -+ rx_antval = 0x4; -+ tx_antval = 0x2; -+ } -+ -+ wlc_phy_rfctrlintc_override_nphy(pi, -+ NPHY_RfctrlIntc_override_TRSW, -+ rx_antval, rx_core + 1); -+ wlc_phy_rfctrlintc_override_nphy(pi, -+ NPHY_RfctrlIntc_override_TRSW, -+ tx_antval, tx_core + 1); -+ } -+} -+ -+static void wlc_phy_rxcal_phycleanup_nphy(struct brcms_phy *pi, u8 rx_core) -+{ -+ -+ write_phy_reg(pi, 0xa2, pi->tx_rx_cal_phy_saveregs[0]); -+ write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7, -+ pi->tx_rx_cal_phy_saveregs[1]); -+ write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5, -+ pi->tx_rx_cal_phy_saveregs[2]); -+ write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[3]); -+ write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[4]); -+ -+ write_phy_reg(pi, 0x7a, pi->tx_rx_cal_phy_saveregs[5]); -+ write_phy_reg(pi, 0x7d, pi->tx_rx_cal_phy_saveregs[6]); -+ write_phy_reg(pi, 0xe7, pi->tx_rx_cal_phy_saveregs[7]); -+ write_phy_reg(pi, 0xec, pi->tx_rx_cal_phy_saveregs[8]); -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ write_phy_reg(pi, 0x342, pi->tx_rx_cal_phy_saveregs[11]); -+ write_phy_reg(pi, 0x343, pi->tx_rx_cal_phy_saveregs[12]); -+ write_phy_reg(pi, 0x346, pi->tx_rx_cal_phy_saveregs[13]); -+ write_phy_reg(pi, 0x347, pi->tx_rx_cal_phy_saveregs[14]); -+ } -+ -+ write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]); -+ write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]); -+} -+ -+static void -+wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core, -+ u16 *rxgain, u8 cal_type) -+{ -+ -+ u16 num_samps; -+ struct phy_iq_est est[PHY_CORE_MAX]; -+ u8 tx_core; -+ struct nphy_iq_comp save_comp, zero_comp; -+ u32 i_pwr, q_pwr, curr_pwr, optim_pwr = 0, prev_pwr = 0, -+ thresh_pwr = 10000; -+ s16 desired_log2_pwr, actual_log2_pwr, delta_pwr; -+ bool gainctrl_done = false; -+ u8 mix_tia_gain = 3; -+ s8 optim_gaintbl_index = 0, prev_gaintbl_index = 0; -+ s8 curr_gaintbl_index = 3; -+ u8 gainctrl_dirn = NPHY_RXCAL_GAIN_INIT; -+ const struct nphy_ipa_txrxgain *nphy_rxcal_gaintbl; -+ u16 hpvga, lpf_biq1, lpf_biq0, lna2, lna1; -+ int fine_gain_idx; -+ s8 txpwrindex; -+ u16 nphy_rxcal_txgain[2]; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ tx_core = rx_core; -+ else -+ tx_core = 1 - rx_core; -+ -+ num_samps = 1024; -+ desired_log2_pwr = (cal_type == 0) ? 13 : 13; -+ -+ wlc_phy_rx_iq_coeffs_nphy(pi, 0, &save_comp); -+ zero_comp.a0 = zero_comp.b0 = zero_comp.a1 = zero_comp.b1 = 0x0; -+ wlc_phy_rx_iq_coeffs_nphy(pi, 1, &zero_comp); -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ mix_tia_gain = 3; -+ else if (NREV_GE(pi->pubpi.phy_rev, 4)) -+ mix_tia_gain = 4; -+ else -+ mix_tia_gain = 6; -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz_rev7; -+ else -+ nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz; -+ } else { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz_rev7; -+ else -+ nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz; -+ } -+ -+ do { -+ -+ hpvga = (NREV_GE(pi->pubpi.phy_rev, 7)) ? -+ 0 : nphy_rxcal_gaintbl[curr_gaintbl_index].hpvga; -+ lpf_biq1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq1; -+ lpf_biq0 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq0; -+ lna2 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna2; -+ lna1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna1; -+ txpwrindex = nphy_rxcal_gaintbl[curr_gaintbl_index].txpwrindex; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ wlc_phy_rfctrl_override_1tomany_nphy( -+ pi, -+ NPHY_REV7_RfctrlOverride_cmd_rxgain, -+ ((lpf_biq1 << 12) | -+ (lpf_biq0 << 8) | -+ (mix_tia_gain << 4) | (lna2 << 2) -+ | lna1), 0x3, 0); -+ else -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), -+ ((hpvga << 12) | -+ (lpf_biq1 << 10) | -+ (lpf_biq0 << 8) | -+ (mix_tia_gain << 4) | -+ (lna2 << 2) | lna1), 0x3, -+ 0); -+ -+ pi->nphy_rxcal_pwr_idx[tx_core] = txpwrindex; -+ -+ if (txpwrindex == -1) { -+ nphy_rxcal_txgain[0] = 0x8ff0 | pi->nphy_gmval; -+ nphy_rxcal_txgain[1] = 0x8ff0 | pi->nphy_gmval; -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, -+ 2, 0x110, 16, -+ nphy_rxcal_txgain); -+ } else { -+ wlc_phy_txpwr_index_nphy(pi, tx_core + 1, txpwrindex, -+ false); -+ } -+ -+ wlc_phy_tx_tone_nphy(pi, (CHSPEC_IS40(pi->radio_chanspec)) ? -+ NPHY_RXCAL_TONEFREQ_40MHz : -+ NPHY_RXCAL_TONEFREQ_20MHz, -+ NPHY_RXCAL_TONEAMP, 0, cal_type, false); -+ -+ wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0); -+ i_pwr = (est[rx_core].i_pwr + num_samps / 2) / num_samps; -+ q_pwr = (est[rx_core].q_pwr + num_samps / 2) / num_samps; -+ curr_pwr = i_pwr + q_pwr; -+ -+ switch (gainctrl_dirn) { -+ case NPHY_RXCAL_GAIN_INIT: -+ if (curr_pwr > thresh_pwr) { -+ gainctrl_dirn = NPHY_RXCAL_GAIN_DOWN; -+ prev_gaintbl_index = curr_gaintbl_index; -+ curr_gaintbl_index--; -+ } else { -+ gainctrl_dirn = NPHY_RXCAL_GAIN_UP; -+ prev_gaintbl_index = curr_gaintbl_index; -+ curr_gaintbl_index++; -+ } -+ break; -+ -+ case NPHY_RXCAL_GAIN_UP: -+ if (curr_pwr > thresh_pwr) { -+ gainctrl_done = true; -+ optim_pwr = prev_pwr; -+ optim_gaintbl_index = prev_gaintbl_index; -+ } else { -+ prev_gaintbl_index = curr_gaintbl_index; -+ curr_gaintbl_index++; -+ } -+ break; -+ -+ case NPHY_RXCAL_GAIN_DOWN: -+ if (curr_pwr > thresh_pwr) { -+ prev_gaintbl_index = curr_gaintbl_index; -+ curr_gaintbl_index--; -+ } else { -+ gainctrl_done = true; -+ optim_pwr = curr_pwr; -+ optim_gaintbl_index = curr_gaintbl_index; -+ } -+ break; -+ -+ default: -+ break; -+ } -+ -+ if ((curr_gaintbl_index < 0) || -+ (curr_gaintbl_index > NPHY_IPA_RXCAL_MAXGAININDEX)) { -+ gainctrl_done = true; -+ optim_pwr = curr_pwr; -+ optim_gaintbl_index = prev_gaintbl_index; -+ } else { -+ prev_pwr = curr_pwr; -+ } -+ -+ wlc_phy_stopplayback_nphy(pi); -+ } while (!gainctrl_done); -+ -+ hpvga = nphy_rxcal_gaintbl[optim_gaintbl_index].hpvga; -+ lpf_biq1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq1; -+ lpf_biq0 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq0; -+ lna2 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna2; -+ lna1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna1; -+ txpwrindex = nphy_rxcal_gaintbl[optim_gaintbl_index].txpwrindex; -+ -+ actual_log2_pwr = wlc_phy_nbits(optim_pwr); -+ delta_pwr = desired_log2_pwr - actual_log2_pwr; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ fine_gain_idx = (int)lpf_biq1 + delta_pwr; -+ -+ if (fine_gain_idx + (int)lpf_biq0 > 10) -+ lpf_biq1 = 10 - lpf_biq0; -+ else -+ lpf_biq1 = (u16) max(fine_gain_idx, 0); -+ -+ wlc_phy_rfctrl_override_1tomany_nphy( -+ pi, -+ NPHY_REV7_RfctrlOverride_cmd_rxgain, -+ ((lpf_biq1 << 12) | -+ (lpf_biq0 << 8) | -+ (mix_tia_gain << 4) | -+ (lna2 << 2) | lna1), 0x3, -+ 0); -+ } else { -+ hpvga = (u16) max(min(((int)hpvga) + delta_pwr, 10), 0); -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), -+ ((hpvga << 12) | -+ (lpf_biq1 << 10) | -+ (lpf_biq0 << 8) | -+ (mix_tia_gain << 4) | -+ (lna2 << 2) | -+ lna1), 0x3, 0); -+ } -+ -+ if (rxgain != NULL) { -+ *rxgain++ = lna1; -+ *rxgain++ = lna2; -+ *rxgain++ = mix_tia_gain; -+ *rxgain++ = lpf_biq0; -+ *rxgain++ = lpf_biq1; -+ *rxgain = hpvga; -+ } -+ -+ wlc_phy_rx_iq_coeffs_nphy(pi, 1, &save_comp); -+} -+ -+static void -+wlc_phy_rxcal_gainctrl_nphy(struct brcms_phy *pi, u8 rx_core, u16 *rxgain, -+ u8 cal_type) -+{ -+ wlc_phy_rxcal_gainctrl_nphy_rev5(pi, rx_core, rxgain, cal_type); -+} -+ -+static u8 -+wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type) -+{ -+ u32 target_bws[2] = { 9500, 21000 }; -+ u32 ref_tones[2] = { 3000, 6000 }; -+ u32 target_bw, ref_tone; -+ -+ u32 target_pwr_ratios[2] = { 28606, 18468 }; -+ u32 target_pwr_ratio, pwr_ratio, last_pwr_ratio = 0; -+ -+ u16 start_rccal_ovr_val = 128; -+ u16 txlpf_rccal_lpc_ovr_val = 128; -+ u16 rxlpf_rccal_hpc_ovr_val = 159; -+ -+ u16 orig_txlpf_rccal_lpc_ovr_val; -+ u16 orig_rxlpf_rccal_hpc_ovr_val; -+ u16 radio_addr_offset_rx; -+ u16 radio_addr_offset_tx; -+ u16 orig_dcBypass; -+ u16 orig_RxStrnFilt40Num[6]; -+ u16 orig_RxStrnFilt40Den[4]; -+ u16 orig_rfctrloverride[2]; -+ u16 orig_rfctrlauxreg[2]; -+ u16 orig_rfctrlrssiothers; -+ u16 tx_lpf_bw = 4; -+ -+ u16 rx_lpf_bw, rx_lpf_bws[2] = { 2, 4 }; -+ u16 lpf_hpc = 7, hpvga_hpc = 7; -+ -+ s8 rccal_stepsize; -+ u16 rccal_val, last_rccal_val = 0, best_rccal_val = 0; -+ u32 ref_iq_vals = 0, target_iq_vals = 0; -+ u16 num_samps, log_num_samps = 10; -+ struct phy_iq_est est[PHY_CORE_MAX]; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ return 0; -+ -+ num_samps = (1 << log_num_samps); -+ -+ if (CHSPEC_IS40(pi->radio_chanspec)) { -+ target_bw = target_bws[1]; -+ target_pwr_ratio = target_pwr_ratios[1]; -+ ref_tone = ref_tones[1]; -+ rx_lpf_bw = rx_lpf_bws[1]; -+ } else { -+ target_bw = target_bws[0]; -+ target_pwr_ratio = target_pwr_ratios[0]; -+ ref_tone = ref_tones[0]; -+ rx_lpf_bw = rx_lpf_bws[0]; -+ } -+ -+ if (core_idx == 0) { -+ radio_addr_offset_rx = RADIO_2056_RX0; -+ radio_addr_offset_tx = -+ (loopback_type == 0) ? RADIO_2056_TX0 : RADIO_2056_TX1; -+ } else { -+ radio_addr_offset_rx = RADIO_2056_RX1; -+ radio_addr_offset_tx = -+ (loopback_type == 0) ? RADIO_2056_TX1 : RADIO_2056_TX0; -+ } -+ -+ orig_txlpf_rccal_lpc_ovr_val = -+ read_radio_reg(pi, -+ (RADIO_2056_TX_TXLPF_RCCAL | -+ radio_addr_offset_tx)); -+ orig_rxlpf_rccal_hpc_ovr_val = -+ read_radio_reg(pi, -+ (RADIO_2056_RX_RXLPF_RCCAL_HPC | -+ radio_addr_offset_rx)); -+ -+ orig_dcBypass = ((read_phy_reg(pi, 0x48) >> 8) & 1); -+ -+ orig_RxStrnFilt40Num[0] = read_phy_reg(pi, 0x267); -+ orig_RxStrnFilt40Num[1] = read_phy_reg(pi, 0x268); -+ orig_RxStrnFilt40Num[2] = read_phy_reg(pi, 0x269); -+ orig_RxStrnFilt40Den[0] = read_phy_reg(pi, 0x26a); -+ orig_RxStrnFilt40Den[1] = read_phy_reg(pi, 0x26b); -+ orig_RxStrnFilt40Num[3] = read_phy_reg(pi, 0x26c); -+ orig_RxStrnFilt40Num[4] = read_phy_reg(pi, 0x26d); -+ orig_RxStrnFilt40Num[5] = read_phy_reg(pi, 0x26e); -+ orig_RxStrnFilt40Den[2] = read_phy_reg(pi, 0x26f); -+ orig_RxStrnFilt40Den[3] = read_phy_reg(pi, 0x270); -+ -+ orig_rfctrloverride[0] = read_phy_reg(pi, 0xe7); -+ orig_rfctrloverride[1] = read_phy_reg(pi, 0xec); -+ orig_rfctrlauxreg[0] = read_phy_reg(pi, 0xf8); -+ orig_rfctrlauxreg[1] = read_phy_reg(pi, 0xfa); -+ orig_rfctrlrssiothers = read_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d); -+ -+ write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx), -+ txlpf_rccal_lpc_ovr_val); -+ -+ write_radio_reg(pi, -+ (RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx), -+ rxlpf_rccal_hpc_ovr_val); -+ -+ mod_phy_reg(pi, 0x48, (0x1 << 8), (0x1 << 8)); -+ -+ write_phy_reg(pi, 0x267, 0x02d4); -+ write_phy_reg(pi, 0x268, 0x0000); -+ write_phy_reg(pi, 0x269, 0x0000); -+ write_phy_reg(pi, 0x26a, 0x0000); -+ write_phy_reg(pi, 0x26b, 0x0000); -+ write_phy_reg(pi, 0x26c, 0x02d4); -+ write_phy_reg(pi, 0x26d, 0x0000); -+ write_phy_reg(pi, 0x26e, 0x0000); -+ write_phy_reg(pi, 0x26f, 0x0000); -+ write_phy_reg(pi, 0x270, 0x0000); -+ -+ or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 8)); -+ or_phy_reg(pi, (core_idx == 0) ? 0xec : 0xe7, (0x1 << 15)); -+ or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 9)); -+ or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 10)); -+ -+ mod_phy_reg(pi, (core_idx == 0) ? 0xfa : 0xf8, -+ (0x7 << 10), (tx_lpf_bw << 10)); -+ mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa, -+ (0x7 << 0), (hpvga_hpc << 0)); -+ mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa, -+ (0x7 << 4), (lpf_hpc << 4)); -+ mod_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d, -+ (0x7 << 8), (rx_lpf_bw << 8)); -+ -+ rccal_stepsize = 16; -+ rccal_val = start_rccal_ovr_val + rccal_stepsize; -+ -+ while (rccal_stepsize >= 0) { -+ write_radio_reg(pi, -+ (RADIO_2056_RX_RXLPF_RCCAL_LPC | -+ radio_addr_offset_rx), rccal_val); -+ -+ if (rccal_stepsize == 16) { -+ -+ wlc_phy_tx_tone_nphy(pi, ref_tone, NPHY_RXCAL_TONEAMP, -+ 0, 1, false); -+ udelay(2); -+ -+ wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0); -+ -+ if (core_idx == 0) -+ ref_iq_vals = -+ max_t(u32, (est[0].i_pwr + -+ est[0].q_pwr) >> -+ (log_num_samps + 1), -+ 1); -+ else -+ ref_iq_vals = -+ max_t(u32, (est[1].i_pwr + -+ est[1].q_pwr) >> -+ (log_num_samps + 1), -+ 1); -+ -+ wlc_phy_tx_tone_nphy(pi, target_bw, NPHY_RXCAL_TONEAMP, -+ 0, 1, false); -+ udelay(2); -+ } -+ -+ wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0); -+ -+ if (core_idx == 0) -+ target_iq_vals = (est[0].i_pwr + est[0].q_pwr) >> -+ (log_num_samps + 1); -+ else -+ target_iq_vals = -+ (est[1].i_pwr + -+ est[1].q_pwr) >> (log_num_samps + 1); -+ -+ pwr_ratio = (uint) ((target_iq_vals << 16) / ref_iq_vals); -+ -+ if (rccal_stepsize == 0) -+ rccal_stepsize--; -+ else if (rccal_stepsize == 1) { -+ last_rccal_val = rccal_val; -+ rccal_val += (pwr_ratio > target_pwr_ratio) ? 1 : -1; -+ last_pwr_ratio = pwr_ratio; -+ rccal_stepsize--; -+ } else { -+ rccal_stepsize = (rccal_stepsize >> 1); -+ rccal_val += ((pwr_ratio > target_pwr_ratio) ? -+ rccal_stepsize : (-rccal_stepsize)); -+ } -+ -+ if (rccal_stepsize == -1) { -+ best_rccal_val = -+ (abs((int)last_pwr_ratio - -+ (int)target_pwr_ratio) < -+ abs((int)pwr_ratio - -+ (int)target_pwr_ratio)) ? last_rccal_val : -+ rccal_val; -+ -+ if (CHSPEC_IS40(pi->radio_chanspec)) { -+ if ((best_rccal_val > 140) -+ || (best_rccal_val < 135)) -+ best_rccal_val = 138; -+ } else { -+ if ((best_rccal_val > 142) -+ || (best_rccal_val < 137)) -+ best_rccal_val = 140; -+ } -+ -+ write_radio_reg(pi, -+ (RADIO_2056_RX_RXLPF_RCCAL_LPC | -+ radio_addr_offset_rx), best_rccal_val); -+ } -+ } -+ -+ wlc_phy_stopplayback_nphy(pi); -+ -+ write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx), -+ orig_txlpf_rccal_lpc_ovr_val); -+ write_radio_reg(pi, -+ (RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx), -+ orig_rxlpf_rccal_hpc_ovr_val); -+ -+ mod_phy_reg(pi, 0x48, (0x1 << 8), (orig_dcBypass << 8)); -+ -+ write_phy_reg(pi, 0x267, orig_RxStrnFilt40Num[0]); -+ write_phy_reg(pi, 0x268, orig_RxStrnFilt40Num[1]); -+ write_phy_reg(pi, 0x269, orig_RxStrnFilt40Num[2]); -+ write_phy_reg(pi, 0x26a, orig_RxStrnFilt40Den[0]); -+ write_phy_reg(pi, 0x26b, orig_RxStrnFilt40Den[1]); -+ write_phy_reg(pi, 0x26c, orig_RxStrnFilt40Num[3]); -+ write_phy_reg(pi, 0x26d, orig_RxStrnFilt40Num[4]); -+ write_phy_reg(pi, 0x26e, orig_RxStrnFilt40Num[5]); -+ write_phy_reg(pi, 0x26f, orig_RxStrnFilt40Den[2]); -+ write_phy_reg(pi, 0x270, orig_RxStrnFilt40Den[3]); -+ -+ write_phy_reg(pi, 0xe7, orig_rfctrloverride[0]); -+ write_phy_reg(pi, 0xec, orig_rfctrloverride[1]); -+ write_phy_reg(pi, 0xf8, orig_rfctrlauxreg[0]); -+ write_phy_reg(pi, 0xfa, orig_rfctrlauxreg[1]); -+ write_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d, orig_rfctrlrssiothers); -+ -+ pi->nphy_anarxlpf_adjusted = false; -+ -+ return best_rccal_val - 0x80; -+} -+ -+#define WAIT_FOR_SCOPE 4000 -+static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi, -+ struct nphy_txgains target_gain, -+ u8 cal_type, bool debug) -+{ -+ u16 orig_BBConfig; -+ u8 core_no, rx_core; -+ u8 best_rccal[2]; -+ u16 gain_save[2]; -+ u16 cal_gain[2]; -+ struct nphy_iqcal_params cal_params[2]; -+ u8 rxcore_state; -+ s8 rxlpf_rccal_hpc, txlpf_rccal_lpc; -+ s8 txlpf_idac; -+ bool phyhang_avoid_state = false; -+ bool skip_rxiqcal = false; -+ -+ orig_BBConfig = read_phy_reg(pi, 0x01); -+ mod_phy_reg(pi, 0x01, (0x1 << 15), 0); -+ -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 4)) { -+ phyhang_avoid_state = pi->phyhang_avoid; -+ pi->phyhang_avoid = false; -+ } -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save); -+ -+ for (core_no = 0; core_no <= 1; core_no++) { -+ wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain, -+ &cal_params[core_no]); -+ cal_gain[core_no] = cal_params[core_no].cal_gain; -+ } -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain); -+ -+ rxcore_state = wlc_phy_rxcore_getstate_nphy( -+ (struct brcms_phy_pub *) pi); -+ -+ for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) { -+ -+ skip_rxiqcal = -+ ((rxcore_state & (1 << rx_core)) == 0) ? true : false; -+ -+ wlc_phy_rxcal_physetup_nphy(pi, rx_core); -+ -+ wlc_phy_rxcal_radio_setup_nphy(pi, rx_core); -+ -+ if ((!skip_rxiqcal) && ((cal_type == 0) || (cal_type == 2))) { -+ -+ wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL, 0); -+ -+ wlc_phy_tx_tone_nphy(pi, -+ (CHSPEC_IS40( -+ pi->radio_chanspec)) ? -+ NPHY_RXCAL_TONEFREQ_40MHz : -+ NPHY_RXCAL_TONEFREQ_20MHz, -+ NPHY_RXCAL_TONEAMP, 0, cal_type, -+ false); -+ -+ if (debug) -+ mdelay(WAIT_FOR_SCOPE); -+ -+ wlc_phy_calc_rx_iq_comp_nphy(pi, rx_core + 1); -+ wlc_phy_stopplayback_nphy(pi); -+ } -+ -+ if (((cal_type == 1) || (cal_type == 2)) -+ && NREV_LT(pi->pubpi.phy_rev, 7)) { -+ -+ if (rx_core == PHY_CORE_1) { -+ -+ if (rxcore_state == 1) -+ wlc_phy_rxcore_setstate_nphy( -+ (struct brcms_phy_pub *) pi, 3); -+ -+ wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL, -+ 1); -+ -+ best_rccal[rx_core] = -+ wlc_phy_rc_sweep_nphy(pi, rx_core, 1); -+ pi->nphy_rccal_value = best_rccal[rx_core]; -+ -+ if (rxcore_state == 1) -+ wlc_phy_rxcore_setstate_nphy( -+ (struct brcms_phy_pub *) pi, -+ rxcore_state); -+ } -+ } -+ -+ wlc_phy_rxcal_radio_cleanup_nphy(pi, rx_core); -+ -+ wlc_phy_rxcal_phycleanup_nphy(pi, rx_core); -+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); -+ } -+ -+ if ((cal_type == 1) || (cal_type == 2)) { -+ -+ best_rccal[0] = best_rccal[1]; -+ write_radio_reg(pi, -+ (RADIO_2056_RX_RXLPF_RCCAL_LPC | -+ RADIO_2056_RX0), (best_rccal[0] | 0x80)); -+ -+ for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) { -+ rxlpf_rccal_hpc = -+ (((int)best_rccal[rx_core] - 12) >> 1) + 10; -+ txlpf_rccal_lpc = ((int)best_rccal[rx_core] - 12) + 10; -+ -+ if (PHY_IPA(pi)) { -+ txlpf_rccal_lpc += -+ (pi->bw == WL_CHANSPEC_BW_40) ? 24 : 12; -+ txlpf_idac = (pi->bw == WL_CHANSPEC_BW_40) ? -+ 0x0e : 0x13; -+ WRITE_RADIO_REG2(pi, RADIO_2056, TX, rx_core, -+ TXLPF_IDAC_4, txlpf_idac); -+ } -+ -+ rxlpf_rccal_hpc = max(min_t(u8, rxlpf_rccal_hpc, 31), -+ 0); -+ txlpf_rccal_lpc = max(min_t(u8, txlpf_rccal_lpc, 31), -+ 0); -+ -+ write_radio_reg(pi, (RADIO_2056_RX_RXLPF_RCCAL_HPC | -+ ((rx_core == -+ PHY_CORE_0) ? RADIO_2056_RX0 : -+ RADIO_2056_RX1)), -+ (rxlpf_rccal_hpc | 0x80)); -+ -+ write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | -+ ((rx_core == -+ PHY_CORE_0) ? RADIO_2056_TX0 : -+ RADIO_2056_TX1)), -+ (txlpf_rccal_lpc | 0x80)); -+ } -+ } -+ -+ write_phy_reg(pi, 0x01, orig_BBConfig); -+ -+ wlc_phy_resetcca_nphy(pi); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ wlc_phy_rfctrl_override_1tomany_nphy( -+ pi, -+ NPHY_REV7_RfctrlOverride_cmd_rxgain, -+ 0, 0x3, 1); -+ else -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1); -+ -+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, -+ gain_save); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 4)) -+ pi->phyhang_avoid = phyhang_avoid_state; -+ -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+ -+ return 0; -+} -+ -+static int -+wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi, -+ struct nphy_txgains target_gain, bool debug) -+{ -+ struct phy_iq_est est[PHY_CORE_MAX]; -+ u8 core_num, rx_core, tx_core; -+ u16 lna_vals[] = { 0x3, 0x3, 0x1 }; -+ u16 hpf1_vals[] = { 0x7, 0x2, 0x0 }; -+ u16 hpf2_vals[] = { 0x2, 0x0, 0x0 }; -+ s16 curr_hpf1, curr_hpf2, curr_hpf, curr_lna; -+ s16 desired_log2_pwr, actual_log2_pwr, hpf_change; -+ u16 orig_RfseqCoreActv, orig_AfectrlCore, orig_AfectrlOverride; -+ u16 orig_RfctrlIntcRx, orig_RfctrlIntcTx; -+ u16 num_samps; -+ u32 i_pwr, q_pwr, tot_pwr[3]; -+ u8 gain_pass, use_hpf_num; -+ u16 mask, val1, val2; -+ u16 core_no; -+ u16 gain_save[2]; -+ u16 cal_gain[2]; -+ struct nphy_iqcal_params cal_params[2]; -+ u8 phy_bw; -+ int bcmerror = 0; -+ bool first_playtone = true; -+ -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 2)) -+ wlc_phy_reapply_txcal_coeffs_nphy(pi); -+ -+ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save); -+ -+ for (core_no = 0; core_no <= 1; core_no++) { -+ wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain, -+ &cal_params[core_no]); -+ cal_gain[core_no] = cal_params[core_no].cal_gain; -+ } -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain); -+ -+ num_samps = 1024; -+ desired_log2_pwr = 13; -+ -+ for (core_num = 0; core_num < 2; core_num++) { -+ -+ rx_core = core_num; -+ tx_core = 1 - core_num; -+ -+ orig_RfseqCoreActv = read_phy_reg(pi, 0xa2); -+ orig_AfectrlCore = read_phy_reg(pi, (rx_core == PHY_CORE_0) ? -+ 0xa6 : 0xa7); -+ orig_AfectrlOverride = read_phy_reg(pi, 0xa5); -+ orig_RfctrlIntcRx = read_phy_reg(pi, (rx_core == PHY_CORE_0) ? -+ 0x91 : 0x92); -+ orig_RfctrlIntcTx = read_phy_reg(pi, (tx_core == PHY_CORE_0) ? -+ 0x91 : 0x92); -+ -+ mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12); -+ mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0); -+ -+ or_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7), -+ ((0x1 << 1) | (0x1 << 2))); -+ or_phy_reg(pi, 0xa5, ((0x1 << 1) | (0x1 << 2))); -+ -+ if (((pi->nphy_rxcalparams) & 0xff000000)) -+ write_phy_reg(pi, -+ (rx_core == PHY_CORE_0) ? 0x91 : 0x92, -+ (CHSPEC_IS5G(pi->radio_chanspec) ? -+ 0x140 : 0x110)); -+ else -+ write_phy_reg(pi, -+ (rx_core == PHY_CORE_0) ? 0x91 : 0x92, -+ (CHSPEC_IS5G(pi->radio_chanspec) ? -+ 0x180 : 0x120)); -+ -+ write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 : 0x92, -+ (CHSPEC_IS5G(pi->radio_chanspec) ? 0x148 : -+ 0x114)); -+ -+ mask = RADIO_2055_COUPLE_RX_MASK | RADIO_2055_COUPLE_TX_MASK; -+ if (rx_core == PHY_CORE_0) { -+ val1 = RADIO_2055_COUPLE_RX_MASK; -+ val2 = RADIO_2055_COUPLE_TX_MASK; -+ } else { -+ val1 = RADIO_2055_COUPLE_TX_MASK; -+ val2 = RADIO_2055_COUPLE_RX_MASK; -+ } -+ -+ if ((pi->nphy_rxcalparams & 0x10000)) { -+ mod_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, mask, -+ val1); -+ mod_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, mask, -+ val2); -+ } -+ -+ for (gain_pass = 0; gain_pass < 4; gain_pass++) { -+ -+ if (debug) -+ mdelay(WAIT_FOR_SCOPE); -+ -+ if (gain_pass < 3) { -+ curr_lna = lna_vals[gain_pass]; -+ curr_hpf1 = hpf1_vals[gain_pass]; -+ curr_hpf2 = hpf2_vals[gain_pass]; -+ } else { -+ -+ if (tot_pwr[1] > 10000) { -+ curr_lna = lna_vals[2]; -+ curr_hpf1 = hpf1_vals[2]; -+ curr_hpf2 = hpf2_vals[2]; -+ use_hpf_num = 1; -+ curr_hpf = curr_hpf1; -+ actual_log2_pwr = -+ wlc_phy_nbits(tot_pwr[2]); -+ } else { -+ if (tot_pwr[0] > 10000) { -+ curr_lna = lna_vals[1]; -+ curr_hpf1 = hpf1_vals[1]; -+ curr_hpf2 = hpf2_vals[1]; -+ use_hpf_num = 1; -+ curr_hpf = curr_hpf1; -+ actual_log2_pwr = -+ wlc_phy_nbits( -+ tot_pwr[1]); -+ } else { -+ curr_lna = lna_vals[0]; -+ curr_hpf1 = hpf1_vals[0]; -+ curr_hpf2 = hpf2_vals[0]; -+ use_hpf_num = 2; -+ curr_hpf = curr_hpf2; -+ actual_log2_pwr = -+ wlc_phy_nbits( -+ tot_pwr[0]); -+ } -+ } -+ -+ hpf_change = desired_log2_pwr - actual_log2_pwr; -+ curr_hpf += hpf_change; -+ curr_hpf = max(min_t(u16, curr_hpf, 10), 0); -+ if (use_hpf_num == 1) -+ curr_hpf1 = curr_hpf; -+ else -+ curr_hpf2 = curr_hpf; -+ } -+ -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10), -+ ((curr_hpf2 << 8) | -+ (curr_hpf1 << 4) | -+ (curr_lna << 2)), 0x3, 0); -+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); -+ -+ wlc_phy_stopplayback_nphy(pi); -+ -+ if (first_playtone) { -+ bcmerror = wlc_phy_tx_tone_nphy(pi, 4000, -+ (u16) (pi->nphy_rxcalparams & -+ 0xffff), 0, 0, true); -+ first_playtone = false; -+ } else { -+ phy_bw = (CHSPEC_IS40(pi->radio_chanspec)) ? -+ 40 : 20; -+ wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff, -+ 0, 0, 0, true); -+ } -+ -+ if (bcmerror == 0) { -+ if (gain_pass < 3) { -+ -+ wlc_phy_rx_iq_est_nphy(pi, est, -+ num_samps, 32, -+ 0); -+ i_pwr = (est[rx_core].i_pwr + -+ num_samps / 2) / num_samps; -+ q_pwr = (est[rx_core].q_pwr + -+ num_samps / 2) / num_samps; -+ tot_pwr[gain_pass] = i_pwr + q_pwr; -+ } else { -+ -+ wlc_phy_calc_rx_iq_comp_nphy(pi, -+ (1 << -+ rx_core)); -+ } -+ -+ wlc_phy_stopplayback_nphy(pi); -+ } -+ -+ if (bcmerror != 0) -+ break; -+ } -+ -+ and_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, ~mask); -+ and_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, ~mask); -+ -+ write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 : -+ 0x92, orig_RfctrlIntcTx); -+ write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x91 : -+ 0x92, orig_RfctrlIntcRx); -+ write_phy_reg(pi, 0xa5, orig_AfectrlOverride); -+ write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : -+ 0xa7, orig_AfectrlCore); -+ write_phy_reg(pi, 0xa2, orig_RfseqCoreActv); -+ -+ if (bcmerror != 0) -+ break; -+ } -+ -+ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10), 0, 0x3, 1); -+ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, -+ gain_save); -+ -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+ -+ return bcmerror; -+} -+ -+int -+wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, -+ u8 cal_type, bool debug) -+{ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ cal_type = 0; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) -+ return wlc_phy_cal_rxiq_nphy_rev3(pi, target_gain, cal_type, -+ debug); -+ else -+ return wlc_phy_cal_rxiq_nphy_rev2(pi, target_gain, debug); -+} -+ -+void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi) -+{ -+ uint core; -+ u32 txgain; -+ u16 rad_gain, dac_gain, bbmult, m1m2; -+ u8 txpi[2], chan_freq_range; -+ s32 rfpwr_offset; -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ if (pi->sh->sromrev < 4) { -+ txpi[0] = txpi[1] = 72; -+ } else { -+ -+ chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0); -+ switch (chan_freq_range) { -+ case WL_CHAN_FREQ_RANGE_2G: -+ txpi[0] = pi->nphy_txpid2g[0]; -+ txpi[1] = pi->nphy_txpid2g[1]; -+ break; -+ case WL_CHAN_FREQ_RANGE_5GL: -+ txpi[0] = pi->nphy_txpid5gl[0]; -+ txpi[1] = pi->nphy_txpid5gl[1]; -+ break; -+ case WL_CHAN_FREQ_RANGE_5GM: -+ txpi[0] = pi->nphy_txpid5g[0]; -+ txpi[1] = pi->nphy_txpid5g[1]; -+ break; -+ case WL_CHAN_FREQ_RANGE_5GH: -+ txpi[0] = pi->nphy_txpid5gh[0]; -+ txpi[1] = pi->nphy_txpid5gh[1]; -+ break; -+ default: -+ txpi[0] = txpi[1] = 91; -+ break; -+ } -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) -+ txpi[0] = txpi[1] = 30; -+ else if (NREV_GE(pi->pubpi.phy_rev, 3)) -+ txpi[0] = txpi[1] = 40; -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 7)) { -+ -+ if ((txpi[0] < 40) || (txpi[0] > 100) || -+ (txpi[1] < 40) || (txpi[1] > 100)) -+ txpi[0] = txpi[1] = 91; -+ } -+ -+ pi->nphy_txpwrindex[PHY_CORE_0].index_internal = txpi[0]; -+ pi->nphy_txpwrindex[PHY_CORE_1].index_internal = txpi[1]; -+ pi->nphy_txpwrindex[PHY_CORE_0].index_internal_save = txpi[0]; -+ pi->nphy_txpwrindex[PHY_CORE_1].index_internal_save = txpi[1]; -+ -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ uint phyrev = pi->pubpi.phy_rev; -+ -+ if (NREV_GE(phyrev, 3)) { -+ if (PHY_IPA(pi)) { -+ u32 *tx_gaintbl = -+ wlc_phy_get_ipa_gaintbl_nphy(pi); -+ txgain = tx_gaintbl[txpi[core]]; -+ } else { -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ if (NREV_IS(phyrev, 3)) { -+ txgain = -+ nphy_tpc_5GHz_txgain_rev3 -+ [txpi[core]]; -+ } else if (NREV_IS(phyrev, 4)) { -+ txgain = ( -+ pi->srom_fem5g.extpagain == -+ 3) ? -+ nphy_tpc_5GHz_txgain_HiPwrEPA -+ [txpi[core]] : -+ nphy_tpc_5GHz_txgain_rev4 -+ [txpi[core]]; -+ } else { -+ txgain = -+ nphy_tpc_5GHz_txgain_rev5 -+ [txpi[core]]; -+ } -+ } else { -+ if (NREV_GE(phyrev, 5) && -+ (pi->srom_fem2g.extpagain == 3)) { -+ txgain = -+ nphy_tpc_txgain_HiPwrEPA -+ [txpi[core]]; -+ } else { -+ txgain = nphy_tpc_txgain_rev3 -+ [txpi[core]]; -+ } -+ } -+ } -+ } else { -+ txgain = nphy_tpc_txgain[txpi[core]]; -+ } -+ -+ if (NREV_GE(phyrev, 3)) -+ rad_gain = (txgain >> 16) & ((1 << (32 - 16 + 1)) - 1); -+ else -+ rad_gain = (txgain >> 16) & ((1 << (28 - 16 + 1)) - 1); -+ -+ if (NREV_GE(phyrev, 7)) -+ dac_gain = (txgain >> 8) & ((1 << (10 - 8 + 1)) - 1); -+ else -+ dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1); -+ -+ bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1); -+ -+ if (NREV_GE(phyrev, 3)) -+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f : -+ 0xa5), (0x1 << 8), (0x1 << 8)); -+ else -+ mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14)); -+ -+ write_phy_reg(pi, (core == PHY_CORE_0) ? 0xaa : 0xab, dac_gain); -+ -+ wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16, -+ &rad_gain); -+ -+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2); -+ m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00); -+ m1m2 |= ((core == PHY_CORE_0) ? (bbmult << 8) : (bbmult << 0)); -+ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2); -+ -+ if (PHY_IPA(pi)) { -+ wlc_phy_table_read_nphy(pi, -+ (core == -+ PHY_CORE_0 ? -+ NPHY_TBL_ID_CORE1TXPWRCTL : -+ NPHY_TBL_ID_CORE2TXPWRCTL), 1, -+ 576 + txpi[core], 32, -+ &rfpwr_offset); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1ff << 4), -+ ((s16) rfpwr_offset) << 4); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 2), (1) << 2); -+ -+ } -+ } -+ -+ and_phy_reg(pi, 0xbf, (u16) (~(0x1f << 0))); -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+} -+ -+static void -+wlc_phy_txpwr_nphy_srom_convert(u8 *srom_max, u16 *pwr_offset, -+ u8 tmp_max_pwr, u8 rate_start, -+ u8 rate_end) -+{ -+ u8 rate; -+ u8 word_num, nibble_num; -+ u8 tmp_nibble; -+ -+ for (rate = rate_start; rate <= rate_end; rate++) { -+ word_num = (rate - rate_start) >> 2; -+ nibble_num = (rate - rate_start) & 0x3; -+ tmp_nibble = (pwr_offset[word_num] >> 4 * nibble_num) & 0xf; -+ -+ srom_max[rate] = tmp_max_pwr - 2 * tmp_nibble; -+ } -+} -+ -+static void -+wlc_phy_txpwr_nphy_po_apply(u8 *srom_max, u8 pwr_offset, -+ u8 rate_start, u8 rate_end) -+{ -+ u8 rate; -+ -+ for (rate = rate_start; rate <= rate_end; rate++) -+ srom_max[rate] -= 2 * pwr_offset; -+} -+ -+void -+wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start, -+ u8 rate_mcs_end, u8 rate_ofdm_start) -+{ -+ u8 rate1, rate2; -+ -+ rate2 = rate_ofdm_start; -+ for (rate1 = rate_mcs_start; rate1 <= rate_mcs_end - 1; rate1++) { -+ power[rate1] = power[rate2]; -+ rate2 += (rate1 == rate_mcs_start) ? 2 : 1; -+ } -+ power[rate_mcs_end] = power[rate_mcs_end - 1]; -+} -+ -+void -+wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power, u8 rate_ofdm_start, -+ u8 rate_ofdm_end, u8 rate_mcs_start) -+{ -+ u8 rate1, rate2; -+ -+ for (rate1 = rate_ofdm_start, rate2 = rate_mcs_start; -+ rate1 <= rate_ofdm_end; rate1++, rate2++) { -+ power[rate1] = power[rate2]; -+ if (rate1 == rate_ofdm_start) -+ power[++rate1] = power[rate2]; -+ } -+} -+ -+void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi) -+{ -+ uint rate1, rate2, band_num; -+ u8 tmp_bw40po = 0, tmp_cddpo = 0, tmp_stbcpo = 0; -+ u8 tmp_max_pwr = 0; -+ u16 pwr_offsets1[2], *pwr_offsets2 = NULL; -+ u8 *tx_srom_max_rate = NULL; -+ -+ for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); -+ band_num++) { -+ switch (band_num) { -+ case 0: -+ -+ tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_2g, -+ pi->nphy_pwrctrl_info[1].max_pwr_2g); -+ -+ pwr_offsets1[0] = pi->cck2gpo; -+ wlc_phy_txpwr_nphy_srom_convert(pi->tx_srom_max_rate_2g, -+ pwr_offsets1, -+ tmp_max_pwr, -+ TXP_FIRST_CCK, -+ TXP_LAST_CCK); -+ -+ pwr_offsets1[0] = (u16) (pi->ofdm2gpo & 0xffff); -+ pwr_offsets1[1] = -+ (u16) (pi->ofdm2gpo >> 16) & 0xffff; -+ -+ pwr_offsets2 = pi->mcs2gpo; -+ -+ tmp_cddpo = pi->cdd2gpo; -+ tmp_stbcpo = pi->stbc2gpo; -+ tmp_bw40po = pi->bw402gpo; -+ -+ tx_srom_max_rate = pi->tx_srom_max_rate_2g; -+ break; -+ case 1: -+ -+ tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gm, -+ pi->nphy_pwrctrl_info[1].max_pwr_5gm); -+ -+ pwr_offsets1[0] = (u16) (pi->ofdm5gpo & 0xffff); -+ pwr_offsets1[1] = -+ (u16) (pi->ofdm5gpo >> 16) & 0xffff; -+ -+ pwr_offsets2 = pi->mcs5gpo; -+ -+ tmp_cddpo = pi->cdd5gpo; -+ tmp_stbcpo = pi->stbc5gpo; -+ tmp_bw40po = pi->bw405gpo; -+ -+ tx_srom_max_rate = pi->tx_srom_max_rate_5g_mid; -+ break; -+ case 2: -+ -+ tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gl, -+ pi->nphy_pwrctrl_info[1].max_pwr_5gl); -+ -+ pwr_offsets1[0] = (u16) (pi->ofdm5glpo & 0xffff); -+ pwr_offsets1[1] = -+ (u16) (pi->ofdm5glpo >> 16) & 0xffff; -+ -+ pwr_offsets2 = pi->mcs5glpo; -+ -+ tmp_cddpo = pi->cdd5glpo; -+ tmp_stbcpo = pi->stbc5glpo; -+ tmp_bw40po = pi->bw405glpo; -+ -+ tx_srom_max_rate = pi->tx_srom_max_rate_5g_low; -+ break; -+ case 3: -+ -+ tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gh, -+ pi->nphy_pwrctrl_info[1].max_pwr_5gh); -+ -+ pwr_offsets1[0] = (u16) (pi->ofdm5ghpo & 0xffff); -+ pwr_offsets1[1] = -+ (u16) (pi->ofdm5ghpo >> 16) & 0xffff; -+ -+ pwr_offsets2 = pi->mcs5ghpo; -+ -+ tmp_cddpo = pi->cdd5ghpo; -+ tmp_stbcpo = pi->stbc5ghpo; -+ tmp_bw40po = pi->bw405ghpo; -+ -+ tx_srom_max_rate = pi->tx_srom_max_rate_5g_hi; -+ break; -+ } -+ -+ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets1, -+ tmp_max_pwr, TXP_FIRST_OFDM, -+ TXP_LAST_OFDM); -+ -+ wlc_phy_ofdm_to_mcs_powers_nphy(tx_srom_max_rate, -+ TXP_FIRST_MCS_20_SISO, -+ TXP_LAST_MCS_20_SISO, -+ TXP_FIRST_OFDM); -+ -+ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets2, -+ tmp_max_pwr, -+ TXP_FIRST_MCS_20_CDD, -+ TXP_LAST_MCS_20_CDD); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) -+ wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo, -+ TXP_FIRST_MCS_20_CDD, -+ TXP_LAST_MCS_20_CDD); -+ -+ wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate, -+ TXP_FIRST_OFDM_20_CDD, -+ TXP_LAST_OFDM_20_CDD, -+ TXP_FIRST_MCS_20_CDD); -+ -+ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets2, -+ tmp_max_pwr, -+ TXP_FIRST_MCS_20_STBC, -+ TXP_LAST_MCS_20_STBC); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) -+ wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, -+ tmp_stbcpo, -+ TXP_FIRST_MCS_20_STBC, -+ TXP_LAST_MCS_20_STBC); -+ -+ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, -+ &pwr_offsets2[2], tmp_max_pwr, -+ TXP_FIRST_MCS_20_SDM, -+ TXP_LAST_MCS_20_SDM); -+ -+ if (NPHY_IS_SROM_REINTERPRET) { -+ -+ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, -+ &pwr_offsets2[4], -+ tmp_max_pwr, -+ TXP_FIRST_MCS_40_SISO, -+ TXP_LAST_MCS_40_SISO); -+ -+ wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate, -+ TXP_FIRST_OFDM_40_SISO, -+ TXP_LAST_OFDM_40_SISO, -+ TXP_FIRST_MCS_40_SISO); -+ -+ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, -+ &pwr_offsets2[4], -+ tmp_max_pwr, -+ TXP_FIRST_MCS_40_CDD, -+ TXP_LAST_MCS_40_CDD); -+ -+ wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo, -+ TXP_FIRST_MCS_40_CDD, -+ TXP_LAST_MCS_40_CDD); -+ -+ wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate, -+ TXP_FIRST_OFDM_40_CDD, -+ TXP_LAST_OFDM_40_CDD, -+ TXP_FIRST_MCS_40_CDD); -+ -+ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, -+ &pwr_offsets2[4], -+ tmp_max_pwr, -+ TXP_FIRST_MCS_40_STBC, -+ TXP_LAST_MCS_40_STBC); -+ -+ wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, -+ tmp_stbcpo, -+ TXP_FIRST_MCS_40_STBC, -+ TXP_LAST_MCS_40_STBC); -+ -+ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, -+ &pwr_offsets2[6], -+ tmp_max_pwr, -+ TXP_FIRST_MCS_40_SDM, -+ TXP_LAST_MCS_40_SDM); -+ } else { -+ -+ for (rate1 = TXP_FIRST_OFDM_40_SISO, rate2 = -+ TXP_FIRST_OFDM; -+ rate1 <= TXP_LAST_MCS_40_SDM; -+ rate1++, rate2++) -+ tx_srom_max_rate[rate1] = -+ tx_srom_max_rate[rate2]; -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) -+ wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, -+ tmp_bw40po, -+ TXP_FIRST_OFDM_40_SISO, -+ TXP_LAST_MCS_40_SDM); -+ -+ tx_srom_max_rate[TXP_MCS_32] = -+ tx_srom_max_rate[TXP_FIRST_MCS_40_CDD]; -+ } -+ -+ return; -+} -+ -+void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi) -+{ -+ u8 tx_pwr_ctrl_state; -+ wlc_phy_txpwr_limit_to_tbl_nphy(pi); -+ wlc_phy_txpwrctrl_pwr_setup_nphy(pi); -+ -+ tx_pwr_ctrl_state = pi->nphy_txpwrctrl; -+ -+ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) { -+ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK); -+ (void)R_REG(&pi->regs->maccontrol); -+ udelay(1); -+ } -+ -+ wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state); -+ -+ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) -+ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0); -+} -+ -+static bool wlc_phy_txpwr_ison_nphy(struct brcms_phy *pi) -+{ -+ return read_phy_reg((pi), 0x1e7) & ((0x1 << 15) | -+ (0x1 << 14) | (0x1 << 13)); -+} -+ -+u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi) -+{ -+ u16 tmp; -+ u16 pwr_idx[2]; -+ -+ if (wlc_phy_txpwr_ison_nphy(pi)) { -+ pwr_idx[0] = wlc_phy_txpwr_idx_cur_get_nphy(pi, PHY_CORE_0); -+ pwr_idx[1] = wlc_phy_txpwr_idx_cur_get_nphy(pi, PHY_CORE_1); -+ -+ tmp = (pwr_idx[0] << 8) | pwr_idx[1]; -+ } else { -+ tmp = ((pi->nphy_txpwrindex[PHY_CORE_0].index_internal & 0xff) -+ << 8) | -+ (pi->nphy_txpwrindex[PHY_CORE_1].index_internal & 0xff); -+ } -+ -+ return tmp; -+} -+ -+void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi) -+{ -+ if (PHY_IPA(pi) -+ && (pi->nphy_force_papd_cal -+ || (wlc_phy_txpwr_ison_nphy(pi) -+ && -+ (((u32) -+ abs(wlc_phy_txpwr_idx_cur_get_nphy(pi, 0) - -+ pi->nphy_papd_tx_gain_at_last_cal[0]) >= 4) -+ || ((u32) -+ abs(wlc_phy_txpwr_idx_cur_get_nphy(pi, 1) - -+ pi->nphy_papd_tx_gain_at_last_cal[1]) >= 4))))) -+ wlc_phy_a4(pi, true); -+} -+ -+void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type) -+{ -+ u16 mask = 0, val = 0, ishw = 0; -+ u8 ctr; -+ uint core; -+ u32 tbl_offset; -+ u32 tbl_len; -+ u16 regval[84]; -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ switch (ctrl_type) { -+ case PHY_TPC_HW_OFF: -+ case PHY_TPC_HW_ON: -+ pi->nphy_txpwrctrl = ctrl_type; -+ break; -+ default: -+ break; -+ } -+ -+ if (ctrl_type == PHY_TPC_HW_OFF) { -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ -+ if (wlc_phy_txpwr_ison_nphy(pi)) { -+ for (core = 0; core < pi->pubpi.phy_corenum; -+ core++) -+ pi->nphy_txpwr_idx[core] = -+ wlc_phy_txpwr_idx_cur_get_nphy( -+ pi, -+ (u8) core); -+ } -+ -+ } -+ -+ tbl_len = 84; -+ tbl_offset = 64; -+ for (ctr = 0; ctr < tbl_len; ctr++) -+ regval[ctr] = 0; -+ wlc_phy_table_write_nphy(pi, 26, tbl_len, tbl_offset, 16, -+ regval); -+ wlc_phy_table_write_nphy(pi, 27, tbl_len, tbl_offset, 16, -+ regval); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) -+ and_phy_reg(pi, 0x1e7, -+ (u16) (~((0x1 << 15) | -+ (0x1 << 14) | (0x1 << 13)))); -+ else -+ and_phy_reg(pi, 0x1e7, -+ (u16) (~((0x1 << 14) | (0x1 << 13)))); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ or_phy_reg(pi, 0x8f, (0x1 << 8)); -+ or_phy_reg(pi, 0xa5, (0x1 << 8)); -+ } else { -+ or_phy_reg(pi, 0xa5, (0x1 << 14)); -+ } -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 2)) -+ mod_phy_reg(pi, 0xdc, 0x00ff, 0x53); -+ else if (NREV_LT(pi->pubpi.phy_rev, 2)) -+ mod_phy_reg(pi, 0xdc, 0x00ff, 0x5a); -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 2) && -+ pi->bw == WL_CHANSPEC_BW_40) -+ wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR, -+ MHF1_IQSWAP_WAR, BRCM_BAND_ALL); -+ -+ } else { -+ -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64, -+ 8, pi->adj_pwr_tbl_nphy); -+ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64, -+ 8, pi->adj_pwr_tbl_nphy); -+ -+ ishw = (ctrl_type == PHY_TPC_HW_ON) ? 0x1 : 0x0; -+ mask = (0x1 << 14) | (0x1 << 13); -+ val = (ishw << 14) | (ishw << 13); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ mask |= (0x1 << 15); -+ val |= (ishw << 15); -+ } -+ -+ mod_phy_reg(pi, 0x1e7, mask, val); -+ -+ if (CHSPEC_IS5G(pi->radio_chanspec)) { -+ if (NREV_GE(pi->pubpi.phy_rev, 7)) { -+ mod_phy_reg(pi, 0x1e7, (0x7f << 0), 0x32); -+ mod_phy_reg(pi, 0x222, (0xff << 0), 0x32); -+ } else { -+ mod_phy_reg(pi, 0x1e7, (0x7f << 0), 0x64); -+ if (NREV_GT(pi->pubpi.phy_rev, 1)) -+ mod_phy_reg(pi, 0x222, -+ (0xff << 0), 0x64); -+ } -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ if ((pi->nphy_txpwr_idx[0] != 128) -+ && (pi->nphy_txpwr_idx[1] != 128)) -+ wlc_phy_txpwr_idx_cur_set_nphy(pi, -+ pi-> -+ nphy_txpwr_idx -+ [0], -+ pi-> -+ nphy_txpwr_idx -+ [1]); -+ } -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ and_phy_reg(pi, 0x8f, ~(0x1 << 8)); -+ and_phy_reg(pi, 0xa5, ~(0x1 << 8)); -+ } else { -+ and_phy_reg(pi, 0xa5, ~(0x1 << 14)); -+ } -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 2)) -+ mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b); -+ else if (NREV_LT(pi->pubpi.phy_rev, 2)) -+ mod_phy_reg(pi, 0xdc, 0x00ff, 0x40); -+ -+ if (NREV_LT(pi->pubpi.phy_rev, 2) && -+ pi->bw == WL_CHANSPEC_BW_40) -+ wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR, -+ 0x0, BRCM_BAND_ALL); -+ -+ if (PHY_IPA(pi)) { -+ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 2), (0) << 2); -+ -+ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 2), (0) << 2); -+ -+ } -+ -+ } -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+} -+ -+void -+wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex, -+ bool restore_cals) -+{ -+ u8 core, txpwrctl_tbl; -+ u16 tx_ind0, iq_ind0, lo_ind0; -+ u16 m1m2; -+ u32 txgain; -+ u16 rad_gain, dac_gain; -+ u8 bbmult; -+ u32 iqcomp; -+ u16 iqcomp_a, iqcomp_b; -+ u32 locomp; -+ u16 tmpval; -+ u8 tx_pwr_ctrl_state; -+ s32 rfpwr_offset; -+ u16 regval[2]; -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ -+ tx_ind0 = 192; -+ iq_ind0 = 320; -+ lo_ind0 = 448; -+ -+ for (core = 0; core < pi->pubpi.phy_corenum; core++) { -+ -+ if ((core_mask & (1 << core)) == 0) -+ continue; -+ -+ txpwrctl_tbl = (core == PHY_CORE_0) ? 26 : 27; -+ -+ if (txpwrindex < 0) { -+ if (pi->nphy_txpwrindex[core].index < 0) -+ continue; -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ mod_phy_reg(pi, 0x8f, -+ (0x1 << 8), -+ pi->nphy_txpwrindex[core]. -+ AfectrlOverride); -+ mod_phy_reg(pi, 0xa5, (0x1 << 8), -+ pi->nphy_txpwrindex[core]. -+ AfectrlOverride); -+ } else { -+ mod_phy_reg(pi, 0xa5, -+ (0x1 << 14), -+ pi->nphy_txpwrindex[core]. -+ AfectrlOverride); -+ } -+ -+ write_phy_reg(pi, (core == PHY_CORE_0) ? -+ 0xaa : 0xab, -+ pi->nphy_txpwrindex[core].AfeCtrlDacGain); -+ -+ wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16, -+ &pi->nphy_txpwrindex[core]. -+ rad_gain); -+ -+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2); -+ m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00); -+ m1m2 |= ((core == PHY_CORE_0) ? -+ (pi->nphy_txpwrindex[core].bbmult << 8) : -+ (pi->nphy_txpwrindex[core].bbmult << 0)); -+ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2); -+ -+ if (restore_cals) { -+ wlc_phy_table_write_nphy( -+ pi, 15, 2, (80 + 2 * core), 16, -+ &pi->nphy_txpwrindex[core].iqcomp_a); -+ wlc_phy_table_write_nphy( -+ pi, 15, 1, (85 + core), 16, -+ &pi->nphy_txpwrindex[core].locomp); -+ wlc_phy_table_write_nphy( -+ pi, 15, 1, (93 + core), 16, -+ &pi->nphy_txpwrindex[core].locomp); -+ } -+ -+ wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl); -+ -+ pi->nphy_txpwrindex[core].index_internal = -+ pi->nphy_txpwrindex[core].index_internal_save; -+ } else { -+ -+ if (pi->nphy_txpwrindex[core].index < 0) { -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) { -+ mod_phy_reg(pi, 0x8f, -+ (0x1 << 8), -+ pi->nphy_txpwrindex[core]. -+ AfectrlOverride); -+ mod_phy_reg(pi, 0xa5, (0x1 << 8), -+ pi->nphy_txpwrindex[core]. -+ AfectrlOverride); -+ } else { -+ pi->nphy_txpwrindex[core]. -+ AfectrlOverride = -+ read_phy_reg(pi, 0xa5); -+ } -+ -+ pi->nphy_txpwrindex[core].AfeCtrlDacGain = -+ read_phy_reg(pi, (core == PHY_CORE_0) ? -+ 0xaa : 0xab); -+ -+ wlc_phy_table_read_nphy(pi, 7, 1, -+ (0x110 + core), 16, -+ &pi-> -+ nphy_txpwrindex[core]. -+ rad_gain); -+ -+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, -+ &tmpval); -+ tmpval >>= ((core == PHY_CORE_0) ? 8 : 0); -+ tmpval &= 0xff; -+ pi->nphy_txpwrindex[core].bbmult = (u8) tmpval; -+ -+ wlc_phy_table_read_nphy(pi, 15, 2, -+ (80 + 2 * core), 16, -+ &pi-> -+ nphy_txpwrindex[core]. -+ iqcomp_a); -+ -+ wlc_phy_table_read_nphy(pi, 15, 1, (85 + core), -+ 16, -+ &pi-> -+ nphy_txpwrindex[core]. -+ locomp); -+ -+ pi->nphy_txpwrindex[core].index_internal_save = -+ pi->nphy_txpwrindex[core]. -+ index_internal; -+ } -+ -+ tx_pwr_ctrl_state = pi->nphy_txpwrctrl; -+ wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF); -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 1)) -+ wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON); -+ -+ wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1, -+ (tx_ind0 + txpwrindex), 32, -+ &txgain); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) -+ rad_gain = (txgain >> 16) & -+ ((1 << (32 - 16 + 1)) - 1); -+ else -+ rad_gain = (txgain >> 16) & -+ ((1 << (28 - 16 + 1)) - 1); -+ -+ dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1); -+ bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1); -+ -+ if (NREV_GE(pi->pubpi.phy_rev, 3)) -+ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f : -+ 0xa5), (0x1 << 8), (0x1 << 8)); -+ else -+ mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14)); -+ -+ write_phy_reg(pi, (core == PHY_CORE_0) ? -+ 0xaa : 0xab, dac_gain); -+ -+ wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16, -+ &rad_gain); -+ -+ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2); -+ m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00); -+ m1m2 |= ((core == PHY_CORE_0) ? -+ (bbmult << 8) : (bbmult << 0)); -+ -+ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2); -+ -+ wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1, -+ (iq_ind0 + txpwrindex), 32, -+ &iqcomp); -+ iqcomp_a = (iqcomp >> 10) & ((1 << (19 - 10 + 1)) - 1); -+ iqcomp_b = (iqcomp >> 0) & ((1 << (9 - 0 + 1)) - 1); -+ -+ if (restore_cals) { -+ regval[0] = (u16) iqcomp_a; -+ regval[1] = (u16) iqcomp_b; -+ wlc_phy_table_write_nphy(pi, 15, 2, -+ (80 + 2 * core), 16, -+ regval); -+ } -+ -+ wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1, -+ (lo_ind0 + txpwrindex), 32, -+ &locomp); -+ if (restore_cals) -+ wlc_phy_table_write_nphy(pi, 15, 1, (85 + core), -+ 16, &locomp); -+ -+ if (NREV_IS(pi->pubpi.phy_rev, 1)) -+ wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF); -+ -+ if (PHY_IPA(pi)) { -+ wlc_phy_table_read_nphy(pi, -+ (core == PHY_CORE_0 ? -+ NPHY_TBL_ID_CORE1TXPWRCTL : -+ NPHY_TBL_ID_CORE2TXPWRCTL), -+ 1, 576 + txpwrindex, 32, -+ &rfpwr_offset); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1ff << 4), -+ ((s16) rfpwr_offset) << 4); -+ -+ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : -+ 0x29b, (0x1 << 2), (1) << 2); -+ -+ } -+ -+ wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state); -+ } -+ -+ pi->nphy_txpwrindex[core].index = txpwrindex; -+ } -+ -+ if (pi->phyhang_avoid) -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+} -+ -+void -+wlc_phy_txpower_sromlimit_get_nphy(struct brcms_phy *pi, uint chan, u8 *max_pwr, -+ u8 txp_rate_idx) -+{ -+ u8 chan_freq_range; -+ -+ chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, chan); -+ switch (chan_freq_range) { -+ case WL_CHAN_FREQ_RANGE_2G: -+ *max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx]; -+ break; -+ case WL_CHAN_FREQ_RANGE_5GM: -+ *max_pwr = pi->tx_srom_max_rate_5g_mid[txp_rate_idx]; -+ break; -+ case WL_CHAN_FREQ_RANGE_5GL: -+ *max_pwr = pi->tx_srom_max_rate_5g_low[txp_rate_idx]; -+ break; -+ case WL_CHAN_FREQ_RANGE_5GH: -+ *max_pwr = pi->tx_srom_max_rate_5g_hi[txp_rate_idx]; -+ break; -+ default: -+ *max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx]; -+ break; -+ } -+ -+ return; -+} -+ -+void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi, bool enable) -+{ -+ u16 clip_off[] = { 0xffff, 0xffff }; -+ -+ if (enable) { -+ if (pi->nphy_deaf_count == 0) { -+ pi->classifier_state = -+ wlc_phy_classifier_nphy(pi, 0, 0); -+ wlc_phy_classifier_nphy(pi, (0x7 << 0), 4); -+ wlc_phy_clip_det_nphy(pi, 0, pi->clip_state); -+ wlc_phy_clip_det_nphy(pi, 1, clip_off); -+ } -+ -+ pi->nphy_deaf_count++; -+ -+ wlc_phy_resetcca_nphy(pi); -+ -+ } else { -+ pi->nphy_deaf_count--; -+ -+ if (pi->nphy_deaf_count == 0) { -+ wlc_phy_classifier_nphy(pi, (0x7 << 0), -+ pi->classifier_state); -+ wlc_phy_clip_det_nphy(pi, 1, pi->clip_state); -+ } -+ } -+} -+ -+void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode) -+{ -+ wlapi_suspend_mac_and_wait(pi->sh->physhim); -+ -+ if (mode) { -+ if (pi->nphy_deaf_count == 0) -+ wlc_phy_stay_in_carriersearch_nphy(pi, true); -+ } else if (pi->nphy_deaf_count > 0) { -+ wlc_phy_stay_in_carriersearch_nphy(pi, false); -+ } -+ -+ wlapi_enable_mac(pi->sh->physhim); -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.c.orig 2011-11-09 13:46:58.276800245 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.c 2011-11-09 13:47:17.032565765 -0500 -@@ -0,0 +1,308 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include "phy_qmath.h" -+ -+/* -+ * Description: This function make 16 bit unsigned multiplication. -+ * To fit the output into 16 bits the 32 bit multiplication result is right -+ * shifted by 16 bits. -+ */ -+u16 qm_mulu16(u16 op1, u16 op2) -+{ -+ return (u16) (((u32) op1 * (u32) op2) >> 16); -+} -+ -+/* -+ * Description: This function make 16 bit multiplication and return the result -+ * in 16 bits. To fit the multiplication result into 16 bits the multiplication -+ * result is right shifted by 15 bits. Right shifting 15 bits instead of 16 bits -+ * is done to remove the extra sign bit formed due to the multiplication. -+ * When both the 16bit inputs are 0x8000 then the output is saturated to -+ * 0x7fffffff. -+ */ -+s16 qm_muls16(s16 op1, s16 op2) -+{ -+ s32 result; -+ if (op1 == (s16) 0x8000 && op2 == (s16) 0x8000) -+ result = 0x7fffffff; -+ else -+ result = ((s32) (op1) * (s32) (op2)); -+ -+ return (s16) (result >> 15); -+} -+ -+/* -+ * Description: This function add two 32 bit numbers and return the 32bit -+ * result. If the result overflow 32 bits, the output will be saturated to -+ * 32bits. -+ */ -+s32 qm_add32(s32 op1, s32 op2) -+{ -+ s32 result; -+ result = op1 + op2; -+ if (op1 < 0 && op2 < 0 && result > 0) -+ result = 0x80000000; -+ else if (op1 > 0 && op2 > 0 && result < 0) -+ result = 0x7fffffff; -+ -+ return result; -+} -+ -+/* -+ * Description: This function add two 16 bit numbers and return the 16bit -+ * result. If the result overflow 16 bits, the output will be saturated to -+ * 16bits. -+ */ -+s16 qm_add16(s16 op1, s16 op2) -+{ -+ s16 result; -+ s32 temp = (s32) op1 + (s32) op2; -+ if (temp > (s32) 0x7fff) -+ result = (s16) 0x7fff; -+ else if (temp < (s32) 0xffff8000) -+ result = (s16) 0xffff8000; -+ else -+ result = (s16) temp; -+ -+ return result; -+} -+ -+/* -+ * Description: This function make 16 bit subtraction and return the 16bit -+ * result. If the result overflow 16 bits, the output will be saturated to -+ * 16bits. -+ */ -+s16 qm_sub16(s16 op1, s16 op2) -+{ -+ s16 result; -+ s32 temp = (s32) op1 - (s32) op2; -+ if (temp > (s32) 0x7fff) -+ result = (s16) 0x7fff; -+ else if (temp < (s32) 0xffff8000) -+ result = (s16) 0xffff8000; -+ else -+ result = (s16) temp; -+ -+ return result; -+} -+ -+/* -+ * Description: This function make a 32 bit saturated left shift when the -+ * specified shift is +ve. This function will make a 32 bit right shift when -+ * the specified shift is -ve. This function return the result after shifting -+ * operation. -+ */ -+s32 qm_shl32(s32 op, int shift) -+{ -+ int i; -+ s32 result; -+ result = op; -+ if (shift > 31) -+ shift = 31; -+ else if (shift < -31) -+ shift = -31; -+ if (shift >= 0) { -+ for (i = 0; i < shift; i++) -+ result = qm_add32(result, result); -+ } else { -+ result = result >> (-shift); -+ } -+ -+ return result; -+} -+ -+/* -+ * Description: This function make a 16 bit saturated left shift when the -+ * specified shift is +ve. This function will make a 16 bit right shift when -+ * the specified shift is -ve. This function return the result after shifting -+ * operation. -+ */ -+s16 qm_shl16(s16 op, int shift) -+{ -+ int i; -+ s16 result; -+ result = op; -+ if (shift > 15) -+ shift = 15; -+ else if (shift < -15) -+ shift = -15; -+ if (shift > 0) { -+ for (i = 0; i < shift; i++) -+ result = qm_add16(result, result); -+ } else { -+ result = result >> (-shift); -+ } -+ -+ return result; -+} -+ -+/* -+ * Description: This function make a 16 bit right shift when shift is +ve. -+ * This function make a 16 bit saturated left shift when shift is -ve. This -+ * function return the result of the shift operation. -+ */ -+s16 qm_shr16(s16 op, int shift) -+{ -+ return qm_shl16(op, -shift); -+} -+ -+/* -+ * Description: This function return the number of redundant sign bits in a -+ * 32 bit number. Example: qm_norm32(0x00000080) = 23 -+ */ -+s16 qm_norm32(s32 op) -+{ -+ u16 u16extraSignBits; -+ if (op == 0) { -+ return 31; -+ } else { -+ u16extraSignBits = 0; -+ while ((op >> 31) == (op >> 30)) { -+ u16extraSignBits++; -+ op = op << 1; -+ } -+ } -+ return u16extraSignBits; -+} -+ -+/* This table is log2(1+(i/32)) where i=[0:1:31], in q.15 format */ -+static const s16 log_table[] = { -+ 0, -+ 1455, -+ 2866, -+ 4236, -+ 5568, -+ 6863, -+ 8124, -+ 9352, -+ 10549, -+ 11716, -+ 12855, -+ 13968, -+ 15055, -+ 16117, -+ 17156, -+ 18173, -+ 19168, -+ 20143, -+ 21098, -+ 22034, -+ 22952, -+ 23852, -+ 24736, -+ 25604, -+ 26455, -+ 27292, -+ 28114, -+ 28922, -+ 29717, -+ 30498, -+ 31267, -+ 32024 -+}; -+ -+#define LOG_TABLE_SIZE 32 /* log_table size */ -+#define LOG2_LOG_TABLE_SIZE 5 /* log2(log_table size) */ -+#define Q_LOG_TABLE 15 /* qformat of log_table */ -+#define LOG10_2 19728 /* log10(2) in q.16 */ -+ -+/* -+ * Description: -+ * This routine takes the input number N and its q format qN and compute -+ * the log10(N). This routine first normalizes the input no N. Then N is in -+ * mag*(2^x) format. mag is any number in the range 2^30-(2^31 - 1). -+ * Then log2(mag * 2^x) = log2(mag) + x is computed. From that -+ * log10(mag * 2^x) = log2(mag * 2^x) * log10(2) is computed. -+ * This routine looks the log2 value in the table considering -+ * LOG2_LOG_TABLE_SIZE+1 MSBs. As the MSB is always 1, only next -+ * LOG2_OF_LOG_TABLE_SIZE MSBs are used for table lookup. Next 16 MSBs are used -+ * for interpolation. -+ * Inputs: -+ * N - number to which log10 has to be found. -+ * qN - q format of N -+ * log10N - address where log10(N) will be written. -+ * qLog10N - address where log10N qformat will be written. -+ * Note/Problem: -+ * For accurate results input should be in normalized or near normalized form. -+ */ -+void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N) -+{ -+ s16 s16norm, s16tableIndex, s16errorApproximation; -+ u16 u16offset; -+ s32 s32log; -+ -+ /* normalize the N. */ -+ s16norm = qm_norm32(N); -+ N = N << s16norm; -+ -+ /* The qformat of N after normalization. -+ * -30 is added to treat the no as between 1.0 to 2.0 -+ * i.e. after adding the -30 to the qformat the decimal point will be -+ * just rigtht of the MSB. (i.e. after sign bit and 1st MSB). i.e. -+ * at the right side of 30th bit. -+ */ -+ qN = qN + s16norm - 30; -+ -+ /* take the table index as the LOG2_OF_LOG_TABLE_SIZE bits right of the -+ * MSB */ -+ s16tableIndex = (s16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE))); -+ -+ /* remove the MSB. the MSB is always 1 after normalization. */ -+ s16tableIndex = -+ s16tableIndex & (s16) ((1 << LOG2_LOG_TABLE_SIZE) - 1); -+ -+ /* remove the (1+LOG2_OF_LOG_TABLE_SIZE) MSBs in the N. */ -+ N = N & ((1 << (32 - (2 + LOG2_LOG_TABLE_SIZE))) - 1); -+ -+ /* take the offset as the 16 MSBS after table index. -+ */ -+ u16offset = (u16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE + 16))); -+ -+ /* look the log value in the table. */ -+ s32log = log_table[s16tableIndex]; /* q.15 format */ -+ -+ /* interpolate using the offset. q.15 format. */ -+ s16errorApproximation = (s16) qm_mulu16(u16offset, -+ (u16) (log_table[s16tableIndex + 1] - -+ log_table[s16tableIndex])); -+ -+ /* q.15 format */ -+ s32log = qm_add16((s16) s32log, s16errorApproximation); -+ -+ /* adjust for the qformat of the N as -+ * log2(mag * 2^x) = log2(mag) + x -+ */ -+ s32log = qm_add32(s32log, ((s32) -qN) << 15); /* q.15 format */ -+ -+ /* normalize the result. */ -+ s16norm = qm_norm32(s32log); -+ -+ /* bring all the important bits into lower 16 bits */ -+ /* q.15+s16norm-16 format */ -+ s32log = qm_shl32(s32log, s16norm - 16); -+ -+ /* compute the log10(N) by multiplying log2(N) with log10(2). -+ * as log10(mag * 2^x) = log2(mag * 2^x) * log10(2) -+ * log10N in q.15+s16norm-16+1 (LOG10_2 is in q.16) -+ */ -+ *log10N = qm_muls16((s16) s32log, (s16) LOG10_2); -+ -+ /* write the q format of the result. */ -+ *qLog10N = 15 + s16norm - 16 + 1; -+ -+ return; -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.h.orig 2011-11-09 13:46:58.276800245 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.h 2011-11-09 13:47:17.032565765 -0500 -@@ -0,0 +1,42 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_QMATH_H_ -+#define _BRCM_QMATH_H_ -+ -+#include -+ -+u16 qm_mulu16(u16 op1, u16 op2); -+ -+s16 qm_muls16(s16 op1, s16 op2); -+ -+s32 qm_add32(s32 op1, s32 op2); -+ -+s16 qm_add16(s16 op1, s16 op2); -+ -+s16 qm_sub16(s16 op1, s16 op2); -+ -+s32 qm_shl32(s32 op, int shift); -+ -+s16 qm_shl16(s16 op, int shift); -+ -+s16 qm_shr16(s16 op, int shift); -+ -+s16 qm_norm32(s32 op); -+ -+void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N); -+ -+#endif /* #ifndef _BRCM_QMATH_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_radio.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_radio.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_radio.h.orig 2011-11-09 13:46:58.277800233 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_radio.h 2011-11-09 13:47:17.035565729 -0500 -@@ -0,0 +1,1533 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_PHY_RADIO_H_ -+#define _BRCM_PHY_RADIO_H_ -+ -+#define RADIO_IDCODE 0x01 -+ -+#define RADIO_DEFAULT_CORE 0 -+ -+#define RXC0_RSSI_RST 0x80 -+#define RXC0_MODE_RSSI 0x40 -+#define RXC0_MODE_OFF 0x20 -+#define RXC0_MODE_CM 0x10 -+#define RXC0_LAN_LOAD 0x08 -+#define RXC0_OFF_ADJ_MASK 0x07 -+ -+#define TXC0_MODE_TXLPF 0x04 -+#define TXC0_PA_TSSI_EN 0x02 -+#define TXC0_TSSI_EN 0x01 -+ -+#define TXC1_PA_GAIN_MASK 0x60 -+#define TXC1_PA_GAIN_3DB 0x40 -+#define TXC1_PA_GAIN_2DB 0x20 -+#define TXC1_TX_MIX_GAIN 0x10 -+#define TXC1_OFF_I_MASK 0x0c -+#define TXC1_OFF_Q_MASK 0x03 -+ -+#define RADIO_2055_READ_OFF 0x100 -+#define RADIO_2057_READ_OFF 0x200 -+ -+#define RADIO_2055_GEN_SPARE 0x00 -+#define RADIO_2055_SP_PIN_PD 0x02 -+#define RADIO_2055_SP_RSSI_CORE1 0x03 -+#define RADIO_2055_SP_PD_MISC_CORE1 0x04 -+#define RADIO_2055_SP_RSSI_CORE2 0x05 -+#define RADIO_2055_SP_PD_MISC_CORE2 0x06 -+#define RADIO_2055_SP_RX_GC1_CORE1 0x07 -+#define RADIO_2055_SP_RX_GC2_CORE1 0x08 -+#define RADIO_2055_SP_RX_GC1_CORE2 0x09 -+#define RADIO_2055_SP_RX_GC2_CORE2 0x0a -+#define RADIO_2055_SP_LPF_BW_SELECT_CORE1 0x0b -+#define RADIO_2055_SP_LPF_BW_SELECT_CORE2 0x0c -+#define RADIO_2055_SP_TX_GC1_CORE1 0x0d -+#define RADIO_2055_SP_TX_GC2_CORE1 0x0e -+#define RADIO_2055_SP_TX_GC1_CORE2 0x0f -+#define RADIO_2055_SP_TX_GC2_CORE2 0x10 -+#define RADIO_2055_MASTER_CNTRL1 0x11 -+#define RADIO_2055_MASTER_CNTRL2 0x12 -+#define RADIO_2055_PD_LGEN 0x13 -+#define RADIO_2055_PD_PLL_TS 0x14 -+#define RADIO_2055_PD_CORE1_LGBUF 0x15 -+#define RADIO_2055_PD_CORE1_TX 0x16 -+#define RADIO_2055_PD_CORE1_RXTX 0x17 -+#define RADIO_2055_PD_CORE1_RSSI_MISC 0x18 -+#define RADIO_2055_PD_CORE2_LGBUF 0x19 -+#define RADIO_2055_PD_CORE2_TX 0x1a -+#define RADIO_2055_PD_CORE2_RXTX 0x1b -+#define RADIO_2055_PD_CORE2_RSSI_MISC 0x1c -+#define RADIO_2055_PWRDET_LGEN 0x1d -+#define RADIO_2055_PWRDET_LGBUF_CORE1 0x1e -+#define RADIO_2055_PWRDET_RXTX_CORE1 0x1f -+#define RADIO_2055_PWRDET_LGBUF_CORE2 0x20 -+#define RADIO_2055_PWRDET_RXTX_CORE2 0x21 -+#define RADIO_2055_RRCCAL_CNTRL_SPARE 0x22 -+#define RADIO_2055_RRCCAL_N_OPT_SEL 0x23 -+#define RADIO_2055_CAL_MISC 0x24 -+#define RADIO_2055_CAL_COUNTER_OUT 0x25 -+#define RADIO_2055_CAL_COUNTER_OUT2 0x26 -+#define RADIO_2055_CAL_CVAR_CNTRL 0x27 -+#define RADIO_2055_CAL_RVAR_CNTRL 0x28 -+#define RADIO_2055_CAL_LPO_CNTRL 0x29 -+#define RADIO_2055_CAL_TS 0x2a -+#define RADIO_2055_CAL_RCCAL_READ_TS 0x2b -+#define RADIO_2055_CAL_RCAL_READ_TS 0x2c -+#define RADIO_2055_PAD_DRIVER 0x2d -+#define RADIO_2055_XO_CNTRL1 0x2e -+#define RADIO_2055_XO_CNTRL2 0x2f -+#define RADIO_2055_XO_REGULATOR 0x30 -+#define RADIO_2055_XO_MISC 0x31 -+#define RADIO_2055_PLL_LF_C1 0x32 -+#define RADIO_2055_PLL_CAL_VTH 0x33 -+#define RADIO_2055_PLL_LF_C2 0x34 -+#define RADIO_2055_PLL_REF 0x35 -+#define RADIO_2055_PLL_LF_R1 0x36 -+#define RADIO_2055_PLL_PFD_CP 0x37 -+#define RADIO_2055_PLL_IDAC_CPOPAMP 0x38 -+#define RADIO_2055_PLL_CP_REGULATOR 0x39 -+#define RADIO_2055_PLL_RCAL 0x3a -+#define RADIO_2055_RF_PLL_MOD0 0x3b -+#define RADIO_2055_RF_PLL_MOD1 0x3c -+#define RADIO_2055_RF_MMD_IDAC1 0x3d -+#define RADIO_2055_RF_MMD_IDAC0 0x3e -+#define RADIO_2055_RF_MMD_SPARE 0x3f -+#define RADIO_2055_VCO_CAL1 0x40 -+#define RADIO_2055_VCO_CAL2 0x41 -+#define RADIO_2055_VCO_CAL3 0x42 -+#define RADIO_2055_VCO_CAL4 0x43 -+#define RADIO_2055_VCO_CAL5 0x44 -+#define RADIO_2055_VCO_CAL6 0x45 -+#define RADIO_2055_VCO_CAL7 0x46 -+#define RADIO_2055_VCO_CAL8 0x47 -+#define RADIO_2055_VCO_CAL9 0x48 -+#define RADIO_2055_VCO_CAL10 0x49 -+#define RADIO_2055_VCO_CAL11 0x4a -+#define RADIO_2055_VCO_CAL12 0x4b -+#define RADIO_2055_VCO_CAL13 0x4c -+#define RADIO_2055_VCO_CAL14 0x4d -+#define RADIO_2055_VCO_CAL15 0x4e -+#define RADIO_2055_VCO_CAL16 0x4f -+#define RADIO_2055_VCO_KVCO 0x50 -+#define RADIO_2055_VCO_CAP_TAIL 0x51 -+#define RADIO_2055_VCO_IDAC_VCO 0x52 -+#define RADIO_2055_VCO_REGULATOR 0x53 -+#define RADIO_2055_PLL_RF_VTH 0x54 -+#define RADIO_2055_LGBUF_CEN_BUF 0x55 -+#define RADIO_2055_LGEN_TUNE1 0x56 -+#define RADIO_2055_LGEN_TUNE2 0x57 -+#define RADIO_2055_LGEN_IDAC1 0x58 -+#define RADIO_2055_LGEN_IDAC2 0x59 -+#define RADIO_2055_LGEN_BIAS_CNT 0x5a -+#define RADIO_2055_LGEN_BIAS_IDAC 0x5b -+#define RADIO_2055_LGEN_RCAL 0x5c -+#define RADIO_2055_LGEN_DIV 0x5d -+#define RADIO_2055_LGEN_SPARE2 0x5e -+#define RADIO_2055_CORE1_LGBUF_A_TUNE 0x5f -+#define RADIO_2055_CORE1_LGBUF_G_TUNE 0x60 -+#define RADIO_2055_CORE1_LGBUF_DIV 0x61 -+#define RADIO_2055_CORE1_LGBUF_A_IDAC 0x62 -+#define RADIO_2055_CORE1_LGBUF_G_IDAC 0x63 -+#define RADIO_2055_CORE1_LGBUF_IDACFIL_OVR 0x64 -+#define RADIO_2055_CORE1_LGBUF_SPARE 0x65 -+#define RADIO_2055_CORE1_RXRF_SPC1 0x66 -+#define RADIO_2055_CORE1_RXRF_REG1 0x67 -+#define RADIO_2055_CORE1_RXRF_REG2 0x68 -+#define RADIO_2055_CORE1_RXRF_RCAL 0x69 -+#define RADIO_2055_CORE1_RXBB_BUFI_LPFCMP 0x6a -+#define RADIO_2055_CORE1_RXBB_LPF 0x6b -+#define RADIO_2055_CORE1_RXBB_MIDAC_HIPAS 0x6c -+#define RADIO_2055_CORE1_RXBB_VGA1_IDAC 0x6d -+#define RADIO_2055_CORE1_RXBB_VGA2_IDAC 0x6e -+#define RADIO_2055_CORE1_RXBB_VGA3_IDAC 0x6f -+#define RADIO_2055_CORE1_RXBB_BUFO_CTRL 0x70 -+#define RADIO_2055_CORE1_RXBB_RCCAL_CTRL 0x71 -+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL1 0x72 -+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL2 0x73 -+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL3 0x74 -+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL4 0x75 -+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL5 0x76 -+#define RADIO_2055_CORE1_RXBB_REGULATOR 0x77 -+#define RADIO_2055_CORE1_RXBB_SPARE1 0x78 -+#define RADIO_2055_CORE1_RXTXBB_RCAL 0x79 -+#define RADIO_2055_CORE1_TXRF_SGM_PGA 0x7a -+#define RADIO_2055_CORE1_TXRF_SGM_PAD 0x7b -+#define RADIO_2055_CORE1_TXRF_CNTR_PGA1 0x7c -+#define RADIO_2055_CORE1_TXRF_CNTR_PAD1 0x7d -+#define RADIO_2055_CORE1_TX_RFPGA_IDAC 0x7e -+#define RADIO_2055_CORE1_TX_PGA_PAD_TN 0x7f -+#define RADIO_2055_CORE1_TX_PAD_IDAC1 0x80 -+#define RADIO_2055_CORE1_TX_PAD_IDAC2 0x81 -+#define RADIO_2055_CORE1_TX_MX_BGTRIM 0x82 -+#define RADIO_2055_CORE1_TXRF_RCAL 0x83 -+#define RADIO_2055_CORE1_TXRF_PAD_TSSI1 0x84 -+#define RADIO_2055_CORE1_TXRF_PAD_TSSI2 0x85 -+#define RADIO_2055_CORE1_TX_RF_SPARE 0x86 -+#define RADIO_2055_CORE1_TXRF_IQCAL1 0x87 -+#define RADIO_2055_CORE1_TXRF_IQCAL2 0x88 -+#define RADIO_2055_CORE1_TXBB_RCCAL_CTRL 0x89 -+#define RADIO_2055_CORE1_TXBB_LPF1 0x8a -+#define RADIO_2055_CORE1_TX_VOS_CNCL 0x8b -+#define RADIO_2055_CORE1_TX_LPF_MXGM_IDAC 0x8c -+#define RADIO_2055_CORE1_TX_BB_MXGM 0x8d -+#define RADIO_2055_CORE2_LGBUF_A_TUNE 0x8e -+#define RADIO_2055_CORE2_LGBUF_G_TUNE 0x8f -+#define RADIO_2055_CORE2_LGBUF_DIV 0x90 -+#define RADIO_2055_CORE2_LGBUF_A_IDAC 0x91 -+#define RADIO_2055_CORE2_LGBUF_G_IDAC 0x92 -+#define RADIO_2055_CORE2_LGBUF_IDACFIL_OVR 0x93 -+#define RADIO_2055_CORE2_LGBUF_SPARE 0x94 -+#define RADIO_2055_CORE2_RXRF_SPC1 0x95 -+#define RADIO_2055_CORE2_RXRF_REG1 0x96 -+#define RADIO_2055_CORE2_RXRF_REG2 0x97 -+#define RADIO_2055_CORE2_RXRF_RCAL 0x98 -+#define RADIO_2055_CORE2_RXBB_BUFI_LPFCMP 0x99 -+#define RADIO_2055_CORE2_RXBB_LPF 0x9a -+#define RADIO_2055_CORE2_RXBB_MIDAC_HIPAS 0x9b -+#define RADIO_2055_CORE2_RXBB_VGA1_IDAC 0x9c -+#define RADIO_2055_CORE2_RXBB_VGA2_IDAC 0x9d -+#define RADIO_2055_CORE2_RXBB_VGA3_IDAC 0x9e -+#define RADIO_2055_CORE2_RXBB_BUFO_CTRL 0x9f -+#define RADIO_2055_CORE2_RXBB_RCCAL_CTRL 0xa0 -+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL1 0xa1 -+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL2 0xa2 -+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL3 0xa3 -+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL4 0xa4 -+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL5 0xa5 -+#define RADIO_2055_CORE2_RXBB_REGULATOR 0xa6 -+#define RADIO_2055_CORE2_RXBB_SPARE1 0xa7 -+#define RADIO_2055_CORE2_RXTXBB_RCAL 0xa8 -+#define RADIO_2055_CORE2_TXRF_SGM_PGA 0xa9 -+#define RADIO_2055_CORE2_TXRF_SGM_PAD 0xaa -+#define RADIO_2055_CORE2_TXRF_CNTR_PGA1 0xab -+#define RADIO_2055_CORE2_TXRF_CNTR_PAD1 0xac -+#define RADIO_2055_CORE2_TX_RFPGA_IDAC 0xad -+#define RADIO_2055_CORE2_TX_PGA_PAD_TN 0xae -+#define RADIO_2055_CORE2_TX_PAD_IDAC1 0xaf -+#define RADIO_2055_CORE2_TX_PAD_IDAC2 0xb0 -+#define RADIO_2055_CORE2_TX_MX_BGTRIM 0xb1 -+#define RADIO_2055_CORE2_TXRF_RCAL 0xb2 -+#define RADIO_2055_CORE2_TXRF_PAD_TSSI1 0xb3 -+#define RADIO_2055_CORE2_TXRF_PAD_TSSI2 0xb4 -+#define RADIO_2055_CORE2_TX_RF_SPARE 0xb5 -+#define RADIO_2055_CORE2_TXRF_IQCAL1 0xb6 -+#define RADIO_2055_CORE2_TXRF_IQCAL2 0xb7 -+#define RADIO_2055_CORE2_TXBB_RCCAL_CTRL 0xb8 -+#define RADIO_2055_CORE2_TXBB_LPF1 0xb9 -+#define RADIO_2055_CORE2_TX_VOS_CNCL 0xba -+#define RADIO_2055_CORE2_TX_LPF_MXGM_IDAC 0xbb -+#define RADIO_2055_CORE2_TX_BB_MXGM 0xbc -+#define RADIO_2055_PRG_GC_HPVGA23_21 0xbd -+#define RADIO_2055_PRG_GC_HPVGA23_22 0xbe -+#define RADIO_2055_PRG_GC_HPVGA23_23 0xbf -+#define RADIO_2055_PRG_GC_HPVGA23_24 0xc0 -+#define RADIO_2055_PRG_GC_HPVGA23_25 0xc1 -+#define RADIO_2055_PRG_GC_HPVGA23_26 0xc2 -+#define RADIO_2055_PRG_GC_HPVGA23_27 0xc3 -+#define RADIO_2055_PRG_GC_HPVGA23_28 0xc4 -+#define RADIO_2055_PRG_GC_HPVGA23_29 0xc5 -+#define RADIO_2055_PRG_GC_HPVGA23_30 0xc6 -+#define RADIO_2055_CORE1_LNA_GAINBST 0xcd -+#define RADIO_2055_CORE1_B0_NBRSSI_VCM 0xd2 -+#define RADIO_2055_CORE1_GEN_SPARE2 0xd6 -+#define RADIO_2055_CORE2_LNA_GAINBST 0xd9 -+#define RADIO_2055_CORE2_B0_NBRSSI_VCM 0xde -+#define RADIO_2055_CORE2_GEN_SPARE2 0xe2 -+ -+#define RADIO_2055_GAINBST_GAIN_DB 6 -+#define RADIO_2055_GAINBST_CODE 0x6 -+ -+#define RADIO_2055_JTAGCTRL_MASK 0x04 -+#define RADIO_2055_JTAGSYNC_MASK 0x08 -+#define RADIO_2055_RRCAL_START 0x40 -+#define RADIO_2055_RRCAL_RST_N 0x01 -+#define RADIO_2055_CAL_LPO_ENABLE 0x80 -+#define RADIO_2055_RCAL_DONE 0x80 -+#define RADIO_2055_NBRSSI_VCM_I_MASK 0x03 -+#define RADIO_2055_NBRSSI_VCM_I_SHIFT 0x00 -+#define RADIO_2055_NBRSSI_VCM_Q_MASK 0x03 -+#define RADIO_2055_NBRSSI_VCM_Q_SHIFT 0x00 -+#define RADIO_2055_WBRSSI_VCM_IQ_MASK 0x0c -+#define RADIO_2055_WBRSSI_VCM_IQ_SHIFT 0x02 -+#define RADIO_2055_NBRSSI_PD 0x01 -+#define RADIO_2055_WBRSSI_G1_PD 0x04 -+#define RADIO_2055_WBRSSI_G2_PD 0x02 -+#define RADIO_2055_NBRSSI_SEL 0x01 -+#define RADIO_2055_WBRSSI_G1_SEL 0x04 -+#define RADIO_2055_WBRSSI_G2_SEL 0x02 -+#define RADIO_2055_COUPLE_RX_MASK 0x01 -+#define RADIO_2055_COUPLE_TX_MASK 0x02 -+#define RADIO_2055_GAINBST_DISABLE 0x02 -+#define RADIO_2055_GAINBST_VAL_MASK 0x07 -+#define RADIO_2055_RXMX_GC_MASK 0x0c -+ -+#define RADIO_MIMO_CORESEL_OFF 0x0 -+#define RADIO_MIMO_CORESEL_CORE1 0x1 -+#define RADIO_MIMO_CORESEL_CORE2 0x2 -+#define RADIO_MIMO_CORESEL_CORE3 0x3 -+#define RADIO_MIMO_CORESEL_CORE4 0x4 -+#define RADIO_MIMO_CORESEL_ALLRX 0x5 -+#define RADIO_MIMO_CORESEL_ALLTX 0x6 -+#define RADIO_MIMO_CORESEL_ALLRXTX 0x7 -+ -+#define RADIO_2064_READ_OFF 0x200 -+ -+#define RADIO_2064_REG000 0x0 -+#define RADIO_2064_REG001 0x1 -+#define RADIO_2064_REG002 0x2 -+#define RADIO_2064_REG003 0x3 -+#define RADIO_2064_REG004 0x4 -+#define RADIO_2064_REG005 0x5 -+#define RADIO_2064_REG006 0x6 -+#define RADIO_2064_REG007 0x7 -+#define RADIO_2064_REG008 0x8 -+#define RADIO_2064_REG009 0x9 -+#define RADIO_2064_REG00A 0xa -+#define RADIO_2064_REG00B 0xb -+#define RADIO_2064_REG00C 0xc -+#define RADIO_2064_REG00D 0xd -+#define RADIO_2064_REG00E 0xe -+#define RADIO_2064_REG00F 0xf -+#define RADIO_2064_REG010 0x10 -+#define RADIO_2064_REG011 0x11 -+#define RADIO_2064_REG012 0x12 -+#define RADIO_2064_REG013 0x13 -+#define RADIO_2064_REG014 0x14 -+#define RADIO_2064_REG015 0x15 -+#define RADIO_2064_REG016 0x16 -+#define RADIO_2064_REG017 0x17 -+#define RADIO_2064_REG018 0x18 -+#define RADIO_2064_REG019 0x19 -+#define RADIO_2064_REG01A 0x1a -+#define RADIO_2064_REG01B 0x1b -+#define RADIO_2064_REG01C 0x1c -+#define RADIO_2064_REG01D 0x1d -+#define RADIO_2064_REG01E 0x1e -+#define RADIO_2064_REG01F 0x1f -+#define RADIO_2064_REG020 0x20 -+#define RADIO_2064_REG021 0x21 -+#define RADIO_2064_REG022 0x22 -+#define RADIO_2064_REG023 0x23 -+#define RADIO_2064_REG024 0x24 -+#define RADIO_2064_REG025 0x25 -+#define RADIO_2064_REG026 0x26 -+#define RADIO_2064_REG027 0x27 -+#define RADIO_2064_REG028 0x28 -+#define RADIO_2064_REG029 0x29 -+#define RADIO_2064_REG02A 0x2a -+#define RADIO_2064_REG02B 0x2b -+#define RADIO_2064_REG02C 0x2c -+#define RADIO_2064_REG02D 0x2d -+#define RADIO_2064_REG02E 0x2e -+#define RADIO_2064_REG02F 0x2f -+#define RADIO_2064_REG030 0x30 -+#define RADIO_2064_REG031 0x31 -+#define RADIO_2064_REG032 0x32 -+#define RADIO_2064_REG033 0x33 -+#define RADIO_2064_REG034 0x34 -+#define RADIO_2064_REG035 0x35 -+#define RADIO_2064_REG036 0x36 -+#define RADIO_2064_REG037 0x37 -+#define RADIO_2064_REG038 0x38 -+#define RADIO_2064_REG039 0x39 -+#define RADIO_2064_REG03A 0x3a -+#define RADIO_2064_REG03B 0x3b -+#define RADIO_2064_REG03C 0x3c -+#define RADIO_2064_REG03D 0x3d -+#define RADIO_2064_REG03E 0x3e -+#define RADIO_2064_REG03F 0x3f -+#define RADIO_2064_REG040 0x40 -+#define RADIO_2064_REG041 0x41 -+#define RADIO_2064_REG042 0x42 -+#define RADIO_2064_REG043 0x43 -+#define RADIO_2064_REG044 0x44 -+#define RADIO_2064_REG045 0x45 -+#define RADIO_2064_REG046 0x46 -+#define RADIO_2064_REG047 0x47 -+#define RADIO_2064_REG048 0x48 -+#define RADIO_2064_REG049 0x49 -+#define RADIO_2064_REG04A 0x4a -+#define RADIO_2064_REG04B 0x4b -+#define RADIO_2064_REG04C 0x4c -+#define RADIO_2064_REG04D 0x4d -+#define RADIO_2064_REG04E 0x4e -+#define RADIO_2064_REG04F 0x4f -+#define RADIO_2064_REG050 0x50 -+#define RADIO_2064_REG051 0x51 -+#define RADIO_2064_REG052 0x52 -+#define RADIO_2064_REG053 0x53 -+#define RADIO_2064_REG054 0x54 -+#define RADIO_2064_REG055 0x55 -+#define RADIO_2064_REG056 0x56 -+#define RADIO_2064_REG057 0x57 -+#define RADIO_2064_REG058 0x58 -+#define RADIO_2064_REG059 0x59 -+#define RADIO_2064_REG05A 0x5a -+#define RADIO_2064_REG05B 0x5b -+#define RADIO_2064_REG05C 0x5c -+#define RADIO_2064_REG05D 0x5d -+#define RADIO_2064_REG05E 0x5e -+#define RADIO_2064_REG05F 0x5f -+#define RADIO_2064_REG060 0x60 -+#define RADIO_2064_REG061 0x61 -+#define RADIO_2064_REG062 0x62 -+#define RADIO_2064_REG063 0x63 -+#define RADIO_2064_REG064 0x64 -+#define RADIO_2064_REG065 0x65 -+#define RADIO_2064_REG066 0x66 -+#define RADIO_2064_REG067 0x67 -+#define RADIO_2064_REG068 0x68 -+#define RADIO_2064_REG069 0x69 -+#define RADIO_2064_REG06A 0x6a -+#define RADIO_2064_REG06B 0x6b -+#define RADIO_2064_REG06C 0x6c -+#define RADIO_2064_REG06D 0x6d -+#define RADIO_2064_REG06E 0x6e -+#define RADIO_2064_REG06F 0x6f -+#define RADIO_2064_REG070 0x70 -+#define RADIO_2064_REG071 0x71 -+#define RADIO_2064_REG072 0x72 -+#define RADIO_2064_REG073 0x73 -+#define RADIO_2064_REG074 0x74 -+#define RADIO_2064_REG075 0x75 -+#define RADIO_2064_REG076 0x76 -+#define RADIO_2064_REG077 0x77 -+#define RADIO_2064_REG078 0x78 -+#define RADIO_2064_REG079 0x79 -+#define RADIO_2064_REG07A 0x7a -+#define RADIO_2064_REG07B 0x7b -+#define RADIO_2064_REG07C 0x7c -+#define RADIO_2064_REG07D 0x7d -+#define RADIO_2064_REG07E 0x7e -+#define RADIO_2064_REG07F 0x7f -+#define RADIO_2064_REG080 0x80 -+#define RADIO_2064_REG081 0x81 -+#define RADIO_2064_REG082 0x82 -+#define RADIO_2064_REG083 0x83 -+#define RADIO_2064_REG084 0x84 -+#define RADIO_2064_REG085 0x85 -+#define RADIO_2064_REG086 0x86 -+#define RADIO_2064_REG087 0x87 -+#define RADIO_2064_REG088 0x88 -+#define RADIO_2064_REG089 0x89 -+#define RADIO_2064_REG08A 0x8a -+#define RADIO_2064_REG08B 0x8b -+#define RADIO_2064_REG08C 0x8c -+#define RADIO_2064_REG08D 0x8d -+#define RADIO_2064_REG08E 0x8e -+#define RADIO_2064_REG08F 0x8f -+#define RADIO_2064_REG090 0x90 -+#define RADIO_2064_REG091 0x91 -+#define RADIO_2064_REG092 0x92 -+#define RADIO_2064_REG093 0x93 -+#define RADIO_2064_REG094 0x94 -+#define RADIO_2064_REG095 0x95 -+#define RADIO_2064_REG096 0x96 -+#define RADIO_2064_REG097 0x97 -+#define RADIO_2064_REG098 0x98 -+#define RADIO_2064_REG099 0x99 -+#define RADIO_2064_REG09A 0x9a -+#define RADIO_2064_REG09B 0x9b -+#define RADIO_2064_REG09C 0x9c -+#define RADIO_2064_REG09D 0x9d -+#define RADIO_2064_REG09E 0x9e -+#define RADIO_2064_REG09F 0x9f -+#define RADIO_2064_REG0A0 0xa0 -+#define RADIO_2064_REG0A1 0xa1 -+#define RADIO_2064_REG0A2 0xa2 -+#define RADIO_2064_REG0A3 0xa3 -+#define RADIO_2064_REG0A4 0xa4 -+#define RADIO_2064_REG0A5 0xa5 -+#define RADIO_2064_REG0A6 0xa6 -+#define RADIO_2064_REG0A7 0xa7 -+#define RADIO_2064_REG0A8 0xa8 -+#define RADIO_2064_REG0A9 0xa9 -+#define RADIO_2064_REG0AA 0xaa -+#define RADIO_2064_REG0AB 0xab -+#define RADIO_2064_REG0AC 0xac -+#define RADIO_2064_REG0AD 0xad -+#define RADIO_2064_REG0AE 0xae -+#define RADIO_2064_REG0AF 0xaf -+#define RADIO_2064_REG0B0 0xb0 -+#define RADIO_2064_REG0B1 0xb1 -+#define RADIO_2064_REG0B2 0xb2 -+#define RADIO_2064_REG0B3 0xb3 -+#define RADIO_2064_REG0B4 0xb4 -+#define RADIO_2064_REG0B5 0xb5 -+#define RADIO_2064_REG0B6 0xb6 -+#define RADIO_2064_REG0B7 0xb7 -+#define RADIO_2064_REG0B8 0xb8 -+#define RADIO_2064_REG0B9 0xb9 -+#define RADIO_2064_REG0BA 0xba -+#define RADIO_2064_REG0BB 0xbb -+#define RADIO_2064_REG0BC 0xbc -+#define RADIO_2064_REG0BD 0xbd -+#define RADIO_2064_REG0BE 0xbe -+#define RADIO_2064_REG0BF 0xbf -+#define RADIO_2064_REG0C0 0xc0 -+#define RADIO_2064_REG0C1 0xc1 -+#define RADIO_2064_REG0C2 0xc2 -+#define RADIO_2064_REG0C3 0xc3 -+#define RADIO_2064_REG0C4 0xc4 -+#define RADIO_2064_REG0C5 0xc5 -+#define RADIO_2064_REG0C6 0xc6 -+#define RADIO_2064_REG0C7 0xc7 -+#define RADIO_2064_REG0C8 0xc8 -+#define RADIO_2064_REG0C9 0xc9 -+#define RADIO_2064_REG0CA 0xca -+#define RADIO_2064_REG0CB 0xcb -+#define RADIO_2064_REG0CC 0xcc -+#define RADIO_2064_REG0CD 0xcd -+#define RADIO_2064_REG0CE 0xce -+#define RADIO_2064_REG0CF 0xcf -+#define RADIO_2064_REG0D0 0xd0 -+#define RADIO_2064_REG0D1 0xd1 -+#define RADIO_2064_REG0D2 0xd2 -+#define RADIO_2064_REG0D3 0xd3 -+#define RADIO_2064_REG0D4 0xd4 -+#define RADIO_2064_REG0D5 0xd5 -+#define RADIO_2064_REG0D6 0xd6 -+#define RADIO_2064_REG0D7 0xd7 -+#define RADIO_2064_REG0D8 0xd8 -+#define RADIO_2064_REG0D9 0xd9 -+#define RADIO_2064_REG0DA 0xda -+#define RADIO_2064_REG0DB 0xdb -+#define RADIO_2064_REG0DC 0xdc -+#define RADIO_2064_REG0DD 0xdd -+#define RADIO_2064_REG0DE 0xde -+#define RADIO_2064_REG0DF 0xdf -+#define RADIO_2064_REG0E0 0xe0 -+#define RADIO_2064_REG0E1 0xe1 -+#define RADIO_2064_REG0E2 0xe2 -+#define RADIO_2064_REG0E3 0xe3 -+#define RADIO_2064_REG0E4 0xe4 -+#define RADIO_2064_REG0E5 0xe5 -+#define RADIO_2064_REG0E6 0xe6 -+#define RADIO_2064_REG0E7 0xe7 -+#define RADIO_2064_REG0E8 0xe8 -+#define RADIO_2064_REG0E9 0xe9 -+#define RADIO_2064_REG0EA 0xea -+#define RADIO_2064_REG0EB 0xeb -+#define RADIO_2064_REG0EC 0xec -+#define RADIO_2064_REG0ED 0xed -+#define RADIO_2064_REG0EE 0xee -+#define RADIO_2064_REG0EF 0xef -+#define RADIO_2064_REG0F0 0xf0 -+#define RADIO_2064_REG0F1 0xf1 -+#define RADIO_2064_REG0F2 0xf2 -+#define RADIO_2064_REG0F3 0xf3 -+#define RADIO_2064_REG0F4 0xf4 -+#define RADIO_2064_REG0F5 0xf5 -+#define RADIO_2064_REG0F6 0xf6 -+#define RADIO_2064_REG0F7 0xf7 -+#define RADIO_2064_REG0F8 0xf8 -+#define RADIO_2064_REG0F9 0xf9 -+#define RADIO_2064_REG0FA 0xfa -+#define RADIO_2064_REG0FB 0xfb -+#define RADIO_2064_REG0FC 0xfc -+#define RADIO_2064_REG0FD 0xfd -+#define RADIO_2064_REG0FE 0xfe -+#define RADIO_2064_REG0FF 0xff -+#define RADIO_2064_REG100 0x100 -+#define RADIO_2064_REG101 0x101 -+#define RADIO_2064_REG102 0x102 -+#define RADIO_2064_REG103 0x103 -+#define RADIO_2064_REG104 0x104 -+#define RADIO_2064_REG105 0x105 -+#define RADIO_2064_REG106 0x106 -+#define RADIO_2064_REG107 0x107 -+#define RADIO_2064_REG108 0x108 -+#define RADIO_2064_REG109 0x109 -+#define RADIO_2064_REG10A 0x10a -+#define RADIO_2064_REG10B 0x10b -+#define RADIO_2064_REG10C 0x10c -+#define RADIO_2064_REG10D 0x10d -+#define RADIO_2064_REG10E 0x10e -+#define RADIO_2064_REG10F 0x10f -+#define RADIO_2064_REG110 0x110 -+#define RADIO_2064_REG111 0x111 -+#define RADIO_2064_REG112 0x112 -+#define RADIO_2064_REG113 0x113 -+#define RADIO_2064_REG114 0x114 -+#define RADIO_2064_REG115 0x115 -+#define RADIO_2064_REG116 0x116 -+#define RADIO_2064_REG117 0x117 -+#define RADIO_2064_REG118 0x118 -+#define RADIO_2064_REG119 0x119 -+#define RADIO_2064_REG11A 0x11a -+#define RADIO_2064_REG11B 0x11b -+#define RADIO_2064_REG11C 0x11c -+#define RADIO_2064_REG11D 0x11d -+#define RADIO_2064_REG11E 0x11e -+#define RADIO_2064_REG11F 0x11f -+#define RADIO_2064_REG120 0x120 -+#define RADIO_2064_REG121 0x121 -+#define RADIO_2064_REG122 0x122 -+#define RADIO_2064_REG123 0x123 -+#define RADIO_2064_REG124 0x124 -+#define RADIO_2064_REG125 0x125 -+#define RADIO_2064_REG126 0x126 -+#define RADIO_2064_REG127 0x127 -+#define RADIO_2064_REG128 0x128 -+#define RADIO_2064_REG129 0x129 -+#define RADIO_2064_REG12A 0x12a -+#define RADIO_2064_REG12B 0x12b -+#define RADIO_2064_REG12C 0x12c -+#define RADIO_2064_REG12D 0x12d -+#define RADIO_2064_REG12E 0x12e -+#define RADIO_2064_REG12F 0x12f -+#define RADIO_2064_REG130 0x130 -+ -+#define RADIO_2056_SYN (0x0 << 12) -+#define RADIO_2056_TX0 (0x2 << 12) -+#define RADIO_2056_TX1 (0x3 << 12) -+#define RADIO_2056_RX0 (0x6 << 12) -+#define RADIO_2056_RX1 (0x7 << 12) -+#define RADIO_2056_ALLTX (0xe << 12) -+#define RADIO_2056_ALLRX (0xf << 12) -+ -+#define RADIO_2056_SYN_RESERVED_ADDR0 0x0 -+#define RADIO_2056_SYN_IDCODE 0x1 -+#define RADIO_2056_SYN_RESERVED_ADDR2 0x2 -+#define RADIO_2056_SYN_RESERVED_ADDR3 0x3 -+#define RADIO_2056_SYN_RESERVED_ADDR4 0x4 -+#define RADIO_2056_SYN_RESERVED_ADDR5 0x5 -+#define RADIO_2056_SYN_RESERVED_ADDR6 0x6 -+#define RADIO_2056_SYN_RESERVED_ADDR7 0x7 -+#define RADIO_2056_SYN_COM_CTRL 0x8 -+#define RADIO_2056_SYN_COM_PU 0x9 -+#define RADIO_2056_SYN_COM_OVR 0xa -+#define RADIO_2056_SYN_COM_RESET 0xb -+#define RADIO_2056_SYN_COM_RCAL 0xc -+#define RADIO_2056_SYN_COM_RC_RXLPF 0xd -+#define RADIO_2056_SYN_COM_RC_TXLPF 0xe -+#define RADIO_2056_SYN_COM_RC_RXHPF 0xf -+#define RADIO_2056_SYN_RESERVED_ADDR16 0x10 -+#define RADIO_2056_SYN_RESERVED_ADDR17 0x11 -+#define RADIO_2056_SYN_RESERVED_ADDR18 0x12 -+#define RADIO_2056_SYN_RESERVED_ADDR19 0x13 -+#define RADIO_2056_SYN_RESERVED_ADDR20 0x14 -+#define RADIO_2056_SYN_RESERVED_ADDR21 0x15 -+#define RADIO_2056_SYN_RESERVED_ADDR22 0x16 -+#define RADIO_2056_SYN_RESERVED_ADDR23 0x17 -+#define RADIO_2056_SYN_RESERVED_ADDR24 0x18 -+#define RADIO_2056_SYN_RESERVED_ADDR25 0x19 -+#define RADIO_2056_SYN_RESERVED_ADDR26 0x1a -+#define RADIO_2056_SYN_RESERVED_ADDR27 0x1b -+#define RADIO_2056_SYN_RESERVED_ADDR28 0x1c -+#define RADIO_2056_SYN_RESERVED_ADDR29 0x1d -+#define RADIO_2056_SYN_RESERVED_ADDR30 0x1e -+#define RADIO_2056_SYN_RESERVED_ADDR31 0x1f -+#define RADIO_2056_SYN_GPIO_MASTER1 0x20 -+#define RADIO_2056_SYN_GPIO_MASTER2 0x21 -+#define RADIO_2056_SYN_TOPBIAS_MASTER 0x22 -+#define RADIO_2056_SYN_TOPBIAS_RCAL 0x23 -+#define RADIO_2056_SYN_AFEREG 0x24 -+#define RADIO_2056_SYN_TEMPPROCSENSE 0x25 -+#define RADIO_2056_SYN_TEMPPROCSENSEIDAC 0x26 -+#define RADIO_2056_SYN_TEMPPROCSENSERCAL 0x27 -+#define RADIO_2056_SYN_LPO 0x28 -+#define RADIO_2056_SYN_VDDCAL_MASTER 0x29 -+#define RADIO_2056_SYN_VDDCAL_IDAC 0x2a -+#define RADIO_2056_SYN_VDDCAL_STATUS 0x2b -+#define RADIO_2056_SYN_RCAL_MASTER 0x2c -+#define RADIO_2056_SYN_RCAL_CODE_OUT 0x2d -+#define RADIO_2056_SYN_RCCAL_CTRL0 0x2e -+#define RADIO_2056_SYN_RCCAL_CTRL1 0x2f -+#define RADIO_2056_SYN_RCCAL_CTRL2 0x30 -+#define RADIO_2056_SYN_RCCAL_CTRL3 0x31 -+#define RADIO_2056_SYN_RCCAL_CTRL4 0x32 -+#define RADIO_2056_SYN_RCCAL_CTRL5 0x33 -+#define RADIO_2056_SYN_RCCAL_CTRL6 0x34 -+#define RADIO_2056_SYN_RCCAL_CTRL7 0x35 -+#define RADIO_2056_SYN_RCCAL_CTRL8 0x36 -+#define RADIO_2056_SYN_RCCAL_CTRL9 0x37 -+#define RADIO_2056_SYN_RCCAL_CTRL10 0x38 -+#define RADIO_2056_SYN_RCCAL_CTRL11 0x39 -+#define RADIO_2056_SYN_ZCAL_SPARE1 0x3a -+#define RADIO_2056_SYN_ZCAL_SPARE2 0x3b -+#define RADIO_2056_SYN_PLL_MAST1 0x3c -+#define RADIO_2056_SYN_PLL_MAST2 0x3d -+#define RADIO_2056_SYN_PLL_MAST3 0x3e -+#define RADIO_2056_SYN_PLL_BIAS_RESET 0x3f -+#define RADIO_2056_SYN_PLL_XTAL0 0x40 -+#define RADIO_2056_SYN_PLL_XTAL1 0x41 -+#define RADIO_2056_SYN_PLL_XTAL3 0x42 -+#define RADIO_2056_SYN_PLL_XTAL4 0x43 -+#define RADIO_2056_SYN_PLL_XTAL5 0x44 -+#define RADIO_2056_SYN_PLL_XTAL6 0x45 -+#define RADIO_2056_SYN_PLL_REFDIV 0x46 -+#define RADIO_2056_SYN_PLL_PFD 0x47 -+#define RADIO_2056_SYN_PLL_CP1 0x48 -+#define RADIO_2056_SYN_PLL_CP2 0x49 -+#define RADIO_2056_SYN_PLL_CP3 0x4a -+#define RADIO_2056_SYN_PLL_LOOPFILTER1 0x4b -+#define RADIO_2056_SYN_PLL_LOOPFILTER2 0x4c -+#define RADIO_2056_SYN_PLL_LOOPFILTER3 0x4d -+#define RADIO_2056_SYN_PLL_LOOPFILTER4 0x4e -+#define RADIO_2056_SYN_PLL_LOOPFILTER5 0x4f -+#define RADIO_2056_SYN_PLL_MMD1 0x50 -+#define RADIO_2056_SYN_PLL_MMD2 0x51 -+#define RADIO_2056_SYN_PLL_VCO1 0x52 -+#define RADIO_2056_SYN_PLL_VCO2 0x53 -+#define RADIO_2056_SYN_PLL_MONITOR1 0x54 -+#define RADIO_2056_SYN_PLL_MONITOR2 0x55 -+#define RADIO_2056_SYN_PLL_VCOCAL1 0x56 -+#define RADIO_2056_SYN_PLL_VCOCAL2 0x57 -+#define RADIO_2056_SYN_PLL_VCOCAL4 0x58 -+#define RADIO_2056_SYN_PLL_VCOCAL5 0x59 -+#define RADIO_2056_SYN_PLL_VCOCAL6 0x5a -+#define RADIO_2056_SYN_PLL_VCOCAL7 0x5b -+#define RADIO_2056_SYN_PLL_VCOCAL8 0x5c -+#define RADIO_2056_SYN_PLL_VCOCAL9 0x5d -+#define RADIO_2056_SYN_PLL_VCOCAL10 0x5e -+#define RADIO_2056_SYN_PLL_VCOCAL11 0x5f -+#define RADIO_2056_SYN_PLL_VCOCAL12 0x60 -+#define RADIO_2056_SYN_PLL_VCOCAL13 0x61 -+#define RADIO_2056_SYN_PLL_VREG 0x62 -+#define RADIO_2056_SYN_PLL_STATUS1 0x63 -+#define RADIO_2056_SYN_PLL_STATUS2 0x64 -+#define RADIO_2056_SYN_PLL_STATUS3 0x65 -+#define RADIO_2056_SYN_LOGEN_PU0 0x66 -+#define RADIO_2056_SYN_LOGEN_PU1 0x67 -+#define RADIO_2056_SYN_LOGEN_PU2 0x68 -+#define RADIO_2056_SYN_LOGEN_PU3 0x69 -+#define RADIO_2056_SYN_LOGEN_PU5 0x6a -+#define RADIO_2056_SYN_LOGEN_PU6 0x6b -+#define RADIO_2056_SYN_LOGEN_PU7 0x6c -+#define RADIO_2056_SYN_LOGEN_PU8 0x6d -+#define RADIO_2056_SYN_LOGEN_BIAS_RESET 0x6e -+#define RADIO_2056_SYN_LOGEN_RCCR1 0x6f -+#define RADIO_2056_SYN_LOGEN_VCOBUF1 0x70 -+#define RADIO_2056_SYN_LOGEN_MIXER1 0x71 -+#define RADIO_2056_SYN_LOGEN_MIXER2 0x72 -+#define RADIO_2056_SYN_LOGEN_BUF1 0x73 -+#define RADIO_2056_SYN_LOGENBUF2 0x74 -+#define RADIO_2056_SYN_LOGEN_BUF3 0x75 -+#define RADIO_2056_SYN_LOGEN_BUF4 0x76 -+#define RADIO_2056_SYN_LOGEN_DIV1 0x77 -+#define RADIO_2056_SYN_LOGEN_DIV2 0x78 -+#define RADIO_2056_SYN_LOGEN_DIV3 0x79 -+#define RADIO_2056_SYN_LOGEN_ACL1 0x7a -+#define RADIO_2056_SYN_LOGEN_ACL2 0x7b -+#define RADIO_2056_SYN_LOGEN_ACL3 0x7c -+#define RADIO_2056_SYN_LOGEN_ACL4 0x7d -+#define RADIO_2056_SYN_LOGEN_ACL5 0x7e -+#define RADIO_2056_SYN_LOGEN_ACL6 0x7f -+#define RADIO_2056_SYN_LOGEN_ACLOUT 0x80 -+#define RADIO_2056_SYN_LOGEN_ACLCAL1 0x81 -+#define RADIO_2056_SYN_LOGEN_ACLCAL2 0x82 -+#define RADIO_2056_SYN_LOGEN_ACLCAL3 0x83 -+#define RADIO_2056_SYN_CALEN 0x84 -+#define RADIO_2056_SYN_LOGEN_PEAKDET1 0x85 -+#define RADIO_2056_SYN_LOGEN_CORE_ACL_OVR 0x86 -+#define RADIO_2056_SYN_LOGEN_RX_DIFF_ACL_OVR 0x87 -+#define RADIO_2056_SYN_LOGEN_TX_DIFF_ACL_OVR 0x88 -+#define RADIO_2056_SYN_LOGEN_RX_CMOS_ACL_OVR 0x89 -+#define RADIO_2056_SYN_LOGEN_TX_CMOS_ACL_OVR 0x8a -+#define RADIO_2056_SYN_LOGEN_VCOBUF2 0x8b -+#define RADIO_2056_SYN_LOGEN_MIXER3 0x8c -+#define RADIO_2056_SYN_LOGEN_BUF5 0x8d -+#define RADIO_2056_SYN_LOGEN_BUF6 0x8e -+#define RADIO_2056_SYN_LOGEN_CBUFRX1 0x8f -+#define RADIO_2056_SYN_LOGEN_CBUFRX2 0x90 -+#define RADIO_2056_SYN_LOGEN_CBUFRX3 0x91 -+#define RADIO_2056_SYN_LOGEN_CBUFRX4 0x92 -+#define RADIO_2056_SYN_LOGEN_CBUFTX1 0x93 -+#define RADIO_2056_SYN_LOGEN_CBUFTX2 0x94 -+#define RADIO_2056_SYN_LOGEN_CBUFTX3 0x95 -+#define RADIO_2056_SYN_LOGEN_CBUFTX4 0x96 -+#define RADIO_2056_SYN_LOGEN_CMOSRX1 0x97 -+#define RADIO_2056_SYN_LOGEN_CMOSRX2 0x98 -+#define RADIO_2056_SYN_LOGEN_CMOSRX3 0x99 -+#define RADIO_2056_SYN_LOGEN_CMOSRX4 0x9a -+#define RADIO_2056_SYN_LOGEN_CMOSTX1 0x9b -+#define RADIO_2056_SYN_LOGEN_CMOSTX2 0x9c -+#define RADIO_2056_SYN_LOGEN_CMOSTX3 0x9d -+#define RADIO_2056_SYN_LOGEN_CMOSTX4 0x9e -+#define RADIO_2056_SYN_LOGEN_VCOBUF2_OVRVAL 0x9f -+#define RADIO_2056_SYN_LOGEN_MIXER3_OVRVAL 0xa0 -+#define RADIO_2056_SYN_LOGEN_BUF5_OVRVAL 0xa1 -+#define RADIO_2056_SYN_LOGEN_BUF6_OVRVAL 0xa2 -+#define RADIO_2056_SYN_LOGEN_CBUFRX1_OVRVAL 0xa3 -+#define RADIO_2056_SYN_LOGEN_CBUFRX2_OVRVAL 0xa4 -+#define RADIO_2056_SYN_LOGEN_CBUFRX3_OVRVAL 0xa5 -+#define RADIO_2056_SYN_LOGEN_CBUFRX4_OVRVAL 0xa6 -+#define RADIO_2056_SYN_LOGEN_CBUFTX1_OVRVAL 0xa7 -+#define RADIO_2056_SYN_LOGEN_CBUFTX2_OVRVAL 0xa8 -+#define RADIO_2056_SYN_LOGEN_CBUFTX3_OVRVAL 0xa9 -+#define RADIO_2056_SYN_LOGEN_CBUFTX4_OVRVAL 0xaa -+#define RADIO_2056_SYN_LOGEN_CMOSRX1_OVRVAL 0xab -+#define RADIO_2056_SYN_LOGEN_CMOSRX2_OVRVAL 0xac -+#define RADIO_2056_SYN_LOGEN_CMOSRX3_OVRVAL 0xad -+#define RADIO_2056_SYN_LOGEN_CMOSRX4_OVRVAL 0xae -+#define RADIO_2056_SYN_LOGEN_CMOSTX1_OVRVAL 0xaf -+#define RADIO_2056_SYN_LOGEN_CMOSTX2_OVRVAL 0xb0 -+#define RADIO_2056_SYN_LOGEN_CMOSTX3_OVRVAL 0xb1 -+#define RADIO_2056_SYN_LOGEN_CMOSTX4_OVRVAL 0xb2 -+#define RADIO_2056_SYN_LOGEN_ACL_WAITCNT 0xb3 -+#define RADIO_2056_SYN_LOGEN_CORE_CALVALID 0xb4 -+#define RADIO_2056_SYN_LOGEN_RX_CMOS_CALVALID 0xb5 -+#define RADIO_2056_SYN_LOGEN_TX_CMOS_VALID 0xb6 -+ -+#define RADIO_2056_TX_RESERVED_ADDR0 0x0 -+#define RADIO_2056_TX_IDCODE 0x1 -+#define RADIO_2056_TX_RESERVED_ADDR2 0x2 -+#define RADIO_2056_TX_RESERVED_ADDR3 0x3 -+#define RADIO_2056_TX_RESERVED_ADDR4 0x4 -+#define RADIO_2056_TX_RESERVED_ADDR5 0x5 -+#define RADIO_2056_TX_RESERVED_ADDR6 0x6 -+#define RADIO_2056_TX_RESERVED_ADDR7 0x7 -+#define RADIO_2056_TX_COM_CTRL 0x8 -+#define RADIO_2056_TX_COM_PU 0x9 -+#define RADIO_2056_TX_COM_OVR 0xa -+#define RADIO_2056_TX_COM_RESET 0xb -+#define RADIO_2056_TX_COM_RCAL 0xc -+#define RADIO_2056_TX_COM_RC_RXLPF 0xd -+#define RADIO_2056_TX_COM_RC_TXLPF 0xe -+#define RADIO_2056_TX_COM_RC_RXHPF 0xf -+#define RADIO_2056_TX_RESERVED_ADDR16 0x10 -+#define RADIO_2056_TX_RESERVED_ADDR17 0x11 -+#define RADIO_2056_TX_RESERVED_ADDR18 0x12 -+#define RADIO_2056_TX_RESERVED_ADDR19 0x13 -+#define RADIO_2056_TX_RESERVED_ADDR20 0x14 -+#define RADIO_2056_TX_RESERVED_ADDR21 0x15 -+#define RADIO_2056_TX_RESERVED_ADDR22 0x16 -+#define RADIO_2056_TX_RESERVED_ADDR23 0x17 -+#define RADIO_2056_TX_RESERVED_ADDR24 0x18 -+#define RADIO_2056_TX_RESERVED_ADDR25 0x19 -+#define RADIO_2056_TX_RESERVED_ADDR26 0x1a -+#define RADIO_2056_TX_RESERVED_ADDR27 0x1b -+#define RADIO_2056_TX_RESERVED_ADDR28 0x1c -+#define RADIO_2056_TX_RESERVED_ADDR29 0x1d -+#define RADIO_2056_TX_RESERVED_ADDR30 0x1e -+#define RADIO_2056_TX_RESERVED_ADDR31 0x1f -+#define RADIO_2056_TX_IQCAL_GAIN_BW 0x20 -+#define RADIO_2056_TX_LOFT_FINE_I 0x21 -+#define RADIO_2056_TX_LOFT_FINE_Q 0x22 -+#define RADIO_2056_TX_LOFT_COARSE_I 0x23 -+#define RADIO_2056_TX_LOFT_COARSE_Q 0x24 -+#define RADIO_2056_TX_TX_COM_MASTER1 0x25 -+#define RADIO_2056_TX_TX_COM_MASTER2 0x26 -+#define RADIO_2056_TX_RXIQCAL_TXMUX 0x27 -+#define RADIO_2056_TX_TX_SSI_MASTER 0x28 -+#define RADIO_2056_TX_IQCAL_VCM_HG 0x29 -+#define RADIO_2056_TX_IQCAL_IDAC 0x2a -+#define RADIO_2056_TX_TSSI_VCM 0x2b -+#define RADIO_2056_TX_TX_AMP_DET 0x2c -+#define RADIO_2056_TX_TX_SSI_MUX 0x2d -+#define RADIO_2056_TX_TSSIA 0x2e -+#define RADIO_2056_TX_TSSIG 0x2f -+#define RADIO_2056_TX_TSSI_MISC1 0x30 -+#define RADIO_2056_TX_TSSI_MISC2 0x31 -+#define RADIO_2056_TX_TSSI_MISC3 0x32 -+#define RADIO_2056_TX_PA_SPARE1 0x33 -+#define RADIO_2056_TX_PA_SPARE2 0x34 -+#define RADIO_2056_TX_INTPAA_MASTER 0x35 -+#define RADIO_2056_TX_INTPAA_GAIN 0x36 -+#define RADIO_2056_TX_INTPAA_BOOST_TUNE 0x37 -+#define RADIO_2056_TX_INTPAA_IAUX_STAT 0x38 -+#define RADIO_2056_TX_INTPAA_IAUX_DYN 0x39 -+#define RADIO_2056_TX_INTPAA_IMAIN_STAT 0x3a -+#define RADIO_2056_TX_INTPAA_IMAIN_DYN 0x3b -+#define RADIO_2056_TX_INTPAA_CASCBIAS 0x3c -+#define RADIO_2056_TX_INTPAA_PASLOPE 0x3d -+#define RADIO_2056_TX_INTPAA_PA_MISC 0x3e -+#define RADIO_2056_TX_INTPAG_MASTER 0x3f -+#define RADIO_2056_TX_INTPAG_GAIN 0x40 -+#define RADIO_2056_TX_INTPAG_BOOST_TUNE 0x41 -+#define RADIO_2056_TX_INTPAG_IAUX_STAT 0x42 -+#define RADIO_2056_TX_INTPAG_IAUX_DYN 0x43 -+#define RADIO_2056_TX_INTPAG_IMAIN_STAT 0x44 -+#define RADIO_2056_TX_INTPAG_IMAIN_DYN 0x45 -+#define RADIO_2056_TX_INTPAG_CASCBIAS 0x46 -+#define RADIO_2056_TX_INTPAG_PASLOPE 0x47 -+#define RADIO_2056_TX_INTPAG_PA_MISC 0x48 -+#define RADIO_2056_TX_PADA_MASTER 0x49 -+#define RADIO_2056_TX_PADA_IDAC 0x4a -+#define RADIO_2056_TX_PADA_CASCBIAS 0x4b -+#define RADIO_2056_TX_PADA_GAIN 0x4c -+#define RADIO_2056_TX_PADA_BOOST_TUNE 0x4d -+#define RADIO_2056_TX_PADA_SLOPE 0x4e -+#define RADIO_2056_TX_PADG_MASTER 0x4f -+#define RADIO_2056_TX_PADG_IDAC 0x50 -+#define RADIO_2056_TX_PADG_CASCBIAS 0x51 -+#define RADIO_2056_TX_PADG_GAIN 0x52 -+#define RADIO_2056_TX_PADG_BOOST_TUNE 0x53 -+#define RADIO_2056_TX_PADG_SLOPE 0x54 -+#define RADIO_2056_TX_PGAA_MASTER 0x55 -+#define RADIO_2056_TX_PGAA_IDAC 0x56 -+#define RADIO_2056_TX_PGAA_GAIN 0x57 -+#define RADIO_2056_TX_PGAA_BOOST_TUNE 0x58 -+#define RADIO_2056_TX_PGAA_SLOPE 0x59 -+#define RADIO_2056_TX_PGAA_MISC 0x5a -+#define RADIO_2056_TX_PGAG_MASTER 0x5b -+#define RADIO_2056_TX_PGAG_IDAC 0x5c -+#define RADIO_2056_TX_PGAG_GAIN 0x5d -+#define RADIO_2056_TX_PGAG_BOOST_TUNE 0x5e -+#define RADIO_2056_TX_PGAG_SLOPE 0x5f -+#define RADIO_2056_TX_PGAG_MISC 0x60 -+#define RADIO_2056_TX_MIXA_MASTER 0x61 -+#define RADIO_2056_TX_MIXA_BOOST_TUNE 0x62 -+#define RADIO_2056_TX_MIXG 0x63 -+#define RADIO_2056_TX_MIXG_BOOST_TUNE 0x64 -+#define RADIO_2056_TX_BB_GM_MASTER 0x65 -+#define RADIO_2056_TX_GMBB_GM 0x66 -+#define RADIO_2056_TX_GMBB_IDAC 0x67 -+#define RADIO_2056_TX_TXLPF_MASTER 0x68 -+#define RADIO_2056_TX_TXLPF_RCCAL 0x69 -+#define RADIO_2056_TX_TXLPF_RCCAL_OFF0 0x6a -+#define RADIO_2056_TX_TXLPF_RCCAL_OFF1 0x6b -+#define RADIO_2056_TX_TXLPF_RCCAL_OFF2 0x6c -+#define RADIO_2056_TX_TXLPF_RCCAL_OFF3 0x6d -+#define RADIO_2056_TX_TXLPF_RCCAL_OFF4 0x6e -+#define RADIO_2056_TX_TXLPF_RCCAL_OFF5 0x6f -+#define RADIO_2056_TX_TXLPF_RCCAL_OFF6 0x70 -+#define RADIO_2056_TX_TXLPF_BW 0x71 -+#define RADIO_2056_TX_TXLPF_GAIN 0x72 -+#define RADIO_2056_TX_TXLPF_IDAC 0x73 -+#define RADIO_2056_TX_TXLPF_IDAC_0 0x74 -+#define RADIO_2056_TX_TXLPF_IDAC_1 0x75 -+#define RADIO_2056_TX_TXLPF_IDAC_2 0x76 -+#define RADIO_2056_TX_TXLPF_IDAC_3 0x77 -+#define RADIO_2056_TX_TXLPF_IDAC_4 0x78 -+#define RADIO_2056_TX_TXLPF_IDAC_5 0x79 -+#define RADIO_2056_TX_TXLPF_IDAC_6 0x7a -+#define RADIO_2056_TX_TXLPF_OPAMP_IDAC 0x7b -+#define RADIO_2056_TX_TXLPF_MISC 0x7c -+#define RADIO_2056_TX_TXSPARE1 0x7d -+#define RADIO_2056_TX_TXSPARE2 0x7e -+#define RADIO_2056_TX_TXSPARE3 0x7f -+#define RADIO_2056_TX_TXSPARE4 0x80 -+#define RADIO_2056_TX_TXSPARE5 0x81 -+#define RADIO_2056_TX_TXSPARE6 0x82 -+#define RADIO_2056_TX_TXSPARE7 0x83 -+#define RADIO_2056_TX_TXSPARE8 0x84 -+#define RADIO_2056_TX_TXSPARE9 0x85 -+#define RADIO_2056_TX_TXSPARE10 0x86 -+#define RADIO_2056_TX_TXSPARE11 0x87 -+#define RADIO_2056_TX_TXSPARE12 0x88 -+#define RADIO_2056_TX_TXSPARE13 0x89 -+#define RADIO_2056_TX_TXSPARE14 0x8a -+#define RADIO_2056_TX_TXSPARE15 0x8b -+#define RADIO_2056_TX_TXSPARE16 0x8c -+#define RADIO_2056_TX_STATUS_INTPA_GAIN 0x8d -+#define RADIO_2056_TX_STATUS_PAD_GAIN 0x8e -+#define RADIO_2056_TX_STATUS_PGA_GAIN 0x8f -+#define RADIO_2056_TX_STATUS_GM_TXLPF_GAIN 0x90 -+#define RADIO_2056_TX_STATUS_TXLPF_BW 0x91 -+#define RADIO_2056_TX_STATUS_TXLPF_RC 0x92 -+#define RADIO_2056_TX_GMBB_IDAC0 0x93 -+#define RADIO_2056_TX_GMBB_IDAC1 0x94 -+#define RADIO_2056_TX_GMBB_IDAC2 0x95 -+#define RADIO_2056_TX_GMBB_IDAC3 0x96 -+#define RADIO_2056_TX_GMBB_IDAC4 0x97 -+#define RADIO_2056_TX_GMBB_IDAC5 0x98 -+#define RADIO_2056_TX_GMBB_IDAC6 0x99 -+#define RADIO_2056_TX_GMBB_IDAC7 0x9a -+ -+#define RADIO_2056_RX_RESERVED_ADDR0 0x0 -+#define RADIO_2056_RX_IDCODE 0x1 -+#define RADIO_2056_RX_RESERVED_ADDR2 0x2 -+#define RADIO_2056_RX_RESERVED_ADDR3 0x3 -+#define RADIO_2056_RX_RESERVED_ADDR4 0x4 -+#define RADIO_2056_RX_RESERVED_ADDR5 0x5 -+#define RADIO_2056_RX_RESERVED_ADDR6 0x6 -+#define RADIO_2056_RX_RESERVED_ADDR7 0x7 -+#define RADIO_2056_RX_COM_CTRL 0x8 -+#define RADIO_2056_RX_COM_PU 0x9 -+#define RADIO_2056_RX_COM_OVR 0xa -+#define RADIO_2056_RX_COM_RESET 0xb -+#define RADIO_2056_RX_COM_RCAL 0xc -+#define RADIO_2056_RX_COM_RC_RXLPF 0xd -+#define RADIO_2056_RX_COM_RC_TXLPF 0xe -+#define RADIO_2056_RX_COM_RC_RXHPF 0xf -+#define RADIO_2056_RX_RESERVED_ADDR16 0x10 -+#define RADIO_2056_RX_RESERVED_ADDR17 0x11 -+#define RADIO_2056_RX_RESERVED_ADDR18 0x12 -+#define RADIO_2056_RX_RESERVED_ADDR19 0x13 -+#define RADIO_2056_RX_RESERVED_ADDR20 0x14 -+#define RADIO_2056_RX_RESERVED_ADDR21 0x15 -+#define RADIO_2056_RX_RESERVED_ADDR22 0x16 -+#define RADIO_2056_RX_RESERVED_ADDR23 0x17 -+#define RADIO_2056_RX_RESERVED_ADDR24 0x18 -+#define RADIO_2056_RX_RESERVED_ADDR25 0x19 -+#define RADIO_2056_RX_RESERVED_ADDR26 0x1a -+#define RADIO_2056_RX_RESERVED_ADDR27 0x1b -+#define RADIO_2056_RX_RESERVED_ADDR28 0x1c -+#define RADIO_2056_RX_RESERVED_ADDR29 0x1d -+#define RADIO_2056_RX_RESERVED_ADDR30 0x1e -+#define RADIO_2056_RX_RESERVED_ADDR31 0x1f -+#define RADIO_2056_RX_RXIQCAL_RXMUX 0x20 -+#define RADIO_2056_RX_RSSI_PU 0x21 -+#define RADIO_2056_RX_RSSI_SEL 0x22 -+#define RADIO_2056_RX_RSSI_GAIN 0x23 -+#define RADIO_2056_RX_RSSI_NB_IDAC 0x24 -+#define RADIO_2056_RX_RSSI_WB2I_IDAC_1 0x25 -+#define RADIO_2056_RX_RSSI_WB2I_IDAC_2 0x26 -+#define RADIO_2056_RX_RSSI_WB2Q_IDAC_1 0x27 -+#define RADIO_2056_RX_RSSI_WB2Q_IDAC_2 0x28 -+#define RADIO_2056_RX_RSSI_POLE 0x29 -+#define RADIO_2056_RX_RSSI_WB1_IDAC 0x2a -+#define RADIO_2056_RX_RSSI_MISC 0x2b -+#define RADIO_2056_RX_LNAA_MASTER 0x2c -+#define RADIO_2056_RX_LNAA_TUNE 0x2d -+#define RADIO_2056_RX_LNAA_GAIN 0x2e -+#define RADIO_2056_RX_LNA_A_SLOPE 0x2f -+#define RADIO_2056_RX_BIASPOLE_LNAA1_IDAC 0x30 -+#define RADIO_2056_RX_LNAA2_IDAC 0x31 -+#define RADIO_2056_RX_LNA1A_MISC 0x32 -+#define RADIO_2056_RX_LNAG_MASTER 0x33 -+#define RADIO_2056_RX_LNAG_TUNE 0x34 -+#define RADIO_2056_RX_LNAG_GAIN 0x35 -+#define RADIO_2056_RX_LNA_G_SLOPE 0x36 -+#define RADIO_2056_RX_BIASPOLE_LNAG1_IDAC 0x37 -+#define RADIO_2056_RX_LNAG2_IDAC 0x38 -+#define RADIO_2056_RX_LNA1G_MISC 0x39 -+#define RADIO_2056_RX_MIXA_MASTER 0x3a -+#define RADIO_2056_RX_MIXA_VCM 0x3b -+#define RADIO_2056_RX_MIXA_CTRLPTAT 0x3c -+#define RADIO_2056_RX_MIXA_LOB_BIAS 0x3d -+#define RADIO_2056_RX_MIXA_CORE_IDAC 0x3e -+#define RADIO_2056_RX_MIXA_CMFB_IDAC 0x3f -+#define RADIO_2056_RX_MIXA_BIAS_AUX 0x40 -+#define RADIO_2056_RX_MIXA_BIAS_MAIN 0x41 -+#define RADIO_2056_RX_MIXA_BIAS_MISC 0x42 -+#define RADIO_2056_RX_MIXA_MAST_BIAS 0x43 -+#define RADIO_2056_RX_MIXG_MASTER 0x44 -+#define RADIO_2056_RX_MIXG_VCM 0x45 -+#define RADIO_2056_RX_MIXG_CTRLPTAT 0x46 -+#define RADIO_2056_RX_MIXG_LOB_BIAS 0x47 -+#define RADIO_2056_RX_MIXG_CORE_IDAC 0x48 -+#define RADIO_2056_RX_MIXG_CMFB_IDAC 0x49 -+#define RADIO_2056_RX_MIXG_BIAS_AUX 0x4a -+#define RADIO_2056_RX_MIXG_BIAS_MAIN 0x4b -+#define RADIO_2056_RX_MIXG_BIAS_MISC 0x4c -+#define RADIO_2056_RX_MIXG_MAST_BIAS 0x4d -+#define RADIO_2056_RX_TIA_MASTER 0x4e -+#define RADIO_2056_RX_TIA_IOPAMP 0x4f -+#define RADIO_2056_RX_TIA_QOPAMP 0x50 -+#define RADIO_2056_RX_TIA_IMISC 0x51 -+#define RADIO_2056_RX_TIA_QMISC 0x52 -+#define RADIO_2056_RX_TIA_GAIN 0x53 -+#define RADIO_2056_RX_TIA_SPARE1 0x54 -+#define RADIO_2056_RX_TIA_SPARE2 0x55 -+#define RADIO_2056_RX_BB_LPF_MASTER 0x56 -+#define RADIO_2056_RX_AACI_MASTER 0x57 -+#define RADIO_2056_RX_RXLPF_IDAC 0x58 -+#define RADIO_2056_RX_RXLPF_OPAMPBIAS_LOWQ 0x59 -+#define RADIO_2056_RX_RXLPF_OPAMPBIAS_HIGHQ 0x5a -+#define RADIO_2056_RX_RXLPF_BIAS_DCCANCEL 0x5b -+#define RADIO_2056_RX_RXLPF_OUTVCM 0x5c -+#define RADIO_2056_RX_RXLPF_INVCM_BODY 0x5d -+#define RADIO_2056_RX_RXLPF_CC_OP 0x5e -+#define RADIO_2056_RX_RXLPF_GAIN 0x5f -+#define RADIO_2056_RX_RXLPF_Q_BW 0x60 -+#define RADIO_2056_RX_RXLPF_HP_CORNER_BW 0x61 -+#define RADIO_2056_RX_RXLPF_RCCAL_HPC 0x62 -+#define RADIO_2056_RX_RXHPF_OFF0 0x63 -+#define RADIO_2056_RX_RXHPF_OFF1 0x64 -+#define RADIO_2056_RX_RXHPF_OFF2 0x65 -+#define RADIO_2056_RX_RXHPF_OFF3 0x66 -+#define RADIO_2056_RX_RXHPF_OFF4 0x67 -+#define RADIO_2056_RX_RXHPF_OFF5 0x68 -+#define RADIO_2056_RX_RXHPF_OFF6 0x69 -+#define RADIO_2056_RX_RXHPF_OFF7 0x6a -+#define RADIO_2056_RX_RXLPF_RCCAL_LPC 0x6b -+#define RADIO_2056_RX_RXLPF_OFF_0 0x6c -+#define RADIO_2056_RX_RXLPF_OFF_1 0x6d -+#define RADIO_2056_RX_RXLPF_OFF_2 0x6e -+#define RADIO_2056_RX_RXLPF_OFF_3 0x6f -+#define RADIO_2056_RX_RXLPF_OFF_4 0x70 -+#define RADIO_2056_RX_UNUSED 0x71 -+#define RADIO_2056_RX_VGA_MASTER 0x72 -+#define RADIO_2056_RX_VGA_BIAS 0x73 -+#define RADIO_2056_RX_VGA_BIAS_DCCANCEL 0x74 -+#define RADIO_2056_RX_VGA_GAIN 0x75 -+#define RADIO_2056_RX_VGA_HP_CORNER_BW 0x76 -+#define RADIO_2056_RX_VGABUF_BIAS 0x77 -+#define RADIO_2056_RX_VGABUF_GAIN_BW 0x78 -+#define RADIO_2056_RX_TXFBMIX_A 0x79 -+#define RADIO_2056_RX_TXFBMIX_G 0x7a -+#define RADIO_2056_RX_RXSPARE1 0x7b -+#define RADIO_2056_RX_RXSPARE2 0x7c -+#define RADIO_2056_RX_RXSPARE3 0x7d -+#define RADIO_2056_RX_RXSPARE4 0x7e -+#define RADIO_2056_RX_RXSPARE5 0x7f -+#define RADIO_2056_RX_RXSPARE6 0x80 -+#define RADIO_2056_RX_RXSPARE7 0x81 -+#define RADIO_2056_RX_RXSPARE8 0x82 -+#define RADIO_2056_RX_RXSPARE9 0x83 -+#define RADIO_2056_RX_RXSPARE10 0x84 -+#define RADIO_2056_RX_RXSPARE11 0x85 -+#define RADIO_2056_RX_RXSPARE12 0x86 -+#define RADIO_2056_RX_RXSPARE13 0x87 -+#define RADIO_2056_RX_RXSPARE14 0x88 -+#define RADIO_2056_RX_RXSPARE15 0x89 -+#define RADIO_2056_RX_RXSPARE16 0x8a -+#define RADIO_2056_RX_STATUS_LNAA_GAIN 0x8b -+#define RADIO_2056_RX_STATUS_LNAG_GAIN 0x8c -+#define RADIO_2056_RX_STATUS_MIXTIA_GAIN 0x8d -+#define RADIO_2056_RX_STATUS_RXLPF_GAIN 0x8e -+#define RADIO_2056_RX_STATUS_VGA_BUF_GAIN 0x8f -+#define RADIO_2056_RX_STATUS_RXLPF_Q 0x90 -+#define RADIO_2056_RX_STATUS_RXLPF_BUF_BW 0x91 -+#define RADIO_2056_RX_STATUS_RXLPF_VGA_HPC 0x92 -+#define RADIO_2056_RX_STATUS_RXLPF_RC 0x93 -+#define RADIO_2056_RX_STATUS_HPC_RC 0x94 -+ -+#define RADIO_2056_LNA1_A_PU 0x01 -+#define RADIO_2056_LNA2_A_PU 0x02 -+#define RADIO_2056_LNA1_G_PU 0x01 -+#define RADIO_2056_LNA2_G_PU 0x02 -+#define RADIO_2056_MIXA_PU_I 0x01 -+#define RADIO_2056_MIXA_PU_Q 0x02 -+#define RADIO_2056_MIXA_PU_GM 0x10 -+#define RADIO_2056_MIXG_PU_I 0x01 -+#define RADIO_2056_MIXG_PU_Q 0x02 -+#define RADIO_2056_MIXG_PU_GM 0x10 -+#define RADIO_2056_TIA_PU 0x01 -+#define RADIO_2056_BB_LPF_PU 0x20 -+#define RADIO_2056_W1_PU 0x02 -+#define RADIO_2056_W2_PU 0x04 -+#define RADIO_2056_NB_PU 0x08 -+#define RADIO_2056_RSSI_W1_SEL 0x02 -+#define RADIO_2056_RSSI_W2_SEL 0x04 -+#define RADIO_2056_RSSI_NB_SEL 0x08 -+#define RADIO_2056_VCM_MASK 0x1c -+#define RADIO_2056_RSSI_VCM_SHIFT 0x02 -+ -+#define RADIO_2057_DACBUF_VINCM_CORE0 0x0 -+#define RADIO_2057_IDCODE 0x1 -+#define RADIO_2057_RCCAL_MASTER 0x2 -+#define RADIO_2057_RCCAL_CAP_SIZE 0x3 -+#define RADIO_2057_RCAL_CONFIG 0x4 -+#define RADIO_2057_GPAIO_CONFIG 0x5 -+#define RADIO_2057_GPAIO_SEL1 0x6 -+#define RADIO_2057_GPAIO_SEL0 0x7 -+#define RADIO_2057_CLPO_CONFIG 0x8 -+#define RADIO_2057_BANDGAP_CONFIG 0x9 -+#define RADIO_2057_BANDGAP_RCAL_TRIM 0xa -+#define RADIO_2057_AFEREG_CONFIG 0xb -+#define RADIO_2057_TEMPSENSE_CONFIG 0xc -+#define RADIO_2057_XTAL_CONFIG1 0xd -+#define RADIO_2057_XTAL_ICORE_SIZE 0xe -+#define RADIO_2057_XTAL_BUF_SIZE 0xf -+#define RADIO_2057_XTAL_PULLCAP_SIZE 0x10 -+#define RADIO_2057_RFPLL_MASTER 0x11 -+#define RADIO_2057_VCOMONITOR_VTH_L 0x12 -+#define RADIO_2057_VCOMONITOR_VTH_H 0x13 -+#define RADIO_2057_VCOCAL_BIASRESET_RFPLLREG_VOUT 0x14 -+#define RADIO_2057_VCO_VARCSIZE_IDAC 0x15 -+#define RADIO_2057_VCOCAL_COUNTVAL0 0x16 -+#define RADIO_2057_VCOCAL_COUNTVAL1 0x17 -+#define RADIO_2057_VCOCAL_INTCLK_COUNT 0x18 -+#define RADIO_2057_VCOCAL_MASTER 0x19 -+#define RADIO_2057_VCOCAL_NUMCAPCHANGE 0x1a -+#define RADIO_2057_VCOCAL_WINSIZE 0x1b -+#define RADIO_2057_VCOCAL_DELAY_AFTER_REFRESH 0x1c -+#define RADIO_2057_VCOCAL_DELAY_AFTER_CLOSELOOP 0x1d -+#define RADIO_2057_VCOCAL_DELAY_AFTER_OPENLOOP 0x1e -+#define RADIO_2057_VCOCAL_DELAY_BEFORE_OPENLOOP 0x1f -+#define RADIO_2057_VCO_FORCECAPEN_FORCECAP1 0x20 -+#define RADIO_2057_VCO_FORCECAP0 0x21 -+#define RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE 0x22 -+#define RADIO_2057_RFPLL_PFD_RESET_PW 0x23 -+#define RADIO_2057_RFPLL_LOOPFILTER_R2 0x24 -+#define RADIO_2057_RFPLL_LOOPFILTER_R1 0x25 -+#define RADIO_2057_RFPLL_LOOPFILTER_C3 0x26 -+#define RADIO_2057_RFPLL_LOOPFILTER_C2 0x27 -+#define RADIO_2057_RFPLL_LOOPFILTER_C1 0x28 -+#define RADIO_2057_CP_KPD_IDAC 0x29 -+#define RADIO_2057_RFPLL_IDACS 0x2a -+#define RADIO_2057_RFPLL_MISC_EN 0x2b -+#define RADIO_2057_RFPLL_MMD0 0x2c -+#define RADIO_2057_RFPLL_MMD1 0x2d -+#define RADIO_2057_RFPLL_MISC_CAL_RESETN 0x2e -+#define RADIO_2057_JTAGXTAL_SIZE_CPBIAS_FILTRES 0x2f -+#define RADIO_2057_VCO_ALCREF_BBPLLXTAL_SIZE 0x30 -+#define RADIO_2057_VCOCAL_READCAP0 0x31 -+#define RADIO_2057_VCOCAL_READCAP1 0x32 -+#define RADIO_2057_VCOCAL_STATUS 0x33 -+#define RADIO_2057_LOGEN_PUS 0x34 -+#define RADIO_2057_LOGEN_PTAT_RESETS 0x35 -+#define RADIO_2057_VCOBUF_IDACS 0x36 -+#define RADIO_2057_VCOBUF_TUNE 0x37 -+#define RADIO_2057_CMOSBUF_TX2GQ_IDACS 0x38 -+#define RADIO_2057_CMOSBUF_TX2GI_IDACS 0x39 -+#define RADIO_2057_CMOSBUF_TX5GQ_IDACS 0x3a -+#define RADIO_2057_CMOSBUF_TX5GI_IDACS 0x3b -+#define RADIO_2057_CMOSBUF_RX2GQ_IDACS 0x3c -+#define RADIO_2057_CMOSBUF_RX2GI_IDACS 0x3d -+#define RADIO_2057_CMOSBUF_RX5GQ_IDACS 0x3e -+#define RADIO_2057_CMOSBUF_RX5GI_IDACS 0x3f -+#define RADIO_2057_LOGEN_MX2G_IDACS 0x40 -+#define RADIO_2057_LOGEN_MX2G_TUNE 0x41 -+#define RADIO_2057_LOGEN_MX5G_IDACS 0x42 -+#define RADIO_2057_LOGEN_MX5G_TUNE 0x43 -+#define RADIO_2057_LOGEN_MX5G_RCCR 0x44 -+#define RADIO_2057_LOGEN_INDBUF2G_IDAC 0x45 -+#define RADIO_2057_LOGEN_INDBUF2G_IBOOST 0x46 -+#define RADIO_2057_LOGEN_INDBUF2G_TUNE 0x47 -+#define RADIO_2057_LOGEN_INDBUF5G_IDAC 0x48 -+#define RADIO_2057_LOGEN_INDBUF5G_IBOOST 0x49 -+#define RADIO_2057_LOGEN_INDBUF5G_TUNE 0x4a -+#define RADIO_2057_CMOSBUF_TX_RCCR 0x4b -+#define RADIO_2057_CMOSBUF_RX_RCCR 0x4c -+#define RADIO_2057_LOGEN_SEL_PKDET 0x4d -+#define RADIO_2057_CMOSBUF_SHAREIQ_PTAT 0x4e -+#define RADIO_2057_RXTXBIAS_CONFIG_CORE0 0x4f -+#define RADIO_2057_TXGM_TXRF_PUS_CORE0 0x50 -+#define RADIO_2057_TXGM_IDAC_BLEED_CORE0 0x51 -+#define RADIO_2057_TXGM_GAIN_CORE0 0x56 -+#define RADIO_2057_TXGM2G_PKDET_PUS_CORE0 0x57 -+#define RADIO_2057_PAD2G_PTATS_CORE0 0x58 -+#define RADIO_2057_PAD2G_IDACS_CORE0 0x59 -+#define RADIO_2057_PAD2G_BOOST_PU_CORE0 0x5a -+#define RADIO_2057_PAD2G_CASCV_GAIN_CORE0 0x5b -+#define RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0 0x5c -+#define RADIO_2057_TXMIX2G_LODC_CORE0 0x5d -+#define RADIO_2057_PAD2G_TUNE_PUS_CORE0 0x5e -+#define RADIO_2057_IPA2G_GAIN_CORE0 0x5f -+#define RADIO_2057_TSSI2G_SPARE1_CORE0 0x60 -+#define RADIO_2057_TSSI2G_SPARE2_CORE0 0x61 -+#define RADIO_2057_IPA2G_TUNEV_CASCV_PTAT_CORE0 0x62 -+#define RADIO_2057_IPA2G_IMAIN_CORE0 0x63 -+#define RADIO_2057_IPA2G_CASCONV_CORE0 0x64 -+#define RADIO_2057_IPA2G_CASCOFFV_CORE0 0x65 -+#define RADIO_2057_IPA2G_BIAS_FILTER_CORE0 0x66 -+#define RADIO_2057_TX5G_PKDET_CORE0 0x69 -+#define RADIO_2057_PGA_PTAT_TXGM5G_PU_CORE0 0x6a -+#define RADIO_2057_PAD5G_PTATS1_CORE0 0x6b -+#define RADIO_2057_PAD5G_CLASS_PTATS2_CORE0 0x6c -+#define RADIO_2057_PGA_BOOSTPTAT_IMAIN_CORE0 0x6d -+#define RADIO_2057_PAD5G_CASCV_IMAIN_CORE0 0x6e -+#define RADIO_2057_TXMIX5G_IBOOST_PAD_IAUX_CORE0 0x6f -+#define RADIO_2057_PGA_BOOST_TUNE_CORE0 0x70 -+#define RADIO_2057_PGA_GAIN_CORE0 0x71 -+#define RADIO_2057_PAD5G_CASCOFFV_GAIN_PUS_CORE0 0x72 -+#define RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0 0x73 -+#define RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0 0x74 -+#define RADIO_2057_IPA5G_IAUX_CORE0 0x75 -+#define RADIO_2057_IPA5G_GAIN_CORE0 0x76 -+#define RADIO_2057_TSSI5G_SPARE1_CORE0 0x77 -+#define RADIO_2057_TSSI5G_SPARE2_CORE0 0x78 -+#define RADIO_2057_IPA5G_CASCOFFV_PU_CORE0 0x79 -+#define RADIO_2057_IPA5G_PTAT_CORE0 0x7a -+#define RADIO_2057_IPA5G_IMAIN_CORE0 0x7b -+#define RADIO_2057_IPA5G_CASCONV_CORE0 0x7c -+#define RADIO_2057_IPA5G_BIAS_FILTER_CORE0 0x7d -+#define RADIO_2057_PAD_BIAS_FILTER_BWS_CORE0 0x80 -+#define RADIO_2057_TR2G_CONFIG1_CORE0_NU 0x81 -+#define RADIO_2057_TR2G_CONFIG2_CORE0_NU 0x82 -+#define RADIO_2057_LNA5G_RFEN_CORE0 0x83 -+#define RADIO_2057_TR5G_CONFIG2_CORE0_NU 0x84 -+#define RADIO_2057_RXRFBIAS_IBOOST_PU_CORE0 0x85 -+#define RADIO_2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE0 0x86 -+#define RADIO_2057_RXGM_CMFBITAIL_AUXPTAT_CORE0 0x87 -+#define RADIO_2057_RXMIX_ICORE_RXGM_IAUX_CORE0 0x88 -+#define RADIO_2057_RXMIX_CMFBITAIL_PU_CORE0 0x89 -+#define RADIO_2057_LNA2_IMAIN_PTAT_PU_CORE0 0x8a -+#define RADIO_2057_LNA2_IAUX_PTAT_CORE0 0x8b -+#define RADIO_2057_LNA1_IMAIN_PTAT_PU_CORE0 0x8c -+#define RADIO_2057_LNA15G_INPUT_MATCH_TUNE_CORE0 0x8d -+#define RADIO_2057_RXRFBIAS_BANDSEL_CORE0 0x8e -+#define RADIO_2057_TIA_CONFIG_CORE0 0x8f -+#define RADIO_2057_TIA_IQGAIN_CORE0 0x90 -+#define RADIO_2057_TIA_IBIAS2_CORE0 0x91 -+#define RADIO_2057_TIA_IBIAS1_CORE0 0x92 -+#define RADIO_2057_TIA_SPARE_Q_CORE0 0x93 -+#define RADIO_2057_TIA_SPARE_I_CORE0 0x94 -+#define RADIO_2057_RXMIX2G_PUS_CORE0 0x95 -+#define RADIO_2057_RXMIX2G_VCMREFS_CORE0 0x96 -+#define RADIO_2057_RXMIX2G_LODC_QI_CORE0 0x97 -+#define RADIO_2057_W12G_BW_LNA2G_PUS_CORE0 0x98 -+#define RADIO_2057_LNA2G_GAIN_CORE0 0x99 -+#define RADIO_2057_LNA2G_TUNE_CORE0 0x9a -+#define RADIO_2057_RXMIX5G_PUS_CORE0 0x9b -+#define RADIO_2057_RXMIX5G_VCMREFS_CORE0 0x9c -+#define RADIO_2057_RXMIX5G_LODC_QI_CORE0 0x9d -+#define RADIO_2057_W15G_BW_LNA5G_PUS_CORE0 0x9e -+#define RADIO_2057_LNA5G_GAIN_CORE0 0x9f -+#define RADIO_2057_LNA5G_TUNE_CORE0 0xa0 -+#define RADIO_2057_LPFSEL_TXRX_RXBB_PUS_CORE0 0xa1 -+#define RADIO_2057_RXBB_BIAS_MASTER_CORE0 0xa2 -+#define RADIO_2057_RXBB_VGABUF_IDACS_CORE0 0xa3 -+#define RADIO_2057_LPF_VCMREF_TXBUF_VCMREF_CORE0 0xa4 -+#define RADIO_2057_TXBUF_VINCM_CORE0 0xa5 -+#define RADIO_2057_TXBUF_IDACS_CORE0 0xa6 -+#define RADIO_2057_LPF_RESP_RXBUF_BW_CORE0 0xa7 -+#define RADIO_2057_RXBB_CC_CORE0 0xa8 -+#define RADIO_2057_RXBB_SPARE3_CORE0 0xa9 -+#define RADIO_2057_RXBB_RCCAL_HPC_CORE0 0xaa -+#define RADIO_2057_LPF_IDACS_CORE0 0xab -+#define RADIO_2057_LPFBYP_DCLOOP_BYP_IDAC_CORE0 0xac -+#define RADIO_2057_TXBUF_GAIN_CORE0 0xad -+#define RADIO_2057_AFELOOPBACK_AACI_RESP_CORE0 0xae -+#define RADIO_2057_RXBUF_DEGEN_CORE0 0xaf -+#define RADIO_2057_RXBB_SPARE2_CORE0 0xb0 -+#define RADIO_2057_RXBB_SPARE1_CORE0 0xb1 -+#define RADIO_2057_RSSI_MASTER_CORE0 0xb2 -+#define RADIO_2057_W2_MASTER_CORE0 0xb3 -+#define RADIO_2057_NB_MASTER_CORE0 0xb4 -+#define RADIO_2057_W2_IDACS0_Q_CORE0 0xb5 -+#define RADIO_2057_W2_IDACS1_Q_CORE0 0xb6 -+#define RADIO_2057_W2_IDACS0_I_CORE0 0xb7 -+#define RADIO_2057_W2_IDACS1_I_CORE0 0xb8 -+#define RADIO_2057_RSSI_GPAIOSEL_W1_IDACS_CORE0 0xb9 -+#define RADIO_2057_NB_IDACS_Q_CORE0 0xba -+#define RADIO_2057_NB_IDACS_I_CORE0 0xbb -+#define RADIO_2057_BACKUP4_CORE0 0xc1 -+#define RADIO_2057_BACKUP3_CORE0 0xc2 -+#define RADIO_2057_BACKUP2_CORE0 0xc3 -+#define RADIO_2057_BACKUP1_CORE0 0xc4 -+#define RADIO_2057_SPARE16_CORE0 0xc5 -+#define RADIO_2057_SPARE15_CORE0 0xc6 -+#define RADIO_2057_SPARE14_CORE0 0xc7 -+#define RADIO_2057_SPARE13_CORE0 0xc8 -+#define RADIO_2057_SPARE12_CORE0 0xc9 -+#define RADIO_2057_SPARE11_CORE0 0xca -+#define RADIO_2057_TX2G_BIAS_RESETS_CORE0 0xcb -+#define RADIO_2057_TX5G_BIAS_RESETS_CORE0 0xcc -+#define RADIO_2057_IQTEST_SEL_PU 0xcd -+#define RADIO_2057_XTAL_CONFIG2 0xce -+#define RADIO_2057_BUFS_MISC_LPFBW_CORE0 0xcf -+#define RADIO_2057_TXLPF_RCCAL_CORE0 0xd0 -+#define RADIO_2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0xd1 -+#define RADIO_2057_LPF_GAIN_CORE0 0xd2 -+#define RADIO_2057_DACBUF_IDACS_BW_CORE0 0xd3 -+#define RADIO_2057_RXTXBIAS_CONFIG_CORE1 0xd4 -+#define RADIO_2057_TXGM_TXRF_PUS_CORE1 0xd5 -+#define RADIO_2057_TXGM_IDAC_BLEED_CORE1 0xd6 -+#define RADIO_2057_TXGM_GAIN_CORE1 0xdb -+#define RADIO_2057_TXGM2G_PKDET_PUS_CORE1 0xdc -+#define RADIO_2057_PAD2G_PTATS_CORE1 0xdd -+#define RADIO_2057_PAD2G_IDACS_CORE1 0xde -+#define RADIO_2057_PAD2G_BOOST_PU_CORE1 0xdf -+#define RADIO_2057_PAD2G_CASCV_GAIN_CORE1 0xe0 -+#define RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1 0xe1 -+#define RADIO_2057_TXMIX2G_LODC_CORE1 0xe2 -+#define RADIO_2057_PAD2G_TUNE_PUS_CORE1 0xe3 -+#define RADIO_2057_IPA2G_GAIN_CORE1 0xe4 -+#define RADIO_2057_TSSI2G_SPARE1_CORE1 0xe5 -+#define RADIO_2057_TSSI2G_SPARE2_CORE1 0xe6 -+#define RADIO_2057_IPA2G_TUNEV_CASCV_PTAT_CORE1 0xe7 -+#define RADIO_2057_IPA2G_IMAIN_CORE1 0xe8 -+#define RADIO_2057_IPA2G_CASCONV_CORE1 0xe9 -+#define RADIO_2057_IPA2G_CASCOFFV_CORE1 0xea -+#define RADIO_2057_IPA2G_BIAS_FILTER_CORE1 0xeb -+#define RADIO_2057_TX5G_PKDET_CORE1 0xee -+#define RADIO_2057_PGA_PTAT_TXGM5G_PU_CORE1 0xef -+#define RADIO_2057_PAD5G_PTATS1_CORE1 0xf0 -+#define RADIO_2057_PAD5G_CLASS_PTATS2_CORE1 0xf1 -+#define RADIO_2057_PGA_BOOSTPTAT_IMAIN_CORE1 0xf2 -+#define RADIO_2057_PAD5G_CASCV_IMAIN_CORE1 0xf3 -+#define RADIO_2057_TXMIX5G_IBOOST_PAD_IAUX_CORE1 0xf4 -+#define RADIO_2057_PGA_BOOST_TUNE_CORE1 0xf5 -+#define RADIO_2057_PGA_GAIN_CORE1 0xf6 -+#define RADIO_2057_PAD5G_CASCOFFV_GAIN_PUS_CORE1 0xf7 -+#define RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1 0xf8 -+#define RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1 0xf9 -+#define RADIO_2057_IPA5G_IAUX_CORE1 0xfa -+#define RADIO_2057_IPA5G_GAIN_CORE1 0xfb -+#define RADIO_2057_TSSI5G_SPARE1_CORE1 0xfc -+#define RADIO_2057_TSSI5G_SPARE2_CORE1 0xfd -+#define RADIO_2057_IPA5G_CASCOFFV_PU_CORE1 0xfe -+#define RADIO_2057_IPA5G_PTAT_CORE1 0xff -+#define RADIO_2057_IPA5G_IMAIN_CORE1 0x100 -+#define RADIO_2057_IPA5G_CASCONV_CORE1 0x101 -+#define RADIO_2057_IPA5G_BIAS_FILTER_CORE1 0x102 -+#define RADIO_2057_PAD_BIAS_FILTER_BWS_CORE1 0x105 -+#define RADIO_2057_TR2G_CONFIG1_CORE1_NU 0x106 -+#define RADIO_2057_TR2G_CONFIG2_CORE1_NU 0x107 -+#define RADIO_2057_LNA5G_RFEN_CORE1 0x108 -+#define RADIO_2057_TR5G_CONFIG2_CORE1_NU 0x109 -+#define RADIO_2057_RXRFBIAS_IBOOST_PU_CORE1 0x10a -+#define RADIO_2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE1 0x10b -+#define RADIO_2057_RXGM_CMFBITAIL_AUXPTAT_CORE1 0x10c -+#define RADIO_2057_RXMIX_ICORE_RXGM_IAUX_CORE1 0x10d -+#define RADIO_2057_RXMIX_CMFBITAIL_PU_CORE1 0x10e -+#define RADIO_2057_LNA2_IMAIN_PTAT_PU_CORE1 0x10f -+#define RADIO_2057_LNA2_IAUX_PTAT_CORE1 0x110 -+#define RADIO_2057_LNA1_IMAIN_PTAT_PU_CORE1 0x111 -+#define RADIO_2057_LNA15G_INPUT_MATCH_TUNE_CORE1 0x112 -+#define RADIO_2057_RXRFBIAS_BANDSEL_CORE1 0x113 -+#define RADIO_2057_TIA_CONFIG_CORE1 0x114 -+#define RADIO_2057_TIA_IQGAIN_CORE1 0x115 -+#define RADIO_2057_TIA_IBIAS2_CORE1 0x116 -+#define RADIO_2057_TIA_IBIAS1_CORE1 0x117 -+#define RADIO_2057_TIA_SPARE_Q_CORE1 0x118 -+#define RADIO_2057_TIA_SPARE_I_CORE1 0x119 -+#define RADIO_2057_RXMIX2G_PUS_CORE1 0x11a -+#define RADIO_2057_RXMIX2G_VCMREFS_CORE1 0x11b -+#define RADIO_2057_RXMIX2G_LODC_QI_CORE1 0x11c -+#define RADIO_2057_W12G_BW_LNA2G_PUS_CORE1 0x11d -+#define RADIO_2057_LNA2G_GAIN_CORE1 0x11e -+#define RADIO_2057_LNA2G_TUNE_CORE1 0x11f -+#define RADIO_2057_RXMIX5G_PUS_CORE1 0x120 -+#define RADIO_2057_RXMIX5G_VCMREFS_CORE1 0x121 -+#define RADIO_2057_RXMIX5G_LODC_QI_CORE1 0x122 -+#define RADIO_2057_W15G_BW_LNA5G_PUS_CORE1 0x123 -+#define RADIO_2057_LNA5G_GAIN_CORE1 0x124 -+#define RADIO_2057_LNA5G_TUNE_CORE1 0x125 -+#define RADIO_2057_LPFSEL_TXRX_RXBB_PUS_CORE1 0x126 -+#define RADIO_2057_RXBB_BIAS_MASTER_CORE1 0x127 -+#define RADIO_2057_RXBB_VGABUF_IDACS_CORE1 0x128 -+#define RADIO_2057_LPF_VCMREF_TXBUF_VCMREF_CORE1 0x129 -+#define RADIO_2057_TXBUF_VINCM_CORE1 0x12a -+#define RADIO_2057_TXBUF_IDACS_CORE1 0x12b -+#define RADIO_2057_LPF_RESP_RXBUF_BW_CORE1 0x12c -+#define RADIO_2057_RXBB_CC_CORE1 0x12d -+#define RADIO_2057_RXBB_SPARE3_CORE1 0x12e -+#define RADIO_2057_RXBB_RCCAL_HPC_CORE1 0x12f -+#define RADIO_2057_LPF_IDACS_CORE1 0x130 -+#define RADIO_2057_LPFBYP_DCLOOP_BYP_IDAC_CORE1 0x131 -+#define RADIO_2057_TXBUF_GAIN_CORE1 0x132 -+#define RADIO_2057_AFELOOPBACK_AACI_RESP_CORE1 0x133 -+#define RADIO_2057_RXBUF_DEGEN_CORE1 0x134 -+#define RADIO_2057_RXBB_SPARE2_CORE1 0x135 -+#define RADIO_2057_RXBB_SPARE1_CORE1 0x136 -+#define RADIO_2057_RSSI_MASTER_CORE1 0x137 -+#define RADIO_2057_W2_MASTER_CORE1 0x138 -+#define RADIO_2057_NB_MASTER_CORE1 0x139 -+#define RADIO_2057_W2_IDACS0_Q_CORE1 0x13a -+#define RADIO_2057_W2_IDACS1_Q_CORE1 0x13b -+#define RADIO_2057_W2_IDACS0_I_CORE1 0x13c -+#define RADIO_2057_W2_IDACS1_I_CORE1 0x13d -+#define RADIO_2057_RSSI_GPAIOSEL_W1_IDACS_CORE1 0x13e -+#define RADIO_2057_NB_IDACS_Q_CORE1 0x13f -+#define RADIO_2057_NB_IDACS_I_CORE1 0x140 -+#define RADIO_2057_BACKUP4_CORE1 0x146 -+#define RADIO_2057_BACKUP3_CORE1 0x147 -+#define RADIO_2057_BACKUP2_CORE1 0x148 -+#define RADIO_2057_BACKUP1_CORE1 0x149 -+#define RADIO_2057_SPARE16_CORE1 0x14a -+#define RADIO_2057_SPARE15_CORE1 0x14b -+#define RADIO_2057_SPARE14_CORE1 0x14c -+#define RADIO_2057_SPARE13_CORE1 0x14d -+#define RADIO_2057_SPARE12_CORE1 0x14e -+#define RADIO_2057_SPARE11_CORE1 0x14f -+#define RADIO_2057_TX2G_BIAS_RESETS_CORE1 0x150 -+#define RADIO_2057_TX5G_BIAS_RESETS_CORE1 0x151 -+#define RADIO_2057_SPARE8_CORE1 0x152 -+#define RADIO_2057_SPARE7_CORE1 0x153 -+#define RADIO_2057_BUFS_MISC_LPFBW_CORE1 0x154 -+#define RADIO_2057_TXLPF_RCCAL_CORE1 0x155 -+#define RADIO_2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156 -+#define RADIO_2057_LPF_GAIN_CORE1 0x157 -+#define RADIO_2057_DACBUF_IDACS_BW_CORE1 0x158 -+#define RADIO_2057_DACBUF_VINCM_CORE1 0x159 -+#define RADIO_2057_RCCAL_START_R1_Q1_P1 0x15a -+#define RADIO_2057_RCCAL_X1 0x15b -+#define RADIO_2057_RCCAL_TRC0 0x15c -+#define RADIO_2057_RCCAL_TRC1 0x15d -+#define RADIO_2057_RCCAL_DONE_OSCCAP 0x15e -+#define RADIO_2057_RCCAL_N0_0 0x15f -+#define RADIO_2057_RCCAL_N0_1 0x160 -+#define RADIO_2057_RCCAL_N1_0 0x161 -+#define RADIO_2057_RCCAL_N1_1 0x162 -+#define RADIO_2057_RCAL_STATUS 0x163 -+#define RADIO_2057_XTALPUOVR_PINCTRL 0x164 -+#define RADIO_2057_OVR_REG0 0x165 -+#define RADIO_2057_OVR_REG1 0x166 -+#define RADIO_2057_OVR_REG2 0x167 -+#define RADIO_2057_OVR_REG3 0x168 -+#define RADIO_2057_OVR_REG4 0x169 -+#define RADIO_2057_RCCAL_SCAP_VAL 0x16a -+#define RADIO_2057_RCCAL_BCAP_VAL 0x16b -+#define RADIO_2057_RCCAL_HPC_VAL 0x16c -+#define RADIO_2057_RCCAL_OVERRIDES 0x16d -+#define RADIO_2057_TX0_IQCAL_GAIN_BW 0x170 -+#define RADIO_2057_TX0_LOFT_FINE_I 0x171 -+#define RADIO_2057_TX0_LOFT_FINE_Q 0x172 -+#define RADIO_2057_TX0_LOFT_COARSE_I 0x173 -+#define RADIO_2057_TX0_LOFT_COARSE_Q 0x174 -+#define RADIO_2057_TX0_TX_SSI_MASTER 0x175 -+#define RADIO_2057_TX0_IQCAL_VCM_HG 0x176 -+#define RADIO_2057_TX0_IQCAL_IDAC 0x177 -+#define RADIO_2057_TX0_TSSI_VCM 0x178 -+#define RADIO_2057_TX0_TX_SSI_MUX 0x179 -+#define RADIO_2057_TX0_TSSIA 0x17a -+#define RADIO_2057_TX0_TSSIG 0x17b -+#define RADIO_2057_TX0_TSSI_MISC1 0x17c -+#define RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN 0x17d -+#define RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP 0x17e -+#define RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN 0x17f -+#define RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP 0x180 -+#define RADIO_2057_TX1_IQCAL_GAIN_BW 0x190 -+#define RADIO_2057_TX1_LOFT_FINE_I 0x191 -+#define RADIO_2057_TX1_LOFT_FINE_Q 0x192 -+#define RADIO_2057_TX1_LOFT_COARSE_I 0x193 -+#define RADIO_2057_TX1_LOFT_COARSE_Q 0x194 -+#define RADIO_2057_TX1_TX_SSI_MASTER 0x195 -+#define RADIO_2057_TX1_IQCAL_VCM_HG 0x196 -+#define RADIO_2057_TX1_IQCAL_IDAC 0x197 -+#define RADIO_2057_TX1_TSSI_VCM 0x198 -+#define RADIO_2057_TX1_TX_SSI_MUX 0x199 -+#define RADIO_2057_TX1_TSSIA 0x19a -+#define RADIO_2057_TX1_TSSIG 0x19b -+#define RADIO_2057_TX1_TSSI_MISC1 0x19c -+#define RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN 0x19d -+#define RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP 0x19e -+#define RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN 0x19f -+#define RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP 0x1a0 -+#define RADIO_2057_AFE_VCM_CAL_MASTER_CORE0 0x1a1 -+#define RADIO_2057_AFE_SET_VCM_I_CORE0 0x1a2 -+#define RADIO_2057_AFE_SET_VCM_Q_CORE0 0x1a3 -+#define RADIO_2057_AFE_STATUS_VCM_IQADC_CORE0 0x1a4 -+#define RADIO_2057_AFE_STATUS_VCM_I_CORE0 0x1a5 -+#define RADIO_2057_AFE_STATUS_VCM_Q_CORE0 0x1a6 -+#define RADIO_2057_AFE_VCM_CAL_MASTER_CORE1 0x1a7 -+#define RADIO_2057_AFE_SET_VCM_I_CORE1 0x1a8 -+#define RADIO_2057_AFE_SET_VCM_Q_CORE1 0x1a9 -+#define RADIO_2057_AFE_STATUS_VCM_IQADC_CORE1 0x1aa -+#define RADIO_2057_AFE_STATUS_VCM_I_CORE1 0x1ab -+#define RADIO_2057_AFE_STATUS_VCM_Q_CORE1 0x1ac -+ -+#define RADIO_2057v7_DACBUF_VINCM_CORE0 0x1ad -+#define RADIO_2057v7_RCCAL_MASTER 0x1ae -+#define RADIO_2057v7_TR2G_CONFIG3_CORE0_NU 0x1af -+#define RADIO_2057v7_TR2G_CONFIG3_CORE1_NU 0x1b0 -+#define RADIO_2057v7_LOGEN_PUS1 0x1b1 -+#define RADIO_2057v7_OVR_REG5 0x1b2 -+#define RADIO_2057v7_OVR_REG6 0x1b3 -+#define RADIO_2057v7_OVR_REG7 0x1b4 -+#define RADIO_2057v7_OVR_REG8 0x1b5 -+#define RADIO_2057v7_OVR_REG9 0x1b6 -+#define RADIO_2057v7_OVR_REG10 0x1b7 -+#define RADIO_2057v7_OVR_REG11 0x1b8 -+#define RADIO_2057v7_OVR_REG12 0x1b9 -+#define RADIO_2057v7_OVR_REG13 0x1ba -+#define RADIO_2057v7_OVR_REG14 0x1bb -+#define RADIO_2057v7_OVR_REG15 0x1bc -+#define RADIO_2057v7_OVR_REG16 0x1bd -+#define RADIO_2057v7_OVR_REG1 0x1be -+#define RADIO_2057v7_OVR_REG18 0x1bf -+#define RADIO_2057v7_OVR_REG19 0x1c0 -+#define RADIO_2057v7_OVR_REG20 0x1c1 -+#define RADIO_2057v7_OVR_REG21 0x1c2 -+#define RADIO_2057v7_OVR_REG2 0x1c3 -+#define RADIO_2057v7_OVR_REG23 0x1c4 -+#define RADIO_2057v7_OVR_REG24 0x1c5 -+#define RADIO_2057v7_OVR_REG25 0x1c6 -+#define RADIO_2057v7_OVR_REG26 0x1c7 -+#define RADIO_2057v7_OVR_REG27 0x1c8 -+#define RADIO_2057v7_OVR_REG28 0x1c9 -+#define RADIO_2057v7_IQTEST_SEL_PU2 0x1ca -+ -+#define RADIO_2057_VCM_MASK 0x7 -+ -+#endif /* _BRCM_PHY_RADIO_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phyreg_n.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phyreg_n.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phyreg_n.h.orig 2011-11-09 13:46:58.277800233 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phyreg_n.h 2011-11-09 13:47:17.035565729 -0500 -@@ -0,0 +1,167 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#define NPHY_TBL_ID_GAIN1 0 -+#define NPHY_TBL_ID_GAIN2 1 -+#define NPHY_TBL_ID_GAINBITS1 2 -+#define NPHY_TBL_ID_GAINBITS2 3 -+#define NPHY_TBL_ID_GAINLIMIT 4 -+#define NPHY_TBL_ID_WRSSIGainLimit 5 -+#define NPHY_TBL_ID_RFSEQ 7 -+#define NPHY_TBL_ID_AFECTRL 8 -+#define NPHY_TBL_ID_ANTSWCTRLLUT 9 -+#define NPHY_TBL_ID_IQLOCAL 15 -+#define NPHY_TBL_ID_NOISEVAR 16 -+#define NPHY_TBL_ID_SAMPLEPLAY 17 -+#define NPHY_TBL_ID_CORE1TXPWRCTL 26 -+#define NPHY_TBL_ID_CORE2TXPWRCTL 27 -+#define NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL 30 -+ -+#define NPHY_TBL_ID_EPSILONTBL0 31 -+#define NPHY_TBL_ID_SCALARTBL0 32 -+#define NPHY_TBL_ID_EPSILONTBL1 33 -+#define NPHY_TBL_ID_SCALARTBL1 34 -+ -+#define NPHY_TO_BPHY_OFF 0xc00 -+ -+#define NPHY_BandControl_currentBand 0x0001 -+#define RFCC_CHIP0_PU 0x0400 -+#define RFCC_POR_FORCE 0x0040 -+#define RFCC_OE_POR_FORCE 0x0080 -+#define NPHY_RfctrlIntc_override_OFF 0 -+#define NPHY_RfctrlIntc_override_TRSW 1 -+#define NPHY_RfctrlIntc_override_PA 2 -+#define NPHY_RfctrlIntc_override_EXT_LNA_PU 3 -+#define NPHY_RfctrlIntc_override_EXT_LNA_GAIN 4 -+#define RIFS_ENABLE 0x80 -+#define BPHY_BAND_SEL_UP20 0x10 -+#define NPHY_MLenable 0x02 -+ -+#define NPHY_RfseqMode_CoreActv_override 0x0001 -+#define NPHY_RfseqMode_Trigger_override 0x0002 -+#define NPHY_RfseqCoreActv_TxRxChain0 (0x11) -+#define NPHY_RfseqCoreActv_TxRxChain1 (0x22) -+ -+#define NPHY_RfseqTrigger_rx2tx 0x0001 -+#define NPHY_RfseqTrigger_tx2rx 0x0002 -+#define NPHY_RfseqTrigger_updategainh 0x0004 -+#define NPHY_RfseqTrigger_updategainl 0x0008 -+#define NPHY_RfseqTrigger_updategainu 0x0010 -+#define NPHY_RfseqTrigger_reset2rx 0x0020 -+#define NPHY_RfseqStatus_rx2tx 0x0001 -+#define NPHY_RfseqStatus_tx2rx 0x0002 -+#define NPHY_RfseqStatus_updategainh 0x0004 -+#define NPHY_RfseqStatus_updategainl 0x0008 -+#define NPHY_RfseqStatus_updategainu 0x0010 -+#define NPHY_RfseqStatus_reset2rx 0x0020 -+#define NPHY_ClassifierCtrl_cck_en 0x1 -+#define NPHY_ClassifierCtrl_ofdm_en 0x2 -+#define NPHY_ClassifierCtrl_waited_en 0x4 -+#define NPHY_IQFlip_ADC1 0x0001 -+#define NPHY_IQFlip_ADC2 0x0010 -+#define NPHY_sampleCmd_STOP 0x0002 -+ -+#define RX_GF_OR_MM 0x0004 -+#define RX_GF_MM_AUTO 0x0100 -+ -+#define NPHY_iqloCalCmdGctl_IQLO_CAL_EN 0x8000 -+ -+#define NPHY_IqestCmd_iqstart 0x1 -+#define NPHY_IqestCmd_iqMode 0x2 -+ -+#define NPHY_TxPwrCtrlCmd_pwrIndex_init 0x40 -+#define NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 0x19 -+ -+#define PRIM_SEL_UP20 0x8000 -+ -+#define NPHY_RFSEQ_RX2TX 0x0 -+#define NPHY_RFSEQ_TX2RX 0x1 -+#define NPHY_RFSEQ_RESET2RX 0x2 -+#define NPHY_RFSEQ_UPDATEGAINH 0x3 -+#define NPHY_RFSEQ_UPDATEGAINL 0x4 -+#define NPHY_RFSEQ_UPDATEGAINU 0x5 -+ -+#define NPHY_RFSEQ_CMD_NOP 0x0 -+#define NPHY_RFSEQ_CMD_RXG_FBW 0x1 -+#define NPHY_RFSEQ_CMD_TR_SWITCH 0x2 -+#define NPHY_RFSEQ_CMD_EXT_PA 0x3 -+#define NPHY_RFSEQ_CMD_RXPD_TXPD 0x4 -+#define NPHY_RFSEQ_CMD_TX_GAIN 0x5 -+#define NPHY_RFSEQ_CMD_RX_GAIN 0x6 -+#define NPHY_RFSEQ_CMD_SET_HPF_BW 0x7 -+#define NPHY_RFSEQ_CMD_CLR_HIQ_DIS 0x8 -+#define NPHY_RFSEQ_CMD_END 0xf -+ -+#define NPHY_REV3_RFSEQ_CMD_NOP 0x0 -+#define NPHY_REV3_RFSEQ_CMD_RXG_FBW 0x1 -+#define NPHY_REV3_RFSEQ_CMD_TR_SWITCH 0x2 -+#define NPHY_REV3_RFSEQ_CMD_INT_PA_PU 0x3 -+#define NPHY_REV3_RFSEQ_CMD_EXT_PA 0x4 -+#define NPHY_REV3_RFSEQ_CMD_RXPD_TXPD 0x5 -+#define NPHY_REV3_RFSEQ_CMD_TX_GAIN 0x6 -+#define NPHY_REV3_RFSEQ_CMD_RX_GAIN 0x7 -+#define NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS 0x8 -+#define NPHY_REV3_RFSEQ_CMD_SET_HPF_H_HPC 0x9 -+#define NPHY_REV3_RFSEQ_CMD_SET_LPF_H_HPC 0xa -+#define NPHY_REV3_RFSEQ_CMD_SET_HPF_M_HPC 0xb -+#define NPHY_REV3_RFSEQ_CMD_SET_LPF_M_HPC 0xc -+#define NPHY_REV3_RFSEQ_CMD_SET_HPF_L_HPC 0xd -+#define NPHY_REV3_RFSEQ_CMD_SET_LPF_L_HPC 0xe -+#define NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS 0xf -+#define NPHY_REV3_RFSEQ_CMD_END 0x1f -+ -+#define NPHY_RSSI_SEL_W1 0x0 -+#define NPHY_RSSI_SEL_W2 0x1 -+#define NPHY_RSSI_SEL_NB 0x2 -+#define NPHY_RSSI_SEL_IQ 0x3 -+#define NPHY_RSSI_SEL_TSSI_2G 0x4 -+#define NPHY_RSSI_SEL_TSSI_5G 0x5 -+#define NPHY_RSSI_SEL_TBD 0x6 -+ -+#define NPHY_RAIL_I 0x0 -+#define NPHY_RAIL_Q 0x1 -+ -+#define NPHY_FORCESIG_DECODEGATEDCLKS 0x8 -+ -+#define NPHY_REV7_RfctrlOverride_cmd_rxrf_pu 0x0 -+#define NPHY_REV7_RfctrlOverride_cmd_rx_pu 0x1 -+#define NPHY_REV7_RfctrlOverride_cmd_tx_pu 0x2 -+#define NPHY_REV7_RfctrlOverride_cmd_rxgain 0x3 -+#define NPHY_REV7_RfctrlOverride_cmd_txgain 0x4 -+ -+#define NPHY_REV7_RXGAINCODE_RFMXGAIN_MASK 0x000ff -+#define NPHY_REV7_RXGAINCODE_LPFGAIN_MASK 0x0ff00 -+#define NPHY_REV7_RXGAINCODE_DVGAGAIN_MASK 0xf0000 -+ -+#define NPHY_REV7_TXGAINCODE_TGAIN_MASK 0x7fff -+#define NPHY_REV7_TXGAINCODE_LPFGAIN_MASK 0x8000 -+#define NPHY_REV7_TXGAINCODE_BIQ0GAIN_SHIFT 14 -+ -+#define NPHY_REV7_RFCTRLOVERRIDE_ID0 0x0 -+#define NPHY_REV7_RFCTRLOVERRIDE_ID1 0x1 -+#define NPHY_REV7_RFCTRLOVERRIDE_ID2 0x2 -+ -+#define NPHY_IqestIqAccLo(core) ((core == 0) ? 0x12c : 0x134) -+ -+#define NPHY_IqestIqAccHi(core) ((core == 0) ? 0x12d : 0x135) -+ -+#define NPHY_IqestipwrAccLo(core) ((core == 0) ? 0x12e : 0x136) -+ -+#define NPHY_IqestipwrAccHi(core) ((core == 0) ? 0x12f : 0x137) -+ -+#define NPHY_IqestqpwrAccLo(core) ((core == 0) ? 0x130 : 0x138) -+ -+#define NPHY_IqestqpwrAccHi(core) ((core == 0) ? 0x131 : 0x139) -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c.orig 2011-11-09 13:46:58.278800221 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c 2011-11-09 13:47:17.036565717 -0500 -@@ -0,0 +1,3250 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include "phytbl_lcn.h" -+ -+static const u32 dot11lcn_gain_tbl_rev0[] = { -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000004, -+ 0x00000000, -+ 0x00000004, -+ 0x00000008, -+ 0x00000001, -+ 0x00000005, -+ 0x00000009, -+ 0x0000000d, -+ 0x0000004d, -+ 0x0000008d, -+ 0x0000000d, -+ 0x0000004d, -+ 0x0000008d, -+ 0x000000cd, -+ 0x0000004f, -+ 0x0000008f, -+ 0x000000cf, -+ 0x000000d3, -+ 0x00000113, -+ 0x00000513, -+ 0x00000913, -+ 0x00000953, -+ 0x00000d53, -+ 0x00001153, -+ 0x00001193, -+ 0x00005193, -+ 0x00009193, -+ 0x0000d193, -+ 0x00011193, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000004, -+ 0x00000000, -+ 0x00000004, -+ 0x00000008, -+ 0x00000001, -+ 0x00000005, -+ 0x00000009, -+ 0x0000000d, -+ 0x0000004d, -+ 0x0000008d, -+ 0x0000000d, -+ 0x0000004d, -+ 0x0000008d, -+ 0x000000cd, -+ 0x0000004f, -+ 0x0000008f, -+ 0x000000cf, -+ 0x000000d3, -+ 0x00000113, -+ 0x00000513, -+ 0x00000913, -+ 0x00000953, -+ 0x00000d53, -+ 0x00001153, -+ 0x00005153, -+ 0x00009153, -+ 0x0000d153, -+ 0x00011153, -+ 0x00015153, -+ 0x00019153, -+ 0x0001d153, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+static const u32 dot11lcn_gain_tbl_rev1[] = { -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000008, -+ 0x00000004, -+ 0x00000008, -+ 0x00000001, -+ 0x00000005, -+ 0x00000009, -+ 0x0000000D, -+ 0x00000011, -+ 0x00000051, -+ 0x00000091, -+ 0x00000011, -+ 0x00000051, -+ 0x00000091, -+ 0x000000d1, -+ 0x00000053, -+ 0x00000093, -+ 0x000000d3, -+ 0x000000d7, -+ 0x00000117, -+ 0x00000517, -+ 0x00000917, -+ 0x00000957, -+ 0x00000d57, -+ 0x00001157, -+ 0x00001197, -+ 0x00005197, -+ 0x00009197, -+ 0x0000d197, -+ 0x00011197, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000008, -+ 0x00000004, -+ 0x00000008, -+ 0x00000001, -+ 0x00000005, -+ 0x00000009, -+ 0x0000000D, -+ 0x00000011, -+ 0x00000051, -+ 0x00000091, -+ 0x00000011, -+ 0x00000051, -+ 0x00000091, -+ 0x000000d1, -+ 0x00000053, -+ 0x00000093, -+ 0x000000d3, -+ 0x000000d7, -+ 0x00000117, -+ 0x00000517, -+ 0x00000917, -+ 0x00000957, -+ 0x00000d57, -+ 0x00001157, -+ 0x00005157, -+ 0x00009157, -+ 0x0000d157, -+ 0x00011157, -+ 0x00015157, -+ 0x00019157, -+ 0x0001d157, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+static const u16 dot11lcn_aux_gain_idx_tbl_rev0[] = { -+ 0x0401, -+ 0x0402, -+ 0x0403, -+ 0x0404, -+ 0x0405, -+ 0x0406, -+ 0x0407, -+ 0x0408, -+ 0x0409, -+ 0x040a, -+ 0x058b, -+ 0x058c, -+ 0x058d, -+ 0x058e, -+ 0x058f, -+ 0x0090, -+ 0x0091, -+ 0x0092, -+ 0x0193, -+ 0x0194, -+ 0x0195, -+ 0x0196, -+ 0x0197, -+ 0x0198, -+ 0x0199, -+ 0x019a, -+ 0x019b, -+ 0x019c, -+ 0x019d, -+ 0x019e, -+ 0x019f, -+ 0x01a0, -+ 0x01a1, -+ 0x01a2, -+ 0x01a3, -+ 0x01a4, -+ 0x01a5, -+ 0x0000, -+}; -+ -+static const u32 dot11lcn_gain_idx_tbl_rev0[] = { -+ 0x00000000, -+ 0x00000000, -+ 0x10000000, -+ 0x00000000, -+ 0x20000000, -+ 0x00000000, -+ 0x30000000, -+ 0x00000000, -+ 0x40000000, -+ 0x00000000, -+ 0x50000000, -+ 0x00000000, -+ 0x60000000, -+ 0x00000000, -+ 0x70000000, -+ 0x00000000, -+ 0x80000000, -+ 0x00000000, -+ 0x90000000, -+ 0x00000008, -+ 0xa0000000, -+ 0x00000008, -+ 0xb0000000, -+ 0x00000008, -+ 0xc0000000, -+ 0x00000008, -+ 0xd0000000, -+ 0x00000008, -+ 0xe0000000, -+ 0x00000008, -+ 0xf0000000, -+ 0x00000008, -+ 0x00000000, -+ 0x00000009, -+ 0x10000000, -+ 0x00000009, -+ 0x20000000, -+ 0x00000019, -+ 0x30000000, -+ 0x00000019, -+ 0x40000000, -+ 0x00000019, -+ 0x50000000, -+ 0x00000019, -+ 0x60000000, -+ 0x00000019, -+ 0x70000000, -+ 0x00000019, -+ 0x80000000, -+ 0x00000019, -+ 0x90000000, -+ 0x00000019, -+ 0xa0000000, -+ 0x00000019, -+ 0xb0000000, -+ 0x00000019, -+ 0xc0000000, -+ 0x00000019, -+ 0xd0000000, -+ 0x00000019, -+ 0xe0000000, -+ 0x00000019, -+ 0xf0000000, -+ 0x00000019, -+ 0x00000000, -+ 0x0000001a, -+ 0x10000000, -+ 0x0000001a, -+ 0x20000000, -+ 0x0000001a, -+ 0x30000000, -+ 0x0000001a, -+ 0x40000000, -+ 0x0000001a, -+ 0x50000000, -+ 0x00000002, -+ 0x60000000, -+ 0x00000002, -+ 0x70000000, -+ 0x00000002, -+ 0x80000000, -+ 0x00000002, -+ 0x90000000, -+ 0x00000002, -+ 0xa0000000, -+ 0x00000002, -+ 0xb0000000, -+ 0x00000002, -+ 0xc0000000, -+ 0x0000000a, -+ 0xd0000000, -+ 0x0000000a, -+ 0xe0000000, -+ 0x0000000a, -+ 0xf0000000, -+ 0x0000000a, -+ 0x00000000, -+ 0x0000000b, -+ 0x10000000, -+ 0x0000000b, -+ 0x20000000, -+ 0x0000000b, -+ 0x30000000, -+ 0x0000000b, -+ 0x40000000, -+ 0x0000000b, -+ 0x50000000, -+ 0x0000001b, -+ 0x60000000, -+ 0x0000001b, -+ 0x70000000, -+ 0x0000001b, -+ 0x80000000, -+ 0x0000001b, -+ 0x90000000, -+ 0x0000001b, -+ 0xa0000000, -+ 0x0000001b, -+ 0xb0000000, -+ 0x0000001b, -+ 0xc0000000, -+ 0x0000001b, -+ 0xd0000000, -+ 0x0000001b, -+ 0xe0000000, -+ 0x0000001b, -+ 0xf0000000, -+ 0x0000001b, -+ 0x00000000, -+ 0x0000001c, -+ 0x10000000, -+ 0x0000001c, -+ 0x20000000, -+ 0x0000001c, -+ 0x30000000, -+ 0x0000001c, -+ 0x40000000, -+ 0x0000001c, -+ 0x50000000, -+ 0x0000001c, -+ 0x60000000, -+ 0x0000001c, -+ 0x70000000, -+ 0x0000001c, -+ 0x80000000, -+ 0x0000001c, -+ 0x90000000, -+ 0x0000001c, -+}; -+ -+static const u16 dot11lcn_aux_gain_idx_tbl_2G[] = { -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0001, -+ 0x0080, -+ 0x0081, -+ 0x0100, -+ 0x0101, -+ 0x0180, -+ 0x0181, -+ 0x0182, -+ 0x0183, -+ 0x0184, -+ 0x0185, -+ 0x0186, -+ 0x0187, -+ 0x0188, -+ 0x0285, -+ 0x0289, -+ 0x028a, -+ 0x028b, -+ 0x028c, -+ 0x028d, -+ 0x028e, -+ 0x028f, -+ 0x0290, -+ 0x0291, -+ 0x0292, -+ 0x0293, -+ 0x0294, -+ 0x0295, -+ 0x0296, -+ 0x0297, -+ 0x0298, -+ 0x0299, -+ 0x029a, -+ 0x0000 -+}; -+ -+static const u8 dot11lcn_gain_val_tbl_2G[] = { -+ 0xfc, -+ 0x02, -+ 0x08, -+ 0x0e, -+ 0x13, -+ 0x1b, -+ 0xfc, -+ 0x02, -+ 0x08, -+ 0x0e, -+ 0x13, -+ 0x1b, -+ 0xfc, -+ 0x00, -+ 0x0c, -+ 0x03, -+ 0xeb, -+ 0xfe, -+ 0x07, -+ 0x0b, -+ 0x0f, -+ 0xfb, -+ 0xfe, -+ 0x01, -+ 0x05, -+ 0x08, -+ 0x0b, -+ 0x0e, -+ 0x11, -+ 0x14, -+ 0x17, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x03, -+ 0x06, -+ 0x09, -+ 0x0c, -+ 0x0f, -+ 0x12, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x03, -+ 0x06, -+ 0x09, -+ 0x0c, -+ 0x0f, -+ 0x12, -+ 0x15, -+ 0x18, -+ 0x1b, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00 -+}; -+ -+static const u32 dot11lcn_gain_idx_tbl_2G[] = { -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x10000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000008, -+ 0x10000000, -+ 0x00000008, -+ 0x00000000, -+ 0x00000010, -+ 0x10000000, -+ 0x00000010, -+ 0x00000000, -+ 0x00000018, -+ 0x10000000, -+ 0x00000018, -+ 0x20000000, -+ 0x00000018, -+ 0x30000000, -+ 0x00000018, -+ 0x40000000, -+ 0x00000018, -+ 0x50000000, -+ 0x00000018, -+ 0x60000000, -+ 0x00000018, -+ 0x70000000, -+ 0x00000018, -+ 0x80000000, -+ 0x00000018, -+ 0x50000000, -+ 0x00000028, -+ 0x90000000, -+ 0x00000028, -+ 0xa0000000, -+ 0x00000028, -+ 0xb0000000, -+ 0x00000028, -+ 0xc0000000, -+ 0x00000028, -+ 0xd0000000, -+ 0x00000028, -+ 0xe0000000, -+ 0x00000028, -+ 0xf0000000, -+ 0x00000028, -+ 0x00000000, -+ 0x00000029, -+ 0x10000000, -+ 0x00000029, -+ 0x20000000, -+ 0x00000029, -+ 0x30000000, -+ 0x00000029, -+ 0x40000000, -+ 0x00000029, -+ 0x50000000, -+ 0x00000029, -+ 0x60000000, -+ 0x00000029, -+ 0x70000000, -+ 0x00000029, -+ 0x80000000, -+ 0x00000029, -+ 0x90000000, -+ 0x00000029, -+ 0xa0000000, -+ 0x00000029, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x10000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000008, -+ 0x10000000, -+ 0x00000008, -+ 0x00000000, -+ 0x00000010, -+ 0x10000000, -+ 0x00000010, -+ 0x00000000, -+ 0x00000018, -+ 0x10000000, -+ 0x00000018, -+ 0x20000000, -+ 0x00000018, -+ 0x30000000, -+ 0x00000018, -+ 0x40000000, -+ 0x00000018, -+ 0x50000000, -+ 0x00000018, -+ 0x60000000, -+ 0x00000018, -+ 0x70000000, -+ 0x00000018, -+ 0x80000000, -+ 0x00000018, -+ 0x50000000, -+ 0x00000028, -+ 0x90000000, -+ 0x00000028, -+ 0xa0000000, -+ 0x00000028, -+ 0xb0000000, -+ 0x00000028, -+ 0xc0000000, -+ 0x00000028, -+ 0xd0000000, -+ 0x00000028, -+ 0xe0000000, -+ 0x00000028, -+ 0xf0000000, -+ 0x00000028, -+ 0x00000000, -+ 0x00000029, -+ 0x10000000, -+ 0x00000029, -+ 0x20000000, -+ 0x00000029, -+ 0x30000000, -+ 0x00000029, -+ 0x40000000, -+ 0x00000029, -+ 0x50000000, -+ 0x00000029, -+ 0x60000000, -+ 0x00000029, -+ 0x70000000, -+ 0x00000029, -+ 0x80000000, -+ 0x00000029, -+ 0x90000000, -+ 0x00000029, -+ 0xa0000000, -+ 0x00000029, -+ 0xb0000000, -+ 0x00000029, -+ 0xc0000000, -+ 0x00000029, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000 -+}; -+ -+static const u32 dot11lcn_gain_tbl_2G[] = { -+ 0x00000000, -+ 0x00000004, -+ 0x00000008, -+ 0x00000001, -+ 0x00000005, -+ 0x00000009, -+ 0x0000000d, -+ 0x0000004d, -+ 0x0000008d, -+ 0x00000049, -+ 0x00000089, -+ 0x000000c9, -+ 0x0000004b, -+ 0x0000008b, -+ 0x000000cb, -+ 0x000000cf, -+ 0x0000010f, -+ 0x0000050f, -+ 0x0000090f, -+ 0x0000094f, -+ 0x00000d4f, -+ 0x0000114f, -+ 0x0000118f, -+ 0x0000518f, -+ 0x0000918f, -+ 0x0000d18f, -+ 0x0001118f, -+ 0x0001518f, -+ 0x0001918f, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000 -+}; -+ -+static const u32 dot11lcn_gain_tbl_extlna_2G[] = { -+ 0x00000000, -+ 0x00000004, -+ 0x00000008, -+ 0x00000001, -+ 0x00000005, -+ 0x00000009, -+ 0x0000000d, -+ 0x00000003, -+ 0x00000007, -+ 0x0000000b, -+ 0x0000000f, -+ 0x0000004f, -+ 0x0000008f, -+ 0x000000cf, -+ 0x0000010f, -+ 0x0000014f, -+ 0x0000018f, -+ 0x0000058f, -+ 0x0000098f, -+ 0x00000d8f, -+ 0x00008000, -+ 0x00008004, -+ 0x00008008, -+ 0x00008001, -+ 0x00008005, -+ 0x00008009, -+ 0x0000800d, -+ 0x00008003, -+ 0x00008007, -+ 0x0000800b, -+ 0x0000800f, -+ 0x0000804f, -+ 0x0000808f, -+ 0x000080cf, -+ 0x0000810f, -+ 0x0000814f, -+ 0x0000818f, -+ 0x0000858f, -+ 0x0000898f, -+ 0x00008d8f, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000 -+}; -+ -+static const u16 dot11lcn_aux_gain_idx_tbl_extlna_2G[] = { -+ 0x0400, -+ 0x0400, -+ 0x0400, -+ 0x0400, -+ 0x0400, -+ 0x0400, -+ 0x0400, -+ 0x0400, -+ 0x0400, -+ 0x0401, -+ 0x0402, -+ 0x0403, -+ 0x0404, -+ 0x0483, -+ 0x0484, -+ 0x0485, -+ 0x0486, -+ 0x0583, -+ 0x0584, -+ 0x0585, -+ 0x0587, -+ 0x0588, -+ 0x0589, -+ 0x058a, -+ 0x0687, -+ 0x0688, -+ 0x0689, -+ 0x068a, -+ 0x068b, -+ 0x068c, -+ 0x068d, -+ 0x068e, -+ 0x068f, -+ 0x0690, -+ 0x0691, -+ 0x0692, -+ 0x0693, -+ 0x0000 -+}; -+ -+static const u8 dot11lcn_gain_val_tbl_extlna_2G[] = { -+ 0xfc, -+ 0x02, -+ 0x08, -+ 0x0e, -+ 0x13, -+ 0x1b, -+ 0xfc, -+ 0x02, -+ 0x08, -+ 0x0e, -+ 0x13, -+ 0x1b, -+ 0xfc, -+ 0x00, -+ 0x0f, -+ 0x03, -+ 0xeb, -+ 0xfe, -+ 0x07, -+ 0x0b, -+ 0x0f, -+ 0xfb, -+ 0xfe, -+ 0x01, -+ 0x05, -+ 0x08, -+ 0x0b, -+ 0x0e, -+ 0x11, -+ 0x14, -+ 0x17, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x03, -+ 0x06, -+ 0x09, -+ 0x0c, -+ 0x0f, -+ 0x12, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x03, -+ 0x06, -+ 0x09, -+ 0x0c, -+ 0x0f, -+ 0x12, -+ 0x15, -+ 0x18, -+ 0x1b, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00 -+}; -+ -+static const u32 dot11lcn_gain_idx_tbl_extlna_2G[] = { -+ 0x00000000, -+ 0x00000040, -+ 0x00000000, -+ 0x00000040, -+ 0x00000000, -+ 0x00000040, -+ 0x00000000, -+ 0x00000040, -+ 0x00000000, -+ 0x00000040, -+ 0x00000000, -+ 0x00000040, -+ 0x00000000, -+ 0x00000040, -+ 0x00000000, -+ 0x00000040, -+ 0x00000000, -+ 0x00000040, -+ 0x10000000, -+ 0x00000040, -+ 0x20000000, -+ 0x00000040, -+ 0x30000000, -+ 0x00000040, -+ 0x40000000, -+ 0x00000040, -+ 0x30000000, -+ 0x00000048, -+ 0x40000000, -+ 0x00000048, -+ 0x50000000, -+ 0x00000048, -+ 0x60000000, -+ 0x00000048, -+ 0x30000000, -+ 0x00000058, -+ 0x40000000, -+ 0x00000058, -+ 0x50000000, -+ 0x00000058, -+ 0x70000000, -+ 0x00000058, -+ 0x80000000, -+ 0x00000058, -+ 0x90000000, -+ 0x00000058, -+ 0xa0000000, -+ 0x00000058, -+ 0x70000000, -+ 0x00000068, -+ 0x80000000, -+ 0x00000068, -+ 0x90000000, -+ 0x00000068, -+ 0xa0000000, -+ 0x00000068, -+ 0xb0000000, -+ 0x00000068, -+ 0xc0000000, -+ 0x00000068, -+ 0xd0000000, -+ 0x00000068, -+ 0xe0000000, -+ 0x00000068, -+ 0xf0000000, -+ 0x00000068, -+ 0x00000000, -+ 0x00000069, -+ 0x10000000, -+ 0x00000069, -+ 0x20000000, -+ 0x00000069, -+ 0x30000000, -+ 0x00000069, -+ 0x40000000, -+ 0x00000041, -+ 0x40000000, -+ 0x00000041, -+ 0x40000000, -+ 0x00000041, -+ 0x40000000, -+ 0x00000041, -+ 0x40000000, -+ 0x00000041, -+ 0x40000000, -+ 0x00000041, -+ 0x40000000, -+ 0x00000041, -+ 0x40000000, -+ 0x00000041, -+ 0x40000000, -+ 0x00000041, -+ 0x50000000, -+ 0x00000041, -+ 0x60000000, -+ 0x00000041, -+ 0x70000000, -+ 0x00000041, -+ 0x80000000, -+ 0x00000041, -+ 0x70000000, -+ 0x00000049, -+ 0x80000000, -+ 0x00000049, -+ 0x90000000, -+ 0x00000049, -+ 0xa0000000, -+ 0x00000049, -+ 0x70000000, -+ 0x00000059, -+ 0x80000000, -+ 0x00000059, -+ 0x90000000, -+ 0x00000059, -+ 0xb0000000, -+ 0x00000059, -+ 0xc0000000, -+ 0x00000059, -+ 0xd0000000, -+ 0x00000059, -+ 0xe0000000, -+ 0x00000059, -+ 0xb0000000, -+ 0x00000069, -+ 0xc0000000, -+ 0x00000069, -+ 0xd0000000, -+ 0x00000069, -+ 0xe0000000, -+ 0x00000069, -+ 0xf0000000, -+ 0x00000069, -+ 0x00000000, -+ 0x0000006a, -+ 0x10000000, -+ 0x0000006a, -+ 0x20000000, -+ 0x0000006a, -+ 0x30000000, -+ 0x0000006a, -+ 0x40000000, -+ 0x0000006a, -+ 0x50000000, -+ 0x0000006a, -+ 0x60000000, -+ 0x0000006a, -+ 0x70000000, -+ 0x0000006a, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000 -+}; -+ -+static const u32 dot11lcn_aux_gain_idx_tbl_5G[] = { -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0001, -+ 0x0002, -+ 0x0003, -+ 0x0004, -+ 0x0083, -+ 0x0084, -+ 0x0085, -+ 0x0086, -+ 0x0087, -+ 0x0186, -+ 0x0187, -+ 0x0188, -+ 0x0189, -+ 0x018a, -+ 0x018b, -+ 0x018c, -+ 0x018d, -+ 0x018e, -+ 0x018f, -+ 0x0190, -+ 0x0191, -+ 0x0192, -+ 0x0193, -+ 0x0194, -+ 0x0195, -+ 0x0196, -+ 0x0197, -+ 0x0198, -+ 0x0199, -+ 0x019a, -+ 0x019b, -+ 0x019c, -+ 0x019d, -+ 0x0000 -+}; -+ -+static const u32 dot11lcn_gain_val_tbl_5G[] = { -+ 0xf7, -+ 0xfd, -+ 0x00, -+ 0x04, -+ 0x04, -+ 0x04, -+ 0xf7, -+ 0xfd, -+ 0x00, -+ 0x04, -+ 0x04, -+ 0x04, -+ 0xf6, -+ 0x00, -+ 0x0c, -+ 0x03, -+ 0xeb, -+ 0xfe, -+ 0x06, -+ 0x0a, -+ 0x10, -+ 0x00, -+ 0x03, -+ 0x06, -+ 0x09, -+ 0x0c, -+ 0x0f, -+ 0x12, -+ 0x15, -+ 0x18, -+ 0x1b, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x03, -+ 0x06, -+ 0x09, -+ 0x0c, -+ 0x0f, -+ 0x12, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x03, -+ 0x06, -+ 0x09, -+ 0x0c, -+ 0x0f, -+ 0x12, -+ 0x15, -+ 0x18, -+ 0x1b, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00 -+}; -+ -+static const u32 dot11lcn_gain_idx_tbl_5G[] = { -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x10000000, -+ 0x00000000, -+ 0x20000000, -+ 0x00000000, -+ 0x30000000, -+ 0x00000000, -+ 0x40000000, -+ 0x00000000, -+ 0x30000000, -+ 0x00000008, -+ 0x40000000, -+ 0x00000008, -+ 0x50000000, -+ 0x00000008, -+ 0x60000000, -+ 0x00000008, -+ 0x70000000, -+ 0x00000008, -+ 0x60000000, -+ 0x00000018, -+ 0x70000000, -+ 0x00000018, -+ 0x80000000, -+ 0x00000018, -+ 0x90000000, -+ 0x00000018, -+ 0xa0000000, -+ 0x00000018, -+ 0xb0000000, -+ 0x00000018, -+ 0xc0000000, -+ 0x00000018, -+ 0xd0000000, -+ 0x00000018, -+ 0xe0000000, -+ 0x00000018, -+ 0xf0000000, -+ 0x00000018, -+ 0x00000000, -+ 0x00000019, -+ 0x10000000, -+ 0x00000019, -+ 0x20000000, -+ 0x00000019, -+ 0x30000000, -+ 0x00000019, -+ 0x40000000, -+ 0x00000019, -+ 0x50000000, -+ 0x00000019, -+ 0x60000000, -+ 0x00000019, -+ 0x70000000, -+ 0x00000019, -+ 0x80000000, -+ 0x00000019, -+ 0x90000000, -+ 0x00000019, -+ 0xa0000000, -+ 0x00000019, -+ 0xb0000000, -+ 0x00000019, -+ 0xc0000000, -+ 0x00000019, -+ 0xd0000000, -+ 0x00000019, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000 -+}; -+ -+static const u32 dot11lcn_gain_tbl_5G[] = { -+ 0x00000000, -+ 0x00000040, -+ 0x00000080, -+ 0x00000001, -+ 0x00000005, -+ 0x00000009, -+ 0x0000000d, -+ 0x00000011, -+ 0x00000015, -+ 0x00000055, -+ 0x00000095, -+ 0x00000017, -+ 0x0000001b, -+ 0x0000005b, -+ 0x0000009b, -+ 0x000000db, -+ 0x0000011b, -+ 0x0000015b, -+ 0x0000019b, -+ 0x0000059b, -+ 0x0000099b, -+ 0x00000d9b, -+ 0x0000119b, -+ 0x0000519b, -+ 0x0000919b, -+ 0x0000d19b, -+ 0x0001119b, -+ 0x0001519b, -+ 0x0001919b, -+ 0x0001d19b, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000 -+}; -+ -+const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev0[] = { -+ {&dot11lcn_gain_tbl_rev0, -+ sizeof(dot11lcn_gain_tbl_rev0) / sizeof(dot11lcn_gain_tbl_rev0[0]), 18, -+ 0, 32} -+ , -+ {&dot11lcn_aux_gain_idx_tbl_rev0, -+ sizeof(dot11lcn_aux_gain_idx_tbl_rev0) / -+ sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16} -+ , -+ {&dot11lcn_gain_idx_tbl_rev0, -+ sizeof(dot11lcn_gain_idx_tbl_rev0) / -+ sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32} -+ , -+}; -+ -+static const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev1[] = { -+ {&dot11lcn_gain_tbl_rev1, -+ sizeof(dot11lcn_gain_tbl_rev1) / sizeof(dot11lcn_gain_tbl_rev1[0]), 18, -+ 0, 32} -+ , -+ {&dot11lcn_aux_gain_idx_tbl_rev0, -+ sizeof(dot11lcn_aux_gain_idx_tbl_rev0) / -+ sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16} -+ , -+ {&dot11lcn_gain_idx_tbl_rev0, -+ sizeof(dot11lcn_gain_idx_tbl_rev0) / -+ sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32} -+ , -+}; -+ -+const struct phytbl_info dot11lcnphytbl_rx_gain_info_2G_rev2[] = { -+ {&dot11lcn_gain_tbl_2G, -+ sizeof(dot11lcn_gain_tbl_2G) / sizeof(dot11lcn_gain_tbl_2G[0]), 18, 0, -+ 32} -+ , -+ {&dot11lcn_aux_gain_idx_tbl_2G, -+ sizeof(dot11lcn_aux_gain_idx_tbl_2G) / -+ sizeof(dot11lcn_aux_gain_idx_tbl_2G[0]), 14, 0, 16} -+ , -+ {&dot11lcn_gain_idx_tbl_2G, -+ sizeof(dot11lcn_gain_idx_tbl_2G) / sizeof(dot11lcn_gain_idx_tbl_2G[0]), -+ 13, 0, 32} -+ , -+ {&dot11lcn_gain_val_tbl_2G, -+ sizeof(dot11lcn_gain_val_tbl_2G) / sizeof(dot11lcn_gain_val_tbl_2G[0]), -+ 17, 0, 8} -+}; -+ -+const struct phytbl_info dot11lcnphytbl_rx_gain_info_5G_rev2[] = { -+ {&dot11lcn_gain_tbl_5G, -+ sizeof(dot11lcn_gain_tbl_5G) / sizeof(dot11lcn_gain_tbl_5G[0]), 18, 0, -+ 32} -+ , -+ {&dot11lcn_aux_gain_idx_tbl_5G, -+ sizeof(dot11lcn_aux_gain_idx_tbl_5G) / -+ sizeof(dot11lcn_aux_gain_idx_tbl_5G[0]), 14, 0, 16} -+ , -+ {&dot11lcn_gain_idx_tbl_5G, -+ sizeof(dot11lcn_gain_idx_tbl_5G) / sizeof(dot11lcn_gain_idx_tbl_5G[0]), -+ 13, 0, 32} -+ , -+ {&dot11lcn_gain_val_tbl_5G, -+ sizeof(dot11lcn_gain_val_tbl_5G) / sizeof(dot11lcn_gain_val_tbl_5G[0]), -+ 17, 0, 8} -+}; -+ -+const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[] = { -+ {&dot11lcn_gain_tbl_extlna_2G, -+ sizeof(dot11lcn_gain_tbl_extlna_2G) / -+ sizeof(dot11lcn_gain_tbl_extlna_2G[0]), 18, 0, 32} -+ , -+ {&dot11lcn_aux_gain_idx_tbl_extlna_2G, -+ sizeof(dot11lcn_aux_gain_idx_tbl_extlna_2G) / -+ sizeof(dot11lcn_aux_gain_idx_tbl_extlna_2G[0]), 14, 0, 16} -+ , -+ {&dot11lcn_gain_idx_tbl_extlna_2G, -+ sizeof(dot11lcn_gain_idx_tbl_extlna_2G) / -+ sizeof(dot11lcn_gain_idx_tbl_extlna_2G[0]), 13, 0, 32} -+ , -+ {&dot11lcn_gain_val_tbl_extlna_2G, -+ sizeof(dot11lcn_gain_val_tbl_extlna_2G) / -+ sizeof(dot11lcn_gain_val_tbl_extlna_2G[0]), 17, 0, 8} -+}; -+ -+const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[] = { -+ {&dot11lcn_gain_tbl_5G, -+ sizeof(dot11lcn_gain_tbl_5G) / sizeof(dot11lcn_gain_tbl_5G[0]), 18, 0, -+ 32} -+ , -+ {&dot11lcn_aux_gain_idx_tbl_5G, -+ sizeof(dot11lcn_aux_gain_idx_tbl_5G) / -+ sizeof(dot11lcn_aux_gain_idx_tbl_5G[0]), 14, 0, 16} -+ , -+ {&dot11lcn_gain_idx_tbl_5G, -+ sizeof(dot11lcn_gain_idx_tbl_5G) / sizeof(dot11lcn_gain_idx_tbl_5G[0]), -+ 13, 0, 32} -+ , -+ {&dot11lcn_gain_val_tbl_5G, -+ sizeof(dot11lcn_gain_val_tbl_5G) / sizeof(dot11lcn_gain_val_tbl_5G[0]), -+ 17, 0, 8} -+}; -+ -+const u32 dot11lcnphytbl_rx_gain_info_sz_rev0 = -+ sizeof(dot11lcnphytbl_rx_gain_info_rev0) / -+ sizeof(dot11lcnphytbl_rx_gain_info_rev0[0]); -+ -+const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz = -+ sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2) / -+ sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2[0]); -+ -+const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz = -+ sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2) / -+ sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2[0]); -+ -+static const u16 dot11lcn_min_sig_sq_tbl_rev0[] = { -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+ 0x014d, -+}; -+ -+static const u16 dot11lcn_noise_scale_tbl_rev0[] = { -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+}; -+ -+static const u32 dot11lcn_fltr_ctrl_tbl_rev0[] = { -+ 0x000141f8, -+ 0x000021f8, -+ 0x000021fb, -+ 0x000041fb, -+ 0x0001fe4b, -+ 0x0000217b, -+ 0x00002133, -+ 0x000040eb, -+ 0x0001fea3, -+ 0x0000024b, -+}; -+ -+static const u32 dot11lcn_ps_ctrl_tbl_rev0[] = { -+ 0x00100001, -+ 0x00200010, -+ 0x00300001, -+ 0x00400010, -+ 0x00500022, -+ 0x00600122, -+ 0x00700222, -+ 0x00800322, -+ 0x00900422, -+ 0x00a00522, -+ 0x00b00622, -+ 0x00c00722, -+ 0x00d00822, -+ 0x00f00922, -+ 0x00100a22, -+ 0x00200b22, -+ 0x00300c22, -+ 0x00400d22, -+ 0x00500e22, -+ 0x00600f22, -+}; -+ -+static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[] = { -+ 0x0007, -+ 0x0005, -+ 0x0006, -+ 0x0004, -+ 0x0007, -+ 0x0005, -+ 0x0006, -+ 0x0004, -+ 0x0007, -+ 0x0005, -+ 0x0006, -+ 0x0004, -+ 0x0007, -+ 0x0005, -+ 0x0006, -+ 0x0004, -+ 0x000b, -+ 0x000b, -+ 0x000a, -+ 0x000a, -+ 0x000b, -+ 0x000b, -+ 0x000a, -+ 0x000a, -+ 0x000b, -+ 0x000b, -+ 0x000a, -+ 0x000a, -+ 0x000b, -+ 0x000b, -+ 0x000a, -+ 0x000a, -+ 0x0007, -+ 0x0005, -+ 0x0006, -+ 0x0004, -+ 0x0007, -+ 0x0005, -+ 0x0006, -+ 0x0004, -+ 0x0007, -+ 0x0005, -+ 0x0006, -+ 0x0004, -+ 0x0007, -+ 0x0005, -+ 0x0006, -+ 0x0004, -+ 0x000b, -+ 0x000b, -+ 0x000a, -+ 0x000a, -+ 0x000b, -+ 0x000b, -+ 0x000a, -+ 0x000a, -+ 0x000b, -+ 0x000b, -+ 0x000a, -+ 0x000a, -+ 0x000b, -+ 0x000b, -+ 0x000a, -+ 0x000a, -+ -+}; -+ -+static const u16 dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[] = { -+ 0x0007, -+ 0x0005, -+ 0x0002, -+ 0x0000, -+ 0x0007, -+ 0x0005, -+ 0x0002, -+ 0x0000, -+ 0x0007, -+ 0x0005, -+ 0x0002, -+ 0x0000, -+ 0x0007, -+ 0x0005, -+ 0x0002, -+ 0x0000, -+ 0x0007, -+ 0x0007, -+ 0x0002, -+ 0x0002, -+ 0x0007, -+ 0x0007, -+ 0x0002, -+ 0x0002, -+ 0x0007, -+ 0x0007, -+ 0x0002, -+ 0x0002, -+ 0x0007, -+ 0x0007, -+ 0x0002, -+ 0x0002, -+ 0x0007, -+ 0x0005, -+ 0x0002, -+ 0x0000, -+ 0x0007, -+ 0x0005, -+ 0x0002, -+ 0x0000, -+ 0x0007, -+ 0x0005, -+ 0x0002, -+ 0x0000, -+ 0x0007, -+ 0x0005, -+ 0x0002, -+ 0x0000, -+ 0x0007, -+ 0x0007, -+ 0x0002, -+ 0x0002, -+ 0x0007, -+ 0x0007, -+ 0x0002, -+ 0x0002, -+ 0x0007, -+ 0x0007, -+ 0x0002, -+ 0x0002, -+ 0x0007, -+ 0x0007, -+ 0x0002, -+ 0x0002, -+}; -+ -+static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = { -+ 0x0002, -+ 0x0008, -+ 0x0004, -+ 0x0001, -+ 0x0002, -+ 0x0008, -+ 0x0004, -+ 0x0001, -+ 0x0002, -+ 0x0008, -+ 0x0004, -+ 0x0001, -+ 0x0002, -+ 0x0008, -+ 0x0004, -+ 0x0001, -+ 0x0002, -+ 0x0008, -+ 0x0004, -+ 0x0001, -+ 0x0002, -+ 0x0008, -+ 0x0004, -+ 0x0001, -+ 0x0002, -+ 0x0008, -+ 0x0004, -+ 0x0001, -+ 0x0002, -+ 0x0008, -+ 0x0004, -+ 0x0001, -+ 0x0002, -+ 0x0008, -+ 0x0004, -+ 0x0001, -+ 0x0002, -+ 0x0008, -+ 0x0004, -+ 0x0001, -+ 0x0002, -+ 0x0008, -+ 0x0004, -+ 0x0001, -+ 0x0002, -+ 0x0008, -+ 0x0004, -+ 0x0001, -+ 0x0002, -+ 0x0008, -+ 0x0004, -+ 0x0001, -+ 0x0002, -+ 0x0008, -+ 0x0004, -+ 0x0001, -+ 0x0002, -+ 0x0008, -+ 0x0004, -+ 0x0001, -+ 0x0002, -+ 0x0008, -+ 0x0004, -+ 0x0001, -+}; -+ -+static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = { -+ 0x000a, -+ 0x0009, -+ 0x0006, -+ 0x0005, -+ 0x000a, -+ 0x0009, -+ 0x0006, -+ 0x0005, -+ 0x000a, -+ 0x0009, -+ 0x0006, -+ 0x0005, -+ 0x000a, -+ 0x0009, -+ 0x0006, -+ 0x0005, -+ 0x000a, -+ 0x0009, -+ 0x0006, -+ 0x0005, -+ 0x000a, -+ 0x0009, -+ 0x0006, -+ 0x0005, -+ 0x000a, -+ 0x0009, -+ 0x0006, -+ 0x0005, -+ 0x000a, -+ 0x0009, -+ 0x0006, -+ 0x0005, -+ 0x000a, -+ 0x0009, -+ 0x0006, -+ 0x0005, -+ 0x000a, -+ 0x0009, -+ 0x0006, -+ 0x0005, -+ 0x000a, -+ 0x0009, -+ 0x0006, -+ 0x0005, -+ 0x000a, -+ 0x0009, -+ 0x0006, -+ 0x0005, -+ 0x000a, -+ 0x0009, -+ 0x0006, -+ 0x0005, -+ 0x000a, -+ 0x0009, -+ 0x0006, -+ 0x0005, -+ 0x000a, -+ 0x0009, -+ 0x0006, -+ 0x0005, -+ 0x000a, -+ 0x0009, -+ 0x0006, -+ 0x0005, -+}; -+ -+static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = { -+ 0x0004, -+ 0x0004, -+ 0x0002, -+ 0x0002, -+ 0x0004, -+ 0x0004, -+ 0x0002, -+ 0x0002, -+ 0x0004, -+ 0x0004, -+ 0x0002, -+ 0x0002, -+ 0x0004, -+ 0x0004, -+ 0x0002, -+ 0x0002, -+ 0x0004, -+ 0x0004, -+ 0x0002, -+ 0x0002, -+ 0x0004, -+ 0x0004, -+ 0x0002, -+ 0x0002, -+ 0x0004, -+ 0x0004, -+ 0x0002, -+ 0x0002, -+ 0x0004, -+ 0x0004, -+ 0x0002, -+ 0x0002, -+ 0x0004, -+ 0x0004, -+ 0x0002, -+ 0x0002, -+ 0x0004, -+ 0x0004, -+ 0x0002, -+ 0x0002, -+ 0x0004, -+ 0x0004, -+ 0x0002, -+ 0x0002, -+ 0x0004, -+ 0x0004, -+ 0x0002, -+ 0x0002, -+ 0x0004, -+ 0x0004, -+ 0x0002, -+ 0x0002, -+ 0x0004, -+ 0x0004, -+ 0x0002, -+ 0x0002, -+ 0x0004, -+ 0x0004, -+ 0x0002, -+ 0x0002, -+ 0x0004, -+ 0x0004, -+ 0x0002, -+ 0x0002, -+}; -+ -+static const u8 dot11lcn_nf_table_rev0[] = { -+ 0x5f, -+ 0x36, -+ 0x29, -+ 0x1f, -+ 0x5f, -+ 0x36, -+ 0x29, -+ 0x1f, -+ 0x5f, -+ 0x36, -+ 0x29, -+ 0x1f, -+ 0x5f, -+ 0x36, -+ 0x29, -+ 0x1f, -+}; -+ -+static const u8 dot11lcn_gain_val_tbl_rev0[] = { -+ 0x09, -+ 0x0f, -+ 0x14, -+ 0x18, -+ 0xfe, -+ 0x07, -+ 0x0b, -+ 0x0f, -+ 0xfb, -+ 0xfe, -+ 0x01, -+ 0x05, -+ 0x08, -+ 0x0b, -+ 0x0e, -+ 0x11, -+ 0x14, -+ 0x17, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x03, -+ 0x06, -+ 0x09, -+ 0x0c, -+ 0x0f, -+ 0x12, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x03, -+ 0x06, -+ 0x09, -+ 0x0c, -+ 0x0f, -+ 0x12, -+ 0x15, -+ 0x18, -+ 0x1b, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x03, -+ 0xeb, -+ 0x00, -+ 0x00, -+}; -+ -+static const u8 dot11lcn_spur_tbl_rev0[] = { -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x02, -+ 0x03, -+ 0x01, -+ 0x03, -+ 0x02, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x02, -+ 0x03, -+ 0x01, -+ 0x03, -+ 0x02, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+ 0x01, -+}; -+ -+static const u16 dot11lcn_unsup_mcs_tbl_rev0[] = { -+ 0x001a, -+ 0x0034, -+ 0x004e, -+ 0x0068, -+ 0x009c, -+ 0x00d0, -+ 0x00ea, -+ 0x0104, -+ 0x0034, -+ 0x0068, -+ 0x009c, -+ 0x00d0, -+ 0x0138, -+ 0x01a0, -+ 0x01d4, -+ 0x0208, -+ 0x004e, -+ 0x009c, -+ 0x00ea, -+ 0x0138, -+ 0x01d4, -+ 0x0270, -+ 0x02be, -+ 0x030c, -+ 0x0068, -+ 0x00d0, -+ 0x0138, -+ 0x01a0, -+ 0x0270, -+ 0x0340, -+ 0x03a8, -+ 0x0410, -+ 0x0018, -+ 0x009c, -+ 0x00d0, -+ 0x0104, -+ 0x00ea, -+ 0x0138, -+ 0x0186, -+ 0x00d0, -+ 0x0104, -+ 0x0104, -+ 0x0138, -+ 0x016c, -+ 0x016c, -+ 0x01a0, -+ 0x0138, -+ 0x0186, -+ 0x0186, -+ 0x01d4, -+ 0x0222, -+ 0x0222, -+ 0x0270, -+ 0x0104, -+ 0x0138, -+ 0x016c, -+ 0x0138, -+ 0x016c, -+ 0x01a0, -+ 0x01d4, -+ 0x01a0, -+ 0x01d4, -+ 0x0208, -+ 0x0208, -+ 0x023c, -+ 0x0186, -+ 0x01d4, -+ 0x0222, -+ 0x01d4, -+ 0x0222, -+ 0x0270, -+ 0x02be, -+ 0x0270, -+ 0x02be, -+ 0x030c, -+ 0x030c, -+ 0x035a, -+ 0x0036, -+ 0x006c, -+ 0x00a2, -+ 0x00d8, -+ 0x0144, -+ 0x01b0, -+ 0x01e6, -+ 0x021c, -+ 0x006c, -+ 0x00d8, -+ 0x0144, -+ 0x01b0, -+ 0x0288, -+ 0x0360, -+ 0x03cc, -+ 0x0438, -+ 0x00a2, -+ 0x0144, -+ 0x01e6, -+ 0x0288, -+ 0x03cc, -+ 0x0510, -+ 0x05b2, -+ 0x0654, -+ 0x00d8, -+ 0x01b0, -+ 0x0288, -+ 0x0360, -+ 0x0510, -+ 0x06c0, -+ 0x0798, -+ 0x0870, -+ 0x0018, -+ 0x0144, -+ 0x01b0, -+ 0x021c, -+ 0x01e6, -+ 0x0288, -+ 0x032a, -+ 0x01b0, -+ 0x021c, -+ 0x021c, -+ 0x0288, -+ 0x02f4, -+ 0x02f4, -+ 0x0360, -+ 0x0288, -+ 0x032a, -+ 0x032a, -+ 0x03cc, -+ 0x046e, -+ 0x046e, -+ 0x0510, -+ 0x021c, -+ 0x0288, -+ 0x02f4, -+ 0x0288, -+ 0x02f4, -+ 0x0360, -+ 0x03cc, -+ 0x0360, -+ 0x03cc, -+ 0x0438, -+ 0x0438, -+ 0x04a4, -+ 0x032a, -+ 0x03cc, -+ 0x046e, -+ 0x03cc, -+ 0x046e, -+ 0x0510, -+ 0x05b2, -+ 0x0510, -+ 0x05b2, -+ 0x0654, -+ 0x0654, -+ 0x06f6, -+}; -+ -+static const u16 dot11lcn_iq_local_tbl_rev0[] = { -+ 0x0200, -+ 0x0300, -+ 0x0400, -+ 0x0600, -+ 0x0800, -+ 0x0b00, -+ 0x1000, -+ 0x1001, -+ 0x1002, -+ 0x1003, -+ 0x1004, -+ 0x1005, -+ 0x1006, -+ 0x1007, -+ 0x1707, -+ 0x2007, -+ 0x2d07, -+ 0x4007, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0200, -+ 0x0300, -+ 0x0400, -+ 0x0600, -+ 0x0800, -+ 0x0b00, -+ 0x1000, -+ 0x1001, -+ 0x1002, -+ 0x1003, -+ 0x1004, -+ 0x1005, -+ 0x1006, -+ 0x1007, -+ 0x1707, -+ 0x2007, -+ 0x2d07, -+ 0x4007, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x4000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+}; -+ -+static const u32 dot11lcn_papd_compdelta_tbl_rev0[] = { -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+ 0x00080000, -+}; -+ -+const struct phytbl_info dot11lcnphytbl_info_rev0[] = { -+ {&dot11lcn_min_sig_sq_tbl_rev0, -+ sizeof(dot11lcn_min_sig_sq_tbl_rev0) / -+ sizeof(dot11lcn_min_sig_sq_tbl_rev0[0]), 2, 0, 16} -+ , -+ {&dot11lcn_noise_scale_tbl_rev0, -+ sizeof(dot11lcn_noise_scale_tbl_rev0) / -+ sizeof(dot11lcn_noise_scale_tbl_rev0[0]), 1, 0, 16} -+ , -+ {&dot11lcn_fltr_ctrl_tbl_rev0, -+ sizeof(dot11lcn_fltr_ctrl_tbl_rev0) / -+ sizeof(dot11lcn_fltr_ctrl_tbl_rev0[0]), 11, 0, 32} -+ , -+ {&dot11lcn_ps_ctrl_tbl_rev0, -+ sizeof(dot11lcn_ps_ctrl_tbl_rev0) / -+ sizeof(dot11lcn_ps_ctrl_tbl_rev0[0]), 12, 0, 32} -+ , -+ {&dot11lcn_gain_idx_tbl_rev0, -+ sizeof(dot11lcn_gain_idx_tbl_rev0) / -+ sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32} -+ , -+ {&dot11lcn_aux_gain_idx_tbl_rev0, -+ sizeof(dot11lcn_aux_gain_idx_tbl_rev0) / -+ sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16} -+ , -+ {&dot11lcn_sw_ctrl_tbl_rev0, -+ sizeof(dot11lcn_sw_ctrl_tbl_rev0) / -+ sizeof(dot11lcn_sw_ctrl_tbl_rev0[0]), 15, 0, 16} -+ , -+ {&dot11lcn_nf_table_rev0, -+ sizeof(dot11lcn_nf_table_rev0) / sizeof(dot11lcn_nf_table_rev0[0]), 16, -+ 0, 8} -+ , -+ {&dot11lcn_gain_val_tbl_rev0, -+ sizeof(dot11lcn_gain_val_tbl_rev0) / -+ sizeof(dot11lcn_gain_val_tbl_rev0[0]), 17, 0, 8} -+ , -+ {&dot11lcn_gain_tbl_rev0, -+ sizeof(dot11lcn_gain_tbl_rev0) / sizeof(dot11lcn_gain_tbl_rev0[0]), 18, -+ 0, 32} -+ , -+ {&dot11lcn_spur_tbl_rev0, -+ sizeof(dot11lcn_spur_tbl_rev0) / sizeof(dot11lcn_spur_tbl_rev0[0]), 20, -+ 0, 8} -+ , -+ {&dot11lcn_unsup_mcs_tbl_rev0, -+ sizeof(dot11lcn_unsup_mcs_tbl_rev0) / -+ sizeof(dot11lcn_unsup_mcs_tbl_rev0[0]), 23, 0, 16} -+ , -+ {&dot11lcn_iq_local_tbl_rev0, -+ sizeof(dot11lcn_iq_local_tbl_rev0) / -+ sizeof(dot11lcn_iq_local_tbl_rev0[0]), 0, 0, 16} -+ , -+ {&dot11lcn_papd_compdelta_tbl_rev0, -+ sizeof(dot11lcn_papd_compdelta_tbl_rev0) / -+ sizeof(dot11lcn_papd_compdelta_tbl_rev0[0]), 24, 0, 32} -+ , -+}; -+ -+const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313 = { -+ &dot11lcn_sw_ctrl_tbl_4313_rev0, -+ sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0) / -+ sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0[0]), 15, 0, 16 -+}; -+ -+const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa = { -+ &dot11lcn_sw_ctrl_tbl_4313_epa_rev0, -+ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0) / -+ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0[0]), 15, 0, 16 -+}; -+ -+const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa = { -+ &dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo, -+ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo) / -+ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[0]), 15, 0, 16 -+}; -+ -+const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250 = { -+ &dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0, -+ sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0) / -+ sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[0]), 15, 0, 16 -+}; -+ -+const u32 dot11lcnphytbl_info_sz_rev0 = -+ sizeof(dot11lcnphytbl_info_rev0) / sizeof(dot11lcnphytbl_info_rev0[0]); -+ -+const struct lcnphy_tx_gain_tbl_entry -+dot11lcnphy_2GHz_extPA_gaintable_rev0[128] = { -+ {3, 0, 31, 0, 72}, -+ {3, 0, 31, 0, 70}, -+ {3, 0, 31, 0, 68}, -+ {3, 0, 30, 0, 67}, -+ {3, 0, 29, 0, 68}, -+ {3, 0, 28, 0, 68}, -+ {3, 0, 27, 0, 69}, -+ {3, 0, 26, 0, 70}, -+ {3, 0, 25, 0, 70}, -+ {3, 0, 24, 0, 71}, -+ {3, 0, 23, 0, 72}, -+ {3, 0, 23, 0, 70}, -+ {3, 0, 22, 0, 71}, -+ {3, 0, 21, 0, 72}, -+ {3, 0, 21, 0, 70}, -+ {3, 0, 21, 0, 68}, -+ {3, 0, 21, 0, 66}, -+ {3, 0, 21, 0, 64}, -+ {3, 0, 21, 0, 63}, -+ {3, 0, 20, 0, 64}, -+ {3, 0, 19, 0, 65}, -+ {3, 0, 19, 0, 64}, -+ {3, 0, 18, 0, 65}, -+ {3, 0, 18, 0, 64}, -+ {3, 0, 17, 0, 65}, -+ {3, 0, 17, 0, 64}, -+ {3, 0, 16, 0, 65}, -+ {3, 0, 16, 0, 64}, -+ {3, 0, 16, 0, 62}, -+ {3, 0, 16, 0, 60}, -+ {3, 0, 16, 0, 58}, -+ {3, 0, 15, 0, 61}, -+ {3, 0, 15, 0, 59}, -+ {3, 0, 14, 0, 61}, -+ {3, 0, 14, 0, 60}, -+ {3, 0, 14, 0, 58}, -+ {3, 0, 13, 0, 60}, -+ {3, 0, 13, 0, 59}, -+ {3, 0, 12, 0, 62}, -+ {3, 0, 12, 0, 60}, -+ {3, 0, 12, 0, 58}, -+ {3, 0, 11, 0, 62}, -+ {3, 0, 11, 0, 60}, -+ {3, 0, 11, 0, 59}, -+ {3, 0, 11, 0, 57}, -+ {3, 0, 10, 0, 61}, -+ {3, 0, 10, 0, 59}, -+ {3, 0, 10, 0, 57}, -+ {3, 0, 9, 0, 62}, -+ {3, 0, 9, 0, 60}, -+ {3, 0, 9, 0, 58}, -+ {3, 0, 9, 0, 57}, -+ {3, 0, 8, 0, 62}, -+ {3, 0, 8, 0, 60}, -+ {3, 0, 8, 0, 58}, -+ {3, 0, 8, 0, 57}, -+ {3, 0, 8, 0, 55}, -+ {3, 0, 7, 0, 61}, -+ {3, 0, 7, 0, 60}, -+ {3, 0, 7, 0, 58}, -+ {3, 0, 7, 0, 56}, -+ {3, 0, 7, 0, 55}, -+ {3, 0, 6, 0, 62}, -+ {3, 0, 6, 0, 60}, -+ {3, 0, 6, 0, 58}, -+ {3, 0, 6, 0, 57}, -+ {3, 0, 6, 0, 55}, -+ {3, 0, 6, 0, 54}, -+ {3, 0, 6, 0, 52}, -+ {3, 0, 5, 0, 61}, -+ {3, 0, 5, 0, 59}, -+ {3, 0, 5, 0, 57}, -+ {3, 0, 5, 0, 56}, -+ {3, 0, 5, 0, 54}, -+ {3, 0, 5, 0, 53}, -+ {3, 0, 5, 0, 51}, -+ {3, 0, 4, 0, 62}, -+ {3, 0, 4, 0, 60}, -+ {3, 0, 4, 0, 58}, -+ {3, 0, 4, 0, 57}, -+ {3, 0, 4, 0, 55}, -+ {3, 0, 4, 0, 54}, -+ {3, 0, 4, 0, 52}, -+ {3, 0, 4, 0, 51}, -+ {3, 0, 4, 0, 49}, -+ {3, 0, 4, 0, 48}, -+ {3, 0, 4, 0, 46}, -+ {3, 0, 3, 0, 60}, -+ {3, 0, 3, 0, 58}, -+ {3, 0, 3, 0, 57}, -+ {3, 0, 3, 0, 55}, -+ {3, 0, 3, 0, 54}, -+ {3, 0, 3, 0, 52}, -+ {3, 0, 3, 0, 51}, -+ {3, 0, 3, 0, 49}, -+ {3, 0, 3, 0, 48}, -+ {3, 0, 3, 0, 46}, -+ {3, 0, 3, 0, 45}, -+ {3, 0, 3, 0, 44}, -+ {3, 0, 3, 0, 43}, -+ {3, 0, 3, 0, 41}, -+ {3, 0, 2, 0, 61}, -+ {3, 0, 2, 0, 59}, -+ {3, 0, 2, 0, 57}, -+ {3, 0, 2, 0, 56}, -+ {3, 0, 2, 0, 54}, -+ {3, 0, 2, 0, 53}, -+ {3, 0, 2, 0, 51}, -+ {3, 0, 2, 0, 50}, -+ {3, 0, 2, 0, 48}, -+ {3, 0, 2, 0, 47}, -+ {3, 0, 2, 0, 46}, -+ {3, 0, 2, 0, 44}, -+ {3, 0, 2, 0, 43}, -+ {3, 0, 2, 0, 42}, -+ {3, 0, 2, 0, 41}, -+ {3, 0, 2, 0, 39}, -+ {3, 0, 2, 0, 38}, -+ {3, 0, 2, 0, 37}, -+ {3, 0, 2, 0, 36}, -+ {3, 0, 2, 0, 35}, -+ {3, 0, 2, 0, 34}, -+ {3, 0, 2, 0, 33}, -+ {3, 0, 2, 0, 32}, -+ {3, 0, 1, 0, 63}, -+ {3, 0, 1, 0, 61}, -+ {3, 0, 1, 0, 59}, -+ {3, 0, 1, 0, 57}, -+}; -+ -+const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[128] = { -+ {7, 0, 31, 0, 72}, -+ {7, 0, 31, 0, 70}, -+ {7, 0, 31, 0, 68}, -+ {7, 0, 30, 0, 67}, -+ {7, 0, 29, 0, 68}, -+ {7, 0, 28, 0, 68}, -+ {7, 0, 27, 0, 69}, -+ {7, 0, 26, 0, 70}, -+ {7, 0, 25, 0, 70}, -+ {7, 0, 24, 0, 71}, -+ {7, 0, 23, 0, 72}, -+ {7, 0, 23, 0, 70}, -+ {7, 0, 22, 0, 71}, -+ {7, 0, 21, 0, 72}, -+ {7, 0, 21, 0, 70}, -+ {7, 0, 21, 0, 68}, -+ {7, 0, 21, 0, 66}, -+ {7, 0, 21, 0, 64}, -+ {7, 0, 21, 0, 63}, -+ {7, 0, 20, 0, 64}, -+ {7, 0, 19, 0, 65}, -+ {7, 0, 19, 0, 64}, -+ {7, 0, 18, 0, 65}, -+ {7, 0, 18, 0, 64}, -+ {7, 0, 17, 0, 65}, -+ {7, 0, 17, 0, 64}, -+ {7, 0, 16, 0, 65}, -+ {7, 0, 16, 0, 64}, -+ {7, 0, 16, 0, 62}, -+ {7, 0, 16, 0, 60}, -+ {7, 0, 16, 0, 58}, -+ {7, 0, 15, 0, 61}, -+ {7, 0, 15, 0, 59}, -+ {7, 0, 14, 0, 61}, -+ {7, 0, 14, 0, 60}, -+ {7, 0, 14, 0, 58}, -+ {7, 0, 13, 0, 60}, -+ {7, 0, 13, 0, 59}, -+ {7, 0, 12, 0, 62}, -+ {7, 0, 12, 0, 60}, -+ {7, 0, 12, 0, 58}, -+ {7, 0, 11, 0, 62}, -+ {7, 0, 11, 0, 60}, -+ {7, 0, 11, 0, 59}, -+ {7, 0, 11, 0, 57}, -+ {7, 0, 10, 0, 61}, -+ {7, 0, 10, 0, 59}, -+ {7, 0, 10, 0, 57}, -+ {7, 0, 9, 0, 62}, -+ {7, 0, 9, 0, 60}, -+ {7, 0, 9, 0, 58}, -+ {7, 0, 9, 0, 57}, -+ {7, 0, 8, 0, 62}, -+ {7, 0, 8, 0, 60}, -+ {7, 0, 8, 0, 58}, -+ {7, 0, 8, 0, 57}, -+ {7, 0, 8, 0, 55}, -+ {7, 0, 7, 0, 61}, -+ {7, 0, 7, 0, 60}, -+ {7, 0, 7, 0, 58}, -+ {7, 0, 7, 0, 56}, -+ {7, 0, 7, 0, 55}, -+ {7, 0, 6, 0, 62}, -+ {7, 0, 6, 0, 60}, -+ {7, 0, 6, 0, 58}, -+ {7, 0, 6, 0, 57}, -+ {7, 0, 6, 0, 55}, -+ {7, 0, 6, 0, 54}, -+ {7, 0, 6, 0, 52}, -+ {7, 0, 5, 0, 61}, -+ {7, 0, 5, 0, 59}, -+ {7, 0, 5, 0, 57}, -+ {7, 0, 5, 0, 56}, -+ {7, 0, 5, 0, 54}, -+ {7, 0, 5, 0, 53}, -+ {7, 0, 5, 0, 51}, -+ {7, 0, 4, 0, 62}, -+ {7, 0, 4, 0, 60}, -+ {7, 0, 4, 0, 58}, -+ {7, 0, 4, 0, 57}, -+ {7, 0, 4, 0, 55}, -+ {7, 0, 4, 0, 54}, -+ {7, 0, 4, 0, 52}, -+ {7, 0, 4, 0, 51}, -+ {7, 0, 4, 0, 49}, -+ {7, 0, 4, 0, 48}, -+ {7, 0, 4, 0, 46}, -+ {7, 0, 3, 0, 60}, -+ {7, 0, 3, 0, 58}, -+ {7, 0, 3, 0, 57}, -+ {7, 0, 3, 0, 55}, -+ {7, 0, 3, 0, 54}, -+ {7, 0, 3, 0, 52}, -+ {7, 0, 3, 0, 51}, -+ {7, 0, 3, 0, 49}, -+ {7, 0, 3, 0, 48}, -+ {7, 0, 3, 0, 46}, -+ {7, 0, 3, 0, 45}, -+ {7, 0, 3, 0, 44}, -+ {7, 0, 3, 0, 43}, -+ {7, 0, 3, 0, 41}, -+ {7, 0, 2, 0, 61}, -+ {7, 0, 2, 0, 59}, -+ {7, 0, 2, 0, 57}, -+ {7, 0, 2, 0, 56}, -+ {7, 0, 2, 0, 54}, -+ {7, 0, 2, 0, 53}, -+ {7, 0, 2, 0, 51}, -+ {7, 0, 2, 0, 50}, -+ {7, 0, 2, 0, 48}, -+ {7, 0, 2, 0, 47}, -+ {7, 0, 2, 0, 46}, -+ {7, 0, 2, 0, 44}, -+ {7, 0, 2, 0, 43}, -+ {7, 0, 2, 0, 42}, -+ {7, 0, 2, 0, 41}, -+ {7, 0, 2, 0, 39}, -+ {7, 0, 2, 0, 38}, -+ {7, 0, 2, 0, 37}, -+ {7, 0, 2, 0, 36}, -+ {7, 0, 2, 0, 35}, -+ {7, 0, 2, 0, 34}, -+ {7, 0, 2, 0, 33}, -+ {7, 0, 2, 0, 32}, -+ {7, 0, 1, 0, 63}, -+ {7, 0, 1, 0, 61}, -+ {7, 0, 1, 0, 59}, -+ {7, 0, 1, 0, 57}, -+}; -+ -+const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[128] = { -+ {255, 255, 0xf0, 0, 152}, -+ {255, 255, 0xf0, 0, 147}, -+ {255, 255, 0xf0, 0, 143}, -+ {255, 255, 0xf0, 0, 139}, -+ {255, 255, 0xf0, 0, 135}, -+ {255, 255, 0xf0, 0, 131}, -+ {255, 255, 0xf0, 0, 128}, -+ {255, 255, 0xf0, 0, 124}, -+ {255, 255, 0xf0, 0, 121}, -+ {255, 255, 0xf0, 0, 117}, -+ {255, 255, 0xf0, 0, 114}, -+ {255, 255, 0xf0, 0, 111}, -+ {255, 255, 0xf0, 0, 107}, -+ {255, 255, 0xf0, 0, 104}, -+ {255, 255, 0xf0, 0, 101}, -+ {255, 255, 0xf0, 0, 99}, -+ {255, 255, 0xf0, 0, 96}, -+ {255, 255, 0xf0, 0, 93}, -+ {255, 255, 0xf0, 0, 90}, -+ {255, 255, 0xf0, 0, 88}, -+ {255, 255, 0xf0, 0, 85}, -+ {255, 255, 0xf0, 0, 83}, -+ {255, 255, 0xf0, 0, 81}, -+ {255, 255, 0xf0, 0, 78}, -+ {255, 255, 0xf0, 0, 76}, -+ {255, 255, 0xf0, 0, 74}, -+ {255, 255, 0xf0, 0, 72}, -+ {255, 255, 0xf0, 0, 70}, -+ {255, 255, 0xf0, 0, 68}, -+ {255, 255, 0xf0, 0, 66}, -+ {255, 255, 0xf0, 0, 64}, -+ {255, 248, 0xf0, 0, 64}, -+ {255, 241, 0xf0, 0, 64}, -+ {255, 251, 0xe0, 0, 64}, -+ {255, 244, 0xe0, 0, 64}, -+ {255, 254, 0xd0, 0, 64}, -+ {255, 246, 0xd0, 0, 64}, -+ {255, 239, 0xd0, 0, 64}, -+ {255, 249, 0xc0, 0, 64}, -+ {255, 242, 0xc0, 0, 64}, -+ {255, 255, 0xb0, 0, 64}, -+ {255, 248, 0xb0, 0, 64}, -+ {255, 241, 0xb0, 0, 64}, -+ {255, 254, 0xa0, 0, 64}, -+ {255, 246, 0xa0, 0, 64}, -+ {255, 239, 0xa0, 0, 64}, -+ {255, 255, 0x90, 0, 64}, -+ {255, 248, 0x90, 0, 64}, -+ {255, 241, 0x90, 0, 64}, -+ {255, 234, 0x90, 0, 64}, -+ {255, 255, 0x80, 0, 64}, -+ {255, 248, 0x80, 0, 64}, -+ {255, 241, 0x80, 0, 64}, -+ {255, 234, 0x80, 0, 64}, -+ {255, 255, 0x70, 0, 64}, -+ {255, 248, 0x70, 0, 64}, -+ {255, 241, 0x70, 0, 64}, -+ {255, 234, 0x70, 0, 64}, -+ {255, 227, 0x70, 0, 64}, -+ {255, 221, 0x70, 0, 64}, -+ {255, 215, 0x70, 0, 64}, -+ {255, 208, 0x70, 0, 64}, -+ {255, 203, 0x70, 0, 64}, -+ {255, 197, 0x70, 0, 64}, -+ {255, 255, 0x60, 0, 64}, -+ {255, 248, 0x60, 0, 64}, -+ {255, 241, 0x60, 0, 64}, -+ {255, 234, 0x60, 0, 64}, -+ {255, 227, 0x60, 0, 64}, -+ {255, 221, 0x60, 0, 64}, -+ {255, 255, 0x50, 0, 64}, -+ {255, 248, 0x50, 0, 64}, -+ {255, 241, 0x50, 0, 64}, -+ {255, 234, 0x50, 0, 64}, -+ {255, 227, 0x50, 0, 64}, -+ {255, 221, 0x50, 0, 64}, -+ {255, 215, 0x50, 0, 64}, -+ {255, 208, 0x50, 0, 64}, -+ {255, 255, 0x40, 0, 64}, -+ {255, 248, 0x40, 0, 64}, -+ {255, 241, 0x40, 0, 64}, -+ {255, 234, 0x40, 0, 64}, -+ {255, 227, 0x40, 0, 64}, -+ {255, 221, 0x40, 0, 64}, -+ {255, 215, 0x40, 0, 64}, -+ {255, 208, 0x40, 0, 64}, -+ {255, 203, 0x40, 0, 64}, -+ {255, 197, 0x40, 0, 64}, -+ {255, 255, 0x30, 0, 64}, -+ {255, 248, 0x30, 0, 64}, -+ {255, 241, 0x30, 0, 64}, -+ {255, 234, 0x30, 0, 64}, -+ {255, 227, 0x30, 0, 64}, -+ {255, 221, 0x30, 0, 64}, -+ {255, 215, 0x30, 0, 64}, -+ {255, 208, 0x30, 0, 64}, -+ {255, 203, 0x30, 0, 64}, -+ {255, 197, 0x30, 0, 64}, -+ {255, 191, 0x30, 0, 64}, -+ {255, 186, 0x30, 0, 64}, -+ {255, 181, 0x30, 0, 64}, -+ {255, 175, 0x30, 0, 64}, -+ {255, 255, 0x20, 0, 64}, -+ {255, 248, 0x20, 0, 64}, -+ {255, 241, 0x20, 0, 64}, -+ {255, 234, 0x20, 0, 64}, -+ {255, 227, 0x20, 0, 64}, -+ {255, 221, 0x20, 0, 64}, -+ {255, 215, 0x20, 0, 64}, -+ {255, 208, 0x20, 0, 64}, -+ {255, 203, 0x20, 0, 64}, -+ {255, 197, 0x20, 0, 64}, -+ {255, 191, 0x20, 0, 64}, -+ {255, 186, 0x20, 0, 64}, -+ {255, 181, 0x20, 0, 64}, -+ {255, 175, 0x20, 0, 64}, -+ {255, 170, 0x20, 0, 64}, -+ {255, 166, 0x20, 0, 64}, -+ {255, 161, 0x20, 0, 64}, -+ {255, 156, 0x20, 0, 64}, -+ {255, 152, 0x20, 0, 64}, -+ {255, 148, 0x20, 0, 64}, -+ {255, 143, 0x20, 0, 64}, -+ {255, 139, 0x20, 0, 64}, -+ {255, 135, 0x20, 0, 64}, -+ {255, 132, 0x20, 0, 64}, -+ {255, 255, 0x10, 0, 64}, -+ {255, 248, 0x10, 0, 64}, -+}; -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h.orig 2011-11-09 13:46:58.278800221 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h 2011-11-09 13:47:17.036565717 -0500 -@@ -0,0 +1,54 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include "phy_int.h" -+ -+extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev0[]; -+extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev0; -+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313; -+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa; -+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa_combo; -+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa; -+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250; -+ -+extern const struct phytbl_info dot11lcnphytbl_info_rev0[]; -+extern const u32 dot11lcnphytbl_info_sz_rev0; -+ -+extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_2G_rev2[]; -+extern const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz; -+ -+extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_5G_rev2[]; -+extern const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz; -+ -+extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[]; -+ -+extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[]; -+ -+struct lcnphy_tx_gain_tbl_entry { -+ unsigned char gm; -+ unsigned char pga; -+ unsigned char pad; -+ unsigned char dac; -+ unsigned char bb_mult; -+}; -+ -+extern const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[]; -+ -+extern const struct -+lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_extPA_gaintable_rev0[]; -+ -+extern const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[]; -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.c.orig 2011-11-09 13:46:58.282800170 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.c 2011-11-09 13:47:17.040565666 -0500 -@@ -0,0 +1,10630 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include "phytbl_n.h" -+ -+static const u32 frame_struct_rev0[] = { -+ 0x08004a04, -+ 0x00100000, -+ 0x01000a05, -+ 0x00100020, -+ 0x09804506, -+ 0x00100030, -+ 0x09804507, -+ 0x00100030, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x08004a0c, -+ 0x00100004, -+ 0x01000a0d, -+ 0x00100024, -+ 0x0980450e, -+ 0x00100034, -+ 0x0980450f, -+ 0x00100034, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000a04, -+ 0x00100000, -+ 0x11008a05, -+ 0x00100020, -+ 0x1980c506, -+ 0x00100030, -+ 0x21810506, -+ 0x00100030, -+ 0x21810506, -+ 0x00100030, -+ 0x01800504, -+ 0x00100030, -+ 0x11808505, -+ 0x00100030, -+ 0x29814507, -+ 0x01100030, -+ 0x00000a04, -+ 0x00100000, -+ 0x11008a05, -+ 0x00100020, -+ 0x21810506, -+ 0x00100030, -+ 0x21810506, -+ 0x00100030, -+ 0x29814507, -+ 0x01100030, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000a0c, -+ 0x00100008, -+ 0x11008a0d, -+ 0x00100028, -+ 0x1980c50e, -+ 0x00100038, -+ 0x2181050e, -+ 0x00100038, -+ 0x2181050e, -+ 0x00100038, -+ 0x0180050c, -+ 0x00100038, -+ 0x1180850d, -+ 0x00100038, -+ 0x2981450f, -+ 0x01100038, -+ 0x00000a0c, -+ 0x00100008, -+ 0x11008a0d, -+ 0x00100028, -+ 0x2181050e, -+ 0x00100038, -+ 0x2181050e, -+ 0x00100038, -+ 0x2981450f, -+ 0x01100038, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x08004a04, -+ 0x00100000, -+ 0x01000a05, -+ 0x00100020, -+ 0x1980c506, -+ 0x00100030, -+ 0x1980c506, -+ 0x00100030, -+ 0x11808504, -+ 0x00100030, -+ 0x3981ca05, -+ 0x00100030, -+ 0x29814507, -+ 0x01100030, -+ 0x00000000, -+ 0x00000000, -+ 0x10008a04, -+ 0x00100000, -+ 0x3981ca05, -+ 0x00100030, -+ 0x1980c506, -+ 0x00100030, -+ 0x29814507, -+ 0x01100030, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x08004a0c, -+ 0x00100008, -+ 0x01000a0d, -+ 0x00100028, -+ 0x1980c50e, -+ 0x00100038, -+ 0x1980c50e, -+ 0x00100038, -+ 0x1180850c, -+ 0x00100038, -+ 0x3981ca0d, -+ 0x00100038, -+ 0x2981450f, -+ 0x01100038, -+ 0x00000000, -+ 0x00000000, -+ 0x10008a0c, -+ 0x00100008, -+ 0x3981ca0d, -+ 0x00100038, -+ 0x1980c50e, -+ 0x00100038, -+ 0x2981450f, -+ 0x01100038, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x40021404, -+ 0x00100000, -+ 0x02001405, -+ 0x00100040, -+ 0x0b004a06, -+ 0x01900060, -+ 0x13008a06, -+ 0x01900060, -+ 0x13008a06, -+ 0x01900060, -+ 0x43020a04, -+ 0x00100060, -+ 0x1b00ca05, -+ 0x00100060, -+ 0x23010a07, -+ 0x01500060, -+ 0x40021404, -+ 0x00100000, -+ 0x1a00d405, -+ 0x00100040, -+ 0x13008a06, -+ 0x01900060, -+ 0x13008a06, -+ 0x01900060, -+ 0x23010a07, -+ 0x01500060, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x4002140c, -+ 0x00100010, -+ 0x0200140d, -+ 0x00100050, -+ 0x0b004a0e, -+ 0x01900070, -+ 0x13008a0e, -+ 0x01900070, -+ 0x13008a0e, -+ 0x01900070, -+ 0x43020a0c, -+ 0x00100070, -+ 0x1b00ca0d, -+ 0x00100070, -+ 0x23010a0f, -+ 0x01500070, -+ 0x4002140c, -+ 0x00100010, -+ 0x1a00d40d, -+ 0x00100050, -+ 0x13008a0e, -+ 0x01900070, -+ 0x13008a0e, -+ 0x01900070, -+ 0x23010a0f, -+ 0x01500070, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x50029404, -+ 0x00100000, -+ 0x32019405, -+ 0x00100040, -+ 0x0b004a06, -+ 0x01900060, -+ 0x0b004a06, -+ 0x01900060, -+ 0x5b02ca04, -+ 0x00100060, -+ 0x3b01d405, -+ 0x00100060, -+ 0x23010a07, -+ 0x01500060, -+ 0x00000000, -+ 0x00000000, -+ 0x5802d404, -+ 0x00100000, -+ 0x3b01d405, -+ 0x00100060, -+ 0x0b004a06, -+ 0x01900060, -+ 0x23010a07, -+ 0x01500060, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x5002940c, -+ 0x00100010, -+ 0x3201940d, -+ 0x00100050, -+ 0x0b004a0e, -+ 0x01900070, -+ 0x0b004a0e, -+ 0x01900070, -+ 0x5b02ca0c, -+ 0x00100070, -+ 0x3b01d40d, -+ 0x00100070, -+ 0x23010a0f, -+ 0x01500070, -+ 0x00000000, -+ 0x00000000, -+ 0x5802d40c, -+ 0x00100010, -+ 0x3b01d40d, -+ 0x00100070, -+ 0x0b004a0e, -+ 0x01900070, -+ 0x23010a0f, -+ 0x01500070, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x40021404, -+ 0x000f4800, -+ 0x62031405, -+ 0x00100040, -+ 0x53028a06, -+ 0x01900060, -+ 0x53028a07, -+ 0x01900060, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x4002140c, -+ 0x000f4808, -+ 0x6203140d, -+ 0x00100048, -+ 0x53028a0e, -+ 0x01900068, -+ 0x53028a0f, -+ 0x01900068, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000a0c, -+ 0x00100004, -+ 0x11008a0d, -+ 0x00100024, -+ 0x1980c50e, -+ 0x00100034, -+ 0x2181050e, -+ 0x00100034, -+ 0x2181050e, -+ 0x00100034, -+ 0x0180050c, -+ 0x00100038, -+ 0x1180850d, -+ 0x00100038, -+ 0x1181850d, -+ 0x00100038, -+ 0x2981450f, -+ 0x01100038, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000a0c, -+ 0x00100008, -+ 0x11008a0d, -+ 0x00100028, -+ 0x2181050e, -+ 0x00100038, -+ 0x2181050e, -+ 0x00100038, -+ 0x1181850d, -+ 0x00100038, -+ 0x2981450f, -+ 0x01100038, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x08004a04, -+ 0x00100000, -+ 0x01000a05, -+ 0x00100020, -+ 0x0180c506, -+ 0x00100030, -+ 0x0180c506, -+ 0x00100030, -+ 0x2180c50c, -+ 0x00100030, -+ 0x49820a0d, -+ 0x0016a130, -+ 0x41824a0d, -+ 0x0016a130, -+ 0x2981450f, -+ 0x01100030, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x2000ca0c, -+ 0x00100000, -+ 0x49820a0d, -+ 0x0016a130, -+ 0x1980c50e, -+ 0x00100030, -+ 0x41824a0d, -+ 0x0016a130, -+ 0x2981450f, -+ 0x01100030, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x4002140c, -+ 0x00100008, -+ 0x0200140d, -+ 0x00100048, -+ 0x0b004a0e, -+ 0x01900068, -+ 0x13008a0e, -+ 0x01900068, -+ 0x13008a0e, -+ 0x01900068, -+ 0x43020a0c, -+ 0x00100070, -+ 0x1b00ca0d, -+ 0x00100070, -+ 0x1b014a0d, -+ 0x00100070, -+ 0x23010a0f, -+ 0x01500070, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x4002140c, -+ 0x00100010, -+ 0x1a00d40d, -+ 0x00100050, -+ 0x13008a0e, -+ 0x01900070, -+ 0x13008a0e, -+ 0x01900070, -+ 0x1b014a0d, -+ 0x00100070, -+ 0x23010a0f, -+ 0x01500070, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x50029404, -+ 0x00100000, -+ 0x32019405, -+ 0x00100040, -+ 0x03004a06, -+ 0x01900060, -+ 0x03004a06, -+ 0x01900060, -+ 0x6b030a0c, -+ 0x00100060, -+ 0x4b02140d, -+ 0x0016a160, -+ 0x4302540d, -+ 0x0016a160, -+ 0x23010a0f, -+ 0x01500060, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x6b03140c, -+ 0x00100060, -+ 0x4b02140d, -+ 0x0016a160, -+ 0x0b004a0e, -+ 0x01900060, -+ 0x4302540d, -+ 0x0016a160, -+ 0x23010a0f, -+ 0x01500060, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x40021404, -+ 0x00100000, -+ 0x1a00d405, -+ 0x00100040, -+ 0x53028a06, -+ 0x01900060, -+ 0x5b02ca06, -+ 0x01900060, -+ 0x5b02ca06, -+ 0x01900060, -+ 0x43020a04, -+ 0x00100060, -+ 0x1b00ca05, -+ 0x00100060, -+ 0x53028a07, -+ 0x0190c060, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x4002140c, -+ 0x00100010, -+ 0x1a00d40d, -+ 0x00100050, -+ 0x53028a0e, -+ 0x01900070, -+ 0x5b02ca0e, -+ 0x01900070, -+ 0x5b02ca0e, -+ 0x01900070, -+ 0x43020a0c, -+ 0x00100070, -+ 0x1b00ca0d, -+ 0x00100070, -+ 0x53028a0f, -+ 0x0190c070, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x40021404, -+ 0x00100000, -+ 0x1a00d405, -+ 0x00100040, -+ 0x5b02ca06, -+ 0x01900060, -+ 0x5b02ca06, -+ 0x01900060, -+ 0x53028a07, -+ 0x0190c060, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x4002140c, -+ 0x00100010, -+ 0x1a00d40d, -+ 0x00100050, -+ 0x5b02ca0e, -+ 0x01900070, -+ 0x5b02ca0e, -+ 0x01900070, -+ 0x53028a0f, -+ 0x0190c070, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+static const u8 frame_lut_rev0[] = { -+ 0x02, -+ 0x04, -+ 0x14, -+ 0x14, -+ 0x03, -+ 0x05, -+ 0x16, -+ 0x16, -+ 0x0a, -+ 0x0c, -+ 0x1c, -+ 0x1c, -+ 0x0b, -+ 0x0d, -+ 0x1e, -+ 0x1e, -+ 0x06, -+ 0x08, -+ 0x18, -+ 0x18, -+ 0x07, -+ 0x09, -+ 0x1a, -+ 0x1a, -+ 0x0e, -+ 0x10, -+ 0x20, -+ 0x28, -+ 0x0f, -+ 0x11, -+ 0x22, -+ 0x2a, -+}; -+ -+static const u32 tmap_tbl_rev0[] = { -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0xf1111110, -+ 0x11111111, -+ 0x11f11111, -+ 0x00000111, -+ 0x11000000, -+ 0x1111f111, -+ 0x11111111, -+ 0x111111f1, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x000aa888, -+ 0x88880000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0xa1111110, -+ 0x11111111, -+ 0x11c11111, -+ 0x00000111, -+ 0x11000000, -+ 0x1111a111, -+ 0x11111111, -+ 0x111111a1, -+ 0xa2222220, -+ 0x22222222, -+ 0x22c22222, -+ 0x00000222, -+ 0x22000000, -+ 0x2222a222, -+ 0x22222222, -+ 0x222222a2, -+ 0xf1111110, -+ 0x11111111, -+ 0x11f11111, -+ 0x00011111, -+ 0x11110000, -+ 0x1111f111, -+ 0x11111111, -+ 0x111111f1, -+ 0xa8aa88a0, -+ 0xa88888a8, -+ 0xa8a8a88a, -+ 0x00088aaa, -+ 0xaaaa0000, -+ 0xa8a8aa88, -+ 0xa88aaaaa, -+ 0xaaaa8a8a, -+ 0xaaa8aaa0, -+ 0x8aaa8aaa, -+ 0xaa8a8a8a, -+ 0x000aaa88, -+ 0x8aaa0000, -+ 0xaaa8a888, -+ 0x8aa88a8a, -+ 0x8a88a888, -+ 0x08080a00, -+ 0x0a08080a, -+ 0x080a0a08, -+ 0x00080808, -+ 0x080a0000, -+ 0x080a0808, -+ 0x080a0808, -+ 0x0a0a0a08, -+ 0xa0a0a0a0, -+ 0x80a0a080, -+ 0x8080a0a0, -+ 0x00008080, -+ 0x80a00000, -+ 0x80a080a0, -+ 0xa080a0a0, -+ 0x8080a0a0, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x99999000, -+ 0x9b9b99bb, -+ 0x9bb99999, -+ 0x9999b9b9, -+ 0x9b99bb90, -+ 0x9bbbbb9b, -+ 0x9b9b9bb9, -+ 0x00000999, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00aaa888, -+ 0x22000000, -+ 0x2222b222, -+ 0x22222222, -+ 0x222222b2, -+ 0xb2222220, -+ 0x22222222, -+ 0x22d22222, -+ 0x00000222, -+ 0x11000000, -+ 0x1111a111, -+ 0x11111111, -+ 0x111111a1, -+ 0xa1111110, -+ 0x11111111, -+ 0x11c11111, -+ 0x00000111, -+ 0x33000000, -+ 0x3333b333, -+ 0x33333333, -+ 0x333333b3, -+ 0xb3333330, -+ 0x33333333, -+ 0x33d33333, -+ 0x00000333, -+ 0x22000000, -+ 0x2222a222, -+ 0x22222222, -+ 0x222222a2, -+ 0xa2222220, -+ 0x22222222, -+ 0x22c22222, -+ 0x00000222, -+ 0x99b99b00, -+ 0x9b9b99bb, -+ 0x9bb99999, -+ 0x9999b9b9, -+ 0x9b99bb99, -+ 0x9bbbbb9b, -+ 0x9b9b9bb9, -+ 0x00000999, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa88, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x08aaa888, -+ 0x22222200, -+ 0x2222f222, -+ 0x22222222, -+ 0x222222f2, -+ 0x22222222, -+ 0x22222222, -+ 0x22f22222, -+ 0x00000222, -+ 0x11000000, -+ 0x1111f111, -+ 0x11111111, -+ 0x11111111, -+ 0xf1111111, -+ 0x11111111, -+ 0x11f11111, -+ 0x01111111, -+ 0xbb9bb900, -+ 0xb9b9bb99, -+ 0xb99bbbbb, -+ 0xbbbb9b9b, -+ 0xb9bb99bb, -+ 0xb99999b9, -+ 0xb9b9b99b, -+ 0x00000bbb, -+ 0xaa000000, -+ 0xa8a8aa88, -+ 0xa88aaaaa, -+ 0xaaaa8a8a, -+ 0xa8aa88aa, -+ 0xa88888a8, -+ 0xa8a8a88a, -+ 0x0a888aaa, -+ 0xaa000000, -+ 0xa8a8aa88, -+ 0xa88aaaaa, -+ 0xaaaa8a8a, -+ 0xa8aa88a0, -+ 0xa88888a8, -+ 0xa8a8a88a, -+ 0x00000aaa, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0xbbbbbb00, -+ 0x999bbbbb, -+ 0x9bb99b9b, -+ 0xb9b9b9bb, -+ 0xb9b99bbb, -+ 0xb9b9b9bb, -+ 0xb9bb9b99, -+ 0x00000999, -+ 0x8a000000, -+ 0xaa88a888, -+ 0xa88888aa, -+ 0xa88a8a88, -+ 0xa88aa88a, -+ 0x88a8aaaa, -+ 0xa8aa8aaa, -+ 0x0888a88a, -+ 0x0b0b0b00, -+ 0x090b0b0b, -+ 0x0b090b0b, -+ 0x0909090b, -+ 0x09090b0b, -+ 0x09090b0b, -+ 0x09090b09, -+ 0x00000909, -+ 0x0a000000, -+ 0x0a080808, -+ 0x080a080a, -+ 0x080a0a08, -+ 0x080a080a, -+ 0x0808080a, -+ 0x0a0a0a08, -+ 0x0808080a, -+ 0xb0b0b000, -+ 0x9090b0b0, -+ 0x90b09090, -+ 0xb0b0b090, -+ 0xb0b090b0, -+ 0x90b0b0b0, -+ 0xb0b09090, -+ 0x00000090, -+ 0x80000000, -+ 0xa080a080, -+ 0xa08080a0, -+ 0xa0808080, -+ 0xa080a080, -+ 0x80a0a0a0, -+ 0xa0a080a0, -+ 0x00a0a0a0, -+ 0x22000000, -+ 0x2222f222, -+ 0x22222222, -+ 0x222222f2, -+ 0xf2222220, -+ 0x22222222, -+ 0x22f22222, -+ 0x00000222, -+ 0x11000000, -+ 0x1111f111, -+ 0x11111111, -+ 0x111111f1, -+ 0xf1111110, -+ 0x11111111, -+ 0x11f11111, -+ 0x00000111, -+ 0x33000000, -+ 0x3333f333, -+ 0x33333333, -+ 0x333333f3, -+ 0xf3333330, -+ 0x33333333, -+ 0x33f33333, -+ 0x00000333, -+ 0x22000000, -+ 0x2222f222, -+ 0x22222222, -+ 0x222222f2, -+ 0xf2222220, -+ 0x22222222, -+ 0x22f22222, -+ 0x00000222, -+ 0x99000000, -+ 0x9b9b99bb, -+ 0x9bb99999, -+ 0x9999b9b9, -+ 0x9b99bb90, -+ 0x9bbbbb9b, -+ 0x9b9b9bb9, -+ 0x00000999, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x88888000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00aaa888, -+ 0x88a88a00, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa88, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa88, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x08aaa888, -+ 0x11000000, -+ 0x1111a111, -+ 0x11111111, -+ 0x111111a1, -+ 0xa1111110, -+ 0x11111111, -+ 0x11c11111, -+ 0x00000111, -+ 0x11000000, -+ 0x1111a111, -+ 0x11111111, -+ 0x111111a1, -+ 0xa1111110, -+ 0x11111111, -+ 0x11c11111, -+ 0x00000111, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+static const u32 tdtrn_tbl_rev0[] = { -+ 0x061c061c, -+ 0x0050ee68, -+ 0xf592fe36, -+ 0xfe5212f6, -+ 0x00000c38, -+ 0xfe5212f6, -+ 0xf592fe36, -+ 0x0050ee68, -+ 0x061c061c, -+ 0xee680050, -+ 0xfe36f592, -+ 0x12f6fe52, -+ 0x0c380000, -+ 0x12f6fe52, -+ 0xfe36f592, -+ 0xee680050, -+ 0x061c061c, -+ 0x0050ee68, -+ 0xf592fe36, -+ 0xfe5212f6, -+ 0x00000c38, -+ 0xfe5212f6, -+ 0xf592fe36, -+ 0x0050ee68, -+ 0x061c061c, -+ 0xee680050, -+ 0xfe36f592, -+ 0x12f6fe52, -+ 0x0c380000, -+ 0x12f6fe52, -+ 0xfe36f592, -+ 0xee680050, -+ 0x05e305e3, -+ 0x004def0c, -+ 0xf5f3fe47, -+ 0xfe611246, -+ 0x00000bc7, -+ 0xfe611246, -+ 0xf5f3fe47, -+ 0x004def0c, -+ 0x05e305e3, -+ 0xef0c004d, -+ 0xfe47f5f3, -+ 0x1246fe61, -+ 0x0bc70000, -+ 0x1246fe61, -+ 0xfe47f5f3, -+ 0xef0c004d, -+ 0x05e305e3, -+ 0x004def0c, -+ 0xf5f3fe47, -+ 0xfe611246, -+ 0x00000bc7, -+ 0xfe611246, -+ 0xf5f3fe47, -+ 0x004def0c, -+ 0x05e305e3, -+ 0xef0c004d, -+ 0xfe47f5f3, -+ 0x1246fe61, -+ 0x0bc70000, -+ 0x1246fe61, -+ 0xfe47f5f3, -+ 0xef0c004d, -+ 0xfa58fa58, -+ 0xf895043b, -+ 0xff4c09c0, -+ 0xfbc6ffa8, -+ 0xfb84f384, -+ 0x0798f6f9, -+ 0x05760122, -+ 0x058409f6, -+ 0x0b500000, -+ 0x05b7f542, -+ 0x08860432, -+ 0x06ddfee7, -+ 0xfb84f384, -+ 0xf9d90664, -+ 0xf7e8025c, -+ 0x00fff7bd, -+ 0x05a805a8, -+ 0xf7bd00ff, -+ 0x025cf7e8, -+ 0x0664f9d9, -+ 0xf384fb84, -+ 0xfee706dd, -+ 0x04320886, -+ 0xf54205b7, -+ 0x00000b50, -+ 0x09f60584, -+ 0x01220576, -+ 0xf6f90798, -+ 0xf384fb84, -+ 0xffa8fbc6, -+ 0x09c0ff4c, -+ 0x043bf895, -+ 0x02d402d4, -+ 0x07de0270, -+ 0xfc96079c, -+ 0xf90afe94, -+ 0xfe00ff2c, -+ 0x02d4065d, -+ 0x092a0096, -+ 0x0014fbb8, -+ 0xfd2cfd2c, -+ 0x076afb3c, -+ 0x0096f752, -+ 0xf991fd87, -+ 0xfb2c0200, -+ 0xfeb8f960, -+ 0x08e0fc96, -+ 0x049802a8, -+ 0xfd2cfd2c, -+ 0x02a80498, -+ 0xfc9608e0, -+ 0xf960feb8, -+ 0x0200fb2c, -+ 0xfd87f991, -+ 0xf7520096, -+ 0xfb3c076a, -+ 0xfd2cfd2c, -+ 0xfbb80014, -+ 0x0096092a, -+ 0x065d02d4, -+ 0xff2cfe00, -+ 0xfe94f90a, -+ 0x079cfc96, -+ 0x027007de, -+ 0x02d402d4, -+ 0x027007de, -+ 0x079cfc96, -+ 0xfe94f90a, -+ 0xff2cfe00, -+ 0x065d02d4, -+ 0x0096092a, -+ 0xfbb80014, -+ 0xfd2cfd2c, -+ 0xfb3c076a, -+ 0xf7520096, -+ 0xfd87f991, -+ 0x0200fb2c, -+ 0xf960feb8, -+ 0xfc9608e0, -+ 0x02a80498, -+ 0xfd2cfd2c, -+ 0x049802a8, -+ 0x08e0fc96, -+ 0xfeb8f960, -+ 0xfb2c0200, -+ 0xf991fd87, -+ 0x0096f752, -+ 0x076afb3c, -+ 0xfd2cfd2c, -+ 0x0014fbb8, -+ 0x092a0096, -+ 0x02d4065d, -+ 0xfe00ff2c, -+ 0xf90afe94, -+ 0xfc96079c, -+ 0x07de0270, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x062a0000, -+ 0xfefa0759, -+ 0x08b80908, -+ 0xf396fc2d, -+ 0xf9d6045c, -+ 0xfc4ef608, -+ 0xf748f596, -+ 0x07b207bf, -+ 0x062a062a, -+ 0xf84ef841, -+ 0xf748f596, -+ 0x03b209f8, -+ 0xf9d6045c, -+ 0x0c6a03d3, -+ 0x08b80908, -+ 0x0106f8a7, -+ 0x062a0000, -+ 0xfefaf8a7, -+ 0x08b8f6f8, -+ 0xf39603d3, -+ 0xf9d6fba4, -+ 0xfc4e09f8, -+ 0xf7480a6a, -+ 0x07b2f841, -+ 0x062af9d6, -+ 0xf84e07bf, -+ 0xf7480a6a, -+ 0x03b2f608, -+ 0xf9d6fba4, -+ 0x0c6afc2d, -+ 0x08b8f6f8, -+ 0x01060759, -+ 0x062a0000, -+ 0xfefa0759, -+ 0x08b80908, -+ 0xf396fc2d, -+ 0xf9d6045c, -+ 0xfc4ef608, -+ 0xf748f596, -+ 0x07b207bf, -+ 0x062a062a, -+ 0xf84ef841, -+ 0xf748f596, -+ 0x03b209f8, -+ 0xf9d6045c, -+ 0x0c6a03d3, -+ 0x08b80908, -+ 0x0106f8a7, -+ 0x062a0000, -+ 0xfefaf8a7, -+ 0x08b8f6f8, -+ 0xf39603d3, -+ 0xf9d6fba4, -+ 0xfc4e09f8, -+ 0xf7480a6a, -+ 0x07b2f841, -+ 0x062af9d6, -+ 0xf84e07bf, -+ 0xf7480a6a, -+ 0x03b2f608, -+ 0xf9d6fba4, -+ 0x0c6afc2d, -+ 0x08b8f6f8, -+ 0x01060759, -+ 0x061c061c, -+ 0xff30009d, -+ 0xffb21141, -+ 0xfd87fb54, -+ 0xf65dfe59, -+ 0x02eef99e, -+ 0x0166f03c, -+ 0xfff809b6, -+ 0x000008a4, -+ 0x000af42b, -+ 0x00eff577, -+ 0xfa840bf2, -+ 0xfc02ff51, -+ 0x08260f67, -+ 0xfff0036f, -+ 0x0842f9c3, -+ 0x00000000, -+ 0x063df7be, -+ 0xfc910010, -+ 0xf099f7da, -+ 0x00af03fe, -+ 0xf40e057c, -+ 0x0a89ff11, -+ 0x0bd5fff6, -+ 0xf75c0000, -+ 0xf64a0008, -+ 0x0fc4fe9a, -+ 0x0662fd12, -+ 0x01a709a3, -+ 0x04ac0279, -+ 0xeebf004e, -+ 0xff6300d0, -+ 0xf9e4f9e4, -+ 0x00d0ff63, -+ 0x004eeebf, -+ 0x027904ac, -+ 0x09a301a7, -+ 0xfd120662, -+ 0xfe9a0fc4, -+ 0x0008f64a, -+ 0x0000f75c, -+ 0xfff60bd5, -+ 0xff110a89, -+ 0x057cf40e, -+ 0x03fe00af, -+ 0xf7daf099, -+ 0x0010fc91, -+ 0xf7be063d, -+ 0x00000000, -+ 0xf9c30842, -+ 0x036ffff0, -+ 0x0f670826, -+ 0xff51fc02, -+ 0x0bf2fa84, -+ 0xf57700ef, -+ 0xf42b000a, -+ 0x08a40000, -+ 0x09b6fff8, -+ 0xf03c0166, -+ 0xf99e02ee, -+ 0xfe59f65d, -+ 0xfb54fd87, -+ 0x1141ffb2, -+ 0x009dff30, -+ 0x05e30000, -+ 0xff060705, -+ 0x085408a0, -+ 0xf425fc59, -+ 0xfa1d042a, -+ 0xfc78f67a, -+ 0xf7acf60e, -+ 0x075a0766, -+ 0x05e305e3, -+ 0xf8a6f89a, -+ 0xf7acf60e, -+ 0x03880986, -+ 0xfa1d042a, -+ 0x0bdb03a7, -+ 0x085408a0, -+ 0x00faf8fb, -+ 0x05e30000, -+ 0xff06f8fb, -+ 0x0854f760, -+ 0xf42503a7, -+ 0xfa1dfbd6, -+ 0xfc780986, -+ 0xf7ac09f2, -+ 0x075af89a, -+ 0x05e3fa1d, -+ 0xf8a60766, -+ 0xf7ac09f2, -+ 0x0388f67a, -+ 0xfa1dfbd6, -+ 0x0bdbfc59, -+ 0x0854f760, -+ 0x00fa0705, -+ 0x05e30000, -+ 0xff060705, -+ 0x085408a0, -+ 0xf425fc59, -+ 0xfa1d042a, -+ 0xfc78f67a, -+ 0xf7acf60e, -+ 0x075a0766, -+ 0x05e305e3, -+ 0xf8a6f89a, -+ 0xf7acf60e, -+ 0x03880986, -+ 0xfa1d042a, -+ 0x0bdb03a7, -+ 0x085408a0, -+ 0x00faf8fb, -+ 0x05e30000, -+ 0xff06f8fb, -+ 0x0854f760, -+ 0xf42503a7, -+ 0xfa1dfbd6, -+ 0xfc780986, -+ 0xf7ac09f2, -+ 0x075af89a, -+ 0x05e3fa1d, -+ 0xf8a60766, -+ 0xf7ac09f2, -+ 0x0388f67a, -+ 0xfa1dfbd6, -+ 0x0bdbfc59, -+ 0x0854f760, -+ 0x00fa0705, -+ 0xfa58fa58, -+ 0xf8f0fe00, -+ 0x0448073d, -+ 0xfdc9fe46, -+ 0xf9910258, -+ 0x089d0407, -+ 0xfd5cf71a, -+ 0x02affde0, -+ 0x083e0496, -+ 0xff5a0740, -+ 0xff7afd97, -+ 0x00fe01f1, -+ 0x0009082e, -+ 0xfa94ff75, -+ 0xfecdf8ea, -+ 0xffb0f693, -+ 0xfd2cfa58, -+ 0x0433ff16, -+ 0xfba405dd, -+ 0xfa610341, -+ 0x06a606cb, -+ 0x0039fd2d, -+ 0x0677fa97, -+ 0x01fa05e0, -+ 0xf896003e, -+ 0x075a068b, -+ 0x012cfc3e, -+ 0xfa23f98d, -+ 0xfc7cfd43, -+ 0xff90fc0d, -+ 0x01c10982, -+ 0x00c601d6, -+ 0xfd2cfd2c, -+ 0x01d600c6, -+ 0x098201c1, -+ 0xfc0dff90, -+ 0xfd43fc7c, -+ 0xf98dfa23, -+ 0xfc3e012c, -+ 0x068b075a, -+ 0x003ef896, -+ 0x05e001fa, -+ 0xfa970677, -+ 0xfd2d0039, -+ 0x06cb06a6, -+ 0x0341fa61, -+ 0x05ddfba4, -+ 0xff160433, -+ 0xfa58fd2c, -+ 0xf693ffb0, -+ 0xf8eafecd, -+ 0xff75fa94, -+ 0x082e0009, -+ 0x01f100fe, -+ 0xfd97ff7a, -+ 0x0740ff5a, -+ 0x0496083e, -+ 0xfde002af, -+ 0xf71afd5c, -+ 0x0407089d, -+ 0x0258f991, -+ 0xfe46fdc9, -+ 0x073d0448, -+ 0xfe00f8f0, -+ 0xfd2cfd2c, -+ 0xfce00500, -+ 0xfc09fddc, -+ 0xfe680157, -+ 0x04c70571, -+ 0xfc3aff21, -+ 0xfcd70228, -+ 0x056d0277, -+ 0x0200fe00, -+ 0x0022f927, -+ 0xfe3c032b, -+ 0xfc44ff3c, -+ 0x03e9fbdb, -+ 0x04570313, -+ 0x04c9ff5c, -+ 0x000d03b8, -+ 0xfa580000, -+ 0xfbe900d2, -+ 0xf9d0fe0b, -+ 0x0125fdf9, -+ 0x042501bf, -+ 0x0328fa2b, -+ 0xffa902f0, -+ 0xfa250157, -+ 0x0200fe00, -+ 0x03740438, -+ 0xff0405fd, -+ 0x030cfe52, -+ 0x0037fb39, -+ 0xff6904c5, -+ 0x04f8fd23, -+ 0xfd31fc1b, -+ 0xfd2cfd2c, -+ 0xfc1bfd31, -+ 0xfd2304f8, -+ 0x04c5ff69, -+ 0xfb390037, -+ 0xfe52030c, -+ 0x05fdff04, -+ 0x04380374, -+ 0xfe000200, -+ 0x0157fa25, -+ 0x02f0ffa9, -+ 0xfa2b0328, -+ 0x01bf0425, -+ 0xfdf90125, -+ 0xfe0bf9d0, -+ 0x00d2fbe9, -+ 0x0000fa58, -+ 0x03b8000d, -+ 0xff5c04c9, -+ 0x03130457, -+ 0xfbdb03e9, -+ 0xff3cfc44, -+ 0x032bfe3c, -+ 0xf9270022, -+ 0xfe000200, -+ 0x0277056d, -+ 0x0228fcd7, -+ 0xff21fc3a, -+ 0x057104c7, -+ 0x0157fe68, -+ 0xfddcfc09, -+ 0x0500fce0, -+ 0xfd2cfd2c, -+ 0x0500fce0, -+ 0xfddcfc09, -+ 0x0157fe68, -+ 0x057104c7, -+ 0xff21fc3a, -+ 0x0228fcd7, -+ 0x0277056d, -+ 0xfe000200, -+ 0xf9270022, -+ 0x032bfe3c, -+ 0xff3cfc44, -+ 0xfbdb03e9, -+ 0x03130457, -+ 0xff5c04c9, -+ 0x03b8000d, -+ 0x0000fa58, -+ 0x00d2fbe9, -+ 0xfe0bf9d0, -+ 0xfdf90125, -+ 0x01bf0425, -+ 0xfa2b0328, -+ 0x02f0ffa9, -+ 0x0157fa25, -+ 0xfe000200, -+ 0x04380374, -+ 0x05fdff04, -+ 0xfe52030c, -+ 0xfb390037, -+ 0x04c5ff69, -+ 0xfd2304f8, -+ 0xfc1bfd31, -+ 0xfd2cfd2c, -+ 0xfd31fc1b, -+ 0x04f8fd23, -+ 0xff6904c5, -+ 0x0037fb39, -+ 0x030cfe52, -+ 0xff0405fd, -+ 0x03740438, -+ 0x0200fe00, -+ 0xfa250157, -+ 0xffa902f0, -+ 0x0328fa2b, -+ 0x042501bf, -+ 0x0125fdf9, -+ 0xf9d0fe0b, -+ 0xfbe900d2, -+ 0xfa580000, -+ 0x000d03b8, -+ 0x04c9ff5c, -+ 0x04570313, -+ 0x03e9fbdb, -+ 0xfc44ff3c, -+ 0xfe3c032b, -+ 0x0022f927, -+ 0x0200fe00, -+ 0x056d0277, -+ 0xfcd70228, -+ 0xfc3aff21, -+ 0x04c70571, -+ 0xfe680157, -+ 0xfc09fddc, -+ 0xfce00500, -+ 0x05a80000, -+ 0xff1006be, -+ 0x0800084a, -+ 0xf49cfc7e, -+ 0xfa580400, -+ 0xfc9cf6da, -+ 0xf800f672, -+ 0x0710071c, -+ 0x05a805a8, -+ 0xf8f0f8e4, -+ 0xf800f672, -+ 0x03640926, -+ 0xfa580400, -+ 0x0b640382, -+ 0x0800084a, -+ 0x00f0f942, -+ 0x05a80000, -+ 0xff10f942, -+ 0x0800f7b6, -+ 0xf49c0382, -+ 0xfa58fc00, -+ 0xfc9c0926, -+ 0xf800098e, -+ 0x0710f8e4, -+ 0x05a8fa58, -+ 0xf8f0071c, -+ 0xf800098e, -+ 0x0364f6da, -+ 0xfa58fc00, -+ 0x0b64fc7e, -+ 0x0800f7b6, -+ 0x00f006be, -+ 0x05a80000, -+ 0xff1006be, -+ 0x0800084a, -+ 0xf49cfc7e, -+ 0xfa580400, -+ 0xfc9cf6da, -+ 0xf800f672, -+ 0x0710071c, -+ 0x05a805a8, -+ 0xf8f0f8e4, -+ 0xf800f672, -+ 0x03640926, -+ 0xfa580400, -+ 0x0b640382, -+ 0x0800084a, -+ 0x00f0f942, -+ 0x05a80000, -+ 0xff10f942, -+ 0x0800f7b6, -+ 0xf49c0382, -+ 0xfa58fc00, -+ 0xfc9c0926, -+ 0xf800098e, -+ 0x0710f8e4, -+ 0x05a8fa58, -+ 0xf8f0071c, -+ 0xf800098e, -+ 0x0364f6da, -+ 0xfa58fc00, -+ 0x0b64fc7e, -+ 0x0800f7b6, -+ 0x00f006be, -+}; -+ -+static const u32 intlv_tbl_rev0[] = { -+ 0x00802070, -+ 0x0671188d, -+ 0x0a60192c, -+ 0x0a300e46, -+ 0x00c1188d, -+ 0x080024d2, -+ 0x00000070, -+}; -+ -+static const u16 pilot_tbl_rev0[] = { -+ 0xff08, -+ 0xff08, -+ 0xff08, -+ 0xff08, -+ 0xff08, -+ 0xff08, -+ 0xff08, -+ 0xff08, -+ 0x80d5, -+ 0x80d5, -+ 0x80d5, -+ 0x80d5, -+ 0x80d5, -+ 0x80d5, -+ 0x80d5, -+ 0x80d5, -+ 0xff0a, -+ 0xff82, -+ 0xffa0, -+ 0xff28, -+ 0xffff, -+ 0xffff, -+ 0xffff, -+ 0xffff, -+ 0xff82, -+ 0xffa0, -+ 0xff28, -+ 0xff0a, -+ 0xffff, -+ 0xffff, -+ 0xffff, -+ 0xffff, -+ 0xf83f, -+ 0xfa1f, -+ 0xfa97, -+ 0xfab5, -+ 0xf2bd, -+ 0xf0bf, -+ 0xffff, -+ 0xffff, -+ 0xf017, -+ 0xf815, -+ 0xf215, -+ 0xf095, -+ 0xf035, -+ 0xf01d, -+ 0xffff, -+ 0xffff, -+ 0xff08, -+ 0xff02, -+ 0xff80, -+ 0xff20, -+ 0xff08, -+ 0xff02, -+ 0xff80, -+ 0xff20, -+ 0xf01f, -+ 0xf817, -+ 0xfa15, -+ 0xf295, -+ 0xf0b5, -+ 0xf03d, -+ 0xffff, -+ 0xffff, -+ 0xf82a, -+ 0xfa0a, -+ 0xfa82, -+ 0xfaa0, -+ 0xf2a8, -+ 0xf0aa, -+ 0xffff, -+ 0xffff, -+ 0xf002, -+ 0xf800, -+ 0xf200, -+ 0xf080, -+ 0xf020, -+ 0xf008, -+ 0xffff, -+ 0xffff, -+ 0xf00a, -+ 0xf802, -+ 0xfa00, -+ 0xf280, -+ 0xf0a0, -+ 0xf028, -+ 0xffff, -+ 0xffff, -+}; -+ -+static const u32 pltlut_tbl_rev0[] = { -+ 0x76540123, -+ 0x62407351, -+ 0x76543201, -+ 0x76540213, -+ 0x76540123, -+ 0x76430521, -+}; -+ -+static const u32 tdi_tbl20_ant0_rev0[] = { -+ 0x00091226, -+ 0x000a1429, -+ 0x000b56ad, -+ 0x000c58b0, -+ 0x000d5ab3, -+ 0x000e9cb6, -+ 0x000f9eba, -+ 0x0000c13d, -+ 0x00020301, -+ 0x00030504, -+ 0x00040708, -+ 0x0005090b, -+ 0x00064b8e, -+ 0x00095291, -+ 0x000a5494, -+ 0x000b9718, -+ 0x000c9927, -+ 0x000d9b2a, -+ 0x000edd2e, -+ 0x000fdf31, -+ 0x000101b4, -+ 0x000243b7, -+ 0x000345bb, -+ 0x000447be, -+ 0x00058982, -+ 0x00068c05, -+ 0x00099309, -+ 0x000a950c, -+ 0x000bd78f, -+ 0x000cd992, -+ 0x000ddb96, -+ 0x000f1d99, -+ 0x00005fa8, -+ 0x0001422c, -+ 0x0002842f, -+ 0x00038632, -+ 0x00048835, -+ 0x0005ca38, -+ 0x0006ccbc, -+ 0x0009d3bf, -+ 0x000b1603, -+ 0x000c1806, -+ 0x000d1a0a, -+ 0x000e1c0d, -+ 0x000f5e10, -+ 0x00008093, -+ 0x00018297, -+ 0x0002c49a, -+ 0x0003c680, -+ 0x0004c880, -+ 0x00060b00, -+ 0x00070d00, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+static const u32 tdi_tbl20_ant1_rev0[] = { -+ 0x00014b26, -+ 0x00028d29, -+ 0x000393ad, -+ 0x00049630, -+ 0x0005d833, -+ 0x0006da36, -+ 0x00099c3a, -+ 0x000a9e3d, -+ 0x000bc081, -+ 0x000cc284, -+ 0x000dc488, -+ 0x000f068b, -+ 0x0000488e, -+ 0x00018b91, -+ 0x0002d214, -+ 0x0003d418, -+ 0x0004d6a7, -+ 0x000618aa, -+ 0x00071aae, -+ 0x0009dcb1, -+ 0x000b1eb4, -+ 0x000c0137, -+ 0x000d033b, -+ 0x000e053e, -+ 0x000f4702, -+ 0x00008905, -+ 0x00020c09, -+ 0x0003128c, -+ 0x0004148f, -+ 0x00051712, -+ 0x00065916, -+ 0x00091b19, -+ 0x000a1d28, -+ 0x000b5f2c, -+ 0x000c41af, -+ 0x000d43b2, -+ 0x000e85b5, -+ 0x000f87b8, -+ 0x0000c9bc, -+ 0x00024cbf, -+ 0x00035303, -+ 0x00045506, -+ 0x0005978a, -+ 0x0006998d, -+ 0x00095b90, -+ 0x000a5d93, -+ 0x000b9f97, -+ 0x000c821a, -+ 0x000d8400, -+ 0x000ec600, -+ 0x000fc800, -+ 0x00010a00, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+static const u32 tdi_tbl40_ant0_rev0[] = { -+ 0x0011a346, -+ 0x00136ccf, -+ 0x0014f5d9, -+ 0x001641e2, -+ 0x0017cb6b, -+ 0x00195475, -+ 0x001b2383, -+ 0x001cad0c, -+ 0x001e7616, -+ 0x0000821f, -+ 0x00020ba8, -+ 0x0003d4b2, -+ 0x00056447, -+ 0x00072dd0, -+ 0x0008b6da, -+ 0x000a02e3, -+ 0x000b8c6c, -+ 0x000d15f6, -+ 0x0011e484, -+ 0x0013ae0d, -+ 0x00153717, -+ 0x00168320, -+ 0x00180ca9, -+ 0x00199633, -+ 0x001b6548, -+ 0x001ceed1, -+ 0x001eb7db, -+ 0x0000c3e4, -+ 0x00024d6d, -+ 0x000416f7, -+ 0x0005a585, -+ 0x00076f0f, -+ 0x0008f818, -+ 0x000a4421, -+ 0x000bcdab, -+ 0x000d9734, -+ 0x00122649, -+ 0x0013efd2, -+ 0x001578dc, -+ 0x0016c4e5, -+ 0x00184e6e, -+ 0x001a17f8, -+ 0x001ba686, -+ 0x001d3010, -+ 0x001ef999, -+ 0x00010522, -+ 0x00028eac, -+ 0x00045835, -+ 0x0005e74a, -+ 0x0007b0d3, -+ 0x00093a5d, -+ 0x000a85e6, -+ 0x000c0f6f, -+ 0x000dd8f9, -+ 0x00126787, -+ 0x00143111, -+ 0x0015ba9a, -+ 0x00170623, -+ 0x00188fad, -+ 0x001a5936, -+ 0x001be84b, -+ 0x001db1d4, -+ 0x001f3b5e, -+ 0x000146e7, -+ 0x00031070, -+ 0x000499fa, -+ 0x00062888, -+ 0x0007f212, -+ 0x00097b9b, -+ 0x000ac7a4, -+ 0x000c50ae, -+ 0x000e1a37, -+ 0x0012a94c, -+ 0x001472d5, -+ 0x0015fc5f, -+ 0x00174868, -+ 0x0018d171, -+ 0x001a9afb, -+ 0x001c2989, -+ 0x001df313, -+ 0x001f7c9c, -+ 0x000188a5, -+ 0x000351af, -+ 0x0004db38, -+ 0x0006aa4d, -+ 0x000833d7, -+ 0x0009bd60, -+ 0x000b0969, -+ 0x000c9273, -+ 0x000e5bfc, -+ 0x00132a8a, -+ 0x0014b414, -+ 0x00163d9d, -+ 0x001789a6, -+ 0x001912b0, -+ 0x001adc39, -+ 0x001c6bce, -+ 0x001e34d8, -+ 0x001fbe61, -+ 0x0001ca6a, -+ 0x00039374, -+ 0x00051cfd, -+ 0x0006ec0b, -+ 0x00087515, -+ 0x0009fe9e, -+ 0x000b4aa7, -+ 0x000cd3b1, -+ 0x000e9d3a, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+static const u32 tdi_tbl40_ant1_rev0[] = { -+ 0x001edb36, -+ 0x000129ca, -+ 0x0002b353, -+ 0x00047cdd, -+ 0x0005c8e6, -+ 0x000791ef, -+ 0x00091bf9, -+ 0x000aaa07, -+ 0x000c3391, -+ 0x000dfd1a, -+ 0x00120923, -+ 0x0013d22d, -+ 0x00155c37, -+ 0x0016eacb, -+ 0x00187454, -+ 0x001a3dde, -+ 0x001b89e7, -+ 0x001d12f0, -+ 0x001f1cfa, -+ 0x00016b88, -+ 0x00033492, -+ 0x0004be1b, -+ 0x00060a24, -+ 0x0007d32e, -+ 0x00095d38, -+ 0x000aec4c, -+ 0x000c7555, -+ 0x000e3edf, -+ 0x00124ae8, -+ 0x001413f1, -+ 0x0015a37b, -+ 0x00172c89, -+ 0x0018b593, -+ 0x001a419c, -+ 0x001bcb25, -+ 0x001d942f, -+ 0x001f63b9, -+ 0x0001ad4d, -+ 0x00037657, -+ 0x0004c260, -+ 0x00068be9, -+ 0x000814f3, -+ 0x0009a47c, -+ 0x000b2d8a, -+ 0x000cb694, -+ 0x000e429d, -+ 0x00128c26, -+ 0x001455b0, -+ 0x0015e4ba, -+ 0x00176e4e, -+ 0x0018f758, -+ 0x001a8361, -+ 0x001c0cea, -+ 0x001dd674, -+ 0x001fa57d, -+ 0x0001ee8b, -+ 0x0003b795, -+ 0x0005039e, -+ 0x0006cd27, -+ 0x000856b1, -+ 0x0009e5c6, -+ 0x000b6f4f, -+ 0x000cf859, -+ 0x000e8462, -+ 0x00130deb, -+ 0x00149775, -+ 0x00162603, -+ 0x0017af8c, -+ 0x00193896, -+ 0x001ac49f, -+ 0x001c4e28, -+ 0x001e17b2, -+ 0x0000a6c7, -+ 0x00023050, -+ 0x0003f9da, -+ 0x00054563, -+ 0x00070eec, -+ 0x00089876, -+ 0x000a2704, -+ 0x000bb08d, -+ 0x000d3a17, -+ 0x001185a0, -+ 0x00134f29, -+ 0x0014d8b3, -+ 0x001667c8, -+ 0x0017f151, -+ 0x00197adb, -+ 0x001b0664, -+ 0x001c8fed, -+ 0x001e5977, -+ 0x0000e805, -+ 0x0002718f, -+ 0x00043b18, -+ 0x000586a1, -+ 0x0007502b, -+ 0x0008d9b4, -+ 0x000a68c9, -+ 0x000bf252, -+ 0x000dbbdc, -+ 0x0011c7e5, -+ 0x001390ee, -+ 0x00151a78, -+ 0x0016a906, -+ 0x00183290, -+ 0x0019bc19, -+ 0x001b4822, -+ 0x001cd12c, -+ 0x001e9ab5, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+static const u16 bdi_tbl_rev0[] = { -+ 0x0070, -+ 0x0126, -+ 0x012c, -+ 0x0246, -+ 0x048d, -+ 0x04d2, -+}; -+ -+static const u32 chanest_tbl_rev0[] = { -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+}; -+ -+static const u8 mcs_tbl_rev0[] = { -+ 0x00, -+ 0x08, -+ 0x0a, -+ 0x10, -+ 0x12, -+ 0x19, -+ 0x1a, -+ 0x1c, -+ 0x40, -+ 0x48, -+ 0x4a, -+ 0x50, -+ 0x52, -+ 0x59, -+ 0x5a, -+ 0x5c, -+ 0x80, -+ 0x88, -+ 0x8a, -+ 0x90, -+ 0x92, -+ 0x99, -+ 0x9a, -+ 0x9c, -+ 0xc0, -+ 0xc8, -+ 0xca, -+ 0xd0, -+ 0xd2, -+ 0xd9, -+ 0xda, -+ 0xdc, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x01, -+ 0x02, -+ 0x04, -+ 0x08, -+ 0x09, -+ 0x0a, -+ 0x0c, -+ 0x10, -+ 0x11, -+ 0x12, -+ 0x14, -+ 0x18, -+ 0x19, -+ 0x1a, -+ 0x1c, -+ 0x20, -+ 0x21, -+ 0x22, -+ 0x24, -+ 0x40, -+ 0x41, -+ 0x42, -+ 0x44, -+ 0x48, -+ 0x49, -+ 0x4a, -+ 0x4c, -+ 0x50, -+ 0x51, -+ 0x52, -+ 0x54, -+ 0x58, -+ 0x59, -+ 0x5a, -+ 0x5c, -+ 0x60, -+ 0x61, -+ 0x62, -+ 0x64, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+}; -+ -+static const u32 noise_var_tbl0_rev0[] = { -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+}; -+ -+static const u32 noise_var_tbl1_rev0[] = { -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+}; -+ -+static const u8 est_pwr_lut_core0_rev0[] = { -+ 0x50, -+ 0x4f, -+ 0x4e, -+ 0x4d, -+ 0x4c, -+ 0x4b, -+ 0x4a, -+ 0x49, -+ 0x48, -+ 0x47, -+ 0x46, -+ 0x45, -+ 0x44, -+ 0x43, -+ 0x42, -+ 0x41, -+ 0x40, -+ 0x3f, -+ 0x3e, -+ 0x3d, -+ 0x3c, -+ 0x3b, -+ 0x3a, -+ 0x39, -+ 0x38, -+ 0x37, -+ 0x36, -+ 0x35, -+ 0x34, -+ 0x33, -+ 0x32, -+ 0x31, -+ 0x30, -+ 0x2f, -+ 0x2e, -+ 0x2d, -+ 0x2c, -+ 0x2b, -+ 0x2a, -+ 0x29, -+ 0x28, -+ 0x27, -+ 0x26, -+ 0x25, -+ 0x24, -+ 0x23, -+ 0x22, -+ 0x21, -+ 0x20, -+ 0x1f, -+ 0x1e, -+ 0x1d, -+ 0x1c, -+ 0x1b, -+ 0x1a, -+ 0x19, -+ 0x18, -+ 0x17, -+ 0x16, -+ 0x15, -+ 0x14, -+ 0x13, -+ 0x12, -+ 0x11, -+}; -+ -+static const u8 est_pwr_lut_core1_rev0[] = { -+ 0x50, -+ 0x4f, -+ 0x4e, -+ 0x4d, -+ 0x4c, -+ 0x4b, -+ 0x4a, -+ 0x49, -+ 0x48, -+ 0x47, -+ 0x46, -+ 0x45, -+ 0x44, -+ 0x43, -+ 0x42, -+ 0x41, -+ 0x40, -+ 0x3f, -+ 0x3e, -+ 0x3d, -+ 0x3c, -+ 0x3b, -+ 0x3a, -+ 0x39, -+ 0x38, -+ 0x37, -+ 0x36, -+ 0x35, -+ 0x34, -+ 0x33, -+ 0x32, -+ 0x31, -+ 0x30, -+ 0x2f, -+ 0x2e, -+ 0x2d, -+ 0x2c, -+ 0x2b, -+ 0x2a, -+ 0x29, -+ 0x28, -+ 0x27, -+ 0x26, -+ 0x25, -+ 0x24, -+ 0x23, -+ 0x22, -+ 0x21, -+ 0x20, -+ 0x1f, -+ 0x1e, -+ 0x1d, -+ 0x1c, -+ 0x1b, -+ 0x1a, -+ 0x19, -+ 0x18, -+ 0x17, -+ 0x16, -+ 0x15, -+ 0x14, -+ 0x13, -+ 0x12, -+ 0x11, -+}; -+ -+static const u8 adj_pwr_lut_core0_rev0[] = { -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+}; -+ -+static const u8 adj_pwr_lut_core1_rev0[] = { -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+}; -+ -+static const u32 gainctrl_lut_core0_rev0[] = { -+ 0x03cc2b44, -+ 0x03cc2b42, -+ 0x03cc2b40, -+ 0x03cc2b3e, -+ 0x03cc2b3d, -+ 0x03cc2b3b, -+ 0x03c82b44, -+ 0x03c82b42, -+ 0x03c82b40, -+ 0x03c82b3e, -+ 0x03c82b3d, -+ 0x03c82b3b, -+ 0x03c82b39, -+ 0x03c82b38, -+ 0x03c82b36, -+ 0x03c82b34, -+ 0x03c42b44, -+ 0x03c42b42, -+ 0x03c42b40, -+ 0x03c42b3e, -+ 0x03c42b3d, -+ 0x03c42b3b, -+ 0x03c42b39, -+ 0x03c42b38, -+ 0x03c42b36, -+ 0x03c42b34, -+ 0x03c42b33, -+ 0x03c42b32, -+ 0x03c42b30, -+ 0x03c42b2f, -+ 0x03c42b2d, -+ 0x03c02b44, -+ 0x03c02b42, -+ 0x03c02b40, -+ 0x03c02b3e, -+ 0x03c02b3d, -+ 0x03c02b3b, -+ 0x03c02b39, -+ 0x03c02b38, -+ 0x03c02b36, -+ 0x03c02b34, -+ 0x03b02b44, -+ 0x03b02b42, -+ 0x03b02b40, -+ 0x03b02b3e, -+ 0x03b02b3d, -+ 0x03b02b3b, -+ 0x03b02b39, -+ 0x03b02b38, -+ 0x03b02b36, -+ 0x03b02b34, -+ 0x03b02b33, -+ 0x03b02b32, -+ 0x03b02b30, -+ 0x03b02b2f, -+ 0x03b02b2d, -+ 0x03a02b44, -+ 0x03a02b42, -+ 0x03a02b40, -+ 0x03a02b3e, -+ 0x03a02b3d, -+ 0x03a02b3b, -+ 0x03a02b39, -+ 0x03a02b38, -+ 0x03a02b36, -+ 0x03a02b34, -+ 0x03902b44, -+ 0x03902b42, -+ 0x03902b40, -+ 0x03902b3e, -+ 0x03902b3d, -+ 0x03902b3b, -+ 0x03902b39, -+ 0x03902b38, -+ 0x03902b36, -+ 0x03902b34, -+ 0x03902b33, -+ 0x03902b32, -+ 0x03902b30, -+ 0x03802b44, -+ 0x03802b42, -+ 0x03802b40, -+ 0x03802b3e, -+ 0x03802b3d, -+ 0x03802b3b, -+ 0x03802b39, -+ 0x03802b38, -+ 0x03802b36, -+ 0x03802b34, -+ 0x03802b33, -+ 0x03802b32, -+ 0x03802b30, -+ 0x03802b2f, -+ 0x03802b2d, -+ 0x03802b2c, -+ 0x03802b2b, -+ 0x03802b2a, -+ 0x03802b29, -+ 0x03802b27, -+ 0x03802b26, -+ 0x03802b25, -+ 0x03802b24, -+ 0x03802b23, -+ 0x03802b22, -+ 0x03802b21, -+ 0x03802b20, -+ 0x03802b1f, -+ 0x03802b1e, -+ 0x03802b1e, -+ 0x03802b1d, -+ 0x03802b1c, -+ 0x03802b1b, -+ 0x03802b1a, -+ 0x03802b1a, -+ 0x03802b19, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x00002b00, -+}; -+ -+static const u32 gainctrl_lut_core1_rev0[] = { -+ 0x03cc2b44, -+ 0x03cc2b42, -+ 0x03cc2b40, -+ 0x03cc2b3e, -+ 0x03cc2b3d, -+ 0x03cc2b3b, -+ 0x03c82b44, -+ 0x03c82b42, -+ 0x03c82b40, -+ 0x03c82b3e, -+ 0x03c82b3d, -+ 0x03c82b3b, -+ 0x03c82b39, -+ 0x03c82b38, -+ 0x03c82b36, -+ 0x03c82b34, -+ 0x03c42b44, -+ 0x03c42b42, -+ 0x03c42b40, -+ 0x03c42b3e, -+ 0x03c42b3d, -+ 0x03c42b3b, -+ 0x03c42b39, -+ 0x03c42b38, -+ 0x03c42b36, -+ 0x03c42b34, -+ 0x03c42b33, -+ 0x03c42b32, -+ 0x03c42b30, -+ 0x03c42b2f, -+ 0x03c42b2d, -+ 0x03c02b44, -+ 0x03c02b42, -+ 0x03c02b40, -+ 0x03c02b3e, -+ 0x03c02b3d, -+ 0x03c02b3b, -+ 0x03c02b39, -+ 0x03c02b38, -+ 0x03c02b36, -+ 0x03c02b34, -+ 0x03b02b44, -+ 0x03b02b42, -+ 0x03b02b40, -+ 0x03b02b3e, -+ 0x03b02b3d, -+ 0x03b02b3b, -+ 0x03b02b39, -+ 0x03b02b38, -+ 0x03b02b36, -+ 0x03b02b34, -+ 0x03b02b33, -+ 0x03b02b32, -+ 0x03b02b30, -+ 0x03b02b2f, -+ 0x03b02b2d, -+ 0x03a02b44, -+ 0x03a02b42, -+ 0x03a02b40, -+ 0x03a02b3e, -+ 0x03a02b3d, -+ 0x03a02b3b, -+ 0x03a02b39, -+ 0x03a02b38, -+ 0x03a02b36, -+ 0x03a02b34, -+ 0x03902b44, -+ 0x03902b42, -+ 0x03902b40, -+ 0x03902b3e, -+ 0x03902b3d, -+ 0x03902b3b, -+ 0x03902b39, -+ 0x03902b38, -+ 0x03902b36, -+ 0x03902b34, -+ 0x03902b33, -+ 0x03902b32, -+ 0x03902b30, -+ 0x03802b44, -+ 0x03802b42, -+ 0x03802b40, -+ 0x03802b3e, -+ 0x03802b3d, -+ 0x03802b3b, -+ 0x03802b39, -+ 0x03802b38, -+ 0x03802b36, -+ 0x03802b34, -+ 0x03802b33, -+ 0x03802b32, -+ 0x03802b30, -+ 0x03802b2f, -+ 0x03802b2d, -+ 0x03802b2c, -+ 0x03802b2b, -+ 0x03802b2a, -+ 0x03802b29, -+ 0x03802b27, -+ 0x03802b26, -+ 0x03802b25, -+ 0x03802b24, -+ 0x03802b23, -+ 0x03802b22, -+ 0x03802b21, -+ 0x03802b20, -+ 0x03802b1f, -+ 0x03802b1e, -+ 0x03802b1e, -+ 0x03802b1d, -+ 0x03802b1c, -+ 0x03802b1b, -+ 0x03802b1a, -+ 0x03802b1a, -+ 0x03802b19, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x03802b18, -+ 0x00002b00, -+}; -+ -+static const u32 iq_lut_core0_rev0[] = { -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+}; -+ -+static const u32 iq_lut_core1_rev0[] = { -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+ 0x0000007f, -+}; -+ -+static const u16 loft_lut_core0_rev0[] = { -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+}; -+ -+static const u16 loft_lut_core1_rev0[] = { -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+ 0x0000, -+ 0x0101, -+ 0x0002, -+ 0x0103, -+}; -+ -+const struct phytbl_info mimophytbl_info_rev0_volatile[] = { -+ {&bdi_tbl_rev0, sizeof(bdi_tbl_rev0) / sizeof(bdi_tbl_rev0[0]), 21, 0, -+ 16} -+ , -+ {&pltlut_tbl_rev0, sizeof(pltlut_tbl_rev0) / sizeof(pltlut_tbl_rev0[0]), -+ 20, 0, 32} -+ , -+ {&gainctrl_lut_core0_rev0, -+ sizeof(gainctrl_lut_core0_rev0) / sizeof(gainctrl_lut_core0_rev0[0]), -+ 26, 192, 32} -+ , -+ {&gainctrl_lut_core1_rev0, -+ sizeof(gainctrl_lut_core1_rev0) / sizeof(gainctrl_lut_core1_rev0[0]), -+ 27, 192, 32} -+ , -+ -+ {&est_pwr_lut_core0_rev0, -+ sizeof(est_pwr_lut_core0_rev0) / sizeof(est_pwr_lut_core0_rev0[0]), 26, -+ 0, 8} -+ , -+ {&est_pwr_lut_core1_rev0, -+ sizeof(est_pwr_lut_core1_rev0) / sizeof(est_pwr_lut_core1_rev0[0]), 27, -+ 0, 8} -+ , -+ {&adj_pwr_lut_core0_rev0, -+ sizeof(adj_pwr_lut_core0_rev0) / sizeof(adj_pwr_lut_core0_rev0[0]), 26, -+ 64, 8} -+ , -+ {&adj_pwr_lut_core1_rev0, -+ sizeof(adj_pwr_lut_core1_rev0) / sizeof(adj_pwr_lut_core1_rev0[0]), 27, -+ 64, 8} -+ , -+ {&iq_lut_core0_rev0, -+ sizeof(iq_lut_core0_rev0) / sizeof(iq_lut_core0_rev0[0]), 26, 320, 32} -+ , -+ {&iq_lut_core1_rev0, -+ sizeof(iq_lut_core1_rev0) / sizeof(iq_lut_core1_rev0[0]), 27, 320, 32} -+ , -+ {&loft_lut_core0_rev0, -+ sizeof(loft_lut_core0_rev0) / sizeof(loft_lut_core0_rev0[0]), 26, 448, -+ 16} -+ , -+ {&loft_lut_core1_rev0, -+ sizeof(loft_lut_core1_rev0) / sizeof(loft_lut_core1_rev0[0]), 27, 448, -+ 16} -+ , -+}; -+ -+const struct phytbl_info mimophytbl_info_rev0[] = { -+ {&frame_struct_rev0, -+ sizeof(frame_struct_rev0) / sizeof(frame_struct_rev0[0]), 10, 0, 32} -+ , -+ {&frame_lut_rev0, sizeof(frame_lut_rev0) / sizeof(frame_lut_rev0[0]), -+ 24, 0, 8} -+ , -+ {&tmap_tbl_rev0, sizeof(tmap_tbl_rev0) / sizeof(tmap_tbl_rev0[0]), 12, -+ 0, 32} -+ , -+ {&tdtrn_tbl_rev0, sizeof(tdtrn_tbl_rev0) / sizeof(tdtrn_tbl_rev0[0]), -+ 14, 0, 32} -+ , -+ {&intlv_tbl_rev0, sizeof(intlv_tbl_rev0) / sizeof(intlv_tbl_rev0[0]), -+ 13, 0, 32} -+ , -+ {&pilot_tbl_rev0, sizeof(pilot_tbl_rev0) / sizeof(pilot_tbl_rev0[0]), -+ 11, 0, 16} -+ , -+ {&tdi_tbl20_ant0_rev0, -+ sizeof(tdi_tbl20_ant0_rev0) / sizeof(tdi_tbl20_ant0_rev0[0]), 19, 128, -+ 32} -+ , -+ {&tdi_tbl20_ant1_rev0, -+ sizeof(tdi_tbl20_ant1_rev0) / sizeof(tdi_tbl20_ant1_rev0[0]), 19, 256, -+ 32} -+ , -+ {&tdi_tbl40_ant0_rev0, -+ sizeof(tdi_tbl40_ant0_rev0) / sizeof(tdi_tbl40_ant0_rev0[0]), 19, 640, -+ 32} -+ , -+ {&tdi_tbl40_ant1_rev0, -+ sizeof(tdi_tbl40_ant1_rev0) / sizeof(tdi_tbl40_ant1_rev0[0]), 19, 768, -+ 32} -+ , -+ {&chanest_tbl_rev0, -+ sizeof(chanest_tbl_rev0) / sizeof(chanest_tbl_rev0[0]), 22, 0, 32} -+ , -+ {&mcs_tbl_rev0, sizeof(mcs_tbl_rev0) / sizeof(mcs_tbl_rev0[0]), 18, 0, -+ 8} -+ , -+ {&noise_var_tbl0_rev0, -+ sizeof(noise_var_tbl0_rev0) / sizeof(noise_var_tbl0_rev0[0]), 16, 0, -+ 32} -+ , -+ {&noise_var_tbl1_rev0, -+ sizeof(noise_var_tbl1_rev0) / sizeof(noise_var_tbl1_rev0[0]), 16, 128, -+ 32} -+ , -+}; -+ -+const u32 mimophytbl_info_sz_rev0 = -+ sizeof(mimophytbl_info_rev0) / sizeof(mimophytbl_info_rev0[0]); -+const u32 mimophytbl_info_sz_rev0_volatile = -+ sizeof(mimophytbl_info_rev0_volatile) / -+ sizeof(mimophytbl_info_rev0_volatile[0]); -+ -+static const u16 ant_swctrl_tbl_rev3[] = { -+ 0x0082, -+ 0x0082, -+ 0x0211, -+ 0x0222, -+ 0x0328, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0144, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0188, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0082, -+ 0x0082, -+ 0x0211, -+ 0x0222, -+ 0x0328, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0144, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0188, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+}; -+ -+static const u16 ant_swctrl_tbl_rev3_1[] = { -+ 0x0022, -+ 0x0022, -+ 0x0011, -+ 0x0022, -+ 0x0022, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0011, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0022, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0022, -+ 0x0022, -+ 0x0011, -+ 0x0022, -+ 0x0022, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0011, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0022, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+}; -+ -+static const u16 ant_swctrl_tbl_rev3_2[] = { -+ 0x0088, -+ 0x0088, -+ 0x0044, -+ 0x0088, -+ 0x0088, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0044, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0088, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0088, -+ 0x0088, -+ 0x0044, -+ 0x0088, -+ 0x0088, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0044, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0088, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+}; -+ -+static const u16 ant_swctrl_tbl_rev3_3[] = { -+ 0x022, -+ 0x022, -+ 0x011, -+ 0x022, -+ 0x000, -+ 0x000, -+ 0x000, -+ 0x000, -+ 0x011, -+ 0x000, -+ 0x000, -+ 0x000, -+ 0x022, -+ 0x000, -+ 0x000, -+ 0x3cc, -+ 0x022, -+ 0x022, -+ 0x011, -+ 0x022, -+ 0x000, -+ 0x000, -+ 0x000, -+ 0x000, -+ 0x011, -+ 0x000, -+ 0x000, -+ 0x000, -+ 0x022, -+ 0x000, -+ 0x000, -+ 0x3cc -+}; -+ -+static const u32 frame_struct_rev3[] = { -+ 0x08004a04, -+ 0x00100000, -+ 0x01000a05, -+ 0x00100020, -+ 0x09804506, -+ 0x00100030, -+ 0x09804507, -+ 0x00100030, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x08004a0c, -+ 0x00100004, -+ 0x01000a0d, -+ 0x00100024, -+ 0x0980450e, -+ 0x00100034, -+ 0x0980450f, -+ 0x00100034, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000a04, -+ 0x00100000, -+ 0x11008a05, -+ 0x00100020, -+ 0x1980c506, -+ 0x00100030, -+ 0x21810506, -+ 0x00100030, -+ 0x21810506, -+ 0x00100030, -+ 0x01800504, -+ 0x00100030, -+ 0x11808505, -+ 0x00100030, -+ 0x29814507, -+ 0x01100030, -+ 0x00000a04, -+ 0x00100000, -+ 0x11008a05, -+ 0x00100020, -+ 0x21810506, -+ 0x00100030, -+ 0x21810506, -+ 0x00100030, -+ 0x29814507, -+ 0x01100030, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000a0c, -+ 0x00100008, -+ 0x11008a0d, -+ 0x00100028, -+ 0x1980c50e, -+ 0x00100038, -+ 0x2181050e, -+ 0x00100038, -+ 0x2181050e, -+ 0x00100038, -+ 0x0180050c, -+ 0x00100038, -+ 0x1180850d, -+ 0x00100038, -+ 0x2981450f, -+ 0x01100038, -+ 0x00000a0c, -+ 0x00100008, -+ 0x11008a0d, -+ 0x00100028, -+ 0x2181050e, -+ 0x00100038, -+ 0x2181050e, -+ 0x00100038, -+ 0x2981450f, -+ 0x01100038, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x08004a04, -+ 0x00100000, -+ 0x01000a05, -+ 0x00100020, -+ 0x1980c506, -+ 0x00100030, -+ 0x1980c506, -+ 0x00100030, -+ 0x11808504, -+ 0x00100030, -+ 0x3981ca05, -+ 0x00100030, -+ 0x29814507, -+ 0x01100030, -+ 0x00000000, -+ 0x00000000, -+ 0x10008a04, -+ 0x00100000, -+ 0x3981ca05, -+ 0x00100030, -+ 0x1980c506, -+ 0x00100030, -+ 0x29814507, -+ 0x01100030, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x08004a0c, -+ 0x00100008, -+ 0x01000a0d, -+ 0x00100028, -+ 0x1980c50e, -+ 0x00100038, -+ 0x1980c50e, -+ 0x00100038, -+ 0x1180850c, -+ 0x00100038, -+ 0x3981ca0d, -+ 0x00100038, -+ 0x2981450f, -+ 0x01100038, -+ 0x00000000, -+ 0x00000000, -+ 0x10008a0c, -+ 0x00100008, -+ 0x3981ca0d, -+ 0x00100038, -+ 0x1980c50e, -+ 0x00100038, -+ 0x2981450f, -+ 0x01100038, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x40021404, -+ 0x00100000, -+ 0x02001405, -+ 0x00100040, -+ 0x0b004a06, -+ 0x01900060, -+ 0x13008a06, -+ 0x01900060, -+ 0x13008a06, -+ 0x01900060, -+ 0x43020a04, -+ 0x00100060, -+ 0x1b00ca05, -+ 0x00100060, -+ 0x23010a07, -+ 0x01500060, -+ 0x40021404, -+ 0x00100000, -+ 0x1a00d405, -+ 0x00100040, -+ 0x13008a06, -+ 0x01900060, -+ 0x13008a06, -+ 0x01900060, -+ 0x23010a07, -+ 0x01500060, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x4002140c, -+ 0x00100010, -+ 0x0200140d, -+ 0x00100050, -+ 0x0b004a0e, -+ 0x01900070, -+ 0x13008a0e, -+ 0x01900070, -+ 0x13008a0e, -+ 0x01900070, -+ 0x43020a0c, -+ 0x00100070, -+ 0x1b00ca0d, -+ 0x00100070, -+ 0x23010a0f, -+ 0x01500070, -+ 0x4002140c, -+ 0x00100010, -+ 0x1a00d40d, -+ 0x00100050, -+ 0x13008a0e, -+ 0x01900070, -+ 0x13008a0e, -+ 0x01900070, -+ 0x23010a0f, -+ 0x01500070, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x50029404, -+ 0x00100000, -+ 0x32019405, -+ 0x00100040, -+ 0x0b004a06, -+ 0x01900060, -+ 0x0b004a06, -+ 0x01900060, -+ 0x5b02ca04, -+ 0x00100060, -+ 0x3b01d405, -+ 0x00100060, -+ 0x23010a07, -+ 0x01500060, -+ 0x00000000, -+ 0x00000000, -+ 0x5802d404, -+ 0x00100000, -+ 0x3b01d405, -+ 0x00100060, -+ 0x0b004a06, -+ 0x01900060, -+ 0x23010a07, -+ 0x01500060, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x5002940c, -+ 0x00100010, -+ 0x3201940d, -+ 0x00100050, -+ 0x0b004a0e, -+ 0x01900070, -+ 0x0b004a0e, -+ 0x01900070, -+ 0x5b02ca0c, -+ 0x00100070, -+ 0x3b01d40d, -+ 0x00100070, -+ 0x23010a0f, -+ 0x01500070, -+ 0x00000000, -+ 0x00000000, -+ 0x5802d40c, -+ 0x00100010, -+ 0x3b01d40d, -+ 0x00100070, -+ 0x0b004a0e, -+ 0x01900070, -+ 0x23010a0f, -+ 0x01500070, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x40021404, -+ 0x000f4800, -+ 0x62031405, -+ 0x00100040, -+ 0x53028a06, -+ 0x01900060, -+ 0x53028a07, -+ 0x01900060, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x4002140c, -+ 0x000f4808, -+ 0x6203140d, -+ 0x00100048, -+ 0x53028a0e, -+ 0x01900068, -+ 0x53028a0f, -+ 0x01900068, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000a0c, -+ 0x00100004, -+ 0x11008a0d, -+ 0x00100024, -+ 0x1980c50e, -+ 0x00100034, -+ 0x2181050e, -+ 0x00100034, -+ 0x2181050e, -+ 0x00100034, -+ 0x0180050c, -+ 0x00100038, -+ 0x1180850d, -+ 0x00100038, -+ 0x1181850d, -+ 0x00100038, -+ 0x2981450f, -+ 0x01100038, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000a0c, -+ 0x00100008, -+ 0x11008a0d, -+ 0x00100028, -+ 0x2181050e, -+ 0x00100038, -+ 0x2181050e, -+ 0x00100038, -+ 0x1181850d, -+ 0x00100038, -+ 0x2981450f, -+ 0x01100038, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x08004a04, -+ 0x00100000, -+ 0x01000a05, -+ 0x00100020, -+ 0x0180c506, -+ 0x00100030, -+ 0x0180c506, -+ 0x00100030, -+ 0x2180c50c, -+ 0x00100030, -+ 0x49820a0d, -+ 0x0016a130, -+ 0x41824a0d, -+ 0x0016a130, -+ 0x2981450f, -+ 0x01100030, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x2000ca0c, -+ 0x00100000, -+ 0x49820a0d, -+ 0x0016a130, -+ 0x1980c50e, -+ 0x00100030, -+ 0x41824a0d, -+ 0x0016a130, -+ 0x2981450f, -+ 0x01100030, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x4002140c, -+ 0x00100008, -+ 0x0200140d, -+ 0x00100048, -+ 0x0b004a0e, -+ 0x01900068, -+ 0x13008a0e, -+ 0x01900068, -+ 0x13008a0e, -+ 0x01900068, -+ 0x43020a0c, -+ 0x00100070, -+ 0x1b00ca0d, -+ 0x00100070, -+ 0x1b014a0d, -+ 0x00100070, -+ 0x23010a0f, -+ 0x01500070, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x4002140c, -+ 0x00100010, -+ 0x1a00d40d, -+ 0x00100050, -+ 0x13008a0e, -+ 0x01900070, -+ 0x13008a0e, -+ 0x01900070, -+ 0x1b014a0d, -+ 0x00100070, -+ 0x23010a0f, -+ 0x01500070, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x50029404, -+ 0x00100000, -+ 0x32019405, -+ 0x00100040, -+ 0x03004a06, -+ 0x01900060, -+ 0x03004a06, -+ 0x01900060, -+ 0x6b030a0c, -+ 0x00100060, -+ 0x4b02140d, -+ 0x0016a160, -+ 0x4302540d, -+ 0x0016a160, -+ 0x23010a0f, -+ 0x01500060, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x6b03140c, -+ 0x00100060, -+ 0x4b02140d, -+ 0x0016a160, -+ 0x0b004a0e, -+ 0x01900060, -+ 0x4302540d, -+ 0x0016a160, -+ 0x23010a0f, -+ 0x01500060, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x40021404, -+ 0x00100000, -+ 0x1a00d405, -+ 0x00100040, -+ 0x53028a06, -+ 0x01900060, -+ 0x5b02ca06, -+ 0x01900060, -+ 0x5b02ca06, -+ 0x01900060, -+ 0x43020a04, -+ 0x00100060, -+ 0x1b00ca05, -+ 0x00100060, -+ 0x53028a07, -+ 0x0190c060, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x4002140c, -+ 0x00100010, -+ 0x1a00d40d, -+ 0x00100050, -+ 0x53028a0e, -+ 0x01900070, -+ 0x5b02ca0e, -+ 0x01900070, -+ 0x5b02ca0e, -+ 0x01900070, -+ 0x43020a0c, -+ 0x00100070, -+ 0x1b00ca0d, -+ 0x00100070, -+ 0x53028a0f, -+ 0x0190c070, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x40021404, -+ 0x00100000, -+ 0x1a00d405, -+ 0x00100040, -+ 0x5b02ca06, -+ 0x01900060, -+ 0x5b02ca06, -+ 0x01900060, -+ 0x53028a07, -+ 0x0190c060, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x4002140c, -+ 0x00100010, -+ 0x1a00d40d, -+ 0x00100050, -+ 0x5b02ca0e, -+ 0x01900070, -+ 0x5b02ca0e, -+ 0x01900070, -+ 0x53028a0f, -+ 0x0190c070, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+static const u16 pilot_tbl_rev3[] = { -+ 0xff08, -+ 0xff08, -+ 0xff08, -+ 0xff08, -+ 0xff08, -+ 0xff08, -+ 0xff08, -+ 0xff08, -+ 0x80d5, -+ 0x80d5, -+ 0x80d5, -+ 0x80d5, -+ 0x80d5, -+ 0x80d5, -+ 0x80d5, -+ 0x80d5, -+ 0xff0a, -+ 0xff82, -+ 0xffa0, -+ 0xff28, -+ 0xffff, -+ 0xffff, -+ 0xffff, -+ 0xffff, -+ 0xff82, -+ 0xffa0, -+ 0xff28, -+ 0xff0a, -+ 0xffff, -+ 0xffff, -+ 0xffff, -+ 0xffff, -+ 0xf83f, -+ 0xfa1f, -+ 0xfa97, -+ 0xfab5, -+ 0xf2bd, -+ 0xf0bf, -+ 0xffff, -+ 0xffff, -+ 0xf017, -+ 0xf815, -+ 0xf215, -+ 0xf095, -+ 0xf035, -+ 0xf01d, -+ 0xffff, -+ 0xffff, -+ 0xff08, -+ 0xff02, -+ 0xff80, -+ 0xff20, -+ 0xff08, -+ 0xff02, -+ 0xff80, -+ 0xff20, -+ 0xf01f, -+ 0xf817, -+ 0xfa15, -+ 0xf295, -+ 0xf0b5, -+ 0xf03d, -+ 0xffff, -+ 0xffff, -+ 0xf82a, -+ 0xfa0a, -+ 0xfa82, -+ 0xfaa0, -+ 0xf2a8, -+ 0xf0aa, -+ 0xffff, -+ 0xffff, -+ 0xf002, -+ 0xf800, -+ 0xf200, -+ 0xf080, -+ 0xf020, -+ 0xf008, -+ 0xffff, -+ 0xffff, -+ 0xf00a, -+ 0xf802, -+ 0xfa00, -+ 0xf280, -+ 0xf0a0, -+ 0xf028, -+ 0xffff, -+ 0xffff, -+}; -+ -+static const u32 tmap_tbl_rev3[] = { -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0xf1111110, -+ 0x11111111, -+ 0x11f11111, -+ 0x00000111, -+ 0x11000000, -+ 0x1111f111, -+ 0x11111111, -+ 0x111111f1, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x000aa888, -+ 0x88880000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0xa1111110, -+ 0x11111111, -+ 0x11c11111, -+ 0x00000111, -+ 0x11000000, -+ 0x1111a111, -+ 0x11111111, -+ 0x111111a1, -+ 0xa2222220, -+ 0x22222222, -+ 0x22c22222, -+ 0x00000222, -+ 0x22000000, -+ 0x2222a222, -+ 0x22222222, -+ 0x222222a2, -+ 0xf1111110, -+ 0x11111111, -+ 0x11f11111, -+ 0x00011111, -+ 0x11110000, -+ 0x1111f111, -+ 0x11111111, -+ 0x111111f1, -+ 0xa8aa88a0, -+ 0xa88888a8, -+ 0xa8a8a88a, -+ 0x00088aaa, -+ 0xaaaa0000, -+ 0xa8a8aa88, -+ 0xa88aaaaa, -+ 0xaaaa8a8a, -+ 0xaaa8aaa0, -+ 0x8aaa8aaa, -+ 0xaa8a8a8a, -+ 0x000aaa88, -+ 0x8aaa0000, -+ 0xaaa8a888, -+ 0x8aa88a8a, -+ 0x8a88a888, -+ 0x08080a00, -+ 0x0a08080a, -+ 0x080a0a08, -+ 0x00080808, -+ 0x080a0000, -+ 0x080a0808, -+ 0x080a0808, -+ 0x0a0a0a08, -+ 0xa0a0a0a0, -+ 0x80a0a080, -+ 0x8080a0a0, -+ 0x00008080, -+ 0x80a00000, -+ 0x80a080a0, -+ 0xa080a0a0, -+ 0x8080a0a0, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x99999000, -+ 0x9b9b99bb, -+ 0x9bb99999, -+ 0x9999b9b9, -+ 0x9b99bb90, -+ 0x9bbbbb9b, -+ 0x9b9b9bb9, -+ 0x00000999, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00aaa888, -+ 0x22000000, -+ 0x2222b222, -+ 0x22222222, -+ 0x222222b2, -+ 0xb2222220, -+ 0x22222222, -+ 0x22d22222, -+ 0x00000222, -+ 0x11000000, -+ 0x1111a111, -+ 0x11111111, -+ 0x111111a1, -+ 0xa1111110, -+ 0x11111111, -+ 0x11c11111, -+ 0x00000111, -+ 0x33000000, -+ 0x3333b333, -+ 0x33333333, -+ 0x333333b3, -+ 0xb3333330, -+ 0x33333333, -+ 0x33d33333, -+ 0x00000333, -+ 0x22000000, -+ 0x2222a222, -+ 0x22222222, -+ 0x222222a2, -+ 0xa2222220, -+ 0x22222222, -+ 0x22c22222, -+ 0x00000222, -+ 0x99b99b00, -+ 0x9b9b99bb, -+ 0x9bb99999, -+ 0x9999b9b9, -+ 0x9b99bb99, -+ 0x9bbbbb9b, -+ 0x9b9b9bb9, -+ 0x00000999, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa88, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x08aaa888, -+ 0x22222200, -+ 0x2222f222, -+ 0x22222222, -+ 0x222222f2, -+ 0x22222222, -+ 0x22222222, -+ 0x22f22222, -+ 0x00000222, -+ 0x11000000, -+ 0x1111f111, -+ 0x11111111, -+ 0x11111111, -+ 0xf1111111, -+ 0x11111111, -+ 0x11f11111, -+ 0x01111111, -+ 0xbb9bb900, -+ 0xb9b9bb99, -+ 0xb99bbbbb, -+ 0xbbbb9b9b, -+ 0xb9bb99bb, -+ 0xb99999b9, -+ 0xb9b9b99b, -+ 0x00000bbb, -+ 0xaa000000, -+ 0xa8a8aa88, -+ 0xa88aaaaa, -+ 0xaaaa8a8a, -+ 0xa8aa88aa, -+ 0xa88888a8, -+ 0xa8a8a88a, -+ 0x0a888aaa, -+ 0xaa000000, -+ 0xa8a8aa88, -+ 0xa88aaaaa, -+ 0xaaaa8a8a, -+ 0xa8aa88a0, -+ 0xa88888a8, -+ 0xa8a8a88a, -+ 0x00000aaa, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0xbbbbbb00, -+ 0x999bbbbb, -+ 0x9bb99b9b, -+ 0xb9b9b9bb, -+ 0xb9b99bbb, -+ 0xb9b9b9bb, -+ 0xb9bb9b99, -+ 0x00000999, -+ 0x8a000000, -+ 0xaa88a888, -+ 0xa88888aa, -+ 0xa88a8a88, -+ 0xa88aa88a, -+ 0x88a8aaaa, -+ 0xa8aa8aaa, -+ 0x0888a88a, -+ 0x0b0b0b00, -+ 0x090b0b0b, -+ 0x0b090b0b, -+ 0x0909090b, -+ 0x09090b0b, -+ 0x09090b0b, -+ 0x09090b09, -+ 0x00000909, -+ 0x0a000000, -+ 0x0a080808, -+ 0x080a080a, -+ 0x080a0a08, -+ 0x080a080a, -+ 0x0808080a, -+ 0x0a0a0a08, -+ 0x0808080a, -+ 0xb0b0b000, -+ 0x9090b0b0, -+ 0x90b09090, -+ 0xb0b0b090, -+ 0xb0b090b0, -+ 0x90b0b0b0, -+ 0xb0b09090, -+ 0x00000090, -+ 0x80000000, -+ 0xa080a080, -+ 0xa08080a0, -+ 0xa0808080, -+ 0xa080a080, -+ 0x80a0a0a0, -+ 0xa0a080a0, -+ 0x00a0a0a0, -+ 0x22000000, -+ 0x2222f222, -+ 0x22222222, -+ 0x222222f2, -+ 0xf2222220, -+ 0x22222222, -+ 0x22f22222, -+ 0x00000222, -+ 0x11000000, -+ 0x1111f111, -+ 0x11111111, -+ 0x111111f1, -+ 0xf1111110, -+ 0x11111111, -+ 0x11f11111, -+ 0x00000111, -+ 0x33000000, -+ 0x3333f333, -+ 0x33333333, -+ 0x333333f3, -+ 0xf3333330, -+ 0x33333333, -+ 0x33f33333, -+ 0x00000333, -+ 0x22000000, -+ 0x2222f222, -+ 0x22222222, -+ 0x222222f2, -+ 0xf2222220, -+ 0x22222222, -+ 0x22f22222, -+ 0x00000222, -+ 0x99000000, -+ 0x9b9b99bb, -+ 0x9bb99999, -+ 0x9999b9b9, -+ 0x9b99bb90, -+ 0x9bbbbb9b, -+ 0x9b9b9bb9, -+ 0x00000999, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x88888000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00aaa888, -+ 0x88a88a00, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa88, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa88, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x08aaa888, -+ 0x11000000, -+ 0x1111a111, -+ 0x11111111, -+ 0x111111a1, -+ 0xa1111110, -+ 0x11111111, -+ 0x11c11111, -+ 0x00000111, -+ 0x11000000, -+ 0x1111a111, -+ 0x11111111, -+ 0x111111a1, -+ 0xa1111110, -+ 0x11111111, -+ 0x11c11111, -+ 0x00000111, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+static const u32 intlv_tbl_rev3[] = { -+ 0x00802070, -+ 0x0671188d, -+ 0x0a60192c, -+ 0x0a300e46, -+ 0x00c1188d, -+ 0x080024d2, -+ 0x00000070, -+}; -+ -+static const u32 tdtrn_tbl_rev3[] = { -+ 0x061c061c, -+ 0x0050ee68, -+ 0xf592fe36, -+ 0xfe5212f6, -+ 0x00000c38, -+ 0xfe5212f6, -+ 0xf592fe36, -+ 0x0050ee68, -+ 0x061c061c, -+ 0xee680050, -+ 0xfe36f592, -+ 0x12f6fe52, -+ 0x0c380000, -+ 0x12f6fe52, -+ 0xfe36f592, -+ 0xee680050, -+ 0x061c061c, -+ 0x0050ee68, -+ 0xf592fe36, -+ 0xfe5212f6, -+ 0x00000c38, -+ 0xfe5212f6, -+ 0xf592fe36, -+ 0x0050ee68, -+ 0x061c061c, -+ 0xee680050, -+ 0xfe36f592, -+ 0x12f6fe52, -+ 0x0c380000, -+ 0x12f6fe52, -+ 0xfe36f592, -+ 0xee680050, -+ 0x05e305e3, -+ 0x004def0c, -+ 0xf5f3fe47, -+ 0xfe611246, -+ 0x00000bc7, -+ 0xfe611246, -+ 0xf5f3fe47, -+ 0x004def0c, -+ 0x05e305e3, -+ 0xef0c004d, -+ 0xfe47f5f3, -+ 0x1246fe61, -+ 0x0bc70000, -+ 0x1246fe61, -+ 0xfe47f5f3, -+ 0xef0c004d, -+ 0x05e305e3, -+ 0x004def0c, -+ 0xf5f3fe47, -+ 0xfe611246, -+ 0x00000bc7, -+ 0xfe611246, -+ 0xf5f3fe47, -+ 0x004def0c, -+ 0x05e305e3, -+ 0xef0c004d, -+ 0xfe47f5f3, -+ 0x1246fe61, -+ 0x0bc70000, -+ 0x1246fe61, -+ 0xfe47f5f3, -+ 0xef0c004d, -+ 0xfa58fa58, -+ 0xf895043b, -+ 0xff4c09c0, -+ 0xfbc6ffa8, -+ 0xfb84f384, -+ 0x0798f6f9, -+ 0x05760122, -+ 0x058409f6, -+ 0x0b500000, -+ 0x05b7f542, -+ 0x08860432, -+ 0x06ddfee7, -+ 0xfb84f384, -+ 0xf9d90664, -+ 0xf7e8025c, -+ 0x00fff7bd, -+ 0x05a805a8, -+ 0xf7bd00ff, -+ 0x025cf7e8, -+ 0x0664f9d9, -+ 0xf384fb84, -+ 0xfee706dd, -+ 0x04320886, -+ 0xf54205b7, -+ 0x00000b50, -+ 0x09f60584, -+ 0x01220576, -+ 0xf6f90798, -+ 0xf384fb84, -+ 0xffa8fbc6, -+ 0x09c0ff4c, -+ 0x043bf895, -+ 0x02d402d4, -+ 0x07de0270, -+ 0xfc96079c, -+ 0xf90afe94, -+ 0xfe00ff2c, -+ 0x02d4065d, -+ 0x092a0096, -+ 0x0014fbb8, -+ 0xfd2cfd2c, -+ 0x076afb3c, -+ 0x0096f752, -+ 0xf991fd87, -+ 0xfb2c0200, -+ 0xfeb8f960, -+ 0x08e0fc96, -+ 0x049802a8, -+ 0xfd2cfd2c, -+ 0x02a80498, -+ 0xfc9608e0, -+ 0xf960feb8, -+ 0x0200fb2c, -+ 0xfd87f991, -+ 0xf7520096, -+ 0xfb3c076a, -+ 0xfd2cfd2c, -+ 0xfbb80014, -+ 0x0096092a, -+ 0x065d02d4, -+ 0xff2cfe00, -+ 0xfe94f90a, -+ 0x079cfc96, -+ 0x027007de, -+ 0x02d402d4, -+ 0x027007de, -+ 0x079cfc96, -+ 0xfe94f90a, -+ 0xff2cfe00, -+ 0x065d02d4, -+ 0x0096092a, -+ 0xfbb80014, -+ 0xfd2cfd2c, -+ 0xfb3c076a, -+ 0xf7520096, -+ 0xfd87f991, -+ 0x0200fb2c, -+ 0xf960feb8, -+ 0xfc9608e0, -+ 0x02a80498, -+ 0xfd2cfd2c, -+ 0x049802a8, -+ 0x08e0fc96, -+ 0xfeb8f960, -+ 0xfb2c0200, -+ 0xf991fd87, -+ 0x0096f752, -+ 0x076afb3c, -+ 0xfd2cfd2c, -+ 0x0014fbb8, -+ 0x092a0096, -+ 0x02d4065d, -+ 0xfe00ff2c, -+ 0xf90afe94, -+ 0xfc96079c, -+ 0x07de0270, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x062a0000, -+ 0xfefa0759, -+ 0x08b80908, -+ 0xf396fc2d, -+ 0xf9d6045c, -+ 0xfc4ef608, -+ 0xf748f596, -+ 0x07b207bf, -+ 0x062a062a, -+ 0xf84ef841, -+ 0xf748f596, -+ 0x03b209f8, -+ 0xf9d6045c, -+ 0x0c6a03d3, -+ 0x08b80908, -+ 0x0106f8a7, -+ 0x062a0000, -+ 0xfefaf8a7, -+ 0x08b8f6f8, -+ 0xf39603d3, -+ 0xf9d6fba4, -+ 0xfc4e09f8, -+ 0xf7480a6a, -+ 0x07b2f841, -+ 0x062af9d6, -+ 0xf84e07bf, -+ 0xf7480a6a, -+ 0x03b2f608, -+ 0xf9d6fba4, -+ 0x0c6afc2d, -+ 0x08b8f6f8, -+ 0x01060759, -+ 0x062a0000, -+ 0xfefa0759, -+ 0x08b80908, -+ 0xf396fc2d, -+ 0xf9d6045c, -+ 0xfc4ef608, -+ 0xf748f596, -+ 0x07b207bf, -+ 0x062a062a, -+ 0xf84ef841, -+ 0xf748f596, -+ 0x03b209f8, -+ 0xf9d6045c, -+ 0x0c6a03d3, -+ 0x08b80908, -+ 0x0106f8a7, -+ 0x062a0000, -+ 0xfefaf8a7, -+ 0x08b8f6f8, -+ 0xf39603d3, -+ 0xf9d6fba4, -+ 0xfc4e09f8, -+ 0xf7480a6a, -+ 0x07b2f841, -+ 0x062af9d6, -+ 0xf84e07bf, -+ 0xf7480a6a, -+ 0x03b2f608, -+ 0xf9d6fba4, -+ 0x0c6afc2d, -+ 0x08b8f6f8, -+ 0x01060759, -+ 0x061c061c, -+ 0xff30009d, -+ 0xffb21141, -+ 0xfd87fb54, -+ 0xf65dfe59, -+ 0x02eef99e, -+ 0x0166f03c, -+ 0xfff809b6, -+ 0x000008a4, -+ 0x000af42b, -+ 0x00eff577, -+ 0xfa840bf2, -+ 0xfc02ff51, -+ 0x08260f67, -+ 0xfff0036f, -+ 0x0842f9c3, -+ 0x00000000, -+ 0x063df7be, -+ 0xfc910010, -+ 0xf099f7da, -+ 0x00af03fe, -+ 0xf40e057c, -+ 0x0a89ff11, -+ 0x0bd5fff6, -+ 0xf75c0000, -+ 0xf64a0008, -+ 0x0fc4fe9a, -+ 0x0662fd12, -+ 0x01a709a3, -+ 0x04ac0279, -+ 0xeebf004e, -+ 0xff6300d0, -+ 0xf9e4f9e4, -+ 0x00d0ff63, -+ 0x004eeebf, -+ 0x027904ac, -+ 0x09a301a7, -+ 0xfd120662, -+ 0xfe9a0fc4, -+ 0x0008f64a, -+ 0x0000f75c, -+ 0xfff60bd5, -+ 0xff110a89, -+ 0x057cf40e, -+ 0x03fe00af, -+ 0xf7daf099, -+ 0x0010fc91, -+ 0xf7be063d, -+ 0x00000000, -+ 0xf9c30842, -+ 0x036ffff0, -+ 0x0f670826, -+ 0xff51fc02, -+ 0x0bf2fa84, -+ 0xf57700ef, -+ 0xf42b000a, -+ 0x08a40000, -+ 0x09b6fff8, -+ 0xf03c0166, -+ 0xf99e02ee, -+ 0xfe59f65d, -+ 0xfb54fd87, -+ 0x1141ffb2, -+ 0x009dff30, -+ 0x05e30000, -+ 0xff060705, -+ 0x085408a0, -+ 0xf425fc59, -+ 0xfa1d042a, -+ 0xfc78f67a, -+ 0xf7acf60e, -+ 0x075a0766, -+ 0x05e305e3, -+ 0xf8a6f89a, -+ 0xf7acf60e, -+ 0x03880986, -+ 0xfa1d042a, -+ 0x0bdb03a7, -+ 0x085408a0, -+ 0x00faf8fb, -+ 0x05e30000, -+ 0xff06f8fb, -+ 0x0854f760, -+ 0xf42503a7, -+ 0xfa1dfbd6, -+ 0xfc780986, -+ 0xf7ac09f2, -+ 0x075af89a, -+ 0x05e3fa1d, -+ 0xf8a60766, -+ 0xf7ac09f2, -+ 0x0388f67a, -+ 0xfa1dfbd6, -+ 0x0bdbfc59, -+ 0x0854f760, -+ 0x00fa0705, -+ 0x05e30000, -+ 0xff060705, -+ 0x085408a0, -+ 0xf425fc59, -+ 0xfa1d042a, -+ 0xfc78f67a, -+ 0xf7acf60e, -+ 0x075a0766, -+ 0x05e305e3, -+ 0xf8a6f89a, -+ 0xf7acf60e, -+ 0x03880986, -+ 0xfa1d042a, -+ 0x0bdb03a7, -+ 0x085408a0, -+ 0x00faf8fb, -+ 0x05e30000, -+ 0xff06f8fb, -+ 0x0854f760, -+ 0xf42503a7, -+ 0xfa1dfbd6, -+ 0xfc780986, -+ 0xf7ac09f2, -+ 0x075af89a, -+ 0x05e3fa1d, -+ 0xf8a60766, -+ 0xf7ac09f2, -+ 0x0388f67a, -+ 0xfa1dfbd6, -+ 0x0bdbfc59, -+ 0x0854f760, -+ 0x00fa0705, -+ 0xfa58fa58, -+ 0xf8f0fe00, -+ 0x0448073d, -+ 0xfdc9fe46, -+ 0xf9910258, -+ 0x089d0407, -+ 0xfd5cf71a, -+ 0x02affde0, -+ 0x083e0496, -+ 0xff5a0740, -+ 0xff7afd97, -+ 0x00fe01f1, -+ 0x0009082e, -+ 0xfa94ff75, -+ 0xfecdf8ea, -+ 0xffb0f693, -+ 0xfd2cfa58, -+ 0x0433ff16, -+ 0xfba405dd, -+ 0xfa610341, -+ 0x06a606cb, -+ 0x0039fd2d, -+ 0x0677fa97, -+ 0x01fa05e0, -+ 0xf896003e, -+ 0x075a068b, -+ 0x012cfc3e, -+ 0xfa23f98d, -+ 0xfc7cfd43, -+ 0xff90fc0d, -+ 0x01c10982, -+ 0x00c601d6, -+ 0xfd2cfd2c, -+ 0x01d600c6, -+ 0x098201c1, -+ 0xfc0dff90, -+ 0xfd43fc7c, -+ 0xf98dfa23, -+ 0xfc3e012c, -+ 0x068b075a, -+ 0x003ef896, -+ 0x05e001fa, -+ 0xfa970677, -+ 0xfd2d0039, -+ 0x06cb06a6, -+ 0x0341fa61, -+ 0x05ddfba4, -+ 0xff160433, -+ 0xfa58fd2c, -+ 0xf693ffb0, -+ 0xf8eafecd, -+ 0xff75fa94, -+ 0x082e0009, -+ 0x01f100fe, -+ 0xfd97ff7a, -+ 0x0740ff5a, -+ 0x0496083e, -+ 0xfde002af, -+ 0xf71afd5c, -+ 0x0407089d, -+ 0x0258f991, -+ 0xfe46fdc9, -+ 0x073d0448, -+ 0xfe00f8f0, -+ 0xfd2cfd2c, -+ 0xfce00500, -+ 0xfc09fddc, -+ 0xfe680157, -+ 0x04c70571, -+ 0xfc3aff21, -+ 0xfcd70228, -+ 0x056d0277, -+ 0x0200fe00, -+ 0x0022f927, -+ 0xfe3c032b, -+ 0xfc44ff3c, -+ 0x03e9fbdb, -+ 0x04570313, -+ 0x04c9ff5c, -+ 0x000d03b8, -+ 0xfa580000, -+ 0xfbe900d2, -+ 0xf9d0fe0b, -+ 0x0125fdf9, -+ 0x042501bf, -+ 0x0328fa2b, -+ 0xffa902f0, -+ 0xfa250157, -+ 0x0200fe00, -+ 0x03740438, -+ 0xff0405fd, -+ 0x030cfe52, -+ 0x0037fb39, -+ 0xff6904c5, -+ 0x04f8fd23, -+ 0xfd31fc1b, -+ 0xfd2cfd2c, -+ 0xfc1bfd31, -+ 0xfd2304f8, -+ 0x04c5ff69, -+ 0xfb390037, -+ 0xfe52030c, -+ 0x05fdff04, -+ 0x04380374, -+ 0xfe000200, -+ 0x0157fa25, -+ 0x02f0ffa9, -+ 0xfa2b0328, -+ 0x01bf0425, -+ 0xfdf90125, -+ 0xfe0bf9d0, -+ 0x00d2fbe9, -+ 0x0000fa58, -+ 0x03b8000d, -+ 0xff5c04c9, -+ 0x03130457, -+ 0xfbdb03e9, -+ 0xff3cfc44, -+ 0x032bfe3c, -+ 0xf9270022, -+ 0xfe000200, -+ 0x0277056d, -+ 0x0228fcd7, -+ 0xff21fc3a, -+ 0x057104c7, -+ 0x0157fe68, -+ 0xfddcfc09, -+ 0x0500fce0, -+ 0xfd2cfd2c, -+ 0x0500fce0, -+ 0xfddcfc09, -+ 0x0157fe68, -+ 0x057104c7, -+ 0xff21fc3a, -+ 0x0228fcd7, -+ 0x0277056d, -+ 0xfe000200, -+ 0xf9270022, -+ 0x032bfe3c, -+ 0xff3cfc44, -+ 0xfbdb03e9, -+ 0x03130457, -+ 0xff5c04c9, -+ 0x03b8000d, -+ 0x0000fa58, -+ 0x00d2fbe9, -+ 0xfe0bf9d0, -+ 0xfdf90125, -+ 0x01bf0425, -+ 0xfa2b0328, -+ 0x02f0ffa9, -+ 0x0157fa25, -+ 0xfe000200, -+ 0x04380374, -+ 0x05fdff04, -+ 0xfe52030c, -+ 0xfb390037, -+ 0x04c5ff69, -+ 0xfd2304f8, -+ 0xfc1bfd31, -+ 0xfd2cfd2c, -+ 0xfd31fc1b, -+ 0x04f8fd23, -+ 0xff6904c5, -+ 0x0037fb39, -+ 0x030cfe52, -+ 0xff0405fd, -+ 0x03740438, -+ 0x0200fe00, -+ 0xfa250157, -+ 0xffa902f0, -+ 0x0328fa2b, -+ 0x042501bf, -+ 0x0125fdf9, -+ 0xf9d0fe0b, -+ 0xfbe900d2, -+ 0xfa580000, -+ 0x000d03b8, -+ 0x04c9ff5c, -+ 0x04570313, -+ 0x03e9fbdb, -+ 0xfc44ff3c, -+ 0xfe3c032b, -+ 0x0022f927, -+ 0x0200fe00, -+ 0x056d0277, -+ 0xfcd70228, -+ 0xfc3aff21, -+ 0x04c70571, -+ 0xfe680157, -+ 0xfc09fddc, -+ 0xfce00500, -+ 0x05a80000, -+ 0xff1006be, -+ 0x0800084a, -+ 0xf49cfc7e, -+ 0xfa580400, -+ 0xfc9cf6da, -+ 0xf800f672, -+ 0x0710071c, -+ 0x05a805a8, -+ 0xf8f0f8e4, -+ 0xf800f672, -+ 0x03640926, -+ 0xfa580400, -+ 0x0b640382, -+ 0x0800084a, -+ 0x00f0f942, -+ 0x05a80000, -+ 0xff10f942, -+ 0x0800f7b6, -+ 0xf49c0382, -+ 0xfa58fc00, -+ 0xfc9c0926, -+ 0xf800098e, -+ 0x0710f8e4, -+ 0x05a8fa58, -+ 0xf8f0071c, -+ 0xf800098e, -+ 0x0364f6da, -+ 0xfa58fc00, -+ 0x0b64fc7e, -+ 0x0800f7b6, -+ 0x00f006be, -+ 0x05a80000, -+ 0xff1006be, -+ 0x0800084a, -+ 0xf49cfc7e, -+ 0xfa580400, -+ 0xfc9cf6da, -+ 0xf800f672, -+ 0x0710071c, -+ 0x05a805a8, -+ 0xf8f0f8e4, -+ 0xf800f672, -+ 0x03640926, -+ 0xfa580400, -+ 0x0b640382, -+ 0x0800084a, -+ 0x00f0f942, -+ 0x05a80000, -+ 0xff10f942, -+ 0x0800f7b6, -+ 0xf49c0382, -+ 0xfa58fc00, -+ 0xfc9c0926, -+ 0xf800098e, -+ 0x0710f8e4, -+ 0x05a8fa58, -+ 0xf8f0071c, -+ 0xf800098e, -+ 0x0364f6da, -+ 0xfa58fc00, -+ 0x0b64fc7e, -+ 0x0800f7b6, -+ 0x00f006be, -+}; -+ -+const u32 noise_var_tbl_rev3[] = { -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+ 0x02110211, -+ 0x0000014d, -+}; -+ -+static const u16 mcs_tbl_rev3[] = { -+ 0x0000, -+ 0x0008, -+ 0x000a, -+ 0x0010, -+ 0x0012, -+ 0x0019, -+ 0x001a, -+ 0x001c, -+ 0x0080, -+ 0x0088, -+ 0x008a, -+ 0x0090, -+ 0x0092, -+ 0x0099, -+ 0x009a, -+ 0x009c, -+ 0x0100, -+ 0x0108, -+ 0x010a, -+ 0x0110, -+ 0x0112, -+ 0x0119, -+ 0x011a, -+ 0x011c, -+ 0x0180, -+ 0x0188, -+ 0x018a, -+ 0x0190, -+ 0x0192, -+ 0x0199, -+ 0x019a, -+ 0x019c, -+ 0x0000, -+ 0x0098, -+ 0x00a0, -+ 0x00a8, -+ 0x009a, -+ 0x00a2, -+ 0x00aa, -+ 0x0120, -+ 0x0128, -+ 0x0128, -+ 0x0130, -+ 0x0138, -+ 0x0138, -+ 0x0140, -+ 0x0122, -+ 0x012a, -+ 0x012a, -+ 0x0132, -+ 0x013a, -+ 0x013a, -+ 0x0142, -+ 0x01a8, -+ 0x01b0, -+ 0x01b8, -+ 0x01b0, -+ 0x01b8, -+ 0x01c0, -+ 0x01c8, -+ 0x01c0, -+ 0x01c8, -+ 0x01d0, -+ 0x01d0, -+ 0x01d8, -+ 0x01aa, -+ 0x01b2, -+ 0x01ba, -+ 0x01b2, -+ 0x01ba, -+ 0x01c2, -+ 0x01ca, -+ 0x01c2, -+ 0x01ca, -+ 0x01d2, -+ 0x01d2, -+ 0x01da, -+ 0x0001, -+ 0x0002, -+ 0x0004, -+ 0x0009, -+ 0x000c, -+ 0x0011, -+ 0x0014, -+ 0x0018, -+ 0x0020, -+ 0x0021, -+ 0x0022, -+ 0x0024, -+ 0x0081, -+ 0x0082, -+ 0x0084, -+ 0x0089, -+ 0x008c, -+ 0x0091, -+ 0x0094, -+ 0x0098, -+ 0x00a0, -+ 0x00a1, -+ 0x00a2, -+ 0x00a4, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+ 0x0007, -+}; -+ -+static const u32 tdi_tbl20_ant0_rev3[] = { -+ 0x00091226, -+ 0x000a1429, -+ 0x000b56ad, -+ 0x000c58b0, -+ 0x000d5ab3, -+ 0x000e9cb6, -+ 0x000f9eba, -+ 0x0000c13d, -+ 0x00020301, -+ 0x00030504, -+ 0x00040708, -+ 0x0005090b, -+ 0x00064b8e, -+ 0x00095291, -+ 0x000a5494, -+ 0x000b9718, -+ 0x000c9927, -+ 0x000d9b2a, -+ 0x000edd2e, -+ 0x000fdf31, -+ 0x000101b4, -+ 0x000243b7, -+ 0x000345bb, -+ 0x000447be, -+ 0x00058982, -+ 0x00068c05, -+ 0x00099309, -+ 0x000a950c, -+ 0x000bd78f, -+ 0x000cd992, -+ 0x000ddb96, -+ 0x000f1d99, -+ 0x00005fa8, -+ 0x0001422c, -+ 0x0002842f, -+ 0x00038632, -+ 0x00048835, -+ 0x0005ca38, -+ 0x0006ccbc, -+ 0x0009d3bf, -+ 0x000b1603, -+ 0x000c1806, -+ 0x000d1a0a, -+ 0x000e1c0d, -+ 0x000f5e10, -+ 0x00008093, -+ 0x00018297, -+ 0x0002c49a, -+ 0x0003c680, -+ 0x0004c880, -+ 0x00060b00, -+ 0x00070d00, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+static const u32 tdi_tbl20_ant1_rev3[] = { -+ 0x00014b26, -+ 0x00028d29, -+ 0x000393ad, -+ 0x00049630, -+ 0x0005d833, -+ 0x0006da36, -+ 0x00099c3a, -+ 0x000a9e3d, -+ 0x000bc081, -+ 0x000cc284, -+ 0x000dc488, -+ 0x000f068b, -+ 0x0000488e, -+ 0x00018b91, -+ 0x0002d214, -+ 0x0003d418, -+ 0x0004d6a7, -+ 0x000618aa, -+ 0x00071aae, -+ 0x0009dcb1, -+ 0x000b1eb4, -+ 0x000c0137, -+ 0x000d033b, -+ 0x000e053e, -+ 0x000f4702, -+ 0x00008905, -+ 0x00020c09, -+ 0x0003128c, -+ 0x0004148f, -+ 0x00051712, -+ 0x00065916, -+ 0x00091b19, -+ 0x000a1d28, -+ 0x000b5f2c, -+ 0x000c41af, -+ 0x000d43b2, -+ 0x000e85b5, -+ 0x000f87b8, -+ 0x0000c9bc, -+ 0x00024cbf, -+ 0x00035303, -+ 0x00045506, -+ 0x0005978a, -+ 0x0006998d, -+ 0x00095b90, -+ 0x000a5d93, -+ 0x000b9f97, -+ 0x000c821a, -+ 0x000d8400, -+ 0x000ec600, -+ 0x000fc800, -+ 0x00010a00, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+static const u32 tdi_tbl40_ant0_rev3[] = { -+ 0x0011a346, -+ 0x00136ccf, -+ 0x0014f5d9, -+ 0x001641e2, -+ 0x0017cb6b, -+ 0x00195475, -+ 0x001b2383, -+ 0x001cad0c, -+ 0x001e7616, -+ 0x0000821f, -+ 0x00020ba8, -+ 0x0003d4b2, -+ 0x00056447, -+ 0x00072dd0, -+ 0x0008b6da, -+ 0x000a02e3, -+ 0x000b8c6c, -+ 0x000d15f6, -+ 0x0011e484, -+ 0x0013ae0d, -+ 0x00153717, -+ 0x00168320, -+ 0x00180ca9, -+ 0x00199633, -+ 0x001b6548, -+ 0x001ceed1, -+ 0x001eb7db, -+ 0x0000c3e4, -+ 0x00024d6d, -+ 0x000416f7, -+ 0x0005a585, -+ 0x00076f0f, -+ 0x0008f818, -+ 0x000a4421, -+ 0x000bcdab, -+ 0x000d9734, -+ 0x00122649, -+ 0x0013efd2, -+ 0x001578dc, -+ 0x0016c4e5, -+ 0x00184e6e, -+ 0x001a17f8, -+ 0x001ba686, -+ 0x001d3010, -+ 0x001ef999, -+ 0x00010522, -+ 0x00028eac, -+ 0x00045835, -+ 0x0005e74a, -+ 0x0007b0d3, -+ 0x00093a5d, -+ 0x000a85e6, -+ 0x000c0f6f, -+ 0x000dd8f9, -+ 0x00126787, -+ 0x00143111, -+ 0x0015ba9a, -+ 0x00170623, -+ 0x00188fad, -+ 0x001a5936, -+ 0x001be84b, -+ 0x001db1d4, -+ 0x001f3b5e, -+ 0x000146e7, -+ 0x00031070, -+ 0x000499fa, -+ 0x00062888, -+ 0x0007f212, -+ 0x00097b9b, -+ 0x000ac7a4, -+ 0x000c50ae, -+ 0x000e1a37, -+ 0x0012a94c, -+ 0x001472d5, -+ 0x0015fc5f, -+ 0x00174868, -+ 0x0018d171, -+ 0x001a9afb, -+ 0x001c2989, -+ 0x001df313, -+ 0x001f7c9c, -+ 0x000188a5, -+ 0x000351af, -+ 0x0004db38, -+ 0x0006aa4d, -+ 0x000833d7, -+ 0x0009bd60, -+ 0x000b0969, -+ 0x000c9273, -+ 0x000e5bfc, -+ 0x00132a8a, -+ 0x0014b414, -+ 0x00163d9d, -+ 0x001789a6, -+ 0x001912b0, -+ 0x001adc39, -+ 0x001c6bce, -+ 0x001e34d8, -+ 0x001fbe61, -+ 0x0001ca6a, -+ 0x00039374, -+ 0x00051cfd, -+ 0x0006ec0b, -+ 0x00087515, -+ 0x0009fe9e, -+ 0x000b4aa7, -+ 0x000cd3b1, -+ 0x000e9d3a, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+static const u32 tdi_tbl40_ant1_rev3[] = { -+ 0x001edb36, -+ 0x000129ca, -+ 0x0002b353, -+ 0x00047cdd, -+ 0x0005c8e6, -+ 0x000791ef, -+ 0x00091bf9, -+ 0x000aaa07, -+ 0x000c3391, -+ 0x000dfd1a, -+ 0x00120923, -+ 0x0013d22d, -+ 0x00155c37, -+ 0x0016eacb, -+ 0x00187454, -+ 0x001a3dde, -+ 0x001b89e7, -+ 0x001d12f0, -+ 0x001f1cfa, -+ 0x00016b88, -+ 0x00033492, -+ 0x0004be1b, -+ 0x00060a24, -+ 0x0007d32e, -+ 0x00095d38, -+ 0x000aec4c, -+ 0x000c7555, -+ 0x000e3edf, -+ 0x00124ae8, -+ 0x001413f1, -+ 0x0015a37b, -+ 0x00172c89, -+ 0x0018b593, -+ 0x001a419c, -+ 0x001bcb25, -+ 0x001d942f, -+ 0x001f63b9, -+ 0x0001ad4d, -+ 0x00037657, -+ 0x0004c260, -+ 0x00068be9, -+ 0x000814f3, -+ 0x0009a47c, -+ 0x000b2d8a, -+ 0x000cb694, -+ 0x000e429d, -+ 0x00128c26, -+ 0x001455b0, -+ 0x0015e4ba, -+ 0x00176e4e, -+ 0x0018f758, -+ 0x001a8361, -+ 0x001c0cea, -+ 0x001dd674, -+ 0x001fa57d, -+ 0x0001ee8b, -+ 0x0003b795, -+ 0x0005039e, -+ 0x0006cd27, -+ 0x000856b1, -+ 0x0009e5c6, -+ 0x000b6f4f, -+ 0x000cf859, -+ 0x000e8462, -+ 0x00130deb, -+ 0x00149775, -+ 0x00162603, -+ 0x0017af8c, -+ 0x00193896, -+ 0x001ac49f, -+ 0x001c4e28, -+ 0x001e17b2, -+ 0x0000a6c7, -+ 0x00023050, -+ 0x0003f9da, -+ 0x00054563, -+ 0x00070eec, -+ 0x00089876, -+ 0x000a2704, -+ 0x000bb08d, -+ 0x000d3a17, -+ 0x001185a0, -+ 0x00134f29, -+ 0x0014d8b3, -+ 0x001667c8, -+ 0x0017f151, -+ 0x00197adb, -+ 0x001b0664, -+ 0x001c8fed, -+ 0x001e5977, -+ 0x0000e805, -+ 0x0002718f, -+ 0x00043b18, -+ 0x000586a1, -+ 0x0007502b, -+ 0x0008d9b4, -+ 0x000a68c9, -+ 0x000bf252, -+ 0x000dbbdc, -+ 0x0011c7e5, -+ 0x001390ee, -+ 0x00151a78, -+ 0x0016a906, -+ 0x00183290, -+ 0x0019bc19, -+ 0x001b4822, -+ 0x001cd12c, -+ 0x001e9ab5, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+static const u32 pltlut_tbl_rev3[] = { -+ 0x76540213, -+ 0x62407351, -+ 0x76543210, -+ 0x76540213, -+ 0x76540213, -+ 0x76430521, -+}; -+ -+static const u32 chanest_tbl_rev3[] = { -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x44444444, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+ 0x10101010, -+}; -+ -+static const u8 frame_lut_rev3[] = { -+ 0x02, -+ 0x04, -+ 0x14, -+ 0x14, -+ 0x03, -+ 0x05, -+ 0x16, -+ 0x16, -+ 0x0a, -+ 0x0c, -+ 0x1c, -+ 0x1c, -+ 0x0b, -+ 0x0d, -+ 0x1e, -+ 0x1e, -+ 0x06, -+ 0x08, -+ 0x18, -+ 0x18, -+ 0x07, -+ 0x09, -+ 0x1a, -+ 0x1a, -+ 0x0e, -+ 0x10, -+ 0x20, -+ 0x28, -+ 0x0f, -+ 0x11, -+ 0x22, -+ 0x2a, -+}; -+ -+static const u8 est_pwr_lut_core0_rev3[] = { -+ 0x55, -+ 0x54, -+ 0x54, -+ 0x53, -+ 0x52, -+ 0x52, -+ 0x51, -+ 0x51, -+ 0x50, -+ 0x4f, -+ 0x4f, -+ 0x4e, -+ 0x4e, -+ 0x4d, -+ 0x4c, -+ 0x4c, -+ 0x4b, -+ 0x4a, -+ 0x49, -+ 0x49, -+ 0x48, -+ 0x47, -+ 0x46, -+ 0x46, -+ 0x45, -+ 0x44, -+ 0x43, -+ 0x42, -+ 0x41, -+ 0x40, -+ 0x40, -+ 0x3f, -+ 0x3e, -+ 0x3d, -+ 0x3c, -+ 0x3a, -+ 0x39, -+ 0x38, -+ 0x37, -+ 0x36, -+ 0x35, -+ 0x33, -+ 0x32, -+ 0x31, -+ 0x2f, -+ 0x2e, -+ 0x2c, -+ 0x2b, -+ 0x29, -+ 0x27, -+ 0x25, -+ 0x23, -+ 0x21, -+ 0x1f, -+ 0x1d, -+ 0x1a, -+ 0x18, -+ 0x15, -+ 0x12, -+ 0x0e, -+ 0x0b, -+ 0x07, -+ 0x02, -+ 0xfd, -+}; -+ -+static const u8 est_pwr_lut_core1_rev3[] = { -+ 0x55, -+ 0x54, -+ 0x54, -+ 0x53, -+ 0x52, -+ 0x52, -+ 0x51, -+ 0x51, -+ 0x50, -+ 0x4f, -+ 0x4f, -+ 0x4e, -+ 0x4e, -+ 0x4d, -+ 0x4c, -+ 0x4c, -+ 0x4b, -+ 0x4a, -+ 0x49, -+ 0x49, -+ 0x48, -+ 0x47, -+ 0x46, -+ 0x46, -+ 0x45, -+ 0x44, -+ 0x43, -+ 0x42, -+ 0x41, -+ 0x40, -+ 0x40, -+ 0x3f, -+ 0x3e, -+ 0x3d, -+ 0x3c, -+ 0x3a, -+ 0x39, -+ 0x38, -+ 0x37, -+ 0x36, -+ 0x35, -+ 0x33, -+ 0x32, -+ 0x31, -+ 0x2f, -+ 0x2e, -+ 0x2c, -+ 0x2b, -+ 0x29, -+ 0x27, -+ 0x25, -+ 0x23, -+ 0x21, -+ 0x1f, -+ 0x1d, -+ 0x1a, -+ 0x18, -+ 0x15, -+ 0x12, -+ 0x0e, -+ 0x0b, -+ 0x07, -+ 0x02, -+ 0xfd, -+}; -+ -+static const u8 adj_pwr_lut_core0_rev3[] = { -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+}; -+ -+static const u8 adj_pwr_lut_core1_rev3[] = { -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+ 0x00, -+}; -+ -+static const u32 gainctrl_lut_core0_rev3[] = { -+ 0x5bf70044, -+ 0x5bf70042, -+ 0x5bf70040, -+ 0x5bf7003e, -+ 0x5bf7003c, -+ 0x5bf7003b, -+ 0x5bf70039, -+ 0x5bf70037, -+ 0x5bf70036, -+ 0x5bf70034, -+ 0x5bf70033, -+ 0x5bf70031, -+ 0x5bf70030, -+ 0x5ba70044, -+ 0x5ba70042, -+ 0x5ba70040, -+ 0x5ba7003e, -+ 0x5ba7003c, -+ 0x5ba7003b, -+ 0x5ba70039, -+ 0x5ba70037, -+ 0x5ba70036, -+ 0x5ba70034, -+ 0x5ba70033, -+ 0x5b770044, -+ 0x5b770042, -+ 0x5b770040, -+ 0x5b77003e, -+ 0x5b77003c, -+ 0x5b77003b, -+ 0x5b770039, -+ 0x5b770037, -+ 0x5b770036, -+ 0x5b770034, -+ 0x5b770033, -+ 0x5b770031, -+ 0x5b770030, -+ 0x5b77002f, -+ 0x5b77002d, -+ 0x5b77002c, -+ 0x5b470044, -+ 0x5b470042, -+ 0x5b470040, -+ 0x5b47003e, -+ 0x5b47003c, -+ 0x5b47003b, -+ 0x5b470039, -+ 0x5b470037, -+ 0x5b470036, -+ 0x5b470034, -+ 0x5b470033, -+ 0x5b470031, -+ 0x5b470030, -+ 0x5b47002f, -+ 0x5b47002d, -+ 0x5b47002c, -+ 0x5b47002b, -+ 0x5b47002a, -+ 0x5b270044, -+ 0x5b270042, -+ 0x5b270040, -+ 0x5b27003e, -+ 0x5b27003c, -+ 0x5b27003b, -+ 0x5b270039, -+ 0x5b270037, -+ 0x5b270036, -+ 0x5b270034, -+ 0x5b270033, -+ 0x5b270031, -+ 0x5b270030, -+ 0x5b27002f, -+ 0x5b170044, -+ 0x5b170042, -+ 0x5b170040, -+ 0x5b17003e, -+ 0x5b17003c, -+ 0x5b17003b, -+ 0x5b170039, -+ 0x5b170037, -+ 0x5b170036, -+ 0x5b170034, -+ 0x5b170033, -+ 0x5b170031, -+ 0x5b170030, -+ 0x5b17002f, -+ 0x5b17002d, -+ 0x5b17002c, -+ 0x5b17002b, -+ 0x5b17002a, -+ 0x5b170028, -+ 0x5b170027, -+ 0x5b170026, -+ 0x5b170025, -+ 0x5b170024, -+ 0x5b170023, -+ 0x5b070044, -+ 0x5b070042, -+ 0x5b070040, -+ 0x5b07003e, -+ 0x5b07003c, -+ 0x5b07003b, -+ 0x5b070039, -+ 0x5b070037, -+ 0x5b070036, -+ 0x5b070034, -+ 0x5b070033, -+ 0x5b070031, -+ 0x5b070030, -+ 0x5b07002f, -+ 0x5b07002d, -+ 0x5b07002c, -+ 0x5b07002b, -+ 0x5b07002a, -+ 0x5b070028, -+ 0x5b070027, -+ 0x5b070026, -+ 0x5b070025, -+ 0x5b070024, -+ 0x5b070023, -+ 0x5b070022, -+ 0x5b070021, -+ 0x5b070020, -+ 0x5b07001f, -+ 0x5b07001e, -+ 0x5b07001d, -+ 0x5b07001d, -+ 0x5b07001c, -+}; -+ -+static const u32 gainctrl_lut_core1_rev3[] = { -+ 0x5bf70044, -+ 0x5bf70042, -+ 0x5bf70040, -+ 0x5bf7003e, -+ 0x5bf7003c, -+ 0x5bf7003b, -+ 0x5bf70039, -+ 0x5bf70037, -+ 0x5bf70036, -+ 0x5bf70034, -+ 0x5bf70033, -+ 0x5bf70031, -+ 0x5bf70030, -+ 0x5ba70044, -+ 0x5ba70042, -+ 0x5ba70040, -+ 0x5ba7003e, -+ 0x5ba7003c, -+ 0x5ba7003b, -+ 0x5ba70039, -+ 0x5ba70037, -+ 0x5ba70036, -+ 0x5ba70034, -+ 0x5ba70033, -+ 0x5b770044, -+ 0x5b770042, -+ 0x5b770040, -+ 0x5b77003e, -+ 0x5b77003c, -+ 0x5b77003b, -+ 0x5b770039, -+ 0x5b770037, -+ 0x5b770036, -+ 0x5b770034, -+ 0x5b770033, -+ 0x5b770031, -+ 0x5b770030, -+ 0x5b77002f, -+ 0x5b77002d, -+ 0x5b77002c, -+ 0x5b470044, -+ 0x5b470042, -+ 0x5b470040, -+ 0x5b47003e, -+ 0x5b47003c, -+ 0x5b47003b, -+ 0x5b470039, -+ 0x5b470037, -+ 0x5b470036, -+ 0x5b470034, -+ 0x5b470033, -+ 0x5b470031, -+ 0x5b470030, -+ 0x5b47002f, -+ 0x5b47002d, -+ 0x5b47002c, -+ 0x5b47002b, -+ 0x5b47002a, -+ 0x5b270044, -+ 0x5b270042, -+ 0x5b270040, -+ 0x5b27003e, -+ 0x5b27003c, -+ 0x5b27003b, -+ 0x5b270039, -+ 0x5b270037, -+ 0x5b270036, -+ 0x5b270034, -+ 0x5b270033, -+ 0x5b270031, -+ 0x5b270030, -+ 0x5b27002f, -+ 0x5b170044, -+ 0x5b170042, -+ 0x5b170040, -+ 0x5b17003e, -+ 0x5b17003c, -+ 0x5b17003b, -+ 0x5b170039, -+ 0x5b170037, -+ 0x5b170036, -+ 0x5b170034, -+ 0x5b170033, -+ 0x5b170031, -+ 0x5b170030, -+ 0x5b17002f, -+ 0x5b17002d, -+ 0x5b17002c, -+ 0x5b17002b, -+ 0x5b17002a, -+ 0x5b170028, -+ 0x5b170027, -+ 0x5b170026, -+ 0x5b170025, -+ 0x5b170024, -+ 0x5b170023, -+ 0x5b070044, -+ 0x5b070042, -+ 0x5b070040, -+ 0x5b07003e, -+ 0x5b07003c, -+ 0x5b07003b, -+ 0x5b070039, -+ 0x5b070037, -+ 0x5b070036, -+ 0x5b070034, -+ 0x5b070033, -+ 0x5b070031, -+ 0x5b070030, -+ 0x5b07002f, -+ 0x5b07002d, -+ 0x5b07002c, -+ 0x5b07002b, -+ 0x5b07002a, -+ 0x5b070028, -+ 0x5b070027, -+ 0x5b070026, -+ 0x5b070025, -+ 0x5b070024, -+ 0x5b070023, -+ 0x5b070022, -+ 0x5b070021, -+ 0x5b070020, -+ 0x5b07001f, -+ 0x5b07001e, -+ 0x5b07001d, -+ 0x5b07001d, -+ 0x5b07001c, -+}; -+ -+static const u32 iq_lut_core0_rev3[] = { -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+static const u32 iq_lut_core1_rev3[] = { -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+static const u16 loft_lut_core0_rev3[] = { -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+}; -+ -+static const u16 loft_lut_core1_rev3[] = { -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+ 0x0000, -+}; -+ -+static const u16 papd_comp_rfpwr_tbl_core0_rev3[] = { -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+}; -+ -+static const u16 papd_comp_rfpwr_tbl_core1_rev3[] = { -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x0036, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x002a, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x001e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x000e, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01fc, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01ee, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+ 0x01d6, -+}; -+ -+static const u32 papd_comp_epsilon_tbl_core0_rev3[] = { -+ 0x00000000, -+ 0x00001fa0, -+ 0x00019f78, -+ 0x0001df7e, -+ 0x03fa9f86, -+ 0x03fd1f90, -+ 0x03fe5f8a, -+ 0x03fb1f94, -+ 0x03fd9fa0, -+ 0x00009f98, -+ 0x03fd1fac, -+ 0x03ff9fa2, -+ 0x03fe9fae, -+ 0x00001fae, -+ 0x03fddfb4, -+ 0x03ff1fb8, -+ 0x03ff9fbc, -+ 0x03ffdfbe, -+ 0x03fe9fc2, -+ 0x03fedfc6, -+ 0x03fedfc6, -+ 0x03ff9fc8, -+ 0x03ff5fc6, -+ 0x03fedfc2, -+ 0x03ff9fc0, -+ 0x03ff5fac, -+ 0x03ff5fac, -+ 0x03ff9fa2, -+ 0x03ff9fa6, -+ 0x03ff9faa, -+ 0x03ff5fb0, -+ 0x03ff5fb4, -+ 0x03ff1fca, -+ 0x03ff5fce, -+ 0x03fcdfdc, -+ 0x03fb4006, -+ 0x00000030, -+ 0x03ff808a, -+ 0x03ff80da, -+ 0x0000016c, -+ 0x03ff8318, -+ 0x03ff063a, -+ 0x03fd8bd6, -+ 0x00014ffe, -+ 0x00034ffe, -+ 0x00034ffe, -+ 0x0003cffe, -+ 0x00040ffe, -+ 0x00040ffe, -+ 0x0003cffe, -+ 0x0003cffe, -+ 0x00020ffe, -+ 0x03fe0ffe, -+ 0x03fdcffe, -+ 0x03f94ffe, -+ 0x03f54ffe, -+ 0x03f44ffe, -+ 0x03ef8ffe, -+ 0x03ee0ffe, -+ 0x03ebcffe, -+ 0x03e8cffe, -+ 0x03e74ffe, -+ 0x03e4cffe, -+ 0x03e38ffe, -+}; -+ -+static const u32 papd_cal_scalars_tbl_core0_rev3[] = { -+ 0x05af005a, -+ 0x0571005e, -+ 0x05040066, -+ 0x04bd006c, -+ 0x047d0072, -+ 0x04430078, -+ 0x03f70081, -+ 0x03cb0087, -+ 0x03870091, -+ 0x035e0098, -+ 0x032e00a1, -+ 0x030300aa, -+ 0x02d800b4, -+ 0x02ae00bf, -+ 0x028900ca, -+ 0x026400d6, -+ 0x024100e3, -+ 0x022200f0, -+ 0x020200ff, -+ 0x01e5010e, -+ 0x01ca011e, -+ 0x01b0012f, -+ 0x01990140, -+ 0x01830153, -+ 0x016c0168, -+ 0x0158017d, -+ 0x01450193, -+ 0x013301ab, -+ 0x012101c5, -+ 0x011101e0, -+ 0x010201fc, -+ 0x00f4021a, -+ 0x00e6011d, -+ 0x00d9012e, -+ 0x00cd0140, -+ 0x00c20153, -+ 0x00b70167, -+ 0x00ac017c, -+ 0x00a30193, -+ 0x009a01ab, -+ 0x009101c4, -+ 0x008901df, -+ 0x008101fb, -+ 0x007a0219, -+ 0x00730239, -+ 0x006d025b, -+ 0x0067027e, -+ 0x006102a4, -+ 0x005c02cc, -+ 0x005602f6, -+ 0x00520323, -+ 0x004d0353, -+ 0x00490385, -+ 0x004503bb, -+ 0x004103f3, -+ 0x003d042f, -+ 0x003a046f, -+ 0x003704b2, -+ 0x003404f9, -+ 0x00310545, -+ 0x002e0596, -+ 0x002b05f5, -+ 0x00290640, -+ 0x002606a4, -+}; -+ -+static const u32 papd_comp_epsilon_tbl_core1_rev3[] = { -+ 0x00000000, -+ 0x00001fa0, -+ 0x00019f78, -+ 0x0001df7e, -+ 0x03fa9f86, -+ 0x03fd1f90, -+ 0x03fe5f8a, -+ 0x03fb1f94, -+ 0x03fd9fa0, -+ 0x00009f98, -+ 0x03fd1fac, -+ 0x03ff9fa2, -+ 0x03fe9fae, -+ 0x00001fae, -+ 0x03fddfb4, -+ 0x03ff1fb8, -+ 0x03ff9fbc, -+ 0x03ffdfbe, -+ 0x03fe9fc2, -+ 0x03fedfc6, -+ 0x03fedfc6, -+ 0x03ff9fc8, -+ 0x03ff5fc6, -+ 0x03fedfc2, -+ 0x03ff9fc0, -+ 0x03ff5fac, -+ 0x03ff5fac, -+ 0x03ff9fa2, -+ 0x03ff9fa6, -+ 0x03ff9faa, -+ 0x03ff5fb0, -+ 0x03ff5fb4, -+ 0x03ff1fca, -+ 0x03ff5fce, -+ 0x03fcdfdc, -+ 0x03fb4006, -+ 0x00000030, -+ 0x03ff808a, -+ 0x03ff80da, -+ 0x0000016c, -+ 0x03ff8318, -+ 0x03ff063a, -+ 0x03fd8bd6, -+ 0x00014ffe, -+ 0x00034ffe, -+ 0x00034ffe, -+ 0x0003cffe, -+ 0x00040ffe, -+ 0x00040ffe, -+ 0x0003cffe, -+ 0x0003cffe, -+ 0x00020ffe, -+ 0x03fe0ffe, -+ 0x03fdcffe, -+ 0x03f94ffe, -+ 0x03f54ffe, -+ 0x03f44ffe, -+ 0x03ef8ffe, -+ 0x03ee0ffe, -+ 0x03ebcffe, -+ 0x03e8cffe, -+ 0x03e74ffe, -+ 0x03e4cffe, -+ 0x03e38ffe, -+}; -+ -+static const u32 papd_cal_scalars_tbl_core1_rev3[] = { -+ 0x05af005a, -+ 0x0571005e, -+ 0x05040066, -+ 0x04bd006c, -+ 0x047d0072, -+ 0x04430078, -+ 0x03f70081, -+ 0x03cb0087, -+ 0x03870091, -+ 0x035e0098, -+ 0x032e00a1, -+ 0x030300aa, -+ 0x02d800b4, -+ 0x02ae00bf, -+ 0x028900ca, -+ 0x026400d6, -+ 0x024100e3, -+ 0x022200f0, -+ 0x020200ff, -+ 0x01e5010e, -+ 0x01ca011e, -+ 0x01b0012f, -+ 0x01990140, -+ 0x01830153, -+ 0x016c0168, -+ 0x0158017d, -+ 0x01450193, -+ 0x013301ab, -+ 0x012101c5, -+ 0x011101e0, -+ 0x010201fc, -+ 0x00f4021a, -+ 0x00e6011d, -+ 0x00d9012e, -+ 0x00cd0140, -+ 0x00c20153, -+ 0x00b70167, -+ 0x00ac017c, -+ 0x00a30193, -+ 0x009a01ab, -+ 0x009101c4, -+ 0x008901df, -+ 0x008101fb, -+ 0x007a0219, -+ 0x00730239, -+ 0x006d025b, -+ 0x0067027e, -+ 0x006102a4, -+ 0x005c02cc, -+ 0x005602f6, -+ 0x00520323, -+ 0x004d0353, -+ 0x00490385, -+ 0x004503bb, -+ 0x004103f3, -+ 0x003d042f, -+ 0x003a046f, -+ 0x003704b2, -+ 0x003404f9, -+ 0x00310545, -+ 0x002e0596, -+ 0x002b05f5, -+ 0x00290640, -+ 0x002606a4, -+}; -+ -+const struct phytbl_info mimophytbl_info_rev3_volatile[] = { -+ {&ant_swctrl_tbl_rev3, -+ sizeof(ant_swctrl_tbl_rev3) / sizeof(ant_swctrl_tbl_rev3[0]), 9, 0, 16} -+ , -+}; -+ -+const struct phytbl_info mimophytbl_info_rev3_volatile1[] = { -+ {&ant_swctrl_tbl_rev3_1, -+ sizeof(ant_swctrl_tbl_rev3_1) / sizeof(ant_swctrl_tbl_rev3_1[0]), 9, 0, -+ 16} -+ , -+}; -+ -+const struct phytbl_info mimophytbl_info_rev3_volatile2[] = { -+ {&ant_swctrl_tbl_rev3_2, -+ sizeof(ant_swctrl_tbl_rev3_2) / sizeof(ant_swctrl_tbl_rev3_2[0]), 9, 0, -+ 16} -+ , -+}; -+ -+const struct phytbl_info mimophytbl_info_rev3_volatile3[] = { -+ {&ant_swctrl_tbl_rev3_3, -+ sizeof(ant_swctrl_tbl_rev3_3) / sizeof(ant_swctrl_tbl_rev3_3[0]), 9, 0, -+ 16} -+ , -+}; -+ -+const struct phytbl_info mimophytbl_info_rev3[] = { -+ {&frame_struct_rev3, -+ sizeof(frame_struct_rev3) / sizeof(frame_struct_rev3[0]), 10, 0, 32} -+ , -+ {&pilot_tbl_rev3, sizeof(pilot_tbl_rev3) / sizeof(pilot_tbl_rev3[0]), -+ 11, 0, 16} -+ , -+ {&tmap_tbl_rev3, sizeof(tmap_tbl_rev3) / sizeof(tmap_tbl_rev3[0]), 12, -+ 0, 32} -+ , -+ {&intlv_tbl_rev3, sizeof(intlv_tbl_rev3) / sizeof(intlv_tbl_rev3[0]), -+ 13, 0, 32} -+ , -+ {&tdtrn_tbl_rev3, sizeof(tdtrn_tbl_rev3) / sizeof(tdtrn_tbl_rev3[0]), -+ 14, 0, 32} -+ , -+ {&noise_var_tbl_rev3, -+ sizeof(noise_var_tbl_rev3) / sizeof(noise_var_tbl_rev3[0]), 16, 0, 32} -+ , -+ {&mcs_tbl_rev3, sizeof(mcs_tbl_rev3) / sizeof(mcs_tbl_rev3[0]), 18, 0, -+ 16} -+ , -+ {&tdi_tbl20_ant0_rev3, -+ sizeof(tdi_tbl20_ant0_rev3) / sizeof(tdi_tbl20_ant0_rev3[0]), 19, 128, -+ 32} -+ , -+ {&tdi_tbl20_ant1_rev3, -+ sizeof(tdi_tbl20_ant1_rev3) / sizeof(tdi_tbl20_ant1_rev3[0]), 19, 256, -+ 32} -+ , -+ {&tdi_tbl40_ant0_rev3, -+ sizeof(tdi_tbl40_ant0_rev3) / sizeof(tdi_tbl40_ant0_rev3[0]), 19, 640, -+ 32} -+ , -+ {&tdi_tbl40_ant1_rev3, -+ sizeof(tdi_tbl40_ant1_rev3) / sizeof(tdi_tbl40_ant1_rev3[0]), 19, 768, -+ 32} -+ , -+ {&pltlut_tbl_rev3, sizeof(pltlut_tbl_rev3) / sizeof(pltlut_tbl_rev3[0]), -+ 20, 0, 32} -+ , -+ {&chanest_tbl_rev3, -+ sizeof(chanest_tbl_rev3) / sizeof(chanest_tbl_rev3[0]), 22, 0, 32} -+ , -+ {&frame_lut_rev3, sizeof(frame_lut_rev3) / sizeof(frame_lut_rev3[0]), -+ 24, 0, 8} -+ , -+ {&est_pwr_lut_core0_rev3, -+ sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26, -+ 0, 8} -+ , -+ {&est_pwr_lut_core1_rev3, -+ sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27, -+ 0, 8} -+ , -+ {&adj_pwr_lut_core0_rev3, -+ sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26, -+ 64, 8} -+ , -+ {&adj_pwr_lut_core1_rev3, -+ sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27, -+ 64, 8} -+ , -+ {&gainctrl_lut_core0_rev3, -+ sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]), -+ 26, 192, 32} -+ , -+ {&gainctrl_lut_core1_rev3, -+ sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]), -+ 27, 192, 32} -+ , -+ {&iq_lut_core0_rev3, -+ sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32} -+ , -+ {&iq_lut_core1_rev3, -+ sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32} -+ , -+ {&loft_lut_core0_rev3, -+ sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448, -+ 16} -+ , -+ {&loft_lut_core1_rev3, -+ sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448, -+ 16} -+}; -+ -+const u32 mimophytbl_info_sz_rev3 = -+ sizeof(mimophytbl_info_rev3) / sizeof(mimophytbl_info_rev3[0]); -+const u32 mimophytbl_info_sz_rev3_volatile = -+ sizeof(mimophytbl_info_rev3_volatile) / -+ sizeof(mimophytbl_info_rev3_volatile[0]); -+const u32 mimophytbl_info_sz_rev3_volatile1 = -+ sizeof(mimophytbl_info_rev3_volatile1) / -+ sizeof(mimophytbl_info_rev3_volatile1[0]); -+const u32 mimophytbl_info_sz_rev3_volatile2 = -+ sizeof(mimophytbl_info_rev3_volatile2) / -+ sizeof(mimophytbl_info_rev3_volatile2[0]); -+const u32 mimophytbl_info_sz_rev3_volatile3 = -+ sizeof(mimophytbl_info_rev3_volatile3) / -+ sizeof(mimophytbl_info_rev3_volatile3[0]); -+ -+static const u32 tmap_tbl_rev7[] = { -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0xf1111110, -+ 0x11111111, -+ 0x11f11111, -+ 0x00000111, -+ 0x11000000, -+ 0x1111f111, -+ 0x11111111, -+ 0x111111f1, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x000aa888, -+ 0x88880000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0xa1111110, -+ 0x11111111, -+ 0x11c11111, -+ 0x00000111, -+ 0x11000000, -+ 0x1111a111, -+ 0x11111111, -+ 0x111111a1, -+ 0xa2222220, -+ 0x22222222, -+ 0x22c22222, -+ 0x00000222, -+ 0x22000000, -+ 0x2222a222, -+ 0x22222222, -+ 0x222222a2, -+ 0xf1111110, -+ 0x11111111, -+ 0x11f11111, -+ 0x00011111, -+ 0x11110000, -+ 0x1111f111, -+ 0x11111111, -+ 0x111111f1, -+ 0xa8aa88a0, -+ 0xa88888a8, -+ 0xa8a8a88a, -+ 0x00088aaa, -+ 0xaaaa0000, -+ 0xa8a8aa88, -+ 0xa88aaaaa, -+ 0xaaaa8a8a, -+ 0xaaa8aaa0, -+ 0x8aaa8aaa, -+ 0xaa8a8a8a, -+ 0x000aaa88, -+ 0x8aaa0000, -+ 0xaaa8a888, -+ 0x8aa88a8a, -+ 0x8a88a888, -+ 0x08080a00, -+ 0x0a08080a, -+ 0x080a0a08, -+ 0x00080808, -+ 0x080a0000, -+ 0x080a0808, -+ 0x080a0808, -+ 0x0a0a0a08, -+ 0xa0a0a0a0, -+ 0x80a0a080, -+ 0x8080a0a0, -+ 0x00008080, -+ 0x80a00000, -+ 0x80a080a0, -+ 0xa080a0a0, -+ 0x8080a0a0, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x99999000, -+ 0x9b9b99bb, -+ 0x9bb99999, -+ 0x9999b9b9, -+ 0x9b99bb90, -+ 0x9bbbbb9b, -+ 0x9b9b9bb9, -+ 0x00000999, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00aaa888, -+ 0x22000000, -+ 0x2222b222, -+ 0x22222222, -+ 0x222222b2, -+ 0xb2222220, -+ 0x22222222, -+ 0x22d22222, -+ 0x00000222, -+ 0x11000000, -+ 0x1111a111, -+ 0x11111111, -+ 0x111111a1, -+ 0xa1111110, -+ 0x11111111, -+ 0x11c11111, -+ 0x00000111, -+ 0x33000000, -+ 0x3333b333, -+ 0x33333333, -+ 0x333333b3, -+ 0xb3333330, -+ 0x33333333, -+ 0x33d33333, -+ 0x00000333, -+ 0x22000000, -+ 0x2222a222, -+ 0x22222222, -+ 0x222222a2, -+ 0xa2222220, -+ 0x22222222, -+ 0x22c22222, -+ 0x00000222, -+ 0x99b99b00, -+ 0x9b9b99bb, -+ 0x9bb99999, -+ 0x9999b9b9, -+ 0x9b99bb99, -+ 0x9bbbbb9b, -+ 0x9b9b9bb9, -+ 0x00000999, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa88, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x08aaa888, -+ 0x22222200, -+ 0x2222f222, -+ 0x22222222, -+ 0x222222f2, -+ 0x22222222, -+ 0x22222222, -+ 0x22f22222, -+ 0x00000222, -+ 0x11000000, -+ 0x1111f111, -+ 0x11111111, -+ 0x11111111, -+ 0xf1111111, -+ 0x11111111, -+ 0x11f11111, -+ 0x01111111, -+ 0xbb9bb900, -+ 0xb9b9bb99, -+ 0xb99bbbbb, -+ 0xbbbb9b9b, -+ 0xb9bb99bb, -+ 0xb99999b9, -+ 0xb9b9b99b, -+ 0x00000bbb, -+ 0xaa000000, -+ 0xa8a8aa88, -+ 0xa88aaaaa, -+ 0xaaaa8a8a, -+ 0xa8aa88aa, -+ 0xa88888a8, -+ 0xa8a8a88a, -+ 0x0a888aaa, -+ 0xaa000000, -+ 0xa8a8aa88, -+ 0xa88aaaaa, -+ 0xaaaa8a8a, -+ 0xa8aa88a0, -+ 0xa88888a8, -+ 0xa8a8a88a, -+ 0x00000aaa, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0xbbbbbb00, -+ 0x999bbbbb, -+ 0x9bb99b9b, -+ 0xb9b9b9bb, -+ 0xb9b99bbb, -+ 0xb9b9b9bb, -+ 0xb9bb9b99, -+ 0x00000999, -+ 0x8a000000, -+ 0xaa88a888, -+ 0xa88888aa, -+ 0xa88a8a88, -+ 0xa88aa88a, -+ 0x88a8aaaa, -+ 0xa8aa8aaa, -+ 0x0888a88a, -+ 0x0b0b0b00, -+ 0x090b0b0b, -+ 0x0b090b0b, -+ 0x0909090b, -+ 0x09090b0b, -+ 0x09090b0b, -+ 0x09090b09, -+ 0x00000909, -+ 0x0a000000, -+ 0x0a080808, -+ 0x080a080a, -+ 0x080a0a08, -+ 0x080a080a, -+ 0x0808080a, -+ 0x0a0a0a08, -+ 0x0808080a, -+ 0xb0b0b000, -+ 0x9090b0b0, -+ 0x90b09090, -+ 0xb0b0b090, -+ 0xb0b090b0, -+ 0x90b0b0b0, -+ 0xb0b09090, -+ 0x00000090, -+ 0x80000000, -+ 0xa080a080, -+ 0xa08080a0, -+ 0xa0808080, -+ 0xa080a080, -+ 0x80a0a0a0, -+ 0xa0a080a0, -+ 0x00a0a0a0, -+ 0x22000000, -+ 0x2222f222, -+ 0x22222222, -+ 0x222222f2, -+ 0xf2222220, -+ 0x22222222, -+ 0x22f22222, -+ 0x00000222, -+ 0x11000000, -+ 0x1111f111, -+ 0x11111111, -+ 0x111111f1, -+ 0xf1111110, -+ 0x11111111, -+ 0x11f11111, -+ 0x00000111, -+ 0x33000000, -+ 0x3333f333, -+ 0x33333333, -+ 0x333333f3, -+ 0xf3333330, -+ 0x33333333, -+ 0x33f33333, -+ 0x00000333, -+ 0x22000000, -+ 0x2222f222, -+ 0x22222222, -+ 0x222222f2, -+ 0xf2222220, -+ 0x22222222, -+ 0x22f22222, -+ 0x00000222, -+ 0x99000000, -+ 0x9b9b99bb, -+ 0x9bb99999, -+ 0x9999b9b9, -+ 0x9b99bb90, -+ 0x9bbbbb9b, -+ 0x9b9b9bb9, -+ 0x00000999, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x88888000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00aaa888, -+ 0x88a88a00, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa88, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x000aa888, -+ 0x88880000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa88, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x08aaa888, -+ 0x11000000, -+ 0x1111a111, -+ 0x11111111, -+ 0x111111a1, -+ 0xa1111110, -+ 0x11111111, -+ 0x11c11111, -+ 0x00000111, -+ 0x11000000, -+ 0x1111a111, -+ 0x11111111, -+ 0x111111a1, -+ 0xa1111110, -+ 0x11111111, -+ 0x11c11111, -+ 0x00000111, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x88000000, -+ 0x8a8a88aa, -+ 0x8aa88888, -+ 0x8888a8a8, -+ 0x8a88aa80, -+ 0x8aaaaa8a, -+ 0x8a8a8aa8, -+ 0x00000888, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+const u32 noise_var_tbl_rev7[] = { -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+ 0x020c020c, -+ 0x0000014d, -+}; -+ -+static const u32 papd_comp_epsilon_tbl_core0_rev7[] = { -+ 0x00000000, -+ 0x00000000, -+ 0x00016023, -+ 0x00006028, -+ 0x00034036, -+ 0x0003402e, -+ 0x0007203c, -+ 0x0006e037, -+ 0x00070030, -+ 0x0009401f, -+ 0x0009a00f, -+ 0x000b600d, -+ 0x000c8007, -+ 0x000ce007, -+ 0x00101fff, -+ 0x00121ff9, -+ 0x0012e004, -+ 0x0014dffc, -+ 0x0016dff6, -+ 0x0018dfe9, -+ 0x001b3fe5, -+ 0x001c5fd0, -+ 0x001ddfc2, -+ 0x001f1fb6, -+ 0x00207fa4, -+ 0x00219f8f, -+ 0x0022ff7d, -+ 0x00247f6c, -+ 0x0024df5b, -+ 0x00267f4b, -+ 0x0027df3b, -+ 0x0029bf3b, -+ 0x002b5f2f, -+ 0x002d3f2e, -+ 0x002f5f2a, -+ 0x002fff15, -+ 0x00315f0b, -+ 0x0032defa, -+ 0x0033beeb, -+ 0x0034fed9, -+ 0x00353ec5, -+ 0x00361eb0, -+ 0x00363e9b, -+ 0x0036be87, -+ 0x0036be70, -+ 0x0038fe67, -+ 0x0044beb2, -+ 0x00513ef3, -+ 0x00595f11, -+ 0x00669f3d, -+ 0x0078dfdf, -+ 0x00a143aa, -+ 0x01642fff, -+ 0x0162afff, -+ 0x01620fff, -+ 0x0160cfff, -+ 0x015f0fff, -+ 0x015dafff, -+ 0x015bcfff, -+ 0x015bcfff, -+ 0x015b4fff, -+ 0x015acfff, -+ 0x01590fff, -+ 0x0156cfff, -+}; -+ -+static const u32 papd_cal_scalars_tbl_core0_rev7[] = { -+ 0x0b5e002d, -+ 0x0ae2002f, -+ 0x0a3b0032, -+ 0x09a70035, -+ 0x09220038, -+ 0x08ab003b, -+ 0x081f003f, -+ 0x07a20043, -+ 0x07340047, -+ 0x06d2004b, -+ 0x067a004f, -+ 0x06170054, -+ 0x05bf0059, -+ 0x0571005e, -+ 0x051e0064, -+ 0x04d3006a, -+ 0x04910070, -+ 0x044c0077, -+ 0x040f007e, -+ 0x03d90085, -+ 0x03a1008d, -+ 0x036f0095, -+ 0x033d009e, -+ 0x030b00a8, -+ 0x02e000b2, -+ 0x02b900bc, -+ 0x029200c7, -+ 0x026d00d3, -+ 0x024900e0, -+ 0x022900ed, -+ 0x020a00fb, -+ 0x01ec010a, -+ 0x01d20119, -+ 0x01b7012a, -+ 0x019e013c, -+ 0x0188014e, -+ 0x01720162, -+ 0x015d0177, -+ 0x0149018e, -+ 0x013701a5, -+ 0x012601be, -+ 0x011501d8, -+ 0x010601f4, -+ 0x00f70212, -+ 0x00e90231, -+ 0x00dc0253, -+ 0x00d00276, -+ 0x00c4029b, -+ 0x00b902c3, -+ 0x00af02ed, -+ 0x00a50319, -+ 0x009c0348, -+ 0x0093037a, -+ 0x008b03af, -+ 0x008303e6, -+ 0x007c0422, -+ 0x00750460, -+ 0x006e04a3, -+ 0x006804e9, -+ 0x00620533, -+ 0x005d0582, -+ 0x005805d6, -+ 0x0053062e, -+ 0x004e068c, -+}; -+ -+static const u32 papd_comp_epsilon_tbl_core1_rev7[] = { -+ 0x00000000, -+ 0x00000000, -+ 0x00016023, -+ 0x00006028, -+ 0x00034036, -+ 0x0003402e, -+ 0x0007203c, -+ 0x0006e037, -+ 0x00070030, -+ 0x0009401f, -+ 0x0009a00f, -+ 0x000b600d, -+ 0x000c8007, -+ 0x000ce007, -+ 0x00101fff, -+ 0x00121ff9, -+ 0x0012e004, -+ 0x0014dffc, -+ 0x0016dff6, -+ 0x0018dfe9, -+ 0x001b3fe5, -+ 0x001c5fd0, -+ 0x001ddfc2, -+ 0x001f1fb6, -+ 0x00207fa4, -+ 0x00219f8f, -+ 0x0022ff7d, -+ 0x00247f6c, -+ 0x0024df5b, -+ 0x00267f4b, -+ 0x0027df3b, -+ 0x0029bf3b, -+ 0x002b5f2f, -+ 0x002d3f2e, -+ 0x002f5f2a, -+ 0x002fff15, -+ 0x00315f0b, -+ 0x0032defa, -+ 0x0033beeb, -+ 0x0034fed9, -+ 0x00353ec5, -+ 0x00361eb0, -+ 0x00363e9b, -+ 0x0036be87, -+ 0x0036be70, -+ 0x0038fe67, -+ 0x0044beb2, -+ 0x00513ef3, -+ 0x00595f11, -+ 0x00669f3d, -+ 0x0078dfdf, -+ 0x00a143aa, -+ 0x01642fff, -+ 0x0162afff, -+ 0x01620fff, -+ 0x0160cfff, -+ 0x015f0fff, -+ 0x015dafff, -+ 0x015bcfff, -+ 0x015bcfff, -+ 0x015b4fff, -+ 0x015acfff, -+ 0x01590fff, -+ 0x0156cfff, -+}; -+ -+static const u32 papd_cal_scalars_tbl_core1_rev7[] = { -+ 0x0b5e002d, -+ 0x0ae2002f, -+ 0x0a3b0032, -+ 0x09a70035, -+ 0x09220038, -+ 0x08ab003b, -+ 0x081f003f, -+ 0x07a20043, -+ 0x07340047, -+ 0x06d2004b, -+ 0x067a004f, -+ 0x06170054, -+ 0x05bf0059, -+ 0x0571005e, -+ 0x051e0064, -+ 0x04d3006a, -+ 0x04910070, -+ 0x044c0077, -+ 0x040f007e, -+ 0x03d90085, -+ 0x03a1008d, -+ 0x036f0095, -+ 0x033d009e, -+ 0x030b00a8, -+ 0x02e000b2, -+ 0x02b900bc, -+ 0x029200c7, -+ 0x026d00d3, -+ 0x024900e0, -+ 0x022900ed, -+ 0x020a00fb, -+ 0x01ec010a, -+ 0x01d20119, -+ 0x01b7012a, -+ 0x019e013c, -+ 0x0188014e, -+ 0x01720162, -+ 0x015d0177, -+ 0x0149018e, -+ 0x013701a5, -+ 0x012601be, -+ 0x011501d8, -+ 0x010601f4, -+ 0x00f70212, -+ 0x00e90231, -+ 0x00dc0253, -+ 0x00d00276, -+ 0x00c4029b, -+ 0x00b902c3, -+ 0x00af02ed, -+ 0x00a50319, -+ 0x009c0348, -+ 0x0093037a, -+ 0x008b03af, -+ 0x008303e6, -+ 0x007c0422, -+ 0x00750460, -+ 0x006e04a3, -+ 0x006804e9, -+ 0x00620533, -+ 0x005d0582, -+ 0x005805d6, -+ 0x0053062e, -+ 0x004e068c, -+}; -+ -+const struct phytbl_info mimophytbl_info_rev7[] = { -+ {&frame_struct_rev3, -+ sizeof(frame_struct_rev3) / sizeof(frame_struct_rev3[0]), 10, 0, 32} -+ , -+ {&pilot_tbl_rev3, sizeof(pilot_tbl_rev3) / sizeof(pilot_tbl_rev3[0]), -+ 11, 0, 16} -+ , -+ {&tmap_tbl_rev7, sizeof(tmap_tbl_rev7) / sizeof(tmap_tbl_rev7[0]), 12, -+ 0, 32} -+ , -+ {&intlv_tbl_rev3, sizeof(intlv_tbl_rev3) / sizeof(intlv_tbl_rev3[0]), -+ 13, 0, 32} -+ , -+ {&tdtrn_tbl_rev3, sizeof(tdtrn_tbl_rev3) / sizeof(tdtrn_tbl_rev3[0]), -+ 14, 0, 32} -+ , -+ {&noise_var_tbl_rev7, -+ sizeof(noise_var_tbl_rev7) / sizeof(noise_var_tbl_rev7[0]), 16, 0, 32} -+ , -+ {&mcs_tbl_rev3, sizeof(mcs_tbl_rev3) / sizeof(mcs_tbl_rev3[0]), 18, 0, -+ 16} -+ , -+ {&tdi_tbl20_ant0_rev3, -+ sizeof(tdi_tbl20_ant0_rev3) / sizeof(tdi_tbl20_ant0_rev3[0]), 19, 128, -+ 32} -+ , -+ {&tdi_tbl20_ant1_rev3, -+ sizeof(tdi_tbl20_ant1_rev3) / sizeof(tdi_tbl20_ant1_rev3[0]), 19, 256, -+ 32} -+ , -+ {&tdi_tbl40_ant0_rev3, -+ sizeof(tdi_tbl40_ant0_rev3) / sizeof(tdi_tbl40_ant0_rev3[0]), 19, 640, -+ 32} -+ , -+ {&tdi_tbl40_ant1_rev3, -+ sizeof(tdi_tbl40_ant1_rev3) / sizeof(tdi_tbl40_ant1_rev3[0]), 19, 768, -+ 32} -+ , -+ {&pltlut_tbl_rev3, sizeof(pltlut_tbl_rev3) / sizeof(pltlut_tbl_rev3[0]), -+ 20, 0, 32} -+ , -+ {&chanest_tbl_rev3, -+ sizeof(chanest_tbl_rev3) / sizeof(chanest_tbl_rev3[0]), 22, 0, 32} -+ , -+ {&frame_lut_rev3, sizeof(frame_lut_rev3) / sizeof(frame_lut_rev3[0]), -+ 24, 0, 8} -+ , -+ {&est_pwr_lut_core0_rev3, -+ sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26, -+ 0, 8} -+ , -+ {&est_pwr_lut_core1_rev3, -+ sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27, -+ 0, 8} -+ , -+ {&adj_pwr_lut_core0_rev3, -+ sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26, -+ 64, 8} -+ , -+ {&adj_pwr_lut_core1_rev3, -+ sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27, -+ 64, 8} -+ , -+ {&gainctrl_lut_core0_rev3, -+ sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]), -+ 26, 192, 32} -+ , -+ {&gainctrl_lut_core1_rev3, -+ sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]), -+ 27, 192, 32} -+ , -+ {&iq_lut_core0_rev3, -+ sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32} -+ , -+ {&iq_lut_core1_rev3, -+ sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32} -+ , -+ {&loft_lut_core0_rev3, -+ sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448, -+ 16} -+ , -+ {&loft_lut_core1_rev3, -+ sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448, -+ 16} -+ , -+ {&papd_comp_rfpwr_tbl_core0_rev3, -+ sizeof(papd_comp_rfpwr_tbl_core0_rev3) / -+ sizeof(papd_comp_rfpwr_tbl_core0_rev3[0]), 26, 576, 16} -+ , -+ {&papd_comp_rfpwr_tbl_core1_rev3, -+ sizeof(papd_comp_rfpwr_tbl_core1_rev3) / -+ sizeof(papd_comp_rfpwr_tbl_core1_rev3[0]), 27, 576, 16} -+ , -+ {&papd_comp_epsilon_tbl_core0_rev7, -+ sizeof(papd_comp_epsilon_tbl_core0_rev7) / -+ sizeof(papd_comp_epsilon_tbl_core0_rev7[0]), 31, 0, 32} -+ , -+ {&papd_cal_scalars_tbl_core0_rev7, -+ sizeof(papd_cal_scalars_tbl_core0_rev7) / -+ sizeof(papd_cal_scalars_tbl_core0_rev7[0]), 32, 0, 32} -+ , -+ {&papd_comp_epsilon_tbl_core1_rev7, -+ sizeof(papd_comp_epsilon_tbl_core1_rev7) / -+ sizeof(papd_comp_epsilon_tbl_core1_rev7[0]), 33, 0, 32} -+ , -+ {&papd_cal_scalars_tbl_core1_rev7, -+ sizeof(papd_cal_scalars_tbl_core1_rev7) / -+ sizeof(papd_cal_scalars_tbl_core1_rev7[0]), 34, 0, 32} -+ , -+}; -+ -+const u32 mimophytbl_info_sz_rev7 = -+ sizeof(mimophytbl_info_rev7) / sizeof(mimophytbl_info_rev7[0]); -+ -+const struct phytbl_info mimophytbl_info_rev16[] = { -+ {&noise_var_tbl_rev7, -+ sizeof(noise_var_tbl_rev7) / sizeof(noise_var_tbl_rev7[0]), 16, 0, 32} -+ , -+ {&est_pwr_lut_core0_rev3, -+ sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26, -+ 0, 8} -+ , -+ {&est_pwr_lut_core1_rev3, -+ sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27, -+ 0, 8} -+ , -+ {&adj_pwr_lut_core0_rev3, -+ sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26, -+ 64, 8} -+ , -+ {&adj_pwr_lut_core1_rev3, -+ sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27, -+ 64, 8} -+ , -+ {&gainctrl_lut_core0_rev3, -+ sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]), -+ 26, 192, 32} -+ , -+ {&gainctrl_lut_core1_rev3, -+ sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]), -+ 27, 192, 32} -+ , -+ {&iq_lut_core0_rev3, -+ sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32} -+ , -+ {&iq_lut_core1_rev3, -+ sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32} -+ , -+ {&loft_lut_core0_rev3, -+ sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448, -+ 16} -+ , -+ {&loft_lut_core1_rev3, -+ sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448, -+ 16} -+ , -+}; -+ -+const u32 mimophytbl_info_sz_rev16 = -+ sizeof(mimophytbl_info_rev16) / sizeof(mimophytbl_info_rev16[0]); -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.h.orig 2011-11-09 13:46:58.282800170 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.h 2011-11-09 13:47:17.040565666 -0500 -@@ -0,0 +1,50 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#define ANT_SWCTRL_TBL_REV3_IDX (0) -+ -+#include -+#include "phy_int.h" -+ -+extern const struct phytbl_info mimophytbl_info_rev0[], -+ mimophytbl_info_rev0_volatile[]; -+ -+extern const u32 mimophytbl_info_sz_rev0, -+ mimophytbl_info_sz_rev0_volatile; -+ -+extern const struct phytbl_info mimophytbl_info_rev3[], -+ mimophytbl_info_rev3_volatile[], -+ mimophytbl_info_rev3_volatile1[], -+ mimophytbl_info_rev3_volatile2[], -+ mimophytbl_info_rev3_volatile3[]; -+ -+extern const u32 mimophytbl_info_sz_rev3, -+ mimophytbl_info_sz_rev3_volatile, -+ mimophytbl_info_sz_rev3_volatile1, -+ mimophytbl_info_sz_rev3_volatile2, -+ mimophytbl_info_sz_rev3_volatile3; -+ -+extern const u32 noise_var_tbl_rev3[]; -+ -+extern const struct phytbl_info mimophytbl_info_rev7[]; -+ -+extern const u32 mimophytbl_info_sz_rev7; -+ -+extern const u32 noise_var_tbl_rev7[]; -+ -+extern const struct phytbl_info mimophytbl_info_rev16[]; -+ -+extern const u32 mimophytbl_info_sz_rev16; -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c.orig 2011-11-09 13:46:58.282800170 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c 2011-11-09 13:47:17.040565666 -0500 -@@ -0,0 +1,225 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * This is "two-way" interface, acting as the SHIM layer between driver -+ * and PHY layer. The driver can optionally call this translation layer -+ * to do some preprocessing, then reach PHY. On the PHY->driver direction, -+ * all calls go through this layer since PHY doesn't have access to the -+ * driver's brcms_hardware pointer. -+ */ -+#include -+#include -+ -+#include "main.h" -+#include "mac80211_if.h" -+#include "phy_shim.h" -+ -+/* PHY SHIM module specific state */ -+struct phy_shim_info { -+ struct brcms_hardware *wlc_hw; /* pointer to main wlc_hw structure */ -+ struct brcms_c_info *wlc; /* pointer to main wlc structure */ -+ struct brcms_info *wl; /* pointer to os-specific private state */ -+}; -+ -+struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw, -+ struct brcms_info *wl, -+ struct brcms_c_info *wlc) { -+ struct phy_shim_info *physhim = NULL; -+ -+ physhim = kzalloc(sizeof(struct phy_shim_info), GFP_ATOMIC); -+ if (!physhim) -+ return NULL; -+ -+ physhim->wlc_hw = wlc_hw; -+ physhim->wlc = wlc; -+ physhim->wl = wl; -+ -+ return physhim; -+} -+ -+void wlc_phy_shim_detach(struct phy_shim_info *physhim) -+{ -+ kfree(physhim); -+} -+ -+struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim, -+ void (*fn)(struct brcms_phy *pi), -+ void *arg, const char *name) -+{ -+ return (struct wlapi_timer *) -+ brcms_init_timer(physhim->wl, (void (*)(void *))fn, -+ arg, name); -+} -+ -+void wlapi_free_timer(struct wlapi_timer *t) -+{ -+ brcms_free_timer((struct brcms_timer *)t); -+} -+ -+void -+wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic) -+{ -+ brcms_add_timer((struct brcms_timer *)t, ms, periodic); -+} -+ -+bool wlapi_del_timer(struct wlapi_timer *t) -+{ -+ return brcms_del_timer((struct brcms_timer *)t); -+} -+ -+void wlapi_intrson(struct phy_shim_info *physhim) -+{ -+ brcms_intrson(physhim->wl); -+} -+ -+u32 wlapi_intrsoff(struct phy_shim_info *physhim) -+{ -+ return brcms_intrsoff(physhim->wl); -+} -+ -+void wlapi_intrsrestore(struct phy_shim_info *physhim, u32 macintmask) -+{ -+ brcms_intrsrestore(physhim->wl, macintmask); -+} -+ -+void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset, u16 v) -+{ -+ brcms_b_write_shm(physhim->wlc_hw, offset, v); -+} -+ -+u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset) -+{ -+ return brcms_b_read_shm(physhim->wlc_hw, offset); -+} -+ -+void -+wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx, u16 mask, -+ u16 val, int bands) -+{ -+ brcms_b_mhf(physhim->wlc_hw, idx, mask, val, bands); -+} -+ -+void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags) -+{ -+ brcms_b_corereset(physhim->wlc_hw, flags); -+} -+ -+void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim) -+{ -+ brcms_c_suspend_mac_and_wait(physhim->wlc); -+} -+ -+void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode) -+{ -+ brcms_b_switch_macfreq(physhim->wlc_hw, spurmode); -+} -+ -+void wlapi_enable_mac(struct phy_shim_info *physhim) -+{ -+ brcms_c_enable_mac(physhim->wlc); -+} -+ -+void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask, u32 val) -+{ -+ brcms_b_mctrl(physhim->wlc_hw, mask, val); -+} -+ -+void wlapi_bmac_phy_reset(struct phy_shim_info *physhim) -+{ -+ brcms_b_phy_reset(physhim->wlc_hw); -+} -+ -+void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw) -+{ -+ brcms_b_bw_set(physhim->wlc_hw, bw); -+} -+ -+u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim) -+{ -+ return brcms_b_get_txant(physhim->wlc_hw); -+} -+ -+void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk) -+{ -+ brcms_b_phyclk_fgc(physhim->wlc_hw, clk); -+} -+ -+void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk) -+{ -+ brcms_b_macphyclk_set(physhim->wlc_hw, clk); -+} -+ -+void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on) -+{ -+ brcms_b_core_phypll_ctl(physhim->wlc_hw, on); -+} -+ -+void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim) -+{ -+ brcms_b_core_phypll_reset(physhim->wlc_hw); -+} -+ -+void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info *physhim) -+{ -+ brcms_c_ucode_wake_override_set(physhim->wlc_hw, -+ BRCMS_WAKE_OVERRIDE_PHYREG); -+} -+ -+void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info *physhim) -+{ -+ brcms_c_ucode_wake_override_clear(physhim->wlc_hw, -+ BRCMS_WAKE_OVERRIDE_PHYREG); -+} -+ -+void -+wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int offset, -+ int len, void *buf) -+{ -+ brcms_b_write_template_ram(physhim->wlc_hw, offset, len, buf); -+} -+ -+u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim, u8 rate) -+{ -+ return brcms_b_rate_shm_offset(physhim->wlc_hw, rate); -+} -+ -+void wlapi_ucode_sample_init(struct phy_shim_info *physhim) -+{ -+} -+ -+void -+wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint offset, void *buf, -+ int len, u32 sel) -+{ -+ brcms_b_copyfrom_objmem(physhim->wlc_hw, offset, buf, len, sel); -+} -+ -+void -+wlapi_copyto_objmem(struct phy_shim_info *physhim, uint offset, const void *buf, -+ int l, u32 sel) -+{ -+ brcms_b_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel); -+} -+ -+char *wlapi_getvar(struct phy_shim_info *physhim, enum brcms_srom_id id) -+{ -+ return getvar(physhim->wlc_hw->sih, id); -+} -+int wlapi_getintvar(struct phy_shim_info *physhim, enum brcms_srom_id id) -+{ -+ return getintvar(physhim->wlc_hw->sih, id); -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h.orig 2011-11-09 13:46:58.282800170 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h 2011-11-09 13:47:17.041565653 -0500 -@@ -0,0 +1,182 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * phy_shim.h: stuff defined in phy_shim.c and included only by the phy -+ */ -+ -+#ifndef _BRCM_PHY_SHIM_H_ -+#define _BRCM_PHY_SHIM_H_ -+ -+#include "types.h" -+ -+#define RADAR_TYPE_NONE 0 /* Radar type None */ -+#define RADAR_TYPE_ETSI_1 1 /* ETSI 1 Radar type */ -+#define RADAR_TYPE_ETSI_2 2 /* ETSI 2 Radar type */ -+#define RADAR_TYPE_ETSI_3 3 /* ETSI 3 Radar type */ -+#define RADAR_TYPE_ITU_E 4 /* ITU E Radar type */ -+#define RADAR_TYPE_ITU_K 5 /* ITU K Radar type */ -+#define RADAR_TYPE_UNCLASSIFIED 6 /* Unclassified Radar type */ -+#define RADAR_TYPE_BIN5 7 /* long pulse radar type */ -+#define RADAR_TYPE_STG2 8 /* staggered-2 radar */ -+#define RADAR_TYPE_STG3 9 /* staggered-3 radar */ -+#define RADAR_TYPE_FRA 10 /* French radar */ -+ -+/* French radar pulse widths */ -+#define FRA_T1_20MHZ 52770 -+#define FRA_T2_20MHZ 61538 -+#define FRA_T3_20MHZ 66002 -+#define FRA_T1_40MHZ 105541 -+#define FRA_T2_40MHZ 123077 -+#define FRA_T3_40MHZ 132004 -+#define FRA_ERR_20MHZ 60 -+#define FRA_ERR_40MHZ 120 -+ -+#define ANTSEL_NA 0 /* No boardlevel selection available */ -+#define ANTSEL_2x4 1 /* 2x4 boardlevel selection available */ -+#define ANTSEL_2x3 2 /* 2x3 CB2 boardlevel selection available */ -+ -+/* Rx Antenna diversity control values */ -+#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */ -+#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */ -+#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */ -+#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */ -+#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */ -+#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0 /* default antdiv setting */ -+ -+#define WL_ANT_RX_MAX 2 /* max 2 receive antennas */ -+#define WL_ANT_HT_RX_MAX 3 /* max 3 receive antennas/cores */ -+#define WL_ANT_IDX_1 0 /* antenna index 1 */ -+#define WL_ANT_IDX_2 1 /* antenna index 2 */ -+ -+/* values for n_preamble_type */ -+#define BRCMS_N_PREAMBLE_MIXEDMODE 0 -+#define BRCMS_N_PREAMBLE_GF 1 -+#define BRCMS_N_PREAMBLE_GF_BRCM 2 -+ -+#define WL_TX_POWER_RATES_LEGACY 45 -+#define WL_TX_POWER_MCS20_FIRST 12 -+#define WL_TX_POWER_MCS20_NUM 16 -+#define WL_TX_POWER_MCS40_FIRST 28 -+#define WL_TX_POWER_MCS40_NUM 17 -+ -+ -+#define WL_TX_POWER_RATES 101 -+#define WL_TX_POWER_CCK_FIRST 0 -+#define WL_TX_POWER_CCK_NUM 4 -+/* Index for first 20MHz OFDM SISO rate */ -+#define WL_TX_POWER_OFDM_FIRST 4 -+/* Index for first 20MHz OFDM CDD rate */ -+#define WL_TX_POWER_OFDM20_CDD_FIRST 12 -+/* Index for first 40MHz OFDM SISO rate */ -+#define WL_TX_POWER_OFDM40_SISO_FIRST 52 -+/* Index for first 40MHz OFDM CDD rate */ -+#define WL_TX_POWER_OFDM40_CDD_FIRST 60 -+#define WL_TX_POWER_OFDM_NUM 8 -+/* Index for first 20MHz MCS SISO rate */ -+#define WL_TX_POWER_MCS20_SISO_FIRST 20 -+/* Index for first 20MHz MCS CDD rate */ -+#define WL_TX_POWER_MCS20_CDD_FIRST 28 -+/* Index for first 20MHz MCS STBC rate */ -+#define WL_TX_POWER_MCS20_STBC_FIRST 36 -+/* Index for first 20MHz MCS SDM rate */ -+#define WL_TX_POWER_MCS20_SDM_FIRST 44 -+/* Index for first 40MHz MCS SISO rate */ -+#define WL_TX_POWER_MCS40_SISO_FIRST 68 -+/* Index for first 40MHz MCS CDD rate */ -+#define WL_TX_POWER_MCS40_CDD_FIRST 76 -+/* Index for first 40MHz MCS STBC rate */ -+#define WL_TX_POWER_MCS40_STBC_FIRST 84 -+/* Index for first 40MHz MCS SDM rate */ -+#define WL_TX_POWER_MCS40_SDM_FIRST 92 -+#define WL_TX_POWER_MCS_1_STREAM_NUM 8 -+#define WL_TX_POWER_MCS_2_STREAM_NUM 8 -+/* Index for 40MHz rate MCS 32 */ -+#define WL_TX_POWER_MCS_32 100 -+#define WL_TX_POWER_MCS_32_NUM 1 -+ -+/* sslpnphy specifics */ -+/* Index for first 20MHz MCS SISO rate */ -+#define WL_TX_POWER_MCS20_SISO_FIRST_SSN 12 -+ -+/* struct tx_power::flags bits */ -+#define WL_TX_POWER_F_ENABLED 1 -+#define WL_TX_POWER_F_HW 2 -+#define WL_TX_POWER_F_MIMO 4 -+#define WL_TX_POWER_F_SISO 8 -+ -+/* values to force tx/rx chain */ -+#define BRCMS_N_TXRX_CHAIN0 0 -+#define BRCMS_N_TXRX_CHAIN1 1 -+ -+struct brcms_phy; -+ -+extern struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw, -+ struct brcms_info *wl, -+ struct brcms_c_info *wlc); -+extern void wlc_phy_shim_detach(struct phy_shim_info *physhim); -+ -+/* PHY to WL utility functions */ -+extern struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim, -+ void (*fn) (struct brcms_phy *pi), -+ void *arg, const char *name); -+extern void wlapi_free_timer(struct wlapi_timer *t); -+extern void wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic); -+extern bool wlapi_del_timer(struct wlapi_timer *t); -+extern void wlapi_intrson(struct phy_shim_info *physhim); -+extern u32 wlapi_intrsoff(struct phy_shim_info *physhim); -+extern void wlapi_intrsrestore(struct phy_shim_info *physhim, -+ u32 macintmask); -+ -+extern void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset, -+ u16 v); -+extern u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset); -+extern void wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx, -+ u16 mask, u16 val, int bands); -+extern void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags); -+extern void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim); -+extern void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode); -+extern void wlapi_enable_mac(struct phy_shim_info *physhim); -+extern void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask, -+ u32 val); -+extern void wlapi_bmac_phy_reset(struct phy_shim_info *physhim); -+extern void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw); -+extern void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk); -+extern void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk); -+extern void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on); -+extern void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim); -+extern void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info * -+ physhim); -+extern void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info * -+ physhim); -+extern void wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int o, -+ int len, void *buf); -+extern u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim, -+ u8 rate); -+extern void wlapi_ucode_sample_init(struct phy_shim_info *physhim); -+extern void wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint, -+ void *buf, int, u32 sel); -+extern void wlapi_copyto_objmem(struct phy_shim_info *physhim, uint, -+ const void *buf, int, u32); -+ -+extern void wlapi_high_update_phy_mode(struct phy_shim_info *physhim, -+ u32 phy_mode); -+extern u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim); -+extern char *wlapi_getvar(struct phy_shim_info *physhim, enum brcms_srom_id id); -+extern int wlapi_getintvar(struct phy_shim_info *physhim, -+ enum brcms_srom_id id); -+ -+#endif /* _BRCM_PHY_SHIM_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.c.orig 2011-11-09 13:46:58.283800157 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.c 2011-11-09 13:47:17.041565653 -0500 -@@ -0,0 +1,458 @@ -+/* -+ * Copyright (c) 2011 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include "pub.h" -+#include "aiutils.h" -+#include "pmu.h" -+ -+/* -+ * external LPO crystal frequency -+ */ -+#define EXT_ILP_HZ 32768 -+ -+/* -+ * Duration for ILP clock frequency measurment in milliseconds -+ * -+ * remark: 1000 must be an integer multiple of this duration -+ */ -+#define ILP_CALC_DUR 10 -+ -+/* Fields in pmucontrol */ -+#define PCTL_ILP_DIV_MASK 0xffff0000 -+#define PCTL_ILP_DIV_SHIFT 16 -+#define PCTL_PLL_PLLCTL_UPD 0x00000400 /* rev 2 */ -+#define PCTL_NOILP_ON_WAIT 0x00000200 /* rev 1 */ -+#define PCTL_HT_REQ_EN 0x00000100 -+#define PCTL_ALP_REQ_EN 0x00000080 -+#define PCTL_XTALFREQ_MASK 0x0000007c -+#define PCTL_XTALFREQ_SHIFT 2 -+#define PCTL_ILP_DIV_EN 0x00000002 -+#define PCTL_LPO_SEL 0x00000001 -+ -+/* ILP clock */ -+#define ILP_CLOCK 32000 -+ -+/* ALP clock on pre-PMU chips */ -+#define ALP_CLOCK 20000000 -+ -+/* pmustatus */ -+#define PST_EXTLPOAVAIL 0x0100 -+#define PST_WDRESET 0x0080 -+#define PST_INTPEND 0x0040 -+#define PST_SBCLKST 0x0030 -+#define PST_SBCLKST_ILP 0x0010 -+#define PST_SBCLKST_ALP 0x0020 -+#define PST_SBCLKST_HT 0x0030 -+#define PST_ALPAVAIL 0x0008 -+#define PST_HTAVAIL 0x0004 -+#define PST_RESINIT 0x0003 -+ -+/* PMU resource bit position */ -+#define PMURES_BIT(bit) (1 << (bit)) -+ -+/* PMU corerev and chip specific PLL controls. -+ * PMU_PLL_XX where is PMU corerev and is an arbitrary -+ * number to differentiate different PLLs controlled by the same PMU rev. -+ */ -+/* pllcontrol registers: -+ * ndiv_pwrdn, pwrdn_ch, refcomp_pwrdn, dly_ch, -+ * p1div, p2div, _bypass_sdmod -+ */ -+#define PMU1_PLL0_PLLCTL0 0 -+#define PMU1_PLL0_PLLCTL1 1 -+#define PMU1_PLL0_PLLCTL2 2 -+#define PMU1_PLL0_PLLCTL3 3 -+#define PMU1_PLL0_PLLCTL4 4 -+#define PMU1_PLL0_PLLCTL5 5 -+ -+/* pmu XtalFreqRatio */ -+#define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF -+#define PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000 -+#define PMU_XTALFREQ_REG_MEASURE_SHIFT 31 -+ -+/* 4313 resources */ -+#define RES4313_BB_PU_RSRC 0 -+#define RES4313_ILP_REQ_RSRC 1 -+#define RES4313_XTAL_PU_RSRC 2 -+#define RES4313_ALP_AVAIL_RSRC 3 -+#define RES4313_RADIO_PU_RSRC 4 -+#define RES4313_BG_PU_RSRC 5 -+#define RES4313_VREG1P4_PU_RSRC 6 -+#define RES4313_AFE_PWRSW_RSRC 7 -+#define RES4313_RX_PWRSW_RSRC 8 -+#define RES4313_TX_PWRSW_RSRC 9 -+#define RES4313_BB_PWRSW_RSRC 10 -+#define RES4313_SYNTH_PWRSW_RSRC 11 -+#define RES4313_MISC_PWRSW_RSRC 12 -+#define RES4313_BB_PLL_PWRSW_RSRC 13 -+#define RES4313_HT_AVAIL_RSRC 14 -+#define RES4313_MACPHY_CLK_AVAIL_RSRC 15 -+ -+/* Determine min/max rsrc masks. Value 0 leaves hardware at default. */ -+static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax) -+{ -+ u32 min_mask = 0, max_mask = 0; -+ uint rsrcs; -+ -+ /* # resources */ -+ rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT; -+ -+ /* determine min/max rsrc masks */ -+ switch (sih->chip) { -+ case BCM43224_CHIP_ID: -+ case BCM43225_CHIP_ID: -+ /* ??? */ -+ break; -+ -+ case BCM4313_CHIP_ID: -+ min_mask = PMURES_BIT(RES4313_BB_PU_RSRC) | -+ PMURES_BIT(RES4313_XTAL_PU_RSRC) | -+ PMURES_BIT(RES4313_ALP_AVAIL_RSRC) | -+ PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC); -+ max_mask = 0xffff; -+ break; -+ default: -+ break; -+ } -+ -+ *pmin = min_mask; -+ *pmax = max_mask; -+} -+ -+static void -+si_pmu_spuravoid_pllupdate(struct si_pub *sih, struct chipcregs __iomem *cc, -+ u8 spuravoid) -+{ -+ u32 tmp = 0; -+ -+ switch (sih->chip) { -+ case BCM43224_CHIP_ID: -+ case BCM43225_CHIP_ID: -+ if (spuravoid == 1) { -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0); -+ W_REG(&cc->pllcontrol_data, 0x11500010); -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1); -+ W_REG(&cc->pllcontrol_data, 0x000C0C06); -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2); -+ W_REG(&cc->pllcontrol_data, 0x0F600a08); -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3); -+ W_REG(&cc->pllcontrol_data, 0x00000000); -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4); -+ W_REG(&cc->pllcontrol_data, 0x2001E920); -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5); -+ W_REG(&cc->pllcontrol_data, 0x88888815); -+ } else { -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0); -+ W_REG(&cc->pllcontrol_data, 0x11100010); -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1); -+ W_REG(&cc->pllcontrol_data, 0x000c0c06); -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2); -+ W_REG(&cc->pllcontrol_data, 0x03000a08); -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3); -+ W_REG(&cc->pllcontrol_data, 0x00000000); -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4); -+ W_REG(&cc->pllcontrol_data, 0x200005c0); -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5); -+ W_REG(&cc->pllcontrol_data, 0x88888815); -+ } -+ tmp = 1 << 10; -+ break; -+ -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0); -+ W_REG(&cc->pllcontrol_data, 0x11100008); -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1); -+ W_REG(&cc->pllcontrol_data, 0x0c000c06); -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2); -+ W_REG(&cc->pllcontrol_data, 0x03000a08); -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3); -+ W_REG(&cc->pllcontrol_data, 0x00000000); -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4); -+ W_REG(&cc->pllcontrol_data, 0x200005c0); -+ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5); -+ W_REG(&cc->pllcontrol_data, 0x88888855); -+ -+ tmp = 1 << 10; -+ break; -+ -+ default: -+ /* bail out */ -+ return; -+ } -+ -+ tmp |= R_REG(&cc->pmucontrol); -+ W_REG(&cc->pmucontrol, tmp); -+} -+ -+u16 si_pmu_fast_pwrup_delay(struct si_pub *sih) -+{ -+ uint delay = PMU_MAX_TRANSITION_DLY; -+ -+ switch (sih->chip) { -+ case BCM43224_CHIP_ID: -+ case BCM43225_CHIP_ID: -+ case BCM4313_CHIP_ID: -+ delay = 3700; -+ break; -+ default: -+ break; -+ } -+ -+ return (u16) delay; -+} -+ -+void si_pmu_sprom_enable(struct si_pub *sih, bool enable) -+{ -+ struct chipcregs __iomem *cc; -+ uint origidx; -+ -+ /* Remember original core before switch to chipc */ -+ origidx = ai_coreidx(sih); -+ cc = ai_setcoreidx(sih, SI_CC_IDX); -+ -+ /* Return to original core */ -+ ai_setcoreidx(sih, origidx); -+} -+ -+/* Read/write a chipcontrol reg */ -+u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) -+{ -+ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol_addr), -+ ~0, reg); -+ return ai_corereg(sih, SI_CC_IDX, -+ offsetof(struct chipcregs, chipcontrol_data), mask, -+ val); -+} -+ -+/* Read/write a regcontrol reg */ -+u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) -+{ -+ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, regcontrol_addr), -+ ~0, reg); -+ return ai_corereg(sih, SI_CC_IDX, -+ offsetof(struct chipcregs, regcontrol_data), mask, -+ val); -+} -+ -+/* Read/write a pllcontrol reg */ -+u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) -+{ -+ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pllcontrol_addr), -+ ~0, reg); -+ return ai_corereg(sih, SI_CC_IDX, -+ offsetof(struct chipcregs, pllcontrol_data), mask, -+ val); -+} -+ -+/* PMU PLL update */ -+void si_pmu_pllupd(struct si_pub *sih) -+{ -+ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pmucontrol), -+ PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD); -+} -+ -+/* query alp/xtal clock frequency */ -+u32 si_pmu_alp_clock(struct si_pub *sih) -+{ -+ u32 clock = ALP_CLOCK; -+ -+ /* bail out with default */ -+ if (!(sih->cccaps & CC_CAP_PMU)) -+ return clock; -+ -+ switch (sih->chip) { -+ case BCM43224_CHIP_ID: -+ case BCM43225_CHIP_ID: -+ case BCM4313_CHIP_ID: -+ /* always 20Mhz */ -+ clock = 20000 * 1000; -+ break; -+ default: -+ break; -+ } -+ -+ return clock; -+} -+ -+void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid) -+{ -+ struct chipcregs __iomem *cc; -+ uint origidx, intr_val; -+ -+ /* Remember original core before switch to chipc */ -+ cc = (struct chipcregs __iomem *) -+ ai_switch_core(sih, CC_CORE_ID, &origidx, &intr_val); -+ -+ /* update the pll changes */ -+ si_pmu_spuravoid_pllupdate(sih, cc, spuravoid); -+ -+ /* Return to original core */ -+ ai_restore_core(sih, origidx, intr_val); -+} -+ -+/* initialize PMU */ -+void si_pmu_init(struct si_pub *sih) -+{ -+ struct chipcregs __iomem *cc; -+ uint origidx; -+ -+ /* Remember original core before switch to chipc */ -+ origidx = ai_coreidx(sih); -+ cc = ai_setcoreidx(sih, SI_CC_IDX); -+ -+ if (sih->pmurev == 1) -+ AND_REG(&cc->pmucontrol, ~PCTL_NOILP_ON_WAIT); -+ else if (sih->pmurev >= 2) -+ OR_REG(&cc->pmucontrol, PCTL_NOILP_ON_WAIT); -+ -+ /* Return to original core */ -+ ai_setcoreidx(sih, origidx); -+} -+ -+/* initialize PMU chip controls and other chip level stuff */ -+void si_pmu_chip_init(struct si_pub *sih) -+{ -+ uint origidx; -+ -+ /* Gate off SPROM clock and chip select signals */ -+ si_pmu_sprom_enable(sih, false); -+ -+ /* Remember original core */ -+ origidx = ai_coreidx(sih); -+ -+ /* Return to original core */ -+ ai_setcoreidx(sih, origidx); -+} -+ -+/* initialize PMU switch/regulators */ -+void si_pmu_swreg_init(struct si_pub *sih) -+{ -+} -+ -+/* initialize PLL */ -+void si_pmu_pll_init(struct si_pub *sih, uint xtalfreq) -+{ -+ struct chipcregs __iomem *cc; -+ uint origidx; -+ -+ /* Remember original core before switch to chipc */ -+ origidx = ai_coreidx(sih); -+ cc = ai_setcoreidx(sih, SI_CC_IDX); -+ -+ switch (sih->chip) { -+ case BCM4313_CHIP_ID: -+ case BCM43224_CHIP_ID: -+ case BCM43225_CHIP_ID: -+ /* ??? */ -+ break; -+ default: -+ break; -+ } -+ -+ /* Return to original core */ -+ ai_setcoreidx(sih, origidx); -+} -+ -+/* initialize PMU resources */ -+void si_pmu_res_init(struct si_pub *sih) -+{ -+ struct chipcregs __iomem *cc; -+ uint origidx; -+ u32 min_mask = 0, max_mask = 0; -+ -+ /* Remember original core before switch to chipc */ -+ origidx = ai_coreidx(sih); -+ cc = ai_setcoreidx(sih, SI_CC_IDX); -+ -+ /* Determine min/max rsrc masks */ -+ si_pmu_res_masks(sih, &min_mask, &max_mask); -+ -+ /* It is required to program max_mask first and then min_mask */ -+ -+ /* Program max resource mask */ -+ -+ if (max_mask) -+ W_REG(&cc->max_res_mask, max_mask); -+ -+ /* Program min resource mask */ -+ -+ if (min_mask) -+ W_REG(&cc->min_res_mask, min_mask); -+ -+ /* Add some delay; allow resources to come up and settle. */ -+ mdelay(2); -+ -+ /* Return to original core */ -+ ai_setcoreidx(sih, origidx); -+} -+ -+u32 si_pmu_measure_alpclk(struct si_pub *sih) -+{ -+ struct chipcregs __iomem *cc; -+ uint origidx; -+ u32 alp_khz; -+ -+ if (sih->pmurev < 10) -+ return 0; -+ -+ /* Remember original core before switch to chipc */ -+ origidx = ai_coreidx(sih); -+ cc = ai_setcoreidx(sih, SI_CC_IDX); -+ -+ if (R_REG(&cc->pmustatus) & PST_EXTLPOAVAIL) { -+ u32 ilp_ctr, alp_hz; -+ -+ /* -+ * Enable the reg to measure the freq, -+ * in case it was disabled before -+ */ -+ W_REG(&cc->pmu_xtalfreq, -+ 1U << PMU_XTALFREQ_REG_MEASURE_SHIFT); -+ -+ /* Delay for well over 4 ILP clocks */ -+ udelay(1000); -+ -+ /* Read the latched number of ALP ticks per 4 ILP ticks */ -+ ilp_ctr = -+ R_REG(&cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK; -+ -+ /* -+ * Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT -+ * bit to save power -+ */ -+ W_REG(&cc->pmu_xtalfreq, 0); -+ -+ /* Calculate ALP frequency */ -+ alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4; -+ -+ /* -+ * Round to nearest 100KHz, and at -+ * the same time convert to KHz -+ */ -+ alp_khz = (alp_hz + 50000) / 100000 * 100; -+ } else -+ alp_khz = 0; -+ -+ /* Return to original core */ -+ ai_setcoreidx(sih, origidx); -+ -+ return alp_khz; -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.h.orig 2011-11-09 13:46:58.283800157 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.h 2011-11-09 13:47:17.041565653 -0500 -@@ -0,0 +1,38 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+ -+#ifndef _BRCM_PMU_H_ -+#define _BRCM_PMU_H_ -+ -+#include "types.h" -+ -+extern u16 si_pmu_fast_pwrup_delay(struct si_pub *sih); -+extern void si_pmu_sprom_enable(struct si_pub *sih, bool enable); -+extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); -+extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); -+extern u32 si_pmu_alp_clock(struct si_pub *sih); -+extern void si_pmu_pllupd(struct si_pub *sih); -+extern void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid); -+extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); -+extern void si_pmu_init(struct si_pub *sih); -+extern void si_pmu_chip_init(struct si_pub *sih); -+extern void si_pmu_pll_init(struct si_pub *sih, u32 xtalfreq); -+extern void si_pmu_res_init(struct si_pub *sih); -+extern void si_pmu_swreg_init(struct si_pub *sih); -+extern u32 si_pmu_measure_alpclk(struct si_pub *sih); -+ -+#endif /* _BRCM_PMU_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pub.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pub.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pub.h.orig 2011-11-09 13:46:58.283800157 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pub.h 2011-11-09 13:47:17.042565640 -0500 -@@ -0,0 +1,634 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_PUB_H_ -+#define _BRCM_PUB_H_ -+ -+#include -+#include "types.h" -+#include "defs.h" -+ -+enum brcms_srom_id { -+ BRCMS_SROM_NULL, -+ BRCMS_SROM_CONT, -+ BRCMS_SROM_AA2G, -+ BRCMS_SROM_AA5G, -+ BRCMS_SROM_AG0, -+ BRCMS_SROM_AG1, -+ BRCMS_SROM_AG2, -+ BRCMS_SROM_AG3, -+ BRCMS_SROM_ANTSWCTL2G, -+ BRCMS_SROM_ANTSWCTL5G, -+ BRCMS_SROM_ANTSWITCH, -+ BRCMS_SROM_BOARDFLAGS2, -+ BRCMS_SROM_BOARDFLAGS, -+ BRCMS_SROM_BOARDNUM, -+ BRCMS_SROM_BOARDREV, -+ BRCMS_SROM_BOARDTYPE, -+ BRCMS_SROM_BW40PO, -+ BRCMS_SROM_BWDUPPO, -+ BRCMS_SROM_BXA2G, -+ BRCMS_SROM_BXA5G, -+ BRCMS_SROM_CC, -+ BRCMS_SROM_CCK2GPO, -+ BRCMS_SROM_CCKBW202GPO, -+ BRCMS_SROM_CCKBW20UL2GPO, -+ BRCMS_SROM_CCODE, -+ BRCMS_SROM_CDDPO, -+ BRCMS_SROM_DEVID, -+ BRCMS_SROM_ET1MACADDR, -+ BRCMS_SROM_EXTPAGAIN2G, -+ BRCMS_SROM_EXTPAGAIN5G, -+ BRCMS_SROM_FREQOFFSET_CORR, -+ BRCMS_SROM_HW_IQCAL_EN, -+ BRCMS_SROM_IL0MACADDR, -+ BRCMS_SROM_IQCAL_SWP_DIS, -+ BRCMS_SROM_LEDBH0, -+ BRCMS_SROM_LEDBH1, -+ BRCMS_SROM_LEDBH2, -+ BRCMS_SROM_LEDBH3, -+ BRCMS_SROM_LEDDC, -+ BRCMS_SROM_LEGOFDM40DUPPO, -+ BRCMS_SROM_LEGOFDMBW202GPO, -+ BRCMS_SROM_LEGOFDMBW205GHPO, -+ BRCMS_SROM_LEGOFDMBW205GLPO, -+ BRCMS_SROM_LEGOFDMBW205GMPO, -+ BRCMS_SROM_LEGOFDMBW20UL2GPO, -+ BRCMS_SROM_LEGOFDMBW20UL5GHPO, -+ BRCMS_SROM_LEGOFDMBW20UL5GLPO, -+ BRCMS_SROM_LEGOFDMBW20UL5GMPO, -+ BRCMS_SROM_MACADDR, -+ BRCMS_SROM_MCS2GPO0, -+ BRCMS_SROM_MCS2GPO1, -+ BRCMS_SROM_MCS2GPO2, -+ BRCMS_SROM_MCS2GPO3, -+ BRCMS_SROM_MCS2GPO4, -+ BRCMS_SROM_MCS2GPO5, -+ BRCMS_SROM_MCS2GPO6, -+ BRCMS_SROM_MCS2GPO7, -+ BRCMS_SROM_MCS32PO, -+ BRCMS_SROM_MCS5GHPO0, -+ BRCMS_SROM_MCS5GHPO1, -+ BRCMS_SROM_MCS5GHPO2, -+ BRCMS_SROM_MCS5GHPO3, -+ BRCMS_SROM_MCS5GHPO4, -+ BRCMS_SROM_MCS5GHPO5, -+ BRCMS_SROM_MCS5GHPO6, -+ BRCMS_SROM_MCS5GHPO7, -+ BRCMS_SROM_MCS5GLPO0, -+ BRCMS_SROM_MCS5GLPO1, -+ BRCMS_SROM_MCS5GLPO2, -+ BRCMS_SROM_MCS5GLPO3, -+ BRCMS_SROM_MCS5GLPO4, -+ BRCMS_SROM_MCS5GLPO5, -+ BRCMS_SROM_MCS5GLPO6, -+ BRCMS_SROM_MCS5GLPO7, -+ BRCMS_SROM_MCS5GPO0, -+ BRCMS_SROM_MCS5GPO1, -+ BRCMS_SROM_MCS5GPO2, -+ BRCMS_SROM_MCS5GPO3, -+ BRCMS_SROM_MCS5GPO4, -+ BRCMS_SROM_MCS5GPO5, -+ BRCMS_SROM_MCS5GPO6, -+ BRCMS_SROM_MCS5GPO7, -+ BRCMS_SROM_MCSBW202GPO, -+ BRCMS_SROM_MCSBW205GHPO, -+ BRCMS_SROM_MCSBW205GLPO, -+ BRCMS_SROM_MCSBW205GMPO, -+ BRCMS_SROM_MCSBW20UL2GPO, -+ BRCMS_SROM_MCSBW20UL5GHPO, -+ BRCMS_SROM_MCSBW20UL5GLPO, -+ BRCMS_SROM_MCSBW20UL5GMPO, -+ BRCMS_SROM_MCSBW402GPO, -+ BRCMS_SROM_MCSBW405GHPO, -+ BRCMS_SROM_MCSBW405GLPO, -+ BRCMS_SROM_MCSBW405GMPO, -+ BRCMS_SROM_MEASPOWER, -+ BRCMS_SROM_OFDM2GPO, -+ BRCMS_SROM_OFDM5GHPO, -+ BRCMS_SROM_OFDM5GLPO, -+ BRCMS_SROM_OFDM5GPO, -+ BRCMS_SROM_OPO, -+ BRCMS_SROM_PA0B0, -+ BRCMS_SROM_PA0B1, -+ BRCMS_SROM_PA0B2, -+ BRCMS_SROM_PA0ITSSIT, -+ BRCMS_SROM_PA0MAXPWR, -+ BRCMS_SROM_PA1B0, -+ BRCMS_SROM_PA1B1, -+ BRCMS_SROM_PA1B2, -+ BRCMS_SROM_PA1HIB0, -+ BRCMS_SROM_PA1HIB1, -+ BRCMS_SROM_PA1HIB2, -+ BRCMS_SROM_PA1HIMAXPWR, -+ BRCMS_SROM_PA1ITSSIT, -+ BRCMS_SROM_PA1LOB0, -+ BRCMS_SROM_PA1LOB1, -+ BRCMS_SROM_PA1LOB2, -+ BRCMS_SROM_PA1LOMAXPWR, -+ BRCMS_SROM_PA1MAXPWR, -+ BRCMS_SROM_PDETRANGE2G, -+ BRCMS_SROM_PDETRANGE5G, -+ BRCMS_SROM_PHYCAL_TEMPDELTA, -+ BRCMS_SROM_RAWTEMPSENSE, -+ BRCMS_SROM_REGREV, -+ BRCMS_SROM_REV, -+ BRCMS_SROM_RSSISAV2G, -+ BRCMS_SROM_RSSISAV5G, -+ BRCMS_SROM_RSSISMC2G, -+ BRCMS_SROM_RSSISMC5G, -+ BRCMS_SROM_RSSISMF2G, -+ BRCMS_SROM_RSSISMF5G, -+ BRCMS_SROM_RXCHAIN, -+ BRCMS_SROM_RXPO2G, -+ BRCMS_SROM_RXPO5G, -+ BRCMS_SROM_STBCPO, -+ BRCMS_SROM_TEMPCORRX, -+ BRCMS_SROM_TEMPOFFSET, -+ BRCMS_SROM_TEMPSENSE_OPTION, -+ BRCMS_SROM_TEMPSENSE_SLOPE, -+ BRCMS_SROM_TEMPTHRESH, -+ BRCMS_SROM_TRI2G, -+ BRCMS_SROM_TRI5GH, -+ BRCMS_SROM_TRI5GL, -+ BRCMS_SROM_TRI5G, -+ BRCMS_SROM_TRISO2G, -+ BRCMS_SROM_TRISO5G, -+ BRCMS_SROM_TSSIPOS2G, -+ BRCMS_SROM_TSSIPOS5G, -+ BRCMS_SROM_TXCHAIN, -+ BRCMS_SROM_TXPID2GA0, -+ BRCMS_SROM_TXPID2GA1, -+ BRCMS_SROM_TXPID2GA2, -+ BRCMS_SROM_TXPID2GA3, -+ BRCMS_SROM_TXPID5GA0, -+ BRCMS_SROM_TXPID5GA1, -+ BRCMS_SROM_TXPID5GA2, -+ BRCMS_SROM_TXPID5GA3, -+ BRCMS_SROM_TXPID5GHA0, -+ BRCMS_SROM_TXPID5GHA1, -+ BRCMS_SROM_TXPID5GHA2, -+ BRCMS_SROM_TXPID5GHA3, -+ BRCMS_SROM_TXPID5GLA0, -+ BRCMS_SROM_TXPID5GLA1, -+ BRCMS_SROM_TXPID5GLA2, -+ BRCMS_SROM_TXPID5GLA3, -+ /* -+ * per-path identifiers (see srom.c) -+ */ -+ BRCMS_SROM_ITT2GA0, -+ BRCMS_SROM_ITT2GA1, -+ BRCMS_SROM_ITT2GA2, -+ BRCMS_SROM_ITT2GA3, -+ BRCMS_SROM_ITT5GA0, -+ BRCMS_SROM_ITT5GA1, -+ BRCMS_SROM_ITT5GA2, -+ BRCMS_SROM_ITT5GA3, -+ BRCMS_SROM_MAXP2GA0, -+ BRCMS_SROM_MAXP2GA1, -+ BRCMS_SROM_MAXP2GA2, -+ BRCMS_SROM_MAXP2GA3, -+ BRCMS_SROM_MAXP5GA0, -+ BRCMS_SROM_MAXP5GA1, -+ BRCMS_SROM_MAXP5GA2, -+ BRCMS_SROM_MAXP5GA3, -+ BRCMS_SROM_MAXP5GHA0, -+ BRCMS_SROM_MAXP5GHA1, -+ BRCMS_SROM_MAXP5GHA2, -+ BRCMS_SROM_MAXP5GHA3, -+ BRCMS_SROM_MAXP5GLA0, -+ BRCMS_SROM_MAXP5GLA1, -+ BRCMS_SROM_MAXP5GLA2, -+ BRCMS_SROM_MAXP5GLA3, -+ BRCMS_SROM_PA2GW0A0, -+ BRCMS_SROM_PA2GW0A1, -+ BRCMS_SROM_PA2GW0A2, -+ BRCMS_SROM_PA2GW0A3, -+ BRCMS_SROM_PA2GW1A0, -+ BRCMS_SROM_PA2GW1A1, -+ BRCMS_SROM_PA2GW1A2, -+ BRCMS_SROM_PA2GW1A3, -+ BRCMS_SROM_PA2GW2A0, -+ BRCMS_SROM_PA2GW2A1, -+ BRCMS_SROM_PA2GW2A2, -+ BRCMS_SROM_PA2GW2A3, -+ BRCMS_SROM_PA2GW3A0, -+ BRCMS_SROM_PA2GW3A1, -+ BRCMS_SROM_PA2GW3A2, -+ BRCMS_SROM_PA2GW3A3, -+ BRCMS_SROM_PA5GHW0A0, -+ BRCMS_SROM_PA5GHW0A1, -+ BRCMS_SROM_PA5GHW0A2, -+ BRCMS_SROM_PA5GHW0A3, -+ BRCMS_SROM_PA5GHW1A0, -+ BRCMS_SROM_PA5GHW1A1, -+ BRCMS_SROM_PA5GHW1A2, -+ BRCMS_SROM_PA5GHW1A3, -+ BRCMS_SROM_PA5GHW2A0, -+ BRCMS_SROM_PA5GHW2A1, -+ BRCMS_SROM_PA5GHW2A2, -+ BRCMS_SROM_PA5GHW2A3, -+ BRCMS_SROM_PA5GHW3A0, -+ BRCMS_SROM_PA5GHW3A1, -+ BRCMS_SROM_PA5GHW3A2, -+ BRCMS_SROM_PA5GHW3A3, -+ BRCMS_SROM_PA5GLW0A0, -+ BRCMS_SROM_PA5GLW0A1, -+ BRCMS_SROM_PA5GLW0A2, -+ BRCMS_SROM_PA5GLW0A3, -+ BRCMS_SROM_PA5GLW1A0, -+ BRCMS_SROM_PA5GLW1A1, -+ BRCMS_SROM_PA5GLW1A2, -+ BRCMS_SROM_PA5GLW1A3, -+ BRCMS_SROM_PA5GLW2A0, -+ BRCMS_SROM_PA5GLW2A1, -+ BRCMS_SROM_PA5GLW2A2, -+ BRCMS_SROM_PA5GLW2A3, -+ BRCMS_SROM_PA5GLW3A0, -+ BRCMS_SROM_PA5GLW3A1, -+ BRCMS_SROM_PA5GLW3A2, -+ BRCMS_SROM_PA5GLW3A3, -+ BRCMS_SROM_PA5GW0A0, -+ BRCMS_SROM_PA5GW0A1, -+ BRCMS_SROM_PA5GW0A2, -+ BRCMS_SROM_PA5GW0A3, -+ BRCMS_SROM_PA5GW1A0, -+ BRCMS_SROM_PA5GW1A1, -+ BRCMS_SROM_PA5GW1A2, -+ BRCMS_SROM_PA5GW1A3, -+ BRCMS_SROM_PA5GW2A0, -+ BRCMS_SROM_PA5GW2A1, -+ BRCMS_SROM_PA5GW2A2, -+ BRCMS_SROM_PA5GW2A3, -+ BRCMS_SROM_PA5GW3A0, -+ BRCMS_SROM_PA5GW3A1, -+ BRCMS_SROM_PA5GW3A2, -+ BRCMS_SROM_PA5GW3A3, -+}; -+ -+#define BRCMS_NUMRATES 16 /* max # of rates in a rateset */ -+#define D11_PHY_HDR_LEN 6 /* Phy header length - 6 bytes */ -+ -+/* phy types */ -+#define PHY_TYPE_A 0 /* Phy type A */ -+#define PHY_TYPE_G 2 /* Phy type G */ -+#define PHY_TYPE_N 4 /* Phy type N */ -+#define PHY_TYPE_LP 5 /* Phy type Low Power A/B/G */ -+#define PHY_TYPE_SSN 6 /* Phy type Single Stream N */ -+#define PHY_TYPE_LCN 8 /* Phy type Single Stream N */ -+#define PHY_TYPE_LCNXN 9 /* Phy type 2-stream N */ -+#define PHY_TYPE_HT 7 /* Phy type 3-Stream N */ -+ -+/* bw */ -+#define BRCMS_10_MHZ 10 /* 10Mhz nphy channel bandwidth */ -+#define BRCMS_20_MHZ 20 /* 20Mhz nphy channel bandwidth */ -+#define BRCMS_40_MHZ 40 /* 40Mhz nphy channel bandwidth */ -+ -+#define BRCMS_RSSI_MINVAL -200 /* Low value, e.g. for forcing roam */ -+#define BRCMS_RSSI_NO_SIGNAL -91 /* NDIS RSSI link quality cutoffs */ -+#define BRCMS_RSSI_VERY_LOW -80 /* Very low quality cutoffs */ -+#define BRCMS_RSSI_LOW -70 /* Low quality cutoffs */ -+#define BRCMS_RSSI_GOOD -68 /* Good quality cutoffs */ -+#define BRCMS_RSSI_VERY_GOOD -58 /* Very good quality cutoffs */ -+#define BRCMS_RSSI_EXCELLENT -57 /* Excellent quality cutoffs */ -+ -+/* a large TX Power as an init value to factor out of min() calculations, -+ * keep low enough to fit in an s8, units are .25 dBm -+ */ -+#define BRCMS_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */ -+ -+/* rate related definitions */ -+#define BRCMS_RATE_FLAG 0x80 /* Flag to indicate it is a basic rate */ -+#define BRCMS_RATE_MASK 0x7f /* Rate value mask w/o basic rate flag */ -+ -+/* legacy rx Antenna diversity for SISO rates */ -+#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */ -+#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */ -+#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */ -+#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */ -+#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */ -+/* default antdiv setting */ -+#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0 -+ -+/* legacy rx Antenna diversity for SISO rates */ -+/* Tx on antenna 0, "legacy term Main" */ -+#define ANT_TX_FORCE_0 0 -+/* Tx on antenna 1, "legacy term Aux" */ -+#define ANT_TX_FORCE_1 1 -+/* Tx on phy's last good Rx antenna */ -+#define ANT_TX_LAST_RX 3 -+/* driver's default tx antenna setting */ -+#define ANT_TX_DEF 3 -+ -+/* Tx Chain values */ -+/* def bitmap of txchain */ -+#define TXCHAIN_DEF 0x1 -+/* default bitmap of tx chains for nphy */ -+#define TXCHAIN_DEF_NPHY 0x3 -+/* default bitmap of tx chains for nphy */ -+#define TXCHAIN_DEF_HTPHY 0x7 -+/* def bitmap of rxchain */ -+#define RXCHAIN_DEF 0x1 -+/* default bitmap of rx chains for nphy */ -+#define RXCHAIN_DEF_NPHY 0x3 -+/* default bitmap of rx chains for nphy */ -+#define RXCHAIN_DEF_HTPHY 0x7 -+/* no antenna switch */ -+#define ANTSWITCH_NONE 0 -+/* antenna switch on 4321CB2, 2of3 */ -+#define ANTSWITCH_TYPE_1 1 -+/* antenna switch on 4321MPCI, 2of3 */ -+#define ANTSWITCH_TYPE_2 2 -+/* antenna switch on 4322, 2of3 */ -+#define ANTSWITCH_TYPE_3 3 -+ -+#define RXBUFSZ PKTBUFSZ -+ -+#define MAX_STREAMS_SUPPORTED 4 /* max number of streams supported */ -+ -+struct brcm_rateset { -+ /* # rates in this set */ -+ u32 count; -+ /* rates in 500kbps units w/hi bit set if basic */ -+ u8 rates[WL_NUMRATES]; -+}; -+ -+struct brcms_c_rateset { -+ uint count; /* number of rates in rates[] */ -+ /* rates in 500kbps units w/hi bit set if basic */ -+ u8 rates[BRCMS_NUMRATES]; -+ u8 htphy_membership; /* HT PHY Membership */ -+ u8 mcs[MCSSET_LEN]; /* supported mcs index bit map */ -+}; -+ -+/* All the HT-specific default advertised capabilities (including AMPDU) -+ * should be grouped here at one place -+ */ -+#define AMPDU_DEF_MPDU_DENSITY 6 /* default mpdu density (110 ==> 4us) */ -+ -+/* wlc internal bss_info */ -+struct brcms_bss_info { -+ u8 BSSID[ETH_ALEN]; /* network BSSID */ -+ u16 flags; /* flags for internal attributes */ -+ u8 SSID_len; /* the length of SSID */ -+ u8 SSID[32]; /* SSID string */ -+ s16 RSSI; /* receive signal strength (in dBm) */ -+ s16 SNR; /* receive signal SNR in dB */ -+ u16 beacon_period; /* units are Kusec */ -+ u16 chanspec; /* Channel num, bw, ctrl_sb and band */ -+ struct brcms_c_rateset rateset; /* supported rates */ -+}; -+ -+#define MAC80211_PROMISC_BCNS (1 << 0) -+#define MAC80211_SCAN (1 << 1) -+ -+/* -+ * Public portion of common driver state structure. -+ * The wlc handle points at this. -+ */ -+struct brcms_pub { -+ struct brcms_c_info *wlc; -+ struct ieee80211_hw *ieee_hw; -+ struct scb_ampdu *global_ampdu; -+ uint mac80211_state; -+ uint unit; /* device instance number */ -+ uint corerev; /* core revision */ -+ struct si_pub *sih; /* SI handle (cookie for siutils calls) */ -+ bool up; /* interface up and running */ -+ bool hw_off; /* HW is off */ -+ bool hw_up; /* one time hw up/down */ -+ bool _piomode; /* true if pio mode */ -+ uint _nbands; /* # bands supported */ -+ uint now; /* # elapsed seconds */ -+ -+ bool promisc; /* promiscuous destination address */ -+ bool delayed_down; /* down delayed */ -+ bool associated; /* true:part of [I]BSS, false: not */ -+ /* (union of stas_associated, aps_associated) */ -+ bool _ampdu; /* ampdu enabled or not */ -+ u8 _n_enab; /* bitmap of 11N + HT support */ -+ -+ u8 cur_etheraddr[ETH_ALEN]; /* our local ethernet address */ -+ -+ int bcmerror; /* last bcm error */ -+ -+ u32 radio_disabled; /* bit vector for radio disabled reasons */ -+ -+ u16 boardrev; /* version # of particular board */ -+ u8 sromrev; /* version # of the srom */ -+ char srom_ccode[BRCM_CNTRY_BUF_SZ]; /* Country Code in SROM */ -+ u32 boardflags; /* Board specific flags from srom */ -+ u32 boardflags2; /* More board flags if sromrev >= 4 */ -+ bool phy_11ncapable; /* the PHY/HW is capable of 802.11N */ -+ -+ struct wl_cnt *_cnt; /* low-level counters in driver */ -+}; -+ -+enum wlc_par_id { -+ IOV_MPC = 1, -+ IOV_RTSTHRESH, -+ IOV_QTXPOWER, -+ IOV_BCN_LI_BCN /* Beacon listen interval in # of beacons */ -+}; -+ -+/*********************************************** -+ * Feature-related macros to optimize out code * -+ * ********************************************* -+ */ -+ -+#define ENAB_1x1 0x01 -+#define ENAB_2x2 0x02 -+#define ENAB_3x3 0x04 -+#define ENAB_4x4 0x08 -+#define SUPPORT_11N (ENAB_1x1|ENAB_2x2) -+#define SUPPORT_HT (ENAB_1x1|ENAB_2x2|ENAB_3x3) -+ -+/* WL11N Support */ -+#define AMPDU_AGG_HOST 1 -+ -+/* pri is priority encoded in the packet. This maps the Packet priority to -+ * enqueue precedence as defined in wlc_prec_map -+ */ -+extern const u8 wlc_prio2prec_map[]; -+#define BRCMS_PRIO_TO_PREC(pri) wlc_prio2prec_map[(pri) & 7] -+ -+#define BRCMS_PREC_COUNT 16 /* Max precedence level implemented */ -+ -+/* Mask to describe all precedence levels */ -+#define BRCMS_PREC_BMP_ALL MAXBITVAL(BRCMS_PREC_COUNT) -+ -+/* -+ * This maps priority to one precedence higher - Used by PS-Poll response -+ * packets to simulate enqueue-at-head operation, but still maintain the -+ * order on the queue -+ */ -+#define BRCMS_PRIO_TO_HI_PREC(pri) min(BRCMS_PRIO_TO_PREC(pri) + 1,\ -+ BRCMS_PREC_COUNT - 1) -+ -+/* Define a bitmap of precedences comprised by each AC */ -+#define BRCMS_PREC_BMP_AC_BE (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BE)) | \ -+ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BE)) | \ -+ NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_EE)) | \ -+ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_EE))) -+#define BRCMS_PREC_BMP_AC_BK (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BK)) | \ -+ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BK)) | \ -+ NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NONE)) | \ -+ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NONE))) -+#define BRCMS_PREC_BMP_AC_VI (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_CL)) | \ -+ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_CL)) | \ -+ NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VI)) | \ -+ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VI))) -+#define BRCMS_PREC_BMP_AC_VO (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VO)) | \ -+ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VO)) | \ -+ NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NC)) | \ -+ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NC))) -+ -+/* network protection config */ -+#define BRCMS_PROT_G_SPEC 1 /* SPEC g protection */ -+#define BRCMS_PROT_G_OVR 2 /* SPEC g prot override */ -+#define BRCMS_PROT_G_USER 3 /* gmode specified by user */ -+#define BRCMS_PROT_OVERLAP 4 /* overlap */ -+#define BRCMS_PROT_N_USER 10 /* nmode specified by user */ -+#define BRCMS_PROT_N_CFG 11 /* n protection */ -+#define BRCMS_PROT_N_CFG_OVR 12 /* n protection override */ -+#define BRCMS_PROT_N_NONGF 13 /* non-GF protection */ -+#define BRCMS_PROT_N_NONGF_OVR 14 /* non-GF protection override */ -+#define BRCMS_PROT_N_PAM_OVR 15 /* n preamble override */ -+#define BRCMS_PROT_N_OBSS 16 /* non-HT OBSS present */ -+ -+/* -+ * 54g modes (basic bits may still be overridden) -+ * -+ * GMODE_LEGACY_B -+ * Rateset: 1b, 2b, 5.5, 11 -+ * Preamble: Long -+ * Shortslot: Off -+ * GMODE_AUTO -+ * Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 -+ * Extended Rateset: 6, 9, 12, 48 -+ * Preamble: Long -+ * Shortslot: Auto -+ * GMODE_ONLY -+ * Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54 -+ * Extended Rateset: 6b, 9, 12b, 48 -+ * Preamble: Short required -+ * Shortslot: Auto -+ * GMODE_B_DEFERRED -+ * Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 -+ * Extended Rateset: 6, 9, 12, 48 -+ * Preamble: Long -+ * Shortslot: On -+ * GMODE_PERFORMANCE -+ * Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54 -+ * Preamble: Short required -+ * Shortslot: On and required -+ * GMODE_LRS -+ * Rateset: 1b, 2b, 5.5b, 11b -+ * Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54 -+ * Preamble: Long -+ * Shortslot: Auto -+ */ -+#define GMODE_LEGACY_B 0 -+#define GMODE_AUTO 1 -+#define GMODE_ONLY 2 -+#define GMODE_B_DEFERRED 3 -+#define GMODE_PERFORMANCE 4 -+#define GMODE_LRS 5 -+#define GMODE_MAX 6 -+ -+/* MCS values greater than this enable multiple streams */ -+#define HIGHEST_SINGLE_STREAM_MCS 7 -+ -+#define MAXBANDS 2 /* Maximum #of bands */ -+ -+/* max number of antenna configurations */ -+#define ANT_SELCFG_MAX 4 -+ -+struct brcms_antselcfg { -+ u8 ant_config[ANT_SELCFG_MAX]; /* antenna configuration */ -+ u8 num_antcfg; /* number of available antenna configurations */ -+}; -+ -+/* common functions for every port */ -+extern struct brcms_c_info * -+brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit, -+ bool piomode, void __iomem *regsva, struct pci_dev *btparam, -+ uint *perr); -+extern uint brcms_c_detach(struct brcms_c_info *wlc); -+extern int brcms_c_up(struct brcms_c_info *wlc); -+extern uint brcms_c_down(struct brcms_c_info *wlc); -+ -+extern bool brcms_c_chipmatch(u16 vendor, u16 device); -+extern void brcms_c_init(struct brcms_c_info *wlc); -+extern void brcms_c_reset(struct brcms_c_info *wlc); -+ -+extern void brcms_c_intrson(struct brcms_c_info *wlc); -+extern u32 brcms_c_intrsoff(struct brcms_c_info *wlc); -+extern void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask); -+extern bool brcms_c_intrsupd(struct brcms_c_info *wlc); -+extern bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc); -+extern bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded); -+extern void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, -+ struct sk_buff *sdu, -+ struct ieee80211_hw *hw); -+extern bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid); -+extern void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, -+ int val); -+extern int brcms_c_get_header_len(void); -+extern void brcms_c_set_addrmatch(struct brcms_c_info *wlc, -+ int match_reg_offset, -+ const u8 *addr); -+extern void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci, -+ const struct ieee80211_tx_queue_params *arg, -+ bool suspend); -+extern struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc); -+extern void brcms_c_ampdu_flush(struct brcms_c_info *wlc, -+ struct ieee80211_sta *sta, u16 tid); -+extern void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, -+ u8 ba_wsize, uint max_rx_ampdu_bytes); -+extern char *getvar(struct si_pub *sih, enum brcms_srom_id id); -+extern int getintvar(struct si_pub *sih, enum brcms_srom_id id); -+extern int brcms_c_module_register(struct brcms_pub *pub, -+ const char *name, struct brcms_info *hdl, -+ int (*down_fn)(void *handle)); -+extern int brcms_c_module_unregister(struct brcms_pub *pub, const char *name, -+ struct brcms_info *hdl); -+extern void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc); -+extern void brcms_c_enable_mac(struct brcms_c_info *wlc); -+extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state); -+extern void brcms_c_scan_start(struct brcms_c_info *wlc); -+extern void brcms_c_scan_stop(struct brcms_c_info *wlc); -+extern int brcms_c_get_curband(struct brcms_c_info *wlc); -+extern void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, -+ bool drop); -+extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel); -+extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl); -+extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc, -+ struct brcm_rateset *currs); -+extern int brcms_c_set_rateset(struct brcms_c_info *wlc, -+ struct brcm_rateset *rs); -+extern int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period); -+extern u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx); -+extern void brcms_c_set_shortslot_override(struct brcms_c_info *wlc, -+ s8 sslot_override); -+extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, -+ u8 interval); -+extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr); -+extern int brcms_c_get_tx_power(struct brcms_c_info *wlc); -+extern void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc); -+extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); -+ -+#endif /* _BRCM_PUB_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.c.orig 2011-11-09 13:46:58.284800145 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.c 2011-11-09 13:47:17.042565640 -0500 -@@ -0,0 +1,514 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+ -+#include "d11.h" -+#include "pub.h" -+#include "rate.h" -+ -+/* -+ * Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate -+ * value -+ */ -+const u8 rate_info[BRCM_MAXRATE + 1] = { -+ /* 0 1 2 3 4 5 6 7 8 9 */ -+/* 0 */ 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, -+/* 10 */ 0x00, 0x37, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00, -+/* 20 */ 0x00, 0x00, 0x6e, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, -+/* 30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, -+/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, -+/* 50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+/* 60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+/* 70 */ 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+/* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+/* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, -+/* 100 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c -+}; -+ -+/* rates are in units of Kbps */ -+const struct brcms_mcs_info mcs_table[MCS_TABLE_SIZE] = { -+ /* MCS 0: SS 1, MOD: BPSK, CR 1/2 */ -+ {6500, 13500, CEIL(6500 * 10, 9), CEIL(13500 * 10, 9), 0x00, -+ BRCM_RATE_6M}, -+ /* MCS 1: SS 1, MOD: QPSK, CR 1/2 */ -+ {13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x08, -+ BRCM_RATE_12M}, -+ /* MCS 2: SS 1, MOD: QPSK, CR 3/4 */ -+ {19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x0A, -+ BRCM_RATE_18M}, -+ /* MCS 3: SS 1, MOD: 16QAM, CR 1/2 */ -+ {26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x10, -+ BRCM_RATE_24M}, -+ /* MCS 4: SS 1, MOD: 16QAM, CR 3/4 */ -+ {39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x12, -+ BRCM_RATE_36M}, -+ /* MCS 5: SS 1, MOD: 64QAM, CR 2/3 */ -+ {52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x19, -+ BRCM_RATE_48M}, -+ /* MCS 6: SS 1, MOD: 64QAM, CR 3/4 */ -+ {58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x1A, -+ BRCM_RATE_54M}, -+ /* MCS 7: SS 1, MOD: 64QAM, CR 5/6 */ -+ {65000, 135000, CEIL(65000 * 10, 9), CEIL(135000 * 10, 9), 0x1C, -+ BRCM_RATE_54M}, -+ /* MCS 8: SS 2, MOD: BPSK, CR 1/2 */ -+ {13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x40, -+ BRCM_RATE_6M}, -+ /* MCS 9: SS 2, MOD: QPSK, CR 1/2 */ -+ {26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x48, -+ BRCM_RATE_12M}, -+ /* MCS 10: SS 2, MOD: QPSK, CR 3/4 */ -+ {39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x4A, -+ BRCM_RATE_18M}, -+ /* MCS 11: SS 2, MOD: 16QAM, CR 1/2 */ -+ {52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x50, -+ BRCM_RATE_24M}, -+ /* MCS 12: SS 2, MOD: 16QAM, CR 3/4 */ -+ {78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x52, -+ BRCM_RATE_36M}, -+ /* MCS 13: SS 2, MOD: 64QAM, CR 2/3 */ -+ {104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0x59, -+ BRCM_RATE_48M}, -+ /* MCS 14: SS 2, MOD: 64QAM, CR 3/4 */ -+ {117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x5A, -+ BRCM_RATE_54M}, -+ /* MCS 15: SS 2, MOD: 64QAM, CR 5/6 */ -+ {130000, 270000, CEIL(130000 * 10, 9), CEIL(270000 * 10, 9), 0x5C, -+ BRCM_RATE_54M}, -+ /* MCS 16: SS 3, MOD: BPSK, CR 1/2 */ -+ {19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x80, -+ BRCM_RATE_6M}, -+ /* MCS 17: SS 3, MOD: QPSK, CR 1/2 */ -+ {39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x88, -+ BRCM_RATE_12M}, -+ /* MCS 18: SS 3, MOD: QPSK, CR 3/4 */ -+ {58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x8A, -+ BRCM_RATE_18M}, -+ /* MCS 19: SS 3, MOD: 16QAM, CR 1/2 */ -+ {78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x90, -+ BRCM_RATE_24M}, -+ /* MCS 20: SS 3, MOD: 16QAM, CR 3/4 */ -+ {117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x92, -+ BRCM_RATE_36M}, -+ /* MCS 21: SS 3, MOD: 64QAM, CR 2/3 */ -+ {156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0x99, -+ BRCM_RATE_48M}, -+ /* MCS 22: SS 3, MOD: 64QAM, CR 3/4 */ -+ {175500, 364500, CEIL(175500 * 10, 9), CEIL(364500 * 10, 9), 0x9A, -+ BRCM_RATE_54M}, -+ /* MCS 23: SS 3, MOD: 64QAM, CR 5/6 */ -+ {195000, 405000, CEIL(195000 * 10, 9), CEIL(405000 * 10, 9), 0x9B, -+ BRCM_RATE_54M}, -+ /* MCS 24: SS 4, MOD: BPSK, CR 1/2 */ -+ {26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0xC0, -+ BRCM_RATE_6M}, -+ /* MCS 25: SS 4, MOD: QPSK, CR 1/2 */ -+ {52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0xC8, -+ BRCM_RATE_12M}, -+ /* MCS 26: SS 4, MOD: QPSK, CR 3/4 */ -+ {78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0xCA, -+ BRCM_RATE_18M}, -+ /* MCS 27: SS 4, MOD: 16QAM, CR 1/2 */ -+ {104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0xD0, -+ BRCM_RATE_24M}, -+ /* MCS 28: SS 4, MOD: 16QAM, CR 3/4 */ -+ {156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0xD2, -+ BRCM_RATE_36M}, -+ /* MCS 29: SS 4, MOD: 64QAM, CR 2/3 */ -+ {208000, 432000, CEIL(208000 * 10, 9), CEIL(432000 * 10, 9), 0xD9, -+ BRCM_RATE_48M}, -+ /* MCS 30: SS 4, MOD: 64QAM, CR 3/4 */ -+ {234000, 486000, CEIL(234000 * 10, 9), CEIL(486000 * 10, 9), 0xDA, -+ BRCM_RATE_54M}, -+ /* MCS 31: SS 4, MOD: 64QAM, CR 5/6 */ -+ {260000, 540000, CEIL(260000 * 10, 9), CEIL(540000 * 10, 9), 0xDB, -+ BRCM_RATE_54M}, -+ /* MCS 32: SS 1, MOD: BPSK, CR 1/2 */ -+ {0, 6000, 0, CEIL(6000 * 10, 9), 0x00, BRCM_RATE_6M}, -+}; -+ -+/* -+ * phycfg for legacy OFDM frames: code rate, modulation scheme, spatial streams -+ * Number of spatial streams: always 1 other fields: refer to table 78 of -+ * section 17.3.2.2 of the original .11a standard -+ */ -+struct legacy_phycfg { -+ u32 rate_ofdm; /* ofdm mac rate */ -+ /* phy ctl byte 3, code rate, modulation type, # of streams */ -+ u8 tx_phy_ctl3; -+}; -+ -+/* Number of legacy_rate_cfg entries in the table */ -+#define LEGACY_PHYCFG_TABLE_SIZE 12 -+ -+/* -+ * In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate -+ * Eventually MIMOPHY would also be converted to this format -+ * 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps -+ */ -+static const struct -+legacy_phycfg legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = { -+ {BRCM_RATE_1M, 0x00}, /* CCK 1Mbps, data rate 0 */ -+ {BRCM_RATE_2M, 0x08}, /* CCK 2Mbps, data rate 1 */ -+ {BRCM_RATE_5M5, 0x10}, /* CCK 5.5Mbps, data rate 2 */ -+ {BRCM_RATE_11M, 0x18}, /* CCK 11Mbps, data rate 3 */ -+ /* OFDM 6Mbps, code rate 1/2, BPSK, 1 spatial stream */ -+ {BRCM_RATE_6M, 0x00}, -+ /* OFDM 9Mbps, code rate 3/4, BPSK, 1 spatial stream */ -+ {BRCM_RATE_9M, 0x02}, -+ /* OFDM 12Mbps, code rate 1/2, QPSK, 1 spatial stream */ -+ {BRCM_RATE_12M, 0x08}, -+ /* OFDM 18Mbps, code rate 3/4, QPSK, 1 spatial stream */ -+ {BRCM_RATE_18M, 0x0A}, -+ /* OFDM 24Mbps, code rate 1/2, 16-QAM, 1 spatial stream */ -+ {BRCM_RATE_24M, 0x10}, -+ /* OFDM 36Mbps, code rate 3/4, 16-QAM, 1 spatial stream */ -+ {BRCM_RATE_36M, 0x12}, -+ /* OFDM 48Mbps, code rate 2/3, 64-QAM, 1 spatial stream */ -+ {BRCM_RATE_48M, 0x19}, -+ /* OFDM 54Mbps, code rate 3/4, 64-QAM, 1 spatial stream */ -+ {BRCM_RATE_54M, 0x1A}, -+}; -+ -+/* Hardware rates (also encodes default basic rates) */ -+ -+const struct brcms_c_rateset cck_ofdm_mimo_rates = { -+ 12, -+ /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, */ -+ { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, -+ /* 54 Mbps */ -+ 0x6c}, -+ 0x00, -+ { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00} -+}; -+ -+const struct brcms_c_rateset ofdm_mimo_rates = { -+ 8, -+ /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */ -+ { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c}, -+ 0x00, -+ { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00} -+}; -+ -+/* Default ratesets that include MCS32 for 40BW channels */ -+static const struct brcms_c_rateset cck_ofdm_40bw_mimo_rates = { -+ 12, -+ /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48 */ -+ { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, -+ /* 54 Mbps */ -+ 0x6c}, -+ 0x00, -+ { 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00} -+}; -+ -+static const struct brcms_c_rateset ofdm_40bw_mimo_rates = { -+ 8, -+ /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */ -+ { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c}, -+ 0x00, -+ { 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00} -+}; -+ -+const struct brcms_c_rateset cck_ofdm_rates = { -+ 12, -+ /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48,*/ -+ { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, -+ /*54 Mbps */ -+ 0x6c}, -+ 0x00, -+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00} -+}; -+ -+const struct brcms_c_rateset gphy_legacy_rates = { -+ 4, -+ /* 1b, 2b, 5.5b, 11b Mbps */ -+ { 0x82, 0x84, 0x8b, 0x96}, -+ 0x00, -+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00} -+}; -+ -+const struct brcms_c_rateset ofdm_rates = { -+ 8, -+ /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */ -+ { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c}, -+ 0x00, -+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00} -+}; -+ -+const struct brcms_c_rateset cck_rates = { -+ 4, -+ /* 1b, 2b, 5.5, 11 Mbps */ -+ { 0x82, 0x84, 0x0b, 0x16}, -+ 0x00, -+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00} -+}; -+ -+/* check if rateset is valid. -+ * if check_brate is true, rateset without a basic rate is considered NOT valid. -+ */ -+static bool brcms_c_rateset_valid(struct brcms_c_rateset *rs, bool check_brate) -+{ -+ uint idx; -+ -+ if (!rs->count) -+ return false; -+ -+ if (!check_brate) -+ return true; -+ -+ /* error if no basic rates */ -+ for (idx = 0; idx < rs->count; idx++) { -+ if (rs->rates[idx] & BRCMS_RATE_FLAG) -+ return true; -+ } -+ return false; -+} -+ -+void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams) -+{ -+ int i; -+ for (i = txstreams; i < MAX_STREAMS_SUPPORTED; i++) -+ rs->mcs[i] = 0; -+} -+ -+/* -+ * filter based on hardware rateset, and sort filtered rateset with basic -+ * bit(s) preserved, and check if resulting rateset is valid. -+*/ -+bool -+brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs, -+ const struct brcms_c_rateset *hw_rs, -+ bool check_brate, u8 txstreams) -+{ -+ u8 rateset[BRCM_MAXRATE + 1]; -+ u8 r; -+ uint count; -+ uint i; -+ -+ memset(rateset, 0, sizeof(rateset)); -+ count = rs->count; -+ -+ for (i = 0; i < count; i++) { -+ /* mask off "basic rate" bit, BRCMS_RATE_FLAG */ -+ r = (int)rs->rates[i] & BRCMS_RATE_MASK; -+ if ((r > BRCM_MAXRATE) || (rate_info[r] == 0)) -+ continue; -+ rateset[r] = rs->rates[i]; /* preserve basic bit! */ -+ } -+ -+ /* fill out the rates in order, looking at only supported rates */ -+ count = 0; -+ for (i = 0; i < hw_rs->count; i++) { -+ r = hw_rs->rates[i] & BRCMS_RATE_MASK; -+ if (rateset[r]) -+ rs->rates[count++] = rateset[r]; -+ } -+ -+ rs->count = count; -+ -+ /* only set the mcs rate bit if the equivalent hw mcs bit is set */ -+ for (i = 0; i < MCSSET_LEN; i++) -+ rs->mcs[i] = (rs->mcs[i] & hw_rs->mcs[i]); -+ -+ if (brcms_c_rateset_valid(rs, check_brate)) -+ return true; -+ else -+ return false; -+} -+ -+/* calculate the rate of a rx'd frame and return it as a ratespec */ -+u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp) -+{ -+ int phy_type; -+ u32 rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT; -+ -+ phy_type = -+ ((rxh->RxChan & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT); -+ -+ if ((phy_type == PHY_TYPE_N) || (phy_type == PHY_TYPE_SSN) || -+ (phy_type == PHY_TYPE_LCN) || (phy_type == PHY_TYPE_HT)) { -+ switch (rxh->PhyRxStatus_0 & PRXS0_FT_MASK) { -+ case PRXS0_CCK: -+ rspec = -+ cck_phy2mac_rate( -+ ((struct cck_phy_hdr *) plcp)->signal); -+ break; -+ case PRXS0_OFDM: -+ rspec = -+ ofdm_phy2mac_rate( -+ ((struct ofdm_phy_hdr *) plcp)->rlpt[0]); -+ break; -+ case PRXS0_PREN: -+ rspec = (plcp[0] & MIMO_PLCP_MCS_MASK) | RSPEC_MIMORATE; -+ if (plcp[0] & MIMO_PLCP_40MHZ) { -+ /* indicate rspec is for 40 MHz mode */ -+ rspec &= ~RSPEC_BW_MASK; -+ rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT); -+ } -+ break; -+ case PRXS0_STDN: -+ /* fallthru */ -+ default: -+ /* not supported, error condition */ -+ break; -+ } -+ if (plcp3_issgi(plcp[3])) -+ rspec |= RSPEC_SHORT_GI; -+ } else -+ if ((phy_type == PHY_TYPE_A) || (rxh->PhyRxStatus_0 & PRXS0_OFDM)) -+ rspec = ofdm_phy2mac_rate( -+ ((struct ofdm_phy_hdr *) plcp)->rlpt[0]); -+ else -+ rspec = cck_phy2mac_rate( -+ ((struct cck_phy_hdr *) plcp)->signal); -+ -+ return rspec; -+} -+ -+/* copy rateset src to dst as-is (no masking or sorting) */ -+void brcms_c_rateset_copy(const struct brcms_c_rateset *src, -+ struct brcms_c_rateset *dst) -+{ -+ memcpy(dst, src, sizeof(struct brcms_c_rateset)); -+} -+ -+/* -+ * Copy and selectively filter one rateset to another. -+ * 'basic_only' means only copy basic rates. -+ * 'rates' indicates cck (11b) and ofdm rates combinations. -+ * - 0: cck and ofdm -+ * - 1: cck only -+ * - 2: ofdm only -+ * 'xmask' is the copy mask (typically 0x7f or 0xff). -+ */ -+void -+brcms_c_rateset_filter(struct brcms_c_rateset *src, struct brcms_c_rateset *dst, -+ bool basic_only, u8 rates, uint xmask, bool mcsallow) -+{ -+ uint i; -+ uint r; -+ uint count; -+ -+ count = 0; -+ for (i = 0; i < src->count; i++) { -+ r = src->rates[i]; -+ if (basic_only && !(r & BRCMS_RATE_FLAG)) -+ continue; -+ if (rates == BRCMS_RATES_CCK && -+ is_ofdm_rate((r & BRCMS_RATE_MASK))) -+ continue; -+ if (rates == BRCMS_RATES_OFDM && -+ is_cck_rate((r & BRCMS_RATE_MASK))) -+ continue; -+ dst->rates[count++] = r & xmask; -+ } -+ dst->count = count; -+ dst->htphy_membership = src->htphy_membership; -+ -+ if (mcsallow && rates != BRCMS_RATES_CCK) -+ memcpy(&dst->mcs[0], &src->mcs[0], MCSSET_LEN); -+ else -+ brcms_c_rateset_mcs_clear(dst); -+} -+ -+/* select rateset for a given phy_type and bandtype and filter it, sort it -+ * and fill rs_tgt with result -+ */ -+void -+brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt, -+ const struct brcms_c_rateset *rs_hw, -+ uint phy_type, int bandtype, bool cck_only, -+ uint rate_mask, bool mcsallow, u8 bw, u8 txstreams) -+{ -+ const struct brcms_c_rateset *rs_dflt; -+ struct brcms_c_rateset rs_sel; -+ if ((PHYTYPE_IS(phy_type, PHY_TYPE_HT)) || -+ (PHYTYPE_IS(phy_type, PHY_TYPE_N)) || -+ (PHYTYPE_IS(phy_type, PHY_TYPE_LCN)) || -+ (PHYTYPE_IS(phy_type, PHY_TYPE_SSN))) { -+ if (bandtype == BRCM_BAND_5G) -+ rs_dflt = (bw == BRCMS_20_MHZ ? -+ &ofdm_mimo_rates : &ofdm_40bw_mimo_rates); -+ else -+ rs_dflt = (bw == BRCMS_20_MHZ ? -+ &cck_ofdm_mimo_rates : -+ &cck_ofdm_40bw_mimo_rates); -+ } else if (PHYTYPE_IS(phy_type, PHY_TYPE_LP)) { -+ rs_dflt = (bandtype == BRCM_BAND_5G) ? -+ &ofdm_rates : &cck_ofdm_rates; -+ } else if (PHYTYPE_IS(phy_type, PHY_TYPE_A)) { -+ rs_dflt = &ofdm_rates; -+ } else if (PHYTYPE_IS(phy_type, PHY_TYPE_G)) { -+ rs_dflt = &cck_ofdm_rates; -+ } else { -+ /* should not happen, error condition */ -+ rs_dflt = &cck_rates; /* force cck */ -+ } -+ -+ /* if hw rateset is not supplied, assign selected rateset to it */ -+ if (!rs_hw) -+ rs_hw = rs_dflt; -+ -+ brcms_c_rateset_copy(rs_dflt, &rs_sel); -+ brcms_c_rateset_mcs_upd(&rs_sel, txstreams); -+ brcms_c_rateset_filter(&rs_sel, rs_tgt, false, -+ cck_only ? BRCMS_RATES_CCK : BRCMS_RATES_CCK_OFDM, -+ rate_mask, mcsallow); -+ brcms_c_rate_hwrs_filter_sort_validate(rs_tgt, rs_hw, false, -+ mcsallow ? txstreams : 1); -+} -+ -+s16 brcms_c_rate_legacy_phyctl(uint rate) -+{ -+ uint i; -+ for (i = 0; i < LEGACY_PHYCFG_TABLE_SIZE; i++) -+ if (rate == legacy_phycfg_table[i].rate_ofdm) -+ return legacy_phycfg_table[i].tx_phy_ctl3; -+ -+ return -1; -+} -+ -+void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset) -+{ -+ uint i; -+ for (i = 0; i < MCSSET_LEN; i++) -+ rateset->mcs[i] = 0; -+} -+ -+void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, u8 txstreams) -+{ -+ memcpy(&rateset->mcs[0], &cck_ofdm_mimo_rates.mcs[0], MCSSET_LEN); -+ brcms_c_rateset_mcs_upd(rateset, txstreams); -+} -+ -+/* Based on bandwidth passed, allow/disallow MCS 32 in the rateset */ -+void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, u8 bw) -+{ -+ if (bw == BRCMS_40_MHZ) -+ setbit(rateset->mcs, 32); -+ else -+ clrbit(rateset->mcs, 32); -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.h.orig 2011-11-09 13:46:58.284800145 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.h 2011-11-09 13:47:17.043565628 -0500 -@@ -0,0 +1,250 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_RATE_H_ -+#define _BRCM_RATE_H_ -+ -+#include "types.h" -+#include "d11.h" -+ -+extern const u8 rate_info[]; -+extern const struct brcms_c_rateset cck_ofdm_mimo_rates; -+extern const struct brcms_c_rateset ofdm_mimo_rates; -+extern const struct brcms_c_rateset cck_ofdm_rates; -+extern const struct brcms_c_rateset ofdm_rates; -+extern const struct brcms_c_rateset cck_rates; -+extern const struct brcms_c_rateset gphy_legacy_rates; -+extern const struct brcms_c_rateset rate_limit_1_2; -+ -+struct brcms_mcs_info { -+ /* phy rate in kbps [20Mhz] */ -+ u32 phy_rate_20; -+ /* phy rate in kbps [40Mhz] */ -+ u32 phy_rate_40; -+ /* phy rate in kbps [20Mhz] with SGI */ -+ u32 phy_rate_20_sgi; -+ /* phy rate in kbps [40Mhz] with SGI */ -+ u32 phy_rate_40_sgi; -+ /* phy ctl byte 3, code rate, modulation type, # of streams */ -+ u8 tx_phy_ctl3; -+ /* matching legacy ofdm rate in 500bkps */ -+ u8 leg_ofdm; -+}; -+ -+#define BRCMS_MAXMCS 32 /* max valid mcs index */ -+#define MCS_TABLE_SIZE 33 /* Number of mcs entries in the table */ -+extern const struct brcms_mcs_info mcs_table[]; -+ -+#define MCS_TXS_MASK 0xc0 /* num tx streams - 1 bit mask */ -+#define MCS_TXS_SHIFT 6 /* num tx streams - 1 bit shift */ -+ -+/* returns num tx streams - 1 */ -+static inline u8 mcs_2_txstreams(u8 mcs) -+{ -+ return (mcs_table[mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT; -+} -+ -+static inline uint mcs_2_rate(u8 mcs, bool is40, bool sgi) -+{ -+ if (sgi) { -+ if (is40) -+ return mcs_table[mcs].phy_rate_40_sgi; -+ return mcs_table[mcs].phy_rate_20_sgi; -+ } -+ if (is40) -+ return mcs_table[mcs].phy_rate_40; -+ -+ return mcs_table[mcs].phy_rate_20; -+} -+ -+/* Macro to use the rate_info table */ -+#define BRCMS_RATE_MASK_FULL 0xff /* Rate value mask with basic rate flag */ -+ -+/* -+ * rate spec : holds rate and mode specific information required to generate a -+ * tx frame. Legacy CCK and OFDM information is held in the same manner as was -+ * done in the past (in the lower byte) the upper 3 bytes primarily hold MIMO -+ * specific information -+ */ -+ -+/* rate spec bit fields */ -+ -+/* Either 500Kbps units or MIMO MCS idx */ -+#define RSPEC_RATE_MASK 0x0000007F -+/* mimo MCS is stored in RSPEC_RATE_MASK */ -+#define RSPEC_MIMORATE 0x08000000 -+/* mimo bw mask */ -+#define RSPEC_BW_MASK 0x00000700 -+/* mimo bw shift */ -+#define RSPEC_BW_SHIFT 8 -+/* mimo Space/Time/Frequency mode mask */ -+#define RSPEC_STF_MASK 0x00003800 -+/* mimo Space/Time/Frequency mode shift */ -+#define RSPEC_STF_SHIFT 11 -+/* mimo coding type mask */ -+#define RSPEC_CT_MASK 0x0000C000 -+/* mimo coding type shift */ -+#define RSPEC_CT_SHIFT 14 -+/* mimo num STC streams per PLCP defn. */ -+#define RSPEC_STC_MASK 0x00300000 -+/* mimo num STC streams per PLCP defn. */ -+#define RSPEC_STC_SHIFT 20 -+/* mimo bit indicates adv coding in use */ -+#define RSPEC_LDPC_CODING 0x00400000 -+/* mimo bit indicates short GI in use */ -+#define RSPEC_SHORT_GI 0x00800000 -+/* bit indicates override both rate & mode */ -+#define RSPEC_OVERRIDE 0x80000000 -+/* bit indicates override rate only */ -+#define RSPEC_OVERRIDE_MCS_ONLY 0x40000000 -+ -+static inline bool rspec_active(u32 rspec) -+{ -+ return rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE); -+} -+ -+static inline u8 rspec_phytxbyte2(u32 rspec) -+{ -+ return (rspec & 0xff00) >> 8; -+} -+ -+static inline u32 rspec_get_bw(u32 rspec) -+{ -+ return (rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT; -+} -+ -+static inline bool rspec_issgi(u32 rspec) -+{ -+ return (rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI; -+} -+ -+static inline bool rspec_is40mhz(u32 rspec) -+{ -+ u32 bw = rspec_get_bw(rspec); -+ -+ return bw == PHY_TXC1_BW_40MHZ || bw == PHY_TXC1_BW_40MHZ_DUP; -+} -+ -+static inline uint rspec2rate(u32 rspec) -+{ -+ if (rspec & RSPEC_MIMORATE) -+ return mcs_2_rate(rspec & RSPEC_RATE_MASK, rspec_is40mhz(rspec), -+ rspec_issgi(rspec)); -+ return rspec & RSPEC_RATE_MASK; -+} -+ -+static inline u8 rspec_mimoplcp3(u32 rspec) -+{ -+ return (rspec & 0xf00000) >> 16; -+} -+ -+static inline bool plcp3_issgi(u8 plcp) -+{ -+ return (plcp & (RSPEC_SHORT_GI >> 16)) != 0; -+} -+ -+static inline uint rspec_stc(u32 rspec) -+{ -+ return (rspec & RSPEC_STC_MASK) >> RSPEC_STC_SHIFT; -+} -+ -+static inline uint rspec_stf(u32 rspec) -+{ -+ return (rspec & RSPEC_STF_MASK) >> RSPEC_STF_SHIFT; -+} -+ -+static inline bool is_mcs_rate(u32 ratespec) -+{ -+ return (ratespec & RSPEC_MIMORATE) != 0; -+} -+ -+static inline bool is_ofdm_rate(u32 ratespec) -+{ -+ return !is_mcs_rate(ratespec) && -+ (rate_info[ratespec & RSPEC_RATE_MASK] & BRCMS_RATE_FLAG); -+} -+ -+static inline bool is_cck_rate(u32 ratespec) -+{ -+ u32 rate = (ratespec & BRCMS_RATE_MASK); -+ -+ return !is_mcs_rate(ratespec) && ( -+ rate == BRCM_RATE_1M || rate == BRCM_RATE_2M || -+ rate == BRCM_RATE_5M5 || rate == BRCM_RATE_11M); -+} -+ -+static inline bool is_single_stream(u8 mcs) -+{ -+ return mcs <= HIGHEST_SINGLE_STREAM_MCS || mcs == 32; -+} -+ -+static inline u8 cck_rspec(u8 cck) -+{ -+ return cck & RSPEC_RATE_MASK; -+} -+ -+/* Convert encoded rate value in plcp header to numerical rates in 500 KHz -+ * increments */ -+extern const u8 ofdm_rate_lookup[]; -+ -+static inline u8 ofdm_phy2mac_rate(u8 rlpt) -+{ -+ return ofdm_rate_lookup[rlpt & 0x7]; -+} -+ -+static inline u8 cck_phy2mac_rate(u8 signal) -+{ -+ return signal/5; -+} -+ -+/* Rates specified in brcms_c_rateset_filter() */ -+#define BRCMS_RATES_CCK_OFDM 0 -+#define BRCMS_RATES_CCK 1 -+#define BRCMS_RATES_OFDM 2 -+ -+/* sanitize, and sort a rateset with the basic bit(s) preserved, validate -+ * rateset */ -+extern bool -+brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs, -+ const struct brcms_c_rateset *hw_rs, -+ bool check_brate, u8 txstreams); -+/* copy rateset src to dst as-is (no masking or sorting) */ -+extern void brcms_c_rateset_copy(const struct brcms_c_rateset *src, -+ struct brcms_c_rateset *dst); -+ -+/* would be nice to have these documented ... */ -+extern u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp); -+ -+extern void brcms_c_rateset_filter(struct brcms_c_rateset *src, -+ struct brcms_c_rateset *dst, bool basic_only, u8 rates, uint xmask, -+ bool mcsallow); -+ -+extern void -+brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt, -+ const struct brcms_c_rateset *rs_hw, uint phy_type, -+ int bandtype, bool cck_only, uint rate_mask, -+ bool mcsallow, u8 bw, u8 txstreams); -+ -+extern s16 brcms_c_rate_legacy_phyctl(uint rate); -+ -+extern void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams); -+extern void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset); -+extern void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, -+ u8 txstreams); -+extern void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, -+ u8 bw); -+ -+#endif /* _BRCM_RATE_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/scb.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/scb.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/scb.h.orig 2011-11-09 13:46:58.284800145 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/scb.h 2011-11-09 13:47:17.043565628 -0500 -@@ -0,0 +1,82 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_SCB_H_ -+#define _BRCM_SCB_H_ -+ -+#include -+#include -+#include -+#include "types.h" -+ -+#define AMPDU_TX_BA_MAX_WSIZE 64 /* max Tx ba window size (in pdu) */ -+ -+#define AMPDU_MAX_SCB_TID NUMPRIO -+ -+/* scb flags */ -+#define SCB_WMECAP 0x0040 -+#define SCB_HTCAP 0x10000 /* HT (MIMO) capable device */ -+#define SCB_IS40 0x80000 /* 40MHz capable */ -+#define SCB_STBCCAP 0x40000000 /* STBC Capable */ -+ -+#define SCB_MAGIC 0xbeefcafe -+ -+/* structure to store per-tid state for the ampdu initiator */ -+struct scb_ampdu_tid_ini { -+ u8 tx_in_transit; /* number of pending mpdus in transit in driver */ -+ u8 tid; /* initiator tid for easy lookup */ -+ /* tx retry count; indexed by seq modulo */ -+ u8 txretry[AMPDU_TX_BA_MAX_WSIZE]; -+ struct scb *scb; /* backptr for easy lookup */ -+ u8 ba_wsize; /* negotiated ba window size (in pdu) */ -+}; -+ -+struct scb_ampdu { -+ struct scb *scb; /* back pointer for easy reference */ -+ u8 mpdu_density; /* mpdu density */ -+ u8 max_pdu; /* max pdus allowed in ampdu */ -+ u8 release; /* # of mpdus released at a time */ -+ u16 min_len; /* min mpdu len to support the density */ -+ u32 max_rx_ampdu_bytes; /* max ampdu rcv length; 8k, 16k, 32k, 64k */ -+ -+ /* -+ * This could easily be a ini[] pointer and we keep this info in wl -+ * itself instead of having mac80211 hold it for us. Also could be made -+ * dynamic per tid instead of static. -+ */ -+ /* initiator info - per tid (NUMPRIO): */ -+ struct scb_ampdu_tid_ini ini[AMPDU_MAX_SCB_TID]; -+}; -+ -+/* station control block - one per remote MAC address */ -+struct scb { -+ u32 magic; -+ u32 flags; /* various bit flags as defined below */ -+ u32 flags2; /* various bit flags2 as defined below */ -+ u8 state; /* current state bitfield of auth/assoc process */ -+ u8 ea[ETH_ALEN]; /* station address */ -+ uint fragresid[NUMPRIO];/* #bytes unused in frag buffer per prio */ -+ -+ u16 seqctl[NUMPRIO]; /* seqctl of last received frame (for dups) */ -+ /* seqctl of last received frame (for dups) for non-QoS data and -+ * management */ -+ u16 seqctl_nonqos; -+ u16 seqnum[NUMPRIO];/* WME: driver maintained sw seqnum per priority */ -+ -+ struct scb_ampdu scb_ampdu; /* AMPDU state including per tid info */ -+}; -+ -+#endif /* _BRCM_SCB_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.c.orig 2011-11-09 13:46:58.285800133 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.c 2011-11-09 13:47:17.044565616 -0500 -@@ -0,0 +1,1298 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include "pub.h" -+#include "nicpci.h" -+#include "aiutils.h" -+#include "otp.h" -+#include "srom.h" -+ -+/* -+ * SROM CRC8 polynomial value: -+ * -+ * x^8 + x^7 +x^6 + x^4 + x^2 + 1 -+ */ -+#define SROM_CRC8_POLY 0xAB -+ -+/* Maximum srom: 6 Kilobits == 768 bytes */ -+#define SROM_MAX 768 -+ -+/* PCI fields */ -+#define PCI_F0DEVID 48 -+ -+#define SROM_WORDS 64 -+ -+#define SROM_SSID 2 -+ -+#define SROM_WL1LHMAXP 29 -+ -+#define SROM_WL1LPAB0 30 -+#define SROM_WL1LPAB1 31 -+#define SROM_WL1LPAB2 32 -+ -+#define SROM_WL1HPAB0 33 -+#define SROM_WL1HPAB1 34 -+#define SROM_WL1HPAB2 35 -+ -+#define SROM_MACHI_IL0 36 -+#define SROM_MACMID_IL0 37 -+#define SROM_MACLO_IL0 38 -+#define SROM_MACHI_ET1 42 -+#define SROM_MACMID_ET1 43 -+#define SROM_MACLO_ET1 44 -+#define SROM3_MACHI 37 -+#define SROM3_MACMID 38 -+#define SROM3_MACLO 39 -+ -+#define SROM_BXARSSI2G 40 -+#define SROM_BXARSSI5G 41 -+ -+#define SROM_TRI52G 42 -+#define SROM_TRI5GHL 43 -+ -+#define SROM_RXPO52G 45 -+ -+#define SROM_AABREV 46 -+/* Fields in AABREV */ -+#define SROM_BR_MASK 0x00ff -+#define SROM_CC_MASK 0x0f00 -+#define SROM_CC_SHIFT 8 -+#define SROM_AA0_MASK 0x3000 -+#define SROM_AA0_SHIFT 12 -+#define SROM_AA1_MASK 0xc000 -+#define SROM_AA1_SHIFT 14 -+ -+#define SROM_WL0PAB0 47 -+#define SROM_WL0PAB1 48 -+#define SROM_WL0PAB2 49 -+ -+#define SROM_LEDBH10 50 -+#define SROM_LEDBH32 51 -+ -+#define SROM_WL10MAXP 52 -+ -+#define SROM_WL1PAB0 53 -+#define SROM_WL1PAB1 54 -+#define SROM_WL1PAB2 55 -+ -+#define SROM_ITT 56 -+ -+#define SROM_BFL 57 -+#define SROM_BFL2 28 -+#define SROM3_BFL2 61 -+ -+#define SROM_AG10 58 -+ -+#define SROM_CCODE 59 -+ -+#define SROM_OPO 60 -+ -+#define SROM3_LEDDC 62 -+ -+#define SROM_CRCREV 63 -+ -+/* SROM Rev 4: Reallocate the software part of the srom to accommodate -+ * MIMO features. It assumes up to two PCIE functions and 440 bytes -+ * of usable srom i.e. the usable storage in chips with OTP that -+ * implements hardware redundancy. -+ */ -+ -+#define SROM4_WORDS 220 -+ -+#define SROM4_SIGN 32 -+#define SROM4_SIGNATURE 0x5372 -+ -+#define SROM4_BREV 33 -+ -+#define SROM4_BFL0 34 -+#define SROM4_BFL1 35 -+#define SROM4_BFL2 36 -+#define SROM4_BFL3 37 -+#define SROM5_BFL0 37 -+#define SROM5_BFL1 38 -+#define SROM5_BFL2 39 -+#define SROM5_BFL3 40 -+ -+#define SROM4_MACHI 38 -+#define SROM4_MACMID 39 -+#define SROM4_MACLO 40 -+#define SROM5_MACHI 41 -+#define SROM5_MACMID 42 -+#define SROM5_MACLO 43 -+ -+#define SROM4_CCODE 41 -+#define SROM4_REGREV 42 -+#define SROM5_CCODE 34 -+#define SROM5_REGREV 35 -+ -+#define SROM4_LEDBH10 43 -+#define SROM4_LEDBH32 44 -+#define SROM5_LEDBH10 59 -+#define SROM5_LEDBH32 60 -+ -+#define SROM4_LEDDC 45 -+#define SROM5_LEDDC 45 -+ -+#define SROM4_AA 46 -+ -+#define SROM4_AG10 47 -+#define SROM4_AG32 48 -+ -+#define SROM4_TXPID2G 49 -+#define SROM4_TXPID5G 51 -+#define SROM4_TXPID5GL 53 -+#define SROM4_TXPID5GH 55 -+ -+#define SROM4_TXRXC 61 -+#define SROM4_TXCHAIN_MASK 0x000f -+#define SROM4_TXCHAIN_SHIFT 0 -+#define SROM4_RXCHAIN_MASK 0x00f0 -+#define SROM4_RXCHAIN_SHIFT 4 -+#define SROM4_SWITCH_MASK 0xff00 -+#define SROM4_SWITCH_SHIFT 8 -+ -+/* Per-path fields */ -+#define MAX_PATH_SROM 4 -+#define SROM4_PATH0 64 -+#define SROM4_PATH1 87 -+#define SROM4_PATH2 110 -+#define SROM4_PATH3 133 -+ -+#define SROM4_2G_ITT_MAXP 0 -+#define SROM4_2G_PA 1 -+#define SROM4_5G_ITT_MAXP 5 -+#define SROM4_5GLH_MAXP 6 -+#define SROM4_5G_PA 7 -+#define SROM4_5GL_PA 11 -+#define SROM4_5GH_PA 15 -+ -+/* All the miriad power offsets */ -+#define SROM4_2G_CCKPO 156 -+#define SROM4_2G_OFDMPO 157 -+#define SROM4_5G_OFDMPO 159 -+#define SROM4_5GL_OFDMPO 161 -+#define SROM4_5GH_OFDMPO 163 -+#define SROM4_2G_MCSPO 165 -+#define SROM4_5G_MCSPO 173 -+#define SROM4_5GL_MCSPO 181 -+#define SROM4_5GH_MCSPO 189 -+#define SROM4_CDDPO 197 -+#define SROM4_STBCPO 198 -+#define SROM4_BW40PO 199 -+#define SROM4_BWDUPPO 200 -+ -+#define SROM4_CRCREV 219 -+ -+/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6. -+ * This is acombined srom for both MIMO and SISO boards, usable in -+ * the .130 4Kilobit OTP with hardware redundancy. -+ */ -+#define SROM8_BREV 65 -+ -+#define SROM8_BFL0 66 -+#define SROM8_BFL1 67 -+#define SROM8_BFL2 68 -+#define SROM8_BFL3 69 -+ -+#define SROM8_MACHI 70 -+#define SROM8_MACMID 71 -+#define SROM8_MACLO 72 -+ -+#define SROM8_CCODE 73 -+#define SROM8_REGREV 74 -+ -+#define SROM8_LEDBH10 75 -+#define SROM8_LEDBH32 76 -+ -+#define SROM8_LEDDC 77 -+ -+#define SROM8_AA 78 -+ -+#define SROM8_AG10 79 -+#define SROM8_AG32 80 -+ -+#define SROM8_TXRXC 81 -+ -+#define SROM8_BXARSSI2G 82 -+#define SROM8_BXARSSI5G 83 -+#define SROM8_TRI52G 84 -+#define SROM8_TRI5GHL 85 -+#define SROM8_RXPO52G 86 -+ -+#define SROM8_FEM2G 87 -+#define SROM8_FEM5G 88 -+#define SROM8_FEM_ANTSWLUT_MASK 0xf800 -+#define SROM8_FEM_ANTSWLUT_SHIFT 11 -+#define SROM8_FEM_TR_ISO_MASK 0x0700 -+#define SROM8_FEM_TR_ISO_SHIFT 8 -+#define SROM8_FEM_PDET_RANGE_MASK 0x00f8 -+#define SROM8_FEM_PDET_RANGE_SHIFT 3 -+#define SROM8_FEM_EXTPA_GAIN_MASK 0x0006 -+#define SROM8_FEM_EXTPA_GAIN_SHIFT 1 -+#define SROM8_FEM_TSSIPOS_MASK 0x0001 -+#define SROM8_FEM_TSSIPOS_SHIFT 0 -+ -+#define SROM8_THERMAL 89 -+ -+/* Temp sense related entries */ -+#define SROM8_MPWR_RAWTS 90 -+#define SROM8_TS_SLP_OPT_CORRX 91 -+/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, -+ * IQSWP: IQ CAL swap disable */ -+#define SROM8_FOC_HWIQ_IQSWP 92 -+ -+/* Temperature delta for PHY calibration */ -+#define SROM8_PHYCAL_TEMPDELTA 93 -+ -+/* Per-path offsets & fields */ -+#define SROM8_PATH0 96 -+#define SROM8_PATH1 112 -+#define SROM8_PATH2 128 -+#define SROM8_PATH3 144 -+ -+#define SROM8_2G_ITT_MAXP 0 -+#define SROM8_2G_PA 1 -+#define SROM8_5G_ITT_MAXP 4 -+#define SROM8_5GLH_MAXP 5 -+#define SROM8_5G_PA 6 -+#define SROM8_5GL_PA 9 -+#define SROM8_5GH_PA 12 -+ -+/* All the miriad power offsets */ -+#define SROM8_2G_CCKPO 160 -+ -+#define SROM8_2G_OFDMPO 161 -+#define SROM8_5G_OFDMPO 163 -+#define SROM8_5GL_OFDMPO 165 -+#define SROM8_5GH_OFDMPO 167 -+ -+#define SROM8_2G_MCSPO 169 -+#define SROM8_5G_MCSPO 177 -+#define SROM8_5GL_MCSPO 185 -+#define SROM8_5GH_MCSPO 193 -+ -+#define SROM8_CDDPO 201 -+#define SROM8_STBCPO 202 -+#define SROM8_BW40PO 203 -+#define SROM8_BWDUPPO 204 -+ -+/* SISO PA parameters are in the path0 spaces */ -+#define SROM8_SISO 96 -+ -+/* Legacy names for SISO PA paramters */ -+#define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP) -+#define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA) -+#define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1) -+#define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2) -+#define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP) -+#define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP) -+#define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA) -+#define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1) -+#define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2) -+#define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA) -+#define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1) -+#define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2) -+#define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA) -+#define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1) -+#define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2) -+ -+/* SROM REV 9 */ -+#define SROM9_2GPO_CCKBW20 160 -+#define SROM9_2GPO_CCKBW20UL 161 -+#define SROM9_2GPO_LOFDMBW20 162 -+#define SROM9_2GPO_LOFDMBW20UL 164 -+ -+#define SROM9_5GLPO_LOFDMBW20 166 -+#define SROM9_5GLPO_LOFDMBW20UL 168 -+#define SROM9_5GMPO_LOFDMBW20 170 -+#define SROM9_5GMPO_LOFDMBW20UL 172 -+#define SROM9_5GHPO_LOFDMBW20 174 -+#define SROM9_5GHPO_LOFDMBW20UL 176 -+ -+#define SROM9_2GPO_MCSBW20 178 -+#define SROM9_2GPO_MCSBW20UL 180 -+#define SROM9_2GPO_MCSBW40 182 -+ -+#define SROM9_5GLPO_MCSBW20 184 -+#define SROM9_5GLPO_MCSBW20UL 186 -+#define SROM9_5GLPO_MCSBW40 188 -+#define SROM9_5GMPO_MCSBW20 190 -+#define SROM9_5GMPO_MCSBW20UL 192 -+#define SROM9_5GMPO_MCSBW40 194 -+#define SROM9_5GHPO_MCSBW20 196 -+#define SROM9_5GHPO_MCSBW20UL 198 -+#define SROM9_5GHPO_MCSBW40 200 -+ -+#define SROM9_PO_MCS32 202 -+#define SROM9_PO_LOFDM40DUP 203 -+ -+/* SROM flags (see sromvar_t) */ -+ -+/* value continues as described by the next entry */ -+#define SRFL_MORE 1 -+#define SRFL_NOFFS 2 /* value bits can't be all one's */ -+#define SRFL_PRHEX 4 /* value is in hexdecimal format */ -+#define SRFL_PRSIGN 8 /* value is in signed decimal format */ -+#define SRFL_CCODE 0x10 /* value is in country code format */ -+#define SRFL_ETHADDR 0x20 /* value is an Ethernet address */ -+#define SRFL_LEDDC 0x40 /* value is an LED duty cycle */ -+/* do not generate a nvram param, entry is for mfgc */ -+#define SRFL_NOVAR 0x80 -+ -+/* Max. nvram variable table size */ -+#define MAXSZ_NVRAM_VARS 4096 -+ -+/* -+ * indicates type of value. -+ */ -+enum brcms_srom_var_type { -+ BRCMS_SROM_STRING, -+ BRCMS_SROM_SNUMBER, -+ BRCMS_SROM_UNUMBER -+}; -+ -+/* -+ * storage type for srom variable. -+ * -+ * var_list: for linked list operations. -+ * varid: identifier of the variable. -+ * var_type: type of variable. -+ * buf: variable value when var_type == BRCMS_SROM_STRING. -+ * uval: unsigned variable value when var_type == BRCMS_SROM_UNUMBER. -+ * sval: signed variable value when var_type == BRCMS_SROM_SNUMBER. -+ */ -+struct brcms_srom_list_head { -+ struct list_head var_list; -+ enum brcms_srom_id varid; -+ enum brcms_srom_var_type var_type; -+ union { -+ char buf[0]; -+ u32 uval; -+ s32 sval; -+ }; -+}; -+ -+struct brcms_sromvar { -+ enum brcms_srom_id varid; -+ u32 revmask; -+ u32 flags; -+ u16 off; -+ u16 mask; -+}; -+ -+struct brcms_varbuf { -+ char *base; /* pointer to buffer base */ -+ char *buf; /* pointer to current position */ -+ unsigned int size; /* current (residual) size in bytes */ -+}; -+ -+/* -+ * Assumptions: -+ * - Ethernet address spans across 3 consecutive words -+ * -+ * Table rules: -+ * - Add multiple entries next to each other if a value spans across multiple -+ * words (even multiple fields in the same word) with each entry except the -+ * last having it's SRFL_MORE bit set. -+ * - Ethernet address entry does not follow above rule and must not have -+ * SRFL_MORE bit set. Its SRFL_ETHADDR bit implies it takes multiple words. -+ * - The last entry's name field must be NULL to indicate the end of the table. -+ * Other entries must have non-NULL name. -+ */ -+static const struct brcms_sromvar pci_sromvars[] = { -+ {BRCMS_SROM_DEVID, 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID, -+ 0xffff}, -+ {BRCMS_SROM_BOARDREV, 0x0000000e, SRFL_PRHEX, SROM_AABREV, -+ SROM_BR_MASK}, -+ {BRCMS_SROM_BOARDREV, 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff}, -+ {BRCMS_SROM_BOARDREV, 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff}, -+ {BRCMS_SROM_BOARDFLAGS, 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff}, -+ {BRCMS_SROM_BOARDFLAGS, 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM_BFL2, 0xffff}, -+ {BRCMS_SROM_BOARDFLAGS, 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM3_BFL2, 0xffff}, -+ {BRCMS_SROM_BOARDFLAGS, 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM4_BFL1, 0xffff}, -+ {BRCMS_SROM_BOARDFLAGS, 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM5_BFL1, 0xffff}, -+ {BRCMS_SROM_BOARDFLAGS, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM8_BFL1, 0xffff}, -+ {BRCMS_SROM_BOARDFLAGS2, 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM4_BFL3, 0xffff}, -+ {BRCMS_SROM_BOARDFLAGS2, 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM5_BFL3, 0xffff}, -+ {BRCMS_SROM_BOARDFLAGS2, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM8_BFL3, 0xffff}, -+ {BRCMS_SROM_BOARDTYPE, 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff}, -+ {BRCMS_SROM_BOARDNUM, 0x00000006, 0, SROM_MACLO_IL0, 0xffff}, -+ {BRCMS_SROM_BOARDNUM, 0x00000008, 0, SROM3_MACLO, 0xffff}, -+ {BRCMS_SROM_BOARDNUM, 0x00000010, 0, SROM4_MACLO, 0xffff}, -+ {BRCMS_SROM_BOARDNUM, 0x000000e0, 0, SROM5_MACLO, 0xffff}, -+ {BRCMS_SROM_BOARDNUM, 0xffffff00, 0, SROM8_MACLO, 0xffff}, -+ {BRCMS_SROM_CC, 0x00000002, 0, SROM_AABREV, SROM_CC_MASK}, -+ {BRCMS_SROM_REGREV, 0x00000008, 0, SROM_OPO, 0xff00}, -+ {BRCMS_SROM_REGREV, 0x00000010, 0, SROM4_REGREV, 0x00ff}, -+ {BRCMS_SROM_REGREV, 0x000000e0, 0, SROM5_REGREV, 0x00ff}, -+ {BRCMS_SROM_REGREV, 0xffffff00, 0, SROM8_REGREV, 0x00ff}, -+ {BRCMS_SROM_LEDBH0, 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff}, -+ {BRCMS_SROM_LEDBH1, 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00}, -+ {BRCMS_SROM_LEDBH2, 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff}, -+ {BRCMS_SROM_LEDBH3, 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00}, -+ {BRCMS_SROM_LEDBH0, 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff}, -+ {BRCMS_SROM_LEDBH1, 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00}, -+ {BRCMS_SROM_LEDBH2, 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff}, -+ {BRCMS_SROM_LEDBH3, 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00}, -+ {BRCMS_SROM_LEDBH0, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff}, -+ {BRCMS_SROM_LEDBH1, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00}, -+ {BRCMS_SROM_LEDBH2, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff}, -+ {BRCMS_SROM_LEDBH3, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00}, -+ {BRCMS_SROM_LEDBH0, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff}, -+ {BRCMS_SROM_LEDBH1, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00}, -+ {BRCMS_SROM_LEDBH2, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff}, -+ {BRCMS_SROM_LEDBH3, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00}, -+ {BRCMS_SROM_PA0B0, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff}, -+ {BRCMS_SROM_PA0B1, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff}, -+ {BRCMS_SROM_PA0B2, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff}, -+ {BRCMS_SROM_PA0ITSSIT, 0x0000000e, 0, SROM_ITT, 0x00ff}, -+ {BRCMS_SROM_PA0MAXPWR, 0x0000000e, 0, SROM_WL10MAXP, 0x00ff}, -+ {BRCMS_SROM_PA0B0, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff}, -+ {BRCMS_SROM_PA0B1, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff}, -+ {BRCMS_SROM_PA0B2, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff}, -+ {BRCMS_SROM_PA0ITSSIT, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00}, -+ {BRCMS_SROM_PA0MAXPWR, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff}, -+ {BRCMS_SROM_OPO, 0x0000000c, 0, SROM_OPO, 0x00ff}, -+ {BRCMS_SROM_OPO, 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff}, -+ {BRCMS_SROM_AA2G, 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK}, -+ {BRCMS_SROM_AA2G, 0x000000f0, 0, SROM4_AA, 0x00ff}, -+ {BRCMS_SROM_AA2G, 0xffffff00, 0, SROM8_AA, 0x00ff}, -+ {BRCMS_SROM_AA5G, 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK}, -+ {BRCMS_SROM_AA5G, 0x000000f0, 0, SROM4_AA, 0xff00}, -+ {BRCMS_SROM_AA5G, 0xffffff00, 0, SROM8_AA, 0xff00}, -+ {BRCMS_SROM_AG0, 0x0000000e, 0, SROM_AG10, 0x00ff}, -+ {BRCMS_SROM_AG1, 0x0000000e, 0, SROM_AG10, 0xff00}, -+ {BRCMS_SROM_AG0, 0x000000f0, 0, SROM4_AG10, 0x00ff}, -+ {BRCMS_SROM_AG1, 0x000000f0, 0, SROM4_AG10, 0xff00}, -+ {BRCMS_SROM_AG2, 0x000000f0, 0, SROM4_AG32, 0x00ff}, -+ {BRCMS_SROM_AG3, 0x000000f0, 0, SROM4_AG32, 0xff00}, -+ {BRCMS_SROM_AG0, 0xffffff00, 0, SROM8_AG10, 0x00ff}, -+ {BRCMS_SROM_AG1, 0xffffff00, 0, SROM8_AG10, 0xff00}, -+ {BRCMS_SROM_AG2, 0xffffff00, 0, SROM8_AG32, 0x00ff}, -+ {BRCMS_SROM_AG3, 0xffffff00, 0, SROM8_AG32, 0xff00}, -+ {BRCMS_SROM_PA1B0, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff}, -+ {BRCMS_SROM_PA1B1, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff}, -+ {BRCMS_SROM_PA1B2, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff}, -+ {BRCMS_SROM_PA1LOB0, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff}, -+ {BRCMS_SROM_PA1LOB1, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff}, -+ {BRCMS_SROM_PA1LOB2, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff}, -+ {BRCMS_SROM_PA1HIB0, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff}, -+ {BRCMS_SROM_PA1HIB1, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff}, -+ {BRCMS_SROM_PA1HIB2, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff}, -+ {BRCMS_SROM_PA1ITSSIT, 0x0000000e, 0, SROM_ITT, 0xff00}, -+ {BRCMS_SROM_PA1MAXPWR, 0x0000000e, 0, SROM_WL10MAXP, 0xff00}, -+ {BRCMS_SROM_PA1LOMAXPWR, 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00}, -+ {BRCMS_SROM_PA1HIMAXPWR, 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff}, -+ {BRCMS_SROM_PA1B0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff}, -+ {BRCMS_SROM_PA1B1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff}, -+ {BRCMS_SROM_PA1B2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff}, -+ {BRCMS_SROM_PA1LOB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff}, -+ {BRCMS_SROM_PA1LOB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff}, -+ {BRCMS_SROM_PA1LOB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff}, -+ {BRCMS_SROM_PA1HIB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff}, -+ {BRCMS_SROM_PA1HIB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff}, -+ {BRCMS_SROM_PA1HIB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff}, -+ {BRCMS_SROM_PA1ITSSIT, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00}, -+ {BRCMS_SROM_PA1MAXPWR, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff}, -+ {BRCMS_SROM_PA1LOMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00}, -+ {BRCMS_SROM_PA1HIMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff}, -+ {BRCMS_SROM_BXA2G, 0x00000008, 0, SROM_BXARSSI2G, 0x1800}, -+ {BRCMS_SROM_RSSISAV2G, 0x00000008, 0, SROM_BXARSSI2G, 0x0700}, -+ {BRCMS_SROM_RSSISMC2G, 0x00000008, 0, SROM_BXARSSI2G, 0x00f0}, -+ {BRCMS_SROM_RSSISMF2G, 0x00000008, 0, SROM_BXARSSI2G, 0x000f}, -+ {BRCMS_SROM_BXA2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800}, -+ {BRCMS_SROM_RSSISAV2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700}, -+ {BRCMS_SROM_RSSISMC2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0}, -+ {BRCMS_SROM_RSSISMF2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f}, -+ {BRCMS_SROM_BXA5G, 0x00000008, 0, SROM_BXARSSI5G, 0x1800}, -+ {BRCMS_SROM_RSSISAV5G, 0x00000008, 0, SROM_BXARSSI5G, 0x0700}, -+ {BRCMS_SROM_RSSISMC5G, 0x00000008, 0, SROM_BXARSSI5G, 0x00f0}, -+ {BRCMS_SROM_RSSISMF5G, 0x00000008, 0, SROM_BXARSSI5G, 0x000f}, -+ {BRCMS_SROM_BXA5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800}, -+ {BRCMS_SROM_RSSISAV5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700}, -+ {BRCMS_SROM_RSSISMC5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0}, -+ {BRCMS_SROM_RSSISMF5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f}, -+ {BRCMS_SROM_TRI2G, 0x00000008, 0, SROM_TRI52G, 0x00ff}, -+ {BRCMS_SROM_TRI5G, 0x00000008, 0, SROM_TRI52G, 0xff00}, -+ {BRCMS_SROM_TRI5GL, 0x00000008, 0, SROM_TRI5GHL, 0x00ff}, -+ {BRCMS_SROM_TRI5GH, 0x00000008, 0, SROM_TRI5GHL, 0xff00}, -+ {BRCMS_SROM_TRI2G, 0xffffff00, 0, SROM8_TRI52G, 0x00ff}, -+ {BRCMS_SROM_TRI5G, 0xffffff00, 0, SROM8_TRI52G, 0xff00}, -+ {BRCMS_SROM_TRI5GL, 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff}, -+ {BRCMS_SROM_TRI5GH, 0xffffff00, 0, SROM8_TRI5GHL, 0xff00}, -+ {BRCMS_SROM_RXPO2G, 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff}, -+ {BRCMS_SROM_RXPO5G, 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00}, -+ {BRCMS_SROM_RXPO2G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff}, -+ {BRCMS_SROM_RXPO5G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00}, -+ {BRCMS_SROM_TXCHAIN, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, -+ SROM4_TXCHAIN_MASK}, -+ {BRCMS_SROM_RXCHAIN, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, -+ SROM4_RXCHAIN_MASK}, -+ {BRCMS_SROM_ANTSWITCH, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, -+ SROM4_SWITCH_MASK}, -+ {BRCMS_SROM_TXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, -+ SROM4_TXCHAIN_MASK}, -+ {BRCMS_SROM_RXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, -+ SROM4_RXCHAIN_MASK}, -+ {BRCMS_SROM_ANTSWITCH, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, -+ SROM4_SWITCH_MASK}, -+ {BRCMS_SROM_TSSIPOS2G, 0xffffff00, 0, SROM8_FEM2G, -+ SROM8_FEM_TSSIPOS_MASK}, -+ {BRCMS_SROM_EXTPAGAIN2G, 0xffffff00, 0, SROM8_FEM2G, -+ SROM8_FEM_EXTPA_GAIN_MASK}, -+ {BRCMS_SROM_PDETRANGE2G, 0xffffff00, 0, SROM8_FEM2G, -+ SROM8_FEM_PDET_RANGE_MASK}, -+ {BRCMS_SROM_TRISO2G, 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK}, -+ {BRCMS_SROM_ANTSWCTL2G, 0xffffff00, 0, SROM8_FEM2G, -+ SROM8_FEM_ANTSWLUT_MASK}, -+ {BRCMS_SROM_TSSIPOS5G, 0xffffff00, 0, SROM8_FEM5G, -+ SROM8_FEM_TSSIPOS_MASK}, -+ {BRCMS_SROM_EXTPAGAIN5G, 0xffffff00, 0, SROM8_FEM5G, -+ SROM8_FEM_EXTPA_GAIN_MASK}, -+ {BRCMS_SROM_PDETRANGE5G, 0xffffff00, 0, SROM8_FEM5G, -+ SROM8_FEM_PDET_RANGE_MASK}, -+ {BRCMS_SROM_TRISO5G, 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK}, -+ {BRCMS_SROM_ANTSWCTL5G, 0xffffff00, 0, SROM8_FEM5G, -+ SROM8_FEM_ANTSWLUT_MASK}, -+ {BRCMS_SROM_TEMPTHRESH, 0xffffff00, 0, SROM8_THERMAL, 0xff00}, -+ {BRCMS_SROM_TEMPOFFSET, 0xffffff00, 0, SROM8_THERMAL, 0x00ff}, -+ {BRCMS_SROM_TXPID2GA0, 0x000000f0, 0, SROM4_TXPID2G, 0x00ff}, -+ {BRCMS_SROM_TXPID2GA1, 0x000000f0, 0, SROM4_TXPID2G, 0xff00}, -+ {BRCMS_SROM_TXPID2GA2, 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff}, -+ {BRCMS_SROM_TXPID2GA3, 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00}, -+ {BRCMS_SROM_TXPID5GA0, 0x000000f0, 0, SROM4_TXPID5G, 0x00ff}, -+ {BRCMS_SROM_TXPID5GA1, 0x000000f0, 0, SROM4_TXPID5G, 0xff00}, -+ {BRCMS_SROM_TXPID5GA2, 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff}, -+ {BRCMS_SROM_TXPID5GA3, 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00}, -+ {BRCMS_SROM_TXPID5GLA0, 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff}, -+ {BRCMS_SROM_TXPID5GLA1, 0x000000f0, 0, SROM4_TXPID5GL, 0xff00}, -+ {BRCMS_SROM_TXPID5GLA2, 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff}, -+ {BRCMS_SROM_TXPID5GLA3, 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00}, -+ {BRCMS_SROM_TXPID5GHA0, 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff}, -+ {BRCMS_SROM_TXPID5GHA1, 0x000000f0, 0, SROM4_TXPID5GH, 0xff00}, -+ {BRCMS_SROM_TXPID5GHA2, 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff}, -+ {BRCMS_SROM_TXPID5GHA3, 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00}, -+ -+ {BRCMS_SROM_CCODE, 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff}, -+ {BRCMS_SROM_CCODE, 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff}, -+ {BRCMS_SROM_CCODE, 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff}, -+ {BRCMS_SROM_CCODE, 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff}, -+ {BRCMS_SROM_MACADDR, 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff}, -+ {BRCMS_SROM_MACADDR, 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff}, -+ {BRCMS_SROM_MACADDR, 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff}, -+ {BRCMS_SROM_MACADDR, 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff}, -+ {BRCMS_SROM_IL0MACADDR, 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, -+ 0xffff}, -+ {BRCMS_SROM_ET1MACADDR, 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, -+ 0xffff}, -+ {BRCMS_SROM_LEDDC, 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, -+ 0xffff}, -+ {BRCMS_SROM_LEDDC, 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC, -+ 0xffff}, -+ {BRCMS_SROM_LEDDC, 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC, -+ 0xffff}, -+ {BRCMS_SROM_LEDDC, 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC, -+ 0xffff}, -+ {BRCMS_SROM_RAWTEMPSENSE, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, -+ 0x01ff}, -+ {BRCMS_SROM_MEASPOWER, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, -+ 0xfe00}, -+ {BRCMS_SROM_TEMPSENSE_SLOPE, 0xffffff00, SRFL_PRHEX, -+ SROM8_TS_SLP_OPT_CORRX, 0x00ff}, -+ {BRCMS_SROM_TEMPCORRX, 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, -+ 0xfc00}, -+ {BRCMS_SROM_TEMPSENSE_OPTION, 0xffffff00, SRFL_PRHEX, -+ SROM8_TS_SLP_OPT_CORRX, 0x0300}, -+ {BRCMS_SROM_FREQOFFSET_CORR, 0xffffff00, SRFL_PRHEX, -+ SROM8_FOC_HWIQ_IQSWP, 0x000f}, -+ {BRCMS_SROM_IQCAL_SWP_DIS, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, -+ 0x0010}, -+ {BRCMS_SROM_HW_IQCAL_EN, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, -+ 0x0020}, -+ {BRCMS_SROM_PHYCAL_TEMPDELTA, 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA, -+ 0x00ff}, -+ -+ {BRCMS_SROM_CCK2GPO, 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff}, -+ {BRCMS_SROM_CCK2GPO, 0x00000100, 0, SROM8_2G_CCKPO, 0xffff}, -+ {BRCMS_SROM_OFDM2GPO, 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM4_2G_OFDMPO + 1, 0xffff}, -+ {BRCMS_SROM_OFDM5GPO, 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM4_5G_OFDMPO + 1, 0xffff}, -+ {BRCMS_SROM_OFDM5GLPO, 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff}, -+ {BRCMS_SROM_OFDM5GHPO, 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff}, -+ {BRCMS_SROM_OFDM2GPO, 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM8_2G_OFDMPO + 1, 0xffff}, -+ {BRCMS_SROM_OFDM5GPO, 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM8_5G_OFDMPO + 1, 0xffff}, -+ {BRCMS_SROM_OFDM5GLPO, 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff}, -+ {BRCMS_SROM_OFDM5GHPO, 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff}, -+ {BRCMS_SROM_MCS2GPO0, 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff}, -+ {BRCMS_SROM_MCS2GPO1, 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff}, -+ {BRCMS_SROM_MCS2GPO2, 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff}, -+ {BRCMS_SROM_MCS2GPO3, 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff}, -+ {BRCMS_SROM_MCS2GPO4, 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff}, -+ {BRCMS_SROM_MCS2GPO5, 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff}, -+ {BRCMS_SROM_MCS2GPO6, 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff}, -+ {BRCMS_SROM_MCS2GPO7, 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff}, -+ {BRCMS_SROM_MCS5GPO0, 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff}, -+ {BRCMS_SROM_MCS5GPO1, 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff}, -+ {BRCMS_SROM_MCS5GPO2, 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff}, -+ {BRCMS_SROM_MCS5GPO3, 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff}, -+ {BRCMS_SROM_MCS5GPO4, 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff}, -+ {BRCMS_SROM_MCS5GPO5, 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff}, -+ {BRCMS_SROM_MCS5GPO6, 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff}, -+ {BRCMS_SROM_MCS5GPO7, 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff}, -+ {BRCMS_SROM_MCS5GLPO0, 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff}, -+ {BRCMS_SROM_MCS5GLPO1, 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff}, -+ {BRCMS_SROM_MCS5GLPO2, 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff}, -+ {BRCMS_SROM_MCS5GLPO3, 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff}, -+ {BRCMS_SROM_MCS5GLPO4, 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff}, -+ {BRCMS_SROM_MCS5GLPO5, 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff}, -+ {BRCMS_SROM_MCS5GLPO6, 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff}, -+ {BRCMS_SROM_MCS5GLPO7, 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff}, -+ {BRCMS_SROM_MCS5GHPO0, 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff}, -+ {BRCMS_SROM_MCS5GHPO1, 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff}, -+ {BRCMS_SROM_MCS5GHPO2, 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff}, -+ {BRCMS_SROM_MCS5GHPO3, 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff}, -+ {BRCMS_SROM_MCS5GHPO4, 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff}, -+ {BRCMS_SROM_MCS5GHPO5, 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff}, -+ {BRCMS_SROM_MCS5GHPO6, 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff}, -+ {BRCMS_SROM_MCS5GHPO7, 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff}, -+ {BRCMS_SROM_MCS2GPO0, 0x00000100, 0, SROM8_2G_MCSPO, 0xffff}, -+ {BRCMS_SROM_MCS2GPO1, 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff}, -+ {BRCMS_SROM_MCS2GPO2, 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff}, -+ {BRCMS_SROM_MCS2GPO3, 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff}, -+ {BRCMS_SROM_MCS2GPO4, 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff}, -+ {BRCMS_SROM_MCS2GPO5, 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff}, -+ {BRCMS_SROM_MCS2GPO6, 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff}, -+ {BRCMS_SROM_MCS2GPO7, 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff}, -+ {BRCMS_SROM_MCS5GPO0, 0x00000100, 0, SROM8_5G_MCSPO, 0xffff}, -+ {BRCMS_SROM_MCS5GPO1, 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff}, -+ {BRCMS_SROM_MCS5GPO2, 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff}, -+ {BRCMS_SROM_MCS5GPO3, 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff}, -+ {BRCMS_SROM_MCS5GPO4, 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff}, -+ {BRCMS_SROM_MCS5GPO5, 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff}, -+ {BRCMS_SROM_MCS5GPO6, 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff}, -+ {BRCMS_SROM_MCS5GPO7, 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff}, -+ {BRCMS_SROM_MCS5GLPO0, 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff}, -+ {BRCMS_SROM_MCS5GLPO1, 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff}, -+ {BRCMS_SROM_MCS5GLPO2, 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff}, -+ {BRCMS_SROM_MCS5GLPO3, 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff}, -+ {BRCMS_SROM_MCS5GLPO4, 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff}, -+ {BRCMS_SROM_MCS5GLPO5, 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff}, -+ {BRCMS_SROM_MCS5GLPO6, 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff}, -+ {BRCMS_SROM_MCS5GLPO7, 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff}, -+ {BRCMS_SROM_MCS5GHPO0, 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff}, -+ {BRCMS_SROM_MCS5GHPO1, 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff}, -+ {BRCMS_SROM_MCS5GHPO2, 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff}, -+ {BRCMS_SROM_MCS5GHPO3, 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff}, -+ {BRCMS_SROM_MCS5GHPO4, 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff}, -+ {BRCMS_SROM_MCS5GHPO5, 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff}, -+ {BRCMS_SROM_MCS5GHPO6, 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff}, -+ {BRCMS_SROM_MCS5GHPO7, 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff}, -+ {BRCMS_SROM_CDDPO, 0x000000f0, 0, SROM4_CDDPO, 0xffff}, -+ {BRCMS_SROM_STBCPO, 0x000000f0, 0, SROM4_STBCPO, 0xffff}, -+ {BRCMS_SROM_BW40PO, 0x000000f0, 0, SROM4_BW40PO, 0xffff}, -+ {BRCMS_SROM_BWDUPPO, 0x000000f0, 0, SROM4_BWDUPPO, 0xffff}, -+ {BRCMS_SROM_CDDPO, 0x00000100, 0, SROM8_CDDPO, 0xffff}, -+ {BRCMS_SROM_STBCPO, 0x00000100, 0, SROM8_STBCPO, 0xffff}, -+ {BRCMS_SROM_BW40PO, 0x00000100, 0, SROM8_BW40PO, 0xffff}, -+ {BRCMS_SROM_BWDUPPO, 0x00000100, 0, SROM8_BWDUPPO, 0xffff}, -+ -+ /* power per rate from sromrev 9 */ -+ {BRCMS_SROM_CCKBW202GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff}, -+ {BRCMS_SROM_CCKBW20UL2GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff}, -+ {BRCMS_SROM_LEGOFDMBW202GPO, 0xfffffe00, SRFL_MORE, -+ SROM9_2GPO_LOFDMBW20, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff}, -+ {BRCMS_SROM_LEGOFDMBW20UL2GPO, 0xfffffe00, SRFL_MORE, -+ SROM9_2GPO_LOFDMBW20UL, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff}, -+ {BRCMS_SROM_LEGOFDMBW205GLPO, 0xfffffe00, SRFL_MORE, -+ SROM9_5GLPO_LOFDMBW20, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff}, -+ {BRCMS_SROM_LEGOFDMBW20UL5GLPO, 0xfffffe00, SRFL_MORE, -+ SROM9_5GLPO_LOFDMBW20UL, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff}, -+ {BRCMS_SROM_LEGOFDMBW205GMPO, 0xfffffe00, SRFL_MORE, -+ SROM9_5GMPO_LOFDMBW20, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff}, -+ {BRCMS_SROM_LEGOFDMBW20UL5GMPO, 0xfffffe00, SRFL_MORE, -+ SROM9_5GMPO_LOFDMBW20UL, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff}, -+ {BRCMS_SROM_LEGOFDMBW205GHPO, 0xfffffe00, SRFL_MORE, -+ SROM9_5GHPO_LOFDMBW20, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff}, -+ {BRCMS_SROM_LEGOFDMBW20UL5GHPO, 0xfffffe00, SRFL_MORE, -+ SROM9_5GHPO_LOFDMBW20UL, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff}, -+ {BRCMS_SROM_MCSBW202GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff}, -+ {BRCMS_SROM_MCSBW20UL2GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff}, -+ {BRCMS_SROM_MCSBW402GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff}, -+ {BRCMS_SROM_MCSBW205GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff}, -+ {BRCMS_SROM_MCSBW20UL5GLPO, 0xfffffe00, SRFL_MORE, -+ SROM9_5GLPO_MCSBW20UL, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff}, -+ {BRCMS_SROM_MCSBW405GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff}, -+ {BRCMS_SROM_MCSBW205GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff}, -+ {BRCMS_SROM_MCSBW20UL5GMPO, 0xfffffe00, SRFL_MORE, -+ SROM9_5GMPO_MCSBW20UL, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff}, -+ {BRCMS_SROM_MCSBW405GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff}, -+ {BRCMS_SROM_MCSBW205GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff}, -+ {BRCMS_SROM_MCSBW20UL5GHPO, 0xfffffe00, SRFL_MORE, -+ SROM9_5GHPO_MCSBW20UL, 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff}, -+ {BRCMS_SROM_MCSBW405GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40, -+ 0xffff}, -+ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff}, -+ {BRCMS_SROM_MCS32PO, 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff}, -+ {BRCMS_SROM_LEGOFDM40DUPPO, 0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff}, -+ -+ {BRCMS_SROM_NULL, 0, 0, 0, 0} -+}; -+ -+static const struct brcms_sromvar perpath_pci_sromvars[] = { -+ {BRCMS_SROM_MAXP2GA0, 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff}, -+ {BRCMS_SROM_ITT2GA0, 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00}, -+ {BRCMS_SROM_ITT5GA0, 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00}, -+ {BRCMS_SROM_PA2GW0A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff}, -+ {BRCMS_SROM_PA2GW1A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff}, -+ {BRCMS_SROM_PA2GW2A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff}, -+ {BRCMS_SROM_PA2GW3A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff}, -+ {BRCMS_SROM_MAXP5GA0, 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff}, -+ {BRCMS_SROM_MAXP5GHA0, 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff}, -+ {BRCMS_SROM_MAXP5GLA0, 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00}, -+ {BRCMS_SROM_PA5GW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff}, -+ {BRCMS_SROM_PA5GW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff}, -+ {BRCMS_SROM_PA5GW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff}, -+ {BRCMS_SROM_PA5GW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff}, -+ {BRCMS_SROM_PA5GLW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff}, -+ {BRCMS_SROM_PA5GLW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1, -+ 0xffff}, -+ {BRCMS_SROM_PA5GLW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2, -+ 0xffff}, -+ {BRCMS_SROM_PA5GLW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3, -+ 0xffff}, -+ {BRCMS_SROM_PA5GHW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff}, -+ {BRCMS_SROM_PA5GHW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1, -+ 0xffff}, -+ {BRCMS_SROM_PA5GHW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2, -+ 0xffff}, -+ {BRCMS_SROM_PA5GHW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3, -+ 0xffff}, -+ {BRCMS_SROM_MAXP2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff}, -+ {BRCMS_SROM_ITT2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00}, -+ {BRCMS_SROM_ITT5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00}, -+ {BRCMS_SROM_PA2GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff}, -+ {BRCMS_SROM_PA2GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff}, -+ {BRCMS_SROM_PA2GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff}, -+ {BRCMS_SROM_MAXP5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff}, -+ {BRCMS_SROM_MAXP5GHA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff}, -+ {BRCMS_SROM_MAXP5GLA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00}, -+ {BRCMS_SROM_PA5GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff}, -+ {BRCMS_SROM_PA5GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff}, -+ {BRCMS_SROM_PA5GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff}, -+ {BRCMS_SROM_PA5GLW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff}, -+ {BRCMS_SROM_PA5GLW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1, -+ 0xffff}, -+ {BRCMS_SROM_PA5GLW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2, -+ 0xffff}, -+ {BRCMS_SROM_PA5GHW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff}, -+ {BRCMS_SROM_PA5GHW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1, -+ 0xffff}, -+ {BRCMS_SROM_PA5GHW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2, -+ 0xffff}, -+ {BRCMS_SROM_NULL, 0, 0, 0, 0} -+}; -+ -+/* crc table has the same contents for every device instance, so it can be -+ * shared between devices. */ -+static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE]; -+ -+static u16 __iomem * -+srom_window_address(struct si_pub *sih, u8 __iomem *curmap) -+{ -+ if (sih->ccrev < 32) -+ return (u16 __iomem *)(curmap + PCI_BAR0_SPROM_OFFSET); -+ if (sih->cccaps & CC_CAP_SROM) -+ return (u16 __iomem *) -+ (curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP); -+ -+ return NULL; -+} -+ -+/* Parse SROM and create name=value pairs. 'srom' points to -+ * the SROM word array. 'off' specifies the offset of the -+ * first word 'srom' points to, which should be either 0 or -+ * SROM3_SWRG_OFF (full SROM or software region). -+ */ -+ -+static uint mask_shift(u16 mask) -+{ -+ uint i; -+ for (i = 0; i < (sizeof(mask) << 3); i++) { -+ if (mask & (1 << i)) -+ return i; -+ } -+ return 0; -+} -+ -+static uint mask_width(u16 mask) -+{ -+ int i; -+ for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) { -+ if (mask & (1 << i)) -+ return (uint) (i - mask_shift(mask) + 1); -+ } -+ return 0; -+} -+ -+static inline void ltoh16_buf(u16 *buf, unsigned int size) -+{ -+ size /= 2; -+ while (size--) -+ *(buf + size) = le16_to_cpu(*(__le16 *)(buf + size)); -+} -+ -+static inline void htol16_buf(u16 *buf, unsigned int size) -+{ -+ size /= 2; -+ while (size--) -+ *(__le16 *)(buf + size) = cpu_to_le16(*(buf + size)); -+} -+ -+/* -+ * convert binary srom data into linked list of srom variable items. -+ */ -+static void -+_initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list) -+{ -+ struct brcms_srom_list_head *entry; -+ enum brcms_srom_id id; -+ u16 w; -+ u32 val; -+ const struct brcms_sromvar *srv; -+ uint width; -+ uint flags; -+ u32 sr = (1 << sromrev); -+ -+ /* first store the srom revision */ -+ entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL); -+ entry->varid = BRCMS_SROM_REV; -+ entry->var_type = BRCMS_SROM_UNUMBER; -+ entry->uval = sromrev; -+ list_add(&entry->var_list, var_list); -+ -+ for (srv = pci_sromvars; srv->varid != BRCMS_SROM_NULL; srv++) { -+ enum brcms_srom_var_type type; -+ u8 ea[ETH_ALEN]; -+ u8 extra_space = 0; -+ -+ if ((srv->revmask & sr) == 0) -+ continue; -+ -+ flags = srv->flags; -+ id = srv->varid; -+ -+ /* This entry is for mfgc only. Don't generate param for it, */ -+ if (flags & SRFL_NOVAR) -+ continue; -+ -+ if (flags & SRFL_ETHADDR) { -+ /* -+ * stored in string format XX:XX:XX:XX:XX:XX (17 chars) -+ */ -+ ea[0] = (srom[srv->off] >> 8) & 0xff; -+ ea[1] = srom[srv->off] & 0xff; -+ ea[2] = (srom[srv->off + 1] >> 8) & 0xff; -+ ea[3] = srom[srv->off + 1] & 0xff; -+ ea[4] = (srom[srv->off + 2] >> 8) & 0xff; -+ ea[5] = srom[srv->off + 2] & 0xff; -+ /* 17 characters + string terminator - union size */ -+ extra_space = 18 - sizeof(s32); -+ type = BRCMS_SROM_STRING; -+ } else { -+ w = srom[srv->off]; -+ val = (w & srv->mask) >> mask_shift(srv->mask); -+ width = mask_width(srv->mask); -+ -+ while (srv->flags & SRFL_MORE) { -+ srv++; -+ if (srv->off == 0) -+ continue; -+ -+ w = srom[srv->off]; -+ val += -+ ((w & srv->mask) >> mask_shift(srv-> -+ mask)) << -+ width; -+ width += mask_width(srv->mask); -+ } -+ -+ if ((flags & SRFL_NOFFS) -+ && ((int)val == (1 << width) - 1)) -+ continue; -+ -+ if (flags & SRFL_CCODE) { -+ type = BRCMS_SROM_STRING; -+ } else if (flags & SRFL_LEDDC) { -+ /* LED Powersave duty cycle has to be scaled: -+ *(oncount >> 24) (offcount >> 8) -+ */ -+ u32 w32 = /* oncount */ -+ (((val >> 8) & 0xff) << 24) | -+ /* offcount */ -+ (((val & 0xff)) << 8); -+ type = BRCMS_SROM_UNUMBER; -+ val = w32; -+ } else if ((flags & SRFL_PRSIGN) -+ && (val & (1 << (width - 1)))) { -+ type = BRCMS_SROM_SNUMBER; -+ val |= ~0 << width; -+ } else -+ type = BRCMS_SROM_UNUMBER; -+ } -+ -+ entry = kzalloc(sizeof(struct brcms_srom_list_head) + -+ extra_space, GFP_KERNEL); -+ entry->varid = id; -+ entry->var_type = type; -+ if (flags & SRFL_ETHADDR) { -+ snprintf(entry->buf, 18, "%pM", ea); -+ } else if (flags & SRFL_CCODE) { -+ if (val == 0) -+ entry->buf[0] = '\0'; -+ else -+ snprintf(entry->buf, 3, "%c%c", -+ (val >> 8), (val & 0xff)); -+ } else { -+ entry->uval = val; -+ } -+ -+ list_add(&entry->var_list, var_list); -+ } -+ -+ if (sromrev >= 4) { -+ /* Do per-path variables */ -+ uint p, pb, psz; -+ -+ if (sromrev >= 8) { -+ pb = SROM8_PATH0; -+ psz = SROM8_PATH1 - SROM8_PATH0; -+ } else { -+ pb = SROM4_PATH0; -+ psz = SROM4_PATH1 - SROM4_PATH0; -+ } -+ -+ for (p = 0; p < MAX_PATH_SROM; p++) { -+ for (srv = perpath_pci_sromvars; -+ srv->varid != BRCMS_SROM_NULL; srv++) { -+ if ((srv->revmask & sr) == 0) -+ continue; -+ -+ if (srv->flags & SRFL_NOVAR) -+ continue; -+ -+ w = srom[pb + srv->off]; -+ val = (w & srv->mask) >> mask_shift(srv->mask); -+ width = mask_width(srv->mask); -+ -+ /* Cheating: no per-path var is more than -+ * 1 word */ -+ if ((srv->flags & SRFL_NOFFS) -+ && ((int)val == (1 << width) - 1)) -+ continue; -+ -+ entry = -+ kzalloc(sizeof(struct brcms_srom_list_head), -+ GFP_KERNEL); -+ entry->varid = srv->varid+p; -+ entry->var_type = BRCMS_SROM_UNUMBER; -+ entry->uval = val; -+ list_add(&entry->var_list, var_list); -+ } -+ pb += psz; -+ } -+ } -+} -+ -+/* -+ * Read in and validate sprom. -+ * Return 0 on success, nonzero on error. -+ */ -+static int -+sprom_read_pci(struct si_pub *sih, u16 __iomem *sprom, uint wordoff, -+ u16 *buf, uint nwords, bool check_crc) -+{ -+ int err = 0; -+ uint i; -+ -+ /* read the sprom */ -+ for (i = 0; i < nwords; i++) -+ buf[i] = R_REG(&sprom[wordoff + i]); -+ -+ if (check_crc) { -+ -+ if (buf[0] == 0xffff) -+ /* -+ * The hardware thinks that an srom that starts with -+ * 0xffff is blank, regardless of the rest of the -+ * content, so declare it bad. -+ */ -+ return -ENODATA; -+ -+ /* fixup the endianness so crc8 will pass */ -+ htol16_buf(buf, nwords * 2); -+ if (crc8(brcms_srom_crc8_table, (u8 *) buf, nwords * 2, -+ CRC8_INIT_VALUE) != -+ CRC8_GOOD_VALUE(brcms_srom_crc8_table)) -+ /* DBG only pci always read srom4 first, then srom8/9 */ -+ err = -EIO; -+ -+ /* now correct the endianness of the byte array */ -+ ltoh16_buf(buf, nwords * 2); -+ } -+ return err; -+} -+ -+static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz) -+{ -+ u8 *otp; -+ uint sz = OTP_SZ_MAX / 2; /* size in words */ -+ int err = 0; -+ -+ otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC); -+ if (otp == NULL) -+ return -ENOMEM; -+ -+ err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz); -+ -+ memcpy(buf, otp, bufsz); -+ -+ kfree(otp); -+ -+ /* Check CRC */ -+ if (buf[0] == 0xffff) -+ /* The hardware thinks that an srom that starts with 0xffff -+ * is blank, regardless of the rest of the content, so declare -+ * it bad. -+ */ -+ return -ENODATA; -+ -+ /* fixup the endianness so crc8 will pass */ -+ htol16_buf(buf, bufsz); -+ if (crc8(brcms_srom_crc8_table, (u8 *) buf, SROM4_WORDS * 2, -+ CRC8_INIT_VALUE) != CRC8_GOOD_VALUE(brcms_srom_crc8_table)) -+ err = -EIO; -+ -+ /* now correct the endianness of the byte array */ -+ ltoh16_buf(buf, bufsz); -+ -+ return err; -+} -+ -+/* -+ * Initialize nonvolatile variable table from sprom. -+ * Return 0 on success, nonzero on error. -+ */ -+static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap) -+{ -+ u16 *srom; -+ u16 __iomem *sromwindow; -+ u8 sromrev = 0; -+ u32 sr; -+ int err = 0; -+ -+ /* -+ * Apply CRC over SROM content regardless SROM is present or not. -+ */ -+ srom = kmalloc(SROM_MAX, GFP_ATOMIC); -+ if (!srom) -+ return -ENOMEM; -+ -+ sromwindow = srom_window_address(sih, curmap); -+ -+ crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY); -+ if (ai_is_sprom_available(sih)) { -+ err = sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS, -+ true); -+ -+ if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) || -+ (((sih->buscoretype == PCIE_CORE_ID) -+ && (sih->buscorerev >= 6)) -+ || ((sih->buscoretype == PCI_CORE_ID) -+ && (sih->buscorerev >= 0xe)))) { -+ /* sromrev >= 4, read more */ -+ err = sprom_read_pci(sih, sromwindow, 0, srom, -+ SROM4_WORDS, true); -+ sromrev = srom[SROM4_CRCREV] & 0xff; -+ } else if (err == 0) { -+ /* srom is good and is rev < 4 */ -+ /* top word of sprom contains version and crc8 */ -+ sromrev = srom[SROM_CRCREV] & 0xff; -+ /* bcm4401 sroms misprogrammed */ -+ if (sromrev == 0x10) -+ sromrev = 1; -+ } -+ } else { -+ /* Use OTP if SPROM not available */ -+ err = otp_read_pci(sih, srom, SROM_MAX); -+ if (err == 0) -+ /* OTP only contain SROM rev8/rev9 for now */ -+ sromrev = srom[SROM4_CRCREV] & 0xff; -+ } -+ -+ if (!err) { -+ struct si_info *sii = (struct si_info *)sih; -+ -+ /* Bitmask for the sromrev */ -+ sr = 1 << sromrev; -+ -+ /* -+ * srom version check: Current valid versions: 1, 2, 3, 4, 5, 8, -+ * 9 -+ */ -+ if ((sr & 0x33e) == 0) { -+ err = -EINVAL; -+ goto errout; -+ } -+ -+ INIT_LIST_HEAD(&sii->var_list); -+ -+ /* parse SROM into name=value pairs. */ -+ _initvars_srom_pci(sromrev, srom, &sii->var_list); -+ } -+ -+errout: -+ kfree(srom); -+ return err; -+} -+ -+void srom_free_vars(struct si_pub *sih) -+{ -+ struct si_info *sii; -+ struct brcms_srom_list_head *entry, *next; -+ -+ sii = (struct si_info *)sih; -+ list_for_each_entry_safe(entry, next, &sii->var_list, var_list) { -+ list_del(&entry->var_list); -+ kfree(entry); -+ } -+} -+/* -+ * Initialize local vars from the right source for this platform. -+ * Return 0 on success, nonzero on error. -+ */ -+int srom_var_init(struct si_pub *sih, void __iomem *curmap) -+{ -+ uint len; -+ -+ len = 0; -+ -+ if (curmap != NULL) -+ return initvars_srom_pci(sih, curmap); -+ -+ return -EINVAL; -+} -+ -+/* -+ * Search the name=value vars for a specific one and return its value. -+ * Returns NULL if not found. -+ */ -+char *getvar(struct si_pub *sih, enum brcms_srom_id id) -+{ -+ struct si_info *sii; -+ struct brcms_srom_list_head *entry; -+ -+ sii = (struct si_info *)sih; -+ -+ list_for_each_entry(entry, &sii->var_list, var_list) -+ if (entry->varid == id) -+ return &entry->buf[0]; -+ -+ /* nothing found */ -+ return NULL; -+} -+ -+/* -+ * Search the vars for a specific one and return its value as -+ * an integer. Returns 0 if not found.- -+ */ -+int getintvar(struct si_pub *sih, enum brcms_srom_id id) -+{ -+ struct si_info *sii; -+ struct brcms_srom_list_head *entry; -+ unsigned long res; -+ -+ sii = (struct si_info *)sih; -+ -+ list_for_each_entry(entry, &sii->var_list, var_list) -+ if (entry->varid == id) { -+ if (entry->var_type == BRCMS_SROM_SNUMBER || -+ entry->var_type == BRCMS_SROM_UNUMBER) -+ return (int)entry->sval; -+ else if (!kstrtoul(&entry->buf[0], 0, &res)) -+ return (int)res; -+ } -+ -+ return 0; -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.h.orig 2011-11-09 13:46:58.285800133 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.h 2011-11-09 13:47:17.044565616 -0500 -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_SROM_H_ -+#define _BRCM_SROM_H_ -+ -+#include "types.h" -+ -+/* Prototypes */ -+extern int srom_var_init(struct si_pub *sih, void __iomem *curmap); -+extern void srom_free_vars(struct si_pub *sih); -+ -+extern int srom_read(struct si_pub *sih, uint bus, void *curmap, -+ uint byteoff, uint nbytes, u16 *buf, bool check_crc); -+ -+/* parse standard PCMCIA cis, normally used by SB/PCMCIA/SDIO/SPI/OTP -+ * and extract from it into name=value pairs -+ */ -+extern int srom_parsecis(u8 **pcis, uint ciscnt, -+ char **vars, uint *count); -+#endif /* _BRCM_SROM_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.c.orig 2011-11-09 13:46:58.286800121 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.c 2011-11-09 13:47:17.045565604 -0500 -@@ -0,0 +1,436 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+ -+#include "types.h" -+#include "d11.h" -+#include "rate.h" -+#include "phy/phy_hal.h" -+#include "channel.h" -+#include "main.h" -+#include "stf.h" -+ -+#define MIN_SPATIAL_EXPANSION 0 -+#define MAX_SPATIAL_EXPANSION 1 -+ -+#define BRCMS_STF_SS_STBC_RX(wlc) (BRCMS_ISNPHY(wlc->band) && \ -+ NREV_GT(wlc->band->phyrev, 3) && NREV_LE(wlc->band->phyrev, 6)) -+ -+#define NSTS_1 1 -+#define NSTS_2 2 -+#define NSTS_3 3 -+#define NSTS_4 4 -+ -+static const u8 txcore_default[5] = { -+ (0), /* bitmap of the core enabled */ -+ (0x01), /* For Nsts = 1, enable core 1 */ -+ (0x03), /* For Nsts = 2, enable core 1 & 2 */ -+ (0x07), /* For Nsts = 3, enable core 1, 2 & 3 */ -+ (0x0f) /* For Nsts = 4, enable all cores */ -+}; -+ -+static void brcms_c_stf_stbc_rx_ht_update(struct brcms_c_info *wlc, int val) -+{ -+ /* MIMOPHYs rev3-6 cannot receive STBC with only one rx core active */ -+ if (BRCMS_STF_SS_STBC_RX(wlc)) { -+ if ((wlc->stf->rxstreams == 1) && (val != HT_CAP_RX_STBC_NO)) -+ return; -+ } -+ -+ if (wlc->pub->up) { -+ brcms_c_update_beacon(wlc); -+ brcms_c_update_probe_resp(wlc, true); -+ } -+} -+ -+/* -+ * every WLC_TEMPSENSE_PERIOD seconds temperature check to decide whether to -+ * turn on/off txchain. -+ */ -+void brcms_c_tempsense_upd(struct brcms_c_info *wlc) -+{ -+ struct brcms_phy_pub *pi = wlc->band->pi; -+ uint active_chains, txchain; -+ -+ /* Check if the chip is too hot. Disable one Tx chain, if it is */ -+ /* high 4 bits are for Rx chain, low 4 bits are for Tx chain */ -+ active_chains = wlc_phy_stf_chain_active_get(pi); -+ txchain = active_chains & 0xf; -+ -+ if (wlc->stf->txchain == wlc->stf->hw_txchain) { -+ if (txchain && (txchain < wlc->stf->hw_txchain)) -+ /* turn off 1 tx chain */ -+ brcms_c_stf_txchain_set(wlc, txchain, true); -+ } else if (wlc->stf->txchain < wlc->stf->hw_txchain) { -+ if (txchain == wlc->stf->hw_txchain) -+ /* turn back on txchain */ -+ brcms_c_stf_txchain_set(wlc, txchain, true); -+ } -+} -+ -+void -+brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel, -+ u16 chanspec) -+{ -+ struct tx_power power; -+ u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id; -+ -+ /* Clear previous settings */ -+ *ss_algo_channel = 0; -+ -+ if (!wlc->pub->up) { -+ *ss_algo_channel = (u16) -1; -+ return; -+ } -+ -+ wlc_phy_txpower_get_current(wlc->band->pi, &power, -+ CHSPEC_CHANNEL(chanspec)); -+ -+ siso_mcs_id = (CHSPEC_IS40(chanspec)) ? -+ WL_TX_POWER_MCS40_SISO_FIRST : WL_TX_POWER_MCS20_SISO_FIRST; -+ cdd_mcs_id = (CHSPEC_IS40(chanspec)) ? -+ WL_TX_POWER_MCS40_CDD_FIRST : WL_TX_POWER_MCS20_CDD_FIRST; -+ stbc_mcs_id = (CHSPEC_IS40(chanspec)) ? -+ WL_TX_POWER_MCS40_STBC_FIRST : WL_TX_POWER_MCS20_STBC_FIRST; -+ -+ /* criteria to choose stf mode */ -+ -+ /* -+ * the "+3dbm (12 0.25db units)" is to account for the fact that with -+ * CDD, tx occurs on both chains -+ */ -+ if (power.target[siso_mcs_id] > (power.target[cdd_mcs_id] + 12)) -+ setbit(ss_algo_channel, PHY_TXC1_MODE_SISO); -+ else -+ setbit(ss_algo_channel, PHY_TXC1_MODE_CDD); -+ -+ /* -+ * STBC is ORed into to algo channel as STBC requires per-packet SCB -+ * capability check so cannot be default mode of operation. One of -+ * SISO, CDD have to be set -+ */ -+ if (power.target[siso_mcs_id] <= (power.target[stbc_mcs_id] + 12)) -+ setbit(ss_algo_channel, PHY_TXC1_MODE_STBC); -+} -+ -+static bool brcms_c_stf_stbc_tx_set(struct brcms_c_info *wlc, s32 int_val) -+{ -+ if ((int_val != AUTO) && (int_val != OFF) && (int_val != ON)) -+ return false; -+ -+ if ((int_val == ON) && (wlc->stf->txstreams == 1)) -+ return false; -+ -+ wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = (s8) int_val; -+ wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = (s8) int_val; -+ -+ return true; -+} -+ -+bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val) -+{ -+ if ((int_val != HT_CAP_RX_STBC_NO) -+ && (int_val != HT_CAP_RX_STBC_ONE_STREAM)) -+ return false; -+ -+ if (BRCMS_STF_SS_STBC_RX(wlc)) { -+ if ((int_val != HT_CAP_RX_STBC_NO) -+ && (wlc->stf->rxstreams == 1)) -+ return false; -+ } -+ -+ brcms_c_stf_stbc_rx_ht_update(wlc, int_val); -+ return true; -+} -+ -+static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts, -+ u8 core_mask) -+{ -+ BCMMSG(wlc->wiphy, "wl%d: Nsts %d core_mask %x\n", -+ wlc->pub->unit, Nsts, core_mask); -+ -+ if (hweight8(core_mask) > wlc->stf->txstreams) -+ core_mask = 0; -+ -+ if ((hweight8(core_mask) == wlc->stf->txstreams) && -+ ((core_mask & ~wlc->stf->txchain) -+ || !(core_mask & wlc->stf->txchain))) -+ core_mask = wlc->stf->txchain; -+ -+ wlc->stf->txcore[Nsts] = core_mask; -+ /* Nsts = 1..4, txcore index = 1..4 */ -+ if (Nsts == 1) { -+ /* Needs to update beacon and ucode generated response -+ * frames when 1 stream core map changed -+ */ -+ wlc->stf->phytxant = core_mask << PHY_TXC_ANT_SHIFT; -+ brcms_b_txant_set(wlc->hw, wlc->stf->phytxant); -+ if (wlc->clk) { -+ brcms_c_suspend_mac_and_wait(wlc); -+ brcms_c_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec); -+ brcms_c_enable_mac(wlc); -+ } -+ } -+ -+ return 0; -+} -+ -+static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val) -+{ -+ int i; -+ u8 core_mask = 0; -+ -+ BCMMSG(wlc->wiphy, "wl%d: val %x\n", wlc->pub->unit, val); -+ -+ wlc->stf->spatial_policy = (s8) val; -+ for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) { -+ core_mask = (val == MAX_SPATIAL_EXPANSION) ? -+ wlc->stf->txchain : txcore_default[i]; -+ brcms_c_stf_txcore_set(wlc, (u8) i, core_mask); -+ } -+ return 0; -+} -+ -+/* -+ * Centralized txant update function. call it whenever wlc->stf->txant and/or -+ * wlc->stf->txchain change. -+ * -+ * Antennas are controlled by ucode indirectly, which drives PHY or GPIO to -+ * achieve various tx/rx antenna selection schemes -+ * -+ * legacy phy, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 -+ * means auto(last rx). -+ * for NREV<3, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 -+ * means last rx and do tx-antenna selection for SISO transmissions -+ * for NREV=3, bit 6 and bit _8_ means antenna 0 and 1 respectively, bit6+bit7 -+ * means last rx and do tx-antenna selection for SISO transmissions -+ * for NREV>=7, bit 6 and bit 7 mean antenna 0 and 1 respectively, nit6+bit7 -+ * means both cores active -+*/ -+static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc) -+{ -+ s8 txant; -+ -+ txant = (s8) wlc->stf->txant; -+ if (BRCMS_PHY_11N_CAP(wlc->band)) { -+ if (txant == ANT_TX_FORCE_0) { -+ wlc->stf->phytxant = PHY_TXC_ANT_0; -+ } else if (txant == ANT_TX_FORCE_1) { -+ wlc->stf->phytxant = PHY_TXC_ANT_1; -+ -+ if (BRCMS_ISNPHY(wlc->band) && -+ NREV_GE(wlc->band->phyrev, 3) -+ && NREV_LT(wlc->band->phyrev, 7)) -+ wlc->stf->phytxant = PHY_TXC_ANT_2; -+ } else { -+ if (BRCMS_ISLCNPHY(wlc->band) || -+ BRCMS_ISSSLPNPHY(wlc->band)) -+ wlc->stf->phytxant = PHY_TXC_LCNPHY_ANT_LAST; -+ else { -+ /* catch out of sync wlc->stf->txcore */ -+ WARN_ON(wlc->stf->txchain <= 0); -+ wlc->stf->phytxant = -+ wlc->stf->txchain << PHY_TXC_ANT_SHIFT; -+ } -+ } -+ } else { -+ if (txant == ANT_TX_FORCE_0) -+ wlc->stf->phytxant = PHY_TXC_OLD_ANT_0; -+ else if (txant == ANT_TX_FORCE_1) -+ wlc->stf->phytxant = PHY_TXC_OLD_ANT_1; -+ else -+ wlc->stf->phytxant = PHY_TXC_OLD_ANT_LAST; -+ } -+ -+ brcms_b_txant_set(wlc->hw, wlc->stf->phytxant); -+} -+ -+int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force) -+{ -+ u8 txchain = (u8) int_val; -+ u8 txstreams; -+ uint i; -+ -+ if (wlc->stf->txchain == txchain) -+ return 0; -+ -+ if ((txchain & ~wlc->stf->hw_txchain) -+ || !(txchain & wlc->stf->hw_txchain)) -+ return -EINVAL; -+ -+ /* -+ * if nrate override is configured to be non-SISO STF mode, reject -+ * reducing txchain to 1 -+ */ -+ txstreams = (u8) hweight8(txchain); -+ if (txstreams > MAX_STREAMS_SUPPORTED) -+ return -EINVAL; -+ -+ wlc->stf->txchain = txchain; -+ wlc->stf->txstreams = txstreams; -+ brcms_c_stf_stbc_tx_set(wlc, wlc->band->band_stf_stbc_tx); -+ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]); -+ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]); -+ wlc->stf->txant = -+ (wlc->stf->txstreams == 1) ? ANT_TX_FORCE_0 : ANT_TX_DEF; -+ _brcms_c_stf_phy_txant_upd(wlc); -+ -+ wlc_phy_stf_chain_set(wlc->band->pi, wlc->stf->txchain, -+ wlc->stf->rxchain); -+ -+ for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) -+ brcms_c_stf_txcore_set(wlc, (u8) i, txcore_default[i]); -+ -+ return 0; -+} -+ -+/* -+ * update wlc->stf->ss_opmode which represents the operational stf_ss mode -+ * we're using -+ */ -+int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band) -+{ -+ int ret_code = 0; -+ u8 prev_stf_ss; -+ u8 upd_stf_ss; -+ -+ prev_stf_ss = wlc->stf->ss_opmode; -+ -+ /* -+ * NOTE: opmode can only be SISO or CDD as STBC is decided on a -+ * per-packet basis -+ */ -+ if (BRCMS_STBC_CAP_PHY(wlc) && -+ wlc->stf->ss_algosel_auto -+ && (wlc->stf->ss_algo_channel != (u16) -1)) { -+ upd_stf_ss = (wlc->stf->txstreams == 1 || -+ isset(&wlc->stf->ss_algo_channel, -+ PHY_TXC1_MODE_SISO)) ? -+ PHY_TXC1_MODE_SISO : PHY_TXC1_MODE_CDD; -+ } else { -+ if (wlc->band != band) -+ return ret_code; -+ upd_stf_ss = (wlc->stf->txstreams == 1) ? -+ PHY_TXC1_MODE_SISO : band->band_stf_ss_mode; -+ } -+ if (prev_stf_ss != upd_stf_ss) { -+ wlc->stf->ss_opmode = upd_stf_ss; -+ brcms_b_band_stf_ss_set(wlc->hw, upd_stf_ss); -+ } -+ -+ return ret_code; -+} -+ -+int brcms_c_stf_attach(struct brcms_c_info *wlc) -+{ -+ wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_SISO; -+ wlc->bandstate[BAND_5G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_CDD; -+ -+ if (BRCMS_ISNPHY(wlc->band) && -+ (wlc_phy_txpower_hw_ctrl_get(wlc->band->pi) != PHY_TPC_HW_ON)) -+ wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode = -+ PHY_TXC1_MODE_CDD; -+ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]); -+ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]); -+ -+ brcms_c_stf_stbc_rx_ht_update(wlc, HT_CAP_RX_STBC_NO); -+ wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF; -+ wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF; -+ -+ if (BRCMS_STBC_CAP_PHY(wlc)) { -+ wlc->stf->ss_algosel_auto = true; -+ /* Init the default value */ -+ wlc->stf->ss_algo_channel = (u16) -1; -+ } -+ return 0; -+} -+ -+void brcms_c_stf_detach(struct brcms_c_info *wlc) -+{ -+} -+ -+void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc) -+{ -+ _brcms_c_stf_phy_txant_upd(wlc); -+} -+ -+void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc) -+{ -+ /* get available rx/tx chains */ -+ wlc->stf->hw_txchain = (u8) getintvar(wlc->hw->sih, BRCMS_SROM_TXCHAIN); -+ wlc->stf->hw_rxchain = (u8) getintvar(wlc->hw->sih, BRCMS_SROM_RXCHAIN); -+ -+ /* these parameter are intended to be used for all PHY types */ -+ if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) { -+ if (BRCMS_ISNPHY(wlc->band)) -+ wlc->stf->hw_txchain = TXCHAIN_DEF_NPHY; -+ else -+ wlc->stf->hw_txchain = TXCHAIN_DEF; -+ } -+ -+ wlc->stf->txchain = wlc->stf->hw_txchain; -+ wlc->stf->txstreams = (u8) hweight8(wlc->stf->hw_txchain); -+ -+ if (wlc->stf->hw_rxchain == 0 || wlc->stf->hw_rxchain == 0xf) { -+ if (BRCMS_ISNPHY(wlc->band)) -+ wlc->stf->hw_rxchain = RXCHAIN_DEF_NPHY; -+ else -+ wlc->stf->hw_rxchain = RXCHAIN_DEF; -+ } -+ -+ wlc->stf->rxchain = wlc->stf->hw_rxchain; -+ wlc->stf->rxstreams = (u8) hweight8(wlc->stf->hw_rxchain); -+ -+ /* initialize the txcore table */ -+ memcpy(wlc->stf->txcore, txcore_default, sizeof(wlc->stf->txcore)); -+ -+ /* default spatial_policy */ -+ wlc->stf->spatial_policy = MIN_SPATIAL_EXPANSION; -+ brcms_c_stf_spatial_policy_set(wlc, MIN_SPATIAL_EXPANSION); -+} -+ -+static u16 _brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, -+ u32 rspec) -+{ -+ u16 phytxant = wlc->stf->phytxant; -+ -+ if (rspec_stf(rspec) != PHY_TXC1_MODE_SISO) -+ phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT; -+ else if (wlc->stf->txant == ANT_TX_DEF) -+ phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT; -+ phytxant &= PHY_TXC_ANT_MASK; -+ return phytxant; -+} -+ -+u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, u32 rspec) -+{ -+ return _brcms_c_stf_phytxchain_sel(wlc, rspec); -+} -+ -+u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, u32 rspec) -+{ -+ u16 phytxant = wlc->stf->phytxant; -+ u16 mask = PHY_TXC_ANT_MASK; -+ -+ /* for non-siso rates or default setting, use the available chains */ -+ if (BRCMS_ISNPHY(wlc->band)) { -+ phytxant = _brcms_c_stf_phytxchain_sel(wlc, rspec); -+ mask = PHY_TXC_HTANT_MASK; -+ } -+ phytxant |= phytxant & mask; -+ return phytxant; -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.h.orig 2011-11-09 13:46:58.286800121 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.h 2011-11-09 13:47:17.045565604 -0500 -@@ -0,0 +1,42 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_STF_H_ -+#define _BRCM_STF_H_ -+ -+#include "types.h" -+ -+extern int brcms_c_stf_attach(struct brcms_c_info *wlc); -+extern void brcms_c_stf_detach(struct brcms_c_info *wlc); -+ -+extern void brcms_c_tempsense_upd(struct brcms_c_info *wlc); -+extern void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, -+ u16 *ss_algo_channel, -+ u16 chanspec); -+extern int brcms_c_stf_ss_update(struct brcms_c_info *wlc, -+ struct brcms_band *band); -+extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc); -+extern int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, -+ bool force); -+extern bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val); -+extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc); -+extern void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc); -+extern u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, -+ u32 rspec); -+extern u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, -+ u32 rspec); -+ -+#endif /* _BRCM_STF_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/types.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/types.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/types.h.orig 2011-11-09 13:46:58.286800121 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/types.h 2011-11-09 13:47:17.045565604 -0500 -@@ -0,0 +1,352 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_TYPES_H_ -+#define _BRCM_TYPES_H_ -+ -+#include -+#include -+ -+#define WL_CHAN_FREQ_RANGE_2G 0 -+#define WL_CHAN_FREQ_RANGE_5GL 1 -+#define WL_CHAN_FREQ_RANGE_5GM 2 -+#define WL_CHAN_FREQ_RANGE_5GH 3 -+ -+/* boardflags */ -+ -+/* Board has gpio 9 controlling the PA */ -+#define BFL_PACTRL 0x00000002 -+/* Not ok to power down the chip pll and oscillator */ -+#define BFL_NOPLLDOWN 0x00000020 -+/* Board supports the Front End Module */ -+#define BFL_FEM 0x00000800 -+/* Board has an external LNA in 2.4GHz band */ -+#define BFL_EXTLNA 0x00001000 -+/* Board has no PA */ -+#define BFL_NOPA 0x00010000 -+/* Power topology uses BUCKBOOST */ -+#define BFL_BUCKBOOST 0x00200000 -+/* Board has FEM and switch to share antenna w/ BT */ -+#define BFL_FEM_BT 0x00400000 -+/* Power topology doesn't use CBUCK */ -+#define BFL_NOCBUCK 0x00800000 -+/* Power topology uses PALDO */ -+#define BFL_PALDO 0x02000000 -+/* Board has an external LNA in 5GHz band */ -+#define BFL_EXTLNA_5GHz 0x10000000 -+ -+/* boardflags2 */ -+ -+/* Board has an external rxbb regulator */ -+#define BFL2_RXBB_INT_REG_DIS 0x00000001 -+/* Flag to implement alternative A-band PLL settings */ -+#define BFL2_APLL_WAR 0x00000002 -+/* Board permits enabling TX Power Control */ -+#define BFL2_TXPWRCTRL_EN 0x00000004 -+/* Board supports the 2X4 diversity switch */ -+#define BFL2_2X4_DIV 0x00000008 -+/* Board supports 5G band power gain */ -+#define BFL2_5G_PWRGAIN 0x00000010 -+/* Board overrides ASPM and Clkreq settings */ -+#define BFL2_PCIEWAR_OVR 0x00000020 -+#define BFL2_LEGACY 0x00000080 -+/* 4321mcm93 board uses Skyworks FEM */ -+#define BFL2_SKWRKFEM_BRD 0x00000100 -+/* Board has a WAR for clock-harmonic spurs */ -+#define BFL2_SPUR_WAR 0x00000200 -+/* Flag to narrow G-band PLL loop b/w */ -+#define BFL2_GPLL_WAR 0x00000400 -+/* Tx CCK pkts on Ant 0 only */ -+#define BFL2_SINGLEANT_CCK 0x00001000 -+/* WAR to reduce and avoid clock-harmonic spurs in 2G */ -+#define BFL2_2G_SPUR_WAR 0x00002000 -+/* Flag to widen G-band PLL loop b/w */ -+#define BFL2_GPLL_WAR2 0x00010000 -+#define BFL2_IPALVLSHIFT_3P3 0x00020000 -+/* Use internal envelope detector for TX IQCAL */ -+#define BFL2_INTERNDET_TXIQCAL 0x00040000 -+/* Keep the buffered Xtal output from radio "ON". Most drivers will turn it -+ * off without this flag to save power. */ -+#define BFL2_XTALBUFOUTEN 0x00080000 -+ -+/* -+ * board specific GPIO assignment, gpio 0-3 are also customer-configurable -+ * led -+ */ -+ -+/* bit 9 controls the PA on new 4306 boards */ -+#define BOARD_GPIO_PACTRL 0x200 -+#define BOARD_GPIO_12 0x1000 -+#define BOARD_GPIO_13 0x2000 -+ -+/* **** Core type/rev defaults **** */ -+#define D11CONF 0x0fffffb0 /* Supported D11 revs: 4, 5, 7-27 -+ * also need to update wlc.h MAXCOREREV -+ */ -+ -+#define NCONF 0x000001ff /* Supported nphy revs: -+ * 0 4321a0 -+ * 1 4321a1 -+ * 2 4321b0/b1/c0/c1 -+ * 3 4322a0 -+ * 4 4322a1 -+ * 5 4716a0 -+ * 6 43222a0, 43224a0 -+ * 7 43226a0 -+ * 8 5357a0, 43236a0 -+ */ -+ -+#define LCNCONF 0x00000007 /* Supported lcnphy revs: -+ * 0 4313a0, 4336a0, 4330a0 -+ * 1 -+ * 2 4330a0 -+ */ -+ -+#define SSLPNCONF 0x0000000f /* Supported sslpnphy revs: -+ * 0 4329a0/k0 -+ * 1 4329b0/4329C0 -+ * 2 4319a0 -+ * 3 5356a0 -+ */ -+ -+/******************************************************************** -+ * Phy/Core Configuration. Defines macros to to check core phy/rev * -+ * compile-time configuration. Defines default core support. * -+ * ****************************************************************** -+ */ -+ -+/* Basic macros to check a configuration bitmask */ -+ -+#define CONF_HAS(config, val) ((config) & (1 << (val))) -+#define CONF_MSK(config, mask) ((config) & (mask)) -+#define MSK_RANGE(low, hi) ((1 << ((hi)+1)) - (1 << (low))) -+#define CONF_RANGE(config, low, hi) (CONF_MSK(config, MSK_RANGE(low, high))) -+ -+#define CONF_IS(config, val) ((config) == (1 << (val))) -+#define CONF_GE(config, val) ((config) & (0-(1 << (val)))) -+#define CONF_GT(config, val) ((config) & (0-2*(1 << (val)))) -+#define CONF_LT(config, val) ((config) & ((1 << (val))-1)) -+#define CONF_LE(config, val) ((config) & (2*(1 << (val))-1)) -+ -+/* Wrappers for some of the above, specific to config constants */ -+ -+#define NCONF_HAS(val) CONF_HAS(NCONF, val) -+#define NCONF_MSK(mask) CONF_MSK(NCONF, mask) -+#define NCONF_IS(val) CONF_IS(NCONF, val) -+#define NCONF_GE(val) CONF_GE(NCONF, val) -+#define NCONF_GT(val) CONF_GT(NCONF, val) -+#define NCONF_LT(val) CONF_LT(NCONF, val) -+#define NCONF_LE(val) CONF_LE(NCONF, val) -+ -+#define LCNCONF_HAS(val) CONF_HAS(LCNCONF, val) -+#define LCNCONF_MSK(mask) CONF_MSK(LCNCONF, mask) -+#define LCNCONF_IS(val) CONF_IS(LCNCONF, val) -+#define LCNCONF_GE(val) CONF_GE(LCNCONF, val) -+#define LCNCONF_GT(val) CONF_GT(LCNCONF, val) -+#define LCNCONF_LT(val) CONF_LT(LCNCONF, val) -+#define LCNCONF_LE(val) CONF_LE(LCNCONF, val) -+ -+#define D11CONF_HAS(val) CONF_HAS(D11CONF, val) -+#define D11CONF_MSK(mask) CONF_MSK(D11CONF, mask) -+#define D11CONF_IS(val) CONF_IS(D11CONF, val) -+#define D11CONF_GE(val) CONF_GE(D11CONF, val) -+#define D11CONF_GT(val) CONF_GT(D11CONF, val) -+#define D11CONF_LT(val) CONF_LT(D11CONF, val) -+#define D11CONF_LE(val) CONF_LE(D11CONF, val) -+ -+#define PHYCONF_HAS(val) CONF_HAS(PHYTYPE, val) -+#define PHYCONF_IS(val) CONF_IS(PHYTYPE, val) -+ -+#define NREV_IS(var, val) \ -+ (NCONF_HAS(val) && (NCONF_IS(val) || ((var) == (val)))) -+ -+#define NREV_GE(var, val) \ -+ (NCONF_GE(val) && (!NCONF_LT(val) || ((var) >= (val)))) -+ -+#define NREV_GT(var, val) \ -+ (NCONF_GT(val) && (!NCONF_LE(val) || ((var) > (val)))) -+ -+#define NREV_LT(var, val) \ -+ (NCONF_LT(val) && (!NCONF_GE(val) || ((var) < (val)))) -+ -+#define NREV_LE(var, val) \ -+ (NCONF_LE(val) && (!NCONF_GT(val) || ((var) <= (val)))) -+ -+#define LCNREV_IS(var, val) \ -+ (LCNCONF_HAS(val) && (LCNCONF_IS(val) || ((var) == (val)))) -+ -+#define LCNREV_GE(var, val) \ -+ (LCNCONF_GE(val) && (!LCNCONF_LT(val) || ((var) >= (val)))) -+ -+#define LCNREV_GT(var, val) \ -+ (LCNCONF_GT(val) && (!LCNCONF_LE(val) || ((var) > (val)))) -+ -+#define LCNREV_LT(var, val) \ -+ (LCNCONF_LT(val) && (!LCNCONF_GE(val) || ((var) < (val)))) -+ -+#define LCNREV_LE(var, val) \ -+ (LCNCONF_LE(val) && (!LCNCONF_GT(val) || ((var) <= (val)))) -+ -+#define D11REV_IS(var, val) \ -+ (D11CONF_HAS(val) && (D11CONF_IS(val) || ((var) == (val)))) -+ -+#define D11REV_GE(var, val) \ -+ (D11CONF_GE(val) && (!D11CONF_LT(val) || ((var) >= (val)))) -+ -+#define D11REV_GT(var, val) \ -+ (D11CONF_GT(val) && (!D11CONF_LE(val) || ((var) > (val)))) -+ -+#define D11REV_LT(var, val) \ -+ (D11CONF_LT(val) && (!D11CONF_GE(val) || ((var) < (val)))) -+ -+#define D11REV_LE(var, val) \ -+ (D11CONF_LE(val) && (!D11CONF_GT(val) || ((var) <= (val)))) -+ -+#define PHYTYPE_IS(var, val)\ -+ (PHYCONF_HAS(val) && (PHYCONF_IS(val) || ((var) == (val)))) -+ -+/* Set up PHYTYPE automatically: (depends on PHY_TYPE_X, from d11.h) */ -+ -+#define _PHYCONF_N (1 << PHY_TYPE_N) -+#define _PHYCONF_LCN (1 << PHY_TYPE_LCN) -+#define _PHYCONF_SSLPN (1 << PHY_TYPE_SSN) -+ -+#define PHYTYPE (_PHYCONF_N | _PHYCONF_LCN | _PHYCONF_SSLPN) -+ -+/* Utility macro to identify 802.11n (HT) capable PHYs */ -+#define PHYTYPE_11N_CAP(phytype) \ -+ (PHYTYPE_IS(phytype, PHY_TYPE_N) || \ -+ PHYTYPE_IS(phytype, PHY_TYPE_LCN) || \ -+ PHYTYPE_IS(phytype, PHY_TYPE_SSN)) -+ -+/* Last but not least: shorter wlc-specific var checks */ -+#define BRCMS_ISNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_N) -+#define BRCMS_ISLCNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_LCN) -+#define BRCMS_ISSSLPNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_SSN) -+ -+#define BRCMS_PHY_11N_CAP(band) PHYTYPE_11N_CAP((band)->phytype) -+ -+/********************************************************************** -+ * ------------- End of Core phy/rev configuration. ----------------- * -+ * ******************************************************************** -+ */ -+ -+#define BCMMSG(dev, fmt, args...) \ -+do { \ -+ if (brcm_msg_level & LOG_TRACE_VAL) \ -+ wiphy_err(dev, "%s: " fmt, __func__, ##args); \ -+} while (0) -+ -+/* -+ * Register access macros. -+ * -+ * These macro's take a pointer to the address to read as one of their -+ * arguments. The macro itself deduces the size of the IO transaction (u8, u16 -+ * or u32). Advantage of this approach in combination with using a struct to -+ * define the registers in a register block, is that access size and access -+ * location are defined in only one spot. This reduces the risk of the -+ * programmer trying to use an unsupported transaction size on a register. -+ * -+ */ -+ -+#define R_REG(r) \ -+ ({ \ -+ __typeof(*(r)) __osl_v; \ -+ switch (sizeof(*(r))) { \ -+ case sizeof(u8): \ -+ __osl_v = readb((u8 __iomem *)(r)); \ -+ break; \ -+ case sizeof(u16): \ -+ __osl_v = readw((u16 __iomem *)(r)); \ -+ break; \ -+ case sizeof(u32): \ -+ __osl_v = readl((u32 __iomem *)(r)); \ -+ break; \ -+ } \ -+ __osl_v; \ -+ }) -+ -+#define W_REG(r, v) do { \ -+ switch (sizeof(*(r))) { \ -+ case sizeof(u8): \ -+ writeb((u8)((v) & 0xFF), (u8 __iomem *)(r)); \ -+ break; \ -+ case sizeof(u16): \ -+ writew((u16)((v) & 0xFFFF), (u16 __iomem *)(r)); \ -+ break; \ -+ case sizeof(u32): \ -+ writel((u32)(v), (u32 __iomem *)(r)); \ -+ break; \ -+ } \ -+ } while (0) -+ -+#ifdef CONFIG_BCM47XX -+/* -+ * bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder -+ * transactions. As a fix, a read after write is performed on certain places -+ * in the code. Older chips and the newer 5357 family don't require this fix. -+ */ -+#define W_REG_FLUSH(r, v) ({ W_REG((r), (v)); (void)R_REG(r); }) -+#else -+#define W_REG_FLUSH(r, v) W_REG((r), (v)) -+#endif /* CONFIG_BCM47XX */ -+ -+#define AND_REG(r, v) W_REG((r), R_REG(r) & (v)) -+#define OR_REG(r, v) W_REG((r), R_REG(r) | (v)) -+ -+#define SET_REG(r, mask, val) \ -+ W_REG((r), ((R_REG(r) & ~(mask)) | (val))) -+ -+/* multi-bool data type: set of bools, mbool is true if any is set */ -+ -+/* set one bool */ -+#define mboolset(mb, bit) ((mb) |= (bit)) -+/* clear one bool */ -+#define mboolclr(mb, bit) ((mb) &= ~(bit)) -+/* true if one bool is set */ -+#define mboolisset(mb, bit) (((mb) & (bit)) != 0) -+#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val))) -+ -+#define CEIL(x, y) (((x) + ((y)-1)) / (y)) -+ -+/* forward declarations */ -+struct wiphy; -+struct ieee80211_sta; -+struct ieee80211_tx_queue_params; -+struct brcms_info; -+struct brcms_c_info; -+struct brcms_hardware; -+struct brcms_txq_info; -+struct brcms_band; -+struct dma_pub; -+struct si_pub; -+struct tx_status; -+struct d11rxhdr; -+struct txpwr_limits; -+ -+/* iovar structure */ -+struct brcmu_iovar { -+ const char *name; /* name for lookup and display */ -+ u16 varid; /* id for switch */ -+ u16 flags; /* driver-specific flag bits */ -+ u16 type; /* base type of argument */ -+ u16 minlen; /* min length for buffer vars */ -+}; -+ -+/* brcm_msg_level is a bit vector with defs in defs.h */ -+extern u32 brcm_msg_level; -+ -+#endif /* _BRCM_TYPES_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.c.orig 2011-11-09 13:46:58.286800121 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.c 2011-11-09 13:47:17.045565604 -0500 -@@ -0,0 +1,109 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include "types.h" -+#include -+ -+enum { -+ D11UCODE_NAMETAG_START = 0, -+ D11LCN0BSINITVALS24, -+ D11LCN0INITVALS24, -+ D11LCN1BSINITVALS24, -+ D11LCN1INITVALS24, -+ D11LCN2BSINITVALS24, -+ D11LCN2INITVALS24, -+ D11N0ABSINITVALS16, -+ D11N0BSINITVALS16, -+ D11N0INITVALS16, -+ D11UCODE_OVERSIGHT16_MIMO, -+ D11UCODE_OVERSIGHT16_MIMOSZ, -+ D11UCODE_OVERSIGHT24_LCN, -+ D11UCODE_OVERSIGHT24_LCNSZ, -+ D11UCODE_OVERSIGHT_BOMMAJOR, -+ D11UCODE_OVERSIGHT_BOMMINOR -+}; -+ -+int brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode) -+{ -+ int rc; -+ -+ rc = brcms_check_firmwares(wl); -+ -+ rc = rc < 0 ? rc : -+ brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn0bsinitvals24, -+ D11LCN0BSINITVALS24); -+ rc = rc < 0 ? -+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn0initvals24, -+ D11LCN0INITVALS24); -+ rc = rc < 0 ? -+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn1bsinitvals24, -+ D11LCN1BSINITVALS24); -+ rc = rc < 0 ? -+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn1initvals24, -+ D11LCN1INITVALS24); -+ rc = rc < 0 ? rc : -+ brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn2bsinitvals24, -+ D11LCN2BSINITVALS24); -+ rc = rc < 0 ? -+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn2initvals24, -+ D11LCN2INITVALS24); -+ rc = rc < 0 ? -+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0absinitvals16, -+ D11N0ABSINITVALS16); -+ rc = rc < 0 ? -+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0bsinitvals16, -+ D11N0BSINITVALS16); -+ rc = rc < 0 ? -+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0initvals16, -+ D11N0INITVALS16); -+ rc = rc < 0 ? -+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_16_mimo, -+ D11UCODE_OVERSIGHT16_MIMO); -+ rc = rc < 0 ? -+ rc : brcms_ucode_init_uint(wl, &ucode->bcm43xx_16_mimosz, -+ D11UCODE_OVERSIGHT16_MIMOSZ); -+ rc = rc < 0 ? -+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_24_lcn, -+ D11UCODE_OVERSIGHT24_LCN); -+ rc = rc < 0 ? -+ rc : brcms_ucode_init_uint(wl, &ucode->bcm43xx_24_lcnsz, -+ D11UCODE_OVERSIGHT24_LCNSZ); -+ rc = rc < 0 ? -+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_bommajor, -+ D11UCODE_OVERSIGHT_BOMMAJOR); -+ rc = rc < 0 ? -+ rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_bomminor, -+ D11UCODE_OVERSIGHT_BOMMINOR); -+ return rc; -+} -+ -+void brcms_ucode_data_free(struct brcms_ucode *ucode) -+{ -+ brcms_ucode_free_buf((void *)ucode->d11lcn0bsinitvals24); -+ brcms_ucode_free_buf((void *)ucode->d11lcn0initvals24); -+ brcms_ucode_free_buf((void *)ucode->d11lcn1bsinitvals24); -+ brcms_ucode_free_buf((void *)ucode->d11lcn1initvals24); -+ brcms_ucode_free_buf((void *)ucode->d11lcn2bsinitvals24); -+ brcms_ucode_free_buf((void *)ucode->d11lcn2initvals24); -+ brcms_ucode_free_buf((void *)ucode->d11n0absinitvals16); -+ brcms_ucode_free_buf((void *)ucode->d11n0bsinitvals16); -+ brcms_ucode_free_buf((void *)ucode->d11n0initvals16); -+ brcms_ucode_free_buf((void *)ucode->bcm43xx_16_mimo); -+ brcms_ucode_free_buf((void *)ucode->bcm43xx_24_lcn); -+ brcms_ucode_free_buf((void *)ucode->bcm43xx_bommajor); -+ brcms_ucode_free_buf((void *)ucode->bcm43xx_bomminor); -+} -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h.orig 2011-11-09 13:46:58.287800109 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h 2011-11-09 13:47:17.046565592 -0500 -@@ -0,0 +1,58 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+#ifndef _BRCM_UCODE_H_ -+#define _BRCM_UCODE_H_ -+ -+#include "types.h" /* forward structure declarations */ -+ -+#define MIN_FW_SIZE 40000 /* minimum firmware file size in bytes */ -+#define MAX_FW_SIZE 150000 -+ -+#define UCODE_LOADER_API_VER 0 -+ -+struct d11init; -+ -+struct brcms_ucode { -+ struct d11init *d11lcn0bsinitvals24; -+ struct d11init *d11lcn0initvals24; -+ struct d11init *d11lcn1bsinitvals24; -+ struct d11init *d11lcn1initvals24; -+ struct d11init *d11lcn2bsinitvals24; -+ struct d11init *d11lcn2initvals24; -+ struct d11init *d11n0absinitvals16; -+ struct d11init *d11n0bsinitvals16; -+ struct d11init *d11n0initvals16; -+ __le32 *bcm43xx_16_mimo; -+ size_t bcm43xx_16_mimosz; -+ __le32 *bcm43xx_24_lcn; -+ size_t bcm43xx_24_lcnsz; -+ u32 *bcm43xx_bommajor; -+ u32 *bcm43xx_bomminor; -+}; -+ -+extern int -+brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode); -+ -+extern void brcms_ucode_data_free(struct brcms_ucode *ucode); -+ -+extern int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, -+ unsigned int idx); -+extern int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, -+ unsigned int idx); -+extern void brcms_ucode_free_buf(void *); -+extern int brcms_check_firmwares(struct brcms_info *wl); -+ -+#endif /* _BRCM_UCODE_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/Makefile.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/Makefile ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/Makefile.orig 2011-11-09 13:46:58.287800109 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/Makefile 2011-11-09 13:47:17.046565592 -0500 -@@ -0,0 +1,28 @@ -+# -+# Makefile fragment for Broadcom 802.11n Networking Device Driver Utilities -+# -+# Copyright (c) 2011 Broadcom Corporation -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ -+ccflags-y := \ -+ -Idrivers/net/wireless/brcm80211/brcmutil \ -+ -Idrivers/net/wireless/brcm80211/include -+ -+BRCMUTIL_OFILES := \ -+ utils.o -+ -+MODULEPFX := brcmutil -+ -+obj-$(CONFIG_BRCMUTIL) += $(MODULEPFX).o -+$(MODULEPFX)-objs = $(BRCMUTIL_OFILES) -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/utils.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/utils.c ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/utils.c.orig 2011-11-09 13:46:58.287800109 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/utils.c 2011-11-09 13:47:17.046565592 -0500 -@@ -0,0 +1,386 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+ -+MODULE_AUTHOR("Broadcom Corporation"); -+MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver utilities."); -+MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards"); -+MODULE_LICENSE("Dual BSD/GPL"); -+ -+struct sk_buff *brcmu_pkt_buf_get_skb(uint len) -+{ -+ struct sk_buff *skb; -+ -+ skb = dev_alloc_skb(len); -+ if (skb) { -+ skb_put(skb, len); -+ skb->priority = 0; -+ } -+ -+ return skb; -+} -+EXPORT_SYMBOL(brcmu_pkt_buf_get_skb); -+ -+/* Free the driver packet. Free the tag if present */ -+void brcmu_pkt_buf_free_skb(struct sk_buff *skb) -+{ -+ struct sk_buff *nskb; -+ int nest = 0; -+ -+ /* perversion: we use skb->next to chain multi-skb packets */ -+ while (skb) { -+ nskb = skb->next; -+ skb->next = NULL; -+ -+ if (skb->destructor) -+ /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if -+ * destructor exists -+ */ -+ dev_kfree_skb_any(skb); -+ else -+ /* can free immediately (even in_irq()) if destructor -+ * does not exist -+ */ -+ dev_kfree_skb(skb); -+ -+ nest++; -+ skb = nskb; -+ } -+} -+EXPORT_SYMBOL(brcmu_pkt_buf_free_skb); -+ -+ -+/* copy a buffer into a pkt buffer chain */ -+uint brcmu_pktfrombuf(struct sk_buff *p, uint offset, int len, -+ unsigned char *buf) -+{ -+ uint n, ret = 0; -+ -+ /* skip 'offset' bytes */ -+ for (; p && offset; p = p->next) { -+ if (offset < (uint) (p->len)) -+ break; -+ offset -= p->len; -+ } -+ -+ if (!p) -+ return 0; -+ -+ /* copy the data */ -+ for (; p && len; p = p->next) { -+ n = min((uint) (p->len) - offset, (uint) len); -+ memcpy(p->data + offset, buf, n); -+ buf += n; -+ len -= n; -+ ret += n; -+ offset = 0; -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL(brcmu_pktfrombuf); -+ -+/* return total length of buffer chain */ -+uint brcmu_pkttotlen(struct sk_buff *p) -+{ -+ uint total; -+ -+ total = 0; -+ for (; p; p = p->next) -+ total += p->len; -+ return total; -+} -+EXPORT_SYMBOL(brcmu_pkttotlen); -+ -+/* -+ * osl multiple-precedence packet queue -+ * hi_prec is always >= the number of the highest non-empty precedence -+ */ -+struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec, -+ struct sk_buff *p) -+{ -+ struct pktq_prec *q; -+ -+ if (pktq_full(pq) || pktq_pfull(pq, prec)) -+ return NULL; -+ -+ q = &pq->q[prec]; -+ -+ if (q->head) -+ q->tail->prev = p; -+ else -+ q->head = p; -+ -+ q->tail = p; -+ q->len++; -+ -+ pq->len++; -+ -+ if (pq->hi_prec < prec) -+ pq->hi_prec = (u8) prec; -+ -+ return p; -+} -+EXPORT_SYMBOL(brcmu_pktq_penq); -+ -+struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec, -+ struct sk_buff *p) -+{ -+ struct pktq_prec *q; -+ -+ if (pktq_full(pq) || pktq_pfull(pq, prec)) -+ return NULL; -+ -+ q = &pq->q[prec]; -+ -+ if (q->head == NULL) -+ q->tail = p; -+ -+ p->prev = q->head; -+ q->head = p; -+ q->len++; -+ -+ pq->len++; -+ -+ if (pq->hi_prec < prec) -+ pq->hi_prec = (u8) prec; -+ -+ return p; -+} -+EXPORT_SYMBOL(brcmu_pktq_penq_head); -+ -+struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec) -+{ -+ struct pktq_prec *q; -+ struct sk_buff *p; -+ -+ q = &pq->q[prec]; -+ -+ p = q->head; -+ if (p == NULL) -+ return NULL; -+ -+ q->head = p->prev; -+ if (q->head == NULL) -+ q->tail = NULL; -+ -+ q->len--; -+ -+ pq->len--; -+ -+ p->prev = NULL; -+ -+ return p; -+} -+EXPORT_SYMBOL(brcmu_pktq_pdeq); -+ -+struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec) -+{ -+ struct pktq_prec *q; -+ struct sk_buff *p, *prev; -+ -+ q = &pq->q[prec]; -+ -+ p = q->head; -+ if (p == NULL) -+ return NULL; -+ -+ for (prev = NULL; p != q->tail; p = p->prev) -+ prev = p; -+ -+ if (prev) -+ prev->prev = NULL; -+ else -+ q->head = NULL; -+ -+ q->tail = prev; -+ q->len--; -+ -+ pq->len--; -+ -+ return p; -+} -+EXPORT_SYMBOL(brcmu_pktq_pdeq_tail); -+ -+void -+brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir, -+ bool (*fn)(struct sk_buff *, void *), void *arg) -+{ -+ struct pktq_prec *q; -+ struct sk_buff *p, *prev = NULL; -+ -+ q = &pq->q[prec]; -+ p = q->head; -+ while (p) { -+ if (fn == NULL || (*fn) (p, arg)) { -+ bool head = (p == q->head); -+ if (head) -+ q->head = p->prev; -+ else -+ prev->prev = p->prev; -+ p->prev = NULL; -+ brcmu_pkt_buf_free_skb(p); -+ q->len--; -+ pq->len--; -+ p = (head ? q->head : prev->prev); -+ } else { -+ prev = p; -+ p = p->prev; -+ } -+ } -+ -+ if (q->head == NULL) -+ q->tail = NULL; -+} -+EXPORT_SYMBOL(brcmu_pktq_pflush); -+ -+void brcmu_pktq_flush(struct pktq *pq, bool dir, -+ bool (*fn)(struct sk_buff *, void *), void *arg) -+{ -+ int prec; -+ for (prec = 0; prec < pq->num_prec; prec++) -+ brcmu_pktq_pflush(pq, prec, dir, fn, arg); -+} -+EXPORT_SYMBOL(brcmu_pktq_flush); -+ -+void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len) -+{ -+ int prec; -+ -+ /* pq is variable size; only zero out what's requested */ -+ memset(pq, 0, -+ offsetof(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec)); -+ -+ pq->num_prec = (u16) num_prec; -+ -+ pq->max = (u16) max_len; -+ -+ for (prec = 0; prec < num_prec; prec++) -+ pq->q[prec].max = pq->max; -+} -+EXPORT_SYMBOL(brcmu_pktq_init); -+ -+struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out) -+{ -+ int prec; -+ -+ if (pq->len == 0) -+ return NULL; -+ -+ for (prec = 0; prec < pq->hi_prec; prec++) -+ if (pq->q[prec].head) -+ break; -+ -+ if (prec_out) -+ *prec_out = prec; -+ -+ return pq->q[prec].tail; -+} -+EXPORT_SYMBOL(brcmu_pktq_peek_tail); -+ -+/* Return sum of lengths of a specific set of precedences */ -+int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp) -+{ -+ int prec, len; -+ -+ len = 0; -+ -+ for (prec = 0; prec <= pq->hi_prec; prec++) -+ if (prec_bmp & (1 << prec)) -+ len += pq->q[prec].len; -+ -+ return len; -+} -+EXPORT_SYMBOL(brcmu_pktq_mlen); -+ -+/* Priority dequeue from a specific set of precedences */ -+struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, -+ int *prec_out) -+{ -+ struct pktq_prec *q; -+ struct sk_buff *p; -+ int prec; -+ -+ if (pq->len == 0) -+ return NULL; -+ -+ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) -+ pq->hi_prec--; -+ -+ while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) -+ if (prec-- == 0) -+ return NULL; -+ -+ q = &pq->q[prec]; -+ -+ p = q->head; -+ if (p == NULL) -+ return NULL; -+ -+ q->head = p->prev; -+ if (q->head == NULL) -+ q->tail = NULL; -+ -+ q->len--; -+ -+ if (prec_out) -+ *prec_out = prec; -+ -+ pq->len--; -+ -+ p->prev = NULL; -+ -+ return p; -+} -+EXPORT_SYMBOL(brcmu_pktq_mdeq); -+ -+#if defined(BCMDBG) -+/* pretty hex print a pkt buffer chain */ -+void brcmu_prpkt(const char *msg, struct sk_buff *p0) -+{ -+ struct sk_buff *p; -+ -+ if (msg && (msg[0] != '\0')) -+ printk(KERN_DEBUG "%s:\n", msg); -+ -+ for (p = p0; p; p = p->next) -+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, p->data, p->len); -+} -+EXPORT_SYMBOL(brcmu_prpkt); -+#endif /* defined(BCMDBG) */ -+ -+#if defined(BCMDBG) -+/* -+ * print bytes formatted as hex to a string. return the resulting -+ * string length -+ */ -+int brcmu_format_hex(char *str, const void *bytes, int len) -+{ -+ int i; -+ char *p = str; -+ const u8 *src = (const u8 *)bytes; -+ -+ for (i = 0; i < len; i++) { -+ p += snprintf(p, 3, "%02X", *src); -+ src++; -+ } -+ return (int)(p - str); -+} -+EXPORT_SYMBOL(brcmu_format_hex); -+#endif /* defined(BCMDBG) */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h.orig 2011-11-09 13:46:58.287800109 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h 2011-11-09 13:47:17.046565592 -0500 -@@ -0,0 +1,59 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_HW_IDS_H_ -+#define _BRCM_HW_IDS_H_ -+ -+#define BCM4325_D11DUAL_ID 0x431b -+#define BCM4325_D11G_ID 0x431c -+#define BCM4325_D11A_ID 0x431d -+ -+#define BCM4329_D11N2G_ID 0x432f /* 4329 802.11n 2.4G device */ -+#define BCM4329_D11N5G_ID 0x4330 /* 4329 802.11n 5G device */ -+#define BCM4329_D11NDUAL_ID 0x432e -+ -+#define BCM4319_D11N_ID 0x4337 /* 4319 802.11n dualband device */ -+#define BCM4319_D11N2G_ID 0x4338 /* 4319 802.11n 2.4G device */ -+#define BCM4319_D11N5G_ID 0x4339 /* 4319 802.11n 5G device */ -+ -+#define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */ -+#define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db */ -+ -+#define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */ -+ -+#define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */ -+#define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */ -+ -+#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ -+ -+/* Chip IDs */ -+#define BCM4313_CHIP_ID 0x4313 /* 4313 chip id */ -+#define BCM4319_CHIP_ID 0x4319 /* 4319 chip id */ -+ -+#define BCM43224_CHIP_ID 43224 /* 43224 chipcommon chipid */ -+#define BCM43225_CHIP_ID 43225 /* 43225 chipcommon chipid */ -+#define BCM43421_CHIP_ID 43421 /* 43421 chipcommon chipid */ -+#define BCM43235_CHIP_ID 43235 /* 43235 chipcommon chipid */ -+#define BCM43236_CHIP_ID 43236 /* 43236 chipcommon chipid */ -+#define BCM43238_CHIP_ID 43238 /* 43238 chipcommon chipid */ -+#define BCM4329_CHIP_ID 0x4329 /* 4329 chipcommon chipid */ -+#define BCM4325_CHIP_ID 0x4325 /* 4325 chipcommon chipid */ -+#define BCM4331_CHIP_ID 0x4331 /* 4331 chipcommon chipid */ -+#define BCM4336_CHIP_ID 0x4336 /* 4336 chipcommon chipid */ -+#define BCM4330_CHIP_ID 0x4330 /* 4330 chipcommon chipid */ -+#define BCM6362_CHIP_ID 0x6362 /* 6362 chipcommon chipid */ -+ -+#endif /* _BRCM_HW_IDS_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_utils.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_utils.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_utils.h.orig 2011-11-09 13:46:58.288800096 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_utils.h 2011-11-09 13:47:17.047565580 -0500 -@@ -0,0 +1,195 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCMU_UTILS_H_ -+#define _BRCMU_UTILS_H_ -+ -+#include -+ -+/* -+ * Spin at most 'us' microseconds while 'exp' is true. -+ * Caller should explicitly test 'exp' when this completes -+ * and take appropriate error action if 'exp' is still true. -+ */ -+#define SPINWAIT(exp, us) { \ -+ uint countdown = (us) + 9; \ -+ while ((exp) && (countdown >= 10)) {\ -+ udelay(10); \ -+ countdown -= 10; \ -+ } \ -+} -+ -+/* osl multi-precedence packet queue */ -+#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */ -+#define PKTQ_MAX_PREC 16 /* Maximum precedence levels */ -+ -+#define BCME_STRLEN 64 /* Max string length for BCM errors */ -+ -+/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */ -+#define PKTBUFSZ 2048 -+ -+#ifndef setbit -+#ifndef NBBY /* the BSD family defines NBBY */ -+#define NBBY 8 /* 8 bits per byte */ -+#endif /* #ifndef NBBY */ -+#define setbit(a, i) (((u8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY)) -+#define clrbit(a, i) (((u8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) -+#define isset(a, i) (((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) -+#define isclr(a, i) ((((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) -+#endif /* setbit */ -+ -+#define NBITS(type) (sizeof(type) * 8) -+#define NBITVAL(nbits) (1 << (nbits)) -+#define MAXBITVAL(nbits) ((1 << (nbits)) - 1) -+#define NBITMASK(nbits) MAXBITVAL(nbits) -+#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8) -+ -+/* crc defines */ -+#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */ -+#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */ -+ -+/* 18-bytes of Ethernet address buffer length */ -+#define ETHER_ADDR_STR_LEN 18 -+ -+struct pktq_prec { -+ struct sk_buff *head; /* first packet to dequeue */ -+ struct sk_buff *tail; /* last packet to dequeue */ -+ u16 len; /* number of queued packets */ -+ u16 max; /* maximum number of queued packets */ -+}; -+ -+/* multi-priority pkt queue */ -+struct pktq { -+ u16 num_prec; /* number of precedences in use */ -+ u16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */ -+ u16 max; /* total max packets */ -+ u16 len; /* total number of packets */ -+ /* -+ * q array must be last since # of elements can be either -+ * PKTQ_MAX_PREC or 1 -+ */ -+ struct pktq_prec q[PKTQ_MAX_PREC]; -+}; -+ -+/* operations on a specific precedence in packet queue */ -+ -+static inline int pktq_plen(struct pktq *pq, int prec) -+{ -+ return pq->q[prec].len; -+} -+ -+static inline int pktq_pavail(struct pktq *pq, int prec) -+{ -+ return pq->q[prec].max - pq->q[prec].len; -+} -+ -+static inline bool pktq_pfull(struct pktq *pq, int prec) -+{ -+ return pq->q[prec].len >= pq->q[prec].max; -+} -+ -+static inline bool pktq_pempty(struct pktq *pq, int prec) -+{ -+ return pq->q[prec].len == 0; -+} -+ -+static inline struct sk_buff *pktq_ppeek(struct pktq *pq, int prec) -+{ -+ return pq->q[prec].head; -+} -+ -+static inline struct sk_buff *pktq_ppeek_tail(struct pktq *pq, int prec) -+{ -+ return pq->q[prec].tail; -+} -+ -+extern struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec, -+ struct sk_buff *p); -+extern struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec, -+ struct sk_buff *p); -+extern struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec); -+extern struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec); -+ -+/* packet primitives */ -+extern struct sk_buff *brcmu_pkt_buf_get_skb(uint len); -+extern void brcmu_pkt_buf_free_skb(struct sk_buff *skb); -+ -+/* Empty the queue at particular precedence level */ -+/* callback function fn(pkt, arg) returns true if pkt belongs to if */ -+extern void brcmu_pktq_pflush(struct pktq *pq, int prec, -+ bool dir, bool (*fn)(struct sk_buff *, void *), void *arg); -+ -+/* operations on a set of precedences in packet queue */ -+ -+extern int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp); -+extern struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, -+ int *prec_out); -+ -+/* operations on packet queue as a whole */ -+ -+static inline int pktq_len(struct pktq *pq) -+{ -+ return (int)pq->len; -+} -+ -+static inline int pktq_max(struct pktq *pq) -+{ -+ return (int)pq->max; -+} -+ -+static inline int pktq_avail(struct pktq *pq) -+{ -+ return (int)(pq->max - pq->len); -+} -+ -+static inline bool pktq_full(struct pktq *pq) -+{ -+ return pq->len >= pq->max; -+} -+ -+static inline bool pktq_empty(struct pktq *pq) -+{ -+ return pq->len == 0; -+} -+ -+extern void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len); -+/* prec_out may be NULL if caller is not interested in return value */ -+extern struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out); -+extern void brcmu_pktq_flush(struct pktq *pq, bool dir, -+ bool (*fn)(struct sk_buff *, void *), void *arg); -+ -+/* externs */ -+/* packet */ -+extern uint brcmu_pktfrombuf(struct sk_buff *p, -+ uint offset, int len, unsigned char *buf); -+extern uint brcmu_pkttotlen(struct sk_buff *p); -+ -+/* ip address */ -+struct ipv4_addr; -+ -+#ifdef BCMDBG -+extern void brcmu_prpkt(const char *msg, struct sk_buff *p0); -+#else -+#define brcmu_prpkt(a, b) -+#endif /* BCMDBG */ -+ -+/* externs */ -+/* format/print */ -+#if defined(BCMDBG) -+extern int brcmu_format_hex(char *str, const void *bytes, int len); -+#endif -+ -+#endif /* _BRCMU_UTILS_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_wifi.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_wifi.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_wifi.h.orig 2011-11-09 13:46:58.288800096 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_wifi.h 2011-11-09 13:47:17.047565580 -0500 -@@ -0,0 +1,239 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCMU_WIFI_H_ -+#define _BRCMU_WIFI_H_ -+ -+#include /* for ETH_ALEN */ -+#include /* for WLAN_PMKID_LEN */ -+ -+/* -+ * A chanspec (u16) holds the channel number, band, bandwidth and control -+ * sideband -+ */ -+ -+/* channel defines */ -+#define CH_UPPER_SB 0x01 -+#define CH_LOWER_SB 0x02 -+#define CH_EWA_VALID 0x04 -+#define CH_20MHZ_APART 4 -+#define CH_10MHZ_APART 2 -+#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ -+#define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ -+#define BRCM_MAX_2G_CHANNEL CH_MAX_2G_CHANNEL /* legacy define */ -+ -+/* bandstate array indices */ -+#define BAND_2G_INDEX 0 /* wlc->bandstate[x] index */ -+#define BAND_5G_INDEX 1 /* wlc->bandstate[x] index */ -+ -+/* -+ * max # supported channels. The max channel no is 216, this is that + 1 -+ * rounded up to a multiple of NBBY (8). DO NOT MAKE it > 255: channels are -+ * u8's all over -+*/ -+#define MAXCHANNEL 224 -+ -+#define WL_CHANSPEC_CHAN_MASK 0x00ff -+#define WL_CHANSPEC_CHAN_SHIFT 0 -+ -+#define WL_CHANSPEC_CTL_SB_MASK 0x0300 -+#define WL_CHANSPEC_CTL_SB_SHIFT 8 -+#define WL_CHANSPEC_CTL_SB_LOWER 0x0100 -+#define WL_CHANSPEC_CTL_SB_UPPER 0x0200 -+#define WL_CHANSPEC_CTL_SB_NONE 0x0300 -+ -+#define WL_CHANSPEC_BW_MASK 0x0C00 -+#define WL_CHANSPEC_BW_SHIFT 10 -+#define WL_CHANSPEC_BW_10 0x0400 -+#define WL_CHANSPEC_BW_20 0x0800 -+#define WL_CHANSPEC_BW_40 0x0C00 -+ -+#define WL_CHANSPEC_BAND_MASK 0xf000 -+#define WL_CHANSPEC_BAND_SHIFT 12 -+#define WL_CHANSPEC_BAND_5G 0x1000 -+#define WL_CHANSPEC_BAND_2G 0x2000 -+#define INVCHANSPEC 255 -+ -+/* used to calculate the chan_freq = chan_factor * 500Mhz + 5 * chan_number */ -+#define WF_CHAN_FACTOR_2_4_G 4814 /* 2.4 GHz band, 2407 MHz */ -+#define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */ -+#define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */ -+ -+#define CHSPEC_CHANNEL(chspec) ((u8)((chspec) & WL_CHANSPEC_CHAN_MASK)) -+#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) -+ -+#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) -+#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) -+ -+#define CHSPEC_IS10(chspec) \ -+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) -+ -+#define CHSPEC_IS20(chspec) \ -+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) -+ -+#ifndef CHSPEC_IS40 -+#define CHSPEC_IS40(chspec) \ -+ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) -+#endif -+ -+#define CHSPEC_IS5G(chspec) \ -+ (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) -+ -+#define CHSPEC_IS2G(chspec) \ -+ (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) -+ -+#define CHSPEC_SB_NONE(chspec) \ -+ (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE) -+ -+#define CHSPEC_SB_UPPER(chspec) \ -+ (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) -+ -+#define CHSPEC_SB_LOWER(chspec) \ -+ (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) -+ -+#define CHSPEC_CTL_CHAN(chspec) \ -+ ((CHSPEC_SB_LOWER(chspec)) ? \ -+ (lower_20_sb(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \ -+ (upper_20_sb(((chspec) & WL_CHANSPEC_CHAN_MASK)))) -+ -+#define CHSPEC2BAND(chspec) (CHSPEC_IS5G(chspec) ? BRCM_BAND_5G : BRCM_BAND_2G) -+ -+#define CHANSPEC_STR_LEN 8 -+ -+static inline int lower_20_sb(int channel) -+{ -+ return channel > CH_10MHZ_APART ? (channel - CH_10MHZ_APART) : 0; -+} -+ -+static inline int upper_20_sb(int channel) -+{ -+ return (channel < (MAXCHANNEL - CH_10MHZ_APART)) ? -+ channel + CH_10MHZ_APART : 0; -+} -+ -+static inline int chspec_bandunit(u16 chspec) -+{ -+ return CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX; -+} -+ -+static inline u16 ch20mhz_chspec(int channel) -+{ -+ u16 rc = channel <= CH_MAX_2G_CHANNEL ? -+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G; -+ -+ return (u16)((u16)channel | WL_CHANSPEC_BW_20 | -+ WL_CHANSPEC_CTL_SB_NONE | rc); -+} -+ -+static inline int next_20mhz_chan(int channel) -+{ -+ return channel < (MAXCHANNEL - CH_20MHZ_APART) ? -+ channel + CH_20MHZ_APART : 0; -+} -+ -+/* defined rate in 500kbps */ -+#define BRCM_MAXRATE 108 /* in 500kbps units */ -+#define BRCM_RATE_1M 2 /* in 500kbps units */ -+#define BRCM_RATE_2M 4 /* in 500kbps units */ -+#define BRCM_RATE_5M5 11 /* in 500kbps units */ -+#define BRCM_RATE_11M 22 /* in 500kbps units */ -+#define BRCM_RATE_6M 12 /* in 500kbps units */ -+#define BRCM_RATE_9M 18 /* in 500kbps units */ -+#define BRCM_RATE_12M 24 /* in 500kbps units */ -+#define BRCM_RATE_18M 36 /* in 500kbps units */ -+#define BRCM_RATE_24M 48 /* in 500kbps units */ -+#define BRCM_RATE_36M 72 /* in 500kbps units */ -+#define BRCM_RATE_48M 96 /* in 500kbps units */ -+#define BRCM_RATE_54M 108 /* in 500kbps units */ -+ -+#define BRCM_2G_25MHZ_OFFSET 5 /* 2.4GHz band channel offset */ -+ -+#define MCSSET_LEN 16 -+ -+static inline bool ac_bitmap_tst(u8 bitmap, int prec) -+{ -+ return (bitmap & (1 << (prec))) != 0; -+} -+ -+/* Enumerate crypto algorithms */ -+#define CRYPTO_ALGO_OFF 0 -+#define CRYPTO_ALGO_WEP1 1 -+#define CRYPTO_ALGO_TKIP 2 -+#define CRYPTO_ALGO_WEP128 3 -+#define CRYPTO_ALGO_AES_CCM 4 -+#define CRYPTO_ALGO_AES_RESERVED1 5 -+#define CRYPTO_ALGO_AES_RESERVED2 6 -+#define CRYPTO_ALGO_NALG 7 -+ -+/* wireless security bitvec */ -+ -+#define WEP_ENABLED 0x0001 -+#define TKIP_ENABLED 0x0002 -+#define AES_ENABLED 0x0004 -+#define WSEC_SWFLAG 0x0008 -+/* to go into transition mode without setting wep */ -+#define SES_OW_ENABLED 0x0040 -+ -+/* WPA authentication mode bitvec */ -+#define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */ -+#define WPA_AUTH_NONE 0x0001 /* none (IBSS) */ -+#define WPA_AUTH_UNSPECIFIED 0x0002 /* over 802.1x */ -+#define WPA_AUTH_PSK 0x0004 /* Pre-shared key */ -+#define WPA_AUTH_RESERVED1 0x0008 -+#define WPA_AUTH_RESERVED2 0x0010 -+ -+#define WPA2_AUTH_RESERVED1 0x0020 -+#define WPA2_AUTH_UNSPECIFIED 0x0040 /* over 802.1x */ -+#define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */ -+#define WPA2_AUTH_RESERVED3 0x0200 -+#define WPA2_AUTH_RESERVED4 0x0400 -+#define WPA2_AUTH_RESERVED5 0x0800 -+ -+/* pmkid */ -+#define MAXPMKID 16 -+ -+#define DOT11_DEFAULT_RTS_LEN 2347 -+#define DOT11_DEFAULT_FRAG_LEN 2346 -+ -+#define DOT11_ICV_AES_LEN 8 -+#define DOT11_QOS_LEN 2 -+#define DOT11_IV_MAX_LEN 8 -+#define DOT11_A4_HDR_LEN 30 -+ -+#define HT_CAP_RX_STBC_NO 0x0 -+#define HT_CAP_RX_STBC_ONE_STREAM 0x1 -+ -+struct pmkid { -+ u8 BSSID[ETH_ALEN]; -+ u8 PMKID[WLAN_PMKID_LEN]; -+}; -+ -+struct pmkid_list { -+ __le32 npmkid; -+ struct pmkid pmkid[1]; -+}; -+ -+struct pmkid_cand { -+ u8 BSSID[ETH_ALEN]; -+ u8 preauth; -+}; -+ -+struct pmkid_cand_list { -+ u32 npmkid_cand; -+ struct pmkid_cand pmkid_cand[1]; -+}; -+ -+#endif /* _BRCMU_WIFI_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/chipcommon.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/chipcommon.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/chipcommon.h.orig 2011-11-09 13:46:58.288800096 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/chipcommon.h 2011-11-09 13:47:17.047565580 -0500 -@@ -0,0 +1,284 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _SBCHIPC_H -+#define _SBCHIPC_H -+ -+#include "defs.h" /* for PAD macro */ -+ -+struct chipcregs { -+ u32 chipid; /* 0x0 */ -+ u32 capabilities; -+ u32 corecontrol; /* corerev >= 1 */ -+ u32 bist; -+ -+ /* OTP */ -+ u32 otpstatus; /* 0x10, corerev >= 10 */ -+ u32 otpcontrol; -+ u32 otpprog; -+ u32 otplayout; /* corerev >= 23 */ -+ -+ /* Interrupt control */ -+ u32 intstatus; /* 0x20 */ -+ u32 intmask; -+ -+ /* Chip specific regs */ -+ u32 chipcontrol; /* 0x28, rev >= 11 */ -+ u32 chipstatus; /* 0x2c, rev >= 11 */ -+ -+ /* Jtag Master */ -+ u32 jtagcmd; /* 0x30, rev >= 10 */ -+ u32 jtagir; -+ u32 jtagdr; -+ u32 jtagctrl; -+ -+ /* serial flash interface registers */ -+ u32 flashcontrol; /* 0x40 */ -+ u32 flashaddress; -+ u32 flashdata; -+ u32 PAD[1]; -+ -+ /* Silicon backplane configuration broadcast control */ -+ u32 broadcastaddress; /* 0x50 */ -+ u32 broadcastdata; -+ -+ /* gpio - cleared only by power-on-reset */ -+ u32 gpiopullup; /* 0x58, corerev >= 20 */ -+ u32 gpiopulldown; /* 0x5c, corerev >= 20 */ -+ u32 gpioin; /* 0x60 */ -+ u32 gpioout; /* 0x64 */ -+ u32 gpioouten; /* 0x68 */ -+ u32 gpiocontrol; /* 0x6C */ -+ u32 gpiointpolarity; /* 0x70 */ -+ u32 gpiointmask; /* 0x74 */ -+ -+ /* GPIO events corerev >= 11 */ -+ u32 gpioevent; -+ u32 gpioeventintmask; -+ -+ /* Watchdog timer */ -+ u32 watchdog; /* 0x80 */ -+ -+ /* GPIO events corerev >= 11 */ -+ u32 gpioeventintpolarity; -+ -+ /* GPIO based LED powersave registers corerev >= 16 */ -+ u32 gpiotimerval; /* 0x88 */ -+ u32 gpiotimeroutmask; -+ -+ /* clock control */ -+ u32 clockcontrol_n; /* 0x90 */ -+ u32 clockcontrol_sb; /* aka m0 */ -+ u32 clockcontrol_pci; /* aka m1 */ -+ u32 clockcontrol_m2; /* mii/uart/mipsref */ -+ u32 clockcontrol_m3; /* cpu */ -+ u32 clkdiv; /* corerev >= 3 */ -+ u32 gpiodebugsel; /* corerev >= 28 */ -+ u32 capabilities_ext; /* 0xac */ -+ -+ /* pll delay registers (corerev >= 4) */ -+ u32 pll_on_delay; /* 0xb0 */ -+ u32 fref_sel_delay; -+ u32 slow_clk_ctl; /* 5 < corerev < 10 */ -+ u32 PAD; -+ -+ /* Instaclock registers (corerev >= 10) */ -+ u32 system_clk_ctl; /* 0xc0 */ -+ u32 clkstatestretch; -+ u32 PAD[2]; -+ -+ /* Indirect backplane access (corerev >= 22) */ -+ u32 bp_addrlow; /* 0xd0 */ -+ u32 bp_addrhigh; -+ u32 bp_data; -+ u32 PAD; -+ u32 bp_indaccess; -+ u32 PAD[3]; -+ -+ /* More clock dividers (corerev >= 32) */ -+ u32 clkdiv2; -+ u32 PAD[2]; -+ -+ /* In AI chips, pointer to erom */ -+ u32 eromptr; /* 0xfc */ -+ -+ /* ExtBus control registers (corerev >= 3) */ -+ u32 pcmcia_config; /* 0x100 */ -+ u32 pcmcia_memwait; -+ u32 pcmcia_attrwait; -+ u32 pcmcia_iowait; -+ u32 ide_config; -+ u32 ide_memwait; -+ u32 ide_attrwait; -+ u32 ide_iowait; -+ u32 prog_config; -+ u32 prog_waitcount; -+ u32 flash_config; -+ u32 flash_waitcount; -+ u32 SECI_config; /* 0x130 SECI configuration */ -+ u32 PAD[3]; -+ -+ /* Enhanced Coexistence Interface (ECI) registers (corerev >= 21) */ -+ u32 eci_output; /* 0x140 */ -+ u32 eci_control; -+ u32 eci_inputlo; -+ u32 eci_inputmi; -+ u32 eci_inputhi; -+ u32 eci_inputintpolaritylo; -+ u32 eci_inputintpolaritymi; -+ u32 eci_inputintpolarityhi; -+ u32 eci_intmasklo; -+ u32 eci_intmaskmi; -+ u32 eci_intmaskhi; -+ u32 eci_eventlo; -+ u32 eci_eventmi; -+ u32 eci_eventhi; -+ u32 eci_eventmasklo; -+ u32 eci_eventmaskmi; -+ u32 eci_eventmaskhi; -+ u32 PAD[3]; -+ -+ /* SROM interface (corerev >= 32) */ -+ u32 sromcontrol; /* 0x190 */ -+ u32 sromaddress; -+ u32 sromdata; -+ u32 PAD[17]; -+ -+ /* Clock control and hardware workarounds (corerev >= 20) */ -+ u32 clk_ctl_st; /* 0x1e0 */ -+ u32 hw_war; -+ u32 PAD[70]; -+ -+ /* UARTs */ -+ u8 uart0data; /* 0x300 */ -+ u8 uart0imr; -+ u8 uart0fcr; -+ u8 uart0lcr; -+ u8 uart0mcr; -+ u8 uart0lsr; -+ u8 uart0msr; -+ u8 uart0scratch; -+ u8 PAD[248]; /* corerev >= 1 */ -+ -+ u8 uart1data; /* 0x400 */ -+ u8 uart1imr; -+ u8 uart1fcr; -+ u8 uart1lcr; -+ u8 uart1mcr; -+ u8 uart1lsr; -+ u8 uart1msr; -+ u8 uart1scratch; -+ u32 PAD[126]; -+ -+ /* PMU registers (corerev >= 20) */ -+ u32 pmucontrol; /* 0x600 */ -+ u32 pmucapabilities; -+ u32 pmustatus; -+ u32 res_state; -+ u32 res_pending; -+ u32 pmutimer; -+ u32 min_res_mask; -+ u32 max_res_mask; -+ u32 res_table_sel; -+ u32 res_dep_mask; -+ u32 res_updn_timer; -+ u32 res_timer; -+ u32 clkstretch; -+ u32 pmuwatchdog; -+ u32 gpiosel; /* 0x638, rev >= 1 */ -+ u32 gpioenable; /* 0x63c, rev >= 1 */ -+ u32 res_req_timer_sel; -+ u32 res_req_timer; -+ u32 res_req_mask; -+ u32 PAD; -+ u32 chipcontrol_addr; /* 0x650 */ -+ u32 chipcontrol_data; /* 0x654 */ -+ u32 regcontrol_addr; -+ u32 regcontrol_data; -+ u32 pllcontrol_addr; -+ u32 pllcontrol_data; -+ u32 pmustrapopt; /* 0x668, corerev >= 28 */ -+ u32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ -+ u32 PAD[100]; -+ u16 sromotp[768]; -+}; -+ -+/* chipid */ -+#define CID_ID_MASK 0x0000ffff /* Chip Id mask */ -+#define CID_REV_MASK 0x000f0000 /* Chip Revision mask */ -+#define CID_REV_SHIFT 16 /* Chip Revision shift */ -+#define CID_PKG_MASK 0x00f00000 /* Package Option mask */ -+#define CID_PKG_SHIFT 20 /* Package Option shift */ -+#define CID_CC_MASK 0x0f000000 /* CoreCount (corerev >= 4) */ -+#define CID_CC_SHIFT 24 -+#define CID_TYPE_MASK 0xf0000000 /* Chip Type */ -+#define CID_TYPE_SHIFT 28 -+ -+/* capabilities */ -+#define CC_CAP_UARTS_MASK 0x00000003 /* Number of UARTs */ -+#define CC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ -+#define CC_CAP_UCLKSEL 0x00000018 /* UARTs clock select */ -+/* UARTs are driven by internal divided clock */ -+#define CC_CAP_UINTCLK 0x00000008 -+#define CC_CAP_UARTGPIO 0x00000020 /* UARTs own GPIOs 15:12 */ -+#define CC_CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */ -+#define CC_CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */ -+#define CC_CAP_EXTBUS_FULL 0x00000040 /* ExtBus: PCMCIA, IDE & Prog */ -+#define CC_CAP_EXTBUS_PROG 0x00000080 /* ExtBus: ProgIf only */ -+#define CC_CAP_FLASH_MASK 0x00000700 /* Type of flash */ -+#define CC_CAP_PLL_MASK 0x00038000 /* Type of PLL */ -+#define CC_CAP_PWR_CTL 0x00040000 /* Power control */ -+#define CC_CAP_OTPSIZE 0x00380000 /* OTP Size (0 = none) */ -+#define CC_CAP_OTPSIZE_SHIFT 19 /* OTP Size shift */ -+#define CC_CAP_OTPSIZE_BASE 5 /* OTP Size base */ -+#define CC_CAP_JTAGP 0x00400000 /* JTAG Master Present */ -+#define CC_CAP_ROM 0x00800000 /* Internal boot rom active */ -+#define CC_CAP_BKPLN64 0x08000000 /* 64-bit backplane */ -+#define CC_CAP_PMU 0x10000000 /* PMU Present, rev >= 20 */ -+#define CC_CAP_SROM 0x40000000 /* Srom Present, rev >= 32 */ -+/* Nand flash present, rev >= 35 */ -+#define CC_CAP_NFLASH 0x80000000 -+ -+#define CC_CAP2_SECI 0x00000001 /* SECI Present, rev >= 36 */ -+/* GSIO (spi/i2c) present, rev >= 37 */ -+#define CC_CAP2_GSIO 0x00000002 -+ -+/* pmucapabilities */ -+#define PCAP_REV_MASK 0x000000ff -+#define PCAP_RC_MASK 0x00001f00 -+#define PCAP_RC_SHIFT 8 -+#define PCAP_TC_MASK 0x0001e000 -+#define PCAP_TC_SHIFT 13 -+#define PCAP_PC_MASK 0x001e0000 -+#define PCAP_PC_SHIFT 17 -+#define PCAP_VC_MASK 0x01e00000 -+#define PCAP_VC_SHIFT 21 -+#define PCAP_CC_MASK 0x1e000000 -+#define PCAP_CC_SHIFT 25 -+#define PCAP5_PC_MASK 0x003e0000 /* PMU corerev >= 5 */ -+#define PCAP5_PC_SHIFT 17 -+#define PCAP5_VC_MASK 0x07c00000 -+#define PCAP5_VC_SHIFT 22 -+#define PCAP5_CC_MASK 0xf8000000 -+#define PCAP5_CC_SHIFT 27 -+ -+/* -+* Maximum delay for the PMU state transition in us. -+* This is an upper bound intended for spinwaits etc. -+*/ -+#define PMU_MAX_TRANSITION_DLY 15000 -+ -+#endif /* _SBCHIPC_H */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/defs.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/defs.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/defs.h.orig 2011-11-09 13:46:58.288800096 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/defs.h 2011-11-09 13:47:17.047565580 -0500 -@@ -0,0 +1,104 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_DEFS_H_ -+#define _BRCM_DEFS_H_ -+ -+#include -+ -+#define SI_BUS 0 -+#define PCI_BUS 1 -+#define PCMCIA_BUS 2 -+#define SDIO_BUS 3 -+#define JTAG_BUS 4 -+#define USB_BUS 5 -+#define SPI_BUS 6 -+ -+#define OFF 0 -+#define ON 1 /* ON = 1 */ -+#define AUTO (-1) /* Auto = -1 */ -+ -+/* -+ * Priority definitions according 802.1D -+ */ -+#define PRIO_8021D_NONE 2 -+#define PRIO_8021D_BK 1 -+#define PRIO_8021D_BE 0 -+#define PRIO_8021D_EE 3 -+#define PRIO_8021D_CL 4 -+#define PRIO_8021D_VI 5 -+#define PRIO_8021D_VO 6 -+#define PRIO_8021D_NC 7 -+ -+#define MAXPRIO 7 -+#define NUMPRIO (MAXPRIO + 1) -+ -+#define WL_NUMRATES 16 /* max # of rates in a rateset */ -+ -+#define BRCM_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NUL */ -+ -+#define BRCM_SET_CHANNEL 30 -+#define BRCM_SET_SRL 32 -+#define BRCM_SET_LRL 34 -+#define BRCM_SET_BCNPRD 76 -+ -+#define BRCM_GET_CURR_RATESET 114 /* current rateset */ -+#define BRCM_GET_PHYLIST 180 -+ -+/* Bit masks for radio disabled status - returned by WL_GET_RADIO */ -+ -+#define WL_RADIO_SW_DISABLE (1<<0) -+#define WL_RADIO_HW_DISABLE (1<<1) -+#define WL_RADIO_MPC_DISABLE (1<<2) -+/* some countries don't support any channel */ -+#define WL_RADIO_COUNTRY_DISABLE (1<<3) -+ -+/* Override bit for SET_TXPWR. if set, ignore other level limits */ -+#define WL_TXPWR_OVERRIDE (1U<<31) -+ -+/* band types */ -+#define BRCM_BAND_AUTO 0 /* auto-select */ -+#define BRCM_BAND_5G 1 /* 5 Ghz */ -+#define BRCM_BAND_2G 2 /* 2.4 Ghz */ -+#define BRCM_BAND_ALL 3 /* all bands */ -+ -+/* Values for PM */ -+#define PM_OFF 0 -+#define PM_MAX 1 -+ -+/* Message levels */ -+#define LOG_ERROR_VAL 0x00000001 -+#define LOG_TRACE_VAL 0x00000002 -+ -+#define PM_OFF 0 -+#define PM_MAX 1 -+#define PM_FAST 2 -+ -+/* -+ * Sonics Configuration Space Registers. -+ */ -+ -+/* core sbconfig regs are top 256bytes of regs */ -+#define SBCONFIGOFF 0xf00 -+ -+/* cpp contortions to concatenate w/arg prescan */ -+#ifndef PAD -+#define _PADLINE(line) pad ## line -+#define _XSTR(line) _PADLINE(line) -+#define PAD _XSTR(__LINE__) -+#endif -+ -+#endif /* _BRCM_DEFS_H_ */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/soc.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/soc.h ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/soc.h.orig 2011-11-09 13:46:58.288800096 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/soc.h 2011-11-09 13:47:17.048565567 -0500 -@@ -0,0 +1,90 @@ -+/* -+ * Copyright (c) 2010 Broadcom Corporation -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _BRCM_SOC_H -+#define _BRCM_SOC_H -+ -+#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */ -+ -+/* core codes */ -+#define NODEV_CORE_ID 0x700 /* Invalid coreid */ -+#define CC_CORE_ID 0x800 /* chipcommon core */ -+#define ILINE20_CORE_ID 0x801 /* iline20 core */ -+#define SRAM_CORE_ID 0x802 /* sram core */ -+#define SDRAM_CORE_ID 0x803 /* sdram core */ -+#define PCI_CORE_ID 0x804 /* pci core */ -+#define MIPS_CORE_ID 0x805 /* mips core */ -+#define ENET_CORE_ID 0x806 /* enet mac core */ -+#define CODEC_CORE_ID 0x807 /* v90 codec core */ -+#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */ -+#define ADSL_CORE_ID 0x809 /* ADSL core */ -+#define ILINE100_CORE_ID 0x80a /* iline100 core */ -+#define IPSEC_CORE_ID 0x80b /* ipsec core */ -+#define UTOPIA_CORE_ID 0x80c /* utopia core */ -+#define PCMCIA_CORE_ID 0x80d /* pcmcia core */ -+#define SOCRAM_CORE_ID 0x80e /* internal memory core */ -+#define MEMC_CORE_ID 0x80f /* memc sdram core */ -+#define OFDM_CORE_ID 0x810 /* OFDM phy core */ -+#define EXTIF_CORE_ID 0x811 /* external interface core */ -+#define D11_CORE_ID 0x812 /* 802.11 MAC core */ -+#define APHY_CORE_ID 0x813 /* 802.11a phy core */ -+#define BPHY_CORE_ID 0x814 /* 802.11b phy core */ -+#define GPHY_CORE_ID 0x815 /* 802.11g phy core */ -+#define MIPS33_CORE_ID 0x816 /* mips3302 core */ -+#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */ -+#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */ -+#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */ -+#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */ -+#define SDIOH_CORE_ID 0x81b /* sdio host core */ -+#define ROBO_CORE_ID 0x81c /* roboswitch core */ -+#define ATA100_CORE_ID 0x81d /* parallel ATA core */ -+#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */ -+#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */ -+#define PCIE_CORE_ID 0x820 /* pci express core */ -+#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */ -+#define SRAMC_CORE_ID 0x822 /* SRAM controller core */ -+#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */ -+#define ARM11_CORE_ID 0x824 /* ARM 1176 core */ -+#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */ -+#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */ -+#define PMU_CORE_ID 0x827 /* PMU core */ -+#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */ -+#define SDIOD_CORE_ID 0x829 /* SDIO device core */ -+#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */ -+#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */ -+#define MIPS74K_CORE_ID 0x82c /* mips 74k core */ -+#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ -+#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */ -+#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */ -+#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */ -+#define SC_CORE_ID 0x831 /* shared common core */ -+#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */ -+#define SPIH_CORE_ID 0x833 /* SPI host core */ -+#define I2S_CORE_ID 0x834 /* I2S core */ -+#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */ -+#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */ -+#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */ -+/* Default component, in ai chips it maps all unused address ranges */ -+#define DEF_AI_COMP 0xfff -+ -+/* Common core control flags */ -+#define SICF_BIST_EN 0x8000 -+#define SICF_PME_EN 0x4000 -+#define SICF_CORE_BITS 0x3ffc -+#define SICF_FGC 0x0002 -+#define SICF_CLOCK_EN 0x0001 -+ -+#endif /* _BRCM_SOC_H */ -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig 2011-11-09 13:46:58.289800083 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig 2011-11-09 13:47:17.048565567 -0500 -@@ -0,0 +1,35 @@ -+config BRCMUTIL -+ tristate -+ -+config BRCMSMAC -+ tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" -+ depends on PCI -+ depends on MAC80211 -+ depends on BCMA=n -+ select BRCMUTIL -+ select FW_LOADER -+ select CRC_CCITT -+ select CRC8 -+ select CORDIC -+ ---help--- -+ This module adds support for PCIe wireless adapters based on Broadcom -+ IEEE802.11n SoftMAC chipsets. If you choose to build a module, it'll -+ be called brcmsmac.ko. -+ -+config BRCMFMAC -+ tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver" -+ depends on MMC -+ depends on CFG80211 -+ select BRCMUTIL -+ select FW_LOADER -+ ---help--- -+ This module adds support for embedded wireless adapters based on -+ Broadcom IEEE802.11n FullMAC chipsets. This driver uses the kernel's -+ wireless extensions subsystem. If you choose to build a module, -+ it'll be called brcmfmac.ko. -+ -+config BRCMDBG -+ bool "Broadcom driver debug functions" -+ depends on BRCMSMAC || BRCMFMAC -+ ---help--- -+ Selecting this enables additional code for debug purposes. -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/Makefile.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/Makefile ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/Makefile.orig 2011-11-09 13:46:58.289800083 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/Makefile 2011-11-09 13:47:17.048565567 -0500 -@@ -0,0 +1,23 @@ -+# -+# Makefile fragment for Broadcom 802.11n Networking Device Driver -+# -+# Copyright (c) 2010 Broadcom Corporation -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ -+# common flags -+subdir-ccflags-$(CONFIG_BRCMDBG) += -DBCMDBG -+ -+obj-$(CONFIG_BRCMUTIL) += brcmutil/ -+obj-$(CONFIG_BRCMFMAC) += brcmfmac/ -+obj-$(CONFIG_BRCMSMAC) += brcmsmac/ -diff -up linux-3.1.x86_64/drivers/net/wireless/Kconfig.orig linux-3.1.x86_64/drivers/net/wireless/Kconfig ---- linux-3.1.x86_64/drivers/net/wireless/Kconfig.orig 2011-11-09 13:48:16.411823422 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/Kconfig 2011-11-09 13:48:24.808718444 -0500 -@@ -271,6 +271,7 @@ config MWL8K - source "drivers/net/wireless/ath/Kconfig" - source "drivers/net/wireless/b43/Kconfig" - source "drivers/net/wireless/b43legacy/Kconfig" -+source "drivers/net/wireless/brcm80211/Kconfig" - source "drivers/net/wireless/hostap/Kconfig" - source "drivers/net/wireless/ipw2x00/Kconfig" - source "drivers/net/wireless/iwlwifi/Kconfig" -diff -up linux-3.1.x86_64/drivers/net/wireless/Makefile.orig linux-3.1.x86_64/drivers/net/wireless/Makefile ---- linux-3.1.x86_64/drivers/net/wireless/Makefile.orig 2011-11-09 13:47:55.028090756 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/Makefile 2011-11-09 13:47:49.856155362 -0500 -@@ -58,3 +58,6 @@ obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl - obj-$(CONFIG_IWM) += iwmc3200wifi/ - - obj-$(CONFIG_MWIFIEX) += mwifiex/ -+ -+obj-$(CONFIG_BRCMFMAC) += brcm80211/ -+obj-$(CONFIG_BRCMSMAC) += brcm80211/ -diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig -index 06c9081..e2c3532 100644 ---- a/drivers/staging/Kconfig -+++ b/drivers/staging/Kconfig -@@ -44,8 +44,6 @@ source "drivers/staging/wlan-ng/Kconfig" - - source "drivers/staging/echo/Kconfig" - --source "drivers/staging/brcm80211/Kconfig" -- - source "drivers/staging/comedi/Kconfig" - - source "drivers/staging/olpc_dcon/Kconfig" -diff --git a/drivers/staging/brcm80211/Kconfig b/drivers/staging/brcm80211/Kconfig -deleted file mode 100644 -index 379cf16..0000000 ---- a/drivers/staging/brcm80211/Kconfig -+++ /dev/null -@@ -1,40 +0,0 @@ --config BRCMUTIL -- tristate -- default n -- --config BRCMSMAC -- tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" -- default n -- depends on PCI -- depends on WLAN && MAC80211 -- depends on X86 || MIPS -- select BRCMUTIL -- select FW_LOADER -- select CRC_CCITT -- ---help--- -- This module adds support for PCIe wireless adapters based on Broadcom -- IEEE802.11n SoftMAC chipsets. If you choose to build a module, it'll -- be called brcmsmac.ko. -- --config BRCMFMAC -- tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver" -- default n -- depends on MMC -- depends on WLAN && CFG80211 -- depends on X86 || MIPS -- select BRCMUTIL -- select FW_LOADER -- select WIRELESS_EXT -- select WEXT_PRIV -- ---help--- -- This module adds support for embedded wireless adapters based on -- Broadcom IEEE802.11n FullMAC chipsets. This driver uses the kernel's -- wireless extensions subsystem. If you choose to build a module, -- it'll be called brcmfmac.ko. -- --config BRCMDBG -- bool "Broadcom driver debug functions" -- default n -- depends on BRCMSMAC || BRCMFMAC -- ---help--- -- Selecting this enables additional code for debug purposes. -diff --git a/drivers/staging/brcm80211/Makefile b/drivers/staging/brcm80211/Makefile -deleted file mode 100644 -index 8b01f5e..0000000 ---- a/drivers/staging/brcm80211/Makefile -+++ /dev/null -@@ -1,24 +0,0 @@ --# --# Makefile fragment for Broadcom 802.11n Networking Device Driver --# --# Copyright (c) 2010 Broadcom Corporation --# --# Permission to use, copy, modify, and/or distribute this software for any --# purpose with or without fee is hereby granted, provided that the above --# copyright notice and this permission notice appear in all copies. --# --# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES --# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF --# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY --# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES --# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION --# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN --# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -- --# common flags --subdir-ccflags-y := -DBCMDMA32 --subdir-ccflags-$(CONFIG_BRCMDBG) += -DBCMDBG -- --obj-$(CONFIG_BRCMUTIL) += brcmutil/ --obj-$(CONFIG_BRCMFMAC) += brcmfmac/ --obj-$(CONFIG_BRCMSMAC) += brcmsmac/ -diff --git a/drivers/staging/brcm80211/brcmfmac/Makefile b/drivers/staging/brcm80211/brcmfmac/Makefile -deleted file mode 100644 -index da3c805..0000000 ---- a/drivers/staging/brcm80211/brcmfmac/Makefile -+++ /dev/null -@@ -1,39 +0,0 @@ --# --# Makefile fragment for Broadcom 802.11n Networking Device Driver --# --# Copyright (c) 2010 Broadcom Corporation --# --# Permission to use, copy, modify, and/or distribute this software for any --# purpose with or without fee is hereby granted, provided that the above --# copyright notice and this permission notice appear in all copies. --# --# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES --# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF --# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY --# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES --# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION --# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN --# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -- --ccflags-y := \ -- -DBRCMF_FIRSTREAD=64 \ -- -DBRCMF_SDALIGN=64 \ -- -DMAX_HDR_READ=64 -- --ccflags-$(CONFIG_BRCMDBG) += -DSHOW_EVENTS -- --ccflags-y += \ -- -Idrivers/staging/brcm80211/brcmfmac \ -- -Idrivers/staging/brcm80211/include -- --DHDOFILES = \ -- wl_cfg80211.o \ -- dhd_cdc.o \ -- dhd_common.o \ -- dhd_sdio.o \ -- dhd_linux.o \ -- bcmsdh.o \ -- bcmsdh_sdmmc.o -- --obj-$(CONFIG_BRCMFMAC) += brcmfmac.o --brcmfmac-objs += $(DHDOFILES) -diff --git a/drivers/staging/brcm80211/brcmsmac/Makefile b/drivers/staging/brcm80211/brcmsmac/Makefile -deleted file mode 100644 -index 1ea3e0c..0000000 ---- a/drivers/staging/brcm80211/brcmsmac/Makefile -+++ /dev/null -@@ -1,58 +0,0 @@ --# --# Makefile fragment for Broadcom 802.11n Networking Device Driver --# --# Copyright (c) 2010 Broadcom Corporation --# --# Permission to use, copy, modify, and/or distribute this software for any --# purpose with or without fee is hereby granted, provided that the above --# copyright notice and this permission notice appear in all copies. --# --# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES --# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF --# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY --# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES --# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION --# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN --# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -- --ccflags-y := \ -- -DWLC_HIGH \ -- -DWLC_LOW \ -- -DSTA \ -- -DWME \ -- -DWL11N \ -- -DDBAND \ -- -DBCMNVRAMR \ -- -Idrivers/staging/brcm80211/brcmsmac \ -- -Idrivers/staging/brcm80211/brcmsmac/phy \ -- -Idrivers/staging/brcm80211/include -- --BRCMSMAC_OFILES := \ -- mac80211_if.o \ -- ucode_loader.o \ -- alloc.o \ -- ampdu.o \ -- antsel.o \ -- bmac.o \ -- channel.o \ -- main.o \ -- phy_shim.o \ -- pmu.o \ -- rate.o \ -- stf.o \ -- aiutils.o \ -- phy/phy_cmn.o \ -- phy/phy_lcn.o \ -- phy/phy_n.o \ -- phy/phytbl_lcn.o \ -- phy/phytbl_n.o \ -- phy/phy_qmath.o \ -- otp.o \ -- srom.o \ -- dma.o \ -- nicpci.o -- --MODULEPFX := brcmsmac -- --obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o --$(MODULEPFX)-objs = $(BRCMSMAC_OFILES) -diff --git a/drivers/staging/brcm80211/brcmutil/Makefile b/drivers/staging/brcm80211/brcmutil/Makefile -deleted file mode 100644 -index 6403423..0000000 ---- a/drivers/staging/brcm80211/brcmutil/Makefile -+++ /dev/null -@@ -1,29 +0,0 @@ --# --# Makefile fragment for Broadcom 802.11n Networking Device Driver Utilities --# --# Copyright (c) 2011 Broadcom Corporation --# --# Permission to use, copy, modify, and/or distribute this software for any --# purpose with or without fee is hereby granted, provided that the above --# copyright notice and this permission notice appear in all copies. --# --# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES --# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF --# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY --# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES --# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION --# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN --# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -- --ccflags-y := \ -- -Idrivers/staging/brcm80211/brcmutil \ -- -Idrivers/staging/brcm80211/include -- --BRCMUTIL_OFILES := \ -- utils.o \ -- wifi.o -- --MODULEPFX := brcmutil -- --obj-$(CONFIG_BRCMUTIL) += $(MODULEPFX).o --$(MODULEPFX)-objs = $(BRCMUTIL_OFILES) --- -diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile -index f3c5e33..f2c2209 100644 ---- a/drivers/staging/Makefile -+++ b/drivers/staging/Makefile -@@ -14,8 +14,6 @@ obj-$(CONFIG_USBIP_CORE) += usbip/ - obj-$(CONFIG_W35UND) += winbond/ - obj-$(CONFIG_PRISM2_USB) += wlan-ng/ - obj-$(CONFIG_ECHO) += echo/ --obj-$(CONFIG_BRCMSMAC) += brcm80211/ --obj-$(CONFIG_BRCMFMAC) += brcm80211/ - obj-$(CONFIG_COMEDI) += comedi/ - obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/ - obj-$(CONFIG_ASUS_OLED) += asus_oled/ diff --git a/cciss-fix-irqf-shared.patch b/cciss-fix-irqf-shared.patch deleted file mode 100644 index d6de3d7c2..000000000 --- a/cciss-fix-irqf-shared.patch +++ /dev/null @@ -1,39 +0,0 @@ -cciss: Add IRQF_SHARED back in for the non-MSI(X) interrupt handler - -From: Stephen M. Cameron - -[ 3.1.x backport ] - -IRQF_SHARED is required for older controllers that don't support MSI(X) -and which may end up sharing an interrupt. - -Also remove deprecated IRQF_DISABLED. - -Signed-off-by: Stephen M. Cameron ---- - drivers/block/cciss.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -RHBZ 754907 -diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c -index 8004ac3..6f22ed0 100644 ---- a/drivers/block/cciss.c -+++ b/drivers/block/cciss.c -@@ -4880,7 +4880,7 @@ static int cciss_request_irq(ctlr_info_t *h, - { - if (h->msix_vector || h->msi_vector) { - if (!request_irq(h->intr[PERF_MODE_INT], msixhandler, -- IRQF_DISABLED, h->devname, h)) -+ 0, h->devname, h)) - return 0; - dev_err(&h->pdev->dev, "Unable to get msi irq %d" - " for %s\n", h->intr[h->intr_mode], -@@ -4889,7 +4889,7 @@ static int cciss_request_irq(ctlr_info_t *h, - } - - if (!request_irq(h->intr[PERF_MODE_INT], intxhandler, -- IRQF_DISABLED, h->devname, h)) -+ IRQF_SHARED, h->devname, h)) - return 0; - dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n", - h->intr[h->intr_mode], h->devname); diff --git a/config-arm-generic b/config-arm-generic index 3141e66a5..558c7c4d0 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -152,6 +152,11 @@ CONFIG_MMC_SDHCI_OF=m CONFIG_MMC_SDHCI_PXAV3=m CONFIG_MMC_SDHCI_PXAV2=m +CONFIG_ARM_APPENDED_DTB=y +CONFIG_MTD_OF_PARTS=y +CONFIG_PL330_DMA=y +# CONFIG_ARM_KPROBES_TEST is not set +# CONFIG_ARM_ATAG_DTB_COMPAT is not set # CONFIG_FTGMAC100 is not set # CONFIG_FTMAC100 is not set @@ -180,3 +185,12 @@ CONFIG_LSM_MMAP_MIN_ADDR=32768 # CONFIG_SND_ALI5451 is not set # CONFIG_DRM_NOUVEAU is not set # CONFIG_MLX4_EN is not set + +# FIXME: Guesses, need checking +# CONFIG_MACH_EUKREA_CPUIMX35SD is not set +CONFIG_ARM_ERRATA_720789=y +CONFIG_ARM_ERRATA_751472=y +# CONFIG_FB_MX3 is not set +# CONFIG_MX3_IPU is not set +# CONFIG_MX3_IPU_IRQS is not set + diff --git a/config-arm-imx b/config-arm-imx index 5ed7ae2ed..2dbe10a1f 100644 --- a/config-arm-imx +++ b/config-arm-imx @@ -93,3 +93,6 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m CONFIG_CPU_FREQ_TABLE=y CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y + +CONFIG_PL310_ERRATA_769419=y +CONFIG_LEDS_RENESAS_TPU=y diff --git a/config-arm-omap-generic b/config-arm-omap-generic index 03913d36d..d623e1817 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -1061,3 +1061,25 @@ CONFIG_LIBCRC32C=y CONFIG_CRYSTALHD=m CONFIG_GPIO_GENERIC_PLATFORM=y + +CONFIG_MACH_OMAP_GENERIC=y +CONFIG_PL310_ERRATA_753970=y +CONFIG_ARM_CPU_TOPOLOGY=y +CONFIG_SCHED_MC=y +CONFIG_SCHED_SMT=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_BROADCOM=y +CONFIG_NET_VENDOR_MICROCHIP=y +CONFIG_SENSORS_AD7314=m +CONFIG_REGULATOR_GPIO=y +CONFIG_VIDEO_MT9P031=m +CONFIG_VIDEO_MT9T001=m +CONFIG_VIDEO_S5K6AA=m +CONFIG_PANEL_DVI=m +CONFIG_PANEL_PICODLP=m +CONFIG_USB_RENESAS_USBHS=m +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +CONFIG_LEDS_RENESAS_TPU=y +# CONFIG_OMAP_IOMMU is not set +CONFIG_USB_RENESAS_USBHS_HCD=m + diff --git a/config-arm-tegra b/config-arm-tegra index b131978d2..495e91e65 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -83,3 +83,10 @@ CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_CRYSTALHD=m + +CONFIG_MACH_VENTANA=y +CONFIG_PL310_ERRATA_753970=y +CONFIG_ARM_CPU_TOPOLOGY=y +CONFIG_SCHED_MC=y +CONFIG_SCHED_SMT=y +CONFIG_LEDS_RENESAS_TPU=y diff --git a/config-debug b/config-debug index a25239038..19ae4656f 100644 --- a/config-debug +++ b/config-debug @@ -24,6 +24,7 @@ CONFIG_FAIL_MAKE_REQUEST=y CONFIG_FAULT_INJECTION_DEBUG_FS=y CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y CONFIG_FAIL_IO_TIMEOUT=y +CONFIG_FAIL_MMC_REQUEST=y CONFIG_SLUB_DEBUG_ON=y @@ -81,7 +82,6 @@ CONFIG_CARL9170_DEBUGFS=y CONFIG_IWLWIFI_DEVICE_TRACING=y CONFIG_DEBUG_OBJECTS_WORK=y -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set CONFIG_DMADEVICES_DEBUG=y CONFIG_DMADEVICES_VDEBUG=y @@ -99,9 +99,8 @@ CONFIG_KDB_KEYBOARD=y CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y CONFIG_TEST_LIST_SORT=y -CONFIG_DEBUG_SET_MODULE_RONX=y - CONFIG_DETECT_HUNG_TASK=y CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y diff --git a/config-generic b/config-generic index a459ec6f3..bd2c47654 100644 --- a/config-generic +++ b/config-generic @@ -32,7 +32,7 @@ CONFIG_KERNEL_GZIP=y CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_BSD_PROCESS_ACCT=y -# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_FHANDLE=y CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y @@ -68,6 +68,7 @@ CONFIG_SLUB=y CONFIG_MISC_DEVICES=y # CONFIG_AD525X_DPOT is not set +# CONFIG_ATMEL_PWM is not set CONFIG_IWMC3200TOP=m # CONFIG_IWMC3200TOP_DEBUG is not set CONFIG_IWMC3200TOP_DEBUGFS=y @@ -80,7 +81,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_LOAD is not set # -- MODULE_FORCE_UNLOAD is controlled by config-debug/nodebug # CONFIG_MODVERSIONS is not set -CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_MODULE_SRCVERSION_ALL is not set # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) @@ -89,6 +90,8 @@ CONFIG_PCI=y # CONFIG_PCI_DEBUG is not set CONFIG_PCI_STUB=y CONFIG_PCI_IOV=y +CONFIG_PCI_PRI=y +CONFIG_PCI_PASID=y CONFIG_HT_IRQ=y CONFIG_PCI_MSI=y CONFIG_PCIEPORTBUS=y @@ -157,6 +160,7 @@ CONFIG_INFINIBAND_AMSO1100=m # CONFIG_INFINIBAND_AMSO1100_DEBUG is not set CONFIG_INFINIBAND_CXGB3=m CONFIG_INFINIBAND_CXGB4=m +CONFIG_SCSI_CXGB3_ISCSI=m CONFIG_SCSI_CXGB4_ISCSI=m # CONFIG_INFINIBAND_CXGB3_DEBUG is not set CONFIG_MLX4_INFINIBAND=m @@ -170,7 +174,7 @@ CONFIG_INFINIBAND_QIB=m CONFIG_BINFMT_ELF=y CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y # CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_MISC=y +CONFIG_BINFMT_MISC=m # # Device Drivers @@ -273,6 +277,7 @@ CONFIG_MTDRAM_ERASE_SIZE=128 # CONFIG_MTD_DOCPROBE is not set # CONFIG_MTD_DOCPROBE_ADVANCED is not set # CONFIG_MTD_DOCPROBE_ADDRESS is not set +# CONFIG_MTD_DOCG3 is not set # # NAND Flash Device Drivers @@ -351,13 +356,14 @@ CONFIG_BLK_CPQ_DA=m CONFIG_BLK_CPQ_CISS_DA=m CONFIG_CISS_SCSI_TAPE=y CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_DRBD=m CONFIG_BLK_DEV_UMEM=m CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_OSD=m -CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM=m CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_BLK_DEV_INITRD=y @@ -432,6 +438,7 @@ CONFIG_BLK_DEV_IDEDMA=y CONFIG_VIRTIO_BLK=m CONFIG_VIRTIO_PCI=y CONFIG_VIRTIO_BALLOON=m +CONFIG_VIRTIO_MMIO=m CONFIG_VIRTIO_NET=m CONFIG_VMXNET3=m CONFIG_HW_RANDOM_VIRTIO=m @@ -498,15 +505,13 @@ CONFIG_SCSI_3W_9XXX=m CONFIG_SCSI_ACARD=m CONFIG_SCSI_AACRAID=m CONFIG_SCSI_AIC7XXX=m -CONFIG_SCSI_AIC94XX=m -# CONFIG_AIC94XX_DEBUG is not set +CONFIG_SCSI_AIC7XXX_OLD=m CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 CONFIG_AIC7XXX_RESET_DELAY_MS=15000 # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set # CONFIG_AIC7XXX_DEBUG_ENABLE is not set CONFIG_AIC7XXX_DEBUG_MASK=0 # CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC7XXX_OLD=m CONFIG_SCSI_AIC79XX=m CONFIG_AIC79XX_CMDS_PER_DEVICE=4 CONFIG_AIC79XX_RESET_DELAY_MS=15000 @@ -514,6 +519,8 @@ CONFIG_AIC79XX_RESET_DELAY_MS=15000 # CONFIG_AIC79XX_DEBUG_ENABLE is not set CONFIG_AIC79XX_DEBUG_MASK=0 # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC94XX=m +# CONFIG_AIC94XX_DEBUG is not set # CONFIG_SCSI_ADVANSYS is not set CONFIG_SCSI_BFA_FC=m CONFIG_MEGARAID_NEWGEN=y @@ -528,6 +535,8 @@ CONFIG_SCSI_MPT2SAS=m CONFIG_SCSI_MPT2SAS_MAX_SGE=128 CONFIG_SCSI_MPT2SAS_LOGGING=y +CONFIG_SCSI_MVUMI=m + CONFIG_SCSI_OSD_INITIATOR=m CONFIG_SCSI_OSD_ULD=m CONFIG_SCSI_OSD_DPRINT_SENSE=1 @@ -543,6 +552,59 @@ CONFIG_SCSI_PM8001=m CONFIG_VMWARE_PVSCSI=m CONFIG_VMWARE_BALLOON=m +CONFIG_SCSI_ARCMSR=m +CONFIG_SCSI_BUSLOGIC=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_FLASHPOINT=y +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INIA100=m +# CONFIG_SCSI_PPA is not set +# CONFIG_SCSI_IMM is not set +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_STEX=m +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_DC395x=m +# CONFIG_SCSI_NSP32 is not set +CONFIG_SCSI_DEBUG=m +CONFIG_SCSI_DC390T=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_QLA_ISCSI=m +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_DPT_I2O is not set +CONFIG_SCSI_LPFC=m +# CONFIG_SCSI_LPFC_DEBUG_FS is not set + +# PCMCIA SCSI adapter support +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set + +# ISA SCSI Controllers. Sorry your life sucks. +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set + + CONFIG_ATA=y CONFIG_ATA_BMDMA=y CONFIG_ATA_VERBOSE_ERROR=y @@ -622,48 +684,6 @@ CONFIG_PATA_VIA=m CONFIG_PATA_WINBOND=m CONFIG_PATA_ATP867X=m -CONFIG_SCSI_BUSLOGIC=m -CONFIG_SCSI_INITIO=m -CONFIG_SCSI_FLASHPOINT=y -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -CONFIG_SCSI_GDTH=m -CONFIG_SCSI_HPTIOP=m -CONFIG_SCSI_IPS=m -CONFIG_SCSI_INIA100=m -CONFIG_SCSI_PPA=m -CONFIG_SCSI_IMM=m -# CONFIG_SCSI_IZIP_EPP16 is not set -# CONFIG_SCSI_IZIP_SLOW_CTR is not set -CONFIG_SCSI_STEX=m -CONFIG_SCSI_SYM53C8XX_2=m -CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 -CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 -CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -CONFIG_SCSI_SYM53C8XX_MMIO=y -CONFIG_SCSI_QLOGIC_1280=m -CONFIG_SCSI_DC395x=m -# CONFIG_SCSI_NSP32 is not set -CONFIG_SCSI_DEBUG=m -CONFIG_SCSI_DC390T=m -CONFIG_SCSI_QLA_FC=m -CONFIG_SCSI_QLA_ISCSI=m -# CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_DPT_I2O is not set -CONFIG_SCSI_LPFC=m - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_LOWLEVEL_PCMCIA=y -CONFIG_PCMCIA_AHA152X=m -# CONFIG_PCMCIA_FDOMAIN is not set -CONFIG_PCMCIA_NINJA_SCSI=m -CONFIG_PCMCIA_QLOGIC=m -CONFIG_PCMCIA_SYM53C500=m - # # Multi-device support (RAID and LVM) @@ -687,6 +707,9 @@ CONFIG_DM_DEBUG=y CONFIG_DM_MIRROR=y CONFIG_DM_MULTIPATH=m CONFIG_DM_SNAPSHOT=y +CONFIG_DM_THIN_PROVISIONING=m +# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set +# CONFIG_DM_DEBUG_SPACE_MAPS is not set CONFIG_DM_UEVENT=y CONFIG_DM_ZERO=y CONFIG_DM_LOG_USERSPACE=m @@ -737,6 +760,8 @@ CONFIG_FIREWIRE_NOSY=m # CONFIG_NET=y +CONFIG_NET_DMA=y + CONFIG_TCP_CONG_ADVANCED=y CONFIG_TCP_CONG_BIC=m CONFIG_TCP_CONG_CUBIC=y @@ -801,6 +826,7 @@ CONFIG_IP_VS_PROTO_UDP=y CONFIG_IP_VS_PROTO_ESP=y CONFIG_IP_VS_PROTO_AH=y CONFIG_IP_VS_PROTO_SCTP=y +CONFIG_IP_VS_IPV6=y CONFIG_IP_VS_RR=m CONFIG_IP_VS_WRR=m CONFIG_IP_VS_LC=m @@ -814,7 +840,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 @@ -845,21 +871,31 @@ CONFIG_NET_9P_RDMA=m # CONFIG_DECNET is not set CONFIG_BRIDGE=m CONFIG_BRIDGE_IGMP_SNOOPING=y + +# PHY timestamping adds overhead # CONFIG_NETWORK_PHY_TIMESTAMPING is not set + CONFIG_NETFILTER=y CONFIG_NETFILTER_ADVANCED=y CONFIG_NF_CONNTRACK=m CONFIG_NETFILTER_NETLINK=m CONFIG_NETFILTER_NETLINK_QUEUE=m CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_TPROXY=m CONFIG_NETFILTER_XTABLES=y CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_MARK=m CONFIG_NETFILTER_XT_CONNMARK=m + +CONFIG_NETFILTER_XT_TARGET_AUDIT=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m CONFIG_NETFILTER_XT_TARGET_CONNMARK=m CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m CONFIG_NETFILTER_XT_TARGET_MARK=m CONFIG_NETFILTER_XT_TARGET_NFLOG=m CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m @@ -870,24 +906,31 @@ CONFIG_NETFILTER_XT_TARGET_TCPMSS=m CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER_XT_TARGET_TEE=m -CONFIG_NETFILTER_XT_TARGET_LED=m -CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m + +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CPU=m CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m CONFIG_NETFILTER_XT_MATCH_CONNMARK=m CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m CONFIG_NETFILTER_XT_MATCH_DSCP=m CONFIG_NETFILTER_XT_MATCH_ESP=m CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m CONFIG_NETFILTER_XT_MATCH_LENGTH=m CONFIG_NETFILTER_XT_MATCH_LIMIT=m CONFIG_NETFILTER_XT_MATCH_MAC=m CONFIG_NETFILTER_XT_MATCH_MARK=m CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m CONFIG_NETFILTER_XT_MATCH_OWNER=m CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m @@ -895,23 +938,15 @@ CONFIG_NETFILTER_XT_MATCH_POLICY=m CONFIG_NETFILTER_XT_MATCH_QUOTA=m CONFIG_NETFILTER_XT_MATCH_RATEEST=m CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m CONFIG_NETFILTER_XT_MATCH_STATE=y CONFIG_NETFILTER_XT_MATCH_STATISTIC=m CONFIG_NETFILTER_XT_MATCH_STRING=m CONFIG_NETFILTER_XT_MATCH_TCPMSS=m CONFIG_NETFILTER_XT_MATCH_TIME=m CONFIG_NETFILTER_XT_MATCH_U32=m -CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -CONFIG_NETFILTER_XT_MATCH_HL=m -CONFIG_NETFILTER_XT_MATCH_OSF=m -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 @@ -1058,7 +1093,7 @@ CONFIG_LLC=m CONFIG_IPX=m # CONFIG_IPX_INTERN is not set CONFIG_ATALK=m -CONFIG_DEV_APPLETALK=y +CONFIG_DEV_APPLETALK=m CONFIG_IPDDP=m CONFIG_IPDDP_ENCAP=y CONFIG_IPDDP_DECAP=y @@ -1072,7 +1107,7 @@ CONFIG_IP_DCCP_CCID2=m CONFIG_IP_DCCP_CCID3=y # CONFIG_IP_DCCP_CCID3_DEBUG is not set # CONFIG_IP_DCCP_DEBUG is not set -CONFIG_NET_DCCPPROBE=m +# CONFIG_NET_DCCPPROBE is not set # # TIPC Configuration (EXPERIMENTAL) @@ -1102,6 +1137,7 @@ CONFIG_NET_SCH_TBF=m CONFIG_NET_SCH_TEQL=m CONFIG_NET_SCH_SFB=m CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_MULTIQ=m CONFIG_NET_SCH_CHOKE=m CONFIG_NET_SCH_QFQ=m CONFIG_NET_CLS=y @@ -1127,6 +1163,7 @@ CONFIG_NET_EMATCH_STACK=32 CONFIG_NET_EMATCH_TEXT=m CONFIG_NET_EMATCH_U32=m +CONFIG_NET_ACT_CSUM=m CONFIG_NET_ACT_GACT=m CONFIG_GACT_PROB=y CONFIG_NET_ACT_IPT=m @@ -1135,7 +1172,7 @@ CONFIG_NET_ACT_NAT=m CONFIG_NET_ACT_PEDIT=m CONFIG_NET_ACT_POLICE=m CONFIG_NET_ACT_SIMP=m -CONFIG_NET_ACT_CSUM=m +CONFIG_NET_ACT_SKBEDIT=m CONFIG_DCB=y @@ -1221,10 +1258,191 @@ CONFIG_RFKILL_INPUT=y # # Ethernet (10 or 100Mbit) # -CONFIG_NETDEV_1000=y -CONFIG_NETDEV_10000=y -CONFIG_NET_ETHERNET=y -CONFIG_PHYLIB=m + +CONFIG_NET_VENDOR_ADAPTEC=y +CONFIG_ADAPTEC_STARFIRE=m + +CONFIG_NET_VENDOR_ALTEON=y +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set + +CONFIG_NET_VENDOR_AMD=y +# CONFIG_LANCE is not set +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_PCMCIA_NMCLAN=m + +CONFIG_NET_VENDOR_ATHEROS=y +CONFIG_ATL2=m +CONFIG_ATL1=m +CONFIG_ATL1C=m +CONFIG_ATL1E=m + +CONFIG_NET_VENDOR_BROCADE=y +CONFIG_BNA=m + +CONFIG_NET_VENDOR_CHELSIO=y +CONFIG_CHELSIO_T1=m +CONFIG_CHELSIO_T1_1G=y +CONFIG_CHELSIO_T3=m +CONFIG_CHELSIO_T4=m +CONFIG_CHELSIO_T4VF=m + +# CONFIG_NET_VENDOR_CIRRUS is not set +# +CONFIG_NET_VENDOR_CISCO=y +CONFIG_ENIC=m + +CONFIG_NET_VENDOR_DEC=y +CONFIG_EWRK3=m +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_DE2104X_DSL=0 +CONFIG_TULIP=m +# CONFIG_TULIP_NAPI is not set +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_NI5010 is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_PCMCIA_XIRCOM=m +CONFIG_ULI526X=m + +CONFIG_NET_VENDOR_DLINK=y +CONFIG_DE600=m +CONFIG_DE620=m +CONFIG_DL2K=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set + +CONFIG_NET_VENDOR_EMULEX=y +CONFIG_BE2NET=m + +CONFIG_NET_VENDOR_EXAR=y +CONFIG_S2IO=m +CONFIG_VXGE=m +# CONFIG_VXGE_DEBUG_TRACE_ALL is not set + +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_FUJITSU is not set +# CONFIG_NET_VENDOR_HP is not set +CONFIG_NET_VENDOR_INTEL=y +CONFIG_E100=m +CONFIG_E1000=m +CONFIG_E1000E=m +CONFIG_IGB=m +CONFIG_IGB_DCA=y +CONFIG_IGBVF=m +CONFIG_IXGB=m +CONFIG_IXGBEVF=m +CONFIG_IXGBE=m +CONFIG_IXGBE_DCA=y +CONFIG_IXGBE_DCB=y + +# CONFIG_NET_VENDOR_I825XX is not set +CONFIG_NET_VENDOR_MARVELL=y +CONFIG_SKGE=m +# CONFIG_SKGE_DEBUG is not set +CONFIG_SKGE_GENESIS=y +CONFIG_SKY2=m +# CONFIG_SKY2_DEBUG is not set + +CONFIG_NET_VENDOR_MICREL=y +CONFIG_KSZ884X_PCI=m +# CONFIG_KS8842 is not set +# CONFIG_KS8851_MLL is not set + +CONFIG_NET_VENDOR_MYRI=y +CONFIG_MYRI10GE=m +CONFIG_MYRI10GE_DCA=y + +CONFIG_NET_VENDOR_NATSEMI=y +CONFIG_NATSEMI=m +CONFIG_NS83820=m + +CONFIG_NET_VENDOR_8390=y +# CONFIG_AC3200 is not set +CONFIG_PCMCIA_AXNET=m +CONFIG_NE2K_PCI=m +CONFIG_NE3210=m +CONFIG_PCMCIA_PCNET=m + +CONFIG_NET_VENDOR_NVIDIA=y +CONFIG_FORCEDETH=m + +CONFIG_NET_VENDOR_OKI=y +# CONFIG_PCH_GBE is not set + +CONFIG_NET_PACKET_ENGINE=y +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m + +CONFIG_NET_VENDOR_QLOGIC=y +CONFIG_QLA3XXX=m +CONFIG_QLCNIC=m +CONFIG_QLGE=m +CONFIG_NETXEN_NIC=m + +CONFIG_NET_VENDOR_REALTEK=y +CONFIG_ATP=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_R8169=m + +CONFIG_NET_VENDOR_RDC=y +CONFIG_R6040=m + +# CONFIG_NET_VENDOR_SEEQ is not set + +CONFIG_NET_VENDOR_SILAN=y +CONFIG_SC92031=m + +CONFIG_NET_VENDOR_SIS=y +CONFIG_SIS900=m +CONFIG_SIS190=m + +CONFIG_NET_VENDOR_SMSC=y +# CONFIG_SMC9194 is not set +CONFIG_PCMCIA_SMC91C92=m +CONFIG_EPIC100=m +CONFIG_SMSC9420=m + +CONFIG_NET_VENDOR_STMICRO=y +CONFIG_STMMAC_ETH=m +# CONFIG_STMMAC_DA is not set +# CONFIG_STMMAC_DUAL_MAC is not set +# CONFIG_STMMAC_TIMER is not set +# CONFIG_STMMAC_DEBUG_FS is not set + +CONFIG_NET_VENDOR_SUN=y +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NIU=m + +CONFIG_NET_VENDOR_TEHUTI=y +CONFIG_TEHUTI=m + +CONFIG_NET_VENDOR_TI=y +CONFIG_TLAN=m + +CONFIG_NET_VENDOR_VIA=y +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_VELOCITY=m + +CONFIG_NET_VENDOR_XIRCOM=y +CONFIG_PCMCIA_XIRC2PS=m + +CONFIG_PHYLIB=y CONFIG_BROADCOM_PHY=m CONFIG_CICADA_PHY=m CONFIG_DAVICOM_PHY=m @@ -1244,144 +1462,43 @@ CONFIG_VITESSE_PHY=m CONFIG_MICREL_PHY=m CONFIG_MII=m -CONFIG_HAPPYMEAL=m -CONFIG_SUNGEM=m CONFIG_NET_VENDOR_3COM=y CONFIG_VORTEX=m CONFIG_TYPHOON=m CONFIG_DNET=m -CONFIG_STMMAC_ETH=m -# CONFIG_STMMAC_DA is not set -# CONFIG_STMMAC_DUAL_MAC is not set -# CONFIG_STMMAC_TIMER is not set -# CONFIG_PCH_GBE is not set -# -# Tulip family network device support -# -CONFIG_NET_TULIP=y -CONFIG_DE2104X=m -CONFIG_DE2104X_DSL=0 -CONFIG_TULIP=m -# CONFIG_TULIP_NAPI is not set -# CONFIG_TULIP_MWI is not set -CONFIG_TULIP_MMIO=y -# CONFIG_NI5010 is not set -CONFIG_DE4X5=m -CONFIG_WINBOND_840=m -CONFIG_DM9102=m -CONFIG_PCMCIA_XIRCOM=m -CONFIG_ULI526X=m -# CONFIG_HP100 is not set CONFIG_LNE390=m -CONFIG_NE3210=m CONFIG_ES3210=m CONFIG_NET_PCI=y -CONFIG_PCNET32=m -CONFIG_AMD8111_ETH=m -CONFIG_ADAPTEC_STARFIRE=m -CONFIG_KSZ884X_PCI=m CONFIG_B44=m CONFIG_B44_PCI=y CONFIG_BNX2=m CONFIG_CNIC=m -CONFIG_QLA3XXX=m -CONFIG_ATL1=m -CONFIG_ATL1C=m -CONFIG_ATL2=m -CONFIG_ATL1E=m -CONFIG_E100=m CONFIG_FEALNX=m -CONFIG_FORCEDETH=m -CONFIG_NATSEMI=m -CONFIG_NE2K_PCI=m -CONFIG_8139CP=m -CONFIG_8139TOO=m -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -CONFIG_8139TOO_8129=y -# CONFIG_8139_OLD_RX_RESET is not set -CONFIG_SIS900=m -CONFIG_SIS190=m -CONFIG_EPIC100=m -CONFIG_SC92031=m -CONFIG_SMSC9420=m -CONFIG_SUNDANCE=m -# CONFIG_SUNDANCE_MMIO is not set -CONFIG_TLAN=m -CONFIG_VIA_RHINE=m -CONFIG_VIA_RHINE_MMIO=y -CONFIG_VIA_VELOCITY=m CONFIG_NET_POCKET=y -CONFIG_ATP=m -CONFIG_DE600=m -CONFIG_DE620=m -CONFIG_CASSINI=m CONFIG_ETHOC=m -# CONFIG_KS8842 is not set -# CONFIG_KS8851_MLL is not set # # Ethernet (1000 Mbit) # -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_DL2K=m -CONFIG_E1000=m -CONFIG_E1000E=m -CONFIG_IGB=m -CONFIG_IGB_DCA=y -CONFIG_IGBVF=m -CONFIG_NS83820=m -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_R8169=m -CONFIG_SKGE=m -# CONFIG_SKGE_DEBUG is not set -CONFIG_SKGE_GENESIS=y CONFIG_TIGON3=m -CONFIG_SKY2=m -# CONFIG_SKY2_DEBUG is not set CONFIG_JME=m # # Ethernet (10000 Mbit) # -CONFIG_CHELSIO_T1=m -CONFIG_CHELSIO_T1_1G=y -CONFIG_CHELSIO_T3=m -CONFIG_CHELSIO_T4=m -CONFIG_CHELSIO_T4VF=m CONFIG_IP1000=m -CONFIG_IXGB=m -CONFIG_IXGBEVF=m -CONFIG_IXGBE=m -CONFIG_IXGBE_DCA=y -CONFIG_IXGBE_DCB=y -CONFIG_MYRI10GE=m -CONFIG_MYRI10GE_DCA=y -CONFIG_NETXEN_NIC=m -CONFIG_NIU=m -CONFIG_S2IO=m -CONFIG_VXGE=m -# CONFIG_VXGE_DEBUG_TRACE_ALL is not set -CONFIG_TEHUTI=m -CONFIG_ENIC=m CONFIG_MLX4_EN=m # CONFIG_MLX4_DEBUG is not set -CONFIG_QLCNIC=m -CONFIG_QLGE=m -CONFIG_BNA=m CONFIG_SFC=m CONFIG_SFC_MTD=y -CONFIG_BE2NET=m -CONFIG_FDDI=y +# CONFIG_FDDI is not set # CONFIG_DEFXX is not set -CONFIG_SKFP=m +# CONFIG_SKFP is not set # CONFIG_HIPPI is not set -CONFIG_PLIP=m +# CONFIG_PLIP is not set CONFIG_PPP=m CONFIG_PPP_MULTILINK=y CONFIG_PPP_FILTER=y @@ -1389,13 +1506,10 @@ CONFIG_PPP_ASYNC=m CONFIG_PPP_SYNC_TTY=m CONFIG_PPP_DEFLATE=m CONFIG_IPPP_FILTER=y -# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_BSDCOMP=y CONFIG_PPPOE=m CONFIG_PPP_MPPE=m -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -# CONFIG_SLIP_MODE_SLIP6 is not set +# CONFIG_SLIP is not set # # Wireless LAN @@ -1444,6 +1558,8 @@ CONFIG_ATH_COMMON=m CONFIG_ATH5K=m CONFIG_ATH5K_DEBUG=y # CONFIG_ATH5K_TRACER is not set +CONFIG_ATH6KL=m +CONFIG_ATH6KL_DEBUG=y CONFIG_ATH9K=m CONFIG_ATH9K_PCI=y CONFIG_ATH9K_AHB=y @@ -1454,6 +1570,7 @@ CONFIG_ATH9K_HTC=m CONFIG_ATH9K_RATE_CONTROL=y CONFIG_CARL9170=m CONFIG_CARL9170_LEDS=y +# CONFIG_CARL9170_HWRNG is not set CONFIG_AT76C50X_USB=m CONFIG_AIRO=m CONFIG_AIRO_CS=m @@ -1466,6 +1583,7 @@ CONFIG_B43_BCMA_PIO=y # CONFIG_B43_DEBUG is not set CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y +CONFIG_B43_PHY_HT=y # CONFIG_B43_FORCE_PIO is not set CONFIG_B43LEGACY=m # CONFIG_B43LEGACY_DEBUG is not set @@ -1474,6 +1592,9 @@ CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y # CONFIG_B43LEGACY_DMA_MODE is not set # CONFIG_B43LEGACY_PIO_MODE is not set +CONFIG_BRCMSMAC=m +CONFIG_BRCMFMAC=m +# CONFIG_BRCMDBG is not set CONFIG_HERMES=m CONFIG_HERMES_CACHE_FW_ON_INIT=y # CONFIG_HERMES_PRISM is not set @@ -1573,24 +1694,12 @@ CONFIG_RTL8192DE=m CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m - -CONFIG_BRCMFMAC=m -CONFIG_BRCMSMAC=m -# CONFIG_BRCMDBG is not set +CONFIG_MWIFIEX_PCIE=m # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_IBMOL is not set -# CONFIG_3C359 is not set -# Broken with gcc4.1 -# CONFIG_TMS380TR is not set -# CONFIG_TMSPCI is not set -# CONFIG_ABYSS is not set -# CONFIG_IBMLS is not set -# CONFIG_PCMCIA_IBMTR is not set - CONFIG_NET_FC=y @@ -1606,11 +1715,6 @@ CONFIG_NET_PCMCIA=y CONFIG_PCMCIA_3C589=m CONFIG_PCMCIA_3C574=m CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -CONFIG_PCMCIA_AXNET=m # # Amateur Radio support @@ -1618,27 +1722,9 @@ CONFIG_PCMCIA_AXNET=m CONFIG_HAMRADIO=y CONFIG_AX25=m CONFIG_AX25_DAMA_SLAVE=y -CONFIG_CAN=m -CONFIG_CAN_RAW=m -CONFIG_CAN_BCM=m -CONFIG_CAN_VCAN=m -CONFIG_CAN_DEV=m -CONFIG_CAN_CALC_BITTIMING=y -CONFIG_CAN_SJA1000=m -CONFIG_CAN_SJA1000_ISA=m -CONFIG_CAN_SJA1000_PLATFORM=m -CONFIG_CAN_EMS_PCI=m -CONFIG_CAN_EMS_USB=m -CONFIG_CAN_ESD_USB2=m -CONFIG_CAN_KVASER_PCI=m -CONFIG_CAN_PLX_PCI=m -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_CAN is not set + CONFIG_NETROM=m CONFIG_ROSE=m CONFIG_MKISS=m @@ -1654,7 +1740,7 @@ CONFIG_BAYCOM_PAR=m CONFIG_BAYCOM_EPP=m CONFIG_YAM=m -CONFIG_NFC=m +# CONFIG_NFC is not set # # IrDA (infrared) support @@ -1887,6 +1973,7 @@ CONFIG_INPUT_CM109=m CONFIG_INPUT_POLLDEV=m CONFIG_INPUT_SPARSEKMAP=m # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_BMA150 is not set CONFIG_INPUT_CMA3000=m CONFIG_INPUT_CMA3000_I2C=m @@ -1989,6 +2076,7 @@ CONFIG_TOUCHSCREEN_MCS5000=m CONFIG_TOUCHSCREEN_MK712=m CONFIG_TOUCHSCREEN_PENMOUNT=m # CONFIG_TOUCHSCREEN_TPS6507X is not set +CONFIG_TOUCHSCREEN_TSC_SERIO=m CONFIG_TOUCHSCREEN_TSC2007=m CONFIG_TOUCHSCREEN_TOUCHIT213=m CONFIG_TOUCHSCREEN_TOUCHRIGHT=m @@ -2010,7 +2098,6 @@ CONFIG_INPUT_UINPUT=m CONFIG_INPUT_WISTRON_BTNS=m CONFIG_INPUT_ATLAS_BTNS=m -CONFIG_INPUT_ATI_REMOTE=m CONFIG_INPUT_ATI_REMOTE2=m CONFIG_INPUT_KEYSPAN_REMOTE=m @@ -2065,6 +2152,7 @@ CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_SHARE_IRQ=y # CONFIG_SERIAL_8250_DETECT_IRQ is not set CONFIG_SERIAL_8250_RSA=y +# CONFIG_SERIAL_8250_DW is not set CONFIG_CYCLADES=m # CONFIG_CYZ_INTR is not set # CONFIG_MOXA_INTELLIO is not set @@ -2274,12 +2362,14 @@ CONFIG_SENSORS_MAX6642=m CONFIG_SENSORS_ADM1275=m CONFIG_SENSORS_UCD9000=m CONFIG_SENSORS_UCD9200=m +CONFIG_SENSORS_ZL6100=m CONFIG_SENSORS_EMC6W201=m CONFIG_PMBUS=m CONFIG_SENSORS_PMBUS=m CONFIG_SENSORS_MAX16064=m CONFIG_SENSORS_LM25066=m +CONFIG_SENSORS_LTC2978=m CONFIG_SENSORS_MAX34440=m CONFIG_SENSORS_MAX8688=m CONFIG_SENSORS_MAX1668=m @@ -2290,25 +2380,7 @@ CONFIG_SENSORS_MAX1668=m # CONFIG_SERIAL_PCH_UART is not set # CONFIG_USB_SWITCH_FSA9480 is not set -CONFIG_W1=m -CONFIG_W1_CON=y -# This is busted. -# If we enable it, it steals Matrox cards, and the -# framebuffer drivers stop working. -# CONFIG_W1_MASTER_MATROX is not set -CONFIG_W1_MASTER_DS2482=m -CONFIG_W1_MASTER_DS2490=m -CONFIG_W1_MASTER_DS1WM=m -CONFIG_W1_SLAVE_THERM=m -CONFIG_W1_SLAVE_SMEM=m -CONFIG_W1_SLAVE_DS2431=m -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 +# CONFIG_W1 is not set # # Mice @@ -2345,6 +2417,7 @@ CONFIG_MACHZ_WDT=m # CONFIG_SC520_WDT is not set CONFIG_ALIM7101_WDT=m CONFIG_ALIM1535_WDT=m +CONFIG_IT87_WDT=m CONFIG_ITCO_WDT=m CONFIG_ITCO_VENDOR_SUPPORT=y # CONFIG_SC1200_WDT is not set @@ -2358,12 +2431,15 @@ CONFIG_IT8712F_WDT=m CONFIG_SMSC_SCH311X_WDT=m CONFIG_W83977F_WDT=m CONFIG_PCIPCWATCHDOG=m +# CONFIG_PCWATCHDOG is not set CONFIG_USBPCWATCHDOG=m # CONFIG_SBC_EPX_C3_WATCHDOG is not set CONFIG_WM8350_WATCHDOG=m CONFIG_WM831X_WATCHDOG=m # CONFIG_MAX63XX_WATCHDOG is not set # CONFIG_DW_WATCHDOG is not set +CONFIG_W83697UG_WDT=m +# CONFIG_WDT is not set CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_TIMERIOMEM=m @@ -2380,6 +2456,7 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set CONFIG_RTC_DRV_CMOS=y CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1511=m CONFIG_RTC_DRV_DS1553=m CONFIG_RTC_DRV_DS1672=m CONFIG_RTC_DRV_DS1742=m @@ -2434,24 +2511,31 @@ CONFIG_AGP_SIS=y CONFIG_AGP_SWORKS=y CONFIG_AGP_VIA=y CONFIG_AGP_EFFICEON=y + CONFIG_VGA_ARB=y CONFIG_VGA_ARB_MAX_GPUS=16 -CONFIG_STUB_POULSBO=m + +# CONFIG_STUB_POULSBO is not set + CONFIG_DRM=m -CONFIG_DRM_TDFX=m -CONFIG_DRM_R128=m +# CONFIG_DRM_TDFX is not set +# CONFIG_DRM_R128 is not set CONFIG_DRM_RADEON=m CONFIG_DRM_RADEON_KMS=y -CONFIG_DRM_I810=m -CONFIG_DRM_MGA=m -CONFIG_DRM_SIS=m -CONFIG_DRM_SAVAGE=m +# CONFIG_DRM_I810 is not set +# CONFIG_DRM_MGA is not set +# CONFIG_DRM_SIS is not set +# CONFIG_DRM_SAVAGE is not set CONFIG_DRM_I915=m CONFIG_DRM_I915_KMS=y -CONFIG_DRM_VIA=m +# CONFIG_DRM_VIA is not set CONFIG_DRM_NOUVEAU=m CONFIG_DRM_NOUVEAU_BACKLIGHT=y CONFIG_DRM_NOUVEAU_DEBUG=y +CONFIG_DRM_PSB=m +# CONFIG_DRM_PSB_MRST is not set +# CONFIG_DRM_PSB_MFLD is not set +# CONFIG_DRM_PSB_CDV is not set CONFIG_DRM_I2C_CH7006=m CONFIG_DRM_I2C_SIL164=m CONFIG_DRM_VMWGFX=m @@ -2501,7 +2585,7 @@ CONFIG_VIDEO_CAFE_CCIC=m CONFIG_VIDEO_CPIA2=m CONFIG_VIDEO_CQCAM=m CONFIG_VIDEO_CX23885=m -# CONFIG_MEDIA_ALTERA_CI is not set +CONFIG_MEDIA_ALTERA_CI=m CONFIG_VIDEO_CX18=m CONFIG_VIDEO_CX18_ALSA=m CONFIG_VIDEO_CX88=m @@ -2523,6 +2607,7 @@ CONFIG_VIDEO_IVTV=m CONFIG_VIDEO_MEYE=m CONFIG_VIDEO_MXB=m CONFIG_VIDEO_PVRUSB2_DVB=y +# CONFIG_VIDEO_PMS is not set CONFIG_VIDEO_HDPVR=m CONFIG_VIDEO_SAA6588=m CONFIG_VIDEO_SAA7134=m @@ -2541,6 +2626,9 @@ CONFIG_VIDEO_ZORAN_LML33R10=m CONFIG_VIDEO_ZORAN_ZR36060=m CONFIG_VIDEO_FB_IVTV=m CONFIG_VIDEO_SAA7164=m +CONFIG_VIDEO_TM6000=m +CONFIG_VIDEO_TM6000_ALSA=m +CONFIG_VIDEO_TM6000_DVB=m CONFIG_VIDEO_TLG2300=m # CONFIG_VIDEO_TIMBERDALE is not set # CONFIG_VIDEO_M5MOLS is not set @@ -2668,6 +2756,13 @@ CONFIG_DVB_USB_ANYSEE=m CONFIG_DVB_USB_DW2102=m CONFIG_DVB_USB_FRIIO=m CONFIG_DVB_USB_EC168=m +CONFIG_DVB_USB_PCTV452E=m +CONFIG_DVB_USB_IT913X=m +CONFIG_DVB_USB_MXL111SF=m +CONFIG_DVB_TDA10071=m +CONFIG_DVB_LNBP22=m +CONFIG_DVB_A8293=m +CONFIG_DVB_IT913X_FE=m CONFIG_DVB_DM1105=m CONFIG_DVB_S921=m CONFIG_DVB_ISL6405=m @@ -2747,6 +2842,7 @@ CONFIG_VIDEO_PVRUSB2_SYSFS=y CONFIG_RC_CORE=m CONFIG_RC_LOOPBACK=m CONFIG_RC_MAP=m +CONFIG_RC_ATI_REMOTE=m CONFIG_IR_NEC_DECODER=m CONFIG_IR_RC5_DECODER=m CONFIG_IR_RC6_DECODER=m @@ -2761,6 +2857,9 @@ CONFIG_IR_ITE_CIR=m CONFIG_IR_NUVOTON=m CONFIG_IR_FINTEK=m CONFIG_IR_REDRAT3=m +CONFIG_IR_ENE=m +CONFIG_IR_STREAMZAP=m +CONFIG_IR_WINBOND_CIR=m CONFIG_V4L_MEM2MEM_DRIVERS=y # CONFIG_VIDEO_MEM2MEM_TESTDEV is not set @@ -2779,19 +2878,16 @@ CONFIG_VIDEO_OUTPUT_CONTROL=m CONFIG_FB=y # CONFIG_FB_FOREIGN_ENDIAN is not set -CONFIG_FB_3DFX=m -CONFIG_FB_3DFX_ACCEL=y -CONFIG_FB_3DFX_I2C=y +# CONFIG_FB_3DFX is not set # CONFIG_FB_ARC is not set # CONFIG_FB_ARK is not set -CONFIG_FB_ATY128=m -CONFIG_FB_ATY=m -CONFIG_FB_ATY_CT=y -CONFIG_FB_ATY_GX=y -CONFIG_FB_ATY_GENERIC_LCD=y +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_ATY_CT is not set +# CONFIG_FB_ATY_GX is not set # CONFIG_FB_ASILIANT is not set # CONFIG_FB_CARMINE is not set -CONFIG_FB_CIRRUS=m +# CONFIG_FB_CIRRUS is not set # CONFIG_FB_CYBER2000 is not set # CONFIG_FB_GEODE is not set # CONFIG_FB_HECUBA is not set @@ -2803,39 +2899,34 @@ CONFIG_FB_I810_I2C=y # CONFIG_FB_INTEL is not set # CONFIG_FB_INTEL_DEBUG is not set # CONFIG_FB_INTEL_I2C is not set -CONFIG_FB_KYRO=m +# CONFIG_FB_KYRO is not set # CONFIG_FB_LE80578 is not set -CONFIG_FB_MATROX=m -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G=y -CONFIG_FB_MATROX_I2C=m -CONFIG_FB_MATROX_MAVEN=m -CONFIG_FB_NEOMAGIC=m -CONFIG_FB_NVIDIA=m +# CONFIG_FB_MATROX is not set +# CONFIG_FB_MATROX_MILLENIUM is not set +# CONFIG_FB_MATROX_MYSTIQUE is not set +# CONFIG_FB_MATROX_G is not set +# CONFIG_FB_MATROX_I2C is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_NVIDIA_I2C is not set # CONFIG_FB_NVIDIA_DEBUG is not set -CONFIG_FB_NVIDIA_I2C=y # CONFIG_FB_PM2 is not set # CONFIG_FB_PM2_FIFO_DISCONNECT is not set # CONFIG_FB_PM3 is not set -CONFIG_FB_RADEON=m +# CONFIG_FB_RADEON is not set +# CONFIG_FB_RADEON_I2C is not set # CONFIG_FB_RADEON_DEBUG is not set -CONFIG_FB_RADEON_I2C=y -CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA is not set # CONFIG_FB_RIVA_DEBUG is not set # 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 +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set # CONFIG_FB_SIS is not set -CONFIG_FB_SIS_300=y -CONFIG_FB_SIS_315=y -CONFIG_FB_SM501=m +# CONFIG_FB_SM501 is not set +# CONFIG_FB_SMSCUFX is not set CONFIG_FB_TILEBLITTING=y -CONFIG_FB_TRIDENT=m +# CONFIG_FB_TRIDENT is not set # CONFIG_FB_UVESA is not set CONFIG_FB_VESA=y CONFIG_FB_VGA16=m @@ -2843,14 +2934,14 @@ CONFIG_FB_VIRTUAL=m 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 is not set # CONFIG_FB_VIA_DIRECT_PROCFS is not set -CONFIG_FB_METRONOME=m +# CONFIG_FB_METRONOME is not set # CONFIG_FB_MB862XX is not set # CONFIG_FB_PRE_INIT_FB is not set # CONFIG_FB_TMIO is not set # CONFIG_FB_BROADSHEET is not set +CONFIG_FB_UDL=m # CONFIG_FIRMWARE_EDID is not set @@ -3032,9 +3123,7 @@ CONFIG_SND_USB_6FIRE=m # # PCMCIA devices # -CONFIG_SND_PCMCIA=y -CONFIG_SND_VXPOCKET=m -CONFIG_SND_PDAUDIOCF=m +# CONFIG_SND_PCMCIA is not set CONFIG_SND_FIREWIRE=y CONFIG_SND_FIREWIRE_SPEAKERS=m @@ -3076,7 +3165,7 @@ 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 +CONFIG_USB_XHCI_HCD=y # CONFIG_USB_XHCI_HCD_DEBUGGING is not set CONFIG_USB_ISP1362_HCD=m @@ -3109,7 +3198,6 @@ CONFIG_USB_STORAGE_REALTEK=m CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set -# uas is broken (#717633, #744099) # CONFIG_USB_UAS is not set @@ -3125,6 +3213,7 @@ CONFIG_HID=m CONFIG_HIDRAW=y CONFIG_HID_PID=y CONFIG_LOGITECH_FF=y +CONFIG_HID_LOGITECH_DJ=m CONFIG_LOGIWII_FF=y CONFIG_LOGIRUMBLEPAD2_FF=y CONFIG_PANTHERLORD_FF=y @@ -3138,10 +3227,12 @@ CONFIG_DRAGONRISE_FF=y CONFIG_GREENASIA_FF=y CONFIG_SMARTJOYPLUS_FF=y CONFIG_LOGIG940_FF=y +CONFIG_LOGIWHEELS_FF=y CONFIG_HID_MAGICMOUSE=y CONFIG_HID_MULTITOUCH=m CONFIG_HID_NTRIG=y CONFIG_HID_QUANTA=y +CONFIG_HID_PRIMAX=m CONFIG_HID_PRODIKEYS=m CONFIG_HID_DRAGONRISE=m CONFIG_HID_GYRATION=m @@ -3218,6 +3309,7 @@ CONFIG_USB_GSPCA_SPCA561=m CONFIG_USB_GSPCA_STK014=m CONFIG_USB_GSPCA_SUNPLUS=m CONFIG_USB_GSPCA_T613=m +CONFIG_USB_GSPCA_TOPRO=m CONFIG_USB_GSPCA_TV8532=m CONFIG_USB_GSPCA_VC032X=m CONFIG_USB_GSPCA_ZC3XX=m @@ -3241,22 +3333,7 @@ CONFIG_USB_S2255=m # CONFIG_VIDEO_SH_MOBILE_CSI2 is not set # CONFIG_USB_SN9C102 is not set CONFIG_USB_ZR364XX=m -CONFIG_SOC_CAMERA=m -CONFIG_SOC_CAMERA_MT9M001=m -CONFIG_SOC_CAMERA_MT9V022=m -CONFIG_SOC_CAMERA_PLATFORM=m -CONFIG_SOC_CAMERA_MT9M111=m -CONFIG_SOC_CAMERA_MT9T031=m -CONFIG_SOC_CAMERA_TW9910=m -CONFIG_SOC_CAMERA_OV772X=m -CONFIG_SOC_CAMERA_MT9T112=m -CONFIG_SOC_CAMERA_RJ54N1=m -CONFIG_SOC_CAMERA_OV9640=m -CONFIG_SOC_CAMERA_OV6650=m -CONFIG_SOC_CAMERA_OV5642=m -CONFIG_SOC_CAMERA_IMX074=m -CONFIG_SOC_CAMERA_OV2640=m -CONFIG_SOC_CAMERA_OV9740=m +# CONFIG_SOC_CAMERA is not set # # USB Network adaptors @@ -3361,6 +3438,7 @@ CONFIG_USB_SERIAL_OTI6858=m CONFIG_USB_SERIAL_OPTICON=m CONFIG_USB_SERIAL_OMNINET=m CONFIG_USB_SERIAL_PL2303=m +# CONFIG_USB_SERIAL_QUATECH2 is not set CONFIG_USB_SERIAL_SAFE=m CONFIG_USB_SERIAL_SAFE_PADDED=y CONFIG_USB_SERIAL_SIERRAWIRELESS=m @@ -3401,6 +3479,7 @@ CONFIG_USB_FTDI_ELAN=m CONFIG_USB_FILE_STORAGE=m # CONFIG_USB_FILE_STORAGE_TEST is not set # CONFIG_USB_GADGET is not set +# CONFIG_USB_DWC3 is not set # CONFIG_USB_GADGETFS is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set @@ -3482,25 +3561,22 @@ CONFIG_MFD_WM8400=m # CONFIG_MFD_JANZ_CMODIO is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_WL1273_CORE is not set # # File systems # CONFIG_MISC_FILESYSTEMS=y -CONFIG_EXT2_FS=m -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -CONFIG_EXT2_FS_XIP=y -CONFIG_EXT3_FS=y -CONFIG_EXT3_DEFAULTS_TO_ORDERED=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set +# ext4 is used for ext2 and ext3 filesystems +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT23=y CONFIG_EXT4_FS_XATTR=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y @@ -3534,13 +3610,14 @@ CONFIG_DNOTIFY=y # Autofsv3 is obsolete. # systemd is dependant upon AUTOFS, so build it in. CONFIG_AUTOFS4_FS=y -CONFIG_EXOFS_FS=m +# CONFIG_EXOFS_FS is not set # CONFIG_EXOFS_DEBUG is not set -CONFIG_NILFS2_FS=m -CONFIG_LOGFS=m +# CONFIG_NILFS2_FS is not set +# CONFIG_LOGFS is not set CONFIG_CEPH_FS=m CONFIG_BLK_DEV_RBD=m CONFIG_CEPH_LIB=m +# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set CONFIG_FSCACHE=m CONFIG_FSCACHE_STATS=y @@ -3593,27 +3670,21 @@ CONFIG_HFS_FS=m CONFIG_HFSPLUS_FS=m CONFIG_BEFS_FS=m # CONFIG_BEFS_DEBUG is not set -CONFIG_BFS_FS=m -CONFIG_EFS_FS=m -CONFIG_JFFS2_FS=m -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set -CONFIG_JFFS2_FS_WRITEBUFFER=y -# CONFIG_JFFS2_FS_WBUF_VERIFY is not set -CONFIG_JFFS2_SUMMARY=y -CONFIG_JFFS2_FS_XATTR=y -CONFIG_JFFS2_FS_POSIX_ACL=y -CONFIG_JFFS2_FS_SECURITY=y +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set + CONFIG_CRAMFS=m CONFIG_SQUASHFS=m CONFIG_SQUASHFS_XATTR=y CONFIG_SQUASHFS_LZO=y CONFIG_SQUASHFS_XZ=y CONFIG_SQUASHFS_ZLIB=y +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set # CONFIG_SQUASHFS_EMBEDDED is not set -CONFIG_VXFS_FS=m +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_QNX4FS_FS=m +# CONFIG_QNX4FS_FS is not set CONFIG_SYSV_FS=m CONFIG_UFS_FS=m # CONFIG_UFS_FS_WRITE is not set @@ -3622,7 +3693,7 @@ CONFIG_9P_FS=m CONFIG_9P_FSCACHE=y CONFIG_9P_FS_POSIX_ACL=y CONFIG_FUSE_FS=m -CONFIG_OMFS_FS=m +# CONFIG_OMFS_FS is not set CONFIG_CUSE=m # @@ -3685,17 +3756,14 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m CONFIG_BTRFS_FS=m CONFIG_BTRFS_FS_POSIX_ACL=y -CONFIG_CONFIGFS_FS=m +CONFIG_CONFIGFS_FS=y CONFIG_DLM=m CONFIG_DLM_DEBUG=y CONFIG_GFS2_FS=m CONFIG_GFS2_FS_LOCKING_DLM=y -CONFIG_UBIFS_FS=m -CONFIG_UBIFS_FS_XATTR=y -# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set -# CONFIG_UBIFS_FS_DEBUG is not set +# CONFIG_UBIFS_FS is not set # # Partition Types @@ -3782,24 +3850,68 @@ CONFIG_FRAME_POINTER=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_DEBUG_DRIVER is not set CONFIG_HEADERS_CHECK=y -# CONFIG_RCU_TORTURE_TEST is not set -# CONFIG_RCU_TRACE is not set # CONFIG_LKDTM is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_LOCKDEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# DEBUG options that don't get enabled/disabled with 'make debug/release' +# +# Kmemleak still produces a lot of false positives. +# CONFIG_DEBUG_KMEMLEAK is not set +# +# This generates a huge amount of dmesg spew +# CONFIG_DEBUG_KOBJECT is not set +# +# +# These debug options are deliberatly left on (even in 'make release' kernels). +# They aren't that much of a performance impact, and the value +# from getting useful bug-reports makes it worth leaving them on. +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_HIGHMEM=y +CONFIG_BOOT_PRINTK_DELAY=y +CONFIG_DEBUG_LIST=y +CONFIG_DEBUG_SHIRQ=y +CONFIG_DEBUG_DEVRES=y +CONFIG_DEBUG_RODATA_TEST=y +CONFIG_DEBUG_NX_TEST=m +CONFIG_DEBUG_SET_MODULE_RONX=y +CONFIG_DEBUG_BOOT_PARAMS=y +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set +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_ATOMIC64_SELFTEST=y +CONFIG_MEMORY_FAILURE=y +CONFIG_HWPOISON_INJECT=m +# CONFIG_DEBUG_SECTION_MISMATCH is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +CONFIG_LATENCYTOP=y +CONFIG_RESOURCE_COUNTERS=y +# CONFIG_COMPAT_BRK is not set +# CONFIG_DEBUG_VIRTUAL is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +CONFIG_EARLY_PRINTK_DBGP=y +# CONFIG_PAGE_POISONING is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_CRASH is not set +# CONFIG_GCOV_KERNEL is not set +# CONFIG_RAMOOPS is not set + CONFIG_KGDB=y CONFIG_KGDB_SERIAL_CONSOLE=y CONFIG_KGDB_TESTS=y CONFIG_KGDB_LOW_LEVEL_TRAP=y # CONFIG_KGDB_TESTS_ON_BOOT is not set + # # Security options # CONFIG_SECURITY=y +CONFIG_SECURITYFS=y # CONFIG_SECURITY_DMESG_RESTRICT is not set CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_NETWORK_XFRM=y @@ -3811,6 +3923,7 @@ CONFIG_SECURITY_SELINUX_DEVELOP=y CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 CONFIG_SECURITY_SELINUX_AVC_STATS=y +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set # CONFIG_SECURITY_SMACK is not set # CONFIG_SECURITY_TOMOYO is not set # CONFIG_SECURITY_APPARMOR is not set @@ -3885,6 +3998,9 @@ CONFIG_CRYPTO_ANSI_CPRNG=m CONFIG_CRYPTO_DEV_HIFN_795X=m CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y CONFIG_CRYPTO_PCRYPT=m +CONFIG_CRYPTO_USER=m + + # Random number generation @@ -3897,6 +4013,7 @@ CONFIG_CRC_CCITT=m CONFIG_CRC_ITU_T=m CONFIG_CRC_T10DIF=m CONFIG_CRC8=m +# CONFIG_CRC7 is not set CONFIG_CORDIC=m CONFIG_CRYPTO_ZLIB=m @@ -3933,6 +4050,7 @@ CONFIG_LCD_PLATFORM=m CONFIG_SCHEDSTATS=y CONFIG_SCHED_DEBUG=y CONFIG_FAIR_GROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y CONFIG_SCHED_OMIT_FRAME_POINTER=y CONFIG_RT_GROUP_SCHED=y CONFIG_SCHED_AUTOGROUP=y @@ -3951,7 +4069,6 @@ 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 # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_SYSFS_DEPRECATED_V2 is not set @@ -3966,6 +4083,8 @@ CONFIG_KEXEC=y CONFIG_HWMON=y # CONFIG_HWMON_DEBUG_CHIP is not set +CONFIG_THERMAL_HWMON=y + CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y @@ -3976,19 +4095,18 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y -# CONFIG_PM_VERBOSE is not set +CONFIG_PM_TRACE_RTC=y # CONFIG_PM_TEST_SUSPEND is not set CONFIG_PM_RUNTIME=y +# CONFIG_PM_OPP is not set CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_DEBUG=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=m -CONFIG_CPU_FREQ_GOV_USERSPACE=m -CONFIG_CPU_FREQ_GOV_ONDEMAND=m -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y CONFIG_CPU_FREQ_TABLE=y CONFIG_CPU_FREQ_STAT=m CONFIG_CPU_FREQ_STAT_DETAILS=y @@ -4001,53 +4119,22 @@ CONFIG_I82365=m # CONFIG_LTPC is not set # CONFIG_COPS is not set -CONFIG_SCSI_AHA152X=m -CONFIG_SCSI_AHA1542=m -# CONFIG_SCSI_IN2000 is not set -CONFIG_SCSI_ARCMSR=m -CONFIG_SCSI_ARCMSR_AER=y -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_ULTRASTOR is not set # CONFIG_EL1 is not set # CONFIG_EL2 is not set -# CONFIG_ELPLUS is not set -# CONFIG_EL16 is not set CONFIG_EL3=m # CONFIG_3C515 is not set -# CONFIG_LANCE is not set CONFIG_NET_VENDOR_SMC=y # CONFIG_WD80x3 is not set CONFIG_ULTRA=m -# CONFIG_SMC9194 is not set # CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_NI52 is not set # CONFIG_NI65 is not set -# CONFIG_AT1700 is not set # CONFIG_DEPCA is not set CONFIG_NET_ISA=y CONFIG_NE2000=m # CONFIG_E2100 is not set -CONFIG_EWRK3=m -# CONFIG_EEXPRESS is not set -# CONFIG_EEXPRESS_PRO is not set # CONFIG_HPLAN_PLUS is not set # CONFIG_HPLAN is not set -# CONFIG_LP486E is not set -# CONFIG_ETH16I is not set -# CONFIG_ZNET is not set -# CONFIG_SEEQ8005 is not set -# CONFIG_AC3200 is not set -# CONFIG_APRICOT is not set -# CONFIG_CS89x0 is not set # CONFIG_IBMTR is not set # CONFIG_SKISA is not set # CONFIG_PROTEON is not set @@ -4080,24 +4167,7 @@ CONFIG_EWRK3=m # CONFIG_SERIAL_8250_HUB6 is not set # CONFIG_SERIAL_8250_EXAR_ST16C554 is not set -# CONFIG_PCWATCHDOG is not set -# CONFIG_WDT is not set - -# CONFIG_VIDEO_PMS is not set -CONFIG_RADIO_ADAPTERS=y -# CONFIG_RADIO_CADET is not set -# CONFIG_RADIO_RTRACK is not set -# CONFIG_RADIO_RTRACK2 is not set -# CONFIG_RADIO_AZTECH is not set -# CONFIG_RADIO_GEMTEK is not set -# CONFIG_RADIO_SF16FMI is not set -# CONFIG_RADIO_SF16FMR2 is not set -# CONFIG_RADIO_TERRATEC is not set -# CONFIG_RADIO_TRUST is not set -# CONFIG_RADIO_TEA5764 is not set -# CONFIG_RADIO_TYPHOON is not set -# CONFIG_RADIO_ZOLTRIX is not set -# CONFIG_RADIO_SAA7706H is not set +# CONFIG_RADIO_ADAPTERS is not set # CONFIG_SND_OPL4_LIB is not set # CONFIG_SND_AD1816A is not set @@ -4162,22 +4232,22 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=m CONFIG_LEDS_TRIGGER_BACKLIGHT=m CONFIG_LEDS_TRIGGER_DEFAULT_ON=m CONFIG_LEDS_ALIX2=m -CONFIG_LEDS_WM8350=m -CONFIG_LEDS_LP3944=m -CONFIG_LEDS_WM831X_STATUS=m -CONFIG_LEDS_REGULATOR=m -CONFIG_LEDS_LT3593=m -CONFIG_LEDS_TRIGGER_GPIO=m +CONFIG_LEDS_CLEVO_MAIL=m CONFIG_LEDS_INTEL_SS4200=m +CONFIG_LEDS_LM3530=m +CONFIG_LEDS_LP3944=m CONFIG_LEDS_LP5521=m CONFIG_LEDS_LP5523=m -CONFIG_LEDS_LM3530=m +CONFIG_LEDS_LT3593=m +CONFIG_LEDS_REGULATOR=m +CONFIG_LEDS_TRIGGER_GPIO=m +CONFIG_LEDS_WM8350=m +CONFIG_LEDS_WM831X_STATUS=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 CONFIG_ASYNC_TX_DMA=y @@ -4198,13 +4268,14 @@ CONFIG_FUNCTION_PROFILER=y CONFIG_RING_BUFFER_BENCHMARK=m CONFIG_FUNCTION_TRACER=y CONFIG_STACK_TRACER=y +# CONFIG_FUNCTION_GRAPH_TRACER is not set CONFIG_KPROBES=y +CONFIG_KPROBE_EVENT=y +# CONFIG_KPROBES_SANITY_TEST is not set CONFIG_JUMP_LABEL=y CONFIG_OPTPROBES=y -# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set - CONFIG_HZ_1000=y CONFIG_TIMER_STATS=y @@ -4220,22 +4291,26 @@ CONFIG_CFAG12864B_RATE=20 CONFIG_POWER_SUPPLY=m # CONFIG_POWER_SUPPLY_DEBUG is not set + # CONFIG_TEST_POWER is not set CONFIG_APM_POWER=m # CONFIG_WM831X_POWER is not set + # 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_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_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_GPIO is not set # CONFIG_CHARGER_PCF50633 is not set +# CONFIG_PDA_POWER is not set + CONFIG_AUXDISPLAY=y CONFIG_UIO=m @@ -4247,7 +4322,6 @@ CONFIG_UIO_SERCOS3=m CONFIG_UIO_PCI_GENERIC=m # CONFIG_UIO_NETX is not set -# CONFIG_CRC7 is not set # LIRC @@ -4267,30 +4341,17 @@ CONFIG_LIRC_TTUSBIR=m # CONFIG_DEVKMEM is not set -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 -# CONFIG_KPROBES_SANITY_TEST is not set -# CONFIG_BACKTRACE_SELF_TEST is not set -CONFIG_LATENCYTOP=y -CONFIG_RESOURCE_COUNTERS=y -# CONFIG_COMPAT_BRK is not set - -#FIXME: x86 generic? -CONFIG_LEDS_CLEVO_MAIL=m CONFIG_INPUT_APANEL=m # CONFIG_INTEL_MENLOW is not set CONFIG_ENCLOSURE_SERVICES=m CONFIG_IPWIRELESS=m -CONFIG_RTC_DRV_DS1511=m # CONFIG_BLK_DEV_XIP is not set CONFIG_MEMSTICK=m @@ -4308,41 +4369,26 @@ CONFIG_A11Y_BRAILLE_CONSOLE=y # MT9V022_PCA9536_SWITCH is not set -CONFIG_THERMAL_HWMON=y - CONFIG_OPTIMIZE_INLINING=y # FIXME: This should be x86/ia64 only # CONFIG_HP_ILO is not set # CONFIG_GPIOLIB is not set - - -CONFIG_NETFILTER_TPROXY=m -CONFIG_NETFILTER_XT_TARGET_TPROXY=m -CONFIG_NETFILTER_XT_MATCH_RECENT=m -# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set -CONFIG_NETFILTER_XT_MATCH_SOCKET=m - -# CONFIG_IP_VS_IPV6 is not set +# CONFIG_PINCTRL is not set CONFIG_NET_DSA=y CONFIG_NET_DSA_MV88E6060=y CONFIG_NET_DSA_MV88E6131=y CONFIG_NET_DSA_MV88E6123_61_65=y -CONFIG_NET_SCH_MULTIQ=m -CONFIG_NET_ACT_SKBEDIT=m +# Used by Maemo, we don't care. +# CONFIG_PHONET is not set -CONFIG_PHONET=m +# CONFIG_ICS932S401 is not set -CONFIG_ICS932S401=m # CONFIG_C2PORT is not set - -CONFIG_IT87_WDT=m -CONFIG_W83697UG_WDT=m - # CONFIG_REGULATOR is not set # CONFIG_REGULATOR_DEBUG is not set @@ -4362,9 +4408,10 @@ CONFIG_UWB_WHCI=m CONFIG_UWB_I1480U=m CONFIG_STAGING=y +CONFIG_STAGING_MEDIA=y +# CONFIG_DVB_AS102 is not set # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set -# CONFIG_VIDEO_TM6000 is not set # CONFIG_WLAGS49_H2 is not set # CONFIG_WLAGS49_H25 is not set # CONFIG_VIDEO_DT3155 is not set @@ -4391,7 +4438,6 @@ CONFIG_USB_ATMEL=m # CONFIG_RTL8192E is not set # CONFIG_INPUT_GPIO is not set # CONFIG_VIDEO_CX25821 is not set -# CONFIG_HYPERV is not set # CONFIG_R8187SE is not set # CONFIG_RTL8192U is not set # CONFIG_BATMAN_ADV is not set @@ -4411,51 +4457,41 @@ CONFIG_USB_ATMEL=m # 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_ALTERA_STAPL=m # CONFIG_DVB_CXD2099 is not set # CONFIG_USBIP_CORE is not set # CONFIG_INTEL_MEI is not set # CONFIG_ZCACHE is not set - -# -# Android +# CONFIG_RTS5139 is not set +# CONFIG_NVEC_LEDS is not set +# CONFIG_VT6655 is not set # +# END OF STAGING -# CONFIG_DEBUG_VIRTUAL is not set -# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set -# CONFIG_FUNCTION_GRAPH_TRACER is not set -CONFIG_EARLY_PRINTK_DBGP=y - -CONFIG_SECURITYFS=y - -CONFIG_SCSI_CXGB3_ISCSI=m CONFIG_LIBFC=m CONFIG_LIBFCOE=m CONFIG_FCOE=m CONFIG_FCOE_FNIC=m -# CONFIG_SCSI_LPFC_DEBUG_FS is not set CONFIG_NOP_USB_XCEIV=m -CONFIG_IMA=y +# CONFIG_IMA is not set CONFIG_IMA_MEASURE_PCR_IDX=10 CONFIG_IMA_AUDIT=y CONFIG_IMA_LSM_RULES=y +# CONFIG_EVM is not set + CONFIG_LSM_MMAP_MIN_ADDR=65536 -# CONFIG_PAGE_POISONING is not set - - -# CONFIG_CRASH_DUMP is not set -# CONFIG_CRASH is not set - CONFIG_STRIP_ASM_SYMS=y # CONFIG_RCU_FANOUT_EXACT is not set CONFIG_RCU_FAST_NO_HZ=y CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_TRACE is not set +CONFIG_SPARSE_RCU_POINTER=y CONFIG_KSM=y CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -4465,62 +4501,29 @@ CONFIG_FANOTIFY=y CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y CONFIG_IEEE802154=m +CONFIG_IEEE802154_6LOWPAN=m CONFIG_IEEE802154_DRIVERS=m CONFIG_IEEE802154_FAKEHARD=m -# CONFIG_GCOV_KERNEL is not set - CONFIG_PPS=m # CONFIG_PPS_CLIENT_KTIMER is not set CONFIG_PPS_CLIENT_LDISC=m # CONFIG_PPS_DEBUG is not set CONFIG_PPS_CLIENT_PARPORT=m CONFIG_PPS_GENERATOR_PARPORT=m +CONFIG_PPS_CLIENT_GPIO=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 - -# DEBUG options that don't get enabled/disabled with 'make debug/release' -# -# Kmemleak still produces a lot of false positives. -# CONFIG_DEBUG_KMEMLEAK is not set -# -# This generates a huge amount of dmesg spew -# CONFIG_DEBUG_KOBJECT is not set -# -# -# These debug options are deliberatly left on (even in 'make release' kernels). -# They aren't that much of a performance impact, and the value -# from getting useful bug-reports makes it worth leaving them on. -CONFIG_DYNAMIC_DEBUG=y -CONFIG_DEBUG_HIGHMEM=y -CONFIG_BOOT_PRINTK_DELAY=y -CONFIG_DEBUG_LIST=y -CONFIG_DEBUG_SHIRQ=y -CONFIG_DEBUG_DEVRES=y -CONFIG_DEBUG_RODATA_TEST=y -CONFIG_DEBUG_NX_TEST=m -CONFIG_DEBUG_BOOT_PARAMS=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_ATOMIC64_SELFTEST=y - -CONFIG_MEMORY_FAILURE=y -CONFIG_HWPOISON_INJECT=m CONFIG_CLEANCACHE=y -CONFIG_BLK_DEV_DRBD=m - # CONFIG_MDIO_GPIO is not set # CONFIG_KEYBOARD_GPIO is not set # CONFIG_KEYBOARD_GPIO_POLLED is not set # CONFIG_MOUSE_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_DESIGNWARE_PCI is not set # CONFIG_I2C_GPIO is not set # CONFIG_DEBUG_GPIO is not set # CONFIG_W1_MASTER_GPIO is not set @@ -4544,32 +4547,14 @@ CONFIG_GPIO_SYSFS=y # CONFIG_GPIO_PCH is not set # CONFIG_GPIO_ML_IOH is not set -CONFIG_KPROBE_EVENT=y - -# CONFIG_RAMOOPS is not set - -CONFIG_IR_ENE=m -CONFIG_IR_STREAMZAP=m -CONFIG_IR_WINBOND_CIR=m - # CONFIG_GPIO_SX150X is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_MAX8998 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TC3589X is not set - -CONFIG_SPARSE_RCU_POINTER=y - -# CONFIG_PM_OPP is not set - +# FIXME: Why? CONFIG_EVENT_POWER_TRACING_DEPRECATED=y +CONFIG_TEST_KSTRTOX=y # CONFIG_XZ_DEC_TEST is not set -CONFIG_PN544_NFC=m -CONFIG_NFC_PN533=m - CONFIG_TARGET_CORE=m CONFIG_ISCSI_TARGET=m CONFIG_LOOPBACK_TARGET=m @@ -4588,8 +4573,6 @@ CONFIG_PSTORE=y CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 -CONFIG_TEST_KSTRTOX=m - CONFIG_BCMA=m CONFIG_BCMA_BLOCKIO=y CONFIG_BCMA_HOST_PCI_POSSIBLE=y @@ -4598,6 +4581,6 @@ CONFIG_BCMA_HOST_PCI=y # CONFIG_GOOGLE_FIRMWARE is not set CONFIG_INTEL_MID_PTI=m - CONFIG_IOMMU_SUPPORT=y +# CONFIG_PM_DEVFREQ is not set diff --git a/config-nodebug b/config-nodebug index 084f88e2e..0f70aa0ae 100644 --- a/config-nodebug +++ b/config-nodebug @@ -24,6 +24,7 @@ CONFIG_CPUMASK_OFFSTACK=y # CONFIG_FAULT_INJECTION_DEBUG_FS is not set # CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set # CONFIG_FAIL_IO_TIMEOUT is not set +# CONFIG_FAIL_MMC_REQUEST is not set # CONFIG_SLUB_DEBUG_ON is not set @@ -81,7 +82,6 @@ CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 # CONFIG_IWLWIFI_DEVICE_TRACING is not set # CONFIG_DEBUG_OBJECTS_WORK is not set -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DMADEVICES_DEBUG is not set # CONFIG_DMADEVICES_VDEBUG is not set @@ -99,9 +99,8 @@ CONFIG_KDB_KEYBOARD=y # CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set # CONFIG_TEST_LIST_SORT is not set -# CONFIG_DEBUG_SET_MODULE_RONX is not set - # CONFIG_DETECT_HUNG_TASK is not set CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set diff --git a/config-powerpc-generic b/config-powerpc-generic index 186aa540a..2ca0c3e83 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -13,19 +13,6 @@ CONFIG_TAU_AVERAGE=y CONFIG_SECCOMP=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_DEBUG=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=m -CONFIG_CPU_FREQ_GOV_USERSPACE=m -CONFIG_CPU_FREQ_GOV_ONDEMAND=m -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m -CONFIG_CPU_FREQ_TABLE=y -CONFIG_CPU_FREQ_STAT=m -CONFIG_CPU_FREQ_STAT_DETAILS=y - CONFIG_PM=y CONFIG_PM_STD_PARTITION="" @@ -51,20 +38,15 @@ CONFIG_AGP_UNINORTH=y CONFIG_FB_OF=y # CONFIG_FB_CONTROL is not set CONFIG_FB_IBM_GXT4500=y -CONFIG_FB_RADEON=y CONFIG_FB_MATROX=y -CONFIG_FB_NVIDIA=m # CONFIG_FB_VGA16 is not set CONFIG_FB_ATY128_BACKLIGHT=y CONFIG_FB_ATY_BACKLIGHT=y -CONFIG_FB_RADEON_BACKLIGHT=y CONFIG_FB_RIVA_BACKLIGHT=y -CONFIG_FB_NVIDIA_BACKLIGHT=y -# FIXME: Do we care about this hardware ? -CONFIG_FB_MB862XX=m -CONFIG_FB_MB862XX_PCI_GDC=y -CONFIG_FB_MB862XX_LIME=y -CONFIG_FB_MB862XX_I2C=y +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_MB862XX_PCI_GDC is not set +# CONFIG_FB_MB862XX_LIME is not set +# CONFIG_FB_MB862XX_I2C is not set CONFIG_SND_POWERMAC=m @@ -178,7 +160,7 @@ CONFIG_IDE_TASK_IOCTL=y # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set -CONFIG_BLK_DEV_IDE_PMAC=y +CONFIG_BLK_DEV_IDE_PMAC=m CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y CONFIG_BLK_DEV_IDEDMA=y # CONFIG_BLK_DEV_HD is not set @@ -200,8 +182,8 @@ CONFIG_EDAC_PASEMI=m CONFIG_EDAC_AMD8131=m CONFIG_EDAC_AMD8111=m -CONFIG_AXON_RAM=m -CONFIG_OPROFILE_CELL=y +# CONFIG_AXON_RAM is not set +# CONFIG_OPROFILE_CELL is not set CONFIG_SUSPEND_FREEZER=y # CONFIG_IDEPCI_PCIBUS_ORDER is not set @@ -211,7 +193,7 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set -CONFIG_MTD_OF_PARTS=m +CONFIG_MTD_OF_PARTS=y # CONFIG_MTD_NAND_FSL_ELBC is not set CONFIG_THERMAL=y @@ -222,9 +204,9 @@ CONFIG_DMADEVICES=y CONFIG_SND_PPC=y -CONFIG_PPC_82xx=y -CONFIG_PPC_83xx=y -CONFIG_PPC_86xx=y +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +# CONFIG_PPC_86xx is not set CONFIG_EXTRA_TARGETS="" # CONFIG_CODE_PATCHING_SELFTEST is not set # CONFIG_FTR_FIXUP_SELFTEST is not set @@ -238,27 +220,28 @@ CONFIG_EXTRA_TARGETS="" # CONFIG_SERIAL_QE is not set # CONFIG_I2C_CPM is not set +CONFIG_NET_VENDOR_IBM=y -CONFIG_SERIO_XILINX_XPS_PS2=m +# CONFIG_SERIO_XILINX_XPS_PS2 is not set # CONFIG_PPC_SMLPAR is not set -CONFIG_MGCOGE=y -CONFIG_GEF_SBC610=y -CONFIG_GEF_PPC9A=y -CONFIG_GEF_SBC310=y +# CONFIG_MGCOGE is not set +# CONFIG_GEF_SBC610 is not set +# CONFIG_GEF_PPC9A is not set +# CONFIG_GEF_SBC310 is not set -CONFIG_QUICC_ENGINE=y -CONFIG_QE_GPIO=y -CONFIG_MPC8xxx_GPIO=y +# CONFIG_QUICC_ENGINE is not set +# CONFIG_QE_GPIO is not set +# CONFIG_MPC8xxx_GPIO is not set CONFIG_IDE_GD=y CONFIG_IDE_GD_ATA=y CONFIG_IDE_GD_ATAPI=y -CONFIG_MCU_MPC8349EMITX=m +# CONFIG_MCU_MPC8349EMITX is not set -CONFIG_GPIO_XILINX=y +# CONFIG_GPIO_XILINX is not set CONFIG_PMIC_DA903X=y CONFIG_BACKLIGHT_DA903X=m @@ -279,11 +262,11 @@ CONFIG_TOUCHSCREEN_DA9034=m CONFIG_SIMPLE_GPIO=y -CONFIG_FSL_PQ_MDIO=m +# CONFIG_FSL_PQ_MDIO is not set -CONFIG_PS3_VRAM=m +# CONFIG_PS3_VRAM is not set CONFIG_MDIO_GPIO=m -CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL=m +# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set # CONFIG_DEBUG_GPIO is not set CONFIG_GPIO_PCA953X=m CONFIG_GPIO_PCF857X=m @@ -291,8 +274,6 @@ CONFIG_GPIO_PCF857X=m # CONFIG_USB_FHCI_HCD is not set # CONFIG_FHCI_DEBUG is not set -# CONFIG_DRM_RADEON_KMS is not set - # CONFIG_AMIGAONE is not set CONFIG_PPC_OF_BOOT_TRAMPOLINE=y @@ -313,20 +294,20 @@ CONFIG_SWIOTLB=y CONFIG_PPC_DISABLE_WERROR=y -CONFIG_XILINX_LL_TEMAC=m -CONFIG_XILINX_EMACLITE=m +# CONFIG_XILINX_LL_TEMAC is not set +# CONFIG_XILINX_EMACLITE is not set CONFIG_GPIO_WM831X=m # CONFIG_GPIO_LANGWELL is not set # CONFIG_GPIO_UCB1400 is not set -CONFIG_EDAC_MPC85XX=m +# CONFIG_EDAC_MPC85XX is not set CONFIG_NR_IRQS=512 CONFIG_SPARSE_IRQ=y -CONFIG_PPC_MPC5200_LPBFIFO=m -CONFIG_CAN_MSCAN=m -CONFIG_CAN_MPC5XXX=m +# CONFIG_PPC_MPC5200_LPBFIFO is not set +# CONFIG_CAN_MSCAN is not set +# CONFIG_CAN_MPC5XXX is not set CONFIG_PATA_MACIO=m CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m # CONFIG_PMIC_ADP5520 is not set @@ -347,7 +328,7 @@ CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m # CONFIG_PPC_MPC512x is not set # CONFIG_RTC_DRV_MPC5121 is not set -CONFIG_MPC512X_DMA=m +# CONFIG_MPC512X_DMA is not set CONFIG_KVM_GUEST=y @@ -358,15 +339,17 @@ CONFIG_I2C_MPC=m 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 +# CONFIG_CRYPTO_DEV_FSL_CAAM is not set # CONFIG_GPIO_GENERIC_PLATFORM is not set # CONFIG_GPIO_MCP23S08 is not set +# CONFIG_CAN_FLEXCAN is not set +# CONFIG_NET_VENDOR_XILINX is not set +# CONFIG_PPC_EPAPR_HV_BYTECHAN is not set +# CONFIG_IBM_EMAC is not set +# CONFIG_NET_VENDOR_PASEMI is not set +# CONFIG_NET_VENDOR_TOSHIBA is not set + # Disable btrfs until it is shown to work with 64k pages (rhbz 747079) # CONFIG_BTRFS_FS is not set diff --git a/config-powerpc32-generic b/config-powerpc32-generic index 31c399e65..e856b9ff0 100644 --- a/config-powerpc32-generic +++ b/config-powerpc32-generic @@ -7,17 +7,17 @@ CONFIG_PPC32=y CONFIG_CPU_FREQ_PMAC=y CONFIG_PPC_CHRP=y CONFIG_PPC_PMAC=y -CONFIG_PPC_MPC52xx=y +# CONFIG_PPC_MPC52xx is not set CONFIG_PPC_PREP=y # CONFIG_PPC_MPC5200_SIMPLE is not set -CONFIG_SATA_FSL=m +# CONFIG_SATA_FSL is not set # CONFIG_SATA_NV is not set # busted in .28git1 # ERROR: "cacheable_memzero" [drivers/net/gianfar_driver.ko] undefined! # CONFIG_GIANFAR is not set -CONFIG_USB_EHCI_FSL=y +# CONFIG_USB_EHCI_FSL is not set CONFIG_PMAC_APM_EMU=y CONFIG_PMAC_BACKLIGHT=y @@ -41,6 +41,7 @@ CONFIG_ADB_PMU_LED=y CONFIG_ADB_PMU_LED_IDE=y CONFIG_PMAC_MEDIABAY=y +CONFIG_NET_VENDOR_APPLE=y CONFIG_BMAC=m CONFIG_MACE=m # CONFIG_MACE_AAUI_PORT is not set @@ -72,24 +73,20 @@ CONFIG_BRIQ_PANEL=m # CONFIG_ATA_PIIX is not set # CONFIG_PATA_AMD is not set # CONFIG_PATA_ATIIXP is not set -CONFIG_PATA_MPC52xx=m +# CONFIG_PATA_MPC52xx is not set # CONFIG_PATA_MPIIX is not set # CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_OPTI is not set # CONFIG_PATA_SERVERWORKS is not set -CONFIG_SERIAL_MPC52xx=y -CONFIG_SERIAL_MPC52xx_CONSOLE=y -CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200 +# CONFIG_SERIAL_MPC52xx is not set # CONFIG_MPC5200_WDT is not set CONFIG_8xxx_WDT=m CONFIG_GEF_WDT=m -CONFIG_PPC_MPC5200_BUGFIX=y -CONFIG_FEC_MPC52xx=m +# CONFIG_PPC_MPC5200_BUGFIX is not set +# CONFIG_NET_VENDOR_FREESCALE is not set #CHECK: This may later become a tristate. -CONFIG_FEC_MPC52xx_MDIO=y -CONFIG_PPC_MPC5200_GPIO=y CONFIG_MDIO_GPIO=m CONFIG_SERIAL_OF_PLATFORM=y @@ -144,26 +141,28 @@ CONFIG_VIRTUALIZATION=y CONFIG_SND_ISA=y CONFIG_CRYPTO_DEV_TALITOS=m -CONFIG_FSL_EMB_PERFMON=y -CONFIG_MPC8272_ADS=y -CONFIG_PQ2FADS=y -CONFIG_EP8248E=y -CONFIG_MPC830x_RDB=y -CONFIG_MPC831x_RDB=y -CONFIG_MPC832x_MDS=y -CONFIG_MPC832x_RDB=y -CONFIG_MPC834x_MDS=y -CONFIG_MPC834x_ITX=y -CONFIG_MPC836x_MDS=y -CONFIG_MPC836x_RDK=y -CONFIG_MPC837x_MDS=y -CONFIG_MPC837x_RDB=y -CONFIG_SBC834x=y -CONFIG_ASP834x=y -CONFIG_KMETER1=y -CONFIG_MPC8641_HPCN=y -CONFIG_SBC8641D=y -CONFIG_MPC8610_HPCD=y +# CONFIG_FSL_EMB_PERFMON is not set +# CONFIG_MPC8272_ADS is not set +# CONFIG_PQ2FADS is not set +# CONFIG_EP8248E is not set +# CONFIG_MPC830x_RDB is not set +# CONFIG_MPC831x_RDB is not set +# CONFIG_MPC832x_MDS is not set +# CONFIG_MPC832x_RDB is not set +# CONFIG_MPC834x_MDS is not set +# CONFIG_MPC834x_ITX is not set +# CONFIG_MPC836x_MDS is not set +# CONFIG_MPC836x_RDK is not set +# CONFIG_MPC837x_MDS is not set +# CONFIG_MPC837x_RDB is not set +# CONFIG_SBC834x is not set +# CONFIG_ASP834x is not set +# CONFIG_KMETER1 is not set +# CONFIG_MPC8641_HPCN is not set +# CONFIG_SBC8641D is not set +# CONFIG_MPC8610_HPCD is not set +# CONFIG_FSL_LBC is not set +# CONFIG_MTD_NAND_FSL_UPM is not set # CONFIG_USB_MUSB_HDRC is not set @@ -172,8 +171,6 @@ CONFIG_MPC8610_HPCD=y # drivers/mtd/maps/sbc8240.c:172: warning: passing argument 1 of 'simple_map_init' from incompatible pointer type # drivers/mtd/maps/sbc8240.c:177: error: 'struct mtd_info' has no member named 'module' -CONFIG_MTD_NAND_FSL_UPM=m - CONFIG_RCU_FANOUT=32 CONFIG_PERF_COUNTERS=y @@ -185,3 +182,4 @@ CONFIG_KVM_BOOK3S_32=m # CONFIG_SCSI_QLA_ISCSI is not set CONFIG_BATTERY_PMU=m + diff --git a/config-powerpc64 b/config-powerpc64 index ad3edf171..42b501675 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -2,42 +2,23 @@ CONFIG_WINDFARM_PM81=y CONFIG_WINDFARM_PM91=y CONFIG_WINDFARM_PM121=y CONFIG_PPC_PMAC64=y -CONFIG_PPC_MAPLE=y -CONFIG_PPC_CELL=y -CONFIG_PPC_IBM_CELL_BLADE=y +# CONFIG_PPC_MAPLE is not set +# CONFIG_PPC_CELL is not set +# CONFIG_PPC_IBM_CELL_BLADE is not set CONFIG_PPC_ISERIES=y CONFIG_PPC_PSERIES=y CONFIG_PPC_PMAC=y -CONFIG_PPC_PASEMI=y +CONFIG_PPC_POWERNV=y +CONFIG_PPC_POWERNV_RTAS=y +# CONFIG_PPC_PASEMI is not set # CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE is not set -CONFIG_PPC_PS3=y -CONFIG_PPC_CELLEB=y -CONFIG_PPC_CELL_QPACE=y -CONFIG_PS3_HTAB_SIZE=20 -# CONFIG_PS3_DYNAMIC_DMA is not set -CONFIG_PS3_ADVANCED=y -CONFIG_PS3_HTAB_SIZE=20 -# CONFIG_PS3_DYNAMIC_DMA is not set -CONFIG_PS3_VUART=y -CONFIG_PS3_PS3AV=y -CONFIG_PS3_STORAGE=m -CONFIG_PS3_DISK=m -CONFIG_PS3_ROM=m -CONFIG_PS3_FLASH=m -CONFIG_PS3_LPM=y -CONFIG_SND_PS3=m -CONFIG_SND_PS3_DEFAULT_START_DELAY=1000 -CONFIG_GELIC_NET=m -CONFIG_GELIC_WIRELESS=y -CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE=y -CONFIG_CBE_THERM=m -CONFIG_CBE_CPUFREQ=m -CONFIG_CBE_CPUFREQ_PMI=m -CONFIG_CBE_CPUFREQ_PMI_ENABLE=y +# CONFIG_PPC_PS3 is not set +# CONFIG_PPC_CELLEB is not set +# CONFIG_PPC_CELL_QPACE is not set CONFIG_PMAC_RACKMETER=m CONFIG_IBMEBUS=y -CONFIG_SPU_FS=m CONFIG_RTAS_FLASH=y +# CONFIG_UDBG_RTAS_CONSOLE is not set CONFIG_PPC_SPLPAR=y CONFIG_SCANLOG=y CONFIG_LPARCFG=y @@ -60,10 +41,9 @@ CONFIG_CPU_FREQ_PMAC64=y CONFIG_SCSI_IPR=m CONFIG_SCSI_IPR_TRACE=y CONFIG_SCSI_IPR_DUMP=y -CONFIG_SPIDER_NET=m CONFIG_HVC_RTAS=y CONFIG_HVC_ISERIES=y -CONFIG_CBE_RAS=y +CONFIG_HVC_OPAL=y # iSeries device drivers # @@ -75,19 +55,13 @@ CONFIG_VIOTAPE=m CONFIG_PASEMI_MAC=m CONFIG_SERIAL_OF_PLATFORM=m -CONFIG_PPC_PASEMI_IOMMU=y CONFIG_SERIAL_TXX9=y CONFIG_SERIAL_TXX9_NR_UARTS=6 CONFIG_SERIAL_TXX9_CONSOLE=y CONFIG_HVC_BEAT=y -CONFIG_FB_PS3=y -CONFIG_FB_PS3_DEFAULT_SIZE_M=18 - CONFIG_PPC_PMI=m -CONFIG_PS3_SYS_MANAGER=y -# CONFIG_BLK_DEV_CELLEB is not set CONFIG_PATA_SCC=m @@ -95,7 +69,7 @@ CONFIG_APM_EMULATION=m CONFIG_PPC64=y CONFIG_VIRT_CPU_ACCOUNTING=y -CONFIG_NR_CPUS=128 +CONFIG_NR_CPUS=1024 # CONFIG_FB_PLATINUM is not set # CONFIG_FB_VALKYRIE is not set # CONFIG_FB_CT65550 is not set @@ -138,19 +112,9 @@ CONFIG_SECCOMP=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y # CONFIG_BLK_DEV_PLATFORM is not set -CONFIG_IBM_NEW_EMAC=m -CONFIG_IBM_NEW_EMAC_RXB=128 -CONFIG_IBM_NEW_EMAC_TXB=64 -CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32 -CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256 -CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0 -# CONFIG_IBM_NEW_EMAC_DEBUG is not set # CONFIG_VIRQ_DEBUG is not set -CONFIG_ELECTRA_CF=m -CONFIG_MTD_NAND_PASEMI=m -CONFIG_EDAC_CELL=m CONFIG_EDAC_CPC925=m CONFIG_FRAME_WARN=2048 @@ -164,14 +128,6 @@ CONFIG_SCSI_IBMVFC=m # CONFIG_SCSI_IBMVFC_TRACE is not set CONFIG_IBM_BSR=m -CONFIG_SERIO_XILINX_XPS_PS2=m - -CONFIG_PPC_IBM_CELL_RESETBUTTON=y -CONFIG_PPC_IBM_CELL_POWERBUTTON=m -CONFIG_CBE_CPUFREQ_SPU_GOVERNOR=m - -CONFIG_RTC_DRV_PS3=y - CONFIG_CRASH_DUMP=y CONFIG_RELOCATABLE=y @@ -202,4 +158,3 @@ CONFIG_IO_EVENT_IRQ=y CONFIG_HW_RANDOM_AMD=m CONFIG_BPF_JIT=y -CONFIG_CPU_FREQ_MAPLE=y diff --git a/config-s390x b/config-s390x index 5251b5b32..f03942191 100644 --- a/config-s390x +++ b/config-s390x @@ -237,3 +237,5 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_WARN_DYNAMIC_STACK is not set CONFIG_CRYPTO_GHASH_S390=m +CONFIG_NET_CORE=y +CONFIG_ETHERNET=y diff --git a/config-sparc64-generic b/config-sparc64-generic index d95a9b1ed..e9b66f6d6 100644 --- a/config-sparc64-generic +++ b/config-sparc64-generic @@ -8,18 +8,7 @@ CONFIG_HZ=100 CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_TABLE=m -CONFIG_CPU_FREQ_DEBUG=y -# CONFIG_CPU_FREQ_STAT is not set -# CONFIG_CPU_FREQ_STAT_DETAILS is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=m -CONFIG_CPU_FREQ_GOV_USERSPACE=m -CONFIG_CPU_FREQ_GOV_ONDEMAND=m -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m + CONFIG_US3_FREQ=m CONFIG_US2E_FREQ=m @@ -54,6 +43,7 @@ CONFIG_I2C_ALI1535=m # CONFIG_VGASTATE is not set # CONFIG_FB_DDC is not set # CONFIG_FB_BW2 is not set +# CONFIG_FB_GRVGA is not set CONFIG_FB_CG3=y CONFIG_FB_CG6=y # CONFIG_FB_RIVA is not set diff --git a/config-x86-32-generic b/config-x86-32-generic index caeae9398..3b55ae521 100644 --- a/config-x86-32-generic +++ b/config-x86-32-generic @@ -57,9 +57,6 @@ CONFIG_FB_GEODE_GX=y # CONFIG_PCI_GOMMCONFIG is not set CONFIG_PCI_GOANY=y -# FIXME: wtf? "x86 specific drivers" -CONFIG_PCMCIA_FDOMAIN=m -CONFIG_SCSI_FUTURE_DOMAIN=m CONFIG_IBM_ASM=m # @@ -138,8 +135,6 @@ CONFIG_CRYPTO_TWOFISH_586=m CONFIG_VIDEO_CAFE_CCIC=m -CONFIG_VMI=y - CONFIG_XEN_MAX_DOMAIN_MEMORY=8 CONFIG_MTD_NAND_CAFE=m @@ -155,6 +150,7 @@ CONFIG_OLPC_XO1_PM=y CONFIG_OLPC_XO15_SCI=y CONFIG_OLPC_XO1_RTC=y CONFIG_OLPC_XO1_SCI=y +# CONFIG_ALIX is not set # staging # CONFIG_FB_OLPC_DCON is not set @@ -204,3 +200,6 @@ CONFIG_I2O_EXT_ADAPTEC=y CONFIG_I2O_CONFIG_OLD_IOCTL=y CONFIG_I2O_BUS=m +# CONFIG_EDAC_SBRIDGE is not set + +# CONFIG_X86_WANT_INTEL_MID is not set diff --git a/config-x86-generic b/config-x86-generic index 23aecbbef..fec30ea87 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -36,10 +36,10 @@ CONFIG_FB_EFI=y # FIXME: 32bit only? # CONFIG_FB_N411 is not set -CONFIG_DMAR=y +CONFIG_INTEL_IOMMU=y CONFIG_DMAR_BROKEN_GFX_WA=y -CONFIG_DMAR_FLOPPY_WA=y -# CONFIG_DMAR_DEFAULT_ON is not set +CONFIG_INTEL_IOMMU_FLOPPY_WA=y +# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set CONFIG_SCSI_ADVANSYS=m CONFIG_SECCOMP=y @@ -59,7 +59,6 @@ CONFIG_DEBUG_STACKOVERFLOW=y CONFIG_ACPI=y CONFIG_ACPI_AC=y # CONFIG_ACPI_ASUS is not set -CONFIG_ACPI_PROCFS_POWER=y CONFIG_ACPI_BATTERY=y CONFIG_ACPI_BUTTON=y CONFIG_ACPI_CONTAINER=m @@ -73,6 +72,8 @@ CONFIG_ACPI_SLEEP=y CONFIG_ACPI_THERMAL=y CONFIG_ACPI_TOSHIBA=m CONFIG_ACPI_VIDEO=m +# FIXME: Next two are deprecated. Remove them when they disappear upstream +# CONFIG_ACPI_PROCFS_POWER is not set # CONFIG_ACPI_PROC_EVENT is not set CONFIG_PNPACPI=y CONFIG_ACPI_PROCESSOR_AGGREGATOR=m @@ -85,10 +86,10 @@ CONFIG_ACPI_APEI_MEMORY_FAILURE=y CONFIG_ACPI_IPMI=m CONFIG_ACPI_CUSTOM_METHOD=m -CONFIG_X86_ACPI_CPUFREQ=m -CONFIG_X86_PCC_CPUFREQ=m -CONFIG_X86_POWERNOW_K8=m -CONFIG_X86_P4_CLOCKMOD=m +CONFIG_X86_ACPI_CPUFREQ=y +CONFIG_X86_PCC_CPUFREQ=y +CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_P4_CLOCKMOD=y # CONFIG_X86_SPEEDSTEP_CENTRINO is not set # @@ -227,8 +228,7 @@ CONFIG_PARAVIRT=y CONFIG_PARAVIRT_TIME_ACCOUNTING=y # CONFIG_PARAVIRT_DEBUG is not set -# PARAVIRT_SPINLOCKS has a 5% perf hit -# FIXME: Still true ? References? +# PARAVIRT_SPINLOCKS has a 5% perf hit on native hw (see kconfig) # CONFIG_PARAVIRT_SPINLOCKS is not set CONFIG_KVM_CLOCK=y @@ -310,7 +310,7 @@ CONFIG_HP_ILO=m CONFIG_BACKLIGHT_APPLE=m -# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set +CONFIG_X86_CHECK_BIOS_CORRUPTION=y # CONFIG_CMDLINE_BOOL is not set @@ -381,3 +381,6 @@ CONFIG_HP_ACCEL=m CONFIG_SCHED_SMT=y CONFIG_CC_STACKPROTECTOR=y CONFIG_RELOCATABLE=y + +# CONFIG_HYPERV is not set + diff --git a/config-x86_64-generic b/config-x86_64-generic index 693c3a8b6..f5b440a73 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -22,8 +22,7 @@ CONFIG_AMD_IOMMU=y CONFIG_AMD_IOMMU_STATS=y # CONFIG_IOMMU_DEBUG is not set CONFIG_SWIOTLB=y -CONFIG_CALGARY_IOMMU=y -CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y +# CONFIG_CALGARY_IOMMU is not set CONFIG_KEXEC_JUMP=y @@ -44,6 +43,9 @@ CONFIG_CRYPTO_AES_X86_64=y CONFIG_CRYPTO_TWOFISH_X86_64=m CONFIG_CRYPTO_SALSA20_X86_64=m CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m +CONFIG_CRYPTO_SHA1_SSSE3=m +CONFIG_CRYPTO_BLOWFISH_X86_64=m +CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=m # CONFIG_I2C_ALI1535 is not set # CONFIG_I2C_ALI1563 is not set @@ -53,6 +55,7 @@ CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m CONFIG_EDAC_AMD64=m # CONFIG_EDAC_AMD64_ERROR_INJECTION is not set +CONFIG_EDAC_SBRIDGE=m # CONFIG_PC8736x_GPIO is not set @@ -62,8 +65,8 @@ CONFIG_SPARSEMEM=y CONFIG_HAVE_MEMORY_PRESENT=y CONFIG_SPARSEMEM_EXTREME=y CONFIG_SPARSEMEM_VMEMMAP=y -CONFIG_MEMORY_HOTPLUG=y -CONFIG_MEMORY_HOTREMOVE=y +# CONFIG_MEMORY_HOTPLUG is not set +# CONFIG_MEMORY_HOTREMOVE is not set # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_RZ1000 is not set @@ -79,7 +82,7 @@ CONFIG_SGI_GRU=m # CONFIG_VIDEO_CAFE_CCIC is not set -CONFIG_XEN_MAX_DOMAIN_MEMORY=32 +CONFIG_XEN_MAX_DOMAIN_MEMORY=128 # CONFIG_XEN_BALLOON_MEMORY_HOTPLUG is not set CONFIG_XEN_DEV_EVTCHN=m CONFIG_XEN_SYS_HYPERVISOR=y @@ -95,7 +98,7 @@ CONFIG_DIRECT_GBPAGES=y CONFIG_X86_MPPARSE=y CONFIG_I7300_IDLE=m -CONFIG_INTR_REMAP=y +CONFIG_IRQ_REMAP=y CONFIG_X86_X2APIC=y CONFIG_SPARSE_IRQ=y diff --git a/drm-i915-sdvo-lvds-is-digital.patch b/drm-i915-sdvo-lvds-is-digital.patch deleted file mode 100644 index 68d0c4b31..000000000 --- a/drm-i915-sdvo-lvds-is-digital.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 64015d6d16d7ed5b6ffcec95dc13e8694bd2a4d6 Mon Sep 17 00:00:00 2001 -From: Chris Wilson -Date: Mon, 20 Jun 2011 22:35:24 +0100 -Subject: [PATCH] drm/i915/sdvo: Include LVDS panels for the IS_DIGITAL check - -We were checking whether the supplied edid matched the connector it was -read from. We do this in case a DDC read returns an EDID for another -device on a multifunction or otherwise interesting card. However, we -failed to include LVDS as a digital device and so rejecting an otherwise -valid EDID. - -Fixes the detection of the secondary SDVO LVDS panel on the Libretto -W105. - -Signed-off-by: Chris Wilson ---- - drivers/gpu/drm/i915/intel_sdvo.c | 28 ++++++++++++++++++++-------- - 1 files changed, 20 insertions(+), 8 deletions(-) - -diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c -index f96975c..26eff9f 100644 ---- a/drivers/gpu/drm/i915/intel_sdvo.c -+++ b/drivers/gpu/drm/i915/intel_sdvo.c -@@ -49,6 +49,7 @@ - #define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK) - #define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK) - #define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK)) -+#define IS_DIGITAL(c) (c->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK)) - - - static const char *tv_format_names[] = { -@@ -1363,6 +1364,18 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) - return status; - } - -+static bool -+intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo, -+ struct edid *edid) -+{ -+ bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); -+ bool connector_is_digital = !!IS_DIGITAL(sdvo); -+ -+ DRM_DEBUG_KMS("connector_is_digital? %d, monitor_is_digital? %d\n", -+ connector_is_digital, monitor_is_digital); -+ return connector_is_digital == monitor_is_digital; -+} -+ - static enum drm_connector_status - intel_sdvo_detect(struct drm_connector *connector, bool force) - { -@@ -1407,10 +1420,12 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) - if (edid == NULL) - edid = intel_sdvo_get_analog_edid(connector); - if (edid != NULL) { -- if (edid->input & DRM_EDID_INPUT_DIGITAL) -- ret = connector_status_disconnected; -- else -+ if (intel_sdvo_connector_matches_edid(intel_sdvo_connector, -+ edid)) - ret = connector_status_connected; -+ else -+ ret = connector_status_disconnected; -+ - connector->display_info.raw_edid = NULL; - kfree(edid); - } else -@@ -1451,11 +1466,8 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) - edid = intel_sdvo_get_analog_edid(connector); - - if (edid != NULL) { -- struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); -- bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); -- bool connector_is_digital = !!IS_TMDS(intel_sdvo_connector); -- -- if (connector_is_digital == monitor_is_digital) { -+ if (intel_sdvo_connector_matches_edid(to_intel_sdvo_connector(connector), -+ edid)) { - drm_mode_connector_update_edid_property(connector, edid); - drm_add_edid_modes(connector, edid); - } --- -1.7.5.4 - diff --git a/drm-lower-severity-radeon-lockup.diff b/drm-lower-severity-radeon-lockup.diff deleted file mode 100644 index 1302c92ea..000000000 --- a/drm-lower-severity-radeon-lockup.diff +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c -index 7fd4e3e..a488b50 100644 ---- a/drivers/gpu/drm/radeon/radeon_fence.c -+++ b/drivers/gpu/drm/radeon/radeon_fence.c -@@ -263,7 +263,7 @@ retry: - */ - if (seq == rdev->fence_drv.last_seq && radeon_gpu_is_lockup(rdev)) { - /* good news we believe it's a lockup */ -- WARN(1, "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n", -+ printk(KERN_WARNING "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n", - fence->seq, seq); - /* FIXME: what should we do ? marking everyone - * as signaled for now diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index cd9bded11..e69de29bb 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -1,8526 +0,0 @@ -diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile -index 0583677..35ef5b1 100644 ---- a/drivers/gpu/drm/nouveau/Makefile -+++ b/drivers/gpu/drm/nouveau/Makefile -@@ -21,16 +21,17 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ - nv40_grctx.o nv50_grctx.o nvc0_grctx.o \ - nv84_crypt.o \ - nva3_copy.o nvc0_copy.o \ -- nv40_mpeg.o nv50_mpeg.o \ -+ nv31_mpeg.o nv50_mpeg.o \ - nv04_instmem.o nv50_instmem.o nvc0_instmem.o \ -- nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \ -- nv50_cursor.o nv50_display.o \ - nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ - nv04_crtc.o nv04_display.o nv04_cursor.o \ -+ nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \ -+ nv50_cursor.o nv50_display.o \ -+ nvd0_display.o \ - nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o \ - nv10_gpio.o nv50_gpio.o \ - nv50_calc.o \ -- nv04_pm.o nv50_pm.o nva3_pm.o \ -+ nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \ - nv50_vram.o nvc0_vram.o \ - nv50_vm.o nvc0_vm.o - -diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c -index 00a55df..fa22b28 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_backlight.c -+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c -@@ -37,8 +37,10 @@ - #include "nouveau_drv.h" - #include "nouveau_drm.h" - #include "nouveau_reg.h" -+#include "nouveau_encoder.h" - --static int nv40_get_intensity(struct backlight_device *bd) -+static int -+nv40_get_intensity(struct backlight_device *bd) - { - struct drm_device *dev = bl_get_data(bd); - int val = (nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK) -@@ -47,7 +49,8 @@ static int nv40_get_intensity(struct backlight_device *bd) - return val; - } - --static int nv40_set_intensity(struct backlight_device *bd) -+static int -+nv40_set_intensity(struct backlight_device *bd) - { - struct drm_device *dev = bl_get_data(bd); - int val = bd->props.brightness; -@@ -65,30 +68,8 @@ static const struct backlight_ops nv40_bl_ops = { - .update_status = nv40_set_intensity, - }; - --static int nv50_get_intensity(struct backlight_device *bd) --{ -- struct drm_device *dev = bl_get_data(bd); -- -- return nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT); --} -- --static int nv50_set_intensity(struct backlight_device *bd) --{ -- struct drm_device *dev = bl_get_data(bd); -- int val = bd->props.brightness; -- -- nv_wr32(dev, NV50_PDISPLAY_SOR_BACKLIGHT, -- val | NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE); -- return 0; --} -- --static const struct backlight_ops nv50_bl_ops = { -- .options = BL_CORE_SUSPENDRESUME, -- .get_brightness = nv50_get_intensity, -- .update_status = nv50_set_intensity, --}; -- --static int nouveau_nv40_backlight_init(struct drm_connector *connector) -+static int -+nv40_backlight_init(struct drm_connector *connector) - { - struct drm_device *dev = connector->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -@@ -113,34 +94,129 @@ static int nouveau_nv40_backlight_init(struct drm_connector *connector) - return 0; - } - --static int nouveau_nv50_backlight_init(struct drm_connector *connector) -+static int -+nv50_get_intensity(struct backlight_device *bd) -+{ -+ struct nouveau_encoder *nv_encoder = bl_get_data(bd); -+ struct drm_device *dev = nv_encoder->base.base.dev; -+ int or = nv_encoder->or; -+ u32 div = 1025; -+ u32 val; -+ -+ val = nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(or)); -+ val &= NV50_PDISP_SOR_PWM_CTL_VAL; -+ return ((val * 100) + (div / 2)) / div; -+} -+ -+static int -+nv50_set_intensity(struct backlight_device *bd) -+{ -+ struct nouveau_encoder *nv_encoder = bl_get_data(bd); -+ struct drm_device *dev = nv_encoder->base.base.dev; -+ int or = nv_encoder->or; -+ u32 div = 1025; -+ u32 val = (bd->props.brightness * div) / 100; -+ -+ nv_wr32(dev, NV50_PDISP_SOR_PWM_CTL(or), -+ NV50_PDISP_SOR_PWM_CTL_NEW | val); -+ return 0; -+} -+ -+static const struct backlight_ops nv50_bl_ops = { -+ .options = BL_CORE_SUSPENDRESUME, -+ .get_brightness = nv50_get_intensity, -+ .update_status = nv50_set_intensity, -+}; -+ -+static int -+nva3_get_intensity(struct backlight_device *bd) -+{ -+ struct nouveau_encoder *nv_encoder = bl_get_data(bd); -+ struct drm_device *dev = nv_encoder->base.base.dev; -+ int or = nv_encoder->or; -+ u32 div, val; -+ -+ div = nv_rd32(dev, NV50_PDISP_SOR_PWM_DIV(or)); -+ val = nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(or)); -+ val &= NVA3_PDISP_SOR_PWM_CTL_VAL; -+ if (div && div >= val) -+ return ((val * 100) + (div / 2)) / div; -+ -+ return 100; -+} -+ -+static int -+nva3_set_intensity(struct backlight_device *bd) -+{ -+ struct nouveau_encoder *nv_encoder = bl_get_data(bd); -+ struct drm_device *dev = nv_encoder->base.base.dev; -+ int or = nv_encoder->or; -+ u32 div, val; -+ -+ div = nv_rd32(dev, NV50_PDISP_SOR_PWM_DIV(or)); -+ val = (bd->props.brightness * div) / 100; -+ if (div) { -+ nv_wr32(dev, NV50_PDISP_SOR_PWM_CTL(or), val | -+ NV50_PDISP_SOR_PWM_CTL_NEW | -+ NVA3_PDISP_SOR_PWM_CTL_UNK); -+ return 0; -+ } -+ -+ return -EINVAL; -+} -+ -+static const struct backlight_ops nva3_bl_ops = { -+ .options = BL_CORE_SUSPENDRESUME, -+ .get_brightness = nva3_get_intensity, -+ .update_status = nva3_set_intensity, -+}; -+ -+static int -+nv50_backlight_init(struct drm_connector *connector) - { - struct drm_device *dev = connector->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_encoder *nv_encoder; - struct backlight_properties props; - struct backlight_device *bd; -+ const struct backlight_ops *ops; -+ -+ nv_encoder = find_encoder(connector, OUTPUT_LVDS); -+ if (!nv_encoder) { -+ nv_encoder = find_encoder(connector, OUTPUT_DP); -+ if (!nv_encoder) -+ return -ENODEV; -+ } - -- if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT)) -+ if (!nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(nv_encoder->or))) - return 0; - -+ if (dev_priv->chipset <= 0xa0 || -+ dev_priv->chipset == 0xaa || -+ dev_priv->chipset == 0xac) -+ ops = &nv50_bl_ops; -+ else -+ ops = &nva3_bl_ops; -+ - memset(&props, 0, sizeof(struct backlight_properties)); - props.type = BACKLIGHT_RAW; -- props.max_brightness = 1025; -- bd = backlight_device_register("nv_backlight", &connector->kdev, dev, -- &nv50_bl_ops, &props); -+ props.max_brightness = 100; -+ bd = backlight_device_register("nv_backlight", &connector->kdev, -+ nv_encoder, ops, &props); - if (IS_ERR(bd)) - return PTR_ERR(bd); - - dev_priv->backlight = bd; -- bd->props.brightness = nv50_get_intensity(bd); -+ bd->props.brightness = bd->ops->get_brightness(bd); - backlight_update_status(bd); - return 0; - } - --int nouveau_backlight_init(struct drm_connector *connector) -+int -+nouveau_backlight_init(struct drm_device *dev) - { -- struct drm_device *dev = connector->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct drm_connector *connector; - - #ifdef CONFIG_ACPI - if (acpi_video_backlight_support()) { -@@ -150,21 +226,28 @@ int nouveau_backlight_init(struct drm_connector *connector) - } - #endif - -- switch (dev_priv->card_type) { -- case NV_40: -- return nouveau_nv40_backlight_init(connector); -- case NV_50: -- return nouveau_nv50_backlight_init(connector); -- default: -- break; -+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -+ if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && -+ connector->connector_type != DRM_MODE_CONNECTOR_eDP) -+ continue; -+ -+ switch (dev_priv->card_type) { -+ case NV_40: -+ return nv40_backlight_init(connector); -+ case NV_50: -+ return nv50_backlight_init(connector); -+ default: -+ break; -+ } - } - -+ - return 0; - } - --void nouveau_backlight_exit(struct drm_connector *connector) -+void -+nouveau_backlight_exit(struct drm_device *dev) - { -- struct drm_device *dev = connector->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - - if (dev_priv->backlight) { -diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c -index b311fab..032a820 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_bios.c -+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c -@@ -296,6 +296,11 @@ munge_reg(struct nvbios *bios, uint32_t reg) - if (dev_priv->card_type < NV_50) - return reg; - -+ if (reg & 0x80000000) { -+ BUG_ON(bios->display.crtc < 0); -+ reg += bios->display.crtc * 0x800; -+ } -+ - if (reg & 0x40000000) { - BUG_ON(!dcbent); - -@@ -304,7 +309,7 @@ munge_reg(struct nvbios *bios, uint32_t reg) - reg += 0x00000080; - } - -- reg &= ~0x60000000; -+ reg &= ~0xe0000000; - return reg; - } - -@@ -1174,22 +1179,19 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - * - */ - -- struct bit_displayport_encoder_table *dpe = NULL; - struct dcb_entry *dcb = bios->display.output; - struct drm_device *dev = bios->dev; - uint8_t cond = bios->data[offset + 1]; -- int dummy; -+ uint8_t *table, *entry; - - BIOSLOG(bios, "0x%04X: subop 0x%02X\n", offset, cond); - - if (!iexec->execute) - return 3; - -- dpe = nouveau_bios_dp_table(dev, dcb, &dummy); -- if (!dpe) { -- NV_ERROR(dev, "0x%04X: INIT_3A: no encoder table!!\n", offset); -+ table = nouveau_dp_bios_data(dev, dcb, &entry); -+ if (!table) - return 3; -- } - - switch (cond) { - case 0: -@@ -1203,7 +1205,7 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - break; - case 1: - case 2: -- if (!(dpe->unknown & cond)) -+ if (!(entry[5] & cond)) - iexec->execute = false; - break; - case 5: -@@ -3221,6 +3223,49 @@ init_8d(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - return 1; - } - -+static void -+init_gpio_unknv50(struct nvbios *bios, struct dcb_gpio_entry *gpio) -+{ -+ const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; -+ u32 r, s, v; -+ -+ /* Not a clue, needs de-magicing */ -+ r = nv50_gpio_ctl[gpio->line >> 4]; -+ s = (gpio->line & 0x0f); -+ v = bios_rd32(bios, r) & ~(0x00010001 << s); -+ switch ((gpio->entry & 0x06000000) >> 25) { -+ case 1: -+ v |= (0x00000001 << s); -+ break; -+ case 2: -+ v |= (0x00010000 << s); -+ break; -+ default: -+ break; -+ } -+ -+ bios_wr32(bios, r, v); -+} -+ -+static void -+init_gpio_unknvd0(struct nvbios *bios, struct dcb_gpio_entry *gpio) -+{ -+ u32 v, i; -+ -+ v = bios_rd32(bios, 0x00d610 + (gpio->line * 4)); -+ v &= 0xffffff00; -+ v |= (gpio->entry & 0x00ff0000) >> 16; -+ bios_wr32(bios, 0x00d610 + (gpio->line * 4), v); -+ -+ i = (gpio->entry & 0x1f000000) >> 24; -+ if (i) { -+ v = bios_rd32(bios, 0x00d640 + ((i - 1) * 4)); -+ v &= 0xffffff00; -+ v |= gpio->line; -+ bios_wr32(bios, 0x00d640 + ((i - 1) * 4), v); -+ } -+} -+ - static int - init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - { -@@ -3235,7 +3280,6 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - - struct drm_nouveau_private *dev_priv = bios->dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -- const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; - int i; - - if (dev_priv->card_type < NV_50) { -@@ -3248,33 +3292,20 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - - for (i = 0; i < bios->dcb.gpio.entries; i++) { - struct dcb_gpio_entry *gpio = &bios->dcb.gpio.entry[i]; -- uint32_t r, s, v; - - BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry); - - BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n", - offset, gpio->tag, gpio->state_default); -- if (bios->execute) -- pgpio->set(bios->dev, gpio->tag, gpio->state_default); - -- /* The NVIDIA binary driver doesn't appear to actually do -- * any of this, my VBIOS does however. -- */ -- /* Not a clue, needs de-magicing */ -- r = nv50_gpio_ctl[gpio->line >> 4]; -- s = (gpio->line & 0x0f); -- v = bios_rd32(bios, r) & ~(0x00010001 << s); -- switch ((gpio->entry & 0x06000000) >> 25) { -- case 1: -- v |= (0x00000001 << s); -- break; -- case 2: -- v |= (0x00010000 << s); -- break; -- default: -- break; -- } -- bios_wr32(bios, r, v); -+ if (!bios->execute) -+ continue; -+ -+ pgpio->set(bios->dev, gpio->tag, gpio->state_default); -+ if (dev_priv->card_type < NV_D0) -+ init_gpio_unknv50(bios, gpio); -+ else -+ init_gpio_unknvd0(bios, gpio); - } - - return 1; -@@ -3737,6 +3768,10 @@ parse_init_table(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - int count = 0, i, ret; - uint8_t id; - -+ /* catch NULL script pointers */ -+ if (offset == 0) -+ return 0; -+ - /* - * Loop until INIT_DONE causes us to break out of the loop - * (or until offset > bios length just in case... ) -@@ -4389,86 +4424,37 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b - return 0; - } - --static uint8_t * --bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent, -- uint16_t record, int record_len, int record_nr, -- bool match_link) -+/* BIT 'U'/'d' table encoder subtables have hashes matching them to -+ * a particular set of encoders. -+ * -+ * This function returns true if a particular DCB entry matches. -+ */ -+bool -+bios_encoder_match(struct dcb_entry *dcb, u32 hash) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nvbios *bios = &dev_priv->vbios; -- uint32_t entry; -- uint16_t table; -- int i, v; -+ if ((hash & 0x000000f0) != (dcb->location << 4)) -+ return false; -+ if ((hash & 0x0000000f) != dcb->type) -+ return false; -+ if (!(hash & (dcb->or << 16))) -+ return false; - -- switch (dcbent->type) { -+ switch (dcb->type) { - case OUTPUT_TMDS: - case OUTPUT_LVDS: - case OUTPUT_DP: -- break; -- default: -- match_link = false; -- break; -- } -- -- for (i = 0; i < record_nr; i++, record += record_len) { -- table = ROM16(bios->data[record]); -- if (!table) -- continue; -- entry = ROM32(bios->data[table]); -- -- if (match_link) { -- v = (entry & 0x00c00000) >> 22; -- if (!(v & dcbent->sorconf.link)) -- continue; -+ if (hash & 0x00c00000) { -+ if (!(hash & (dcb->sorconf.link << 22))) -+ return false; - } -- -- v = (entry & 0x000f0000) >> 16; -- if (!(v & dcbent->or)) -- continue; -- -- v = (entry & 0x000000f0) >> 4; -- if (v != dcbent->location) -- continue; -- -- v = (entry & 0x0000000f); -- if (v != dcbent->type) -- continue; -- -- return &bios->data[table]; -- } -- -- return NULL; --} -- --void * --nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent, -- int *length) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nvbios *bios = &dev_priv->vbios; -- uint8_t *table; -- -- if (!bios->display.dp_table_ptr) { -- NV_ERROR(dev, "No pointer to DisplayPort table\n"); -- return NULL; -- } -- table = &bios->data[bios->display.dp_table_ptr]; -- -- if (table[0] != 0x20 && table[0] != 0x21) { -- NV_ERROR(dev, "DisplayPort table version 0x%02x unknown\n", -- table[0]); -- return NULL; -+ default: -+ return true; - } -- -- *length = table[4]; -- return bios_output_config_match(dev, dcbent, -- bios->display.dp_table_ptr + table[1], -- table[2], table[3], table[0] >= 0x21); - } - - int --nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, -- uint32_t sub, int pxclk) -+nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, -+ struct dcb_entry *dcbent, int crtc) - { - /* - * The display script table is located by the BIT 'U' table. -@@ -4498,7 +4484,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, - uint8_t *table = &bios->data[bios->display.script_table_ptr]; - uint8_t *otable = NULL; - uint16_t script; -- int i = 0; -+ int i; - - if (!bios->display.script_table_ptr) { - NV_ERROR(dev, "No pointer to output script table\n"); -@@ -4550,30 +4536,33 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, - - NV_DEBUG_KMS(dev, "Searching for output entry for %d %d %d\n", - dcbent->type, dcbent->location, dcbent->or); -- otable = bios_output_config_match(dev, dcbent, table[1] + -- bios->display.script_table_ptr, -- table[2], table[3], table[0] >= 0x21); -+ for (i = 0; i < table[3]; i++) { -+ otable = ROMPTR(bios, table[table[1] + (i * table[2])]); -+ if (otable && bios_encoder_match(dcbent, ROM32(otable[0]))) -+ break; -+ } -+ - if (!otable) { - NV_DEBUG_KMS(dev, "failed to match any output table\n"); - return 1; - } - -- if (pxclk < -2 || pxclk > 0) { -+ if (pclk < -2 || pclk > 0) { - /* Try to find matching script table entry */ - for (i = 0; i < otable[5]; i++) { -- if (ROM16(otable[table[4] + i*6]) == sub) -+ if (ROM16(otable[table[4] + i*6]) == type) - break; - } - - if (i == otable[5]) { - NV_ERROR(dev, "Table 0x%04x not found for %d/%d, " - "using first\n", -- sub, dcbent->type, dcbent->or); -+ type, dcbent->type, dcbent->or); - i = 0; - } - } - -- if (pxclk == 0) { -+ if (pclk == 0) { - script = ROM16(otable[6]); - if (!script) { - NV_DEBUG_KMS(dev, "output script 0 not found\n"); -@@ -4581,9 +4570,9 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, - } - - NV_DEBUG_KMS(dev, "0x%04X: parsing output script 0\n", script); -- nouveau_bios_run_init_table(dev, script, dcbent); -+ nouveau_bios_run_init_table(dev, script, dcbent, crtc); - } else -- if (pxclk == -1) { -+ if (pclk == -1) { - script = ROM16(otable[8]); - if (!script) { - NV_DEBUG_KMS(dev, "output script 1 not found\n"); -@@ -4591,9 +4580,9 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, - } - - NV_DEBUG_KMS(dev, "0x%04X: parsing output script 1\n", script); -- nouveau_bios_run_init_table(dev, script, dcbent); -+ nouveau_bios_run_init_table(dev, script, dcbent, crtc); - } else -- if (pxclk == -2) { -+ if (pclk == -2) { - if (table[4] >= 12) - script = ROM16(otable[10]); - else -@@ -4604,31 +4593,31 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, - } - - NV_DEBUG_KMS(dev, "0x%04X: parsing output script 2\n", script); -- nouveau_bios_run_init_table(dev, script, dcbent); -+ nouveau_bios_run_init_table(dev, script, dcbent, crtc); - } else -- if (pxclk > 0) { -+ if (pclk > 0) { - script = ROM16(otable[table[4] + i*6 + 2]); - if (script) -- script = clkcmptable(bios, script, pxclk); -+ script = clkcmptable(bios, script, pclk); - if (!script) { - NV_DEBUG_KMS(dev, "clock script 0 not found\n"); - return 1; - } - - NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 0\n", script); -- nouveau_bios_run_init_table(dev, script, dcbent); -+ nouveau_bios_run_init_table(dev, script, dcbent, crtc); - } else -- if (pxclk < 0) { -+ if (pclk < 0) { - script = ROM16(otable[table[4] + i*6 + 4]); - if (script) -- script = clkcmptable(bios, script, -pxclk); -+ script = clkcmptable(bios, script, -pclk); - if (!script) { - NV_DEBUG_KMS(dev, "clock script 1 not found\n"); - return 1; - } - - NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 1\n", script); -- nouveau_bios_run_init_table(dev, script, dcbent); -+ nouveau_bios_run_init_table(dev, script, dcbent, crtc); - } - - return 0; -@@ -5478,14 +5467,6 @@ parse_bit_U_tbl_entry(struct drm_device *dev, struct nvbios *bios, - return 0; - } - --static int --parse_bit_displayport_tbl_entry(struct drm_device *dev, struct nvbios *bios, -- struct bit_entry *bitentry) --{ -- bios->display.dp_table_ptr = ROM16(bios->data[bitentry->offset]); -- return 0; --} -- - struct bit_table { - const char id; - int (* const parse_fn)(struct drm_device *, struct nvbios *, struct bit_entry *); -@@ -5559,7 +5540,6 @@ parse_bit_structure(struct nvbios *bios, const uint16_t bitoffset) - parse_bit_table(bios, bitoffset, &BIT_TABLE('L', lvds)); - parse_bit_table(bios, bitoffset, &BIT_TABLE('T', tmds)); - parse_bit_table(bios, bitoffset, &BIT_TABLE('U', U)); -- parse_bit_table(bios, bitoffset, &BIT_TABLE('d', displayport)); - - return 0; - } -@@ -5884,9 +5864,15 @@ parse_dcb_gpio_table(struct nvbios *bios) - } - - e->line = (e->entry & 0x0000001f) >> 0; -- e->state_default = (e->entry & 0x01000000) >> 24; -- e->state[0] = (e->entry & 0x18000000) >> 27; -- e->state[1] = (e->entry & 0x60000000) >> 29; -+ if (gpio[0] == 0x40) { -+ e->state_default = (e->entry & 0x01000000) >> 24; -+ e->state[0] = (e->entry & 0x18000000) >> 27; -+ e->state[1] = (e->entry & 0x60000000) >> 29; -+ } else { -+ e->state_default = (e->entry & 0x00000080) >> 7; -+ e->state[0] = (entry[4] >> 4) & 3; -+ e->state[1] = (entry[4] >> 6) & 3; -+ } - } - } - -@@ -6156,7 +6142,14 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, - } - case OUTPUT_DP: - entry->dpconf.sor.link = (conf & 0x00000030) >> 4; -- entry->dpconf.link_bw = (conf & 0x00e00000) >> 21; -+ switch ((conf & 0x00e00000) >> 21) { -+ case 0: -+ entry->dpconf.link_bw = 162000; -+ break; -+ default: -+ entry->dpconf.link_bw = 270000; -+ break; -+ } - switch ((conf & 0x0f000000) >> 24) { - case 0xf: - entry->dpconf.link_nr = 4; -@@ -6769,7 +6762,7 @@ uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev) - - void - nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, -- struct dcb_entry *dcbent) -+ struct dcb_entry *dcbent, int crtc) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; -@@ -6777,11 +6770,22 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, - - spin_lock_bh(&bios->lock); - bios->display.output = dcbent; -+ bios->display.crtc = crtc; - parse_init_table(bios, table, &iexec); - bios->display.output = NULL; - spin_unlock_bh(&bios->lock); - } - -+void -+nouveau_bios_init_exec(struct drm_device *dev, uint16_t table) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nvbios *bios = &dev_priv->vbios; -+ struct init_exec iexec = { true, false }; -+ -+ parse_init_table(bios, table, &iexec); -+} -+ - static bool NVInitVBIOS(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -@@ -6863,9 +6867,8 @@ nouveau_run_vbios_init(struct drm_device *dev) - - if (dev_priv->card_type >= NV_50) { - for (i = 0; i < bios->dcb.entries; i++) { -- nouveau_bios_run_display_table(dev, -- &bios->dcb.entry[i], -- 0, 0); -+ nouveau_bios_run_display_table(dev, 0, 0, -+ &bios->dcb.entry[i], -1); - } - } - -diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h -index 050c314..8adb69e 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_bios.h -+++ b/drivers/gpu/drm/nouveau/nouveau_bios.h -@@ -289,8 +289,8 @@ struct nvbios { - - struct { - struct dcb_entry *output; -+ int crtc; - uint16_t script_table_ptr; -- uint16_t dp_table_ptr; - } display; - - struct { -diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c -index 890d50e..7226f41 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_bo.c -+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c -@@ -956,7 +956,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) - break; - } - -- if (dev_priv->card_type == NV_C0) -+ if (dev_priv->card_type >= NV_C0) - page_shift = node->page_shift; - else - page_shift = 12; -diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c -index 0e3241c..bb6ec9e 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_channel.c -+++ b/drivers/gpu/drm/nouveau/nouveau_channel.c -@@ -412,13 +412,17 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, - return ret; - init->channel = chan->id; - -- if (chan->dma.ib_max) -- init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM | -- NOUVEAU_GEM_DOMAIN_GART; -- else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM) -+ if (nouveau_vram_pushbuf == 0) { -+ if (chan->dma.ib_max) -+ init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM | -+ NOUVEAU_GEM_DOMAIN_GART; -+ else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM) -+ init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM; -+ else -+ init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART; -+ } else { - init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM; -- else -- init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART; -+ } - - if (dev_priv->card_type < NV_C0) { - init->subchan[0].handle = NvM2MF; -diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c -index 939d4df..e0d275e 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_connector.c -+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c -@@ -39,7 +39,7 @@ - - static void nouveau_connector_hotplug(void *, int); - --static struct nouveau_encoder * -+struct nouveau_encoder * - find_encoder(struct drm_connector *connector, int type) - { - struct drm_device *dev = connector->dev; -@@ -116,10 +116,6 @@ nouveau_connector_destroy(struct drm_connector *connector) - nouveau_connector_hotplug, connector); - } - -- if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS || -- connector->connector_type == DRM_MODE_CONNECTOR_eDP) -- nouveau_backlight_exit(connector); -- - kfree(nv_connector->edid); - drm_sysfs_connector_remove(connector); - drm_connector_cleanup(connector); -@@ -712,11 +708,8 @@ nouveau_connector_mode_valid(struct drm_connector *connector, - case OUTPUT_TV: - return get_slave_funcs(encoder)->mode_valid(encoder, mode); - case OUTPUT_DP: -- if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7) -- max_clock = nv_encoder->dp.link_nr * 270000; -- else -- max_clock = nv_encoder->dp.link_nr * 162000; -- -+ max_clock = nv_encoder->dp.link_nr; -+ max_clock *= nv_encoder->dp.link_bw; - clock = clock * nouveau_connector_bpp(connector) / 8; - break; - default: -@@ -871,7 +864,6 @@ nouveau_connector_create(struct drm_device *dev, int index) - dev->mode_config.scaling_mode_property, - nv_connector->scaling_mode); - } -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; - /* fall-through */ - case DCB_CONNECTOR_TV_0: - case DCB_CONNECTOR_TV_1: -@@ -888,27 +880,20 @@ nouveau_connector_create(struct drm_device *dev, int index) - dev->mode_config.dithering_mode_property, - nv_connector->use_dithering ? - DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF); -- -- if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS) { -- if (dev_priv->card_type >= NV_50) -- connector->polled = DRM_CONNECTOR_POLL_HPD; -- else -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; -- } - break; - } - -- if (pgpio->irq_register) { -+ if (nv_connector->dcb->gpio_tag != 0xff && pgpio->irq_register) { - pgpio->irq_register(dev, nv_connector->dcb->gpio_tag, - nouveau_connector_hotplug, connector); -+ -+ connector->polled = DRM_CONNECTOR_POLL_HPD; -+ } else { -+ connector->polled = DRM_CONNECTOR_POLL_CONNECT; - } - - drm_sysfs_connector_add(connector); - -- if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS || -- connector->connector_type == DRM_MODE_CONNECTOR_eDP) -- nouveau_backlight_init(connector); -- - dcb->drm = connector; - return dcb->drm; - -@@ -925,22 +910,13 @@ nouveau_connector_hotplug(void *data, int plugged) - struct drm_connector *connector = data; - struct drm_device *dev = connector->dev; - -- NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un", -- drm_get_connector_name(connector)); -- -- if (connector->encoder && connector->encoder->crtc && -- connector->encoder->crtc->enabled) { -- struct nouveau_encoder *nv_encoder = nouveau_encoder(connector->encoder); -- struct drm_encoder_helper_funcs *helper = -- connector->encoder->helper_private; -+ NV_DEBUG(dev, "%splugged %s\n", plugged ? "" : "un", -+ drm_get_connector_name(connector)); - -- if (nv_encoder->dcb->type == OUTPUT_DP) { -- if (plugged) -- helper->dpms(connector->encoder, DRM_MODE_DPMS_ON); -- else -- helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF); -- } -- } -+ if (plugged) -+ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); -+ else -+ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); - - drm_helper_hpd_irq_event(dev); - } -diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h -index cb1ce2a..bf8e128 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_crtc.h -+++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h -@@ -82,14 +82,13 @@ static inline struct drm_crtc *to_drm_crtc(struct nouveau_crtc *crtc) - } - - int nv50_crtc_create(struct drm_device *dev, int index); --int nv50_cursor_init(struct nouveau_crtc *); --void nv50_cursor_fini(struct nouveau_crtc *); - int nv50_crtc_cursor_set(struct drm_crtc *drm_crtc, struct drm_file *file_priv, - uint32_t buffer_handle, uint32_t width, - uint32_t height); - int nv50_crtc_cursor_move(struct drm_crtc *drm_crtc, int x, int y); - - int nv04_cursor_init(struct nouveau_crtc *); -+int nv50_cursor_init(struct nouveau_crtc *); - - struct nouveau_connector * - nouveau_crtc_connector_get(struct nouveau_crtc *crtc); -diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c -index eb514ea..ddbabef 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_display.c -+++ b/drivers/gpu/drm/nouveau/nouveau_display.c -@@ -105,9 +105,12 @@ nouveau_framebuffer_init(struct drm_device *dev, - if (dev_priv->chipset == 0x50) - nv_fb->r_format |= (tile_flags << 8); - -- if (!tile_flags) -- nv_fb->r_pitch = 0x00100000 | fb->pitch; -- else { -+ if (!tile_flags) { -+ if (dev_priv->card_type < NV_D0) -+ nv_fb->r_pitch = 0x00100000 | fb->pitch; -+ else -+ nv_fb->r_pitch = 0x01000000 | fb->pitch; -+ } else { - u32 mode = nvbo->tile_mode; - if (dev_priv->card_type >= NV_C0) - mode >>= 4; -diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c -index 7beb82a..de5efe7 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_dp.c -+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c -@@ -28,557 +28,669 @@ - #include "nouveau_i2c.h" - #include "nouveau_connector.h" - #include "nouveau_encoder.h" -+#include "nouveau_crtc.h" - --static int --auxch_rd(struct drm_encoder *encoder, int address, uint8_t *buf, int size) --{ -- struct drm_device *dev = encoder->dev; -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- struct nouveau_i2c_chan *auxch; -- int ret; -+/****************************************************************************** -+ * aux channel util functions -+ *****************************************************************************/ -+#define AUX_DBG(fmt, args...) do { \ -+ if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_AUXCH) { \ -+ NV_PRINTK(KERN_DEBUG, dev, "AUXCH(%d): " fmt, ch, ##args); \ -+ } \ -+} while (0) -+#define AUX_ERR(fmt, args...) NV_ERROR(dev, "AUXCH(%d): " fmt, ch, ##args) - -- auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); -- if (!auxch) -- return -ENODEV; -- -- ret = nouveau_dp_auxch(auxch, 9, address, buf, size); -- if (ret) -- return ret; -- -- return 0; -+static void -+auxch_fini(struct drm_device *dev, int ch) -+{ -+ nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); - } - - static int --auxch_wr(struct drm_encoder *encoder, int address, uint8_t *buf, int size) -+auxch_init(struct drm_device *dev, int ch) - { -- struct drm_device *dev = encoder->dev; -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- struct nouveau_i2c_chan *auxch; -- int ret; -+ const u32 unksel = 1; /* nfi which to use, or if it matters.. */ -+ const u32 ureq = unksel ? 0x00100000 : 0x00200000; -+ const u32 urep = unksel ? 0x01000000 : 0x02000000; -+ u32 ctrl, timeout; - -- auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); -- if (!auxch) -- return -ENODEV; -+ /* wait up to 1ms for any previous transaction to be done... */ -+ timeout = 1000; -+ do { -+ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); -+ udelay(1); -+ if (!timeout--) { -+ AUX_ERR("begin idle timeout 0x%08x", ctrl); -+ return -EBUSY; -+ } -+ } while (ctrl & 0x03010000); - -- ret = nouveau_dp_auxch(auxch, 8, address, buf, size); -- return ret; -+ /* set some magic, and wait up to 1ms for it to appear */ -+ nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq); -+ timeout = 1000; -+ do { -+ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); -+ udelay(1); -+ if (!timeout--) { -+ AUX_ERR("magic wait 0x%08x\n", ctrl); -+ auxch_fini(dev, ch); -+ return -EBUSY; -+ } -+ } while ((ctrl & 0x03000000) != urep); -+ -+ return 0; - } - - static int --nouveau_dp_lane_count_set(struct drm_encoder *encoder, uint8_t cmd) -+auxch_tx(struct drm_device *dev, int ch, u8 type, u32 addr, u8 *data, u8 size) - { -- struct drm_device *dev = encoder->dev; -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- uint32_t tmp; -- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); -+ u32 ctrl, stat, timeout, retries; -+ u32 xbuf[4] = {}; -+ int ret, i; - -- tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); -- tmp &= ~(NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED | -- NV50_SOR_DP_CTRL_LANE_MASK); -- tmp |= ((1 << (cmd & DP_LANE_COUNT_MASK)) - 1) << 16; -- if (cmd & DP_LANE_COUNT_ENHANCED_FRAME_EN) -- tmp |= NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED; -- nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); -+ AUX_DBG("%d: 0x%08x %d\n", type, addr, size); - -- return auxch_wr(encoder, DP_LANE_COUNT_SET, &cmd, 1); --} -+ ret = auxch_init(dev, ch); -+ if (ret) -+ goto out; - --static int --nouveau_dp_link_bw_set(struct drm_encoder *encoder, uint8_t cmd) --{ -- struct drm_device *dev = encoder->dev; -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- uint32_t tmp; -- int reg = 0x614300 + (nv_encoder->or * 0x800); -+ stat = nv_rd32(dev, 0x00e4e8 + (ch * 0x50)); -+ if (!(stat & 0x10000000)) { -+ AUX_DBG("sink not detected\n"); -+ ret = -ENXIO; -+ goto out; -+ } - -- tmp = nv_rd32(dev, reg); -- tmp &= 0xfff3ffff; -- if (cmd == DP_LINK_BW_2_7) -- tmp |= 0x00040000; -- nv_wr32(dev, reg, tmp); -+ if (!(type & 1)) { -+ memcpy(xbuf, data, size); -+ for (i = 0; i < 16; i += 4) { -+ AUX_DBG("wr 0x%08x\n", xbuf[i / 4]); -+ nv_wr32(dev, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]); -+ } -+ } - -- return auxch_wr(encoder, DP_LINK_BW_SET, &cmd, 1); --} -+ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); -+ ctrl &= ~0x0001f0ff; -+ ctrl |= type << 12; -+ ctrl |= size - 1; -+ nv_wr32(dev, 0x00e4e0 + (ch * 0x50), addr); - --static int --nouveau_dp_link_train_set(struct drm_encoder *encoder, int pattern) --{ -- struct drm_device *dev = encoder->dev; -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- uint32_t tmp; -- uint8_t cmd; -- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); -- int ret; -+ /* retry transaction a number of times on failure... */ -+ ret = -EREMOTEIO; -+ for (retries = 0; retries < 32; retries++) { -+ /* reset, and delay a while if this is a retry */ -+ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); -+ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); -+ if (retries) -+ udelay(400); - -- tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); -- tmp &= ~NV50_SOR_DP_CTRL_TRAINING_PATTERN; -- tmp |= (pattern << 24); -- nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); -+ /* transaction request, wait up to 1ms for it to complete */ -+ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); - -- ret = auxch_rd(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1); -- if (ret) -- return ret; -- cmd &= ~DP_TRAINING_PATTERN_MASK; -- cmd |= (pattern & DP_TRAINING_PATTERN_MASK); -- return auxch_wr(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1); --} -+ timeout = 1000; -+ do { -+ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); -+ udelay(1); -+ if (!timeout--) { -+ AUX_ERR("tx req timeout 0x%08x\n", ctrl); -+ goto out; -+ } -+ } while (ctrl & 0x00010000); - --static int --nouveau_dp_max_voltage_swing(struct drm_encoder *encoder) --{ -- 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 i, dpe_headerlen, max_vs = 0; -+ /* read status, and check if transaction completed ok */ -+ stat = nv_mask(dev, 0x00e4e8 + (ch * 0x50), 0, 0); -+ if (!(stat & 0x000f0f00)) { -+ ret = 0; -+ break; -+ } - -- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); -- if (!dpe) -- return false; -- dpse = (void *)((char *)dpe + dpe_headerlen); -+ AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); -+ } - -- for (i = 0; i < dpe_headerlen; i++, dpse++) { -- if (dpse->vs_level > max_vs) -- max_vs = dpse->vs_level; -+ if (type & 1) { -+ for (i = 0; i < 16; i += 4) { -+ xbuf[i / 4] = nv_rd32(dev, 0x00e4d0 + (ch * 0x50) + i); -+ AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); -+ } -+ memcpy(data, xbuf, size); - } - -- return max_vs; -+out: -+ auxch_fini(dev, ch); -+ return ret; - } - --static int --nouveau_dp_max_pre_emphasis(struct drm_encoder *encoder, int vs) -+static u32 -+dp_link_bw_get(struct drm_device *dev, int or, int link) - { -- 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 i, dpe_headerlen, max_pre = 0; -- -- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); -- if (!dpe) -- return false; -- dpse = (void *)((char *)dpe + dpe_headerlen); -- -- for (i = 0; i < dpe_headerlen; i++, dpse++) { -- if (dpse->vs_level != vs) -- continue; -+ u32 ctrl = nv_rd32(dev, 0x614300 + (or * 0x800)); -+ if (!(ctrl & 0x000c0000)) -+ return 162000; -+ return 270000; -+} - -- if (dpse->pre_level > max_pre) -- max_pre = dpse->pre_level; -+static int -+dp_lane_count_get(struct drm_device *dev, int or, int link) -+{ -+ u32 ctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); -+ switch (ctrl & 0x000f0000) { -+ case 0x00010000: return 1; -+ case 0x00030000: return 2; -+ default: -+ return 4; - } -- -- return max_pre; - } - --static bool --nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config) -+void -+nouveau_dp_tu_update(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) - { -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- struct drm_device *dev = encoder->dev; -- struct bit_displayport_encoder_table *dpe; -- int ret, i, dpe_headerlen, vs = 0, pre = 0; -- uint8_t request[2]; -+ const u32 symbol = 100000; -+ int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0; -+ int TU, VTUi, VTUf, VTUa; -+ u64 link_data_rate, link_ratio, unk; -+ u32 best_diff = 64 * symbol; -+ u32 link_nr, link_bw, r; - -- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); -- if (!dpe) -- return false; -+ /* calculate packed data rate for each lane */ -+ link_nr = dp_lane_count_get(dev, or, link); -+ link_data_rate = (clk * bpp / 8) / link_nr; - -- ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2); -- if (ret) -- return false; -+ /* calculate ratio of packed data rate to link symbol rate */ -+ link_bw = dp_link_bw_get(dev, or, link); -+ link_ratio = link_data_rate * symbol; -+ r = do_div(link_ratio, link_bw); - -- NV_DEBUG_KMS(dev, "\t\tadjust 0x%02x 0x%02x\n", request[0], request[1]); -+ for (TU = 64; TU >= 32; TU--) { -+ /* calculate average number of valid symbols in each TU */ -+ u32 tu_valid = link_ratio * TU; -+ u32 calc, diff; - -- /* Keep all lanes at the same level.. */ -- for (i = 0; i < nv_encoder->dp.link_nr; i++) { -- int lane_req = (request[i >> 1] >> ((i & 1) << 2)) & 0xf; -- int lane_vs = lane_req & 3; -- int lane_pre = (lane_req >> 2) & 3; -+ /* find a hw representation for the fraction.. */ -+ VTUi = tu_valid / symbol; -+ calc = VTUi * symbol; -+ diff = tu_valid - calc; -+ if (diff) { -+ if (diff >= (symbol / 2)) { -+ VTUf = symbol / (symbol - diff); -+ if (symbol - (VTUf * diff)) -+ VTUf++; - -- if (lane_vs > vs) -- vs = lane_vs; -- if (lane_pre > pre) -- pre = lane_pre; -- } -+ if (VTUf <= 15) { -+ VTUa = 1; -+ calc += symbol - (symbol / VTUf); -+ } else { -+ VTUa = 0; -+ VTUf = 1; -+ calc += symbol; -+ } -+ } else { -+ VTUa = 0; -+ VTUf = min((int)(symbol / diff), 15); -+ calc += symbol / VTUf; -+ } - -- if (vs >= nouveau_dp_max_voltage_swing(encoder)) { -- vs = nouveau_dp_max_voltage_swing(encoder); -- vs |= 4; -+ diff = calc - tu_valid; -+ } else { -+ /* no remainder, but the hw doesn't like the fractional -+ * part to be zero. decrement the integer part and -+ * have the fraction add a whole symbol back -+ */ -+ VTUa = 0; -+ VTUf = 1; -+ VTUi--; -+ } -+ -+ if (diff < best_diff) { -+ best_diff = diff; -+ bestTU = TU; -+ bestVTUa = VTUa; -+ bestVTUf = VTUf; -+ bestVTUi = VTUi; -+ if (diff == 0) -+ break; -+ } - } - -- if (pre >= nouveau_dp_max_pre_emphasis(encoder, vs & 3)) { -- pre = nouveau_dp_max_pre_emphasis(encoder, vs & 3); -- pre |= 4; -+ if (!bestTU) { -+ NV_ERROR(dev, "DP: unable to find suitable config\n"); -+ return; - } - -- /* Update the configuration for all lanes.. */ -- for (i = 0; i < nv_encoder->dp.link_nr; i++) -- config[i] = (pre << 3) | vs; -+ /* XXX close to vbios numbers, but not right */ -+ unk = (symbol - link_ratio) * bestTU; -+ unk *= link_ratio; -+ r = do_div(unk, symbol); -+ r = do_div(unk, symbol); -+ unk += 6; - -- return true; -+ nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2); -+ nv_mask(dev, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 | -+ bestVTUf << 16 | -+ bestVTUi << 8 | -+ unk); - } - --static bool --nouveau_dp_link_train_commit(struct drm_encoder *encoder, uint8_t *config) -+u8 * -+nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) - { -- 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 or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); -- int dpe_headerlen, ret, i; -- -- NV_DEBUG_KMS(dev, "\t\tconfig 0x%02x 0x%02x 0x%02x 0x%02x\n", -- config[0], config[1], config[2], config[3]); -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nvbios *bios = &dev_priv->vbios; -+ struct bit_entry d; -+ u8 *table; -+ int i; - -- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); -- if (!dpe) -- return false; -- dpse = (void *)((char *)dpe + dpe_headerlen); -+ if (bit_table(dev, 'd', &d)) { -+ NV_ERROR(dev, "BIT 'd' table not found\n"); -+ return NULL; -+ } - -- for (i = 0; i < dpe->record_nr; i++, dpse++) { -- if (dpse->vs_level == (config[0] & 3) && -- dpse->pre_level == ((config[0] >> 3) & 3)) -- break; -+ if (d.version != 1) { -+ NV_ERROR(dev, "BIT 'd' table version %d unknown\n", d.version); -+ return NULL; - } -- BUG_ON(i == dpe->record_nr); - -- for (i = 0; i < nv_encoder->dp.link_nr; i++) { -- const int shift[4] = { 16, 8, 0, 24 }; -- uint32_t mask = 0xff << shift[i]; -- uint32_t reg0, reg1, reg2; -+ table = ROMPTR(bios, d.data[0]); -+ if (!table) { -+ NV_ERROR(dev, "displayport table pointer invalid\n"); -+ return NULL; -+ } - -- reg0 = nv_rd32(dev, NV50_SOR_DP_UNK118(or, link)) & ~mask; -- reg0 |= (dpse->reg0 << shift[i]); -- reg1 = nv_rd32(dev, NV50_SOR_DP_UNK120(or, link)) & ~mask; -- reg1 |= (dpse->reg1 << shift[i]); -- reg2 = nv_rd32(dev, NV50_SOR_DP_UNK130(or, link)) & 0xffff00ff; -- reg2 |= (dpse->reg2 << 8); -- nv_wr32(dev, NV50_SOR_DP_UNK118(or, link), reg0); -- nv_wr32(dev, NV50_SOR_DP_UNK120(or, link), reg1); -- nv_wr32(dev, NV50_SOR_DP_UNK130(or, link), reg2); -+ switch (table[0]) { -+ case 0x20: -+ case 0x21: -+ case 0x30: -+ break; -+ default: -+ NV_ERROR(dev, "displayport table 0x%02x unknown\n", table[0]); -+ return NULL; - } - -- ret = auxch_wr(encoder, DP_TRAINING_LANE0_SET, config, 4); -- if (ret) -- return false; -+ for (i = 0; i < table[3]; i++) { -+ *entry = ROMPTR(bios, table[table[1] + (i * table[2])]); -+ if (*entry && bios_encoder_match(dcb, ROM32((*entry)[0]))) -+ return table; -+ } - -- return true; -+ NV_ERROR(dev, "displayport encoder table not found\n"); -+ return NULL; - } - --bool --nouveau_dp_link_train(struct drm_encoder *encoder) -+/****************************************************************************** -+ * link training -+ *****************************************************************************/ -+struct dp_state { -+ struct dcb_entry *dcb; -+ u8 *table; -+ u8 *entry; -+ int auxch; -+ int crtc; -+ int or; -+ int link; -+ u8 *dpcd; -+ int link_nr; -+ u32 link_bw; -+ u8 stat[6]; -+ u8 conf[4]; -+}; -+ -+static void -+dp_set_link_config(struct drm_device *dev, struct dp_state *dp) - { -- struct drm_device *dev = encoder->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- struct nouveau_connector *nv_connector; -- struct bit_displayport_encoder_table *dpe; -- int dpe_headerlen; -- uint8_t config[4], status[3]; -- bool cr_done, cr_max_vs, eq_done, hpd_state; -- int ret = 0, i, tries, voltage; -+ int or = dp->or, link = dp->link; -+ u8 *entry, sink[2]; -+ u32 dp_ctrl; -+ u16 script; - -- NV_DEBUG_KMS(dev, "link training!!\n"); -+ NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); - -- nv_connector = nouveau_encoder_connector_get(nv_encoder); -- if (!nv_connector) -- return false; -- -- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); -- if (!dpe) { -- NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or); -- return false; -+ /* set selected link rate on source */ -+ switch (dp->link_bw) { -+ case 270000: -+ nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00040000); -+ sink[0] = DP_LINK_BW_2_7; -+ break; -+ default: -+ nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00000000); -+ sink[0] = DP_LINK_BW_1_62; -+ break; - } - -- /* disable hotplug detect, this flips around on some panels during -- * link training. -+ /* offset +0x0a of each dp encoder table entry is a pointer to another -+ * table, that has (among other things) pointers to more scripts that -+ * need to be executed, this time depending on link speed. - */ -- hpd_state = pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); -+ entry = ROMPTR(&dev_priv->vbios, dp->entry[10]); -+ if (entry) { -+ if (dp->table[0] < 0x30) { -+ while (dp->link_bw < (ROM16(entry[0]) * 10)) -+ entry += 4; -+ script = ROM16(entry[2]); -+ } else { -+ while (dp->link_bw < (entry[0] * 27000)) -+ entry += 3; -+ script = ROM16(entry[1]); -+ } - -- if (dpe->script0) { -- NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); -- nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0), -- nv_encoder->dcb); -+ nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc); - } - --train: -- cr_done = eq_done = false; -+ /* configure lane count on the source */ -+ dp_ctrl = ((1 << dp->link_nr) - 1) << 16; -+ sink[1] = dp->link_nr; -+ if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) { -+ dp_ctrl |= 0x00004000; -+ sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; -+ } - -- /* set link configuration */ -- NV_DEBUG_KMS(dev, "\tbegin train: bw %d, lanes %d\n", -- nv_encoder->dp.link_bw, nv_encoder->dp.link_nr); -+ nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x001f4000, dp_ctrl); - -- ret = nouveau_dp_link_bw_set(encoder, nv_encoder->dp.link_bw); -- if (ret) -- return false; -+ /* inform the sink of the new configuration */ -+ auxch_tx(dev, dp->auxch, 8, DP_LINK_BW_SET, sink, 2); -+} - -- config[0] = nv_encoder->dp.link_nr; -- if (nv_encoder->dp.dpcd_version >= 0x11 && -- nv_encoder->dp.enhanced_frame) -- config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; -+static void -+dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 tp) -+{ -+ u8 sink_tp; - -- ret = nouveau_dp_lane_count_set(encoder, config[0]); -- if (ret) -- return false; -+ NV_DEBUG_KMS(dev, "training pattern %d\n", tp); - -- /* clock recovery */ -- NV_DEBUG_KMS(dev, "\tbegin cr\n"); -- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_1); -- if (ret) -- goto stop; -+ nv_mask(dev, NV50_SOR_DP_CTRL(dp->or, dp->link), 0x0f000000, tp << 24); - -- tries = 0; -- voltage = -1; -- memset(config, 0x00, sizeof(config)); -- for (;;) { -- if (!nouveau_dp_link_train_commit(encoder, config)) -- break; -+ auxch_tx(dev, dp->auxch, 9, DP_TRAINING_PATTERN_SET, &sink_tp, 1); -+ sink_tp &= ~DP_TRAINING_PATTERN_MASK; -+ sink_tp |= tp; -+ auxch_tx(dev, dp->auxch, 8, DP_TRAINING_PATTERN_SET, &sink_tp, 1); -+} - -- udelay(100); -+static const u8 nv50_lane_map[] = { 16, 8, 0, 24 }; -+static const u8 nvaf_lane_map[] = { 24, 16, 8, 0 }; - -- ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 2); -- if (ret) -- break; -- NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n", -- status[0], status[1]); -+static int -+dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ u32 mask = 0, drv = 0, pre = 0, unk = 0; -+ const u8 *shifts; -+ int link = dp->link; -+ int or = dp->or; -+ int i; - -- cr_done = true; -- cr_max_vs = false; -- for (i = 0; i < nv_encoder->dp.link_nr; i++) { -- int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf; -+ if (dev_priv->chipset != 0xaf) -+ shifts = nv50_lane_map; -+ else -+ shifts = nvaf_lane_map; - -- if (!(lane & DP_LANE_CR_DONE)) { -- cr_done = false; -- if (config[i] & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED) -- cr_max_vs = true; -- break; -+ for (i = 0; i < dp->link_nr; i++) { -+ u8 *conf = dp->entry + dp->table[4]; -+ u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; -+ u8 lpre = (lane & 0x0c) >> 2; -+ u8 lvsw = (lane & 0x03) >> 0; -+ -+ mask |= 0xff << shifts[i]; -+ unk |= 1 << (shifts[i] >> 3); -+ -+ dp->conf[i] = (lpre << 3) | lvsw; -+ if (lvsw == DP_TRAIN_VOLTAGE_SWING_1200) -+ dp->conf[i] |= DP_TRAIN_MAX_SWING_REACHED; -+ if (lpre == DP_TRAIN_PRE_EMPHASIS_9_5) -+ dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; -+ -+ NV_DEBUG_KMS(dev, "config lane %d %02x\n", i, dp->conf[i]); -+ -+ if (dp->table[0] < 0x30) { -+ u8 *last = conf + (dp->entry[4] * dp->table[5]); -+ while (lvsw != conf[0] || lpre != conf[1]) { -+ conf += dp->table[5]; -+ if (conf >= last) -+ return -EINVAL; - } -- } - -- if ((config[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { -- voltage = config[0] & DP_TRAIN_VOLTAGE_SWING_MASK; -- tries = 0; -- } -+ conf += 2; -+ } else { -+ /* no lookup table anymore, set entries for each -+ * combination of voltage swing and pre-emphasis -+ * level allowed by the DP spec. -+ */ -+ switch (lvsw) { -+ case 0: lpre += 0; break; -+ case 1: lpre += 4; break; -+ case 2: lpre += 7; break; -+ case 3: lpre += 9; break; -+ } - -- if (cr_done || cr_max_vs || (++tries == 5)) -- break; -+ conf = conf + (lpre * dp->table[5]); -+ conf++; -+ } - -- if (!nouveau_dp_link_train_adjust(encoder, config)) -- break; -+ drv |= conf[0] << shifts[i]; -+ pre |= conf[1] << shifts[i]; -+ unk = (unk & ~0x0000ff00) | (conf[2] << 8); - } - -- if (!cr_done) -- goto stop; -+ nv_mask(dev, NV50_SOR_DP_UNK118(or, link), mask, drv); -+ nv_mask(dev, NV50_SOR_DP_UNK120(or, link), mask, pre); -+ nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000ff0f, unk); -+ -+ return auxch_tx(dev, dp->auxch, 8, DP_TRAINING_LANE0_SET, dp->conf, 4); -+} -+ -+static int -+dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay) -+{ -+ int ret; -+ -+ udelay(delay); - -- /* channel equalisation */ -- NV_DEBUG_KMS(dev, "\tbegin eq\n"); -- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_2); -+ ret = auxch_tx(dev, dp->auxch, 9, DP_LANE0_1_STATUS, dp->stat, 6); - if (ret) -- goto stop; -+ return ret; - -- for (tries = 0; tries <= 5; tries++) { -- udelay(400); -+ NV_DEBUG_KMS(dev, "status %02x %02x %02x %02x %02x %02x\n", -+ dp->stat[0], dp->stat[1], dp->stat[2], dp->stat[3], -+ dp->stat[4], dp->stat[5]); -+ return 0; -+} - -- ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 3); -- if (ret) -- break; -- NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n", -- status[0], status[1]); -+static int -+dp_link_train_cr(struct drm_device *dev, struct dp_state *dp) -+{ -+ bool cr_done = false, abort = false; -+ int voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK; -+ int tries = 0, i; - -- eq_done = true; -- if (!(status[2] & DP_INTERLANE_ALIGN_DONE)) -- eq_done = false; -+ dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_1); - -- for (i = 0; eq_done && i < nv_encoder->dp.link_nr; i++) { -- int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf; -+ do { -+ if (dp_link_train_commit(dev, dp) || -+ dp_link_train_update(dev, dp, 100)) -+ break; - -+ cr_done = true; -+ for (i = 0; i < dp->link_nr; i++) { -+ u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; - if (!(lane & DP_LANE_CR_DONE)) { - cr_done = false; -+ if (dp->conf[i] & DP_TRAIN_MAX_SWING_REACHED) -+ abort = true; - break; - } -+ } - -- if (!(lane & DP_LANE_CHANNEL_EQ_DONE) || -- !(lane & DP_LANE_SYMBOL_LOCKED)) { -- eq_done = false; -- break; -- } -+ if ((dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { -+ voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK; -+ tries = 0; - } -+ } while (!cr_done && !abort && ++tries < 5); - -- if (eq_done || !cr_done) -- break; -+ return cr_done ? 0 : -1; -+} - -- if (!nouveau_dp_link_train_adjust(encoder, config) || -- !nouveau_dp_link_train_commit(encoder, config)) -- break; -- } -+static int -+dp_link_train_eq(struct drm_device *dev, struct dp_state *dp) -+{ -+ bool eq_done, cr_done = true; -+ int tries = 0, i; - --stop: -- /* end link training */ -- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_DISABLE); -- if (ret) -- return false; -+ dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_2); - -- /* retry at a lower setting, if possible */ -- if (!ret && !(eq_done && cr_done)) { -- NV_DEBUG_KMS(dev, "\twe failed\n"); -- if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62) { -- NV_DEBUG_KMS(dev, "retry link training at low rate\n"); -- nv_encoder->dp.link_bw = DP_LINK_BW_1_62; -- goto train; -- } -- } -+ do { -+ if (dp_link_train_update(dev, dp, 400)) -+ break; - -- if (dpe->script1) { -- NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or); -- nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1), -- nv_encoder->dcb); -- } -+ eq_done = !!(dp->stat[2] & DP_INTERLANE_ALIGN_DONE); -+ for (i = 0; i < dp->link_nr && eq_done; i++) { -+ u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; -+ if (!(lane & DP_LANE_CR_DONE)) -+ cr_done = false; -+ if (!(lane & DP_LANE_CHANNEL_EQ_DONE) || -+ !(lane & DP_LANE_SYMBOL_LOCKED)) -+ eq_done = false; -+ } - -- /* re-enable hotplug detect */ -- pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, hpd_state); -+ if (dp_link_train_commit(dev, dp)) -+ break; -+ } while (!eq_done && cr_done && ++tries <= 5); - -- return eq_done; -+ return eq_done ? 0 : -1; - } - - bool --nouveau_dp_detect(struct drm_encoder *encoder) -+nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) - { -+ struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; -+ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); -+ struct nouveau_connector *nv_connector = -+ nouveau_encoder_connector_get(nv_encoder); - struct drm_device *dev = encoder->dev; -- uint8_t dpcd[4]; -- int ret; -+ struct nouveau_i2c_chan *auxch; -+ const u32 bw_list[] = { 270000, 162000, 0 }; -+ const u32 *link_bw = bw_list; -+ struct dp_state dp; - -- ret = auxch_rd(encoder, 0x0000, dpcd, 4); -- if (ret) -+ auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); -+ if (!auxch) - return false; - -- NV_DEBUG_KMS(dev, "encoder: link_bw %d, link_nr %d\n" -- "display: link_bw %d, link_nr %d version 0x%02x\n", -- nv_encoder->dcb->dpconf.link_bw, -- nv_encoder->dcb->dpconf.link_nr, -- dpcd[1], dpcd[2] & 0x0f, dpcd[0]); -+ dp.table = nouveau_dp_bios_data(dev, nv_encoder->dcb, &dp.entry); -+ if (!dp.table) -+ return -EINVAL; - -- nv_encoder->dp.dpcd_version = dpcd[0]; -+ dp.dcb = nv_encoder->dcb; -+ dp.crtc = nv_crtc->index; -+ dp.auxch = auxch->rd; -+ dp.or = nv_encoder->or; -+ dp.link = !(nv_encoder->dcb->sorconf.link & 1); -+ dp.dpcd = nv_encoder->dp.dpcd; - -- nv_encoder->dp.link_bw = dpcd[1]; -- if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62 && -- !nv_encoder->dcb->dpconf.link_bw) -- nv_encoder->dp.link_bw = DP_LINK_BW_1_62; -+ /* some sinks toggle hotplug in response to some of the actions -+ * we take during link training (DP_SET_POWER is one), we need -+ * to ignore them for the moment to avoid races. -+ */ -+ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); - -- nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; -- if (nv_encoder->dp.link_nr > nv_encoder->dcb->dpconf.link_nr) -- nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; -+ /* enable down-spreading, if possible */ -+ if (dp.table[1] >= 16) { -+ u16 script = ROM16(dp.entry[14]); -+ if (nv_encoder->dp.dpcd[3] & 1) -+ script = ROM16(dp.entry[12]); - -- nv_encoder->dp.enhanced_frame = (dpcd[2] & DP_ENHANCED_FRAME_CAP); -+ nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc); -+ } - -- return true; --} -+ /* execute pre-train script from vbios */ -+ nouveau_bios_run_init_table(dev, ROM16(dp.entry[6]), dp.dcb, dp.crtc); - --int --nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, -- uint8_t *data, int data_nr) --{ -- struct drm_device *dev = auxch->dev; -- uint32_t tmp, ctrl, stat = 0, data32[4] = {}; -- int ret = 0, i, index = auxch->rd; -+ /* start off at highest link rate supported by encoder and display */ -+ while (*link_bw > nv_encoder->dp.link_bw) -+ link_bw++; - -- NV_DEBUG_KMS(dev, "ch %d cmd %d addr 0x%x len %d\n", index, cmd, addr, data_nr); -+ while (link_bw[0]) { -+ /* find minimum required lane count at this link rate */ -+ dp.link_nr = nv_encoder->dp.link_nr; -+ while ((dp.link_nr >> 1) * link_bw[0] > datarate) -+ dp.link_nr >>= 1; - -- tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); -- nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp | 0x00100000); -- tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); -- if (!(tmp & 0x01000000)) { -- NV_ERROR(dev, "expected bit 24 == 1, got 0x%08x\n", tmp); -- ret = -EIO; -- goto out; -- } -+ /* drop link rate to minimum with this lane count */ -+ while ((link_bw[1] * dp.link_nr) > datarate) -+ link_bw++; -+ dp.link_bw = link_bw[0]; -+ -+ /* program selected link configuration */ -+ dp_set_link_config(dev, &dp); - -- for (i = 0; i < 3; i++) { -- tmp = nv_rd32(dev, NV50_AUXCH_STAT(auxch->rd)); -- if (tmp & NV50_AUXCH_STAT_STATE_READY) -+ /* attempt to train the link at this configuration */ -+ memset(dp.stat, 0x00, sizeof(dp.stat)); -+ if (!dp_link_train_cr(dev, &dp) && -+ !dp_link_train_eq(dev, &dp)) - break; -- udelay(100); -- } - -- if (i == 3) { -- ret = -EBUSY; -- goto out; -+ /* retry at lower rate */ -+ link_bw++; - } - -- if (!(cmd & 1)) { -- memcpy(data32, data, data_nr); -- for (i = 0; i < 4; i++) { -- NV_DEBUG_KMS(dev, "wr %d: 0x%08x\n", i, data32[i]); -- nv_wr32(dev, NV50_AUXCH_DATA_OUT(index, i), data32[i]); -- } -- } -+ /* finish link training */ -+ dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE); - -- nv_wr32(dev, NV50_AUXCH_ADDR(index), addr); -- ctrl = nv_rd32(dev, NV50_AUXCH_CTRL(index)); -- ctrl &= ~(NV50_AUXCH_CTRL_CMD | NV50_AUXCH_CTRL_LEN); -- ctrl |= (cmd << NV50_AUXCH_CTRL_CMD_SHIFT); -- ctrl |= ((data_nr - 1) << NV50_AUXCH_CTRL_LEN_SHIFT); -+ /* execute post-train script from vbios */ -+ nouveau_bios_run_init_table(dev, ROM16(dp.entry[8]), dp.dcb, dp.crtc); - -- for (i = 0; i < 16; i++) { -- nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000); -- nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl); -- nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x00010000); -- if (!nv_wait(dev, NV50_AUXCH_CTRL(index), -- 0x00010000, 0x00000000)) { -- NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n", -- nv_rd32(dev, NV50_AUXCH_CTRL(index))); -- ret = -EBUSY; -- goto out; -- } -+ /* re-enable hotplug detect */ -+ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true); -+ return true; -+} -+ -+bool -+nouveau_dp_detect(struct drm_encoder *encoder) -+{ -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct drm_device *dev = encoder->dev; -+ struct nouveau_i2c_chan *auxch; -+ u8 *dpcd = nv_encoder->dp.dpcd; -+ int ret; - -- udelay(400); -+ auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); -+ if (!auxch) -+ return false; - -- stat = nv_rd32(dev, NV50_AUXCH_STAT(index)); -- if ((stat & NV50_AUXCH_STAT_REPLY_AUX) != -- NV50_AUXCH_STAT_REPLY_AUX_DEFER) -- break; -- } -+ ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8); -+ if (ret) -+ return false; - -- if (i == 16) { -- NV_ERROR(dev, "auxch DEFER too many times, bailing\n"); -- ret = -EREMOTEIO; -- goto out; -- } -+ nv_encoder->dp.link_bw = 27000 * dpcd[1]; -+ nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; - -- if (cmd & 1) { -- if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) { -- ret = -EREMOTEIO; -- goto out; -- } -+ NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n", -+ nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); -+ NV_DEBUG_KMS(dev, "encoder: %dx%d\n", -+ nv_encoder->dcb->dpconf.link_nr, -+ nv_encoder->dcb->dpconf.link_bw); - -- for (i = 0; i < 4; i++) { -- data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i)); -- NV_DEBUG_KMS(dev, "rd %d: 0x%08x\n", i, data32[i]); -- } -- memcpy(data, data32, data_nr); -- } -+ if (nv_encoder->dcb->dpconf.link_nr < nv_encoder->dp.link_nr) -+ nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; -+ if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw) -+ nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw; - --out: -- tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); -- nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp & ~0x00100000); -- tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); -- if (tmp & 0x01000000) { -- NV_ERROR(dev, "expected bit 24 == 0, got 0x%08x\n", tmp); -- ret = -EIO; -- } -+ NV_DEBUG_KMS(dev, "maximum: %dx%d\n", -+ nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); - -- udelay(400); -+ return true; -+} - -- return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY); -+int -+nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, -+ uint8_t *data, int data_nr) -+{ -+ return auxch_tx(auxch->dev, auxch->rd, cmd, addr, data, data_nr); - } - - static int - nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) - { - struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adap; -- struct drm_device *dev = auxch->dev; - struct i2c_msg *msg = msgs; - int ret, mcnt = num; - -@@ -602,19 +714,6 @@ nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) - if (ret < 0) - return ret; - -- switch (ret & NV50_AUXCH_STAT_REPLY_I2C) { -- case NV50_AUXCH_STAT_REPLY_I2C_ACK: -- break; -- case NV50_AUXCH_STAT_REPLY_I2C_NACK: -- return -EREMOTEIO; -- case NV50_AUXCH_STAT_REPLY_I2C_DEFER: -- udelay(100); -- continue; -- default: -- NV_ERROR(dev, "bad auxch reply: 0x%08x\n", ret); -- return -EREMOTEIO; -- } -- - ptr += cnt; - remaining -= cnt; - } -diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c -index b30ddd8..c1e01f3 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_drv.c -+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c -@@ -41,7 +41,7 @@ int nouveau_agpmode = -1; - module_param_named(agpmode, nouveau_agpmode, int, 0400); - - MODULE_PARM_DESC(modeset, "Enable kernel modesetting"); --static int nouveau_modeset = -1; /* kms */ -+int nouveau_modeset = -1; - module_param_named(modeset, nouveau_modeset, int, 0400); - - MODULE_PARM_DESC(vbios, "Override default VBIOS location"); -diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h -index d7d51de..29837da 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_drv.h -+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h -@@ -414,12 +414,13 @@ struct nouveau_gpio_engine { - }; - - struct nouveau_pm_voltage_level { -- u8 voltage; -- u8 vid; -+ u32 voltage; /* microvolts */ -+ u8 vid; - }; - - struct nouveau_pm_voltage { - bool supported; -+ u8 version; - u8 vid_mask; - - struct nouveau_pm_voltage_level *level; -@@ -428,17 +429,48 @@ struct nouveau_pm_voltage { - - struct nouveau_pm_memtiming { - int id; -- u32 reg_100220; -- u32 reg_100224; -- u32 reg_100228; -- u32 reg_10022c; -- u32 reg_100230; -- u32 reg_100234; -- u32 reg_100238; -- u32 reg_10023c; -- u32 reg_100240; -+ u32 reg_0; /* 0x10f290 on Fermi, 0x100220 for older */ -+ u32 reg_1; -+ u32 reg_2; -+ u32 reg_3; -+ u32 reg_4; -+ u32 reg_5; -+ u32 reg_6; -+ u32 reg_7; -+ u32 reg_8; -+ /* To be written to 0x1002c0 */ -+ u8 CL; -+ u8 WR; - }; - -+struct nouveau_pm_tbl_header{ -+ u8 version; -+ u8 header_len; -+ u8 entry_cnt; -+ u8 entry_len; -+}; -+ -+struct nouveau_pm_tbl_entry{ -+ u8 tWR; -+ u8 tUNK_1; -+ u8 tCL; -+ u8 tRP; /* Byte 3 */ -+ u8 empty_4; -+ u8 tRAS; /* Byte 5 */ -+ u8 empty_6; -+ u8 tRFC; /* Byte 7 */ -+ u8 empty_8; -+ u8 tRC; /* Byte 9 */ -+ u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14; -+ u8 empty_15,empty_16,empty_17; -+ u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21; -+}; -+ -+/* nouveau_mem.c */ -+void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, -+ struct nouveau_pm_tbl_entry *e, uint8_t magic_number, -+ struct nouveau_pm_memtiming *timing); -+ - #define NOUVEAU_PM_MAX_LEVEL 8 - struct nouveau_pm_level { - struct device_attribute dev_attr; -@@ -448,11 +480,19 @@ struct nouveau_pm_level { - u32 core; - u32 memory; - u32 shader; -- u32 unk05; -- u32 unk0a; -+ u32 rop; -+ u32 copy; -+ u32 daemon; -+ u32 vdec; -+ u32 unk05; /* nv50:nva3, roughly.. */ -+ u32 unka0; /* nva3:nvc0 */ -+ u32 hub01; /* nvc0- */ -+ u32 hub06; /* nvc0- */ -+ u32 hub07; /* nvc0- */ - -- u8 voltage; -- u8 fanspeed; -+ u32 volt_min; /* microvolts */ -+ u32 volt_max; -+ u8 fanspeed; - - u16 memscript; - struct nouveau_pm_memtiming *timing; -@@ -496,6 +536,11 @@ struct nouveau_pm_engine { - void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *, - u32 id, int khz); - void (*clock_set)(struct drm_device *, void *); -+ -+ int (*clocks_get)(struct drm_device *, struct nouveau_pm_level *); -+ void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *); -+ void (*clocks_set)(struct drm_device *, void *); -+ - int (*voltage_get)(struct drm_device *); - int (*voltage_set)(struct drm_device *, int voltage); - int (*fanspeed_get)(struct drm_device *); -@@ -504,7 +549,7 @@ struct nouveau_pm_engine { - }; - - struct nouveau_vram_engine { -- struct nouveau_mm *mm; -+ struct nouveau_mm mm; - - int (*init)(struct drm_device *); - void (*takedown)(struct drm_device *dev); -@@ -623,6 +668,7 @@ enum nouveau_card_type { - NV_40 = 0x40, - NV_50 = 0x50, - NV_C0 = 0xc0, -+ NV_D0 = 0xd0 - }; - - struct drm_nouveau_private { -@@ -633,8 +679,8 @@ struct drm_nouveau_private { - enum nouveau_card_type card_type; - /* exact chipset, derived from NV_PMC_BOOT_0 */ - int chipset; -- int stepping; - int flags; -+ u32 crystal; - - void __iomem *mmio; - -@@ -721,7 +767,6 @@ struct drm_nouveau_private { - uint64_t vram_size; - uint64_t vram_sys_base; - -- uint64_t fb_phys; - uint64_t fb_available_size; - uint64_t fb_mappable_pages; - uint64_t fb_aper_free; -@@ -784,6 +829,7 @@ nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo) - } - - /* nouveau_drv.c */ -+extern int nouveau_modeset; - extern int nouveau_agpmode; - extern int nouveau_duallink; - extern int nouveau_uscript_lvds; -@@ -824,6 +870,8 @@ extern bool nouveau_wait_eq(struct drm_device *, uint64_t timeout, - uint32_t reg, uint32_t mask, uint32_t val); - extern bool nouveau_wait_ne(struct drm_device *, uint64_t timeout, - uint32_t reg, uint32_t mask, uint32_t val); -+extern bool nouveau_wait_cb(struct drm_device *, u64 timeout, -+ bool (*cond)(void *), void *); - extern bool nouveau_wait_for_idle(struct drm_device *); - extern int nouveau_card_init(struct drm_device *); - -@@ -1006,15 +1054,15 @@ static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector - - /* nouveau_backlight.c */ - #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT --extern int nouveau_backlight_init(struct drm_connector *); --extern void nouveau_backlight_exit(struct drm_connector *); -+extern int nouveau_backlight_init(struct drm_device *); -+extern void nouveau_backlight_exit(struct drm_device *); - #else --static inline int nouveau_backlight_init(struct drm_connector *dev) -+static inline int nouveau_backlight_init(struct drm_device *dev) - { - return 0; - } - --static inline void nouveau_backlight_exit(struct drm_connector *dev) { } -+static inline void nouveau_backlight_exit(struct drm_device *dev) { } - #endif - - /* nouveau_bios.c */ -@@ -1022,7 +1070,8 @@ extern int nouveau_bios_init(struct drm_device *); - extern void nouveau_bios_takedown(struct drm_device *dev); - extern int nouveau_run_vbios_init(struct drm_device *); - extern void nouveau_bios_run_init_table(struct drm_device *, uint16_t table, -- struct dcb_entry *); -+ struct dcb_entry *, int crtc); -+extern void nouveau_bios_init_exec(struct drm_device *, uint16_t table); - extern struct dcb_gpio_entry *nouveau_bios_gpio_entry(struct drm_device *, - enum dcb_gpio_tag); - extern struct dcb_connector_table_entry * -@@ -1030,11 +1079,8 @@ nouveau_bios_connector_entry(struct drm_device *, int index); - extern u32 get_pll_register(struct drm_device *, enum pll_types); - extern int get_pll_limits(struct drm_device *, uint32_t limit_match, - struct pll_lims *); --extern int nouveau_bios_run_display_table(struct drm_device *, -- struct dcb_entry *, -- uint32_t script, int pxclk); --extern void *nouveau_bios_dp_table(struct drm_device *, struct dcb_entry *, -- int *length); -+extern int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, -+ struct dcb_entry *, int crtc); - extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); - extern uint8_t *nouveau_bios_embedded_edid(struct drm_device *); - extern int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk, -@@ -1043,6 +1089,7 @@ extern int run_tmds_table(struct drm_device *, struct dcb_entry *, - int head, int pxclk); - extern int call_lvds_script(struct drm_device *, struct dcb_entry *, int head, - enum LVDS_script, int pxclk); -+bool bios_encoder_match(struct dcb_entry *, u32 hash); - - /* nouveau_ttm.c */ - int nouveau_ttm_global_init(struct drm_nouveau_private *); -@@ -1053,7 +1100,9 @@ int nouveau_ttm_mmap(struct file *, struct vm_area_struct *); - int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, - uint8_t *data, int data_nr); - bool nouveau_dp_detect(struct drm_encoder *); --bool nouveau_dp_link_train(struct drm_encoder *); -+bool nouveau_dp_link_train(struct drm_encoder *, u32 datarate); -+void nouveau_dp_tu_update(struct drm_device *, int, int, u32, u32); -+u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **); - - /* nv04_fb.c */ - extern int nv04_fb_init(struct drm_device *); -@@ -1179,8 +1228,8 @@ extern int nva3_copy_create(struct drm_device *dev); - /* nvc0_copy.c */ - extern int nvc0_copy_create(struct drm_device *dev, int engine); - --/* nv40_mpeg.c */ --extern int nv40_mpeg_create(struct drm_device *dev); -+/* nv31_mpeg.c */ -+extern int nv31_mpeg_create(struct drm_device *dev); - - /* nv50_mpeg.c */ - extern int nv50_mpeg_create(struct drm_device *dev); -@@ -1265,6 +1314,11 @@ extern int nv04_display_create(struct drm_device *); - extern int nv04_display_init(struct drm_device *); - extern void nv04_display_destroy(struct drm_device *); - -+/* nvd0_display.c */ -+extern int nvd0_display_create(struct drm_device *); -+extern int nvd0_display_init(struct drm_device *); -+extern void nvd0_display_destroy(struct drm_device *); -+ - /* nv04_crtc.c */ - extern int nv04_crtc_create(struct drm_device *, int index); - -@@ -1374,6 +1428,8 @@ int nv50_gpio_init(struct drm_device *dev); - void nv50_gpio_fini(struct drm_device *dev); - int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); - int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); -+int nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); -+int nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); - int nv50_gpio_irq_register(struct drm_device *, enum dcb_gpio_tag, - void (*)(void *, int), void *); - void nv50_gpio_irq_unregister(struct drm_device *, enum dcb_gpio_tag, -@@ -1448,6 +1504,8 @@ static inline void nv_wr08(struct drm_device *dev, unsigned reg, u8 val) - nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val)) - #define nv_wait_ne(dev, reg, mask, val) \ - nouveau_wait_ne(dev, 2000000000ULL, (reg), (mask), (val)) -+#define nv_wait_cb(dev, func, data) \ -+ nouveau_wait_cb(dev, 2000000000ULL, (func), (data)) - - /* PRAMIN access */ - static inline u32 nv_ri32(struct drm_device *dev, unsigned offset) -@@ -1514,6 +1572,7 @@ enum { - NOUVEAU_REG_DEBUG_RMVIO = 0x80, - NOUVEAU_REG_DEBUG_VGAATTR = 0x100, - NOUVEAU_REG_DEBUG_EVO = 0x200, -+ NOUVEAU_REG_DEBUG_AUXCH = 0x400 - }; - - #define NV_REG_DEBUG(type, dev, fmt, arg...) do { \ -diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h -index ae69b61..e5d6e3f 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_encoder.h -+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h -@@ -49,17 +49,17 @@ struct nouveau_encoder { - - union { - struct { -- int mc_unknown; -- uint32_t unk0; -- uint32_t unk1; -- int dpcd_version; -+ u8 dpcd[8]; - int link_nr; - int link_bw; -- bool enhanced_frame; -+ u32 datarate; - } dp; - }; - }; - -+struct nouveau_encoder * -+find_encoder(struct drm_connector *connector, int type); -+ - static inline struct nouveau_encoder *nouveau_encoder(struct drm_encoder *enc) - { - struct drm_encoder_slave *slave = to_encoder_slave(enc); -@@ -83,21 +83,4 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder); - int nv50_sor_create(struct drm_connector *, struct dcb_entry *); - int nv50_dac_create(struct drm_connector *, struct dcb_entry *); - --struct bit_displayport_encoder_table { -- uint32_t match; -- uint8_t record_nr; -- uint8_t unknown; -- uint16_t script0; -- uint16_t script1; -- uint16_t unknown_table; --} __attribute__ ((packed)); -- --struct bit_displayport_encoder_table_entry { -- uint8_t vs_level; -- uint8_t pre_level; -- uint8_t reg0; -- uint8_t reg1; -- uint8_t reg2; --} __attribute__ ((packed)); -- - #endif /* __NOUVEAU_ENCODER_H__ */ -diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c -index ae22dfa..2f6daae 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_fence.c -+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c -@@ -519,7 +519,7 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) - 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, -+ ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_FROM_MEMORY, - mem->start << PAGE_SHIFT, - mem->size, NV_MEM_ACCESS_RW, - NV_MEM_TARGET_VRAM, &obj); -diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c -index cb389d0..f6a27fa 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_i2c.c -+++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c -@@ -107,6 +107,13 @@ nv4e_i2c_getsda(void *data) - return !!((nv_rd32(dev, i2c->rd) >> 16) & 8); - } - -+static const uint32_t nv50_i2c_port[] = { -+ 0x00e138, 0x00e150, 0x00e168, 0x00e180, -+ 0x00e254, 0x00e274, 0x00e764, 0x00e780, -+ 0x00e79c, 0x00e7b8 -+}; -+#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port) -+ - static int - nv50_i2c_getscl(void *data) - { -@@ -130,28 +137,32 @@ static void - nv50_i2c_setscl(void *data, int state) - { - struct nouveau_i2c_chan *i2c = data; -- struct drm_device *dev = i2c->dev; - -- nv_wr32(dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0)); -+ nv_wr32(i2c->dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0)); - } - - static void - nv50_i2c_setsda(void *data, int state) - { - struct nouveau_i2c_chan *i2c = data; -- struct drm_device *dev = i2c->dev; - -- nv_wr32(dev, i2c->wr, -- (nv_rd32(dev, i2c->rd) & 1) | 4 | (state ? 2 : 0)); -+ nv_mask(i2c->dev, i2c->wr, 0x00000006, 4 | (state ? 2 : 0)); - i2c->data = state; - } - --static const uint32_t nv50_i2c_port[] = { -- 0x00e138, 0x00e150, 0x00e168, 0x00e180, -- 0x00e254, 0x00e274, 0x00e764, 0x00e780, -- 0x00e79c, 0x00e7b8 --}; --#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port) -+static int -+nvd0_i2c_getscl(void *data) -+{ -+ struct nouveau_i2c_chan *i2c = data; -+ return !!(nv_rd32(i2c->dev, i2c->rd) & 0x10); -+} -+ -+static int -+nvd0_i2c_getsda(void *data) -+{ -+ struct nouveau_i2c_chan *i2c = data; -+ return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20); -+} - - int - nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) -@@ -163,7 +174,8 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) - if (entry->chan) - return -EEXIST; - -- if (dev_priv->card_type >= NV_50 && entry->read >= NV50_I2C_PORTS) { -+ if (dev_priv->card_type >= NV_50 && -+ dev_priv->card_type <= NV_C0 && entry->read >= NV50_I2C_PORTS) { - NV_ERROR(dev, "unknown i2c port %d\n", entry->read); - return -EINVAL; - } -@@ -192,10 +204,17 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) - case 5: - i2c->bit.setsda = nv50_i2c_setsda; - i2c->bit.setscl = nv50_i2c_setscl; -- i2c->bit.getsda = nv50_i2c_getsda; -- i2c->bit.getscl = nv50_i2c_getscl; -- i2c->rd = nv50_i2c_port[entry->read]; -- i2c->wr = i2c->rd; -+ if (dev_priv->card_type < NV_D0) { -+ i2c->bit.getsda = nv50_i2c_getsda; -+ i2c->bit.getscl = nv50_i2c_getscl; -+ i2c->rd = nv50_i2c_port[entry->read]; -+ i2c->wr = i2c->rd; -+ } else { -+ i2c->bit.getsda = nvd0_i2c_getsda; -+ i2c->bit.getscl = nvd0_i2c_getscl; -+ i2c->rd = 0x00d014 + (entry->read * 0x20); -+ i2c->wr = i2c->rd; -+ } - break; - case 6: - i2c->rd = entry->read; -@@ -267,7 +286,10 @@ nouveau_i2c_find(struct drm_device *dev, int index) - val = 0xe001; - } - -- nv_wr32(dev, reg, (nv_rd32(dev, reg) & ~0xf003) | val); -+ /* nfi, but neither auxch or i2c work if it's 1 */ -+ nv_mask(dev, reg + 0x0c, 0x00000001, 0x00000000); -+ /* nfi, but switches auxch vs normal i2c */ -+ nv_mask(dev, reg + 0x00, 0x0000f003, val); - } - - if (!i2c->chan && nouveau_i2c_init(dev, i2c, index)) -diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c -index f9ae2fc..36bec48 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_mem.c -+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c -@@ -408,8 +408,6 @@ nouveau_mem_vram_init(struct drm_device *dev) - if (ret) - return ret; - -- dev_priv->fb_phys = pci_resource_start(dev->pdev, 1); -- - ret = nouveau_ttm_global_init(dev_priv); - if (ret) - return ret; -@@ -504,35 +502,146 @@ nouveau_mem_gart_init(struct drm_device *dev) - return 0; - } - -+/* XXX: For now a dummy. More samples required, possibly even a card -+ * Called from nouveau_perf.c */ -+void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, -+ struct nouveau_pm_tbl_entry *e, uint8_t magic_number, -+ struct nouveau_pm_memtiming *timing) { -+ -+ NV_DEBUG(dev,"Timing entry format unknown, please contact nouveau developers"); -+} -+ -+void nv40_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, -+ struct nouveau_pm_tbl_entry *e, uint8_t magic_number, -+ struct nouveau_pm_memtiming *timing) { -+ -+ timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP); -+ -+ /* XXX: I don't trust the -1's and +1's... they must come -+ * from somewhere! */ -+ timing->reg_1 = (e->tWR + 2 + magic_number) << 24 | -+ 1 << 16 | -+ (e->tUNK_1 + 2 + magic_number) << 8 | -+ (e->tCL + 2 - magic_number); -+ timing->reg_2 = (magic_number << 24 | e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10); -+ timing->reg_2 |= 0x20200000; -+ -+ NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x\n", timing->id, -+ timing->reg_0, timing->reg_1,timing->reg_2); -+} -+ -+void nv50_mem_timing_entry(struct drm_device *dev, struct bit_entry *P, struct nouveau_pm_tbl_header *hdr, -+ struct nouveau_pm_tbl_entry *e, uint8_t magic_number,struct nouveau_pm_memtiming *timing) { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ uint8_t unk18 = 1, -+ unk19 = 1, -+ unk20 = 0, -+ unk21 = 0; -+ -+ switch (min(hdr->entry_len, (u8) 22)) { -+ case 22: -+ unk21 = e->tUNK_21; -+ case 21: -+ unk20 = e->tUNK_20; -+ case 20: -+ unk19 = e->tUNK_19; -+ case 19: -+ unk18 = e->tUNK_18; -+ break; -+ } -+ -+ timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP); -+ -+ /* XXX: I don't trust the -1's and +1's... they must come -+ * from somewhere! */ -+ timing->reg_1 = (e->tWR + unk19 + 1 + magic_number) << 24 | -+ max(unk18, (u8) 1) << 16 | -+ (e->tUNK_1 + unk19 + 1 + magic_number) << 8; -+ if (dev_priv->chipset == 0xa8) { -+ timing->reg_1 |= (e->tCL - 1); -+ } else { -+ timing->reg_1 |= (e->tCL + 2 - magic_number); -+ } -+ timing->reg_2 = (e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10); -+ -+ timing->reg_5 = (e->tRAS << 24 | e->tRC); -+ timing->reg_5 += max(e->tUNK_10, e->tUNK_11) << 16; -+ -+ if (P->version == 1) { -+ timing->reg_2 |= magic_number << 24; -+ timing->reg_3 = (0x14 + e->tCL) << 24 | -+ 0x16 << 16 | -+ (e->tCL - 1) << 8 | -+ (e->tCL - 1); -+ timing->reg_4 = (nv_rd32(dev,0x10022c) & 0xffff0000) | e->tUNK_13 << 8 | e->tUNK_13; -+ timing->reg_5 |= (e->tCL + 2) << 8; -+ timing->reg_7 = 0x4000202 | (e->tCL - 1) << 16; -+ } else { -+ timing->reg_2 |= (unk19 - 1) << 24; -+ /* XXX: reg_10022c for recentish cards pretty much unknown*/ -+ timing->reg_3 = e->tCL - 1; -+ timing->reg_4 = (unk20 << 24 | unk21 << 16 | -+ e->tUNK_13 << 8 | e->tUNK_13); -+ /* XXX: +6? */ -+ timing->reg_5 |= (unk19 + 6) << 8; -+ -+ /* XXX: reg_10023c currently unknown -+ * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */ -+ timing->reg_7 = 0x202; -+ } -+ -+ NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", timing->id, -+ timing->reg_0, timing->reg_1, -+ timing->reg_2, timing->reg_3); -+ NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n", -+ timing->reg_4, timing->reg_5, -+ timing->reg_6, timing->reg_7); -+ NV_DEBUG(dev, " 240: %08x\n", timing->reg_8); -+} -+ -+void nvc0_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, -+ struct nouveau_pm_tbl_entry *e, struct nouveau_pm_memtiming *timing) { -+ timing->reg_0 = (e->tRC << 24 | (e->tRFC & 0x7f) << 17 | e->tRAS << 8 | e->tRP); -+ timing->reg_1 = (nv_rd32(dev,0x10f294) & 0xff000000) | (e->tUNK_11&0x0f) << 20 | (e->tUNK_19 << 7) | (e->tCL & 0x0f); -+ timing->reg_2 = (nv_rd32(dev,0x10f298) & 0xff0000ff) | e->tWR << 16 | e->tUNK_1 << 8; -+ timing->reg_3 = e->tUNK_20 << 9 | e->tUNK_13; -+ timing->reg_4 = (nv_rd32(dev,0x10f2a0) & 0xfff000ff) | e->tUNK_12 << 15; -+ NV_DEBUG(dev, "Entry %d: 290: %08x %08x %08x %08x\n", timing->id, -+ timing->reg_0, timing->reg_1, -+ timing->reg_2, timing->reg_3); -+ NV_DEBUG(dev, " 2a0: %08x %08x %08x %08x\n", -+ timing->reg_4, timing->reg_5, -+ timing->reg_6, timing->reg_7); -+} -+ -+/** -+ * Processes the Memory Timing BIOS table, stores generated -+ * register values -+ * @pre init scripts were run, memtiming regs are initialized -+ */ - void - nouveau_mem_timing_init(struct drm_device *dev) - { -- /* cards < NVC0 only */ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - struct nouveau_pm_memtimings *memtimings = &pm->memtimings; - struct nvbios *bios = &dev_priv->vbios; - struct bit_entry P; -- u8 tUNK_0, tUNK_1, tUNK_2; -- u8 tRP; /* Byte 3 */ -- u8 tRAS; /* Byte 5 */ -- u8 tRFC; /* Byte 7 */ -- 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; -+ struct nouveau_pm_tbl_header *hdr = NULL; -+ uint8_t magic_number; -+ u8 *entry; -+ int i; - - if (bios->type == NVBIOS_BIT) { - if (bit_table(dev, 'P', &P)) - return; - - if (P.version == 1) -- mem = ROMPTR(bios, P.data[4]); -+ hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[4]); - else - if (P.version == 2) -- mem = ROMPTR(bios, P.data[8]); -+ hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[8]); - else { - NV_WARN(dev, "unknown mem for BIT P %d\n", P.version); - } -@@ -541,150 +650,56 @@ nouveau_mem_timing_init(struct drm_device *dev) - return; - } - -- if (!mem) { -+ if (!hdr) { - NV_DEBUG(dev, "memory timing table pointer invalid\n"); - return; - } - -- if (mem[0] != 0x10) { -- NV_WARN(dev, "memory timing table 0x%02x unknown\n", mem[0]); -+ if (hdr->version != 0x10) { -+ NV_WARN(dev, "memory timing table 0x%02x unknown\n", hdr->version); - return; - } - - /* validate record length */ -- entries = mem[2]; -- recordlen = mem[3]; -- if (recordlen < 15) { -- NV_ERROR(dev, "mem timing table length unknown: %d\n", mem[3]); -+ if (hdr->entry_len < 15) { -+ NV_ERROR(dev, "mem timing table length unknown: %d\n", hdr->entry_len); - return; - } - - /* parse vbios entries into common format */ - memtimings->timing = -- kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL); -+ kcalloc(hdr->entry_cnt, sizeof(*memtimings->timing), GFP_KERNEL); - 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) { -+ * Used in calculations later... source unknown */ -+ magic_number = 0; -+ if (P.version == 1) { - magic_number = (nv_rd32(dev, 0x100228) & 0x0f000000) >> 24; - } - -- entry = mem + mem[1]; -- for (i = 0; i < entries; i++, entry += recordlen) { -+ entry = (u8*) hdr + hdr->header_len; -+ for (i = 0; i < hdr->entry_cnt; i++, entry += hdr->entry_len) { - struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i]; - if (entry[0] == 0) - continue; - -- tUNK_18 = 1; -- tUNK_19 = 1; -- tUNK_20 = 0; -- tUNK_21 = 0; -- switch (min(recordlen, 22)) { -- case 22: -- tUNK_21 = entry[21]; -- case 21: -- tUNK_20 = entry[20]; -- case 20: -- tUNK_19 = entry[19]; -- case 19: -- tUNK_18 = entry[18]; -- default: -- tUNK_0 = entry[0]; -- tUNK_1 = entry[1]; -- tUNK_2 = entry[2]; -- tRP = entry[3]; -- tRAS = entry[5]; -- tRFC = entry[7]; -- tRC = entry[9]; -- tUNK_10 = entry[10]; -- tUNK_11 = entry[11]; -- tUNK_12 = entry[12]; -- tUNK_13 = entry[13]; -- tUNK_14 = entry[14]; -- break; -- } -- -- timing->reg_100220 = (tRC << 24 | tRFC << 16 | tRAS << 8 | tRP); -- -- /* XXX: I don't trust the -1's and +1's... they must come -- * from somewhere! */ -- 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 (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? */ -- } - timing->id = i; -+ timing->WR = entry[0]; -+ timing->CL = entry[2]; - -- NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, -- timing->reg_100220, timing->reg_100224, -- timing->reg_100228, timing->reg_10022c); -- 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); -+ if(dev_priv->card_type <= NV_40) { -+ nv40_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]); -+ } else if(dev_priv->card_type == NV_50){ -+ nv50_mem_timing_entry(dev,&P,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]); -+ } else if(dev_priv->card_type == NV_C0) { -+ nvc0_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,&pm->memtimings.timing[i]); -+ } - } - -- memtimings->nr_timing = entries; -- memtimings->supported = (dev_priv->chipset <= 0x98); -+ memtimings->nr_timing = hdr->entry_cnt; -+ memtimings->supported = P.version == 1; - } - - void -@@ -693,7 +708,10 @@ nouveau_mem_timing_fini(struct drm_device *dev) - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_memtimings *mem = &dev_priv->engine.pm.memtimings; - -- kfree(mem->timing); -+ if(mem->timing) { -+ kfree(mem->timing); -+ mem->timing = NULL; -+ } - } - - static int -diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.c b/drivers/gpu/drm/nouveau/nouveau_mm.c -index 1640dec..b29ffb3 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_mm.c -+++ b/drivers/gpu/drm/nouveau/nouveau_mm.c -@@ -27,7 +27,7 @@ - #include "nouveau_mm.h" - - static inline void --region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a) -+region_put(struct nouveau_mm *mm, struct nouveau_mm_node *a) - { - list_del(&a->nl_entry); - list_del(&a->fl_entry); -@@ -35,7 +35,7 @@ region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a) - } - - static struct nouveau_mm_node * --region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size) -+region_split(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) - { - struct nouveau_mm_node *b; - -@@ -57,33 +57,33 @@ region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size) - return b; - } - --#define node(root, dir) ((root)->nl_entry.dir == &rmm->nodes) ? NULL : \ -+#define node(root, dir) ((root)->nl_entry.dir == &mm->nodes) ? NULL : \ - list_entry((root)->nl_entry.dir, struct nouveau_mm_node, nl_entry) - - void --nouveau_mm_put(struct nouveau_mm *rmm, struct nouveau_mm_node *this) -+nouveau_mm_put(struct nouveau_mm *mm, struct nouveau_mm_node *this) - { - struct nouveau_mm_node *prev = node(this, prev); - struct nouveau_mm_node *next = node(this, next); - -- list_add(&this->fl_entry, &rmm->free); -+ list_add(&this->fl_entry, &mm->free); - this->type = 0; - - if (prev && prev->type == 0) { - prev->length += this->length; -- region_put(rmm, this); -+ region_put(mm, this); - this = prev; - } - - if (next && next->type == 0) { - next->offset = this->offset; - next->length += this->length; -- region_put(rmm, this); -+ region_put(mm, this); - } - } - - int --nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, -+nouveau_mm_get(struct nouveau_mm *mm, int type, u32 size, u32 size_nc, - u32 align, struct nouveau_mm_node **pnode) - { - struct nouveau_mm_node *prev, *this, *next; -@@ -92,17 +92,17 @@ nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, - u32 splitoff; - u32 s, e; - -- list_for_each_entry(this, &rmm->free, fl_entry) { -+ list_for_each_entry(this, &mm->free, fl_entry) { - e = this->offset + this->length; - s = this->offset; - - prev = node(this, prev); - if (prev && prev->type != type) -- s = roundup(s, rmm->block_size); -+ s = roundup(s, mm->block_size); - - next = node(this, next); - if (next && next->type != type) -- e = rounddown(e, rmm->block_size); -+ e = rounddown(e, mm->block_size); - - s = (s + align_mask) & ~align_mask; - e &= ~align_mask; -@@ -110,10 +110,10 @@ nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, - continue; - - splitoff = s - this->offset; -- if (splitoff && !region_split(rmm, this, splitoff)) -+ if (splitoff && !region_split(mm, this, splitoff)) - return -ENOMEM; - -- this = region_split(rmm, this, min(size, e - s)); -+ this = region_split(mm, this, min(size, e - s)); - if (!this) - return -ENOMEM; - -@@ -127,52 +127,49 @@ nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, - } - - int --nouveau_mm_init(struct nouveau_mm **prmm, u32 offset, u32 length, u32 block) -+nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block) - { -- struct nouveau_mm *rmm; -- struct nouveau_mm_node *heap; -+ struct nouveau_mm_node *node; - -- heap = kzalloc(sizeof(*heap), GFP_KERNEL); -- if (!heap) -- return -ENOMEM; -- heap->offset = roundup(offset, block); -- heap->length = rounddown(offset + length, block) - heap->offset; -+ if (block) { -+ mutex_init(&mm->mutex); -+ INIT_LIST_HEAD(&mm->nodes); -+ INIT_LIST_HEAD(&mm->free); -+ mm->block_size = block; -+ mm->heap_nodes = 0; -+ } - -- rmm = kzalloc(sizeof(*rmm), GFP_KERNEL); -- if (!rmm) { -- kfree(heap); -+ node = kzalloc(sizeof(*node), GFP_KERNEL); -+ if (!node) - return -ENOMEM; -- } -- rmm->block_size = block; -- mutex_init(&rmm->mutex); -- INIT_LIST_HEAD(&rmm->nodes); -- INIT_LIST_HEAD(&rmm->free); -- list_add(&heap->nl_entry, &rmm->nodes); -- list_add(&heap->fl_entry, &rmm->free); -+ node->offset = roundup(offset, mm->block_size); -+ node->length = rounddown(offset + length, mm->block_size) - node->offset; - -- *prmm = rmm; -+ list_add_tail(&node->nl_entry, &mm->nodes); -+ list_add_tail(&node->fl_entry, &mm->free); -+ mm->heap_nodes++; - return 0; - } - - int --nouveau_mm_fini(struct nouveau_mm **prmm) -+nouveau_mm_fini(struct nouveau_mm *mm) - { -- struct nouveau_mm *rmm = *prmm; - struct nouveau_mm_node *node, *heap = -- list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry); -+ list_first_entry(&mm->nodes, struct nouveau_mm_node, nl_entry); -+ int nodes = 0; - -- if (!list_is_singular(&rmm->nodes)) { -- printk(KERN_ERR "nouveau_mm not empty at destroy time!\n"); -- list_for_each_entry(node, &rmm->nodes, nl_entry) { -- printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n", -- node->type, node->offset, node->length); -+ list_for_each_entry(node, &mm->nodes, nl_entry) { -+ if (nodes++ == mm->heap_nodes) { -+ printk(KERN_ERR "nouveau_mm in use at destroy time!\n"); -+ list_for_each_entry(node, &mm->nodes, nl_entry) { -+ printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n", -+ node->type, node->offset, node->length); -+ } -+ WARN_ON(1); -+ return -EBUSY; - } -- WARN_ON(1); -- return -EBUSY; - } - - kfree(heap); -- kfree(rmm); -- *prmm = NULL; - return 0; - } -diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.h b/drivers/gpu/drm/nouveau/nouveau_mm.h -index b9c016d..57a600c 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_mm.h -+++ b/drivers/gpu/drm/nouveau/nouveau_mm.h -@@ -42,10 +42,11 @@ struct nouveau_mm { - struct mutex mutex; - - u32 block_size; -+ int heap_nodes; - }; - --int nouveau_mm_init(struct nouveau_mm **, u32 offset, u32 length, u32 block); --int nouveau_mm_fini(struct nouveau_mm **); -+int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block); -+int nouveau_mm_fini(struct nouveau_mm *); - int nouveau_mm_pre(struct nouveau_mm *); - int nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc, - u32 align, struct nouveau_mm_node **); -diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c -index 159b7c4..02222c5 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_object.c -+++ b/drivers/gpu/drm/nouveau/nouveau_object.c -@@ -693,6 +693,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) - static int - nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm) - { -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct drm_device *dev = chan->dev; - struct nouveau_gpuobj *pgd = NULL; - struct nouveau_vm_pgd *vpgd; -@@ -722,6 +723,9 @@ nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm) - nv_wo32(chan->ramin, 0x020c, 0x000000ff); - - /* map display semaphore buffers into channel's vm */ -+ if (dev_priv->card_type >= NV_D0) -+ return 0; -+ - for (i = 0; i < 2; i++) { - struct nv50_display_crtc *dispc = &nv50_display(dev)->crtc[i]; - -@@ -746,7 +750,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, - int ret, i; - - NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); -- if (dev_priv->card_type == NV_C0) -+ if (dev_priv->card_type >= NV_C0) - return nvc0_gpuobj_channel_init(chan, vm); - - /* Allocate a chunk of memory for per-channel object storage */ -@@ -793,7 +797,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, - return ret; - - /* dma objects for display sync channel semaphore blocks */ -- for (i = 0; i < 2; i++) { -+ for (i = 0; i < dev->mode_config.num_crtc; i++) { - struct nouveau_gpuobj *sem = NULL; - struct nv50_display_crtc *dispc = - &nv50_display(dev)->crtc[i]; -@@ -875,18 +879,18 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) - - NV_DEBUG(dev, "ch%d\n", chan->id); - -- if (dev_priv->card_type >= NV_50) { -+ if (dev_priv->card_type >= NV_50 && dev_priv->card_type <= NV_C0) { - struct nv50_display *disp = nv50_display(dev); - -- for (i = 0; i < 2; i++) { -+ for (i = 0; i < dev->mode_config.num_crtc; i++) { - struct nv50_display_crtc *dispc = &disp->crtc[i]; - nouveau_bo_vma_del(dispc->sem.bo, &chan->dispc_vma[i]); - } -- -- nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); -- nouveau_gpuobj_ref(NULL, &chan->vm_pd); - } - -+ nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); -+ nouveau_gpuobj_ref(NULL, &chan->vm_pd); -+ - if (drm_mm_initialized(&chan->ramin_heap)) - drm_mm_takedown(&chan->ramin_heap); - nouveau_gpuobj_ref(NULL, &chan->ramin); -diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c -index ef9dec0..9f178aa 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_perf.c -+++ b/drivers/gpu/drm/nouveau/nouveau_perf.c -@@ -127,13 +127,57 @@ nouveau_perf_timing(struct drm_device *dev, struct bit_entry *P, - - entry += ramcfg * recordlen; - if (entry[1] >= pm->memtimings.nr_timing) { -- NV_WARN(dev, "timingset %d does not exist\n", entry[1]); -+ if (entry[1] != 0xff) -+ NV_WARN(dev, "timingset %d does not exist\n", entry[1]); - return NULL; - } - - return &pm->memtimings.timing[entry[1]]; - } - -+static void -+nouveau_perf_voltage(struct drm_device *dev, struct bit_entry *P, -+ struct nouveau_pm_level *perflvl) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nvbios *bios = &dev_priv->vbios; -+ u8 *vmap; -+ int id; -+ -+ id = perflvl->volt_min; -+ perflvl->volt_min = 0; -+ -+ /* boards using voltage table version <0x40 store the voltage -+ * level directly in the perflvl entry as a multiple of 10mV -+ */ -+ if (dev_priv->engine.pm.voltage.version < 0x40) { -+ perflvl->volt_min = id * 10000; -+ perflvl->volt_max = perflvl->volt_min; -+ return; -+ } -+ -+ /* on newer ones, the perflvl stores an index into yet another -+ * vbios table containing a min/max voltage value for the perflvl -+ */ -+ if (P->version != 2 || P->length < 34) { -+ NV_DEBUG(dev, "where's our volt map table ptr? %d %d\n", -+ P->version, P->length); -+ return; -+ } -+ -+ vmap = ROMPTR(bios, P->data[32]); -+ if (!vmap) { -+ NV_DEBUG(dev, "volt map table pointer invalid\n"); -+ return; -+ } -+ -+ if (id < vmap[3]) { -+ vmap += vmap[1] + (vmap[2] * id); -+ perflvl->volt_min = ROM32(vmap[0]); -+ perflvl->volt_max = ROM32(vmap[4]); -+ } -+} -+ - void - nouveau_perf_init(struct drm_device *dev) - { -@@ -141,6 +185,8 @@ nouveau_perf_init(struct drm_device *dev) - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - struct nvbios *bios = &dev_priv->vbios; - struct bit_entry P; -+ struct nouveau_pm_memtimings *memtimings = &pm->memtimings; -+ struct nouveau_pm_tbl_header mt_hdr; - u8 version, headerlen, recordlen, entries; - u8 *perf, *entry; - int vid, i; -@@ -188,6 +234,22 @@ nouveau_perf_init(struct drm_device *dev) - } - - entry = perf + headerlen; -+ -+ /* For version 0x15, initialize memtiming table */ -+ if(version == 0x15) { -+ memtimings->timing = -+ kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL); -+ if(!memtimings) { -+ NV_WARN(dev,"Could not allocate memtiming table\n"); -+ return; -+ } -+ -+ mt_hdr.entry_cnt = entries; -+ mt_hdr.entry_len = 14; -+ mt_hdr.version = version; -+ mt_hdr.header_len = 4; -+ } -+ - for (i = 0; i < entries; i++) { - struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; - -@@ -203,7 +265,8 @@ nouveau_perf_init(struct drm_device *dev) - case 0x13: - case 0x15: - perflvl->fanspeed = entry[55]; -- perflvl->voltage = (recordlen > 56) ? entry[56] : 0; -+ if (recordlen > 56) -+ perflvl->volt_min = entry[56]; - perflvl->core = ROM32(entry[1]) * 10; - perflvl->memory = ROM32(entry[5]) * 20; - break; -@@ -211,9 +274,10 @@ nouveau_perf_init(struct drm_device *dev) - case 0x23: - case 0x24: - perflvl->fanspeed = entry[4]; -- perflvl->voltage = entry[5]; -- perflvl->core = ROM16(entry[6]) * 1000; -- -+ perflvl->volt_min = entry[5]; -+ perflvl->shader = ROM16(entry[6]) * 1000; -+ perflvl->core = perflvl->shader; -+ perflvl->core += (signed char)entry[8] * 1000; - if (dev_priv->chipset == 0x49 || - dev_priv->chipset == 0x4b) - perflvl->memory = ROM16(entry[11]) * 1000; -@@ -223,7 +287,7 @@ nouveau_perf_init(struct drm_device *dev) - break; - case 0x25: - perflvl->fanspeed = entry[4]; -- perflvl->voltage = entry[5]; -+ perflvl->volt_min = entry[5]; - perflvl->core = ROM16(entry[6]) * 1000; - perflvl->shader = ROM16(entry[10]) * 1000; - perflvl->memory = ROM16(entry[12]) * 1000; -@@ -232,7 +296,7 @@ nouveau_perf_init(struct drm_device *dev) - perflvl->memscript = ROM16(entry[2]); - case 0x35: - perflvl->fanspeed = entry[6]; -- perflvl->voltage = entry[7]; -+ perflvl->volt_min = entry[7]; - perflvl->core = ROM16(entry[8]) * 1000; - perflvl->shader = ROM16(entry[10]) * 1000; - perflvl->memory = ROM16(entry[12]) * 1000; -@@ -240,30 +304,34 @@ nouveau_perf_init(struct drm_device *dev) - perflvl->unk05 = ROM16(entry[16]) * 1000; - break; - case 0x40: --#define subent(n) entry[perf[2] + ((n) * perf[3])] -+#define subent(n) (ROM16(entry[perf[2] + ((n) * perf[3])]) & 0xfff) * 1000 - perflvl->fanspeed = 0; /*XXX*/ -- perflvl->voltage = entry[2]; -+ perflvl->volt_min = entry[2]; - 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; -+ perflvl->core = subent(0); -+ perflvl->shader = subent(1); -+ perflvl->memory = subent(2); -+ perflvl->vdec = subent(3); -+ perflvl->unka0 = subent(4); - } else { -- perflvl->shader = ROM16(subent(3)) & 0xfff; -+ perflvl->hub06 = subent(0); -+ perflvl->hub01 = subent(1); -+ perflvl->copy = subent(2); -+ perflvl->shader = subent(3); -+ perflvl->rop = subent(4); -+ perflvl->memory = subent(5); -+ perflvl->vdec = subent(6); -+ perflvl->daemon = subent(10); -+ perflvl->hub07 = subent(11); - 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; - } - - /* make sure vid is valid */ -- if (pm->voltage.supported && perflvl->voltage) { -- vid = nouveau_volt_vid_lookup(dev, perflvl->voltage); -+ nouveau_perf_voltage(dev, &P, perflvl); -+ if (pm->voltage.supported && perflvl->volt_min) { -+ vid = nouveau_volt_vid_lookup(dev, perflvl->volt_min); - if (vid < 0) { - NV_DEBUG(dev, "drop perflvl %d, bad vid\n", i); - entry += recordlen; -@@ -272,7 +340,11 @@ nouveau_perf_init(struct drm_device *dev) - } - - /* get the corresponding memory timings */ -- if (version > 0x15) { -+ if (version == 0x15) { -+ memtimings->timing[i].id = i; -+ nv30_mem_timing_entry(dev,&mt_hdr,(struct nouveau_pm_tbl_entry*) &entry[41],0,&memtimings->timing[i]); -+ perflvl->timing = &memtimings->timing[i]; -+ } else if (version > 0x15) { - /* last 3 args are for < 0x40, ignored for >= 0x40 */ - perflvl->timing = - nouveau_perf_timing(dev, &P, -diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c -index da8d994..a539fd2 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_pm.c -+++ b/drivers/gpu/drm/nouveau/nouveau_pm.c -@@ -64,18 +64,26 @@ nouveau_pm_perflvl_set(struct drm_device *dev, struct nouveau_pm_level *perflvl) - if (perflvl == pm->cur) - return 0; - -- if (pm->voltage.supported && pm->voltage_set && perflvl->voltage) { -- ret = pm->voltage_set(dev, perflvl->voltage); -+ if (pm->voltage.supported && pm->voltage_set && perflvl->volt_min) { -+ ret = pm->voltage_set(dev, perflvl->volt_min); - if (ret) { - NV_ERROR(dev, "voltage_set %d failed: %d\n", -- perflvl->voltage, ret); -+ perflvl->volt_min, ret); - } - } - -- nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core); -- nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader); -- nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory); -- nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05); -+ if (pm->clocks_pre) { -+ void *state = pm->clocks_pre(dev, perflvl); -+ if (IS_ERR(state)) -+ return PTR_ERR(state); -+ pm->clocks_set(dev, state); -+ } else -+ if (pm->clock_set) { -+ nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core); -+ nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader); -+ nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory); -+ nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05); -+ } - - pm->cur = perflvl; - return 0; -@@ -92,9 +100,6 @@ nouveau_pm_profile_set(struct drm_device *dev, const char *profile) - if (nouveau_perflvl_wr != 7777) - return -EPERM; - -- if (!pm->clock_set) -- return -EINVAL; -- - if (!strncmp(profile, "boot", 4)) - perflvl = &pm->boot; - else { -@@ -123,31 +128,37 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - int ret; - -- if (!pm->clock_get) -- return -EINVAL; -- - memset(perflvl, 0, sizeof(*perflvl)); - -- ret = pm->clock_get(dev, PLL_CORE); -- if (ret > 0) -- perflvl->core = ret; -+ if (pm->clocks_get) { -+ ret = pm->clocks_get(dev, perflvl); -+ if (ret) -+ return ret; -+ } else -+ if (pm->clock_get) { -+ ret = pm->clock_get(dev, PLL_CORE); -+ if (ret > 0) -+ perflvl->core = ret; - -- ret = pm->clock_get(dev, PLL_MEMORY); -- if (ret > 0) -- perflvl->memory = ret; -+ ret = pm->clock_get(dev, PLL_MEMORY); -+ if (ret > 0) -+ perflvl->memory = ret; - -- ret = pm->clock_get(dev, PLL_SHADER); -- if (ret > 0) -- perflvl->shader = ret; -+ ret = pm->clock_get(dev, PLL_SHADER); -+ if (ret > 0) -+ perflvl->shader = ret; - -- ret = pm->clock_get(dev, PLL_UNK05); -- if (ret > 0) -- perflvl->unk05 = ret; -+ ret = pm->clock_get(dev, PLL_UNK05); -+ if (ret > 0) -+ perflvl->unk05 = ret; -+ } - - if (pm->voltage.supported && pm->voltage_get) { - ret = pm->voltage_get(dev); -- if (ret > 0) -- perflvl->voltage = ret; -+ if (ret > 0) { -+ perflvl->volt_min = ret; -+ perflvl->volt_max = ret; -+ } - } - - return 0; -@@ -156,7 +167,7 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) - static void - nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) - { -- char c[16], s[16], v[16], f[16], t[16]; -+ char c[16], s[16], v[32], f[16], t[16], m[16]; - - c[0] = '\0'; - if (perflvl->core) -@@ -166,9 +177,19 @@ nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) - if (perflvl->shader) - snprintf(s, sizeof(s), " shader %dMHz", perflvl->shader / 1000); - -+ m[0] = '\0'; -+ if (perflvl->memory) -+ snprintf(m, sizeof(m), " memory %dMHz", perflvl->memory / 1000); -+ - v[0] = '\0'; -- if (perflvl->voltage) -- snprintf(v, sizeof(v), " voltage %dmV", perflvl->voltage * 10); -+ if (perflvl->volt_min && perflvl->volt_min != perflvl->volt_max) { -+ snprintf(v, sizeof(v), " voltage %dmV-%dmV", -+ perflvl->volt_min / 1000, perflvl->volt_max / 1000); -+ } else -+ if (perflvl->volt_min) { -+ snprintf(v, sizeof(v), " voltage %dmV", -+ perflvl->volt_min / 1000); -+ } - - f[0] = '\0'; - if (perflvl->fanspeed) -@@ -178,8 +199,7 @@ nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) - if (perflvl->timing) - snprintf(t, sizeof(t), " timing %d", perflvl->timing->id); - -- snprintf(ptr, len, "memory %dMHz%s%s%s%s%s\n", perflvl->memory / 1000, -- c, s, v, f, t); -+ snprintf(ptr, len, "%s%s%s%s%s%s\n", c, s, m, t, v, f); - } - - static ssize_t -@@ -190,7 +210,7 @@ nouveau_pm_get_perflvl_info(struct device *d, - char *ptr = buf; - int len = PAGE_SIZE; - -- snprintf(ptr, len, "%d: ", perflvl->id); -+ snprintf(ptr, len, "%d:", perflvl->id); - ptr += strlen(buf); - len -= strlen(buf); - -@@ -211,9 +231,9 @@ nouveau_pm_get_perflvl(struct device *d, struct device_attribute *a, char *buf) - if (!pm->cur) - snprintf(ptr, len, "setting: boot\n"); - else if (pm->cur == &pm->boot) -- snprintf(ptr, len, "setting: boot\nc: "); -+ snprintf(ptr, len, "setting: boot\nc:"); - else -- snprintf(ptr, len, "setting: static %d\nc: ", pm->cur->id); -+ snprintf(ptr, len, "setting: static %d\nc:", pm->cur->id); - ptr += strlen(buf); - len -= strlen(buf); - -@@ -292,7 +312,7 @@ nouveau_sysfs_fini(struct drm_device *dev) - } - } - --#ifdef CONFIG_HWMON -+#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) - static ssize_t - nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) - { -@@ -409,7 +429,7 @@ static const struct attribute_group hwmon_attrgroup = { - static int - nouveau_hwmon_init(struct drm_device *dev) - { --#ifdef CONFIG_HWMON -+#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - struct device *hwmon_dev; -@@ -442,7 +462,7 @@ nouveau_hwmon_init(struct drm_device *dev) - static void - nouveau_hwmon_fini(struct drm_device *dev) - { --#ifdef CONFIG_HWMON -+#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - -@@ -488,7 +508,7 @@ nouveau_pm_init(struct drm_device *dev) - NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl); - for (i = 0; i < pm->nr_perflvl; i++) { - nouveau_pm_perflvl_info(&pm->perflvl[i], info, sizeof(info)); -- NV_INFO(dev, "%d: %s", pm->perflvl[i].id, info); -+ NV_INFO(dev, "%d:%s", pm->perflvl[i].id, info); - } - - /* determine current ("boot") performance level */ -@@ -498,7 +518,7 @@ nouveau_pm_init(struct drm_device *dev) - pm->cur = &pm->boot; - - nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info)); -- NV_INFO(dev, "c: %s", info); -+ NV_INFO(dev, "c:%s", info); - } - - /* switch performance levels now if requested */ -diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.h b/drivers/gpu/drm/nouveau/nouveau_pm.h -index 4a9838dd..8ac02cd 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_pm.h -+++ b/drivers/gpu/drm/nouveau/nouveau_pm.h -@@ -52,6 +52,11 @@ void *nv04_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, - u32 id, int khz); - void nv04_pm_clock_set(struct drm_device *, void *); - -+/* nv40_pm.c */ -+int nv40_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); -+void *nv40_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); -+void nv40_pm_clocks_set(struct drm_device *, void *); -+ - /* nv50_pm.c */ - int nv50_pm_clock_get(struct drm_device *, u32 id); - void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, -@@ -59,10 +64,12 @@ void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, - void nv50_pm_clock_set(struct drm_device *, void *); - - /* nva3_pm.c */ --int nva3_pm_clock_get(struct drm_device *, u32 id); --void *nva3_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, -- u32 id, int khz); --void nva3_pm_clock_set(struct drm_device *, void *); -+int nva3_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); -+void *nva3_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); -+void nva3_pm_clocks_set(struct drm_device *, void *); -+ -+/* nvc0_pm.c */ -+int nvc0_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); - - /* nouveau_temp.c */ - void nouveau_temp_init(struct drm_device *dev); -diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h -index f18cdfc..43a96b9 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_reg.h -+++ b/drivers/gpu/drm/nouveau/nouveau_reg.h -@@ -826,9 +826,12 @@ - #define NV50_PDISPLAY_SOR_DPMS_STATE_ACTIVE 0x00030000 - #define NV50_PDISPLAY_SOR_DPMS_STATE_BLANKED 0x00080000 - #define NV50_PDISPLAY_SOR_DPMS_STATE_WAIT 0x10000000 --#define NV50_PDISPLAY_SOR_BACKLIGHT 0x0061c084 --#define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000 --#define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff -+#define NV50_PDISP_SOR_PWM_DIV(i) (0x0061c080 + (i) * 0x800) -+#define NV50_PDISP_SOR_PWM_CTL(i) (0x0061c084 + (i) * 0x800) -+#define NV50_PDISP_SOR_PWM_CTL_NEW 0x80000000 -+#define NVA3_PDISP_SOR_PWM_CTL_UNK 0x40000000 -+#define NV50_PDISP_SOR_PWM_CTL_VAL 0x000007ff -+#define NVA3_PDISP_SOR_PWM_CTL_VAL 0x00ffffff - #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 -@@ -843,7 +846,7 @@ - #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_SCFG(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) -diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c -index 2706cb3..c8a463b 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c -+++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c -@@ -12,8 +12,8 @@ struct nouveau_sgdma_be { - struct drm_device *dev; - - dma_addr_t *pages; -- bool *ttm_alloced; - unsigned nr_pages; -+ bool unmap_pages; - - u64 offset; - bool bound; -@@ -26,43 +26,28 @@ nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages, - { - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; - struct drm_device *dev = nvbe->dev; -+ int i; - - NV_DEBUG(nvbe->dev, "num_pages = %ld\n", num_pages); - -- if (nvbe->pages) -- return -EINVAL; -- -- nvbe->pages = kmalloc(sizeof(dma_addr_t) * num_pages, GFP_KERNEL); -- if (!nvbe->pages) -- return -ENOMEM; -+ nvbe->pages = dma_addrs; -+ nvbe->nr_pages = num_pages; -+ nvbe->unmap_pages = true; - -- nvbe->ttm_alloced = kmalloc(sizeof(bool) * num_pages, GFP_KERNEL); -- if (!nvbe->ttm_alloced) { -- kfree(nvbe->pages); -- nvbe->pages = NULL; -- return -ENOMEM; -+ /* this code path isn't called and is incorrect anyways */ -+ if (0) { /* dma_addrs[0] != DMA_ERROR_CODE) { */ -+ nvbe->unmap_pages = false; -+ return 0; - } - -- nvbe->nr_pages = 0; -- while (num_pages--) { -- /* this code path isn't called and is incorrect anyways */ -- if (0) { /*dma_addrs[nvbe->nr_pages] != DMA_ERROR_CODE)*/ -- nvbe->pages[nvbe->nr_pages] = -- dma_addrs[nvbe->nr_pages]; -- nvbe->ttm_alloced[nvbe->nr_pages] = true; -- } else { -- nvbe->pages[nvbe->nr_pages] = -- pci_map_page(dev->pdev, pages[nvbe->nr_pages], 0, -- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); -- if (pci_dma_mapping_error(dev->pdev, -- nvbe->pages[nvbe->nr_pages])) { -- be->func->clear(be); -- return -EFAULT; -- } -- nvbe->ttm_alloced[nvbe->nr_pages] = false; -+ for (i = 0; i < num_pages; i++) { -+ nvbe->pages[i] = pci_map_page(dev->pdev, pages[i], 0, -+ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); -+ if (pci_dma_mapping_error(dev->pdev, nvbe->pages[i])) { -+ nvbe->nr_pages = --i; -+ be->func->clear(be); -+ return -EFAULT; - } -- -- nvbe->nr_pages++; - } - - return 0; -@@ -72,26 +57,20 @@ static void - nouveau_sgdma_clear(struct ttm_backend *be) - { - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; -- struct drm_device *dev; -- -- if (nvbe && nvbe->pages) { -- dev = nvbe->dev; -- NV_DEBUG(dev, "\n"); -+ struct drm_device *dev = nvbe->dev; - -- if (nvbe->bound) -- be->func->unbind(be); -+ if (nvbe->bound) -+ be->func->unbind(be); - -+ if (nvbe->unmap_pages) { - while (nvbe->nr_pages--) { -- if (!nvbe->ttm_alloced[nvbe->nr_pages]) -- pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages], -+ pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages], - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - } -- kfree(nvbe->pages); -- kfree(nvbe->ttm_alloced); -- nvbe->pages = NULL; -- nvbe->ttm_alloced = NULL; -- nvbe->nr_pages = 0; -+ nvbe->unmap_pages = false; - } -+ -+ nvbe->pages = NULL; - } - - static void -diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c -index 10656e4..82478e0 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_state.c -+++ b/drivers/gpu/drm/nouveau/nouveau_state.c -@@ -286,9 +286,9 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) - engine->gpio.get = nv10_gpio_get; - engine->gpio.set = nv10_gpio_set; - engine->gpio.irq_enable = NULL; -- engine->pm.clock_get = nv04_pm_clock_get; -- engine->pm.clock_pre = nv04_pm_clock_pre; -- engine->pm.clock_set = nv04_pm_clock_set; -+ engine->pm.clocks_get = nv40_pm_clocks_get; -+ engine->pm.clocks_pre = nv40_pm_clocks_pre; -+ engine->pm.clocks_set = nv40_pm_clocks_set; - engine->pm.voltage_get = nouveau_voltage_gpio_get; - engine->pm.voltage_set = nouveau_voltage_gpio_set; - engine->pm.temp_get = nv40_temp_get; -@@ -299,7 +299,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) - case 0x50: - case 0x80: /* gotta love NVIDIA's consistency.. */ - case 0x90: -- case 0xA0: -+ case 0xa0: - engine->instmem.init = nv50_instmem_init; - engine->instmem.takedown = nv50_instmem_takedown; - engine->instmem.suspend = nv50_instmem_suspend; -@@ -359,9 +359,9 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) - engine->pm.clock_set = nv50_pm_clock_set; - break; - default: -- engine->pm.clock_get = nva3_pm_clock_get; -- engine->pm.clock_pre = nva3_pm_clock_pre; -- engine->pm.clock_set = nva3_pm_clock_set; -+ engine->pm.clocks_get = nva3_pm_clocks_get; -+ engine->pm.clocks_pre = nva3_pm_clocks_pre; -+ engine->pm.clocks_set = nva3_pm_clocks_set; - break; - } - engine->pm.voltage_get = nouveau_voltage_gpio_get; -@@ -376,7 +376,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) - engine->vram.put = nv50_vram_del; - engine->vram.flags_valid = nv50_vram_flags_valid; - break; -- case 0xC0: -+ case 0xc0: - engine->instmem.init = nvc0_instmem_init; - engine->instmem.takedown = nvc0_instmem_takedown; - engine->instmem.suspend = nvc0_instmem_suspend; -@@ -422,12 +422,73 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) - engine->vram.put = nv50_vram_del; - engine->vram.flags_valid = nvc0_vram_flags_valid; - engine->pm.temp_get = nv84_temp_get; -+ engine->pm.clocks_get = nvc0_pm_clocks_get; -+ engine->pm.voltage_get = nouveau_voltage_gpio_get; -+ engine->pm.voltage_set = nouveau_voltage_gpio_set; -+ break; -+ case 0xd0: -+ engine->instmem.init = nvc0_instmem_init; -+ engine->instmem.takedown = nvc0_instmem_takedown; -+ engine->instmem.suspend = nvc0_instmem_suspend; -+ engine->instmem.resume = nvc0_instmem_resume; -+ engine->instmem.get = nv50_instmem_get; -+ engine->instmem.put = nv50_instmem_put; -+ engine->instmem.map = nv50_instmem_map; -+ engine->instmem.unmap = nv50_instmem_unmap; -+ engine->instmem.flush = nv84_instmem_flush; -+ engine->mc.init = nv50_mc_init; -+ engine->mc.takedown = nv50_mc_takedown; -+ engine->timer.init = nv04_timer_init; -+ engine->timer.read = nv04_timer_read; -+ engine->timer.takedown = nv04_timer_takedown; -+ engine->fb.init = nvc0_fb_init; -+ engine->fb.takedown = nvc0_fb_takedown; -+ engine->fifo.channels = 128; -+ engine->fifo.init = nvc0_fifo_init; -+ engine->fifo.takedown = nvc0_fifo_takedown; -+ engine->fifo.disable = nvc0_fifo_disable; -+ engine->fifo.enable = nvc0_fifo_enable; -+ engine->fifo.reassign = nvc0_fifo_reassign; -+ engine->fifo.channel_id = nvc0_fifo_channel_id; -+ engine->fifo.create_context = nvc0_fifo_create_context; -+ engine->fifo.destroy_context = nvc0_fifo_destroy_context; -+ engine->fifo.load_context = nvc0_fifo_load_context; -+ engine->fifo.unload_context = nvc0_fifo_unload_context; -+ engine->display.early_init = nouveau_stub_init; -+ engine->display.late_takedown = nouveau_stub_takedown; -+ engine->display.create = nvd0_display_create; -+ engine->display.init = nvd0_display_init; -+ engine->display.destroy = nvd0_display_destroy; -+ engine->gpio.init = nv50_gpio_init; -+ engine->gpio.takedown = nouveau_stub_takedown; -+ engine->gpio.get = nvd0_gpio_get; -+ engine->gpio.set = nvd0_gpio_set; -+ engine->gpio.irq_register = nv50_gpio_irq_register; -+ engine->gpio.irq_unregister = nv50_gpio_irq_unregister; -+ engine->gpio.irq_enable = nv50_gpio_irq_enable; -+ engine->vram.init = nvc0_vram_init; -+ engine->vram.takedown = nv50_vram_fini; -+ engine->vram.get = nvc0_vram_new; -+ engine->vram.put = nv50_vram_del; -+ engine->vram.flags_valid = nvc0_vram_flags_valid; -+ engine->pm.clocks_get = nvc0_pm_clocks_get; -+ engine->pm.voltage_get = nouveau_voltage_gpio_get; -+ engine->pm.voltage_set = nouveau_voltage_gpio_set; - break; - default: - NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); - return 1; - } - -+ /* headless mode */ -+ if (nouveau_modeset == 2) { -+ engine->display.early_init = nouveau_stub_init; -+ engine->display.late_takedown = nouveau_stub_takedown; -+ engine->display.create = nouveau_stub_init; -+ engine->display.init = nouveau_stub_init; -+ engine->display.destroy = nouveau_stub_takedown; -+ } -+ - return 0; - } - -@@ -449,21 +510,6 @@ nouveau_vga_set_decode(void *priv, bool state) - return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; - } - --static int --nouveau_card_init_channel(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- int ret; -- -- ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL, -- NvDmaFB, NvDmaTT); -- if (ret) -- return ret; -- -- mutex_unlock(&dev_priv->channel->mutex); -- return 0; --} -- - static void nouveau_switcheroo_set_state(struct pci_dev *pdev, - enum vga_switcheroo_state state) - { -@@ -630,8 +676,11 @@ nouveau_card_init(struct drm_device *dev) - break; - } - -- if (dev_priv->card_type == NV_40) -- nv40_mpeg_create(dev); -+ if (dev_priv->card_type == NV_40 || -+ dev_priv->chipset == 0x31 || -+ dev_priv->chipset == 0x34 || -+ dev_priv->chipset == 0x36) -+ nv31_mpeg_create(dev); - else - if (dev_priv->card_type == NV_50 && - (dev_priv->chipset < 0x98 || dev_priv->chipset == 0xa0)) -@@ -651,41 +700,69 @@ nouveau_card_init(struct drm_device *dev) - goto out_engine; - } - -- ret = engine->display.create(dev); -+ ret = nouveau_irq_init(dev); - if (ret) - goto out_fifo; - -- ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1); -- if (ret) -- goto out_vblank; -+ /* initialise general modesetting */ -+ drm_mode_config_init(dev); -+ drm_mode_create_scaling_mode_property(dev); -+ drm_mode_create_dithering_property(dev); -+ dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; -+ dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1); -+ dev->mode_config.min_width = 0; -+ dev->mode_config.min_height = 0; -+ if (dev_priv->card_type < NV_10) { -+ dev->mode_config.max_width = 2048; -+ dev->mode_config.max_height = 2048; -+ } else -+ if (dev_priv->card_type < NV_50) { -+ dev->mode_config.max_width = 4096; -+ dev->mode_config.max_height = 4096; -+ } else { -+ dev->mode_config.max_width = 8192; -+ dev->mode_config.max_height = 8192; -+ } - -- ret = nouveau_irq_init(dev); -+ ret = engine->display.create(dev); - if (ret) -- goto out_vblank; -+ goto out_irq; - -- /* what about PVIDEO/PCRTC/PRAMDAC etc? */ -+ nouveau_backlight_init(dev); - - if (dev_priv->eng[NVOBJ_ENGINE_GR]) { - ret = nouveau_fence_init(dev); - if (ret) -- goto out_irq; -+ goto out_disp; - -- ret = nouveau_card_init_channel(dev); -+ ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL, -+ NvDmaFB, NvDmaTT); - if (ret) - goto out_fence; -+ -+ mutex_unlock(&dev_priv->channel->mutex); -+ } -+ -+ if (dev->mode_config.num_crtc) { -+ ret = drm_vblank_init(dev, dev->mode_config.num_crtc); -+ if (ret) -+ goto out_chan; -+ -+ nouveau_fbcon_init(dev); -+ drm_kms_helper_poll_init(dev); - } - -- nouveau_fbcon_init(dev); -- drm_kms_helper_poll_init(dev); - return 0; - -+out_chan: -+ nouveau_channel_put_unlocked(&dev_priv->channel); - out_fence: - nouveau_fence_fini(dev); -+out_disp: -+ nouveau_backlight_exit(dev); -+ engine->display.destroy(dev); - out_irq: - nouveau_irq_fini(dev); --out_vblank: -- drm_vblank_cleanup(dev); -- engine->display.destroy(dev); - out_fifo: - if (!dev_priv->noaccel) - engine->fifo.takedown(dev); -@@ -732,15 +809,20 @@ static void nouveau_card_takedown(struct drm_device *dev) - struct nouveau_engine *engine = &dev_priv->engine; - int e; - -- drm_kms_helper_poll_fini(dev); -- nouveau_fbcon_fini(dev); -+ if (dev->mode_config.num_crtc) { -+ drm_kms_helper_poll_fini(dev); -+ nouveau_fbcon_fini(dev); -+ drm_vblank_cleanup(dev); -+ } - - if (dev_priv->channel) { - nouveau_channel_put_unlocked(&dev_priv->channel); - nouveau_fence_fini(dev); - } - -+ nouveau_backlight_exit(dev); - engine->display.destroy(dev); -+ drm_mode_config_cleanup(dev); - - if (!dev_priv->noaccel) { - engine->fifo.takedown(dev); -@@ -774,7 +856,6 @@ static void nouveau_card_takedown(struct drm_device *dev) - engine->vram.takedown(dev); - - nouveau_irq_fini(dev); -- drm_vblank_cleanup(dev); - - nouveau_pm_fini(dev); - nouveau_bios_takedown(dev); -@@ -907,7 +988,7 @@ static int nouveau_remove_conflicting_drivers(struct drm_device *dev) - int nouveau_load(struct drm_device *dev, unsigned long flags) - { - struct drm_nouveau_private *dev_priv; -- uint32_t reg0; -+ uint32_t reg0, strap; - resource_size_t mmio_start_offs; - int ret; - -@@ -951,13 +1032,11 @@ 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) -@@ -987,6 +1066,9 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) - case 0xc0: - dev_priv->card_type = NV_C0; - break; -+ case 0xd0: -+ dev_priv->card_type = NV_D0; -+ break; - default: - NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0); - ret = -EINVAL; -@@ -996,6 +1078,23 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) - NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", - dev_priv->card_type, reg0); - -+ /* determine frequency of timing crystal */ -+ strap = nv_rd32(dev, 0x101000); -+ if ( dev_priv->chipset < 0x17 || -+ (dev_priv->chipset >= 0x20 && dev_priv->chipset <= 0x25)) -+ strap &= 0x00000040; -+ else -+ strap &= 0x00400040; -+ -+ switch (strap) { -+ case 0x00000000: dev_priv->crystal = 13500; break; -+ case 0x00000040: dev_priv->crystal = 14318; break; -+ case 0x00400000: dev_priv->crystal = 27000; break; -+ case 0x00400040: dev_priv->crystal = 25000; break; -+ } -+ -+ NV_DEBUG(dev, "crystal freq: %dKHz\n", dev_priv->crystal); -+ - /* Determine whether we'll attempt acceleration or not, some - * cards are disabled by default here due to them being known - * non-functional, or never been tested due to lack of hw. -@@ -1030,7 +1129,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) - ioremap(pci_resource_start(dev->pdev, ramin_bar), - dev_priv->ramin_size); - if (!dev_priv->ramin) { -- NV_ERROR(dev, "Failed to PRAMIN BAR"); -+ NV_ERROR(dev, "Failed to map PRAMIN BAR\n"); - ret = -ENOMEM; - goto err_mmio; - } -@@ -1130,7 +1229,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, - getparam->value = 1; - break; - case NOUVEAU_GETPARAM_HAS_PAGEFLIP: -- getparam->value = 1; -+ getparam->value = dev_priv->card_type < NV_D0; - break; - case NOUVEAU_GETPARAM_GRAPH_UNITS: - /* NV40 and NV50 versions are quite different, but register -@@ -1198,6 +1297,23 @@ nouveau_wait_ne(struct drm_device *dev, uint64_t timeout, - return false; - } - -+/* Wait until cond(data) == true, up until timeout has hit */ -+bool -+nouveau_wait_cb(struct drm_device *dev, u64 timeout, -+ bool (*cond)(void *), void *data) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; -+ u64 start = ptimer->read(dev); -+ -+ do { -+ if (cond(data) == true) -+ return true; -+ } while (ptimer->read(dev) - start < timeout); -+ -+ return false; -+} -+ - /* Waits for PGRAPH to go completely idle */ - bool nouveau_wait_for_idle(struct drm_device *dev) - { -diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c -index 244fd38..ef0832b 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_vm.c -+++ b/drivers/gpu/drm/nouveau/nouveau_vm.c -@@ -172,9 +172,9 @@ nouveau_vm_unmap_pgt(struct nouveau_vm *vm, int big, u32 fpde, u32 lpde) - vm->map_pgt(vpgd->obj, pde, vpgt->obj); - } - -- mutex_unlock(&vm->mm->mutex); -+ mutex_unlock(&vm->mm.mutex); - nouveau_gpuobj_ref(NULL, &pgt); -- mutex_lock(&vm->mm->mutex); -+ mutex_lock(&vm->mm.mutex); - } - } - -@@ -191,18 +191,18 @@ nouveau_vm_map_pgt(struct nouveau_vm *vm, u32 pde, u32 type) - pgt_size = (1 << (vm->pgt_bits + 12)) >> type; - pgt_size *= 8; - -- mutex_unlock(&vm->mm->mutex); -+ mutex_unlock(&vm->mm.mutex); - ret = nouveau_gpuobj_new(vm->dev, NULL, pgt_size, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &pgt); -- mutex_lock(&vm->mm->mutex); -+ mutex_lock(&vm->mm.mutex); - if (unlikely(ret)) - return ret; - - /* someone beat us to filling the PDE while we didn't have the lock */ - if (unlikely(vpgt->refcount[big]++)) { -- mutex_unlock(&vm->mm->mutex); -+ mutex_unlock(&vm->mm.mutex); - nouveau_gpuobj_ref(NULL, &pgt); -- mutex_lock(&vm->mm->mutex); -+ mutex_lock(&vm->mm.mutex); - return 0; - } - -@@ -223,10 +223,10 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, - u32 fpde, lpde, pde; - int ret; - -- mutex_lock(&vm->mm->mutex); -- ret = nouveau_mm_get(vm->mm, page_shift, msize, 0, align, &vma->node); -+ mutex_lock(&vm->mm.mutex); -+ ret = nouveau_mm_get(&vm->mm, page_shift, msize, 0, align, &vma->node); - if (unlikely(ret != 0)) { -- mutex_unlock(&vm->mm->mutex); -+ mutex_unlock(&vm->mm.mutex); - return ret; - } - -@@ -245,13 +245,13 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, - if (ret) { - if (pde != fpde) - nouveau_vm_unmap_pgt(vm, big, fpde, pde - 1); -- nouveau_mm_put(vm->mm, vma->node); -- mutex_unlock(&vm->mm->mutex); -+ nouveau_mm_put(&vm->mm, vma->node); -+ mutex_unlock(&vm->mm.mutex); - vma->node = NULL; - return ret; - } - } -- mutex_unlock(&vm->mm->mutex); -+ mutex_unlock(&vm->mm.mutex); - - vma->vm = vm; - vma->offset = (u64)vma->node->offset << 12; -@@ -270,11 +270,11 @@ nouveau_vm_put(struct nouveau_vma *vma) - fpde = (vma->node->offset >> vm->pgt_bits); - lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits; - -- mutex_lock(&vm->mm->mutex); -+ mutex_lock(&vm->mm.mutex); - nouveau_vm_unmap_pgt(vm, vma->node->type != vm->spg_shift, fpde, lpde); -- nouveau_mm_put(vm->mm, vma->node); -+ nouveau_mm_put(&vm->mm, vma->node); - vma->node = NULL; -- mutex_unlock(&vm->mm->mutex); -+ mutex_unlock(&vm->mm.mutex); - } - - int -@@ -306,7 +306,7 @@ nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset, - block = length; - - } else -- if (dev_priv->card_type == NV_C0) { -+ if (dev_priv->card_type >= NV_C0) { - vm->map_pgt = nvc0_vm_map_pgt; - vm->map = nvc0_vm_map; - vm->map_sg = nvc0_vm_map_sg; -@@ -360,11 +360,11 @@ nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd) - - nouveau_gpuobj_ref(pgd, &vpgd->obj); - -- mutex_lock(&vm->mm->mutex); -+ mutex_lock(&vm->mm.mutex); - for (i = vm->fpde; i <= vm->lpde; i++) - vm->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj); - list_add(&vpgd->head, &vm->pgd_list); -- mutex_unlock(&vm->mm->mutex); -+ mutex_unlock(&vm->mm.mutex); - return 0; - } - -@@ -377,7 +377,7 @@ nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd) - if (!mpgd) - return; - -- mutex_lock(&vm->mm->mutex); -+ mutex_lock(&vm->mm.mutex); - list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { - if (vpgd->obj == mpgd) { - pgd = vpgd->obj; -@@ -386,7 +386,7 @@ nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd) - break; - } - } -- mutex_unlock(&vm->mm->mutex); -+ mutex_unlock(&vm->mm.mutex); - - nouveau_gpuobj_ref(NULL, &pgd); - } -diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h -index 579ca8c..6ce995f 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_vm.h -+++ b/drivers/gpu/drm/nouveau/nouveau_vm.h -@@ -51,7 +51,7 @@ struct nouveau_vma { - - struct nouveau_vm { - struct drm_device *dev; -- struct nouveau_mm *mm; -+ struct nouveau_mm mm; - int refcount; - - struct list_head pgd_list; -diff --git a/drivers/gpu/drm/nouveau/nouveau_volt.c b/drivers/gpu/drm/nouveau/nouveau_volt.c -index 75e87274..86d03e1 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_volt.c -+++ b/drivers/gpu/drm/nouveau/nouveau_volt.c -@@ -27,7 +27,7 @@ - #include "nouveau_drv.h" - #include "nouveau_pm.h" - --static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a }; -+static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 }; - static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]); - - int -@@ -170,6 +170,13 @@ nouveau_volt_init(struct drm_device *dev) - */ - vidshift = 2; - break; -+ case 0x40: -+ headerlen = volt[1]; -+ recordlen = volt[2]; -+ entries = volt[3]; /* not a clue what the entries are for.. */ -+ vidmask = volt[11]; /* guess.. */ -+ vidshift = 0; -+ break; - default: - NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]); - return; -@@ -197,16 +204,37 @@ nouveau_volt_init(struct drm_device *dev) - } - - /* parse vbios entries into common format */ -- voltage->level = kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL); -- if (!voltage->level) -- return; -+ voltage->version = volt[0]; -+ if (voltage->version < 0x40) { -+ voltage->nr_level = entries; -+ voltage->level = -+ kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL); -+ if (!voltage->level) -+ return; - -- entry = volt + headerlen; -- for (i = 0; i < entries; i++, entry += recordlen) { -- voltage->level[i].voltage = entry[0]; -- voltage->level[i].vid = entry[1] >> vidshift; -+ entry = volt + headerlen; -+ for (i = 0; i < entries; i++, entry += recordlen) { -+ voltage->level[i].voltage = entry[0] * 10000; -+ voltage->level[i].vid = entry[1] >> vidshift; -+ } -+ } else { -+ u32 volt_uv = ROM32(volt[4]); -+ s16 step_uv = ROM16(volt[8]); -+ u8 vid; -+ -+ voltage->nr_level = voltage->vid_mask + 1; -+ voltage->level = kcalloc(voltage->nr_level, -+ sizeof(*voltage->level), GFP_KERNEL); -+ if (!voltage->level) -+ return; -+ -+ for (vid = 0; vid <= voltage->vid_mask; vid++) { -+ voltage->level[vid].voltage = volt_uv; -+ voltage->level[vid].vid = vid; -+ volt_uv += step_uv; -+ } - } -- voltage->nr_level = entries; -+ - voltage->supported = true; - } - -diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c -index 1715e14..6bd8518 100644 ---- a/drivers/gpu/drm/nouveau/nv04_display.c -+++ b/drivers/gpu/drm/nouveau/nv04_display.c -@@ -126,27 +126,6 @@ nv04_display_create(struct drm_device *dev) - - nouveau_hw_save_vga_fonts(dev, 1); - -- drm_mode_config_init(dev); -- drm_mode_create_scaling_mode_property(dev); -- drm_mode_create_dithering_property(dev); -- -- dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; -- -- dev->mode_config.min_width = 0; -- dev->mode_config.min_height = 0; -- switch (dev_priv->card_type) { -- case NV_04: -- dev->mode_config.max_width = 2048; -- dev->mode_config.max_height = 2048; -- break; -- default: -- dev->mode_config.max_width = 4096; -- dev->mode_config.max_height = 4096; -- break; -- } -- -- dev->mode_config.fb_base = dev_priv->fb_phys; -- - nv04_crtc_create(dev, 0); - if (nv_two_heads(dev)) - nv04_crtc_create(dev, 1); -@@ -235,8 +214,6 @@ nv04_display_destroy(struct drm_device *dev) - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) - crtc->funcs->restore(crtc); - -- drm_mode_config_cleanup(dev); -- - nouveau_hw_save_vga_fonts(dev, 0); - } - -diff --git a/drivers/gpu/drm/nouveau/nv04_pm.c b/drivers/gpu/drm/nouveau/nv04_pm.c -index eb1c70d..9ae92a8 100644 ---- a/drivers/gpu/drm/nouveau/nv04_pm.c -+++ b/drivers/gpu/drm/nouveau/nv04_pm.c -@@ -68,6 +68,7 @@ void - nv04_pm_clock_set(struct drm_device *dev, void *pre_state) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; - struct nv04_pm_state *state = pre_state; - u32 reg = state->pll.reg; - -@@ -85,6 +86,9 @@ nv04_pm_clock_set(struct drm_device *dev, void *pre_state) - nv_mask(dev, 0x1002c0, 0, 1 << 8); - } - -+ if (reg == NV_PRAMDAC_NVPLL_COEFF) -+ ptimer->init(dev); -+ - kfree(state); - } - -diff --git a/drivers/gpu/drm/nouveau/nv04_timer.c b/drivers/gpu/drm/nouveau/nv04_timer.c -index 1d09ddd..263301b 100644 ---- a/drivers/gpu/drm/nouveau/nv04_timer.c -+++ b/drivers/gpu/drm/nouveau/nv04_timer.c -@@ -6,43 +6,75 @@ - int - nv04_timer_init(struct drm_device *dev) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ u32 m, n, d; -+ - nv_wr32(dev, NV04_PTIMER_INTR_EN_0, 0x00000000); - nv_wr32(dev, NV04_PTIMER_INTR_0, 0xFFFFFFFF); - -- /* Just use the pre-existing values when possible for now; these regs -- * are not written in nv (driver writer missed a /4 on the address), and -- * writing 8 and 3 to the correct regs breaks the timings on the LVDS -- * hardware sequencing microcode. -- * A correct solution (involving calculations with the GPU PLL) can -- * be done when kernel modesetting lands -- */ -- if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) || -- !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) { -- nv_wr32(dev, NV04_PTIMER_NUMERATOR, 0x00000008); -- nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 0x00000003); -+ /* aim for 31.25MHz, which gives us nanosecond timestamps */ -+ d = 1000000 / 32; -+ -+ /* determine base clock for timer source */ -+ if (dev_priv->chipset < 0x40) { -+ n = dev_priv->engine.pm.clock_get(dev, PLL_CORE); -+ } else -+ if (dev_priv->chipset == 0x40) { -+ /*XXX: figure this out */ -+ n = 0; -+ } else { -+ n = dev_priv->crystal; -+ m = 1; -+ while (n < (d * 2)) { -+ n += (n / m); -+ m++; -+ } -+ -+ nv_wr32(dev, 0x009220, m - 1); -+ } -+ -+ if (!n) { -+ NV_WARN(dev, "PTIMER: unknown input clock freq\n"); -+ if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) || -+ !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) { -+ nv_wr32(dev, NV04_PTIMER_NUMERATOR, 1); -+ nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 1); -+ } -+ return 0; -+ } -+ -+ /* reduce ratio to acceptable values */ -+ while (((n % 5) == 0) && ((d % 5) == 0)) { -+ n /= 5; -+ d /= 5; - } - -+ while (((n % 2) == 0) && ((d % 2) == 0)) { -+ n /= 2; -+ d /= 2; -+ } -+ -+ while (n > 0xffff || d > 0xffff) { -+ n >>= 1; -+ d >>= 1; -+ } -+ -+ nv_wr32(dev, NV04_PTIMER_NUMERATOR, n); -+ nv_wr32(dev, NV04_PTIMER_DENOMINATOR, d); - return 0; - } - --uint64_t -+u64 - nv04_timer_read(struct drm_device *dev) - { -- uint32_t low; -- /* From kmmio dumps on nv28 this looks like how the blob does this. -- * It reads the high dword twice, before and after. -- * The only explanation seems to be that the 64-bit timer counter -- * advances between high and low dword reads and may corrupt the -- * result. Not confirmed. -- */ -- uint32_t high2 = nv_rd32(dev, NV04_PTIMER_TIME_1); -- uint32_t high1; -+ u32 hi, lo; -+ - do { -- high1 = high2; -- low = nv_rd32(dev, NV04_PTIMER_TIME_0); -- high2 = nv_rd32(dev, NV04_PTIMER_TIME_1); -- } while (high1 != high2); -- return (((uint64_t)high2) << 32) | (uint64_t)low; -+ hi = nv_rd32(dev, NV04_PTIMER_TIME_1); -+ lo = nv_rd32(dev, NV04_PTIMER_TIME_0); -+ } while (hi != nv_rd32(dev, NV04_PTIMER_TIME_1)); -+ -+ return ((u64)hi << 32 | lo); - } - - void -diff --git a/drivers/gpu/drm/nouveau/nv31_mpeg.c b/drivers/gpu/drm/nouveau/nv31_mpeg.c -new file mode 100644 -index 0000000..6f06a07 ---- /dev/null -+++ b/drivers/gpu/drm/nouveau/nv31_mpeg.c -@@ -0,0 +1,344 @@ -+/* -+ * 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"), -+ * 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 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) OR AUTHOR(S) 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: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+#include "nouveau_drv.h" -+#include "nouveau_ramht.h" -+ -+struct nv31_mpeg_engine { -+ struct nouveau_exec_engine base; -+ atomic_t refcount; -+}; -+ -+ -+static int -+nv31_mpeg_context_new(struct nouveau_channel *chan, int engine) -+{ -+ struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); -+ -+ if (!atomic_add_unless(&pmpeg->refcount, 1, 1)) -+ return -EBUSY; -+ -+ chan->engctx[engine] = (void *)0xdeadcafe; -+ return 0; -+} -+ -+static void -+nv31_mpeg_context_del(struct nouveau_channel *chan, int engine) -+{ -+ struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); -+ atomic_dec(&pmpeg->refcount); -+ chan->engctx[engine] = NULL; -+} -+ -+static int -+nv40_mpeg_context_new(struct nouveau_channel *chan, int engine) -+{ -+ struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj *ctx = NULL; -+ unsigned long flags; -+ int ret; -+ -+ NV_DEBUG(dev, "ch%d\n", chan->id); -+ -+ ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC | -+ NVOBJ_FLAG_ZERO_FREE, &ctx); -+ if (ret) -+ return ret; -+ -+ nv_wo32(ctx, 0x78, 0x02001ec1); -+ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ nv_mask(dev, 0x002500, 0x00000001, 0x00000000); -+ if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id) -+ nv_wr32(dev, 0x00330c, ctx->pinst >> 4); -+ nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4); -+ nv_mask(dev, 0x002500, 0x00000001, 0x00000001); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ -+ chan->engctx[engine] = ctx; -+ return 0; -+} -+ -+static void -+nv40_mpeg_context_del(struct nouveau_channel *chan, int engine) -+{ -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; -+ struct nouveau_gpuobj *ctx = chan->engctx[engine]; -+ struct drm_device *dev = chan->dev; -+ unsigned long flags; -+ u32 inst = 0x80000000 | (ctx->pinst >> 4); -+ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); -+ if (nv_rd32(dev, 0x00b318) == inst) -+ nv_mask(dev, 0x00b318, 0x80000000, 0x00000000); -+ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ -+ nouveau_gpuobj_ref(NULL, &ctx); -+ chan->engctx[engine] = NULL; -+} -+ -+static int -+nv31_mpeg_object_new(struct nouveau_channel *chan, int engine, -+ u32 handle, u16 class) -+{ -+ struct drm_device *dev = chan->dev; -+ struct nouveau_gpuobj *obj = NULL; -+ int ret; -+ -+ ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC | -+ NVOBJ_FLAG_ZERO_FREE, &obj); -+ if (ret) -+ return ret; -+ obj->engine = 2; -+ obj->class = class; -+ -+ nv_wo32(obj, 0x00, class); -+ -+ ret = nouveau_ramht_insert(chan, handle, obj); -+ nouveau_gpuobj_ref(NULL, &obj); -+ return ret; -+} -+ -+static int -+nv31_mpeg_init(struct drm_device *dev, int engine) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); -+ int i; -+ -+ /* VPE init */ -+ nv_mask(dev, 0x000200, 0x00000002, 0x00000000); -+ nv_mask(dev, 0x000200, 0x00000002, 0x00000002); -+ nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ -+ nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ -+ -+ for (i = 0; i < dev_priv->engine.fb.num_tiles; i++) -+ pmpeg->base.set_tile_region(dev, i); -+ -+ /* PMPEG init */ -+ nv_wr32(dev, 0x00b32c, 0x00000000); -+ nv_wr32(dev, 0x00b314, 0x00000100); -+ nv_wr32(dev, 0x00b220, nv44_graph_class(dev) ? 0x00000044 : 0x00000031); -+ nv_wr32(dev, 0x00b300, 0x02001ec1); -+ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); -+ -+ nv_wr32(dev, 0x00b100, 0xffffffff); -+ nv_wr32(dev, 0x00b140, 0xffffffff); -+ -+ if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) { -+ NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200)); -+ return -EBUSY; -+ } -+ -+ return 0; -+} -+ -+static int -+nv31_mpeg_fini(struct drm_device *dev, int engine, bool suspend) -+{ -+ /*XXX: context save? */ -+ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); -+ nv_wr32(dev, 0x00b140, 0x00000000); -+ return 0; -+} -+ -+static int -+nv31_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) -+{ -+ struct drm_device *dev = chan->dev; -+ u32 inst = data << 4; -+ u32 dma0 = nv_ri32(dev, inst + 0); -+ u32 dma1 = nv_ri32(dev, inst + 4); -+ u32 dma2 = nv_ri32(dev, inst + 8); -+ u32 base = (dma2 & 0xfffff000) | (dma0 >> 20); -+ u32 size = dma1 + 1; -+ -+ /* only allow linear DMA objects */ -+ if (!(dma0 & 0x00002000)) -+ return -EINVAL; -+ -+ if (mthd == 0x0190) { -+ /* DMA_CMD */ -+ nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000)); -+ nv_wr32(dev, 0x00b334, base); -+ nv_wr32(dev, 0x00b324, size); -+ } else -+ if (mthd == 0x01a0) { -+ /* DMA_DATA */ -+ nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); -+ nv_wr32(dev, 0x00b360, base); -+ nv_wr32(dev, 0x00b364, size); -+ } else { -+ /* DMA_IMAGE, VRAM only */ -+ if (dma0 & 0x000c0000) -+ return -EINVAL; -+ -+ nv_wr32(dev, 0x00b370, base); -+ nv_wr32(dev, 0x00b374, size); -+ } -+ -+ return 0; -+} -+ -+static int -+nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj *ctx; -+ unsigned long flags; -+ int i; -+ -+ /* hardcode drm channel id on nv3x, so swmthd lookup works */ -+ if (dev_priv->card_type < NV_40) -+ return 0; -+ -+ spin_lock_irqsave(&dev_priv->channels.lock, flags); -+ for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -+ if (!dev_priv->channels.ptr[i]) -+ continue; -+ -+ ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG]; -+ if (ctx && ctx->pinst == inst) -+ break; -+ } -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); -+ return i; -+} -+ -+static void -+nv31_vpe_set_tile_region(struct drm_device *dev, int i) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; -+ -+ nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch); -+ nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit); -+ nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr); -+} -+ -+static void -+nv31_mpeg_isr(struct drm_device *dev) -+{ -+ u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4; -+ u32 chid = nv31_mpeg_isr_chid(dev, inst); -+ u32 stat = nv_rd32(dev, 0x00b100); -+ u32 type = nv_rd32(dev, 0x00b230); -+ u32 mthd = nv_rd32(dev, 0x00b234); -+ u32 data = nv_rd32(dev, 0x00b238); -+ u32 show = stat; -+ -+ if (stat & 0x01000000) { -+ /* happens on initial binding of the object */ -+ if (type == 0x00000020 && mthd == 0x0000) { -+ nv_mask(dev, 0x00b308, 0x00000000, 0x00000000); -+ show &= ~0x01000000; -+ } -+ -+ if (type == 0x00000010) { -+ if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data)) -+ show &= ~0x01000000; -+ } -+ } -+ -+ nv_wr32(dev, 0x00b100, stat); -+ nv_wr32(dev, 0x00b230, 0x00000001); -+ -+ if (show && nouveau_ratelimit()) { -+ NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", -+ chid, inst, stat, type, mthd, data); -+ } -+} -+ -+static void -+nv31_vpe_isr(struct drm_device *dev) -+{ -+ if (nv_rd32(dev, 0x00b100)) -+ nv31_mpeg_isr(dev); -+ -+ if (nv_rd32(dev, 0x00b800)) { -+ u32 stat = nv_rd32(dev, 0x00b800); -+ NV_INFO(dev, "PMSRCH: 0x%08x\n", stat); -+ nv_wr32(dev, 0xb800, stat); -+ } -+} -+ -+static void -+nv31_mpeg_destroy(struct drm_device *dev, int engine) -+{ -+ struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); -+ -+ nouveau_irq_unregister(dev, 0); -+ -+ NVOBJ_ENGINE_DEL(dev, MPEG); -+ kfree(pmpeg); -+} -+ -+int -+nv31_mpeg_create(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nv31_mpeg_engine *pmpeg; -+ -+ pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); -+ if (!pmpeg) -+ return -ENOMEM; -+ atomic_set(&pmpeg->refcount, 0); -+ -+ pmpeg->base.destroy = nv31_mpeg_destroy; -+ pmpeg->base.init = nv31_mpeg_init; -+ pmpeg->base.fini = nv31_mpeg_fini; -+ if (dev_priv->card_type < NV_40) { -+ pmpeg->base.context_new = nv31_mpeg_context_new; -+ pmpeg->base.context_del = nv31_mpeg_context_del; -+ } else { -+ pmpeg->base.context_new = nv40_mpeg_context_new; -+ pmpeg->base.context_del = nv40_mpeg_context_del; -+ } -+ pmpeg->base.object_new = nv31_mpeg_object_new; -+ -+ /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between -+ * all VPE engines, for this driver's purposes the PMPEG engine -+ * will be treated as the "master" and handle the global VPE -+ * bits too -+ */ -+ pmpeg->base.set_tile_region = nv31_vpe_set_tile_region; -+ nouveau_irq_register(dev, 0, nv31_vpe_isr); -+ -+ NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); -+ NVOBJ_CLASS(dev, 0x3174, MPEG); -+ NVOBJ_MTHD (dev, 0x3174, 0x0190, nv31_mpeg_mthd_dma); -+ NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv31_mpeg_mthd_dma); -+ NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv31_mpeg_mthd_dma); -+ -+#if 0 -+ NVOBJ_ENGINE_ADD(dev, ME, &pme->base); -+ NVOBJ_CLASS(dev, 0x4075, ME); -+#endif -+ return 0; -+ -+} -diff --git a/drivers/gpu/drm/nouveau/nv40_mpeg.c b/drivers/gpu/drm/nouveau/nv40_mpeg.c -deleted file mode 100644 -index ad03a0e..0000000 ---- a/drivers/gpu/drm/nouveau/nv40_mpeg.c -+++ /dev/null -@@ -1,311 +0,0 @@ --/* -- * 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"), -- * 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 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) OR AUTHOR(S) 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: Ben Skeggs -- */ -- --#include "drmP.h" --#include "nouveau_drv.h" --#include "nouveau_ramht.h" -- --struct nv40_mpeg_engine { -- struct nouveau_exec_engine base; --}; -- --static int --nv40_mpeg_context_new(struct nouveau_channel *chan, int engine) --{ -- struct drm_device *dev = chan->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *ctx = NULL; -- unsigned long flags; -- int ret; -- -- NV_DEBUG(dev, "ch%d\n", chan->id); -- -- ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC | -- NVOBJ_FLAG_ZERO_FREE, &ctx); -- if (ret) -- return ret; -- -- nv_wo32(ctx, 0x78, 0x02001ec1); -- -- spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -- nv_mask(dev, 0x002500, 0x00000001, 0x00000000); -- if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id) -- nv_wr32(dev, 0x00330c, ctx->pinst >> 4); -- nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4); -- nv_mask(dev, 0x002500, 0x00000001, 0x00000001); -- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -- -- chan->engctx[engine] = ctx; -- return 0; --} -- --static void --nv40_mpeg_context_del(struct nouveau_channel *chan, int engine) --{ -- struct drm_nouveau_private *dev_priv = chan->dev->dev_private; -- struct nouveau_gpuobj *ctx = chan->engctx[engine]; -- struct drm_device *dev = chan->dev; -- unsigned long flags; -- u32 inst = 0x80000000 | (ctx->pinst >> 4); -- -- spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); -- if (nv_rd32(dev, 0x00b318) == inst) -- nv_mask(dev, 0x00b318, 0x80000000, 0x00000000); -- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); -- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -- -- nouveau_gpuobj_ref(NULL, &ctx); -- chan->engctx[engine] = NULL; --} -- --static int --nv40_mpeg_object_new(struct nouveau_channel *chan, int engine, -- u32 handle, u16 class) --{ -- struct drm_device *dev = chan->dev; -- struct nouveau_gpuobj *obj = NULL; -- int ret; -- -- ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC | -- NVOBJ_FLAG_ZERO_FREE, &obj); -- if (ret) -- return ret; -- obj->engine = 2; -- obj->class = class; -- -- nv_wo32(obj, 0x00, class); -- -- ret = nouveau_ramht_insert(chan, handle, obj); -- nouveau_gpuobj_ref(NULL, &obj); -- return ret; --} -- --static int --nv40_mpeg_init(struct drm_device *dev, int engine) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine); -- int i; -- -- /* VPE init */ -- nv_mask(dev, 0x000200, 0x00000002, 0x00000000); -- nv_mask(dev, 0x000200, 0x00000002, 0x00000002); -- nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ -- nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ -- -- for (i = 0; i < dev_priv->engine.fb.num_tiles; i++) -- pmpeg->base.set_tile_region(dev, i); -- -- /* PMPEG init */ -- nv_wr32(dev, 0x00b32c, 0x00000000); -- nv_wr32(dev, 0x00b314, 0x00000100); -- nv_wr32(dev, 0x00b220, 0x00000044); -- nv_wr32(dev, 0x00b300, 0x02001ec1); -- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); -- -- nv_wr32(dev, 0x00b100, 0xffffffff); -- nv_wr32(dev, 0x00b140, 0xffffffff); -- -- if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) { -- NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200)); -- return -EBUSY; -- } -- -- return 0; --} -- --static int --nv40_mpeg_fini(struct drm_device *dev, int engine, bool suspend) --{ -- /*XXX: context save? */ -- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); -- nv_wr32(dev, 0x00b140, 0x00000000); -- return 0; --} -- --static int --nv40_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) --{ -- struct drm_device *dev = chan->dev; -- u32 inst = data << 4; -- u32 dma0 = nv_ri32(dev, inst + 0); -- u32 dma1 = nv_ri32(dev, inst + 4); -- u32 dma2 = nv_ri32(dev, inst + 8); -- u32 base = (dma2 & 0xfffff000) | (dma0 >> 20); -- u32 size = dma1 + 1; -- -- /* only allow linear DMA objects */ -- if (!(dma0 & 0x00002000)) -- return -EINVAL; -- -- if (mthd == 0x0190) { -- /* DMA_CMD */ -- nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000)); -- nv_wr32(dev, 0x00b334, base); -- nv_wr32(dev, 0x00b324, size); -- } else -- if (mthd == 0x01a0) { -- /* DMA_DATA */ -- nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); -- nv_wr32(dev, 0x00b360, base); -- nv_wr32(dev, 0x00b364, size); -- } else { -- /* DMA_IMAGE, VRAM only */ -- if (dma0 & 0x000c0000) -- return -EINVAL; -- -- nv_wr32(dev, 0x00b370, base); -- nv_wr32(dev, 0x00b374, size); -- } -- -- return 0; --} -- --static int --nv40_mpeg_isr_chid(struct drm_device *dev, u32 inst) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *ctx; -- unsigned long flags; -- int i; -- -- spin_lock_irqsave(&dev_priv->channels.lock, flags); -- for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- if (!dev_priv->channels.ptr[i]) -- continue; -- -- ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG]; -- if (ctx && ctx->pinst == inst) -- break; -- } -- spin_unlock_irqrestore(&dev_priv->channels.lock, flags); -- return i; --} -- --static void --nv40_vpe_set_tile_region(struct drm_device *dev, int i) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; -- -- nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch); -- nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit); -- nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr); --} -- --static void --nv40_mpeg_isr(struct drm_device *dev) --{ -- u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4; -- u32 chid = nv40_mpeg_isr_chid(dev, inst); -- u32 stat = nv_rd32(dev, 0x00b100); -- u32 type = nv_rd32(dev, 0x00b230); -- u32 mthd = nv_rd32(dev, 0x00b234); -- u32 data = nv_rd32(dev, 0x00b238); -- u32 show = stat; -- -- if (stat & 0x01000000) { -- /* happens on initial binding of the object */ -- if (type == 0x00000020 && mthd == 0x0000) { -- nv_mask(dev, 0x00b308, 0x00000000, 0x00000000); -- show &= ~0x01000000; -- } -- -- if (type == 0x00000010) { -- if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data)) -- show &= ~0x01000000; -- } -- } -- -- nv_wr32(dev, 0x00b100, stat); -- nv_wr32(dev, 0x00b230, 0x00000001); -- -- if (show && nouveau_ratelimit()) { -- NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", -- chid, inst, stat, type, mthd, data); -- } --} -- --static void --nv40_vpe_isr(struct drm_device *dev) --{ -- if (nv_rd32(dev, 0x00b100)) -- nv40_mpeg_isr(dev); -- -- if (nv_rd32(dev, 0x00b800)) { -- u32 stat = nv_rd32(dev, 0x00b800); -- NV_INFO(dev, "PMSRCH: 0x%08x\n", stat); -- nv_wr32(dev, 0xb800, stat); -- } --} -- --static void --nv40_mpeg_destroy(struct drm_device *dev, int engine) --{ -- struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine); -- -- nouveau_irq_unregister(dev, 0); -- -- NVOBJ_ENGINE_DEL(dev, MPEG); -- kfree(pmpeg); --} -- --int --nv40_mpeg_create(struct drm_device *dev) --{ -- struct nv40_mpeg_engine *pmpeg; -- -- pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); -- if (!pmpeg) -- return -ENOMEM; -- -- pmpeg->base.destroy = nv40_mpeg_destroy; -- pmpeg->base.init = nv40_mpeg_init; -- pmpeg->base.fini = nv40_mpeg_fini; -- pmpeg->base.context_new = nv40_mpeg_context_new; -- pmpeg->base.context_del = nv40_mpeg_context_del; -- pmpeg->base.object_new = nv40_mpeg_object_new; -- -- /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between -- * all VPE engines, for this driver's purposes the PMPEG engine -- * will be treated as the "master" and handle the global VPE -- * bits too -- */ -- pmpeg->base.set_tile_region = nv40_vpe_set_tile_region; -- nouveau_irq_register(dev, 0, nv40_vpe_isr); -- -- NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); -- NVOBJ_CLASS(dev, 0x3174, MPEG); -- NVOBJ_MTHD (dev, 0x3174, 0x0190, nv40_mpeg_mthd_dma); -- NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv40_mpeg_mthd_dma); -- NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv40_mpeg_mthd_dma); -- --#if 0 -- NVOBJ_ENGINE_ADD(dev, ME, &pme->base); -- NVOBJ_CLASS(dev, 0x4075, ME); --#endif -- return 0; -- --} -diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c -new file mode 100644 -index 0000000..e676b0d ---- /dev/null -+++ b/drivers/gpu/drm/nouveau/nv40_pm.c -@@ -0,0 +1,348 @@ -+/* -+ * 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"), -+ * 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 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) OR AUTHOR(S) 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: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+#include "nouveau_drv.h" -+#include "nouveau_bios.h" -+#include "nouveau_pm.h" -+#include "nouveau_hw.h" -+ -+#define min2(a,b) ((a) < (b) ? (a) : (b)) -+ -+static u32 -+read_pll_1(struct drm_device *dev, u32 reg) -+{ -+ u32 ctrl = nv_rd32(dev, reg + 0x00); -+ int P = (ctrl & 0x00070000) >> 16; -+ int N = (ctrl & 0x0000ff00) >> 8; -+ int M = (ctrl & 0x000000ff) >> 0; -+ u32 ref = 27000, clk = 0; -+ -+ if (ctrl & 0x80000000) -+ clk = ref * N / M; -+ -+ return clk >> P; -+} -+ -+static u32 -+read_pll_2(struct drm_device *dev, u32 reg) -+{ -+ u32 ctrl = nv_rd32(dev, reg + 0x00); -+ u32 coef = nv_rd32(dev, reg + 0x04); -+ int N2 = (coef & 0xff000000) >> 24; -+ int M2 = (coef & 0x00ff0000) >> 16; -+ int N1 = (coef & 0x0000ff00) >> 8; -+ int M1 = (coef & 0x000000ff) >> 0; -+ int P = (ctrl & 0x00070000) >> 16; -+ u32 ref = 27000, clk = 0; -+ -+ if ((ctrl & 0x80000000) && M1) { -+ clk = ref * N1 / M1; -+ if ((ctrl & 0x40000100) == 0x40000000) { -+ if (M2) -+ clk = clk * N2 / M2; -+ else -+ clk = 0; -+ } -+ } -+ -+ return clk >> P; -+} -+ -+static u32 -+read_clk(struct drm_device *dev, u32 src) -+{ -+ switch (src) { -+ case 3: -+ return read_pll_2(dev, 0x004000); -+ case 2: -+ return read_pll_1(dev, 0x004008); -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+int -+nv40_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) -+{ -+ u32 ctrl = nv_rd32(dev, 0x00c040); -+ -+ perflvl->core = read_clk(dev, (ctrl & 0x00000003) >> 0); -+ perflvl->shader = read_clk(dev, (ctrl & 0x00000030) >> 4); -+ perflvl->memory = read_pll_2(dev, 0x4020); -+ return 0; -+} -+ -+struct nv40_pm_state { -+ u32 ctrl; -+ u32 npll_ctrl; -+ u32 npll_coef; -+ u32 spll; -+ u32 mpll_ctrl; -+ u32 mpll_coef; -+}; -+ -+static int -+nv40_calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll, -+ u32 clk, int *N1, int *M1, int *N2, int *M2, int *log2P) -+{ -+ struct nouveau_pll_vals coef; -+ int ret; -+ -+ ret = get_pll_limits(dev, reg, pll); -+ if (ret) -+ return ret; -+ -+ if (clk < pll->vco1.maxfreq) -+ pll->vco2.maxfreq = 0; -+ -+ ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef); -+ if (ret == 0) -+ return -ERANGE; -+ -+ *N1 = coef.N1; -+ *M1 = coef.M1; -+ if (N2 && M2) { -+ if (pll->vco2.maxfreq) { -+ *N2 = coef.N2; -+ *M2 = coef.M2; -+ } else { -+ *N2 = 1; -+ *M2 = 1; -+ } -+ } -+ *log2P = coef.log2P; -+ return 0; -+} -+ -+void * -+nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) -+{ -+ struct nv40_pm_state *info; -+ struct pll_lims pll; -+ int N1, N2, M1, M2, log2P; -+ int ret; -+ -+ info = kmalloc(sizeof(*info), GFP_KERNEL); -+ if (!info) -+ return ERR_PTR(-ENOMEM); -+ -+ /* core/geometric clock */ -+ ret = nv40_calc_pll(dev, 0x004000, &pll, perflvl->core, -+ &N1, &M1, &N2, &M2, &log2P); -+ if (ret < 0) -+ goto out; -+ -+ if (N2 == M2) { -+ info->npll_ctrl = 0x80000100 | (log2P << 16); -+ info->npll_coef = (N1 << 8) | M1; -+ } else { -+ info->npll_ctrl = 0xc0000000 | (log2P << 16); -+ info->npll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1; -+ } -+ -+ /* use the second PLL for shader/rop clock, if it differs from core */ -+ if (perflvl->shader && perflvl->shader != perflvl->core) { -+ ret = nv40_calc_pll(dev, 0x004008, &pll, perflvl->shader, -+ &N1, &M1, NULL, NULL, &log2P); -+ if (ret < 0) -+ goto out; -+ -+ info->spll = 0xc0000000 | (log2P << 16) | (N1 << 8) | M1; -+ info->ctrl = 0x00000223; -+ } else { -+ info->spll = 0x00000000; -+ info->ctrl = 0x00000333; -+ } -+ -+ /* memory clock */ -+ if (!perflvl->memory) { -+ info->mpll_ctrl = 0x00000000; -+ goto out; -+ } -+ -+ ret = nv40_calc_pll(dev, 0x004020, &pll, perflvl->memory, -+ &N1, &M1, &N2, &M2, &log2P); -+ if (ret < 0) -+ goto out; -+ -+ info->mpll_ctrl = 0x80000000 | (log2P << 16); -+ info->mpll_ctrl |= min2(pll.log2p_bias + log2P, pll.max_log2p) << 20; -+ if (N2 == M2) { -+ info->mpll_ctrl |= 0x00000100; -+ info->mpll_coef = (N1 << 8) | M1; -+ } else { -+ info->mpll_ctrl |= 0x40000000; -+ info->mpll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1; -+ } -+ -+out: -+ if (ret < 0) { -+ kfree(info); -+ info = ERR_PTR(ret); -+ } -+ return info; -+} -+ -+static bool -+nv40_pm_gr_idle(void *data) -+{ -+ struct drm_device *dev = data; -+ -+ if ((nv_rd32(dev, 0x400760) & 0x000000f0) >> 4 != -+ (nv_rd32(dev, 0x400760) & 0x0000000f)) -+ return false; -+ -+ if (nv_rd32(dev, 0x400700)) -+ return false; -+ -+ return true; -+} -+ -+void -+nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nv40_pm_state *info = pre_state; -+ unsigned long flags; -+ struct bit_entry M; -+ u32 crtc_mask = 0; -+ u8 sr1[2]; -+ int i; -+ -+ /* determine which CRTCs are active, fetch VGA_SR1 for each */ -+ for (i = 0; i < 2; i++) { -+ u32 vbl = nv_rd32(dev, 0x600808 + (i * 0x2000)); -+ u32 cnt = 0; -+ do { -+ if (vbl != nv_rd32(dev, 0x600808 + (i * 0x2000))) { -+ nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01); -+ sr1[i] = nv_rd08(dev, 0x0c03c5 + (i * 0x2000)); -+ if (!(sr1[i] & 0x20)) -+ crtc_mask |= (1 << i); -+ break; -+ } -+ udelay(1); -+ } while (cnt++ < 32); -+ } -+ -+ /* halt and idle engines */ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ nv_mask(dev, 0x002500, 0x00000001, 0x00000000); -+ if (!nv_wait(dev, 0x002500, 0x00000010, 0x00000000)) -+ goto resume; -+ nv_mask(dev, 0x003220, 0x00000001, 0x00000000); -+ if (!nv_wait(dev, 0x003220, 0x00000010, 0x00000000)) -+ goto resume; -+ nv_mask(dev, 0x003200, 0x00000001, 0x00000000); -+ nv04_fifo_cache_pull(dev, false); -+ -+ if (!nv_wait_cb(dev, nv40_pm_gr_idle, dev)) -+ goto resume; -+ -+ /* set engine clocks */ -+ nv_mask(dev, 0x00c040, 0x00000333, 0x00000000); -+ nv_wr32(dev, 0x004004, info->npll_coef); -+ nv_mask(dev, 0x004000, 0xc0070100, info->npll_ctrl); -+ nv_mask(dev, 0x004008, 0xc007ffff, info->spll); -+ mdelay(5); -+ nv_mask(dev, 0x00c040, 0x00000333, info->ctrl); -+ -+ if (!info->mpll_ctrl) -+ goto resume; -+ -+ /* wait for vblank start on active crtcs, disable memory access */ -+ for (i = 0; i < 2; i++) { -+ if (!(crtc_mask & (1 << i))) -+ continue; -+ nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00000000); -+ nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); -+ nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01); -+ nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i] | 0x20); -+ } -+ -+ /* prepare ram for reclocking */ -+ nv_wr32(dev, 0x1002d4, 0x00000001); /* precharge */ -+ nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */ -+ nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */ -+ nv_mask(dev, 0x100210, 0x80000000, 0x00000000); /* no auto refresh */ -+ nv_wr32(dev, 0x1002dc, 0x00000001); /* enable self-refresh */ -+ -+ /* change the PLL of each memory partition */ -+ nv_mask(dev, 0x00c040, 0x0000c000, 0x00000000); -+ switch (dev_priv->chipset) { -+ case 0x40: -+ case 0x45: -+ case 0x41: -+ case 0x42: -+ case 0x47: -+ nv_mask(dev, 0x004044, 0xc0771100, info->mpll_ctrl); -+ nv_mask(dev, 0x00402c, 0xc0771100, info->mpll_ctrl); -+ nv_wr32(dev, 0x004048, info->mpll_coef); -+ nv_wr32(dev, 0x004030, info->mpll_coef); -+ case 0x43: -+ case 0x49: -+ case 0x4b: -+ nv_mask(dev, 0x004038, 0xc0771100, info->mpll_ctrl); -+ nv_wr32(dev, 0x00403c, info->mpll_coef); -+ default: -+ nv_mask(dev, 0x004020, 0xc0771100, info->mpll_ctrl); -+ nv_wr32(dev, 0x004024, info->mpll_coef); -+ break; -+ } -+ udelay(100); -+ nv_mask(dev, 0x00c040, 0x0000c000, 0x0000c000); -+ -+ /* re-enable normal operation of memory controller */ -+ nv_wr32(dev, 0x1002dc, 0x00000000); -+ nv_mask(dev, 0x100210, 0x80000000, 0x80000000); -+ udelay(100); -+ -+ /* execute memory reset script from vbios */ -+ if (!bit_table(dev, 'M', &M)) -+ nouveau_bios_init_exec(dev, ROM16(M.data[0])); -+ -+ /* make sure we're in vblank (hopefully the same one as before), and -+ * then re-enable crtc memory access -+ */ -+ for (i = 0; i < 2; i++) { -+ if (!(crtc_mask & (1 << i))) -+ continue; -+ nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); -+ nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01); -+ nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i]); -+ } -+ -+ /* resume engines */ -+resume: -+ nv_wr32(dev, 0x003250, 0x00000001); -+ nv_mask(dev, 0x003220, 0x00000001, 0x00000001); -+ nv_wr32(dev, 0x003200, 0x00000001); -+ nv_wr32(dev, 0x002500, 0x00000001); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ -+ kfree(info); -+} -diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c -index 5d98907..882080e 100644 ---- a/drivers/gpu/drm/nouveau/nv50_crtc.c -+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c -@@ -329,8 +329,6 @@ nv50_crtc_destroy(struct drm_crtc *crtc) - - drm_crtc_cleanup(&nv_crtc->base); - -- nv50_cursor_fini(nv_crtc); -- - nouveau_bo_unmap(nv_crtc->lut.nvbo); - nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); - nouveau_bo_unmap(nv_crtc->cursor.nvbo); -diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c -index 9752c35..adfc9b6 100644 ---- a/drivers/gpu/drm/nouveau/nv50_cursor.c -+++ b/drivers/gpu/drm/nouveau/nv50_cursor.c -@@ -137,21 +137,3 @@ nv50_cursor_init(struct nouveau_crtc *nv_crtc) - nv_crtc->cursor.show = nv50_cursor_show; - return 0; - } -- --void --nv50_cursor_fini(struct nouveau_crtc *nv_crtc) --{ -- struct drm_device *dev = nv_crtc->base.dev; -- int idx = nv_crtc->index; -- -- NV_DEBUG_KMS(dev, "\n"); -- -- nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0); -- if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), -- NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { -- NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); -- NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", -- nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx))); -- } --} -- -diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c -index db1a5f4..d23ca00 100644 ---- a/drivers/gpu/drm/nouveau/nv50_display.c -+++ b/drivers/gpu/drm/nouveau/nv50_display.c -@@ -247,6 +247,16 @@ static int nv50_display_disable(struct drm_device *dev) - } - } - -+ for (i = 0; i < 2; i++) { -+ nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0); -+ if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), -+ NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { -+ NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); -+ NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", -+ nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); -+ } -+ } -+ - nv50_evo_fini(dev); - - for (i = 0; i < 3; i++) { -@@ -286,23 +296,6 @@ int nv50_display_create(struct drm_device *dev) - return -ENOMEM; - dev_priv->engine.display.priv = priv; - -- /* init basic kernel modesetting */ -- drm_mode_config_init(dev); -- -- /* Initialise some optional connector properties. */ -- drm_mode_create_scaling_mode_property(dev); -- drm_mode_create_dithering_property(dev); -- -- dev->mode_config.min_width = 0; -- dev->mode_config.min_height = 0; -- -- dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; -- -- dev->mode_config.max_width = 8192; -- dev->mode_config.max_height = 8192; -- -- dev->mode_config.fb_base = dev_priv->fb_phys; -- - /* Create CRTC objects */ - for (i = 0; i < 2; i++) - nv50_crtc_create(dev, i); -@@ -364,8 +357,6 @@ nv50_display_destroy(struct drm_device *dev) - - NV_DEBUG_KMS(dev, "\n"); - -- drm_mode_config_cleanup(dev); -- - nv50_display_disable(dev); - nouveau_irq_unregister(dev, 26); - kfree(disp); -@@ -698,7 +689,7 @@ nv50_display_unk10_handler(struct drm_device *dev) - struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i]; - - if (dcb->type == type && (dcb->or & (1 << or))) { -- nouveau_bios_run_display_table(dev, dcb, 0, -1); -+ nouveau_bios_run_display_table(dev, 0, -1, dcb, -1); - disp->irq.dcb = dcb; - goto ack; - } -@@ -711,37 +702,6 @@ ack: - } - - static void --nv50_display_unk20_dp_hack(struct drm_device *dev, struct dcb_entry *dcb) --{ -- int or = ffs(dcb->or) - 1, link = !(dcb->dpconf.sor.link & 1); -- struct drm_encoder *encoder; -- uint32_t tmp, unk0 = 0, unk1 = 0; -- -- if (dcb->type != OUTPUT_DP) -- return; -- -- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- -- if (nv_encoder->dcb == dcb) { -- unk0 = nv_encoder->dp.unk0; -- unk1 = nv_encoder->dp.unk1; -- break; -- } -- } -- -- if (unk0 || unk1) { -- tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); -- tmp &= 0xfffffe03; -- nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp | unk0); -- -- tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link)); -- tmp &= 0xfef080c0; -- nv_wr32(dev, NV50_SOR_DP_UNK128(or, link), tmp | unk1); -- } --} -- --static void - nv50_display_unk20_handler(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -@@ -753,7 +713,7 @@ nv50_display_unk20_handler(struct drm_device *dev) - NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); - dcb = disp->irq.dcb; - if (dcb) { -- nouveau_bios_run_display_table(dev, dcb, 0, -2); -+ nouveau_bios_run_display_table(dev, 0, -2, dcb, -1); - disp->irq.dcb = NULL; - } - -@@ -837,9 +797,15 @@ nv50_display_unk20_handler(struct drm_device *dev) - } - - script = nv50_display_script_select(dev, dcb, mc, pclk); -- nouveau_bios_run_display_table(dev, dcb, script, pclk); -+ nouveau_bios_run_display_table(dev, script, pclk, dcb, -1); - -- nv50_display_unk20_dp_hack(dev, dcb); -+ if (type == OUTPUT_DP) { -+ int link = !(dcb->dpconf.sor.link & 1); -+ if ((mc & 0x000f0000) == 0x00020000) -+ nouveau_dp_tu_update(dev, or, link, pclk, 18); -+ else -+ nouveau_dp_tu_update(dev, or, link, pclk, 24); -+ } - - if (dcb->type != OUTPUT_ANALOG) { - tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or)); -@@ -904,7 +870,7 @@ nv50_display_unk40_handler(struct drm_device *dev) - if (!dcb) - goto ack; - -- nouveau_bios_run_display_table(dev, dcb, script, -pclk); -+ nouveau_bios_run_display_table(dev, script, -pclk, dcb, -1); - nv50_display_unk40_dp_set_tmds(dev, dcb); - - ack: -diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c -index d4f4206..793a5cc 100644 ---- a/drivers/gpu/drm/nouveau/nv50_gpio.c -+++ b/drivers/gpu/drm/nouveau/nv50_gpio.c -@@ -98,6 +98,37 @@ nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) - } - - int -+nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) -+{ -+ struct dcb_gpio_entry *gpio; -+ u32 v; -+ -+ gpio = nouveau_bios_gpio_entry(dev, tag); -+ if (!gpio) -+ return -ENOENT; -+ -+ v = nv_rd32(dev, 0x00d610 + (gpio->line * 4)); -+ v &= 0x00004000; -+ return (!!v == (gpio->state[1] & 1)); -+} -+ -+int -+nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) -+{ -+ struct dcb_gpio_entry *gpio; -+ u32 v; -+ -+ gpio = nouveau_bios_gpio_entry(dev, tag); -+ if (!gpio) -+ return -ENOENT; -+ -+ v = gpio->state[state] ^ 2; -+ -+ nv_mask(dev, 0x00d610 + (gpio->line * 4), 0x00003000, v << 12); -+ return 0; -+} -+ -+int - nv50_gpio_irq_register(struct drm_device *dev, enum dcb_gpio_tag tag, - void (*handler)(void *, int), void *data) - { -diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c -index d43c46c..8c979b3 100644 ---- a/drivers/gpu/drm/nouveau/nv50_graph.c -+++ b/drivers/gpu/drm/nouveau/nv50_graph.c -@@ -120,70 +120,62 @@ nv50_graph_unload_context(struct drm_device *dev) - return 0; - } - --static void --nv50_graph_init_reset(struct drm_device *dev) --{ -- uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21); -- NV_DEBUG(dev, "\n"); -- -- nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e); -- nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | pmc_e); --} -- --static void --nv50_graph_init_intr(struct drm_device *dev) --{ -- NV_DEBUG(dev, "\n"); -- -- nv_wr32(dev, NV03_PGRAPH_INTR, 0xffffffff); -- nv_wr32(dev, 0x400138, 0xffffffff); -- nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xffffffff); --} -- --static void --nv50_graph_init_regs__nv(struct drm_device *dev) -+static int -+nv50_graph_init(struct drm_device *dev, int engine) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t units = nv_rd32(dev, 0x1540); -+ struct nv50_graph_engine *pgraph = nv_engine(dev, engine); -+ u32 units = nv_rd32(dev, 0x001540); - int i; - - NV_DEBUG(dev, "\n"); - -+ /* master reset */ -+ nv_mask(dev, 0x000200, 0x00200100, 0x00000000); -+ nv_mask(dev, 0x000200, 0x00200100, 0x00200100); -+ nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */ -+ -+ /* reset/enable traps and interrupts */ - nv_wr32(dev, 0x400804, 0xc0000000); - nv_wr32(dev, 0x406800, 0xc0000000); - nv_wr32(dev, 0x400c04, 0xc0000000); - nv_wr32(dev, 0x401800, 0xc0000000); - nv_wr32(dev, 0x405018, 0xc0000000); - nv_wr32(dev, 0x402000, 0xc0000000); -- - for (i = 0; i < 16; i++) { -- if (units & 1 << i) { -- if (dev_priv->chipset < 0xa0) { -- nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000); -- nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000); -- nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000); -- } else { -- nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000); -- nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000); -- nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000); -- } -+ if (!(units & (1 << i))) -+ continue; -+ -+ if (dev_priv->chipset < 0xa0) { -+ nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000); -+ nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000); -+ nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000); -+ } else { -+ nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000); -+ nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000); -+ nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000); - } - } - - nv_wr32(dev, 0x400108, 0xffffffff); -- -- nv_wr32(dev, 0x400824, 0x00004000); -+ nv_wr32(dev, 0x400138, 0xffffffff); -+ nv_wr32(dev, 0x400100, 0xffffffff); -+ nv_wr32(dev, 0x40013c, 0xffffffff); - nv_wr32(dev, 0x400500, 0x00010001); --} -- --static void --nv50_graph_init_zcull(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- int i; - -- NV_DEBUG(dev, "\n"); -+ /* upload context program, initialise ctxctl defaults */ -+ nv_wr32(dev, 0x400324, 0x00000000); -+ for (i = 0; i < pgraph->ctxprog_size; i++) -+ nv_wr32(dev, 0x400328, pgraph->ctxprog[i]); -+ nv_wr32(dev, 0x400824, 0x00000000); -+ nv_wr32(dev, 0x400828, 0x00000000); -+ nv_wr32(dev, 0x40082c, 0x00000000); -+ nv_wr32(dev, 0x400830, 0x00000000); -+ nv_wr32(dev, 0x400724, 0x00000000); -+ nv_wr32(dev, 0x40032c, 0x00000000); -+ nv_wr32(dev, 0x400320, 4); /* CTXCTL_CMD = NEWCTXDMA */ - -+ /* some unknown zcull magic */ - switch (dev_priv->chipset & 0xf0) { - case 0x50: - case 0x80: -@@ -212,43 +204,7 @@ nv50_graph_init_zcull(struct drm_device *dev) - nv_wr32(dev, 0x402c28 + (i * 8), 0x00000000); - nv_wr32(dev, 0x402c2c + (i * 8), 0x00000000); - } --} -- --static int --nv50_graph_init_ctxctl(struct drm_device *dev) --{ -- struct nv50_graph_engine *pgraph = nv_engine(dev, NVOBJ_ENGINE_GR); -- int i; -- -- NV_DEBUG(dev, "\n"); -- -- nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); -- for (i = 0; i < pgraph->ctxprog_size; i++) -- nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, pgraph->ctxprog[i]); -- -- 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); -- return 0; --} -- --static int --nv50_graph_init(struct drm_device *dev, int engine) --{ -- int ret; -- -- NV_DEBUG(dev, "\n"); -- -- nv50_graph_init_reset(dev); -- nv50_graph_init_regs__nv(dev); -- nv50_graph_init_zcull(dev); -- -- ret = nv50_graph_init_ctxctl(dev); -- if (ret) -- return ret; - -- nv50_graph_init_intr(dev); - return 0; - } - -diff --git a/drivers/gpu/drm/nouveau/nv50_grctx.c b/drivers/gpu/drm/nouveau/nv50_grctx.c -index de9abff..d05c2c3 100644 ---- a/drivers/gpu/drm/nouveau/nv50_grctx.c -+++ b/drivers/gpu/drm/nouveau/nv50_grctx.c -@@ -40,6 +40,12 @@ - #define CP_FLAG_UNK0B ((0 * 32) + 0xb) - #define CP_FLAG_UNK0B_CLEAR 0 - #define CP_FLAG_UNK0B_SET 1 -+#define CP_FLAG_XFER_SWITCH ((0 * 32) + 0xe) -+#define CP_FLAG_XFER_SWITCH_DISABLE 0 -+#define CP_FLAG_XFER_SWITCH_ENABLE 1 -+#define CP_FLAG_STATE ((0 * 32) + 0x1c) -+#define CP_FLAG_STATE_STOPPED 0 -+#define CP_FLAG_STATE_RUNNING 1 - #define CP_FLAG_UNK1D ((0 * 32) + 0x1d) - #define CP_FLAG_UNK1D_CLEAR 0 - #define CP_FLAG_UNK1D_SET 1 -@@ -194,6 +200,9 @@ nv50_grctx_init(struct nouveau_grctx *ctx) - "the devs.\n"); - return -ENOSYS; - } -+ -+ cp_set (ctx, STATE, RUNNING); -+ cp_set (ctx, XFER_SWITCH, ENABLE); - /* decide whether we're loading/unloading the context */ - cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save); - cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save); -@@ -260,6 +269,8 @@ nv50_grctx_init(struct nouveau_grctx *ctx) - cp_name(ctx, cp_exit); - cp_set (ctx, USER_SAVE, NOT_PENDING); - cp_set (ctx, USER_LOAD, NOT_PENDING); -+ cp_set (ctx, XFER_SWITCH, DISABLE); -+ cp_set (ctx, STATE, STOPPED); - cp_out (ctx, CP_END); - ctx->ctxvals_pos += 0x400; /* padding... no idea why you need it */ - -diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c -index 8a28100..3d5a86b 100644 ---- a/drivers/gpu/drm/nouveau/nv50_pm.c -+++ b/drivers/gpu/drm/nouveau/nv50_pm.c -@@ -115,15 +115,15 @@ nv50_pm_clock_set(struct drm_device *dev, void *pre_state) - BIT_M.version == 1 && BIT_M.length >= 0x0b) { - script = ROM16(BIT_M.data[0x05]); - if (script) -- nouveau_bios_run_init_table(dev, script, NULL); -+ nouveau_bios_run_init_table(dev, script, NULL, -1); - script = ROM16(BIT_M.data[0x07]); - if (script) -- nouveau_bios_run_init_table(dev, script, NULL); -+ nouveau_bios_run_init_table(dev, script, NULL, -1); - script = ROM16(BIT_M.data[0x09]); - if (script) -- nouveau_bios_run_init_table(dev, script, NULL); -+ nouveau_bios_run_init_table(dev, script, NULL, -1); - -- nouveau_bios_run_init_table(dev, perflvl->memscript, NULL); -+ nouveau_bios_run_init_table(dev, perflvl->memscript, NULL, -1); - } - - if (state->type == PLL_MEMORY) { -diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c -index ffe8b48..2633aa8 100644 ---- a/drivers/gpu/drm/nouveau/nv50_sor.c -+++ b/drivers/gpu/drm/nouveau/nv50_sor.c -@@ -124,7 +124,7 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) - if (mode == DRM_MODE_DPMS_ON) { - u8 status = DP_SET_POWER_D0; - nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); -- nouveau_dp_link_train(encoder); -+ nouveau_dp_link_train(encoder, nv_encoder->dp.datarate); - } else { - u8 status = DP_SET_POWER_D3; - nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); -@@ -187,14 +187,13 @@ nv50_sor_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 nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); -+ struct nouveau_connector *nv_connector; - uint32_t mode_ctl = 0; - int ret; - - NV_DEBUG_KMS(dev, "or %d type %d -> crtc %d\n", - nv_encoder->or, nv_encoder->dcb->type, crtc->index); - -- nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); -- - switch (nv_encoder->dcb->type) { - case OUTPUT_TMDS: - if (nv_encoder->dcb->sorconf.link & 1) { -@@ -206,7 +205,15 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - mode_ctl = 0x0200; - break; - case OUTPUT_DP: -- mode_ctl |= (nv_encoder->dp.mc_unknown << 16); -+ nv_connector = nouveau_encoder_connector_get(nv_encoder); -+ if (nv_connector && nv_connector->base.display_info.bpc == 6) { -+ nv_encoder->dp.datarate = crtc->mode->clock * 18 / 8; -+ mode_ctl |= 0x00020000; -+ } else { -+ nv_encoder->dp.datarate = crtc->mode->clock * 24 / 8; -+ mode_ctl |= 0x00050000; -+ } -+ - if (nv_encoder->dcb->sorconf.link & 1) - mode_ctl |= 0x00000800; - else -@@ -227,6 +234,8 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) - mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NVSYNC; - -+ nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); -+ - ret = RING_SPACE(evo, 2); - if (ret) { - NV_ERROR(dev, "no space while connecting SOR\n"); -@@ -313,31 +322,6 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry) - encoder->possible_crtcs = entry->heads; - encoder->possible_clones = 0; - -- if (nv_encoder->dcb->type == OUTPUT_DP) { -- int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1); -- uint32_t tmp; -- -- tmp = nv_rd32(dev, 0x61c700 + (or * 0x800)); -- if (!tmp) -- tmp = nv_rd32(dev, 0x610798 + (or * 8)); -- -- switch ((tmp & 0x00000f00) >> 8) { -- case 8: -- case 9: -- nv_encoder->dp.mc_unknown = (tmp & 0x000f0000) >> 16; -- tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); -- nv_encoder->dp.unk0 = tmp & 0x000001fc; -- tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link)); -- nv_encoder->dp.unk1 = tmp & 0x010f7f3f; -- break; -- default: -- break; -- } -- -- if (!nv_encoder->dp.mc_unknown) -- nv_encoder->dp.mc_unknown = 5; -- } -- - drm_mode_connector_attach_encoder(connector, encoder); - return 0; - } -diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c -index af32dae..9da2383 100644 ---- a/drivers/gpu/drm/nouveau/nv50_vram.c -+++ b/drivers/gpu/drm/nouveau/nv50_vram.c -@@ -51,7 +51,7 @@ void - nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_mm *mm = dev_priv->engine.vram.mm; -+ struct nouveau_mm *mm = &dev_priv->engine.vram.mm; - struct nouveau_mm_node *this; - struct nouveau_mem *mem; - -@@ -82,7 +82,7 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, - u32 memtype, struct nouveau_mem **pmem) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_mm *mm = dev_priv->engine.vram.mm; -+ struct nouveau_mm *mm = &dev_priv->engine.vram.mm; - struct nouveau_mm_node *r; - struct nouveau_mem *mem; - int comp = (memtype & 0x300) >> 8; -diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c -index e4b2b9e..618c144 100644 ---- a/drivers/gpu/drm/nouveau/nva3_pm.c -+++ b/drivers/gpu/drm/nouveau/nva3_pm.c -@@ -27,178 +27,316 @@ - #include "nouveau_bios.h" - #include "nouveau_pm.h" - --/* 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. -- */ -+static u32 read_clk(struct drm_device *, int, bool); -+static u32 read_pll(struct drm_device *, int, u32); - --struct nva3_pm_state { -- enum pll_types type; -- u32 src0; -- u32 src1; -- u32 ctrl; -- u32 coef; -- u32 old_pnm; -- u32 new_pnm; -- u32 new_div; --}; -+static u32 -+read_vco(struct drm_device *dev, int clk) -+{ -+ u32 sctl = nv_rd32(dev, 0x4120 + (clk * 4)); -+ if ((sctl & 0x00000030) != 0x00000030) -+ return read_pll(dev, 0x41, 0x00e820); -+ return read_pll(dev, 0x42, 0x00e8a0); -+} - --static int --nva3_pm_pll_offset(u32 id) -+static u32 -+read_clk(struct drm_device *dev, int clk, bool ignore_en) - { -- static const u32 pll_map[] = { -- 0x00, PLL_CORE, -- 0x01, PLL_SHADER, -- 0x02, PLL_MEMORY, -- 0x00, 0x00 -- }; -- const u32 *map = pll_map; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ u32 sctl, sdiv, sclk; - -- while (map[1]) { -- if (id == map[1]) -- return map[0]; -- map += 2; -+ /* refclk for the 0xe8xx plls is a fixed frequency */ -+ if (clk >= 0x40) { -+ if (dev_priv->chipset == 0xaf) { -+ /* no joke.. seriously.. sigh.. */ -+ return nv_rd32(dev, 0x00471c) * 1000; -+ } -+ -+ return dev_priv->crystal; - } - -- return -ENOENT; -+ sctl = nv_rd32(dev, 0x4120 + (clk * 4)); -+ if (!ignore_en && !(sctl & 0x00000100)) -+ return 0; -+ -+ switch (sctl & 0x00003000) { -+ case 0x00000000: -+ return dev_priv->crystal; -+ case 0x00002000: -+ if (sctl & 0x00000040) -+ return 108000; -+ return 100000; -+ case 0x00003000: -+ sclk = read_vco(dev, clk); -+ sdiv = ((sctl & 0x003f0000) >> 16) + 2; -+ return (sclk * 2) / sdiv; -+ default: -+ return 0; -+ } - } - --int --nva3_pm_clock_get(struct drm_device *dev, u32 id) -+static u32 -+read_pll(struct drm_device *dev, int clk, u32 pll) -+{ -+ u32 ctrl = nv_rd32(dev, pll + 0); -+ u32 sclk = 0, P = 1, N = 1, M = 1; -+ -+ if (!(ctrl & 0x00000008)) { -+ if (ctrl & 0x00000001) { -+ u32 coef = nv_rd32(dev, pll + 4); -+ M = (coef & 0x000000ff) >> 0; -+ N = (coef & 0x0000ff00) >> 8; -+ P = (coef & 0x003f0000) >> 16; -+ -+ /* no post-divider on these.. */ -+ if ((pll & 0x00ff00) == 0x00e800) -+ P = 1; -+ -+ sclk = read_clk(dev, 0x00 + clk, false); -+ } -+ } else { -+ sclk = read_clk(dev, 0x10 + clk, false); -+ } -+ -+ return sclk * N / (M * P); -+} -+ -+struct creg { -+ u32 clk; -+ u32 pll; -+}; -+ -+static int -+calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) - { -- u32 src0, src1, ctrl, coef; -- struct pll_lims pll; -- int ret, off; -- int P, N, M; -+ struct pll_lims limits; -+ u32 oclk, sclk, sdiv; -+ int P, N, M, diff; -+ int ret; -+ -+ reg->pll = 0; -+ reg->clk = 0; -+ if (!khz) { -+ NV_DEBUG(dev, "no clock for 0x%04x/0x%02x\n", pll, clk); -+ return 0; -+ } -+ -+ switch (khz) { -+ case 27000: -+ reg->clk = 0x00000100; -+ return khz; -+ case 100000: -+ reg->clk = 0x00002100; -+ return khz; -+ case 108000: -+ reg->clk = 0x00002140; -+ return khz; -+ default: -+ sclk = read_vco(dev, clk); -+ sdiv = min((sclk * 2) / (khz - 2999), (u32)65); -+ /* if the clock has a PLL attached, and we can get a within -+ * [-2, 3) MHz of a divider, we'll disable the PLL and use -+ * the divider instead. -+ * -+ * divider can go as low as 2, limited here because NVIDIA -+ * and the VBIOS on my NVA8 seem to prefer using the PLL -+ * for 810MHz - is there a good reason? -+ */ -+ if (sdiv > 4) { -+ oclk = (sclk * 2) / sdiv; -+ diff = khz - oclk; -+ if (!pll || (diff >= -2000 && diff < 3000)) { -+ reg->clk = (((sdiv - 2) << 16) | 0x00003100); -+ return oclk; -+ } -+ } - -- ret = get_pll_limits(dev, id, &pll); -+ if (!pll) { -+ NV_ERROR(dev, "bad freq %02x: %d %d\n", clk, khz, sclk); -+ return -ERANGE; -+ } -+ -+ break; -+ } -+ -+ ret = get_pll_limits(dev, pll, &limits); - if (ret) - return ret; - -- off = nva3_pm_pll_offset(id); -- if (off < 0) -- return off; -+ limits.refclk = read_clk(dev, clk - 0x10, true); -+ if (!limits.refclk) -+ return -EINVAL; -+ -+ ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P); -+ if (ret >= 0) { -+ reg->clk = nv_rd32(dev, 0x4120 + (clk * 4)); -+ reg->pll = (P << 16) | (N << 8) | M; -+ } -+ return ret; -+} -+ -+static void -+prog_pll(struct drm_device *dev, int clk, u32 pll, struct creg *reg) -+{ -+ const u32 src0 = 0x004120 + (clk * 4); -+ const u32 src1 = 0x004160 + (clk * 4); -+ const u32 ctrl = pll + 0; -+ const u32 coef = pll + 4; -+ u32 cntl; -+ -+ if (!reg->clk && !reg->pll) { -+ NV_DEBUG(dev, "no clock for %02x\n", clk); -+ return; -+ } - -- 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); -+ cntl = nv_rd32(dev, ctrl) & 0xfffffff2; -+ if (reg->pll) { -+ nv_mask(dev, src0, 0x00000101, 0x00000101); -+ nv_wr32(dev, coef, reg->pll); -+ nv_wr32(dev, ctrl, cntl | 0x00000015); -+ nv_mask(dev, src1, 0x00000100, 0x00000000); -+ nv_mask(dev, src1, 0x00000001, 0x00000000); -+ } else { -+ nv_mask(dev, src1, 0x003f3141, 0x00000101 | reg->clk); -+ nv_wr32(dev, ctrl, cntl | 0x0000001d); -+ nv_mask(dev, ctrl, 0x00000001, 0x00000000); -+ nv_mask(dev, src0, 0x00000100, 0x00000000); -+ nv_mask(dev, src0, 0x00000001, 0x00000000); -+ } -+} - -- if (ctrl & 0x00000008) { -- u32 div = ((src1 & 0x003c0000) >> 18) + 1; -- return (pll.refclk * 2) / div; -+static void -+prog_clk(struct drm_device *dev, int clk, struct creg *reg) -+{ -+ if (!reg->clk) { -+ NV_DEBUG(dev, "no clock for %02x\n", clk); -+ return; - } - -- P = (coef & 0x003f0000) >> 16; -- N = (coef & 0x0000ff00) >> 8; -- M = (coef & 0x000000ff); -- return pll.refclk * N / M / P; -+ nv_mask(dev, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | reg->clk); -+} -+ -+int -+nva3_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) -+{ -+ perflvl->core = read_pll(dev, 0x00, 0x4200); -+ perflvl->shader = read_pll(dev, 0x01, 0x4220); -+ perflvl->memory = read_pll(dev, 0x02, 0x4000); -+ perflvl->unka0 = read_clk(dev, 0x20, false); -+ perflvl->vdec = read_clk(dev, 0x21, false); -+ perflvl->daemon = read_clk(dev, 0x25, false); -+ perflvl->copy = perflvl->core; -+ return 0; - } - -+struct nva3_pm_state { -+ struct creg nclk; -+ struct creg sclk; -+ struct creg mclk; -+ struct creg vdec; -+ struct creg unka0; -+}; -+ - void * --nva3_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, -- u32 id, int khz) -+nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) - { -- struct nva3_pm_state *pll; -- struct pll_lims limits; -- int N, M, P, diff; -- int ret, off; -+ struct nva3_pm_state *info; -+ int ret; - -- ret = get_pll_limits(dev, id, &limits); -- if (ret < 0) -- return (ret == -ENOENT) ? NULL : ERR_PTR(ret); -+ info = kzalloc(sizeof(*info), GFP_KERNEL); -+ if (!info) -+ return ERR_PTR(-ENOMEM); - -- off = nva3_pm_pll_offset(id); -- if (id < 0) -- return ERR_PTR(-EINVAL); -+ ret = calc_clk(dev, 0x10, 0x4200, perflvl->core, &info->nclk); -+ if (ret < 0) -+ goto out; - -+ ret = calc_clk(dev, 0x11, 0x4220, perflvl->shader, &info->sclk); -+ if (ret < 0) -+ goto out; - -- 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 = calc_clk(dev, 0x12, 0x4000, perflvl->memory, &info->mclk); -+ if (ret < 0) -+ goto out; - -- /* 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 = calc_clk(dev, 0x20, 0x0000, perflvl->unka0, &info->unka0); -+ if (ret < 0) -+ goto out; - -- if (!pll->new_div) { -- ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P); -- if (ret < 0) -- return ERR_PTR(ret); -+ ret = calc_clk(dev, 0x21, 0x0000, perflvl->vdec, &info->vdec); -+ if (ret < 0) -+ goto out; - -- pll->new_pnm = (P << 16) | (N << 8) | M; -- pll->new_div = 2 - 1; -- } else { -- pll->new_pnm = 0; -- pll->new_div--; -+out: -+ if (ret < 0) { -+ kfree(info); -+ info = ERR_PTR(ret); - } -+ return info; -+} -+ -+static bool -+nva3_pm_grcp_idle(void *data) -+{ -+ struct drm_device *dev = data; - -- if ((nv_rd32(dev, pll->src1) & 0x00000101) != 0x00000101) -- pll->old_pnm = nv_rd32(dev, pll->coef); -- return pll; -+ if (!(nv_rd32(dev, 0x400304) & 0x00000001)) -+ return true; -+ if (nv_rd32(dev, 0x400308) == 0x0050001c) -+ return true; -+ return false; - } - - void --nva3_pm_clock_set(struct drm_device *dev, void *pre_state) -+nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) - { -- struct nva3_pm_state *pll = pre_state; -- u32 ctrl = 0; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nva3_pm_state *info = pre_state; -+ unsigned long flags; - -- /* 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; -+ /* prevent any new grctx switches from starting */ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ nv_wr32(dev, 0x400324, 0x00000000); -+ nv_wr32(dev, 0x400328, 0x0050001c); /* wait flag 0x1c */ -+ /* wait for any pending grctx switches to complete */ -+ if (!nv_wait_cb(dev, nva3_pm_grcp_idle, dev)) { -+ NV_ERROR(dev, "pm: ctxprog didn't go idle\n"); -+ goto cleanup; - } -- -- 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); -+ /* freeze PFIFO */ -+ nv_mask(dev, 0x002504, 0x00000001, 0x00000001); -+ if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) { -+ NV_ERROR(dev, "pm: fifo didn't go idle\n"); -+ goto cleanup; - } - -- 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); -- } -+ prog_pll(dev, 0x00, 0x004200, &info->nclk); -+ prog_pll(dev, 0x01, 0x004220, &info->sclk); -+ prog_clk(dev, 0x20, &info->unka0); -+ prog_clk(dev, 0x21, &info->vdec); - -- if (pll->type == PLL_MEMORY) { -+ if (info->mclk.clk || info->mclk.pll) { -+ nv_wr32(dev, 0x100210, 0); -+ nv_wr32(dev, 0x1002dc, 1); -+ nv_wr32(dev, 0x004018, 0x00001000); -+ prog_pll(dev, 0x02, 0x004000, &info->mclk); -+ if (nv_rd32(dev, 0x4000) & 0x00000008) -+ nv_wr32(dev, 0x004018, 0x1000d000); -+ else -+ nv_wr32(dev, 0x004018, 0x10005000); - nv_wr32(dev, 0x1002dc, 0); - nv_wr32(dev, 0x100210, 0x80000000); - } - -- kfree(pll); -+cleanup: -+ /* unfreeze PFIFO */ -+ nv_mask(dev, 0x002504, 0x00000001, 0x00000000); -+ /* restore ctxprog to normal */ -+ nv_wr32(dev, 0x400324, 0x00000000); -+ nv_wr32(dev, 0x400328, 0x0070009c); /* set flag 0x1c */ -+ /* unblock it if necessary */ -+ if (nv_rd32(dev, 0x400308) == 0x0050001c) -+ nv_mask(dev, 0x400824, 0x10000000, 0x10000000); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ kfree(info); - } -- -diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c -index 08e6b11..5bf5503 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_fb.c -+++ b/drivers/gpu/drm/nouveau/nvc0_fb.c -@@ -32,6 +32,30 @@ struct nvc0_fb_priv { - dma_addr_t r100c10; - }; - -+static inline void -+nvc0_mfb_subp_isr(struct drm_device *dev, int unit, int subp) -+{ -+ u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400); -+ u32 stat = nv_rd32(dev, subp_base + 0x020); -+ -+ if (stat) { -+ NV_INFO(dev, "PMFB%d_SUBP%d: 0x%08x\n", unit, subp, stat); -+ nv_wr32(dev, subp_base + 0x020, stat); -+ } -+} -+ -+static void -+nvc0_mfb_isr(struct drm_device *dev) -+{ -+ u32 units = nv_rd32(dev, 0x00017c); -+ while (units) { -+ u32 subp, unit = ffs(units) - 1; -+ for (subp = 0; subp < 2; subp++) -+ nvc0_mfb_subp_isr(dev, unit, subp); -+ units &= ~(1 << unit); -+ } -+} -+ - static void - nvc0_fb_destroy(struct drm_device *dev) - { -@@ -39,6 +63,8 @@ nvc0_fb_destroy(struct drm_device *dev) - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nvc0_fb_priv *priv = pfb->priv; - -+ nouveau_irq_unregister(dev, 25); -+ - if (priv->r100c10_page) { - pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); -@@ -74,6 +100,7 @@ nvc0_fb_create(struct drm_device *dev) - return -EFAULT; - } - -+ nouveau_irq_register(dev, 25, nvc0_mfb_isr); - return 0; - } - -diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c -index 6f9f341..dcbe0d5 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_fifo.c -+++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c -@@ -322,7 +322,7 @@ nvc0_fifo_init(struct drm_device *dev) - } - - /* PSUBFIFO[n] */ -- for (i = 0; i < 3; i++) { -+ for (i = 0; i < priv->spoon_nr; i++) { - nv_mask(dev, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); - nv_wr32(dev, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ - nv_wr32(dev, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTR_EN */ -diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c -index 5b2f6f4..4b8d0b3 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_graph.c -+++ b/drivers/gpu/drm/nouveau/nvc0_graph.c -@@ -390,7 +390,7 @@ nvc0_graph_init_gpc_0(struct drm_device *dev) - } - - nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918); -- nv_wr32(dev, GPC_BCAST(0x08ac), priv->rop_nr); -+ nv_wr32(dev, GPC_BCAST(0x08ac), nv_rd32(dev, 0x100800)); - } - - static void -@@ -700,22 +700,6 @@ nvc0_graph_isr(struct drm_device *dev) - nv_wr32(dev, 0x400500, 0x00010001); - } - --static void --nvc0_runk140_isr(struct drm_device *dev) --{ -- u32 units = nv_rd32(dev, 0x00017c) & 0x1f; -- -- while (units) { -- u32 unit = ffs(units) - 1; -- u32 reg = 0x140000 + unit * 0x2000; -- u32 st0 = nv_mask(dev, reg + 0x1020, 0, 0); -- u32 st1 = nv_mask(dev, reg + 0x1420, 0, 0); -- -- NV_DEBUG(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1); -- units &= ~(1 << unit); -- } --} -- - static int - nvc0_graph_create_fw(struct drm_device *dev, const char *fwname, - struct nvc0_graph_fuc *fuc) -@@ -764,7 +748,6 @@ nvc0_graph_destroy(struct drm_device *dev, int engine) - } - - nouveau_irq_unregister(dev, 12); -- nouveau_irq_unregister(dev, 25); - - nouveau_gpuobj_ref(NULL, &priv->unk4188b8); - nouveau_gpuobj_ref(NULL, &priv->unk4188b4); -@@ -803,7 +786,6 @@ nvc0_graph_create(struct drm_device *dev) - - NVOBJ_ENGINE_ADD(dev, GR, &priv->base); - nouveau_irq_register(dev, 12, nvc0_graph_isr); -- nouveau_irq_register(dev, 25, nvc0_runk140_isr); - - if (nouveau_ctxfw) { - NV_INFO(dev, "PGRAPH: using external firmware\n"); -@@ -864,6 +846,9 @@ nvc0_graph_create(struct drm_device *dev) - case 0xce: /* 4/4/0/0, 4 */ - priv->magic_not_rop_nr = 0x03; - break; -+ case 0xcf: /* 4/0/0/0, 3 */ -+ priv->magic_not_rop_nr = 0x03; -+ break; - } - - if (!priv->magic_not_rop_nr) { -@@ -889,20 +874,3 @@ error: - nvc0_graph_destroy(dev, NVOBJ_ENGINE_GR); - return ret; - } -- --MODULE_FIRMWARE("nouveau/nvc0_fuc409c"); --MODULE_FIRMWARE("nouveau/nvc0_fuc409d"); --MODULE_FIRMWARE("nouveau/nvc0_fuc41ac"); --MODULE_FIRMWARE("nouveau/nvc0_fuc41ad"); --MODULE_FIRMWARE("nouveau/nvc3_fuc409c"); --MODULE_FIRMWARE("nouveau/nvc3_fuc409d"); --MODULE_FIRMWARE("nouveau/nvc3_fuc41ac"); --MODULE_FIRMWARE("nouveau/nvc3_fuc41ad"); --MODULE_FIRMWARE("nouveau/nvc4_fuc409c"); --MODULE_FIRMWARE("nouveau/nvc4_fuc409d"); --MODULE_FIRMWARE("nouveau/nvc4_fuc41ac"); --MODULE_FIRMWARE("nouveau/nvc4_fuc41ad"); --MODULE_FIRMWARE("nouveau/fuc409c"); --MODULE_FIRMWARE("nouveau/fuc409d"); --MODULE_FIRMWARE("nouveau/fuc41ac"); --MODULE_FIRMWARE("nouveau/fuc41ad"); -diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.h b/drivers/gpu/drm/nouveau/nvc0_graph.h -index 55689e9..636fe98 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_graph.h -+++ b/drivers/gpu/drm/nouveau/nvc0_graph.h -@@ -82,6 +82,7 @@ nvc0_graph_class(struct drm_device *dev) - case 0xc3: - case 0xc4: - case 0xce: /* guess, mmio trace shows only 0x9097 state */ -+ case 0xcf: /* guess, mmio trace shows only 0x9097 state */ - return 0x9097; - case 0xc1: - return 0x9197; -diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c -index 31018ea..dd0e6a7 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_grctx.c -+++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c -@@ -1678,7 +1678,10 @@ nvc0_grctx_generate_tp(struct drm_device *dev) - nv_wr32(dev, 0x419c04, 0x00000006); - nv_wr32(dev, 0x419c08, 0x00000002); - nv_wr32(dev, 0x419c20, 0x00000000); -- nv_wr32(dev, 0x419cb0, 0x00060048); //XXX: 0xce 0x00020048 -+ if (chipset == 0xce || chipset == 0xcf) -+ nv_wr32(dev, 0x419cb0, 0x00020048); -+ else -+ nv_wr32(dev, 0x419cb0, 0x00060048); - nv_wr32(dev, 0x419ce8, 0x00000000); - nv_wr32(dev, 0x419cf4, 0x00000183); - nv_wr32(dev, 0x419d20, chipset != 0xc1 ? 0x02180000 : 0x12180000); -@@ -1783,11 +1786,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) - nv_wr32(dev, 0x40587c, 0x00000000); - - if (1) { -- const u8 chipset_tp_max[] = { 16, 4, 0, 4, 8, 0, 0, 0, -- 16, 0, 0, 0, 0, 0, 8, 0 }; -- u8 max = chipset_tp_max[dev_priv->chipset & 0x0f]; -- u8 tpnr[GPC_MAX]; -- u8 data[TP_MAX]; -+ u8 tpnr[GPC_MAX], data[TP_MAX]; - - memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); - memset(data, 0x1f, sizeof(data)); -@@ -1801,7 +1800,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) - data[tp] = gpc; - } - -- for (i = 0; i < max / 4; i++) -+ for (i = 0; i < 4; i++) - nv_wr32(dev, 0x4060a8 + (i * 4), ((u32 *)data)[i]); - } - -diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc -index 0ec2add..06f5e26 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc -+++ b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc -@@ -77,6 +77,11 @@ chipsets: - .b16 nvc0_gpc_mmio_tail - .b16 nvc0_tpc_mmio_head - .b16 nvc3_tpc_mmio_tail -+.b8 0xcf 0 0 0 -+.b16 nvc0_gpc_mmio_head -+.b16 nvc0_gpc_mmio_tail -+.b16 nvc0_tpc_mmio_head -+.b16 nvcf_tpc_mmio_tail - .b8 0 0 0 0 - - // GPC mmio lists -@@ -134,8 +139,9 @@ mmctx_data(0x000750, 2) - nvc0_tpc_mmio_tail: - mmctx_data(0x000758, 1) - mmctx_data(0x0002c4, 1) --mmctx_data(0x0004bc, 1) - mmctx_data(0x0006e0, 1) -+nvcf_tpc_mmio_tail: -+mmctx_data(0x0004bc, 1) - nvc3_tpc_mmio_tail: - mmctx_data(0x000544, 1) - nvc1_tpc_mmio_tail: -diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h -index 1896c89..6f82032 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h -+++ b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h -@@ -25,23 +25,26 @@ uint32_t nvc0_grgpc_data[] = { - 0x00000000, - 0x00000000, - 0x000000c0, -- 0x011000b0, -- 0x01640114, -+ 0x011c00bc, -+ 0x01700120, - 0x000000c1, -- 0x011400b0, -- 0x01780114, -+ 0x012000bc, -+ 0x01840120, - 0x000000c3, -- 0x011000b0, -- 0x01740114, -+ 0x011c00bc, -+ 0x01800120, - 0x000000c4, -- 0x011000b0, -- 0x01740114, -+ 0x011c00bc, -+ 0x01800120, - 0x000000c8, -- 0x011000b0, -- 0x01640114, -+ 0x011c00bc, -+ 0x01700120, - 0x000000ce, -- 0x011000b0, -- 0x01740114, -+ 0x011c00bc, -+ 0x01800120, -+ 0x000000cf, -+ 0x011c00bc, -+ 0x017c0120, - 0x00000000, - 0x00000380, - 0x14000400, -@@ -90,8 +93,8 @@ uint32_t nvc0_grgpc_data[] = { - 0x04000750, - 0x00000758, - 0x000002c4, -- 0x000004bc, - 0x000006e0, -+ 0x000004bc, - 0x00000544, - }; - -diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc -index a1a5991..e4f8c7e 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc -+++ b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc -@@ -56,6 +56,9 @@ chipsets: - .b8 0xce 0 0 0 - .b16 nvc0_hub_mmio_head - .b16 nvc0_hub_mmio_tail -+.b8 0xcf 0 0 0 -+.b16 nvc0_hub_mmio_head -+.b16 nvc0_hub_mmio_tail - .b8 0 0 0 0 - - nvc0_hub_mmio_head: -diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h -index b3b541b..241d326 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h -+++ b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h -@@ -23,17 +23,19 @@ uint32_t nvc0_grhub_data[] = { - 0x00000000, - 0x00000000, - 0x000000c0, -- 0x012c0090, -+ 0x01340098, - 0x000000c1, -- 0x01300090, -+ 0x01380098, - 0x000000c3, -- 0x012c0090, -+ 0x01340098, - 0x000000c4, -- 0x012c0090, -+ 0x01340098, - 0x000000c8, -- 0x012c0090, -+ 0x01340098, - 0x000000ce, -- 0x012c0090, -+ 0x01340098, -+ 0x000000cf, -+ 0x01340098, - 0x00000000, - 0x0417e91c, - 0x04400204, -@@ -190,8 +192,6 @@ uint32_t nvc0_grhub_data[] = { - 0x00000000, - 0x00000000, - 0x00000000, -- 0x00000000, -- 0x00000000, - }; - - uint32_t nvc0_grhub_code[] = { -diff --git a/drivers/gpu/drm/nouveau/nvc0_pm.c b/drivers/gpu/drm/nouveau/nvc0_pm.c -new file mode 100644 -index 0000000..929aded ---- /dev/null -+++ b/drivers/gpu/drm/nouveau/nvc0_pm.c -@@ -0,0 +1,155 @@ -+/* -+ * 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"), -+ * 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 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) OR AUTHOR(S) 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: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+#include "nouveau_drv.h" -+#include "nouveau_bios.h" -+#include "nouveau_pm.h" -+ -+static u32 read_div(struct drm_device *, int, u32, u32); -+static u32 read_pll(struct drm_device *, u32); -+ -+static u32 -+read_vco(struct drm_device *dev, u32 dsrc) -+{ -+ u32 ssrc = nv_rd32(dev, dsrc); -+ if (!(ssrc & 0x00000100)) -+ return read_pll(dev, 0x00e800); -+ return read_pll(dev, 0x00e820); -+} -+ -+static u32 -+read_pll(struct drm_device *dev, u32 pll) -+{ -+ u32 ctrl = nv_rd32(dev, pll + 0); -+ u32 coef = nv_rd32(dev, pll + 4); -+ u32 P = (coef & 0x003f0000) >> 16; -+ u32 N = (coef & 0x0000ff00) >> 8; -+ u32 M = (coef & 0x000000ff) >> 0; -+ u32 sclk, doff; -+ -+ if (!(ctrl & 0x00000001)) -+ return 0; -+ -+ switch (pll & 0xfff000) { -+ case 0x00e000: -+ sclk = 27000; -+ P = 1; -+ break; -+ case 0x137000: -+ doff = (pll - 0x137000) / 0x20; -+ sclk = read_div(dev, doff, 0x137120, 0x137140); -+ break; -+ case 0x132000: -+ switch (pll) { -+ case 0x132000: -+ sclk = read_pll(dev, 0x132020); -+ break; -+ case 0x132020: -+ sclk = read_div(dev, 0, 0x137320, 0x137330); -+ break; -+ default: -+ return 0; -+ } -+ break; -+ default: -+ return 0; -+ } -+ -+ return sclk * N / M / P; -+} -+ -+static u32 -+read_div(struct drm_device *dev, int doff, u32 dsrc, u32 dctl) -+{ -+ u32 ssrc = nv_rd32(dev, dsrc + (doff * 4)); -+ u32 sctl = nv_rd32(dev, dctl + (doff * 4)); -+ -+ switch (ssrc & 0x00000003) { -+ case 0: -+ if ((ssrc & 0x00030000) != 0x00030000) -+ return 27000; -+ return 108000; -+ case 2: -+ return 100000; -+ case 3: -+ if (sctl & 0x80000000) { -+ u32 sclk = read_vco(dev, dsrc + (doff * 4)); -+ u32 sdiv = (sctl & 0x0000003f) + 2; -+ return (sclk * 2) / sdiv; -+ } -+ -+ return read_vco(dev, dsrc + (doff * 4)); -+ default: -+ return 0; -+ } -+} -+ -+static u32 -+read_mem(struct drm_device *dev) -+{ -+ u32 ssel = nv_rd32(dev, 0x1373f0); -+ if (ssel & 0x00000001) -+ return read_div(dev, 0, 0x137300, 0x137310); -+ return read_pll(dev, 0x132000); -+} -+ -+static u32 -+read_clk(struct drm_device *dev, int clk) -+{ -+ u32 sctl = nv_rd32(dev, 0x137250 + (clk * 4)); -+ u32 ssel = nv_rd32(dev, 0x137100); -+ u32 sclk, sdiv; -+ -+ if (ssel & (1 << clk)) { -+ if (clk < 7) -+ sclk = read_pll(dev, 0x137000 + (clk * 0x20)); -+ else -+ sclk = read_pll(dev, 0x1370e0); -+ sdiv = ((sctl & 0x00003f00) >> 8) + 2; -+ } else { -+ sclk = read_div(dev, clk, 0x137160, 0x1371d0); -+ sdiv = ((sctl & 0x0000003f) >> 0) + 2; -+ } -+ -+ if (sctl & 0x80000000) -+ return (sclk * 2) / sdiv; -+ return sclk; -+} -+ -+int -+nvc0_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) -+{ -+ perflvl->shader = read_clk(dev, 0x00); -+ perflvl->core = perflvl->shader / 2; -+ perflvl->memory = read_mem(dev); -+ perflvl->rop = read_clk(dev, 0x01); -+ perflvl->hub07 = read_clk(dev, 0x02); -+ perflvl->hub06 = read_clk(dev, 0x07); -+ perflvl->hub01 = read_clk(dev, 0x08); -+ perflvl->copy = read_clk(dev, 0x09); -+ perflvl->daemon = read_clk(dev, 0x0c); -+ perflvl->vdec = read_clk(dev, 0x0e); -+ return 0; -+} -diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c -index e45a24d..edbfe93 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_vram.c -+++ b/drivers/gpu/drm/nouveau/nvc0_vram.c -@@ -61,7 +61,7 @@ nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, - u32 type, struct nouveau_mem **pmem) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_mm *mm = dev_priv->engine.vram.mm; -+ struct nouveau_mm *mm = &dev_priv->engine.vram.mm; - struct nouveau_mm_node *r; - struct nouveau_mem *mem; - int ret; -@@ -106,12 +106,50 @@ nvc0_vram_init(struct drm_device *dev) - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; - const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ - const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ -- u32 length; -+ u32 parts = nv_rd32(dev, 0x121c74); -+ u32 bsize = nv_rd32(dev, 0x10f20c); -+ u32 offset, length; -+ bool uniform = true; -+ int ret, i; - -- dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; -- dev_priv->vram_size *= nv_rd32(dev, 0x121c74); -+ NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800)); -+ NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize); - -- length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; -+ /* read amount of vram attached to each memory controller */ -+ for (i = 0; i < parts; i++) { -+ u32 psize = nv_rd32(dev, 0x11020c + (i * 0x1000)); -+ if (psize != bsize) { -+ if (psize < bsize) -+ bsize = psize; -+ uniform = false; -+ } -+ -+ NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", i, psize); -+ -+ dev_priv->vram_size += (u64)psize << 20; -+ } -+ -+ /* if all controllers have the same amount attached, there's no holes */ -+ if (uniform) { -+ offset = rsvd_head; -+ length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; -+ return nouveau_mm_init(&vram->mm, offset, length, 1); -+ } - -- return nouveau_mm_init(&vram->mm, rsvd_head, length, 1); -+ /* otherwise, address lowest common amount from 0GiB */ -+ ret = nouveau_mm_init(&vram->mm, rsvd_head, (bsize << 8) * parts, 1); -+ if (ret) -+ return ret; -+ -+ /* and the rest starting from (8GiB + common_size) */ -+ offset = (0x0200000000ULL >> 12) + (bsize << 8); -+ length = (dev_priv->vram_size >> 12) - (bsize << 8) - rsvd_tail; -+ -+ ret = nouveau_mm_init(&vram->mm, offset, length, 0); -+ if (ret) { -+ nouveau_mm_fini(&vram->mm); -+ return ret; -+ } -+ -+ return 0; - } -diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c -new file mode 100644 -index 0000000..23d63b4 ---- /dev/null -+++ b/drivers/gpu/drm/nouveau/nvd0_display.c -@@ -0,0 +1,1473 @@ -+/* -+ * 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"), -+ * 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 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) OR AUTHOR(S) 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: Ben Skeggs -+ */ -+ -+#include -+ -+#include "drmP.h" -+#include "drm_crtc_helper.h" -+ -+#include "nouveau_drv.h" -+#include "nouveau_connector.h" -+#include "nouveau_encoder.h" -+#include "nouveau_crtc.h" -+#include "nouveau_dma.h" -+#include "nouveau_fb.h" -+#include "nv50_display.h" -+ -+struct nvd0_display { -+ struct nouveau_gpuobj *mem; -+ struct { -+ dma_addr_t handle; -+ u32 *ptr; -+ } evo[1]; -+ -+ struct tasklet_struct tasklet; -+ u32 modeset; -+}; -+ -+static struct nvd0_display * -+nvd0_display(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ return dev_priv->engine.display.priv; -+} -+ -+static inline int -+evo_icmd(struct drm_device *dev, int id, u32 mthd, u32 data) -+{ -+ int ret = 0; -+ nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000001); -+ nv_wr32(dev, 0x610704 + (id * 0x10), data); -+ nv_mask(dev, 0x610704 + (id * 0x10), 0x80000ffc, 0x80000000 | mthd); -+ if (!nv_wait(dev, 0x610704 + (id * 0x10), 0x80000000, 0x00000000)) -+ ret = -EBUSY; -+ nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000000); -+ return ret; -+} -+ -+static u32 * -+evo_wait(struct drm_device *dev, int id, int nr) -+{ -+ struct nvd0_display *disp = nvd0_display(dev); -+ u32 put = nv_rd32(dev, 0x640000 + (id * 0x1000)) / 4; -+ -+ if (put + nr >= (PAGE_SIZE / 4)) { -+ disp->evo[id].ptr[put] = 0x20000000; -+ -+ nv_wr32(dev, 0x640000 + (id * 0x1000), 0x00000000); -+ if (!nv_wait(dev, 0x640004 + (id * 0x1000), ~0, 0x00000000)) { -+ NV_ERROR(dev, "evo %d dma stalled\n", id); -+ return NULL; -+ } -+ -+ put = 0; -+ } -+ -+ return disp->evo[id].ptr + put; -+} -+ -+static void -+evo_kick(u32 *push, struct drm_device *dev, int id) -+{ -+ struct nvd0_display *disp = nvd0_display(dev); -+ nv_wr32(dev, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2); -+} -+ -+#define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m)) -+#define evo_data(p,d) *((p)++) = (d) -+ -+static struct drm_crtc * -+nvd0_display_crtc_get(struct drm_encoder *encoder) -+{ -+ return nouveau_encoder(encoder)->crtc; -+} -+ -+/****************************************************************************** -+ * CRTC -+ *****************************************************************************/ -+static int -+nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update) -+{ -+ struct drm_device *dev = nv_crtc->base.dev; -+ u32 *push, mode; -+ -+ mode = 0x00000000; -+ if (on) { -+ /* 0x11: 6bpc dynamic 2x2 -+ * 0x13: 8bpc dynamic 2x2 -+ * 0x19: 6bpc static 2x2 -+ * 0x1b: 8bpc static 2x2 -+ * 0x21: 6bpc temporal -+ * 0x23: 8bpc temporal -+ */ -+ mode = 0x00000011; -+ } -+ -+ push = evo_wait(dev, 0, 4); -+ if (push) { -+ evo_mthd(push, 0x0490 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, mode); -+ if (update) { -+ evo_mthd(push, 0x0080, 1); -+ evo_data(push, 0x00000000); -+ } -+ evo_kick(push, dev, 0); -+ } -+ -+ return 0; -+} -+ -+static int -+nvd0_crtc_set_scale(struct nouveau_crtc *nv_crtc, int type, bool update) -+{ -+ struct drm_display_mode *mode = &nv_crtc->base.mode; -+ struct drm_device *dev = nv_crtc->base.dev; -+ struct nouveau_connector *nv_connector; -+ u32 *push, outX, outY; -+ -+ outX = mode->hdisplay; -+ outY = mode->vdisplay; -+ -+ nv_connector = nouveau_crtc_connector_get(nv_crtc); -+ if (nv_connector && nv_connector->native_mode) { -+ struct drm_display_mode *native = nv_connector->native_mode; -+ u32 xratio = (native->hdisplay << 19) / mode->hdisplay; -+ u32 yratio = (native->vdisplay << 19) / mode->vdisplay; -+ -+ switch (type) { -+ case DRM_MODE_SCALE_ASPECT: -+ if (xratio > yratio) { -+ outX = (mode->hdisplay * yratio) >> 19; -+ outY = (mode->vdisplay * yratio) >> 19; -+ } else { -+ outX = (mode->hdisplay * xratio) >> 19; -+ outY = (mode->vdisplay * xratio) >> 19; -+ } -+ break; -+ case DRM_MODE_SCALE_FULLSCREEN: -+ outX = native->hdisplay; -+ outY = native->vdisplay; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ push = evo_wait(dev, 0, 16); -+ if (push) { -+ evo_mthd(push, 0x04c0 + (nv_crtc->index * 0x300), 3); -+ evo_data(push, (outY << 16) | outX); -+ evo_data(push, (outY << 16) | outX); -+ evo_data(push, (outY << 16) | outX); -+ evo_mthd(push, 0x0494 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, 0x00000000); -+ evo_mthd(push, 0x04b8 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, (mode->vdisplay << 16) | mode->hdisplay); -+ if (update) { -+ evo_mthd(push, 0x0080, 1); -+ evo_data(push, 0x00000000); -+ } -+ evo_kick(push, dev, 0); -+ } -+ -+ return 0; -+} -+ -+static int -+nvd0_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb, -+ int x, int y, bool update) -+{ -+ struct nouveau_framebuffer *nvfb = nouveau_framebuffer(fb); -+ u32 *push; -+ -+ push = evo_wait(fb->dev, 0, 16); -+ if (push) { -+ evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, nvfb->nvbo->bo.offset >> 8); -+ evo_mthd(push, 0x0468 + (nv_crtc->index * 0x300), 4); -+ evo_data(push, (fb->height << 16) | fb->width); -+ evo_data(push, nvfb->r_pitch); -+ evo_data(push, nvfb->r_format); -+ evo_data(push, nvfb->r_dma); -+ evo_mthd(push, 0x04b0 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, (y << 16) | x); -+ if (update) { -+ evo_mthd(push, 0x0080, 1); -+ evo_data(push, 0x00000000); -+ } -+ evo_kick(push, fb->dev, 0); -+ } -+ -+ nv_crtc->fb.tile_flags = nvfb->r_dma; -+ return 0; -+} -+ -+static void -+nvd0_crtc_cursor_show(struct nouveau_crtc *nv_crtc, bool show, bool update) -+{ -+ struct drm_device *dev = nv_crtc->base.dev; -+ u32 *push = evo_wait(dev, 0, 16); -+ if (push) { -+ if (show) { -+ evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2); -+ evo_data(push, 0x85000000); -+ evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8); -+ evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1); -+ evo_data(push, NvEvoVRAM); -+ } else { -+ evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, 0x05000000); -+ evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1); -+ evo_data(push, 0x00000000); -+ } -+ -+ if (update) { -+ evo_mthd(push, 0x0080, 1); -+ evo_data(push, 0x00000000); -+ } -+ -+ evo_kick(push, dev, 0); -+ } -+} -+ -+static void -+nvd0_crtc_dpms(struct drm_crtc *crtc, int mode) -+{ -+} -+ -+static void -+nvd0_crtc_prepare(struct drm_crtc *crtc) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ u32 *push; -+ -+ push = evo_wait(crtc->dev, 0, 2); -+ if (push) { -+ evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, 0x00000000); -+ evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, 0x03000000); -+ evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1); -+ evo_data(push, 0x00000000); -+ evo_kick(push, crtc->dev, 0); -+ } -+ -+ nvd0_crtc_cursor_show(nv_crtc, false, false); -+} -+ -+static void -+nvd0_crtc_commit(struct drm_crtc *crtc) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ u32 *push; -+ -+ push = evo_wait(crtc->dev, 0, 32); -+ if (push) { -+ evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, nv_crtc->fb.tile_flags); -+ evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4); -+ evo_data(push, 0x83000000); -+ evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8); -+ evo_data(push, 0x00000000); -+ evo_data(push, 0x00000000); -+ evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1); -+ evo_data(push, NvEvoVRAM); -+ evo_mthd(push, 0x0430 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, 0xffffff00); -+ evo_kick(push, crtc->dev, 0); -+ } -+ -+ nvd0_crtc_cursor_show(nv_crtc, nv_crtc->cursor.visible, true); -+} -+ -+static bool -+nvd0_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode) -+{ -+ return true; -+} -+ -+static int -+nvd0_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) -+{ -+ struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb); -+ int ret; -+ -+ ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM); -+ if (ret) -+ return ret; -+ -+ if (old_fb) { -+ nvfb = nouveau_framebuffer(old_fb); -+ nouveau_bo_unpin(nvfb->nvbo); -+ } -+ -+ return 0; -+} -+ -+static int -+nvd0_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode, -+ struct drm_display_mode *mode, int x, int y, -+ struct drm_framebuffer *old_fb) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ struct nouveau_connector *nv_connector; -+ u32 htotal = mode->htotal; -+ u32 vtotal = mode->vtotal; -+ u32 hsyncw = mode->hsync_end - mode->hsync_start - 1; -+ u32 vsyncw = mode->vsync_end - mode->vsync_start - 1; -+ u32 hfrntp = mode->hsync_start - mode->hdisplay; -+ u32 vfrntp = mode->vsync_start - mode->vdisplay; -+ u32 hbackp = mode->htotal - mode->hsync_end; -+ u32 vbackp = mode->vtotal - mode->vsync_end; -+ u32 hss2be = hsyncw + hbackp; -+ u32 vss2be = vsyncw + vbackp; -+ u32 hss2de = htotal - hfrntp; -+ u32 vss2de = vtotal - vfrntp; -+ u32 syncs, *push; -+ int ret; -+ -+ syncs = 0x00000001; -+ if (mode->flags & DRM_MODE_FLAG_NHSYNC) -+ syncs |= 0x00000008; -+ if (mode->flags & DRM_MODE_FLAG_NVSYNC) -+ syncs |= 0x00000010; -+ -+ ret = nvd0_crtc_swap_fbs(crtc, old_fb); -+ if (ret) -+ return ret; -+ -+ push = evo_wait(crtc->dev, 0, 64); -+ if (push) { -+ evo_mthd(push, 0x0410 + (nv_crtc->index * 0x300), 5); -+ evo_data(push, 0x00000000); -+ evo_data(push, (vtotal << 16) | htotal); -+ evo_data(push, (vsyncw << 16) | hsyncw); -+ evo_data(push, (vss2be << 16) | hss2be); -+ evo_data(push, (vss2de << 16) | hss2de); -+ evo_mthd(push, 0x042c + (nv_crtc->index * 0x300), 1); -+ evo_data(push, 0x00000000); /* ??? */ -+ evo_mthd(push, 0x0450 + (nv_crtc->index * 0x300), 3); -+ evo_data(push, mode->clock * 1000); -+ evo_data(push, 0x00200000); /* ??? */ -+ evo_data(push, mode->clock * 1000); -+ evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, syncs); -+ evo_kick(push, crtc->dev, 0); -+ } -+ -+ nv_connector = nouveau_crtc_connector_get(nv_crtc); -+ nvd0_crtc_set_dither(nv_crtc, nv_connector->use_dithering, false); -+ nvd0_crtc_set_scale(nv_crtc, nv_connector->scaling_mode, false); -+ nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, false); -+ return 0; -+} -+ -+static int -+nvd0_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, -+ struct drm_framebuffer *old_fb) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ int ret; -+ -+ if (!crtc->fb) { -+ NV_DEBUG_KMS(crtc->dev, "No FB bound\n"); -+ return 0; -+ } -+ -+ ret = nvd0_crtc_swap_fbs(crtc, old_fb); -+ if (ret) -+ return ret; -+ -+ nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, true); -+ return 0; -+} -+ -+static int -+nvd0_crtc_mode_set_base_atomic(struct drm_crtc *crtc, -+ struct drm_framebuffer *fb, int x, int y, -+ enum mode_set_atomic state) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ nvd0_crtc_set_image(nv_crtc, fb, x, y, true); -+ return 0; -+} -+ -+static void -+nvd0_crtc_lut_load(struct drm_crtc *crtc) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo); -+ int i; -+ -+ for (i = 0; i < 256; i++) { -+ writew(0x6000 + (nv_crtc->lut.r[i] >> 2), lut + (i * 0x20) + 0); -+ writew(0x6000 + (nv_crtc->lut.g[i] >> 2), lut + (i * 0x20) + 2); -+ writew(0x6000 + (nv_crtc->lut.b[i] >> 2), lut + (i * 0x20) + 4); -+ } -+} -+ -+static int -+nvd0_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, -+ uint32_t handle, uint32_t width, uint32_t height) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ struct drm_device *dev = crtc->dev; -+ struct drm_gem_object *gem; -+ struct nouveau_bo *nvbo; -+ bool visible = (handle != 0); -+ int i, ret = 0; -+ -+ if (visible) { -+ if (width != 64 || height != 64) -+ return -EINVAL; -+ -+ gem = drm_gem_object_lookup(dev, file_priv, handle); -+ if (unlikely(!gem)) -+ return -ENOENT; -+ nvbo = nouveau_gem_object(gem); -+ -+ ret = nouveau_bo_map(nvbo); -+ if (ret == 0) { -+ for (i = 0; i < 64 * 64; i++) { -+ u32 v = nouveau_bo_rd32(nvbo, i); -+ nouveau_bo_wr32(nv_crtc->cursor.nvbo, i, v); -+ } -+ nouveau_bo_unmap(nvbo); -+ } -+ -+ drm_gem_object_unreference_unlocked(gem); -+ } -+ -+ if (visible != nv_crtc->cursor.visible) { -+ nvd0_crtc_cursor_show(nv_crtc, visible, true); -+ nv_crtc->cursor.visible = visible; -+ } -+ -+ return ret; -+} -+ -+static int -+nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ const u32 data = (y << 16) | x; -+ -+ nv_wr32(crtc->dev, 0x64d084 + (nv_crtc->index * 0x1000), data); -+ nv_wr32(crtc->dev, 0x64d080 + (nv_crtc->index * 0x1000), 0x00000000); -+ return 0; -+} -+ -+static void -+nvd0_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, -+ uint32_t start, uint32_t size) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ u32 end = max(start + size, (u32)256); -+ u32 i; -+ -+ for (i = start; i < end; i++) { -+ nv_crtc->lut.r[i] = r[i]; -+ nv_crtc->lut.g[i] = g[i]; -+ nv_crtc->lut.b[i] = b[i]; -+ } -+ -+ nvd0_crtc_lut_load(crtc); -+} -+ -+static void -+nvd0_crtc_destroy(struct drm_crtc *crtc) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ nouveau_bo_unmap(nv_crtc->cursor.nvbo); -+ nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); -+ nouveau_bo_unmap(nv_crtc->lut.nvbo); -+ nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); -+ drm_crtc_cleanup(crtc); -+ kfree(crtc); -+} -+ -+static const struct drm_crtc_helper_funcs nvd0_crtc_hfunc = { -+ .dpms = nvd0_crtc_dpms, -+ .prepare = nvd0_crtc_prepare, -+ .commit = nvd0_crtc_commit, -+ .mode_fixup = nvd0_crtc_mode_fixup, -+ .mode_set = nvd0_crtc_mode_set, -+ .mode_set_base = nvd0_crtc_mode_set_base, -+ .mode_set_base_atomic = nvd0_crtc_mode_set_base_atomic, -+ .load_lut = nvd0_crtc_lut_load, -+}; -+ -+static const struct drm_crtc_funcs nvd0_crtc_func = { -+ .cursor_set = nvd0_crtc_cursor_set, -+ .cursor_move = nvd0_crtc_cursor_move, -+ .gamma_set = nvd0_crtc_gamma_set, -+ .set_config = drm_crtc_helper_set_config, -+ .destroy = nvd0_crtc_destroy, -+}; -+ -+static void -+nvd0_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y) -+{ -+} -+ -+static void -+nvd0_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset) -+{ -+} -+ -+static int -+nvd0_crtc_create(struct drm_device *dev, int index) -+{ -+ struct nouveau_crtc *nv_crtc; -+ struct drm_crtc *crtc; -+ int ret, i; -+ -+ nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL); -+ if (!nv_crtc) -+ return -ENOMEM; -+ -+ nv_crtc->index = index; -+ nv_crtc->set_dither = nvd0_crtc_set_dither; -+ nv_crtc->set_scale = nvd0_crtc_set_scale; -+ nv_crtc->cursor.set_offset = nvd0_cursor_set_offset; -+ nv_crtc->cursor.set_pos = nvd0_cursor_set_pos; -+ for (i = 0; i < 256; i++) { -+ nv_crtc->lut.r[i] = i << 8; -+ nv_crtc->lut.g[i] = i << 8; -+ nv_crtc->lut.b[i] = i << 8; -+ } -+ -+ crtc = &nv_crtc->base; -+ drm_crtc_init(dev, crtc, &nvd0_crtc_func); -+ drm_crtc_helper_add(crtc, &nvd0_crtc_hfunc); -+ drm_mode_crtc_set_gamma_size(crtc, 256); -+ -+ ret = nouveau_bo_new(dev, 64 * 64 * 4, 0x100, TTM_PL_FLAG_VRAM, -+ 0, 0x0000, &nv_crtc->cursor.nvbo); -+ if (!ret) { -+ ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); -+ if (!ret) -+ ret = nouveau_bo_map(nv_crtc->cursor.nvbo); -+ if (ret) -+ nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); -+ } -+ -+ if (ret) -+ goto out; -+ -+ ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM, -+ 0, 0x0000, &nv_crtc->lut.nvbo); -+ if (!ret) { -+ ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); -+ if (!ret) -+ ret = nouveau_bo_map(nv_crtc->lut.nvbo); -+ if (ret) -+ nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); -+ } -+ -+ if (ret) -+ goto out; -+ -+ nvd0_crtc_lut_load(crtc); -+ -+out: -+ if (ret) -+ nvd0_crtc_destroy(crtc); -+ return ret; -+} -+ -+/****************************************************************************** -+ * DAC -+ *****************************************************************************/ -+static void -+nvd0_dac_dpms(struct drm_encoder *encoder, int mode) -+{ -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct drm_device *dev = encoder->dev; -+ int or = nv_encoder->or; -+ u32 dpms_ctrl; -+ -+ dpms_ctrl = 0x80000000; -+ if (mode == DRM_MODE_DPMS_STANDBY || mode == DRM_MODE_DPMS_OFF) -+ dpms_ctrl |= 0x00000001; -+ if (mode == DRM_MODE_DPMS_SUSPEND || mode == DRM_MODE_DPMS_OFF) -+ dpms_ctrl |= 0x00000004; -+ -+ nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000); -+ nv_mask(dev, 0x61a004 + (or * 0x0800), 0xc000007f, dpms_ctrl); -+ nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000); -+} -+ -+static bool -+nvd0_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode) -+{ -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct nouveau_connector *nv_connector; -+ -+ nv_connector = nouveau_encoder_connector_get(nv_encoder); -+ if (nv_connector && nv_connector->native_mode) { -+ if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) { -+ int id = adjusted_mode->base.id; -+ *adjusted_mode = *nv_connector->native_mode; -+ adjusted_mode->base.id = id; -+ } -+ } -+ -+ return true; -+} -+ -+static void -+nvd0_dac_prepare(struct drm_encoder *encoder) -+{ -+} -+ -+static void -+nvd0_dac_commit(struct drm_encoder *encoder) -+{ -+} -+ -+static void -+nvd0_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode) -+{ -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); -+ u32 *push; -+ -+ nvd0_dac_dpms(encoder, DRM_MODE_DPMS_ON); -+ -+ push = evo_wait(encoder->dev, 0, 4); -+ if (push) { -+ evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 2); -+ evo_data(push, 1 << nv_crtc->index); -+ evo_data(push, 0x00ff); -+ evo_kick(push, encoder->dev, 0); -+ } -+ -+ nv_encoder->crtc = encoder->crtc; -+} -+ -+static void -+nvd0_dac_disconnect(struct drm_encoder *encoder) -+{ -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct drm_device *dev = encoder->dev; -+ u32 *push; -+ -+ if (nv_encoder->crtc) { -+ nvd0_crtc_prepare(nv_encoder->crtc); -+ -+ push = evo_wait(dev, 0, 4); -+ if (push) { -+ evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 1); -+ evo_data(push, 0x00000000); -+ evo_mthd(push, 0x0080, 1); -+ evo_data(push, 0x00000000); -+ evo_kick(push, dev, 0); -+ } -+ -+ nv_encoder->crtc = NULL; -+ } -+} -+ -+static enum drm_connector_status -+nvd0_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) -+{ -+ enum drm_connector_status status = connector_status_disconnected; -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct drm_device *dev = encoder->dev; -+ int or = nv_encoder->or; -+ u32 load; -+ -+ nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00100000); -+ udelay(9500); -+ nv_wr32(dev, 0x61a00c + (or * 0x800), 0x80000000); -+ -+ load = nv_rd32(dev, 0x61a00c + (or * 0x800)); -+ if ((load & 0x38000000) == 0x38000000) -+ status = connector_status_connected; -+ -+ nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00000000); -+ return status; -+} -+ -+static void -+nvd0_dac_destroy(struct drm_encoder *encoder) -+{ -+ drm_encoder_cleanup(encoder); -+ kfree(encoder); -+} -+ -+static const struct drm_encoder_helper_funcs nvd0_dac_hfunc = { -+ .dpms = nvd0_dac_dpms, -+ .mode_fixup = nvd0_dac_mode_fixup, -+ .prepare = nvd0_dac_prepare, -+ .commit = nvd0_dac_commit, -+ .mode_set = nvd0_dac_mode_set, -+ .disable = nvd0_dac_disconnect, -+ .get_crtc = nvd0_display_crtc_get, -+ .detect = nvd0_dac_detect -+}; -+ -+static const struct drm_encoder_funcs nvd0_dac_func = { -+ .destroy = nvd0_dac_destroy, -+}; -+ -+static int -+nvd0_dac_create(struct drm_connector *connector, struct dcb_entry *dcbe) -+{ -+ struct drm_device *dev = connector->dev; -+ struct nouveau_encoder *nv_encoder; -+ struct drm_encoder *encoder; -+ -+ nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); -+ if (!nv_encoder) -+ return -ENOMEM; -+ nv_encoder->dcb = dcbe; -+ nv_encoder->or = ffs(dcbe->or) - 1; -+ -+ encoder = to_drm_encoder(nv_encoder); -+ encoder->possible_crtcs = dcbe->heads; -+ encoder->possible_clones = 0; -+ drm_encoder_init(dev, encoder, &nvd0_dac_func, DRM_MODE_ENCODER_DAC); -+ drm_encoder_helper_add(encoder, &nvd0_dac_hfunc); -+ -+ drm_mode_connector_attach_encoder(connector, encoder); -+ return 0; -+} -+ -+/****************************************************************************** -+ * SOR -+ *****************************************************************************/ -+static void -+nvd0_sor_dpms(struct drm_encoder *encoder, int mode) -+{ -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct drm_device *dev = encoder->dev; -+ struct drm_encoder *partner; -+ int or = nv_encoder->or; -+ u32 dpms_ctrl; -+ -+ nv_encoder->last_dpms = mode; -+ -+ list_for_each_entry(partner, &dev->mode_config.encoder_list, head) { -+ struct nouveau_encoder *nv_partner = nouveau_encoder(partner); -+ -+ if (partner->encoder_type != DRM_MODE_ENCODER_TMDS) -+ continue; -+ -+ if (nv_partner != nv_encoder && -+ nv_partner->dcb->or == nv_encoder->or) { -+ if (nv_partner->last_dpms == DRM_MODE_DPMS_ON) -+ return; -+ break; -+ } -+ } -+ -+ dpms_ctrl = (mode == DRM_MODE_DPMS_ON); -+ dpms_ctrl |= 0x80000000; -+ -+ nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); -+ nv_mask(dev, 0x61c004 + (or * 0x0800), 0x80000001, dpms_ctrl); -+ nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); -+ nv_wait(dev, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000); -+} -+ -+static bool -+nvd0_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode) -+{ -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct nouveau_connector *nv_connector; -+ -+ nv_connector = nouveau_encoder_connector_get(nv_encoder); -+ if (nv_connector && nv_connector->native_mode) { -+ if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) { -+ int id = adjusted_mode->base.id; -+ *adjusted_mode = *nv_connector->native_mode; -+ adjusted_mode->base.id = id; -+ } -+ } -+ -+ return true; -+} -+ -+static void -+nvd0_sor_prepare(struct drm_encoder *encoder) -+{ -+} -+ -+static void -+nvd0_sor_commit(struct drm_encoder *encoder) -+{ -+} -+ -+static void -+nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, -+ struct drm_display_mode *mode) -+{ -+ struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); -+ struct nouveau_connector *nv_connector; -+ struct nvbios *bios = &dev_priv->vbios; -+ u32 mode_ctrl = (1 << nv_crtc->index); -+ u32 *push, or_config; -+ -+ nv_connector = nouveau_encoder_connector_get(nv_encoder); -+ switch (nv_encoder->dcb->type) { -+ case OUTPUT_TMDS: -+ if (nv_encoder->dcb->sorconf.link & 1) { -+ if (mode->clock < 165000) -+ mode_ctrl |= 0x00000100; -+ else -+ mode_ctrl |= 0x00000500; -+ } else { -+ mode_ctrl |= 0x00000200; -+ } -+ -+ or_config = (mode_ctrl & 0x00000f00) >> 8; -+ if (mode->clock >= 165000) -+ or_config |= 0x0100; -+ break; -+ case OUTPUT_LVDS: -+ or_config = (mode_ctrl & 0x00000f00) >> 8; -+ if (bios->fp_no_ddc) { -+ if (bios->fp.dual_link) -+ or_config |= 0x0100; -+ if (bios->fp.if_is_24bit) -+ or_config |= 0x0200; -+ } else { -+ if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) { -+ if (((u8 *)nv_connector->edid)[121] == 2) -+ or_config |= 0x0100; -+ } else -+ if (mode->clock >= bios->fp.duallink_transition_clk) { -+ or_config |= 0x0100; -+ } -+ -+ if (or_config & 0x0100) { -+ if (bios->fp.strapless_is_24bit & 2) -+ or_config |= 0x0200; -+ } else { -+ if (bios->fp.strapless_is_24bit & 1) -+ or_config |= 0x0200; -+ } -+ -+ if (nv_connector->base.display_info.bpc == 8) -+ or_config |= 0x0200; -+ -+ } -+ break; -+ default: -+ BUG_ON(1); -+ break; -+ } -+ -+ nvd0_sor_dpms(encoder, DRM_MODE_DPMS_ON); -+ -+ push = evo_wait(encoder->dev, 0, 4); -+ if (push) { -+ evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 2); -+ evo_data(push, mode_ctrl); -+ evo_data(push, or_config); -+ evo_kick(push, encoder->dev, 0); -+ } -+ -+ nv_encoder->crtc = encoder->crtc; -+} -+ -+static void -+nvd0_sor_disconnect(struct drm_encoder *encoder) -+{ -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct drm_device *dev = encoder->dev; -+ u32 *push; -+ -+ if (nv_encoder->crtc) { -+ nvd0_crtc_prepare(nv_encoder->crtc); -+ -+ push = evo_wait(dev, 0, 4); -+ if (push) { -+ evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1); -+ evo_data(push, 0x00000000); -+ evo_mthd(push, 0x0080, 1); -+ evo_data(push, 0x00000000); -+ evo_kick(push, dev, 0); -+ } -+ -+ nv_encoder->crtc = NULL; -+ nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; -+ } -+} -+ -+static void -+nvd0_sor_destroy(struct drm_encoder *encoder) -+{ -+ drm_encoder_cleanup(encoder); -+ kfree(encoder); -+} -+ -+static const struct drm_encoder_helper_funcs nvd0_sor_hfunc = { -+ .dpms = nvd0_sor_dpms, -+ .mode_fixup = nvd0_sor_mode_fixup, -+ .prepare = nvd0_sor_prepare, -+ .commit = nvd0_sor_commit, -+ .mode_set = nvd0_sor_mode_set, -+ .disable = nvd0_sor_disconnect, -+ .get_crtc = nvd0_display_crtc_get, -+}; -+ -+static const struct drm_encoder_funcs nvd0_sor_func = { -+ .destroy = nvd0_sor_destroy, -+}; -+ -+static int -+nvd0_sor_create(struct drm_connector *connector, struct dcb_entry *dcbe) -+{ -+ struct drm_device *dev = connector->dev; -+ struct nouveau_encoder *nv_encoder; -+ struct drm_encoder *encoder; -+ -+ nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); -+ if (!nv_encoder) -+ return -ENOMEM; -+ nv_encoder->dcb = dcbe; -+ nv_encoder->or = ffs(dcbe->or) - 1; -+ nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; -+ -+ encoder = to_drm_encoder(nv_encoder); -+ encoder->possible_crtcs = dcbe->heads; -+ encoder->possible_clones = 0; -+ drm_encoder_init(dev, encoder, &nvd0_sor_func, DRM_MODE_ENCODER_TMDS); -+ drm_encoder_helper_add(encoder, &nvd0_sor_hfunc); -+ -+ drm_mode_connector_attach_encoder(connector, encoder); -+ return 0; -+} -+ -+/****************************************************************************** -+ * IRQ -+ *****************************************************************************/ -+static struct dcb_entry * -+lookup_dcb(struct drm_device *dev, int id, u32 mc) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ int type, or, i; -+ -+ if (id < 4) { -+ type = OUTPUT_ANALOG; -+ or = id; -+ } else { -+ switch (mc & 0x00000f00) { -+ case 0x00000000: type = OUTPUT_LVDS; break; -+ case 0x00000100: type = OUTPUT_TMDS; break; -+ case 0x00000200: type = OUTPUT_TMDS; break; -+ case 0x00000500: type = OUTPUT_TMDS; break; -+ default: -+ NV_ERROR(dev, "PDISP: unknown SOR mc 0x%08x\n", mc); -+ return NULL; -+ } -+ -+ or = id - 4; -+ } -+ -+ for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { -+ struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i]; -+ if (dcb->type == type && (dcb->or & (1 << or))) -+ return dcb; -+ } -+ -+ NV_ERROR(dev, "PDISP: DCB for %d/0x%08x not found\n", id, mc); -+ return NULL; -+} -+ -+static void -+nvd0_display_unk1_handler(struct drm_device *dev, u32 crtc, u32 mask) -+{ -+ struct dcb_entry *dcb; -+ int i; -+ -+ for (i = 0; mask && i < 8; i++) { -+ u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20)); -+ if (!(mcc & (1 << crtc))) -+ continue; -+ -+ dcb = lookup_dcb(dev, i, mcc); -+ if (!dcb) -+ continue; -+ -+ nouveau_bios_run_display_table(dev, 0x0000, -1, dcb, crtc); -+ } -+ -+ nv_wr32(dev, 0x6101d4, 0x00000000); -+ nv_wr32(dev, 0x6109d4, 0x00000000); -+ nv_wr32(dev, 0x6101d0, 0x80000000); -+} -+ -+static void -+nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) -+{ -+ struct dcb_entry *dcb; -+ u32 or, tmp, pclk; -+ int i; -+ -+ for (i = 0; mask && i < 8; i++) { -+ u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20)); -+ if (!(mcc & (1 << crtc))) -+ continue; -+ -+ dcb = lookup_dcb(dev, i, mcc); -+ if (!dcb) -+ continue; -+ -+ nouveau_bios_run_display_table(dev, 0x0000, -2, dcb, crtc); -+ } -+ -+ pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000; -+ if (mask & 0x00010000) { -+ nv50_crtc_set_clock(dev, crtc, pclk); -+ } -+ -+ for (i = 0; mask && i < 8; i++) { -+ u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20)); -+ u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20)); -+ if (!(mcp & (1 << crtc))) -+ continue; -+ -+ dcb = lookup_dcb(dev, i, mcp); -+ if (!dcb) -+ continue; -+ or = ffs(dcb->or) - 1; -+ -+ nouveau_bios_run_display_table(dev, cfg, pclk, dcb, crtc); -+ -+ nv_wr32(dev, 0x612200 + (crtc * 0x800), 0x00000000); -+ switch (dcb->type) { -+ case OUTPUT_ANALOG: -+ nv_wr32(dev, 0x612280 + (or * 0x800), 0x00000000); -+ break; -+ case OUTPUT_TMDS: -+ case OUTPUT_LVDS: -+ if (cfg & 0x00000100) -+ tmp = 0x00000101; -+ else -+ tmp = 0x00000000; -+ -+ nv_mask(dev, 0x612300 + (or * 0x800), 0x00000707, tmp); -+ break; -+ default: -+ break; -+ } -+ -+ break; -+ } -+ -+ nv_wr32(dev, 0x6101d4, 0x00000000); -+ nv_wr32(dev, 0x6109d4, 0x00000000); -+ nv_wr32(dev, 0x6101d0, 0x80000000); -+} -+ -+static void -+nvd0_display_unk4_handler(struct drm_device *dev, u32 crtc, u32 mask) -+{ -+ struct dcb_entry *dcb; -+ int pclk, i; -+ -+ pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000; -+ -+ for (i = 0; mask && i < 8; i++) { -+ u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20)); -+ u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20)); -+ if (!(mcp & (1 << crtc))) -+ continue; -+ -+ dcb = lookup_dcb(dev, i, mcp); -+ if (!dcb) -+ continue; -+ -+ nouveau_bios_run_display_table(dev, cfg, -pclk, dcb, crtc); -+ } -+ -+ nv_wr32(dev, 0x6101d4, 0x00000000); -+ nv_wr32(dev, 0x6109d4, 0x00000000); -+ nv_wr32(dev, 0x6101d0, 0x80000000); -+} -+ -+static void -+nvd0_display_bh(unsigned long data) -+{ -+ struct drm_device *dev = (struct drm_device *)data; -+ struct nvd0_display *disp = nvd0_display(dev); -+ u32 mask, crtc; -+ int i; -+ -+ if (drm_debug & (DRM_UT_DRIVER | DRM_UT_KMS)) { -+ NV_INFO(dev, "PDISP: modeset req %d\n", disp->modeset); -+ NV_INFO(dev, " STAT: 0x%08x 0x%08x 0x%08x\n", -+ nv_rd32(dev, 0x6101d0), -+ nv_rd32(dev, 0x6101d4), nv_rd32(dev, 0x6109d4)); -+ for (i = 0; i < 8; i++) { -+ NV_INFO(dev, " %s%d: 0x%08x 0x%08x\n", -+ i < 4 ? "DAC" : "SOR", i, -+ nv_rd32(dev, 0x640180 + (i * 0x20)), -+ nv_rd32(dev, 0x660180 + (i * 0x20))); -+ } -+ } -+ -+ mask = nv_rd32(dev, 0x6101d4); -+ crtc = 0; -+ if (!mask) { -+ mask = nv_rd32(dev, 0x6109d4); -+ crtc = 1; -+ } -+ -+ if (disp->modeset & 0x00000001) -+ nvd0_display_unk1_handler(dev, crtc, mask); -+ if (disp->modeset & 0x00000002) -+ nvd0_display_unk2_handler(dev, crtc, mask); -+ if (disp->modeset & 0x00000004) -+ nvd0_display_unk4_handler(dev, crtc, mask); -+} -+ -+static void -+nvd0_display_intr(struct drm_device *dev) -+{ -+ struct nvd0_display *disp = nvd0_display(dev); -+ u32 intr = nv_rd32(dev, 0x610088); -+ -+ if (intr & 0x00000002) { -+ u32 stat = nv_rd32(dev, 0x61009c); -+ int chid = ffs(stat) - 1; -+ if (chid >= 0) { -+ u32 mthd = nv_rd32(dev, 0x6101f0 + (chid * 12)); -+ u32 data = nv_rd32(dev, 0x6101f4 + (chid * 12)); -+ u32 unkn = nv_rd32(dev, 0x6101f8 + (chid * 12)); -+ -+ NV_INFO(dev, "EvoCh: chid %d mthd 0x%04x data 0x%08x " -+ "0x%08x 0x%08x\n", -+ chid, (mthd & 0x0000ffc), data, mthd, unkn); -+ nv_wr32(dev, 0x61009c, (1 << chid)); -+ nv_wr32(dev, 0x6101f0 + (chid * 12), 0x90000000); -+ } -+ -+ intr &= ~0x00000002; -+ } -+ -+ if (intr & 0x00100000) { -+ u32 stat = nv_rd32(dev, 0x6100ac); -+ -+ if (stat & 0x00000007) { -+ disp->modeset = stat; -+ tasklet_schedule(&disp->tasklet); -+ -+ nv_wr32(dev, 0x6100ac, (stat & 0x00000007)); -+ stat &= ~0x00000007; -+ } -+ -+ if (stat) { -+ NV_INFO(dev, "PDISP: unknown intr24 0x%08x\n", stat); -+ nv_wr32(dev, 0x6100ac, stat); -+ } -+ -+ intr &= ~0x00100000; -+ } -+ -+ if (intr & 0x01000000) { -+ u32 stat = nv_rd32(dev, 0x6100bc); -+ nv_wr32(dev, 0x6100bc, stat); -+ intr &= ~0x01000000; -+ } -+ -+ if (intr & 0x02000000) { -+ u32 stat = nv_rd32(dev, 0x6108bc); -+ nv_wr32(dev, 0x6108bc, stat); -+ intr &= ~0x02000000; -+ } -+ -+ if (intr) -+ NV_INFO(dev, "PDISP: unknown intr 0x%08x\n", intr); -+} -+ -+/****************************************************************************** -+ * Init -+ *****************************************************************************/ -+static void -+nvd0_display_fini(struct drm_device *dev) -+{ -+ int i; -+ -+ /* fini cursors */ -+ for (i = 14; i >= 13; i--) { -+ if (!(nv_rd32(dev, 0x610490 + (i * 0x10)) & 0x00000001)) -+ continue; -+ -+ nv_mask(dev, 0x610490 + (i * 0x10), 0x00000001, 0x00000000); -+ nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00000000); -+ nv_mask(dev, 0x610090, 1 << i, 0x00000000); -+ nv_mask(dev, 0x6100a0, 1 << i, 0x00000000); -+ } -+ -+ /* fini master */ -+ if (nv_rd32(dev, 0x610490) & 0x00000010) { -+ nv_mask(dev, 0x610490, 0x00000010, 0x00000000); -+ nv_mask(dev, 0x610490, 0x00000003, 0x00000000); -+ nv_wait(dev, 0x610490, 0x80000000, 0x00000000); -+ nv_mask(dev, 0x610090, 0x00000001, 0x00000000); -+ nv_mask(dev, 0x6100a0, 0x00000001, 0x00000000); -+ } -+} -+ -+int -+nvd0_display_init(struct drm_device *dev) -+{ -+ struct nvd0_display *disp = nvd0_display(dev); -+ u32 *push; -+ int i; -+ -+ if (nv_rd32(dev, 0x6100ac) & 0x00000100) { -+ nv_wr32(dev, 0x6100ac, 0x00000100); -+ nv_mask(dev, 0x6194e8, 0x00000001, 0x00000000); -+ if (!nv_wait(dev, 0x6194e8, 0x00000002, 0x00000000)) { -+ NV_ERROR(dev, "PDISP: 0x6194e8 0x%08x\n", -+ nv_rd32(dev, 0x6194e8)); -+ return -EBUSY; -+ } -+ } -+ -+ /* nfi what these are exactly, i do know that SOR_MODE_CTRL won't -+ * work at all unless you do the SOR part below. -+ */ -+ for (i = 0; i < 3; i++) { -+ u32 dac = nv_rd32(dev, 0x61a000 + (i * 0x800)); -+ nv_wr32(dev, 0x6101c0 + (i * 0x800), dac); -+ } -+ -+ for (i = 0; i < 4; i++) { -+ u32 sor = nv_rd32(dev, 0x61c000 + (i * 0x800)); -+ nv_wr32(dev, 0x6301c4 + (i * 0x800), sor); -+ } -+ -+ for (i = 0; i < 2; i++) { -+ u32 crtc0 = nv_rd32(dev, 0x616104 + (i * 0x800)); -+ u32 crtc1 = nv_rd32(dev, 0x616108 + (i * 0x800)); -+ u32 crtc2 = nv_rd32(dev, 0x61610c + (i * 0x800)); -+ nv_wr32(dev, 0x6101b4 + (i * 0x800), crtc0); -+ nv_wr32(dev, 0x6101b8 + (i * 0x800), crtc1); -+ nv_wr32(dev, 0x6101bc + (i * 0x800), crtc2); -+ } -+ -+ /* point at our hash table / objects, enable interrupts */ -+ nv_wr32(dev, 0x610010, (disp->mem->vinst >> 8) | 9); -+ nv_mask(dev, 0x6100b0, 0x00000307, 0x00000307); -+ -+ /* init master */ -+ nv_wr32(dev, 0x610494, (disp->evo[0].handle >> 8) | 3); -+ nv_wr32(dev, 0x610498, 0x00010000); -+ nv_wr32(dev, 0x61049c, 0x00000001); -+ nv_mask(dev, 0x610490, 0x00000010, 0x00000010); -+ nv_wr32(dev, 0x640000, 0x00000000); -+ nv_wr32(dev, 0x610490, 0x01000013); -+ if (!nv_wait(dev, 0x610490, 0x80000000, 0x00000000)) { -+ NV_ERROR(dev, "PDISP: master 0x%08x\n", -+ nv_rd32(dev, 0x610490)); -+ return -EBUSY; -+ } -+ nv_mask(dev, 0x610090, 0x00000001, 0x00000001); -+ nv_mask(dev, 0x6100a0, 0x00000001, 0x00000001); -+ -+ /* init cursors */ -+ for (i = 13; i <= 14; i++) { -+ nv_wr32(dev, 0x610490 + (i * 0x10), 0x00000001); -+ if (!nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00010000)) { -+ NV_ERROR(dev, "PDISP: curs%d 0x%08x\n", i, -+ nv_rd32(dev, 0x610490 + (i * 0x10))); -+ return -EBUSY; -+ } -+ -+ nv_mask(dev, 0x610090, 1 << i, 1 << i); -+ nv_mask(dev, 0x6100a0, 1 << i, 1 << i); -+ } -+ -+ push = evo_wait(dev, 0, 32); -+ if (!push) -+ return -EBUSY; -+ evo_mthd(push, 0x0088, 1); -+ evo_data(push, NvEvoSync); -+ evo_mthd(push, 0x0084, 1); -+ evo_data(push, 0x00000000); -+ evo_mthd(push, 0x0084, 1); -+ evo_data(push, 0x80000000); -+ evo_mthd(push, 0x008c, 1); -+ evo_data(push, 0x00000000); -+ evo_kick(push, dev, 0); -+ -+ return 0; -+} -+ -+void -+nvd0_display_destroy(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nvd0_display *disp = nvd0_display(dev); -+ struct pci_dev *pdev = dev->pdev; -+ -+ nvd0_display_fini(dev); -+ -+ pci_free_consistent(pdev, PAGE_SIZE, disp->evo[0].ptr, disp->evo[0].handle); -+ nouveau_gpuobj_ref(NULL, &disp->mem); -+ nouveau_irq_unregister(dev, 26); -+ -+ dev_priv->engine.display.priv = NULL; -+ kfree(disp); -+} -+ -+int -+nvd0_display_create(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; -+ struct dcb_table *dcb = &dev_priv->vbios.dcb; -+ struct drm_connector *connector, *tmp; -+ struct pci_dev *pdev = dev->pdev; -+ struct nvd0_display *disp; -+ struct dcb_entry *dcbe; -+ int ret, i; -+ -+ disp = kzalloc(sizeof(*disp), GFP_KERNEL); -+ if (!disp) -+ return -ENOMEM; -+ dev_priv->engine.display.priv = disp; -+ -+ /* create crtc objects to represent the hw heads */ -+ for (i = 0; i < 2; i++) { -+ ret = nvd0_crtc_create(dev, i); -+ if (ret) -+ goto out; -+ } -+ -+ /* create encoder/connector objects based on VBIOS DCB table */ -+ for (i = 0, dcbe = &dcb->entry[0]; i < dcb->entries; i++, dcbe++) { -+ connector = nouveau_connector_create(dev, dcbe->connector); -+ if (IS_ERR(connector)) -+ continue; -+ -+ if (dcbe->location != DCB_LOC_ON_CHIP) { -+ NV_WARN(dev, "skipping off-chip encoder %d/%d\n", -+ dcbe->type, ffs(dcbe->or) - 1); -+ continue; -+ } -+ -+ switch (dcbe->type) { -+ case OUTPUT_TMDS: -+ case OUTPUT_LVDS: -+ nvd0_sor_create(connector, dcbe); -+ break; -+ case OUTPUT_ANALOG: -+ nvd0_dac_create(connector, dcbe); -+ break; -+ default: -+ NV_WARN(dev, "skipping unsupported encoder %d/%d\n", -+ dcbe->type, ffs(dcbe->or) - 1); -+ continue; -+ } -+ } -+ -+ /* cull any connectors we created that don't have an encoder */ -+ list_for_each_entry_safe(connector, tmp, &dev->mode_config.connector_list, head) { -+ if (connector->encoder_ids[0]) -+ continue; -+ -+ NV_WARN(dev, "%s has no encoders, removing\n", -+ drm_get_connector_name(connector)); -+ connector->funcs->destroy(connector); -+ } -+ -+ /* setup interrupt handling */ -+ tasklet_init(&disp->tasklet, nvd0_display_bh, (unsigned long)dev); -+ nouveau_irq_register(dev, 26, nvd0_display_intr); -+ -+ /* hash table and dma objects for the memory areas we care about */ -+ ret = nouveau_gpuobj_new(dev, NULL, 0x4000, 0x10000, -+ NVOBJ_FLAG_ZERO_ALLOC, &disp->mem); -+ if (ret) -+ goto out; -+ -+ nv_wo32(disp->mem, 0x1000, 0x00000049); -+ nv_wo32(disp->mem, 0x1004, (disp->mem->vinst + 0x2000) >> 8); -+ nv_wo32(disp->mem, 0x1008, (disp->mem->vinst + 0x2fff) >> 8); -+ nv_wo32(disp->mem, 0x100c, 0x00000000); -+ nv_wo32(disp->mem, 0x1010, 0x00000000); -+ nv_wo32(disp->mem, 0x1014, 0x00000000); -+ nv_wo32(disp->mem, 0x0000, NvEvoSync); -+ nv_wo32(disp->mem, 0x0004, (0x1000 << 9) | 0x00000001); -+ -+ nv_wo32(disp->mem, 0x1020, 0x00000049); -+ nv_wo32(disp->mem, 0x1024, 0x00000000); -+ nv_wo32(disp->mem, 0x1028, (dev_priv->vram_size - 1) >> 8); -+ nv_wo32(disp->mem, 0x102c, 0x00000000); -+ nv_wo32(disp->mem, 0x1030, 0x00000000); -+ nv_wo32(disp->mem, 0x1034, 0x00000000); -+ nv_wo32(disp->mem, 0x0008, NvEvoVRAM); -+ nv_wo32(disp->mem, 0x000c, (0x1020 << 9) | 0x00000001); -+ -+ nv_wo32(disp->mem, 0x1040, 0x00000009); -+ nv_wo32(disp->mem, 0x1044, 0x00000000); -+ nv_wo32(disp->mem, 0x1048, (dev_priv->vram_size - 1) >> 8); -+ nv_wo32(disp->mem, 0x104c, 0x00000000); -+ nv_wo32(disp->mem, 0x1050, 0x00000000); -+ nv_wo32(disp->mem, 0x1054, 0x00000000); -+ nv_wo32(disp->mem, 0x0010, NvEvoVRAM_LP); -+ nv_wo32(disp->mem, 0x0014, (0x1040 << 9) | 0x00000001); -+ -+ nv_wo32(disp->mem, 0x1060, 0x0fe00009); -+ nv_wo32(disp->mem, 0x1064, 0x00000000); -+ nv_wo32(disp->mem, 0x1068, (dev_priv->vram_size - 1) >> 8); -+ nv_wo32(disp->mem, 0x106c, 0x00000000); -+ nv_wo32(disp->mem, 0x1070, 0x00000000); -+ nv_wo32(disp->mem, 0x1074, 0x00000000); -+ nv_wo32(disp->mem, 0x0018, NvEvoFB32); -+ nv_wo32(disp->mem, 0x001c, (0x1060 << 9) | 0x00000001); -+ -+ pinstmem->flush(dev); -+ -+ /* push buffers for evo channels */ -+ disp->evo[0].ptr = -+ pci_alloc_consistent(pdev, PAGE_SIZE, &disp->evo[0].handle); -+ if (!disp->evo[0].ptr) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ ret = nvd0_display_init(dev); -+ if (ret) -+ goto out; -+ -+out: -+ if (ret) -+ nvd0_display_destroy(dev); -+ return ret; -+} diff --git a/elantech.patch b/elantech.patch deleted file mode 100644 index fa7c67fec..000000000 --- a/elantech.patch +++ /dev/null @@ -1,2180 +0,0 @@ -From 13ac768d9a8731c8b3bab7d6c86520f290272fe7 Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Fri, 9 Sep 2011 10:22:19 -0700 -Subject: Input: elantech - correct x, y value range for v2 hardware -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -x, y values are actually 12-bit long. Also update protocol document to -reflect the change. - -Signed-off-by: JJ Ding -Acked-by: Daniel Kurtz -Acked-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - Documentation/input/elantech.txt | 8 ++++---- - drivers/input/mouse/elantech.c | 8 ++++---- - 2 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt -index db798af..bce9941 100644 ---- a/Documentation/input/elantech.txt -+++ b/Documentation/input/elantech.txt -@@ -389,14 +389,14 @@ byte 0: - byte 1: - - bit 7 6 5 4 3 2 1 0 -- p7 p6 p5 p4 . x10 x9 x8 -+ p7 p6 p5 p4 x11 x10 x9 x8 - - byte 2: - - bit 7 6 5 4 3 2 1 0 - x7 x6 x5 x4 x3 x2 x1 x0 - -- x10..x0 = absolute x value (horizontal) -+ x11..x0 = absolute x value (horizontal) - - byte 3: - -@@ -420,7 +420,7 @@ byte 3: - byte 4: - - bit 7 6 5 4 3 2 1 0 -- p3 p1 p2 p0 . . y9 y8 -+ p3 p1 p2 p0 y11 y10 y9 y8 - - p7..p0 = pressure (not EF113) - -@@ -429,7 +429,7 @@ byte 5: - bit 7 6 5 4 3 2 1 0 - y7 y6 y5 y4 y3 y2 y1 y0 - -- y9..y0 = absolute y value (vertical) -+ y11..y0 = absolute y value (vertical) - - - 4.2.2 Two finger touch -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index 3250356..da161da 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -290,15 +290,15 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - /* pass through... */ - case 1: - /* -- * byte 1: . . . . . x10 x9 x8 -+ * byte 1: . . . . x11 x10 x9 x8 - * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 - */ -- x1 = ((packet[1] & 0x07) << 8) | packet[2]; -+ x1 = ((packet[1] & 0x0f) << 8) | packet[2]; - /* -- * byte 4: . . . . . . y9 y8 -+ * byte 4: . . . . y11 y10 y9 y8 - * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 - */ -- y1 = ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5]); -+ y1 = ETP_YMAX_V2 - (((packet[4] & 0x0f) << 8) | packet[5]); - - input_report_abs(dev, ABS_X, x1); - input_report_abs(dev, ABS_Y, y1); --- -1.7.6.4 - - -From c47c9334b4ebb6ecb565d9bf834df170fcd09484 Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Fri, 9 Sep 2011 10:22:58 -0700 -Subject: Input: elantech - get rid of ETP_2FT_* in elantech.h -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -For two finger touches the coordinate of each finger gets reported -separately but with reduced resolution. - -With this change, we now have the same range for ST and MT data and -scale MT data because it has lower resolution to match ST. - -Suggested-by: Dmitry Torokhov -Signed-off-by: JJ Ding -Acked-by: Daniel Kurtz -Acked-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.c | 28 +++++++++++++--------------- - drivers/input/mouse/elantech.h | 11 ----------- - 2 files changed, 13 insertions(+), 26 deletions(-) - -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index da161da..cd8e2e5 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -273,11 +273,11 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - struct elantech_data *etd = psmouse->private; - struct input_dev *dev = psmouse->dev; - unsigned char *packet = psmouse->packet; -- unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0, width = 0, pres = 0; -+ unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0; -+ unsigned int width = 0, pres = 0; - - /* byte 0: n1 n0 . . . . R L */ - fingers = (packet[0] & 0xc0) >> 6; -- input_report_key(dev, BTN_TOUCH, fingers != 0); - - switch (fingers) { - case 3: -@@ -300,9 +300,6 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - */ - y1 = ETP_YMAX_V2 - (((packet[4] & 0x0f) << 8) | packet[5]); - -- input_report_abs(dev, ABS_X, x1); -- input_report_abs(dev, ABS_Y, y1); -- - pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); - width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); - break; -@@ -314,22 +311,18 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - * byte 0: . . ay8 ax8 . . . . - * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 - */ -- x1 = ((packet[0] & 0x10) << 4) | packet[1]; -+ x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2; - /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ -- y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); -+ y1 = ETP_YMAX_V2 - -+ ((((packet[0] & 0x20) << 3) | packet[2]) << 2); - /* - * byte 3: . . by8 bx8 . . . . - * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 - */ -- x2 = ((packet[3] & 0x10) << 4) | packet[4]; -+ x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2; - /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ -- y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); -- /* -- * For compatibility with the X Synaptics driver scale up -- * one coordinate and report as ordinary mouse movent -- */ -- input_report_abs(dev, ABS_X, x1 << 2); -- input_report_abs(dev, ABS_Y, y1 << 2); -+ y2 = ETP_YMAX_V2 - -+ ((((packet[3] & 0x20) << 3) | packet[5]) << 2); - - /* Unknown so just report sensible values */ - pres = 127; -@@ -337,6 +330,11 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - break; - } - -+ input_report_key(dev, BTN_TOUCH, fingers != 0); -+ if (fingers != 0) { -+ input_report_abs(dev, ABS_X, x1); -+ input_report_abs(dev, ABS_Y, y1); -+ } - elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); - input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); - input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); -diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h -index fabb2b9..1c5894e 100644 ---- a/drivers/input/mouse/elantech.h -+++ b/drivers/input/mouse/elantech.h -@@ -82,17 +82,6 @@ - #define ETP_WMIN_V2 0 - #define ETP_WMAX_V2 15 - --/* -- * For two finger touches the coordinate of each finger gets reported -- * separately but with reduced resolution. -- */ --#define ETP_2FT_FUZZ 4 -- --#define ETP_2FT_XMIN ( 0 + ETP_2FT_FUZZ) --#define ETP_2FT_XMAX (288 - ETP_2FT_FUZZ) --#define ETP_2FT_YMIN ( 0 + ETP_2FT_FUZZ) --#define ETP_2FT_YMAX (192 - ETP_2FT_FUZZ) -- - struct elantech_data { - unsigned char reg_10; - unsigned char reg_11; --- -1.7.6.4 - - -From aa719e391c1769c93ec42a30daffa4ffa2a8503c Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Fri, 9 Sep 2011 10:26:16 -0700 -Subject: Input: elantech - use firmware provided x, y ranges -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -With newer hardware, the touchpad provides range info. -Let's use it. - -Signed-off-by: JJ Ding -Acked-by: Daniel Kurtz -Acked-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.c | 71 +++++++++++++++++++++++++++++++-------- - drivers/input/mouse/elantech.h | 3 +- - 2 files changed, 58 insertions(+), 16 deletions(-) - -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index cd8e2e5..296b6a6 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -223,7 +223,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) - input_report_abs(dev, ABS_X, - ((packet[1] & 0x0c) << 6) | packet[2]); - input_report_abs(dev, ABS_Y, -- ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3])); -+ etd->y_max - (((packet[1] & 0x03) << 8) | packet[3])); - } - - input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); -@@ -233,7 +233,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) - input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); - - if (etd->fw_version < 0x020000 && -- (etd->capabilities & ETP_CAP_HAS_ROCKER)) { -+ (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { - /* rocker up */ - input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); - /* rocker down */ -@@ -298,7 +298,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - * byte 4: . . . . y11 y10 y9 y8 - * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 - */ -- y1 = ETP_YMAX_V2 - (((packet[4] & 0x0f) << 8) | packet[5]); -+ y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); - - pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); - width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); -@@ -313,7 +313,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - */ - x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2; - /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ -- y1 = ETP_YMAX_V2 - -+ y1 = etd->y_max - - ((((packet[0] & 0x20) << 3) | packet[2]) << 2); - /* - * byte 3: . . by8 bx8 . . . . -@@ -321,7 +321,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - */ - x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2; - /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ -- y2 = ETP_YMAX_V2 - -+ y2 = etd->y_max - - ((((packet[3] & 0x20) << 3) | packet[5]) << 2); - - /* Unknown so just report sensible values */ -@@ -468,6 +468,41 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) - return rc; - } - -+static void elantech_set_range(struct psmouse *psmouse, -+ unsigned int *x_min, unsigned int *y_min, -+ unsigned int *x_max, unsigned int *y_max) -+{ -+ struct elantech_data *etd = psmouse->private; -+ int i; -+ -+ switch (etd->hw_version) { -+ case 1: -+ *x_min = ETP_XMIN_V1; -+ *y_min = ETP_YMIN_V1; -+ *x_max = ETP_XMAX_V1; -+ *y_max = ETP_YMAX_V1; -+ break; -+ -+ case 2: -+ if (etd->fw_version == 0x020800 || -+ etd->fw_version == 0x020b00 || -+ etd->fw_version == 0x020030) { -+ *x_min = ETP_XMIN_V2; -+ *y_min = ETP_YMIN_V2; -+ *x_max = ETP_XMAX_V2; -+ *y_max = ETP_YMAX_V2; -+ } else { -+ i = (etd->fw_version > 0x020800 && -+ etd->fw_version < 0x020900) ? 1 : 2; -+ *x_min = 0; -+ *y_min = 0; -+ *x_max = (etd->capabilities[1] - i) * 64; -+ *y_max = (etd->capabilities[2] - i) * 64; -+ } -+ break; -+ } -+} -+ - /* - * Set the appropriate event bits for the input subsystem - */ -@@ -475,6 +510,9 @@ static void elantech_set_input_params(struct psmouse *psmouse) - { - struct input_dev *dev = psmouse->dev; - struct elantech_data *etd = psmouse->private; -+ unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0; -+ -+ elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max); - - __set_bit(EV_KEY, dev->evbit); - __set_bit(EV_ABS, dev->evbit); -@@ -492,18 +530,18 @@ static void elantech_set_input_params(struct psmouse *psmouse) - case 1: - /* Rocker button */ - if (etd->fw_version < 0x020000 && -- (etd->capabilities & ETP_CAP_HAS_ROCKER)) { -+ (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { - __set_bit(BTN_FORWARD, dev->keybit); - __set_bit(BTN_BACK, dev->keybit); - } -- input_set_abs_params(dev, ABS_X, ETP_XMIN_V1, ETP_XMAX_V1, 0, 0); -- input_set_abs_params(dev, ABS_Y, ETP_YMIN_V1, ETP_YMAX_V1, 0, 0); -+ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); -+ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); - break; - - case 2: - __set_bit(BTN_TOOL_QUADTAP, dev->keybit); -- input_set_abs_params(dev, ABS_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); -- input_set_abs_params(dev, ABS_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); -+ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); -+ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); - if (etd->reports_pressure) { - input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, - ETP_PMAX_V2, 0, 0); -@@ -512,10 +550,12 @@ static void elantech_set_input_params(struct psmouse *psmouse) - } - __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); - input_mt_init_slots(dev, 2); -- input_set_abs_params(dev, ABS_MT_POSITION_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); -- input_set_abs_params(dev, ABS_MT_POSITION_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); -+ input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); -+ input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); - break; - } -+ -+ etd->y_max = y_max; - } - - struct elantech_attr_data { -@@ -769,13 +809,14 @@ int elantech_init(struct psmouse *psmouse) - pr_info("assuming hardware version %d, firmware version %d.%d.%d\n", - etd->hw_version, param[0], param[1], param[2]); - -- if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) { -+ if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, -+ etd->capabilities)) { - pr_err("failed to query capabilities.\n"); - goto init_fail; - } - pr_info("Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n", -- param[0], param[1], param[2]); -- etd->capabilities = param[0]; -+ etd->capabilities[0], etd->capabilities[1], -+ etd->capabilities[2]); - - /* - * This firmware suffers from misreporting coordinates when -diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h -index 1c5894e..b54ea27 100644 ---- a/drivers/input/mouse/elantech.h -+++ b/drivers/input/mouse/elantech.h -@@ -93,13 +93,14 @@ struct elantech_data { - unsigned char reg_25; - unsigned char reg_26; - unsigned char debug; -- unsigned char capabilities; -+ unsigned char capabilities[3]; - bool paritycheck; - bool jumpy_cursor; - bool reports_pressure; - unsigned char hw_version; - unsigned int fw_version; - unsigned int single_finger_reports; -+ unsigned int y_max; - unsigned char parity[256]; - }; - --- -1.7.6.4 - - -From 91f395e84dc83707b01c69e297894dbf992a566e Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Fri, 9 Sep 2011 10:27:42 -0700 -Subject: Input: elantech - remove ETP_EDGE_FUZZ_V2 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Don't try to be too clever and remove ETP_EDGE_FUZZ_V2. X, Y ranges -should be just the raw resolution of the device. Otherwise, they can -cause underflow on the Y axis. - -Suggested-by: Éric Piel -Signed-off-by: JJ Ding -Acked-by: Daniel Kurtz -Acked-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.h | 15 ++++++--------- - 1 files changed, 6 insertions(+), 9 deletions(-) - -diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h -index b54ea27..d9e6144 100644 ---- a/drivers/input/mouse/elantech.h -+++ b/drivers/input/mouse/elantech.h -@@ -66,16 +66,13 @@ - #define ETP_YMAX_V1 (384 - ETP_EDGE_FUZZ_V1) - - /* -- * It seems the resolution for hardware version 2 doubled. -- * Hence the X and Y ranges are doubled too. -- * The bezel around the pad also appears to be smaller -+ * The resolution for older v2 hardware doubled. -+ * (newer v2's firmware provides command so we can query) - */ --#define ETP_EDGE_FUZZ_V2 8 -- --#define ETP_XMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2) --#define ETP_XMAX_V2 (1152 - ETP_EDGE_FUZZ_V2) --#define ETP_YMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2) --#define ETP_YMAX_V2 ( 768 - ETP_EDGE_FUZZ_V2) -+#define ETP_XMIN_V2 0 -+#define ETP_XMAX_V2 1152 -+#define ETP_YMIN_V2 0 -+#define ETP_YMAX_V2 768 - - #define ETP_PMIN_V2 0 - #define ETP_PMAX_V2 255 --- -1.7.6.4 - - -From cc66bde05d267cce5a6f64d877e63036505cc31e Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Fri, 9 Sep 2011 10:28:04 -0700 -Subject: Input: elantech - packet checking for v2 hardware -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -For v2 hardware, there is no real parity check, but we can still check -some constant bits for data integrity. - -Also rename elantech_check_parity_v1 to elantech_packet_check_v1 to make -these packet checking function names consistent. - -Signed-off-by: JJ Ding -Acked-by: Daniel Kurtz -Acked-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.c | 39 ++++++++++++++++++++++++++++++++++----- - 1 files changed, 34 insertions(+), 5 deletions(-) - -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index 296b6a6..f2e3a2b 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -350,7 +350,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - input_sync(dev); - } - --static int elantech_check_parity_v1(struct psmouse *psmouse) -+static int elantech_packet_check_v1(struct psmouse *psmouse) - { - struct elantech_data *etd = psmouse->private; - unsigned char *packet = psmouse->packet; -@@ -374,6 +374,34 @@ static int elantech_check_parity_v1(struct psmouse *psmouse) - etd->parity[packet[3]] == p3; - } - -+static int elantech_packet_check_v2(struct psmouse *psmouse) -+{ -+ struct elantech_data *etd = psmouse->private; -+ unsigned char *packet = psmouse->packet; -+ -+ /* -+ * V2 hardware has two flavors. Older ones that do not report pressure, -+ * and newer ones that reports pressure and width. With newer ones, all -+ * packets (1, 2, 3 finger touch) have the same constant bits. With -+ * older ones, 1/3 finger touch packets and 2 finger touch packets -+ * have different constant bits. -+ * With all three cases, if the constant bits are not exactly what I -+ * expected, I consider them invalid. -+ */ -+ if (etd->reports_pressure) -+ return (packet[0] & 0x0c) == 0x04 && -+ (packet[3] & 0x0f) == 0x02; -+ -+ if ((packet[0] & 0xc0) == 0x80) -+ return (packet[0] & 0x0c) == 0x0c && -+ (packet[3] & 0x0e) == 0x08; -+ -+ return (packet[0] & 0x3c) == 0x3c && -+ (packet[1] & 0xf0) == 0x00 && -+ (packet[3] & 0x3e) == 0x38 && -+ (packet[4] & 0xf0) == 0x00; -+} -+ - /* - * Process byte stream from mouse and handle complete packets - */ -@@ -389,14 +417,16 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) - - switch (etd->hw_version) { - case 1: -- if (etd->paritycheck && !elantech_check_parity_v1(psmouse)) -+ if (etd->paritycheck && !elantech_packet_check_v1(psmouse)) - return PSMOUSE_BAD_DATA; - - elantech_report_absolute_v1(psmouse); - break; - - case 2: -- /* We don't know how to check parity in protocol v2 */ -+ if (etd->paritycheck && !elantech_packet_check_v2(psmouse)) -+ return PSMOUSE_BAD_DATA; -+ - elantech_report_absolute_v2(psmouse); - break; - } -@@ -795,8 +825,7 @@ int elantech_init(struct psmouse *psmouse) - etd->hw_version = 2; - /* For now show extra debug information */ - etd->debug = 1; -- /* Don't know how to do parity checking for version 2 */ -- etd->paritycheck = 0; -+ etd->paritycheck = 1; - - if (etd->fw_version >= 0x020800) - etd->reports_pressure = true; --- -1.7.6.4 - - -From 7e1abba14d70426b251ee58451ab1671af425409 Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Fri, 9 Sep 2011 10:28:19 -0700 -Subject: Input: elantech - clean up elantech_init -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Group property setting code into elantech_set_properties. - -Signed-off-by: JJ Ding -Acked-by: Daniel Kurtz -Acked-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.c | 69 ++++++++++++++++++++++----------------- - 1 files changed, 39 insertions(+), 30 deletions(-) - -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index f2e3a2b..1ab1c14 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -791,6 +791,42 @@ static int elantech_reconnect(struct psmouse *psmouse) - } - - /* -+ * determine hardware version and set some properties according to it. -+ */ -+static void elantech_set_properties(struct elantech_data *etd) -+{ -+ /* -+ * Assume every version greater than 0x020030 is new EeePC style -+ * hardware with 6 byte packets, except 0x020600 -+ */ -+ if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) -+ etd->hw_version = 1; -+ else -+ etd->hw_version = 2; -+ -+ /* -+ * Turn on packet checking by default. -+ */ -+ etd->paritycheck = 1; -+ -+ /* -+ * This firmware suffers from misreporting coordinates when -+ * a touch action starts causing the mouse cursor or scrolled page -+ * to jump. Enable a workaround. -+ */ -+ etd->jumpy_cursor = -+ (etd->fw_version == 0x020022 || etd->fw_version == 0x020600); -+ -+ if (etd->hw_version == 2) { -+ /* For now show extra debug information */ -+ etd->debug = 1; -+ -+ if (etd->fw_version >= 0x020800) -+ etd->reports_pressure = true; -+ } -+} -+ -+/* - * Initialize the touchpad and create sysfs entries - */ - int elantech_init(struct psmouse *psmouse) -@@ -816,26 +852,9 @@ int elantech_init(struct psmouse *psmouse) - } - - etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; -- -- /* -- * Assume every version greater than this is new EeePC style -- * hardware with 6 byte packets -- */ -- if (etd->fw_version >= 0x020030) { -- etd->hw_version = 2; -- /* For now show extra debug information */ -- etd->debug = 1; -- etd->paritycheck = 1; -- -- if (etd->fw_version >= 0x020800) -- etd->reports_pressure = true; -- -- } else { -- etd->hw_version = 1; -- etd->paritycheck = 1; -- } -- -- pr_info("assuming hardware version %d, firmware version %d.%d.%d\n", -+ elantech_set_properties(etd); -+ pr_info("assuming hardware version %d " -+ "(with firmware version 0x%02x%02x%02x)\n", - etd->hw_version, param[0], param[1], param[2]); - - if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, -@@ -847,16 +866,6 @@ int elantech_init(struct psmouse *psmouse) - etd->capabilities[0], etd->capabilities[1], - etd->capabilities[2]); - -- /* -- * This firmware suffers from misreporting coordinates when -- * a touch action starts causing the mouse cursor or scrolled page -- * to jump. Enable a workaround. -- */ -- if (etd->fw_version == 0x020022 || etd->fw_version == 0x020600) { -- pr_info("firmware version 2.0.34/2.6.0 detected, enabling jumpy cursor workaround\n"); -- etd->jumpy_cursor = true; -- } -- - if (elantech_set_absolute_mode(psmouse)) { - pr_err("failed to put touchpad into absolute mode.\n"); - goto init_fail; --- -1.7.6.4 - - -From 709d9ebd2853032df0599c30d5ac61c8397679f3 Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Fri, 9 Sep 2011 10:30:31 -0700 -Subject: Input: elantech - add v3 hardware support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -v3 hardware's packet format is almost identical to v2 (one/three finger touch), -except when sensing two finger touch, the hardware sends 12 bytes of data. - -Signed-off-by: JJ Ding -Acked-by: Daniel Kurtz -Acked-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - Documentation/input/elantech.txt | 117 +++++++++++++++++++-- - drivers/input/mouse/elantech.c | 208 ++++++++++++++++++++++++++++++++++---- - drivers/input/mouse/elantech.h | 12 ++ - 3 files changed, 306 insertions(+), 31 deletions(-) - -diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt -index bce9941..cee08ee 100644 ---- a/Documentation/input/elantech.txt -+++ b/Documentation/input/elantech.txt -@@ -16,15 +16,22 @@ Contents - - 1. Introduction - 2. Extra knobs -- 3. Hardware version 1 -- 3.1 Registers -- 3.2 Native relative mode 4 byte packet format -- 3.3 Native absolute mode 4 byte packet format -- 4. Hardware version 2 -+ 3. Differentiating hardware versions -+ 4. Hardware version 1 - 4.1 Registers -- 4.2 Native absolute mode 6 byte packet format -- 4.2.1 One finger touch -- 4.2.2 Two finger touch -+ 4.2 Native relative mode 4 byte packet format -+ 4.3 Native absolute mode 4 byte packet format -+ 5. Hardware version 2 -+ 5.1 Registers -+ 5.2 Native absolute mode 6 byte packet format -+ 5.2.1 Parity checking and packet re-synchronization -+ 5.2.2 One/Three finger touch -+ 5.2.3 Two finger touch -+ 6. Hardware version 3 -+ 6.1 Registers -+ 6.2 Native absolute mode 6 byte packet format -+ 6.2.1 One/Three finger touch -+ 6.2.2 Two finger touch - - - -@@ -375,7 +382,7 @@ For all the other ones, there are just a few constant bits: - - In case an error is detected, all the packets are shifted by one (and packet[0] is discarded). - --5.2.1 One/Three finger touch -+5.2.2 One/Three finger touch - ~~~~~~~~~~~~~~~~ - - byte 0: -@@ -384,7 +391,7 @@ byte 0: - n1 n0 w3 w2 . . R L - - L, R = 1 when Left, Right mouse button pressed -- n1..n0 = numbers of fingers on touchpad -+ n1..n0 = number of fingers on touchpad - - byte 1: - -@@ -432,7 +439,7 @@ byte 5: - y11..y0 = absolute y value (vertical) - - --4.2.2 Two finger touch -+5.2.3 Two finger touch - ~~~~~~~~~~~~~~~~ - - Note that the two pairs of coordinates are not exactly the coordinates of the -@@ -446,7 +453,7 @@ byte 0: - n1 n0 ay8 ax8 . . R L - - L, R = 1 when Left, Right mouse button pressed -- n1..n0 = numbers of fingers on touchpad -+ n1..n0 = number of fingers on touchpad - - byte 1: - -@@ -480,3 +487,89 @@ byte 5: - by7 by8 by5 by4 by3 by2 by1 by0 - - by8..by0 = upper-right finger absolute y value -+ -+///////////////////////////////////////////////////////////////////////////// -+ -+6. Hardware version 3 -+ ================== -+ -+6.1 Registers -+ ~~~~~~~~~ -+* reg_10 -+ -+ bit 7 6 5 4 3 2 1 0 -+ 0 0 0 0 0 0 0 A -+ -+ A: 1 = enable absolute tracking -+ -+6.2 Native absolute mode 6 byte packet format -+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+1 and 3 finger touch shares the same 6-byte packet format, except that -+3 finger touch only reports the position of the center of all three fingers. -+ -+Firmware would send 12 bytes of data for 2 finger touch. -+ -+Note on debounce: -+In case the box has unstable power supply or other electricity issues, or -+when number of finger changes, F/W would send "debounce packet" to inform -+driver that the hardware is in debounce status. -+The debouce packet has the following signature: -+ byte 0: 0xc4 -+ byte 1: 0xff -+ byte 2: 0xff -+ byte 3: 0x02 -+ byte 4: 0xff -+ byte 5: 0xff -+When we encounter this kind of packet, we just ignore it. -+ -+6.2.1 One/Three finger touch -+ ~~~~~~~~~~~~~~~~~~~~~~ -+ -+byte 0: -+ -+ bit 7 6 5 4 3 2 1 0 -+ n1 n0 w3 w2 0 1 R L -+ -+ L, R = 1 when Left, Right mouse button pressed -+ n1..n0 = number of fingers on touchpad -+ -+byte 1: -+ -+ bit 7 6 5 4 3 2 1 0 -+ p7 p6 p5 p4 x11 x10 x9 x8 -+ -+byte 2: -+ -+ bit 7 6 5 4 3 2 1 0 -+ x7 x6 x5 x4 x3 x2 x1 x0 -+ -+ x11..x0 = absolute x value (horizontal) -+ -+byte 3: -+ -+ bit 7 6 5 4 3 2 1 0 -+ 0 0 w1 w0 0 0 1 0 -+ -+ w3..w0 = width of the finger touch -+ -+byte 4: -+ -+ bit 7 6 5 4 3 2 1 0 -+ p3 p1 p2 p0 y11 y10 y9 y8 -+ -+ p7..p0 = pressure -+ -+byte 5: -+ -+ bit 7 6 5 4 3 2 1 0 -+ y7 y6 y5 y4 y3 y2 y1 y0 -+ -+ y11..y0 = absolute y value (vertical) -+ -+6.2.2 Two finger touch -+ ~~~~~~~~~~~~~~~~ -+ -+The packet format is exactly the same for two finger touch, except the hardware -+sends two 6 byte packets. The first packet contains data for the first finger, -+the second packet has data for the second finger. So for two finger touch a -+total of 12 bytes are sent. -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index 1ab1c14..9cfc70a 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -108,6 +108,16 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, - rc = -1; - } - break; -+ -+ case 3: -+ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || -+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, reg) || -+ elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) { -+ rc = -1; -+ } -+ break; - } - - if (rc) -@@ -154,6 +164,18 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, - rc = -1; - } - break; -+ -+ case 3: -+ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || -+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, reg) || -+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, val) || -+ elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { -+ rc = -1; -+ } -+ break; - } - - if (rc) -@@ -350,6 +372,84 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - input_sync(dev); - } - -+/* -+ * Interpret complete data packets and report absolute mode input events for -+ * hardware version 3. (12 byte packets for two fingers) -+ */ -+static void elantech_report_absolute_v3(struct psmouse *psmouse, -+ int packet_type) -+{ -+ struct input_dev *dev = psmouse->dev; -+ struct elantech_data *etd = psmouse->private; -+ unsigned char *packet = psmouse->packet; -+ unsigned int fingers = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0; -+ unsigned int width = 0, pres = 0; -+ -+ /* byte 0: n1 n0 . . . . R L */ -+ fingers = (packet[0] & 0xc0) >> 6; -+ -+ switch (fingers) { -+ case 3: -+ case 1: -+ /* -+ * byte 1: . . . . x11 x10 x9 x8 -+ * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 -+ */ -+ x1 = ((packet[1] & 0x0f) << 8) | packet[2]; -+ /* -+ * byte 4: . . . . y11 y10 y9 y8 -+ * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 -+ */ -+ y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); -+ break; -+ -+ case 2: -+ if (packet_type == PACKET_V3_HEAD) { -+ /* -+ * byte 1: . . . . ax11 ax10 ax9 ax8 -+ * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 -+ */ -+ etd->prev_x = ((packet[1] & 0x0f) << 8) | packet[2]; -+ /* -+ * byte 4: . . . . ay11 ay10 ay9 ay8 -+ * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 -+ */ -+ etd->prev_y = etd->y_max - -+ (((packet[4] & 0x0f) << 8) | packet[5]); -+ /* -+ * wait for next packet -+ */ -+ return; -+ } -+ -+ /* packet_type == PACKET_V3_TAIL */ -+ x1 = etd->prev_x; -+ y1 = etd->prev_y; -+ x2 = ((packet[1] & 0x0f) << 8) | packet[2]; -+ y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); -+ break; -+ } -+ -+ pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); -+ width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); -+ -+ input_report_key(dev, BTN_TOUCH, fingers != 0); -+ if (fingers != 0) { -+ input_report_abs(dev, ABS_X, x1); -+ input_report_abs(dev, ABS_Y, y1); -+ } -+ elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); -+ input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); -+ input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); -+ input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); -+ input_report_key(dev, BTN_LEFT, packet[0] & 0x01); -+ input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); -+ input_report_abs(dev, ABS_PRESSURE, pres); -+ input_report_abs(dev, ABS_TOOL_WIDTH, width); -+ -+ input_sync(dev); -+} -+ - static int elantech_packet_check_v1(struct psmouse *psmouse) - { - struct elantech_data *etd = psmouse->private; -@@ -403,11 +503,37 @@ static int elantech_packet_check_v2(struct psmouse *psmouse) - } - - /* -+ * We check the constant bits to determine what packet type we get, -+ * so packet checking is mandatory for v3 hardware. -+ */ -+static int elantech_packet_check_v3(struct psmouse *psmouse) -+{ -+ const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff }; -+ unsigned char *packet = psmouse->packet; -+ -+ /* -+ * check debounce first, it has the same signature in byte 0 -+ * and byte 3 as PACKET_V3_HEAD. -+ */ -+ if (!memcmp(packet, debounce_packet, sizeof(debounce_packet))) -+ return PACKET_DEBOUNCE; -+ -+ if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02) -+ return PACKET_V3_HEAD; -+ -+ if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) -+ return PACKET_V3_TAIL; -+ -+ return PACKET_UNKNOWN; -+} -+ -+/* - * Process byte stream from mouse and handle complete packets - */ - static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) - { - struct elantech_data *etd = psmouse->private; -+ int packet_type; - - if (psmouse->pktcnt < psmouse->pktsize) - return PSMOUSE_GOOD_DATA; -@@ -429,6 +555,18 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) - - elantech_report_absolute_v2(psmouse); - break; -+ -+ case 3: -+ packet_type = elantech_packet_check_v3(psmouse); -+ /* ignore debounce */ -+ if (packet_type == PACKET_DEBOUNCE) -+ return PSMOUSE_FULL_PACKET; -+ -+ if (packet_type == PACKET_UNKNOWN) -+ return PSMOUSE_BAD_DATA; -+ -+ elantech_report_absolute_v3(psmouse, packet_type); -+ break; - } - - return PSMOUSE_FULL_PACKET; -@@ -463,8 +601,15 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) - elantech_write_reg(psmouse, 0x11, etd->reg_11) || - elantech_write_reg(psmouse, 0x21, etd->reg_21)) { - rc = -1; -- break; - } -+ break; -+ -+ case 3: -+ etd->reg_10 = 0x0b; -+ if (elantech_write_reg(psmouse, 0x10, etd->reg_10)) -+ rc = -1; -+ -+ break; - } - - if (rc == 0) { -@@ -498,11 +643,12 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) - return rc; - } - --static void elantech_set_range(struct psmouse *psmouse, -- unsigned int *x_min, unsigned int *y_min, -- unsigned int *x_max, unsigned int *y_max) -+static int elantech_set_range(struct psmouse *psmouse, -+ unsigned int *x_min, unsigned int *y_min, -+ unsigned int *x_max, unsigned int *y_max) - { - struct elantech_data *etd = psmouse->private; -+ unsigned char param[3]; - int i; - - switch (etd->hw_version) { -@@ -530,19 +676,30 @@ static void elantech_set_range(struct psmouse *psmouse, - *y_max = (etd->capabilities[2] - i) * 64; - } - break; -+ -+ case 3: -+ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) -+ return -1; -+ -+ *x_max = (0x0f & param[0]) << 8 | param[1]; -+ *y_max = (0xf0 & param[0]) << 4 | param[2]; -+ break; - } -+ -+ return 0; - } - - /* - * Set the appropriate event bits for the input subsystem - */ --static void elantech_set_input_params(struct psmouse *psmouse) -+static int elantech_set_input_params(struct psmouse *psmouse) - { - struct input_dev *dev = psmouse->dev; - struct elantech_data *etd = psmouse->private; - unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0; - -- elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max); -+ if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max)) -+ return -1; - - __set_bit(EV_KEY, dev->evbit); - __set_bit(EV_ABS, dev->evbit); -@@ -570,6 +727,9 @@ static void elantech_set_input_params(struct psmouse *psmouse) - - case 2: - __set_bit(BTN_TOOL_QUADTAP, dev->keybit); -+ __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); -+ /* fall through */ -+ case 3: - input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); - input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); - if (etd->reports_pressure) { -@@ -578,7 +738,6 @@ static void elantech_set_input_params(struct psmouse *psmouse) - input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, - ETP_WMAX_V2, 0, 0); - } -- __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); - input_mt_init_slots(dev, 2); - input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); - input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); -@@ -586,6 +745,8 @@ static void elantech_set_input_params(struct psmouse *psmouse) - } - - etd->y_max = y_max; -+ -+ return 0; - } - - struct elantech_attr_data { -@@ -727,7 +888,8 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) - * Report this in case there are Elantech models that use a different - * set of magic numbers - */ -- if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) { -+ if (param[0] != 0x3c || param[1] != 0x03 || -+ (param[2] != 0xc8 && param[2] != 0x00)) { - pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", - param[0], param[1], param[2]); - return -1; -@@ -793,16 +955,16 @@ static int elantech_reconnect(struct psmouse *psmouse) - /* - * determine hardware version and set some properties according to it. - */ --static void elantech_set_properties(struct elantech_data *etd) -+static int elantech_set_properties(struct elantech_data *etd) - { -- /* -- * Assume every version greater than 0x020030 is new EeePC style -- * hardware with 6 byte packets, except 0x020600 -- */ - if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) - etd->hw_version = 1; -- else -+ else if (etd->fw_version < 0x150600) - etd->hw_version = 2; -+ else if ((etd->fw_version & 0x0f0000) >> 16 == 5) -+ etd->hw_version = 3; -+ else -+ return -1; - - /* - * Turn on packet checking by default. -@@ -817,13 +979,15 @@ static void elantech_set_properties(struct elantech_data *etd) - etd->jumpy_cursor = - (etd->fw_version == 0x020022 || etd->fw_version == 0x020600); - -- if (etd->hw_version == 2) { -+ if (etd->hw_version > 1) { - /* For now show extra debug information */ - etd->debug = 1; - - if (etd->fw_version >= 0x020800) - etd->reports_pressure = true; - } -+ -+ return 0; - } - - /* -@@ -850,9 +1014,12 @@ int elantech_init(struct psmouse *psmouse) - pr_err("failed to query firmware version.\n"); - goto init_fail; - } -- - etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; -- elantech_set_properties(etd); -+ -+ if (elantech_set_properties(etd)) { -+ pr_err("unknown hardware version, aborting...\n"); -+ goto init_fail; -+ } - pr_info("assuming hardware version %d " - "(with firmware version 0x%02x%02x%02x)\n", - etd->hw_version, param[0], param[1], param[2]); -@@ -871,7 +1038,10 @@ int elantech_init(struct psmouse *psmouse) - goto init_fail; - } - -- elantech_set_input_params(psmouse); -+ if (elantech_set_input_params(psmouse)) { -+ pr_err("failed to query touchpad range.\n"); -+ goto init_fail; -+ } - - error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, - &elantech_attr_group); -@@ -883,7 +1053,7 @@ int elantech_init(struct psmouse *psmouse) - psmouse->protocol_handler = elantech_process_byte; - psmouse->disconnect = elantech_disconnect; - psmouse->reconnect = elantech_reconnect; -- psmouse->pktsize = etd->hw_version == 2 ? 6 : 4; -+ psmouse->pktsize = etd->hw_version > 1 ? 6 : 4; - - return 0; - -diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h -index d9e6144..236c33c 100644 ---- a/drivers/input/mouse/elantech.h -+++ b/drivers/input/mouse/elantech.h -@@ -16,6 +16,7 @@ - /* - * Command values for Synaptics style queries - */ -+#define ETP_FW_ID_QUERY 0x00 - #define ETP_FW_VERSION_QUERY 0x01 - #define ETP_CAPABILITIES_QUERY 0x02 - -@@ -24,6 +25,7 @@ - */ - #define ETP_REGISTER_READ 0x10 - #define ETP_REGISTER_WRITE 0x11 -+#define ETP_REGISTER_READWRITE 0x00 - - /* - * Hardware version 2 custom PS/2 command value -@@ -79,6 +81,14 @@ - #define ETP_WMIN_V2 0 - #define ETP_WMAX_V2 15 - -+/* -+ * v3 hardware has 2 kinds of packet types. -+ */ -+#define PACKET_UNKNOWN 0x01 -+#define PACKET_DEBOUNCE 0x02 -+#define PACKET_V3_HEAD 0x03 -+#define PACKET_V3_TAIL 0x04 -+ - struct elantech_data { - unsigned char reg_10; - unsigned char reg_11; -@@ -98,6 +108,8 @@ struct elantech_data { - unsigned int fw_version; - unsigned int single_finger_reports; - unsigned int y_max; -+ unsigned int prev_x; -+ unsigned int prev_y; - unsigned char parity[256]; - }; - --- -1.7.6.4 - - -From 5936f37c68ab27b24d6f2faf23268a9aefd3092e Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Fri, 9 Sep 2011 10:31:58 -0700 -Subject: Input: elantech - add v4 hardware support - -v4 hardware is a true multitouch capable touchpad (up to 5 fingers). -The packet format is quite complex, please see protocol document for -reference. - -Signed-off-by: JJ Ding -Signed-off-by: Dmitry Torokhov ---- - Documentation/input/elantech.txt | 170 ++++++++++++++++++++++++++ - drivers/input/mouse/elantech.c | 249 ++++++++++++++++++++++++++++++++++++-- - drivers/input/mouse/elantech.h | 29 ++++- - 3 files changed, 432 insertions(+), 16 deletions(-) - -diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt -index cee08ee..5602eb7 100644 ---- a/Documentation/input/elantech.txt -+++ b/Documentation/input/elantech.txt -@@ -32,6 +32,12 @@ Contents - 6.2 Native absolute mode 6 byte packet format - 6.2.1 One/Three finger touch - 6.2.2 Two finger touch -+ 7. Hardware version 4 -+ 7.1 Registers -+ 7.2 Native absolute mode 6 byte packet format -+ 7.2.1 Status packet -+ 7.2.2 Head packet -+ 7.2.3 Motion packet - - - -@@ -573,3 +579,167 @@ The packet format is exactly the same for two finger touch, except the hardware - sends two 6 byte packets. The first packet contains data for the first finger, - the second packet has data for the second finger. So for two finger touch a - total of 12 bytes are sent. -+ -+///////////////////////////////////////////////////////////////////////////// -+ -+7. Hardware version 4 -+ ================== -+ -+7.1 Registers -+ ~~~~~~~~~ -+* reg_07 -+ -+ bit 7 6 5 4 3 2 1 0 -+ 0 0 0 0 0 0 0 A -+ -+ A: 1 = enable absolute tracking -+ -+7.2 Native absolute mode 6 byte packet format -+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers. -+Unfortunately, due to PS/2's limited bandwidth, its packet format is rather -+complex. -+ -+Whenever the numbers or identities of the fingers changes, the hardware sends a -+status packet to indicate how many and which fingers is on touchpad, followed by -+head packets or motion packets. A head packet contains data of finger id, finger -+position (absolute x, y values), width, and pressure. A motion packet contains -+two fingers' position delta. -+ -+For example, when status packet tells there are 2 fingers on touchpad, then we -+can expect two following head packets. If the finger status doesn't change, -+the following packets would be motion packets, only sending delta of finger -+position, until we receive a status packet. -+ -+One exception is one finger touch. when a status packet tells us there is only -+one finger, the hardware would just send head packets afterwards. -+ -+7.2.1 Status packet -+ ~~~~~~~~~~~~~ -+ -+byte 0: -+ -+ bit 7 6 5 4 3 2 1 0 -+ . . . . 0 1 R L -+ -+ L, R = 1 when Left, Right mouse button pressed -+ -+byte 1: -+ -+ bit 7 6 5 4 3 2 1 0 -+ . . . ft4 ft3 ft2 ft1 ft0 -+ -+ ft4 ft3 ft2 ft1 ft0 ftn = 1 when finger n is on touchpad -+ -+byte 2: not used -+ -+byte 3: -+ -+ bit 7 6 5 4 3 2 1 0 -+ . . . 1 0 0 0 0 -+ -+ constant bits -+ -+byte 4: -+ -+ bit 7 6 5 4 3 2 1 0 -+ p . . . . . . . -+ -+ p = 1 for palm -+ -+byte 5: not used -+ -+7.2.2 Head packet -+ ~~~~~~~~~~~ -+ -+byte 0: -+ -+ bit 7 6 5 4 3 2 1 0 -+ w3 w2 w1 w0 0 1 R L -+ -+ L, R = 1 when Left, Right mouse button pressed -+ w3..w0 = finger width (spans how many trace lines) -+ -+byte 1: -+ -+ bit 7 6 5 4 3 2 1 0 -+ p7 p6 p5 p4 x11 x10 x9 x8 -+ -+byte 2: -+ -+ bit 7 6 5 4 3 2 1 0 -+ x7 x6 x5 x4 x3 x2 x1 x0 -+ -+ x11..x0 = absolute x value (horizontal) -+ -+byte 3: -+ -+ bit 7 6 5 4 3 2 1 0 -+ id2 id1 id0 1 0 0 0 1 -+ -+ id2..id0 = finger id -+ -+byte 4: -+ -+ bit 7 6 5 4 3 2 1 0 -+ p3 p1 p2 p0 y11 y10 y9 y8 -+ -+ p7..p0 = pressure -+ -+byte 5: -+ -+ bit 7 6 5 4 3 2 1 0 -+ y7 y6 y5 y4 y3 y2 y1 y0 -+ -+ y11..y0 = absolute y value (vertical) -+ -+7.2.3 Motion packet -+ ~~~~~~~~~~~~~ -+ -+byte 0: -+ -+ bit 7 6 5 4 3 2 1 0 -+ id2 id1 id0 w 0 1 R L -+ -+ L, R = 1 when Left, Right mouse button pressed -+ id2..id0 = finger id -+ w = 1 when delta overflows (> 127 or < -128), in this case -+ firmware sends us (delta x / 5) and (delta y / 5) -+ -+byte 1: -+ -+ bit 7 6 5 4 3 2 1 0 -+ x7 x6 x5 x4 x3 x2 x1 x0 -+ -+ x7..x0 = delta x (two's complement) -+ -+byte 2: -+ -+ bit 7 6 5 4 3 2 1 0 -+ y7 y6 y5 y4 y3 y2 y1 y0 -+ -+ y7..y0 = delta y (two's complement) -+ -+byte 3: -+ -+ bit 7 6 5 4 3 2 1 0 -+ id2 id1 id0 1 0 0 1 0 -+ -+ id2..id0 = finger id -+ -+byte 4: -+ -+ bit 7 6 5 4 3 2 1 0 -+ x7 x6 x5 x4 x3 x2 x1 x0 -+ -+ x7..x0 = delta x (two's complement) -+ -+byte 5: -+ -+ bit 7 6 5 4 3 2 1 0 -+ y7 y6 y5 y4 y3 y2 y1 y0 -+ -+ y7..y0 = delta y (two's complement) -+ -+ byte 0 ~ 2 for one finger -+ byte 3 ~ 5 for another -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index 9cfc70a..b8733b3 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -84,7 +84,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, - unsigned char param[3]; - int rc = 0; - -- if (reg < 0x10 || reg > 0x26) -+ if (reg < 0x07 || reg > 0x26) - return -1; - - if (reg > 0x11 && reg < 0x20) -@@ -109,7 +109,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, - } - break; - -- case 3: -+ case 3 ... 4: - if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || - elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || - elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -@@ -122,8 +122,10 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, - - if (rc) - pr_err("failed to read register 0x%02x.\n", reg); -- else -+ else if (etd->hw_version != 4) - *val = param[0]; -+ else -+ *val = param[1]; - - return rc; - } -@@ -137,7 +139,7 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, - struct elantech_data *etd = psmouse->private; - int rc = 0; - -- if (reg < 0x10 || reg > 0x26) -+ if (reg < 0x07 || reg > 0x26) - return -1; - - if (reg > 0x11 && reg < 0x20) -@@ -176,6 +178,20 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, - rc = -1; - } - break; -+ -+ case 4: -+ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || -+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, reg) || -+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || -+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, val) || -+ elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { -+ rc = -1; -+ } -+ break; - } - - if (rc) -@@ -409,12 +425,12 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, - * byte 1: . . . . ax11 ax10 ax9 ax8 - * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 - */ -- etd->prev_x = ((packet[1] & 0x0f) << 8) | packet[2]; -+ etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2]; - /* - * byte 4: . . . . ay11 ay10 ay9 ay8 - * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 - */ -- etd->prev_y = etd->y_max - -+ etd->mt[0].y = etd->y_max - - (((packet[4] & 0x0f) << 8) | packet[5]); - /* - * wait for next packet -@@ -423,8 +439,8 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, - } - - /* packet_type == PACKET_V3_TAIL */ -- x1 = etd->prev_x; -- y1 = etd->prev_y; -+ x1 = etd->mt[0].x; -+ y1 = etd->mt[0].y; - x2 = ((packet[1] & 0x0f) << 8) | packet[2]; - y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); - break; -@@ -450,6 +466,129 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, - input_sync(dev); - } - -+static void elantech_input_sync_v4(struct psmouse *psmouse) -+{ -+ struct input_dev *dev = psmouse->dev; -+ unsigned char *packet = psmouse->packet; -+ -+ input_report_key(dev, BTN_LEFT, packet[0] & 0x01); -+ input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); -+ input_mt_report_pointer_emulation(dev, true); -+ input_sync(dev); -+} -+ -+static void process_packet_status_v4(struct psmouse *psmouse) -+{ -+ struct input_dev *dev = psmouse->dev; -+ unsigned char *packet = psmouse->packet; -+ unsigned fingers; -+ int i; -+ -+ /* notify finger state change */ -+ fingers = packet[1] & 0x1f; -+ for (i = 0; i < ETP_MAX_FINGERS; i++) { -+ if ((fingers & (1 << i)) == 0) { -+ input_mt_slot(dev, i); -+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, false); -+ } -+ } -+ -+ elantech_input_sync_v4(psmouse); -+} -+ -+static void process_packet_head_v4(struct psmouse *psmouse) -+{ -+ struct input_dev *dev = psmouse->dev; -+ struct elantech_data *etd = psmouse->private; -+ unsigned char *packet = psmouse->packet; -+ int id = ((packet[3] & 0xe0) >> 5) - 1; -+ int pres, traces; -+ -+ if (id < 0) -+ return; -+ -+ etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2]; -+ etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); -+ pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); -+ traces = (packet[0] & 0xf0) >> 4; -+ -+ input_mt_slot(dev, id); -+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); -+ -+ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); -+ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); -+ input_report_abs(dev, ABS_MT_PRESSURE, pres); -+ input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width); -+ /* report this for backwards compatibility */ -+ input_report_abs(dev, ABS_TOOL_WIDTH, traces); -+ -+ elantech_input_sync_v4(psmouse); -+} -+ -+static void process_packet_motion_v4(struct psmouse *psmouse) -+{ -+ struct input_dev *dev = psmouse->dev; -+ struct elantech_data *etd = psmouse->private; -+ unsigned char *packet = psmouse->packet; -+ int weight, delta_x1 = 0, delta_y1 = 0, delta_x2 = 0, delta_y2 = 0; -+ int id, sid; -+ -+ id = ((packet[0] & 0xe0) >> 5) - 1; -+ if (id < 0) -+ return; -+ -+ sid = ((packet[3] & 0xe0) >> 5) - 1; -+ weight = (packet[0] & 0x10) ? ETP_WEIGHT_VALUE : 1; -+ /* -+ * Motion packets give us the delta of x, y values of specific fingers, -+ * but in two's complement. Let the compiler do the conversion for us. -+ * Also _enlarge_ the numbers to int, in case of overflow. -+ */ -+ delta_x1 = (signed char)packet[1]; -+ delta_y1 = (signed char)packet[2]; -+ delta_x2 = (signed char)packet[4]; -+ delta_y2 = (signed char)packet[5]; -+ -+ etd->mt[id].x += delta_x1 * weight; -+ etd->mt[id].y -= delta_y1 * weight; -+ input_mt_slot(dev, id); -+ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); -+ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); -+ -+ if (sid >= 0) { -+ etd->mt[sid].x += delta_x2 * weight; -+ etd->mt[sid].y -= delta_y2 * weight; -+ input_mt_slot(dev, sid); -+ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[sid].x); -+ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[sid].y); -+ } -+ -+ elantech_input_sync_v4(psmouse); -+} -+ -+static void elantech_report_absolute_v4(struct psmouse *psmouse, -+ int packet_type) -+{ -+ switch (packet_type) { -+ case PACKET_V4_STATUS: -+ process_packet_status_v4(psmouse); -+ break; -+ -+ case PACKET_V4_HEAD: -+ process_packet_head_v4(psmouse); -+ break; -+ -+ case PACKET_V4_MOTION: -+ process_packet_motion_v4(psmouse); -+ break; -+ -+ case PACKET_UNKNOWN: -+ default: -+ /* impossible to get here */ -+ break; -+ } -+} -+ - static int elantech_packet_check_v1(struct psmouse *psmouse) - { - struct elantech_data *etd = psmouse->private; -@@ -504,7 +643,7 @@ static int elantech_packet_check_v2(struct psmouse *psmouse) - - /* - * We check the constant bits to determine what packet type we get, -- * so packet checking is mandatory for v3 hardware. -+ * so packet checking is mandatory for v3 and later hardware. - */ - static int elantech_packet_check_v3(struct psmouse *psmouse) - { -@@ -527,6 +666,25 @@ static int elantech_packet_check_v3(struct psmouse *psmouse) - return PACKET_UNKNOWN; - } - -+static int elantech_packet_check_v4(struct psmouse *psmouse) -+{ -+ unsigned char *packet = psmouse->packet; -+ -+ if ((packet[0] & 0x0c) == 0x04 && -+ (packet[3] & 0x1f) == 0x11) -+ return PACKET_V4_HEAD; -+ -+ if ((packet[0] & 0x0c) == 0x04 && -+ (packet[3] & 0x1f) == 0x12) -+ return PACKET_V4_MOTION; -+ -+ if ((packet[0] & 0x0c) == 0x04 && -+ (packet[3] & 0x1f) == 0x10) -+ return PACKET_V4_STATUS; -+ -+ return PACKET_UNKNOWN; -+} -+ - /* - * Process byte stream from mouse and handle complete packets - */ -@@ -567,6 +725,14 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) - - elantech_report_absolute_v3(psmouse, packet_type); - break; -+ -+ case 4: -+ packet_type = elantech_packet_check_v4(psmouse); -+ if (packet_type == PACKET_UNKNOWN) -+ return PSMOUSE_BAD_DATA; -+ -+ elantech_report_absolute_v4(psmouse, packet_type); -+ break; - } - - return PSMOUSE_FULL_PACKET; -@@ -610,6 +776,13 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) - rc = -1; - - break; -+ -+ case 4: -+ etd->reg_07 = 0x01; -+ if (elantech_write_reg(psmouse, 0x07, etd->reg_07)) -+ rc = -1; -+ -+ goto skip_readback_reg_10; /* v4 has no reg 0x10 to read */ - } - - if (rc == 0) { -@@ -637,6 +810,7 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) - } - } - -+ skip_readback_reg_10: - if (rc) - pr_err("failed to initialise registers.\n"); - -@@ -645,10 +819,12 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) - - static int elantech_set_range(struct psmouse *psmouse, - unsigned int *x_min, unsigned int *y_min, -- unsigned int *x_max, unsigned int *y_max) -+ unsigned int *x_max, unsigned int *y_max, -+ unsigned int *width) - { - struct elantech_data *etd = psmouse->private; - unsigned char param[3]; -+ unsigned char traces; - int i; - - switch (etd->hw_version) { -@@ -684,6 +860,19 @@ static int elantech_set_range(struct psmouse *psmouse, - *x_max = (0x0f & param[0]) << 8 | param[1]; - *y_max = (0xf0 & param[0]) << 4 | param[2]; - break; -+ -+ case 4: -+ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) -+ return -1; -+ -+ *x_max = (0x0f & param[0]) << 8 | param[1]; -+ *y_max = (0xf0 & param[0]) << 4 | param[2]; -+ traces = etd->capabilities[1]; -+ if ((traces < 2) || (traces > *x_max)) -+ return -1; -+ -+ *width = *x_max / (traces - 1); -+ break; - } - - return 0; -@@ -696,9 +885,9 @@ static int elantech_set_input_params(struct psmouse *psmouse) - { - struct input_dev *dev = psmouse->dev; - struct elantech_data *etd = psmouse->private; -- unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0; -+ unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0; - -- if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max)) -+ if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width)) - return -1; - - __set_bit(EV_KEY, dev->evbit); -@@ -742,9 +931,37 @@ static int elantech_set_input_params(struct psmouse *psmouse) - input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); - input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); - break; -+ -+ case 4: -+ __set_bit(BTN_TOOL_QUADTAP, dev->keybit); -+ /* For X to recognize me as touchpad. */ -+ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); -+ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); -+ /* -+ * range of pressure and width is the same as v2, -+ * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility. -+ */ -+ input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, -+ ETP_PMAX_V2, 0, 0); -+ input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, -+ ETP_WMAX_V2, 0, 0); -+ /* Multitouch capable pad, up to 5 fingers. */ -+ input_mt_init_slots(dev, ETP_MAX_FINGERS); -+ input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); -+ input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); -+ input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2, -+ ETP_PMAX_V2, 0, 0); -+ /* -+ * The firmware reports how many trace lines the finger spans, -+ * convert to surface unit as Protocol-B requires. -+ */ -+ input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0, -+ ETP_WMAX_V2 * width, 0, 0); -+ break; - } - - etd->y_max = y_max; -+ etd->width = width; - - return 0; - } -@@ -816,6 +1033,7 @@ static ssize_t elantech_set_int_attr(struct psmouse *psmouse, - elantech_show_int_attr, \ - elantech_set_int_attr) - -+ELANTECH_INT_ATTR(reg_07, 0x07); - ELANTECH_INT_ATTR(reg_10, 0x10); - ELANTECH_INT_ATTR(reg_11, 0x11); - ELANTECH_INT_ATTR(reg_20, 0x20); -@@ -829,6 +1047,7 @@ ELANTECH_INT_ATTR(debug, 0); - ELANTECH_INT_ATTR(paritycheck, 0); - - static struct attribute *elantech_attrs[] = { -+ &psmouse_attr_reg_07.dattr.attr, - &psmouse_attr_reg_10.dattr.attr, - &psmouse_attr_reg_11.dattr.attr, - &psmouse_attr_reg_20.dattr.attr, -@@ -957,12 +1176,16 @@ static int elantech_reconnect(struct psmouse *psmouse) - */ - static int elantech_set_properties(struct elantech_data *etd) - { -+ int ver = (etd->fw_version & 0x0f0000) >> 16; -+ - if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) - etd->hw_version = 1; - else if (etd->fw_version < 0x150600) - etd->hw_version = 2; -- else if ((etd->fw_version & 0x0f0000) >> 16 == 5) -+ else if (ver == 5) - etd->hw_version = 3; -+ else if (ver == 6) -+ etd->hw_version = 4; - else - return -1; - -diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h -index 236c33c..7ecaef0 100644 ---- a/drivers/input/mouse/elantech.h -+++ b/drivers/input/mouse/elantech.h -@@ -82,14 +82,37 @@ - #define ETP_WMAX_V2 15 - - /* -- * v3 hardware has 2 kinds of packet types. -+ * v3 hardware has 2 kinds of packet types, -+ * v4 hardware has 3. - */ - #define PACKET_UNKNOWN 0x01 - #define PACKET_DEBOUNCE 0x02 - #define PACKET_V3_HEAD 0x03 - #define PACKET_V3_TAIL 0x04 -+#define PACKET_V4_HEAD 0x05 -+#define PACKET_V4_MOTION 0x06 -+#define PACKET_V4_STATUS 0x07 -+ -+/* -+ * track up to 5 fingers for v4 hardware -+ */ -+#define ETP_MAX_FINGERS 5 -+ -+/* -+ * weight value for v4 hardware -+ */ -+#define ETP_WEIGHT_VALUE 5 -+ -+/* -+ * The base position for one finger, v4 hardware -+ */ -+struct finger_pos { -+ unsigned int x; -+ unsigned int y; -+}; - - struct elantech_data { -+ unsigned char reg_07; - unsigned char reg_10; - unsigned char reg_11; - unsigned char reg_20; -@@ -108,8 +131,8 @@ struct elantech_data { - unsigned int fw_version; - unsigned int single_finger_reports; - unsigned int y_max; -- unsigned int prev_x; -- unsigned int prev_y; -+ unsigned int width; -+ struct finger_pos mt[ETP_MAX_FINGERS]; - unsigned char parity[256]; - }; - --- -1.7.6.4 - - -From 3c09085f371a68f09147abb59b35db928fe3950f Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Tue, 20 Sep 2011 22:42:51 -0700 -Subject: Input: elantech - better support all those v2 variants -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -V2 hardware has many variants. This patch adddresses two issues: - - - some model also has debounce packets, but with a different signature - than v3. Now we just check debounce for all v2 hardware. - - - due to different scanning methods the hardware uses, x and y ranges have - to be calculated differently. And for some specific versions, we can just - see them as custom-made, so set {x, y} the same values as Windows driver - does. - -Signed-off-by: JJ Ding -Tested-by: Richard Schütz -Reviewed-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.c | 46 +++++++++++++++++++++++++++++++++++---- - drivers/input/mouse/elantech.h | 1 + - 2 files changed, 42 insertions(+), 5 deletions(-) - -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index b8733b3..c2d91eb 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -613,6 +613,18 @@ static int elantech_packet_check_v1(struct psmouse *psmouse) - etd->parity[packet[3]] == p3; - } - -+static int elantech_debounce_check_v2(struct psmouse *psmouse) -+{ -+ /* -+ * When we encounter packet that matches this exactly, it means the -+ * hardware is in debounce status. Just ignore the whole packet. -+ */ -+ const u8 debounce_packet[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff }; -+ unsigned char *packet = psmouse->packet; -+ -+ return !memcmp(packet, debounce_packet, sizeof(debounce_packet)); -+} -+ - static int elantech_packet_check_v2(struct psmouse *psmouse) - { - struct elantech_data *etd = psmouse->private; -@@ -708,6 +720,10 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) - break; - - case 2: -+ /* ignore debounce */ -+ if (elantech_debounce_check_v2(psmouse)) -+ return PSMOUSE_FULL_PACKET; -+ - if (etd->paritycheck && !elantech_packet_check_v2(psmouse)) - return PSMOUSE_BAD_DATA; - -@@ -825,7 +841,6 @@ static int elantech_set_range(struct psmouse *psmouse, - struct elantech_data *etd = psmouse->private; - unsigned char param[3]; - unsigned char traces; -- int i; - - switch (etd->hw_version) { - case 1: -@@ -844,12 +859,33 @@ static int elantech_set_range(struct psmouse *psmouse, - *x_max = ETP_XMAX_V2; - *y_max = ETP_YMAX_V2; - } else { -+ int i; -+ int fixed_dpi; -+ - i = (etd->fw_version > 0x020800 && - etd->fw_version < 0x020900) ? 1 : 2; -- *x_min = 0; -- *y_min = 0; -- *x_max = (etd->capabilities[1] - i) * 64; -- *y_max = (etd->capabilities[2] - i) * 64; -+ -+ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) -+ return -1; -+ -+ fixed_dpi = param[1] & 0x10; -+ -+ if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) { -+ if (synaptics_send_cmd(psmouse, ETP_SAMPLE_QUERY, param)) -+ return -1; -+ -+ *x_max = (etd->capabilities[1] - i) * param[1] / 2; -+ *y_max = (etd->capabilities[2] - i) * param[2] / 2; -+ } else if (etd->fw_version == 0x040216) { -+ *x_max = 819; -+ *y_max = 405; -+ } else if (etd->fw_version == 0x040219 || etd->fw_version == 0x040215) { -+ *x_max = 900; -+ *y_max = 500; -+ } else { -+ *x_max = (etd->capabilities[1] - i) * 64; -+ *y_max = (etd->capabilities[2] - i) * 64; -+ } - } - break; - -diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h -index 7ecaef0..9e5f1aa 100644 ---- a/drivers/input/mouse/elantech.h -+++ b/drivers/input/mouse/elantech.h -@@ -19,6 +19,7 @@ - #define ETP_FW_ID_QUERY 0x00 - #define ETP_FW_VERSION_QUERY 0x01 - #define ETP_CAPABILITIES_QUERY 0x02 -+#define ETP_SAMPLE_QUERY 0x03 - - /* - * Command values for register reading or writing --- -1.7.6.4 - - -From 6c0ec284648f0346e96b0079999cb7af055f58ab Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Tue, 20 Sep 2011 22:42:51 -0700 -Subject: Input: elantech - remove module parameter force_elantech -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This essentially reverts commit f81bc788ff91d4efd4baf88b2c29713838caa8e5. - -With recent work on elantech driver, I believe we now have complete support -for all elantech touchpads. So remove this hack. - -Signed-off-by: JJ Ding -Reviewed-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.c | 12 ++---------- - 1 files changed, 2 insertions(+), 10 deletions(-) - -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index c2d91eb..25290b3 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -28,10 +28,6 @@ - printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \ - } while (0) - --static bool force_elantech; --module_param_named(force_elantech, force_elantech, bool, 0644); --MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default)."); -- - /* - * Send a Synaptics style sliced query command - */ -@@ -1164,12 +1160,8 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) - param[0], param[1], param[2]); - - if (!elantech_is_signature_valid(param)) { -- if (!force_elantech) { -- pr_debug("Probably not a real Elantech touchpad. Aborting.\n"); -- return -1; -- } -- -- pr_debug("Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n"); -+ pr_debug("Probably not a real Elantech touchpad. Aborting.\n"); -+ return -1; - } - - if (set_properties) { --- -1.7.6.4 - -From 3940d6185a982a970ff562e085caccbdd62f40bb Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Tue, 8 Nov 2011 22:13:14 -0800 -Subject: [PATCH] Input: elantech - adjust hw_version detection logic -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This patch fixes some v3 hardware (fw_version: 0x150500) wrongly detected -as v2 hardware. - -Reported-by: Marc Dietrich -Signed-off-by: JJ Ding -Tested-By: Marc Dietrich -Acked-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.c | 26 ++++++++++++++++++-------- - 1 files changed, 18 insertions(+), 8 deletions(-) - -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index 09b93b1..e2a9867 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -1210,18 +1210,28 @@ static int elantech_reconnect(struct psmouse *psmouse) - */ - static int elantech_set_properties(struct elantech_data *etd) - { -+ /* This represents the version of IC body. */ - int ver = (etd->fw_version & 0x0f0000) >> 16; - -+ /* Early version of Elan touchpads doesn't obey the rule. */ - if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) - etd->hw_version = 1; -- else if (etd->fw_version < 0x150600) -- etd->hw_version = 2; -- else if (ver == 5) -- etd->hw_version = 3; -- else if (ver == 6) -- etd->hw_version = 4; -- else -- return -1; -+ else { -+ switch (ver) { -+ case 2: -+ case 4: -+ etd->hw_version = 2; -+ break; -+ case 5: -+ etd->hw_version = 3; -+ break; -+ case 6: -+ etd->hw_version = 4; -+ break; -+ default: -+ return -1; -+ } -+ } - - /* - * Turn on packet checking by default. --- -1.7.7.3 - diff --git a/epoll-limit-paths.patch b/epoll-limit-paths.patch index 440db27b9..4ed306af4 100644 --- a/epoll-limit-paths.patch +++ b/epoll-limit-paths.patch @@ -1,4 +1,4 @@ -From 6a4ca79652219cf22da800d990e5b46feaea1ad9 Mon Sep 17 00:00:00 2001 +From 0a6cc45426fe3baaf231efd7efe4300fd879efc8 Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Mon, 24 Oct 2011 14:59:02 +1100 Subject: [PATCH] epoll: limit paths @@ -91,7 +91,7 @@ Signed-off-by: Andrew Morton 3 files changed, 203 insertions(+), 25 deletions(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c -index 4a53743..414ac74 100644 +index b84fad9..414ac74 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -197,6 +197,12 @@ struct eventpoll { @@ -137,7 +137,7 @@ index 4a53743..414ac74 100644 .llseek = noop_llseek, }; --/* Fast test to see if the file is an evenpoll file */ +-/* Fast test to see if the file is an eventpoll file */ -static inline int is_file_epoll(struct file *f) -{ - return f->f_op == &eventpoll_fops; @@ -449,7 +449,7 @@ index f362733..657ab55 100644 diff --git a/include/linux/fs.h b/include/linux/fs.h -index 277f497..93778e0 100644 +index ba98668..d393a68 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -985,6 +985,7 @@ struct file { diff --git a/ext4-Support-check-none-nocheck-mount-options.patch b/ext4-Support-check-none-nocheck-mount-options.patch new file mode 100644 index 000000000..281e4237a --- /dev/null +++ b/ext4-Support-check-none-nocheck-mount-options.patch @@ -0,0 +1,51 @@ +From ea75f7357e3a881bd1bd0db5e483fc6a8681567b Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Tue, 10 Jan 2012 09:39:02 -0500 +Subject: [PATCH] ext4: Support "check=none" "nocheck" mount options + +The ext2/ext3 filesystems supported "check=none" and "nocheck" as mount options +even though that was already the default behavior and it essentially did +nothing. When using ext4 to mount ext2/ext3 filesystems, that mount option +causes the mount to fail. That isn't as backward compatible as it could be, +so add support to ext4 to accept the option. + +Signed-off-by: Josh Boyer +--- + fs/ext4/super.c | 7 ++++++- + 1 files changed, 6 insertions(+), 1 deletions(-) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 3e1329e..5ff09e7 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -1333,7 +1333,7 @@ enum { + Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, + Opt_inode_readahead_blks, Opt_journal_ioprio, + Opt_dioread_nolock, Opt_dioread_lock, +- Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable, ++ Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable, Opt_nocheck, + }; + + static const match_table_t tokens = { +@@ -1409,6 +1409,8 @@ static const match_table_t tokens = { + {Opt_init_itable, "init_itable=%u"}, + {Opt_init_itable, "init_itable"}, + {Opt_noinit_itable, "noinit_itable"}, ++ {Opt_nocheck, "check=none"}, ++ {Opt_nocheck, "nocheck"}, + {Opt_err, NULL}, + }; + +@@ -1905,6 +1907,9 @@ set_qf_format: + case Opt_noinit_itable: + clear_opt(sb, INIT_INODE_TABLE); + break; ++ case Opt_nocheck: ++ /* ext2/ext3 used to "support" this option. Silently eat it */ ++ break; + default: + ext4_msg(sb, KERN_ERR, + "Unrecognized mount option \"%s\" " +-- +1.7.7.5 + diff --git a/fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch b/fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch new file mode 100644 index 000000000..5bab4f4ad --- /dev/null +++ b/fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch @@ -0,0 +1,106 @@ +Path: news.gmane.org!not-for-mail +From: Niels de Vos +Newsgroups: gmane.linux.kernel,gmane.linux.file-systems +Subject: [PATCH v2] fs: Invalidate the cache for a parent block-device if fsync() is called for a partition +Date: Mon, 23 Jan 2012 10:38:29 +0000 +Lines: 58 +Approved: news@gmane.org +Message-ID: <1327315109-7740-1-git-send-email-ndevos@redhat.com> +References: <4F19356E.3020708@redhat.com> +NNTP-Posting-Host: lo.gmane.org +X-Trace: dough.gmane.org 1327315263 30652 80.91.229.12 (23 Jan 2012 10:41:03 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Mon, 23 Jan 2012 10:41:03 +0000 (UTC) +Cc: linux-kernel@vger.kernel.org, Niels de Vos , + "Bryn M. Reeves" , + Mikulas Patocka +To: linux-fsdevel@vger.kernel.org +Original-X-From: linux-kernel-owner@vger.kernel.org Mon Jan 23 11:40:58 2012 +Return-path: +Envelope-to: glk-linux-kernel-3@lo.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1RpHKb-0008Bu-Fh + for glk-linux-kernel-3@lo.gmane.org; Mon, 23 Jan 2012 11:40:57 +0100 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1753263Ab2AWKkt (ORCPT ); + Mon, 23 Jan 2012 05:40:49 -0500 +Original-Received: from mx1.redhat.com ([209.132.183.28]:58739 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1751990Ab2AWKks (ORCPT ); + Mon, 23 Jan 2012 05:40:48 -0500 +Original-Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q0NAelMx027033 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Mon, 23 Jan 2012 05:40:47 -0500 +Original-Received: from ndevos.usersys.redhat.com (dhcp-1-51.fab.redhat.com [10.33.1.51]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q0NAejLn013691; + Mon, 23 Jan 2012 05:40:46 -0500 +In-Reply-To: <4F19356E.3020708@redhat.com> +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Original-Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel:1242432 gmane.linux.file-systems:60751 +Archived-At: + +Executing an fsync() on a file-descriptor of a partition flushes the +caches for that partition by calling blkdev_issue_flush(). However, it +seems that reading data through the parent device will still return the +old cached data. + +The cache for the block-device is not synced if the block-device is kept +open (due to a mounted partition, for example). Only when all users for +the disk have exited, the cache for the disk is made consistent again. + +Calling invalidate_bdev() on the parent block-device in case +blkdev_fsync() was called for a partition, fixes this. + +The problem can be worked around by forcing the caches to be flushed +with either + # blockdev --flushbufs ${dev_disk} +or + # echo 3 > /proc/sys/vm/drop_caches + +CC: Bryn M. Reeves +CC: Mikulas Patocka +Signed-off-by: Niels de Vos + +--- +v2: +- Do not call invalidate_bdev() from blkdev_issue_flush() and prevent + performance degration with journalled filesystems. + + Suggested was to call invalidate_bdev() in fsync_bdev(), but this is + not in the call-path of mkfs.ext3 and similar tools. Hence the issue + persists. + +- Correct phrasing a little, changing ioctl-BLKFLSBUF is not required. + +- This issue also occurs when doing an ioctl-BLKFLSBUF on a partition. + Reading the whole disk will still return cached data. If this is an + issue, it will need a seperate patch. +--- + fs/block_dev.c | 4 ++++ + 1 files changed, 4 insertions(+), 0 deletions(-) + +diff --git a/fs/block_dev.c b/fs/block_dev.c +index 0e575d1..433c4de 100644 +--- a/fs/block_dev.c ++++ b/fs/block_dev.c +@@ -424,6 +424,10 @@ int blkdev_fsync(struct file *filp, loff_t start, loff_t end, int datasync) + if (error == -EOPNOTSUPP) + error = 0; + ++ /* invalidate parent block_device */ ++ if (!error && bdev != bdev->bd_contains) ++ invalidate_bdev(bdev->bd_contains); ++ + return error; + } + EXPORT_SYMBOL(blkdev_fsync); +-- +1.7.6.5 + diff --git a/hvcs_pi_buf_alloc.patch b/hvcs_pi_buf_alloc.patch deleted file mode 100644 index ecabe49b1..000000000 --- a/hvcs_pi_buf_alloc.patch +++ /dev/null @@ -1,43 +0,0 @@ - -The Power platform requires the partner info buffer to be page aligned -otherwise it will fail the partner info hcall with H_PARAMETER. Switch -from using kmalloc to allocate this buffer to __get_free_page to ensure -page alignment. - -Signed-off-by: Brian King ---- - - drivers/tty/hvc/hvcs.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff -puN drivers/tty/hvc/hvcs.c~hvcs_pi_buf_alloc drivers/tty/hvc/hvcs.c ---- linux-2.6/drivers/tty/hvc/hvcs.c~hvcs_pi_buf_alloc 2011-09-09 16:00:25.000000000 -0500 -+++ linux-2.6-bjking1/drivers/tty/hvc/hvcs.c 2011-09-09 16:07:08.000000000 -0500 -@@ -1532,7 +1532,7 @@ static int __devinit hvcs_initialize(voi - goto register_fail; - } - -- hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL); -+ hvcs_pi_buff = (unsigned long *) __get_free_page(GFP_KERNEL); - if (!hvcs_pi_buff) { - rc = -ENOMEM; - goto buff_alloc_fail; -@@ -1548,7 +1548,7 @@ static int __devinit hvcs_initialize(voi - return 0; - - kthread_fail: -- kfree(hvcs_pi_buff); -+ free_page((unsigned long)hvcs_pi_buff); - buff_alloc_fail: - tty_unregister_driver(hvcs_tty_driver); - register_fail: -@@ -1597,7 +1597,7 @@ static void __exit hvcs_module_exit(void - kthread_stop(hvcs_task); - - spin_lock(&hvcs_pi_lock); -- kfree(hvcs_pi_buff); -+ free_page((unsigned long)hvcs_pi_buff); - hvcs_pi_buff = NULL; - spin_unlock(&hvcs_pi_lock); - -_ diff --git a/kernel.spec b/kernel.spec index 9d2d7da07..848a58fa0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,16 +42,16 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with -%define real_sublevel 1 +%define real_sublevel 2 # fake_sublevel is the 2.6.x version we're faking %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # Do we have a -stable update to apply? -%define stable_update 10 +%define stable_update 2 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -472,7 +472,7 @@ Version: %{rpmversion} Release: %{pkg_release} # DO NOT CHANGE THE 'ExclusiveArch' LINE TO TEMPORARILY EXCLUDE AN ARCHITECTURE BUILD. # SET %%nobuildarches (ABOVE) INSTEAD -ExclusiveArch: noarch %{all_x86} x86_64 ppc ppc64 ia64 %{sparc} s390 s390x alpha alphaev56 %{arm} +ExclusiveArch: noarch %{all_x86} x86_64 ppc ppc64 %{sparc} s390 s390x alpha alphaev56 %{arm} ExclusiveOS: Linux %kernel_reqprovconf @@ -481,7 +481,7 @@ ExclusiveOS: Linux # List the packages used during the kernel build # BuildRequires: module-init-tools, patch >= 2.5.4, bash >= 2.03, sh-utils, tar -BuildRequires: bzip2, findutils, gzip, m4, perl, make >= 3.78, diffutils, gawk +BuildRequires: bzip2, xz, findutils, gzip, m4, perl, make >= 3.78, diffutils, gawk BuildRequires: gcc >= 3.4.2, binutils >= 2.12, redhat-rpm-config BuildRequires: net-tools BuildRequires: xmlto, asciidoc @@ -506,7 +506,7 @@ BuildRequires: rpm-build >= 4.4.2.1-4 %define debuginfo_args --strict-build-id %endif -Source0: ftp://ftp.kernel.org/pub/linux/kernel/v3.x/linux-%{realversion}.tar.bz2 +Source0: ftp://ftp.kernel.org/pub/linux/kernel/v3.x/linux-%{realversion}.tar.xz Source11: genkey Source14: find-provides @@ -549,11 +549,11 @@ Source1000: config-local # For a stable release kernel %if 0%{?stable_update} %if 0%{?stable_base} -%define stable_patch_00 patch-3.%{real_sublevel}.%{stable_base}.bz2 +%define stable_patch_00 patch-3.%{real_sublevel}.%{stable_base}.xz Patch00: %{stable_patch_00} %endif %if 0%{?stable_rc} -%define stable_patch_01 patch-3.%{real_sublevel}.%{stable_update}-rc%{stable_rc}.bz2 +%define stable_patch_01 patch-3.%{real_sublevel}.%{stable_update}-rc%{stable_rc}.xz Patch01: %{stable_patch_01} %endif %endif @@ -580,8 +580,6 @@ Patch100: taint-vbox.patch Patch160: linux-2.6-32bit-mmap-exec-randomization.patch Patch161: linux-2.6-i386-nx-emulation.patch -Patch202: linux-2.6-debug-taint-vm.patch - Patch350: force-version-2.6.patch Patch383: linux-2.6-defaults-aspm.patch @@ -608,9 +606,6 @@ Patch700: linux-2.6-e1000-ich9-montevina.patch Patch800: linux-2.6-crash-driver.patch -# Platform -Patch900: samsung-laptop-brightness-fixes-3.2.patch - # crypto/ # virt + ksm patches @@ -624,10 +619,6 @@ Patch1810: drm-nouveau-updates.patch Patch1824: drm-intel-next.patch # hush the i915 fbc noise Patch1826: drm-i915-fbc-stfu.patch -# rhbz#729882, https://bugs.freedesktop.org/attachment.cgi?id=49069 -Patch1827: drm-i915-sdvo-lvds-is-digital.patch - -Patch1850: drm-lower-severity-radeon-lockup.diff Patch1900: linux-2.6-intel-iommu-igfx.patch @@ -640,10 +631,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 -Patch2905: media-dib0700-correct-error-message.patch - -Patch3000: rcutree-avoid-false-quiescent-states.patch - # fs fixes #rhbz 753346 @@ -652,41 +639,22 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 # patches headed upstream -Patch12010: add-appleir-usb-driver.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch12021: udlfb-bind-framebuffer-to-interface.patch - -Patch12025: rcu-avoid-just-onlined-cpu-resched.patch Patch12026: block-stray-block-put-after-teardown.patch Patch12030: epoll-limit-paths.patch -Patch12031: HID-wacom-Set-input-bits-before-registration.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13002: revert-efi-rtclock.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch -Patch13009: hvcs_pi_buf_alloc.patch - Patch20000: utrace.patch # Flattened devicetree support Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch -Patch21002: arm-tegra-usb-no-reset.patch - -#rhbz #735946 -Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch -Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch -Patch21022: mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch - -#rhbz 748691 -Patch21030: be2net-non-member-vlan-pkts-not-received-in-promisco.patch -Patch21031: benet-remove-bogus-unlikely-on-vlan-check.patch - -Patch21040: x86-code-dump-fix-truncation.patch #rhbz 717735 Patch21045: nfs-client-freezer.patch @@ -694,18 +662,10 @@ Patch21045: nfs-client-freezer.patch #rhbz 590880 Patch21046: alps.patch -#rhbz 741117 -Patch21048: b44-Use-dev_kfree_skb_irq-in-b44_tx.patch - -#rhbz 771006 -Patch21050: thp-reduce-khugepaged-freezing-latency.patch - -#rhbz 728607 -Patch21060: elantech.patch - -#rhbz 770233 -Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch +#rhbz 746097 +Patch21049: tpm_tis-delay-after-aborting-cmd.patch +Patch21070: ext4-Support-check-none-nocheck-mount-options.patch Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch Patch21072: ext3-Fix-error-handling-on-inode-bitmap-corruption.patch @@ -719,41 +679,31 @@ Patch21075: KVM-x86-fix-missing-checks-in-syscall-emulation.patch #rhbz 728740 Patch21076: rtl8192cu-Fix-WARNING-on-suspend-resume.patch -Patch21077: 01-block-add-and-use-scsi_blk_cmd_ioctl.patch -Patch21078: 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch -Patch21079: 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch +#rhbz752176 +Patch21080: sysfs-msi-irq-per-device.patch #rhbz 782686 Patch21082: procfs-parse-mount-options.patch Patch21083: procfs-add-hidepid-and-gid-mount-options.patch Patch21084: proc-fix-null-pointer-deref-in-proc_pid_permission.patch -#rhbz 782681 -Patch21085: proc-clean-up-and-fix-proc-pid-mem-handling.patch +#rhbz 783211 +Patch21087: fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch -#rhbz 782687 -Patch21086: loop-prevent-information-leak-after-failed-read.patch - -#backport brcm80211 from 3.2-rc1 -Patch21090: brcm80211.patch -Patch21091: bcma-brcmsmac-compat.patch +#rhbz 771058 +Patch21100: msi-irq-sysfs-warning.patch # rhbz 754907 -Patch21100: cciss-fix-irqf-shared.patch Patch21101: hpsa-add-irqf-shared.patch -#rhbz 731365 -Patch21220: mac80211_offchannel_rework_revert.patch - Patch21225: pci-Rework-ASPM-disable-code.patch Patch21227: mac80211-fix-work-removal-on-deauth-request.patch -#rhbz 781625 -Patch21228: SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch +#rhbz 718790 +Patch21230: rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch -#rhbz #757839 -Patch21230: net-sky2-88e8059-fix-link-speed.patch +Patch22000: rcu-reintroduce-missing-calls.patch %endif @@ -1027,6 +977,7 @@ ApplyPatch() case "$patch" in *.bz2) bunzip2 < "$RPM_SOURCE_DIR/$patch" | $patch_command ${1+"$@"} ;; *.gz) gunzip < "$RPM_SOURCE_DIR/$patch" | $patch_command ${1+"$@"} ;; + *.xz) unxz < "$RPM_SOURCE_DIR/$patch" | $patch_command ${1+"$@"} ;; *) $patch_command ${1+"$@"} < "$RPM_SOURCE_DIR/$patch" ;; esac } @@ -1177,7 +1128,6 @@ ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R # ApplyPatch arm-omap-dt-compat.patch ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch -ApplyPatch arm-tegra-usb-no-reset.patch ApplyPatch taint-vbox.patch # @@ -1217,9 +1167,6 @@ ApplyPatch acpi-sony-nonvs-blacklist.patch # force UTSNAME to show version 2.6.4X ApplyPatch force-version-2.6.patch -# Various low-impact patches to aid debugging. -ApplyPatch linux-2.6-debug-taint-vm.patch - # # PCI # @@ -1278,9 +1225,6 @@ ApplyOptionalPatch drm-nouveau-updates.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch ApplyPatch drm-i915-fbc-stfu.patch -ApplyPatch drm-i915-sdvo-lvds-is-digital.patch - -ApplyPatch drm-lower-severity-radeon-lockup.diff ApplyPatch linux-2.6-intel-iommu-igfx.patch @@ -1294,21 +1238,12 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-fixes.patch ApplyOptionalPatch linux-2.6-v4l-dvb-update.patch ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch -# Platform fixes not sent for -stable -ApplyPatch samsung-laptop-brightness-fixes-3.2.patch - # Patches headed upstream -ApplyPatch rcutree-avoid-false-quiescent-states.patch ApplyPatch disable-i8042-check-on-apple-mac.patch -ApplyPatch add-appleir-usb-driver.patch - -ApplyPatch udlfb-bind-framebuffer-to-interface.patch ApplyPatch epoll-limit-paths.patch -ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch ApplyPatch block-stray-block-put-after-teardown.patch -ApplyPatch HID-wacom-Set-input-bits-before-registration.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -1316,62 +1251,32 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch revert-efi-rtclock.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch -ApplyPatch hvcs_pi_buf_alloc.patch - -ApplyPatch media-dib0700-correct-error-message.patch - # utrace. ApplyPatch utrace.patch -#rhbz #735946 -ApplyPatch 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch -ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch -ApplyPatch mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch - -#rhbz 748691 -ApplyPatch be2net-non-member-vlan-pkts-not-received-in-promisco.patch -ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch - -#rhbz 736815 -ApplyPatch x86-code-dump-fix-truncation.patch - -#rhbz 728607 -ApplyPatch elantech.patch - -#backport brcm80211 from 3.2-rc1 -ApplyPatch brcm80211.patch -# Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 -ApplyPatch bcma-brcmsmac-compat.patch +#rhbz 752176 +ApplyPatch sysfs-msi-irq-per-device.patch # rhbz 754907 -ApplyPatch cciss-fix-irqf-shared.patch ApplyPatch hpsa-add-irqf-shared.patch -#rhbz 731365 -ApplyPatch mac80211_offchannel_rework_revert.patch - ApplyPatch pci-Rework-ASPM-disable-code.patch ApplyPatch mac80211-fix-work-removal-on-deauth-request.patch -#rhbz #757839 -ApplyPatch net-sky2-88e8059-fix-link-speed.patch - #rhbz 717735 ApplyPatch nfs-client-freezer.patch #rhbz 590880 ApplyPatch alps.patch -#rhbz 741117 -ApplyPatch b44-Use-dev_kfree_skb_irq-in-b44_tx.patch +#rhbz 746097 +ApplyPatch tpm_tis-delay-after-aborting-cmd.patch -#rhbz 771006 -ApplyPatch thp-reduce-khugepaged-freezing-latency.patch - -#rhbz 770233 -ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch +#rhbz 771058 +ApplyPatch msi-irq-sysfs-warning.patch +ApplyPatch ext4-Support-check-none-nocheck-mount-options.patch ApplyPatch ext4-Fix-error-handling-on-inode-bitmap-corruption.patch ApplyPatch ext3-Fix-error-handling-on-inode-bitmap-corruption.patch @@ -1382,24 +1287,18 @@ ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch #rhbz 728740 ApplyPatch rtl8192cu-Fix-WARNING-on-suspend-resume.patch -#rhbz 769911 -ApplyPatch 01-block-add-and-use-scsi_blk_cmd_ioctl.patch -ApplyPatch 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch -ApplyPatch 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch - #rhbz 782686 ApplyPatch procfs-parse-mount-options.patch ApplyPatch procfs-add-hidepid-and-gid-mount-options.patch ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch -#rhbz 782681 -ApplyPatch proc-clean-up-and-fix-proc-pid-mem-handling.patch +ApplyPatch rcu-reintroduce-missing-calls.patch -#rhbz 782687 -ApplyPatch loop-prevent-information-leak-after-failed-read.patch +#rhbz 718790 +ApplyPatch rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch -#rhbz 781625 -ApplyPatch SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch +#rhbz 783211 +ApplyPatch fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch # END OF PATCH APPLICATIONS @@ -2048,6 +1947,9 @@ fi # and build. %changelog +* Mon Jan 30 2012 Dave Jones 2.6.42.2-1 +- Rebase to 3.2.2 + * Mon Jan 23 2012 Josh Boyer 2.6.41.10-3 - Fix NULL pointer dereference in sym53c8xx module (rhbz 781625) diff --git a/linux-2.6-32bit-mmap-exec-randomization.patch b/linux-2.6-32bit-mmap-exec-randomization.patch index 6008173b0..c25323323 100644 --- a/linux-2.6-32bit-mmap-exec-randomization.patch +++ b/linux-2.6-32bit-mmap-exec-randomization.patch @@ -152,7 +152,7 @@ Main executable randomisation (PIE) : 12 bits (guessed) struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) --- a/arch/x86/mm/mmap.c +++ b/arch/x86/mm/mmap.c -@@ -124,13 +124,16 @@ static unsigned long mmap_legacy_base(void) +@@ -124,13 +124,19 @@ static unsigned long mmap_legacy_base(void) */ void arch_pick_mmap_layout(struct mm_struct *mm) { @@ -163,9 +163,12 @@ Main executable randomisation (PIE) : 12 bits (guessed) } else { mm->mmap_base = mmap_base(); mm->get_unmapped_area = arch_get_unmapped_area_topdown; ++#ifdef CONFIG_X86_32 + if (!(current->personality & READ_IMPLIES_EXEC) ++ && !(__supported_pte_mask & _PAGE_NX) + && mmap_is_ia32()) + mm->get_unmapped_exec_area = arch_get_unmapped_exec_area; ++#endif mm->unmap_area = arch_unmap_area_topdown; } } @@ -224,3 +227,25 @@ Main executable randomisation (PIE) : 12 bits (guessed) if (new_addr & ~PAGE_MASK) { ret = new_addr; goto out; +diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c +index 57d1868..29c0c35 100644 +--- a/arch/x86/kernel/process.c ++++ b/arch/x86/kernel/process.c +@@ -669,6 +669,16 @@ unsigned long arch_align_stack(unsigned long sp) + unsigned long arch_randomize_brk(struct mm_struct *mm) + { + unsigned long range_end = mm->brk + 0x02000000; +- return randomize_range(mm->brk, range_end, 0) ? : mm->brk; ++ unsigned long bump = 0; ++#ifdef CONFIG_X86_32 ++ /* in the case of NX emulation, shove the brk segment way out of the ++ way of the exec randomization area, since it can collide with ++ future allocations if not. */ ++ if ( (mm->get_unmapped_exec_area == arch_get_unmapped_exec_area) && ++ (mm->brk < 0x08000000) ) { ++ bump = (TASK_SIZE/6); ++ } ++#endif ++ return bump + (randomize_range(mm->brk, range_end, 0) ? : mm->brk); + } + diff --git a/linux-2.6-debug-taint-vm.patch b/linux-2.6-debug-taint-vm.patch deleted file mode 100644 index 672509db2..000000000 --- a/linux-2.6-debug-taint-vm.patch +++ /dev/null @@ -1,51 +0,0 @@ -diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index 4e8985a..70d0853 100644 ---- a/mm/page_alloc.c -+++ b/mm/page_alloc.c -@@ -318,6 +318,7 @@ static void bad_page(struct page *page) - current->comm, page_to_pfn(page)); - dump_page(page); - -+ print_modules(); - dump_stack(); - out: - /* Leave bad fields for debug, except PageBuddy could make trouble */ -diff --git a/mm/slab.c b/mm/slab.c -index d96e223..6f8905b 100644 ---- a/mm/slab.c -+++ b/mm/slab.c -@@ -1886,8 +1886,8 @@ static void check_poison_obj(struct kmem_cache *cachep, void *objp) - /* Print header */ - if (lines == 0) { - printk(KERN_ERR -- "Slab corruption: %s start=%p, len=%d\n", -- cachep->name, realobj, size); -+ "Slab corruption (%s): %s start=%p, len=%d\n", -+ print_tainted(), cachep->name, realobj, size); - print_objinfo(cachep, objp, 0); - } - /* Hexdump the affected line */ -@@ -2985,8 +2985,8 @@ static void check_slabp(struct kmem_cache *cachep, struct slab *slabp) - if (entries != cachep->num - slabp->inuse) { - bad: - printk(KERN_ERR "slab: Internal list corruption detected in " -- "cache '%s'(%d), slabp %p(%d). Hexdump:\n", -- cachep->name, cachep->num, slabp, slabp->inuse); -+ "cache '%s'(%d), slabp %p(%d). Tainted(%s). Hexdump:\n", -+ cachep->name, cachep->num, slabp, slabp->inuse, print_tainted()); - for (i = 0; - i < sizeof(*slabp) + cachep->num * sizeof(kmem_bufctl_t); - i++) { -diff --git a/mm/slub.c b/mm/slub.c -index 35f351f..e7ccb39 100644 ---- a/mm/slub.c -+++ b/mm/slub.c -@@ -472,7 +472,7 @@ static void slab_bug(struct kmem_cache *s, char *fmt, ...) - va_end(args); - printk(KERN_ERR "========================================" - "=====================================\n"); -- printk(KERN_ERR "BUG %s: %s\n", s->name, buf); -+ printk(KERN_ERR "BUG %s (%s): %s\n", s->name, print_tainted(), buf); - printk(KERN_ERR "----------------------------------------" - "-------------------------------------\n\n"); - } diff --git a/linux-2.6-e1000-ich9-montevina.patch b/linux-2.6-e1000-ich9-montevina.patch index d45fd5673..ec38a3902 100644 --- a/linux-2.6-e1000-ich9-montevina.patch +++ b/linux-2.6-e1000-ich9-montevina.patch @@ -1,11 +1,22 @@ +From 802e6d8c8477a553a677b23a247d6d2638e01958 Mon Sep 17 00:00:00 2001 +From: Dave Jones +Date: Wed, 26 Oct 2011 13:31:47 -0400 +Subject: [PATCH] e1000e: ich9 montevina + This only showed up in one SDV (Montevina). The PCIE slots don't seem to like network cards, so this is the only hope to get networking working. It's never going upstream, but it's low impact enough to carry just to keep those SDVs working. +--- + drivers/net/ethernet/intel/e1000e/ich8lan.c | 6 ++++++ + drivers/net/ethernet/intel/e1000e/netdev.c | 1 + + 2 files changed, 7 insertions(+), 0 deletions(-) ---- linux-2.6.35.noarch/drivers/net/e1000e/ich8lan.c~ 2010-09-29 17:53:13.000000000 -0400 -+++ linux-2.6.35.noarch/drivers/net/e1000e/ich8lan.c 2010-09-29 17:54:00.000000000 -0400 -@@ -424,6 +424,12 @@ static s32 e1000_init_phy_params_ich8lan +diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c +index 6a17c62..0e40975 100644 +--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c ++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c +@@ -452,6 +452,12 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) /* Verify phy id */ switch (phy->id) { @@ -18,9 +29,11 @@ enough to carry just to keep those SDVs working. case IGP03E1000_E_PHY_ID: phy->type = e1000_phy_igp_3; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; ---- linux-2.6.35.noarch/drivers/net/e1000e/netdev.c~ 2010-09-29 17:54:07.000000000 -0400 -+++ linux-2.6.35.noarch/drivers/net/e1000e/netdev.c 2010-09-29 17:54:29.000000000 -0400 -@@ -5994,6 +5994,7 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci +diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c +index a855db1..edac30b 100644 +--- a/drivers/net/ethernet/intel/e1000e/netdev.c ++++ b/drivers/net/ethernet/intel/e1000e/netdev.c +@@ -6359,6 +6359,7 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M), board_ich9lan }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_AMT), board_ich9lan }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_V), board_ich9lan }, @@ -28,3 +41,6 @@ enough to carry just to keep those SDVs working. { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LM), board_ich9lan }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LF), board_ich9lan }, +-- +1.7.6.4 + diff --git a/linux-2.6-i386-nx-emulation.patch b/linux-2.6-i386-nx-emulation.patch index fb58c612e..07a0faec8 100644 --- a/linux-2.6-i386-nx-emulation.patch +++ b/linux-2.6-i386-nx-emulation.patch @@ -592,25 +592,3 @@ mmu_notifier_invalidate_range_start(mm, start, end); if (is_vm_hugetlb_page(vma)) hugetlb_change_protection(vma, start, end, vma->vm_page_prot); -diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c -index 57d1868..29c0c35 100644 ---- a/arch/x86/kernel/process.c -+++ b/arch/x86/kernel/process.c -@@ -669,6 +669,16 @@ unsigned long arch_align_stack(unsigned long sp) - unsigned long arch_randomize_brk(struct mm_struct *mm) - { - unsigned long range_end = mm->brk + 0x02000000; -- return randomize_range(mm->brk, range_end, 0) ? : mm->brk; -+ unsigned long bump = 0; -+#ifdef CONFIG_X86_32 -+ /* in the case of NX emulation, shove the brk segment way out of the -+ way of the exec randomization area, since it can collide with -+ future allocations if not. */ -+ if ( (mm->get_unmapped_exec_area == arch_get_unmapped_exec_area) && -+ (mm->brk < 0x08000000) ) { -+ bump = (TASK_SIZE/6); -+ } -+#endif -+ return bump + (randomize_range(mm->brk, range_end, 0) ? : mm->brk); - } - diff --git a/linux-2.6-intel-iommu-igfx.patch b/linux-2.6-intel-iommu-igfx.patch index b2f8f19e3..3a45abaec 100644 --- a/linux-2.6-intel-iommu-igfx.patch +++ b/linux-2.6-intel-iommu-igfx.patch @@ -1,6 +1,7 @@ -Subject: [PATCH] [intel_iommu] Default to igfx_off +From 602e1f209dd983e40d989e871cd253e8187899b8 Mon Sep 17 00:00:00 2001 From: drago01 -To: fedora-kernel-list +Date: Wed, 26 Oct 2011 13:37:27 -0400 +Subject: [PATCH] Default to igfx_off This option seems to causes way to many issues, it is being investigated by Intel's chipset team for months now and @@ -16,14 +17,14 @@ Signed-off-by: Adel Gadllah Reviewed-by: Adam Jackson --- Documentation/kernel-parameters.txt | 11 +++++------ - drivers/pci/intel-iommu.c | 9 +++++---- + drivers/iommu/intel-iommu.c | 9 +++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index e7848a0..9914485 100644 +index 81c287f..ee5693b 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt -@@ -992,12 +992,11 @@ and is between 256 and 4096 characters. It is defined in the file +@@ -1014,12 +1014,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Enable intel iommu driver. off Disable intel iommu driver. @@ -40,22 +41,22 @@ index e7848a0..9914485 100644 + mapped as normal device. forcedac [x86_64] With this option iommu will not optimize to look - for io virtual address below 32 bit forcing dual -diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c -index 4173125..8f36786 100644 + for io virtual address below 32-bit forcing dual +diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c +index bdc447f..240db6b 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c -@@ -340,7 +340,8 @@ int dmar_disabled = 0; - int dmar_disabled = 1; - #endif /*CONFIG_DMAR_DEFAULT_ON*/ - +@@ -408,7 +408,8 @@ int dmar_disabled = 1; + int intel_iommu_enabled = 0; + EXPORT_SYMBOL_GPL(intel_iommu_enabled); + -static int dmar_map_gfx = 1; +/* disabled by default; causes way too many issues */ +static int dmar_map_gfx = 0; static int dmar_forcedac; static int intel_iommu_strict; - -@@ -361,10 +362,10 @@ static int __init intel_iommu_setup(char *str) + static int intel_iommu_superpage = 1; +@@ -433,10 +434,10 @@ static int __init intel_iommu_setup(char *str) } else if (!strncmp(str, "off", 3)) { dmar_disabled = 1; printk(KERN_INFO "Intel-IOMMU: disabled\n"); @@ -70,9 +71,5 @@ index 4173125..8f36786 100644 printk(KERN_INFO "Intel-IOMMU: Forcing DAC for PCI devices\n"); -- -1.6.6.1 -_______________________________________________ -kernel mailing list -kernel@lists.fedoraproject.org -https://admin.fedoraproject.org/mailman/listinfo/kernel +1.7.7.4 diff --git a/loop-prevent-information-leak-after-failed-read.patch b/loop-prevent-information-leak-after-failed-read.patch deleted file mode 100644 index 040a234c3..000000000 --- a/loop-prevent-information-leak-after-failed-read.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 3bb9068278ea524581237abadd41377a14717e7d Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov -Date: Wed, 16 Nov 2011 09:21:48 +0100 -Subject: [PATCH] loop: prevent information leak after failed read - -If read was not fully successful we have to fail whole bio to prevent -information leak of old pages - -##Testcase_begin -dd if=/dev/zero of=./file bs=1M count=1 -losetup /dev/loop0 ./file -o 4096 -truncate -s 0 ./file -# OOps loop offset is now beyond i_size, so read will silently fail. -# So bio's pages would not be cleared, may which result in information leak. -hexdump -C /dev/loop0 -##testcase_end - -Signed-off-by: Dmitry Monakhov -Signed-off-by: Andrew Morton -Signed-off-by: Jens Axboe ---- - drivers/block/loop.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/drivers/block/loop.c b/drivers/block/loop.c -index 3d80682..0d56739 100644 ---- a/drivers/block/loop.c -+++ b/drivers/block/loop.c -@@ -372,7 +372,8 @@ do_lo_receive(struct loop_device *lo, - - if (retval < 0) - return retval; -- -+ if (retval != bvec->bv_len) -+ return -EIO; - return 0; - } - --- -1.7.7.5 - diff --git a/mac80211_offchannel_rework_revert.patch b/mac80211_offchannel_rework_revert.patch deleted file mode 100644 index 859799714..000000000 --- a/mac80211_offchannel_rework_revert.patch +++ /dev/null @@ -1,594 +0,0 @@ -diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h -index 9fab144..4f8cf7f 100644 ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -694,6 +694,8 @@ struct tpt_led_trigger { - * well be on the operating channel - * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to - * determine if we are on the operating channel or not -+ * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning, -+ * gets only set in conjunction with SCAN_SW_SCANNING - * @SCAN_COMPLETED: Set for our scan work function when the driver reported - * that the scan completed. - * @SCAN_ABORTED: Set for our scan work function when the driver reported -@@ -702,6 +704,7 @@ struct tpt_led_trigger { - enum { - SCAN_SW_SCANNING, - SCAN_HW_SCANNING, -+ SCAN_OFF_CHANNEL, - SCAN_COMPLETED, - SCAN_ABORTED, - }; -@@ -1197,14 +1200,10 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); - void ieee80211_sched_scan_stopped_work(struct work_struct *work); - - /* off-channel helpers */ --bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local); --void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, -- bool tell_ap); --void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, -- bool offchannel_ps_enable); -+void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local); -+void ieee80211_offchannel_stop_station(struct ieee80211_local *local); - void ieee80211_offchannel_return(struct ieee80211_local *local, -- bool enable_beaconing, -- bool offchannel_ps_disable); -+ bool enable_beaconing); - void ieee80211_hw_roc_setup(struct ieee80211_local *local); - - /* interface handling */ -diff --git a/net/mac80211/main.c b/net/mac80211/main.c -index acb4423..2d607e5 100644 ---- a/net/mac80211/main.c -+++ b/net/mac80211/main.c -@@ -92,47 +92,6 @@ static void ieee80211_reconfig_filter(struct work_struct *work) - ieee80211_configure_filter(local); - } - --/* -- * Returns true if we are logically configured to be on -- * the operating channel AND the hardware-conf is currently -- * configured on the operating channel. Compares channel-type -- * as well. -- */ --bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local) --{ -- struct ieee80211_channel *chan, *scan_chan; -- enum nl80211_channel_type channel_type; -- -- /* This logic needs to match logic in ieee80211_hw_config */ -- if (local->scan_channel) { -- chan = local->scan_channel; -- /* If scanning on oper channel, use whatever channel-type -- * is currently in use. -- */ -- if (chan == local->oper_channel) -- channel_type = local->_oper_channel_type; -- else -- channel_type = NL80211_CHAN_NO_HT; -- } else if (local->tmp_channel) { -- chan = scan_chan = local->tmp_channel; -- channel_type = local->tmp_channel_type; -- } else { -- chan = local->oper_channel; -- channel_type = local->_oper_channel_type; -- } -- -- if (chan != local->oper_channel || -- channel_type != local->_oper_channel_type) -- return false; -- -- /* Check current hardware-config against oper_channel. */ -- if ((local->oper_channel != local->hw.conf.channel) || -- (local->_oper_channel_type != local->hw.conf.channel_type)) -- return false; -- -- return true; --} -- - int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) - { - struct ieee80211_channel *chan, *scan_chan; -@@ -145,9 +104,6 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) - - scan_chan = local->scan_channel; - -- /* If this off-channel logic ever changes, ieee80211_on_oper_channel -- * may need to change as well. -- */ - offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; - if (scan_chan) { - chan = scan_chan; -@@ -158,19 +114,17 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) - channel_type = local->_oper_channel_type; - else - channel_type = NL80211_CHAN_NO_HT; -- } else if (local->tmp_channel) { -+ local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; -+ } else if (local->tmp_channel && -+ local->oper_channel != local->tmp_channel) { - chan = scan_chan = local->tmp_channel; - channel_type = local->tmp_channel_type; -+ local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; - } else { - chan = local->oper_channel; - channel_type = local->_oper_channel_type; -- } -- -- if (chan != local->oper_channel || -- channel_type != local->_oper_channel_type) -- local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; -- else - local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; -+ } - - offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; - -@@ -279,7 +233,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, - - if (changed & BSS_CHANGED_BEACON_ENABLED) { - if (local->quiescing || !ieee80211_sdata_running(sdata) || -- test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) { -+ test_bit(SCAN_SW_SCANNING, &local->scanning)) { - sdata->vif.bss_conf.enable_beacon = false; - } else { - /* -diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c -index 13427b1..b4e5267 100644 ---- a/net/mac80211/offchannel.c -+++ b/net/mac80211/offchannel.c -@@ -17,14 +17,10 @@ - #include "driver-trace.h" - - /* -- * Tell our hardware to disable PS. -- * Optionally inform AP that we will go to sleep so that it will buffer -- * the frames while we are doing off-channel work. This is optional -- * because we *may* be doing work on-operating channel, and want our -- * hardware unconditionally awake, but still let the AP send us normal frames. -+ * inform AP that we will go to sleep so that it will buffer the frames -+ * while we scan - */ --static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata, -- bool tell_ap) -+static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) - { - struct ieee80211_local *local = sdata->local; - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; -@@ -45,8 +41,8 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata, - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); - } - -- if (tell_ap && (!local->offchannel_ps_enabled || -- !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))) -+ if (!(local->offchannel_ps_enabled) || -+ !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) - /* - * If power save was enabled, no need to send a nullfunc - * frame because AP knows that we are sleeping. But if the -@@ -81,9 +77,6 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) - * we are sleeping, let's just enable power save mode in - * hardware. - */ -- /* TODO: Only set hardware if CONF_PS changed? -- * TODO: Should we set offchannel_ps_enabled to false? -- */ - local->hw.conf.flags |= IEEE80211_CONF_PS; - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); - } else if (local->hw.conf.dynamic_ps_timeout > 0) { -@@ -102,61 +95,63 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) - ieee80211_sta_reset_conn_monitor(sdata); - } - --void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, -- bool offchannel_ps_enable) -+void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) - { - struct ieee80211_sub_if_data *sdata; - -- /* -- * notify the AP about us leaving the channel and stop all -- * STA interfaces. -- */ - mutex_lock(&local->iflist_mtx); - list_for_each_entry(sdata, &local->interfaces, list) { - if (!ieee80211_sdata_running(sdata)) - continue; - -- if (sdata->vif.type != NL80211_IFTYPE_MONITOR) -- set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); -- -- /* Check to see if we should disable beaconing. */ -+ /* disable beaconing */ - if (sdata->vif.type == NL80211_IFTYPE_AP || - sdata->vif.type == NL80211_IFTYPE_ADHOC || - sdata->vif.type == NL80211_IFTYPE_MESH_POINT) - ieee80211_bss_info_change_notify( - sdata, BSS_CHANGED_BEACON_ENABLED); - -- if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { -+ /* -+ * only handle non-STA interfaces here, STA interfaces -+ * are handled in ieee80211_offchannel_stop_station(), -+ * e.g., from the background scan state machine. -+ * -+ * In addition, do not stop monitor interface to allow it to be -+ * used from user space controlled off-channel operations. -+ */ -+ if (sdata->vif.type != NL80211_IFTYPE_STATION && -+ sdata->vif.type != NL80211_IFTYPE_MONITOR) { -+ set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); - netif_tx_stop_all_queues(sdata->dev); -- if (offchannel_ps_enable && -- (sdata->vif.type == NL80211_IFTYPE_STATION) && -- sdata->u.mgd.associated) -- ieee80211_offchannel_ps_enable(sdata, true); - } - } - mutex_unlock(&local->iflist_mtx); - } - --void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, -- bool tell_ap) -+void ieee80211_offchannel_stop_station(struct ieee80211_local *local) - { - struct ieee80211_sub_if_data *sdata; - -+ /* -+ * notify the AP about us leaving the channel and stop all STA interfaces -+ */ - mutex_lock(&local->iflist_mtx); - list_for_each_entry(sdata, &local->interfaces, list) { - if (!ieee80211_sdata_running(sdata)) - continue; - -- if (sdata->vif.type == NL80211_IFTYPE_STATION && -- sdata->u.mgd.associated) -- ieee80211_offchannel_ps_enable(sdata, tell_ap); -+ if (sdata->vif.type == NL80211_IFTYPE_STATION) { -+ set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); -+ netif_tx_stop_all_queues(sdata->dev); -+ if (sdata->u.mgd.associated) -+ ieee80211_offchannel_ps_enable(sdata); -+ } - } - mutex_unlock(&local->iflist_mtx); - } - - void ieee80211_offchannel_return(struct ieee80211_local *local, -- bool enable_beaconing, -- bool offchannel_ps_disable) -+ bool enable_beaconing) - { - struct ieee80211_sub_if_data *sdata; - -@@ -166,8 +161,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, - continue; - - /* Tell AP we're back */ -- if (offchannel_ps_disable && -- sdata->vif.type == NL80211_IFTYPE_STATION) { -+ if (sdata->vif.type == NL80211_IFTYPE_STATION) { - if (sdata->u.mgd.associated) - ieee80211_offchannel_ps_disable(sdata); - } -@@ -187,7 +181,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, - netif_tx_wake_all_queues(sdata->dev); - } - -- /* Check to see if we should re-enable beaconing */ -+ /* re-enable beaconing */ - if (enable_beaconing && - (sdata->vif.type == NL80211_IFTYPE_AP || - sdata->vif.type == NL80211_IFTYPE_ADHOC || -diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c -index fe2c2a7..b46880e 100644 ---- a/net/mac80211/rx.c -+++ b/net/mac80211/rx.c -@@ -417,10 +417,16 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) - return RX_CONTINUE; - - if (test_bit(SCAN_HW_SCANNING, &local->scanning) || -- test_bit(SCAN_SW_SCANNING, &local->scanning) || - local->sched_scanning) - return ieee80211_scan_rx(rx->sdata, skb); - -+ if (test_bit(SCAN_SW_SCANNING, &local->scanning)) { -+ /* drop all the other packets during a software scan anyway */ -+ if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED) -+ dev_kfree_skb(skb); -+ return RX_QUEUED; -+ } -+ - /* scanning finished during invoking of handlers */ - I802_DEBUG_INC(local->rx_handlers_drop_passive_scan); - return RX_DROP_UNUSABLE; -@@ -2771,7 +2777,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, - local->dot11ReceivedFragmentCount++; - - if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || -- test_bit(SCAN_SW_SCANNING, &local->scanning))) -+ test_bit(SCAN_OFF_CHANNEL, &local->scanning))) - status->rx_flags |= IEEE80211_RX_IN_SCAN; - - if (ieee80211_is_mgmt(fc)) -diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c -index 6f09eca..2ba4977 100644 ---- a/net/mac80211/scan.c -+++ b/net/mac80211/scan.c -@@ -212,14 +212,6 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) - if (bss) - ieee80211_rx_bss_put(sdata->local, bss); - -- /* If we are on-operating-channel, and this packet is for the -- * current channel, pass the pkt on up the stack so that -- * the rest of the stack can make use of it. -- */ -- if (ieee80211_cfg_on_oper_channel(sdata->local) -- && (channel == sdata->local->oper_channel)) -- return RX_CONTINUE; -- - dev_kfree_skb(skb); - return RX_QUEUED; - } -@@ -262,8 +254,6 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, - bool was_hw_scan) - { - struct ieee80211_local *local = hw_to_local(hw); -- bool on_oper_chan; -- bool enable_beacons = false; - - lockdep_assert_held(&local->mtx); - -@@ -296,25 +286,11 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, - local->scanning = 0; - local->scan_channel = NULL; - -- on_oper_chan = ieee80211_cfg_on_oper_channel(local); -- -- if (was_hw_scan || !on_oper_chan) -- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); -- else -- /* Set power back to normal operating levels. */ -- ieee80211_hw_config(local, 0); -- -+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); - if (!was_hw_scan) { -- bool on_oper_chan2; - ieee80211_configure_filter(local); - drv_sw_scan_complete(local); -- on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); -- /* We should always be on-channel at this point. */ -- WARN_ON(!on_oper_chan2); -- if (on_oper_chan2 && (on_oper_chan != on_oper_chan2)) -- enable_beacons = true; -- -- ieee80211_offchannel_return(local, enable_beacons, true); -+ ieee80211_offchannel_return(local, true); - } - - ieee80211_recalc_idle(local); -@@ -355,15 +331,13 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) - */ - drv_sw_scan_start(local); - -+ ieee80211_offchannel_stop_beaconing(local); -+ - local->leave_oper_channel_time = 0; - local->next_scan_state = SCAN_DECISION; - local->scan_channel_idx = 0; - -- /* We always want to use off-channel PS, even if we -- * are not really leaving oper-channel. Don't -- * tell the AP though, as long as we are on-channel. -- */ -- ieee80211_offchannel_enable_all_ps(local, false); -+ drv_flush(local, false); - - ieee80211_configure_filter(local); - -@@ -506,20 +480,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, - } - mutex_unlock(&local->iflist_mtx); - -- next_chan = local->scan_req->channels[local->scan_channel_idx]; -- -- if (ieee80211_cfg_on_oper_channel(local)) { -- /* We're currently on operating channel. */ -- if (next_chan == local->oper_channel) -- /* We don't need to move off of operating channel. */ -- local->next_scan_state = SCAN_SET_CHANNEL; -- else -- /* -- * We do need to leave operating channel, as next -- * scan is somewhere else. -- */ -- local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; -- } else { -+ if (local->scan_channel) { - /* - * we're currently scanning a different channel, let's - * see if we can scan another channel without interfering -@@ -535,6 +496,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, - * - * Otherwise switch back to the operating channel. - */ -+ next_chan = local->scan_req->channels[local->scan_channel_idx]; - - bad_latency = time_after(jiffies + - ieee80211_scan_get_channel_time(next_chan), -@@ -552,6 +514,12 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, - local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; - else - local->next_scan_state = SCAN_SET_CHANNEL; -+ } else { -+ /* -+ * we're on the operating channel currently, let's -+ * leave that channel now to scan another one -+ */ -+ local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; - } - - *next_delay = 0; -@@ -560,10 +528,9 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, - static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, - unsigned long *next_delay) - { -- /* PS will already be in off-channel mode, -- * we do that once at the beginning of scanning. -- */ -- ieee80211_offchannel_stop_vifs(local, false); -+ ieee80211_offchannel_stop_station(local); -+ -+ __set_bit(SCAN_OFF_CHANNEL, &local->scanning); - - /* - * What if the nullfunc frames didn't arrive? -@@ -586,15 +553,15 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca - { - /* switch back to the operating channel */ - local->scan_channel = NULL; -- if (!ieee80211_cfg_on_oper_channel(local)) -- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); -+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); - - /* -- * Re-enable vifs and beaconing. Leave PS -- * in off-channel state..will put that back -- * on-channel at the end of scanning. -+ * Only re-enable station mode interface now; beaconing will be -+ * re-enabled once the full scan has been completed. - */ -- ieee80211_offchannel_return(local, true, false); -+ ieee80211_offchannel_return(local, false); -+ -+ __clear_bit(SCAN_OFF_CHANNEL, &local->scanning); - - *next_delay = HZ / 5; - local->next_scan_state = SCAN_DECISION; -diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c -index 8cb0d2d..54ea022 100644 ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -258,8 +258,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) - if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) - return TX_CONTINUE; - -- if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) && -- test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) && -+ if (unlikely(test_bit(SCAN_OFF_CHANNEL, &tx->local->scanning)) && - !ieee80211_is_probe_req(hdr->frame_control) && - !ieee80211_is_nullfunc(hdr->frame_control)) - /* -diff --git a/net/mac80211/work.c b/net/mac80211/work.c -index 7737f20..b76bf33 100644 ---- a/net/mac80211/work.c -+++ b/net/mac80211/work.c -@@ -901,26 +901,6 @@ static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct, - return false; - } - --static enum nl80211_channel_type --ieee80211_calc_ct(enum nl80211_channel_type wk_ct, -- enum nl80211_channel_type oper_ct) --{ -- switch (wk_ct) { -- case NL80211_CHAN_NO_HT: -- return oper_ct; -- case NL80211_CHAN_HT20: -- if (oper_ct != NL80211_CHAN_NO_HT) -- return oper_ct; -- return wk_ct; -- case NL80211_CHAN_HT40MINUS: -- case NL80211_CHAN_HT40PLUS: -- return wk_ct; -- } -- WARN_ON(1); /* shouldn't get here */ -- return wk_ct; --} -- -- - static void ieee80211_work_timer(unsigned long data) - { - struct ieee80211_local *local = (void *) data; -@@ -971,52 +951,18 @@ static void ieee80211_work_work(struct work_struct *work) - } - - if (!started && !local->tmp_channel) { -- bool on_oper_chan; -- bool tmp_chan_changed = false; -- bool on_oper_chan2; -- enum nl80211_channel_type wk_ct; -- on_oper_chan = ieee80211_cfg_on_oper_channel(local); -- -- /* Work with existing channel type if possible. */ -- wk_ct = wk->chan_type; -- if (wk->chan == local->hw.conf.channel) -- wk_ct = ieee80211_calc_ct(wk->chan_type, -- local->hw.conf.channel_type); -- -- if (local->tmp_channel) -- if ((local->tmp_channel != wk->chan) || -- (local->tmp_channel_type != wk_ct)) -- tmp_chan_changed = true; -- -- local->tmp_channel = wk->chan; -- local->tmp_channel_type = wk_ct; - /* -- * Leave the station vifs in awake mode if they -- * happen to be on the same channel as -- * the requested channel. -+ * TODO: could optimize this by leaving the -+ * station vifs in awake mode if they -+ * happen to be on the same channel as -+ * the requested channel - */ -- on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); -- if (on_oper_chan != on_oper_chan2) { -- if (on_oper_chan2) { -- /* going off oper channel, PS too */ -- ieee80211_offchannel_stop_vifs(local, -- true); -- ieee80211_hw_config(local, 0); -- } else { -- /* going on channel, but leave PS -- * off-channel. */ -- ieee80211_hw_config(local, 0); -- ieee80211_offchannel_return(local, -- true, -- false); -- } -- } else if (tmp_chan_changed) -- /* Still off-channel, but on some other -- * channel, so update hardware. -- * PS should already be off-channel. -- */ -- ieee80211_hw_config(local, 0); -+ ieee80211_offchannel_stop_beaconing(local); -+ ieee80211_offchannel_stop_station(local); - -+ local->tmp_channel = wk->chan; -+ local->tmp_channel_type = wk->chan_type; -+ ieee80211_hw_config(local, 0); - started = true; - wk->timeout = jiffies; - } -@@ -1102,8 +1048,7 @@ static void ieee80211_work_work(struct work_struct *work) - * we still need to do a hardware config. Currently, - * we cannot be here while scanning, however. - */ -- if (!ieee80211_cfg_on_oper_channel(local)) -- ieee80211_hw_config(local, 0); -+ ieee80211_hw_config(local, 0); - - /* At the least, we need to disable offchannel_ps, - * so just go ahead and run the entire offchannel -@@ -1111,7 +1056,7 @@ static void ieee80211_work_work(struct work_struct *work) - * beaconing if we were already on-oper-channel - * as a future optimization. - */ -- ieee80211_offchannel_return(local, true, true); -+ ieee80211_offchannel_return(local, true); - - /* give connection some time to breathe */ - run_again(local, jiffies + HZ/2); diff --git a/media-dib0700-correct-error-message.patch b/media-dib0700-correct-error-message.patch deleted file mode 100644 index 5e5d3bfa2..000000000 --- a/media-dib0700-correct-error-message.patch +++ /dev/null @@ -1,103 +0,0 @@ -From: Olivier Grenie -Date: Thu, 4 Aug 2011 16:10:03 +0000 (-0300) -Subject: [media] dib0700: correct error message -X-Git-Tag: next-20110927~67^2~4^2~223 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=680417bb318adc5f1f8f392730776176fbcdedd8 - -[media] dib0700: correct error message - -The goal of this patch is to correct a previous patch. In case of error, -the err() function should be used instead of dprintk() function. - -[mchehab@redhat.com: as I've replaced dprintk by deb_info, on the the - previous patch, to avoid breaking bisect, I had to fix a merge conflict - on this one] -Signed-off-by: Olivier Grenie -Signed-off-by: Mauro Carvalho Chehab ---- - -diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c -index a224e94..b693ed1 100644 ---- a/drivers/media/dvb/dvb-usb/dib0700_core.c -+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c -@@ -31,7 +31,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, - int ret; - - if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - -@@ -117,7 +117,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ - int ret; - - if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - -@@ -138,7 +138,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) - - if (st->fw_version >= 0x10201) { - if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - -@@ -227,7 +227,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, - } else { - /* Write request */ - if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - st->buf[0] = REQUEST_NEW_I2C_WRITE; -@@ -273,7 +273,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; - if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - -@@ -368,7 +368,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, - int ret; - - if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - -@@ -400,7 +400,7 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) - return -EINVAL; - - if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - -@@ -560,7 +560,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) - } - - if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - -@@ -610,7 +610,7 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) - int new_proto, ret; - - if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - diff --git a/mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch b/mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch deleted file mode 100644 index 6202341ae..000000000 --- a/mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch +++ /dev/null @@ -1,115 +0,0 @@ -https://lkml.org/lkml/2011/11/10/173 - -Date Thu, 10 Nov 2011 10:06:16 +0000 -From Mel Gorman <> -Subject [PATCH] mm: Do not stall in synchronous compaction for THP allocations - - -Occasionally during large file copies to slow storage, there are still -reports of user-visible stalls when THP is enabled. Reports on this -have been intermittent and not reliable to reproduce locally but; - -Andy Isaacson reported a problem copying to VFAT on SD Card - https://lkml.org/lkml/2011/11/7/2 - - In this case, it was stuck in munmap for betwen 20 and 60 - seconds in compaction. It is also possible that khugepaged - was holding mmap_sem on this process if CONFIG_NUMA was set. - -Johannes Weiner reported stalls on USB - https://lkml.org/lkml/2011/7/25/378 - - In this case, there is no stack trace but it looks like the - same problem. The USB stick may have been using NTFS as a - filesystem based on other work done related to writing back - to USB around the same time. - -Internally in SUSE, I received a bug report related to stalls in firefox - when using Java and Flash heavily while copying from NFS - to VFAT on USB. It has not been confirmed to be the same problem - but if it looks like a duck and quacks like a duck..... -In the past, commit [11bc82d6: mm: compaction: Use async migration for -__GFP_NO_KSWAPD and enforce no writeback] forced that sync compaction -would never be used for THP allocations. This was reverted in commit -[c6a140bf: mm/compaction: reverse the change that forbade sync -migraton with __GFP_NO_KSWAPD] on the grounds that it was uncertain -it was beneficial. - -While user-visible stalls do not happen for me when writing to USB, -I setup a test running postmark while short-lived processes created -anonymous mapping. The objective was to exercise the paths that -allocate transparent huge pages. I then logged when processes were -stalled for more than 1 second, recorded a stack strace and did some -analysis to aggregate unique "stall events" which revealed - -Time stalled in this event: 47369 ms -Event count: 20 -usemem sleep_on_page 3690 ms -usemem sleep_on_page 2148 ms -usemem sleep_on_page 1534 ms -usemem sleep_on_page 1518 ms -usemem sleep_on_page 1225 ms -usemem sleep_on_page 2205 ms -usemem sleep_on_page 2399 ms -usemem sleep_on_page 2398 ms -usemem sleep_on_page 3760 ms -usemem sleep_on_page 1861 ms -usemem sleep_on_page 2948 ms -usemem sleep_on_page 1515 ms -usemem sleep_on_page 1386 ms -usemem sleep_on_page 1882 ms -usemem sleep_on_page 1850 ms -usemem sleep_on_page 3715 ms -usemem sleep_on_page 3716 ms -usemem sleep_on_page 4846 ms -usemem sleep_on_page 1306 ms -usemem sleep_on_page 1467 ms -[] wait_on_page_bit+0x6c/0x80 -[] unmap_and_move+0x1bf/0x360 -[] migrate_pages+0xa2/0x1b0 -[] compact_zone+0x1f3/0x2f0 -[] compact_zone_order+0xa8/0xf0 -[] try_to_compact_pages+0xdf/0x110 -[] __alloc_pages_direct_compact+0xda/0x1a0 -[] __alloc_pages_slowpath+0x55d/0x7a0 -[] __alloc_pages_nodemask+0x1b1/0x1c0 -[] alloc_pages_vma+0x9b/0x160 -[] do_huge_pmd_anonymous_page+0x160/0x270 -[] do_page_fault+0x207/0x4c0 -[] page_fault+0x25/0x30 -The stall times are approximate at best but the estimates represent 25% -of the worst stalls and even if the estimates are off by a factor of -10, it's severe. - -This patch once again prevents sync migration for transparent -hugepage allocations as it is preferable to fail a THP allocation -than stall. It was suggested that __GFP_NORETRY be used instead of -__GFP_NO_KSWAPD. This would look less like a special case but would -still cause compaction to run at least once with sync compaction. - -If accepted, this is a -stable candidate. - -Reported-by: Andy Isaacson -Reported-by: Johannes Weiner -Signed-off-by: Mel Gorman ---- - -diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index 9dd443d..84bf962 100644 ---- a/mm/page_alloc.c -+++ b/mm/page_alloc.c -@@ -2168,7 +2168,13 @@ rebalance: - sync_migration); - if (page) - goto got_pg; -- sync_migration = true; -+ -+ /* -+ * Do not use sync migration for transparent hugepage allocations as -+ * it could stall writing back pages which is far worse than simply -+ * failing to promote a page. -+ */ -+ sync_migration = !(gfp_mask & __GFP_NO_KSWAPD); - - /* Try direct reclaim and then allocating */ - page = __alloc_pages_direct_reclaim(gfp_mask, order, diff --git a/msi-irq-sysfs-warning.patch b/msi-irq-sysfs-warning.patch new file mode 100644 index 000000000..dce440e4a --- /dev/null +++ b/msi-irq-sysfs-warning.patch @@ -0,0 +1,87 @@ +commit 3ff0e97a1bc3059bfbcc1d864c5d4ff5f8d3c2b9 +Author: Neil Horman +Date: Tue Jan 3 10:17:21 2012 -0500 + + msi: fix imbalanced refcount of msi irq sysfs objects + + This warning was recently reported to me: + + ------------[ cut here ]------------ + WARNING: at lib/kobject.c:595 kobject_put+0x50/0x60() + Hardware name: VMware Virtual Platform + kobject: '(null)' (ffff880027b0df40): is not initialized, yet kobject_put() is + being called. + Modules linked in: vmxnet3(+) vmw_balloon i2c_piix4 i2c_core shpchp raid10 + vmw_pvscsi + Pid: 630, comm: modprobe Tainted: G W 3.1.6-1.fc16.x86_64 #1 + Call Trace: + [] warn_slowpath_common+0x7f/0xc0 + [] warn_slowpath_fmt+0x46/0x50 + [] ? free_desc+0x63/0x70 + [] kobject_put+0x50/0x60 + [] free_msi_irqs+0xd5/0x120 + [] pci_enable_msi_block+0x24c/0x2c0 + [] vmxnet3_alloc_intr_resources+0x173/0x240 [vmxnet3] + [] vmxnet3_probe_device+0x615/0x834 [vmxnet3] + [] local_pci_probe+0x5c/0xd0 + [] pci_device_probe+0x109/0x130 + [] driver_probe_device+0x9c/0x2b0 + [] __driver_attach+0xab/0xb0 + [] ? driver_probe_device+0x2b0/0x2b0 + [] ? driver_probe_device+0x2b0/0x2b0 + [] bus_for_each_dev+0x5c/0x90 + [] driver_attach+0x1e/0x20 + [] bus_add_driver+0x1b0/0x2a0 + [] ? 0xffffffffa0187fff + [] driver_register+0x76/0x140 + [] ? printk+0x51/0x53 + [] ? 0xffffffffa0187fff + [] __pci_register_driver+0x56/0xd0 + [] vmxnet3_init_module+0x3a/0x3c [vmxnet3] + [] do_one_initcall+0x42/0x180 + [] sys_init_module+0x91/0x200 + [] system_call_fastpath+0x16/0x1b + ---[ end trace 44593438a59a9558 ]--- + Using INTx interrupt, #Rx queues: 1. + + It occurs when populate_msi_sysfs fails, which in turn causes free_msi_irqs to + be called. Because populate_msi_sysfs fails, we never registered any of the + msi irq sysfs objects, but free_msi_irqs still calls kobject_del and kobject_put + on each of them, which gets flagged in the above stack trace. + + The fix is pretty straightforward. We can key of the parent pointer in the + kobject. It is only set if the kobject_init_and_add succededs in + populate_msi_sysfs. If anything fails there, each kobject has its parent reset + to NULL + + Signed-off-by: Neil Horman + CC: Jesse Barnes + CC: Bjorn Helgaas + CC: Greg Kroah-Hartman + CC: linux-pci@vger.kernel.org + +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index 337e16a..82de95e 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -323,8 +323,18 @@ static void free_msi_irqs(struct pci_dev *dev) + if (list_is_last(&entry->list, &dev->msi_list)) + iounmap(entry->mask_base); + } +- kobject_del(&entry->kobj); +- kobject_put(&entry->kobj); ++ ++ /* ++ * Its possible that we get into this path ++ * When populate_msi_sysfs fails, which means the entries ++ * were not registered with sysfs. In that case don't ++ * unregister them. ++ */ ++ if (entry->kobj.parent) { ++ kobject_del(&entry->kobj); ++ kobject_put(&entry->kobj); ++ } ++ + list_del(&entry->list); + kfree(entry); + } diff --git a/net-sky2-88e8059-fix-link-speed.patch b/net-sky2-88e8059-fix-link-speed.patch deleted file mode 100644 index 61e1c75df..000000000 --- a/net-sky2-88e8059-fix-link-speed.patch +++ /dev/null @@ -1,42 +0,0 @@ -commit 27d240fdae2808d727ad9ce48ec029731a457524 -Author: stephen hemminger -Date: Fri Nov 4 12:17:17 2011 +0000 - - sky2: fix regression on Yukon Optima - - [ backport to 3.1 ] - - Changes to support other Optima types, introduced an accidental - regression that caused 88E8059 to come up in 10Mbit/sec. - - The Yukon Optima supports a reverse auto-negotiation feature that - was incorrectly setup, and not needed. The feature could be used to - allow wake-on-lan at higher speeds. But doing it correctly would require - other changes to initialization. - - Reported-by: Pavel Mateja - Signed-off-by: Stephen Hemminger - Signed-off-by: David S. Miller - -diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c -index cbd026f..fdc6c39 100644 ---- a/drivers/net/sky2.c -+++ b/drivers/net/sky2.c -@@ -366,17 +366,6 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) - gm_phy_write(hw, port, PHY_MARV_FE_SPEC_2, spec); - } - } else { -- if (hw->chip_id >= CHIP_ID_YUKON_OPT) { -- u16 ctrl2 = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL_2); -- -- /* enable PHY Reverse Auto-Negotiation */ -- ctrl2 |= 1u << 13; -- -- /* Write PHY changes (SW-reset must follow) */ -- gm_phy_write(hw, port, PHY_MARV_EXT_CTRL_2, ctrl2); -- } -- -- - /* disable energy detect */ - ctrl &= ~PHY_M_PC_EN_DET_MSK; - diff --git a/nfs-client-freezer.patch b/nfs-client-freezer.patch index 6b4d34d8a..5f5b0836e 100644 --- a/nfs-client-freezer.patch +++ b/nfs-client-freezer.patch @@ -1,106 +1,4 @@ @@ -, +, @@ - fs/cifs/transport.c | 3 ++- - include/linux/freezer.h | 19 +++++++++++++++++-- - 2 files changed, 19 insertions(+), 3 deletions(-) ---- a/fs/cifs/transport.c -+++ a/fs/cifs/transport.c -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -324,7 +325,7 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) - { - int error; - -- error = wait_event_killable(server->response_q, -+ error = wait_event_freezekillable(server->response_q, - midQ->midState != MID_REQUEST_SUBMITTED); - if (error < 0) - return -ERESTARTSYS; ---- a/include/linux/freezer.h -+++ a/include/linux/freezer.h -@@ -134,10 +134,25 @@ static inline void set_freezable_with_signal(void) - } - - /* -- * Freezer-friendly wrappers around wait_event_interruptible() and -- * wait_event_interruptible_timeout(), originally defined in -+ * Freezer-friendly wrappers around wait_event_interruptible(), -+ * wait_event_killable() and wait_event_interruptible_timeout(), originally -+ * defined in - */ - -+#define wait_event_freezekillable(wq, condition) \ -+({ \ -+ int __retval; \ -+ do { \ -+ __retval = wait_event_killable(wq, \ -+ (condition) || freezing(current)); \ -+ if (__retval && !freezing(current)) \ -+ break; \ -+ else if (!(condition)) \ -+ __retval = -ERESTARTSYS; \ -+ } while (try_to_freeze()); \ -+ __retval; \ -+}) -+ - #define wait_event_freezable(wq, condition) \ - ({ \ - int __retval; \ - include/linux/freezer.h | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) ---- a/include/linux/freezer.h -+++ a/include/linux/freezer.h -@@ -143,7 +143,7 @@ static inline void set_freezable_with_signal(void) - ({ \ - int __retval; \ - do { \ -- __retval = wait_event_killable(wq, \ -+ __retval = wait_event_killable(wq, \ - (condition) || freezing(current)); \ - if (__retval && !freezing(current)) \ - break; \ - include/linux/freezer.h | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) ---- a/include/linux/freezer.h -+++ a/include/linux/freezer.h -@@ -203,6 +203,9 @@ static inline void set_freezable_with_signal(void) {} - #define wait_event_freezable_timeout(wq, condition, timeout) \ - wait_event_interruptible_timeout(wq, condition, timeout) - -+#define wait_event_freezekillable(wq, condition) \ -+ wait_event_killable(wq, condition) -+ - #endif /* !CONFIG_FREEZER */ - - #endif /* FREEZER_H_INCLUDED */ - description on Rafael's request.] - include/linux/freezer.h | 11 +++-------- - 1 files changed, 3 insertions(+), 8 deletions(-) ---- a/include/linux/freezer.h -+++ a/include/linux/freezer.h -@@ -142,14 +142,9 @@ static inline void set_freezable_with_signal(void) - #define wait_event_freezekillable(wq, condition) \ - ({ \ - int __retval; \ -- do { \ -- __retval = wait_event_killable(wq, \ -- (condition) || freezing(current)); \ -- if (__retval && !freezing(current)) \ -- break; \ -- else if (!(condition)) \ -- __retval = -ERESTARTSYS; \ -- } while (try_to_freeze()); \ -+ freezer_do_not_count(); \ -+ __retval = wait_event_killable(wq, (condition)); \ -+ freezer_count(); \ - __retval; \ - }) - fs/nfs/inode.c | 3 ++- fs/nfs/nfs3proc.c | 3 ++- fs/nfs/nfs4proc.c | 5 +++-- @@ -156,7 +54,7 @@ #include "nfs4_fs.h" #include "delegation.h" -@@ -244,7 +245,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) +@@ -241,7 +242,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) *timeout = NFS4_POLL_RETRY_MIN; if (*timeout > NFS4_POLL_RETRY_MAX) *timeout = NFS4_POLL_RETRY_MAX; @@ -165,7 +63,7 @@ if (fatal_signal_pending(current)) res = -ERESTARTSYS; *timeout <<= 1; -@@ -3970,7 +3971,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 +@@ -3950,7 +3951,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 static unsigned long nfs4_set_lock_task_retry(unsigned long timeout) { @@ -195,7 +93,7 @@ return res; --- a/include/linux/freezer.h +++ a/include/linux/freezer.h -@@ -134,6 +134,29 @@ static inline void set_freezable_with_signal(void) +@@ -135,6 +135,29 @@ static inline void set_freezable_with_signal(void) } /* @@ -225,7 +123,7 @@ * Freezer-friendly wrappers around wait_event_interruptible(), * wait_event_killable() and wait_event_interruptible_timeout(), originally * defined in -@@ -192,6 +215,11 @@ static inline int freezer_should_skip(struct task_struct *p) { return 0; } +@@ -194,6 +217,11 @@ static inline int freezer_should_skip(struct task_struct *p) { return 0; } static inline void set_freezable(void) {} static inline void set_freezable_with_signal(void) {} @@ -260,7 +158,7 @@ 1 files changed, 18 insertions(+), 3 deletions(-) --- a/include/linux/freezer.h +++ a/include/linux/freezer.h -@@ -140,18 +140,33 @@ static inline void set_freezable_with_signal(void) +@@ -141,18 +141,33 @@ static inline void set_freezable_with_signal(void) * while in this function. */ diff --git a/proc-clean-up-and-fix-proc-pid-mem-handling.patch b/proc-clean-up-and-fix-proc-pid-mem-handling.patch deleted file mode 100644 index c793475d2..000000000 --- a/proc-clean-up-and-fix-proc-pid-mem-handling.patch +++ /dev/null @@ -1,268 +0,0 @@ -From e268337dfe26dfc7efd422a804dbb27977a3cccc Mon Sep 17 00:00:00 2001 -From: Linus Torvalds -Date: Tue, 17 Jan 2012 15:21:19 -0800 -Subject: [PATCH] proc: clean up and fix /proc//mem handling -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Jüri Aedla reported that the /proc//mem handling really isn't very -robust, and it also doesn't match the permission checking of any of the -other related files. - -This changes it to do the permission checks at open time, and instead of -tracking the process, it tracks the VM at the time of the open. That -simplifies the code a lot, but does mean that if you hold the file -descriptor open over an execve(), you'll continue to read from the _old_ -VM. - -That is different from our previous behavior, but much simpler. If -somebody actually finds a load where this matters, we'll need to revert -this commit. - -I suspect that nobody will ever notice - because the process mapping -addresses will also have changed as part of the execve. So you cannot -actually usefully access the fd across a VM change simply because all -the offsets for IO would have changed too. - -Reported-by: Jüri Aedla -Cc: Al Viro -Signed-off-by: Linus Torvalds ---- - fs/proc/base.c | 145 +++++++++++++++----------------------------------------- - 1 files changed, 39 insertions(+), 106 deletions(-) - -diff --git a/fs/proc/base.c b/fs/proc/base.c -index 5485a53..662ddf2 100644 ---- a/fs/proc/base.c -+++ b/fs/proc/base.c -@@ -198,65 +198,7 @@ static int proc_root_link(struct dentry *dentry, struct path *path) - return result; - } - --static struct mm_struct *__check_mem_permission(struct task_struct *task) --{ -- struct mm_struct *mm; -- -- mm = get_task_mm(task); -- if (!mm) -- return ERR_PTR(-EINVAL); -- -- /* -- * A task can always look at itself, in case it chooses -- * to use system calls instead of load instructions. -- */ -- if (task == current) -- return mm; -- -- /* -- * If current is actively ptrace'ing, and would also be -- * permitted to freshly attach with ptrace now, permit it. -- */ -- if (task_is_stopped_or_traced(task)) { -- int match; -- rcu_read_lock(); -- match = (ptrace_parent(task) == current); -- rcu_read_unlock(); -- if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH)) -- return mm; -- } -- -- /* -- * No one else is allowed. -- */ -- mmput(mm); -- return ERR_PTR(-EPERM); --} -- --/* -- * If current may access user memory in @task return a reference to the -- * corresponding mm, otherwise ERR_PTR. -- */ --static struct mm_struct *check_mem_permission(struct task_struct *task) --{ -- struct mm_struct *mm; -- int err; -- -- /* -- * Avoid racing if task exec's as we might get a new mm but validate -- * against old credentials. -- */ -- err = mutex_lock_killable(&task->signal->cred_guard_mutex); -- if (err) -- return ERR_PTR(err); -- -- mm = __check_mem_permission(task); -- mutex_unlock(&task->signal->cred_guard_mutex); -- -- return mm; --} -- --struct mm_struct *mm_for_maps(struct task_struct *task) -+static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) - { - struct mm_struct *mm; - int err; -@@ -267,7 +209,7 @@ struct mm_struct *mm_for_maps(struct task_struct *task) - - mm = get_task_mm(task); - if (mm && mm != current->mm && -- !ptrace_may_access(task, PTRACE_MODE_READ)) { -+ !ptrace_may_access(task, mode)) { - mmput(mm); - mm = ERR_PTR(-EACCES); - } -@@ -276,6 +218,11 @@ struct mm_struct *mm_for_maps(struct task_struct *task) - return mm; - } - -+struct mm_struct *mm_for_maps(struct task_struct *task) -+{ -+ return mm_access(task, PTRACE_MODE_READ); -+} -+ - static int proc_pid_cmdline(struct task_struct *task, char * buffer) - { - int res = 0; -@@ -752,38 +699,39 @@ static const struct file_operations proc_single_file_operations = { - - static int mem_open(struct inode* inode, struct file* file) - { -- file->private_data = (void*)((long)current->self_exec_id); -+ struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); -+ struct mm_struct *mm; -+ -+ if (!task) -+ return -ESRCH; -+ -+ mm = mm_access(task, PTRACE_MODE_ATTACH); -+ put_task_struct(task); -+ -+ if (IS_ERR(mm)) -+ return PTR_ERR(mm); -+ - /* OK to pass negative loff_t, we can catch out-of-range */ - file->f_mode |= FMODE_UNSIGNED_OFFSET; -+ file->private_data = mm; -+ - return 0; - } - - static ssize_t mem_read(struct file * file, char __user * buf, - size_t count, loff_t *ppos) - { -- struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); -+ int ret; - char *page; - unsigned long src = *ppos; -- int ret = -ESRCH; -- struct mm_struct *mm; -+ struct mm_struct *mm = file->private_data; - -- if (!task) -- goto out_no_task; -+ if (!mm) -+ return 0; - -- ret = -ENOMEM; - page = (char *)__get_free_page(GFP_TEMPORARY); - if (!page) -- goto out; -- -- mm = check_mem_permission(task); -- ret = PTR_ERR(mm); -- if (IS_ERR(mm)) -- goto out_free; -- -- ret = -EIO; -- -- if (file->private_data != (void*)((long)current->self_exec_id)) -- goto out_put; -+ return -ENOMEM; - - ret = 0; - -@@ -810,13 +758,7 @@ static ssize_t mem_read(struct file * file, char __user * buf, - } - *ppos = src; - --out_put: -- mmput(mm); --out_free: - free_page((unsigned long) page); --out: -- put_task_struct(task); --out_no_task: - return ret; - } - -@@ -825,27 +767,15 @@ static ssize_t mem_write(struct file * file, const char __user *buf, - { - int copied; - char *page; -- struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); - unsigned long dst = *ppos; -- struct mm_struct *mm; -+ struct mm_struct *mm = file->private_data; - -- copied = -ESRCH; -- if (!task) -- goto out_no_task; -+ if (!mm) -+ return 0; - -- copied = -ENOMEM; - page = (char *)__get_free_page(GFP_TEMPORARY); - if (!page) -- goto out_task; -- -- mm = check_mem_permission(task); -- copied = PTR_ERR(mm); -- if (IS_ERR(mm)) -- goto out_free; -- -- copied = -EIO; -- if (file->private_data != (void *)((long)current->self_exec_id)) -- goto out_mm; -+ return -ENOMEM; - - copied = 0; - while (count > 0) { -@@ -869,13 +799,7 @@ static ssize_t mem_write(struct file * file, const char __user *buf, - } - *ppos = dst; - --out_mm: -- mmput(mm); --out_free: - free_page((unsigned long) page); --out_task: -- put_task_struct(task); --out_no_task: - return copied; - } - -@@ -895,11 +819,20 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig) - return file->f_pos; - } - -+static int mem_release(struct inode *inode, struct file *file) -+{ -+ struct mm_struct *mm = file->private_data; -+ -+ mmput(mm); -+ return 0; -+} -+ - static const struct file_operations proc_mem_operations = { - .llseek = mem_lseek, - .read = mem_read, - .write = mem_write, - .open = mem_open, -+ .release = mem_release, - }; - - static ssize_t environ_read(struct file *file, char __user *buf, --- -1.7.7.5 - diff --git a/rcu-avoid-just-onlined-cpu-resched.patch b/rcu-avoid-just-onlined-cpu-resched.patch deleted file mode 100644 index 517f37591..000000000 --- a/rcu-avoid-just-onlined-cpu-resched.patch +++ /dev/null @@ -1,47 +0,0 @@ -rcu: Avoid having just-onlined CPU resched itself when RCU is idle - -CPUs set rdp->qs_pending when coming online to resolve races with -grace-period start. However, this means that if RCU is idle, the -just-onlined CPU might needlessly send itself resched IPIs. Adjust -the online-CPU initialization to avoid this, and also to correctly -cause the CPU to respond to the current grace period if needed. - -Signed-off-by: Paul E. McKenney ---- - kernel/rcutree.c | 13 +++++++++---- - 1 files changed, 9 insertions(+), 4 deletions(-) - -diff --git a/kernel/rcutree.c b/kernel/rcutree.c -index ba06207..472d6b2 100644 ---- a/kernel/rcutree.c -+++ b/kernel/rcutree.c -@@ -1865,8 +1865,6 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible) - - /* Set up local state, ensuring consistent view of global state. */ - raw_spin_lock_irqsave(&rnp->lock, flags); -- rdp->passed_quiesc = 0; /* We could be racing with new GP, */ -- rdp->qs_pending = 1; /* so set up to respond to current GP. */ - rdp->beenonline = 1; /* We have now been online. */ - rdp->preemptible = preemptible; - rdp->qlen_last_fqs_check = 0; -@@ -1891,8 +1889,15 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible) - rnp->qsmaskinit |= mask; - mask = rnp->grpmask; - if (rnp == rdp->mynode) { -- rdp->gpnum = rnp->completed; /* if GP in progress... */ -- rdp->completed = rnp->completed; -+ /* -+ * If there is a grace period in progress, we will -+ * set up to wait for it next time we run the -+ * RCU core code. -+ */ -+ rdp->gpnum = rnp->completed; -+ rdp->completed = rnp->completed; -+ rdp->passed_quiesc = 0; -+ rdp->qs_pending = 0; - rdp->passed_quiesc_completed = rnp->completed - 1; - } - raw_spin_unlock(&rnp->lock); /* irqs already disabled. */ --- -1.7.6 - diff --git a/rcu-reintroduce-missing-calls.patch b/rcu-reintroduce-missing-calls.patch new file mode 100644 index 000000000..b887df750 --- /dev/null +++ b/rcu-reintroduce-missing-calls.patch @@ -0,0 +1,632 @@ +commit cf778b00e96df6d64f8e21b8395d1f8a859ecdc7 +Author: Eric Dumazet +Date: Thu Jan 12 04:41:32 2012 +0000 + + net: reintroduce missing rcu_assign_pointer() calls + + commit a9b3cd7f32 (rcu: convert uses of rcu_assign_pointer(x, NULL) to + RCU_INIT_POINTER) did a lot of incorrect changes, since it did a + complete conversion of rcu_assign_pointer(x, y) to RCU_INIT_POINTER(x, + y). + + We miss needed barriers, even on x86, when y is not NULL. + + Signed-off-by: Eric Dumazet + CC: Stephen Hemminger + CC: Paul E. McKenney + Signed-off-by: David S. Miller + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/core/netpoll.c linux-3.2.net/net/core/netpoll.c +--- linux-3.2.noarch/net/core/netpoll.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/core/netpoll.c 2012-01-20 16:50:26.761797929 -0500 +@@ -763,7 +763,7 @@ int __netpoll_setup(struct netpoll *np) + } + + /* last thing to do is link it to the net device structure */ +- RCU_INIT_POINTER(ndev->npinfo, npinfo); ++ rcu_assign_pointer(ndev->npinfo, npinfo); + + return 0; + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/core/net-sysfs.c linux-3.2.net/net/core/net-sysfs.c +--- linux-3.2.noarch/net/core/net-sysfs.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/core/net-sysfs.c 2012-01-20 16:50:26.730798974 -0500 +@@ -990,9 +990,9 @@ static ssize_t store_xps_map(struct netd + nonempty = 1; + } + +- if (nonempty) +- RCU_INIT_POINTER(dev->xps_maps, new_dev_maps); +- else { ++ if (nonempty) { ++ rcu_assign_pointer(dev->xps_maps, new_dev_maps); ++ } else { + kfree(new_dev_maps); + RCU_INIT_POINTER(dev->xps_maps, NULL); + } +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/decnet/dn_dev.c linux-3.2.net/net/decnet/dn_dev.c +--- linux-3.2.noarch/net/decnet/dn_dev.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/decnet/dn_dev.c 2012-01-20 16:50:26.793796851 -0500 +@@ -388,7 +388,7 @@ static int dn_dev_insert_ifa(struct dn_d + } + + ifa->ifa_next = dn_db->ifa_list; +- RCU_INIT_POINTER(dn_db->ifa_list, ifa); ++ rcu_assign_pointer(dn_db->ifa_list, ifa); + + dn_ifaddr_notify(RTM_NEWADDR, ifa); + blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa); +@@ -1093,7 +1093,7 @@ static struct dn_dev *dn_dev_create(stru + + memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms)); + +- RCU_INIT_POINTER(dev->dn_ptr, dn_db); ++ rcu_assign_pointer(dev->dn_ptr, dn_db); + dn_db->dev = dev; + init_timer(&dn_db->timer); + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv4/devinet.c linux-3.2.net/net/ipv4/devinet.c +--- linux-3.2.noarch/net/ipv4/devinet.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/ipv4/devinet.c 2012-01-20 16:50:26.829795637 -0500 +@@ -258,7 +258,7 @@ static struct in_device *inetdev_init(st + ip_mc_up(in_dev); + + /* we can receive as soon as ip_ptr is set -- do this last */ +- RCU_INIT_POINTER(dev->ip_ptr, in_dev); ++ rcu_assign_pointer(dev->ip_ptr, in_dev); + out: + return in_dev; + out_kfree: +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv4/fib_trie.c linux-3.2.net/net/ipv4/fib_trie.c +--- linux-3.2.noarch/net/ipv4/fib_trie.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/ipv4/fib_trie.c 2012-01-20 16:50:26.865794425 -0500 +@@ -205,7 +205,7 @@ static inline struct tnode *node_parent_ + return (struct tnode *)(parent & ~NODE_TYPE_MASK); + } + +-/* Same as RCU_INIT_POINTER ++/* Same as rcu_assign_pointer + * but that macro() assumes that value is a pointer. + */ + static inline void node_set_parent(struct rt_trie_node *node, struct tnode *ptr) +@@ -529,7 +529,7 @@ static void tnode_put_child_reorg(struct + if (n) + node_set_parent(n, tn); + +- RCU_INIT_POINTER(tn->child[i], n); ++ rcu_assign_pointer(tn->child[i], n); + } + + #define MAX_WORK 10 +@@ -1015,7 +1015,7 @@ static void trie_rebalance(struct trie * + + tp = node_parent((struct rt_trie_node *) tn); + if (!tp) +- RCU_INIT_POINTER(t->trie, (struct rt_trie_node *)tn); ++ rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); + + tnode_free_flush(); + if (!tp) +@@ -1027,7 +1027,7 @@ static void trie_rebalance(struct trie * + if (IS_TNODE(tn)) + tn = (struct tnode *)resize(t, (struct tnode *)tn); + +- RCU_INIT_POINTER(t->trie, (struct rt_trie_node *)tn); ++ rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); + tnode_free_flush(); + } + +@@ -1164,7 +1164,7 @@ static struct list_head *fib_insert_node + put_child(t, (struct tnode *)tp, cindex, + (struct rt_trie_node *)tn); + } else { +- RCU_INIT_POINTER(t->trie, (struct rt_trie_node *)tn); ++ rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); + tp = tn; + } + } +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv4/igmp.c linux-3.2.net/net/ipv4/igmp.c +--- linux-3.2.noarch/net/ipv4/igmp.c 2012-01-20 16:22:44.923961882 -0500 ++++ linux-3.2.net/net/ipv4/igmp.c 2012-01-20 16:50:26.898793315 -0500 +@@ -1244,7 +1244,7 @@ void ip_mc_inc_group(struct in_device *i + + im->next_rcu = in_dev->mc_list; + in_dev->mc_count++; +- RCU_INIT_POINTER(in_dev->mc_list, im); ++ rcu_assign_pointer(in_dev->mc_list, im); + + #ifdef CONFIG_IP_MULTICAST + igmpv3_del_delrec(in_dev, im->multiaddr); +@@ -1816,7 +1816,7 @@ int ip_mc_join_group(struct sock *sk , s + iml->next_rcu = inet->mc_list; + iml->sflist = NULL; + iml->sfmode = MCAST_EXCLUDE; +- RCU_INIT_POINTER(inet->mc_list, iml); ++ rcu_assign_pointer(inet->mc_list, iml); + ip_mc_inc_group(in_dev, addr); + err = 0; + done: +@@ -2003,7 +2003,7 @@ int ip_mc_source(int add, int omode, str + atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc); + kfree_rcu(psl, rcu); + } +- RCU_INIT_POINTER(pmc->sflist, newpsl); ++ rcu_assign_pointer(pmc->sflist, newpsl); + psl = newpsl; + } + rv = 1; /* > 0 for insert logic below if sl_count is 0 */ +@@ -2106,7 +2106,7 @@ int ip_mc_msfilter(struct sock *sk, stru + } else + (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode, + 0, NULL, 0); +- RCU_INIT_POINTER(pmc->sflist, newpsl); ++ rcu_assign_pointer(pmc->sflist, newpsl); + pmc->sfmode = msf->imsf_fmode; + err = 0; + done: +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv4/ipip.c linux-3.2.net/net/ipv4/ipip.c +--- linux-3.2.noarch/net/ipv4/ipip.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/ipv4/ipip.c 2012-01-20 16:50:26.916792707 -0500 +@@ -231,7 +231,7 @@ static void ipip_tunnel_unlink(struct ip + (iter = rtnl_dereference(*tp)) != NULL; + tp = &iter->next) { + if (t == iter) { +- RCU_INIT_POINTER(*tp, t->next); ++ rcu_assign_pointer(*tp, t->next); + break; + } + } +@@ -241,8 +241,8 @@ static void ipip_tunnel_link(struct ipip + { + struct ip_tunnel __rcu **tp = ipip_bucket(ipn, t); + +- RCU_INIT_POINTER(t->next, rtnl_dereference(*tp)); +- RCU_INIT_POINTER(*tp, t); ++ rcu_assign_pointer(t->next, rtnl_dereference(*tp)); ++ rcu_assign_pointer(*tp, t); + } + + static struct ip_tunnel * ipip_tunnel_locate(struct net *net, +@@ -792,7 +792,7 @@ static int __net_init ipip_fb_tunnel_ini + return -ENOMEM; + + dev_hold(dev); +- RCU_INIT_POINTER(ipn->tunnels_wc[0], tunnel); ++ rcu_assign_pointer(ipn->tunnels_wc[0], tunnel); + return 0; + } + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv4/ipmr.c linux-3.2.net/net/ipv4/ipmr.c +--- linux-3.2.noarch/net/ipv4/ipmr.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/ipv4/ipmr.c 2012-01-20 16:50:26.946791698 -0500 +@@ -1225,7 +1225,7 @@ int ip_mroute_setsockopt(struct sock *sk + + ret = ip_ra_control(sk, 1, mrtsock_destruct); + if (ret == 0) { +- RCU_INIT_POINTER(mrt->mroute_sk, sk); ++ rcu_assign_pointer(mrt->mroute_sk, sk); + IPV4_DEVCONF_ALL(net, MC_FORWARDING)++; + } + rtnl_unlock(); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv6/addrconf.c linux-3.2.net/net/ipv6/addrconf.c +--- linux-3.2.noarch/net/ipv6/addrconf.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/ipv6/addrconf.c 2012-01-20 16:50:26.977790653 -0500 +@@ -429,7 +429,7 @@ static struct inet6_dev * ipv6_add_dev(s + ndev->tstamp = jiffies; + addrconf_sysctl_register(ndev); + /* protected by rtnl_lock */ +- RCU_INIT_POINTER(dev->ip6_ptr, ndev); ++ rcu_assign_pointer(dev->ip6_ptr, ndev); + + /* Join all-node multicast group */ + ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv6/ip6_tunnel.c linux-3.2.net/net/ipv6/ip6_tunnel.c +--- linux-3.2.noarch/net/ipv6/ip6_tunnel.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/ipv6/ip6_tunnel.c 2012-01-20 16:50:27.004789743 -0500 +@@ -218,8 +218,8 @@ ip6_tnl_link(struct ip6_tnl_net *ip6n, s + { + struct ip6_tnl __rcu **tp = ip6_tnl_bucket(ip6n, &t->parms); + +- RCU_INIT_POINTER(t->next , rtnl_dereference(*tp)); +- RCU_INIT_POINTER(*tp, t); ++ rcu_assign_pointer(t->next , rtnl_dereference(*tp)); ++ rcu_assign_pointer(*tp, t); + } + + /** +@@ -237,7 +237,7 @@ ip6_tnl_unlink(struct ip6_tnl_net *ip6n, + (iter = rtnl_dereference(*tp)) != NULL; + tp = &iter->next) { + if (t == iter) { +- RCU_INIT_POINTER(*tp, t->next); ++ rcu_assign_pointer(*tp, t->next); + break; + } + } +@@ -1450,7 +1450,7 @@ static int __net_init ip6_fb_tnl_dev_ini + + t->parms.proto = IPPROTO_IPV6; + dev_hold(dev); +- RCU_INIT_POINTER(ip6n->tnls_wc[0], t); ++ rcu_assign_pointer(ip6n->tnls_wc[0], t); + return 0; + } + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv6/raw.c linux-3.2.net/net/ipv6/raw.c +--- linux-3.2.noarch/net/ipv6/raw.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/ipv6/raw.c 2012-01-20 16:50:27.022789138 -0500 +@@ -131,7 +131,7 @@ static mh_filter_t __rcu *mh_filter __re + + int rawv6_mh_filter_register(mh_filter_t filter) + { +- RCU_INIT_POINTER(mh_filter, filter); ++ rcu_assign_pointer(mh_filter, filter); + return 0; + } + EXPORT_SYMBOL(rawv6_mh_filter_register); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv6/sit.c linux-3.2.net/net/ipv6/sit.c +--- linux-3.2.noarch/net/ipv6/sit.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/ipv6/sit.c 2012-01-20 16:50:27.042788464 -0500 +@@ -182,7 +182,7 @@ static void ipip6_tunnel_unlink(struct s + (iter = rtnl_dereference(*tp)) != NULL; + tp = &iter->next) { + if (t == iter) { +- RCU_INIT_POINTER(*tp, t->next); ++ rcu_assign_pointer(*tp, t->next); + break; + } + } +@@ -192,8 +192,8 @@ static void ipip6_tunnel_link(struct sit + { + struct ip_tunnel __rcu **tp = ipip6_bucket(sitn, t); + +- RCU_INIT_POINTER(t->next, rtnl_dereference(*tp)); +- RCU_INIT_POINTER(*tp, t); ++ rcu_assign_pointer(t->next, rtnl_dereference(*tp)); ++ rcu_assign_pointer(*tp, t); + } + + static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn) +@@ -393,7 +393,7 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t + p->addr = a->addr; + p->flags = a->flags; + t->prl_count++; +- RCU_INIT_POINTER(t->prl, p); ++ rcu_assign_pointer(t->prl, p); + out: + return err; + } +@@ -1177,7 +1177,7 @@ static int __net_init ipip6_fb_tunnel_in + if (!dev->tstats) + return -ENOMEM; + dev_hold(dev); +- RCU_INIT_POINTER(sitn->tunnels_wc[0], tunnel); ++ rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); + return 0; + } + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/mac80211/agg-rx.c linux-3.2.net/net/mac80211/agg-rx.c +--- linux-3.2.noarch/net/mac80211/agg-rx.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/mac80211/agg-rx.c 2012-01-20 16:50:27.058787924 -0500 +@@ -326,7 +326,7 @@ void ieee80211_process_addba_request(str + status = WLAN_STATUS_SUCCESS; + + /* activate it for RX */ +- RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx); ++ rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx); + + if (timeout) + mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout)); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/mac80211/cfg.c linux-3.2.net/net/mac80211/cfg.c +--- linux-3.2.noarch/net/mac80211/cfg.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/mac80211/cfg.c 2012-01-20 16:50:27.082787116 -0500 +@@ -575,7 +575,7 @@ static int ieee80211_config_beacon(struc + + sdata->vif.bss_conf.dtim_period = new->dtim_period; + +- RCU_INIT_POINTER(sdata->u.ap.beacon, new); ++ rcu_assign_pointer(sdata->u.ap.beacon, new); + + synchronize_rcu(); + +@@ -922,7 +922,7 @@ static int ieee80211_change_station(stru + return -EBUSY; + } + +- RCU_INIT_POINTER(vlansdata->u.vlan.sta, sta); ++ rcu_assign_pointer(vlansdata->u.vlan.sta, sta); + } + + sta->sdata = vlansdata; +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/mac80211/ibss.c linux-3.2.net/net/mac80211/ibss.c +--- linux-3.2.noarch/net/mac80211/ibss.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/mac80211/ibss.c 2012-01-20 16:50:27.102786444 -0500 +@@ -184,7 +184,7 @@ static void __ieee80211_sta_join_ibss(st + *pos++ = 0; /* U-APSD no in use */ + } + +- RCU_INIT_POINTER(ifibss->presp, skb); ++ rcu_assign_pointer(ifibss->presp, skb); + + sdata->vif.bss_conf.beacon_int = beacon_int; + sdata->vif.bss_conf.basic_rates = basic_rates; +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/mac80211/sta_info.c linux-3.2.net/net/mac80211/sta_info.c +--- linux-3.2.noarch/net/mac80211/sta_info.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/mac80211/sta_info.c 2012-01-20 16:50:27.131785466 -0500 +@@ -73,7 +73,7 @@ static int sta_info_hash_del(struct ieee + if (!s) + return -ENOENT; + if (s == sta) { +- RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)], ++ rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], + s->hnext); + return 0; + } +@@ -83,7 +83,7 @@ static int sta_info_hash_del(struct ieee + s = rcu_dereference_protected(s->hnext, + lockdep_is_held(&local->sta_lock)); + if (rcu_access_pointer(s->hnext)) { +- RCU_INIT_POINTER(s->hnext, sta->hnext); ++ rcu_assign_pointer(s->hnext, sta->hnext); + return 0; + } + +@@ -232,7 +232,7 @@ static void sta_info_hash_add(struct iee + struct sta_info *sta) + { + sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)]; +- RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)], sta); ++ rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta); + } + + static void sta_unblock(struct work_struct *wk) +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_conntrack_core.c linux-3.2.net/net/netfilter/nf_conntrack_core.c +--- linux-3.2.noarch/net/netfilter/nf_conntrack_core.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netfilter/nf_conntrack_core.c 2012-01-20 16:50:27.169784186 -0500 +@@ -776,7 +776,7 @@ init_conntrack(struct net *net, struct n + if (exp->helper) { + help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); + if (help) +- RCU_INIT_POINTER(help->helper, exp->helper); ++ rcu_assign_pointer(help->helper, exp->helper); + } + + #ifdef CONFIG_NF_CONNTRACK_MARK +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_conntrack_ecache.c linux-3.2.net/net/netfilter/nf_conntrack_ecache.c +--- linux-3.2.noarch/net/netfilter/nf_conntrack_ecache.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netfilter/nf_conntrack_ecache.c 2012-01-20 16:50:27.187783578 -0500 +@@ -91,7 +91,7 @@ int nf_conntrack_register_notifier(struc + ret = -EBUSY; + goto out_unlock; + } +- RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, new); ++ rcu_assign_pointer(net->ct.nf_conntrack_event_cb, new); + mutex_unlock(&nf_ct_ecache_mutex); + return ret; + +@@ -128,7 +128,7 @@ int nf_ct_expect_register_notifier(struc + ret = -EBUSY; + goto out_unlock; + } +- RCU_INIT_POINTER(net->ct.nf_expect_event_cb, new); ++ rcu_assign_pointer(net->ct.nf_expect_event_cb, new); + mutex_unlock(&nf_ct_ecache_mutex); + return ret; + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_conntrack_extend.c linux-3.2.net/net/netfilter/nf_conntrack_extend.c +--- linux-3.2.noarch/net/netfilter/nf_conntrack_extend.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netfilter/nf_conntrack_extend.c 2012-01-20 16:50:27.204783008 -0500 +@@ -169,7 +169,7 @@ int nf_ct_extend_register(struct nf_ct_e + before updating alloc_size */ + type->alloc_size = ALIGN(sizeof(struct nf_ct_ext), type->align) + + type->len; +- RCU_INIT_POINTER(nf_ct_ext_types[type->id], type); ++ rcu_assign_pointer(nf_ct_ext_types[type->id], type); + update_alloc_size(type); + out: + mutex_unlock(&nf_ct_ext_type_mutex); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_conntrack_helper.c linux-3.2.net/net/netfilter/nf_conntrack_helper.c +--- linux-3.2.noarch/net/netfilter/nf_conntrack_helper.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netfilter/nf_conntrack_helper.c 2012-01-20 16:50:27.227782232 -0500 +@@ -145,7 +145,7 @@ int __nf_ct_try_assign_helper(struct nf_ + memset(&help->help, 0, sizeof(help->help)); + } + +- RCU_INIT_POINTER(help->helper, helper); ++ rcu_assign_pointer(help->helper, helper); + out: + return ret; + } +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_conntrack_netlink.c linux-3.2.net/net/netfilter/nf_conntrack_netlink.c +--- linux-3.2.noarch/net/netfilter/nf_conntrack_netlink.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netfilter/nf_conntrack_netlink.c 2012-01-20 16:50:27.271780750 -0500 +@@ -1163,7 +1163,7 @@ ctnetlink_change_helper(struct nf_conn * + return -EOPNOTSUPP; + } + +- RCU_INIT_POINTER(help->helper, helper); ++ rcu_assign_pointer(help->helper, helper); + + return 0; + } +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_log.c linux-3.2.net/net/netfilter/nf_log.c +--- linux-3.2.noarch/net/netfilter/nf_log.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netfilter/nf_log.c 2012-01-20 16:50:27.280780448 -0500 +@@ -55,7 +55,7 @@ int nf_log_register(u_int8_t pf, struct + llog = rcu_dereference_protected(nf_loggers[pf], + lockdep_is_held(&nf_log_mutex)); + if (llog == NULL) +- RCU_INIT_POINTER(nf_loggers[pf], logger); ++ rcu_assign_pointer(nf_loggers[pf], logger); + } + + mutex_unlock(&nf_log_mutex); +@@ -92,7 +92,7 @@ int nf_log_bind_pf(u_int8_t pf, const st + mutex_unlock(&nf_log_mutex); + return -ENOENT; + } +- RCU_INIT_POINTER(nf_loggers[pf], logger); ++ rcu_assign_pointer(nf_loggers[pf], logger); + mutex_unlock(&nf_log_mutex); + return 0; + } +@@ -250,7 +250,7 @@ static int nf_log_proc_dostring(ctl_tabl + mutex_unlock(&nf_log_mutex); + return -ENOENT; + } +- RCU_INIT_POINTER(nf_loggers[tindex], logger); ++ rcu_assign_pointer(nf_loggers[tindex], logger); + mutex_unlock(&nf_log_mutex); + } else { + mutex_lock(&nf_log_mutex); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nfnetlink.c linux-3.2.net/net/netfilter/nfnetlink.c +--- linux-3.2.noarch/net/netfilter/nfnetlink.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netfilter/nfnetlink.c 2012-01-20 16:50:27.302779705 -0500 +@@ -59,7 +59,7 @@ int nfnetlink_subsys_register(const stru + nfnl_unlock(); + return -EBUSY; + } +- RCU_INIT_POINTER(subsys_table[n->subsys_id], n); ++ rcu_assign_pointer(subsys_table[n->subsys_id], n); + nfnl_unlock(); + + return 0; +@@ -210,7 +210,7 @@ static int __net_init nfnetlink_net_init + if (!nfnl) + return -ENOMEM; + net->nfnl_stash = nfnl; +- RCU_INIT_POINTER(net->nfnl, nfnl); ++ rcu_assign_pointer(net->nfnl, nfnl); + return 0; + } + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_queue.c linux-3.2.net/net/netfilter/nf_queue.c +--- linux-3.2.noarch/net/netfilter/nf_queue.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netfilter/nf_queue.c 2012-01-20 16:50:27.293780010 -0500 +@@ -40,7 +40,7 @@ int nf_register_queue_handler(u_int8_t p + else if (old) + ret = -EBUSY; + else { +- RCU_INIT_POINTER(queue_handler[pf], qh); ++ rcu_assign_pointer(queue_handler[pf], qh); + ret = 0; + } + mutex_unlock(&queue_handler_mutex); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netlabel/netlabel_domainhash.c linux-3.2.net/net/netlabel/netlabel_domainhash.c +--- linux-3.2.noarch/net/netlabel/netlabel_domainhash.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netlabel/netlabel_domainhash.c 2012-01-20 16:50:27.311779402 -0500 +@@ -282,7 +282,7 @@ int __init netlbl_domhsh_init(u32 size) + INIT_LIST_HEAD(&hsh_tbl->tbl[iter]); + + spin_lock(&netlbl_domhsh_lock); +- RCU_INIT_POINTER(netlbl_domhsh, hsh_tbl); ++ rcu_assign_pointer(netlbl_domhsh, hsh_tbl); + spin_unlock(&netlbl_domhsh_lock); + + return 0; +@@ -330,7 +330,7 @@ int netlbl_domhsh_add(struct netlbl_dom_ + &rcu_dereference(netlbl_domhsh)->tbl[bkt]); + } else { + INIT_LIST_HEAD(&entry->list); +- RCU_INIT_POINTER(netlbl_domhsh_def, entry); ++ rcu_assign_pointer(netlbl_domhsh_def, entry); + } + + if (entry->type == NETLBL_NLTYPE_ADDRSELECT) { +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netlabel/netlabel_unlabeled.c linux-3.2.net/net/netlabel/netlabel_unlabeled.c +--- linux-3.2.noarch/net/netlabel/netlabel_unlabeled.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netlabel/netlabel_unlabeled.c 2012-01-20 16:50:27.327778863 -0500 +@@ -354,7 +354,7 @@ static struct netlbl_unlhsh_iface *netlb + INIT_LIST_HEAD(&iface->list); + if (netlbl_unlhsh_rcu_deref(netlbl_unlhsh_def) != NULL) + goto add_iface_failure; +- RCU_INIT_POINTER(netlbl_unlhsh_def, iface); ++ rcu_assign_pointer(netlbl_unlhsh_def, iface); + } + spin_unlock(&netlbl_unlhsh_lock); + +@@ -1447,11 +1447,9 @@ int __init netlbl_unlabel_init(u32 size) + for (iter = 0; iter < hsh_tbl->size; iter++) + INIT_LIST_HEAD(&hsh_tbl->tbl[iter]); + +- rcu_read_lock(); + spin_lock(&netlbl_unlhsh_lock); +- RCU_INIT_POINTER(netlbl_unlhsh, hsh_tbl); ++ rcu_assign_pointer(netlbl_unlhsh, hsh_tbl); + spin_unlock(&netlbl_unlhsh_lock); +- rcu_read_unlock(); + + register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier); + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/phonet/af_phonet.c linux-3.2.net/net/phonet/af_phonet.c +--- linux-3.2.noarch/net/phonet/af_phonet.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/phonet/af_phonet.c 2012-01-20 16:50:27.345778258 -0500 +@@ -480,7 +480,7 @@ int __init_or_module phonet_proto_regist + if (proto_tab[protocol]) + err = -EBUSY; + else +- RCU_INIT_POINTER(proto_tab[protocol], pp); ++ rcu_assign_pointer(proto_tab[protocol], pp); + mutex_unlock(&proto_tab_lock); + + return err; +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/phonet/pn_dev.c linux-3.2.net/net/phonet/pn_dev.c +--- linux-3.2.noarch/net/phonet/pn_dev.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/phonet/pn_dev.c 2012-01-20 16:50:27.353777988 -0500 +@@ -390,7 +390,7 @@ int phonet_route_add(struct net_device * + daddr = daddr >> 2; + mutex_lock(&routes->lock); + if (routes->table[daddr] == NULL) { +- RCU_INIT_POINTER(routes->table[daddr], dev); ++ rcu_assign_pointer(routes->table[daddr], dev); + dev_hold(dev); + err = 0; + } +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/phonet/socket.c linux-3.2.net/net/phonet/socket.c +--- linux-3.2.noarch/net/phonet/socket.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/phonet/socket.c 2012-01-20 16:50:27.365777583 -0500 +@@ -680,7 +680,7 @@ int pn_sock_bind_res(struct sock *sk, u8 + mutex_lock(&resource_mutex); + if (pnres.sk[res] == NULL) { + sock_hold(sk); +- RCU_INIT_POINTER(pnres.sk[res], sk); ++ rcu_assign_pointer(pnres.sk[res], sk); + ret = 0; + } + mutex_unlock(&resource_mutex); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/socket.c linux-3.2.net/net/socket.c +--- linux-3.2.noarch/net/socket.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/socket.c 2012-01-20 16:50:27.410776068 -0500 +@@ -2472,7 +2472,7 @@ int sock_register(const struct net_proto + lockdep_is_held(&net_family_lock))) + err = -EEXIST; + else { +- RCU_INIT_POINTER(net_families[ops->family], ops); ++ rcu_assign_pointer(net_families[ops->family], ops); + err = 0; + } + spin_unlock(&net_family_lock); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/sunrpc/auth_gss/auth_gss.c linux-3.2.net/net/sunrpc/auth_gss/auth_gss.c +--- linux-3.2.noarch/net/sunrpc/auth_gss/auth_gss.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/sunrpc/auth_gss/auth_gss.c 2012-01-20 16:50:27.428775461 -0500 +@@ -122,7 +122,7 @@ gss_cred_set_ctx(struct rpc_cred *cred, + if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)) + return; + gss_get_ctx(ctx); +- RCU_INIT_POINTER(gss_cred->gc_ctx, ctx); ++ rcu_assign_pointer(gss_cred->gc_ctx, ctx); + set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); + smp_mb__before_clear_bit(); + clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/xfrm/xfrm_user.c linux-3.2.net/net/xfrm/xfrm_user.c +--- linux-3.2.noarch/net/xfrm/xfrm_user.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/xfrm/xfrm_user.c 2012-01-20 16:50:27.449774754 -0500 +@@ -2927,7 +2927,7 @@ static int __net_init xfrm_user_net_init + if (nlsk == NULL) + return -ENOMEM; + net->xfrm.nlsk_stash = nlsk; /* Don't set to NULL */ +- RCU_INIT_POINTER(net->xfrm.nlsk, nlsk); ++ rcu_assign_pointer(net->xfrm.nlsk, nlsk); + return 0; + } + diff --git a/rcutree-avoid-false-quiescent-states.patch b/rcutree-avoid-false-quiescent-states.patch deleted file mode 100644 index 9c7ffea34..000000000 --- a/rcutree-avoid-false-quiescent-states.patch +++ /dev/null @@ -1,67 +0,0 @@ -diff --git a/kernel/rcutree.c b/kernel/rcutree.c -index ba06207..c38a882 100644 ---- a/kernel/rcutree.c -+++ b/kernel/rcutree.c -@@ -1476,9 +1476,6 @@ static void rcu_process_callbacks(struct softirq_action *unused) - &__get_cpu_var(rcu_sched_data)); - __rcu_process_callbacks(&rcu_bh_state, &__get_cpu_var(rcu_bh_data)); - rcu_preempt_process_callbacks(); -- -- /* If we are last CPU on way to dyntick-idle mode, accelerate it. */ -- rcu_needs_cpu_flush(); - } - - /* -diff --git a/kernel/rcutree.h b/kernel/rcutree.h -index 01b2ccd..795f7fc 100644 ---- a/kernel/rcutree.h -+++ b/kernel/rcutree.h -@@ -450,7 +450,6 @@ static int rcu_preempt_needs_cpu(int cpu); - static void __cpuinit rcu_preempt_init_percpu_data(int cpu); - static void rcu_preempt_send_cbs_to_online(void); - static void __init __rcu_init_preempt(void); --static void rcu_needs_cpu_flush(void); - static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags); - static void rcu_preempt_boost_start_gp(struct rcu_node *rnp); - static void invoke_rcu_callbacks_kthread(void); -diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h -index 8aafbb8..b0254de 100644 ---- a/kernel/rcutree_plugin.h -+++ b/kernel/rcutree_plugin.h -@@ -1907,15 +1907,6 @@ int rcu_needs_cpu(int cpu) - return rcu_needs_cpu_quick_check(cpu); - } - --/* -- * Check to see if we need to continue a callback-flush operations to -- * allow the last CPU to enter dyntick-idle mode. But fast dyntick-idle -- * entry is not configured, so we never do need to. -- */ --static void rcu_needs_cpu_flush(void) --{ --} -- - #else /* #if !defined(CONFIG_RCU_FAST_NO_HZ) */ - - #define RCU_NEEDS_CPU_FLUSHES 5 -@@ -1991,20 +1982,4 @@ int rcu_needs_cpu(int cpu) - return c; - } - --/* -- * Check to see if we need to continue a callback-flush operations to -- * allow the last CPU to enter dyntick-idle mode. -- */ --static void rcu_needs_cpu_flush(void) --{ -- int cpu = smp_processor_id(); -- unsigned long flags; -- -- if (per_cpu(rcu_dyntick_drain, cpu) <= 0) -- return; -- local_irq_save(flags); -- (void)rcu_needs_cpu(cpu); -- local_irq_restore(flags); --} -- - #endif /* #else #if !defined(CONFIG_RCU_FAST_NO_HZ) */ diff --git a/rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch b/rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch new file mode 100644 index 000000000..0946aad6b --- /dev/null +++ b/rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch @@ -0,0 +1,116 @@ +From efc3dbc37412c027e363736b4f4c74ee5e8ecffc Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Tue, 24 Jan 2012 17:03:44 -0500 +Subject: [PATCH] rds: Make rds_sock_lock BH rather than IRQ safe. + +rds_sock_info() triggers locking warnings because we try to perform a +local_bh_enable() (via sock_i_ino()) while hardware interrupts are +disabled (via taking rds_sock_lock). + +There is no reason for rds_sock_lock to be a hardware IRQ disabling +lock, none of these access paths run in hardware interrupt context. + +Therefore making it a BH disabling lock is safe and sufficient to +fix this bug. + +Reported-by: Kumar Sanghvi +Reported-by: Josh Boyer +Signed-off-by: David S. Miller +--- + net/rds/af_rds.c | 20 ++++++++------------ + 1 files changed, 8 insertions(+), 12 deletions(-) + +diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c +index bb6ad81..424ff62 100644 +--- a/net/rds/af_rds.c ++++ b/net/rds/af_rds.c +@@ -68,7 +68,6 @@ static int rds_release(struct socket *sock) + { + struct sock *sk = sock->sk; + struct rds_sock *rs; +- unsigned long flags; + + if (!sk) + goto out; +@@ -94,10 +93,10 @@ static int rds_release(struct socket *sock) + rds_rdma_drop_keys(rs); + rds_notify_queue_get(rs, NULL); + +- spin_lock_irqsave(&rds_sock_lock, flags); ++ spin_lock_bh(&rds_sock_lock); + list_del_init(&rs->rs_item); + rds_sock_count--; +- spin_unlock_irqrestore(&rds_sock_lock, flags); ++ spin_unlock_bh(&rds_sock_lock); + + rds_trans_put(rs->rs_transport); + +@@ -409,7 +408,6 @@ static const struct proto_ops rds_proto_ops = { + + static int __rds_create(struct socket *sock, struct sock *sk, int protocol) + { +- unsigned long flags; + struct rds_sock *rs; + + sock_init_data(sock, sk); +@@ -426,10 +424,10 @@ static int __rds_create(struct socket *sock, struct sock *sk, int protocol) + spin_lock_init(&rs->rs_rdma_lock); + rs->rs_rdma_keys = RB_ROOT; + +- spin_lock_irqsave(&rds_sock_lock, flags); ++ spin_lock_bh(&rds_sock_lock); + list_add_tail(&rs->rs_item, &rds_sock_list); + rds_sock_count++; +- spin_unlock_irqrestore(&rds_sock_lock, flags); ++ spin_unlock_bh(&rds_sock_lock); + + return 0; + } +@@ -471,12 +469,11 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len, + { + struct rds_sock *rs; + struct rds_incoming *inc; +- unsigned long flags; + unsigned int total = 0; + + len /= sizeof(struct rds_info_message); + +- spin_lock_irqsave(&rds_sock_lock, flags); ++ spin_lock_bh(&rds_sock_lock); + + list_for_each_entry(rs, &rds_sock_list, rs_item) { + read_lock(&rs->rs_recv_lock); +@@ -492,7 +489,7 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len, + read_unlock(&rs->rs_recv_lock); + } + +- spin_unlock_irqrestore(&rds_sock_lock, flags); ++ spin_unlock_bh(&rds_sock_lock); + + lens->nr = total; + lens->each = sizeof(struct rds_info_message); +@@ -504,11 +501,10 @@ static void rds_sock_info(struct socket *sock, unsigned int len, + { + struct rds_info_socket sinfo; + struct rds_sock *rs; +- unsigned long flags; + + len /= sizeof(struct rds_info_socket); + +- spin_lock_irqsave(&rds_sock_lock, flags); ++ spin_lock_bh(&rds_sock_lock); + + if (len < rds_sock_count) + goto out; +@@ -529,7 +525,7 @@ out: + lens->nr = rds_sock_count; + lens->each = sizeof(struct rds_info_socket); + +- spin_unlock_irqrestore(&rds_sock_lock, flags); ++ spin_unlock_bh(&rds_sock_lock); + } + + static void rds_exit(void) +-- +1.7.7.6 + diff --git a/rtl8192cu-Fix-WARNING-on-suspend-resume.patch b/rtl8192cu-Fix-WARNING-on-suspend-resume.patch index e784b1632..bdc8a5492 100644 --- a/rtl8192cu-Fix-WARNING-on-suspend-resume.patch +++ b/rtl8192cu-Fix-WARNING-on-suspend-resume.patch @@ -1,8 +1,3 @@ -From e234ca17f2d5ce23606fceef2df6c02f8555547e Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Wed, 11 Jan 2012 13:35:33 -0500 -Subject: [PATCH] rtl8192cu: Fix WARNING on suspend/resume - A recent LKML thread (http://lkml.indiana.edu/hypermail/linux/kernel/1112.3/00965.html) discusses warnings that occur during a suspend/resume cycle. The driver attempts to read the firmware file before userspace is ready, leading to the @@ -18,6 +13,8 @@ through a suspend/resume cycle, and does not have to be reread. This patch should fix the bug reported in https://bugzilla.redhat.com/show_bug.cgi?id=771002. +Note: This patch also touches rtl8192ce as the "firmware" loaded message +is now printed in the wrong place. Note: This patch also touches rtl8192ce as the "firmware" loaded message is now printed in the wrong place. @@ -27,30 +24,25 @@ Signed-off-by: Larry Finger Cc: Linus Torvalds Cc: Stable -Backported to Fedora 3.1.x. --- drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 1 - drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 1 + drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 58 +++++++++++++++++---- 3 files changed, 49 insertions(+), 11 deletions(-) -diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c -index 49a064b..e3c4ac7 100644 ---- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c -+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c -@@ -226,7 +226,6 @@ int rtl92c_download_fw(struct ieee80211_hw *hw) +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:07:58.830625006 -0500 ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:08:06.825439927 -0500 +@@ -227,7 +227,6 @@ int rtl92c_download_fw(struct ieee80211_ u32 fwsize; enum version_8192c version = rtlhal->version; - pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); if (!rtlhal->pfirmware) return 1; - -diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c -index 373dc78..9c3a8f1 100644 ---- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c -+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c -@@ -171,6 +171,7 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) + +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +@@ -186,6 +186,7 @@ int rtl92c_init_sw_vars(struct ieee80211 memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); rtlpriv->rtlhal.fwsize = firmware->size; release_firmware(firmware); @@ -58,21 +50,18 @@ index 373dc78..9c3a8f1 100644 return 0; } -diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c -index ef63c0d..f4230dd 100644 ---- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c -+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c -@@ -42,6 +42,9 @@ - #include "led.h" +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +@@ -43,6 +43,8 @@ #include "hw.h" #include + #include +#include +#include -+ MODULE_AUTHOR("Georgia "); MODULE_AUTHOR("Ziv Huang "); -@@ -50,6 +53,10 @@ MODULE_LICENSE("GPL"); +@@ -51,6 +53,10 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); @@ -83,10 +72,10 @@ index ef63c0d..f4230dd 100644 static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); -@@ -60,12 +67,21 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) - rtlpriv->dm.dm_flag = 0; - rtlpriv->dm.disable_framebursting = 0; +@@ -62,12 +68,21 @@ static int rtl92cu_init_sw_vars(struct i + rtlpriv->dm.disable_framebursting = false; rtlpriv->dm.thermalvalue = 0; + rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; - rtlpriv->rtlhal.pfirmware = vmalloc(0x4000); - if (!rtlpriv->rtlhal.pfirmware) { + @@ -107,7 +96,7 @@ index ef63c0d..f4230dd 100644 /* request fw */ err = request_firmware(&firmware, rtlpriv->cfg->fw_name, rtlpriv->io.dev); -@@ -80,9 +96,14 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) +@@ -82,9 +97,14 @@ static int rtl92cu_init_sw_vars(struct i release_firmware(firmware); return 1; } @@ -123,7 +112,7 @@ index ef63c0d..f4230dd 100644 return 0; } -@@ -91,12 +112,30 @@ static void rtl92cu_deinit_sw_vars(struct ieee80211_hw *hw) +@@ -93,12 +113,30 @@ static void rtl92cu_deinit_sw_vars(struc { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -156,7 +145,7 @@ index ef63c0d..f4230dd 100644 static struct rtl_hal_ops rtl8192cu_hal_ops = { .init_sw_vars = rtl92cu_init_sw_vars, .deinit_sw_vars = rtl92cu_deinit_sw_vars, -@@ -338,11 +377,10 @@ static struct usb_driver rtl8192cu_driver = { +@@ -374,11 +412,10 @@ static struct usb_driver rtl8192cu_drive .disconnect = rtl_usb_disconnect, .id_table = rtl8192c_usb_ids, @@ -172,6 +161,3 @@ index ef63c0d..f4230dd 100644 #ifdef CONFIG_AUTOSUSPEND .supports_autosuspend = 1, #endif --- -1.7.7.5 - diff --git a/samsung-laptop-brightness-fixes-3.2.patch b/samsung-laptop-brightness-fixes-3.2.patch deleted file mode 100644 index 61032176b..000000000 --- a/samsung-laptop-brightness-fixes-3.2.patch +++ /dev/null @@ -1,238 +0,0 @@ -From: Jason Stubbs -Date: Tue, 20 Sep 2011 16:16:13 +0000 (-0700) -Subject: Platform: Brightness quirk for samsung laptop driver -X-Git-Tag: v3.2-rc1~111^2~41 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=ac080523141d5bfa5f60ef2436480f645f915e9c - -Platform: Brightness quirk for samsung laptop driver - -On some Samsung laptops the brightness regulation works slightly different. -All SABI commands except for set_brightness work as expected. The behaviour -of set_brightness is as follows: - -- Setting a new brightness will only step one level toward the new brightness - level. For example, setting a level of 5 when the current level is 2 will - result in a brightness level of 3. -- A spurious KEY_BRIGHTNESS_UP or KEY_BRIGHTNESS_DOWN event is also generated - along with the change in brightness. -- Neither of the above two issues occur when changing from/to brightness - level 0. - -This patch adds detection and a non-intrusive workaround for the above issues. - -Signed-off-by: Jason Stubbs -Tested-by: David Herrmann -Signed-off-by: Greg Kroah-Hartman -Signed-off-by: Matthew Garrett ---- - -diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c -index 4d3bed4..6474e42 100644 ---- a/drivers/platform/x86/samsung-laptop.c -+++ b/drivers/platform/x86/samsung-laptop.c -@@ -226,6 +226,7 @@ static struct backlight_device *backlight_device; - static struct mutex sabi_mutex; - static struct platform_device *sdev; - static struct rfkill *rfk; -+static bool has_stepping_quirk; - - static int force; - module_param(force, bool, 0); -@@ -382,6 +383,17 @@ static void set_brightness(u8 user_brightness) - { - u8 user_level = user_brightness + sabi_config->min_brightness; - -+ if (has_stepping_quirk && user_level != 0) { -+ /* -+ * short circuit if the specified level is what's already set -+ * to prevent the screen from flickering needlessly -+ */ -+ if (user_brightness == read_brightness()) -+ return; -+ -+ sabi_set_command(sabi_config->commands.set_brightness, 0); -+ } -+ - sabi_set_command(sabi_config->commands.set_brightness, user_level); - } - -@@ -390,6 +402,34 @@ static int get_brightness(struct backlight_device *bd) - return (int)read_brightness(); - } - -+static void check_for_stepping_quirk(void) -+{ -+ u8 initial_level = read_brightness(); -+ u8 check_level; -+ -+ /* -+ * Some laptops exhibit the strange behaviour of stepping toward -+ * (rather than setting) the brightness except when changing to/from -+ * brightness level 0. This behaviour is checked for here and worked -+ * around in set_brightness. -+ */ -+ -+ if (initial_level <= 2) -+ check_level = initial_level + 2; -+ else -+ check_level = initial_level - 2; -+ -+ has_stepping_quirk = false; -+ set_brightness(check_level); -+ -+ if (read_brightness() != check_level) { -+ has_stepping_quirk = true; -+ pr_info("enabled workaround for brightness stepping quirk\n"); -+ } -+ -+ set_brightness(initial_level); -+} -+ - static int update_status(struct backlight_device *bd) - { - set_brightness(bd->props.brightness); -@@ -805,6 +845,9 @@ static int __init samsung_init(void) - } - } - -+ /* Check for stepping quirk */ -+ check_for_stepping_quirk(); -+ - /* knock up a platform device to hang stuff off of */ - sdev = platform_device_register_simple("samsung", -1, NULL, 0); - if (IS_ERR(sdev)) -From: Jason Stubbs -Date: Tue, 20 Sep 2011 16:16:14 +0000 (-0700) -Subject: Platform: Samsung laptop DMI info for NC210/NC110 -X-Git-Tag: v3.2-rc1~111^2~40 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=7b3c257ce4267e004a7c7e68c05d1eb70da8c972 - -Platform: Samsung laptop DMI info for NC210/NC110 - -This patch just adds the DMI info for the samsung laptop driver to work with -the NC210/NC110. It needs the brightness quirk patch for proper support. - -Signed-off-by: Jason Stubbs -Signed-off-by: Greg Kroah-Hartman -Signed-off-by: Matthew Garrett ---- - -diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c -index 6474e42..8ffab50 100644 ---- a/drivers/platform/x86/samsung-laptop.c -+++ b/drivers/platform/x86/samsung-laptop.c -@@ -737,6 +737,15 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { - }, - .callback = dmi_check_cb, - }, -+ { -+ .ident = "NC210/NC110", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"), -+ DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"), -+ }, -+ .callback = dmi_check_cb, -+ }, - { }, - }; - MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); -From: Raul Gutierrez Segales -Date: Tue, 20 Sep 2011 16:16:15 +0000 (-0700) -Subject: Platform: fix samsung-laptop DMI identification for N220 model -X-Git-Tag: v3.2-rc1~111^2~39 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=f689c875c13c9d62b3c4de09cd5dad66549f700d - -Platform: fix samsung-laptop DMI identification for N220 model - -This is a follow-up for commit 78a7539b, which didn't cover the -Samsung N220 laptop. With this backlight brightness works nicely -on the N220 netbook. - -Signed-off-by: Raul Gutierrez Segales -Signed-off-by: Greg Kroah-Hartman -Signed-off-by: Matthew Garrett ---- - -diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c -index 8ffab50..1e436eb 100644 ---- a/drivers/platform/x86/samsung-laptop.c -+++ b/drivers/platform/x86/samsung-laptop.c -@@ -663,6 +663,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { - .callback = dmi_check_cb, - }, - { -+ .ident = "N220", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, -+ "SAMSUNG ELECTRONICS CO., LTD."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "N220"), -+ DMI_MATCH(DMI_BOARD_NAME, "N220"), -+ }, -+ .callback = dmi_check_cb, -+ }, -+ { - .ident = "N150/N210/N220/N230", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, -From: John Serock -Date: Thu, 13 Oct 2011 10:42:01 +0000 (-0400) -Subject: Platform: Detect samsung laptop quirk when initial level is zero -X-Git-Tag: v3.2-rc1~111^2~29 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=ba05b237372bad82533d1f717569d1d817ff3c27 - -Platform: Detect samsung laptop quirk when initial level is zero - -This patch depends on the "Platform: Brightness quirk for samsung -laptop driver" patch from Jason Stubbs. This patch adds a check for an -initial brightness level of 0; if the level is 0, this patch changes -the brightness level to 1 before the driver attempts to detect the -brightness quirk. - -The Samsung N150 netbook experiences the brightness quirk. Without -Jason's patch, the only brightness levels available on the N150 are 0, -1, and 8. This patch ensures that, when the initial brightness level -is 0, the samsang-laptop driver detects the brightness quirk on the -N150, thereby making brightness levels 0 through 8 available. - -Signed-off-by: John Serock -Acked-by: Jason Stubbs -Signed-off-by: Matthew Garrett ---- - -diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c -index 1e436eb..31ddd57 100644 ---- a/drivers/platform/x86/samsung-laptop.c -+++ b/drivers/platform/x86/samsung-laptop.c -@@ -404,8 +404,9 @@ static int get_brightness(struct backlight_device *bd) - - static void check_for_stepping_quirk(void) - { -- u8 initial_level = read_brightness(); -+ u8 initial_level; - u8 check_level; -+ u8 orig_level = read_brightness(); - - /* - * Some laptops exhibit the strange behaviour of stepping toward -@@ -414,6 +415,11 @@ static void check_for_stepping_quirk(void) - * around in set_brightness. - */ - -+ if (orig_level == 0) -+ set_brightness(1); -+ -+ initial_level = read_brightness(); -+ - if (initial_level <= 2) - check_level = initial_level + 2; - else -@@ -427,7 +433,7 @@ static void check_for_stepping_quirk(void) - pr_info("enabled workaround for brightness stepping quirk\n"); - } - -- set_brightness(initial_level); -+ set_brightness(orig_level); - } - - static int update_status(struct backlight_device *bd) diff --git a/sources b/sources index 030427a02..6c0833def 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -a8e1c25a93a685ec2a1c3a808715fe9d patch-3.1.10.bz2 +364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz +5e53edbf75fcaa3a8d1697f3a053102d patch-3.2.2.xz diff --git a/sysfs-msi-irq-per-device.patch b/sysfs-msi-irq-per-device.patch new file mode 100644 index 000000000..a2bf57c92 --- /dev/null +++ b/sysfs-msi-irq-per-device.patch @@ -0,0 +1,239 @@ +From: Neil Horman +Date: Thu, 6 Oct 2011 18:08:18 +0000 (-0400) +Subject: PCI/sysfs: add per pci device msi[x] irq listing (v5) +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fjbarnes%2Fpci.git;a=commitdiff_plain;h=933aa5c1f69aa650f59ba783307fc7ed7cc5fafa + +PCI/sysfs: add per pci device msi[x] irq listing (v5) + +This patch adds a per-pci-device subdirectory in sysfs called: +/sys/bus/pci/devices//msi_irqs + +This sub-directory exports the set of msi vectors allocated by a given +pci device, by creating a numbered sub-directory for each vector beneath +msi_irqs. For each vector various attributes can be exported. +Currently the only attribute is called mode, which tracks the +operational mode of that vector (msi vs. msix) + +Acked-by: Greg Kroah-Hartman +Signed-off-by: Jesse Barnes +--- + +diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci +index 349ecf2..34f5110 100644 +--- a/Documentation/ABI/testing/sysfs-bus-pci ++++ b/Documentation/ABI/testing/sysfs-bus-pci +@@ -66,6 +66,24 @@ Description: + re-discover previously removed devices. + Depends on CONFIG_HOTPLUG. + ++What: /sys/bus/pci/devices/.../msi_irqs/ ++Date: September, 2011 ++Contact: Neil Horman ++Description: ++ The /sys/devices/.../msi_irqs directory contains a variable set ++ of sub-directories, with each sub-directory being named after a ++ corresponding msi irq vector allocated to that device. Each ++ numbered sub-directory N contains attributes of that irq. ++ Note that this directory is not created for device drivers which ++ do not support msi irqs ++ ++What: /sys/bus/pci/devices/.../msi_irqs//mode ++Date: September 2011 ++Contact: Neil Horman ++Description: ++ This attribute indicates the mode that the irq vector named by ++ the parent directory is in (msi vs. msix) ++ + What: /sys/bus/pci/devices/.../remove + Date: January 2009 + Contact: Linux PCI developers +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index 2f10328..73613e2 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -322,6 +322,8 @@ static void free_msi_irqs(struct pci_dev *dev) + if (list_is_last(&entry->list, &dev->msi_list)) + iounmap(entry->mask_base); + } ++ kobject_del(&entry->kobj); ++ kobject_put(&entry->kobj); + list_del(&entry->list); + kfree(entry); + } +@@ -402,6 +404,98 @@ void pci_restore_msi_state(struct pci_dev *dev) + } + EXPORT_SYMBOL_GPL(pci_restore_msi_state); + ++ ++#define to_msi_attr(obj) container_of(obj, struct msi_attribute, attr) ++#define to_msi_desc(obj) container_of(obj, struct msi_desc, kobj) ++ ++struct msi_attribute { ++ struct attribute attr; ++ ssize_t (*show)(struct msi_desc *entry, struct msi_attribute *attr, ++ char *buf); ++ ssize_t (*store)(struct msi_desc *entry, struct msi_attribute *attr, ++ const char *buf, size_t count); ++}; ++ ++static ssize_t show_msi_mode(struct msi_desc *entry, struct msi_attribute *atr, ++ char *buf) ++{ ++ return sprintf(buf, "%s\n", entry->msi_attrib.is_msix ? "msix" : "msi"); ++} ++ ++static ssize_t msi_irq_attr_show(struct kobject *kobj, ++ struct attribute *attr, char *buf) ++{ ++ struct msi_attribute *attribute = to_msi_attr(attr); ++ struct msi_desc *entry = to_msi_desc(kobj); ++ ++ if (!attribute->show) ++ return -EIO; ++ ++ return attribute->show(entry, attribute, buf); ++} ++ ++static const struct sysfs_ops msi_irq_sysfs_ops = { ++ .show = msi_irq_attr_show, ++}; ++ ++static struct msi_attribute mode_attribute = ++ __ATTR(mode, S_IRUGO, show_msi_mode, NULL); ++ ++ ++struct attribute *msi_irq_default_attrs[] = { ++ &mode_attribute.attr, ++ NULL ++}; ++ ++void msi_kobj_release(struct kobject *kobj) ++{ ++ struct msi_desc *entry = to_msi_desc(kobj); ++ ++ pci_dev_put(entry->dev); ++} ++ ++static struct kobj_type msi_irq_ktype = { ++ .release = msi_kobj_release, ++ .sysfs_ops = &msi_irq_sysfs_ops, ++ .default_attrs = msi_irq_default_attrs, ++}; ++ ++static int populate_msi_sysfs(struct pci_dev *pdev) ++{ ++ struct msi_desc *entry; ++ struct kobject *kobj; ++ int ret; ++ int count = 0; ++ ++ pdev->msi_kset = kset_create_and_add("msi_irqs", NULL, &pdev->dev.kobj); ++ if (!pdev->msi_kset) ++ return -ENOMEM; ++ ++ list_for_each_entry(entry, &pdev->msi_list, list) { ++ kobj = &entry->kobj; ++ kobj->kset = pdev->msi_kset; ++ pci_dev_get(pdev); ++ ret = kobject_init_and_add(kobj, &msi_irq_ktype, NULL, ++ "%u", entry->irq); ++ if (ret) ++ goto out_unroll; ++ ++ count++; ++ } ++ ++ return 0; ++ ++out_unroll: ++ list_for_each_entry(entry, &pdev->msi_list, list) { ++ if (!count) ++ break; ++ kobject_del(&entry->kobj); ++ kobject_put(&entry->kobj); ++ count--; ++ } ++ return ret; ++} ++ + /** + * msi_capability_init - configure device's MSI capability structure + * @dev: pointer to the pci_dev data structure of MSI device function +@@ -453,6 +547,13 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) + return ret; + } + ++ ret = populate_msi_sysfs(dev); ++ if (ret) { ++ msi_mask_irq(entry, mask, ~mask); ++ free_msi_irqs(dev); ++ return ret; ++ } ++ + /* Set MSI enabled bits */ + pci_intx_for_msi(dev, 0); + msi_set_enable(dev, pos, 1); +@@ -573,6 +674,12 @@ static int msix_capability_init(struct pci_dev *dev, + + msix_program_entries(dev, entries); + ++ ret = populate_msi_sysfs(dev); ++ if (ret) { ++ ret = 0; ++ goto error; ++ } ++ + /* Set MSI-X enabled bits and unmask the function */ + pci_intx_for_msi(dev, 0); + dev->msix_enabled = 1; +@@ -731,6 +838,8 @@ void pci_disable_msi(struct pci_dev *dev) + + pci_msi_shutdown(dev); + free_msi_irqs(dev); ++ kset_unregister(dev->msi_kset); ++ dev->msi_kset = NULL; + } + EXPORT_SYMBOL(pci_disable_msi); + +@@ -829,6 +938,8 @@ void pci_disable_msix(struct pci_dev *dev) + + pci_msix_shutdown(dev); + free_msi_irqs(dev); ++ kset_unregister(dev->msi_kset); ++ dev->msi_kset = NULL; + } + EXPORT_SYMBOL(pci_disable_msix); + +diff --git a/include/linux/msi.h b/include/linux/msi.h +index 05acced..ce93a34 100644 +--- a/include/linux/msi.h ++++ b/include/linux/msi.h +@@ -1,6 +1,7 @@ + #ifndef LINUX_MSI_H + #define LINUX_MSI_H + ++#include + #include + + struct msi_msg { +@@ -44,6 +45,8 @@ struct msi_desc { + + /* Last set MSI message */ + struct msi_msg msg; ++ ++ struct kobject kobj; + }; + + /* +diff --git a/include/linux/pci.h b/include/linux/pci.h +index 7cda65b..84225c7 100644 +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -336,6 +336,7 @@ struct pci_dev { + struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */ + #ifdef CONFIG_PCI_MSI + struct list_head msi_list; ++ struct kset *msi_kset; + #endif + struct pci_vpd *vpd; + #ifdef CONFIG_PCI_ATS diff --git a/thp-reduce-khugepaged-freezing-latency.patch b/thp-reduce-khugepaged-freezing-latency.patch deleted file mode 100644 index b7b205177..000000000 --- a/thp-reduce-khugepaged-freezing-latency.patch +++ /dev/null @@ -1,54 +0,0 @@ -From: Andrea Arcangeli -Subject: thp: reduce khugepaged freezing latency - -Use wait_event_freezable_timeout() instead of -schedule_timeout_interruptible() to avoid missing freezer wakeups. A -try_to_freeze() would have been needed in the -khugepaged_alloc_hugepage tight loop too in case of the allocation -failing repeatedly, and wait_event_freezable_timeout will provide it -too. - -khugepaged would still freeze just fine by trying again the next -minute but it's better if it freezes immediately. - -Reported-by: Jiri Slaby -Signed-off-by: Andrea Arcangeli - -diff --git a/mm/huge_memory.c b/mm/huge_memory.c -index 4298aba..fd925d0 100644 ---- a/mm/huge_memory.c -+++ b/mm/huge_memory.c -@@ -2259,12 +2259,9 @@ static void khugepaged_do_scan(struct page **hpage) - - static void khugepaged_alloc_sleep(void) - { -- DEFINE_WAIT(wait); -- add_wait_queue(&khugepaged_wait, &wait); -- schedule_timeout_interruptible( -- msecs_to_jiffies( -- khugepaged_alloc_sleep_millisecs)); -- remove_wait_queue(&khugepaged_wait, &wait); -+ wait_event_freezable_timeout(khugepaged_wait, false, -+ msecs_to_jiffies( -+ khugepaged_alloc_sleep_millisecs)); - } - - #ifndef CONFIG_NUMA -@@ -2313,14 +2310,11 @@ static void khugepaged_loop(void) - if (unlikely(kthread_should_stop())) - break; - if (khugepaged_has_work()) { -- DEFINE_WAIT(wait); - if (!khugepaged_scan_sleep_millisecs) - continue; -- add_wait_queue(&khugepaged_wait, &wait); -- schedule_timeout_interruptible( -+ wait_event_freezable_timeout(khugepaged_wait, false, - msecs_to_jiffies( - khugepaged_scan_sleep_millisecs)); -- remove_wait_queue(&khugepaged_wait, &wait); - } else if (khugepaged_enabled()) - wait_event_freezable(khugepaged_wait, - khugepaged_wait_event()); - - diff --git a/tpm_tis-delay-after-aborting-cmd.patch b/tpm_tis-delay-after-aborting-cmd.patch new file mode 100644 index 000000000..315284f50 --- /dev/null +++ b/tpm_tis-delay-after-aborting-cmd.patch @@ -0,0 +1,17 @@ +This patch adds a delay after aborting a command. Some TPMs need +this and will not process the subsequent command correctly otherwise. + +Signed-off-by: Stefan Berger + +--- linux-3.1.noarch/drivers/char/tpm/tpm_tis.c~ 2011-12-20 18:08:01.654464487 -0500 ++++ linux-3.1.noarch/drivers/char/tpm/tpm_tis.c 2011-12-20 18:08:23.476380364 -0500 +@@ -432,6 +432,9 @@ static int probe_itpm(struct tpm_chip *c + out: + itpm = rem_itpm; + tpm_tis_ready(chip); ++ /* some TPMs need a break here otherwise they will not work ++ * correctly on the immediately subsequent command */ ++ msleep(chip->vendor.timeout_b); + release_locality(chip, chip->vendor.locality, 0); + + return rc; diff --git a/udlfb-bind-framebuffer-to-interface.patch b/udlfb-bind-framebuffer-to-interface.patch deleted file mode 100644 index 1c5c6df9b..000000000 --- a/udlfb-bind-framebuffer-to-interface.patch +++ /dev/null @@ -1,33 +0,0 @@ -From c91a793f66d5b06292aa431ae3a36c8aca991fa3 Mon Sep 17 00:00:00 2001 -From: Kay Sievers -Date: Tue, 5 Jul 2011 17:04:11 -0700 -Subject: [PATCH] drivers/video/udlfb bind framebuffer to interface. - -Udlfb has been binding the framebuffer device to its parent, which -isn't correct and causes confusion with operations like udev remove. - -Coming plug and play multiseat support is dependent on this fix. - -Signed-off-by: Kay Sievers -Signed-off-by: Bernie Thompson -Signed-off-by: Paul Mundt ---- - drivers/video/udlfb.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c -index 816a4fd..c6584c9 100644 ---- a/drivers/video/udlfb.c -+++ b/drivers/video/udlfb.c -@@ -1549,7 +1549,7 @@ static int dlfb_usb_probe(struct usb_interface *interface, - /* We don't register a new USB class. Our client interface is fbdev */ - - /* allocates framebuffer driver structure, not framebuffer memory */ -- info = framebuffer_alloc(0, &usbdev->dev); -+ info = framebuffer_alloc(0, &interface->dev); - if (!info) { - retval = -ENOMEM; - pr_err("framebuffer_alloc failed\n"); --- -1.7.4.4 - diff --git a/utrace.patch b/utrace.patch index 576c737f3..060d351e5 100644 --- a/utrace.patch +++ b/utrace.patch @@ -1,39 +1,38 @@ From davej Wed Aug 3 15:16:11 2011 +From oleg@redhat.com Mon Nov 21 15:06:14 2011 Return-Path: oleg@redhat.com -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:11 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:37 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:14 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 92D6F9D8C5; - Wed, 3 Aug 2011 15:12:08 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id RRq2PiCBdMzK; Wed, 3 Aug 2011 15:12:08 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 75C149D898; - Wed, 3 Aug 2011 15:12:08 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9A1F8D50F1; + Mon, 21 Nov 2011 15:06:14 -0500 (EST) +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 gJzpul4rDNnA; Mon, 21 Nov 2011 15:06:14 -0500 (EST) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7DD4BD50EA; + Mon, 21 Nov 2011 15:06:14 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JC01d029136; - Wed, 3 Aug 2011 15:12:01 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6BJJ022074; + Mon, 21 Nov 2011 15:06:12 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:28 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:26 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:32 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:30 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 01/31] utrace core -Message-ID: <20110803190926.GA30903@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 01/33] utrace core +Message-ID: <20111121200130.GA27756@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO Content-Length: 139951 Lines: 3867 @@ -711,10 +710,10 @@ index 3a1dafd..f0c0ea2 100644 if (p->files) fdt = files_fdtable(p->files); diff --git a/include/linux/sched.h b/include/linux/sched.h -index 20b03bf..c6d79af 100644 +index 68daf4f..4d45f93 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h -@@ -1406,6 +1406,11 @@ struct task_struct { +@@ -1403,6 +1403,11 @@ struct task_struct { #endif seccomp_t seccomp; @@ -1425,7 +1424,7 @@ index 0000000..f251efe + +#endif /* linux/utrace.h */ diff --git a/init/Kconfig b/init/Kconfig -index d627783..7afce1f 100644 +index 43298f9..3f670e5 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -372,6 +372,15 @@ config AUDIT_TREE @@ -1445,7 +1444,7 @@ index d627783..7afce1f 100644 menu "RCU Subsystem" diff --git a/kernel/Makefile b/kernel/Makefile -index d06467f..85828da 100644 +index e898c5b..e43bbfb 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o @@ -3906,47 +3905,40 @@ index 0000000..ef856c9 1.5.5.1 -From davej Wed Aug 3 15:16:13 2011 +From oleg@redhat.com Mon Nov 21 15:06:17 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:13 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:37 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:17 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 419B39D8CF; - Wed, 3 Aug 2011 15:12:11 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1CCED128D6B; + Mon, 21 Nov 2011 15:06:17 -0500 (EST) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id AmaThyCcp1K4; Wed, 3 Aug 2011 15:12:11 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2A0B29CE59; - Wed, 3 Aug 2011 15:12:11 -0400 (EDT) + with ESMTP id FWdJDV74o-ay; Mon, 21 Nov 2011 15:06:17 -0500 (EST) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 082081285E4; + Mon, 21 Nov 2011 15:06:17 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JC3DW023262; - Wed, 3 Aug 2011 15:12:04 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6E7d015251; + Mon, 21 Nov 2011 15:06:15 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:31 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:29 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:35 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:33 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 02/31] utrace: add utrace_init_task/utrace_free_task calls -Message-ID: <20110803190929.GA30907@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 02/33] utrace: add utrace_init_task/utrace_free_task calls +Message-ID: <20111121200133.GA27759@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO Content-Length: 1295 Lines: 47 @@ -3966,7 +3958,7 @@ Signed-off-by: Oleg Nesterov 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/kernel/fork.c b/kernel/fork.c -index e7ceaca..a9891da 100644 +index ba0d172..b8719c2 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -66,6 +66,7 @@ @@ -3986,7 +3978,7 @@ index e7ceaca..a9891da 100644 free_task_struct(tsk); } EXPORT_SYMBOL(free_task); -@@ -1096,6 +1099,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, +@@ -1093,6 +1096,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, if (!p) goto fork_out; @@ -3999,47 +3991,40 @@ index e7ceaca..a9891da 100644 1.5.5.1 -From davej Wed Aug 3 15:16:18 2011 +From oleg@redhat.com Mon Nov 21 15:06:20 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:18 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:07 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:20 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F28379DE70; - Wed, 3 Aug 2011 15:12:13 -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 p92IDp0LZ5jX; Wed, 3 Aug 2011 15:12:13 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D4E339DE68; - Wed, 3 Aug 2011 15:12:13 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8779AD87BC; + Mon, 21 Nov 2011 15:06:20 -0500 (EST) +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 umzAMwRd7rMt; Mon, 21 Nov 2011 15:06:20 -0500 (EST) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 72C98D8707; + Mon, 21 Nov 2011 15:06:20 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JC6IA023283; - Wed, 3 Aug 2011 15:12:07 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6HAj015261; + Mon, 21 Nov 2011 15:06:18 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:34 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:32 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:39 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:36 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 03/31] tracehooks: add utrace hooks -Message-ID: <20110803190932.GA30915@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 03/33] tracehooks: add utrace hooks +Message-ID: <20111121200136.GA27766@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO Content-Length: 2310 Lines: 75 @@ -4120,48 +4105,41 @@ index a71a292..8cc28bc 100644 1.5.5.1 -From davej Wed Aug 3 15:16:14 2011 +From oleg@redhat.com Mon Nov 21 15:06:23 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:14 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:37 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:23 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 92FCA9D8FA; - Wed, 3 Aug 2011 15:12:16 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id lQaZCHUpw8DT; Wed, 3 Aug 2011 15:12:16 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7479B9D8C9; - Wed, 3 Aug 2011 15:12:16 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6559BD4FDE; + Mon, 21 Nov 2011 15:06:23 -0500 (EST) +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 6BjISiO+cS1U; Mon, 21 Nov 2011 15:06:23 -0500 (EST) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 50366D4C39; + Mon, 21 Nov 2011 15:06:23 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JC91G023308; - Wed, 3 Aug 2011 15:12:09 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6KT9017533; + Mon, 21 Nov 2011 15:06:21 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:37 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:35 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:42 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:39 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 04/31] tracehooks: reintroduce +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 04/33] tracehooks: reintroduce tracehook_consider_fatal_signal() -Message-ID: <20110803190935.GA30918@redhat.com> +Message-ID: <20111121200139.GA27769@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO Content-Length: 3257 Lines: 90 @@ -4177,7 +4155,7 @@ Signed-off-by: Oleg Nesterov 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c -index ffabcd9..1018ab6 100644 +index a9807dd..f506e1b 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -329,7 +329,7 @@ void __kprobes do_per_trap(struct pt_regs *regs) @@ -4189,7 +4167,7 @@ index ffabcd9..1018ab6 100644 return; info.si_signo = SIGTRAP; info.si_errno = 0; -@@ -428,7 +428,7 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code, +@@ -429,7 +429,7 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code, if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) return; if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) { @@ -4232,7 +4210,7 @@ index 8cc28bc..ec2af67 100644 /** * set_notify_resume - cause tracehook_notify_resume() to be called diff --git a/kernel/signal.c b/kernel/signal.c -index 291c970..d7ef0da 100644 +index b3f78d0..d7b90cd 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -494,7 +494,7 @@ int unhandled_signal(struct task_struct *tsk, int sig) @@ -4257,46 +4235,39 @@ index 291c970..d7ef0da 100644 1.5.5.1 -From davej Wed Aug 3 15:16:20 2011 +From oleg@redhat.com Mon Nov 21 15:06:26 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:20 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:08 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:25 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 374FE9DE74; - Wed, 3 Aug 2011 15:12:19 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E7A2DD498A; + Mon, 21 Nov 2011 15:06:25 -0500 (EST) 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 Sun0Twp72xGV; Wed, 3 Aug 2011 15:12:19 -0400 (EDT) + with ESMTP id 4L9zskFVsr4I; Mon, 21 Nov 2011 15:06:25 -0500 (EST) Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 223E39DD25; - Wed, 3 Aug 2011 15:12:19 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D3487D4C39; + Mon, 21 Nov 2011 15:06:25 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCBgK008326; - Wed, 3 Aug 2011 15:12:12 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6Nnp017552; + Mon, 21 Nov 2011 15:06:24 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:39 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:37 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:44 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:42 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 05/31] add utrace hooks into sig_ignored() and +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 05/33] add utrace hooks into sig_ignored() and recalc_sigpending() -Message-ID: <20110803190937.GA30926@redhat.com> +Message-ID: <20111121200142.GA27777@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO @@ -4327,7 +4298,7 @@ index f251efe..1b8da1c 100644 /* diff --git a/kernel/signal.c b/kernel/signal.c -index d7ef0da..0f9af0b 100644 +index d7b90cd..8594cb2 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -87,7 +87,7 @@ static int sig_ignored(struct task_struct *t, int sig, int from_ancestor_ns) @@ -4355,45 +4326,38 @@ index d7ef0da..0f9af0b 100644 1.5.5.1 -From davej Wed Aug 3 15:16:21 2011 +From oleg@redhat.com Mon Nov 21 15:06:28 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:21 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:09 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:28 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 054279DE7D; - Wed, 3 Aug 2011 15:12:22 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6E4A6D4F4A; + Mon, 21 Nov 2011 15:06:28 -0500 (EST) 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 1BosZIzYSIW0; Wed, 3 Aug 2011 15:12:21 -0400 (EDT) + with ESMTP id vEeGLyK1+rX9; Mon, 21 Nov 2011 15:06:28 -0500 (EST) Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E41DC9DE7B; - Wed, 3 Aug 2011 15:12:21 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5AD50D4C39; + Mon, 21 Nov 2011 15:06:28 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JCEgD022264; - Wed, 3 Aug 2011 15:12:15 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6QOB029543; + Mon, 21 Nov 2011 15:06:26 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:42 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:40 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:47 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:45 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 06/31] restore the EXEC/EXIT/CLONE utrace hooks -Message-ID: <20110803190940.GA30929@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 06/33] restore the EXEC/EXIT/CLONE utrace hooks +Message-ID: <20111121200145.GA27780@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO @@ -4412,10 +4376,10 @@ Signed-off-by: Oleg Nesterov 4 files changed, 15 insertions(+), 1 deletions(-) diff --git a/fs/exec.c b/fs/exec.c -index da80612..a0814cd 100644 +index 3625464..7d8f8bd 100644 --- a/fs/exec.c +++ b/fs/exec.c -@@ -1401,9 +1401,12 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) +@@ -1397,9 +1397,12 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) */ bprm->recursion_depth = depth; if (retval >= 0) { @@ -4447,10 +4411,10 @@ index 1b8da1c..9ac0b1b 100644 /* diff --git a/kernel/exit.c b/kernel/exit.c -index 2913b35..c1b0ab6 100644 +index d0b7d98..f5eba3b 100644 --- a/kernel/exit.c +++ b/kernel/exit.c -@@ -913,6 +913,7 @@ NORET_TYPE void do_exit(long code) +@@ -911,6 +911,7 @@ NORET_TYPE void do_exit(long code) */ set_fs(USER_DS); @@ -4459,10 +4423,10 @@ index 2913b35..c1b0ab6 100644 validate_creds_for_do_exit(tsk); diff --git a/kernel/fork.c b/kernel/fork.c -index a9891da..37f4a07 100644 +index b8719c2..09d5049 100644 --- a/kernel/fork.c +++ b/kernel/fork.c -@@ -1539,6 +1539,8 @@ long do_fork(unsigned long clone_flags, +@@ -1535,6 +1535,8 @@ long do_fork(unsigned long clone_flags, audit_finish_fork(p); @@ -4471,7 +4435,7 @@ index a9891da..37f4a07 100644 /* * We set PF_STARTING at creation in case tracing wants to * use this to distinguish a fully live task from one that -@@ -1550,6 +1552,8 @@ long do_fork(unsigned long clone_flags, +@@ -1546,6 +1548,8 @@ long do_fork(unsigned long clone_flags, wake_up_new_task(p); /* forking complete and child started to run, tell ptracer */ @@ -4484,48 +4448,41 @@ index a9891da..37f4a07 100644 1.5.5.1 -From davej Wed Aug 3 15:16:23 2011 +From oleg@redhat.com Mon Nov 21 15:06:30 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:23 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:13 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:30 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B36EC9DE82; - Wed, 3 Aug 2011 15:12:24 -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 7Qqv+lXfqHw6; Wed, 3 Aug 2011 15:12:24 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9F8AF9DD25; - Wed, 3 Aug 2011 15:12:24 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D248D1284E0; + Mon, 21 Nov 2011 15:06:30 -0500 (EST) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id divvekTmLScS; Mon, 21 Nov 2011 15:06:30 -0500 (EST) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BDC9412800E; + Mon, 21 Nov 2011 15:06:30 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCH0U023349; - Wed, 3 Aug 2011 15:12:17 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6Shj029546; + Mon, 21 Nov 2011 15:06:29 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:45 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:43 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:49 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:47 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 07/31] utrace: utrace_report_death() can use +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 07/33] utrace: utrace_report_death() can use task_utrace_struct() -Message-ID: <20110803190943.GA30936@redhat.com> +Message-ID: <20111121200147.GA27787@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO Content-Length: 1692 Lines: 44 @@ -4575,45 +4532,38 @@ index ef856c9..1e750ad 100644 1.5.5.1 -From davej Wed Aug 3 15:16:15 2011 +From oleg@redhat.com Mon Nov 21 15:06:33 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:15 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:39 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:33 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 76DA49D9C7; - Wed, 3 Aug 2011 15:12:27 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 25xHJjCTouA4; Wed, 3 Aug 2011 15:12:27 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 62E1BD50A3; + Mon, 21 Nov 2011 15:06:33 -0500 (EST) +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 FB36YkOAHDc5; Mon, 21 Nov 2011 15:06:33 -0500 (EST) Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 490E79D9AB; - Wed, 3 Aug 2011 15:12:27 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4D161D4C39; + Mon, 21 Nov 2011 15:06:33 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCKXo023360; - Wed, 3 Aug 2011 15:12:20 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6VBW022130; + Mon, 21 Nov 2011 15:06:31 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:47 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:45 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:52 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:50 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 08/31] restore the DEATH/REAP utrace hooks -Message-ID: <20110803190945.GA30939@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 08/33] restore the DEATH/REAP utrace hooks +Message-ID: <20111121200150.GA27790@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO @@ -4666,7 +4616,7 @@ index 9a2e2f4..cf13839 100644 + #endif /* linux/utrace.h */ diff --git a/kernel/exit.c b/kernel/exit.c -index c1b0ab6..ba5ba22 100644 +index f5eba3b..746c5df 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -168,6 +168,8 @@ void release_task(struct task_struct * p) @@ -4678,7 +4628,7 @@ index c1b0ab6..ba5ba22 100644 /* don't need to get the RCU readlock here - the process is dead and * can't be modifying its own credentials. But shut RCU-lockdep up */ rcu_read_lock(); -@@ -860,6 +862,8 @@ static void exit_notify(struct task_struct *tsk, int group_dead) +@@ -858,6 +860,8 @@ static void exit_notify(struct task_struct *tsk, int group_dead) wake_up_process(tsk->signal->group_exit_task); write_unlock_irq(&tasklist_lock); @@ -4691,47 +4641,40 @@ index c1b0ab6..ba5ba22 100644 1.5.5.1 -From davej Wed Aug 3 15:22:02 2011 +From oleg@redhat.com Mon Nov 21 15:06:35 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:22:02 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:17:16 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:35 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 26DB69DE8C; - Wed, 3 Aug 2011 15:12:30 -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 DbxGfmFvtTiR; Wed, 3 Aug 2011 15:12:30 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 0A30A9DE91; - Wed, 3 Aug 2011 15:12:30 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D4AB3D8761; + Mon, 21 Nov 2011 15:06:35 -0500 (EST) +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 TiShkH1f6rnj; Mon, 21 Nov 2011 15:06:35 -0500 (EST) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BCB85D877F; + Mon, 21 Nov 2011 15:06:35 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCMDQ008389; - Wed, 3 Aug 2011 15:12:23 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6XNu015312; + Mon, 21 Nov 2011 15:06:34 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:50 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:48 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:54 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:52 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 09/31] utrace: remove jobctl bits -Message-ID: <20110803190948.GA30942@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 09/33] utrace: remove jobctl bits +Message-ID: <20111121200152.GA27793@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO Content-Length: 1888 Lines: 56 @@ -4793,47 +4736,40 @@ index 1e750ad..5d3974e 100644 1.5.5.1 -From davej Wed Aug 3 15:16:17 2011 +From oleg@redhat.com Mon Nov 21 15:06:38 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:17 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:52 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:38 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id AB6E39DA46; - Wed, 3 Aug 2011 15:12:32 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id LkzmRGslEelr; Wed, 3 Aug 2011 15:12:32 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 959659DA60; - Wed, 3 Aug 2011 15:12:32 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 425CED8707; + Mon, 21 Nov 2011 15:06:38 -0500 (EST) +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 9paRC+dwSflh; Mon, 21 Nov 2011 15:06:38 -0500 (EST) +Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2DDBCD8410; + Mon, 21 Nov 2011 15:06:38 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCPx7023400; - Wed, 3 Aug 2011 15:12:25 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6a31031355; + Mon, 21 Nov 2011 15:06:36 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:53 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:51 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:56 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:55 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 10/31] ptrace: take ->siglock around s/TRACED/RUNNING/ -Message-ID: <20110803190951.GA30949@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 10/33] ptrace: take ->siglock around s/TRACED/RUNNING/ +Message-ID: <20111121200155.GA27801@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO Content-Length: 1624 Lines: 56 @@ -4851,7 +4787,7 @@ Signed-off-by: Oleg Nesterov 2 files changed, 10 insertions(+), 1 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 9de3ecf..56b8fc1 100644 +index 24d0447..daf47bc 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -589,6 +589,8 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info) @@ -4877,10 +4813,10 @@ index 9de3ecf..56b8fc1 100644 return 0; } diff --git a/kernel/signal.c b/kernel/signal.c -index 0f9af0b..71f5cca 100644 +index 8594cb2..4512bb4 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -1878,7 +1878,10 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1886,7 +1886,10 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) if (gstop_done) do_notify_parent_cldstop(current, false, why); @@ -4895,47 +4831,40 @@ index 0f9af0b..71f5cca 100644 1.5.5.1 -From davej Wed Aug 3 15:16:37 2011 +From oleg@redhat.com Mon Nov 21 15:06:40 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:37 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:29 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:40 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5034E9DEA4; - Wed, 3 Aug 2011 15:12:35 -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 8BhFlmqmXy8l; Wed, 3 Aug 2011 15:12:35 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 31AEE9DEAB; - Wed, 3 Aug 2011 15:12:35 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B0D19D877F; + Mon, 21 Nov 2011 15:06:40 -0500 (EST) +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 3jv-cDBpMP5B; Mon, 21 Nov 2011 15:06:40 -0500 (EST) +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 9C98DD8410; + Mon, 21 Nov 2011 15:06:40 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCRCZ008434; - Wed, 3 Aug 2011 15:12:28 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6cHF029573; + Mon, 21 Nov 2011 15:06:39 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:55 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:53 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:59 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:57 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 11/31] introduce wake_up_quiescent() -Message-ID: <20110803190953.GA30952@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 11/33] introduce wake_up_quiescent() +Message-ID: <20111121200157.GA27805@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO Content-Length: 3186 Lines: 93 @@ -4968,7 +4897,7 @@ index a822300..2be3712 100644 extern int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p, bool group); diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 56b8fc1..4194664 100644 +index daf47bc..8439ef1 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -621,7 +621,7 @@ static int ptrace_resume(struct task_struct *child, long request, @@ -4981,7 +4910,7 @@ index 56b8fc1..4194664 100644 } diff --git a/kernel/signal.c b/kernel/signal.c -index 71f5cca..3e8e0b1 100644 +index 4512bb4..99a6008 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -702,6 +702,14 @@ void signal_wake_up(struct task_struct *t, int resume) @@ -5008,7 +4937,7 @@ index 71f5cca..3e8e0b1 100644 else ptrace_trap_notify(t); } while_each_thread(p, t); -@@ -1879,7 +1887,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1887,7 +1895,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) do_notify_parent_cldstop(current, false, why); spin_lock_irq(¤t->sighand->siglock); @@ -5034,49 +4963,42 @@ index 5d3974e..cebc390 100644 1.5.5.1 -From davej Wed Aug 3 15:22:01 2011 +From oleg@redhat.com Mon Nov 21 15:06:43 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:22:01 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:17:15 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:43 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F2DE19DC07; - Wed, 3 Aug 2011 15:12:37 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id IYfqfx8GhNWc; Wed, 3 Aug 2011 15:12:37 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D645E9DAF7; - Wed, 3 Aug 2011 15:12:37 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6488BD514C; + Mon, 21 Nov 2011 15:06:43 -0500 (EST) +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 TKQUj5mU4NYM; Mon, 21 Nov 2011 15:06:43 -0500 (EST) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4EC82D5000; + Mon, 21 Nov 2011 15:06:43 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCUNh008446; - Wed, 3 Aug 2011 15:12:31 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6fp6015343; + Mon, 21 Nov 2011 15:06:41 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:58 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:56 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:02 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:59 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 12/31] introduce ptrace_signal_wake_up() -Message-ID: <20110803190956.GA30959@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 12/33] introduce ptrace_signal_wake_up() +Message-ID: <20111121200159.GA27812@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 3667 +Content-Length: 3670 Lines: 113 Add the new helper, ptrace_signal_wake_up(), change ptrace.c/signal.c @@ -5118,7 +5040,7 @@ index 800f113..6d9282a 100644 extern long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data); diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 4194664..1a50090 100644 +index 8439ef1..a464ab5 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -25,6 +25,18 @@ @@ -5167,7 +5089,7 @@ index 4194664..1a50090 100644 unlock_task_sighand(child, &flags); ret = 0; -@@ -760,7 +772,7 @@ int ptrace_request(struct task_struct *child, long request, +@@ -757,7 +769,7 @@ int ptrace_request(struct task_struct *child, long request, * start of this trap and now. Trigger re-trap. */ if (child->jobctl & JOBCTL_TRAP_NOTIFY) @@ -5177,7 +5099,7 @@ index 4194664..1a50090 100644 } unlock_task_sighand(child, &flags); diff --git a/kernel/signal.c b/kernel/signal.c -index 3e8e0b1..0dc6abb 100644 +index 99a6008..7a47a93 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -854,7 +854,7 @@ static void ptrace_trap_notify(struct task_struct *t) @@ -5193,48 +5115,41 @@ index 3e8e0b1..0dc6abb 100644 1.5.5.1 -From davej Wed Aug 3 15:15:58 2011 +From oleg@redhat.com Mon Nov 21 15:06:46 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:15:58 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:13:17 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:46 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8FF88DA558; - Wed, 3 Aug 2011 15:12:40 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 3A7AED8410; + Mon, 21 Nov 2011 15:06:46 -0500 (EST) 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 1cOfIyuaRoO3; Wed, 3 Aug 2011 15:12:40 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7B6E8DA4A9; - Wed, 3 Aug 2011 15:12:40 -0400 (EDT) + with ESMTP id jhYAwDyYmdhg; Mon, 21 Nov 2011 15:06:46 -0500 (EST) +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 25D5FD889A; + Mon, 21 Nov 2011 15:06:46 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCXpn023459; - Wed, 3 Aug 2011 15:12:33 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6h29029619; + Mon, 21 Nov 2011 15:06:44 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:01 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:59 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:04 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:02 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 13/31] wait_task_inactive: treat task->state and +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 13/33] wait_task_inactive: treat task->state and match_state as bitmasks -Message-ID: <20110803190959.GA30962@redhat.com> +Message-ID: <20111121200202.GA27816@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO Content-Length: 1558 Lines: 39 @@ -5263,10 +5178,10 @@ Signed-off-by: Oleg Nesterov 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c -index ccacdbd..66ef2fb 100644 +index 0e9344a..84ecc0a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c -@@ -2289,7 +2289,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) +@@ -2443,7 +2443,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) * is actually now running somewhere else! */ while (task_running(rq, p)) { @@ -5279,47 +5194,40 @@ index ccacdbd..66ef2fb 100644 1.5.5.1 -From davej Wed Aug 3 15:16:24 2011 +From oleg@redhat.com Mon Nov 21 15:06:48 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:24 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:21 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:48 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 34C189DC30; - Wed, 3 Aug 2011 15:12:43 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id RHggq6bqo+Q9; Wed, 3 Aug 2011 15:12:43 -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 zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 210D59DC14; - Wed, 3 Aug 2011 15:12:43 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C2934D5000; + Mon, 21 Nov 2011 15:06:48 -0500 (EST) +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 ThT2PyhztDpQ; Mon, 21 Nov 2011 15:06:48 -0500 (EST) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id ACE02D4F84; + Mon, 21 Nov 2011 15:06:48 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JCZsD022395; - Wed, 3 Aug 2011 15:12:36 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6kdb022201; + Mon, 21 Nov 2011 15:06:47 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:03 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:01 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:07 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:05 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 14/31] introduce TASK_UTRACED state -Message-ID: <20110803191001.GA30969@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 14/33] introduce TASK_UTRACED state +Message-ID: <20111121200205.GA27823@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO Content-Length: 2913 Lines: 84 @@ -5358,10 +5266,10 @@ index f0c0ea2..e0daec4 100644 static inline const char *get_task_state(struct task_struct *tsk) diff --git a/include/linux/sched.h b/include/linux/sched.h -index c6d79af..f3f0a77 100644 +index 4d45f93..746b4d3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h -@@ -184,16 +184,17 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) +@@ -185,16 +185,17 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) #define TASK_UNINTERRUPTIBLE 2 #define __TASK_STOPPED 4 #define __TASK_TRACED 8 @@ -5386,7 +5294,7 @@ index c6d79af..f3f0a77 100644 extern char ___assert_task_state[1 - 2*!!( sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1)]; -@@ -202,15 +203,16 @@ extern char ___assert_task_state[1 - 2*!!( +@@ -203,15 +204,16 @@ extern char ___assert_task_state[1 - 2*!!( #define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE) #define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED) #define TASK_TRACED (TASK_WAKEKILL | __TASK_TRACED) @@ -5409,47 +5317,40 @@ index c6d79af..f3f0a77 100644 1.5.5.1 -From davej Wed Aug 3 15:16:02 2011 +From oleg@redhat.com Mon Nov 21 15:06:51 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:02 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:13:18 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:51 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D7FFADA44E; - Wed, 3 Aug 2011 15:12:45 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 48F35D889C; + Mon, 21 Nov 2011 15:06:51 -0500 (EST) 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 LFGdvSMswLJT; Wed, 3 Aug 2011 15:12:45 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BA46CDA441; - Wed, 3 Aug 2011 15:12:45 -0400 (EDT) + with ESMTP id ZXkDvXaDg0cN; Mon, 21 Nov 2011 15:06:51 -0500 (EST) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 34485D889A; + Mon, 21 Nov 2011 15:06:51 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCcpZ029424; - Wed, 3 Aug 2011 15:12:39 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6nlT022211; + Mon, 21 Nov 2011 15:06:49 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:06 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:04 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:09 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:08 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 15/31] utrace: use TASK_UTRACED instead of TASK_TRACED -Message-ID: <20110803191004.GA30972@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 15/33] utrace: use TASK_UTRACED instead of TASK_TRACED +Message-ID: <20111121200208.GA27826@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO Content-Length: 4316 Lines: 130 @@ -5585,48 +5486,41 @@ index cebc390..2097103 100644 1.5.5.1 -From davej Wed Aug 3 15:21:40 2011 +From oleg@redhat.com Mon Nov 21 15:06:53 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:21:40 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:42 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:53 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7035E9DECC; - Wed, 3 Aug 2011 15:12:48 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B8F54D5296; + Mon, 21 Nov 2011 15:06:53 -0500 (EST) 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 rmRalMQFlNua; Wed, 3 Aug 2011 15:12:48 -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 5CC809DEC9; - Wed, 3 Aug 2011 15:12:48 -0400 (EDT) + with ESMTP id PX4Y3H1mw0hD; Mon, 21 Nov 2011 15:06:53 -0500 (EST) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A4B5CD528E; + Mon, 21 Nov 2011 15:06:53 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JCfwv010344; - Wed, 3 Aug 2011 15:12:41 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6pXd029643; + Mon, 21 Nov 2011 15:06:52 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:09 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:07 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:12 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:10 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 16/31] reintroduce tracehook_finish_jctl() as +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 16/33] reintroduce tracehook_finish_jctl() as utrace_end_stop() -Message-ID: <20110803191007.GA30979@redhat.com> +Message-ID: <20111121200210.GA27829@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO Content-Length: 2401 Lines: 77 @@ -5670,10 +5564,10 @@ index cf13839..0279c74 100644 + #endif /* linux/utrace.h */ diff --git a/kernel/signal.c b/kernel/signal.c -index 0dc6abb..a625309 100644 +index 7a47a93..ba46eab 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -1895,6 +1895,8 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1903,6 +1903,8 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) read_unlock(&tasklist_lock); } @@ -5682,7 +5576,7 @@ index 0dc6abb..a625309 100644 /* * While in TASK_TRACED, we were considered "frozen enough". * Now that we woke up, it's crucial if we're supposed to be -@@ -2059,6 +2061,9 @@ static bool do_signal_stop(int signr) +@@ -2067,6 +2069,9 @@ static bool do_signal_stop(int signr) /* Now we don't run again until woken by SIGCONT or SIGKILL */ schedule(); @@ -5709,47 +5603,40 @@ index 2097103..d41b982 100644 1.5.5.1 -From davej Wed Aug 3 15:21:41 2011 +From oleg@redhat.com Mon Nov 21 15:06:56 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:21:41 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:42 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:56 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 153719DD18; - Wed, 3 Aug 2011 15:12:51 -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 ffM0oM8RRtgL; Wed, 3 Aug 2011 15:12:51 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 0253E9DEC9; - Wed, 3 Aug 2011 15:12:51 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4A487D83A1; + Mon, 21 Nov 2011 15:06:56 -0500 (EST) +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 3vHogPyhojlJ; Mon, 21 Nov 2011 15:06:56 -0500 (EST) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 358A0D88B0; + Mon, 21 Nov 2011 15:06:56 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCh9Z023559; - Wed, 3 Aug 2011 15:12:44 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6sHk017679; + Mon, 21 Nov 2011 15:06:54 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:11 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:09 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:14 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:12 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 17/31] teach wake_up_quiescent() to do "selective" wake_up -Message-ID: <20110803191009.GA30982@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 17/33] teach wake_up_quiescent() to do "selective" wake_up +Message-ID: <20111121200212.GA27836@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO Content-Length: 1335 Lines: 46 @@ -5767,7 +5654,7 @@ Signed-off-by: Oleg Nesterov 1 files changed, 15 insertions(+), 0 deletions(-) diff --git a/kernel/signal.c b/kernel/signal.c -index a625309..0d1675a 100644 +index ba46eab..e06f795 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -701,11 +701,26 @@ void signal_wake_up(struct task_struct *t, int resume) @@ -5801,48 +5688,41 @@ index a625309..0d1675a 100644 1.5.5.1 -From davej Wed Aug 3 15:21:43 2011 +From oleg@redhat.com Mon Nov 21 15:06:59 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:21:43 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:43 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:58 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B0E899DECF; - Wed, 3 Aug 2011 15:12:53 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C88E2D528B; + Mon, 21 Nov 2011 15:06:58 -0500 (EST) 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 s0bDFhAmsQWN; Wed, 3 Aug 2011 15:12:53 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9DC6E9DEC9; - Wed, 3 Aug 2011 15:12:53 -0400 (EDT) + with ESMTP id nNrAxBD5KOME; Mon, 21 Nov 2011 15:06:58 -0500 (EST) +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 B2114D51C1; + Mon, 21 Nov 2011 15:06:58 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCkUr029453; - Wed, 3 Aug 2011 15:12:46 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6uQQ031440; + Mon, 21 Nov 2011 15:06:57 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:14 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:12 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:17 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:15 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 18/31] ptrace_stop: do not assume the task is running after +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 18/33] ptrace_stop: do not assume the task is running after wake_up_quiescent() -Message-ID: <20110803191012.GA30985@redhat.com> +Message-ID: <20111121200215.GA27839@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO Content-Length: 956 Lines: 31 @@ -5857,10 +5737,10 @@ Signed-off-by: Oleg Nesterov 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/kernel/signal.c b/kernel/signal.c -index 0d1675a..249760f 100644 +index e06f795..9348da6 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -1908,6 +1908,14 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1916,6 +1916,14 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) if (clear_code) current->exit_code = 0; read_unlock(&tasklist_lock); @@ -5879,48 +5759,41 @@ index 0d1675a..249760f 100644 1.5.5.1 -From davej Wed Aug 3 15:16:26 2011 +From oleg@redhat.com Mon Nov 21 15:07:01 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:26 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:22 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:01 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 69B489DC62; - Wed, 3 Aug 2011 15:12:56 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 4BNNeoYSdCTc; Wed, 3 Aug 2011 15:12:56 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4A9899DC14; - Wed, 3 Aug 2011 15:12:56 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4BF37D889A; + Mon, 21 Nov 2011 15:07:01 -0500 (EST) +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 5p8tvlXAqUHr; Mon, 21 Nov 2011 15:07:01 -0500 (EST) +Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 37C22D8757; + Mon, 21 Nov 2011 15:07:01 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCnRf023575; - Wed, 3 Aug 2011 15:12:49 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6xFJ031449; + Mon, 21 Nov 2011 15:06:59 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:16 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:14 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:19 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:18 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 19/31] get_signal_to_deliver: restore/restructure +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 19/33] get_signal_to_deliver: restore/restructure utrace/ptrace signal reporting -Message-ID: <20110803191014.GA30992@redhat.com> +Message-ID: <20111121200218.GA27846@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO Content-Length: 3556 Lines: 115 @@ -5986,10 +5859,10 @@ index 0279c74..63103e2 100644 + #endif /* linux/utrace.h */ diff --git a/kernel/signal.c b/kernel/signal.c -index 249760f..3c783d3 100644 +index 9348da6..38ea4e6 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -2234,17 +2234,27 @@ relock: +@@ -2242,17 +2242,27 @@ relock: for (;;) { struct k_sigaction *ka; @@ -6025,7 +5898,7 @@ index 249760f..3c783d3 100644 if (!signr) break; /* will return 0 */ -@@ -2254,9 +2264,9 @@ relock: +@@ -2262,9 +2272,9 @@ relock: regs, cookie); if (!signr) continue; @@ -6041,46 +5914,39 @@ index 249760f..3c783d3 100644 1.5.5.1 -From davej Wed Aug 3 15:16:27 2011 +From oleg@redhat.com Mon Nov 21 15:07:03 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:27 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:22 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:03 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 119589DC72; - Wed, 3 Aug 2011 15:12:59 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id Vxp8fnt8hEcf; Wed, 3 Aug 2011 15:12:59 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id CB362D89E9; + Mon, 21 Nov 2011 15:07:03 -0500 (EST) +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 wm2JqccPnhsV; Mon, 21 Nov 2011 15:07:03 -0500 (EST) Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F22049DCAE; - Wed, 3 Aug 2011 15:12:58 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B6D25D89DE; + Mon, 21 Nov 2011 15:07:03 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JCpO4010401; - Wed, 3 Aug 2011 15:12:52 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK715f031455; + Mon, 21 Nov 2011 15:07:02 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:19 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:17 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:22 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:20 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 20/31] utrace_get_signal: +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 20/33] utrace_get_signal: s/JOBCTL_STOP_PENDING/JOBCTL_PENDING_MASK/ -Message-ID: <20110803191017.GA30995@redhat.com> +Message-ID: <20111121200220.GA27849@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO @@ -6121,47 +5987,40 @@ index d41b982..0bb0a06 100644 1.5.5.1 -From davej Wed Aug 3 15:16:03 2011 +From oleg@redhat.com Mon Nov 21 15:07:07 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:03 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:13:19 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:06 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A9253DA3CB; - Wed, 3 Aug 2011 15:13:01 -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 HLlRhTJ2MbYS; Wed, 3 Aug 2011 15:13:01 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9582C4C43B; - Wed, 3 Aug 2011 15:13:01 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8C14BD4F84; + Mon, 21 Nov 2011 15:07:06 -0500 (EST) +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 39eM-KKZxrZ3; Mon, 21 Nov 2011 15:07:06 -0500 (EST) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7628FD4FF4; + Mon, 21 Nov 2011 15:07:06 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCsFX008586; - Wed, 3 Aug 2011 15:12:54 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK74dN022253; + Mon, 21 Nov 2011 15:07:04 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:22 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:20 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:25 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:23 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 21/31] introduce ptrace_set_syscall_trace() -Message-ID: <20110803191020.GA31002@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 21/33] introduce ptrace_set_syscall_trace() +Message-ID: <20111121200223.GA27856@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO Content-Length: 1549 Lines: 52 @@ -6176,7 +6035,7 @@ Signed-off-by: Oleg Nesterov 1 files changed, 10 insertions(+), 5 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 1a50090..dc2ad34 100644 +index a464ab5..43357e5 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -38,6 +38,14 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent) @@ -6219,47 +6078,40 @@ index 1a50090..dc2ad34 100644 1.5.5.1 -From davej Wed Aug 3 15:21:45 2011 +From oleg@redhat.com Mon Nov 21 15:07:09 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:21:45 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:43 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:09 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5C4889DEE6; - Wed, 3 Aug 2011 15:13:04 -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 eXIPU4nVv+7Z; Wed, 3 Aug 2011 15:13:04 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 3F82C9DED6; - Wed, 3 Aug 2011 15:13:04 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1ADF01285E4; + Mon, 21 Nov 2011 15:07:09 -0500 (EST) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id rF+XegsxVXnL; Mon, 21 Nov 2011 15:07:09 -0500 (EST) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 067E41287D0; + Mon, 21 Nov 2011 15:07:09 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCueo029507; - Wed, 3 Aug 2011 15:12:57 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK76tD022270; + Mon, 21 Nov 2011 15:07:07 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:24 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:22 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:27 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:25 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 22/31] introduce PT_SYSCALL_TRACE flag -Message-ID: <20110803191022.GA31005@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 22/33] introduce PT_SYSCALL_TRACE flag +Message-ID: <20111121200225.GA27860@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO Content-Length: 2268 Lines: 73 @@ -6315,7 +6167,7 @@ index ec2af67..eb9fe30 100644 ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index dc2ad34..7deb292 100644 +index 43357e5..1ac03eb 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -40,10 +40,13 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent) @@ -6338,48 +6190,41 @@ index dc2ad34..7deb292 100644 1.5.5.1 -From davej Wed Aug 3 15:16:05 2011 +From oleg@redhat.com Mon Nov 21 15:07:11 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:05 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:13:20 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:11 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E516ADA488; - Wed, 3 Aug 2011 15:13:06 -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 rP7Um8DZjclX; Wed, 3 Aug 2011 15:13:06 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D155EDA3F8; - Wed, 3 Aug 2011 15:13:06 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B7D62D4DCC; + Mon, 21 Nov 2011 15:07:11 -0500 (EST) +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 1ENpGO166I-W; Mon, 21 Nov 2011 15:07:11 -0500 (EST) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A3A55D498A; + Mon, 21 Nov 2011 15:07:11 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCxfF029532; - Wed, 3 Aug 2011 15:13:00 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK79AS017728; + Mon, 21 Nov 2011 15:07:10 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:27 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:25 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:30 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:28 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 23/31] utrace: don't clear TIF_SYSCALL_TRACE if it is +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 23/33] utrace: don't clear TIF_SYSCALL_TRACE if it is needed by ptrace -Message-ID: <20110803191025.GA31012@redhat.com> +Message-ID: <20111121200228.GA27863@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO Content-Length: 797 Lines: 24 @@ -6409,47 +6254,40 @@ index 0bb0a06..bebf6de 100644 1.5.5.1 -From davej Wed Aug 3 15:16:08 2011 +From oleg@redhat.com Mon Nov 21 15:07:14 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:08 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:29 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:14 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 80872DA4B2; - Wed, 3 Aug 2011 15:13:09 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5376AD8774; + Mon, 21 Nov 2011 15:07:14 -0500 (EST) 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 AbpC0Wk1ZhtT; Wed, 3 Aug 2011 15:13:09 -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 6D97DDA3F8; - Wed, 3 Aug 2011 15:13:09 -0400 (EDT) + with ESMTP id 5Oc8ErfFfJSs; Mon, 21 Nov 2011 15:07:14 -0500 (EST) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 3F2CFD81E9; + Mon, 21 Nov 2011 15:07:14 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JD2RU022591; - Wed, 3 Aug 2011 15:13:02 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7Cw3015467; + Mon, 21 Nov 2011 15:07:12 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:30 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:28 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:32 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:30 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 24/31] introduce task_utrace_lock/task_utrace_unlock -Message-ID: <20110803191028.GA31015@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 24/33] introduce task_utrace_lock/task_utrace_unlock +Message-ID: <20111121200230.GA27870@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO Content-Length: 2190 Lines: 81 @@ -6536,48 +6374,41 @@ index bebf6de..960dd9e 100644 1.5.5.1 -From davej Wed Aug 3 15:21:46 2011 +From oleg@redhat.com Mon Nov 21 15:07:17 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:21:46 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:43 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:17 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 24B3E9DEF6; - Wed, 3 Aug 2011 15:13:12 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 01034D498A; + Mon, 21 Nov 2011 15:07:17 -0500 (EST) 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 2jg9j3-p4bHL; Wed, 3 Aug 2011 15:13:12 -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 zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 119759DEF9; - Wed, 3 Aug 2011 15:13:12 -0400 (EDT) + with ESMTP id BglmrU3H2hJr; Mon, 21 Nov 2011 15:07:16 -0500 (EST) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E0D31D4FF4; + Mon, 21 Nov 2011 15:07:16 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JD485022603; - Wed, 3 Aug 2011 15:13:05 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7Egx015474; + Mon, 21 Nov 2011 15:07:15 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:32 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:30 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:35 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:33 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 25/31] teach ptrace_set_syscall_trace() to play well with +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 25/33] teach ptrace_set_syscall_trace() to play well with utrace -Message-ID: <20110803191030.GA31018@redhat.com> +Message-ID: <20111121200233.GA27873@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO Content-Length: 1545 Lines: 49 @@ -6599,7 +6430,7 @@ Signed-off-by: Oleg Nesterov 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 7deb292..69850e9 100644 +index 1ac03eb..739183a 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -24,6 +24,7 @@ @@ -6632,45 +6463,38 @@ index 7deb292..69850e9 100644 1.5.5.1 -From davej Wed Aug 3 15:16:29 2011 +From oleg@redhat.com Mon Nov 21 15:07:19 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:28 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:24 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:19 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 062709DE55; - Wed, 3 Aug 2011 15:13:15 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8F87F128EAA; + Mon, 21 Nov 2011 15:07:19 -0500 (EST) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id lhwVoEywGaPJ; Wed, 3 Aug 2011 15:13:14 -0400 (EDT) + with ESMTP id yittEjCd+X4F; Mon, 21 Nov 2011 15:07:19 -0500 (EST) Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E4C139DE11; - Wed, 3 Aug 2011 15:13:14 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7BC701287D0; + Mon, 21 Nov 2011 15:07:19 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JD7Go010523; - Wed, 3 Aug 2011 15:13:08 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK7HbH031553; + Mon, 21 Nov 2011 15:07:18 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:35 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:33 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:38 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:36 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 26/31] introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK -Message-ID: <20110803191033.GA31025@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 26/33] introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK +Message-ID: <20111121200236.GA27880@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO @@ -6762,7 +6586,7 @@ index eb9fe30..21c8ca2 100644 } diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 69850e9..d250a71 100644 +index 739183a..792080d 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -630,13 +630,16 @@ static int ptrace_resume(struct task_struct *child, long request, @@ -6786,48 +6610,41 @@ index 69850e9..d250a71 100644 1.5.5.1 -From davej Wed Aug 3 15:16:30 2011 +From oleg@redhat.com Mon Nov 21 15:07:22 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:30 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:25 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:22 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B3BF49DE11; - Wed, 3 Aug 2011 15:13:17 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 0C136128FB0; + Mon, 21 Nov 2011 15:07:22 -0500 (EST) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id zC72ecV9Jz07; Wed, 3 Aug 2011 15:13:17 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 98ACE9DE59; - Wed, 3 Aug 2011 15:13:17 -0400 (EDT) + with ESMTP id GNbS20gY5Jq9; Mon, 21 Nov 2011 15:07:21 -0500 (EST) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id EB5821287D0; + Mon, 21 Nov 2011 15:07:21 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JDATh023726; - Wed, 3 Aug 2011 15:13:10 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK7Kn1029766; + Mon, 21 Nov 2011 15:07:20 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:38 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:36 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:40 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:38 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 27/31] utrace: finish_resume_report: don't do +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 27/33] utrace: finish_resume_report: don't do user_xxx_step() if ptrace_wants_step() -Message-ID: <20110803191036.GA31028@redhat.com> +Message-ID: <20111121200238.GA27883@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO Content-Length: 2741 Lines: 84 @@ -6917,48 +6734,41 @@ index 960dd9e..05e8532 100644 1.5.5.1 -From davej Wed Aug 3 15:16:32 2011 +From oleg@redhat.com Mon Nov 21 15:07:24 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:32 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:25 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:24 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 614CD9DE73; - Wed, 3 Aug 2011 15:13:20 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8954F12914D; + Mon, 21 Nov 2011 15:07:24 -0500 (EST) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id jcWOXzUaaIYu; Wed, 3 Aug 2011 15:13:20 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 438889DE59; - Wed, 3 Aug 2011 15:13:20 -0400 (EDT) + with ESMTP id 0lU8wXKC78yu; Mon, 21 Nov 2011 15:07:24 -0500 (EST) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 759B61287D0; + Mon, 21 Nov 2011 15:07:24 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JDDZ7029595; - Wed, 3 Aug 2011 15:13:13 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7Mi7022329; + Mon, 21 Nov 2011 15:07:23 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:40 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:38 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:43 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:41 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 28/31] ptrace: shift user_*_step() from ptrace_resume() to +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 28/33] ptrace: shift user_*_step() from ptrace_resume() to ptrace_stop() -Message-ID: <20110803191038.GA31035@redhat.com> +Message-ID: <20111121200241.GA27890@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO Content-Length: 2374 Lines: 70 @@ -6990,7 +6800,7 @@ Signed-off-by: Oleg Nesterov 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index d250a71..d1ef124 100644 +index 792080d..eba9a22 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -635,14 +635,10 @@ static int ptrace_resume(struct task_struct *child, long request, @@ -7009,10 +6819,10 @@ index d250a71..d1ef124 100644 child->exit_code = data; diff --git a/kernel/signal.c b/kernel/signal.c -index 3c783d3..43a3e77 100644 +index 38ea4e6..b13d2bc 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -1920,6 +1920,17 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1928,6 +1928,17 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) utrace_end_stop(); @@ -7034,45 +6844,38 @@ index 3c783d3..43a3e77 100644 1.5.5.1 -From davej Wed Aug 3 15:16:34 2011 +From oleg@redhat.com Mon Nov 21 15:07:27 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:34 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:25 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:27 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1A6019DE59; - Wed, 3 Aug 2011 15:13:23 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 043581287D0; + Mon, 21 Nov 2011 15:07:27 -0500 (EST) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id db2hhAqFwsPu; Wed, 3 Aug 2011 15:13:23 -0400 (EDT) + with ESMTP id 4WO1El1jiIrJ; Mon, 21 Nov 2011 15:07:26 -0500 (EST) Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 034739DE83; - Wed, 3 Aug 2011 15:13:23 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E3FCA129045; + Mon, 21 Nov 2011 15:07:26 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JDFNp008715; - Wed, 3 Aug 2011 15:13:16 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7OdV017836; + Mon, 21 Nov 2011 15:07:25 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:43 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:41 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:45 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:43 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 29/31] ptrace_disable: no need to disable stepping -Message-ID: <20110803191041.GA31039@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 29/33] ptrace_disable: no need to disable stepping +Message-ID: <20111121200243.GA27893@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO @@ -7109,47 +6912,40 @@ index d1557dc..96d315a 100644 1.5.5.1 -From davej Wed Aug 3 15:21:48 2011 +From oleg@redhat.com Mon Nov 21 15:07:29 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:21:48 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:52 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:29 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 95706917AF; - Wed, 3 Aug 2011 15:13:25 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8A6E8D4C39; + Mon, 21 Nov 2011 15:07:29 -0500 (EST) 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 ctq4DF3wXncJ; Wed, 3 Aug 2011 15:13:25 -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 7FD14914AF; - Wed, 3 Aug 2011 15:13:25 -0400 (EDT) + with ESMTP id NLURBx2yQes5; Mon, 21 Nov 2011 15:07:29 -0500 (EST) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7660DD498A; + Mon, 21 Nov 2011 15:07:29 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JDIRO010579; - Wed, 3 Aug 2011 15:13:18 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7RnP015578; + Mon, 21 Nov 2011 15:07:27 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:46 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:44 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:48 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:46 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 30/31] ptrace_report_syscall: check TIF_SYSCALL_EMU -Message-ID: <20110803191044.GA31046@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 30/33] ptrace_report_syscall: check TIF_SYSCALL_EMU +Message-ID: <20111121200246.GA27896@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO Content-Length: 858 Lines: 28 @@ -7183,46 +6979,39 @@ index b6812d4..90ca578 100644 1.5.5.1 -From davej Wed Aug 3 15:21:49 2011 +From oleg@redhat.com Mon Nov 21 15:07:32 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:21:49 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:52 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:32 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 400F49191F; - Wed, 3 Aug 2011 15:13:28 -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 UeLOLM29JRc7; Wed, 3 Aug 2011 15:13:28 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 10D1312916C; + Mon, 21 Nov 2011 15:07:32 -0500 (EST) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id Z14plX1oxaYL; Mon, 21 Nov 2011 15:07:32 -0500 (EST) Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2D05C903F6; - Wed, 3 Aug 2011 15:13:28 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F12FF128E1D; + Mon, 21 Nov 2011 15:07:31 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JDKCA023784; - Wed, 3 Aug 2011 15:13:21 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7T0q022460; + Mon, 21 Nov 2011 15:07:30 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:48 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:46 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:50 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:48 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 31/31] utrace_resume: check irqs_disabled() to shut up +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 31/33] utrace_resume: check irqs_disabled() to shut up lockdep -Message-ID: <20110803191046.GA31049@redhat.com> +Message-ID: <20111121200248.GA27903@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO @@ -7256,49 +7045,41 @@ index 05e8532..c817a46 100644 1.5.5.1 -From davej Tue Aug 9 13:39:54 2011 +From oleg@redhat.com Mon Nov 21 15:07:34 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Tue, 09 Aug 2011 13:39:54 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Tue, 9 Aug 2011 13:39:44 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:34 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5FCAC12983C; - Tue, 9 Aug 2011 13:39:44 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id nDWbqog6fbHK; Tue, 9 Aug 2011 13:39:44 -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 zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4BEF712983B; - Tue, 9 Aug 2011 13:39:44 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 860BCD8A3E; + Mon, 21 Nov 2011 15:07:34 -0500 (EST) +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 pVTbN1oF62dg; Mon, 21 Nov 2011 15:07:34 -0500 (EST) +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 6FBFFD87A3; + Mon, 21 Nov 2011 15:07:34 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p79HdahY022801; - Tue, 9 Aug 2011 13:39:37 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK7W0B029871; + Mon, 21 Nov 2011 15:07:32 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Tue, 9 Aug 2011 19:36:58 +0200 (CEST) -Date: Tue, 9 Aug 2011 19:36:56 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:53 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:51 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH utrace-3.1 32/31] ptrace_report_syscall: check if - TIF_SYSCALL_EMU is defined -Message-ID: <20110809173656.GC26443@redhat.com> -References: <20110802174514.GA23073@redhat.com> <20110803190806.GA30619@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 32/33] ptrace_report_syscall: check if TIF_SYSCALL_EMU is + defined +Message-ID: <20111121200251.GA27906@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO Content-Length: 839 Lines: 31 @@ -7335,50 +7116,43 @@ index 90ca578..a1bac95 100644 1.5.5.1 -From davej Thu Sep 1 14:14:49 2011 +From oleg@redhat.com Mon Nov 21 15:07:37 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 01 Sep 2011 14:14:49 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Thu, 1 Sep 2011 14:13:55 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:37 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1BA199C63F; - Thu, 1 Sep 2011 14:13:55 -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 0vQx9zlcQB36; Thu, 1 Sep 2011 14:13:55 -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 zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 009959C63D; - Thu, 1 Sep 2011 14:13:55 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 33405D8A50; + Mon, 21 Nov 2011 15:07:37 -0500 (EST) +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 3WH8FhvizjEA; Mon, 21 Nov 2011 15:07:37 -0500 (EST) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1274FD89BB; + Mon, 21 Nov 2011 15:07:37 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p81IDrDX015389; - Thu, 1 Sep 2011 14:13:54 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7YHr017898; + Mon, 21 Nov 2011 15:07:35 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Thu, 1 Sep 2011 20:10:54 +0200 (CEST) -Date: Thu, 1 Sep 2011 20:10:53 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:55 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:53 +0100 From: Oleg Nesterov -To: Dave Jones -Cc: kernel@lists.fedoraproject.org, cebbert@redhat.com -Subject: [PATCH F-16] bz735118: utrace: s390: fix the compile problem with - traps.c -Message-ID: <20110901181053.GA24990@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 33/33] utrace: s390: fix the compile problem with traps.c +Message-ID: <20111121200253.GA27913@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO -Content-Length: 777 -Lines: 27 - -https://bugzilla.redhat.com/show_bug.cgi?id=735118 +Content-Length: 725 +Lines: 25 d99e60e5 "tracehooks: reintroduce tracehook_consider_fatal_signal()" breaks the compilation of arch/s390/kernel/traps.c. Restore the @@ -7390,7 +7164,7 @@ Signed-off-by: Oleg Nesterov 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c -index 1018ab6..50e975d 100644 +index f506e1b..3132498 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -18,7 +18,7 @@ diff --git a/x86-code-dump-fix-truncation.patch b/x86-code-dump-fix-truncation.patch deleted file mode 100644 index dcd5a815c..000000000 --- a/x86-code-dump-fix-truncation.patch +++ /dev/null @@ -1,73 +0,0 @@ -From: Clemens Ladisch -Date: Mon, 19 Dec 2011 21:07:58 +0000 (+0100) -Subject: x86, dumpstack: Fix code bytes breakage due to missing KERN_CONT -X-Git-Url: https://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftip%2Ftip.git;a=commitdiff_plain;h=13f541c10b30fc6529200d7f9a0073217709622f - -x86, dumpstack: Fix code bytes breakage due to missing KERN_CONT - -When printing the code bytes in show_registers(), the markers around the -byte at the fault address could make the printk() format string look -like a valid log level and facility code. This would prevent this byte -from being printed and result in a spurious newline: - -[ 7555.765589] Code: 8b 32 e9 94 00 00 00 81 7d 00 ff 00 00 00 0f 87 96 00 00 00 48 8b 83 c0 00 00 00 44 89 e2 44 89 e6 48 89 df 48 8b 80 d8 02 00 00 -[ 7555.765683] 8b 48 28 48 89 d0 81 e2 ff 0f 00 00 48 c1 e8 0c 48 c1 e0 04 - -Add KERN_CONT where needed, and elsewhere in show_registers() for -consistency. - -Signed-off-by: Clemens Ladisch -Link: http://lkml.kernel.org/r/4EEFA7AE.9020407@ladisch.de -Signed-off-by: H. Peter Anvin ---- - -diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c -index 3b97a80..c99f9ed 100644 ---- a/arch/x86/kernel/dumpstack_32.c -+++ b/arch/x86/kernel/dumpstack_32.c -@@ -116,16 +116,16 @@ void show_registers(struct pt_regs *regs) - for (i = 0; i < code_len; i++, ip++) { - if (ip < (u8 *)PAGE_OFFSET || - probe_kernel_address(ip, c)) { -- printk(" Bad EIP value."); -+ printk(KERN_CONT " Bad EIP value."); - break; - } - if (ip == (u8 *)regs->ip) -- printk("<%02x> ", c); -+ printk(KERN_CONT "<%02x> ", c); - else -- printk("%02x ", c); -+ printk(KERN_CONT "%02x ", c); - } - } -- printk("\n"); -+ printk(KERN_CONT "\n"); - } - - int is_valid_bugaddr(unsigned long ip) -diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c -index 19853ad..6d728d9 100644 ---- a/arch/x86/kernel/dumpstack_64.c -+++ b/arch/x86/kernel/dumpstack_64.c -@@ -284,16 +284,16 @@ void show_registers(struct pt_regs *regs) - for (i = 0; i < code_len; i++, ip++) { - if (ip < (u8 *)PAGE_OFFSET || - probe_kernel_address(ip, c)) { -- printk(" Bad RIP value."); -+ printk(KERN_CONT " Bad RIP value."); - break; - } - if (ip == (u8 *)regs->ip) -- printk("<%02x> ", c); -+ printk(KERN_CONT "<%02x> ", c); - else -- printk("%02x ", c); -+ printk(KERN_CONT "%02x ", c); - } - } -- printk("\n"); -+ printk(KERN_CONT "\n"); - } - - int is_valid_bugaddr(unsigned long ip) From 652c2c141d4d3aa85fc10e38e5bd10510691c757 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 30 Jan 2012 12:51:06 -0500 Subject: [PATCH 291/397] Reinstate patch to remove overlap between bcma/b43 and brcmsmac --- bcma-brcmsmac-compat.patch | 35 +++++++++++++++++++++++++++++++++++ kernel.spec | 9 +++++++++ 2 files changed, 44 insertions(+) create mode 100644 bcma-brcmsmac-compat.patch diff --git a/bcma-brcmsmac-compat.patch b/bcma-brcmsmac-compat.patch new file mode 100644 index 000000000..e16e5b0c5 --- /dev/null +++ b/bcma-brcmsmac-compat.patch @@ -0,0 +1,35 @@ +Simple patch to remove the overlap between the bcma (i.e. b43) driver +and the brcmsmac driver. David Woodhouse +confirmed that this patch restores functionality of bcm4331 devices. + +-- John W. Linville + +diff -up linux-3.1.x86_64/drivers/bcma/host_pci.c.orig linux-3.1.x86_64/drivers/bcma/host_pci.c +--- linux-3.1.x86_64/drivers/bcma/host_pci.c.orig 2011-11-10 11:41:26.829742757 -0500 ++++ linux-3.1.x86_64/drivers/bcma/host_pci.c 2011-11-10 11:41:22.884792078 -0500 +@@ -225,11 +225,13 @@ static void bcma_host_pci_remove(struct + } + + static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { +- { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, ++#if 0 /* Not in Fedora... */ ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, ++#endif + { 0, }, + }; + MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl); +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig 2011-11-10 11:42:31.764930961 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig 2011-11-10 11:42:33.613907846 -0500 +@@ -5,7 +5,6 @@ config BRCMSMAC + tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" + depends on PCI + depends on MAC80211 +- depends on BCMA=n + select BRCMUTIL + select FW_LOADER + select CRC_CCITT diff --git a/kernel.spec b/kernel.spec index 848a58fa0..95f21ea30 100644 --- a/kernel.spec +++ b/kernel.spec @@ -690,6 +690,9 @@ Patch21084: proc-fix-null-pointer-deref-in-proc_pid_permission.patch #rhbz 783211 Patch21087: fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch +# Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 +Patch21091: bcma-brcmsmac-compat.patch + #rhbz 771058 Patch21100: msi-irq-sysfs-warning.patch @@ -1300,6 +1303,9 @@ ApplyPatch rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch #rhbz 783211 ApplyPatch fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch +# Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 +ApplyPatch bcma-brcmsmac-compat.patch + # END OF PATCH APPLICATIONS %endif @@ -1947,6 +1953,9 @@ fi # and build. %changelog +* Mon Jan 30 2012 John W. Linville +- Reinstate patch to remove overlap between bcma/b43 and brcmsmac + * Mon Jan 30 2012 Dave Jones 2.6.42.2-1 - Rebase to 3.2.2 From 2984100a2b8494aae8a0cd734e3288a930c65a17 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 30 Jan 2012 13:08:18 -0500 Subject: [PATCH 292/397] Restore the Savage DRM and several others that were accidentally early-deprecated. --- config-generic | 24 +++++++++--------------- kernel.spec | 3 +++ 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/config-generic b/config-generic index bd2c47654..025b58cde 100644 --- a/config-generic +++ b/config-generic @@ -2511,31 +2511,25 @@ CONFIG_AGP_SIS=y CONFIG_AGP_SWORKS=y CONFIG_AGP_VIA=y CONFIG_AGP_EFFICEON=y - CONFIG_VGA_ARB=y CONFIG_VGA_ARB_MAX_GPUS=16 - -# CONFIG_STUB_POULSBO is not set - +CONFIG_STUB_POULSBO=m +# CONFIG_DRM_PSB is not set CONFIG_DRM=m -# CONFIG_DRM_TDFX is not set -# CONFIG_DRM_R128 is not set +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m CONFIG_DRM_RADEON=m CONFIG_DRM_RADEON_KMS=y -# CONFIG_DRM_I810 is not set -# CONFIG_DRM_MGA is not set -# CONFIG_DRM_SIS is not set -# CONFIG_DRM_SAVAGE is not set +CONFIG_DRM_I810=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_SAVAGE=m CONFIG_DRM_I915=m CONFIG_DRM_I915_KMS=y -# CONFIG_DRM_VIA is not set +CONFIG_DRM_VIA=m CONFIG_DRM_NOUVEAU=m CONFIG_DRM_NOUVEAU_BACKLIGHT=y CONFIG_DRM_NOUVEAU_DEBUG=y -CONFIG_DRM_PSB=m -# CONFIG_DRM_PSB_MRST is not set -# CONFIG_DRM_PSB_MFLD is not set -# CONFIG_DRM_PSB_CDV is not set CONFIG_DRM_I2C_CH7006=m CONFIG_DRM_I2C_SIL164=m CONFIG_DRM_VMWGFX=m diff --git a/kernel.spec b/kernel.spec index 95f21ea30..ceea70ed4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1953,6 +1953,9 @@ fi # and build. %changelog +* Mon Jan 30 2012 Dave Jones +- Restore the Savage DRM and several others that were accidentally early-deprecated. + * Mon Jan 30 2012 John W. Linville - Reinstate patch to remove overlap between bcma/b43 and brcmsmac From d8fd9cb2c8b141b4cc95cfb7dd09e094c6275149 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 30 Jan 2012 14:00:38 -0500 Subject: [PATCH 293/397] Enable kmemleak (off by default) in kernel-debug (rhbz 782419) --- config-debug | 5 +++++ kernel.spec | 12 ++++++++++++ realtek_async_autopm.patch | 13 +++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 realtek_async_autopm.patch diff --git a/config-debug b/config-debug index 19ae4656f..e3c1e6e44 100644 --- a/config-debug +++ b/config-debug @@ -104,3 +104,8 @@ CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y + +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 +# CONFIG_DEBUG_KMEMLEAK_TEST is not set +CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y diff --git a/kernel.spec b/kernel.spec index ceea70ed4..add1c5ac6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -706,6 +706,9 @@ Patch21227: mac80211-fix-work-removal-on-deauth-request.patch #rhbz 718790 Patch21230: rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch +#rhbz 784345 +Patch21231: realtek_async_autopm.patch + Patch22000: rcu-reintroduce-missing-calls.patch %endif @@ -1306,6 +1309,9 @@ ApplyPatch fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch +#rhbz 784345 +ApplyPatch realtek_async_autopm.patch + # END OF PATCH APPLICATIONS %endif @@ -1953,6 +1959,12 @@ fi # and build. %changelog +* Mon Jan 30 2012 Dave Jones +- Enable kmemleak (off by default) in kernel-debug (rhbz 782419) + +* Mon Jan 30 2012 Dave Jones +- Test fix for realtek_async_autopm oops from Stanislaw Gruszka (rhbz 784345) + * Mon Jan 30 2012 Dave Jones - Restore the Savage DRM and several others that were accidentally early-deprecated. diff --git a/realtek_async_autopm.patch b/realtek_async_autopm.patch new file mode 100644 index 000000000..3c6b45cca --- /dev/null +++ b/realtek_async_autopm.patch @@ -0,0 +1,13 @@ +diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c +index 1f62723..d32f720 100644 +--- a/drivers/usb/storage/realtek_cr.c ++++ b/drivers/usb/storage/realtek_cr.c +@@ -789,7 +789,7 @@ static void rts51x_suspend_timer_fn(unsigned long data) + rts51x_set_stat(chip, RTS51X_STAT_SS); + /* ignore mass storage interface's children */ + pm_suspend_ignore_children(&us->pusb_intf->dev, true); +- usb_autopm_put_interface(us->pusb_intf); ++ usb_autopm_put_interface_async(us->pusb_intf); + US_DEBUGP("%s: RTS51X_STAT_SS 01," + "intf->pm_usage_cnt:%d, power.usage:%d\n", + __func__, From c24ab00680b1ba9d58a207cbf59b64535583dca8 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Tue, 31 Jan 2012 12:12:10 -0600 Subject: [PATCH 294/397] diable TOUCHSCREEN_EETI on all arm arches --- config-arm-generic | 3 +++ config-arm-kirkwood | 2 -- kernel.spec | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/config-arm-generic b/config-arm-generic index 558c7c4d0..4f44a3e37 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -186,6 +186,9 @@ CONFIG_LSM_MMAP_MIN_ADDR=32768 # CONFIG_DRM_NOUVEAU is not set # CONFIG_MLX4_EN is not set +# drivers/input/touchscreen/eeti_ts.c:65:2: error: implicit declaration of function 'irq_to_gpio' [-Werror=implicit-function-declaration] +# CONFIG_TOUCHSCREEN_EETI is not set + # FIXME: Guesses, need checking # CONFIG_MACH_EUKREA_CPUIMX35SD is not set CONFIG_ARM_ERRATA_720789=y diff --git a/config-arm-kirkwood b/config-arm-kirkwood index 415e822dc..5eb6a3db3 100644 --- a/config-arm-kirkwood +++ b/config-arm-kirkwood @@ -39,5 +39,3 @@ CONFIG_LEDS_NETXBIG=m CONFIG_RTC_DRV_MV=m CONFIG_MV_XOR=y CONFIG_CRYPTO_DEV_MV_CESA=m - -# CONFIG_TOUCHSCREEN_EETI is not set diff --git a/kernel.spec b/kernel.spec index add1c5ac6..feecda2a5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1959,6 +1959,9 @@ fi # and build. %changelog +* Tue Jan 31 2012 Dennis Gilmore +- diable TOUCHSCREEN_EETI on all arm arches + * Mon Jan 30 2012 Dave Jones - Enable kmemleak (off by default) in kernel-debug (rhbz 782419) From 4fc891d8e343fb0ef69804579c2d304bc88aa922 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Wed, 1 Feb 2012 01:59:50 -0600 Subject: [PATCH 295/397] diable TOUCHSCREEN_EETI on all arm arches - add patch for arm mtd --- arm-build-bug-on.patch | 28 ++++++++++++++++++++++++++++ kernel.spec | 3 +++ 2 files changed, 31 insertions(+) create mode 100644 arm-build-bug-on.patch diff --git a/arm-build-bug-on.patch b/arm-build-bug-on.patch new file mode 100644 index 000000000..deb0998d6 --- /dev/null +++ b/arm-build-bug-on.patch @@ -0,0 +1,28 @@ +BUILD_BUG_ON is defined in linux/kernel.h but that is not included by the +asm/bug.h header which uses it. This causes a build error: + +...include/linux/mtd/map.h: In function 'inline_map_read': +...include/linux/mtd/map.h:408:3: error: implicit declaration of function +'BUILD_BUG_ON' [-Werror=implicit-function-declaration] + +The check is not essential and is not present for other architectures, so +just remove it. + +Signed-off-by: Simon Glass chromium.org> +--- + arch/arm/include/asm/bug.h | 1 - + 1 files changed, 0 insertions(+), 1 deletions(-) + +diff --git a/arch/arm/include/asm/bug.h b/arch/arm/include/asm/bug.h +index 9abe7a0..fac79dc 100644 +--- a/arch/arm/include/asm/bug.h ++++ b/arch/arm/include/asm/bug.h +@@ -32,7 +32,6 @@ + + #define __BUG(__file, __line, __value) \ + do { \ +- BUILD_BUG_ON(sizeof(struct bug_entry) != 12); \ + asm volatile("1:\t" BUG_INSTR_TYPE #__value "\n" \ + ".pushsection .rodata.str, \"aMS\", %progbits, 1\n" \ + "2:\t.asciz " #__file "\n" \ +-- diff --git a/kernel.spec b/kernel.spec index feecda2a5..bc8c2b5ac 100644 --- a/kernel.spec +++ b/kernel.spec @@ -655,6 +655,7 @@ Patch20000: utrace.patch # Flattened devicetree support Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch +Patch21002: arm-build-bug-on.patch #rhbz 717735 Patch21045: nfs-client-freezer.patch @@ -1134,6 +1135,7 @@ ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R # ApplyPatch arm-omap-dt-compat.patch ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch +ApplyPatch arm-build-bug-on.patch ApplyPatch taint-vbox.patch # @@ -1961,6 +1963,7 @@ fi %changelog * Tue Jan 31 2012 Dennis Gilmore - diable TOUCHSCREEN_EETI on all arm arches +- add patch for arm mtd * Mon Jan 30 2012 Dave Jones - Enable kmemleak (off by default) in kernel-debug (rhbz 782419) From 49cb1746ef62fd0e035dbd65b6f2db56eb0557ac Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Tue, 31 Jan 2012 19:45:16 -0600 Subject: [PATCH 296/397] diable TOUCHSCREEN_EETI on all arm arches - add patch for arm mtd - add patch for stmmac on arm --- arm-stmmac-mmc-core.patch | 26 ++++++++++++++++++++++++++ kernel.spec | 3 +++ 2 files changed, 29 insertions(+) create mode 100644 arm-stmmac-mmc-core.patch diff --git a/arm-stmmac-mmc-core.patch b/arm-stmmac-mmc-core.patch new file mode 100644 index 000000000..469fe42d4 --- /dev/null +++ b/arm-stmmac-mmc-core.patch @@ -0,0 +1,26 @@ +Fix this error: + + CC drivers/net/ethernet/stmicro/stmmac/mmc_core.o +drivers/net/ethernet/stmicro/stmmac/mmc_core.c: In function 'dwmac_mmc_ctrl': +drivers/net/ethernet/stmicro/stmmac/mmc_core.c:143:2: error: implicit + declaration of function 'pr_debug' [-Werror=implicit-function-declaration] + +Signed-off-by: Stefan Roese denx.de> +Cc: Giuseppe Cavallaro st.com> +--- + drivers/net/ethernet/stmicro/stmmac/mmc_core.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c +index 41e6b33..c07cfe9 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c ++++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c +@@ -22,6 +22,7 @@ + Author: Giuseppe Cavallaro st.com> + *******************************************************************************/ + ++#include + #include + #include "mmc.h" + +-- diff --git a/kernel.spec b/kernel.spec index bc8c2b5ac..80b22cc8a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -656,6 +656,7 @@ Patch20000: utrace.patch Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch Patch21002: arm-build-bug-on.patch +Patch21003: arm-stmmac-mmc-core.patch #rhbz 717735 Patch21045: nfs-client-freezer.patch @@ -1136,6 +1137,7 @@ ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R ApplyPatch arm-omap-dt-compat.patch ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch ApplyPatch arm-build-bug-on.patch +ApplyPatch arm-stmmac-mmc-core.patch ApplyPatch taint-vbox.patch # @@ -1964,6 +1966,7 @@ fi * Tue Jan 31 2012 Dennis Gilmore - diable TOUCHSCREEN_EETI on all arm arches - add patch for arm mtd +- add patch for stmmac on arm * Mon Jan 30 2012 Dave Jones - Enable kmemleak (off by default) in kernel-debug (rhbz 782419) From 327c79795521d0faccd25e4f633369c5afe73cc3 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Wed, 1 Feb 2012 07:19:04 -0600 Subject: [PATCH 297/397] diable TOUCHSCREEN_EETI on all arm arches - add patch for arm mtd - add patch for stmmac on arm - disable USB_IMX21_HCD pn imx - enable CACHE_L2X0 on imx --- config-arm-imx | 4 ++-- kernel.spec | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/config-arm-imx b/config-arm-imx index 2dbe10a1f..7aa2c779b 100644 --- a/config-arm-imx +++ b/config-arm-imx @@ -33,7 +33,7 @@ CONFIG_MXC_IRQ_PRIOR=y CONFIG_MXC_PWM=m CONFIG_MXC_DEBUG_BOARD=y # CONFIG_CPU_BPREDICT_DISABLE is not set -# CONFIG_CACHE_L2X0 is not set +CONFIG_CACHE_L2X0=y CONFIG_ARM_DMA_MEM_BUFFERABLE=y CONFIG_ARM_ERRATA_411920=y CONFIG_PL310_ERRATA_588369=y @@ -56,7 +56,7 @@ CONFIG_DVB_TDA1004X=m CONFIG_DVB_PLL=m CONFIG_SND_IMX_SOC=m CONFIG_USB_EHCI_MXC=y -CONFIG_USB_IMX21_HCD=m +# CONFIG_USB_IMX21_HCD is not set CONFIG_MMC_SDHCI_ESDHC_IMX=m CONFIG_MMC_MXC=m CONFIG_RTC_MXC=m diff --git a/kernel.spec b/kernel.spec index 80b22cc8a..b3f8c2b97 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1967,6 +1967,8 @@ fi - diable TOUCHSCREEN_EETI on all arm arches - add patch for arm mtd - add patch for stmmac on arm +- disable USB_IMX21_HCD pn imx +- enable CACHE_L2X0 on imx * Mon Jan 30 2012 Dave Jones - Enable kmemleak (off by default) in kernel-debug (rhbz 782419) From 1648faf090c7404b08a5cf39e2925b884283e213 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 1 Feb 2012 09:36:31 -0500 Subject: [PATCH 298/397] Revert the f16 use-ext4-for-ext2/ext3 change. --- config-generic | 18 +++++++++++++++--- kernel.spec | 3 +++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/config-generic b/config-generic index 025b58cde..8b4d38800 100644 --- a/config-generic +++ b/config-generic @@ -3566,14 +3566,26 @@ CONFIG_MFD_WM8400=m # CONFIG_MISC_FILESYSTEMS=y -# ext4 is used for ext2 and ext3 filesystems -# CONFIG_EXT2_FS is not set -# CONFIG_EXT3_FS is not set +CONFIG_EXT2_FS=m +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_DEFAULTS_TO_ORDERED=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set + CONFIG_EXT4_FS=y CONFIG_EXT4_USE_FOR_EXT23=y CONFIG_EXT4_FS_XATTR=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_USE_FOR_EXT23 is not set + CONFIG_JBD2=y CONFIG_FS_MBCACHE=y CONFIG_REISERFS_FS=m diff --git a/kernel.spec b/kernel.spec index b3f8c2b97..168a3ebc2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1963,6 +1963,9 @@ fi # and build. %changelog +* Wed Feb 01 2012 Dave Jones +- Revert the f16 use-ext4-for-ext2/ext3 change. + * Tue Jan 31 2012 Dennis Gilmore - diable TOUCHSCREEN_EETI on all arm arches - add patch for arm mtd From 2c860b02ae50f877c7fee6547fb817a8e47af2b7 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 1 Feb 2012 11:54:23 -0500 Subject: [PATCH 299/397] Revert more f16 config changes that shouldn't be in f15. --- config-generic | 17 +++++++++-------- config-x86-generic | 8 ++++---- kernel.spec | 3 +++ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/config-generic b/config-generic index 8b4d38800..56ad06735 100644 --- a/config-generic +++ b/config-generic @@ -174,7 +174,7 @@ CONFIG_INFINIBAND_QIB=m CONFIG_BINFMT_ELF=y CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y # CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_MISC=m +CONFIG_BINFMT_MISC=y # # Device Drivers @@ -363,7 +363,7 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_OSD=m -CONFIG_BLK_DEV_RAM=m +CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_BLK_DEV_INITRD=y @@ -3580,7 +3580,6 @@ CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_EXT4_FS=y -CONFIG_EXT4_USE_FOR_EXT23=y CONFIG_EXT4_FS_XATTR=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y @@ -4107,12 +4106,14 @@ CONFIG_PM_RUNTIME=y # CONFIG_PM_OPP is not set CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEBUG=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m CONFIG_CPU_FREQ_TABLE=y CONFIG_CPU_FREQ_STAT=m CONFIG_CPU_FREQ_STAT_DETAILS=y diff --git a/config-x86-generic b/config-x86-generic index fec30ea87..c57aa12d3 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -86,10 +86,10 @@ CONFIG_ACPI_APEI_MEMORY_FAILURE=y CONFIG_ACPI_IPMI=m CONFIG_ACPI_CUSTOM_METHOD=m -CONFIG_X86_ACPI_CPUFREQ=y -CONFIG_X86_PCC_CPUFREQ=y -CONFIG_X86_POWERNOW_K8=y -CONFIG_X86_P4_CLOCKMOD=y +CONFIG_X86_ACPI_CPUFREQ=m +CONFIG_X86_PCC_CPUFREQ=m +CONFIG_X86_POWERNOW_K8=m +CONFIG_X86_P4_CLOCKMOD=m # CONFIG_X86_SPEEDSTEP_CENTRINO is not set # diff --git a/kernel.spec b/kernel.spec index 168a3ebc2..cb00d00f1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1963,6 +1963,9 @@ fi # and build. %changelog +* Wed Feb 01 2012 Dave Jones +- Revert more f16 config changes that shouldn't be in f15. + * Wed Feb 01 2012 Dave Jones - Revert the f16 use-ext4-for-ext2/ext3 change. From 8b0318d553a45281e27c03963341705ad13a28e6 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Thu, 2 Feb 2012 09:06:29 -0600 Subject: [PATCH 300/397] add patch to ensure that mfd-core is builtin when building nvec on tegra build nvec-leds on tegra kernel --- arm-tegra-nvec-kconfig.patch | 10 ++++++++++ config-arm-tegra | 1 + kernel.spec | 6 ++++++ 3 files changed, 17 insertions(+) create mode 100644 arm-tegra-nvec-kconfig.patch diff --git a/arm-tegra-nvec-kconfig.patch b/arm-tegra-nvec-kconfig.patch new file mode 100644 index 000000000..a3f568cd5 --- /dev/null +++ b/arm-tegra-nvec-kconfig.patch @@ -0,0 +1,10 @@ +--- linux-2.6.42.noarch/drivers/staging/nvec/Kconfig.orig 2012-02-02 08:16:12.512727480 -0600 ++++ linux-2.6.42.noarch/drivers/staging/nvec/Kconfig 2012-02-01 18:44:56.674990109 -0600 +@@ -1,6 +1,6 @@ + config MFD_NVEC + bool "NV Tegra Embedded Controller SMBus Interface" +- depends on I2C && GPIOLIB && ARCH_TEGRA ++ depends on I2C && GPIOLIB && ARCH_TEGRA && MFD_CORE=y + help + Say Y here to enable support for a nVidia compliant embedded + controller. diff --git a/config-arm-tegra b/config-arm-tegra index 495e91e65..11f060d06 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -68,6 +68,7 @@ CONFIG_KEYBOARD_NVEC=y CONFIG_SERIO_NVEC_PS2=y CONFIG_NVEC_POWER=y CONFIG_POWER_SUPPLY=y +CONFIG_NVEC_LEDS=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_DEBUG=y diff --git a/kernel.spec b/kernel.spec index cb00d00f1..3b4f4423b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -657,6 +657,7 @@ Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch Patch21002: arm-build-bug-on.patch Patch21003: arm-stmmac-mmc-core.patch +Patch21004: arm-tegra-nvec-kconfig.patch #rhbz 717735 Patch21045: nfs-client-freezer.patch @@ -1138,6 +1139,7 @@ ApplyPatch arm-omap-dt-compat.patch ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch ApplyPatch arm-build-bug-on.patch ApplyPatch arm-stmmac-mmc-core.patch +ApplyPatch arm-tegra-nvec-kconfig.patch ApplyPatch taint-vbox.patch # @@ -1963,6 +1965,10 @@ fi # and build. %changelog +* Thu Feb 02 2012 Dennis Gilmore +- add patch to ensure that mfd-core is builtin when building nvec on tegra +- build nvec-leds on tegra kernel + * Wed Feb 01 2012 Dave Jones - Revert more f16 config changes that shouldn't be in f15. From 85243fee591fa1aeacd90e818211cf16a2a89cd5 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 3 Feb 2012 13:38:02 -0500 Subject: [PATCH 301/397] Linux 3.2.3 --- kernel.spec | 31 +--- ...1-fix-work-removal-on-deauth-request.patch | 154 ------------------ ...ds_sock_lock-BH-rather-than-IRQ-safe.patch | 116 ------------- realtek_async_autopm.patch | 13 -- sources | 2 +- tpm_tis-delay-after-aborting-cmd.patch | 17 -- 6 files changed, 5 insertions(+), 328 deletions(-) delete mode 100644 mac80211-fix-work-removal-on-deauth-request.patch delete mode 100644 rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch delete mode 100644 realtek_async_autopm.patch delete mode 100644 tpm_tis-delay-after-aborting-cmd.patch diff --git a/kernel.spec b/kernel.spec index 3b4f4423b..0e571faef 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 @@ -665,9 +665,6 @@ Patch21045: nfs-client-freezer.patch #rhbz 590880 Patch21046: alps.patch -#rhbz 746097 -Patch21049: tpm_tis-delay-after-aborting-cmd.patch - Patch21070: ext4-Support-check-none-nocheck-mount-options.patch Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch Patch21072: ext3-Fix-error-handling-on-inode-bitmap-corruption.patch @@ -704,16 +701,6 @@ Patch21101: hpsa-add-irqf-shared.patch Patch21225: pci-Rework-ASPM-disable-code.patch -Patch21227: mac80211-fix-work-removal-on-deauth-request.patch - -#rhbz 718790 -Patch21230: rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch - -#rhbz 784345 -Patch21231: realtek_async_autopm.patch - -Patch22000: rcu-reintroduce-missing-calls.patch - %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1274,17 +1261,12 @@ ApplyPatch hpsa-add-irqf-shared.patch ApplyPatch pci-Rework-ASPM-disable-code.patch -ApplyPatch mac80211-fix-work-removal-on-deauth-request.patch - #rhbz 717735 ApplyPatch nfs-client-freezer.patch #rhbz 590880 ApplyPatch alps.patch -#rhbz 746097 -ApplyPatch tpm_tis-delay-after-aborting-cmd.patch - #rhbz 771058 ApplyPatch msi-irq-sysfs-warning.patch @@ -1304,20 +1286,12 @@ ApplyPatch procfs-parse-mount-options.patch ApplyPatch procfs-add-hidepid-and-gid-mount-options.patch ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch -ApplyPatch rcu-reintroduce-missing-calls.patch - -#rhbz 718790 -ApplyPatch rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch - #rhbz 783211 ApplyPatch fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch -#rhbz 784345 -ApplyPatch realtek_async_autopm.patch - # END OF PATCH APPLICATIONS %endif @@ -1965,6 +1939,9 @@ fi # and build. %changelog +* Fri Feb 03 2012 Dave Jones +- Linux 3.2.3 + * Thu Feb 02 2012 Dennis Gilmore - add patch to ensure that mfd-core is builtin when building nvec on tegra - build nvec-leds on tegra kernel diff --git a/mac80211-fix-work-removal-on-deauth-request.patch b/mac80211-fix-work-removal-on-deauth-request.patch deleted file mode 100644 index 60b91d3cf..000000000 --- a/mac80211-fix-work-removal-on-deauth-request.patch +++ /dev/null @@ -1,154 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Johannes Berg -Newsgroups: gmane.linux.kernel.wireless.general -Subject: [PATCH 3.3] mac80211: fix work removal on deauth request -Date: Wed, 18 Jan 2012 14:10:25 +0100 -Lines: 107 -Approved: news@gmane.org -Message-ID: <1326892225.4778.5.camel@jlt3.sipsolutions.net> -NNTP-Posting-Host: lo.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset="UTF-8" -Content-Transfer-Encoding: 7bit -X-Trace: dough.gmane.org 1326892249 18013 80.91.229.12 (18 Jan 2012 13:10:49 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Wed, 18 Jan 2012 13:10:49 +0000 (UTC) -Cc: linux-wireless , - Pontus Fuchs -To: John Linville -Original-X-From: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Wed Jan 18 14:10:44 2012 -Return-path: -Envelope-to: glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1RnVHo-00044l-Aq - for glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Wed, 18 Jan 2012 14:10:44 +0100 -Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand - id S1757410Ab2ARNK3 (ORCPT - ); - Wed, 18 Jan 2012 08:10:29 -0500 -Original-Received: from he.sipsolutions.net ([78.46.109.217]:45023 "EHLO - sipsolutions.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1754365Ab2ARNK2 (ORCPT - ); - Wed, 18 Jan 2012 08:10:28 -0500 -Original-Received: by sipsolutions.net with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) - (Exim 4.77) - (envelope-from ) - id 1RnVHW-0004hf-Lx; Wed, 18 Jan 2012 14:10:26 +0100 -X-Mailer: Evolution 2.30.3 -Original-Sender: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Xref: news.gmane.org gmane.linux.kernel.wireless.general:84095 -Archived-At: - -From: Johannes Berg - -When deauth is requested while an auth or assoc -work item is in progress, we currently delete it -without regard for any state it might need to -clean up. Fix it by cleaning up for those items. - -In the case Pontus found, the problem manifested -itself as such: - -authenticate with 00:23:69:aa:dd:7b (try 1) -authenticated -failed to insert Dummy STA entry for the AP (error -17) -deauthenticating from 00:23:69:aa:dd:7b by local choice (reason=2) - -It could also happen differently if the driver -uses the tx_sync callback. - -We can't just call the ->done() method of the work -items because that will lock up due to the locking -in cfg80211. This fix isn't very clean, but that -seems acceptable since I have patches pending to -remove this code completely. - -Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Reported-by: Pontus Fuchs -Tested-by: Pontus Fuchs -Signed-off-by: Johannes Berg ---- - net/mac80211/mlme.c | 38 +++++++++++++++++++++++++++----------- - 1 file changed, 27 insertions(+), 11 deletions(-) - ---- a/net/mac80211/mlme.c 2012-01-18 14:04:33.000000000 +0100 -+++ b/net/mac80211/mlme.c 2012-01-18 14:04:34.000000000 +0100 -@@ -2750,7 +2750,6 @@ int ieee80211_mgd_deauth(struct ieee8021 - { - struct ieee80211_local *local = sdata->local; - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; -- struct ieee80211_work *wk; - u8 bssid[ETH_ALEN]; - bool assoc_bss = false; - -@@ -2763,30 +2762,47 @@ int ieee80211_mgd_deauth(struct ieee8021 - assoc_bss = true; - } else { - bool not_auth_yet = false; -+ struct ieee80211_work *tmp, *wk = NULL; - - mutex_unlock(&ifmgd->mtx); - - mutex_lock(&local->mtx); -- list_for_each_entry(wk, &local->work_list, list) { -- if (wk->sdata != sdata) -+ list_for_each_entry(tmp, &local->work_list, list) { -+ if (tmp->sdata != sdata) - continue; - -- if (wk->type != IEEE80211_WORK_DIRECT_PROBE && -- wk->type != IEEE80211_WORK_AUTH && -- wk->type != IEEE80211_WORK_ASSOC && -- wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) -+ if (tmp->type != IEEE80211_WORK_DIRECT_PROBE && -+ tmp->type != IEEE80211_WORK_AUTH && -+ tmp->type != IEEE80211_WORK_ASSOC && -+ tmp->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) - continue; - -- if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN)) -+ if (memcmp(req->bss->bssid, tmp->filter_ta, ETH_ALEN)) - continue; - -- not_auth_yet = wk->type == IEEE80211_WORK_DIRECT_PROBE; -- list_del_rcu(&wk->list); -- free_work(wk); -+ not_auth_yet = tmp->type == IEEE80211_WORK_DIRECT_PROBE; -+ list_del_rcu(&tmp->list); -+ synchronize_rcu(); -+ wk = tmp; - break; - } - mutex_unlock(&local->mtx); - -+ if (wk && wk->type == IEEE80211_WORK_ASSOC) { -+ /* clean up dummy sta & TX sync */ -+ sta_info_destroy_addr(wk->sdata, wk->filter_ta); -+ if (wk->assoc.synced) -+ drv_finish_tx_sync(local, wk->sdata, -+ wk->filter_ta, -+ IEEE80211_TX_SYNC_ASSOC); -+ } else if (wk && wk->type == IEEE80211_WORK_AUTH) { -+ if (wk->probe_auth.synced) -+ drv_finish_tx_sync(local, wk->sdata, -+ wk->filter_ta, -+ IEEE80211_TX_SYNC_AUTH); -+ } -+ kfree(wk); -+ - /* - * If somebody requests authentication and we haven't - * sent out an auth frame yet there's no need to send - - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - diff --git a/rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch b/rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch deleted file mode 100644 index 0946aad6b..000000000 --- a/rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch +++ /dev/null @@ -1,116 +0,0 @@ -From efc3dbc37412c027e363736b4f4c74ee5e8ecffc Mon Sep 17 00:00:00 2001 -From: "David S. Miller" -Date: Tue, 24 Jan 2012 17:03:44 -0500 -Subject: [PATCH] rds: Make rds_sock_lock BH rather than IRQ safe. - -rds_sock_info() triggers locking warnings because we try to perform a -local_bh_enable() (via sock_i_ino()) while hardware interrupts are -disabled (via taking rds_sock_lock). - -There is no reason for rds_sock_lock to be a hardware IRQ disabling -lock, none of these access paths run in hardware interrupt context. - -Therefore making it a BH disabling lock is safe and sufficient to -fix this bug. - -Reported-by: Kumar Sanghvi -Reported-by: Josh Boyer -Signed-off-by: David S. Miller ---- - net/rds/af_rds.c | 20 ++++++++------------ - 1 files changed, 8 insertions(+), 12 deletions(-) - -diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c -index bb6ad81..424ff62 100644 ---- a/net/rds/af_rds.c -+++ b/net/rds/af_rds.c -@@ -68,7 +68,6 @@ static int rds_release(struct socket *sock) - { - struct sock *sk = sock->sk; - struct rds_sock *rs; -- unsigned long flags; - - if (!sk) - goto out; -@@ -94,10 +93,10 @@ static int rds_release(struct socket *sock) - rds_rdma_drop_keys(rs); - rds_notify_queue_get(rs, NULL); - -- spin_lock_irqsave(&rds_sock_lock, flags); -+ spin_lock_bh(&rds_sock_lock); - list_del_init(&rs->rs_item); - rds_sock_count--; -- spin_unlock_irqrestore(&rds_sock_lock, flags); -+ spin_unlock_bh(&rds_sock_lock); - - rds_trans_put(rs->rs_transport); - -@@ -409,7 +408,6 @@ static const struct proto_ops rds_proto_ops = { - - static int __rds_create(struct socket *sock, struct sock *sk, int protocol) - { -- unsigned long flags; - struct rds_sock *rs; - - sock_init_data(sock, sk); -@@ -426,10 +424,10 @@ static int __rds_create(struct socket *sock, struct sock *sk, int protocol) - spin_lock_init(&rs->rs_rdma_lock); - rs->rs_rdma_keys = RB_ROOT; - -- spin_lock_irqsave(&rds_sock_lock, flags); -+ spin_lock_bh(&rds_sock_lock); - list_add_tail(&rs->rs_item, &rds_sock_list); - rds_sock_count++; -- spin_unlock_irqrestore(&rds_sock_lock, flags); -+ spin_unlock_bh(&rds_sock_lock); - - return 0; - } -@@ -471,12 +469,11 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len, - { - struct rds_sock *rs; - struct rds_incoming *inc; -- unsigned long flags; - unsigned int total = 0; - - len /= sizeof(struct rds_info_message); - -- spin_lock_irqsave(&rds_sock_lock, flags); -+ spin_lock_bh(&rds_sock_lock); - - list_for_each_entry(rs, &rds_sock_list, rs_item) { - read_lock(&rs->rs_recv_lock); -@@ -492,7 +489,7 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len, - read_unlock(&rs->rs_recv_lock); - } - -- spin_unlock_irqrestore(&rds_sock_lock, flags); -+ spin_unlock_bh(&rds_sock_lock); - - lens->nr = total; - lens->each = sizeof(struct rds_info_message); -@@ -504,11 +501,10 @@ static void rds_sock_info(struct socket *sock, unsigned int len, - { - struct rds_info_socket sinfo; - struct rds_sock *rs; -- unsigned long flags; - - len /= sizeof(struct rds_info_socket); - -- spin_lock_irqsave(&rds_sock_lock, flags); -+ spin_lock_bh(&rds_sock_lock); - - if (len < rds_sock_count) - goto out; -@@ -529,7 +525,7 @@ out: - lens->nr = rds_sock_count; - lens->each = sizeof(struct rds_info_socket); - -- spin_unlock_irqrestore(&rds_sock_lock, flags); -+ spin_unlock_bh(&rds_sock_lock); - } - - static void rds_exit(void) --- -1.7.7.6 - diff --git a/realtek_async_autopm.patch b/realtek_async_autopm.patch deleted file mode 100644 index 3c6b45cca..000000000 --- a/realtek_async_autopm.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c -index 1f62723..d32f720 100644 ---- a/drivers/usb/storage/realtek_cr.c -+++ b/drivers/usb/storage/realtek_cr.c -@@ -789,7 +789,7 @@ static void rts51x_suspend_timer_fn(unsigned long data) - rts51x_set_stat(chip, RTS51X_STAT_SS); - /* ignore mass storage interface's children */ - pm_suspend_ignore_children(&us->pusb_intf->dev, true); -- usb_autopm_put_interface(us->pusb_intf); -+ usb_autopm_put_interface_async(us->pusb_intf); - US_DEBUGP("%s: RTS51X_STAT_SS 01," - "intf->pm_usage_cnt:%d, power.usage:%d\n", - __func__, diff --git a/sources b/sources index 6c0833def..c395e0ba0 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz -5e53edbf75fcaa3a8d1697f3a053102d patch-3.2.2.xz +4ffcd30b95b4d2435be40405507319dd patch-3.2.3.xz diff --git a/tpm_tis-delay-after-aborting-cmd.patch b/tpm_tis-delay-after-aborting-cmd.patch deleted file mode 100644 index 315284f50..000000000 --- a/tpm_tis-delay-after-aborting-cmd.patch +++ /dev/null @@ -1,17 +0,0 @@ -This patch adds a delay after aborting a command. Some TPMs need -this and will not process the subsequent command correctly otherwise. - -Signed-off-by: Stefan Berger - ---- linux-3.1.noarch/drivers/char/tpm/tpm_tis.c~ 2011-12-20 18:08:01.654464487 -0500 -+++ linux-3.1.noarch/drivers/char/tpm/tpm_tis.c 2011-12-20 18:08:23.476380364 -0500 -@@ -432,6 +432,9 @@ static int probe_itpm(struct tpm_chip *c - out: - itpm = rem_itpm; - tpm_tis_ready(chip); -+ /* some TPMs need a break here otherwise they will not work -+ * correctly on the immediately subsequent command */ -+ msleep(chip->vendor.timeout_b); - release_locality(chip, chip->vendor.locality, 0); - - return rc; From ebc6e50a9868d3ce91a86b834ca2b13ae2472201 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 5 Feb 2012 16:53:28 -0500 Subject: [PATCH 302/397] readahead: fix pipeline break caused by block plug Also, remove unnecessary block-stray-block-put-after-teardown.patch --- block-readahead-block-plug.patch | 92 ++++++++++++++++++++++ block-stray-block-put-after-teardown.patch | 11 --- kernel.spec | 9 ++- 3 files changed, 99 insertions(+), 13 deletions(-) create mode 100644 block-readahead-block-plug.patch delete mode 100644 block-stray-block-put-after-teardown.patch diff --git a/block-readahead-block-plug.patch b/block-readahead-block-plug.patch new file mode 100644 index 000000000..0b7bca650 --- /dev/null +++ b/block-readahead-block-plug.patch @@ -0,0 +1,92 @@ +commit 3deaa7190a8da38453c4fabd9dec7f66d17fff67 +Author: Shaohua Li +Date: Fri Feb 3 15:37:17 2012 -0800 + + readahead: fix pipeline break caused by block plug + + Herbert Poetzl reported a performance regression since 2.6.39. The test + is a simple dd read, but with big block size. The reason is: + + T1: ra (A, A+128k), (A+128k, A+256k) + T2: lock_page for page A, submit the 256k + T3: hit page A+128K, ra (A+256k, A+384). the range isn't submitted + because of plug and there isn't any lock_page till we hit page A+256k + because all pages from A to A+256k is in memory + T4: hit page A+256k, ra (A+384, A+ 512). Because of plug, the range isn't + submitted again. + T5: lock_page A+256k, so (A+256k, A+512k) will be submitted. The task is + waitting for (A+256k, A+512k) finish. + + There is no request to disk in T3 and T4, so readahead pipeline breaks. + + We really don't need block plug for generic_file_aio_read() for buffered + I/O. The readahead already has plug and has fine grained control when I/O + should be submitted. Deleting plug for buffered I/O fixes the regression. + + One side effect is plug makes the request size 256k, the size is 128k + without it. This is because default ra size is 128k and not a reason we + need plug here. + + Vivek said: + + : We submit some readahead IO to device request queue but because of nested + : plug, queue never gets unplugged. When read logic reaches a page which is + : not in page cache, it waits for page to be read from the disk + : (lock_page_killable()) and that time we flush the plug list. + : + : So effectively read ahead logic is kind of broken in parts because of + : nested plugging. Removing top level plug (generic_file_aio_read()) for + : buffered reads, will allow unplugging queue earlier for readahead. + + Signed-off-by: Shaohua Li + Signed-off-by: Wu Fengguang + Reported-by: Herbert Poetzl + Tested-by: Eric Dumazet + Cc: Christoph Hellwig + Cc: Jens Axboe + Cc: Vivek Goyal + Cc: + Signed-off-by: Andrew Morton + Signed-off-by: Linus Torvalds + +diff --git a/mm/filemap.c b/mm/filemap.c +index 97f49ed..b662757 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -1400,15 +1400,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, + unsigned long seg = 0; + size_t count; + loff_t *ppos = &iocb->ki_pos; +- struct blk_plug plug; + + count = 0; + retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE); + if (retval) + return retval; + +- blk_start_plug(&plug); +- + /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ + if (filp->f_flags & O_DIRECT) { + loff_t size; +@@ -1424,8 +1421,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, + retval = filemap_write_and_wait_range(mapping, pos, + pos + iov_length(iov, nr_segs) - 1); + if (!retval) { ++ struct blk_plug plug; ++ ++ blk_start_plug(&plug); + retval = mapping->a_ops->direct_IO(READ, iocb, + iov, pos, nr_segs); ++ blk_finish_plug(&plug); + } + if (retval > 0) { + *ppos = pos + retval; +@@ -1481,7 +1482,6 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, + break; + } + out: +- blk_finish_plug(&plug); + return retval; + } + EXPORT_SYMBOL(generic_file_aio_read); diff --git a/block-stray-block-put-after-teardown.patch b/block-stray-block-put-after-teardown.patch deleted file mode 100644 index f4bf9c40c..000000000 --- a/block-stray-block-put-after-teardown.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- linux-2.6.39.noarch/block/elevator.c~ 2011-08-09 10:07:41.532774872 -0400 -+++ linux-2.6.39.noarch/block/elevator.c 2011-08-09 10:07:56.131724173 -0400 -@@ -815,7 +815,7 @@ void elv_completed_request(struct reques - */ - if (blk_account_rq(rq)) { - q->in_flight[rq_is_sync(rq)]--; -- if ((rq->cmd_flags & REQ_SORTED) && -+ if ((rq->cmd_flags & REQ_SORTED) && e->ops && - e->ops->elevator_completed_req_fn) - e->ops->elevator_completed_req_fn(q, rq); - } diff --git a/kernel.spec b/kernel.spec index 0e571faef..a17c188eb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -642,7 +642,8 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch12026: block-stray-block-put-after-teardown.patch +Patch12025: block-readahead-block-plug.patch + Patch12030: epoll-limit-paths.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch @@ -1242,7 +1243,7 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch epoll-limit-paths.patch -ApplyPatch block-stray-block-put-after-teardown.patch +ApplyPatch block-readahead-block-plug.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -1939,6 +1940,10 @@ fi # and build. %changelog +* Sun Feb 05 2012 Dave Jones +- Remove unnecessary block-stray-block-put-after-teardown.patch +- readahead: fix pipeline break caused by block plug + * Fri Feb 03 2012 Dave Jones - Linux 3.2.3 From 9f1f3a3c6355b29175c91ebe6120d5f2e3e5716e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 8 Feb 2012 08:28:25 -0500 Subject: [PATCH 303/397] Drop patch that was NAKd upstream (rhbz 783211) --- ...block-device-if-fsync-called-on-part.patch | 106 ------------------ kernel.spec | 11 +- 2 files changed, 4 insertions(+), 113 deletions(-) delete mode 100644 fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch diff --git a/fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch b/fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch deleted file mode 100644 index 5bab4f4ad..000000000 --- a/fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch +++ /dev/null @@ -1,106 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Niels de Vos -Newsgroups: gmane.linux.kernel,gmane.linux.file-systems -Subject: [PATCH v2] fs: Invalidate the cache for a parent block-device if fsync() is called for a partition -Date: Mon, 23 Jan 2012 10:38:29 +0000 -Lines: 58 -Approved: news@gmane.org -Message-ID: <1327315109-7740-1-git-send-email-ndevos@redhat.com> -References: <4F19356E.3020708@redhat.com> -NNTP-Posting-Host: lo.gmane.org -X-Trace: dough.gmane.org 1327315263 30652 80.91.229.12 (23 Jan 2012 10:41:03 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Mon, 23 Jan 2012 10:41:03 +0000 (UTC) -Cc: linux-kernel@vger.kernel.org, Niels de Vos , - "Bryn M. Reeves" , - Mikulas Patocka -To: linux-fsdevel@vger.kernel.org -Original-X-From: linux-kernel-owner@vger.kernel.org Mon Jan 23 11:40:58 2012 -Return-path: -Envelope-to: glk-linux-kernel-3@lo.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1RpHKb-0008Bu-Fh - for glk-linux-kernel-3@lo.gmane.org; Mon, 23 Jan 2012 11:40:57 +0100 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1753263Ab2AWKkt (ORCPT ); - Mon, 23 Jan 2012 05:40:49 -0500 -Original-Received: from mx1.redhat.com ([209.132.183.28]:58739 "EHLO mx1.redhat.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1751990Ab2AWKks (ORCPT ); - Mon, 23 Jan 2012 05:40:48 -0500 -Original-Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q0NAelMx027033 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Mon, 23 Jan 2012 05:40:47 -0500 -Original-Received: from ndevos.usersys.redhat.com (dhcp-1-51.fab.redhat.com [10.33.1.51]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q0NAejLn013691; - Mon, 23 Jan 2012 05:40:46 -0500 -In-Reply-To: <4F19356E.3020708@redhat.com> -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Original-Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel:1242432 gmane.linux.file-systems:60751 -Archived-At: - -Executing an fsync() on a file-descriptor of a partition flushes the -caches for that partition by calling blkdev_issue_flush(). However, it -seems that reading data through the parent device will still return the -old cached data. - -The cache for the block-device is not synced if the block-device is kept -open (due to a mounted partition, for example). Only when all users for -the disk have exited, the cache for the disk is made consistent again. - -Calling invalidate_bdev() on the parent block-device in case -blkdev_fsync() was called for a partition, fixes this. - -The problem can be worked around by forcing the caches to be flushed -with either - # blockdev --flushbufs ${dev_disk} -or - # echo 3 > /proc/sys/vm/drop_caches - -CC: Bryn M. Reeves -CC: Mikulas Patocka -Signed-off-by: Niels de Vos - ---- -v2: -- Do not call invalidate_bdev() from blkdev_issue_flush() and prevent - performance degration with journalled filesystems. - - Suggested was to call invalidate_bdev() in fsync_bdev(), but this is - not in the call-path of mkfs.ext3 and similar tools. Hence the issue - persists. - -- Correct phrasing a little, changing ioctl-BLKFLSBUF is not required. - -- This issue also occurs when doing an ioctl-BLKFLSBUF on a partition. - Reading the whole disk will still return cached data. If this is an - issue, it will need a seperate patch. ---- - fs/block_dev.c | 4 ++++ - 1 files changed, 4 insertions(+), 0 deletions(-) - -diff --git a/fs/block_dev.c b/fs/block_dev.c -index 0e575d1..433c4de 100644 ---- a/fs/block_dev.c -+++ b/fs/block_dev.c -@@ -424,6 +424,10 @@ int blkdev_fsync(struct file *filp, loff_t start, loff_t end, int datasync) - if (error == -EOPNOTSUPP) - error = 0; - -+ /* invalidate parent block_device */ -+ if (!error && bdev != bdev->bd_contains) -+ invalidate_bdev(bdev->bd_contains); -+ - return error; - } - EXPORT_SYMBOL(blkdev_fsync); --- -1.7.6.5 - diff --git a/kernel.spec b/kernel.spec index a17c188eb..71b191e93 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -688,9 +688,6 @@ Patch21082: procfs-parse-mount-options.patch Patch21083: procfs-add-hidepid-and-gid-mount-options.patch Patch21084: proc-fix-null-pointer-deref-in-proc_pid_permission.patch -#rhbz 783211 -Patch21087: fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch - # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 Patch21091: bcma-brcmsmac-compat.patch @@ -1287,9 +1284,6 @@ ApplyPatch procfs-parse-mount-options.patch ApplyPatch procfs-add-hidepid-and-gid-mount-options.patch ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch -#rhbz 783211 -ApplyPatch fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch - # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch @@ -1940,6 +1934,9 @@ fi # and build. %changelog +* Wed Feb 08 2012 Josh Boyer +- Drop patch that was NAKd upstream (rhbz 783211) + * Sun Feb 05 2012 Dave Jones - Remove unnecessary block-stray-block-put-after-teardown.patch - readahead: fix pipeline break caused by block plug From c2a76c7eafc9846fb6fe5f6d688fc66ac8d20916 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 8 Feb 2012 08:33:05 -0500 Subject: [PATCH 304/397] CVE-2011-4086: jbd2: unmapped buffer with _Unwritten or _Delay flags set can lead to DoS (rhbz 788260) --- ...nd-BH_Unwritten-in-journal_unmap_buf.patch | 91 +++++++++++++++++++ kernel.spec | 8 ++ 2 files changed, 99 insertions(+) create mode 100644 jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch diff --git a/jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch b/jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch new file mode 100644 index 000000000..5ea8ccc10 --- /dev/null +++ b/jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch @@ -0,0 +1,91 @@ +Path: news.gmane.org!not-for-mail +From: Eric Sandeen +Newsgroups: gmane.comp.file-systems.ext4 +Subject: [PATCH] jbd2: clear BH_Delay & BH_Unwritten in journal_unmap_buffer +Date: Tue, 07 Feb 2012 16:07:20 -0600 +Lines: 42 +Approved: news@gmane.org +Message-ID: <4F31A098.4050601@redhat.com> +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 7bit +X-Trace: dough.gmane.org 1328656072 12026 80.91.229.3 (7 Feb 2012 23:07:52 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Tue, 7 Feb 2012 23:07:52 +0000 (UTC) +To: ext4 development +Original-X-From: linux-ext4-owner@vger.kernel.org Wed Feb 08 00:07:52 2012 +Return-path: +Envelope-to: gcfe-linux-ext4@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1Ruu8d-0000lK-5P + for gcfe-linux-ext4@plane.gmane.org; Wed, 08 Feb 2012 00:07:51 +0100 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1756187Ab2BGXHt (ORCPT ); + Tue, 7 Feb 2012 18:07:49 -0500 +Original-Received: from mx1.redhat.com ([209.132.183.28]:19432 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1753992Ab2BGXHs (ORCPT ); + Tue, 7 Feb 2012 18:07:48 -0500 +Original-Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q17N7dj0027622 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) + for ; Tue, 7 Feb 2012 18:07:48 -0500 +Original-Received: from liberator.sandeen.net (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q17M7Kgt001990 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) + for ; Tue, 7 Feb 2012 17:07:21 -0500 +User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:10.0) Gecko/20120129 Thunderbird/10.0 +X-Enigmail-Version: 1.3.5 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +Original-Sender: linux-ext4-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-ext4@vger.kernel.org +Xref: news.gmane.org gmane.comp.file-systems.ext4:30623 +Archived-At: + +journal_unmap_buffer()'s zap_buffer: code clears a lot of buffer head +state ala discard_buffer(), but does not touch _Delay or _Unwritten +as discard_buffer() does. + +This can be problematic in some areas of the ext4 code which assume +that if they have found a buffer marked unwritten or delay, then it's +a live one. Perhaps those spots should check whether it is mapped +as well, but if jbd2 is going to tear down a buffer, let's really +tear it down completely. + +Without this I get some fsx failures on sub-page-block filesystems +up until v3.2, at which point 4e96b2dbbf1d7e81f22047a50f862555a6cb87cb +and 189e868fa8fdca702eb9db9d8afc46b5cb9144c9 make the failures go +away, because buried within that large change is some more flag +clearing. I still think it's worth doing in jbd2, since +->invalidatepage leads here directly, and it's the right place +to clear away these flags. + +Signed-off-by: Eric Sandeen +Cc: stable@vger.kernel.org +--- + +diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c +index 35ae096..52653306 100644 +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -1949,6 +1949,8 @@ zap_buffer_unlocked: + clear_buffer_mapped(bh); + clear_buffer_req(bh); + clear_buffer_new(bh); ++ clear_buffer_delay(bh); ++ clear_buffer_unwritten(bh); + bh->b_bdev = NULL; + return may_free; + } + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-ext4" 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 71b191e93..e7a304b10 100644 --- a/kernel.spec +++ b/kernel.spec @@ -688,6 +688,9 @@ Patch21082: procfs-parse-mount-options.patch Patch21083: procfs-add-hidepid-and-gid-mount-options.patch Patch21084: proc-fix-null-pointer-deref-in-proc_pid_permission.patch +#rhbz 788260 +Patch21085: jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch + # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 Patch21091: bcma-brcmsmac-compat.patch @@ -1284,6 +1287,9 @@ ApplyPatch procfs-parse-mount-options.patch ApplyPatch procfs-add-hidepid-and-gid-mount-options.patch ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch +#rhbz 788260 +ApplyPatch jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch + # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch @@ -1935,6 +1941,8 @@ fi %changelog * Wed Feb 08 2012 Josh Boyer +- CVE-2011-4086: jbd2: unmapped buffer with _Unwritten or _Delay flags + set can lead to DoS (rhbz 788260) - Drop patch that was NAKd upstream (rhbz 783211) * Sun Feb 05 2012 Dave Jones From 71aea6e1f7c05b013c8e3fb4b09aa04285fc06a8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 8 Feb 2012 10:51:51 -0500 Subject: [PATCH 305/397] Fix e1000e Tx hang check (rhbz 785806) --- e1000e-Avoid-wrong-check-on-TX-hang.patch | 95 +++++++++++++++++++++++ kernel.spec | 7 ++ 2 files changed, 102 insertions(+) create mode 100644 e1000e-Avoid-wrong-check-on-TX-hang.patch diff --git a/e1000e-Avoid-wrong-check-on-TX-hang.patch b/e1000e-Avoid-wrong-check-on-TX-hang.patch new file mode 100644 index 000000000..6064ddde8 --- /dev/null +++ b/e1000e-Avoid-wrong-check-on-TX-hang.patch @@ -0,0 +1,95 @@ +From 09357b00255c233705b1cf6d76a8d147340545b8 Mon Sep 17 00:00:00 2001 +From: Jeff Kirsher +Date: Fri, 18 Nov 2011 14:25:00 +0000 +Subject: [PATCH] e1000e: Avoid wrong check on TX hang + +Based on the original patch submitted my Michael Wang +. +Descriptors may not be write-back while checking TX hang with flag +FLAG2_DMA_BURST on. +So when we detect hang, we just flush the descriptor and detect +again for once. + +-v2 change 1 to true and 0 to false and remove extra () + +CC: Michael Wang +CC: Flavio Leitner +Acked-by: Jesse Brandeburg +Tested-by: Aaron Brown +Signed-off-by: Jeff Kirsher +--- + drivers/net/ethernet/intel/e1000e/e1000.h | 1 + + drivers/net/ethernet/intel/e1000e/netdev.c | 23 ++++++++++++++++++++--- + 2 files changed, 21 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h +index 9fe18d1..f478a22 100644 +--- a/drivers/net/ethernet/intel/e1000e/e1000.h ++++ b/drivers/net/ethernet/intel/e1000e/e1000.h +@@ -309,6 +309,7 @@ struct e1000_adapter { + u32 txd_cmd; + + bool detect_tx_hung; ++ bool tx_hang_recheck; + u8 tx_timeout_factor; + + u32 tx_int_delay; +diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c +index c6e9763..c12df69 100644 +--- a/drivers/net/ethernet/intel/e1000e/netdev.c ++++ b/drivers/net/ethernet/intel/e1000e/netdev.c +@@ -1014,6 +1014,7 @@ static void e1000_print_hw_hang(struct work_struct *work) + struct e1000_adapter *adapter = container_of(work, + struct e1000_adapter, + print_hang_task); ++ struct net_device *netdev = adapter->netdev; + struct e1000_ring *tx_ring = adapter->tx_ring; + unsigned int i = tx_ring->next_to_clean; + unsigned int eop = tx_ring->buffer_info[i].next_to_watch; +@@ -1025,6 +1026,21 @@ static void e1000_print_hw_hang(struct work_struct *work) + if (test_bit(__E1000_DOWN, &adapter->state)) + return; + ++ if (!adapter->tx_hang_recheck && ++ (adapter->flags2 & FLAG2_DMA_BURST)) { ++ /* May be block on write-back, flush and detect again ++ * flush pending descriptor writebacks to memory ++ */ ++ ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); ++ /* execute the writes immediately */ ++ e1e_flush(); ++ adapter->tx_hang_recheck = true; ++ return; ++ } ++ /* Real hang detected */ ++ adapter->tx_hang_recheck = false; ++ netif_stop_queue(netdev); ++ + e1e_rphy(hw, PHY_STATUS, &phy_status); + e1e_rphy(hw, PHY_1000T_STATUS, &phy_1000t_status); + e1e_rphy(hw, PHY_EXT_STATUS, &phy_ext_status); +@@ -1145,10 +1161,10 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) + if (tx_ring->buffer_info[i].time_stamp && + time_after(jiffies, tx_ring->buffer_info[i].time_stamp + + (adapter->tx_timeout_factor * HZ)) && +- !(er32(STATUS) & E1000_STATUS_TXOFF)) { ++ !(er32(STATUS) & E1000_STATUS_TXOFF)) + schedule_work(&adapter->print_hang_task); +- netif_stop_queue(netdev); +- } ++ else ++ adapter->tx_hang_recheck = false; + } + adapter->total_tx_bytes += total_tx_bytes; + adapter->total_tx_packets += total_tx_packets; +@@ -3838,6 +3854,7 @@ static int e1000_open(struct net_device *netdev) + + e1000_irq_enable(adapter); + ++ adapter->tx_hang_recheck = false; + netif_start_queue(netdev); + + adapter->idle_check = true; +-- +1.7.9 + diff --git a/kernel.spec b/kernel.spec index e7a304b10..7f685042f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -694,6 +694,9 @@ Patch21085: jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 Patch21091: bcma-brcmsmac-compat.patch +#rhbz 785806 +Patch21092: e1000e-Avoid-wrong-check-on-TX-hang.patch + #rhbz 771058 Patch21100: msi-irq-sysfs-warning.patch @@ -1290,6 +1293,9 @@ ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch #rhbz 788260 ApplyPatch jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch +#rhbz 785806 +ApplyPatch e1000e-Avoid-wrong-check-on-TX-hang.patch + # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch @@ -1944,6 +1950,7 @@ fi - CVE-2011-4086: jbd2: unmapped buffer with _Unwritten or _Delay flags set can lead to DoS (rhbz 788260) - Drop patch that was NAKd upstream (rhbz 783211) +- Fix e1000e Tx hang check (rhbz 785806) * Sun Feb 05 2012 Dave Jones - Remove unnecessary block-stray-block-put-after-teardown.patch From c93c7e5a024ba4a748cd86bb4d59d96e0aa197fa Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 9 Feb 2012 15:41:58 -0500 Subject: [PATCH 306/397] bsg: fix sysfs link remove warning (#787862) --- bsg-fix-sysfs-link-remove-warning.patch | 16 ++++++++++++++++ kernel.spec | 9 ++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 bsg-fix-sysfs-link-remove-warning.patch diff --git a/bsg-fix-sysfs-link-remove-warning.patch b/bsg-fix-sysfs-link-remove-warning.patch new file mode 100644 index 000000000..6e7625327 --- /dev/null +++ b/bsg-fix-sysfs-link-remove-warning.patch @@ -0,0 +1,16 @@ +diff --git a/block/bsg.c b/block/bsg.c +index 4cf703f..ff64ae3 100644 +--- a/block/bsg.c ++++ b/block/bsg.c +@@ -983,7 +983,8 @@ void bsg_unregister_queue(struct request_queue *q) + + mutex_lock(&bsg_mutex); + idr_remove(&bsg_minor_idr, bcd->minor); +- sysfs_remove_link(&q->kobj, "bsg"); ++ if (q->kobj.sd) ++ sysfs_remove_link(&q->kobj, "bsg"); + device_unregister(bcd->class_dev); + bcd->class_dev = NULL; + kref_put(&bcd->ref, bsg_kref_release_function); +-- +1.7.4.4 diff --git a/kernel.spec b/kernel.spec index 7f685042f..a0d1a183e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -644,6 +644,8 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12025: block-readahead-block-plug.patch +Patch12026: bsg-fix-sysfs-link-remove-warning.patch + Patch12030: epoll-limit-paths.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch @@ -1248,6 +1250,8 @@ ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch epoll-limit-paths.patch ApplyPatch block-readahead-block-plug.patch +ApplyPatch bsg-fix-sysfs-link-remove-warning.patch + # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -1946,7 +1950,10 @@ fi # and build. %changelog -* Wed Feb 08 2012 Josh Boyer +* Thu Feb 09 2012 Dave Jones +- bsg: fix sysfs link remove warning (#787862) + +* Wed Feb 08 2012 Josh Boyer 2.6.42.3-2.fc15 - CVE-2011-4086: jbd2: unmapped buffer with _Unwritten or _Delay flags set can lead to DoS (rhbz 788260) - Drop patch that was NAKd upstream (rhbz 783211) From aef732d8e5607105b3c6b4a4bde4164c07a1f6d2 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 10 Feb 2012 12:33:35 -0500 Subject: [PATCH 307/397] Implement TIOCGSERIAL for acm_tty_ioctl (rhbz 787607) --- cdc-acm-tiocgserial.patch | 58 +++++++++++++++++++++++++++++++++++++++ kernel.spec | 8 ++++++ 2 files changed, 66 insertions(+) create mode 100644 cdc-acm-tiocgserial.patch diff --git a/cdc-acm-tiocgserial.patch b/cdc-acm-tiocgserial.patch new file mode 100644 index 000000000..ec82506e8 --- /dev/null +++ b/cdc-acm-tiocgserial.patch @@ -0,0 +1,58 @@ +From http://permalink.gmane.org/gmane.linux.usb.general/9236 + +attempt to diagnose https://bugzilla.redhat.com/show_bug.cgi?id=787607 + +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c +index 9543b19..6dcc3a3 100644 +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -734,15 +734,40 @@ static int acm_tty_tiocmset(struct tty_s + return acm_set_control(acm, acm->ctrlout = newctrl); + } + ++static int get_serial_info(struct acm *acm, struct serial_struct __user *info) ++{ ++ struct serial_struct tmp; ++ ++ if (!info) ++ return -EINVAL; ++ ++ memset(&tmp, 0, sizeof(tmp)); ++ tmp.flags = ASYNC_LOW_LATENCY; ++ tmp.xmit_fifo_size = acm->writesize; ++ tmp.baud_base = le32_to_cpu(acm->line.dwDTERate); ++ ++ if (copy_to_user(info, &tmp, sizeof(tmp))) ++ return -EFAULT; ++ else ++ return 0; ++} ++ + static int acm_tty_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) + { + struct acm *acm = tty->driver_data; ++ int rv = -ENOIOCTLCMD; + + if (!ACM_READY(acm)) + return -EINVAL; + +- return -ENOIOCTLCMD; ++ switch (cmd) { ++ case TIOCGSERIAL: /* gets serial port data */ ++ rv = get_serial_info(acm, (struct serial_struct __user *) arg); ++ break; ++ } ++ ++ return rv; + } + + static const __u32 acm_tty_speed[] = { diff --git a/kernel.spec b/kernel.spec index a0d1a183e..9aff5b508 100644 --- a/kernel.spec +++ b/kernel.spec @@ -653,6 +653,8 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13002: revert-efi-rtclock.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch +Patch14000: cdc-acm-tiocgserial.patch + Patch20000: utrace.patch # Flattened devicetree support @@ -1258,6 +1260,9 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch revert-efi-rtclock.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=787607 +ApplyPatch cdc-acm-tiocgserial.patch + # utrace. ApplyPatch utrace.patch @@ -1950,6 +1955,9 @@ fi # and build. %changelog +* Fri Feb 10 2012 Dave Jones +- Implement TIOCGSERIAL for acm_tty_ioctl (rhbz 787607) + * Thu Feb 09 2012 Dave Jones - bsg: fix sysfs link remove warning (#787862) From 0b719f3d4a60f43f46a5549aa5efb301f260f08f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 10 Feb 2012 14:56:13 -0500 Subject: [PATCH 308/397] Patch to prevent NULL pointer dereference in sd_revalidate_disk (rhbz 754518) --- kernel.spec | 11 +++++++++- ...validate_disk-prevent-NULL-ptr-deref.patch | 22 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch diff --git a/kernel.spec b/kernel.spec index 9aff5b508..e69eae0c1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -701,6 +701,9 @@ Patch21091: bcma-brcmsmac-compat.patch #rhbz 785806 Patch21092: e1000e-Avoid-wrong-check-on-TX-hang.patch +#rhbz 754518 +Patch21093: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch + #rhbz 771058 Patch21100: msi-irq-sysfs-warning.patch @@ -1305,6 +1308,9 @@ ApplyPatch jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch #rhbz 785806 ApplyPatch e1000e-Avoid-wrong-check-on-TX-hang.patch +#rhbz 754518 +ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch + # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch @@ -1955,6 +1961,9 @@ fi # and build. %changelog +* Fri Feb 10 2012 Josh Boyer +- Patch to prevent NULL pointer dereference in sd_revalidate_disk (rhbz 754518) + * Fri Feb 10 2012 Dave Jones - Implement TIOCGSERIAL for acm_tty_ioctl (rhbz 787607) diff --git a/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch b/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch new file mode 100644 index 000000000..492376d78 --- /dev/null +++ b/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -0,0 +1,22 @@ +--- a/drivers/scsi/sd.c ++++ a/drivers/scsi/sd.c +@@ -2362,13 +2362,18 @@ static int sd_try_extended_inquiry(struct scsi_device *sdp) + static int sd_revalidate_disk(struct gendisk *disk) + { + struct scsi_disk *sdkp = scsi_disk(disk); +- struct scsi_device *sdp = sdkp->device; ++ struct scsi_device *sdp; + unsigned char *buffer; + unsigned flush = 0; + + SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, + "sd_revalidate_disk\n")); + ++ if (!sdkp) ++ goto out; ++ ++ sdp = sdkp->device; ++ + /* + * If the device is offline, don't try and read capacity or any + * of the other niceties. From 2d5a4c92f5f96dea2c0e37c9b933798767eb5581 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 13 Feb 2012 15:18:56 -0500 Subject: [PATCH 309/397] Linux 3.2.6 --- block-readahead-block-plug.patch | 92 --------- kernel.spec | 12 +- pci-Rework-ASPM-disable-code.patch | 287 ----------------------------- sources | 2 +- 4 files changed, 5 insertions(+), 388 deletions(-) delete mode 100644 block-readahead-block-plug.patch delete mode 100644 pci-Rework-ASPM-disable-code.patch diff --git a/block-readahead-block-plug.patch b/block-readahead-block-plug.patch deleted file mode 100644 index 0b7bca650..000000000 --- a/block-readahead-block-plug.patch +++ /dev/null @@ -1,92 +0,0 @@ -commit 3deaa7190a8da38453c4fabd9dec7f66d17fff67 -Author: Shaohua Li -Date: Fri Feb 3 15:37:17 2012 -0800 - - readahead: fix pipeline break caused by block plug - - Herbert Poetzl reported a performance regression since 2.6.39. The test - is a simple dd read, but with big block size. The reason is: - - T1: ra (A, A+128k), (A+128k, A+256k) - T2: lock_page for page A, submit the 256k - T3: hit page A+128K, ra (A+256k, A+384). the range isn't submitted - because of plug and there isn't any lock_page till we hit page A+256k - because all pages from A to A+256k is in memory - T4: hit page A+256k, ra (A+384, A+ 512). Because of plug, the range isn't - submitted again. - T5: lock_page A+256k, so (A+256k, A+512k) will be submitted. The task is - waitting for (A+256k, A+512k) finish. - - There is no request to disk in T3 and T4, so readahead pipeline breaks. - - We really don't need block plug for generic_file_aio_read() for buffered - I/O. The readahead already has plug and has fine grained control when I/O - should be submitted. Deleting plug for buffered I/O fixes the regression. - - One side effect is plug makes the request size 256k, the size is 128k - without it. This is because default ra size is 128k and not a reason we - need plug here. - - Vivek said: - - : We submit some readahead IO to device request queue but because of nested - : plug, queue never gets unplugged. When read logic reaches a page which is - : not in page cache, it waits for page to be read from the disk - : (lock_page_killable()) and that time we flush the plug list. - : - : So effectively read ahead logic is kind of broken in parts because of - : nested plugging. Removing top level plug (generic_file_aio_read()) for - : buffered reads, will allow unplugging queue earlier for readahead. - - Signed-off-by: Shaohua Li - Signed-off-by: Wu Fengguang - Reported-by: Herbert Poetzl - Tested-by: Eric Dumazet - Cc: Christoph Hellwig - Cc: Jens Axboe - Cc: Vivek Goyal - Cc: - Signed-off-by: Andrew Morton - Signed-off-by: Linus Torvalds - -diff --git a/mm/filemap.c b/mm/filemap.c -index 97f49ed..b662757 100644 ---- a/mm/filemap.c -+++ b/mm/filemap.c -@@ -1400,15 +1400,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, - unsigned long seg = 0; - size_t count; - loff_t *ppos = &iocb->ki_pos; -- struct blk_plug plug; - - count = 0; - retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE); - if (retval) - return retval; - -- blk_start_plug(&plug); -- - /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ - if (filp->f_flags & O_DIRECT) { - loff_t size; -@@ -1424,8 +1421,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, - retval = filemap_write_and_wait_range(mapping, pos, - pos + iov_length(iov, nr_segs) - 1); - if (!retval) { -+ struct blk_plug plug; -+ -+ blk_start_plug(&plug); - retval = mapping->a_ops->direct_IO(READ, iocb, - iov, pos, nr_segs); -+ blk_finish_plug(&plug); - } - if (retval > 0) { - *ppos = pos + retval; -@@ -1481,7 +1482,6 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, - break; - } - out: -- blk_finish_plug(&plug); - return retval; - } - EXPORT_SYMBOL(generic_file_aio_read); diff --git a/kernel.spec b/kernel.spec index e69eae0c1..fb2455b4c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # Do we have a -stable update to apply? -%define stable_update 3 +%define stable_update 6 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -642,8 +642,6 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch12025: block-readahead-block-plug.patch - Patch12026: bsg-fix-sysfs-link-remove-warning.patch Patch12030: epoll-limit-paths.patch @@ -710,8 +708,6 @@ Patch21100: msi-irq-sysfs-warning.patch # rhbz 754907 Patch21101: hpsa-add-irqf-shared.patch -Patch21225: pci-Rework-ASPM-disable-code.patch - %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1253,7 +1249,6 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch epoll-limit-paths.patch -ApplyPatch block-readahead-block-plug.patch ApplyPatch bsg-fix-sysfs-link-remove-warning.patch @@ -1275,8 +1270,6 @@ ApplyPatch sysfs-msi-irq-per-device.patch # rhbz 754907 ApplyPatch hpsa-add-irqf-shared.patch -ApplyPatch pci-Rework-ASPM-disable-code.patch - #rhbz 717735 ApplyPatch nfs-client-freezer.patch @@ -1961,6 +1954,9 @@ fi # and build. %changelog +* Mon Feb 13 2012 Dave Jones 2.6.42.6-3 +- Linux 3.2.6 + * Fri Feb 10 2012 Josh Boyer - Patch to prevent NULL pointer dereference in sd_revalidate_disk (rhbz 754518) diff --git a/pci-Rework-ASPM-disable-code.patch b/pci-Rework-ASPM-disable-code.patch deleted file mode 100644 index d6fb24320..000000000 --- a/pci-Rework-ASPM-disable-code.patch +++ /dev/null @@ -1,287 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Matthew Garrett -Newsgroups: gmane.linux.acpi.devel,gmane.linux.kernel.pci,gmane.linux.kernel -Subject: [PATCH] pci: Rework ASPM disable code -Date: Thu, 10 Nov 2011 16:38:33 -0500 -Lines: 232 -Approved: news@gmane.org -Message-ID: <1320961113-5050-1-git-send-email-mjg@redhat.com> -NNTP-Posting-Host: lo.gmane.org -X-Trace: dough.gmane.org 1320961145 13112 80.91.229.12 (10 Nov 2011 21:39:05 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Thu, 10 Nov 2011 21:39:05 +0000 (UTC) -Cc: linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, - linux-kernel@vger.kernel.org, Matthew Garrett -To: jbarnes@virtuousgeek.org -Original-X-From: linux-acpi-owner@vger.kernel.org Thu Nov 10 22:38:57 2011 -Return-path: -Envelope-to: glad-acpi-devel@lo.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1ROcKm-0003jN-CL - for glad-acpi-devel@lo.gmane.org; Thu, 10 Nov 2011 22:38:56 +0100 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1751342Ab1KJViu (ORCPT ); - Thu, 10 Nov 2011 16:38:50 -0500 -Original-Received: from mx1.redhat.com ([209.132.183.28]:32030 "EHLO mx1.redhat.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1750805Ab1KJVit (ORCPT ); - Thu, 10 Nov 2011 16:38:49 -0500 -Original-Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id pAALcmdw013333 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Thu, 10 Nov 2011 16:38:49 -0500 -Original-Received: from cavan.codon.org.uk (ovpn-113-157.phx2.redhat.com [10.3.113.157]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id pAALclkW022022 - (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NO); - Thu, 10 Nov 2011 16:38:48 -0500 -Original-Received: from 209-6-41-104.c3-0.smr-ubr1.sbo-smr.ma.cable.rcn.com ([209.6.41.104] helo=localhost.localdomain) - by cavan.codon.org.uk with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) - (Exim 4.72) - (envelope-from ) - id 1ROcKa-0000F4-E4; Thu, 10 Nov 2011 21:38:44 +0000 -X-SA-Do-Not-Run: Yes -X-SA-Exim-Connect-IP: 209.6.41.104 -X-SA-Exim-Mail-From: mjg@redhat.com -X-SA-Exim-Scanned: No (on cavan.codon.org.uk); SAEximRunCond expanded to false -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Original-Sender: linux-acpi-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-acpi@vger.kernel.org -Xref: news.gmane.org gmane.linux.acpi.devel:51182 gmane.linux.kernel.pci:12503 gmane.linux.kernel:1214427 -Archived-At: - -Right now we forcibly clear ASPM state on all devices if the BIOS indicates -that the feature isn't supported. Based on the Microsoft presentation -"PCI Express In Depth for Windows Vista and Beyond", I'm starting to think -that this may be an error. The implication is that unless the platform -grants full control via _OSC, Windows will not touch any PCIe features - -including ASPM. In that case clearing ASPM state would be an error unless -the platform has granted us that control. - -This patch reworks the ASPM disabling code such that the actual clearing -of state is triggered by a successful handoff of PCIe control to the OS. -The general ASPM code undergoes some changes in order to ensure that the -ability to clear the bits isn't overridden by ASPM having already been -disabled. Further, this theoretically now allows for situations where -only a subset of PCIe roots hand over control, leaving the others in the -BIOS state. - -It's difficult to know for sure that this is the right thing to do - -there's zero public documentation on the interaction between all of these -components. But enough vendors enable ASPM on platforms and then set this -bit that it seems likely that they're expecting the OS to leave them alone. - -Measured to save around 5W on an idle Thinkpad X220. - -Signed-off-by: Matthew Garrett ---- - drivers/acpi/pci_root.c | 7 +++++ - drivers/pci/pci-acpi.c | 1 - - drivers/pci/pcie/aspm.c | 58 +++++++++++++++++++++++++++++---------------- - include/linux/pci-aspm.h | 4 +- - 4 files changed, 46 insertions(+), 24 deletions(-) - -diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c -index 2672c79..7aff631 100644 ---- a/drivers/acpi/pci_root.c -+++ b/drivers/acpi/pci_root.c -@@ -596,6 +596,13 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) - if (ACPI_SUCCESS(status)) { - dev_info(root->bus->bridge, - "ACPI _OSC control (0x%02x) granted\n", flags); -+ if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { -+ /* -+ * We have ASPM control, but the FADT indicates -+ * that it's unsupported. Clear it. -+ */ -+ pcie_clear_aspm(root->bus); -+ } - } else { - dev_info(root->bus->bridge, - "ACPI _OSC request failed (%s), " -diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c -index 4ecb640..c8e7585 100644 ---- a/drivers/pci/pci-acpi.c -+++ b/drivers/pci/pci-acpi.c -@@ -395,7 +395,6 @@ static int __init acpi_pci_init(void) - - if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { - printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n"); -- pcie_clear_aspm(); - pcie_no_aspm(); - } - -diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c -index cbfbab1..1cfbf22 100644 ---- a/drivers/pci/pcie/aspm.c -+++ b/drivers/pci/pcie/aspm.c -@@ -68,7 +68,7 @@ struct pcie_link_state { - struct aspm_latency acceptable[8]; - }; - --static int aspm_disabled, aspm_force, aspm_clear_state; -+static int aspm_disabled, aspm_force; - static bool aspm_support_enabled = true; - static DEFINE_MUTEX(aspm_lock); - static LIST_HEAD(link_list); -@@ -500,9 +500,6 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) - int pos; - u32 reg32; - -- if (aspm_clear_state) -- return -EINVAL; -- - /* - * Some functions in a slot might not all be PCIe functions, - * very strange. Disable ASPM for the whole slot -@@ -574,9 +571,6 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) - pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) - return; - -- if (aspm_disabled && !aspm_clear_state) -- return; -- - /* VIA has a strange chipset, root port is under a bridge */ - if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT && - pdev->bus->self) -@@ -608,7 +602,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 || aspm_clear_state) { -+ if (aspm_policy != POLICY_POWERSAVE) { - pcie_config_aspm_path(link); - pcie_set_clkpm(link, policy_to_clkpm_state(link)); - } -@@ -649,8 +643,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) - struct pci_dev *parent = pdev->bus->self; - struct pcie_link_state *link, *root, *parent_link; - -- if ((aspm_disabled && !aspm_clear_state) || !pci_is_pcie(pdev) || -- !parent || !parent->link_state) -+ if (!pci_is_pcie(pdev) || !parent || !parent->link_state) - return; - if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && - (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) -@@ -734,13 +727,18 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev) - * pci_disable_link_state - disable pci device's link state, so the link will - * never enter specific states - */ --static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) -+static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem, -+ bool force) - { - struct pci_dev *parent = pdev->bus->self; - struct pcie_link_state *link; - -- if (aspm_disabled || !pci_is_pcie(pdev)) -+ if (aspm_disabled && !force) -+ return; -+ -+ if (!pci_is_pcie(pdev)) - return; -+ - if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT || - pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) - parent = pdev; -@@ -768,16 +766,31 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) - - void pci_disable_link_state_locked(struct pci_dev *pdev, int state) - { -- __pci_disable_link_state(pdev, state, false); -+ __pci_disable_link_state(pdev, state, false, false); - } - EXPORT_SYMBOL(pci_disable_link_state_locked); - - void pci_disable_link_state(struct pci_dev *pdev, int state) - { -- __pci_disable_link_state(pdev, state, true); -+ __pci_disable_link_state(pdev, state, true, false); - } - EXPORT_SYMBOL(pci_disable_link_state); - -+void pcie_clear_aspm(struct pci_bus *bus) -+{ -+ struct pci_dev *child; -+ -+ /* -+ * Clear any ASPM setup that the firmware has carried out on this bus -+ */ -+ list_for_each_entry(child, &bus->devices, bus_list) { -+ __pci_disable_link_state(child, PCIE_LINK_STATE_L0S | -+ PCIE_LINK_STATE_L1 | -+ PCIE_LINK_STATE_CLKPM, -+ false, true); -+ } -+} -+ - static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp) - { - int i; -@@ -935,6 +948,7 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) - static int __init pcie_aspm_disable(char *str) - { - if (!strcmp(str, "off")) { -+ aspm_policy = POLICY_DEFAULT; - aspm_disabled = 1; - aspm_support_enabled = false; - printk(KERN_INFO "PCIe ASPM is disabled\n"); -@@ -947,16 +961,18 @@ static int __init pcie_aspm_disable(char *str) - - __setup("pcie_aspm=", pcie_aspm_disable); - --void pcie_clear_aspm(void) --{ -- if (!aspm_force) -- aspm_clear_state = 1; --} -- - void pcie_no_aspm(void) - { -- if (!aspm_force) -+ /* -+ * Disabling ASPM is intended to prevent the kernel from modifying -+ * existing hardware state, not to clear existing state. To that end: -+ * (a) set policy to POLICY_DEFAULT in order to avoid changing state -+ * (b) prevent userspace from changing policy -+ */ -+ if (!aspm_force) { -+ aspm_policy = POLICY_DEFAULT; - aspm_disabled = 1; -+ } - } - - /** -diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h -index 7cea7b6..c832014 100644 ---- a/include/linux/pci-aspm.h -+++ b/include/linux/pci-aspm.h -@@ -29,7 +29,7 @@ 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 pci_disable_link_state_locked(struct pci_dev *pdev, int state); --extern void pcie_clear_aspm(void); -+extern void pcie_clear_aspm(struct pci_bus *bus); - extern void pcie_no_aspm(void); - #else - static inline void pcie_aspm_init_link_state(struct pci_dev *pdev) -@@ -47,7 +47,7 @@ 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) - { - } --static inline void pcie_clear_aspm(void) -+static inline void pcie_clear_aspm(struct pci_bus *bus) - { - } - static inline void pcie_no_aspm(void) --- -1.7.7.1 - --- -To unsubscribe from this list: send the line "unsubscribe linux-acpi" 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/sources b/sources index c395e0ba0..9fdef1f29 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz -4ffcd30b95b4d2435be40405507319dd patch-3.2.3.xz +0aea8fc5e705c5b1ef68697de9379cef patch-3.2.6.xz From 3ee3622a6749e705ba92e536ded7919b2e8a9bc4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 15 Feb 2012 19:08:53 -0500 Subject: [PATCH 310/397] Require newer linux-firmware for updated bnx2/bnx2x drivers --- kernel.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index fb2455b4c..a6637ddb0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -448,7 +448,7 @@ Requires(pre): %{initrd_prereq}\ %if %{with_firmware}\ Requires(pre): kernel-firmware >= %{rpmversion}-%{pkg_release}\ %else\ -Requires(pre): linux-firmware >= 20100806-2\ +Requires(pre): linux-firmware >= 20120206-0.1.git06c8f81\ %endif\ Requires(post): /sbin/new-kernel-pkg\ Requires(preun): /sbin/new-kernel-pkg\ @@ -1954,6 +1954,9 @@ fi # and build. %changelog +* Wed Feb 15 2012 Josh Boyer +- Require newer linux-firmware for updated bnx2/bnx2x drivers + * Mon Feb 13 2012 Dave Jones 2.6.42.6-3 - Linux 3.2.6 From 90bc499fe8309e814bba1bbeceef7573a28892a3 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 17 Feb 2012 10:22:19 -0500 Subject: [PATCH 311/397] Freeze all filesystems during system suspend/hibernate. --- hibernate-freeze-filesystems.patch | 257 +++++++++++++++++++++++++++++ kernel.spec | 7 + 2 files changed, 264 insertions(+) create mode 100644 hibernate-freeze-filesystems.patch diff --git a/hibernate-freeze-filesystems.patch b/hibernate-freeze-filesystems.patch new file mode 100644 index 000000000..dfb2f0478 --- /dev/null +++ b/hibernate-freeze-filesystems.patch @@ -0,0 +1,257 @@ +From: Rafael J. Wysocki + +Freeze all filesystems during system suspend and (kernel-driven) +hibernation by calling freeze_supers() for all superblocks and thaw +them during the subsequent resume with the help of thaw_supers(). + +This makes filesystems stay in a consistent state in case something +goes wrong between system suspend (or hibernation) and the subsequent +resume (e.g. journal replays won't be necessary in those cases). In +particular, this should help to solve a long-standing issue that, in +some cases, during resume from hibernation the boot loader causes the +journal to be replied for the filesystem containing the kernel image +and/or initrd causing it to become inconsistent with the information +stored in the hibernation image. + +The user-space-driven hibernation (s2disk) is not covered by this +change, because the freezing of filesystems prevents s2disk from +accessing device special files it needs to do its job. + +This change is based on earlier work by Nigel Cunningham. + +Signed-off-by: Rafael J. Wysocki +--- + fs/super.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/fs.h | 3 + + kernel/power/hibernate.c | 11 +++++-- + kernel/power/power.h | 23 -------------- + kernel/power/suspend.c | 42 +++++++++++++++++++++++++++ + 5 files changed, 128 insertions(+), 24 deletions(-) + +Index: linux/include/linux/fs.h +=================================================================== +--- linux.orig/include/linux/fs.h ++++ linux/include/linux/fs.h +@@ -210,6 +210,7 @@ struct inodes_stat_t { + #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */ + #define MS_I_VERSION (1<<23) /* Update inode I_version field */ + #define MS_STRICTATIME (1<<24) /* Always perform atime updates */ ++#define MS_FROZEN (1<<25) /* Frozen filesystem */ + #define MS_NOSEC (1<<28) + #define MS_BORN (1<<29) + #define MS_ACTIVE (1<<30) +@@ -2501,6 +2502,8 @@ extern void drop_super(struct super_bloc + extern void iterate_supers(void (*)(struct super_block *, void *), void *); + extern void iterate_supers_type(struct file_system_type *, + void (*)(struct super_block *, void *), void *); ++extern int freeze_supers(void); ++extern void thaw_supers(void); + + extern int dcache_dir_open(struct inode *, struct file *); + extern int dcache_dir_close(struct inode *, struct file *); +Index: linux/fs/super.c +=================================================================== +--- linux.orig/fs/super.c ++++ linux/fs/super.c +@@ -594,6 +594,79 @@ void iterate_supers_type(struct file_sys + EXPORT_SYMBOL(iterate_supers_type); + + /** ++ * thaw_supers - call thaw_super() for all superblocks ++ */ ++void thaw_supers(void) ++{ ++ struct super_block *sb, *p = NULL; ++ ++ spin_lock(&sb_lock); ++ list_for_each_entry(sb, &super_blocks, s_list) { ++ if (list_empty(&sb->s_instances)) ++ continue; ++ sb->s_count++; ++ spin_unlock(&sb_lock); ++ ++ if (sb->s_flags & MS_FROZEN) { ++ thaw_super(sb); ++ sb->s_flags &= ~MS_FROZEN; ++ } ++ ++ spin_lock(&sb_lock); ++ if (p) ++ __put_super(p); ++ p = sb; ++ } ++ if (p) ++ __put_super(p); ++ spin_unlock(&sb_lock); ++} ++ ++/** ++ * freeze_supers - call freeze_super() for all superblocks ++ */ ++int freeze_supers(void) ++{ ++ struct super_block *sb, *p = NULL; ++ int error = 0; ++ ++ spin_lock(&sb_lock); ++ /* ++ * Freeze in reverse order so filesystems depending on others are ++ * frozen in the right order (eg. loopback on ext3). ++ */ ++ list_for_each_entry_reverse(sb, &super_blocks, s_list) { ++ if (list_empty(&sb->s_instances)) ++ continue; ++ sb->s_count++; ++ spin_unlock(&sb_lock); ++ ++ if (sb->s_root && sb->s_frozen != SB_FREEZE_TRANS ++ && !(sb->s_flags & MS_RDONLY)) { ++ error = freeze_super(sb); ++ if (!error) ++ sb->s_flags |= MS_FROZEN; ++ } ++ ++ spin_lock(&sb_lock); ++ if (error) ++ break; ++ if (p) ++ __put_super(p); ++ p = sb; ++ } ++ if (p) ++ __put_super(p); ++ spin_unlock(&sb_lock); ++ ++ if (error) ++ thaw_supers(); ++ ++ return error; ++} ++ ++ ++/** + * get_super - get the superblock of a device + * @bdev: device to get the superblock for + * +Index: linux/kernel/power/power.h +=================================================================== +--- linux.orig/kernel/power/power.h ++++ linux/kernel/power/power.h +@@ -1,3 +1,4 @@ ++#include + #include + #include + #include +@@ -227,25 +228,3 @@ enum { + #define TEST_MAX (__TEST_AFTER_LAST - 1) + + extern int pm_test_level; +- +-#ifdef CONFIG_SUSPEND_FREEZER +-static inline int suspend_freeze_processes(void) +-{ +- int error = freeze_processes(); +- return error ? : freeze_kernel_threads(); +-} +- +-static inline void suspend_thaw_processes(void) +-{ +- thaw_processes(); +-} +-#else +-static inline int suspend_freeze_processes(void) +-{ +- return 0; +-} +- +-static inline void suspend_thaw_processes(void) +-{ +-} +-#endif +Index: linux/kernel/power/suspend.c +=================================================================== +--- linux.orig/kernel/power/suspend.c ++++ linux/kernel/power/suspend.c +@@ -29,6 +29,48 @@ + + #include "power.h" + ++#ifdef CONFIG_SUSPEND_FREEZER ++ ++static inline int suspend_freeze_processes(void) ++{ ++ int error; ++ ++ error = freeze_processes(); ++ if (error) ++ return error; ++ ++ error = freeze_supers(); ++ if (error) { ++ thaw_processes(); ++ return error; ++ } ++ ++ error = freeze_kernel_threads(); ++ if (error) ++ thaw_supers(); ++ ++ return error; ++} ++ ++static inline void suspend_thaw_processes(void) ++{ ++ thaw_supers(); ++ thaw_processes(); ++} ++ ++#else /* !CONFIG_SUSPEND_FREEZER */ ++ ++static inline int suspend_freeze_processes(void) ++{ ++ return 0; ++} ++ ++static inline void suspend_thaw_processes(void) ++{ ++} ++ ++#endif /* !CONFIG_SUSPEND_FREEZER */ ++ + const char *const pm_states[PM_SUSPEND_MAX] = { + [PM_SUSPEND_STANDBY] = "standby", + [PM_SUSPEND_MEM] = "mem", +Index: linux/kernel/power/hibernate.c +=================================================================== +--- linux.orig/kernel/power/hibernate.c ++++ linux/kernel/power/hibernate.c +@@ -626,12 +626,17 @@ int hibernate(void) + if (error) + goto Finish; + +- error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); ++ error = freeze_supers(); + if (error) + goto Thaw; ++ ++ error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); ++ if (error) ++ goto Thaw_fs; ++ + if (freezer_test_done) { + freezer_test_done = false; +- goto Thaw; ++ goto Thaw_fs; + } + + if (in_suspend) { +@@ -655,6 +660,8 @@ int hibernate(void) + pr_debug("PM: Image restored successfully.\n"); + } + ++ Thaw_fs: ++ thaw_supers(); + Thaw: + thaw_processes(); + Finish: + diff --git a/kernel.spec b/kernel.spec index a6637ddb0..f3656e26b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -653,6 +653,8 @@ Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch14000: cdc-acm-tiocgserial.patch +Patch15000: hibernate-freeze-filesystems.patch + Patch20000: utrace.patch # Flattened devicetree support @@ -1261,6 +1263,8 @@ ApplyPatch efi-dont-map-boot-services-on-32bit.patch # https://bugzilla.redhat.com/show_bug.cgi?id=787607 ApplyPatch cdc-acm-tiocgserial.patch +ApplyPatch hibernate-freeze-filesystems.patch + # utrace. ApplyPatch utrace.patch @@ -1954,6 +1958,9 @@ fi # and build. %changelog +* Thu Feb 16 2012 Dave Jones +- Freeze all filesystems during system suspend/hibernate. + * Wed Feb 15 2012 Josh Boyer - Require newer linux-firmware for updated bnx2/bnx2x drivers From 8559739b7bc8a274517779bb4d0b1a23b8b7f578 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 17 Feb 2012 14:56:06 -0500 Subject: [PATCH 312/397] Reenable radio drivers. (rhbz 784824) --- config-generic | 15 ++++++++++++++- kernel.spec | 3 +++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 56ad06735..72d4bd172 100644 --- a/config-generic +++ b/config-generic @@ -4174,7 +4174,20 @@ CONFIG_NE2000=m # CONFIG_SERIAL_8250_HUB6 is not set # CONFIG_SERIAL_8250_EXAR_ST16C554 is not set -# CONFIG_RADIO_ADAPTERS is not set +CONFIG_RADIO_ADAPTERS=y +CONFIG_RADIO_TEA5764=m +CONFIG_RADIO_SAA7706H=m +CONFIG_RADIO_CADET=m +CONFIG_RADIO_RTRACK=m +CONFIG_RADIO_RTRACK2=m +CONFIG_RADIO_AZTECH=m +CONFIG_RADIO_GEMTEK=m +CONFIG_RADIO_SF16FMI=m +CONFIG_RADIO_SF16FMR2=m +CONFIG_RADIO_TERRATEC=m +CONFIG_RADIO_TRUST=m +CONFIG_RADIO_TYPHOON=m +CONFIG_RADIO_ZOLTRIX=m # CONFIG_SND_OPL4_LIB is not set # CONFIG_SND_AD1816A is not set diff --git a/kernel.spec b/kernel.spec index f3656e26b..050965d92 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1958,6 +1958,9 @@ fi # and build. %changelog +* Fri Feb 17 2012 Dave Jones +- Reenable radio drivers. (rhbz 784824) + * Thu Feb 16 2012 Dave Jones - Freeze all filesystems during system suspend/hibernate. From 7052360844a4e89967532b77ed37dd54dc83db86 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 17 Feb 2012 16:02:56 -0500 Subject: [PATCH 313/397] improve handling of null rate in LIS3LV02Dx accelerometer driver. (rhbz 785814) --- kernel.spec | 7 +++ lis3-improve-handling-of-null-rate.patch | 79 ++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 lis3-improve-handling-of-null-rate.patch diff --git a/kernel.spec b/kernel.spec index 050965d92..32a1fe337 100644 --- a/kernel.spec +++ b/kernel.spec @@ -655,6 +655,8 @@ Patch14000: cdc-acm-tiocgserial.patch Patch15000: hibernate-freeze-filesystems.patch +Patch15010: lis3-improve-handling-of-null-rate.patch + Patch20000: utrace.patch # Flattened devicetree support @@ -1265,6 +1267,8 @@ ApplyPatch cdc-acm-tiocgserial.patch ApplyPatch hibernate-freeze-filesystems.patch +ApplyPatch lis3-improve-handling-of-null-rate.patch + # utrace. ApplyPatch utrace.patch @@ -1958,6 +1962,9 @@ fi # and build. %changelog +* Fri Feb 17 2012 Dave Jones +- improve handling of null rate in LIS3LV02Dx accelerometer driver. (rhbz 785814) + * Fri Feb 17 2012 Dave Jones - Reenable radio drivers. (rhbz 784824) diff --git a/lis3-improve-handling-of-null-rate.patch b/lis3-improve-handling-of-null-rate.patch new file mode 100644 index 000000000..98512564a --- /dev/null +++ b/lis3-improve-handling-of-null-rate.patch @@ -0,0 +1,79 @@ +>From 56fb161a9ca0129f8e266e4dbe79346552ff8089 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=89ric=20Piel?= +Date: Thu, 3 Nov 2011 16:22:40 +0100 +Subject: [PATCH] lis3: Improve handling of null rate +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When obtaining a rate of 0, we would disable the device supposely +because it seems to behave incorectly. It actually only comes from the +fact that the device is off and on lis3dc it's reflected in the rate. +So handle this nicely by just waiting a safe time, and then using the +device as normally. + +Signed-off-by: ??ric Piel +--- + drivers/misc/lis3lv02d/lis3lv02d.c | 16 ++++++++-------- + 1 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c +index 35c67e0..42dce2a 100644 +--- a/drivers/misc/lis3lv02d/lis3lv02d.c ++++ b/drivers/misc/lis3lv02d/lis3lv02d.c +@@ -188,7 +188,8 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z) + /* conversion btw sampling rate and the register values */ + static int lis3_12_rates[4] = {40, 160, 640, 2560}; + static int lis3_8_rates[2] = {100, 400}; +-static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000}; ++/* LIS3DC: 0 = power off, above 9 = undefined */ ++static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000, -1, -1, -1, -1, -1, -1}; + + /* ODR is Output Data Rate */ + static int lis3lv02d_get_odr(struct lis3lv02d *lis3) +@@ -202,12 +203,11 @@ static int lis3lv02d_get_odr(struct lis3lv02d *lis3) + return lis3->odrs[(ctrl >> shift)]; + } + +-static int lis3lv02d_get_pwron_wait(struct lis3lv02d *lis3) ++static int lis3lv02d_wait_pwron(struct lis3lv02d *lis3) + { + int div = lis3lv02d_get_odr(lis3); +- +- if (WARN_ONCE(div == 0, "device returned spurious data")) +- return -ENXIO; ++ if (div <= 0) ++ div = 1; /* maximum delay */ + + /* LIS3 power on delay is quite long */ + msleep(lis3->pwron_delay / div); +@@ -274,7 +274,7 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) + + lis3->read(lis3, ctlreg, ®); + lis3->write(lis3, ctlreg, (reg | selftest)); +- ret = lis3lv02d_get_pwron_wait(lis3); ++ ret = lis3lv02d_wait_pwron(lis3); + if (ret) + goto fail; + +@@ -285,7 +285,7 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) + + /* back to normal settings */ + lis3->write(lis3, ctlreg, reg); +- ret = lis3lv02d_get_pwron_wait(lis3); ++ ret = lis3lv02d_wait_pwron(lis3); + if (ret) + goto fail; + +@@ -397,7 +397,7 @@ int lis3lv02d_poweron(struct lis3lv02d *lis3) + lis3->write(lis3, CTRL_REG2, reg); + } + +- err = lis3lv02d_get_pwron_wait(lis3); ++ err = lis3lv02d_wait_pwron(lis3); + if (err) + return err; + +-- +1.7.7.1 + From 14843a4634c1a27ff8f641e714e99694134c0e13 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 20 Feb 2012 13:23:52 -0500 Subject: [PATCH 314/397] NFSv4: Fix an Oops in the NFSv4 getacl code --- kernel.spec | 11 ++++- nfs-oops-getacl.patch | 96 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 nfs-oops-getacl.patch diff --git a/kernel.spec b/kernel.spec index 32a1fe337..3080d1a99 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 6 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -669,8 +669,10 @@ Patch21004: arm-tegra-nvec-kconfig.patch #rhbz 717735 Patch21045: nfs-client-freezer.patch +Patch21046: nfs-oops-getacl.patch + #rhbz 590880 -Patch21046: alps.patch +Patch21050: alps.patch Patch21070: ext4-Support-check-none-nocheck-mount-options.patch Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch @@ -1281,6 +1283,8 @@ ApplyPatch hpsa-add-irqf-shared.patch #rhbz 717735 ApplyPatch nfs-client-freezer.patch +ApplyPatch nfs-oops-getacl.patch + #rhbz 590880 ApplyPatch alps.patch @@ -1962,6 +1966,9 @@ fi # and build. %changelog +* Mon Feb 20 2012 Dave Jones +- NFSv4: Fix an Oops in the NFSv4 getacl code + * Fri Feb 17 2012 Dave Jones - improve handling of null rate in LIS3LV02Dx accelerometer driver. (rhbz 785814) diff --git a/nfs-oops-getacl.patch b/nfs-oops-getacl.patch new file mode 100644 index 000000000..53e599dd4 --- /dev/null +++ b/nfs-oops-getacl.patch @@ -0,0 +1,96 @@ +From 331818f1c468a24e581aedcbe52af799366a9dfe Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Fri, 3 Feb 2012 18:30:53 -0500 +Subject: [PATCH] NFSv4: Fix an Oops in the NFSv4 getacl code + +Commit bf118a342f10dafe44b14451a1392c3254629a1f (NFSv4: include bitmap +in nfsv4 get acl data) introduces the 'acl_scratch' page for the case +where we may need to decode multi-page data. However it fails to take +into account the fact that the variable may be NULL (for the case where +we're not doing multi-page decode), and it also attaches it to the +encoding xdr_stream rather than the decoding one. + +The immediate result is an Oops in nfs4_xdr_enc_getacl due to the +call to page_address() with a NULL page pointer. + +Signed-off-by: Trond Myklebust +Cc: Andy Adamson +Cc: stable@vger.kernel.org +--- + fs/nfs/nfs4proc.c | 8 ++++---- + fs/nfs/nfs4xdr.c | 5 ++++- + include/linux/nfs_xdr.h | 2 +- + 3 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index f0c849c..d202e04 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -3575,8 +3575,8 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu + } + if (npages > 1) { + /* for decoding across pages */ +- args.acl_scratch = alloc_page(GFP_KERNEL); +- if (!args.acl_scratch) ++ res.acl_scratch = alloc_page(GFP_KERNEL); ++ if (!res.acl_scratch) + goto out_free; + } + args.acl_len = npages * PAGE_SIZE; +@@ -3612,8 +3612,8 @@ out_free: + for (i = 0; i < npages; i++) + if (pages[i]) + __free_page(pages[i]); +- if (args.acl_scratch) +- __free_page(args.acl_scratch); ++ if (res.acl_scratch) ++ __free_page(res.acl_scratch); + return ret; + } + +diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c +index 95e92e4..33bd8d0 100644 +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -2522,7 +2522,6 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, + + xdr_inline_pages(&req->rq_rcv_buf, replen << 2, + args->acl_pages, args->acl_pgbase, args->acl_len); +- xdr_set_scratch_buffer(xdr, page_address(args->acl_scratch), PAGE_SIZE); + + encode_nops(&hdr); + } +@@ -6032,6 +6031,10 @@ nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr, + struct compound_hdr hdr; + int status; + ++ if (res->acl_scratch != NULL) { ++ void *p = page_address(res->acl_scratch); ++ xdr_set_scratch_buffer(xdr, p, PAGE_SIZE); ++ } + status = decode_compound_hdr(xdr, &hdr); + if (status) + goto out; +diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h +index a764cef..d6ba9a1 100644 +--- a/include/linux/nfs_xdr.h ++++ b/include/linux/nfs_xdr.h +@@ -614,7 +614,6 @@ struct nfs_getaclargs { + size_t acl_len; + unsigned int acl_pgbase; + struct page ** acl_pages; +- struct page * acl_scratch; + struct nfs4_sequence_args seq_args; + }; + +@@ -624,6 +623,7 @@ struct nfs_getaclres { + size_t acl_len; + size_t acl_data_offset; + int acl_flags; ++ struct page * acl_scratch; + struct nfs4_sequence_res seq_res; + }; + +-- +1.7.4.1 + From 361557c29fb09159c2aa64769a2786949c388a82 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 20 Feb 2012 18:25:11 -0500 Subject: [PATCH 315/397] Linux 3.2.7 --- kernel.spec | 7 +++++-- sources | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 3080d1a99..487ac285e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 6 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 # Set rpm version accordingly @@ -1966,6 +1966,9 @@ fi # and build. %changelog +* Mon Feb 20 2012 Dave Jones +- Linux 3.2.7 + * Mon Feb 20 2012 Dave Jones - NFSv4: Fix an Oops in the NFSv4 getacl code diff --git a/sources b/sources index 9fdef1f29..a9fa76d85 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz 0aea8fc5e705c5b1ef68697de9379cef patch-3.2.6.xz +e507fce2c266549df9565172196c912d patch-3.2.7.xz From 15ac9dc02a19277368ce11d06ffb6cae6cf8c213 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 20 Feb 2012 18:25:33 -0500 Subject: [PATCH 316/397] remove old patch --- sources | 1 - 1 file changed, 1 deletion(-) diff --git a/sources b/sources index a9fa76d85..8a47cc81a 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz -0aea8fc5e705c5b1ef68697de9379cef patch-3.2.6.xz e507fce2c266549df9565172196c912d patch-3.2.7.xz From a36c81d3a6fe84eeb8ea2cf8db915616b7a8bcef Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 20 Feb 2012 20:05:10 -0500 Subject: [PATCH 317/397] Do not call drivers when invalidating partitions for -ENOMEDIUM --- kernel.spec | 9 +- scsi-fix-sd_revalidate_disk-oops.patch | 116 +++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 scsi-fix-sd_revalidate_disk-oops.patch diff --git a/kernel.spec b/kernel.spec index 487ac285e..06398038d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -706,7 +706,8 @@ Patch21091: bcma-brcmsmac-compat.patch Patch21092: e1000e-Avoid-wrong-check-on-TX-hang.patch #rhbz 754518 -Patch21093: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch +#Patch21093: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch +Patch21093: scsi-fix-sd_revalidate_disk-oops.patch #rhbz 771058 Patch21100: msi-irq-sysfs-warning.patch @@ -1314,7 +1315,8 @@ ApplyPatch jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch ApplyPatch e1000e-Avoid-wrong-check-on-TX-hang.patch #rhbz 754518 -ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch +#ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch +ApplyPatch scsi-fix-sd_revalidate_disk-oops.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch @@ -1966,6 +1968,9 @@ fi # and build. %changelog +* Mon Feb 20 2012 Dave Jones 2.6.42.7-1 +- Do not call drivers when invalidating partitions for -ENOMEDIUM + * Mon Feb 20 2012 Dave Jones - Linux 3.2.7 diff --git a/scsi-fix-sd_revalidate_disk-oops.patch b/scsi-fix-sd_revalidate_disk-oops.patch new file mode 100644 index 000000000..defa240a2 --- /dev/null +++ b/scsi-fix-sd_revalidate_disk-oops.patch @@ -0,0 +1,116 @@ +--- linux-2.6.42.noarch/fs/partitions/check.c~ 2012-02-20 18:32:55.314253719 -0500 ++++ linux-2.6.42.noarch/fs/partitions/check.c 2012-02-20 18:34:46.509859745 -0500 +@@ -539,17 +539,11 @@ static bool disk_unlock_native_capacity( + } + } + +-int rescan_partitions(struct gendisk *disk, struct block_device *bdev) ++static int drop_partitions(struct gendisk *disk, struct block_device *bdev) + { +- struct parsed_partitions *state = NULL; + struct disk_part_iter piter; + struct hd_struct *part; +- int p, highest, res; +-rescan: +- if (state && !IS_ERR(state)) { +- kfree(state); +- state = NULL; +- } ++ int res; + + if (bdev->bd_part_count) + return -EBUSY; +@@ -562,6 +556,24 @@ rescan: + delete_partition(disk, part->partno); + disk_part_iter_exit(&piter); + ++ return 0; ++} ++ ++int rescan_partitions(struct gendisk *disk, struct block_device *bdev) ++{ ++ struct parsed_partitions *state = NULL; ++ struct hd_struct *part; ++ int p, highest, res; ++rescan: ++ if (state && !IS_ERR(state)) { ++ kfree(state); ++ state = NULL; ++ } ++ ++ res = drop_partitions(disk, bdev); ++ if (res) ++ return res; ++ + if (disk->fops->revalidate_disk) + disk->fops->revalidate_disk(disk); + check_disk_size_change(disk, bdev); +@@ -665,6 +677,26 @@ rescan: + return 0; + } + ++int invalidate_partitions(struct gendisk *disk, struct block_device *bdev) ++{ ++ int res; ++ ++ if (!bdev->bd_invalidated) ++ return 0; ++ ++ res = drop_partitions(disk, bdev); ++ if (res) ++ return res; ++ ++ set_capacity(disk, 0); ++ check_disk_size_change(disk, bdev); ++ bdev->bd_invalidated = 0; ++ /* tell userspace that the media / partition table may have changed */ ++ kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE); ++ ++ return 0; ++} ++ + unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p) + { + struct address_space *mapping = bdev->bd_inode->i_mapping; +--- linux-2.6.42.noarch/include/linux/genhd.h~ 2012-02-20 18:35:02.777802107 -0500 ++++ linux-2.6.42.noarch/include/linux/genhd.h 2012-02-20 18:35:13.873762792 -0500 +@@ -596,6 +596,7 @@ extern char *disk_name (struct gendisk * + + extern int disk_expand_part_tbl(struct gendisk *disk, int target); + extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); ++extern int invalidate_partitions(struct gendisk *disk, struct block_device *bdev); + extern struct hd_struct * __must_check add_partition(struct gendisk *disk, + int partno, sector_t start, + sector_t len, int flags, +--- linux-2.6.42.noarch/fs/block_dev.c~ 2012-02-20 18:35:24.890723757 -0500 ++++ linux-2.6.42.noarch/fs/block_dev.c 2012-02-20 18:36:25.166510197 -0500 +@@ -1159,8 +1159,12 @@ static int __blkdev_get(struct block_dev + * The latter is necessary to prevent ghost + * partitions on a removed medium. + */ +- if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM)) +- rescan_partitions(disk, bdev); ++ if (bdev->bd_invalidated) { ++ if (!ret) ++ rescan_partitions(disk, bdev); ++ else if (ret == -ENOMEDIUM) ++ invalidate_partitions(disk, bdev); ++ } + if (ret) + goto out_clear; + } else { +@@ -1190,8 +1194,12 @@ static int __blkdev_get(struct block_dev + if (bdev->bd_disk->fops->open) + ret = bdev->bd_disk->fops->open(bdev, mode); + /* the same as first opener case, read comment there */ +- if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM)) +- rescan_partitions(bdev->bd_disk, bdev); ++ if (bdev->bd_invalidated) { ++ if (!ret) ++ rescan_partitions(bdev->bd_disk, bdev); ++ else if (ret == -ENOMEDIUM) ++ invalidate_partitions(bdev->bd_disk, bdev); ++ } + if (ret) + goto out_unlock_bdev; + } From 853703eece486868981717916452f880e55556ee Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 27 Feb 2012 13:57:05 -0500 Subject: [PATCH 318/397] Add patch to fix regression in FADT revision checks (rhbz 730007 727865) --- ...x-regression-in-FADT-revision-checks.patch | 58 +++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 ACPICA-Fix-regression-in-FADT-revision-checks.patch diff --git a/ACPICA-Fix-regression-in-FADT-revision-checks.patch b/ACPICA-Fix-regression-in-FADT-revision-checks.patch new file mode 100644 index 000000000..d6b590389 --- /dev/null +++ b/ACPICA-Fix-regression-in-FADT-revision-checks.patch @@ -0,0 +1,58 @@ + commit 64b3db22c04586997ab4be46dd5a5b99f8a2d390 (2.6.39), +"Remove use of unreliable FADT revision field" causes regression +for old P4 systems because now cst_control and other fields are +not reset to 0. + + The effect is that acpi_processor_power_init will notice +cst_control != 0 and a write to CST_CNT register is performed +that should not happen. As result, the system oopses after the +"No _CST, giving up" message, sometimes in acpi_ns_internalize_name, +sometimes in acpi_ns_get_type, usually at random places. May be +during migration to CPU 1 in acpi_processor_get_throttling. + + Every one of these settings help to avoid this problem: + - acpi=off + - processor.nocst=1 + - maxcpus=1 + + The fix is to update acpi_gbl_FADT.header.length after +the original value is used to check for old revisions. + +Signed-off-by: Julian Anastasov +--- + drivers/acpi/acpica/tbfadt.c | 8 ++++---- + 1 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c +index c5d8704..4c9c760 100644 +--- a/drivers/acpi/acpica/tbfadt.c ++++ b/drivers/acpi/acpica/tbfadt.c +@@ -363,10 +363,6 @@ static void acpi_tb_convert_fadt(void) + u32 address32; + u32 i; + +- /* Update the local FADT table header length */ +- +- acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); +- + /* + * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary. + * Later code will always use the X 64-bit field. Also, check for an +@@ -408,6 +404,10 @@ static void acpi_tb_convert_fadt(void) + acpi_gbl_FADT.boot_flags = 0; + } + ++ /* Update the local FADT table header length */ ++ ++ acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); ++ + /* + * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" + * generic address structures as necessary. Later code will always use +-- +1.7.3.4 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-acpi" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index 06398038d..9d4a4a1a8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -715,6 +715,9 @@ Patch21100: msi-irq-sysfs-warning.patch # rhbz 754907 Patch21101: hpsa-add-irqf-shared.patch +#rhbz 727865 730007 +Patch21102: ACPICA-Fix-regression-in-FADT-revision-checks.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1321,6 +1324,9 @@ ApplyPatch scsi-fix-sd_revalidate_disk-oops.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch +#rhbz 727865 730007 +ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch + # END OF PATCH APPLICATIONS %endif @@ -1968,6 +1974,9 @@ fi # and build. %changelog +* Mon Feb 27 2012 Josh Boyer +- Add patch to fix regression in FADT revision checks (rhbz 730007 727865) + * Mon Feb 20 2012 Dave Jones 2.6.42.7-1 - Do not call drivers when invalidating partitions for -ENOMEDIUM From 5c51b136d3911008ab0f858e196e0846cbfb8c82 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 28 Feb 2012 14:05:39 -0600 Subject: [PATCH 319/397] CVE-2012-1090 CIFS: fix dentry refcount leak when opening a FIFO on lookup (rhbz 798296) --- ...ry-refcount-leak-when-opening-a-FIFO.patch | 61 +++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch diff --git a/cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch b/cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch new file mode 100644 index 000000000..9fd87acac --- /dev/null +++ b/cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch @@ -0,0 +1,61 @@ +From 5bccda0ebc7c0331b81ac47d39e4b920b198b2cd Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Thu, 23 Feb 2012 09:37:45 -0500 +Subject: [PATCH] cifs: fix dentry refcount leak when opening a FIFO on lookup + +The cifs code will attempt to open files on lookup under certain +circumstances. What happens though if we find that the file we opened +was actually a FIFO or other special file? + +Currently, the open filehandle just ends up being leaked leading to +a dentry refcount mismatch and oops on umount. Fix this by having the +code close the filehandle on the server if it turns out not to be a +regular file. While we're at it, change this spaghetti if statement +into a switch too. + +Cc: stable@vger.kernel.org +Reported-by: CAI Qian +Tested-by: CAI Qian +Reviewed-by: Shirish Pargaonkar +Signed-off-by: Jeff Layton +Signed-off-by: Steve French +--- + fs/cifs/dir.c | 20 ++++++++++++++++++-- + 1 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c +index 63a196b..bc7e244 100644 +--- a/fs/cifs/dir.c ++++ b/fs/cifs/dir.c +@@ -584,10 +584,26 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, + * If either that or op not supported returned, follow + * the normal lookup. + */ +- if ((rc == 0) || (rc == -ENOENT)) ++ switch (rc) { ++ case 0: ++ /* ++ * The server may allow us to open things like ++ * FIFOs, but the client isn't set up to deal ++ * with that. If it's not a regular file, just ++ * close it and proceed as if it were a normal ++ * lookup. ++ */ ++ if (newInode && !S_ISREG(newInode->i_mode)) { ++ CIFSSMBClose(xid, pTcon, fileHandle); ++ break; ++ } ++ case -ENOENT: + posix_open = true; +- else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP)) ++ case -EOPNOTSUPP: ++ break; ++ default: + pTcon->broken_posix_open = true; ++ } + } + if (!posix_open) + rc = cifs_get_inode_info_unix(&newInode, full_path, +-- +1.7.0.4 + diff --git a/kernel.spec b/kernel.spec index 9d4a4a1a8..014bce730 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -718,6 +718,9 @@ Patch21101: hpsa-add-irqf-shared.patch #rhbz 727865 730007 Patch21102: ACPICA-Fix-regression-in-FADT-revision-checks.patch +# rhbz 798296 +Patch21103: cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1327,6 +1330,9 @@ ApplyPatch bcma-brcmsmac-compat.patch #rhbz 727865 730007 ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch +# rhbz 798296 +ApplyPatch cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch + # END OF PATCH APPLICATIONS %endif @@ -1974,6 +1980,9 @@ fi # and build. %changelog +* Tue Feb 28 2012 Justin M. Forbes 2.6.42.7-3 +- CVE-2012-1090 CIFS: fix dentry refcount leak when opening a FIFO on lookup (rhbz 798296) + * Mon Feb 27 2012 Josh Boyer - Add patch to fix regression in FADT revision checks (rhbz 730007 727865) From d76ff50e7f7d8abe2ae5123eb6fe23296e994eaf Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 28 Feb 2012 15:34:18 -0500 Subject: [PATCH 320/397] Add patch to enable keyboard backlight on Sony laptops (rhbz 728478) --- kernel.spec | 11 ++++- ...Enable-keyboard-backlight-by-default.patch | 44 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 sony-laptop-Enable-keyboard-backlight-by-default.patch diff --git a/kernel.spec b/kernel.spec index 014bce730..6da868501 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -721,6 +721,9 @@ Patch21102: ACPICA-Fix-regression-in-FADT-revision-checks.patch # rhbz 798296 Patch21103: cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch +#rhbz 728478 +Patch21104: sony-laptop-Enable-keyboard-backlight-by-default.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1333,6 +1336,9 @@ ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch # rhbz 798296 ApplyPatch cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch +#rhbz 728478 +ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch + # END OF PATCH APPLICATIONS %endif @@ -1980,6 +1986,9 @@ fi # and build. %changelog +* Tue Feb 28 2012 Josh Boyer +- Add patch to enable keyboard backlight on Sony laptops (rhbz 728478) + * Tue Feb 28 2012 Justin M. Forbes 2.6.42.7-3 - CVE-2012-1090 CIFS: fix dentry refcount leak when opening a FIFO on lookup (rhbz 798296) diff --git a/sony-laptop-Enable-keyboard-backlight-by-default.patch b/sony-laptop-Enable-keyboard-backlight-by-default.patch new file mode 100644 index 000000000..c993fd86d --- /dev/null +++ b/sony-laptop-Enable-keyboard-backlight-by-default.patch @@ -0,0 +1,44 @@ +From 0dbc2bc96b1ec741bdd43451c286ccd45da3310b Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Wed, 2 Nov 2011 14:31:59 -0400 +Subject: [PATCH] sony-laptop: Enable keyboard backlight by default + +When the keyboard backlight support was originally added, the commit said +to default it to on with a 10 second timeout. That actually wasn't the +case, as the default value is commented out for the kbd_backlight parameter. +Because it is a static variable, it gets set to 0 by default without some +other form of initialization. + +However, it seems the function to set the value wasn't actually called +immediately, so whatever state the keyboard was in initially would remain. +Then commit df410d522410e67660 was introduced during the 2.6.39 timeframe to +immediately set whatever value was present (as well as attempt to +restore/reset the state on module removal or resume). That seems to have +now forced the light off immediately when the module is loaded unless +the option kbd_backlight=1 is specified. + +Let's enable it by default again (for the first time). This should solve +https://bugzilla.redhat.com/show_bug.cgi?id=728478 + +Acked-by: Mattia Dongili +Signed-off-by: Josh Boyer +--- + drivers/platform/x86/sony-laptop.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c +index c006dee..40c4705 100644 +--- a/drivers/platform/x86/sony-laptop.c ++++ b/drivers/platform/x86/sony-laptop.c +@@ -127,7 +127,7 @@ MODULE_PARM_DESC(minor, + "default is -1 (automatic)"); + #endif + +-static int kbd_backlight; /* = 1 */ ++static int kbd_backlight = 1; + module_param(kbd_backlight, int, 0444); + MODULE_PARM_DESC(kbd_backlight, + "set this to 0 to disable keyboard backlight, " +-- +1.7.7.6 + From 1fbb428f2e0326377d57c0c84f17c2608d02c839 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 1 Mar 2012 12:59:39 -0500 Subject: [PATCH 321/397] temporarily switch to low-performance polling IRQ mode when unexpected IRQs occur. --- kernel.spec | 8 + unhandled-irqs-switch-to-polling.patch | 269 +++++++++++++++++++++++++ 2 files changed, 277 insertions(+) create mode 100644 unhandled-irqs-switch-to-polling.patch diff --git a/kernel.spec b/kernel.spec index 6da868501..1683f10a4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -724,6 +724,8 @@ Patch21103: cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch #rhbz 728478 Patch21104: sony-laptop-Enable-keyboard-backlight-by-default.patch +Patch21200: unhandled-irqs-switch-to-polling.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1339,6 +1341,8 @@ ApplyPatch cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch #rhbz 728478 ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch +ApplyPatch unhandled-irqs-switch-to-polling.patch + # END OF PATCH APPLICATIONS %endif @@ -1986,6 +1990,10 @@ fi # and build. %changelog +* Thu Mar 01 2012 Dave Jones +- temporarily switch to low-performance polling IRQ mode when + unexpected IRQs occur. + * Tue Feb 28 2012 Josh Boyer - Add patch to enable keyboard backlight on Sony laptops (rhbz 728478) diff --git a/unhandled-irqs-switch-to-polling.patch b/unhandled-irqs-switch-to-polling.patch new file mode 100644 index 000000000..8eb09052b --- /dev/null +++ b/unhandled-irqs-switch-to-polling.patch @@ -0,0 +1,269 @@ +From davej Mon Jan 30 16:40:11 2012 +Return-Path: linux-kernel-owner@vger.kernel.org +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-4.9 required=5.0 tests=DKIM_ADSP_CUSTOM_MED, + DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_HI,T_DKIM_INVALID,T_RP_MATCHES_RCVD, + T_TO_NO_BRKTS_FREEMAIL,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk.kernelslacker.org with IMAP (fetchmail-6.3.20) + for (single-drop); Mon, 30 Jan 2012 16:40:11 -0500 (EST) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + zmail11.collab.prod.int.phx2.redhat.com with LMTP; Mon, 30 Jan 2012 + 16:37:45 -0500 (EST) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4BAD0114054; + Mon, 30 Jan 2012 16:37:45 -0500 (EST) +X-Quarantine-ID: <1529X45BXJfc> +Authentication-Results: zmta01.collab.prod.int.phx2.redhat.com (amavisd-new); + dkim=softfail (fail, body has been altered) header.i=@gmail.com +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 1529X45BXJfc; Mon, 30 Jan 2012 16:37:45 -0500 (EST) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 717AC11404F; + Mon, 30 Jan 2012 16:37:44 -0500 (EST) +Received: from mx1.redhat.com (ext-mx14.extmail.prod.ext.phx2.redhat.com [10.5.110.19]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q0ULbhea005095; + Mon, 30 Jan 2012 16:37:43 -0500 +Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q0ULQIU9002068; + Mon, 30 Jan 2012 16:37:42 -0500 +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1753551Ab2A3Vha (ORCPT + + 52 others); Mon, 30 Jan 2012 16:37:30 -0500 +Received: from mail-pz0-f46.google.com ([209.85.210.46]:44901 "EHLO + mail-pz0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1751932Ab2A3Vh2 (ORCPT + ); + Mon, 30 Jan 2012 16:37:28 -0500 +Received: by dadi2 with SMTP id i2so3911730dad.19 + for ; Mon, 30 Jan 2012 13:37:28 -0800 (PST) +Received-SPF: pass (google.com: domain of jeroen.vandenkeybus@gmail.com designates 10.68.218.68 as permitted sender) client-ip=10.68.218.68; +Authentication-Results: mr.google.com; spf=pass (google.com: domain of jeroen.vandenkeybus@gmail.com designates 10.68.218.68 as permitted sender) smtp.mail=jeroen.vandenkeybus@gmail.com; dkim=pass header.i=jeroen.vandenkeybus@gmail.com +Received: from mr.google.com ([10.68.218.68]) + by 10.68.218.68 with SMTP id pe4mr25063612pbc.97.1327959448228 (num_hops = 1); + Mon, 30 Jan 2012 13:37:28 -0800 (PST) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=gamma; + h=mime-version:date:message-id:subject:from:to:cc:content-type; + bh=acUEKJRLazlNr7PWqoJIHm/MPkfhI5SUq1Z0ntfqXSE=; + b=J1hmytKDfluL7NI73mVH+flbQ2+36FPRRx+DFhrPs8hiOebxJHysZZH+etW1ppCJG0 + ORowrKZYuyXb1CVYkSAYSnZ60r0edu8VycE4wsVItKQV8f0ZFyFZi5HteL1KiBRHqTYI + soeRaI/zW4cJv3AbTTc1Aj/4/HXKyuPtj0Ayc= +MIME-Version: 1.0 +Received: by 10.68.218.68 with SMTP id pe4mr20868027pbc.97.1327959448085; Mon, + 30 Jan 2012 13:37:28 -0800 (PST) +Received: by 10.143.38.11 with HTTP; Mon, 30 Jan 2012 13:37:28 -0800 (PST) +Date: Mon, 30 Jan 2012 22:37:28 +0100 +Message-ID: +Subject: [PATCH] Unhandled IRQs on AMD E-450: temporarily switch to + low-performance polling IRQ mode +From: Jeroen Van den Keybus +To: linux-kernel@vger.kernel.org +Cc: Clemens Ladisch , "Huang, Shane" , + Borislav Petkov , "Nguyen, Dong" , + jesse.brandeburg@gmail.com +Content-Type: text/plain; charset=ISO-8859-1 +Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org +X-RedHat-Spam-Score: -4.898 (DKIM_ADSP_CUSTOM_MED,DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_HI,T_DKIM_INVALID,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.19 +Status: RO +Content-Length: 7029 +Lines: 189 + +It seems that some motherboard designs using the ASM1083 PCI/PCIe +bridge (PCI device ID 1b21:1080, Rev. 01) suffer from stuck IRQ lines +on the PCI bus (causing the kernel to emit 'IRQxx: nobody cared' and +disable the IRQ). The following patch is an attempt to mitigate the +serious impact of permanently disabling an IRQ in that case and +actually make PCI devices better usable on this platform. + +It seems that the bridge fails to issue a IRQ deassertion message on +the PCIe bus, when the relevant driver causes the interrupting PCI +device to deassert its IRQ line. To solve this issue, it was tried to +re-issue an IRQ on a PCI device being able to do so (e1000 in this +case), but we suspect that the attempt to re-assert/deassert may have +occurred too soon after the initial IRQ for the ASM1083. Anyway, it +didn't work but if, after some delay, a new IRQ occurred, the related +IRQ deassertion message eventually did clear the IOAPIC IRQ. It would +be useful to re-enable the IRQ here. + +Therefore the patch below to poll_spurious_irqs() in spurious.c is +proposed, It does the following: + +1. lets the kernel decide that an IRQ is unhandled after only 10 +positives (instead of 100,000); +2. briefly (a few seconds or so, currently 1 s) switches to polling +IRQ at a higher rate than usual (100..1,000Hz instead of 10Hz, +currently 100Hz), but not too high to avoid excessive CPU load. Any +device drivers 'see' their interrupts handled with a higher latency +than usual, but they will still operate properly; +3. afterwards, simply reenable the IRQ. + +If proper operation of the PCIe legacy IRQ line emulation is restored +after 3, the system operates again at normal performance. If the IRQ +is still stuck after this procedure, the sequence repeats. + +If a genuinely stuck IRQ is used with this solution, the system would +simply sustain short bursts of 10 unhandled IRQs per second, and use +polling mode indefinitely at a moderate 100Hz rate. It seemed a good +alternative to the default irqpoll behaviour to me, which is why I +left it in poll_spurious_irqs() (instead of creating a new kernel +option). Additionally, if any device happens to share an IRQ with a +faulty one, that device is no longer banned forever. + +Debugging output is still present and may be removed. Bad IRQ +reporting is also commented out now. + +I have now tried it for about 2 months and I can conclude the following: + +1. The patch works and, judging from my Firewire card interrupt on +IRQ16, which repeats every 64 secs, I can confirm that the IRQ usually +gets reset when a new IRQ arrives (polling mode runs for 64 seconds +every time). +2. When testing a SiL-3114 SATA PCI card behind the ASM1083, I could +keep this running at fairly high speeds (50..70MB/s) for an hour or +so, but eventually the SiL driver crashed. In such conditions the PCI +system had to deal with a few hundred IRQs per second / polling mode +kicking in every 5..10 seconds). + +I would like to thank Clemens Ladisch for his invaluable help in +finding a solution (and providing a patch to avoid my SATA going down +every time during debugging). + + +Signed-off-by: Jeroen Van den Keybus +====== + +diff -up linux-3.2-rc4.orig/kernel/irq/spurious.c +linux-3.2-rc4/kernel/irq/spurious.c +--- linux-3.2-rc4.orig/kernel/irq/spurious.c 2011-12-01 23:56:01.000000000 +0100 ++++ linux-3.2-rc4/kernel/irq/spurious.c 2011-12-11 16:14:48.188377387 +0100 +@@ -18,7 +18,7 @@ + + static int irqfixup __read_mostly; + +-#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10) ++#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/100) + static void poll_spurious_irqs(unsigned long dummy); + static DEFINE_TIMER(poll_spurious_irq_timer, poll_spurious_irqs, 0, 0); + static int irq_poll_cpu; +@@ -141,14 +141,15 @@ out: + static void poll_spurious_irqs(unsigned long dummy) + { + struct irq_desc *desc; +- int i; ++ int i, poll_again; + + if (atomic_inc_return(&irq_poll_active) != 1) + goto out; + irq_poll_cpu = smp_processor_id(); + ++ poll_again = 0; /* Will stay false as long as no polling candidate is found */ + for_each_irq_desc(i, desc) { +- unsigned int state; ++ unsigned int state, irq; + + if (!i) + continue; +@@ -158,15 +159,33 @@ static void poll_spurious_irqs(unsigned + barrier(); + if (!(state & IRQS_SPURIOUS_DISABLED)) + continue; +- +- local_irq_disable(); +- try_one_irq(i, desc, true); +- local_irq_enable(); ++ ++ /* We end up here with a disabled spurious interrupt. ++ desc->irqs_unhandled now tracks the number of times ++ the interrupt has been polled */ ++ ++ irq = desc->irq_data.irq; ++ if (desc->irqs_unhandled < 100) { /* 1 second delay with poll frequency 100 Hz */ ++ if (desc->irqs_unhandled == 0) ++ printk("Polling IRQ %d\n", irq); ++ local_irq_disable(); ++ try_one_irq(i, desc, true); ++ local_irq_enable(); ++ desc->irqs_unhandled++; ++ poll_again = 1; ++ } else { ++ printk("Reenabling IRQ %d\n", irq); ++ irq_enable(desc); /* Reenable the interrupt line */ ++ desc->depth--; ++ desc->istate &= (~IRQS_SPURIOUS_DISABLED); ++ desc->irqs_unhandled = 0; ++ } + } ++ if (poll_again) ++ mod_timer(&poll_spurious_irq_timer, ++ jiffies + POLL_SPURIOUS_IRQ_INTERVAL); + out: + atomic_dec(&irq_poll_active); +- mod_timer(&poll_spurious_irq_timer, +- jiffies + POLL_SPURIOUS_IRQ_INTERVAL); + } + + static inline int bad_action_ret(irqreturn_t action_ret) +@@ -177,11 +196,19 @@ static inline int bad_action_ret(irqretu + } + + /* +- * If 99,900 of the previous 100,000 interrupts have not been handled ++ * If 9 of the previous 10 interrupts have not been handled + * then assume that the IRQ is stuck in some manner. Drop a diagnostic + * and try to turn the IRQ off. + * +- * (The other 100-of-100,000 interrupts may have been a correctly ++ * Although this may cause early deactivation of a sporadically ++ * malfunctioning IRQ line, the poll system will: ++ * a) Poll it for 100 cycles at a 100 Hz rate ++ * b) Reenable it afterwards ++ * ++ * In worst case, with current settings, this will cause short bursts ++ * of 10 interrupts every second. ++ * ++ * (The other single interrupt may have been a correctly + * functioning device sharing an IRQ with the failing one) + */ + static void +@@ -302,19 +329,19 @@ void note_interrupt(unsigned int irq, st + } + + desc->irq_count++; +- if (likely(desc->irq_count < 100000)) ++ if (likely(desc->irq_count < 10)) + return; + + desc->irq_count = 0; +- if (unlikely(desc->irqs_unhandled > 99900)) { ++ if (unlikely(desc->irqs_unhandled >= 9)) { + /* + * The interrupt is stuck + */ +- __report_bad_irq(irq, desc, action_ret); ++ /* __report_bad_irq(irq, desc, action_ret); */ + /* + * Now kill the IRQ + */ +- printk(KERN_EMERG "Disabling IRQ #%d\n", irq); ++ printk(KERN_EMERG "Disabling IRQ %d\n", irq); + desc->istate |= IRQS_SPURIOUS_DISABLED; + desc->depth++; + irq_disable(desc); + +====== +-- +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/ + From 4f70627e9e1a3ec0c091ed2729f9a44e80c7eeda Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 1 Mar 2012 14:15:23 -0500 Subject: [PATCH 322/397] Temporarily enable CONFIG_DEBUG_PAGEALLOC in -debug builds to help track down some long-standing bugs. --- config-debug | 3 +++ kernel.spec | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/config-debug b/config-debug index e3c1e6e44..ad5f5352c 100644 --- a/config-debug +++ b/config-debug @@ -109,3 +109,6 @@ CONFIG_DEBUG_KMEMLEAK=y CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y + +# Temporary +CONFIG_DEBUG_PAGEALLOC=y diff --git a/kernel.spec b/kernel.spec index 1683f10a4..f3838b606 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1990,6 +1990,11 @@ fi # and build. %changelog +* Thu Mar 01 2012 Dave Jones +- Temporarily enable CONFIG_DEBUG_PAGEALLOC in -debug builds to help track + down some long-standing bugs. + Note: This will make -debug builds even slower than normal. + * Thu Mar 01 2012 Dave Jones - temporarily switch to low-performance polling IRQ mode when unexpected IRQs occur. From 48010561b5bb5a68942db94b6918cd0a594ff915 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 1 Mar 2012 16:46:04 -0600 Subject: [PATCH 323/397] Linux 3.2.9 --- kernel.spec | 15 ++--- linux-2.6-i386-nx-emulation.patch | 98 ++++++++++++++++++++----------- sources | 2 +- utrace.patch | 2 +- 4 files changed, 71 insertions(+), 46 deletions(-) diff --git a/kernel.spec b/kernel.spec index f3838b606..402cc2489 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 4 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # Do we have a -stable update to apply? -%define stable_update 7 +%define stable_update 9 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -644,8 +644,6 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12026: bsg-fix-sysfs-link-remove-warning.patch -Patch12030: epoll-limit-paths.patch - Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13002: revert-efi-rtclock.patch @@ -669,8 +667,6 @@ Patch21004: arm-tegra-nvec-kconfig.patch #rhbz 717735 Patch21045: nfs-client-freezer.patch -Patch21046: nfs-oops-getacl.patch - #rhbz 590880 Patch21050: alps.patch @@ -1266,8 +1262,6 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch ApplyPatch disable-i8042-check-on-apple-mac.patch -ApplyPatch epoll-limit-paths.patch - ApplyPatch bsg-fix-sysfs-link-remove-warning.patch # rhbz#605888 @@ -1295,8 +1289,6 @@ ApplyPatch hpsa-add-irqf-shared.patch #rhbz 717735 ApplyPatch nfs-client-freezer.patch -ApplyPatch nfs-oops-getacl.patch - #rhbz 590880 ApplyPatch alps.patch @@ -1990,6 +1982,9 @@ fi # and build. %changelog +* Thu Mar 01 2012 Justin M. Forbes 2.6.42.9-1 +- Linux 3.2.9 + * Thu Mar 01 2012 Dave Jones - Temporarily enable CONFIG_DEBUG_PAGEALLOC in -debug builds to help track down some long-standing bugs. diff --git a/linux-2.6-i386-nx-emulation.patch b/linux-2.6-i386-nx-emulation.patch index 07a0faec8..d97d52999 100644 --- a/linux-2.6-i386-nx-emulation.patch +++ b/linux-2.6-i386-nx-emulation.patch @@ -1,3 +1,5 @@ +diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h +index 41935fa..6e9259b 100644 --- a/arch/x86/include/asm/desc.h +++ b/arch/x86/include/asm/desc.h @@ -5,6 +5,7 @@ @@ -44,6 +46,8 @@ +#endif /* CONFIG_X86_32 */ + #endif /* _ASM_X86_DESC_H */ +diff --git a/arch/x86/include/asm/mmu.h b/arch/x86/include/asm/mmu.h +index 5f55e69..aba94f0 100644 --- a/arch/x86/include/asm/mmu.h +++ b/arch/x86/include/asm/mmu.h @@ -7,6 +7,9 @@ @@ -68,9 +72,11 @@ } mm_context_t; #ifdef CONFIG_SMP +diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h +index a7d2db9..cc4ad60 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h -@@ -289,6 +289,12 @@ static inline void set_ldt(const void *addr, unsigned entries) +@@ -298,6 +298,12 @@ static inline void set_ldt(const void *addr, unsigned entries) { PVOP_VCALL2(pv_cpu_ops.set_ldt, addr, entries); } @@ -83,9 +89,11 @@ static inline void store_gdt(struct desc_ptr *dtr) { PVOP_VCALL1(pv_cpu_ops.store_gdt, dtr); +diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h +index 8e8b9a4..cca421e 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h -@@ -118,6 +118,9 @@ struct pv_cpu_ops { +@@ -125,6 +125,9 @@ struct pv_cpu_ops { void (*store_gdt)(struct desc_ptr *); void (*store_idt)(struct desc_ptr *); void (*set_ldt)(const void *desc, unsigned entries); @@ -95,9 +103,11 @@ unsigned long (*store_tr)(void); void (*load_tls)(struct thread_struct *t, unsigned int cpu); #ifdef CONFIG_X86_64 +diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c +index aa003b1..c094152 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c -@@ -802,6 +802,22 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) +@@ -844,6 +844,22 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) /* Filter out anything that depends on CPUID levels we don't have */ filter_cpuid_features(c, true); @@ -120,9 +130,11 @@ /* If the model name is still unset, do table lookup. */ if (!c->x86_model_id[0]) { const char *p; +diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c +index d90272e..cc594fc 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c -@@ -345,6 +345,9 @@ struct pv_cpu_ops pv_cpu_ops = { +@@ -358,6 +358,9 @@ struct pv_cpu_ops pv_cpu_ops = { .read_tscp = native_read_tscp, .load_tr_desc = native_load_tr_desc, .set_ldt = native_set_ldt, @@ -132,9 +144,11 @@ .load_gdt = native_load_gdt, .load_idt = native_load_idt, .store_gdt = native_store_gdt, +diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c +index 8598296..641ae48 100644 --- 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, +@@ -247,7 +247,10 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, void start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) { @@ -145,7 +159,7 @@ regs->fs = 0; 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) +@@ -255,6 +258,11 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) regs->cs = __USER_CS; regs->ip = new_ip; regs->sp = new_sp; @@ -157,17 +171,17 @@ /* * Free the old FP and other extended state */ -@@ -311,6 +319,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) - if (preload_fpu) - prefetch(next->fpu.state); +@@ -320,6 +328,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) + */ + lazy_save_gs(prev->gs); + if (next_p->mm) + load_user_cs_desc(cpu, next_p->mm); + /* - * Reload esp0. + * Load the per-thread Thread-Local Storage descriptor. */ -@@ -404,3 +415,40 @@ unsigned long get_wchan(struct task_struct *p) +@@ -390,3 +401,40 @@ unsigned long get_wchan(struct task_struct *p) return 0; } @@ -208,9 +222,11 @@ + mm->context.exec_limit = 0; + set_user_cs(&mm->context.user_cs, 0); +} +diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c +index 31d9d0f..f7c210d 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c -@@ -109,6 +109,78 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) +@@ -107,6 +107,78 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) dec_preempt_count(); } @@ -289,7 +305,7 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, long error_code, siginfo_t *info) -@@ -265,6 +337,29 @@ do_general_protection(struct pt_regs *regs, long error_code) +@@ -263,6 +335,29 @@ do_general_protection(struct pt_regs *regs, long error_code) if (!user_mode(regs)) goto gp_in_kernel; @@ -319,7 +335,7 @@ tsk->thread.error_code = error_code; tsk->thread.trap_no = 13; -@@ -792,19 +887,37 @@ do_device_not_available(struct pt_regs *regs, long error_code) +@@ -649,19 +744,37 @@ do_device_not_available(struct pt_regs *regs, long error_code) } #ifdef CONFIG_X86_32 @@ -366,6 +382,8 @@ } #endif +diff --git a/arch/x86/mm/setup_nx.c b/arch/x86/mm/setup_nx.c +index 410531d..eb040ad 100644 --- a/arch/x86/mm/setup_nx.c +++ b/arch/x86/mm/setup_nx.c @@ -1,3 +1,4 @@ @@ -373,16 +391,16 @@ #include #include #include -@@ -6,7 +6,7 @@ +@@ -5,7 +6,7 @@ #include #include - + -static int disable_nx __cpuinitdata; +int disable_nx __cpuinitdata; - + /* * noexec = on|off -@@ -40,6 +42,10 @@ void __cpuinit x86_configure_nx(void) +@@ -40,6 +41,10 @@ void __cpuinit x86_configure_nx(void) void __init x86_report_nx(void) { if (!cpu_has_nx) { @@ -393,9 +411,11 @@ printk(KERN_NOTICE "Notice: NX (Execute Disable) protection " "missing in CPU!\n"); } else { +diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c +index d6c0418..c15b765 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c -@@ -6,6 +6,7 @@ +@@ -7,6 +7,7 @@ #include #include @@ -403,7 +423,7 @@ #include #include #include -@@ -131,6 +132,12 @@ void smp_invalidate_interrupt(struct pt_regs *regs) +@@ -134,6 +135,12 @@ void smp_invalidate_interrupt(struct pt_regs *regs) union smp_flush_state *f; cpu = smp_processor_id(); @@ -416,9 +436,11 @@ /* * orig_rax contains the negated interrupt vector. * Use that to determine where the sender put the data. +diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c +index 1f92865..b8f4319 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c -@@ -335,6 +335,24 @@ static void xen_set_ldt(const void *addr, unsigned entries) +@@ -354,6 +354,24 @@ static void xen_set_ldt(const void *addr, unsigned entries) xen_mc_issue(PARAVIRT_LAZY_CPU); } @@ -443,7 +465,7 @@ static void xen_load_gdt(const struct desc_ptr *dtr) { unsigned long va = dtr->address; -@@ -961,6 +979,9 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = { +@@ -994,6 +1012,9 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { .load_tr_desc = paravirt_nop, .set_ldt = xen_set_ldt, @@ -453,9 +475,11 @@ .load_gdt = xen_load_gdt, .load_idt = xen_load_idt, .load_tls = xen_load_tls, +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index 21ac5ee..3f26963 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c -@@ -717,6 +722,15 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) +@@ -711,6 +711,15 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) if (retval) goto out_free_dentry; @@ -471,9 +495,11 @@ /* OK, This is the point of no return */ current->flags &= ~PF_FORKNOEXEC; current->mm->def_flags = def_flags; +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 1c4f3e9..52011a7 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h -@@ -101,6 +101,9 @@ struct bio_list; +@@ -102,6 +102,9 @@ struct fs_struct; struct perf_event_context; struct blk_plug; @@ -483,9 +509,11 @@ /* * List of flags we want to share for kernel threads, * if only because they are not used by them anyway. ---- b/mm/mmap.c +diff --git a/mm/mmap.c b/mm/mmap.c +index eae90af..f4de6c0 100644 +--- a/mm/mmap.c +++ b/mm/mmap.c -@@ -44,6 +45,18 @@ +@@ -46,6 +46,18 @@ #define arch_rebalance_pgtables(addr, len) (addr) #endif @@ -504,7 +532,7 @@ static void unmap_region(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev, unsigned long start, unsigned long end); -@@ -432,6 +432,8 @@ __vma_link(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -424,6 +436,8 @@ __vma_link(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev, struct rb_node **rb_link, struct rb_node *rb_parent) { @@ -513,7 +541,7 @@ __vma_link_list(mm, vma, prev, rb_parent); __vma_link_rb(mm, vma, rb_link, rb_parent); } -@@ -489,6 +504,8 @@ +@@ -478,6 +492,8 @@ __vma_unlink(struct mm_struct *mm, struct vm_area_struct *vma, rb_erase(&vma->vm_rb, &mm->mm_rb); if (mm->mmap_cache == vma) mm->mmap_cache = prev; @@ -522,7 +550,7 @@ } /* -@@ -790,6 +807,8 @@ +@@ -794,6 +810,8 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm, } else /* cases 2, 5, 7 */ err = vma_adjust(prev, prev->vm_start, end, prev->vm_pgoff, NULL); @@ -530,8 +558,8 @@ + arch_add_exec_range(mm, prev->vm_end); if (err) return NULL; - return prev; -@@ -1966,10 +2075,14 @@ + khugepaged_enter_vma_merge(prev); +@@ -1972,10 +1990,14 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, if (new->vm_ops && new->vm_ops->open) new->vm_ops->open(new); @@ -548,7 +576,7 @@ err = vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new); /* Success. */ -@@ -2254,6 +2367,7 @@ +@@ -2263,6 +2285,7 @@ void exit_mmap(struct mm_struct *mm) free_pgtables(&tlb, vma, FIRST_USER_ADDRESS, 0); tlb_finish_mmu(&tlb, 0, end); @@ -556,6 +584,8 @@ /* * Walk the list again, actually closing and freeing it, +diff --git a/mm/mprotect.c b/mm/mprotect.c +index 5a688a2..128d996 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -25,9 +25,14 @@ @@ -573,7 +603,7 @@ #ifndef pgprot_modify static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot) { -@@ -138,7 +143,7 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, +@@ -148,7 +153,7 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, struct mm_struct *mm = vma->vm_mm; unsigned long oldflags = vma->vm_flags; long nrpages = (end - start) >> PAGE_SHIFT; @@ -582,7 +612,7 @@ pgoff_t pgoff; int error; int dirty_accountable = 0; -@@ -203,6 +208,9 @@ success: +@@ -213,6 +218,9 @@ success: dirty_accountable = 1; } diff --git a/sources b/sources index 8a47cc81a..14e00fa7a 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz -e507fce2c266549df9565172196c912d patch-3.2.7.xz +3916159a999ee49cd6bd002556c629ad patch-3.2.9.xz diff --git a/utrace.patch b/utrace.patch index 060d351e5..5f678e592 100644 --- a/utrace.patch +++ b/utrace.patch @@ -3962,9 +3962,9 @@ index ba0d172..b8719c2 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -66,6 +66,7 @@ - #include #include #include + #include +#include #include From b2fb454be9036d82d6c26d8d59e484a971a9e66f Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Fri, 2 Mar 2012 12:29:49 -0500 Subject: [PATCH 324/397] drm-intel-crtc-dpms-fix.patch: Fix system hang on gen2 kit on DPMS (#730853) --- drm-intel-crtc-dpms-fix.patch | 40 +++++++++++++++++++++++++++++++++++ kernel.spec | 5 +++++ 2 files changed, 45 insertions(+) create mode 100644 drm-intel-crtc-dpms-fix.patch diff --git a/drm-intel-crtc-dpms-fix.patch b/drm-intel-crtc-dpms-fix.patch new file mode 100644 index 000000000..eb582cbec --- /dev/null +++ b/drm-intel-crtc-dpms-fix.patch @@ -0,0 +1,40 @@ +From aed3f09db39596e539f90b11a5016aea4d8442e1 Mon Sep 17 00:00:00 2001 +From: Alban Browaeys +Date: Fri, 24 Feb 2012 17:12:45 +0000 +Subject: [PATCH] drm/i915: Prevent a machine hang by checking crtc->active + before loading lut + +Before loading the lut (gamma), check the active state of intel_crtc, +otherwise at least on gen2 hang ensue. + +This is reproducible in Xorg via: + xset dpms force off +then + xgamma -rgamma 2.0 # freeze. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=44505 +Signed-off-by: Alban Browaeys +Signed-off-by: Chris Wilson +Reviewed-by: Jesse Barnes +Cc: stable@kernel.org +Signed-off-by: Jesse Barnes +--- + drivers/gpu/drm/i915/intel_display.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index 4871ba0..f851db7 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -6184,7 +6184,7 @@ void intel_crtc_load_lut(struct drm_crtc *crtc) + int i; + + /* The clocks have to be on to load the palette. */ +- if (!crtc->enabled) ++ if (!crtc->enabled || !intel_crtc->active) + return; + + /* use legacy palette for Ironlake */ +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index 402cc2489..cc5497e8b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -617,6 +617,7 @@ Patch1500: fix_xen_guest_on_old_EC2.patch Patch1810: drm-nouveau-updates.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch +Patch1825: drm-intel-crtc-dpms-fix.patch # hush the i915 fbc noise Patch1826: drm-i915-fbc-stfu.patch @@ -1244,6 +1245,7 @@ ApplyOptionalPatch drm-nouveau-updates.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch +ApplyPatch drm-intel-crtc-dpms-fix.patch ApplyPatch drm-i915-fbc-stfu.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch @@ -1982,6 +1984,9 @@ fi # and build. %changelog +* Fri Mar 02 2012 Adam Jackson +- drm-intel-crtc-dpms-fix.patch: Fix system hang on gen2 kit on DPMS (#730853) + * Thu Mar 01 2012 Justin M. Forbes 2.6.42.9-1 - Linux 3.2.9 From 93f9c95edbf93ef45a153694f3f68e82a29543d7 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 2 Mar 2012 14:39:44 -0600 Subject: [PATCH 325/397] Disable threading on compression/decompression for hibernate --- ...threading-in-compression-for-hibernate.patch | 17 +++++++++++++++++ kernel.spec | 9 +++++++++ 2 files changed, 26 insertions(+) create mode 100644 disable-threading-in-compression-for-hibernate.patch diff --git a/disable-threading-in-compression-for-hibernate.patch b/disable-threading-in-compression-for-hibernate.patch new file mode 100644 index 000000000..685c294ef --- /dev/null +++ b/disable-threading-in-compression-for-hibernate.patch @@ -0,0 +1,17 @@ +In attempt to find the cause of some of the hibernate issues we are seeing, +turn off threading for compression. + +Signed-off-by: Justin M. Forbes + +diff -ruNp a/kernel/power/swap.c b/kernel/power/swap.c +--- a/kernel/power/swap.c 2012-03-02 13:52:27.777485028 -0600 ++++ b/kernel/power/swap.c 2012-03-02 14:05:20.168115129 -0600 +@@ -401,7 +401,7 @@ static int swap_writer_finish(struct swa + #define LZO_CMP_SIZE (LZO_CMP_PAGES * PAGE_SIZE) + + /* Maximum number of threads for compression/decompression. */ +-#define LZO_THREADS 3 ++#define LZO_THREADS 1 + + /* Maximum number of pages for read buffering. */ + #define LZO_READ_PAGES (MAP_PAGE_ENTRIES * 8) diff --git a/kernel.spec b/kernel.spec index cc5497e8b..d81842622 100644 --- a/kernel.spec +++ b/kernel.spec @@ -721,6 +721,9 @@ Patch21103: cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch #rhbz 728478 Patch21104: sony-laptop-Enable-keyboard-backlight-by-default.patch +# Disable threading in hibernate compression +Patch21105: disable-threading-in-compression-for-hibernate.patch + Patch21200: unhandled-irqs-switch-to-polling.patch %endif @@ -1335,6 +1338,9 @@ ApplyPatch cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch #rhbz 728478 ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch +#Disable threading in hibernate compression +ApplyPatch disable-threading-in-compression-for-hibernate.patch + ApplyPatch unhandled-irqs-switch-to-polling.patch # END OF PATCH APPLICATIONS @@ -1984,6 +1990,9 @@ fi # and build. %changelog +* Fri Mar 02 2012 Justin M. Forbes +- Disable threading in hibernate compression/decompression + * Fri Mar 02 2012 Adam Jackson - drm-intel-crtc-dpms-fix.patch: Fix system hang on gen2 kit on DPMS (#730853) From be72cc46b5c99bc8947e1aa9039575ab8cfb3a6e Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 2 Mar 2012 16:03:02 -0500 Subject: [PATCH 326/397] Enable VM debugging in non-debug kernels too. --- config-nodebug | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-nodebug b/config-nodebug index 0f70aa0ae..43b70d774 100644 --- a/config-nodebug +++ b/config-nodebug @@ -8,7 +8,7 @@ CONFIG_SND_PCM_XRUN_DEBUG=y # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_DEBUG_LOCK_ALLOC is not set # CONFIG_PROVE_LOCKING is not set -# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_VM=y # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_PROVE_RCU is not set # CONFIG_PROVE_RCU_REPEATEDLY is not set diff --git a/kernel.spec b/kernel.spec index d81842622..aa0c77f24 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1990,6 +1990,9 @@ fi # and build. %changelog +* Fri Mar 02 2012 Dave Jones +- Enable VM debugging in non-debug kernels too. + * Fri Mar 02 2012 Justin M. Forbes - Disable threading in hibernate compression/decompression From 3bb94782bdf7141abe3cf31622af765b6d514037 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 5 Mar 2012 09:40:00 -0500 Subject: [PATCH 327/397] CVE-2012-1097 regset: Prevent null pointer reference on readonly regsets --- kernel.spec | 13 +++- ...ull-pointer-reference-on-readonly-re.patch | 63 +++++++++++++++++++ ...AULT-not-EIO-on-host-side-memory-fau.patch | 46 ++++++++++++++ 3 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 regset-Prevent-null-pointer-reference-on-readonly-re.patch create mode 100644 regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch diff --git a/kernel.spec b/kernel.spec index aa0c77f24..0c697d2f1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -724,6 +724,10 @@ Patch21104: sony-laptop-Enable-keyboard-backlight-by-default.patch # Disable threading in hibernate compression Patch21105: disable-threading-in-compression-for-hibernate.patch +#rhbz 799782 CVE-2012-1097 +Patch21106: regset-Prevent-null-pointer-reference-on-readonly-re.patch +Patch21107: regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch + Patch21200: unhandled-irqs-switch-to-polling.patch %endif @@ -1341,6 +1345,10 @@ ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch #Disable threading in hibernate compression ApplyPatch disable-threading-in-compression-for-hibernate.patch +#rhbz 799782 CVE-2012-1097 +ApplyPatch regset-Prevent-null-pointer-reference-on-readonly-re.patch +ApplyPatch regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch + ApplyPatch unhandled-irqs-switch-to-polling.patch # END OF PATCH APPLICATIONS @@ -1990,6 +1998,9 @@ fi # and build. %changelog +* Mon Mar 05 2012 Josh Boyer +- CVE-2012-1097 regset: Prevent null pointer reference on readonly regsets + * Fri Mar 02 2012 Dave Jones - Enable VM debugging in non-debug kernels too. diff --git a/regset-Prevent-null-pointer-reference-on-readonly-re.patch b/regset-Prevent-null-pointer-reference-on-readonly-re.patch new file mode 100644 index 000000000..6e2462ee1 --- /dev/null +++ b/regset-Prevent-null-pointer-reference-on-readonly-re.patch @@ -0,0 +1,63 @@ +From c8e252586f8d5de906385d8cf6385fee289a825e Mon Sep 17 00:00:00 2001 +From: "H. Peter Anvin" +Date: Fri, 2 Mar 2012 10:43:48 -0800 +Subject: [PATCH 1/2] regset: Prevent null pointer reference on readonly + regsets + +The regset common infrastructure assumed that regsets would always +have .get and .set methods, but not necessarily .active methods. +Unfortunately people have since written regsets without .set methods. + +Rather than putting in stub functions everywhere, handle regsets with +null .get or .set methods explicitly. + +Signed-off-by: H. Peter Anvin +Reviewed-by: Oleg Nesterov +Acked-by: Roland McGrath +Cc: +Signed-off-by: Linus Torvalds +--- + fs/binfmt_elf.c | 2 +- + include/linux/regset.h | 6 ++++++ + 2 files changed, 7 insertions(+), 1 deletions(-) + +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index bcb884e..07d096c 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -1421,7 +1421,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t, + for (i = 1; i < view->n; ++i) { + const struct user_regset *regset = &view->regsets[i]; + do_thread_regset_writeback(t->task, regset); +- if (regset->core_note_type && ++ if (regset->core_note_type && regset->get && + (!regset->active || regset->active(t->task, regset))) { + int ret; + size_t size = regset->n * regset->size; +diff --git a/include/linux/regset.h b/include/linux/regset.h +index 8abee65..5150fd1 100644 +--- a/include/linux/regset.h ++++ b/include/linux/regset.h +@@ -335,6 +335,9 @@ static inline int copy_regset_to_user(struct task_struct *target, + { + const struct user_regset *regset = &view->regsets[setno]; + ++ if (!regset->get) ++ return -EOPNOTSUPP; ++ + if (!access_ok(VERIFY_WRITE, data, size)) + return -EIO; + +@@ -358,6 +361,9 @@ static inline int copy_regset_from_user(struct task_struct *target, + { + const struct user_regset *regset = &view->regsets[setno]; + ++ if (!regset->set) ++ return -EOPNOTSUPP; ++ + if (!access_ok(VERIFY_READ, data, size)) + return -EIO; + +-- +1.7.7.6 + diff --git a/regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch b/regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch new file mode 100644 index 000000000..21b8ae1ce --- /dev/null +++ b/regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch @@ -0,0 +1,46 @@ +From 5189fa19a4b2b4c3bec37c3a019d446148827717 Mon Sep 17 00:00:00 2001 +From: "H. Peter Anvin" +Date: Fri, 2 Mar 2012 10:43:49 -0800 +Subject: [PATCH 2/2] regset: Return -EFAULT, not -EIO, on host-side memory + fault + +There is only one error code to return for a bad user-space buffer +pointer passed to a system call in the same address space as the +system call is executed, and that is EFAULT. Furthermore, the +low-level access routines, which catch most of the faults, return +EFAULT already. + +Signed-off-by: H. Peter Anvin +Reviewed-by: Oleg Nesterov +Acked-by: Roland McGrath +Cc: +Signed-off-by: Linus Torvalds +--- + include/linux/regset.h | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/regset.h b/include/linux/regset.h +index 5150fd1..686f373 100644 +--- a/include/linux/regset.h ++++ b/include/linux/regset.h +@@ -339,7 +339,7 @@ static inline int copy_regset_to_user(struct task_struct *target, + return -EOPNOTSUPP; + + if (!access_ok(VERIFY_WRITE, data, size)) +- return -EIO; ++ return -EFAULT; + + return regset->get(target, regset, offset, size, NULL, data); + } +@@ -365,7 +365,7 @@ static inline int copy_regset_from_user(struct task_struct *target, + return -EOPNOTSUPP; + + if (!access_ok(VERIFY_READ, data, size)) +- return -EIO; ++ return -EFAULT; + + return regset->set(target, regset, offset, size, NULL, data); + } +-- +1.7.7.6 + From d826f97738690a1be084fa8aaccf2e6c0c5cdd2a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 5 Mar 2012 15:35:58 -0500 Subject: [PATCH 328/397] Add patch to fix BUG_ON mm->nr_ptes (rhbz 786632) --- kernel.spec | 6 ++ mm-thp-fix-BUG-on-mm-nr_ptes.patch | 121 +++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 mm-thp-fix-BUG-on-mm-nr_ptes.patch diff --git a/kernel.spec b/kernel.spec index 0c697d2f1..5755f42af 100644 --- a/kernel.spec +++ b/kernel.spec @@ -728,6 +728,9 @@ Patch21105: disable-threading-in-compression-for-hibernate.patch Patch21106: regset-Prevent-null-pointer-reference-on-readonly-re.patch Patch21107: regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch +#rhbz 786632 +Patch21108: mm-thp-fix-BUG-on-mm-nr_ptes.patch + Patch21200: unhandled-irqs-switch-to-polling.patch %endif @@ -1351,6 +1354,8 @@ ApplyPatch regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch ApplyPatch unhandled-irqs-switch-to-polling.patch +ApplyPatch mm-thp-fix-BUG-on-mm-nr_ptes.patch + # END OF PATCH APPLICATIONS %endif @@ -2000,6 +2005,7 @@ fi %changelog * Mon Mar 05 2012 Josh Boyer - CVE-2012-1097 regset: Prevent null pointer reference on readonly regsets +- Add patch to fix BUG_ON mm->nr_ptes (rhbz 786632) * Fri Mar 02 2012 Dave Jones - Enable VM debugging in non-debug kernels too. diff --git a/mm-thp-fix-BUG-on-mm-nr_ptes.patch b/mm-thp-fix-BUG-on-mm-nr_ptes.patch new file mode 100644 index 000000000..44be5d5a9 --- /dev/null +++ b/mm-thp-fix-BUG-on-mm-nr_ptes.patch @@ -0,0 +1,121 @@ +On Thu, 16 Feb 2012, Andrea Arcangeli wrote: +> On Thu, Feb 16, 2012 at 01:53:04AM -0800, Hugh Dickins wrote: +> > Yes (and I think less troublesome than most BUGs, coming at exit +> > while not holding locks; though we could well make it a WARN_ON, +> > I don't think that existed back in the day). +> +> A WARN_ON would be fine with me, go ahead if you prefer it... only +> risk would be to go unnoticed or be underestimated. I am ok with the +> BUG_ON too (even if this time it triggered false positives... sigh). +> +> > Acked-by: Hugh Dickins +> +> Thanks for the quick review! +> +> > In looking into the bug, it had actually bothered me a little that you +> > were setting aside those pages, yet not counting them into nr_ptes; +> > though the only thing that cares is oom_kill.c, and the count of pages +> > in each hugepage can only dwarf the count in nr_ptes (whereas, without +> > hugepages, it's possible to populate very sparsely and nr_ptes become +> > significant). +> +> Agreed, it's not significant either ways. +> +> Running my two primary systems with this applied for half a day and no +> problem so far so it should be good foro -mm at least. + +And I've had no trouble running your patch since then (but I never hit +the bug it fixes either). But we've all forgottent about it, so let me +bring your patch back inline (I've added one introductory sentence) and +address to akpm... + + +From: Andrea Arcangeli +Subject: [PATCH] mm: thp: fix BUG on mm->nr_ptes + +Dave Jones reports a few Fedora users hitting the BUG_ON(mm->nr_ptes...) +in exit_mmap() recently. + +Quoting Hugh's discovery and explanation of the SMP race condition: + +=== +mm->nr_ptes had unusual locking: down_read mmap_sem plus +page_table_lock when incrementing, down_write mmap_sem (or mm_users 0) +when decrementing; whereas THP is careful to increment and decrement +it under page_table_lock. + +Now most of those paths in THP also hold mmap_sem for read or write +(with appropriate checks on mm_users), but two do not: when +split_huge_page() is called by hwpoison_user_mappings(), and when +called by add_to_swap(). + +It's conceivable that the latter case is responsible for the +exit_mmap() BUG_ON mm->nr_ptes that has been reported on Fedora. +=== + +The simplest way to fix it without having to alter the locking is to +make split_huge_page() a noop in nr_ptes terms, so by counting the +preallocated pagetables that exists for every mapped hugepage. It was +an arbitrary choice not to count them and either way is not wrong or +right, because they are not used but they're still allocated. + +Reported-by: Dave Jones +Reported-by: Hugh Dickins +Signed-off-by: Andrea Arcangeli +Acked-by: Hugh Dickins +--- + mm/huge_memory.c | 6 +++--- + 1 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index 91d3efb..8f7fc39 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -671,6 +671,7 @@ static int __do_huge_pmd_anonymous_page(struct mm_struct *mm, + set_pmd_at(mm, haddr, pmd, entry); + prepare_pmd_huge_pte(pgtable, mm); + add_mm_counter(mm, MM_ANONPAGES, HPAGE_PMD_NR); ++ mm->nr_ptes++; + spin_unlock(&mm->page_table_lock); + } + +@@ -789,6 +790,7 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm, + pmd = pmd_mkold(pmd_wrprotect(pmd)); + set_pmd_at(dst_mm, addr, dst_pmd, pmd); + prepare_pmd_huge_pte(pgtable, dst_mm); ++ dst_mm->nr_ptes++; + + ret = 0; + out_unlock: +@@ -887,7 +889,6 @@ static int do_huge_pmd_wp_page_fallback(struct mm_struct *mm, + } + kfree(pages); + +- mm->nr_ptes++; + smp_wmb(); /* make pte visible before pmd */ + pmd_populate(mm, pmd, pgtable); + page_remove_rmap(page); +@@ -1047,6 +1048,7 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, + VM_BUG_ON(page_mapcount(page) < 0); + add_mm_counter(tlb->mm, MM_ANONPAGES, -HPAGE_PMD_NR); + VM_BUG_ON(!PageHead(page)); ++ tlb->mm->nr_ptes--; + spin_unlock(&tlb->mm->page_table_lock); + tlb_remove_page(tlb, page); + pte_free(tlb->mm, pgtable); +@@ -1375,7 +1377,6 @@ static int __split_huge_page_map(struct page *page, + pte_unmap(pte); + } + +- mm->nr_ptes++; + smp_wmb(); /* make pte visible before pmd */ + /* + * Up to this point the pmd is present and huge and +@@ -1988,7 +1989,6 @@ static void collapse_huge_page(struct mm_struct *mm, + set_pmd_at(mm, address, pmd, _pmd); + update_mmu_cache(vma, address, _pmd); + prepare_pmd_huge_pte(pgtable, mm); +- mm->nr_ptes--; + spin_unlock(&mm->page_table_lock); + + #ifndef CONFIG_NUMA From e2507362663e0194b96cafa5b1888b5c476d0c47 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 7 Mar 2012 07:55:38 -0500 Subject: [PATCH 329/397] memcg: unregister events attached to the same eventfd can oops (rhbz 800817) --- kernel.spec | 12 +++- ...-unregistring-of-events-attached-to-.patch | 69 +++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 mm-memcg-Correct-unregistring-of-events-attached-to-.patch diff --git a/kernel.spec b/kernel.spec index 5755f42af..4e05a24fa 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -731,6 +731,9 @@ Patch21107: regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch #rhbz 786632 Patch21108: mm-thp-fix-BUG-on-mm-nr_ptes.patch +#rhbz 800817 +Patch21109: mm-memcg-Correct-unregistring-of-events-attached-to-.patch + Patch21200: unhandled-irqs-switch-to-polling.patch %endif @@ -1354,8 +1357,12 @@ ApplyPatch regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch ApplyPatch unhandled-irqs-switch-to-polling.patch +#rhbz 786632 ApplyPatch mm-thp-fix-BUG-on-mm-nr_ptes.patch +#rhbz 800817 +ApplyPatch mm-memcg-Correct-unregistring-of-events-attached-to-.patch + # END OF PATCH APPLICATIONS %endif @@ -2003,6 +2010,9 @@ fi # and build. %changelog +* Wed Mar 07 2012 Josh Boye +- memcg: unregister events attached to the same eventfd can oops (rhbz 800817) + * Mon Mar 05 2012 Josh Boyer - CVE-2012-1097 regset: Prevent null pointer reference on readonly regsets - Add patch to fix BUG_ON mm->nr_ptes (rhbz 786632) diff --git a/mm-memcg-Correct-unregistring-of-events-attached-to-.patch b/mm-memcg-Correct-unregistring-of-events-attached-to-.patch new file mode 100644 index 000000000..5da0f02b2 --- /dev/null +++ b/mm-memcg-Correct-unregistring-of-events-attached-to-.patch @@ -0,0 +1,69 @@ +From 371528caec553785c37f73fa3926ea0de84f986f Mon Sep 17 00:00:00 2001 +From: Anton Vorontsov +Date: Fri, 24 Feb 2012 05:14:46 +0400 +Subject: [PATCH] mm: memcg: Correct unregistring of events attached to the + same eventfd + +There is an issue when memcg unregisters events that were attached to +the same eventfd: + +- On the first call mem_cgroup_usage_unregister_event() removes all + events attached to a given eventfd, and if there were no events left, + thresholds->primary would become NULL; + +- Since there were several events registered, cgroups core will call + mem_cgroup_usage_unregister_event() again, but now kernel will oops, + as the function doesn't expect that threshold->primary may be NULL. + +That's a good question whether mem_cgroup_usage_unregister_event() +should actually remove all events in one go, but nowadays it can't +do any better as cftype->unregister_event callback doesn't pass +any private event-associated cookie. So, let's fix the issue by +simply checking for threshold->primary. + +FWIW, w/o the patch the following oops may be observed: + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000004 + IP: [] mem_cgroup_usage_unregister_event+0x9c/0x1f0 + Pid: 574, comm: kworker/0:2 Not tainted 3.3.0-rc4+ #9 Bochs Bochs + RIP: 0010:[] [] mem_cgroup_usage_unregister_event+0x9c/0x1f0 + RSP: 0018:ffff88001d0b9d60 EFLAGS: 00010246 + Process kworker/0:2 (pid: 574, threadinfo ffff88001d0b8000, task ffff88001de91cc0) + Call Trace: + [] cgroup_event_remove+0x2b/0x60 + [] process_one_work+0x174/0x450 + [] worker_thread+0x123/0x2d0 + +Cc: stable +Signed-off-by: Anton Vorontsov +Acked-by: KAMEZAWA Hiroyuki +Cc: Kirill A. Shutemov +Cc: Michal Hocko +Signed-off-by: Linus Torvalds + +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index 6728a7a..228d646 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -4414,6 +4414,9 @@ static void mem_cgroup_usage_unregister_event(struct cgroup *cgrp, + */ + BUG_ON(!thresholds); + ++ if (!thresholds->primary) ++ goto unlock; ++ + usage = mem_cgroup_usage(memcg, type == _MEMSWAP); + + /* Check if a threshold crossed before removing */ +@@ -4462,7 +4465,7 @@ swap_buffers: + + /* To be sure that nobody uses thresholds */ + synchronize_rcu(); +- ++unlock: + mutex_unlock(&memcg->thresholds_lock); + } + +-- +1.7.7.6 + From 761d970eca202ba50e102a5fe401877cc1c07434 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 7 Mar 2012 11:58:37 -0500 Subject: [PATCH 330/397] Add CVE number --- kernel.spec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 4e05a24fa..7544b369a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2011,7 +2011,8 @@ fi %changelog * Wed Mar 07 2012 Josh Boye -- memcg: unregister events attached to the same eventfd can oops (rhbz 800817) +- CVE-2012-1146: memcg: unregister events attached to the same eventfd can + oops (rhbz 800817) * Mon Mar 05 2012 Josh Boyer - CVE-2012-1097 regset: Prevent null pointer reference on readonly regsets From fcf71737a12497487d2058c78e17ed7f8835624b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 7 Mar 2012 17:08:44 -0500 Subject: [PATCH 331/397] Add debug patch for bugs 787171/766277 --- kernel.spec | 7 +++++++ weird-root-dentry-name-debug.patch | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 weird-root-dentry-name-debug.patch diff --git a/kernel.spec b/kernel.spec index 7544b369a..7f6a2ca9f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -736,6 +736,8 @@ Patch21109: mm-memcg-Correct-unregistring-of-events-attached-to-.patch Patch21200: unhandled-irqs-switch-to-polling.patch +Patch22000: weird-root-dentry-name-debug.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1357,6 +1359,8 @@ ApplyPatch regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch ApplyPatch unhandled-irqs-switch-to-polling.patch +ApplyPatch weird-root-dentry-name-debug.patch + #rhbz 786632 ApplyPatch mm-thp-fix-BUG-on-mm-nr_ptes.patch @@ -2010,6 +2014,9 @@ fi # and build. %changelog +* Wed Mar 07 2012 Dave Jones +- Add debug patch for bugs 787171/766277 + * Wed Mar 07 2012 Josh Boye - CVE-2012-1146: memcg: unregister events attached to the same eventfd can oops (rhbz 800817) diff --git a/weird-root-dentry-name-debug.patch b/weird-root-dentry-name-debug.patch new file mode 100644 index 000000000..e2fb2e116 --- /dev/null +++ b/weird-root-dentry-name-debug.patch @@ -0,0 +1,19 @@ +debug patch for bz 787171/766277 + +diff --git a/fs/dcache.c b/fs/dcache.c +index bcbdb33..a6a5fdb 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -2530,8 +2530,10 @@ global_root: + */ + if (IS_ROOT(dentry) && + (dentry->d_name.len != 1 || dentry->d_name.name[0] != '/')) { +- WARN(1, "Root dentry has weird name <%.*s>\n", +- (int) dentry->d_name.len, dentry->d_name.name); ++ WARN(1, "Root dentry has weird name <%.*s> vfsmnt:%s fs:%s\n", ++ (int) dentry->d_name.len, dentry->d_name.name, ++ vfsmnt->mnt_root->d_name.name, ++ vfsmnt->mnt_sb->s_type->name); + } + if (!slash) + error = prepend(buffer, buflen, "/", 1); From ad6cae5b9e24ba8928c32462f78fbdffe8b85625 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 12 Mar 2012 09:19:54 -0400 Subject: [PATCH 332/397] Add patch to ignore bogus io-apic entries (rhbz 801501) --- kernel.spec | 9 +- ...ter-checks-for-bogus-io-apic-entries.patch | 93 +++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch diff --git a/kernel.spec b/kernel.spec index 7f6a2ca9f..11af56819 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -734,6 +734,8 @@ Patch21108: mm-thp-fix-BUG-on-mm-nr_ptes.patch #rhbz 800817 Patch21109: mm-memcg-Correct-unregistring-of-events-attached-to-.patch +Patch21110: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch + Patch21200: unhandled-irqs-switch-to-polling.patch Patch22000: weird-root-dentry-name-debug.patch @@ -1367,6 +1369,8 @@ ApplyPatch mm-thp-fix-BUG-on-mm-nr_ptes.patch #rhbz 800817 ApplyPatch mm-memcg-Correct-unregistring-of-events-attached-to-.patch +ApplyPatch x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch + # END OF PATCH APPLICATIONS %endif @@ -2014,6 +2018,9 @@ fi # and build. %changelog +* Mon Mar 12 2012 Josh Boyer +- Add patch to ignore bogus io-apic entries (rhbz 801501) + * Wed Mar 07 2012 Dave Jones - Add debug patch for bugs 787171/766277 diff --git a/x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch b/x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch new file mode 100644 index 000000000..9928829e0 --- /dev/null +++ b/x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch @@ -0,0 +1,93 @@ +On Tue, 2012-01-31 at 09:26 -0500, Josh Boyer wrote: +> On Wed, Jan 25, 2012 at 06:15:35PM -0500, Josh Boyer wrote: +> > On Wed, Jan 25, 2012 at 02:04:08PM -0800, Suresh Siddha wrote: +> > > On Wed, 2012-01-25 at 08:49 -0500, Josh Boyer wrote: +> > > > [ 0.000000] IOAPIC[1]: apic_id 2, version 255, address 0xfec28000, GSI 24-279 +> > > +> > > This looks indeed like a bogus entry probably returning all 1's for +> > > RTE's etc. Can you please send me a dmesg with "apic=verbose" boot +> > > parameter? +> > +> > Here you go: +> > +> > https://bugzilla.redhat.com/attachment.cgi?id=557552 +> +> Was this helpful at all? I've been watching lkml for a related patch +> in case I was missed on CC but haven't seen anything as of yet. + +Yes, it was helpful. Something like the appended patch should ignore the +bogus io-apic entry all together. As I can't test this, can you or the +reporter give the appended patch a try and ack please? + +thanks, +suresh +--- + +From: Suresh Siddha +Subject: x86, ioapic: add register checks for bogus io-apic entries + +With the recent changes to clear_IO_APIC_pin() which tries to clear +remoteIRR bit explicitly, some of the users started to see +"Unable to reset IRR for apic .." messages. + +Close look shows that these are related to bogus IO-APIC entries which +return's all 1's for their io-apic registers. And the above mentioned error +messages are benign. But kernel should have ignored such io-apic's in the +first place. + +Check if register 0, 1, 2 of the listed io-apic are all 1's and ignore +such io-apic. + +Reported-by: Álvaro Castillo +Signed-off-by: Suresh Siddha +--- + arch/x86/kernel/apic/io_apic.c | 26 ++++++++++++++++++++++++++ + 1 files changed, 26 insertions(+), 0 deletions(-) + +diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c +index fb07275..953e54d 100644 +--- a/arch/x86/kernel/apic/io_apic.c ++++ b/arch/x86/kernel/apic/io_apic.c +@@ -3979,6 +3979,26 @@ static __init int bad_ioapic(unsigned long address) + return 0; + } + ++static __init int bad_ioapic_regs(int idx) ++{ ++ union IO_APIC_reg_00 reg_00; ++ union IO_APIC_reg_01 reg_01; ++ union IO_APIC_reg_02 reg_02; ++ ++ reg_00.raw = io_apic_read(idx, 0); ++ reg_01.raw = io_apic_read(idx, 1); ++ reg_02.raw = io_apic_read(idx, 2); ++ ++ if (reg_00.raw == -1 && reg_01.raw == -1 && reg_02.raw == -1) { ++ printk(KERN_WARNING ++ "I/O APIC 0x%x regs return all ones, skipping!\n", ++ mpc_ioapic_addr(idx)); ++ return 1; ++ } ++ ++ return 0; ++} ++ + void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) + { + int idx = 0; +@@ -3995,6 +4015,12 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) + ioapics[idx].mp_config.apicaddr = address; + + set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); ++ ++ if (bad_ioapic_regs(idx)) { ++ clear_fixmap(FIX_IO_APIC_BASE_0 + idx); ++ return; ++ } ++ + ioapics[idx].mp_config.apicid = io_apic_unique_id(id); + ioapics[idx].mp_config.apicver = io_apic_get_version(idx); + + + + From e95ee579d9239ec87eadc41ba8151c6460032a73 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 12 Mar 2012 14:58:06 -0400 Subject: [PATCH 333/397] Make the irqpoll patch less chatty (rhbz 800520) Should look at making the frequency of checking dynamic, but this will help the immediate problem. --- unhandled-irqs-switch-to-polling.patch | 47 ++++++++++---------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/unhandled-irqs-switch-to-polling.patch b/unhandled-irqs-switch-to-polling.patch index 8eb09052b..6eeaf0bec 100644 --- a/unhandled-irqs-switch-to-polling.patch +++ b/unhandled-irqs-switch-to-polling.patch @@ -140,16 +140,16 @@ every time during debugging). Signed-off-by: Jeroen Van den Keybus + +Make it less chatty. Josh Boyer ====== -diff -up linux-3.2-rc4.orig/kernel/irq/spurious.c -linux-3.2-rc4/kernel/irq/spurious.c ---- linux-3.2-rc4.orig/kernel/irq/spurious.c 2011-12-01 23:56:01.000000000 +0100 -+++ linux-3.2-rc4/kernel/irq/spurious.c 2011-12-11 16:14:48.188377387 +0100 +--- linux-2.6.orig/kernel/irq/spurious.c ++++ linux-2.6/kernel/irq/spurious.c @@ -18,7 +18,7 @@ - + static int irqfixup __read_mostly; - + -#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10) +#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/100) static void poll_spurious_irqs(unsigned long dummy); @@ -161,42 +161,37 @@ linux-3.2-rc4/kernel/irq/spurious.c struct irq_desc *desc; - int i; + int i, poll_again; - + if (atomic_inc_return(&irq_poll_active) != 1) goto out; irq_poll_cpu = smp_processor_id(); - + + poll_again = 0; /* Will stay false as long as no polling candidate is found */ for_each_irq_desc(i, desc) { - unsigned int state; + unsigned int state, irq; - + if (!i) continue; -@@ -158,15 +159,33 @@ static void poll_spurious_irqs(unsigned - barrier(); +@@ -159,14 +160,29 @@ static void poll_spurious_irqs(unsigned if (!(state & IRQS_SPURIOUS_DISABLED)) continue; -- + - local_irq_disable(); - try_one_irq(i, desc, true); - local_irq_enable(); -+ + /* We end up here with a disabled spurious interrupt. + desc->irqs_unhandled now tracks the number of times + the interrupt has been polled */ + + irq = desc->irq_data.irq; + if (desc->irqs_unhandled < 100) { /* 1 second delay with poll frequency 100 Hz */ -+ if (desc->irqs_unhandled == 0) -+ printk("Polling IRQ %d\n", irq); + local_irq_disable(); + try_one_irq(i, desc, true); + local_irq_enable(); + desc->irqs_unhandled++; + poll_again = 1; + } else { -+ printk("Reenabling IRQ %d\n", irq); + irq_enable(desc); /* Reenable the interrupt line */ + desc->depth--; + desc->istate &= (~IRQS_SPURIOUS_DISABLED); @@ -211,11 +206,11 @@ linux-3.2-rc4/kernel/irq/spurious.c - mod_timer(&poll_spurious_irq_timer, - jiffies + POLL_SPURIOUS_IRQ_INTERVAL); } - + static inline int bad_action_ret(irqreturn_t action_ret) -@@ -177,11 +196,19 @@ static inline int bad_action_ret(irqretu +@@ -177,11 +193,19 @@ static inline int bad_action_ret(irqretu } - + /* - * If 99,900 of the previous 100,000 interrupts have not been handled + * If 9 of the previous 10 interrupts have not been handled @@ -235,14 +230,14 @@ linux-3.2-rc4/kernel/irq/spurious.c * functioning device sharing an IRQ with the failing one) */ static void -@@ -302,19 +329,19 @@ void note_interrupt(unsigned int irq, st +@@ -302,19 +326,19 @@ void note_interrupt(unsigned int irq, st } - + desc->irq_count++; - if (likely(desc->irq_count < 100000)) + if (likely(desc->irq_count < 10)) return; - + desc->irq_count = 0; - if (unlikely(desc->irqs_unhandled > 99900)) { + if (unlikely(desc->irqs_unhandled >= 9)) { @@ -259,11 +254,3 @@ linux-3.2-rc4/kernel/irq/spurious.c desc->istate |= IRQS_SPURIOUS_DISABLED; desc->depth++; irq_disable(desc); - -====== --- -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/ - From 2eb45048c78deaeccac3aba393cb3d56ffcac443 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 13 Mar 2012 00:24:38 -0500 Subject: [PATCH 334/397] Linux 3.2.10 --- bsg-fix-sysfs-link-remove-warning.patch | 16 --- ...ry-refcount-leak-when-opening-a-FIFO.patch | 61 --------- kernel.spec | 39 +----- ...-unregistring-of-events-attached-to-.patch | 69 ---------- mm-thp-fix-BUG-on-mm-nr_ptes.patch | 121 ------------------ ...ull-pointer-reference-on-readonly-re.patch | 63 --------- ...AULT-not-EIO-on-host-side-memory-fau.patch | 46 ------- sources | 2 +- 8 files changed, 6 insertions(+), 411 deletions(-) delete mode 100644 bsg-fix-sysfs-link-remove-warning.patch delete mode 100644 cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch delete mode 100644 mm-memcg-Correct-unregistring-of-events-attached-to-.patch delete mode 100644 mm-thp-fix-BUG-on-mm-nr_ptes.patch delete mode 100644 regset-Prevent-null-pointer-reference-on-readonly-re.patch delete mode 100644 regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch diff --git a/bsg-fix-sysfs-link-remove-warning.patch b/bsg-fix-sysfs-link-remove-warning.patch deleted file mode 100644 index 6e7625327..000000000 --- a/bsg-fix-sysfs-link-remove-warning.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/block/bsg.c b/block/bsg.c -index 4cf703f..ff64ae3 100644 ---- a/block/bsg.c -+++ b/block/bsg.c -@@ -983,7 +983,8 @@ void bsg_unregister_queue(struct request_queue *q) - - mutex_lock(&bsg_mutex); - idr_remove(&bsg_minor_idr, bcd->minor); -- sysfs_remove_link(&q->kobj, "bsg"); -+ if (q->kobj.sd) -+ sysfs_remove_link(&q->kobj, "bsg"); - device_unregister(bcd->class_dev); - bcd->class_dev = NULL; - kref_put(&bcd->ref, bsg_kref_release_function); --- -1.7.4.4 diff --git a/cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch b/cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch deleted file mode 100644 index 9fd87acac..000000000 --- a/cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 5bccda0ebc7c0331b81ac47d39e4b920b198b2cd Mon Sep 17 00:00:00 2001 -From: Jeff Layton -Date: Thu, 23 Feb 2012 09:37:45 -0500 -Subject: [PATCH] cifs: fix dentry refcount leak when opening a FIFO on lookup - -The cifs code will attempt to open files on lookup under certain -circumstances. What happens though if we find that the file we opened -was actually a FIFO or other special file? - -Currently, the open filehandle just ends up being leaked leading to -a dentry refcount mismatch and oops on umount. Fix this by having the -code close the filehandle on the server if it turns out not to be a -regular file. While we're at it, change this spaghetti if statement -into a switch too. - -Cc: stable@vger.kernel.org -Reported-by: CAI Qian -Tested-by: CAI Qian -Reviewed-by: Shirish Pargaonkar -Signed-off-by: Jeff Layton -Signed-off-by: Steve French ---- - fs/cifs/dir.c | 20 ++++++++++++++++++-- - 1 files changed, 18 insertions(+), 2 deletions(-) - -diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c -index 63a196b..bc7e244 100644 ---- a/fs/cifs/dir.c -+++ b/fs/cifs/dir.c -@@ -584,10 +584,26 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, - * If either that or op not supported returned, follow - * the normal lookup. - */ -- if ((rc == 0) || (rc == -ENOENT)) -+ switch (rc) { -+ case 0: -+ /* -+ * The server may allow us to open things like -+ * FIFOs, but the client isn't set up to deal -+ * with that. If it's not a regular file, just -+ * close it and proceed as if it were a normal -+ * lookup. -+ */ -+ if (newInode && !S_ISREG(newInode->i_mode)) { -+ CIFSSMBClose(xid, pTcon, fileHandle); -+ break; -+ } -+ case -ENOENT: - posix_open = true; -- else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP)) -+ case -EOPNOTSUPP: -+ break; -+ default: - pTcon->broken_posix_open = true; -+ } - } - if (!posix_open) - rc = cifs_get_inode_info_unix(&newInode, full_path, --- -1.7.0.4 - diff --git a/kernel.spec b/kernel.spec index 11af56819..6a861bc13 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 4 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # Do we have a -stable update to apply? -%define stable_update 9 +%define stable_update 10 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -617,7 +617,6 @@ Patch1500: fix_xen_guest_on_old_EC2.patch Patch1810: drm-nouveau-updates.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch -Patch1825: drm-intel-crtc-dpms-fix.patch # hush the i915 fbc noise Patch1826: drm-i915-fbc-stfu.patch @@ -643,8 +642,6 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch12026: bsg-fix-sysfs-link-remove-warning.patch - Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13002: revert-efi-rtclock.patch @@ -715,25 +712,12 @@ Patch21101: hpsa-add-irqf-shared.patch #rhbz 727865 730007 Patch21102: ACPICA-Fix-regression-in-FADT-revision-checks.patch -# rhbz 798296 -Patch21103: cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch - #rhbz 728478 Patch21104: sony-laptop-Enable-keyboard-backlight-by-default.patch # Disable threading in hibernate compression Patch21105: disable-threading-in-compression-for-hibernate.patch -#rhbz 799782 CVE-2012-1097 -Patch21106: regset-Prevent-null-pointer-reference-on-readonly-re.patch -Patch21107: regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch - -#rhbz 786632 -Patch21108: mm-thp-fix-BUG-on-mm-nr_ptes.patch - -#rhbz 800817 -Patch21109: mm-memcg-Correct-unregistring-of-events-attached-to-.patch - Patch21110: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch Patch21200: unhandled-irqs-switch-to-polling.patch @@ -1262,7 +1246,6 @@ ApplyOptionalPatch drm-nouveau-updates.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch -ApplyPatch drm-intel-crtc-dpms-fix.patch ApplyPatch drm-i915-fbc-stfu.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch @@ -1281,8 +1264,6 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch ApplyPatch disable-i8042-check-on-apple-mac.patch -ApplyPatch bsg-fix-sysfs-link-remove-warning.patch - # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -1346,29 +1327,16 @@ ApplyPatch bcma-brcmsmac-compat.patch #rhbz 727865 730007 ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch -# rhbz 798296 -ApplyPatch cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch - #rhbz 728478 ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch #Disable threading in hibernate compression ApplyPatch disable-threading-in-compression-for-hibernate.patch -#rhbz 799782 CVE-2012-1097 -ApplyPatch regset-Prevent-null-pointer-reference-on-readonly-re.patch -ApplyPatch regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch - ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch -#rhbz 786632 -ApplyPatch mm-thp-fix-BUG-on-mm-nr_ptes.patch - -#rhbz 800817 -ApplyPatch mm-memcg-Correct-unregistring-of-events-attached-to-.patch - ApplyPatch x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch # END OF PATCH APPLICATIONS @@ -2018,6 +1986,9 @@ fi # and build. %changelog +* Mon Mar 12 2012 Justin M. Forbes - 2.6.42.10-1 +- Linux 3.2.10 + * Mon Mar 12 2012 Josh Boyer - Add patch to ignore bogus io-apic entries (rhbz 801501) diff --git a/mm-memcg-Correct-unregistring-of-events-attached-to-.patch b/mm-memcg-Correct-unregistring-of-events-attached-to-.patch deleted file mode 100644 index 5da0f02b2..000000000 --- a/mm-memcg-Correct-unregistring-of-events-attached-to-.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 371528caec553785c37f73fa3926ea0de84f986f Mon Sep 17 00:00:00 2001 -From: Anton Vorontsov -Date: Fri, 24 Feb 2012 05:14:46 +0400 -Subject: [PATCH] mm: memcg: Correct unregistring of events attached to the - same eventfd - -There is an issue when memcg unregisters events that were attached to -the same eventfd: - -- On the first call mem_cgroup_usage_unregister_event() removes all - events attached to a given eventfd, and if there were no events left, - thresholds->primary would become NULL; - -- Since there were several events registered, cgroups core will call - mem_cgroup_usage_unregister_event() again, but now kernel will oops, - as the function doesn't expect that threshold->primary may be NULL. - -That's a good question whether mem_cgroup_usage_unregister_event() -should actually remove all events in one go, but nowadays it can't -do any better as cftype->unregister_event callback doesn't pass -any private event-associated cookie. So, let's fix the issue by -simply checking for threshold->primary. - -FWIW, w/o the patch the following oops may be observed: - - BUG: unable to handle kernel NULL pointer dereference at 0000000000000004 - IP: [] mem_cgroup_usage_unregister_event+0x9c/0x1f0 - Pid: 574, comm: kworker/0:2 Not tainted 3.3.0-rc4+ #9 Bochs Bochs - RIP: 0010:[] [] mem_cgroup_usage_unregister_event+0x9c/0x1f0 - RSP: 0018:ffff88001d0b9d60 EFLAGS: 00010246 - Process kworker/0:2 (pid: 574, threadinfo ffff88001d0b8000, task ffff88001de91cc0) - Call Trace: - [] cgroup_event_remove+0x2b/0x60 - [] process_one_work+0x174/0x450 - [] worker_thread+0x123/0x2d0 - -Cc: stable -Signed-off-by: Anton Vorontsov -Acked-by: KAMEZAWA Hiroyuki -Cc: Kirill A. Shutemov -Cc: Michal Hocko -Signed-off-by: Linus Torvalds - -diff --git a/mm/memcontrol.c b/mm/memcontrol.c -index 6728a7a..228d646 100644 ---- a/mm/memcontrol.c -+++ b/mm/memcontrol.c -@@ -4414,6 +4414,9 @@ static void mem_cgroup_usage_unregister_event(struct cgroup *cgrp, - */ - BUG_ON(!thresholds); - -+ if (!thresholds->primary) -+ goto unlock; -+ - usage = mem_cgroup_usage(memcg, type == _MEMSWAP); - - /* Check if a threshold crossed before removing */ -@@ -4462,7 +4465,7 @@ swap_buffers: - - /* To be sure that nobody uses thresholds */ - synchronize_rcu(); -- -+unlock: - mutex_unlock(&memcg->thresholds_lock); - } - --- -1.7.7.6 - diff --git a/mm-thp-fix-BUG-on-mm-nr_ptes.patch b/mm-thp-fix-BUG-on-mm-nr_ptes.patch deleted file mode 100644 index 44be5d5a9..000000000 --- a/mm-thp-fix-BUG-on-mm-nr_ptes.patch +++ /dev/null @@ -1,121 +0,0 @@ -On Thu, 16 Feb 2012, Andrea Arcangeli wrote: -> On Thu, Feb 16, 2012 at 01:53:04AM -0800, Hugh Dickins wrote: -> > Yes (and I think less troublesome than most BUGs, coming at exit -> > while not holding locks; though we could well make it a WARN_ON, -> > I don't think that existed back in the day). -> -> A WARN_ON would be fine with me, go ahead if you prefer it... only -> risk would be to go unnoticed or be underestimated. I am ok with the -> BUG_ON too (even if this time it triggered false positives... sigh). -> -> > Acked-by: Hugh Dickins -> -> Thanks for the quick review! -> -> > In looking into the bug, it had actually bothered me a little that you -> > were setting aside those pages, yet not counting them into nr_ptes; -> > though the only thing that cares is oom_kill.c, and the count of pages -> > in each hugepage can only dwarf the count in nr_ptes (whereas, without -> > hugepages, it's possible to populate very sparsely and nr_ptes become -> > significant). -> -> Agreed, it's not significant either ways. -> -> Running my two primary systems with this applied for half a day and no -> problem so far so it should be good foro -mm at least. - -And I've had no trouble running your patch since then (but I never hit -the bug it fixes either). But we've all forgottent about it, so let me -bring your patch back inline (I've added one introductory sentence) and -address to akpm... - - -From: Andrea Arcangeli -Subject: [PATCH] mm: thp: fix BUG on mm->nr_ptes - -Dave Jones reports a few Fedora users hitting the BUG_ON(mm->nr_ptes...) -in exit_mmap() recently. - -Quoting Hugh's discovery and explanation of the SMP race condition: - -=== -mm->nr_ptes had unusual locking: down_read mmap_sem plus -page_table_lock when incrementing, down_write mmap_sem (or mm_users 0) -when decrementing; whereas THP is careful to increment and decrement -it under page_table_lock. - -Now most of those paths in THP also hold mmap_sem for read or write -(with appropriate checks on mm_users), but two do not: when -split_huge_page() is called by hwpoison_user_mappings(), and when -called by add_to_swap(). - -It's conceivable that the latter case is responsible for the -exit_mmap() BUG_ON mm->nr_ptes that has been reported on Fedora. -=== - -The simplest way to fix it without having to alter the locking is to -make split_huge_page() a noop in nr_ptes terms, so by counting the -preallocated pagetables that exists for every mapped hugepage. It was -an arbitrary choice not to count them and either way is not wrong or -right, because they are not used but they're still allocated. - -Reported-by: Dave Jones -Reported-by: Hugh Dickins -Signed-off-by: Andrea Arcangeli -Acked-by: Hugh Dickins ---- - mm/huge_memory.c | 6 +++--- - 1 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/mm/huge_memory.c b/mm/huge_memory.c -index 91d3efb..8f7fc39 100644 ---- a/mm/huge_memory.c -+++ b/mm/huge_memory.c -@@ -671,6 +671,7 @@ static int __do_huge_pmd_anonymous_page(struct mm_struct *mm, - set_pmd_at(mm, haddr, pmd, entry); - prepare_pmd_huge_pte(pgtable, mm); - add_mm_counter(mm, MM_ANONPAGES, HPAGE_PMD_NR); -+ mm->nr_ptes++; - spin_unlock(&mm->page_table_lock); - } - -@@ -789,6 +790,7 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm, - pmd = pmd_mkold(pmd_wrprotect(pmd)); - set_pmd_at(dst_mm, addr, dst_pmd, pmd); - prepare_pmd_huge_pte(pgtable, dst_mm); -+ dst_mm->nr_ptes++; - - ret = 0; - out_unlock: -@@ -887,7 +889,6 @@ static int do_huge_pmd_wp_page_fallback(struct mm_struct *mm, - } - kfree(pages); - -- mm->nr_ptes++; - smp_wmb(); /* make pte visible before pmd */ - pmd_populate(mm, pmd, pgtable); - page_remove_rmap(page); -@@ -1047,6 +1048,7 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, - VM_BUG_ON(page_mapcount(page) < 0); - add_mm_counter(tlb->mm, MM_ANONPAGES, -HPAGE_PMD_NR); - VM_BUG_ON(!PageHead(page)); -+ tlb->mm->nr_ptes--; - spin_unlock(&tlb->mm->page_table_lock); - tlb_remove_page(tlb, page); - pte_free(tlb->mm, pgtable); -@@ -1375,7 +1377,6 @@ static int __split_huge_page_map(struct page *page, - pte_unmap(pte); - } - -- mm->nr_ptes++; - smp_wmb(); /* make pte visible before pmd */ - /* - * Up to this point the pmd is present and huge and -@@ -1988,7 +1989,6 @@ static void collapse_huge_page(struct mm_struct *mm, - set_pmd_at(mm, address, pmd, _pmd); - update_mmu_cache(vma, address, _pmd); - prepare_pmd_huge_pte(pgtable, mm); -- mm->nr_ptes--; - spin_unlock(&mm->page_table_lock); - - #ifndef CONFIG_NUMA diff --git a/regset-Prevent-null-pointer-reference-on-readonly-re.patch b/regset-Prevent-null-pointer-reference-on-readonly-re.patch deleted file mode 100644 index 6e2462ee1..000000000 --- a/regset-Prevent-null-pointer-reference-on-readonly-re.patch +++ /dev/null @@ -1,63 +0,0 @@ -From c8e252586f8d5de906385d8cf6385fee289a825e Mon Sep 17 00:00:00 2001 -From: "H. Peter Anvin" -Date: Fri, 2 Mar 2012 10:43:48 -0800 -Subject: [PATCH 1/2] regset: Prevent null pointer reference on readonly - regsets - -The regset common infrastructure assumed that regsets would always -have .get and .set methods, but not necessarily .active methods. -Unfortunately people have since written regsets without .set methods. - -Rather than putting in stub functions everywhere, handle regsets with -null .get or .set methods explicitly. - -Signed-off-by: H. Peter Anvin -Reviewed-by: Oleg Nesterov -Acked-by: Roland McGrath -Cc: -Signed-off-by: Linus Torvalds ---- - fs/binfmt_elf.c | 2 +- - include/linux/regset.h | 6 ++++++ - 2 files changed, 7 insertions(+), 1 deletions(-) - -diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c -index bcb884e..07d096c 100644 ---- a/fs/binfmt_elf.c -+++ b/fs/binfmt_elf.c -@@ -1421,7 +1421,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t, - for (i = 1; i < view->n; ++i) { - const struct user_regset *regset = &view->regsets[i]; - do_thread_regset_writeback(t->task, regset); -- if (regset->core_note_type && -+ if (regset->core_note_type && regset->get && - (!regset->active || regset->active(t->task, regset))) { - int ret; - size_t size = regset->n * regset->size; -diff --git a/include/linux/regset.h b/include/linux/regset.h -index 8abee65..5150fd1 100644 ---- a/include/linux/regset.h -+++ b/include/linux/regset.h -@@ -335,6 +335,9 @@ static inline int copy_regset_to_user(struct task_struct *target, - { - const struct user_regset *regset = &view->regsets[setno]; - -+ if (!regset->get) -+ return -EOPNOTSUPP; -+ - if (!access_ok(VERIFY_WRITE, data, size)) - return -EIO; - -@@ -358,6 +361,9 @@ static inline int copy_regset_from_user(struct task_struct *target, - { - const struct user_regset *regset = &view->regsets[setno]; - -+ if (!regset->set) -+ return -EOPNOTSUPP; -+ - if (!access_ok(VERIFY_READ, data, size)) - return -EIO; - --- -1.7.7.6 - diff --git a/regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch b/regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch deleted file mode 100644 index 21b8ae1ce..000000000 --- a/regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 5189fa19a4b2b4c3bec37c3a019d446148827717 Mon Sep 17 00:00:00 2001 -From: "H. Peter Anvin" -Date: Fri, 2 Mar 2012 10:43:49 -0800 -Subject: [PATCH 2/2] regset: Return -EFAULT, not -EIO, on host-side memory - fault - -There is only one error code to return for a bad user-space buffer -pointer passed to a system call in the same address space as the -system call is executed, and that is EFAULT. Furthermore, the -low-level access routines, which catch most of the faults, return -EFAULT already. - -Signed-off-by: H. Peter Anvin -Reviewed-by: Oleg Nesterov -Acked-by: Roland McGrath -Cc: -Signed-off-by: Linus Torvalds ---- - include/linux/regset.h | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/include/linux/regset.h b/include/linux/regset.h -index 5150fd1..686f373 100644 ---- a/include/linux/regset.h -+++ b/include/linux/regset.h -@@ -339,7 +339,7 @@ static inline int copy_regset_to_user(struct task_struct *target, - return -EOPNOTSUPP; - - if (!access_ok(VERIFY_WRITE, data, size)) -- return -EIO; -+ return -EFAULT; - - return regset->get(target, regset, offset, size, NULL, data); - } -@@ -365,7 +365,7 @@ static inline int copy_regset_from_user(struct task_struct *target, - return -EOPNOTSUPP; - - if (!access_ok(VERIFY_READ, data, size)) -- return -EIO; -+ return -EFAULT; - - return regset->set(target, regset, offset, size, NULL, data); - } --- -1.7.7.6 - diff --git a/sources b/sources index 14e00fa7a..a003ef5f5 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz -3916159a999ee49cd6bd002556c629ad patch-3.2.9.xz +7481fa09f2efda915ed19a9da33a2e59 patch-3.2.10.xz From 58fb9ef4a512a75c614cdfb95e40cb488ce9473e Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 14 Mar 2012 18:26:04 -0400 Subject: [PATCH 335/397] Reduce the foot print of the NFSv4 idmapping coda (bz 593035) --- ...reduce-the-footprint-of-the-idmapper.patch | 109 ++++++++++++++++++ ...Reduce-the-footprint-of-the-idmapper.patch | 46 ++++++++ kernel.spec | 9 +- 3 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch create mode 100644 NFSv4-Reduce-the-footprint-of-the-idmapper.patch diff --git a/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch b/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch new file mode 100644 index 000000000..42d1052e2 --- /dev/null +++ b/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch @@ -0,0 +1,109 @@ +diff -up linux-3.2.noarch/fs/nfs/idmap.c.orig linux-3.2.noarch/fs/nfs/idmap.c +--- linux-3.2.noarch/fs/nfs/idmap.c.orig 2012-03-14 13:08:37.462928792 -0400 ++++ linux-3.2.noarch/fs/nfs/idmap.c 2012-03-14 13:10:17.076030982 -0400 +@@ -365,7 +365,7 @@ struct idmap_hashent { + + struct idmap_hashtable { + __u8 h_type; +- struct idmap_hashent h_entries[IDMAP_HASH_SZ]; ++ struct idmap_hashent *h_entries; + }; + + struct idmap { +@@ -420,20 +420,39 @@ nfs_idmap_new(struct nfs_client *clp) + return 0; + } + ++static void ++idmap_alloc_hashtable(struct idmap_hashtable *h) ++{ ++ if (h->h_entries != NULL) ++ return; ++ h->h_entries = kcalloc(IDMAP_HASH_SZ, ++ sizeof(*h->h_entries), ++ GFP_KERNEL); ++} ++ ++static void ++idmap_free_hashtable(struct idmap_hashtable *h) ++{ ++ int i; ++ ++ if (h->h_entries == NULL) ++ return; ++ for (i = 0; i < IDMAP_HASH_SZ; i++) ++ kfree(h->h_entries[i].ih_name); ++ kfree(h->h_entries); ++} ++ + void + nfs_idmap_delete(struct nfs_client *clp) + { + struct idmap *idmap = clp->cl_idmap; +- int i; + + if (!idmap) + return; + rpc_unlink(idmap->idmap_dentry); + clp->cl_idmap = NULL; +- for (i = 0; i < ARRAY_SIZE(idmap->idmap_user_hash.h_entries); i++) +- kfree(idmap->idmap_user_hash.h_entries[i].ih_name); +- for (i = 0; i < ARRAY_SIZE(idmap->idmap_group_hash.h_entries); i++) +- kfree(idmap->idmap_group_hash.h_entries[i].ih_name); ++ idmap_free_hashtable(&idmap->idmap_user_hash); ++ idmap_free_hashtable(&idmap->idmap_group_hash); + kfree(idmap); + } + +@@ -443,6 +462,8 @@ nfs_idmap_delete(struct nfs_client *clp) + static inline struct idmap_hashent * + idmap_name_hash(struct idmap_hashtable* h, const char *name, size_t len) + { ++ if (h->h_entries == NULL) ++ return NULL; + return &h->h_entries[fnvhash32(name, len) % IDMAP_HASH_SZ]; + } + +@@ -451,6 +472,8 @@ idmap_lookup_name(struct idmap_hashtable + { + struct idmap_hashent *he = idmap_name_hash(h, name, len); + ++ if (he == NULL) ++ return NULL; + if (he->ih_namelen != len || memcmp(he->ih_name, name, len) != 0) + return NULL; + if (time_after(jiffies, he->ih_expires)) +@@ -461,6 +484,8 @@ idmap_lookup_name(struct idmap_hashtable + static inline struct idmap_hashent * + idmap_id_hash(struct idmap_hashtable* h, __u32 id) + { ++ if (h->h_entries == NULL) ++ return NULL; + return &h->h_entries[fnvhash32(&id, sizeof(id)) % IDMAP_HASH_SZ]; + } + +@@ -468,6 +493,9 @@ static struct idmap_hashent * + idmap_lookup_id(struct idmap_hashtable *h, __u32 id) + { + struct idmap_hashent *he = idmap_id_hash(h, id); ++ ++ if (he == NULL) ++ return NULL; + if (he->ih_id != id || he->ih_namelen == 0) + return NULL; + if (time_after(jiffies, he->ih_expires)) +@@ -483,12 +511,14 @@ idmap_lookup_id(struct idmap_hashtable * + static inline struct idmap_hashent * + idmap_alloc_name(struct idmap_hashtable *h, char *name, size_t len) + { ++ idmap_alloc_hashtable(h); + return idmap_name_hash(h, name, len); + } + + static inline struct idmap_hashent * + idmap_alloc_id(struct idmap_hashtable *h, __u32 id) + { ++ idmap_alloc_hashtable(h); + return idmap_id_hash(h, id); + } + diff --git a/NFSv4-Reduce-the-footprint-of-the-idmapper.patch b/NFSv4-Reduce-the-footprint-of-the-idmapper.patch new file mode 100644 index 000000000..4110ef904 --- /dev/null +++ b/NFSv4-Reduce-the-footprint-of-the-idmapper.patch @@ -0,0 +1,46 @@ +diff -up linux-3.2.noarch/fs/nfs/idmap.c.orig linux-3.2.noarch/fs/nfs/idmap.c +--- linux-3.2.noarch/fs/nfs/idmap.c.orig 2012-02-07 07:12:52.585471833 -0500 ++++ linux-3.2.noarch/fs/nfs/idmap.c 2012-03-14 13:08:37.462928792 -0400 +@@ -360,7 +360,7 @@ struct idmap_hashent { + unsigned long ih_expires; + __u32 ih_id; + size_t ih_namelen; +- char ih_name[IDMAP_NAMESZ]; ++ const char *ih_name; + }; + + struct idmap_hashtable { +@@ -424,11 +424,16 @@ void + nfs_idmap_delete(struct nfs_client *clp) + { + struct idmap *idmap = clp->cl_idmap; ++ int i; + + if (!idmap) + return; + rpc_unlink(idmap->idmap_dentry); + clp->cl_idmap = NULL; ++ for (i = 0; i < ARRAY_SIZE(idmap->idmap_user_hash.h_entries); i++) ++ kfree(idmap->idmap_user_hash.h_entries[i].ih_name); ++ for (i = 0; i < ARRAY_SIZE(idmap->idmap_group_hash.h_entries); i++) ++ kfree(idmap->idmap_group_hash.h_entries[i].ih_name); + kfree(idmap); + } + +@@ -491,9 +496,14 @@ static void + idmap_update_entry(struct idmap_hashent *he, const char *name, + size_t namelen, __u32 id) + { ++ char *str = kmalloc(namelen + 1, GFP_KERNEL); ++ if (str == NULL) ++ return; ++ kfree(he->ih_name); + he->ih_id = id; +- memcpy(he->ih_name, name, namelen); +- he->ih_name[namelen] = '\0'; ++ memcpy(str, name, namelen); ++ str[namelen] = '\0'; ++ he->ih_name = str; + he->ih_namelen = namelen; + he->ih_expires = jiffies + nfs_idmap_cache_timeout; + } diff --git a/kernel.spec b/kernel.spec index 6a861bc13..33cc8e83e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -637,6 +637,8 @@ Patch2901: linux-2.6-v4l-dvb-experimental.patch Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 +Patch4000: NFSv4-Reduce-the-footprint-of-the-idmapper.patch +Patch4001: NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch # patches headed upstream @@ -1174,7 +1176,9 @@ ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # eCryptfs # NFSv4 - +ApplyPatch NFSv4-Reduce-the-footprint-of-the-idmapper.patch +ApplyPatch NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch + # USB # WMI @@ -1986,6 +1990,9 @@ fi # and build. %changelog +* Wed Mar 14 2012 Steve Dickson +- Reduce the foot print of the NFSv4 idmapping coda (bz 593035) + * Mon Mar 12 2012 Justin M. Forbes - 2.6.42.10-1 - Linux 3.2.10 From 9e8b42e8ea2002fc7c217886d95a785bca6fd609 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 14 Mar 2012 20:29:41 -0400 Subject: [PATCH 336/397] Fixup irqpoll patch to only activate on machines with ASM108x PCI bridge --- kernel.spec | 7 +- unhandled-irqs-switch-to-polling.patch | 145 ++++++++++--------------- 2 files changed, 65 insertions(+), 87 deletions(-) diff --git a/kernel.spec b/kernel.spec index 33cc8e83e..2d5fc91f3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -1990,6 +1990,9 @@ fi # and build. %changelog +* Wed Mar 14 2012 Josh Boyer +- Fixup irqpoll patch to only activate on machines with ASM108x PCI bridge + * Wed Mar 14 2012 Steve Dickson - Reduce the foot print of the NFSv4 idmapping coda (bz 593035) @@ -2002,7 +2005,7 @@ fi * Wed Mar 07 2012 Dave Jones - Add debug patch for bugs 787171/766277 -* Wed Mar 07 2012 Josh Boye +* Wed Mar 07 2012 Josh Boyer - CVE-2012-1146: memcg: unregister events attached to the same eventfd can oops (rhbz 800817) diff --git a/unhandled-irqs-switch-to-polling.patch b/unhandled-irqs-switch-to-polling.patch index 6eeaf0bec..39169ba96 100644 --- a/unhandled-irqs-switch-to-polling.patch +++ b/unhandled-irqs-switch-to-polling.patch @@ -1,62 +1,3 @@ -From davej Mon Jan 30 16:40:11 2012 -Return-Path: linux-kernel-owner@vger.kernel.org -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-4.9 required=5.0 tests=DKIM_ADSP_CUSTOM_MED, - DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_HI,T_DKIM_INVALID,T_RP_MATCHES_RCVD, - T_TO_NO_BRKTS_FREEMAIL,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk.kernelslacker.org with IMAP (fetchmail-6.3.20) - for (single-drop); Mon, 30 Jan 2012 16:40:11 -0500 (EST) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail11.collab.prod.int.phx2.redhat.com with LMTP; Mon, 30 Jan 2012 - 16:37:45 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4BAD0114054; - Mon, 30 Jan 2012 16:37:45 -0500 (EST) -X-Quarantine-ID: <1529X45BXJfc> -Authentication-Results: zmta01.collab.prod.int.phx2.redhat.com (amavisd-new); - dkim=softfail (fail, body has been altered) header.i=@gmail.com -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 1529X45BXJfc; Mon, 30 Jan 2012 16:37:45 -0500 (EST) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 717AC11404F; - Mon, 30 Jan 2012 16:37:44 -0500 (EST) -Received: from mx1.redhat.com (ext-mx14.extmail.prod.ext.phx2.redhat.com [10.5.110.19]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q0ULbhea005095; - Mon, 30 Jan 2012 16:37:43 -0500 -Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q0ULQIU9002068; - Mon, 30 Jan 2012 16:37:42 -0500 -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1753551Ab2A3Vha (ORCPT - + 52 others); Mon, 30 Jan 2012 16:37:30 -0500 -Received: from mail-pz0-f46.google.com ([209.85.210.46]:44901 "EHLO - mail-pz0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1751932Ab2A3Vh2 (ORCPT - ); - Mon, 30 Jan 2012 16:37:28 -0500 -Received: by dadi2 with SMTP id i2so3911730dad.19 - for ; Mon, 30 Jan 2012 13:37:28 -0800 (PST) -Received-SPF: pass (google.com: domain of jeroen.vandenkeybus@gmail.com designates 10.68.218.68 as permitted sender) client-ip=10.68.218.68; -Authentication-Results: mr.google.com; spf=pass (google.com: domain of jeroen.vandenkeybus@gmail.com designates 10.68.218.68 as permitted sender) smtp.mail=jeroen.vandenkeybus@gmail.com; dkim=pass header.i=jeroen.vandenkeybus@gmail.com -Received: from mr.google.com ([10.68.218.68]) - by 10.68.218.68 with SMTP id pe4mr25063612pbc.97.1327959448228 (num_hops = 1); - Mon, 30 Jan 2012 13:37:28 -0800 (PST) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=gamma; - h=mime-version:date:message-id:subject:from:to:cc:content-type; - bh=acUEKJRLazlNr7PWqoJIHm/MPkfhI5SUq1Z0ntfqXSE=; - b=J1hmytKDfluL7NI73mVH+flbQ2+36FPRRx+DFhrPs8hiOebxJHysZZH+etW1ppCJG0 - ORowrKZYuyXb1CVYkSAYSnZ60r0edu8VycE4wsVItKQV8f0ZFyFZi5HteL1KiBRHqTYI - soeRaI/zW4cJv3AbTTc1Aj/4/HXKyuPtj0Ayc= -MIME-Version: 1.0 -Received: by 10.68.218.68 with SMTP id pe4mr20868027pbc.97.1327959448085; Mon, - 30 Jan 2012 13:37:28 -0800 (PST) -Received: by 10.143.38.11 with HTTP; Mon, 30 Jan 2012 13:37:28 -0800 (PST) Date: Mon, 30 Jan 2012 22:37:28 +0100 Message-ID: Subject: [PATCH] Unhandled IRQs on AMD E-450: temporarily switch to @@ -141,21 +82,23 @@ every time during debugging). Signed-off-by: Jeroen Van den Keybus -Make it less chatty. Josh Boyer +Make it less chatty. Only kick it in if we detect an ASM1083 PCI bridge. + +Josh Boyer ====== --- linux-2.6.orig/kernel/irq/spurious.c +++ linux-2.6/kernel/irq/spurious.c -@@ -18,7 +18,7 @@ +@@ -18,6 +18,8 @@ static int irqfixup __read_mostly; --#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10) -+#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/100) ++int irq_poll_and_retry = 0; ++ + #define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10) static void poll_spurious_irqs(unsigned long dummy); static DEFINE_TIMER(poll_spurious_irq_timer, poll_spurious_irqs, 0, 0); - static int irq_poll_cpu; -@@ -141,14 +141,15 @@ out: +@@ -141,12 +143,13 @@ out: static void poll_spurious_irqs(unsigned long dummy) { struct irq_desc *desc; @@ -168,12 +111,9 @@ Make it less chatty. Josh Boyer + poll_again = 0; /* Will stay false as long as no polling candidate is found */ for_each_irq_desc(i, desc) { -- unsigned int state; -+ unsigned int state, irq; + unsigned int state; - if (!i) - continue; -@@ -159,14 +160,29 @@ static void poll_spurious_irqs(unsigned +@@ -159,14 +162,33 @@ static void poll_spurious_irqs(unsigned if (!(state & IRQS_SPURIOUS_DISABLED)) continue; @@ -183,19 +123,23 @@ Make it less chatty. Josh Boyer + /* We end up here with a disabled spurious interrupt. + desc->irqs_unhandled now tracks the number of times + the interrupt has been polled */ -+ -+ irq = desc->irq_data.irq; -+ if (desc->irqs_unhandled < 100) { /* 1 second delay with poll frequency 100 Hz */ ++ if (irq_poll_and_retry) { ++ if (desc->irqs_unhandled < 100) { /* 1 second delay with poll frequency 100 Hz */ ++ local_irq_disable(); ++ try_one_irq(i, desc, true); ++ local_irq_enable(); ++ desc->irqs_unhandled++; ++ poll_again = 1; ++ } else { ++ irq_enable(desc); /* Reenable the interrupt line */ ++ desc->depth--; ++ desc->istate &= (~IRQS_SPURIOUS_DISABLED); ++ desc->irqs_unhandled = 0; ++ } ++ } else { + local_irq_disable(); + try_one_irq(i, desc, true); + local_irq_enable(); -+ desc->irqs_unhandled++; -+ poll_again = 1; -+ } else { -+ irq_enable(desc); /* Reenable the interrupt line */ -+ desc->depth--; -+ desc->istate &= (~IRQS_SPURIOUS_DISABLED); -+ desc->irqs_unhandled = 0; + } } + if (poll_again) @@ -208,7 +152,7 @@ Make it less chatty. Josh Boyer } static inline int bad_action_ret(irqreturn_t action_ret) -@@ -177,11 +193,19 @@ static inline int bad_action_ret(irqretu +@@ -177,11 +199,19 @@ static inline int bad_action_ret(irqretu } /* @@ -230,7 +174,7 @@ Make it less chatty. Josh Boyer * functioning device sharing an IRQ with the failing one) */ static void -@@ -302,19 +326,19 @@ void note_interrupt(unsigned int irq, st +@@ -302,19 +332,24 @@ void note_interrupt(unsigned int irq, st } desc->irq_count++; @@ -242,15 +186,46 @@ Make it less chatty. Josh Boyer - if (unlikely(desc->irqs_unhandled > 99900)) { + if (unlikely(desc->irqs_unhandled >= 9)) { /* - * The interrupt is stuck +- * The interrupt is stuck ++ * The interrupt might be stuck */ - __report_bad_irq(irq, desc, action_ret); -+ /* __report_bad_irq(irq, desc, action_ret); */ ++ if (!irq_poll_and_retry) { ++ __report_bad_irq(irq, desc, action_ret); ++ printk(KERN_EMERG "Disabling IRQ %d\n", irq); ++ } else { ++ printk(KERN_INFO "IRQ %d might be stuck. Polling\n", ++ irq); ++ } /* * Now kill the IRQ */ - printk(KERN_EMERG "Disabling IRQ #%d\n", irq); -+ printk(KERN_EMERG "Disabling IRQ %d\n", irq); desc->istate |= IRQS_SPURIOUS_DISABLED; desc->depth++; irq_disable(desc); +--- linux-2.6.orig/drivers/pci/quirks.c ++++ linux-2.6/drivers/pci/quirks.c +@@ -1677,6 +1677,22 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm); + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm); + ++/* ASM108x transparent PCI bridges apparently have broken IRQ deassert ++ * handling. This causes interrupts to get "stuck" and eventually disabled. ++ * However, the interrupts are often shared and disabling them is fairly bad. ++ * It's been somewhat successful to switch to polling mode and retry after ++ * a bit, so let's do that. ++ */ ++extern int irq_poll_and_retry; ++static void quirk_asm108x_poll_interrupts(struct pci_dev *dev) ++{ ++ dev_info(&dev->dev, "Buggy bridge found [%04x:%04x]\n", ++ dev->vendor, dev->device); ++ dev_info(&dev->dev, "Stuck interrupts will be polled and retried\n"); ++ irq_poll_and_retry = 1; ++} ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_asm108x_poll_interrupts); ++ + #ifdef CONFIG_X86_IO_APIC + /* + * Boot interrupts on some chipsets cannot be turned off. For these chipsets, From 2a92931ecc252e670c4387d26595d5a32d4391b0 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 15 Mar 2012 14:30:58 -0500 Subject: [PATCH 337/397] CVE-2012-1179 fix pmd_bad() triggering in code paths holding mmap_sem read mode --- kernel.spec | 13 +- mm-thp-fix-pmd_bad-triggering.patch | 447 ++++++++++++++++++++++++++++ 2 files changed, 458 insertions(+), 2 deletions(-) create mode 100644 mm-thp-fix-pmd_bad-triggering.patch diff --git a/kernel.spec b/kernel.spec index 2d5fc91f3..22455d88e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -720,6 +720,9 @@ Patch21104: sony-laptop-Enable-keyboard-backlight-by-default.patch # Disable threading in hibernate compression Patch21105: disable-threading-in-compression-for-hibernate.patch +#rhbz 803809 CVE-2012-1179 +Patch21106: mm-thp-fix-pmd_bad-triggering.patch + Patch21110: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch Patch21200: unhandled-irqs-switch-to-polling.patch @@ -1337,12 +1340,15 @@ ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch #Disable threading in hibernate compression ApplyPatch disable-threading-in-compression-for-hibernate.patch -ApplyPatch unhandled-irqs-switch-to-polling.patch +# ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch ApplyPatch x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch +#rhbz 803809 CVE-2012-1179 +ApplyPatch mm-thp-fix-pmd_bad-triggering.patch + # END OF PATCH APPLICATIONS %endif @@ -1990,6 +1996,9 @@ fi # and build. %changelog +* Thu Mar 15 2012 Justin M. Forbes - 2.6.42.10-3 +- CVE-2012-1179 fix pmd_bad() triggering in code paths holding mmap_sem read mode (rhbz 803809) + * Wed Mar 14 2012 Josh Boyer - Fixup irqpoll patch to only activate on machines with ASM108x PCI bridge diff --git a/mm-thp-fix-pmd_bad-triggering.patch b/mm-thp-fix-pmd_bad-triggering.patch new file mode 100644 index 000000000..3af9d2e2d --- /dev/null +++ b/mm-thp-fix-pmd_bad-triggering.patch @@ -0,0 +1,447 @@ +In some cases it may happen that pmd_none_or_clear_bad() is called +with the mmap_sem hold in read mode. In those cases the huge page +faults can allocate hugepmds under pmd_none_or_clear_bad() and that +can trigger a false positive from pmd_bad() that will not like to see +a pmd materializing as trans huge. + +It's not khugepaged the problem, khugepaged holds the mmap_sem in +write mode (and all those sites must hold the mmap_sem in read mode to +prevent pagetables to go away from under them, during code review it +seems vm86 mode on 32bit kernels requires that too unless it's +restricted to 1 thread per process or UP builds). The race is only +with the huge pagefaults that can convert a pmd_none() into a +pmd_trans_huge(). + +Effectively all these pmd_none_or_clear_bad() sites running with +mmap_sem in read mode are somewhat speculative with the page faults, +and the result is always undefined when they run simultaneously. This +is probably why it wasn't common to run into this. For example if the +madvise(MADV_DONTNEED) runs zap_page_range() shortly before the page +fault, the hugepage will not be zapped, if the page fault runs first +it will be zapped. + +Altering pmd_bad() not to error out if it finds hugepmds won't be +enough to fix this, because zap_pmd_range would then proceed to call +zap_pte_range (which would be incorrect if the pmd become a +pmd_trans_huge()). + +The simplest way to fix this is to read the pmd in the local stack +(regardless of what we read, no need of actual CPU barriers, only +compiler barrier needed), and be sure it is not changing under the +code that computes its value. Even if the real pmd is changing under +the value we hold on the stack, we don't care. If we actually end up +in zap_pte_range it means the pmd was not none already and it was not +huge, and it can't become huge from under us (khugepaged locking +explained above). + +All we need is to enforce that there is no way anymore that in a code +path like below, pmd_trans_huge can be false, but +pmd_none_or_clear_bad can run into a hugepmd. The overhead of a +barrier() is just a compiler tweak and should not be measurable (I +only added it for THP builds). I don't exclude different compiler +versions may have prevented the race too by caching the value of *pmd +on the stack (that hasn't been verified, but it wouldn't be impossible +considering pmd_none_or_clear_bad, pmd_bad, pmd_trans_huge, pmd_none +are all inlines and there's no external function called in between +pmd_trans_huge and pmd_none_or_clear_bad). + + if (pmd_trans_huge(*pmd)) { + if (next-addr != HPAGE_PMD_SIZE) { + VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem)); + split_huge_page_pmd(vma->vm_mm, pmd); + } else if (zap_huge_pmd(tlb, vma, pmd, addr)) + continue; + /* fall through */ + } + if (pmd_none_or_clear_bad(pmd)) + +Because this race condition could be exercised without special +privileges this was reported in CVE-2012-1179. + +The race was identified and fully explained by Ulrich who debugged it. +I'm quoting his accurate explanation below, for reference. + +====== start quote ======= + mapcount 0 page_mapcount 1 + kernel BUG at mm/huge_memory.c:1384! + +At some point prior to the panic, a "bad pmd ..." message similar to the +following is logged on the console: + + mm/memory.c:145: bad pmd ffff8800376e1f98(80000000314000e7). + +The "bad pmd ..." message is logged by pmd_clear_bad() before it clears +the page's PMD table entry. + + 143 void pmd_clear_bad(pmd_t *pmd) + 144 { +-> 145 pmd_ERROR(*pmd); + 146 pmd_clear(pmd); + 147 } + +After the PMD table entry has been cleared, there is an inconsistency +between the actual number of PMD table entries that are mapping the page +and the page's map count (_mapcount field in struct page). When the page +is subsequently reclaimed, __split_huge_page() detects this inconsistency. + + 1381 if (mapcount != page_mapcount(page)) + 1382 printk(KERN_ERR "mapcount %d page_mapcount %d\n", + 1383 mapcount, page_mapcount(page)); +-> 1384 BUG_ON(mapcount != page_mapcount(page)); + +The root cause of the problem is a race of two threads in a multithreaded +process. Thread B incurs a page fault on a virtual address that has never +been accessed (PMD entry is zero) while Thread A is executing an madvise() +system call on a virtual address within the same 2 MB (huge page) range. + + virtual address space + .---------------------. + | | + | | + .-|---------------------| + | | | + | | |<-- B(fault) + | | | + 2 MB | |/////////////////////|-. + huge < |/////////////////////| > A(range) + page | |/////////////////////|-' + | | | + | | | + '-|---------------------| + | | + | | + '---------------------' + +- Thread A is executing an madvise(..., MADV_DONTNEED) system call + on the virtual address range "A(range)" shown in the picture. + +sys_madvise + // Acquire the semaphore in shared mode. + down_read(¤t->mm->mmap_sem) + ... + madvise_vma + switch (behavior) + case MADV_DONTNEED: + madvise_dontneed + zap_page_range + unmap_vmas + unmap_page_range + zap_pud_range + zap_pmd_range + // + // Assume that this huge page has never been accessed. + // I.e. content of the PMD entry is zero (not mapped). + // + if (pmd_trans_huge(*pmd)) { + // We don't get here due to the above assumption. + } + // + // Assume that Thread B incurred a page fault and + .---------> // sneaks in here as shown below. + | // + | if (pmd_none_or_clear_bad(pmd)) + | { + | if (unlikely(pmd_bad(*pmd))) + | pmd_clear_bad + | { + | pmd_ERROR + | // Log "bad pmd ..." message here. + | pmd_clear + | // Clear the page's PMD entry. + | // Thread B incremented the map count + | // in page_add_new_anon_rmap(), but + | // now the page is no longer mapped + | // by a PMD entry (-> inconsistency). + | } + | } + | + v +- Thread B is handling a page fault on virtual address "B(fault)" shown + in the picture. + +... +do_page_fault + __do_page_fault + // Acquire the semaphore in shared mode. + down_read_trylock(&mm->mmap_sem) + ... + handle_mm_fault + if (pmd_none(*pmd) && transparent_hugepage_enabled(vma)) + // We get here due to the above assumption (PMD entry is zero). + do_huge_pmd_anonymous_page + alloc_hugepage_vma + // Allocate a new transparent huge page here. + ... + __do_huge_pmd_anonymous_page + ... + spin_lock(&mm->page_table_lock) + ... + page_add_new_anon_rmap + // Here we increment the page's map count (starts at -1). + atomic_set(&page->_mapcount, 0) + set_pmd_at + // Here we set the page's PMD entry which will be cleared + // when Thread A calls pmd_clear_bad(). + ... + spin_unlock(&mm->page_table_lock) + +The mmap_sem does not prevent the race because both threads are acquiring +it in shared mode (down_read). Thread B holds the page_table_lock while +the page's map count and PMD table entry are updated. However, Thread A +does not synchronize on that lock. +====== end quote ======= + +Reported-by: Ulrich Obergfell +Signed-off-by: Andrea Arcangeli +--- + arch/x86/kernel/vm86_32.c | 2 + + fs/proc/task_mmu.c | 9 ++++++ + include/asm-generic/pgtable.h | 57 +++++++++++++++++++++++++++++++++++++++++ + mm/memcontrol.c | 4 +++ + mm/memory.c | 14 ++++++++-- + mm/mempolicy.c | 2 +- + mm/mincore.c | 2 +- + mm/pagewalk.c | 2 +- + mm/swapfile.c | 4 +-- + 9 files changed, 87 insertions(+), 9 deletions(-) + +diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c +index b466cab..328cb37 100644 +--- a/arch/x86/kernel/vm86_32.c ++++ b/arch/x86/kernel/vm86_32.c +@@ -172,6 +172,7 @@ static void mark_screen_rdonly(struct mm_struct *mm) + spinlock_t *ptl; + int i; + ++ down_write(&mm->mmap_sem); + pgd = pgd_offset(mm, 0xA0000); + if (pgd_none_or_clear_bad(pgd)) + goto out; +@@ -190,6 +191,7 @@ static void mark_screen_rdonly(struct mm_struct *mm) + } + pte_unmap_unlock(pte, ptl); + out: ++ up_write(&mm->mmap_sem); + flush_tlb(); + } + +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index 7dcd2a2..3efa725 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -409,6 +409,9 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, + } else { + spin_unlock(&walk->mm->page_table_lock); + } ++ ++ if (pmd_trans_unstable(pmd)) ++ return 0; + /* + * The mmap_sem held all the way back in m_start() is what + * keeps khugepaged out of here and from collapsing things +@@ -507,6 +510,8 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr, + struct page *page; + + split_huge_page_pmd(walk->mm, pmd); ++ if (pmd_trans_unstable(pmd)) ++ return 0; + + pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); + for (; addr != end; pte++, addr += PAGE_SIZE) { +@@ -670,6 +675,8 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, + int err = 0; + + split_huge_page_pmd(walk->mm, pmd); ++ if (pmd_trans_unstable(pmd)) ++ return 0; + + /* find the first VMA at or above 'addr' */ + vma = find_vma(walk->mm, addr); +@@ -961,6 +968,8 @@ static int gather_pte_stats(pmd_t *pmd, unsigned long addr, + spin_unlock(&walk->mm->page_table_lock); + } + ++ if (pmd_trans_unstable(pmd)) ++ return 0; + orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); + do { + struct page *page = can_gather_numa_stats(*pte, md->vma, addr); +diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h +index 76bff2b..10f8291 100644 +--- a/include/asm-generic/pgtable.h ++++ b/include/asm-generic/pgtable.h +@@ -443,6 +443,63 @@ static inline int pmd_write(pmd_t pmd) + #endif /* __HAVE_ARCH_PMD_WRITE */ + #endif + ++/* ++ * This function is meant to be used by sites walking pagetables with ++ * the mmap_sem hold in read mode to protect against MADV_DONTNEED and ++ * transhuge page faults. MADV_DONTNEED can convert a transhuge pmd ++ * into a null pmd and the transhuge page fault can convert a null pmd ++ * into an hugepmd or into a regular pmd (if the hugepage allocation ++ * fails). While holding the mmap_sem in read mode the pmd becomes ++ * stable and stops changing under us only if it's not null and not a ++ * transhuge pmd. When those races occurs and this function makes a ++ * difference vs the standard pmd_none_or_clear_bad, the result is ++ * undefined so behaving like if the pmd was none is safe (because it ++ * can return none anyway). The compiler level barrier() is critically ++ * important to compute the two checks atomically on the same pmdval. ++ */ ++static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) ++{ ++ /* depend on compiler for an atomic pmd read */ ++ pmd_t pmdval = *pmd; ++ /* ++ * The barrier will stabilize the pmdval in a register or on ++ * the stack so that it will stop changing under the code. ++ */ ++#ifdef CONFIG_TRANSPARENT_HUGEPAGE ++ barrier(); ++#endif ++ if (pmd_none(pmdval)) ++ return 1; ++ if (unlikely(pmd_bad(pmdval))) { ++ if (!pmd_trans_huge(pmdval)) ++ pmd_clear_bad(pmd); ++ return 1; ++ } ++ return 0; ++} ++ ++/* ++ * This is a noop if Transparent Hugepage Support is not built into ++ * the kernel. Otherwise it is equivalent to ++ * pmd_none_or_trans_huge_or_clear_bad(), and shall only be called in ++ * places that already verified the pmd is not none and they want to ++ * walk ptes while holding the mmap sem in read mode (write mode don't ++ * need this). If THP is not enabled, the pmd can't go away under the ++ * code even if MADV_DONTNEED runs, but if THP is enabled we need to ++ * run a pmd_trans_unstable before walking the ptes after ++ * split_huge_page_pmd returns (because it may have run when the pmd ++ * become null, but then a page fault can map in a THP and not a ++ * regular page). ++ */ ++static inline int pmd_trans_unstable(pmd_t *pmd) ++{ ++#ifdef CONFIG_TRANSPARENT_HUGEPAGE ++ return pmd_none_or_trans_huge_or_clear_bad(pmd); ++#else ++ return 0; ++#endif ++} ++ + #endif /* !__ASSEMBLY__ */ + + #endif /* _ASM_GENERIC_PGTABLE_H */ +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index d0e57a3..67b0578 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -5193,6 +5193,8 @@ static int mem_cgroup_count_precharge_pte_range(pmd_t *pmd, + spinlock_t *ptl; + + split_huge_page_pmd(walk->mm, pmd); ++ if (pmd_trans_unstable(pmd)) ++ return 0; + + pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); + for (; addr != end; pte++, addr += PAGE_SIZE) +@@ -5355,6 +5357,8 @@ static int mem_cgroup_move_charge_pte_range(pmd_t *pmd, + spinlock_t *ptl; + + split_huge_page_pmd(walk->mm, pmd); ++ if (pmd_trans_unstable(pmd)) ++ return 0; + retry: + pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); + for (; addr != end; addr += PAGE_SIZE) { +diff --git a/mm/memory.c b/mm/memory.c +index fa2f04e..e3090fc 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -1251,12 +1251,20 @@ static inline unsigned long zap_pmd_range(struct mmu_gather *tlb, + VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem)); + split_huge_page_pmd(vma->vm_mm, pmd); + } else if (zap_huge_pmd(tlb, vma, pmd)) +- continue; ++ goto next; + /* fall through */ + } +- if (pmd_none_or_clear_bad(pmd)) +- continue; ++ /* ++ * Here there can be other concurrent MADV_DONTNEED or ++ * trans huge page faults running, and if the pmd is ++ * none or trans huge it can change under us. This is ++ * because MADV_DONTNEED holds the mmap_sem in read ++ * mode. ++ */ ++ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) ++ goto next; + next = zap_pte_range(tlb, vma, pmd, addr, next, details); ++ next: + cond_resched(); + } while (pmd++, addr = next, addr != end); + +diff --git a/mm/mempolicy.c b/mm/mempolicy.c +index 47296fe..0a37570 100644 +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -512,7 +512,7 @@ static inline int check_pmd_range(struct vm_area_struct *vma, pud_t *pud, + do { + next = pmd_addr_end(addr, end); + split_huge_page_pmd(vma->vm_mm, pmd); +- if (pmd_none_or_clear_bad(pmd)) ++ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) + continue; + if (check_pte_range(vma, pmd, addr, next, nodes, + flags, private)) +diff --git a/mm/mincore.c b/mm/mincore.c +index 636a868..936b4ce 100644 +--- a/mm/mincore.c ++++ b/mm/mincore.c +@@ -164,7 +164,7 @@ static void mincore_pmd_range(struct vm_area_struct *vma, pud_t *pud, + } + /* fall through */ + } +- if (pmd_none_or_clear_bad(pmd)) ++ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) + mincore_unmapped_range(vma, addr, next, vec); + else + mincore_pte_range(vma, pmd, addr, next, vec); +diff --git a/mm/pagewalk.c b/mm/pagewalk.c +index 2f5cf10..aa9701e 100644 +--- a/mm/pagewalk.c ++++ b/mm/pagewalk.c +@@ -59,7 +59,7 @@ again: + continue; + + split_huge_page_pmd(walk->mm, pmd); +- if (pmd_none_or_clear_bad(pmd)) ++ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) + goto again; + err = walk_pte_range(pmd, addr, next, walk); + if (err) +diff --git a/mm/swapfile.c b/mm/swapfile.c +index d999f09..f31b29d 100644 +--- a/mm/swapfile.c ++++ b/mm/swapfile.c +@@ -932,9 +932,7 @@ static inline int unuse_pmd_range(struct vm_area_struct *vma, pud_t *pud, + pmd = pmd_offset(pud, addr); + do { + next = pmd_addr_end(addr, end); +- if (unlikely(pmd_trans_huge(*pmd))) +- continue; +- if (pmd_none_or_clear_bad(pmd)) ++ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) + continue; + ret = unuse_pte_range(vma, pmd, addr, next, entry, page); + if (ret) + +-- +To unsubscribe, send a message with 'unsubscribe linux-mm' in +the body to majordomo@kvack.org. For more info on Linux MM, +see: http://www.linux-mm.org/ . +Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ +Don't email: email@kvack.org From e8229fb9d20c05c37a0ab0b6f985d5aa65d602ec Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 16 Mar 2012 07:58:36 -0400 Subject: [PATCH 338/397] Fixup irqpoll patch to really not impact machines without ASM108x bridges (rhbz 800520) WITH FEELING THIS TIME --- kernel.spec | 7 +++++-- unhandled-irqs-switch-to-polling.patch | 25 +++++++++++++++++++++---- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/kernel.spec b/kernel.spec index 22455d88e..915f095c7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -1340,7 +1340,7 @@ ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch #Disable threading in hibernate compression ApplyPatch disable-threading-in-compression-for-hibernate.patch -# ApplyPatch unhandled-irqs-switch-to-polling.patch +ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch @@ -1996,6 +1996,9 @@ fi # and build. %changelog +* Fri Mar 16 2012 Josh Boyer +- Fix irqpoll patch to really only apply for ASM108x machines (rhbz 800520) + * Thu Mar 15 2012 Justin M. Forbes - 2.6.42.10-3 - CVE-2012-1179 fix pmd_bad() triggering in code paths holding mmap_sem read mode (rhbz 803809) diff --git a/unhandled-irqs-switch-to-polling.patch b/unhandled-irqs-switch-to-polling.patch index 39169ba96..2f25cda6f 100644 --- a/unhandled-irqs-switch-to-polling.patch +++ b/unhandled-irqs-switch-to-polling.patch @@ -174,17 +174,34 @@ Josh Boyer * functioning device sharing an IRQ with the failing one) */ static void -@@ -302,19 +332,24 @@ void note_interrupt(unsigned int irq, st +@@ -269,6 +299,8 @@ try_misrouted_irq(unsigned int irq, stru + void note_interrupt(unsigned int irq, struct irq_desc *desc, + irqreturn_t action_ret) + { ++ int unhandled_thresh = 999000; ++ + if (desc->istate & IRQS_POLL_INPROGRESS) + return; + +@@ -302,19 +334,31 @@ void note_interrupt(unsigned int irq, st } desc->irq_count++; - if (likely(desc->irq_count < 100000)) -+ if (likely(desc->irq_count < 10)) - return; +- return; ++ if (!irq_poll_and_retry) ++ if (likely(desc->irq_count < 100000)) ++ return; ++ else ++ if (likely(desc->irq_count < 10)) ++ return; desc->irq_count = 0; - if (unlikely(desc->irqs_unhandled > 99900)) { -+ if (unlikely(desc->irqs_unhandled >= 9)) { ++ if (irq_poll_and_retry) ++ unhandled_thresh = 9; ++ ++ if (unlikely(desc->irqs_unhandled >= unhandled_thresh)) { /* - * The interrupt is stuck + * The interrupt might be stuck From 262c90838526b8ab4f808d72008d8fea7f393089 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 16 Mar 2012 13:18:44 -0500 Subject: [PATCH 339/397] re-enable threading on hibernate compression/decompressio --- ...threading-in-compression-for-hibernate.patch | 17 ----------------- kernel.spec | 9 +++------ 2 files changed, 3 insertions(+), 23 deletions(-) delete mode 100644 disable-threading-in-compression-for-hibernate.patch diff --git a/disable-threading-in-compression-for-hibernate.patch b/disable-threading-in-compression-for-hibernate.patch deleted file mode 100644 index 685c294ef..000000000 --- a/disable-threading-in-compression-for-hibernate.patch +++ /dev/null @@ -1,17 +0,0 @@ -In attempt to find the cause of some of the hibernate issues we are seeing, -turn off threading for compression. - -Signed-off-by: Justin M. Forbes - -diff -ruNp a/kernel/power/swap.c b/kernel/power/swap.c ---- a/kernel/power/swap.c 2012-03-02 13:52:27.777485028 -0600 -+++ b/kernel/power/swap.c 2012-03-02 14:05:20.168115129 -0600 -@@ -401,7 +401,7 @@ static int swap_writer_finish(struct swa - #define LZO_CMP_SIZE (LZO_CMP_PAGES * PAGE_SIZE) - - /* Maximum number of threads for compression/decompression. */ --#define LZO_THREADS 3 -+#define LZO_THREADS 1 - - /* Maximum number of pages for read buffering. */ - #define LZO_READ_PAGES (MAP_PAGE_ENTRIES * 8) diff --git a/kernel.spec b/kernel.spec index 915f095c7..fd5f6075c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -717,9 +717,6 @@ Patch21102: ACPICA-Fix-regression-in-FADT-revision-checks.patch #rhbz 728478 Patch21104: sony-laptop-Enable-keyboard-backlight-by-default.patch -# Disable threading in hibernate compression -Patch21105: disable-threading-in-compression-for-hibernate.patch - #rhbz 803809 CVE-2012-1179 Patch21106: mm-thp-fix-pmd_bad-triggering.patch @@ -1337,9 +1334,6 @@ ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch #rhbz 728478 ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch -#Disable threading in hibernate compression -ApplyPatch disable-threading-in-compression-for-hibernate.patch - ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch @@ -1996,6 +1990,9 @@ fi # and build. %changelog +* Fri Mar 16 2012 Justin M. Forbes +- re-enable threading on hibernate compression/decompression + * Fri Mar 16 2012 Josh Boyer - Fix irqpoll patch to really only apply for ASM108x machines (rhbz 800520) From bf487c0089c936fada89fd35129fc61e91e6fdf5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Mar 2012 08:44:32 -0400 Subject: [PATCH 340/397] mac80211: fix possible tid_rx->reorder_timer use after free from Stanislaw Gruska (rhbz 804007) --- kernel.spec | 12 +++++- ...-tid_rx-reorder_timer-use-after-free.patch | 42 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch diff --git a/kernel.spec b/kernel.spec index fd5f6075c..b8014c175 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -724,6 +724,9 @@ Patch21110: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch Patch21200: unhandled-irqs-switch-to-polling.patch +#rhbz 804007 +Patch21305: mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch + Patch22000: weird-root-dentry-name-debug.patch %endif @@ -1334,6 +1337,9 @@ ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch #rhbz 728478 ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch +#rhbz 804007 +ApplyPatch mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch + ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch @@ -1990,6 +1996,10 @@ fi # and build. %changelog +* Tue Mar 20 2012 Josh Boyer +- mac80211: fix possible tid_rx->reorder_timer use after free + from Stanislaw Gruska (rhbz 804007) + * Fri Mar 16 2012 Justin M. Forbes - re-enable threading on hibernate compression/decompression diff --git a/mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch b/mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch new file mode 100644 index 000000000..accda8afc --- /dev/null +++ b/mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch @@ -0,0 +1,42 @@ +Is possible that we will arm the tid_rx->reorder_timer after +del_timer_sync() in ___ieee80211_stop_rx_ba_session(). We need to stop +timer after RCU grace period finish, so move it to +ieee80211_free_tid_rx(). Timer will not be armed again, as +rcu_dereference(sta->ampdu_mlme.tid_rx[tid]) will return NULL. + +Debug object detected problem with the following warning: +ODEBUG: free active (active state 0) object type: timer_list hint: sta_rx_agg_reorder_timer_expired+0x0/0xf0 [mac80211] + +Bug report (with all warning messages): +https://bugzilla.redhat.com/show_bug.cgi?id=804007 + +Reported-by: "jan p. springer" +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Gruszka +--- + net/mac80211/agg-rx.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c +index 1068f66..64d3ce5 100644 +--- a/net/mac80211/agg-rx.c ++++ b/net/mac80211/agg-rx.c +@@ -49,6 +49,8 @@ static void ieee80211_free_tid_rx(struct rcu_head *h) + container_of(h, struct tid_ampdu_rx, rcu_head); + int i; + ++ del_timer_sync(&tid_rx->reorder_timer); ++ + for (i = 0; i < tid_rx->buf_size; i++) + dev_kfree_skb(tid_rx->reorder_buf[i]); + kfree(tid_rx->reorder_buf); +@@ -91,7 +93,6 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, + tid, WLAN_BACK_RECIPIENT, reason); + + del_timer_sync(&tid_rx->session_timer); +- del_timer_sync(&tid_rx->reorder_timer); + + call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); + } +-- +1.7.1 From a5904b156a389e347cf19d56ecd2c829ec4e8a4e Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 20 Mar 2012 10:47:43 -0500 Subject: [PATCH 341/397] Linux 3.2.12 --- ...wner-group-name-string-when-doing-op.patch | 605 ++++++++++++++++++ SHLIB_BASE-randomization.patch | 69 ++ kernel.spec | 21 +- scsi-fix-sd_revalidate_disk-oops.patch | 116 ---- sources | 2 +- 5 files changed, 692 insertions(+), 121 deletions(-) create mode 100644 NFSv4-Save-the-owner-group-name-string-when-doing-op.patch create mode 100644 SHLIB_BASE-randomization.patch delete mode 100644 scsi-fix-sd_revalidate_disk-oops.patch diff --git a/NFSv4-Save-the-owner-group-name-string-when-doing-op.patch b/NFSv4-Save-the-owner-group-name-string-when-doing-op.patch new file mode 100644 index 000000000..610ec0113 --- /dev/null +++ b/NFSv4-Save-the-owner-group-name-string-when-doing-op.patch @@ -0,0 +1,605 @@ +ommit 6926afd1925a54a13684ebe05987868890665e2b +Author: Trond Myklebust +Date: Sat Jan 7 13:22:46 2012 -0500 + + NFSv4: Save the owner/group name string when doing open + + ...so that we can do the uid/gid mapping outside the asynchronous RPC + context. + This fixes a bug in the current NFSv4 atomic open code where the client + isn't able to determine what the true uid/gid fields of the file are, + (because the asynchronous nature of the OPEN call denies it the ability + to do an upcall) and so fills them with default values, marking the + inode as needing revalidation. + Unfortunately, in some cases, the VFS will do some additional sanity + checks on the file, and may override the server's decision to allow + the open because it sees the wrong owner/group fields. + + Signed-off-by: Trond Myklebust + +diff -up linux-3.2.noarch/fs/nfs/idmap.c.orig linux-3.2.noarch/fs/nfs/idmap.c +--- linux-3.2.noarch/fs/nfs/idmap.c.orig 2012-03-15 10:38:58.876578000 -0400 ++++ linux-3.2.noarch/fs/nfs/idmap.c 2012-03-15 10:51:10.344228000 -0400 +@@ -38,6 +38,89 @@ + #include + #include + #include ++#include ++ ++/** ++ * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields ++ * @fattr: fully initialised struct nfs_fattr ++ * @owner_name: owner name string cache ++ * @group_name: group name string cache ++ */ ++void nfs_fattr_init_names(struct nfs_fattr *fattr, ++ struct nfs4_string *owner_name, ++ struct nfs4_string *group_name) ++{ ++ fattr->owner_name = owner_name; ++ fattr->group_name = group_name; ++} ++ ++static void nfs_fattr_free_owner_name(struct nfs_fattr *fattr) ++{ ++ fattr->valid &= ~NFS_ATTR_FATTR_OWNER_NAME; ++ kfree(fattr->owner_name->data); ++} ++ ++static void nfs_fattr_free_group_name(struct nfs_fattr *fattr) ++{ ++ fattr->valid &= ~NFS_ATTR_FATTR_GROUP_NAME; ++ kfree(fattr->group_name->data); ++} ++ ++static bool nfs_fattr_map_owner_name(struct nfs_server *server, struct nfs_fattr *fattr) ++{ ++ struct nfs4_string *owner = fattr->owner_name; ++ __u32 uid; ++ ++ if (!(fattr->valid & NFS_ATTR_FATTR_OWNER_NAME)) ++ return false; ++ if (nfs_map_name_to_uid(server, owner->data, owner->len, &uid) == 0) { ++ fattr->uid = uid; ++ fattr->valid |= NFS_ATTR_FATTR_OWNER; ++ } ++ return true; ++} ++ ++static bool nfs_fattr_map_group_name(struct nfs_server *server, struct nfs_fattr *fattr) ++{ ++ struct nfs4_string *group = fattr->group_name; ++ __u32 gid; ++ ++ if (!(fattr->valid & NFS_ATTR_FATTR_GROUP_NAME)) ++ return false; ++ if (nfs_map_group_to_gid(server, group->data, group->len, &gid) == 0) { ++ fattr->gid = gid; ++ fattr->valid |= NFS_ATTR_FATTR_GROUP; ++ } ++ return true; ++} ++ ++/** ++ * nfs_fattr_free_names - free up the NFSv4 owner and group strings ++ * @fattr: a fully initialised nfs_fattr structure ++ */ ++void nfs_fattr_free_names(struct nfs_fattr *fattr) ++{ ++ if (fattr->valid & NFS_ATTR_FATTR_OWNER_NAME) ++ nfs_fattr_free_owner_name(fattr); ++ if (fattr->valid & NFS_ATTR_FATTR_GROUP_NAME) ++ nfs_fattr_free_group_name(fattr); ++} ++ ++/** ++ * nfs_fattr_map_and_free_names - map owner/group strings into uid/gid and free ++ * @server: pointer to the filesystem nfs_server structure ++ * @fattr: a fully initialised nfs_fattr structure ++ * ++ * This helper maps the cached NFSv4 owner/group strings in fattr into ++ * their numeric uid/gid equivalents, and then frees the cached strings. ++ */ ++void nfs_fattr_map_and_free_names(struct nfs_server *server, struct nfs_fattr *fattr) ++{ ++ if (nfs_fattr_map_owner_name(server, fattr)) ++ nfs_fattr_free_owner_name(fattr); ++ if (nfs_fattr_map_group_name(server, fattr)) ++ nfs_fattr_free_group_name(fattr); ++} + + static int nfs_map_string_to_numeric(const char *name, size_t namelen, __u32 *res) + { +diff -up linux-3.2.noarch/fs/nfs/inode.c.orig linux-3.2.noarch/fs/nfs/inode.c +--- linux-3.2.noarch/fs/nfs/inode.c.orig 2012-03-15 10:39:00.362624000 -0400 ++++ linux-3.2.noarch/fs/nfs/inode.c 2012-03-15 10:51:10.352227000 -0400 +@@ -1020,6 +1020,8 @@ void nfs_fattr_init(struct nfs_fattr *fa + fattr->valid = 0; + fattr->time_start = jiffies; + fattr->gencount = nfs_inc_attr_generation_counter(); ++ fattr->owner_name = NULL; ++ fattr->group_name = NULL; + } + + struct nfs_fattr *nfs_alloc_fattr(void) +diff -up linux-3.2.noarch/fs/nfs/nfs4proc.c.orig linux-3.2.noarch/fs/nfs/nfs4proc.c +--- linux-3.2.noarch/fs/nfs/nfs4proc.c.orig 2012-03-15 10:39:00.380629000 -0400 ++++ linux-3.2.noarch/fs/nfs/nfs4proc.c 2012-03-15 10:51:10.362231000 -0400 +@@ -52,6 +52,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -765,6 +766,8 @@ struct nfs4_opendata { + struct nfs_openres o_res; + struct nfs_open_confirmargs c_arg; + struct nfs_open_confirmres c_res; ++ struct nfs4_string owner_name; ++ struct nfs4_string group_name; + struct nfs_fattr f_attr; + struct nfs_fattr dir_attr; + struct dentry *dir; +@@ -788,6 +791,7 @@ static void nfs4_init_opendata_res(struc + p->o_res.server = p->o_arg.server; + nfs_fattr_init(&p->f_attr); + nfs_fattr_init(&p->dir_attr); ++ nfs_fattr_init_names(&p->f_attr, &p->owner_name, &p->group_name); + } + + static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, +@@ -819,6 +823,7 @@ static struct nfs4_opendata *nfs4_openda + p->o_arg.name = &dentry->d_name; + p->o_arg.server = server; + p->o_arg.bitmask = server->attr_bitmask; ++ p->o_arg.dir_bitmask = server->cache_consistency_bitmask; + p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; + if (flags & O_CREAT) { + u32 *s; +@@ -855,6 +860,7 @@ static void nfs4_opendata_free(struct kr + dput(p->dir); + dput(p->dentry); + nfs_sb_deactive(sb); ++ nfs_fattr_free_names(&p->f_attr); + kfree(p); + } + +@@ -1579,6 +1585,8 @@ static int _nfs4_recover_proc_open(struc + if (status != 0 || !data->rpc_done) + return status; + ++ nfs_fattr_map_and_free_names(NFS_SERVER(dir), &data->f_attr); ++ + nfs_refresh_inode(dir, o_res->dir_attr); + + if (o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { +@@ -1611,6 +1619,8 @@ static int _nfs4_proc_open(struct nfs4_o + return status; + } + ++ nfs_fattr_map_and_free_names(server, &data->f_attr); ++ + if (o_arg->open_flags & O_CREAT) { + update_changeattr(dir, &o_res->cinfo); + nfs_post_op_update_inode(dir, o_res->dir_attr); +diff -up linux-3.2.noarch/fs/nfs/nfs4xdr.c.orig linux-3.2.noarch/fs/nfs/nfs4xdr.c +--- linux-3.2.noarch/fs/nfs/nfs4xdr.c.orig 2012-03-15 10:38:54.054438000 -0400 ++++ linux-3.2.noarch/fs/nfs/nfs4xdr.c 2012-03-15 10:51:10.373231000 -0400 +@@ -2298,7 +2298,7 @@ static void nfs4_xdr_enc_open(struct rpc + encode_getfh(xdr, &hdr); + encode_getfattr(xdr, args->bitmask, &hdr); + encode_restorefh(xdr, &hdr); +- encode_getfattr(xdr, args->bitmask, &hdr); ++ encode_getfattr(xdr, args->dir_bitmask, &hdr); + encode_nops(&hdr); + } + +@@ -3791,7 +3791,8 @@ out_overflow: + } + + static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, +- const struct nfs_server *server, uint32_t *uid, int may_sleep) ++ const struct nfs_server *server, uint32_t *uid, ++ struct nfs4_string *owner_name) + { + uint32_t len; + __be32 *p; +@@ -3808,8 +3809,12 @@ static int decode_attr_owner(struct xdr_ + p = xdr_inline_decode(xdr, len); + if (unlikely(!p)) + goto out_overflow; +- if (!may_sleep) { +- /* do nothing */ ++ if (owner_name != NULL) { ++ owner_name->data = kmemdup(p, len, GFP_NOWAIT); ++ if (owner_name->data != NULL) { ++ owner_name->len = len; ++ ret = NFS_ATTR_FATTR_OWNER_NAME; ++ } + } else if (len < XDR_MAX_NETOBJ) { + if (nfs_map_name_to_uid(server, (char *)p, len, uid) == 0) + ret = NFS_ATTR_FATTR_OWNER; +@@ -3829,7 +3834,8 @@ out_overflow: + } + + static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, +- const struct nfs_server *server, uint32_t *gid, int may_sleep) ++ const struct nfs_server *server, uint32_t *gid, ++ struct nfs4_string *group_name) + { + uint32_t len; + __be32 *p; +@@ -3846,8 +3852,12 @@ static int decode_attr_group(struct xdr_ + p = xdr_inline_decode(xdr, len); + if (unlikely(!p)) + goto out_overflow; +- if (!may_sleep) { +- /* do nothing */ ++ if (group_name != NULL) { ++ group_name->data = kmemdup(p, len, GFP_NOWAIT); ++ if (group_name->data != NULL) { ++ group_name->len = len; ++ ret = NFS_ATTR_FATTR_GROUP_NAME; ++ } + } else if (len < XDR_MAX_NETOBJ) { + if (nfs_map_group_to_gid(server, (char *)p, len, gid) == 0) + ret = NFS_ATTR_FATTR_GROUP; +@@ -4284,7 +4294,7 @@ xdr_error: + + static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, + struct nfs_fattr *fattr, struct nfs_fh *fh, +- const struct nfs_server *server, int may_sleep) ++ const struct nfs_server *server) + { + int status; + umode_t fmode = 0; +@@ -4351,12 +4361,12 @@ static int decode_getfattr_attrs(struct + goto xdr_error; + fattr->valid |= status; + +- status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, may_sleep); ++ status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, fattr->owner_name); + if (status < 0) + goto xdr_error; + fattr->valid |= status; + +- status = decode_attr_group(xdr, bitmap, server, &fattr->gid, may_sleep); ++ status = decode_attr_group(xdr, bitmap, server, &fattr->gid, fattr->group_name); + if (status < 0) + goto xdr_error; + fattr->valid |= status; +@@ -4397,7 +4407,7 @@ xdr_error: + } + + static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, +- struct nfs_fh *fh, const struct nfs_server *server, int may_sleep) ++ struct nfs_fh *fh, const struct nfs_server *server) + { + __be32 *savep; + uint32_t attrlen, +@@ -4416,7 +4426,7 @@ static int decode_getfattr_generic(struc + if (status < 0) + goto xdr_error; + +- status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server, may_sleep); ++ status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server); + if (status < 0) + goto xdr_error; + +@@ -4427,9 +4437,9 @@ xdr_error: + } + + static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, +- const struct nfs_server *server, int may_sleep) ++ const struct nfs_server *server) + { +- return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep); ++ return decode_getfattr_generic(xdr, fattr, NULL, server); + } + + /* +@@ -5710,8 +5720,7 @@ static int nfs4_xdr_dec_open_downgrade(s + status = decode_open_downgrade(xdr, res); + if (status != 0) + goto out; +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -5737,8 +5746,7 @@ static int nfs4_xdr_dec_access(struct rp + status = decode_access(xdr, res); + if (status != 0) + goto out; +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -5767,8 +5775,7 @@ static int nfs4_xdr_dec_lookup(struct rp + status = decode_getfh(xdr, res->fh); + if (status) + goto out; +- status = decode_getfattr(xdr, res->fattr, res->server +- ,!RPC_IS_ASYNC(rqstp->rq_task)); ++ status = decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -5794,8 +5801,7 @@ static int nfs4_xdr_dec_lookup_root(stru + goto out; + status = decode_getfh(xdr, res->fh); + if (status == 0) +- status = decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ status = decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -5821,8 +5827,7 @@ static int nfs4_xdr_dec_remove(struct rp + status = decode_remove(xdr, &res->cinfo); + if (status) + goto out; +- decode_getfattr(xdr, res->dir_attr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->dir_attr, res->server); + out: + return status; + } +@@ -5855,14 +5860,12 @@ static int nfs4_xdr_dec_rename(struct rp + if (status) + goto out; + /* Current FH is target directory */ +- if (decode_getfattr(xdr, res->new_fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)) != 0) ++ if (decode_getfattr(xdr, res->new_fattr, res->server)) + goto out; + status = decode_restorefh(xdr); + if (status) + goto out; +- decode_getfattr(xdr, res->old_fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->old_fattr, res->server); + out: + return status; + } +@@ -5898,14 +5901,12 @@ static int nfs4_xdr_dec_link(struct rpc_ + * Note order: OP_LINK leaves the directory as the current + * filehandle. + */ +- if (decode_getfattr(xdr, res->dir_attr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)) != 0) ++ if (decode_getfattr(xdr, res->dir_attr, res->server)) + goto out; + status = decode_restorefh(xdr); + if (status) + goto out; +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -5937,14 +5938,12 @@ static int nfs4_xdr_dec_create(struct rp + status = decode_getfh(xdr, res->fh); + if (status) + goto out; +- if (decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)) != 0) ++ if (decode_getfattr(xdr, res->fattr, res->server)) + goto out; + status = decode_restorefh(xdr); + if (status) + goto out; +- decode_getfattr(xdr, res->dir_fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->dir_fattr, res->server); + out: + return status; + } +@@ -5976,8 +5975,7 @@ static int nfs4_xdr_dec_getattr(struct r + status = decode_putfh(xdr); + if (status) + goto out; +- status = decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ status = decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -6079,8 +6077,7 @@ static int nfs4_xdr_dec_close(struct rpc + * an ESTALE error. Shouldn't be a problem, + * though, since fattr->valid will remain unset. + */ +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -6111,13 +6108,11 @@ static int nfs4_xdr_dec_open(struct rpc_ + goto out; + if (decode_getfh(xdr, &res->fh) != 0) + goto out; +- if (decode_getfattr(xdr, res->f_attr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)) != 0) ++ if (decode_getfattr(xdr, res->f_attr, res->server) != 0) + goto out; + if (decode_restorefh(xdr) != 0) + goto out; +- decode_getfattr(xdr, res->dir_attr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->dir_attr, res->server); + out: + return status; + } +@@ -6165,8 +6160,7 @@ static int nfs4_xdr_dec_open_noattr(stru + status = decode_open(xdr, res); + if (status) + goto out; +- decode_getfattr(xdr, res->f_attr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->f_attr, res->server); + out: + return status; + } +@@ -6193,8 +6187,7 @@ static int nfs4_xdr_dec_setattr(struct r + status = decode_setattr(xdr); + if (status) + goto out; +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -6374,8 +6367,7 @@ static int nfs4_xdr_dec_write(struct rpc + if (status) + goto out; + if (res->fattr) +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + if (!status) + status = res->count; + out: +@@ -6404,8 +6396,7 @@ static int nfs4_xdr_dec_commit(struct rp + if (status) + goto out; + if (res->fattr) +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -6564,8 +6555,7 @@ static int nfs4_xdr_dec_delegreturn(stru + status = decode_delegreturn(xdr); + if (status != 0) + goto out; +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -6594,8 +6584,7 @@ static int nfs4_xdr_dec_fs_locations(str + goto out; + xdr_enter_page(xdr, PAGE_SIZE); + status = decode_getfattr(xdr, &res->fs_locations->fattr, +- res->fs_locations->server, +- !RPC_IS_ASYNC(req->rq_task)); ++ res->fs_locations->server); + out: + return status; + } +@@ -6844,8 +6833,7 @@ static int nfs4_xdr_dec_layoutcommit(str + status = decode_layoutcommit(xdr, rqstp, res); + if (status) + goto out; +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -6976,7 +6964,7 @@ int nfs4_decode_dirent(struct xdr_stream + goto out_overflow; + + if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, +- entry->server, 1) < 0) ++ entry->server) < 0) + goto out_overflow; + if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) + entry->ino = entry->fattr->mounted_on_fileid; +diff -up linux-3.2.noarch/include/linux/nfs_idmap.h.orig linux-3.2.noarch/include/linux/nfs_idmap.h +--- linux-3.2.noarch/include/linux/nfs_idmap.h.orig 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.noarch/include/linux/nfs_idmap.h 2012-03-15 10:51:10.395228000 -0400 +@@ -66,6 +66,8 @@ struct idmap_msg { + /* Forward declaration to make this header independent of others */ + struct nfs_client; + struct nfs_server; ++struct nfs_fattr; ++struct nfs4_string; + + #ifdef CONFIG_NFS_USE_NEW_IDMAPPER + +@@ -97,6 +99,12 @@ void nfs_idmap_delete(struct nfs_client + + #endif /* CONFIG_NFS_USE_NEW_IDMAPPER */ + ++void nfs_fattr_init_names(struct nfs_fattr *fattr, ++ struct nfs4_string *owner_name, ++ struct nfs4_string *group_name); ++void nfs_fattr_free_names(struct nfs_fattr *); ++void nfs_fattr_map_and_free_names(struct nfs_server *, struct nfs_fattr *); ++ + int nfs_map_name_to_uid(const struct nfs_server *, const char *, size_t, __u32 *); + int nfs_map_group_to_gid(const struct nfs_server *, const char *, size_t, __u32 *); + int nfs_map_uid_to_name(const struct nfs_server *, __u32, char *, size_t); +diff -up linux-3.2.noarch/include/linux/nfs_xdr.h.orig linux-3.2.noarch/include/linux/nfs_xdr.h +--- linux-3.2.noarch/include/linux/nfs_xdr.h.orig 2012-03-15 10:38:54.464449000 -0400 ++++ linux-3.2.noarch/include/linux/nfs_xdr.h 2012-03-15 10:51:10.415229000 -0400 +@@ -18,6 +18,11 @@ + /* Forward declaration for NFS v3 */ + struct nfs4_secinfo_flavors; + ++struct nfs4_string { ++ unsigned int len; ++ char *data; ++}; ++ + struct nfs_fsid { + uint64_t major; + uint64_t minor; +@@ -61,6 +66,8 @@ struct nfs_fattr { + struct timespec pre_ctime; /* pre_op_attr.ctime */ + unsigned long time_start; + unsigned long gencount; ++ struct nfs4_string *owner_name; ++ struct nfs4_string *group_name; + }; + + #define NFS_ATTR_FATTR_TYPE (1U << 0) +@@ -85,6 +92,8 @@ struct nfs_fattr { + #define NFS_ATTR_FATTR_V4_REFERRAL (1U << 19) /* NFSv4 referral */ + #define NFS_ATTR_FATTR_MOUNTPOINT (1U << 20) /* Treat as mountpoint */ + #define NFS_ATTR_FATTR_MOUNTED_ON_FILEID (1U << 21) ++#define NFS_ATTR_FATTR_OWNER_NAME (1U << 22) ++#define NFS_ATTR_FATTR_GROUP_NAME (1U << 23) + + #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \ + | NFS_ATTR_FATTR_MODE \ +@@ -324,6 +333,7 @@ struct nfs_openargs { + const struct qstr * name; + const struct nfs_server *server; /* Needed for ID mapping */ + const u32 * bitmask; ++ const u32 * dir_bitmask; + __u32 claim; + struct nfs4_sequence_args seq_args; + }; +@@ -342,6 +352,8 @@ struct nfs_openres { + __u32 do_recall; + __u64 maxsize; + __u32 attrset[NFS4_BITMAP_SIZE]; ++ struct nfs4_string *owner; ++ struct nfs4_string *group_owner; + struct nfs4_sequence_res seq_res; + }; + +@@ -778,11 +790,6 @@ struct nfs3_getaclres { + struct posix_acl * acl_default; + }; + +-struct nfs4_string { +- unsigned int len; +- char *data; +-}; +- + #ifdef CONFIG_NFS_V4 + + typedef u64 clientid4; diff --git a/SHLIB_BASE-randomization.patch b/SHLIB_BASE-randomization.patch new file mode 100644 index 000000000..80e4d644b --- /dev/null +++ b/SHLIB_BASE-randomization.patch @@ -0,0 +1,69 @@ +diff -uNrp kernel-3.2.fc16.orig/arch/x86/mm/mmap.c kernel-3.2.fc16.new/arch/x86/mm/mmap.c +--- kernel-3.2.fc16.orig/arch/x86/mm/mmap.c 2012-03-19 16:47:03.495169091 -0400 ++++ kernel-3.2.fc16.new/arch/x86/mm/mmap.c 2012-03-19 16:50:03.574168052 -0400 +@@ -106,6 +106,10 @@ static unsigned long mmap_legacy_base(vo + return TASK_UNMAPPED_BASE + mmap_rnd(); + } + ++#ifdef CONFIG_X86_32 ++ #define SHLIB_BASE 0x00111000 ++#endif ++ + /* + * This function, called very early during the creation of a new + * process VM image, sets up which VM layout function to use: +@@ -126,8 +126,10 @@ void arch_pick_mmap_layout(struct mm_str + #ifdef CONFIG_X86_32 + if (!(current->personality & READ_IMPLIES_EXEC) + && !(__supported_pte_mask & _PAGE_NX) +- && mmap_is_ia32()) ++ && mmap_is_ia32()) { ++ mm->shlib_base = SHLIB_BASE + mmap_rnd(); + mm->get_unmapped_exec_area = arch_get_unmapped_exec_area; ++ } + #endif + mm->unmap_area = arch_unmap_area_topdown; + } +diff -uNrp kernel-3.2.fc16.orig/include/linux/mm_types.h kernel-3.2.fc16.new/include/linux/mm_types.h +--- kernel-3.2.fc16.orig/include/linux/mm_types.h 2012-03-19 16:46:47.382169153 -0400 ++++ kernel-3.2.fc16.new/include/linux/mm_types.h 2012-03-19 16:50:40.738168219 -0400 +@@ -300,6 +300,7 @@ struct mm_struct { + void (*unmap_area) (struct mm_struct *mm, unsigned long addr); + #endif + unsigned long mmap_base; /* base of mmap area */ ++ unsigned long shlib_base; /* base of lib map area (ASCII armour)*/ + unsigned long task_size; /* size of task vm space */ + unsigned long cached_hole_size; /* if non-zero, the largest hole below free_area_cache */ + unsigned long free_area_cache; /* first hole of size cached_hole_size or larger */ +diff -uNrp kernel-3.2.fc16.orig/mm/mmap.c kernel-3.2.fc16.new/mm/mmap.c +--- kernel-3.2.fc16.orig/mm/mmap.c 2012-03-19 16:46:15.791169274 -0400 ++++ kernel-3.2.fc16.new/mm/mmap.c 2012-03-19 16:51:37.351166875 -0400 +@@ -1594,8 +1594,6 @@ static bool should_randomize(void) + !(current->personality & ADDR_NO_RANDOMIZE); + } + +-#define SHLIB_BASE 0x00110000 +- + unsigned long + arch_get_unmapped_exec_area(struct file *filp, unsigned long addr0, + unsigned long len0, unsigned long pgoff, unsigned long flags) +@@ -1612,8 +1610,8 @@ arch_get_unmapped_exec_area(struct file + return addr; + + if (!addr) +- addr = !should_randomize() ? SHLIB_BASE : +- randomize_range(SHLIB_BASE, 0x01000000, len); ++ addr = !should_randomize() ? mm->shlib_base : ++ randomize_range(mm->shlib_base, 0x01000000, len); + + if (addr) { + addr = PAGE_ALIGN(addr); +@@ -1623,7 +1621,7 @@ arch_get_unmapped_exec_area(struct file + return addr; + } + +- addr = SHLIB_BASE; ++ addr = mm->shlib_base; + for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { + /* At this point: (!vma || addr < vma->vm_end). */ + if (TASK_SIZE - len < addr) diff --git a/kernel.spec b/kernel.spec index fd5f6075c..e28ce9288 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 4 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # Do we have a -stable update to apply? -%define stable_update 10 +%define stable_update 12 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -639,6 +639,7 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 Patch4000: NFSv4-Reduce-the-footprint-of-the-idmapper.patch Patch4001: NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch +Patch4003: NFSv4-Save-the-owner-group-name-string-when-doing-op.patch # patches headed upstream @@ -703,7 +704,6 @@ Patch21092: e1000e-Avoid-wrong-check-on-TX-hang.patch #rhbz 754518 #Patch21093: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch -Patch21093: scsi-fix-sd_revalidate_disk-oops.patch #rhbz 771058 Patch21100: msi-irq-sysfs-warning.patch @@ -720,6 +720,9 @@ Patch21104: sony-laptop-Enable-keyboard-backlight-by-default.patch #rhbz 803809 CVE-2012-1179 Patch21106: mm-thp-fix-pmd_bad-triggering.patch +#rhbz 804947 CVE-2012-1568 +Patch21107: SHLIB_BASE-randomization.patch + Patch21110: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch Patch21200: unhandled-irqs-switch-to-polling.patch @@ -1178,6 +1181,7 @@ ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 ApplyPatch NFSv4-Reduce-the-footprint-of-the-idmapper.patch ApplyPatch NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch +ApplyPatch NFSv4-Save-the-owner-group-name-string-when-doing-op.patch # USB @@ -1323,7 +1327,6 @@ ApplyPatch e1000e-Avoid-wrong-check-on-TX-hang.patch #rhbz 754518 #ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch -ApplyPatch scsi-fix-sd_revalidate_disk-oops.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch @@ -1343,6 +1346,9 @@ ApplyPatch x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch #rhbz 803809 CVE-2012-1179 ApplyPatch mm-thp-fix-pmd_bad-triggering.patch +#rhbz 804947 CVE-2012-1568 +ApplyPatch SHLIB_BASE-randomization.patch + # END OF PATCH APPLICATIONS %endif @@ -1990,6 +1996,13 @@ fi # and build. %changelog +* Tue Mar 20 2012 Justin M. Forbes 2.6.42.12-1 +- Linux 3.2.10 +- CVE-2012-1568 SHLIB_BASE randomization (rhbz 804947) + +* Mon Mar 19 2012 Steve Dickson +- NFSv4: Save the owner/group name string when doing open (bz 794780) + * Fri Mar 16 2012 Justin M. Forbes - re-enable threading on hibernate compression/decompression diff --git a/scsi-fix-sd_revalidate_disk-oops.patch b/scsi-fix-sd_revalidate_disk-oops.patch deleted file mode 100644 index defa240a2..000000000 --- a/scsi-fix-sd_revalidate_disk-oops.patch +++ /dev/null @@ -1,116 +0,0 @@ ---- linux-2.6.42.noarch/fs/partitions/check.c~ 2012-02-20 18:32:55.314253719 -0500 -+++ linux-2.6.42.noarch/fs/partitions/check.c 2012-02-20 18:34:46.509859745 -0500 -@@ -539,17 +539,11 @@ static bool disk_unlock_native_capacity( - } - } - --int rescan_partitions(struct gendisk *disk, struct block_device *bdev) -+static int drop_partitions(struct gendisk *disk, struct block_device *bdev) - { -- struct parsed_partitions *state = NULL; - struct disk_part_iter piter; - struct hd_struct *part; -- int p, highest, res; --rescan: -- if (state && !IS_ERR(state)) { -- kfree(state); -- state = NULL; -- } -+ int res; - - if (bdev->bd_part_count) - return -EBUSY; -@@ -562,6 +556,24 @@ rescan: - delete_partition(disk, part->partno); - disk_part_iter_exit(&piter); - -+ return 0; -+} -+ -+int rescan_partitions(struct gendisk *disk, struct block_device *bdev) -+{ -+ struct parsed_partitions *state = NULL; -+ struct hd_struct *part; -+ int p, highest, res; -+rescan: -+ if (state && !IS_ERR(state)) { -+ kfree(state); -+ state = NULL; -+ } -+ -+ res = drop_partitions(disk, bdev); -+ if (res) -+ return res; -+ - if (disk->fops->revalidate_disk) - disk->fops->revalidate_disk(disk); - check_disk_size_change(disk, bdev); -@@ -665,6 +677,26 @@ rescan: - return 0; - } - -+int invalidate_partitions(struct gendisk *disk, struct block_device *bdev) -+{ -+ int res; -+ -+ if (!bdev->bd_invalidated) -+ return 0; -+ -+ res = drop_partitions(disk, bdev); -+ if (res) -+ return res; -+ -+ set_capacity(disk, 0); -+ check_disk_size_change(disk, bdev); -+ bdev->bd_invalidated = 0; -+ /* tell userspace that the media / partition table may have changed */ -+ kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE); -+ -+ return 0; -+} -+ - unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p) - { - struct address_space *mapping = bdev->bd_inode->i_mapping; ---- linux-2.6.42.noarch/include/linux/genhd.h~ 2012-02-20 18:35:02.777802107 -0500 -+++ linux-2.6.42.noarch/include/linux/genhd.h 2012-02-20 18:35:13.873762792 -0500 -@@ -596,6 +596,7 @@ extern char *disk_name (struct gendisk * - - extern int disk_expand_part_tbl(struct gendisk *disk, int target); - extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); -+extern int invalidate_partitions(struct gendisk *disk, struct block_device *bdev); - extern struct hd_struct * __must_check add_partition(struct gendisk *disk, - int partno, sector_t start, - sector_t len, int flags, ---- linux-2.6.42.noarch/fs/block_dev.c~ 2012-02-20 18:35:24.890723757 -0500 -+++ linux-2.6.42.noarch/fs/block_dev.c 2012-02-20 18:36:25.166510197 -0500 -@@ -1159,8 +1159,12 @@ static int __blkdev_get(struct block_dev - * The latter is necessary to prevent ghost - * partitions on a removed medium. - */ -- if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM)) -- rescan_partitions(disk, bdev); -+ if (bdev->bd_invalidated) { -+ if (!ret) -+ rescan_partitions(disk, bdev); -+ else if (ret == -ENOMEDIUM) -+ invalidate_partitions(disk, bdev); -+ } - if (ret) - goto out_clear; - } else { -@@ -1190,8 +1194,12 @@ static int __blkdev_get(struct block_dev - if (bdev->bd_disk->fops->open) - ret = bdev->bd_disk->fops->open(bdev, mode); - /* the same as first opener case, read comment there */ -- if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM)) -- rescan_partitions(bdev->bd_disk, bdev); -+ if (bdev->bd_invalidated) { -+ if (!ret) -+ rescan_partitions(bdev->bd_disk, bdev); -+ else if (ret == -ENOMEDIUM) -+ invalidate_partitions(bdev->bd_disk, bdev); -+ } - if (ret) - goto out_unlock_bdev; - } diff --git a/sources b/sources index a003ef5f5..02f08ef39 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz -7481fa09f2efda915ed19a9da33a2e59 patch-3.2.10.xz +ee0ce13f2cb7f03a8cda0910fd0fa050 patch-3.2.12.xz From 5da4893716e920246e29f9e61c262e530a95bc38 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 20 Mar 2012 10:55:20 -0500 Subject: [PATCH 342/397] Fix merge date order --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index a14c6fcd7..1f9bfa263 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2006,7 +2006,7 @@ fi - Linux 3.2.10 - CVE-2012-1568 SHLIB_BASE randomization (rhbz 804947) -* Mon Mar 19 2012 Steve Dickson +* Tue Mar 20 2012 Steve Dickson - NFSv4: Save the owner/group name string when doing open (bz 794780) * Tue Mar 20 2012 Josh Boyer From db8452b1c571bc2f2bb3a7fa87976daf5c7daf13 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 26 Mar 2012 09:41:15 -0400 Subject: [PATCH 343/397] Linux 3.2.13 --- kernel.spec | 5 ++++- sources | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 1f9bfa263..02732d948 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # Do we have a -stable update to apply? -%define stable_update 12 +%define stable_update 13 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2002,6 +2002,9 @@ fi # and build. %changelog +* Mon Mar 26 2012 Dave Jones +- Linux 3.2.13 + * Tue Mar 20 2012 Justin M. Forbes 2.6.42.12-1 - Linux 3.2.10 - CVE-2012-1568 SHLIB_BASE randomization (rhbz 804947) diff --git a/sources b/sources index 02f08ef39..5bcdc8a35 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz ee0ce13f2cb7f03a8cda0910fd0fa050 patch-3.2.12.xz +687632bb0ba65439198ac60f2c02a8f2 patch-3.2.13.xz From f4908601bf08435bf05fea48d2dcea1494826bbc Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 29 Mar 2012 10:58:35 -0400 Subject: [PATCH 344/397] Drop __cpuinitdata on disable_nx for x86_32 (rhbz 808075) --- kernel.spec | 7 ++- ...cpuinitdata-for-disable_nx-on-x86_32.patch | 47 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch diff --git a/kernel.spec b/kernel.spec index 02732d948..23376de5e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -579,6 +579,7 @@ Patch09: linux-2.6-upstream-reverts.patch Patch100: taint-vbox.patch Patch160: linux-2.6-32bit-mmap-exec-randomization.patch Patch161: linux-2.6-i386-nx-emulation.patch +Patch162: nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch Patch350: force-version-2.6.patch @@ -1165,6 +1166,7 @@ ApplyPatch taint-vbox.patch # ApplyPatch linux-2.6-32bit-mmap-exec-randomization.patch ApplyPatch linux-2.6-i386-nx-emulation.patch +ApplyPatch nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch # # bugfixes to drivers and filesystems @@ -2002,6 +2004,9 @@ fi # and build. %changelog +* Thu Mar 29 2012 Josh Boyer +- Drop __cpuinitdata on disable_nx for x86_32 (rhbz 808075) + * Mon Mar 26 2012 Dave Jones - Linux 3.2.13 diff --git a/nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch b/nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch new file mode 100644 index 000000000..38c96caed --- /dev/null +++ b/nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch @@ -0,0 +1,47 @@ +>From e540f21852043a4d8e8cf5e505607909d0ab0f51 Mon Sep 17 00:00:00 2001 +From: Tim Gardner +Date: Thu, 29 Mar 2012 06:21:01 -0600 +Subject: [PATCH] UBUNTU: SAUCE: disable_nx should not be in __cpuinitdata + section for X86_32 + +I noticed a section mismatch warning while building 3.2.0-20.33 for X86_32. + + AR arch/x86/lib/lib.a + LD vmlinux.o + MODPOST vmlinux.o +WARNING: vmlinux.o(.text+0x187833): Section mismatch in reference from the function load_elf_binary() to the variable .cpuinit.data:disable_nx +The function load_elf_binary() references +the variable __cpuinitdata disable_nx. +This is often because load_elf_binary lacks a __cpuinitdata +annotation or the annotation of disable_nx is wrong. + +load_elf_binary() is definitely called after initialization. + +This code was added by 'UBUNTU: ubuntu: nx-emu - i386: NX emulation', so +this is not an upstream problem. + +Reported-by: Tetsuo Handa +Signed-off-by: Tim Gardner +--- + arch/x86/mm/setup_nx.c | 4 ++++ + 1 files changed, 4 insertions(+), 0 deletions(-) + +diff --git a/arch/x86/mm/setup_nx.c b/arch/x86/mm/setup_nx.c +index 90c9eff3..89fd946 100644 +--- a/arch/x86/mm/setup_nx.c ++++ b/arch/x86/mm/setup_nx.c +@@ -6,7 +6,11 @@ + #include + #include + ++#ifdef CONFIG_X86_32 ++int disable_nx; /* referenced by load_elf_binary() */ ++#else + int disable_nx __cpuinitdata; ++#endif + + /* + * noexec = on|off +-- +1.7.9.1 + From 09037335b6ef92689e79d19cc4af07e59455f719 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 30 Mar 2012 10:49:57 -0400 Subject: [PATCH 345/397] Add patch to fix incorrect buffer length in __nfs4_get_acl_uncached --- kernel.spec | 9 +++++- ...er-copied-in-__nfs4_get_acl_uncached.patch | 32 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch diff --git a/kernel.spec b/kernel.spec index 23376de5e..856b1a6ab 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -731,6 +731,8 @@ Patch21200: unhandled-irqs-switch-to-polling.patch #rhbz 804007 Patch21305: mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch +Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch + Patch22000: weird-root-dentry-name-debug.patch %endif @@ -1357,6 +1359,8 @@ ApplyPatch mm-thp-fix-pmd_bad-triggering.patch #rhbz 804947 CVE-2012-1568 ApplyPatch SHLIB_BASE-randomization.patch +ApplyPatch nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch + # END OF PATCH APPLICATIONS %endif @@ -2004,6 +2008,9 @@ fi # and build. %changelog +* Fri Mar 30 2012 Josh Boyer +- Add patch to fix incorrect buffer length in __nfs4_get_acl_uncached + * Thu Mar 29 2012 Josh Boyer - Drop __cpuinitdata on disable_nx for x86_32 (rhbz 808075) diff --git a/nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch b/nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch new file mode 100644 index 000000000..981f1f467 --- /dev/null +++ b/nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch @@ -0,0 +1,32 @@ +From 20e0fa98b751facf9a1101edaefbc19c82616a68 Mon Sep 17 00:00:00 2001 +From: Sachin Prabhu +Date: Thu, 22 Mar 2012 16:46:28 +0000 +Subject: [PATCH] Fix length of buffer copied in __nfs4_get_acl_uncached + +_copy_from_pages() used to copy data from the temporary buffer to the +user passed buffer is passed the wrong size parameter when copying +data. res.acl_len contains both the bitmap and acl lenghts while +acl_len contains the acl length after adjusting for the bitmap size. + +Signed-off-by: Sachin Prabhu +Signed-off-by: Trond Myklebust +--- + fs/nfs/nfs4proc.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index e809d23..45df7d4 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -3712,7 +3712,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu + if (acl_len > buflen) + goto out_free; + _copy_from_pages(buf, pages, res.acl_data_offset, +- res.acl_len); ++ acl_len); + } + ret = acl_len; + out_free: +-- +1.7.7.6 + From 77c32d730a254ab9f043ead358f9bab549515c35 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 30 Mar 2012 11:08:12 -0400 Subject: [PATCH 346/397] CVE-2012-1601: kvm: NULL dereference from irqchip_in_kernel and vcpu->arch.apic inconsistency (rhbz 808207) --- ...cpus-are-consistent-with-in-kernel-i.patch | 106 ++++++++++++++++++ kernel.spec | 8 ++ 2 files changed, 114 insertions(+) create mode 100644 KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch diff --git a/KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch b/KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch new file mode 100644 index 000000000..7e1664f41 --- /dev/null +++ b/KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch @@ -0,0 +1,106 @@ +From 5b40572ed5f0344b9dbee486a17c589ce1abe1a3 Mon Sep 17 00:00:00 2001 +From: Avi Kivity +Date: Mon, 5 Mar 2012 14:23:29 +0200 +Subject: [PATCH] KVM: Ensure all vcpus are consistent with in-kernel irqchip + settings + +If some vcpus are created before KVM_CREATE_IRQCHIP, then +irqchip_in_kernel() and vcpu->arch.apic will be inconsistent, leading +to potential NULL pointer dereferences. + +Fix by: +- ensuring that no vcpus are installed when KVM_CREATE_IRQCHIP is called +- ensuring that a vcpu has an apic if it is installed after KVM_CREATE_IRQCHIP + +This is somewhat long winded because vcpu->arch.apic is created without +kvm->lock held. + +Based on earlier patch by Michael Ellerman. + +Signed-off-by: Michael Ellerman +Signed-off-by: Avi Kivity +--- + arch/ia64/kvm/kvm-ia64.c | 5 +++++ + arch/x86/kvm/x86.c | 8 ++++++++ + include/linux/kvm_host.h | 7 +++++++ + virt/kvm/kvm_main.c | 4 ++++ + 4 files changed, 24 insertions(+), 0 deletions(-) + +diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c +index d8ddbba..f5104b7 100644 +--- a/arch/ia64/kvm/kvm-ia64.c ++++ b/arch/ia64/kvm/kvm-ia64.c +@@ -1172,6 +1172,11 @@ out: + + #define PALE_RESET_ENTRY 0x80000000ffffffb0UL + ++bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) ++{ ++ return irqchip_in_kernel(vcpu->kcm) == (vcpu->arch.apic != NULL); ++} ++ + int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) + { + struct kvm_vcpu *v; +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 3ee008f..be9594a 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -3199,6 +3199,9 @@ long kvm_arch_vm_ioctl(struct file *filp, + r = -EEXIST; + if (kvm->arch.vpic) + goto create_irqchip_unlock; ++ r = -EINVAL; ++ if (atomic_read(&kvm->online_vcpus)) ++ goto create_irqchip_unlock; + r = -ENOMEM; + vpic = kvm_create_pic(kvm); + if (vpic) { +@@ -6107,6 +6110,11 @@ void kvm_arch_check_processor_compat(void *rtn) + kvm_x86_ops->check_processor_compatibility(rtn); + } + ++bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) ++{ ++ return irqchip_in_kernel(vcpu->kvm) == (vcpu->arch.apic != NULL); ++} ++ + int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) + { + struct page *page; +diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h +index 355e445..759fa26 100644 +--- a/include/linux/kvm_host.h ++++ b/include/linux/kvm_host.h +@@ -805,6 +805,13 @@ static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu) + { + return vcpu->kvm->bsp_vcpu_id == vcpu->vcpu_id; + } ++ ++bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu); ++ ++#else ++ ++static bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) { return true; } ++ + #endif + + #ifdef __KVM_HAVE_DEVICE_ASSIGNMENT +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index e4431ad..94e148e 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -1651,6 +1651,10 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id) + goto vcpu_destroy; + + mutex_lock(&kvm->lock); ++ if (!kvm_vcpu_compatible(vcpu)) { ++ r = -EINVAL; ++ goto unlock_vcpu_destroy; ++ } + if (atomic_read(&kvm->online_vcpus) == KVM_MAX_VCPUS) { + r = -EINVAL; + goto unlock_vcpu_destroy; +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index 856b1a6ab..891b77f6e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -733,6 +733,9 @@ Patch21305: mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch +#rhbz 808207 CVE-2012-1601 +Patch21520: KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch + Patch22000: weird-root-dentry-name-debug.patch %endif @@ -1361,6 +1364,9 @@ ApplyPatch SHLIB_BASE-randomization.patch ApplyPatch nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch +#rhbz 808207 CVE-2012-1601 +ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch + # END OF PATCH APPLICATIONS %endif @@ -2009,6 +2015,8 @@ fi %changelog * Fri Mar 30 2012 Josh Boyer +- CVE-2012-1601: kvm: NULL dereference from irqchip_in_kernel and + vcpu->arch.apic inconsistency (rhbz 808207) - Add patch to fix incorrect buffer length in __nfs4_get_acl_uncached * Thu Mar 29 2012 Josh Boyer From 7954e4a2011e28e510bf2747ff4e0550e0f533bd Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 2 Apr 2012 11:56:44 -0400 Subject: [PATCH 347/397] Linux 3.3 --- ...truct-x86_emulate_ops-with-get_cpuid.patch | 78 - ...-missing-checks-in-syscall-emulation.patch | 144 - ...wner-group-name-string-when-doing-op.patch | 605 --- alps.patch | 1861 ------- arm-build-bug-on.patch | 28 - arm-stmmac-mmc-core.patch | 26 - bcma-brcmsmac-compat.patch | 12 +- bluetooth-use-after-free.patch | 105 + cdc-acm-tiocgserial.patch | 58 - config-arm-generic | 15 +- config-arm-highbank | 1 + config-arm-imx | 4 +- config-arm-kirkwood | 2 + config-arm-omap-generic | 11 + config-arm-tegra | 10 +- config-generic | 52 +- config-powerpc-generic | 7 + config-powerpc64 | 3 + config-sparc64-generic | 1 + config-x86-32-generic | 4 + config-x86-generic | 12 + config-x86_64-generic | 3 + drm-i915-dp-stfu.patch | 69 + drm-nouveau-updates.patch | 0 e1000e-Avoid-wrong-check-on-TX-hang.patch | 95 - ...-handling-on-inode-bitmap-corruption.patch | 40 - ...-handling-on-inode-bitmap-corruption.patch | 19 - hibernate-freeze-filesystems.patch | 326 +- hpsa-add-irqf-shared.patch | 34 - kernel.spec | 152 +- linux-2.6-defaults-acpi-video.patch | 10 +- linux-2.6-serial-460800.patch | 4 +- mcelog-rcu-splat.patch | 15 + mm-thp-fix-pmd_bad-triggering.patch | 4 +- msi-irq-sysfs-warning.patch | 87 - nfs-client-freezer.patch | 197 - ...pointer-deref-in-proc_pid_permission.patch | 44 - ...fs-add-hidepid-and-gid-mount-options.patch | 342 -- procfs-parse-mount-options.patch | 173 - revert-efi-rtclock.patch | 76 - rt2x00_fix_MCU_request_failures.patch | 136 + rtl8192cu-Fix-WARNING-on-suspend-resume.patch | 163 - ...validate_disk-prevent-NULL-ptr-deref.patch | 22 - ...zation.patch => shlib_base_randomize.patch | 0 silence-timekeeping-spew.patch | 16 + sources | 4 +- sysfs-msi-irq-per-device.patch | 239 - utrace.patch | 4300 ++++------------- 48 files changed, 1606 insertions(+), 8003 deletions(-) delete mode 100644 KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch delete mode 100644 KVM-x86-fix-missing-checks-in-syscall-emulation.patch delete mode 100644 NFSv4-Save-the-owner-group-name-string-when-doing-op.patch delete mode 100644 alps.patch delete mode 100644 arm-build-bug-on.patch delete mode 100644 arm-stmmac-mmc-core.patch create mode 100644 bluetooth-use-after-free.patch delete mode 100644 cdc-acm-tiocgserial.patch create mode 100644 drm-i915-dp-stfu.patch delete mode 100644 drm-nouveau-updates.patch delete mode 100644 e1000e-Avoid-wrong-check-on-TX-hang.patch delete mode 100644 ext3-Fix-error-handling-on-inode-bitmap-corruption.patch delete mode 100644 ext4-Fix-error-handling-on-inode-bitmap-corruption.patch delete mode 100644 hpsa-add-irqf-shared.patch create mode 100644 mcelog-rcu-splat.patch delete mode 100644 msi-irq-sysfs-warning.patch delete mode 100644 nfs-client-freezer.patch delete mode 100644 proc-fix-null-pointer-deref-in-proc_pid_permission.patch delete mode 100644 procfs-add-hidepid-and-gid-mount-options.patch delete mode 100644 procfs-parse-mount-options.patch delete mode 100644 revert-efi-rtclock.patch create mode 100644 rt2x00_fix_MCU_request_failures.patch delete mode 100644 rtl8192cu-Fix-WARNING-on-suspend-resume.patch delete mode 100644 scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch rename SHLIB_BASE-randomization.patch => shlib_base_randomize.patch (100%) create mode 100644 silence-timekeeping-spew.patch delete mode 100644 sysfs-msi-irq-per-device.patch diff --git a/KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch b/KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch deleted file mode 100644 index f9dbaa014..000000000 --- a/KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 0769c5de24621141c953fbe1f943582d37cb4244 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Stephan=20B=C3=A4rwolf?= -Date: Thu, 12 Jan 2012 16:43:03 +0100 -Subject: [PATCH 1/2] KVM: x86: extend "struct x86_emulate_ops" with - "get_cpuid" - -In order to be able to proceed checks on CPU-specific properties -within the emulator, function "get_cpuid" is introduced. -With "get_cpuid" it is possible to virtually call the guests -"cpuid"-opcode without changing the VM's context. - -[mtosatti: cleanup/beautify code] - -Signed-off-by: Stephan Baerwolf -Signed-off-by: Marcelo Tosatti ---- - arch/x86/include/asm/kvm_emulate.h | 3 +++ - arch/x86/kvm/x86.c | 23 +++++++++++++++++++++++ - 2 files changed, 26 insertions(+), 0 deletions(-) - -diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h -index ab4092e..c8b2868 100644 ---- a/arch/x86/include/asm/kvm_emulate.h -+++ b/arch/x86/include/asm/kvm_emulate.h -@@ -190,6 +190,9 @@ struct x86_emulate_ops { - int (*intercept)(struct x86_emulate_ctxt *ctxt, - struct x86_instruction_info *info, - enum x86_intercept_stage stage); -+ -+ bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt, -+ u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); - }; - - typedef u32 __attribute__((vector_size(16))) sse128_t; -diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c -index f0fa3fb..c95ca2d 100644 ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -4205,6 +4205,28 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt, - return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage); - } - -+static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt, -+ u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) -+{ -+ struct kvm_cpuid_entry2 *cpuid = NULL; -+ -+ if (eax && ecx) -+ cpuid = kvm_find_cpuid_entry(emul_to_vcpu(ctxt), -+ *eax, *ecx); -+ -+ if (cpuid) { -+ *eax = cpuid->eax; -+ *ecx = cpuid->ecx; -+ if (ebx) -+ *ebx = cpuid->ebx; -+ if (edx) -+ *edx = cpuid->edx; -+ return true; -+ } -+ -+ return false; -+} -+ - static struct x86_emulate_ops emulate_ops = { - .read_std = kvm_read_guest_virt_system, - .write_std = kvm_write_guest_virt_system, -@@ -4236,6 +4258,7 @@ static struct x86_emulate_ops emulate_ops = { - .get_fpu = emulator_get_fpu, - .put_fpu = emulator_put_fpu, - .intercept = emulator_intercept, -+ .get_cpuid = emulator_get_cpuid, - }; - - static void cache_all_regs(struct kvm_vcpu *vcpu) --- -1.7.7.5 - diff --git a/KVM-x86-fix-missing-checks-in-syscall-emulation.patch b/KVM-x86-fix-missing-checks-in-syscall-emulation.patch deleted file mode 100644 index 933a13431..000000000 --- a/KVM-x86-fix-missing-checks-in-syscall-emulation.patch +++ /dev/null @@ -1,144 +0,0 @@ -From e28ba7bb020f07193bc000453c8775e9d2c0dda7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Stephan=20B=C3=A4rwolf?= -Date: Thu, 12 Jan 2012 16:43:04 +0100 -Subject: [PATCH 2/2] KVM: x86: fix missing checks in syscall emulation - -On hosts without this patch, 32bit guests will crash (and 64bit guests -may behave in a wrong way) for example by simply executing following -nasm-demo-application: - - [bits 32] - global _start - SECTION .text - _start: syscall - -(I tested it with winxp and linux - both always crashed) - - Disassembly of section .text: - - 00000000 <_start>: - 0: 0f 05 syscall - -The reason seems a missing "invalid opcode"-trap (int6) for the -syscall opcode "0f05", which is not available on Intel CPUs -within non-longmodes, as also on some AMD CPUs within legacy-mode. -(depending on CPU vendor, MSR_EFER and cpuid) - -Because previous mentioned OSs may not engage corresponding -syscall target-registers (STAR, LSTAR, CSTAR), they remain -NULL and (non trapping) syscalls are leading to multiple -faults and finally crashs. - -Depending on the architecture (AMD or Intel) pretended by -guests, various checks according to vendor's documentation -are implemented to overcome the current issue and behave -like the CPUs physical counterparts. - -[mtosatti: cleanup/beautify code] - -Signed-off-by: Stephan Baerwolf -Signed-off-by: Marcelo Tosatti ---- - arch/x86/include/asm/kvm_emulate.h | 13 +++++++++ - arch/x86/kvm/emulate.c | 51 ++++++++++++++++++++++++++++++++++++ - 2 files changed, 64 insertions(+), 0 deletions(-) - -diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h -index c8b2868..7b9cfc4 100644 ---- a/arch/x86/include/asm/kvm_emulate.h -+++ b/arch/x86/include/asm/kvm_emulate.h -@@ -301,6 +301,19 @@ struct x86_emulate_ctxt { - #define X86EMUL_MODE_PROT (X86EMUL_MODE_PROT16|X86EMUL_MODE_PROT32| \ - X86EMUL_MODE_PROT64) - -+/* CPUID vendors */ -+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx 0x68747541 -+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx 0x444d4163 -+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_edx 0x69746e65 -+ -+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx 0x69444d41 -+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx 0x21726574 -+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_edx 0x74656273 -+ -+#define X86EMUL_CPUID_VENDOR_GenuineIntel_ebx 0x756e6547 -+#define X86EMUL_CPUID_VENDOR_GenuineIntel_ecx 0x6c65746e -+#define X86EMUL_CPUID_VENDOR_GenuineIntel_edx 0x49656e69 -+ - enum x86_intercept_stage { - X86_ICTP_NONE = 0, /* Allow zero-init to not match anything */ - X86_ICPT_PRE_EXCEPT, -diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c -index 05a562b..0982507 100644 ---- a/arch/x86/kvm/emulate.c -+++ b/arch/x86/kvm/emulate.c -@@ -1891,6 +1891,51 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt, - ss->p = 1; - } - -+static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt) -+{ -+ struct x86_emulate_ops *ops = ctxt->ops; -+ u32 eax, ebx, ecx, edx; -+ -+ /* -+ * syscall should always be enabled in longmode - so only become -+ * vendor specific (cpuid) if other modes are active... -+ */ -+ if (ctxt->mode == X86EMUL_MODE_PROT64) -+ return true; -+ -+ eax = 0x00000000; -+ ecx = 0x00000000; -+ if (ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)) { -+ /* -+ * Intel ("GenuineIntel") -+ * remark: Intel CPUs only support "syscall" in 64bit -+ * longmode. Also an 64bit guest with a -+ * 32bit compat-app running will #UD !! While this -+ * behaviour can be fixed (by emulating) into AMD -+ * response - CPUs of AMD can't behave like Intel. -+ */ -+ if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx && -+ ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx && -+ edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx) -+ return false; -+ -+ /* AMD ("AuthenticAMD") */ -+ if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx && -+ ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx && -+ edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx) -+ return true; -+ -+ /* AMD ("AMDisbetter!") */ -+ if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx && -+ ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx && -+ edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx) -+ return true; -+ } -+ -+ /* default: (not Intel, not AMD), apply Intel's stricter rules... */ -+ return false; -+} -+ - static int em_syscall(struct x86_emulate_ctxt *ctxt) - { - struct x86_emulate_ops *ops = ctxt->ops; -@@ -1904,9 +1949,15 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt) - ctxt->mode == X86EMUL_MODE_VM86) - return emulate_ud(ctxt); - -+ if (!(em_syscall_is_enabled(ctxt))) -+ return emulate_ud(ctxt); -+ - ops->get_msr(ctxt, MSR_EFER, &efer); - setup_syscalls_segments(ctxt, &cs, &ss); - -+ if (!(efer & EFER_SCE)) -+ return emulate_ud(ctxt); -+ - ops->get_msr(ctxt, MSR_STAR, &msr_data); - msr_data >>= 32; - cs_sel = (u16)(msr_data & 0xfffc); --- -1.7.7.5 - diff --git a/NFSv4-Save-the-owner-group-name-string-when-doing-op.patch b/NFSv4-Save-the-owner-group-name-string-when-doing-op.patch deleted file mode 100644 index 610ec0113..000000000 --- a/NFSv4-Save-the-owner-group-name-string-when-doing-op.patch +++ /dev/null @@ -1,605 +0,0 @@ -ommit 6926afd1925a54a13684ebe05987868890665e2b -Author: Trond Myklebust -Date: Sat Jan 7 13:22:46 2012 -0500 - - NFSv4: Save the owner/group name string when doing open - - ...so that we can do the uid/gid mapping outside the asynchronous RPC - context. - This fixes a bug in the current NFSv4 atomic open code where the client - isn't able to determine what the true uid/gid fields of the file are, - (because the asynchronous nature of the OPEN call denies it the ability - to do an upcall) and so fills them with default values, marking the - inode as needing revalidation. - Unfortunately, in some cases, the VFS will do some additional sanity - checks on the file, and may override the server's decision to allow - the open because it sees the wrong owner/group fields. - - Signed-off-by: Trond Myklebust - -diff -up linux-3.2.noarch/fs/nfs/idmap.c.orig linux-3.2.noarch/fs/nfs/idmap.c ---- linux-3.2.noarch/fs/nfs/idmap.c.orig 2012-03-15 10:38:58.876578000 -0400 -+++ linux-3.2.noarch/fs/nfs/idmap.c 2012-03-15 10:51:10.344228000 -0400 -@@ -38,6 +38,89 @@ - #include - #include - #include -+#include -+ -+/** -+ * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields -+ * @fattr: fully initialised struct nfs_fattr -+ * @owner_name: owner name string cache -+ * @group_name: group name string cache -+ */ -+void nfs_fattr_init_names(struct nfs_fattr *fattr, -+ struct nfs4_string *owner_name, -+ struct nfs4_string *group_name) -+{ -+ fattr->owner_name = owner_name; -+ fattr->group_name = group_name; -+} -+ -+static void nfs_fattr_free_owner_name(struct nfs_fattr *fattr) -+{ -+ fattr->valid &= ~NFS_ATTR_FATTR_OWNER_NAME; -+ kfree(fattr->owner_name->data); -+} -+ -+static void nfs_fattr_free_group_name(struct nfs_fattr *fattr) -+{ -+ fattr->valid &= ~NFS_ATTR_FATTR_GROUP_NAME; -+ kfree(fattr->group_name->data); -+} -+ -+static bool nfs_fattr_map_owner_name(struct nfs_server *server, struct nfs_fattr *fattr) -+{ -+ struct nfs4_string *owner = fattr->owner_name; -+ __u32 uid; -+ -+ if (!(fattr->valid & NFS_ATTR_FATTR_OWNER_NAME)) -+ return false; -+ if (nfs_map_name_to_uid(server, owner->data, owner->len, &uid) == 0) { -+ fattr->uid = uid; -+ fattr->valid |= NFS_ATTR_FATTR_OWNER; -+ } -+ return true; -+} -+ -+static bool nfs_fattr_map_group_name(struct nfs_server *server, struct nfs_fattr *fattr) -+{ -+ struct nfs4_string *group = fattr->group_name; -+ __u32 gid; -+ -+ if (!(fattr->valid & NFS_ATTR_FATTR_GROUP_NAME)) -+ return false; -+ if (nfs_map_group_to_gid(server, group->data, group->len, &gid) == 0) { -+ fattr->gid = gid; -+ fattr->valid |= NFS_ATTR_FATTR_GROUP; -+ } -+ return true; -+} -+ -+/** -+ * nfs_fattr_free_names - free up the NFSv4 owner and group strings -+ * @fattr: a fully initialised nfs_fattr structure -+ */ -+void nfs_fattr_free_names(struct nfs_fattr *fattr) -+{ -+ if (fattr->valid & NFS_ATTR_FATTR_OWNER_NAME) -+ nfs_fattr_free_owner_name(fattr); -+ if (fattr->valid & NFS_ATTR_FATTR_GROUP_NAME) -+ nfs_fattr_free_group_name(fattr); -+} -+ -+/** -+ * nfs_fattr_map_and_free_names - map owner/group strings into uid/gid and free -+ * @server: pointer to the filesystem nfs_server structure -+ * @fattr: a fully initialised nfs_fattr structure -+ * -+ * This helper maps the cached NFSv4 owner/group strings in fattr into -+ * their numeric uid/gid equivalents, and then frees the cached strings. -+ */ -+void nfs_fattr_map_and_free_names(struct nfs_server *server, struct nfs_fattr *fattr) -+{ -+ if (nfs_fattr_map_owner_name(server, fattr)) -+ nfs_fattr_free_owner_name(fattr); -+ if (nfs_fattr_map_group_name(server, fattr)) -+ nfs_fattr_free_group_name(fattr); -+} - - static int nfs_map_string_to_numeric(const char *name, size_t namelen, __u32 *res) - { -diff -up linux-3.2.noarch/fs/nfs/inode.c.orig linux-3.2.noarch/fs/nfs/inode.c ---- linux-3.2.noarch/fs/nfs/inode.c.orig 2012-03-15 10:39:00.362624000 -0400 -+++ linux-3.2.noarch/fs/nfs/inode.c 2012-03-15 10:51:10.352227000 -0400 -@@ -1020,6 +1020,8 @@ void nfs_fattr_init(struct nfs_fattr *fa - fattr->valid = 0; - fattr->time_start = jiffies; - fattr->gencount = nfs_inc_attr_generation_counter(); -+ fattr->owner_name = NULL; -+ fattr->group_name = NULL; - } - - struct nfs_fattr *nfs_alloc_fattr(void) -diff -up linux-3.2.noarch/fs/nfs/nfs4proc.c.orig linux-3.2.noarch/fs/nfs/nfs4proc.c ---- linux-3.2.noarch/fs/nfs/nfs4proc.c.orig 2012-03-15 10:39:00.380629000 -0400 -+++ linux-3.2.noarch/fs/nfs/nfs4proc.c 2012-03-15 10:51:10.362231000 -0400 -@@ -52,6 +52,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -765,6 +766,8 @@ struct nfs4_opendata { - struct nfs_openres o_res; - struct nfs_open_confirmargs c_arg; - struct nfs_open_confirmres c_res; -+ struct nfs4_string owner_name; -+ struct nfs4_string group_name; - struct nfs_fattr f_attr; - struct nfs_fattr dir_attr; - struct dentry *dir; -@@ -788,6 +791,7 @@ static void nfs4_init_opendata_res(struc - p->o_res.server = p->o_arg.server; - nfs_fattr_init(&p->f_attr); - nfs_fattr_init(&p->dir_attr); -+ nfs_fattr_init_names(&p->f_attr, &p->owner_name, &p->group_name); - } - - static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, -@@ -819,6 +823,7 @@ static struct nfs4_opendata *nfs4_openda - p->o_arg.name = &dentry->d_name; - p->o_arg.server = server; - p->o_arg.bitmask = server->attr_bitmask; -+ p->o_arg.dir_bitmask = server->cache_consistency_bitmask; - p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; - if (flags & O_CREAT) { - u32 *s; -@@ -855,6 +860,7 @@ static void nfs4_opendata_free(struct kr - dput(p->dir); - dput(p->dentry); - nfs_sb_deactive(sb); -+ nfs_fattr_free_names(&p->f_attr); - kfree(p); - } - -@@ -1579,6 +1585,8 @@ static int _nfs4_recover_proc_open(struc - if (status != 0 || !data->rpc_done) - return status; - -+ nfs_fattr_map_and_free_names(NFS_SERVER(dir), &data->f_attr); -+ - nfs_refresh_inode(dir, o_res->dir_attr); - - if (o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { -@@ -1611,6 +1619,8 @@ static int _nfs4_proc_open(struct nfs4_o - return status; - } - -+ nfs_fattr_map_and_free_names(server, &data->f_attr); -+ - if (o_arg->open_flags & O_CREAT) { - update_changeattr(dir, &o_res->cinfo); - nfs_post_op_update_inode(dir, o_res->dir_attr); -diff -up linux-3.2.noarch/fs/nfs/nfs4xdr.c.orig linux-3.2.noarch/fs/nfs/nfs4xdr.c ---- linux-3.2.noarch/fs/nfs/nfs4xdr.c.orig 2012-03-15 10:38:54.054438000 -0400 -+++ linux-3.2.noarch/fs/nfs/nfs4xdr.c 2012-03-15 10:51:10.373231000 -0400 -@@ -2298,7 +2298,7 @@ static void nfs4_xdr_enc_open(struct rpc - encode_getfh(xdr, &hdr); - encode_getfattr(xdr, args->bitmask, &hdr); - encode_restorefh(xdr, &hdr); -- encode_getfattr(xdr, args->bitmask, &hdr); -+ encode_getfattr(xdr, args->dir_bitmask, &hdr); - encode_nops(&hdr); - } - -@@ -3791,7 +3791,8 @@ out_overflow: - } - - static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, -- const struct nfs_server *server, uint32_t *uid, int may_sleep) -+ const struct nfs_server *server, uint32_t *uid, -+ struct nfs4_string *owner_name) - { - uint32_t len; - __be32 *p; -@@ -3808,8 +3809,12 @@ static int decode_attr_owner(struct xdr_ - p = xdr_inline_decode(xdr, len); - if (unlikely(!p)) - goto out_overflow; -- if (!may_sleep) { -- /* do nothing */ -+ if (owner_name != NULL) { -+ owner_name->data = kmemdup(p, len, GFP_NOWAIT); -+ if (owner_name->data != NULL) { -+ owner_name->len = len; -+ ret = NFS_ATTR_FATTR_OWNER_NAME; -+ } - } else if (len < XDR_MAX_NETOBJ) { - if (nfs_map_name_to_uid(server, (char *)p, len, uid) == 0) - ret = NFS_ATTR_FATTR_OWNER; -@@ -3829,7 +3834,8 @@ out_overflow: - } - - static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, -- const struct nfs_server *server, uint32_t *gid, int may_sleep) -+ const struct nfs_server *server, uint32_t *gid, -+ struct nfs4_string *group_name) - { - uint32_t len; - __be32 *p; -@@ -3846,8 +3852,12 @@ static int decode_attr_group(struct xdr_ - p = xdr_inline_decode(xdr, len); - if (unlikely(!p)) - goto out_overflow; -- if (!may_sleep) { -- /* do nothing */ -+ if (group_name != NULL) { -+ group_name->data = kmemdup(p, len, GFP_NOWAIT); -+ if (group_name->data != NULL) { -+ group_name->len = len; -+ ret = NFS_ATTR_FATTR_GROUP_NAME; -+ } - } else if (len < XDR_MAX_NETOBJ) { - if (nfs_map_group_to_gid(server, (char *)p, len, gid) == 0) - ret = NFS_ATTR_FATTR_GROUP; -@@ -4284,7 +4294,7 @@ xdr_error: - - static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, - struct nfs_fattr *fattr, struct nfs_fh *fh, -- const struct nfs_server *server, int may_sleep) -+ const struct nfs_server *server) - { - int status; - umode_t fmode = 0; -@@ -4351,12 +4361,12 @@ static int decode_getfattr_attrs(struct - goto xdr_error; - fattr->valid |= status; - -- status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, may_sleep); -+ status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, fattr->owner_name); - if (status < 0) - goto xdr_error; - fattr->valid |= status; - -- status = decode_attr_group(xdr, bitmap, server, &fattr->gid, may_sleep); -+ status = decode_attr_group(xdr, bitmap, server, &fattr->gid, fattr->group_name); - if (status < 0) - goto xdr_error; - fattr->valid |= status; -@@ -4397,7 +4407,7 @@ xdr_error: - } - - static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, -- struct nfs_fh *fh, const struct nfs_server *server, int may_sleep) -+ struct nfs_fh *fh, const struct nfs_server *server) - { - __be32 *savep; - uint32_t attrlen, -@@ -4416,7 +4426,7 @@ static int decode_getfattr_generic(struc - if (status < 0) - goto xdr_error; - -- status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server, may_sleep); -+ status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server); - if (status < 0) - goto xdr_error; - -@@ -4427,9 +4437,9 @@ xdr_error: - } - - static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, -- const struct nfs_server *server, int may_sleep) -+ const struct nfs_server *server) - { -- return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep); -+ return decode_getfattr_generic(xdr, fattr, NULL, server); - } - - /* -@@ -5710,8 +5720,7 @@ static int nfs4_xdr_dec_open_downgrade(s - status = decode_open_downgrade(xdr, res); - if (status != 0) - goto out; -- decode_getfattr(xdr, res->fattr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)); -+ decode_getfattr(xdr, res->fattr, res->server); - out: - return status; - } -@@ -5737,8 +5746,7 @@ static int nfs4_xdr_dec_access(struct rp - status = decode_access(xdr, res); - if (status != 0) - goto out; -- decode_getfattr(xdr, res->fattr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)); -+ decode_getfattr(xdr, res->fattr, res->server); - out: - return status; - } -@@ -5767,8 +5775,7 @@ static int nfs4_xdr_dec_lookup(struct rp - status = decode_getfh(xdr, res->fh); - if (status) - goto out; -- status = decode_getfattr(xdr, res->fattr, res->server -- ,!RPC_IS_ASYNC(rqstp->rq_task)); -+ status = decode_getfattr(xdr, res->fattr, res->server); - out: - return status; - } -@@ -5794,8 +5801,7 @@ static int nfs4_xdr_dec_lookup_root(stru - goto out; - status = decode_getfh(xdr, res->fh); - if (status == 0) -- status = decode_getfattr(xdr, res->fattr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)); -+ status = decode_getfattr(xdr, res->fattr, res->server); - out: - return status; - } -@@ -5821,8 +5827,7 @@ static int nfs4_xdr_dec_remove(struct rp - status = decode_remove(xdr, &res->cinfo); - if (status) - goto out; -- decode_getfattr(xdr, res->dir_attr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)); -+ decode_getfattr(xdr, res->dir_attr, res->server); - out: - return status; - } -@@ -5855,14 +5860,12 @@ static int nfs4_xdr_dec_rename(struct rp - if (status) - goto out; - /* Current FH is target directory */ -- if (decode_getfattr(xdr, res->new_fattr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)) != 0) -+ if (decode_getfattr(xdr, res->new_fattr, res->server)) - goto out; - status = decode_restorefh(xdr); - if (status) - goto out; -- decode_getfattr(xdr, res->old_fattr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)); -+ decode_getfattr(xdr, res->old_fattr, res->server); - out: - return status; - } -@@ -5898,14 +5901,12 @@ static int nfs4_xdr_dec_link(struct rpc_ - * Note order: OP_LINK leaves the directory as the current - * filehandle. - */ -- if (decode_getfattr(xdr, res->dir_attr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)) != 0) -+ if (decode_getfattr(xdr, res->dir_attr, res->server)) - goto out; - status = decode_restorefh(xdr); - if (status) - goto out; -- decode_getfattr(xdr, res->fattr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)); -+ decode_getfattr(xdr, res->fattr, res->server); - out: - return status; - } -@@ -5937,14 +5938,12 @@ static int nfs4_xdr_dec_create(struct rp - status = decode_getfh(xdr, res->fh); - if (status) - goto out; -- if (decode_getfattr(xdr, res->fattr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)) != 0) -+ if (decode_getfattr(xdr, res->fattr, res->server)) - goto out; - status = decode_restorefh(xdr); - if (status) - goto out; -- decode_getfattr(xdr, res->dir_fattr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)); -+ decode_getfattr(xdr, res->dir_fattr, res->server); - out: - return status; - } -@@ -5976,8 +5975,7 @@ static int nfs4_xdr_dec_getattr(struct r - status = decode_putfh(xdr); - if (status) - goto out; -- status = decode_getfattr(xdr, res->fattr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)); -+ status = decode_getfattr(xdr, res->fattr, res->server); - out: - return status; - } -@@ -6079,8 +6077,7 @@ static int nfs4_xdr_dec_close(struct rpc - * an ESTALE error. Shouldn't be a problem, - * though, since fattr->valid will remain unset. - */ -- decode_getfattr(xdr, res->fattr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)); -+ decode_getfattr(xdr, res->fattr, res->server); - out: - return status; - } -@@ -6111,13 +6108,11 @@ static int nfs4_xdr_dec_open(struct rpc_ - goto out; - if (decode_getfh(xdr, &res->fh) != 0) - goto out; -- if (decode_getfattr(xdr, res->f_attr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)) != 0) -+ if (decode_getfattr(xdr, res->f_attr, res->server) != 0) - goto out; - if (decode_restorefh(xdr) != 0) - goto out; -- decode_getfattr(xdr, res->dir_attr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)); -+ decode_getfattr(xdr, res->dir_attr, res->server); - out: - return status; - } -@@ -6165,8 +6160,7 @@ static int nfs4_xdr_dec_open_noattr(stru - status = decode_open(xdr, res); - if (status) - goto out; -- decode_getfattr(xdr, res->f_attr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)); -+ decode_getfattr(xdr, res->f_attr, res->server); - out: - return status; - } -@@ -6193,8 +6187,7 @@ static int nfs4_xdr_dec_setattr(struct r - status = decode_setattr(xdr); - if (status) - goto out; -- decode_getfattr(xdr, res->fattr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)); -+ decode_getfattr(xdr, res->fattr, res->server); - out: - return status; - } -@@ -6374,8 +6367,7 @@ static int nfs4_xdr_dec_write(struct rpc - if (status) - goto out; - if (res->fattr) -- decode_getfattr(xdr, res->fattr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)); -+ decode_getfattr(xdr, res->fattr, res->server); - if (!status) - status = res->count; - out: -@@ -6404,8 +6396,7 @@ static int nfs4_xdr_dec_commit(struct rp - if (status) - goto out; - if (res->fattr) -- decode_getfattr(xdr, res->fattr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)); -+ decode_getfattr(xdr, res->fattr, res->server); - out: - return status; - } -@@ -6564,8 +6555,7 @@ static int nfs4_xdr_dec_delegreturn(stru - status = decode_delegreturn(xdr); - if (status != 0) - goto out; -- decode_getfattr(xdr, res->fattr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)); -+ decode_getfattr(xdr, res->fattr, res->server); - out: - return status; - } -@@ -6594,8 +6584,7 @@ static int nfs4_xdr_dec_fs_locations(str - goto out; - xdr_enter_page(xdr, PAGE_SIZE); - status = decode_getfattr(xdr, &res->fs_locations->fattr, -- res->fs_locations->server, -- !RPC_IS_ASYNC(req->rq_task)); -+ res->fs_locations->server); - out: - return status; - } -@@ -6844,8 +6833,7 @@ static int nfs4_xdr_dec_layoutcommit(str - status = decode_layoutcommit(xdr, rqstp, res); - if (status) - goto out; -- decode_getfattr(xdr, res->fattr, res->server, -- !RPC_IS_ASYNC(rqstp->rq_task)); -+ decode_getfattr(xdr, res->fattr, res->server); - out: - return status; - } -@@ -6976,7 +6964,7 @@ int nfs4_decode_dirent(struct xdr_stream - goto out_overflow; - - if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, -- entry->server, 1) < 0) -+ entry->server) < 0) - goto out_overflow; - if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) - entry->ino = entry->fattr->mounted_on_fileid; -diff -up linux-3.2.noarch/include/linux/nfs_idmap.h.orig linux-3.2.noarch/include/linux/nfs_idmap.h ---- linux-3.2.noarch/include/linux/nfs_idmap.h.orig 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.noarch/include/linux/nfs_idmap.h 2012-03-15 10:51:10.395228000 -0400 -@@ -66,6 +66,8 @@ struct idmap_msg { - /* Forward declaration to make this header independent of others */ - struct nfs_client; - struct nfs_server; -+struct nfs_fattr; -+struct nfs4_string; - - #ifdef CONFIG_NFS_USE_NEW_IDMAPPER - -@@ -97,6 +99,12 @@ void nfs_idmap_delete(struct nfs_client - - #endif /* CONFIG_NFS_USE_NEW_IDMAPPER */ - -+void nfs_fattr_init_names(struct nfs_fattr *fattr, -+ struct nfs4_string *owner_name, -+ struct nfs4_string *group_name); -+void nfs_fattr_free_names(struct nfs_fattr *); -+void nfs_fattr_map_and_free_names(struct nfs_server *, struct nfs_fattr *); -+ - int nfs_map_name_to_uid(const struct nfs_server *, const char *, size_t, __u32 *); - int nfs_map_group_to_gid(const struct nfs_server *, const char *, size_t, __u32 *); - int nfs_map_uid_to_name(const struct nfs_server *, __u32, char *, size_t); -diff -up linux-3.2.noarch/include/linux/nfs_xdr.h.orig linux-3.2.noarch/include/linux/nfs_xdr.h ---- linux-3.2.noarch/include/linux/nfs_xdr.h.orig 2012-03-15 10:38:54.464449000 -0400 -+++ linux-3.2.noarch/include/linux/nfs_xdr.h 2012-03-15 10:51:10.415229000 -0400 -@@ -18,6 +18,11 @@ - /* Forward declaration for NFS v3 */ - struct nfs4_secinfo_flavors; - -+struct nfs4_string { -+ unsigned int len; -+ char *data; -+}; -+ - struct nfs_fsid { - uint64_t major; - uint64_t minor; -@@ -61,6 +66,8 @@ struct nfs_fattr { - struct timespec pre_ctime; /* pre_op_attr.ctime */ - unsigned long time_start; - unsigned long gencount; -+ struct nfs4_string *owner_name; -+ struct nfs4_string *group_name; - }; - - #define NFS_ATTR_FATTR_TYPE (1U << 0) -@@ -85,6 +92,8 @@ struct nfs_fattr { - #define NFS_ATTR_FATTR_V4_REFERRAL (1U << 19) /* NFSv4 referral */ - #define NFS_ATTR_FATTR_MOUNTPOINT (1U << 20) /* Treat as mountpoint */ - #define NFS_ATTR_FATTR_MOUNTED_ON_FILEID (1U << 21) -+#define NFS_ATTR_FATTR_OWNER_NAME (1U << 22) -+#define NFS_ATTR_FATTR_GROUP_NAME (1U << 23) - - #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \ - | NFS_ATTR_FATTR_MODE \ -@@ -324,6 +333,7 @@ struct nfs_openargs { - const struct qstr * name; - const struct nfs_server *server; /* Needed for ID mapping */ - const u32 * bitmask; -+ const u32 * dir_bitmask; - __u32 claim; - struct nfs4_sequence_args seq_args; - }; -@@ -342,6 +352,8 @@ struct nfs_openres { - __u32 do_recall; - __u64 maxsize; - __u32 attrset[NFS4_BITMAP_SIZE]; -+ struct nfs4_string *owner; -+ struct nfs4_string *group_owner; - struct nfs4_sequence_res seq_res; - }; - -@@ -778,11 +790,6 @@ struct nfs3_getaclres { - struct posix_acl * acl_default; - }; - --struct nfs4_string { -- unsigned int len; -- char *data; --}; -- - #ifdef CONFIG_NFS_V4 - - typedef u64 clientid4; diff --git a/alps.patch b/alps.patch deleted file mode 100644 index 331716d3b..000000000 --- a/alps.patch +++ /dev/null @@ -1,1861 +0,0 @@ -From d4b347b29b4d14647c7394f7167bf6785dc98e50 Mon Sep 17 00:00:00 2001 -From: Seth Forshee -Date: Mon, 7 Nov 2011 19:53:15 -0800 -Subject: [PATCH 1/6] Input: ALPS - move protocol information to Documentation - -In preparation for new protocol support, move the protocol -information currently documented in alps.c to -Documentation/input/alps.txt, where it can be expanded without -cluttering up the driver. - -Signed-off-by: Seth Forshee -Acked-by: Chase Douglas -Signed-off-by: Dmitry Torokhov ---- - Documentation/input/alps.txt | 75 ++++++++++++++++++++++++++++++++++++++++++ - drivers/input/mouse/alps.c | 37 +-------------------- - 2 files changed, 76 insertions(+), 36 deletions(-) - create mode 100644 Documentation/input/alps.txt - -diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt -new file mode 100644 -index 0000000..ab5478f ---- /dev/null -+++ b/Documentation/input/alps.txt -@@ -0,0 +1,75 @@ -+ALPS Touchpad Protocol -+---------------------- -+ -+Introduction -+------------ -+ -+Currently the ALPS touchpad driver supports two protocol versions in use by -+ALPS touchpads, the "old" and "new" protocol versions. Fundamentally these -+differ only in the format of their event packets (in reality many features may -+be found on new protocol devices that aren't found on the old protocol -+devices, but these are handled transparently as feature differences rather -+than protocol differences). -+ -+Detection -+--------- -+ -+All ALPS touchpads should respond to the "E6 report" command sequence: -+E8-E6-E6-E6-E9. An ALPS touchpad should respond with either 00-00-0A or -+00-00-64. -+ -+If the E6 report is successful, the touchpad model is identified using the "E7 -+report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is -+matched against known models in the alps_model_data_array. -+ -+Packet Format -+------------- -+ -+In the following tables, the following notation us used. -+ -+ CAPITALS = stick, miniscules = touchpad -+ -+?'s can have different meanings on different models, such as wheel rotation, -+extra buttons, stick buttons on a dualpoint, etc. -+ -+PS/2 packet format -+------------------ -+ -+ byte 0: 0 0 YSGN XSGN 1 M R L -+ byte 1: X7 X6 X5 X4 X3 X2 X1 X0 -+ byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 -+ -+Note that the device never signals overflow condition. -+ -+ALPS Absolute Mode - Old Format -+------------------------------- -+ -+ byte 0: 1 0 0 0 1 x9 x8 x7 -+ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -+ byte 2: 0 ? ? l r ? fin ges -+ byte 3: 0 ? ? ? ? y9 y8 y7 -+ byte 4: 0 y6 y5 y4 y3 y2 y1 y0 -+ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 -+ -+ALPS Absolute Mode - New Format -+------------------------------- -+ -+ byte 0: 1 ? ? ? 1 ? ? ? -+ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -+ byte 2: 0 x10 x9 x8 x7 ? fin ges -+ byte 3: 0 y9 y8 y7 1 M R L -+ byte 4: 0 y6 y5 y4 y3 y2 y1 y0 -+ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 -+ -+Dualpoint device -- interleaved packet format -+--------------------------------------------- -+ -+ byte 0: 1 1 0 0 1 1 1 1 -+ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -+ byte 2: 0 x10 x9 x8 x7 0 fin ges -+ byte 3: 0 0 YSGN XSGN 1 1 1 1 -+ byte 4: X7 X6 X5 X4 X3 X2 X1 X0 -+ byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 -+ byte 6: 0 y9 y8 y7 1 m r l -+ byte 7: 0 y6 y5 y4 y3 y2 y1 y0 -+ byte 8: 0 z6 z5 z4 z3 z2 z1 z0 -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 003587c..19d0943 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -67,42 +67,7 @@ static const struct alps_model_info alps_model_data[] = { - * isn't valid per PS/2 spec. - */ - --/* -- * PS/2 packet format -- * -- * byte 0: 0 0 YSGN XSGN 1 M R L -- * byte 1: X7 X6 X5 X4 X3 X2 X1 X0 -- * byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 -- * -- * Note that the device never signals overflow condition. -- * -- * ALPS absolute Mode - new format -- * -- * byte 0: 1 ? ? ? 1 ? ? ? -- * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -- * byte 2: 0 x10 x9 x8 x7 ? fin ges -- * byte 3: 0 y9 y8 y7 1 M R L -- * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 -- * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 -- * -- * Dualpoint device -- interleaved packet format -- * -- * byte 0: 1 1 0 0 1 1 1 1 -- * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -- * byte 2: 0 x10 x9 x8 x7 0 fin ges -- * byte 3: 0 0 YSGN XSGN 1 1 1 1 -- * byte 4: X7 X6 X5 X4 X3 X2 X1 X0 -- * byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 -- * byte 6: 0 y9 y8 y7 1 m r l -- * byte 7: 0 y6 y5 y4 y3 y2 y1 y0 -- * byte 8: 0 z6 z5 z4 z3 z2 z1 z0 -- * -- * CAPITALS = stick, miniscules = touchpad -- * -- * ?'s can have different meanings on different models, -- * such as wheel rotation, extra buttons, stick buttons -- * on a dualpoint, etc. -- */ -+/* Packet formats are described in Documentation/input/alps.txt */ - - static bool alps_is_valid_first_byte(const struct alps_model_info *model, - unsigned char data) --- -1.7.7.3 - - -From fa629ef5222193214da9a2b3c94369f79353bec9 Mon Sep 17 00:00:00 2001 -From: Seth Forshee -Date: Mon, 7 Nov 2011 19:53:24 -0800 -Subject: [PATCH 2/6] Input: ALPS - add protocol version field in - alps_model_info - -In preparation for adding support for more ALPS protocol versions, -add a field for the protocol version to the model info instead of -using a field in the flags. OLDPROTO and !OLDPROTO are now called -version 1 and version 2, repsectively. - -Signed-off-by: Seth Forshee -Acked-by: Chase Douglas -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 47 +++++++++++++++++++++---------------------- - drivers/input/mouse/alps.h | 4 +++ - 2 files changed, 27 insertions(+), 24 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 19d0943..77b776d 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -23,7 +23,6 @@ - #include "psmouse.h" - #include "alps.h" - --#define ALPS_OLDPROTO 0x01 /* old style input */ - #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ - #define ALPS_PASS 0x04 /* device has a pass-through port */ - -@@ -35,30 +34,30 @@ - 6-byte ALPS packet */ - - static const struct alps_model_info alps_model_data[] = { -- { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ -- { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ -- { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, -- { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, -- { { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 }, /* HP ze1115 */ -- { { 0x63, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ -- { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ -- { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ -- { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ -- { { 0x73, 0x00, 0x0a }, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ -- { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, -- { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ -- { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ -- { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, -- { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ -+ { { 0x32, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ -+ { { 0x33, 0x02, 0x0a }, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ -+ { { 0x53, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x53, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x60, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ -+ { { 0x63, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x02, 0x28 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ -+ { { 0x63, 0x02, 0x3c }, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ -+ { { 0x63, 0x02, 0x50 }, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ -+ { { 0x63, 0x02, 0x64 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ -+ { { 0x73, 0x00, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ -+ { { 0x73, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x73, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ -+ { { 0x20, 0x02, 0x0e }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ -+ { { 0x22, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, -+ { { 0x22, 0x02, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ - /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ -- { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, -+ { { 0x62, 0x02, 0x14 }, ALPS_PROTO_V2, 0xcf, 0xcf, - ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, -- { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ -- { { 0x52, 0x01, 0x14 }, 0xff, 0xff, -- ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ -+ { { 0x73, 0x02, 0x50 }, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ -+ { { 0x52, 0x01, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, -+ ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ - }; - - /* -@@ -112,7 +111,7 @@ static void alps_process_packet(struct psmouse *psmouse) - int x, y, z, ges, fin, left, right, middle; - int back = 0, forward = 0; - -- if (model->flags & ALPS_OLDPROTO) { -+ if (model->proto_version == ALPS_PROTO_V1) { - left = packet[2] & 0x10; - right = packet[2] & 0x08; - middle = 0; -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 904ed8b..4ce9bba 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -12,8 +12,12 @@ - #ifndef _ALPS_H - #define _ALPS_H - -+#define ALPS_PROTO_V1 0 -+#define ALPS_PROTO_V2 1 -+ - struct alps_model_info { - unsigned char signature[3]; -+ unsigned char proto_version; - unsigned char byte0, mask0; - unsigned char flags; - }; --- -1.7.7.3 - - -From b46615fe9215214ac00e26d35fc54dbe1c510803 Mon Sep 17 00:00:00 2001 -From: Seth Forshee -Date: Mon, 7 Nov 2011 19:53:30 -0800 -Subject: [PATCH 3/6] Input: ALPS - remove assumptions about packet size - -In preparation for version 4 protocol support, which has 8-byte -data packets, remove all hard-coded assumptions about packet size -and use psmouse->pktsize instead. - -Signed-off-by: Seth Forshee -Acked-by: Chase Douglas -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 10 +++++----- - 1 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 77b776d..44a0a71 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -308,7 +308,7 @@ static void alps_flush_packet(unsigned long data) - - serio_pause_rx(psmouse->ps2dev.serio); - -- if (psmouse->pktcnt == 6) { -+ if (psmouse->pktcnt == psmouse->pktsize) { - - /* - * We did not any more data in reasonable amount of time. -@@ -359,8 +359,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) - return PSMOUSE_BAD_DATA; - } - -- /* Bytes 2 - 6 should have 0 in the highest bit */ -- if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && -+ /* Bytes 2 - pktsize should have 0 in the highest bit */ -+ if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && - (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { - psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", - psmouse->pktcnt - 1, -@@ -368,7 +368,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) - return PSMOUSE_BAD_DATA; - } - -- if (psmouse->pktcnt == 6) { -+ if (psmouse->pktcnt == psmouse->pktsize) { - alps_process_packet(psmouse); - return PSMOUSE_FULL_PACKET; - } -@@ -529,7 +529,7 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) - static int alps_poll(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -- unsigned char buf[6]; -+ unsigned char buf[sizeof(psmouse->packet)]; - bool poll_failed; - - if (priv->i->flags & ALPS_PASS) --- -1.7.7.3 - - -From 25bded7cd60fa460e520e9f819bd06f4c5cb53f0 Mon Sep 17 00:00:00 2001 -From: Seth Forshee -Date: Mon, 7 Nov 2011 19:53:36 -0800 -Subject: [PATCH 4/6] Input: ALPS - add support for protocol versions 3 and 4 - -This patch adds support for two ALPS touchpad protocols not -supported currently by the driver, which I am arbitrarily naming -version 3 and version 4. Support is single-touch only at this time, -although both protocols are capable of limited multitouch support. - -Thanks to Andrew Skalski, who did the initial reverse-engineering -of the v3 protocol. - -Signed-off-by: Seth Forshee -Acked-by: Chase Douglas -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 791 +++++++++++++++++++++++++++++++++++++++-- - drivers/input/mouse/alps.h | 14 + - drivers/input/mouse/psmouse.h | 1 + - 3 files changed, 768 insertions(+), 38 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 44a0a71..a0248fd 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -23,6 +23,50 @@ - #include "psmouse.h" - #include "alps.h" - -+/* -+ * Definitions for ALPS version 3 and 4 command mode protocol -+ */ -+#define ALPS_CMD_NIBBLE_10 0x01f2 -+ -+static const struct alps_nibble_commands alps_v3_nibble_commands[] = { -+ { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ -+ { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ -+ { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ -+ { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ -+ { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ -+ { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ -+ { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ -+ { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ -+ { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ -+ { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ -+ { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ -+ { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ -+ { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ -+ { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ -+ { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ -+ { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ -+}; -+ -+static const struct alps_nibble_commands alps_v4_nibble_commands[] = { -+ { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */ -+ { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ -+ { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ -+ { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ -+ { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ -+ { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ -+ { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ -+ { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ -+ { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ -+ { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ -+ { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ -+ { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ -+ { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ -+ { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ -+ { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ -+ { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ -+}; -+ -+ - #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ - #define ALPS_PASS 0x04 /* device has a pass-through port */ - -@@ -34,30 +78,33 @@ - 6-byte ALPS packet */ - - static const struct alps_model_info alps_model_data[] = { -- { { 0x32, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ -- { { 0x33, 0x02, 0x0a }, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ -- { { 0x53, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x53, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x60, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ -- { { 0x63, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x02, 0x28 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ -- { { 0x63, 0x02, 0x3c }, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ -- { { 0x63, 0x02, 0x50 }, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ -- { { 0x63, 0x02, 0x64 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ -- { { 0x73, 0x00, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ -- { { 0x73, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x73, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ -- { { 0x20, 0x02, 0x0e }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ -- { { 0x22, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, -- { { 0x22, 0x02, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ -+ { { 0x32, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ -+ { { 0x33, 0x02, 0x0a }, 0x00, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ -+ { { 0x53, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x53, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x60, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ -+ { { 0x63, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x02, 0x28 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ -+ { { 0x63, 0x02, 0x3c }, 0x00, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ -+ { { 0x63, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ -+ { { 0x63, 0x02, 0x64 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ -+ { { 0x73, 0x00, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ -+ { { 0x73, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x73, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ -+ { { 0x20, 0x02, 0x0e }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ -+ { { 0x22, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, -+ { { 0x22, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ - /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ -- { { 0x62, 0x02, 0x14 }, ALPS_PROTO_V2, 0xcf, 0xcf, -+ { { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, - ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, -- { { 0x73, 0x02, 0x50 }, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ -- { { 0x52, 0x01, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, -- ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ -+ { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ -+ { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, -+ ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ -+ { { 0x73, 0x02, 0x64 }, 0x9b, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, -+ { { 0x73, 0x02, 0x64 }, 0x9d, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, -+ { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, - }; - - /* -@@ -101,7 +148,7 @@ static void alps_report_buttons(struct psmouse *psmouse, - input_sync(dev2); - } - --static void alps_process_packet(struct psmouse *psmouse) -+static void alps_process_packet_v1_v2(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; -@@ -203,6 +250,224 @@ static void alps_process_packet(struct psmouse *psmouse) - input_sync(dev); - } - -+static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ unsigned char *packet = psmouse->packet; -+ struct input_dev *dev = priv->dev2; -+ int x, y, z, left, right, middle; -+ -+ /* Sanity check packet */ -+ if (!(packet[0] & 0x40)) { -+ psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n"); -+ return; -+ } -+ -+ /* -+ * There's a special packet that seems to indicate the end -+ * of a stream of trackstick data. Filter these out. -+ */ -+ if (packet[1] == 0x7f && packet[2] == 0x7f && packet[4] == 0x7f) -+ return; -+ -+ x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f)); -+ y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f)); -+ z = (packet[4] & 0x7c) >> 2; -+ -+ /* -+ * The x and y values tend to be quite large, and when used -+ * alone the trackstick is difficult to use. Scale them down -+ * to compensate. -+ */ -+ x /= 8; -+ y /= 8; -+ -+ input_report_rel(dev, REL_X, x); -+ input_report_rel(dev, REL_Y, -y); -+ -+ /* -+ * Most ALPS models report the trackstick buttons in the touchpad -+ * packets, but a few report them here. No reliable way has been -+ * found to differentiate between the models upfront, so we enable -+ * the quirk in response to seeing a button press in the trackstick -+ * packet. -+ */ -+ left = packet[3] & 0x01; -+ right = packet[3] & 0x02; -+ middle = packet[3] & 0x04; -+ -+ if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) && -+ (left || right || middle)) -+ priv->quirks |= ALPS_QUIRK_TRACKSTICK_BUTTONS; -+ -+ if (priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) { -+ input_report_key(dev, BTN_LEFT, left); -+ input_report_key(dev, BTN_RIGHT, right); -+ input_report_key(dev, BTN_MIDDLE, middle); -+ } -+ -+ input_sync(dev); -+ return; -+} -+ -+static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ unsigned char *packet = psmouse->packet; -+ struct input_dev *dev = psmouse->dev; -+ struct input_dev *dev2 = priv->dev2; -+ int x, y, z; -+ int left, right, middle; -+ -+ /* -+ * There's no single feature of touchpad position and bitmap -+ * packets that can be used to distinguish between them. We -+ * rely on the fact that a bitmap packet should always follow -+ * a position packet with bit 6 of packet[4] set. -+ */ -+ if (priv->multi_packet) { -+ priv->multi_packet = 0; -+ -+ /* -+ * Sometimes a position packet will indicate a multi-packet -+ * sequence, but then what follows is another position -+ * packet. Check for this, and when it happens process the -+ * position packet as usual. -+ */ -+ if (packet[0] & 0x40) { -+ /* -+ * Bitmap packets are not yet supported, so for now -+ * just ignore them. -+ */ -+ return; -+ } -+ } -+ -+ if (!priv->multi_packet && (packet[4] & 0x40)) -+ priv->multi_packet = 1; -+ else -+ priv->multi_packet = 0; -+ -+ left = packet[3] & 0x01; -+ right = packet[3] & 0x02; -+ middle = packet[3] & 0x04; -+ -+ x = ((packet[1] & 0x7f) << 4) | ((packet[4] & 0x30) >> 2) | -+ ((packet[0] & 0x30) >> 4); -+ y = ((packet[2] & 0x7f) << 4) | (packet[4] & 0x0f); -+ z = packet[5] & 0x7f; -+ -+ /* -+ * Sometimes the hardware sends a single packet with z = 0 -+ * in the middle of a stream. Real releases generate packets -+ * with x, y, and z all zero, so these seem to be flukes. -+ * Ignore them. -+ */ -+ if (x && y && !z) -+ return; -+ -+ if (z >= 64) -+ input_report_key(dev, BTN_TOUCH, 1); -+ else -+ input_report_key(dev, BTN_TOUCH, 0); -+ -+ if (z > 0) { -+ input_report_abs(dev, ABS_X, x); -+ input_report_abs(dev, ABS_Y, y); -+ } -+ input_report_abs(dev, ABS_PRESSURE, z); -+ -+ input_report_key(dev, BTN_TOOL_FINGER, z > 0); -+ input_report_key(dev, BTN_LEFT, left); -+ input_report_key(dev, BTN_RIGHT, right); -+ input_report_key(dev, BTN_MIDDLE, middle); -+ -+ input_sync(dev); -+ -+ if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { -+ left = packet[3] & 0x10; -+ right = packet[3] & 0x20; -+ middle = packet[3] & 0x40; -+ -+ input_report_key(dev2, BTN_LEFT, left); -+ input_report_key(dev2, BTN_RIGHT, right); -+ input_report_key(dev2, BTN_MIDDLE, middle); -+ input_sync(dev2); -+ } -+} -+ -+static void alps_process_packet_v3(struct psmouse *psmouse) -+{ -+ unsigned char *packet = psmouse->packet; -+ -+ /* -+ * v3 protocol packets come in three types, two representing -+ * touchpad data and one representing trackstick data. -+ * Trackstick packets seem to be distinguished by always -+ * having 0x3f in the last byte. This value has never been -+ * observed in the last byte of either of the other types -+ * of packets. -+ */ -+ if (packet[5] == 0x3f) { -+ alps_process_trackstick_packet_v3(psmouse); -+ return; -+ } -+ -+ alps_process_touchpad_packet_v3(psmouse); -+} -+ -+static void alps_process_packet_v4(struct psmouse *psmouse) -+{ -+ unsigned char *packet = psmouse->packet; -+ struct input_dev *dev = psmouse->dev; -+ int x, y, z; -+ int left, right; -+ -+ left = packet[4] & 0x01; -+ right = packet[4] & 0x02; -+ -+ x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) | -+ ((packet[0] & 0x30) >> 4); -+ y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f); -+ z = packet[5] & 0x7f; -+ -+ if (z >= 64) -+ input_report_key(dev, BTN_TOUCH, 1); -+ else -+ input_report_key(dev, BTN_TOUCH, 0); -+ -+ if (z > 0) { -+ input_report_abs(dev, ABS_X, x); -+ input_report_abs(dev, ABS_Y, y); -+ } -+ input_report_abs(dev, ABS_PRESSURE, z); -+ -+ input_report_key(dev, BTN_TOOL_FINGER, z > 0); -+ input_report_key(dev, BTN_LEFT, left); -+ input_report_key(dev, BTN_RIGHT, right); -+ -+ input_sync(dev); -+} -+ -+static void alps_process_packet(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ const struct alps_model_info *model = priv->i; -+ -+ switch (model->proto_version) { -+ case ALPS_PROTO_V1: -+ case ALPS_PROTO_V2: -+ alps_process_packet_v1_v2(psmouse); -+ break; -+ case ALPS_PROTO_V3: -+ alps_process_packet_v3(psmouse); -+ break; -+ case ALPS_PROTO_V4: -+ alps_process_packet_v4(psmouse); -+ break; -+ } -+} -+ - static void alps_report_bare_ps2_packet(struct psmouse *psmouse, - unsigned char packet[], - bool report_buttons) -@@ -376,11 +641,127 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) - return PSMOUSE_GOOD_DATA; - } - -+static int alps_command_mode_send_nibble(struct psmouse *psmouse, int nibble) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ struct alps_data *priv = psmouse->private; -+ int command; -+ unsigned char *param; -+ unsigned char dummy[4]; -+ -+ BUG_ON(nibble > 0xf); -+ -+ command = priv->nibble_commands[nibble].command; -+ param = (command & 0x0f00) ? -+ dummy : (unsigned char *)&priv->nibble_commands[nibble].data; -+ -+ if (ps2_command(ps2dev, param, command)) -+ return -1; -+ -+ return 0; -+} -+ -+static int alps_command_mode_set_addr(struct psmouse *psmouse, int addr) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ struct alps_data *priv = psmouse->private; -+ int i, nibble; -+ -+ if (ps2_command(ps2dev, NULL, priv->addr_command)) -+ return -1; -+ -+ for (i = 12; i >= 0; i -= 4) { -+ nibble = (addr >> i) & 0xf; -+ if (alps_command_mode_send_nibble(psmouse, nibble)) -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static int __alps_command_mode_read_reg(struct psmouse *psmouse, int addr) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ unsigned char param[4]; -+ -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -+ return -1; -+ -+ /* -+ * The address being read is returned in the first two bytes -+ * of the result. Check that this address matches the expected -+ * address. -+ */ -+ if (addr != ((param[0] << 8) | param[1])) -+ return -1; -+ -+ return param[2]; -+} -+ -+static int alps_command_mode_read_reg(struct psmouse *psmouse, int addr) -+{ -+ if (alps_command_mode_set_addr(psmouse, addr)) -+ return -1; -+ return __alps_command_mode_read_reg(psmouse, addr); -+} -+ -+static int __alps_command_mode_write_reg(struct psmouse *psmouse, u8 value) -+{ -+ if (alps_command_mode_send_nibble(psmouse, (value >> 4) & 0xf)) -+ return -1; -+ if (alps_command_mode_send_nibble(psmouse, value & 0xf)) -+ return -1; -+ return 0; -+} -+ -+static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr, -+ u8 value) -+{ -+ if (alps_command_mode_set_addr(psmouse, addr)) -+ return -1; -+ return __alps_command_mode_write_reg(psmouse, value); -+} -+ -+static int alps_enter_command_mode(struct psmouse *psmouse, -+ unsigned char *resp) -+{ -+ unsigned char param[4]; -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ -+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -+ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { -+ psmouse_err(psmouse, "failed to enter command mode\n"); -+ return -1; -+ } -+ -+ if (param[0] != 0x88 && param[1] != 0x07) { -+ psmouse_dbg(psmouse, -+ "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", -+ param[0], param[1], param[2]); -+ return -1; -+ } -+ -+ if (resp) -+ *resp = param[2]; -+ return 0; -+} -+ -+static inline int alps_exit_command_mode(struct psmouse *psmouse) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) -+ return -1; -+ return 0; -+} -+ - static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) - { - struct ps2dev *ps2dev = &psmouse->ps2dev; - static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; - unsigned char param[4]; -+ const struct alps_model_info *model = NULL; - int i; - - /* -@@ -428,12 +809,41 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int - *version = (param[0] << 8) | (param[1] << 4) | i; - } - -- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) -+ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { - if (!memcmp(param, alps_model_data[i].signature, -- sizeof(alps_model_data[i].signature))) -- return alps_model_data + i; -+ sizeof(alps_model_data[i].signature))) { -+ model = alps_model_data + i; -+ break; -+ } -+ } - -- return NULL; -+ if (model && model->proto_version > ALPS_PROTO_V2) { -+ /* -+ * Need to check command mode response to identify -+ * model -+ */ -+ model = NULL; -+ if (alps_enter_command_mode(psmouse, param)) { -+ psmouse_warn(psmouse, -+ "touchpad failed to enter command mode\n"); -+ } else { -+ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { -+ if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && -+ alps_model_data[i].command_mode_resp == param[0]) { -+ model = alps_model_data + i; -+ break; -+ } -+ } -+ alps_exit_command_mode(psmouse); -+ -+ if (!model) -+ psmouse_dbg(psmouse, -+ "Unknown command mode response %2.2x\n", -+ param[0]); -+ } -+ } -+ -+ return model; - } - - /* -@@ -441,7 +851,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int - * subsequent commands. It looks like glidepad is behind stickpointer, - * I'd thought it would be other way around... - */ --static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) -+static int alps_passthrough_mode_v2(struct psmouse *psmouse, bool enable) - { - struct ps2dev *ps2dev = &psmouse->ps2dev; - int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; -@@ -458,7 +868,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) - return 0; - } - --static int alps_absolute_mode(struct psmouse *psmouse) -+static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) - { - struct ps2dev *ps2dev = &psmouse->ps2dev; - -@@ -533,13 +943,13 @@ static int alps_poll(struct psmouse *psmouse) - bool poll_failed; - - if (priv->i->flags & ALPS_PASS) -- alps_passthrough_mode(psmouse, true); -+ alps_passthrough_mode_v2(psmouse, true); - - poll_failed = ps2_command(&psmouse->ps2dev, buf, - PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; - - if (priv->i->flags & ALPS_PASS) -- alps_passthrough_mode(psmouse, false); -+ alps_passthrough_mode_v2(psmouse, false); - - if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) - return -1; -@@ -556,13 +966,13 @@ static int alps_poll(struct psmouse *psmouse) - return 0; - } - --static int alps_hw_init(struct psmouse *psmouse) -+static int alps_hw_init_v1_v2(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; - - if ((model->flags & ALPS_PASS) && -- alps_passthrough_mode(psmouse, true)) { -+ alps_passthrough_mode_v2(psmouse, true)) { - return -1; - } - -@@ -571,13 +981,13 @@ static int alps_hw_init(struct psmouse *psmouse) - return -1; - } - -- if (alps_absolute_mode(psmouse)) { -+ if (alps_absolute_mode_v1_v2(psmouse)) { - psmouse_err(psmouse, "Failed to enable absolute mode\n"); - return -1; - } - - if ((model->flags & ALPS_PASS) && -- alps_passthrough_mode(psmouse, false)) { -+ alps_passthrough_mode_v2(psmouse, false)) { - return -1; - } - -@@ -590,6 +1000,297 @@ static int alps_hw_init(struct psmouse *psmouse) - return 0; - } - -+/* -+ * Enable or disable passthrough mode to the trackstick. Must be in -+ * command mode when calling this function. -+ */ -+static int alps_passthrough_mode_v3(struct psmouse *psmouse, bool enable) -+{ -+ int reg_val; -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0008); -+ if (reg_val == -1) -+ return -1; -+ -+ if (enable) -+ reg_val |= 0x01; -+ else -+ reg_val &= ~0x01; -+ -+ if (__alps_command_mode_write_reg(psmouse, reg_val)) -+ return -1; -+ -+ return 0; -+} -+ -+/* Must be in command mode when calling this function */ -+static int alps_absolute_mode_v3(struct psmouse *psmouse) -+{ -+ int reg_val; -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0004); -+ if (reg_val == -1) -+ return -1; -+ -+ reg_val |= 0x06; -+ if (__alps_command_mode_write_reg(psmouse, reg_val)) -+ return -1; -+ -+ return 0; -+} -+ -+static int alps_hw_init_v3(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ int reg_val; -+ unsigned char param[4]; -+ -+ priv->nibble_commands = alps_v3_nibble_commands; -+ priv->addr_command = PSMOUSE_CMD_RESET_WRAP; -+ -+ if (alps_enter_command_mode(psmouse, NULL)) -+ goto error; -+ -+ /* Check for trackstick */ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0008); -+ if (reg_val == -1) -+ goto error; -+ if (reg_val & 0x80) { -+ if (alps_passthrough_mode_v3(psmouse, true)) -+ goto error; -+ if (alps_exit_command_mode(psmouse)) -+ goto error; -+ -+ /* -+ * E7 report for the trackstick -+ * -+ * There have been reports of failures to seem to trace back -+ * to the above trackstick check failing. When these occur -+ * this E7 report fails, so when that happens we continue -+ * with the assumption that there isn't a trackstick after -+ * all. -+ */ -+ param[0] = 0x64; -+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -+ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { -+ psmouse_warn(psmouse, "trackstick E7 report failed\n"); -+ } else { -+ psmouse_dbg(psmouse, -+ "trackstick E7 report: %2.2x %2.2x %2.2x\n", -+ param[0], param[1], param[2]); -+ -+ /* -+ * Not sure what this does, but it is absolutely -+ * essential. Without it, the touchpad does not -+ * work at all and the trackstick just emits normal -+ * PS/2 packets. -+ */ -+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -+ alps_command_mode_send_nibble(psmouse, 0x9) || -+ alps_command_mode_send_nibble(psmouse, 0x4)) { -+ psmouse_err(psmouse, -+ "Error sending magic E6 sequence\n"); -+ goto error_passthrough; -+ } -+ } -+ -+ if (alps_enter_command_mode(psmouse, NULL)) -+ goto error_passthrough; -+ if (alps_passthrough_mode_v3(psmouse, false)) -+ goto error; -+ } -+ -+ if (alps_absolute_mode_v3(psmouse)) { -+ psmouse_err(psmouse, "Failed to enter absolute mode\n"); -+ goto error; -+ } -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0006); -+ if (reg_val == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) -+ goto error; -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0007); -+ if (reg_val == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) -+ goto error; -+ -+ if (alps_command_mode_read_reg(psmouse, 0x0144) == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, 0x04)) -+ goto error; -+ -+ if (alps_command_mode_read_reg(psmouse, 0x0159) == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_read_reg(psmouse, 0x0163) == -1) -+ goto error; -+ if (alps_command_mode_write_reg(psmouse, 0x0163, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_read_reg(psmouse, 0x0162) == -1) -+ goto error; -+ if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04)) -+ goto error; -+ -+ /* -+ * This ensures the trackstick packets are in the format -+ * supported by this driver. If bit 1 isn't set the packet -+ * format is different. -+ */ -+ if (alps_command_mode_write_reg(psmouse, 0x0008, 0x82)) -+ goto error; -+ -+ alps_exit_command_mode(psmouse); -+ -+ /* Set rate and enable data reporting */ -+ param[0] = 0x64; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { -+ psmouse_err(psmouse, "Failed to enable data reporting\n"); -+ return -1; -+ } -+ -+ return 0; -+ -+error_passthrough: -+ /* Something failed while in passthrough mode, so try to get out */ -+ if (!alps_enter_command_mode(psmouse, NULL)) -+ alps_passthrough_mode_v3(psmouse, false); -+error: -+ /* -+ * Leaving the touchpad in command mode will essentially render -+ * it unusable until the machine reboots, so exit it here just -+ * to be safe -+ */ -+ alps_exit_command_mode(psmouse); -+ return -1; -+} -+ -+/* Must be in command mode when calling this function */ -+static int alps_absolute_mode_v4(struct psmouse *psmouse) -+{ -+ int reg_val; -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0004); -+ if (reg_val == -1) -+ return -1; -+ -+ reg_val |= 0x02; -+ if (__alps_command_mode_write_reg(psmouse, reg_val)) -+ return -1; -+ -+ return 0; -+} -+ -+static int alps_hw_init_v4(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ unsigned char param[4]; -+ -+ priv->nibble_commands = alps_v4_nibble_commands; -+ priv->addr_command = PSMOUSE_CMD_DISABLE; -+ -+ if (alps_enter_command_mode(psmouse, NULL)) -+ goto error; -+ -+ if (alps_absolute_mode_v4(psmouse)) { -+ psmouse_err(psmouse, "Failed to enter absolute mode\n"); -+ goto error; -+ } -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0007, 0x8c)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0149, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0160, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x017f, 0x15)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0151, 0x01)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0168, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x014a, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0161, 0x03)) -+ goto error; -+ -+ alps_exit_command_mode(psmouse); -+ -+ /* -+ * This sequence changes the output from a 9-byte to an -+ * 8-byte format. All the same data seems to be present, -+ * just in a more compact format. -+ */ -+ param[0] = 0xc8; -+ param[1] = 0x64; -+ param[2] = 0x50; -+ if (ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, ¶m[2], PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, param, PSMOUSE_CMD_GETID)) -+ return -1; -+ -+ /* Set rate and enable data reporting */ -+ param[0] = 0x64; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { -+ psmouse_err(psmouse, "Failed to enable data reporting\n"); -+ return -1; -+ } -+ -+ return 0; -+ -+error: -+ /* -+ * Leaving the touchpad in command mode will essentially render -+ * it unusable until the machine reboots, so exit it here just -+ * to be safe -+ */ -+ alps_exit_command_mode(psmouse); -+ return -1; -+} -+ -+static int alps_hw_init(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ const struct alps_model_info *model = priv->i; -+ int ret = -1; -+ -+ switch (model->proto_version) { -+ case ALPS_PROTO_V1: -+ case ALPS_PROTO_V2: -+ ret = alps_hw_init_v1_v2(psmouse); -+ break; -+ case ALPS_PROTO_V3: -+ ret = alps_hw_init_v3(psmouse); -+ break; -+ case ALPS_PROTO_V4: -+ ret = alps_hw_init_v4(psmouse); -+ break; -+ } -+ -+ return ret; -+} -+ - static int alps_reconnect(struct psmouse *psmouse) - { - const struct alps_model_info *model; -@@ -630,6 +1331,8 @@ int alps_init(struct psmouse *psmouse) - - psmouse->private = priv; - -+ psmouse_reset(psmouse); -+ - model = alps_get_model(psmouse, &version); - if (!model) - goto init_fail; -@@ -657,8 +1360,20 @@ int alps_init(struct psmouse *psmouse) - BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); - - dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); -- input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); -- input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); -+ -+ switch (model->proto_version) { -+ case ALPS_PROTO_V1: -+ case ALPS_PROTO_V2: -+ input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); -+ break; -+ case ALPS_PROTO_V3: -+ case ALPS_PROTO_V4: -+ input_set_abs_params(dev1, ABS_X, 0, 2000, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, 1400, 0, 0); -+ break; -+ } -+ - input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); - - if (model->flags & ALPS_WHEEL) { -@@ -701,7 +1416,7 @@ int alps_init(struct psmouse *psmouse) - psmouse->poll = alps_poll; - psmouse->disconnect = alps_disconnect; - psmouse->reconnect = alps_reconnect; -- psmouse->pktsize = 6; -+ psmouse->pktsize = model->proto_version == ALPS_PROTO_V4 ? 8 : 6; - - /* We are having trouble resyncing ALPS touchpads so disable it for now */ - psmouse->resync_time = 0; -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 4ce9bba..62db7f4 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -14,22 +14,36 @@ - - #define ALPS_PROTO_V1 0 - #define ALPS_PROTO_V2 1 -+#define ALPS_PROTO_V3 2 -+#define ALPS_PROTO_V4 3 - - struct alps_model_info { - unsigned char signature[3]; -+ unsigned char command_mode_resp; /* v3/v4 only */ - unsigned char proto_version; - unsigned char byte0, mask0; - unsigned char flags; - }; - -+struct alps_nibble_commands { -+ int command; -+ unsigned char data; -+}; -+ - struct alps_data { - struct input_dev *dev2; /* Relative device */ - char phys[32]; /* Phys */ - const struct alps_model_info *i;/* Info */ -+ const struct alps_nibble_commands *nibble_commands; -+ int addr_command; /* Command to set register address */ - int prev_fin; /* Finger bit from previous packet */ -+ int multi_packet; /* Multi-packet data in progress */ -+ u8 quirks; - struct timer_list timer; - }; - -+#define ALPS_QUIRK_TRACKSTICK_BUTTONS 1 /* trakcstick buttons in trackstick packet */ -+ - #ifdef CONFIG_MOUSE_PS2_ALPS - int alps_detect(struct psmouse *psmouse, bool set_properties); - int alps_init(struct psmouse *psmouse); -diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h -index 9b84b0c..11a9c6c 100644 ---- a/drivers/input/mouse/psmouse.h -+++ b/drivers/input/mouse/psmouse.h -@@ -8,6 +8,7 @@ - #define PSMOUSE_CMD_SETSTREAM 0x00ea - #define PSMOUSE_CMD_SETPOLL 0x00f0 - #define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */ -+#define PSMOUSE_CMD_RESET_WRAP 0x00ec - #define PSMOUSE_CMD_GETID 0x02f2 - #define PSMOUSE_CMD_SETRATE 0x10f3 - #define PSMOUSE_CMD_ENABLE 0x00f4 --- -1.7.7.3 - - -From 01ce661fc83005947dc958a5739c153843af8a73 Mon Sep 17 00:00:00 2001 -From: Seth Forshee -Date: Mon, 7 Nov 2011 19:54:13 -0800 -Subject: [PATCH 5/6] Input: ALPS - add semi-MT support for v3 protocol - -Signed-off-by: Seth Forshee -Acked-by: Chase Douglas -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 233 ++++++++++++++++++++++++++++++++++++++++---- - drivers/input/mouse/alps.h | 1 + - 2 files changed, 215 insertions(+), 19 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index a0248fd..bd87380 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -17,6 +17,7 @@ - - #include - #include -+#include - #include - #include - -@@ -26,6 +27,12 @@ - /* - * Definitions for ALPS version 3 and 4 command mode protocol - */ -+#define ALPS_V3_X_MAX 2000 -+#define ALPS_V3_Y_MAX 1400 -+ -+#define ALPS_BITMAP_X_BITS 15 -+#define ALPS_BITMAP_Y_BITS 11 -+ - #define ALPS_CMD_NIBBLE_10 0x01f2 - - static const struct alps_nibble_commands alps_v3_nibble_commands[] = { -@@ -250,6 +257,137 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) - input_sync(dev); - } - -+/* -+ * Process bitmap data from v3 and v4 protocols. Returns the number of -+ * fingers detected. A return value of 0 means at least one of the -+ * bitmaps was empty. -+ * -+ * The bitmaps don't have enough data to track fingers, so this function -+ * only generates points representing a bounding box of all contacts. -+ * These points are returned in x1, y1, x2, and y2 when the return value -+ * is greater than 0. -+ */ -+static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, -+ int *x1, int *y1, int *x2, int *y2) -+{ -+ struct alps_bitmap_point { -+ int start_bit; -+ int num_bits; -+ }; -+ -+ int fingers_x = 0, fingers_y = 0, fingers; -+ int i, bit, prev_bit; -+ struct alps_bitmap_point x_low = {0,}, x_high = {0,}; -+ struct alps_bitmap_point y_low = {0,}, y_high = {0,}; -+ struct alps_bitmap_point *point; -+ -+ if (!x_map || !y_map) -+ return 0; -+ -+ *x1 = *y1 = *x2 = *y2 = 0; -+ -+ prev_bit = 0; -+ point = &x_low; -+ for (i = 0; x_map != 0; i++, x_map >>= 1) { -+ bit = x_map & 1; -+ if (bit) { -+ if (!prev_bit) { -+ point->start_bit = i; -+ fingers_x++; -+ } -+ point->num_bits++; -+ } else { -+ if (prev_bit) -+ point = &x_high; -+ else -+ point->num_bits = 0; -+ } -+ prev_bit = bit; -+ } -+ -+ /* -+ * y bitmap is reversed for what we need (lower positions are in -+ * higher bits), so we process from the top end. -+ */ -+ y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - ALPS_BITMAP_Y_BITS); -+ prev_bit = 0; -+ point = &y_low; -+ for (i = 0; y_map != 0; i++, y_map <<= 1) { -+ bit = y_map & (1 << (sizeof(y_map) * BITS_PER_BYTE - 1)); -+ if (bit) { -+ if (!prev_bit) { -+ point->start_bit = i; -+ fingers_y++; -+ } -+ point->num_bits++; -+ } else { -+ if (prev_bit) -+ point = &y_high; -+ else -+ point->num_bits = 0; -+ } -+ prev_bit = bit; -+ } -+ -+ /* -+ * Fingers can overlap, so we use the maximum count of fingers -+ * on either axis as the finger count. -+ */ -+ fingers = max(fingers_x, fingers_y); -+ -+ /* -+ * If total fingers is > 1 but either axis reports only a single -+ * contact, we have overlapping or adjacent fingers. For the -+ * purposes of creating a bounding box, divide the single contact -+ * (roughly) equally between the two points. -+ */ -+ if (fingers > 1) { -+ if (fingers_x == 1) { -+ i = x_low.num_bits / 2; -+ x_low.num_bits = x_low.num_bits - i; -+ x_high.start_bit = x_low.start_bit + i; -+ x_high.num_bits = max(i, 1); -+ } else if (fingers_y == 1) { -+ i = y_low.num_bits / 2; -+ y_low.num_bits = y_low.num_bits - i; -+ y_high.start_bit = y_low.start_bit + i; -+ y_high.num_bits = max(i, 1); -+ } -+ } -+ -+ *x1 = (ALPS_V3_X_MAX * (2 * x_low.start_bit + x_low.num_bits - 1)) / -+ (2 * (ALPS_BITMAP_X_BITS - 1)); -+ *y1 = (ALPS_V3_Y_MAX * (2 * y_low.start_bit + y_low.num_bits - 1)) / -+ (2 * (ALPS_BITMAP_Y_BITS - 1)); -+ -+ if (fingers > 1) { -+ *x2 = (ALPS_V3_X_MAX * (2 * x_high.start_bit + x_high.num_bits - 1)) / -+ (2 * (ALPS_BITMAP_X_BITS - 1)); -+ *y2 = (ALPS_V3_Y_MAX * (2 * y_high.start_bit + y_high.num_bits - 1)) / -+ (2 * (ALPS_BITMAP_Y_BITS - 1)); -+ } -+ -+ return fingers; -+} -+ -+static void alps_set_slot(struct input_dev *dev, int slot, bool active, -+ int x, int y) -+{ -+ input_mt_slot(dev, slot); -+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); -+ if (active) { -+ input_report_abs(dev, ABS_MT_POSITION_X, x); -+ input_report_abs(dev, ABS_MT_POSITION_Y, y); -+ } -+} -+ -+static void alps_report_semi_mt_data(struct input_dev *dev, int num_fingers, -+ int x1, int y1, int x2, int y2) -+{ -+ alps_set_slot(dev, 0, num_fingers != 0, x1, y1); -+ alps_set_slot(dev, 1, num_fingers == 2, x2, y2); -+} -+ - static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -@@ -318,16 +456,17 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - struct input_dev *dev2 = priv->dev2; - int x, y, z; - int left, right, middle; -+ int x1 = 0, y1 = 0, x2 = 0, y2 = 0; -+ int fingers = 0, bmap_fingers; -+ unsigned int x_bitmap, y_bitmap; - - /* -- * There's no single feature of touchpad position and bitmap -- * packets that can be used to distinguish between them. We -- * rely on the fact that a bitmap packet should always follow -- * a position packet with bit 6 of packet[4] set. -+ * There's no single feature of touchpad position and bitmap packets -+ * that can be used to distinguish between them. We rely on the fact -+ * that a bitmap packet should always follow a position packet with -+ * bit 6 of packet[4] set. - */ - if (priv->multi_packet) { -- priv->multi_packet = 0; -- - /* - * Sometimes a position packet will indicate a multi-packet - * sequence, but then what follows is another position -@@ -335,18 +474,49 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - * position packet as usual. - */ - if (packet[0] & 0x40) { -+ fingers = (packet[5] & 0x3) + 1; -+ x_bitmap = ((packet[4] & 0x7e) << 8) | -+ ((packet[1] & 0x7f) << 2) | -+ ((packet[0] & 0x30) >> 4); -+ y_bitmap = ((packet[3] & 0x70) << 4) | -+ ((packet[2] & 0x7f) << 1) | -+ (packet[4] & 0x01); -+ -+ bmap_fingers = alps_process_bitmap(x_bitmap, y_bitmap, -+ &x1, &y1, &x2, &y2); -+ - /* -- * Bitmap packets are not yet supported, so for now -- * just ignore them. -+ * We shouldn't report more than one finger if -+ * we don't have two coordinates. - */ -- return; -+ if (fingers > 1 && bmap_fingers < 2) -+ fingers = bmap_fingers; -+ -+ /* Now process position packet */ -+ packet = priv->multi_data; -+ } else { -+ priv->multi_packet = 0; - } - } - -- if (!priv->multi_packet && (packet[4] & 0x40)) -+ /* -+ * Bit 6 of byte 0 is not usually set in position packets. The only -+ * times it seems to be set is in situations where the data is -+ * suspect anyway, e.g. a palm resting flat on the touchpad. Given -+ * this combined with the fact that this bit is useful for filtering -+ * out misidentified bitmap packets, we reject anything with this -+ * bit set. -+ */ -+ if (packet[0] & 0x40) -+ return; -+ -+ if (!priv->multi_packet && (packet[4] & 0x40)) { - priv->multi_packet = 1; -- else -- priv->multi_packet = 0; -+ memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); -+ return; -+ } -+ -+ priv->multi_packet = 0; - - left = packet[3] & 0x01; - right = packet[3] & 0x02; -@@ -366,22 +536,38 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - if (x && y && !z) - return; - -+ /* -+ * If we don't have MT data or the bitmaps were empty, we have -+ * to rely on ST data. -+ */ -+ if (!fingers) { -+ x1 = x; -+ y1 = y; -+ fingers = z > 0 ? 1 : 0; -+ } -+ - if (z >= 64) - input_report_key(dev, BTN_TOUCH, 1); - else - input_report_key(dev, BTN_TOUCH, 0); - -+ alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); -+ -+ input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); -+ input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); -+ input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); -+ input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4); -+ -+ input_report_key(dev, BTN_LEFT, left); -+ input_report_key(dev, BTN_RIGHT, right); -+ input_report_key(dev, BTN_MIDDLE, middle); -+ - if (z > 0) { - input_report_abs(dev, ABS_X, x); - input_report_abs(dev, ABS_Y, y); - } - input_report_abs(dev, ABS_PRESSURE, z); - -- input_report_key(dev, BTN_TOOL_FINGER, z > 0); -- input_report_key(dev, BTN_LEFT, left); -- input_report_key(dev, BTN_RIGHT, right); -- input_report_key(dev, BTN_MIDDLE, middle); -- - input_sync(dev); - - if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { -@@ -1368,9 +1554,18 @@ int alps_init(struct psmouse *psmouse) - input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); - break; - case ALPS_PROTO_V3: -+ set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); -+ input_mt_init_slots(dev1, 2); -+ input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); -+ input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); -+ -+ set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); -+ set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); -+ set_bit(BTN_TOOL_QUADTAP, dev1->keybit); -+ /* fall through */ - case ALPS_PROTO_V4: -- input_set_abs_params(dev1, ABS_X, 0, 2000, 0, 0); -- input_set_abs_params(dev1, ABS_Y, 0, 1400, 0, 0); -+ input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); - break; - } - -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 62db7f4..a00a4ab 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -38,6 +38,7 @@ struct alps_data { - int addr_command; /* Command to set register address */ - int prev_fin; /* Finger bit from previous packet */ - int multi_packet; /* Multi-packet data in progress */ -+ unsigned char multi_data[6]; /* Saved multi-packet data */ - u8 quirks; - struct timer_list timer; - }; --- -1.7.7.3 - - -From 7cf801cfc0774b777aa6861cf4a43a90b112b1ed Mon Sep 17 00:00:00 2001 -From: Seth Forshee -Date: Mon, 7 Nov 2011 19:54:35 -0800 -Subject: [PATCH 6/6] Input: ALPS - add documentation for protocol versions 3 - and 4 - -Also converts from using "old" and "new" to describe the already-known -protocols to using "version 1" and "version 2" to match the code. - -Signed-off-by: Seth Forshee -Acked-by: Chase Douglas -Signed-off-by: Dmitry Torokhov ---- - Documentation/input/alps.txt | 135 ++++++++++++++++++++++++++++++++++++++---- - 1 files changed, 124 insertions(+), 11 deletions(-) - -diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt -index ab5478f..f274c28 100644 ---- a/Documentation/input/alps.txt -+++ b/Documentation/input/alps.txt -@@ -4,12 +4,9 @@ ALPS Touchpad Protocol - Introduction - ------------ - --Currently the ALPS touchpad driver supports two protocol versions in use by --ALPS touchpads, the "old" and "new" protocol versions. Fundamentally these --differ only in the format of their event packets (in reality many features may --be found on new protocol devices that aren't found on the old protocol --devices, but these are handled transparently as feature differences rather --than protocol differences). -+Currently the ALPS touchpad driver supports four protocol versions in use by -+ALPS touchpads, called versions 1, 2, 3, and 4. Information about the various -+protocol versions is contained in the following sections. - - Detection - --------- -@@ -22,10 +19,37 @@ If the E6 report is successful, the touchpad model is identified using the "E7 - report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is - matched against known models in the alps_model_data_array. - -+With protocol versions 3 and 4, the E7 report model signature is always -+73-02-64. To differentiate between these versions, the response from the -+"Enter Command Mode" sequence must be inspected as described below. -+ -+Command Mode -+------------ -+ -+Protocol versions 3 and 4 have a command mode that is used to read and write -+one-byte device registers in a 16-bit address space. The command sequence -+EC-EC-EC-E9 places the device in command mode, and the device will respond -+with 88-07 followed by a third byte. This third byte can be used to determine -+whether the devices uses the version 3 or 4 protocol. -+ -+To exit command mode, PSMOUSE_CMD_SETSTREAM (EA) is sent to the touchpad. -+ -+While in command mode, register addresses can be set by first sending a -+specific command, either EC for v3 devices or F5 for v4 devices. Then the -+address is sent one nibble at a time, where each nibble is encoded as a -+command with optional data. This enoding differs slightly between the v3 and -+v4 protocols. -+ -+Once an address has been set, the addressed register can be read by sending -+PSMOUSE_CMD_GETINFO (E9). The first two bytes of the response contains the -+address of the register being read, and the third contains the value of the -+register. Registers are written by writing the value one nibble at a time -+using the same encoding used for addresses. -+ - Packet Format - ------------- - --In the following tables, the following notation us used. -+In the following tables, the following notation is used. - - CAPITALS = stick, miniscules = touchpad - -@@ -41,8 +65,8 @@ PS/2 packet format - - Note that the device never signals overflow condition. - --ALPS Absolute Mode - Old Format --------------------------------- -+ALPS Absolute Mode - Protocol Verion 1 -+-------------------------------------- - - byte 0: 1 0 0 0 1 x9 x8 x7 - byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -@@ -51,8 +75,8 @@ ALPS Absolute Mode - Old Format - byte 4: 0 y6 y5 y4 y3 y2 y1 y0 - byte 5: 0 z6 z5 z4 z3 z2 z1 z0 - --ALPS Absolute Mode - New Format --------------------------------- -+ALPS Absolute Mode - Protocol Version 2 -+--------------------------------------- - - byte 0: 1 ? ? ? 1 ? ? ? - byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -@@ -73,3 +97,92 @@ Dualpoint device -- interleaved packet format - byte 6: 0 y9 y8 y7 1 m r l - byte 7: 0 y6 y5 y4 y3 y2 y1 y0 - byte 8: 0 z6 z5 z4 z3 z2 z1 z0 -+ -+ALPS Absolute Mode - Protocol Version 3 -+--------------------------------------- -+ -+ALPS protocol version 3 has three different packet formats. The first two are -+associated with touchpad events, and the third is associatd with trackstick -+events. -+ -+The first type is the touchpad position packet. -+ -+ byte 0: 1 ? x1 x0 1 1 1 1 -+ byte 1: 0 x10 x9 x8 x7 x6 x5 x4 -+ byte 2: 0 y10 y9 y8 y7 y6 y5 y4 -+ byte 3: 0 M R L 1 m r l -+ byte 4: 0 mt x3 x2 y3 y2 y1 y0 -+ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 -+ -+Note that for some devices the trackstick buttons are reported in this packet, -+and on others it is reported in the trackstick packets. -+ -+The second packet type contains bitmaps representing the x and y axes. In the -+bitmaps a given bit is set if there is a finger covering that position on the -+given axis. Thus the bitmap packet can be used for low-resolution multi-touch -+data, although finger tracking is not possible. This packet also encodes the -+number of contacts (f1 and f0 in the table below). -+ -+ byte 0: 1 1 x1 x0 1 1 1 1 -+ byte 1: 0 x8 x7 x6 x5 x4 x3 x2 -+ byte 2: 0 y7 y6 y5 y4 y3 y2 y1 -+ byte 3: 0 y10 y9 y8 1 1 1 1 -+ byte 4: 0 x14 x13 x12 x11 x10 x9 y0 -+ byte 5: 0 1 ? ? ? ? f1 f0 -+ -+This packet only appears after a position packet with the mt bit set, and -+ususally only appears when there are two or more contacts (although -+ocassionally it's seen with only a single contact). -+ -+The final v3 packet type is the trackstick packet. -+ -+ byte 0: 1 1 x7 y7 1 1 1 1 -+ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -+ byte 2: 0 y6 y5 y4 y3 y2 y1 y0 -+ byte 3: 0 1 0 0 1 0 0 0 -+ byte 4: 0 z4 z3 z2 z1 z0 ? ? -+ byte 5: 0 0 1 1 1 1 1 1 -+ -+ALPS Absolute Mode - Protocol Version 4 -+--------------------------------------- -+ -+Protocol version 4 has an 8-byte packet format. -+ -+ byte 0: 1 ? x1 x0 1 1 1 1 -+ byte 1: 0 x10 x9 x8 x7 x6 x5 x4 -+ byte 2: 0 y10 y9 y8 y7 y6 y5 y4 -+ byte 3: 0 1 x3 x2 y3 y2 y1 y0 -+ byte 4: 0 ? ? ? 1 ? r l -+ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 -+ byte 6: bitmap data (described below) -+ byte 7: bitmap data (described below) -+ -+The last two bytes represent a partial bitmap packet, with 3 full packets -+required to construct a complete bitmap packet. Once assembled, the 6-byte -+bitmap packet has the following format: -+ -+ byte 0: 0 1 x7 x6 x5 x4 x3 x2 -+ byte 1: 0 x1 x0 y4 y3 y2 y1 y0 -+ byte 2: 0 0 ? x14 x13 x12 x11 x10 -+ byte 3: 0 x9 x8 y9 y8 y7 y6 y5 -+ byte 4: 0 0 0 0 0 0 0 0 -+ byte 5: 0 0 0 0 0 0 0 y10 -+ -+There are several things worth noting here. -+ -+ 1) In the bitmap data, bit 6 of byte 0 serves as a sync byte to -+ identify the first fragment of a bitmap packet. -+ -+ 2) The bitmaps represent the same data as in the v3 bitmap packets, although -+ the packet layout is different. -+ -+ 3) There doesn't seem to be a count of the contact points anywhere in the v4 -+ protocol packets. Deriving a count of contact points must be done by -+ analyzing the bitmaps. -+ -+ 4) There is a 3 to 1 ratio of position packets to bitmap packets. Therefore -+ MT position can only be updated for every third ST position update, and -+ the count of contact points can only be updated every third packet as -+ well. -+ -+So far no v4 devices with tracksticks have been encountered. --- -1.7.7.3 - diff --git a/arm-build-bug-on.patch b/arm-build-bug-on.patch deleted file mode 100644 index deb0998d6..000000000 --- a/arm-build-bug-on.patch +++ /dev/null @@ -1,28 +0,0 @@ -BUILD_BUG_ON is defined in linux/kernel.h but that is not included by the -asm/bug.h header which uses it. This causes a build error: - -...include/linux/mtd/map.h: In function 'inline_map_read': -...include/linux/mtd/map.h:408:3: error: implicit declaration of function -'BUILD_BUG_ON' [-Werror=implicit-function-declaration] - -The check is not essential and is not present for other architectures, so -just remove it. - -Signed-off-by: Simon Glass chromium.org> ---- - arch/arm/include/asm/bug.h | 1 - - 1 files changed, 0 insertions(+), 1 deletions(-) - -diff --git a/arch/arm/include/asm/bug.h b/arch/arm/include/asm/bug.h -index 9abe7a0..fac79dc 100644 ---- a/arch/arm/include/asm/bug.h -+++ b/arch/arm/include/asm/bug.h -@@ -32,7 +32,6 @@ - - #define __BUG(__file, __line, __value) \ - do { \ -- BUILD_BUG_ON(sizeof(struct bug_entry) != 12); \ - asm volatile("1:\t" BUG_INSTR_TYPE #__value "\n" \ - ".pushsection .rodata.str, \"aMS\", %progbits, 1\n" \ - "2:\t.asciz " #__file "\n" \ --- diff --git a/arm-stmmac-mmc-core.patch b/arm-stmmac-mmc-core.patch deleted file mode 100644 index 469fe42d4..000000000 --- a/arm-stmmac-mmc-core.patch +++ /dev/null @@ -1,26 +0,0 @@ -Fix this error: - - CC drivers/net/ethernet/stmicro/stmmac/mmc_core.o -drivers/net/ethernet/stmicro/stmmac/mmc_core.c: In function 'dwmac_mmc_ctrl': -drivers/net/ethernet/stmicro/stmmac/mmc_core.c:143:2: error: implicit - declaration of function 'pr_debug' [-Werror=implicit-function-declaration] - -Signed-off-by: Stefan Roese denx.de> -Cc: Giuseppe Cavallaro st.com> ---- - drivers/net/ethernet/stmicro/stmmac/mmc_core.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c -index 41e6b33..c07cfe9 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c -@@ -22,6 +22,7 @@ - Author: Giuseppe Cavallaro st.com> - *******************************************************************************/ - -+#include - #include - #include "mmc.h" - --- diff --git a/bcma-brcmsmac-compat.patch b/bcma-brcmsmac-compat.patch index e16e5b0c5..269cc862f 100644 --- a/bcma-brcmsmac-compat.patch +++ b/bcma-brcmsmac-compat.patch @@ -22,14 +22,14 @@ diff -up linux-3.1.x86_64/drivers/bcma/host_pci.c.orig linux-3.1.x86_64/drivers/ { 0, }, }; MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl); -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig 2011-11-10 11:42:31.764930961 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig 2011-11-10 11:42:33.613907846 -0500 -@@ -5,7 +5,6 @@ config BRCMSMAC + +--- linux-2.6.43.noarch/drivers/net/wireless/brcm80211/Kconfig~ 2012-03-26 12:37:17.512820450 -0400 ++++ linux-2.6.43.noarch/drivers/net/wireless/brcm80211/Kconfig 2012-03-26 12:37:36.270777605 -0400 +@@ -4,7 +4,6 @@ config BRCMUTIL + config BRCMSMAC tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" - depends on PCI depends on MAC80211 -- depends on BCMA=n +- depends on BCMA select BRCMUTIL select FW_LOADER select CRC_CCITT diff --git a/bluetooth-use-after-free.patch b/bluetooth-use-after-free.patch new file mode 100644 index 000000000..0d21cad9a --- /dev/null +++ b/bluetooth-use-after-free.patch @@ -0,0 +1,105 @@ +From 2a5a5ec620a29d4ba07743c3151cdf0a417c8f8c Mon Sep 17 00:00:00 2001 +From: Andrei Emeltchenko +Date: Thu, 2 Feb 2012 10:32:18 +0200 +Subject: [PATCH] Bluetooth: Use list _safe deleting from conn chan_list + +Fixes possible bug when deleting element from the list in +function hci_chan_list_flush. list_for_each_entry_rcu is used +and after deleting element from the list we also free pointer +and then list_entry_rcu is taken from freed pointer. + +Signed-off-by: Andrei Emeltchenko +Acked-by: Marcel Holtmann +Signed-off-by: Johan Hedberg +--- + net/bluetooth/hci_conn.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index b074bd6..b4ecdde 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -975,10 +975,10 @@ int hci_chan_del(struct hci_chan *chan) + + void hci_chan_list_flush(struct hci_conn *conn) + { +- struct hci_chan *chan; ++ struct hci_chan *chan, *n; + + BT_DBG("conn %p", conn); + +- list_for_each_entry_rcu(chan, &conn->chan_list, list) ++ list_for_each_entry_safe(chan, n, &conn->chan_list, list) + hci_chan_del(chan); + } +-- +1.7.6.5 + +From 3c4e0df028935618d052235ba85bc7079be13394 Mon Sep 17 00:00:00 2001 +From: Andrei Emeltchenko +Date: Thu, 2 Feb 2012 10:32:17 +0200 +Subject: [PATCH] Bluetooth: Use list _safe deleting from conn_hash_list + +Use list_for_each_entry_safe which is safe version against removal +of list entry. Otherwise we remove hci_conn element and reference +next element which result in accessing LIST_POISON. + +[ 95.571834] Bluetooth: unknown link type 127 +[ 95.578349] BUG: unable to handle kernel paging request at 20002000 +[ 95.580236] IP: [<20002000>] 0x20001fff +[ 95.580763] *pde = 00000000 +[ 95.581196] Oops: 0000 [#1] SMP +... +[ 95.582298] Pid: 3355, comm: hciconfig Tainted: G O 3.2.0-VirttualBox +[ 95.582298] EIP: 0060:[<20002000>] EFLAGS: 00210206 CPU: 0 +[ 95.582298] EIP is at 0x20002000 +... +[ 95.582298] Call Trace: +[ 95.582298] [] ? hci_conn_hash_flush+0x76/0xf0 [bluetooth] +[ 95.582298] [] hci_dev_do_close+0xc1/0x2e0 [bluetooth] +[ 95.582298] [] ? hci_dev_get+0x69/0xb0 [bluetooth] +[ 95.582298] [] hci_dev_close+0x2a/0x50 [bluetooth] +[ 95.582298] [] hci_sock_ioctl+0x1af/0x3f0 [bluetooth] +[ 95.582298] [] ? handle_pte_fault+0x8a/0x8f0 +[ 95.582298] [] sock_ioctl+0x5f/0x260 +[ 95.582298] [] ? sock_fasync+0x90/0x90 +[ 95.582298] [] do_vfs_ioctl+0x83/0x5b0 +[ 95.582298] [] ? do_page_fault+0x297/0x500 +[ 95.582298] [] ? spurious_fault+0xd0/0xd0 +[ 95.582298] [] ? up_read+0x1b/0x30 +[ 95.582298] [] ? do_page_fault+0x297/0x500 +[ 95.582298] [] ? init_fpu+0xef/0x160 +[ 95.582298] [] ? do_debug+0x180/0x180 +[ 95.582298] [] ? fpu_finit+0x28/0x80 +[ 95.582298] [] sys_ioctl+0x87/0x90 +[ 95.582298] [] sysenter_do_call+0x12/0x38 +... + +Signed-off-by: Andrei Emeltchenko +Acked-by: Marcel Holtmann +Signed-off-by: Johan Hedberg +--- + net/bluetooth/hci_conn.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index aca71c0..b074bd6 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -795,11 +795,11 @@ timer: + void hci_conn_hash_flush(struct hci_dev *hdev) + { + struct hci_conn_hash *h = &hdev->conn_hash; +- struct hci_conn *c; ++ struct hci_conn *c, *n; + + BT_DBG("hdev %s", hdev->name); + +- list_for_each_entry_rcu(c, &h->list, list) { ++ list_for_each_entry_safe(c, n, &h->list, list) { + c->state = BT_CLOSED; + + hci_proto_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM); +-- +1.7.6.5 + diff --git a/cdc-acm-tiocgserial.patch b/cdc-acm-tiocgserial.patch deleted file mode 100644 index ec82506e8..000000000 --- a/cdc-acm-tiocgserial.patch +++ /dev/null @@ -1,58 +0,0 @@ -From http://permalink.gmane.org/gmane.linux.usb.general/9236 - -attempt to diagnose https://bugzilla.redhat.com/show_bug.cgi?id=787607 - -diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c -index 9543b19..6dcc3a3 100644 ---- a/drivers/usb/class/cdc-acm.c -+++ b/drivers/usb/class/cdc-acm.c -@@ -39,6 +39,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -734,15 +734,40 @@ static int acm_tty_tiocmset(struct tty_s - return acm_set_control(acm, acm->ctrlout = newctrl); - } - -+static int get_serial_info(struct acm *acm, struct serial_struct __user *info) -+{ -+ struct serial_struct tmp; -+ -+ if (!info) -+ return -EINVAL; -+ -+ memset(&tmp, 0, sizeof(tmp)); -+ tmp.flags = ASYNC_LOW_LATENCY; -+ tmp.xmit_fifo_size = acm->writesize; -+ tmp.baud_base = le32_to_cpu(acm->line.dwDTERate); -+ -+ if (copy_to_user(info, &tmp, sizeof(tmp))) -+ return -EFAULT; -+ else -+ return 0; -+} -+ - static int acm_tty_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) - { - struct acm *acm = tty->driver_data; -+ int rv = -ENOIOCTLCMD; - - if (!ACM_READY(acm)) - return -EINVAL; - -- return -ENOIOCTLCMD; -+ switch (cmd) { -+ case TIOCGSERIAL: /* gets serial port data */ -+ rv = get_serial_info(acm, (struct serial_struct __user *) arg); -+ break; -+ } -+ -+ return rv; - } - - static const __u32 acm_tty_speed[] = { diff --git a/config-arm-generic b/config-arm-generic index 4f44a3e37..2ad9ca63c 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -186,9 +186,6 @@ CONFIG_LSM_MMAP_MIN_ADDR=32768 # CONFIG_DRM_NOUVEAU is not set # CONFIG_MLX4_EN is not set -# drivers/input/touchscreen/eeti_ts.c:65:2: error: implicit declaration of function 'irq_to_gpio' [-Werror=implicit-function-declaration] -# CONFIG_TOUCHSCREEN_EETI is not set - # FIXME: Guesses, need checking # CONFIG_MACH_EUKREA_CPUIMX35SD is not set CONFIG_ARM_ERRATA_720789=y @@ -197,3 +194,15 @@ CONFIG_ARM_ERRATA_751472=y # CONFIG_MX3_IPU is not set # CONFIG_MX3_IPU_IRQS is not set +# CONFIG_OF_SELFTEST is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set + +# CONFIG_MACH_IMX51_DT is not set +# CONFIG_MACH_IMX53_DT is not set +# CONFIG_MACH_MX53_EVK is not set +# CONFIG_MACH_MX53_SMD is not set +# CONFIG_MACH_MX53_LOCO is not set +# CONFIG_MACH_MX53_ARD is not set +# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set diff --git a/config-arm-highbank b/config-arm-highbank index d4aca8222..8cd7fc3b5 100644 --- a/config-arm-highbank +++ b/config-arm-highbank @@ -14,3 +14,4 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m CONFIG_CPU_FREQ_TABLE=y CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_NET_CALXEDA_XGMAC=y diff --git a/config-arm-imx b/config-arm-imx index 7aa2c779b..2dbe10a1f 100644 --- a/config-arm-imx +++ b/config-arm-imx @@ -33,7 +33,7 @@ CONFIG_MXC_IRQ_PRIOR=y CONFIG_MXC_PWM=m CONFIG_MXC_DEBUG_BOARD=y # CONFIG_CPU_BPREDICT_DISABLE is not set -CONFIG_CACHE_L2X0=y +# CONFIG_CACHE_L2X0 is not set CONFIG_ARM_DMA_MEM_BUFFERABLE=y CONFIG_ARM_ERRATA_411920=y CONFIG_PL310_ERRATA_588369=y @@ -56,7 +56,7 @@ CONFIG_DVB_TDA1004X=m CONFIG_DVB_PLL=m CONFIG_SND_IMX_SOC=m CONFIG_USB_EHCI_MXC=y -# CONFIG_USB_IMX21_HCD is not set +CONFIG_USB_IMX21_HCD=m CONFIG_MMC_SDHCI_ESDHC_IMX=m CONFIG_MMC_MXC=m CONFIG_RTC_MXC=m diff --git a/config-arm-kirkwood b/config-arm-kirkwood index 5eb6a3db3..415e822dc 100644 --- a/config-arm-kirkwood +++ b/config-arm-kirkwood @@ -39,3 +39,5 @@ CONFIG_LEDS_NETXBIG=m CONFIG_RTC_DRV_MV=m CONFIG_MV_XOR=y CONFIG_CRYPTO_DEV_MV_CESA=m + +# CONFIG_TOUCHSCREEN_EETI is not set diff --git a/config-arm-omap-generic b/config-arm-omap-generic index d623e1817..de17513e4 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -1083,3 +1083,14 @@ CONFIG_LEDS_RENESAS_TPU=y # CONFIG_OMAP_IOMMU is not set CONFIG_USB_RENESAS_USBHS_HCD=m +# CONFIG_SOC_OMAPTI81XX is not set +# CONFIG_SOC_OMAPAM33XX is not set +# CONFIG_MACH_TI8148EVM is not set +# CONFIG_OMAP4_ERRATA_I688 is not set +# CONFIG_ARM_LPAE is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_S5M_CORE is not set +# CONFIG_VIDEO_AS3645A is not set diff --git a/config-arm-tegra b/config-arm-tegra index 11f060d06..9658d4989 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -68,7 +68,6 @@ CONFIG_KEYBOARD_NVEC=y CONFIG_SERIO_NVEC_PS2=y CONFIG_NVEC_POWER=y CONFIG_POWER_SUPPLY=y -CONFIG_NVEC_LEDS=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_DEBUG=y @@ -91,3 +90,12 @@ CONFIG_ARM_CPU_TOPOLOGY=y CONFIG_SCHED_MC=y CONFIG_SCHED_SMT=y CONFIG_LEDS_RENESAS_TPU=y + +# CONFIG_ARCH_TEGRA_2x_SOC is not set +# CONFIG_ARCH_TEGRA_3x_SOC is not set +# CONFIG_ETHERNET is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_DVB_TDA1004X is not set +# CONFIG_DVB_PLL is not set +# CONFIG_SND_SOC_TEGRA_ALC5632 is not set + diff --git a/config-generic b/config-generic index 72d4bd172..299df87e4 100644 --- a/config-generic +++ b/config-generic @@ -4600,7 +4600,57 @@ CONFIG_BCMA_HOST_PCI=y # CONFIG_BCMA_DEBUG is not set # CONFIG_GOOGLE_FIRMWARE is not set -CONFIG_INTEL_MID_PTI=m +# CONFIG_INTEL_MID_PTI is not set CONFIG_IOMMU_SUPPORT=y # CONFIG_PM_DEVFREQ is not set +# CONFIG_AUDIT_LOGINUID_IMMUTABLE is not set +CONFIG_CGROUP_MEM_RES_CTLR_KMEM=y +CONFIG_UNIX_DIAG=m +CONFIG_INET_UDP_DIAG=m +CONFIG_NETFILTER_NETLINK_ACCT=m +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NETFILTER_XT_MATCH_ECN=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_IP_VS_SH_TAB_BITS=8 +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_OPENVSWITCH=m +CONFIG_NETPRIO_CGROUP=m +# CONFIG_BLK_DEV_NVME is not set +CONFIG_NET_TEAM=m +CONFIG_NET_TEAM_MODE_ROUNDROBIN=m +CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m +CONFIG_NET_CALXEDA_XGMAC=m +# CONFIG_STMMAC_PLATFORM is not set +# CONFIG_STMMAC_PCI is not set +CONFIG_ATH9K_BTCOEX_SUPPORT=y +# CONFIG_B43_BCMA_EXTRA is not set +CONFIG_BRCMFMAC_SDIO=y +# CONFIG_IWLWIFI_P2P is not set +CONFIG_IWLEGACY_DEBUG=y +CONFIG_IWLEGACY_DEBUGFS=y +CONFIG_IWLEGACY_DEBUGFS=y +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +CONFIG_TOUCHSCREEN_EGALAX=m +CONFIG_TOUCHSCREEN_PIXCIR=m +# CONFIG_BATTERY_SBS is not set +# CONFIG_CHARGER_LP8727 is not set +CONFIG_IR_SANYO_DECODER=m +CONFIG_MEDIA_TUNER_MT2063=m +CONFIG_USB_GSPCA_JL2005BCD=m +CONFIG_V4L_PCI_DRIVERS=y +# CONFIG_V4L_ISA_PARPORT_DRIVERS is not set +# CONFIG_V4L_PLATFORM_DRIVERS is not set +CONFIG_DVB_HD29L2=m +CONFIG_HID_ROCCAT_ISKU=m +CONFIG_HID_WIIMOTE_EXT=y +# CONFIG_USB_EHCI_MV is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_OT200 is not set +CONFIG_INFINIBAND_SRPT=m +# CONFIG_RTLLIB is not set +# CONFIG_ANDROID is not set +# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_NFSD_FAULT_INJECTION is not set diff --git a/config-powerpc-generic b/config-powerpc-generic index 2ca0c3e83..9e6a92222 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -353,3 +353,10 @@ CONFIG_RFKILL_GPIO=m # Disable btrfs until it is shown to work with 64k pages (rhbz 747079) # CONFIG_BTRFS_FS is not set +# CONFIG_OF_SELFTEST is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_CPU_IDLE is not set +# CONFIG_V4L_RADIO_ISA_DRIVERS is not set +CONFIG_STRICT_DEVMEM=y diff --git a/config-powerpc64 b/config-powerpc64 index 42b501675..c5c569752 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -158,3 +158,6 @@ CONFIG_IO_EVENT_IRQ=y CONFIG_HW_RANDOM_AMD=m CONFIG_BPF_JIT=y +# CONFIG_PPC_ICSWX_PID is not set +# CONFIG_PPC_ICSWX_USE_SIGILL is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set diff --git a/config-sparc64-generic b/config-sparc64-generic index e9b66f6d6..2b29f9b7e 100644 --- a/config-sparc64-generic +++ b/config-sparc64-generic @@ -195,3 +195,4 @@ CONFIG_CRYPTO_DEV_NIAGARA2=y # CONFIG_MTD_OF_PARTS is not set # CONFIG_MTD_PHYSMAP_OF is not set # CONFIG_MMC_SDHCI_OF is not set +# CONFIG_OF_SELFTEST is not set diff --git a/config-x86-32-generic b/config-x86-32-generic index 3b55ae521..3f4fc346f 100644 --- a/config-x86-32-generic +++ b/config-x86-32-generic @@ -203,3 +203,7 @@ CONFIG_I2O_BUS=m # CONFIG_EDAC_SBRIDGE is not set # CONFIG_X86_WANT_INTEL_MID is not set +# CONFIG_OF_SELFTEST is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set diff --git a/config-x86-generic b/config-x86-generic index c57aa12d3..9f9f5b5b8 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -384,3 +384,15 @@ CONFIG_RELOCATABLE=y # CONFIG_HYPERV is not set +CONFIG_EFI_STUB=y +CONFIG_PCI_IOAPIC=y +CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m +CONFIG_VIA_WDT=m +# CONFIG_V4L_RADIO_ISA_DRIVERS is not set +CONFIG_DRM_GMA500=m +CONFIG_FUJITSU_TABLET=m +CONFIG_AMILO_RFKILL=m +# CONFIG_DEBUG_NMI_SELFTEST is not set +CONFIG_CRYPTO_SERPENT_SSE2_586=m +# CONFIG_DRM_GMA600 is not set +# CONFIG_DRM_GMA3600 is not set diff --git a/config-x86_64-generic b/config-x86_64-generic index f5b440a73..a41b45015 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -118,3 +118,6 @@ CONFIG_BPF_JIT=y # Should be 32bit only, but lacks KConfig depends # CONFIG_XO15_EBOOK is not set +# CONFIG_X86_NUMACHIP is not set +CONFIG_AMD_IOMMU_V2=m +CONFIG_CRYPTO_SERPENT_SSE2_X86_64=m diff --git a/drm-i915-dp-stfu.patch b/drm-i915-dp-stfu.patch new file mode 100644 index 000000000..8948229dc --- /dev/null +++ b/drm-i915-dp-stfu.patch @@ -0,0 +1,69 @@ +From 04a43e2598db35b3d0ec25925bb8475b5c0a3809 Mon Sep 17 00:00:00 2001 +From: Adam Jackson +Date: Fri, 16 Mar 2012 16:39:11 -0400 +Subject: [PATCH] drm/i915/dp: Use DRM_ERROR not WARN for sanity checks + +These are noisy as shit and creating a ton of abrt reports. I don't +need more, thanks. Proper fix upstream eventually. + +Signed-off-by: Adam Jackson +--- + drivers/gpu/drm/i915/intel_dp.c | 14 ++++++++------ + 1 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c +index 94f860c..6bf27c9 100644 +--- a/drivers/gpu/drm/i915/intel_dp.c ++++ b/drivers/gpu/drm/i915/intel_dp.c +@@ -331,7 +331,7 @@ intel_dp_check_edp(struct intel_dp *intel_dp) + if (!is_edp(intel_dp)) + return; + if (!ironlake_edp_have_panel_power(intel_dp) && !ironlake_edp_have_panel_vdd(intel_dp)) { +- WARN(1, "eDP powered off while attempting aux channel communication.\n"); ++ DRM_ERROR("eDP powered off while attempting aux channel communication.\n"); + DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n", + I915_READ(PCH_PP_STATUS), + I915_READ(PCH_PP_CONTROL)); +@@ -386,7 +386,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, + } + + if (try == 3) { +- WARN(1, "dp_aux_ch not started status 0x%08x\n", ++ DRM_ERROR("dp_aux_ch not started status 0x%08x\n", + I915_READ(ch_ctl)); + return -EBUSY; + } +@@ -992,8 +992,8 @@ static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) + return; + DRM_DEBUG_KMS("Turn eDP VDD on\n"); + +- WARN(intel_dp->want_panel_vdd, +- "eDP VDD already requested on\n"); ++ if (intel_dp->want_panel_vdd) ++ DRM_ERROR("eDP VDD already requested on\n"); + + intel_dp->want_panel_vdd = true; + +@@ -1058,7 +1058,8 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) + return; + + DRM_DEBUG_KMS("Turn eDP VDD off %d\n", intel_dp->want_panel_vdd); +- WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on"); ++ if (!intel_dp->want_panel_vdd) ++ DRM_ERROR("eDP VDD not forced on"); + + intel_dp->want_panel_vdd = false; + +@@ -1128,7 +1129,8 @@ static void ironlake_edp_panel_off(struct intel_dp *intel_dp) + + DRM_DEBUG_KMS("Turn eDP power off\n"); + +- WARN(intel_dp->want_panel_vdd, "Cannot turn power off while VDD is on\n"); ++ if (intel_dp->want_panel_vdd) ++ DRM_ERROR("Cannot turn power off while VDD is on\n"); + + pp = ironlake_get_pp_control(dev_priv); + pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE); +-- +1.7.7.6 + diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch deleted file mode 100644 index e69de29bb..000000000 diff --git a/e1000e-Avoid-wrong-check-on-TX-hang.patch b/e1000e-Avoid-wrong-check-on-TX-hang.patch deleted file mode 100644 index 6064ddde8..000000000 --- a/e1000e-Avoid-wrong-check-on-TX-hang.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 09357b00255c233705b1cf6d76a8d147340545b8 Mon Sep 17 00:00:00 2001 -From: Jeff Kirsher -Date: Fri, 18 Nov 2011 14:25:00 +0000 -Subject: [PATCH] e1000e: Avoid wrong check on TX hang - -Based on the original patch submitted my Michael Wang -. -Descriptors may not be write-back while checking TX hang with flag -FLAG2_DMA_BURST on. -So when we detect hang, we just flush the descriptor and detect -again for once. - --v2 change 1 to true and 0 to false and remove extra () - -CC: Michael Wang -CC: Flavio Leitner -Acked-by: Jesse Brandeburg -Tested-by: Aaron Brown -Signed-off-by: Jeff Kirsher ---- - drivers/net/ethernet/intel/e1000e/e1000.h | 1 + - drivers/net/ethernet/intel/e1000e/netdev.c | 23 ++++++++++++++++++++--- - 2 files changed, 21 insertions(+), 3 deletions(-) - -diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h -index 9fe18d1..f478a22 100644 ---- a/drivers/net/ethernet/intel/e1000e/e1000.h -+++ b/drivers/net/ethernet/intel/e1000e/e1000.h -@@ -309,6 +309,7 @@ struct e1000_adapter { - u32 txd_cmd; - - bool detect_tx_hung; -+ bool tx_hang_recheck; - u8 tx_timeout_factor; - - u32 tx_int_delay; -diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c -index c6e9763..c12df69 100644 ---- a/drivers/net/ethernet/intel/e1000e/netdev.c -+++ b/drivers/net/ethernet/intel/e1000e/netdev.c -@@ -1014,6 +1014,7 @@ static void e1000_print_hw_hang(struct work_struct *work) - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, - print_hang_task); -+ struct net_device *netdev = adapter->netdev; - struct e1000_ring *tx_ring = adapter->tx_ring; - unsigned int i = tx_ring->next_to_clean; - unsigned int eop = tx_ring->buffer_info[i].next_to_watch; -@@ -1025,6 +1026,21 @@ static void e1000_print_hw_hang(struct work_struct *work) - if (test_bit(__E1000_DOWN, &adapter->state)) - return; - -+ if (!adapter->tx_hang_recheck && -+ (adapter->flags2 & FLAG2_DMA_BURST)) { -+ /* May be block on write-back, flush and detect again -+ * flush pending descriptor writebacks to memory -+ */ -+ ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); -+ /* execute the writes immediately */ -+ e1e_flush(); -+ adapter->tx_hang_recheck = true; -+ return; -+ } -+ /* Real hang detected */ -+ adapter->tx_hang_recheck = false; -+ netif_stop_queue(netdev); -+ - e1e_rphy(hw, PHY_STATUS, &phy_status); - e1e_rphy(hw, PHY_1000T_STATUS, &phy_1000t_status); - e1e_rphy(hw, PHY_EXT_STATUS, &phy_ext_status); -@@ -1145,10 +1161,10 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) - if (tx_ring->buffer_info[i].time_stamp && - time_after(jiffies, tx_ring->buffer_info[i].time_stamp - + (adapter->tx_timeout_factor * HZ)) && -- !(er32(STATUS) & E1000_STATUS_TXOFF)) { -+ !(er32(STATUS) & E1000_STATUS_TXOFF)) - schedule_work(&adapter->print_hang_task); -- netif_stop_queue(netdev); -- } -+ else -+ adapter->tx_hang_recheck = false; - } - adapter->total_tx_bytes += total_tx_bytes; - adapter->total_tx_packets += total_tx_packets; -@@ -3838,6 +3854,7 @@ static int e1000_open(struct net_device *netdev) - - e1000_irq_enable(adapter); - -+ adapter->tx_hang_recheck = false; - netif_start_queue(netdev); - - adapter->idle_check = true; --- -1.7.9 - diff --git a/ext3-Fix-error-handling-on-inode-bitmap-corruption.patch b/ext3-Fix-error-handling-on-inode-bitmap-corruption.patch deleted file mode 100644 index 73cc52228..000000000 --- a/ext3-Fix-error-handling-on-inode-bitmap-corruption.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 1415dd8705394399d59a3df1ab48d149e1e41e77 Mon Sep 17 00:00:00 2001 -From: Jan Kara -Date: Thu, 8 Dec 2011 21:13:46 +0100 -Subject: [PATCH] ext3: Fix error handling on inode bitmap corruption - -When insert_inode_locked() fails in ext3_new_inode() it most likely -means inode bitmap got corrupted and we allocated again inode which -is already in use. Also doing unlock_new_inode() during error recovery -is wrong since inode does not have I_NEW set. Fix the problem by jumping -to fail: (instead of fail_drop:) which declares filesystem error and -does not call unlock_new_inode(). - -Reviewed-by: Eric Sandeen -Signed-off-by: Jan Kara ---- - fs/ext3/ialloc.c | 8 ++++++-- - 1 files changed, 6 insertions(+), 2 deletions(-) - -diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c -index 5c866e0..adae962 100644 ---- a/fs/ext3/ialloc.c -+++ b/fs/ext3/ialloc.c -@@ -525,8 +525,12 @@ got: - if (IS_DIRSYNC(inode)) - handle->h_sync = 1; - if (insert_inode_locked(inode) < 0) { -- err = -EINVAL; -- goto fail_drop; -+ /* -+ * Likely a bitmap corruption causing inode to be allocated -+ * twice. -+ */ -+ err = -EIO; -+ goto fail; - } - spin_lock(&sbi->s_next_gen_lock); - inode->i_generation = sbi->s_next_generation++; --- -1.7.6.5 - diff --git a/ext4-Fix-error-handling-on-inode-bitmap-corruption.patch b/ext4-Fix-error-handling-on-inode-bitmap-corruption.patch deleted file mode 100644 index e22a2b4ff..000000000 --- a/ext4-Fix-error-handling-on-inode-bitmap-corruption.patch +++ /dev/null @@ -1,19 +0,0 @@ -diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c -index 00beb4f..8fb6844 100644 ---- a/fs/ext4/ialloc.c -+++ b/fs/ext4/ialloc.c -@@ -885,8 +885,12 @@ got: - if (IS_DIRSYNC(inode)) - ext4_handle_sync(handle); - if (insert_inode_locked(inode) < 0) { -- err = -EINVAL; -- goto fail_drop; -+ /* -+ * Likely a bitmap corruption causing inode to be allocated -+ * twice. -+ */ -+ err = -EIO; -+ goto fail; - } - spin_lock(&sbi->s_next_gen_lock); - inode->i_generation = sbi->s_next_generation++; diff --git a/hibernate-freeze-filesystems.patch b/hibernate-freeze-filesystems.patch index dfb2f0478..841cab643 100644 --- a/hibernate-freeze-filesystems.patch +++ b/hibernate-freeze-filesystems.patch @@ -1,59 +1,35 @@ -From: Rafael J. Wysocki +commit b94887bbc0621e1e8402e7f0ec4bc3adf46c9a6e +Author: Rafael J. Wysocki +Date: Fri Feb 17 12:42:08 2012 -0500 -Freeze all filesystems during system suspend and (kernel-driven) -hibernation by calling freeze_supers() for all superblocks and thaw -them during the subsequent resume with the help of thaw_supers(). + Freeze all filesystems during system suspend and (kernel-driven) + hibernation by calling freeze_supers() for all superblocks and thaw + them during the subsequent resume with the help of thaw_supers(). + + This makes filesystems stay in a consistent state in case something + goes wrong between system suspend (or hibernation) and the subsequent + resume (e.g. journal replays won't be necessary in those cases). In + particular, this should help to solve a long-standing issue that, in + some cases, during resume from hibernation the boot loader causes the + journal to be replied for the filesystem containing the kernel image + and/or initrd causing it to become inconsistent with the information + stored in the hibernation image. + + The user-space-driven hibernation (s2disk) is not covered by this + change, because the freezing of filesystems prevents s2disk from + accessing device special files it needs to do its job. + + This change is based on earlier work by Nigel Cunningham. + + Signed-off-by: Rafael J. Wysocki + + Rebased to 3.3-rc3 by Josh Boyer -This makes filesystems stay in a consistent state in case something -goes wrong between system suspend (or hibernation) and the subsequent -resume (e.g. journal replays won't be necessary in those cases). In -particular, this should help to solve a long-standing issue that, in -some cases, during resume from hibernation the boot loader causes the -journal to be replied for the filesystem containing the kernel image -and/or initrd causing it to become inconsistent with the information -stored in the hibernation image. - -The user-space-driven hibernation (s2disk) is not covered by this -change, because the freezing of filesystems prevents s2disk from -accessing device special files it needs to do its job. - -This change is based on earlier work by Nigel Cunningham. - -Signed-off-by: Rafael J. Wysocki ---- - fs/super.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++ - include/linux/fs.h | 3 + - kernel/power/hibernate.c | 11 +++++-- - kernel/power/power.h | 23 -------------- - kernel/power/suspend.c | 42 +++++++++++++++++++++++++++ - 5 files changed, 128 insertions(+), 24 deletions(-) - -Index: linux/include/linux/fs.h -=================================================================== ---- linux.orig/include/linux/fs.h -+++ linux/include/linux/fs.h -@@ -210,6 +210,7 @@ struct inodes_stat_t { - #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */ - #define MS_I_VERSION (1<<23) /* Update inode I_version field */ - #define MS_STRICTATIME (1<<24) /* Always perform atime updates */ -+#define MS_FROZEN (1<<25) /* Frozen filesystem */ - #define MS_NOSEC (1<<28) - #define MS_BORN (1<<29) - #define MS_ACTIVE (1<<30) -@@ -2501,6 +2502,8 @@ extern void drop_super(struct super_bloc - extern void iterate_supers(void (*)(struct super_block *, void *), void *); - extern void iterate_supers_type(struct file_system_type *, - void (*)(struct super_block *, void *), void *); -+extern int freeze_supers(void); -+extern void thaw_supers(void); - - extern int dcache_dir_open(struct inode *, struct file *); - extern int dcache_dir_close(struct inode *, struct file *); -Index: linux/fs/super.c -=================================================================== ---- linux.orig/fs/super.c -+++ linux/fs/super.c -@@ -594,6 +594,79 @@ void iterate_supers_type(struct file_sys +diff --git a/fs/super.c b/fs/super.c +index 6015c02..c8057fa 100644 +--- a/fs/super.c ++++ b/fs/super.c +@@ -594,6 +594,79 @@ void iterate_supers_type(struct file_system_type *type, EXPORT_SYMBOL(iterate_supers_type); /** @@ -65,7 +41,7 @@ Index: linux/fs/super.c + + spin_lock(&sb_lock); + list_for_each_entry(sb, &super_blocks, s_list) { -+ if (list_empty(&sb->s_instances)) ++ if (hlist_unhashed(&sb->s_instances)) + continue; + sb->s_count++; + spin_unlock(&sb_lock); @@ -99,7 +75,7 @@ Index: linux/fs/super.c + * frozen in the right order (eg. loopback on ext3). + */ + list_for_each_entry_reverse(sb, &super_blocks, s_list) { -+ if (list_empty(&sb->s_instances)) ++ if (hlist_unhashed(&sb->s_instances)) + continue; + sb->s_count++; + spin_unlock(&sb_lock); @@ -133,98 +109,31 @@ Index: linux/fs/super.c * get_super - get the superblock of a device * @bdev: device to get the superblock for * -Index: linux/kernel/power/power.h -=================================================================== ---- linux.orig/kernel/power/power.h -+++ linux/kernel/power/power.h -@@ -1,3 +1,4 @@ -+#include - #include - #include - #include -@@ -227,25 +228,3 @@ enum { - #define TEST_MAX (__TEST_AFTER_LAST - 1) +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 386da09..a164f4a 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -210,6 +210,7 @@ struct inodes_stat_t { + #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */ + #define MS_I_VERSION (1<<23) /* Update inode I_version field */ + #define MS_STRICTATIME (1<<24) /* Always perform atime updates */ ++#define MS_FROZEN (1<<25) /* Frozen filesystem */ + #define MS_NOSEC (1<<28) + #define MS_BORN (1<<29) + #define MS_ACTIVE (1<<30) +@@ -2501,6 +2502,8 @@ extern void drop_super(struct super_block *sb); + extern void iterate_supers(void (*)(struct super_block *, void *), void *); + extern void iterate_supers_type(struct file_system_type *, + void (*)(struct super_block *, void *), void *); ++extern int freeze_supers(void); ++extern void thaw_supers(void); - extern int pm_test_level; -- --#ifdef CONFIG_SUSPEND_FREEZER --static inline int suspend_freeze_processes(void) --{ -- int error = freeze_processes(); -- return error ? : freeze_kernel_threads(); --} -- --static inline void suspend_thaw_processes(void) --{ -- thaw_processes(); --} --#else --static inline int suspend_freeze_processes(void) --{ -- return 0; --} -- --static inline void suspend_thaw_processes(void) --{ --} --#endif -Index: linux/kernel/power/suspend.c -=================================================================== ---- linux.orig/kernel/power/suspend.c -+++ linux/kernel/power/suspend.c -@@ -29,6 +29,48 @@ - - #include "power.h" - -+#ifdef CONFIG_SUSPEND_FREEZER -+ -+static inline int suspend_freeze_processes(void) -+{ -+ int error; -+ -+ error = freeze_processes(); -+ if (error) -+ return error; -+ -+ error = freeze_supers(); -+ if (error) { -+ thaw_processes(); -+ return error; -+ } -+ -+ error = freeze_kernel_threads(); -+ if (error) -+ thaw_supers(); -+ -+ return error; -+} -+ -+static inline void suspend_thaw_processes(void) -+{ -+ thaw_supers(); -+ thaw_processes(); -+} -+ -+#else /* !CONFIG_SUSPEND_FREEZER */ -+ -+static inline int suspend_freeze_processes(void) -+{ -+ return 0; -+} -+ -+static inline void suspend_thaw_processes(void) -+{ -+} -+ -+#endif /* !CONFIG_SUSPEND_FREEZER */ -+ - const char *const pm_states[PM_SUSPEND_MAX] = { - [PM_SUSPEND_STANDBY] = "standby", - [PM_SUSPEND_MEM] = "mem", -Index: linux/kernel/power/hibernate.c -=================================================================== ---- linux.orig/kernel/power/hibernate.c -+++ linux/kernel/power/hibernate.c + extern int dcache_dir_open(struct inode *, struct file *); + extern int dcache_dir_close(struct inode *, struct file *); +diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c +index 6d6d288..492fc62 100644 +--- a/kernel/power/hibernate.c ++++ b/kernel/power/hibernate.c @@ -626,12 +626,17 @@ int hibernate(void) if (error) goto Finish; @@ -254,4 +163,125 @@ Index: linux/kernel/power/hibernate.c Thaw: thaw_processes(); Finish: - +diff --git a/kernel/power/power.h b/kernel/power/power.h +index 21724ee..40d6f64 100644 +--- a/kernel/power/power.h ++++ b/kernel/power/power.h +@@ -1,3 +1,4 @@ ++#include + #include + #include + #include +@@ -227,45 +228,3 @@ enum { + #define TEST_MAX (__TEST_AFTER_LAST - 1) + + extern int pm_test_level; +- +-#ifdef CONFIG_SUSPEND_FREEZER +-static inline int suspend_freeze_processes(void) +-{ +- int error; +- +- error = freeze_processes(); +- +- /* +- * freeze_processes() automatically thaws every task if freezing +- * fails. So we need not do anything extra upon error. +- */ +- if (error) +- goto Finish; +- +- error = freeze_kernel_threads(); +- +- /* +- * freeze_kernel_threads() thaws only kernel threads upon freezing +- * failure. So we have to thaw the userspace tasks ourselves. +- */ +- if (error) +- thaw_processes(); +- +- Finish: +- return error; +-} +- +-static inline void suspend_thaw_processes(void) +-{ +- thaw_processes(); +-} +-#else +-static inline int suspend_freeze_processes(void) +-{ +- return 0; +-} +- +-static inline void suspend_thaw_processes(void) +-{ +-} +-#endif +diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c +index 4fd51be..5f51fc7 100644 +--- a/kernel/power/suspend.c ++++ b/kernel/power/suspend.c +@@ -29,6 +29,62 @@ + + #include "power.h" + ++#ifdef CONFIG_SUSPEND_FREEZER ++ ++static inline int suspend_freeze_processes(void) ++{ ++ int error; ++ ++ error = freeze_processes(); ++ ++ /* ++ * freeze_processes() automatically thaws every task if freezing ++ * fails. So we need not do anything extra upon error. ++ */ ++ ++ if (error) ++ goto Finish; ++ ++ error = freeze_supers(); ++ if (error) { ++ thaw_processes(); ++ goto Finish; ++ } ++ ++ error = freeze_kernel_threads(); ++ ++ /* ++ * freeze_kernel_threads() thaws only kernel threads upon freezing ++ * failure. So we have to thaw the userspace tasks ourselves. ++ */ ++ if (error) { ++ thaw_supers(); ++ thaw_processes(); ++ } ++ ++Finish: ++ return error; ++} ++ ++static inline void suspend_thaw_processes(void) ++{ ++ thaw_supers(); ++ thaw_processes(); ++} ++ ++#else /* !CONFIG_SUSPEND_FREEZER */ ++ ++static inline int suspend_freeze_processes(void) ++{ ++ return 0; ++} ++ ++static inline void suspend_thaw_processes(void) ++{ ++} ++ ++#endif /* !CONFIG_SUSPEND_FREEZER */ ++ + const char *const pm_states[PM_SUSPEND_MAX] = { + [PM_SUSPEND_STANDBY] = "standby", + [PM_SUSPEND_MEM] = "mem", diff --git a/hpsa-add-irqf-shared.patch b/hpsa-add-irqf-shared.patch deleted file mode 100644 index d29e2353e..000000000 --- a/hpsa-add-irqf-shared.patch +++ /dev/null @@ -1,34 +0,0 @@ -hpsa: Add IRQF_SHARED back in for the non-MSI(X) interrupt handler - -From: Stephen M. Cameron - -IRQF_SHARED is required for older controllers that don't support MSI(X) -and which may end up sharing an interrupt. All the controllers hpsa -normally supports have MSI(X) capability, but older controllers may be -encountered via the hpsa_allow_any=1 module parameter. - -Also remove deprecated IRQF_DISABLED. - -Signed-off-by: Stephen M. Cameron ---- - drivers/scsi/hpsa.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -RHBZ 754907 -diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c -index 865d452..594ce83 100644 ---- a/drivers/scsi/hpsa.c -+++ b/drivers/scsi/hpsa.c -@@ -4072,10 +4072,10 @@ static int hpsa_request_irq(struct ctlr_info *h, - - if (h->msix_vector || h->msi_vector) - rc = request_irq(h->intr[h->intr_mode], msixhandler, -- IRQF_DISABLED, h->devname, h); -+ 0, h->devname, h); - else - rc = request_irq(h->intr[h->intr_mode], intxhandler, -- IRQF_DISABLED, h->devname, h); -+ IRQF_SHARED, h->devname, h); - if (rc) { - dev_err(&h->pdev->dev, "unable to get irq %d for %s\n", - h->intr[h->intr_mode], h->devname); diff --git a/kernel.spec b/kernel.spec index 891b77f6e..078b63cbb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,16 +42,16 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with -%define real_sublevel 2 +%define real_sublevel 3 # fake_sublevel is the 2.6.x version we're faking %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # Do we have a -stable update to apply? -%define stable_update 13 +%define stable_update 0 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -600,6 +600,7 @@ Patch470: die-floppy-die.patch Patch471: floppy-drop-disable_hlt-warning.patch Patch510: linux-2.6-silence-noise.patch +Patch511: silence-timekeeping-spew.patch Patch520: quite-apm.patch Patch530: linux-2.6-silence-fbcon-logo.patch @@ -614,10 +615,10 @@ Patch1500: fix_xen_guest_on_old_EC2.patch # DRM -# nouveau + drm fixes -Patch1810: drm-nouveau-updates.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch +Patch1825: drm-i915-dp-stfu.patch + # hush the i915 fbc noise Patch1826: drm-i915-fbc-stfu.patch @@ -640,7 +641,6 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 Patch4000: NFSv4-Reduce-the-footprint-of-the-idmapper.patch Patch4001: NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch -Patch4003: NFSv4-Save-the-owner-group-name-string-when-doing-op.patch # patches headed upstream @@ -648,89 +648,57 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch -Patch13002: revert-efi-rtclock.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch -Patch14000: cdc-acm-tiocgserial.patch +Patch14000: hibernate-freeze-filesystems.patch -Patch15000: hibernate-freeze-filesystems.patch +Patch14010: lis3-improve-handling-of-null-rate.patch -Patch15010: lis3-improve-handling-of-null-rate.patch +Patch15000: bluetooth-use-after-free.patch Patch20000: utrace.patch # Flattened devicetree support Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch -Patch21002: arm-build-bug-on.patch -Patch21003: arm-stmmac-mmc-core.patch Patch21004: arm-tegra-nvec-kconfig.patch -#rhbz 717735 -Patch21045: nfs-client-freezer.patch - -#rhbz 590880 -Patch21050: alps.patch - Patch21070: ext4-Support-check-none-nocheck-mount-options.patch -Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch -Patch21072: ext3-Fix-error-handling-on-inode-bitmap-corruption.patch #rhbz 769766 -Patch21073: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch - -#rhbz 773392 -Patch21074: KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch -Patch21075: KVM-x86-fix-missing-checks-in-syscall-emulation.patch - -#rhbz 728740 -Patch21076: rtl8192cu-Fix-WARNING-on-suspend-resume.patch - -#rhbz752176 -Patch21080: sysfs-msi-irq-per-device.patch - -#rhbz 782686 -Patch21082: procfs-parse-mount-options.patch -Patch21083: procfs-add-hidepid-and-gid-mount-options.patch -Patch21084: proc-fix-null-pointer-deref-in-proc_pid_permission.patch - -#rhbz 788260 -Patch21085: jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch +Patch21072: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 Patch21091: bcma-brcmsmac-compat.patch -#rhbz 785806 -Patch21092: e1000e-Avoid-wrong-check-on-TX-hang.patch +#rhbz 772772 +Patch21232: rt2x00_fix_MCU_request_failures.patch -#rhbz 754518 -#Patch21093: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch +#rhbz 788260 +Patch21233: jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch -#rhbz 771058 -Patch21100: msi-irq-sysfs-warning.patch - -# rhbz 754907 -Patch21101: hpsa-add-irqf-shared.patch +#rhbz 789644 +Patch21237: mcelog-rcu-splat.patch #rhbz 727865 730007 -Patch21102: ACPICA-Fix-regression-in-FADT-revision-checks.patch +Patch21240: ACPICA-Fix-regression-in-FADT-revision-checks.patch #rhbz 728478 -Patch21104: sony-laptop-Enable-keyboard-backlight-by-default.patch +Patch21242: sony-laptop-Enable-keyboard-backlight-by-default.patch #rhbz 803809 CVE-2012-1179 -Patch21106: mm-thp-fix-pmd_bad-triggering.patch +Patch21244: mm-thp-fix-pmd_bad-triggering.patch -#rhbz 804947 CVE-2012-1568 -Patch21107: SHLIB_BASE-randomization.patch - -Patch21110: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch - -Patch21200: unhandled-irqs-switch-to-polling.patch +Patch21300: unhandled-irqs-switch-to-polling.patch #rhbz 804007 Patch21305: mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch +#rhbz 804957 CVE-2012-1568 +Patch21306: shlib_base_randomize.patch + +Patch21350: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch + Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch #rhbz 808207 CVE-2012-1601 @@ -1159,10 +1127,8 @@ ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R # # ARM # -ApplyPatch arm-omap-dt-compat.patch +#ApplyPatch arm-omap-dt-compat.patch ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch -ApplyPatch arm-build-bug-on.patch -ApplyPatch arm-stmmac-mmc-core.patch ApplyPatch arm-tegra-nvec-kconfig.patch ApplyPatch taint-vbox.patch @@ -1191,7 +1157,6 @@ ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 ApplyPatch NFSv4-Reduce-the-footprint-of-the-idmapper.patch ApplyPatch NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch -ApplyPatch NFSv4-Save-the-owner-group-name-string-when-doing-op.patch # USB @@ -1240,6 +1205,8 @@ ApplyPatch linux-2.6-serial-460800.patch # Silence some useless messages that still get printed with 'quiet' ApplyPatch linux-2.6-silence-noise.patch +ApplyPatch silence-timekeeping-spew.patch + # Make fbcon not show the penguins with 'quiet' ApplyPatch linux-2.6-silence-fbcon-logo.patch @@ -1259,11 +1226,9 @@ ApplyPatch fix_xen_guest_on_old_EC2.patch # DRM core -# Nouveau DRM -ApplyOptionalPatch drm-nouveau-updates.patch - # Intel DRM ApplyOptionalPatch drm-intel-next.patch +ApplyPatch drm-i915-dp-stfu.patch ApplyPatch drm-i915-fbc-stfu.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch @@ -1285,62 +1250,31 @@ ApplyPatch disable-i8042-check-on-apple-mac.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch -ApplyPatch revert-efi-rtclock.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=787607 -ApplyPatch cdc-acm-tiocgserial.patch - ApplyPatch hibernate-freeze-filesystems.patch ApplyPatch lis3-improve-handling-of-null-rate.patch +ApplyPatch bluetooth-use-after-free.patch + # utrace. ApplyPatch utrace.patch -#rhbz 752176 -ApplyPatch sysfs-msi-irq-per-device.patch - -# rhbz 754907 -ApplyPatch hpsa-add-irqf-shared.patch - -#rhbz 717735 -ApplyPatch nfs-client-freezer.patch - -#rhbz 590880 -ApplyPatch alps.patch - -#rhbz 771058 -ApplyPatch msi-irq-sysfs-warning.patch - ApplyPatch ext4-Support-check-none-nocheck-mount-options.patch -ApplyPatch ext4-Fix-error-handling-on-inode-bitmap-corruption.patch -ApplyPatch ext3-Fix-error-handling-on-inode-bitmap-corruption.patch -#rhbz 773392 -ApplyPatch KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch -ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch +#rhbz 772772 +ApplyPatch rt2x00_fix_MCU_request_failures.patch -#rhbz 728740 -ApplyPatch rtl8192cu-Fix-WARNING-on-suspend-resume.patch - -#rhbz 782686 -ApplyPatch procfs-parse-mount-options.patch -ApplyPatch procfs-add-hidepid-and-gid-mount-options.patch -ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch - -#rhbz 788260 +#rhbz 788269 ApplyPatch jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch -#rhbz 785806 -ApplyPatch e1000e-Avoid-wrong-check-on-TX-hang.patch - -#rhbz 754518 -#ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch - # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch +#rhbz 789644 +ApplyPatch mcelog-rcu-splat.patch + #rhbz 727865 730007 ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch @@ -1350,6 +1284,9 @@ ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch #rhbz 804007 ApplyPatch mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch +#rhbz 804957 CVE-2012-1568 +ApplyPatch shlib_base_randomize.patch + ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch @@ -1359,9 +1296,6 @@ ApplyPatch x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch #rhbz 803809 CVE-2012-1179 ApplyPatch mm-thp-fix-pmd_bad-triggering.patch -#rhbz 804947 CVE-2012-1568 -ApplyPatch SHLIB_BASE-randomization.patch - ApplyPatch nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch #rhbz 808207 CVE-2012-1601 @@ -2014,6 +1948,12 @@ fi # and build. %changelog +* Mon Apr 02 2012 Dave Jones +- Linux 3.3 + +* Fri Mar 30 2012 Dave Jones +- Silence the timekeeping "Adjusting tsc more then 11%" spew. (rhbz 798600) + * Fri Mar 30 2012 Josh Boyer - CVE-2012-1601: kvm: NULL dereference from irqchip_in_kernel and vcpu->arch.apic inconsistency (rhbz 808207) diff --git a/linux-2.6-defaults-acpi-video.patch b/linux-2.6-defaults-acpi-video.patch index af883b0d3..b83f4b614 100644 --- a/linux-2.6-defaults-acpi-video.patch +++ b/linux-2.6-defaults-acpi-video.patch @@ -1,13 +1,13 @@ diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c -index d8d7596..a1b7117 100644 +index eaef02a..2029819 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c -@@ -71,7 +71,7 @@ MODULE_AUTHOR("Bruno Ducrot"); +@@ -69,7 +69,7 @@ MODULE_AUTHOR("Bruno Ducrot"); MODULE_DESCRIPTION("ACPI Video Driver"); MODULE_LICENSE("GPL"); --static int brightness_switch_enabled = 1; -+static int brightness_switch_enabled = 0; +-static bool brightness_switch_enabled = 1; ++static bool brightness_switch_enabled = 0; module_param(brightness_switch_enabled, bool, 0644); - static int acpi_video_bus_add(struct acpi_device *device); + /* diff --git a/linux-2.6-serial-460800.patch b/linux-2.6-serial-460800.patch index 9aa392c9e..979b248d5 100644 --- a/linux-2.6-serial-460800.patch +++ b/linux-2.6-serial-460800.patch @@ -1,7 +1,7 @@ diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 2209620..659c1bb 100644 ---- a/drivers/tty/serial/8250.c -+++ b/drivers/tty/serial/8250.c +--- a/drivers/tty/serial/8250/8250.c ++++ b/drivers/tty/serial/8250/8250.c @@ -7,6 +7,9 @@ * * Copyright (C) 2001 Russell King. diff --git a/mcelog-rcu-splat.patch b/mcelog-rcu-splat.patch new file mode 100644 index 000000000..12c1fe3ea --- /dev/null +++ b/mcelog-rcu-splat.patch @@ -0,0 +1,15 @@ +diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c +index f22a9f7..f525f99 100644 +--- a/arch/x86/kernel/cpu/mcheck/mce.c ++++ b/arch/x86/kernel/cpu/mcheck/mce.c +@@ -191,7 +191,7 @@ static void drain_mcelog_buffer(void) + { + unsigned int next, i, prev = 0; + +- next = rcu_dereference_check_mce(mcelog.next); ++ next = ACCESS_ONCE(mcelog.next); + + do { + struct mce *m; + + \ No newline at end of file diff --git a/mm-thp-fix-pmd_bad-triggering.patch b/mm-thp-fix-pmd_bad-triggering.patch index 3af9d2e2d..8e1a77cd7 100644 --- a/mm-thp-fix-pmd_bad-triggering.patch +++ b/mm-thp-fix-pmd_bad-triggering.patch @@ -363,7 +363,7 @@ index fa2f04e..e3090fc 100644 @@ -1251,12 +1251,20 @@ static inline unsigned long zap_pmd_range(struct mmu_gather *tlb, VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem)); split_huge_page_pmd(vma->vm_mm, pmd); - } else if (zap_huge_pmd(tlb, vma, pmd)) + } else if (zap_huge_pmd(tlb, vma, pmd, addr)) - continue; + goto next; /* fall through */ @@ -444,4 +444,4 @@ To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ -Don't email: email@kvack.org +Don't email: email@kvack.org \ No newline at end of file diff --git a/msi-irq-sysfs-warning.patch b/msi-irq-sysfs-warning.patch deleted file mode 100644 index dce440e4a..000000000 --- a/msi-irq-sysfs-warning.patch +++ /dev/null @@ -1,87 +0,0 @@ -commit 3ff0e97a1bc3059bfbcc1d864c5d4ff5f8d3c2b9 -Author: Neil Horman -Date: Tue Jan 3 10:17:21 2012 -0500 - - msi: fix imbalanced refcount of msi irq sysfs objects - - This warning was recently reported to me: - - ------------[ cut here ]------------ - WARNING: at lib/kobject.c:595 kobject_put+0x50/0x60() - Hardware name: VMware Virtual Platform - kobject: '(null)' (ffff880027b0df40): is not initialized, yet kobject_put() is - being called. - Modules linked in: vmxnet3(+) vmw_balloon i2c_piix4 i2c_core shpchp raid10 - vmw_pvscsi - Pid: 630, comm: modprobe Tainted: G W 3.1.6-1.fc16.x86_64 #1 - Call Trace: - [] warn_slowpath_common+0x7f/0xc0 - [] warn_slowpath_fmt+0x46/0x50 - [] ? free_desc+0x63/0x70 - [] kobject_put+0x50/0x60 - [] free_msi_irqs+0xd5/0x120 - [] pci_enable_msi_block+0x24c/0x2c0 - [] vmxnet3_alloc_intr_resources+0x173/0x240 [vmxnet3] - [] vmxnet3_probe_device+0x615/0x834 [vmxnet3] - [] local_pci_probe+0x5c/0xd0 - [] pci_device_probe+0x109/0x130 - [] driver_probe_device+0x9c/0x2b0 - [] __driver_attach+0xab/0xb0 - [] ? driver_probe_device+0x2b0/0x2b0 - [] ? driver_probe_device+0x2b0/0x2b0 - [] bus_for_each_dev+0x5c/0x90 - [] driver_attach+0x1e/0x20 - [] bus_add_driver+0x1b0/0x2a0 - [] ? 0xffffffffa0187fff - [] driver_register+0x76/0x140 - [] ? printk+0x51/0x53 - [] ? 0xffffffffa0187fff - [] __pci_register_driver+0x56/0xd0 - [] vmxnet3_init_module+0x3a/0x3c [vmxnet3] - [] do_one_initcall+0x42/0x180 - [] sys_init_module+0x91/0x200 - [] system_call_fastpath+0x16/0x1b - ---[ end trace 44593438a59a9558 ]--- - Using INTx interrupt, #Rx queues: 1. - - It occurs when populate_msi_sysfs fails, which in turn causes free_msi_irqs to - be called. Because populate_msi_sysfs fails, we never registered any of the - msi irq sysfs objects, but free_msi_irqs still calls kobject_del and kobject_put - on each of them, which gets flagged in the above stack trace. - - The fix is pretty straightforward. We can key of the parent pointer in the - kobject. It is only set if the kobject_init_and_add succededs in - populate_msi_sysfs. If anything fails there, each kobject has its parent reset - to NULL - - Signed-off-by: Neil Horman - CC: Jesse Barnes - CC: Bjorn Helgaas - CC: Greg Kroah-Hartman - CC: linux-pci@vger.kernel.org - -diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c -index 337e16a..82de95e 100644 ---- a/drivers/pci/msi.c -+++ b/drivers/pci/msi.c -@@ -323,8 +323,18 @@ static void free_msi_irqs(struct pci_dev *dev) - if (list_is_last(&entry->list, &dev->msi_list)) - iounmap(entry->mask_base); - } -- kobject_del(&entry->kobj); -- kobject_put(&entry->kobj); -+ -+ /* -+ * Its possible that we get into this path -+ * When populate_msi_sysfs fails, which means the entries -+ * were not registered with sysfs. In that case don't -+ * unregister them. -+ */ -+ if (entry->kobj.parent) { -+ kobject_del(&entry->kobj); -+ kobject_put(&entry->kobj); -+ } -+ - list_del(&entry->list); - kfree(entry); - } diff --git a/nfs-client-freezer.patch b/nfs-client-freezer.patch deleted file mode 100644 index 5f5b0836e..000000000 --- a/nfs-client-freezer.patch +++ /dev/null @@ -1,197 +0,0 @@ -@@ -, +, @@ - fs/nfs/inode.c | 3 ++- - fs/nfs/nfs3proc.c | 3 ++- - fs/nfs/nfs4proc.c | 5 +++-- - fs/nfs/proc.c | 3 ++- - include/linux/freezer.h | 28 ++++++++++++++++++++++++++++ - net/sunrpc/sched.c | 3 ++- - 6 files changed, 39 insertions(+), 6 deletions(-) ---- a/fs/nfs/inode.c -+++ a/fs/nfs/inode.c -@@ -38,6 +38,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -77,7 +78,7 @@ int nfs_wait_bit_killable(void *word) - { - if (fatal_signal_pending(current)) - return -ERESTARTSYS; -- schedule(); -+ freezable_schedule(); - return 0; - } - ---- a/fs/nfs/nfs3proc.c -+++ a/fs/nfs/nfs3proc.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - #include "iostat.h" - #include "internal.h" -@@ -32,7 +33,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) - res = rpc_call_sync(clnt, msg, flags); - if (res != -EJUKEBOX && res != -EKEYEXPIRED) - break; -- schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); -+ freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); - res = -ERESTARTSYS; - } while (!fatal_signal_pending(current)); - return res; ---- a/fs/nfs/nfs4proc.c -+++ a/fs/nfs/nfs4proc.c -@@ -53,6 +53,7 @@ - #include - #include - #include -+#include - - #include "nfs4_fs.h" - #include "delegation.h" -@@ -241,7 +242,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) - *timeout = NFS4_POLL_RETRY_MIN; - if (*timeout > NFS4_POLL_RETRY_MAX) - *timeout = NFS4_POLL_RETRY_MAX; -- schedule_timeout_killable(*timeout); -+ freezable_schedule_timeout_killable(*timeout); - if (fatal_signal_pending(current)) - res = -ERESTARTSYS; - *timeout <<= 1; -@@ -3950,7 +3951,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 - static unsigned long - nfs4_set_lock_task_retry(unsigned long timeout) - { -- schedule_timeout_killable(timeout); -+ freezable_schedule_timeout_killable(timeout); - timeout <<= 1; - if (timeout > NFS4_LOCK_MAXTIMEOUT) - return NFS4_LOCK_MAXTIMEOUT; ---- a/fs/nfs/proc.c -+++ a/fs/nfs/proc.c -@@ -41,6 +41,7 @@ - #include - #include - #include -+#include - #include "internal.h" - - #define NFSDBG_FACILITY NFSDBG_PROC -@@ -59,7 +60,7 @@ nfs_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) - res = rpc_call_sync(clnt, msg, flags); - if (res != -EKEYEXPIRED) - break; -- schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); -+ freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); - res = -ERESTARTSYS; - } while (!fatal_signal_pending(current)); - return res; ---- a/include/linux/freezer.h -+++ a/include/linux/freezer.h -@@ -135,6 +135,29 @@ static inline void set_freezable_with_signal(void) - } - - /* -+ * These macros are intended to be used whenever you want allow a task that's -+ * sleeping in TASK_UNINTERRUPTIBLE or TASK_KILLABLE state to be frozen. Note -+ * that neither return any clear indication of whether a freeze event happened -+ * while in this function. -+ */ -+ -+/* Like schedule(), but should not block the freezer. */ -+#define freezable_schedule() \ -+({ \ -+ freezer_do_not_count(); \ -+ schedule(); \ -+ freezer_count(); \ -+}) -+ -+/* Like schedule_timeout_killable(), but should not block the freezer. */ -+#define freezable_schedule_timeout_killable(timeout) \ -+({ \ -+ freezer_do_not_count(); \ -+ schedule_timeout_killable(timeout); \ -+ freezer_count(); \ -+}) -+ -+/* - * Freezer-friendly wrappers around wait_event_interruptible(), - * wait_event_killable() and wait_event_interruptible_timeout(), originally - * defined in -@@ -194,6 +217,11 @@ static inline int freezer_should_skip(struct task_struct *p) { return 0; } - static inline void set_freezable(void) {} - static inline void set_freezable_with_signal(void) {} - -+#define freezable_schedule() schedule() -+ -+#define freezable_schedule_timeout_killable(timeout) \ -+ schedule_timeout_killable(timeout) -+ - #define wait_event_freezable(wq, condition) \ - wait_event_interruptible(wq, condition) - ---- a/net/sunrpc/sched.c -+++ a/net/sunrpc/sched.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - - #include - -@@ -231,7 +232,7 @@ static int rpc_wait_bit_killable(void *word) - { - if (fatal_signal_pending(current)) - return -ERESTARTSYS; -- schedule(); -+ freezable_schedule(); - return 0; - } - - include/linux/freezer.h | 21 ++++++++++++++++++--- - 1 files changed, 18 insertions(+), 3 deletions(-) ---- a/include/linux/freezer.h -+++ a/include/linux/freezer.h -@@ -141,18 +141,33 @@ static inline void set_freezable_with_signal(void) - * while in this function. - */ - --/* Like schedule(), but should not block the freezer. */ -+/* -+ * Like schedule(), but should not block the freezer. It may return immediately -+ * if it ends up racing with the freezer. Callers must be able to deal with -+ * spurious wakeups. -+ */ - #define freezable_schedule() \ - ({ \ - freezer_do_not_count(); \ -- schedule(); \ -+ if (!try_to_freeze()) \ -+ schedule(); \ - freezer_count(); \ - }) - --/* Like schedule_timeout_killable(), but should not block the freezer. */ -+/* -+ * Like schedule_timeout_killable(), but should not block the freezer. It may -+ * end up returning immediately if it ends up racing with the freezer. Callers -+ * must be able to deal with the loose wakeup timing that can occur when the -+ * freezer races in. When that occurs, this function will return the timeout -+ * value instead of 0. -+ */ - #define freezable_schedule_timeout_killable(timeout) \ - ({ \ - freezer_do_not_count(); \ -+ if (try_to_freeze()) { \ -+ freezer_count(); \ -+ return timeout; \ -+ } \ - schedule_timeout_killable(timeout); \ - freezer_count(); \ - }) diff --git a/proc-fix-null-pointer-deref-in-proc_pid_permission.patch b/proc-fix-null-pointer-deref-in-proc_pid_permission.patch deleted file mode 100644 index 62d2fb21a..000000000 --- a/proc-fix-null-pointer-deref-in-proc_pid_permission.patch +++ /dev/null @@ -1,44 +0,0 @@ -From a2ef990ab5a6705a356d146dd773a3b359787497 Mon Sep 17 00:00:00 2001 -From: Xiaotian Feng -Date: Thu, 12 Jan 2012 17:17:08 -0800 -Subject: [PATCH] proc: fix null pointer deref in proc_pid_permission() - -get_proc_task() can fail to search the task and return NULL, -put_task_struct() will then bomb the kernel with following oops: - - BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 - IP: [] proc_pid_permission+0x64/0xe0 - PGD 112075067 PUD 112814067 PMD 0 - Oops: 0002 [#1] PREEMPT SMP - -This is a regression introduced by commit 0499680a ("procfs: add hidepid= -and gid= mount options"). The kernel should return -ESRCH if -get_proc_task() failed. - -Signed-off-by: Xiaotian Feng -Cc: Al Viro -Cc: Vasiliy Kulikov -Cc: Stephen Wilson -Acked-by: David Rientjes -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds ---- - fs/proc/base.c | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) - -diff --git a/fs/proc/base.c b/fs/proc/base.c -index 8173dfd..5485a53 100644 ---- a/fs/proc/base.c -+++ b/fs/proc/base.c -@@ -654,6 +654,8 @@ static int proc_pid_permission(struct inode *inode, int mask) - bool has_perms; - - task = get_proc_task(inode); -+ if (!task) -+ return -ESRCH; - has_perms = has_pid_permissions(pid, task, 1); - put_task_struct(task); - --- -1.7.7.5 - diff --git a/procfs-add-hidepid-and-gid-mount-options.patch b/procfs-add-hidepid-and-gid-mount-options.patch deleted file mode 100644 index 803f77d4c..000000000 --- a/procfs-add-hidepid-and-gid-mount-options.patch +++ /dev/null @@ -1,342 +0,0 @@ -From 0499680a42141d86417a8fbaa8c8db806bea1201 Mon Sep 17 00:00:00 2001 -From: Vasiliy Kulikov -Date: Tue, 10 Jan 2012 15:11:31 -0800 -Subject: [PATCH] procfs: add hidepid= and gid= mount options - -Add support for mount options to restrict access to /proc/PID/ -directories. The default backward-compatible "relaxed" behaviour is left -untouched. - -The first mount option is called "hidepid" and its value defines how much -info about processes we want to be available for non-owners: - -hidepid=0 (default) means the old behavior - anybody may read all -world-readable /proc/PID/* files. - -hidepid=1 means users may not access any /proc// directories, but -their own. Sensitive files like cmdline, sched*, status are now protected -against other users. As permission checking done in proc_pid_permission() -and files' permissions are left untouched, programs expecting specific -files' modes are not confused. - -hidepid=2 means hidepid=1 plus all /proc/PID/ will be invisible to other -users. It doesn't mean that it hides whether a process exists (it can be -learned by other means, e.g. by kill -0 $PID), but it hides process' euid -and egid. It compicates intruder's task of gathering info about running -processes, whether some daemon runs with elevated privileges, whether -another user runs some sensitive program, whether other users run any -program at all, etc. - -gid=XXX defines a group that will be able to gather all processes' info -(as in hidepid=0 mode). This group should be used instead of putting -nonroot user in sudoers file or something. However, untrusted users (like -daemons, etc.) which are not supposed to monitor the tasks in the whole -system should not be added to the group. - -hidepid=1 or higher is designed to restrict access to procfs files, which -might reveal some sensitive private information like precise keystrokes -timings: - -http://www.openwall.com/lists/oss-security/2011/11/05/3 - -hidepid=1/2 doesn't break monitoring userspace tools. ps, top, pgrep, and -conky gracefully handle EPERM/ENOENT and behave as if the current user is -the only user running processes. pstree shows the process subtree which -contains "pstree" process. - -Note: the patch doesn't deal with setuid/setgid issues of keeping -preopened descriptors of procfs files (like -https://lkml.org/lkml/2011/2/7/368). We rely on that the leaked -information like the scheduling counters of setuid apps doesn't threaten -anybody's privacy - only the user started the setuid program may read the -counters. - -Signed-off-by: Vasiliy Kulikov -Cc: Alexey Dobriyan -Cc: Al Viro -Cc: Randy Dunlap -Cc: "H. Peter Anvin" -Cc: Greg KH -Cc: Theodore Tso -Cc: Alan Cox -Cc: James Morris -Cc: Oleg Nesterov -Cc: Hugh Dickins -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds ---- - Documentation/filesystems/proc.txt | 39 ++++++++++++++++++++ - fs/proc/base.c | 69 +++++++++++++++++++++++++++++++++++- - fs/proc/inode.c | 8 ++++ - fs/proc/root.c | 21 +++++++++-- - include/linux/pid_namespace.h | 2 + - 5 files changed, 135 insertions(+), 4 deletions(-) - -diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt -index 0ec91f0..12fee13 100644 ---- a/Documentation/filesystems/proc.txt -+++ b/Documentation/filesystems/proc.txt -@@ -41,6 +41,8 @@ Table of Contents - 3.5 /proc//mountinfo - Information about mounts - 3.6 /proc//comm & /proc//task//comm - -+ 4 Configuring procfs -+ 4.1 Mount options - - ------------------------------------------------------------------------------ - Preface -@@ -1542,3 +1544,40 @@ a task to set its own or one of its thread siblings comm value. The comm value - is limited in size compared to the cmdline value, so writing anything longer - then the kernel's TASK_COMM_LEN (currently 16 chars) will result in a truncated - comm value. -+ -+ -+------------------------------------------------------------------------------ -+Configuring procfs -+------------------------------------------------------------------------------ -+ -+4.1 Mount options -+--------------------- -+ -+The following mount options are supported: -+ -+ hidepid= Set /proc// access mode. -+ gid= Set the group authorized to learn processes information. -+ -+hidepid=0 means classic mode - everybody may access all /proc// directories -+(default). -+ -+hidepid=1 means users may not access any /proc// directories but their -+own. Sensitive files like cmdline, sched*, status are now protected against -+other users. This makes it impossible to learn whether any user runs -+specific program (given the program doesn't reveal itself by its behaviour). -+As an additional bonus, as /proc//cmdline is unaccessible for other users, -+poorly written programs passing sensitive information via program arguments are -+now protected against local eavesdroppers. -+ -+hidepid=2 means hidepid=1 plus all /proc// will be fully invisible to other -+users. It doesn't mean that it hides a fact whether a process with a specific -+pid value exists (it can be learned by other means, e.g. by "kill -0 $PID"), -+but it hides process' uid and gid, which may be learned by stat()'ing -+/proc// otherwise. It greatly complicates an intruder's task of gathering -+information about running processes, whether some daemon runs with elevated -+privileges, whether other user runs some sensitive program, whether other users -+run any program at all, etc. -+ -+gid= defines a group authorized to learn processes information otherwise -+prohibited by hidepid=. If you use some daemon like identd which needs to learn -+information about processes information, just add identd to this group. -diff --git a/fs/proc/base.c b/fs/proc/base.c -index 4d755fe..8173dfd 100644 ---- a/fs/proc/base.c -+++ b/fs/proc/base.c -@@ -631,6 +631,50 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr) - return 0; - } - -+/* -+ * May current process learn task's sched/cmdline info (for hide_pid_min=1) -+ * or euid/egid (for hide_pid_min=2)? -+ */ -+static bool has_pid_permissions(struct pid_namespace *pid, -+ struct task_struct *task, -+ int hide_pid_min) -+{ -+ if (pid->hide_pid < hide_pid_min) -+ return true; -+ if (in_group_p(pid->pid_gid)) -+ return true; -+ return ptrace_may_access(task, PTRACE_MODE_READ); -+} -+ -+ -+static int proc_pid_permission(struct inode *inode, int mask) -+{ -+ struct pid_namespace *pid = inode->i_sb->s_fs_info; -+ struct task_struct *task; -+ bool has_perms; -+ -+ task = get_proc_task(inode); -+ has_perms = has_pid_permissions(pid, task, 1); -+ put_task_struct(task); -+ -+ if (!has_perms) { -+ if (pid->hide_pid == 2) { -+ /* -+ * Let's make getdents(), stat(), and open() -+ * consistent with each other. If a process -+ * may not stat() a file, it shouldn't be seen -+ * in procfs at all. -+ */ -+ return -ENOENT; -+ } -+ -+ return -EPERM; -+ } -+ return generic_permission(inode, mask); -+} -+ -+ -+ - static const struct inode_operations proc_def_inode_operations = { - .setattr = proc_setattr, - }; -@@ -1615,6 +1659,7 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) - struct inode *inode = dentry->d_inode; - struct task_struct *task; - const struct cred *cred; -+ struct pid_namespace *pid = dentry->d_sb->s_fs_info; - - generic_fillattr(inode, stat); - -@@ -1623,6 +1668,14 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) - stat->gid = 0; - task = pid_task(proc_pid(inode), PIDTYPE_PID); - if (task) { -+ if (!has_pid_permissions(pid, task, 2)) { -+ rcu_read_unlock(); -+ /* -+ * This doesn't prevent learning whether PID exists, -+ * it only makes getattr() consistent with readdir(). -+ */ -+ return -ENOENT; -+ } - if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || - task_dumpable(task)) { - cred = __task_cred(task); -@@ -3119,6 +3172,7 @@ static const struct inode_operations proc_tgid_base_inode_operations = { - .lookup = proc_tgid_base_lookup, - .getattr = pid_getattr, - .setattr = proc_setattr, -+ .permission = proc_pid_permission, - }; - - static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid) -@@ -3322,6 +3376,12 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi - proc_pid_instantiate, iter.task, NULL); - } - -+static int fake_filldir(void *buf, const char *name, int namelen, -+ loff_t offset, u64 ino, unsigned d_type) -+{ -+ return 0; -+} -+ - /* for the /proc/ directory itself, after non-process stuff has been done */ - int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) - { -@@ -3329,6 +3389,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) - struct task_struct *reaper; - struct tgid_iter iter; - struct pid_namespace *ns; -+ filldir_t __filldir; - - if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET) - goto out_no_task; -@@ -3350,8 +3411,13 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) - for (iter = next_tgid(ns, iter); - iter.task; - iter.tgid += 1, iter = next_tgid(ns, iter)) { -+ if (has_pid_permissions(ns, iter.task, 2)) -+ __filldir = filldir; -+ else -+ __filldir = fake_filldir; -+ - filp->f_pos = iter.tgid + TGID_OFFSET; -- if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) { -+ if (proc_pid_fill_cache(filp, dirent, __filldir, iter) < 0) { - put_task_struct(iter.task); - goto out; - } -@@ -3686,6 +3752,7 @@ static const struct inode_operations proc_task_inode_operations = { - .lookup = proc_task_lookup, - .getattr = proc_task_getattr, - .setattr = proc_setattr, -+ .permission = proc_pid_permission, - }; - - static const struct file_operations proc_task_operations = { -diff --git a/fs/proc/inode.c b/fs/proc/inode.c -index 27c762f..84fd323 100644 ---- a/fs/proc/inode.c -+++ b/fs/proc/inode.c -@@ -106,6 +106,14 @@ void __init proc_init_inodecache(void) - - static int proc_show_options(struct seq_file *seq, struct vfsmount *vfs) - { -+ struct super_block *sb = vfs->mnt_sb; -+ struct pid_namespace *pid = sb->s_fs_info; -+ -+ if (pid->pid_gid) -+ seq_printf(seq, ",gid=%lu", (unsigned long)pid->pid_gid); -+ if (pid->hide_pid != 0) -+ seq_printf(seq, ",hidepid=%u", pid->hide_pid); -+ - return 0; - } - -diff --git a/fs/proc/root.c b/fs/proc/root.c -index 6a8ac1d..46a15d8 100644 ---- a/fs/proc/root.c -+++ b/fs/proc/root.c -@@ -38,10 +38,12 @@ static int proc_set_super(struct super_block *sb, void *data) - } - - enum { -- Opt_err, -+ Opt_gid, Opt_hidepid, Opt_err, - }; - - static const match_table_t tokens = { -+ {Opt_hidepid, "hidepid=%u"}, -+ {Opt_gid, "gid=%u"}, - {Opt_err, NULL}, - }; - -@@ -49,8 +51,7 @@ static int proc_parse_options(char *options, struct pid_namespace *pid) - { - char *p; - substring_t args[MAX_OPT_ARGS]; -- -- pr_debug("proc: options = %s\n", options); -+ int option; - - if (!options) - return 1; -@@ -63,6 +64,20 @@ static int proc_parse_options(char *options, struct pid_namespace *pid) - args[0].to = args[0].from = 0; - token = match_token(p, tokens, args); - switch (token) { -+ case Opt_gid: -+ if (match_int(&args[0], &option)) -+ return 0; -+ pid->pid_gid = option; -+ break; -+ case Opt_hidepid: -+ if (match_int(&args[0], &option)) -+ return 0; -+ if (option < 0 || option > 2) { -+ pr_err("proc: hidepid value must be between 0 and 2.\n"); -+ return 0; -+ } -+ pid->hide_pid = option; -+ break; - default: - pr_err("proc: unrecognized mount option \"%s\" " - "or missing value\n", p); -diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h -index 38d1032..e7cf666 100644 ---- a/include/linux/pid_namespace.h -+++ b/include/linux/pid_namespace.h -@@ -30,6 +30,8 @@ struct pid_namespace { - #ifdef CONFIG_BSD_PROCESS_ACCT - struct bsd_acct_struct *bacct; - #endif -+ gid_t pid_gid; -+ int hide_pid; - }; - - extern struct pid_namespace init_pid_ns; --- -1.7.7.5 - diff --git a/procfs-parse-mount-options.patch b/procfs-parse-mount-options.patch deleted file mode 100644 index 0187a1d44..000000000 --- a/procfs-parse-mount-options.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 97412950b10e64f347aec4a9b759395c2465adf6 Mon Sep 17 00:00:00 2001 -From: Vasiliy Kulikov -Date: Tue, 10 Jan 2012 15:11:27 -0800 -Subject: [PATCH] procfs: parse mount options - -Add support for procfs mount options. Actual mount options are coming in -the next patches. - -Signed-off-by: Vasiliy Kulikov -Cc: Alexey Dobriyan -Cc: Al Viro -Cc: Randy Dunlap -Cc: "H. Peter Anvin" -Cc: Greg KH -Cc: Theodore Tso -Cc: Alan Cox -Cc: James Morris -Cc: Oleg Nesterov -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds ---- - fs/proc/inode.c | 10 +++++++++ - fs/proc/internal.h | 1 + - fs/proc/root.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++- - 3 files changed, 64 insertions(+), 2 deletions(-) - -diff --git a/fs/proc/inode.c b/fs/proc/inode.c -index 51a1766..27c762f 100644 ---- a/fs/proc/inode.c -+++ b/fs/proc/inode.c -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -17,7 +18,9 @@ - #include - #include - #include -+#include - #include -+#include - - #include - #include -@@ -101,12 +104,19 @@ void __init proc_init_inodecache(void) - init_once); - } - -+static int proc_show_options(struct seq_file *seq, struct vfsmount *vfs) -+{ -+ return 0; -+} -+ - static const struct super_operations proc_sops = { - .alloc_inode = proc_alloc_inode, - .destroy_inode = proc_destroy_inode, - .drop_inode = generic_delete_inode, - .evict_inode = proc_evict_inode, - .statfs = simple_statfs, -+ .remount_fs = proc_remount, -+ .show_options = proc_show_options, - }; - - static void __pde_users_dec(struct proc_dir_entry *pde) -diff --git a/fs/proc/internal.h b/fs/proc/internal.h -index 7838e5c..2925775 100644 ---- a/fs/proc/internal.h -+++ b/fs/proc/internal.h -@@ -117,6 +117,7 @@ void pde_put(struct proc_dir_entry *pde); - - int proc_fill_super(struct super_block *); - struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *); -+int proc_remount(struct super_block *sb, int *flags, char *data); - - /* - * These are generic /proc routines that use the internal -diff --git a/fs/proc/root.c b/fs/proc/root.c -index 03102d9..6a8ac1d 100644 ---- a/fs/proc/root.c -+++ b/fs/proc/root.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - - #include "internal.h" - -@@ -36,6 +37,48 @@ static int proc_set_super(struct super_block *sb, void *data) - return err; - } - -+enum { -+ Opt_err, -+}; -+ -+static const match_table_t tokens = { -+ {Opt_err, NULL}, -+}; -+ -+static int proc_parse_options(char *options, struct pid_namespace *pid) -+{ -+ char *p; -+ substring_t args[MAX_OPT_ARGS]; -+ -+ pr_debug("proc: options = %s\n", options); -+ -+ if (!options) -+ return 1; -+ -+ while ((p = strsep(&options, ",")) != NULL) { -+ int token; -+ if (!*p) -+ continue; -+ -+ args[0].to = args[0].from = 0; -+ token = match_token(p, tokens, args); -+ switch (token) { -+ default: -+ pr_err("proc: unrecognized mount option \"%s\" " -+ "or missing value\n", p); -+ return 0; -+ } -+ } -+ -+ return 1; -+} -+ -+int proc_remount(struct super_block *sb, int *flags, char *data) -+{ -+ struct pid_namespace *pid = sb->s_fs_info; -+ return !proc_parse_options(data, pid); -+} -+ - static struct dentry *proc_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) - { -@@ -43,11 +86,15 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, - struct super_block *sb; - struct pid_namespace *ns; - struct proc_inode *ei; -+ char *options; - -- if (flags & MS_KERNMOUNT) -+ if (flags & MS_KERNMOUNT) { - ns = (struct pid_namespace *)data; -- else -+ options = NULL; -+ } else { - ns = current->nsproxy->pid_ns; -+ options = data; -+ } - - sb = sget(fs_type, proc_test_super, proc_set_super, ns); - if (IS_ERR(sb)) -@@ -55,6 +102,10 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, - - if (!sb->s_root) { - sb->s_flags = flags; -+ if (!proc_parse_options(options, ns)) { -+ deactivate_locked_super(sb); -+ return ERR_PTR(-EINVAL); -+ } - err = proc_fill_super(sb); - if (err) { - deactivate_locked_super(sb); --- -1.7.7.5 - diff --git a/revert-efi-rtclock.patch b/revert-efi-rtclock.patch deleted file mode 100644 index 87ecaa11a..000000000 --- a/revert-efi-rtclock.patch +++ /dev/null @@ -1,76 +0,0 @@ -diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c -index 3ae4128..e17c6d2 100644 ---- a/arch/x86/platform/efi/efi.c -+++ b/arch/x86/platform/efi/efi.c -@@ -89,50 +89,26 @@ early_param("add_efi_memmap", setup_add_efi_memmap); - - static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) - { -- unsigned long flags; -- efi_status_t status; -- -- spin_lock_irqsave(&rtc_lock, flags); -- status = efi_call_virt2(get_time, tm, tc); -- spin_unlock_irqrestore(&rtc_lock, flags); -- return status; -+ return efi_call_virt2(get_time, tm, tc); - } - - static efi_status_t virt_efi_set_time(efi_time_t *tm) - { -- unsigned long flags; -- efi_status_t status; -- -- spin_lock_irqsave(&rtc_lock, flags); -- status = efi_call_virt1(set_time, tm); -- spin_unlock_irqrestore(&rtc_lock, flags); -- return status; -+ return efi_call_virt1(set_time, tm); - } - - static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled, - efi_bool_t *pending, - efi_time_t *tm) - { -- unsigned long flags; -- efi_status_t status; -- -- spin_lock_irqsave(&rtc_lock, flags); -- status = efi_call_virt3(get_wakeup_time, -- enabled, pending, tm); -- spin_unlock_irqrestore(&rtc_lock, flags); -- return status; -+ return efi_call_virt3(get_wakeup_time, -+ enabled, pending, tm); - } - - static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) - { -- unsigned long flags; -- efi_status_t status; -- -- spin_lock_irqsave(&rtc_lock, flags); -- status = efi_call_virt2(set_wakeup_time, -- enabled, tm); -- spin_unlock_irqrestore(&rtc_lock, flags); -- return status; -+ return efi_call_virt2(set_wakeup_time, -+ enabled, tm); - } - - static efi_status_t virt_efi_get_variable(efi_char16_t *name, -@@ -232,14 +208,11 @@ static efi_status_t __init phys_efi_set_virtual_address_map( - static efi_status_t __init phys_efi_get_time(efi_time_t *tm, - efi_time_cap_t *tc) - { -- unsigned long flags; - efi_status_t status; - -- spin_lock_irqsave(&rtc_lock, flags); - efi_call_phys_prelog(); - status = efi_call_phys2(efi_phys.get_time, tm, tc); - efi_call_phys_epilog(); -- spin_unlock_irqrestore(&rtc_lock, flags); - return status; - } - diff --git a/rt2x00_fix_MCU_request_failures.patch b/rt2x00_fix_MCU_request_failures.patch new file mode 100644 index 000000000..f7b8a6a4c --- /dev/null +++ b/rt2x00_fix_MCU_request_failures.patch @@ -0,0 +1,136 @@ +diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h +index 2571a2f..822f9e5 100644 +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -1627,6 +1627,7 @@ struct mac_iveiv_entry { + + /* + * H2M_MAILBOX_CSR: Host-to-MCU Mailbox. ++ * CMD_TOKEN: Command id, 0xff disable status reporting + */ + #define H2M_MAILBOX_CSR 0x7010 + #define H2M_MAILBOX_CSR_ARG0 FIELD32(0x000000ff) +@@ -1636,6 +1637,8 @@ struct mac_iveiv_entry { + + /* + * H2M_MAILBOX_CID: ++ * Free slots contain 0xff. MCU will store command's token to lowest free slot. ++ * If all slots are occupied status will be dropped. + */ + #define H2M_MAILBOX_CID 0x7014 + #define H2M_MAILBOX_CID_CMD0 FIELD32(0x000000ff) +@@ -1645,6 +1648,7 @@ struct mac_iveiv_entry { + + /* + * H2M_MAILBOX_STATUS: ++ * Command status will be saved to same slot as command id. + */ + #define H2M_MAILBOX_STATUS 0x701c + +@@ -2259,6 +2263,12 @@ struct mac_iveiv_entry { + + /* + * MCU mailbox commands. ++ * MCU_SLEEP - go to power-save mode. ++ * arg1: 1: save as much power as possible, 0: save less power ++ * status: 1: success, 2: already asleep, ++ * 3: maybe MAC is busy so can't finish this task ++ * MCU_RADIO_OFF ++ * arg0: 0: do power-saving, NOT turn off radio + */ + #define MCU_SLEEP 0x30 + #define MCU_WAKEUP 0x31 +@@ -2279,7 +2289,9 @@ struct mac_iveiv_entry { + /* + * MCU mailbox tokens + */ +-#define TOKEN_WAKUP 3 ++#define TOKEN_SLEEP 1 ++#define TOKEN_RADIO_OFF 2 ++#define TOKEN_WAKEUP 3 + + /* + * DMA descriptor defines. +diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c +index dc88bae..9ac3017 100644 +--- a/drivers/net/wireless/rt2x00/rt2800pci.c ++++ b/drivers/net/wireless/rt2x00/rt2800pci.c +@@ -517,23 +517,6 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) + } + } + +-static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, +- enum dev_state state) +-{ +- if (state == STATE_AWAKE) { +- rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02); +- rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP); +- } else if (state == STATE_SLEEP) { +- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, +- 0xffffffff); +- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, +- 0xffffffff); +- rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01); +- } +- +- return 0; +-} +- + static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, + enum dev_state state) + { +@@ -541,14 +524,20 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, + + switch (state) { + case STATE_RADIO_ON: +- /* +- * Before the radio can be enabled, the device first has +- * to be woken up. After that it needs a bit of time +- * to be fully awake and then the radio can be enabled. +- */ +- rt2800pci_set_state(rt2x00dev, STATE_AWAKE); +- msleep(1); ++ /* Initialise all registers and send MCU_BOOT_SIGNAL. */ + retval = rt2800pci_enable_radio(rt2x00dev); ++ ++ /* After resume MCU_BOOT_SIGNAL will trash those. */ ++ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); ++ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); ++ ++ /* Finish initialization procedure. */ ++ rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, ++ 0xff, 0x02); ++ rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF); ++ ++ rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKEUP, 0, 0); ++ rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP); + break; + case STATE_RADIO_OFF: + /* +@@ -556,7 +545,7 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, + * be put to sleep for powersaving. + */ + rt2800pci_disable_radio(rt2x00dev); +- rt2800pci_set_state(rt2x00dev, STATE_SLEEP); ++ rt2800pci_set_device_state(rt2x00dev, STATE_SLEEP); + break; + case STATE_RADIO_IRQ_ON: + case STATE_RADIO_IRQ_OFF: +@@ -565,8 +554,16 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, + case STATE_DEEP_SLEEP: + case STATE_SLEEP: + case STATE_STANDBY: ++ /* PCIe devices won't report status after SLEEP request. */ ++ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); ++ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); ++ rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP, ++ 0xff, 0x01); ++ break; + case STATE_AWAKE: +- retval = rt2800pci_set_state(rt2x00dev, state); ++ rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKEUP, ++ 0, 0x02); ++ rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP); + break; + default: + retval = -ENOTSUPP; diff --git a/rtl8192cu-Fix-WARNING-on-suspend-resume.patch b/rtl8192cu-Fix-WARNING-on-suspend-resume.patch deleted file mode 100644 index bdc8a5492..000000000 --- a/rtl8192cu-Fix-WARNING-on-suspend-resume.patch +++ /dev/null @@ -1,163 +0,0 @@ -A recent LKML thread (http://lkml.indiana.edu/hypermail/linux/kernel/1112.3/00965.html) -discusses warnings that occur during a suspend/resume cycle. The driver -attempts to read the firmware file before userspace is ready, leading to the -following warning: - -WARNING: at drivers/base/firmware_class.c:537 _request_firmware+0x3f6/0x420() - -For rtl8192cu, the problem is fixed by storing the firmware in a global buffer -rather than one allocated per device. The usage count is increased when -suspending and decreased when resuming. This way, the firmware is retained -through a suspend/resume cycle, and does not have to be reread. - -This patch should fix the bug reported in -https://bugzilla.redhat.com/show_bug.cgi?id=771002. - -Note: This patch also touches rtl8192ce as the "firmware" loaded message -is now printed in the wrong place. -Note: This patch also touches rtl8192ce as the "firmware" loaded message -is now printed in the wrong place. - -Reported-by: Mohammed Arafa -Reported-by: Dave Jones -Signed-off-by: Larry Finger -Cc: Linus Torvalds -Cc: Stable - ---- - drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 1 - - drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 1 + - drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 58 +++++++++++++++++---- - 3 files changed, 49 insertions(+), 11 deletions(-) - ---- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:07:58.830625006 -0500 -+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:08:06.825439927 -0500 -@@ -227,7 +227,6 @@ int rtl92c_download_fw(struct ieee80211_ - u32 fwsize; - enum version_8192c version = rtlhal->version; - -- pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); - if (!rtlhal->pfirmware) - return 1; - ---- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c -+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c -@@ -186,6 +186,7 @@ int rtl92c_init_sw_vars(struct ieee80211 - memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); - rtlpriv->rtlhal.fwsize = firmware->size; - release_firmware(firmware); -+ pr_info("rtl8192ce: Loaded firmware file %s\n", rtlpriv->cfg->fw_name); - - return 0; - } ---- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c -+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c -@@ -43,6 +43,8 @@ - #include "hw.h" - #include - #include -+#include -+#include - - MODULE_AUTHOR("Georgia "); - MODULE_AUTHOR("Ziv Huang "); -@@ -51,6 +53,10 @@ MODULE_LICENSE("GPL"); - MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); - MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); - -+static char *rtl8192cu_firmware; /* pointer to firmware */ -+static int firmware_size; -+static atomic_t usage_count; -+ - static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -@@ -62,12 +68,21 @@ static int rtl92cu_init_sw_vars(struct i - rtlpriv->dm.disable_framebursting = false; - rtlpriv->dm.thermalvalue = 0; - rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; -- rtlpriv->rtlhal.pfirmware = vmalloc(0x4000); -- if (!rtlpriv->rtlhal.pfirmware) { -+ -+ if (rtl8192cu_firmware) { -+ /* firmware already loaded - true for suspend/resume -+ * and multiple instances of the device */ -+ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware; -+ rtlpriv->rtlhal.fwsize = firmware_size; -+ return 0; -+ } -+ rtl8192cu_firmware = vzalloc(0x4000); -+ if (!rtl8192cu_firmware) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Can't alloc buffer for fw.\n")); - return 1; - } -+ - /* request fw */ - err = request_firmware(&firmware, rtlpriv->cfg->fw_name, - rtlpriv->io.dev); -@@ -82,9 +97,14 @@ static int rtl92cu_init_sw_vars(struct i - release_firmware(firmware); - return 1; - } -- memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); -+ pr_info("rtl8192cu: Loaded firmware from file %s\n", -+ rtlpriv->cfg->fw_name); -+ memcpy(rtl8192cu_firmware, firmware->data, firmware->size); -+ firmware_size = firmware->size; - rtlpriv->rtlhal.fwsize = firmware->size; -+ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware; - release_firmware(firmware); -+ atomic_inc(&usage_count); - - return 0; - } -@@ -93,12 +113,30 @@ static void rtl92cu_deinit_sw_vars(struc - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - -- if (rtlpriv->rtlhal.pfirmware) { -- vfree(rtlpriv->rtlhal.pfirmware); -+ atomic_dec(&usage_count); -+ if (!atomic_read(&usage_count) && rtlpriv->rtlhal.pfirmware) { -+ vfree(rtl8192cu_firmware); -+ rtl8192cu_firmware = NULL; - rtlpriv->rtlhal.pfirmware = NULL; - } - } - -+#ifdef CONFIG_PM_SLEEP -+static int rtl8192cu_usb_suspend(struct usb_interface *pusb_intf, -+ pm_message_t message) -+{ -+ /* Increase usage_count to Save loaded fw across suspend/resume */ -+ atomic_inc(&usage_count); -+ return 0; -+} -+ -+static int rtl8192cu_usb_resume(struct usb_interface *pusb_intf) -+{ -+ atomic_dec(&usage_count); /* after resume, decrease usage count */ -+ return 0; -+} -+#endif -+ - static struct rtl_hal_ops rtl8192cu_hal_ops = { - .init_sw_vars = rtl92cu_init_sw_vars, - .deinit_sw_vars = rtl92cu_deinit_sw_vars, -@@ -374,11 +412,10 @@ static struct usb_driver rtl8192cu_drive - .disconnect = rtl_usb_disconnect, - .id_table = rtl8192c_usb_ids, - --#ifdef CONFIG_PM -- /* .suspend = rtl_usb_suspend, */ -- /* .resume = rtl_usb_resume, */ -- /* .reset_resume = rtl8192c_resume, */ --#endif /* CONFIG_PM */ -+#ifdef CONFIG_PM_SLEEP -+ .suspend = rtl8192cu_usb_suspend, -+ .resume = rtl8192cu_usb_resume, -+#endif /* CONFIG_PM_SLEEP */ - #ifdef CONFIG_AUTOSUSPEND - .supports_autosuspend = 1, - #endif diff --git a/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch b/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch deleted file mode 100644 index 492376d78..000000000 --- a/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- a/drivers/scsi/sd.c -+++ a/drivers/scsi/sd.c -@@ -2362,13 +2362,18 @@ static int sd_try_extended_inquiry(struct scsi_device *sdp) - static int sd_revalidate_disk(struct gendisk *disk) - { - struct scsi_disk *sdkp = scsi_disk(disk); -- struct scsi_device *sdp = sdkp->device; -+ struct scsi_device *sdp; - unsigned char *buffer; - unsigned flush = 0; - - SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, - "sd_revalidate_disk\n")); - -+ if (!sdkp) -+ goto out; -+ -+ sdp = sdkp->device; -+ - /* - * If the device is offline, don't try and read capacity or any - * of the other niceties. diff --git a/SHLIB_BASE-randomization.patch b/shlib_base_randomize.patch similarity index 100% rename from SHLIB_BASE-randomization.patch rename to shlib_base_randomize.patch diff --git a/silence-timekeeping-spew.patch b/silence-timekeeping-spew.patch new file mode 100644 index 000000000..19416d433 --- /dev/null +++ b/silence-timekeeping-spew.patch @@ -0,0 +1,16 @@ +--- linux-3.3.0-4.fc17.noarch/kernel/time/timekeeping.c~ 2012-03-30 14:18:15.591162207 -0400 ++++ linux-3.3.0-4.fc17.noarch/kernel/time/timekeeping.c 2012-03-30 14:18:38.959121171 -0400 +@@ -854,13 +854,6 @@ static void timekeeping_adjust(s64 offse + } else /* No adjustment needed */ + return; + +- WARN_ONCE(timekeeper.clock->maxadj && +- (timekeeper.mult + adj > timekeeper.clock->mult + +- timekeeper.clock->maxadj), +- "Adjusting %s more then 11%% (%ld vs %ld)\n", +- timekeeper.clock->name, (long)timekeeper.mult + adj, +- (long)timekeeper.clock->mult + +- timekeeper.clock->maxadj); + /* + * So the following can be confusing. + * diff --git a/sources b/sources index 5bcdc8a35..2fad201c9 100644 --- a/sources +++ b/sources @@ -1,3 +1 @@ -364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz -ee0ce13f2cb7f03a8cda0910fd0fa050 patch-3.2.12.xz -687632bb0ba65439198ac60f2c02a8f2 patch-3.2.13.xz +7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz diff --git a/sysfs-msi-irq-per-device.patch b/sysfs-msi-irq-per-device.patch deleted file mode 100644 index a2bf57c92..000000000 --- a/sysfs-msi-irq-per-device.patch +++ /dev/null @@ -1,239 +0,0 @@ -From: Neil Horman -Date: Thu, 6 Oct 2011 18:08:18 +0000 (-0400) -Subject: PCI/sysfs: add per pci device msi[x] irq listing (v5) -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fjbarnes%2Fpci.git;a=commitdiff_plain;h=933aa5c1f69aa650f59ba783307fc7ed7cc5fafa - -PCI/sysfs: add per pci device msi[x] irq listing (v5) - -This patch adds a per-pci-device subdirectory in sysfs called: -/sys/bus/pci/devices//msi_irqs - -This sub-directory exports the set of msi vectors allocated by a given -pci device, by creating a numbered sub-directory for each vector beneath -msi_irqs. For each vector various attributes can be exported. -Currently the only attribute is called mode, which tracks the -operational mode of that vector (msi vs. msix) - -Acked-by: Greg Kroah-Hartman -Signed-off-by: Jesse Barnes ---- - -diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci -index 349ecf2..34f5110 100644 ---- a/Documentation/ABI/testing/sysfs-bus-pci -+++ b/Documentation/ABI/testing/sysfs-bus-pci -@@ -66,6 +66,24 @@ Description: - re-discover previously removed devices. - Depends on CONFIG_HOTPLUG. - -+What: /sys/bus/pci/devices/.../msi_irqs/ -+Date: September, 2011 -+Contact: Neil Horman -+Description: -+ The /sys/devices/.../msi_irqs directory contains a variable set -+ of sub-directories, with each sub-directory being named after a -+ corresponding msi irq vector allocated to that device. Each -+ numbered sub-directory N contains attributes of that irq. -+ Note that this directory is not created for device drivers which -+ do not support msi irqs -+ -+What: /sys/bus/pci/devices/.../msi_irqs//mode -+Date: September 2011 -+Contact: Neil Horman -+Description: -+ This attribute indicates the mode that the irq vector named by -+ the parent directory is in (msi vs. msix) -+ - What: /sys/bus/pci/devices/.../remove - Date: January 2009 - Contact: Linux PCI developers -diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c -index 2f10328..73613e2 100644 ---- a/drivers/pci/msi.c -+++ b/drivers/pci/msi.c -@@ -322,6 +322,8 @@ static void free_msi_irqs(struct pci_dev *dev) - if (list_is_last(&entry->list, &dev->msi_list)) - iounmap(entry->mask_base); - } -+ kobject_del(&entry->kobj); -+ kobject_put(&entry->kobj); - list_del(&entry->list); - kfree(entry); - } -@@ -402,6 +404,98 @@ void pci_restore_msi_state(struct pci_dev *dev) - } - EXPORT_SYMBOL_GPL(pci_restore_msi_state); - -+ -+#define to_msi_attr(obj) container_of(obj, struct msi_attribute, attr) -+#define to_msi_desc(obj) container_of(obj, struct msi_desc, kobj) -+ -+struct msi_attribute { -+ struct attribute attr; -+ ssize_t (*show)(struct msi_desc *entry, struct msi_attribute *attr, -+ char *buf); -+ ssize_t (*store)(struct msi_desc *entry, struct msi_attribute *attr, -+ const char *buf, size_t count); -+}; -+ -+static ssize_t show_msi_mode(struct msi_desc *entry, struct msi_attribute *atr, -+ char *buf) -+{ -+ return sprintf(buf, "%s\n", entry->msi_attrib.is_msix ? "msix" : "msi"); -+} -+ -+static ssize_t msi_irq_attr_show(struct kobject *kobj, -+ struct attribute *attr, char *buf) -+{ -+ struct msi_attribute *attribute = to_msi_attr(attr); -+ struct msi_desc *entry = to_msi_desc(kobj); -+ -+ if (!attribute->show) -+ return -EIO; -+ -+ return attribute->show(entry, attribute, buf); -+} -+ -+static const struct sysfs_ops msi_irq_sysfs_ops = { -+ .show = msi_irq_attr_show, -+}; -+ -+static struct msi_attribute mode_attribute = -+ __ATTR(mode, S_IRUGO, show_msi_mode, NULL); -+ -+ -+struct attribute *msi_irq_default_attrs[] = { -+ &mode_attribute.attr, -+ NULL -+}; -+ -+void msi_kobj_release(struct kobject *kobj) -+{ -+ struct msi_desc *entry = to_msi_desc(kobj); -+ -+ pci_dev_put(entry->dev); -+} -+ -+static struct kobj_type msi_irq_ktype = { -+ .release = msi_kobj_release, -+ .sysfs_ops = &msi_irq_sysfs_ops, -+ .default_attrs = msi_irq_default_attrs, -+}; -+ -+static int populate_msi_sysfs(struct pci_dev *pdev) -+{ -+ struct msi_desc *entry; -+ struct kobject *kobj; -+ int ret; -+ int count = 0; -+ -+ pdev->msi_kset = kset_create_and_add("msi_irqs", NULL, &pdev->dev.kobj); -+ if (!pdev->msi_kset) -+ return -ENOMEM; -+ -+ list_for_each_entry(entry, &pdev->msi_list, list) { -+ kobj = &entry->kobj; -+ kobj->kset = pdev->msi_kset; -+ pci_dev_get(pdev); -+ ret = kobject_init_and_add(kobj, &msi_irq_ktype, NULL, -+ "%u", entry->irq); -+ if (ret) -+ goto out_unroll; -+ -+ count++; -+ } -+ -+ return 0; -+ -+out_unroll: -+ list_for_each_entry(entry, &pdev->msi_list, list) { -+ if (!count) -+ break; -+ kobject_del(&entry->kobj); -+ kobject_put(&entry->kobj); -+ count--; -+ } -+ return ret; -+} -+ - /** - * msi_capability_init - configure device's MSI capability structure - * @dev: pointer to the pci_dev data structure of MSI device function -@@ -453,6 +547,13 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) - return ret; - } - -+ ret = populate_msi_sysfs(dev); -+ if (ret) { -+ msi_mask_irq(entry, mask, ~mask); -+ free_msi_irqs(dev); -+ return ret; -+ } -+ - /* Set MSI enabled bits */ - pci_intx_for_msi(dev, 0); - msi_set_enable(dev, pos, 1); -@@ -573,6 +674,12 @@ static int msix_capability_init(struct pci_dev *dev, - - msix_program_entries(dev, entries); - -+ ret = populate_msi_sysfs(dev); -+ if (ret) { -+ ret = 0; -+ goto error; -+ } -+ - /* Set MSI-X enabled bits and unmask the function */ - pci_intx_for_msi(dev, 0); - dev->msix_enabled = 1; -@@ -731,6 +838,8 @@ void pci_disable_msi(struct pci_dev *dev) - - pci_msi_shutdown(dev); - free_msi_irqs(dev); -+ kset_unregister(dev->msi_kset); -+ dev->msi_kset = NULL; - } - EXPORT_SYMBOL(pci_disable_msi); - -@@ -829,6 +938,8 @@ void pci_disable_msix(struct pci_dev *dev) - - pci_msix_shutdown(dev); - free_msi_irqs(dev); -+ kset_unregister(dev->msi_kset); -+ dev->msi_kset = NULL; - } - EXPORT_SYMBOL(pci_disable_msix); - -diff --git a/include/linux/msi.h b/include/linux/msi.h -index 05acced..ce93a34 100644 ---- a/include/linux/msi.h -+++ b/include/linux/msi.h -@@ -1,6 +1,7 @@ - #ifndef LINUX_MSI_H - #define LINUX_MSI_H - -+#include - #include - - struct msi_msg { -@@ -44,6 +45,8 @@ struct msi_desc { - - /* Last set MSI message */ - struct msi_msg msg; -+ -+ struct kobject kobj; - }; - - /* -diff --git a/include/linux/pci.h b/include/linux/pci.h -index 7cda65b..84225c7 100644 ---- a/include/linux/pci.h -+++ b/include/linux/pci.h -@@ -336,6 +336,7 @@ struct pci_dev { - struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */ - #ifdef CONFIG_PCI_MSI - struct list_head msi_list; -+ struct kset *msi_kset; - #endif - struct pci_vpd *vpd; - #ifdef CONFIG_PCI_ATS diff --git a/utrace.patch b/utrace.patch index 5f678e592..fdf24a472 100644 --- a/utrace.patch +++ b/utrace.patch @@ -1,81 +1,74 @@ -From davej Wed Aug 3 15:16:11 2011 -From oleg@redhat.com Mon Nov 21 15:06:14 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:14 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9A1F8D50F1; - Mon, 21 Nov 2011 15:06:14 -0500 (EST) -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 gJzpul4rDNnA; Mon, 21 Nov 2011 15:06:14 -0500 (EST) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7DD4BD50EA; - Mon, 21 Nov 2011 15:06:14 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6BJJ022074; - Mon, 21 Nov 2011 15:06:12 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:32 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:30 +0100 +From d007ce2c3f1f67624fde5e6b7ccc00566b7df9c3 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 01/33] utrace core -Message-ID: <20111121200130.GA27756@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Status: RO -Content-Length: 139951 -Lines: 3867 +Date: Sat, 25 Feb 2012 07:29:40 -0500 +Subject: [PATCH] utrace for 3.3-rc4 kernel, on top of + b52b80023f262ce8a0ffdcb490acb23e8678377a. -From: Roland McGrath +The split-out series is available in the git repository at: -This adds the utrace facility, a new modular interface in the kernel for -implementing user thread tracing and debugging. This fits on top of the -tracehook_* layer, so the new code is well-isolated. + git@github.com:utrace/linux.git utrace-3.3 -The new interface is in and the DocBook utrace book -describes it. It allows for multiple separate tracing engines to work in -parallel without interfering with each other. Higher-level tracing -facilities can be implemented as loadable kernel modules using this layer. +Oleg Nesterov (31): + utrace: add utrace_init_task/utrace_free_task calls + tracehooks: add utrace hooks + tracehooks: reintroduce tracehook_consider_fatal_signal() + add utrace hooks into sig_ignored() and recalc_sigpending() + restore the EXEC/EXIT/CLONE utrace hooks + utrace: utrace_report_death() can use task_utrace_struct() + restore the DEATH/REAP utrace hooks + utrace: remove jobctl bits + ptrace: take ->siglock around s/TRACED/RUNNING/ + introduce wake_up_quiescent() + introduce ptrace_signal_wake_up() + wait_task_inactive: treat task->state and match_state as bitmasks + introduce TASK_UTRACED state + utrace: use TASK_UTRACED instead of TASK_TRACED + reintroduce tracehook_finish_jctl() as utrace_end_stop() + teach wake_up_quiescent() to do "selective" wake_up + ptrace_stop: do not assume the task is running after wake_up_quiescent() + get_signal_to_deliver: restore/restructure utrace/ptrace signal reporting + utrace_get_signal: s/JOBCTL_STOP_PENDING/JOBCTL_PENDING_MASK/ + introduce ptrace_set_syscall_trace() + introduce PT_SYSCALL_TRACE flag + utrace: don't clear TIF_SYSCALL_TRACE if it is needed by ptrace + introduce task_utrace_lock/task_utrace_unlock + teach ptrace_set_syscall_trace() to play well with utrace + introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK + utrace: finish_resume_report: don't do user_xxx_step() if ptrace_wants_step() + ptrace: shift user_*_step() from ptrace_resume() to ptrace_stop() + ptrace_disable: no need to disable stepping + ptrace_report_syscall: check TIF_SYSCALL_EMU + utrace_resume: check irqs_disabled() to shut up lockdep + utrace: s390: fix the compile problem with traps.c -The new facility is made optional under CONFIG_UTRACE. -When this is not enabled, no new code is added. -It can only be enabled on machines that have all the -prerequisites and select CONFIG_HAVE_ARCH_TRACEHOOK. +Roland McGrath (1): + utrace core -In this initial version, utrace and ptrace do not play together at all, -the next patches try to fix this. +Tony Breeds (1): + ptrace_report_syscall: check if TIF_SYSCALL_EMU is defined -This is is same/old utrace-core patch except: - - - use task->jobctl/JOBCTL_STOP_DEQUEUED instead of removed - signal->flags/SIGNAL_STOP_DEQUEUED in utrace_get_signal() - - - do not include the tracehook changes, this comes with the - next patches - -Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov --- Documentation/DocBook/Makefile | 2 +- Documentation/DocBook/utrace.tmpl | 589 +++++++++ - fs/proc/array.c | 3 + - include/linux/sched.h | 5 + - include/linux/utrace.h | 692 +++++++++++ + arch/s390/kernel/traps.c | 6 +- + arch/x86/kernel/ptrace.c | 1 - + fs/exec.c | 5 +- + fs/proc/array.c | 14 +- + include/linux/ptrace.h | 7 + + include/linux/sched.h | 25 +- + include/linux/signal.h | 2 + + include/linux/tracehook.h | 59 +- + include/linux/utrace.h | 774 ++++++++++++ init/Kconfig | 9 + kernel/Makefile | 1 + - kernel/utrace.c | 2440 +++++++++++++++++++++++++++++++++++++ - 8 files changed, 3740 insertions(+), 1 deletions(-) + kernel/exit.c | 5 + + kernel/fork.c | 9 + + kernel/ptrace.c | 57 +- + kernel/sched/core.c | 2 +- + kernel/signal.c | 97 ++- + kernel/utrace.c | 2466 +++++++++++++++++++++++++++++++++++++ + 19 files changed, 4074 insertions(+), 56 deletions(-) create mode 100644 Documentation/DocBook/utrace.tmpl create mode 100644 include/linux/utrace.h create mode 100644 kernel/utrace.c @@ -688,8 +681,69 @@ index 0000000..0c40add + + + +diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c +index 5ce3750..4f0b32f 100644 +--- a/arch/s390/kernel/traps.c ++++ b/arch/s390/kernel/traps.c +@@ -18,7 +18,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +@@ -330,7 +330,7 @@ void __kprobes do_per_trap(struct pt_regs *regs) + + if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) + return; +- if (!current->ptrace) ++ if (!tracehook_consider_fatal_signal(current, SIGTRAP)) + return; + info.si_signo = SIGTRAP; + info.si_errno = 0; +@@ -415,7 +415,7 @@ static void __kprobes illegal_op(struct pt_regs *regs) + if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) + return; + if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) { +- if (current->ptrace) { ++ if (tracehook_consider_fatal_signal(current, SIGTRAP)) { + info.si_signo = SIGTRAP; + info.si_errno = 0; + info.si_code = TRAP_BRKPT; +diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c +index 5026738..97687f3 100644 +--- a/arch/x86/kernel/ptrace.c ++++ b/arch/x86/kernel/ptrace.c +@@ -809,7 +809,6 @@ static int ioperm_get(struct task_struct *target, + */ + void ptrace_disable(struct task_struct *child) + { +- user_disable_single_step(child); + #ifdef TIF_SYSCALL_EMU + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); + #endif +diff --git a/fs/exec.c b/fs/exec.c +index 92ce83a..87ff31f 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1402,9 +1402,12 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) + */ + bprm->recursion_depth = depth; + if (retval >= 0) { +- if (depth == 0) ++ if (depth == 0) { ++ UTRACE_HOOK(current, EXEC, ++ report_exec(fmt, bprm, regs)); + ptrace_event(PTRACE_EVENT_EXEC, + old_pid); ++ } + put_binfmt(fmt); + allow_write_access(bprm->file); + if (bprm->file) diff --git a/fs/proc/array.c b/fs/proc/array.c -index 3a1dafd..f0c0ea2 100644 +index c602b8d..a700b78 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -81,6 +81,7 @@ @@ -700,7 +754,25 @@ index 3a1dafd..f0c0ea2 100644 #include #include -@@ -192,6 +193,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, +@@ -137,11 +138,12 @@ static const char * const task_state_array[] = { + "D (disk sleep)", /* 2 */ + "T (stopped)", /* 4 */ + "t (tracing stop)", /* 8 */ +- "Z (zombie)", /* 16 */ +- "X (dead)", /* 32 */ +- "x (dead)", /* 64 */ +- "K (wakekill)", /* 128 */ +- "W (waking)", /* 256 */ ++ "t (tracing stop)", /* 16 (stopped by utrace) */ ++ "Z (zombie)", /* 32 */ ++ "X (dead)", /* 64 */ ++ "x (dead)", /* 128 */ ++ "K (wakekill)", /* 256 */ ++ "W (waking)", /* 512 */ + }; + + static inline const char *get_task_state(struct task_struct *tsk) +@@ -192,6 +194,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, cred->uid, cred->euid, cred->suid, cred->fsuid, cred->gid, cred->egid, cred->sgid, cred->fsgid); @@ -709,11 +781,87 @@ index 3a1dafd..f0c0ea2 100644 task_lock(p); if (p->files) fdt = files_fdtable(p->files); +diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h +index c2f1f6a..236b920 100644 +--- a/include/linux/ptrace.h ++++ b/include/linux/ptrace.h +@@ -104,6 +104,10 @@ + + #define PT_TRACE_MASK 0x000003f4 + ++#define PT_SYSCALL_TRACE 0x00020000 ++#define PT_SINGLE_STEP 0x00040000 ++#define PT_SINGLE_BLOCK 0x00080000 ++ + /* single stepping state bits (used on ARM and PA-RISC) */ + #define PT_SINGLESTEP_BIT 31 + #define PT_SINGLESTEP (1< /* For struct task_struct. */ + #include /* for IS_ERR_VALUE */ + ++extern void ptrace_signal_wake_up(struct task_struct *p, int quiescent); + + extern long arch_ptrace(struct task_struct *child, long request, + unsigned long addr, unsigned long data); +@@ -228,6 +233,8 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) + + if (unlikely(ptrace) && current->ptrace) { + child->ptrace = current->ptrace; ++ child->ptrace &= ++ ~(PT_SYSCALL_TRACE | PT_SINGLE_STEP | PT_SINGLE_BLOCK); + __ptrace_link(child, current->parent); + + if (child->ptrace & PT_SEIZED) diff --git a/include/linux/sched.h b/include/linux/sched.h -index 68daf4f..4d45f93 100644 +index 7d379a6..a3c4599 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h -@@ -1403,6 +1403,11 @@ struct task_struct { +@@ -185,16 +185,17 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) + #define TASK_UNINTERRUPTIBLE 2 + #define __TASK_STOPPED 4 + #define __TASK_TRACED 8 ++#define __TASK_UTRACED 16 + /* in tsk->exit_state */ +-#define EXIT_ZOMBIE 16 +-#define EXIT_DEAD 32 ++#define EXIT_ZOMBIE 32 ++#define EXIT_DEAD 64 + /* in tsk->state again */ +-#define TASK_DEAD 64 +-#define TASK_WAKEKILL 128 +-#define TASK_WAKING 256 +-#define TASK_STATE_MAX 512 ++#define TASK_DEAD 128 ++#define TASK_WAKEKILL 256 ++#define TASK_WAKING 512 ++#define TASK_STATE_MAX 1024 + +-#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKW" ++#define TASK_STATE_TO_CHAR_STR "RSDTtUZXxKW" + + extern char ___assert_task_state[1 - 2*!!( + sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1)]; +@@ -203,15 +204,16 @@ extern char ___assert_task_state[1 - 2*!!( + #define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE) + #define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED) + #define TASK_TRACED (TASK_WAKEKILL | __TASK_TRACED) ++#define TASK_UTRACED (TASK_WAKEKILL | __TASK_UTRACED) + + /* Convenience macros for the sake of wake_up */ + #define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE) +-#define TASK_ALL (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED) ++#define TASK_ALL (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED | __TASK_UTRACED) + + /* get_task_state() */ + #define TASK_REPORT (TASK_RUNNING | TASK_INTERRUPTIBLE | \ + TASK_UNINTERRUPTIBLE | __TASK_STOPPED | \ +- __TASK_TRACED) ++ __TASK_TRACED | __TASK_UTRACED) + + #define task_is_traced(task) ((task->state & __TASK_TRACED) != 0) + #define task_is_stopped(task) ((task->state & __TASK_STOPPED) != 0) +@@ -1420,6 +1422,11 @@ struct task_struct { #endif seccomp_t seccomp; @@ -725,12 +873,140 @@ index 68daf4f..4d45f93 100644 /* Thread group tracking */ u32 parent_exec_id; u32 self_exec_id; +diff --git a/include/linux/signal.h b/include/linux/signal.h +index 7987ce74..c320549 100644 +--- a/include/linux/signal.h ++++ b/include/linux/signal.h +@@ -239,6 +239,8 @@ static inline int valid_signal(unsigned long sig) + struct timespec; + struct pt_regs; + ++extern int wake_up_quiescent(struct task_struct *p, unsigned int state); ++ + extern int next_signal(struct sigpending *pending, sigset_t *mask); + extern int do_send_sig_info(int sig, struct siginfo *info, + struct task_struct *p, bool group); +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index a71a292..a1bac95 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + struct linux_binprm; + + /* +@@ -58,8 +59,12 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) + { + int ptrace = current->ptrace; + +- if (!(ptrace & PT_PTRACED)) +- return; ++ if (!(ptrace & PT_SYSCALL_TRACE)) { ++#ifdef TIF_SYSCALL_EMU ++ if (!test_thread_flag(TIF_SYSCALL_EMU)) ++#endif ++ return; ++ } + + ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); + +@@ -96,10 +101,16 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) + static inline __must_check int tracehook_report_syscall_entry( + struct pt_regs *regs) + { ++ if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && ++ utrace_report_syscall_entry(regs)) ++ return 1; + ptrace_report_syscall(regs); + return 0; + } + ++#define ptrace_wants_step(task) \ ++ ((task)->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK)) ++ + /** + * tracehook_report_syscall_exit - task has just finished a system call + * @regs: user register state of current task +@@ -119,7 +130,10 @@ static inline __must_check int tracehook_report_syscall_entry( + */ + static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) + { +- if (step) { ++ if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) ++ utrace_report_syscall_exit(regs); ++ ++ if (step && ptrace_wants_step(current)) { + siginfo_t info; + user_single_step_siginfo(current, regs, &info); + force_sig_info(SIGTRAP, &info, current); +@@ -148,10 +162,34 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, + const struct k_sigaction *ka, + struct pt_regs *regs, int stepping) + { +- if (stepping) ++ if (task_utrace_flags(current)) ++ utrace_signal_handler(current, stepping); ++ if (stepping && ptrace_wants_step(current)) + ptrace_notify(SIGTRAP); + } + ++/** ++ * tracehook_consider_fatal_signal - suppress special handling of fatal signal ++ * @task: task receiving the signal ++ * @sig: signal number being sent ++ * ++ * Return nonzero to prevent special handling of this termination signal. ++ * Normally handler for signal is %SIG_DFL. It can be %SIG_IGN if @sig is ++ * ignored, in which case force_sig() is about to reset it to %SIG_DFL. ++ * When this returns zero, this signal might cause a quick termination ++ * that does not give the debugger a chance to intercept the signal. ++ * ++ * Called with or without @task->sighand->siglock held. ++ */ ++static inline int tracehook_consider_fatal_signal(struct task_struct *task, ++ int sig) ++{ ++ if (unlikely(task_utrace_flags(task) & (UTRACE_EVENT(SIGNAL_TERM) | ++ UTRACE_EVENT(SIGNAL_CORE)))) ++ return 1; ++ return task->ptrace != 0; ++} ++ + #ifdef TIF_NOTIFY_RESUME + /** + * set_notify_resume - cause tracehook_notify_resume() to be called +@@ -179,10 +217,21 @@ static inline void set_notify_resume(struct task_struct *task) + * asynchronously, this will be called again before we return to + * user mode. + * +- * Called without locks. ++ * Called without locks. However, on some machines this may be ++ * called with interrupts disabled. + */ + static inline void tracehook_notify_resume(struct pt_regs *regs) + { ++ struct task_struct *task = current; ++ /* ++ * Prevent the following store/load from getting ahead of the ++ * caller which clears TIF_NOTIFY_RESUME. This pairs with the ++ * implicit mb() before setting TIF_NOTIFY_RESUME in ++ * set_notify_resume(). ++ */ ++ smp_mb(); ++ if (task_utrace_flags(task)) ++ utrace_resume(task, regs); + } + #endif /* TIF_NOTIFY_RESUME */ + diff --git a/include/linux/utrace.h b/include/linux/utrace.h new file mode 100644 -index 0000000..f251efe +index 0000000..46959af --- /dev/null +++ b/include/linux/utrace.h -@@ -0,0 +1,692 @@ +@@ -0,0 +1,774 @@ +/* + * utrace infrastructure interface for debugging user processes + * @@ -832,7 +1108,7 @@ index 0000000..f251efe +void utrace_report_clone(unsigned long, struct task_struct *); +void utrace_finish_vfork(struct task_struct *); +void utrace_report_exit(long *exit_code); -+void utrace_report_death(struct task_struct *, struct utrace *, bool, int); ++void utrace_report_death(struct task_struct *, bool, int); +void utrace_report_jctl(int notify, int type); +void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *, + struct pt_regs *regs); @@ -840,8 +1116,22 @@ index 0000000..f251efe +void utrace_report_syscall_exit(struct pt_regs *); +void utrace_signal_handler(struct task_struct *, int); + ++#define UTRACE_FLAG(task, ev) (task_utrace_flags(task) & UTRACE_EVENT(ev)) ++ ++#define UTRACE_HOOK(task, ev, callback) \ ++ do { \ ++ if (UTRACE_FLAG(task, ev)) \ ++ utrace_ ## callback; \ ++ } while (0) ++ +#ifndef CONFIG_UTRACE + ++static inline void task_utrace_lock(struct task_struct *task) ++{ ++} ++static inline void task_utrace_unlock(struct task_struct *task) ++{ ++} +/* + * uses these accessors to avoid #ifdef CONFIG_UTRACE. + */ @@ -864,6 +1154,9 @@ index 0000000..f251efe + +#else /* CONFIG_UTRACE */ + ++extern void task_utrace_lock(struct task_struct *task); ++extern void task_utrace_unlock(struct task_struct *task); ++ +static inline unsigned long task_utrace_flags(struct task_struct *task) +{ + return task->utrace_flags; @@ -1033,6 +1326,7 @@ index 0000000..f251efe +#define UTRACE_ATTACH_MATCH_MASK 0x000f +#define UTRACE_ATTACH_CREATE 0x0010 /* Attach a new engine. */ +#define UTRACE_ATTACH_EXCLUSIVE 0x0020 /* Refuse if existing match. */ ++#define UTRACE_ATTACH_ATOMIC 0x0040 /* For _CREATE, don't sleep */ + +/** + * struct utrace_engine - per-engine structure @@ -1422,14 +1716,78 @@ index 0000000..f251efe + +#endif /* CONFIG_UTRACE */ + ++static inline void utrace_release_task(struct task_struct *task) ++{ ++ /* see utrace_add_engine() about this barrier */ ++ smp_mb(); ++ if (task_utrace_flags(task)) ++ utrace_maybe_reap(task, task_utrace_struct(task), true); ++} ++ ++static inline void utrace_exit_notify(struct task_struct *task, ++ int signal, int group_dead) ++{ ++ /* ++ * If utrace_set_events() was just called to enable ++ * UTRACE_EVENT(DEATH), then we are obliged to call ++ * utrace_report_death() and not miss it. utrace_set_events() ++ * checks @task->exit_state under tasklist_lock to synchronize ++ * with exit_notify(), the caller. ++ */ ++ if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) ++ utrace_report_death(task, group_dead, signal); ++} ++ ++/** ++ * utrace_end_stop - report about return from STOPPED/TRACED ++ * ++ * This is called by do_signal_stop() and ptrace_stop after wakeup. ++ */ ++static inline void utrace_end_stop(void) ++{ ++ if (task_utrace_flags(current)) ++ utrace_finish_stop(); ++} ++ ++/** ++ * utrace_hook_signal - deliver synthetic signal to traced task ++ * @task: @current ++ * @regs: task_pt_regs(@current) ++ * @info: details of synthetic signal ++ * @return_ka: sigaction for synthetic signal ++ * ++ * Return zero to check for a real pending signal normally. ++ * Return -1 after releasing the siglock to repeat the check. ++ * Return a signal number to induce an artificial signal delivery, ++ * setting *@info and *@return_ka to specify its details and behavior. ++ * ++ * The @return_ka->sa_handler value controls the disposition of the ++ * signal, no matter the signal number. For %SIG_DFL, the return value ++ * is a representative signal to indicate the behavior (e.g. %SIGTERM ++ * for death, %SIGQUIT for core dump, %SIGSTOP for job control stop, ++ * %SIGTSTP for stop unless in an orphaned pgrp), but the signal number ++ * reported will be @info->si_signo instead. ++ * ++ * Called with @task->sighand->siglock held, before dequeuing pending signals. ++ */ ++static inline int utrace_hook_signal(struct task_struct *task, ++ struct pt_regs *regs, ++ siginfo_t *info, ++ struct k_sigaction *return_ka) ++{ ++ if (unlikely(task_utrace_flags(task))) ++ return utrace_get_signal(task, regs, info, return_ka); ++ return 0; ++} ++ +#endif /* linux/utrace.h */ diff --git a/init/Kconfig b/init/Kconfig -index 43298f9..3f670e5 100644 +index 3f42cd6..5f4f92e 100644 --- a/init/Kconfig +++ b/init/Kconfig -@@ -372,6 +372,15 @@ config AUDIT_TREE - depends on AUDITSYSCALL - select FSNOTIFY +@@ -386,6 +386,15 @@ config AUDIT_LOGINUID_IMMUTABLE + one to drop potentially dangerous capabilites from the login tasks, + but may not be backwards compatible with older init systems. +config UTRACE + bool "Infrastructure for tracing and debugging user processes" @@ -1444,10 +1802,10 @@ index 43298f9..3f670e5 100644 menu "RCU Subsystem" diff --git a/kernel/Makefile b/kernel/Makefile -index e898c5b..e43bbfb 100644 +index 2d9de86..6c6749d 100644 --- a/kernel/Makefile +++ b/kernel/Makefile -@@ -68,6 +68,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o +@@ -67,6 +67,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o obj-$(CONFIG_SMP) += stop_machine.o obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o @@ -1455,12 +1813,418 @@ index e898c5b..e43bbfb 100644 obj-$(CONFIG_AUDIT) += audit.o auditfilter.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o obj-$(CONFIG_AUDIT_WATCH) += audit_watch.o +diff --git a/kernel/exit.c b/kernel/exit.c +index 4b4042f..b1e0518 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -169,6 +169,8 @@ void release_task(struct task_struct * p) + struct task_struct *leader; + int zap_leader; + repeat: ++ utrace_release_task(p); ++ + /* don't need to get the RCU readlock here - the process is dead and + * can't be modifying its own credentials. But shut RCU-lockdep up */ + rcu_read_lock(); +@@ -857,6 +859,8 @@ static void exit_notify(struct task_struct *tsk, int group_dead) + wake_up_process(tsk->signal->group_exit_task); + write_unlock_irq(&tasklist_lock); + ++ utrace_exit_notify(tsk, autoreap ? -1 : SIGCHLD, group_dead); ++ + /* If the process is dead, release it - nobody will wait for it */ + if (autoreap) + release_task(tsk); +@@ -910,6 +914,7 @@ void do_exit(long code) + */ + set_fs(USER_DS); + ++ UTRACE_HOOK(current, EXIT, report_exit(&code)); + ptrace_event(PTRACE_EVENT_EXIT, code); + + validate_creds_for_do_exit(tsk); +diff --git a/kernel/fork.c b/kernel/fork.c +index e2cd3e2..fa40928 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -67,6 +67,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -170,6 +171,8 @@ void free_task(struct task_struct *tsk) + free_thread_info(tsk->stack); + rt_mutex_debug_task_free(tsk); + ftrace_graph_exit_task(tsk); ++ if (task_utrace_struct(tsk)) ++ utrace_free_task(tsk); + free_task_struct(tsk); + } + EXPORT_SYMBOL(free_task); +@@ -1115,6 +1118,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, + if (!p) + goto fork_out; + ++ utrace_init_task(p); ++ + ftrace_graph_init_task(p); + + rt_mutex_init_task(p); +@@ -1583,6 +1583,8 @@ long do_fork(unsigned long clone_flags, + get_task_struct(p); + } + ++ UTRACE_HOOK(current, CLONE, report_clone(clone_flags, p)); ++ + wake_up_new_task(p); + + /* forking complete and child started to run, tell ptracer */ +@@ -1561,6 +1568,8 @@ long do_fork(unsigned long clone_flags, + wake_up_new_task(p); + + /* forking complete and child started to run, tell ptracer */ ++ if (clone_flags & CLONE_VFORK) ++ UTRACE_HOOK(current, CLONE, finish_vfork(current)); + if (unlikely(trace)) + ptrace_event(trace, nr); + +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index 00ab2ca..a7024b8 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -24,7 +24,34 @@ + #include + #include + #include ++#include + ++void ptrace_signal_wake_up(struct task_struct *p, int quiescent) ++{ ++ unsigned int state; ++ ++ set_tsk_thread_flag(p, TIF_SIGPENDING); ++ ++ state = TASK_INTERRUPTIBLE; ++ if (quiescent) ++ state |= (__TASK_STOPPED | __TASK_TRACED); ++ if (!wake_up_quiescent(p, state)) ++ kick_process(p); ++} ++ ++static void ptrace_set_syscall_trace(struct task_struct *p, bool on) ++{ ++ task_utrace_lock(p); ++ if (on) { ++ p->ptrace |= PT_SYSCALL_TRACE; ++ set_tsk_thread_flag(p, TIF_SYSCALL_TRACE); ++ } else { ++ p->ptrace &= ~PT_SYSCALL_TRACE; ++ if (!(task_utrace_flags(p) & UTRACE_EVENT_SYSCALL)) ++ clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); ++ } ++ task_utrace_unlock(p); ++} + + static int ptrace_trapping_sleep_fn(void *flags) + { +@@ -117,7 +144,7 @@ void __ptrace_unlink(struct task_struct *child) + * TASK_KILLABLE sleeps. + */ + if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child)) +- signal_wake_up(child, task_is_traced(child)); ++ ptrace_signal_wake_up(child, task_is_traced(child)); + + spin_unlock(&child->sighand->siglock); + } +@@ -315,7 +342,7 @@ static int ptrace_attach(struct task_struct *task, long request, + */ + if (task_is_stopped(task) && + task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING)) +- signal_wake_up(task, 1); ++ ptrace_signal_wake_up(task, 1); + + spin_unlock(&task->sighand->siglock); + +@@ -425,7 +452,7 @@ static int ptrace_detach(struct task_struct *child, unsigned int data) + + /* Architecture-specific hardware disable .. */ + ptrace_disable(child); +- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); ++ ptrace_set_syscall_trace(child, false); + + write_lock_irq(&tasklist_lock); + /* +@@ -608,13 +635,12 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info) + static int ptrace_resume(struct task_struct *child, long request, + unsigned long data) + { ++ unsigned long flags; ++ + if (!valid_signal(data)) + return -EIO; + +- if (request == PTRACE_SYSCALL) +- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); +- else +- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); ++ ptrace_set_syscall_trace(child, request == PTRACE_SYSCALL); + + #ifdef TIF_SYSCALL_EMU + if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP) +@@ -623,20 +649,23 @@ static int ptrace_resume(struct task_struct *child, long request, + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); + #endif + ++ child->ptrace &= ~(PT_SINGLE_STEP | PT_SINGLE_BLOCK); + if (is_singleblock(request)) { + if (unlikely(!arch_has_block_step())) + return -EIO; +- user_enable_block_step(child); ++ child->ptrace |= PT_SINGLE_BLOCK; + } else if (is_singlestep(request) || is_sysemu_singlestep(request)) { + if (unlikely(!arch_has_single_step())) + return -EIO; +- user_enable_single_step(child); +- } else { +- user_disable_single_step(child); ++ child->ptrace |= PT_SINGLE_STEP; + } + + child->exit_code = data; +- wake_up_state(child, __TASK_TRACED); ++ ++ if (lock_task_sighand(child, &flags)) { ++ wake_up_quiescent(child, __TASK_TRACED); ++ unlock_task_sighand(child, &flags); ++ } + + return 0; + } +@@ -744,7 +773,7 @@ int ptrace_request(struct task_struct *child, long request, + * tracee into STOP. + */ + if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP))) +- signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); ++ ptrace_signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); + + unlock_task_sighand(child, &flags); + ret = 0; +@@ -770,7 +799,7 @@ int ptrace_request(struct task_struct *child, long request, + * start of this trap and now. Trigger re-trap. + */ + if (child->jobctl & JOBCTL_TRAP_NOTIFY) +- signal_wake_up(child, true); ++ ptrace_signal_wake_up(child, true); + ret = 0; + } + unlock_task_sighand(child, &flags); +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 5255c9d..f1719b8 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -1167,7 +1167,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) + * is actually now running somewhere else! + */ + while (task_running(rq, p)) { +- if (match_state && unlikely(p->state != match_state)) ++ if (match_state && !likely(p->state & match_state)) + return 0; + cpu_relax(); + } +diff --git a/kernel/signal.c b/kernel/signal.c +index c73c428..0508d93 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -88,7 +88,7 @@ static int sig_ignored(struct task_struct *t, int sig, int from_ancestor_ns) + /* + * Tracers may want to know about even ignored signals. + */ +- return !t->ptrace; ++ return !t->ptrace && !UTRACE_FLAG(t, SIGNAL_IGN); + } + + /* +@@ -151,6 +151,11 @@ void recalc_sigpending_and_wake(struct task_struct *t) + + void recalc_sigpending(void) + { ++ if (task_utrace_flags(current) && utrace_interrupt_pending()) { ++ set_thread_flag(TIF_SIGPENDING); ++ return; ++ } ++ + if (!recalc_sigpending_tsk(current) && !freezing(current)) + clear_thread_flag(TIF_SIGPENDING); + +@@ -495,7 +500,7 @@ int unhandled_signal(struct task_struct *tsk, int sig) + if (handler != SIG_IGN && handler != SIG_DFL) + return 0; + /* if ptraced, let the tracer determine */ +- return !tsk->ptrace; ++ return !tracehook_consider_fatal_signal(tsk, sig); + } + + /* +@@ -697,6 +702,29 @@ void signal_wake_up(struct task_struct *t, int resume) + kick_process(t); + } + ++#define STATE_QUIESCENT (__TASK_STOPPED | __TASK_TRACED | __TASK_UTRACED) ++/* ++ * wakes up the STOPPED/TRACED task, must be called with ->siglock held. ++ */ ++int wake_up_quiescent(struct task_struct *p, unsigned int state) ++{ ++ unsigned int quiescent = (p->state & STATE_QUIESCENT); ++ ++ WARN_ON(state & ~(STATE_QUIESCENT | TASK_INTERRUPTIBLE)); ++ ++ if (quiescent) { ++ state &= ~TASK_INTERRUPTIBLE; ++ if ((quiescent & ~state) != 0) { ++ p->state &= ~state; ++ WARN_ON(!(p->state & STATE_QUIESCENT)); ++ WARN_ON(!(p->state & TASK_WAKEKILL)); ++ return 0; ++ } ++ } ++ ++ return wake_up_state(p, state); ++} ++ + /* + * Remove signals in mask from the pending set and queue. + * Returns 1 if any signals were found. +@@ -842,7 +870,7 @@ static void ptrace_trap_notify(struct task_struct *t) + assert_spin_locked(&t->sighand->siglock); + + task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY); +- signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); ++ ptrace_signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); + } + + /* +@@ -884,7 +912,7 @@ static int prepare_signal(int sig, struct task_struct *p, int from_ancestor_ns) + task_clear_jobctl_pending(t, JOBCTL_STOP_PENDING); + rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending); + if (likely(!(t->ptrace & PT_SEIZED))) +- wake_up_state(t, __TASK_STOPPED); ++ wake_up_quiescent(t, __TASK_STOPPED); + else + ptrace_trap_notify(t); + } while_each_thread(p, t); +@@ -983,7 +1011,7 @@ static void complete_signal(int sig, struct task_struct *p, int group) + if (sig_fatal(p, sig) && + !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) && + !sigismember(&t->real_blocked, sig) && +- (sig == SIGKILL || !t->ptrace)) { ++ (sig == SIGKILL || !tracehook_consider_fatal_signal(t, sig))) { + /* + * This signal will be fatal to the whole group. + */ +@@ -1913,10 +1941,34 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) + if (gstop_done) + do_notify_parent_cldstop(current, false, why); + +- __set_current_state(TASK_RUNNING); ++ spin_lock_irq(¤t->sighand->siglock); ++ wake_up_quiescent(current, __TASK_TRACED); ++ spin_unlock_irq(¤t->sighand->siglock); ++ + if (clear_code) + current->exit_code = 0; + read_unlock(&tasklist_lock); ++ ++ /* ++ * It is possible that __TASK_UTRACED was added by utrace ++ * while we were __TASK_TRACED and before we take ->siglock ++ * for wake_up_quiescent(), we need to block in this case. ++ * Otherwise this is unnecessary but absolutely harmless. ++ */ ++ schedule(); ++ } ++ ++ utrace_end_stop(); ++ ++ if (current->ptrace & PT_SINGLE_BLOCK) ++ user_enable_block_step(current); ++ else if (current->ptrace & PT_SINGLE_STEP) ++ user_enable_single_step(current); ++ else { ++ user_disable_single_step(current); ++ /* if utrace needs the stepping it should reassert */ ++ if (task_utrace_flags(current)) ++ set_thread_flag(TIF_NOTIFY_RESUME); + } + + /* +@@ -2081,6 +2133,9 @@ static bool do_signal_stop(int signr) + + /* Now we don't run again until woken by SIGCONT or SIGKILL */ + schedule(); ++ ++ utrace_end_stop(); ++ + return true; + } else { + /* +@@ -2231,17 +2286,27 @@ relock: + for (;;) { + struct k_sigaction *ka; + +- if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) && +- do_signal_stop(0)) ++ signr = utrace_hook_signal(current, regs, info, return_ka); ++ if (unlikely(signr < 0)) + goto relock; + +- if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) { +- do_jobctl_trap(); +- spin_unlock_irq(&sighand->siglock); +- goto relock; +- } ++ if (unlikely(signr != 0)) ++ ka = return_ka; ++ else { ++ if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) && ++ do_signal_stop(0)) ++ goto relock; ++ ++ if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) { ++ do_jobctl_trap(); ++ spin_unlock_irq(&sighand->siglock); ++ goto relock; ++ } + +- signr = dequeue_signal(current, ¤t->blocked, info); ++ signr = dequeue_signal(current, ¤t->blocked, info); ++ ++ ka = &sighand->action[signr-1]; ++ } + + if (!signr) + break; /* will return 0 */ +@@ -2251,9 +2316,9 @@ relock: + regs, cookie); + if (!signr) + continue; +- } + +- ka = &sighand->action[signr-1]; ++ ka = &sighand->action[signr-1]; ++ } + + /* Trace actually delivered signals. */ + trace_signal_deliver(signr, info, ka); diff --git a/kernel/utrace.c b/kernel/utrace.c new file mode 100644 -index 0000000..ef856c9 +index 0000000..a169e1b --- /dev/null +++ b/kernel/utrace.c -@@ -0,0 +1,2440 @@ +@@ -0,0 +1,2466 @@ +/* + * utrace infrastructure interface for debugging user processes + * @@ -1542,6 +2306,32 @@ index 0000000..ef856c9 +} +module_init(utrace_init); + ++void task_utrace_lock(struct task_struct *task) ++{ ++ struct utrace *utrace = task_utrace_struct(task); ++ ++ if (!utrace) { ++ task_lock(task); ++ utrace = task_utrace_struct(task); ++ if (!utrace) ++ return; ++ ++ task_unlock(task); ++ } ++ ++ spin_lock(&utrace->lock); ++} ++ ++void task_utrace_unlock(struct task_struct *task) ++{ ++ struct utrace *utrace = task_utrace_struct(task); ++ ++ if (utrace) ++ spin_unlock(&utrace->lock); ++ else ++ task_unlock(task); ++} ++ +/* + * Set up @task.utrace for the first time. We can have races + * between two utrace_attach_task() calls here. The task_lock() @@ -1550,9 +2340,9 @@ index 0000000..ef856c9 + * + * This returns false only in case of a memory allocation failure. + */ -+static bool utrace_task_alloc(struct task_struct *task) ++static bool utrace_task_alloc(struct task_struct *task, gfp_t gfp_flags) +{ -+ struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, GFP_KERNEL); ++ struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, gfp_flags); + if (unlikely(!utrace)) + return false; + spin_lock_init(&utrace->lock); @@ -1732,6 +2522,7 @@ index 0000000..ef856c9 +{ + struct utrace *utrace = task_utrace_struct(target); + struct utrace_engine *engine; ++ gfp_t gfp_flags; + int ret; + + if (!(flags & UTRACE_ATTACH_CREATE)) { @@ -1754,13 +2545,16 @@ index 0000000..ef856c9 + */ + return ERR_PTR(-EPERM); + ++ gfp_flags = (flags & UTRACE_ATTACH_ATOMIC) ++ ? GFP_ATOMIC : GFP_KERNEL; ++ + if (!utrace) { -+ if (unlikely(!utrace_task_alloc(target))) ++ if (unlikely(!utrace_task_alloc(target, gfp_flags))) + return ERR_PTR(-ENOMEM); + utrace = task_utrace_struct(target); + } + -+ engine = kmem_cache_alloc(utrace_engine_cachep, GFP_KERNEL); ++ engine = kmem_cache_alloc(utrace_engine_cachep, gfp_flags); + if (unlikely(!engine)) + return ERR_PTR(-ENOMEM); + @@ -1925,6 +2719,8 @@ index 0000000..ef856c9 + */ +#define ENGINE_STOP (1UL << _UTRACE_NEVENTS) + ++#define task_is_utraced(task) ((task->state & __TASK_UTRACED) != 0) ++ +static void mark_engine_wants_stop(struct task_struct *task, + struct utrace_engine *engine) +{ @@ -2039,7 +2835,7 @@ index 0000000..ef856c9 + + ret = 0; + if ((old_flags & ~events) && target != current && -+ !task_is_stopped_or_traced(target) && !target->exit_state) { ++ !task_is_utraced(target) && !target->exit_state) { + /* + * This barrier ensures that our engine->flags changes + * have hit before we examine utrace->reporting, @@ -2086,21 +2882,21 @@ index 0000000..ef856c9 + */ +static bool utrace_do_stop(struct task_struct *target, struct utrace *utrace) +{ -+ if (task_is_stopped(target)) { ++ if (task_is_stopped_or_traced(target)) { + /* + * Stopped is considered quiescent; when it wakes up, it will + * go through utrace_finish_stop() before doing anything else. + */ + spin_lock_irq(&target->sighand->siglock); -+ if (likely(task_is_stopped(target))) -+ __set_task_state(target, TASK_TRACED); ++ if (likely(task_is_stopped_or_traced(target))) ++ target->state |= TASK_UTRACED; + spin_unlock_irq(&target->sighand->siglock); + } else if (utrace->resume > UTRACE_REPORT) { + utrace->resume = UTRACE_REPORT; + set_notify_resume(target); + } + -+ return task_is_traced(target); ++ return task_is_utraced(target); +} + +/* @@ -2111,11 +2907,7 @@ index 0000000..ef856c9 +{ + lockdep_assert_held(&utrace->lock); + spin_lock_irq(&target->sighand->siglock); -+ if (target->signal->flags & SIGNAL_STOP_STOPPED || -+ target->signal->group_stop_count) -+ target->state = TASK_STOPPED; -+ else -+ wake_up_state(target, __TASK_TRACED); ++ wake_up_quiescent(target, __TASK_UTRACED); + spin_unlock_irq(&target->sighand->siglock); +} + @@ -2162,6 +2954,7 @@ index 0000000..ef856c9 + BUG_ON(utrace->death); + flags &= UTRACE_EVENT(REAP); + } else if (!(flags & UTRACE_EVENT_SYSCALL) && ++ !(task->ptrace & PT_SYSCALL_TRACE) && + test_tsk_thread_flag(task, TIF_SYSCALL_TRACE)) { + clear_tsk_thread_flag(task, TIF_SYSCALL_TRACE); + } @@ -2177,7 +2970,7 @@ index 0000000..ef856c9 + /* + * If no more engines want it stopped, wake it up. + */ -+ if (task_is_traced(task) && !(flags & ENGINE_STOP)) { ++ if (task_is_utraced(task) && !(flags & ENGINE_STOP)) { + /* + * It just resumes, so make sure single-step + * is not left set. @@ -2206,7 +2999,7 @@ index 0000000..ef856c9 +void utrace_finish_stop(void) +{ + /* -+ * If we were task_is_traced() and then SIGKILL'ed, make ++ * If we were task_is_utraced() and then SIGKILL'ed, make + * sure we do nothing until the tracer drops utrace->lock. + */ + if (unlikely(__fatal_signal_pending(current))) { @@ -2216,7 +3009,7 @@ index 0000000..ef856c9 +} + +/* -+ * Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up. ++ * Perform %UTRACE_STOP, i.e. block in TASK_UTRACED until woken up. + * @task == current, @utrace == current->utrace, which is not locked. + * Return true if we were woken up by SIGKILL even though some utrace + * engine may still want us to stay stopped. @@ -2266,15 +3059,7 @@ index 0000000..ef856c9 + return; + } + -+ __set_current_state(TASK_TRACED); -+ -+ /* -+ * If there is a group stop in progress, -+ * we must participate in the bookkeeping. -+ */ -+ if (unlikely(task->signal->group_stop_count) && -+ !--task->signal->group_stop_count) -+ task->signal->flags = SIGNAL_STOP_STOPPED; ++ __set_current_state(TASK_UTRACED); + + spin_unlock_irq(&task->sighand->siglock); + spin_unlock(&utrace->lock); @@ -2284,14 +3069,14 @@ index 0000000..ef856c9 + utrace_finish_stop(); + + /* -+ * While in TASK_TRACED, we were considered "frozen enough". ++ * While in TASK_UTRACED, we were considered "frozen enough". + * Now that we woke up, it's crucial if we're supposed to be + * frozen that we freeze now before running anything substantial. + */ + try_to_freeze(); + + /* -+ * While we were in TASK_TRACED, complete_signal() considered ++ * While we were in TASK_UTRACED, complete_signal() considered + * us "uninterested" in signal wakeups. Now make sure our + * TIF_SIGPENDING state is correct for normal running. + */ @@ -2562,7 +3347,7 @@ index 0000000..ef856c9 + if (unlikely(IS_ERR(utrace))) + return PTR_ERR(utrace); + -+ reset = task_is_traced(target); ++ reset = task_is_utraced(target); + ret = 0; + + /* @@ -3222,9 +4007,10 @@ index 0000000..ef856c9 + * For this reason, utrace_release_task checks for the event bits that get + * us here, and delays its cleanup for us to do. + */ -+void utrace_report_death(struct task_struct *task, struct utrace *utrace, -+ bool group_dead, int signal) ++void utrace_report_death(struct task_struct *task, bool group_dead, int signal) +{ ++ struct utrace *utrace = task_utrace_struct(task); ++ + INIT_REPORT(report); + + BUG_ON(!task->exit_state); @@ -3274,7 +4060,8 @@ index 0000000..ef856c9 + + case UTRACE_BLOCKSTEP: + if (likely(arch_has_block_step())) { -+ user_enable_block_step(task); ++ if (!ptrace_wants_step(task)) ++ user_enable_block_step(task); + break; + } + @@ -3287,7 +4074,8 @@ index 0000000..ef856c9 + + case UTRACE_SINGLESTEP: + if (likely(arch_has_single_step())) { -+ user_enable_single_step(task); ++ if (!ptrace_wants_step(task)) ++ user_enable_single_step(task); + } else { + /* + * This means some callback is to blame for failing @@ -3302,7 +4090,8 @@ index 0000000..ef856c9 + case UTRACE_REPORT: + case UTRACE_RESUME: + default: -+ user_disable_single_step(task); ++ if (!ptrace_wants_step(task)) ++ user_disable_single_step(task); + break; + } +} @@ -3323,7 +4112,8 @@ index 0000000..ef856c9 + * code path leads to calling into get_signal_to_deliver(), which + * implicitly reenables them by virtue of spin_unlock_irq. + */ -+ local_irq_enable(); ++ if (irqs_disabled()) /* make trace_hardirqs_on() happy */ ++ local_irq_enable(); + + /* + * If this flag is still set it's because there was a signal @@ -3499,7 +4289,7 @@ index 0000000..ef856c9 + ka = NULL; + memset(return_ka, 0, sizeof *return_ka); + } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || -+ unlikely(task->signal->group_stop_count)) { ++ unlikely(task->jobctl & JOBCTL_PENDING_MASK)) { + /* + * If no engine is interested in intercepting signals or + * we must stop, let the caller just dequeue them normally @@ -3902,3281 +4692,5 @@ index 0000000..ef856c9 + seq_printf(m, "Utrace:\t%lx\n", p->utrace_flags); +} -- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:17 2011 -Return-Path: oleg@redhat.com -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:17 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1CCED128D6B; - Mon, 21 Nov 2011 15:06:17 -0500 (EST) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id FWdJDV74o-ay; Mon, 21 Nov 2011 15:06:17 -0500 (EST) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 082081285E4; - Mon, 21 Nov 2011 15:06:17 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6E7d015251; - Mon, 21 Nov 2011 15:06:15 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:35 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:33 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 02/33] utrace: add utrace_init_task/utrace_free_task calls -Message-ID: <20111121200133.GA27759@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 -Status: RO -Content-Length: 1295 -Lines: 47 - -Add the necessary copy_process()->utrace_init_task() and -free_task()->utrace_free_task() calls. - -Originally this was the part of "utrace core" patch, but since -tracehooks are dying it doesn't make sense to reintroduce them. -Instead, just call the utrace_ helpers directly. This is fine -even without CONFIG_UTRACE, gcc is smart enough to optimize out -the code in free_task(). - -Signed-off-by: Oleg Nesterov ---- - kernel/fork.c | 5 +++++ - 1 files changed, 5 insertions(+), 0 deletions(-) - -diff --git a/kernel/fork.c b/kernel/fork.c -index ba0d172..b8719c2 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -66,6 +66,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -167,6 +168,8 @@ void free_task(struct task_struct *tsk) - free_thread_info(tsk->stack); - rt_mutex_debug_task_free(tsk); - ftrace_graph_exit_task(tsk); -+ if (task_utrace_struct(tsk)) -+ utrace_free_task(tsk); - free_task_struct(tsk); - } - EXPORT_SYMBOL(free_task); -@@ -1093,6 +1096,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, - if (!p) - goto fork_out; - -+ utrace_init_task(p); -+ - ftrace_graph_init_task(p); - - rt_mutex_init_task(p); --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:20 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:20 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8779AD87BC; - Mon, 21 Nov 2011 15:06:20 -0500 (EST) -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 umzAMwRd7rMt; Mon, 21 Nov 2011 15:06:20 -0500 (EST) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 72C98D8707; - Mon, 21 Nov 2011 15:06:20 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6HAj015261; - Mon, 21 Nov 2011 15:06:18 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:39 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:36 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 03/33] tracehooks: add utrace hooks -Message-ID: <20111121200136.GA27766@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 -Status: RO -Content-Length: 2310 -Lines: 75 - -Add the necessary utrace hooks in the tracehooks which were not -removed yet. - -Signed-off-by: Oleg Nesterov ---- - include/linux/tracehook.h | 22 +++++++++++++++++++++- - 1 files changed, 21 insertions(+), 1 deletions(-) - -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index a71a292..8cc28bc 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -49,6 +49,7 @@ - #include - #include - #include -+#include - struct linux_binprm; - - /* -@@ -96,6 +97,9 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) - static inline __must_check int tracehook_report_syscall_entry( - struct pt_regs *regs) - { -+ if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && -+ utrace_report_syscall_entry(regs)) -+ return 1; - ptrace_report_syscall(regs); - return 0; - } -@@ -119,6 +123,9 @@ static inline __must_check int tracehook_report_syscall_entry( - */ - static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) - { -+ if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) -+ utrace_report_syscall_exit(regs); -+ - if (step) { - siginfo_t info; - user_single_step_siginfo(current, regs, &info); -@@ -148,6 +155,8 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, - const struct k_sigaction *ka, - struct pt_regs *regs, int stepping) - { -+ if (task_utrace_flags(current)) -+ utrace_signal_handler(current, stepping); - if (stepping) - ptrace_notify(SIGTRAP); - } -@@ -179,10 +188,21 @@ static inline void set_notify_resume(struct task_struct *task) - * asynchronously, this will be called again before we return to - * user mode. - * -- * Called without locks. -+ * Called without locks. However, on some machines this may be -+ * called with interrupts disabled. - */ - static inline void tracehook_notify_resume(struct pt_regs *regs) - { -+ struct task_struct *task = current; -+ /* -+ * Prevent the following store/load from getting ahead of the -+ * caller which clears TIF_NOTIFY_RESUME. This pairs with the -+ * implicit mb() before setting TIF_NOTIFY_RESUME in -+ * set_notify_resume(). -+ */ -+ smp_mb(); -+ if (task_utrace_flags(task)) -+ utrace_resume(task, regs); - } - #endif /* TIF_NOTIFY_RESUME */ - --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:23 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:23 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6559BD4FDE; - Mon, 21 Nov 2011 15:06:23 -0500 (EST) -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 6BjISiO+cS1U; Mon, 21 Nov 2011 15:06:23 -0500 (EST) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 50366D4C39; - Mon, 21 Nov 2011 15:06:23 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6KT9017533; - Mon, 21 Nov 2011 15:06:21 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:42 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:39 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 04/33] tracehooks: reintroduce - tracehook_consider_fatal_signal() -Message-ID: <20111121200139.GA27769@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Status: RO -Content-Length: 3257 -Lines: 90 - -Add the killed tracehook_consider_fatal_signal() back. It has multiple -callers and it is not easy add the necessary checks inline. - -Signed-off-by: Oleg Nesterov ---- - arch/s390/kernel/traps.c | 4 ++-- - include/linux/tracehook.h | 22 ++++++++++++++++++++++ - kernel/signal.c | 4 ++-- - 3 files changed, 26 insertions(+), 4 deletions(-) - -diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c -index a9807dd..f506e1b 100644 ---- a/arch/s390/kernel/traps.c -+++ b/arch/s390/kernel/traps.c -@@ -329,7 +329,7 @@ void __kprobes do_per_trap(struct pt_regs *regs) - - if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) - return; -- if (!current->ptrace) -+ if (!tracehook_consider_fatal_signal(current, SIGTRAP)) - return; - info.si_signo = SIGTRAP; - info.si_errno = 0; -@@ -429,7 +429,7 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code, - if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) - return; - if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) { -- if (current->ptrace) { -+ if (tracehook_consider_fatal_signal(current, SIGTRAP)) { - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = TRAP_BRKPT; -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 8cc28bc..ec2af67 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -161,6 +161,28 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, - ptrace_notify(SIGTRAP); - } - -+/** -+ * tracehook_consider_fatal_signal - suppress special handling of fatal signal -+ * @task: task receiving the signal -+ * @sig: signal number being sent -+ * -+ * Return nonzero to prevent special handling of this termination signal. -+ * Normally handler for signal is %SIG_DFL. It can be %SIG_IGN if @sig is -+ * ignored, in which case force_sig() is about to reset it to %SIG_DFL. -+ * When this returns zero, this signal might cause a quick termination -+ * that does not give the debugger a chance to intercept the signal. -+ * -+ * Called with or without @task->sighand->siglock held. -+ */ -+static inline int tracehook_consider_fatal_signal(struct task_struct *task, -+ int sig) -+{ -+ if (unlikely(task_utrace_flags(task) & (UTRACE_EVENT(SIGNAL_TERM) | -+ UTRACE_EVENT(SIGNAL_CORE)))) -+ return 1; -+ return task->ptrace != 0; -+} -+ - #ifdef TIF_NOTIFY_RESUME - /** - * set_notify_resume - cause tracehook_notify_resume() to be called -diff --git a/kernel/signal.c b/kernel/signal.c -index b3f78d0..d7b90cd 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -494,7 +494,7 @@ int unhandled_signal(struct task_struct *tsk, int sig) - if (handler != SIG_IGN && handler != SIG_DFL) - return 0; - /* if ptraced, let the tracer determine */ -- return !tsk->ptrace; -+ return !tracehook_consider_fatal_signal(tsk, sig); - } - - /* -@@ -982,7 +982,7 @@ static void complete_signal(int sig, struct task_struct *p, int group) - if (sig_fatal(p, sig) && - !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) && - !sigismember(&t->real_blocked, sig) && -- (sig == SIGKILL || !t->ptrace)) { -+ (sig == SIGKILL || !tracehook_consider_fatal_signal(t, sig))) { - /* - * This signal will be fatal to the whole group. - */ --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:26 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:25 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E7A2DD498A; - Mon, 21 Nov 2011 15:06:25 -0500 (EST) -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 4L9zskFVsr4I; Mon, 21 Nov 2011 15:06:25 -0500 (EST) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D3487D4C39; - Mon, 21 Nov 2011 15:06:25 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6Nnp017552; - Mon, 21 Nov 2011 15:06:24 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:44 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:42 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 05/33] add utrace hooks into sig_ignored() and - recalc_sigpending() -Message-ID: <20111121200142.GA27777@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Status: RO -Content-Length: 1508 -Lines: 51 - -Add the necessary and somewhat "special" hooks into sig_ignored() and -recalc_sigpending(). Basically this restores _force_sigpending() and -_consider_ignored_signal() tracehook logic. - -Signed-off-by: Oleg Nesterov ---- - include/linux/utrace.h | 2 ++ - kernel/signal.c | 7 ++++++- - 2 files changed, 8 insertions(+), 1 deletions(-) - -diff --git a/include/linux/utrace.h b/include/linux/utrace.h -index f251efe..1b8da1c 100644 ---- a/include/linux/utrace.h -+++ b/include/linux/utrace.h -@@ -107,6 +107,8 @@ bool utrace_report_syscall_entry(struct pt_regs *); - void utrace_report_syscall_exit(struct pt_regs *); - void utrace_signal_handler(struct task_struct *, int); - -+#define UTRACE_FLAG(task, ev) (task_utrace_flags(task) & UTRACE_EVENT(ev)) -+ - #ifndef CONFIG_UTRACE - - /* -diff --git a/kernel/signal.c b/kernel/signal.c -index d7b90cd..8594cb2 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -87,7 +87,7 @@ static int sig_ignored(struct task_struct *t, int sig, int from_ancestor_ns) - /* - * Tracers may want to know about even ignored signals. - */ -- return !t->ptrace; -+ return !t->ptrace && !UTRACE_FLAG(t, SIGNAL_IGN); - } - - /* -@@ -150,6 +150,11 @@ void recalc_sigpending_and_wake(struct task_struct *t) - - void recalc_sigpending(void) - { -+ if (task_utrace_flags(current) && utrace_interrupt_pending()) { -+ set_thread_flag(TIF_SIGPENDING); -+ return; -+ } -+ - if (!recalc_sigpending_tsk(current) && !freezing(current)) - clear_thread_flag(TIF_SIGPENDING); - --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:28 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:28 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6E4A6D4F4A; - Mon, 21 Nov 2011 15:06:28 -0500 (EST) -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 vEeGLyK1+rX9; Mon, 21 Nov 2011 15:06:28 -0500 (EST) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5AD50D4C39; - Mon, 21 Nov 2011 15:06:28 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6QOB029543; - Mon, 21 Nov 2011 15:06:26 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:47 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:45 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 06/33] restore the EXEC/EXIT/CLONE utrace hooks -Message-ID: <20111121200145.GA27780@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Status: RO -Content-Length: 2383 -Lines: 83 - -Restore the "trivial" EXEC/EXIT/CLONE utrace hooks. Add the -simple helper, UTRACE_HOOK(), to minimize the changes. - -Signed-off-by: Oleg Nesterov ---- - fs/exec.c | 5 ++++- - include/linux/utrace.h | 6 ++++++ - kernel/exit.c | 1 + - kernel/fork.c | 4 ++++ - 4 files changed, 15 insertions(+), 1 deletions(-) - -diff --git a/fs/exec.c b/fs/exec.c -index 3625464..7d8f8bd 100644 ---- a/fs/exec.c -+++ b/fs/exec.c -@@ -1397,9 +1397,12 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) - */ - bprm->recursion_depth = depth; - if (retval >= 0) { -- if (depth == 0) -+ if (depth == 0) { -+ UTRACE_HOOK(current, EXEC, -+ report_exec(fmt, bprm, regs)); - ptrace_event(PTRACE_EVENT_EXEC, - old_pid); -+ } - put_binfmt(fmt); - allow_write_access(bprm->file); - if (bprm->file) -diff --git a/include/linux/utrace.h b/include/linux/utrace.h -index 1b8da1c..9ac0b1b 100644 ---- a/include/linux/utrace.h -+++ b/include/linux/utrace.h -@@ -109,6 +109,12 @@ void utrace_signal_handler(struct task_struct *, int); - - #define UTRACE_FLAG(task, ev) (task_utrace_flags(task) & UTRACE_EVENT(ev)) - -+#define UTRACE_HOOK(task, ev, callback) \ -+ do { \ -+ if (UTRACE_FLAG(task, ev)) \ -+ utrace_ ## callback; \ -+ } while (0) -+ - #ifndef CONFIG_UTRACE - - /* -diff --git a/kernel/exit.c b/kernel/exit.c -index d0b7d98..f5eba3b 100644 ---- a/kernel/exit.c -+++ b/kernel/exit.c -@@ -911,6 +911,7 @@ NORET_TYPE void do_exit(long code) - */ - set_fs(USER_DS); - -+ UTRACE_HOOK(current, EXIT, report_exit(&code)); - ptrace_event(PTRACE_EVENT_EXIT, code); - - validate_creds_for_do_exit(tsk); -diff --git a/kernel/fork.c b/kernel/fork.c -index b8719c2..09d5049 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -1535,6 +1535,8 @@ long do_fork(unsigned long clone_flags, - - audit_finish_fork(p); - -+ UTRACE_HOOK(current, CLONE, report_clone(clone_flags, p)); -+ - /* - * We set PF_STARTING at creation in case tracing wants to - * use this to distinguish a fully live task from one that -@@ -1546,6 +1548,8 @@ long do_fork(unsigned long clone_flags, - wake_up_new_task(p); - - /* forking complete and child started to run, tell ptracer */ -+ if (clone_flags & CLONE_VFORK) -+ UTRACE_HOOK(current, CLONE, finish_vfork(current)); - if (unlikely(trace)) - ptrace_event(trace, nr); - --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:30 2011 -Return-Path: oleg@redhat.com -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:30 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D248D1284E0; - Mon, 21 Nov 2011 15:06:30 -0500 (EST) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id divvekTmLScS; Mon, 21 Nov 2011 15:06:30 -0500 (EST) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BDC9412800E; - Mon, 21 Nov 2011 15:06:30 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6Shj029546; - Mon, 21 Nov 2011 15:06:29 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:49 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:47 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 07/33] utrace: utrace_report_death() can use - task_utrace_struct() -Message-ID: <20111121200147.GA27787@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Status: RO -Content-Length: 1692 -Lines: 44 - -utrace_report_death() assumes that the caller (exit_notify) should -pass task->utrace as an argument. This is no longer needed, it can -safely do task_utrace_struct(). This way we avoid the nasty changes -in exit_notify(). - -Signed-off-by: Oleg Nesterov ---- - include/linux/utrace.h | 2 +- - kernel/utrace.c | 5 +++-- - 2 files changed, 4 insertions(+), 3 deletions(-) - -diff --git a/include/linux/utrace.h b/include/linux/utrace.h -index 9ac0b1b..9a2e2f4 100644 ---- a/include/linux/utrace.h -+++ b/include/linux/utrace.h -@@ -99,7 +99,7 @@ int utrace_get_signal(struct task_struct *, struct pt_regs *, - void utrace_report_clone(unsigned long, struct task_struct *); - void utrace_finish_vfork(struct task_struct *); - void utrace_report_exit(long *exit_code); --void utrace_report_death(struct task_struct *, struct utrace *, bool, int); -+void utrace_report_death(struct task_struct *, bool, int); - void utrace_report_jctl(int notify, int type); - void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *, - struct pt_regs *regs); -diff --git a/kernel/utrace.c b/kernel/utrace.c -index ef856c9..1e750ad 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -1759,9 +1759,10 @@ void utrace_report_exit(long *exit_code) - * For this reason, utrace_release_task checks for the event bits that get - * us here, and delays its cleanup for us to do. - */ --void utrace_report_death(struct task_struct *task, struct utrace *utrace, -- bool group_dead, int signal) -+void utrace_report_death(struct task_struct *task, bool group_dead, int signal) - { -+ struct utrace *utrace = task_utrace_struct(task); -+ - INIT_REPORT(report); - - BUG_ON(!task->exit_state); --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:33 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:33 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 62E1BD50A3; - Mon, 21 Nov 2011 15:06:33 -0500 (EST) -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 FB36YkOAHDc5; Mon, 21 Nov 2011 15:06:33 -0500 (EST) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4D161D4C39; - Mon, 21 Nov 2011 15:06:33 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6VBW022130; - Mon, 21 Nov 2011 15:06:31 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:52 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:50 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 08/33] restore the DEATH/REAP utrace hooks -Message-ID: <20111121200150.GA27790@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Status: RO -Content-Length: 2346 -Lines: 70 - -Restore the necessary hooks in release_task() and exit_notify(), -add the corresponding helpers into utrace.h. - -Note: the @signal argument passed to ->report_death() does not -match the previous behaviour. I think this shouldn't affect the -current users, and I bet nobody can really understand what this -magic argument should actually mean anyway. - -Signed-off-by: Oleg Nesterov ---- - include/linux/utrace.h | 22 ++++++++++++++++++++++ - kernel/exit.c | 4 ++++ - 2 files changed, 26 insertions(+), 0 deletions(-) - -diff --git a/include/linux/utrace.h b/include/linux/utrace.h -index 9a2e2f4..cf13839 100644 ---- a/include/linux/utrace.h -+++ b/include/linux/utrace.h -@@ -697,4 +697,26 @@ static inline __must_check int utrace_barrier_pid(struct pid *pid, - - #endif /* CONFIG_UTRACE */ - -+static inline void utrace_release_task(struct task_struct *task) -+{ -+ /* see utrace_add_engine() about this barrier */ -+ smp_mb(); -+ if (task_utrace_flags(task)) -+ utrace_maybe_reap(task, task_utrace_struct(task), true); -+} -+ -+static inline void utrace_exit_notify(struct task_struct *task, -+ int signal, int group_dead) -+{ -+ /* -+ * If utrace_set_events() was just called to enable -+ * UTRACE_EVENT(DEATH), then we are obliged to call -+ * utrace_report_death() and not miss it. utrace_set_events() -+ * checks @task->exit_state under tasklist_lock to synchronize -+ * with exit_notify(), the caller. -+ */ -+ if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) -+ utrace_report_death(task, group_dead, signal); -+} -+ - #endif /* linux/utrace.h */ -diff --git a/kernel/exit.c b/kernel/exit.c -index f5eba3b..746c5df 100644 ---- a/kernel/exit.c -+++ b/kernel/exit.c -@@ -168,6 +168,8 @@ void release_task(struct task_struct * p) - struct task_struct *leader; - int zap_leader; - repeat: -+ utrace_release_task(p); -+ - /* don't need to get the RCU readlock here - the process is dead and - * can't be modifying its own credentials. But shut RCU-lockdep up */ - rcu_read_lock(); -@@ -858,6 +860,8 @@ static void exit_notify(struct task_struct *tsk, int group_dead) - wake_up_process(tsk->signal->group_exit_task); - write_unlock_irq(&tasklist_lock); - -+ utrace_exit_notify(tsk, autoreap ? -1 : SIGCHLD, group_dead); -+ - /* If the process is dead, release it - nobody will wait for it */ - if (autoreap) - release_task(tsk); --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:35 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:35 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D4AB3D8761; - Mon, 21 Nov 2011 15:06:35 -0500 (EST) -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 TiShkH1f6rnj; Mon, 21 Nov 2011 15:06:35 -0500 (EST) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BCB85D877F; - Mon, 21 Nov 2011 15:06:35 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6XNu015312; - Mon, 21 Nov 2011 15:06:34 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:54 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:52 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 09/33] utrace: remove jobctl bits -Message-ID: <20111121200152.GA27793@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 -Status: RO -Content-Length: 1888 -Lines: 56 - -- change utrace_get_signal() to check JOBCTL_STOP_PENDING instead of - signal->group_stop_count. With the recent changes group_stop_count - doesn't necessarily mean this task should participate in group stop. - -- remove the "participate in group stop" code from utrace_wakeup() and - utrace_stop(), this is no longer needed and wrong. - -Signed-off-by: Oleg Nesterov ---- - kernel/utrace.c | 16 ++-------------- - 1 files changed, 2 insertions(+), 14 deletions(-) - -diff --git a/kernel/utrace.c b/kernel/utrace.c -index 1e750ad..5d3974e 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -648,11 +648,7 @@ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) - { - lockdep_assert_held(&utrace->lock); - spin_lock_irq(&target->sighand->siglock); -- if (target->signal->flags & SIGNAL_STOP_STOPPED || -- target->signal->group_stop_count) -- target->state = TASK_STOPPED; -- else -- wake_up_state(target, __TASK_TRACED); -+ wake_up_state(target, __TASK_TRACED); - spin_unlock_irq(&target->sighand->siglock); - } - -@@ -805,14 +801,6 @@ relock: - - __set_current_state(TASK_TRACED); - -- /* -- * If there is a group stop in progress, -- * we must participate in the bookkeeping. -- */ -- if (unlikely(task->signal->group_stop_count) && -- !--task->signal->group_stop_count) -- task->signal->flags = SIGNAL_STOP_STOPPED; -- - spin_unlock_irq(&task->sighand->siglock); - spin_unlock(&utrace->lock); - -@@ -2037,7 +2025,7 @@ int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, - ka = NULL; - memset(return_ka, 0, sizeof *return_ka); - } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || -- unlikely(task->signal->group_stop_count)) { -+ unlikely(task->jobctl & JOBCTL_STOP_PENDING)) { - /* - * If no engine is interested in intercepting signals or - * we must stop, let the caller just dequeue them normally --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:38 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:38 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 425CED8707; - Mon, 21 Nov 2011 15:06:38 -0500 (EST) -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 9paRC+dwSflh; Mon, 21 Nov 2011 15:06:38 -0500 (EST) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2DDBCD8410; - Mon, 21 Nov 2011 15:06:38 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6a31031355; - Mon, 21 Nov 2011 15:06:36 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:56 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:55 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 10/33] ptrace: take ->siglock around s/TRACED/RUNNING/ -Message-ID: <20111121200155.GA27801@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 -Status: RO -Content-Length: 1624 -Lines: 56 - -change ptrace_resume() and ptrace_stop() to take ->siglock around changing -task->state from TRACED to RUNNING. - -With this patch __TASK_TRACED/STOPPED bits are fully protected by ->siglock, -nobody can set or clear these bits without ->siglock held. - -Signed-off-by: Oleg Nesterov ---- - kernel/ptrace.c | 8 +++++++- - kernel/signal.c | 3 +++ - 2 files changed, 10 insertions(+), 1 deletions(-) - -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 24d0447..daf47bc 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -589,6 +589,8 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info) - static int ptrace_resume(struct task_struct *child, long request, - unsigned long data) - { -+ unsigned long flags; -+ - if (!valid_signal(data)) - return -EIO; - -@@ -617,7 +619,11 @@ static int ptrace_resume(struct task_struct *child, long request, - } - - child->exit_code = data; -- wake_up_state(child, __TASK_TRACED); -+ -+ if (lock_task_sighand(child, &flags)) { -+ wake_up_state(child, __TASK_TRACED); -+ unlock_task_sighand(child, &flags); -+ } - - return 0; - } -diff --git a/kernel/signal.c b/kernel/signal.c -index 8594cb2..4512bb4 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -1886,7 +1886,10 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) - if (gstop_done) - do_notify_parent_cldstop(current, false, why); - -+ spin_lock_irq(¤t->sighand->siglock); - __set_current_state(TASK_RUNNING); -+ spin_unlock_irq(¤t->sighand->siglock); -+ - if (clear_code) - current->exit_code = 0; - read_unlock(&tasklist_lock); --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:40 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:40 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B0D19D877F; - Mon, 21 Nov 2011 15:06:40 -0500 (EST) -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 3jv-cDBpMP5B; Mon, 21 Nov 2011 15:06:40 -0500 (EST) -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 9C98DD8410; - Mon, 21 Nov 2011 15:06:40 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6cHF029573; - Mon, 21 Nov 2011 15:06:39 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:59 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:57 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 11/33] introduce wake_up_quiescent() -Message-ID: <20111121200157.GA27805@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Status: RO -Content-Length: 3186 -Lines: 93 - -No functional changes. Add the new helper, wake_up_quiescent(task, state), -which simply returns wake_up_state(task, state). Change all callers which -do wake_up_state(STOPPED/TRACED) to use the new helper. ptrace_stop() is -a bit special, it does __set_current_state(RUNNING) in the very unlikely -case, change it as well. - -Signed-off-by: Oleg Nesterov ---- - include/linux/signal.h | 2 ++ - kernel/ptrace.c | 2 +- - kernel/signal.c | 12 ++++++++++-- - kernel/utrace.c | 2 +- - 4 files changed, 14 insertions(+), 4 deletions(-) - -diff --git a/include/linux/signal.h b/include/linux/signal.h -index a822300..2be3712 100644 ---- a/include/linux/signal.h -+++ b/include/linux/signal.h -@@ -239,6 +239,8 @@ static inline int valid_signal(unsigned long sig) - struct timespec; - struct pt_regs; - -+extern int wake_up_quiescent(struct task_struct *p, unsigned int state); -+ - extern int next_signal(struct sigpending *pending, sigset_t *mask); - extern int do_send_sig_info(int sig, struct siginfo *info, - struct task_struct *p, bool group); -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index daf47bc..8439ef1 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -621,7 +621,7 @@ static int ptrace_resume(struct task_struct *child, long request, - child->exit_code = data; - - if (lock_task_sighand(child, &flags)) { -- wake_up_state(child, __TASK_TRACED); -+ wake_up_quiescent(child, __TASK_TRACED); - unlock_task_sighand(child, &flags); - } - -diff --git a/kernel/signal.c b/kernel/signal.c -index 4512bb4..99a6008 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -702,6 +702,14 @@ void signal_wake_up(struct task_struct *t, int resume) - } - - /* -+ * wakes up the STOPPED/TRACED task, must be called with ->siglock held. -+ */ -+int wake_up_quiescent(struct task_struct *p, unsigned int state) -+{ -+ return wake_up_state(p, state); -+} -+ -+/* - * Remove signals in mask from the pending set and queue. - * Returns 1 if any signals were found. - * -@@ -888,7 +896,7 @@ static int prepare_signal(int sig, struct task_struct *p, int from_ancestor_ns) - task_clear_jobctl_pending(t, JOBCTL_STOP_PENDING); - rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending); - if (likely(!(t->ptrace & PT_SEIZED))) -- wake_up_state(t, __TASK_STOPPED); -+ wake_up_quiescent(t, __TASK_STOPPED); - else - ptrace_trap_notify(t); - } while_each_thread(p, t); -@@ -1887,7 +1895,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) - do_notify_parent_cldstop(current, false, why); - - spin_lock_irq(¤t->sighand->siglock); -- __set_current_state(TASK_RUNNING); -+ wake_up_quiescent(current, __TASK_TRACED); - spin_unlock_irq(¤t->sighand->siglock); - - if (clear_code) -diff --git a/kernel/utrace.c b/kernel/utrace.c -index 5d3974e..cebc390 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -648,7 +648,7 @@ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) - { - lockdep_assert_held(&utrace->lock); - spin_lock_irq(&target->sighand->siglock); -- wake_up_state(target, __TASK_TRACED); -+ wake_up_quiescent(target, __TASK_TRACED); - spin_unlock_irq(&target->sighand->siglock); - } - --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:43 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:43 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6488BD514C; - Mon, 21 Nov 2011 15:06:43 -0500 (EST) -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 TKQUj5mU4NYM; Mon, 21 Nov 2011 15:06:43 -0500 (EST) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4EC82D5000; - Mon, 21 Nov 2011 15:06:43 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6fp6015343; - Mon, 21 Nov 2011 15:06:41 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:02 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:59 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 12/33] introduce ptrace_signal_wake_up() -Message-ID: <20111121200159.GA27812@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 -Status: RO -Content-Length: 3670 -Lines: 113 - -Add the new helper, ptrace_signal_wake_up(), change ptrace.c/signal.c -to use it instead of signal_wake_up() to wake up a STOPPED/TRACED task. - -The new helper does almost the same, except: - - - it doesn't use the TASK_WAKEKILL bit to wake up the TRACED - or STOPPED task, it uses __TASK_STOPPED | __TASK_TRACED - explicitly. This is what ptrace actually wants, it should - never wake up a TASK_KILLABLE task. - - This should be cleanuped upatream, signal_wake_up() should - take the state as an argument, not a boolean. Until then - we add a new static helper. - - - it uses wake_up_quiescent() instead of wake_up_state(). - -Thereafter every change from STOPPED/TRACED to RUNNING is done via -wake_up_quiescent(). - -Signed-off-by: Oleg Nesterov ---- - include/linux/ptrace.h | 1 + - kernel/ptrace.c | 20 ++++++++++++++++---- - kernel/signal.c | 2 +- - 3 files changed, 18 insertions(+), 5 deletions(-) - -diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h -index 800f113..6d9282a 100644 ---- a/include/linux/ptrace.h -+++ b/include/linux/ptrace.h -@@ -113,6 +113,7 @@ - #include /* For unlikely. */ - #include /* For struct task_struct. */ - -+extern void ptrace_signal_wake_up(struct task_struct *p, int quiescent); - - extern long arch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data); -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 8439ef1..a464ab5 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -25,6 +25,18 @@ - #include - #include - -+void ptrace_signal_wake_up(struct task_struct *p, int quiescent) -+{ -+ unsigned int state; -+ -+ set_tsk_thread_flag(p, TIF_SIGPENDING); -+ -+ state = TASK_INTERRUPTIBLE; -+ if (quiescent) -+ state |= (__TASK_STOPPED | __TASK_TRACED); -+ if (!wake_up_quiescent(p, state)) -+ kick_process(p); -+} - - static int ptrace_trapping_sleep_fn(void *flags) - { -@@ -106,7 +118,7 @@ void __ptrace_unlink(struct task_struct *child) - * TASK_KILLABLE sleeps. - */ - if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child)) -- signal_wake_up(child, task_is_traced(child)); -+ ptrace_signal_wake_up(child, task_is_traced(child)); - - spin_unlock(&child->sighand->siglock); - } -@@ -296,7 +308,7 @@ static int ptrace_attach(struct task_struct *task, long request, - */ - if (task_is_stopped(task) && - task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING)) -- signal_wake_up(task, 1); -+ ptrace_signal_wake_up(task, 1); - - spin_unlock(&task->sighand->siglock); - -@@ -731,7 +743,7 @@ int ptrace_request(struct task_struct *child, long request, - * tracee into STOP. - */ - if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP))) -- signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); -+ ptrace_signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); - - unlock_task_sighand(child, &flags); - ret = 0; -@@ -757,7 +769,7 @@ int ptrace_request(struct task_struct *child, long request, - * start of this trap and now. Trigger re-trap. - */ - if (child->jobctl & JOBCTL_TRAP_NOTIFY) -- signal_wake_up(child, true); -+ ptrace_signal_wake_up(child, true); - ret = 0; - } - unlock_task_sighand(child, &flags); -diff --git a/kernel/signal.c b/kernel/signal.c -index 99a6008..7a47a93 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -854,7 +854,7 @@ static void ptrace_trap_notify(struct task_struct *t) - assert_spin_locked(&t->sighand->siglock); - - task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY); -- signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); -+ ptrace_signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); - } - - /* --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:46 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:46 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 3A7AED8410; - Mon, 21 Nov 2011 15:06:46 -0500 (EST) -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 jhYAwDyYmdhg; Mon, 21 Nov 2011 15:06:46 -0500 (EST) -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 25D5FD889A; - Mon, 21 Nov 2011 15:06:46 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6h29029619; - Mon, 21 Nov 2011 15:06:44 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:04 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:02 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 13/33] wait_task_inactive: treat task->state and - match_state as bitmasks -Message-ID: <20111121200202.GA27816@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Status: RO -Content-Length: 1558 -Lines: 39 - -Change wait_task_inactive() to check "state & match_state" instead of -"state == match_state". This should not make any difference, but this -allows us to add more "stopped" bits which can be set or cleared -independently. - -IOW. wait_task_inactive() assumes that if task->state != 0, it can -only be changed to TASK_RUNNING. Currently this is true, and in this -case "state & match_state" continues to work. But, unlike the current -check, it also works if task->state has other bits set while the caller -is only interested in, say, __TASK_TRACED. - -Note: I think wait_task_inactive() should be cleanuped upstrean anyway, -nowadays we have TASK_WAKING and task->state != 0 doesn't necessarily -mean it is TASK_RUNNING. It also makes sense to exclude the !TASK_REPORT -bits during the check. Finally, probably this patch makes sense anyway -even without utrace. For example, a stopped _and_ traced thread could -have task->state = TASK_STOPPED | TASK_TRACED, this can be useful. - -Signed-off-by: Oleg Nesterov ---- - kernel/sched.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/kernel/sched.c b/kernel/sched.c -index 0e9344a..84ecc0a 100644 ---- a/kernel/sched.c -+++ b/kernel/sched.c -@@ -2443,7 +2443,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) - * is actually now running somewhere else! - */ - while (task_running(rq, p)) { -- if (match_state && unlikely(p->state != match_state)) -+ if (match_state && !likely(p->state & match_state)) - return 0; - cpu_relax(); - } --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:48 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:48 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C2934D5000; - Mon, 21 Nov 2011 15:06:48 -0500 (EST) -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 ThT2PyhztDpQ; Mon, 21 Nov 2011 15:06:48 -0500 (EST) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id ACE02D4F84; - Mon, 21 Nov 2011 15:06:48 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6kdb022201; - Mon, 21 Nov 2011 15:06:47 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:07 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:05 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 14/33] introduce TASK_UTRACED state -Message-ID: <20111121200205.GA27823@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Status: RO -Content-Length: 2913 -Lines: 84 - -Introduce TASK_UTRACED state, will be used by utrace instead of TASK_TRACED. - -Note: this state is reported as "t (tracing stop)" to the user-space to -avoid the confusion. IOW, it looks like TASK_TRACED in /proc/pid/status. - -Signed-off-by: Oleg Nesterov ---- - fs/proc/array.c | 11 ++++++----- - include/linux/sched.h | 20 +++++++++++--------- - 2 files changed, 17 insertions(+), 14 deletions(-) - -diff --git a/fs/proc/array.c b/fs/proc/array.c -index f0c0ea2..e0daec4 100644 ---- a/fs/proc/array.c -+++ b/fs/proc/array.c -@@ -138,11 +138,12 @@ static const char * const task_state_array[] = { - "D (disk sleep)", /* 2 */ - "T (stopped)", /* 4 */ - "t (tracing stop)", /* 8 */ -- "Z (zombie)", /* 16 */ -- "X (dead)", /* 32 */ -- "x (dead)", /* 64 */ -- "K (wakekill)", /* 128 */ -- "W (waking)", /* 256 */ -+ "t (tracing stop)", /* 16 (stopped by utrace) */ -+ "Z (zombie)", /* 32 */ -+ "X (dead)", /* 64 */ -+ "x (dead)", /* 128 */ -+ "K (wakekill)", /* 256 */ -+ "W (waking)", /* 512 */ - }; - - static inline const char *get_task_state(struct task_struct *tsk) -diff --git a/include/linux/sched.h b/include/linux/sched.h -index 4d45f93..746b4d3 100644 ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -185,16 +185,17 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) - #define TASK_UNINTERRUPTIBLE 2 - #define __TASK_STOPPED 4 - #define __TASK_TRACED 8 -+#define __TASK_UTRACED 16 - /* in tsk->exit_state */ --#define EXIT_ZOMBIE 16 --#define EXIT_DEAD 32 -+#define EXIT_ZOMBIE 32 -+#define EXIT_DEAD 64 - /* in tsk->state again */ --#define TASK_DEAD 64 --#define TASK_WAKEKILL 128 --#define TASK_WAKING 256 --#define TASK_STATE_MAX 512 -+#define TASK_DEAD 128 -+#define TASK_WAKEKILL 256 -+#define TASK_WAKING 512 -+#define TASK_STATE_MAX 1024 - --#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKW" -+#define TASK_STATE_TO_CHAR_STR "RSDTtUZXxKW" - - extern char ___assert_task_state[1 - 2*!!( - sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1)]; -@@ -203,15 +204,16 @@ extern char ___assert_task_state[1 - 2*!!( - #define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE) - #define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED) - #define TASK_TRACED (TASK_WAKEKILL | __TASK_TRACED) -+#define TASK_UTRACED (TASK_WAKEKILL | __TASK_UTRACED) - - /* Convenience macros for the sake of wake_up */ - #define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE) --#define TASK_ALL (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED) -+#define TASK_ALL (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED | __TASK_UTRACED) - - /* get_task_state() */ - #define TASK_REPORT (TASK_RUNNING | TASK_INTERRUPTIBLE | \ - TASK_UNINTERRUPTIBLE | __TASK_STOPPED | \ -- __TASK_TRACED) -+ __TASK_TRACED | __TASK_UTRACED) - - #define task_is_traced(task) ((task->state & __TASK_TRACED) != 0) - #define task_is_stopped(task) ((task->state & __TASK_STOPPED) != 0) --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:51 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:51 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 48F35D889C; - Mon, 21 Nov 2011 15:06:51 -0500 (EST) -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 ZXkDvXaDg0cN; Mon, 21 Nov 2011 15:06:51 -0500 (EST) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 34485D889A; - Mon, 21 Nov 2011 15:06:51 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6nlT022211; - Mon, 21 Nov 2011 15:06:49 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:09 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:08 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 15/33] utrace: use TASK_UTRACED instead of TASK_TRACED -Message-ID: <20111121200208.GA27826@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Status: RO -Content-Length: 4316 -Lines: 130 - -Change utrace.c to use TASK_UTRACED instead of TASK_TRACED. - -- utrace_stop/utrace_wakeup: simply use the new state - -- utrace_do_stop: do not clear STOPPED/TRACED, but add the new - __TASK_UTRACED bit to state the fact that both ptrace and utrace - want this task to be stopped - -- naturally, do not use task_is_traced() to check if this task was - stopped by utrace, use the new task_is_utraced() helper which - checks __TASK_UTRACED. - -Signed-off-by: Oleg Nesterov ---- - kernel/utrace.c | 26 ++++++++++++++------------ - 1 files changed, 14 insertions(+), 12 deletions(-) - -diff --git a/kernel/utrace.c b/kernel/utrace.c -index cebc390..2097103 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -462,6 +462,8 @@ static void put_detached_list(struct list_head *list) - */ - #define ENGINE_STOP (1UL << _UTRACE_NEVENTS) - -+#define task_is_utraced(task) ((task->state & __TASK_UTRACED) != 0) -+ - static void mark_engine_wants_stop(struct task_struct *task, - struct utrace_engine *engine) - { -@@ -576,7 +578,7 @@ int utrace_set_events(struct task_struct *target, - - ret = 0; - if ((old_flags & ~events) && target != current && -- !task_is_stopped_or_traced(target) && !target->exit_state) { -+ !task_is_utraced(target) && !target->exit_state) { - /* - * This barrier ensures that our engine->flags changes - * have hit before we examine utrace->reporting, -@@ -623,21 +625,21 @@ static void mark_engine_detached(struct utrace_engine *engine) - */ - static bool utrace_do_stop(struct task_struct *target, struct utrace *utrace) - { -- if (task_is_stopped(target)) { -+ if (task_is_stopped_or_traced(target)) { - /* - * Stopped is considered quiescent; when it wakes up, it will - * go through utrace_finish_stop() before doing anything else. - */ - spin_lock_irq(&target->sighand->siglock); -- if (likely(task_is_stopped(target))) -- __set_task_state(target, TASK_TRACED); -+ if (likely(task_is_stopped_or_traced(target))) -+ target->state |= TASK_UTRACED; - spin_unlock_irq(&target->sighand->siglock); - } else if (utrace->resume > UTRACE_REPORT) { - utrace->resume = UTRACE_REPORT; - set_notify_resume(target); - } - -- return task_is_traced(target); -+ return task_is_utraced(target); - } - - /* -@@ -648,7 +650,7 @@ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) - { - lockdep_assert_held(&utrace->lock); - spin_lock_irq(&target->sighand->siglock); -- wake_up_quiescent(target, __TASK_TRACED); -+ wake_up_quiescent(target, __TASK_UTRACED); - spin_unlock_irq(&target->sighand->siglock); - } - -@@ -710,7 +712,7 @@ static bool utrace_reset(struct task_struct *task, struct utrace *utrace) - /* - * If no more engines want it stopped, wake it up. - */ -- if (task_is_traced(task) && !(flags & ENGINE_STOP)) { -+ if (task_is_utraced(task) && !(flags & ENGINE_STOP)) { - /* - * It just resumes, so make sure single-step - * is not left set. -@@ -749,7 +751,7 @@ void utrace_finish_stop(void) - } - - /* -- * Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up. -+ * Perform %UTRACE_STOP, i.e. block in TASK_UTRACED until woken up. - * @task == current, @utrace == current->utrace, which is not locked. - * Return true if we were woken up by SIGKILL even though some utrace - * engine may still want us to stay stopped. -@@ -799,7 +801,7 @@ relock: - return; - } - -- __set_current_state(TASK_TRACED); -+ __set_current_state(TASK_UTRACED); - - spin_unlock_irq(&task->sighand->siglock); - spin_unlock(&utrace->lock); -@@ -809,14 +811,14 @@ relock: - utrace_finish_stop(); - - /* -- * While in TASK_TRACED, we were considered "frozen enough". -+ * While in TASK_UTRACED, we were considered "frozen enough". - * Now that we woke up, it's crucial if we're supposed to be - * frozen that we freeze now before running anything substantial. - */ - try_to_freeze(); - - /* -- * While we were in TASK_TRACED, complete_signal() considered -+ * While we were in TASK_UTRACED, complete_signal() considered - * us "uninterested" in signal wakeups. Now make sure our - * TIF_SIGPENDING state is correct for normal running. - */ -@@ -1087,7 +1089,7 @@ int utrace_control(struct task_struct *target, - if (unlikely(IS_ERR(utrace))) - return PTR_ERR(utrace); - -- reset = task_is_traced(target); -+ reset = task_is_utraced(target); - ret = 0; - - /* --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:53 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:53 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B8F54D5296; - Mon, 21 Nov 2011 15:06:53 -0500 (EST) -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 PX4Y3H1mw0hD; Mon, 21 Nov 2011 15:06:53 -0500 (EST) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A4B5CD528E; - Mon, 21 Nov 2011 15:06:53 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6pXd029643; - Mon, 21 Nov 2011 15:06:52 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:12 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:10 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 16/33] reintroduce tracehook_finish_jctl() as - utrace_end_stop() -Message-ID: <20111121200210.GA27829@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Status: RO -Content-Length: 2401 -Lines: 77 - -utrace_finish_stop() is needed to avoid the races with SIGKILL which -wakes up UTRACED task, and thus it should be called every time after -the STOPPED/TRACED/UTRACED returns from schedule(), remember that -TASK_UTRACED can be added while the task is STOPPED/UTRACED. - -- change do_signal_state() to call this helper right after schedule(), - otherwise this logic is broken by the upstream changes - -- now that utrace doesn't control TASK_TRACED bit, ptrace_stop() must - call this helper too. - -Signed-off-by: Oleg Nesterov ---- - include/linux/utrace.h | 11 +++++++++++ - kernel/signal.c | 5 +++++ - kernel/utrace.c | 2 +- - 3 files changed, 17 insertions(+), 1 deletions(-) - -diff --git a/include/linux/utrace.h b/include/linux/utrace.h -index cf13839..0279c74 100644 ---- a/include/linux/utrace.h -+++ b/include/linux/utrace.h -@@ -719,4 +719,15 @@ static inline void utrace_exit_notify(struct task_struct *task, - utrace_report_death(task, group_dead, signal); - } - -+/** -+ * utrace_end_stop - report about return from STOPPED/TRACED -+ * -+ * This is called by do_signal_stop() and ptrace_stop after wakeup. -+ */ -+static inline void utrace_end_stop(void) -+{ -+ if (task_utrace_flags(current)) -+ utrace_finish_stop(); -+} -+ - #endif /* linux/utrace.h */ -diff --git a/kernel/signal.c b/kernel/signal.c -index 7a47a93..ba46eab 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -1903,6 +1903,8 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) - read_unlock(&tasklist_lock); - } - -+ utrace_end_stop(); -+ - /* - * While in TASK_TRACED, we were considered "frozen enough". - * Now that we woke up, it's crucial if we're supposed to be -@@ -2067,6 +2069,9 @@ static bool do_signal_stop(int signr) - - /* Now we don't run again until woken by SIGCONT or SIGKILL */ - schedule(); -+ -+ utrace_end_stop(); -+ - return true; - } else { - /* -diff --git a/kernel/utrace.c b/kernel/utrace.c -index 2097103..d41b982 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -741,7 +741,7 @@ static bool utrace_reset(struct task_struct *task, struct utrace *utrace) - void utrace_finish_stop(void) - { - /* -- * If we were task_is_traced() and then SIGKILL'ed, make -+ * If we were task_is_utraced() and then SIGKILL'ed, make - * sure we do nothing until the tracer drops utrace->lock. - */ - if (unlikely(__fatal_signal_pending(current))) { --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:56 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:56 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4A487D83A1; - Mon, 21 Nov 2011 15:06:56 -0500 (EST) -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 3vHogPyhojlJ; Mon, 21 Nov 2011 15:06:56 -0500 (EST) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 358A0D88B0; - Mon, 21 Nov 2011 15:06:56 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6sHk017679; - Mon, 21 Nov 2011 15:06:54 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:14 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:12 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 17/33] teach wake_up_quiescent() to do "selective" wake_up -Message-ID: <20111121200212.GA27836@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Status: RO -Content-Length: 1335 -Lines: 46 - -Both utrace and ptrace can want the same thread to be quiescent, in this -case its state is TASK_TRACED | TASK_UTRACED. And this also means that -this task must not run unless both utrace and ptrace resume it. - -Change wake_up_quiescent(p, state) to do "p->state &= ~state" and return -false unless there is no more "quiescent" bits in task->state. - -Signed-off-by: Oleg Nesterov ---- - kernel/signal.c | 15 +++++++++++++++ - 1 files changed, 15 insertions(+), 0 deletions(-) - -diff --git a/kernel/signal.c b/kernel/signal.c -index ba46eab..e06f795 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -701,11 +701,26 @@ void signal_wake_up(struct task_struct *t, int resume) - kick_process(t); - } - -+#define STATE_QUIESCENT (__TASK_STOPPED | __TASK_TRACED | __TASK_UTRACED) - /* - * wakes up the STOPPED/TRACED task, must be called with ->siglock held. - */ - int wake_up_quiescent(struct task_struct *p, unsigned int state) - { -+ unsigned int quiescent = (p->state & STATE_QUIESCENT); -+ -+ WARN_ON(state & ~(STATE_QUIESCENT | TASK_INTERRUPTIBLE)); -+ -+ if (quiescent) { -+ state &= ~TASK_INTERRUPTIBLE; -+ if ((quiescent & ~state) != 0) { -+ p->state &= ~state; -+ WARN_ON(!(p->state & STATE_QUIESCENT)); -+ WARN_ON(!(p->state & TASK_WAKEKILL)); -+ return 0; -+ } -+ } -+ - return wake_up_state(p, state); - } - --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:59 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:58 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C88E2D528B; - Mon, 21 Nov 2011 15:06:58 -0500 (EST) -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 nNrAxBD5KOME; Mon, 21 Nov 2011 15:06:58 -0500 (EST) -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 B2114D51C1; - Mon, 21 Nov 2011 15:06:58 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6uQQ031440; - Mon, 21 Nov 2011 15:06:57 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:17 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:15 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 18/33] ptrace_stop: do not assume the task is running after - wake_up_quiescent() -Message-ID: <20111121200215.GA27839@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 -Status: RO -Content-Length: 956 -Lines: 31 - -If ptrace_stop() sets TASK_TRACED and then detects we should not stop, -it can race with utrace_do_stop() which can see TASK_TRACED and add -TASK_UTRACED. In this case we should stop for utrace needs. - -Signed-off-by: Oleg Nesterov ---- - kernel/signal.c | 8 ++++++++ - 1 files changed, 8 insertions(+), 0 deletions(-) - -diff --git a/kernel/signal.c b/kernel/signal.c -index e06f795..9348da6 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -1916,6 +1916,14 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) - if (clear_code) - current->exit_code = 0; - read_unlock(&tasklist_lock); -+ -+ /* -+ * It is possible that __TASK_UTRACED was added by utrace -+ * while we were __TASK_TRACED and before we take ->siglock -+ * for wake_up_quiescent(), we need to block in this case. -+ * Otherwise this is unnecessary but absolutely harmless. -+ */ -+ schedule(); - } - - utrace_end_stop(); --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:01 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:01 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4BF37D889A; - Mon, 21 Nov 2011 15:07:01 -0500 (EST) -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 5p8tvlXAqUHr; Mon, 21 Nov 2011 15:07:01 -0500 (EST) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 37C22D8757; - Mon, 21 Nov 2011 15:07:01 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6xFJ031449; - Mon, 21 Nov 2011 15:06:59 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:19 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:18 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 19/33] get_signal_to_deliver: restore/restructure - utrace/ptrace signal reporting -Message-ID: <20111121200218.GA27846@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 -Status: RO -Content-Length: 3556 -Lines: 115 - -- Reintroduce tracehook_get_signal() as utrace_hook_signal(). - -- Change get_signal_to_deliver() to call utrace_hook_signal() first, - before dequeue_signal() - -- Always call ptrace_signal() if signal != SIGKILL, no matter whether - this signal comes from utrace or not. - - Since this can change signr again, update "struct k_sigaction *ka" - in this case. - -IOW, roughly, ptrace acts as if it is the last attached engine, it -takes the final decision about the signal. - -Signed-off-by: Oleg Nesterov ---- - include/linux/utrace.h | 31 +++++++++++++++++++++++++++++++ - kernel/signal.c | 30 ++++++++++++++++++++---------- - 2 files changed, 51 insertions(+), 10 deletions(-) - -diff --git a/include/linux/utrace.h b/include/linux/utrace.h -index 0279c74..63103e2 100644 ---- a/include/linux/utrace.h -+++ b/include/linux/utrace.h -@@ -730,4 +730,35 @@ static inline void utrace_end_stop(void) - utrace_finish_stop(); - } - -+/** -+ * utrace_hook_signal - deliver synthetic signal to traced task -+ * @task: @current -+ * @regs: task_pt_regs(@current) -+ * @info: details of synthetic signal -+ * @return_ka: sigaction for synthetic signal -+ * -+ * Return zero to check for a real pending signal normally. -+ * Return -1 after releasing the siglock to repeat the check. -+ * Return a signal number to induce an artificial signal delivery, -+ * setting *@info and *@return_ka to specify its details and behavior. -+ * -+ * The @return_ka->sa_handler value controls the disposition of the -+ * signal, no matter the signal number. For %SIG_DFL, the return value -+ * is a representative signal to indicate the behavior (e.g. %SIGTERM -+ * for death, %SIGQUIT for core dump, %SIGSTOP for job control stop, -+ * %SIGTSTP for stop unless in an orphaned pgrp), but the signal number -+ * reported will be @info->si_signo instead. -+ * -+ * Called with @task->sighand->siglock held, before dequeuing pending signals. -+ */ -+static inline int utrace_hook_signal(struct task_struct *task, -+ struct pt_regs *regs, -+ siginfo_t *info, -+ struct k_sigaction *return_ka) -+{ -+ if (unlikely(task_utrace_flags(task))) -+ return utrace_get_signal(task, regs, info, return_ka); -+ return 0; -+} -+ - #endif /* linux/utrace.h */ -diff --git a/kernel/signal.c b/kernel/signal.c -index 9348da6..38ea4e6 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -2242,17 +2242,27 @@ relock: - for (;;) { - struct k_sigaction *ka; - -- if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) && -- do_signal_stop(0)) -+ signr = utrace_hook_signal(current, regs, info, return_ka); -+ if (unlikely(signr < 0)) - goto relock; - -- if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) { -- do_jobctl_trap(); -- spin_unlock_irq(&sighand->siglock); -- goto relock; -- } -+ if (unlikely(signr != 0)) -+ ka = return_ka; -+ else { -+ if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) && -+ do_signal_stop(0)) -+ goto relock; - -- signr = dequeue_signal(current, ¤t->blocked, info); -+ if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) { -+ do_jobctl_trap(); -+ spin_unlock_irq(&sighand->siglock); -+ goto relock; -+ } -+ -+ signr = dequeue_signal(current, ¤t->blocked, info); -+ -+ ka = &sighand->action[signr-1]; -+ } - - if (!signr) - break; /* will return 0 */ -@@ -2262,9 +2272,9 @@ relock: - regs, cookie); - if (!signr) - continue; -- } - -- ka = &sighand->action[signr-1]; -+ ka = &sighand->action[signr-1]; -+ } - - /* Trace actually delivered signals. */ - trace_signal_deliver(signr, info, ka); --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:03 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:03 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id CB362D89E9; - Mon, 21 Nov 2011 15:07:03 -0500 (EST) -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 wm2JqccPnhsV; Mon, 21 Nov 2011 15:07:03 -0500 (EST) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B6D25D89DE; - Mon, 21 Nov 2011 15:07:03 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK715f031455; - Mon, 21 Nov 2011 15:07:02 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:22 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:20 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 20/33] utrace_get_signal: - s/JOBCTL_STOP_PENDING/JOBCTL_PENDING_MASK/ -Message-ID: <20111121200220.GA27849@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 -Status: RO -Content-Length: 1204 -Lines: 33 - -utrace_get_signal() checks JOBCTL_STOP_PENDING to detect the -case when we should not try to dequeue the signal but should -try to participate in the group-stop. - -With the recent changes this is not enough, everything which -contrbutes to recalc_sigpending_tsk() should be respected. - -Check JOBCTL_PENDING_MASK instead. This matches the -JOBCTL_STOP_PENDING | JOBCTL_TRAP_MASK code in the caller, -get_signal_to_deliver(). Note that this code won't run if -utrace_get_signal() returns signr > 0. - -Signed-off-by: Oleg Nesterov ---- - kernel/utrace.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/kernel/utrace.c b/kernel/utrace.c -index d41b982..0bb0a06 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -2027,7 +2027,7 @@ int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, - ka = NULL; - memset(return_ka, 0, sizeof *return_ka); - } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || -- unlikely(task->jobctl & JOBCTL_STOP_PENDING)) { -+ unlikely(task->jobctl & JOBCTL_PENDING_MASK)) { - /* - * If no engine is interested in intercepting signals or - * we must stop, let the caller just dequeue them normally --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:07 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:06 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8C14BD4F84; - Mon, 21 Nov 2011 15:07:06 -0500 (EST) -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 39eM-KKZxrZ3; Mon, 21 Nov 2011 15:07:06 -0500 (EST) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7628FD4FF4; - Mon, 21 Nov 2011 15:07:06 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK74dN022253; - Mon, 21 Nov 2011 15:07:04 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:25 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:23 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 21/33] introduce ptrace_set_syscall_trace() -Message-ID: <20111121200223.GA27856@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Status: RO -Content-Length: 1549 -Lines: 52 - -No functional changes. Add the new helper, ptrace_set_syscall_trace(), -which should be used to set/clear TIF_SYSCALL_TRACE in ptrace code. -Currently it does nothing more. - -Signed-off-by: Oleg Nesterov ---- - kernel/ptrace.c | 15 ++++++++++----- - 1 files changed, 10 insertions(+), 5 deletions(-) - -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index a464ab5..43357e5 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -38,6 +38,14 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent) - kick_process(p); - } - -+static void ptrace_set_syscall_trace(struct task_struct *p, bool on) -+{ -+ if (on) -+ set_tsk_thread_flag(p, TIF_SYSCALL_TRACE); -+ else -+ clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); -+} -+ - static int ptrace_trapping_sleep_fn(void *flags) - { - schedule(); -@@ -418,7 +426,7 @@ static int ptrace_detach(struct task_struct *child, unsigned int data) - - /* Architecture-specific hardware disable .. */ - ptrace_disable(child); -- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -+ ptrace_set_syscall_trace(child, false); - - write_lock_irq(&tasklist_lock); - /* -@@ -606,10 +614,7 @@ static int ptrace_resume(struct task_struct *child, long request, - if (!valid_signal(data)) - return -EIO; - -- if (request == PTRACE_SYSCALL) -- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -- else -- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -+ ptrace_set_syscall_trace(child, request == PTRACE_SYSCALL); - - #ifdef TIF_SYSCALL_EMU - if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP) --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:09 2011 -Return-Path: oleg@redhat.com -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:09 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1ADF01285E4; - Mon, 21 Nov 2011 15:07:09 -0500 (EST) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id rF+XegsxVXnL; Mon, 21 Nov 2011 15:07:09 -0500 (EST) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 067E41287D0; - Mon, 21 Nov 2011 15:07:09 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK76tD022270; - Mon, 21 Nov 2011 15:07:07 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:27 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:25 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 22/33] introduce PT_SYSCALL_TRACE flag -Message-ID: <20111121200225.GA27860@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Status: RO -Content-Length: 2268 -Lines: 73 - -Currently tracehooks assume that if the ptraced task has -TIF_SYSCALL_TRACE set, the tracee should report the syscall. -This is not true, this thread flag can be set by utrace. - -Add the new internal ptrace flag, PT_SYSCALL_TRACE. Change -ptrace_set_syscall_trace() to set/clear this bit along with -TIF_SYSCALL_TRACE, change ptrace_report_syscall() to check -this flag instead of PT_PTRACED. - -Signed-off-by: Oleg Nesterov ---- - include/linux/ptrace.h | 3 +++ - include/linux/tracehook.h | 2 +- - kernel/ptrace.c | 7 +++++-- - 3 files changed, 9 insertions(+), 3 deletions(-) - -diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h -index 6d9282a..c10f610 100644 ---- a/include/linux/ptrace.h -+++ b/include/linux/ptrace.h -@@ -104,6 +104,8 @@ - - #define PT_TRACE_MASK 0x000003f4 - -+#define PT_SYSCALL_TRACE 0x00020000 -+ - /* single stepping state bits (used on ARM and PA-RISC) */ - #define PT_SINGLESTEP_BIT 31 - #define PT_SINGLESTEP (1<ptrace) { - child->ptrace = current->ptrace; -+ child->ptrace &= ~PT_SYSCALL_TRACE; - __ptrace_link(child, current->parent); - - if (child->ptrace & PT_SEIZED) -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index ec2af67..eb9fe30 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -59,7 +59,7 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) - { - int ptrace = current->ptrace; - -- if (!(ptrace & PT_PTRACED)) -+ if (!(ptrace & PT_SYSCALL_TRACE)) - return; - - ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 43357e5..1ac03eb 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -40,10 +40,13 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent) - - static void ptrace_set_syscall_trace(struct task_struct *p, bool on) - { -- if (on) -+ if (on) { -+ p->ptrace |= PT_SYSCALL_TRACE; - set_tsk_thread_flag(p, TIF_SYSCALL_TRACE); -- else -+ } else { -+ p->ptrace &= ~PT_SYSCALL_TRACE; - clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); -+ } - } - - static int ptrace_trapping_sleep_fn(void *flags) --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:11 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:11 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B7D62D4DCC; - Mon, 21 Nov 2011 15:07:11 -0500 (EST) -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 1ENpGO166I-W; Mon, 21 Nov 2011 15:07:11 -0500 (EST) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A3A55D498A; - Mon, 21 Nov 2011 15:07:11 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK79AS017728; - Mon, 21 Nov 2011 15:07:10 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:30 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:28 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 23/33] utrace: don't clear TIF_SYSCALL_TRACE if it is - needed by ptrace -Message-ID: <20111121200228.GA27863@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Status: RO -Content-Length: 797 -Lines: 24 - -TIF_SYSCALL_TRACE should be cleared only if both ptrace and utrace do -not want it, change utrace_reset() to check PT_SYSCALL_TRACE before -clear_tsk_thread_flag(TIF_SYSCALL_TRACE). - -Signed-off-by: Oleg Nesterov ---- - kernel/utrace.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/kernel/utrace.c b/kernel/utrace.c -index 0bb0a06..bebf6de 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -697,6 +697,7 @@ static bool utrace_reset(struct task_struct *task, struct utrace *utrace) - BUG_ON(utrace->death); - flags &= UTRACE_EVENT(REAP); - } else if (!(flags & UTRACE_EVENT_SYSCALL) && -+ !(task->ptrace & PT_SYSCALL_TRACE) && - test_tsk_thread_flag(task, TIF_SYSCALL_TRACE)) { - clear_tsk_thread_flag(task, TIF_SYSCALL_TRACE); - } --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:14 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:14 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5376AD8774; - Mon, 21 Nov 2011 15:07:14 -0500 (EST) -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 5Oc8ErfFfJSs; Mon, 21 Nov 2011 15:07:14 -0500 (EST) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 3F2CFD81E9; - Mon, 21 Nov 2011 15:07:14 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7Cw3015467; - Mon, 21 Nov 2011 15:07:12 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:32 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:30 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 24/33] introduce task_utrace_lock/task_utrace_unlock -Message-ID: <20111121200230.GA27870@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 -Status: RO -Content-Length: 2190 -Lines: 81 - -- Add task_utrace_lock(task). It simply takes task->utrace->lock if - this task was ever utraced. Otherwise it takes task_lock(), this - serializes with utrace_attach_task()->utrace_task_alloc(). In both - case the caller can be sure it can't race with anything which needs - utrace->lock. - -- Add task_utrace_unlock(task), it releases the corresponding lock. - -Signed-off-by: Oleg Nesterov ---- - include/linux/utrace.h | 9 +++++++++ - kernel/utrace.c | 26 ++++++++++++++++++++++++++ - 2 files changed, 35 insertions(+), 0 deletions(-) - -diff --git a/include/linux/utrace.h b/include/linux/utrace.h -index 63103e2..f37373b 100644 ---- a/include/linux/utrace.h -+++ b/include/linux/utrace.h -@@ -117,6 +117,12 @@ void utrace_signal_handler(struct task_struct *, int); - - #ifndef CONFIG_UTRACE - -+static inline void task_utrace_lock(struct task_struct *task) -+{ -+} -+static inline void task_utrace_unlock(struct task_struct *task) -+{ -+} - /* - * uses these accessors to avoid #ifdef CONFIG_UTRACE. - */ -@@ -139,6 +145,9 @@ static inline void task_utrace_proc_status(struct seq_file *m, - - #else /* CONFIG_UTRACE */ - -+extern void task_utrace_lock(struct task_struct *task); -+extern void task_utrace_unlock(struct task_struct *task); -+ - static inline unsigned long task_utrace_flags(struct task_struct *task) - { - return task->utrace_flags; -diff --git a/kernel/utrace.c b/kernel/utrace.c -index bebf6de..960dd9e 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -79,6 +79,32 @@ static int __init utrace_init(void) - } - module_init(utrace_init); - -+void task_utrace_lock(struct task_struct *task) -+{ -+ struct utrace *utrace = task_utrace_struct(task); -+ -+ if (!utrace) { -+ task_lock(task); -+ utrace = task_utrace_struct(task); -+ if (!utrace) -+ return; -+ -+ task_unlock(task); -+ } -+ -+ spin_lock(&utrace->lock); -+} -+ -+void task_utrace_unlock(struct task_struct *task) -+{ -+ struct utrace *utrace = task_utrace_struct(task); -+ -+ if (utrace) -+ spin_unlock(&utrace->lock); -+ else -+ task_unlock(task); -+} -+ - /* - * Set up @task.utrace for the first time. We can have races - * between two utrace_attach_task() calls here. The task_lock() --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:17 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:17 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 01034D498A; - Mon, 21 Nov 2011 15:07:17 -0500 (EST) -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 BglmrU3H2hJr; Mon, 21 Nov 2011 15:07:16 -0500 (EST) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E0D31D4FF4; - Mon, 21 Nov 2011 15:07:16 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7Egx015474; - Mon, 21 Nov 2011 15:07:15 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:35 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:33 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 25/33] teach ptrace_set_syscall_trace() to play well with - utrace -Message-ID: <20111121200233.GA27873@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 -Status: RO -Content-Length: 1545 -Lines: 49 - -1. ptrace_set_syscall_trace(true)->set_tsk_thread_flag(TIF_SYSCALL_TRACE) - can race with utrace_control()->utrace_reset() path which can miss - PT_SYSCALL_TRACE and clear TIF_SYSCALL_TRACE after it was already set. - -2. ptrace_set_syscall_trace(false) clears TIF_SYSCALL_TRACE and this is - not utrace-friendly, it can need this flag. - -Change ptrace_set_syscall_trace() to take task_utrace_lock(), this is -enough to fix the 1st problem. Check task_utrace_flags() before clearing -TIF_SYSCALL_TRACE, this fixes 2. - -Signed-off-by: Oleg Nesterov ---- - kernel/ptrace.c | 6 +++++- - 1 files changed, 5 insertions(+), 1 deletions(-) - -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 1ac03eb..739183a 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - - void ptrace_signal_wake_up(struct task_struct *p, int quiescent) - { -@@ -40,13 +41,16 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent) - - static void ptrace_set_syscall_trace(struct task_struct *p, bool on) - { -+ task_utrace_lock(p); - if (on) { - p->ptrace |= PT_SYSCALL_TRACE; - set_tsk_thread_flag(p, TIF_SYSCALL_TRACE); - } else { - p->ptrace &= ~PT_SYSCALL_TRACE; -- clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); -+ if (!(task_utrace_flags(p) & UTRACE_EVENT_SYSCALL)) -+ clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); - } -+ task_utrace_unlock(p); - } - - static int ptrace_trapping_sleep_fn(void *flags) --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:19 2011 -Return-Path: oleg@redhat.com -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:19 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8F87F128EAA; - Mon, 21 Nov 2011 15:07:19 -0500 (EST) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id yittEjCd+X4F; Mon, 21 Nov 2011 15:07:19 -0500 (EST) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7BC701287D0; - Mon, 21 Nov 2011 15:07:19 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK7HbH031553; - Mon, 21 Nov 2011 15:07:18 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:38 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:36 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 26/33] introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK -Message-ID: <20111121200236.GA27880@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 -Status: RO -Content-Length: 3723 -Lines: 108 - -Add the new internal ptrace flags, PT_SINGLE_STEP and PT_SINGLE_BLOCK. - -Like PT_SYSCALL_TRACE, this is needed to avoid the unnecessary ptrace -reports when TIF_SINGLESTEP was set by another engine, not by ptrace. -Also, we need these bits to coordinate the user_*_single_step() calls -from ptrace and utrace. - -TODO: update the !x86 ptrace code which does user_disable_single_step(). - -Signed-off-by: Oleg Nesterov ---- - arch/x86/kernel/ptrace.c | 1 + - include/linux/ptrace.h | 5 ++++- - include/linux/tracehook.h | 7 +++++-- - kernel/ptrace.c | 3 +++ - 4 files changed, 13 insertions(+), 3 deletions(-) - -diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c -index 8252879..d1557dc 100644 ---- a/arch/x86/kernel/ptrace.c -+++ b/arch/x86/kernel/ptrace.c -@@ -808,6 +808,7 @@ static int ioperm_get(struct task_struct *target, - */ - void ptrace_disable(struct task_struct *child) - { -+ child->ptrace &= ~(PT_SINGLE_STEP | PT_SINGLE_BLOCK); - user_disable_single_step(child); - #ifdef TIF_SYSCALL_EMU - clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); -diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h -index c10f610..2743315 100644 ---- a/include/linux/ptrace.h -+++ b/include/linux/ptrace.h -@@ -105,6 +105,8 @@ - #define PT_TRACE_MASK 0x000003f4 - - #define PT_SYSCALL_TRACE 0x00020000 -+#define PT_SINGLE_STEP 0x00040000 -+#define PT_SINGLE_BLOCK 0x00080000 - - /* single stepping state bits (used on ARM and PA-RISC) */ - #define PT_SINGLESTEP_BIT 31 -@@ -229,7 +231,8 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) - - if (unlikely(ptrace) && current->ptrace) { - child->ptrace = current->ptrace; -- child->ptrace &= ~PT_SYSCALL_TRACE; -+ child->ptrace &= -+ ~(PT_SYSCALL_TRACE | PT_SINGLE_STEP | PT_SINGLE_BLOCK); - __ptrace_link(child, current->parent); - - if (child->ptrace & PT_SEIZED) -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index eb9fe30..21c8ca2 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -104,6 +104,9 @@ static inline __must_check int tracehook_report_syscall_entry( - return 0; - } - -+#define ptrace_wants_step() \ -+ (current->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK)) -+ - /** - * tracehook_report_syscall_exit - task has just finished a system call - * @regs: user register state of current task -@@ -126,7 +129,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) - if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) - utrace_report_syscall_exit(regs); - -- if (step) { -+ if (step && ptrace_wants_step()) { - siginfo_t info; - user_single_step_siginfo(current, regs, &info); - force_sig_info(SIGTRAP, &info, current); -@@ -157,7 +160,7 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, - { - if (task_utrace_flags(current)) - utrace_signal_handler(current, stepping); -- if (stepping) -+ if (stepping && ptrace_wants_step()) - ptrace_notify(SIGTRAP); - } - -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 739183a..792080d 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -630,13 +630,16 @@ static int ptrace_resume(struct task_struct *child, long request, - clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); - #endif - -+ child->ptrace &= ~(PT_SINGLE_STEP | PT_SINGLE_BLOCK); - if (is_singleblock(request)) { - if (unlikely(!arch_has_block_step())) - return -EIO; -+ child->ptrace |= PT_SINGLE_BLOCK; - user_enable_block_step(child); - } else if (is_singlestep(request) || is_sysemu_singlestep(request)) { - if (unlikely(!arch_has_single_step())) - return -EIO; -+ child->ptrace |= PT_SINGLE_STEP; - user_enable_single_step(child); - } else { - user_disable_single_step(child); --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:22 2011 -Return-Path: oleg@redhat.com -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:22 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 0C136128FB0; - Mon, 21 Nov 2011 15:07:22 -0500 (EST) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id GNbS20gY5Jq9; Mon, 21 Nov 2011 15:07:21 -0500 (EST) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id EB5821287D0; - Mon, 21 Nov 2011 15:07:21 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK7Kn1029766; - Mon, 21 Nov 2011 15:07:20 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:40 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:38 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 27/33] utrace: finish_resume_report: don't do - user_xxx_step() if ptrace_wants_step() -Message-ID: <20111121200238.GA27883@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Status: RO -Content-Length: 2741 -Lines: 84 - -finish_resume_report() should not enable/disable the stepping if -ptrace_wants_step() == T. If ptrace wants block_step while utrace -wants single_step we could "promote" the stepping, but I do not -think this really makes sense. - -Unless the tracee is killed this can't race with ptrace, this is -called by the tracee itself. If it is killed we do not care. - -Signed-off-by: Oleg Nesterov ---- - include/linux/tracehook.h | 8 ++++---- - kernel/utrace.c | 9 ++++++--- - 2 files changed, 10 insertions(+), 7 deletions(-) - -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 21c8ca2..b6812d4 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -104,8 +104,8 @@ static inline __must_check int tracehook_report_syscall_entry( - return 0; - } - --#define ptrace_wants_step() \ -- (current->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK)) -+#define ptrace_wants_step(task) \ -+ ((task)->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK)) - - /** - * tracehook_report_syscall_exit - task has just finished a system call -@@ -129,7 +129,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) - if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) - utrace_report_syscall_exit(regs); - -- if (step && ptrace_wants_step()) { -+ if (step && ptrace_wants_step(current)) { - siginfo_t info; - user_single_step_siginfo(current, regs, &info); - force_sig_info(SIGTRAP, &info, current); -@@ -160,7 +160,7 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, - { - if (task_utrace_flags(current)) - utrace_signal_handler(current, stepping); -- if (stepping && ptrace_wants_step()) -+ if (stepping && ptrace_wants_step(current)) - ptrace_notify(SIGTRAP); - } - -diff --git a/kernel/utrace.c b/kernel/utrace.c -index 960dd9e..05e8532 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -1829,7 +1829,8 @@ static void finish_resume_report(struct task_struct *task, - - case UTRACE_BLOCKSTEP: - if (likely(arch_has_block_step())) { -- user_enable_block_step(task); -+ if (!ptrace_wants_step(task)) -+ user_enable_block_step(task); - break; - } - -@@ -1842,7 +1843,8 @@ static void finish_resume_report(struct task_struct *task, - - case UTRACE_SINGLESTEP: - if (likely(arch_has_single_step())) { -- user_enable_single_step(task); -+ if (!ptrace_wants_step(task)) -+ user_enable_single_step(task); - } else { - /* - * This means some callback is to blame for failing -@@ -1857,7 +1859,8 @@ static void finish_resume_report(struct task_struct *task, - case UTRACE_REPORT: - case UTRACE_RESUME: - default: -- user_disable_single_step(task); -+ if (!ptrace_wants_step(task)) -+ user_disable_single_step(task); - break; - } - } --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:24 2011 -Return-Path: oleg@redhat.com -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:24 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8954F12914D; - Mon, 21 Nov 2011 15:07:24 -0500 (EST) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 0lU8wXKC78yu; Mon, 21 Nov 2011 15:07:24 -0500 (EST) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 759B61287D0; - Mon, 21 Nov 2011 15:07:24 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7Mi7022329; - Mon, 21 Nov 2011 15:07:23 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:43 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:41 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 28/33] ptrace: shift user_*_step() from ptrace_resume() to - ptrace_stop() -Message-ID: <20111121200241.GA27890@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Status: RO -Content-Length: 2374 -Lines: 70 - -1. ptrace_resume() plays with the stopped task which can be also - task_is_utraced(). In this case user_enable_xxx_step() can race - with utrace_reset()->user_disable_single_step(). - - We could change utrace_reset() to check ptrace_wants_step() and - add the task_utrace_lock + unlock barrier after ptrace_resume() - sets PT_SINGLE_STEP. - - But it is better to reassign enable/desable from the tracer to - the tracee, it can check its PT_SINGLE_ bits after wakeup. This - also makes sense because enable_step(task) can be faster if - task == current. - -2. ptrace can do user_disable_single_step() while utrace needs the - stepping. - - Set TIF_NOTIFY_RESUME after user_disable_single_step() to ensure - the tracee can't return to the user-space without utrace_resume(). - Any correct engine which wants the stepping should reassert it. - -Signed-off-by: Oleg Nesterov ---- - kernel/ptrace.c | 4 ---- - kernel/signal.c | 11 +++++++++++ - 2 files changed, 11 insertions(+), 4 deletions(-) - -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 792080d..eba9a22 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -635,14 +635,10 @@ static int ptrace_resume(struct task_struct *child, long request, - if (unlikely(!arch_has_block_step())) - return -EIO; - child->ptrace |= PT_SINGLE_BLOCK; -- user_enable_block_step(child); - } else if (is_singlestep(request) || is_sysemu_singlestep(request)) { - if (unlikely(!arch_has_single_step())) - return -EIO; - child->ptrace |= PT_SINGLE_STEP; -- user_enable_single_step(child); -- } else { -- user_disable_single_step(child); - } - - child->exit_code = data; -diff --git a/kernel/signal.c b/kernel/signal.c -index 38ea4e6..b13d2bc 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -1928,6 +1928,17 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) - - utrace_end_stop(); - -+ if (current->ptrace & PT_SINGLE_BLOCK) -+ user_enable_block_step(current); -+ else if (current->ptrace & PT_SINGLE_STEP) -+ user_enable_single_step(current); -+ else { -+ user_disable_single_step(current); -+ /* if utrace needs the stepping it should reassert */ -+ if (task_utrace_flags(current)) -+ set_thread_flag(TIF_NOTIFY_RESUME); -+ } -+ - /* - * While in TASK_TRACED, we were considered "frozen enough". - * Now that we woke up, it's crucial if we're supposed to be --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:27 2011 -Return-Path: oleg@redhat.com -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:27 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 043581287D0; - Mon, 21 Nov 2011 15:07:27 -0500 (EST) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 4WO1El1jiIrJ; Mon, 21 Nov 2011 15:07:26 -0500 (EST) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E3FCA129045; - Mon, 21 Nov 2011 15:07:26 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7OdV017836; - Mon, 21 Nov 2011 15:07:25 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:45 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:43 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 29/33] ptrace_disable: no need to disable stepping -Message-ID: <20111121200243.GA27893@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Status: RO -Content-Length: 945 -Lines: 29 - -ptrace_disable() is called when the tracee is quiescent and we -are going to untrace. This means we are going to clear ->ptrace -and wake up the tracee. Now that ptrace_stop() checks PT_ bits -and does user_disable_single_step() we can remove this code from -ptrace_disable(), it is unneeded and not utrace-friendly. - -TODO: change !x86 code. - -Signed-off-by: Oleg Nesterov ---- - arch/x86/kernel/ptrace.c | 2 -- - 1 files changed, 0 insertions(+), 2 deletions(-) - -diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c -index d1557dc..96d315a 100644 ---- a/arch/x86/kernel/ptrace.c -+++ b/arch/x86/kernel/ptrace.c -@@ -808,8 +808,6 @@ static int ioperm_get(struct task_struct *target, - */ - void ptrace_disable(struct task_struct *child) - { -- child->ptrace &= ~(PT_SINGLE_STEP | PT_SINGLE_BLOCK); -- user_disable_single_step(child); - #ifdef TIF_SYSCALL_EMU - clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); - #endif --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:29 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:29 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8A6E8D4C39; - Mon, 21 Nov 2011 15:07:29 -0500 (EST) -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 NLURBx2yQes5; Mon, 21 Nov 2011 15:07:29 -0500 (EST) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7660DD498A; - Mon, 21 Nov 2011 15:07:29 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7RnP015578; - Mon, 21 Nov 2011 15:07:27 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:48 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:46 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 30/33] ptrace_report_syscall: check TIF_SYSCALL_EMU -Message-ID: <20111121200246.GA27896@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 -Status: RO -Content-Length: 858 -Lines: 28 - -4d16a64 "introduce PT_SYSCALL_TRACE flag" breaks PTRACE_SYSEMU -which doesn't set PT_SYSCALL_TRACE. - -Change ptrace_report_syscall() to check TIF_SYSCALL_EMU as well. -This can't conflict with utrace, this flag can only be set by -ptrace. - -Signed-off-by: Oleg Nesterov ---- - include/linux/tracehook.h | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index b6812d4..90ca578 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -59,7 +59,7 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) - { - int ptrace = current->ptrace; - -- if (!(ptrace & PT_SYSCALL_TRACE)) -+ if (!(ptrace & PT_SYSCALL_TRACE) && !test_thread_flag(TIF_SYSCALL_EMU)) - return; - - ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:32 2011 -Return-Path: oleg@redhat.com -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:32 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 10D1312916C; - Mon, 21 Nov 2011 15:07:32 -0500 (EST) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id Z14plX1oxaYL; Mon, 21 Nov 2011 15:07:32 -0500 (EST) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F12FF128E1D; - Mon, 21 Nov 2011 15:07:31 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7T0q022460; - Mon, 21 Nov 2011 15:07:30 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:50 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:48 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 31/33] utrace_resume: check irqs_disabled() to shut up - lockdep -Message-ID: <20111121200248.GA27903@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Status: RO -Content-Length: 823 -Lines: 26 - -utrace_resume() enables irqs unconditionally. With the recent changes -in lockdep.c this triggers the warning. Check irqs_disabled() before -local_irq_enable(). - -Signed-off-by: Oleg Nesterov ---- - kernel/utrace.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/kernel/utrace.c b/kernel/utrace.c -index 05e8532..c817a46 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -1881,7 +1881,8 @@ void utrace_resume(struct task_struct *task, struct pt_regs *regs) - * code path leads to calling into get_signal_to_deliver(), which - * implicitly reenables them by virtue of spin_unlock_irq. - */ -- local_irq_enable(); -+ if (irqs_disabled()) /* make trace_hardirqs_on() happy */ -+ local_irq_enable(); - - /* - * If this flag is still set it's because there was a signal --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:34 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:34 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 860BCD8A3E; - Mon, 21 Nov 2011 15:07:34 -0500 (EST) -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 pVTbN1oF62dg; Mon, 21 Nov 2011 15:07:34 -0500 (EST) -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 6FBFFD87A3; - Mon, 21 Nov 2011 15:07:34 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK7W0B029871; - Mon, 21 Nov 2011 15:07:32 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:53 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:51 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 32/33] ptrace_report_syscall: check if TIF_SYSCALL_EMU is - defined -Message-ID: <20111121200251.GA27906@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Status: RO -Content-Length: 839 -Lines: 31 - -From: Tony Breeds - -TIF_SYSCALL_EMU is x86 only, add ifdef into ptrace_report_syscall(). - -Signed-off-by: Oleg Nesterov ---- - include/linux/tracehook.h | 8 ++++++-- - 1 files changed, 6 insertions(+), 2 deletions(-) - -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 90ca578..a1bac95 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -59,8 +59,12 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) - { - int ptrace = current->ptrace; - -- if (!(ptrace & PT_SYSCALL_TRACE) && !test_thread_flag(TIF_SYSCALL_EMU)) -- return; -+ if (!(ptrace & PT_SYSCALL_TRACE)) { -+#ifdef TIF_SYSCALL_EMU -+ if (!test_thread_flag(TIF_SYSCALL_EMU)) -+#endif -+ return; -+ } - - ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); - --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:37 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:37 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 33405D8A50; - Mon, 21 Nov 2011 15:07:37 -0500 (EST) -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 3WH8FhvizjEA; Mon, 21 Nov 2011 15:07:37 -0500 (EST) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1274FD89BB; - Mon, 21 Nov 2011 15:07:37 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7YHr017898; - Mon, 21 Nov 2011 15:07:35 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:55 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:53 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 33/33] utrace: s390: fix the compile problem with traps.c -Message-ID: <20111121200253.GA27913@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Status: RO -Content-Length: 725 -Lines: 25 - -d99e60e5 "tracehooks: reintroduce tracehook_consider_fatal_signal()" -breaks the compilation of arch/s390/kernel/traps.c. Restore the -necessary include removed by upstream 73b7d40f commit. - -Signed-off-by: Oleg Nesterov ---- - arch/s390/kernel/traps.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c -index f506e1b..3132498 100644 ---- a/arch/s390/kernel/traps.c -+++ b/arch/s390/kernel/traps.c -@@ -18,7 +18,7 @@ - #include - #include - #include --#include -+#include - #include - #include - #include --- -1.5.5.1 - +1.7.9.1 From 5710fe27ee1bcc61274ff99be2f72cdf3d139938 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 2 Apr 2012 14:15:23 -0400 Subject: [PATCH 348/397] Linux 3.3.1 --- ...nd-BH_Unwritten-in-journal_unmap_buf.patch | 91 ---- kernel.spec | 24 +- mm-thp-fix-pmd_bad-triggering.patch | 447 ------------------ sources | 1 + ...ter-checks-for-bogus-io-apic-entries.patch | 93 ---- 5 files changed, 7 insertions(+), 649 deletions(-) delete mode 100644 jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch delete mode 100644 mm-thp-fix-pmd_bad-triggering.patch delete mode 100644 x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch diff --git a/jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch b/jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch deleted file mode 100644 index 5ea8ccc10..000000000 --- a/jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch +++ /dev/null @@ -1,91 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Eric Sandeen -Newsgroups: gmane.comp.file-systems.ext4 -Subject: [PATCH] jbd2: clear BH_Delay & BH_Unwritten in journal_unmap_buffer -Date: Tue, 07 Feb 2012 16:07:20 -0600 -Lines: 42 -Approved: news@gmane.org -Message-ID: <4F31A098.4050601@redhat.com> -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: 7bit -X-Trace: dough.gmane.org 1328656072 12026 80.91.229.3 (7 Feb 2012 23:07:52 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Tue, 7 Feb 2012 23:07:52 +0000 (UTC) -To: ext4 development -Original-X-From: linux-ext4-owner@vger.kernel.org Wed Feb 08 00:07:52 2012 -Return-path: -Envelope-to: gcfe-linux-ext4@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1Ruu8d-0000lK-5P - for gcfe-linux-ext4@plane.gmane.org; Wed, 08 Feb 2012 00:07:51 +0100 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1756187Ab2BGXHt (ORCPT ); - Tue, 7 Feb 2012 18:07:49 -0500 -Original-Received: from mx1.redhat.com ([209.132.183.28]:19432 "EHLO mx1.redhat.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1753992Ab2BGXHs (ORCPT ); - Tue, 7 Feb 2012 18:07:48 -0500 -Original-Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q17N7dj0027622 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) - for ; Tue, 7 Feb 2012 18:07:48 -0500 -Original-Received: from liberator.sandeen.net (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q17M7Kgt001990 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) - for ; Tue, 7 Feb 2012 17:07:21 -0500 -User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:10.0) Gecko/20120129 Thunderbird/10.0 -X-Enigmail-Version: 1.3.5 -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 -Original-Sender: linux-ext4-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-ext4@vger.kernel.org -Xref: news.gmane.org gmane.comp.file-systems.ext4:30623 -Archived-At: - -journal_unmap_buffer()'s zap_buffer: code clears a lot of buffer head -state ala discard_buffer(), but does not touch _Delay or _Unwritten -as discard_buffer() does. - -This can be problematic in some areas of the ext4 code which assume -that if they have found a buffer marked unwritten or delay, then it's -a live one. Perhaps those spots should check whether it is mapped -as well, but if jbd2 is going to tear down a buffer, let's really -tear it down completely. - -Without this I get some fsx failures on sub-page-block filesystems -up until v3.2, at which point 4e96b2dbbf1d7e81f22047a50f862555a6cb87cb -and 189e868fa8fdca702eb9db9d8afc46b5cb9144c9 make the failures go -away, because buried within that large change is some more flag -clearing. I still think it's worth doing in jbd2, since -->invalidatepage leads here directly, and it's the right place -to clear away these flags. - -Signed-off-by: Eric Sandeen -Cc: stable@vger.kernel.org ---- - -diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c -index 35ae096..52653306 100644 ---- a/fs/jbd2/transaction.c -+++ b/fs/jbd2/transaction.c -@@ -1949,6 +1949,8 @@ zap_buffer_unlocked: - clear_buffer_mapped(bh); - clear_buffer_req(bh); - clear_buffer_new(bh); -+ clear_buffer_delay(bh); -+ clear_buffer_unwritten(bh); - bh->b_bdev = NULL; - return may_free; - } - - --- -To unsubscribe from this list: send the line "unsubscribe linux-ext4" 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 078b63cbb..f2470248c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 @@ -674,9 +674,6 @@ Patch21091: bcma-brcmsmac-compat.patch #rhbz 772772 Patch21232: rt2x00_fix_MCU_request_failures.patch -#rhbz 788260 -Patch21233: jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch - #rhbz 789644 Patch21237: mcelog-rcu-splat.patch @@ -686,9 +683,6 @@ Patch21240: ACPICA-Fix-regression-in-FADT-revision-checks.patch #rhbz 728478 Patch21242: sony-laptop-Enable-keyboard-backlight-by-default.patch -#rhbz 803809 CVE-2012-1179 -Patch21244: mm-thp-fix-pmd_bad-triggering.patch - Patch21300: unhandled-irqs-switch-to-polling.patch #rhbz 804007 @@ -697,8 +691,6 @@ Patch21305: mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch #rhbz 804957 CVE-2012-1568 Patch21306: shlib_base_randomize.patch -Patch21350: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch - Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch #rhbz 808207 CVE-2012-1601 @@ -1252,7 +1244,8 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch -ApplyPatch hibernate-freeze-filesystems.patch +# FIXME +#ApplyPatch hibernate-freeze-filesystems.patch ApplyPatch lis3-improve-handling-of-null-rate.patch @@ -1266,9 +1259,6 @@ ApplyPatch ext4-Support-check-none-nocheck-mount-options.patch #rhbz 772772 ApplyPatch rt2x00_fix_MCU_request_failures.patch -#rhbz 788269 -ApplyPatch jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch - # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch @@ -1291,11 +1281,6 @@ ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch -ApplyPatch x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch - -#rhbz 803809 CVE-2012-1179 -ApplyPatch mm-thp-fix-pmd_bad-triggering.patch - ApplyPatch nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch #rhbz 808207 CVE-2012-1601 @@ -1948,6 +1933,9 @@ fi # and build. %changelog +* Mon Apr 02 2012 Dave Jones +- Linux 3.3.1 + * Mon Apr 02 2012 Dave Jones - Linux 3.3 diff --git a/mm-thp-fix-pmd_bad-triggering.patch b/mm-thp-fix-pmd_bad-triggering.patch deleted file mode 100644 index 8e1a77cd7..000000000 --- a/mm-thp-fix-pmd_bad-triggering.patch +++ /dev/null @@ -1,447 +0,0 @@ -In some cases it may happen that pmd_none_or_clear_bad() is called -with the mmap_sem hold in read mode. In those cases the huge page -faults can allocate hugepmds under pmd_none_or_clear_bad() and that -can trigger a false positive from pmd_bad() that will not like to see -a pmd materializing as trans huge. - -It's not khugepaged the problem, khugepaged holds the mmap_sem in -write mode (and all those sites must hold the mmap_sem in read mode to -prevent pagetables to go away from under them, during code review it -seems vm86 mode on 32bit kernels requires that too unless it's -restricted to 1 thread per process or UP builds). The race is only -with the huge pagefaults that can convert a pmd_none() into a -pmd_trans_huge(). - -Effectively all these pmd_none_or_clear_bad() sites running with -mmap_sem in read mode are somewhat speculative with the page faults, -and the result is always undefined when they run simultaneously. This -is probably why it wasn't common to run into this. For example if the -madvise(MADV_DONTNEED) runs zap_page_range() shortly before the page -fault, the hugepage will not be zapped, if the page fault runs first -it will be zapped. - -Altering pmd_bad() not to error out if it finds hugepmds won't be -enough to fix this, because zap_pmd_range would then proceed to call -zap_pte_range (which would be incorrect if the pmd become a -pmd_trans_huge()). - -The simplest way to fix this is to read the pmd in the local stack -(regardless of what we read, no need of actual CPU barriers, only -compiler barrier needed), and be sure it is not changing under the -code that computes its value. Even if the real pmd is changing under -the value we hold on the stack, we don't care. If we actually end up -in zap_pte_range it means the pmd was not none already and it was not -huge, and it can't become huge from under us (khugepaged locking -explained above). - -All we need is to enforce that there is no way anymore that in a code -path like below, pmd_trans_huge can be false, but -pmd_none_or_clear_bad can run into a hugepmd. The overhead of a -barrier() is just a compiler tweak and should not be measurable (I -only added it for THP builds). I don't exclude different compiler -versions may have prevented the race too by caching the value of *pmd -on the stack (that hasn't been verified, but it wouldn't be impossible -considering pmd_none_or_clear_bad, pmd_bad, pmd_trans_huge, pmd_none -are all inlines and there's no external function called in between -pmd_trans_huge and pmd_none_or_clear_bad). - - if (pmd_trans_huge(*pmd)) { - if (next-addr != HPAGE_PMD_SIZE) { - VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem)); - split_huge_page_pmd(vma->vm_mm, pmd); - } else if (zap_huge_pmd(tlb, vma, pmd, addr)) - continue; - /* fall through */ - } - if (pmd_none_or_clear_bad(pmd)) - -Because this race condition could be exercised without special -privileges this was reported in CVE-2012-1179. - -The race was identified and fully explained by Ulrich who debugged it. -I'm quoting his accurate explanation below, for reference. - -====== start quote ======= - mapcount 0 page_mapcount 1 - kernel BUG at mm/huge_memory.c:1384! - -At some point prior to the panic, a "bad pmd ..." message similar to the -following is logged on the console: - - mm/memory.c:145: bad pmd ffff8800376e1f98(80000000314000e7). - -The "bad pmd ..." message is logged by pmd_clear_bad() before it clears -the page's PMD table entry. - - 143 void pmd_clear_bad(pmd_t *pmd) - 144 { --> 145 pmd_ERROR(*pmd); - 146 pmd_clear(pmd); - 147 } - -After the PMD table entry has been cleared, there is an inconsistency -between the actual number of PMD table entries that are mapping the page -and the page's map count (_mapcount field in struct page). When the page -is subsequently reclaimed, __split_huge_page() detects this inconsistency. - - 1381 if (mapcount != page_mapcount(page)) - 1382 printk(KERN_ERR "mapcount %d page_mapcount %d\n", - 1383 mapcount, page_mapcount(page)); --> 1384 BUG_ON(mapcount != page_mapcount(page)); - -The root cause of the problem is a race of two threads in a multithreaded -process. Thread B incurs a page fault on a virtual address that has never -been accessed (PMD entry is zero) while Thread A is executing an madvise() -system call on a virtual address within the same 2 MB (huge page) range. - - virtual address space - .---------------------. - | | - | | - .-|---------------------| - | | | - | | |<-- B(fault) - | | | - 2 MB | |/////////////////////|-. - huge < |/////////////////////| > A(range) - page | |/////////////////////|-' - | | | - | | | - '-|---------------------| - | | - | | - '---------------------' - -- Thread A is executing an madvise(..., MADV_DONTNEED) system call - on the virtual address range "A(range)" shown in the picture. - -sys_madvise - // Acquire the semaphore in shared mode. - down_read(¤t->mm->mmap_sem) - ... - madvise_vma - switch (behavior) - case MADV_DONTNEED: - madvise_dontneed - zap_page_range - unmap_vmas - unmap_page_range - zap_pud_range - zap_pmd_range - // - // Assume that this huge page has never been accessed. - // I.e. content of the PMD entry is zero (not mapped). - // - if (pmd_trans_huge(*pmd)) { - // We don't get here due to the above assumption. - } - // - // Assume that Thread B incurred a page fault and - .---------> // sneaks in here as shown below. - | // - | if (pmd_none_or_clear_bad(pmd)) - | { - | if (unlikely(pmd_bad(*pmd))) - | pmd_clear_bad - | { - | pmd_ERROR - | // Log "bad pmd ..." message here. - | pmd_clear - | // Clear the page's PMD entry. - | // Thread B incremented the map count - | // in page_add_new_anon_rmap(), but - | // now the page is no longer mapped - | // by a PMD entry (-> inconsistency). - | } - | } - | - v -- Thread B is handling a page fault on virtual address "B(fault)" shown - in the picture. - -... -do_page_fault - __do_page_fault - // Acquire the semaphore in shared mode. - down_read_trylock(&mm->mmap_sem) - ... - handle_mm_fault - if (pmd_none(*pmd) && transparent_hugepage_enabled(vma)) - // We get here due to the above assumption (PMD entry is zero). - do_huge_pmd_anonymous_page - alloc_hugepage_vma - // Allocate a new transparent huge page here. - ... - __do_huge_pmd_anonymous_page - ... - spin_lock(&mm->page_table_lock) - ... - page_add_new_anon_rmap - // Here we increment the page's map count (starts at -1). - atomic_set(&page->_mapcount, 0) - set_pmd_at - // Here we set the page's PMD entry which will be cleared - // when Thread A calls pmd_clear_bad(). - ... - spin_unlock(&mm->page_table_lock) - -The mmap_sem does not prevent the race because both threads are acquiring -it in shared mode (down_read). Thread B holds the page_table_lock while -the page's map count and PMD table entry are updated. However, Thread A -does not synchronize on that lock. -====== end quote ======= - -Reported-by: Ulrich Obergfell -Signed-off-by: Andrea Arcangeli ---- - arch/x86/kernel/vm86_32.c | 2 + - fs/proc/task_mmu.c | 9 ++++++ - include/asm-generic/pgtable.h | 57 +++++++++++++++++++++++++++++++++++++++++ - mm/memcontrol.c | 4 +++ - mm/memory.c | 14 ++++++++-- - mm/mempolicy.c | 2 +- - mm/mincore.c | 2 +- - mm/pagewalk.c | 2 +- - mm/swapfile.c | 4 +-- - 9 files changed, 87 insertions(+), 9 deletions(-) - -diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c -index b466cab..328cb37 100644 ---- a/arch/x86/kernel/vm86_32.c -+++ b/arch/x86/kernel/vm86_32.c -@@ -172,6 +172,7 @@ static void mark_screen_rdonly(struct mm_struct *mm) - spinlock_t *ptl; - int i; - -+ down_write(&mm->mmap_sem); - pgd = pgd_offset(mm, 0xA0000); - if (pgd_none_or_clear_bad(pgd)) - goto out; -@@ -190,6 +191,7 @@ static void mark_screen_rdonly(struct mm_struct *mm) - } - pte_unmap_unlock(pte, ptl); - out: -+ up_write(&mm->mmap_sem); - flush_tlb(); - } - -diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c -index 7dcd2a2..3efa725 100644 ---- a/fs/proc/task_mmu.c -+++ b/fs/proc/task_mmu.c -@@ -409,6 +409,9 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, - } else { - spin_unlock(&walk->mm->page_table_lock); - } -+ -+ if (pmd_trans_unstable(pmd)) -+ return 0; - /* - * The mmap_sem held all the way back in m_start() is what - * keeps khugepaged out of here and from collapsing things -@@ -507,6 +510,8 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr, - struct page *page; - - split_huge_page_pmd(walk->mm, pmd); -+ if (pmd_trans_unstable(pmd)) -+ return 0; - - pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); - for (; addr != end; pte++, addr += PAGE_SIZE) { -@@ -670,6 +675,8 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, - int err = 0; - - split_huge_page_pmd(walk->mm, pmd); -+ if (pmd_trans_unstable(pmd)) -+ return 0; - - /* find the first VMA at or above 'addr' */ - vma = find_vma(walk->mm, addr); -@@ -961,6 +968,8 @@ static int gather_pte_stats(pmd_t *pmd, unsigned long addr, - spin_unlock(&walk->mm->page_table_lock); - } - -+ if (pmd_trans_unstable(pmd)) -+ return 0; - orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); - do { - struct page *page = can_gather_numa_stats(*pte, md->vma, addr); -diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h -index 76bff2b..10f8291 100644 ---- a/include/asm-generic/pgtable.h -+++ b/include/asm-generic/pgtable.h -@@ -443,6 +443,63 @@ static inline int pmd_write(pmd_t pmd) - #endif /* __HAVE_ARCH_PMD_WRITE */ - #endif - -+/* -+ * This function is meant to be used by sites walking pagetables with -+ * the mmap_sem hold in read mode to protect against MADV_DONTNEED and -+ * transhuge page faults. MADV_DONTNEED can convert a transhuge pmd -+ * into a null pmd and the transhuge page fault can convert a null pmd -+ * into an hugepmd or into a regular pmd (if the hugepage allocation -+ * fails). While holding the mmap_sem in read mode the pmd becomes -+ * stable and stops changing under us only if it's not null and not a -+ * transhuge pmd. When those races occurs and this function makes a -+ * difference vs the standard pmd_none_or_clear_bad, the result is -+ * undefined so behaving like if the pmd was none is safe (because it -+ * can return none anyway). The compiler level barrier() is critically -+ * important to compute the two checks atomically on the same pmdval. -+ */ -+static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) -+{ -+ /* depend on compiler for an atomic pmd read */ -+ pmd_t pmdval = *pmd; -+ /* -+ * The barrier will stabilize the pmdval in a register or on -+ * the stack so that it will stop changing under the code. -+ */ -+#ifdef CONFIG_TRANSPARENT_HUGEPAGE -+ barrier(); -+#endif -+ if (pmd_none(pmdval)) -+ return 1; -+ if (unlikely(pmd_bad(pmdval))) { -+ if (!pmd_trans_huge(pmdval)) -+ pmd_clear_bad(pmd); -+ return 1; -+ } -+ return 0; -+} -+ -+/* -+ * This is a noop if Transparent Hugepage Support is not built into -+ * the kernel. Otherwise it is equivalent to -+ * pmd_none_or_trans_huge_or_clear_bad(), and shall only be called in -+ * places that already verified the pmd is not none and they want to -+ * walk ptes while holding the mmap sem in read mode (write mode don't -+ * need this). If THP is not enabled, the pmd can't go away under the -+ * code even if MADV_DONTNEED runs, but if THP is enabled we need to -+ * run a pmd_trans_unstable before walking the ptes after -+ * split_huge_page_pmd returns (because it may have run when the pmd -+ * become null, but then a page fault can map in a THP and not a -+ * regular page). -+ */ -+static inline int pmd_trans_unstable(pmd_t *pmd) -+{ -+#ifdef CONFIG_TRANSPARENT_HUGEPAGE -+ return pmd_none_or_trans_huge_or_clear_bad(pmd); -+#else -+ return 0; -+#endif -+} -+ - #endif /* !__ASSEMBLY__ */ - - #endif /* _ASM_GENERIC_PGTABLE_H */ -diff --git a/mm/memcontrol.c b/mm/memcontrol.c -index d0e57a3..67b0578 100644 ---- a/mm/memcontrol.c -+++ b/mm/memcontrol.c -@@ -5193,6 +5193,8 @@ static int mem_cgroup_count_precharge_pte_range(pmd_t *pmd, - spinlock_t *ptl; - - split_huge_page_pmd(walk->mm, pmd); -+ if (pmd_trans_unstable(pmd)) -+ return 0; - - pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); - for (; addr != end; pte++, addr += PAGE_SIZE) -@@ -5355,6 +5357,8 @@ static int mem_cgroup_move_charge_pte_range(pmd_t *pmd, - spinlock_t *ptl; - - split_huge_page_pmd(walk->mm, pmd); -+ if (pmd_trans_unstable(pmd)) -+ return 0; - retry: - pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); - for (; addr != end; addr += PAGE_SIZE) { -diff --git a/mm/memory.c b/mm/memory.c -index fa2f04e..e3090fc 100644 ---- a/mm/memory.c -+++ b/mm/memory.c -@@ -1251,12 +1251,20 @@ static inline unsigned long zap_pmd_range(struct mmu_gather *tlb, - VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem)); - split_huge_page_pmd(vma->vm_mm, pmd); - } else if (zap_huge_pmd(tlb, vma, pmd, addr)) -- continue; -+ goto next; - /* fall through */ - } -- if (pmd_none_or_clear_bad(pmd)) -- continue; -+ /* -+ * Here there can be other concurrent MADV_DONTNEED or -+ * trans huge page faults running, and if the pmd is -+ * none or trans huge it can change under us. This is -+ * because MADV_DONTNEED holds the mmap_sem in read -+ * mode. -+ */ -+ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) -+ goto next; - next = zap_pte_range(tlb, vma, pmd, addr, next, details); -+ next: - cond_resched(); - } while (pmd++, addr = next, addr != end); - -diff --git a/mm/mempolicy.c b/mm/mempolicy.c -index 47296fe..0a37570 100644 ---- a/mm/mempolicy.c -+++ b/mm/mempolicy.c -@@ -512,7 +512,7 @@ static inline int check_pmd_range(struct vm_area_struct *vma, pud_t *pud, - do { - next = pmd_addr_end(addr, end); - split_huge_page_pmd(vma->vm_mm, pmd); -- if (pmd_none_or_clear_bad(pmd)) -+ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) - continue; - if (check_pte_range(vma, pmd, addr, next, nodes, - flags, private)) -diff --git a/mm/mincore.c b/mm/mincore.c -index 636a868..936b4ce 100644 ---- a/mm/mincore.c -+++ b/mm/mincore.c -@@ -164,7 +164,7 @@ static void mincore_pmd_range(struct vm_area_struct *vma, pud_t *pud, - } - /* fall through */ - } -- if (pmd_none_or_clear_bad(pmd)) -+ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) - mincore_unmapped_range(vma, addr, next, vec); - else - mincore_pte_range(vma, pmd, addr, next, vec); -diff --git a/mm/pagewalk.c b/mm/pagewalk.c -index 2f5cf10..aa9701e 100644 ---- a/mm/pagewalk.c -+++ b/mm/pagewalk.c -@@ -59,7 +59,7 @@ again: - continue; - - split_huge_page_pmd(walk->mm, pmd); -- if (pmd_none_or_clear_bad(pmd)) -+ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) - goto again; - err = walk_pte_range(pmd, addr, next, walk); - if (err) -diff --git a/mm/swapfile.c b/mm/swapfile.c -index d999f09..f31b29d 100644 ---- a/mm/swapfile.c -+++ b/mm/swapfile.c -@@ -932,9 +932,7 @@ static inline int unuse_pmd_range(struct vm_area_struct *vma, pud_t *pud, - pmd = pmd_offset(pud, addr); - do { - next = pmd_addr_end(addr, end); -- if (unlikely(pmd_trans_huge(*pmd))) -- continue; -- if (pmd_none_or_clear_bad(pmd)) -+ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) - continue; - ret = unuse_pte_range(vma, pmd, addr, next, entry, page); - if (ret) - --- -To unsubscribe, send a message with 'unsubscribe linux-mm' in -the body to majordomo@kvack.org. For more info on Linux MM, -see: http://www.linux-mm.org/ . -Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ -Don't email: email@kvack.org \ No newline at end of file diff --git a/sources b/sources index 2fad201c9..e8c9e05f6 100644 --- a/sources +++ b/sources @@ -1 +1,2 @@ 7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz +10771d657c5bf342bcfe66ed06653ecb patch-3.3.1.xz diff --git a/x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch b/x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch deleted file mode 100644 index 9928829e0..000000000 --- a/x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch +++ /dev/null @@ -1,93 +0,0 @@ -On Tue, 2012-01-31 at 09:26 -0500, Josh Boyer wrote: -> On Wed, Jan 25, 2012 at 06:15:35PM -0500, Josh Boyer wrote: -> > On Wed, Jan 25, 2012 at 02:04:08PM -0800, Suresh Siddha wrote: -> > > On Wed, 2012-01-25 at 08:49 -0500, Josh Boyer wrote: -> > > > [ 0.000000] IOAPIC[1]: apic_id 2, version 255, address 0xfec28000, GSI 24-279 -> > > -> > > This looks indeed like a bogus entry probably returning all 1's for -> > > RTE's etc. Can you please send me a dmesg with "apic=verbose" boot -> > > parameter? -> > -> > Here you go: -> > -> > https://bugzilla.redhat.com/attachment.cgi?id=557552 -> -> Was this helpful at all? I've been watching lkml for a related patch -> in case I was missed on CC but haven't seen anything as of yet. - -Yes, it was helpful. Something like the appended patch should ignore the -bogus io-apic entry all together. As I can't test this, can you or the -reporter give the appended patch a try and ack please? - -thanks, -suresh ---- - -From: Suresh Siddha -Subject: x86, ioapic: add register checks for bogus io-apic entries - -With the recent changes to clear_IO_APIC_pin() which tries to clear -remoteIRR bit explicitly, some of the users started to see -"Unable to reset IRR for apic .." messages. - -Close look shows that these are related to bogus IO-APIC entries which -return's all 1's for their io-apic registers. And the above mentioned error -messages are benign. But kernel should have ignored such io-apic's in the -first place. - -Check if register 0, 1, 2 of the listed io-apic are all 1's and ignore -such io-apic. - -Reported-by: Álvaro Castillo -Signed-off-by: Suresh Siddha ---- - arch/x86/kernel/apic/io_apic.c | 26 ++++++++++++++++++++++++++ - 1 files changed, 26 insertions(+), 0 deletions(-) - -diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c -index fb07275..953e54d 100644 ---- a/arch/x86/kernel/apic/io_apic.c -+++ b/arch/x86/kernel/apic/io_apic.c -@@ -3979,6 +3979,26 @@ static __init int bad_ioapic(unsigned long address) - return 0; - } - -+static __init int bad_ioapic_regs(int idx) -+{ -+ union IO_APIC_reg_00 reg_00; -+ union IO_APIC_reg_01 reg_01; -+ union IO_APIC_reg_02 reg_02; -+ -+ reg_00.raw = io_apic_read(idx, 0); -+ reg_01.raw = io_apic_read(idx, 1); -+ reg_02.raw = io_apic_read(idx, 2); -+ -+ if (reg_00.raw == -1 && reg_01.raw == -1 && reg_02.raw == -1) { -+ printk(KERN_WARNING -+ "I/O APIC 0x%x regs return all ones, skipping!\n", -+ mpc_ioapic_addr(idx)); -+ return 1; -+ } -+ -+ return 0; -+} -+ - void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) - { - int idx = 0; -@@ -3995,6 +4015,12 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) - ioapics[idx].mp_config.apicaddr = address; - - set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); -+ -+ if (bad_ioapic_regs(idx)) { -+ clear_fixmap(FIX_IO_APIC_BASE_0 + idx); -+ return; -+ } -+ - ioapics[idx].mp_config.apicid = io_apic_unique_id(id); - ioapics[idx].mp_config.apicver = io_apic_get_version(idx); - - - - From 5f8cac2df40b3f62928c134071a718378620074a Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 3 Apr 2012 00:23:23 -0400 Subject: [PATCH 349/397] Disable CONFIG_DEBUG_PAGEALLOC in -debug builds again. --- config-debug | 2 -- kernel.spec | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/config-debug b/config-debug index ad5f5352c..ca1ba2b59 100644 --- a/config-debug +++ b/config-debug @@ -110,5 +110,3 @@ CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y -# Temporary -CONFIG_DEBUG_PAGEALLOC=y diff --git a/kernel.spec b/kernel.spec index f2470248c..ef609f979 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -1933,6 +1933,9 @@ fi # and build. %changelog +* Tue Apr 03 2012 Dave Jones 2.6.43.1-2 +- Disable CONFIG_DEBUG_PAGEALLOC in -debug builds again. + * Mon Apr 02 2012 Dave Jones - Linux 3.3.1 From 99bedf074aaf1fb4e71643a84cbeb884edb9e0e4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 28 Mar 2012 11:56:33 -0400 Subject: [PATCH 350/397] iwl{wifi,legacy}: Fix warnings on remove interface from Stanislaw Gruszka (rhbz 770467) --- iwlegacy-do-not-nulify-il-vif-on-reset.patch | 77 ++++++++++++++++++++ iwlwifi-do-not-nulify-ctx-vif-on-reset.patch | 66 +++++++++++++++++ kernel.spec | 12 +++ 3 files changed, 155 insertions(+) create mode 100644 iwlegacy-do-not-nulify-il-vif-on-reset.patch create mode 100644 iwlwifi-do-not-nulify-ctx-vif-on-reset.patch diff --git a/iwlegacy-do-not-nulify-il-vif-on-reset.patch b/iwlegacy-do-not-nulify-il-vif-on-reset.patch new file mode 100644 index 000000000..d1913d708 --- /dev/null +++ b/iwlegacy-do-not-nulify-il-vif-on-reset.patch @@ -0,0 +1,77 @@ +This il->vif is dereferenced in different part of iwlegacy code, so do +not nullify it. This should fix random crashes observed in companion +with microcode errors i.e. crash in il3945_config_ap(). + +Additionally this should address also +WARNING: at drivers/net/wireless/iwlegacy/common.c:4656 il_mac_remove_interface +at least one of the possible reasons of that warning. + +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlegacy/3945-mac.c | 2 -- + drivers/net/wireless/iwlegacy/4965-mac.c | 2 -- + drivers/net/wireless/iwlegacy/common.c | 15 ++++++++++++--- + 3 files changed, 12 insertions(+), 7 deletions(-) + +--- linux-3.3.noarch.orig/drivers/net/wireless/iwlegacy/3945-mac.c ++++ linux-3.3.noarch/drivers/net/wireless/iwlegacy/3945-mac.c +@@ -2684,7 +2684,6 @@ il3945_bg_restart(struct work_struct *da + + if (test_and_clear_bit(S_FW_ERROR, &il->status)) { + mutex_lock(&il->mutex); +- il->ctx.vif = NULL; + il->is_open = 0; + mutex_unlock(&il->mutex); + il3945_down(il); +--- linux-3.3.noarch.orig/drivers/net/wireless/iwlegacy/4965-mac.c ++++ linux-3.3.noarch/drivers/net/wireless/iwlegacy/4965-mac.c +@@ -5381,7 +5381,6 @@ il4965_bg_restart(struct work_struct *da + + if (test_and_clear_bit(S_FW_ERROR, &il->status)) { + mutex_lock(&il->mutex); +- il->ctx.vif = NULL; + il->is_open = 0; + + __il4965_down(il); +--- linux-3.3.noarch.orig/drivers/net/wireless/iwlegacy/common.c ++++ linux-3.3.noarch/drivers/net/wireless/iwlegacy/common.c +@@ -4575,6 +4575,7 @@ il_mac_add_interface(struct ieee80211_hw + struct il_priv *il = hw->priv; + struct il_vif_priv *vif_priv = (void *)vif->drv_priv; + int err; ++ bool reset; + u32 modes; + + D_MAC80211("enter: type %d, addr %pM\n", vif->type, vif->addr); +@@ -4594,6 +4595,16 @@ il_mac_add_interface(struct ieee80211_hw + goto out; + } + ++ /* ++ * We do not support multiple virtual interfaces, but on hardware reset ++ * we have to add the same interface again. ++ */ ++ reset = (il->ctx.vif == vif); ++ if (il->ctx.vif && !reset) { ++ err = -EOPNOTSUPP; ++ goto out; ++ } ++ + modes = il->ctx.interface_modes | il->ctx.exclusive_interface_modes; + if (!(modes & BIT(vif->type))) { + err = -EOPNOTSUPP; +@@ -4605,8 +4616,11 @@ il_mac_add_interface(struct ieee80211_hw + + err = il_setup_interface(il, &il->ctx); + if (err) { +- il->ctx.vif = NULL; +- il->iw_mode = NL80211_IFTYPE_STATION; ++ IL_WARN("Fail to set mode %d\n", vif->type); ++ if (!reset) { ++ il->ctx.vif = NULL; ++ il->iw_mode = NL80211_IFTYPE_STATION; ++ } + } + + out: diff --git a/iwlwifi-do-not-nulify-ctx-vif-on-reset.patch b/iwlwifi-do-not-nulify-ctx-vif-on-reset.patch new file mode 100644 index 000000000..e03f2d304 --- /dev/null +++ b/iwlwifi-do-not-nulify-ctx-vif-on-reset.patch @@ -0,0 +1,66 @@ +ctx->vif is dereferenced in different part of iwlwifi code, so do not +nullify it. + +This should address at least one of the possible reasons of WARNING at +iwlagn_mac_remove_interface, and perhaps some random crashes when +firmware reset is performed. + +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlwifi/iwl-agn.c | 3 --- + drivers/net/wireless/iwlwifi/iwl-mac80211.c | 10 +++++++++- + 2 files changed, 9 insertions(+), 4 deletions(-) + +--- linux-3.3.noarch.orig/drivers/net/wireless/iwlwifi/iwl-agn.c ++++ linux-3.3.noarch/drivers/net/wireless/iwlwifi/iwl-agn.c +@@ -1403,7 +1403,6 @@ static void iwl_bg_run_time_calib_work(s + + void iwlagn_prepare_restart(struct iwl_priv *priv) + { +- struct iwl_rxon_context *ctx; + bool bt_full_concurrent; + u8 bt_ci_compliance; + u8 bt_load; +@@ -1412,8 +1411,6 @@ void iwlagn_prepare_restart(struct iwl_p + + lockdep_assert_held(&priv->shrd->mutex); + +- for_each_context(priv, ctx) +- ctx->vif = NULL; + priv->is_open = 0; + + /* +--- linux-3.3.noarch.orig/drivers/net/wireless/iwlwifi/iwl-mac80211.c ++++ linux-3.3.noarch/drivers/net/wireless/iwlwifi/iwl-mac80211.c +@@ -1226,6 +1226,7 @@ static int iwlagn_mac_add_interface(stru + struct iwl_rxon_context *tmp, *ctx = NULL; + int err; + enum nl80211_iftype viftype = ieee80211_vif_type_p2p(vif); ++ bool reset = false; + + IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", + viftype, vif->addr); +@@ -1247,6 +1248,13 @@ static int iwlagn_mac_add_interface(stru + tmp->interface_modes | tmp->exclusive_interface_modes; + + if (tmp->vif) { ++ /* On reset we need to add the same interface again */ ++ if (tmp->vif == vif) { ++ reset = true; ++ ctx = tmp; ++ break; ++ } ++ + /* check if this busy context is exclusive */ + if (tmp->exclusive_interface_modes & + BIT(tmp->vif->type)) { +@@ -1273,7 +1281,7 @@ static int iwlagn_mac_add_interface(stru + ctx->vif = vif; + + err = iwl_setup_interface(priv, ctx); +- if (!err) ++ if (!err || reset) + goto out; + + ctx->vif = NULL; diff --git a/kernel.spec b/kernel.spec index ef609f979..886cf561f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -691,6 +691,10 @@ Patch21305: mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch #rhbz 804957 CVE-2012-1568 Patch21306: shlib_base_randomize.patch +#rhbz 770476 +Patch21370: iwlegacy-do-not-nulify-il-vif-on-reset.patch +Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch + Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch #rhbz 808207 CVE-2012-1601 @@ -1286,6 +1290,10 @@ ApplyPatch nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch #rhbz 808207 CVE-2012-1601 ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch +#rhbz 770476 +ApplyPatch iwlegacy-do-not-nulify-il-vif-on-reset.patch +ApplyPatch iwlwifi-do-not-nulify-ctx-vif-on-reset.patch + # END OF PATCH APPLICATIONS %endif @@ -1933,6 +1941,10 @@ fi # and build. %changelog +* Tue Apr 03 2012 Josh Boyer +- iwl{wifi,legacy}: Fix warnings on remove interface from Stanislaw Gruszka + (rhbz 770467) + * Tue Apr 03 2012 Dave Jones 2.6.43.1-2 - Disable CONFIG_DEBUG_PAGEALLOC in -debug builds again. From 295a916d88fd1373566159eafc37dc1943711ce5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 3 Apr 2012 12:55:28 -0400 Subject: [PATCH 351/397] Fix crash in uvc_video_clock_update from Laurent Pinchart (rhbz 806433) --- kernel.spec | 9 +- ...uced-crash-in-uvc_video_clock_update.patch | 113 ++++++++++++++++++ 2 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch diff --git a/kernel.spec b/kernel.spec index 886cf561f..f5f64b516 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -691,6 +691,9 @@ Patch21305: mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch #rhbz 804957 CVE-2012-1568 Patch21306: shlib_base_randomize.patch +#rhbz 806433 +Patch21360: uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch + #rhbz 770476 Patch21370: iwlegacy-do-not-nulify-il-vif-on-reset.patch Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch @@ -1294,6 +1297,9 @@ ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch ApplyPatch iwlegacy-do-not-nulify-il-vif-on-reset.patch ApplyPatch iwlwifi-do-not-nulify-ctx-vif-on-reset.patch +#rhbz 806433 +ApplyPatch uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch + # END OF PATCH APPLICATIONS %endif @@ -1942,6 +1948,7 @@ fi %changelog * Tue Apr 03 2012 Josh Boyer +- Fix crash in uvc_video_clock_update from Laurent Pinchart (rhbz 806433) - iwl{wifi,legacy}: Fix warnings on remove interface from Stanislaw Gruszka (rhbz 770467) diff --git a/uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch b/uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch new file mode 100644 index 000000000..5f2a1c006 --- /dev/null +++ b/uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch @@ -0,0 +1,113 @@ +@@ -, +, @@ + drivers/media/video/uvc/uvc_video.c | 50 ++++++++++++++++++++++------------ + 1 files changed, 32 insertions(+), 18 deletions(-) +--- a/drivers/media/video/uvc/uvc_video.c ++++ a/drivers/media/video/uvc/uvc_video.c +@@ -468,22 +468,30 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf, + spin_unlock_irqrestore(&stream->clock.lock, flags); + } + +-static int uvc_video_clock_init(struct uvc_streaming *stream) ++static void uvc_video_clock_reset(struct uvc_streaming *stream) + { + struct uvc_clock *clock = &stream->clock; + +- spin_lock_init(&clock->lock); + clock->head = 0; + clock->count = 0; +- clock->size = 32; + clock->last_sof = -1; + clock->sof_offset = -1; ++} ++ ++static int uvc_video_clock_init(struct uvc_streaming *stream) ++{ ++ struct uvc_clock *clock = &stream->clock; ++ ++ spin_lock_init(&clock->lock); ++ clock->size = 32; + + clock->samples = kmalloc(clock->size * sizeof(*clock->samples), + GFP_KERNEL); + if (clock->samples == NULL) + return -ENOMEM; + ++ uvc_video_clock_reset(stream); ++ + return 0; + } + +@@ -1424,8 +1432,6 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) + + if (free_buffers) + uvc_free_urb_buffers(stream); +- +- uvc_video_clock_cleanup(stream); + } + + /* +@@ -1555,10 +1561,6 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) + + uvc_video_stats_start(stream); + +- ret = uvc_video_clock_init(stream); +- if (ret < 0) +- return ret; +- + if (intf->num_altsetting > 1) { + struct usb_host_endpoint *best_ep = NULL; + unsigned int best_psize = 3 * 1024; +@@ -1683,6 +1685,8 @@ int uvc_video_resume(struct uvc_streaming *stream, int reset) + + stream->frozen = 0; + ++ uvc_video_clock_reset(stream); ++ + ret = uvc_commit_video(stream, &stream->ctrl); + if (ret < 0) { + uvc_queue_enable(&stream->queue, 0); +@@ -1819,25 +1823,35 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable) + uvc_uninit_video(stream, 1); + usb_set_interface(stream->dev->udev, stream->intfnum, 0); + uvc_queue_enable(&stream->queue, 0); ++ uvc_video_clock_cleanup(stream); + return 0; + } + +- ret = uvc_queue_enable(&stream->queue, 1); ++ ret = uvc_video_clock_init(stream); + if (ret < 0) + return ret; + ++ ret = uvc_queue_enable(&stream->queue, 1); ++ if (ret < 0) ++ goto error_queue; ++ + /* Commit the streaming parameters. */ + ret = uvc_commit_video(stream, &stream->ctrl); +- if (ret < 0) { +- uvc_queue_enable(&stream->queue, 0); +- return ret; +- } ++ if (ret < 0) ++ goto error_commit; + + ret = uvc_init_video(stream, GFP_KERNEL); +- if (ret < 0) { +- usb_set_interface(stream->dev->udev, stream->intfnum, 0); +- uvc_queue_enable(&stream->queue, 0); +- } ++ if (ret < 0) ++ goto error_video; ++ ++ return 0; ++ ++error_video: ++ usb_set_interface(stream->dev->udev, stream->intfnum, 0); ++error_commit: ++ uvc_queue_enable(&stream->queue, 0); ++error_queue: ++ uvc_video_clock_cleanup(stream); + + return ret; + } From 77ab0813b656bd3f2f24db5a51a4b726f010f3bf Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 4 Apr 2012 08:19:48 -0400 Subject: [PATCH 352/397] Fix NULL pointer dereference in i2400m (rhbz 808603) --- kernel.spec | 9 +++++ ...vent-a-possible-kernel-bug-due-to-mi.patch | 34 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch diff --git a/kernel.spec b/kernel.spec index f5f64b516..a9698065d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -698,6 +698,9 @@ Patch21360: uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch Patch21370: iwlegacy-do-not-nulify-il-vif-on-reset.patch Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch +#rhbz 808603 +Patch21380: wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch + Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch #rhbz 808207 CVE-2012-1601 @@ -1300,6 +1303,9 @@ ApplyPatch iwlwifi-do-not-nulify-ctx-vif-on-reset.patch #rhbz 806433 ApplyPatch uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch +#rhbz 808603 +ApplyPatch wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch + # END OF PATCH APPLICATIONS %endif @@ -1947,6 +1953,9 @@ fi # and build. %changelog +* Wed Apr 04 2012 Josh Boyer +- Fix NULL pointer dereference in i2400m (rhbz 808603) + * Tue Apr 03 2012 Josh Boyer - Fix crash in uvc_video_clock_update from Laurent Pinchart (rhbz 806433) - iwl{wifi,legacy}: Fix warnings on remove interface from Stanislaw Gruszka diff --git a/wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch b/wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch new file mode 100644 index 000000000..92b2e9970 --- /dev/null +++ b/wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch @@ -0,0 +1,34 @@ +From 4eee6a3a04e8bb53fbe7de0f64d0524d3fbe3f80 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 26 Mar 2012 09:01:30 +0000 +Subject: [PATCH] wimax: i2400m - prevent a possible kernel bug due to missing + fw_name string + +This happened on a machine with a custom hotplug script calling nameif, +probably due to slow firmware loading. At the time nameif uses ethtool +to gather interface information, i2400m->fw_name is zero and so a null +pointer dereference occurs from within i2400m_get_drvinfo(). + +Signed-off-by: Phil Sutter +Signed-off-by: David S. Miller +--- + drivers/net/wimax/i2400m/netdev.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c +index 63e4b70..1d76ae8 100644 +--- a/drivers/net/wimax/i2400m/netdev.c ++++ b/drivers/net/wimax/i2400m/netdev.c +@@ -597,7 +597,8 @@ static void i2400m_get_drvinfo(struct net_device *net_dev, + struct i2400m *i2400m = net_dev_to_i2400m(net_dev); + + strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver) - 1); +- strncpy(info->fw_version, i2400m->fw_name, sizeof(info->fw_version) - 1); ++ strncpy(info->fw_version, ++ i2400m->fw_name ? : "", sizeof(info->fw_version) - 1); + if (net_dev->dev.parent) + strncpy(info->bus_info, dev_name(net_dev->dev.parent), + sizeof(info->bus_info) - 1); +-- +1.7.7.6 + From dd5b515ac784b6b68e2309289461a46fefcff80a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 4 Apr 2012 10:42:03 -0400 Subject: [PATCH 353/397] Disable runtime PM for hotpluggable ATA ports (rhbz 806676) --- kernel.spec | 7 + ...ble-runtime-pm-for-hotpluggable-port.patch | 180 ++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 libata-disable-runtime-pm-for-hotpluggable-port.patch diff --git a/kernel.spec b/kernel.spec index a9698065d..ec218a7c6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -701,6 +701,9 @@ Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch #rhbz 808603 Patch21380: wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch +#rhbz 806676 +Patch21385: libata-disable-runtime-pm-for-hotpluggable-port.patch + Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch #rhbz 808207 CVE-2012-1601 @@ -1306,6 +1309,9 @@ ApplyPatch uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch #rhbz 808603 ApplyPatch wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch +#rhbz 806676 +ApplyPatch libata-disable-runtime-pm-for-hotpluggable-port.patch + # END OF PATCH APPLICATIONS %endif @@ -1954,6 +1960,7 @@ fi %changelog * Wed Apr 04 2012 Josh Boyer +- Disable runtime PM for hotpluggable ATA ports (rhbz 806676) - Fix NULL pointer dereference in i2400m (rhbz 808603) * Tue Apr 03 2012 Josh Boyer diff --git a/libata-disable-runtime-pm-for-hotpluggable-port.patch b/libata-disable-runtime-pm-for-hotpluggable-port.patch new file mode 100644 index 000000000..06020fdde --- /dev/null +++ b/libata-disable-runtime-pm-for-hotpluggable-port.patch @@ -0,0 +1,180 @@ +Path: news.gmane.org!not-for-mail +From: Lin Ming +Newsgroups: gmane.linux.ide,gmane.linux.kernel +Subject: [PATCH v2] libata: disable runtime pm for hotpluggable port +Date: Tue, 13 Mar 2012 09:57:37 +0800 +Lines: 131 +Approved: news@gmane.org +Message-ID: <1331603857.3436.24.camel@minggr> +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 7bit +X-Trace: dough.gmane.org 1331603865 12388 80.91.229.3 (13 Mar 2012 01:57:45 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Tue, 13 Mar 2012 01:57:45 +0000 (UTC) +Cc: linux-ide@vger.kernel.org, lkml , + jslaby@suse.cz, cwillu@cwillu.com, jackdachef@gmail.com, + Sergei Shtylyov +To: Jeff Garzik +Original-X-From: linux-ide-owner@vger.kernel.org Tue Mar 13 02:57:43 2012 +Return-path: +Envelope-to: lnx-linux-ide@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1S7Gze-0005pE-Sg + for lnx-linux-ide@plane.gmane.org; Tue, 13 Mar 2012 02:57:43 +0100 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1754650Ab2CMB5l (ORCPT ); + Mon, 12 Mar 2012 21:57:41 -0400 +Original-Received: from mga14.intel.com ([143.182.124.37]:15186 "EHLO mga14.intel.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1754582Ab2CMB5k (ORCPT ); + Mon, 12 Mar 2012 21:57:40 -0400 +Original-Received: from azsmga002.ch.intel.com ([10.2.17.35]) + by azsmga102.ch.intel.com with ESMTP; 12 Mar 2012 18:57:39 -0700 +X-ExtLoop1: 1 +X-IronPort-AV: E=Sophos;i="4.71,315,1320652800"; + d="scan'208";a="76719701" +Original-Received: from minggr.sh.intel.com (HELO [10.239.36.45]) ([10.239.36.45]) + by AZSMGA002.ch.intel.com with ESMTP; 12 Mar 2012 18:57:38 -0700 +X-Mailer: Evolution 2.30.3 +Original-Sender: linux-ide-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-ide@vger.kernel.org +Xref: news.gmane.org gmane.linux.ide:51560 gmane.linux.kernel:1266262 +Archived-At: + +Currently, hotplug doesn't work if port is already runtime suspended. +For now, we simply disable runtime pm for hotpluggable port. +Later, we should add runtime pm support for hotpluggable port too. + +Bug report: +https://lkml.org/lkml/2012/2/19/70 + +v2: +- Use bit 2 and 3 for flags ATA_FLAG_EXTERNAL and ATA_FLAG_PLUGGABLE. + +TODO: add similar hotpluggable port check for controllers other than +AHCI. + +Reported-and-tested-by: Jiri Slaby +Reported-and-tested-by: cwillu@cwillu.com +Reported-and-tested-by: jackdachef@gmail.com +Signed-off-by: Lin Ming +--- + drivers/ata/ahci.c | 3 +++ + drivers/ata/ahci.h | 3 +++ + drivers/ata/libahci.c | 20 ++++++++++++++++++++ + drivers/ata/libata-transport.c | 6 ++++-- + include/linux/libata.h | 2 ++ + 5 files changed, 32 insertions(+), 2 deletions(-) + +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index d07bf03..02e93ff 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -1145,6 +1145,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + if (hpriv->cap & HOST_CAP_PMP) + pi.flags |= ATA_FLAG_PMP; + ++ if (hpriv->cap & HOST_CAP_SXS) ++ pi.flags |= ATA_FLAG_EXTERNAL; ++ + ahci_set_em_messages(hpriv, &pi); + + if (ahci_broken_system_poweroff(pdev)) { +diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h +index b175000..92f7172 100644 +--- a/drivers/ata/ahci.h ++++ b/drivers/ata/ahci.h +@@ -172,6 +172,9 @@ enum { + PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */ + PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ + PORT_CMD_FBSCP = (1 << 22), /* FBS Capable Port */ ++ PORT_CMD_ESP = (1 << 21), /* External SATA Port */ ++ PORT_CMD_MPSP = (1 << 19), /* Mechanical Presence Switch Attached to Port */ ++ PORT_CMD_HPCP = (1 << 18), /* Hot Plug Capable Port */ + PORT_CMD_PMP = (1 << 17), /* PMP attached */ + PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ + PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ +diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c +index a72bfd0..7d72d3c 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -1097,6 +1097,23 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap, + writel(1 << port_no, mmio + HOST_IRQ_STAT); + } + ++static bool ahci_port_pluggable(struct ata_port *ap) ++{ ++ void __iomem *port_mmio = ahci_port_base(ap); ++ u32 cmd; ++ ++ cmd = readl(port_mmio + PORT_CMD); ++ ++ if ((ap->flags & ATA_FLAG_EXTERNAL) && ++ (cmd & PORT_CMD_ESP)) ++ return true; ++ ++ if (cmd & (PORT_CMD_MPSP | PORT_CMD_HPCP)) ++ return true; ++ ++ return false; ++} ++ + void ahci_init_controller(struct ata_host *host) + { + struct ahci_host_priv *hpriv = host->private_data; +@@ -1112,6 +1129,9 @@ void ahci_init_controller(struct ata_host *host) + if (ata_port_is_dummy(ap)) + continue; + ++ if (ahci_port_pluggable(ap)) ++ ap->flags |= ATA_FLAG_PLUGGABLE; ++ + ahci_port_init(host->dev, ap, i, mmio, port_mmio); + } + +diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c +index 74aaee3..a7166b9 100644 +--- a/drivers/ata/libata-transport.c ++++ b/drivers/ata/libata-transport.c +@@ -292,8 +292,10 @@ int ata_tport_add(struct device *parent, + } + + device_enable_async_suspend(dev); +- pm_runtime_set_active(dev); +- pm_runtime_enable(dev); ++ if (!(ap->flags & ATA_FLAG_PLUGGABLE)) { ++ pm_runtime_set_active(dev); ++ pm_runtime_enable(dev); ++ } + + transport_add_device(dev); + transport_configure_device(dev); +diff --git a/include/linux/libata.h b/include/linux/libata.h +index cafc09a..f46961d 100644 +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -187,6 +187,8 @@ enum { + ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ + /* (doesn't imply presence) */ + ATA_FLAG_SATA = (1 << 1), ++ ATA_FLAG_EXTERNAL = (1 << 2), /* Controller supports external SATA */ ++ ATA_FLAG_PLUGGABLE = (1 << 3), /* Port is hotpluggable */ + ATA_FLAG_NO_ATAPI = (1 << 6), /* No ATAPI support */ + ATA_FLAG_PIO_DMA = (1 << 7), /* PIO cmds via DMA */ + ATA_FLAG_PIO_LBA48 = (1 << 8), /* Host DMA engine is LBA28 only */ +-- +1.7.2.5 + + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-ide" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + From 8df928e24a171ab004d8a8f65e45a19f6d54c010 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 4 Apr 2012 10:50:46 -0400 Subject: [PATCH 354/397] Add additional bug number for libata hotplug fix (rhbz 807632) --- kernel.spec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index ec218a7c6..07fd20611 100644 --- a/kernel.spec +++ b/kernel.spec @@ -701,7 +701,7 @@ Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch #rhbz 808603 Patch21380: wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch -#rhbz 806676 +#rhbz 806676 807632 Patch21385: libata-disable-runtime-pm-for-hotpluggable-port.patch Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch @@ -1309,7 +1309,7 @@ ApplyPatch uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch #rhbz 808603 ApplyPatch wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch -#rhbz 806676 +#rhbz 806676 807632 ApplyPatch libata-disable-runtime-pm-for-hotpluggable-port.patch # END OF PATCH APPLICATIONS @@ -1960,7 +1960,7 @@ fi %changelog * Wed Apr 04 2012 Josh Boyer -- Disable runtime PM for hotpluggable ATA ports (rhbz 806676) +- Disable runtime PM for hotpluggable ATA ports (rhbz 806676 807632) - Fix NULL pointer dereference in i2400m (rhbz 808603) * Tue Apr 03 2012 Josh Boyer From a1fee212e7ea12e8c2162e9fddfe83c3bdcfd2f9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 4 Apr 2012 14:43:32 -0400 Subject: [PATCH 355/397] Increase the size of the dmesg buffer Bump it to 256K, as discussed in the community kernel meeting on Mar 30, 2012 --- config-generic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 299df87e4..33cb50960 100644 --- a/config-generic +++ b/config-generic @@ -39,7 +39,7 @@ CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=17 +CONFIG_LOG_BUF_SHIFT=18 # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set # CONFIG_EXPERT is not set From 446e33ca6da4be00919c1dd43341713364bedb7e Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 5 Apr 2012 11:42:53 -0400 Subject: [PATCH 356/397] Better watermark the number of pages used by hibernation I/O (Bojan Smojver) (rhbz 785384) --- hibernate-watermark.patch | 99 +++++++++++++++++++++++++++++++++++++++ kernel.spec | 5 ++ 2 files changed, 104 insertions(+) create mode 100644 hibernate-watermark.patch diff --git a/hibernate-watermark.patch b/hibernate-watermark.patch new file mode 100644 index 000000000..2cb75e6ef --- /dev/null +++ b/hibernate-watermark.patch @@ -0,0 +1,99 @@ + +--- a/kernel/power/swap.c ++++ a/kernel/power/swap.c +@@ -6,7 +6,7 @@ + * + * Copyright (C) 1998,2001-2005 Pavel Machek + * Copyright (C) 2006 Rafael J. Wysocki +- * Copyright (C) 2010 Bojan Smojver ++ * Copyright (C) 2010-2012 Bojan Smojver + * + * This file is released under the GPLv2. + * +@@ -51,6 +51,15 @@ + + #define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(sector_t) - 1) + ++/* ++ * Number of pages required to be kept free while writing the image. Always ++ * three quarters of all available pages before the writing starts. ++ */ ++static inline unsigned long reqd_free_pages(void) ++{ ++ return (nr_free_pages() / 4) * 3; ++} ++ + struct swap_map_page { + sector_t entries[MAP_PAGE_ENTRIES]; + sector_t next_swap; +@@ -72,7 +81,7 @@ struct swap_map_handle { + sector_t cur_swap; + sector_t first_sector; + unsigned int k; +- unsigned long nr_free_pages, written; ++ unsigned long reqd_free_pages; + u32 crc32; + }; + +@@ -316,8 +325,7 @@ static int get_swap_writer(struct swap_map_handle *handle) + goto err_rel; + } + handle->k = 0; +- handle->nr_free_pages = nr_free_pages() >> 1; +- handle->written = 0; ++ handle->reqd_free_pages = reqd_free_pages(); + handle->first_sector = handle->cur_swap; + return 0; + err_rel: +@@ -352,11 +360,15 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, + handle->cur_swap = offset; + handle->k = 0; + } +- if (bio_chain && ++handle->written > handle->nr_free_pages) { ++ if (bio_chain && nr_free_pages() <= handle->reqd_free_pages) { + error = hib_wait_on_bio_chain(bio_chain); + if (error) + goto out; +- handle->written = 0; ++ /* ++ * Recalculate the number of required free pages, to make sure ++ * we never take more than a quarter. ++ */ ++ handle->reqd_free_pages = reqd_free_pages(); + } + out: + return error; +@@ -404,7 +416,7 @@ static int swap_writer_finish(struct swap_map_handle *handle, + #define LZO_THREADS 3 + + /* Maximum number of pages for read buffering. */ +-#define LZO_READ_PAGES (MAP_PAGE_ENTRIES * 8) ++#define LZO_READ_PAGES 8192 + + + /** +@@ -615,10 +627,10 @@ static int save_image_lzo(struct swap_map_handle *handle, + } + + /* +- * Adjust number of free pages after all allocations have been done. +- * We don't want to run out of pages when writing. ++ * Adjust the number of required free pages after all allocations have ++ * been done. We don't want to run out of pages when writing. + */ +- handle->nr_free_pages = nr_free_pages() >> 1; ++ handle->reqd_free_pages = reqd_free_pages(); + + /* + * Start the CRC32 thread. +@@ -1129,8 +1141,9 @@ static int load_image_lzo(struct swap_map_handle *handle, + + /* + * Adjust number of pages for read buffering, in case we are short. ++ * Never take more than a quarter of all available pages. + */ +- read_pages = (nr_free_pages() - snapshot_get_image_size()) >> 1; ++ read_pages = (nr_free_pages() - snapshot_get_image_size()) / 4; + read_pages = clamp_val(read_pages, LZO_CMP_PAGES, LZO_READ_PAGES); + + for (i = 0; i < read_pages; i++) { diff --git a/kernel.spec b/kernel.spec index 07fd20611..6bc7050b6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -651,6 +651,7 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch14000: hibernate-freeze-filesystems.patch +Patch14001: hibernate-watermark.patch Patch14010: lis3-improve-handling-of-null-rate.patch @@ -1259,6 +1260,7 @@ ApplyPatch efi-dont-map-boot-services-on-32bit.patch # FIXME #ApplyPatch hibernate-freeze-filesystems.patch +ApplyPatch hibernate-watermark.patch ApplyPatch lis3-improve-handling-of-null-rate.patch @@ -1959,6 +1961,9 @@ fi # and build. %changelog +* Thu Apr 05 2012 Dave Jones +- Better watermark the number of pages used by hibernation I/O (Bojan Smojver) (rhbz 785384) + * Wed Apr 04 2012 Josh Boyer - Disable runtime PM for hotpluggable ATA ports (rhbz 806676 807632) - Fix NULL pointer dereference in i2400m (rhbz 808603) From 961ef7f50dd9716b3ddc611d2d1261a5ecb2175e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 10 Apr 2012 09:11:21 -0400 Subject: [PATCH 357/397] Backport fixes for correct register constraints in cmpxchg.h (rhbz 809014) --- kernel.spec | 13 ++++++- ...e-sized-register-constraint-in-__add.patch | 35 +++++++++++++++++++ ...zed-register-constraint-in-__xchg_op.patch | 32 +++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 x86-Use-correct-byte-sized-register-constraint-in-__add.patch create mode 100644 x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch diff --git a/kernel.spec b/kernel.spec index 6bc7050b6..f35abf7a9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -705,6 +705,10 @@ Patch21380: wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch #rhbz 806676 807632 Patch21385: libata-disable-runtime-pm-for-hotpluggable-port.patch +#rhbz 809014 +Patch21390: x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch +Patch21391: x86-Use-correct-byte-sized-register-constraint-in-__add.patch + Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch #rhbz 808207 CVE-2012-1601 @@ -1314,6 +1318,10 @@ ApplyPatch wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch #rhbz 806676 807632 ApplyPatch libata-disable-runtime-pm-for-hotpluggable-port.patch +#rhbz 809014 +ApplyPatch x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch +ApplyPatch x86-Use-correct-byte-sized-register-constraint-in-__add.patch + # END OF PATCH APPLICATIONS %endif @@ -1961,6 +1969,9 @@ fi # and build. %changelog +* Tue Apr 10 2012 Josh Boyer +- Backport fixes for correct register constraints in cmpxchg.h (rhbz 809014) + * Thu Apr 05 2012 Dave Jones - Better watermark the number of pages used by hibernation I/O (Bojan Smojver) (rhbz 785384) diff --git a/x86-Use-correct-byte-sized-register-constraint-in-__add.patch b/x86-Use-correct-byte-sized-register-constraint-in-__add.patch new file mode 100644 index 000000000..3ec765691 --- /dev/null +++ b/x86-Use-correct-byte-sized-register-constraint-in-__add.patch @@ -0,0 +1,35 @@ +From: H. Peter Anvin +Date: Fri, 6 Apr 2012 16:30:57 +0000 (-0700) +Subject: x86: Use correct byte-sized register constraint in __add() +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftip%2Ftip.git;a=commitdiff_plain;h=8c91c5325e107ec17e40a59a47c6517387d64eb7 + +x86: Use correct byte-sized register constraint in __add() + +Similar to: + + 2ca052a x86: Use correct byte-sized register constraint in __xchg_op() + +... the __add() macro also needs to use a "q" constraint in the +byte-sized case, lest we try to generate an illegal register. + +Link: http://lkml.kernel.org/r/4F7A3315.501@goop.org +Signed-off-by: H. Peter Anvin +Cc: Jeremy Fitzhardinge +Cc: Leigh Scott +Cc: Thomas Reitmayr +Cc: v3.3 +--- + +diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h +index bc18d0e..99480e5 100644 +--- a/arch/x86/include/asm/cmpxchg.h ++++ b/arch/x86/include/asm/cmpxchg.h +@@ -173,7 +173,7 @@ extern void __add_wrong_size(void) + switch (sizeof(*(ptr))) { \ + case __X86_CASE_B: \ + asm volatile (lock "addb %b1, %0\n" \ +- : "+m" (*(ptr)) : "ri" (inc) \ ++ : "+m" (*(ptr)) : "qi" (inc) \ + : "memory", "cc"); \ + break; \ + case __X86_CASE_W: \ diff --git a/x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch b/x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch new file mode 100644 index 000000000..a33602f9f --- /dev/null +++ b/x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch @@ -0,0 +1,32 @@ +From: Jeremy Fitzhardinge +Date: Mon, 2 Apr 2012 23:15:33 +0000 (-0700) +Subject: x86: Use correct byte-sized register constraint in __xchg_op() +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftip%2Ftip.git;a=commitdiff_plain;h=2ca052a3710fac208eee690faefdeb8bbd4586a1 + +x86: Use correct byte-sized register constraint in __xchg_op() + +x86-64 can access the low half of any register, but i386 can only do +it with a subset of registers. 'r' causes compilation failures on i386, +but 'q' expresses the constraint properly. + +Signed-off-by: Jeremy Fitzhardinge +Link: http://lkml.kernel.org/r/4F7A3315.501@goop.org +Reported-by: Leigh Scott +Tested-by: Thomas Reitmayr +Signed-off-by: H. Peter Anvin +Cc: v3.3 +--- + +diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h +index b3b7332..bc18d0e 100644 +--- a/arch/x86/include/asm/cmpxchg.h ++++ b/arch/x86/include/asm/cmpxchg.h +@@ -43,7 +43,7 @@ extern void __add_wrong_size(void) + switch (sizeof(*(ptr))) { \ + case __X86_CASE_B: \ + asm volatile (lock #op "b %b0, %1\n" \ +- : "+r" (__ret), "+m" (*(ptr)) \ ++ : "+q" (__ret), "+m" (*(ptr)) \ + : : "memory", "cc"); \ + break; \ + case __X86_CASE_W: \ From 91f796e3da8d1d7cacb86fbe0bd65a4cca0b6545 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 10 Apr 2012 15:11:33 -0400 Subject: [PATCH 358/397] Apply upstream patch to add USB device 13d3:3375 (rhbz 811087) --- ...-USB-device-13d3-3375-as-an-Atheros-.patch | 58 +++++++++++++++++++ kernel.spec | 3 + 2 files changed, 61 insertions(+) create mode 100644 Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch diff --git a/Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch b/Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch new file mode 100644 index 000000000..f238d50da --- /dev/null +++ b/Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch @@ -0,0 +1,58 @@ +From 9498ba7a1d38d42eef4ef6d906ab1743c9f0fd6f Mon Sep 17 00:00:00 2001 +From: Eran +Date: Mon, 5 Dec 2011 22:15:29 +0000 +Subject: [PATCH] Bluetooth: Adding USB device 13d3:3375 as an Atheros AR3012. + +The bluetooth module in the Asus UX31/UX21 is based on Atheros AR3012 +and requires a firmware to be uploaded before it's usable. + +output of usb-devices for this module: +T: Bus=01 Lev=02 Prnt=02 Port=07 Cnt=03 Dev#= 6 Spd=12 MxCh= 0 +D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=13d3 ProdID=3375 Rev=00.02 +S: Manufacturer=Atheros Communications +S: Product=Bluetooth USB Host Controller +S: SerialNumber=Alaska Day 2006 +C: #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA +I: If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb + +Signed-off-by: Eran +Tested-by: Michal Labedzki +Signed-off-by: Gustavo F. Padovan + +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index 4eca6e5..4844247 100644 +--- a/drivers/bluetooth/ath3k.c ++++ b/drivers/bluetooth/ath3k.c +@@ -72,6 +72,7 @@ static struct usb_device_id ath3k_table[] = { + + /* Atheros AR3012 with sflash firmware*/ + { USB_DEVICE(0x0CF3, 0x3004) }, ++ { USB_DEVICE(0x13d3, 0x3375) }, + + /* Atheros AR5BBU12 with sflash firmware */ + { USB_DEVICE(0x0489, 0xE02C) }, +@@ -88,6 +89,7 @@ static struct usb_device_id ath3k_blist_tbl[] = { + + /* Atheros AR3012 with sflash firmware*/ + { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, + + { } /* Terminating entry */ + }; +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 22f695e..480cad9 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -129,6 +129,7 @@ static struct usb_device_id blacklist_table[] = { + + /* Atheros 3012 with sflash firmware */ + { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, + + /* Atheros AR5BBU12 with sflash firmware */ + { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index f35abf7a9..644b33d12 100644 --- a/kernel.spec +++ b/kernel.spec @@ -656,6 +656,7 @@ Patch14001: hibernate-watermark.patch Patch14010: lis3-improve-handling-of-null-rate.patch Patch15000: bluetooth-use-after-free.patch +Patch15001: Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch Patch20000: utrace.patch @@ -1269,6 +1270,7 @@ ApplyPatch hibernate-watermark.patch ApplyPatch lis3-improve-handling-of-null-rate.patch ApplyPatch bluetooth-use-after-free.patch +ApplyPatch Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch # utrace. ApplyPatch utrace.patch @@ -1970,6 +1972,7 @@ fi %changelog * Tue Apr 10 2012 Josh Boyer +- Apply upstream patch to add USB device 13d3:3375 (rhbz 811087) - Backport fixes for correct register constraints in cmpxchg.h (rhbz 809014) * Thu Apr 05 2012 Dave Jones From c7fc574893445be4917fac957447c937bd82eb85 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Apr 2012 16:53:26 -0300 Subject: [PATCH 359/397] Add the Kernel media updates with fixes for 3.4 and other material for 3.4/3.5 Those patches contain important fixes, expecially the one for BZ#808871 and BZ#807052, at the DVB core. Also add poll_requested_events - The new events interface requires this function in order to work. Signed-off-by: Mauro Carvalho Chehab --- add-poll-requested-events.patch | 393 + config-generic | 15 + drivers-media-update.patch | 38223 +++++++++++++++++++++++++ kernel.spec | 17 +- linux-2.6-v4l-dvb-experimental.patch | 0 linux-2.6-v4l-dvb-fixes.patch | 0 linux-2.6-v4l-dvb-update.patch | 0 7 files changed, 38640 insertions(+), 8 deletions(-) create mode 100644 add-poll-requested-events.patch create mode 100644 drivers-media-update.patch delete mode 100644 linux-2.6-v4l-dvb-experimental.patch delete mode 100644 linux-2.6-v4l-dvb-fixes.patch delete mode 100644 linux-2.6-v4l-dvb-update.patch diff --git a/add-poll-requested-events.patch b/add-poll-requested-events.patch new file mode 100644 index 000000000..9ab28c1b3 --- /dev/null +++ b/add-poll-requested-events.patch @@ -0,0 +1,393 @@ +commit 626cf236608505d376e4799adb4f7eb00a8594af +Author: Hans Verkuil +Date: Fri Mar 23 15:02:27 2012 -0700 + + poll: add poll_requested_events() and poll_does_not_wait() functions + + In some cases the poll() implementation in a driver has to do different + things depending on the events the caller wants to poll for. An example + is when a driver needs to start a DMA engine if the caller polls for + POLLIN, but doesn't want to do that if POLLIN is not requested but instead + only POLLOUT or POLLPRI is requested. This is something that can happen + in the video4linux subsystem among others. + + Unfortunately, the current epoll/poll/select implementation doesn't + provide that information reliably. The poll_table_struct does have it: it + has a key field with the event mask. But once a poll() call matches one + or more bits of that mask any following poll() calls are passed a NULL + poll_table pointer. + + Also, the eventpoll implementation always left the key field at ~0 instead + of using the requested events mask. + + This was changed in eventpoll.c so the key field now contains the actual + events that should be polled for as set by the caller. + + The solution to the NULL poll_table pointer is to set the qproc field to + NULL in poll_table once poll() matches the events, not the poll_table + pointer itself. That way drivers can obtain the mask through a new + poll_requested_events inline. + + The poll_table_struct can still be NULL since some kernel code calls it + internally (netfs_state_poll() in ./drivers/staging/pohmelfs/netfs.h). In + that case poll_requested_events() returns ~0 (i.e. all events). + + Very rarely drivers might want to know whether poll_wait will actually + wait. If another earlier file descriptor in the set already matched the + events the caller wanted to wait for, then the kernel will return from the + select() call without waiting. This might be useful information in order + to avoid doing expensive work. + + A new helper function poll_does_not_wait() is added that drivers can use + to detect this situation. This is now used in sock_poll_wait() in + include/net/sock.h. This was the only place in the kernel that needed + this information. + + Drivers should no longer access any of the poll_table internals, but use + the poll_requested_events() and poll_does_not_wait() access functions + instead. In order to enforce that the poll_table fields are now prepended + with an underscore and a comment was added warning against using them + directly. + + This required a change in unix_dgram_poll() in unix/af_unix.c which used + the key field to get the requested events. It's been replaced by a call + to poll_requested_events(). + + For qproc it was especially important to change its name since the + behavior of that field changes with this patch since this function pointer + can now be NULL when that wasn't possible in the past. + + Any driver accessing the qproc or key fields directly will now fail to compile. + + Some notes regarding the correctness of this patch: the driver's poll() + function is called with a 'struct poll_table_struct *wait' argument. This + pointer may or may not be NULL, drivers can never rely on it being one or + the other as that depends on whether or not an earlier file descriptor in + the select()'s fdset matched the requested events. + + There are only three things a driver can do with the wait argument: + + 1) obtain the key field: + + events = wait ? wait->key : ~0; + + This will still work although it should be replaced with the new + poll_requested_events() function (which does exactly the same). + This will now even work better, since wait is no longer set to NULL + unnecessarily. + + 2) use the qproc callback. This could be deadly since qproc can now be + NULL. Renaming qproc should prevent this from happening. There are no + kernel drivers that actually access this callback directly, BTW. + + 3) test whether wait == NULL to determine whether poll would return without + waiting. This is no longer sufficient as the correct test is now + wait == NULL || wait->_qproc == NULL. + + However, the worst that can happen here is a slight performance hit in + the case where wait != NULL and wait->_qproc == NULL. In that case the + driver will assume that poll_wait() will actually add the fd to the set + of waiting file descriptors. Of course, poll_wait() will not do that + since it tests for wait->_qproc. This will not break anything, though. + + There is only one place in the whole kernel where this happens + (sock_poll_wait() in include/net/sock.h) and that code will be replaced + by a call to poll_does_not_wait() in the next patch. + + Note that even if wait->_qproc != NULL drivers cannot rely on poll_wait() + actually waiting. The next file descriptor from the set might match the + event mask and thus any possible waits will never happen. + + Signed-off-by: Hans Verkuil + Reviewed-by: Jonathan Corbet + Reviewed-by: Al Viro + Cc: Davide Libenzi + Signed-off-by: Hans de Goede + Cc: Mauro Carvalho Chehab + Cc: David Miller + Cc: Eric Dumazet + Signed-off-by: Andrew Morton + Signed-off-by: Linus Torvalds + +diff --git a/fs/eventpoll.c b/fs/eventpoll.c +index 4d9d3a4..ca30007 100644 +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -699,9 +699,12 @@ static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head, + void *priv) + { + struct epitem *epi, *tmp; ++ poll_table pt; + ++ init_poll_funcptr(&pt, NULL); + list_for_each_entry_safe(epi, tmp, head, rdllink) { +- if (epi->ffd.file->f_op->poll(epi->ffd.file, NULL) & ++ pt._key = epi->event.events; ++ if (epi->ffd.file->f_op->poll(epi->ffd.file, &pt) & + epi->event.events) + return POLLIN | POLLRDNORM; + else { +@@ -1097,6 +1100,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, + /* Initialize the poll table using the queue callback */ + epq.epi = epi; + init_poll_funcptr(&epq.pt, ep_ptable_queue_proc); ++ epq.pt._key = event->events; + + /* + * Attach the item to the poll hooks and get current event bits. +@@ -1191,6 +1195,9 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even + { + int pwake = 0; + unsigned int revents; ++ poll_table pt; ++ ++ init_poll_funcptr(&pt, NULL); + + /* + * Set the new event interest mask before calling f_op->poll(); +@@ -1198,13 +1205,14 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even + * f_op->poll() call and the new event set registering. + */ + epi->event.events = event->events; ++ pt._key = event->events; + epi->event.data = event->data; /* protected by mtx */ + + /* + * Get current event bits. We can safely use the file* here because + * its usage count has been increased by the caller of this function. + */ +- revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL); ++ revents = epi->ffd.file->f_op->poll(epi->ffd.file, &pt); + + /* + * If the item is "hot" and it is not registered inside the ready +@@ -1239,6 +1247,9 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head, + unsigned int revents; + struct epitem *epi; + struct epoll_event __user *uevent; ++ poll_table pt; ++ ++ init_poll_funcptr(&pt, NULL); + + /* + * We can loop without lock because we are passed a task private list. +@@ -1251,7 +1262,8 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head, + + list_del_init(&epi->rdllink); + +- revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL) & ++ pt._key = epi->event.events; ++ revents = epi->ffd.file->f_op->poll(epi->ffd.file, &pt) & + epi->event.events; + + /* +diff --git a/fs/select.c b/fs/select.c +index e782258..ecfd0b1 100644 +--- a/fs/select.c ++++ b/fs/select.c +@@ -223,7 +223,7 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, + get_file(filp); + entry->filp = filp; + entry->wait_address = wait_address; +- entry->key = p->key; ++ entry->key = p->_key; + init_waitqueue_func_entry(&entry->wait, pollwake); + entry->wait.private = pwq; + add_wait_queue(wait_address, &entry->wait); +@@ -386,13 +386,11 @@ get_max: + static inline void wait_key_set(poll_table *wait, unsigned long in, + unsigned long out, unsigned long bit) + { +- if (wait) { +- wait->key = POLLEX_SET; +- if (in & bit) +- wait->key |= POLLIN_SET; +- if (out & bit) +- wait->key |= POLLOUT_SET; +- } ++ wait->_key = POLLEX_SET; ++ if (in & bit) ++ wait->_key |= POLLIN_SET; ++ if (out & bit) ++ wait->_key |= POLLOUT_SET; + } + + int do_select(int n, fd_set_bits *fds, struct timespec *end_time) +@@ -414,7 +412,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) + poll_initwait(&table); + wait = &table.pt; + if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { +- wait = NULL; ++ wait->_qproc = NULL; + timed_out = 1; + } + +@@ -459,17 +457,17 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) + if ((mask & POLLIN_SET) && (in & bit)) { + res_in |= bit; + retval++; +- wait = NULL; ++ wait->_qproc = NULL; + } + if ((mask & POLLOUT_SET) && (out & bit)) { + res_out |= bit; + retval++; +- wait = NULL; ++ wait->_qproc = NULL; + } + if ((mask & POLLEX_SET) && (ex & bit)) { + res_ex |= bit; + retval++; +- wait = NULL; ++ wait->_qproc = NULL; + } + } + } +@@ -481,7 +479,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) + *rexp = res_ex; + cond_resched(); + } +- wait = NULL; ++ wait->_qproc = NULL; + if (retval || timed_out || signal_pending(current)) + break; + if (table.error) { +@@ -720,7 +718,7 @@ struct poll_list { + * interested in events matching the pollfd->events mask, and the result + * matching that mask is both recorded in pollfd->revents and returned. The + * pwait poll_table will be used by the fd-provided poll handler for waiting, +- * if non-NULL. ++ * if pwait->_qproc is non-NULL. + */ + static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) + { +@@ -738,9 +736,7 @@ static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) + if (file != NULL) { + mask = DEFAULT_POLLMASK; + if (file->f_op && file->f_op->poll) { +- if (pwait) +- pwait->key = pollfd->events | +- POLLERR | POLLHUP; ++ pwait->_key = pollfd->events|POLLERR|POLLHUP; + mask = file->f_op->poll(file, pwait); + } + /* Mask out unneeded events. */ +@@ -763,7 +759,7 @@ static int do_poll(unsigned int nfds, struct poll_list *list, + + /* Optimise the no-wait case */ + if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { +- pt = NULL; ++ pt->_qproc = NULL; + timed_out = 1; + } + +@@ -781,22 +777,22 @@ static int do_poll(unsigned int nfds, struct poll_list *list, + for (; pfd != pfd_end; pfd++) { + /* + * Fish for events. If we found one, record it +- * and kill the poll_table, so we don't ++ * and kill poll_table->_qproc, so we don't + * needlessly register any other waiters after + * this. They'll get immediately deregistered + * when we break out and return. + */ + if (do_pollfd(pfd, pt)) { + count++; +- pt = NULL; ++ pt->_qproc = NULL; + } + } + } + /* + * All waiters have already been registered, so don't provide +- * a poll_table to them on the next loop iteration. ++ * a poll_table->_qproc to them on the next loop iteration. + */ +- pt = NULL; ++ pt->_qproc = NULL; + if (!count) { + count = wait->error; + if (signal_pending(current)) +diff --git a/include/linux/poll.h b/include/linux/poll.h +index cf40010..48fe8bc 100644 +--- a/include/linux/poll.h ++++ b/include/linux/poll.h +@@ -32,21 +32,46 @@ struct poll_table_struct; + */ + typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *); + ++/* ++ * Do not touch the structure directly, use the access functions ++ * poll_does_not_wait() and poll_requested_events() instead. ++ */ + typedef struct poll_table_struct { +- poll_queue_proc qproc; +- unsigned long key; ++ poll_queue_proc _qproc; ++ unsigned long _key; + } poll_table; + + static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p) + { +- if (p && wait_address) +- p->qproc(filp, wait_address, p); ++ if (p && p->_qproc && wait_address) ++ p->_qproc(filp, wait_address, p); ++} ++ ++/* ++ * Return true if it is guaranteed that poll will not wait. This is the case ++ * if the poll() of another file descriptor in the set got an event, so there ++ * is no need for waiting. ++ */ ++static inline bool poll_does_not_wait(const poll_table *p) ++{ ++ return p == NULL || p->_qproc == NULL; ++} ++ ++/* ++ * Return the set of events that the application wants to poll for. ++ * This is useful for drivers that need to know whether a DMA transfer has ++ * to be started implicitly on poll(). You typically only want to do that ++ * if the application is actually polling for POLLIN and/or POLLOUT. ++ */ ++static inline unsigned long poll_requested_events(const poll_table *p) ++{ ++ return p ? p->_key : ~0UL; + } + + static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc) + { +- pt->qproc = qproc; +- pt->key = ~0UL; /* all events enabled */ ++ pt->_qproc = qproc; ++ pt->_key = ~0UL; /* all events enabled */ + } + + struct poll_table_entry { +diff --git a/include/net/sock.h b/include/net/sock.h +index 04bc0b3..a6ba1f8 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -1854,7 +1854,7 @@ static inline bool wq_has_sleeper(struct socket_wq *wq) + static inline void sock_poll_wait(struct file *filp, + wait_queue_head_t *wait_address, poll_table *p) + { +- if (p && wait_address) { ++ if (!poll_does_not_wait(p) && wait_address) { + poll_wait(filp, wait_address, p); + /* + * We need to be sure we are in sync with the +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index eb4277c..d510353 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -2206,7 +2206,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, + } + + /* No write status requested, avoid expensive OUT tests. */ +- if (wait && !(wait->key & (POLLWRBAND | POLLWRNORM | POLLOUT))) ++ if (!(poll_requested_events(wait) & (POLLWRBAND|POLLWRNORM|POLLOUT))) + return mask; + + writable = unix_writable(sk); diff --git a/config-generic b/config-generic index 33cb50960..33fcbf07a 100644 --- a/config-generic +++ b/config-generic @@ -2624,6 +2624,15 @@ CONFIG_VIDEO_TM6000=m CONFIG_VIDEO_TM6000_ALSA=m CONFIG_VIDEO_TM6000_DVB=m CONFIG_VIDEO_TLG2300=m +# CONFIG_VIDEO_ADV7183 is not set +# CONFIG_VIDEO_VS6624 is not set +# CONFIG_VIDEO_MT9M032 is not set + +CONFIG_IR_GPIO_CIR=m +CONFIG_MEDIA_TUNER_FC0011=m +CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_USB_KEENE=n + # CONFIG_VIDEO_TIMBERDALE is not set # CONFIG_VIDEO_M5MOLS is not set @@ -2733,6 +2742,12 @@ CONFIG_DVB_STV0299=m CONFIG_DVB_MB86A16=m CONFIG_DVB_DRXD=m CONFIG_DVB_CXD2820R=m +CONFIG_DVB_USB_AZ6007=m +CONFIG_DVB_USB_RTL28XXU=m +CONFIG_DVB_USB_AF9035=m +CONFIG_DVB_RTL2830=m +CONFIG_DVB_M88RS2000=m +CONFIG_DVB_AF9033=m # # Supported Frontend Modules diff --git a/drivers-media-update.patch b/drivers-media-update.patch new file mode 100644 index 000000000..5d5612b72 --- /dev/null +++ b/drivers-media-update.patch @@ -0,0 +1,38223 @@ +Driver updates with all media stuff + +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/az6007.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/az6007.c +@@ -0,0 +1,957 @@ ++/* ++ * Driver for AzureWave 6007 DVB-C/T USB2.0 and clones ++ * ++ * Copyright (c) Henry Wang ++ * ++ * This driver was made publicly available by Terratec, at: ++ * http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz ++ * The original driver's license is GPL, as declared with MODULE_LICENSE() ++ * ++ * Copyright (c) 2010-2011 Mauro Carvalho Chehab ++ * Driver modified by in order to work with upstream drxk driver, and ++ * tons of bugs got fixed. ++ * ++ * 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 under 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 "drxk.h" ++#include "mt2063.h" ++#include "dvb_ca_en50221.h" ++ ++#define DVB_USB_LOG_PREFIX "az6007" ++#include "dvb-usb.h" ++ ++/* debug */ ++int dvb_usb_az6007_debug; ++module_param_named(debug, dvb_usb_az6007_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." ++ DVB_USB_DEBUG_STATUS); ++ ++#define deb_info(args...) dprintk(dvb_usb_az6007_debug, 0x01, args) ++#define deb_xfer(args...) dprintk(dvb_usb_az6007_debug, 0x02, args) ++#define deb_rc(args...) dprintk(dvb_usb_az6007_debug, 0x04, args) ++#define deb_fe(args...) dprintk(dvb_usb_az6007_debug, 0x08, args) ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++/* Known requests (Cypress FX2 firmware + az6007 "private" ones*/ ++ ++#define FX2_OED 0xb5 ++#define AZ6007_READ_DATA 0xb7 ++#define AZ6007_I2C_RD 0xb9 ++#define AZ6007_POWER 0xbc ++#define AZ6007_I2C_WR 0xbd ++#define FX2_SCON1 0xc0 ++#define AZ6007_TS_THROUGH 0xc7 ++#define AZ6007_READ_IR 0xb4 ++ ++struct az6007_device_state { ++ struct mutex mutex; ++ struct mutex ca_mutex; ++ struct dvb_ca_en50221 ca; ++ unsigned warm:1; ++ int (*gate_ctrl) (struct dvb_frontend *, int); ++ unsigned char data[4096]; ++}; ++ ++static struct drxk_config terratec_h7_drxk = { ++ .adr = 0x29, ++ .parallel_ts = true, ++ .dynamic_clk = true, ++ .single_master = true, ++ .enable_merr_cfg = true, ++ .no_i2c_bridge = false, ++ .chunk_size = 64, ++ .mpeg_out_clk_strength = 0x02, ++ .microcode_name = "dvb-usb-terratec-h7-drxk.fw", ++}; ++ ++static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) ++{ ++ struct dvb_usb_adapter *adap = fe->sec_priv; ++ struct az6007_device_state *st; ++ int status = 0; ++ ++ deb_info("%s: %s\n", __func__, enable ? "enable" : "disable"); ++ ++ if (!adap) ++ return -EINVAL; ++ ++ st = adap->dev->priv; ++ ++ if (!st) ++ return -EINVAL; ++ ++ if (enable) ++ status = st->gate_ctrl(fe, 1); ++ else ++ status = st->gate_ctrl(fe, 0); ++ ++ return status; ++} ++ ++static struct mt2063_config az6007_mt2063_config = { ++ .tuner_address = 0x60, ++ .refclock = 36125000, ++}; ++ ++static int __az6007_read(struct usb_device *udev, u8 req, u16 value, ++ u16 index, u8 *b, int blen) ++{ ++ int ret; ++ ++ ret = usb_control_msg(udev, ++ usb_rcvctrlpipe(udev, 0), ++ req, ++ USB_TYPE_VENDOR | USB_DIR_IN, ++ value, index, b, blen, 5000); ++ if (ret < 0) { ++ warn("usb read operation failed. (%d)", ret); ++ return -EIO; ++ } ++ ++ deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, ++ index); ++ debug_dump(b, blen, deb_xfer); ++ ++ return ret; ++} ++ ++static int az6007_read(struct dvb_usb_device *d, u8 req, u16 value, ++ u16 index, u8 *b, int blen) ++{ ++ struct az6007_device_state *st = d->priv; ++ int ret; ++ ++ if (mutex_lock_interruptible(&st->mutex) < 0) ++ return -EAGAIN; ++ ++ ret = __az6007_read(d->udev, req, value, index, b, blen); ++ ++ mutex_unlock(&st->mutex); ++ ++ return ret; ++} ++ ++static int __az6007_write(struct usb_device *udev, u8 req, u16 value, ++ u16 index, u8 *b, int blen) ++{ ++ int ret; ++ ++ deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, ++ index); ++ debug_dump(b, blen, deb_xfer); ++ ++ if (blen > 64) { ++ err("az6007: tried to write %d bytes, but I2C max size is 64 bytes\n", ++ blen); ++ return -EOPNOTSUPP; ++ } ++ ++ ret = usb_control_msg(udev, ++ usb_sndctrlpipe(udev, 0), ++ req, ++ USB_TYPE_VENDOR | USB_DIR_OUT, ++ value, index, b, blen, 5000); ++ if (ret != blen) { ++ err("usb write operation failed. (%d)", ret); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int az6007_write(struct dvb_usb_device *d, u8 req, u16 value, ++ u16 index, u8 *b, int blen) ++{ ++ struct az6007_device_state *st = d->priv; ++ int ret; ++ ++ if (mutex_lock_interruptible(&st->mutex) < 0) ++ return -EAGAIN; ++ ++ ret = __az6007_write(d->udev, req, value, index, b, blen); ++ ++ mutex_unlock(&st->mutex); ++ ++ return ret; ++} ++ ++static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) ++{ ++ struct dvb_usb_device *d = adap->dev; ++ ++ deb_info("%s: %s", __func__, onoff ? "enable" : "disable"); ++ ++ return az6007_write(d, 0xbc, onoff, 0, NULL, 0); ++} ++ ++/* remote control stuff (does not work with my box) */ ++static int az6007_rc_query(struct dvb_usb_device *d) ++{ ++ struct az6007_device_state *st = d->priv; ++ unsigned code = 0; ++ ++ az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10); ++ ++ if (st->data[1] == 0x44) ++ return 0; ++ ++ if ((st->data[1] ^ st->data[2]) == 0xff) ++ code = st->data[1]; ++ else ++ code = st->data[1] << 8 | st->data[2]; ++ ++ if ((st->data[3] ^ st->data[4]) == 0xff) ++ code = code << 8 | st->data[3]; ++ else ++ code = code << 16 | st->data[3] << 8 | st->data[4]; ++ ++ rc_keydown(d->rc_dev, code, st->data[5]); ++ ++ return 0; ++} ++ ++static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, ++ int slot, ++ int address) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; ++ ++ int ret; ++ u8 req; ++ u16 value; ++ u16 index; ++ int blen; ++ u8 *b; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ b = kmalloc(12, GFP_KERNEL); ++ if (!b) ++ return -ENOMEM; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ req = 0xC1; ++ value = address; ++ index = 0; ++ blen = 1; ++ ++ ret = az6007_read(d, req, value, index, b, blen); ++ if (ret < 0) { ++ warn("usb in operation failed. (%d)", ret); ++ ret = -EINVAL; ++ } else { ++ ret = b[0]; ++ } ++ ++ mutex_unlock(&state->ca_mutex); ++ kfree(b); ++ return ret; ++} ++ ++static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, ++ int slot, ++ int address, ++ u8 value) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; ++ ++ int ret; ++ u8 req; ++ u16 value1; ++ u16 index; ++ int blen; ++ ++ deb_info("%s %d", __func__, slot); ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ req = 0xC2; ++ value1 = address; ++ index = value; ++ blen = 0; ++ ++ ret = az6007_write(d, req, value1, index, NULL, blen); ++ if (ret != 0) ++ warn("usb out operation failed. (%d)", ret); ++ ++ mutex_unlock(&state->ca_mutex); ++ return ret; ++} ++ ++static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca, ++ int slot, ++ u8 address) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; ++ ++ int ret; ++ u8 req; ++ u16 value; ++ u16 index; ++ int blen; ++ u8 *b; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ b = kmalloc(12, GFP_KERNEL); ++ if (!b) ++ return -ENOMEM; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ req = 0xC3; ++ value = address; ++ index = 0; ++ blen = 2; ++ ++ ret = az6007_read(d, req, value, index, b, blen); ++ if (ret < 0) { ++ warn("usb in operation failed. (%d)", ret); ++ ret = -EINVAL; ++ } else { ++ if (b[0] == 0) ++ warn("Read CI IO error"); ++ ++ ret = b[1]; ++ deb_info("read cam data = %x from 0x%x", b[1], value); ++ } ++ ++ mutex_unlock(&state->ca_mutex); ++ kfree(b); ++ return ret; ++} ++ ++static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca, ++ int slot, ++ u8 address, ++ u8 value) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; ++ ++ int ret; ++ u8 req; ++ u16 value1; ++ u16 index; ++ int blen; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ req = 0xC4; ++ value1 = address; ++ index = value; ++ blen = 0; ++ ++ ret = az6007_write(d, req, value1, index, NULL, blen); ++ if (ret != 0) { ++ warn("usb out operation failed. (%d)", ret); ++ goto failed; ++ } ++ ++failed: ++ mutex_unlock(&state->ca_mutex); ++ return ret; ++} ++ ++static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ ++ int ret; ++ u8 req; ++ u16 value; ++ u16 index; ++ int blen; ++ u8 *b; ++ ++ b = kmalloc(12, GFP_KERNEL); ++ if (!b) ++ return -ENOMEM; ++ ++ req = 0xC8; ++ value = 0; ++ index = 0; ++ blen = 1; ++ ++ ret = az6007_read(d, req, value, index, b, blen); ++ if (ret < 0) { ++ warn("usb in operation failed. (%d)", ret); ++ ret = -EIO; ++ } else{ ++ ret = b[0]; ++ } ++ kfree(b); ++ return ret; ++} ++ ++static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; ++ ++ int ret, i; ++ u8 req; ++ u16 value; ++ u16 index; ++ int blen; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ req = 0xC6; ++ value = 1; ++ index = 0; ++ blen = 0; ++ ++ ret = az6007_write(d, req, value, index, NULL, blen); ++ if (ret != 0) { ++ warn("usb out operation failed. (%d)", ret); ++ goto failed; ++ } ++ ++ msleep(500); ++ req = 0xC6; ++ value = 0; ++ index = 0; ++ blen = 0; ++ ++ ret = az6007_write(d, req, value, index, NULL, blen); ++ if (ret != 0) { ++ warn("usb out operation failed. (%d)", ret); ++ goto failed; ++ } ++ ++ for (i = 0; i < 15; i++) { ++ msleep(100); ++ ++ if (CI_CamReady(ca, slot)) { ++ deb_info("CAM Ready"); ++ break; ++ } ++ } ++ msleep(5000); ++ ++failed: ++ mutex_unlock(&state->ca_mutex); ++ return ret; ++} ++ ++static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) ++{ ++ return 0; ++} ++ ++static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; ++ ++ int ret; ++ u8 req; ++ u16 value; ++ u16 index; ++ int blen; ++ ++ deb_info("%s", __func__); ++ mutex_lock(&state->ca_mutex); ++ req = 0xC7; ++ value = 1; ++ index = 0; ++ blen = 0; ++ ++ ret = az6007_write(d, req, value, index, NULL, blen); ++ if (ret != 0) { ++ warn("usb out operation failed. (%d)", ret); ++ goto failed; ++ } ++ ++failed: ++ mutex_unlock(&state->ca_mutex); ++ return ret; ++} ++ ++static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; ++ int ret; ++ u8 req; ++ u16 value; ++ u16 index; ++ int blen; ++ u8 *b; ++ ++ b = kmalloc(12, GFP_KERNEL); ++ if (!b) ++ return -ENOMEM; ++ mutex_lock(&state->ca_mutex); ++ ++ req = 0xC5; ++ value = 0; ++ index = 0; ++ blen = 1; ++ ++ ret = az6007_read(d, req, value, index, b, blen); ++ if (ret < 0) { ++ warn("usb in operation failed. (%d)", ret); ++ ret = -EIO; ++ } else ++ ret = 0; ++ ++ if (!ret && b[0] == 1) { ++ ret = DVB_CA_EN50221_POLL_CAM_PRESENT | ++ DVB_CA_EN50221_POLL_CAM_READY; ++ } ++ ++ mutex_unlock(&state->ca_mutex); ++ kfree(b); ++ return ret; ++} ++ ++ ++static void az6007_ci_uninit(struct dvb_usb_device *d) ++{ ++ struct az6007_device_state *state; ++ ++ deb_info("%s", __func__); ++ ++ if (NULL == d) ++ return; ++ ++ state = (struct az6007_device_state *)d->priv; ++ if (NULL == state) ++ return; ++ ++ if (NULL == state->ca.data) ++ return; ++ ++ dvb_ca_en50221_release(&state->ca); ++ ++ memset(&state->ca, 0, sizeof(state->ca)); ++} ++ ++ ++static int az6007_ci_init(struct dvb_usb_adapter *a) ++{ ++ struct dvb_usb_device *d = a->dev; ++ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; ++ int ret; ++ ++ deb_info("%s", __func__); ++ ++ mutex_init(&state->ca_mutex); ++ ++ state->ca.owner = THIS_MODULE; ++ state->ca.read_attribute_mem = az6007_ci_read_attribute_mem; ++ state->ca.write_attribute_mem = az6007_ci_write_attribute_mem; ++ state->ca.read_cam_control = az6007_ci_read_cam_control; ++ state->ca.write_cam_control = az6007_ci_write_cam_control; ++ state->ca.slot_reset = az6007_ci_slot_reset; ++ state->ca.slot_shutdown = az6007_ci_slot_shutdown; ++ state->ca.slot_ts_enable = az6007_ci_slot_ts_enable; ++ state->ca.poll_slot_status = az6007_ci_poll_slot_status; ++ state->ca.data = d; ++ ++ ret = dvb_ca_en50221_init(&a->dvb_adap, ++ &state->ca, ++ 0, /* flags */ ++ 1);/* n_slots */ ++ if (ret != 0) { ++ err("Cannot initialize CI: Error %d.", ret); ++ memset(&state->ca, 0, sizeof(state->ca)); ++ return ret; ++ } ++ ++ deb_info("CI initialized."); ++ ++ return 0; ++} ++ ++static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ struct az6007_device_state *st = d->priv; ++ int ret; ++ ++ ret = az6007_read(d, AZ6007_READ_DATA, 6, 0, st->data, 6); ++ memcpy(mac, st->data, sizeof(mac)); ++ ++ if (ret > 0) ++ deb_info("%s: mac is %02x:%02x:%02x:%02x:%02x:%02x\n", ++ __func__, mac[0], mac[1], mac[2], ++ mac[3], mac[4], mac[5]); ++ ++ return ret; ++} ++ ++static int az6007_frontend_attach(struct dvb_usb_adapter *adap) ++{ ++ struct az6007_device_state *st = adap->dev->priv; ++ ++ deb_info("attaching demod drxk"); ++ ++ adap->fe_adap[0].fe = dvb_attach(drxk_attach, &terratec_h7_drxk, ++ &adap->dev->i2c_adap); ++ if (!adap->fe_adap[0].fe) ++ return -EINVAL; ++ ++ adap->fe_adap[0].fe->sec_priv = adap; ++ st->gate_ctrl = adap->fe_adap[0].fe->ops.i2c_gate_ctrl; ++ adap->fe_adap[0].fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; ++ ++ az6007_ci_init(adap); ++ ++ return 0; ++} ++ ++static int az6007_tuner_attach(struct dvb_usb_adapter *adap) ++{ ++ deb_info("attaching tuner mt2063"); ++ ++ /* Attach mt2063 to DVB-C frontend */ ++ if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) ++ adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1); ++ if (!dvb_attach(mt2063_attach, adap->fe_adap[0].fe, ++ &az6007_mt2063_config, ++ &adap->dev->i2c_adap)) ++ return -EINVAL; ++ ++ if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) ++ adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0); ++ ++ return 0; ++} ++ ++int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) ++{ ++ struct az6007_device_state *st = d->priv; ++ int ret; ++ ++ deb_info("%s()\n", __func__); ++ ++ if (!st->warm) { ++ mutex_init(&st->mutex); ++ ++ ret = az6007_write(d, AZ6007_POWER, 0, 2, NULL, 0); ++ if (ret < 0) ++ return ret; ++ msleep(60); ++ ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0); ++ if (ret < 0) ++ return ret; ++ msleep(100); ++ ret = az6007_write(d, AZ6007_POWER, 1, 3, NULL, 0); ++ if (ret < 0) ++ return ret; ++ msleep(20); ++ ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0); ++ if (ret < 0) ++ return ret; ++ ++ msleep(400); ++ ret = az6007_write(d, FX2_SCON1, 0, 3, NULL, 0); ++ if (ret < 0) ++ return ret; ++ msleep(150); ++ ret = az6007_write(d, FX2_SCON1, 1, 3, NULL, 0); ++ if (ret < 0) ++ return ret; ++ msleep(430); ++ ret = az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0); ++ if (ret < 0) ++ return ret; ++ ++ st->warm = true; ++ ++ return 0; ++ } ++ ++ if (!onoff) ++ return 0; ++ ++ az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0); ++ az6007_write(d, AZ6007_TS_THROUGH, 0, 0, NULL, 0); ++ ++ return 0; ++} ++ ++/* I2C */ ++static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], ++ int num) ++{ ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ struct az6007_device_state *st = d->priv; ++ int i, j, len; ++ int ret = 0; ++ u16 index; ++ u16 value; ++ int length; ++ u8 req, addr; ++ ++ if (mutex_lock_interruptible(&st->mutex) < 0) ++ return -EAGAIN; ++ ++ for (i = 0; i < num; i++) { ++ addr = msgs[i].addr << 1; ++ if (((i + 1) < num) ++ && (msgs[i].len == 1) ++ && (!msgs[i].flags & I2C_M_RD) ++ && (msgs[i + 1].flags & I2C_M_RD) ++ && (msgs[i].addr == msgs[i + 1].addr)) { ++ /* ++ * A write + read xfer for the same address, where ++ * the first xfer has just 1 byte length. ++ * Need to join both into one operation ++ */ ++ if (dvb_usb_az6007_debug & 2) ++ printk(KERN_DEBUG ++ "az6007 I2C xfer write+read addr=0x%x len=%d/%d: ", ++ addr, msgs[i].len, msgs[i + 1].len); ++ req = AZ6007_I2C_RD; ++ index = msgs[i].buf[0]; ++ value = addr | (1 << 8); ++ length = 6 + msgs[i + 1].len; ++ len = msgs[i + 1].len; ++ ret = __az6007_read(d->udev, req, value, index, ++ st->data, length); ++ if (ret >= len) { ++ for (j = 0; j < len; j++) { ++ msgs[i + 1].buf[j] = st->data[j + 5]; ++ if (dvb_usb_az6007_debug & 2) ++ printk(KERN_CONT ++ "0x%02x ", ++ msgs[i + 1].buf[j]); ++ } ++ } else ++ ret = -EIO; ++ i++; ++ } else if (!(msgs[i].flags & I2C_M_RD)) { ++ /* write bytes */ ++ if (dvb_usb_az6007_debug & 2) ++ printk(KERN_DEBUG ++ "az6007 I2C xfer write addr=0x%x len=%d: ", ++ addr, msgs[i].len); ++ req = AZ6007_I2C_WR; ++ index = msgs[i].buf[0]; ++ value = addr | (1 << 8); ++ length = msgs[i].len - 1; ++ len = msgs[i].len - 1; ++ if (dvb_usb_az6007_debug & 2) ++ printk(KERN_CONT "(0x%02x) ", msgs[i].buf[0]); ++ for (j = 0; j < len; j++) { ++ st->data[j] = msgs[i].buf[j + 1]; ++ if (dvb_usb_az6007_debug & 2) ++ printk(KERN_CONT "0x%02x ", ++ st->data[j]); ++ } ++ ret = __az6007_write(d->udev, req, value, index, ++ st->data, length); ++ } else { ++ /* read bytes */ ++ if (dvb_usb_az6007_debug & 2) ++ printk(KERN_DEBUG ++ "az6007 I2C xfer read addr=0x%x len=%d: ", ++ addr, msgs[i].len); ++ req = AZ6007_I2C_RD; ++ index = msgs[i].buf[0]; ++ value = addr; ++ length = msgs[i].len + 6; ++ len = msgs[i].len; ++ ret = __az6007_read(d->udev, req, value, index, ++ st->data, length); ++ for (j = 0; j < len; j++) { ++ msgs[i].buf[j] = st->data[j + 5]; ++ if (dvb_usb_az6007_debug & 2) ++ printk(KERN_CONT ++ "0x%02x ", st->data[j + 5]); ++ } ++ } ++ if (dvb_usb_az6007_debug & 2) ++ printk(KERN_CONT "\n"); ++ if (ret < 0) ++ goto err; ++ } ++err: ++ mutex_unlock(&st->mutex); ++ ++ if (ret < 0) { ++ info("%s ERROR: %i", __func__, ret); ++ return ret; ++ } ++ return num; ++} ++ ++static u32 az6007_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static struct i2c_algorithm az6007_i2c_algo = { ++ .master_xfer = az6007_i2c_xfer, ++ .functionality = az6007_i2c_func, ++}; ++ ++int az6007_identify_state(struct usb_device *udev, ++ struct dvb_usb_device_properties *props, ++ struct dvb_usb_device_description **desc, int *cold) ++{ ++ int ret; ++ u8 *mac; ++ ++ mac = kmalloc(6, GFP_ATOMIC); ++ if (!mac) ++ return -ENOMEM; ++ ++ /* Try to read the mac address */ ++ ret = __az6007_read(udev, AZ6007_READ_DATA, 6, 0, mac, 6); ++ if (ret == 6) ++ *cold = 0; ++ else ++ *cold = 1; ++ ++ kfree(mac); ++ ++ if (*cold) { ++ __az6007_write(udev, 0x09, 1, 0, NULL, 0); ++ __az6007_write(udev, 0x00, 0, 0, NULL, 0); ++ __az6007_write(udev, 0x00, 0, 0, NULL, 0); ++ } ++ ++ deb_info("Device is on %s state\n", *cold ? "warm" : "cold"); ++ return 0; ++} ++ ++static struct dvb_usb_device_properties az6007_properties; ++ ++static void az6007_usb_disconnect(struct usb_interface *intf) ++{ ++ struct dvb_usb_device *d = usb_get_intfdata(intf); ++ az6007_ci_uninit(d); ++ dvb_usb_device_exit(intf); ++} ++ ++static int az6007_usb_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ return dvb_usb_device_init(intf, &az6007_properties, ++ THIS_MODULE, NULL, adapter_nr); ++} ++ ++static struct usb_device_id az6007_usb_table[] = { ++ {USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007)}, ++ {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7)}, ++ {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2)}, ++ {0}, ++}; ++ ++MODULE_DEVICE_TABLE(usb, az6007_usb_table); ++ ++static struct dvb_usb_device_properties az6007_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = CYPRESS_FX2, ++ .firmware = "dvb-usb-terratec-h7-az6007.fw", ++ .no_reconnect = 1, ++ .size_of_priv = sizeof(struct az6007_device_state), ++ .identify_state = az6007_identify_state, ++ .num_adapters = 1, ++ .adapter = { ++ { ++ .num_frontends = 1, ++ .fe = {{ ++ .streaming_ctrl = az6007_streaming_ctrl, ++ .tuner_attach = az6007_tuner_attach, ++ .frontend_attach = az6007_frontend_attach, ++ ++ /* parameter for the MPEG2-data transfer */ ++ .stream = { ++ .type = USB_BULK, ++ .count = 10, ++ .endpoint = 0x02, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ } } ++ } }, ++ .power_ctrl = az6007_power_ctrl, ++ .read_mac_address = az6007_read_mac_addr, ++ ++ .rc.core = { ++ .rc_interval = 400, ++ .rc_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS, ++ .module_name = "az6007", ++ .rc_query = az6007_rc_query, ++ .allowed_protos = RC_TYPE_NEC, ++ }, ++ .i2c_algo = &az6007_i2c_algo, ++ ++ .num_device_descs = 2, ++ .devices = { ++ { .name = "AzureWave DTV StarBox DVB-T/C USB2.0 (az6007)", ++ .cold_ids = { &az6007_usb_table[0], NULL }, ++ .warm_ids = { NULL }, ++ }, ++ { .name = "TerraTec DTV StarBox DVB-T/C USB2.0 (az6007)", ++ .cold_ids = { &az6007_usb_table[1], &az6007_usb_table[2], NULL }, ++ .warm_ids = { NULL }, ++ }, ++ { NULL }, ++ } ++}; ++ ++/* usb specific object needed to register this driver with the usb subsystem */ ++static struct usb_driver az6007_usb_driver = { ++ .name = "dvb_usb_az6007", ++ .probe = az6007_usb_probe, ++ .disconnect = az6007_usb_disconnect, ++ .id_table = az6007_usb_table, ++}; ++ ++/* module stuff */ ++static int __init az6007_usb_module_init(void) ++{ ++ int result; ++ deb_info("az6007 usb module init\n"); ++ ++ result = usb_register(&az6007_usb_driver); ++ if (result) { ++ err("usb_register failed. (%d)", result); ++ return result; ++ } ++ ++ return 0; ++} ++ ++static void __exit az6007_usb_module_exit(void) ++{ ++ /* deregister this driver from the USB subsystem */ ++ deb_info("az6007 usb module exit\n"); ++ usb_deregister(&az6007_usb_driver); ++} ++ ++module_init(az6007_usb_module_init); ++module_exit(az6007_usb_module_exit); ++ ++MODULE_AUTHOR("Henry Wang "); ++MODULE_AUTHOR("Mauro Carvalho Chehab "); ++MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones"); ++MODULE_VERSION("1.1"); ++MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/az6007.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/az6007.h +@@ -0,0 +1,18 @@ ++#ifndef _DVB_USB_AZ6007_H_ ++#define _DVB_USB_AZ6007_H_ ++ ++#define DVB_USB_LOG_PREFIX "az6007" ++#include "dvb-usb.h" ++ ++ ++extern int dvb_usb_az6007_debug; ++#define deb_info(args...) dprintk(dvb_usb_az6007_debug,0x01,args) ++#define deb_xfer(args...) dprintk(dvb_usb_az6007_debug,0x02,args) ++#define deb_rc(args...) dprintk(dvb_usb_az6007_debug,0x04,args) ++#define deb_fe(args...) dprintk(dvb_usb_az6007_debug,0x08,args) ++ ++ ++extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec); ++extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); ++ ++#endif +Index: linux-3.3.x86_64/drivers/media/common/tuners/mt2063.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/common/tuners/mt2063.c ++++ linux-3.3.x86_64/drivers/media/common/tuners/mt2063.c +@@ -350,7 +350,7 @@ static int MT2063_Sleep(struct dvb_front + /* + * ToDo: Add code here to implement a OS blocking + */ +- msleep(10); ++ msleep(100); + + return 0; + } +@@ -2226,7 +2226,7 @@ static struct dvb_tuner_ops mt2063_ops = + .info = { + .name = "MT2063 Silicon Tuner", + .frequency_min = 45000000, +- .frequency_max = 850000000, ++ .frequency_max = 865000000, + .frequency_step = 0, + }, + +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/dvb-usb-ids.h ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +@@ -51,6 +51,7 @@ + #define USB_VID_PINNACLE 0x2304 + #define USB_VID_PCTV 0x2013 + #define USB_VID_PIXELVIEW 0x1554 ++#define USB_VID_REALTEK 0x0bda + #define USB_VID_TECHNOTREND 0x0b48 + #define USB_VID_TERRATEC 0x0ccd + #define USB_VID_TELESTAR 0x10b9 +@@ -75,11 +76,14 @@ + #define USB_PID_AFATECH_AF9005 0x9020 + #define USB_PID_AFATECH_AF9015_9015 0x9015 + #define USB_PID_AFATECH_AF9015_9016 0x9016 ++#define USB_PID_AFATECH_AF9035 0x9035 ++#define USB_PID_AFATECH_AF9035_2 0x1001 + #define USB_PID_TREKSTOR_DVBT 0x901b + #define USB_VID_ALINK_DTU 0xf170 + #define USB_PID_ANSONIC_DVBT_USB 0x6000 + #define USB_PID_ANYSEE 0x861f + #define USB_PID_AZUREWAVE_AD_TU700 0x3237 ++#define USB_PID_AZUREWAVE_6007 0x0ccd + #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 + #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 + #define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 +@@ -125,6 +129,8 @@ + #define USB_PID_E3C_EC168_3 0xfffb + #define USB_PID_E3C_EC168_4 0x1001 + #define USB_PID_E3C_EC168_5 0x1002 ++#define USB_PID_FREECOM_DVBT 0x0160 ++#define USB_PID_FREECOM_DVBT_2 0x0161 + #define USB_PID_UNIWILL_STK7700P 0x6003 + #define USB_PID_GENIUS_TVGO_DVB_T03 0x4012 + #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 +@@ -148,6 +154,7 @@ + #define USB_PID_KWORLD_VSTREAM_WARM 0x17df + #define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055 + #define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2 0x0069 ++#define USB_PID_TERRATEC_CINERGY_T_STICK 0x0093 + #define USB_PID_TERRATEC_CINERGY_T_STICK_RC 0x0097 + #define USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC 0x0099 + #define USB_PID_TWINHAN_VP7041_COLD 0x3201 +@@ -217,6 +224,11 @@ + #define USB_PID_AVERMEDIA_A850T 0x850b + #define USB_PID_AVERMEDIA_A805 0xa805 + #define USB_PID_AVERMEDIA_A815M 0x815a ++#define USB_PID_AVERMEDIA_A835 0xa835 ++#define USB_PID_AVERMEDIA_B835 0xb835 ++#define USB_PID_AVERMEDIA_1867 0x1867 ++#define USB_PID_AVERMEDIA_A867 0xa867 ++#define USB_PID_AVERMEDIA_TWINSTAR 0x0825 + #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 + #define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d + #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a +@@ -226,6 +238,8 @@ + #define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062 + #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 + #define USB_PID_TERRATEC_CINERGY_T_XXS_2 0x00ab ++#define USB_PID_TERRATEC_H7 0x10b4 ++#define USB_PID_TERRATEC_H7_2 0x10a3 + #define USB_PID_TERRATEC_T3 0x10a0 + #define USB_PID_TERRATEC_T5 0x10a1 + #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e +@@ -249,6 +263,8 @@ + #define USB_PID_PCTV_400E 0x020f + #define USB_PID_PCTV_450E 0x0222 + #define USB_PID_PCTV_452E 0x021f ++#define USB_PID_REALTEK_RTL2831U 0x2831 ++#define USB_PID_REALTEK_RTL2832U 0x2832 + #define USB_PID_TECHNOTREND_CONNECT_S2_3600 0x3007 + #define USB_PID_TECHNOTREND_CONNECT_S2_3650_CI 0x300a + #define USB_PID_NEBULA_DIGITV 0x0201 +Index: linux-3.3.x86_64/drivers/media/dvb/ddbridge/ddbridge-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/ddbridge/ddbridge-core.c ++++ linux-3.3.x86_64/drivers/media/dvb/ddbridge/ddbridge-core.c +@@ -578,6 +578,7 @@ static int demod_attach_drxk(struct ddb_ + struct drxk_config config; + + memset(&config, 0, sizeof(config)); ++ config.microcode_name = "drxk_a3.mc"; + config.adr = 0x29 + (input->nr & 1); + + fe = input->fe = dvb_attach(drxk_attach, &config, i2c); +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/drxk_hard.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/drxk_hard.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/drxk_hard.c +@@ -28,7 +28,6 @@ + #include + #include + #include +-#include + #include + + #include "dvb_frontend.h" +@@ -91,10 +90,6 @@ bool IsA1WithRomCode(struct drxk_state * + #define DRXK_MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH (0x03) + #endif + +-#ifndef DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH +-#define DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH (0x06) +-#endif +- + #define DEFAULT_DRXK_MPEG_LOCK_TIMEOUT 700 + #define DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT 500 + +@@ -650,9 +645,6 @@ static int init_state(struct drxk_state + u32 ulQual83 = DEFAULT_MER_83; + u32 ulQual93 = DEFAULT_MER_93; + +- u32 ulDVBTStaticTSClock = 1; +- u32 ulDVBCStaticTSClock = 1; +- + u32 ulMpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; + u32 ulDemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; + +@@ -662,7 +654,6 @@ static int init_state(struct drxk_state + u32 ulGPIOCfg = 0x0113; + u32 ulInvertTSClock = 0; + u32 ulTSDataStrength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH; +- u32 ulTSClockkStrength = DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH; + u32 ulDVBTBitrate = 50000000; + u32 ulDVBCBitrate = DRXK_QAM_SYMBOLRATE_MAX * 8; + +@@ -815,8 +806,7 @@ static int init_state(struct drxk_state + state->m_invertSTR = false; /* If TRUE; invert STR signals */ + state->m_invertVAL = false; /* If TRUE; invert VAL signals */ + state->m_invertCLK = (ulInvertTSClock != 0); /* If TRUE; invert CLK signals */ +- state->m_DVBTStaticCLK = (ulDVBTStaticTSClock != 0); +- state->m_DVBCStaticCLK = (ulDVBCStaticTSClock != 0); ++ + /* If TRUE; static MPEG clockrate will be used; + otherwise clockrate will adapt to the bitrate of the TS */ + +@@ -824,7 +814,6 @@ static int init_state(struct drxk_state + state->m_DVBCBitrate = ulDVBCBitrate; + + state->m_TSDataStrength = (ulTSDataStrength & 0x07); +- state->m_TSClockkStrength = (ulTSClockkStrength & 0x07); + + /* Maximum bitrate in b/s in case static clockrate is selected */ + state->m_mpegTsStaticBitrate = 19392658; +@@ -1189,6 +1178,7 @@ static int MPEGTSConfigurePins(struct dr + int status = -1; + u16 sioPdrMclkCfg = 0; + u16 sioPdrMdxCfg = 0; ++ u16 err_cfg = 0; + + dprintk(1, ": mpeg %s, %s mode\n", + mpegEnable ? "enable" : "disable", +@@ -1254,12 +1244,17 @@ static int MPEGTSConfigurePins(struct dr + status = write16(state, SIO_PDR_MSTRT_CFG__A, sioPdrMdxCfg); + if (status < 0) + goto error; +- status = write16(state, SIO_PDR_MERR_CFG__A, 0x0000); /* Disable */ ++ ++ if (state->enable_merr_cfg) ++ err_cfg = sioPdrMdxCfg; ++ ++ status = write16(state, SIO_PDR_MERR_CFG__A, err_cfg); + if (status < 0) + goto error; +- status = write16(state, SIO_PDR_MVAL_CFG__A, 0x0000); /* Disable */ ++ status = write16(state, SIO_PDR_MVAL_CFG__A, err_cfg); + if (status < 0) + goto error; ++ + if (state->m_enableParallel == true) { + /* paralel -> enable MD1 to MD7 */ + status = write16(state, SIO_PDR_MD1_CFG__A, sioPdrMdxCfg); +@@ -6070,9 +6065,7 @@ static int init_drxk(struct drxk_state * + if (status < 0) + goto error; + +- if (!state->microcode_name) +- load_microcode(state, "drxk_a3.mc"); +- else ++ if (state->microcode_name) + load_microcode(state, state->microcode_name); + + /* disable token-ring bus through OFDM block for possible ucode upload */ +@@ -6323,15 +6316,12 @@ static int drxk_get_tune_settings(struct + switch (p->delivery_system) { + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_C: ++ case SYS_DVBT: + sets->min_delay_ms = 3000; + sets->max_drift = 0; + sets->step_size = 0; + return 0; + default: +- /* +- * For DVB-T, let it use the default DVB core way, that is: +- * fepriv->step_size = fe->ops.info.frequency_stepsize * 2 +- */ + return -EINVAL; + } + } +@@ -6391,6 +6381,21 @@ struct dvb_frontend *drxk_attach(const s + state->antenna_gpio = config->antenna_gpio; + state->antenna_dvbt = config->antenna_dvbt; + state->m_ChunkSize = config->chunk_size; ++ state->enable_merr_cfg = config->enable_merr_cfg; ++ ++ if (config->dynamic_clk) { ++ state->m_DVBTStaticCLK = 0; ++ state->m_DVBCStaticCLK = 0; ++ } else { ++ state->m_DVBTStaticCLK = 1; ++ state->m_DVBCStaticCLK = 1; ++ } ++ ++ ++ if (config->mpeg_out_clk_strength) ++ state->m_TSClockkStrength = config->mpeg_out_clk_strength & 0x07; ++ else ++ state->m_TSClockkStrength = 0x06; + + if (config->parallel_ts) + state->m_enableParallel = true; +Index: linux-3.3.x86_64/drivers/media/dvb/ngene/ngene-cards.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/ngene/ngene-cards.c ++++ linux-3.3.x86_64/drivers/media/dvb/ngene/ngene-cards.c +@@ -216,6 +216,7 @@ static int demod_attach_drxk(struct ngen + struct drxk_config config; + + memset(&config, 0, sizeof(config)); ++ config.microcode_name = "drxk_a3.mc"; + config.adr = 0x29 + (chan->number ^ 2); + + chan->fe = dvb_attach(drxk_attach, &config, i2c); +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/drxk.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/drxk.h ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/drxk.h +@@ -7,15 +7,19 @@ + /** + * struct drxk_config - Configure the initial parameters for DRX-K + * +- * adr: I2C Address of the DRX-K +- * parallel_ts: true means that the device uses parallel TS, ++ * @adr: I2C Address of the DRX-K ++ * @parallel_ts: True means that the device uses parallel TS, + * Serial otherwise. +- * single_master: Device is on the single master mode +- * no_i2c_bridge: Don't switch the I2C bridge to talk with tuner +- * antenna_gpio: GPIO bit used to control the antenna +- * antenna_dvbt: GPIO bit for changing antenna to DVB-C. A value of 1 ++ * @dynamic_clk: True means that the clock will be dynamically ++ * adjusted. Static clock otherwise. ++ * @enable_merr_cfg: Enable SIO_PDR_PERR_CFG/SIO_PDR_MVAL_CFG. ++ * @single_master: Device is on the single master mode ++ * @no_i2c_bridge: Don't switch the I2C bridge to talk with tuner ++ * @antenna_gpio: GPIO bit used to control the antenna ++ * @antenna_dvbt: GPIO bit for changing antenna to DVB-C. A value of 1 + * means that 1=DVBC, 0 = DVBT. Zero means the opposite. +- * microcode_name: Name of the firmware file with the microcode ++ * @mpeg_out_clk_strength: DRXK Mpeg output clock drive strength. ++ * @microcode_name: Name of the firmware file with the microcode + * + * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is + * UIO-3. +@@ -25,11 +29,14 @@ struct drxk_config { + bool single_master; + bool no_i2c_bridge; + bool parallel_ts; ++ bool dynamic_clk; ++ bool enable_merr_cfg; + + bool antenna_dvbt; + u16 antenna_gpio; + +- int chunk_size; ++ u8 mpeg_out_clk_strength; ++ int chunk_size; + + const char *microcode_name; + }; +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/drxk_hard.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/drxk_hard.h ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/drxk_hard.h +@@ -332,6 +332,7 @@ struct drxk_state { + + u16 UIO_mask; /* Bits used by UIO */ + ++ bool enable_merr_cfg; + bool single_master; + bool no_i2c_bridge; + bool antenna_dvbt; +Index: linux-3.3.x86_64/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c ++++ linux-3.3.x86_64/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c +@@ -18,6 +18,8 @@ + */ + + static struct rc_map_table nec_terratec_cinergy_xs[] = { ++ ++ /* Terratec Grey IR, with most keys in orange */ + { 0x1441, KEY_HOME}, + { 0x1401, KEY_POWER2}, + +@@ -78,6 +80,56 @@ static struct rc_map_table nec_terratec_ + { 0x144e, KEY_REWIND}, + { 0x144f, KEY_FASTFORWARD}, + { 0x145c, KEY_NEXT}, ++ ++ /* Terratec Black IR, with most keys in black */ ++ { 0x04eb01, KEY_POWER2}, ++ ++ { 0x04eb02, KEY_1}, ++ { 0x04eb03, KEY_2}, ++ { 0x04eb04, KEY_3}, ++ { 0x04eb05, KEY_4}, ++ { 0x04eb06, KEY_5}, ++ { 0x04eb07, KEY_6}, ++ { 0x04eb08, KEY_7}, ++ { 0x04eb09, KEY_8}, ++ { 0x04eb0a, KEY_9}, ++ { 0x04eb0c, KEY_0}, ++ ++ { 0x04eb0b, KEY_TEXT}, /* TXT */ ++ { 0x04eb0d, KEY_REFRESH}, /* Refresh */ ++ ++ { 0x04eb0e, KEY_HOME}, ++ { 0x04eb0f, KEY_EPG}, ++ ++ { 0x04eb10, KEY_UP}, ++ { 0x04eb11, KEY_LEFT}, ++ { 0x04eb12, KEY_OK}, ++ { 0x04eb13, KEY_RIGHT}, ++ { 0x04eb14, KEY_DOWN}, ++ ++ { 0x04eb15, KEY_BACKSPACE}, ++ { 0x04eb16, KEY_INFO}, ++ ++ { 0x04eb17, KEY_RED}, ++ { 0x04eb18, KEY_GREEN}, ++ { 0x04eb19, KEY_YELLOW}, ++ { 0x04eb1a, KEY_BLUE}, ++ ++ { 0x04eb1c, KEY_VOLUMEUP}, ++ { 0x04eb1e, KEY_VOLUMEDOWN}, ++ ++ { 0x04eb1d, KEY_MUTE}, ++ ++ { 0x04eb1b, KEY_CHANNELUP}, ++ { 0x04eb1f, KEY_CHANNELDOWN}, ++ ++ { 0x04eb40, KEY_RECORD}, ++ { 0x04eb4c, KEY_PLAY}, ++ { 0x04eb58, KEY_PAUSE}, ++ ++ { 0x04eb54, KEY_REWIND}, ++ { 0x04eb48, KEY_STOP}, ++ { 0x04eb5c, KEY_NEXT}, + }; + + static struct rc_map_list nec_terratec_cinergy_xs_map = { +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/Kconfig +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/Kconfig ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/Kconfig +@@ -361,6 +361,14 @@ config DVB_USB_EC168 + help + Say Y here to support the E3C EC168 DVB-T USB2.0 receiver. + ++config DVB_USB_AZ6007 ++ tristate "AzureWave 6007 and clones DVB-T/C USB2.0 support" ++ depends on DVB_USB ++ select DVB_DRXK if !DVB_FE_CUSTOMISE ++ select MEDIA_TUNER_MT2063 if !DVB_FE_CUSTOMISE ++ help ++ Say Y here to support theAfatech AF9005 based DVB-T/DVB-C receivers. ++ + config DVB_USB_AZ6027 + tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support" + depends on DVB_USB +@@ -378,6 +386,7 @@ config DVB_USB_LME2510 + select DVB_IX2505V if !DVB_FE_CUSTOMISE + select DVB_STV0299 if !DVB_FE_CUSTOMISE + select DVB_PLL if !DVB_FE_CUSTOMISE ++ select DVB_M88RS2000 if !DVB_FE_CUSTOMISE + help + Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 . + +@@ -403,3 +412,25 @@ config DVB_USB_MXL111SF + select VIDEO_TVEEPROM + help + Say Y here to support the MxL111SF USB2.0 DTV receiver. ++ ++config DVB_USB_RTL28XXU ++ tristate "Realtek RTL28xxU DVB USB support" ++ depends on DVB_USB && EXPERIMENTAL ++ select DVB_RTL2830 ++ select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE ++ select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE ++ select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE ++ help ++ Say Y here to support the Realtek RTL28xxU DVB USB receiver. ++ ++config DVB_USB_AF9035 ++ tristate "Afatech AF9035 DVB-T USB2.0 support" ++ depends on DVB_USB ++ select DVB_AF9033 ++ select MEDIA_TUNER_TUA9001 if !MEDIA_TUNER_CUSTOMISE ++ select MEDIA_TUNER_FC0011 if !MEDIA_TUNER_CUSTOMISE ++ select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE ++ select MEDIA_TUNER_TDA18218 if !MEDIA_TUNER_CUSTOMISE ++ help ++ Say Y here to support the Afatech AF9035 based DVB USB receiver. ++ +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/Makefile ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/Makefile +@@ -54,7 +54,6 @@ obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb + dvb-usb-opera-objs = opera1.o + obj-$(CONFIG_DVB_USB_OPERA1) += dvb-usb-opera.o + +- + dvb-usb-af9005-objs = af9005.o af9005-fe.o + obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o + +@@ -88,6 +87,9 @@ obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-f + dvb-usb-ec168-objs = ec168.o + obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o + ++dvb-usb-az6007-objs = az6007.o ++obj-$(CONFIG_DVB_USB_AZ6007) += dvb-usb-az6007.o ++ + dvb-usb-az6027-objs = az6027.o + obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o + +@@ -105,8 +107,15 @@ obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-us + obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-demod.o + obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o + +-ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ ++dvb-usb-rtl28xxu-objs = rtl28xxu.o ++obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o ++ ++dvb-usb-af9035-objs = af9035.o ++obj-$(CONFIG_DVB_USB_AF9035) += dvb-usb-af9035.o ++ ++ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core ++ccflags-y += -I$(srctree)/drivers/media/dvb/frontends/ + # due to tuner-xc3028 +-ccflags-y += -Idrivers/media/common/tuners +-EXTRA_CFLAGS += -Idrivers/media/dvb/ttpci ++ccflags-y += -I$(srctree)/drivers/media/common/tuners ++ccflags-y += -I$(srctree)/drivers/media/dvb/ttpci + +Index: linux-3.3.x86_64/drivers/media/video/omap/omap_vout.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/omap/omap_vout.c ++++ linux-3.3.x86_64/drivers/media/video/omap/omap_vout.c +@@ -2268,13 +2268,12 @@ static struct platform_driver omap_vout_ + .driver = { + .name = VOUT_NAME, + }, +- .probe = omap_vout_probe, + .remove = omap_vout_remove, + }; + + static int __init omap_vout_init(void) + { +- if (platform_driver_register(&omap_vout_driver) != 0) { ++ if (platform_driver_probe(&omap_vout_driver, omap_vout_probe) != 0) { + printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n"); + return -EINVAL; + } +Index: linux-3.3.x86_64/Documentation/DocBook/media/v4l/compat.xml +=================================================================== +--- linux-3.3.x86_64.orig/Documentation/DocBook/media/v4l/compat.xml ++++ linux-3.3.x86_64/Documentation/DocBook/media/v4l/compat.xml +@@ -2393,6 +2393,10 @@ details. + to the User controls class. + + ++ ++ Added the device_caps field to struct v4l2_capabilities and added the new ++ V4L2_CAP_DEVICE_CAPS capability. ++ + + + +Index: linux-3.3.x86_64/Documentation/DocBook/media/v4l/v4l2.xml +=================================================================== +--- linux-3.3.x86_64.orig/Documentation/DocBook/media/v4l/v4l2.xml ++++ linux-3.3.x86_64/Documentation/DocBook/media/v4l/v4l2.xml +@@ -128,6 +128,13 @@ structs, ioctls) must be noted in more d + applications. --> + + ++ 3.3 ++ 2012-01-11 ++ hv ++ Added device_caps field to struct v4l2_capabilities. ++ ++ ++ + 3.2 + 2011-08-26 + hv +@@ -417,7 +424,7 @@ and discussions on the V4L mailing list. + + + Video for Linux Two API Specification +- Revision 3.2 ++ Revision 3.3 + + + &sub-common; +Index: linux-3.3.x86_64/Documentation/DocBook/media/v4l/vidioc-querycap.xml +=================================================================== +--- linux-3.3.x86_64.orig/Documentation/DocBook/media/v4l/vidioc-querycap.xml ++++ linux-3.3.x86_64/Documentation/DocBook/media/v4l/vidioc-querycap.xml +@@ -124,12 +124,35 @@ printf ("Version: %u.%u.%u\n", + + __u32 + capabilities +- Device capabilities, see . ++ Available capabilities of the physical device as a whole, see . The same physical device can export ++ multiple devices in /dev (e.g. /dev/videoX, /dev/vbiY and /dev/radioZ). ++ The capabilities field should contain a union ++ of all capabilities available around the several V4L2 devices exported ++ to userspace. ++ For all those devices the capabilities field ++ returns the same set of capabilities. This allows applications to open ++ just one of the devices (typically the video device) and discover whether ++ video, vbi and/or radio are also supported. ++ + + + __u32 +- reserved[4] ++ device_caps ++ Device capabilities of the opened device, see . Should contain the available capabilities ++ of that specific device node. So, for example, device_caps ++ of a radio device will only contain radio related capabilities and ++ no video or vbi capabilities. This field is only set if the capabilities ++ field contains the V4L2_CAP_DEVICE_CAPS capability. ++ Only the capabilities field can have the ++ V4L2_CAP_DEVICE_CAPS capability, device_caps ++ will never set V4L2_CAP_DEVICE_CAPS. ++ ++ ++ ++ __u32 ++ reserved[3] + Reserved for future extensions. Drivers must set + this array to zero. + +@@ -276,6 +299,13 @@ linkend="async">asynchronous I/O + The device supports the streaming I/O method. + ++ ++ V4L2_CAP_DEVICE_CAPS ++ 0x80000000 ++ The driver fills the device_caps ++ field. This capability can only appear in the capabilities ++ field and never in the device_caps field. ++ + + + +Index: linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-417.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx231xx/cx231xx-417.c ++++ linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-417.c +@@ -1686,7 +1686,6 @@ static struct v4l2_capability pvr_capabi + .capabilities = (V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | + V4L2_CAP_STREAMING | V4L2_CAP_READWRITE), +- .reserved = {0, 0, 0, 0} + }; + static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +Index: linux-3.3.x86_64/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/pvrusb2/pvrusb2-v4l2.c ++++ linux-3.3.x86_64/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +@@ -96,7 +96,6 @@ static struct v4l2_capability pvr_capabi + .capabilities = (V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | + V4L2_CAP_READWRITE), +- .reserved = {0,0,0,0} + }; + + static struct v4l2_fmtdesc pvr_fmtdesc [] = { +Index: linux-3.3.x86_64/drivers/media/video/v4l2-ioctl.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/v4l2-ioctl.c ++++ linux-3.3.x86_64/drivers/media/video/v4l2-ioctl.c +@@ -260,6 +260,8 @@ static const char *v4l2_ioctls[] = { + [_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD", + [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD", + ++ [_IOC_NR(VIDIOC_DECODER_CMD)] = "VIDIOC_DECODER_CMD", ++ [_IOC_NR(VIDIOC_TRY_DECODER_CMD)] = "VIDIOC_TRY_DECODER_CMD", + [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", + [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", + +@@ -540,10 +542,12 @@ static long __video_do_ioctl(struct file + if (!ret) + dbgarg(cmd, "driver=%s, card=%s, bus=%s, " + "version=0x%08x, " +- "capabilities=0x%08x\n", ++ "capabilities=0x%08x, " ++ "device_caps=0x%08x\n", + cap->driver, cap->card, cap->bus_info, + cap->version, +- cap->capabilities); ++ cap->capabilities, ++ cap->device_caps); + break; + } + +@@ -1762,6 +1766,32 @@ static long __video_do_ioctl(struct file + dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); + break; + } ++ case VIDIOC_DECODER_CMD: ++ { ++ struct v4l2_decoder_cmd *p = arg; ++ ++ if (!ops->vidioc_decoder_cmd) ++ break; ++ if (ret_prio) { ++ ret = ret_prio; ++ break; ++ } ++ ret = ops->vidioc_decoder_cmd(file, fh, p); ++ if (!ret) ++ dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); ++ break; ++ } ++ case VIDIOC_TRY_DECODER_CMD: ++ { ++ struct v4l2_decoder_cmd *p = arg; ++ ++ if (!ops->vidioc_try_decoder_cmd) ++ break; ++ ret = ops->vidioc_try_decoder_cmd(file, fh, p); ++ if (!ret) ++ dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); ++ break; ++ } + case VIDIOC_G_PARM: + { + struct v4l2_streamparm *p = arg; +@@ -1909,7 +1939,13 @@ static long __video_do_ioctl(struct file + { + if (!ops->vidioc_log_status) + break; ++ if (vfd->v4l2_dev) ++ pr_info("%s: ================= START STATUS =================\n", ++ vfd->v4l2_dev->name); + ret = ops->vidioc_log_status(file, fh); ++ if (vfd->v4l2_dev) ++ pr_info("%s: ================== END STATUS ==================\n", ++ vfd->v4l2_dev->name); + break; + } + #ifdef CONFIG_VIDEO_ADV_DEBUG +@@ -2419,7 +2455,7 @@ video_usercopy(struct file *file, unsign + /* Handles IOCTL */ + err = func(file, cmd, parg); + if (err == -ENOIOCTLCMD) +- err = -EINVAL; ++ err = -ENOTTY; + + if (has_array_args) { + *kernel_ptr = user_ptr; +Index: linux-3.3.x86_64/include/linux/videodev2.h +=================================================================== +--- linux-3.3.x86_64.orig/include/linux/videodev2.h ++++ linux-3.3.x86_64/include/linux/videodev2.h +@@ -235,16 +235,25 @@ struct v4l2_fract { + __u32 denominator; + }; + +-/* +- * D R I V E R C A P A B I L I T I E S +- */ ++/** ++ * struct v4l2_capability - Describes V4L2 device caps returned by VIDIOC_QUERYCAP ++ * ++ * @driver: name of the driver module (e.g. "bttv") ++ * @card: name of the card (e.g. "Hauppauge WinTV") ++ * @bus_info: name of the bus (e.g. "PCI:" + pci_name(pci_dev) ) ++ * @version: KERNEL_VERSION ++ * @capabilities: capabilities of the physical device as a whole ++ * @device_caps: capabilities accessed via this particular device (node) ++ * @reserved: reserved fields for future extensions ++ */ + struct v4l2_capability { +- __u8 driver[16]; /* i.e. "bttv" */ +- __u8 card[32]; /* i.e. "Hauppauge WinTV" */ +- __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */ +- __u32 version; /* should use KERNEL_VERSION() */ +- __u32 capabilities; /* Device capabilities */ +- __u32 reserved[4]; ++ __u8 driver[16]; ++ __u8 card[32]; ++ __u8 bus_info[32]; ++ __u32 version; ++ __u32 capabilities; ++ __u32 device_caps; ++ __u32 reserved[3]; + }; + + /* Values for 'capabilities' field */ +@@ -274,6 +283,8 @@ struct v4l2_capability { + #define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ + #define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */ + ++#define V4L2_CAP_DEVICE_CAPS 0x80000000 /* sets device capabilities field */ ++ + /* + * V I D E O I M A G E F O R M A T + */ +@@ -751,20 +762,20 @@ struct v4l2_crop { + + /* Selection targets */ + +-/* current cropping area */ +-#define V4L2_SEL_TGT_CROP_ACTIVE 0 +-/* default cropping area */ +-#define V4L2_SEL_TGT_CROP_DEFAULT 1 +-/* cropping bounds */ +-#define V4L2_SEL_TGT_CROP_BOUNDS 2 +-/* current composing area */ +-#define V4L2_SEL_TGT_COMPOSE_ACTIVE 256 +-/* default composing area */ +-#define V4L2_SEL_TGT_COMPOSE_DEFAULT 257 +-/* composing bounds */ +-#define V4L2_SEL_TGT_COMPOSE_BOUNDS 258 +-/* current composing area plus all padding pixels */ +-#define V4L2_SEL_TGT_COMPOSE_PADDED 259 ++/* Current cropping area */ ++#define V4L2_SEL_TGT_CROP_ACTIVE 0x0000 ++/* Default cropping area */ ++#define V4L2_SEL_TGT_CROP_DEFAULT 0x0001 ++/* Cropping bounds */ ++#define V4L2_SEL_TGT_CROP_BOUNDS 0x0002 ++/* Current composing area */ ++#define V4L2_SEL_TGT_COMPOSE_ACTIVE 0x0100 ++/* Default composing area */ ++#define V4L2_SEL_TGT_COMPOSE_DEFAULT 0x0101 ++/* Composing bounds */ ++#define V4L2_SEL_TGT_COMPOSE_BOUNDS 0x0102 ++/* Current composing area plus all padding pixels */ ++#define V4L2_SEL_TGT_COMPOSE_PADDED 0x0103 + + /** + * struct v4l2_selection - selection info +@@ -774,7 +785,7 @@ struct v4l2_crop { + * @r: coordinates of selection window + * @reserved: for future use, rounds structure size to 64 bytes, set to zero + * +- * Hardware may use multiple helper window to process a video stream. ++ * Hardware may use multiple helper windows to process a video stream. + * The structure is used to exchange this selection areas between + * an application and a driver. + */ +@@ -1125,6 +1136,7 @@ struct v4l2_ext_controls { + #define V4L2_CTRL_CLASS_CAMERA 0x009a0000 /* Camera class controls */ + #define V4L2_CTRL_CLASS_FM_TX 0x009b0000 /* FM Modulator control class */ + #define V4L2_CTRL_CLASS_FLASH 0x009c0000 /* Camera flash controls */ ++#define V4L2_CTRL_CLASS_JPEG 0x009d0000 /* JPEG-compression controls */ + + #define V4L2_CTRL_ID_MASK (0x0fffffff) + #define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) +@@ -1396,6 +1408,16 @@ enum v4l2_mpeg_audio_ac3_bitrate { + V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17, + V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18, + }; ++#define V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK (V4L2_CID_MPEG_BASE+112) ++enum v4l2_mpeg_audio_dec_playback { ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO = 0, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO = 1, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT = 2, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_RIGHT = 3, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_MONO = 4, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO = 5, ++}; ++#define V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK (V4L2_CID_MPEG_BASE+113) + + /* MPEG video controls specific to multiplexed streams */ + #define V4L2_CID_MPEG_VIDEO_ENCODING (V4L2_CID_MPEG_BASE+200) +@@ -1446,6 +1468,9 @@ enum v4l2_mpeg_video_multi_slice_mode { + V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES = 2, + }; + #define V4L2_CID_MPEG_VIDEO_VBV_SIZE (V4L2_CID_MPEG_BASE+222) ++#define V4L2_CID_MPEG_VIDEO_DEC_PTS (V4L2_CID_MPEG_BASE+223) ++#define V4L2_CID_MPEG_VIDEO_DEC_FRAME (V4L2_CID_MPEG_BASE+224) ++ + #define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP (V4L2_CID_MPEG_BASE+300) + #define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP (V4L2_CID_MPEG_BASE+301) + #define V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP (V4L2_CID_MPEG_BASE+302) +@@ -1734,6 +1759,29 @@ enum v4l2_flash_strobe_source { + #define V4L2_CID_FLASH_CHARGE (V4L2_CID_FLASH_CLASS_BASE + 11) + #define V4L2_CID_FLASH_READY (V4L2_CID_FLASH_CLASS_BASE + 12) + ++/* JPEG-class control IDs defined by V4L2 */ ++#define V4L2_CID_JPEG_CLASS_BASE (V4L2_CTRL_CLASS_JPEG | 0x900) ++#define V4L2_CID_JPEG_CLASS (V4L2_CTRL_CLASS_JPEG | 1) ++ ++#define V4L2_CID_JPEG_CHROMA_SUBSAMPLING (V4L2_CID_JPEG_CLASS_BASE + 1) ++enum v4l2_jpeg_chroma_subsampling { ++ V4L2_JPEG_CHROMA_SUBSAMPLING_444 = 0, ++ V4L2_JPEG_CHROMA_SUBSAMPLING_422 = 1, ++ V4L2_JPEG_CHROMA_SUBSAMPLING_420 = 2, ++ V4L2_JPEG_CHROMA_SUBSAMPLING_411 = 3, ++ V4L2_JPEG_CHROMA_SUBSAMPLING_410 = 4, ++ V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY = 5, ++}; ++#define V4L2_CID_JPEG_RESTART_INTERVAL (V4L2_CID_JPEG_CLASS_BASE + 2) ++#define V4L2_CID_JPEG_COMPRESSION_QUALITY (V4L2_CID_JPEG_CLASS_BASE + 3) ++ ++#define V4L2_CID_JPEG_ACTIVE_MARKER (V4L2_CID_JPEG_CLASS_BASE + 4) ++#define V4L2_JPEG_ACTIVE_MARKER_APP0 (1 << 0) ++#define V4L2_JPEG_ACTIVE_MARKER_APP1 (1 << 1) ++#define V4L2_JPEG_ACTIVE_MARKER_COM (1 << 16) ++#define V4L2_JPEG_ACTIVE_MARKER_DQT (1 << 17) ++#define V4L2_JPEG_ACTIVE_MARKER_DHT (1 << 18) ++ + /* + * T U N I N G + */ +@@ -1897,6 +1945,54 @@ struct v4l2_encoder_cmd { + }; + }; + ++/* Decoder commands */ ++#define V4L2_DEC_CMD_START (0) ++#define V4L2_DEC_CMD_STOP (1) ++#define V4L2_DEC_CMD_PAUSE (2) ++#define V4L2_DEC_CMD_RESUME (3) ++ ++/* Flags for V4L2_DEC_CMD_START */ ++#define V4L2_DEC_CMD_START_MUTE_AUDIO (1 << 0) ++ ++/* Flags for V4L2_DEC_CMD_PAUSE */ ++#define V4L2_DEC_CMD_PAUSE_TO_BLACK (1 << 0) ++ ++/* Flags for V4L2_DEC_CMD_STOP */ ++#define V4L2_DEC_CMD_STOP_TO_BLACK (1 << 0) ++#define V4L2_DEC_CMD_STOP_IMMEDIATELY (1 << 1) ++ ++/* Play format requirements (returned by the driver): */ ++ ++/* The decoder has no special format requirements */ ++#define V4L2_DEC_START_FMT_NONE (0) ++/* The decoder requires full GOPs */ ++#define V4L2_DEC_START_FMT_GOP (1) ++ ++/* The structure must be zeroed before use by the application ++ This ensures it can be extended safely in the future. */ ++struct v4l2_decoder_cmd { ++ __u32 cmd; ++ __u32 flags; ++ union { ++ struct { ++ __u64 pts; ++ } stop; ++ ++ struct { ++ /* 0 or 1000 specifies normal speed, ++ 1 specifies forward single stepping, ++ -1 specifies backward single stepping, ++ >1: playback at speed/1000 of the normal speed, ++ <-1: reverse playback at (-speed/1000) of the normal speed. */ ++ __s32 speed; ++ __u32 format; ++ } start; ++ ++ struct { ++ __u32 data[16]; ++ } raw; ++ }; ++}; + #endif + + +@@ -2307,6 +2403,11 @@ struct v4l2_create_buffers { + #define VIDIOC_G_SELECTION _IOWR('V', 94, struct v4l2_selection) + #define VIDIOC_S_SELECTION _IOWR('V', 95, struct v4l2_selection) + ++/* Experimental, these two ioctls may change over the next couple of kernel ++ versions. */ ++#define VIDIOC_DECODER_CMD _IOWR('V', 96, struct v4l2_decoder_cmd) ++#define VIDIOC_TRY_DECODER_CMD _IOWR('V', 97, struct v4l2_decoder_cmd) ++ + /* Reminder: when adding new ioctls please add support for them to + drivers/media/video/v4l2-compat-ioctl32.c as well! */ + +Index: linux-3.3.x86_64/drivers/media/video/vivi.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/vivi.c ++++ linux-3.3.x86_64/drivers/media/video/vivi.c +@@ -819,8 +819,9 @@ static int vidioc_querycap(struct file * + strcpy(cap->driver, "vivi"); + strcpy(cap->card, "vivi"); + strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); +- cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \ ++ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; ++ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; + } + +@@ -958,14 +959,6 @@ static int vidioc_streamoff(struct file + return vb2_streamoff(&dev->vb_vidq, i); + } + +-static int vidioc_log_status(struct file *file, void *priv) +-{ +- struct vivi_dev *dev = video_drvdata(file); +- +- v4l2_ctrl_handler_log_status(&dev->ctrl_handler, dev->v4l2_dev.name); +- return 0; +-} +- + static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) + { + return 0; +@@ -1008,17 +1001,6 @@ static int vidioc_s_input(struct file *f + return 0; + } + +-static int vidioc_subscribe_event(struct v4l2_fh *fh, +- struct v4l2_event_subscription *sub) +-{ +- switch (sub->type) { +- case V4L2_EVENT_CTRL: +- return v4l2_event_subscribe(fh, sub, 0); +- default: +- return -EINVAL; +- } +-} +- + /* --- controls ---------------------------------------------- */ + + static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl) +@@ -1057,17 +1039,10 @@ static unsigned int + vivi_poll(struct file *file, struct poll_table_struct *wait) + { + struct vivi_dev *dev = video_drvdata(file); +- struct v4l2_fh *fh = file->private_data; + struct vb2_queue *q = &dev->vb_vidq; +- unsigned int res; + + dprintk(dev, 1, "%s\n", __func__); +- res = vb2_poll(q, file, wait); +- if (v4l2_event_pending(fh)) +- res |= POLLPRI; +- else +- poll_wait(file, &fh->wait, wait); +- return res; ++ return vb2_poll(q, file, wait); + } + + static int vivi_close(struct file *file) +@@ -1209,8 +1184,8 @@ static const struct v4l2_ioctl_ops vivi_ + .vidioc_s_input = vidioc_s_input, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, +- .vidioc_log_status = vidioc_log_status, +- .vidioc_subscribe_event = vidioc_subscribe_event, ++ .vidioc_log_status = v4l2_ctrl_log_status, ++ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + }; + +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-driver.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-driver.h ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-driver.h +@@ -331,6 +331,7 @@ struct ivtv_stream { + struct ivtv *itv; /* for ease of use */ + const char *name; /* name of the stream */ + int type; /* stream type */ ++ u32 caps; /* V4L2 capabilities */ + + struct v4l2_fh *fh; /* pointer to the streaming filehandle */ + spinlock_t qlock; /* locks access to the queues */ +@@ -630,6 +631,16 @@ struct ivtv { + + struct v4l2_device v4l2_dev; + struct cx2341x_handler cxhdl; ++ struct { ++ /* PTS/Frame count control cluster */ ++ struct v4l2_ctrl *ctrl_pts; ++ struct v4l2_ctrl *ctrl_frame; ++ }; ++ struct { ++ /* Audio Playback control cluster */ ++ struct v4l2_ctrl *ctrl_audio_playback; ++ struct v4l2_ctrl *ctrl_audio_multilingual_playback; ++ }; + struct v4l2_ctrl_handler hdl_gpio; + struct v4l2_subdev sd_gpio; /* GPIO sub-device */ + u16 instance; +@@ -649,7 +660,6 @@ struct ivtv { + u8 audio_stereo_mode; /* decoder setting how to handle stereo MPEG audio */ + u8 audio_bilingual_mode; /* decoder setting how to handle bilingual MPEG audio */ + +- + /* Locking */ + spinlock_t lock; /* lock access to this struct */ + struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */ +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-ioctl.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-ioctl.c ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-ioctl.c +@@ -246,34 +246,40 @@ static int ivtv_validate_speed(int cur_s + } + + static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, +- struct video_command *vc, int try) ++ struct v4l2_decoder_cmd *dc, int try) + { + struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; + + if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) + return -EINVAL; + +- switch (vc->cmd) { +- case VIDEO_CMD_PLAY: { +- vc->flags = 0; +- vc->play.speed = ivtv_validate_speed(itv->speed, vc->play.speed); +- if (vc->play.speed < 0) +- vc->play.format = VIDEO_PLAY_FMT_GOP; ++ switch (dc->cmd) { ++ case V4L2_DEC_CMD_START: { ++ dc->flags &= V4L2_DEC_CMD_START_MUTE_AUDIO; ++ dc->start.speed = ivtv_validate_speed(itv->speed, dc->start.speed); ++ if (dc->start.speed < 0) ++ dc->start.format = V4L2_DEC_START_FMT_GOP; ++ else ++ dc->start.format = V4L2_DEC_START_FMT_NONE; ++ if (dc->start.speed != 500 && dc->start.speed != 1500) ++ dc->flags = dc->start.speed == 1000 ? 0 : ++ V4L2_DEC_CMD_START_MUTE_AUDIO; + if (try) break; + ++ itv->speed_mute_audio = dc->flags & V4L2_DEC_CMD_START_MUTE_AUDIO; + if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG) + return -EBUSY; + if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) { + /* forces ivtv_set_speed to be called */ + itv->speed = 0; + } +- return ivtv_start_decoding(id, vc->play.speed); ++ return ivtv_start_decoding(id, dc->start.speed); + } + +- case VIDEO_CMD_STOP: +- vc->flags &= VIDEO_CMD_STOP_IMMEDIATELY|VIDEO_CMD_STOP_TO_BLACK; +- if (vc->flags & VIDEO_CMD_STOP_IMMEDIATELY) +- vc->stop.pts = 0; ++ case V4L2_DEC_CMD_STOP: ++ dc->flags &= V4L2_DEC_CMD_STOP_IMMEDIATELY | V4L2_DEC_CMD_STOP_TO_BLACK; ++ if (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) ++ dc->stop.pts = 0; + if (try) break; + if (atomic_read(&itv->decoding) == 0) + return 0; +@@ -281,22 +287,22 @@ static int ivtv_video_command(struct ivt + return -EBUSY; + + itv->output_mode = OUT_NONE; +- return ivtv_stop_v4l2_decode_stream(s, vc->flags, vc->stop.pts); ++ return ivtv_stop_v4l2_decode_stream(s, dc->flags, dc->stop.pts); + +- case VIDEO_CMD_FREEZE: +- vc->flags &= VIDEO_CMD_FREEZE_TO_BLACK; ++ case V4L2_DEC_CMD_PAUSE: ++ dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK; + if (try) break; + if (itv->output_mode != OUT_MPG) + return -EBUSY; + if (atomic_read(&itv->decoding) > 0) { + ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, +- (vc->flags & VIDEO_CMD_FREEZE_TO_BLACK) ? 1 : 0); ++ (dc->flags & V4L2_DEC_CMD_PAUSE_TO_BLACK) ? 1 : 0); + set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); + } + break; + +- case VIDEO_CMD_CONTINUE: +- vc->flags = 0; ++ case V4L2_DEC_CMD_RESUME: ++ dc->flags = 0; + if (try) break; + if (itv->output_mode != OUT_MPG) + return -EBUSY; +@@ -754,12 +760,15 @@ static int ivtv_s_register(struct file * + + static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap) + { +- struct ivtv *itv = fh2id(fh)->itv; ++ struct ivtv_open_id *id = fh2id(file->private_data); ++ struct ivtv *itv = id->itv; ++ struct ivtv_stream *s = &itv->streams[id->type]; + + strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); + strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); + snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev)); +- vcap->capabilities = itv->v4l2_cap; /* capabilities */ ++ vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS; ++ vcap->device_caps = s->caps; + return 0; + } + +@@ -1476,8 +1485,6 @@ static int ivtv_log_status(struct file * + struct v4l2_audio audin; + int i; + +- IVTV_INFO("================= START STATUS CARD #%d =================\n", +- itv->instance); + IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name); + if (itv->hw_flags & IVTV_HW_TVEEPROM) { + struct tveeprom tv; +@@ -1501,13 +1508,6 @@ static int ivtv_log_status(struct file * + "YUV Frames", + "Passthrough", + }; +- static const char * const audio_modes[5] = { +- "Stereo", +- "Left", +- "Right", +- "Mono", +- "Swapped" +- }; + static const char * const alpha_mode[4] = { + "None", + "Global", +@@ -1536,9 +1536,6 @@ static int ivtv_log_status(struct file * + ivtv_get_output(itv, itv->active_output, &vidout); + ivtv_get_audio_output(itv, 0, &audout); + IVTV_INFO("Video Output: %s\n", vidout.name); +- IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name, +- audio_modes[itv->audio_stereo_mode], +- audio_modes[itv->audio_bilingual_mode]); + if (mode < 0 || mode > OUT_PASSTHROUGH) + mode = OUT_NONE; + IVTV_INFO("Output Mode: %s\n", output_modes[mode]); +@@ -1566,12 +1563,27 @@ static int ivtv_log_status(struct file * + IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", + (long long)itv->mpg_data_received, + (long long)itv->vbi_data_inserted); +- IVTV_INFO("================== END STATUS CARD #%d ==================\n", +- itv->instance); +- + return 0; + } + ++static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) ++{ ++ struct ivtv_open_id *id = fh2id(file->private_data); ++ struct ivtv *itv = id->itv; ++ ++ IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd); ++ return ivtv_video_command(itv, id, dec, false); ++} ++ ++static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) ++{ ++ struct ivtv_open_id *id = fh2id(file->private_data); ++ struct ivtv *itv = id->itv; ++ ++ IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n", dec->cmd); ++ return ivtv_video_command(itv, id, dec, true); ++} ++ + static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) + { + struct ivtv_open_id *id = fh2id(filp->private_data); +@@ -1605,9 +1617,15 @@ static int ivtv_decoder_ioctls(struct fi + return ivtv_yuv_prep_frame(itv, args); + } + ++ case IVTV_IOC_PASSTHROUGH_MODE: ++ IVTV_DEBUG_IOCTL("IVTV_IOC_PASSTHROUGH_MODE\n"); ++ if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) ++ return -EINVAL; ++ return ivtv_passthrough_mode(itv, *(int *)arg != 0); ++ + case VIDEO_GET_PTS: { +- u32 data[CX2341X_MBOX_MAX_DATA]; +- u64 *pts = arg; ++ s64 *pts = arg; ++ s64 frame; + + IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n"); + if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { +@@ -1616,29 +1634,12 @@ static int ivtv_decoder_ioctls(struct fi + } + if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) + return -EINVAL; +- +- if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { +- *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) | +- (u64)itv->last_dec_timing[1]; +- break; +- } +- *pts = 0; +- if (atomic_read(&itv->decoding)) { +- if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { +- IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); +- return -EIO; +- } +- memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); +- set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); +- *pts = (u64) ((u64) data[2] << 32) | (u64) data[1]; +- /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/ +- } +- break; ++ return ivtv_g_pts_frame(itv, pts, &frame); + } + + case VIDEO_GET_FRAME_COUNT: { +- u32 data[CX2341X_MBOX_MAX_DATA]; +- u64 *frame = arg; ++ s64 *frame = arg; ++ s64 pts; + + IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n"); + if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { +@@ -1647,71 +1648,58 @@ static int ivtv_decoder_ioctls(struct fi + } + if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) + return -EINVAL; +- +- if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { +- *frame = itv->last_dec_timing[0]; +- break; +- } +- *frame = 0; +- if (atomic_read(&itv->decoding)) { +- if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { +- IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); +- return -EIO; +- } +- memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); +- set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); +- *frame = data[0]; +- } +- break; ++ return ivtv_g_pts_frame(itv, &pts, frame); + } + + case VIDEO_PLAY: { +- struct video_command vc; ++ struct v4l2_decoder_cmd dc; + + IVTV_DEBUG_IOCTL("VIDEO_PLAY\n"); +- memset(&vc, 0, sizeof(vc)); +- vc.cmd = VIDEO_CMD_PLAY; +- return ivtv_video_command(itv, id, &vc, 0); ++ memset(&dc, 0, sizeof(dc)); ++ dc.cmd = V4L2_DEC_CMD_START; ++ return ivtv_video_command(itv, id, &dc, 0); + } + + case VIDEO_STOP: { +- struct video_command vc; ++ struct v4l2_decoder_cmd dc; + + IVTV_DEBUG_IOCTL("VIDEO_STOP\n"); +- memset(&vc, 0, sizeof(vc)); +- vc.cmd = VIDEO_CMD_STOP; +- vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY; +- return ivtv_video_command(itv, id, &vc, 0); ++ memset(&dc, 0, sizeof(dc)); ++ dc.cmd = V4L2_DEC_CMD_STOP; ++ dc.flags = V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY; ++ return ivtv_video_command(itv, id, &dc, 0); + } + + case VIDEO_FREEZE: { +- struct video_command vc; ++ struct v4l2_decoder_cmd dc; + + IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n"); +- memset(&vc, 0, sizeof(vc)); +- vc.cmd = VIDEO_CMD_FREEZE; +- return ivtv_video_command(itv, id, &vc, 0); ++ memset(&dc, 0, sizeof(dc)); ++ dc.cmd = V4L2_DEC_CMD_PAUSE; ++ return ivtv_video_command(itv, id, &dc, 0); + } + + case VIDEO_CONTINUE: { +- struct video_command vc; ++ struct v4l2_decoder_cmd dc; + + IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n"); +- memset(&vc, 0, sizeof(vc)); +- vc.cmd = VIDEO_CMD_CONTINUE; +- return ivtv_video_command(itv, id, &vc, 0); ++ memset(&dc, 0, sizeof(dc)); ++ dc.cmd = V4L2_DEC_CMD_RESUME; ++ return ivtv_video_command(itv, id, &dc, 0); + } + + case VIDEO_COMMAND: + case VIDEO_TRY_COMMAND: { +- struct video_command *vc = arg; ++ /* Note: struct v4l2_decoder_cmd has the same layout as ++ struct video_command */ ++ struct v4l2_decoder_cmd *dc = arg; + int try = (cmd == VIDEO_TRY_COMMAND); + + if (try) +- IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd); ++ IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", dc->cmd); + else +- IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd); +- return ivtv_video_command(itv, id, vc, try); ++ IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", dc->cmd); ++ return ivtv_video_command(itv, id, dc, try); + } + + case VIDEO_GET_EVENT: { +@@ -1775,17 +1763,13 @@ static int ivtv_decoder_ioctls(struct fi + IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n"); + if (iarg > AUDIO_STEREO_SWAPPED) + return -EINVAL; +- itv->audio_stereo_mode = iarg; +- ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); +- return 0; ++ return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg + 1); + + case AUDIO_BILINGUAL_CHANNEL_SELECT: + IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); + if (iarg > AUDIO_STEREO_SWAPPED) + return -EINVAL; +- itv->audio_bilingual_mode = iarg; +- ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); +- return 0; ++ return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg + 1); + + default: + return -EINVAL; +@@ -1800,6 +1784,7 @@ static long ivtv_default(struct file *fi + + if (!valid_prio) { + switch (cmd) { ++ case IVTV_IOC_PASSTHROUGH_MODE: + case VIDEO_PLAY: + case VIDEO_STOP: + case VIDEO_FREEZE: +@@ -1825,6 +1810,7 @@ static long ivtv_default(struct file *fi + } + + case IVTV_IOC_DMA_FRAME: ++ case IVTV_IOC_PASSTHROUGH_MODE: + case VIDEO_GET_PTS: + case VIDEO_GET_FRAME_COUNT: + case VIDEO_GET_EVENT: +@@ -1889,6 +1875,8 @@ static const struct v4l2_ioctl_ops ivtv_ + .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap, + .vidioc_encoder_cmd = ivtv_encoder_cmd, + .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd, ++ .vidioc_decoder_cmd = ivtv_decoder_cmd, ++ .vidioc_try_decoder_cmd = ivtv_try_decoder_cmd, + .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out, + .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap, + .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap, +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-streams.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-streams.c ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-streams.c +@@ -78,60 +78,73 @@ static struct { + int num_offset; + int dma, pio; + enum v4l2_buf_type buf_type; ++ u32 v4l2_caps; + const struct v4l2_file_operations *fops; + } ivtv_stream_info[] = { + { /* IVTV_ENC_STREAM_TYPE_MPG */ + "encoder MPG", + VFL_TYPE_GRABBER, 0, + PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, ++ V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | ++ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, + &ivtv_v4l2_enc_fops + }, + { /* IVTV_ENC_STREAM_TYPE_YUV */ + "encoder YUV", + VFL_TYPE_GRABBER, IVTV_V4L2_ENC_YUV_OFFSET, + PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, ++ V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | ++ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, + &ivtv_v4l2_enc_fops + }, + { /* IVTV_ENC_STREAM_TYPE_VBI */ + "encoder VBI", + VFL_TYPE_VBI, 0, + PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VBI_CAPTURE, ++ V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_TUNER | ++ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, + &ivtv_v4l2_enc_fops + }, + { /* IVTV_ENC_STREAM_TYPE_PCM */ + "encoder PCM", + VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET, + PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_PRIVATE, ++ V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, + &ivtv_v4l2_enc_fops + }, + { /* IVTV_ENC_STREAM_TYPE_RAD */ + "encoder radio", + VFL_TYPE_RADIO, 0, + PCI_DMA_NONE, 1, V4L2_BUF_TYPE_PRIVATE, ++ V4L2_CAP_RADIO | V4L2_CAP_TUNER, + &ivtv_v4l2_enc_fops + }, + { /* IVTV_DEC_STREAM_TYPE_MPG */ + "decoder MPG", + VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET, + PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, ++ V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, + &ivtv_v4l2_dec_fops + }, + { /* IVTV_DEC_STREAM_TYPE_VBI */ + "decoder VBI", + VFL_TYPE_VBI, IVTV_V4L2_DEC_VBI_OFFSET, + PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_CAPTURE, ++ V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_READWRITE, + &ivtv_v4l2_enc_fops + }, + { /* IVTV_DEC_STREAM_TYPE_VOUT */ + "decoder VOUT", + VFL_TYPE_VBI, IVTV_V4L2_DEC_VOUT_OFFSET, + PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_OUTPUT, ++ V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, + &ivtv_v4l2_dec_fops + }, + { /* IVTV_DEC_STREAM_TYPE_YUV */ + "decoder YUV", + VFL_TYPE_GRABBER, IVTV_V4L2_DEC_YUV_OFFSET, + PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, ++ V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, + &ivtv_v4l2_dec_fops + } + }; +@@ -149,6 +162,7 @@ static void ivtv_stream_init(struct ivtv + s->itv = itv; + s->type = type; + s->name = ivtv_stream_info[type].name; ++ s->caps = ivtv_stream_info[type].v4l2_caps; + + if (ivtv_stream_info[type].pio) + s->dma = PCI_DMA_NONE; +@@ -209,8 +223,8 @@ static int ivtv_prep_dev(struct ivtv *it + + s->vdev->num = num; + s->vdev->v4l2_dev = &itv->v4l2_dev; +- s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler; + s->vdev->fops = ivtv_stream_info[type].fops; ++ s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler; + s->vdev->release = video_device_release; + s->vdev->tvnorms = V4L2_STD_ALL; + s->vdev->lock = &itv->serialize_lock; +@@ -891,7 +905,7 @@ int ivtv_stop_v4l2_decode_stream(struct + IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags); + + /* Stop Decoder */ +- if (!(flags & VIDEO_CMD_STOP_IMMEDIATELY) || pts) { ++ if (!(flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) || pts) { + u32 tmp = 0; + + /* Wait until the decoder is no longer running */ +@@ -911,7 +925,7 @@ int ivtv_stop_v4l2_decode_stream(struct + break; + } + } +- ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & VIDEO_CMD_STOP_TO_BLACK, 0, 0); ++ ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & V4L2_DEC_CMD_STOP_TO_BLACK, 0, 0); + + /* turn off notification of dual/stereo mode change */ + ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1); +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/it913x.c ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c +@@ -64,6 +64,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr + struct it913x_state { + u8 id; + struct ite_config it913x_config; ++ u8 pid_filter_onoff; + }; + + struct ite_config it913x_config; +@@ -237,12 +238,27 @@ static int it913x_read_reg(struct usb_de + + static u32 it913x_query(struct usb_device *udev, u8 pro) + { +- int ret; ++ int ret, i; + u8 data[4]; +- ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ, +- 0x1222, 0, &data[0], 3); ++ u8 ver; ++ ++ for (i = 0; i < 5; i++) { ++ ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ, ++ 0x1222, 0, &data[0], 3); ++ ver = data[0]; ++ if (ver > 0 && ver < 3) ++ break; ++ msleep(100); ++ } + +- it913x_config.chip_ver = data[0]; ++ if (ver < 1 || ver > 2) { ++ info("Failed to identify chip version applying 1"); ++ it913x_config.chip_ver = 0x1; ++ it913x_config.chip_type = 0x9135; ++ return 0; ++ } ++ ++ it913x_config.chip_ver = ver; + it913x_config.chip_type = (u16)(data[2] << 8) + data[1]; + + info("Chip Version=%02x Chip Type=%04x", it913x_config.chip_ver, +@@ -259,15 +275,16 @@ static u32 it913x_query(struct usb_devic + + static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) + { ++ struct it913x_state *st = adap->dev->priv; + struct usb_device *udev = adap->dev->udev; + int ret; + u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; + +- if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) +- return -EAGAIN; ++ mutex_lock(&adap->dev->i2c_mutex); ++ + deb_info(1, "PID_C (%02x)", onoff); + +- ret = it913x_wr_reg(udev, pro, PID_EN, onoff); ++ ret = it913x_wr_reg(udev, pro, PID_EN, st->pid_filter_onoff); + + mutex_unlock(&adap->dev->i2c_mutex); + return ret; +@@ -276,12 +293,13 @@ static int it913x_pid_filter_ctrl(struct + static int it913x_pid_filter(struct dvb_usb_adapter *adap, + int index, u16 pid, int onoff) + { ++ struct it913x_state *st = adap->dev->priv; + struct usb_device *udev = adap->dev->udev; + int ret; + u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; + +- if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) +- return -EAGAIN; ++ mutex_lock(&adap->dev->i2c_mutex); ++ + deb_info(1, "PID_F (%02x)", onoff); + + ret = it913x_wr_reg(udev, pro, PID_LSB, (u8)(pid & 0xff)); +@@ -292,6 +310,13 @@ static int it913x_pid_filter(struct dvb_ + + ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f)); + ++ if (udev->speed == USB_SPEED_HIGH && pid == 0x2000) { ++ ret |= it913x_wr_reg(udev, pro, PID_EN, !onoff); ++ st->pid_filter_onoff = !onoff; ++ } else ++ st->pid_filter_onoff = ++ adap->fe_adap[adap->active_fe].pid_filtering; ++ + mutex_unlock(&adap->dev->i2c_mutex); + return 0; + } +@@ -316,8 +341,8 @@ static int it913x_i2c_xfer(struct i2c_ad + int ret; + u32 reg; + u8 pro; +- if (mutex_lock_interruptible(&d->i2c_mutex) < 0) +- return -EAGAIN; ++ ++ mutex_lock(&d->i2c_mutex); + + debug_data_snipet(1, "Message out", msg[0].buf); + deb_info(2, "num of messages %d address %02x", num, msg[0].addr); +@@ -358,8 +383,7 @@ static int it913x_rc_query(struct dvb_us + int ret; + u32 key; + /* Avoid conflict with frontends*/ +- if (mutex_lock_interruptible(&d->i2c_mutex) < 0) +- return -EAGAIN; ++ mutex_lock(&d->i2c_mutex); + + ret = it913x_io(d->udev, READ_LONG, PRO_LINK, CMD_IR_GET, + 0, 0, &ibuf[0], sizeof(ibuf)); +@@ -388,19 +412,12 @@ static int ite_firmware_select(struct us + { + int sw; + /* auto switch */ +- if (le16_to_cpu(udev->descriptor.idProduct) == +- USB_PID_ITETECH_IT9135) +- sw = IT9135_V1_FW; +- else if (le16_to_cpu(udev->descriptor.idProduct) == +- USB_PID_ITETECH_IT9135_9005) ++ if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_KWORLD_2) ++ sw = IT9137_FW; ++ else if (it913x_config.chip_ver == 1) + sw = IT9135_V1_FW; +- else if (le16_to_cpu(udev->descriptor.idProduct) == +- USB_PID_ITETECH_IT9135_9006) { ++ else + sw = IT9135_V2_FW; +- if (it913x_config.tuner_id_0 == 0) +- it913x_config.tuner_id_0 = IT9135_60; +- } else +- sw = IT9137_FW; + + /* force switch */ + if (dvb_usb_it913x_firmware != IT9135_AUTO) +@@ -410,41 +427,103 @@ static int ite_firmware_select(struct us + case IT9135_V1_FW: + it913x_config.firmware_ver = 1; + it913x_config.adc_x2 = 1; ++ it913x_config.read_slevel = false; + props->firmware = fw_it9135_v1; + break; + case IT9135_V2_FW: + it913x_config.firmware_ver = 1; + it913x_config.adc_x2 = 1; ++ it913x_config.read_slevel = false; + props->firmware = fw_it9135_v2; ++ switch (it913x_config.tuner_id_0) { ++ case IT9135_61: ++ case IT9135_62: ++ break; ++ default: ++ info("Unknown tuner ID applying default 0x60"); ++ case IT9135_60: ++ it913x_config.tuner_id_0 = IT9135_60; ++ } + break; + case IT9137_FW: + default: + it913x_config.firmware_ver = 0; + it913x_config.adc_x2 = 0; ++ it913x_config.read_slevel = true; + props->firmware = fw_it9137; + } + + return 0; + } + ++static void it913x_select_remote(struct usb_device *udev, ++ struct dvb_usb_device_properties *props) ++{ ++ switch (le16_to_cpu(udev->descriptor.idProduct)) { ++ case USB_PID_ITETECH_IT9135_9005: ++ props->rc.core.rc_codes = RC_MAP_IT913X_V2; ++ return; ++ default: ++ props->rc.core.rc_codes = RC_MAP_IT913X_V1; ++ } ++ return; ++} ++ + #define TS_MPEG_PKT_SIZE 188 + #define EP_LOW 21 + #define TS_BUFFER_SIZE_PID (EP_LOW*TS_MPEG_PKT_SIZE) + #define EP_HIGH 348 + #define TS_BUFFER_SIZE_MAX (EP_HIGH*TS_MPEG_PKT_SIZE) + +-static int it913x_identify_state(struct usb_device *udev, +- struct dvb_usb_device_properties *props, +- struct dvb_usb_device_description **desc, +- int *cold) ++static int it913x_select_config(struct usb_device *udev, ++ struct dvb_usb_device_properties *props) + { +- int ret = 0, firm_no; +- u8 reg, remote; ++ int ret = 0, reg; ++ bool proprietary_ir = false; + +- firm_no = it913x_return_status(udev); ++ if (it913x_config.chip_ver == 0x02 ++ && it913x_config.chip_type == 0x9135) ++ reg = it913x_read_reg(udev, 0x461d); ++ else ++ reg = it913x_read_reg(udev, 0x461b); + +- /* checnk for dual mode */ +- it913x_config.dual_mode = it913x_read_reg(udev, 0x49c5); ++ if (reg < 0) ++ return reg; ++ ++ if (reg == 0) { ++ it913x_config.dual_mode = 0; ++ it913x_config.tuner_id_0 = IT9135_38; ++ proprietary_ir = true; ++ } else { ++ /* TS mode */ ++ reg = it913x_read_reg(udev, 0x49c5); ++ if (reg < 0) ++ return reg; ++ it913x_config.dual_mode = reg; ++ ++ /* IR mode type */ ++ reg = it913x_read_reg(udev, 0x49ac); ++ if (reg < 0) ++ return reg; ++ if (reg == 5) { ++ info("Remote propriety (raw) mode"); ++ proprietary_ir = true; ++ } else if (reg == 1) { ++ info("Remote HID mode NOT SUPPORTED"); ++ proprietary_ir = false; ++ props->rc.core.rc_codes = NULL; ++ } else ++ props->rc.core.rc_codes = NULL; ++ ++ /* Tuner_id */ ++ reg = it913x_read_reg(udev, 0x49d0); ++ if (reg < 0) ++ return reg; ++ it913x_config.tuner_id_0 = reg; ++ } ++ ++ if (proprietary_ir) ++ it913x_select_remote(udev, props); + + if (udev->speed != USB_SPEED_HIGH) { + props->adapter[0].fe[0].pid_filter_count = 5; +@@ -459,17 +538,6 @@ static int it913x_identify_state(struct + if(props->adapter[0].fe[0].pid_filter_count == 5) + props->adapter[0].fe[0].pid_filter_count = 31; + +- /* TODO different remotes */ +- remote = it913x_read_reg(udev, 0x49ac); /* Remote */ +- if (remote == 0) +- props->rc.core.rc_codes = NULL; +- +- /* TODO at the moment tuner_id is always assigned to 0x38 */ +- it913x_config.tuner_id_0 = it913x_read_reg(udev, 0x49d0); +- +- info("Dual mode=%x Remote=%x Tuner Type=%x", it913x_config.dual_mode +- , remote, it913x_config.tuner_id_0); +- + /* Select Stream Buffer Size and pid filter option*/ + if (pid_filter) { + props->adapter[0].fe[0].stream.u.bulk.buffersize = +@@ -490,8 +558,29 @@ static int it913x_identify_state(struct + } else + props->num_adapters = 1; + ++ info("Dual mode=%x Tuner Type=%x", it913x_config.dual_mode, ++ it913x_config.tuner_id_0); ++ + ret = ite_firmware_select(udev, props); + ++ return ret; ++} ++ ++static int it913x_identify_state(struct usb_device *udev, ++ struct dvb_usb_device_properties *props, ++ struct dvb_usb_device_description **desc, ++ int *cold) ++{ ++ int ret = 0, firm_no; ++ u8 reg; ++ ++ firm_no = it913x_return_status(udev); ++ ++ /* Read and select config */ ++ ret = it913x_select_config(udev, props); ++ if (ret < 0) ++ return ret; ++ + if (firm_no > 0) { + *cold = 0; + return 0; +@@ -538,18 +627,22 @@ static int it913x_identify_state(struct + + static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) + { ++ struct it913x_state *st = adap->dev->priv; + int ret = 0; + u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; + +- if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) +- return -EAGAIN; + deb_info(1, "STM (%02x)", onoff); + +- if (!onoff) ++ if (!onoff) { ++ mutex_lock(&adap->dev->i2c_mutex); ++ + ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1); + ++ mutex_unlock(&adap->dev->i2c_mutex); ++ st->pid_filter_onoff = ++ adap->fe_adap[adap->active_fe].pid_filtering; + +- mutex_unlock(&adap->dev->i2c_mutex); ++ } + + return ret; + } +@@ -582,30 +675,41 @@ static int it913x_download_firmware(stru + if ((packet_size > min_pkt) || (i == fw->size)) { + fw_data = (u8 *)(fw->data + pos); + pos += packet_size; +- if (packet_size > 0) +- ret |= it913x_io(udev, WRITE_DATA, ++ if (packet_size > 0) { ++ ret = it913x_io(udev, WRITE_DATA, + DEV_0, CMD_SCATTER_WRITE, 0, + 0, fw_data, packet_size); ++ if (ret < 0) ++ break; ++ } + udelay(1000); + } + } + i++; + } + +- ret |= it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0); +- +- msleep(100); +- + if (ret < 0) +- info("FRM Firmware Download Failed (%04x)" , ret); ++ info("FRM Firmware Download Failed (%d)" , ret); + else + info("FRM Firmware Download Completed - Resetting Device"); + +- ret |= it913x_return_status(udev); ++ msleep(30); ++ ++ ret = it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0); ++ if (ret < 0) ++ info("FRM Device not responding to reboot"); ++ ++ ret = it913x_return_status(udev); ++ if (ret == 0) { ++ info("FRM Failed to reboot device"); ++ return -ENODEV; ++ } + + msleep(30); + +- ret |= it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_400); ++ ret = it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_400); ++ ++ msleep(30); + + /* Tuner function */ + if (it913x_config.dual_mode) +@@ -789,7 +893,7 @@ static struct dvb_usb_device_properties + .rc_query = it913x_rc_query, + .rc_interval = IT913X_POLL, + .allowed_protos = RC_TYPE_NEC, +- .rc_codes = RC_MAP_MSI_DIGIVOX_III, ++ .rc_codes = RC_MAP_IT913X_V1, + }, + .i2c_algo = &it913x_i2c_algo, + .num_device_descs = 5, +@@ -823,5 +927,5 @@ module_usb_driver(it913x_driver); + + MODULE_AUTHOR("Malcolm Priestley "); + MODULE_DESCRIPTION("it913x USB 2 Driver"); +-MODULE_VERSION("1.22"); ++MODULE_VERSION("1.28"); + MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/base/driver.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/base/driver.c ++++ linux-3.3.x86_64/drivers/base/driver.c +@@ -234,7 +234,6 @@ int driver_register(struct device_driver + + other = driver_find(drv->name, drv->bus); + if (other) { +- put_driver(other); + printk(KERN_ERR "Error: Driver '%s' is already registered, " + "aborting...\n", drv->name); + return -EBUSY; +@@ -275,7 +274,9 @@ EXPORT_SYMBOL_GPL(driver_unregister); + * Call kset_find_obj() to iterate over list of drivers on + * a bus to find driver by name. Return driver if found. + * +- * Note that kset_find_obj increments driver's reference count. ++ * This routine provides no locking to prevent the driver it returns ++ * from being unregistered or unloaded while the caller is using it. ++ * The caller is responsible for preventing this. + */ + struct device_driver *driver_find(const char *name, struct bus_type *bus) + { +@@ -283,6 +284,8 @@ struct device_driver *driver_find(const + struct driver_private *priv; + + if (k) { ++ /* Drop reference added by kset_find_obj() */ ++ kobject_put(k); + priv = to_driver(k); + return priv->driver; + } +Index: linux-3.3.x86_64/drivers/input/gameport/gameport.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/input/gameport/gameport.c ++++ linux-3.3.x86_64/drivers/input/gameport/gameport.c +@@ -449,7 +449,6 @@ static ssize_t gameport_rebind_driver(st + } else if ((drv = driver_find(buf, &gameport_bus)) != NULL) { + gameport_disconnect_port(gameport); + error = gameport_bind_driver(gameport, to_gameport_driver(drv)); +- put_driver(drv); + } else { + error = -EINVAL; + } +Index: linux-3.3.x86_64/drivers/input/serio/serio.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/input/serio/serio.c ++++ linux-3.3.x86_64/drivers/input/serio/serio.c +@@ -441,7 +441,6 @@ static ssize_t serio_rebind_driver(struc + } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { + serio_disconnect_port(serio); + error = serio_bind_driver(serio, to_serio_driver(drv)); +- put_driver(drv); + serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); + } else { + error = -EINVAL; +Index: linux-3.3.x86_64/drivers/media/video/cx18/cx18-alsa-main.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx18/cx18-alsa-main.c ++++ linux-3.3.x86_64/drivers/media/video/cx18/cx18-alsa-main.c +@@ -285,7 +285,6 @@ static void __exit cx18_alsa_exit(void) + + drv = driver_find("cx18", &pci_bus_type); + ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback); +- put_driver(drv); + + cx18_ext_init = NULL; + printk(KERN_INFO "cx18-alsa: module unload complete\n"); +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtvfb.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtvfb.c ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtvfb.c +@@ -1293,7 +1293,6 @@ static int __init ivtvfb_init(void) + + drv = driver_find("ivtv", &pci_bus_type); + err = driver_for_each_device(drv, NULL, ®istered, ivtvfb_callback_init); +- put_driver(drv); + if (!registered) { + printk(KERN_ERR "ivtvfb: no cards found\n"); + return -ENODEV; +@@ -1310,7 +1309,6 @@ static void ivtvfb_cleanup(void) + + drv = driver_find("ivtv", &pci_bus_type); + err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup); +- put_driver(drv); + } + + module_init(ivtvfb_init); +Index: linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-mdevice.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-fimc/fimc-mdevice.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-mdevice.c +@@ -344,16 +344,13 @@ static int fimc_md_register_platform_ent + return -ENODEV; + ret = driver_for_each_device(driver, NULL, fmd, + fimc_register_callback); +- put_driver(driver); + if (ret) + return ret; + + driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type); +- if (driver) { ++ if (driver) + ret = driver_for_each_device(driver, NULL, fmd, + csis_register_callback); +- put_driver(driver); +- } + return ret; + } + +@@ -753,7 +750,7 @@ static int __devinit fimc_md_probe(struc + struct fimc_md *fmd; + int ret; + +- fmd = kzalloc(sizeof(struct fimc_md), GFP_KERNEL); ++ fmd = devm_kzalloc(&pdev->dev, sizeof(*fmd), GFP_KERNEL); + if (!fmd) + return -ENOMEM; + +@@ -774,7 +771,7 @@ static int __devinit fimc_md_probe(struc + ret = v4l2_device_register(&pdev->dev, &fmd->v4l2_dev); + if (ret < 0) { + v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); +- goto err1; ++ return ret; + } + ret = media_device_register(&fmd->media_dev); + if (ret < 0) { +@@ -816,8 +813,6 @@ err3: + fimc_md_unregister_entities(fmd); + err2: + v4l2_device_unregister(&fmd->v4l2_dev); +-err1: +- kfree(fmd); + return ret; + } + +@@ -831,7 +826,6 @@ static int __devexit fimc_md_remove(stru + fimc_md_unregister_entities(fmd); + media_device_unregister(&fmd->media_dev); + fimc_md_put_clocks(fmd); +- kfree(fmd); + return 0; + } + +Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/mixer_video.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/mixer_video.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-tv/mixer_video.c +@@ -58,7 +58,6 @@ static struct v4l2_subdev *find_and_regi + } + + done: +- put_driver(drv); + return sd; + } + +Index: linux-3.3.x86_64/drivers/s390/net/smsgiucv_app.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/s390/net/smsgiucv_app.c ++++ linux-3.3.x86_64/drivers/s390/net/smsgiucv_app.c +@@ -168,7 +168,7 @@ static int __init smsgiucv_app_init(void + rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT); + if (rc) { + kfree(smsg_app_dev); +- goto fail_put_driver; ++ goto fail; + } + smsg_app_dev->bus = &iucv_bus; + smsg_app_dev->parent = iucv_root; +@@ -177,7 +177,7 @@ static int __init smsgiucv_app_init(void + rc = device_register(smsg_app_dev); + if (rc) { + put_device(smsg_app_dev); +- goto fail_put_driver; ++ goto fail; + } + + /* convert sender to uppercase characters */ +@@ -191,12 +191,11 @@ static int __init smsgiucv_app_init(void + rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); + if (rc) { + device_unregister(smsg_app_dev); +- goto fail_put_driver; ++ goto fail; + } + + rc = 0; +-fail_put_driver: +- put_driver(smsgiucv_drv); ++fail: + return rc; + } + module_init(smsgiucv_app_init); +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/anysee.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/anysee.c ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/anysee.c +@@ -58,7 +58,7 @@ static int anysee_ctrl_msg(struct dvb_us + u8 *rbuf, u8 rlen) + { + struct anysee_state *state = d->priv; +- int act_len, ret; ++ int act_len, ret, i; + u8 buf[64]; + + memcpy(&buf[0], sbuf, slen); +@@ -73,26 +73,52 @@ static int anysee_ctrl_msg(struct dvb_us + /* We need receive one message more after dvb_usb_generic_rw due + to weird transaction flow, which is 1 x send + 2 x receive. */ + ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0); +- if (!ret) { ++ if (ret) ++ goto error_unlock; ++ ++ /* TODO FIXME: dvb_usb_generic_rw() fails rarely with error code -32 ++ * (EPIPE, Broken pipe). Function supports currently msleep() as a ++ * parameter but I would not like to use it, since according to ++ * Documentation/timers/timers-howto.txt it should not be used such ++ * short, under < 20ms, sleeps. Repeating failed message would be ++ * better choice as not to add unwanted delays... ++ * Fixing that correctly is one of those or both; ++ * 1) use repeat if possible ++ * 2) add suitable delay ++ */ ++ ++ /* get answer, retry few times if error returned */ ++ for (i = 0; i < 3; i++) { + /* receive 2nd answer */ + ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, + d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf), + &act_len, 2000); +- if (ret) +- err("%s: recv bulk message failed: %d", __func__, ret); +- else { ++ ++ if (ret) { ++ deb_info("%s: recv bulk message failed: %d", ++ __func__, ret); ++ } else { + deb_xfer("<<< "); + debug_dump(buf, rlen, deb_xfer); + + if (buf[63] != 0x4f) + deb_info("%s: cmd failed\n", __func__); ++ ++ break; + } + } + ++ if (ret) { ++ /* all retries failed, it is fatal */ ++ err("%s: recv bulk message failed: %d", __func__, ret); ++ goto error_unlock; ++ } ++ + /* read request, copy returned data to return buf */ +- if (!ret && rbuf && rlen) ++ if (rbuf && rlen) + memcpy(rbuf, buf, rlen); + ++error_unlock: + mutex_unlock(&anysee_usb_mutex); + + return ret; +Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/hdmi_drv.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/hdmi_drv.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-tv/hdmi_drv.c +@@ -30,6 +30,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -66,6 +67,8 @@ struct hdmi_device { + struct v4l2_device v4l2_dev; + /** subdev of HDMIPHY interface */ + struct v4l2_subdev *phy_sd; ++ /** subdev of MHL interface */ ++ struct v4l2_subdev *mhl_sd; + /** configuration of current graphic mode */ + const struct hdmi_preset_conf *cur_conf; + /** current preset */ +@@ -74,10 +77,6 @@ struct hdmi_device { + struct hdmi_resources res; + }; + +-struct hdmi_driver_data { +- int hdmiphy_bus; +-}; +- + struct hdmi_tg_regs { + u8 cmd; + u8 h_fsz_l; +@@ -129,23 +128,11 @@ struct hdmi_preset_conf { + struct v4l2_mbus_framefmt mbus_fmt; + }; + +-/* I2C module and id for HDMIPHY */ +-static struct i2c_board_info hdmiphy_info = { +- I2C_BOARD_INFO("hdmiphy", 0x38), +-}; +- +-static struct hdmi_driver_data hdmi_driver_data[] = { +- { .hdmiphy_bus = 3 }, +- { .hdmiphy_bus = 8 }, +-}; +- + static struct platform_device_id hdmi_driver_types[] = { + { + .name = "s5pv210-hdmi", +- .driver_data = (unsigned long)&hdmi_driver_data[0], + }, { + .name = "exynos4-hdmi", +- .driver_data = (unsigned long)&hdmi_driver_data[1], + }, { + /* end node */ + } +@@ -587,7 +574,15 @@ static int hdmi_streamon(struct hdmi_dev + if (tries == 0) { + dev_err(dev, "hdmiphy's pll could not reach steady state.\n"); + v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); +- hdmi_dumpregs(hdev, "s_stream"); ++ hdmi_dumpregs(hdev, "hdmiphy - s_stream"); ++ return -EIO; ++ } ++ ++ /* starting MHL */ ++ ret = v4l2_subdev_call(hdev->mhl_sd, video, s_stream, 1); ++ if (hdev->mhl_sd && ret) { ++ v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); ++ hdmi_dumpregs(hdev, "mhl - s_stream"); + return -EIO; + } + +@@ -618,6 +613,7 @@ static int hdmi_streamoff(struct hdmi_de + clk_set_parent(res->sclk_hdmi, res->sclk_pixel); + clk_enable(res->sclk_hdmi); + ++ v4l2_subdev_call(hdev->mhl_sd, video, s_stream, 0); + v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); + + hdmi_dumpregs(hdev, "streamoff"); +@@ -739,6 +735,7 @@ static int hdmi_runtime_suspend(struct d + struct hdmi_device *hdev = sd_to_hdmi_dev(sd); + + dev_dbg(dev, "%s\n", __func__); ++ v4l2_subdev_call(hdev->mhl_sd, core, s_power, 0); + hdmi_resource_poweroff(&hdev->res); + return 0; + } +@@ -757,6 +754,11 @@ static int hdmi_runtime_resume(struct de + if (ret) + goto fail; + ++ /* starting MHL */ ++ ret = v4l2_subdev_call(hdev->mhl_sd, core, s_power, 1); ++ if (hdev->mhl_sd && ret) ++ goto fail; ++ + dev_dbg(dev, "poweron succeed\n"); + + return 0; +@@ -867,15 +869,21 @@ static int __devinit hdmi_probe(struct p + { + struct device *dev = &pdev->dev; + struct resource *res; +- struct i2c_adapter *phy_adapter; ++ struct i2c_adapter *adapter; + struct v4l2_subdev *sd; + struct hdmi_device *hdmi_dev = NULL; +- struct hdmi_driver_data *drv_data; ++ struct s5p_hdmi_platform_data *pdata = dev->platform_data; + int ret; + + dev_dbg(dev, "probe start\n"); + +- hdmi_dev = kzalloc(sizeof(*hdmi_dev), GFP_KERNEL); ++ if (!pdata) { ++ dev_err(dev, "platform data is missing\n"); ++ ret = -ENODEV; ++ goto fail; ++ } ++ ++ hdmi_dev = devm_kzalloc(&pdev->dev, sizeof(*hdmi_dev), GFP_KERNEL); + if (!hdmi_dev) { + dev_err(dev, "out of memory\n"); + ret = -ENOMEM; +@@ -886,7 +894,7 @@ static int __devinit hdmi_probe(struct p + + ret = hdmi_resources_init(hdmi_dev); + if (ret) +- goto fail_hdev; ++ goto fail; + + /* mapping HDMI registers */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +@@ -896,24 +904,26 @@ static int __devinit hdmi_probe(struct p + goto fail_init; + } + +- hdmi_dev->regs = ioremap(res->start, resource_size(res)); ++ hdmi_dev->regs = devm_ioremap(&pdev->dev, res->start, ++ resource_size(res)); + if (hdmi_dev->regs == NULL) { + dev_err(dev, "register mapping failed.\n"); + ret = -ENXIO; +- goto fail_hdev; ++ goto fail_init; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res == NULL) { + dev_err(dev, "get interrupt resource failed.\n"); + ret = -ENXIO; +- goto fail_regs; ++ goto fail_init; + } + +- ret = request_irq(res->start, hdmi_irq_handler, 0, "hdmi", hdmi_dev); ++ ret = devm_request_irq(&pdev->dev, res->start, hdmi_irq_handler, 0, ++ "hdmi", hdmi_dev); + if (ret) { + dev_err(dev, "request interrupt failed.\n"); +- goto fail_regs; ++ goto fail_init; + } + hdmi_dev->irq = res->start; + +@@ -924,28 +934,54 @@ static int __devinit hdmi_probe(struct p + ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev); + if (ret) { + dev_err(dev, "could not register v4l2 device.\n"); +- goto fail_irq; ++ goto fail_init; + } + +- drv_data = (struct hdmi_driver_data *) +- platform_get_device_id(pdev)->driver_data; +- phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus); +- if (phy_adapter == NULL) { +- dev_err(dev, "adapter request failed\n"); ++ /* testing if hdmiphy info is present */ ++ if (!pdata->hdmiphy_info) { ++ dev_err(dev, "hdmiphy info is missing in platform data\n"); ++ ret = -ENXIO; ++ goto fail_vdev; ++ } ++ ++ adapter = i2c_get_adapter(pdata->hdmiphy_bus); ++ if (adapter == NULL) { ++ dev_err(dev, "hdmiphy adapter request failed\n"); + ret = -ENXIO; + goto fail_vdev; + } + + hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev, +- phy_adapter, &hdmiphy_info, NULL); ++ adapter, pdata->hdmiphy_info, NULL); + /* on failure or not adapter is no longer useful */ +- i2c_put_adapter(phy_adapter); ++ i2c_put_adapter(adapter); + if (hdmi_dev->phy_sd == NULL) { + dev_err(dev, "missing subdev for hdmiphy\n"); + ret = -ENODEV; + goto fail_vdev; + } + ++ /* initialization of MHL interface if present */ ++ if (pdata->mhl_info) { ++ adapter = i2c_get_adapter(pdata->mhl_bus); ++ if (adapter == NULL) { ++ dev_err(dev, "MHL adapter request failed\n"); ++ ret = -ENXIO; ++ goto fail_vdev; ++ } ++ ++ hdmi_dev->mhl_sd = v4l2_i2c_new_subdev_board( ++ &hdmi_dev->v4l2_dev, adapter, ++ pdata->mhl_info, NULL); ++ /* on failure or not adapter is no longer useful */ ++ i2c_put_adapter(adapter); ++ if (hdmi_dev->mhl_sd == NULL) { ++ dev_err(dev, "missing subdev for MHL\n"); ++ ret = -ENODEV; ++ goto fail_vdev; ++ } ++ } ++ + clk_enable(hdmi_dev->res.hdmi); + + pm_runtime_enable(dev); +@@ -969,18 +1005,9 @@ static int __devinit hdmi_probe(struct p + fail_vdev: + v4l2_device_unregister(&hdmi_dev->v4l2_dev); + +-fail_irq: +- free_irq(hdmi_dev->irq, hdmi_dev); +- +-fail_regs: +- iounmap(hdmi_dev->regs); +- + fail_init: + hdmi_resources_cleanup(hdmi_dev); + +-fail_hdev: +- kfree(hdmi_dev); +- + fail: + dev_err(dev, "probe failed\n"); + return ret; +@@ -996,8 +1023,6 @@ static int __devexit hdmi_remove(struct + clk_disable(hdmi_dev->res.hdmi); + v4l2_device_unregister(&hdmi_dev->v4l2_dev); + disable_irq(hdmi_dev->irq); +- free_irq(hdmi_dev->irq, hdmi_dev); +- iounmap(hdmi_dev->regs); + hdmi_resources_cleanup(hdmi_dev); + kfree(hdmi_dev); + dev_info(dev, "remove sucessful\n"); +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/lmedm04.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/lmedm04.c ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/lmedm04.c +@@ -77,6 +77,7 @@ + #include "stv0299.h" + #include "dvb-pll.h" + #include "z0194a.h" ++#include "m88rs2000.h" + + + +@@ -104,7 +105,7 @@ MODULE_PARM_DESC(firmware, "set default + + static int pid_filter; + module_param_named(pid, pid_filter, int, 0644); +-MODULE_PARM_DESC(pid, "set default 0=on 1=off"); ++MODULE_PARM_DESC(pid, "set default 0=default 1=off 2=on"); + + + DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +@@ -113,6 +114,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr + #define TUNER_LG 0x1 + #define TUNER_S7395 0x2 + #define TUNER_S0194 0x3 ++#define TUNER_RS2000 0x4 + + struct lme2510_state { + u8 id; +@@ -121,6 +123,8 @@ struct lme2510_state { + u8 signal_level; + u8 signal_sn; + u8 time_key; ++ u8 last_key; ++ u8 key_timeout; + u8 i2c_talk_onoff; + u8 i2c_gate; + u8 i2c_tuner_gate_w; +@@ -128,6 +132,7 @@ struct lme2510_state { + u8 i2c_tuner_addr; + u8 stream_on; + u8 pid_size; ++ u8 pid_off; + void *buffer; + struct urb *lme_urb; + void *usb_buffer; +@@ -178,14 +183,8 @@ static int lme2510_usb_talk(struct dvb_u + /* the read/write capped at 64 */ + memcpy(buff, wbuf, (wlen < 64) ? wlen : 64); + +- ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01)); +- + ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01); + +- msleep(10); +- +- ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01)); +- + ret |= lme2510_bulk_read(d->udev, buff, (rlen < 64) ? + rlen : 64 , 0x01); + +@@ -199,9 +198,14 @@ static int lme2510_usb_talk(struct dvb_u + + static int lme2510_stream_restart(struct dvb_usb_device *d) + { +- static u8 stream_on[] = LME_ST_ON_W; ++ struct lme2510_state *st = d->priv; ++ u8 all_pids[] = LME_ALL_PIDS; ++ u8 stream_on[] = LME_ST_ON_W; + int ret; +- u8 rbuff[10]; ++ u8 rbuff[1]; ++ if (st->pid_off) ++ ret = lme2510_usb_talk(d, all_pids, sizeof(all_pids), ++ rbuff, sizeof(rbuff)); + /*Restart Stream Command*/ + ret = lme2510_usb_talk(d, stream_on, sizeof(stream_on), + rbuff, sizeof(rbuff)); +@@ -308,6 +312,14 @@ static void lme2510_int_response(struct + ((ibuf[2] & 0x01) << 0x03); + } + break; ++ case TUNER_RS2000: ++ if (ibuf[2] > 0) ++ st->signal_lock = 0xff; ++ else ++ st->signal_lock = 0xf0; ++ st->signal_level = ibuf[4]; ++ st->signal_sn = ibuf[5]; ++ st->time_key = ibuf[7]; + default: + break; + } +@@ -359,19 +371,20 @@ static int lme2510_int_read(struct dvb_u + static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) + { + struct lme2510_state *st = adap->dev->priv; +- static u8 clear_pid_reg[] = LME_CLEAR_PID; ++ static u8 clear_pid_reg[] = LME_ALL_PIDS; + static u8 rbuf[1]; + int ret; + + deb_info(1, "PID Clearing Filter"); + +- ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); +- if (ret < 0) +- return -EAGAIN; ++ mutex_lock(&adap->dev->i2c_mutex); + +- if (!onoff) ++ if (!onoff) { + ret |= lme2510_usb_talk(adap->dev, clear_pid_reg, + sizeof(clear_pid_reg), rbuf, sizeof(rbuf)); ++ st->pid_off = true; ++ } else ++ st->pid_off = false; + + st->pid_size = 0; + +@@ -389,11 +402,9 @@ static int lme2510_pid_filter(struct dvb + pid, index, onoff); + + if (onoff) { +- ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); +- if (ret < 0) +- return -EAGAIN; +- ret |= lme2510_enable_pid(adap->dev, index, pid); +- mutex_unlock(&adap->dev->i2c_mutex); ++ mutex_lock(&adap->dev->i2c_mutex); ++ ret |= lme2510_enable_pid(adap->dev, index, pid); ++ mutex_unlock(&adap->dev->i2c_mutex); + } + + +@@ -425,9 +436,6 @@ static int lme2510_msg(struct dvb_usb_de + int ret = 0; + struct lme2510_state *st = d->priv; + +- if (mutex_lock_interruptible(&d->i2c_mutex) < 0) +- return -EAGAIN; +- + if (st->i2c_talk_onoff == 1) { + + ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); +@@ -456,8 +464,6 @@ static int lme2510_msg(struct dvb_usb_de + st->i2c_talk_onoff = 0; + } + } +- if ((wbuf[3] != 0x6) & (wbuf[3] != 0x5)) +- msleep(5); + } + break; + case TUNER_S0194: +@@ -472,10 +478,12 @@ static int lme2510_msg(struct dvb_usb_de + } + } + break; ++ case TUNER_RS2000: + default: + break; + } + } else { ++ /* TODO rewrite this section */ + switch (st->tuner_config) { + case TUNER_LG: + switch (wbuf[3]) { +@@ -559,6 +567,24 @@ static int lme2510_msg(struct dvb_usb_de + break; + } + break; ++ case TUNER_RS2000: ++ switch (wbuf[3]) { ++ case 0x8c: ++ rbuf[0] = 0x55; ++ rbuf[1] = 0xff; ++ if (st->last_key == st->time_key) { ++ st->key_timeout++; ++ if (st->key_timeout > 5) ++ rbuf[1] = 0; ++ } else ++ st->key_timeout = 0; ++ st->last_key = st->time_key; ++ break; ++ default: ++ lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); ++ st->i2c_talk_onoff = 1; ++ break; ++ } + default: + break; + } +@@ -568,8 +594,6 @@ static int lme2510_msg(struct dvb_usb_de + + } + +- mutex_unlock(&d->i2c_mutex); +- + return ret; + } + +@@ -584,6 +608,8 @@ static int lme2510_i2c_xfer(struct i2c_a + u16 len; + u8 gate = st->i2c_gate; + ++ mutex_lock(&d->i2c_mutex); ++ + if (gate == 0) + gate = 5; + +@@ -622,6 +648,7 @@ static int lme2510_i2c_xfer(struct i2c_a + + if (lme2510_msg(d, obuf, len, ibuf, 64) < 0) { + deb_info(1, "i2c transfer failed."); ++ mutex_unlock(&d->i2c_mutex); + return -EAGAIN; + } + +@@ -634,6 +661,8 @@ static int lme2510_i2c_xfer(struct i2c_a + } + } + } ++ ++ mutex_unlock(&d->i2c_mutex); + return i; + } + +@@ -653,7 +682,7 @@ static int lme2510_identify_state(struct + struct dvb_usb_device_description **desc, + int *cold) + { +- if (pid_filter > 0) ++ if (pid_filter != 2) + props->adapter[0].fe[0].caps &= + ~DVB_USB_ADAP_NEED_PID_FILTERING; + *cold = 0; +@@ -663,7 +692,7 @@ static int lme2510_identify_state(struct + static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) + { + struct lme2510_state *st = adap->dev->priv; +- static u8 clear_reg_3[] = LME_CLEAR_PID; ++ static u8 clear_reg_3[] = LME_ALL_PIDS; + static u8 rbuf[1]; + int ret = 0, rlen = sizeof(rbuf); + +@@ -675,8 +704,7 @@ static int lme2510_streaming_ctrl(struct + else { + deb_info(1, "STM Steam Off"); + /* mutex is here only to avoid collision with I2C */ +- if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) +- return -EAGAIN; ++ mutex_lock(&adap->dev->i2c_mutex); + + ret = lme2510_usb_talk(adap->dev, clear_reg_3, + sizeof(clear_reg_3), rbuf, rlen); +@@ -781,16 +809,18 @@ static int lme_firmware_switch(struct us + const char fw_c_s7395[] = "dvb-usb-lme2510c-s7395.fw"; + const char fw_c_lg[] = "dvb-usb-lme2510c-lg.fw"; + const char fw_c_s0194[] = "dvb-usb-lme2510c-s0194.fw"; ++ const char fw_c_rs2000[] = "dvb-usb-lme2510c-rs2000.fw"; + const char fw_lg[] = "dvb-usb-lme2510-lg.fw"; + const char fw_s0194[] = "dvb-usb-lme2510-s0194.fw"; + const char *fw_lme; +- int ret, cold_fw; ++ int ret = 0, cold_fw; + + cold = (cold > 0) ? (cold & 1) : 0; + + cold_fw = !cold; + +- if (le16_to_cpu(udev->descriptor.idProduct) == 0x1122) { ++ switch (le16_to_cpu(udev->descriptor.idProduct)) { ++ case 0x1122: + switch (dvb_usb_lme2510_firmware) { + default: + dvb_usb_lme2510_firmware = TUNER_S0194; +@@ -813,7 +843,8 @@ static int lme_firmware_switch(struct us + cold_fw = 0; + break; + } +- } else { ++ break; ++ case 0x1120: + switch (dvb_usb_lme2510_firmware) { + default: + dvb_usb_lme2510_firmware = TUNER_S7395; +@@ -842,8 +873,17 @@ static int lme_firmware_switch(struct us + cold_fw = 0; + break; + } ++ break; ++ case 0x22f0: ++ fw_lme = fw_c_rs2000; ++ ret = request_firmware(&fw, fw_lme, &udev->dev); ++ dvb_usb_lme2510_firmware = TUNER_RS2000; ++ break; ++ default: ++ fw_lme = fw_c_s7395; + } + ++ + if (cold_fw) { + info("FRM Loading %s file", fw_lme); + ret = lme2510_download_firmware(udev, fw); +@@ -906,6 +946,29 @@ static struct stv0299_config sharp_z0194 + .set_symbol_rate = sharp_z0194a_set_symbol_rate, + }; + ++static int dm04_rs2000_set_ts_param(struct dvb_frontend *fe, ++ int caller) ++{ ++ struct dvb_usb_adapter *adap = fe->dvb->priv; ++ struct dvb_usb_device *d = adap->dev; ++ struct lme2510_state *st = d->priv; ++ ++ mutex_lock(&d->i2c_mutex); ++ if ((st->i2c_talk_onoff == 1) && (st->stream_on & 1)) { ++ st->i2c_talk_onoff = 0; ++ lme2510_stream_restart(d); ++ } ++ mutex_unlock(&d->i2c_mutex); ++ ++ return 0; ++} ++ ++static struct m88rs2000_config m88rs2000_config = { ++ .demod_addr = 0xd0, ++ .tuner_addr = 0xc0, ++ .set_ts_params = dm04_rs2000_set_ts_param, ++}; ++ + static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, + fe_sec_voltage_t voltage) + { +@@ -915,8 +978,7 @@ static int dm04_lme2510_set_voltage(stru + static u8 rbuf[1]; + int ret = 0, len = 3, rlen = 1; + +- if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) +- return -EAGAIN; ++ mutex_lock(&adap->dev->i2c_mutex); + + switch (voltage) { + case SEC_VOLTAGE_18: +@@ -937,12 +999,31 @@ static int dm04_lme2510_set_voltage(stru + return (ret < 0) ? -ENODEV : 0; + } + ++static int dm04_rs2000_read_signal_strength(struct dvb_frontend *fe, ++ u16 *strength) ++{ ++ struct dvb_usb_adapter *adap = fe->dvb->priv; ++ struct lme2510_state *st = adap->dev->priv; ++ ++ *strength = (u16)((u32)st->signal_level * 0xffff / 0x7f); ++ return 0; ++} ++ ++static int dm04_rs2000_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct dvb_usb_adapter *adap = fe->dvb->priv; ++ struct lme2510_state *st = adap->dev->priv; ++ ++ *snr = (u16)((u32)st->signal_sn * 0xffff / 0xff); ++ return 0; ++} ++ + static int lme_name(struct dvb_usb_adapter *adap) + { + struct lme2510_state *st = adap->dev->priv; + const char *desc = adap->dev->desc->name; + char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395", +- " SHARP:BS2F7HZ0194"}; ++ " SHARP:BS2F7HZ0194", " RS2000"}; + char *name = adap->fe_adap[0].fe->ops.info.name; + + strlcpy(name, desc, 128); +@@ -958,60 +1039,82 @@ static int dm04_lme2510_frontend_attach( + int ret = 0; + + st->i2c_talk_onoff = 1; ++ switch (le16_to_cpu(adap->dev->udev->descriptor.idProduct)) { ++ case 0x1122: ++ case 0x1120: ++ st->i2c_gate = 4; ++ adap->fe_adap[0].fe = dvb_attach(tda10086_attach, ++ &tda10086_config, &adap->dev->i2c_adap); ++ if (adap->fe_adap[0].fe) { ++ info("TUN Found Frontend TDA10086"); ++ st->i2c_tuner_gate_w = 4; ++ st->i2c_tuner_gate_r = 4; ++ st->i2c_tuner_addr = 0xc0; ++ st->tuner_config = TUNER_LG; ++ if (dvb_usb_lme2510_firmware != TUNER_LG) { ++ dvb_usb_lme2510_firmware = TUNER_LG; ++ ret = lme_firmware_switch(adap->dev->udev, 1); ++ } ++ break; ++ } + +- st->i2c_gate = 4; +- adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config, +- &adap->dev->i2c_adap); +- +- if (adap->fe_adap[0].fe) { +- info("TUN Found Frontend TDA10086"); +- st->i2c_tuner_gate_w = 4; +- st->i2c_tuner_gate_r = 4; +- st->i2c_tuner_addr = 0xc0; +- st->tuner_config = TUNER_LG; +- if (dvb_usb_lme2510_firmware != TUNER_LG) { +- dvb_usb_lme2510_firmware = TUNER_LG; +- ret = lme_firmware_switch(adap->dev->udev, 1); ++ st->i2c_gate = 4; ++ adap->fe_adap[0].fe = dvb_attach(stv0299_attach, ++ &sharp_z0194_config, &adap->dev->i2c_adap); ++ if (adap->fe_adap[0].fe) { ++ info("FE Found Stv0299"); ++ st->i2c_tuner_gate_w = 4; ++ st->i2c_tuner_gate_r = 5; ++ st->i2c_tuner_addr = 0xc0; ++ st->tuner_config = TUNER_S0194; ++ if (dvb_usb_lme2510_firmware != TUNER_S0194) { ++ dvb_usb_lme2510_firmware = TUNER_S0194; ++ ret = lme_firmware_switch(adap->dev->udev, 1); ++ } ++ break; + } +- goto end; +- } + +- st->i2c_gate = 4; +- adap->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194_config, ++ st->i2c_gate = 5; ++ adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config, + &adap->dev->i2c_adap); +- if (adap->fe_adap[0].fe) { +- info("FE Found Stv0299"); +- st->i2c_tuner_gate_w = 4; +- st->i2c_tuner_gate_r = 5; +- st->i2c_tuner_addr = 0xc0; +- st->tuner_config = TUNER_S0194; +- if (dvb_usb_lme2510_firmware != TUNER_S0194) { +- dvb_usb_lme2510_firmware = TUNER_S0194; +- ret = lme_firmware_switch(adap->dev->udev, 1); ++ ++ if (adap->fe_adap[0].fe) { ++ info("FE Found Stv0288"); ++ st->i2c_tuner_gate_w = 4; ++ st->i2c_tuner_gate_r = 5; ++ st->i2c_tuner_addr = 0xc0; ++ st->tuner_config = TUNER_S7395; ++ if (dvb_usb_lme2510_firmware != TUNER_S7395) { ++ dvb_usb_lme2510_firmware = TUNER_S7395; ++ ret = lme_firmware_switch(adap->dev->udev, 1); ++ } ++ break; + } +- goto end; +- } ++ case 0x22f0: ++ st->i2c_gate = 5; ++ adap->fe_adap[0].fe = dvb_attach(m88rs2000_attach, ++ &m88rs2000_config, &adap->dev->i2c_adap); + +- st->i2c_gate = 5; +- adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config, +- &adap->dev->i2c_adap); +- if (adap->fe_adap[0].fe) { +- info("FE Found Stv0288"); +- st->i2c_tuner_gate_w = 4; +- st->i2c_tuner_gate_r = 5; +- st->i2c_tuner_addr = 0xc0; +- st->tuner_config = TUNER_S7395; +- if (dvb_usb_lme2510_firmware != TUNER_S7395) { +- dvb_usb_lme2510_firmware = TUNER_S7395; +- ret = lme_firmware_switch(adap->dev->udev, 1); ++ if (adap->fe_adap[0].fe) { ++ info("FE Found M88RS2000"); ++ st->i2c_tuner_gate_w = 5; ++ st->i2c_tuner_gate_r = 5; ++ st->i2c_tuner_addr = 0xc0; ++ st->tuner_config = TUNER_RS2000; ++ adap->fe_adap[0].fe->ops.read_signal_strength = ++ dm04_rs2000_read_signal_strength; ++ adap->fe_adap[0].fe->ops.read_snr = ++ dm04_rs2000_read_snr; + } +- } else { +- info("DM04 Not Supported"); +- return -ENODEV; ++ break; + } + ++ if (adap->fe_adap[0].fe == NULL) { ++ info("DM04/QQBOX Not Powered up or not Supported"); ++ return -ENODEV; ++ } + +-end: if (ret) { ++ if (ret) { + if (adap->fe_adap[0].fe) { + dvb_frontend_detach(adap->fe_adap[0].fe); + adap->fe_adap[0].fe = NULL; +@@ -1028,7 +1131,7 @@ end: if (ret) { + static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) + { + struct lme2510_state *st = adap->dev->priv; +- char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA"}; ++ char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA", "RS2000"}; + int ret = 0; + + switch (st->tuner_config) { +@@ -1047,6 +1150,9 @@ static int dm04_lme2510_tuner(struct dvb + &adap->dev->i2c_adap, DVB_PLL_OPERA1)) + ret = st->tuner_config; + break; ++ case TUNER_RS2000: ++ ret = st->tuner_config; ++ break; + default: + break; + } +@@ -1054,7 +1160,7 @@ static int dm04_lme2510_tuner(struct dvb + if (ret) + info("TUN Found %s tuner", tun_msg[ret]); + else { +- info("TUN No tuner found --- reseting device"); ++ info("TUN No tuner found --- resetting device"); + lme_coldreset(adap->dev->udev); + return -ENODEV; + } +@@ -1075,10 +1181,9 @@ static int lme2510_powerup(struct dvb_us + static u8 lnb_on[] = LNB_ON; + static u8 lnb_off[] = LNB_OFF; + static u8 rbuf[1]; +- int ret, len = 3, rlen = 1; ++ int ret = 0, len = 3, rlen = 1; + +- if (mutex_lock_interruptible(&d->i2c_mutex) < 0) +- return -EAGAIN; ++ mutex_lock(&d->i2c_mutex); + + if (onoff) + ret = lme2510_usb_talk(d, lnb_on, len, rbuf, rlen); +@@ -1136,6 +1241,7 @@ static int lme2510_probe(struct usb_inte + static struct usb_device_id lme2510_table[] = { + { USB_DEVICE(0x3344, 0x1122) }, /* LME2510 */ + { USB_DEVICE(0x3344, 0x1120) }, /* LME2510C */ ++ { USB_DEVICE(0x3344, 0x22f0) }, /* LME2510C RS2000 */ + {} /* Terminating entry */ + }; + +@@ -1153,7 +1259,7 @@ static struct dvb_usb_device_properties + DVB_USB_ADAP_NEED_PID_FILTERING| + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .streaming_ctrl = lme2510_streaming_ctrl, +- .pid_filter_count = 15, ++ .pid_filter_count = 32, + .pid_filter = lme2510_pid_filter, + .pid_filter_ctrl = lme2510_pid_filter_ctrl, + .frontend_attach = dm04_lme2510_frontend_attach, +@@ -1204,7 +1310,7 @@ static struct dvb_usb_device_properties + DVB_USB_ADAP_NEED_PID_FILTERING| + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .streaming_ctrl = lme2510_streaming_ctrl, +- .pid_filter_count = 15, ++ .pid_filter_count = 32, + .pid_filter = lme2510_pid_filter, + .pid_filter_ctrl = lme2510_pid_filter_ctrl, + .frontend_attach = dm04_lme2510_frontend_attach, +@@ -1234,11 +1340,14 @@ static struct dvb_usb_device_properties + .identify_state = lme2510_identify_state, + .i2c_algo = &lme2510_i2c_algo, + .generic_bulk_ctrl_endpoint = 0, +- .num_device_descs = 1, ++ .num_device_descs = 2, + .devices = { + { "DM04_LME2510C_DVB-S", + { &lme2510_table[1], NULL }, + }, ++ { "DM04_LME2510C_DVB-S RS2000", ++ { &lme2510_table[2], NULL }, ++ }, + } + }; + +@@ -1295,5 +1404,5 @@ module_usb_driver(lme2510_driver); + + MODULE_AUTHOR("Malcolm Priestley "); + MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); +-MODULE_VERSION("1.91"); ++MODULE_VERSION("1.99"); + MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/video/ov6650.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ov6650.c ++++ linux-3.3.x86_64/drivers/media/video/ov6650.c +@@ -649,7 +649,7 @@ static int ov6650_s_fmt(struct v4l2_subd + clkrc = CLKRC_24MHz; + } else { + dev_err(&client->dev, +- "unspported input clock, check platform data\n"); ++ "unsupported input clock, check platform data\n"); + return -EINVAL; + } + mclk = sense->master_clock; +@@ -1046,18 +1046,7 @@ static struct i2c_driver ov6650_i2c_driv + .id_table = ov6650_id, + }; + +-static int __init ov6650_module_init(void) +-{ +- return i2c_add_driver(&ov6650_i2c_driver); +-} +- +-static void __exit ov6650_module_exit(void) +-{ +- i2c_del_driver(&ov6650_i2c_driver); +-} +- +-module_init(ov6650_module_init); +-module_exit(ov6650_module_exit); ++module_i2c_driver(ov6650_i2c_driver); + + MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV6650"); + MODULE_AUTHOR("Janusz Krzysztofik "); +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/tda1004x.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/tda1004x.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/tda1004x.c +@@ -1272,7 +1272,7 @@ struct dvb_frontend* tda10045_attach(con + /* allocate memory for the internal state */ + state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL); + if (!state) { +- printk(KERN_ERR "Can't alocate memory for tda10045 state\n"); ++ printk(KERN_ERR "Can't allocate memory for tda10045 state\n"); + return NULL; + } + +@@ -1342,7 +1342,7 @@ struct dvb_frontend* tda10046_attach(con + /* allocate memory for the internal state */ + state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL); + if (!state) { +- printk(KERN_ERR "Can't alocate memory for tda10046 state\n"); ++ printk(KERN_ERR "Can't allocate memory for tda10046 state\n"); + return NULL; + } + +Index: linux-3.3.x86_64/drivers/media/video/davinci/vpif.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/davinci/vpif.h ++++ linux-3.3.x86_64/drivers/media/video/davinci/vpif.h +@@ -18,8 +18,6 @@ + + #include + #include +-#include +-#include + #include + + /* Maximum channel allowed */ +Index: linux-3.3.x86_64/drivers/media/video/davinci/vpif_display.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/davinci/vpif_display.c ++++ linux-3.3.x86_64/drivers/media/video/davinci/vpif_display.c +@@ -39,8 +39,6 @@ + #include + #include + +-#include +- + #include "vpif_display.h" + #include "vpif.h" + +Index: linux-3.3.x86_64/include/media/davinci/vpif_types.h +=================================================================== +--- linux-3.3.x86_64.orig/include/media/davinci/vpif_types.h ++++ linux-3.3.x86_64/include/media/davinci/vpif_types.h +@@ -17,6 +17,8 @@ + #ifndef _VPIF_TYPES_H + #define _VPIF_TYPES_H + ++#include ++ + #define VPIF_CAPTURE_MAX_CHANNELS 2 + + enum vpif_if_type { +Index: linux-3.3.x86_64/drivers/media/video/tm6000/tm6000-input.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tm6000/tm6000-input.c ++++ linux-3.3.x86_64/drivers/media/video/tm6000/tm6000-input.c +@@ -481,8 +481,6 @@ int tm6000_ir_fini(struct tm6000_core *d + + dprintk(2, "%s\n",__func__); + +- rc_unregister_device(ir->rc); +- + if (!ir->polling) + __tm6000_ir_int_stop(ir->rc); + +@@ -492,6 +490,7 @@ int tm6000_ir_fini(struct tm6000_core *d + tm6000_flash_led(dev, 0); + ir->pwled = 0; + ++ rc_unregister_device(ir->rc); + + kfree(ir); + dev->ir = NULL; +Index: linux-3.3.x86_64/drivers/media/dvb/mantis/mantis_hif.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/mantis/mantis_hif.c ++++ linux-3.3.x86_64/drivers/media/dvb/mantis/mantis_hif.c +@@ -76,7 +76,7 @@ static int mantis_hif_write_wait(struct + udelay(500); + timeout++; + if (timeout > 100) { +- dprintk(MANTIS_ERROR, 1, "Adater(%d) Slot(0): Write operation timed out!", mantis->num); ++ dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write operation timed out!", mantis->num); + rc = -ETIMEDOUT; + break; + } +Index: linux-3.3.x86_64/drivers/media/common/tuners/max2165.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/common/tuners/max2165.c ++++ linux-3.3.x86_64/drivers/media/common/tuners/max2165.c +@@ -168,7 +168,7 @@ int fixpt_div32(u32 dividend, u32 diviso + int i; + + if (0 == divisor) +- return -1; ++ return -EINVAL; + + q = dividend / divisor; + remainder = dividend - q * divisor; +@@ -194,10 +194,13 @@ static int max2165_set_rf(struct max2165 + u8 tf_ntch; + u32 t; + u32 quotient, fraction; ++ int ret; + + /* Set PLL divider according to RF frequency */ +- fixpt_div32(freq / 1000, priv->config->osc_clk * 1000, +- "ient, &fraction); ++ ret = fixpt_div32(freq / 1000, priv->config->osc_clk * 1000, ++ "ient, &fraction); ++ if (ret != 0) ++ return ret; + + /* 20-bit fraction */ + fraction >>= 12; +Index: linux-3.3.x86_64/drivers/media/video/v4l2-compat-ioctl32.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/v4l2-compat-ioctl32.c ++++ linux-3.3.x86_64/drivers/media/video/v4l2-compat-ioctl32.c +@@ -14,12 +14,11 @@ + */ + + #include +-#include + #include ++#include ++#include + #include + +-#ifdef CONFIG_COMPAT +- + static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + { + long ret = -ENOIOCTLCMD; +@@ -937,6 +936,7 @@ static long do_video_ioctl(struct file * + + long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) + { ++ struct video_device *vdev = video_devdata(file); + long ret = -ENOIOCTLCMD; + + if (!file->f_op->unlocked_ioctl) +@@ -1005,6 +1005,8 @@ long v4l2_compat_ioctl32(struct file *fi + case VIDIOC_G_ENC_INDEX: + case VIDIOC_ENCODER_CMD: + case VIDIOC_TRY_ENCODER_CMD: ++ case VIDIOC_DECODER_CMD: ++ case VIDIOC_TRY_DECODER_CMD: + case VIDIOC_DBG_S_REGISTER: + case VIDIOC_DBG_G_REGISTER: + case VIDIOC_DBG_G_CHIP_IDENT: +@@ -1025,14 +1027,16 @@ long v4l2_compat_ioctl32(struct file *fi + break; + + default: +- printk(KERN_WARNING "compat_ioctl32: " +- "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", +- _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd); ++ if (vdev->fops->compat_ioctl32) ++ ret = vdev->fops->compat_ioctl32(file, cmd, arg); ++ ++ if (ret == -ENOIOCTLCMD) ++ printk(KERN_WARNING "compat_ioctl32: " ++ "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", ++ _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), ++ cmd); + break; + } + return ret; + } + EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32); +-#endif +- +-MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/include/media/v4l2-ioctl.h +=================================================================== +--- linux-3.3.x86_64.orig/include/media/v4l2-ioctl.h ++++ linux-3.3.x86_64/include/media/v4l2-ioctl.h +@@ -211,6 +211,10 @@ struct v4l2_ioctl_ops { + struct v4l2_encoder_cmd *a); + int (*vidioc_try_encoder_cmd) (struct file *file, void *fh, + struct v4l2_encoder_cmd *a); ++ int (*vidioc_decoder_cmd) (struct file *file, void *fh, ++ struct v4l2_decoder_cmd *a); ++ int (*vidioc_try_decoder_cmd) (struct file *file, void *fh, ++ struct v4l2_decoder_cmd *a); + + /* Stream type-dependent parameter ioctls */ + int (*vidioc_g_parm) (struct file *file, void *fh, +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-driver.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-driver.c ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-driver.c +@@ -55,7 +55,7 @@ + #include "ivtv-routing.h" + #include "ivtv-controls.h" + #include "ivtv-gpio.h" +- ++#include + #include + #include + #include +@@ -99,7 +99,7 @@ static int i2c_clock_period[IVTV_MAX_CAR + + static unsigned int cardtype_c = 1; + static unsigned int tuner_c = 1; +-static bool radio_c = 1; ++static int radio_c = 1; + static unsigned int i2c_clock_period_c = 1; + static char pal[] = "---"; + static char secam[] = "--"; +@@ -139,7 +139,7 @@ static int tunertype = -1; + static int newi2c = -1; + + module_param_array(tuner, int, &tuner_c, 0644); +-module_param_array(radio, bool, &radio_c, 0644); ++module_param_array(radio, int, &radio_c, 0644); + module_param_array(cardtype, int, &cardtype_c, 0644); + module_param_string(pal, pal, sizeof(pal), 0644); + module_param_string(secam, secam, sizeof(secam), 0644); +@@ -744,8 +744,6 @@ static int __devinit ivtv_init_struct1(s + + itv->cur_dma_stream = -1; + itv->cur_pio_stream = -1; +- itv->audio_stereo_mode = AUDIO_STEREO; +- itv->audio_bilingual_mode = AUDIO_MONO_LEFT; + + /* Ctrls */ + itv->speed = 1000; +@@ -815,7 +813,7 @@ static int ivtv_setup_pci(struct ivtv *i + IVTV_ERR("Can't enable device!\n"); + return -EIO; + } +- if (pci_set_dma_mask(pdev, 0xffffffff)) { ++ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { + IVTV_ERR("No suitable DMA available.\n"); + return -EIO; + } +@@ -1200,6 +1198,32 @@ static int __devinit ivtv_probe(struct p + itv->tuner_std = itv->std; + + if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { ++ struct v4l2_ctrl_handler *hdl = itv->v4l2_dev.ctrl_handler; ++ ++ itv->ctrl_pts = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops, ++ V4L2_CID_MPEG_VIDEO_DEC_PTS, 0, 0, 1, 0); ++ itv->ctrl_frame = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops, ++ V4L2_CID_MPEG_VIDEO_DEC_FRAME, 0, 0x7fffffff, 1, 0); ++ /* Note: V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO is not supported, ++ mask that menu item. */ ++ itv->ctrl_audio_playback = ++ v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops, ++ V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO, ++ 1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO); ++ itv->ctrl_audio_multilingual_playback = ++ v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops, ++ V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO, ++ 1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT); ++ if (hdl->error) { ++ retval = hdl->error; ++ goto free_i2c; ++ } ++ v4l2_ctrl_cluster(2, &itv->ctrl_pts); ++ v4l2_ctrl_cluster(2, &itv->ctrl_audio_playback); + ivtv_call_all(itv, video, s_std_output, itv->std); + /* Turn off the output signal. The mpeg decoder is not yet + active so without this you would get a green image until the +@@ -1236,6 +1260,7 @@ free_streams: + free_irq: + free_irq(itv->pdev->irq, (void *)itv); + free_i2c: ++ v4l2_ctrl_handler_free(&itv->cxhdl.hdl); + exit_ivtv_i2c(itv); + free_io: + ivtv_iounmap(itv); +@@ -1375,7 +1400,7 @@ static void ivtv_remove(struct pci_dev * + else + type = IVTV_DEC_STREAM_TYPE_MPG; + ivtv_stop_v4l2_decode_stream(&itv->streams[type], +- VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); ++ V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0); + } + ivtv_halt_firmware(itv); + } +@@ -1391,6 +1416,8 @@ static void ivtv_remove(struct pci_dev * + ivtv_streams_cleanup(itv, 1); + ivtv_udma_free(itv); + ++ v4l2_ctrl_handler_free(&itv->cxhdl.hdl); ++ + exit_ivtv_i2c(itv); + + free_irq(itv->pdev->irq, (void *)itv); +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-fileops.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-fileops.c ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-fileops.c +@@ -746,8 +746,9 @@ unsigned int ivtv_v4l2_dec_poll(struct f + return res; + } + +-unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) ++unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table *wait) + { ++ unsigned long req_events = poll_requested_events(wait); + struct ivtv_open_id *id = fh2id(filp->private_data); + struct ivtv *itv = id->itv; + struct ivtv_stream *s = &itv->streams[id->type]; +@@ -755,7 +756,8 @@ unsigned int ivtv_v4l2_enc_poll(struct f + unsigned res = 0; + + /* Start a capture if there is none */ +- if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { ++ if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags) && ++ (req_events & (POLLIN | POLLRDNORM))) { + int rc; + + rc = ivtv_start_capture(id); +@@ -900,7 +902,7 @@ int ivtv_v4l2_close(struct file *filp) + if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { + struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT]; + +- ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); ++ ivtv_stop_decoding(id, V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0); + + /* If all output streams are closed, and if the user doesn't have + IVTV_DEC_STREAM_TYPE_VOUT open, then disable CC on TV-out. */ +Index: linux-3.3.x86_64/drivers/media/video/v4l2-ctrls.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/v4l2-ctrls.c ++++ linux-3.3.x86_64/drivers/media/video/v4l2-ctrls.c +@@ -175,6 +175,15 @@ const char * const *v4l2_ctrl_get_menu(u + "16-bit CRC", + NULL + }; ++ static const char * const mpeg_audio_dec_playback[] = { ++ "Auto", ++ "Stereo", ++ "Left", ++ "Right", ++ "Mono", ++ "Swapped Stereo", ++ NULL ++ }; + static const char * const mpeg_video_encoding[] = { + "MPEG-1", + "MPEG-2", +@@ -236,8 +245,8 @@ const char * const *v4l2_ctrl_get_menu(u + }; + static const char * const tune_preemphasis[] = { + "No Preemphasis", +- "50 useconds", +- "75 useconds", ++ "50 Microseconds", ++ "75 Microseconds", + NULL, + }; + static const char * const header_mode[] = { +@@ -334,7 +343,7 @@ const char * const *v4l2_ctrl_get_menu(u + }; + static const char * const mpeg4_profile[] = { + "Simple", +- "Adcanved Simple", ++ "Advanced Simple", + "Core", + "Simple Scalable", + "Advanced Coding Efficency", +@@ -353,6 +362,16 @@ const char * const *v4l2_ctrl_get_menu(u + NULL, + }; + ++ static const char * const jpeg_chroma_subsampling[] = { ++ "4:4:4", ++ "4:2:2", ++ "4:2:0", ++ "4:1:1", ++ "4:1:0", ++ "Gray", ++ NULL, ++ }; ++ + switch (id) { + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + return mpeg_audio_sampling_freq; +@@ -374,6 +393,9 @@ const char * const *v4l2_ctrl_get_menu(u + return mpeg_audio_emphasis; + case V4L2_CID_MPEG_AUDIO_CRC: + return mpeg_audio_crc; ++ case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: ++ case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: ++ return mpeg_audio_dec_playback; + case V4L2_CID_MPEG_VIDEO_ENCODING: + return mpeg_video_encoding; + case V4L2_CID_MPEG_VIDEO_ASPECT: +@@ -414,6 +436,9 @@ const char * const *v4l2_ctrl_get_menu(u + return mpeg_mpeg4_level; + case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: + return mpeg4_profile; ++ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: ++ return jpeg_chroma_subsampling; ++ + default: + return NULL; + } +@@ -492,6 +517,8 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_MPEG_AUDIO_MUTE: return "Audio Mute"; + case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: return "Audio AAC Bitrate"; + case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: return "Audio AC-3 Bitrate"; ++ case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: return "Audio Playback"; ++ case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: return "Audio Multilingual Playback"; + case V4L2_CID_MPEG_VIDEO_ENCODING: return "Video Encoding"; + case V4L2_CID_MPEG_VIDEO_ASPECT: return "Video Aspect"; + case V4L2_CID_MPEG_VIDEO_B_FRAMES: return "Video B Frames"; +@@ -546,6 +573,8 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: return "Number of MBs in a Slice"; + case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: return "Slice Partitioning Method"; + case V4L2_CID_MPEG_VIDEO_VBV_SIZE: return "VBV Buffer Size"; ++ case V4L2_CID_MPEG_VIDEO_DEC_PTS: return "Video Decoder PTS"; ++ case V4L2_CID_MPEG_VIDEO_DEC_FRAME: return "Video Decoder Frame Count"; + + /* CAMERA controls */ + /* Keep the order of the 'case's the same as in videodev2.h! */ +@@ -607,6 +636,14 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_FLASH_CHARGE: return "Charge"; + case V4L2_CID_FLASH_READY: return "Ready to Strobe"; + ++ /* JPEG encoder controls */ ++ /* Keep the order of the 'case's the same as in videodev2.h! */ ++ case V4L2_CID_JPEG_CLASS: return "JPEG Compression Controls"; ++ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: return "Chroma Subsampling"; ++ case V4L2_CID_JPEG_RESTART_INTERVAL: return "Restart Interval"; ++ case V4L2_CID_JPEG_COMPRESSION_QUALITY: return "Compression Quality"; ++ case V4L2_CID_JPEG_ACTIVE_MARKER: return "Active Markers"; ++ + default: + return NULL; + } +@@ -674,6 +711,8 @@ void v4l2_ctrl_fill(u32 id, const char * + case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: + case V4L2_CID_MPEG_AUDIO_EMPHASIS: + case V4L2_CID_MPEG_AUDIO_CRC: ++ case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: ++ case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: + case V4L2_CID_MPEG_VIDEO_ENCODING: + case V4L2_CID_MPEG_VIDEO_ASPECT: + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: +@@ -693,6 +732,7 @@ void v4l2_ctrl_fill(u32 id, const char * + case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: + case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: + case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: ++ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: + *type = V4L2_CTRL_TYPE_MENU; + break; + case V4L2_CID_RDS_TX_PS_NAME: +@@ -704,6 +744,7 @@ void v4l2_ctrl_fill(u32 id, const char * + case V4L2_CID_MPEG_CLASS: + case V4L2_CID_FM_TX_CLASS: + case V4L2_CID_FLASH_CLASS: ++ case V4L2_CID_JPEG_CLASS: + *type = V4L2_CTRL_TYPE_CTRL_CLASS; + /* You can neither read not write these */ + *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY; +@@ -717,6 +758,7 @@ void v4l2_ctrl_fill(u32 id, const char * + *max = 0xFFFFFF; + break; + case V4L2_CID_FLASH_FAULT: ++ case V4L2_CID_JPEG_ACTIVE_MARKER: + *type = V4L2_CTRL_TYPE_BITMASK; + break; + case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: +@@ -724,6 +766,11 @@ void v4l2_ctrl_fill(u32 id, const char * + *type = V4L2_CTRL_TYPE_INTEGER; + *flags |= V4L2_CTRL_FLAG_READ_ONLY; + break; ++ case V4L2_CID_MPEG_VIDEO_DEC_FRAME: ++ case V4L2_CID_MPEG_VIDEO_DEC_PTS: ++ *type = V4L2_CTRL_TYPE_INTEGER64; ++ *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_VOLATILE; ++ break; + default: + *type = V4L2_CTRL_TYPE_INTEGER; + break; +@@ -1470,7 +1517,7 @@ EXPORT_SYMBOL(v4l2_ctrl_add_ctrl); + int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl, + struct v4l2_ctrl_handler *add) + { +- struct v4l2_ctrl *ctrl; ++ struct v4l2_ctrl_ref *ref; + int ret = 0; + + /* Do nothing if either handler is NULL or if they are the same */ +@@ -1479,7 +1526,9 @@ int v4l2_ctrl_add_handler(struct v4l2_ct + if (hdl->error) + return hdl->error; + mutex_lock(&add->lock); +- list_for_each_entry(ctrl, &add->ctrls, node) { ++ list_for_each_entry(ref, &add->ctrl_refs, node) { ++ struct v4l2_ctrl *ctrl = ref->ctrl; ++ + /* Skip handler-private controls. */ + if (ctrl->is_private) + continue; +@@ -2359,3 +2408,35 @@ void v4l2_ctrl_del_event(struct v4l2_ctr + v4l2_ctrl_unlock(ctrl); + } + EXPORT_SYMBOL(v4l2_ctrl_del_event); ++ ++int v4l2_ctrl_log_status(struct file *file, void *fh) ++{ ++ struct video_device *vfd = video_devdata(file); ++ struct v4l2_fh *vfh = file->private_data; ++ ++ if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) && vfd->v4l2_dev) ++ v4l2_ctrl_handler_log_status(vfh->ctrl_handler, ++ vfd->v4l2_dev->name); ++ return 0; ++} ++EXPORT_SYMBOL(v4l2_ctrl_log_status); ++ ++int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, ++ struct v4l2_event_subscription *sub) ++{ ++ if (sub->type == V4L2_EVENT_CTRL) ++ return v4l2_event_subscribe(fh, sub, 0); ++ return -EINVAL; ++} ++EXPORT_SYMBOL(v4l2_ctrl_subscribe_event); ++ ++unsigned int v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait) ++{ ++ struct v4l2_fh *fh = file->private_data; ++ ++ if (v4l2_event_pending(fh)) ++ return POLLPRI; ++ poll_wait(file, &fh->wait, wait); ++ return 0; ++} ++EXPORT_SYMBOL(v4l2_ctrl_poll); +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-controls.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-controls.c ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-controls.c +@@ -21,6 +21,7 @@ + #include "ivtv-driver.h" + #include "ivtv-ioctl.h" + #include "ivtv-controls.h" ++#include "ivtv-mailbox.h" + + static int ivtv_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt) + { +@@ -99,3 +100,64 @@ struct cx2341x_handler_ops ivtv_cxhdl_op + .s_video_encoding = ivtv_s_video_encoding, + .s_stream_vbi_fmt = ivtv_s_stream_vbi_fmt, + }; ++ ++int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame) ++{ ++ u32 data[CX2341X_MBOX_MAX_DATA]; ++ ++ if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { ++ *pts = (s64)((u64)itv->last_dec_timing[2] << 32) | ++ (u64)itv->last_dec_timing[1]; ++ *frame = itv->last_dec_timing[0]; ++ return 0; ++ } ++ *pts = 0; ++ *frame = 0; ++ if (atomic_read(&itv->decoding)) { ++ if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { ++ IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); ++ return -EIO; ++ } ++ memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); ++ set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); ++ *pts = (s64)((u64) data[2] << 32) | (u64) data[1]; ++ *frame = data[0]; ++ /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/ ++ } ++ return 0; ++} ++ ++static int ivtv_g_volatile_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl); ++ ++ switch (ctrl->id) { ++ /* V4L2_CID_MPEG_VIDEO_DEC_PTS and V4L2_CID_MPEG_VIDEO_DEC_FRAME ++ control cluster */ ++ case V4L2_CID_MPEG_VIDEO_DEC_PTS: ++ return ivtv_g_pts_frame(itv, &itv->ctrl_pts->val64, ++ &itv->ctrl_frame->val64); ++ } ++ return 0; ++} ++ ++static int ivtv_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl); ++ ++ switch (ctrl->id) { ++ /* V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK and MULTILINGUAL_PLAYBACK ++ control cluster */ ++ case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: ++ itv->audio_stereo_mode = itv->ctrl_audio_playback->val - 1; ++ itv->audio_bilingual_mode = itv->ctrl_audio_multilingual_playback->val - 1; ++ ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); ++ break; ++ } ++ return 0; ++} ++ ++const struct v4l2_ctrl_ops ivtv_hdl_out_ops = { ++ .s_ctrl = ivtv_s_ctrl, ++ .g_volatile_ctrl = ivtv_g_volatile_ctrl, ++}; +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-controls.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-controls.h ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-controls.h +@@ -22,5 +22,7 @@ + #define IVTV_CONTROLS_H + + extern struct cx2341x_handler_ops ivtv_cxhdl_ops; ++extern const struct v4l2_ctrl_ops ivtv_hdl_out_ops; ++int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame); + + #endif +Index: linux-3.3.x86_64/drivers/media/dvb/ddbridge/ddbridge.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/ddbridge/ddbridge.h ++++ linux-3.3.x86_64/drivers/media/dvb/ddbridge/ddbridge.h +@@ -32,8 +32,6 @@ + #include + #include + #include +-#include +-#include + #include + + #include "dmxdev.h" +Index: linux-3.3.x86_64/drivers/media/video/cx18/cx18-driver.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx18/cx18-driver.h ++++ linux-3.3.x86_64/drivers/media/video/cx18/cx18-driver.h +@@ -44,8 +44,6 @@ + #include + #include + +-#include +-#include + #include + #include + #include +Index: linux-3.3.x86_64/include/linux/ivtv.h +=================================================================== +--- linux-3.3.x86_64.orig/include/linux/ivtv.h ++++ linux-3.3.x86_64/include/linux/ivtv.h +@@ -58,7 +58,11 @@ struct ivtv_dma_frame { + __u32 src_height; + }; + +-#define IVTV_IOC_DMA_FRAME _IOW ('V', BASE_VIDIOC_PRIVATE+0, struct ivtv_dma_frame) ++#define IVTV_IOC_DMA_FRAME _IOW ('V', BASE_VIDIOC_PRIVATE+0, struct ivtv_dma_frame) ++ ++/* Select the passthrough mode (if the argument is non-zero). In the passthrough ++ mode the output of the encoder is passed immediately into the decoder. */ ++#define IVTV_IOC_PASSTHROUGH_MODE _IOW ('V', BASE_VIDIOC_PRIVATE+1, int) + + /* Deprecated defines: applications should use the defines from videodev2.h */ + #define IVTV_SLICED_TYPE_TELETEXT_B V4L2_MPEG_VBI_IVTV_TELETEXT_B +Index: linux-3.3.x86_64/drivers/media/rc/keymaps/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/keymaps/Makefile ++++ linux-3.3.x86_64/drivers/media/rc/keymaps/Makefile +@@ -41,8 +41,11 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t + rc-imon-mce.o \ + rc-imon-pad.o \ + rc-iodata-bctv7e.o \ ++ rc-it913x-v1.o \ ++ rc-it913x-v2.o \ + rc-kaiomy.o \ + rc-kworld-315u.o \ ++ rc-kworld-pc150u.o \ + rc-kworld-plus-tv-analog.o \ + rc-leadtek-y04g0051.o \ + rc-lirc.o \ +Index: linux-3.3.x86_64/drivers/media/rc/keymaps/rc-it913x-v1.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/rc/keymaps/rc-it913x-v1.c +@@ -0,0 +1,95 @@ ++/* ITE Generic remotes Version 1 ++ * ++ * Copyright (C) 2012 Malcolm Priestley (tvboxspy@gmail.com) ++ * ++ * 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 ++ ++ ++static struct rc_map_table it913x_v1_rc[] = { ++ /* Type 1 */ ++ { 0x61d601, KEY_VIDEO }, /* Source */ ++ { 0x61d602, KEY_3 }, ++ { 0x61d603, KEY_POWER }, /* ShutDown */ ++ { 0x61d604, KEY_1 }, ++ { 0x61d605, KEY_5 }, ++ { 0x61d606, KEY_6 }, ++ { 0x61d607, KEY_CHANNELDOWN }, /* CH- */ ++ { 0x61d608, KEY_2 }, ++ { 0x61d609, KEY_CHANNELUP }, /* CH+ */ ++ { 0x61d60a, KEY_9 }, ++ { 0x61d60b, KEY_ZOOM }, /* Zoom */ ++ { 0x61d60c, KEY_7 }, ++ { 0x61d60d, KEY_8 }, ++ { 0x61d60e, KEY_VOLUMEUP }, /* Vol+ */ ++ { 0x61d60f, KEY_4 }, ++ { 0x61d610, KEY_ESC }, /* [back up arrow] */ ++ { 0x61d611, KEY_0 }, ++ { 0x61d612, KEY_OK }, /* [enter arrow] */ ++ { 0x61d613, KEY_VOLUMEDOWN }, /* Vol- */ ++ { 0x61d614, KEY_RECORD }, /* Rec */ ++ { 0x61d615, KEY_STOP }, /* Stop */ ++ { 0x61d616, KEY_PLAY }, /* Play */ ++ { 0x61d617, KEY_MUTE }, /* Mute */ ++ { 0x61d618, KEY_UP }, ++ { 0x61d619, KEY_DOWN }, ++ { 0x61d61a, KEY_LEFT }, ++ { 0x61d61b, KEY_RIGHT }, ++ { 0x61d61c, KEY_RED }, ++ { 0x61d61d, KEY_GREEN }, ++ { 0x61d61e, KEY_YELLOW }, ++ { 0x61d61f, KEY_BLUE }, ++ { 0x61d643, KEY_POWER2 }, /* [red power button] */ ++ /* Type 2 - 20 buttons */ ++ { 0x807f0d, KEY_0 }, ++ { 0x807f04, KEY_1 }, ++ { 0x807f05, KEY_2 }, ++ { 0x807f06, KEY_3 }, ++ { 0x807f07, KEY_4 }, ++ { 0x807f08, KEY_5 }, ++ { 0x807f09, KEY_6 }, ++ { 0x807f0a, KEY_7 }, ++ { 0x807f1b, KEY_8 }, ++ { 0x807f1f, KEY_9 }, ++ { 0x807f12, KEY_POWER }, ++ { 0x807f01, KEY_MEDIA_REPEAT}, /* Recall */ ++ { 0x807f19, KEY_PAUSE }, /* Timeshift */ ++ { 0x807f1e, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ ++ { 0x807f03, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ ++ { 0x807f1a, KEY_CHANNELUP }, ++ { 0x807f02, KEY_CHANNELDOWN }, ++ { 0x807f0c, KEY_ZOOM }, ++ { 0x807f00, KEY_RECORD }, ++ { 0x807f0e, KEY_STOP }, ++}; ++ ++static struct rc_map_list it913x_v1_map = { ++ .map = { ++ .scan = it913x_v1_rc, ++ .size = ARRAY_SIZE(it913x_v1_rc), ++ .rc_type = RC_TYPE_NEC, ++ .name = RC_MAP_IT913X_V1, ++ } ++}; ++ ++static int __init init_rc_it913x_v1_map(void) ++{ ++ return rc_map_register(&it913x_v1_map); ++} ++ ++static void __exit exit_rc_it913x_v1_map(void) ++{ ++ rc_map_unregister(&it913x_v1_map); ++} ++ ++module_init(init_rc_it913x_v1_map) ++module_exit(exit_rc_it913x_v1_map) ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); +Index: linux-3.3.x86_64/drivers/media/rc/keymaps/rc-it913x-v2.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/rc/keymaps/rc-it913x-v2.c +@@ -0,0 +1,94 @@ ++/* ITE Generic remotes Version 2 ++ * ++ * Copyright (C) 2012 Malcolm Priestley (tvboxspy@gmail.com) ++ * ++ * 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 ++ ++ ++static struct rc_map_table it913x_v2_rc[] = { ++ /* Type 1 */ ++ /* 9005 remote */ ++ { 0x807f12, KEY_POWER2 }, /* Power (RED POWER BUTTON)*/ ++ { 0x807f1a, KEY_VIDEO }, /* Source */ ++ { 0x807f1e, KEY_MUTE }, /* Mute */ ++ { 0x807f01, KEY_RECORD }, /* Record */ ++ { 0x807f02, KEY_CHANNELUP }, /* Channel+ */ ++ { 0x807f03, KEY_TIME }, /* TimeShift */ ++ { 0x807f04, KEY_VOLUMEUP }, /* Volume- */ ++ { 0x807f05, KEY_SCREEN }, /* FullScreen */ ++ { 0x807f06, KEY_VOLUMEDOWN }, /* Volume- */ ++ { 0x807f07, KEY_0 }, /* 0 */ ++ { 0x807f08, KEY_CHANNELDOWN }, /* Channel- */ ++ { 0x807f09, KEY_PREVIOUS }, /* Recall */ ++ { 0x807f0a, KEY_1 }, /* 1 */ ++ { 0x807f1b, KEY_2 }, /* 2 */ ++ { 0x807f1f, KEY_3 }, /* 3 */ ++ { 0x807f0c, KEY_4 }, /* 4 */ ++ { 0x807f0d, KEY_5 }, /* 5 */ ++ { 0x807f0e, KEY_6 }, /* 6 */ ++ { 0x807f00, KEY_7 }, /* 7 */ ++ { 0x807f0f, KEY_8 }, /* 8 */ ++ { 0x807f19, KEY_9 }, /* 9 */ ++ ++ /* Type 2 */ ++ /* keys stereo, snapshot unassigned */ ++ { 0x866b00, KEY_0 }, ++ { 0x866b1b, KEY_1 }, ++ { 0x866b02, KEY_2 }, ++ { 0x866b03, KEY_3 }, ++ { 0x866b04, KEY_4 }, ++ { 0x866b05, KEY_5 }, ++ { 0x866b06, KEY_6 }, ++ { 0x866b07, KEY_7 }, ++ { 0x866b08, KEY_8 }, ++ { 0x866b09, KEY_9 }, ++ { 0x866b12, KEY_POWER }, ++ { 0x866b13, KEY_MUTE }, ++ { 0x866b0a, KEY_PREVIOUS }, /* Recall */ ++ { 0x866b1e, KEY_PAUSE }, ++ { 0x866b0c, KEY_VOLUMEUP }, ++ { 0x866b18, KEY_VOLUMEDOWN }, ++ { 0x866b0b, KEY_CHANNELUP }, ++ { 0x866b18, KEY_CHANNELDOWN }, ++ { 0x866b10, KEY_ZOOM }, ++ { 0x866b1d, KEY_RECORD }, ++ { 0x866b0e, KEY_STOP }, ++ { 0x866b11, KEY_EPG}, ++ { 0x866b1a, KEY_FASTFORWARD }, ++ { 0x866b0f, KEY_REWIND }, ++ { 0x866b1c, KEY_TV }, ++ { 0x866b1b, KEY_TEXT }, ++ ++}; ++ ++static struct rc_map_list it913x_v2_map = { ++ .map = { ++ .scan = it913x_v2_rc, ++ .size = ARRAY_SIZE(it913x_v2_rc), ++ .rc_type = RC_TYPE_NEC, ++ .name = RC_MAP_IT913X_V2, ++ } ++}; ++ ++static int __init init_rc_it913x_v2_map(void) ++{ ++ return rc_map_register(&it913x_v2_map); ++} ++ ++static void __exit exit_rc_it913x_v2_map(void) ++{ ++ rc_map_unregister(&it913x_v2_map); ++} ++ ++module_init(init_rc_it913x_v2_map) ++module_exit(exit_rc_it913x_v2_map) ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); +Index: linux-3.3.x86_64/include/media/rc-map.h +=================================================================== +--- linux-3.3.x86_64.orig/include/media/rc-map.h ++++ linux-3.3.x86_64/include/media/rc-map.h +@@ -102,8 +102,11 @@ void rc_map_init(void); + #define RC_MAP_IMON_MCE "rc-imon-mce" + #define RC_MAP_IMON_PAD "rc-imon-pad" + #define RC_MAP_IODATA_BCTV7E "rc-iodata-bctv7e" ++#define RC_MAP_IT913X_V1 "rc-it913x-v1" ++#define RC_MAP_IT913X_V2 "rc-it913x-v2" + #define RC_MAP_KAIOMY "rc-kaiomy" + #define RC_MAP_KWORLD_315U "rc-kworld-315u" ++#define RC_MAP_KWORLD_PC150U "rc-kworld-pc150u" + #define RC_MAP_KWORLD_PLUS_TV_ANALOG "rc-kworld-plus-tv-analog" + #define RC_MAP_LEADTEK_Y04G0051 "rc-leadtek-y04g0051" + #define RC_MAP_LIRC "rc-lirc" +Index: linux-3.3.x86_64/drivers/media/video/bt8xx/bttv-driver.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/bt8xx/bttv-driver.c ++++ linux-3.3.x86_64/drivers/media/video/bt8xx/bttv-driver.c +@@ -2035,11 +2035,7 @@ static int bttv_log_status(struct file * + struct bttv_fh *fh = f; + struct bttv *btv = fh->btv; + +- pr_info("%d: ======== START STATUS CARD #%d ========\n", +- btv->c.nr, btv->c.nr); + bttv_call_all(btv, core, log_status); +- pr_info("%d: ======== END STATUS CARD #%d ========\n", +- btv->c.nr, btv->c.nr); + return 0; + } + +Index: linux-3.3.x86_64/drivers/media/video/cx18/cx18-ioctl.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx18/cx18-ioctl.c ++++ linux-3.3.x86_64/drivers/media/video/cx18/cx18-ioctl.c +@@ -1085,8 +1085,6 @@ static int cx18_log_status(struct file * + struct v4l2_audio audin; + int i; + +- CX18_INFO("================= START STATUS CARD #%d " +- "=================\n", cx->instance); + CX18_INFO("Version: %s Card: %s\n", CX18_VERSION, cx->card_name); + if (cx->hw_flags & CX18_HW_TVEEPROM) { + struct tveeprom tv; +@@ -1120,8 +1118,6 @@ static int cx18_log_status(struct file * + CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", + (long long)cx->mpg_data_received, + (long long)cx->vbi_data_inserted); +- CX18_INFO("================== END STATUS CARD #%d " +- "==================\n", cx->instance); + return 0; + } + +Index: linux-3.3.x86_64/drivers/media/video/pwc/pwc-v4l.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/pwc/pwc-v4l.c ++++ linux-3.3.x86_64/drivers/media/video/pwc/pwc-v4l.c +@@ -1146,14 +1146,6 @@ leave: + return ret; + } + +-static int pwc_log_status(struct file *file, void *priv) +-{ +- struct pwc_device *pdev = video_drvdata(file); +- +- v4l2_ctrl_handler_log_status(&pdev->ctrl_handler, PWC_NAME); +- return 0; +-} +- + const struct v4l2_ioctl_ops pwc_ioctl_ops = { + .vidioc_querycap = pwc_querycap, + .vidioc_enum_input = pwc_enum_input, +@@ -1169,9 +1161,11 @@ const struct v4l2_ioctl_ops pwc_ioctl_op + .vidioc_dqbuf = pwc_dqbuf, + .vidioc_streamon = pwc_streamon, + .vidioc_streamoff = pwc_streamoff, +- .vidioc_log_status = pwc_log_status, ++ .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_enum_framesizes = pwc_enum_framesizes, + .vidioc_enum_frameintervals = pwc_enum_frameintervals, + .vidioc_g_parm = pwc_g_parm, + .vidioc_s_parm = pwc_s_parm, ++ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + }; +Index: linux-3.3.x86_64/drivers/media/video/saa7164/saa7164-encoder.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7164/saa7164-encoder.c ++++ linux-3.3.x86_64/drivers/media/video/saa7164/saa7164-encoder.c +@@ -791,11 +791,6 @@ static int vidioc_s_fmt_vid_cap(struct f + return 0; + } + +-static int vidioc_log_status(struct file *file, void *priv) +-{ +- return 0; +-} +- + static int fill_queryctrl(struct saa7164_encoder_params *params, + struct v4l2_queryctrl *c) + { +@@ -1347,7 +1342,6 @@ static const struct v4l2_ioctl_ops mpeg_ + .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, + .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, + .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, +- .vidioc_log_status = vidioc_log_status, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_chip_ident = saa7164_g_chip_ident, + #ifdef CONFIG_VIDEO_ADV_DEBUG +Index: linux-3.3.x86_64/drivers/media/video/saa7164/saa7164-vbi.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7164/saa7164-vbi.c ++++ linux-3.3.x86_64/drivers/media/video/saa7164/saa7164-vbi.c +@@ -730,11 +730,6 @@ static int vidioc_s_fmt_vid_cap(struct f + return 0; + } + +-static int vidioc_log_status(struct file *file, void *priv) +-{ +- return 0; +-} +- + static int fill_queryctrl(struct saa7164_vbi_params *params, + struct v4l2_queryctrl *c) + { +@@ -1256,7 +1251,6 @@ static const struct v4l2_ioctl_ops vbi_i + .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, + .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, + .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, +- .vidioc_log_status = vidioc_log_status, + .vidioc_queryctrl = vidioc_queryctrl, + #if 0 + .vidioc_g_chip_ident = saa7164_g_chip_ident, +Index: linux-3.3.x86_64/include/media/v4l2-ctrls.h +=================================================================== +--- linux-3.3.x86_64.orig/include/media/v4l2-ctrls.h ++++ linux-3.3.x86_64/include/media/v4l2-ctrls.h +@@ -33,6 +33,7 @@ struct video_device; + struct v4l2_subdev; + struct v4l2_subscribed_event; + struct v4l2_fh; ++struct poll_table_struct; + + /** struct v4l2_ctrl_ops - The control operations that the driver has to provide. + * @g_volatile_ctrl: Get a new value for this control. Generally only relevant +@@ -492,6 +493,18 @@ void v4l2_ctrl_add_event(struct v4l2_ctr + void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl, + struct v4l2_subscribed_event *sev); + ++/* Can be used as a vidioc_log_status function that just dumps all controls ++ associated with the filehandle. */ ++int v4l2_ctrl_log_status(struct file *file, void *fh); ++ ++/* Can be used as a vidioc_subscribe_event function that just subscribes ++ control events. */ ++int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, ++ struct v4l2_event_subscription *sub); ++ ++/* Can be used as a poll function that just polls for control events. */ ++unsigned int v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait); ++ + /* Helpers for ioctl_ops. If hdl == NULL then they will all return -EINVAL. */ + int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc); + int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm); +Index: linux-3.3.x86_64/drivers/media/video/v4l2-subdev.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/v4l2-subdev.c ++++ linux-3.3.x86_64/drivers/media/video/v4l2-subdev.c +@@ -194,8 +194,16 @@ static long subdev_do_ioctl(struct file + } + #endif + +- case VIDIOC_LOG_STATUS: +- return v4l2_subdev_call(sd, core, log_status); ++ case VIDIOC_LOG_STATUS: { ++ int ret; ++ ++ pr_info("%s: ================= START STATUS =================\n", ++ sd->name); ++ ret = v4l2_subdev_call(sd, core, log_status); ++ pr_info("%s: ================== END STATUS ==================\n", ++ sd->name); ++ return ret; ++ } + + #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) + case VIDIOC_SUBDEV_G_FMT: { +Index: linux-3.3.x86_64/drivers/media/radio/Kconfig +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/Kconfig ++++ linux-3.3.x86_64/drivers/media/radio/Kconfig +@@ -43,7 +43,7 @@ config USB_DSBR + + config RADIO_MAXIRADIO + tristate "Guillemot MAXI Radio FM 2000 radio" +- depends on VIDEO_V4L2 && PCI ++ depends on VIDEO_V4L2 && PCI && SND + ---help--- + Choose Y here if you have this radio card. This card may also be + found as Gemtek PCI FM. +@@ -80,6 +80,16 @@ config RADIO_SI4713 + To compile this driver as a module, choose M here: the + module will be called radio-si4713. + ++config USB_KEENE ++ tristate "Keene FM Transmitter USB support" ++ depends on USB && VIDEO_V4L2 ++ ---help--- ++ Say Y here if you want to connect this type of FM transmitter ++ to your computer's USB port. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called radio-keene. ++ + config RADIO_TEA5764 + tristate "TEA5764 I2C FM radio support" + depends on I2C && VIDEO_V4L2 +@@ -167,6 +177,10 @@ menuconfig V4L_RADIO_ISA_DRIVERS + + if V4L_RADIO_ISA_DRIVERS + ++config RADIO_ISA ++ depends on ISA ++ tristate ++ + config RADIO_CADET + tristate "ADS Cadet AM/FM Tuner" + depends on ISA && VIDEO_V4L2 +@@ -174,20 +188,13 @@ config RADIO_CADET + Choose Y here if you have one of these AM/FM radio cards, and then + fill in the port address below. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . +- +- Further documentation on this driver can be found on the WWW at +- . +- + To compile this driver as a module, choose M here: the + module will be called radio-cadet. + + config RADIO_RTRACK + tristate "AIMSlab RadioTrack (aka RadioReveal) support" + depends on ISA && VIDEO_V4L2 ++ select RADIO_ISA + ---help--- + Choose Y here if you have one of these FM radio cards, and then fill + in the port address below. +@@ -201,11 +208,7 @@ config RADIO_RTRACK + You must also pass the module a suitable io parameter, 0x248 has + been reported to be used by these cards. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . More information is +- contained in the file ++ More information is contained in the file + . + + To compile this driver as a module, choose M here: the +@@ -214,7 +217,7 @@ config RADIO_RTRACK + config RADIO_RTRACK_PORT + hex "RadioTrack i/o port (0x20f or 0x30f)" + depends on RADIO_RTRACK=y +- default "20f" ++ default "30f" + help + Enter either 0x30f or 0x20f here. The card default is 0x30f, if you + haven't changed the jumper setting on the card. +@@ -222,14 +225,14 @@ config RADIO_RTRACK_PORT + config RADIO_RTRACK2 + tristate "AIMSlab RadioTrack II support" + depends on ISA && VIDEO_V4L2 ++ select RADIO_ISA + ---help--- + Choose Y here if you have this FM radio card, and then fill in the + port address below. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . ++ Note: this driver hasn't been tested since a long time due to lack ++ of hardware. If you have this hardware, then please contact the ++ linux-media mailinglist. + + To compile this driver as a module, choose M here: the + module will be called radio-rtrack2. +@@ -245,15 +248,11 @@ config RADIO_RTRACK2_PORT + config RADIO_AZTECH + tristate "Aztech/Packard Bell Radio" + depends on ISA && VIDEO_V4L2 ++ select RADIO_ISA + ---help--- + Choose Y here if you have one of these FM radio cards, and then fill + in the port address below. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . +- + To compile this driver as a module, choose M here: the + module will be called radio-aztech. + +@@ -269,6 +268,7 @@ config RADIO_AZTECH_PORT + config RADIO_GEMTEK + tristate "GemTek Radio card (or compatible) support" + depends on ISA && VIDEO_V4L2 ++ select RADIO_ISA + ---help--- + Choose Y here if you have this FM radio card, and then fill in the + I/O port address and settings below. The following cards either have +@@ -278,23 +278,21 @@ config RADIO_GEMTEK + - Typhoon Radio card (some models) + - Hama Radio card + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . +- + To compile this driver as a module, choose M here: the + module will be called radio-gemtek. + + config RADIO_GEMTEK_PORT +- hex "Fixed I/O port (0x20c, 0x30c, 0x24c, 0x34c, 0c24c or 0x28c)" ++ hex "Fixed I/O port (0x20c, 0x30c, 0x24c, 0x34c, 0x248 or 0x28c)" + depends on RADIO_GEMTEK=y + default "34c" + help +- Enter either 0x20c, 0x30c, 0x24c or 0x34c here. The card default is +- 0x34c, if you haven't changed the jumper setting on the card. On +- Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the I/O ++ Enter either 0x20c, 0x30c, 0x24c, 0x34c, 0x248 or 0x28c here. The ++ card default is 0x34c, if you haven't changed the jumper setting ++ on the card. ++ ++ On Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the I/O + port is 0x20c, 0x248 or 0x28c. ++ + If automatic I/O port probing is enabled this port will be used only + in case of automatic probing failure, ie. as a fallback. + +@@ -318,11 +316,6 @@ config RADIO_MIROPCM20 + sound card driver "Miro miroSOUND PCM1pro/PCM12/PCM20radio" as this + is required for the radio-miropcm20. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . +- + To compile this driver as a module, choose M here: the + module will be called radio-miropcm20. + +@@ -332,11 +325,6 @@ config RADIO_SF16FMI + ---help--- + Choose Y here if you have one of these FM radio cards. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . +- + To compile this driver as a module, choose M here: the + module will be called radio-sf16fmi. + +@@ -346,50 +334,35 @@ config RADIO_SF16FMR2 + ---help--- + Choose Y here if you have one of these FM radio cards. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found on the WWW at +- . +- + To compile this driver as a module, choose M here: the + module will be called radio-sf16fmr2. + + config RADIO_TERRATEC + tristate "TerraTec ActiveRadio ISA Standalone" + depends on ISA && VIDEO_V4L2 ++ select RADIO_ISA + ---help--- +- Choose Y here if you have this FM radio card, and then fill in the +- port address below. (TODO) +- +- Note: This driver is in its early stages. Right now volume and +- frequency control and muting works at least for me, but +- unfortunately I have not found anybody who wants to use this card +- with Linux. So if it is this what YOU are trying to do right now, +- PLEASE DROP ME A NOTE!! Rolf Offermanns . ++ Choose Y here if you have this FM radio card. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . ++ Note: this driver hasn't been tested since a long time due to lack ++ of hardware. If you have this hardware, then please contact the ++ linux-media mailinglist. + + To compile this driver as a module, choose M here: the + module will be called radio-terratec. + +-config RADIO_TERRATEC_PORT +- hex "Terratec i/o port (normally 0x590)" +- depends on RADIO_TERRATEC=y +- default "590" +- help +- Fill in the I/O port of your TerraTec FM radio card. If unsure, go +- with the default. +- + config RADIO_TRUST + tristate "Trust FM radio card" + depends on ISA && VIDEO_V4L2 ++ select RADIO_ISA + help + This is a driver for the Trust FM radio cards. Say Y if you have + such a card and want to use it under Linux. + ++ Note: this driver hasn't been tested since a long time due to lack ++ of hardware. If you have this hardware, then please contact the ++ linux-media mailinglist. ++ + To compile this driver as a module, choose M here: the + module will be called radio-trust. + +@@ -404,14 +377,14 @@ config RADIO_TRUST_PORT + config RADIO_TYPHOON + tristate "Typhoon Radio (a.k.a. EcoRadio)" + depends on ISA && VIDEO_V4L2 ++ select RADIO_ISA + ---help--- + Choose Y here if you have one of these FM radio cards, and then fill + in the port address and the frequency used for muting below. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . ++ Note: this driver hasn't been tested since a long time due to lack ++ of hardware. If you have this hardware, then please contact the ++ linux-media mailinglist. + + To compile this driver as a module, choose M here: the + module will be called radio-typhoon. +@@ -438,14 +411,14 @@ config RADIO_TYPHOON_MUTEFREQ + config RADIO_ZOLTRIX + tristate "Zoltrix Radio" + depends on ISA && VIDEO_V4L2 ++ select RADIO_ISA + ---help--- + Choose Y here if you have one of these FM radio cards, and then fill + in the port address below. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . ++ Note: this driver hasn't been tested since a long time due to lack ++ of hardware. If you have this hardware, then please contact the ++ linux-media mailinglist. + + To compile this driver as a module, choose M here: the + module will be called radio-zoltrix. +Index: linux-3.3.x86_64/drivers/media/radio/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/Makefile ++++ linux-3.3.x86_64/drivers/media/radio/Makefile +@@ -2,6 +2,7 @@ + # Makefile for the kernel character device drivers. + # + ++obj-$(CONFIG_RADIO_ISA) += radio-isa.o + obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o + obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o + obj-$(CONFIG_RADIO_SF16FMI) += radio-sf16fmi.o +@@ -20,6 +21,7 @@ obj-$(CONFIG_RADIO_MIROPCM20) += radio-m + obj-$(CONFIG_USB_DSBR) += dsbr100.o + obj-$(CONFIG_RADIO_SI470X) += si470x/ + obj-$(CONFIG_USB_MR800) += radio-mr800.o ++obj-$(CONFIG_USB_KEENE) += radio-keene.o + obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o + obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o + obj-$(CONFIG_RADIO_TEF6862) += tef6862.o +Index: linux-3.3.x86_64/drivers/media/radio/radio-keene.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/radio/radio-keene.c +@@ -0,0 +1,427 @@ ++/* ++ * Copyright (c) 2012 Hans Verkuil ++ * ++ * 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 ++ */ ++ ++/* kernel includes */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* driver and module definitions */ ++MODULE_AUTHOR("Hans Verkuil "); ++MODULE_DESCRIPTION("Keene FM Transmitter driver"); ++MODULE_LICENSE("GPL"); ++ ++/* Actually, it advertises itself as a Logitech */ ++#define USB_KEENE_VENDOR 0x046d ++#define USB_KEENE_PRODUCT 0x0a0e ++ ++/* Probably USB_TIMEOUT should be modified in module parameter */ ++#define BUFFER_LENGTH 8 ++#define USB_TIMEOUT 500 ++ ++/* Frequency limits in MHz */ ++#define FREQ_MIN 76U ++#define FREQ_MAX 108U ++#define FREQ_MUL 16000U ++ ++/* USB Device ID List */ ++static struct usb_device_id usb_keene_device_table[] = { ++ {USB_DEVICE_AND_INTERFACE_INFO(USB_KEENE_VENDOR, USB_KEENE_PRODUCT, ++ USB_CLASS_HID, 0, 0) }, ++ { } /* Terminating entry */ ++}; ++ ++MODULE_DEVICE_TABLE(usb, usb_keene_device_table); ++ ++struct keene_device { ++ struct usb_device *usbdev; ++ struct usb_interface *intf; ++ struct video_device vdev; ++ struct v4l2_device v4l2_dev; ++ struct v4l2_ctrl_handler hdl; ++ struct mutex lock; ++ ++ u8 *buffer; ++ unsigned curfreq; ++ u8 tx; ++ u8 pa; ++ bool stereo; ++ bool muted; ++ bool preemph_75_us; ++}; ++ ++static inline struct keene_device *to_keene_dev(struct v4l2_device *v4l2_dev) ++{ ++ return container_of(v4l2_dev, struct keene_device, v4l2_dev); ++} ++ ++/* Set frequency (if non-0), PA, mute and turn on/off the FM transmitter. */ ++static int keene_cmd_main(struct keene_device *radio, unsigned freq, bool play) ++{ ++ unsigned short freq_send = freq ? (freq - 76 * 16000) / 800 : 0; ++ int ret; ++ ++ radio->buffer[0] = 0x00; ++ radio->buffer[1] = 0x50; ++ radio->buffer[2] = (freq_send >> 8) & 0xff; ++ radio->buffer[3] = freq_send & 0xff; ++ radio->buffer[4] = radio->pa; ++ /* If bit 4 is set, then tune to the frequency. ++ If bit 3 is set, then unmute; if bit 2 is set, then mute. ++ If bit 1 is set, then enter idle mode; if bit 0 is set, ++ then enter transit mode. ++ */ ++ radio->buffer[5] = (radio->muted ? 4 : 8) | (play ? 1 : 2) | ++ (freq ? 0x10 : 0); ++ radio->buffer[6] = 0x00; ++ radio->buffer[7] = 0x00; ++ ++ ret = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0), ++ 9, 0x21, 0x200, 2, radio->buffer, BUFFER_LENGTH, USB_TIMEOUT); ++ ++ if (ret < 0) { ++ dev_warn(&radio->vdev.dev, "%s failed (%d)\n", __func__, ret); ++ return ret; ++ } ++ if (freq) ++ radio->curfreq = freq; ++ return 0; ++} ++ ++/* Set TX, stereo and preemphasis mode (50 us vs 75 us). */ ++static int keene_cmd_set(struct keene_device *radio) ++{ ++ int ret; ++ ++ radio->buffer[0] = 0x00; ++ radio->buffer[1] = 0x51; ++ radio->buffer[2] = radio->tx; ++ /* If bit 0 is set, then transmit mono, otherwise stereo. ++ If bit 2 is set, then enable 75 us preemphasis, otherwise ++ it is 50 us. */ ++ radio->buffer[3] = (!radio->stereo) | (radio->preemph_75_us ? 4 : 0); ++ radio->buffer[4] = 0x00; ++ radio->buffer[5] = 0x00; ++ radio->buffer[6] = 0x00; ++ radio->buffer[7] = 0x00; ++ ++ ret = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0), ++ 9, 0x21, 0x200, 2, radio->buffer, BUFFER_LENGTH, USB_TIMEOUT); ++ ++ if (ret < 0) { ++ dev_warn(&radio->vdev.dev, "%s failed (%d)\n", __func__, ret); ++ return ret; ++ } ++ return 0; ++} ++ ++/* Handle unplugging the device. ++ * We call video_unregister_device in any case. ++ * The last function called in this procedure is ++ * usb_keene_device_release. ++ */ ++static void usb_keene_disconnect(struct usb_interface *intf) ++{ ++ struct keene_device *radio = to_keene_dev(usb_get_intfdata(intf)); ++ ++ v4l2_device_get(&radio->v4l2_dev); ++ mutex_lock(&radio->lock); ++ usb_set_intfdata(intf, NULL); ++ video_unregister_device(&radio->vdev); ++ v4l2_device_disconnect(&radio->v4l2_dev); ++ mutex_unlock(&radio->lock); ++ v4l2_device_put(&radio->v4l2_dev); ++} ++ ++static int vidioc_querycap(struct file *file, void *priv, ++ struct v4l2_capability *v) ++{ ++ struct keene_device *radio = video_drvdata(file); ++ ++ strlcpy(v->driver, "radio-keene", sizeof(v->driver)); ++ strlcpy(v->card, "Keene FM Transmitter", sizeof(v->card)); ++ usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info)); ++ v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_MODULATOR; ++ v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; ++ return 0; ++} ++ ++static int vidioc_g_modulator(struct file *file, void *priv, ++ struct v4l2_modulator *v) ++{ ++ struct keene_device *radio = video_drvdata(file); ++ ++ if (v->index > 0) ++ return -EINVAL; ++ ++ strlcpy(v->name, "FM", sizeof(v->name)); ++ v->rangelow = FREQ_MIN * FREQ_MUL; ++ v->rangehigh = FREQ_MAX * FREQ_MUL; ++ v->txsubchans = radio->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; ++ v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; ++ return 0; ++} ++ ++static int vidioc_s_modulator(struct file *file, void *priv, ++ struct v4l2_modulator *v) ++{ ++ struct keene_device *radio = video_drvdata(file); ++ ++ if (v->index > 0) ++ return -EINVAL; ++ ++ radio->stereo = (v->txsubchans == V4L2_TUNER_SUB_STEREO); ++ return keene_cmd_set(radio); ++} ++ ++static int vidioc_s_frequency(struct file *file, void *priv, ++ struct v4l2_frequency *f) ++{ ++ struct keene_device *radio = video_drvdata(file); ++ ++ if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) ++ return -EINVAL; ++ f->frequency = clamp(f->frequency, ++ FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL); ++ return keene_cmd_main(radio, f->frequency, true); ++} ++ ++static int vidioc_g_frequency(struct file *file, void *priv, ++ struct v4l2_frequency *f) ++{ ++ struct keene_device *radio = video_drvdata(file); ++ ++ if (f->tuner != 0) ++ return -EINVAL; ++ f->type = V4L2_TUNER_RADIO; ++ f->frequency = radio->curfreq; ++ return 0; ++} ++ ++static int keene_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ static const u8 db2tx[] = { ++ /* -15, -12, -9, -6, -3, 0 dB */ ++ 0x03, 0x13, 0x02, 0x12, 0x22, 0x32, ++ /* 3, 6, 9, 12, 15, 18 dB */ ++ 0x21, 0x31, 0x20, 0x30, 0x40, 0x50 ++ }; ++ struct keene_device *radio = ++ container_of(ctrl->handler, struct keene_device, hdl); ++ ++ switch (ctrl->id) { ++ case V4L2_CID_AUDIO_MUTE: ++ radio->muted = ctrl->val; ++ return keene_cmd_main(radio, 0, true); ++ ++ case V4L2_CID_TUNE_POWER_LEVEL: ++ /* To go from dBuV to the register value we apply the ++ following formula: */ ++ radio->pa = (ctrl->val - 71) * 100 / 62; ++ return keene_cmd_main(radio, 0, true); ++ ++ case V4L2_CID_TUNE_PREEMPHASIS: ++ radio->preemph_75_us = ctrl->val == V4L2_PREEMPHASIS_75_uS; ++ return keene_cmd_set(radio); ++ ++ case V4L2_CID_AUDIO_COMPRESSION_GAIN: ++ radio->tx = db2tx[(ctrl->val - ctrl->minimum) / ctrl->step]; ++ return keene_cmd_set(radio); ++ } ++ return -EINVAL; ++} ++ ++static int vidioc_subscribe_event(struct v4l2_fh *fh, ++ struct v4l2_event_subscription *sub) ++{ ++ switch (sub->type) { ++ case V4L2_EVENT_CTRL: ++ return v4l2_event_subscribe(fh, sub, 0); ++ default: ++ return -EINVAL; ++ } ++} ++ ++ ++/* File system interface */ ++static const struct v4l2_file_operations usb_keene_fops = { ++ .owner = THIS_MODULE, ++ .open = v4l2_fh_open, ++ .release = v4l2_fh_release, ++ .poll = v4l2_ctrl_poll, ++ .unlocked_ioctl = video_ioctl2, ++}; ++ ++static const struct v4l2_ctrl_ops keene_ctrl_ops = { ++ .s_ctrl = keene_s_ctrl, ++}; ++ ++static const struct v4l2_ioctl_ops usb_keene_ioctl_ops = { ++ .vidioc_querycap = vidioc_querycap, ++ .vidioc_g_modulator = vidioc_g_modulator, ++ .vidioc_s_modulator = vidioc_s_modulator, ++ .vidioc_g_frequency = vidioc_g_frequency, ++ .vidioc_s_frequency = vidioc_s_frequency, ++ .vidioc_log_status = v4l2_ctrl_log_status, ++ .vidioc_subscribe_event = vidioc_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, ++}; ++ ++static void usb_keene_video_device_release(struct v4l2_device *v4l2_dev) ++{ ++ struct keene_device *radio = to_keene_dev(v4l2_dev); ++ ++ /* free rest memory */ ++ v4l2_ctrl_handler_free(&radio->hdl); ++ kfree(radio->buffer); ++ kfree(radio); ++} ++ ++/* check if the device is present and register with v4l and usb if it is */ ++static int usb_keene_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ struct usb_device *dev = interface_to_usbdev(intf); ++ struct keene_device *radio; ++ struct v4l2_ctrl_handler *hdl; ++ int retval = 0; ++ ++ /* ++ * The Keene FM transmitter USB device has the same USB ID as ++ * the Logitech AudioHub Speaker, but it should ignore the hid. ++ * Check if the name is that of the Keene device. ++ * If not, then someone connected the AudioHub and we shouldn't ++ * attempt to handle this driver. ++ * For reference: the product name of the AudioHub is ++ * "AudioHub Speaker". ++ */ ++ if (dev->product && strcmp(dev->product, "B-LINK USB Audio ")) ++ return -ENODEV; ++ ++ radio = kzalloc(sizeof(struct keene_device), GFP_KERNEL); ++ if (radio) ++ radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL); ++ ++ if (!radio || !radio->buffer) { ++ dev_err(&intf->dev, "kmalloc for keene_device failed\n"); ++ kfree(radio); ++ retval = -ENOMEM; ++ goto err; ++ } ++ ++ hdl = &radio->hdl; ++ v4l2_ctrl_handler_init(hdl, 4); ++ v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_AUDIO_MUTE, ++ 0, 1, 1, 0); ++ v4l2_ctrl_new_std_menu(hdl, &keene_ctrl_ops, V4L2_CID_TUNE_PREEMPHASIS, ++ V4L2_PREEMPHASIS_75_uS, 1, V4L2_PREEMPHASIS_50_uS); ++ v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_TUNE_POWER_LEVEL, ++ 84, 118, 1, 118); ++ v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_AUDIO_COMPRESSION_GAIN, ++ -15, 18, 3, 0); ++ radio->pa = 118; ++ radio->tx = 0x32; ++ radio->stereo = true; ++ radio->curfreq = 95.16 * FREQ_MUL; ++ if (hdl->error) { ++ retval = hdl->error; ++ ++ v4l2_ctrl_handler_free(hdl); ++ goto err_v4l2; ++ } ++ retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev); ++ if (retval < 0) { ++ dev_err(&intf->dev, "couldn't register v4l2_device\n"); ++ goto err_v4l2; ++ } ++ ++ mutex_init(&radio->lock); ++ ++ radio->v4l2_dev.ctrl_handler = hdl; ++ radio->v4l2_dev.release = usb_keene_video_device_release; ++ strlcpy(radio->vdev.name, radio->v4l2_dev.name, ++ sizeof(radio->vdev.name)); ++ radio->vdev.v4l2_dev = &radio->v4l2_dev; ++ radio->vdev.fops = &usb_keene_fops; ++ radio->vdev.ioctl_ops = &usb_keene_ioctl_ops; ++ radio->vdev.lock = &radio->lock; ++ radio->vdev.release = video_device_release_empty; ++ ++ radio->usbdev = interface_to_usbdev(intf); ++ radio->intf = intf; ++ usb_set_intfdata(intf, &radio->v4l2_dev); ++ ++ video_set_drvdata(&radio->vdev, radio); ++ set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags); ++ ++ retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO, -1); ++ if (retval < 0) { ++ dev_err(&intf->dev, "could not register video device\n"); ++ goto err_vdev; ++ } ++ v4l2_ctrl_handler_setup(hdl); ++ dev_info(&intf->dev, "V4L2 device registered as %s\n", ++ video_device_node_name(&radio->vdev)); ++ return 0; ++ ++err_vdev: ++ v4l2_device_unregister(&radio->v4l2_dev); ++err_v4l2: ++ kfree(radio->buffer); ++ kfree(radio); ++err: ++ return retval; ++} ++ ++/* USB subsystem interface */ ++static struct usb_driver usb_keene_driver = { ++ .name = "radio-keene", ++ .probe = usb_keene_probe, ++ .disconnect = usb_keene_disconnect, ++ .id_table = usb_keene_device_table, ++}; ++ ++static int __init keene_init(void) ++{ ++ int retval = usb_register(&usb_keene_driver); ++ ++ if (retval) ++ pr_err(KBUILD_MODNAME ++ ": usb_register failed. Error number %d\n", retval); ++ ++ return retval; ++} ++ ++static void __exit keene_exit(void) ++{ ++ usb_deregister(&usb_keene_driver); ++} ++ ++module_init(keene_init); ++module_exit(keene_exit); ++ +Index: linux-3.3.x86_64/drivers/media/rc/fintek-cir.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/fintek-cir.c ++++ linux-3.3.x86_64/drivers/media/rc/fintek-cir.c +@@ -117,7 +117,7 @@ static u8 fintek_cir_reg_read(struct fin + static void cir_dump_regs(struct fintek_dev *fintek) + { + fintek_config_mode_enable(fintek); +- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); ++ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); + + pr_reg("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME); + pr_reg(" * CR CIR BASE ADDR: 0x%x\n", +@@ -143,7 +143,7 @@ static int fintek_hw_detect(struct finte + u8 chip_major, chip_minor; + u8 vendor_major, vendor_minor; + u8 portsel, ir_class; +- u16 vendor; ++ u16 vendor, chip; + int ret = 0; + + fintek_config_mode_enable(fintek); +@@ -176,6 +176,7 @@ static int fintek_hw_detect(struct finte + + chip_major = fintek_cr_read(fintek, GCR_CHIP_ID_HI); + chip_minor = fintek_cr_read(fintek, GCR_CHIP_ID_LO); ++ chip = chip_major << 8 | chip_minor; + + vendor_major = fintek_cr_read(fintek, GCR_VENDOR_ID_HI); + vendor_minor = fintek_cr_read(fintek, GCR_VENDOR_ID_LO); +@@ -192,6 +193,15 @@ static int fintek_hw_detect(struct finte + fintek->chip_major = chip_major; + fintek->chip_minor = chip_minor; + fintek->chip_vendor = vendor; ++ ++ /* ++ * Newer reviews of this chipset uses port 8 instead of 5 ++ */ ++ if ((chip != 0x0408) || (chip != 0x0804)) ++ fintek->logical_dev_cir = LOGICAL_DEV_CIR_REV2; ++ else ++ fintek->logical_dev_cir = LOGICAL_DEV_CIR_REV1; ++ + spin_unlock_irqrestore(&fintek->fintek_lock, flags); + + return ret; +@@ -200,7 +210,7 @@ static int fintek_hw_detect(struct finte + static void fintek_cir_ldev_init(struct fintek_dev *fintek) + { + /* Select CIR logical device and enable */ +- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); ++ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); + fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); + + /* Write allocated CIR address and IRQ information to hardware */ +@@ -381,7 +391,7 @@ static irqreturn_t fintek_cir_isr(int ir + fit_dbg_verbose("%s firing", __func__); + + fintek_config_mode_enable(fintek); +- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); ++ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); + fintek_config_mode_disable(fintek); + + /* +@@ -422,7 +432,7 @@ static void fintek_enable_cir(struct fin + fintek_config_mode_enable(fintek); + + /* enable the CIR logical device */ +- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); ++ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); + fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); + + fintek_config_mode_disable(fintek); +@@ -439,7 +449,7 @@ static void fintek_disable_cir(struct fi + fintek_config_mode_enable(fintek); + + /* disable the CIR logical device */ +- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); ++ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); + fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN); + + fintek_config_mode_disable(fintek); +@@ -611,7 +621,7 @@ static int fintek_suspend(struct pnp_dev + fintek_config_mode_enable(fintek); + + /* disable cir logical dev */ +- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); ++ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); + fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN); + + fintek_config_mode_disable(fintek); +@@ -634,7 +644,7 @@ static int fintek_resume(struct pnp_dev + + /* Enable CIR logical device */ + fintek_config_mode_enable(fintek); +- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); ++ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); + fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); + + fintek_config_mode_disable(fintek); +Index: linux-3.3.x86_64/drivers/media/rc/fintek-cir.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/fintek-cir.h ++++ linux-3.3.x86_64/drivers/media/rc/fintek-cir.h +@@ -88,6 +88,7 @@ struct fintek_dev { + u8 chip_major; + u8 chip_minor; + u16 chip_vendor; ++ u8 logical_dev_cir; + + /* hardware features */ + bool hw_learning_capable; +@@ -172,7 +173,8 @@ struct fintek_dev { + #define LOGICAL_DEV_ENABLE 0x01 + + /* Logical device number of the CIR function */ +-#define LOGICAL_DEV_CIR 0x05 ++#define LOGICAL_DEV_CIR_REV1 0x05 ++#define LOGICAL_DEV_CIR_REV2 0x08 + + /* CIR Logical Device (LDN 0x08) config registers */ + #define CIR_CR_COMMAND_INDEX 0x04 +Index: linux-3.3.x86_64/drivers/media/radio/radio-isa.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/radio/radio-isa.c +@@ -0,0 +1,340 @@ ++/* ++ * Framework for ISA radio drivers. ++ * This takes care of all the V4L2 scaffolding, allowing the ISA drivers ++ * to concentrate on the actual hardware operation. ++ * ++ * Copyright (C) 2012 Hans Verkuil ++ * ++ * 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 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., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "radio-isa.h" ++ ++MODULE_AUTHOR("Hans Verkuil"); ++MODULE_DESCRIPTION("A framework for ISA radio drivers."); ++MODULE_LICENSE("GPL"); ++ ++#define FREQ_LOW (87U * 16000U) ++#define FREQ_HIGH (108U * 16000U) ++ ++static int radio_isa_querycap(struct file *file, void *priv, ++ struct v4l2_capability *v) ++{ ++ struct radio_isa_card *isa = video_drvdata(file); ++ ++ strlcpy(v->driver, isa->drv->driver.driver.name, sizeof(v->driver)); ++ strlcpy(v->card, isa->drv->card, sizeof(v->card)); ++ snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name); ++ ++ v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; ++ v->device_caps = v->capabilities | V4L2_CAP_DEVICE_CAPS; ++ return 0; ++} ++ ++static int radio_isa_g_tuner(struct file *file, void *priv, ++ struct v4l2_tuner *v) ++{ ++ struct radio_isa_card *isa = video_drvdata(file); ++ const struct radio_isa_ops *ops = isa->drv->ops; ++ ++ if (v->index > 0) ++ return -EINVAL; ++ ++ strlcpy(v->name, "FM", sizeof(v->name)); ++ v->type = V4L2_TUNER_RADIO; ++ v->rangelow = FREQ_LOW; ++ v->rangehigh = FREQ_HIGH; ++ v->capability = V4L2_TUNER_CAP_LOW; ++ if (isa->drv->has_stereo) ++ v->capability |= V4L2_TUNER_CAP_STEREO; ++ ++ if (ops->g_rxsubchans) ++ v->rxsubchans = ops->g_rxsubchans(isa); ++ else ++ v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; ++ v->audmode = isa->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO; ++ if (ops->g_signal) ++ v->signal = ops->g_signal(isa); ++ else ++ v->signal = (v->rxsubchans & V4L2_TUNER_SUB_STEREO) ? ++ 0xffff : 0; ++ return 0; ++} ++ ++static int radio_isa_s_tuner(struct file *file, void *priv, ++ struct v4l2_tuner *v) ++{ ++ struct radio_isa_card *isa = video_drvdata(file); ++ const struct radio_isa_ops *ops = isa->drv->ops; ++ ++ if (v->index) ++ return -EINVAL; ++ if (ops->s_stereo) { ++ isa->stereo = (v->audmode == V4L2_TUNER_MODE_STEREO); ++ return ops->s_stereo(isa, isa->stereo); ++ } ++ return 0; ++} ++ ++static int radio_isa_s_frequency(struct file *file, void *priv, ++ struct v4l2_frequency *f) ++{ ++ struct radio_isa_card *isa = video_drvdata(file); ++ int res; ++ ++ if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) ++ return -EINVAL; ++ f->frequency = clamp(f->frequency, FREQ_LOW, FREQ_HIGH); ++ res = isa->drv->ops->s_frequency(isa, f->frequency); ++ if (res == 0) ++ isa->freq = f->frequency; ++ return res; ++} ++ ++static int radio_isa_g_frequency(struct file *file, void *priv, ++ struct v4l2_frequency *f) ++{ ++ struct radio_isa_card *isa = video_drvdata(file); ++ ++ if (f->tuner != 0) ++ return -EINVAL; ++ f->type = V4L2_TUNER_RADIO; ++ f->frequency = isa->freq; ++ return 0; ++} ++ ++static int radio_isa_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct radio_isa_card *isa = ++ container_of(ctrl->handler, struct radio_isa_card, hdl); ++ ++ switch (ctrl->id) { ++ case V4L2_CID_AUDIO_MUTE: ++ return isa->drv->ops->s_mute_volume(isa, ctrl->val, ++ isa->volume ? isa->volume->val : 0); ++ } ++ return -EINVAL; ++} ++ ++static int radio_isa_log_status(struct file *file, void *priv) ++{ ++ struct radio_isa_card *isa = video_drvdata(file); ++ ++ v4l2_info(&isa->v4l2_dev, "I/O Port = 0x%03x\n", isa->io); ++ v4l2_ctrl_handler_log_status(&isa->hdl, isa->v4l2_dev.name); ++ return 0; ++} ++ ++static int radio_isa_subscribe_event(struct v4l2_fh *fh, ++ struct v4l2_event_subscription *sub) ++{ ++ if (sub->type == V4L2_EVENT_CTRL) ++ return v4l2_event_subscribe(fh, sub, 0); ++ return -EINVAL; ++} ++ ++static const struct v4l2_ctrl_ops radio_isa_ctrl_ops = { ++ .s_ctrl = radio_isa_s_ctrl, ++}; ++ ++static const struct v4l2_file_operations radio_isa_fops = { ++ .owner = THIS_MODULE, ++ .open = v4l2_fh_open, ++ .release = v4l2_fh_release, ++ .poll = v4l2_ctrl_poll, ++ .unlocked_ioctl = video_ioctl2, ++}; ++ ++static const struct v4l2_ioctl_ops radio_isa_ioctl_ops = { ++ .vidioc_querycap = radio_isa_querycap, ++ .vidioc_g_tuner = radio_isa_g_tuner, ++ .vidioc_s_tuner = radio_isa_s_tuner, ++ .vidioc_g_frequency = radio_isa_g_frequency, ++ .vidioc_s_frequency = radio_isa_s_frequency, ++ .vidioc_log_status = radio_isa_log_status, ++ .vidioc_subscribe_event = radio_isa_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, ++}; ++ ++int radio_isa_match(struct device *pdev, unsigned int dev) ++{ ++ struct radio_isa_driver *drv = pdev->platform_data; ++ ++ return drv->probe || drv->io_params[dev] >= 0; ++} ++EXPORT_SYMBOL_GPL(radio_isa_match); ++ ++static bool radio_isa_valid_io(const struct radio_isa_driver *drv, int io) ++{ ++ int i; ++ ++ for (i = 0; i < drv->num_of_io_ports; i++) ++ if (drv->io_ports[i] == io) ++ return true; ++ return false; ++} ++ ++int radio_isa_probe(struct device *pdev, unsigned int dev) ++{ ++ struct radio_isa_driver *drv = pdev->platform_data; ++ const struct radio_isa_ops *ops = drv->ops; ++ struct v4l2_device *v4l2_dev; ++ struct radio_isa_card *isa; ++ int res; ++ ++ isa = drv->ops->alloc(); ++ if (isa == NULL) ++ return -ENOMEM; ++ dev_set_drvdata(pdev, isa); ++ isa->drv = drv; ++ isa->io = drv->io_params[dev]; ++ v4l2_dev = &isa->v4l2_dev; ++ strlcpy(v4l2_dev->name, dev_name(pdev), sizeof(v4l2_dev->name)); ++ ++ if (drv->probe && ops->probe) { ++ int i; ++ ++ for (i = 0; i < drv->num_of_io_ports; ++i) { ++ int io = drv->io_ports[i]; ++ ++ if (request_region(io, drv->region_size, v4l2_dev->name)) { ++ bool found = ops->probe(isa, io); ++ ++ release_region(io, drv->region_size); ++ if (found) { ++ isa->io = io; ++ break; ++ } ++ } ++ } ++ } ++ ++ if (!radio_isa_valid_io(drv, isa->io)) { ++ int i; ++ ++ if (isa->io < 0) ++ return -ENODEV; ++ v4l2_err(v4l2_dev, "you must set an I/O address with io=0x%03x", ++ drv->io_ports[0]); ++ for (i = 1; i < drv->num_of_io_ports; i++) ++ printk(KERN_CONT "/0x%03x", drv->io_ports[i]); ++ printk(KERN_CONT ".\n"); ++ kfree(isa); ++ return -EINVAL; ++ } ++ ++ if (!request_region(isa->io, drv->region_size, v4l2_dev->name)) { ++ v4l2_err(v4l2_dev, "port 0x%x already in use\n", isa->io); ++ kfree(isa); ++ return -EBUSY; ++ } ++ ++ res = v4l2_device_register(pdev, v4l2_dev); ++ if (res < 0) { ++ v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); ++ goto err_dev_reg; ++ } ++ ++ v4l2_ctrl_handler_init(&isa->hdl, 1); ++ isa->mute = v4l2_ctrl_new_std(&isa->hdl, &radio_isa_ctrl_ops, ++ V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); ++ if (drv->max_volume) ++ isa->volume = v4l2_ctrl_new_std(&isa->hdl, &radio_isa_ctrl_ops, ++ V4L2_CID_AUDIO_VOLUME, 0, drv->max_volume, 1, ++ drv->max_volume); ++ v4l2_dev->ctrl_handler = &isa->hdl; ++ if (isa->hdl.error) { ++ res = isa->hdl.error; ++ v4l2_err(v4l2_dev, "Could not register controls\n"); ++ goto err_hdl; ++ } ++ if (drv->max_volume) ++ v4l2_ctrl_cluster(2, &isa->mute); ++ v4l2_dev->ctrl_handler = &isa->hdl; ++ ++ mutex_init(&isa->lock); ++ isa->vdev.lock = &isa->lock; ++ strlcpy(isa->vdev.name, v4l2_dev->name, sizeof(isa->vdev.name)); ++ isa->vdev.v4l2_dev = v4l2_dev; ++ isa->vdev.fops = &radio_isa_fops; ++ isa->vdev.ioctl_ops = &radio_isa_ioctl_ops; ++ isa->vdev.release = video_device_release_empty; ++ set_bit(V4L2_FL_USE_FH_PRIO, &isa->vdev.flags); ++ video_set_drvdata(&isa->vdev, isa); ++ isa->freq = FREQ_LOW; ++ isa->stereo = drv->has_stereo; ++ ++ if (ops->init) ++ res = ops->init(isa); ++ if (!res) ++ res = v4l2_ctrl_handler_setup(&isa->hdl); ++ if (!res) ++ res = ops->s_frequency(isa, isa->freq); ++ if (!res && ops->s_stereo) ++ res = ops->s_stereo(isa, isa->stereo); ++ if (res < 0) { ++ v4l2_err(v4l2_dev, "Could not setup card\n"); ++ goto err_node_reg; ++ } ++ res = video_register_device(&isa->vdev, VFL_TYPE_RADIO, ++ drv->radio_nr_params[dev]); ++ if (res < 0) { ++ v4l2_err(v4l2_dev, "Could not register device node\n"); ++ goto err_node_reg; ++ } ++ ++ v4l2_info(v4l2_dev, "Initialized radio card %s on port 0x%03x\n", ++ drv->card, isa->io); ++ return 0; ++ ++err_node_reg: ++ v4l2_ctrl_handler_free(&isa->hdl); ++err_hdl: ++ v4l2_device_unregister(&isa->v4l2_dev); ++err_dev_reg: ++ release_region(isa->io, drv->region_size); ++ kfree(isa); ++ return res; ++} ++EXPORT_SYMBOL_GPL(radio_isa_probe); ++ ++int radio_isa_remove(struct device *pdev, unsigned int dev) ++{ ++ struct radio_isa_card *isa = dev_get_drvdata(pdev); ++ const struct radio_isa_ops *ops = isa->drv->ops; ++ ++ ops->s_mute_volume(isa, true, isa->volume ? isa->volume->cur.val : 0); ++ video_unregister_device(&isa->vdev); ++ v4l2_ctrl_handler_free(&isa->hdl); ++ v4l2_device_unregister(&isa->v4l2_dev); ++ release_region(isa->io, isa->drv->region_size); ++ v4l2_info(&isa->v4l2_dev, "Removed radio card %s\n", isa->drv->card); ++ kfree(isa); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(radio_isa_remove); +Index: linux-3.3.x86_64/drivers/media/radio/radio-isa.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/radio/radio-isa.h +@@ -0,0 +1,105 @@ ++/* ++ * Framework for ISA radio drivers. ++ * This takes care of all the V4L2 scaffolding, allowing the ISA drivers ++ * to concentrate on the actual hardware operation. ++ * ++ * Copyright (C) 2012 Hans Verkuil ++ * ++ * 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 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., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#ifndef _RADIO_ISA_H_ ++#define _RADIO_ISA_H_ ++ ++#include ++#include ++#include ++#include ++ ++struct radio_isa_driver; ++struct radio_isa_ops; ++ ++/* Core structure for radio ISA cards */ ++struct radio_isa_card { ++ const struct radio_isa_driver *drv; ++ struct v4l2_device v4l2_dev; ++ struct v4l2_ctrl_handler hdl; ++ struct video_device vdev; ++ struct mutex lock; ++ const struct radio_isa_ops *ops; ++ struct { /* mute/volume cluster */ ++ struct v4l2_ctrl *mute; ++ struct v4l2_ctrl *volume; ++ }; ++ /* I/O port */ ++ int io; ++ ++ /* Card is in stereo audio mode */ ++ bool stereo; ++ /* Current frequency */ ++ u32 freq; ++}; ++ ++struct radio_isa_ops { ++ /* Allocate and initialize a radio_isa_card struct */ ++ struct radio_isa_card *(*alloc)(void); ++ /* Probe whether a card is present at the given port */ ++ bool (*probe)(struct radio_isa_card *isa, int io); ++ /* Special card initialization can be done here, this is called after ++ * the standard controls are registered, but before they are setup, ++ * thus allowing drivers to add their own controls here. */ ++ int (*init)(struct radio_isa_card *isa); ++ /* Set mute and volume. */ ++ int (*s_mute_volume)(struct radio_isa_card *isa, bool mute, int volume); ++ /* Set frequency */ ++ int (*s_frequency)(struct radio_isa_card *isa, u32 freq); ++ /* Set stereo/mono audio mode */ ++ int (*s_stereo)(struct radio_isa_card *isa, bool stereo); ++ /* Get rxsubchans value for VIDIOC_G_TUNER */ ++ u32 (*g_rxsubchans)(struct radio_isa_card *isa); ++ /* Get the signal strength for VIDIOC_G_TUNER */ ++ u32 (*g_signal)(struct radio_isa_card *isa); ++}; ++ ++/* Top level structure needed to instantiate the cards */ ++struct radio_isa_driver { ++ struct isa_driver driver; ++ const struct radio_isa_ops *ops; ++ /* The module_param_array with the specified I/O ports */ ++ int *io_params; ++ /* The module_param_array with the radio_nr values */ ++ int *radio_nr_params; ++ /* Whether we should probe for possible cards */ ++ bool probe; ++ /* The list of possible I/O ports */ ++ const int *io_ports; ++ /* The size of that list */ ++ int num_of_io_ports; ++ /* The region size to request */ ++ unsigned region_size; ++ /* The name of the card */ ++ const char *card; ++ /* Card can capture stereo audio */ ++ bool has_stereo; ++ /* The maximum volume for the volume control. If 0, then there ++ is no volume control possible. */ ++ int max_volume; ++}; ++ ++int radio_isa_match(struct device *pdev, unsigned int dev); ++int radio_isa_probe(struct device *pdev, unsigned int dev); ++int radio_isa_remove(struct device *pdev, unsigned int dev); ++ ++#endif +Index: linux-3.3.x86_64/drivers/media/radio/radio-aimslab.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-aimslab.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-aimslab.c +@@ -1,16 +1,13 @@ +-/* radiotrack (radioreveal) driver for Linux radio support +- * (c) 1997 M. Kirkwood ++/* ++ * AimsLab RadioTrack (aka RadioVeveal) driver ++ * ++ * Copyright 1997 M. Kirkwood ++ * ++ * Converted to the radio-isa framework by Hans Verkuil + * Converted to V4L2 API by Mauro Carvalho Chehab + * Converted to new API by Alan Cox + * Various bugfixes and enhancements by Russell Kroll + * +- * History: +- * 1999-02-24 Russell Kroll +- * Fine tuning/VIDEO_TUNER_LOW +- * Frequency range expanded to start at 87 MHz +- * +- * TODO: Allow for more than one of these foolish entities :-) +- * + * Notes on the hardware (reverse engineered from other peoples' + * reverse engineering of AIMS' code :-) + * +@@ -26,6 +23,7 @@ + * wait(a_wee_while); + * out(port, stop_changing_the_volume); + * ++ * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool. + */ + + #include /* Modules */ +@@ -34,401 +32,179 @@ + #include /* msleep */ + #include /* kernel radio structs */ + #include /* outb, outb_p */ ++#include + #include + #include ++#include ++#include "radio-isa.h" + +-MODULE_AUTHOR("M.Kirkwood"); ++MODULE_AUTHOR("M. Kirkwood"); + MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION("0.0.3"); ++MODULE_VERSION("1.0.0"); + + #ifndef CONFIG_RADIO_RTRACK_PORT + #define CONFIG_RADIO_RTRACK_PORT -1 + #endif + +-static int io = CONFIG_RADIO_RTRACK_PORT; +-static int radio_nr = -1; ++#define RTRACK_MAX 2 + +-module_param(io, int, 0); +-MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)"); +-module_param(radio_nr, int, 0); ++static int io[RTRACK_MAX] = { [0] = CONFIG_RADIO_RTRACK_PORT, ++ [1 ... (RTRACK_MAX - 1)] = -1 }; ++static int radio_nr[RTRACK_MAX] = { [0 ... (RTRACK_MAX - 1)] = -1 }; ++ ++module_param_array(io, int, NULL, 0444); ++MODULE_PARM_DESC(io, "I/O addresses of the RadioTrack card (0x20f or 0x30f)"); ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); + +-struct rtrack +-{ +- struct v4l2_device v4l2_dev; +- struct video_device vdev; +- int port; ++struct rtrack { ++ struct radio_isa_card isa; + int curvol; +- unsigned long curfreq; +- int muted; +- int io; +- struct mutex lock; + }; + +-static struct rtrack rtrack_card; +- +-/* local things */ +- +-static void rt_decvol(struct rtrack *rt) +-{ +- outb(0x58, rt->io); /* volume down + sigstr + on */ +- msleep(100); +- outb(0xd8, rt->io); /* volume steady + sigstr + on */ +-} +- +-static void rt_incvol(struct rtrack *rt) +-{ +- outb(0x98, rt->io); /* volume up + sigstr + on */ +- msleep(100); +- outb(0xd8, rt->io); /* volume steady + sigstr + on */ +-} +- +-static void rt_mute(struct rtrack *rt) +-{ +- rt->muted = 1; +- mutex_lock(&rt->lock); +- outb(0xd0, rt->io); /* volume steady, off */ +- mutex_unlock(&rt->lock); +-} +- +-static int rt_setvol(struct rtrack *rt, int vol) ++static struct radio_isa_card *rtrack_alloc(void) + { +- int i; +- +- mutex_lock(&rt->lock); +- +- if (vol == rt->curvol) { /* requested volume = current */ +- if (rt->muted) { /* user is unmuting the card */ +- rt->muted = 0; +- outb(0xd8, rt->io); /* enable card */ +- } +- mutex_unlock(&rt->lock); +- return 0; +- } +- +- if (vol == 0) { /* volume = 0 means mute the card */ +- outb(0x48, rt->io); /* volume down but still "on" */ +- msleep(2000); /* make sure it's totally down */ +- outb(0xd0, rt->io); /* volume steady, off */ +- rt->curvol = 0; /* track the volume state! */ +- mutex_unlock(&rt->lock); +- return 0; +- } +- +- rt->muted = 0; +- if (vol > rt->curvol) +- for (i = rt->curvol; i < vol; i++) +- rt_incvol(rt); +- else +- for (i = rt->curvol; i > vol; i--) +- rt_decvol(rt); ++ struct rtrack *rt = kzalloc(sizeof(struct rtrack), GFP_KERNEL); + +- rt->curvol = vol; +- mutex_unlock(&rt->lock); +- return 0; ++ if (rt) ++ rt->curvol = 0xff; ++ return rt ? &rt->isa : NULL; + } + +-/* the 128+64 on these outb's is to keep the volume stable while tuning +- * without them, the volume _will_ creep up with each frequency change +- * and bit 4 (+16) is to keep the signal strength meter enabled ++/* The 128+64 on these outb's is to keep the volume stable while tuning. ++ * Without them, the volume _will_ creep up with each frequency change ++ * and bit 4 (+16) is to keep the signal strength meter enabled. + */ + +-static void send_0_byte(struct rtrack *rt) ++static void send_0_byte(struct radio_isa_card *isa, int on) + { +- if (rt->curvol == 0 || rt->muted) { +- outb_p(128+64+16+ 1, rt->io); /* wr-enable + data low */ +- outb_p(128+64+16+2+1, rt->io); /* clock */ +- } +- else { +- outb_p(128+64+16+8+ 1, rt->io); /* on + wr-enable + data low */ +- outb_p(128+64+16+8+2+1, rt->io); /* clock */ +- } ++ outb_p(128+64+16+on+1, isa->io); /* wr-enable + data low */ ++ outb_p(128+64+16+on+2+1, isa->io); /* clock */ + msleep(1); + } + +-static void send_1_byte(struct rtrack *rt) ++static void send_1_byte(struct radio_isa_card *isa, int on) + { +- if (rt->curvol == 0 || rt->muted) { +- outb_p(128+64+16+4 +1, rt->io); /* wr-enable+data high */ +- outb_p(128+64+16+4+2+1, rt->io); /* clock */ +- } +- else { +- outb_p(128+64+16+8+4 +1, rt->io); /* on+wr-enable+data high */ +- outb_p(128+64+16+8+4+2+1, rt->io); /* clock */ +- } +- ++ outb_p(128+64+16+on+4+1, isa->io); /* wr-enable+data high */ ++ outb_p(128+64+16+on+4+2+1, isa->io); /* clock */ + msleep(1); + } + +-static int rt_setfreq(struct rtrack *rt, unsigned long freq) ++static int rtrack_s_frequency(struct radio_isa_card *isa, u32 freq) + { ++ int on = v4l2_ctrl_g_ctrl(isa->mute) ? 0 : 8; + int i; + +- mutex_lock(&rt->lock); /* Stop other ops interfering */ +- +- rt->curfreq = freq; +- +- /* now uses VIDEO_TUNER_LOW for fine tuning */ +- + freq += 171200; /* Add 10.7 MHz IF */ + freq /= 800; /* Convert to 50 kHz units */ + +- send_0_byte(rt); /* 0: LSB of frequency */ ++ send_0_byte(isa, on); /* 0: LSB of frequency */ + + for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ + if (freq & (1 << i)) +- send_1_byte(rt); ++ send_1_byte(isa, on); + else +- send_0_byte(rt); ++ send_0_byte(isa, on); + +- send_0_byte(rt); /* 14: test bit - always 0 */ +- send_0_byte(rt); /* 15: test bit - always 0 */ ++ send_0_byte(isa, on); /* 14: test bit - always 0 */ ++ send_0_byte(isa, on); /* 15: test bit - always 0 */ + +- send_0_byte(rt); /* 16: band data 0 - always 0 */ +- send_0_byte(rt); /* 17: band data 1 - always 0 */ +- send_0_byte(rt); /* 18: band data 2 - always 0 */ +- send_0_byte(rt); /* 19: time base - always 0 */ +- +- send_0_byte(rt); /* 20: spacing (0 = 25 kHz) */ +- send_1_byte(rt); /* 21: spacing (1 = 25 kHz) */ +- send_0_byte(rt); /* 22: spacing (0 = 25 kHz) */ +- send_1_byte(rt); /* 23: AM/FM (FM = 1, always) */ +- +- if (rt->curvol == 0 || rt->muted) +- outb(0xd0, rt->io); /* volume steady + sigstr */ +- else +- outb(0xd8, rt->io); /* volume steady + sigstr + on */ ++ send_0_byte(isa, on); /* 16: band data 0 - always 0 */ ++ send_0_byte(isa, on); /* 17: band data 1 - always 0 */ ++ send_0_byte(isa, on); /* 18: band data 2 - always 0 */ ++ send_0_byte(isa, on); /* 19: time base - always 0 */ + +- mutex_unlock(&rt->lock); ++ send_0_byte(isa, on); /* 20: spacing (0 = 25 kHz) */ ++ send_1_byte(isa, on); /* 21: spacing (1 = 25 kHz) */ ++ send_0_byte(isa, on); /* 22: spacing (0 = 25 kHz) */ ++ send_1_byte(isa, on); /* 23: AM/FM (FM = 1, always) */ + ++ outb(0xd0 + on, isa->io); /* volume steady + sigstr */ + return 0; + } + +-static int rt_getsigstr(struct rtrack *rt) ++static u32 rtrack_g_signal(struct radio_isa_card *isa) + { +- int sig = 1; +- +- mutex_lock(&rt->lock); +- if (inb(rt->io) & 2) /* bit set = no signal present */ +- sig = 0; +- mutex_unlock(&rt->lock); +- return sig; +-} +- +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- strlcpy(v->driver, "radio-aimslab", sizeof(v->driver)); +- strlcpy(v->card, "RadioTrack", sizeof(v->card)); +- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; +- return 0; +-} +- +-static int vidioc_g_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- struct rtrack *rt = video_drvdata(file); +- +- if (v->index > 0) +- return -EINVAL; +- +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- v->rangelow = 87 * 16000; +- v->rangehigh = 108 * 16000; +- v->rxsubchans = V4L2_TUNER_SUB_MONO; +- v->capability = V4L2_TUNER_CAP_LOW; +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->signal = 0xffff * rt_getsigstr(rt); +- return 0; ++ /* bit set = no signal present */ ++ return 0xffff * !(inb(isa->io) & 2); + } + +-static int vidioc_s_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) ++static int rtrack_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) + { +- return v->index ? -EINVAL : 0; +-} ++ struct rtrack *rt = container_of(isa, struct rtrack, isa); ++ int curvol = rt->curvol; + +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct rtrack *rt = video_drvdata(file); +- +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- rt_setfreq(rt, f->frequency); +- return 0; +-} +- +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct rtrack *rt = video_drvdata(file); +- +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = rt->curfreq; +- return 0; +-} +- +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- switch (qc->id) { +- case V4L2_CID_AUDIO_MUTE: +- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); +- case V4L2_CID_AUDIO_VOLUME: +- return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff); +- } +- return -EINVAL; +-} +- +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct rtrack *rt = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- ctrl->value = rt->muted; +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- ctrl->value = rt->curvol; ++ if (mute) { ++ outb(0xd0, isa->io); /* volume steady + sigstr + off */ + return 0; + } +- return -EINVAL; +-} +- +-static int vidioc_s_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct rtrack *rt = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (ctrl->value) +- rt_mute(rt); +- else +- rt_setvol(rt, rt->curvol); +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- rt_setvol(rt, ctrl->value); +- return 0; ++ if (vol == 0) { /* volume = 0 means mute the card */ ++ outb(0x48, isa->io); /* volume down but still "on" */ ++ msleep(curvol * 3); /* make sure it's totally down */ ++ } else if (curvol < vol) { ++ outb(0x98, isa->io); /* volume up + sigstr + on */ ++ for (; curvol < vol; curvol++) ++ udelay(3000); ++ } else if (curvol > vol) { ++ outb(0x58, isa->io); /* volume down + sigstr + on */ ++ for (; curvol > vol; curvol--) ++ udelay(3000); + } +- return -EINVAL; +-} +- +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; ++ outb(0xd8, isa->io); /* volume steady + sigstr + on */ ++ rt->curvol = vol; + return 0; + } + +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +-{ +- return i ? -EINVAL : 0; +-} +- +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) ++/* Mute card - prevents noisy bootups */ ++static int rtrack_initialize(struct radio_isa_card *isa) + { +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; ++ /* this ensures that the volume is all the way up */ ++ outb(0x90, isa->io); /* volume up but still "on" */ ++ msleep(3000); /* make sure it's totally up */ ++ outb(0xc0, isa->io); /* steady volume, mute card */ + return 0; + } + +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- return a->index ? -EINVAL : 0; +-} +- +-static const struct v4l2_file_operations rtrack_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, ++static const struct radio_isa_ops rtrack_ops = { ++ .alloc = rtrack_alloc, ++ .init = rtrack_initialize, ++ .s_mute_volume = rtrack_s_mute_volume, ++ .s_frequency = rtrack_s_frequency, ++ .g_signal = rtrack_g_signal, + }; + +-static const struct v4l2_ioctl_ops rtrack_ioctl_ops = { +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl, ++static const int rtrack_ioports[] = { 0x20f, 0x30f }; ++ ++static struct radio_isa_driver rtrack_driver = { ++ .driver = { ++ .match = radio_isa_match, ++ .probe = radio_isa_probe, ++ .remove = radio_isa_remove, ++ .driver = { ++ .name = "radio-aimslab", ++ }, ++ }, ++ .io_params = io, ++ .radio_nr_params = radio_nr, ++ .io_ports = rtrack_ioports, ++ .num_of_io_ports = ARRAY_SIZE(rtrack_ioports), ++ .region_size = 2, ++ .card = "AIMSlab RadioTrack/RadioReveal", ++ .ops = &rtrack_ops, ++ .has_stereo = true, ++ .max_volume = 0xff, + }; + + static int __init rtrack_init(void) + { +- struct rtrack *rt = &rtrack_card; +- struct v4l2_device *v4l2_dev = &rt->v4l2_dev; +- int res; +- +- strlcpy(v4l2_dev->name, "rtrack", sizeof(v4l2_dev->name)); +- rt->io = io; +- +- if (rt->io == -1) { +- v4l2_err(v4l2_dev, "you must set an I/O address with io=0x20f or 0x30f\n"); +- return -EINVAL; +- } +- +- if (!request_region(rt->io, 2, "rtrack")) { +- v4l2_err(v4l2_dev, "port 0x%x already in use\n", rt->io); +- return -EBUSY; +- } +- +- res = v4l2_device_register(NULL, v4l2_dev); +- if (res < 0) { +- release_region(rt->io, 2); +- v4l2_err(v4l2_dev, "could not register v4l2_device\n"); +- return res; +- } +- +- strlcpy(rt->vdev.name, v4l2_dev->name, sizeof(rt->vdev.name)); +- rt->vdev.v4l2_dev = v4l2_dev; +- rt->vdev.fops = &rtrack_fops; +- rt->vdev.ioctl_ops = &rtrack_ioctl_ops; +- rt->vdev.release = video_device_release_empty; +- video_set_drvdata(&rt->vdev, rt); +- +- /* Set up the I/O locking */ +- +- mutex_init(&rt->lock); +- +- /* mute card - prevents noisy bootups */ +- +- /* this ensures that the volume is all the way down */ +- outb(0x48, rt->io); /* volume down but still "on" */ +- msleep(2000); /* make sure it's totally down */ +- outb(0xc0, rt->io); /* steady volume, mute card */ +- +- if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_device_unregister(&rt->v4l2_dev); +- release_region(rt->io, 2); +- return -EINVAL; +- } +- v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n"); +- +- return 0; ++ return isa_register_driver(&rtrack_driver.driver, RTRACK_MAX); + } + + static void __exit rtrack_exit(void) + { +- struct rtrack *rt = &rtrack_card; +- +- video_unregister_device(&rt->vdev); +- v4l2_device_unregister(&rt->v4l2_dev); +- release_region(rt->io, 2); ++ isa_unregister_driver(&rtrack_driver.driver); + } + + module_init(rtrack_init); + module_exit(rtrack_exit); +- +Index: linux-3.3.x86_64/drivers/media/radio/radio-aztech.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-aztech.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-aztech.c +@@ -1,5 +1,7 @@ +-/* radio-aztech.c - Aztech radio card driver for Linux 2.2 ++/* ++ * radio-aztech.c - Aztech radio card driver + * ++ * Converted to the radio-isa framework by Hans Verkuil + * Converted to V4L2 API by Mauro Carvalho Chehab + * Adapted to support the Video for Linux API by + * Russell Kroll . Based on original tuner code by: +@@ -10,19 +12,7 @@ + * Scott McGrath (smcgrath@twilight.vtc.vsc.edu) + * William McGrath (wmcgrath@twilight.vtc.vsc.edu) + * +- * The basis for this code may be found at http://bigbang.vtc.vsc.edu/fmradio/ +- * along with more information on the card itself. +- * +- * History: +- * 1999-02-24 Russell Kroll +- * Fine tuning/VIDEO_TUNER_LOW +- * Range expanded to 87-108 MHz (from 87.9-107.8) +- * +- * Notable changes from the original source: +- * - includes stripped down to the essentials +- * - for loops used as delays replaced with udelay() +- * - #defines removed, changed to static values +- * - tuning structure changed - no more character arrays, other changes ++ * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool. + */ + + #include /* Modules */ +@@ -31,126 +21,72 @@ + #include /* udelay */ + #include /* kernel radio structs */ + #include /* outb, outb_p */ ++#include + #include + #include ++#include ++#include "radio-isa.h" + + MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); + MODULE_DESCRIPTION("A driver for the Aztech radio card."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION("0.0.3"); ++MODULE_VERSION("1.0.0"); + + /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ +- + #ifndef CONFIG_RADIO_AZTECH_PORT + #define CONFIG_RADIO_AZTECH_PORT -1 + #endif + +-static int io = CONFIG_RADIO_AZTECH_PORT; +-static int radio_nr = -1; +-static int radio_wait_time = 1000; +- +-module_param(io, int, 0); +-module_param(radio_nr, int, 0); +-MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)"); ++#define AZTECH_MAX 2 + +-struct aztech +-{ +- struct v4l2_device v4l2_dev; +- struct video_device vdev; +- int io; ++static int io[AZTECH_MAX] = { [0] = CONFIG_RADIO_AZTECH_PORT, ++ [1 ... (AZTECH_MAX - 1)] = -1 }; ++static int radio_nr[AZTECH_MAX] = { [0 ... (AZTECH_MAX - 1)] = -1 }; ++static const int radio_wait_time = 1000; ++ ++module_param_array(io, int, NULL, 0444); ++MODULE_PARM_DESC(io, "I/O addresses of the Aztech card (0x350 or 0x358)"); ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); ++ ++struct aztech { ++ struct radio_isa_card isa; + int curvol; +- unsigned long curfreq; +- int stereo; +- struct mutex lock; + }; + +-static struct aztech aztech_card; +- +-static int volconvert(int level) +-{ +- level >>= 14; /* Map 16bits down to 2 bit */ +- level &= 3; +- +- /* convert to card-friendly values */ +- switch (level) { +- case 0: +- return 0; +- case 1: +- return 1; +- case 2: +- return 4; +- case 3: +- return 5; +- } +- return 0; /* Quieten gcc */ +-} +- + static void send_0_byte(struct aztech *az) + { + udelay(radio_wait_time); +- outb_p(2 + volconvert(az->curvol), az->io); +- outb_p(64 + 2 + volconvert(az->curvol), az->io); ++ outb_p(2 + az->curvol, az->isa.io); ++ outb_p(64 + 2 + az->curvol, az->isa.io); + } + + static void send_1_byte(struct aztech *az) + { +- udelay (radio_wait_time); +- outb_p(128 + 2 + volconvert(az->curvol), az->io); +- outb_p(128 + 64 + 2 + volconvert(az->curvol), az->io); +-} +- +-static int az_setvol(struct aztech *az, int vol) +-{ +- mutex_lock(&az->lock); +- outb(volconvert(vol), az->io); +- mutex_unlock(&az->lock); +- return 0; +-} +- +-/* thanks to Michael Dwyer for giving me a dose of clues in +- * the signal strength department.. +- * +- * This card has a stereo bit - bit 0 set = mono, not set = stereo +- * It also has a "signal" bit - bit 1 set = bad signal, not set = good +- * +- */ +- +-static int az_getsigstr(struct aztech *az) +-{ +- int sig = 1; +- +- mutex_lock(&az->lock); +- if (inb(az->io) & 2) /* bit set = no signal present */ +- sig = 0; +- mutex_unlock(&az->lock); +- return sig; ++ udelay(radio_wait_time); ++ outb_p(128 + 2 + az->curvol, az->isa.io); ++ outb_p(128 + 64 + 2 + az->curvol, az->isa.io); + } + +-static int az_getstereo(struct aztech *az) ++static struct radio_isa_card *aztech_alloc(void) + { +- int stereo = 1; ++ struct aztech *az = kzalloc(sizeof(*az), GFP_KERNEL); + +- mutex_lock(&az->lock); +- if (inb(az->io) & 1) /* bit set = mono */ +- stereo = 0; +- mutex_unlock(&az->lock); +- return stereo; ++ return az ? &az->isa : NULL; + } + +-static int az_setfreq(struct aztech *az, unsigned long frequency) ++static int aztech_s_frequency(struct radio_isa_card *isa, u32 freq) + { ++ struct aztech *az = container_of(isa, struct aztech, isa); + int i; + +- mutex_lock(&az->lock); +- +- az->curfreq = frequency; +- frequency += 171200; /* Add 10.7 MHz IF */ +- frequency /= 800; /* Convert to 50 kHz units */ ++ freq += 171200; /* Add 10.7 MHz IF */ ++ freq /= 800; /* Convert to 50 kHz units */ + + send_0_byte(az); /* 0: LSB of frequency */ + + for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ +- if (frequency & (1 << i)) ++ if (freq & (1 << i)) + send_1_byte(az); + else + send_0_byte(az); +@@ -158,7 +94,7 @@ static int az_setfreq(struct aztech *az, + send_0_byte(az); /* 14: test bit - always 0 */ + send_0_byte(az); /* 15: test bit - always 0 */ + send_0_byte(az); /* 16: band data 0 - always 0 */ +- if (az->stereo) /* 17: stereo (1 to enable) */ ++ if (isa->stereo) /* 17: stereo (1 to enable) */ + send_1_byte(az); + else + send_0_byte(az); +@@ -173,225 +109,77 @@ static int az_setfreq(struct aztech *az, + /* latch frequency */ + + udelay(radio_wait_time); +- outb_p(128 + 64 + volconvert(az->curvol), az->io); +- +- mutex_unlock(&az->lock); +- +- return 0; +-} ++ outb_p(128 + 64 + az->curvol, az->isa.io); + +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- strlcpy(v->driver, "radio-aztech", sizeof(v->driver)); +- strlcpy(v->card, "Aztech Radio", sizeof(v->card)); +- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; + return 0; + } + +-static int vidioc_g_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- struct aztech *az = video_drvdata(file); +- +- if (v->index > 0) +- return -EINVAL; +- +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- +- v->rangelow = 87 * 16000; +- v->rangehigh = 108 * 16000; +- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; +- v->capability = V4L2_TUNER_CAP_LOW; +- if (az_getstereo(az)) +- v->audmode = V4L2_TUNER_MODE_STEREO; +- else +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->signal = 0xFFFF * az_getsigstr(az); +- +- return 0; +-} +- +-static int vidioc_s_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- return v->index ? -EINVAL : 0; +-} +- +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; +- return 0; +-} +- +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +-{ +- return i ? -EINVAL : 0; +-} +- +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) ++/* thanks to Michael Dwyer for giving me a dose of clues in ++ * the signal strength department.. ++ * ++ * This card has a stereo bit - bit 0 set = mono, not set = stereo ++ */ ++static u32 aztech_g_rxsubchans(struct radio_isa_card *isa) + { +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; ++ if (inb(isa->io) & 1) ++ return V4L2_TUNER_SUB_MONO; ++ return V4L2_TUNER_SUB_STEREO; + } + +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) ++static int aztech_s_stereo(struct radio_isa_card *isa, bool stereo) + { +- return a->index ? -EINVAL : 0; ++ return aztech_s_frequency(isa, isa->freq); + } + +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) ++static int aztech_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) + { +- struct aztech *az = video_drvdata(file); ++ struct aztech *az = container_of(isa, struct aztech, isa); + +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- az_setfreq(az, f->frequency); ++ if (mute) ++ vol = 0; ++ az->curvol = (vol & 1) + ((vol & 2) << 1); ++ outb(az->curvol, isa->io); + return 0; + } + +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct aztech *az = video_drvdata(file); +- +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = az->curfreq; +- return 0; +-} +- +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- switch (qc->id) { +- case V4L2_CID_AUDIO_MUTE: +- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); +- case V4L2_CID_AUDIO_VOLUME: +- return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff); +- } +- return -EINVAL; +-} +- +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct aztech *az = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (az->curvol == 0) +- ctrl->value = 1; +- else +- ctrl->value = 0; +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- ctrl->value = az->curvol * 6554; +- return 0; +- } +- return -EINVAL; +-} +- +-static int vidioc_s_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct aztech *az = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (ctrl->value) +- az_setvol(az, 0); +- else +- az_setvol(az, az->curvol); +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- az_setvol(az, ctrl->value); +- return 0; +- } +- return -EINVAL; +-} +- +-static const struct v4l2_file_operations aztech_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, ++static const struct radio_isa_ops aztech_ops = { ++ .alloc = aztech_alloc, ++ .s_mute_volume = aztech_s_mute_volume, ++ .s_frequency = aztech_s_frequency, ++ .s_stereo = aztech_s_stereo, ++ .g_rxsubchans = aztech_g_rxsubchans, + }; + +-static const struct v4l2_ioctl_ops aztech_ioctl_ops = { +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl, ++static const int aztech_ioports[] = { 0x350, 0x358 }; ++ ++static struct radio_isa_driver aztech_driver = { ++ .driver = { ++ .match = radio_isa_match, ++ .probe = radio_isa_probe, ++ .remove = radio_isa_remove, ++ .driver = { ++ .name = "radio-aztech", ++ }, ++ }, ++ .io_params = io, ++ .radio_nr_params = radio_nr, ++ .io_ports = aztech_ioports, ++ .num_of_io_ports = ARRAY_SIZE(aztech_ioports), ++ .region_size = 2, ++ .card = "Aztech Radio", ++ .ops = &aztech_ops, ++ .has_stereo = true, ++ .max_volume = 3, + }; + + static int __init aztech_init(void) + { +- struct aztech *az = &aztech_card; +- struct v4l2_device *v4l2_dev = &az->v4l2_dev; +- int res; +- +- strlcpy(v4l2_dev->name, "aztech", sizeof(v4l2_dev->name)); +- az->io = io; +- +- if (az->io == -1) { +- v4l2_err(v4l2_dev, "you must set an I/O address with io=0x350 or 0x358\n"); +- return -EINVAL; +- } +- +- if (!request_region(az->io, 2, "aztech")) { +- v4l2_err(v4l2_dev, "port 0x%x already in use\n", az->io); +- return -EBUSY; +- } +- +- res = v4l2_device_register(NULL, v4l2_dev); +- if (res < 0) { +- release_region(az->io, 2); +- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); +- return res; +- } +- +- mutex_init(&az->lock); +- strlcpy(az->vdev.name, v4l2_dev->name, sizeof(az->vdev.name)); +- az->vdev.v4l2_dev = v4l2_dev; +- az->vdev.fops = &aztech_fops; +- az->vdev.ioctl_ops = &aztech_ioctl_ops; +- az->vdev.release = video_device_release_empty; +- video_set_drvdata(&az->vdev, az); +- /* mute card - prevents noisy bootups */ +- outb(0, az->io); +- +- if (video_register_device(&az->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_device_unregister(v4l2_dev); +- release_region(az->io, 2); +- return -EINVAL; +- } +- +- v4l2_info(v4l2_dev, "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n"); +- return 0; ++ return isa_register_driver(&aztech_driver.driver, AZTECH_MAX); + } + + static void __exit aztech_exit(void) + { +- struct aztech *az = &aztech_card; +- +- video_unregister_device(&az->vdev); +- v4l2_device_unregister(&az->v4l2_dev); +- release_region(az->io, 2); ++ isa_unregister_driver(&aztech_driver.driver); + } + + module_init(aztech_init); +Index: linux-3.3.x86_64/drivers/media/radio/radio-gemtek.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-gemtek.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-gemtek.c +@@ -1,4 +1,7 @@ +-/* GemTek radio card driver for Linux (C) 1998 Jonas Munsin ++/* ++ * GemTek radio card driver ++ * ++ * Copyright 1998 Jonas Munsin + * + * GemTek hasn't released any specs on the card, so the protocol had to + * be reverse engineered with dosemu. +@@ -11,9 +14,12 @@ + * Converted to new API by Alan Cox + * Various bugfixes and enhancements by Russell Kroll + * +- * TODO: Allow for more than one of these foolish entities :-) +- * ++ * Converted to the radio-isa framework by Hans Verkuil + * Converted to V4L2 API by Mauro Carvalho Chehab ++ * ++ * Note: this card seems to swap the left and right audio channels! ++ * ++ * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool. + */ + + #include /* Modules */ +@@ -23,8 +29,10 @@ + #include /* kernel radio structs */ + #include + #include /* outb, outb_p */ ++#include + #include + #include ++#include "radio-isa.h" + + /* + * Module info. +@@ -33,7 +41,7 @@ + MODULE_AUTHOR("Jonas Munsin, Pekka Seppänen "); + MODULE_DESCRIPTION("A driver for the GemTek Radio card."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION("0.0.4"); ++MODULE_VERSION("1.0.0"); + + /* + * Module params. +@@ -46,45 +54,29 @@ MODULE_VERSION("0.0.4"); + #define CONFIG_RADIO_GEMTEK_PROBE 1 + #endif + +-static int io = CONFIG_RADIO_GEMTEK_PORT; +-static bool probe = CONFIG_RADIO_GEMTEK_PROBE; +-static bool hardmute; +-static bool shutdown = 1; +-static bool keepmuted = 1; +-static bool initmute = 1; +-static int radio_nr = -1; ++#define GEMTEK_MAX 4 + +-module_param(io, int, 0444); +-MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic " +- "probing is disabled or fails. The most common I/O ports are: 0x20c " +- "0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to " +- "work for the combined sound/radiocard)."); ++static bool probe = CONFIG_RADIO_GEMTEK_PROBE; ++static bool hardmute; ++static int io[GEMTEK_MAX] = { [0] = CONFIG_RADIO_GEMTEK_PORT, ++ [1 ... (GEMTEK_MAX - 1)] = -1 }; ++static int radio_nr[GEMTEK_MAX] = { [0 ... (GEMTEK_MAX - 1)] = -1 }; + + module_param(probe, bool, 0444); +-MODULE_PARM_DESC(probe, "Enable automatic device probing. Note: only the most " +- "common I/O ports used by the card are probed."); ++MODULE_PARM_DESC(probe, "Enable automatic device probing."); + + module_param(hardmute, bool, 0644); +-MODULE_PARM_DESC(hardmute, "Enable `hard muting' by shutting down PLL, may " ++MODULE_PARM_DESC(hardmute, "Enable 'hard muting' by shutting down PLL, may " + "reduce static noise."); + +-module_param(shutdown, bool, 0644); +-MODULE_PARM_DESC(shutdown, "Enable shutting down PLL and muting line when " +- "module is unloaded."); +- +-module_param(keepmuted, bool, 0644); +-MODULE_PARM_DESC(keepmuted, "Keep card muted even when frequency is changed."); +- +-module_param(initmute, bool, 0444); +-MODULE_PARM_DESC(initmute, "Mute card when module is loaded."); +- +-module_param(radio_nr, int, 0444); ++module_param_array(io, int, NULL, 0444); ++MODULE_PARM_DESC(io, "Force I/O ports for the GemTek Radio card if automatic " ++ "probing is disabled or fails. The most common I/O ports are: 0x20c " ++ "0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to " ++ "work for the combined sound/radiocard)."); + +-/* +- * Functions for controlling the card. +- */ +-#define GEMTEK_LOWFREQ (87*16000) +-#define GEMTEK_HIGHFREQ (108*16000) ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); + + /* + * Frequency calculation constants. Intermediate frequency 10.52 MHz (nominal +@@ -108,18 +100,11 @@ module_param(radio_nr, int, 0444); + #define LONG_DELAY 75 /* usec */ + + struct gemtek { +- struct v4l2_device v4l2_dev; +- struct video_device vdev; +- struct mutex lock; +- unsigned long lastfreq; +- int muted; +- int verified; +- int io; ++ struct radio_isa_card isa; ++ bool muted; + u32 bu2614data; + }; + +-static struct gemtek gemtek_card; +- + #define BU2614_FREQ_BITS 16 /* D0..D15, Frequency data */ + #define BU2614_PORT_BITS 3 /* P0..P2, Output port control data */ + #define BU2614_VOID_BITS 4 /* unused */ +@@ -166,31 +151,24 @@ static struct gemtek gemtek_card; + */ + static void gemtek_bu2614_transmit(struct gemtek *gt) + { ++ struct radio_isa_card *isa = >->isa; + int i, bit, q, mute; + +- mutex_lock(>->lock); +- + mute = gt->muted ? GEMTEK_MT : 0x00; + +- outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io); +- udelay(SHORT_DELAY); +- outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io); ++ outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, isa->io); + udelay(LONG_DELAY); + + for (i = 0, q = gt->bu2614data; i < 32; i++, q >>= 1) { + bit = (q & 1) ? GEMTEK_DA : 0; +- outb_p(mute | GEMTEK_CE | bit, gt->io); ++ outb_p(mute | GEMTEK_CE | bit, isa->io); + udelay(SHORT_DELAY); +- outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, gt->io); ++ outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, isa->io); + udelay(SHORT_DELAY); + } + +- outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io); ++ outb_p(mute | GEMTEK_DA | GEMTEK_CK, isa->io); + udelay(SHORT_DELAY); +- outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io); +- udelay(LONG_DELAY); +- +- mutex_unlock(>->lock); + } + + /* +@@ -198,21 +176,27 @@ static void gemtek_bu2614_transmit(struc + */ + static unsigned long gemtek_convfreq(unsigned long freq) + { +- return ((freq<muted = true; ++ return gt ? >->isa : NULL; + } + + /* + * Set FM-frequency. + */ +-static void gemtek_setfreq(struct gemtek *gt, unsigned long freq) ++static int gemtek_s_frequency(struct radio_isa_card *isa, u32 freq) + { +- if (keepmuted && hardmute && gt->muted) +- return; ++ struct gemtek *gt = container_of(isa, struct gemtek, isa); + +- freq = clamp_val(freq, GEMTEK_LOWFREQ, GEMTEK_HIGHFREQ); +- +- gt->lastfreq = freq; +- gt->muted = 0; ++ if (hardmute && gt->muted) ++ return 0; + + gemtek_bu2614_set(gt, BU2614_PORT, 0); + gemtek_bu2614_set(gt, BU2614_FMES, 0); +@@ -220,23 +204,25 @@ static void gemtek_setfreq(struct gemtek + gemtek_bu2614_set(gt, BU2614_SWAL, 0); + gemtek_bu2614_set(gt, BU2614_FMUN, 1); /* GT bit set */ + gemtek_bu2614_set(gt, BU2614_TEST, 0); +- + gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_STDF_3_125_KHZ); + gemtek_bu2614_set(gt, BU2614_FREQ, gemtek_convfreq(freq)); +- + gemtek_bu2614_transmit(gt); ++ return 0; + } + + /* + * Set mute flag. + */ +-static void gemtek_mute(struct gemtek *gt) ++static int gemtek_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) + { ++ struct gemtek *gt = container_of(isa, struct gemtek, isa); + int i; + +- gt->muted = 1; +- ++ gt->muted = mute; + if (hardmute) { ++ if (!mute) ++ return gemtek_s_frequency(isa, isa->freq); ++ + /* Turn off PLL, disable data output */ + gemtek_bu2614_set(gt, BU2614_PORT, 0); + gemtek_bu2614_set(gt, BU2614_FMES, 0); /* CT bit off */ +@@ -247,367 +233,85 @@ static void gemtek_mute(struct gemtek *g + gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_PLL_OFF); + gemtek_bu2614_set(gt, BU2614_FREQ, 0); + gemtek_bu2614_transmit(gt); +- return; ++ return 0; + } + +- mutex_lock(>->lock); +- + /* Read bus contents (CE, CK and DA). */ +- i = inb_p(gt->io); ++ i = inb_p(isa->io); + /* Write it back with mute flag set. */ +- outb_p((i >> 5) | GEMTEK_MT, gt->io); ++ outb_p((i >> 5) | (mute ? GEMTEK_MT : 0), isa->io); + udelay(SHORT_DELAY); +- +- mutex_unlock(>->lock); +-} +- +-/* +- * Unset mute flag. +- */ +-static void gemtek_unmute(struct gemtek *gt) +-{ +- int i; +- +- gt->muted = 0; +- if (hardmute) { +- /* Turn PLL back on. */ +- gemtek_setfreq(gt, gt->lastfreq); +- return; +- } +- mutex_lock(>->lock); +- +- i = inb_p(gt->io); +- outb_p(i >> 5, gt->io); +- udelay(SHORT_DELAY); +- +- mutex_unlock(>->lock); ++ return 0; + } + +-/* +- * Get signal strength (= stereo status). +- */ +-static inline int gemtek_getsigstr(struct gemtek *gt) ++static u32 gemtek_g_rxsubchans(struct radio_isa_card *isa) + { +- int sig; +- +- mutex_lock(>->lock); +- sig = inb_p(gt->io) & GEMTEK_NS ? 0 : 1; +- mutex_unlock(>->lock); +- return sig; ++ if (inb_p(isa->io) & GEMTEK_NS) ++ return V4L2_TUNER_SUB_MONO; ++ return V4L2_TUNER_SUB_STEREO; + } + + /* + * Check if requested card acts like GemTek Radio card. + */ +-static int gemtek_verify(struct gemtek *gt, int port) ++static bool gemtek_probe(struct radio_isa_card *isa, int io) + { + int i, q; + +- if (gt->verified == port) +- return 1; +- +- mutex_lock(>->lock); +- +- q = inb_p(port); /* Read bus contents before probing. */ ++ q = inb_p(io); /* Read bus contents before probing. */ + /* Try to turn on CE, CK and DA respectively and check if card responds + properly. */ + for (i = 0; i < 3; ++i) { +- outb_p(1 << i, port); ++ outb_p(1 << i, io); + udelay(SHORT_DELAY); + +- if ((inb_p(port) & (~GEMTEK_NS)) != (0x17 | (1 << (i + 5)))) { +- mutex_unlock(>->lock); +- return 0; +- } ++ if ((inb_p(io) & ~GEMTEK_NS) != (0x17 | (1 << (i + 5)))) ++ return false; + } +- outb_p(q >> 5, port); /* Write bus contents back. */ ++ outb_p(q >> 5, io); /* Write bus contents back. */ + udelay(SHORT_DELAY); +- +- mutex_unlock(>->lock); +- gt->verified = port; +- +- return 1; +-} +- +-/* +- * Automatic probing for card. +- */ +-static int gemtek_probe(struct gemtek *gt) +-{ +- struct v4l2_device *v4l2_dev = >->v4l2_dev; +- int ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c }; +- int i; +- +- if (!probe) { +- v4l2_info(v4l2_dev, "Automatic device probing disabled.\n"); +- return -1; +- } +- +- v4l2_info(v4l2_dev, "Automatic device probing enabled.\n"); +- +- for (i = 0; i < ARRAY_SIZE(ioports); ++i) { +- v4l2_info(v4l2_dev, "Trying I/O port 0x%x...\n", ioports[i]); +- +- if (!request_region(ioports[i], 1, "gemtek-probe")) { +- v4l2_warn(v4l2_dev, "I/O port 0x%x busy!\n", +- ioports[i]); +- continue; +- } +- +- if (gemtek_verify(gt, ioports[i])) { +- v4l2_info(v4l2_dev, "Card found from I/O port " +- "0x%x!\n", ioports[i]); +- +- release_region(ioports[i], 1); +- gt->io = ioports[i]; +- return gt->io; +- } +- +- release_region(ioports[i], 1); +- } +- +- v4l2_err(v4l2_dev, "Automatic probing failed!\n"); +- return -1; ++ return true; + } + +-/* +- * Video 4 Linux stuff. +- */ +- +-static const struct v4l2_file_operations gemtek_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, ++static const struct radio_isa_ops gemtek_ops = { ++ .alloc = gemtek_alloc, ++ .probe = gemtek_probe, ++ .s_mute_volume = gemtek_s_mute_volume, ++ .s_frequency = gemtek_s_frequency, ++ .g_rxsubchans = gemtek_g_rxsubchans, + }; + +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- strlcpy(v->driver, "radio-gemtek", sizeof(v->driver)); +- strlcpy(v->card, "GemTek", sizeof(v->card)); +- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; +- return 0; +-} +- +-static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) +-{ +- struct gemtek *gt = video_drvdata(file); +- +- if (v->index > 0) +- return -EINVAL; +- +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- v->rangelow = GEMTEK_LOWFREQ; +- v->rangehigh = GEMTEK_HIGHFREQ; +- v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; +- v->signal = 0xffff * gemtek_getsigstr(gt); +- if (v->signal) { +- v->audmode = V4L2_TUNER_MODE_STEREO; +- v->rxsubchans = V4L2_TUNER_SUB_STEREO; +- } else { +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->rxsubchans = V4L2_TUNER_SUB_MONO; +- } +- return 0; +-} +- +-static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) +-{ +- return (v->index != 0) ? -EINVAL : 0; +-} +- +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct gemtek *gt = video_drvdata(file); +- +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = gt->lastfreq; +- return 0; +-} +- +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct gemtek *gt = video_drvdata(file); +- +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- gemtek_setfreq(gt, f->frequency); +- return 0; +-} +- +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- switch (qc->id) { +- case V4L2_CID_AUDIO_MUTE: +- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); +- default: +- return -EINVAL; +- } +-} +- +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct gemtek *gt = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- ctrl->value = gt->muted; +- return 0; +- } +- return -EINVAL; +-} ++static const int gemtek_ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c }; + +-static int vidioc_s_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct gemtek *gt = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (ctrl->value) +- gemtek_mute(gt); +- else +- gemtek_unmute(gt); +- return 0; +- } +- return -EINVAL; +-} +- +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; +- return 0; +-} +- +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +-{ +- return (i != 0) ? -EINVAL : 0; +-} +- +-static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) +-{ +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; +-} +- +-static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) +-{ +- return (a->index != 0) ? -EINVAL : 0; +-} +- +-static const struct v4l2_ioctl_ops gemtek_ioctl_ops = { +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl ++static struct radio_isa_driver gemtek_driver = { ++ .driver = { ++ .match = radio_isa_match, ++ .probe = radio_isa_probe, ++ .remove = radio_isa_remove, ++ .driver = { ++ .name = "radio-gemtek", ++ }, ++ }, ++ .io_params = io, ++ .radio_nr_params = radio_nr, ++ .io_ports = gemtek_ioports, ++ .num_of_io_ports = ARRAY_SIZE(gemtek_ioports), ++ .region_size = 1, ++ .card = "GemTek Radio", ++ .ops = &gemtek_ops, ++ .has_stereo = true, + }; + +-/* +- * Initialization / cleanup related stuff. +- */ +- + static int __init gemtek_init(void) + { +- struct gemtek *gt = &gemtek_card; +- struct v4l2_device *v4l2_dev = >->v4l2_dev; +- int res; +- +- strlcpy(v4l2_dev->name, "gemtek", sizeof(v4l2_dev->name)); +- +- v4l2_info(v4l2_dev, "GemTek Radio card driver: v0.0.3\n"); +- +- mutex_init(>->lock); +- +- gt->verified = -1; +- gt->io = io; +- gemtek_probe(gt); +- if (gt->io) { +- if (!request_region(gt->io, 1, "gemtek")) { +- v4l2_err(v4l2_dev, "I/O port 0x%x already in use.\n", gt->io); +- return -EBUSY; +- } +- +- if (!gemtek_verify(gt, gt->io)) +- v4l2_warn(v4l2_dev, "Card at I/O port 0x%x does not " +- "respond properly, check your " +- "configuration.\n", gt->io); +- else +- v4l2_info(v4l2_dev, "Using I/O port 0x%x.\n", gt->io); +- } else if (probe) { +- v4l2_err(v4l2_dev, "Automatic probing failed and no " +- "fixed I/O port defined.\n"); +- return -ENODEV; +- } else { +- v4l2_err(v4l2_dev, "Automatic probing disabled but no fixed " +- "I/O port defined."); +- return -EINVAL; +- } +- +- res = v4l2_device_register(NULL, v4l2_dev); +- if (res < 0) { +- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); +- release_region(gt->io, 1); +- return res; +- } +- +- strlcpy(gt->vdev.name, v4l2_dev->name, sizeof(gt->vdev.name)); +- gt->vdev.v4l2_dev = v4l2_dev; +- gt->vdev.fops = &gemtek_fops; +- gt->vdev.ioctl_ops = &gemtek_ioctl_ops; +- gt->vdev.release = video_device_release_empty; +- video_set_drvdata(>->vdev, gt); +- +- /* Set defaults */ +- gt->lastfreq = GEMTEK_LOWFREQ; +- gt->bu2614data = 0; +- +- if (initmute) +- gemtek_mute(gt); +- +- if (video_register_device(>->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_device_unregister(v4l2_dev); +- release_region(gt->io, 1); +- return -EBUSY; +- } +- +- return 0; ++ gemtek_driver.probe = probe; ++ return isa_register_driver(&gemtek_driver.driver, GEMTEK_MAX); + } + +-/* +- * Module cleanup +- */ + static void __exit gemtek_exit(void) + { +- struct gemtek *gt = &gemtek_card; +- struct v4l2_device *v4l2_dev = >->v4l2_dev; +- +- if (shutdown) { +- hardmute = 1; /* Turn off PLL */ +- gemtek_mute(gt); +- } else { +- v4l2_info(v4l2_dev, "Module unloaded but card not muted!\n"); +- } +- +- video_unregister_device(>->vdev); +- v4l2_device_unregister(>->v4l2_dev); +- release_region(gt->io, 1); ++ hardmute = 1; /* Turn off PLL */ ++ isa_unregister_driver(&gemtek_driver.driver); + } + + module_init(gemtek_init); +Index: linux-3.3.x86_64/drivers/media/radio/radio-rtrack2.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-rtrack2.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-rtrack2.c +@@ -1,11 +1,12 @@ +-/* RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff ++/* ++ * RadioTrack II driver ++ * Copyright 1998 Ben Pfaff + * + * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood + * Converted to new API by Alan Cox + * Various bugfixes and enhancements by Russell Kroll + * +- * TODO: Allow for more than one of these foolish entities :-) +- * ++ * Converted to the radio-isa framework by Hans Verkuil + * Converted to V4L2 API by Mauro Carvalho Chehab + */ + +@@ -16,325 +17,123 @@ + #include /* kernel radio structs */ + #include + #include /* outb, outb_p */ ++#include + #include + #include ++#include "radio-isa.h" + + MODULE_AUTHOR("Ben Pfaff"); + MODULE_DESCRIPTION("A driver for the RadioTrack II radio card."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION("0.0.3"); ++MODULE_VERSION("0.1.99"); + + #ifndef CONFIG_RADIO_RTRACK2_PORT + #define CONFIG_RADIO_RTRACK2_PORT -1 + #endif + +-static int io = CONFIG_RADIO_RTRACK2_PORT; +-static int radio_nr = -1; +- +-module_param(io, int, 0); +-MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)"); +-module_param(radio_nr, int, 0); +- +-struct rtrack2 +-{ +- struct v4l2_device v4l2_dev; +- struct video_device vdev; +- int io; +- unsigned long curfreq; +- int muted; +- struct mutex lock; +-}; +- +-static struct rtrack2 rtrack2_card; ++#define RTRACK2_MAX 2 + ++static int io[RTRACK2_MAX] = { [0] = CONFIG_RADIO_RTRACK2_PORT, ++ [1 ... (RTRACK2_MAX - 1)] = -1 }; ++static int radio_nr[RTRACK2_MAX] = { [0 ... (RTRACK2_MAX - 1)] = -1 }; + +-/* local things */ +- +-static void rt_mute(struct rtrack2 *dev) +-{ +- if (dev->muted) +- return; +- mutex_lock(&dev->lock); +- outb(1, dev->io); +- mutex_unlock(&dev->lock); +- dev->muted = 1; +-} ++module_param_array(io, int, NULL, 0444); ++MODULE_PARM_DESC(io, "I/O addresses of the RadioTrack card (0x20f or 0x30f)"); ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); + +-static void rt_unmute(struct rtrack2 *dev) ++static struct radio_isa_card *rtrack2_alloc(void) + { +- if(dev->muted == 0) +- return; +- mutex_lock(&dev->lock); +- outb(0, dev->io); +- mutex_unlock(&dev->lock); +- dev->muted = 0; ++ return kzalloc(sizeof(struct radio_isa_card), GFP_KERNEL); + } + +-static void zero(struct rtrack2 *dev) ++static void zero(struct radio_isa_card *isa) + { +- outb_p(1, dev->io); +- outb_p(3, dev->io); +- outb_p(1, dev->io); ++ outb_p(1, isa->io); ++ outb_p(3, isa->io); ++ outb_p(1, isa->io); + } + +-static void one(struct rtrack2 *dev) ++static void one(struct radio_isa_card *isa) + { +- outb_p(5, dev->io); +- outb_p(7, dev->io); +- outb_p(5, dev->io); ++ outb_p(5, isa->io); ++ outb_p(7, isa->io); ++ outb_p(5, isa->io); + } + +-static int rt_setfreq(struct rtrack2 *dev, unsigned long freq) ++static int rtrack2_s_frequency(struct radio_isa_card *isa, u32 freq) + { + int i; + +- mutex_lock(&dev->lock); +- dev->curfreq = freq; + freq = freq / 200 + 856; + +- outb_p(0xc8, dev->io); +- outb_p(0xc9, dev->io); +- outb_p(0xc9, dev->io); ++ outb_p(0xc8, isa->io); ++ outb_p(0xc9, isa->io); ++ outb_p(0xc9, isa->io); + + for (i = 0; i < 10; i++) +- zero(dev); ++ zero(isa); + + for (i = 14; i >= 0; i--) + if (freq & (1 << i)) +- one(dev); ++ one(isa); + else +- zero(dev); +- +- outb_p(0xc8, dev->io); +- if (!dev->muted) +- outb_p(0, dev->io); +- +- mutex_unlock(&dev->lock); +- return 0; +-} +- +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- strlcpy(v->driver, "radio-rtrack2", sizeof(v->driver)); +- strlcpy(v->card, "RadioTrack II", sizeof(v->card)); +- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; +- return 0; +-} +- +-static int vidioc_s_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- return v->index ? -EINVAL : 0; +-} +- +-static int rt_getsigstr(struct rtrack2 *dev) +-{ +- int sig = 1; +- +- mutex_lock(&dev->lock); +- if (inb(dev->io) & 2) /* bit set = no signal present */ +- sig = 0; +- mutex_unlock(&dev->lock); +- return sig; +-} ++ zero(isa); + +-static int vidioc_g_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- struct rtrack2 *rt = video_drvdata(file); +- +- if (v->index > 0) +- return -EINVAL; +- +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- v->rangelow = 88 * 16000; +- v->rangehigh = 108 * 16000; +- v->rxsubchans = V4L2_TUNER_SUB_MONO; +- v->capability = V4L2_TUNER_CAP_LOW; +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->signal = 0xFFFF * rt_getsigstr(rt); ++ outb_p(0xc8, isa->io); ++ if (!v4l2_ctrl_g_ctrl(isa->mute)) ++ outb_p(0, isa->io); + return 0; + } + +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) ++static u32 rtrack2_g_signal(struct radio_isa_card *isa) + { +- struct rtrack2 *rt = video_drvdata(file); +- +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- rt_setfreq(rt, f->frequency); +- return 0; ++ /* bit set = no signal present */ ++ return (inb(isa->io) & 2) ? 0 : 0xffff; + } + +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) ++static int rtrack2_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) + { +- struct rtrack2 *rt = video_drvdata(file); +- +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = rt->curfreq; ++ outb(mute, isa->io); + return 0; + } + +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- switch (qc->id) { +- case V4L2_CID_AUDIO_MUTE: +- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); +- case V4L2_CID_AUDIO_VOLUME: +- return v4l2_ctrl_query_fill(qc, 0, 65535, 65535, 65535); +- } +- return -EINVAL; +-} +- +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct rtrack2 *rt = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- ctrl->value = rt->muted; +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- if (rt->muted) +- ctrl->value = 0; +- else +- ctrl->value = 65535; +- return 0; +- } +- return -EINVAL; +-} +- +-static int vidioc_s_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct rtrack2 *rt = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (ctrl->value) +- rt_mute(rt); +- else +- rt_unmute(rt); +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- if (ctrl->value) +- rt_unmute(rt); +- else +- rt_mute(rt); +- return 0; +- } +- return -EINVAL; +-} +- +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; +- return 0; +-} +- +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +-{ +- return i ? -EINVAL : 0; +-} +- +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; +-} +- +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- return a->index ? -EINVAL : 0; +-} +- +-static const struct v4l2_file_operations rtrack2_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, ++static const struct radio_isa_ops rtrack2_ops = { ++ .alloc = rtrack2_alloc, ++ .s_mute_volume = rtrack2_s_mute_volume, ++ .s_frequency = rtrack2_s_frequency, ++ .g_signal = rtrack2_g_signal, + }; + +-static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = { +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, ++static const int rtrack2_ioports[] = { 0x20f, 0x30f }; ++ ++static struct radio_isa_driver rtrack2_driver = { ++ .driver = { ++ .match = radio_isa_match, ++ .probe = radio_isa_probe, ++ .remove = radio_isa_remove, ++ .driver = { ++ .name = "radio-rtrack2", ++ }, ++ }, ++ .io_params = io, ++ .radio_nr_params = radio_nr, ++ .io_ports = rtrack2_ioports, ++ .num_of_io_ports = ARRAY_SIZE(rtrack2_ioports), ++ .region_size = 4, ++ .card = "AIMSlab RadioTrack II", ++ .ops = &rtrack2_ops, ++ .has_stereo = true, + }; + + static int __init rtrack2_init(void) + { +- struct rtrack2 *dev = &rtrack2_card; +- struct v4l2_device *v4l2_dev = &dev->v4l2_dev; +- int res; +- +- strlcpy(v4l2_dev->name, "rtrack2", sizeof(v4l2_dev->name)); +- dev->io = io; +- if (dev->io == -1) { +- v4l2_err(v4l2_dev, "You must set an I/O address with io=0x20c or io=0x30c\n"); +- return -EINVAL; +- } +- if (!request_region(dev->io, 4, "rtrack2")) { +- v4l2_err(v4l2_dev, "port 0x%x already in use\n", dev->io); +- return -EBUSY; +- } +- +- res = v4l2_device_register(NULL, v4l2_dev); +- if (res < 0) { +- release_region(dev->io, 4); +- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); +- return res; +- } +- +- strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); +- dev->vdev.v4l2_dev = v4l2_dev; +- dev->vdev.fops = &rtrack2_fops; +- dev->vdev.ioctl_ops = &rtrack2_ioctl_ops; +- dev->vdev.release = video_device_release_empty; +- video_set_drvdata(&dev->vdev, dev); +- +- /* mute card - prevents noisy bootups */ +- outb(1, dev->io); +- dev->muted = 1; +- +- mutex_init(&dev->lock); +- if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_device_unregister(v4l2_dev); +- release_region(dev->io, 4); +- return -EINVAL; +- } +- +- v4l2_info(v4l2_dev, "AIMSlab Radiotrack II card driver.\n"); +- +- return 0; ++ return isa_register_driver(&rtrack2_driver.driver, RTRACK2_MAX); + } + + static void __exit rtrack2_exit(void) + { +- struct rtrack2 *dev = &rtrack2_card; +- +- video_unregister_device(&dev->vdev); +- v4l2_device_unregister(&dev->v4l2_dev); +- release_region(dev->io, 4); ++ isa_unregister_driver(&rtrack2_driver.driver); + } + + module_init(rtrack2_init); +Index: linux-3.3.x86_64/drivers/media/radio/radio-terratec.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-terratec.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-terratec.c +@@ -16,11 +16,7 @@ + * Frequency control is done digitally -- ie out(port,encodefreq(95.8)); + * Volume Control is done digitally + * +- * there is a I2C controlled RDS decoder (SAA6588) onboard, which i would like to support someday +- * (as soon i have understand how to get started :) +- * If you can help me out with that, please contact me!! +- * +- * ++ * Converted to the radio-isa framework by Hans Verkuil + * Converted to V4L2 API by Mauro Carvalho Chehab + */ + +@@ -30,43 +26,24 @@ + #include /* kernel radio structs */ + #include + #include /* outb, outb_p */ ++#include + #include + #include ++#include "radio-isa.h" + +-MODULE_AUTHOR("R.OFFERMANNS & others"); ++MODULE_AUTHOR("R. Offermans & others"); + MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION("0.0.3"); +- +-#ifndef CONFIG_RADIO_TERRATEC_PORT +-#define CONFIG_RADIO_TERRATEC_PORT 0x590 +-#endif ++MODULE_VERSION("0.1.99"); + +-static int io = CONFIG_RADIO_TERRATEC_PORT; ++/* Note: there seems to be only one possible port (0x590), but without ++ hardware this is hard to verify. For now, this is the only one we will ++ support. */ ++static int io = 0x590; + static int radio_nr = -1; + +-module_param(io, int, 0); +-MODULE_PARM_DESC(io, "I/O address of the TerraTec ActiveRadio card (0x590 or 0x591)"); +-module_param(radio_nr, int, 0); +- +-static struct v4l2_queryctrl radio_qctrl[] = { +- { +- .id = V4L2_CID_AUDIO_MUTE, +- .name = "Mute", +- .minimum = 0, +- .maximum = 1, +- .default_value = 1, +- .type = V4L2_CTRL_TYPE_BOOLEAN, +- },{ +- .id = V4L2_CID_AUDIO_VOLUME, +- .name = "Volume", +- .minimum = 0, +- .maximum = 0xff, +- .step = 1, +- .default_value = 0xff, +- .type = V4L2_CTRL_TYPE_INTEGER, +- } +-}; ++module_param(radio_nr, int, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device number"); + + #define WRT_DIS 0x00 + #define CLK_OFF 0x00 +@@ -76,63 +53,24 @@ static struct v4l2_queryctrl radio_qctrl + #define CLK_ON 0x08 + #define WRT_EN 0x10 + +-struct terratec ++static struct radio_isa_card *terratec_alloc(void) + { +- struct v4l2_device v4l2_dev; +- struct video_device vdev; +- int io; +- int curvol; +- unsigned long curfreq; +- int muted; +- struct mutex lock; +-}; +- +-static struct terratec terratec_card; +- +-/* local things */ ++ return kzalloc(sizeof(struct radio_isa_card), GFP_KERNEL); ++} + +-static void tt_write_vol(struct terratec *tt, int volume) ++static int terratec_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) + { + int i; + +- volume = volume + (volume * 32); /* change both channels */ +- mutex_lock(&tt->lock); ++ if (mute) ++ vol = 0; ++ vol = vol + (vol * 32); /* change both channels */ + for (i = 0; i < 8; i++) { +- if (volume & (0x80 >> i)) +- outb(0x80, tt->io + 1); ++ if (vol & (0x80 >> i)) ++ outb(0x80, isa->io + 1); + else +- outb(0x00, tt->io + 1); ++ outb(0x00, isa->io + 1); + } +- mutex_unlock(&tt->lock); +-} +- +- +- +-static void tt_mute(struct terratec *tt) +-{ +- tt->muted = 1; +- tt_write_vol(tt, 0); +-} +- +-static int tt_setvol(struct terratec *tt, int vol) +-{ +- if (vol == tt->curvol) { /* requested volume = current */ +- if (tt->muted) { /* user is unmuting the card */ +- tt->muted = 0; +- tt_write_vol(tt, vol); /* enable card */ +- } +- return 0; +- } +- +- if (vol == 0) { /* volume = 0 means mute the card */ +- tt_write_vol(tt, 0); /* "turn off card" by setting vol to 0 */ +- tt->curvol = vol; /* track the volume state! */ +- return 0; +- } +- +- tt->muted = 0; +- tt_write_vol(tt, vol); +- tt->curvol = vol; + return 0; + } + +@@ -140,20 +78,15 @@ static int tt_setvol(struct terratec *tt + /* this is the worst part in this driver */ + /* many more or less strange things are going on here, but hey, it works :) */ + +-static int tt_setfreq(struct terratec *tt, unsigned long freq1) ++static int terratec_s_frequency(struct radio_isa_card *isa, u32 freq) + { +- int freq; + int i; + int p; +- int temp; ++ int temp; + long rest; + unsigned char buffer[25]; /* we have to bit shift 25 registers */ + +- mutex_lock(&tt->lock); +- +- tt->curfreq = freq1; +- +- freq = freq1 / 160; /* convert the freq. to a nice to handle value */ ++ freq = freq / 160; /* convert the freq. to a nice to handle value */ + memset(buffer, 0, sizeof(buffer)); + + rest = freq * 10 + 10700; /* I once had understood what is going on here */ +@@ -175,239 +108,61 @@ static int tt_setfreq(struct terratec *t + + for (i = 24; i > -1; i--) { /* bit shift the values to the radiocard */ + if (buffer[i] == 1) { +- outb(WRT_EN | DATA, tt->io); +- outb(WRT_EN | DATA | CLK_ON, tt->io); +- outb(WRT_EN | DATA, tt->io); ++ outb(WRT_EN | DATA, isa->io); ++ outb(WRT_EN | DATA | CLK_ON, isa->io); ++ outb(WRT_EN | DATA, isa->io); + } else { +- outb(WRT_EN | 0x00, tt->io); +- outb(WRT_EN | 0x00 | CLK_ON, tt->io); +- } +- } +- outb(0x00, tt->io); +- +- mutex_unlock(&tt->lock); +- +- return 0; +-} +- +-static int tt_getsigstr(struct terratec *tt) +-{ +- if (inb(tt->io) & 2) /* bit set = no signal present */ +- return 0; +- return 1; /* signal present */ +-} +- +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- strlcpy(v->driver, "radio-terratec", sizeof(v->driver)); +- strlcpy(v->card, "ActiveRadio", sizeof(v->card)); +- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; +- return 0; +-} +- +-static int vidioc_g_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- struct terratec *tt = video_drvdata(file); +- +- if (v->index > 0) +- return -EINVAL; +- +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- v->rangelow = 87 * 16000; +- v->rangehigh = 108 * 16000; +- v->rxsubchans = V4L2_TUNER_SUB_MONO; +- v->capability = V4L2_TUNER_CAP_LOW; +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->signal = 0xFFFF * tt_getsigstr(tt); +- return 0; +-} +- +-static int vidioc_s_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- return v->index ? -EINVAL : 0; +-} +- +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct terratec *tt = video_drvdata(file); +- +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- tt_setfreq(tt, f->frequency); +- return 0; +-} +- +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct terratec *tt = video_drvdata(file); +- +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = tt->curfreq; +- return 0; +-} +- +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { +- if (qc->id && qc->id == radio_qctrl[i].id) { +- memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); +- return 0; ++ outb(WRT_EN | 0x00, isa->io); ++ outb(WRT_EN | 0x00 | CLK_ON, isa->io); + } + } +- return -EINVAL; +-} +- +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct terratec *tt = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (tt->muted) +- ctrl->value = 1; +- else +- ctrl->value = 0; +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- ctrl->value = tt->curvol * 6554; +- return 0; +- } +- return -EINVAL; +-} +- +-static int vidioc_s_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct terratec *tt = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (ctrl->value) +- tt_mute(tt); +- else +- tt_setvol(tt,tt->curvol); +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- tt_setvol(tt,ctrl->value); +- return 0; +- } +- return -EINVAL; +-} +- +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; ++ outb(0x00, isa->io); + return 0; + } + +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) ++static u32 terratec_g_signal(struct radio_isa_card *isa) + { +- return i ? -EINVAL : 0; ++ /* bit set = no signal present */ ++ return (inb(isa->io) & 2) ? 0 : 0xffff; + } + +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; +-} +- +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- return a->index ? -EINVAL : 0; +-} +- +-static const struct v4l2_file_operations terratec_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, ++static const struct radio_isa_ops terratec_ops = { ++ .alloc = terratec_alloc, ++ .s_mute_volume = terratec_s_mute_volume, ++ .s_frequency = terratec_s_frequency, ++ .g_signal = terratec_g_signal, + }; + +-static const struct v4l2_ioctl_ops terratec_ioctl_ops = { +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, ++static const int terratec_ioports[] = { 0x590 }; ++ ++static struct radio_isa_driver terratec_driver = { ++ .driver = { ++ .match = radio_isa_match, ++ .probe = radio_isa_probe, ++ .remove = radio_isa_remove, ++ .driver = { ++ .name = "radio-terratec", ++ }, ++ }, ++ .io_params = &io, ++ .radio_nr_params = &radio_nr, ++ .io_ports = terratec_ioports, ++ .num_of_io_ports = ARRAY_SIZE(terratec_ioports), ++ .region_size = 2, ++ .card = "TerraTec ActiveRadio", ++ .ops = &terratec_ops, ++ .has_stereo = true, ++ .max_volume = 10, + }; + + static int __init terratec_init(void) + { +- struct terratec *tt = &terratec_card; +- struct v4l2_device *v4l2_dev = &tt->v4l2_dev; +- int res; +- +- strlcpy(v4l2_dev->name, "terratec", sizeof(v4l2_dev->name)); +- tt->io = io; +- if (tt->io == -1) { +- v4l2_err(v4l2_dev, "you must set an I/O address with io=0x590 or 0x591\n"); +- return -EINVAL; +- } +- if (!request_region(tt->io, 2, "terratec")) { +- v4l2_err(v4l2_dev, "port 0x%x already in use\n", io); +- return -EBUSY; +- } +- +- res = v4l2_device_register(NULL, v4l2_dev); +- if (res < 0) { +- release_region(tt->io, 2); +- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); +- return res; +- } +- +- strlcpy(tt->vdev.name, v4l2_dev->name, sizeof(tt->vdev.name)); +- tt->vdev.v4l2_dev = v4l2_dev; +- tt->vdev.fops = &terratec_fops; +- tt->vdev.ioctl_ops = &terratec_ioctl_ops; +- tt->vdev.release = video_device_release_empty; +- video_set_drvdata(&tt->vdev, tt); +- +- mutex_init(&tt->lock); +- +- /* mute card - prevents noisy bootups */ +- tt_write_vol(tt, 0); +- +- if (video_register_device(&tt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_device_unregister(&tt->v4l2_dev); +- release_region(tt->io, 2); +- return -EINVAL; +- } +- +- v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver.\n"); +- return 0; ++ return isa_register_driver(&terratec_driver.driver, 1); + } + + static void __exit terratec_exit(void) + { +- struct terratec *tt = &terratec_card; +- struct v4l2_device *v4l2_dev = &tt->v4l2_dev; +- +- video_unregister_device(&tt->vdev); +- v4l2_device_unregister(&tt->v4l2_dev); +- release_region(tt->io, 2); +- v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver unloaded.\n"); ++ isa_unregister_driver(&terratec_driver.driver); + } + + module_init(terratec_init); +Index: linux-3.3.x86_64/drivers/media/radio/radio-trust.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-trust.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-trust.c +@@ -21,13 +21,15 @@ + #include + #include + #include ++#include + #include + #include ++#include "radio-isa.h" + + MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); + MODULE_DESCRIPTION("A driver for the Trust FM Radio card."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION("0.0.3"); ++MODULE_VERSION("0.1.99"); + + /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ + +@@ -35,39 +37,38 @@ MODULE_VERSION("0.0.3"); + #define CONFIG_RADIO_TRUST_PORT -1 + #endif + +-static int io = CONFIG_RADIO_TRUST_PORT; +-static int radio_nr = -1; ++#define TRUST_MAX 2 + +-module_param(io, int, 0); +-MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)"); +-module_param(radio_nr, int, 0); ++static int io[TRUST_MAX] = { [0] = CONFIG_RADIO_TRUST_PORT, ++ [1 ... (TRUST_MAX - 1)] = -1 }; ++static int radio_nr[TRUST_MAX] = { [0 ... (TRUST_MAX - 1)] = -1 }; ++ ++module_param_array(io, int, NULL, 0444); ++MODULE_PARM_DESC(io, "I/O addresses of the Trust FM Radio card (0x350 or 0x358)"); ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); + + struct trust { +- struct v4l2_device v4l2_dev; +- struct video_device vdev; +- int io; ++ struct radio_isa_card isa; + int ioval; +- __u16 curvol; +- __u16 curbass; +- __u16 curtreble; +- int muted; +- unsigned long curfreq; +- int curstereo; +- int curmute; +- struct mutex lock; + }; + +-static struct trust trust_card; ++static struct radio_isa_card *trust_alloc(void) ++{ ++ struct trust *tr = kzalloc(sizeof(*tr), GFP_KERNEL); ++ ++ return tr ? &tr->isa : NULL; ++} + + /* i2c addresses */ + #define TDA7318_ADDR 0x88 + #define TSA6060T_ADDR 0xc4 + +-#define TR_DELAY do { inb(tr->io); inb(tr->io); inb(tr->io); } while (0) +-#define TR_SET_SCL outb(tr->ioval |= 2, tr->io) +-#define TR_CLR_SCL outb(tr->ioval &= 0xfd, tr->io) +-#define TR_SET_SDA outb(tr->ioval |= 1, tr->io) +-#define TR_CLR_SDA outb(tr->ioval &= 0xfe, tr->io) ++#define TR_DELAY do { inb(tr->isa.io); inb(tr->isa.io); inb(tr->isa.io); } while (0) ++#define TR_SET_SCL outb(tr->ioval |= 2, tr->isa.io) ++#define TR_CLR_SCL outb(tr->ioval &= 0xfd, tr->isa.io) ++#define TR_SET_SDA outb(tr->ioval |= 1, tr->isa.io) ++#define TR_CLR_SDA outb(tr->ioval &= 0xfe, tr->isa.io) + + static void write_i2c(struct trust *tr, int n, ...) + { +@@ -84,10 +85,10 @@ static void write_i2c(struct trust *tr, + TR_CLR_SCL; + TR_DELAY; + +- for(; n; n--) { ++ for (; n; n--) { + val = va_arg(args, unsigned); +- for(mask = 0x80; mask; mask >>= 1) { +- if(val & mask) ++ for (mask = 0x80; mask; mask >>= 1) { ++ if (val & mask) + TR_SET_SDA; + else + TR_CLR_SDA; +@@ -115,317 +116,128 @@ static void write_i2c(struct trust *tr, + va_end(args); + } + +-static void tr_setvol(struct trust *tr, __u16 vol) ++static int trust_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) + { +- mutex_lock(&tr->lock); +- tr->curvol = vol / 2048; +- write_i2c(tr, 2, TDA7318_ADDR, tr->curvol ^ 0x1f); +- mutex_unlock(&tr->lock); +-} ++ struct trust *tr = container_of(isa, struct trust, isa); + +-static int basstreble2chip[15] = { +- 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8 +-}; +- +-static void tr_setbass(struct trust *tr, __u16 bass) +-{ +- mutex_lock(&tr->lock); +- tr->curbass = bass / 4370; +- write_i2c(tr, 2, TDA7318_ADDR, 0x60 | basstreble2chip[tr->curbass]); +- mutex_unlock(&tr->lock); ++ tr->ioval = (tr->ioval & 0xf7) | (mute << 3); ++ outb(tr->ioval, isa->io); ++ write_i2c(tr, 2, TDA7318_ADDR, vol ^ 0x1f); ++ return 0; + } + +-static void tr_settreble(struct trust *tr, __u16 treble) ++static int trust_s_stereo(struct radio_isa_card *isa, bool stereo) + { +- mutex_lock(&tr->lock); +- tr->curtreble = treble / 4370; +- write_i2c(tr, 2, TDA7318_ADDR, 0x70 | basstreble2chip[tr->curtreble]); +- mutex_unlock(&tr->lock); +-} ++ struct trust *tr = container_of(isa, struct trust, isa); + +-static void tr_setstereo(struct trust *tr, int stereo) +-{ +- mutex_lock(&tr->lock); +- tr->curstereo = !!stereo; +- tr->ioval = (tr->ioval & 0xfb) | (!tr->curstereo << 2); +- outb(tr->ioval, tr->io); +- mutex_unlock(&tr->lock); +-} +- +-static void tr_setmute(struct trust *tr, int mute) +-{ +- mutex_lock(&tr->lock); +- tr->curmute = !!mute; +- tr->ioval = (tr->ioval & 0xf7) | (tr->curmute << 3); +- outb(tr->ioval, tr->io); +- mutex_unlock(&tr->lock); ++ tr->ioval = (tr->ioval & 0xfb) | (!stereo << 2); ++ outb(tr->ioval, isa->io); ++ return 0; + } + +-static int tr_getsigstr(struct trust *tr) ++static u32 trust_g_signal(struct radio_isa_card *isa) + { + int i, v; + +- mutex_lock(&tr->lock); + for (i = 0, v = 0; i < 100; i++) +- v |= inb(tr->io); +- mutex_unlock(&tr->lock); ++ v |= inb(isa->io); + return (v & 1) ? 0 : 0xffff; + } + +-static int tr_getstereo(struct trust *tr) +-{ +- /* don't know how to determine it, just return the setting */ +- return tr->curstereo; +-} +- +-static void tr_setfreq(struct trust *tr, unsigned long f) +-{ +- mutex_lock(&tr->lock); +- tr->curfreq = f; +- f /= 160; /* Convert to 10 kHz units */ +- f += 1070; /* Add 10.7 MHz IF */ +- write_i2c(tr, 5, TSA6060T_ADDR, (f << 1) | 1, f >> 7, 0x60 | ((f >> 15) & 1), 0); +- mutex_unlock(&tr->lock); +-} +- +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- strlcpy(v->driver, "radio-trust", sizeof(v->driver)); +- strlcpy(v->card, "Trust FM Radio", sizeof(v->card)); +- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; +- return 0; +-} +- +-static int vidioc_g_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- struct trust *tr = video_drvdata(file); +- +- if (v->index > 0) +- return -EINVAL; +- +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- v->rangelow = 87.5 * 16000; +- v->rangehigh = 108 * 16000; +- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; +- v->capability = V4L2_TUNER_CAP_LOW; +- if (tr_getstereo(tr)) +- v->audmode = V4L2_TUNER_MODE_STEREO; +- else +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->signal = tr_getsigstr(tr); +- return 0; +-} +- +-static int vidioc_s_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) ++static int trust_s_frequency(struct radio_isa_card *isa, u32 freq) + { +- struct trust *tr = video_drvdata(file); ++ struct trust *tr = container_of(isa, struct trust, isa); + +- if (v->index) +- return -EINVAL; +- tr_setstereo(tr, v->audmode == V4L2_TUNER_MODE_STEREO); ++ freq /= 160; /* Convert to 10 kHz units */ ++ freq += 1070; /* Add 10.7 MHz IF */ ++ write_i2c(tr, 5, TSA6060T_ADDR, (freq << 1) | 1, ++ freq >> 7, 0x60 | ((freq >> 15) & 1), 0); + return 0; + } + +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct trust *tr = video_drvdata(file); +- +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- tr_setfreq(tr, f->frequency); +- return 0; +-} +- +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct trust *tr = video_drvdata(file); +- +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = tr->curfreq; +- return 0; +-} +- +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- switch (qc->id) { +- case V4L2_CID_AUDIO_MUTE: +- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); +- case V4L2_CID_AUDIO_VOLUME: +- return v4l2_ctrl_query_fill(qc, 0, 65535, 2048, 65535); +- case V4L2_CID_AUDIO_BASS: +- case V4L2_CID_AUDIO_TREBLE: +- return v4l2_ctrl_query_fill(qc, 0, 65535, 4370, 32768); +- } +- return -EINVAL; +-} +- +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct trust *tr = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- ctrl->value = tr->curmute; +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- ctrl->value = tr->curvol * 2048; +- return 0; +- case V4L2_CID_AUDIO_BASS: +- ctrl->value = tr->curbass * 4370; +- return 0; +- case V4L2_CID_AUDIO_TREBLE: +- ctrl->value = tr->curtreble * 4370; +- return 0; +- } +- return -EINVAL; +-} ++static int basstreble2chip[15] = { ++ 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8 ++}; + +-static int vidioc_s_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) ++static int trust_s_ctrl(struct v4l2_ctrl *ctrl) + { +- struct trust *tr = video_drvdata(file); ++ struct radio_isa_card *isa = ++ container_of(ctrl->handler, struct radio_isa_card, hdl); ++ struct trust *tr = container_of(isa, struct trust, isa); + + switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- tr_setmute(tr, ctrl->value); +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- tr_setvol(tr, ctrl->value); +- return 0; + case V4L2_CID_AUDIO_BASS: +- tr_setbass(tr, ctrl->value); ++ write_i2c(tr, 2, TDA7318_ADDR, 0x60 | basstreble2chip[ctrl->val]); + return 0; + case V4L2_CID_AUDIO_TREBLE: +- tr_settreble(tr, ctrl->value); ++ write_i2c(tr, 2, TDA7318_ADDR, 0x70 | basstreble2chip[ctrl->val]); + return 0; + } + return -EINVAL; + } + +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; +- return 0; +-} +- +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +-{ +- return i ? -EINVAL : 0; +-} +- +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; +-} +- +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- return a->index ? -EINVAL : 0; +-} +- +-static const struct v4l2_file_operations trust_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, +-}; +- +-static const struct v4l2_ioctl_ops trust_ioctl_ops = { +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, ++static const struct v4l2_ctrl_ops trust_ctrl_ops = { ++ .s_ctrl = trust_s_ctrl, + }; + +-static int __init trust_init(void) ++static int trust_initialize(struct radio_isa_card *isa) + { +- struct trust *tr = &trust_card; +- struct v4l2_device *v4l2_dev = &tr->v4l2_dev; +- int res; ++ struct trust *tr = container_of(isa, struct trust, isa); + +- strlcpy(v4l2_dev->name, "trust", sizeof(v4l2_dev->name)); +- tr->io = io; + tr->ioval = 0xf; +- mutex_init(&tr->lock); +- +- if (tr->io == -1) { +- v4l2_err(v4l2_dev, "You must set an I/O address with io=0x0x350 or 0x358\n"); +- return -EINVAL; +- } +- if (!request_region(tr->io, 2, "Trust FM Radio")) { +- v4l2_err(v4l2_dev, "port 0x%x already in use\n", tr->io); +- return -EBUSY; +- } +- +- res = v4l2_device_register(NULL, v4l2_dev); +- if (res < 0) { +- release_region(tr->io, 2); +- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); +- return res; +- } +- +- strlcpy(tr->vdev.name, v4l2_dev->name, sizeof(tr->vdev.name)); +- tr->vdev.v4l2_dev = v4l2_dev; +- tr->vdev.fops = &trust_fops; +- tr->vdev.ioctl_ops = &trust_ioctl_ops; +- tr->vdev.release = video_device_release_empty; +- video_set_drvdata(&tr->vdev, tr); +- + write_i2c(tr, 2, TDA7318_ADDR, 0x80); /* speaker att. LF = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0xa0); /* speaker att. RF = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0xc0); /* speaker att. LR = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0xe0); /* speaker att. RR = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0x40); /* stereo 1 input, gain = 18.75 dB */ + +- tr_setvol(tr, 0xffff); +- tr_setbass(tr, 0x8000); +- tr_settreble(tr, 0x8000); +- tr_setstereo(tr, 1); +- +- /* mute card - prevents noisy bootups */ +- tr_setmute(tr, 1); +- +- if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_device_unregister(v4l2_dev); +- release_region(tr->io, 2); +- return -EINVAL; +- } ++ v4l2_ctrl_new_std(&isa->hdl, &trust_ctrl_ops, ++ V4L2_CID_AUDIO_BASS, 0, 15, 1, 8); ++ v4l2_ctrl_new_std(&isa->hdl, &trust_ctrl_ops, ++ V4L2_CID_AUDIO_TREBLE, 0, 15, 1, 8); ++ return isa->hdl.error; ++} + +- v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n"); ++static const struct radio_isa_ops trust_ops = { ++ .init = trust_initialize, ++ .alloc = trust_alloc, ++ .s_mute_volume = trust_s_mute_volume, ++ .s_frequency = trust_s_frequency, ++ .s_stereo = trust_s_stereo, ++ .g_signal = trust_g_signal, ++}; + +- return 0; +-} ++static const int trust_ioports[] = { 0x350, 0x358 }; ++ ++static struct radio_isa_driver trust_driver = { ++ .driver = { ++ .match = radio_isa_match, ++ .probe = radio_isa_probe, ++ .remove = radio_isa_remove, ++ .driver = { ++ .name = "radio-trust", ++ }, ++ }, ++ .io_params = io, ++ .radio_nr_params = radio_nr, ++ .io_ports = trust_ioports, ++ .num_of_io_ports = ARRAY_SIZE(trust_ioports), ++ .region_size = 2, ++ .card = "Trust FM Radio", ++ .ops = &trust_ops, ++ .has_stereo = true, ++ .max_volume = 31, ++}; + +-static void __exit cleanup_trust_module(void) ++static int __init trust_init(void) + { +- struct trust *tr = &trust_card; ++ return isa_register_driver(&trust_driver.driver, TRUST_MAX); ++} + +- video_unregister_device(&tr->vdev); +- v4l2_device_unregister(&tr->v4l2_dev); +- release_region(tr->io, 2); ++static void __exit trust_exit(void) ++{ ++ isa_unregister_driver(&trust_driver.driver); + } + + module_init(trust_init); +-module_exit(cleanup_trust_module); ++module_exit(trust_exit); +Index: linux-3.3.x86_64/drivers/media/radio/radio-typhoon.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-typhoon.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-typhoon.c +@@ -33,63 +33,53 @@ + #include /* request_region */ + #include /* kernel radio structs */ + #include /* outb, outb_p */ ++#include + #include + #include ++#include "radio-isa.h" + + #define DRIVER_VERSION "0.1.2" + + MODULE_AUTHOR("Dr. Henrik Seidel"); + MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio)."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION(DRIVER_VERSION); ++MODULE_VERSION("0.1.99"); + + #ifndef CONFIG_RADIO_TYPHOON_PORT + #define CONFIG_RADIO_TYPHOON_PORT -1 + #endif + + #ifndef CONFIG_RADIO_TYPHOON_MUTEFREQ +-#define CONFIG_RADIO_TYPHOON_MUTEFREQ 0 ++#define CONFIG_RADIO_TYPHOON_MUTEFREQ 87000 + #endif + +-static int io = CONFIG_RADIO_TYPHOON_PORT; +-static int radio_nr = -1; +- +-module_param(io, int, 0); +-MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)"); +- +-module_param(radio_nr, int, 0); ++#define TYPHOON_MAX 2 + ++static int io[TYPHOON_MAX] = { [0] = CONFIG_RADIO_TYPHOON_PORT, ++ [1 ... (TYPHOON_MAX - 1)] = -1 }; ++static int radio_nr[TYPHOON_MAX] = { [0 ... (TYPHOON_MAX - 1)] = -1 }; + static unsigned long mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ; ++ ++module_param_array(io, int, NULL, 0444); ++MODULE_PARM_DESC(io, "I/O addresses of the Typhoon card (0x316 or 0x336)"); ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); + module_param(mutefreq, ulong, 0); + MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)"); + +-#define BANNER "Typhoon Radio Card driver v" DRIVER_VERSION "\n" +- + struct typhoon { +- struct v4l2_device v4l2_dev; +- struct video_device vdev; +- int io; +- int curvol; ++ struct radio_isa_card isa; + int muted; +- unsigned long curfreq; +- unsigned long mutefreq; +- struct mutex lock; + }; + +-static struct typhoon typhoon_card; +- +-static void typhoon_setvol_generic(struct typhoon *dev, int vol) ++static struct radio_isa_card *typhoon_alloc(void) + { +- mutex_lock(&dev->lock); +- vol >>= 14; /* Map 16 bit to 2 bit */ +- vol &= 3; +- outb_p(vol / 2, dev->io); /* Set the volume, high bit. */ +- outb_p(vol % 2, dev->io + 2); /* Set the volume, low bit. */ +- mutex_unlock(&dev->lock); ++ struct typhoon *ty = kzalloc(sizeof(*ty), GFP_KERNEL); ++ ++ return ty ? &ty->isa : NULL; + } + +-static int typhoon_setfreq_generic(struct typhoon *dev, +- unsigned long frequency) ++static int typhoon_s_frequency(struct radio_isa_card *isa, u32 freq) + { + unsigned long outval; + unsigned long x; +@@ -105,302 +95,86 @@ static int typhoon_setfreq_generic(struc + * + */ + +- mutex_lock(&dev->lock); +- x = frequency / 160; ++ x = freq / 160; + outval = (x * x + 2500) / 5000; + outval = (outval * x + 5000) / 10000; + outval -= (10 * x * x + 10433) / 20866; + outval += 4 * x - 11505; + +- outb_p((outval >> 8) & 0x01, dev->io + 4); +- outb_p(outval >> 9, dev->io + 6); +- outb_p(outval & 0xff, dev->io + 8); +- mutex_unlock(&dev->lock); +- +- return 0; +-} +- +-static int typhoon_setfreq(struct typhoon *dev, unsigned long frequency) +-{ +- typhoon_setfreq_generic(dev, frequency); +- dev->curfreq = frequency; +- return 0; +-} +- +-static void typhoon_mute(struct typhoon *dev) +-{ +- if (dev->muted == 1) +- return; +- typhoon_setvol_generic(dev, 0); +- typhoon_setfreq_generic(dev, dev->mutefreq); +- dev->muted = 1; +-} +- +-static void typhoon_unmute(struct typhoon *dev) +-{ +- if (dev->muted == 0) +- return; +- typhoon_setfreq_generic(dev, dev->curfreq); +- typhoon_setvol_generic(dev, dev->curvol); +- dev->muted = 0; +-} +- +-static int typhoon_setvol(struct typhoon *dev, int vol) +-{ +- if (dev->muted && vol != 0) { /* user is unmuting the card */ +- dev->curvol = vol; +- typhoon_unmute(dev); +- return 0; +- } +- if (vol == dev->curvol) /* requested volume == current */ +- return 0; +- +- if (vol == 0) { /* volume == 0 means mute the card */ +- typhoon_mute(dev); +- dev->curvol = vol; +- return 0; +- } +- typhoon_setvol_generic(dev, vol); +- dev->curvol = vol; +- return 0; +-} +- +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- strlcpy(v->driver, "radio-typhoon", sizeof(v->driver)); +- strlcpy(v->card, "Typhoon Radio", sizeof(v->card)); +- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; +- return 0; +-} +- +-static int vidioc_g_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- if (v->index > 0) +- return -EINVAL; +- +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- v->rangelow = 87.5 * 16000; +- v->rangehigh = 108 * 16000; +- v->rxsubchans = V4L2_TUNER_SUB_MONO; +- v->capability = V4L2_TUNER_CAP_LOW; +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->signal = 0xFFFF; /* We can't get the signal strength */ ++ outb_p((outval >> 8) & 0x01, isa->io + 4); ++ outb_p(outval >> 9, isa->io + 6); ++ outb_p(outval & 0xff, isa->io + 8); + return 0; + } + +-static int vidioc_s_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- return v->index ? -EINVAL : 0; +-} +- +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) ++static int typhoon_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) + { +- struct typhoon *dev = video_drvdata(file); ++ struct typhoon *ty = container_of(isa, struct typhoon, isa); + +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = dev->curfreq; +- return 0; +-} +- +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct typhoon *dev = video_drvdata(file); +- +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- dev->curfreq = f->frequency; +- typhoon_setfreq(dev, dev->curfreq); +- return 0; +-} +- +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- switch (qc->id) { +- case V4L2_CID_AUDIO_MUTE: +- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); +- case V4L2_CID_AUDIO_VOLUME: +- return v4l2_ctrl_query_fill(qc, 0, 65535, 16384, 65535); +- } +- return -EINVAL; +-} +- +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct typhoon *dev = video_drvdata(file); ++ if (mute) ++ vol = 0; ++ vol >>= 14; /* Map 16 bit to 2 bit */ ++ vol &= 3; ++ outb_p(vol / 2, isa->io); /* Set the volume, high bit. */ ++ outb_p(vol % 2, isa->io + 2); /* Set the volume, low bit. */ + +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- ctrl->value = dev->muted; +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- ctrl->value = dev->curvol; +- return 0; ++ if (vol == 0 && !ty->muted) { ++ ty->muted = true; ++ return typhoon_s_frequency(isa, mutefreq << 4); + } +- return -EINVAL; +-} +- +-static int vidioc_s_ctrl (struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct typhoon *dev = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (ctrl->value) +- typhoon_mute(dev); +- else +- typhoon_unmute(dev); +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- typhoon_setvol(dev, ctrl->value); +- return 0; ++ if (vol && ty->muted) { ++ ty->muted = false; ++ return typhoon_s_frequency(isa, isa->freq); + } +- return -EINVAL; +-} +- +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; + return 0; + } + +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +-{ +- return i ? -EINVAL : 0; +-} +- +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; +-} +- +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- return a->index ? -EINVAL : 0; +-} +- +-static int vidioc_log_status(struct file *file, void *priv) +-{ +- struct typhoon *dev = video_drvdata(file); +- struct v4l2_device *v4l2_dev = &dev->v4l2_dev; +- +- v4l2_info(v4l2_dev, BANNER); +-#ifdef MODULE +- v4l2_info(v4l2_dev, "Load type: Driver loaded as a module\n\n"); +-#else +- v4l2_info(v4l2_dev, "Load type: Driver compiled into kernel\n\n"); +-#endif +- v4l2_info(v4l2_dev, "frequency = %lu kHz\n", dev->curfreq >> 4); +- v4l2_info(v4l2_dev, "volume = %d\n", dev->curvol); +- v4l2_info(v4l2_dev, "mute = %s\n", dev->muted ? "on" : "off"); +- v4l2_info(v4l2_dev, "io = 0x%x\n", dev->io); +- v4l2_info(v4l2_dev, "mute frequency = %lu kHz\n", dev->mutefreq >> 4); +- return 0; +-} +- +-static const struct v4l2_file_operations typhoon_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, ++static const struct radio_isa_ops typhoon_ops = { ++ .alloc = typhoon_alloc, ++ .s_mute_volume = typhoon_s_mute_volume, ++ .s_frequency = typhoon_s_frequency, + }; + +-static const struct v4l2_ioctl_ops typhoon_ioctl_ops = { +- .vidioc_log_status = vidioc_log_status, +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl, ++static const int typhoon_ioports[] = { 0x316, 0x336 }; ++ ++static struct radio_isa_driver typhoon_driver = { ++ .driver = { ++ .match = radio_isa_match, ++ .probe = radio_isa_probe, ++ .remove = radio_isa_remove, ++ .driver = { ++ .name = "radio-typhoon", ++ }, ++ }, ++ .io_params = io, ++ .radio_nr_params = radio_nr, ++ .io_ports = typhoon_ioports, ++ .num_of_io_ports = ARRAY_SIZE(typhoon_ioports), ++ .region_size = 8, ++ .card = "Typhoon Radio", ++ .ops = &typhoon_ops, ++ .has_stereo = true, ++ .max_volume = 3, + }; + + static int __init typhoon_init(void) + { +- struct typhoon *dev = &typhoon_card; +- struct v4l2_device *v4l2_dev = &dev->v4l2_dev; +- int res; +- +- strlcpy(v4l2_dev->name, "typhoon", sizeof(v4l2_dev->name)); +- dev->io = io; +- +- if (dev->io == -1) { +- v4l2_err(v4l2_dev, "You must set an I/O address with io=0x316 or io=0x336\n"); +- return -EINVAL; +- } +- +- if (mutefreq < 87000 || mutefreq > 108500) { +- v4l2_err(v4l2_dev, "You must set a frequency (in kHz) used when muting the card,\n"); +- v4l2_err(v4l2_dev, "e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n"); +- return -EINVAL; ++ if (mutefreq < 87000 || mutefreq > 108000) { ++ printk(KERN_ERR "%s: You must set a frequency (in kHz) used when muting the card,\n", ++ typhoon_driver.driver.driver.name); ++ printk(KERN_ERR "%s: e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108000)\n", ++ typhoon_driver.driver.driver.name); ++ return -ENODEV; + } +- dev->curfreq = dev->mutefreq = mutefreq << 4; +- +- mutex_init(&dev->lock); +- if (!request_region(dev->io, 8, "typhoon")) { +- v4l2_err(v4l2_dev, "port 0x%x already in use\n", +- dev->io); +- return -EBUSY; +- } +- +- res = v4l2_device_register(NULL, v4l2_dev); +- if (res < 0) { +- release_region(dev->io, 8); +- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); +- return res; +- } +- v4l2_info(v4l2_dev, BANNER); +- +- strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); +- dev->vdev.v4l2_dev = v4l2_dev; +- dev->vdev.fops = &typhoon_fops; +- dev->vdev.ioctl_ops = &typhoon_ioctl_ops; +- dev->vdev.release = video_device_release_empty; +- video_set_drvdata(&dev->vdev, dev); +- +- /* mute card - prevents noisy bootups */ +- typhoon_mute(dev); +- +- if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_device_unregister(&dev->v4l2_dev); +- release_region(dev->io, 8); +- return -EINVAL; +- } +- v4l2_info(v4l2_dev, "port 0x%x.\n", dev->io); +- v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", mutefreq); +- +- return 0; ++ return isa_register_driver(&typhoon_driver.driver, TYPHOON_MAX); + } + + static void __exit typhoon_exit(void) + { +- struct typhoon *dev = &typhoon_card; +- +- video_unregister_device(&dev->vdev); +- v4l2_device_unregister(&dev->v4l2_dev); +- release_region(dev->io, 8); ++ isa_unregister_driver(&typhoon_driver.driver); + } + ++ + module_init(typhoon_init); + module_exit(typhoon_exit); + +Index: linux-3.3.x86_64/drivers/media/radio/radio-zoltrix.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-zoltrix.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-zoltrix.c +@@ -1,5 +1,6 @@ +-/* zoltrix radio plus driver for Linux radio support +- * (c) 1998 C. van Schaik ++/* ++ * Zoltrix Radio Plus driver ++ * Copyright 1998 C. van Schaik + * + * BUGS + * Due to the inconsistency in reading from the signal flags +@@ -27,6 +28,14 @@ + * + * 2006-07-24 - Converted to V4L2 API + * by Mauro Carvalho Chehab ++ * ++ * Converted to the radio-isa framework by Hans Verkuil ++ * ++ * Note that this is the driver for the Zoltrix Radio Plus. ++ * This driver does not work for the Zoltrix Radio Plus 108 or the ++ * Zoltrix Radio Plus for Windows. ++ * ++ * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool. + */ + + #include /* Modules */ +@@ -36,82 +45,70 @@ + #include /* kernel radio structs */ + #include + #include /* outb, outb_p */ ++#include + #include + #include ++#include "radio-isa.h" + +-MODULE_AUTHOR("C.van Schaik"); ++MODULE_AUTHOR("C. van Schaik"); + MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION("0.0.3"); ++MODULE_VERSION("0.1.99"); + + #ifndef CONFIG_RADIO_ZOLTRIX_PORT + #define CONFIG_RADIO_ZOLTRIX_PORT -1 + #endif + +-static int io = CONFIG_RADIO_ZOLTRIX_PORT; +-static int radio_nr = -1; ++#define ZOLTRIX_MAX 2 + +-module_param(io, int, 0); +-MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)"); +-module_param(radio_nr, int, 0); ++static int io[ZOLTRIX_MAX] = { [0] = CONFIG_RADIO_ZOLTRIX_PORT, ++ [1 ... (ZOLTRIX_MAX - 1)] = -1 }; ++static int radio_nr[ZOLTRIX_MAX] = { [0 ... (ZOLTRIX_MAX - 1)] = -1 }; ++ ++module_param_array(io, int, NULL, 0444); ++MODULE_PARM_DESC(io, "I/O addresses of the Zoltrix Radio Plus card (0x20c or 0x30c)"); ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); + + struct zoltrix { +- struct v4l2_device v4l2_dev; +- struct video_device vdev; +- int io; ++ struct radio_isa_card isa; + int curvol; +- unsigned long curfreq; +- int muted; +- unsigned int stereo; +- struct mutex lock; ++ bool muted; + }; + +-static struct zoltrix zoltrix_card; ++static struct radio_isa_card *zoltrix_alloc(void) ++{ ++ struct zoltrix *zol = kzalloc(sizeof(*zol), GFP_KERNEL); + +-static int zol_setvol(struct zoltrix *zol, int vol) ++ return zol ? &zol->isa : NULL; ++} ++ ++static int zoltrix_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) + { +- zol->curvol = vol; +- if (zol->muted) +- return 0; ++ struct zoltrix *zol = container_of(isa, struct zoltrix, isa); + +- mutex_lock(&zol->lock); +- if (vol == 0) { +- outb(0, zol->io); +- outb(0, zol->io); +- inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ +- mutex_unlock(&zol->lock); ++ zol->curvol = vol; ++ zol->muted = mute; ++ if (mute || vol == 0) { ++ outb(0, isa->io); ++ outb(0, isa->io); ++ inb(isa->io + 3); /* Zoltrix needs to be read to confirm */ + return 0; + } + +- outb(zol->curvol-1, zol->io); ++ outb(vol - 1, isa->io); + msleep(10); +- inb(zol->io + 2); +- mutex_unlock(&zol->lock); ++ inb(isa->io + 2); + return 0; + } + +-static void zol_mute(struct zoltrix *zol) +-{ +- zol->muted = 1; +- mutex_lock(&zol->lock); +- outb(0, zol->io); +- outb(0, zol->io); +- inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ +- mutex_unlock(&zol->lock); +-} +- +-static void zol_unmute(struct zoltrix *zol) +-{ +- zol->muted = 0; +- zol_setvol(zol, zol->curvol); +-} +- +-static int zol_setfreq(struct zoltrix *zol, unsigned long freq) ++/* tunes the radio to the desired frequency */ ++static int zoltrix_s_frequency(struct radio_isa_card *isa, u32 freq) + { +- /* tunes the radio to the desired frequency */ +- struct v4l2_device *v4l2_dev = &zol->v4l2_dev; ++ struct zoltrix *zol = container_of(isa, struct zoltrix, isa); ++ struct v4l2_device *v4l2_dev = &isa->v4l2_dev; + unsigned long long bitmask, f, m; +- unsigned int stereo = zol->stereo; ++ bool stereo = isa->stereo; + int i; + + if (freq == 0) { +@@ -125,340 +122,125 @@ static int zol_setfreq(struct zoltrix *z + bitmask = 0xc480402c10080000ull; + i = 45; + +- mutex_lock(&zol->lock); +- +- zol->curfreq = freq; ++ outb(0, isa->io); ++ outb(0, isa->io); ++ inb(isa->io + 3); /* Zoltrix needs to be read to confirm */ + +- outb(0, zol->io); +- outb(0, zol->io); +- inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ +- +- outb(0x40, zol->io); +- outb(0xc0, zol->io); ++ outb(0x40, isa->io); ++ outb(0xc0, isa->io); + + bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ (stereo << 31)); + while (i--) { + if ((bitmask & 0x8000000000000000ull) != 0) { +- outb(0x80, zol->io); ++ outb(0x80, isa->io); + udelay(50); +- outb(0x00, zol->io); ++ outb(0x00, isa->io); + udelay(50); +- outb(0x80, zol->io); ++ outb(0x80, isa->io); + udelay(50); + } else { +- outb(0xc0, zol->io); ++ outb(0xc0, isa->io); + udelay(50); +- outb(0x40, zol->io); ++ outb(0x40, isa->io); + udelay(50); +- outb(0xc0, zol->io); ++ outb(0xc0, isa->io); + udelay(50); + } + bitmask *= 2; + } + /* termination sequence */ +- outb(0x80, zol->io); +- outb(0xc0, zol->io); +- outb(0x40, zol->io); ++ outb(0x80, isa->io); ++ outb(0xc0, isa->io); ++ outb(0x40, isa->io); + udelay(1000); +- inb(zol->io + 2); +- ++ inb(isa->io + 2); + udelay(1000); + +- if (zol->muted) { +- outb(0, zol->io); +- outb(0, zol->io); +- inb(zol->io + 3); +- udelay(1000); +- } +- +- mutex_unlock(&zol->lock); +- +- if (!zol->muted) +- zol_setvol(zol, zol->curvol); +- return 0; ++ return zoltrix_s_mute_volume(isa, zol->muted, zol->curvol); + } + + /* Get signal strength */ +-static int zol_getsigstr(struct zoltrix *zol) ++static u32 zoltrix_g_rxsubchans(struct radio_isa_card *isa) + { ++ struct zoltrix *zol = container_of(isa, struct zoltrix, isa); + int a, b; + +- mutex_lock(&zol->lock); +- outb(0x00, zol->io); /* This stuff I found to do nothing */ +- outb(zol->curvol, zol->io); ++ outb(0x00, isa->io); /* This stuff I found to do nothing */ ++ outb(zol->curvol, isa->io); + msleep(20); + +- a = inb(zol->io); ++ a = inb(isa->io); + msleep(10); +- b = inb(zol->io); +- +- mutex_unlock(&zol->lock); ++ b = inb(isa->io); + +- if (a != b) +- return 0; +- +- /* I found this out by playing with a binary scanner on the card io */ +- return a == 0xcf || a == 0xdf || a == 0xef; ++ return (a == b && a == 0xcf) ? ++ V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; + } + +-static int zol_is_stereo(struct zoltrix *zol) ++static u32 zoltrix_g_signal(struct radio_isa_card *isa) + { +- int x1, x2; +- +- mutex_lock(&zol->lock); ++ struct zoltrix *zol = container_of(isa, struct zoltrix, isa); ++ int a, b; + +- outb(0x00, zol->io); +- outb(zol->curvol, zol->io); ++ outb(0x00, isa->io); /* This stuff I found to do nothing */ ++ outb(zol->curvol, isa->io); + msleep(20); + +- x1 = inb(zol->io); ++ a = inb(isa->io); + msleep(10); +- x2 = inb(zol->io); +- +- mutex_unlock(&zol->lock); +- +- return x1 == x2 && x1 == 0xcf; +-} +- +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- strlcpy(v->driver, "radio-zoltrix", sizeof(v->driver)); +- strlcpy(v->card, "Zoltrix Radio", sizeof(v->card)); +- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; +- return 0; +-} +- +-static int vidioc_g_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- struct zoltrix *zol = video_drvdata(file); +- +- if (v->index > 0) +- return -EINVAL; +- +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- v->rangelow = 88 * 16000; +- v->rangehigh = 108 * 16000; +- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; +- v->capability = V4L2_TUNER_CAP_LOW; +- if (zol_is_stereo(zol)) +- v->audmode = V4L2_TUNER_MODE_STEREO; +- else +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->signal = 0xFFFF * zol_getsigstr(zol); +- return 0; +-} +- +-static int vidioc_s_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- return v->index ? -EINVAL : 0; +-} +- +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct zoltrix *zol = video_drvdata(file); +- +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- if (zol_setfreq(zol, f->frequency) != 0) +- return -EINVAL; +- return 0; +-} +- +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct zoltrix *zol = video_drvdata(file); +- +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = zol->curfreq; +- return 0; +-} +- +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- switch (qc->id) { +- case V4L2_CID_AUDIO_MUTE: +- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); +- case V4L2_CID_AUDIO_VOLUME: +- return v4l2_ctrl_query_fill(qc, 0, 65535, 4096, 65535); +- } +- return -EINVAL; +-} +- +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct zoltrix *zol = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- ctrl->value = zol->muted; +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- ctrl->value = zol->curvol * 4096; +- return 0; +- } +- return -EINVAL; +-} ++ b = inb(isa->io); + +-static int vidioc_s_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct zoltrix *zol = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (ctrl->value) +- zol_mute(zol); +- else { +- zol_unmute(zol); +- zol_setvol(zol, zol->curvol); +- } +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- zol_setvol(zol, ctrl->value / 4096); ++ if (a != b) + return 0; +- } +- zol->stereo = 1; +- if (zol_setfreq(zol, zol->curfreq) != 0) +- return -EINVAL; +-#if 0 +-/* FIXME: Implement stereo/mono switch on V4L2 */ +- if (v->mode & VIDEO_SOUND_STEREO) { +- zol->stereo = 1; +- zol_setfreq(zol, zol->curfreq); +- } +- if (v->mode & VIDEO_SOUND_MONO) { +- zol->stereo = 0; +- zol_setfreq(zol, zol->curfreq); +- } +-#endif +- return -EINVAL; +-} +- +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; +- return 0; +-} +- +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +-{ +- return i ? -EINVAL : 0; +-} + +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; ++ /* I found this out by playing with a binary scanner on the card io */ ++ return (a == 0xcf || a == 0xdf || a == 0xef) ? 0xffff : 0; + } + +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) ++static int zoltrix_s_stereo(struct radio_isa_card *isa, bool stereo) + { +- return a->index ? -EINVAL : 0; ++ return zoltrix_s_frequency(isa, isa->freq); + } + +-static const struct v4l2_file_operations zoltrix_fops = +-{ +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, ++static const struct radio_isa_ops zoltrix_ops = { ++ .alloc = zoltrix_alloc, ++ .s_mute_volume = zoltrix_s_mute_volume, ++ .s_frequency = zoltrix_s_frequency, ++ .s_stereo = zoltrix_s_stereo, ++ .g_rxsubchans = zoltrix_g_rxsubchans, ++ .g_signal = zoltrix_g_signal, + }; + +-static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = { +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl, ++static const int zoltrix_ioports[] = { 0x20c, 0x30c }; ++ ++static struct radio_isa_driver zoltrix_driver = { ++ .driver = { ++ .match = radio_isa_match, ++ .probe = radio_isa_probe, ++ .remove = radio_isa_remove, ++ .driver = { ++ .name = "radio-zoltrix", ++ }, ++ }, ++ .io_params = io, ++ .radio_nr_params = radio_nr, ++ .io_ports = zoltrix_ioports, ++ .num_of_io_ports = ARRAY_SIZE(zoltrix_ioports), ++ .region_size = 2, ++ .card = "Zoltrix Radio Plus", ++ .ops = &zoltrix_ops, ++ .has_stereo = true, ++ .max_volume = 15, + }; + + static int __init zoltrix_init(void) + { +- struct zoltrix *zol = &zoltrix_card; +- struct v4l2_device *v4l2_dev = &zol->v4l2_dev; +- int res; +- +- strlcpy(v4l2_dev->name, "zoltrix", sizeof(v4l2_dev->name)); +- zol->io = io; +- if (zol->io == -1) { +- v4l2_err(v4l2_dev, "You must set an I/O address with io=0x20c or 0x30c\n"); +- return -EINVAL; +- } +- if (zol->io != 0x20c && zol->io != 0x30c) { +- v4l2_err(v4l2_dev, "invalid port, try 0x20c or 0x30c\n"); +- return -ENXIO; +- } +- +- if (!request_region(zol->io, 2, "zoltrix")) { +- v4l2_err(v4l2_dev, "port 0x%x already in use\n", zol->io); +- return -EBUSY; +- } +- +- res = v4l2_device_register(NULL, v4l2_dev); +- if (res < 0) { +- release_region(zol->io, 2); +- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); +- return res; +- } +- +- mutex_init(&zol->lock); +- +- /* mute card - prevents noisy bootups */ +- +- /* this ensures that the volume is all the way down */ +- +- outb(0, zol->io); +- outb(0, zol->io); +- msleep(20); +- inb(zol->io + 3); +- +- zol->curvol = 0; +- zol->stereo = 1; +- +- strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name)); +- zol->vdev.v4l2_dev = v4l2_dev; +- zol->vdev.fops = &zoltrix_fops; +- zol->vdev.ioctl_ops = &zoltrix_ioctl_ops; +- zol->vdev.release = video_device_release_empty; +- video_set_drvdata(&zol->vdev, zol); +- +- if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_device_unregister(v4l2_dev); +- release_region(zol->io, 2); +- return -EINVAL; +- } +- v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n"); +- +- return 0; ++ return isa_register_driver(&zoltrix_driver.driver, ZOLTRIX_MAX); + } + + static void __exit zoltrix_exit(void) + { +- struct zoltrix *zol = &zoltrix_card; +- +- video_unregister_device(&zol->vdev); +- v4l2_device_unregister(&zol->v4l2_dev); +- release_region(zol->io, 2); ++ isa_unregister_driver(&zoltrix_driver.driver); + } + + module_init(zoltrix_init); +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-core/dvb_frontend.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-core/dvb_frontend.c ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-core/dvb_frontend.c +@@ -143,10 +143,12 @@ struct dvb_frontend_private { + static void dvb_frontend_wakeup(struct dvb_frontend *fe); + static int dtv_get_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p_out); ++static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, ++ struct dvb_frontend_parameters *p); + + static bool has_get_frontend(struct dvb_frontend *fe) + { +- return fe->ops.get_frontend; ++ return fe->ops.get_frontend != NULL; + } + + /* +@@ -655,6 +657,8 @@ restart: + dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); + re_tune = true; + fepriv->state = FESTATE_TUNED; ++ } else { ++ re_tune = false; + } + + if (fe->ops.tune) +@@ -695,6 +699,7 @@ restart: + fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; + fepriv->delay = HZ / 2; + } ++ dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); + fe->ops.read_status(fe, &s); + if (s != fepriv->status) { + dvb_frontend_add_event(fe, s); /* update event list */ +@@ -1831,6 +1836,13 @@ static int dtv_set_frontend(struct dvb_f + return -EINVAL; + + /* ++ * Initialize output parameters to match the values given by ++ * the user. FE_SET_FRONTEND triggers an initial frontend event ++ * with status = 0, which copies output parameters to userspace. ++ */ ++ dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); ++ ++ /* + * Be sure that the bandwidth will be filled for all + * non-satellite systems, as tuners need to know what + * low pass/Nyquist half filter should be applied, in +Index: linux-3.3.x86_64/drivers/media/common/tuners/xc5000.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/common/tuners/xc5000.c ++++ linux-3.3.x86_64/drivers/media/common/tuners/xc5000.c +@@ -49,9 +49,6 @@ static LIST_HEAD(hybrid_tuner_instance_l + #define dprintk(level, fmt, arg...) if (debug >= level) \ + printk(KERN_INFO "%s: " fmt, "xc5000", ## arg) + +-#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.6.114.fw" +-#define XC5000_DEFAULT_FIRMWARE_SIZE 12401 +- + struct xc5000_priv { + struct tuner_i2c_props i2c_props; + struct list_head hybrid_tuner_instance_list; +@@ -62,6 +59,8 @@ struct xc5000_priv { + u8 video_standard; + u8 rf_mode; + u8 radio_input; ++ ++ int chip_id; + }; + + /* Misc Defines */ +@@ -204,6 +203,33 @@ static struct XC_TV_STANDARD XC5000_Stan + {"FM Radio-INPUT1_MONO", 0x0278, 0x9002} + }; + ++ ++struct xc5000_fw_cfg { ++ char *name; ++ u16 size; ++}; ++ ++static const struct xc5000_fw_cfg xc5000a_1_6_114 = { ++ .name = "dvb-fe-xc5000-1.6.114.fw", ++ .size = 12401, ++}; ++ ++static const struct xc5000_fw_cfg xc5000c_41_024_5_31875 = { ++ .name = "dvb-fe-xc5000c-41.024.5-31875.fw", ++ .size = 16503, ++}; ++ ++static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id) ++{ ++ switch (chip_id) { ++ default: ++ case XC5000A: ++ return &xc5000a_1_6_114; ++ case XC5000C: ++ return &xc5000c_41_024_5_31875; ++ } ++} ++ + static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe); + static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); + static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val); +@@ -552,12 +578,14 @@ static int xc5000_fwupload(struct dvb_fr + struct xc5000_priv *priv = fe->tuner_priv; + const struct firmware *fw; + int ret; ++ const struct xc5000_fw_cfg *desired_fw = ++ xc5000_assign_firmware(priv->chip_id); + + /* request the firmware, this will block and timeout */ + printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", +- XC5000_DEFAULT_FIRMWARE); ++ desired_fw->name); + +- ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, ++ ret = request_firmware(&fw, desired_fw->name, + priv->i2c_props.adap->dev.parent); + if (ret) { + printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); +@@ -569,7 +597,7 @@ static int xc5000_fwupload(struct dvb_fr + ret = XC_RESULT_SUCCESS; + } + +- if (fw->size != XC5000_DEFAULT_FIRMWARE_SIZE) { ++ if (fw->size != desired_fw->size) { + printk(KERN_ERR "xc5000: firmware incorrect size\n"); + ret = XC_RESULT_RESET_FAILURE; + } else { +@@ -1139,6 +1167,13 @@ struct dvb_frontend *xc5000_attach(struc + if (priv->radio_input == 0) + priv->radio_input = cfg->radio_input; + ++ /* don't override chip id if it's already been set ++ unless explicitly specified */ ++ if ((priv->chip_id == 0) || (cfg->chip_id)) ++ /* use default chip id if none specified, set to 0 so ++ it can be overridden if this is a hybrid driver */ ++ priv->chip_id = (cfg->chip_id) ? cfg->chip_id : 0; ++ + /* Check if firmware has been loaded. It is possible that another + instance of the driver has loaded the firmware. + */ +Index: linux-3.3.x86_64/drivers/media/common/tuners/xc5000.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/common/tuners/xc5000.h ++++ linux-3.3.x86_64/drivers/media/common/tuners/xc5000.h +@@ -27,10 +27,15 @@ + struct dvb_frontend; + struct i2c_adapter; + ++#define XC5000A 1 ++#define XC5000C 2 ++ + struct xc5000_config { + u8 i2c_address; + u32 if_khz; + u8 radio_input; ++ ++ int chip_id; + }; + + /* xc5000 callback command */ +Index: linux-3.3.x86_64/drivers/media/common/tuners/tuner-types.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/common/tuners/tuner-types.c ++++ linux-3.3.x86_64/drivers/media/common/tuners/tuner-types.c +@@ -1868,6 +1868,10 @@ struct tunertype tuners[] = { + .params = tuner_tena_tnf_5337_params, + .count = ARRAY_SIZE(tuner_tena_tnf_5337_params), + }, ++ [TUNER_XC5000C] = { /* Xceive 5000C */ ++ .name = "Xceive 5000C tuner", ++ /* see xc5000.c for details */ ++ }, + }; + EXPORT_SYMBOL(tuners); + +Index: linux-3.3.x86_64/drivers/media/video/tuner-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tuner-core.c ++++ linux-3.3.x86_64/drivers/media/video/tuner-core.c +@@ -380,6 +380,21 @@ static void set_type(struct i2c_client * + tune_now = 0; + break; + } ++ case TUNER_XC5000C: ++ { ++ struct xc5000_config xc5000c_cfg = { ++ .i2c_address = t->i2c->addr, ++ /* if_khz will be set at dvb_attach() */ ++ .if_khz = 0, ++ .chip_id = XC5000C, ++ }; ++ ++ if (!dvb_attach(xc5000_attach, ++ &t->fe, t->i2c->adapter, &xc5000c_cfg)) ++ goto attach_failed; ++ tune_now = 0; ++ break; ++ } + case TUNER_NXP_TDA18271: + { + struct tda18271_config cfg = { +@@ -1314,18 +1329,7 @@ static struct i2c_driver tuner_driver = + .id_table = tuner_id, + }; + +-static __init int init_tuner(void) +-{ +- return i2c_add_driver(&tuner_driver); +-} +- +-static __exit void exit_tuner(void) +-{ +- i2c_del_driver(&tuner_driver); +-} +- +-module_init(init_tuner); +-module_exit(exit_tuner); ++module_i2c_driver(tuner_driver); + + MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners"); + MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); +Index: linux-3.3.x86_64/include/media/tuner.h +=================================================================== +--- linux-3.3.x86_64.orig/include/media/tuner.h ++++ linux-3.3.x86_64/include/media/tuner.h +@@ -136,6 +136,7 @@ + #define TUNER_TENA_TNF_5337 86 + + #define TUNER_XC4000 87 /* Xceive Silicon Tuner */ ++#define TUNER_XC5000C 88 /* Xceive Silicon Tuner */ + + /* tv card specific */ + #define TDA9887_PRESENT (1<<0) +Index: linux-3.3.x86_64/drivers/media/video/tveeprom.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tveeprom.c ++++ linux-3.3.x86_64/drivers/media/video/tveeprom.c +@@ -286,8 +286,16 @@ hauppauge_tuner[] = + { TUNER_ABSENT, "MaxLinear 301"}, + { TUNER_ABSENT, "Mirics MSi001"}, + { TUNER_ABSENT, "MaxLinear MxL241SF"}, +- { TUNER_ABSENT, "Xceive XC5000C"}, ++ { TUNER_XC5000C, "Xceive XC5000C"}, + { TUNER_ABSENT, "Montage M68TS2020"}, ++ { TUNER_ABSENT, "Siano SMS1530"}, ++ { TUNER_ABSENT, "Dibcom 7090"}, ++ { TUNER_ABSENT, "Xceive XC5200C"}, ++ { TUNER_ABSENT, "NXP 18273"}, ++ { TUNER_ABSENT, "Montage M88TS2022"}, ++ /* 180-189 */ ++ { TUNER_ABSENT, "NXP 18272M"}, ++ { TUNER_ABSENT, "NXP 18272S"}, + }; + + /* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are +Index: linux-3.3.x86_64/drivers/media/radio/radio-sf16fmr2.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-sf16fmr2.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-sf16fmr2.c +@@ -9,16 +9,23 @@ + #include + #include /* Modules */ + #include /* Initdata */ ++#include + #include /* request_region */ + #include /* outb, outb_p */ ++#include + #include + + MODULE_AUTHOR("Ondrej Zary"); + MODULE_DESCRIPTION("MediaForte SF16-FMR2 FM radio card driver"); + MODULE_LICENSE("GPL"); + ++static int radio_nr = -1; ++module_param(radio_nr, int, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device number"); ++ + struct fmr2 { + int io; ++ struct v4l2_device v4l2_dev; + struct snd_tea575x tea; + struct v4l2_ctrl *volume; + struct v4l2_ctrl *balance; +@@ -26,7 +33,6 @@ struct fmr2 { + + /* the port is hardwired so no need to support multiple cards */ + #define FMR2_PORT 0x384 +-static struct fmr2 fmr2_card; + + /* TEA575x tuner pins */ + #define STR_DATA (1 << 0) +@@ -172,7 +178,7 @@ static int fmr2_tea_ext_init(struct snd_ + fmr2->volume = v4l2_ctrl_new_std(&tea->ctrl_handler, &fmr2_ctrl_ops, V4L2_CID_AUDIO_VOLUME, 0, 68, 2, 56); + fmr2->balance = v4l2_ctrl_new_std(&tea->ctrl_handler, &fmr2_ctrl_ops, V4L2_CID_AUDIO_BALANCE, -68, 68, 2, 0); + if (tea->ctrl_handler.error) { +- printk(KERN_ERR "radio-sf16fmr2: can't initialize contrls\n"); ++ printk(KERN_ERR "radio-sf16fmr2: can't initialize controls\n"); + return tea->ctrl_handler.error; + } + } +@@ -180,26 +186,46 @@ static int fmr2_tea_ext_init(struct snd_ + return 0; + } + +-static int __init fmr2_init(void) ++static int __devinit fmr2_probe(struct device *pdev, unsigned int dev) + { +- struct fmr2 *fmr2 = &fmr2_card; ++ struct fmr2 *fmr2; ++ int err; ++ ++ fmr2 = kzalloc(sizeof(*fmr2), GFP_KERNEL); ++ if (fmr2 == NULL) ++ return -ENOMEM; + ++ strlcpy(fmr2->v4l2_dev.name, dev_name(pdev), ++ sizeof(fmr2->v4l2_dev.name)); + fmr2->io = FMR2_PORT; + +- if (!request_region(fmr2->io, 2, "SF16-FMR2")) { ++ if (!request_region(fmr2->io, 2, fmr2->v4l2_dev.name)) { + printk(KERN_ERR "radio-sf16fmr2: I/O port 0x%x already in use\n", fmr2->io); ++ kfree(fmr2); + return -EBUSY; + } + ++ dev_set_drvdata(pdev, fmr2); ++ err = v4l2_device_register(pdev, &fmr2->v4l2_dev); ++ if (err < 0) { ++ v4l2_err(&fmr2->v4l2_dev, "Could not register v4l2_device\n"); ++ release_region(fmr2->io, 2); ++ kfree(fmr2); ++ return err; ++ } ++ fmr2->tea.v4l2_dev = &fmr2->v4l2_dev; + fmr2->tea.private_data = fmr2; ++ fmr2->tea.radio_nr = radio_nr; + fmr2->tea.ops = &fmr2_tea_ops; + fmr2->tea.ext_init = fmr2_tea_ext_init; + strlcpy(fmr2->tea.card, "SF16-FMR2", sizeof(fmr2->tea.card)); +- strcpy(fmr2->tea.bus_info, "ISA"); ++ snprintf(fmr2->tea.bus_info, sizeof(fmr2->tea.bus_info), "ISA:%s", ++ fmr2->v4l2_dev.name); + + if (snd_tea575x_init(&fmr2->tea)) { + printk(KERN_ERR "radio-sf16fmr2: Unable to detect TEA575x tuner\n"); + release_region(fmr2->io, 2); ++ kfree(fmr2); + return -ENODEV; + } + +@@ -207,12 +233,33 @@ static int __init fmr2_init(void) + return 0; + } + +-static void __exit fmr2_exit(void) ++static int __exit fmr2_remove(struct device *pdev, unsigned int dev) + { +- struct fmr2 *fmr2 = &fmr2_card; ++ struct fmr2 *fmr2 = dev_get_drvdata(pdev); + + snd_tea575x_exit(&fmr2->tea); + release_region(fmr2->io, 2); ++ v4l2_device_unregister(&fmr2->v4l2_dev); ++ kfree(fmr2); ++ return 0; ++} ++ ++struct isa_driver fmr2_driver = { ++ .probe = fmr2_probe, ++ .remove = fmr2_remove, ++ .driver = { ++ .name = "radio-sf16fmr2", ++ }, ++}; ++ ++static int __init fmr2_init(void) ++{ ++ return isa_register_driver(&fmr2_driver, 1); ++} ++ ++static void __exit fmr2_exit(void) ++{ ++ isa_unregister_driver(&fmr2_driver); + } + + module_init(fmr2_init); +Index: linux-3.3.x86_64/drivers/media/video/davinci/dm355_ccdc.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/davinci/dm355_ccdc.c ++++ linux-3.3.x86_64/drivers/media/video/davinci/dm355_ccdc.c +@@ -292,7 +292,7 @@ static int validate_ccdc_param(struct cc + if ((ccdcparam->med_filt_thres < 0) || + (ccdcparam->med_filt_thres > CCDC_MED_FILT_THRESH)) { + dev_dbg(ccdc_cfg.dev, +- "Invalid value of median filter thresold\n"); ++ "Invalid value of median filter threshold\n"); + return -EINVAL; + } + +Index: linux-3.3.x86_64/drivers/media/video/Kconfig +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/Kconfig ++++ linux-3.3.x86_64/drivers/media/video/Kconfig +@@ -273,6 +273,16 @@ config VIDEO_ADV7180 + To compile this driver as a module, choose M here: the + module will be called adv7180. + ++config VIDEO_ADV7183 ++ tristate "Analog Devices ADV7183 decoder" ++ depends on VIDEO_V4L2 && I2C ++ ---help--- ++ V4l2 subdevice driver for the Analog Devices ++ ADV7183 video decoder. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called adv7183. ++ + config VIDEO_BT819 + tristate "BT819A VideoStream decoder" + depends on VIDEO_V4L2 && I2C +@@ -459,6 +469,9 @@ config VIDEO_AK881X + + comment "Camera sensor devices" + ++config VIDEO_APTINA_PLL ++ tristate ++ + config VIDEO_OV7670 + tristate "OmniVision OV7670 sensor support" + depends on I2C && VIDEO_V4L2 +@@ -467,9 +480,28 @@ config VIDEO_OV7670 + OV7670 VGA camera. It currently only works with the M88ALP01 + controller. + ++config VIDEO_VS6624 ++ tristate "ST VS6624 sensor support" ++ depends on VIDEO_V4L2 && I2C ++ ---help--- ++ This is a Video4Linux2 sensor-level driver for the ST VS6624 ++ camera. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called vs6624. ++ ++config VIDEO_MT9M032 ++ tristate "MT9M032 camera sensor support" ++ depends on I2C && VIDEO_V4L2 ++ select VIDEO_APTINA_PLL ++ ---help--- ++ This driver supports MT9M032 camera sensors from Aptina, monochrome ++ models only. ++ + config VIDEO_MT9P031 + tristate "Aptina MT9P031 support" + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API ++ select VIDEO_APTINA_PLL + ---help--- + This is a Video4Linux2 sensor-level driver for the Aptina + (Micron) mt9p031 5 Mpixel camera. +@@ -851,6 +883,8 @@ source "drivers/media/video/davinci/Kcon + + source "drivers/media/video/omap/Kconfig" + ++source "drivers/media/video/blackfin/Kconfig" ++ + config VIDEO_SH_VOU + tristate "SuperH VOU video output driver" + depends on VIDEO_DEV && ARCH_SHMOBILE +@@ -1087,7 +1121,7 @@ config VIDEO_MX2_HOSTSUPPORT + config VIDEO_MX2 + tristate "i.MX27/i.MX25 Camera Sensor Interface driver" + depends on VIDEO_DEV && SOC_CAMERA && (MACH_MX27 || ARCH_MX25) +- select VIDEOBUF_DMA_CONTIG ++ select VIDEOBUF2_DMA_CONTIG + select VIDEO_MX2_HOSTSUPPORT + ---help--- + This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor +@@ -1116,7 +1150,8 @@ config VIDEO_ATMEL_ISI + + config VIDEO_S5P_MIPI_CSIS + tristate "Samsung S5P and EXYNOS4 MIPI CSI receiver driver" +- depends on VIDEO_V4L2 && PM_RUNTIME && PLAT_S5P && VIDEO_V4L2_SUBDEV_API ++ depends on VIDEO_V4L2 && PM_RUNTIME && PLAT_S5P ++ depends on VIDEO_V4L2_SUBDEV_API && REGULATOR + ---help--- + This is a v4l2 driver for Samsung S5P/EXYNOS4 MIPI-CSI receiver. + +@@ -1176,4 +1211,14 @@ config VIDEO_SAMSUNG_S5P_MFC + help + MFC 5.1 driver for V4L2. + ++config VIDEO_MX2_EMMAPRP ++ tristate "MX2 eMMa-PrP support" ++ depends on VIDEO_DEV && VIDEO_V4L2 && SOC_IMX27 ++ select VIDEOBUF2_DMA_CONTIG ++ select V4L2_MEM2MEM_DEV ++ help ++ MX2X chips have a PrP that can be used to process buffers from ++ memory to memory. Operations include resizing and format ++ conversion. ++ + endif # V4L_MEM2MEM_DRIVERS +Index: linux-3.3.x86_64/drivers/media/video/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/Makefile ++++ linux-3.3.x86_64/drivers/media/video/Makefile +@@ -12,16 +12,19 @@ omap2cam-objs := omap24xxcam.o omap24xxc + + videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ + v4l2-event.o v4l2-ctrls.o v4l2-subdev.o ++ifeq ($(CONFIG_COMPAT),y) ++ videodev-objs += v4l2-compat-ioctl32.o ++endif + + # V4L2 core modules + + obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o +-ifeq ($(CONFIG_COMPAT),y) +- obj-$(CONFIG_VIDEO_DEV) += v4l2-compat-ioctl32.o +-endif +- + obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o + ++# Helper modules ++ ++obj-$(CONFIG_VIDEO_APTINA_PLL) += aptina-pll.o ++ + # All i2c modules must come first: + + obj-$(CONFIG_VIDEO_TUNER) += tuner.o +@@ -40,8 +43,10 @@ obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o + obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o + obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o + obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o ++obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o + obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o + obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o ++obj-$(CONFIG_VIDEO_VS6624) += vs6624.o + obj-$(CONFIG_VIDEO_BT819) += bt819.o + obj-$(CONFIG_VIDEO_BT856) += bt856.o + obj-$(CONFIG_VIDEO_BT866) += bt866.o +@@ -65,6 +70,7 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083 + obj-$(CONFIG_VIDEO_OV7670) += ov7670.o + obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o + obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o ++obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o + obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o + obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o + obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o +@@ -177,6 +183,8 @@ obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_ + obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o + obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o + ++obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o ++ + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/ + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg/ + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc/ +@@ -184,6 +192,8 @@ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV) += s5 + + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D) += s5p-g2d/ + ++obj-$(CONFIG_BLACKFIN) += blackfin/ ++ + obj-$(CONFIG_ARCH_DAVINCI) += davinci/ + + obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o +@@ -199,6 +209,6 @@ obj-y += davinci/ + + obj-$(CONFIG_ARCH_OMAP) += omap/ + +-ccflags-y += -Idrivers/media/dvb/dvb-core +-ccflags-y += -Idrivers/media/dvb/frontends +-ccflags-y += -Idrivers/media/common/tuners ++ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core ++ccflags-y += -I$(srctree)/drivers/media/dvb/frontends ++ccflags-y += -I$(srctree)/drivers/media/common/tuners +Index: linux-3.3.x86_64/drivers/media/video/mx2_emmaprp.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/mx2_emmaprp.c +@@ -0,0 +1,1008 @@ ++/* ++ * Support eMMa-PrP through mem2mem framework. ++ * ++ * eMMa-PrP is a piece of HW that allows fetching buffers ++ * from one memory location and do several operations on ++ * them such as scaling or format conversion giving, as a result ++ * a new processed buffer in another memory location. ++ * ++ * Based on mem2mem_testdev.c by Pawel Osciak. ++ * ++ * Copyright (c) 2011 Vista Silicon S.L. ++ * Javier Martin ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#define EMMAPRP_MODULE_NAME "mem2mem-emmaprp" ++ ++MODULE_DESCRIPTION("Mem-to-mem device which supports eMMa-PrP present in mx2 SoCs"); ++MODULE_AUTHOR("Javier Martin v4l2_dev, "%s: " fmt, __func__, ## arg) ++ ++/* EMMA PrP */ ++#define PRP_CNTL 0x00 ++#define PRP_INTR_CNTL 0x04 ++#define PRP_INTRSTATUS 0x08 ++#define PRP_SOURCE_Y_PTR 0x0c ++#define PRP_SOURCE_CB_PTR 0x10 ++#define PRP_SOURCE_CR_PTR 0x14 ++#define PRP_DEST_RGB1_PTR 0x18 ++#define PRP_DEST_RGB2_PTR 0x1c ++#define PRP_DEST_Y_PTR 0x20 ++#define PRP_DEST_CB_PTR 0x24 ++#define PRP_DEST_CR_PTR 0x28 ++#define PRP_SRC_FRAME_SIZE 0x2c ++#define PRP_DEST_CH1_LINE_STRIDE 0x30 ++#define PRP_SRC_PIXEL_FORMAT_CNTL 0x34 ++#define PRP_CH1_PIXEL_FORMAT_CNTL 0x38 ++#define PRP_CH1_OUT_IMAGE_SIZE 0x3c ++#define PRP_CH2_OUT_IMAGE_SIZE 0x40 ++#define PRP_SRC_LINE_STRIDE 0x44 ++#define PRP_CSC_COEF_012 0x48 ++#define PRP_CSC_COEF_345 0x4c ++#define PRP_CSC_COEF_678 0x50 ++#define PRP_CH1_RZ_HORI_COEF1 0x54 ++#define PRP_CH1_RZ_HORI_COEF2 0x58 ++#define PRP_CH1_RZ_HORI_VALID 0x5c ++#define PRP_CH1_RZ_VERT_COEF1 0x60 ++#define PRP_CH1_RZ_VERT_COEF2 0x64 ++#define PRP_CH1_RZ_VERT_VALID 0x68 ++#define PRP_CH2_RZ_HORI_COEF1 0x6c ++#define PRP_CH2_RZ_HORI_COEF2 0x70 ++#define PRP_CH2_RZ_HORI_VALID 0x74 ++#define PRP_CH2_RZ_VERT_COEF1 0x78 ++#define PRP_CH2_RZ_VERT_COEF2 0x7c ++#define PRP_CH2_RZ_VERT_VALID 0x80 ++ ++#define PRP_CNTL_CH1EN (1 << 0) ++#define PRP_CNTL_CH2EN (1 << 1) ++#define PRP_CNTL_CSIEN (1 << 2) ++#define PRP_CNTL_DATA_IN_YUV420 (0 << 3) ++#define PRP_CNTL_DATA_IN_YUV422 (1 << 3) ++#define PRP_CNTL_DATA_IN_RGB16 (2 << 3) ++#define PRP_CNTL_DATA_IN_RGB32 (3 << 3) ++#define PRP_CNTL_CH1_OUT_RGB8 (0 << 5) ++#define PRP_CNTL_CH1_OUT_RGB16 (1 << 5) ++#define PRP_CNTL_CH1_OUT_RGB32 (2 << 5) ++#define PRP_CNTL_CH1_OUT_YUV422 (3 << 5) ++#define PRP_CNTL_CH2_OUT_YUV420 (0 << 7) ++#define PRP_CNTL_CH2_OUT_YUV422 (1 << 7) ++#define PRP_CNTL_CH2_OUT_YUV444 (2 << 7) ++#define PRP_CNTL_CH1_LEN (1 << 9) ++#define PRP_CNTL_CH2_LEN (1 << 10) ++#define PRP_CNTL_SKIP_FRAME (1 << 11) ++#define PRP_CNTL_SWRST (1 << 12) ++#define PRP_CNTL_CLKEN (1 << 13) ++#define PRP_CNTL_WEN (1 << 14) ++#define PRP_CNTL_CH1BYP (1 << 15) ++#define PRP_CNTL_IN_TSKIP(x) ((x) << 16) ++#define PRP_CNTL_CH1_TSKIP(x) ((x) << 19) ++#define PRP_CNTL_CH2_TSKIP(x) ((x) << 22) ++#define PRP_CNTL_INPUT_FIFO_LEVEL(x) ((x) << 25) ++#define PRP_CNTL_RZ_FIFO_LEVEL(x) ((x) << 27) ++#define PRP_CNTL_CH2B1EN (1 << 29) ++#define PRP_CNTL_CH2B2EN (1 << 30) ++#define PRP_CNTL_CH2FEN (1 << 31) ++ ++#define PRP_SIZE_HEIGHT(x) (x) ++#define PRP_SIZE_WIDTH(x) ((x) << 16) ++ ++/* IRQ Enable and status register */ ++#define PRP_INTR_RDERR (1 << 0) ++#define PRP_INTR_CH1WERR (1 << 1) ++#define PRP_INTR_CH2WERR (1 << 2) ++#define PRP_INTR_CH1FC (1 << 3) ++#define PRP_INTR_CH2FC (1 << 5) ++#define PRP_INTR_LBOVF (1 << 7) ++#define PRP_INTR_CH2OVF (1 << 8) ++ ++#define PRP_INTR_ST_RDERR (1 << 0) ++#define PRP_INTR_ST_CH1WERR (1 << 1) ++#define PRP_INTR_ST_CH2WERR (1 << 2) ++#define PRP_INTR_ST_CH2B2CI (1 << 3) ++#define PRP_INTR_ST_CH2B1CI (1 << 4) ++#define PRP_INTR_ST_CH1B2CI (1 << 5) ++#define PRP_INTR_ST_CH1B1CI (1 << 6) ++#define PRP_INTR_ST_LBOVF (1 << 7) ++#define PRP_INTR_ST_CH2OVF (1 << 8) ++ ++struct emmaprp_fmt { ++ char *name; ++ u32 fourcc; ++ /* Types the format can be used for */ ++ u32 types; ++}; ++ ++static struct emmaprp_fmt formats[] = { ++ { ++ .name = "YUV 4:2:0 Planar", ++ .fourcc = V4L2_PIX_FMT_YUV420, ++ .types = MEM2MEM_CAPTURE, ++ }, ++ { ++ .name = "4:2:2, packed, YUYV", ++ .fourcc = V4L2_PIX_FMT_YUYV, ++ .types = MEM2MEM_OUTPUT, ++ }, ++}; ++ ++/* Per-queue, driver-specific private data */ ++struct emmaprp_q_data { ++ unsigned int width; ++ unsigned int height; ++ unsigned int sizeimage; ++ struct emmaprp_fmt *fmt; ++}; ++ ++enum { ++ V4L2_M2M_SRC = 0, ++ V4L2_M2M_DST = 1, ++}; ++ ++#define NUM_FORMATS ARRAY_SIZE(formats) ++ ++static struct emmaprp_fmt *find_format(struct v4l2_format *f) ++{ ++ struct emmaprp_fmt *fmt; ++ unsigned int k; ++ ++ for (k = 0; k < NUM_FORMATS; k++) { ++ fmt = &formats[k]; ++ if (fmt->fourcc == f->fmt.pix.pixelformat) ++ break; ++ } ++ ++ if (k == NUM_FORMATS) ++ return NULL; ++ ++ return &formats[k]; ++} ++ ++struct emmaprp_dev { ++ struct v4l2_device v4l2_dev; ++ struct video_device *vfd; ++ ++ struct mutex dev_mutex; ++ spinlock_t irqlock; ++ ++ int irq_emma; ++ void __iomem *base_emma; ++ struct clk *clk_emma; ++ struct resource *res_emma; ++ ++ struct v4l2_m2m_dev *m2m_dev; ++ struct vb2_alloc_ctx *alloc_ctx; ++}; ++ ++struct emmaprp_ctx { ++ struct emmaprp_dev *dev; ++ /* Abort requested by m2m */ ++ int aborting; ++ struct emmaprp_q_data q_data[2]; ++ struct v4l2_m2m_ctx *m2m_ctx; ++}; ++ ++static struct emmaprp_q_data *get_q_data(struct emmaprp_ctx *ctx, ++ enum v4l2_buf_type type) ++{ ++ switch (type) { ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT: ++ return &(ctx->q_data[V4L2_M2M_SRC]); ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ return &(ctx->q_data[V4L2_M2M_DST]); ++ default: ++ BUG(); ++ } ++ return NULL; ++} ++ ++/* ++ * mem2mem callbacks ++ */ ++static void emmaprp_job_abort(void *priv) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ struct emmaprp_dev *pcdev = ctx->dev; ++ ++ ctx->aborting = 1; ++ ++ dprintk(pcdev, "Aborting task\n"); ++ ++ v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->m2m_ctx); ++} ++ ++static void emmaprp_lock(void *priv) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ struct emmaprp_dev *pcdev = ctx->dev; ++ mutex_lock(&pcdev->dev_mutex); ++} ++ ++static void emmaprp_unlock(void *priv) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ struct emmaprp_dev *pcdev = ctx->dev; ++ mutex_unlock(&pcdev->dev_mutex); ++} ++ ++static inline void emmaprp_dump_regs(struct emmaprp_dev *pcdev) ++{ ++ dprintk(pcdev, ++ "eMMa-PrP Registers:\n" ++ " SOURCE_Y_PTR = 0x%08X\n" ++ " SRC_FRAME_SIZE = 0x%08X\n" ++ " DEST_Y_PTR = 0x%08X\n" ++ " DEST_CR_PTR = 0x%08X\n" ++ " DEST_CB_PTR = 0x%08X\n" ++ " CH2_OUT_IMAGE_SIZE = 0x%08X\n" ++ " CNTL = 0x%08X\n", ++ readl(pcdev->base_emma + PRP_SOURCE_Y_PTR), ++ readl(pcdev->base_emma + PRP_SRC_FRAME_SIZE), ++ readl(pcdev->base_emma + PRP_DEST_Y_PTR), ++ readl(pcdev->base_emma + PRP_DEST_CR_PTR), ++ readl(pcdev->base_emma + PRP_DEST_CB_PTR), ++ readl(pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE), ++ readl(pcdev->base_emma + PRP_CNTL)); ++} ++ ++static void emmaprp_device_run(void *priv) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ struct emmaprp_q_data *s_q_data, *d_q_data; ++ struct vb2_buffer *src_buf, *dst_buf; ++ struct emmaprp_dev *pcdev = ctx->dev; ++ unsigned int s_width, s_height; ++ unsigned int d_width, d_height; ++ unsigned int d_size; ++ dma_addr_t p_in, p_out; ++ u32 tmp; ++ ++ src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); ++ dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); ++ ++ s_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ s_width = s_q_data->width; ++ s_height = s_q_data->height; ++ ++ d_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ d_width = d_q_data->width; ++ d_height = d_q_data->height; ++ d_size = d_width * d_height; ++ ++ p_in = vb2_dma_contig_plane_dma_addr(src_buf, 0); ++ p_out = vb2_dma_contig_plane_dma_addr(dst_buf, 0); ++ if (!p_in || !p_out) { ++ v4l2_err(&pcdev->v4l2_dev, ++ "Acquiring kernel pointers to buffers failed\n"); ++ return; ++ } ++ ++ /* Input frame parameters */ ++ writel(p_in, pcdev->base_emma + PRP_SOURCE_Y_PTR); ++ writel(PRP_SIZE_WIDTH(s_width) | PRP_SIZE_HEIGHT(s_height), ++ pcdev->base_emma + PRP_SRC_FRAME_SIZE); ++ ++ /* Output frame parameters */ ++ writel(p_out, pcdev->base_emma + PRP_DEST_Y_PTR); ++ writel(p_out + d_size, pcdev->base_emma + PRP_DEST_CB_PTR); ++ writel(p_out + d_size + (d_size >> 2), ++ pcdev->base_emma + PRP_DEST_CR_PTR); ++ writel(PRP_SIZE_WIDTH(d_width) | PRP_SIZE_HEIGHT(d_height), ++ pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); ++ ++ /* IRQ configuration */ ++ tmp = readl(pcdev->base_emma + PRP_INTR_CNTL); ++ writel(tmp | PRP_INTR_RDERR | ++ PRP_INTR_CH2WERR | ++ PRP_INTR_CH2FC, ++ pcdev->base_emma + PRP_INTR_CNTL); ++ ++ emmaprp_dump_regs(pcdev); ++ ++ /* Enable transfer */ ++ tmp = readl(pcdev->base_emma + PRP_CNTL); ++ writel(tmp | PRP_CNTL_CH2_OUT_YUV420 | ++ PRP_CNTL_DATA_IN_YUV422 | ++ PRP_CNTL_CH2EN, ++ pcdev->base_emma + PRP_CNTL); ++} ++ ++static irqreturn_t emmaprp_irq(int irq_emma, void *data) ++{ ++ struct emmaprp_dev *pcdev = data; ++ struct emmaprp_ctx *curr_ctx; ++ struct vb2_buffer *src_vb, *dst_vb; ++ unsigned long flags; ++ u32 irqst; ++ ++ /* Check irq flags and clear irq */ ++ irqst = readl(pcdev->base_emma + PRP_INTRSTATUS); ++ writel(irqst, pcdev->base_emma + PRP_INTRSTATUS); ++ dprintk(pcdev, "irqst = 0x%08x\n", irqst); ++ ++ curr_ctx = v4l2_m2m_get_curr_priv(pcdev->m2m_dev); ++ if (curr_ctx == NULL) { ++ pr_err("Instance released before the end of transaction\n"); ++ return IRQ_HANDLED; ++ } ++ ++ if (!curr_ctx->aborting) { ++ if ((irqst & PRP_INTR_ST_RDERR) || ++ (irqst & PRP_INTR_ST_CH2WERR)) { ++ pr_err("PrP bus error ocurred, this transfer is probably corrupted\n"); ++ writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL); ++ } else if (irqst & PRP_INTR_ST_CH2B1CI) { /* buffer ready */ ++ src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); ++ dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx); ++ ++ spin_lock_irqsave(&pcdev->irqlock, flags); ++ v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE); ++ v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE); ++ spin_unlock_irqrestore(&pcdev->irqlock, flags); ++ } ++ } ++ ++ v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->m2m_ctx); ++ return IRQ_HANDLED; ++} ++ ++/* ++ * video ioctls ++ */ ++static int vidioc_querycap(struct file *file, void *priv, ++ struct v4l2_capability *cap) ++{ ++ strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1); ++ strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); ++ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT ++ | V4L2_CAP_STREAMING; ++ ++ return 0; ++} ++ ++static int enum_fmt(struct v4l2_fmtdesc *f, u32 type) ++{ ++ int i, num; ++ struct emmaprp_fmt *fmt; ++ ++ num = 0; ++ ++ for (i = 0; i < NUM_FORMATS; ++i) { ++ if (formats[i].types & type) { ++ /* index-th format of type type found ? */ ++ if (num == f->index) ++ break; ++ /* Correct type but haven't reached our index yet, ++ * just increment per-type index */ ++ ++num; ++ } ++ } ++ ++ if (i < NUM_FORMATS) { ++ /* Format found */ ++ fmt = &formats[i]; ++ strlcpy(f->description, fmt->name, sizeof(f->description) - 1); ++ f->pixelformat = fmt->fourcc; ++ return 0; ++ } ++ ++ /* Format not found */ ++ return -EINVAL; ++} ++ ++static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_fmtdesc *f) ++{ ++ return enum_fmt(f, MEM2MEM_CAPTURE); ++} ++ ++static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, ++ struct v4l2_fmtdesc *f) ++{ ++ return enum_fmt(f, MEM2MEM_OUTPUT); ++} ++ ++static int vidioc_g_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f) ++{ ++ struct vb2_queue *vq; ++ struct emmaprp_q_data *q_data; ++ ++ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); ++ if (!vq) ++ return -EINVAL; ++ ++ q_data = get_q_data(ctx, f->type); ++ ++ f->fmt.pix.width = q_data->width; ++ f->fmt.pix.height = q_data->height; ++ f->fmt.pix.field = V4L2_FIELD_NONE; ++ f->fmt.pix.pixelformat = q_data->fmt->fourcc; ++ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) ++ f->fmt.pix.bytesperline = q_data->width * 3 / 2; ++ else /* YUYV */ ++ f->fmt.pix.bytesperline = q_data->width * 2; ++ f->fmt.pix.sizeimage = q_data->sizeimage; ++ ++ return 0; ++} ++ ++static int vidioc_g_fmt_vid_out(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ return vidioc_g_fmt(priv, f); ++} ++ ++static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ return vidioc_g_fmt(priv, f); ++} ++ ++static int vidioc_try_fmt(struct v4l2_format *f) ++{ ++ enum v4l2_field field; ++ ++ ++ if (!find_format(f)) ++ return -EINVAL; ++ ++ field = f->fmt.pix.field; ++ if (field == V4L2_FIELD_ANY) ++ field = V4L2_FIELD_NONE; ++ else if (V4L2_FIELD_NONE != field) ++ return -EINVAL; ++ ++ /* V4L2 specification suggests the driver corrects the format struct ++ * if any of the dimensions is unsupported */ ++ f->fmt.pix.field = field; ++ ++ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) { ++ v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, ++ W_ALIGN_YUV420, &f->fmt.pix.height, ++ MIN_H, MAX_H, H_ALIGN, S_ALIGN); ++ f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2; ++ } else { ++ v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, ++ W_ALIGN_OTHERS, &f->fmt.pix.height, ++ MIN_H, MAX_H, H_ALIGN, S_ALIGN); ++ f->fmt.pix.bytesperline = f->fmt.pix.width * 2; ++ } ++ f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; ++ ++ return 0; ++} ++ ++static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct emmaprp_fmt *fmt; ++ struct emmaprp_ctx *ctx = priv; ++ ++ fmt = find_format(f); ++ if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) { ++ v4l2_err(&ctx->dev->v4l2_dev, ++ "Fourcc format (0x%08x) invalid.\n", ++ f->fmt.pix.pixelformat); ++ return -EINVAL; ++ } ++ ++ return vidioc_try_fmt(f); ++} ++ ++static int vidioc_try_fmt_vid_out(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct emmaprp_fmt *fmt; ++ struct emmaprp_ctx *ctx = priv; ++ ++ fmt = find_format(f); ++ if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) { ++ v4l2_err(&ctx->dev->v4l2_dev, ++ "Fourcc format (0x%08x) invalid.\n", ++ f->fmt.pix.pixelformat); ++ return -EINVAL; ++ } ++ ++ return vidioc_try_fmt(f); ++} ++ ++static int vidioc_s_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f) ++{ ++ struct emmaprp_q_data *q_data; ++ struct vb2_queue *vq; ++ int ret; ++ ++ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); ++ if (!vq) ++ return -EINVAL; ++ ++ q_data = get_q_data(ctx, f->type); ++ if (!q_data) ++ return -EINVAL; ++ ++ if (vb2_is_busy(vq)) { ++ v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__); ++ return -EBUSY; ++ } ++ ++ ret = vidioc_try_fmt(f); ++ if (ret) ++ return ret; ++ ++ q_data->fmt = find_format(f); ++ q_data->width = f->fmt.pix.width; ++ q_data->height = f->fmt.pix.height; ++ if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420) ++ q_data->sizeimage = q_data->width * q_data->height * 3 / 2; ++ else /* YUYV */ ++ q_data->sizeimage = q_data->width * q_data->height * 2; ++ ++ dprintk(ctx->dev, ++ "Setting format for type %d, wxh: %dx%d, fmt: %d\n", ++ f->type, q_data->width, q_data->height, q_data->fmt->fourcc); ++ ++ return 0; ++} ++ ++static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ int ret; ++ ++ ret = vidioc_try_fmt_vid_cap(file, priv, f); ++ if (ret) ++ return ret; ++ ++ return vidioc_s_fmt(priv, f); ++} ++ ++static int vidioc_s_fmt_vid_out(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ int ret; ++ ++ ret = vidioc_try_fmt_vid_out(file, priv, f); ++ if (ret) ++ return ret; ++ ++ return vidioc_s_fmt(priv, f); ++} ++ ++static int vidioc_reqbufs(struct file *file, void *priv, ++ struct v4l2_requestbuffers *reqbufs) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ ++ return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); ++} ++ ++static int vidioc_querybuf(struct file *file, void *priv, ++ struct v4l2_buffer *buf) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ ++ return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); ++} ++ ++static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ ++ return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); ++} ++ ++static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ ++ return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); ++} ++ ++static int vidioc_streamon(struct file *file, void *priv, ++ enum v4l2_buf_type type) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ ++ return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); ++} ++ ++static int vidioc_streamoff(struct file *file, void *priv, ++ enum v4l2_buf_type type) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ ++ return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); ++} ++ ++static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = { ++ .vidioc_querycap = vidioc_querycap, ++ ++ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, ++ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, ++ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, ++ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, ++ ++ .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, ++ .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, ++ .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, ++ .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, ++ ++ .vidioc_reqbufs = vidioc_reqbufs, ++ .vidioc_querybuf = vidioc_querybuf, ++ ++ .vidioc_qbuf = vidioc_qbuf, ++ .vidioc_dqbuf = vidioc_dqbuf, ++ ++ .vidioc_streamon = vidioc_streamon, ++ .vidioc_streamoff = vidioc_streamoff, ++}; ++ ++ ++/* ++ * Queue operations ++ */ ++static int emmaprp_queue_setup(struct vb2_queue *vq, ++ const struct v4l2_format *fmt, ++ unsigned int *nbuffers, unsigned int *nplanes, ++ unsigned int sizes[], void *alloc_ctxs[]) ++{ ++ struct emmaprp_ctx *ctx = vb2_get_drv_priv(vq); ++ struct emmaprp_q_data *q_data; ++ unsigned int size, count = *nbuffers; ++ ++ q_data = get_q_data(ctx, vq->type); ++ ++ if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420) ++ size = q_data->width * q_data->height * 3 / 2; ++ else ++ size = q_data->width * q_data->height * 2; ++ ++ while (size * count > MEM2MEM_VID_MEM_LIMIT) ++ (count)--; ++ ++ *nplanes = 1; ++ *nbuffers = count; ++ sizes[0] = size; ++ ++ alloc_ctxs[0] = ctx->dev->alloc_ctx; ++ ++ dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size); ++ ++ return 0; ++} ++ ++static int emmaprp_buf_prepare(struct vb2_buffer *vb) ++{ ++ struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); ++ struct emmaprp_q_data *q_data; ++ ++ dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type); ++ ++ q_data = get_q_data(ctx, vb->vb2_queue->type); ++ ++ if (vb2_plane_size(vb, 0) < q_data->sizeimage) { ++ dprintk(ctx->dev, "%s data will not fit into plane" ++ "(%lu < %lu)\n", __func__, ++ vb2_plane_size(vb, 0), ++ (long)q_data->sizeimage); ++ return -EINVAL; ++ } ++ ++ vb2_set_plane_payload(vb, 0, q_data->sizeimage); ++ ++ return 0; ++} ++ ++static void emmaprp_buf_queue(struct vb2_buffer *vb) ++{ ++ struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); ++ v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); ++} ++ ++static struct vb2_ops emmaprp_qops = { ++ .queue_setup = emmaprp_queue_setup, ++ .buf_prepare = emmaprp_buf_prepare, ++ .buf_queue = emmaprp_buf_queue, ++}; ++ ++static int queue_init(void *priv, struct vb2_queue *src_vq, ++ struct vb2_queue *dst_vq) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ int ret; ++ ++ memset(src_vq, 0, sizeof(*src_vq)); ++ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ src_vq->io_modes = VB2_MMAP; ++ src_vq->drv_priv = ctx; ++ src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); ++ src_vq->ops = &emmaprp_qops; ++ src_vq->mem_ops = &vb2_dma_contig_memops; ++ ++ ret = vb2_queue_init(src_vq); ++ if (ret) ++ return ret; ++ ++ memset(dst_vq, 0, sizeof(*dst_vq)); ++ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ dst_vq->io_modes = VB2_MMAP; ++ dst_vq->drv_priv = ctx; ++ dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); ++ dst_vq->ops = &emmaprp_qops; ++ dst_vq->mem_ops = &vb2_dma_contig_memops; ++ ++ return vb2_queue_init(dst_vq); ++} ++ ++/* ++ * File operations ++ */ ++static int emmaprp_open(struct file *file) ++{ ++ struct emmaprp_dev *pcdev = video_drvdata(file); ++ struct emmaprp_ctx *ctx; ++ ++ ctx = kzalloc(sizeof *ctx, GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ ++ file->private_data = ctx; ++ ctx->dev = pcdev; ++ ++ ctx->m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init); ++ ++ if (IS_ERR(ctx->m2m_ctx)) { ++ int ret = PTR_ERR(ctx->m2m_ctx); ++ ++ kfree(ctx); ++ return ret; ++ } ++ ++ clk_enable(pcdev->clk_emma); ++ ctx->q_data[V4L2_M2M_SRC].fmt = &formats[1]; ++ ctx->q_data[V4L2_M2M_DST].fmt = &formats[0]; ++ ++ dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx); ++ ++ return 0; ++} ++ ++static int emmaprp_release(struct file *file) ++{ ++ struct emmaprp_dev *pcdev = video_drvdata(file); ++ struct emmaprp_ctx *ctx = file->private_data; ++ ++ dprintk(pcdev, "Releasing instance %p\n", ctx); ++ ++ clk_disable(pcdev->clk_emma); ++ v4l2_m2m_ctx_release(ctx->m2m_ctx); ++ kfree(ctx); ++ ++ return 0; ++} ++ ++static unsigned int emmaprp_poll(struct file *file, ++ struct poll_table_struct *wait) ++{ ++ struct emmaprp_ctx *ctx = file->private_data; ++ ++ return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); ++} ++ ++static int emmaprp_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct emmaprp_ctx *ctx = file->private_data; ++ ++ return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); ++} ++ ++static const struct v4l2_file_operations emmaprp_fops = { ++ .owner = THIS_MODULE, ++ .open = emmaprp_open, ++ .release = emmaprp_release, ++ .poll = emmaprp_poll, ++ .unlocked_ioctl = video_ioctl2, ++ .mmap = emmaprp_mmap, ++}; ++ ++static struct video_device emmaprp_videodev = { ++ .name = MEM2MEM_NAME, ++ .fops = &emmaprp_fops, ++ .ioctl_ops = &emmaprp_ioctl_ops, ++ .minor = -1, ++ .release = video_device_release, ++}; ++ ++static struct v4l2_m2m_ops m2m_ops = { ++ .device_run = emmaprp_device_run, ++ .job_abort = emmaprp_job_abort, ++ .lock = emmaprp_lock, ++ .unlock = emmaprp_unlock, ++}; ++ ++static int emmaprp_probe(struct platform_device *pdev) ++{ ++ struct emmaprp_dev *pcdev; ++ struct video_device *vfd; ++ struct resource *res_emma; ++ int irq_emma; ++ int ret; ++ ++ pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL); ++ if (!pcdev) ++ return -ENOMEM; ++ ++ spin_lock_init(&pcdev->irqlock); ++ ++ pcdev->clk_emma = clk_get(&pdev->dev, NULL); ++ if (IS_ERR(pcdev->clk_emma)) { ++ ret = PTR_ERR(pcdev->clk_emma); ++ goto free_dev; ++ } ++ ++ irq_emma = platform_get_irq(pdev, 0); ++ res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (irq_emma < 0 || res_emma == NULL) { ++ dev_err(&pdev->dev, "Missing platform resources data\n"); ++ ret = -ENODEV; ++ goto free_clk; ++ } ++ ++ ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev); ++ if (ret) ++ goto free_clk; ++ ++ mutex_init(&pcdev->dev_mutex); ++ ++ vfd = video_device_alloc(); ++ if (!vfd) { ++ v4l2_err(&pcdev->v4l2_dev, "Failed to allocate video device\n"); ++ ret = -ENOMEM; ++ goto unreg_dev; ++ } ++ ++ *vfd = emmaprp_videodev; ++ vfd->lock = &pcdev->dev_mutex; ++ ++ video_set_drvdata(vfd, pcdev); ++ snprintf(vfd->name, sizeof(vfd->name), "%s", emmaprp_videodev.name); ++ pcdev->vfd = vfd; ++ v4l2_info(&pcdev->v4l2_dev, EMMAPRP_MODULE_NAME ++ " Device registered as /dev/video%d\n", vfd->num); ++ ++ platform_set_drvdata(pdev, pcdev); ++ ++ if (devm_request_mem_region(&pdev->dev, res_emma->start, ++ resource_size(res_emma), MEM2MEM_NAME) == NULL) ++ goto rel_vdev; ++ ++ pcdev->base_emma = devm_ioremap(&pdev->dev, res_emma->start, ++ resource_size(res_emma)); ++ if (!pcdev->base_emma) ++ goto rel_vdev; ++ ++ pcdev->irq_emma = irq_emma; ++ pcdev->res_emma = res_emma; ++ ++ if (devm_request_irq(&pdev->dev, pcdev->irq_emma, emmaprp_irq, ++ 0, MEM2MEM_NAME, pcdev) < 0) ++ goto rel_vdev; ++ ++ pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); ++ if (IS_ERR(pcdev->alloc_ctx)) { ++ v4l2_err(&pcdev->v4l2_dev, "Failed to alloc vb2 context\n"); ++ ret = PTR_ERR(pcdev->alloc_ctx); ++ goto rel_vdev; ++ } ++ ++ pcdev->m2m_dev = v4l2_m2m_init(&m2m_ops); ++ if (IS_ERR(pcdev->m2m_dev)) { ++ v4l2_err(&pcdev->v4l2_dev, "Failed to init mem2mem device\n"); ++ ret = PTR_ERR(pcdev->m2m_dev); ++ goto rel_ctx; ++ } ++ ++ ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); ++ if (ret) { ++ v4l2_err(&pcdev->v4l2_dev, "Failed to register video device\n"); ++ goto rel_m2m; ++ } ++ ++ return 0; ++ ++ ++rel_m2m: ++ v4l2_m2m_release(pcdev->m2m_dev); ++rel_ctx: ++ vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); ++rel_vdev: ++ video_device_release(vfd); ++unreg_dev: ++ v4l2_device_unregister(&pcdev->v4l2_dev); ++free_clk: ++ clk_put(pcdev->clk_emma); ++free_dev: ++ kfree(pcdev); ++ ++ return ret; ++} ++ ++static int emmaprp_remove(struct platform_device *pdev) ++{ ++ struct emmaprp_dev *pcdev = platform_get_drvdata(pdev); ++ ++ v4l2_info(&pcdev->v4l2_dev, "Removing " EMMAPRP_MODULE_NAME); ++ ++ video_unregister_device(pcdev->vfd); ++ v4l2_m2m_release(pcdev->m2m_dev); ++ vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); ++ v4l2_device_unregister(&pcdev->v4l2_dev); ++ clk_put(pcdev->clk_emma); ++ kfree(pcdev); ++ ++ return 0; ++} ++ ++static struct platform_driver emmaprp_pdrv = { ++ .probe = emmaprp_probe, ++ .remove = emmaprp_remove, ++ .driver = { ++ .name = MEM2MEM_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static void __exit emmaprp_exit(void) ++{ ++ platform_driver_unregister(&emmaprp_pdrv); ++} ++ ++static int __init emmaprp_init(void) ++{ ++ return platform_driver_register(&emmaprp_pdrv); ++} ++ ++module_init(emmaprp_init); ++module_exit(emmaprp_exit); +Index: linux-3.3.x86_64/drivers/media/common/tuners/mt2063.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/common/tuners/mt2063.h ++++ linux-3.3.x86_64/drivers/media/common/tuners/mt2063.h +@@ -23,10 +23,6 @@ static inline struct dvb_frontend *mt206 + return NULL; + } + +-int mt2063_setTune(struct dvb_frontend *fe, u32 f_in, +- u32 bw_in, +- enum MTTune_atv_standard tv_type); +- + /* FIXME: Should use the standard DVB attachment interfaces */ + unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe); + unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe); +Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/sdo_drv.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/sdo_drv.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-tv/sdo_drv.c +@@ -301,7 +301,7 @@ static int __devinit sdo_probe(struct pl + struct clk *sclk_vpll; + + dev_info(dev, "probe start\n"); +- sdev = kzalloc(sizeof *sdev, GFP_KERNEL); ++ sdev = devm_kzalloc(&pdev->dev, sizeof *sdev, GFP_KERNEL); + if (!sdev) { + dev_err(dev, "not enough memory.\n"); + ret = -ENOMEM; +@@ -314,14 +314,14 @@ static int __devinit sdo_probe(struct pl + if (res == NULL) { + dev_err(dev, "get memory resource failed.\n"); + ret = -ENXIO; +- goto fail_sdev; ++ goto fail; + } + +- sdev->regs = ioremap(res->start, resource_size(res)); ++ sdev->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (sdev->regs == NULL) { + dev_err(dev, "register mapping failed.\n"); + ret = -ENXIO; +- goto fail_sdev; ++ goto fail; + } + + /* acquiring interrupt */ +@@ -329,12 +329,13 @@ static int __devinit sdo_probe(struct pl + if (res == NULL) { + dev_err(dev, "get interrupt resource failed.\n"); + ret = -ENXIO; +- goto fail_regs; ++ goto fail; + } +- ret = request_irq(res->start, sdo_irq_handler, 0, "s5p-sdo", sdev); ++ ret = devm_request_irq(&pdev->dev, res->start, sdo_irq_handler, 0, ++ "s5p-sdo", sdev); + if (ret) { + dev_err(dev, "request interrupt failed.\n"); +- goto fail_regs; ++ goto fail; + } + sdev->irq = res->start; + +@@ -343,7 +344,7 @@ static int __devinit sdo_probe(struct pl + if (IS_ERR_OR_NULL(sdev->sclk_dac)) { + dev_err(dev, "failed to get clock 'sclk_dac'\n"); + ret = -ENXIO; +- goto fail_irq; ++ goto fail; + } + sdev->dac = clk_get(dev, "dac"); + if (IS_ERR_OR_NULL(sdev->dac)) { +@@ -415,12 +416,6 @@ fail_dac: + clk_put(sdev->dac); + fail_sclk_dac: + clk_put(sdev->sclk_dac); +-fail_irq: +- free_irq(sdev->irq, sdev); +-fail_regs: +- iounmap(sdev->regs); +-fail_sdev: +- kfree(sdev); + fail: + dev_info(dev, "probe failed\n"); + return ret; +@@ -439,9 +434,6 @@ static int __devexit sdo_remove(struct p + clk_put(sdev->dacphy); + clk_put(sdev->dac); + clk_put(sdev->sclk_dac); +- free_irq(sdev->irq, sdev); +- iounmap(sdev->regs); +- kfree(sdev); + + dev_info(&pdev->dev, "remove successful\n"); + return 0; +Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/Kconfig +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/Kconfig ++++ linux-3.3.x86_64/drivers/media/video/s5p-tv/Kconfig +@@ -46,6 +46,16 @@ config VIDEO_SAMSUNG_S5P_HDMIPHY + as module. It is an I2C driver, that exposes a V4L2 + subdev for use by other drivers. + ++config VIDEO_SAMSUNG_S5P_SII9234 ++ tristate "Samsung SII9234 Driver" ++ depends on VIDEO_DEV && VIDEO_V4L2 && I2C ++ depends on VIDEO_SAMSUNG_S5P_TV ++ help ++ Say Y here if you want support for the MHL interface ++ in S5P Samsung SoC. The driver can be compiled ++ as module. It is an I2C driver, that exposes a V4L2 ++ subdev for use by other drivers. ++ + config VIDEO_SAMSUNG_S5P_SDO + tristate "Samsung Analog TV Driver" + depends on VIDEO_DEV && VIDEO_V4L2 +Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/Makefile ++++ linux-3.3.x86_64/drivers/media/video/s5p-tv/Makefile +@@ -8,6 +8,8 @@ + + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMIPHY) += s5p-hdmiphy.o + s5p-hdmiphy-y += hdmiphy_drv.o ++obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SII9234) += s5p-sii9234.o ++s5p-sii9234-y += sii9234_drv.o + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMI) += s5p-hdmi.o + s5p-hdmi-y += hdmi_drv.o + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SDO) += s5p-sdo.o +Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/sii9234_drv.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/s5p-tv/sii9234_drv.c +@@ -0,0 +1,432 @@ ++/* ++ * Samsung MHL interface driver ++ * ++ * Copyright (C) 2011 Samsung Electronics Co.Ltd ++ * Author: Tomasz Stanislawski ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++MODULE_AUTHOR("Tomasz Stanislawski "); ++MODULE_DESCRIPTION("Samsung MHL interface driver"); ++MODULE_LICENSE("GPL"); ++ ++struct sii9234_context { ++ struct i2c_client *client; ++ struct regulator *power; ++ int gpio_n_reset; ++ struct v4l2_subdev sd; ++}; ++ ++static inline struct sii9234_context *sd_to_context(struct v4l2_subdev *sd) ++{ ++ return container_of(sd, struct sii9234_context, sd); ++} ++ ++static inline int sii9234_readb(struct i2c_client *client, int addr) ++{ ++ return i2c_smbus_read_byte_data(client, addr); ++} ++ ++static inline int sii9234_writeb(struct i2c_client *client, int addr, int value) ++{ ++ return i2c_smbus_write_byte_data(client, addr, value); ++} ++ ++static inline int sii9234_writeb_mask(struct i2c_client *client, int addr, ++ int value, int mask) ++{ ++ int ret; ++ ++ ret = i2c_smbus_read_byte_data(client, addr); ++ if (ret < 0) ++ return ret; ++ ret = (ret & ~mask) | (value & mask); ++ return i2c_smbus_write_byte_data(client, addr, ret); ++} ++ ++static inline int sii9234_readb_idx(struct i2c_client *client, int addr) ++{ ++ int ret; ++ ret = i2c_smbus_write_byte_data(client, 0xbc, addr >> 8); ++ if (ret < 0) ++ return ret; ++ ret = i2c_smbus_write_byte_data(client, 0xbd, addr & 0xff); ++ if (ret < 0) ++ return ret; ++ return i2c_smbus_read_byte_data(client, 0xbe); ++} ++ ++static inline int sii9234_writeb_idx(struct i2c_client *client, int addr, ++ int value) ++{ ++ int ret; ++ ret = i2c_smbus_write_byte_data(client, 0xbc, addr >> 8); ++ if (ret < 0) ++ return ret; ++ ret = i2c_smbus_write_byte_data(client, 0xbd, addr & 0xff); ++ if (ret < 0) ++ return ret; ++ ret = i2c_smbus_write_byte_data(client, 0xbe, value); ++ return ret; ++} ++ ++static inline int sii9234_writeb_idx_mask(struct i2c_client *client, int addr, ++ int value, int mask) ++{ ++ int ret; ++ ++ ret = sii9234_readb_idx(client, addr); ++ if (ret < 0) ++ return ret; ++ ret = (ret & ~mask) | (value & mask); ++ return sii9234_writeb_idx(client, addr, ret); ++} ++ ++static int sii9234_reset(struct sii9234_context *ctx) ++{ ++ struct i2c_client *client = ctx->client; ++ struct device *dev = &client->dev; ++ int ret, tries; ++ ++ gpio_direction_output(ctx->gpio_n_reset, 1); ++ mdelay(1); ++ gpio_direction_output(ctx->gpio_n_reset, 0); ++ mdelay(1); ++ gpio_direction_output(ctx->gpio_n_reset, 1); ++ mdelay(1); ++ ++ /* going to TTPI mode */ ++ ret = sii9234_writeb(client, 0xc7, 0); ++ if (ret < 0) { ++ dev_err(dev, "failed to set TTPI mode\n"); ++ return ret; ++ } ++ for (tries = 0; tries < 100 ; ++tries) { ++ ret = sii9234_readb(client, 0x1b); ++ if (ret > 0) ++ break; ++ if (ret < 0) { ++ dev_err(dev, "failed to reset device\n"); ++ return -EIO; ++ } ++ mdelay(1); ++ } ++ if (tries == 100) { ++ dev_err(dev, "maximal number of tries reached\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int sii9234_verify_version(struct i2c_client *client) ++{ ++ struct device *dev = &client->dev; ++ int family, rev, tpi_rev, dev_id, sub_id, hdcp, id; ++ ++ family = sii9234_readb(client, 0x1b); ++ rev = sii9234_readb(client, 0x1c) & 0x0f; ++ tpi_rev = sii9234_readb(client, 0x1d) & 0x7f; ++ dev_id = sii9234_readb_idx(client, 0x0103); ++ sub_id = sii9234_readb_idx(client, 0x0102); ++ hdcp = sii9234_readb(client, 0x30); ++ ++ if (family < 0 || rev < 0 || tpi_rev < 0 || dev_id < 0 || ++ sub_id < 0 || hdcp < 0) { ++ dev_err(dev, "failed to read chip's version\n"); ++ return -EIO; ++ } ++ ++ id = (dev_id << 8) | sub_id; ++ ++ dev_info(dev, "chip: SiL%02x family: %02x, rev: %02x\n", ++ id, family, rev); ++ dev_info(dev, "tpi_rev:%02x, hdcp: %02x\n", tpi_rev, hdcp); ++ if (id != 0x9234) { ++ dev_err(dev, "not supported chip\n"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static u8 data[][3] = { ++/* setup from driver created by doonsoo45.kim */ ++ { 0x01, 0x05, 0x04 }, /* Enable Auto soft reset on SCDT = 0 */ ++ { 0x01, 0x08, 0x35 }, /* Power Up TMDS Tx Core */ ++ { 0x01, 0x0d, 0x1c }, /* HDMI Transcode mode enable */ ++ { 0x01, 0x2b, 0x01 }, /* Enable HDCP Compliance workaround */ ++ { 0x01, 0x79, 0x40 }, /* daniel test...MHL_INT */ ++ { 0x01, 0x80, 0x34 }, /* Enable Rx PLL Clock Value */ ++ { 0x01, 0x90, 0x27 }, /* Enable CBUS discovery */ ++ { 0x01, 0x91, 0xe5 }, /* Skip RGND detection */ ++ { 0x01, 0x92, 0x46 }, /* Force MHD mode */ ++ { 0x01, 0x93, 0xdc }, /* Disable CBUS pull-up during RGND measurement */ ++ { 0x01, 0x94, 0x66 }, /* 1.8V CBUS VTH & GND threshold */ ++ { 0x01, 0x95, 0x31 }, /* RGND block & single discovery attempt */ ++ { 0x01, 0x96, 0x22 }, /* use 1K and 2K setting */ ++ { 0x01, 0xa0, 0x10 }, /* SIMG: Term mode */ ++ { 0x01, 0xa1, 0xfc }, /* Disable internal Mobile HD driver */ ++ { 0x01, 0xa3, 0xfa }, /* SIMG: Output Swing default EB, 3x Clk Mult */ ++ { 0x01, 0xa5, 0x80 }, /* SIMG: RGND Hysterisis, 3x mode for Beast */ ++ { 0x01, 0xa6, 0x0c }, /* SIMG: Swing Offset */ ++ { 0x02, 0x3d, 0x3f }, /* Power up CVCC 1.2V core */ ++ { 0x03, 0x00, 0x00 }, /* SIMG: correcting HW default */ ++ { 0x03, 0x11, 0x01 }, /* Enable TxPLL Clock */ ++ { 0x03, 0x12, 0x15 }, /* Enable Tx Clock Path & Equalizer */ ++ { 0x03, 0x13, 0x60 }, /* SIMG: Set termination value */ ++ { 0x03, 0x14, 0xf0 }, /* SIMG: Change CKDT level */ ++ { 0x03, 0x17, 0x07 }, /* SIMG: PLL Calrefsel */ ++ { 0x03, 0x1a, 0x20 }, /* VCO Cal */ ++ { 0x03, 0x22, 0xe0 }, /* SIMG: Auto EQ */ ++ { 0x03, 0x23, 0xc0 }, /* SIMG: Auto EQ */ ++ { 0x03, 0x24, 0xa0 }, /* SIMG: Auto EQ */ ++ { 0x03, 0x25, 0x80 }, /* SIMG: Auto EQ */ ++ { 0x03, 0x26, 0x60 }, /* SIMG: Auto EQ */ ++ { 0x03, 0x27, 0x40 }, /* SIMG: Auto EQ */ ++ { 0x03, 0x28, 0x20 }, /* SIMG: Auto EQ */ ++ { 0x03, 0x29, 0x00 }, /* SIMG: Auto EQ */ ++ { 0x03, 0x31, 0x0b }, /* SIMG: Rx PLL BW value from I2C BW ~ 4MHz */ ++ { 0x03, 0x45, 0x06 }, /* SIMG: DPLL Mode */ ++ { 0x03, 0x4b, 0x06 }, /* SIMG: Correcting HW default */ ++ { 0x03, 0x4c, 0xa0 }, /* Manual zone control */ ++ { 0x03, 0x4d, 0x02 }, /* SIMG: PLL Mode Value (order is important) */ ++}; ++ ++static int sii9234_set_internal(struct sii9234_context *ctx) ++{ ++ struct i2c_client *client = ctx->client; ++ int i, ret; ++ ++ for (i = 0; i < ARRAY_SIZE(data); ++i) { ++ int addr = (data[i][0] << 8) | data[i][1]; ++ ret = sii9234_writeb_idx(client, addr, data[i][2]); ++ if (ret < 0) ++ return ret; ++ } ++ return 0; ++} ++ ++static int sii9234_runtime_suspend(struct device *dev) ++{ ++ struct v4l2_subdev *sd = dev_get_drvdata(dev); ++ struct sii9234_context *ctx = sd_to_context(sd); ++ struct i2c_client *client = ctx->client; ++ ++ dev_info(dev, "suspend start\n"); ++ ++ sii9234_writeb_mask(client, 0x1e, 3, 3); ++ regulator_disable(ctx->power); ++ ++ return 0; ++} ++ ++static int sii9234_runtime_resume(struct device *dev) ++{ ++ struct v4l2_subdev *sd = dev_get_drvdata(dev); ++ struct sii9234_context *ctx = sd_to_context(sd); ++ struct i2c_client *client = ctx->client; ++ int ret; ++ ++ dev_info(dev, "resume start\n"); ++ regulator_enable(ctx->power); ++ ++ ret = sii9234_reset(ctx); ++ if (ret) ++ goto fail; ++ ++ /* enable tpi */ ++ ret = sii9234_writeb_mask(client, 0x1e, 1, 0); ++ if (ret < 0) ++ goto fail; ++ ret = sii9234_set_internal(ctx); ++ if (ret < 0) ++ goto fail; ++ ++ return 0; ++ ++fail: ++ dev_err(dev, "failed to resume\n"); ++ regulator_disable(ctx->power); ++ ++ return ret; ++} ++ ++static const struct dev_pm_ops sii9234_pm_ops = { ++ .runtime_suspend = sii9234_runtime_suspend, ++ .runtime_resume = sii9234_runtime_resume, ++}; ++ ++static int sii9234_s_power(struct v4l2_subdev *sd, int on) ++{ ++ struct sii9234_context *ctx = sd_to_context(sd); ++ int ret; ++ ++ if (on) ++ ret = pm_runtime_get_sync(&ctx->client->dev); ++ else ++ ret = pm_runtime_put(&ctx->client->dev); ++ /* only values < 0 indicate errors */ ++ return IS_ERR_VALUE(ret) ? ret : 0; ++} ++ ++static int sii9234_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ struct sii9234_context *ctx = sd_to_context(sd); ++ ++ /* (dis/en)able TDMS output */ ++ sii9234_writeb_mask(ctx->client, 0x1a, enable ? 0 : ~0 , 1 << 4); ++ return 0; ++} ++ ++static const struct v4l2_subdev_core_ops sii9234_core_ops = { ++ .s_power = sii9234_s_power, ++}; ++ ++static const struct v4l2_subdev_video_ops sii9234_video_ops = { ++ .s_stream = sii9234_s_stream, ++}; ++ ++static const struct v4l2_subdev_ops sii9234_ops = { ++ .core = &sii9234_core_ops, ++ .video = &sii9234_video_ops, ++}; ++ ++static int __devinit sii9234_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct device *dev = &client->dev; ++ struct sii9234_platform_data *pdata = dev->platform_data; ++ struct sii9234_context *ctx; ++ int ret; ++ ++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) { ++ dev_err(dev, "out of memory\n"); ++ ret = -ENOMEM; ++ goto fail; ++ } ++ ctx->client = client; ++ ++ ctx->power = regulator_get(dev, "hdmi-en"); ++ if (IS_ERR(ctx->power)) { ++ dev_err(dev, "failed to acquire regulator hdmi-en\n"); ++ ret = PTR_ERR(ctx->power); ++ goto fail_ctx; ++ } ++ ++ ctx->gpio_n_reset = pdata->gpio_n_reset; ++ ret = gpio_request(ctx->gpio_n_reset, "MHL_RST"); ++ if (ret) { ++ dev_err(dev, "failed to acquire MHL_RST gpio\n"); ++ goto fail_power; ++ } ++ ++ v4l2_i2c_subdev_init(&ctx->sd, client, &sii9234_ops); ++ ++ pm_runtime_enable(dev); ++ ++ /* enable device */ ++ ret = pm_runtime_get_sync(dev); ++ if (ret) ++ goto fail_pm; ++ ++ /* verify chip version */ ++ ret = sii9234_verify_version(client); ++ if (ret) ++ goto fail_pm_get; ++ ++ /* stop processing */ ++ pm_runtime_put(dev); ++ ++ dev_info(dev, "probe successful\n"); ++ ++ return 0; ++ ++fail_pm_get: ++ pm_runtime_put_sync(dev); ++ ++fail_pm: ++ pm_runtime_disable(dev); ++ gpio_free(ctx->gpio_n_reset); ++ ++fail_power: ++ regulator_put(ctx->power); ++ ++fail_ctx: ++ kfree(ctx); ++ ++fail: ++ dev_err(dev, "probe failed\n"); ++ ++ return ret; ++} ++ ++static int __devexit sii9234_remove(struct i2c_client *client) ++{ ++ struct device *dev = &client->dev; ++ struct v4l2_subdev *sd = i2c_get_clientdata(client); ++ struct sii9234_context *ctx = sd_to_context(sd); ++ ++ pm_runtime_disable(dev); ++ gpio_free(ctx->gpio_n_reset); ++ regulator_put(ctx->power); ++ kfree(ctx); ++ ++ dev_info(dev, "remove successful\n"); ++ ++ return 0; ++} ++ ++ ++static const struct i2c_device_id sii9234_id[] = { ++ { "SII9234", 0 }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(i2c, sii9234_id); ++static struct i2c_driver sii9234_driver = { ++ .driver = { ++ .name = "sii9234", ++ .owner = THIS_MODULE, ++ .pm = &sii9234_pm_ops, ++ }, ++ .probe = sii9234_probe, ++ .remove = __devexit_p(sii9234_remove), ++ .id_table = sii9234_id, ++}; ++ ++static int __init sii9234_init(void) ++{ ++ return i2c_add_driver(&sii9234_driver); ++} ++module_init(sii9234_init); ++ ++static void __exit sii9234_exit(void) ++{ ++ i2c_del_driver(&sii9234_driver); ++} ++module_exit(sii9234_exit); +Index: linux-3.3.x86_64/include/media/sii9234.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/include/media/sii9234.h +@@ -0,0 +1,24 @@ ++/* ++ * Driver header for SII9234 MHL converter chip. ++ * ++ * Copyright (c) 2011 Samsung Electronics, Co. Ltd ++ * Contact: Tomasz Stanislawski ++ * ++ * 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. ++ */ ++ ++#ifndef SII9234_H ++#define SII9234_H ++ ++/** ++ * @gpio_n_reset: GPIO driving nRESET pin ++ */ ++ ++struct sii9234_platform_data { ++ int gpio_n_reset; ++}; ++ ++#endif /* SII9234_H */ +Index: linux-3.3.x86_64/include/media/s5p_hdmi.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/include/media/s5p_hdmi.h +@@ -0,0 +1,35 @@ ++/* ++ * Driver header for S5P HDMI chip. ++ * ++ * Copyright (c) 2011 Samsung Electronics, Co. Ltd ++ * Contact: Tomasz Stanislawski ++ * ++ * 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. ++ */ ++ ++#ifndef S5P_HDMI_H ++#define S5P_HDMI_H ++ ++struct i2c_board_info; ++ ++/** ++ * @hdmiphy_bus: controller id for HDMIPHY bus ++ * @hdmiphy_info: template for HDMIPHY I2C device ++ * @mhl_bus: controller id for MHL control bus ++ * @mhl_info: template for MHL I2C device ++ * ++ * NULL pointer for *_info fields indicates that ++ * the corresponding chip is not present ++ */ ++struct s5p_hdmi_platform_data { ++ int hdmiphy_bus; ++ struct i2c_board_info *hdmiphy_info; ++ int mhl_bus; ++ struct i2c_board_info *mhl_info; ++}; ++ ++#endif /* S5P_HDMI_H */ ++ +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/Kconfig +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/Kconfig ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/Kconfig +@@ -425,6 +425,13 @@ config DVB_CXD2820R + help + Say Y when you want to support this frontend. + ++config DVB_RTL2830 ++ tristate "Realtek RTL2830 DVB-T" ++ depends on DVB_CORE && I2C ++ default m if DVB_FE_CUSTOMISE ++ help ++ Say Y when you want to support this frontend. ++ + comment "DVB-C (cable) frontends" + depends on DVB_CORE + +@@ -698,6 +705,19 @@ config DVB_IT913X_FE + A DVB-T tuner module. + Say Y when you want to support this frontend. + ++config DVB_M88RS2000 ++ tristate "M88RS2000 DVB-S demodulator and tuner" ++ depends on DVB_CORE && I2C ++ default m if DVB_FE_CUSTOMISE ++ help ++ A DVB-S tuner module. ++ Say Y when you want to support this frontend. ++ ++config DVB_AF9033 ++ tristate "Afatech AF9033 DVB-T demodulator" ++ depends on DVB_CORE && I2C ++ default m if DVB_FE_CUSTOMISE ++ + comment "Tools to develop new frontends" + + config DVB_DUMMY_FE +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/Makefile ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/Makefile +@@ -2,8 +2,8 @@ + # Makefile for the kernel DVB frontend device drivers. + # + +-ccflags-y += -Idrivers/media/dvb/dvb-core/ +-ccflags-y += -Idrivers/media/common/tuners/ ++ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core/ ++ccflags-y += -I$(srctree)/drivers/media/common/tuners/ + + stb0899-objs = stb0899_drv.o stb0899_algo.o + stv0900-objs = stv0900_core.o stv0900_sw.o +@@ -96,4 +96,7 @@ obj-$(CONFIG_DVB_TDA18271C2DD) += tda182 + obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o + obj-$(CONFIG_DVB_A8293) += a8293.o + obj-$(CONFIG_DVB_TDA10071) += tda10071.o ++obj-$(CONFIG_DVB_RTL2830) += rtl2830.o ++obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o ++obj-$(CONFIG_DVB_AF9033) += af9033.o + +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830.c +@@ -0,0 +1,562 @@ ++/* ++ * Realtek RTL2830 DVB-T demodulator driver ++ * ++ * Copyright (C) 2011 Antti Palosaari ++ * ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++ ++/* ++ * Driver implements own I2C-adapter for tuner I2C access. That's since chip ++ * have unusual I2C-gate control which closes gate automatically after each ++ * I2C transfer. Using own I2C adapter we can workaround that. ++ */ ++ ++#include "rtl2830_priv.h" ++ ++int rtl2830_debug; ++module_param_named(debug, rtl2830_debug, int, 0644); ++MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); ++ ++/* write multiple hardware registers */ ++static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, u8 *val, int len) ++{ ++ int ret; ++ u8 buf[1+len]; ++ struct i2c_msg msg[1] = { ++ { ++ .addr = priv->cfg.i2c_addr, ++ .flags = 0, ++ .len = 1+len, ++ .buf = buf, ++ } ++ }; ++ ++ buf[0] = reg; ++ memcpy(&buf[1], val, len); ++ ++ ret = i2c_transfer(priv->i2c, msg, 1); ++ if (ret == 1) { ++ ret = 0; ++ } else { ++ warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len); ++ ret = -EREMOTEIO; ++ } ++ return ret; ++} ++ ++/* read multiple hardware registers */ ++static int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len) ++{ ++ int ret; ++ struct i2c_msg msg[2] = { ++ { ++ .addr = priv->cfg.i2c_addr, ++ .flags = 0, ++ .len = 1, ++ .buf = ®, ++ }, { ++ .addr = priv->cfg.i2c_addr, ++ .flags = I2C_M_RD, ++ .len = len, ++ .buf = val, ++ } ++ }; ++ ++ ret = i2c_transfer(priv->i2c, msg, 2); ++ if (ret == 2) { ++ ret = 0; ++ } else { ++ warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len); ++ ret = -EREMOTEIO; ++ } ++ return ret; ++} ++ ++/* write multiple registers */ ++static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) ++{ ++ int ret; ++ u8 reg2 = (reg >> 0) & 0xff; ++ u8 page = (reg >> 8) & 0xff; ++ ++ /* switch bank if needed */ ++ if (page != priv->page) { ++ ret = rtl2830_wr(priv, 0x00, &page, 1); ++ if (ret) ++ return ret; ++ ++ priv->page = page; ++ } ++ ++ return rtl2830_wr(priv, reg2, val, len); ++} ++ ++/* read multiple registers */ ++static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) ++{ ++ int ret; ++ u8 reg2 = (reg >> 0) & 0xff; ++ u8 page = (reg >> 8) & 0xff; ++ ++ /* switch bank if needed */ ++ if (page != priv->page) { ++ ret = rtl2830_wr(priv, 0x00, &page, 1); ++ if (ret) ++ return ret; ++ ++ priv->page = page; ++ } ++ ++ return rtl2830_rd(priv, reg2, val, len); ++} ++ ++#if 0 /* currently not used */ ++/* write single register */ ++static int rtl2830_wr_reg(struct rtl2830_priv *priv, u16 reg, u8 val) ++{ ++ return rtl2830_wr_regs(priv, reg, &val, 1); ++} ++#endif ++ ++/* read single register */ ++static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val) ++{ ++ return rtl2830_rd_regs(priv, reg, val, 1); ++} ++ ++/* write single register with mask */ ++int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask) ++{ ++ int ret; ++ u8 tmp; ++ ++ /* no need for read if whole reg is written */ ++ if (mask != 0xff) { ++ ret = rtl2830_rd_regs(priv, reg, &tmp, 1); ++ if (ret) ++ return ret; ++ ++ val &= mask; ++ tmp &= ~mask; ++ val |= tmp; ++ } ++ ++ return rtl2830_wr_regs(priv, reg, &val, 1); ++} ++ ++/* read single register with mask */ ++int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask) ++{ ++ int ret, i; ++ u8 tmp; ++ ++ ret = rtl2830_rd_regs(priv, reg, &tmp, 1); ++ if (ret) ++ return ret; ++ ++ tmp &= mask; ++ ++ /* find position of the first bit */ ++ for (i = 0; i < 8; i++) { ++ if ((mask >> i) & 0x01) ++ break; ++ } ++ *val = tmp >> i; ++ ++ return 0; ++} ++ ++static int rtl2830_init(struct dvb_frontend *fe) ++{ ++ struct rtl2830_priv *priv = fe->demodulator_priv; ++ int ret, i; ++ u64 num; ++ u8 buf[3], tmp; ++ u32 if_ctl; ++ struct rtl2830_reg_val_mask tab[] = { ++ { 0x00d, 0x01, 0x03 }, ++ { 0x00d, 0x10, 0x10 }, ++ { 0x104, 0x00, 0x1e }, ++ { 0x105, 0x80, 0x80 }, ++ { 0x110, 0x02, 0x03 }, ++ { 0x110, 0x08, 0x0c }, ++ { 0x17b, 0x00, 0x40 }, ++ { 0x17d, 0x05, 0x0f }, ++ { 0x17d, 0x50, 0xf0 }, ++ { 0x18c, 0x08, 0x0f }, ++ { 0x18d, 0x00, 0xc0 }, ++ { 0x188, 0x05, 0x0f }, ++ { 0x189, 0x00, 0xfc }, ++ { 0x2d5, 0x02, 0x02 }, ++ { 0x2f1, 0x02, 0x06 }, ++ { 0x2f1, 0x20, 0xf8 }, ++ { 0x16d, 0x00, 0x01 }, ++ { 0x1a6, 0x00, 0x80 }, ++ { 0x106, priv->cfg.vtop, 0x3f }, ++ { 0x107, priv->cfg.krf, 0x3f }, ++ { 0x112, 0x28, 0xff }, ++ { 0x103, priv->cfg.agc_targ_val, 0xff }, ++ { 0x00a, 0x02, 0x07 }, ++ { 0x140, 0x0c, 0x3c }, ++ { 0x140, 0x40, 0xc0 }, ++ { 0x15b, 0x05, 0x07 }, ++ { 0x15b, 0x28, 0x38 }, ++ { 0x15c, 0x05, 0x07 }, ++ { 0x15c, 0x28, 0x38 }, ++ { 0x115, priv->cfg.spec_inv, 0x01 }, ++ { 0x16f, 0x01, 0x07 }, ++ { 0x170, 0x18, 0x38 }, ++ { 0x172, 0x0f, 0x0f }, ++ { 0x173, 0x08, 0x38 }, ++ { 0x175, 0x01, 0x07 }, ++ { 0x176, 0x00, 0xc0 }, ++ }; ++ ++ for (i = 0; i < ARRAY_SIZE(tab); i++) { ++ ret = rtl2830_wr_reg_mask(priv, tab[i].reg, tab[i].val, ++ tab[i].mask); ++ if (ret) ++ goto err; ++ } ++ ++ ret = rtl2830_wr_regs(priv, 0x18f, "\x28\x00", 2); ++ if (ret) ++ goto err; ++ ++ ret = rtl2830_wr_regs(priv, 0x195, ++ "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8); ++ if (ret) ++ goto err; ++ ++ num = priv->cfg.if_dvbt % priv->cfg.xtal; ++ num *= 0x400000; ++ num = div_u64(num, priv->cfg.xtal); ++ num = -num; ++ if_ctl = num & 0x3fffff; ++ dbg("%s: if_ctl=%08x", __func__, if_ctl); ++ ++ ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */ ++ if (ret) ++ goto err; ++ ++ buf[0] = tmp << 6; ++ buf[0] = (if_ctl >> 16) & 0x3f; ++ buf[1] = (if_ctl >> 8) & 0xff; ++ buf[2] = (if_ctl >> 0) & 0xff; ++ ++ ret = rtl2830_wr_regs(priv, 0x119, buf, 3); ++ if (ret) ++ goto err; ++ ++ /* TODO: spec init */ ++ ++ /* soft reset */ ++ ret = rtl2830_wr_reg_mask(priv, 0x101, 0x04, 0x04); ++ if (ret) ++ goto err; ++ ++ ret = rtl2830_wr_reg_mask(priv, 0x101, 0x00, 0x04); ++ if (ret) ++ goto err; ++ ++ priv->sleeping = false; ++ ++ return ret; ++err: ++ dbg("%s: failed=%d", __func__, ret); ++ return ret; ++} ++ ++static int rtl2830_sleep(struct dvb_frontend *fe) ++{ ++ struct rtl2830_priv *priv = fe->demodulator_priv; ++ priv->sleeping = true; ++ return 0; ++} ++ ++int rtl2830_get_tune_settings(struct dvb_frontend *fe, ++ struct dvb_frontend_tune_settings *s) ++{ ++ s->min_delay_ms = 500; ++ s->step_size = fe->ops.info.frequency_stepsize * 2; ++ s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; ++ ++ return 0; ++} ++ ++static int rtl2830_set_frontend(struct dvb_frontend *fe) ++{ ++ struct rtl2830_priv *priv = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret, i; ++ static u8 bw_params1[3][34] = { ++ { ++ 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41, ++ 0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a, ++ 0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82, ++ 0x03, 0x73, 0x03, 0xcf, /* 6 MHz */ ++ }, { ++ 0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca, ++ 0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca, ++ 0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e, ++ 0x03, 0xd0, 0x04, 0x53, /* 7 MHz */ ++ }, { ++ 0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0, ++ 0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a, ++ 0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f, ++ 0x04, 0x24, 0x04, 0xdb, /* 8 MHz */ ++ }, ++ }; ++ static u8 bw_params2[3][6] = { ++ {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30,}, /* 6 MHz */ ++ {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98,}, /* 7 MHz */ ++ {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64,}, /* 8 MHz */ ++ }; ++ ++ ++ dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__, ++ c->frequency, c->bandwidth_hz, c->inversion); ++ ++ /* program tuner */ ++ if (fe->ops.tuner_ops.set_params) ++ fe->ops.tuner_ops.set_params(fe); ++ ++ switch (c->bandwidth_hz) { ++ case 6000000: ++ i = 0; ++ break; ++ case 7000000: ++ i = 1; ++ break; ++ case 8000000: ++ i = 2; ++ break; ++ default: ++ dbg("invalid bandwidth"); ++ return -EINVAL; ++ } ++ ++ ret = rtl2830_wr_reg_mask(priv, 0x008, i << 1, 0x06); ++ if (ret) ++ goto err; ++ ++ /* 1/2 split I2C write */ ++ ret = rtl2830_wr_regs(priv, 0x11c, &bw_params1[i][0], 17); ++ if (ret) ++ goto err; ++ ++ /* 2/2 split I2C write */ ++ ret = rtl2830_wr_regs(priv, 0x12d, &bw_params1[i][17], 17); ++ if (ret) ++ goto err; ++ ++ ret = rtl2830_wr_regs(priv, 0x19d, bw_params2[i], 6); ++ if (ret) ++ goto err; ++ ++ return ret; ++err: ++ dbg("%s: failed=%d", __func__, ret); ++ return ret; ++} ++ ++static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status) ++{ ++ struct rtl2830_priv *priv = fe->demodulator_priv; ++ int ret; ++ u8 tmp; ++ *status = 0; ++ ++ if (priv->sleeping) ++ return 0; ++ ++ ret = rtl2830_rd_reg_mask(priv, 0x351, &tmp, 0x78); /* [6:3] */ ++ if (ret) ++ goto err; ++ ++ if (tmp == 11) { ++ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | ++ FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; ++ } else if (tmp == 10) { ++ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | ++ FE_HAS_VITERBI; ++ } ++ ++ return ret; ++err: ++ dbg("%s: failed=%d", __func__, ret); ++ return ret; ++} ++ ++static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ *snr = 0; ++ return 0; ++} ++ ++static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ *ber = 0; ++ return 0; ++} ++ ++static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ *ucblocks = 0; ++ return 0; ++} ++ ++static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength) ++{ ++ *strength = 0; ++ return 0; ++} ++ ++static struct dvb_frontend_ops rtl2830_ops; ++ ++static u32 rtl2830_tuner_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static int rtl2830_tuner_i2c_xfer(struct i2c_adapter *i2c_adap, ++ struct i2c_msg msg[], int num) ++{ ++ struct rtl2830_priv *priv = i2c_get_adapdata(i2c_adap); ++ int ret; ++ ++ /* open i2c-gate */ ++ ret = rtl2830_wr_reg_mask(priv, 0x101, 0x08, 0x08); ++ if (ret) ++ goto err; ++ ++ ret = i2c_transfer(priv->i2c, msg, num); ++ if (ret < 0) ++ warn("tuner i2c failed=%d", ret); ++ ++ return ret; ++err: ++ dbg("%s: failed=%d", __func__, ret); ++ return ret; ++} ++ ++static struct i2c_algorithm rtl2830_tuner_i2c_algo = { ++ .master_xfer = rtl2830_tuner_i2c_xfer, ++ .functionality = rtl2830_tuner_i2c_func, ++}; ++ ++struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(struct dvb_frontend *fe) ++{ ++ struct rtl2830_priv *priv = fe->demodulator_priv; ++ return &priv->tuner_i2c_adapter; ++} ++EXPORT_SYMBOL(rtl2830_get_tuner_i2c_adapter); ++ ++static void rtl2830_release(struct dvb_frontend *fe) ++{ ++ struct rtl2830_priv *priv = fe->demodulator_priv; ++ ++ i2c_del_adapter(&priv->tuner_i2c_adapter); ++ kfree(priv); ++} ++ ++struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg, ++ struct i2c_adapter *i2c) ++{ ++ struct rtl2830_priv *priv = NULL; ++ int ret = 0; ++ u8 tmp; ++ ++ /* allocate memory for the internal state */ ++ priv = kzalloc(sizeof(struct rtl2830_priv), GFP_KERNEL); ++ if (priv == NULL) ++ goto err; ++ ++ /* setup the priv */ ++ priv->i2c = i2c; ++ memcpy(&priv->cfg, cfg, sizeof(struct rtl2830_config)); ++ ++ /* check if the demod is there */ ++ ret = rtl2830_rd_reg(priv, 0x000, &tmp); ++ if (ret) ++ goto err; ++ ++ /* create dvb_frontend */ ++ memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(struct dvb_frontend_ops)); ++ priv->fe.demodulator_priv = priv; ++ ++ /* create tuner i2c adapter */ ++ strlcpy(priv->tuner_i2c_adapter.name, "RTL2830 tuner I2C adapter", ++ sizeof(priv->tuner_i2c_adapter.name)); ++ priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo; ++ priv->tuner_i2c_adapter.algo_data = NULL; ++ i2c_set_adapdata(&priv->tuner_i2c_adapter, priv); ++ if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) { ++ err("tuner I2C bus could not be initialized"); ++ goto err; ++ } ++ ++ priv->sleeping = true; ++ ++ return &priv->fe; ++err: ++ dbg("%s: failed=%d", __func__, ret); ++ kfree(priv); ++ return NULL; ++} ++EXPORT_SYMBOL(rtl2830_attach); ++ ++static struct dvb_frontend_ops rtl2830_ops = { ++ .delsys = { SYS_DVBT }, ++ .info = { ++ .name = "Realtek RTL2830 (DVB-T)", ++ .caps = FE_CAN_FEC_1_2 | ++ FE_CAN_FEC_2_3 | ++ FE_CAN_FEC_3_4 | ++ FE_CAN_FEC_5_6 | ++ FE_CAN_FEC_7_8 | ++ FE_CAN_FEC_AUTO | ++ FE_CAN_QPSK | ++ FE_CAN_QAM_16 | ++ FE_CAN_QAM_64 | ++ FE_CAN_QAM_AUTO | ++ FE_CAN_TRANSMISSION_MODE_AUTO | ++ FE_CAN_GUARD_INTERVAL_AUTO | ++ FE_CAN_HIERARCHY_AUTO | ++ FE_CAN_RECOVER | ++ FE_CAN_MUTE_TS ++ }, ++ ++ .release = rtl2830_release, ++ ++ .init = rtl2830_init, ++ .sleep = rtl2830_sleep, ++ ++ .get_tune_settings = rtl2830_get_tune_settings, ++ ++ .set_frontend = rtl2830_set_frontend, ++ ++ .read_status = rtl2830_read_status, ++ .read_snr = rtl2830_read_snr, ++ .read_ber = rtl2830_read_ber, ++ .read_ucblocks = rtl2830_read_ucblocks, ++ .read_signal_strength = rtl2830_read_signal_strength, ++}; ++ ++MODULE_AUTHOR("Antti Palosaari "); ++MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver"); ++MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830.h +@@ -0,0 +1,97 @@ ++/* ++ * Realtek RTL2830 DVB-T demodulator driver ++ * ++ * Copyright (C) 2011 Antti Palosaari ++ * ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef RTL2830_H ++#define RTL2830_H ++ ++#include ++ ++struct rtl2830_config { ++ /* ++ * Demodulator I2C address. ++ */ ++ u8 i2c_addr; ++ ++ /* ++ * Xtal frequency. ++ * Hz ++ * 4000000, 16000000, 25000000, 28800000 ++ */ ++ u32 xtal; ++ ++ /* ++ * TS output mode. ++ */ ++ u8 ts_mode; ++ ++ /* ++ * Spectrum inversion. ++ */ ++ bool spec_inv; ++ ++ /* ++ * IFs for all used modes. ++ * Hz ++ * 4570000, 4571429, 36000000, 36125000, 36166667, 44000000 ++ */ ++ u32 if_dvbt; ++ ++ /* ++ */ ++ u8 vtop; ++ ++ /* ++ */ ++ u8 krf; ++ ++ /* ++ */ ++ u8 agc_targ_val; ++}; ++ ++#if defined(CONFIG_DVB_RTL2830) || \ ++ (defined(CONFIG_DVB_RTL2830_MODULE) && defined(MODULE)) ++extern struct dvb_frontend *rtl2830_attach( ++ const struct rtl2830_config *config, ++ struct i2c_adapter *i2c ++); ++ ++extern struct i2c_adapter *rtl2830_get_tuner_i2c_adapter( ++ struct dvb_frontend *fe ++); ++#else ++static inline struct dvb_frontend *rtl2830_attach( ++ const struct rtl2830_config *config, ++ struct i2c_adapter *i2c ++) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++ ++static inline struct i2c_adapter *rtl2830_get_tuner_i2c_adapter( ++ struct dvb_frontend *fe ++) ++{ ++ return NULL; ++} ++#endif ++ ++#endif /* RTL2830_H */ +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830_priv.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830_priv.h +@@ -0,0 +1,57 @@ ++/* ++ * Realtek RTL2830 DVB-T demodulator driver ++ * ++ * Copyright (C) 2011 Antti Palosaari ++ * ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef RTL2830_PRIV_H ++#define RTL2830_PRIV_H ++ ++#include "dvb_frontend.h" ++#include "rtl2830.h" ++ ++#define LOG_PREFIX "rtl2830" ++ ++#undef dbg ++#define dbg(f, arg...) \ ++ if (rtl2830_debug) \ ++ printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) ++#undef err ++#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) ++#undef info ++#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) ++#undef warn ++#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) ++ ++struct rtl2830_priv { ++ struct i2c_adapter *i2c; ++ struct dvb_frontend fe; ++ struct rtl2830_config cfg; ++ struct i2c_adapter tuner_i2c_adapter; ++ ++ bool sleeping; ++ ++ u8 page; /* active register page */ ++}; ++ ++struct rtl2830_reg_val_mask { ++ u16 reg; ++ u8 val; ++ u8 mask; ++}; ++ ++#endif /* RTL2830_PRIV_H */ +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/rtl28xxu.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/rtl28xxu.c +@@ -0,0 +1,982 @@ ++/* ++ * Realtek RTL28xxU DVB USB driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * Copyright (C) 2011 Antti Palosaari ++ * ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include "rtl28xxu.h" ++ ++#include "rtl2830.h" ++ ++#include "qt1010.h" ++#include "mt2060.h" ++#include "mxl5005s.h" ++ ++/* debug */ ++static int dvb_usb_rtl28xxu_debug; ++module_param_named(debug, dvb_usb_rtl28xxu_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) ++{ ++ int ret; ++ unsigned int pipe; ++ u8 requesttype; ++ u8 *buf; ++ ++ buf = kmalloc(req->size, GFP_KERNEL); ++ if (!buf) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ if (req->index & CMD_WR_FLAG) { ++ /* write */ ++ memcpy(buf, req->data, req->size); ++ requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); ++ pipe = usb_sndctrlpipe(d->udev, 0); ++ } else { ++ /* read */ ++ requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); ++ pipe = usb_rcvctrlpipe(d->udev, 0); ++ } ++ ++ ret = usb_control_msg(d->udev, pipe, 0, requesttype, req->value, ++ req->index, buf, req->size, 1000); ++ if (ret > 0) ++ ret = 0; ++ ++ deb_dump(0, requesttype, req->value, req->index, buf, req->size, ++ deb_xfer); ++ ++ /* read request, copy returned data to return buf */ ++ if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) ++ memcpy(req->data, buf, req->size); ++ ++ kfree(buf); ++ ++ if (ret) ++ goto err; ++ ++ return ret; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static int rtl2831_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) ++{ ++ struct rtl28xxu_req req; ++ ++ if (reg < 0x3000) ++ req.index = CMD_USB_WR; ++ else if (reg < 0x4000) ++ req.index = CMD_SYS_WR; ++ else ++ req.index = CMD_IR_WR; ++ ++ req.value = reg; ++ req.size = len; ++ req.data = val; ++ ++ return rtl28xxu_ctrl_msg(d, &req); ++} ++ ++static int rtl2831_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) ++{ ++ struct rtl28xxu_req req; ++ ++ if (reg < 0x3000) ++ req.index = CMD_USB_RD; ++ else if (reg < 0x4000) ++ req.index = CMD_SYS_RD; ++ else ++ req.index = CMD_IR_RD; ++ ++ req.value = reg; ++ req.size = len; ++ req.data = val; ++ ++ return rtl28xxu_ctrl_msg(d, &req); ++} ++ ++static int rtl2831_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val) ++{ ++ return rtl2831_wr_regs(d, reg, &val, 1); ++} ++ ++static int rtl2831_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val) ++{ ++ return rtl2831_rd_regs(d, reg, val, 1); ++} ++ ++/* I2C */ ++static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], ++ int num) ++{ ++ int ret; ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ struct rtl28xxu_priv *priv = d->priv; ++ struct rtl28xxu_req req; ++ ++ /* ++ * It is not known which are real I2C bus xfer limits, but testing ++ * with RTL2831U + MT2060 gives max RD 24 and max WR 22 bytes. ++ * TODO: find out RTL2832U lens ++ */ ++ ++ /* ++ * I2C adapter logic looks rather complicated due to fact it handles ++ * three different access methods. Those methods are; ++ * 1) integrated demod access ++ * 2) old I2C access ++ * 3) new I2C access ++ * ++ * Used method is selected in order 1, 2, 3. Method 3 can handle all ++ * requests but there is two reasons why not use it always; ++ * 1) It is most expensive, usually two USB messages are needed ++ * 2) At least RTL2831U does not support it ++ * ++ * Method 3 is needed in case of I2C write+read (typical register read) ++ * where write is more than one byte. ++ */ ++ ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ if (num == 2 && !(msg[0].flags & I2C_M_RD) && ++ (msg[1].flags & I2C_M_RD)) { ++ if (msg[0].len > 24 || msg[1].len > 24) { ++ /* TODO: check msg[0].len max */ ++ ret = -EOPNOTSUPP; ++ goto err_mutex_unlock; ++ } else if (msg[0].addr == 0x10) { ++ /* method 1 - integrated demod */ ++ req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); ++ req.index = CMD_DEMOD_RD | priv->page; ++ req.size = msg[1].len; ++ req.data = &msg[1].buf[0]; ++ ret = rtl28xxu_ctrl_msg(d, &req); ++ } else if (msg[0].len < 2) { ++ /* method 2 - old I2C */ ++ req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); ++ req.index = CMD_I2C_RD; ++ req.size = msg[1].len; ++ req.data = &msg[1].buf[0]; ++ ret = rtl28xxu_ctrl_msg(d, &req); ++ } else { ++ /* method 3 - new I2C */ ++ req.value = (msg[0].addr << 1); ++ req.index = CMD_I2C_DA_WR; ++ req.size = msg[0].len; ++ req.data = msg[0].buf; ++ ret = rtl28xxu_ctrl_msg(d, &req); ++ if (ret) ++ goto err_mutex_unlock; ++ ++ req.value = (msg[0].addr << 1); ++ req.index = CMD_I2C_DA_RD; ++ req.size = msg[1].len; ++ req.data = msg[1].buf; ++ ret = rtl28xxu_ctrl_msg(d, &req); ++ } ++ } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { ++ if (msg[0].len > 22) { ++ /* TODO: check msg[0].len max */ ++ ret = -EOPNOTSUPP; ++ goto err_mutex_unlock; ++ } else if (msg[0].addr == 0x10) { ++ /* method 1 - integrated demod */ ++ if (msg[0].buf[0] == 0x00) { ++ /* save demod page for later demod access */ ++ priv->page = msg[0].buf[1]; ++ ret = 0; ++ } else { ++ req.value = (msg[0].buf[0] << 8) | ++ (msg[0].addr << 1); ++ req.index = CMD_DEMOD_WR | priv->page; ++ req.size = msg[0].len-1; ++ req.data = &msg[0].buf[1]; ++ ret = rtl28xxu_ctrl_msg(d, &req); ++ } ++ } else if (msg[0].len < 23) { ++ /* method 2 - old I2C */ ++ req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); ++ req.index = CMD_I2C_WR; ++ req.size = msg[0].len-1; ++ req.data = &msg[0].buf[1]; ++ ret = rtl28xxu_ctrl_msg(d, &req); ++ } else { ++ /* method 3 - new I2C */ ++ req.value = (msg[0].addr << 1); ++ req.index = CMD_I2C_DA_WR; ++ req.size = msg[0].len; ++ req.data = msg[0].buf; ++ ret = rtl28xxu_ctrl_msg(d, &req); ++ } ++ } else { ++ ret = -EINVAL; ++ } ++ ++err_mutex_unlock: ++ mutex_unlock(&d->i2c_mutex); ++ ++ return ret ? ret : num; ++} ++ ++static u32 rtl28xxu_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static struct i2c_algorithm rtl28xxu_i2c_algo = { ++ .master_xfer = rtl28xxu_i2c_xfer, ++ .functionality = rtl28xxu_i2c_func, ++}; ++ ++static struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = { ++ .i2c_addr = 0x10, /* 0x20 */ ++ .xtal = 28800000, ++ .ts_mode = 0, ++ .spec_inv = 1, ++ .if_dvbt = 36150000, ++ .vtop = 0x20, ++ .krf = 0x04, ++ .agc_targ_val = 0x2d, ++ ++}; ++ ++static struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = { ++ .i2c_addr = 0x10, /* 0x20 */ ++ .xtal = 28800000, ++ .ts_mode = 0, ++ .spec_inv = 1, ++ .if_dvbt = 36125000, ++ .vtop = 0x20, ++ .krf = 0x04, ++ .agc_targ_val = 0x2d, ++}; ++ ++static struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = { ++ .i2c_addr = 0x10, /* 0x20 */ ++ .xtal = 28800000, ++ .ts_mode = 0, ++ .spec_inv = 0, ++ .if_dvbt = 4570000, ++ .vtop = 0x3f, ++ .krf = 0x04, ++ .agc_targ_val = 0x3e, ++}; ++ ++static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) ++{ ++ int ret; ++ struct rtl28xxu_priv *priv = adap->dev->priv; ++ u8 buf[1]; ++ struct rtl2830_config *rtl2830_config; ++ /* open RTL2831U/RTL2830 I2C gate */ ++ struct rtl28xxu_req req_gate = { 0x0120, 0x0011, 0x0001, "\x08" }; ++ /* for MT2060 tuner probe */ ++ struct rtl28xxu_req req_mt2060 = { 0x00c0, CMD_I2C_RD, 1, buf }; ++ /* for QT1010 tuner probe */ ++ struct rtl28xxu_req req_qt1010 = { 0x0fc4, CMD_I2C_RD, 1, buf }; ++ ++ deb_info("%s:\n", __func__); ++ ++ /* ++ * RTL2831U GPIOs ++ * ========================================================= ++ * GPIO0 | tuner#0 | 0 off | 1 on | MXL5005S (?) ++ * GPIO2 | LED | 0 off | 1 on | ++ * GPIO4 | tuner#1 | 0 on | 1 off | MT2060 ++ */ ++ ++ /* GPIO direction */ ++ ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a); ++ if (ret) ++ goto err; ++ ++ /* enable as output GPIO0, GPIO2, GPIO4 */ ++ ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15); ++ if (ret) ++ goto err; ++ ++ /* ++ * Probe used tuner. We need to know used tuner before demod attach ++ * since there is some demod params needed to set according to tuner. ++ */ ++ ++ /* open demod I2C gate */ ++ ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate); ++ if (ret) ++ goto err; ++ ++ /* check QT1010 ID(?) register; reg=0f val=2c */ ++ ret = rtl28xxu_ctrl_msg(adap->dev, &req_qt1010); ++ if (ret == 0 && buf[0] == 0x2c) { ++ priv->tuner = TUNER_RTL2830_QT1010; ++ rtl2830_config = &rtl28xxu_rtl2830_qt1010_config; ++ deb_info("%s: QT1010\n", __func__); ++ goto found; ++ } else { ++ deb_info("%s: QT1010 probe failed=%d - %02x\n", ++ __func__, ret, buf[0]); ++ } ++ ++ /* open demod I2C gate */ ++ ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate); ++ if (ret) ++ goto err; ++ ++ /* check MT2060 ID register; reg=00 val=63 */ ++ ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2060); ++ if (ret == 0 && buf[0] == 0x63) { ++ priv->tuner = TUNER_RTL2830_MT2060; ++ rtl2830_config = &rtl28xxu_rtl2830_mt2060_config; ++ deb_info("%s: MT2060\n", __func__); ++ goto found; ++ } else { ++ deb_info("%s: MT2060 probe failed=%d - %02x\n", ++ __func__, ret, buf[0]); ++ } ++ ++ /* assume MXL5005S */ ++ ret = 0; ++ priv->tuner = TUNER_RTL2830_MXL5005S; ++ rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config; ++ deb_info("%s: MXL5005S\n", __func__); ++ goto found; ++ ++found: ++ /* attach demodulator */ ++ adap->fe_adap[0].fe = dvb_attach(rtl2830_attach, rtl2830_config, ++ &adap->dev->i2c_adap); ++ if (adap->fe_adap[0].fe == NULL) { ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ return ret; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) ++{ ++ int ret; ++ struct rtl28xxu_priv *priv = adap->dev->priv; ++ u8 buf[1]; ++ /* open RTL2832U/RTL2832 I2C gate */ ++ struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"}; ++ /* close RTL2832U/RTL2832 I2C gate */ ++ struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"}; ++ /* for FC2580 tuner probe */ ++ struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf}; ++ ++ deb_info("%s:\n", __func__); ++ ++ /* GPIO direction */ ++ ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a); ++ if (ret) ++ goto err; ++ ++ /* enable as output GPIO0, GPIO2, GPIO4 */ ++ ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15); ++ if (ret) ++ goto err; ++ ++ ret = rtl2831_wr_reg(adap->dev, SYS_DEMOD_CTL, 0xe8); ++ if (ret) ++ goto err; ++ ++ /* ++ * Probe used tuner. We need to know used tuner before demod attach ++ * since there is some demod params needed to set according to tuner. ++ */ ++ ++ /* open demod I2C gate */ ++ ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_open); ++ if (ret) ++ goto err; ++ ++ /* check FC2580 ID register; reg=01 val=56 */ ++ ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc2580); ++ if (ret == 0 && buf[0] == 0x56) { ++ priv->tuner = TUNER_RTL2832_FC2580; ++ deb_info("%s: FC2580\n", __func__); ++ goto found; ++ } else { ++ deb_info("%s: FC2580 probe failed=%d - %02x\n", ++ __func__, ret, buf[0]); ++ } ++ ++ /* close demod I2C gate */ ++ ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close); ++ if (ret) ++ goto err; ++ ++ /* tuner not found */ ++ ret = -ENODEV; ++ goto err; ++ ++found: ++ /* close demod I2C gate */ ++ ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close); ++ if (ret) ++ goto err; ++ ++ /* attach demodulator */ ++ /* TODO: */ ++ ++ return ret; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static struct qt1010_config rtl28xxu_qt1010_config = { ++ .i2c_address = 0x62, /* 0xc4 */ ++}; ++ ++static struct mt2060_config rtl28xxu_mt2060_config = { ++ .i2c_address = 0x60, /* 0xc0 */ ++ .clock_out = 0, ++}; ++ ++static struct mxl5005s_config rtl28xxu_mxl5005s_config = { ++ .i2c_address = 0x63, /* 0xc6 */ ++ .if_freq = IF_FREQ_4570000HZ, ++ .xtal_freq = CRYSTAL_FREQ_16000000HZ, ++ .agc_mode = MXL_SINGLE_AGC, ++ .tracking_filter = MXL_TF_C_H, ++ .rssi_enable = MXL_RSSI_ENABLE, ++ .cap_select = MXL_CAP_SEL_ENABLE, ++ .div_out = MXL_DIV_OUT_4, ++ .clock_out = MXL_CLOCK_OUT_DISABLE, ++ .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, ++ .top = MXL5005S_TOP_25P2, ++ .mod_mode = MXL_DIGITAL_MODE, ++ .if_mode = MXL_ZERO_IF, ++ .AgcMasterByte = 0x00, ++}; ++ ++static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap) ++{ ++ int ret; ++ struct rtl28xxu_priv *priv = adap->dev->priv; ++ struct i2c_adapter *rtl2830_tuner_i2c; ++ struct dvb_frontend *fe; ++ ++ deb_info("%s:\n", __func__); ++ ++ /* use rtl2830 driver I2C adapter, for more info see rtl2830 driver */ ++ rtl2830_tuner_i2c = rtl2830_get_tuner_i2c_adapter(adap->fe_adap[0].fe); ++ ++ switch (priv->tuner) { ++ case TUNER_RTL2830_QT1010: ++ fe = dvb_attach(qt1010_attach, adap->fe_adap[0].fe, ++ rtl2830_tuner_i2c, &rtl28xxu_qt1010_config); ++ break; ++ case TUNER_RTL2830_MT2060: ++ fe = dvb_attach(mt2060_attach, adap->fe_adap[0].fe, ++ rtl2830_tuner_i2c, &rtl28xxu_mt2060_config, ++ 1220); ++ break; ++ case TUNER_RTL2830_MXL5005S: ++ fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, ++ rtl2830_tuner_i2c, &rtl28xxu_mxl5005s_config); ++ break; ++ default: ++ fe = NULL; ++ err("unknown tuner=%d", priv->tuner); ++ } ++ ++ if (fe == NULL) { ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ return 0; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) ++{ ++ int ret; ++ struct rtl28xxu_priv *priv = adap->dev->priv; ++ struct dvb_frontend *fe; ++ ++ deb_info("%s:\n", __func__); ++ ++ switch (priv->tuner) { ++ case TUNER_RTL2832_FC2580: ++ /* TODO: */ ++ fe = NULL; ++ break; ++ default: ++ fe = NULL; ++ err("unknown tuner=%d", priv->tuner); ++ } ++ ++ if (fe == NULL) { ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ return 0; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static int rtl28xxu_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff) ++{ ++ int ret; ++ u8 buf[2], gpio; ++ ++ deb_info("%s: onoff=%d\n", __func__, onoff); ++ ++ ret = rtl2831_rd_reg(adap->dev, SYS_GPIO_OUT_VAL, &gpio); ++ if (ret) ++ goto err; ++ ++ if (onoff) { ++ buf[0] = 0x00; ++ buf[1] = 0x00; ++ gpio |= 0x04; /* LED on */ ++ } else { ++ buf[0] = 0x10; /* stall EPA */ ++ buf[1] = 0x02; /* reset EPA */ ++ gpio &= (~0x04); /* LED off */ ++ } ++ ++ ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_VAL, gpio); ++ if (ret) ++ goto err; ++ ++ ret = rtl2831_wr_regs(adap->dev, USB_EPA_CTL, buf, 2); ++ if (ret) ++ goto err; ++ ++ return ret; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff) ++{ ++ int ret; ++ u8 gpio, sys0; ++ ++ deb_info("%s: onoff=%d\n", __func__, onoff); ++ ++ /* demod adc */ ++ ret = rtl2831_rd_reg(d, SYS_SYS0, &sys0); ++ if (ret) ++ goto err; ++ ++ /* tuner power, read GPIOs */ ++ ret = rtl2831_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio); ++ if (ret) ++ goto err; ++ ++ deb_info("%s: RD SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio); ++ ++ if (onoff) { ++ gpio |= 0x01; /* GPIO0 = 1 */ ++ gpio &= (~0x10); /* GPIO4 = 0 */ ++ sys0 = sys0 & 0x0f; ++ sys0 |= 0xe0; ++ } else { ++ gpio &= (~0x01); /* GPIO0 = 0 */ ++ gpio |= 0x10; /* GPIO4 = 1 */ ++ sys0 = sys0 & (~0xc0); ++ } ++ ++ deb_info("%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio); ++ ++ /* demod adc */ ++ ret = rtl2831_wr_reg(d, SYS_SYS0, sys0); ++ if (ret) ++ goto err; ++ ++ /* tuner power, write GPIOs */ ++ ret = rtl2831_wr_reg(d, SYS_GPIO_OUT_VAL, gpio); ++ if (ret) ++ goto err; ++ ++ return ret; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static int rtl2831u_rc_query(struct dvb_usb_device *d) ++{ ++ int ret, i; ++ struct rtl28xxu_priv *priv = d->priv; ++ u8 buf[5]; ++ u32 rc_code; ++ struct rtl28xxu_reg_val rc_nec_tab[] = { ++ { 0x3033, 0x80 }, ++ { 0x3020, 0x43 }, ++ { 0x3021, 0x16 }, ++ { 0x3022, 0x16 }, ++ { 0x3023, 0x5a }, ++ { 0x3024, 0x2d }, ++ { 0x3025, 0x16 }, ++ { 0x3026, 0x01 }, ++ { 0x3028, 0xb0 }, ++ { 0x3029, 0x04 }, ++ { 0x302c, 0x88 }, ++ { 0x302e, 0x13 }, ++ { 0x3030, 0xdf }, ++ { 0x3031, 0x05 }, ++ }; ++ ++ /* init remote controller */ ++ if (!priv->rc_active) { ++ for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { ++ ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg, ++ rc_nec_tab[i].val); ++ if (ret) ++ goto err; ++ } ++ priv->rc_active = true; ++ } ++ ++ ret = rtl2831_rd_regs(d, SYS_IRRC_RP, buf, 5); ++ if (ret) ++ goto err; ++ ++ if (buf[4] & 0x01) { ++ if (buf[2] == (u8) ~buf[3]) { ++ if (buf[0] == (u8) ~buf[1]) { ++ /* NEC standard (16 bit) */ ++ rc_code = buf[0] << 8 | buf[2]; ++ } else { ++ /* NEC extended (24 bit) */ ++ rc_code = buf[0] << 16 | ++ buf[1] << 8 | buf[2]; ++ } ++ } else { ++ /* NEC full (32 bit) */ ++ rc_code = buf[0] << 24 | buf[1] << 16 | ++ buf[2] << 8 | buf[3]; ++ } ++ ++ rc_keydown(d->rc_dev, rc_code, 0); ++ ++ ret = rtl2831_wr_reg(d, SYS_IRRC_SR, 1); ++ if (ret) ++ goto err; ++ ++ /* repeated intentionally to avoid extra keypress */ ++ ret = rtl2831_wr_reg(d, SYS_IRRC_SR, 1); ++ if (ret) ++ goto err; ++ } ++ ++ return ret; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static int rtl2832u_rc_query(struct dvb_usb_device *d) ++{ ++ int ret, i; ++ struct rtl28xxu_priv *priv = d->priv; ++ u8 buf[128]; ++ int len; ++ struct rtl28xxu_reg_val rc_nec_tab[] = { ++ { IR_RX_CTRL, 0x20 }, ++ { IR_RX_BUF_CTRL, 0x80 }, ++ { IR_RX_IF, 0xff }, ++ { IR_RX_IE, 0xff }, ++ { IR_MAX_DURATION0, 0xd0 }, ++ { IR_MAX_DURATION1, 0x07 }, ++ { IR_IDLE_LEN0, 0xc0 }, ++ { IR_IDLE_LEN1, 0x00 }, ++ { IR_GLITCH_LEN, 0x03 }, ++ { IR_RX_CLK, 0x09 }, ++ { IR_RX_CFG, 0x1c }, ++ { IR_MAX_H_TOL_LEN, 0x1e }, ++ { IR_MAX_L_TOL_LEN, 0x1e }, ++ { IR_RX_CTRL, 0x80 }, ++ }; ++ ++ /* init remote controller */ ++ if (!priv->rc_active) { ++ for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { ++ ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg, ++ rc_nec_tab[i].val); ++ if (ret) ++ goto err; ++ } ++ priv->rc_active = true; ++ } ++ ++ ret = rtl2831_rd_reg(d, IR_RX_IF, &buf[0]); ++ if (ret) ++ goto err; ++ ++ if (buf[0] != 0x83) ++ goto exit; ++ ++ ret = rtl2831_rd_reg(d, IR_RX_BC, &buf[0]); ++ if (ret) ++ goto err; ++ ++ len = buf[0]; ++ ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); ++ ++ /* TODO: pass raw IR to Kernel IR decoder */ ++ ++ ret = rtl2831_wr_reg(d, IR_RX_IF, 0x03); ++ ret = rtl2831_wr_reg(d, IR_RX_BUF_CTRL, 0x80); ++ ret = rtl2831_wr_reg(d, IR_RX_CTRL, 0x80); ++ ++exit: ++ return ret; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++enum rtl28xxu_usb_table_entry { ++ RTL2831U_0BDA_2831, ++ RTL2831U_14AA_0160, ++ RTL2831U_14AA_0161, ++}; ++ ++static struct usb_device_id rtl28xxu_table[] = { ++ /* RTL2831U */ ++ [RTL2831U_0BDA_2831] = { ++ USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U)}, ++ [RTL2831U_14AA_0160] = { ++ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT)}, ++ [RTL2831U_14AA_0161] = { ++ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2)}, ++ ++ /* RTL2832U */ ++ {} /* terminating entry */ ++}; ++ ++MODULE_DEVICE_TABLE(usb, rtl28xxu_table); ++ ++static struct dvb_usb_device_properties rtl28xxu_properties[] = { ++ { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .no_reconnect = 1, ++ ++ .size_of_priv = sizeof(struct rtl28xxu_priv), ++ ++ .num_adapters = 1, ++ .adapter = { ++ { ++ .num_frontends = 1, ++ .fe = { ++ { ++ .frontend_attach = rtl2831u_frontend_attach, ++ .tuner_attach = rtl2831u_tuner_attach, ++ .streaming_ctrl = rtl28xxu_streaming_ctrl, ++ .stream = { ++ .type = USB_BULK, ++ .count = 6, ++ .endpoint = 0x81, ++ .u = { ++ .bulk = { ++ .buffersize = 8*512, ++ } ++ } ++ } ++ } ++ } ++ } ++ }, ++ ++ .power_ctrl = rtl28xxu_power_ctrl, ++ ++ .rc.core = { ++ .protocol = RC_TYPE_NEC, ++ .module_name = "rtl28xxu", ++ .rc_query = rtl2831u_rc_query, ++ .rc_interval = 400, ++ .allowed_protos = RC_TYPE_NEC, ++ .rc_codes = RC_MAP_EMPTY, ++ }, ++ ++ .i2c_algo = &rtl28xxu_i2c_algo, ++ ++ .num_device_descs = 2, ++ .devices = { ++ { ++ .name = "Realtek RTL2831U reference design", ++ .warm_ids = { ++ &rtl28xxu_table[RTL2831U_0BDA_2831], ++ }, ++ }, ++ { ++ .name = "Freecom USB2.0 DVB-T", ++ .warm_ids = { ++ &rtl28xxu_table[RTL2831U_14AA_0160], ++ &rtl28xxu_table[RTL2831U_14AA_0161], ++ }, ++ }, ++ } ++ }, ++ { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .no_reconnect = 1, ++ ++ .size_of_priv = sizeof(struct rtl28xxu_priv), ++ ++ .num_adapters = 1, ++ .adapter = { ++ { ++ .num_frontends = 1, ++ .fe = { ++ { ++ .frontend_attach = rtl2832u_frontend_attach, ++ .tuner_attach = rtl2832u_tuner_attach, ++ .streaming_ctrl = rtl28xxu_streaming_ctrl, ++ .stream = { ++ .type = USB_BULK, ++ .count = 6, ++ .endpoint = 0x81, ++ .u = { ++ .bulk = { ++ .buffersize = 8*512, ++ } ++ } ++ } ++ } ++ } ++ } ++ }, ++ ++ .power_ctrl = rtl28xxu_power_ctrl, ++ ++ .rc.core = { ++ .protocol = RC_TYPE_NEC, ++ .module_name = "rtl28xxu", ++ .rc_query = rtl2832u_rc_query, ++ .rc_interval = 400, ++ .allowed_protos = RC_TYPE_NEC, ++ .rc_codes = RC_MAP_EMPTY, ++ }, ++ ++ .i2c_algo = &rtl28xxu_i2c_algo, ++ ++ .num_device_descs = 0, /* disabled as no support for RTL2832 */ ++ .devices = { ++ { ++ .name = "Realtek RTL2832U reference design", ++ }, ++ } ++ }, ++ ++}; ++ ++static int rtl28xxu_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ int ret, i; ++ int properties_count = ARRAY_SIZE(rtl28xxu_properties); ++ struct dvb_usb_device *d; ++ ++ deb_info("%s: interface=%d\n", __func__, ++ intf->cur_altsetting->desc.bInterfaceNumber); ++ ++ if (intf->cur_altsetting->desc.bInterfaceNumber != 0) ++ return 0; ++ ++ for (i = 0; i < properties_count; i++) { ++ ret = dvb_usb_device_init(intf, &rtl28xxu_properties[i], ++ THIS_MODULE, &d, adapter_nr); ++ if (ret == 0 || ret != -ENODEV) ++ break; ++ } ++ ++ if (ret) ++ goto err; ++ ++ /* init USB endpoints */ ++ ret = rtl2831_wr_reg(d, USB_SYSCTL_0, 0x09); ++ if (ret) ++ goto err; ++ ++ ret = rtl2831_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4); ++ if (ret) ++ goto err; ++ ++ ret = rtl2831_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4); ++ if (ret) ++ goto err; ++ ++ return ret; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static struct usb_driver rtl28xxu_driver = { ++ .name = "dvb_usb_rtl28xxu", ++ .probe = rtl28xxu_probe, ++ .disconnect = dvb_usb_device_exit, ++ .id_table = rtl28xxu_table, ++}; ++ ++/* module stuff */ ++static int __init rtl28xxu_module_init(void) ++{ ++ int ret; ++ ++ deb_info("%s:\n", __func__); ++ ++ ret = usb_register(&rtl28xxu_driver); ++ if (ret) ++ err("usb_register failed=%d", ret); ++ ++ return ret; ++} ++ ++static void __exit rtl28xxu_module_exit(void) ++{ ++ deb_info("%s:\n", __func__); ++ ++ /* deregister this driver from the USB subsystem */ ++ usb_deregister(&rtl28xxu_driver); ++} ++ ++module_init(rtl28xxu_module_init); ++module_exit(rtl28xxu_module_exit); ++ ++MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver"); ++MODULE_AUTHOR("Antti Palosaari "); ++MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/rtl28xxu.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/rtl28xxu.h +@@ -0,0 +1,264 @@ ++/* ++ * Realtek RTL28xxU DVB USB driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * Copyright (C) 2011 Antti Palosaari ++ * ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef RTL28XXU_H ++#define RTL28XXU_H ++ ++#define DVB_USB_LOG_PREFIX "rtl28xxu" ++#include "dvb-usb.h" ++ ++#define deb_info(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x01, args) ++#define deb_rc(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x02, args) ++#define deb_xfer(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x04, args) ++#define deb_reg(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x08, args) ++#define deb_i2c(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x10, args) ++#define deb_fw(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x20, args) ++ ++#define deb_dump(r, t, v, i, b, l, func) { \ ++ int loop_; \ ++ func("%02x %02x %02x %02x %02x %02x %02x %02x", \ ++ t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \ ++ if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ ++ func(" >>> "); \ ++ else \ ++ func(" <<< "); \ ++ for (loop_ = 0; loop_ < l; loop_++) \ ++ func("%02x ", b[loop_]); \ ++ func("\n");\ ++} ++ ++/* ++ * USB commands ++ * (usb_control_msg() index parameter) ++ */ ++ ++#define DEMOD 0x0000 ++#define USB 0x0100 ++#define SYS 0x0200 ++#define I2C 0x0300 ++#define I2C_DA 0x0600 ++ ++#define CMD_WR_FLAG 0x0010 ++#define CMD_DEMOD_RD 0x0000 ++#define CMD_DEMOD_WR 0x0010 ++#define CMD_USB_RD 0x0100 ++#define CMD_USB_WR 0x0110 ++#define CMD_SYS_RD 0x0200 ++#define CMD_IR_RD 0x0201 ++#define CMD_IR_WR 0x0211 ++#define CMD_SYS_WR 0x0210 ++#define CMD_I2C_RD 0x0300 ++#define CMD_I2C_WR 0x0310 ++#define CMD_I2C_DA_RD 0x0600 ++#define CMD_I2C_DA_WR 0x0610 ++ ++ ++struct rtl28xxu_priv { ++ u8 chip_id; ++ u8 tuner; ++ u8 page; /* integrated demod active register page */ ++ bool rc_active; ++}; ++ ++enum rtl28xxu_chip_id { ++ CHIP_ID_NONE, ++ CHIP_ID_RTL2831U, ++ CHIP_ID_RTL2832U, ++}; ++ ++enum rtl28xxu_tuner { ++ TUNER_NONE, ++ ++ TUNER_RTL2830_QT1010, ++ TUNER_RTL2830_MT2060, ++ TUNER_RTL2830_MXL5005S, ++ ++ TUNER_RTL2832_MT2266, ++ TUNER_RTL2832_FC2580, ++ TUNER_RTL2832_MT2063, ++ TUNER_RTL2832_MAX3543, ++ TUNER_RTL2832_TUA9001, ++ TUNER_RTL2832_MXL5007T, ++ TUNER_RTL2832_FC0012, ++ TUNER_RTL2832_E4000, ++ TUNER_RTL2832_TDA18272, ++ TUNER_RTL2832_FC0013, ++}; ++ ++struct rtl28xxu_req { ++ u16 value; ++ u16 index; ++ u16 size; ++ u8 *data; ++}; ++ ++struct rtl28xxu_reg_val { ++ u16 reg; ++ u8 val; ++}; ++ ++/* ++ * memory map ++ * ++ * 0x0000 DEMOD : demodulator ++ * 0x2000 USB : SIE, USB endpoint, debug, DMA ++ * 0x3000 SYS : system ++ * 0xfc00 RC : remote controller (not RTL2831U) ++ */ ++ ++/* ++ * USB registers ++ */ ++/* SIE Control Registers */ ++#define USB_SYSCTL 0x2000 /* USB system control */ ++#define USB_SYSCTL_0 0x2000 /* USB system control */ ++#define USB_SYSCTL_1 0x2001 /* USB system control */ ++#define USB_SYSCTL_2 0x2002 /* USB system control */ ++#define USB_SYSCTL_3 0x2003 /* USB system control */ ++#define USB_IRQSTAT 0x2008 /* SIE interrupt status */ ++#define USB_IRQEN 0x200C /* SIE interrupt enable */ ++#define USB_CTRL 0x2010 /* USB control */ ++#define USB_STAT 0x2014 /* USB status */ ++#define USB_DEVADDR 0x2018 /* USB device address */ ++#define USB_TEST 0x201C /* USB test mode */ ++#define USB_FRAME_NUMBER 0x2020 /* frame number */ ++#define USB_FIFO_ADDR 0x2028 /* address of SIE FIFO RAM */ ++#define USB_FIFO_CMD 0x202A /* SIE FIFO RAM access command */ ++#define USB_FIFO_DATA 0x2030 /* SIE FIFO RAM data */ ++/* Endpoint Registers */ ++#define EP0_SETUPA 0x20F8 /* EP 0 setup packet lower byte */ ++#define EP0_SETUPB 0x20FC /* EP 0 setup packet higher byte */ ++#define USB_EP0_CFG 0x2104 /* EP 0 configure */ ++#define USB_EP0_CTL 0x2108 /* EP 0 control */ ++#define USB_EP0_STAT 0x210C /* EP 0 status */ ++#define USB_EP0_IRQSTAT 0x2110 /* EP 0 interrupt status */ ++#define USB_EP0_IRQEN 0x2114 /* EP 0 interrupt enable */ ++#define USB_EP0_MAXPKT 0x2118 /* EP 0 max packet size */ ++#define USB_EP0_BC 0x2120 /* EP 0 FIFO byte counter */ ++#define USB_EPA_CFG 0x2144 /* EP A configure */ ++#define USB_EPA_CFG_0 0x2144 /* EP A configure */ ++#define USB_EPA_CFG_1 0x2145 /* EP A configure */ ++#define USB_EPA_CFG_2 0x2146 /* EP A configure */ ++#define USB_EPA_CFG_3 0x2147 /* EP A configure */ ++#define USB_EPA_CTL 0x2148 /* EP A control */ ++#define USB_EPA_CTL_0 0x2148 /* EP A control */ ++#define USB_EPA_CTL_1 0x2149 /* EP A control */ ++#define USB_EPA_CTL_2 0x214A /* EP A control */ ++#define USB_EPA_CTL_3 0x214B /* EP A control */ ++#define USB_EPA_STAT 0x214C /* EP A status */ ++#define USB_EPA_IRQSTAT 0x2150 /* EP A interrupt status */ ++#define USB_EPA_IRQEN 0x2154 /* EP A interrupt enable */ ++#define USB_EPA_MAXPKT 0x2158 /* EP A max packet size */ ++#define USB_EPA_MAXPKT_0 0x2158 /* EP A max packet size */ ++#define USB_EPA_MAXPKT_1 0x2159 /* EP A max packet size */ ++#define USB_EPA_MAXPKT_2 0x215A /* EP A max packet size */ ++#define USB_EPA_MAXPKT_3 0x215B /* EP A max packet size */ ++#define USB_EPA_FIFO_CFG 0x2160 /* EP A FIFO configure */ ++#define USB_EPA_FIFO_CFG_0 0x2160 /* EP A FIFO configure */ ++#define USB_EPA_FIFO_CFG_1 0x2161 /* EP A FIFO configure */ ++#define USB_EPA_FIFO_CFG_2 0x2162 /* EP A FIFO configure */ ++#define USB_EPA_FIFO_CFG_3 0x2163 /* EP A FIFO configure */ ++/* Debug Registers */ ++#define USB_PHYTSTDIS 0x2F04 /* PHY test disable */ ++#define USB_TOUT_VAL 0x2F08 /* USB time-out time */ ++#define USB_VDRCTRL 0x2F10 /* UTMI vendor signal control */ ++#define USB_VSTAIN 0x2F14 /* UTMI vendor signal status in */ ++#define USB_VLOADM 0x2F18 /* UTMI load vendor signal status in */ ++#define USB_VSTAOUT 0x2F1C /* UTMI vendor signal status out */ ++#define USB_UTMI_TST 0x2F80 /* UTMI test */ ++#define USB_UTMI_STATUS 0x2F84 /* UTMI status */ ++#define USB_TSTCTL 0x2F88 /* test control */ ++#define USB_TSTCTL2 0x2F8C /* test control 2 */ ++#define USB_PID_FORCE 0x2F90 /* force PID */ ++#define USB_PKTERR_CNT 0x2F94 /* packet error counter */ ++#define USB_RXERR_CNT 0x2F98 /* RX error counter */ ++#define USB_MEM_BIST 0x2F9C /* MEM BIST test */ ++#define USB_SLBBIST 0x2FA0 /* self-loop-back BIST */ ++#define USB_CNTTEST 0x2FA4 /* counter test */ ++#define USB_PHYTST 0x2FC0 /* USB PHY test */ ++#define USB_DBGIDX 0x2FF0 /* select individual block debug signal */ ++#define USB_DBGMUX 0x2FF4 /* debug signal module mux */ ++ ++/* ++ * SYS registers ++ */ ++/* demod control registers */ ++#define SYS_SYS0 0x3000 /* include DEMOD_CTL, GPO, GPI, GPOE */ ++#define SYS_DEMOD_CTL 0x3000 /* control register for DVB-T demodulator */ ++/* GPIO registers */ ++#define SYS_GPIO_OUT_VAL 0x3001 /* output value of GPIO */ ++#define SYS_GPIO_IN_VAL 0x3002 /* input value of GPIO */ ++#define SYS_GPIO_OUT_EN 0x3003 /* output enable of GPIO */ ++#define SYS_SYS1 0x3004 /* include GPD, SYSINTE, SYSINTS, GP_CFG0 */ ++#define SYS_GPIO_DIR 0x3004 /* direction control for GPIO */ ++#define SYS_SYSINTE 0x3005 /* system interrupt enable */ ++#define SYS_SYSINTS 0x3006 /* system interrupt status */ ++#define SYS_GPIO_CFG0 0x3007 /* PAD configuration for GPIO0-GPIO3 */ ++#define SYS_SYS2 0x3008 /* include GP_CFG1 and 3 reserved bytes */ ++#define SYS_GPIO_CFG1 0x3008 /* PAD configuration for GPIO4 */ ++#define SYS_DEMOD_CTL1 0x300B ++ ++/* IrDA registers */ ++#define SYS_IRRC_PSR 0x3020 /* IR protocol selection */ ++#define SYS_IRRC_PER 0x3024 /* IR protocol extension */ ++#define SYS_IRRC_SF 0x3028 /* IR sampling frequency */ ++#define SYS_IRRC_DPIR 0x302C /* IR data package interval */ ++#define SYS_IRRC_CR 0x3030 /* IR control */ ++#define SYS_IRRC_RP 0x3034 /* IR read port */ ++#define SYS_IRRC_SR 0x3038 /* IR status */ ++/* I2C master registers */ ++#define SYS_I2CCR 0x3040 /* I2C clock */ ++#define SYS_I2CMCR 0x3044 /* I2C master control */ ++#define SYS_I2CMSTR 0x3048 /* I2C master SCL timing */ ++#define SYS_I2CMSR 0x304C /* I2C master status */ ++#define SYS_I2CMFR 0x3050 /* I2C master FIFO */ ++ ++/* ++ * IR registers ++ */ ++#define IR_RX_BUF 0xFC00 ++#define IR_RX_IE 0xFD00 ++#define IR_RX_IF 0xFD01 ++#define IR_RX_CTRL 0xFD02 ++#define IR_RX_CFG 0xFD03 ++#define IR_MAX_DURATION0 0xFD04 ++#define IR_MAX_DURATION1 0xFD05 ++#define IR_IDLE_LEN0 0xFD06 ++#define IR_IDLE_LEN1 0xFD07 ++#define IR_GLITCH_LEN 0xFD08 ++#define IR_RX_BUF_CTRL 0xFD09 ++#define IR_RX_BUF_DATA 0xFD0A ++#define IR_RX_BC 0xFD0B ++#define IR_RX_CLK 0xFD0C ++#define IR_RX_C_COUNT_L 0xFD0D ++#define IR_RX_C_COUNT_H 0xFD0E ++#define IR_SUSPEND_CTRL 0xFD10 ++#define IR_ERR_TOL_CTRL 0xFD11 ++#define IR_UNIT_LEN 0xFD12 ++#define IR_ERR_TOL_LEN 0xFD13 ++#define IR_MAX_H_TOL_LEN 0xFD14 ++#define IR_MAX_L_TOL_LEN 0xFD15 ++#define IR_MASK_CTRL 0xFD16 ++#define IR_MASK_DATA 0xFD17 ++#define IR_RES_MASK_ADDR 0xFD18 ++#define IR_RES_MASK_T_LEN 0xFD19 ++ ++#endif +Index: linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-jpeg/jpeg-core.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-core.c +@@ -32,10 +32,9 @@ + + static struct s5p_jpeg_fmt formats_enc[] = { + { +- .name = "YUV 4:2:0 planar, YCbCr", +- .fourcc = V4L2_PIX_FMT_YUV420, +- .depth = 12, +- .colplanes = 3, ++ .name = "JPEG JFIF", ++ .fourcc = V4L2_PIX_FMT_JPEG, ++ .colplanes = 1, + .types = MEM2MEM_CAPTURE, + }, + { +@@ -43,7 +42,7 @@ static struct s5p_jpeg_fmt formats_enc[] + .fourcc = V4L2_PIX_FMT_YUYV, + .depth = 16, + .colplanes = 1, +- .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, ++ .types = MEM2MEM_OUTPUT, + }, + { + .name = "RGB565", +@@ -203,6 +202,16 @@ static const unsigned char hactblg0[162] + 0xf9, 0xfa + }; + ++static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c) ++{ ++ return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler); ++} ++ ++static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh) ++{ ++ return container_of(fh, struct s5p_jpeg_ctx, fh); ++} ++ + static inline void jpeg_set_qtbl(void __iomem *regs, const unsigned char *qtbl, + unsigned long tab, int len) + { +@@ -269,6 +278,7 @@ static int queue_init(void *priv, struct + struct vb2_queue *dst_vq); + static struct s5p_jpeg_fmt *s5p_jpeg_find_format(unsigned int mode, + __u32 pixelformat); ++static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx); + + static int s5p_jpeg_open(struct file *file) + { +@@ -276,12 +286,18 @@ static int s5p_jpeg_open(struct file *fi + struct video_device *vfd = video_devdata(file); + struct s5p_jpeg_ctx *ctx; + struct s5p_jpeg_fmt *out_fmt; ++ int ret = 0; + + ctx = kzalloc(sizeof *ctx, GFP_KERNEL); + if (!ctx) + return -ENOMEM; + +- file->private_data = ctx; ++ v4l2_fh_init(&ctx->fh, vfd); ++ /* Use separate control handler per file handle */ ++ ctx->fh.ctrl_handler = &ctx->ctrl_handler; ++ file->private_data = &ctx->fh; ++ v4l2_fh_add(&ctx->fh); ++ + ctx->jpeg = jpeg; + if (vfd == jpeg->vfd_encoder) { + ctx->mode = S5P_JPEG_ENCODE; +@@ -291,24 +307,35 @@ static int s5p_jpeg_open(struct file *fi + out_fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_JPEG); + } + ++ ret = s5p_jpeg_controls_create(ctx); ++ if (ret < 0) ++ goto error; ++ + ctx->m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init); + if (IS_ERR(ctx->m2m_ctx)) { +- int err = PTR_ERR(ctx->m2m_ctx); +- kfree(ctx); +- return err; ++ ret = PTR_ERR(ctx->m2m_ctx); ++ goto error; + } + + ctx->out_q.fmt = out_fmt; + ctx->cap_q.fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_YUYV); +- + return 0; ++ ++error: ++ v4l2_fh_del(&ctx->fh); ++ v4l2_fh_exit(&ctx->fh); ++ kfree(ctx); ++ return ret; + } + + static int s5p_jpeg_release(struct file *file) + { +- struct s5p_jpeg_ctx *ctx = file->private_data; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); + + v4l2_m2m_ctx_release(ctx->m2m_ctx); ++ v4l2_ctrl_handler_free(&ctx->ctrl_handler); ++ v4l2_fh_del(&ctx->fh); ++ v4l2_fh_exit(&ctx->fh); + kfree(ctx); + + return 0; +@@ -317,14 +344,14 @@ static int s5p_jpeg_release(struct file + static unsigned int s5p_jpeg_poll(struct file *file, + struct poll_table_struct *wait) + { +- struct s5p_jpeg_ctx *ctx = file->private_data; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); + + return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); + } + + static int s5p_jpeg_mmap(struct file *file, struct vm_area_struct *vma) + { +- struct s5p_jpeg_ctx *ctx = file->private_data; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); + + return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); + } +@@ -448,7 +475,7 @@ static bool s5p_jpeg_parse_hdr(struct s5 + static int s5p_jpeg_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + if (ctx->mode == S5P_JPEG_ENCODE) { + strlcpy(cap->driver, S5P_JPEG_M2M_NAME " encoder", +@@ -497,9 +524,7 @@ static int enum_fmt(struct s5p_jpeg_fmt + static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) + { +- struct s5p_jpeg_ctx *ctx; +- +- ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + if (ctx->mode == S5P_JPEG_ENCODE) + return enum_fmt(formats_enc, NUM_FORMATS_ENC, f, +@@ -511,9 +536,7 @@ static int s5p_jpeg_enum_fmt_vid_cap(str + static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv, + struct v4l2_fmtdesc *f) + { +- struct s5p_jpeg_ctx *ctx; +- +- ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + if (ctx->mode == S5P_JPEG_ENCODE) + return enum_fmt(formats_enc, NUM_FORMATS_ENC, f, +@@ -538,7 +561,7 @@ static int s5p_jpeg_g_fmt(struct file *f + struct vb2_queue *vq; + struct s5p_jpeg_q_data *q_data = NULL; + struct v4l2_pix_format *pix = &f->fmt.pix; +- struct s5p_jpeg_ctx *ct = priv; ++ struct s5p_jpeg_ctx *ct = fh_to_ctx(priv); + + vq = v4l2_m2m_get_vq(ct->m2m_ctx, f->type); + if (!vq) +@@ -659,8 +682,8 @@ static int vidioc_try_fmt(struct v4l2_fo + static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) + { ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + struct s5p_jpeg_fmt *fmt; +- struct s5p_jpeg_ctx *ctx = priv; + + fmt = s5p_jpeg_find_format(ctx->mode, f->fmt.pix.pixelformat); + if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) { +@@ -676,8 +699,8 @@ static int s5p_jpeg_try_fmt_vid_cap(stru + static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *f) + { ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + struct s5p_jpeg_fmt *fmt; +- struct s5p_jpeg_ctx *ctx = priv; + + fmt = s5p_jpeg_find_format(ctx->mode, f->fmt.pix.pixelformat); + if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) { +@@ -728,7 +751,7 @@ static int s5p_jpeg_s_fmt_vid_cap(struct + if (ret) + return ret; + +- return s5p_jpeg_s_fmt(priv, f); ++ return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); + } + + static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, +@@ -740,13 +763,13 @@ static int s5p_jpeg_s_fmt_vid_out(struct + if (ret) + return ret; + +- return s5p_jpeg_s_fmt(priv, f); ++ return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); + } + + static int s5p_jpeg_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *reqbufs) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); + } +@@ -754,14 +777,14 @@ static int s5p_jpeg_reqbufs(struct file + static int s5p_jpeg_querybuf(struct file *file, void *priv, + struct v4l2_buffer *buf) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); + } + + static int s5p_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); + } +@@ -769,7 +792,7 @@ static int s5p_jpeg_qbuf(struct file *fi + static int s5p_jpeg_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *buf) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); + } +@@ -777,7 +800,7 @@ static int s5p_jpeg_dqbuf(struct file *f + static int s5p_jpeg_streamon(struct file *file, void *priv, + enum v4l2_buf_type type) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); + } +@@ -785,7 +808,7 @@ static int s5p_jpeg_streamon(struct file + static int s5p_jpeg_streamoff(struct file *file, void *priv, + enum v4l2_buf_type type) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); + } +@@ -793,7 +816,7 @@ static int s5p_jpeg_streamoff(struct fil + int s5p_jpeg_g_selection(struct file *file, void *priv, + struct v4l2_selection *s) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && + s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) +@@ -822,33 +845,89 @@ int s5p_jpeg_g_selection(struct file *fi + return 0; + } + +-static int s5p_jpeg_g_jpegcomp(struct file *file, void *priv, +- struct v4l2_jpegcompression *compr) ++/* ++ * V4L2 controls ++ */ ++ ++static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl); ++ struct s5p_jpeg *jpeg = ctx->jpeg; ++ unsigned long flags; + +- if (ctx->mode == S5P_JPEG_DECODE) +- return -ENOTTY; ++ switch (ctrl->id) { ++ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: ++ spin_lock_irqsave(&jpeg->slock, flags); ++ ++ WARN_ON(ctx->subsampling > S5P_SUBSAMPLING_MODE_GRAY); ++ if (ctx->subsampling > 2) ++ ctrl->val = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; ++ else ++ ctrl->val = ctx->subsampling; ++ spin_unlock_irqrestore(&jpeg->slock, flags); ++ break; ++ } + +- memset(compr, 0, sizeof(*compr)); +- compr->quality = ctx->compr_quality; ++ return 0; ++} ++ ++static int s5p_jpeg_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ctx->jpeg->slock, flags); ++ ++ switch (ctrl->id) { ++ case V4L2_CID_JPEG_COMPRESSION_QUALITY: ++ ctx->compr_quality = S5P_JPEG_COMPR_QUAL_WORST - ctrl->val; ++ break; ++ case V4L2_CID_JPEG_RESTART_INTERVAL: ++ ctx->restart_interval = ctrl->val; ++ break; ++ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: ++ ctx->subsampling = ctrl->val; ++ break; ++ } + ++ spin_unlock_irqrestore(&ctx->jpeg->slock, flags); + return 0; + } + +-static int s5p_jpeg_s_jpegcomp(struct file *file, void *priv, +- struct v4l2_jpegcompression *compr) ++static const struct v4l2_ctrl_ops s5p_jpeg_ctrl_ops = { ++ .g_volatile_ctrl = s5p_jpeg_g_volatile_ctrl, ++ .s_ctrl = s5p_jpeg_s_ctrl, ++}; ++ ++static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ unsigned int mask = ~0x27; /* 444, 422, 420, GRAY */ ++ struct v4l2_ctrl *ctrl; + +- if (ctx->mode == S5P_JPEG_DECODE) +- return -ENOTTY; ++ v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3); + +- compr->quality = clamp(compr->quality, S5P_JPEG_COMPR_QUAL_BEST, +- S5P_JPEG_COMPR_QUAL_WORST); ++ if (ctx->mode == S5P_JPEG_ENCODE) { ++ v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops, ++ V4L2_CID_JPEG_COMPRESSION_QUALITY, ++ 0, 3, 1, 3); ++ ++ v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops, ++ V4L2_CID_JPEG_RESTART_INTERVAL, ++ 0, 3, 0xffff, 0); ++ mask = ~0x06; /* 422, 420 */ ++ } ++ ++ ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops, ++ V4L2_CID_JPEG_CHROMA_SUBSAMPLING, ++ V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, mask, ++ V4L2_JPEG_CHROMA_SUBSAMPLING_422); + +- ctx->compr_quality = S5P_JPEG_COMPR_QUAL_WORST - compr->quality; ++ if (ctx->ctrl_handler.error) ++ return ctx->ctrl_handler.error; + ++ if (ctx->mode == S5P_JPEG_DECODE) ++ ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE | ++ V4L2_CTRL_FLAG_READ_ONLY; + return 0; + } + +@@ -877,9 +956,6 @@ static const struct v4l2_ioctl_ops s5p_j + .vidioc_streamoff = s5p_jpeg_streamoff, + + .vidioc_g_selection = s5p_jpeg_g_selection, +- +- .vidioc_g_jpegcomp = s5p_jpeg_g_jpegcomp, +- .vidioc_s_jpegcomp = s5p_jpeg_s_jpegcomp, + }; + + /* +@@ -908,13 +984,8 @@ static void s5p_jpeg_device_run(void *pr + jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_565); + else + jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_422); +- if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV) +- jpeg_subsampling_mode(jpeg->regs, +- S5P_JPEG_SUBSAMPLING_422); +- else +- jpeg_subsampling_mode(jpeg->regs, +- S5P_JPEG_SUBSAMPLING_420); +- jpeg_dri(jpeg->regs, 0); ++ jpeg_subsampling_mode(jpeg->regs, ctx->subsampling); ++ jpeg_dri(jpeg->regs, ctx->restart_interval); + jpeg_x(jpeg->regs, ctx->out_q.w); + jpeg_y(jpeg->regs, ctx->out_q.h); + jpeg_imgadr(jpeg->regs, src_addr); +@@ -953,14 +1024,18 @@ static void s5p_jpeg_device_run(void *pr + jpeg_htbl_dc(jpeg->regs, 2); + jpeg_htbl_ac(jpeg->regs, 3); + jpeg_htbl_dc(jpeg->regs, 3); +- } else { ++ } else { /* S5P_JPEG_DECODE */ + jpeg_rst_int_enable(jpeg->regs, true); + jpeg_data_num_int_enable(jpeg->regs, true); + jpeg_final_mcu_num_int_enable(jpeg->regs, true); +- jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422); ++ if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV) ++ jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422); ++ else ++ jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_420); + jpeg_jpgadr(jpeg->regs, src_addr); + jpeg_imgadr(jpeg->regs, dst_addr); + } ++ + jpeg_start(jpeg->regs); + } + +@@ -1162,6 +1237,8 @@ static irqreturn_t s5p_jpeg_irq(int irq, + bool timer_elapsed = false; + bool op_completed = false; + ++ spin_lock(&jpeg->slock); ++ + curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); + + src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); +@@ -1192,6 +1269,9 @@ static irqreturn_t s5p_jpeg_irq(int irq, + v4l2_m2m_buf_done(dst_buf, state); + v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->m2m_ctx); + ++ curr_ctx->subsampling = jpeg_get_subsampling_mode(jpeg->regs); ++ spin_unlock(&jpeg->slock); ++ + jpeg_clear_int(jpeg->regs); + + return IRQ_HANDLED; +@@ -1215,6 +1295,7 @@ static int s5p_jpeg_probe(struct platfor + return -ENOMEM; + + mutex_init(&jpeg->lock); ++ spin_lock_init(&jpeg->slock); + jpeg->dev = &pdev->dev; + + /* memory-mapped registers */ +Index: linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-core.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-jpeg/jpeg-core.h ++++ linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-core.h +@@ -14,6 +14,8 @@ + #define JPEG_CORE_H_ + + #include ++#include ++#include + + #define S5P_JPEG_M2M_NAME "s5p-jpeg" + +@@ -47,6 +49,7 @@ + /** + * struct s5p_jpeg - JPEG IP abstraction + * @lock: the mutex protecting this structure ++ * @slock: spinlock protecting the device contexts + * @v4l2_dev: v4l2 device for mem2mem mode + * @vfd_encoder: video device node for encoder mem2mem mode + * @vfd_decoder: video device node for decoder mem2mem mode +@@ -60,6 +63,7 @@ + */ + struct s5p_jpeg { + struct mutex lock; ++ struct spinlock slock; + + struct v4l2_device v4l2_dev; + struct video_device *vfd_encoder; +@@ -117,15 +121,20 @@ struct s5p_jpeg_q_data { + * @out_q: source (output) queue information + * @cap_fmt: destination (capture) queue queue information + * @hdr_parsed: set if header has been parsed during decompression ++ * @ctrl_handler: controls handler + */ + struct s5p_jpeg_ctx { + struct s5p_jpeg *jpeg; + unsigned int mode; +- unsigned int compr_quality; ++ unsigned short compr_quality; ++ unsigned short restart_interval; ++ unsigned short subsampling; + struct v4l2_m2m_ctx *m2m_ctx; + struct s5p_jpeg_q_data out_q; + struct s5p_jpeg_q_data cap_q; ++ struct v4l2_fh fh; + bool hdr_parsed; ++ struct v4l2_ctrl_handler ctrl_handler; + }; + + /** +Index: linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-hw.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-jpeg/jpeg-hw.h ++++ linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-hw.h +@@ -13,6 +13,7 @@ + #define JPEG_HW_H_ + + #include ++#include + + #include "jpeg-hw.h" + #include "jpeg-regs.h" +@@ -25,8 +26,6 @@ + #define S5P_JPEG_DECODE 1 + #define S5P_JPEG_RAW_IN_565 0 + #define S5P_JPEG_RAW_IN_422 1 +-#define S5P_JPEG_SUBSAMPLING_422 0 +-#define S5P_JPEG_SUBSAMPLING_420 1 + #define S5P_JPEG_RAW_OUT_422 0 + #define S5P_JPEG_RAW_OUT_420 1 + +@@ -91,21 +90,26 @@ static inline void jpeg_proc_mode(void _ + writel(reg, regs + S5P_JPGMOD); + } + +-static inline void jpeg_subsampling_mode(void __iomem *regs, unsigned long mode) ++static inline void jpeg_subsampling_mode(void __iomem *regs, unsigned int mode) + { + unsigned long reg, m; + +- m = S5P_SUBSAMPLING_MODE_422; +- if (mode == S5P_JPEG_SUBSAMPLING_422) +- m = S5P_SUBSAMPLING_MODE_422; +- else if (mode == S5P_JPEG_SUBSAMPLING_420) ++ if (mode == V4L2_JPEG_CHROMA_SUBSAMPLING_420) + m = S5P_SUBSAMPLING_MODE_420; ++ else ++ m = S5P_SUBSAMPLING_MODE_422; ++ + reg = readl(regs + S5P_JPGMOD); + reg &= ~S5P_SUBSAMPLING_MODE_MASK; + reg |= m; + writel(reg, regs + S5P_JPGMOD); + } + ++static inline unsigned int jpeg_get_subsampling_mode(void __iomem *regs) ++{ ++ return readl(regs + S5P_JPGMOD) & S5P_SUBSAMPLING_MODE_MASK; ++} ++ + static inline void jpeg_dri(void __iomem *regs, unsigned int dri) + { + unsigned long reg; +Index: linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-fimc/fimc-core.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-core.c +@@ -1602,24 +1602,35 @@ static void fimc_clk_put(struct fimc_dev + { + int i; + for (i = 0; i < fimc->num_clocks; i++) { +- if (fimc->clock[i]) +- clk_put(fimc->clock[i]); ++ if (IS_ERR_OR_NULL(fimc->clock[i])) ++ continue; ++ clk_unprepare(fimc->clock[i]); ++ clk_put(fimc->clock[i]); ++ fimc->clock[i] = NULL; + } + } + + static int fimc_clk_get(struct fimc_dev *fimc) + { +- int i; ++ int i, ret; ++ + for (i = 0; i < fimc->num_clocks; i++) { + fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]); +- if (!IS_ERR_OR_NULL(fimc->clock[i])) +- continue; +- dev_err(&fimc->pdev->dev, "failed to get fimc clock: %s\n", +- fimc_clocks[i]); +- return -ENXIO; ++ if (IS_ERR(fimc->clock[i])) ++ goto err; ++ ret = clk_prepare(fimc->clock[i]); ++ if (ret < 0) { ++ clk_put(fimc->clock[i]); ++ fimc->clock[i] = NULL; ++ goto err; ++ } + } +- + return 0; ++err: ++ fimc_clk_put(fimc); ++ dev_err(&fimc->pdev->dev, "failed to get clock: %s\n", ++ fimc_clocks[i]); ++ return -ENXIO; + } + + static int fimc_m2m_suspend(struct fimc_dev *fimc) +@@ -1667,8 +1678,6 @@ static int fimc_probe(struct platform_de + struct s5p_platform_fimc *pdata; + int ret = 0; + +- dev_dbg(&pdev->dev, "%s():\n", __func__); +- + drv_data = (struct samsung_fimc_driverdata *) + platform_get_device_id(pdev)->driver_data; + +@@ -1678,7 +1687,7 @@ static int fimc_probe(struct platform_de + return -EINVAL; + } + +- fimc = kzalloc(sizeof(struct fimc_dev), GFP_KERNEL); ++ fimc = devm_kzalloc(&pdev->dev, sizeof(*fimc), GFP_KERNEL); + if (!fimc) + return -ENOMEM; + +@@ -1689,51 +1698,35 @@ static int fimc_probe(struct platform_de + pdata = pdev->dev.platform_data; + fimc->pdata = pdata; + +- + init_waitqueue_head(&fimc->irq_queue); + spin_lock_init(&fimc->slock); + mutex_init(&fimc->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!res) { +- dev_err(&pdev->dev, "failed to find the registers\n"); +- ret = -ENOENT; +- goto err_info; +- } +- +- fimc->regs_res = request_mem_region(res->start, resource_size(res), +- dev_name(&pdev->dev)); +- if (!fimc->regs_res) { +- dev_err(&pdev->dev, "failed to obtain register region\n"); +- ret = -ENOENT; +- goto err_info; +- } +- +- fimc->regs = ioremap(res->start, resource_size(res)); +- if (!fimc->regs) { +- dev_err(&pdev->dev, "failed to map registers\n"); +- ret = -ENXIO; +- goto err_req_region; ++ fimc->regs = devm_request_and_ioremap(&pdev->dev, res); ++ if (fimc->regs == NULL) { ++ dev_err(&pdev->dev, "Failed to obtain io memory\n"); ++ return -ENOENT; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); +- if (!res) { +- dev_err(&pdev->dev, "failed to get IRQ resource\n"); +- ret = -ENXIO; +- goto err_regs_unmap; ++ if (res == NULL) { ++ dev_err(&pdev->dev, "Failed to get IRQ resource\n"); ++ return -ENXIO; + } + fimc->irq = res->start; + + fimc->num_clocks = MAX_FIMC_CLOCKS; + ret = fimc_clk_get(fimc); + if (ret) +- goto err_regs_unmap; ++ return ret; + clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency); + clk_enable(fimc->clock[CLK_BUS]); + + platform_set_drvdata(pdev, fimc); + +- ret = request_irq(fimc->irq, fimc_irq_handler, 0, pdev->name, fimc); ++ ret = devm_request_irq(&pdev->dev, fimc->irq, fimc_irq_handler, ++ 0, pdev->name, fimc); + if (ret) { + dev_err(&pdev->dev, "failed to install irq (%d)\n", ret); + goto err_clk; +@@ -1742,7 +1735,7 @@ static int fimc_probe(struct platform_de + pm_runtime_enable(&pdev->dev); + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) +- goto err_irq; ++ goto err_clk; + /* Initialize contiguous memory allocator */ + fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); + if (IS_ERR(fimc->alloc_ctx)) { +@@ -1757,17 +1750,8 @@ static int fimc_probe(struct platform_de + + err_pm: + pm_runtime_put(&pdev->dev); +-err_irq: +- free_irq(fimc->irq, fimc); + err_clk: + fimc_clk_put(fimc); +-err_regs_unmap: +- iounmap(fimc->regs); +-err_req_region: +- release_resource(fimc->regs_res); +- kfree(fimc->regs_res); +-err_info: +- kfree(fimc); + return ret; + } + +@@ -1854,11 +1838,6 @@ static int __devexit fimc_remove(struct + + clk_disable(fimc->clock[CLK_BUS]); + fimc_clk_put(fimc); +- free_irq(fimc->irq, fimc); +- iounmap(fimc->regs); +- release_resource(fimc->regs_res); +- kfree(fimc->regs_res); +- kfree(fimc); + + dev_info(&pdev->dev, "driver unloaded\n"); + return 0; +Index: linux-3.3.x86_64/drivers/media/video/s5p-fimc/mipi-csis.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-fimc/mipi-csis.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-fimc/mipi-csis.c +@@ -1,8 +1,8 @@ + /* + * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver + * +- * Copyright (C) 2011 Samsung Electronics Co., Ltd. +- * Contact: Sylwester Nawrocki, ++ * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. ++ * Sylwester Nawrocki, + * + * 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 +@@ -100,7 +100,6 @@ enum { + * @pads: CSIS pads array + * @sd: v4l2_subdev associated with CSIS device instance + * @pdev: CSIS platform device +- * @regs_res: requested I/O register memory resource + * @regs: mmaped I/O registers memory + * @clock: CSIS clocks + * @irq: requested s5p-mipi-csis irq number +@@ -113,7 +112,6 @@ struct csis_state { + struct media_pad pads[CSIS_PADS_NUM]; + struct v4l2_subdev sd; + struct platform_device *pdev; +- struct resource *regs_res; + void __iomem *regs; + struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES]; + struct clk *clock[NUM_CSIS_CLOCKS]; +@@ -258,26 +256,36 @@ static void s5pcsis_clk_put(struct csis_ + { + int i; + +- for (i = 0; i < NUM_CSIS_CLOCKS; i++) +- if (!IS_ERR_OR_NULL(state->clock[i])) +- clk_put(state->clock[i]); ++ for (i = 0; i < NUM_CSIS_CLOCKS; i++) { ++ if (IS_ERR_OR_NULL(state->clock[i])) ++ continue; ++ clk_unprepare(state->clock[i]); ++ clk_put(state->clock[i]); ++ state->clock[i] = NULL; ++ } + } + + static int s5pcsis_clk_get(struct csis_state *state) + { + struct device *dev = &state->pdev->dev; +- int i; ++ int i, ret; + + for (i = 0; i < NUM_CSIS_CLOCKS; i++) { + state->clock[i] = clk_get(dev, csi_clock_name[i]); +- if (IS_ERR(state->clock[i])) { +- s5pcsis_clk_put(state); +- dev_err(dev, "failed to get clock: %s\n", +- csi_clock_name[i]); +- return -ENXIO; ++ if (IS_ERR(state->clock[i])) ++ goto err; ++ ret = clk_prepare(state->clock[i]); ++ if (ret < 0) { ++ clk_put(state->clock[i]); ++ state->clock[i] = NULL; ++ goto err; + } + } + return 0; ++err: ++ s5pcsis_clk_put(state); ++ dev_err(dev, "failed to get clock: %s\n", csi_clock_name[i]); ++ return -ENXIO; + } + + static int s5pcsis_s_power(struct v4l2_subdev *sd, int on) +@@ -480,12 +488,11 @@ static int __devinit s5pcsis_probe(struc + { + struct s5p_platform_mipi_csis *pdata; + struct resource *mem_res; +- struct resource *regs_res; + struct csis_state *state; + int ret = -ENOMEM; + int i; + +- state = kzalloc(sizeof(*state), GFP_KERNEL); ++ state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + +@@ -495,52 +502,27 @@ static int __devinit s5pcsis_probe(struc + pdata = pdev->dev.platform_data; + if (pdata == NULL || pdata->phy_enable == NULL) { + dev_err(&pdev->dev, "Platform data not fully specified\n"); +- goto e_free; ++ return -EINVAL; + } + + if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) || + pdata->lanes > CSIS0_MAX_LANES) { +- ret = -EINVAL; + dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n", + pdata->lanes); +- goto e_free; ++ return -EINVAL; + } + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!mem_res) { +- dev_err(&pdev->dev, "Failed to get IO memory region\n"); +- goto e_free; +- } +- +- regs_res = request_mem_region(mem_res->start, resource_size(mem_res), +- pdev->name); +- if (!regs_res) { +- dev_err(&pdev->dev, "Failed to request IO memory region\n"); +- goto e_free; +- } +- state->regs_res = regs_res; +- +- state->regs = ioremap(mem_res->start, resource_size(mem_res)); +- if (!state->regs) { +- dev_err(&pdev->dev, "Failed to remap IO region\n"); +- goto e_reqmem; ++ state->regs = devm_request_and_ioremap(&pdev->dev, mem_res); ++ if (state->regs == NULL) { ++ dev_err(&pdev->dev, "Failed to request and remap io memory\n"); ++ return -ENXIO; + } + +- ret = s5pcsis_clk_get(state); +- if (ret) +- goto e_unmap; +- +- clk_enable(state->clock[CSIS_CLK_MUX]); +- if (pdata->clk_rate) +- clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate); +- else +- dev_WARN(&pdev->dev, "No clock frequency specified!\n"); +- + state->irq = platform_get_irq(pdev, 0); + if (state->irq < 0) { +- ret = state->irq; + dev_err(&pdev->dev, "Failed to get irq\n"); +- goto e_clkput; ++ return state->irq; + } + + for (i = 0; i < CSIS_NUM_SUPPLIES; i++) +@@ -549,12 +531,22 @@ static int __devinit s5pcsis_probe(struc + ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES, + state->supplies); + if (ret) ++ return ret; ++ ++ ret = s5pcsis_clk_get(state); ++ if (ret) + goto e_clkput; + +- ret = request_irq(state->irq, s5pcsis_irq_handler, 0, +- dev_name(&pdev->dev), state); ++ clk_enable(state->clock[CSIS_CLK_MUX]); ++ if (pdata->clk_rate) ++ clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate); ++ else ++ dev_WARN(&pdev->dev, "No clock frequency specified!\n"); ++ ++ ret = devm_request_irq(&pdev->dev, state->irq, s5pcsis_irq_handler, ++ 0, dev_name(&pdev->dev), state); + if (ret) { +- dev_err(&pdev->dev, "request_irq failed\n"); ++ dev_err(&pdev->dev, "Interrupt request failed\n"); + goto e_regput; + } + +@@ -573,7 +565,7 @@ static int __devinit s5pcsis_probe(struc + ret = media_entity_init(&state->sd.entity, + CSIS_PADS_NUM, state->pads, 0); + if (ret < 0) +- goto e_irqfree; ++ goto e_clkput; + + /* This allows to retrieve the platform device id by the host driver */ + v4l2_set_subdevdata(&state->sd, pdev); +@@ -582,22 +574,13 @@ static int __devinit s5pcsis_probe(struc + platform_set_drvdata(pdev, &state->sd); + + pm_runtime_enable(&pdev->dev); +- + return 0; + +-e_irqfree: +- free_irq(state->irq, state); + e_regput: + regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); + e_clkput: + clk_disable(state->clock[CSIS_CLK_MUX]); + s5pcsis_clk_put(state); +-e_unmap: +- iounmap(state->regs); +-e_reqmem: +- release_mem_region(regs_res->start, resource_size(regs_res)); +-e_free: +- kfree(state); + return ret; + } + +@@ -699,21 +682,15 @@ static int __devexit s5pcsis_remove(stru + { + struct v4l2_subdev *sd = platform_get_drvdata(pdev); + struct csis_state *state = sd_to_csis_state(sd); +- struct resource *res = state->regs_res; + + pm_runtime_disable(&pdev->dev); +- s5pcsis_suspend(&pdev->dev); ++ s5pcsis_pm_suspend(&pdev->dev, false); + clk_disable(state->clock[CSIS_CLK_MUX]); + pm_runtime_set_suspended(&pdev->dev); +- + s5pcsis_clk_put(state); + regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); + + media_entity_cleanup(&state->sd.entity); +- free_irq(state->irq, state); +- iounmap(state->regs); +- release_mem_region(res->start, resource_size(res)); +- kfree(state); + + return 0; + } +Index: linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-core.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-fimc/fimc-core.h ++++ linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-core.h +@@ -434,7 +434,6 @@ struct fimc_ctx; + * @num_clocks: the number of clocks managed by this device instance + * @clock: clocks required for FIMC operation + * @regs: the mapped hardware registers +- * @regs_res: the resource claimed for IO registers + * @irq: FIMC interrupt number + * @irq_queue: interrupt handler waitqueue + * @v4l2_dev: root v4l2_device +@@ -454,7 +453,6 @@ struct fimc_dev { + u16 num_clocks; + struct clk *clock[MAX_FIMC_CLOCKS]; + void __iomem *regs; +- struct resource *regs_res; + int irq; + wait_queue_head_t irq_queue; + struct v4l2_device *v4l2_dev; +Index: linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-capture.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-fimc/fimc-capture.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-capture.c +@@ -1019,52 +1019,117 @@ static int fimc_cap_dqbuf(struct file *f + return vb2_dqbuf(&fimc->vid_cap.vbq, buf, file->f_flags & O_NONBLOCK); + } + +-static int fimc_cap_cropcap(struct file *file, void *fh, +- struct v4l2_cropcap *cr) ++static int fimc_cap_create_bufs(struct file *file, void *priv, ++ struct v4l2_create_buffers *create) + { + struct fimc_dev *fimc = video_drvdata(file); +- struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame; + +- if (cr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) +- return -EINVAL; ++ return vb2_create_bufs(&fimc->vid_cap.vbq, create); ++} + +- cr->bounds.left = 0; +- cr->bounds.top = 0; +- cr->bounds.width = f->o_width; +- cr->bounds.height = f->o_height; +- cr->defrect = cr->bounds; ++static int fimc_cap_prepare_buf(struct file *file, void *priv, ++ struct v4l2_buffer *b) ++{ ++ struct fimc_dev *fimc = video_drvdata(file); + +- return 0; ++ return vb2_prepare_buf(&fimc->vid_cap.vbq, b); + } + +-static int fimc_cap_g_crop(struct file *file, void *fh, struct v4l2_crop *cr) ++static int fimc_cap_g_selection(struct file *file, void *fh, ++ struct v4l2_selection *s) + { + struct fimc_dev *fimc = video_drvdata(file); +- struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame; ++ struct fimc_ctx *ctx = fimc->vid_cap.ctx; ++ struct fimc_frame *f = &ctx->s_frame; + +- cr->c.left = f->offs_h; +- cr->c.top = f->offs_v; +- cr->c.width = f->width; +- cr->c.height = f->height; ++ if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) ++ return -EINVAL; + +- return 0; ++ switch (s->target) { ++ case V4L2_SEL_TGT_COMPOSE_DEFAULT: ++ case V4L2_SEL_TGT_COMPOSE_BOUNDS: ++ f = &ctx->d_frame; ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ s->r.left = 0; ++ s->r.top = 0; ++ s->r.width = f->o_width; ++ s->r.height = f->o_height; ++ return 0; ++ ++ case V4L2_SEL_TGT_COMPOSE_ACTIVE: ++ f = &ctx->d_frame; ++ case V4L2_SEL_TGT_CROP_ACTIVE: ++ s->r.left = f->offs_h; ++ s->r.top = f->offs_v; ++ s->r.width = f->width; ++ s->r.height = f->height; ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++/* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */ ++int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b) ++{ ++ if (a->left < b->left || a->top < b->top) ++ return 0; ++ if (a->left + a->width > b->left + b->width) ++ return 0; ++ if (a->top + a->height > b->top + b->height) ++ return 0; ++ ++ return 1; + } + +-static int fimc_cap_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) ++static int fimc_cap_s_selection(struct file *file, void *fh, ++ struct v4l2_selection *s) + { + struct fimc_dev *fimc = video_drvdata(file); + struct fimc_ctx *ctx = fimc->vid_cap.ctx; +- struct fimc_frame *ff; ++ struct v4l2_rect rect = s->r; ++ struct fimc_frame *f; + unsigned long flags; ++ unsigned int pad; ++ ++ if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) ++ return -EINVAL; ++ ++ switch (s->target) { ++ case V4L2_SEL_TGT_COMPOSE_DEFAULT: ++ case V4L2_SEL_TGT_COMPOSE_BOUNDS: ++ case V4L2_SEL_TGT_COMPOSE_ACTIVE: ++ f = &ctx->d_frame; ++ pad = FIMC_SD_PAD_SOURCE; ++ break; ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ case V4L2_SEL_TGT_CROP_ACTIVE: ++ f = &ctx->s_frame; ++ pad = FIMC_SD_PAD_SINK; ++ break; ++ default: ++ return -EINVAL; ++ } + +- fimc_capture_try_crop(ctx, &cr->c, FIMC_SD_PAD_SINK); +- ff = &ctx->s_frame; ++ fimc_capture_try_crop(ctx, &rect, pad); + ++ if (s->flags & V4L2_SEL_FLAG_LE && ++ !enclosed_rectangle(&rect, &s->r)) ++ return -ERANGE; ++ ++ if (s->flags & V4L2_SEL_FLAG_GE && ++ !enclosed_rectangle(&s->r, &rect)) ++ return -ERANGE; ++ ++ s->r = rect; + spin_lock_irqsave(&fimc->slock, flags); +- set_frame_crop(ff, cr->c.left, cr->c.top, cr->c.width, cr->c.height); +- set_bit(ST_CAPT_APPLY_CFG, &fimc->state); ++ set_frame_crop(f, s->r.left, s->r.top, s->r.width, ++ s->r.height); + spin_unlock_irqrestore(&fimc->slock, flags); + ++ set_bit(ST_CAPT_APPLY_CFG, &fimc->state); + return 0; + } + +@@ -1082,12 +1147,14 @@ static const struct v4l2_ioctl_ops fimc_ + .vidioc_qbuf = fimc_cap_qbuf, + .vidioc_dqbuf = fimc_cap_dqbuf, + ++ .vidioc_prepare_buf = fimc_cap_prepare_buf, ++ .vidioc_create_bufs = fimc_cap_create_bufs, ++ + .vidioc_streamon = fimc_cap_streamon, + .vidioc_streamoff = fimc_cap_streamoff, + +- .vidioc_g_crop = fimc_cap_g_crop, +- .vidioc_s_crop = fimc_cap_s_crop, +- .vidioc_cropcap = fimc_cap_cropcap, ++ .vidioc_g_selection = fimc_cap_g_selection, ++ .vidioc_s_selection = fimc_cap_s_selection, + + .vidioc_enum_input = fimc_cap_enum_input, + .vidioc_s_input = fimc_cap_s_input, +Index: linux-3.3.x86_64/drivers/media/video/videobuf2-vmalloc.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/videobuf2-vmalloc.c ++++ linux-3.3.x86_64/drivers/media/video/videobuf2-vmalloc.c +@@ -10,6 +10,7 @@ + * the Free Software Foundation. + */ + ++#include + #include + #include + #include +@@ -22,6 +23,7 @@ + struct vb2_vmalloc_buf { + void *vaddr; + struct page **pages; ++ struct vm_area_struct *vma; + int write; + unsigned long size; + unsigned int n_pages; +@@ -71,6 +73,8 @@ static void *vb2_vmalloc_get_userptr(voi + struct vb2_vmalloc_buf *buf; + unsigned long first, last; + int n_pages, offset; ++ struct vm_area_struct *vma; ++ dma_addr_t physp; + + buf = kzalloc(sizeof(*buf), GFP_KERNEL); + if (!buf) +@@ -80,23 +84,37 @@ static void *vb2_vmalloc_get_userptr(voi + offset = vaddr & ~PAGE_MASK; + buf->size = size; + +- first = vaddr >> PAGE_SHIFT; +- last = (vaddr + size - 1) >> PAGE_SHIFT; +- buf->n_pages = last - first + 1; +- buf->pages = kzalloc(buf->n_pages * sizeof(struct page *), GFP_KERNEL); +- if (!buf->pages) +- goto fail_pages_array_alloc; +- +- /* current->mm->mmap_sem is taken by videobuf2 core */ +- n_pages = get_user_pages(current, current->mm, vaddr & PAGE_MASK, +- buf->n_pages, write, 1, /* force */ +- buf->pages, NULL); +- if (n_pages != buf->n_pages) +- goto fail_get_user_pages; +- +- buf->vaddr = vm_map_ram(buf->pages, buf->n_pages, -1, PAGE_KERNEL); +- if (!buf->vaddr) +- goto fail_get_user_pages; ++ ++ vma = find_vma(current->mm, vaddr); ++ if (vma && (vma->vm_flags & VM_PFNMAP) && (vma->vm_pgoff)) { ++ if (vb2_get_contig_userptr(vaddr, size, &vma, &physp)) ++ goto fail_pages_array_alloc; ++ buf->vma = vma; ++ buf->vaddr = ioremap_nocache(physp, size); ++ if (!buf->vaddr) ++ goto fail_pages_array_alloc; ++ } else { ++ first = vaddr >> PAGE_SHIFT; ++ last = (vaddr + size - 1) >> PAGE_SHIFT; ++ buf->n_pages = last - first + 1; ++ buf->pages = kzalloc(buf->n_pages * sizeof(struct page *), ++ GFP_KERNEL); ++ if (!buf->pages) ++ goto fail_pages_array_alloc; ++ ++ /* current->mm->mmap_sem is taken by videobuf2 core */ ++ n_pages = get_user_pages(current, current->mm, ++ vaddr & PAGE_MASK, buf->n_pages, ++ write, 1, /* force */ ++ buf->pages, NULL); ++ if (n_pages != buf->n_pages) ++ goto fail_get_user_pages; ++ ++ buf->vaddr = vm_map_ram(buf->pages, buf->n_pages, -1, ++ PAGE_KERNEL); ++ if (!buf->vaddr) ++ goto fail_get_user_pages; ++ } + + buf->vaddr += offset; + return buf; +@@ -120,14 +138,20 @@ static void vb2_vmalloc_put_userptr(void + unsigned long vaddr = (unsigned long)buf->vaddr & PAGE_MASK; + unsigned int i; + +- if (vaddr) +- vm_unmap_ram((void *)vaddr, buf->n_pages); +- for (i = 0; i < buf->n_pages; ++i) { +- if (buf->write) +- set_page_dirty_lock(buf->pages[i]); +- put_page(buf->pages[i]); ++ if (buf->pages) { ++ if (vaddr) ++ vm_unmap_ram((void *)vaddr, buf->n_pages); ++ for (i = 0; i < buf->n_pages; ++i) { ++ if (buf->write) ++ set_page_dirty_lock(buf->pages[i]); ++ put_page(buf->pages[i]); ++ } ++ kfree(buf->pages); ++ } else { ++ if (buf->vma) ++ vb2_put_vma(buf->vma); ++ iounmap(buf->vaddr); + } +- kfree(buf->pages); + kfree(buf); + } + +Index: linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-g2d/g2d.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d.c +@@ -178,6 +178,9 @@ static int g2d_s_ctrl(struct v4l2_ctrl * + { + struct g2d_ctx *ctx = container_of(ctrl->handler, struct g2d_ctx, + ctrl_handler); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ctx->dev->ctrl_lock, flags); + switch (ctrl->id) { + case V4L2_CID_COLORFX: + if (ctrl->val == V4L2_COLORFX_NEGATIVE) +@@ -185,10 +188,13 @@ static int g2d_s_ctrl(struct v4l2_ctrl * + else + ctx->rop = ROP4_COPY; + break; +- default: +- v4l2_err(&ctx->dev->v4l2_dev, "unknown control\n"); +- return -EINVAL; ++ ++ case V4L2_CID_HFLIP: ++ ctx->flip = ctx->ctrl_hflip->val | (ctx->ctrl_vflip->val << 1); ++ break; ++ + } ++ spin_unlock_irqrestore(&ctx->dev->ctrl_lock, flags); + return 0; + } + +@@ -200,11 +206,13 @@ int g2d_setup_ctrls(struct g2d_ctx *ctx) + { + struct g2d_dev *dev = ctx->dev; + +- v4l2_ctrl_handler_init(&ctx->ctrl_handler, 1); +- if (ctx->ctrl_handler.error) { +- v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n"); +- return ctx->ctrl_handler.error; +- } ++ v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3); ++ ++ ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &g2d_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ ++ ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &g2d_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); + + v4l2_ctrl_new_std_menu( + &ctx->ctrl_handler, +@@ -215,10 +223,14 @@ int g2d_setup_ctrls(struct g2d_ctx *ctx) + V4L2_COLORFX_NONE); + + if (ctx->ctrl_handler.error) { +- v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n"); +- return ctx->ctrl_handler.error; ++ int err = ctx->ctrl_handler.error; ++ v4l2_err(&dev->v4l2_dev, "g2d_setup_ctrls failed\n"); ++ v4l2_ctrl_handler_free(&ctx->ctrl_handler); ++ return err; + } + ++ v4l2_ctrl_cluster(2, &ctx->ctrl_hflip); ++ + return 0; + } + +@@ -547,6 +559,7 @@ static void device_run(void *prv) + struct g2d_ctx *ctx = prv; + struct g2d_dev *dev = ctx->dev; + struct vb2_buffer *src, *dst; ++ unsigned long flags; + u32 cmd = 0; + + dev->curr = ctx; +@@ -557,6 +570,8 @@ static void device_run(void *prv) + clk_enable(dev->gate); + g2d_reset(dev); + ++ spin_lock_irqsave(&dev->ctrl_lock, flags); ++ + g2d_set_src_size(dev, &ctx->in); + g2d_set_src_addr(dev, vb2_dma_contig_plane_dma_addr(src, 0)); + +@@ -564,11 +579,15 @@ static void device_run(void *prv) + g2d_set_dst_addr(dev, vb2_dma_contig_plane_dma_addr(dst, 0)); + + g2d_set_rop4(dev, ctx->rop); ++ g2d_set_flip(dev, ctx->flip); ++ + if (ctx->in.c_width != ctx->out.c_width || + ctx->in.c_height != ctx->out.c_height) + cmd |= g2d_cmd_stretch(1); + g2d_set_cmd(dev, cmd); + g2d_start(dev); ++ ++ spin_unlock_irqrestore(&dev->ctrl_lock, flags); + } + + static irqreturn_t g2d_isr(int irq, void *prv) +@@ -658,7 +677,7 @@ static int g2d_probe(struct platform_dev + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; +- spin_lock_init(&dev->irqlock); ++ spin_lock_init(&dev->ctrl_lock); + mutex_init(&dev->mutex); + atomic_set(&dev->num_inst, 0); + init_waitqueue_head(&dev->irq_queue); +@@ -693,18 +712,30 @@ static int g2d_probe(struct platform_dev + goto unmap_regs; + } + ++ ret = clk_prepare(dev->clk); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to prepare g2d clock\n"); ++ goto put_clk; ++ } ++ + dev->gate = clk_get(&pdev->dev, "fimg2d"); + if (IS_ERR_OR_NULL(dev->gate)) { + dev_err(&pdev->dev, "failed to get g2d clock gate\n"); + ret = -ENXIO; +- goto put_clk; ++ goto unprep_clk; ++ } ++ ++ ret = clk_prepare(dev->gate); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to prepare g2d clock gate\n"); ++ goto put_clk_gate; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(&pdev->dev, "failed to find IRQ\n"); + ret = -ENXIO; +- goto put_clk_gate; ++ goto unprep_clk_gate; + } + + dev->irq = res->start; +@@ -764,8 +795,12 @@ alloc_ctx_cleanup: + vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); + rel_irq: + free_irq(dev->irq, dev); ++unprep_clk_gate: ++ clk_unprepare(dev->gate); + put_clk_gate: + clk_put(dev->gate); ++unprep_clk: ++ clk_unprepare(dev->clk); + put_clk: + clk_put(dev->clk); + unmap_regs: +@@ -787,7 +822,9 @@ static int g2d_remove(struct platform_de + v4l2_device_unregister(&dev->v4l2_dev); + vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); + free_irq(dev->irq, dev); ++ clk_unprepare(dev->gate); + clk_put(dev->gate); ++ clk_unprepare(dev->clk); + clk_put(dev->clk); + iounmap(dev->regs); + release_resource(dev->res_regs); +Index: linux-3.3.x86_64/drivers/media/video/s5p-mfc/s5p_mfc_pm.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-mfc/s5p_mfc_pm.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-mfc/s5p_mfc_pm.c +@@ -41,15 +41,29 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev * + pm->clock_gate = clk_get(&dev->plat_dev->dev, MFC_GATE_CLK_NAME); + if (IS_ERR(pm->clock_gate)) { + mfc_err("Failed to get clock-gating control\n"); +- ret = -ENOENT; ++ ret = PTR_ERR(pm->clock_gate); + goto err_g_ip_clk; + } ++ ++ ret = clk_prepare(pm->clock_gate); ++ if (ret) { ++ mfc_err("Failed to preapre clock-gating control\n"); ++ goto err_p_ip_clk; ++ } ++ + pm->clock = clk_get(&dev->plat_dev->dev, MFC_CLKNAME); + if (IS_ERR(pm->clock)) { + mfc_err("Failed to get MFC clock\n"); +- ret = -ENOENT; ++ ret = PTR_ERR(pm->clock); + goto err_g_ip_clk_2; + } ++ ++ ret = clk_prepare(pm->clock); ++ if (ret) { ++ mfc_err("Failed to prepare MFC clock\n"); ++ goto err_p_ip_clk_2; ++ } ++ + atomic_set(&pm->power, 0); + #ifdef CONFIG_PM_RUNTIME + pm->device = &dev->plat_dev->dev; +@@ -59,7 +73,11 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev * + atomic_set(&clk_ref, 0); + #endif + return 0; ++err_p_ip_clk_2: ++ clk_put(pm->clock); + err_g_ip_clk_2: ++ clk_unprepare(pm->clock_gate); ++err_p_ip_clk: + clk_put(pm->clock_gate); + err_g_ip_clk: + return ret; +@@ -67,7 +85,9 @@ err_g_ip_clk: + + void s5p_mfc_final_pm(struct s5p_mfc_dev *dev) + { ++ clk_unprepare(pm->clock_gate); + clk_put(pm->clock_gate); ++ clk_unprepare(pm->clock); + clk_put(pm->clock); + #ifdef CONFIG_PM_RUNTIME + pm_runtime_disable(pm->device); +Index: linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d-hw.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-g2d/g2d-hw.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d-hw.c +@@ -77,6 +77,11 @@ void g2d_set_rop4(struct g2d_dev *d, u32 + w(r, ROP4_REG); + } + ++void g2d_set_flip(struct g2d_dev *d, u32 r) ++{ ++ w(r, SRC_MSK_DIRECT_REG); ++} ++ + u32 g2d_cmd_stretch(u32 e) + { + e &= 1; +Index: linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-g2d/g2d.h ++++ linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d.h +@@ -20,7 +20,7 @@ struct g2d_dev { + struct v4l2_m2m_dev *m2m_dev; + struct video_device *vfd; + struct mutex mutex; +- spinlock_t irqlock; ++ spinlock_t ctrl_lock; + atomic_t num_inst; + struct vb2_alloc_ctx *alloc_ctx; + struct resource *res_regs; +@@ -57,8 +57,11 @@ struct g2d_ctx { + struct v4l2_m2m_ctx *m2m_ctx; + struct g2d_frame in; + struct g2d_frame out; ++ struct v4l2_ctrl *ctrl_hflip; ++ struct v4l2_ctrl *ctrl_vflip; + struct v4l2_ctrl_handler ctrl_handler; + u32 rop; ++ u32 flip; + }; + + struct g2d_fmt { +@@ -77,6 +80,7 @@ void g2d_set_dst_addr(struct g2d_dev *d, + void g2d_start(struct g2d_dev *d); + void g2d_clear_int(struct g2d_dev *d); + void g2d_set_rop4(struct g2d_dev *d, u32 r); ++void g2d_set_flip(struct g2d_dev *d, u32 r); + u32 g2d_cmd_stretch(u32 e); + void g2d_set_cmd(struct g2d_dev *d, u32 c); + +Index: linux-3.3.x86_64/drivers/media/video/s5k6aa.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5k6aa.c ++++ linux-3.3.x86_64/drivers/media/video/s5k6aa.c +@@ -1582,8 +1582,8 @@ static int s5k6aa_probe(struct i2c_clien + s5k6aa->inv_vflip = pdata->vert_flip; + + sd = &s5k6aa->sd; +- strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name)); + v4l2_i2c_subdev_init(sd, client, &s5k6aa_subdev_ops); ++ strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name)); + + sd->internal_ops = &s5k6aa_subdev_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; +@@ -1663,18 +1663,7 @@ static struct i2c_driver s5k6aa_i2c_driv + .id_table = s5k6aa_id, + }; + +-static int __init s5k6aa_init(void) +-{ +- return i2c_add_driver(&s5k6aa_i2c_driver); +-} +- +-static void __exit s5k6aa_exit(void) +-{ +- i2c_del_driver(&s5k6aa_i2c_driver); +-} +- +-module_init(s5k6aa_init); +-module_exit(s5k6aa_exit); ++module_i2c_driver(s5k6aa_i2c_driver); + + MODULE_DESCRIPTION("Samsung S5K6AA(FX) SXGA camera driver"); + MODULE_AUTHOR("Sylwester Nawrocki "); +Index: linux-3.3.x86_64/drivers/media/video/noon010pc30.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/noon010pc30.c ++++ linux-3.3.x86_64/drivers/media/video/noon010pc30.c +@@ -725,8 +725,8 @@ static int noon010_probe(struct i2c_clie + + mutex_init(&info->lock); + sd = &info->sd; +- strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); + v4l2_i2c_subdev_init(sd, client, &noon010_ops); ++ strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); + + sd->internal_ops = &noon010_subdev_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; +@@ -844,18 +844,7 @@ static struct i2c_driver noon010_i2c_dri + .id_table = noon010_id, + }; + +-static int __init noon010_init(void) +-{ +- return i2c_add_driver(&noon010_i2c_driver); +-} +- +-static void __exit noon010_exit(void) +-{ +- i2c_del_driver(&noon010_i2c_driver); +-} +- +-module_init(noon010_init); +-module_exit(noon010_exit); ++module_i2c_driver(noon010_i2c_driver); + + MODULE_DESCRIPTION("Siliconfile NOON010PC30 camera driver"); + MODULE_AUTHOR("Sylwester Nawrocki "); +Index: linux-3.3.x86_64/drivers/media/video/m5mols/m5mols_core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/m5mols/m5mols_core.c ++++ linux-3.3.x86_64/drivers/media/video/m5mols/m5mols_core.c +@@ -982,8 +982,8 @@ static int __devinit m5mols_probe(struct + } + + sd = &info->sd; +- strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); + v4l2_i2c_subdev_init(sd, client, &m5mols_ops); ++ strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + sd->internal_ops = &m5mols_subdev_internal_ops; +@@ -1057,18 +1057,7 @@ static struct i2c_driver m5mols_i2c_driv + .id_table = m5mols_id, + }; + +-static int __init m5mols_mod_init(void) +-{ +- return i2c_add_driver(&m5mols_i2c_driver); +-} +- +-static void __exit m5mols_mod_exit(void) +-{ +- i2c_del_driver(&m5mols_i2c_driver); +-} +- +-module_init(m5mols_mod_init); +-module_exit(m5mols_mod_exit); ++module_i2c_driver(m5mols_i2c_driver); + + MODULE_AUTHOR("HeungJun Kim "); + MODULE_AUTHOR("Dongsoo Kim "); +Index: linux-3.3.x86_64/Documentation/video4linux/gspca.txt +=================================================================== +--- linux-3.3.x86_64.orig/Documentation/video4linux/gspca.txt ++++ linux-3.3.x86_64/Documentation/video4linux/gspca.txt +@@ -217,6 +217,7 @@ ov534_9 06f8:3003 Hercules Dualpix HD W + sonixj 06f8:3004 Hercules Classic Silver + sonixj 06f8:3008 Hercules Deluxe Optical Glass + pac7302 06f8:3009 Hercules Classic Link ++pac7302 06f8:301b Hercules Link + nw80x 0728:d001 AVerMedia Camguard + spca508 0733:0110 ViewQuest VQ110 + spca501 0733:0401 Intel Create and Share +Index: linux-3.3.x86_64/drivers/media/video/gspca/pac7302.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/gspca/pac7302.c ++++ linux-3.3.x86_64/drivers/media/video/gspca/pac7302.c +@@ -1,8 +1,8 @@ + /* +- * Pixart PAC7302 library +- * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li ++ * Pixart PAC7302 driver + * +- * V4L2 by Jean-Francois Moine ++ * Copyright (C) 2008-2012 Jean-Francois Moine ++ * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li + * + * Separated from Pixart PAC7311 library by Márton Németh + * Camera button input handling by Márton Németh +@@ -63,67 +63,61 @@ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +-#define MODULE_NAME "pac7302" +- + #include + #include + #include "gspca.h" ++/* Include pac common sof detection functions */ ++#include "pac_common.h" + +-MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); ++MODULE_AUTHOR("Jean-Francois Moine , " ++ "Thomas Kaiser thomas@kaiser-linux.li"); + MODULE_DESCRIPTION("Pixart PAC7302"); + MODULE_LICENSE("GPL"); + ++enum e_ctrl { ++ BRIGHTNESS, ++ CONTRAST, ++ COLORS, ++ WHITE_BALANCE, ++ RED_BALANCE, ++ BLUE_BALANCE, ++ GAIN, ++ AUTOGAIN, ++ EXPOSURE, ++ VFLIP, ++ HFLIP, ++ NCTRLS /* number of controls */ ++}; ++ + /* specific webcam descriptor for pac7302 */ + struct sd { + struct gspca_dev gspca_dev; /* !! must be the first item */ + +- unsigned char brightness; +- unsigned char contrast; +- unsigned char colors; +- unsigned char white_balance; +- unsigned char red_balance; +- unsigned char blue_balance; +- unsigned char gain; +- unsigned char autogain; +- unsigned short exposure; +- __u8 hflip; +- __u8 vflip; ++ struct gspca_ctrl ctrls[NCTRLS]; ++ + u8 flags; + #define FL_HFLIP 0x01 /* mirrored by default */ + #define FL_VFLIP 0x02 /* vertical flipped by default */ + + u8 sof_read; +- u8 autogain_ignore_frames; ++ s8 autogain_ignore_frames; + + atomic_t avg_lum; + }; + + /* V4L2 controls supported by the driver */ +-static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); ++static void setbrightcont(struct gspca_dev *gspca_dev); ++static void setcolors(struct gspca_dev *gspca_dev); ++static void setwhitebalance(struct gspca_dev *gspca_dev); ++static void setredbalance(struct gspca_dev *gspca_dev); ++static void setbluebalance(struct gspca_dev *gspca_dev); ++static void setgain(struct gspca_dev *gspca_dev); ++static void setexposure(struct gspca_dev *gspca_dev); ++static void setautogain(struct gspca_dev *gspca_dev); ++static void sethvflip(struct gspca_dev *gspca_dev); + + static const struct ctrl sd_ctrls[] = { +- { ++[BRIGHTNESS] = { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, +@@ -132,13 +126,11 @@ static const struct ctrl sd_ctrls[] = { + #define BRIGHTNESS_MAX 0x20 + .maximum = BRIGHTNESS_MAX, + .step = 1, +-#define BRIGHTNESS_DEF 0x10 +- .default_value = BRIGHTNESS_DEF, ++ .default_value = 0x10, + }, +- .set = sd_setbrightness, +- .get = sd_getbrightness, ++ .set_control = setbrightcont + }, +- { ++[CONTRAST] = { + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, +@@ -147,13 +139,11 @@ static const struct ctrl sd_ctrls[] = { + #define CONTRAST_MAX 255 + .maximum = CONTRAST_MAX, + .step = 1, +-#define CONTRAST_DEF 127 +- .default_value = CONTRAST_DEF, ++ .default_value = 127, + }, +- .set = sd_setcontrast, +- .get = sd_getcontrast, ++ .set_control = setbrightcont + }, +- { ++[COLORS] = { + { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, +@@ -162,13 +152,11 @@ static const struct ctrl sd_ctrls[] = { + #define COLOR_MAX 255 + .maximum = COLOR_MAX, + .step = 1, +-#define COLOR_DEF 127 +- .default_value = COLOR_DEF, ++ .default_value = 127 + }, +- .set = sd_setcolors, +- .get = sd_getcolors, ++ .set_control = setcolors + }, +- { ++[WHITE_BALANCE] = { + { + .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, + .type = V4L2_CTRL_TYPE_INTEGER, +@@ -176,13 +164,11 @@ static const struct ctrl sd_ctrls[] = { + .minimum = 0, + .maximum = 255, + .step = 1, +-#define WHITEBALANCE_DEF 4 +- .default_value = WHITEBALANCE_DEF, ++ .default_value = 4, + }, +- .set = sd_setwhitebalance, +- .get = sd_getwhitebalance, ++ .set_control = setwhitebalance + }, +- { ++[RED_BALANCE] = { + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, +@@ -190,13 +176,11 @@ static const struct ctrl sd_ctrls[] = { + .minimum = 0, + .maximum = 3, + .step = 1, +-#define REDBALANCE_DEF 1 +- .default_value = REDBALANCE_DEF, ++ .default_value = 1, + }, +- .set = sd_setredbalance, +- .get = sd_getredbalance, ++ .set_control = setredbalance + }, +- { ++[BLUE_BALANCE] = { + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, +@@ -204,29 +188,25 @@ static const struct ctrl sd_ctrls[] = { + .minimum = 0, + .maximum = 3, + .step = 1, +-#define BLUEBALANCE_DEF 1 +- .default_value = BLUEBALANCE_DEF, ++ .default_value = 1, + }, +- .set = sd_setbluebalance, +- .get = sd_getbluebalance, ++ .set_control = setbluebalance + }, +- { ++[GAIN] = { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, +-#define GAIN_MAX 255 +- .maximum = GAIN_MAX, ++ .maximum = 255, + .step = 1, + #define GAIN_DEF 127 + #define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */ + .default_value = GAIN_DEF, + }, +- .set = sd_setgain, +- .get = sd_getgain, ++ .set_control = setgain + }, +- { ++[EXPOSURE] = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, +@@ -238,10 +218,9 @@ static const struct ctrl sd_ctrls[] = { + #define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */ + .default_value = EXPOSURE_DEF, + }, +- .set = sd_setexposure, +- .get = sd_getexposure, ++ .set_control = setexposure + }, +- { ++[AUTOGAIN] = { + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, +@@ -252,10 +231,9 @@ static const struct ctrl sd_ctrls[] = { + #define AUTOGAIN_DEF 1 + .default_value = AUTOGAIN_DEF, + }, +- .set = sd_setautogain, +- .get = sd_getautogain, ++ .set_control = setautogain, + }, +- { ++[HFLIP] = { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, +@@ -263,13 +241,11 @@ static const struct ctrl sd_ctrls[] = { + .minimum = 0, + .maximum = 1, + .step = 1, +-#define HFLIP_DEF 0 +- .default_value = HFLIP_DEF, ++ .default_value = 0, + }, +- .set = sd_sethflip, +- .get = sd_gethflip, ++ .set_control = sethvflip, + }, +- { ++[VFLIP] = { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, +@@ -277,11 +253,9 @@ static const struct ctrl sd_ctrls[] = { + .minimum = 0, + .maximum = 1, + .step = 1, +-#define VFLIP_DEF 0 +- .default_value = VFLIP_DEF, ++ .default_value = 0, + }, +- .set = sd_setvflip, +- .get = sd_getvflip, ++ .set_control = sethvflip + }, + }; + +@@ -290,21 +264,21 @@ static const struct v4l2_pix_format vga_ + .bytesperline = 640, + .sizeimage = 640 * 480 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, +- .priv = 0}, ++ }, + }; + + #define LOAD_PAGE3 255 + #define END_OF_SEQUENCE 0 + + /* pac 7302 */ +-static const __u8 init_7302[] = { ++static const u8 init_7302[] = { + /* index,value */ + 0xff, 0x01, /* page 1 */ + 0x78, 0x00, /* deactivate */ + 0xff, 0x01, + 0x78, 0x40, /* led off */ + }; +-static const __u8 start_7302[] = { ++static const u8 start_7302[] = { + /* index, len, [value]* */ + 0xff, 1, 0x00, /* page 0 */ + 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, +@@ -319,7 +293,7 @@ static const __u8 start_7302[] = { + 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11, + 0x00, 0x54, 0x11, + 0x55, 1, 0x00, +- 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, ++ 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, + 0x6b, 1, 0x00, + 0x6e, 3, 0x08, 0x06, 0x00, + 0x72, 3, 0x00, 0xff, 0x00, +@@ -370,7 +344,7 @@ static const __u8 start_7302[] = { + + #define SKIP 0xaa + /* page 3 - the value SKIP says skip the index - see reg_w_page() */ +-static const __u8 page3_7302[] = { ++static const u8 page3_7302[] = { + 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16, + 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, + 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +@@ -394,7 +368,7 @@ static const __u8 page3_7302[] = { + }; + + static void reg_w_buf(struct gspca_dev *gspca_dev, +- __u8 index, ++ u8 index, + const u8 *buffer, int len) + { + int ret; +@@ -410,7 +384,7 @@ static void reg_w_buf(struct gspca_dev * + index, gspca_dev->usb_buf, len, + 500); + if (ret < 0) { +- pr_err("reg_w_buf failed index 0x%02x, error %d\n", ++ pr_err("reg_w_buf failed i: %02x error %d\n", + index, ret); + gspca_dev->usb_err = ret; + } +@@ -418,8 +392,8 @@ static void reg_w_buf(struct gspca_dev * + + + static void reg_w(struct gspca_dev *gspca_dev, +- __u8 index, +- __u8 value) ++ u8 index, ++ u8 value) + { + int ret; + +@@ -433,14 +407,14 @@ static void reg_w(struct gspca_dev *gspc + 0, index, gspca_dev->usb_buf, 1, + 500); + if (ret < 0) { +- pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n", ++ pr_err("reg_w() failed i: %02x v: %02x error %d\n", + index, value, ret); + gspca_dev->usb_err = ret; + } + } + + static void reg_w_seq(struct gspca_dev *gspca_dev, +- const __u8 *seq, int len) ++ const u8 *seq, int len) + { + while (--len >= 0) { + reg_w(gspca_dev, seq[0], seq[1]); +@@ -450,7 +424,7 @@ static void reg_w_seq(struct gspca_dev * + + /* load the beginning of a page */ + static void reg_w_page(struct gspca_dev *gspca_dev, +- const __u8 *page, int len) ++ const u8 *page, int len) + { + int index; + int ret = 0; +@@ -468,7 +442,7 @@ static void reg_w_page(struct gspca_dev + 0, index, gspca_dev->usb_buf, 1, + 500); + if (ret < 0) { +- pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n", ++ pr_err("reg_w_page() failed i: %02x v: %02x error %d\n", + index, page[index], ret); + gspca_dev->usb_err = ret; + break; +@@ -478,8 +452,8 @@ static void reg_w_page(struct gspca_dev + + /* output a variable sequence */ + static void reg_w_var(struct gspca_dev *gspca_dev, +- const __u8 *seq, +- const __u8 *page3, unsigned int page3_len) ++ const u8 *seq, ++ const u8 *page3, unsigned int page3_len) + { + int index, len; + +@@ -493,11 +467,13 @@ static void reg_w_var(struct gspca_dev * + reg_w_page(gspca_dev, page3, page3_len); + break; + default: ++#ifdef GSPCA_DEBUG + if (len > USB_BUF_SZ) { + PDEBUG(D_ERR|D_STREAM, + "Incorrect variable sequence"); + return; + } ++#endif + while (len > 0) { + if (len < 8) { + reg_w_buf(gspca_dev, +@@ -524,21 +500,11 @@ static int sd_config(struct gspca_dev *g + + cam = &gspca_dev->cam; + +- PDEBUG(D_CONF, "Find Sensor PAC7302"); + cam->cam_mode = vga_mode; /* only 640x480 */ + cam->nmodes = ARRAY_SIZE(vga_mode); + +- sd->brightness = BRIGHTNESS_DEF; +- sd->contrast = CONTRAST_DEF; +- sd->colors = COLOR_DEF; +- sd->white_balance = WHITEBALANCE_DEF; +- sd->red_balance = REDBALANCE_DEF; +- sd->blue_balance = BLUEBALANCE_DEF; +- sd->gain = GAIN_DEF; +- sd->exposure = EXPOSURE_DEF; +- sd->autogain = AUTOGAIN_DEF; +- sd->hflip = HFLIP_DEF; +- sd->vflip = VFLIP_DEF; ++ gspca_dev->cam.ctrls = sd->ctrls; ++ + sd->flags = id->driver_info; + return 0; + } +@@ -548,19 +514,19 @@ static void setbrightcont(struct gspca_d + { + struct sd *sd = (struct sd *) gspca_dev; + int i, v; +- static const __u8 max[10] = ++ static const u8 max[10] = + {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, + 0xd4, 0xec}; +- static const __u8 delta[10] = ++ static const u8 delta[10] = + {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, + 0x11, 0x0b}; + + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + for (i = 0; i < 10; i++) { + v = max[i]; +- v += (sd->brightness - BRIGHTNESS_MAX) ++ v += (sd->ctrls[BRIGHTNESS].val - BRIGHTNESS_MAX) + * 150 / BRIGHTNESS_MAX; /* 200 ? */ +- v -= delta[i] * sd->contrast / CONTRAST_MAX; ++ v -= delta[i] * sd->ctrls[CONTRAST].val / CONTRAST_MAX; + if (v < 0) + v = 0; + else if (v > 0xff) +@@ -584,12 +550,11 @@ static void setcolors(struct gspca_dev * + reg_w(gspca_dev, 0x11, 0x01); + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + for (i = 0; i < 9; i++) { +- v = a[i] * sd->colors / COLOR_MAX + b[i]; ++ v = a[i] * sd->ctrls[COLORS].val / COLOR_MAX + b[i]; + reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); + reg_w(gspca_dev, 0x0f + 2 * i + 1, v); + } + reg_w(gspca_dev, 0xdc, 0x01); +- PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); + } + + static void setwhitebalance(struct gspca_dev *gspca_dev) +@@ -597,10 +562,9 @@ static void setwhitebalance(struct gspca + struct sd *sd = (struct sd *) gspca_dev; + + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ +- reg_w(gspca_dev, 0xc6, sd->white_balance); ++ reg_w(gspca_dev, 0xc6, sd->ctrls[WHITE_BALANCE].val); + + reg_w(gspca_dev, 0xdc, 0x01); +- PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance); + } + + static void setredbalance(struct gspca_dev *gspca_dev) +@@ -608,10 +572,9 @@ static void setredbalance(struct gspca_d + struct sd *sd = (struct sd *) gspca_dev; + + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ +- reg_w(gspca_dev, 0xc5, sd->red_balance); ++ reg_w(gspca_dev, 0xc5, sd->ctrls[RED_BALANCE].val); + + reg_w(gspca_dev, 0xdc, 0x01); +- PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance); + } + + static void setbluebalance(struct gspca_dev *gspca_dev) +@@ -619,10 +582,9 @@ static void setbluebalance(struct gspca_ + struct sd *sd = (struct sd *) gspca_dev; + + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ +- reg_w(gspca_dev, 0xc7, sd->blue_balance); ++ reg_w(gspca_dev, 0xc7, sd->ctrls[BLUE_BALANCE].val); + + reg_w(gspca_dev, 0xdc, 0x01); +- PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance); + } + + static void setgain(struct gspca_dev *gspca_dev) +@@ -630,7 +592,7 @@ static void setgain(struct gspca_dev *gs + struct sd *sd = (struct sd *) gspca_dev; + + reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ +- reg_w(gspca_dev, 0x10, sd->gain >> 3); ++ reg_w(gspca_dev, 0x10, sd->ctrls[GAIN].val >> 3); + + /* load registers to sensor (Bit 0, auto clear) */ + reg_w(gspca_dev, 0x11, 0x01); +@@ -639,13 +601,13 @@ static void setgain(struct gspca_dev *gs + static void setexposure(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- __u8 clockdiv; +- __u16 exposure; ++ u8 clockdiv; ++ u16 exposure; + + /* register 2 of frame 3 contains the clock divider configuring the + no fps according to the formula: 90 / reg. sd->exposure is the + desired exposure time in 0.5 ms. */ +- clockdiv = (90 * sd->exposure + 1999) / 2000; ++ clockdiv = (90 * sd->ctrls[EXPOSURE].val + 1999) / 2000; + + /* Note clockdiv = 3 also works, but when running at 30 fps, depending + on the scene being recorded, the camera switches to another +@@ -664,7 +626,7 @@ static void setexposure(struct gspca_dev + + /* frame exposure time in ms = 1000 * clockdiv / 90 -> + exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */ +- exposure = (sd->exposure * 45 * 448) / (1000 * clockdiv); ++ exposure = (sd->ctrls[EXPOSURE].val * 45 * 448) / (1000 * clockdiv); + /* 0 = use full frametime, 448 = no exposure, reverse it */ + exposure = 448 - exposure; + +@@ -677,15 +639,35 @@ static void setexposure(struct gspca_dev + reg_w(gspca_dev, 0x11, 0x01); + } + ++static void setautogain(struct gspca_dev *gspca_dev) ++{ ++ struct sd *sd = (struct sd *) gspca_dev; ++ ++ /* when switching to autogain set defaults to make sure ++ we are on a valid point of the autogain gain / ++ exposure knee graph, and give this change time to ++ take effect before doing autogain. */ ++ if (sd->ctrls[AUTOGAIN].val) { ++ sd->ctrls[EXPOSURE].val = EXPOSURE_DEF; ++ sd->ctrls[GAIN].val = GAIN_DEF; ++ sd->autogain_ignore_frames = ++ PAC_AUTOGAIN_IGNORE_FRAMES; ++ } else { ++ sd->autogain_ignore_frames = -1; ++ } ++ setexposure(gspca_dev); ++ setgain(gspca_dev); ++} ++ + static void sethvflip(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; + u8 data, hflip, vflip; + +- hflip = sd->hflip; ++ hflip = sd->ctrls[HFLIP].val; + if (sd->flags & FL_HFLIP) + hflip = !hflip; +- vflip = sd->vflip; ++ vflip = sd->ctrls[VFLIP].val; + if (sd->flags & FL_VFLIP) + vflip = !vflip; + +@@ -708,8 +690,6 @@ static int sd_start(struct gspca_dev *gs + { + struct sd *sd = (struct sd *) gspca_dev; + +- sd->sof_read = 0; +- + reg_w_var(gspca_dev, start_7302, + page3_7302, sizeof(page3_7302)); + setbrightcont(gspca_dev); +@@ -717,15 +697,13 @@ static int sd_start(struct gspca_dev *gs + setwhitebalance(gspca_dev); + setredbalance(gspca_dev); + setbluebalance(gspca_dev); +- setgain(gspca_dev); +- setexposure(gspca_dev); ++ setautogain(gspca_dev); + sethvflip(gspca_dev); + + /* only resolution 640x480 is supported for pac7302 */ + + sd->sof_read = 0; +- sd->autogain_ignore_frames = 0; +- atomic_set(&sd->avg_lum, -1); ++ atomic_set(&sd->avg_lum, 270 + sd->ctrls[BRIGHTNESS].val); + + /* start stream */ + reg_w(gspca_dev, 0xff, 0x01); +@@ -751,8 +729,10 @@ static void sd_stop0(struct gspca_dev *g + reg_w(gspca_dev, 0x78, 0x40); + } + +-/* Include pac common sof detection functions */ +-#include "pac_common.h" ++/* !! coarse_grained_expo_autogain is not used !! */ ++#define exp_too_low_cnt flags ++#define exp_too_high_cnt sof_read ++#include "autogain_functions.h" + + static void do_autogain(struct gspca_dev *gspca_dev) + { +@@ -761,65 +741,44 @@ static void do_autogain(struct gspca_dev + int desired_lum; + const int deadzone = 30; + +- if (avg_lum == -1) ++ if (sd->autogain_ignore_frames < 0) + return; + +- desired_lum = 270 + sd->brightness; +- +- if (sd->autogain_ignore_frames > 0) ++ if (sd->autogain_ignore_frames > 0) { + sd->autogain_ignore_frames--; +- else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum, +- deadzone, GAIN_KNEE, EXPOSURE_KNEE)) ++ } else { ++ desired_lum = 270 + sd->ctrls[BRIGHTNESS].val; ++ ++ auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum, ++ deadzone, GAIN_KNEE, EXPOSURE_KNEE); + sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; ++ } + } + +-/* JPEG header, part 1 */ +-static const unsigned char pac_jpeg_header1[] = { +- 0xff, 0xd8, /* SOI: Start of Image */ +- +- 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ +- 0x00, 0x11, /* length = 17 bytes (including this length field) */ +- 0x08 /* Precision: 8 */ +- /* 2 bytes is placed here: number of image lines */ +- /* 2 bytes is placed here: samples per line */ +-}; +- +-/* JPEG header, continued */ +-static const unsigned char pac_jpeg_header2[] = { +- 0x03, /* Number of image components: 3 */ +- 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ +- 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ +- 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ +- +- 0xff, 0xda, /* SOS: Start Of Scan */ +- 0x00, 0x0c, /* length = 12 bytes (including this length field) */ +- 0x03, /* number of components: 3 */ +- 0x01, 0x00, /* selector 1, table 0x00 */ +- 0x02, 0x11, /* selector 2, table 0x11 */ +- 0x03, 0x11, /* selector 3, table 0x11 */ +- 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ +- 0x00 /* Successive approximation: 0 */ ++/* JPEG header */ ++static const u8 jpeg_header[] = { ++ 0xff, 0xd8, /* SOI: Start of Image */ ++ ++ 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ ++ 0x00, 0x11, /* length = 17 bytes (including this length field) */ ++ 0x08, /* Precision: 8 */ ++ 0x02, 0x80, /* height = 640 (image rotated) */ ++ 0x01, 0xe0, /* width = 480 */ ++ 0x03, /* Number of image components: 3 */ ++ 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ ++ 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ ++ 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ ++ ++ 0xff, 0xda, /* SOS: Start Of Scan */ ++ 0x00, 0x0c, /* length = 12 bytes (including this length field) */ ++ 0x03, /* number of components: 3 */ ++ 0x01, 0x00, /* selector 1, table 0x00 */ ++ 0x02, 0x11, /* selector 2, table 0x11 */ ++ 0x03, 0x11, /* selector 3, table 0x11 */ ++ 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ ++ 0x00 /* Successive approximation: 0 */ + }; + +-static void pac_start_frame(struct gspca_dev *gspca_dev, +- __u16 lines, __u16 samples_per_line) +-{ +- unsigned char tmpbuf[4]; +- +- gspca_frame_add(gspca_dev, FIRST_PACKET, +- pac_jpeg_header1, sizeof(pac_jpeg_header1)); +- +- tmpbuf[0] = lines >> 8; +- tmpbuf[1] = lines & 0xff; +- tmpbuf[2] = samples_per_line >> 8; +- tmpbuf[3] = samples_per_line & 0xff; +- +- gspca_frame_add(gspca_dev, INTER_PACKET, +- tmpbuf, sizeof(tmpbuf)); +- gspca_frame_add(gspca_dev, INTER_PACKET, +- pac_jpeg_header2, sizeof(pac_jpeg_header2)); +-} +- + /* this function is run at interrupt level */ + static void sd_pkt_scan(struct gspca_dev *gspca_dev, + u8 *data, /* isoc packet */ +@@ -827,7 +786,7 @@ static void sd_pkt_scan(struct gspca_dev + { + struct sd *sd = (struct sd *) gspca_dev; + u8 *image; +- unsigned char *sof; ++ u8 *sof; + + sof = pac_find_sof(&sd->sof_read, data, len); + if (sof) { +@@ -864,234 +823,21 @@ static void sd_pkt_scan(struct gspca_dev + n >= lum_offset) + atomic_set(&sd->avg_lum, data[-lum_offset] + + data[-lum_offset + 1]); +- else +- atomic_set(&sd->avg_lum, -1); + + /* Start the new frame with the jpeg header */ + /* The PAC7302 has the image rotated 90 degrees */ +- pac_start_frame(gspca_dev, +- gspca_dev->width, gspca_dev->height); ++ gspca_frame_add(gspca_dev, FIRST_PACKET, ++ jpeg_header, sizeof jpeg_header); + } + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); + } + +-static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->brightness = val; +- if (gspca_dev->streaming) +- setbrightcont(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->brightness; +- return 0; +-} +- +-static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->contrast = val; +- if (gspca_dev->streaming) +- setbrightcont(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->contrast; +- return 0; +-} +- +-static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->colors = val; +- if (gspca_dev->streaming) +- setcolors(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->colors; +- return 0; +-} +- +-static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->white_balance = val; +- if (gspca_dev->streaming) +- setwhitebalance(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->white_balance; +- return 0; +-} +- +-static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->red_balance = val; +- if (gspca_dev->streaming) +- setredbalance(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->red_balance; +- return 0; +-} +- +-static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->blue_balance = val; +- if (gspca_dev->streaming) +- setbluebalance(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->blue_balance; +- return 0; +-} +- +-static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->gain = val; +- if (gspca_dev->streaming) +- setgain(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->gain; +- return 0; +-} +- +-static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->exposure = val; +- if (gspca_dev->streaming) +- setexposure(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->exposure; +- return 0; +-} +- +-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->autogain = val; +- /* when switching to autogain set defaults to make sure +- we are on a valid point of the autogain gain / +- exposure knee graph, and give this change time to +- take effect before doing autogain. */ +- if (sd->autogain) { +- sd->exposure = EXPOSURE_DEF; +- sd->gain = GAIN_DEF; +- if (gspca_dev->streaming) { +- sd->autogain_ignore_frames = +- PAC_AUTOGAIN_IGNORE_FRAMES; +- setexposure(gspca_dev); +- setgain(gspca_dev); +- } +- } +- +- return gspca_dev->usb_err; +-} +- +-static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->autogain; +- return 0; +-} +- +-static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->hflip = val; +- if (gspca_dev->streaming) +- sethvflip(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->hflip; +- return 0; +-} +- +-static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->vflip = val; +- if (gspca_dev->streaming) +- sethvflip(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->vflip; +- return 0; +-} +- + #ifdef CONFIG_VIDEO_ADV_DEBUG + static int sd_dbg_s_register(struct gspca_dev *gspca_dev, + struct v4l2_dbg_register *reg) + { +- __u8 index; +- __u8 value; ++ u8 index; ++ u8 value; + + /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit + long on the USB bus) +@@ -1103,8 +849,8 @@ static int sd_dbg_s_register(struct gspc + ) { + /* Currently writing to page 0 is only supported. */ + /* reg_w() only supports 8bit index */ +- index = reg->reg & 0x000000ff; +- value = reg->val & 0x000000ff; ++ index = reg->reg; ++ value = reg->val; + + /* Note that there shall be no access to other page + by any other function between the page swith and +@@ -1165,7 +911,7 @@ static int sd_int_pkt_scan(struct gspca_ + + /* sub-driver description for pac7302 */ + static const struct sd_desc sd_desc = { +- .name = MODULE_NAME, ++ .name = KBUILD_MODNAME, + .ctrls = sd_ctrls, + .nctrls = ARRAY_SIZE(sd_ctrls), + .config = sd_config, +@@ -1187,6 +933,7 @@ static const struct sd_desc sd_desc = { + /* -- module initialisation -- */ + static const struct usb_device_id device_table[] = { + {USB_DEVICE(0x06f8, 0x3009)}, ++ {USB_DEVICE(0x06f8, 0x301b)}, + {USB_DEVICE(0x093a, 0x2620)}, + {USB_DEVICE(0x093a, 0x2621)}, + {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP}, +@@ -1211,7 +958,7 @@ static int sd_probe(struct usb_interface + } + + static struct usb_driver sd_driver = { +- .name = MODULE_NAME, ++ .name = KBUILD_MODNAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +Index: linux-3.3.x86_64/drivers/media/video/gspca/sonixj.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/gspca/sonixj.c ++++ linux-3.3.x86_64/drivers/media/video/gspca/sonixj.c +@@ -39,7 +39,9 @@ enum e_ctrl { + BLUE, + RED, + GAMMA, ++ EXPOSURE, + AUTOGAIN, ++ GAIN, + HFLIP, + VFLIP, + SHARPNESS, +@@ -131,7 +133,9 @@ static void setcontrast(struct gspca_dev + static void setcolors(struct gspca_dev *gspca_dev); + static void setredblue(struct gspca_dev *gspca_dev); + static void setgamma(struct gspca_dev *gspca_dev); +-static void setautogain(struct gspca_dev *gspca_dev); ++static void setexposure(struct gspca_dev *gspca_dev); ++static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); ++static void setgain(struct gspca_dev *gspca_dev); + static void sethvflip(struct gspca_dev *gspca_dev); + static void setsharpness(struct gspca_dev *gspca_dev); + static void setillum(struct gspca_dev *gspca_dev); +@@ -213,6 +217,18 @@ static const struct ctrl sd_ctrls[NCTRLS + }, + .set_control = setgamma + }, ++[EXPOSURE] = { ++ { ++ .id = V4L2_CID_EXPOSURE, ++ .type = V4L2_CTRL_TYPE_INTEGER, ++ .name = "Exposure", ++ .minimum = 500, ++ .maximum = 1500, ++ .step = 1, ++ .default_value = 1024 ++ }, ++ .set_control = setexposure ++ }, + [AUTOGAIN] = { + { + .id = V4L2_CID_AUTOGAIN, +@@ -223,7 +239,19 @@ static const struct ctrl sd_ctrls[NCTRLS + .step = 1, + .default_value = 1 + }, +- .set_control = setautogain ++ .set = sd_setautogain, ++ }, ++[GAIN] = { ++ { ++ .id = V4L2_CID_GAIN, ++ .type = V4L2_CTRL_TYPE_INTEGER, ++ .name = "Gain", ++ .minimum = 4, ++ .maximum = 49, ++ .step = 1, ++ .default_value = 15 ++ }, ++ .set_control = setgain + }, + [HFLIP] = { + { +@@ -290,60 +318,87 @@ static const struct ctrl sd_ctrls[NCTRLS + + /* table of the disabled controls */ + static const __u32 ctrl_dis[] = { +-[SENSOR_ADCM1700] = (1 << AUTOGAIN) | ++[SENSOR_ADCM1700] = (1 << EXPOSURE) | ++ (1 << AUTOGAIN) | ++ (1 << GAIN) | + (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_GC0307] = (1 << HFLIP) | ++[SENSOR_GC0307] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_HV7131R] = (1 << HFLIP) | ++[SENSOR_HV7131R] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP) | + (1 << FREQ), + +-[SENSOR_MI0360] = (1 << HFLIP) | ++[SENSOR_MI0360] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_MI0360B] = (1 << HFLIP) | ++[SENSOR_MI0360B] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_MO4000] = (1 << HFLIP) | ++[SENSOR_MO4000] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_MT9V111] = (1 << HFLIP) | ++[SENSOR_MT9V111] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_OM6802] = (1 << HFLIP) | ++[SENSOR_OM6802] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_OV7630] = (1 << HFLIP), +- +-[SENSOR_OV7648] = (1 << HFLIP), +- +-[SENSOR_OV7660] = (1 << AUTOGAIN) | ++[SENSOR_OV7630] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP), ++ ++[SENSOR_OV7648] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP), ++ ++[SENSOR_OV7660] = (1 << EXPOSURE) | ++ (1 << AUTOGAIN) | ++ (1 << GAIN) | + (1 << HFLIP) | + (1 << VFLIP), + +-[SENSOR_PO1030] = (1 << AUTOGAIN) | ++[SENSOR_PO1030] = (1 << EXPOSURE) | ++ (1 << AUTOGAIN) | ++ (1 << GAIN) | + (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_PO2030N] = (1 << AUTOGAIN) | +- (1 << FREQ), ++[SENSOR_PO2030N] = (1 << FREQ), + +-[SENSOR_SOI768] = (1 << AUTOGAIN) | ++[SENSOR_SOI768] = (1 << EXPOSURE) | ++ (1 << AUTOGAIN) | ++ (1 << GAIN) | + (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_SP80708] = (1 << AUTOGAIN) | ++[SENSOR_SP80708] = (1 << EXPOSURE) | ++ (1 << AUTOGAIN) | ++ (1 << GAIN) | + (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), +@@ -1242,14 +1297,6 @@ static const u8 po2030n_sensor_param1[][ + {0xa1, 0x6e, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10}, +- {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, +- {0xc1, 0x6e, 0x16, 0x52, 0x40, 0x48, 0x00, 0x10}, +-/*after start*/ +- {0xa1, 0x6e, 0x15, 0x0f, 0x00, 0x00, 0x00, 0x10}, +- {DELAY, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */ +- {0xa1, 0x6e, 0x1a, 0x05, 0x00, 0x00, 0x00, 0x10}, +- {DELAY, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */ +- {0xa1, 0x6e, 0x1b, 0x53, 0x00, 0x00, 0x00, 0x10}, + {} + }; + +@@ -1858,7 +1905,7 @@ static int sd_init(struct gspca_dev *gsp + return gspca_dev->usb_err; + } + +-static u32 setexposure(struct gspca_dev *gspca_dev, ++static u32 expo_adjust(struct gspca_dev *gspca_dev, + u32 expo) + { + struct sd *sd = (struct sd *) gspca_dev; +@@ -1982,28 +2029,28 @@ static void setbrightness(struct gspca_d + expo = 0x002dc6c0; + else if (expo < 0x02a0) + expo = 0x02a0; +- sd->exposure = setexposure(gspca_dev, expo); ++ sd->exposure = expo_adjust(gspca_dev, expo); + break; + case SENSOR_MI0360: + case SENSOR_MO4000: + expo = brightness << 4; +- sd->exposure = setexposure(gspca_dev, expo); ++ sd->exposure = expo_adjust(gspca_dev, expo); + break; + case SENSOR_MI0360B: + expo = brightness << 2; +- sd->exposure = setexposure(gspca_dev, expo); ++ sd->exposure = expo_adjust(gspca_dev, expo); + break; + case SENSOR_GC0307: + expo = brightness; +- sd->exposure = setexposure(gspca_dev, expo); ++ sd->exposure = expo_adjust(gspca_dev, expo); + return; /* don't set the Y offset */ + case SENSOR_MT9V111: + expo = brightness << 2; +- sd->exposure = setexposure(gspca_dev, expo); ++ sd->exposure = expo_adjust(gspca_dev, expo); + return; /* don't set the Y offset */ + case SENSOR_OM6802: + expo = brightness << 2; +- sd->exposure = setexposure(gspca_dev, expo); ++ sd->exposure = expo_adjust(gspca_dev, expo); + return; /* Y offset already set */ + } + +@@ -2112,6 +2159,23 @@ static void setgamma(struct gspca_dev *g + reg_w(gspca_dev, 0x20, gamma, sizeof gamma); + } + ++static void setexposure(struct gspca_dev *gspca_dev) ++{ ++ struct sd *sd = (struct sd *) gspca_dev; ++ ++ if (sd->sensor == SENSOR_PO2030N) { ++ u8 rexpo[] = /* 1a: expo H, 1b: expo M */ ++ {0xa1, 0x6e, 0x1a, 0x00, 0x40, 0x00, 0x00, 0x10}; ++ ++ rexpo[3] = sd->ctrls[EXPOSURE].val >> 8; ++ i2c_w8(gspca_dev, rexpo); ++ msleep(6); ++ rexpo[2] = 0x1b; ++ rexpo[3] = sd->ctrls[EXPOSURE].val; ++ i2c_w8(gspca_dev, rexpo); ++ } ++} ++ + static void setautogain(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +@@ -2139,6 +2203,19 @@ static void setautogain(struct gspca_dev + sd->ag_cnt = -1; + } + ++static void setgain(struct gspca_dev *gspca_dev) ++{ ++ struct sd *sd = (struct sd *) gspca_dev; ++ ++ if (sd->sensor == SENSOR_PO2030N) { ++ u8 rgain[] = /* 15: gain */ ++ {0xa1, 0x6e, 0x15, 0x00, 0x40, 0x00, 0x00, 0x15}; ++ ++ rgain[3] = sd->ctrls[GAIN].val; ++ i2c_w8(gspca_dev, rgain); ++ } ++} ++ + static void sethvflip(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +@@ -2623,6 +2700,10 @@ static int sd_start(struct gspca_dev *gs + setcontrast(gspca_dev); + setcolors(gspca_dev); + setautogain(gspca_dev); ++ if (!(gspca_dev->ctrl_inac & ((1 << EXPOSURE) | (1 << GAIN)))) { ++ setexposure(gspca_dev); ++ setgain(gspca_dev); ++ } + setfreq(gspca_dev); + + sd->pktsz = sd->npkt = 0; +@@ -2719,6 +2800,12 @@ static void sd_stop0(struct gspca_dev *g + } + } + ++/* !! coarse_grained_expo_autogain is not used !! */ ++#define exp_too_low_cnt bridge ++#define exp_too_high_cnt sensor ++ ++#include "autogain_functions.h" ++ + static void do_autogain(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +@@ -2736,6 +2823,13 @@ static void do_autogain(struct gspca_dev + + delta = atomic_read(&sd->avg_lum); + PDEBUG(D_FRAM, "mean lum %d", delta); ++ ++ if (sd->sensor == SENSOR_PO2030N) { ++ auto_gain_n_exposure(gspca_dev, delta, luma_mean, luma_delta, ++ 15, 1024); ++ return; ++ } ++ + if (delta < luma_mean - luma_delta || + delta > luma_mean + luma_delta) { + switch (sd->sensor) { +@@ -2744,7 +2838,7 @@ static void do_autogain(struct gspca_dev + expotimes += (luma_mean - delta) >> 6; + if (expotimes < 0) + expotimes = 0; +- sd->exposure = setexposure(gspca_dev, ++ sd->exposure = expo_adjust(gspca_dev, + (unsigned int) expotimes); + break; + case SENSOR_HV7131R: +@@ -2752,7 +2846,7 @@ static void do_autogain(struct gspca_dev + expotimes += (luma_mean - delta) >> 4; + if (expotimes < 0) + expotimes = 0; +- sd->exposure = setexposure(gspca_dev, ++ sd->exposure = expo_adjust(gspca_dev, + (unsigned int) (expotimes << 8)); + break; + case SENSOR_OM6802: +@@ -2761,7 +2855,7 @@ static void do_autogain(struct gspca_dev + expotimes += (luma_mean - delta) >> 2; + if (expotimes < 0) + expotimes = 0; +- sd->exposure = setexposure(gspca_dev, ++ sd->exposure = expo_adjust(gspca_dev, + (unsigned int) expotimes); + setredblue(gspca_dev); + break; +@@ -2773,7 +2867,7 @@ static void do_autogain(struct gspca_dev + expotimes += (luma_mean - delta) >> 6; + if (expotimes < 0) + expotimes = 0; +- sd->exposure = setexposure(gspca_dev, ++ sd->exposure = expo_adjust(gspca_dev, + (unsigned int) expotimes); + setredblue(gspca_dev); + break; +@@ -2948,16 +3042,18 @@ marker_found: + } + } + +-static int sd_get_jcomp(struct gspca_dev *gspca_dev, +- struct v4l2_jpegcompression *jcomp) ++static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) + { + struct sd *sd = (struct sd *) gspca_dev; + +- memset(jcomp, 0, sizeof *jcomp); +- jcomp->quality = sd->quality; +- jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT +- | V4L2_JPEG_MARKER_DQT; +- return 0; ++ sd->ctrls[AUTOGAIN].val = val; ++ if (val) ++ gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN); ++ else ++ gspca_dev->ctrl_inac &= ~(1 << EXPOSURE) & ~(1 << GAIN); ++ if (gspca_dev->streaming) ++ setautogain(gspca_dev); ++ return gspca_dev->usb_err; + } + + static int sd_querymenu(struct gspca_dev *gspca_dev, +@@ -3012,7 +3108,6 @@ static const struct sd_desc sd_desc = { + .stop0 = sd_stop0, + .pkt_scan = sd_pkt_scan, + .dq_callback = do_autogain, +- .get_jcomp = sd_get_jcomp, + .querymenu = sd_querymenu, + #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + .int_pkt_scan = sd_int_pkt_scan, +Index: linux-3.3.x86_64/drivers/media/video/gspca/zc3xx.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/gspca/zc3xx.c ++++ linux-3.3.x86_64/drivers/media/video/gspca/zc3xx.c +@@ -1,7 +1,7 @@ + /* +- * Z-Star/Vimicro zc301/zc302p/vc30x library ++ * Z-Star/Vimicro zc301/zc302p/vc30x driver + * +- * Copyright (C) 2009-2011 Jean-Francois Moine ++ * Copyright (C) 2009-2012 Jean-Francois Moine + * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.fr + * + * This program is free software; you can redistribute it and/or modify +@@ -21,8 +21,6 @@ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +-#define MODULE_NAME "zc3xx" +- + #include + #include "gspca.h" + #include "jpeg.h" +@@ -34,7 +32,7 @@ MODULE_LICENSE("GPL"); + + static int force_sensor = -1; + +-#define QUANT_VAL 1 /* quantization table */ ++#define REG08_DEF 3 /* default JPEG compression (70%) */ + #include "zc3xx-reg.h" + + /* controls */ +@@ -46,6 +44,7 @@ enum e_ctrl { + AUTOGAIN, + LIGHTFREQ, + SHARPNESS, ++ QUALITY, + NCTRLS /* number of controls */ + }; + +@@ -57,10 +56,10 @@ struct sd { + + struct gspca_ctrl ctrls[NCTRLS]; + +- u8 quality; /* image quality */ +-#define QUALITY_MIN 50 +-#define QUALITY_MAX 80 +-#define QUALITY_DEF 70 ++ struct work_struct work; ++ struct workqueue_struct *work_thread; ++ ++ u8 reg08; /* webcam compression quality */ + + u8 bridge; + u8 sensor; /* Type of image sensor chip */ +@@ -101,6 +100,7 @@ static void setexposure(struct gspca_dev + static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); + static void setlightfreq(struct gspca_dev *gspca_dev); + static void setsharpness(struct gspca_dev *gspca_dev); ++static int sd_setquality(struct gspca_dev *gspca_dev, __s32 val); + + static const struct ctrl sd_ctrls[NCTRLS] = { + [BRIGHTNESS] = { +@@ -188,6 +188,18 @@ static const struct ctrl sd_ctrls[NCTRLS + }, + .set_control = setsharpness + }, ++[QUALITY] = { ++ { ++ .id = V4L2_CID_JPEG_COMPRESSION_QUALITY, ++ .type = V4L2_CTRL_TYPE_INTEGER, ++ .name = "Compression Quality", ++ .minimum = 40, ++ .maximum = 70, ++ .step = 1, ++ .default_value = 70 /* updated in sd_init() */ ++ }, ++ .set = sd_setquality ++ }, + }; + + static const struct v4l2_pix_format vga_mode[] = { +@@ -229,6 +241,9 @@ static const struct v4l2_pix_format sif_ + .priv = 0}, + }; + ++/* bridge reg08 -> JPEG quality conversion table */ ++static u8 jpeg_qual[] = {40, 50, 60, 70, /*80*/}; ++ + /* usb exchanges */ + struct usb_action { + u8 req; +@@ -3894,7 +3909,6 @@ static const struct usb_action pas106b_I + /* Gains */ + {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, +- {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN}, + {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, + /* Auto correction */ + {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, +@@ -5640,7 +5654,7 @@ static const struct usb_action gc0303_No + {} + }; + +-static u8 reg_r_i(struct gspca_dev *gspca_dev, ++static u8 reg_r(struct gspca_dev *gspca_dev, + u16 index) + { + int ret; +@@ -5655,24 +5669,14 @@ static u8 reg_r_i(struct gspca_dev *gspc + index, gspca_dev->usb_buf, 1, + 500); + if (ret < 0) { +- pr_err("reg_r_i err %d\n", ret); ++ pr_err("reg_r err %d\n", ret); + gspca_dev->usb_err = ret; + return 0; + } + return gspca_dev->usb_buf[0]; + } + +-static u8 reg_r(struct gspca_dev *gspca_dev, +- u16 index) +-{ +- u8 ret; +- +- ret = reg_r_i(gspca_dev, index); +- PDEBUG(D_USBI, "reg r [%04x] -> %02x", index, ret); +- return ret; +-} +- +-static void reg_w_i(struct gspca_dev *gspca_dev, ++static void reg_w(struct gspca_dev *gspca_dev, + u8 value, + u16 index) + { +@@ -5692,14 +5696,6 @@ static void reg_w_i(struct gspca_dev *gs + } + } + +-static void reg_w(struct gspca_dev *gspca_dev, +- u8 value, +- u16 index) +-{ +- PDEBUG(D_USBO, "reg w [%04x] = %02x", index, value); +- reg_w_i(gspca_dev, value, index); +-} +- + static u16 i2c_read(struct gspca_dev *gspca_dev, + u8 reg) + { +@@ -5708,16 +5704,14 @@ static u16 i2c_read(struct gspca_dev *gs + + if (gspca_dev->usb_err < 0) + return 0; +- reg_w_i(gspca_dev, reg, 0x0092); +- reg_w_i(gspca_dev, 0x02, 0x0090); /* <- read command */ ++ reg_w(gspca_dev, reg, 0x0092); ++ reg_w(gspca_dev, 0x02, 0x0090); /* <- read command */ + msleep(20); +- retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ ++ retbyte = reg_r(gspca_dev, 0x0091); /* read status */ + if (retbyte != 0x00) + pr_err("i2c_r status error %02x\n", retbyte); +- retval = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */ +- retval |= reg_r_i(gspca_dev, 0x0096) << 8; /* read Hightbyte */ +- PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)", +- reg, retval, retbyte); ++ retval = reg_r(gspca_dev, 0x0095); /* read Lowbyte */ ++ retval |= reg_r(gspca_dev, 0x0096) << 8; /* read Hightbyte */ + return retval; + } + +@@ -5730,16 +5724,14 @@ static u8 i2c_write(struct gspca_dev *gs + + if (gspca_dev->usb_err < 0) + return 0; +- reg_w_i(gspca_dev, reg, 0x92); +- reg_w_i(gspca_dev, valL, 0x93); +- reg_w_i(gspca_dev, valH, 0x94); +- reg_w_i(gspca_dev, 0x01, 0x90); /* <- write command */ ++ reg_w(gspca_dev, reg, 0x92); ++ reg_w(gspca_dev, valL, 0x93); ++ reg_w(gspca_dev, valH, 0x94); ++ reg_w(gspca_dev, 0x01, 0x90); /* <- write command */ + msleep(1); +- retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ ++ retbyte = reg_r(gspca_dev, 0x0091); /* read status */ + if (retbyte != 0x00) + pr_err("i2c_w status error %02x\n", retbyte); +- PDEBUG(D_USBO, "i2c w [%02x] = %02x%02x (%02x)", +- reg, valH, valL, retbyte); + return retbyte; + } + +@@ -5906,6 +5898,8 @@ static void getexposure(struct gspca_dev + { + struct sd *sd = (struct sd *) gspca_dev; + ++ if (sd->sensor != SENSOR_HV7131R) ++ return; + sd->ctrls[EXPOSURE].val = (i2c_read(gspca_dev, 0x25) << 9) + | (i2c_read(gspca_dev, 0x26) << 1) + | (i2c_read(gspca_dev, 0x27) >> 7); +@@ -5916,6 +5910,8 @@ static void setexposure(struct gspca_dev + struct sd *sd = (struct sd *) gspca_dev; + int val; + ++ if (sd->sensor != SENSOR_HV7131R) ++ return; + val = sd->ctrls[EXPOSURE].val; + i2c_write(gspca_dev, 0x25, val >> 9, 0x00); + i2c_write(gspca_dev, 0x26, val >> 1, 0x00); +@@ -5925,32 +5921,20 @@ static void setexposure(struct gspca_dev + static void setquality(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- u8 frxt; ++ s8 reg07; + ++ reg07 = 0; + switch (sd->sensor) { +- case SENSOR_ADCM2700: +- case SENSOR_GC0305: +- case SENSOR_HV7131B: +- case SENSOR_HV7131R: + case SENSOR_OV7620: ++ reg07 = 0x30; ++ break; ++ case SENSOR_HV7131R: + case SENSOR_PAS202B: +- case SENSOR_PO2030: +- return; ++ return; /* done by work queue */ + } +-/*fixme: is it really 0008 0007 0018 for all other sensors? */ +- reg_w(gspca_dev, QUANT_VAL, 0x0008); +- frxt = 0x30; +- reg_w(gspca_dev, frxt, 0x0007); +-#if QUANT_VAL == 0 || QUANT_VAL == 1 || QUANT_VAL == 2 +- frxt = 0xff; +-#elif QUANT_VAL == 3 +- frxt = 0xf0; +-#elif QUANT_VAL == 4 +- frxt = 0xe0; +-#else +- frxt = 0x20; +-#endif +- reg_w(gspca_dev, frxt, 0x0018); ++ reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING); ++ if (reg07 != 0) ++ reg_w(gspca_dev, reg07, 0x0007); + } + + /* Matches the sensor's internal frame rate to the lighting frequency. +@@ -6084,6 +6068,115 @@ static void setautogain(struct gspca_dev + reg_w(gspca_dev, autoval, 0x0180); + } + ++/* update the transfer parameters */ ++/* This function is executed from a work queue. */ ++/* The exact use of the bridge registers 07 and 08 is not known. ++ * The following algorithm has been adapted from ms-win traces */ ++static void transfer_update(struct work_struct *work) ++{ ++ struct sd *sd = container_of(work, struct sd, work); ++ struct gspca_dev *gspca_dev = &sd->gspca_dev; ++ int change, good; ++ u8 reg07, reg11; ++ ++ /* synchronize with the main driver and initialize the registers */ ++ mutex_lock(&gspca_dev->usb_lock); ++ reg07 = 0; /* max */ ++ reg_w(gspca_dev, reg07, 0x0007); ++ reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING); ++ mutex_unlock(&gspca_dev->usb_lock); ++ ++ good = 0; ++ for (;;) { ++ msleep(100); ++ ++ /* get the transfer status */ ++ /* the bit 0 of the bridge register 11 indicates overflow */ ++ mutex_lock(&gspca_dev->usb_lock); ++ if (!gspca_dev->present || !gspca_dev->streaming) ++ goto err; ++ reg11 = reg_r(gspca_dev, 0x0011); ++ if (gspca_dev->usb_err < 0 ++ || !gspca_dev->present || !gspca_dev->streaming) ++ goto err; ++ ++ change = reg11 & 0x01; ++ if (change) { /* overflow */ ++ switch (reg07) { ++ case 0: /* max */ ++ reg07 = sd->sensor == SENSOR_HV7131R ++ ? 0x30 : 0x32; ++ if (sd->reg08 != 0) { ++ change = 3; ++ sd->reg08--; ++ } ++ break; ++ case 0x32: ++ reg07 -= 4; ++ break; ++ default: ++ reg07 -= 2; ++ break; ++ case 2: ++ change = 0; /* already min */ ++ break; ++ } ++ good = 0; ++ } else { /* no overflow */ ++ if (reg07 != 0) { /* if not max */ ++ good++; ++ if (good >= 10) { ++ good = 0; ++ change = 1; ++ reg07 += 2; ++ switch (reg07) { ++ case 0x30: ++ if (sd->sensor == SENSOR_PAS202B) ++ reg07 += 2; ++ break; ++ case 0x32: ++ case 0x34: ++ reg07 = 0; ++ break; ++ } ++ } ++ } else { /* reg07 max */ ++ if (sd->reg08 < sizeof jpeg_qual - 1) { ++ good++; ++ if (good > 10) { ++ sd->reg08++; ++ change = 2; ++ } ++ } ++ } ++ } ++ if (change) { ++ if (change & 1) { ++ reg_w(gspca_dev, reg07, 0x0007); ++ if (gspca_dev->usb_err < 0 ++ || !gspca_dev->present ++ || !gspca_dev->streaming) ++ goto err; ++ } ++ if (change & 2) { ++ reg_w(gspca_dev, sd->reg08, ++ ZC3XX_R008_CLOCKSETTING); ++ if (gspca_dev->usb_err < 0 ++ || !gspca_dev->present ++ || !gspca_dev->streaming) ++ goto err; ++ sd->ctrls[QUALITY].val = jpeg_qual[sd->reg08]; ++ jpeg_set_qual(sd->jpeg_hdr, ++ jpeg_qual[sd->reg08]); ++ } ++ } ++ mutex_unlock(&gspca_dev->usb_lock); ++ } ++ return; ++err: ++ mutex_unlock(&gspca_dev->usb_lock); ++} ++ + static void send_unknown(struct gspca_dev *gspca_dev, int sensor) + { + reg_w(gspca_dev, 0x01, 0x0000); /* bridge reset */ +@@ -6411,7 +6504,9 @@ static int sd_config(struct gspca_dev *g + sd->sensor = id->driver_info; + + gspca_dev->cam.ctrls = sd->ctrls; +- sd->quality = QUALITY_DEF; ++ sd->reg08 = REG08_DEF; ++ ++ INIT_WORK(&sd->work, transfer_update); + + return 0; + } +@@ -6464,6 +6559,27 @@ static int sd_init(struct gspca_dev *gsp + [SENSOR_PO2030] = 1, + [SENSOR_TAS5130C] = 1, + }; ++ static const u8 reg08_tb[SENSOR_MAX] = { ++ [SENSOR_ADCM2700] = 1, ++ [SENSOR_CS2102] = 3, ++ [SENSOR_CS2102K] = 3, ++ [SENSOR_GC0303] = 2, ++ [SENSOR_GC0305] = 3, ++ [SENSOR_HDCS2020] = 1, ++ [SENSOR_HV7131B] = 3, ++ [SENSOR_HV7131R] = 3, ++ [SENSOR_ICM105A] = 3, ++ [SENSOR_MC501CB] = 3, ++ [SENSOR_MT9V111_1] = 3, ++ [SENSOR_MT9V111_3] = 3, ++ [SENSOR_OV7620] = 1, ++ [SENSOR_OV7630C] = 3, ++ [SENSOR_PAS106] = 3, ++ [SENSOR_PAS202B] = 3, ++ [SENSOR_PB0330] = 3, ++ [SENSOR_PO2030] = 2, ++ [SENSOR_TAS5130C] = 3, ++ }; + + sensor = zcxx_probeSensor(gspca_dev); + if (sensor >= 0) +@@ -6528,7 +6644,6 @@ static int sd_init(struct gspca_dev *gsp + case 0x0e: + PDEBUG(D_PROBE, "Find Sensor PAS202B"); + sd->sensor = SENSOR_PAS202B; +-/* sd->sharpness = 1; */ + break; + case 0x0f: + PDEBUG(D_PROBE, "Find Sensor PAS106"); +@@ -6616,13 +6731,21 @@ static int sd_init(struct gspca_dev *gsp + } + + sd->ctrls[GAMMA].def = gamma[sd->sensor]; ++ sd->reg08 = reg08_tb[sd->sensor]; ++ sd->ctrls[QUALITY].def = jpeg_qual[sd->reg08]; ++ sd->ctrls[QUALITY].min = jpeg_qual[0]; ++ sd->ctrls[QUALITY].max = jpeg_qual[ARRAY_SIZE(jpeg_qual) - 1]; + + switch (sd->sensor) { + case SENSOR_HV7131R: ++ gspca_dev->ctrl_dis = (1 << QUALITY); + break; + case SENSOR_OV7630C: + gspca_dev->ctrl_dis = (1 << LIGHTFREQ) | (1 << EXPOSURE); + break; ++ case SENSOR_PAS202B: ++ gspca_dev->ctrl_dis = (1 << QUALITY) | (1 << EXPOSURE); ++ break; + default: + gspca_dev->ctrl_dis = (1 << EXPOSURE); + break; +@@ -6685,7 +6808,6 @@ static int sd_start(struct gspca_dev *gs + /* create the JPEG header */ + jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x21); /* JPEG 422 */ +- jpeg_set_qual(sd->jpeg_hdr, sd->quality); + + mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; + switch (sd->sensor) { +@@ -6761,10 +6883,9 @@ static int sd_start(struct gspca_dev *gs + reg_r(gspca_dev, 0x0180); /* from win */ + reg_w(gspca_dev, 0x00, 0x0180); + break; +- default: +- setquality(gspca_dev); +- break; + } ++ setquality(gspca_dev); ++ jpeg_set_qual(sd->jpeg_hdr, jpeg_qual[sd->reg08]); + setlightfreq(gspca_dev); + + switch (sd->sensor) { +@@ -6776,8 +6897,7 @@ static int sd_start(struct gspca_dev *gs + reg_w(gspca_dev, 0x40, 0x0117); + break; + case SENSOR_HV7131R: +- if (!sd->ctrls[AUTOGAIN].val) +- setexposure(gspca_dev); ++ setexposure(gspca_dev); + reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN); + break; + case SENSOR_GC0305: +@@ -6802,13 +6922,19 @@ static int sd_start(struct gspca_dev *gs + } + + setautogain(gspca_dev); +- switch (sd->sensor) { +- case SENSOR_PO2030: +- msleep(50); +- reg_w(gspca_dev, 0x00, 0x0007); /* (from win traces) */ +- reg_w(gspca_dev, 0x02, ZC3XX_R008_CLOCKSETTING); +- break; ++ ++ /* start the transfer update thread if needed */ ++ if (gspca_dev->usb_err >= 0) { ++ switch (sd->sensor) { ++ case SENSOR_HV7131R: ++ case SENSOR_PAS202B: ++ sd->work_thread = ++ create_singlethread_workqueue(KBUILD_MODNAME); ++ queue_work(sd->work_thread, &sd->work); ++ break; ++ } + } ++ + return gspca_dev->usb_err; + } + +@@ -6817,6 +6943,12 @@ static void sd_stop0(struct gspca_dev *g + { + struct sd *sd = (struct sd *) gspca_dev; + ++ if (sd->work_thread != NULL) { ++ mutex_unlock(&gspca_dev->usb_lock); ++ destroy_workqueue(sd->work_thread); ++ mutex_lock(&gspca_dev->usb_lock); ++ sd->work_thread = NULL; ++ } + if (!gspca_dev->present) + return; + send_unknown(gspca_dev, sd->sensor); +@@ -6893,19 +7025,33 @@ static int sd_querymenu(struct gspca_dev + return -EINVAL; + } + ++static int sd_setquality(struct gspca_dev *gspca_dev, __s32 val) ++{ ++ struct sd *sd = (struct sd *) gspca_dev; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(jpeg_qual) - 1; i++) { ++ if (val <= jpeg_qual[i]) ++ break; ++ } ++ if (i > 0 ++ && i == sd->reg08 ++ && val < jpeg_qual[sd->reg08]) ++ i--; ++ sd->reg08 = i; ++ sd->ctrls[QUALITY].val = jpeg_qual[i]; ++ if (gspca_dev->streaming) ++ jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); ++ return gspca_dev->usb_err; ++} ++ + static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) + { + struct sd *sd = (struct sd *) gspca_dev; + +- if (jcomp->quality < QUALITY_MIN) +- sd->quality = QUALITY_MIN; +- else if (jcomp->quality > QUALITY_MAX) +- sd->quality = QUALITY_MAX; +- else +- sd->quality = jcomp->quality; +- if (gspca_dev->streaming) +- jpeg_set_qual(sd->jpeg_hdr, sd->quality); ++ sd_setquality(gspca_dev, jcomp->quality); ++ jcomp->quality = sd->ctrls[QUALITY].val; + return gspca_dev->usb_err; + } + +@@ -6915,7 +7061,7 @@ static int sd_get_jcomp(struct gspca_dev + struct sd *sd = (struct sd *) gspca_dev; + + memset(jcomp, 0, sizeof *jcomp); +- jcomp->quality = sd->quality; ++ jcomp->quality = sd->ctrls[QUALITY].val; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT + | V4L2_JPEG_MARKER_DQT; + return 0; +@@ -6938,7 +7084,7 @@ static int sd_int_pkt_scan(struct gspca_ + #endif + + static const struct sd_desc sd_desc = { +- .name = MODULE_NAME, ++ .name = KBUILD_MODNAME, + .ctrls = sd_ctrls, + .nctrls = ARRAY_SIZE(sd_ctrls), + .config = sd_config, +@@ -7023,7 +7169,7 @@ static int sd_probe(struct usb_interface + + /* USB driver */ + static struct usb_driver sd_driver = { +- .name = MODULE_NAME, ++ .name = KBUILD_MODNAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/au8522_decoder.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/au8522_decoder.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/au8522_decoder.c +@@ -839,15 +839,4 @@ static struct i2c_driver au8522_driver = + .id_table = au8522_id, + }; + +-static __init int init_au8522(void) +-{ +- return i2c_add_driver(&au8522_driver); +-} +- +-static __exit void exit_au8522(void) +-{ +- i2c_del_driver(&au8522_driver); +-} +- +-module_init(init_au8522); +-module_exit(exit_au8522); ++module_i2c_driver(au8522_driver); +Index: linux-3.3.x86_64/drivers/media/radio/radio-tea5764.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-tea5764.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-tea5764.c +@@ -575,21 +575,7 @@ static struct i2c_driver tea5764_i2c_dri + .id_table = tea5764_id, + }; + +-/* init the driver */ +-static int __init tea5764_init(void) +-{ +- int ret = i2c_add_driver(&tea5764_i2c_driver); +- +- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ": " +- DRIVER_DESC "\n"); +- return ret; +-} +- +-/* cleanup the driver */ +-static void __exit tea5764_exit(void) +-{ +- i2c_del_driver(&tea5764_i2c_driver); +-} ++module_i2c_driver(tea5764_i2c_driver); + + MODULE_AUTHOR(DRIVER_AUTHOR); + MODULE_DESCRIPTION(DRIVER_DESC); +@@ -600,6 +586,3 @@ module_param(use_xtal, int, 0); + MODULE_PARM_DESC(use_xtal, "Chip have a xtal connected in board"); + module_param(radio_nr, int, 0); + MODULE_PARM_DESC(radio_nr, "video4linux device number to use"); +- +-module_init(tea5764_init); +-module_exit(tea5764_exit); +Index: linux-3.3.x86_64/drivers/media/radio/saa7706h.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/saa7706h.c ++++ linux-3.3.x86_64/drivers/media/radio/saa7706h.c +@@ -434,18 +434,7 @@ static struct i2c_driver saa7706h_driver + .id_table = saa7706h_id, + }; + +-static __init int saa7706h_init(void) +-{ +- return i2c_add_driver(&saa7706h_driver); +-} +- +-static __exit void saa7706h_exit(void) +-{ +- i2c_del_driver(&saa7706h_driver); +-} +- +-module_init(saa7706h_init); +-module_exit(saa7706h_exit); ++module_i2c_driver(saa7706h_driver); + + MODULE_DESCRIPTION("SAA7706H Car Radio DSP driver"); + MODULE_AUTHOR("Mocean Laboratories"); +Index: linux-3.3.x86_64/drivers/media/radio/si470x/radio-si470x-i2c.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/si470x/radio-si470x-i2c.c ++++ linux-3.3.x86_64/drivers/media/radio/si470x/radio-si470x-i2c.c +@@ -539,33 +539,7 @@ static struct i2c_driver si470x_i2c_driv + .id_table = si470x_i2c_id, + }; + +- +- +-/************************************************************************** +- * Module Interface +- **************************************************************************/ +- +-/* +- * si470x_i2c_init - module init +- */ +-static int __init si470x_i2c_init(void) +-{ +- printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n"); +- return i2c_add_driver(&si470x_i2c_driver); +-} +- +- +-/* +- * si470x_i2c_exit - module exit +- */ +-static void __exit si470x_i2c_exit(void) +-{ +- i2c_del_driver(&si470x_i2c_driver); +-} +- +- +-module_init(si470x_i2c_init); +-module_exit(si470x_i2c_exit); ++module_i2c_driver(si470x_i2c_driver); + + MODULE_LICENSE("GPL"); + MODULE_AUTHOR(DRIVER_AUTHOR); +Index: linux-3.3.x86_64/drivers/media/radio/si4713-i2c.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/si4713-i2c.c ++++ linux-3.3.x86_64/drivers/media/radio/si4713-i2c.c +@@ -2106,17 +2106,4 @@ static struct i2c_driver si4713_i2c_driv + .id_table = si4713_id, + }; + +-/* Module Interface */ +-static int __init si4713_module_init(void) +-{ +- return i2c_add_driver(&si4713_i2c_driver); +-} +- +-static void __exit si4713_module_exit(void) +-{ +- i2c_del_driver(&si4713_i2c_driver); +-} +- +-module_init(si4713_module_init); +-module_exit(si4713_module_exit); +- ++module_i2c_driver(si4713_i2c_driver); +Index: linux-3.3.x86_64/drivers/media/radio/tef6862.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/tef6862.c ++++ linux-3.3.x86_64/drivers/media/radio/tef6862.c +@@ -215,20 +215,8 @@ static struct i2c_driver tef6862_driver + .id_table = tef6862_id, + }; + +-static __init int tef6862_init(void) +-{ +- return i2c_add_driver(&tef6862_driver); +-} +- +-static __exit void tef6862_exit(void) +-{ +- i2c_del_driver(&tef6862_driver); +-} +- +-module_init(tef6862_init); +-module_exit(tef6862_exit); ++module_i2c_driver(tef6862_driver); + + MODULE_DESCRIPTION("TEF6862 Car Radio Enhanced Selectivity Tuner"); + MODULE_AUTHOR("Mocean Laboratories"); + MODULE_LICENSE("GPL v2"); +- +Index: linux-3.3.x86_64/drivers/media/video/adp1653.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/adp1653.c ++++ linux-3.3.x86_64/drivers/media/video/adp1653.c +@@ -33,7 +33,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -482,24 +481,7 @@ static struct i2c_driver adp1653_i2c_dri + .id_table = adp1653_id_table, + }; + +-static int __init adp1653_init(void) +-{ +- int rval; +- +- rval = i2c_add_driver(&adp1653_i2c_driver); +- if (rval) +- printk(KERN_ALERT "%s: failed at i2c_add_driver\n", __func__); +- +- return rval; +-} +- +-static void __exit adp1653_exit(void) +-{ +- i2c_del_driver(&adp1653_i2c_driver); +-} +- +-module_init(adp1653_init); +-module_exit(adp1653_exit); ++module_i2c_driver(adp1653_i2c_driver); + + MODULE_AUTHOR("Sakari Ailus "); + MODULE_DESCRIPTION("Analog Devices ADP1653 LED flash driver"); +Index: linux-3.3.x86_64/drivers/media/video/adv7170.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/adv7170.c ++++ linux-3.3.x86_64/drivers/media/video/adv7170.c +@@ -407,15 +407,4 @@ static struct i2c_driver adv7170_driver + .id_table = adv7170_id, + }; + +-static __init int init_adv7170(void) +-{ +- return i2c_add_driver(&adv7170_driver); +-} +- +-static __exit void exit_adv7170(void) +-{ +- i2c_del_driver(&adv7170_driver); +-} +- +-module_init(init_adv7170); +-module_exit(exit_adv7170); ++module_i2c_driver(adv7170_driver); +Index: linux-3.3.x86_64/drivers/media/video/adv7175.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/adv7175.c ++++ linux-3.3.x86_64/drivers/media/video/adv7175.c +@@ -457,15 +457,4 @@ static struct i2c_driver adv7175_driver + .id_table = adv7175_id, + }; + +-static __init int init_adv7175(void) +-{ +- return i2c_add_driver(&adv7175_driver); +-} +- +-static __exit void exit_adv7175(void) +-{ +- i2c_del_driver(&adv7175_driver); +-} +- +-module_init(init_adv7175); +-module_exit(exit_adv7175); ++module_i2c_driver(adv7175_driver); +Index: linux-3.3.x86_64/drivers/media/video/adv7180.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/adv7180.c ++++ linux-3.3.x86_64/drivers/media/video/adv7180.c +@@ -444,20 +444,8 @@ static struct i2c_driver adv7180_driver + .id_table = adv7180_id, + }; + +-static __init int adv7180_init(void) +-{ +- return i2c_add_driver(&adv7180_driver); +-} +- +-static __exit void adv7180_exit(void) +-{ +- i2c_del_driver(&adv7180_driver); +-} +- +-module_init(adv7180_init); +-module_exit(adv7180_exit); ++module_i2c_driver(adv7180_driver); + + MODULE_DESCRIPTION("Analog Devices ADV7180 video decoder driver"); + MODULE_AUTHOR("Mocean Laboratories"); + MODULE_LICENSE("GPL v2"); +- +Index: linux-3.3.x86_64/drivers/media/video/adv7343.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/adv7343.c ++++ linux-3.3.x86_64/drivers/media/video/adv7343.c +@@ -475,15 +475,4 @@ static struct i2c_driver adv7343_driver + .id_table = adv7343_id, + }; + +-static __init int init_adv7343(void) +-{ +- return i2c_add_driver(&adv7343_driver); +-} +- +-static __exit void exit_adv7343(void) +-{ +- i2c_del_driver(&adv7343_driver); +-} +- +-module_init(init_adv7343); +-module_exit(exit_adv7343); ++module_i2c_driver(adv7343_driver); +Index: linux-3.3.x86_64/drivers/media/video/ak881x.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ak881x.c ++++ linux-3.3.x86_64/drivers/media/video/ak881x.c +@@ -352,18 +352,7 @@ static struct i2c_driver ak881x_i2c_driv + .id_table = ak881x_id, + }; + +-static int __init ak881x_module_init(void) +-{ +- return i2c_add_driver(&ak881x_i2c_driver); +-} +- +-static void __exit ak881x_module_exit(void) +-{ +- i2c_del_driver(&ak881x_i2c_driver); +-} +- +-module_init(ak881x_module_init); +-module_exit(ak881x_module_exit); ++module_i2c_driver(ak881x_i2c_driver); + + MODULE_DESCRIPTION("TV-output driver for ak8813/ak8814"); + MODULE_AUTHOR("Guennadi Liakhovetski "); +Index: linux-3.3.x86_64/drivers/media/video/as3645a.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/as3645a.c ++++ linux-3.3.x86_64/drivers/media/video/as3645a.c +@@ -881,24 +881,7 @@ static struct i2c_driver as3645a_i2c_dri + .id_table = as3645a_id_table, + }; + +-static int __init as3645a_init(void) +-{ +- int rval; +- +- rval = i2c_add_driver(&as3645a_i2c_driver); +- if (rval) +- pr_err("%s: Failed to register the driver\n", AS3645A_NAME); +- +- return rval; +-} +- +-static void __exit as3645a_exit(void) +-{ +- i2c_del_driver(&as3645a_i2c_driver); +-} +- +-module_init(as3645a_init); +-module_exit(as3645a_exit); ++module_i2c_driver(as3645a_i2c_driver); + + MODULE_AUTHOR("Laurent Pinchart "); + MODULE_DESCRIPTION("LED flash driver for AS3645A, LM3555 and their clones"); +Index: linux-3.3.x86_64/drivers/media/video/bt819.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/bt819.c ++++ linux-3.3.x86_64/drivers/media/video/bt819.c +@@ -514,15 +514,4 @@ static struct i2c_driver bt819_driver = + .id_table = bt819_id, + }; + +-static __init int init_bt819(void) +-{ +- return i2c_add_driver(&bt819_driver); +-} +- +-static __exit void exit_bt819(void) +-{ +- i2c_del_driver(&bt819_driver); +-} +- +-module_init(init_bt819); +-module_exit(exit_bt819); ++module_i2c_driver(bt819_driver); +Index: linux-3.3.x86_64/drivers/media/video/bt856.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/bt856.c ++++ linux-3.3.x86_64/drivers/media/video/bt856.c +@@ -270,15 +270,4 @@ static struct i2c_driver bt856_driver = + .id_table = bt856_id, + }; + +-static __init int init_bt856(void) +-{ +- return i2c_add_driver(&bt856_driver); +-} +- +-static __exit void exit_bt856(void) +-{ +- i2c_del_driver(&bt856_driver); +-} +- +-module_init(init_bt856); +-module_exit(exit_bt856); ++module_i2c_driver(bt856_driver); +Index: linux-3.3.x86_64/drivers/media/video/bt866.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/bt866.c ++++ linux-3.3.x86_64/drivers/media/video/bt866.c +@@ -240,15 +240,4 @@ static struct i2c_driver bt866_driver = + .id_table = bt866_id, + }; + +-static __init int init_bt866(void) +-{ +- return i2c_add_driver(&bt866_driver); +-} +- +-static __exit void exit_bt866(void) +-{ +- i2c_del_driver(&bt866_driver); +-} +- +-module_init(init_bt866); +-module_exit(exit_bt866); ++module_i2c_driver(bt866_driver); +Index: linux-3.3.x86_64/drivers/media/video/cs5345.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cs5345.c ++++ linux-3.3.x86_64/drivers/media/video/cs5345.c +@@ -249,15 +249,4 @@ static struct i2c_driver cs5345_driver = + .id_table = cs5345_id, + }; + +-static __init int init_cs5345(void) +-{ +- return i2c_add_driver(&cs5345_driver); +-} +- +-static __exit void exit_cs5345(void) +-{ +- i2c_del_driver(&cs5345_driver); +-} +- +-module_init(init_cs5345); +-module_exit(exit_cs5345); ++module_i2c_driver(cs5345_driver); +Index: linux-3.3.x86_64/drivers/media/video/cs53l32a.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cs53l32a.c ++++ linux-3.3.x86_64/drivers/media/video/cs53l32a.c +@@ -248,15 +248,4 @@ static struct i2c_driver cs53l32a_driver + .id_table = cs53l32a_id, + }; + +-static __init int init_cs53l32a(void) +-{ +- return i2c_add_driver(&cs53l32a_driver); +-} +- +-static __exit void exit_cs53l32a(void) +-{ +- i2c_del_driver(&cs53l32a_driver); +-} +- +-module_init(init_cs53l32a); +-module_exit(exit_cs53l32a); ++module_i2c_driver(cs53l32a_driver); +Index: linux-3.3.x86_64/drivers/media/video/cx25840/cx25840-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx25840/cx25840-core.c ++++ linux-3.3.x86_64/drivers/media/video/cx25840/cx25840-core.c +@@ -5301,15 +5301,4 @@ static struct i2c_driver cx25840_driver + .id_table = cx25840_id, + }; + +-static __init int init_cx25840(void) +-{ +- return i2c_add_driver(&cx25840_driver); +-} +- +-static __exit void exit_cx25840(void) +-{ +- i2c_del_driver(&cx25840_driver); +-} +- +-module_init(init_cx25840); +-module_exit(exit_cx25840); ++module_i2c_driver(cx25840_driver); +Index: linux-3.3.x86_64/drivers/media/video/imx074.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/imx074.c ++++ linux-3.3.x86_64/drivers/media/video/imx074.c +@@ -468,18 +468,7 @@ static struct i2c_driver imx074_i2c_driv + .id_table = imx074_id, + }; + +-static int __init imx074_mod_init(void) +-{ +- return i2c_add_driver(&imx074_i2c_driver); +-} +- +-static void __exit imx074_mod_exit(void) +-{ +- i2c_del_driver(&imx074_i2c_driver); +-} +- +-module_init(imx074_mod_init); +-module_exit(imx074_mod_exit); ++module_i2c_driver(imx074_i2c_driver); + + MODULE_DESCRIPTION("Sony IMX074 Camera driver"); + MODULE_AUTHOR("Guennadi Liakhovetski "); +Index: linux-3.3.x86_64/drivers/media/video/indycam.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/indycam.c ++++ linux-3.3.x86_64/drivers/media/video/indycam.c +@@ -387,15 +387,4 @@ static struct i2c_driver indycam_driver + .id_table = indycam_id, + }; + +-static __init int init_indycam(void) +-{ +- return i2c_add_driver(&indycam_driver); +-} +- +-static __exit void exit_indycam(void) +-{ +- i2c_del_driver(&indycam_driver); +-} +- +-module_init(init_indycam); +-module_exit(exit_indycam); ++module_i2c_driver(indycam_driver); +Index: linux-3.3.x86_64/drivers/media/video/ir-kbd-i2c.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ir-kbd-i2c.c ++++ linux-3.3.x86_64/drivers/media/video/ir-kbd-i2c.c +@@ -471,7 +471,7 @@ static const struct i2c_device_id ir_kbd + { } + }; + +-static struct i2c_driver driver = { ++static struct i2c_driver ir_kbd_driver = { + .driver = { + .name = "ir-kbd-i2c", + }, +@@ -480,21 +480,10 @@ static struct i2c_driver driver = { + .id_table = ir_kbd_id, + }; + ++module_i2c_driver(ir_kbd_driver); ++ + /* ----------------------------------------------------------------------- */ + + MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller"); + MODULE_DESCRIPTION("input driver for i2c IR remote controls"); + MODULE_LICENSE("GPL"); +- +-static int __init ir_init(void) +-{ +- return i2c_add_driver(&driver); +-} +- +-static void __exit ir_fini(void) +-{ +- i2c_del_driver(&driver); +-} +- +-module_init(ir_init); +-module_exit(ir_fini); +Index: linux-3.3.x86_64/drivers/media/video/ks0127.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ks0127.c ++++ linux-3.3.x86_64/drivers/media/video/ks0127.c +@@ -721,15 +721,4 @@ static struct i2c_driver ks0127_driver = + .id_table = ks0127_id, + }; + +-static __init int init_ks0127(void) +-{ +- return i2c_add_driver(&ks0127_driver); +-} +- +-static __exit void exit_ks0127(void) +-{ +- i2c_del_driver(&ks0127_driver); +-} +- +-module_init(init_ks0127); +-module_exit(exit_ks0127); ++module_i2c_driver(ks0127_driver); +Index: linux-3.3.x86_64/drivers/media/video/m52790.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/m52790.c ++++ linux-3.3.x86_64/drivers/media/video/m52790.c +@@ -213,15 +213,4 @@ static struct i2c_driver m52790_driver = + .id_table = m52790_id, + }; + +-static __init int init_m52790(void) +-{ +- return i2c_add_driver(&m52790_driver); +-} +- +-static __exit void exit_m52790(void) +-{ +- i2c_del_driver(&m52790_driver); +-} +- +-module_init(init_m52790); +-module_exit(exit_m52790); ++module_i2c_driver(m52790_driver); +Index: linux-3.3.x86_64/drivers/media/video/msp3400-driver.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/msp3400-driver.c ++++ linux-3.3.x86_64/drivers/media/video/msp3400-driver.c +@@ -881,18 +881,7 @@ static struct i2c_driver msp_driver = { + .id_table = msp_id, + }; + +-static __init int init_msp(void) +-{ +- return i2c_add_driver(&msp_driver); +-} +- +-static __exit void exit_msp(void) +-{ +- i2c_del_driver(&msp_driver); +-} +- +-module_init(init_msp); +-module_exit(exit_msp); ++module_i2c_driver(msp_driver); + + /* + * Overrides for Emacs so that we follow Linus's tabbing style. +Index: linux-3.3.x86_64/drivers/media/video/mt9m001.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9m001.c ++++ linux-3.3.x86_64/drivers/media/video/mt9m001.c +@@ -730,18 +730,7 @@ static struct i2c_driver mt9m001_i2c_dri + .id_table = mt9m001_id, + }; + +-static int __init mt9m001_mod_init(void) +-{ +- return i2c_add_driver(&mt9m001_i2c_driver); +-} +- +-static void __exit mt9m001_mod_exit(void) +-{ +- i2c_del_driver(&mt9m001_i2c_driver); +-} +- +-module_init(mt9m001_mod_init); +-module_exit(mt9m001_mod_exit); ++module_i2c_driver(mt9m001_i2c_driver); + + MODULE_DESCRIPTION("Micron MT9M001 Camera driver"); + MODULE_AUTHOR("Guennadi Liakhovetski "); +Index: linux-3.3.x86_64/drivers/media/video/mt9m111.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9m111.c ++++ linux-3.3.x86_64/drivers/media/video/mt9m111.c +@@ -1008,18 +1008,7 @@ static struct i2c_driver mt9m111_i2c_dri + .id_table = mt9m111_id, + }; + +-static int __init mt9m111_mod_init(void) +-{ +- return i2c_add_driver(&mt9m111_i2c_driver); +-} +- +-static void __exit mt9m111_mod_exit(void) +-{ +- i2c_del_driver(&mt9m111_i2c_driver); +-} +- +-module_init(mt9m111_mod_init); +-module_exit(mt9m111_mod_exit); ++module_i2c_driver(mt9m111_i2c_driver); + + MODULE_DESCRIPTION("Micron/Aptina MT9M111/MT9M112/MT9M131 Camera driver"); + MODULE_AUTHOR("Robert Jarzmik"); +Index: linux-3.3.x86_64/drivers/media/video/mt9p031.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9p031.c ++++ linux-3.3.x86_64/drivers/media/video/mt9p031.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + + #include +@@ -28,6 +27,8 @@ + #include + #include + ++#include "aptina-pll.h" ++ + #define MT9P031_PIXEL_ARRAY_WIDTH 2752 + #define MT9P031_PIXEL_ARRAY_HEIGHT 2004 + +@@ -98,14 +99,6 @@ + #define MT9P031_TEST_PATTERN_RED 0xa2 + #define MT9P031_TEST_PATTERN_BLUE 0xa3 + +-struct mt9p031_pll_divs { +- u32 ext_freq; +- u32 target_freq; +- u8 m; +- u8 n; +- u8 p1; +-}; +- + struct mt9p031 { + struct v4l2_subdev subdev; + struct media_pad pad; +@@ -115,10 +108,8 @@ struct mt9p031 { + struct mt9p031_platform_data *pdata; + struct mutex power_lock; /* lock to protect power_count */ + int power_count; +- u16 xskip; +- u16 yskip; + +- const struct mt9p031_pll_divs *pll; ++ struct aptina_pll pll; + + /* Registers cache */ + u16 output_control; +@@ -186,33 +177,31 @@ static int mt9p031_reset(struct mt9p031 + 0); + } + +-/* +- * This static table uses ext_freq and vdd_io values to select suitable +- * PLL dividers m, n and p1 which have been calculated as specifiec in p36 +- * of Aptina's mt9p031 datasheet. New values should be added here. +- */ +-static const struct mt9p031_pll_divs mt9p031_divs[] = { +- /* ext_freq target_freq m n p1 */ +- {21000000, 48000000, 26, 2, 6} +-}; +- +-static int mt9p031_pll_get_divs(struct mt9p031 *mt9p031) ++static int mt9p031_pll_setup(struct mt9p031 *mt9p031) + { ++ static const struct aptina_pll_limits limits = { ++ .ext_clock_min = 6000000, ++ .ext_clock_max = 27000000, ++ .int_clock_min = 2000000, ++ .int_clock_max = 13500000, ++ .out_clock_min = 180000000, ++ .out_clock_max = 360000000, ++ .pix_clock_max = 96000000, ++ .n_min = 1, ++ .n_max = 64, ++ .m_min = 16, ++ .m_max = 255, ++ .p1_min = 1, ++ .p1_max = 128, ++ }; ++ + struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); +- int i; ++ struct mt9p031_platform_data *pdata = mt9p031->pdata; + +- for (i = 0; i < ARRAY_SIZE(mt9p031_divs); i++) { +- if (mt9p031_divs[i].ext_freq == mt9p031->pdata->ext_freq && +- mt9p031_divs[i].target_freq == mt9p031->pdata->target_freq) { +- mt9p031->pll = &mt9p031_divs[i]; +- return 0; +- } +- } ++ mt9p031->pll.ext_clock = pdata->ext_freq; ++ mt9p031->pll.pix_clock = pdata->target_freq; + +- dev_err(&client->dev, "Couldn't find PLL dividers for ext_freq = %d, " +- "target_freq = %d\n", mt9p031->pdata->ext_freq, +- mt9p031->pdata->target_freq); +- return -EINVAL; ++ return aptina_pll_calculate(&client->dev, &limits, &mt9p031->pll); + } + + static int mt9p031_pll_enable(struct mt9p031 *mt9p031) +@@ -226,11 +215,11 @@ static int mt9p031_pll_enable(struct mt9 + return ret; + + ret = mt9p031_write(client, MT9P031_PLL_CONFIG_1, +- (mt9p031->pll->m << 8) | (mt9p031->pll->n - 1)); ++ (mt9p031->pll.m << 8) | (mt9p031->pll.n - 1)); + if (ret < 0) + return ret; + +- ret = mt9p031_write(client, MT9P031_PLL_CONFIG_2, mt9p031->pll->p1 - 1); ++ ret = mt9p031_write(client, MT9P031_PLL_CONFIG_2, mt9p031->pll.p1 - 1); + if (ret < 0) + return ret; + +@@ -785,8 +774,6 @@ static int mt9p031_open(struct v4l2_subd + format->field = V4L2_FIELD_NONE; + format->colorspace = V4L2_COLORSPACE_SRGB; + +- mt9p031->xskip = 1; +- mt9p031->yskip = 1; + return mt9p031_set_power(subdev, 1); + } + +@@ -905,7 +892,7 @@ static int mt9p031_probe(struct i2c_clie + mt9p031->format.field = V4L2_FIELD_NONE; + mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB; + +- ret = mt9p031_pll_get_divs(mt9p031); ++ ret = mt9p031_pll_setup(mt9p031); + + done: + if (ret < 0) { +@@ -945,18 +932,7 @@ static struct i2c_driver mt9p031_i2c_dri + .id_table = mt9p031_id, + }; + +-static int __init mt9p031_mod_init(void) +-{ +- return i2c_add_driver(&mt9p031_i2c_driver); +-} +- +-static void __exit mt9p031_mod_exit(void) +-{ +- i2c_del_driver(&mt9p031_i2c_driver); +-} +- +-module_init(mt9p031_mod_init); +-module_exit(mt9p031_mod_exit); ++module_i2c_driver(mt9p031_i2c_driver); + + MODULE_DESCRIPTION("Aptina MT9P031 Camera driver"); + MODULE_AUTHOR("Bastian Hecht "); +Index: linux-3.3.x86_64/drivers/media/video/mt9t001.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9t001.c ++++ linux-3.3.x86_64/drivers/media/video/mt9t001.c +@@ -817,18 +817,7 @@ static struct i2c_driver mt9t001_driver + .id_table = mt9t001_id, + }; + +-static int __init mt9t001_init(void) +-{ +- return i2c_add_driver(&mt9t001_driver); +-} +- +-static void __exit mt9t001_exit(void) +-{ +- i2c_del_driver(&mt9t001_driver); +-} +- +-module_init(mt9t001_init); +-module_exit(mt9t001_exit); ++module_i2c_driver(mt9t001_driver); + + MODULE_DESCRIPTION("Aptina (Micron) MT9T001 Camera driver"); + MODULE_AUTHOR("Laurent Pinchart "); +Index: linux-3.3.x86_64/drivers/media/video/mt9t031.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9t031.c ++++ linux-3.3.x86_64/drivers/media/video/mt9t031.c +@@ -850,18 +850,7 @@ static struct i2c_driver mt9t031_i2c_dri + .id_table = mt9t031_id, + }; + +-static int __init mt9t031_mod_init(void) +-{ +- return i2c_add_driver(&mt9t031_i2c_driver); +-} +- +-static void __exit mt9t031_mod_exit(void) +-{ +- i2c_del_driver(&mt9t031_i2c_driver); +-} +- +-module_init(mt9t031_mod_init); +-module_exit(mt9t031_mod_exit); ++module_i2c_driver(mt9t031_i2c_driver); + + MODULE_DESCRIPTION("Micron MT9T031 Camera driver"); + MODULE_AUTHOR("Guennadi Liakhovetski "); +Index: linux-3.3.x86_64/drivers/media/video/mt9t112.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9t112.c ++++ linux-3.3.x86_64/drivers/media/video/mt9t112.c +@@ -1117,21 +1117,7 @@ static struct i2c_driver mt9t112_i2c_dri + .id_table = mt9t112_id, + }; + +-/************************************************************************ +- module function +-************************************************************************/ +-static int __init mt9t112_module_init(void) +-{ +- return i2c_add_driver(&mt9t112_i2c_driver); +-} +- +-static void __exit mt9t112_module_exit(void) +-{ +- i2c_del_driver(&mt9t112_i2c_driver); +-} +- +-module_init(mt9t112_module_init); +-module_exit(mt9t112_module_exit); ++module_i2c_driver(mt9t112_i2c_driver); + + MODULE_DESCRIPTION("SoC Camera driver for mt9t112"); + MODULE_AUTHOR("Kuninori Morimoto"); +Index: linux-3.3.x86_64/drivers/media/video/mt9v011.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9v011.c ++++ linux-3.3.x86_64/drivers/media/video/mt9v011.c +@@ -709,15 +709,4 @@ static struct i2c_driver mt9v011_driver + .id_table = mt9v011_id, + }; + +-static __init int init_mt9v011(void) +-{ +- return i2c_add_driver(&mt9v011_driver); +-} +- +-static __exit void exit_mt9v011(void) +-{ +- i2c_del_driver(&mt9v011_driver); +-} +- +-module_init(init_mt9v011); +-module_exit(exit_mt9v011); ++module_i2c_driver(mt9v011_driver); +Index: linux-3.3.x86_64/drivers/media/video/mt9v022.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9v022.c ++++ linux-3.3.x86_64/drivers/media/video/mt9v022.c +@@ -872,18 +872,7 @@ static struct i2c_driver mt9v022_i2c_dri + .id_table = mt9v022_id, + }; + +-static int __init mt9v022_mod_init(void) +-{ +- return i2c_add_driver(&mt9v022_i2c_driver); +-} +- +-static void __exit mt9v022_mod_exit(void) +-{ +- i2c_del_driver(&mt9v022_i2c_driver); +-} +- +-module_init(mt9v022_mod_init); +-module_exit(mt9v022_mod_exit); ++module_i2c_driver(mt9v022_i2c_driver); + + MODULE_DESCRIPTION("Micron MT9V022 Camera driver"); + MODULE_AUTHOR("Guennadi Liakhovetski "); +Index: linux-3.3.x86_64/drivers/media/video/mt9v032.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9v032.c ++++ linux-3.3.x86_64/drivers/media/video/mt9v032.c +@@ -756,18 +756,7 @@ static struct i2c_driver mt9v032_driver + .id_table = mt9v032_id, + }; + +-static int __init mt9v032_init(void) +-{ +- return i2c_add_driver(&mt9v032_driver); +-} +- +-static void __exit mt9v032_exit(void) +-{ +- i2c_del_driver(&mt9v032_driver); +-} +- +-module_init(mt9v032_init); +-module_exit(mt9v032_exit); ++module_i2c_driver(mt9v032_driver); + + MODULE_DESCRIPTION("Aptina MT9V032 Camera driver"); + MODULE_AUTHOR("Laurent Pinchart "); +Index: linux-3.3.x86_64/drivers/media/video/ov2640.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ov2640.c ++++ linux-3.3.x86_64/drivers/media/video/ov2640.c +@@ -1103,21 +1103,7 @@ static struct i2c_driver ov2640_i2c_driv + .id_table = ov2640_id, + }; + +-/* +- * Module functions +- */ +-static int __init ov2640_module_init(void) +-{ +- return i2c_add_driver(&ov2640_i2c_driver); +-} +- +-static void __exit ov2640_module_exit(void) +-{ +- i2c_del_driver(&ov2640_i2c_driver); +-} +- +-module_init(ov2640_module_init); +-module_exit(ov2640_module_exit); ++module_i2c_driver(ov2640_i2c_driver); + + MODULE_DESCRIPTION("SoC Camera driver for Omni Vision 2640 sensor"); + MODULE_AUTHOR("Alberto Panizzo"); +Index: linux-3.3.x86_64/drivers/media/video/ov5642.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ov5642.c ++++ linux-3.3.x86_64/drivers/media/video/ov5642.c +@@ -1068,18 +1068,7 @@ static struct i2c_driver ov5642_i2c_driv + .id_table = ov5642_id, + }; + +-static int __init ov5642_mod_init(void) +-{ +- return i2c_add_driver(&ov5642_i2c_driver); +-} +- +-static void __exit ov5642_mod_exit(void) +-{ +- i2c_del_driver(&ov5642_i2c_driver); +-} +- +-module_init(ov5642_mod_init); +-module_exit(ov5642_mod_exit); ++module_i2c_driver(ov5642_i2c_driver); + + MODULE_DESCRIPTION("Omnivision OV5642 Camera driver"); + MODULE_AUTHOR("Bastian Hecht "); +Index: linux-3.3.x86_64/drivers/media/video/ov7670.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ov7670.c ++++ linux-3.3.x86_64/drivers/media/video/ov7670.c +@@ -1583,15 +1583,4 @@ static struct i2c_driver ov7670_driver = + .id_table = ov7670_id, + }; + +-static __init int init_ov7670(void) +-{ +- return i2c_add_driver(&ov7670_driver); +-} +- +-static __exit void exit_ov7670(void) +-{ +- i2c_del_driver(&ov7670_driver); +-} +- +-module_init(init_ov7670); +-module_exit(exit_ov7670); ++module_i2c_driver(ov7670_driver); +Index: linux-3.3.x86_64/drivers/media/video/ov772x.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ov772x.c ++++ linux-3.3.x86_64/drivers/media/video/ov772x.c +@@ -1123,22 +1123,7 @@ static struct i2c_driver ov772x_i2c_driv + .id_table = ov772x_id, + }; + +-/* +- * module function +- */ +- +-static int __init ov772x_module_init(void) +-{ +- return i2c_add_driver(&ov772x_i2c_driver); +-} +- +-static void __exit ov772x_module_exit(void) +-{ +- i2c_del_driver(&ov772x_i2c_driver); +-} +- +-module_init(ov772x_module_init); +-module_exit(ov772x_module_exit); ++module_i2c_driver(ov772x_i2c_driver); + + MODULE_DESCRIPTION("SoC Camera driver for ov772x"); + MODULE_AUTHOR("Kuninori Morimoto"); +Index: linux-3.3.x86_64/drivers/media/video/ov9640.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ov9640.c ++++ linux-3.3.x86_64/drivers/media/video/ov9640.c +@@ -738,18 +738,7 @@ static struct i2c_driver ov9640_i2c_driv + .id_table = ov9640_id, + }; + +-static int __init ov9640_module_init(void) +-{ +- return i2c_add_driver(&ov9640_i2c_driver); +-} +- +-static void __exit ov9640_module_exit(void) +-{ +- i2c_del_driver(&ov9640_i2c_driver); +-} +- +-module_init(ov9640_module_init); +-module_exit(ov9640_module_exit); ++module_i2c_driver(ov9640_i2c_driver); + + MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV96xx"); + MODULE_AUTHOR("Marek Vasut "); +Index: linux-3.3.x86_64/drivers/media/video/ov9740.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ov9740.c ++++ linux-3.3.x86_64/drivers/media/video/ov9740.c +@@ -998,18 +998,7 @@ static struct i2c_driver ov9740_i2c_driv + .id_table = ov9740_id, + }; + +-static int __init ov9740_module_init(void) +-{ +- return i2c_add_driver(&ov9740_i2c_driver); +-} +- +-static void __exit ov9740_module_exit(void) +-{ +- i2c_del_driver(&ov9740_i2c_driver); +-} +- +-module_init(ov9740_module_init); +-module_exit(ov9740_module_exit); ++module_i2c_driver(ov9740_i2c_driver); + + MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV9740"); + MODULE_AUTHOR("Andrew Chew "); +Index: linux-3.3.x86_64/drivers/media/video/rj54n1cb0c.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/rj54n1cb0c.c ++++ linux-3.3.x86_64/drivers/media/video/rj54n1cb0c.c +@@ -1407,18 +1407,7 @@ static struct i2c_driver rj54n1_i2c_driv + .id_table = rj54n1_id, + }; + +-static int __init rj54n1_mod_init(void) +-{ +- return i2c_add_driver(&rj54n1_i2c_driver); +-} +- +-static void __exit rj54n1_mod_exit(void) +-{ +- i2c_del_driver(&rj54n1_i2c_driver); +-} +- +-module_init(rj54n1_mod_init); +-module_exit(rj54n1_mod_exit); ++module_i2c_driver(rj54n1_i2c_driver); + + MODULE_DESCRIPTION("Sharp RJ54N1CB0C Camera driver"); + MODULE_AUTHOR("Guennadi Liakhovetski "); +Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/hdmiphy_drv.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/hdmiphy_drv.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-tv/hdmiphy_drv.c +@@ -175,14 +175,4 @@ static struct i2c_driver hdmiphy_driver + .id_table = hdmiphy_id, + }; + +-static int __init hdmiphy_init(void) +-{ +- return i2c_add_driver(&hdmiphy_driver); +-} +-module_init(hdmiphy_init); +- +-static void __exit hdmiphy_exit(void) +-{ +- i2c_del_driver(&hdmiphy_driver); +-} +-module_exit(hdmiphy_exit); ++module_i2c_driver(hdmiphy_driver); +Index: linux-3.3.x86_64/drivers/media/video/saa6588.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa6588.c ++++ linux-3.3.x86_64/drivers/media/video/saa6588.c +@@ -539,15 +539,4 @@ static struct i2c_driver saa6588_driver + .id_table = saa6588_id, + }; + +-static __init int init_saa6588(void) +-{ +- return i2c_add_driver(&saa6588_driver); +-} +- +-static __exit void exit_saa6588(void) +-{ +- i2c_del_driver(&saa6588_driver); +-} +- +-module_init(init_saa6588); +-module_exit(exit_saa6588); ++module_i2c_driver(saa6588_driver); +Index: linux-3.3.x86_64/drivers/media/video/saa7110.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7110.c ++++ linux-3.3.x86_64/drivers/media/video/saa7110.c +@@ -491,15 +491,4 @@ static struct i2c_driver saa7110_driver + .id_table = saa7110_id, + }; + +-static __init int init_saa7110(void) +-{ +- return i2c_add_driver(&saa7110_driver); +-} +- +-static __exit void exit_saa7110(void) +-{ +- i2c_del_driver(&saa7110_driver); +-} +- +-module_init(init_saa7110); +-module_exit(exit_saa7110); ++module_i2c_driver(saa7110_driver); +Index: linux-3.3.x86_64/drivers/media/video/saa7115.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7115.c ++++ linux-3.3.x86_64/drivers/media/video/saa7115.c +@@ -1724,15 +1724,4 @@ static struct i2c_driver saa711x_driver + .id_table = saa711x_id, + }; + +-static __init int init_saa711x(void) +-{ +- return i2c_add_driver(&saa711x_driver); +-} +- +-static __exit void exit_saa711x(void) +-{ +- i2c_del_driver(&saa711x_driver); +-} +- +-module_init(init_saa711x); +-module_exit(exit_saa711x); ++module_i2c_driver(saa711x_driver); +Index: linux-3.3.x86_64/drivers/media/video/saa7127.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7127.c ++++ linux-3.3.x86_64/drivers/media/video/saa7127.c +@@ -852,15 +852,4 @@ static struct i2c_driver saa7127_driver + .id_table = saa7127_id, + }; + +-static __init int init_saa7127(void) +-{ +- return i2c_add_driver(&saa7127_driver); +-} +- +-static __exit void exit_saa7127(void) +-{ +- i2c_del_driver(&saa7127_driver); +-} +- +-module_init(init_saa7127); +-module_exit(exit_saa7127); ++module_i2c_driver(saa7127_driver); +Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa6752hs.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa6752hs.c ++++ linux-3.3.x86_64/drivers/media/video/saa7134/saa6752hs.c +@@ -1001,18 +1001,7 @@ static struct i2c_driver saa6752hs_drive + .id_table = saa6752hs_id, + }; + +-static __init int init_saa6752hs(void) +-{ +- return i2c_add_driver(&saa6752hs_driver); +-} +- +-static __exit void exit_saa6752hs(void) +-{ +- i2c_del_driver(&saa6752hs_driver); +-} +- +-module_init(init_saa6752hs); +-module_exit(exit_saa6752hs); ++module_i2c_driver(saa6752hs_driver); + + /* + * Overrides for Emacs so that we follow Linus's tabbing style. +Index: linux-3.3.x86_64/drivers/media/video/saa717x.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa717x.c ++++ linux-3.3.x86_64/drivers/media/video/saa717x.c +@@ -1375,15 +1375,4 @@ static struct i2c_driver saa717x_driver + .id_table = saa717x_id, + }; + +-static __init int init_saa717x(void) +-{ +- return i2c_add_driver(&saa717x_driver); +-} +- +-static __exit void exit_saa717x(void) +-{ +- i2c_del_driver(&saa717x_driver); +-} +- +-module_init(init_saa717x); +-module_exit(exit_saa717x); ++module_i2c_driver(saa717x_driver); +Index: linux-3.3.x86_64/drivers/media/video/saa7185.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7185.c ++++ linux-3.3.x86_64/drivers/media/video/saa7185.c +@@ -374,15 +374,4 @@ static struct i2c_driver saa7185_driver + .id_table = saa7185_id, + }; + +-static __init int init_saa7185(void) +-{ +- return i2c_add_driver(&saa7185_driver); +-} +- +-static __exit void exit_saa7185(void) +-{ +- i2c_del_driver(&saa7185_driver); +-} +- +-module_init(init_saa7185); +-module_exit(exit_saa7185); ++module_i2c_driver(saa7185_driver); +Index: linux-3.3.x86_64/drivers/media/video/saa7191.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7191.c ++++ linux-3.3.x86_64/drivers/media/video/saa7191.c +@@ -656,15 +656,4 @@ static struct i2c_driver saa7191_driver + .id_table = saa7191_id, + }; + +-static __init int init_saa7191(void) +-{ +- return i2c_add_driver(&saa7191_driver); +-} +- +-static __exit void exit_saa7191(void) +-{ +- i2c_del_driver(&saa7191_driver); +-} +- +-module_init(init_saa7191); +-module_exit(exit_saa7191); ++module_i2c_driver(saa7191_driver); +Index: linux-3.3.x86_64/drivers/media/video/sr030pc30.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/sr030pc30.c ++++ linux-3.3.x86_64/drivers/media/video/sr030pc30.c +@@ -864,18 +864,7 @@ static struct i2c_driver sr030pc30_i2c_d + .id_table = sr030pc30_id, + }; + +-static int __init sr030pc30_init(void) +-{ +- return i2c_add_driver(&sr030pc30_i2c_driver); +-} +- +-static void __exit sr030pc30_exit(void) +-{ +- i2c_del_driver(&sr030pc30_i2c_driver); +-} +- +-module_init(sr030pc30_init); +-module_exit(sr030pc30_exit); ++module_i2c_driver(sr030pc30_i2c_driver); + + MODULE_DESCRIPTION("Siliconfile SR030PC30 camera driver"); + MODULE_AUTHOR("Sylwester Nawrocki "); +Index: linux-3.3.x86_64/drivers/media/video/tda7432.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tda7432.c ++++ linux-3.3.x86_64/drivers/media/video/tda7432.c +@@ -482,15 +482,4 @@ static struct i2c_driver tda7432_driver + .id_table = tda7432_id, + }; + +-static __init int init_tda7432(void) +-{ +- return i2c_add_driver(&tda7432_driver); +-} +- +-static __exit void exit_tda7432(void) +-{ +- i2c_del_driver(&tda7432_driver); +-} +- +-module_init(init_tda7432); +-module_exit(exit_tda7432); ++module_i2c_driver(tda7432_driver); +Index: linux-3.3.x86_64/drivers/media/video/tda9840.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tda9840.c ++++ linux-3.3.x86_64/drivers/media/video/tda9840.c +@@ -208,15 +208,4 @@ static struct i2c_driver tda9840_driver + .id_table = tda9840_id, + }; + +-static __init int init_tda9840(void) +-{ +- return i2c_add_driver(&tda9840_driver); +-} +- +-static __exit void exit_tda9840(void) +-{ +- i2c_del_driver(&tda9840_driver); +-} +- +-module_init(init_tda9840); +-module_exit(exit_tda9840); ++module_i2c_driver(tda9840_driver); +Index: linux-3.3.x86_64/drivers/media/video/tea6415c.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tea6415c.c ++++ linux-3.3.x86_64/drivers/media/video/tea6415c.c +@@ -184,15 +184,4 @@ static struct i2c_driver tea6415c_driver + .id_table = tea6415c_id, + }; + +-static __init int init_tea6415c(void) +-{ +- return i2c_add_driver(&tea6415c_driver); +-} +- +-static __exit void exit_tea6415c(void) +-{ +- i2c_del_driver(&tea6415c_driver); +-} +- +-module_init(init_tea6415c); +-module_exit(exit_tea6415c); ++module_i2c_driver(tea6415c_driver); +Index: linux-3.3.x86_64/drivers/media/video/tea6420.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tea6420.c ++++ linux-3.3.x86_64/drivers/media/video/tea6420.c +@@ -166,15 +166,4 @@ static struct i2c_driver tea6420_driver + .id_table = tea6420_id, + }; + +-static __init int init_tea6420(void) +-{ +- return i2c_add_driver(&tea6420_driver); +-} +- +-static __exit void exit_tea6420(void) +-{ +- i2c_del_driver(&tea6420_driver); +-} +- +-module_init(init_tea6420); +-module_exit(exit_tea6420); ++module_i2c_driver(tea6420_driver); +Index: linux-3.3.x86_64/drivers/media/video/ths7303.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ths7303.c ++++ linux-3.3.x86_64/drivers/media/video/ths7303.c +@@ -137,16 +137,4 @@ static struct i2c_driver ths7303_driver + .id_table = ths7303_id, + }; + +-static int __init ths7303_init(void) +-{ +- return i2c_add_driver(&ths7303_driver); +-} +- +-static void __exit ths7303_exit(void) +-{ +- i2c_del_driver(&ths7303_driver); +-} +- +-module_init(ths7303_init); +-module_exit(ths7303_exit); +- ++module_i2c_driver(ths7303_driver); +Index: linux-3.3.x86_64/drivers/media/video/tlv320aic23b.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tlv320aic23b.c ++++ linux-3.3.x86_64/drivers/media/video/tlv320aic23b.c +@@ -227,15 +227,4 @@ static struct i2c_driver tlv320aic23b_dr + .id_table = tlv320aic23b_id, + }; + +-static __init int init_tlv320aic23b(void) +-{ +- return i2c_add_driver(&tlv320aic23b_driver); +-} +- +-static __exit void exit_tlv320aic23b(void) +-{ +- i2c_del_driver(&tlv320aic23b_driver); +-} +- +-module_init(init_tlv320aic23b); +-module_exit(exit_tlv320aic23b); ++module_i2c_driver(tlv320aic23b_driver); +Index: linux-3.3.x86_64/drivers/media/video/tvaudio.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tvaudio.c ++++ linux-3.3.x86_64/drivers/media/video/tvaudio.c +@@ -2078,15 +2078,4 @@ static struct i2c_driver tvaudio_driver + .id_table = tvaudio_id, + }; + +-static __init int init_tvaudio(void) +-{ +- return i2c_add_driver(&tvaudio_driver); +-} +- +-static __exit void exit_tvaudio(void) +-{ +- i2c_del_driver(&tvaudio_driver); +-} +- +-module_init(init_tvaudio); +-module_exit(exit_tvaudio); ++module_i2c_driver(tvaudio_driver); +Index: linux-3.3.x86_64/drivers/media/video/tvp514x.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tvp514x.c ++++ linux-3.3.x86_64/drivers/media/video/tvp514x.c +@@ -1163,15 +1163,4 @@ static struct i2c_driver tvp514x_driver + .id_table = tvp514x_id, + }; + +-static int __init tvp514x_init(void) +-{ +- return i2c_add_driver(&tvp514x_driver); +-} +- +-static void __exit tvp514x_exit(void) +-{ +- i2c_del_driver(&tvp514x_driver); +-} +- +-module_init(tvp514x_init); +-module_exit(tvp514x_exit); ++module_i2c_driver(tvp514x_driver); +Index: linux-3.3.x86_64/drivers/media/video/tvp5150.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tvp5150.c ++++ linux-3.3.x86_64/drivers/media/video/tvp5150.c +@@ -17,6 +17,13 @@ + + #include "tvp5150_reg.h" + ++#define TVP5150_H_MAX 720 ++#define TVP5150_V_MAX_525_60 480 ++#define TVP5150_V_MAX_OTHERS 576 ++#define TVP5150_MAX_CROP_LEFT 511 ++#define TVP5150_MAX_CROP_TOP 127 ++#define TVP5150_CROP_SHIFT 2 ++ + MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); + MODULE_AUTHOR("Mauro Carvalho Chehab"); + MODULE_LICENSE("GPL"); +@@ -29,6 +36,7 @@ MODULE_PARM_DESC(debug, "Debug level (0- + struct tvp5150 { + struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; ++ struct v4l2_rect rect; + + v4l2_std_id norm; /* Current set standard */ + u32 input; +@@ -732,6 +740,13 @@ static int tvp5150_s_std(struct v4l2_sub + if (decoder->norm == std) + return 0; + ++ /* Change cropping height limits */ ++ if (std & V4L2_STD_525_60) ++ decoder->rect.height = TVP5150_V_MAX_525_60; ++ else ++ decoder->rect.height = TVP5150_V_MAX_OTHERS; ++ ++ + return tvp5150_set_std(sd, std); + } + +@@ -828,11 +843,8 @@ static int tvp5150_mbus_fmt(struct v4l2_ + else + std = decoder->norm; + +- f->width = 720; +- if (std & V4L2_STD_525_60) +- f->height = 480; +- else +- f->height = 576; ++ f->width = decoder->rect.width; ++ f->height = decoder->rect.height; + + f->code = V4L2_MBUS_FMT_YUYV8_2X8; + f->field = V4L2_FIELD_SEQ_TB; +@@ -843,6 +855,99 @@ static int tvp5150_mbus_fmt(struct v4l2_ + return 0; + } + ++static int tvp5150_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) ++{ ++ struct v4l2_rect rect = a->c; ++ struct tvp5150 *decoder = to_tvp5150(sd); ++ v4l2_std_id std; ++ int hmax; ++ ++ v4l2_dbg(1, debug, sd, "%s left=%d, top=%d, width=%d, height=%d\n", ++ __func__, rect.left, rect.top, rect.width, rect.height); ++ ++ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ /* tvp5150 has some special limits */ ++ rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT); ++ rect.width = clamp(rect.width, ++ TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect.left, ++ TVP5150_H_MAX - rect.left); ++ rect.top = clamp(rect.top, 0, TVP5150_MAX_CROP_TOP); ++ ++ /* Calculate height based on current standard */ ++ if (decoder->norm == V4L2_STD_ALL) ++ std = tvp5150_read_std(sd); ++ else ++ std = decoder->norm; ++ ++ if (std & V4L2_STD_525_60) ++ hmax = TVP5150_V_MAX_525_60; ++ else ++ hmax = TVP5150_V_MAX_OTHERS; ++ ++ rect.height = clamp(rect.height, ++ hmax - TVP5150_MAX_CROP_TOP - rect.top, ++ hmax - rect.top); ++ ++ tvp5150_write(sd, TVP5150_VERT_BLANKING_START, rect.top); ++ tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, ++ rect.top + rect.height - hmax); ++ tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_MSB, ++ rect.left >> TVP5150_CROP_SHIFT); ++ tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_LSB, ++ rect.left | (1 << TVP5150_CROP_SHIFT)); ++ tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_MSB, ++ (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >> ++ TVP5150_CROP_SHIFT); ++ tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_LSB, ++ rect.left + rect.width - TVP5150_MAX_CROP_LEFT); ++ ++ decoder->rect = rect; ++ ++ return 0; ++} ++ ++static int tvp5150_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) ++{ ++ struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd); ++ ++ a->c = decoder->rect; ++ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ ++ return 0; ++} ++ ++static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) ++{ ++ struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd); ++ v4l2_std_id std; ++ ++ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ a->bounds.left = 0; ++ a->bounds.top = 0; ++ a->bounds.width = TVP5150_H_MAX; ++ ++ /* Calculate height based on current standard */ ++ if (decoder->norm == V4L2_STD_ALL) ++ std = tvp5150_read_std(sd); ++ else ++ std = decoder->norm; ++ ++ if (std & V4L2_STD_525_60) ++ a->bounds.height = TVP5150_V_MAX_525_60; ++ else ++ a->bounds.height = TVP5150_V_MAX_OTHERS; ++ ++ a->defrect = a->bounds; ++ a->pixelaspect.numerator = 1; ++ a->pixelaspect.denominator = 1; ++ ++ return 0; ++} ++ + /**************************************************************************** + I2C Command + ****************************************************************************/ +@@ -998,6 +1103,10 @@ static const struct v4l2_subdev_video_op + .enum_mbus_fmt = tvp5150_enum_mbus_fmt, + .s_mbus_fmt = tvp5150_mbus_fmt, + .try_mbus_fmt = tvp5150_mbus_fmt, ++ .g_mbus_fmt = tvp5150_mbus_fmt, ++ .s_crop = tvp5150_s_crop, ++ .g_crop = tvp5150_g_crop, ++ .cropcap = tvp5150_cropcap, + }; + + static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { +@@ -1083,6 +1192,15 @@ static int tvp5150_probe(struct i2c_clie + } + v4l2_ctrl_handler_setup(&core->hdl); + ++ /* Default is no cropping */ ++ core->rect.top = 0; ++ if (tvp5150_read_std(sd) & V4L2_STD_525_60) ++ core->rect.height = TVP5150_V_MAX_525_60; ++ else ++ core->rect.height = TVP5150_V_MAX_OTHERS; ++ core->rect.left = 0; ++ core->rect.width = TVP5150_H_MAX; ++ + if (debug > 1) + tvp5150_log_status(sd); + return 0; +@@ -1121,15 +1239,4 @@ static struct i2c_driver tvp5150_driver + .id_table = tvp5150_id, + }; + +-static __init int init_tvp5150(void) +-{ +- return i2c_add_driver(&tvp5150_driver); +-} +- +-static __exit void exit_tvp5150(void) +-{ +- i2c_del_driver(&tvp5150_driver); +-} +- +-module_init(init_tvp5150); +-module_exit(exit_tvp5150); ++module_i2c_driver(tvp5150_driver); +Index: linux-3.3.x86_64/drivers/media/video/tvp7002.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tvp7002.c ++++ linux-3.3.x86_64/drivers/media/video/tvp7002.c +@@ -1069,27 +1069,4 @@ static struct i2c_driver tvp7002_driver + .id_table = tvp7002_id, + }; + +-/* +- * tvp7002_init - Initialize driver via I2C interface +- * +- * Register the TVP7002 driver. +- * Return 0 on success or error code on failure. +- */ +-static int __init tvp7002_init(void) +-{ +- return i2c_add_driver(&tvp7002_driver); +-} +- +-/* +- * tvp7002_exit - Remove driver via I2C interface +- * +- * Unregister the TVP7002 driver. +- * Returns nothing. +- */ +-static void __exit tvp7002_exit(void) +-{ +- i2c_del_driver(&tvp7002_driver); +-} +- +-module_init(tvp7002_init); +-module_exit(tvp7002_exit); ++module_i2c_driver(tvp7002_driver); +Index: linux-3.3.x86_64/drivers/media/video/tw9910.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tw9910.c ++++ linux-3.3.x86_64/drivers/media/video/tw9910.c +@@ -951,21 +951,7 @@ static struct i2c_driver tw9910_i2c_driv + .id_table = tw9910_id, + }; + +-/* +- * module function +- */ +-static int __init tw9910_module_init(void) +-{ +- return i2c_add_driver(&tw9910_i2c_driver); +-} +- +-static void __exit tw9910_module_exit(void) +-{ +- i2c_del_driver(&tw9910_i2c_driver); +-} +- +-module_init(tw9910_module_init); +-module_exit(tw9910_module_exit); ++module_i2c_driver(tw9910_i2c_driver); + + MODULE_DESCRIPTION("SoC Camera driver for tw9910"); + MODULE_AUTHOR("Kuninori Morimoto"); +Index: linux-3.3.x86_64/drivers/media/video/upd64031a.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/upd64031a.c ++++ linux-3.3.x86_64/drivers/media/video/upd64031a.c +@@ -271,15 +271,4 @@ static struct i2c_driver upd64031a_drive + .id_table = upd64031a_id, + }; + +-static __init int init_upd64031a(void) +-{ +- return i2c_add_driver(&upd64031a_driver); +-} +- +-static __exit void exit_upd64031a(void) +-{ +- i2c_del_driver(&upd64031a_driver); +-} +- +-module_init(init_upd64031a); +-module_exit(exit_upd64031a); ++module_i2c_driver(upd64031a_driver); +Index: linux-3.3.x86_64/drivers/media/video/upd64083.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/upd64083.c ++++ linux-3.3.x86_64/drivers/media/video/upd64083.c +@@ -243,15 +243,4 @@ static struct i2c_driver upd64083_driver + .id_table = upd64083_id, + }; + +-static __init int init_upd64083(void) +-{ +- return i2c_add_driver(&upd64083_driver); +-} +- +-static __exit void exit_upd64083(void) +-{ +- i2c_del_driver(&upd64083_driver); +-} +- +-module_init(init_upd64083); +-module_exit(exit_upd64083); ++module_i2c_driver(upd64083_driver); +Index: linux-3.3.x86_64/drivers/media/video/vp27smpx.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/vp27smpx.c ++++ linux-3.3.x86_64/drivers/media/video/vp27smpx.c +@@ -208,15 +208,4 @@ static struct i2c_driver vp27smpx_driver + .id_table = vp27smpx_id, + }; + +-static __init int init_vp27smpx(void) +-{ +- return i2c_add_driver(&vp27smpx_driver); +-} +- +-static __exit void exit_vp27smpx(void) +-{ +- i2c_del_driver(&vp27smpx_driver); +-} +- +-module_init(init_vp27smpx); +-module_exit(exit_vp27smpx); ++module_i2c_driver(vp27smpx_driver); +Index: linux-3.3.x86_64/drivers/media/video/vpx3220.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/vpx3220.c ++++ linux-3.3.x86_64/drivers/media/video/vpx3220.c +@@ -588,15 +588,4 @@ static struct i2c_driver vpx3220_driver + .id_table = vpx3220_id, + }; + +-static __init int init_vpx3220(void) +-{ +- return i2c_add_driver(&vpx3220_driver); +-} +- +-static __exit void exit_vpx3220(void) +-{ +- i2c_del_driver(&vpx3220_driver); +-} +- +-module_init(init_vpx3220); +-module_exit(exit_vpx3220); ++module_i2c_driver(vpx3220_driver); +Index: linux-3.3.x86_64/drivers/media/video/wm8739.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/wm8739.c ++++ linux-3.3.x86_64/drivers/media/video/wm8739.c +@@ -291,15 +291,4 @@ static struct i2c_driver wm8739_driver = + .id_table = wm8739_id, + }; + +-static __init int init_wm8739(void) +-{ +- return i2c_add_driver(&wm8739_driver); +-} +- +-static __exit void exit_wm8739(void) +-{ +- i2c_del_driver(&wm8739_driver); +-} +- +-module_init(init_wm8739); +-module_exit(exit_wm8739); ++module_i2c_driver(wm8739_driver); +Index: linux-3.3.x86_64/drivers/media/video/wm8775.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/wm8775.c ++++ linux-3.3.x86_64/drivers/media/video/wm8775.c +@@ -339,15 +339,4 @@ static struct i2c_driver wm8775_driver = + .id_table = wm8775_id, + }; + +-static __init int init_wm8775(void) +-{ +- return i2c_add_driver(&wm8775_driver); +-} +- +-static __exit void exit_wm8775(void) +-{ +- i2c_del_driver(&wm8775_driver); +-} +- +-module_init(init_wm8775); +-module_exit(exit_wm8775); ++module_i2c_driver(wm8775_driver); +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe-priv.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/it913x-fe-priv.h ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe-priv.h +@@ -201,6 +201,11 @@ fe_modulation_t fe_con[] = { + QAM_64, + }; + ++enum { ++ PRIORITY_HIGH = 0, /* High-priority stream */ ++ PRIORITY_LOW, /* Low-priority stream */ ++}; ++ + /* Standard demodulator functions */ + static struct it913xset set_solo_fe[] = { + {PRO_LINK, GPIOH5_EN, {0x01}, 0x01}, +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/it913x-fe.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe.c +@@ -57,6 +57,7 @@ struct it913x_fe_state { + u32 frequency; + fe_modulation_t constellation; + fe_transmit_mode_t transmission_mode; ++ u8 priority; + u32 crystalFrequency; + u32 adcFrequency; + u8 tuner_type; +@@ -500,19 +501,87 @@ static int it913x_fe_read_status(struct + return 0; + } + ++/* FEC values based on fe_code_rate_t non supported values 0*/ ++int it913x_qpsk_pval[] = {0, -93, -91, -90, 0, -89, -88}; ++int it913x_16qam_pval[] = {0, -87, -85, -84, 0, -83, -82}; ++int it913x_64qam_pval[] = {0, -82, -80, -78, 0, -77, -76}; ++ ++static int it913x_get_signal_strength(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ struct it913x_fe_state *state = fe->demodulator_priv; ++ u8 code_rate; ++ int ret, temp; ++ u8 lna_gain_os; ++ ++ ret = it913x_read_reg_u8(state, VAR_P_INBAND); ++ if (ret < 0) ++ return ret; ++ ++ /* VHF/UHF gain offset */ ++ if (state->frequency < 300000000) ++ lna_gain_os = 7; ++ else ++ lna_gain_os = 14; ++ ++ temp = (ret - 100) - lna_gain_os; ++ ++ if (state->priority == PRIORITY_HIGH) ++ code_rate = p->code_rate_HP; ++ else ++ code_rate = p->code_rate_LP; ++ ++ if (code_rate >= ARRAY_SIZE(it913x_qpsk_pval)) ++ return -EINVAL; ++ ++ deb_info("Reg VAR_P_INBAND:%d Calc Offset Value:%d", ret, temp); ++ ++ /* Apply FEC offset values*/ ++ switch (p->modulation) { ++ case QPSK: ++ temp -= it913x_qpsk_pval[code_rate]; ++ break; ++ case QAM_16: ++ temp -= it913x_16qam_pval[code_rate]; ++ break; ++ case QAM_64: ++ temp -= it913x_64qam_pval[code_rate]; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (temp < -15) ++ ret = 0; ++ else if ((-15 <= temp) && (temp < 0)) ++ ret = (2 * (temp + 15)) / 3; ++ else if ((0 <= temp) && (temp < 20)) ++ ret = 4 * temp + 10; ++ else if ((20 <= temp) && (temp < 35)) ++ ret = (2 * (temp - 20)) / 3 + 90; ++ else if (temp >= 35) ++ ret = 100; ++ ++ deb_info("Signal Strength :%d", ret); ++ ++ return ret; ++} ++ + static int it913x_fe_read_signal_strength(struct dvb_frontend *fe, + u16 *strength) + { + struct it913x_fe_state *state = fe->demodulator_priv; +- int ret = it913x_read_reg_u8(state, SIGNAL_LEVEL); +- /*SIGNAL_LEVEL always returns 100%! so using FE_HAS_SIGNAL as switch*/ +- if (state->it913x_status & FE_HAS_SIGNAL) +- ret = (ret * 0xff) / 0x64; +- else +- ret = 0x0; +- ret |= ret << 0x8; +- *strength = ret; +- return 0; ++ int ret = 0; ++ if (state->config->read_slevel) { ++ if (state->it913x_status & FE_HAS_SIGNAL) ++ ret = it913x_read_reg_u8(state, SIGNAL_LEVEL); ++ } else ++ ret = it913x_get_signal_strength(fe); ++ ++ if (ret >= 0) ++ *strength = (u16)((u32)ret * 0xffff / 0x64); ++ ++ return (ret < 0) ? -ENODEV : 0; + } + + static int it913x_fe_read_snr(struct dvb_frontend *fe, u16 *snr) +@@ -606,6 +675,8 @@ static int it913x_fe_get_frontend(struct + if (reg[2] < 4) + p->hierarchy = fe_hi[reg[2]]; + ++ state->priority = reg[5]; ++ + p->code_rate_HP = (reg[6] < 6) ? fe_code[reg[6]] : FEC_NONE; + p->code_rate_LP = (reg[7] < 6) ? fe_code[reg[7]] : FEC_NONE; + +@@ -972,5 +1043,5 @@ static struct dvb_frontend_ops it913x_fe + + MODULE_DESCRIPTION("it913x Frontend and it9137 tuner"); + MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); +-MODULE_VERSION("1.13"); ++MODULE_VERSION("1.15"); + MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/it913x-fe.h ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe.h +@@ -34,6 +34,8 @@ struct ite_config { + u8 tuner_id_1; + u8 dual_mode; + u8 adf; ++ /* option to read SIGNAL_LEVEL */ ++ u8 read_slevel; + }; + + #if defined(CONFIG_DVB_IT913X_FE) || (defined(CONFIG_DVB_IT913X_FE_MODULE) && \ +@@ -168,6 +170,8 @@ static inline struct dvb_frontend *it913 + #define EST_SIGNAL_LEVEL 0x004a + #define FREE_BAND 0x004b + #define SUSPEND_FLAG 0x004c ++#define VAR_P_INBAND 0x00f7 ++ + /* Build in tuner types */ + #define IT9137 0x38 + #define IT9135_38 0x38 +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/cx22702.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/cx22702.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/cx22702.c +@@ -502,10 +502,26 @@ static int cx22702_read_signal_strength( + u16 *signal_strength) + { + struct cx22702_state *state = fe->demodulator_priv; ++ u8 reg23; + +- u16 rs_ber; +- rs_ber = cx22702_readreg(state, 0x23); +- *signal_strength = (rs_ber << 8) | rs_ber; ++ /* ++ * Experience suggests that the strength signal register works as ++ * follows: ++ * - In the absence of signal, value is 0xff. ++ * - In the presence of a weak signal, bit 7 is set, not sure what ++ * the lower 7 bits mean. ++ * - In the presence of a strong signal, the register holds a 7-bit ++ * value (bit 7 is cleared), with greater values standing for ++ * weaker signals. ++ */ ++ reg23 = cx22702_readreg(state, 0x23); ++ if (reg23 & 0x80) { ++ *signal_strength = 0; ++ } else { ++ reg23 = ~reg23 & 0x7f; ++ /* Scale to 16 bit */ ++ *signal_strength = (reg23 << 9) | (reg23 << 2) | (reg23 >> 5); ++ } + + return 0; + } +Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-cards.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx-cards.c ++++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-cards.c +@@ -353,6 +353,44 @@ static struct em28xx_reg_seq hauppauge_9 + }; + #endif + ++/* 1b80:e425 MaxMedia UB425-TC ++ * GPIO_6 - demod reset, 0=active ++ * GPIO_7 - LED, 0=active ++ */ ++static struct em28xx_reg_seq maxmedia_ub425_tc[] = { ++ {EM2874_R80_GPIO, 0x83, 0xff, 100}, ++ {EM2874_R80_GPIO, 0xc3, 0xff, 100}, /* GPIO_6 = 1 */ ++ {EM2874_R80_GPIO, 0x43, 0xff, 000}, /* GPIO_7 = 0 */ ++ {-1, -1, -1, -1}, ++}; ++ ++/* 2304:0242 PCTV QuatroStick (510e) ++ * GPIO_2: decoder reset, 0=active ++ * GPIO_4: decoder suspend, 0=active ++ * GPIO_6: demod reset, 0=active ++ * GPIO_7: LED, 1=active ++ */ ++static struct em28xx_reg_seq pctv_510e[] = { ++ {EM2874_R80_GPIO, 0x10, 0xff, 100}, ++ {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ ++ {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ ++ { -1, -1, -1, -1}, ++}; ++ ++/* 2013:0251 PCTV QuatroStick nano (520e) ++ * GPIO_2: decoder reset, 0=active ++ * GPIO_4: decoder suspend, 0=active ++ * GPIO_6: demod reset, 0=active ++ * GPIO_7: LED, 1=active ++ */ ++static struct em28xx_reg_seq pctv_520e[] = { ++ {EM2874_R80_GPIO, 0x10, 0xff, 100}, ++ {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ ++ {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ ++ {EM2874_R80_GPIO, 0xd4, 0xff, 000}, /* GPIO_7 = 1 */ ++ { -1, -1, -1, -1}, ++}; ++ + /* + * Board definitions + */ +@@ -1908,6 +1946,41 @@ struct em28xx_board em28xx_boards[] = { + .amux = EM28XX_AMUX_LINE_IN, + } }, + }, ++ /* 1b80:e425 MaxMedia UB425-TC ++ * Empia EM2874B + Micronas DRX 3913KA2 + NXP TDA18271HDC2 */ ++ [EM2874_BOARD_MAXMEDIA_UB425_TC] = { ++ .name = "MaxMedia UB425-TC", ++ .tuner_type = TUNER_ABSENT, ++ .tuner_gpio = maxmedia_ub425_tc, ++ .has_dvb = 1, ++ .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | ++ EM28XX_I2C_CLK_WAIT_ENABLE | ++ EM28XX_I2C_FREQ_400_KHZ, ++ }, ++ /* 2304:0242 PCTV QuatroStick (510e) ++ * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */ ++ [EM2884_BOARD_PCTV_510E] = { ++ .name = "PCTV QuatroStick (510e)", ++ .tuner_type = TUNER_ABSENT, ++ .tuner_gpio = pctv_510e, ++ .has_dvb = 1, ++ .ir_codes = RC_MAP_PINNACLE_PCTV_HD, ++ .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | ++ EM28XX_I2C_CLK_WAIT_ENABLE | ++ EM28XX_I2C_FREQ_400_KHZ, ++ }, ++ /* 2013:0251 PCTV QuatroStick nano (520e) ++ * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */ ++ [EM2884_BOARD_PCTV_520E] = { ++ .name = "PCTV QuatroStick nano (520e)", ++ .tuner_type = TUNER_ABSENT, ++ .tuner_gpio = pctv_520e, ++ .has_dvb = 1, ++ .ir_codes = RC_MAP_PINNACLE_PCTV_HD, ++ .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | ++ EM28XX_I2C_CLK_WAIT_ENABLE | ++ EM28XX_I2C_FREQ_400_KHZ, ++ }, + }; + const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); + +@@ -2059,6 +2132,12 @@ struct usb_device_id em28xx_id_table[] = + .driver_info = EM2860_BOARD_HT_VIDBOX_NW03 }, + { USB_DEVICE(0x1b80, 0xe309), /* Sveon STV40 */ + .driver_info = EM2860_BOARD_EASYCAP }, ++ { USB_DEVICE(0x1b80, 0xe425), ++ .driver_info = EM2874_BOARD_MAXMEDIA_UB425_TC }, ++ { USB_DEVICE(0x2304, 0x0242), ++ .driver_info = EM2884_BOARD_PCTV_510E }, ++ { USB_DEVICE(0x2013, 0x0251), ++ .driver_info = EM2884_BOARD_PCTV_520E }, + { }, + }; + MODULE_DEVICE_TABLE(usb, em28xx_id_table); +@@ -3122,7 +3201,6 @@ static int em28xx_usb_probe(struct usb_i + int i, nr; + const int ifnum = interface->altsetting[0].desc.bInterfaceNumber; + char *speed; +- char descr[255] = ""; + + udev = usb_get_dev(interface_to_usbdev(interface)); + +@@ -3227,21 +3305,11 @@ static int em28xx_usb_probe(struct usb_i + speed = "unknown"; + } + +- if (udev->manufacturer) +- strlcpy(descr, udev->manufacturer, sizeof(descr)); +- +- if (udev->product) { +- if (*descr) +- strlcat(descr, " ", sizeof(descr)); +- strlcat(descr, udev->product, sizeof(descr)); +- } +- +- if (*descr) +- strlcat(descr, " ", sizeof(descr)); +- + printk(KERN_INFO DRIVER_NAME +- ": New device %s@ %s Mbps (%04x:%04x, interface %d, class %d)\n", +- descr, ++ ": New device %s %s @ %s Mbps " ++ "(%04x:%04x, interface %d, class %d)\n", ++ udev->manufacturer ? udev->manufacturer : "", ++ udev->product ? udev->product : "", + speed, + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), +@@ -3307,6 +3375,17 @@ static int em28xx_usb_probe(struct usb_i + goto unlock_and_free; + } + ++ if (has_dvb) { ++ /* pre-allocate DVB isoc transfer buffers */ ++ retval = em28xx_alloc_isoc(dev, EM28XX_DIGITAL_MODE, ++ EM28XX_DVB_MAX_PACKETS, ++ EM28XX_DVB_NUM_BUFS, ++ dev->dvb_max_pkt_size); ++ if (retval) { ++ goto unlock_and_free; ++ } ++ } ++ + request_modules(dev); + + /* Should be the last thing to do, to avoid newer udev's to +@@ -3379,7 +3458,7 @@ static void em28xx_usb_disconnect(struct + video_device_node_name(dev->vdev)); + + dev->state |= DEV_MISCONFIGURED; +- em28xx_uninit_isoc(dev); ++ em28xx_uninit_isoc(dev, dev->mode); + dev->state |= DEV_DISCONNECTED; + wake_up_interruptible(&dev->wait_frame); + wake_up_interruptible(&dev->wait_stream); +@@ -3388,6 +3467,9 @@ static void em28xx_usb_disconnect(struct + em28xx_release_resources(dev); + } + ++ /* free DVB isoc buffers */ ++ em28xx_uninit_isoc(dev, EM28XX_DIGITAL_MODE); ++ + mutex_unlock(&dev->lock); + + em28xx_close_extension(dev); +Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx-core.c ++++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-core.c +@@ -666,6 +666,7 @@ int em28xx_capture_start(struct em28xx * + + return rc; + } ++EXPORT_SYMBOL_GPL(em28xx_capture_start); + + int em28xx_vbi_supported(struct em28xx *dev) + { +@@ -961,146 +962,192 @@ static void em28xx_irq_callback(struct u + /* + * Stop and Deallocate URBs + */ +-void em28xx_uninit_isoc(struct em28xx *dev) ++void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode) + { + struct urb *urb; ++ struct em28xx_usb_isoc_bufs *isoc_bufs; + int i; + +- em28xx_isocdbg("em28xx: called em28xx_uninit_isoc\n"); ++ em28xx_isocdbg("em28xx: called em28xx_uninit_isoc in mode %d\n", mode); ++ ++ if (mode == EM28XX_DIGITAL_MODE) ++ isoc_bufs = &dev->isoc_ctl.digital_bufs; ++ else ++ isoc_bufs = &dev->isoc_ctl.analog_bufs; + + dev->isoc_ctl.nfields = -1; +- for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { +- urb = dev->isoc_ctl.urb[i]; ++ for (i = 0; i < isoc_bufs->num_bufs; i++) { ++ urb = isoc_bufs->urb[i]; + if (urb) { + if (!irqs_disabled()) + usb_kill_urb(urb); + else + usb_unlink_urb(urb); + +- if (dev->isoc_ctl.transfer_buffer[i]) { ++ if (isoc_bufs->transfer_buffer[i]) { + usb_free_coherent(dev->udev, + urb->transfer_buffer_length, +- dev->isoc_ctl.transfer_buffer[i], ++ isoc_bufs->transfer_buffer[i], + urb->transfer_dma); + } + usb_free_urb(urb); +- dev->isoc_ctl.urb[i] = NULL; ++ isoc_bufs->urb[i] = NULL; + } +- dev->isoc_ctl.transfer_buffer[i] = NULL; ++ isoc_bufs->transfer_buffer[i] = NULL; + } + +- kfree(dev->isoc_ctl.urb); +- kfree(dev->isoc_ctl.transfer_buffer); ++ kfree(isoc_bufs->urb); ++ kfree(isoc_bufs->transfer_buffer); + +- dev->isoc_ctl.urb = NULL; +- dev->isoc_ctl.transfer_buffer = NULL; +- dev->isoc_ctl.num_bufs = 0; ++ isoc_bufs->urb = NULL; ++ isoc_bufs->transfer_buffer = NULL; ++ isoc_bufs->num_bufs = 0; + + em28xx_capture_start(dev, 0); + } + EXPORT_SYMBOL_GPL(em28xx_uninit_isoc); + + /* +- * Allocate URBs and start IRQ ++ * Allocate URBs + */ +-int em28xx_init_isoc(struct em28xx *dev, int max_packets, +- int num_bufs, int max_pkt_size, +- int (*isoc_copy) (struct em28xx *dev, struct urb *urb)) ++int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode, ++ int max_packets, int num_bufs, int max_pkt_size) + { +- struct em28xx_dmaqueue *dma_q = &dev->vidq; +- struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; ++ struct em28xx_usb_isoc_bufs *isoc_bufs; + int i; + int sb_size, pipe; + struct urb *urb; + int j, k; +- int rc; + +- em28xx_isocdbg("em28xx: called em28xx_prepare_isoc\n"); ++ em28xx_isocdbg("em28xx: called em28xx_alloc_isoc in mode %d\n", mode); ++ ++ if (mode == EM28XX_DIGITAL_MODE) ++ isoc_bufs = &dev->isoc_ctl.digital_bufs; ++ else ++ isoc_bufs = &dev->isoc_ctl.analog_bufs; + + /* De-allocates all pending stuff */ +- em28xx_uninit_isoc(dev); ++ em28xx_uninit_isoc(dev, mode); + +- dev->isoc_ctl.isoc_copy = isoc_copy; +- dev->isoc_ctl.num_bufs = num_bufs; ++ isoc_bufs->num_bufs = num_bufs; + +- dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); +- if (!dev->isoc_ctl.urb) { ++ isoc_bufs->urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); ++ if (!isoc_bufs->urb) { + em28xx_errdev("cannot alloc memory for usb buffers\n"); + return -ENOMEM; + } + +- dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, +- GFP_KERNEL); +- if (!dev->isoc_ctl.transfer_buffer) { ++ isoc_bufs->transfer_buffer = kzalloc(sizeof(void *)*num_bufs, ++ GFP_KERNEL); ++ if (!isoc_bufs->transfer_buffer) { + em28xx_errdev("cannot allocate memory for usb transfer\n"); +- kfree(dev->isoc_ctl.urb); ++ kfree(isoc_bufs->urb); + return -ENOMEM; + } + +- dev->isoc_ctl.max_pkt_size = max_pkt_size; ++ isoc_bufs->max_pkt_size = max_pkt_size; ++ isoc_bufs->num_packets = max_packets; + dev->isoc_ctl.vid_buf = NULL; + dev->isoc_ctl.vbi_buf = NULL; + +- sb_size = max_packets * dev->isoc_ctl.max_pkt_size; ++ sb_size = isoc_bufs->num_packets * isoc_bufs->max_pkt_size; + + /* allocate urbs and transfer buffers */ +- for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { +- urb = usb_alloc_urb(max_packets, GFP_KERNEL); ++ for (i = 0; i < isoc_bufs->num_bufs; i++) { ++ urb = usb_alloc_urb(isoc_bufs->num_packets, GFP_KERNEL); + if (!urb) { + em28xx_err("cannot alloc isoc_ctl.urb %i\n", i); +- em28xx_uninit_isoc(dev); ++ em28xx_uninit_isoc(dev, mode); + return -ENOMEM; + } +- dev->isoc_ctl.urb[i] = urb; ++ isoc_bufs->urb[i] = urb; + +- dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev, ++ isoc_bufs->transfer_buffer[i] = usb_alloc_coherent(dev->udev, + sb_size, GFP_KERNEL, &urb->transfer_dma); +- if (!dev->isoc_ctl.transfer_buffer[i]) { ++ if (!isoc_bufs->transfer_buffer[i]) { + em28xx_err("unable to allocate %i bytes for transfer" + " buffer %i%s\n", + sb_size, i, + in_interrupt() ? " while in int" : ""); +- em28xx_uninit_isoc(dev); ++ em28xx_uninit_isoc(dev, mode); + return -ENOMEM; + } +- memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); ++ memset(isoc_bufs->transfer_buffer[i], 0, sb_size); + + /* FIXME: this is a hack - should be + 'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK' + should also be using 'desc.bInterval' + */ + pipe = usb_rcvisocpipe(dev->udev, +- dev->mode == EM28XX_ANALOG_MODE ? ++ mode == EM28XX_ANALOG_MODE ? + EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL); + + usb_fill_int_urb(urb, dev->udev, pipe, +- dev->isoc_ctl.transfer_buffer[i], sb_size, ++ isoc_bufs->transfer_buffer[i], sb_size, + em28xx_irq_callback, dev, 1); + +- urb->number_of_packets = max_packets; ++ urb->number_of_packets = isoc_bufs->num_packets; + urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; + + k = 0; +- for (j = 0; j < max_packets; j++) { ++ for (j = 0; j < isoc_bufs->num_packets; j++) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = +- dev->isoc_ctl.max_pkt_size; +- k += dev->isoc_ctl.max_pkt_size; ++ isoc_bufs->max_pkt_size; ++ k += isoc_bufs->max_pkt_size; + } + } + ++ return 0; ++} ++EXPORT_SYMBOL_GPL(em28xx_alloc_isoc); ++ ++/* ++ * Allocate URBs and start IRQ ++ */ ++int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode, ++ int max_packets, int num_bufs, int max_pkt_size, ++ int (*isoc_copy) (struct em28xx *dev, struct urb *urb)) ++{ ++ struct em28xx_dmaqueue *dma_q = &dev->vidq; ++ struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; ++ struct em28xx_usb_isoc_bufs *isoc_bufs; ++ int i; ++ int rc; ++ int alloc; ++ ++ em28xx_isocdbg("em28xx: called em28xx_init_isoc in mode %d\n", mode); ++ ++ dev->isoc_ctl.isoc_copy = isoc_copy; ++ ++ if (mode == EM28XX_DIGITAL_MODE) { ++ isoc_bufs = &dev->isoc_ctl.digital_bufs; ++ /* no need to free/alloc isoc buffers in digital mode */ ++ alloc = 0; ++ } else { ++ isoc_bufs = &dev->isoc_ctl.analog_bufs; ++ alloc = 1; ++ } ++ ++ if (alloc) { ++ rc = em28xx_alloc_isoc(dev, mode, max_packets, ++ num_bufs, max_pkt_size); ++ if (rc) ++ return rc; ++ } ++ + init_waitqueue_head(&dma_q->wq); + init_waitqueue_head(&vbi_dma_q->wq); + + em28xx_capture_start(dev, 1); + + /* submit urbs and enables IRQ */ +- for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { +- rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); ++ for (i = 0; i < isoc_bufs->num_bufs; i++) { ++ rc = usb_submit_urb(isoc_bufs->urb[i], GFP_ATOMIC); + if (rc) { + em28xx_err("submit of urb %i failed (error=%i)\n", i, + rc); +- em28xx_uninit_isoc(dev); ++ em28xx_uninit_isoc(dev, mode); + return rc; + } + } +Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-dvb.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx-dvb.c ++++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-dvb.c +@@ -61,9 +61,6 @@ if (debug >= level) \ + printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \ + } while (0) + +-#define EM28XX_DVB_NUM_BUFS 5 +-#define EM28XX_DVB_MAX_PACKETS 64 +- + struct em28xx_dvb { + struct dvb_frontend *fe[2]; + +@@ -172,20 +169,21 @@ static int em28xx_start_streaming(struct + max_dvb_packet_size = dev->dvb_max_pkt_size; + if (max_dvb_packet_size < 0) + return max_dvb_packet_size; +- dprintk(1, "Using %d buffers each with %d bytes\n", ++ dprintk(1, "Using %d buffers each with %d x %d bytes\n", + EM28XX_DVB_NUM_BUFS, ++ EM28XX_DVB_MAX_PACKETS, + max_dvb_packet_size); + +- return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS, +- EM28XX_DVB_NUM_BUFS, max_dvb_packet_size, +- em28xx_dvb_isoc_copy); ++ return em28xx_init_isoc(dev, EM28XX_DIGITAL_MODE, ++ EM28XX_DVB_MAX_PACKETS, EM28XX_DVB_NUM_BUFS, ++ max_dvb_packet_size, em28xx_dvb_isoc_copy); + } + + static int em28xx_stop_streaming(struct em28xx_dvb *dvb) + { + struct em28xx *dev = dvb->adapter.priv; + +- em28xx_uninit_isoc(dev); ++ em28xx_capture_start(dev, 0); + + em28xx_set_mode(dev, EM28XX_SUSPEND); + +@@ -327,6 +325,19 @@ struct drxk_config hauppauge_930c_drxk = + .chunk_size = 56, + }; + ++struct drxk_config maxmedia_ub425_tc_drxk = { ++ .adr = 0x29, ++ .single_master = 1, ++ .no_i2c_bridge = 1, ++}; ++ ++struct drxk_config pctv_520e_drxk = { ++ .adr = 0x29, ++ .single_master = 1, ++ .microcode_name = "dvb-demod-drxk-pctv.fw", ++ .chunk_size = 58, ++}; ++ + static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) + { + struct em28xx_dvb *dvb = fe->sec_priv; +@@ -460,6 +471,33 @@ static void terratec_h5_init(struct em28 + em28xx_gpio_set(dev, terratec_h5_end); + }; + ++static void pctv_520e_init(struct em28xx *dev) ++{ ++ /* ++ * Init TDA8295(?) analog demodulator. Looks like I2C traffic to ++ * digital demodulator and tuner are routed via TDA8295. ++ */ ++ int i; ++ struct { ++ unsigned char r[4]; ++ int len; ++ } regs[] = { ++ {{ 0x06, 0x02, 0x00, 0x31 }, 4}, ++ {{ 0x01, 0x02 }, 2}, ++ {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, ++ {{ 0x01, 0x00 }, 2}, ++ {{ 0x01, 0x00, 0xff, 0xaf }, 4}, ++ {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, ++ {{ 0x01, 0x00 }, 2}, ++ {{ 0x01, 0x00, 0x73, 0xaf }, 4}, ++ }; ++ ++ dev->i2c_client.addr = 0x82 >> 1; /* 0x41 */ ++ ++ for (i = 0; i < ARRAY_SIZE(regs); i++) ++ i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); ++}; ++ + static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe) + { + /* Values extracted from a USB trace of the Terratec Windows driver */ +@@ -938,6 +976,48 @@ static int em28xx_dvb_init(struct em28xx + dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap, + &em28xx_a8293_config); + break; ++ case EM2874_BOARD_MAXMEDIA_UB425_TC: ++ /* attach demodulator */ ++ dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk, ++ &dev->i2c_adap); ++ ++ if (dvb->fe[0]) { ++ /* disable I2C-gate */ ++ dvb->fe[0]->ops.i2c_gate_ctrl = NULL; ++ ++ /* attach tuner */ ++ if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], ++ &dev->i2c_adap, 0x60)) { ++ dvb_frontend_detach(dvb->fe[0]); ++ result = -EINVAL; ++ goto out_free; ++ } ++ } ++ ++ /* TODO: we need drx-3913k firmware in order to support DVB-T */ ++ em28xx_info("MaxMedia UB425-TC: only DVB-C supported by that " \ ++ "driver version\n"); ++ ++ break; ++ case EM2884_BOARD_PCTV_510E: ++ case EM2884_BOARD_PCTV_520E: ++ pctv_520e_init(dev); ++ ++ /* attach demodulator */ ++ dvb->fe[0] = dvb_attach(drxk_attach, &pctv_520e_drxk, ++ &dev->i2c_adap); ++ ++ if (dvb->fe[0]) { ++ /* attach tuner */ ++ if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, ++ &dev->i2c_adap, ++ &em28xx_cxd2820r_tda18271_config)) { ++ dvb_frontend_detach(dvb->fe[0]); ++ result = -EINVAL; ++ goto out_free; ++ } ++ } ++ break; + default: + em28xx_errdev("/2: The frontend of your DVB/ATSC card" + " isn't supported yet\n"); +Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-video.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx-video.c ++++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-video.c +@@ -760,17 +760,19 @@ buffer_prepare(struct videobuf_queue *vq + goto fail; + } + +- if (!dev->isoc_ctl.num_bufs) ++ if (!dev->isoc_ctl.analog_bufs.num_bufs) + urb_init = 1; + + if (urb_init) { + if (em28xx_vbi_supported(dev) == 1) +- rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS, ++ rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE, ++ EM28XX_NUM_PACKETS, + EM28XX_NUM_BUFS, + dev->max_pkt_size, + em28xx_isoc_copy_vbi); + else +- rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS, ++ rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE, ++ EM28XX_NUM_PACKETS, + EM28XX_NUM_BUFS, + dev->max_pkt_size, + em28xx_isoc_copy); +@@ -2267,7 +2269,7 @@ static int em28xx_v4l2_close(struct file + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); + + /* do this before setting alternate! */ +- em28xx_uninit_isoc(dev); ++ em28xx_uninit_isoc(dev, EM28XX_ANALOG_MODE); + em28xx_set_mode(dev, EM28XX_SUSPEND); + + /* set alternate 0 */ +Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx.h ++++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx.h +@@ -125,6 +125,9 @@ + #define EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C 81 + #define EM2884_BOARD_CINERGY_HTC_STICK 82 + #define EM2860_BOARD_HT_VIDBOX_NW03 83 ++#define EM2874_BOARD_MAXMEDIA_UB425_TC 84 ++#define EM2884_BOARD_PCTV_510E 85 ++#define EM2884_BOARD_PCTV_520E 86 + + /* Limits minimum and default number of buffers */ + #define EM28XX_MIN_BUF 4 +@@ -151,12 +154,14 @@ + + /* number of buffers for isoc transfers */ + #define EM28XX_NUM_BUFS 5 ++#define EM28XX_DVB_NUM_BUFS 5 + + /* number of packets for each buffer + windows requests only 64 packets .. so we better do the same + this is what I found out for all alternate numbers there! + */ + #define EM28XX_NUM_PACKETS 64 ++#define EM28XX_DVB_MAX_PACKETS 64 + + #define EM28XX_INTERLACED_DEFAULT 1 + +@@ -197,10 +202,13 @@ enum em28xx_mode { + + struct em28xx; + +-struct em28xx_usb_isoc_ctl { ++struct em28xx_usb_isoc_bufs { + /* max packet size of isoc transaction */ + int max_pkt_size; + ++ /* number of packets in each buffer */ ++ int num_packets; ++ + /* number of allocated urbs */ + int num_bufs; + +@@ -209,6 +217,14 @@ struct em28xx_usb_isoc_ctl { + + /* transfer buffers for isoc transfer */ + char **transfer_buffer; ++}; ++ ++struct em28xx_usb_isoc_ctl { ++ /* isoc transfer buffers for analog mode */ ++ struct em28xx_usb_isoc_bufs analog_bufs; ++ ++ /* isoc transfer buffers for digital mode */ ++ struct em28xx_usb_isoc_bufs digital_bufs; + + /* Last buffer command and region */ + u8 cmd; +@@ -600,9 +616,6 @@ struct em28xx { + unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ + int dvb_alt; /* alternate for DVB */ + unsigned int dvb_max_pkt_size; /* wMaxPacketSize for DVB */ +- struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ +- char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc +- transfer */ + char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ + + /* helper funcs that call usb_control_msg */ +@@ -676,10 +689,12 @@ int em28xx_vbi_supported(struct em28xx * + int em28xx_set_outfmt(struct em28xx *dev); + int em28xx_resolution_set(struct em28xx *dev); + int em28xx_set_alternate(struct em28xx *dev); +-int em28xx_init_isoc(struct em28xx *dev, int max_packets, +- int num_bufs, int max_pkt_size, ++int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode, ++ int max_packets, int num_bufs, int max_pkt_size); ++int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode, ++ int max_packets, int num_bufs, int max_pkt_size, + int (*isoc_copy) (struct em28xx *dev, struct urb *urb)); +-void em28xx_uninit_isoc(struct em28xx *dev); ++void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode); + int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev); + int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode); + int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); +Index: linux-3.3.x86_64/drivers/media/video/mx2_camera.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mx2_camera.c ++++ linux-3.3.x86_64/drivers/media/video/mx2_camera.c +@@ -3,6 +3,7 @@ + * + * Copyright (C) 2008, Sascha Hauer, Pengutronix + * Copyright (C) 2010, Baruch Siach, Orex Computed Radiography ++ * Copyright (C) 2012, Javier Martin, Vista Silicon S.L. + * + * 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 +@@ -18,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -30,17 +32,14 @@ + + #include + #include +-#include +-#include ++#include ++#include + #include + #include + + #include + + #include +-#ifdef CONFIG_MACH_MX27 +-#include +-#endif + #include + + #include +@@ -206,10 +205,23 @@ + #define PRP_INTR_LBOVF (1 << 7) + #define PRP_INTR_CH2OVF (1 << 8) + +-#define mx27_camera_emma(pcdev) (cpu_is_mx27() && pcdev->use_emma) ++/* Resizing registers */ ++#define PRP_RZ_VALID_TBL_LEN(x) ((x) << 24) ++#define PRP_RZ_VALID_BILINEAR (1 << 31) + + #define MAX_VIDEO_MEM 16 + ++#define RESIZE_NUM_MIN 1 ++#define RESIZE_NUM_MAX 20 ++#define BC_COEF 3 ++#define SZ_COEF (1 << BC_COEF) ++ ++#define RESIZE_DIR_H 0 ++#define RESIZE_DIR_V 1 ++ ++#define RESIZE_ALGO_BILINEAR 0 ++#define RESIZE_ALGO_AVERAGING 1 ++ + struct mx2_prp_cfg { + int channel; + u32 in_fmt; +@@ -219,6 +231,13 @@ struct mx2_prp_cfg { + u32 irq_flags; + }; + ++/* prp resizing parameters */ ++struct emma_prp_resize { ++ int algo; /* type of algorithm used */ ++ int len; /* number of coefficients */ ++ unsigned char s[RESIZE_NUM_MAX]; /* table of coefficients */ ++}; ++ + /* prp configuration for a client-host fmt pair */ + struct mx2_fmt_cfg { + enum v4l2_mbus_pixelcode in_fmt; +@@ -226,6 +245,26 @@ struct mx2_fmt_cfg { + struct mx2_prp_cfg cfg; + }; + ++enum mx2_buffer_state { ++ MX2_STATE_QUEUED, ++ MX2_STATE_ACTIVE, ++ MX2_STATE_DONE, ++}; ++ ++struct mx2_buf_internal { ++ struct list_head queue; ++ int bufnum; ++ bool discard; ++}; ++ ++/* buffer for one video frame */ ++struct mx2_buffer { ++ /* common v4l buffer stuff -- must be first */ ++ struct vb2_buffer vb; ++ enum mx2_buffer_state state; ++ struct mx2_buf_internal internal; ++}; ++ + struct mx2_camera_dev { + struct device *dev; + struct soc_camera_host soc_host; +@@ -242,6 +281,7 @@ struct mx2_camera_dev { + + struct list_head capture; + struct list_head active_bufs; ++ struct list_head discard; + + spinlock_t lock; + +@@ -250,26 +290,23 @@ struct mx2_camera_dev { + struct mx2_buffer *fb1_active; + struct mx2_buffer *fb2_active; + +- int use_emma; +- + u32 csicr1; + ++ struct mx2_buf_internal buf_discard[2]; + void *discard_buffer; + dma_addr_t discard_buffer_dma; + size_t discard_size; + struct mx2_fmt_cfg *emma_prp; ++ struct emma_prp_resize resizing[2]; ++ unsigned int s_width, s_height; + u32 frame_count; ++ struct vb2_alloc_ctx *alloc_ctx; + }; + +-/* buffer for one video frame */ +-struct mx2_buffer { +- /* common v4l buffer stuff -- must be first */ +- struct videobuf_buffer vb; +- +- enum v4l2_mbus_pixelcode code; +- +- int bufnum; +-}; ++static struct mx2_buffer *mx2_ibuf_to_buf(struct mx2_buf_internal *int_buf) ++{ ++ return container_of(int_buf, struct mx2_buffer, internal); ++} + + static struct mx2_fmt_cfg mx27_emma_prp_table[] = { + /* +@@ -324,13 +361,36 @@ static struct mx2_fmt_cfg *mx27_emma_prp + return &mx27_emma_prp_table[0]; + }; + ++static void mx27_update_emma_buf(struct mx2_camera_dev *pcdev, ++ unsigned long phys, int bufnum) ++{ ++ struct mx2_fmt_cfg *prp = pcdev->emma_prp; ++ ++ if (prp->cfg.channel == 1) { ++ writel(phys, pcdev->base_emma + ++ PRP_DEST_RGB1_PTR + 4 * bufnum); ++ } else { ++ writel(phys, pcdev->base_emma + ++ PRP_DEST_Y_PTR - 0x14 * bufnum); ++ if (prp->out_fmt == V4L2_PIX_FMT_YUV420) { ++ u32 imgsize = pcdev->icd->user_height * ++ pcdev->icd->user_width; ++ ++ writel(phys + imgsize, pcdev->base_emma + ++ PRP_DEST_CB_PTR - 0x14 * bufnum); ++ writel(phys + ((5 * imgsize) / 4), pcdev->base_emma + ++ PRP_DEST_CR_PTR - 0x14 * bufnum); ++ } ++ } ++} ++ + static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) + { + unsigned long flags; + + clk_disable(pcdev->clk_csi); + writel(0, pcdev->base_csi + CSICR1); +- if (mx27_camera_emma(pcdev)) { ++ if (cpu_is_mx27()) { + writel(0, pcdev->base_emma + PRP_CNTL); + } else if (cpu_is_mx25()) { + spin_lock_irqsave(&pcdev->lock, flags); +@@ -362,7 +422,7 @@ static int mx2_camera_add_device(struct + + csicr1 = CSICR1_MCLKEN; + +- if (mx27_camera_emma(pcdev)) { ++ if (cpu_is_mx27()) { + csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC | + CSICR1_RXFF_LEVEL(0); + } else if (cpu_is_mx27()) +@@ -392,56 +452,13 @@ static void mx2_camera_remove_device(str + + mx2_camera_deactivate(pcdev); + +- if (pcdev->discard_buffer) { +- dma_free_coherent(ici->v4l2_dev.dev, pcdev->discard_size, +- pcdev->discard_buffer, +- pcdev->discard_buffer_dma); +- pcdev->discard_buffer = NULL; +- } +- + pcdev->icd = NULL; + } + +-#ifdef CONFIG_MACH_MX27 +-static void mx27_camera_dma_enable(struct mx2_camera_dev *pcdev) +-{ +- u32 tmp; +- +- imx_dma_enable(pcdev->dma); +- +- tmp = readl(pcdev->base_csi + CSICR1); +- tmp |= CSICR1_RF_OR_INTEN; +- writel(tmp, pcdev->base_csi + CSICR1); +-} +- +-static irqreturn_t mx27_camera_irq(int irq_csi, void *data) +-{ +- struct mx2_camera_dev *pcdev = data; +- u32 status = readl(pcdev->base_csi + CSISR); +- +- if (status & CSISR_SOF_INT && pcdev->active) { +- u32 tmp; +- +- tmp = readl(pcdev->base_csi + CSICR1); +- writel(tmp | CSICR1_CLR_RXFIFO, pcdev->base_csi + CSICR1); +- mx27_camera_dma_enable(pcdev); +- } +- +- writel(CSISR_SOF_INT | CSISR_RFF_OR_INT, pcdev->base_csi + CSISR); +- +- return IRQ_HANDLED; +-} +-#else +-static irqreturn_t mx27_camera_irq(int irq_csi, void *data) +-{ +- return IRQ_NONE; +-} +-#endif /* CONFIG_MACH_MX27 */ +- + static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb, + int state) + { +- struct videobuf_buffer *vb; ++ struct vb2_buffer *vb; + struct mx2_buffer *buf; + struct mx2_buffer **fb_active = fb == 1 ? &pcdev->fb1_active : + &pcdev->fb2_active; +@@ -454,25 +471,24 @@ static void mx25_camera_frame_done(struc + goto out; + + vb = &(*fb_active)->vb; +- dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +- vb, vb->baddr, vb->bsize); +- +- vb->state = state; +- do_gettimeofday(&vb->ts); +- vb->field_count++; ++ dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, ++ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); + +- wake_up(&vb->done); ++ do_gettimeofday(&vb->v4l2_buf.timestamp); ++ vb->v4l2_buf.sequence++; ++ vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + + if (list_empty(&pcdev->capture)) { + buf = NULL; + writel(0, pcdev->base_csi + fb_reg); + } else { +- buf = list_entry(pcdev->capture.next, struct mx2_buffer, +- vb.queue); ++ buf = list_first_entry(&pcdev->capture, struct mx2_buffer, ++ internal.queue); + vb = &buf->vb; +- list_del(&vb->queue); +- vb->state = VIDEOBUF_ACTIVE; +- writel(videobuf_to_dma_contig(vb), pcdev->base_csi + fb_reg); ++ list_del(&buf->internal.queue); ++ buf->state = MX2_STATE_ACTIVE; ++ writel(vb2_dma_contig_plane_dma_addr(vb, 0), ++ pcdev->base_csi + fb_reg); + } + + *fb_active = buf; +@@ -487,9 +503,9 @@ static irqreturn_t mx25_camera_irq(int i + u32 status = readl(pcdev->base_csi + CSISR); + + if (status & CSISR_DMA_TSF_FB1_INT) +- mx25_camera_frame_done(pcdev, 1, VIDEOBUF_DONE); ++ mx25_camera_frame_done(pcdev, 1, MX2_STATE_DONE); + else if (status & CSISR_DMA_TSF_FB2_INT) +- mx25_camera_frame_done(pcdev, 2, VIDEOBUF_DONE); ++ mx25_camera_frame_done(pcdev, 2, MX2_STATE_DONE); + + /* FIXME: handle CSISR_RFF_OR_INT */ + +@@ -501,59 +517,50 @@ static irqreturn_t mx25_camera_irq(int i + /* + * Videobuf operations + */ +-static int mx2_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, +- unsigned int *size) ++static int mx2_videobuf_setup(struct vb2_queue *vq, ++ const struct v4l2_format *fmt, ++ unsigned int *count, unsigned int *num_planes, ++ unsigned int sizes[], void *alloc_ctxs[]) + { +- struct soc_camera_device *icd = vq->priv_data; ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vq); ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct mx2_camera_dev *pcdev = ici->priv; + int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); + +- dev_dbg(icd->parent, "count=%d, size=%d\n", *count, *size); ++ dev_dbg(icd->parent, "count=%d, size=%d\n", *count, sizes[0]); ++ ++ /* TODO: support for VIDIOC_CREATE_BUFS not ready */ ++ if (fmt != NULL) ++ return -ENOTTY; + + if (bytes_per_line < 0) + return bytes_per_line; + +- *size = bytes_per_line * icd->user_height; ++ alloc_ctxs[0] = pcdev->alloc_ctx; ++ ++ sizes[0] = bytes_per_line * icd->user_height; + + if (0 == *count) + *count = 32; +- if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) +- *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size; ++ if (!*num_planes && ++ sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024) ++ *count = (MAX_VIDEO_MEM * 1024 * 1024) / sizes[0]; + +- return 0; +-} +- +-static void free_buffer(struct videobuf_queue *vq, struct mx2_buffer *buf) +-{ +- struct soc_camera_device *icd = vq->priv_data; +- struct videobuf_buffer *vb = &buf->vb; ++ *num_planes = 1; + +- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +- vb, vb->baddr, vb->bsize); +- +- /* +- * This waits until this buffer is out of danger, i.e., until it is no +- * longer in state VIDEOBUF_QUEUED or VIDEOBUF_ACTIVE +- */ +- videobuf_waiton(vq, vb, 0, 0); +- +- videobuf_dma_contig_free(vq, vb); +- dev_dbg(icd->parent, "%s freed\n", __func__); +- +- vb->state = VIDEOBUF_NEEDS_INIT; ++ return 0; + } + +-static int mx2_videobuf_prepare(struct videobuf_queue *vq, +- struct videobuf_buffer *vb, enum v4l2_field field) ++static int mx2_videobuf_prepare(struct vb2_buffer *vb) + { +- struct soc_camera_device *icd = vq->priv_data; +- struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); + int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); + int ret = 0; + +- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +- vb, vb->baddr, vb->bsize); ++ dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, ++ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); + + if (bytes_per_line < 0) + return bytes_per_line; +@@ -563,99 +570,58 @@ static int mx2_videobuf_prepare(struct v + * This can be useful if you want to see if we actually fill + * the buffer with something + */ +- memset((void *)vb->baddr, 0xaa, vb->bsize); ++ memset((void *)vb2_plane_vaddr(vb, 0), ++ 0xaa, vb2_get_plane_payload(vb, 0)); + #endif + +- if (buf->code != icd->current_fmt->code || +- vb->width != icd->user_width || +- vb->height != icd->user_height || +- vb->field != field) { +- buf->code = icd->current_fmt->code; +- vb->width = icd->user_width; +- vb->height = icd->user_height; +- vb->field = field; +- vb->state = VIDEOBUF_NEEDS_INIT; +- } +- +- vb->size = bytes_per_line * vb->height; +- if (vb->baddr && vb->bsize < vb->size) { ++ vb2_set_plane_payload(vb, 0, bytes_per_line * icd->user_height); ++ if (vb2_plane_vaddr(vb, 0) && ++ vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) { + ret = -EINVAL; + goto out; + } + +- if (vb->state == VIDEOBUF_NEEDS_INIT) { +- ret = videobuf_iolock(vq, vb, NULL); +- if (ret) +- goto fail; +- +- vb->state = VIDEOBUF_PREPARED; +- } +- + return 0; + +-fail: +- free_buffer(vq, buf); + out: + return ret; + } + +-static void mx2_videobuf_queue(struct videobuf_queue *vq, +- struct videobuf_buffer *vb) ++static void mx2_videobuf_queue(struct vb2_buffer *vb) + { +- struct soc_camera_device *icd = vq->priv_data; ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); + struct soc_camera_host *ici = + to_soc_camera_host(icd->parent); + struct mx2_camera_dev *pcdev = ici->priv; + struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); + unsigned long flags; + +- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +- vb, vb->baddr, vb->bsize); ++ dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, ++ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); + + spin_lock_irqsave(&pcdev->lock, flags); + +- vb->state = VIDEOBUF_QUEUED; +- list_add_tail(&vb->queue, &pcdev->capture); +- +- if (mx27_camera_emma(pcdev)) { +- goto out; +-#ifdef CONFIG_MACH_MX27 +- } else if (cpu_is_mx27()) { +- int ret; +- +- if (pcdev->active == NULL) { +- ret = imx_dma_setup_single(pcdev->dma, +- videobuf_to_dma_contig(vb), vb->size, +- (u32)pcdev->base_dma + 0x10, +- DMA_MODE_READ); +- if (ret) { +- vb->state = VIDEOBUF_ERROR; +- wake_up(&vb->done); +- goto out; +- } ++ buf->state = MX2_STATE_QUEUED; ++ list_add_tail(&buf->internal.queue, &pcdev->capture); + +- vb->state = VIDEOBUF_ACTIVE; +- pcdev->active = buf; +- } +-#endif +- } else { /* cpu_is_mx25() */ ++ if (cpu_is_mx25()) { + u32 csicr3, dma_inten = 0; + + if (pcdev->fb1_active == NULL) { +- writel(videobuf_to_dma_contig(vb), ++ writel(vb2_dma_contig_plane_dma_addr(vb, 0), + pcdev->base_csi + CSIDMASA_FB1); + pcdev->fb1_active = buf; + dma_inten = CSICR1_FB1_DMA_INTEN; + } else if (pcdev->fb2_active == NULL) { +- writel(videobuf_to_dma_contig(vb), ++ writel(vb2_dma_contig_plane_dma_addr(vb, 0), + pcdev->base_csi + CSIDMASA_FB2); + pcdev->fb2_active = buf; + dma_inten = CSICR1_FB2_DMA_INTEN; + } + + if (dma_inten) { +- list_del(&vb->queue); +- vb->state = VIDEOBUF_ACTIVE; ++ list_del(&buf->internal.queue); ++ buf->state = MX2_STATE_ACTIVE; + + csicr3 = readl(pcdev->base_csi + CSICR3); + +@@ -674,36 +640,31 @@ static void mx2_videobuf_queue(struct vi + } + } + +-out: + spin_unlock_irqrestore(&pcdev->lock, flags); + } + +-static void mx2_videobuf_release(struct videobuf_queue *vq, +- struct videobuf_buffer *vb) ++static void mx2_videobuf_release(struct vb2_buffer *vb) + { +- struct soc_camera_device *icd = vq->priv_data; ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct mx2_camera_dev *pcdev = ici->priv; + struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); + unsigned long flags; + + #ifdef DEBUG +- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +- vb, vb->baddr, vb->bsize); ++ dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, ++ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); + +- switch (vb->state) { +- case VIDEOBUF_ACTIVE: ++ switch (buf->state) { ++ case MX2_STATE_ACTIVE: + dev_info(icd->parent, "%s (active)\n", __func__); + break; +- case VIDEOBUF_QUEUED: ++ case MX2_STATE_QUEUED: + dev_info(icd->parent, "%s (queued)\n", __func__); + break; +- case VIDEOBUF_PREPARED: +- dev_info(icd->parent, "%s (prepared)\n", __func__); +- break; + default: + dev_info(icd->parent, "%s (unknown) %d\n", __func__, +- vb->state); ++ buf->state); + break; + } + #endif +@@ -717,11 +678,9 @@ static void mx2_videobuf_release(struct + * state. This requires a specific handling for each of the these DMA + * types. + */ ++ + spin_lock_irqsave(&pcdev->lock, flags); +- if (vb->state == VIDEOBUF_QUEUED) { +- list_del(&vb->queue); +- vb->state = VIDEOBUF_ERROR; +- } else if (cpu_is_mx25() && vb->state == VIDEOBUF_ACTIVE) { ++ if (cpu_is_mx25() && buf->state == MX2_STATE_ACTIVE) { + if (pcdev->fb1_active == buf) { + pcdev->csicr1 &= ~CSICR1_FB1_DMA_INTEN; + writel(0, pcdev->base_csi + CSIDMASA_FB1); +@@ -732,30 +691,260 @@ static void mx2_videobuf_release(struct + pcdev->fb2_active = NULL; + } + writel(pcdev->csicr1, pcdev->base_csi + CSICR1); +- vb->state = VIDEOBUF_ERROR; + } + spin_unlock_irqrestore(&pcdev->lock, flags); ++} ++ ++static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, ++ int bytesperline) ++{ ++ struct soc_camera_host *ici = ++ to_soc_camera_host(icd->parent); ++ struct mx2_camera_dev *pcdev = ici->priv; ++ struct mx2_fmt_cfg *prp = pcdev->emma_prp; ++ ++ writel((pcdev->s_width << 16) | pcdev->s_height, ++ pcdev->base_emma + PRP_SRC_FRAME_SIZE); ++ writel(prp->cfg.src_pixel, ++ pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); ++ if (prp->cfg.channel == 1) { ++ writel((icd->user_width << 16) | icd->user_height, ++ pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); ++ writel(bytesperline, ++ pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); ++ writel(prp->cfg.ch1_pixel, ++ pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); ++ } else { /* channel 2 */ ++ writel((icd->user_width << 16) | icd->user_height, ++ pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); ++ } ++ ++ /* Enable interrupts */ ++ writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL); ++} ++ ++static void mx2_prp_resize_commit(struct mx2_camera_dev *pcdev) ++{ ++ int dir; ++ ++ for (dir = RESIZE_DIR_H; dir <= RESIZE_DIR_V; dir++) { ++ unsigned char *s = pcdev->resizing[dir].s; ++ int len = pcdev->resizing[dir].len; ++ unsigned int coeff[2] = {0, 0}; ++ unsigned int valid = 0; ++ int i; ++ ++ if (len == 0) ++ continue; ++ ++ for (i = RESIZE_NUM_MAX - 1; i >= 0; i--) { ++ int j; ++ ++ j = i > 9 ? 1 : 0; ++ coeff[j] = (coeff[j] << BC_COEF) | ++ (s[i] & (SZ_COEF - 1)); ++ ++ if (i == 5 || i == 15) ++ coeff[j] <<= 1; ++ ++ valid = (valid << 1) | (s[i] >> BC_COEF); ++ } ++ ++ valid |= PRP_RZ_VALID_TBL_LEN(len); ++ ++ if (pcdev->resizing[dir].algo == RESIZE_ALGO_BILINEAR) ++ valid |= PRP_RZ_VALID_BILINEAR; ++ ++ if (pcdev->emma_prp->cfg.channel == 1) { ++ if (dir == RESIZE_DIR_H) { ++ writel(coeff[0], pcdev->base_emma + ++ PRP_CH1_RZ_HORI_COEF1); ++ writel(coeff[1], pcdev->base_emma + ++ PRP_CH1_RZ_HORI_COEF2); ++ writel(valid, pcdev->base_emma + ++ PRP_CH1_RZ_HORI_VALID); ++ } else { ++ writel(coeff[0], pcdev->base_emma + ++ PRP_CH1_RZ_VERT_COEF1); ++ writel(coeff[1], pcdev->base_emma + ++ PRP_CH1_RZ_VERT_COEF2); ++ writel(valid, pcdev->base_emma + ++ PRP_CH1_RZ_VERT_VALID); ++ } ++ } else { ++ if (dir == RESIZE_DIR_H) { ++ writel(coeff[0], pcdev->base_emma + ++ PRP_CH2_RZ_HORI_COEF1); ++ writel(coeff[1], pcdev->base_emma + ++ PRP_CH2_RZ_HORI_COEF2); ++ writel(valid, pcdev->base_emma + ++ PRP_CH2_RZ_HORI_VALID); ++ } else { ++ writel(coeff[0], pcdev->base_emma + ++ PRP_CH2_RZ_VERT_COEF1); ++ writel(coeff[1], pcdev->base_emma + ++ PRP_CH2_RZ_VERT_COEF2); ++ writel(valid, pcdev->base_emma + ++ PRP_CH2_RZ_VERT_VALID); ++ } ++ } ++ } ++} ++ ++static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) ++{ ++ struct soc_camera_device *icd = soc_camera_from_vb2q(q); ++ struct soc_camera_host *ici = ++ to_soc_camera_host(icd->parent); ++ struct mx2_camera_dev *pcdev = ici->priv; ++ struct mx2_fmt_cfg *prp = pcdev->emma_prp; ++ struct vb2_buffer *vb; ++ struct mx2_buffer *buf; ++ unsigned long phys; ++ int bytesperline; ++ ++ if (cpu_is_mx27()) { ++ unsigned long flags; ++ if (count < 2) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&pcdev->lock, flags); ++ ++ buf = list_first_entry(&pcdev->capture, struct mx2_buffer, ++ internal.queue); ++ buf->internal.bufnum = 0; ++ vb = &buf->vb; ++ buf->state = MX2_STATE_ACTIVE; ++ ++ phys = vb2_dma_contig_plane_dma_addr(vb, 0); ++ mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); ++ list_move_tail(pcdev->capture.next, &pcdev->active_bufs); ++ ++ buf = list_first_entry(&pcdev->capture, struct mx2_buffer, ++ internal.queue); ++ buf->internal.bufnum = 1; ++ vb = &buf->vb; ++ buf->state = MX2_STATE_ACTIVE; ++ ++ phys = vb2_dma_contig_plane_dma_addr(vb, 0); ++ mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); ++ list_move_tail(pcdev->capture.next, &pcdev->active_bufs); ++ ++ bytesperline = soc_mbus_bytes_per_line(icd->user_width, ++ icd->current_fmt->host_fmt); ++ if (bytesperline < 0) ++ return bytesperline; ++ ++ /* ++ * I didn't manage to properly enable/disable the prp ++ * on a per frame basis during running transfers, ++ * thus we allocate a buffer here and use it to ++ * discard frames when no buffer is available. ++ * Feel free to work on this ;) ++ */ ++ pcdev->discard_size = icd->user_height * bytesperline; ++ pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, ++ pcdev->discard_size, &pcdev->discard_buffer_dma, ++ GFP_KERNEL); ++ if (!pcdev->discard_buffer) ++ return -ENOMEM; ++ ++ pcdev->buf_discard[0].discard = true; ++ list_add_tail(&pcdev->buf_discard[0].queue, ++ &pcdev->discard); ++ ++ pcdev->buf_discard[1].discard = true; ++ list_add_tail(&pcdev->buf_discard[1].queue, ++ &pcdev->discard); ++ ++ mx2_prp_resize_commit(pcdev); ++ ++ mx27_camera_emma_buf_init(icd, bytesperline); ++ ++ if (prp->cfg.channel == 1) { ++ writel(PRP_CNTL_CH1EN | ++ PRP_CNTL_CSIEN | ++ prp->cfg.in_fmt | ++ prp->cfg.out_fmt | ++ PRP_CNTL_CH1_LEN | ++ PRP_CNTL_CH1BYP | ++ PRP_CNTL_CH1_TSKIP(0) | ++ PRP_CNTL_IN_TSKIP(0), ++ pcdev->base_emma + PRP_CNTL); ++ } else { ++ writel(PRP_CNTL_CH2EN | ++ PRP_CNTL_CSIEN | ++ prp->cfg.in_fmt | ++ prp->cfg.out_fmt | ++ PRP_CNTL_CH2_LEN | ++ PRP_CNTL_CH2_TSKIP(0) | ++ PRP_CNTL_IN_TSKIP(0), ++ pcdev->base_emma + PRP_CNTL); ++ } ++ spin_unlock_irqrestore(&pcdev->lock, flags); ++ } ++ ++ return 0; ++} ++ ++static int mx2_stop_streaming(struct vb2_queue *q) ++{ ++ struct soc_camera_device *icd = soc_camera_from_vb2q(q); ++ struct soc_camera_host *ici = ++ to_soc_camera_host(icd->parent); ++ struct mx2_camera_dev *pcdev = ici->priv; ++ struct mx2_fmt_cfg *prp = pcdev->emma_prp; ++ unsigned long flags; ++ void *b; ++ u32 cntl; ++ ++ if (cpu_is_mx27()) { ++ spin_lock_irqsave(&pcdev->lock, flags); ++ ++ cntl = readl(pcdev->base_emma + PRP_CNTL); ++ if (prp->cfg.channel == 1) { ++ writel(cntl & ~PRP_CNTL_CH1EN, ++ pcdev->base_emma + PRP_CNTL); ++ } else { ++ writel(cntl & ~PRP_CNTL_CH2EN, ++ pcdev->base_emma + PRP_CNTL); ++ } ++ INIT_LIST_HEAD(&pcdev->capture); ++ INIT_LIST_HEAD(&pcdev->active_bufs); ++ INIT_LIST_HEAD(&pcdev->discard); ++ ++ b = pcdev->discard_buffer; ++ pcdev->discard_buffer = NULL; ++ ++ spin_unlock_irqrestore(&pcdev->lock, flags); ++ ++ dma_free_coherent(ici->v4l2_dev.dev, ++ pcdev->discard_size, b, pcdev->discard_buffer_dma); ++ } + +- free_buffer(vq, buf); ++ return 0; + } + +-static struct videobuf_queue_ops mx2_videobuf_ops = { +- .buf_setup = mx2_videobuf_setup, +- .buf_prepare = mx2_videobuf_prepare, +- .buf_queue = mx2_videobuf_queue, +- .buf_release = mx2_videobuf_release, ++static struct vb2_ops mx2_videobuf_ops = { ++ .queue_setup = mx2_videobuf_setup, ++ .buf_prepare = mx2_videobuf_prepare, ++ .buf_queue = mx2_videobuf_queue, ++ .buf_cleanup = mx2_videobuf_release, ++ .start_streaming = mx2_start_streaming, ++ .stop_streaming = mx2_stop_streaming, + }; + +-static void mx2_camera_init_videobuf(struct videobuf_queue *q, ++static int mx2_camera_init_videobuf(struct vb2_queue *q, + struct soc_camera_device *icd) + { +- struct soc_camera_host *ici = to_soc_camera_host(icd->parent); +- struct mx2_camera_dev *pcdev = ici->priv; ++ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ q->io_modes = VB2_MMAP | VB2_USERPTR; ++ q->drv_priv = icd; ++ q->ops = &mx2_videobuf_ops; ++ q->mem_ops = &vb2_dma_contig_memops; ++ q->buf_struct_size = sizeof(struct mx2_buffer); + +- videobuf_queue_dma_contig_init(q, &mx2_videobuf_ops, pcdev->dev, +- &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, +- V4L2_FIELD_NONE, sizeof(struct mx2_buffer), +- icd, &icd->video_lock); ++ return vb2_queue_init(q); + } + + #define MX2_BUS_FLAGS (V4L2_MBUS_MASTER | \ +@@ -785,82 +974,6 @@ static int mx27_camera_emma_prp_reset(st + return -ETIMEDOUT; + } + +-static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, +- int bytesperline) +-{ +- struct soc_camera_host *ici = +- to_soc_camera_host(icd->parent); +- struct mx2_camera_dev *pcdev = ici->priv; +- struct mx2_fmt_cfg *prp = pcdev->emma_prp; +- u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width; +- +- if (prp->cfg.channel == 1) { +- writel(pcdev->discard_buffer_dma, +- pcdev->base_emma + PRP_DEST_RGB1_PTR); +- writel(pcdev->discard_buffer_dma, +- pcdev->base_emma + PRP_DEST_RGB2_PTR); +- +- writel(PRP_CNTL_CH1EN | +- PRP_CNTL_CSIEN | +- prp->cfg.in_fmt | +- prp->cfg.out_fmt | +- PRP_CNTL_CH1_LEN | +- PRP_CNTL_CH1BYP | +- PRP_CNTL_CH1_TSKIP(0) | +- PRP_CNTL_IN_TSKIP(0), +- pcdev->base_emma + PRP_CNTL); +- +- writel((icd->user_width << 16) | icd->user_height, +- pcdev->base_emma + PRP_SRC_FRAME_SIZE); +- writel((icd->user_width << 16) | icd->user_height, +- pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); +- writel(bytesperline, +- pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); +- writel(prp->cfg.src_pixel, +- pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); +- writel(prp->cfg.ch1_pixel, +- pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); +- } else { /* channel 2 */ +- writel(pcdev->discard_buffer_dma, +- pcdev->base_emma + PRP_DEST_Y_PTR); +- writel(pcdev->discard_buffer_dma, +- pcdev->base_emma + PRP_SOURCE_Y_PTR); +- +- if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) { +- writel(pcdev->discard_buffer_dma + imgsize, +- pcdev->base_emma + PRP_DEST_CB_PTR); +- writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4), +- pcdev->base_emma + PRP_DEST_CR_PTR); +- writel(pcdev->discard_buffer_dma + imgsize, +- pcdev->base_emma + PRP_SOURCE_CB_PTR); +- writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4), +- pcdev->base_emma + PRP_SOURCE_CR_PTR); +- } +- +- writel(PRP_CNTL_CH2EN | +- PRP_CNTL_CSIEN | +- prp->cfg.in_fmt | +- prp->cfg.out_fmt | +- PRP_CNTL_CH2_LEN | +- PRP_CNTL_CH2_TSKIP(0) | +- PRP_CNTL_IN_TSKIP(0), +- pcdev->base_emma + PRP_CNTL); +- +- writel((icd->user_width << 16) | icd->user_height, +- pcdev->base_emma + PRP_SRC_FRAME_SIZE); +- +- writel((icd->user_width << 16) | icd->user_height, +- pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); +- +- writel(prp->cfg.src_pixel, +- pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); +- +- } +- +- /* Enable interrupts */ +- writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL); +-} +- + static int mx2_camera_set_bus_param(struct soc_camera_device *icd) + { + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); +@@ -939,31 +1052,10 @@ static int mx2_camera_set_bus_param(stru + if (bytesperline < 0) + return bytesperline; + +- if (mx27_camera_emma(pcdev)) { ++ if (cpu_is_mx27()) { + ret = mx27_camera_emma_prp_reset(pcdev); + if (ret) + return ret; +- +- if (pcdev->discard_buffer) +- dma_free_coherent(ici->v4l2_dev.dev, +- pcdev->discard_size, pcdev->discard_buffer, +- pcdev->discard_buffer_dma); +- +- /* +- * I didn't manage to properly enable/disable the prp +- * on a per frame basis during running transfers, +- * thus we allocate a buffer here and use it to +- * discard frames when no buffer is available. +- * Feel free to work on this ;) +- */ +- pcdev->discard_size = icd->user_height * bytesperline; +- pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, +- pcdev->discard_size, &pcdev->discard_buffer_dma, +- GFP_KERNEL); +- if (!pcdev->discard_buffer) +- return -ENOMEM; +- +- mx27_camera_emma_buf_init(icd, bytesperline); + } else if (cpu_is_mx25()) { + writel((bytesperline * icd->user_height) >> 2, + pcdev->base_csi + CSIRXCNT); +@@ -1052,6 +1144,123 @@ static int mx2_camera_get_formats(struct + return formats; + } + ++static int mx2_emmaprp_resize(struct mx2_camera_dev *pcdev, ++ struct v4l2_mbus_framefmt *mf_in, ++ struct v4l2_pix_format *pix_out, bool apply) ++{ ++ int num, den; ++ unsigned long m; ++ int i, dir; ++ ++ for (dir = RESIZE_DIR_H; dir <= RESIZE_DIR_V; dir++) { ++ struct emma_prp_resize tmprsz; ++ unsigned char *s = tmprsz.s; ++ int len = 0; ++ int in, out; ++ ++ if (dir == RESIZE_DIR_H) { ++ in = mf_in->width; ++ out = pix_out->width; ++ } else { ++ in = mf_in->height; ++ out = pix_out->height; ++ } ++ ++ if (in < out) ++ return -EINVAL; ++ else if (in == out) ++ continue; ++ ++ /* Calculate ratio */ ++ m = gcd(in, out); ++ num = in / m; ++ den = out / m; ++ if (num > RESIZE_NUM_MAX) ++ return -EINVAL; ++ ++ if ((num >= 2 * den) && (den == 1) && ++ (num < 9) && (!(num & 0x01))) { ++ int sum = 0; ++ int j; ++ ++ /* Average scaling for >= 2:1 ratios */ ++ /* Support can be added for num >=9 and odd values */ ++ ++ tmprsz.algo = RESIZE_ALGO_AVERAGING; ++ len = num; ++ ++ for (i = 0; i < (len / 2); i++) ++ s[i] = 8; ++ ++ do { ++ for (i = 0; i < (len / 2); i++) { ++ s[i] = s[i] >> 1; ++ sum = 0; ++ for (j = 0; j < (len / 2); j++) ++ sum += s[j]; ++ if (sum == 4) ++ break; ++ } ++ } while (sum != 4); ++ ++ for (i = (len / 2); i < len; i++) ++ s[i] = s[len - i - 1]; ++ ++ s[len - 1] |= SZ_COEF; ++ } else { ++ /* bilinear scaling for < 2:1 ratios */ ++ int v; /* overflow counter */ ++ int coeff, nxt; /* table output */ ++ int in_pos_inc = 2 * den; ++ int out_pos = num; ++ int out_pos_inc = 2 * num; ++ int init_carry = num - den; ++ int carry = init_carry; ++ ++ tmprsz.algo = RESIZE_ALGO_BILINEAR; ++ v = den + in_pos_inc; ++ do { ++ coeff = v - out_pos; ++ out_pos += out_pos_inc; ++ carry += out_pos_inc; ++ for (nxt = 0; v < out_pos; nxt++) { ++ v += in_pos_inc; ++ carry -= in_pos_inc; ++ } ++ ++ if (len > RESIZE_NUM_MAX) ++ return -EINVAL; ++ ++ coeff = ((coeff << BC_COEF) + ++ (in_pos_inc >> 1)) / in_pos_inc; ++ ++ if (coeff >= (SZ_COEF - 1)) ++ coeff--; ++ ++ coeff |= SZ_COEF; ++ s[len] = (unsigned char)coeff; ++ len++; ++ ++ for (i = 1; i < nxt; i++) { ++ if (len >= RESIZE_NUM_MAX) ++ return -EINVAL; ++ s[len] = 0; ++ len++; ++ } ++ } while (carry != init_carry); ++ } ++ tmprsz.len = len; ++ if (dir == RESIZE_DIR_H) ++ mf_in->width = pix_out->width; ++ else ++ mf_in->height = pix_out->height; ++ ++ if (apply) ++ memcpy(&pcdev->resizing[dir], &tmprsz, sizeof(tmprsz)); ++ } ++ return 0; ++} ++ + static int mx2_camera_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) + { +@@ -1063,6 +1272,9 @@ static int mx2_camera_set_fmt(struct soc + struct v4l2_mbus_framefmt mf; + int ret; + ++ dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n", ++ __func__, pix->width, pix->height); ++ + xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); + if (!xlate) { + dev_warn(icd->parent, "Format %x not found\n", +@@ -1080,6 +1292,22 @@ static int mx2_camera_set_fmt(struct soc + if (ret < 0 && ret != -ENOIOCTLCMD) + return ret; + ++ /* Store width and height returned by the sensor for resizing */ ++ pcdev->s_width = mf.width; ++ pcdev->s_height = mf.height; ++ dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n", ++ __func__, pcdev->s_width, pcdev->s_height); ++ ++ pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, ++ xlate->host_fmt->fourcc); ++ ++ memset(pcdev->resizing, 0, sizeof(pcdev->resizing)); ++ if ((mf.width != pix->width || mf.height != pix->height) && ++ pcdev->emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { ++ if (mx2_emmaprp_resize(pcdev, &mf, pix, true) < 0) ++ dev_dbg(icd->parent, "%s: can't resize\n", __func__); ++ } ++ + if (mf.code != xlate->code) + return -EINVAL; + +@@ -1089,9 +1317,8 @@ static int mx2_camera_set_fmt(struct soc + pix->colorspace = mf.colorspace; + icd->current_fmt = xlate; + +- if (mx27_camera_emma(pcdev)) +- pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, +- xlate->host_fmt->fourcc); ++ dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n", ++ __func__, pix->width, pix->height); + + return 0; + } +@@ -1104,9 +1331,14 @@ static int mx2_camera_try_fmt(struct soc + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_mbus_framefmt mf; + __u32 pixfmt = pix->pixelformat; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct mx2_camera_dev *pcdev = ici->priv; + unsigned int width_limit; + int ret; + ++ dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n", ++ __func__, pix->width, pix->height); ++ + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (pixfmt && !xlate) { + dev_warn(icd->parent, "Format %x not found\n", pixfmt); +@@ -1156,6 +1388,20 @@ static int mx2_camera_try_fmt(struct soc + if (ret < 0) + return ret; + ++ dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n", ++ __func__, pcdev->s_width, pcdev->s_height); ++ ++ /* If the sensor does not support image size try PrP resizing */ ++ pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, ++ xlate->host_fmt->fourcc); ++ ++ memset(pcdev->resizing, 0, sizeof(pcdev->resizing)); ++ if ((mf.width != pix->width || mf.height != pix->height) && ++ pcdev->emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { ++ if (mx2_emmaprp_resize(pcdev, &mf, pix, false) < 0) ++ dev_dbg(icd->parent, "%s: can't resize\n", __func__); ++ } ++ + if (mf.field == V4L2_FIELD_ANY) + mf.field = V4L2_FIELD_NONE; + /* +@@ -1174,6 +1420,9 @@ static int mx2_camera_try_fmt(struct soc + pix->field = mf.field; + pix->colorspace = mf.colorspace; + ++ dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n", ++ __func__, pix->width, pix->height); ++ + return 0; + } + +@@ -1187,136 +1436,11 @@ static int mx2_camera_querycap(struct so + return 0; + } + +-static int mx2_camera_reqbufs(struct soc_camera_device *icd, +- struct v4l2_requestbuffers *p) +-{ +- int i; +- +- for (i = 0; i < p->count; i++) { +- struct mx2_buffer *buf = container_of(icd->vb_vidq.bufs[i], +- struct mx2_buffer, vb); +- INIT_LIST_HEAD(&buf->vb.queue); +- } +- +- return 0; +-} +- +-#ifdef CONFIG_MACH_MX27 +-static void mx27_camera_frame_done(struct mx2_camera_dev *pcdev, int state) +-{ +- struct videobuf_buffer *vb; +- struct mx2_buffer *buf; +- unsigned long flags; +- int ret; +- +- spin_lock_irqsave(&pcdev->lock, flags); +- +- if (!pcdev->active) { +- dev_err(pcdev->dev, "%s called with no active buffer!\n", +- __func__); +- goto out; +- } +- +- vb = &pcdev->active->vb; +- buf = container_of(vb, struct mx2_buffer, vb); +- WARN_ON(list_empty(&vb->queue)); +- dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +- vb, vb->baddr, vb->bsize); +- +- /* _init is used to debug races, see comment in pxa_camera_reqbufs() */ +- list_del_init(&vb->queue); +- vb->state = state; +- do_gettimeofday(&vb->ts); +- vb->field_count++; +- +- wake_up(&vb->done); +- +- if (list_empty(&pcdev->capture)) { +- pcdev->active = NULL; +- goto out; +- } +- +- pcdev->active = list_entry(pcdev->capture.next, +- struct mx2_buffer, vb.queue); +- +- vb = &pcdev->active->vb; +- vb->state = VIDEOBUF_ACTIVE; +- +- ret = imx_dma_setup_single(pcdev->dma, videobuf_to_dma_contig(vb), +- vb->size, (u32)pcdev->base_dma + 0x10, DMA_MODE_READ); +- +- if (ret) { +- vb->state = VIDEOBUF_ERROR; +- pcdev->active = NULL; +- wake_up(&vb->done); +- } +- +-out: +- spin_unlock_irqrestore(&pcdev->lock, flags); +-} +- +-static void mx27_camera_dma_err_callback(int channel, void *data, int err) +-{ +- struct mx2_camera_dev *pcdev = data; +- +- mx27_camera_frame_done(pcdev, VIDEOBUF_ERROR); +-} +- +-static void mx27_camera_dma_callback(int channel, void *data) +-{ +- struct mx2_camera_dev *pcdev = data; +- +- mx27_camera_frame_done(pcdev, VIDEOBUF_DONE); +-} +- +-#define DMA_REQ_CSI_RX 31 /* FIXME: Add this to a resource */ +- +-static int __devinit mx27_camera_dma_init(struct platform_device *pdev, +- struct mx2_camera_dev *pcdev) +-{ +- int err; +- +- pcdev->dma = imx_dma_request_by_prio("CSI RX DMA", DMA_PRIO_HIGH); +- if (pcdev->dma < 0) { +- dev_err(&pdev->dev, "%s failed to request DMA channel\n", +- __func__); +- return pcdev->dma; +- } +- +- err = imx_dma_setup_handlers(pcdev->dma, mx27_camera_dma_callback, +- mx27_camera_dma_err_callback, pcdev); +- if (err) { +- dev_err(&pdev->dev, "%s failed to set DMA callback\n", +- __func__); +- goto err_out; +- } +- +- err = imx_dma_config_channel(pcdev->dma, +- IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO, +- IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, +- DMA_REQ_CSI_RX, 1); +- if (err) { +- dev_err(&pdev->dev, "%s failed to config DMA channel\n", +- __func__); +- goto err_out; +- } +- +- imx_dma_config_burstlen(pcdev->dma, 64); +- +- return 0; +- +-err_out: +- imx_dma_free(pcdev->dma); +- +- return err; +-} +-#endif /* CONFIG_MACH_MX27 */ +- + static unsigned int mx2_camera_poll(struct file *file, poll_table *pt) + { + struct soc_camera_device *icd = file->private_data; + +- return videobuf_poll_stream(file, &icd->vb_vidq, pt); ++ return vb2_poll(&icd->vb2_vidq, file, pt); + } + + static struct soc_camera_host_ops mx2_soc_camera_host_ops = { +@@ -1327,144 +1451,148 @@ static struct soc_camera_host_ops mx2_so + .set_crop = mx2_camera_set_crop, + .get_formats = mx2_camera_get_formats, + .try_fmt = mx2_camera_try_fmt, +- .init_videobuf = mx2_camera_init_videobuf, +- .reqbufs = mx2_camera_reqbufs, ++ .init_videobuf2 = mx2_camera_init_videobuf, + .poll = mx2_camera_poll, + .querycap = mx2_camera_querycap, + .set_bus_param = mx2_camera_set_bus_param, + }; + + static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, +- int bufnum, int state) ++ int bufnum, bool err) + { +- u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width; ++#ifdef DEBUG + struct mx2_fmt_cfg *prp = pcdev->emma_prp; ++#endif ++ struct mx2_buf_internal *ibuf; + struct mx2_buffer *buf; +- struct videobuf_buffer *vb; ++ struct vb2_buffer *vb; + unsigned long phys; + +- if (!list_empty(&pcdev->active_bufs)) { +- buf = list_entry(pcdev->active_bufs.next, +- struct mx2_buffer, vb.queue); ++ ibuf = list_first_entry(&pcdev->active_bufs, struct mx2_buf_internal, ++ queue); + +- BUG_ON(buf->bufnum != bufnum); ++ BUG_ON(ibuf->bufnum != bufnum); ++ ++ if (ibuf->discard) { ++ /* ++ * Discard buffer must not be returned to user space. ++ * Just return it to the discard queue. ++ */ ++ list_move_tail(pcdev->active_bufs.next, &pcdev->discard); ++ } else { ++ buf = mx2_ibuf_to_buf(ibuf); + + vb = &buf->vb; + #ifdef DEBUG +- phys = videobuf_to_dma_contig(vb); ++ phys = vb2_dma_contig_plane_dma_addr(vb, 0); + if (prp->cfg.channel == 1) { + if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + + 4 * bufnum) != phys) { +- dev_err(pcdev->dev, "%p != %p\n", phys, +- readl(pcdev->base_emma + +- PRP_DEST_RGB1_PTR + +- 4 * bufnum)); ++ dev_err(pcdev->dev, "%lx != %x\n", phys, ++ readl(pcdev->base_emma + ++ PRP_DEST_RGB1_PTR + 4 * bufnum)); + } + } else { + if (readl(pcdev->base_emma + PRP_DEST_Y_PTR - + 0x14 * bufnum) != phys) { +- dev_err(pcdev->dev, "%p != %p\n", phys, +- readl(pcdev->base_emma + +- PRP_DEST_Y_PTR - +- 0x14 * bufnum)); ++ dev_err(pcdev->dev, "%lx != %x\n", phys, ++ readl(pcdev->base_emma + ++ PRP_DEST_Y_PTR - 0x14 * bufnum)); + } + } + #endif +- dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, +- vb->baddr, vb->bsize); +- +- list_del(&vb->queue); +- vb->state = state; +- do_gettimeofday(&vb->ts); +- vb->field_count = pcdev->frame_count * 2; +- pcdev->frame_count++; +- +- wake_up(&vb->done); ++ dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, vb, ++ vb2_plane_vaddr(vb, 0), ++ vb2_get_plane_payload(vb, 0)); ++ ++ list_del_init(&buf->internal.queue); ++ do_gettimeofday(&vb->v4l2_buf.timestamp); ++ vb->v4l2_buf.sequence = pcdev->frame_count; ++ if (err) ++ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); ++ else ++ vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + } + ++ pcdev->frame_count++; ++ + if (list_empty(&pcdev->capture)) { +- if (prp->cfg.channel == 1) { +- writel(pcdev->discard_buffer_dma, pcdev->base_emma + +- PRP_DEST_RGB1_PTR + 4 * bufnum); +- } else { +- writel(pcdev->discard_buffer_dma, pcdev->base_emma + +- PRP_DEST_Y_PTR - +- 0x14 * bufnum); +- if (prp->out_fmt == V4L2_PIX_FMT_YUV420) { +- writel(pcdev->discard_buffer_dma + imgsize, +- pcdev->base_emma + PRP_DEST_CB_PTR - +- 0x14 * bufnum); +- writel(pcdev->discard_buffer_dma + +- ((5 * imgsize) / 4), pcdev->base_emma + +- PRP_DEST_CR_PTR - 0x14 * bufnum); +- } ++ if (list_empty(&pcdev->discard)) { ++ dev_warn(pcdev->dev, "%s: trying to access empty discard list\n", ++ __func__); ++ return; + } ++ ++ ibuf = list_first_entry(&pcdev->discard, ++ struct mx2_buf_internal, queue); ++ ibuf->bufnum = bufnum; ++ ++ list_move_tail(pcdev->discard.next, &pcdev->active_bufs); ++ mx27_update_emma_buf(pcdev, pcdev->discard_buffer_dma, bufnum); + return; + } + +- buf = list_entry(pcdev->capture.next, +- struct mx2_buffer, vb.queue); ++ buf = list_first_entry(&pcdev->capture, struct mx2_buffer, ++ internal.queue); + +- buf->bufnum = !bufnum; ++ buf->internal.bufnum = bufnum; + + list_move_tail(pcdev->capture.next, &pcdev->active_bufs); + + vb = &buf->vb; +- vb->state = VIDEOBUF_ACTIVE; ++ buf->state = MX2_STATE_ACTIVE; + +- phys = videobuf_to_dma_contig(vb); +- if (prp->cfg.channel == 1) { +- writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum); +- } else { +- writel(phys, pcdev->base_emma + +- PRP_DEST_Y_PTR - 0x14 * bufnum); +- if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) { +- writel(phys + imgsize, pcdev->base_emma + +- PRP_DEST_CB_PTR - 0x14 * bufnum); +- writel(phys + ((5 * imgsize) / 4), pcdev->base_emma + +- PRP_DEST_CR_PTR - 0x14 * bufnum); +- } +- } ++ phys = vb2_dma_contig_plane_dma_addr(vb, 0); ++ mx27_update_emma_buf(pcdev, phys, bufnum); + } + + static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) + { + struct mx2_camera_dev *pcdev = data; + unsigned int status = readl(pcdev->base_emma + PRP_INTRSTATUS); +- struct mx2_buffer *buf; ++ struct mx2_buf_internal *ibuf; ++ ++ spin_lock(&pcdev->lock); ++ ++ if (list_empty(&pcdev->active_bufs)) { ++ dev_warn(pcdev->dev, "%s: called while active list is empty\n", ++ __func__); ++ ++ if (!status) { ++ spin_unlock(&pcdev->lock); ++ return IRQ_NONE; ++ } ++ } + + if (status & (1 << 7)) { /* overflow */ +- u32 cntl; +- /* +- * We only disable channel 1 here since this is the only +- * enabled channel +- * +- * FIXME: the correct DMA overflow handling should be resetting +- * the buffer, returning an error frame, and continuing with +- * the next one. +- */ +- cntl = readl(pcdev->base_emma + PRP_CNTL); ++ u32 cntl = readl(pcdev->base_emma + PRP_CNTL); + writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN), + pcdev->base_emma + PRP_CNTL); + writel(cntl, pcdev->base_emma + PRP_CNTL); +- } +- if ((((status & (3 << 5)) == (3 << 5)) || +- ((status & (3 << 3)) == (3 << 3))) +- && !list_empty(&pcdev->active_bufs)) { ++ ++ ibuf = list_first_entry(&pcdev->active_bufs, ++ struct mx2_buf_internal, queue); ++ mx27_camera_frame_done_emma(pcdev, ++ ibuf->bufnum, true); ++ ++ status &= ~(1 << 7); ++ } else if (((status & (3 << 5)) == (3 << 5)) || ++ ((status & (3 << 3)) == (3 << 3))) { + /* + * Both buffers have triggered, process the one we're expecting + * to first + */ +- buf = list_entry(pcdev->active_bufs.next, +- struct mx2_buffer, vb.queue); +- mx27_camera_frame_done_emma(pcdev, buf->bufnum, VIDEOBUF_DONE); +- status &= ~(1 << (6 - buf->bufnum)); /* mark processed */ +- } +- if ((status & (1 << 6)) || (status & (1 << 4))) +- mx27_camera_frame_done_emma(pcdev, 0, VIDEOBUF_DONE); +- if ((status & (1 << 5)) || (status & (1 << 3))) +- mx27_camera_frame_done_emma(pcdev, 1, VIDEOBUF_DONE); ++ ibuf = list_first_entry(&pcdev->active_bufs, ++ struct mx2_buf_internal, queue); ++ mx27_camera_frame_done_emma(pcdev, ibuf->bufnum, false); ++ status &= ~(1 << (6 - ibuf->bufnum)); /* mark processed */ ++ } else if ((status & (1 << 6)) || (status & (1 << 4))) { ++ mx27_camera_frame_done_emma(pcdev, 0, false); ++ } else if ((status & (1 << 5)) || (status & (1 << 3))) { ++ mx27_camera_frame_done_emma(pcdev, 1, false); ++ } + ++ spin_unlock(&pcdev->lock); + writel(status, pcdev->base_emma + PRP_INTRSTATUS); + + return IRQ_HANDLED; +@@ -1527,8 +1655,6 @@ static int __devinit mx2_camera_probe(st + struct resource *res_csi, *res_emma; + void __iomem *base_csi; + int irq_csi, irq_emma; +- irq_handler_t mx2_cam_irq_handler = cpu_is_mx25() ? mx25_camera_irq +- : mx27_camera_irq; + int err = 0; + + dev_dbg(&pdev->dev, "initialising\n"); +@@ -1550,22 +1676,11 @@ static int __devinit mx2_camera_probe(st + + pcdev->clk_csi = clk_get(&pdev->dev, NULL); + if (IS_ERR(pcdev->clk_csi)) { ++ dev_err(&pdev->dev, "Could not get csi clock\n"); + err = PTR_ERR(pcdev->clk_csi); + goto exit_kfree; + } + +- dev_dbg(&pdev->dev, "Camera clock frequency: %ld\n", +- clk_get_rate(pcdev->clk_csi)); +- +- /* Initialize DMA */ +-#ifdef CONFIG_MACH_MX27 +- if (cpu_is_mx27()) { +- err = mx27_camera_dma_init(pdev, pcdev); +- if (err) +- goto exit_clk_put; +- } +-#endif /* CONFIG_MACH_MX27 */ +- + pcdev->res_csi = res_csi; + pcdev->pdata = pdev->dev.platform_data; + if (pcdev->pdata) { +@@ -1585,6 +1700,7 @@ static int __devinit mx2_camera_probe(st + + INIT_LIST_HEAD(&pcdev->capture); + INIT_LIST_HEAD(&pcdev->active_bufs); ++ INIT_LIST_HEAD(&pcdev->discard); + spin_lock_init(&pcdev->lock); + + /* +@@ -1606,11 +1722,13 @@ static int __devinit mx2_camera_probe(st + pcdev->base_dma = res_csi->start; + pcdev->dev = &pdev->dev; + +- err = request_irq(pcdev->irq_csi, mx2_cam_irq_handler, 0, +- MX2_CAM_DRV_NAME, pcdev); +- if (err) { +- dev_err(pcdev->dev, "Camera interrupt register failed \n"); +- goto exit_iounmap; ++ if (cpu_is_mx25()) { ++ err = request_irq(pcdev->irq_csi, mx25_camera_irq, 0, ++ MX2_CAM_DRV_NAME, pcdev); ++ if (err) { ++ dev_err(pcdev->dev, "Camera interrupt register failed \n"); ++ goto exit_iounmap; ++ } + } + + if (cpu_is_mx27()) { +@@ -1618,14 +1736,15 @@ static int __devinit mx2_camera_probe(st + res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1); + irq_emma = platform_get_irq(pdev, 1); + +- if (res_emma && irq_emma >= 0) { +- dev_info(&pdev->dev, "Using EMMA\n"); +- pcdev->use_emma = 1; +- pcdev->res_emma = res_emma; +- pcdev->irq_emma = irq_emma; +- if (mx27_camera_emma_init(pcdev)) +- goto exit_free_irq; ++ if (!res_emma || !irq_emma) { ++ dev_err(&pdev->dev, "no EMMA resources\n"); ++ goto exit_free_irq; + } ++ ++ pcdev->res_emma = res_emma; ++ pcdev->irq_emma = irq_emma; ++ if (mx27_camera_emma_init(pcdev)) ++ goto exit_free_irq; + } + + pcdev->soc_host.drv_name = MX2_CAM_DRV_NAME, +@@ -1633,6 +1752,12 @@ static int __devinit mx2_camera_probe(st + pcdev->soc_host.priv = pcdev; + pcdev->soc_host.v4l2_dev.dev = &pdev->dev; + pcdev->soc_host.nr = pdev->id; ++ ++ pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); ++ if (IS_ERR(pcdev->alloc_ctx)) { ++ err = PTR_ERR(pcdev->alloc_ctx); ++ goto eallocctx; ++ } + err = soc_camera_host_register(&pcdev->soc_host); + if (err) + goto exit_free_emma; +@@ -1643,26 +1768,24 @@ static int __devinit mx2_camera_probe(st + return 0; + + exit_free_emma: +- if (mx27_camera_emma(pcdev)) { ++ vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); ++eallocctx: ++ if (cpu_is_mx27()) { + free_irq(pcdev->irq_emma, pcdev); + clk_disable(pcdev->clk_emma); + clk_put(pcdev->clk_emma); + iounmap(pcdev->base_emma); +- release_mem_region(res_emma->start, resource_size(res_emma)); ++ release_mem_region(pcdev->res_emma->start, resource_size(pcdev->res_emma)); + } + exit_free_irq: +- free_irq(pcdev->irq_csi, pcdev); ++ if (cpu_is_mx25()) ++ free_irq(pcdev->irq_csi, pcdev); + exit_iounmap: + iounmap(base_csi); + exit_release: + release_mem_region(res_csi->start, resource_size(res_csi)); + exit_dma_free: +-#ifdef CONFIG_MACH_MX27 +- if (cpu_is_mx27()) +- imx_dma_free(pcdev->dma); +-exit_clk_put: + clk_put(pcdev->clk_csi); +-#endif /* CONFIG_MACH_MX27 */ + exit_kfree: + kfree(pcdev); + exit: +@@ -1677,19 +1800,18 @@ static int __devexit mx2_camera_remove(s + struct resource *res; + + clk_put(pcdev->clk_csi); +-#ifdef CONFIG_MACH_MX27 ++ if (cpu_is_mx25()) ++ free_irq(pcdev->irq_csi, pcdev); + if (cpu_is_mx27()) +- imx_dma_free(pcdev->dma); +-#endif /* CONFIG_MACH_MX27 */ +- free_irq(pcdev->irq_csi, pcdev); +- if (mx27_camera_emma(pcdev)) + free_irq(pcdev->irq_emma, pcdev); + + soc_camera_host_unregister(&pcdev->soc_host); + ++ vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); ++ + iounmap(pcdev->base_csi); + +- if (mx27_camera_emma(pcdev)) { ++ if (cpu_is_mx27()) { + clk_disable(pcdev->clk_emma); + clk_put(pcdev->clk_emma); + iounmap(pcdev->base_emma); +Index: linux-3.3.x86_64/drivers/media/rc/rc-core-priv.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/rc-core-priv.h ++++ linux-3.3.x86_64/drivers/media/rc/rc-core-priv.h +@@ -35,7 +35,7 @@ struct ir_raw_event_ctrl { + struct list_head list; /* to keep track of raw clients */ + struct task_struct *thread; + spinlock_t lock; +- struct kfifo kfifo; /* fifo for the pulse/space durations */ ++ struct kfifo_rec_ptr_1 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 rc_dev *dev; /* pointer to the parent rc_dev */ +Index: linux-3.3.x86_64/drivers/media/video/s2255drv.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s2255drv.c ++++ linux-3.3.x86_64/drivers/media/video/s2255drv.c +@@ -134,7 +134,7 @@ + + /* usb config commands */ + #define IN_DATA_TOKEN cpu_to_le32(0x2255c0de) +-#define CMD_2255 cpu_to_le32(0xc2255000) ++#define CMD_2255 0xc2255000 + #define CMD_SET_MODE cpu_to_le32((CMD_2255 | 0x10)) + #define CMD_START cpu_to_le32((CMD_2255 | 0x20)) + #define CMD_STOP cpu_to_le32((CMD_2255 | 0x30)) +@@ -852,15 +852,13 @@ static int vidioc_querycap(struct file * + static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) + { +- int index = 0; +- if (f) +- index = f->index; ++ int index = f->index; + + if (index >= ARRAY_SIZE(formats)) + return -EINVAL; +- if (!jpeg_enable && ((formats[index].fourcc == V4L2_PIX_FMT_JPEG) || +- (formats[index].fourcc == V4L2_PIX_FMT_MJPEG))) +- return -EINVAL; ++ if (!jpeg_enable && ((formats[index].fourcc == V4L2_PIX_FMT_JPEG) || ++ (formats[index].fourcc == V4L2_PIX_FMT_MJPEG))) ++ return -EINVAL; + dprintk(4, "name %s\n", formats[index].name); + strlcpy(f->description, formats[index].name, sizeof(f->description)); + f->pixelformat = formats[index].fourcc; +@@ -2027,7 +2025,7 @@ static int save_frame(struct s2255_dev * + pdata[1]); + offset = jj + PREFIX_SIZE; + bframe = 1; +- cc = pdword[1]; ++ cc = le32_to_cpu(pdword[1]); + if (cc >= MAX_CHANNELS) { + printk(KERN_ERR + "bad channel\n"); +@@ -2036,22 +2034,22 @@ static int save_frame(struct s2255_dev * + /* reverse it */ + dev->cc = G_chnmap[cc]; + channel = &dev->channel[dev->cc]; +- payload = pdword[3]; ++ payload = le32_to_cpu(pdword[3]); + if (payload > channel->req_image_size) { + channel->bad_payload++; + /* discard the bad frame */ + return -EINVAL; + } + channel->pkt_size = payload; +- channel->jpg_size = pdword[4]; ++ channel->jpg_size = le32_to_cpu(pdword[4]); + break; + case S2255_MARKER_RESPONSE: + + pdata += DEF_USB_BLOCK; + jj += DEF_USB_BLOCK; +- if (pdword[1] >= MAX_CHANNELS) ++ if (le32_to_cpu(pdword[1]) >= MAX_CHANNELS) + break; +- cc = G_chnmap[pdword[1]]; ++ cc = G_chnmap[le32_to_cpu(pdword[1])]; + if (cc >= MAX_CHANNELS) + break; + channel = &dev->channel[cc]; +@@ -2074,11 +2072,11 @@ static int save_frame(struct s2255_dev * + wake_up(&dev->fw_data->wait_fw); + break; + case S2255_RESPONSE_STATUS: +- channel->vidstatus = pdword[3]; ++ channel->vidstatus = le32_to_cpu(pdword[3]); + channel->vidstatus_ready = 1; + wake_up(&channel->wait_vidstatus); + dprintk(5, "got vidstatus %x chan %d\n", +- pdword[3], cc); ++ le32_to_cpu(pdword[3]), cc); + break; + default: + printk(KERN_INFO "s2255 unknown resp\n"); +@@ -2605,10 +2603,11 @@ static int s2255_probe(struct usb_interf + __le32 *pRel; + pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4]; + printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel); +- dev->dsp_fw_ver = *pRel; +- if (*pRel < S2255_CUR_DSP_FWVER) ++ dev->dsp_fw_ver = le32_to_cpu(*pRel); ++ if (dev->dsp_fw_ver < S2255_CUR_DSP_FWVER) + printk(KERN_INFO "s2255: f2255usb.bin out of date.\n"); +- if (dev->pid == 0x2257 && *pRel < S2255_MIN_DSP_COLORFILTER) ++ if (dev->pid == 0x2257 && ++ dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER) + printk(KERN_WARNING "s2255: 2257 requires firmware %d" + " or above.\n", S2255_MIN_DSP_COLORFILTER); + } +Index: linux-3.3.x86_64/drivers/media/common/tuners/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/common/tuners/Makefile ++++ linux-3.3.x86_64/drivers/media/common/tuners/Makefile +@@ -28,6 +28,8 @@ obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc + obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o + obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o + obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o ++obj-$(CONFIG_MEDIA_TUNER_TUA9001) += tua9001.o ++obj-$(CONFIG_MEDIA_TUNER_FC0011) += fc0011.o + +-ccflags-y += -Idrivers/media/dvb/dvb-core +-ccflags-y += -Idrivers/media/dvb/frontends ++ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core ++ccflags-y += -I$(srctree)/drivers/media/dvb/frontends +Index: linux-3.3.x86_64/drivers/media/video/saa7134/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7134/Makefile ++++ linux-3.3.x86_64/drivers/media/video/saa7134/Makefile +@@ -10,7 +10,7 @@ obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7 + + obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o + +-ccflags-y += -Idrivers/media/video +-ccflags-y += -Idrivers/media/common/tuners +-ccflags-y += -Idrivers/media/dvb/dvb-core +-ccflags-y += -Idrivers/media/dvb/frontends ++ccflags-y += -I$(srctree)/drivers/media/video ++ccflags-y += -I$(srctree)/drivers/media/common/tuners ++ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core ++ccflags-y += -I$(srctree)/drivers/media/dvb/frontends +Index: linux-3.3.x86_64/drivers/media/video/saa7164/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7164/Makefile ++++ linux-3.3.x86_64/drivers/media/video/saa7164/Makefile +@@ -4,9 +4,9 @@ saa7164-objs := saa7164-cards.o saa7164- + + obj-$(CONFIG_VIDEO_SAA7164) += saa7164.o + +-ccflags-y += -Idrivers/media/video +-ccflags-y += -Idrivers/media/common/tuners +-ccflags-y += -Idrivers/media/dvb/dvb-core +-ccflags-y += -Idrivers/media/dvb/frontends ++ccflags-y += -I$(srctree)/drivers/media/video ++ccflags-y += -I$(srctree)/drivers/media/common/tuners ++ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core ++ccflags-y += -I$(srctree)/drivers/media/dvb/frontends + + ccflags-y += $(extra-cflags-y) $(extra-cflags-m) +Index: linux-3.3.x86_64/drivers/media/video/ivtv/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/Makefile ++++ linux-3.3.x86_64/drivers/media/video/ivtv/Makefile +@@ -7,8 +7,8 @@ ivtv-objs := ivtv-routing.o ivtv-cards.o + obj-$(CONFIG_VIDEO_IVTV) += ivtv.o + obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o + +-ccflags-y += -Idrivers/media/video +-ccflags-y += -Idrivers/media/common/tuners +-ccflags-y += -Idrivers/media/dvb/dvb-core +-ccflags-y += -Idrivers/media/dvb/frontends ++ccflags-y += -I$(srctree)/drivers/media/video ++ccflags-y += -I$(srctree)/drivers/media/common/tuners ++ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core ++ccflags-y += -I$(srctree)/drivers/media/dvb/frontends + +Index: linux-3.3.x86_64/drivers/media/video/gspca/gl860/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/gspca/gl860/Makefile ++++ linux-3.3.x86_64/drivers/media/video/gspca/gl860/Makefile +@@ -6,5 +6,5 @@ gspca_gl860-objs := gl860.o \ + gl860-ov9655.o \ + gl860-mi2020.o + +-ccflags-y += -Idrivers/media/video/gspca ++ccflags-y += -I$(srctree)/drivers/media/video/gspca + +Index: linux-3.3.x86_64/drivers/media/video/gspca/m5602/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/gspca/m5602/Makefile ++++ linux-3.3.x86_64/drivers/media/video/gspca/m5602/Makefile +@@ -8,4 +8,4 @@ gspca_m5602-objs := m5602_core.o \ + m5602_s5k83a.o \ + m5602_s5k4aa.o + +-ccflags-y += -Idrivers/media/video/gspca ++ccflags-y += -I$(srctree)/drivers/media/video/gspca +Index: linux-3.3.x86_64/drivers/media/video/gspca/stv06xx/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/gspca/stv06xx/Makefile ++++ linux-3.3.x86_64/drivers/media/video/gspca/stv06xx/Makefile +@@ -6,5 +6,5 @@ gspca_stv06xx-objs := stv06xx.o \ + stv06xx_pb0100.o \ + stv06xx_st6422.o + +-ccflags-y += -Idrivers/media/video/gspca ++ccflags-y += -I$(srctree)/drivers/media/video/gspca + +Index: linux-3.3.x86_64/Documentation/dvb/cards.txt +=================================================================== +--- linux-3.3.x86_64.orig/Documentation/dvb/cards.txt ++++ linux-3.3.x86_64/Documentation/dvb/cards.txt +@@ -119,4 +119,5 @@ o Cards based on the Phillips saa7134 PC + - Compro Videomate DVB-T300 + - Compro Videomate DVB-T200 + - AVerMedia AVerTVHD MCE A180 ++ - KWorld PC150-U ATSC Hybrid + +Index: linux-3.3.x86_64/drivers/media/rc/keymaps/rc-kworld-pc150u.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/rc/keymaps/rc-kworld-pc150u.c +@@ -0,0 +1,102 @@ ++/* kworld-pc150u.c - Keytable for kworld_pc150u Remote Controller ++ * ++ * keymap imported from ir-keymaps.c ++ * ++ * Copyright (c) 2010 by Kyle Strickland ++ * (based on kworld-plus-tv-analog.c 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 ++#include ++ ++/* Kworld PC150-U ++ Kyle Strickland ++ */ ++ ++static struct rc_map_table kworld_pc150u[] = { ++ { 0x0c, KEY_MEDIA }, /* Kworld key */ ++ { 0x16, KEY_EJECTCLOSECD }, /* -> ) */ ++ { 0x1d, KEY_POWER2 }, ++ ++ { 0x00, KEY_1 }, ++ { 0x01, KEY_2 }, ++ { 0x02, KEY_3 }, ++ { 0x03, KEY_4 }, ++ { 0x04, KEY_5 }, ++ { 0x05, KEY_6 }, ++ { 0x06, KEY_7 }, ++ { 0x07, KEY_8 }, ++ { 0x08, KEY_9 }, ++ { 0x0a, KEY_0 }, ++ ++ { 0x09, KEY_AGAIN }, ++ { 0x14, KEY_MUTE }, ++ ++ { 0x1e, KEY_LAST }, ++ { 0x17, KEY_ZOOM }, ++ { 0x1f, KEY_HOMEPAGE }, ++ { 0x0e, KEY_ESC }, ++ ++ { 0x20, KEY_UP }, ++ { 0x21, KEY_DOWN }, ++ { 0x42, KEY_LEFT }, ++ { 0x43, KEY_RIGHT }, ++ { 0x0b, KEY_ENTER }, ++ ++ { 0x10, KEY_CHANNELUP }, ++ { 0x11, KEY_CHANNELDOWN }, ++ ++ { 0x13, KEY_VOLUMEUP }, ++ { 0x12, KEY_VOLUMEDOWN }, ++ ++ { 0x19, KEY_TIME}, /* Timeshift */ ++ { 0x1a, KEY_STOP}, ++ { 0x1b, KEY_RECORD}, ++ { 0x4b, KEY_EMAIL}, ++ ++ { 0x40, KEY_REWIND}, ++ { 0x44, KEY_PLAYPAUSE}, ++ { 0x41, KEY_FORWARD}, ++ { 0x22, KEY_TEXT}, ++ ++ { 0x15, KEY_AUDIO}, /* ((*)) */ ++ { 0x0f, KEY_MODE}, /* display ratio */ ++ { 0x1c, KEY_SYSRQ}, /* snapshot */ ++ { 0x4a, KEY_SLEEP}, /* sleep timer */ ++ ++ { 0x48, KEY_SOUND}, /* switch theater mode */ ++ { 0x49, KEY_BLUE}, /* A */ ++ { 0x18, KEY_RED}, /* B */ ++ { 0x23, KEY_GREEN}, /* C */ ++}; ++ ++static struct rc_map_list kworld_pc150u_map = { ++ .map = { ++ .scan = kworld_pc150u, ++ .size = ARRAY_SIZE(kworld_pc150u), ++ .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ ++ .name = RC_MAP_KWORLD_PC150U, ++ } ++}; ++ ++static int __init init_rc_map_kworld_pc150u(void) ++{ ++ return rc_map_register(&kworld_pc150u_map); ++} ++ ++static void __exit exit_rc_map_kworld_pc150u(void) ++{ ++ rc_map_unregister(&kworld_pc150u_map); ++} ++ ++module_init(init_rc_map_kworld_pc150u) ++module_exit(exit_rc_map_kworld_pc150u) ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Kyle Strickland "); +Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-cards.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa7134-cards.c ++++ linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-cards.c +@@ -33,6 +33,7 @@ + #include "tea5767.h" + #include "tda18271.h" + #include "xc5000.h" ++#include "s5h1411.h" + + /* commly used strings */ + static char name_mute[] = "mute"; +@@ -5712,6 +5713,36 @@ struct saa7134_board saa7134_boards[] = + .amux = LINE1, + } }, + }, ++ [SAA7134_BOARD_KWORLD_PC150U] = { ++ .name = "Kworld PC150-U", ++ .audio_clock = 0x00187de7, ++ .tuner_type = TUNER_PHILIPS_TDA8290, ++ .radio_type = UNSET, ++ .tuner_addr = ADDR_UNSET, ++ .radio_addr = ADDR_UNSET, ++ .mpeg = SAA7134_MPEG_DVB, ++ .gpiomask = 1 << 21, ++ .ts_type = SAA7134_MPEG_TS_PARALLEL, ++ .inputs = { { ++ .name = name_tv, ++ .vmux = 1, ++ .amux = TV, ++ .tv = 1, ++ }, { ++ .name = name_comp, ++ .vmux = 3, ++ .amux = LINE1, ++ }, { ++ .name = name_svideo, ++ .vmux = 8, ++ .amux = LINE2, ++ } }, ++ .radio = { ++ .name = name_radio, ++ .amux = TV, ++ .gpio = 0x0000000, ++ }, ++ }, + + }; + +@@ -6306,6 +6337,12 @@ struct pci_device_id saa7134_pci_tbl[] = + .driver_data = SAA7134_BOARD_KWORLD_ATSC110, /* ATSC 115 */ + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, ++ .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ ++ .subvendor = 0x17de, ++ .subdevice = 0xa134, ++ .driver_data = SAA7134_BOARD_KWORLD_PC150U, ++ }, { ++ .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x1461, + .subdevice = 0x7360, +@@ -7134,6 +7171,23 @@ static inline int saa7134_kworld_sbtvd_t + return 0; + } + ++static int saa7134_kworld_pc150u_toggle_agc(struct saa7134_dev *dev, ++ enum tda18271_mode mode) ++{ ++ switch (mode) { ++ case TDA18271_ANALOG: ++ saa7134_set_gpio(dev, 18, 0); ++ break; ++ case TDA18271_DIGITAL: ++ saa7134_set_gpio(dev, 18, 1); ++ msleep(30); ++ break; ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ + static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, + int command, int arg) + { +@@ -7150,6 +7204,9 @@ static int saa7134_tda8290_18271_callbac + case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: + ret = saa7134_kworld_sbtvd_toggle_agc(dev, arg); + break; ++ case SAA7134_BOARD_KWORLD_PC150U: ++ ret = saa7134_kworld_pc150u_toggle_agc(dev, arg); ++ break; + default: + break; + } +@@ -7171,6 +7228,7 @@ static int saa7134_tda8290_callback(stru + case SAA7134_BOARD_HAUPPAUGE_HVR1120: + case SAA7134_BOARD_AVERMEDIA_M733A: + case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: ++ case SAA7134_BOARD_KWORLD_PC150U: + case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2: + /* tda8290 + tda18271 */ + ret = saa7134_tda8290_18271_callback(dev, command, arg); +@@ -7452,6 +7510,7 @@ int saa7134_board_init1(struct saa7134_d + case SAA7134_BOARD_BEHOLD_X7: + case SAA7134_BOARD_BEHOLD_H7: + case SAA7134_BOARD_BEHOLD_A7: ++ case SAA7134_BOARD_KWORLD_PC150U: + dev->has_remote = SAA7134_REMOTE_I2C; + break; + case SAA7134_BOARD_AVERMEDIA_A169_B: +Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-dvb.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa7134-dvb.c ++++ linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-dvb.c +@@ -61,6 +61,7 @@ + #include "zl10036.h" + #include "zl10039.h" + #include "mt312.h" ++#include "s5h1411.h" + + MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); + MODULE_LICENSE("GPL"); +@@ -1158,6 +1159,33 @@ static struct tda18271_config prohdtv_pr + .output_opt = TDA18271_OUTPUT_LT_OFF, + }; + ++static struct tda18271_std_map kworld_tda18271_std_map = { ++ .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 3, ++ .if_lvl = 6, .rfagc_top = 0x37 }, ++ .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 0, ++ .if_lvl = 6, .rfagc_top = 0x37 }, ++}; ++ ++static struct tda18271_config kworld_pc150u_tda18271_config = { ++ .std_map = &kworld_tda18271_std_map, ++ .gate = TDA18271_GATE_ANALOG, ++ .output_opt = TDA18271_OUTPUT_LT_OFF, ++ .config = 3, /* Use tuner callback for AGC */ ++ .rf_cal_on_startup = 1 ++}; ++ ++static struct s5h1411_config kworld_s5h1411_config = { ++ .output_mode = S5H1411_PARALLEL_OUTPUT, ++ .gpio = S5H1411_GPIO_OFF, ++ .qam_if = S5H1411_IF_4000, ++ .vsb_if = S5H1411_IF_3250, ++ .inversion = S5H1411_INVERSION_ON, ++ .status_mode = S5H1411_DEMODLOCKING, ++ .mpeg_timing = ++ S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, ++}; ++ ++ + /* ================================================================== + * Core code + */ +@@ -1438,6 +1466,22 @@ static int dvb_init(struct saa7134_dev * + &dev->i2c_adap, 0x61, + TUNER_PHILIPS_TUV1236D); + break; ++ case SAA7134_BOARD_KWORLD_PC150U: ++ saa7134_set_gpio(dev, 18, 1); /* Switch to digital mode */ ++ saa7134_tuner_callback(dev, 0, ++ TDA18271_CALLBACK_CMD_AGC_ENABLE, 1); ++ fe0->dvb.frontend = dvb_attach(s5h1411_attach, ++ &kworld_s5h1411_config, ++ &dev->i2c_adap); ++ if (fe0->dvb.frontend != NULL) { ++ dvb_attach(tda829x_attach, fe0->dvb.frontend, ++ &dev->i2c_adap, 0x4b, ++ &tda829x_no_probe); ++ dvb_attach(tda18271_attach, fe0->dvb.frontend, ++ 0x60, &dev->i2c_adap, ++ &kworld_pc150u_tda18271_config); ++ } ++ break; + case SAA7134_BOARD_FLYDVBS_LR300: + fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, + &dev->i2c_adap); +Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-i2c.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa7134-i2c.c ++++ linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-i2c.c +@@ -254,7 +254,9 @@ static int saa7134_i2c_xfer(struct i2c_a + addr = msgs[i].addr << 1; + if (msgs[i].flags & I2C_M_RD) + addr |= 1; +- if (i > 0 && msgs[i].flags & I2C_M_RD && msgs[i].addr != 0x40) { ++ if (i > 0 && msgs[i].flags & ++ I2C_M_RD && msgs[i].addr != 0x40 && ++ msgs[i].addr != 0x19) { + /* workaround for a saa7134 i2c bug + * needed to talk to the mt352 demux + * thanks to pinnacle for the hint */ +@@ -279,6 +281,16 @@ static int saa7134_i2c_xfer(struct i2c_a + d1printk("%02x", rc); + msgs[i].buf[byte] = rc; + } ++ /* discard mysterious extra byte when reading ++ from Samsung S5H1411. i2c bus gets error ++ if we do not. */ ++ if (0x19 == msgs[i].addr) { ++ d1printk(" ?"); ++ rc = i2c_recv_byte(dev); ++ if (rc < 0) ++ goto err; ++ d1printk("%02x", rc); ++ } + } else { + /* write bytes */ + d2printk("write bytes\n"); +Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-input.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa7134-input.c ++++ linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-input.c +@@ -210,6 +210,54 @@ static int get_key_msi_tvanywhere_plus(s + return 1; + } + ++/* copied and modified from get_key_msi_tvanywhere_plus() */ ++static int get_key_kworld_pc150u(struct IR_i2c *ir, u32 *ir_key, ++ u32 *ir_raw) ++{ ++ unsigned char b; ++ unsigned int gpio; ++ ++ /* is needed to access GPIO. Used by the saa_readl macro. */ ++ struct saa7134_dev *dev = ir->c->adapter->algo_data; ++ if (dev == NULL) { ++ i2cdprintk("get_key_kworld_pc150u: " ++ "ir->c->adapter->algo_data is NULL!\n"); ++ return -EIO; ++ } ++ ++ /* rising SAA7134_GPIO_GPRESCAN reads the status */ ++ ++ saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); ++ saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); ++ ++ gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); ++ ++ /* GPIO&0x100 is pulsed low when a button is pressed. Don't do ++ I2C receive if gpio&0x100 is not low. */ ++ ++ if (gpio & 0x100) ++ return 0; /* No button press */ ++ ++ /* GPIO says there is a button press. Get it. */ ++ ++ if (1 != i2c_master_recv(ir->c, &b, 1)) { ++ i2cdprintk("read error\n"); ++ return -EIO; ++ } ++ ++ /* No button press */ ++ ++ if (b == 0xff) ++ return 0; ++ ++ /* Button pressed */ ++ ++ dprintk("get_key_kworld_pc150u: Key = 0x%02X\n", b); ++ *ir_key = b; ++ *ir_raw = b; ++ return 1; ++} ++ + static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) + { + unsigned char b; +@@ -894,6 +942,21 @@ void saa7134_probe_i2c_ir(struct saa7134 + info.addr = 0x30; + /* MSI TV@nywhere Plus controller doesn't seem to + respond to probes unless we read something from ++ an existing device. Weird... ++ REVISIT: might no longer be needed */ ++ rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); ++ dprintk("probe 0x%02x @ %s: %s\n", ++ msg_msi.addr, dev->i2c_adap.name, ++ (1 == rc) ? "yes" : "no"); ++ break; ++ case SAA7134_BOARD_KWORLD_PC150U: ++ /* copied and modified from MSI TV@nywhere Plus */ ++ dev->init_data.name = "Kworld PC150-U"; ++ dev->init_data.get_key = get_key_kworld_pc150u; ++ dev->init_data.ir_codes = RC_MAP_KWORLD_PC150U; ++ info.addr = 0x30; ++ /* MSI TV@nywhere Plus controller doesn't seem to ++ respond to probes unless we read something from + an existing device. Weird... + REVISIT: might no longer be needed */ + rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); +Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa7134.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa7134.h ++++ linux-3.3.x86_64/drivers/media/video/saa7134/saa7134.h +@@ -126,8 +126,8 @@ struct saa7134_card_ir { + unsigned users; + + u32 polling; +- u32 last_gpio; +- u32 mask_keycode, mask_keydown, mask_keyup; ++ u32 last_gpio; ++ u32 mask_keycode, mask_keydown, mask_keyup; + + bool running; + bool active; +@@ -331,6 +331,7 @@ struct saa7134_card_ir { + #define SAA7134_BOARD_BEHOLD_501 186 + #define SAA7134_BOARD_BEHOLD_503FM 187 + #define SAA7134_BOARD_SENSORAY811_911 188 ++#define SAA7134_BOARD_KWORLD_PC150U 189 + + #define SAA7134_MAXBOARDS 32 + #define SAA7134_INPUT_MAX 8 +Index: linux-3.3.x86_64/drivers/media/video/cx18/cx18-driver.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx18/cx18-driver.c ++++ linux-3.3.x86_64/drivers/media/video/cx18/cx18-driver.c +@@ -38,7 +38,7 @@ + #include "cx18-ioctl.h" + #include "cx18-controls.h" + #include "tuner-xc2028.h" +- ++#include + #include + + /* If you have already X v4l cards, then set this to X. This way +@@ -75,7 +75,7 @@ static int radio[CX18_MAX_CARDS] = { -1, + -1, -1, -1, -1, -1, -1, -1, -1 }; + static unsigned cardtype_c = 1; + static unsigned tuner_c = 1; +-static bool radio_c = 1; ++static unsigned radio_c = 1; + static char pal[] = "--"; + static char secam[] = "--"; + static char ntsc[] = "-"; +@@ -110,7 +110,7 @@ static int retry_mmio = 1; + int cx18_debug; + + module_param_array(tuner, int, &tuner_c, 0644); +-module_param_array(radio, bool, &radio_c, 0644); ++module_param_array(radio, int, &radio_c, 0644); + module_param_array(cardtype, int, &cardtype_c, 0644); + module_param_string(pal, pal, sizeof(pal), 0644); + module_param_string(secam, secam, sizeof(secam), 0644); +@@ -812,7 +812,7 @@ static int cx18_setup_pci(struct cx18 *c + CX18_ERR("Can't enable device %d!\n", cx->instance); + return -EIO; + } +- if (pci_set_dma_mask(pci_dev, 0xffffffff)) { ++ if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) { + CX18_ERR("No suitable DMA available, card %d\n", cx->instance); + return -EIO; + } +Index: linux-3.3.x86_64/drivers/media/rc/Kconfig +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/Kconfig ++++ linux-3.3.x86_64/drivers/media/rc/Kconfig +@@ -266,4 +266,13 @@ config RC_LOOPBACK + To compile this driver as a module, choose M here: the module will + be called rc_loopback. + ++config IR_GPIO_CIR ++ tristate "GPIO IR remote control" ++ depends on RC_CORE ++ ---help--- ++ Say Y if you want to use GPIO based IR Receiver. ++ ++ To compile this driver as a module, choose M here: the module will ++ be called gpio-ir-recv. ++ + endif #RC_CORE +Index: linux-3.3.x86_64/drivers/media/rc/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/Makefile ++++ linux-3.3.x86_64/drivers/media/rc/Makefile +@@ -26,3 +26,4 @@ obj-$(CONFIG_IR_REDRAT3) += redrat3.o + obj-$(CONFIG_IR_STREAMZAP) += streamzap.o + obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o + obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o ++obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.o +Index: linux-3.3.x86_64/drivers/media/rc/gpio-ir-recv.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/rc/gpio-ir-recv.c +@@ -0,0 +1,205 @@ ++/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++ ++#define GPIO_IR_DRIVER_NAME "gpio-rc-recv" ++#define GPIO_IR_DEVICE_NAME "gpio_ir_recv" ++ ++struct gpio_rc_dev { ++ struct rc_dev *rcdev; ++ int gpio_nr; ++ bool active_low; ++}; ++ ++static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) ++{ ++ struct gpio_rc_dev *gpio_dev = dev_id; ++ int gval; ++ int rc = 0; ++ enum raw_event_type type = IR_SPACE; ++ ++ gval = gpio_get_value_cansleep(gpio_dev->gpio_nr); ++ ++ if (gval < 0) ++ goto err_get_value; ++ ++ if (gpio_dev->active_low) ++ gval = !gval; ++ ++ if (gval == 1) ++ type = IR_PULSE; ++ ++ rc = ir_raw_event_store_edge(gpio_dev->rcdev, type); ++ if (rc < 0) ++ goto err_get_value; ++ ++ ir_raw_event_handle(gpio_dev->rcdev); ++ ++err_get_value: ++ return IRQ_HANDLED; ++} ++ ++static int __devinit gpio_ir_recv_probe(struct platform_device *pdev) ++{ ++ struct gpio_rc_dev *gpio_dev; ++ struct rc_dev *rcdev; ++ const struct gpio_ir_recv_platform_data *pdata = ++ pdev->dev.platform_data; ++ int rc; ++ ++ if (!pdata) ++ return -EINVAL; ++ ++ if (pdata->gpio_nr < 0) ++ return -EINVAL; ++ ++ gpio_dev = kzalloc(sizeof(struct gpio_rc_dev), GFP_KERNEL); ++ if (!gpio_dev) ++ return -ENOMEM; ++ ++ rcdev = rc_allocate_device(); ++ if (!rcdev) { ++ rc = -ENOMEM; ++ goto err_allocate_device; ++ } ++ ++ rcdev->driver_type = RC_DRIVER_IR_RAW; ++ rcdev->allowed_protos = RC_TYPE_ALL; ++ rcdev->input_name = GPIO_IR_DEVICE_NAME; ++ rcdev->input_id.bustype = BUS_HOST; ++ rcdev->driver_name = GPIO_IR_DRIVER_NAME; ++ rcdev->map_name = RC_MAP_EMPTY; ++ ++ gpio_dev->rcdev = rcdev; ++ gpio_dev->gpio_nr = pdata->gpio_nr; ++ gpio_dev->active_low = pdata->active_low; ++ ++ rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv"); ++ if (rc < 0) ++ goto err_gpio_request; ++ rc = gpio_direction_input(pdata->gpio_nr); ++ if (rc < 0) ++ goto err_gpio_direction_input; ++ ++ rc = rc_register_device(rcdev); ++ if (rc < 0) { ++ dev_err(&pdev->dev, "failed to register rc device\n"); ++ goto err_register_rc_device; ++ } ++ ++ platform_set_drvdata(pdev, gpio_dev); ++ ++ rc = request_any_context_irq(gpio_to_irq(pdata->gpio_nr), ++ gpio_ir_recv_irq, ++ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, ++ "gpio-ir-recv-irq", gpio_dev); ++ if (rc < 0) ++ goto err_request_irq; ++ ++ return 0; ++ ++err_request_irq: ++ platform_set_drvdata(pdev, NULL); ++ rc_unregister_device(rcdev); ++err_register_rc_device: ++err_gpio_direction_input: ++ gpio_free(pdata->gpio_nr); ++err_gpio_request: ++ rc_free_device(rcdev); ++ rcdev = NULL; ++err_allocate_device: ++ kfree(gpio_dev); ++ return rc; ++} ++ ++static int __devexit gpio_ir_recv_remove(struct platform_device *pdev) ++{ ++ struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); ++ ++ free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev); ++ platform_set_drvdata(pdev, NULL); ++ rc_unregister_device(gpio_dev->rcdev); ++ gpio_free(gpio_dev->gpio_nr); ++ rc_free_device(gpio_dev->rcdev); ++ kfree(gpio_dev); ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int gpio_ir_recv_suspend(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); ++ ++ if (device_may_wakeup(dev)) ++ enable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr)); ++ else ++ disable_irq(gpio_to_irq(gpio_dev->gpio_nr)); ++ ++ return 0; ++} ++ ++static int gpio_ir_recv_resume(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); ++ ++ if (device_may_wakeup(dev)) ++ disable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr)); ++ else ++ enable_irq(gpio_to_irq(gpio_dev->gpio_nr)); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops gpio_ir_recv_pm_ops = { ++ .suspend = gpio_ir_recv_suspend, ++ .resume = gpio_ir_recv_resume, ++}; ++#endif ++ ++static struct platform_driver gpio_ir_recv_driver = { ++ .probe = gpio_ir_recv_probe, ++ .remove = __devexit_p(gpio_ir_recv_remove), ++ .driver = { ++ .name = GPIO_IR_DRIVER_NAME, ++ .owner = THIS_MODULE, ++#ifdef CONFIG_PM ++ .pm = &gpio_ir_recv_pm_ops, ++#endif ++ }, ++}; ++ ++static int __init gpio_ir_recv_init(void) ++{ ++ return platform_driver_register(&gpio_ir_recv_driver); ++} ++module_init(gpio_ir_recv_init); ++ ++static void __exit gpio_ir_recv_exit(void) ++{ ++ platform_driver_unregister(&gpio_ir_recv_driver); ++} ++module_exit(gpio_ir_recv_exit); ++ ++MODULE_DESCRIPTION("GPIO IR Receiver driver"); ++MODULE_LICENSE("GPL v2"); +Index: linux-3.3.x86_64/include/media/gpio-ir-recv.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/include/media/gpio-ir-recv.h +@@ -0,0 +1,22 @@ ++/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * 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. ++ */ ++ ++#ifndef __GPIO_IR_RECV_H__ ++#define __GPIO_IR_RECV_H__ ++ ++struct gpio_ir_recv_platform_data { ++ int gpio_nr; ++ bool active_low; ++}; ++ ++#endif /* __GPIO_IR_RECV_H__ */ ++ +Index: linux-3.3.x86_64/drivers/media/rc/ir-sony-decoder.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/ir-sony-decoder.c ++++ linux-3.3.x86_64/drivers/media/rc/ir-sony-decoder.c +@@ -130,7 +130,7 @@ static int ir_sony_decode(struct rc_dev + case 15: + device = bitrev8((data->bits >> 0) & 0xFF); + subdevice = 0; +- function = bitrev8((data->bits >> 7) & 0xFD); ++ function = bitrev8((data->bits >> 7) & 0xFE); + break; + case 20: + device = bitrev8((data->bits >> 5) & 0xF8); +Index: linux-3.3.x86_64/drivers/media/video/cx25821/cx25821-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx25821/cx25821-core.c ++++ linux-3.3.x86_64/drivers/media/video/cx25821/cx25821-core.c +@@ -1474,8 +1474,13 @@ static DEFINE_PCI_DEVICE_TABLE(cx25821_p + .device = 0x8210, + .subvendor = 0x14f1, + .subdevice = 0x0920, +- }, +- { ++ }, { ++ /* CX25821 No Brand */ ++ .vendor = 0x14f1, ++ .device = 0x8210, ++ .subvendor = 0x0000, ++ .subdevice = 0x0000, ++ }, { + /* --- end of list --- */ + } + }; +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/dib0090.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/dib0090.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/dib0090.c +@@ -519,7 +519,7 @@ static int dib0090_fw_identify(struct dv + return 0; + + identification_error: +- return -EIO;; ++ return -EIO; + } + + static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg) +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/stb0899_drv.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/stb0899_drv.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/stb0899_drv.c +@@ -67,7 +67,7 @@ static const struct stb0899_tab stb0899_ + * Crude linear extrapolation below -84.8dBm and above -8.0dBm. + */ + static const struct stb0899_tab stb0899_dvbsrf_tab[] = { +- { -950, -128 }, ++ { -750, -128 }, + { -748, -94 }, + { -745, -92 }, + { -735, -90 }, +@@ -131,7 +131,7 @@ static const struct stb0899_tab stb0899_ + { -730, 13645 }, + { -750, 13909 }, + { -766, 14153 }, +- { -999, 16383 } ++ { -950, 16383 } + }; + + /* DVB-S2 Es/N0 quant in dB/100 vs read value * 100*/ +@@ -964,6 +964,7 @@ static int stb0899_read_signal_strength( + + int val; + u32 reg; ++ *strength = 0; + switch (state->delsys) { + case SYS_DVBS: + case SYS_DSS: +@@ -983,11 +984,11 @@ static int stb0899_read_signal_strength( + break; + case SYS_DVBS2: + if (internal->lock) { +- reg = STB0899_READ_S2REG(STB0899_DEMOD, IF_AGC_GAIN); ++ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_GAIN); + val = STB0899_GETFIELD(IF_AGC_GAIN, reg); + + *strength = stb0899_table_lookup(stb0899_dvbs2rf_tab, ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1, val); +- *strength += 750; ++ *strength += 950; + dprintk(state->verbose, FE_DEBUG, 1, "IF_AGC_GAIN = 0x%04x, C = %d * 0.1 dBm", + val & 0x3fff, *strength); + } +@@ -1009,6 +1010,7 @@ static int stb0899_read_snr(struct dvb_f + u8 buf[2]; + u32 reg; + ++ *snr = 0; + reg = stb0899_read_reg(state, STB0899_VSTATUS); + switch (state->delsys) { + case SYS_DVBS: +@@ -1071,7 +1073,7 @@ static int stb0899_read_status(struct dv + reg = stb0899_read_reg(state, STB0899_VSTATUS); + if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) { + dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_CARRIER | FE_HAS_LOCK"); +- *status |= FE_HAS_CARRIER | FE_HAS_LOCK; ++ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK; + + reg = stb0899_read_reg(state, STB0899_PLPARM); + if (STB0899_GETFIELD(VITCURPUN, reg)) { +Index: linux-3.3.x86_64/include/sound/tea575x-tuner.h +=================================================================== +--- linux-3.3.x86_64.orig/include/sound/tea575x-tuner.h ++++ linux-3.3.x86_64/include/sound/tea575x-tuner.h +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #define TEA575X_FMIF 10700 + +@@ -42,13 +43,16 @@ struct snd_tea575x_ops { + }; + + struct snd_tea575x { ++ struct v4l2_device *v4l2_dev; + struct video_device vd; /* video device */ ++ int radio_nr; /* radio_nr */ + bool tea5759; /* 5759 chip is present */ ++ bool cannot_read_data; /* Device cannot read the data pin */ + bool mute; /* Device is muted? */ + bool stereo; /* receiving stereo */ + bool tuned; /* tuned to a station */ + unsigned int val; /* hw value */ +- unsigned long freq; /* frequency */ ++ u32 freq; /* frequency */ + struct mutex mutex; + struct snd_tea575x_ops *ops; + void *private_data; +Index: linux-3.3.x86_64/sound/i2c/other/tea575x-tuner.c +=================================================================== +--- linux-3.3.x86_64.orig/sound/i2c/other/tea575x-tuner.c ++++ linux-3.3.x86_64/sound/i2c/other/tea575x-tuner.c +@@ -25,21 +25,20 @@ + #include + #include + #include +-#include ++#include ++#include + #include ++#include + #include ++#include + #include + + MODULE_AUTHOR("Jaroslav Kysela "); + MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); + MODULE_LICENSE("GPL"); + +-static int radio_nr = -1; +-module_param(radio_nr, int, 0); +- +-#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) +-#define FREQ_LO (50UL * 16000) +-#define FREQ_HI (150UL * 16000) ++#define FREQ_LO (76U * 16000) ++#define FREQ_HI (108U * 16000) + + /* + * definitions +@@ -121,28 +120,10 @@ static unsigned int snd_tea575x_read(str + return data; + } + +-static void snd_tea575x_get_freq(struct snd_tea575x *tea) +-{ +- unsigned long freq; +- +- freq = snd_tea575x_read(tea) & TEA575X_BIT_FREQ_MASK; +- /* freq *= 12.5 */ +- freq *= 125; +- freq /= 10; +- /* crystal fixup */ +- if (tea->tea5759) +- freq += TEA575X_FMIF; +- else +- freq -= TEA575X_FMIF; +- +- tea->freq = freq * 16; /* from kHz */ +-} +- + static void snd_tea575x_set_freq(struct snd_tea575x *tea) + { +- unsigned long freq; ++ u32 freq = tea->freq; + +- freq = clamp(tea->freq, FREQ_LO, FREQ_HI); + freq /= 16; /* to kHz */ + /* crystal fixup */ + if (tea->tea5759) +@@ -167,12 +148,14 @@ static int vidioc_querycap(struct file * + { + struct snd_tea575x *tea = video_drvdata(file); + +- strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver)); ++ strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); + strlcpy(v->card, tea->card, sizeof(v->card)); + strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); + strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); +- v->version = RADIO_VERSION; +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; ++ v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; ++ if (!tea->cannot_read_data) ++ v->device_caps |= V4L2_CAP_HW_FREQ_SEEK; ++ v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; + } + +@@ -191,18 +174,24 @@ static int vidioc_g_tuner(struct file *f + v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; + v->rangelow = FREQ_LO; + v->rangehigh = FREQ_HI; +- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; +- v->audmode = tea->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO; ++ v->rxsubchans = tea->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; ++ v->audmode = (tea->val & TEA575X_BIT_MONO) ? ++ V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO; + v->signal = tea->tuned ? 0xffff : 0; +- + return 0; + } + + static int vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) + { +- if (v->index > 0) ++ struct snd_tea575x *tea = video_drvdata(file); ++ ++ if (v->index) + return -EINVAL; ++ tea->val &= ~TEA575X_BIT_MONO; ++ if (v->audmode == V4L2_TUNER_MODE_MONO) ++ tea->val |= TEA575X_BIT_MONO; ++ snd_tea575x_write(tea, tea->val); + return 0; + } + +@@ -214,7 +203,6 @@ static int vidioc_g_frequency(struct fil + if (f->tuner != 0) + return -EINVAL; + f->type = V4L2_TUNER_RADIO; +- snd_tea575x_get_freq(tea); + f->frequency = tea->freq; + return 0; + } +@@ -227,32 +215,47 @@ static int vidioc_s_frequency(struct fil + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; + +- if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) +- return -EINVAL; +- +- tea->freq = f->frequency; +- ++ tea->val &= ~TEA575X_BIT_SEARCH; ++ tea->freq = clamp(f->frequency, FREQ_LO, FREQ_HI); + snd_tea575x_set_freq(tea); +- + return 0; + } + +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) ++static int vidioc_s_hw_freq_seek(struct file *file, void *fh, ++ struct v4l2_hw_freq_seek *a) + { +- if (a->index > 1) +- return -EINVAL; +- +- strcpy(a->name, "Radio"); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; +-} ++ struct snd_tea575x *tea = video_drvdata(file); + +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- if (a->index != 0) ++ if (tea->cannot_read_data) ++ return -ENOTTY; ++ if (a->tuner || a->wrap_around) + return -EINVAL; ++ tea->val |= TEA575X_BIT_SEARCH; ++ tea->val &= ~TEA575X_BIT_UPDOWN; ++ if (a->seek_upward) ++ tea->val |= TEA575X_BIT_UPDOWN; ++ snd_tea575x_write(tea, tea->val); ++ for (;;) { ++ unsigned val = snd_tea575x_read(tea); ++ ++ if (!(val & TEA575X_BIT_SEARCH)) { ++ /* Found a frequency */ ++ val &= TEA575X_BIT_FREQ_MASK; ++ val = (val * 10) / 125; ++ if (tea->tea5759) ++ val += TEA575X_FMIF; ++ else ++ val -= TEA575X_FMIF; ++ tea->freq = clamp(val * 16, FREQ_LO, FREQ_HI); ++ return 0; ++ } ++ if (schedule_timeout_interruptible(msecs_to_jiffies(10))) { ++ /* some signal arrived, stop search */ ++ tea->val &= ~TEA575X_BIT_SEARCH; ++ snd_tea575x_write(tea, tea->val); ++ return -ERESTARTSYS; ++ } ++ } + return 0; + } + +@@ -273,23 +276,27 @@ static int tea575x_s_ctrl(struct v4l2_ct + static const struct v4l2_file_operations tea575x_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = video_ioctl2, ++ .open = v4l2_fh_open, ++ .release = v4l2_fh_release, ++ .poll = v4l2_ctrl_poll, + }; + + static const struct v4l2_ioctl_ops tea575x_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, ++ .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek, ++ .vidioc_log_status = v4l2_ctrl_log_status, ++ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + }; + +-static struct video_device tea575x_radio = { +- .name = "tea575x-tuner", ++static const struct video_device tea575x_radio = { + .fops = &tea575x_fops, + .ioctl_ops = &tea575x_ioctl_ops, +- .release = video_device_release_empty, ++ .release = video_device_release_empty, + }; + + static const struct v4l2_ctrl_ops tea575x_ctrl_ops = { +@@ -303,11 +310,15 @@ int snd_tea575x_init(struct snd_tea575x + { + int retval; + +- tea->mute = 1; ++ tea->mute = true; + +- snd_tea575x_write(tea, 0x55AA); +- if (snd_tea575x_read(tea) != 0x55AA) +- return -ENODEV; ++ /* Not all devices can or know how to read the data back. ++ Such devices can set cannot_read_data to true. */ ++ if (!tea->cannot_read_data) { ++ snd_tea575x_write(tea, 0x55AA); ++ if (snd_tea575x_read(tea) != 0x55AA) ++ return -ENODEV; ++ } + + tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40; + tea->freq = 90500 * 16; /* 90.5Mhz default */ +@@ -316,14 +327,17 @@ int snd_tea575x_init(struct snd_tea575x + tea->vd = tea575x_radio; + video_set_drvdata(&tea->vd, tea); + mutex_init(&tea->mutex); ++ strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name)); + tea->vd.lock = &tea->mutex; ++ tea->vd.v4l2_dev = tea->v4l2_dev; ++ tea->vd.ctrl_handler = &tea->ctrl_handler; ++ set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags); + + v4l2_ctrl_handler_init(&tea->ctrl_handler, 1); +- tea->vd.ctrl_handler = &tea->ctrl_handler; + v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops, V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); + retval = tea->ctrl_handler.error; + if (retval) { +- printk(KERN_ERR "tea575x-tuner: can't initialize controls\n"); ++ v4l2_err(tea->v4l2_dev, "can't initialize controls\n"); + v4l2_ctrl_handler_free(&tea->ctrl_handler); + return retval; + } +@@ -338,9 +352,9 @@ int snd_tea575x_init(struct snd_tea575x + + v4l2_ctrl_handler_setup(&tea->ctrl_handler); + +- retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, radio_nr); ++ retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->radio_nr); + if (retval) { +- printk(KERN_ERR "tea575x-tuner: can't register video device!\n"); ++ v4l2_err(tea->v4l2_dev, "can't register video device!\n"); + v4l2_ctrl_handler_free(&tea->ctrl_handler); + return retval; + } +Index: linux-3.3.x86_64/sound/pci/es1968.c +=================================================================== +--- linux-3.3.x86_64.orig/sound/pci/es1968.c ++++ linux-3.3.x86_64/sound/pci/es1968.c +@@ -142,6 +142,7 @@ static int enable_mpu[SNDRV_CARDS] = {[0 + #ifdef SUPPORT_JOYSTICK + static bool joystick[SNDRV_CARDS]; + #endif ++static int radio_nr[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; + + module_param_array(index, int, NULL, 0444); + MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); +@@ -165,6 +166,9 @@ MODULE_PARM_DESC(enable_mpu, "Enable MPU + module_param_array(joystick, bool, NULL, 0444); + MODULE_PARM_DESC(joystick, "Enable joystick."); + #endif ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); ++ + + + #define NR_APUS 64 +@@ -558,6 +562,7 @@ struct es1968 { + struct work_struct hwvol_work; + + #ifdef CONFIG_SND_ES1968_RADIO ++ struct v4l2_device v4l2_dev; + struct snd_tea575x tea; + #endif + }; +@@ -2613,6 +2618,7 @@ static int snd_es1968_free(struct es1968 + + #ifdef CONFIG_SND_ES1968_RADIO + snd_tea575x_exit(&chip->tea); ++ v4l2_device_unregister(&chip->v4l2_dev); + #endif + + if (chip->irq >= 0) +@@ -2655,6 +2661,7 @@ static int __devinit snd_es1968_create(s + int capt_streams, + int chip_type, + int do_pm, ++ int radio_nr, + struct es1968 **chip_ret) + { + static struct snd_device_ops ops = { +@@ -2751,7 +2758,14 @@ static int __devinit snd_es1968_create(s + snd_card_set_dev(card, &pci->dev); + + #ifdef CONFIG_SND_ES1968_RADIO ++ err = v4l2_device_register(&pci->dev, &chip->v4l2_dev); ++ if (err < 0) { ++ snd_es1968_free(chip); ++ return err; ++ } ++ chip->tea.v4l2_dev = &chip->v4l2_dev; + chip->tea.private_data = chip; ++ chip->tea.radio_nr = radio_nr; + chip->tea.ops = &snd_es1968_tea_ops; + strlcpy(chip->tea.card, "SF64-PCE2", sizeof(chip->tea.card)); + sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); +@@ -2797,6 +2811,7 @@ static int __devinit snd_es1968_probe(st + pcm_substreams_c[dev], + pci_id->driver_data, + use_pm[dev], ++ radio_nr[dev], + &chip)) < 0) { + snd_card_free(card); + return err; +Index: linux-3.3.x86_64/sound/pci/fm801.c +=================================================================== +--- linux-3.3.x86_64.orig/sound/pci/fm801.c ++++ linux-3.3.x86_64/sound/pci/fm801.c +@@ -58,6 +58,7 @@ static bool enable[SNDRV_CARDS] = SNDRV_ + * High 16-bits are video (radio) device number + 1 + */ + static int tea575x_tuner[SNDRV_CARDS]; ++static int radio_nr[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; + + module_param_array(index, int, NULL, 0444); + MODULE_PARM_DESC(index, "Index value for the FM801 soundcard."); +@@ -67,6 +68,9 @@ module_param_array(enable, bool, NULL, 0 + MODULE_PARM_DESC(enable, "Enable FM801 soundcard."); + module_param_array(tea575x_tuner, int, NULL, 0444); + MODULE_PARM_DESC(tea575x_tuner, "TEA575x tuner access method (0 = auto, 1 = SF256-PCS, 2=SF256-PCP, 3=SF64-PCR, 8=disable, +16=tuner-only)."); ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); ++ + + #define TUNER_DISABLED (1<<3) + #define TUNER_ONLY (1<<4) +@@ -197,6 +201,7 @@ struct fm801 { + struct snd_info_entry *proc_entry; + + #ifdef CONFIG_SND_FM801_TEA575X_BOOL ++ struct v4l2_device v4l2_dev; + struct snd_tea575x tea; + #endif + +@@ -1154,8 +1159,10 @@ static int snd_fm801_free(struct fm801 * + + __end_hw: + #ifdef CONFIG_SND_FM801_TEA575X_BOOL +- if (!(chip->tea575x_tuner & TUNER_DISABLED)) ++ if (!(chip->tea575x_tuner & TUNER_DISABLED)) { + snd_tea575x_exit(&chip->tea); ++ v4l2_device_unregister(&chip->v4l2_dev); ++ } + #endif + if (chip->irq >= 0) + free_irq(chip->irq, chip); +@@ -1175,6 +1182,7 @@ static int snd_fm801_dev_free(struct snd + static int __devinit snd_fm801_create(struct snd_card *card, + struct pci_dev * pci, + int tea575x_tuner, ++ int radio_nr, + struct fm801 ** rchip) + { + struct fm801 *chip; +@@ -1234,6 +1242,13 @@ static int __devinit snd_fm801_create(st + snd_card_set_dev(card, &pci->dev); + + #ifdef CONFIG_SND_FM801_TEA575X_BOOL ++ err = v4l2_device_register(&pci->dev, &chip->v4l2_dev); ++ if (err < 0) { ++ snd_fm801_free(chip); ++ return err; ++ } ++ chip->tea.v4l2_dev = &chip->v4l2_dev; ++ chip->tea.radio_nr = radio_nr; + chip->tea.private_data = chip; + chip->tea.ops = &snd_fm801_tea_ops; + sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); +@@ -1241,6 +1256,7 @@ static int __devinit snd_fm801_create(st + (tea575x_tuner & TUNER_TYPE_MASK) < 4) { + if (snd_tea575x_init(&chip->tea)) { + snd_printk(KERN_ERR "TEA575x radio not found\n"); ++ snd_fm801_free(chip); + return -ENODEV; + } + } else if ((tea575x_tuner & TUNER_TYPE_MASK) == 0) { +@@ -1287,7 +1303,7 @@ static int __devinit snd_card_fm801_prob + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; +- if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], &chip)) < 0) { ++ if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], radio_nr[dev], &chip)) < 0) { + snd_card_free(card); + return err; + } +Index: linux-3.3.x86_64/drivers/media/radio/radio-maxiradio.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-maxiradio.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-maxiradio.c +@@ -42,67 +42,37 @@ + #include + #include + #include ++#include + #include + #include +- +-#define DRIVER_VERSION "0.7.8" +- ++#include ++#include ++#include + + MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net"); +-MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio."); ++MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION(DRIVER_VERSION); ++MODULE_VERSION("1.0.0"); + + static int radio_nr = -1; +-module_param(radio_nr, int, 0); +- +-static int debug; +- +-module_param(debug, int, 0644); +-MODULE_PARM_DESC(debug, "activates debug info"); +- +-#define dprintk(dev, num, fmt, arg...) \ +- v4l2_dbg(num, debug, &dev->v4l2_dev, fmt, ## arg) +- +-#ifndef PCI_VENDOR_ID_GUILLEMOT +-#define PCI_VENDOR_ID_GUILLEMOT 0x5046 +-#endif +- +-#ifndef PCI_DEVICE_ID_GUILLEMOT +-#define PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO 0x1001 +-#endif +- ++module_param(radio_nr, int, 0644); ++MODULE_PARM_DESC(radio_nr, "Radio device number"); + + /* TEA5757 pin mappings */ + static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16; + +-#define FREQ_LO (87 * 16000) +-#define FREQ_HI (108 * 16000) +- +-#define FREQ_IF 171200 /* 10.7*16000 */ +-#define FREQ_STEP 200 /* 12.5*16 */ +- +-/* (x==fmhz*16*1000) -> bits */ +-#define FREQ2BITS(x) \ +- ((((unsigned int)(x) + FREQ_IF + (FREQ_STEP << 1)) / (FREQ_STEP << 2)) << 2) +- +-#define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF) ++static atomic_t maxiradio_instance = ATOMIC_INIT(0); + ++#define PCI_VENDOR_ID_GUILLEMOT 0x5046 ++#define PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO 0x1001 + + struct maxiradio + { ++ struct snd_tea575x tea; + struct v4l2_device v4l2_dev; +- struct video_device vdev; + struct pci_dev *pdev; + + u16 io; /* base of radio io */ +- u16 muted; /* VIDEO_AUDIO_MUTE */ +- u16 stereo; /* VIDEO_TUNER_STEREO_ON */ +- u16 tuned; /* signal strength (0 or 0xffff) */ +- +- unsigned long freq; +- +- struct mutex lock; + }; + + static inline struct maxiradio *to_maxiradio(struct v4l2_device *v4l2_dev) +@@ -110,259 +80,41 @@ static inline struct maxiradio *to_maxir + return container_of(v4l2_dev, struct maxiradio, v4l2_dev); + } + +-static void outbit(unsigned long bit, u16 io) +-{ +- int val = power | wren | (bit ? data : 0); +- +- outb(val, io); +- udelay(4); +- outb(val | clk, io); +- udelay(4); +- outb(val, io); +- udelay(4); +-} +- +-static void turn_power(struct maxiradio *dev, int p) +-{ +- if (p != 0) { +- dprintk(dev, 1, "Radio powered on\n"); +- outb(power, dev->io); +- } else { +- dprintk(dev, 1, "Radio powered off\n"); +- outb(0, dev->io); +- } +-} +- +-static void set_freq(struct maxiradio *dev, u32 freq) +-{ +- unsigned long int si; +- int bl; +- int io = dev->io; +- int val = FREQ2BITS(freq); +- +- /* TEA5757 shift register bits (see pdf) */ +- +- outbit(0, io); /* 24 search */ +- outbit(1, io); /* 23 search up/down */ +- +- outbit(0, io); /* 22 stereo/mono */ +- +- outbit(0, io); /* 21 band */ +- outbit(0, io); /* 20 band (only 00=FM works I think) */ +- +- outbit(0, io); /* 19 port ? */ +- outbit(0, io); /* 18 port ? */ +- +- outbit(0, io); /* 17 search level */ +- outbit(0, io); /* 16 search level */ +- +- si = 0x8000; +- for (bl = 1; bl <= 16; bl++) { +- outbit(val & si, io); +- si >>= 1; +- } +- +- dprintk(dev, 1, "Radio freq set to %d.%02d MHz\n", +- freq / 16000, +- freq % 16000 * 100 / 16000); +- +- turn_power(dev, 1); +-} +- +-static int get_stereo(u16 io) +-{ +- outb(power,io); +- udelay(4); +- +- return !(inb(io) & mo_st); +-} +- +-static int get_tune(u16 io) +-{ +- outb(power+clk,io); +- udelay(4); +- +- return !(inb(io) & mo_st); +-} +- +- +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- struct maxiradio *dev = video_drvdata(file); +- +- strlcpy(v->driver, "radio-maxiradio", sizeof(v->driver)); +- strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof(v->card)); +- snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(dev->pdev)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; +- return 0; +-} +- +-static int vidioc_g_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) ++static void maxiradio_tea575x_set_pins(struct snd_tea575x *tea, u8 pins) + { +- struct maxiradio *dev = video_drvdata(file); ++ struct maxiradio *dev = tea->private_data; ++ u8 bits = 0; + +- if (v->index > 0) +- return -EINVAL; ++ bits |= (pins & TEA575X_DATA) ? data : 0; ++ bits |= (pins & TEA575X_CLK) ? clk : 0; ++ bits |= (pins & TEA575X_WREN) ? wren : 0; ++ bits |= power; + +- mutex_lock(&dev->lock); +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- v->rangelow = FREQ_LO; +- v->rangehigh = FREQ_HI; +- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; +- v->capability = V4L2_TUNER_CAP_LOW; +- if (get_stereo(dev->io)) +- v->audmode = V4L2_TUNER_MODE_STEREO; +- else +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->signal = 0xffff * get_tune(dev->io); +- mutex_unlock(&dev->lock); +- +- return 0; +-} +- +-static int vidioc_s_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- return v->index ? -EINVAL : 0; +-} +- +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; +- return 0; +-} +- +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +-{ +- return i ? -EINVAL : 0; +-} +- +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; +-} +- +- +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- return a->index ? -EINVAL : 0; +-} +- +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct maxiradio *dev = video_drvdata(file); +- +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) { +- dprintk(dev, 1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", +- f->frequency / 16000, +- f->frequency % 16000 * 100 / 16000, +- FREQ_LO / 16000, FREQ_HI / 16000); +- +- return -EINVAL; +- } +- +- mutex_lock(&dev->lock); +- dev->freq = f->frequency; +- set_freq(dev, dev->freq); +- msleep(125); +- mutex_unlock(&dev->lock); +- +- return 0; +-} +- +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct maxiradio *dev = video_drvdata(file); +- +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = dev->freq; +- +- dprintk(dev, 4, "radio freq is %d.%02d MHz", +- f->frequency / 16000, +- f->frequency % 16000 * 100 / 16000); +- +- return 0; +-} +- +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- switch (qc->id) { +- case V4L2_CID_AUDIO_MUTE: +- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); +- } +- return -EINVAL; ++ outb(bits, dev->io); + } + +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) ++/* Note: this card cannot read out the data of the shift registers, ++ only the mono/stereo pin works. */ ++static u8 maxiradio_tea575x_get_pins(struct snd_tea575x *tea) + { +- struct maxiradio *dev = video_drvdata(file); ++ struct maxiradio *dev = tea->private_data; ++ u8 bits = inb(dev->io); + +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- ctrl->value = dev->muted; +- return 0; +- } +- +- return -EINVAL; ++ return ((bits & data) ? TEA575X_DATA : 0) | ++ ((bits & mo_st) ? TEA575X_MOST : 0); + } + +-static int vidioc_s_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) ++static void maxiradio_tea575x_set_direction(struct snd_tea575x *tea, bool output) + { +- struct maxiradio *dev = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- mutex_lock(&dev->lock); +- dev->muted = ctrl->value; +- if (dev->muted) +- turn_power(dev, 0); +- else +- set_freq(dev, dev->freq); +- mutex_unlock(&dev->lock); +- return 0; +- } +- +- return -EINVAL; + } + +-static const struct v4l2_file_operations maxiradio_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, +-}; +- +-static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = { +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl, ++static struct snd_tea575x_ops maxiradio_tea_ops = { ++ .set_pins = maxiradio_tea575x_set_pins, ++ .get_pins = maxiradio_tea575x_get_pins, ++ .set_direction = maxiradio_tea575x_set_direction, + }; + +-static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ++static int __devinit maxiradio_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + { + struct maxiradio *dev; + struct v4l2_device *v4l2_dev; +@@ -375,63 +127,60 @@ static int __devinit maxiradio_init_one( + } + + v4l2_dev = &dev->v4l2_dev; +- mutex_init(&dev->lock); +- dev->pdev = pdev; +- dev->muted = 1; +- dev->freq = FREQ_LO; +- +- strlcpy(v4l2_dev->name, "maxiradio", sizeof(v4l2_dev->name)); ++ v4l2_device_set_name(v4l2_dev, "maxiradio", &maxiradio_instance); + + retval = v4l2_device_register(&pdev->dev, v4l2_dev); + if (retval < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + goto errfr; + } ++ dev->tea.private_data = dev; ++ dev->tea.ops = &maxiradio_tea_ops; ++ /* The data pin cannot be read. This may be a hardware limitation, or ++ we just don't know how to read it. */ ++ dev->tea.cannot_read_data = true; ++ dev->tea.v4l2_dev = v4l2_dev; ++ dev->tea.radio_nr = radio_nr; ++ strlcpy(dev->tea.card, "Maxi Radio FM2000", sizeof(dev->tea.card)); ++ snprintf(dev->tea.bus_info, sizeof(dev->tea.bus_info), ++ "PCI:%s", pci_name(pdev)); ++ ++ retval = -ENODEV; + + if (!request_region(pci_resource_start(pdev, 0), +- pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) { +- v4l2_err(v4l2_dev, "can't reserve I/O ports\n"); +- goto err_out; ++ pci_resource_len(pdev, 0), v4l2_dev->name)) { ++ dev_err(&pdev->dev, "can't reserve I/O ports\n"); ++ goto err_hdl; + } + + if (pci_enable_device(pdev)) + goto err_out_free_region; + + dev->io = pci_resource_start(pdev, 0); +- strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); +- dev->vdev.v4l2_dev = v4l2_dev; +- dev->vdev.fops = &maxiradio_fops; +- dev->vdev.ioctl_ops = &maxiradio_ioctl_ops; +- dev->vdev.release = video_device_release_empty; +- video_set_drvdata(&dev->vdev, dev); +- +- if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_err(v4l2_dev, "can't register device!"); ++ if (snd_tea575x_init(&dev->tea)) { ++ printk(KERN_ERR "radio-maxiradio: Unable to detect TEA575x tuner\n"); + goto err_out_free_region; + } +- +- v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n"); +- +- v4l2_info(v4l2_dev, "found Guillemot MAXI Radio device (io = 0x%x)\n", +- dev->io); + return 0; + + err_out_free_region: + release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); +-err_out: ++err_hdl: + v4l2_device_unregister(v4l2_dev); + errfr: + kfree(dev); +- return -ENODEV; ++ return retval; + } + +-static void __devexit maxiradio_remove_one(struct pci_dev *pdev) ++static void __devexit maxiradio_remove(struct pci_dev *pdev) + { + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct maxiradio *dev = to_maxiradio(v4l2_dev); + +- video_unregister_device(&dev->vdev); +- v4l2_device_unregister(&dev->v4l2_dev); ++ snd_tea575x_exit(&dev->tea); ++ /* Turn off power */ ++ outb(0, dev->io); ++ v4l2_device_unregister(v4l2_dev); + release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + } + +@@ -446,19 +195,19 @@ MODULE_DEVICE_TABLE(pci, maxiradio_pci_t + static struct pci_driver maxiradio_driver = { + .name = "radio-maxiradio", + .id_table = maxiradio_pci_tbl, +- .probe = maxiradio_init_one, +- .remove = __devexit_p(maxiradio_remove_one), ++ .probe = maxiradio_probe, ++ .remove = __devexit_p(maxiradio_remove), + }; + +-static int __init maxiradio_radio_init(void) ++static int __init maxiradio_init(void) + { + return pci_register_driver(&maxiradio_driver); + } + +-static void __exit maxiradio_radio_exit(void) ++static void __exit maxiradio_exit(void) + { + pci_unregister_driver(&maxiradio_driver); + } + +-module_init(maxiradio_radio_init); +-module_exit(maxiradio_radio_exit); ++module_init(maxiradio_init); ++module_exit(maxiradio_exit); +Index: linux-3.3.x86_64/include/media/v4l2-dev.h +=================================================================== +--- linux-3.3.x86_64.orig/include/media/v4l2-dev.h ++++ linux-3.3.x86_64/include/media/v4l2-dev.h +@@ -62,6 +62,9 @@ struct v4l2_file_operations { + unsigned int (*poll) (struct file *, struct poll_table_struct *); + long (*ioctl) (struct file *, unsigned int, unsigned long); + long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); ++#ifdef CONFIG_COMPAT ++ long (*compat_ioctl32) (struct file *, unsigned int, unsigned long); ++#endif + unsigned long (*get_unmapped_area) (struct file *, unsigned long, + unsigned long, unsigned long, unsigned long); + int (*mmap) (struct file *, struct vm_area_struct *); +Index: linux-3.3.x86_64/drivers/media/video/uvc/uvc_v4l2.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/uvc/uvc_v4l2.c ++++ linux-3.3.x86_64/drivers/media/video/uvc/uvc_v4l2.c +@@ -11,6 +11,7 @@ + * + */ + ++#include + #include + #include + #include +@@ -1012,7 +1013,7 @@ static long uvc_v4l2_do_ioctl(struct fil + + default: + uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd); +- return -EINVAL; ++ return -ENOTTY; + } + + return ret; +@@ -1030,6 +1031,207 @@ static long uvc_v4l2_ioctl(struct file * + return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl); + } + ++#ifdef CONFIG_COMPAT ++struct uvc_xu_control_mapping32 { ++ __u32 id; ++ __u8 name[32]; ++ __u8 entity[16]; ++ __u8 selector; ++ ++ __u8 size; ++ __u8 offset; ++ __u32 v4l2_type; ++ __u32 data_type; ++ ++ compat_caddr_t menu_info; ++ __u32 menu_count; ++ ++ __u32 reserved[4]; ++}; ++ ++static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp, ++ const struct uvc_xu_control_mapping32 __user *up) ++{ ++ struct uvc_menu_info __user *umenus; ++ struct uvc_menu_info __user *kmenus; ++ compat_caddr_t p; ++ ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ __copy_from_user(kp, up, offsetof(typeof(*up), menu_info)) || ++ __get_user(kp->menu_count, &up->menu_count)) ++ return -EFAULT; ++ ++ memset(kp->reserved, 0, sizeof(kp->reserved)); ++ ++ if (kp->menu_count == 0) { ++ kp->menu_info = NULL; ++ return 0; ++ } ++ ++ if (__get_user(p, &up->menu_info)) ++ return -EFAULT; ++ umenus = compat_ptr(p); ++ if (!access_ok(VERIFY_READ, umenus, kp->menu_count * sizeof(*umenus))) ++ return -EFAULT; ++ ++ kmenus = compat_alloc_user_space(kp->menu_count * sizeof(*kmenus)); ++ if (kmenus == NULL) ++ return -EFAULT; ++ kp->menu_info = kmenus; ++ ++ if (copy_in_user(kmenus, umenus, kp->menu_count * sizeof(*umenus))) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp, ++ struct uvc_xu_control_mapping32 __user *up) ++{ ++ struct uvc_menu_info __user *umenus; ++ struct uvc_menu_info __user *kmenus = kp->menu_info; ++ compat_caddr_t p; ++ ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ __copy_to_user(up, kp, offsetof(typeof(*up), menu_info)) || ++ __put_user(kp->menu_count, &up->menu_count)) ++ return -EFAULT; ++ ++ __clear_user(up->reserved, sizeof(up->reserved)); ++ ++ if (kp->menu_count == 0) ++ return 0; ++ ++ if (get_user(p, &up->menu_info)) ++ return -EFAULT; ++ umenus = compat_ptr(p); ++ if (!access_ok(VERIFY_WRITE, umenus, kp->menu_count * sizeof(*umenus))) ++ return -EFAULT; ++ ++ if (copy_in_user(umenus, kmenus, kp->menu_count * sizeof(*umenus))) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++struct uvc_xu_control_query32 { ++ __u8 unit; ++ __u8 selector; ++ __u8 query; ++ __u16 size; ++ compat_caddr_t data; ++}; ++ ++static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp, ++ const struct uvc_xu_control_query32 __user *up) ++{ ++ u8 __user *udata; ++ u8 __user *kdata; ++ compat_caddr_t p; ++ ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ __copy_from_user(kp, up, offsetof(typeof(*up), data))) ++ return -EFAULT; ++ ++ if (kp->size == 0) { ++ kp->data = NULL; ++ return 0; ++ } ++ ++ if (__get_user(p, &up->data)) ++ return -EFAULT; ++ udata = compat_ptr(p); ++ if (!access_ok(VERIFY_READ, udata, kp->size)) ++ return -EFAULT; ++ ++ kdata = compat_alloc_user_space(kp->size); ++ if (kdata == NULL) ++ return -EFAULT; ++ kp->data = kdata; ++ ++ if (copy_in_user(kdata, udata, kp->size)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp, ++ struct uvc_xu_control_query32 __user *up) ++{ ++ u8 __user *udata; ++ u8 __user *kdata = kp->data; ++ compat_caddr_t p; ++ ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ __copy_to_user(up, kp, offsetof(typeof(*up), data))) ++ return -EFAULT; ++ ++ if (kp->size == 0) ++ return 0; ++ ++ if (get_user(p, &up->data)) ++ return -EFAULT; ++ udata = compat_ptr(p); ++ if (!access_ok(VERIFY_READ, udata, kp->size)) ++ return -EFAULT; ++ ++ if (copy_in_user(udata, kdata, kp->size)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++#define UVCIOC_CTRL_MAP32 _IOWR('u', 0x20, struct uvc_xu_control_mapping32) ++#define UVCIOC_CTRL_QUERY32 _IOWR('u', 0x21, struct uvc_xu_control_query32) ++ ++static long uvc_v4l2_compat_ioctl32(struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ union { ++ struct uvc_xu_control_mapping xmap; ++ struct uvc_xu_control_query xqry; ++ } karg; ++ void __user *up = compat_ptr(arg); ++ mm_segment_t old_fs; ++ long ret; ++ ++ switch (cmd) { ++ case UVCIOC_CTRL_MAP32: ++ cmd = UVCIOC_CTRL_MAP; ++ ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up); ++ break; ++ ++ case UVCIOC_CTRL_QUERY32: ++ cmd = UVCIOC_CTRL_QUERY; ++ ret = uvc_v4l2_get_xu_query(&karg.xqry, up); ++ break; ++ ++ default: ++ return -ENOIOCTLCMD; ++ } ++ ++ old_fs = get_fs(); ++ set_fs(KERNEL_DS); ++ ret = uvc_v4l2_ioctl(file, cmd, (unsigned long)&karg); ++ set_fs(old_fs); ++ ++ if (ret < 0) ++ return ret; ++ ++ switch (cmd) { ++ case UVCIOC_CTRL_MAP: ++ ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up); ++ break; ++ ++ case UVCIOC_CTRL_QUERY: ++ ret = uvc_v4l2_put_xu_query(&karg.xqry, up); ++ break; ++ } ++ ++ return ret; ++} ++#endif ++ + static ssize_t uvc_v4l2_read(struct file *file, char __user *data, + size_t count, loff_t *ppos) + { +@@ -1076,6 +1278,9 @@ const struct v4l2_file_operations uvc_fo + .open = uvc_v4l2_open, + .release = uvc_v4l2_release, + .unlocked_ioctl = uvc_v4l2_ioctl, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl32 = uvc_v4l2_compat_ioctl32, ++#endif + .read = uvc_v4l2_read, + .mmap = uvc_v4l2_mmap, + .poll = uvc_v4l2_poll, +Index: linux-3.3.x86_64/drivers/media/video/uvc/uvc_queue.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/uvc/uvc_queue.c ++++ linux-3.3.x86_64/drivers/media/video/uvc/uvc_queue.c +@@ -126,7 +126,7 @@ void uvc_queue_init(struct uvc_video_que + int drop_corrupted) + { + queue->queue.type = type; +- queue->queue.io_modes = VB2_MMAP; ++ queue->queue.io_modes = VB2_MMAP | VB2_USERPTR; + queue->queue.drv_priv = queue; + queue->queue.buf_struct_size = sizeof(struct uvc_buffer); + queue->queue.ops = &uvc_queue_qops; +Index: linux-3.3.x86_64/drivers/media/video/uvc/uvc_driver.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/uvc/uvc_driver.c ++++ linux-3.3.x86_64/drivers/media/video/uvc/uvc_driver.c +@@ -23,6 +23,7 @@ + * codec can't handle MJPEG data. + */ + ++#include + #include + #include + #include +@@ -32,7 +33,6 @@ + #include + #include + #include +-#include + #include + + #include +@@ -2139,6 +2139,15 @@ static struct usb_device_id uvc_ids[] = + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_MINMAX }, ++ /* Dell XPS m1530 */ ++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE ++ | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x05a9, ++ .idProduct = 0x2640, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = 1, ++ .bInterfaceProtocol = 0, ++ .driver_info = UVC_QUIRK_PROBE_DEF }, + /* Apple Built-In iSight */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/stv0288.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/stv0288.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/stv0288.c +@@ -506,7 +506,7 @@ static int stv0288_set_frontend(struct d + tda[1] = (unsigned char)tm; + stv0288_writeregI(state, 0x2b, tda[1]); + stv0288_writeregI(state, 0x2c, tda[2]); +- udelay(30); ++ msleep(30); + } + state->tuner_frequency = c->frequency; + state->fec_inner = FEC_AUTO; +Index: linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-cards.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx231xx/cx231xx-cards.c ++++ linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-cards.c +@@ -861,7 +861,6 @@ void cx231xx_release_resources(struct cx + kfree(dev->sliced_cc_mode.alt_max_pkt_size); + kfree(dev->ts1_mode.alt_max_pkt_size); + kfree(dev); +- dev = NULL; + } + + /* +Index: linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-video.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx231xx/cx231xx-video.c ++++ linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-video.c +@@ -2319,8 +2319,7 @@ static int cx231xx_v4l2_close(struct fil + if (dev->state & DEV_DISCONNECTED) { + if (atomic_read(&dev->devlist_count) > 0) { + cx231xx_release_resources(dev); +- kfree(dev); +- dev = NULL; ++ fh->dev = NULL; + return 0; + } + return 0; +@@ -2350,8 +2349,7 @@ static int cx231xx_v4l2_close(struct fil + free the remaining resources */ + if (dev->state & DEV_DISCONNECTED) { + cx231xx_release_resources(dev); +- kfree(dev); +- dev = NULL; ++ fh->dev = NULL; + return 0; + } + +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/dib9000.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/dib9000.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/dib9000.c +@@ -33,7 +33,7 @@ struct i2c_device { + + /* lock */ + #define DIB_LOCK struct mutex +-#define DibAcquireLock(lock) do { if (mutex_lock_interruptible(lock) < 0) dprintk("could not get the lock"); } while (0) ++#define DibAcquireLock(lock) mutex_lock_interruptible(lock) + #define DibReleaseLock(lock) mutex_unlock(lock) + #define DibInitLock(lock) mutex_init(lock) + #define DibFreeLock(lock) +@@ -446,7 +446,10 @@ static int dib9000_risc_mem_read(struct + if (!state->platform.risc.fw_is_running) + return -EIO; + +- DibAcquireLock(&state->platform.risc.mem_lock); ++ if (DibAcquireLock(&state->platform.risc.mem_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + dib9000_risc_mem_setup(state, cmd | 0x80); + dib9000_risc_mem_read_chunks(state, b, len); + DibReleaseLock(&state->platform.risc.mem_lock); +@@ -459,7 +462,10 @@ static int dib9000_risc_mem_write(struct + if (!state->platform.risc.fw_is_running) + return -EIO; + +- DibAcquireLock(&state->platform.risc.mem_lock); ++ if (DibAcquireLock(&state->platform.risc.mem_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + dib9000_risc_mem_setup(state, cmd); + dib9000_risc_mem_write_chunks(state, b, m->size); + DibReleaseLock(&state->platform.risc.mem_lock); +@@ -531,7 +537,10 @@ static int dib9000_mbx_send_attr(struct + if (!state->platform.risc.fw_is_running) + return -EINVAL; + +- DibAcquireLock(&state->platform.risc.mbx_if_lock); ++ if (DibAcquireLock(&state->platform.risc.mbx_if_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + tmp = MAX_MAILBOX_TRY; + do { + size = dib9000_read_word_attr(state, 1043, attr) & 0xff; +@@ -593,7 +602,10 @@ static u8 dib9000_mbx_read(struct dib900 + if (!state->platform.risc.fw_is_running) + return 0; + +- DibAcquireLock(&state->platform.risc.mbx_if_lock); ++ if (DibAcquireLock(&state->platform.risc.mbx_if_lock) < 0) { ++ dprintk("could not get the lock"); ++ return 0; ++ } + if (risc_id == 1) + mc_base = 16; + else +@@ -701,7 +713,10 @@ static int dib9000_mbx_process(struct di + if (!state->platform.risc.fw_is_running) + return -1; + +- DibAcquireLock(&state->platform.risc.mbx_lock); ++ if (DibAcquireLock(&state->platform.risc.mbx_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -1; ++ } + + if (dib9000_mbx_count(state, 1, attr)) /* 1=RiscB */ + ret = dib9000_mbx_fetch_to_cache(state, attr); +@@ -1178,7 +1193,10 @@ static int dib9000_fw_get_channel(struct + struct dibDVBTChannel *ch; + int ret = 0; + +- DibAcquireLock(&state->platform.risc.mem_mbx_lock); ++ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { + ret = -EIO; + goto error; +@@ -1660,7 +1678,10 @@ static int dib9000_fw_component_bus_xfer + p[12] = 0; + } + +- DibAcquireLock(&state->platform.risc.mem_mbx_lock); ++ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { ++ dprintk("could not get the lock"); ++ return 0; ++ } + + dib9000_risc_mem_write(state, FE_MM_W_COMPONENT_ACCESS, p); + +@@ -1768,7 +1789,10 @@ int dib9000_fw_pid_filter_ctrl(struct dv + return 0; + } + +- DibAcquireLock(&state->demod_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + + val = dib9000_read_word(state, 294 + 1) & 0xffef; + val |= (onoff & 0x1) << 4; +@@ -1800,7 +1824,10 @@ int dib9000_fw_pid_filter(struct dvb_fro + return 0; + } + +- DibAcquireLock(&state->demod_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff); + ret = dib9000_write_word(state, 300 + 1 + id, + onoff ? (1 << 13) | pid : 0); +@@ -1848,7 +1875,10 @@ static int dib9000_sleep(struct dvb_fron + u8 index_frontend; + int ret = 0; + +- DibAcquireLock(&state->demod_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { + ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]); + if (ret < 0) +@@ -1874,8 +1904,12 @@ static int dib9000_get_frontend(struct d + fe_status_t stat; + int ret = 0; + +- if (state->get_frontend_internal == 0) +- DibAcquireLock(&state->demod_lock); ++ if (state->get_frontend_internal == 0) { ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } ++ } + + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { + state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat); +@@ -1978,7 +2012,10 @@ static int dib9000_set_frontend(struct d + } + + state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */ +- DibAcquireLock(&state->demod_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return 0; ++ } + + fe->dtv_property_cache.delivery_system = SYS_DVBT; + +@@ -2138,7 +2175,10 @@ static int dib9000_read_status(struct dv + u8 index_frontend; + u16 lock = 0, lock_slave = 0; + +- DibAcquireLock(&state->demod_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) + lock_slave |= dib9000_read_lock(state->fe[index_frontend]); + +@@ -2168,8 +2208,15 @@ static int dib9000_read_ber(struct dvb_f + u16 *c; + int ret = 0; + +- DibAcquireLock(&state->demod_lock); +- DibAcquireLock(&state->platform.risc.mem_mbx_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } ++ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { ++ dprintk("could not get the lock"); ++ ret = -EINTR; ++ goto error; ++ } + if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { + DibReleaseLock(&state->platform.risc.mem_mbx_lock); + ret = -EIO; +@@ -2196,7 +2243,10 @@ static int dib9000_read_signal_strength( + u16 val; + int ret = 0; + +- DibAcquireLock(&state->demod_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + *strength = 0; + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { + state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val); +@@ -2206,8 +2256,13 @@ static int dib9000_read_signal_strength( + *strength += val; + } + +- DibAcquireLock(&state->platform.risc.mem_mbx_lock); ++ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { ++ dprintk("could not get the lock"); ++ ret = -EINTR; ++ goto error; ++ } + if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { ++ DibReleaseLock(&state->platform.risc.mem_mbx_lock); + ret = -EIO; + goto error; + } +@@ -2232,9 +2287,14 @@ static u32 dib9000_get_snr(struct dvb_fr + u32 n, s, exp; + u16 val; + +- DibAcquireLock(&state->platform.risc.mem_mbx_lock); +- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) +- return -EIO; ++ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { ++ dprintk("could not get the lock"); ++ return 0; ++ } ++ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { ++ DibReleaseLock(&state->platform.risc.mem_mbx_lock); ++ return 0; ++ } + dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); + DibReleaseLock(&state->platform.risc.mem_mbx_lock); + +@@ -2266,7 +2326,10 @@ static int dib9000_read_snr(struct dvb_f + u8 index_frontend; + u32 snr_master; + +- DibAcquireLock(&state->demod_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + snr_master = dib9000_get_snr(fe); + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) + snr_master += dib9000_get_snr(state->fe[index_frontend]); +@@ -2288,9 +2351,17 @@ static int dib9000_read_unc_blocks(struc + u16 *c = (u16 *)state->i2c_read_buffer; + int ret = 0; + +- DibAcquireLock(&state->demod_lock); +- DibAcquireLock(&state->platform.risc.mem_mbx_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } ++ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { ++ dprintk("could not get the lock"); ++ ret = -EINTR; ++ goto error; ++ } + if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { ++ DibReleaseLock(&state->platform.risc.mem_mbx_lock); + ret = -EIO; + goto error; + } +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/drxd_hard.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/drxd_hard.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/drxd_hard.c +@@ -101,9 +101,9 @@ struct SCfgAgc { + + struct SNoiseCal { + int cpOpt; +- u16 cpNexpOfs; +- u16 tdCal2k; +- u16 tdCal8k; ++ short cpNexpOfs; ++ short tdCal2k; ++ short tdCal8k; + }; + + enum app_env { +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/m88rs2000.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/m88rs2000.c +@@ -0,0 +1,904 @@ ++/* ++ Driver for M88RS2000 demodulator and tuner ++ ++ Copyright (C) 2012 Malcolm Priestley (tvboxspy@gmail.com) ++ Beta Driver ++ ++ Include various calculation code from DS3000 driver. ++ Copyright (C) 2009 Konstantin Dimitrov. ++ ++ 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ ++*/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#include "dvb_frontend.h" ++#include "m88rs2000.h" ++ ++struct m88rs2000_state { ++ struct i2c_adapter *i2c; ++ const struct m88rs2000_config *config; ++ struct dvb_frontend frontend; ++ u8 no_lock_count; ++ u32 tuner_frequency; ++ u32 symbol_rate; ++ fe_code_rate_t fec_inner; ++ u8 tuner_level; ++ int errmode; ++}; ++ ++static int m88rs2000_debug; ++ ++module_param_named(debug, m88rs2000_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); ++ ++#define dprintk(level, args...) do { \ ++ if (level & m88rs2000_debug) \ ++ printk(KERN_DEBUG "m88rs2000-fe: " args); \ ++} while (0) ++ ++#define deb_info(args...) dprintk(0x01, args) ++#define info(format, arg...) \ ++ printk(KERN_INFO "m88rs2000-fe: " format "\n" , ## arg) ++ ++static int m88rs2000_writereg(struct m88rs2000_state *state, u8 tuner, ++ u8 reg, u8 data) ++{ ++ int ret; ++ u8 addr = (tuner == 0) ? state->config->tuner_addr : ++ state->config->demod_addr; ++ u8 buf[] = { reg, data }; ++ struct i2c_msg msg = { ++ .addr = addr, ++ .flags = 0, ++ .buf = buf, ++ .len = 2 ++ }; ++ ++ ret = i2c_transfer(state->i2c, &msg, 1); ++ ++ if (ret != 1) ++ deb_info("%s: writereg error (reg == 0x%02x, val == 0x%02x, " ++ "ret == %i)\n", __func__, reg, data, ret); ++ ++ return (ret != 1) ? -EREMOTEIO : 0; ++} ++ ++static int m88rs2000_demod_write(struct m88rs2000_state *state, u8 reg, u8 data) ++{ ++ return m88rs2000_writereg(state, 1, reg, data); ++} ++ ++static int m88rs2000_tuner_write(struct m88rs2000_state *state, u8 reg, u8 data) ++{ ++ m88rs2000_demod_write(state, 0x81, 0x84); ++ udelay(10); ++ return m88rs2000_writereg(state, 0, reg, data); ++ ++} ++ ++static int m88rs2000_write(struct dvb_frontend *fe, const u8 buf[], int len) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ ++ if (len != 2) ++ return -EINVAL; ++ ++ return m88rs2000_writereg(state, 1, buf[0], buf[1]); ++} ++ ++static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 tuner, u8 reg) ++{ ++ int ret; ++ u8 b0[] = { reg }; ++ u8 b1[] = { 0 }; ++ u8 addr = (tuner == 0) ? state->config->tuner_addr : ++ state->config->demod_addr; ++ struct i2c_msg msg[] = { ++ { ++ .addr = addr, ++ .flags = 0, ++ .buf = b0, ++ .len = 1 ++ }, { ++ .addr = addr, ++ .flags = I2C_M_RD, ++ .buf = b1, ++ .len = 1 ++ } ++ }; ++ ++ ret = i2c_transfer(state->i2c, msg, 2); ++ ++ if (ret != 2) ++ deb_info("%s: readreg error (reg == 0x%02x, ret == %i)\n", ++ __func__, reg, ret); ++ ++ return b1[0]; ++} ++ ++static u8 m88rs2000_demod_read(struct m88rs2000_state *state, u8 reg) ++{ ++ return m88rs2000_readreg(state, 1, reg); ++} ++ ++static u8 m88rs2000_tuner_read(struct m88rs2000_state *state, u8 reg) ++{ ++ m88rs2000_demod_write(state, 0x81, 0x85); ++ udelay(10); ++ return m88rs2000_readreg(state, 0, reg); ++} ++ ++static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ int ret; ++ u32 temp; ++ u8 b[3]; ++ ++ if ((srate < 1000000) || (srate > 45000000)) ++ return -EINVAL; ++ ++ temp = srate / 1000; ++ temp *= 11831; ++ temp /= 68; ++ temp -= 3; ++ ++ b[0] = (u8) (temp >> 16) & 0xff; ++ b[1] = (u8) (temp >> 8) & 0xff; ++ b[2] = (u8) temp & 0xff; ++ ret = m88rs2000_demod_write(state, 0x93, b[2]); ++ ret |= m88rs2000_demod_write(state, 0x94, b[1]); ++ ret |= m88rs2000_demod_write(state, 0x95, b[0]); ++ ++ deb_info("m88rs2000: m88rs2000_set_symbolrate\n"); ++ return ret; ++} ++ ++static int m88rs2000_send_diseqc_msg(struct dvb_frontend *fe, ++ struct dvb_diseqc_master_cmd *m) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ ++ int i; ++ u8 reg; ++ deb_info("%s\n", __func__); ++ m88rs2000_demod_write(state, 0x9a, 0x30); ++ reg = m88rs2000_demod_read(state, 0xb2); ++ reg &= 0x3f; ++ m88rs2000_demod_write(state, 0xb2, reg); ++ for (i = 0; i < m->msg_len; i++) ++ m88rs2000_demod_write(state, 0xb3 + i, m->msg[i]); ++ ++ reg = m88rs2000_demod_read(state, 0xb1); ++ reg &= 0x87; ++ reg |= ((m->msg_len - 1) << 3) | 0x07; ++ reg &= 0x7f; ++ m88rs2000_demod_write(state, 0xb1, reg); ++ ++ for (i = 0; i < 15; i++) { ++ if ((m88rs2000_demod_read(state, 0xb1) & 0x40) == 0x0) ++ break; ++ msleep(20); ++ } ++ ++ reg = m88rs2000_demod_read(state, 0xb1); ++ if ((reg & 0x40) > 0x0) { ++ reg &= 0x7f; ++ reg |= 0x40; ++ m88rs2000_demod_write(state, 0xb1, reg); ++ } ++ ++ reg = m88rs2000_demod_read(state, 0xb2); ++ reg &= 0x3f; ++ reg |= 0x80; ++ m88rs2000_demod_write(state, 0xb2, reg); ++ m88rs2000_demod_write(state, 0x9a, 0xb0); ++ ++ ++ return 0; ++} ++ ++static int m88rs2000_send_diseqc_burst(struct dvb_frontend *fe, ++ fe_sec_mini_cmd_t burst) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ u8 reg0, reg1; ++ deb_info("%s\n", __func__); ++ m88rs2000_demod_write(state, 0x9a, 0x30); ++ msleep(50); ++ reg0 = m88rs2000_demod_read(state, 0xb1); ++ reg1 = m88rs2000_demod_read(state, 0xb2); ++ /* TODO complete this section */ ++ m88rs2000_demod_write(state, 0xb2, reg1); ++ m88rs2000_demod_write(state, 0xb1, reg0); ++ m88rs2000_demod_write(state, 0x9a, 0xb0); ++ ++ return 0; ++} ++ ++static int m88rs2000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ u8 reg0, reg1; ++ m88rs2000_demod_write(state, 0x9a, 0x30); ++ reg0 = m88rs2000_demod_read(state, 0xb1); ++ reg1 = m88rs2000_demod_read(state, 0xb2); ++ ++ reg1 &= 0x3f; ++ ++ switch (tone) { ++ case SEC_TONE_ON: ++ reg0 |= 0x4; ++ reg0 &= 0xbc; ++ break; ++ case SEC_TONE_OFF: ++ reg1 |= 0x80; ++ break; ++ default: ++ break; ++ } ++ m88rs2000_demod_write(state, 0xb2, reg1); ++ m88rs2000_demod_write(state, 0xb1, reg0); ++ m88rs2000_demod_write(state, 0x9a, 0xb0); ++ return 0; ++} ++ ++struct inittab { ++ u8 cmd; ++ u8 reg; ++ u8 val; ++}; ++ ++struct inittab m88rs2000_setup[] = { ++ {DEMOD_WRITE, 0x9a, 0x30}, ++ {DEMOD_WRITE, 0x00, 0x01}, ++ {WRITE_DELAY, 0x19, 0x00}, ++ {DEMOD_WRITE, 0x00, 0x00}, ++ {DEMOD_WRITE, 0x9a, 0xb0}, ++ {DEMOD_WRITE, 0x81, 0xc1}, ++ {TUNER_WRITE, 0x42, 0x73}, ++ {TUNER_WRITE, 0x05, 0x07}, ++ {TUNER_WRITE, 0x20, 0x27}, ++ {TUNER_WRITE, 0x07, 0x02}, ++ {TUNER_WRITE, 0x11, 0xff}, ++ {TUNER_WRITE, 0x60, 0xf9}, ++ {TUNER_WRITE, 0x08, 0x01}, ++ {TUNER_WRITE, 0x00, 0x41}, ++ {DEMOD_WRITE, 0x81, 0x81}, ++ {DEMOD_WRITE, 0x86, 0xc6}, ++ {DEMOD_WRITE, 0x9a, 0x30}, ++ {DEMOD_WRITE, 0xf0, 0x22}, ++ {DEMOD_WRITE, 0xf1, 0xbf}, ++ {DEMOD_WRITE, 0xb0, 0x45}, ++ {DEMOD_WRITE, 0xb2, 0x01}, /* set voltage pin always set 1*/ ++ {DEMOD_WRITE, 0x9a, 0xb0}, ++ {0xff, 0xaa, 0xff} ++}; ++ ++struct inittab m88rs2000_shutdown[] = { ++ {DEMOD_WRITE, 0x9a, 0x30}, ++ {DEMOD_WRITE, 0xb0, 0x00}, ++ {DEMOD_WRITE, 0xf1, 0x89}, ++ {DEMOD_WRITE, 0x00, 0x01}, ++ {DEMOD_WRITE, 0x9a, 0xb0}, ++ {TUNER_WRITE, 0x00, 0x40}, ++ {DEMOD_WRITE, 0x81, 0x81}, ++ {0xff, 0xaa, 0xff} ++}; ++ ++struct inittab tuner_reset[] = { ++ {TUNER_WRITE, 0x42, 0x73}, ++ {TUNER_WRITE, 0x05, 0x07}, ++ {TUNER_WRITE, 0x20, 0x27}, ++ {TUNER_WRITE, 0x07, 0x02}, ++ {TUNER_WRITE, 0x11, 0xff}, ++ {TUNER_WRITE, 0x60, 0xf9}, ++ {TUNER_WRITE, 0x08, 0x01}, ++ {TUNER_WRITE, 0x00, 0x41}, ++ {0xff, 0xaa, 0xff} ++}; ++ ++struct inittab fe_reset[] = { ++ {DEMOD_WRITE, 0x00, 0x01}, ++ {DEMOD_WRITE, 0xf1, 0xbf}, ++ {DEMOD_WRITE, 0x00, 0x01}, ++ {DEMOD_WRITE, 0x20, 0x81}, ++ {DEMOD_WRITE, 0x21, 0x80}, ++ {DEMOD_WRITE, 0x10, 0x33}, ++ {DEMOD_WRITE, 0x11, 0x44}, ++ {DEMOD_WRITE, 0x12, 0x07}, ++ {DEMOD_WRITE, 0x18, 0x20}, ++ {DEMOD_WRITE, 0x28, 0x04}, ++ {DEMOD_WRITE, 0x29, 0x8e}, ++ {DEMOD_WRITE, 0x3b, 0xff}, ++ {DEMOD_WRITE, 0x32, 0x10}, ++ {DEMOD_WRITE, 0x33, 0x02}, ++ {DEMOD_WRITE, 0x34, 0x30}, ++ {DEMOD_WRITE, 0x35, 0xff}, ++ {DEMOD_WRITE, 0x38, 0x50}, ++ {DEMOD_WRITE, 0x39, 0x68}, ++ {DEMOD_WRITE, 0x3c, 0x7f}, ++ {DEMOD_WRITE, 0x3d, 0x0f}, ++ {DEMOD_WRITE, 0x45, 0x20}, ++ {DEMOD_WRITE, 0x46, 0x24}, ++ {DEMOD_WRITE, 0x47, 0x7c}, ++ {DEMOD_WRITE, 0x48, 0x16}, ++ {DEMOD_WRITE, 0x49, 0x04}, ++ {DEMOD_WRITE, 0x4a, 0x01}, ++ {DEMOD_WRITE, 0x4b, 0x78}, ++ {DEMOD_WRITE, 0X4d, 0xd2}, ++ {DEMOD_WRITE, 0x4e, 0x6d}, ++ {DEMOD_WRITE, 0x50, 0x30}, ++ {DEMOD_WRITE, 0x51, 0x30}, ++ {DEMOD_WRITE, 0x54, 0x7b}, ++ {DEMOD_WRITE, 0x56, 0x09}, ++ {DEMOD_WRITE, 0x58, 0x59}, ++ {DEMOD_WRITE, 0x59, 0x37}, ++ {DEMOD_WRITE, 0x63, 0xfa}, ++ {0xff, 0xaa, 0xff} ++}; ++ ++struct inittab fe_trigger[] = { ++ {DEMOD_WRITE, 0x97, 0x04}, ++ {DEMOD_WRITE, 0x99, 0x77}, ++ {DEMOD_WRITE, 0x9b, 0x64}, ++ {DEMOD_WRITE, 0x9e, 0x00}, ++ {DEMOD_WRITE, 0x9f, 0xf8}, ++ {DEMOD_WRITE, 0xa0, 0x20}, ++ {DEMOD_WRITE, 0xa1, 0xe0}, ++ {DEMOD_WRITE, 0xa3, 0x38}, ++ {DEMOD_WRITE, 0x98, 0xff}, ++ {DEMOD_WRITE, 0xc0, 0x0f}, ++ {DEMOD_WRITE, 0x89, 0x01}, ++ {DEMOD_WRITE, 0x00, 0x00}, ++ {WRITE_DELAY, 0x0a, 0x00}, ++ {DEMOD_WRITE, 0x00, 0x01}, ++ {DEMOD_WRITE, 0x00, 0x00}, ++ {DEMOD_WRITE, 0x9a, 0xb0}, ++ {0xff, 0xaa, 0xff} ++}; ++ ++static int m88rs2000_tab_set(struct m88rs2000_state *state, ++ struct inittab *tab) ++{ ++ int ret = 0; ++ u8 i; ++ if (tab == NULL) ++ return -EINVAL; ++ ++ for (i = 0; i < 255; i++) { ++ switch (tab[i].cmd) { ++ case 0x01: ++ ret = m88rs2000_demod_write(state, tab[i].reg, ++ tab[i].val); ++ break; ++ case 0x02: ++ ret = m88rs2000_tuner_write(state, tab[i].reg, ++ tab[i].val); ++ break; ++ case 0x10: ++ if (tab[i].reg > 0) ++ mdelay(tab[i].reg); ++ break; ++ case 0xff: ++ if (tab[i].reg == 0xaa && tab[i].val == 0xff) ++ return 0; ++ case 0x00: ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (ret < 0) ++ return -ENODEV; ++ } ++ return 0; ++} ++ ++static int m88rs2000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt) ++{ ++ deb_info("%s: %s\n", __func__, ++ volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" : ++ volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??"); ++ ++ return 0; ++} ++ ++static int m88rs2000_startup(struct m88rs2000_state *state) ++{ ++ int ret = 0; ++ u8 reg; ++ ++ reg = m88rs2000_tuner_read(state, 0x00); ++ if ((reg & 0x40) == 0) ++ ret = -ENODEV; ++ ++ return ret; ++} ++ ++static int m88rs2000_init(struct dvb_frontend *fe) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ int ret; ++ ++ deb_info("m88rs2000: init chip\n"); ++ /* Setup frontend from shutdown/cold */ ++ ret = m88rs2000_tab_set(state, m88rs2000_setup); ++ ++ return ret; ++} ++ ++static int m88rs2000_sleep(struct dvb_frontend *fe) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ int ret; ++ /* Shutdown the frondend */ ++ ret = m88rs2000_tab_set(state, m88rs2000_shutdown); ++ return ret; ++} ++ ++static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ u8 reg = m88rs2000_demod_read(state, 0x8c); ++ ++ *status = 0; ++ ++ if ((reg & 0x7) == 0x7) { ++ *status = FE_HAS_CARRIER | FE_HAS_SIGNAL | FE_HAS_VITERBI ++ | FE_HAS_LOCK; ++ if (state->config->set_ts_params) ++ state->config->set_ts_params(fe, CALL_IS_READ); ++ } ++ return 0; ++} ++ ++/* Extact code for these unknown but lmedm04 driver uses interupt callbacks */ ++ ++static int m88rs2000_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ deb_info("m88rs2000_read_ber %d\n", *ber); ++ *ber = 0; ++ return 0; ++} ++ ++static int m88rs2000_read_signal_strength(struct dvb_frontend *fe, ++ u16 *strength) ++{ ++ *strength = 0; ++ return 0; ++} ++ ++static int m88rs2000_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ deb_info("m88rs2000_read_snr %d\n", *snr); ++ *snr = 0; ++ return 0; ++} ++ ++static int m88rs2000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ deb_info("m88rs2000_read_ber %d\n", *ucblocks); ++ *ucblocks = 0; ++ return 0; ++} ++ ++static int m88rs2000_tuner_gate_ctrl(struct m88rs2000_state *state, u8 offset) ++{ ++ int ret; ++ ret = m88rs2000_tuner_write(state, 0x51, 0x1f - offset); ++ ret |= m88rs2000_tuner_write(state, 0x51, 0x1f); ++ ret |= m88rs2000_tuner_write(state, 0x50, offset); ++ ret |= m88rs2000_tuner_write(state, 0x50, 0x00); ++ msleep(20); ++ return ret; ++} ++ ++static int m88rs2000_set_tuner_rf(struct dvb_frontend *fe) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ int reg; ++ reg = m88rs2000_tuner_read(state, 0x3d); ++ reg &= 0x7f; ++ if (reg < 0x16) ++ reg = 0xa1; ++ else if (reg == 0x16) ++ reg = 0x99; ++ else ++ reg = 0xf9; ++ ++ m88rs2000_tuner_write(state, 0x60, reg); ++ reg = m88rs2000_tuner_gate_ctrl(state, 0x08); ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ return reg; ++} ++ ++static int m88rs2000_set_tuner(struct dvb_frontend *fe, u16 *offset) ++{ ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ int ret; ++ u32 frequency = c->frequency; ++ s32 offset_khz; ++ s32 tmp; ++ u32 symbol_rate = (c->symbol_rate / 1000); ++ u32 f3db, gdiv28; ++ u16 value, ndiv, lpf_coeff; ++ u8 lpf_mxdiv, mlpf_max, mlpf_min, nlpf; ++ u8 lo = 0x01, div4 = 0x0; ++ ++ /* Reset Tuner */ ++ ret = m88rs2000_tab_set(state, tuner_reset); ++ ++ /* Calculate frequency divider */ ++ if (frequency < 1060000) { ++ lo |= 0x10; ++ div4 = 0x1; ++ ndiv = (frequency * 14 * 4) / FE_CRYSTAL_KHZ; ++ } else ++ ndiv = (frequency * 14 * 2) / FE_CRYSTAL_KHZ; ++ ndiv = ndiv + ndiv % 2; ++ ndiv = ndiv - 1024; ++ ++ ret = m88rs2000_tuner_write(state, 0x10, 0x80 | lo); ++ ++ /* Set frequency divider */ ++ ret |= m88rs2000_tuner_write(state, 0x01, (ndiv >> 8) & 0xf); ++ ret |= m88rs2000_tuner_write(state, 0x02, ndiv & 0xff); ++ ++ ret |= m88rs2000_tuner_write(state, 0x03, 0x06); ++ ret |= m88rs2000_tuner_gate_ctrl(state, 0x10); ++ if (ret < 0) ++ return -ENODEV; ++ ++ /* Tuner Frequency Range */ ++ ret = m88rs2000_tuner_write(state, 0x10, lo); ++ ++ ret |= m88rs2000_tuner_gate_ctrl(state, 0x08); ++ ++ /* Tuner RF */ ++ ret |= m88rs2000_set_tuner_rf(fe); ++ ++ gdiv28 = (FE_CRYSTAL_KHZ / 1000 * 1694 + 500) / 1000; ++ ret |= m88rs2000_tuner_write(state, 0x04, gdiv28 & 0xff); ++ ret |= m88rs2000_tuner_gate_ctrl(state, 0x04); ++ if (ret < 0) ++ return -ENODEV; ++ ++ value = m88rs2000_tuner_read(state, 0x26); ++ ++ f3db = (symbol_rate * 135) / 200 + 2000; ++ f3db += FREQ_OFFSET_LOW_SYM_RATE; ++ if (f3db < 7000) ++ f3db = 7000; ++ if (f3db > 40000) ++ f3db = 40000; ++ ++ gdiv28 = gdiv28 * 207 / (value * 2 + 151); ++ mlpf_max = gdiv28 * 135 / 100; ++ mlpf_min = gdiv28 * 78 / 100; ++ if (mlpf_max > 63) ++ mlpf_max = 63; ++ ++ lpf_coeff = 2766; ++ ++ nlpf = (f3db * gdiv28 * 2 / lpf_coeff / ++ (FE_CRYSTAL_KHZ / 1000) + 1) / 2; ++ if (nlpf > 23) ++ nlpf = 23; ++ if (nlpf < 1) ++ nlpf = 1; ++ ++ lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000) ++ * lpf_coeff * 2 / f3db + 1) / 2; ++ ++ if (lpf_mxdiv < mlpf_min) { ++ nlpf++; ++ lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000) ++ * lpf_coeff * 2 / f3db + 1) / 2; ++ } ++ ++ if (lpf_mxdiv > mlpf_max) ++ lpf_mxdiv = mlpf_max; ++ ++ ret = m88rs2000_tuner_write(state, 0x04, lpf_mxdiv); ++ ret |= m88rs2000_tuner_write(state, 0x06, nlpf); ++ ++ ret |= m88rs2000_tuner_gate_ctrl(state, 0x04); ++ ++ ret |= m88rs2000_tuner_gate_ctrl(state, 0x01); ++ ++ msleep(80); ++ /* calculate offset assuming 96000kHz*/ ++ offset_khz = (ndiv - ndiv % 2 + 1024) * FE_CRYSTAL_KHZ ++ / 14 / (div4 + 1) / 2; ++ ++ offset_khz -= frequency; ++ ++ tmp = offset_khz; ++ tmp *= 65536; ++ ++ tmp = (2 * tmp + 96000) / (2 * 96000); ++ if (tmp < 0) ++ tmp += 65536; ++ ++ *offset = tmp & 0xffff; ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ ++ return (ret < 0) ? -EINVAL : 0; ++} ++ ++static int m88rs2000_set_fec(struct m88rs2000_state *state, ++ fe_code_rate_t fec) ++{ ++ int ret; ++ u16 fec_set; ++ switch (fec) { ++ /* This is not confirmed kept for reference */ ++/* case FEC_1_2: ++ fec_set = 0x88; ++ break; ++ case FEC_2_3: ++ fec_set = 0x68; ++ break; ++ case FEC_3_4: ++ fec_set = 0x48; ++ break; ++ case FEC_5_6: ++ fec_set = 0x28; ++ break; ++ case FEC_7_8: ++ fec_set = 0x18; ++ break; */ ++ case FEC_AUTO: ++ default: ++ fec_set = 0x08; ++ } ++ ret = m88rs2000_demod_write(state, 0x76, fec_set); ++ ++ return 0; ++} ++ ++ ++static fe_code_rate_t m88rs2000_get_fec(struct m88rs2000_state *state) ++{ ++ u8 reg; ++ m88rs2000_demod_write(state, 0x9a, 0x30); ++ reg = m88rs2000_demod_read(state, 0x76); ++ m88rs2000_demod_write(state, 0x9a, 0xb0); ++ ++ switch (reg) { ++ case 0x88: ++ return FEC_1_2; ++ case 0x68: ++ return FEC_2_3; ++ case 0x48: ++ return FEC_3_4; ++ case 0x28: ++ return FEC_5_6; ++ case 0x18: ++ return FEC_7_8; ++ case 0x08: ++ default: ++ break; ++ } ++ ++ return FEC_AUTO; ++} ++ ++static int m88rs2000_set_frontend(struct dvb_frontend *fe) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ fe_status_t status; ++ int i, ret; ++ u16 offset = 0; ++ u8 reg; ++ ++ state->no_lock_count = 0; ++ ++ if (c->delivery_system != SYS_DVBS) { ++ deb_info("%s: unsupported delivery " ++ "system selected (%d)\n", ++ __func__, c->delivery_system); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Set Tuner */ ++ ret = m88rs2000_set_tuner(fe, &offset); ++ if (ret < 0) ++ return -ENODEV; ++ ++ ret = m88rs2000_demod_write(state, 0x9a, 0x30); ++ /* Unknown usually 0xc6 sometimes 0xc1 */ ++ reg = m88rs2000_demod_read(state, 0x86); ++ ret |= m88rs2000_demod_write(state, 0x86, reg); ++ /* Offset lower nibble always 0 */ ++ ret |= m88rs2000_demod_write(state, 0x9c, (offset >> 8)); ++ ret |= m88rs2000_demod_write(state, 0x9d, offset & 0xf0); ++ ++ ++ /* Reset Demod */ ++ ret = m88rs2000_tab_set(state, fe_reset); ++ if (ret < 0) ++ return -ENODEV; ++ ++ /* Unknown */ ++ reg = m88rs2000_demod_read(state, 0x70); ++ ret = m88rs2000_demod_write(state, 0x70, reg); ++ ++ /* Set FEC */ ++ ret |= m88rs2000_set_fec(state, c->fec_inner); ++ ret |= m88rs2000_demod_write(state, 0x85, 0x1); ++ ret |= m88rs2000_demod_write(state, 0x8a, 0xbf); ++ ret |= m88rs2000_demod_write(state, 0x8d, 0x1e); ++ ret |= m88rs2000_demod_write(state, 0x90, 0xf1); ++ ret |= m88rs2000_demod_write(state, 0x91, 0x08); ++ ++ if (ret < 0) ++ return -ENODEV; ++ ++ /* Set Symbol Rate */ ++ ret = m88rs2000_set_symbolrate(fe, c->symbol_rate); ++ if (ret < 0) ++ return -ENODEV; ++ ++ /* Set up Demod */ ++ ret = m88rs2000_tab_set(state, fe_trigger); ++ if (ret < 0) ++ return -ENODEV; ++ ++ for (i = 0; i < 25; i++) { ++ u8 reg = m88rs2000_demod_read(state, 0x8c); ++ if ((reg & 0x7) == 0x7) { ++ status = FE_HAS_LOCK; ++ break; ++ } ++ state->no_lock_count++; ++ if (state->no_lock_count > 15) { ++ reg = m88rs2000_demod_read(state, 0x70); ++ reg ^= 0x4; ++ m88rs2000_demod_write(state, 0x70, reg); ++ state->no_lock_count = 0; ++ } ++ if (state->no_lock_count == 20) ++ m88rs2000_set_tuner_rf(fe); ++ msleep(20); ++ } ++ ++ if (status & FE_HAS_LOCK) { ++ state->fec_inner = m88rs2000_get_fec(state); ++ /* Uknown suspect SNR level */ ++ reg = m88rs2000_demod_read(state, 0x65); ++ } ++ ++ state->tuner_frequency = c->frequency; ++ state->symbol_rate = c->symbol_rate; ++ return 0; ++} ++ ++static int m88rs2000_get_frontend(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ c->fec_inner = state->fec_inner; ++ c->frequency = state->tuner_frequency; ++ c->symbol_rate = state->symbol_rate; ++ return 0; ++} ++ ++static int m88rs2000_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ ++ if (enable) ++ m88rs2000_demod_write(state, 0x81, 0x84); ++ else ++ m88rs2000_demod_write(state, 0x81, 0x81); ++ udelay(10); ++ return 0; ++} ++ ++static void m88rs2000_release(struct dvb_frontend *fe) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ kfree(state); ++} ++ ++static struct dvb_frontend_ops m88rs2000_ops = { ++ .delsys = { SYS_DVBS }, ++ .info = { ++ .name = "M88RS2000 DVB-S", ++ .frequency_min = 950000, ++ .frequency_max = 2150000, ++ .frequency_stepsize = 1000, /* kHz for QPSK frontends */ ++ .frequency_tolerance = 5000, ++ .symbol_rate_min = 1000000, ++ .symbol_rate_max = 45000000, ++ .symbol_rate_tolerance = 500, /* ppm */ ++ .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | ++ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | ++ FE_CAN_QPSK | ++ FE_CAN_FEC_AUTO ++ }, ++ ++ .release = m88rs2000_release, ++ .init = m88rs2000_init, ++ .sleep = m88rs2000_sleep, ++ .write = m88rs2000_write, ++ .i2c_gate_ctrl = m88rs2000_i2c_gate_ctrl, ++ .read_status = m88rs2000_read_status, ++ .read_ber = m88rs2000_read_ber, ++ .read_signal_strength = m88rs2000_read_signal_strength, ++ .read_snr = m88rs2000_read_snr, ++ .read_ucblocks = m88rs2000_read_ucblocks, ++ .diseqc_send_master_cmd = m88rs2000_send_diseqc_msg, ++ .diseqc_send_burst = m88rs2000_send_diseqc_burst, ++ .set_tone = m88rs2000_set_tone, ++ .set_voltage = m88rs2000_set_voltage, ++ ++ .set_frontend = m88rs2000_set_frontend, ++ .get_frontend = m88rs2000_get_frontend, ++}; ++ ++struct dvb_frontend *m88rs2000_attach(const struct m88rs2000_config *config, ++ struct i2c_adapter *i2c) ++{ ++ struct m88rs2000_state *state = NULL; ++ ++ /* allocate memory for the internal state */ ++ state = kzalloc(sizeof(struct m88rs2000_state), GFP_KERNEL); ++ if (state == NULL) ++ goto error; ++ ++ /* setup the state */ ++ state->config = config; ++ state->i2c = i2c; ++ state->tuner_frequency = 0; ++ state->symbol_rate = 0; ++ state->fec_inner = 0; ++ ++ if (m88rs2000_startup(state) < 0) ++ goto error; ++ ++ /* create dvb_frontend */ ++ memcpy(&state->frontend.ops, &m88rs2000_ops, ++ sizeof(struct dvb_frontend_ops)); ++ state->frontend.demodulator_priv = state; ++ return &state->frontend; ++ ++error: ++ kfree(state); ++ ++ return NULL; ++} ++EXPORT_SYMBOL(m88rs2000_attach); ++ ++MODULE_DESCRIPTION("M88RS2000 DVB-S Demodulator driver"); ++MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION("1.13"); ++ +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/m88rs2000.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/m88rs2000.h +@@ -0,0 +1,66 @@ ++/* ++ Driver for M88RS2000 demodulator ++ ++ 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ ++*/ ++ ++#ifndef M88RS2000_H ++#define M88RS2000_H ++ ++#include ++#include "dvb_frontend.h" ++ ++struct m88rs2000_config { ++ /* Demodulator i2c address */ ++ u8 demod_addr; ++ /* Tuner address */ ++ u8 tuner_addr; ++ ++ u8 *inittab; ++ ++ /* minimum delay before retuning */ ++ int min_delay_ms; ++ ++ int (*set_ts_params)(struct dvb_frontend *, int); ++}; ++ ++enum { ++ CALL_IS_SET_FRONTEND = 0x0, ++ CALL_IS_READ, ++}; ++ ++#if defined(CONFIG_DVB_M88RS2000) || (defined(CONFIG_DVB_M88RS2000_MODULE) && \ ++ defined(MODULE)) ++extern struct dvb_frontend *m88rs2000_attach( ++ const struct m88rs2000_config *config, struct i2c_adapter *i2c); ++#else ++static inline struct dvb_frontend *m88rs2000_attach( ++ const struct m88rs2000_config *config, struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif /* CONFIG_DVB_M88RS2000 */ ++ ++#define FE_CRYSTAL_KHZ 27000 ++#define FREQ_OFFSET_LOW_SYM_RATE 3000 ++ ++enum { ++ DEMOD_WRITE = 0x1, ++ TUNER_WRITE, ++ WRITE_DELAY = 0x10, ++}; ++#endif /* M88RS2000_H */ +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/lmedm04.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/lmedm04.h ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/lmedm04.h +@@ -41,6 +41,7 @@ + #define LME_ST_ON_W {0x06, 0x00} + #define LME_CLEAR_PID {0x03, 0x02, 0x20, 0xa0} + #define LME_ZERO_PID {0x03, 0x06, 0x00, 0x00, 0x01, 0x00, 0x20, 0x9c} ++#define LME_ALL_PIDS {0x03, 0x06, 0x00, 0xff, 0x01, 0x1f, 0x20, 0x81} + + /* LNB Voltage + * 07 XX XX +Index: linux-3.3.x86_64/drivers/media/video/adv7183.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/adv7183.c +@@ -0,0 +1,699 @@ ++/* ++ * adv7183.c Analog Devices ADV7183 video decoder driver ++ * ++ * Copyright (c) 2011 Analog Devices Inc. ++ * ++ * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "adv7183_regs.h" ++ ++struct adv7183 { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ ++ v4l2_std_id std; /* Current set standard */ ++ u32 input; ++ u32 output; ++ unsigned reset_pin; ++ unsigned oe_pin; ++ struct v4l2_mbus_framefmt fmt; ++}; ++ ++/* EXAMPLES USING 27 MHz CLOCK ++ * Mode 1 CVBS Input (Composite Video on AIN5) ++ * All standards are supported through autodetect, 8-bit, 4:2:2, ITU-R BT.656 output on P15 to P8. ++ */ ++static const unsigned char adv7183_init_regs[] = { ++ ADV7183_IN_CTRL, 0x04, /* CVBS input on AIN5 */ ++ ADV7183_DIGI_CLAMP_CTRL_1, 0x00, /* Slow down digital clamps */ ++ ADV7183_SHAP_FILT_CTRL, 0x41, /* Set CSFM to SH1 */ ++ ADV7183_ADC_CTRL, 0x16, /* Power down ADC 1 and ADC 2 */ ++ ADV7183_CTI_DNR_CTRL_4, 0x04, /* Set DNR threshold to 4 for flat response */ ++ /* ADI recommended programming sequence */ ++ ADV7183_ADI_CTRL, 0x80, ++ ADV7183_CTI_DNR_CTRL_4, 0x20, ++ 0x52, 0x18, ++ 0x58, 0xED, ++ 0x77, 0xC5, ++ 0x7C, 0x93, ++ 0x7D, 0x00, ++ 0xD0, 0x48, ++ 0xD5, 0xA0, ++ 0xD7, 0xEA, ++ ADV7183_SD_SATURATION_CR, 0x3E, ++ ADV7183_PAL_V_END, 0x3E, ++ ADV7183_PAL_F_TOGGLE, 0x0F, ++ ADV7183_ADI_CTRL, 0x00, ++}; ++ ++static inline struct adv7183 *to_adv7183(struct v4l2_subdev *sd) ++{ ++ return container_of(sd, struct adv7183, sd); ++} ++static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) ++{ ++ return &container_of(ctrl->handler, struct adv7183, hdl)->sd; ++} ++ ++static inline int adv7183_read(struct v4l2_subdev *sd, unsigned char reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return i2c_smbus_read_byte_data(client, reg); ++} ++ ++static inline int adv7183_write(struct v4l2_subdev *sd, unsigned char reg, ++ unsigned char value) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return i2c_smbus_write_byte_data(client, reg, value); ++} ++ ++static int adv7183_writeregs(struct v4l2_subdev *sd, ++ const unsigned char *regs, unsigned int num) ++{ ++ unsigned char reg, data; ++ unsigned int cnt = 0; ++ ++ if (num & 0x1) { ++ v4l2_err(sd, "invalid regs array\n"); ++ return -1; ++ } ++ ++ while (cnt < num) { ++ reg = *regs++; ++ data = *regs++; ++ cnt += 2; ++ ++ adv7183_write(sd, reg, data); ++ } ++ return 0; ++} ++ ++static int adv7183_log_status(struct v4l2_subdev *sd) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ ++ v4l2_info(sd, "adv7183: Input control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_IN_CTRL)); ++ v4l2_info(sd, "adv7183: Video selection = 0x%02x\n", ++ adv7183_read(sd, ADV7183_VD_SEL)); ++ v4l2_info(sd, "adv7183: Output control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_OUT_CTRL)); ++ v4l2_info(sd, "adv7183: Extended output control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_EXT_OUT_CTRL)); ++ v4l2_info(sd, "adv7183: Autodetect enable = 0x%02x\n", ++ adv7183_read(sd, ADV7183_AUTO_DET_EN)); ++ v4l2_info(sd, "adv7183: Contrast = 0x%02x\n", ++ adv7183_read(sd, ADV7183_CONTRAST)); ++ v4l2_info(sd, "adv7183: Brightness = 0x%02x\n", ++ adv7183_read(sd, ADV7183_BRIGHTNESS)); ++ v4l2_info(sd, "adv7183: Hue = 0x%02x\n", ++ adv7183_read(sd, ADV7183_HUE)); ++ v4l2_info(sd, "adv7183: Default value Y = 0x%02x\n", ++ adv7183_read(sd, ADV7183_DEF_Y)); ++ v4l2_info(sd, "adv7183: Default value C = 0x%02x\n", ++ adv7183_read(sd, ADV7183_DEF_C)); ++ v4l2_info(sd, "adv7183: ADI control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_ADI_CTRL)); ++ v4l2_info(sd, "adv7183: Power Management = 0x%02x\n", ++ adv7183_read(sd, ADV7183_POW_MANAGE)); ++ v4l2_info(sd, "adv7183: Status 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n", ++ adv7183_read(sd, ADV7183_STATUS_1), ++ adv7183_read(sd, ADV7183_STATUS_2), ++ adv7183_read(sd, ADV7183_STATUS_3)); ++ v4l2_info(sd, "adv7183: Ident = 0x%02x\n", ++ adv7183_read(sd, ADV7183_IDENT)); ++ v4l2_info(sd, "adv7183: Analog clamp control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_ANAL_CLAMP_CTRL)); ++ v4l2_info(sd, "adv7183: Digital clamp control 1 = 0x%02x\n", ++ adv7183_read(sd, ADV7183_DIGI_CLAMP_CTRL_1)); ++ v4l2_info(sd, "adv7183: Shaping filter control 1 and 2 = 0x%02x 0x%02x\n", ++ adv7183_read(sd, ADV7183_SHAP_FILT_CTRL), ++ adv7183_read(sd, ADV7183_SHAP_FILT_CTRL_2)); ++ v4l2_info(sd, "adv7183: Comb filter control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_COMB_FILT_CTRL)); ++ v4l2_info(sd, "adv7183: ADI control 2 = 0x%02x\n", ++ adv7183_read(sd, ADV7183_ADI_CTRL_2)); ++ v4l2_info(sd, "adv7183: Pixel delay control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_PIX_DELAY_CTRL)); ++ v4l2_info(sd, "adv7183: Misc gain control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_MISC_GAIN_CTRL)); ++ v4l2_info(sd, "adv7183: AGC mode control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_AGC_MODE_CTRL)); ++ v4l2_info(sd, "adv7183: Chroma gain control 1 and 2 = 0x%02x 0x%02x\n", ++ adv7183_read(sd, ADV7183_CHRO_GAIN_CTRL_1), ++ adv7183_read(sd, ADV7183_CHRO_GAIN_CTRL_2)); ++ v4l2_info(sd, "adv7183: Luma gain control 1 and 2 = 0x%02x 0x%02x\n", ++ adv7183_read(sd, ADV7183_LUMA_GAIN_CTRL_1), ++ adv7183_read(sd, ADV7183_LUMA_GAIN_CTRL_2)); ++ v4l2_info(sd, "adv7183: Vsync field control 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n", ++ adv7183_read(sd, ADV7183_VS_FIELD_CTRL_1), ++ adv7183_read(sd, ADV7183_VS_FIELD_CTRL_2), ++ adv7183_read(sd, ADV7183_VS_FIELD_CTRL_3)); ++ v4l2_info(sd, "adv7183: Hsync positon control 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n", ++ adv7183_read(sd, ADV7183_HS_POS_CTRL_1), ++ adv7183_read(sd, ADV7183_HS_POS_CTRL_2), ++ adv7183_read(sd, ADV7183_HS_POS_CTRL_3)); ++ v4l2_info(sd, "adv7183: Polarity = 0x%02x\n", ++ adv7183_read(sd, ADV7183_POLARITY)); ++ v4l2_info(sd, "adv7183: ADC control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_ADC_CTRL)); ++ v4l2_info(sd, "adv7183: SD offset Cb and Cr = 0x%02x 0x%02x\n", ++ adv7183_read(sd, ADV7183_SD_OFFSET_CB), ++ adv7183_read(sd, ADV7183_SD_OFFSET_CR)); ++ v4l2_info(sd, "adv7183: SD saturation Cb and Cr = 0x%02x 0x%02x\n", ++ adv7183_read(sd, ADV7183_SD_SATURATION_CB), ++ adv7183_read(sd, ADV7183_SD_SATURATION_CR)); ++ v4l2_info(sd, "adv7183: Drive strength = 0x%02x\n", ++ adv7183_read(sd, ADV7183_DRIVE_STR)); ++ v4l2_ctrl_handler_log_status(&decoder->hdl, sd->name); ++ return 0; ++} ++ ++static int adv7183_g_std(struct v4l2_subdev *sd, v4l2_std_id *std) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ ++ *std = decoder->std; ++ return 0; ++} ++ ++static int adv7183_s_std(struct v4l2_subdev *sd, v4l2_std_id std) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ int reg; ++ ++ reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF; ++ if (std == V4L2_STD_PAL_60) ++ reg |= 0x60; ++ else if (std == V4L2_STD_NTSC_443) ++ reg |= 0x70; ++ else if (std == V4L2_STD_PAL_N) ++ reg |= 0x90; ++ else if (std == V4L2_STD_PAL_M) ++ reg |= 0xA0; ++ else if (std == V4L2_STD_PAL_Nc) ++ reg |= 0xC0; ++ else if (std & V4L2_STD_PAL) ++ reg |= 0x80; ++ else if (std & V4L2_STD_NTSC) ++ reg |= 0x50; ++ else if (std & V4L2_STD_SECAM) ++ reg |= 0xE0; ++ else ++ return -EINVAL; ++ adv7183_write(sd, ADV7183_IN_CTRL, reg); ++ ++ decoder->std = std; ++ ++ return 0; ++} ++ ++static int adv7183_reset(struct v4l2_subdev *sd, u32 val) ++{ ++ int reg; ++ ++ reg = adv7183_read(sd, ADV7183_POW_MANAGE) | 0x80; ++ adv7183_write(sd, ADV7183_POW_MANAGE, reg); ++ /* wait 5ms before any further i2c writes are performed */ ++ usleep_range(5000, 10000); ++ return 0; ++} ++ ++static int adv7183_s_routing(struct v4l2_subdev *sd, ++ u32 input, u32 output, u32 config) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ int reg; ++ ++ if ((input > ADV7183_COMPONENT1) || (output > ADV7183_16BIT_OUT)) ++ return -EINVAL; ++ ++ if (input != decoder->input) { ++ decoder->input = input; ++ reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF0; ++ switch (input) { ++ case ADV7183_COMPOSITE1: ++ reg |= 0x1; ++ break; ++ case ADV7183_COMPOSITE2: ++ reg |= 0x2; ++ break; ++ case ADV7183_COMPOSITE3: ++ reg |= 0x3; ++ break; ++ case ADV7183_COMPOSITE4: ++ reg |= 0x4; ++ break; ++ case ADV7183_COMPOSITE5: ++ reg |= 0x5; ++ break; ++ case ADV7183_COMPOSITE6: ++ reg |= 0xB; ++ break; ++ case ADV7183_COMPOSITE7: ++ reg |= 0xC; ++ break; ++ case ADV7183_COMPOSITE8: ++ reg |= 0xD; ++ break; ++ case ADV7183_COMPOSITE9: ++ reg |= 0xE; ++ break; ++ case ADV7183_COMPOSITE10: ++ reg |= 0xF; ++ break; ++ case ADV7183_SVIDEO0: ++ reg |= 0x6; ++ break; ++ case ADV7183_SVIDEO1: ++ reg |= 0x7; ++ break; ++ case ADV7183_SVIDEO2: ++ reg |= 0x8; ++ break; ++ case ADV7183_COMPONENT0: ++ reg |= 0x9; ++ break; ++ case ADV7183_COMPONENT1: ++ reg |= 0xA; ++ break; ++ default: ++ break; ++ } ++ adv7183_write(sd, ADV7183_IN_CTRL, reg); ++ } ++ ++ if (output != decoder->output) { ++ decoder->output = output; ++ reg = adv7183_read(sd, ADV7183_OUT_CTRL) & 0xC0; ++ switch (output) { ++ case ADV7183_16BIT_OUT: ++ reg |= 0x9; ++ break; ++ default: ++ reg |= 0xC; ++ break; ++ } ++ adv7183_write(sd, ADV7183_OUT_CTRL, reg); ++ } ++ ++ return 0; ++} ++ ++static int adv7183_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ int val = ctrl->val; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ if (val < 0) ++ val = 127 - val; ++ adv7183_write(sd, ADV7183_BRIGHTNESS, val); ++ break; ++ case V4L2_CID_CONTRAST: ++ adv7183_write(sd, ADV7183_CONTRAST, val); ++ break; ++ case V4L2_CID_SATURATION: ++ adv7183_write(sd, ADV7183_SD_SATURATION_CB, val >> 8); ++ adv7183_write(sd, ADV7183_SD_SATURATION_CR, (val & 0xFF)); ++ break; ++ case V4L2_CID_HUE: ++ adv7183_write(sd, ADV7183_SD_OFFSET_CB, val >> 8); ++ adv7183_write(sd, ADV7183_SD_OFFSET_CR, (val & 0xFF)); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int adv7183_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ int reg; ++ ++ /* enable autodetection block */ ++ reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF; ++ adv7183_write(sd, ADV7183_IN_CTRL, reg); ++ ++ /* wait autodetection switch */ ++ mdelay(10); ++ ++ /* get autodetection result */ ++ reg = adv7183_read(sd, ADV7183_STATUS_1); ++ switch ((reg >> 0x4) & 0x7) { ++ case 0: ++ *std = V4L2_STD_NTSC; ++ break; ++ case 1: ++ *std = V4L2_STD_NTSC_443; ++ break; ++ case 2: ++ *std = V4L2_STD_PAL_M; ++ break; ++ case 3: ++ *std = V4L2_STD_PAL_60; ++ break; ++ case 4: ++ *std = V4L2_STD_PAL; ++ break; ++ case 5: ++ *std = V4L2_STD_SECAM; ++ break; ++ case 6: ++ *std = V4L2_STD_PAL_Nc; ++ break; ++ case 7: ++ *std = V4L2_STD_SECAM; ++ break; ++ default: ++ *std = V4L2_STD_UNKNOWN; ++ break; ++ } ++ ++ /* after std detection, write back user set std */ ++ adv7183_s_std(sd, decoder->std); ++ return 0; ++} ++ ++static int adv7183_g_input_status(struct v4l2_subdev *sd, u32 *status) ++{ ++ int reg; ++ ++ *status = V4L2_IN_ST_NO_SIGNAL; ++ reg = adv7183_read(sd, ADV7183_STATUS_1); ++ if (reg < 0) ++ return reg; ++ if (reg & 0x1) ++ *status = 0; ++ return 0; ++} ++ ++static int adv7183_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, ++ enum v4l2_mbus_pixelcode *code) ++{ ++ if (index > 0) ++ return -EINVAL; ++ ++ *code = V4L2_MBUS_FMT_UYVY8_2X8; ++ return 0; ++} ++ ++static int adv7183_try_mbus_fmt(struct v4l2_subdev *sd, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ ++ fmt->code = V4L2_MBUS_FMT_UYVY8_2X8; ++ fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ if (decoder->std & V4L2_STD_525_60) { ++ fmt->field = V4L2_FIELD_SEQ_TB; ++ fmt->width = 720; ++ fmt->height = 480; ++ } else { ++ fmt->field = V4L2_FIELD_SEQ_BT; ++ fmt->width = 720; ++ fmt->height = 576; ++ } ++ return 0; ++} ++ ++static int adv7183_s_mbus_fmt(struct v4l2_subdev *sd, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ ++ adv7183_try_mbus_fmt(sd, fmt); ++ decoder->fmt = *fmt; ++ return 0; ++} ++ ++static int adv7183_g_mbus_fmt(struct v4l2_subdev *sd, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ ++ *fmt = decoder->fmt; ++ return 0; ++} ++ ++static int adv7183_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ ++ if (enable) ++ gpio_direction_output(decoder->oe_pin, 0); ++ else ++ gpio_direction_output(decoder->oe_pin, 1); ++ udelay(1); ++ return 0; ++} ++ ++static int adv7183_g_chip_ident(struct v4l2_subdev *sd, ++ struct v4l2_dbg_chip_ident *chip) ++{ ++ int rev; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ /* 0x11 for adv7183, 0x13 for adv7183b */ ++ rev = adv7183_read(sd, ADV7183_IDENT); ++ ++ return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7183, rev); ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int adv7183_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ if (!v4l2_chip_match_i2c_client(client, ®->match)) ++ return -EINVAL; ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ reg->val = adv7183_read(sd, reg->reg & 0xff); ++ reg->size = 1; ++ return 0; ++} ++ ++static int adv7183_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ if (!v4l2_chip_match_i2c_client(client, ®->match)) ++ return -EINVAL; ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ adv7183_write(sd, reg->reg & 0xff, reg->val & 0xff); ++ return 0; ++} ++#endif ++ ++static const struct v4l2_ctrl_ops adv7183_ctrl_ops = { ++ .s_ctrl = adv7183_s_ctrl, ++}; ++ ++static const struct v4l2_subdev_core_ops adv7183_core_ops = { ++ .log_status = adv7183_log_status, ++ .g_std = adv7183_g_std, ++ .s_std = adv7183_s_std, ++ .reset = adv7183_reset, ++ .g_chip_ident = adv7183_g_chip_ident, ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = adv7183_g_register, ++ .s_register = adv7183_s_register, ++#endif ++}; ++ ++static const struct v4l2_subdev_video_ops adv7183_video_ops = { ++ .s_routing = adv7183_s_routing, ++ .querystd = adv7183_querystd, ++ .g_input_status = adv7183_g_input_status, ++ .enum_mbus_fmt = adv7183_enum_mbus_fmt, ++ .try_mbus_fmt = adv7183_try_mbus_fmt, ++ .s_mbus_fmt = adv7183_s_mbus_fmt, ++ .g_mbus_fmt = adv7183_g_mbus_fmt, ++ .s_stream = adv7183_s_stream, ++}; ++ ++static const struct v4l2_subdev_ops adv7183_ops = { ++ .core = &adv7183_core_ops, ++ .video = &adv7183_video_ops, ++}; ++ ++static int adv7183_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct adv7183 *decoder; ++ struct v4l2_subdev *sd; ++ struct v4l2_ctrl_handler *hdl; ++ int ret; ++ struct v4l2_mbus_framefmt fmt; ++ const unsigned *pin_array; ++ ++ /* Check if the adapter supports the needed features */ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) ++ return -EIO; ++ ++ v4l_info(client, "chip found @ 0x%02x (%s)\n", ++ client->addr << 1, client->adapter->name); ++ ++ pin_array = client->dev.platform_data; ++ if (pin_array == NULL) ++ return -EINVAL; ++ ++ decoder = kzalloc(sizeof(struct adv7183), GFP_KERNEL); ++ if (decoder == NULL) ++ return -ENOMEM; ++ ++ decoder->reset_pin = pin_array[0]; ++ decoder->oe_pin = pin_array[1]; ++ ++ if (gpio_request(decoder->reset_pin, "ADV7183 Reset")) { ++ v4l_err(client, "failed to request GPIO %d\n", decoder->reset_pin); ++ ret = -EBUSY; ++ goto err_free_decoder; ++ } ++ ++ if (gpio_request(decoder->oe_pin, "ADV7183 Output Enable")) { ++ v4l_err(client, "failed to request GPIO %d\n", decoder->oe_pin); ++ ret = -EBUSY; ++ goto err_free_reset; ++ } ++ ++ sd = &decoder->sd; ++ v4l2_i2c_subdev_init(sd, client, &adv7183_ops); ++ ++ hdl = &decoder->hdl; ++ v4l2_ctrl_handler_init(hdl, 4); ++ v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); ++ v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x80); ++ v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 0xFFFF, 1, 0x8080); ++ v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops, ++ V4L2_CID_HUE, 0, 0xFFFF, 1, 0x8080); ++ /* hook the control handler into the driver */ ++ sd->ctrl_handler = hdl; ++ if (hdl->error) { ++ ret = hdl->error; ++ ++ v4l2_ctrl_handler_free(hdl); ++ goto err_free_oe; ++ } ++ ++ /* v4l2 doesn't support an autodetect standard, pick PAL as default */ ++ decoder->std = V4L2_STD_PAL; ++ decoder->input = ADV7183_COMPOSITE4; ++ decoder->output = ADV7183_8BIT_OUT; ++ ++ gpio_direction_output(decoder->oe_pin, 1); ++ /* reset chip */ ++ gpio_direction_output(decoder->reset_pin, 0); ++ /* reset pulse width at least 5ms */ ++ mdelay(10); ++ gpio_direction_output(decoder->reset_pin, 1); ++ /* wait 5ms before any further i2c writes are performed */ ++ mdelay(5); ++ ++ adv7183_writeregs(sd, adv7183_init_regs, ARRAY_SIZE(adv7183_init_regs)); ++ adv7183_s_std(sd, decoder->std); ++ fmt.width = 720; ++ fmt.height = 576; ++ adv7183_s_mbus_fmt(sd, &fmt); ++ ++ /* initialize the hardware to the default control values */ ++ ret = v4l2_ctrl_handler_setup(hdl); ++ if (ret) { ++ v4l2_ctrl_handler_free(hdl); ++ goto err_free_oe; ++ } ++ ++ return 0; ++err_free_oe: ++ gpio_free(decoder->oe_pin); ++err_free_reset: ++ gpio_free(decoder->reset_pin); ++err_free_decoder: ++ kfree(decoder); ++ return ret; ++} ++ ++static int adv7183_remove(struct i2c_client *client) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(client); ++ struct adv7183 *decoder = to_adv7183(sd); ++ ++ v4l2_device_unregister_subdev(sd); ++ v4l2_ctrl_handler_free(sd->ctrl_handler); ++ gpio_free(decoder->oe_pin); ++ gpio_free(decoder->reset_pin); ++ kfree(decoder); ++ return 0; ++} ++ ++static const struct i2c_device_id adv7183_id[] = { ++ {"adv7183", 0}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(i2c, adv7183_id); ++ ++static struct i2c_driver adv7183_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "adv7183", ++ }, ++ .probe = adv7183_probe, ++ .remove = __devexit_p(adv7183_remove), ++ .id_table = adv7183_id, ++}; ++ ++static __init int adv7183_init(void) ++{ ++ return i2c_add_driver(&adv7183_driver); ++} ++ ++static __exit void adv7183_exit(void) ++{ ++ i2c_del_driver(&adv7183_driver); ++} ++ ++module_init(adv7183_init); ++module_exit(adv7183_exit); ++ ++MODULE_DESCRIPTION("Analog Devices ADV7183 video decoder driver"); ++MODULE_AUTHOR("Scott Jiang "); ++MODULE_LICENSE("GPL v2"); +Index: linux-3.3.x86_64/drivers/media/video/adv7183_regs.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/adv7183_regs.h +@@ -0,0 +1,107 @@ ++/* ++ * adv7183 - Analog Devices ADV7183 video decoder registers ++ * ++ * Copyright (c) 2011 Analog Devices Inc. ++ * ++ * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef _ADV7183_REGS_H_ ++#define _ADV7183_REGS_H_ ++ ++#define ADV7183_IN_CTRL 0x00 /* Input control */ ++#define ADV7183_VD_SEL 0x01 /* Video selection */ ++#define ADV7183_OUT_CTRL 0x03 /* Output control */ ++#define ADV7183_EXT_OUT_CTRL 0x04 /* Extended output control */ ++#define ADV7183_AUTO_DET_EN 0x07 /* Autodetect enable */ ++#define ADV7183_CONTRAST 0x08 /* Contrast */ ++#define ADV7183_BRIGHTNESS 0x0A /* Brightness */ ++#define ADV7183_HUE 0x0B /* Hue */ ++#define ADV7183_DEF_Y 0x0C /* Default value Y */ ++#define ADV7183_DEF_C 0x0D /* Default value C */ ++#define ADV7183_ADI_CTRL 0x0E /* ADI control */ ++#define ADV7183_POW_MANAGE 0x0F /* Power Management */ ++#define ADV7183_STATUS_1 0x10 /* Status 1 */ ++#define ADV7183_IDENT 0x11 /* Ident */ ++#define ADV7183_STATUS_2 0x12 /* Status 2 */ ++#define ADV7183_STATUS_3 0x13 /* Status 3 */ ++#define ADV7183_ANAL_CLAMP_CTRL 0x14 /* Analog clamp control */ ++#define ADV7183_DIGI_CLAMP_CTRL_1 0x15 /* Digital clamp control 1 */ ++#define ADV7183_SHAP_FILT_CTRL 0x17 /* Shaping filter control */ ++#define ADV7183_SHAP_FILT_CTRL_2 0x18 /* Shaping filter control 2 */ ++#define ADV7183_COMB_FILT_CTRL 0x19 /* Comb filter control */ ++#define ADV7183_ADI_CTRL_2 0x1D /* ADI control 2 */ ++#define ADV7183_PIX_DELAY_CTRL 0x27 /* Pixel delay control */ ++#define ADV7183_MISC_GAIN_CTRL 0x2B /* Misc gain control */ ++#define ADV7183_AGC_MODE_CTRL 0x2C /* AGC mode control */ ++#define ADV7183_CHRO_GAIN_CTRL_1 0x2D /* Chroma gain control 1 */ ++#define ADV7183_CHRO_GAIN_CTRL_2 0x2E /* Chroma gain control 2 */ ++#define ADV7183_LUMA_GAIN_CTRL_1 0x2F /* Luma gain control 1 */ ++#define ADV7183_LUMA_GAIN_CTRL_2 0x30 /* Luma gain control 2 */ ++#define ADV7183_VS_FIELD_CTRL_1 0x31 /* Vsync field control 1 */ ++#define ADV7183_VS_FIELD_CTRL_2 0x32 /* Vsync field control 2 */ ++#define ADV7183_VS_FIELD_CTRL_3 0x33 /* Vsync field control 3 */ ++#define ADV7183_HS_POS_CTRL_1 0x34 /* Hsync positon control 1 */ ++#define ADV7183_HS_POS_CTRL_2 0x35 /* Hsync positon control 2 */ ++#define ADV7183_HS_POS_CTRL_3 0x36 /* Hsync positon control 3 */ ++#define ADV7183_POLARITY 0x37 /* Polarity */ ++#define ADV7183_NTSC_COMB_CTRL 0x38 /* NTSC comb control */ ++#define ADV7183_PAL_COMB_CTRL 0x39 /* PAL comb control */ ++#define ADV7183_ADC_CTRL 0x3A /* ADC control */ ++#define ADV7183_MAN_WIN_CTRL 0x3D /* Manual window control */ ++#define ADV7183_RESAMPLE_CTRL 0x41 /* Resample control */ ++#define ADV7183_GEMSTAR_CTRL_1 0x48 /* Gemstar ctrl 1 */ ++#define ADV7183_GEMSTAR_CTRL_2 0x49 /* Gemstar ctrl 2 */ ++#define ADV7183_GEMSTAR_CTRL_3 0x4A /* Gemstar ctrl 3 */ ++#define ADV7183_GEMSTAR_CTRL_4 0x4B /* Gemstar ctrl 4 */ ++#define ADV7183_GEMSTAR_CTRL_5 0x4C /* Gemstar ctrl 5 */ ++#define ADV7183_CTI_DNR_CTRL_1 0x4D /* CTI DNR ctrl 1 */ ++#define ADV7183_CTI_DNR_CTRL_2 0x4E /* CTI DNR ctrl 2 */ ++#define ADV7183_CTI_DNR_CTRL_4 0x50 /* CTI DNR ctrl 4 */ ++#define ADV7183_LOCK_CNT 0x51 /* Lock count */ ++#define ADV7183_FREE_LINE_LEN 0x8F /* Free-Run line length 1 */ ++#define ADV7183_VBI_INFO 0x90 /* VBI info */ ++#define ADV7183_WSS_1 0x91 /* WSS 1 */ ++#define ADV7183_WSS_2 0x92 /* WSS 2 */ ++#define ADV7183_EDTV_1 0x93 /* EDTV 1 */ ++#define ADV7183_EDTV_2 0x94 /* EDTV 2 */ ++#define ADV7183_EDTV_3 0x95 /* EDTV 3 */ ++#define ADV7183_CGMS_1 0x96 /* CGMS 1 */ ++#define ADV7183_CGMS_2 0x97 /* CGMS 2 */ ++#define ADV7183_CGMS_3 0x98 /* CGMS 3 */ ++#define ADV7183_CCAP_1 0x99 /* CCAP 1 */ ++#define ADV7183_CCAP_2 0x9A /* CCAP 2 */ ++#define ADV7183_LETTERBOX_1 0x9B /* Letterbox 1 */ ++#define ADV7183_LETTERBOX_2 0x9C /* Letterbox 2 */ ++#define ADV7183_LETTERBOX_3 0x9D /* Letterbox 3 */ ++#define ADV7183_CRC_EN 0xB2 /* CRC enable */ ++#define ADV7183_ADC_SWITCH_1 0xC3 /* ADC switch 1 */ ++#define ADV7183_ADC_SWITCH_2 0xC4 /* ADC swithc 2 */ ++#define ADV7183_LETTERBOX_CTRL_1 0xDC /* Letterbox control 1 */ ++#define ADV7183_LETTERBOX_CTRL_2 0xDD /* Letterbox control 2 */ ++#define ADV7183_SD_OFFSET_CB 0xE1 /* SD offset Cb */ ++#define ADV7183_SD_OFFSET_CR 0xE2 /* SD offset Cr */ ++#define ADV7183_SD_SATURATION_CB 0xE3 /* SD saturation Cb */ ++#define ADV7183_SD_SATURATION_CR 0xE4 /* SD saturation Cr */ ++#define ADV7183_NTSC_V_BEGIN 0xE5 /* NTSC V bit begin */ ++#define ADV7183_NTSC_V_END 0xE6 /* NTSC V bit end */ ++#define ADV7183_NTSC_F_TOGGLE 0xE7 /* NTSC F bit toggle */ ++#define ADV7183_PAL_V_BEGIN 0xE8 /* PAL V bit begin */ ++#define ADV7183_PAL_V_END 0xE9 /* PAL V bit end */ ++#define ADV7183_PAL_F_TOGGLE 0xEA /* PAL F bit toggle */ ++#define ADV7183_DRIVE_STR 0xF4 /* Drive strength */ ++#define ADV7183_IF_COMP_CTRL 0xF8 /* IF comp control */ ++#define ADV7183_VS_MODE_CTRL 0xF9 /* VS mode control */ ++ ++#endif +Index: linux-3.3.x86_64/include/media/adv7183.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/include/media/adv7183.h +@@ -0,0 +1,47 @@ ++/* ++ * adv7183.h - definition for adv7183 inputs and outputs ++ * ++ * Copyright (c) 2011 Analog Devices Inc. ++ * ++ * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef _ADV7183_H_ ++#define _ADV7183_H_ ++ ++/* ADV7183 HW inputs */ ++#define ADV7183_COMPOSITE0 0 /* CVBS in on AIN1 */ ++#define ADV7183_COMPOSITE1 1 /* CVBS in on AIN2 */ ++#define ADV7183_COMPOSITE2 2 /* CVBS in on AIN3 */ ++#define ADV7183_COMPOSITE3 3 /* CVBS in on AIN4 */ ++#define ADV7183_COMPOSITE4 4 /* CVBS in on AIN5 */ ++#define ADV7183_COMPOSITE5 5 /* CVBS in on AIN6 */ ++#define ADV7183_COMPOSITE6 6 /* CVBS in on AIN7 */ ++#define ADV7183_COMPOSITE7 7 /* CVBS in on AIN8 */ ++#define ADV7183_COMPOSITE8 8 /* CVBS in on AIN9 */ ++#define ADV7183_COMPOSITE9 9 /* CVBS in on AIN10 */ ++#define ADV7183_COMPOSITE10 10 /* CVBS in on AIN11 */ ++ ++#define ADV7183_SVIDEO0 11 /* Y on AIN1, C on AIN4 */ ++#define ADV7183_SVIDEO1 12 /* Y on AIN2, C on AIN5 */ ++#define ADV7183_SVIDEO2 13 /* Y on AIN3, C on AIN6 */ ++ ++#define ADV7183_COMPONENT0 14 /* Y on AIN1, Pr on AIN4, Pb on AIN5 */ ++#define ADV7183_COMPONENT1 15 /* Y on AIN2, Pr on AIN3, Pb on AIN6 */ ++ ++/* ADV7183 HW outputs */ ++#define ADV7183_8BIT_OUT 0 ++#define ADV7183_16BIT_OUT 1 ++ ++#endif +Index: linux-3.3.x86_64/include/media/v4l2-chip-ident.h +=================================================================== +--- linux-3.3.x86_64.orig/include/media/v4l2-chip-ident.h ++++ linux-3.3.x86_64/include/media/v4l2-chip-ident.h +@@ -143,6 +143,9 @@ enum { + /* module saa6588: just ident 6588 */ + V4L2_IDENT_SAA6588 = 6588, + ++ /* module vs6624: just ident 6624 */ ++ V4L2_IDENT_VS6624 = 6624, ++ + /* module saa6752hs: reserved range 6750-6759 */ + V4L2_IDENT_SAA6752HS = 6752, + V4L2_IDENT_SAA6752HS_AC3 = 6753, +@@ -162,6 +165,9 @@ enum { + /* module adv7180: just ident 7180 */ + V4L2_IDENT_ADV7180 = 7180, + ++ /* module adv7183: just ident 7183 */ ++ V4L2_IDENT_ADV7183 = 7183, ++ + /* module saa7185: just ident 7185 */ + V4L2_IDENT_SAA7185 = 7185, + +Index: linux-3.3.x86_64/drivers/media/video/vs6624.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/vs6624.c +@@ -0,0 +1,928 @@ ++/* ++ * vs6624.c ST VS6624 CMOS image sensor driver ++ * ++ * Copyright (c) 2011 Analog Devices Inc. ++ * ++ * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "vs6624_regs.h" ++ ++#define VGA_WIDTH 640 ++#define VGA_HEIGHT 480 ++#define QVGA_WIDTH 320 ++#define QVGA_HEIGHT 240 ++#define QQVGA_WIDTH 160 ++#define QQVGA_HEIGHT 120 ++#define CIF_WIDTH 352 ++#define CIF_HEIGHT 288 ++#define QCIF_WIDTH 176 ++#define QCIF_HEIGHT 144 ++#define QQCIF_WIDTH 88 ++#define QQCIF_HEIGHT 72 ++ ++#define MAX_FRAME_RATE 30 ++ ++struct vs6624 { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct v4l2_fract frame_rate; ++ struct v4l2_mbus_framefmt fmt; ++ unsigned ce_pin; ++}; ++ ++static const struct vs6624_format { ++ enum v4l2_mbus_pixelcode mbus_code; ++ enum v4l2_colorspace colorspace; ++} vs6624_formats[] = { ++ { ++ .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, ++ .colorspace = V4L2_COLORSPACE_JPEG, ++ }, ++ { ++ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, ++ .colorspace = V4L2_COLORSPACE_JPEG, ++ }, ++ { ++ .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, ++ .colorspace = V4L2_COLORSPACE_SRGB, ++ }, ++}; ++ ++static struct v4l2_mbus_framefmt vs6624_default_fmt = { ++ .width = VGA_WIDTH, ++ .height = VGA_HEIGHT, ++ .code = V4L2_MBUS_FMT_UYVY8_2X8, ++ .field = V4L2_FIELD_NONE, ++ .colorspace = V4L2_COLORSPACE_JPEG, ++}; ++ ++static const u16 vs6624_p1[] = { ++ 0x8104, 0x03, ++ 0x8105, 0x01, ++ 0xc900, 0x03, ++ 0xc904, 0x47, ++ 0xc905, 0x10, ++ 0xc906, 0x80, ++ 0xc907, 0x3a, ++ 0x903a, 0x02, ++ 0x903b, 0x47, ++ 0x903c, 0x15, ++ 0xc908, 0x31, ++ 0xc909, 0xdc, ++ 0xc90a, 0x80, ++ 0xc90b, 0x44, ++ 0x9044, 0x02, ++ 0x9045, 0x31, ++ 0x9046, 0xe2, ++ 0xc90c, 0x07, ++ 0xc90d, 0xe0, ++ 0xc90e, 0x80, ++ 0xc90f, 0x47, ++ 0x9047, 0x90, ++ 0x9048, 0x83, ++ 0x9049, 0x81, ++ 0x904a, 0xe0, ++ 0x904b, 0x60, ++ 0x904c, 0x08, ++ 0x904d, 0x90, ++ 0x904e, 0xc0, ++ 0x904f, 0x43, ++ 0x9050, 0x74, ++ 0x9051, 0x01, ++ 0x9052, 0xf0, ++ 0x9053, 0x80, ++ 0x9054, 0x05, ++ 0x9055, 0xE4, ++ 0x9056, 0x90, ++ 0x9057, 0xc0, ++ 0x9058, 0x43, ++ 0x9059, 0xf0, ++ 0x905a, 0x02, ++ 0x905b, 0x07, ++ 0x905c, 0xec, ++ 0xc910, 0x5d, ++ 0xc911, 0xca, ++ 0xc912, 0x80, ++ 0xc913, 0x5d, ++ 0x905d, 0xa3, ++ 0x905e, 0x04, ++ 0x905f, 0xf0, ++ 0x9060, 0xa3, ++ 0x9061, 0x04, ++ 0x9062, 0xf0, ++ 0x9063, 0x22, ++ 0xc914, 0x72, ++ 0xc915, 0x92, ++ 0xc916, 0x80, ++ 0xc917, 0x64, ++ 0x9064, 0x74, ++ 0x9065, 0x01, ++ 0x9066, 0x02, ++ 0x9067, 0x72, ++ 0x9068, 0x95, ++ 0xc918, 0x47, ++ 0xc919, 0xf2, ++ 0xc91a, 0x81, ++ 0xc91b, 0x69, ++ 0x9169, 0x74, ++ 0x916a, 0x02, ++ 0x916b, 0xf0, ++ 0x916c, 0xec, ++ 0x916d, 0xb4, ++ 0x916e, 0x10, ++ 0x916f, 0x0a, ++ 0x9170, 0x90, ++ 0x9171, 0x80, ++ 0x9172, 0x16, ++ 0x9173, 0xe0, ++ 0x9174, 0x70, ++ 0x9175, 0x04, ++ 0x9176, 0x90, ++ 0x9177, 0xd3, ++ 0x9178, 0xc4, ++ 0x9179, 0xf0, ++ 0x917a, 0x22, ++ 0xc91c, 0x0a, ++ 0xc91d, 0xbe, ++ 0xc91e, 0x80, ++ 0xc91f, 0x73, ++ 0x9073, 0xfc, ++ 0x9074, 0xa3, ++ 0x9075, 0xe0, ++ 0x9076, 0xf5, ++ 0x9077, 0x82, ++ 0x9078, 0x8c, ++ 0x9079, 0x83, ++ 0x907a, 0xa3, ++ 0x907b, 0xa3, ++ 0x907c, 0xe0, ++ 0x907d, 0xfc, ++ 0x907e, 0xa3, ++ 0x907f, 0xe0, ++ 0x9080, 0xc3, ++ 0x9081, 0x9f, ++ 0x9082, 0xff, ++ 0x9083, 0xec, ++ 0x9084, 0x9e, ++ 0x9085, 0xfe, ++ 0x9086, 0x02, ++ 0x9087, 0x0a, ++ 0x9088, 0xea, ++ 0xc920, 0x47, ++ 0xc921, 0x38, ++ 0xc922, 0x80, ++ 0xc923, 0x89, ++ 0x9089, 0xec, ++ 0x908a, 0xd3, ++ 0x908b, 0x94, ++ 0x908c, 0x20, ++ 0x908d, 0x40, ++ 0x908e, 0x01, ++ 0x908f, 0x1c, ++ 0x9090, 0x90, ++ 0x9091, 0xd3, ++ 0x9092, 0xd4, ++ 0x9093, 0xec, ++ 0x9094, 0xf0, ++ 0x9095, 0x02, ++ 0x9096, 0x47, ++ 0x9097, 0x3d, ++ 0xc924, 0x45, ++ 0xc925, 0xca, ++ 0xc926, 0x80, ++ 0xc927, 0x98, ++ 0x9098, 0x12, ++ 0x9099, 0x77, ++ 0x909a, 0xd6, ++ 0x909b, 0x02, ++ 0x909c, 0x45, ++ 0x909d, 0xcd, ++ 0xc928, 0x20, ++ 0xc929, 0xd5, ++ 0xc92a, 0x80, ++ 0xc92b, 0x9e, ++ 0x909e, 0x90, ++ 0x909f, 0x82, ++ 0x90a0, 0x18, ++ 0x90a1, 0xe0, ++ 0x90a2, 0xb4, ++ 0x90a3, 0x03, ++ 0x90a4, 0x0e, ++ 0x90a5, 0x90, ++ 0x90a6, 0x83, ++ 0x90a7, 0xbf, ++ 0x90a8, 0xe0, ++ 0x90a9, 0x60, ++ 0x90aa, 0x08, ++ 0x90ab, 0x90, ++ 0x90ac, 0x81, ++ 0x90ad, 0xfc, ++ 0x90ae, 0xe0, ++ 0x90af, 0xff, ++ 0x90b0, 0xc3, ++ 0x90b1, 0x13, ++ 0x90b2, 0xf0, ++ 0x90b3, 0x90, ++ 0x90b4, 0x81, ++ 0x90b5, 0xfc, ++ 0x90b6, 0xe0, ++ 0x90b7, 0xff, ++ 0x90b8, 0x02, ++ 0x90b9, 0x20, ++ 0x90ba, 0xda, ++ 0xc92c, 0x70, ++ 0xc92d, 0xbc, ++ 0xc92e, 0x80, ++ 0xc92f, 0xbb, ++ 0x90bb, 0x90, ++ 0x90bc, 0x82, ++ 0x90bd, 0x18, ++ 0x90be, 0xe0, ++ 0x90bf, 0xb4, ++ 0x90c0, 0x03, ++ 0x90c1, 0x06, ++ 0x90c2, 0x90, ++ 0x90c3, 0xc1, ++ 0x90c4, 0x06, ++ 0x90c5, 0x74, ++ 0x90c6, 0x05, ++ 0x90c7, 0xf0, ++ 0x90c8, 0x90, ++ 0x90c9, 0xd3, ++ 0x90ca, 0xa0, ++ 0x90cb, 0x02, ++ 0x90cc, 0x70, ++ 0x90cd, 0xbf, ++ 0xc930, 0x72, ++ 0xc931, 0x21, ++ 0xc932, 0x81, ++ 0xc933, 0x3b, ++ 0x913b, 0x7d, ++ 0x913c, 0x02, ++ 0x913d, 0x7f, ++ 0x913e, 0x7b, ++ 0x913f, 0x02, ++ 0x9140, 0x72, ++ 0x9141, 0x25, ++ 0xc934, 0x28, ++ 0xc935, 0xae, ++ 0xc936, 0x80, ++ 0xc937, 0xd2, ++ 0x90d2, 0xf0, ++ 0x90d3, 0x90, ++ 0x90d4, 0xd2, ++ 0x90d5, 0x0a, ++ 0x90d6, 0x02, ++ 0x90d7, 0x28, ++ 0x90d8, 0xb4, ++ 0xc938, 0x28, ++ 0xc939, 0xb1, ++ 0xc93a, 0x80, ++ 0xc93b, 0xd9, ++ 0x90d9, 0x90, ++ 0x90da, 0x83, ++ 0x90db, 0xba, ++ 0x90dc, 0xe0, ++ 0x90dd, 0xff, ++ 0x90de, 0x90, ++ 0x90df, 0xd2, ++ 0x90e0, 0x08, ++ 0x90e1, 0xe0, ++ 0x90e2, 0xe4, ++ 0x90e3, 0xef, ++ 0x90e4, 0xf0, ++ 0x90e5, 0xa3, ++ 0x90e6, 0xe0, ++ 0x90e7, 0x74, ++ 0x90e8, 0xff, ++ 0x90e9, 0xf0, ++ 0x90ea, 0x90, ++ 0x90eb, 0xd2, ++ 0x90ec, 0x0a, ++ 0x90ed, 0x02, ++ 0x90ee, 0x28, ++ 0x90ef, 0xb4, ++ 0xc93c, 0x29, ++ 0xc93d, 0x79, ++ 0xc93e, 0x80, ++ 0xc93f, 0xf0, ++ 0x90f0, 0xf0, ++ 0x90f1, 0x90, ++ 0x90f2, 0xd2, ++ 0x90f3, 0x0e, ++ 0x90f4, 0x02, ++ 0x90f5, 0x29, ++ 0x90f6, 0x7f, ++ 0xc940, 0x29, ++ 0xc941, 0x7c, ++ 0xc942, 0x80, ++ 0xc943, 0xf7, ++ 0x90f7, 0x90, ++ 0x90f8, 0x83, ++ 0x90f9, 0xba, ++ 0x90fa, 0xe0, ++ 0x90fb, 0xff, ++ 0x90fc, 0x90, ++ 0x90fd, 0xd2, ++ 0x90fe, 0x0c, ++ 0x90ff, 0xe0, ++ 0x9100, 0xe4, ++ 0x9101, 0xef, ++ 0x9102, 0xf0, ++ 0x9103, 0xa3, ++ 0x9104, 0xe0, ++ 0x9105, 0x74, ++ 0x9106, 0xff, ++ 0x9107, 0xf0, ++ 0x9108, 0x90, ++ 0x9109, 0xd2, ++ 0x910a, 0x0e, ++ 0x910b, 0x02, ++ 0x910c, 0x29, ++ 0x910d, 0x7f, ++ 0xc944, 0x2a, ++ 0xc945, 0x42, ++ 0xc946, 0x81, ++ 0xc947, 0x0e, ++ 0x910e, 0xf0, ++ 0x910f, 0x90, ++ 0x9110, 0xd2, ++ 0x9111, 0x12, ++ 0x9112, 0x02, ++ 0x9113, 0x2a, ++ 0x9114, 0x48, ++ 0xc948, 0x2a, ++ 0xc949, 0x45, ++ 0xc94a, 0x81, ++ 0xc94b, 0x15, ++ 0x9115, 0x90, ++ 0x9116, 0x83, ++ 0x9117, 0xba, ++ 0x9118, 0xe0, ++ 0x9119, 0xff, ++ 0x911a, 0x90, ++ 0x911b, 0xd2, ++ 0x911c, 0x10, ++ 0x911d, 0xe0, ++ 0x911e, 0xe4, ++ 0x911f, 0xef, ++ 0x9120, 0xf0, ++ 0x9121, 0xa3, ++ 0x9122, 0xe0, ++ 0x9123, 0x74, ++ 0x9124, 0xff, ++ 0x9125, 0xf0, ++ 0x9126, 0x90, ++ 0x9127, 0xd2, ++ 0x9128, 0x12, ++ 0x9129, 0x02, ++ 0x912a, 0x2a, ++ 0x912b, 0x48, ++ 0xc900, 0x01, ++ 0x0000, 0x00, ++}; ++ ++static const u16 vs6624_p2[] = { ++ 0x806f, 0x01, ++ 0x058c, 0x01, ++ 0x0000, 0x00, ++}; ++ ++static const u16 vs6624_run_setup[] = { ++ 0x1d18, 0x00, /* Enableconstrainedwhitebalance */ ++ VS6624_PEAK_MIN_OUT_G_MSB, 0x3c, /* Damper PeakGain Output MSB */ ++ VS6624_PEAK_MIN_OUT_G_LSB, 0x66, /* Damper PeakGain Output LSB */ ++ VS6624_CM_LOW_THR_MSB, 0x65, /* Damper Low MSB */ ++ VS6624_CM_LOW_THR_LSB, 0xd1, /* Damper Low LSB */ ++ VS6624_CM_HIGH_THR_MSB, 0x66, /* Damper High MSB */ ++ VS6624_CM_HIGH_THR_LSB, 0x62, /* Damper High LSB */ ++ VS6624_CM_MIN_OUT_MSB, 0x00, /* Damper Min output MSB */ ++ VS6624_CM_MIN_OUT_LSB, 0x00, /* Damper Min output LSB */ ++ VS6624_NORA_DISABLE, 0x00, /* Nora fDisable */ ++ VS6624_NORA_USAGE, 0x04, /* Nora usage */ ++ VS6624_NORA_LOW_THR_MSB, 0x63, /* Damper Low MSB Changed 0x63 to 0x65 */ ++ VS6624_NORA_LOW_THR_LSB, 0xd1, /* Damper Low LSB */ ++ VS6624_NORA_HIGH_THR_MSB, 0x68, /* Damper High MSB */ ++ VS6624_NORA_HIGH_THR_LSB, 0xdd, /* Damper High LSB */ ++ VS6624_NORA_MIN_OUT_MSB, 0x3a, /* Damper Min output MSB */ ++ VS6624_NORA_MIN_OUT_LSB, 0x00, /* Damper Min output LSB */ ++ VS6624_F2B_DISABLE, 0x00, /* Disable */ ++ 0x1d8a, 0x30, /* MAXWeightHigh */ ++ 0x1d91, 0x62, /* fpDamperLowThresholdHigh MSB */ ++ 0x1d92, 0x4a, /* fpDamperLowThresholdHigh LSB */ ++ 0x1d95, 0x65, /* fpDamperHighThresholdHigh MSB */ ++ 0x1d96, 0x0e, /* fpDamperHighThresholdHigh LSB */ ++ 0x1da1, 0x3a, /* fpMinimumDamperOutputLow MSB */ ++ 0x1da2, 0xb8, /* fpMinimumDamperOutputLow LSB */ ++ 0x1e08, 0x06, /* MAXWeightLow */ ++ 0x1e0a, 0x0a, /* MAXWeightHigh */ ++ 0x1601, 0x3a, /* Red A MSB */ ++ 0x1602, 0x14, /* Red A LSB */ ++ 0x1605, 0x3b, /* Blue A MSB */ ++ 0x1606, 0x85, /* BLue A LSB */ ++ 0x1609, 0x3b, /* RED B MSB */ ++ 0x160a, 0x85, /* RED B LSB */ ++ 0x160d, 0x3a, /* Blue B MSB */ ++ 0x160e, 0x14, /* Blue B LSB */ ++ 0x1611, 0x30, /* Max Distance from Locus MSB */ ++ 0x1612, 0x8f, /* Max Distance from Locus MSB */ ++ 0x1614, 0x01, /* Enable constrainer */ ++ 0x0000, 0x00, ++}; ++ ++static const u16 vs6624_default[] = { ++ VS6624_CONTRAST0, 0x84, ++ VS6624_SATURATION0, 0x75, ++ VS6624_GAMMA0, 0x11, ++ VS6624_CONTRAST1, 0x84, ++ VS6624_SATURATION1, 0x75, ++ VS6624_GAMMA1, 0x11, ++ VS6624_MAN_RG, 0x80, ++ VS6624_MAN_GG, 0x80, ++ VS6624_MAN_BG, 0x80, ++ VS6624_WB_MODE, 0x1, ++ VS6624_EXPO_COMPENSATION, 0xfe, ++ VS6624_EXPO_METER, 0x0, ++ VS6624_LIGHT_FREQ, 0x64, ++ VS6624_PEAK_GAIN, 0xe, ++ VS6624_PEAK_LOW_THR, 0x28, ++ VS6624_HMIRROR0, 0x0, ++ VS6624_VFLIP0, 0x0, ++ VS6624_ZOOM_HSTEP0_MSB, 0x0, ++ VS6624_ZOOM_HSTEP0_LSB, 0x1, ++ VS6624_ZOOM_VSTEP0_MSB, 0x0, ++ VS6624_ZOOM_VSTEP0_LSB, 0x1, ++ VS6624_PAN_HSTEP0_MSB, 0x0, ++ VS6624_PAN_HSTEP0_LSB, 0xf, ++ VS6624_PAN_VSTEP0_MSB, 0x0, ++ VS6624_PAN_VSTEP0_LSB, 0xf, ++ VS6624_SENSOR_MODE, 0x1, ++ VS6624_SYNC_CODE_SETUP, 0x21, ++ VS6624_DISABLE_FR_DAMPER, 0x0, ++ VS6624_FR_DEN, 0x1, ++ VS6624_FR_NUM_LSB, 0xf, ++ VS6624_INIT_PIPE_SETUP, 0x0, ++ VS6624_IMG_FMT0, 0x0, ++ VS6624_YUV_SETUP, 0x1, ++ VS6624_IMAGE_SIZE0, 0x2, ++ 0x0000, 0x00, ++}; ++ ++static inline struct vs6624 *to_vs6624(struct v4l2_subdev *sd) ++{ ++ return container_of(sd, struct vs6624, sd); ++} ++static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) ++{ ++ return &container_of(ctrl->handler, struct vs6624, hdl)->sd; ++} ++ ++static int vs6624_read(struct v4l2_subdev *sd, u16 index) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ u8 buf[2]; ++ ++ buf[0] = index >> 8; ++ buf[1] = index; ++ i2c_master_send(client, buf, 2); ++ i2c_master_recv(client, buf, 1); ++ ++ return buf[0]; ++} ++ ++static int vs6624_write(struct v4l2_subdev *sd, u16 index, ++ u8 value) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ u8 buf[3]; ++ ++ buf[0] = index >> 8; ++ buf[1] = index; ++ buf[2] = value; ++ ++ return i2c_master_send(client, buf, 3); ++} ++ ++static int vs6624_writeregs(struct v4l2_subdev *sd, const u16 *regs) ++{ ++ u16 reg; ++ u8 data; ++ ++ while (*regs != 0x00) { ++ reg = *regs++; ++ data = *regs++; ++ ++ vs6624_write(sd, reg, data); ++ } ++ return 0; ++} ++ ++static int vs6624_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ ++ switch (ctrl->id) { ++ case V4L2_CID_CONTRAST: ++ vs6624_write(sd, VS6624_CONTRAST0, ctrl->val); ++ break; ++ case V4L2_CID_SATURATION: ++ vs6624_write(sd, VS6624_SATURATION0, ctrl->val); ++ break; ++ case V4L2_CID_HFLIP: ++ vs6624_write(sd, VS6624_HMIRROR0, ctrl->val); ++ break; ++ case V4L2_CID_VFLIP: ++ vs6624_write(sd, VS6624_VFLIP0, ctrl->val); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int vs6624_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, ++ enum v4l2_mbus_pixelcode *code) ++{ ++ if (index >= ARRAY_SIZE(vs6624_formats)) ++ return -EINVAL; ++ ++ *code = vs6624_formats[index].mbus_code; ++ return 0; ++} ++ ++static int vs6624_try_mbus_fmt(struct v4l2_subdev *sd, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ int index; ++ ++ for (index = 0; index < ARRAY_SIZE(vs6624_formats); index++) ++ if (vs6624_formats[index].mbus_code == fmt->code) ++ break; ++ if (index >= ARRAY_SIZE(vs6624_formats)) { ++ /* default to first format */ ++ index = 0; ++ fmt->code = vs6624_formats[0].mbus_code; ++ } ++ ++ /* sensor mode is VGA */ ++ if (fmt->width > VGA_WIDTH) ++ fmt->width = VGA_WIDTH; ++ if (fmt->height > VGA_HEIGHT) ++ fmt->height = VGA_HEIGHT; ++ fmt->width = fmt->width & (~3); ++ fmt->height = fmt->height & (~3); ++ fmt->field = V4L2_FIELD_NONE; ++ fmt->colorspace = vs6624_formats[index].colorspace; ++ return 0; ++} ++ ++static int vs6624_s_mbus_fmt(struct v4l2_subdev *sd, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ struct vs6624 *sensor = to_vs6624(sd); ++ int ret; ++ ++ ret = vs6624_try_mbus_fmt(sd, fmt); ++ if (ret) ++ return ret; ++ ++ /* set image format */ ++ switch (fmt->code) { ++ case V4L2_MBUS_FMT_UYVY8_2X8: ++ vs6624_write(sd, VS6624_IMG_FMT0, 0x0); ++ vs6624_write(sd, VS6624_YUV_SETUP, 0x1); ++ break; ++ case V4L2_MBUS_FMT_YUYV8_2X8: ++ vs6624_write(sd, VS6624_IMG_FMT0, 0x0); ++ vs6624_write(sd, VS6624_YUV_SETUP, 0x3); ++ break; ++ case V4L2_MBUS_FMT_RGB565_2X8_LE: ++ vs6624_write(sd, VS6624_IMG_FMT0, 0x4); ++ vs6624_write(sd, VS6624_RGB_SETUP, 0x0); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* set image size */ ++ if ((fmt->width == VGA_WIDTH) && (fmt->height == VGA_HEIGHT)) ++ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x2); ++ else if ((fmt->width == QVGA_WIDTH) && (fmt->height == QVGA_HEIGHT)) ++ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x4); ++ else if ((fmt->width == QQVGA_WIDTH) && (fmt->height == QQVGA_HEIGHT)) ++ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x6); ++ else if ((fmt->width == CIF_WIDTH) && (fmt->height == CIF_HEIGHT)) ++ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x3); ++ else if ((fmt->width == QCIF_WIDTH) && (fmt->height == QCIF_HEIGHT)) ++ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x5); ++ else if ((fmt->width == QQCIF_WIDTH) && (fmt->height == QQCIF_HEIGHT)) ++ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x7); ++ else { ++ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x8); ++ vs6624_write(sd, VS6624_MAN_HSIZE0_MSB, fmt->width >> 8); ++ vs6624_write(sd, VS6624_MAN_HSIZE0_LSB, fmt->width & 0xFF); ++ vs6624_write(sd, VS6624_MAN_VSIZE0_MSB, fmt->height >> 8); ++ vs6624_write(sd, VS6624_MAN_VSIZE0_LSB, fmt->height & 0xFF); ++ vs6624_write(sd, VS6624_CROP_CTRL0, 0x1); ++ } ++ ++ sensor->fmt = *fmt; ++ ++ return 0; ++} ++ ++static int vs6624_g_mbus_fmt(struct v4l2_subdev *sd, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ struct vs6624 *sensor = to_vs6624(sd); ++ ++ *fmt = sensor->fmt; ++ return 0; ++} ++ ++static int vs6624_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct vs6624 *sensor = to_vs6624(sd); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ memset(cp, 0, sizeof(*cp)); ++ cp->capability = V4L2_CAP_TIMEPERFRAME; ++ cp->timeperframe.numerator = sensor->frame_rate.denominator; ++ cp->timeperframe.denominator = sensor->frame_rate.numerator; ++ return 0; ++} ++ ++static int vs6624_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct vs6624 *sensor = to_vs6624(sd); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ struct v4l2_fract *tpf = &cp->timeperframe; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ if (cp->extendedmode != 0) ++ return -EINVAL; ++ ++ if (tpf->numerator == 0 || tpf->denominator == 0 ++ || (tpf->denominator > tpf->numerator * MAX_FRAME_RATE)) { ++ /* reset to max frame rate */ ++ tpf->numerator = 1; ++ tpf->denominator = MAX_FRAME_RATE; ++ } ++ sensor->frame_rate.numerator = tpf->denominator; ++ sensor->frame_rate.denominator = tpf->numerator; ++ vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0); ++ vs6624_write(sd, VS6624_FR_NUM_MSB, ++ sensor->frame_rate.numerator >> 8); ++ vs6624_write(sd, VS6624_FR_NUM_LSB, ++ sensor->frame_rate.numerator & 0xFF); ++ vs6624_write(sd, VS6624_FR_DEN, ++ sensor->frame_rate.denominator & 0xFF); ++ return 0; ++} ++ ++static int vs6624_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ if (enable) ++ vs6624_write(sd, VS6624_USER_CMD, 0x2); ++ else ++ vs6624_write(sd, VS6624_USER_CMD, 0x4); ++ udelay(100); ++ return 0; ++} ++ ++static int vs6624_g_chip_ident(struct v4l2_subdev *sd, ++ struct v4l2_dbg_chip_ident *chip) ++{ ++ int rev; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ rev = (vs6624_read(sd, VS6624_FW_VSN_MAJOR) << 8) ++ | vs6624_read(sd, VS6624_FW_VSN_MINOR); ++ ++ return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_VS6624, rev); ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int vs6624_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ if (!v4l2_chip_match_i2c_client(client, ®->match)) ++ return -EINVAL; ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ reg->val = vs6624_read(sd, reg->reg & 0xffff); ++ reg->size = 1; ++ return 0; ++} ++ ++static int vs6624_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ if (!v4l2_chip_match_i2c_client(client, ®->match)) ++ return -EINVAL; ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ vs6624_write(sd, reg->reg & 0xffff, reg->val & 0xff); ++ return 0; ++} ++#endif ++ ++static const struct v4l2_ctrl_ops vs6624_ctrl_ops = { ++ .s_ctrl = vs6624_s_ctrl, ++}; ++ ++static const struct v4l2_subdev_core_ops vs6624_core_ops = { ++ .g_chip_ident = vs6624_g_chip_ident, ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = vs6624_g_register, ++ .s_register = vs6624_s_register, ++#endif ++}; ++ ++static const struct v4l2_subdev_video_ops vs6624_video_ops = { ++ .enum_mbus_fmt = vs6624_enum_mbus_fmt, ++ .try_mbus_fmt = vs6624_try_mbus_fmt, ++ .s_mbus_fmt = vs6624_s_mbus_fmt, ++ .g_mbus_fmt = vs6624_g_mbus_fmt, ++ .s_parm = vs6624_s_parm, ++ .g_parm = vs6624_g_parm, ++ .s_stream = vs6624_s_stream, ++}; ++ ++static const struct v4l2_subdev_ops vs6624_ops = { ++ .core = &vs6624_core_ops, ++ .video = &vs6624_video_ops, ++}; ++ ++static int __devinit vs6624_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct vs6624 *sensor; ++ struct v4l2_subdev *sd; ++ struct v4l2_ctrl_handler *hdl; ++ const unsigned *ce; ++ int ret; ++ ++ /* Check if the adapter supports the needed features */ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) ++ return -EIO; ++ ++ ce = client->dev.platform_data; ++ if (ce == NULL) ++ return -EINVAL; ++ ++ ret = gpio_request(*ce, "VS6624 Chip Enable"); ++ if (ret) { ++ v4l_err(client, "failed to request GPIO %d\n", *ce); ++ return ret; ++ } ++ gpio_direction_output(*ce, 1); ++ /* wait 100ms before any further i2c writes are performed */ ++ mdelay(100); ++ ++ sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); ++ if (sensor == NULL) { ++ gpio_free(*ce); ++ return -ENOMEM; ++ } ++ ++ sd = &sensor->sd; ++ v4l2_i2c_subdev_init(sd, client, &vs6624_ops); ++ ++ vs6624_writeregs(sd, vs6624_p1); ++ vs6624_write(sd, VS6624_MICRO_EN, 0x2); ++ vs6624_write(sd, VS6624_DIO_EN, 0x1); ++ mdelay(10); ++ vs6624_writeregs(sd, vs6624_p2); ++ ++ vs6624_writeregs(sd, vs6624_default); ++ vs6624_write(sd, VS6624_HSYNC_SETUP, 0xF); ++ vs6624_writeregs(sd, vs6624_run_setup); ++ ++ /* set frame rate */ ++ sensor->frame_rate.numerator = MAX_FRAME_RATE; ++ sensor->frame_rate.denominator = 1; ++ vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0); ++ vs6624_write(sd, VS6624_FR_NUM_MSB, ++ sensor->frame_rate.numerator >> 8); ++ vs6624_write(sd, VS6624_FR_NUM_LSB, ++ sensor->frame_rate.numerator & 0xFF); ++ vs6624_write(sd, VS6624_FR_DEN, ++ sensor->frame_rate.denominator & 0xFF); ++ ++ sensor->fmt = vs6624_default_fmt; ++ sensor->ce_pin = *ce; ++ ++ v4l_info(client, "chip found @ 0x%02x (%s)\n", ++ client->addr << 1, client->adapter->name); ++ ++ hdl = &sensor->hdl; ++ v4l2_ctrl_handler_init(hdl, 4); ++ v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x87); ++ v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 0xFF, 1, 0x78); ++ v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ /* hook the control handler into the driver */ ++ sd->ctrl_handler = hdl; ++ if (hdl->error) { ++ int err = hdl->error; ++ ++ v4l2_ctrl_handler_free(hdl); ++ kfree(sensor); ++ gpio_free(*ce); ++ return err; ++ } ++ ++ /* initialize the hardware to the default control values */ ++ ret = v4l2_ctrl_handler_setup(hdl); ++ if (ret) { ++ v4l2_ctrl_handler_free(hdl); ++ kfree(sensor); ++ gpio_free(*ce); ++ } ++ return ret; ++} ++ ++static int __devexit vs6624_remove(struct i2c_client *client) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(client); ++ struct vs6624 *sensor = to_vs6624(sd); ++ ++ v4l2_device_unregister_subdev(sd); ++ v4l2_ctrl_handler_free(sd->ctrl_handler); ++ gpio_free(sensor->ce_pin); ++ kfree(sensor); ++ return 0; ++} ++ ++static const struct i2c_device_id vs6624_id[] = { ++ {"vs6624", 0}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(i2c, vs6624_id); ++ ++static struct i2c_driver vs6624_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "vs6624", ++ }, ++ .probe = vs6624_probe, ++ .remove = __devexit_p(vs6624_remove), ++ .id_table = vs6624_id, ++}; ++ ++static __init int vs6624_init(void) ++{ ++ return i2c_add_driver(&vs6624_driver); ++} ++ ++static __exit void vs6624_exit(void) ++{ ++ i2c_del_driver(&vs6624_driver); ++} ++ ++module_init(vs6624_init); ++module_exit(vs6624_exit); ++ ++MODULE_DESCRIPTION("VS6624 sensor driver"); ++MODULE_AUTHOR("Scott Jiang "); ++MODULE_LICENSE("GPL v2"); +Index: linux-3.3.x86_64/drivers/media/video/vs6624_regs.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/vs6624_regs.h +@@ -0,0 +1,337 @@ ++/* ++ * vs6624 - ST VS6624 CMOS image sensor registers ++ * ++ * Copyright (c) 2011 Analog Devices Inc. ++ * ++ * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef _VS6624_REGS_H_ ++#define _VS6624_REGS_H_ ++ ++/* low level control registers */ ++#define VS6624_MICRO_EN 0xC003 /* power enable for all MCU clock */ ++#define VS6624_DIO_EN 0xC044 /* enable digital I/O */ ++/* device parameters */ ++#define VS6624_DEV_ID_MSB 0x0001 /* device id MSB */ ++#define VS6624_DEV_ID_LSB 0x0002 /* device id LSB */ ++#define VS6624_FW_VSN_MAJOR 0x0004 /* firmware version major */ ++#define VS6624_FW_VSN_MINOR 0x0006 /* firmware version minor */ ++#define VS6624_PATCH_VSN_MAJOR 0x0008 /* patch version major */ ++#define VS6624_PATCH_VSN_MINOR 0x000A /* patch version minor */ ++/* host interface manager control */ ++#define VS6624_USER_CMD 0x0180 /* user level control of operating states */ ++/* host interface manager status */ ++#define VS6624_STATE 0x0202 /* current state of the mode manager */ ++/* run mode control */ ++#define VS6624_METER_ON 0x0280 /* if false AE and AWB are disabled */ ++/* mode setup */ ++#define VS6624_ACTIVE_PIPE_SETUP 0x0302 /* select the active bank for non view live mode */ ++#define VS6624_SENSOR_MODE 0x0308 /* select the different sensor mode */ ++/* pipe setup bank0 */ ++#define VS6624_IMAGE_SIZE0 0x0380 /* required output dimension */ ++#define VS6624_MAN_HSIZE0_MSB 0x0383 /* input required manual H size MSB */ ++#define VS6624_MAN_HSIZE0_LSB 0x0384 /* input required manual H size LSB */ ++#define VS6624_MAN_VSIZE0_MSB 0x0387 /* input required manual V size MSB */ ++#define VS6624_MAN_VSIZE0_LSB 0x0388 /* input required manual V size LSB */ ++#define VS6624_ZOOM_HSTEP0_MSB 0x038B /* set the zoom H step MSB */ ++#define VS6624_ZOOM_HSTEP0_LSB 0x038C /* set the zoom H step LSB */ ++#define VS6624_ZOOM_VSTEP0_MSB 0x038F /* set the zoom V step MSB */ ++#define VS6624_ZOOM_VSTEP0_LSB 0x0390 /* set the zoom V step LSB */ ++#define VS6624_ZOOM_CTRL0 0x0392 /* control zoon in, out and stop */ ++#define VS6624_PAN_HSTEP0_MSB 0x0395 /* set the pan H step MSB */ ++#define VS6624_PAN_HSTEP0_LSB 0x0396 /* set the pan H step LSB */ ++#define VS6624_PAN_VSTEP0_MSB 0x0399 /* set the pan V step MSB */ ++#define VS6624_PAN_VSTEP0_LSB 0x039A /* set the pan V step LSB */ ++#define VS6624_PAN_CTRL0 0x039C /* control pan operation */ ++#define VS6624_CROP_CTRL0 0x039E /* select cropping mode */ ++#define VS6624_CROP_HSTART0_MSB 0x03A1 /* set the cropping H start address MSB */ ++#define VS6624_CROP_HSTART0_LSB 0x03A2 /* set the cropping H start address LSB */ ++#define VS6624_CROP_HSIZE0_MSB 0x03A5 /* set the cropping H size MSB */ ++#define VS6624_CROP_HSIZE0_LSB 0x03A6 /* set the cropping H size LSB */ ++#define VS6624_CROP_VSTART0_MSB 0x03A9 /* set the cropping V start address MSB */ ++#define VS6624_CROP_VSTART0_LSB 0x03AA /* set the cropping V start address LSB */ ++#define VS6624_CROP_VSIZE0_MSB 0x03AD /* set the cropping V size MSB */ ++#define VS6624_CROP_VSIZE0_LSB 0x03AE /* set the cropping V size LSB */ ++#define VS6624_IMG_FMT0 0x03B0 /* select required output image format */ ++#define VS6624_BAYER_OUT_ALIGN0 0x03B2 /* set bayer output alignment */ ++#define VS6624_CONTRAST0 0x03B4 /* contrast control for output */ ++#define VS6624_SATURATION0 0x03B6 /* saturation control for output */ ++#define VS6624_GAMMA0 0x03B8 /* gamma settings */ ++#define VS6624_HMIRROR0 0x03BA /* horizontal image orientation flip */ ++#define VS6624_VFLIP0 0x03BC /* vertical image orientation flip */ ++#define VS6624_CHANNEL_ID0 0x03BE /* logical DMA channel number */ ++/* pipe setup bank1 */ ++#define VS6624_IMAGE_SIZE1 0x0400 /* required output dimension */ ++#define VS6624_MAN_HSIZE1_MSB 0x0403 /* input required manual H size MSB */ ++#define VS6624_MAN_HSIZE1_LSB 0x0404 /* input required manual H size LSB */ ++#define VS6624_MAN_VSIZE1_MSB 0x0407 /* input required manual V size MSB */ ++#define VS6624_MAN_VSIZE1_LSB 0x0408 /* input required manual V size LSB */ ++#define VS6624_ZOOM_HSTEP1_MSB 0x040B /* set the zoom H step MSB */ ++#define VS6624_ZOOM_HSTEP1_LSB 0x040C /* set the zoom H step LSB */ ++#define VS6624_ZOOM_VSTEP1_MSB 0x040F /* set the zoom V step MSB */ ++#define VS6624_ZOOM_VSTEP1_LSB 0x0410 /* set the zoom V step LSB */ ++#define VS6624_ZOOM_CTRL1 0x0412 /* control zoon in, out and stop */ ++#define VS6624_PAN_HSTEP1_MSB 0x0415 /* set the pan H step MSB */ ++#define VS6624_PAN_HSTEP1_LSB 0x0416 /* set the pan H step LSB */ ++#define VS6624_PAN_VSTEP1_MSB 0x0419 /* set the pan V step MSB */ ++#define VS6624_PAN_VSTEP1_LSB 0x041A /* set the pan V step LSB */ ++#define VS6624_PAN_CTRL1 0x041C /* control pan operation */ ++#define VS6624_CROP_CTRL1 0x041E /* select cropping mode */ ++#define VS6624_CROP_HSTART1_MSB 0x0421 /* set the cropping H start address MSB */ ++#define VS6624_CROP_HSTART1_LSB 0x0422 /* set the cropping H start address LSB */ ++#define VS6624_CROP_HSIZE1_MSB 0x0425 /* set the cropping H size MSB */ ++#define VS6624_CROP_HSIZE1_LSB 0x0426 /* set the cropping H size LSB */ ++#define VS6624_CROP_VSTART1_MSB 0x0429 /* set the cropping V start address MSB */ ++#define VS6624_CROP_VSTART1_LSB 0x042A /* set the cropping V start address LSB */ ++#define VS6624_CROP_VSIZE1_MSB 0x042D /* set the cropping V size MSB */ ++#define VS6624_CROP_VSIZE1_LSB 0x042E /* set the cropping V size LSB */ ++#define VS6624_IMG_FMT1 0x0430 /* select required output image format */ ++#define VS6624_BAYER_OUT_ALIGN1 0x0432 /* set bayer output alignment */ ++#define VS6624_CONTRAST1 0x0434 /* contrast control for output */ ++#define VS6624_SATURATION1 0x0436 /* saturation control for output */ ++#define VS6624_GAMMA1 0x0438 /* gamma settings */ ++#define VS6624_HMIRROR1 0x043A /* horizontal image orientation flip */ ++#define VS6624_VFLIP1 0x043C /* vertical image orientation flip */ ++#define VS6624_CHANNEL_ID1 0x043E /* logical DMA channel number */ ++/* view live control */ ++#define VS6624_VIEW_LIVE_EN 0x0480 /* enable view live mode */ ++#define VS6624_INIT_PIPE_SETUP 0x0482 /* select initial pipe setup bank */ ++/* view live status */ ++#define VS6624_CUR_PIPE_SETUP 0x0500 /* indicates most recently applied setup bank */ ++/* power management */ ++#define VS6624_TIME_TO_POWER_DOWN 0x0580 /* automatically transition time to stop mode */ ++/* video timing parameter host inputs */ ++#define VS6624_EXT_CLK_FREQ_NUM_MSB 0x0605 /* external clock frequency numerator MSB */ ++#define VS6624_EXT_CLK_FREQ_NUM_LSB 0x0606 /* external clock frequency numerator LSB */ ++#define VS6624_EXT_CLK_FREQ_DEN 0x0608 /* external clock frequency denominator */ ++/* video timing control */ ++#define VS6624_SYS_CLK_MODE 0x0880 /* decides system clock frequency */ ++/* frame dimension parameter host inputs */ ++#define VS6624_LIGHT_FREQ 0x0C80 /* AC frequency used for flicker free time */ ++#define VS6624_FLICKER_COMPAT 0x0C82 /* flicker compatible frame length */ ++/* static frame rate control */ ++#define VS6624_FR_NUM_MSB 0x0D81 /* desired frame rate numerator MSB */ ++#define VS6624_FR_NUM_LSB 0x0D82 /* desired frame rate numerator LSB */ ++#define VS6624_FR_DEN 0x0D84 /* desired frame rate denominator */ ++/* automatic frame rate control */ ++#define VS6624_DISABLE_FR_DAMPER 0x0E80 /* defines frame rate mode */ ++#define VS6624_MIN_DAMPER_OUT_MSB 0x0E8C /* minimum frame rate MSB */ ++#define VS6624_MIN_DAMPER_OUT_LSB 0x0E8A /* minimum frame rate LSB */ ++/* exposure controls */ ++#define VS6624_EXPO_MODE 0x1180 /* exposure mode */ ++#define VS6624_EXPO_METER 0x1182 /* weights to be associated with the zones */ ++#define VS6624_EXPO_TIME_NUM 0x1184 /* exposure time numerator */ ++#define VS6624_EXPO_TIME_DEN 0x1186 /* exposure time denominator */ ++#define VS6624_EXPO_TIME_MSB 0x1189 /* exposure time for the Manual Mode MSB */ ++#define VS6624_EXPO_TIME_LSB 0x118A /* exposure time for the Manual Mode LSB */ ++#define VS6624_EXPO_COMPENSATION 0x1190 /* exposure compensation */ ++#define VS6624_DIRECT_COARSE_MSB 0x1195 /* coarse integration lines for Direct Mode MSB */ ++#define VS6624_DIRECT_COARSE_LSB 0x1196 /* coarse integration lines for Direct Mode LSB */ ++#define VS6624_DIRECT_FINE_MSB 0x1199 /* fine integration pixels for Direct Mode MSB */ ++#define VS6624_DIRECT_FINE_LSB 0x119A /* fine integration pixels for Direct Mode LSB */ ++#define VS6624_DIRECT_ANAL_GAIN_MSB 0x119D /* analog gain for Direct Mode MSB */ ++#define VS6624_DIRECT_ANAL_GAIN_LSB 0x119E /* analog gain for Direct Mode LSB */ ++#define VS6624_DIRECT_DIGI_GAIN_MSB 0x11A1 /* digital gain for Direct Mode MSB */ ++#define VS6624_DIRECT_DIGI_GAIN_LSB 0x11A2 /* digital gain for Direct Mode LSB */ ++#define VS6624_FLASH_COARSE_MSB 0x11A5 /* coarse integration lines for Flash Gun Mode MSB */ ++#define VS6624_FLASH_COARSE_LSB 0x11A6 /* coarse integration lines for Flash Gun Mode LSB */ ++#define VS6624_FLASH_FINE_MSB 0x11A9 /* fine integration pixels for Flash Gun Mode MSB */ ++#define VS6624_FLASH_FINE_LSB 0x11AA /* fine integration pixels for Flash Gun Mode LSB */ ++#define VS6624_FLASH_ANAL_GAIN_MSB 0x11AD /* analog gain for Flash Gun Mode MSB */ ++#define VS6624_FLASH_ANAL_GAIN_LSB 0x11AE /* analog gain for Flash Gun Mode LSB */ ++#define VS6624_FLASH_DIGI_GAIN_MSB 0x11B1 /* digital gain for Flash Gun Mode MSB */ ++#define VS6624_FLASH_DIGI_GAIN_LSB 0x11B2 /* digital gain for Flash Gun Mode LSB */ ++#define VS6624_FREEZE_AE 0x11B4 /* freeze auto exposure */ ++#define VS6624_MAX_INT_TIME_MSB 0x11B7 /* user maximum integration time MSB */ ++#define VS6624_MAX_INT_TIME_LSB 0x11B8 /* user maximum integration time LSB */ ++#define VS6624_FLASH_AG_THR_MSB 0x11BB /* recommend flash gun analog gain threshold MSB */ ++#define VS6624_FLASH_AG_THR_LSB 0x11BC /* recommend flash gun analog gain threshold LSB */ ++#define VS6624_ANTI_FLICKER_MODE 0x11C0 /* anti flicker mode */ ++/* white balance control */ ++#define VS6624_WB_MODE 0x1480 /* set white balance mode */ ++#define VS6624_MAN_RG 0x1482 /* user setting for red channel gain */ ++#define VS6624_MAN_GG 0x1484 /* user setting for green channel gain */ ++#define VS6624_MAN_BG 0x1486 /* user setting for blue channel gain */ ++#define VS6624_FLASH_RG_MSB 0x148B /* red gain for Flash Gun MSB */ ++#define VS6624_FLASH_RG_LSB 0x148C /* red gain for Flash Gun LSB */ ++#define VS6624_FLASH_GG_MSB 0x148F /* green gain for Flash Gun MSB */ ++#define VS6624_FLASH_GG_LSB 0x1490 /* green gain for Flash Gun LSB */ ++#define VS6624_FLASH_BG_MSB 0x1493 /* blue gain for Flash Gun MSB */ ++#define VS6624_FLASH_BG_LSB 0x1494 /* blue gain for Flash Gun LSB */ ++/* sensor setup */ ++#define VS6624_BC_OFFSET 0x1990 /* Black Correction Offset */ ++/* image stability */ ++#define VS6624_STABLE_WB 0x1900 /* white balance stable */ ++#define VS6624_STABLE_EXPO 0x1902 /* exposure stable */ ++#define VS6624_STABLE 0x1906 /* system stable */ ++/* flash control */ ++#define VS6624_FLASH_MODE 0x1A80 /* flash mode */ ++#define VS6624_FLASH_OFF_LINE_MSB 0x1A83 /* off line at flash pulse mode MSB */ ++#define VS6624_FLASH_OFF_LINE_LSB 0x1A84 /* off line at flash pulse mode LSB */ ++/* flash status */ ++#define VS6624_FLASH_RECOM 0x1B00 /* flash gun is recommended */ ++#define VS6624_FLASH_GRAB_COMPLETE 0x1B02 /* flash gun image has been grabbed */ ++/* scythe filter controls */ ++#define VS6624_SCYTHE_FILTER 0x1D80 /* disable scythe defect correction */ ++/* jack filter controls */ ++#define VS6624_JACK_FILTER 0x1E00 /* disable jack defect correction */ ++/* demosaic control */ ++#define VS6624_ANTI_ALIAS_FILTER 0x1E80 /* anti alias filter suppress */ ++/* color matrix dampers */ ++#define VS6624_CM_DISABLE 0x1F00 /* disable color matrix damper */ ++#define VS6624_CM_LOW_THR_MSB 0x1F03 /* low threshold for exposure MSB */ ++#define VS6624_CM_LOW_THR_LSB 0x1F04 /* low threshold for exposure LSB */ ++#define VS6624_CM_HIGH_THR_MSB 0x1F07 /* high threshold for exposure MSB */ ++#define VS6624_CM_HIGH_THR_LSB 0x1F08 /* high threshold for exposure LSB */ ++#define VS6624_CM_MIN_OUT_MSB 0x1F0B /* minimum possible damper output MSB */ ++#define VS6624_CM_MIN_OUT_LSB 0x1F0C /* minimum possible damper output LSB */ ++/* peaking control */ ++#define VS6624_PEAK_GAIN 0x2000 /* controls peaking gain */ ++#define VS6624_PEAK_G_DISABLE 0x2002 /* disable peak gain damping */ ++#define VS6624_PEAK_LOW_THR_G_MSB 0x2005 /* low threshold for exposure for gain MSB */ ++#define VS6624_PEAK_LOW_THR_G_LSB 0x2006 /* low threshold for exposure for gain LSB */ ++#define VS6624_PEAK_HIGH_THR_G_MSB 0x2009 /* high threshold for exposure for gain MSB */ ++#define VS6624_PEAK_HIGH_THR_G_LSB 0x200A /* high threshold for exposure for gain LSB */ ++#define VS6624_PEAK_MIN_OUT_G_MSB 0x200D /* minimum damper output for gain MSB */ ++#define VS6624_PEAK_MIN_OUT_G_LSB 0x200E /* minimum damper output for gain LSB */ ++#define VS6624_PEAK_LOW_THR 0x2010 /* adjust degree of coring */ ++#define VS6624_PEAK_C_DISABLE 0x2012 /* disable coring damping */ ++#define VS6624_PEAK_HIGH_THR 0x2014 /* adjust maximum gain */ ++#define VS6624_PEAK_LOW_THR_C_MSB 0x2017 /* low threshold for exposure for coring MSB */ ++#define VS6624_PEAK_LOW_THR_C_LSB 0x2018 /* low threshold for exposure for coring LSB */ ++#define VS6624_PEAK_HIGH_THR_C_MSB 0x201B /* high threshold for exposure for coring MSB */ ++#define VS6624_PEAK_HIGH_THR_C_LSB 0x201C /* high threshold for exposure for coring LSB */ ++#define VS6624_PEAK_MIN_OUT_C_MSB 0x201F /* minimum damper output for coring MSB */ ++#define VS6624_PEAK_MIN_OUT_C_LSB 0x2020 /* minimum damper output for coring LSB */ ++/* pipe 0 RGB to YUV matrix manual control */ ++#define VS6624_RYM0_MAN_CTRL 0x2180 /* enable manual RGB to YUV matrix */ ++#define VS6624_RYM0_W00_MSB 0x2183 /* row 0 column 0 of YUV matrix MSB */ ++#define VS6624_RYM0_W00_LSB 0x2184 /* row 0 column 0 of YUV matrix LSB */ ++#define VS6624_RYM0_W01_MSB 0x2187 /* row 0 column 1 of YUV matrix MSB */ ++#define VS6624_RYM0_W01_LSB 0x2188 /* row 0 column 1 of YUV matrix LSB */ ++#define VS6624_RYM0_W02_MSB 0x218C /* row 0 column 2 of YUV matrix MSB */ ++#define VS6624_RYM0_W02_LSB 0x218D /* row 0 column 2 of YUV matrix LSB */ ++#define VS6624_RYM0_W10_MSB 0x2190 /* row 1 column 0 of YUV matrix MSB */ ++#define VS6624_RYM0_W10_LSB 0x218F /* row 1 column 0 of YUV matrix LSB */ ++#define VS6624_RYM0_W11_MSB 0x2193 /* row 1 column 1 of YUV matrix MSB */ ++#define VS6624_RYM0_W11_LSB 0x2194 /* row 1 column 1 of YUV matrix LSB */ ++#define VS6624_RYM0_W12_MSB 0x2197 /* row 1 column 2 of YUV matrix MSB */ ++#define VS6624_RYM0_W12_LSB 0x2198 /* row 1 column 2 of YUV matrix LSB */ ++#define VS6624_RYM0_W20_MSB 0x219B /* row 2 column 0 of YUV matrix MSB */ ++#define VS6624_RYM0_W20_LSB 0x219C /* row 2 column 0 of YUV matrix LSB */ ++#define VS6624_RYM0_W21_MSB 0x21A0 /* row 2 column 1 of YUV matrix MSB */ ++#define VS6624_RYM0_W21_LSB 0x219F /* row 2 column 1 of YUV matrix LSB */ ++#define VS6624_RYM0_W22_MSB 0x21A3 /* row 2 column 2 of YUV matrix MSB */ ++#define VS6624_RYM0_W22_LSB 0x21A4 /* row 2 column 2 of YUV matrix LSB */ ++#define VS6624_RYM0_YINY_MSB 0x21A7 /* Y in Y MSB */ ++#define VS6624_RYM0_YINY_LSB 0x21A8 /* Y in Y LSB */ ++#define VS6624_RYM0_YINCB_MSB 0x21AB /* Y in Cb MSB */ ++#define VS6624_RYM0_YINCB_LSB 0x21AC /* Y in Cb LSB */ ++#define VS6624_RYM0_YINCR_MSB 0x21B0 /* Y in Cr MSB */ ++#define VS6624_RYM0_YINCR_LSB 0x21AF /* Y in Cr LSB */ ++/* pipe 1 RGB to YUV matrix manual control */ ++#define VS6624_RYM1_MAN_CTRL 0x2200 /* enable manual RGB to YUV matrix */ ++#define VS6624_RYM1_W00_MSB 0x2203 /* row 0 column 0 of YUV matrix MSB */ ++#define VS6624_RYM1_W00_LSB 0x2204 /* row 0 column 0 of YUV matrix LSB */ ++#define VS6624_RYM1_W01_MSB 0x2207 /* row 0 column 1 of YUV matrix MSB */ ++#define VS6624_RYM1_W01_LSB 0x2208 /* row 0 column 1 of YUV matrix LSB */ ++#define VS6624_RYM1_W02_MSB 0x220C /* row 0 column 2 of YUV matrix MSB */ ++#define VS6624_RYM1_W02_LSB 0x220D /* row 0 column 2 of YUV matrix LSB */ ++#define VS6624_RYM1_W10_MSB 0x2210 /* row 1 column 0 of YUV matrix MSB */ ++#define VS6624_RYM1_W10_LSB 0x220F /* row 1 column 0 of YUV matrix LSB */ ++#define VS6624_RYM1_W11_MSB 0x2213 /* row 1 column 1 of YUV matrix MSB */ ++#define VS6624_RYM1_W11_LSB 0x2214 /* row 1 column 1 of YUV matrix LSB */ ++#define VS6624_RYM1_W12_MSB 0x2217 /* row 1 column 2 of YUV matrix MSB */ ++#define VS6624_RYM1_W12_LSB 0x2218 /* row 1 column 2 of YUV matrix LSB */ ++#define VS6624_RYM1_W20_MSB 0x221B /* row 2 column 0 of YUV matrix MSB */ ++#define VS6624_RYM1_W20_LSB 0x221C /* row 2 column 0 of YUV matrix LSB */ ++#define VS6624_RYM1_W21_MSB 0x2220 /* row 2 column 1 of YUV matrix MSB */ ++#define VS6624_RYM1_W21_LSB 0x221F /* row 2 column 1 of YUV matrix LSB */ ++#define VS6624_RYM1_W22_MSB 0x2223 /* row 2 column 2 of YUV matrix MSB */ ++#define VS6624_RYM1_W22_LSB 0x2224 /* row 2 column 2 of YUV matrix LSB */ ++#define VS6624_RYM1_YINY_MSB 0x2227 /* Y in Y MSB */ ++#define VS6624_RYM1_YINY_LSB 0x2228 /* Y in Y LSB */ ++#define VS6624_RYM1_YINCB_MSB 0x222B /* Y in Cb MSB */ ++#define VS6624_RYM1_YINCB_LSB 0x222C /* Y in Cb LSB */ ++#define VS6624_RYM1_YINCR_MSB 0x2220 /* Y in Cr MSB */ ++#define VS6624_RYM1_YINCR_LSB 0x222F /* Y in Cr LSB */ ++/* pipe 0 gamma manual control */ ++#define VS6624_GAMMA_MAN_CTRL0 0x2280 /* enable manual gamma setup */ ++#define VS6624_GAMMA_PEAK_R0 0x2282 /* peaked red channel gamma value */ ++#define VS6624_GAMMA_PEAK_G0 0x2284 /* peaked green channel gamma value */ ++#define VS6624_GAMMA_PEAK_B0 0x2286 /* peaked blue channel gamma value */ ++#define VS6624_GAMMA_UNPEAK_R0 0x2288 /* unpeaked red channel gamma value */ ++#define VS6624_GAMMA_UNPEAK_G0 0x228A /* unpeaked green channel gamma value */ ++#define VS6624_GAMMA_UNPEAK_B0 0x228C /* unpeaked blue channel gamma value */ ++/* pipe 1 gamma manual control */ ++#define VS6624_GAMMA_MAN_CTRL1 0x2300 /* enable manual gamma setup */ ++#define VS6624_GAMMA_PEAK_R1 0x2302 /* peaked red channel gamma value */ ++#define VS6624_GAMMA_PEAK_G1 0x2304 /* peaked green channel gamma value */ ++#define VS6624_GAMMA_PEAK_B1 0x2306 /* peaked blue channel gamma value */ ++#define VS6624_GAMMA_UNPEAK_R1 0x2308 /* unpeaked red channel gamma value */ ++#define VS6624_GAMMA_UNPEAK_G1 0x230A /* unpeaked green channel gamma value */ ++#define VS6624_GAMMA_UNPEAK_B1 0x230C /* unpeaked blue channel gamma value */ ++/* fade to black */ ++#define VS6624_F2B_DISABLE 0x2480 /* disable fade to black */ ++#define VS6624_F2B_BLACK_VAL_MSB 0x2483 /* black value MSB */ ++#define VS6624_F2B_BLACK_VAL_LSB 0x2484 /* black value LSB */ ++#define VS6624_F2B_LOW_THR_MSB 0x2487 /* low threshold for exposure MSB */ ++#define VS6624_F2B_LOW_THR_LSB 0x2488 /* low threshold for exposure LSB */ ++#define VS6624_F2B_HIGH_THR_MSB 0x248B /* high threshold for exposure MSB */ ++#define VS6624_F2B_HIGH_THR_LSB 0x248C /* high threshold for exposure LSB */ ++#define VS6624_F2B_MIN_OUT_MSB 0x248F /* minimum damper output MSB */ ++#define VS6624_F2B_MIN_OUT_LSB 0x2490 /* minimum damper output LSB */ ++/* output formatter control */ ++#define VS6624_CODE_CK_EN 0x2580 /* code check enable */ ++#define VS6624_BLANK_FMT 0x2582 /* blank format */ ++#define VS6624_SYNC_CODE_SETUP 0x2584 /* sync code setup */ ++#define VS6624_HSYNC_SETUP 0x2586 /* H sync setup */ ++#define VS6624_VSYNC_SETUP 0x2588 /* V sync setup */ ++#define VS6624_PCLK_SETUP 0x258A /* PCLK setup */ ++#define VS6624_PCLK_EN 0x258C /* PCLK enable */ ++#define VS6624_OPF_SP_SETUP 0x258E /* output formatter sp setup */ ++#define VS6624_BLANK_DATA_MSB 0x2590 /* blank data MSB */ ++#define VS6624_BLANK_DATA_LSB 0x2592 /* blank data LSB */ ++#define VS6624_RGB_SETUP 0x2594 /* RGB setup */ ++#define VS6624_YUV_SETUP 0x2596 /* YUV setup */ ++#define VS6624_VSYNC_RIS_COARSE_H 0x2598 /* V sync rising coarse high */ ++#define VS6624_VSYNC_RIS_COARSE_L 0x259A /* V sync rising coarse low */ ++#define VS6624_VSYNC_RIS_FINE_H 0x259C /* V sync rising fine high */ ++#define VS6624_VSYNC_RIS_FINE_L 0x259E /* V sync rising fine low */ ++#define VS6624_VSYNC_FALL_COARSE_H 0x25A0 /* V sync falling coarse high */ ++#define VS6624_VSYNC_FALL_COARSE_L 0x25A2 /* V sync falling coarse low */ ++#define VS6624_VSYNC_FALL_FINE_H 0x25A4 /* V sync falling fine high */ ++#define VS6624_VSYNC_FALL_FINE_L 0x25A6 /* V sync falling fine low */ ++#define VS6624_HSYNC_RIS_H 0x25A8 /* H sync rising high */ ++#define VS6624_HSYNC_RIS_L 0x25AA /* H sync rising low */ ++#define VS6624_HSYNC_FALL_H 0x25AC /* H sync falling high */ ++#define VS6624_HSYNC_FALL_L 0x25AE /* H sync falling low */ ++#define VS6624_OUT_IF 0x25B0 /* output interface */ ++#define VS6624_CCP_EXT_DATA 0x25B2 /* CCP extra data */ ++/* NoRA controls */ ++#define VS6624_NORA_DISABLE 0x2600 /* NoRA control mode */ ++#define VS6624_NORA_USAGE 0x2602 /* usage */ ++#define VS6624_NORA_SPLIT_KN 0x2604 /* split kn */ ++#define VS6624_NORA_SPLIT_NI 0x2606 /* split ni */ ++#define VS6624_NORA_TIGHT_G 0x2608 /* tight green */ ++#define VS6624_NORA_DISABLE_NP 0x260A /* disable noro promoting */ ++#define VS6624_NORA_LOW_THR_MSB 0x260D /* low threshold for exposure MSB */ ++#define VS6624_NORA_LOW_THR_LSB 0x260E /* low threshold for exposure LSB */ ++#define VS6624_NORA_HIGH_THR_MSB 0x2611 /* high threshold for exposure MSB */ ++#define VS6624_NORA_HIGH_THR_LSB 0x2612 /* high threshold for exposure LSB */ ++#define VS6624_NORA_MIN_OUT_MSB 0x2615 /* minimum damper output MSB */ ++#define VS6624_NORA_MIN_OUT_LSB 0x2616 /* minimum damper output LSB */ ++ ++#endif +Index: linux-3.3.x86_64/drivers/media/video/blackfin/Kconfig +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/blackfin/Kconfig +@@ -0,0 +1,10 @@ ++config VIDEO_BLACKFIN_CAPTURE ++ tristate "Blackfin Video Capture Driver" ++ depends on VIDEO_V4L2 && BLACKFIN && I2C ++ select VIDEOBUF2_DMA_CONTIG ++ help ++ V4L2 bridge driver for Blackfin video capture device. ++ Choose PPI or EPPI as its interface. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called bfin_video_capture. +Index: linux-3.3.x86_64/drivers/media/video/blackfin/Makefile +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/blackfin/Makefile +@@ -0,0 +1,2 @@ ++bfin_video_capture-objs := bfin_capture.o ppi.o ++obj-$(CONFIG_VIDEO_BLACKFIN_CAPTURE) += bfin_video_capture.o +Index: linux-3.3.x86_64/drivers/media/video/blackfin/bfin_capture.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/blackfin/bfin_capture.c +@@ -0,0 +1,1059 @@ ++/* ++ * Analog Devices video capture driver ++ * ++ * Copyright (c) 2011 Analog Devices Inc. ++ * ++ * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++#define CAPTURE_DRV_NAME "bfin_capture" ++#define BCAP_MIN_NUM_BUF 2 ++ ++struct bcap_format { ++ char *desc; ++ u32 pixelformat; ++ enum v4l2_mbus_pixelcode mbus_code; ++ int bpp; /* bits per pixel */ ++}; ++ ++struct bcap_buffer { ++ struct vb2_buffer vb; ++ struct list_head list; ++}; ++ ++struct bcap_device { ++ /* capture device instance */ ++ struct v4l2_device v4l2_dev; ++ /* v4l2 control handler */ ++ struct v4l2_ctrl_handler ctrl_handler; ++ /* device node data */ ++ struct video_device *video_dev; ++ /* sub device instance */ ++ struct v4l2_subdev *sd; ++ /* capture config */ ++ struct bfin_capture_config *cfg; ++ /* ppi interface */ ++ struct ppi_if *ppi; ++ /* current input */ ++ unsigned int cur_input; ++ /* current selected standard */ ++ v4l2_std_id std; ++ /* used to store pixel format */ ++ struct v4l2_pix_format fmt; ++ /* bits per pixel*/ ++ int bpp; ++ /* used to store sensor supported format */ ++ struct bcap_format *sensor_formats; ++ /* number of sensor formats array */ ++ int num_sensor_formats; ++ /* pointing to current video buffer */ ++ struct bcap_buffer *cur_frm; ++ /* pointing to next video buffer */ ++ struct bcap_buffer *next_frm; ++ /* buffer queue used in videobuf2 */ ++ struct vb2_queue buffer_queue; ++ /* allocator-specific contexts for each plane */ ++ struct vb2_alloc_ctx *alloc_ctx; ++ /* queue of filled frames */ ++ struct list_head dma_queue; ++ /* used in videobuf2 callback */ ++ spinlock_t lock; ++ /* used to access capture device */ ++ struct mutex mutex; ++ /* used to wait ppi to complete one transfer */ ++ struct completion comp; ++ /* prepare to stop */ ++ bool stop; ++}; ++ ++struct bcap_fh { ++ struct v4l2_fh fh; ++ /* indicates whether this file handle is doing IO */ ++ bool io_allowed; ++}; ++ ++static const struct bcap_format bcap_formats[] = { ++ { ++ .desc = "YCbCr 4:2:2 Interleaved UYVY", ++ .pixelformat = V4L2_PIX_FMT_UYVY, ++ .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, ++ .bpp = 16, ++ }, ++ { ++ .desc = "YCbCr 4:2:2 Interleaved YUYV", ++ .pixelformat = V4L2_PIX_FMT_YUYV, ++ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, ++ .bpp = 16, ++ }, ++ { ++ .desc = "RGB 565", ++ .pixelformat = V4L2_PIX_FMT_RGB565, ++ .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, ++ .bpp = 16, ++ }, ++ { ++ .desc = "RGB 444", ++ .pixelformat = V4L2_PIX_FMT_RGB444, ++ .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, ++ .bpp = 16, ++ }, ++ ++}; ++#define BCAP_MAX_FMTS ARRAY_SIZE(bcap_formats) ++ ++static irqreturn_t bcap_isr(int irq, void *dev_id); ++ ++static struct bcap_buffer *to_bcap_vb(struct vb2_buffer *vb) ++{ ++ return container_of(vb, struct bcap_buffer, vb); ++} ++ ++static int bcap_init_sensor_formats(struct bcap_device *bcap_dev) ++{ ++ enum v4l2_mbus_pixelcode code; ++ struct bcap_format *sf; ++ unsigned int num_formats = 0; ++ int i, j; ++ ++ while (!v4l2_subdev_call(bcap_dev->sd, video, ++ enum_mbus_fmt, num_formats, &code)) ++ num_formats++; ++ if (!num_formats) ++ return -ENXIO; ++ ++ sf = kzalloc(num_formats * sizeof(*sf), GFP_KERNEL); ++ if (!sf) ++ return -ENOMEM; ++ ++ for (i = 0; i < num_formats; i++) { ++ v4l2_subdev_call(bcap_dev->sd, video, ++ enum_mbus_fmt, i, &code); ++ for (j = 0; j < BCAP_MAX_FMTS; j++) ++ if (code == bcap_formats[j].mbus_code) ++ break; ++ if (j == BCAP_MAX_FMTS) { ++ /* we don't allow this sensor working with our bridge */ ++ kfree(sf); ++ return -EINVAL; ++ } ++ sf[i] = bcap_formats[j]; ++ } ++ bcap_dev->sensor_formats = sf; ++ bcap_dev->num_sensor_formats = num_formats; ++ return 0; ++} ++ ++static void bcap_free_sensor_formats(struct bcap_device *bcap_dev) ++{ ++ bcap_dev->num_sensor_formats = 0; ++ kfree(bcap_dev->sensor_formats); ++ bcap_dev->sensor_formats = NULL; ++} ++ ++static int bcap_open(struct file *file) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct video_device *vfd = bcap_dev->video_dev; ++ struct bcap_fh *bcap_fh; ++ ++ if (!bcap_dev->sd) { ++ v4l2_err(&bcap_dev->v4l2_dev, "No sub device registered\n"); ++ return -ENODEV; ++ } ++ ++ bcap_fh = kzalloc(sizeof(*bcap_fh), GFP_KERNEL); ++ if (!bcap_fh) { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "unable to allocate memory for file handle object\n"); ++ return -ENOMEM; ++ } ++ ++ v4l2_fh_init(&bcap_fh->fh, vfd); ++ ++ /* store pointer to v4l2_fh in private_data member of file */ ++ file->private_data = &bcap_fh->fh; ++ v4l2_fh_add(&bcap_fh->fh); ++ bcap_fh->io_allowed = false; ++ return 0; ++} ++ ++static int bcap_release(struct file *file) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct v4l2_fh *fh = file->private_data; ++ struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); ++ ++ /* if this instance is doing IO */ ++ if (bcap_fh->io_allowed) ++ vb2_queue_release(&bcap_dev->buffer_queue); ++ ++ file->private_data = NULL; ++ v4l2_fh_del(&bcap_fh->fh); ++ v4l2_fh_exit(&bcap_fh->fh); ++ kfree(bcap_fh); ++ return 0; ++} ++ ++static int bcap_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ return vb2_mmap(&bcap_dev->buffer_queue, vma); ++} ++ ++#ifndef CONFIG_MMU ++static unsigned long bcap_get_unmapped_area(struct file *file, ++ unsigned long addr, ++ unsigned long len, ++ unsigned long pgoff, ++ unsigned long flags) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ return vb2_get_unmapped_area(&bcap_dev->buffer_queue, ++ addr, ++ len, ++ pgoff, ++ flags); ++} ++#endif ++ ++static unsigned int bcap_poll(struct file *file, poll_table *wait) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ return vb2_poll(&bcap_dev->buffer_queue, file, wait); ++} ++ ++static int bcap_queue_setup(struct vb2_queue *vq, ++ const struct v4l2_format *fmt, ++ unsigned int *nbuffers, unsigned int *nplanes, ++ unsigned int sizes[], void *alloc_ctxs[]) ++{ ++ struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); ++ ++ if (*nbuffers < BCAP_MIN_NUM_BUF) ++ *nbuffers = BCAP_MIN_NUM_BUF; ++ ++ *nplanes = 1; ++ sizes[0] = bcap_dev->fmt.sizeimage; ++ alloc_ctxs[0] = bcap_dev->alloc_ctx; ++ ++ return 0; ++} ++ ++static int bcap_buffer_init(struct vb2_buffer *vb) ++{ ++ struct bcap_buffer *buf = to_bcap_vb(vb); ++ ++ INIT_LIST_HEAD(&buf->list); ++ return 0; ++} ++ ++static int bcap_buffer_prepare(struct vb2_buffer *vb) ++{ ++ struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); ++ struct bcap_buffer *buf = to_bcap_vb(vb); ++ unsigned long size; ++ ++ size = bcap_dev->fmt.sizeimage; ++ if (vb2_plane_size(vb, 0) < size) { ++ v4l2_err(&bcap_dev->v4l2_dev, "buffer too small (%lu < %lu)\n", ++ vb2_plane_size(vb, 0), size); ++ return -EINVAL; ++ } ++ vb2_set_plane_payload(&buf->vb, 0, size); ++ ++ return 0; ++} ++ ++static void bcap_buffer_queue(struct vb2_buffer *vb) ++{ ++ struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); ++ struct bcap_buffer *buf = to_bcap_vb(vb); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&bcap_dev->lock, flags); ++ list_add_tail(&buf->list, &bcap_dev->dma_queue); ++ spin_unlock_irqrestore(&bcap_dev->lock, flags); ++} ++ ++static void bcap_buffer_cleanup(struct vb2_buffer *vb) ++{ ++ struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); ++ struct bcap_buffer *buf = to_bcap_vb(vb); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&bcap_dev->lock, flags); ++ list_del_init(&buf->list); ++ spin_unlock_irqrestore(&bcap_dev->lock, flags); ++} ++ ++static void bcap_lock(struct vb2_queue *vq) ++{ ++ struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); ++ mutex_lock(&bcap_dev->mutex); ++} ++ ++static void bcap_unlock(struct vb2_queue *vq) ++{ ++ struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); ++ mutex_unlock(&bcap_dev->mutex); ++} ++ ++static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count) ++{ ++ struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); ++ struct ppi_if *ppi = bcap_dev->ppi; ++ struct ppi_params params; ++ int ret; ++ ++ /* enable streamon on the sub device */ ++ ret = v4l2_subdev_call(bcap_dev->sd, video, s_stream, 1); ++ if (ret && (ret != -ENOIOCTLCMD)) { ++ v4l2_err(&bcap_dev->v4l2_dev, "stream on failed in subdev\n"); ++ return ret; ++ } ++ ++ /* set ppi params */ ++ params.width = bcap_dev->fmt.width; ++ params.height = bcap_dev->fmt.height; ++ params.bpp = bcap_dev->bpp; ++ params.ppi_control = bcap_dev->cfg->ppi_control; ++ params.int_mask = bcap_dev->cfg->int_mask; ++ params.blank_clocks = bcap_dev->cfg->blank_clocks; ++ ret = ppi->ops->set_params(ppi, ¶ms); ++ if (ret < 0) { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "Error in setting ppi params\n"); ++ return ret; ++ } ++ ++ /* attach ppi DMA irq handler */ ++ ret = ppi->ops->attach_irq(ppi, bcap_isr); ++ if (ret < 0) { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "Error in attaching interrupt handler\n"); ++ return ret; ++ } ++ ++ INIT_COMPLETION(bcap_dev->comp); ++ bcap_dev->stop = false; ++ return 0; ++} ++ ++static int bcap_stop_streaming(struct vb2_queue *vq) ++{ ++ struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); ++ struct ppi_if *ppi = bcap_dev->ppi; ++ int ret; ++ ++ if (!vb2_is_streaming(vq)) ++ return 0; ++ ++ bcap_dev->stop = true; ++ wait_for_completion(&bcap_dev->comp); ++ ppi->ops->stop(ppi); ++ ppi->ops->detach_irq(ppi); ++ ret = v4l2_subdev_call(bcap_dev->sd, video, s_stream, 0); ++ if (ret && (ret != -ENOIOCTLCMD)) ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "stream off failed in subdev\n"); ++ ++ /* release all active buffers */ ++ while (!list_empty(&bcap_dev->dma_queue)) { ++ bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, ++ struct bcap_buffer, list); ++ list_del(&bcap_dev->next_frm->list); ++ vb2_buffer_done(&bcap_dev->next_frm->vb, VB2_BUF_STATE_ERROR); ++ } ++ return 0; ++} ++ ++static struct vb2_ops bcap_video_qops = { ++ .queue_setup = bcap_queue_setup, ++ .buf_init = bcap_buffer_init, ++ .buf_prepare = bcap_buffer_prepare, ++ .buf_cleanup = bcap_buffer_cleanup, ++ .buf_queue = bcap_buffer_queue, ++ .wait_prepare = bcap_unlock, ++ .wait_finish = bcap_lock, ++ .start_streaming = bcap_start_streaming, ++ .stop_streaming = bcap_stop_streaming, ++}; ++ ++static int bcap_reqbufs(struct file *file, void *priv, ++ struct v4l2_requestbuffers *req_buf) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct vb2_queue *vq = &bcap_dev->buffer_queue; ++ struct v4l2_fh *fh = file->private_data; ++ struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); ++ ++ if (vb2_is_busy(vq)) ++ return -EBUSY; ++ ++ bcap_fh->io_allowed = true; ++ ++ return vb2_reqbufs(vq, req_buf); ++} ++ ++static int bcap_querybuf(struct file *file, void *priv, ++ struct v4l2_buffer *buf) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ return vb2_querybuf(&bcap_dev->buffer_queue, buf); ++} ++ ++static int bcap_qbuf(struct file *file, void *priv, ++ struct v4l2_buffer *buf) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct v4l2_fh *fh = file->private_data; ++ struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); ++ ++ if (!bcap_fh->io_allowed) ++ return -EBUSY; ++ ++ return vb2_qbuf(&bcap_dev->buffer_queue, buf); ++} ++ ++static int bcap_dqbuf(struct file *file, void *priv, ++ struct v4l2_buffer *buf) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct v4l2_fh *fh = file->private_data; ++ struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); ++ ++ if (!bcap_fh->io_allowed) ++ return -EBUSY; ++ ++ return vb2_dqbuf(&bcap_dev->buffer_queue, ++ buf, file->f_flags & O_NONBLOCK); ++} ++ ++static irqreturn_t bcap_isr(int irq, void *dev_id) ++{ ++ struct ppi_if *ppi = dev_id; ++ struct bcap_device *bcap_dev = ppi->priv; ++ struct timeval timevalue; ++ struct vb2_buffer *vb = &bcap_dev->cur_frm->vb; ++ dma_addr_t addr; ++ ++ spin_lock(&bcap_dev->lock); ++ ++ if (bcap_dev->cur_frm != bcap_dev->next_frm) { ++ do_gettimeofday(&timevalue); ++ vb->v4l2_buf.timestamp = timevalue; ++ vb2_buffer_done(vb, VB2_BUF_STATE_DONE); ++ bcap_dev->cur_frm = bcap_dev->next_frm; ++ } ++ ++ ppi->ops->stop(ppi); ++ ++ if (bcap_dev->stop) { ++ complete(&bcap_dev->comp); ++ } else { ++ if (!list_empty(&bcap_dev->dma_queue)) { ++ bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, ++ struct bcap_buffer, list); ++ list_del(&bcap_dev->next_frm->list); ++ addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->next_frm->vb, 0); ++ ppi->ops->update_addr(ppi, (unsigned long)addr); ++ } ++ ppi->ops->start(ppi); ++ } ++ ++ spin_unlock(&bcap_dev->lock); ++ ++ return IRQ_HANDLED; ++} ++ ++static int bcap_streamon(struct file *file, void *priv, ++ enum v4l2_buf_type buf_type) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct bcap_fh *fh = file->private_data; ++ struct ppi_if *ppi = bcap_dev->ppi; ++ dma_addr_t addr; ++ int ret; ++ ++ if (!fh->io_allowed) ++ return -EBUSY; ++ ++ /* call streamon to start streaming in videobuf */ ++ ret = vb2_streamon(&bcap_dev->buffer_queue, buf_type); ++ if (ret) ++ return ret; ++ ++ /* if dma queue is empty, return error */ ++ if (list_empty(&bcap_dev->dma_queue)) { ++ v4l2_err(&bcap_dev->v4l2_dev, "dma queue is empty\n"); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ /* get the next frame from the dma queue */ ++ bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, ++ struct bcap_buffer, list); ++ bcap_dev->cur_frm = bcap_dev->next_frm; ++ /* remove buffer from the dma queue */ ++ list_del(&bcap_dev->cur_frm->list); ++ addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0); ++ /* update DMA address */ ++ ppi->ops->update_addr(ppi, (unsigned long)addr); ++ /* enable ppi */ ++ ppi->ops->start(ppi); ++ ++ return 0; ++err: ++ vb2_streamoff(&bcap_dev->buffer_queue, buf_type); ++ return ret; ++} ++ ++static int bcap_streamoff(struct file *file, void *priv, ++ enum v4l2_buf_type buf_type) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct bcap_fh *fh = file->private_data; ++ ++ if (!fh->io_allowed) ++ return -EBUSY; ++ ++ return vb2_streamoff(&bcap_dev->buffer_queue, buf_type); ++} ++ ++static int bcap_querystd(struct file *file, void *priv, v4l2_std_id *std) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ return v4l2_subdev_call(bcap_dev->sd, video, querystd, std); ++} ++ ++static int bcap_g_std(struct file *file, void *priv, v4l2_std_id *std) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ *std = bcap_dev->std; ++ return 0; ++} ++ ++static int bcap_s_std(struct file *file, void *priv, v4l2_std_id *std) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ int ret; ++ ++ if (vb2_is_busy(&bcap_dev->buffer_queue)) ++ return -EBUSY; ++ ++ ret = v4l2_subdev_call(bcap_dev->sd, core, s_std, *std); ++ if (ret < 0) ++ return ret; ++ ++ bcap_dev->std = *std; ++ return 0; ++} ++ ++static int bcap_enum_input(struct file *file, void *priv, ++ struct v4l2_input *input) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct bfin_capture_config *config = bcap_dev->cfg; ++ int ret; ++ u32 status; ++ ++ if (input->index >= config->num_inputs) ++ return -EINVAL; ++ ++ *input = config->inputs[input->index]; ++ /* get input status */ ++ ret = v4l2_subdev_call(bcap_dev->sd, video, g_input_status, &status); ++ if (!ret) ++ input->status = status; ++ return 0; ++} ++ ++static int bcap_g_input(struct file *file, void *priv, unsigned int *index) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ *index = bcap_dev->cur_input; ++ return 0; ++} ++ ++static int bcap_s_input(struct file *file, void *priv, unsigned int index) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct bfin_capture_config *config = bcap_dev->cfg; ++ struct bcap_route *route; ++ int ret; ++ ++ if (vb2_is_busy(&bcap_dev->buffer_queue)) ++ return -EBUSY; ++ ++ if (index >= config->num_inputs) ++ return -EINVAL; ++ ++ route = &config->routes[index]; ++ ret = v4l2_subdev_call(bcap_dev->sd, video, s_routing, ++ route->input, route->output, 0); ++ if ((ret < 0) && (ret != -ENOIOCTLCMD)) { ++ v4l2_err(&bcap_dev->v4l2_dev, "Failed to set input\n"); ++ return ret; ++ } ++ bcap_dev->cur_input = index; ++ return 0; ++} ++ ++static int bcap_try_format(struct bcap_device *bcap, ++ struct v4l2_pix_format *pixfmt, ++ enum v4l2_mbus_pixelcode *mbus_code, ++ int *bpp) ++{ ++ struct bcap_format *sf = bcap->sensor_formats; ++ struct bcap_format *fmt = NULL; ++ struct v4l2_mbus_framefmt mbus_fmt; ++ int ret, i; ++ ++ for (i = 0; i < bcap->num_sensor_formats; i++) { ++ fmt = &sf[i]; ++ if (pixfmt->pixelformat == fmt->pixelformat) ++ break; ++ } ++ if (i == bcap->num_sensor_formats) ++ fmt = &sf[0]; ++ ++ if (mbus_code) ++ *mbus_code = fmt->mbus_code; ++ if (bpp) ++ *bpp = fmt->bpp; ++ v4l2_fill_mbus_format(&mbus_fmt, pixfmt, fmt->mbus_code); ++ ret = v4l2_subdev_call(bcap->sd, video, ++ try_mbus_fmt, &mbus_fmt); ++ if (ret < 0) ++ return ret; ++ v4l2_fill_pix_format(pixfmt, &mbus_fmt); ++ pixfmt->bytesperline = pixfmt->width * fmt->bpp / 8; ++ pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; ++ return 0; ++} ++ ++static int bcap_enum_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_fmtdesc *fmt) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct bcap_format *sf = bcap_dev->sensor_formats; ++ ++ if (fmt->index >= bcap_dev->num_sensor_formats) ++ return -EINVAL; ++ ++ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ strlcpy(fmt->description, ++ sf[fmt->index].desc, ++ sizeof(fmt->description)); ++ fmt->pixelformat = sf[fmt->index].pixelformat; ++ return 0; ++} ++ ++static int bcap_try_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *fmt) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; ++ ++ return bcap_try_format(bcap_dev, pixfmt, NULL, NULL); ++} ++ ++static int bcap_g_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *fmt) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ fmt->fmt.pix = bcap_dev->fmt; ++ return 0; ++} ++ ++static int bcap_s_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *fmt) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct v4l2_mbus_framefmt mbus_fmt; ++ enum v4l2_mbus_pixelcode mbus_code; ++ struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; ++ int ret, bpp; ++ ++ if (vb2_is_busy(&bcap_dev->buffer_queue)) ++ return -EBUSY; ++ ++ /* see if format works */ ++ ret = bcap_try_format(bcap_dev, pixfmt, &mbus_code, &bpp); ++ if (ret < 0) ++ return ret; ++ ++ v4l2_fill_mbus_format(&mbus_fmt, pixfmt, mbus_code); ++ ret = v4l2_subdev_call(bcap_dev->sd, video, s_mbus_fmt, &mbus_fmt); ++ if (ret < 0) ++ return ret; ++ bcap_dev->fmt = *pixfmt; ++ bcap_dev->bpp = bpp; ++ return 0; ++} ++ ++static int bcap_querycap(struct file *file, void *priv, ++ struct v4l2_capability *cap) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; ++ strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); ++ strlcpy(cap->bus_info, "Blackfin Platform", sizeof(cap->bus_info)); ++ strlcpy(cap->card, bcap_dev->cfg->card_name, sizeof(cap->card)); ++ return 0; ++} ++ ++static int bcap_g_parm(struct file *file, void *fh, ++ struct v4l2_streamparm *a) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ return v4l2_subdev_call(bcap_dev->sd, video, g_parm, a); ++} ++ ++static int bcap_s_parm(struct file *file, void *fh, ++ struct v4l2_streamparm *a) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ return v4l2_subdev_call(bcap_dev->sd, video, s_parm, a); ++} ++ ++static int bcap_g_chip_ident(struct file *file, void *priv, ++ struct v4l2_dbg_chip_ident *chip) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ chip->ident = V4L2_IDENT_NONE; ++ chip->revision = 0; ++ if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && ++ chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) ++ return -EINVAL; ++ ++ return v4l2_subdev_call(bcap_dev->sd, core, ++ g_chip_ident, chip); ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int bcap_dbg_g_register(struct file *file, void *priv, ++ struct v4l2_dbg_register *reg) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ return v4l2_subdev_call(bcap_dev->sd, core, ++ g_register, reg); ++} ++ ++static int bcap_dbg_s_register(struct file *file, void *priv, ++ struct v4l2_dbg_register *reg) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ return v4l2_subdev_call(bcap_dev->sd, core, ++ s_register, reg); ++} ++#endif ++ ++static int bcap_log_status(struct file *file, void *priv) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ /* status for sub devices */ ++ v4l2_device_call_all(&bcap_dev->v4l2_dev, 0, core, log_status); ++ return 0; ++} ++ ++static const struct v4l2_ioctl_ops bcap_ioctl_ops = { ++ .vidioc_querycap = bcap_querycap, ++ .vidioc_g_fmt_vid_cap = bcap_g_fmt_vid_cap, ++ .vidioc_enum_fmt_vid_cap = bcap_enum_fmt_vid_cap, ++ .vidioc_s_fmt_vid_cap = bcap_s_fmt_vid_cap, ++ .vidioc_try_fmt_vid_cap = bcap_try_fmt_vid_cap, ++ .vidioc_enum_input = bcap_enum_input, ++ .vidioc_g_input = bcap_g_input, ++ .vidioc_s_input = bcap_s_input, ++ .vidioc_querystd = bcap_querystd, ++ .vidioc_s_std = bcap_s_std, ++ .vidioc_g_std = bcap_g_std, ++ .vidioc_reqbufs = bcap_reqbufs, ++ .vidioc_querybuf = bcap_querybuf, ++ .vidioc_qbuf = bcap_qbuf, ++ .vidioc_dqbuf = bcap_dqbuf, ++ .vidioc_streamon = bcap_streamon, ++ .vidioc_streamoff = bcap_streamoff, ++ .vidioc_g_parm = bcap_g_parm, ++ .vidioc_s_parm = bcap_s_parm, ++ .vidioc_g_chip_ident = bcap_g_chip_ident, ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .vidioc_g_register = bcap_dbg_g_register, ++ .vidioc_s_register = bcap_dbg_s_register, ++#endif ++ .vidioc_log_status = bcap_log_status, ++}; ++ ++static struct v4l2_file_operations bcap_fops = { ++ .owner = THIS_MODULE, ++ .open = bcap_open, ++ .release = bcap_release, ++ .unlocked_ioctl = video_ioctl2, ++ .mmap = bcap_mmap, ++#ifndef CONFIG_MMU ++ .get_unmapped_area = bcap_get_unmapped_area, ++#endif ++ .poll = bcap_poll ++}; ++ ++static int __devinit bcap_probe(struct platform_device *pdev) ++{ ++ struct bcap_device *bcap_dev; ++ struct video_device *vfd; ++ struct i2c_adapter *i2c_adap; ++ struct bfin_capture_config *config; ++ struct vb2_queue *q; ++ int ret; ++ ++ config = pdev->dev.platform_data; ++ if (!config) { ++ v4l2_err(pdev->dev.driver, "Unable to get board config\n"); ++ return -ENODEV; ++ } ++ ++ bcap_dev = kzalloc(sizeof(*bcap_dev), GFP_KERNEL); ++ if (!bcap_dev) { ++ v4l2_err(pdev->dev.driver, "Unable to alloc bcap_dev\n"); ++ return -ENOMEM; ++ } ++ ++ bcap_dev->cfg = config; ++ ++ bcap_dev->ppi = ppi_create_instance(config->ppi_info); ++ if (!bcap_dev->ppi) { ++ v4l2_err(pdev->dev.driver, "Unable to create ppi\n"); ++ ret = -ENODEV; ++ goto err_free_dev; ++ } ++ bcap_dev->ppi->priv = bcap_dev; ++ ++ bcap_dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); ++ if (IS_ERR(bcap_dev->alloc_ctx)) { ++ ret = PTR_ERR(bcap_dev->alloc_ctx); ++ goto err_free_ppi; ++ } ++ ++ vfd = video_device_alloc(); ++ if (!vfd) { ++ ret = -ENOMEM; ++ v4l2_err(pdev->dev.driver, "Unable to alloc video device\n"); ++ goto err_cleanup_ctx; ++ } ++ ++ /* initialize field of video device */ ++ vfd->release = video_device_release; ++ vfd->fops = &bcap_fops; ++ vfd->ioctl_ops = &bcap_ioctl_ops; ++ vfd->tvnorms = 0; ++ vfd->v4l2_dev = &bcap_dev->v4l2_dev; ++ set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); ++ strncpy(vfd->name, CAPTURE_DRV_NAME, sizeof(vfd->name)); ++ bcap_dev->video_dev = vfd; ++ ++ ret = v4l2_device_register(&pdev->dev, &bcap_dev->v4l2_dev); ++ if (ret) { ++ v4l2_err(pdev->dev.driver, ++ "Unable to register v4l2 device\n"); ++ goto err_release_vdev; ++ } ++ v4l2_info(&bcap_dev->v4l2_dev, "v4l2 device registered\n"); ++ ++ bcap_dev->v4l2_dev.ctrl_handler = &bcap_dev->ctrl_handler; ++ ret = v4l2_ctrl_handler_init(&bcap_dev->ctrl_handler, 0); ++ if (ret) { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "Unable to init control handler\n"); ++ goto err_unreg_v4l2; ++ } ++ ++ spin_lock_init(&bcap_dev->lock); ++ /* initialize queue */ ++ q = &bcap_dev->buffer_queue; ++ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ q->io_modes = VB2_MMAP; ++ q->drv_priv = bcap_dev; ++ q->buf_struct_size = sizeof(struct bcap_buffer); ++ q->ops = &bcap_video_qops; ++ q->mem_ops = &vb2_dma_contig_memops; ++ ++ vb2_queue_init(q); ++ ++ mutex_init(&bcap_dev->mutex); ++ init_completion(&bcap_dev->comp); ++ ++ /* init video dma queues */ ++ INIT_LIST_HEAD(&bcap_dev->dma_queue); ++ ++ vfd->lock = &bcap_dev->mutex; ++ ++ /* register video device */ ++ ret = video_register_device(bcap_dev->video_dev, VFL_TYPE_GRABBER, -1); ++ if (ret) { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "Unable to register video device\n"); ++ goto err_free_handler; ++ } ++ video_set_drvdata(bcap_dev->video_dev, bcap_dev); ++ v4l2_info(&bcap_dev->v4l2_dev, "video device registered as: %s\n", ++ video_device_node_name(vfd)); ++ ++ /* load up the subdevice */ ++ i2c_adap = i2c_get_adapter(config->i2c_adapter_id); ++ if (!i2c_adap) { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "Unable to find i2c adapter\n"); ++ goto err_unreg_vdev; ++ ++ } ++ bcap_dev->sd = v4l2_i2c_new_subdev_board(&bcap_dev->v4l2_dev, ++ i2c_adap, ++ &config->board_info, ++ NULL); ++ if (bcap_dev->sd) { ++ int i; ++ /* update tvnorms from the sub devices */ ++ for (i = 0; i < config->num_inputs; i++) ++ vfd->tvnorms |= config->inputs[i].std; ++ } else { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "Unable to register sub device\n"); ++ goto err_unreg_vdev; ++ } ++ ++ v4l2_info(&bcap_dev->v4l2_dev, "v4l2 sub device registered\n"); ++ ++ /* now we can probe the default state */ ++ if (vfd->tvnorms) { ++ v4l2_std_id std; ++ ret = v4l2_subdev_call(bcap_dev->sd, core, g_std, &std); ++ if (ret) { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "Unable to get std\n"); ++ goto err_unreg_vdev; ++ } ++ bcap_dev->std = std; ++ } ++ ret = bcap_init_sensor_formats(bcap_dev); ++ if (ret) { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "Unable to create sensor formats table\n"); ++ goto err_unreg_vdev; ++ } ++ return 0; ++err_unreg_vdev: ++ video_unregister_device(bcap_dev->video_dev); ++ bcap_dev->video_dev = NULL; ++err_free_handler: ++ v4l2_ctrl_handler_free(&bcap_dev->ctrl_handler); ++err_unreg_v4l2: ++ v4l2_device_unregister(&bcap_dev->v4l2_dev); ++err_release_vdev: ++ if (bcap_dev->video_dev) ++ video_device_release(bcap_dev->video_dev); ++err_cleanup_ctx: ++ vb2_dma_contig_cleanup_ctx(bcap_dev->alloc_ctx); ++err_free_ppi: ++ ppi_delete_instance(bcap_dev->ppi); ++err_free_dev: ++ kfree(bcap_dev); ++ return ret; ++} ++ ++static int __devexit bcap_remove(struct platform_device *pdev) ++{ ++ struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); ++ struct bcap_device *bcap_dev = container_of(v4l2_dev, ++ struct bcap_device, v4l2_dev); ++ ++ bcap_free_sensor_formats(bcap_dev); ++ video_unregister_device(bcap_dev->video_dev); ++ v4l2_ctrl_handler_free(&bcap_dev->ctrl_handler); ++ v4l2_device_unregister(v4l2_dev); ++ vb2_dma_contig_cleanup_ctx(bcap_dev->alloc_ctx); ++ ppi_delete_instance(bcap_dev->ppi); ++ kfree(bcap_dev); ++ return 0; ++} ++ ++static struct platform_driver bcap_driver = { ++ .driver = { ++ .name = CAPTURE_DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++ .probe = bcap_probe, ++ .remove = __devexit_p(bcap_remove), ++}; ++ ++static __init int bcap_init(void) ++{ ++ return platform_driver_register(&bcap_driver); ++} ++ ++static __exit void bcap_exit(void) ++{ ++ platform_driver_unregister(&bcap_driver); ++} ++ ++module_init(bcap_init); ++module_exit(bcap_exit); ++ ++MODULE_DESCRIPTION("Analog Devices blackfin video capture driver"); ++MODULE_AUTHOR("Scott Jiang "); ++MODULE_LICENSE("GPL v2"); +Index: linux-3.3.x86_64/drivers/media/video/blackfin/ppi.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/blackfin/ppi.c +@@ -0,0 +1,271 @@ ++/* ++ * ppi.c Analog Devices Parallel Peripheral Interface driver ++ * ++ * Copyright (c) 2011 Analog Devices Inc. ++ * ++ * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++static int ppi_attach_irq(struct ppi_if *ppi, irq_handler_t handler); ++static void ppi_detach_irq(struct ppi_if *ppi); ++static int ppi_start(struct ppi_if *ppi); ++static int ppi_stop(struct ppi_if *ppi); ++static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params); ++static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr); ++ ++static const struct ppi_ops ppi_ops = { ++ .attach_irq = ppi_attach_irq, ++ .detach_irq = ppi_detach_irq, ++ .start = ppi_start, ++ .stop = ppi_stop, ++ .set_params = ppi_set_params, ++ .update_addr = ppi_update_addr, ++}; ++ ++static irqreturn_t ppi_irq_err(int irq, void *dev_id) ++{ ++ struct ppi_if *ppi = dev_id; ++ const struct ppi_info *info = ppi->info; ++ ++ switch (info->type) { ++ case PPI_TYPE_PPI: ++ { ++ struct bfin_ppi_regs *reg = info->base; ++ unsigned short status; ++ ++ /* register on bf561 is cleared when read ++ * others are W1C ++ */ ++ status = bfin_read16(®->status); ++ bfin_write16(®->status, 0xff00); ++ break; ++ } ++ case PPI_TYPE_EPPI: ++ { ++ struct bfin_eppi_regs *reg = info->base; ++ bfin_write16(®->status, 0xffff); ++ break; ++ } ++ default: ++ break; ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static int ppi_attach_irq(struct ppi_if *ppi, irq_handler_t handler) ++{ ++ const struct ppi_info *info = ppi->info; ++ int ret; ++ ++ ret = request_dma(info->dma_ch, "PPI_DMA"); ++ ++ if (ret) { ++ pr_err("Unable to allocate DMA channel for PPI\n"); ++ return ret; ++ } ++ set_dma_callback(info->dma_ch, handler, ppi); ++ ++ if (ppi->err_int) { ++ ret = request_irq(info->irq_err, ppi_irq_err, 0, "PPI ERROR", ppi); ++ if (ret) { ++ pr_err("Unable to allocate IRQ for PPI\n"); ++ free_dma(info->dma_ch); ++ } ++ } ++ return ret; ++} ++ ++static void ppi_detach_irq(struct ppi_if *ppi) ++{ ++ const struct ppi_info *info = ppi->info; ++ ++ if (ppi->err_int) ++ free_irq(info->irq_err, ppi); ++ free_dma(info->dma_ch); ++} ++ ++static int ppi_start(struct ppi_if *ppi) ++{ ++ const struct ppi_info *info = ppi->info; ++ ++ /* enable DMA */ ++ enable_dma(info->dma_ch); ++ ++ /* enable PPI */ ++ ppi->ppi_control |= PORT_EN; ++ switch (info->type) { ++ case PPI_TYPE_PPI: ++ { ++ struct bfin_ppi_regs *reg = info->base; ++ bfin_write16(®->control, ppi->ppi_control); ++ break; ++ } ++ case PPI_TYPE_EPPI: ++ { ++ struct bfin_eppi_regs *reg = info->base; ++ bfin_write32(®->control, ppi->ppi_control); ++ break; ++ } ++ default: ++ return -EINVAL; ++ } ++ ++ SSYNC(); ++ return 0; ++} ++ ++static int ppi_stop(struct ppi_if *ppi) ++{ ++ const struct ppi_info *info = ppi->info; ++ ++ /* disable PPI */ ++ ppi->ppi_control &= ~PORT_EN; ++ switch (info->type) { ++ case PPI_TYPE_PPI: ++ { ++ struct bfin_ppi_regs *reg = info->base; ++ bfin_write16(®->control, ppi->ppi_control); ++ break; ++ } ++ case PPI_TYPE_EPPI: ++ { ++ struct bfin_eppi_regs *reg = info->base; ++ bfin_write32(®->control, ppi->ppi_control); ++ break; ++ } ++ default: ++ return -EINVAL; ++ } ++ ++ /* disable DMA */ ++ clear_dma_irqstat(info->dma_ch); ++ disable_dma(info->dma_ch); ++ ++ SSYNC(); ++ return 0; ++} ++ ++static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) ++{ ++ const struct ppi_info *info = ppi->info; ++ int dma32 = 0; ++ int dma_config, bytes_per_line, lines_per_frame; ++ ++ bytes_per_line = params->width * params->bpp / 8; ++ lines_per_frame = params->height; ++ if (params->int_mask == 0xFFFFFFFF) ++ ppi->err_int = false; ++ else ++ ppi->err_int = true; ++ ++ dma_config = (DMA_FLOW_STOP | WNR | RESTART | DMA2D | DI_EN); ++ ppi->ppi_control = params->ppi_control & ~PORT_EN; ++ switch (info->type) { ++ case PPI_TYPE_PPI: ++ { ++ struct bfin_ppi_regs *reg = info->base; ++ ++ if (params->ppi_control & DMA32) ++ dma32 = 1; ++ ++ bfin_write16(®->control, ppi->ppi_control); ++ bfin_write16(®->count, bytes_per_line - 1); ++ bfin_write16(®->frame, lines_per_frame); ++ break; ++ } ++ case PPI_TYPE_EPPI: ++ { ++ struct bfin_eppi_regs *reg = info->base; ++ ++ if ((params->ppi_control & PACK_EN) ++ || (params->ppi_control & 0x38000) > DLEN_16) ++ dma32 = 1; ++ ++ bfin_write32(®->control, ppi->ppi_control); ++ bfin_write16(®->line, bytes_per_line + params->blank_clocks); ++ bfin_write16(®->frame, lines_per_frame); ++ bfin_write16(®->hdelay, 0); ++ bfin_write16(®->vdelay, 0); ++ bfin_write16(®->hcount, bytes_per_line); ++ bfin_write16(®->vcount, lines_per_frame); ++ break; ++ } ++ default: ++ return -EINVAL; ++ } ++ ++ if (dma32) { ++ dma_config |= WDSIZE_32; ++ set_dma_x_count(info->dma_ch, bytes_per_line >> 2); ++ set_dma_x_modify(info->dma_ch, 4); ++ set_dma_y_modify(info->dma_ch, 4); ++ } else { ++ dma_config |= WDSIZE_16; ++ set_dma_x_count(info->dma_ch, bytes_per_line >> 1); ++ set_dma_x_modify(info->dma_ch, 2); ++ set_dma_y_modify(info->dma_ch, 2); ++ } ++ set_dma_y_count(info->dma_ch, lines_per_frame); ++ set_dma_config(info->dma_ch, dma_config); ++ ++ SSYNC(); ++ return 0; ++} ++ ++static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr) ++{ ++ set_dma_start_addr(ppi->info->dma_ch, addr); ++} ++ ++struct ppi_if *ppi_create_instance(const struct ppi_info *info) ++{ ++ struct ppi_if *ppi; ++ ++ if (!info || !info->pin_req) ++ return NULL; ++ ++ if (peripheral_request_list(info->pin_req, KBUILD_MODNAME)) { ++ pr_err("request peripheral failed\n"); ++ return NULL; ++ } ++ ++ ppi = kzalloc(sizeof(*ppi), GFP_KERNEL); ++ if (!ppi) { ++ peripheral_free_list(info->pin_req); ++ pr_err("unable to allocate memory for ppi handle\n"); ++ return NULL; ++ } ++ ppi->ops = &ppi_ops; ++ ppi->info = info; ++ ++ pr_info("ppi probe success\n"); ++ return ppi; ++} ++ ++void ppi_delete_instance(struct ppi_if *ppi) ++{ ++ peripheral_free_list(ppi->info->pin_req); ++ kfree(ppi); ++} +Index: linux-3.3.x86_64/include/media/blackfin/bfin_capture.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/include/media/blackfin/bfin_capture.h +@@ -0,0 +1,37 @@ ++#ifndef _BFIN_CAPTURE_H_ ++#define _BFIN_CAPTURE_H_ ++ ++#include ++ ++struct v4l2_input; ++struct ppi_info; ++ ++struct bcap_route { ++ u32 input; ++ u32 output; ++}; ++ ++struct bfin_capture_config { ++ /* card name */ ++ char *card_name; ++ /* inputs available at the sub device */ ++ struct v4l2_input *inputs; ++ /* number of inputs supported */ ++ int num_inputs; ++ /* routing information for each input */ ++ struct bcap_route *routes; ++ /* i2c bus adapter no */ ++ int i2c_adapter_id; ++ /* i2c subdevice board info */ ++ struct i2c_board_info board_info; ++ /* ppi board info */ ++ const struct ppi_info *ppi_info; ++ /* ppi control */ ++ unsigned long ppi_control; ++ /* ppi interrupt mask */ ++ u32 int_mask; ++ /* horizontal blanking clocks */ ++ int blank_clocks; ++}; ++ ++#endif +Index: linux-3.3.x86_64/include/media/blackfin/ppi.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/include/media/blackfin/ppi.h +@@ -0,0 +1,74 @@ ++/* ++ * Analog Devices PPI header file ++ * ++ * Copyright (c) 2011 Analog Devices Inc. ++ * ++ * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef _PPI_H_ ++#define _PPI_H_ ++ ++#include ++ ++#ifdef EPPI_EN ++#define PORT_EN EPPI_EN ++#define DMA32 0 ++#define PACK_EN PACKEN ++#endif ++ ++struct ppi_if; ++ ++struct ppi_params { ++ int width; ++ int height; ++ int bpp; ++ unsigned long ppi_control; ++ u32 int_mask; ++ int blank_clocks; ++}; ++ ++struct ppi_ops { ++ int (*attach_irq)(struct ppi_if *ppi, irq_handler_t handler); ++ void (*detach_irq)(struct ppi_if *ppi); ++ int (*start)(struct ppi_if *ppi); ++ int (*stop)(struct ppi_if *ppi); ++ int (*set_params)(struct ppi_if *ppi, struct ppi_params *params); ++ void (*update_addr)(struct ppi_if *ppi, unsigned long addr); ++}; ++ ++enum ppi_type { ++ PPI_TYPE_PPI, ++ PPI_TYPE_EPPI, ++}; ++ ++struct ppi_info { ++ enum ppi_type type; ++ int dma_ch; ++ int irq_err; ++ void __iomem *base; ++ const unsigned short *pin_req; ++}; ++ ++struct ppi_if { ++ unsigned long ppi_control; ++ const struct ppi_ops *ops; ++ const struct ppi_info *info; ++ bool err_int; ++ void *priv; ++}; ++ ++struct ppi_if *ppi_create_instance(const struct ppi_info *info); ++void ppi_delete_instance(struct ppi_if *ppi); ++#endif +Index: linux-3.3.x86_64/Documentation/DocBook/media/v4l/selection-api.xml +=================================================================== +--- linux-3.3.x86_64.orig/Documentation/DocBook/media/v4l/selection-api.xml ++++ linux-3.3.x86_64/Documentation/DocBook/media/v4l/selection-api.xml +@@ -52,6 +52,10 @@ cropping and composing rectangles have t + + + ++ ++For complete list of the available selection targets see table ++ + + +
+@@ -186,7 +190,7 @@ V4L2_SEL_TGT_COMPOSE_ACTIVE + +
+ +- Scaling control. ++ Scaling control + + An application can detect if scaling is performed by comparing the width + and the height of rectangles obtained using V4L2_SEL_TGT_CROP_ACTIVE +@@ -200,7 +204,7 @@ the scaling ratios using these values. + +- Comparison with old cropping API. ++ Comparison with old cropping API + + The selection API was introduced to cope with deficiencies of previous + API , that was designed to control simple capture +Index: linux-3.3.x86_64/Documentation/DocBook/media/v4l/vidioc-g-selection.xml +=================================================================== +--- linux-3.3.x86_64.orig/Documentation/DocBook/media/v4l/vidioc-g-selection.xml ++++ linux-3.3.x86_64/Documentation/DocBook/media/v4l/vidioc-g-selection.xml +@@ -58,43 +58,43 @@ + + The ioctls are used to query and configure selection rectangles. + +- To query the cropping (composing) rectangle set +-&v4l2-selection;::type to the respective buffer type. Do not +-use multiplanar buffers. Use V4L2_BUF_TYPE_VIDEO_CAPTURE ++ To query the cropping (composing) rectangle set &v4l2-selection; ++ type field to the respective buffer type. ++Do not use multiplanar buffers. Use V4L2_BUF_TYPE_VIDEO_CAPTURE + instead of V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE + . Use V4L2_BUF_TYPE_VIDEO_OUTPUT instead of + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE . The next step is +-setting &v4l2-selection;::target to value +- V4L2_SEL_TGT_CROP_ACTIVE ( ++setting the value of &v4l2-selection; target field ++to V4L2_SEL_TGT_CROP_ACTIVE ( + V4L2_SEL_TGT_COMPOSE_ACTIVE ). Please refer to table or for additional +-targets. Fields &v4l2-selection;::flags and +- &v4l2-selection;::reserved are ignored and they +-must be filled with zeros. The driver fills the rest of the structure or ++targets. The flags and reserved ++ fields of &v4l2-selection; are ignored and they must be filled ++with zeros. The driver fills the rest of the structure or + returns &EINVAL; if incorrect buffer type or target was used. If cropping + (composing) is not supported then the active rectangle is not mutable and it is +-always equal to the bounds rectangle. Finally, structure +-&v4l2-selection;::r is filled with the current cropping ++always equal to the bounds rectangle. Finally, the &v4l2-rect; ++r rectangle is filled with the current cropping + (composing) coordinates. The coordinates are expressed in driver-dependent + units. The only exception are rectangles for images in raw formats, whose + coordinates are always expressed in pixels. + +- To change the cropping (composing) rectangle set +-&v4l2-selection;::type to the respective buffer type. Do not ++ To change the cropping (composing) rectangle set the &v4l2-selection; ++type field to the respective buffer type. Do not + use multiplanar buffers. Use V4L2_BUF_TYPE_VIDEO_CAPTURE + instead of V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE + . Use V4L2_BUF_TYPE_VIDEO_OUTPUT instead of + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE . The next step is +-setting &v4l2-selection;::target to value +- V4L2_SEL_TGT_CROP_ACTIVE ( ++setting the value of &v4l2-selection; target to ++V4L2_SEL_TGT_CROP_ACTIVE ( + V4L2_SEL_TGT_COMPOSE_ACTIVE ). Please refer to table or for additional +-targets. Set desired active area into the field +-&v4l2-selection;::r . Field +-&v4l2-selection;::reserved is ignored and must be filled with +-zeros. The driver may adjust the rectangle coordinates. An application may +-introduce constraints to control rounding behaviour. Set the field +- &v4l2-selection;::flags to one of values: ++targets. The &v4l2-rect; r rectangle need to be ++set to the desired active area. Field &v4l2-selection; reserved ++ is ignored and must be filled with zeros. The driver may adjust ++coordinates of the requested rectangle. An application may ++introduce constraints to control rounding behaviour. The &v4l2-selection; ++flags field must be set to one of the following: + + + +@@ -129,7 +129,7 @@ and vertical offset and sizes are chosen + + + +- Satisfy constraints from &v4l2-selection;::flags. ++ Satisfy constraints from &v4l2-selection; flags. + + + Adjust width, height, left, and top to hardware limits and alignments. +@@ -145,7 +145,7 @@ and vertical offset and sizes are chosen + + + +-On success the field &v4l2-selection;::r contains ++On success the &v4l2-rect; r field contains + the adjusted rectangle. When the parameters are unsuitable the application may + modify the cropping (composing) or image parameters and repeat the cycle until + satisfactory parameters have been negotiated. If constraints flags have to be +@@ -162,38 +162,38 @@ exist no rectangle that sati + + + V4L2_SEL_TGT_CROP_ACTIVE +- 0 +- area that is currently cropped by hardware ++ 0x0000 ++ The area that is currently cropped by hardware. + + + V4L2_SEL_TGT_CROP_DEFAULT +- 1 +- suggested cropping rectangle that covers the "whole picture" ++ 0x0001 ++ Suggested cropping rectangle that covers the "whole picture". + + + V4L2_SEL_TGT_CROP_BOUNDS +- 2 +- limits for the cropping rectangle ++ 0x0002 ++ Limits for the cropping rectangle. + + + V4L2_SEL_TGT_COMPOSE_ACTIVE +- 256 +- area to which data are composed by hardware ++ 0x0100 ++ The area to which data is composed by hardware. + + + V4L2_SEL_TGT_COMPOSE_DEFAULT +- 257 +- suggested composing rectangle that covers the "whole picture" ++ 0x0101 ++ Suggested composing rectangle that covers the "whole picture". + + + V4L2_SEL_TGT_COMPOSE_BOUNDS +- 258 +- limits for the composing rectangle ++ 0x0102 ++ Limits for the composing rectangle. + + + V4L2_SEL_TGT_COMPOSE_PADDED +- 259 +- the active area and all padding pixels that are inserted or modified by the hardware ++ 0x0103 ++ The active area and all padding pixels that are inserted or modified by hardware. + + + +@@ -209,12 +209,14 @@ exist no rectangle that sati + + V4L2_SEL_FLAG_GE + 0x00000001 +- indicate that adjusted rectangle must contain a rectangle from &v4l2-selection;::r ++ Indicates that the adjusted rectangle must contain the original ++ &v4l2-selection; r rectangle. + + + V4L2_SEL_FLAG_LE + 0x00000002 +- indicate that adjusted rectangle must be inside a rectangle from &v4l2-selection;::r ++ Indicates that the adjusted rectangle must be inside the original ++ &v4l2-rect; r rectangle. + + + +@@ -245,27 +247,29 @@ exist no rectangle that sati + + __u32 + type +- Type of the buffer (from &v4l2-buf-type;) ++ Type of the buffer (from &v4l2-buf-type;). + + + __u32 + target +- used to select between cropping and composing rectangles ++ Used to select between cropping ++ and composing rectangles. + + + __u32 + flags +- control over coordinates adjustments, refer to selection flags ++ Flags controlling the selection rectangle adjustments, refer to ++ selection flags. + + + &v4l2-rect; + r +- selection rectangle ++ The selection rectangle. + + + __u32 + reserved[9] +- Reserved fields for future use ++ Reserved fields for future use. + + + +@@ -278,24 +282,24 @@ exist no rectangle that sati + + EINVAL + +- The buffer &v4l2-selection;::type +-or &v4l2-selection;::target is not supported, or +-the &v4l2-selection;::flags are invalid. ++ Given buffer type type or ++the selection target target is not supported, ++or the flags argument is not valid. + + + + ERANGE + +- it is not possible to adjust a rectangle +-&v4l2-selection;::r that satisfies all contraints from +- &v4l2-selection;::flags . ++ It is not possible to adjust &v4l2-rect; ++r rectangle to satisfy all contraints given in the ++flags argument. + + + + EBUSY + +- it is not possible to apply change of selection rectangle at the moment. +-Usually because streaming is in progress. ++ It is not possible to apply change of the selection rectangle ++at the moment. Usually because streaming is in progress. + + + +Index: linux-3.3.x86_64/drivers/media/video/w9966.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/w9966.c ++++ linux-3.3.x86_64/drivers/media/video/w9966.c +@@ -129,9 +129,9 @@ MODULE_LICENSE("GPL"); + MODULE_VERSION("0.33.1"); + + #ifdef MODULE +-static const char *pardev[] = {[0 ... W9966_MAXCAMS] = ""}; ++static char *pardev[] = {[0 ... W9966_MAXCAMS] = ""}; + #else +-static const char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"}; ++static char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"}; + #endif + module_param_array(pardev, charp, NULL, 0); + MODULE_PARM_DESC(pardev, "pardev: where to search for\n" +Index: linux-3.3.x86_64/drivers/media/dvb/pt1/pt1.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/pt1/pt1.c ++++ linux-3.3.x86_64/drivers/media/dvb/pt1/pt1.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include "dvbdev.h" + #include "dvb_demux.h" +@@ -77,6 +78,8 @@ struct pt1 { + struct pt1_adapter *adaps[PT1_NR_ADAPS]; + struct pt1_table *tables; + struct task_struct *kthread; ++ int table_index; ++ int buf_index; + + struct mutex lock; + int power; +@@ -90,12 +93,12 @@ struct pt1_adapter { + u8 *buf; + int upacket_count; + int packet_count; ++ int st_count; + + struct dvb_adapter adap; + struct dvb_demux demux; + int users; + struct dmxdev dmxdev; +- struct dvb_net net; + struct dvb_frontend *fe; + int (*orig_set_voltage)(struct dvb_frontend *fe, + fe_sec_voltage_t voltage); +@@ -119,7 +122,7 @@ static u32 pt1_read_reg(struct pt1 *pt1, + return readl(pt1->regs + reg * 4); + } + +-static int pt1_nr_tables = 64; ++static int pt1_nr_tables = 8; + module_param_named(nr_tables, pt1_nr_tables, int, 0); + + static void pt1_increment_table_count(struct pt1 *pt1) +@@ -264,6 +267,7 @@ static int pt1_filter(struct pt1 *pt1, s + struct pt1_adapter *adap; + int offset; + u8 *buf; ++ int sc; + + if (!page->upackets[PT1_NR_UPACKETS - 1]) + return 0; +@@ -280,6 +284,16 @@ static int pt1_filter(struct pt1 *pt1, s + else if (!adap->upacket_count) + continue; + ++ if (upacket >> 24 & 1) ++ printk_ratelimited(KERN_INFO "earth-pt1: device " ++ "buffer overflowing. table[%d] buf[%d]\n", ++ pt1->table_index, pt1->buf_index); ++ sc = upacket >> 26 & 0x7; ++ if (adap->st_count != -1 && sc != ((adap->st_count + 1) & 0x7)) ++ printk_ratelimited(KERN_INFO "earth-pt1: data loss" ++ " in streamID(adapter)[%d]\n", index); ++ adap->st_count = sc; ++ + buf = adap->buf; + offset = adap->packet_count * 188 + adap->upacket_count * 3; + buf[offset] = upacket >> 16; +@@ -303,30 +317,25 @@ static int pt1_filter(struct pt1 *pt1, s + static int pt1_thread(void *data) + { + struct pt1 *pt1; +- int table_index; +- int buf_index; + struct pt1_buffer_page *page; + + pt1 = data; + set_freezable(); + +- table_index = 0; +- buf_index = 0; +- + while (!kthread_should_stop()) { + try_to_freeze(); + +- page = pt1->tables[table_index].bufs[buf_index].page; ++ page = pt1->tables[pt1->table_index].bufs[pt1->buf_index].page; + if (!pt1_filter(pt1, page)) { + schedule_timeout_interruptible((HZ + 999) / 1000); + continue; + } + +- if (++buf_index >= PT1_NR_BUFS) { ++ if (++pt1->buf_index >= PT1_NR_BUFS) { + pt1_increment_table_count(pt1); +- buf_index = 0; +- if (++table_index >= pt1_nr_tables) +- table_index = 0; ++ pt1->buf_index = 0; ++ if (++pt1->table_index >= pt1_nr_tables) ++ pt1->table_index = 0; + } + } + +@@ -477,21 +486,60 @@ err: + return ret; + } + ++static int pt1_start_polling(struct pt1 *pt1) ++{ ++ int ret = 0; ++ ++ mutex_lock(&pt1->lock); ++ if (!pt1->kthread) { ++ pt1->kthread = kthread_run(pt1_thread, pt1, "earth-pt1"); ++ if (IS_ERR(pt1->kthread)) { ++ ret = PTR_ERR(pt1->kthread); ++ pt1->kthread = NULL; ++ } ++ } ++ mutex_unlock(&pt1->lock); ++ return ret; ++} ++ + static int pt1_start_feed(struct dvb_demux_feed *feed) + { + struct pt1_adapter *adap; + adap = container_of(feed->demux, struct pt1_adapter, demux); +- if (!adap->users++) ++ if (!adap->users++) { ++ int ret; ++ ++ ret = pt1_start_polling(adap->pt1); ++ if (ret) ++ return ret; + pt1_set_stream(adap->pt1, adap->index, 1); ++ } + return 0; + } + ++static void pt1_stop_polling(struct pt1 *pt1) ++{ ++ int i, count; ++ ++ mutex_lock(&pt1->lock); ++ for (i = 0, count = 0; i < PT1_NR_ADAPS; i++) ++ count += pt1->adaps[i]->users; ++ ++ if (count == 0 && pt1->kthread) { ++ kthread_stop(pt1->kthread); ++ pt1->kthread = NULL; ++ } ++ mutex_unlock(&pt1->lock); ++} ++ + static int pt1_stop_feed(struct dvb_demux_feed *feed) + { + struct pt1_adapter *adap; + adap = container_of(feed->demux, struct pt1_adapter, demux); +- if (!--adap->users) ++ if (!--adap->users) { + pt1_set_stream(adap->pt1, adap->index, 0); ++ pt1_stop_polling(adap->pt1); ++ } + return 0; + } + +@@ -575,7 +623,6 @@ static int pt1_wakeup(struct dvb_fronten + + static void pt1_free_adapter(struct pt1_adapter *adap) + { +- dvb_net_release(&adap->net); + adap->demux.dmx.close(&adap->demux.dmx); + dvb_dmxdev_release(&adap->dmxdev); + dvb_dmx_release(&adap->demux); +@@ -616,6 +663,7 @@ pt1_alloc_adapter(struct pt1 *pt1) + adap->buf = buf; + adap->upacket_count = 0; + adap->packet_count = 0; ++ adap->st_count = -1; + + dvb_adap = &adap->adap; + dvb_adap->priv = adap; +@@ -644,8 +692,6 @@ pt1_alloc_adapter(struct pt1 *pt1) + if (ret < 0) + goto err_dmx_release; + +- dvb_net_init(dvb_adap, &adap->net, &demux->dmx); +- + return adap; + + err_dmx_release: +@@ -1020,7 +1066,8 @@ static void __devexit pt1_remove(struct + pt1 = pci_get_drvdata(pdev); + regs = pt1->regs; + +- kthread_stop(pt1->kthread); ++ if (pt1->kthread) ++ kthread_stop(pt1->kthread); + pt1_cleanup_tables(pt1); + pt1_cleanup_frontends(pt1); + pt1_disable_ram(pt1); +@@ -1043,7 +1090,6 @@ pt1_probe(struct pci_dev *pdev, const st + void __iomem *regs; + struct pt1 *pt1; + struct i2c_adapter *i2c_adap; +- struct task_struct *kthread; + + ret = pci_enable_device(pdev); + if (ret < 0) +@@ -1139,17 +1185,8 @@ pt1_probe(struct pci_dev *pdev, const st + if (ret < 0) + goto err_pt1_cleanup_frontends; + +- kthread = kthread_run(pt1_thread, pt1, "pt1"); +- if (IS_ERR(kthread)) { +- ret = PTR_ERR(kthread); +- goto err_pt1_cleanup_tables; +- } +- +- pt1->kthread = kthread; + return 0; + +-err_pt1_cleanup_tables: +- pt1_cleanup_tables(pt1); + err_pt1_cleanup_frontends: + pt1_cleanup_frontends(pt1); + err_pt1_disable_ram: +Index: linux-3.3.x86_64/drivers/media/video/aptina-pll.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/aptina-pll.c +@@ -0,0 +1,174 @@ ++/* ++ * Aptina Sensor PLL Configuration ++ * ++ * Copyright (C) 2012 Laurent Pinchart ++ * ++ * 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 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., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "aptina-pll.h" ++ ++int aptina_pll_calculate(struct device *dev, ++ const struct aptina_pll_limits *limits, ++ struct aptina_pll *pll) ++{ ++ unsigned int mf_min; ++ unsigned int mf_max; ++ unsigned int p1_min; ++ unsigned int p1_max; ++ unsigned int p1; ++ unsigned int div; ++ ++ dev_dbg(dev, "PLL: ext clock %u pix clock %u\n", ++ pll->ext_clock, pll->pix_clock); ++ ++ if (pll->ext_clock < limits->ext_clock_min || ++ pll->ext_clock > limits->ext_clock_max) { ++ dev_err(dev, "pll: invalid external clock frequency.\n"); ++ return -EINVAL; ++ } ++ ++ if (pll->pix_clock == 0 || pll->pix_clock > limits->pix_clock_max) { ++ dev_err(dev, "pll: invalid pixel clock frequency.\n"); ++ return -EINVAL; ++ } ++ ++ /* Compute the multiplier M and combined N*P1 divisor. */ ++ div = gcd(pll->pix_clock, pll->ext_clock); ++ pll->m = pll->pix_clock / div; ++ div = pll->ext_clock / div; ++ ++ /* We now have the smallest M and N*P1 values that will result in the ++ * desired pixel clock frequency, but they might be out of the valid ++ * range. Compute the factor by which we should multiply them given the ++ * following constraints: ++ * ++ * - minimum/maximum multiplier ++ * - minimum/maximum multiplier output clock frequency assuming the ++ * minimum/maximum N value ++ * - minimum/maximum combined N*P1 divisor ++ */ ++ mf_min = DIV_ROUND_UP(limits->m_min, pll->m); ++ mf_min = max(mf_min, limits->out_clock_min / ++ (pll->ext_clock / limits->n_min * pll->m)); ++ mf_min = max(mf_min, limits->n_min * limits->p1_min / div); ++ mf_max = limits->m_max / pll->m; ++ mf_max = min(mf_max, limits->out_clock_max / ++ (pll->ext_clock / limits->n_max * pll->m)); ++ mf_max = min(mf_max, DIV_ROUND_UP(limits->n_max * limits->p1_max, div)); ++ ++ dev_dbg(dev, "pll: mf min %u max %u\n", mf_min, mf_max); ++ if (mf_min > mf_max) { ++ dev_err(dev, "pll: no valid combined N*P1 divisor.\n"); ++ return -EINVAL; ++ } ++ ++ /* ++ * We're looking for the highest acceptable P1 value for which a ++ * multiplier factor MF exists that fulfills the following conditions: ++ * ++ * 1. p1 is in the [p1_min, p1_max] range given by the limits and is ++ * even ++ * 2. mf is in the [mf_min, mf_max] range computed above ++ * 3. div * mf is a multiple of p1, in order to compute ++ * n = div * mf / p1 ++ * m = pll->m * mf ++ * 4. the internal clock frequency, given by ext_clock / n, is in the ++ * [int_clock_min, int_clock_max] range given by the limits ++ * 5. the output clock frequency, given by ext_clock / n * m, is in the ++ * [out_clock_min, out_clock_max] range given by the limits ++ * ++ * The first naive approach is to iterate over all p1 values acceptable ++ * according to (1) and all mf values acceptable according to (2), and ++ * stop at the first combination that fulfills (3), (4) and (5). This ++ * has a O(n^2) complexity. ++ * ++ * Instead of iterating over all mf values in the [mf_min, mf_max] range ++ * we can compute the mf increment between two acceptable values ++ * according to (3) with ++ * ++ * mf_inc = p1 / gcd(div, p1) (6) ++ * ++ * and round the minimum up to the nearest multiple of mf_inc. This will ++ * restrict the number of mf values to be checked. ++ * ++ * Furthermore, conditions (4) and (5) only restrict the range of ++ * acceptable p1 and mf values by modifying the minimum and maximum ++ * limits. (5) can be expressed as ++ * ++ * ext_clock / (div * mf / p1) * m * mf >= out_clock_min ++ * ext_clock / (div * mf / p1) * m * mf <= out_clock_max ++ * ++ * or ++ * ++ * p1 >= out_clock_min * div / (ext_clock * m) (7) ++ * p1 <= out_clock_max * div / (ext_clock * m) ++ * ++ * Similarly, (4) can be expressed as ++ * ++ * mf >= ext_clock * p1 / (int_clock_max * div) (8) ++ * mf <= ext_clock * p1 / (int_clock_min * div) ++ * ++ * We can thus iterate over the restricted p1 range defined by the ++ * combination of (1) and (7), and then compute the restricted mf range ++ * defined by the combination of (2), (6) and (8). If the resulting mf ++ * range is not empty, any value in the mf range is acceptable. We thus ++ * select the mf lwoer bound and the corresponding p1 value. ++ */ ++ if (limits->p1_min == 0) { ++ dev_err(dev, "pll: P1 minimum value must be >0.\n"); ++ return -EINVAL; ++ } ++ ++ p1_min = max(limits->p1_min, DIV_ROUND_UP(limits->out_clock_min * div, ++ pll->ext_clock * pll->m)); ++ p1_max = min(limits->p1_max, limits->out_clock_max * div / ++ (pll->ext_clock * pll->m)); ++ ++ for (p1 = p1_max & ~1; p1 >= p1_min; p1 -= 2) { ++ unsigned int mf_inc = p1 / gcd(div, p1); ++ unsigned int mf_high; ++ unsigned int mf_low; ++ ++ mf_low = max(roundup(mf_min, mf_inc), ++ DIV_ROUND_UP(pll->ext_clock * p1, ++ limits->int_clock_max * div)); ++ mf_high = min(mf_max, pll->ext_clock * p1 / ++ (limits->int_clock_min * div)); ++ ++ if (mf_low > mf_high) ++ continue; ++ ++ pll->n = div * mf_low / p1; ++ pll->m *= mf_low; ++ pll->p1 = p1; ++ dev_dbg(dev, "PLL: N %u M %u P1 %u\n", pll->n, pll->m, pll->p1); ++ return 0; ++ } ++ ++ dev_err(dev, "pll: no valid N and P1 divisors found.\n"); ++ return -EINVAL; ++} ++EXPORT_SYMBOL_GPL(aptina_pll_calculate); ++ ++MODULE_DESCRIPTION("Aptina PLL Helpers"); ++MODULE_AUTHOR("Laurent Pinchart "); ++MODULE_LICENSE("GPL v2"); +Index: linux-3.3.x86_64/drivers/media/video/aptina-pll.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/aptina-pll.h +@@ -0,0 +1,56 @@ ++/* ++ * Aptina Sensor PLL Configuration ++ * ++ * Copyright (C) 2012 Laurent Pinchart ++ * ++ * 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 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., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#ifndef __APTINA_PLL_H ++#define __APTINA_PLL_H ++ ++struct aptina_pll { ++ unsigned int ext_clock; ++ unsigned int pix_clock; ++ ++ unsigned int n; ++ unsigned int m; ++ unsigned int p1; ++}; ++ ++struct aptina_pll_limits { ++ unsigned int ext_clock_min; ++ unsigned int ext_clock_max; ++ unsigned int int_clock_min; ++ unsigned int int_clock_max; ++ unsigned int out_clock_min; ++ unsigned int out_clock_max; ++ unsigned int pix_clock_max; ++ ++ unsigned int n_min; ++ unsigned int n_max; ++ unsigned int m_min; ++ unsigned int m_max; ++ unsigned int p1_min; ++ unsigned int p1_max; ++}; ++ ++struct device; ++ ++int aptina_pll_calculate(struct device *dev, ++ const struct aptina_pll_limits *limits, ++ struct aptina_pll *pll); ++ ++#endif /* __APTINA_PLL_H */ +Index: linux-3.3.x86_64/drivers/media/video/mt9m032.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/mt9m032.c +@@ -0,0 +1,868 @@ ++/* ++ * Driver for MT9M032 CMOS Image Sensor from Micron ++ * ++ * Copyright (C) 2010-2011 Lund Engineering ++ * Contact: Gil Lund ++ * Author: Martin Hostettler ++ * ++ * 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 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., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "aptina-pll.h" ++ ++/* ++ * width and height include active boundary and black parts ++ * ++ * column 0- 15 active boundary ++ * column 16-1455 image ++ * column 1456-1471 active boundary ++ * column 1472-1599 black ++ * ++ * row 0- 51 black ++ * row 53- 59 active boundary ++ * row 60-1139 image ++ * row 1140-1147 active boundary ++ * row 1148-1151 black ++ */ ++ ++#define MT9M032_PIXEL_ARRAY_WIDTH 1600 ++#define MT9M032_PIXEL_ARRAY_HEIGHT 1152 ++ ++#define MT9M032_CHIP_VERSION 0x00 ++#define MT9M032_CHIP_VERSION_VALUE 0x1402 ++#define MT9M032_ROW_START 0x01 ++#define MT9M032_ROW_START_MIN 0 ++#define MT9M032_ROW_START_MAX 1152 ++#define MT9M032_ROW_START_DEF 60 ++#define MT9M032_COLUMN_START 0x02 ++#define MT9M032_COLUMN_START_MIN 0 ++#define MT9M032_COLUMN_START_MAX 1600 ++#define MT9M032_COLUMN_START_DEF 16 ++#define MT9M032_ROW_SIZE 0x03 ++#define MT9M032_ROW_SIZE_MIN 32 ++#define MT9M032_ROW_SIZE_MAX 1152 ++#define MT9M032_ROW_SIZE_DEF 1080 ++#define MT9M032_COLUMN_SIZE 0x04 ++#define MT9M032_COLUMN_SIZE_MIN 32 ++#define MT9M032_COLUMN_SIZE_MAX 1600 ++#define MT9M032_COLUMN_SIZE_DEF 1440 ++#define MT9M032_HBLANK 0x05 ++#define MT9M032_VBLANK 0x06 ++#define MT9M032_VBLANK_MAX 0x7ff ++#define MT9M032_SHUTTER_WIDTH_HIGH 0x08 ++#define MT9M032_SHUTTER_WIDTH_LOW 0x09 ++#define MT9M032_SHUTTER_WIDTH_MIN 1 ++#define MT9M032_SHUTTER_WIDTH_MAX 1048575 ++#define MT9M032_SHUTTER_WIDTH_DEF 1943 ++#define MT9M032_PIX_CLK_CTRL 0x0a ++#define MT9M032_PIX_CLK_CTRL_INV_PIXCLK 0x8000 ++#define MT9M032_RESTART 0x0b ++#define MT9M032_RESET 0x0d ++#define MT9M032_PLL_CONFIG1 0x11 ++#define MT9M032_PLL_CONFIG1_OUTDIV_MASK 0x3f ++#define MT9M032_PLL_CONFIG1_MUL_SHIFT 8 ++#define MT9M032_READ_MODE1 0x1e ++#define MT9M032_READ_MODE2 0x20 ++#define MT9M032_READ_MODE2_VFLIP_SHIFT 15 ++#define MT9M032_READ_MODE2_HFLIP_SHIFT 14 ++#define MT9M032_READ_MODE2_ROW_BLC 0x40 ++#define MT9M032_GAIN_GREEN1 0x2b ++#define MT9M032_GAIN_BLUE 0x2c ++#define MT9M032_GAIN_RED 0x2d ++#define MT9M032_GAIN_GREEN2 0x2e ++ ++/* write only */ ++#define MT9M032_GAIN_ALL 0x35 ++#define MT9M032_GAIN_DIGITAL_MASK 0x7f ++#define MT9M032_GAIN_DIGITAL_SHIFT 8 ++#define MT9M032_GAIN_AMUL_SHIFT 6 ++#define MT9M032_GAIN_ANALOG_MASK 0x3f ++#define MT9M032_FORMATTER1 0x9e ++#define MT9M032_FORMATTER2 0x9f ++#define MT9M032_FORMATTER2_DOUT_EN 0x1000 ++#define MT9M032_FORMATTER2_PIXCLK_EN 0x2000 ++ ++/* ++ * The available MT9M032 datasheet is missing documentation for register 0x10 ++ * MT9P031 seems to be close enough, so use constants from that datasheet for ++ * now. ++ * But keep the name MT9P031 to remind us, that this isn't really confirmed ++ * for this sensor. ++ */ ++#define MT9P031_PLL_CONTROL 0x10 ++#define MT9P031_PLL_CONTROL_PWROFF 0x0050 ++#define MT9P031_PLL_CONTROL_PWRON 0x0051 ++#define MT9P031_PLL_CONTROL_USEPLL 0x0052 ++#define MT9P031_PLL_CONFIG2 0x11 ++#define MT9P031_PLL_CONFIG2_P1_DIV_MASK 0x1f ++ ++struct mt9m032 { ++ struct v4l2_subdev subdev; ++ struct media_pad pad; ++ struct mt9m032_platform_data *pdata; ++ ++ unsigned int pix_clock; ++ ++ struct v4l2_ctrl_handler ctrls; ++ struct { ++ struct v4l2_ctrl *hflip; ++ struct v4l2_ctrl *vflip; ++ }; ++ ++ struct mutex lock; /* Protects streaming, format, interval and crop */ ++ ++ bool streaming; ++ ++ struct v4l2_mbus_framefmt format; ++ struct v4l2_rect crop; ++ struct v4l2_fract frame_interval; ++}; ++ ++#define to_mt9m032(sd) container_of(sd, struct mt9m032, subdev) ++#define to_dev(sensor) \ ++ (&((struct i2c_client *)v4l2_get_subdevdata(&(sensor)->subdev))->dev) ++ ++static int mt9m032_read(struct i2c_client *client, u8 reg) ++{ ++ return i2c_smbus_read_word_swapped(client, reg); ++} ++ ++static int mt9m032_write(struct i2c_client *client, u8 reg, const u16 data) ++{ ++ return i2c_smbus_write_word_swapped(client, reg, data); ++} ++ ++static u32 mt9m032_row_time(struct mt9m032 *sensor, unsigned int width) ++{ ++ unsigned int effective_width; ++ u32 ns; ++ ++ effective_width = width + 716; /* empirical value */ ++ ns = div_u64(1000000000ULL * effective_width, sensor->pix_clock); ++ dev_dbg(to_dev(sensor), "MT9M032 line time: %u ns\n", ns); ++ return ns; ++} ++ ++static int mt9m032_update_timing(struct mt9m032 *sensor, ++ struct v4l2_fract *interval) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ struct v4l2_rect *crop = &sensor->crop; ++ unsigned int min_vblank; ++ unsigned int vblank; ++ u32 row_time; ++ ++ if (!interval) ++ interval = &sensor->frame_interval; ++ ++ row_time = mt9m032_row_time(sensor, crop->width); ++ ++ vblank = div_u64(1000000000ULL * interval->numerator, ++ (u64)row_time * interval->denominator) ++ - crop->height; ++ ++ if (vblank > MT9M032_VBLANK_MAX) { ++ /* hardware limits to 11 bit values */ ++ interval->denominator = 1000; ++ interval->numerator = ++ div_u64((crop->height + MT9M032_VBLANK_MAX) * ++ (u64)row_time * interval->denominator, ++ 1000000000ULL); ++ vblank = div_u64(1000000000ULL * interval->numerator, ++ (u64)row_time * interval->denominator) ++ - crop->height; ++ } ++ /* enforce minimal 1.6ms blanking time. */ ++ min_vblank = 1600000 / row_time; ++ vblank = clamp_t(unsigned int, vblank, min_vblank, MT9M032_VBLANK_MAX); ++ ++ return mt9m032_write(client, MT9M032_VBLANK, vblank); ++} ++ ++static int mt9m032_update_geom_timing(struct mt9m032 *sensor) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ int ret; ++ ++ ret = mt9m032_write(client, MT9M032_COLUMN_SIZE, ++ sensor->crop.width - 1); ++ if (!ret) ++ ret = mt9m032_write(client, MT9M032_ROW_SIZE, ++ sensor->crop.height - 1); ++ if (!ret) ++ ret = mt9m032_write(client, MT9M032_COLUMN_START, ++ sensor->crop.left); ++ if (!ret) ++ ret = mt9m032_write(client, MT9M032_ROW_START, ++ sensor->crop.top); ++ if (!ret) ++ ret = mt9m032_update_timing(sensor, NULL); ++ return ret; ++} ++ ++static int update_formatter2(struct mt9m032 *sensor, bool streaming) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ u16 reg_val = MT9M032_FORMATTER2_DOUT_EN ++ | 0x0070; /* parts reserved! */ ++ /* possibly for changing to 14-bit mode */ ++ ++ if (streaming) ++ reg_val |= MT9M032_FORMATTER2_PIXCLK_EN; /* pixclock enable */ ++ ++ return mt9m032_write(client, MT9M032_FORMATTER2, reg_val); ++} ++ ++static int mt9m032_setup_pll(struct mt9m032 *sensor) ++{ ++ static const struct aptina_pll_limits limits = { ++ .ext_clock_min = 8000000, ++ .ext_clock_max = 16500000, ++ .int_clock_min = 2000000, ++ .int_clock_max = 24000000, ++ .out_clock_min = 322000000, ++ .out_clock_max = 693000000, ++ .pix_clock_max = 99000000, ++ .n_min = 1, ++ .n_max = 64, ++ .m_min = 16, ++ .m_max = 255, ++ .p1_min = 1, ++ .p1_max = 128, ++ }; ++ ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ struct mt9m032_platform_data *pdata = sensor->pdata; ++ struct aptina_pll pll; ++ int ret; ++ ++ pll.ext_clock = pdata->ext_clock; ++ pll.pix_clock = pdata->pix_clock; ++ ++ ret = aptina_pll_calculate(&client->dev, &limits, &pll); ++ if (ret < 0) ++ return ret; ++ ++ sensor->pix_clock = pdata->pix_clock; ++ ++ ret = mt9m032_write(client, MT9M032_PLL_CONFIG1, ++ (pll.m << MT9M032_PLL_CONFIG1_MUL_SHIFT) ++ | (pll.p1 - 1)); ++ if (!ret) ++ ret = mt9m032_write(client, MT9P031_PLL_CONFIG2, pll.n - 1); ++ if (!ret) ++ ret = mt9m032_write(client, MT9P031_PLL_CONTROL, ++ MT9P031_PLL_CONTROL_PWRON | ++ MT9P031_PLL_CONTROL_USEPLL); ++ if (!ret) /* more reserved, Continuous, Master Mode */ ++ ret = mt9m032_write(client, MT9M032_READ_MODE1, 0x8006); ++ if (!ret) /* Set 14-bit mode, select 7 divider */ ++ ret = mt9m032_write(client, MT9M032_FORMATTER1, 0x111e); ++ ++ return ret; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * Subdev pad operations ++ */ ++ ++static int mt9m032_enum_mbus_code(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_fh *fh, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->index != 0) ++ return -EINVAL; ++ ++ code->code = V4L2_MBUS_FMT_Y8_1X8; ++ return 0; ++} ++ ++static int mt9m032_enum_frame_size(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_fh *fh, ++ struct v4l2_subdev_frame_size_enum *fse) ++{ ++ if (fse->index != 0 || fse->code != V4L2_MBUS_FMT_Y8_1X8) ++ return -EINVAL; ++ ++ fse->min_width = MT9M032_COLUMN_SIZE_DEF; ++ fse->max_width = MT9M032_COLUMN_SIZE_DEF; ++ fse->min_height = MT9M032_ROW_SIZE_DEF; ++ fse->max_height = MT9M032_ROW_SIZE_DEF; ++ ++ return 0; ++} ++ ++/** ++ * __mt9m032_get_pad_crop() - get crop rect ++ * @sensor: pointer to the sensor struct ++ * @fh: file handle for getting the try crop rect from ++ * @which: select try or active crop rect ++ * ++ * Returns a pointer the current active or fh relative try crop rect ++ */ ++static struct v4l2_rect * ++__mt9m032_get_pad_crop(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh, ++ enum v4l2_subdev_format_whence which) ++{ ++ switch (which) { ++ case V4L2_SUBDEV_FORMAT_TRY: ++ return v4l2_subdev_get_try_crop(fh, 0); ++ case V4L2_SUBDEV_FORMAT_ACTIVE: ++ return &sensor->crop; ++ default: ++ return NULL; ++ } ++} ++ ++/** ++ * __mt9m032_get_pad_format() - get format ++ * @sensor: pointer to the sensor struct ++ * @fh: file handle for getting the try format from ++ * @which: select try or active format ++ * ++ * Returns a pointer the current active or fh relative try format ++ */ ++static struct v4l2_mbus_framefmt * ++__mt9m032_get_pad_format(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh, ++ enum v4l2_subdev_format_whence which) ++{ ++ switch (which) { ++ case V4L2_SUBDEV_FORMAT_TRY: ++ return v4l2_subdev_get_try_format(fh, 0); ++ case V4L2_SUBDEV_FORMAT_ACTIVE: ++ return &sensor->format; ++ default: ++ return NULL; ++ } ++} ++ ++static int mt9m032_get_pad_format(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_fh *fh, ++ struct v4l2_subdev_format *fmt) ++{ ++ struct mt9m032 *sensor = to_mt9m032(subdev); ++ ++ mutex_lock(&sensor->lock); ++ fmt->format = *__mt9m032_get_pad_format(sensor, fh, fmt->which); ++ mutex_unlock(&sensor->lock); ++ ++ return 0; ++} ++ ++static int mt9m032_set_pad_format(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_fh *fh, ++ struct v4l2_subdev_format *fmt) ++{ ++ struct mt9m032 *sensor = to_mt9m032(subdev); ++ int ret; ++ ++ mutex_lock(&sensor->lock); ++ ++ if (sensor->streaming && fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { ++ ret = -EBUSY; ++ goto done; ++ } ++ ++ /* Scaling is not supported, the format is thus fixed. */ ++ ret = mt9m032_get_pad_format(subdev, fh, fmt); ++ ++done: ++ mutex_lock(&sensor->lock); ++ return ret; ++} ++ ++static int mt9m032_get_pad_crop(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_fh *fh, ++ struct v4l2_subdev_crop *crop) ++{ ++ struct mt9m032 *sensor = to_mt9m032(subdev); ++ ++ mutex_lock(&sensor->lock); ++ crop->rect = *__mt9m032_get_pad_crop(sensor, fh, crop->which); ++ mutex_unlock(&sensor->lock); ++ ++ return 0; ++} ++ ++static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_fh *fh, ++ struct v4l2_subdev_crop *crop) ++{ ++ struct mt9m032 *sensor = to_mt9m032(subdev); ++ struct v4l2_mbus_framefmt *format; ++ struct v4l2_rect *__crop; ++ struct v4l2_rect rect; ++ int ret = 0; ++ ++ mutex_lock(&sensor->lock); ++ ++ if (sensor->streaming && crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) { ++ ret = -EBUSY; ++ goto done; ++ } ++ ++ /* Clamp the crop rectangle boundaries and align them to a multiple of 2 ++ * pixels to ensure a GRBG Bayer pattern. ++ */ ++ rect.left = clamp(ALIGN(crop->rect.left, 2), MT9M032_COLUMN_START_MIN, ++ MT9M032_COLUMN_START_MAX); ++ rect.top = clamp(ALIGN(crop->rect.top, 2), MT9M032_ROW_START_MIN, ++ MT9M032_ROW_START_MAX); ++ rect.width = clamp(ALIGN(crop->rect.width, 2), MT9M032_COLUMN_SIZE_MIN, ++ MT9M032_COLUMN_SIZE_MAX); ++ rect.height = clamp(ALIGN(crop->rect.height, 2), MT9M032_ROW_SIZE_MIN, ++ MT9M032_ROW_SIZE_MAX); ++ ++ rect.width = min(rect.width, MT9M032_PIXEL_ARRAY_WIDTH - rect.left); ++ rect.height = min(rect.height, MT9M032_PIXEL_ARRAY_HEIGHT - rect.top); ++ ++ __crop = __mt9m032_get_pad_crop(sensor, fh, crop->which); ++ ++ if (rect.width != __crop->width || rect.height != __crop->height) { ++ /* Reset the output image size if the crop rectangle size has ++ * been modified. ++ */ ++ format = __mt9m032_get_pad_format(sensor, fh, crop->which); ++ format->width = rect.width; ++ format->height = rect.height; ++ } ++ ++ *__crop = rect; ++ crop->rect = rect; ++ ++ if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) ++ ret = mt9m032_update_geom_timing(sensor); ++ ++done: ++ mutex_unlock(&sensor->lock); ++ return ret; ++} ++ ++static int mt9m032_get_frame_interval(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_frame_interval *fi) ++{ ++ struct mt9m032 *sensor = to_mt9m032(subdev); ++ ++ mutex_lock(&sensor->lock); ++ memset(fi, 0, sizeof(*fi)); ++ fi->interval = sensor->frame_interval; ++ mutex_unlock(&sensor->lock); ++ ++ return 0; ++} ++ ++static int mt9m032_set_frame_interval(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_frame_interval *fi) ++{ ++ struct mt9m032 *sensor = to_mt9m032(subdev); ++ int ret; ++ ++ mutex_lock(&sensor->lock); ++ ++ if (sensor->streaming) { ++ ret = -EBUSY; ++ goto done; ++ } ++ ++ /* Avoid divisions by 0. */ ++ if (fi->interval.denominator == 0) ++ fi->interval.denominator = 1; ++ ++ ret = mt9m032_update_timing(sensor, &fi->interval); ++ if (!ret) ++ sensor->frame_interval = fi->interval; ++ ++done: ++ mutex_unlock(&sensor->lock); ++ return ret; ++} ++ ++static int mt9m032_s_stream(struct v4l2_subdev *subdev, int streaming) ++{ ++ struct mt9m032 *sensor = to_mt9m032(subdev); ++ int ret; ++ ++ mutex_lock(&sensor->lock); ++ ret = update_formatter2(sensor, streaming); ++ if (!ret) ++ sensor->streaming = streaming; ++ mutex_unlock(&sensor->lock); ++ ++ return ret; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * V4L2 subdev core operations ++ */ ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int mt9m032_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct mt9m032 *sensor = to_mt9m032(sd); ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ int val; ++ ++ if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) ++ return -EINVAL; ++ if (reg->match.addr != client->addr) ++ return -ENODEV; ++ ++ val = mt9m032_read(client, reg->reg); ++ if (val < 0) ++ return -EIO; ++ ++ reg->size = 2; ++ reg->val = val; ++ ++ return 0; ++} ++ ++static int mt9m032_s_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct mt9m032 *sensor = to_mt9m032(sd); ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ ++ if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) ++ return -EINVAL; ++ ++ if (reg->match.addr != client->addr) ++ return -ENODEV; ++ ++ return mt9m032_write(client, reg->reg, reg->val); ++} ++#endif ++ ++/* ----------------------------------------------------------------------------- ++ * V4L2 subdev control operations ++ */ ++ ++static int update_read_mode2(struct mt9m032 *sensor, bool vflip, bool hflip) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ int reg_val = (vflip << MT9M032_READ_MODE2_VFLIP_SHIFT) ++ | (hflip << MT9M032_READ_MODE2_HFLIP_SHIFT) ++ | MT9M032_READ_MODE2_ROW_BLC ++ | 0x0007; ++ ++ return mt9m032_write(client, MT9M032_READ_MODE2, reg_val); ++} ++ ++static int mt9m032_set_gain(struct mt9m032 *sensor, s32 val) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ int digital_gain_val; /* in 1/8th (0..127) */ ++ int analog_mul; /* 0 or 1 */ ++ int analog_gain_val; /* in 1/16th. (0..63) */ ++ u16 reg_val; ++ ++ digital_gain_val = 51; /* from setup example */ ++ ++ if (val < 63) { ++ analog_mul = 0; ++ analog_gain_val = val; ++ } else { ++ analog_mul = 1; ++ analog_gain_val = val / 2; ++ } ++ ++ /* a_gain = (1 + analog_mul) + (analog_gain_val + 1) / 16 */ ++ /* overall_gain = a_gain * (1 + digital_gain_val / 8) */ ++ ++ reg_val = ((digital_gain_val & MT9M032_GAIN_DIGITAL_MASK) ++ << MT9M032_GAIN_DIGITAL_SHIFT) ++ | ((analog_mul & 1) << MT9M032_GAIN_AMUL_SHIFT) ++ | (analog_gain_val & MT9M032_GAIN_ANALOG_MASK); ++ ++ return mt9m032_write(client, MT9M032_GAIN_ALL, reg_val); ++} ++ ++static int mt9m032_try_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ if (ctrl->id == V4L2_CID_GAIN && ctrl->val >= 63) { ++ /* round because of multiplier used for values >= 63 */ ++ ctrl->val &= ~1; ++ } ++ ++ return 0; ++} ++ ++static int mt9m032_set_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct mt9m032 *sensor = ++ container_of(ctrl->handler, struct mt9m032, ctrls); ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ int ret; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_GAIN: ++ return mt9m032_set_gain(sensor, ctrl->val); ++ ++ case V4L2_CID_HFLIP: ++ /* case V4L2_CID_VFLIP: -- In the same cluster */ ++ return update_read_mode2(sensor, sensor->vflip->val, ++ sensor->hflip->val); ++ ++ case V4L2_CID_EXPOSURE: ++ ret = mt9m032_write(client, MT9M032_SHUTTER_WIDTH_HIGH, ++ (ctrl->val >> 16) & 0xffff); ++ if (ret < 0) ++ return ret; ++ ++ return mt9m032_write(client, MT9M032_SHUTTER_WIDTH_LOW, ++ ctrl->val & 0xffff); ++ } ++ ++ return 0; ++} ++ ++static struct v4l2_ctrl_ops mt9m032_ctrl_ops = { ++ .s_ctrl = mt9m032_set_ctrl, ++ .try_ctrl = mt9m032_try_ctrl, ++}; ++ ++/* -------------------------------------------------------------------------- */ ++ ++static const struct v4l2_subdev_core_ops mt9m032_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = mt9m032_g_register, ++ .s_register = mt9m032_s_register, ++#endif ++}; ++ ++static const struct v4l2_subdev_video_ops mt9m032_video_ops = { ++ .s_stream = mt9m032_s_stream, ++ .g_frame_interval = mt9m032_get_frame_interval, ++ .s_frame_interval = mt9m032_set_frame_interval, ++}; ++ ++static const struct v4l2_subdev_pad_ops mt9m032_pad_ops = { ++ .enum_mbus_code = mt9m032_enum_mbus_code, ++ .enum_frame_size = mt9m032_enum_frame_size, ++ .get_fmt = mt9m032_get_pad_format, ++ .set_fmt = mt9m032_set_pad_format, ++ .set_crop = mt9m032_set_pad_crop, ++ .get_crop = mt9m032_get_pad_crop, ++}; ++ ++static const struct v4l2_subdev_ops mt9m032_ops = { ++ .core = &mt9m032_core_ops, ++ .video = &mt9m032_video_ops, ++ .pad = &mt9m032_pad_ops, ++}; ++ ++/* ----------------------------------------------------------------------------- ++ * Driver initialization and probing ++ */ ++ ++static int mt9m032_probe(struct i2c_client *client, ++ const struct i2c_device_id *devid) ++{ ++ struct i2c_adapter *adapter = client->adapter; ++ struct mt9m032 *sensor; ++ int chip_version; ++ int ret; ++ ++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { ++ dev_warn(&client->dev, ++ "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); ++ return -EIO; ++ } ++ ++ if (!client->dev.platform_data) ++ return -ENODEV; ++ ++ sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); ++ if (sensor == NULL) ++ return -ENOMEM; ++ ++ mutex_init(&sensor->lock); ++ ++ sensor->pdata = client->dev.platform_data; ++ ++ v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops); ++ sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ chip_version = mt9m032_read(client, MT9M032_CHIP_VERSION); ++ if (chip_version != MT9M032_CHIP_VERSION_VALUE) { ++ dev_err(&client->dev, "MT9M032 not detected, wrong version " ++ "0x%04x\n", chip_version); ++ ret = -ENODEV; ++ goto error_sensor; ++ } ++ ++ dev_info(&client->dev, "MT9M032 detected at address 0x%02x\n", ++ client->addr); ++ ++ sensor->frame_interval.numerator = 1; ++ sensor->frame_interval.denominator = 30; ++ ++ sensor->crop.left = MT9M032_COLUMN_START_DEF; ++ sensor->crop.top = MT9M032_ROW_START_DEF; ++ sensor->crop.width = MT9M032_COLUMN_SIZE_DEF; ++ sensor->crop.height = MT9M032_ROW_SIZE_DEF; ++ ++ sensor->format.width = sensor->crop.width; ++ sensor->format.height = sensor->crop.height; ++ sensor->format.code = V4L2_MBUS_FMT_Y8_1X8; ++ sensor->format.field = V4L2_FIELD_NONE; ++ sensor->format.colorspace = V4L2_COLORSPACE_SRGB; ++ ++ v4l2_ctrl_handler_init(&sensor->ctrls, 4); ++ ++ v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops, ++ V4L2_CID_GAIN, 0, 127, 1, 64); ++ ++ sensor->hflip = v4l2_ctrl_new_std(&sensor->ctrls, ++ &mt9m032_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ sensor->vflip = v4l2_ctrl_new_std(&sensor->ctrls, ++ &mt9m032_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ ++ v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops, ++ V4L2_CID_EXPOSURE, MT9M032_SHUTTER_WIDTH_MIN, ++ MT9M032_SHUTTER_WIDTH_MAX, 1, ++ MT9M032_SHUTTER_WIDTH_DEF); ++ ++ if (sensor->ctrls.error) { ++ ret = sensor->ctrls.error; ++ dev_err(&client->dev, "control initialization error %d\n", ret); ++ goto error_ctrl; ++ } ++ ++ v4l2_ctrl_cluster(2, &sensor->hflip); ++ ++ sensor->subdev.ctrl_handler = &sensor->ctrls; ++ sensor->pad.flags = MEDIA_PAD_FL_SOURCE; ++ ret = media_entity_init(&sensor->subdev.entity, 1, &sensor->pad, 0); ++ if (ret < 0) ++ goto error_ctrl; ++ ++ ret = mt9m032_write(client, MT9M032_RESET, 1); /* reset on */ ++ if (ret < 0) ++ goto error_entity; ++ mt9m032_write(client, MT9M032_RESET, 0); /* reset off */ ++ if (ret < 0) ++ goto error_entity; ++ ++ ret = mt9m032_setup_pll(sensor); ++ if (ret < 0) ++ goto error_entity; ++ usleep_range(10000, 11000); ++ ++ ret = v4l2_ctrl_handler_setup(&sensor->ctrls); ++ if (ret < 0) ++ goto error_entity; ++ ++ /* SIZE */ ++ ret = mt9m032_update_geom_timing(sensor); ++ if (ret < 0) ++ goto error_entity; ++ ++ ret = mt9m032_write(client, 0x41, 0x0000); /* reserved !!! */ ++ if (ret < 0) ++ goto error_entity; ++ ret = mt9m032_write(client, 0x42, 0x0003); /* reserved !!! */ ++ if (ret < 0) ++ goto error_entity; ++ ret = mt9m032_write(client, 0x43, 0x0003); /* reserved !!! */ ++ if (ret < 0) ++ goto error_entity; ++ ret = mt9m032_write(client, 0x7f, 0x0000); /* reserved !!! */ ++ if (ret < 0) ++ goto error_entity; ++ if (sensor->pdata->invert_pixclock) { ++ ret = mt9m032_write(client, MT9M032_PIX_CLK_CTRL, ++ MT9M032_PIX_CLK_CTRL_INV_PIXCLK); ++ if (ret < 0) ++ goto error_entity; ++ } ++ ++ ret = mt9m032_write(client, MT9M032_RESTART, 1); /* Restart on */ ++ if (ret < 0) ++ goto error_entity; ++ msleep(100); ++ ret = mt9m032_write(client, MT9M032_RESTART, 0); /* Restart off */ ++ if (ret < 0) ++ goto error_entity; ++ msleep(100); ++ ret = update_formatter2(sensor, false); ++ if (ret < 0) ++ goto error_entity; ++ ++ return ret; ++ ++error_entity: ++ media_entity_cleanup(&sensor->subdev.entity); ++error_ctrl: ++ v4l2_ctrl_handler_free(&sensor->ctrls); ++error_sensor: ++ mutex_destroy(&sensor->lock); ++ kfree(sensor); ++ return ret; ++} ++ ++static int mt9m032_remove(struct i2c_client *client) ++{ ++ struct v4l2_subdev *subdev = i2c_get_clientdata(client); ++ struct mt9m032 *sensor = to_mt9m032(subdev); ++ ++ v4l2_device_unregister_subdev(&sensor->subdev); ++ v4l2_ctrl_handler_free(&sensor->ctrls); ++ media_entity_cleanup(&sensor->subdev.entity); ++ mutex_destroy(&sensor->lock); ++ kfree(sensor); ++ return 0; ++} ++ ++static const struct i2c_device_id mt9m032_id_table[] = { ++ { MT9M032_NAME, 0 }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(i2c, mt9m032_id_table); ++ ++static struct i2c_driver mt9m032_i2c_driver = { ++ .driver = { ++ .name = MT9M032_NAME, ++ }, ++ .probe = mt9m032_probe, ++ .remove = mt9m032_remove, ++ .id_table = mt9m032_id_table, ++}; ++ ++module_i2c_driver(mt9m032_i2c_driver); ++ ++MODULE_AUTHOR("Martin Hostettler "); ++MODULE_DESCRIPTION("MT9M032 camera sensor driver"); ++MODULE_LICENSE("GPL v2"); +Index: linux-3.3.x86_64/include/media/mt9m032.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/include/media/mt9m032.h +@@ -0,0 +1,36 @@ ++/* ++ * Driver for MT9M032 CMOS Image Sensor from Micron ++ * ++ * Copyright (C) 2010-2011 Lund Engineering ++ * Contact: Gil Lund ++ * Author: Martin Hostettler ++ * ++ * 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 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., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ * ++ */ ++ ++#ifndef MT9M032_H ++#define MT9M032_H ++ ++#define MT9M032_NAME "mt9m032" ++#define MT9M032_I2C_ADDR (0xb8 >> 1) ++ ++struct mt9m032_platform_data { ++ u32 ext_clock; ++ u32 pix_clock; ++ bool invert_pixclock; ++ ++}; ++#endif /* MT9M032_H */ +Index: linux-3.3.x86_64/drivers/media/video/v4l2-dev.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/v4l2-dev.c ++++ linux-3.3.x86_64/drivers/media/video/v4l2-dev.c +@@ -788,7 +788,7 @@ static void __exit videodev_exit(void) + unregister_chrdev_region(dev, VIDEO_NUM_DEVICES); + } + +-module_init(videodev_init) ++subsys_initcall(videodev_init); + module_exit(videodev_exit) + + MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab "); +Index: linux-3.3.x86_64/drivers/media/media-devnode.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/media-devnode.c ++++ linux-3.3.x86_64/drivers/media/media-devnode.c +@@ -312,7 +312,7 @@ static void __exit media_devnode_exit(vo + unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES); + } + +-module_init(media_devnode_init) ++subsys_initcall(media_devnode_init); + module_exit(media_devnode_exit) + + MODULE_AUTHOR("Laurent Pinchart "); +Index: linux-3.3.x86_64/drivers/media/rc/mceusb.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/mceusb.c ++++ linux-3.3.x86_64/drivers/media/rc/mceusb.c +@@ -361,6 +361,8 @@ static struct usb_device_id mceusb_dev_t + { USB_DEVICE(VENDOR_FORMOSA, 0xe03c) }, + /* Formosa Industrial Computing */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe03e) }, ++ /* Formosa Industrial Computing */ ++ { USB_DEVICE(VENDOR_FORMOSA, 0xe042) }, + /* Fintek eHome Infrared Transceiver (HP branded) */ + { USB_DEVICE(VENDOR_FINTEK, 0x5168) }, + /* Fintek eHome Infrared Transceiver */ +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/au8522_dig.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/au8522_dig.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/au8522_dig.c +@@ -604,6 +604,11 @@ static int au8522_set_frontend(struct dv + + au8522_enable_modulation(fe, c->modulation); + ++ /* Allow the tuner to settle */ ++ msleep(100); ++ ++ au8522_enable_modulation(fe, c->modulation); ++ + state->current_frequency = c->frequency; + + return 0; +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/dib0700_core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/dib0700_core.c ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/dib0700_core.c +@@ -677,11 +677,9 @@ static void dib0700_rc_urb_completion(st + u8 toggle; + + deb_info("%s()\n", __func__); +- if (d == NULL) +- return; +- + if (d->rc_dev == NULL) { + /* This will occur if disable_rc_polling=1 */ ++ kfree(purb->transfer_buffer); + usb_free_urb(purb); + return; + } +@@ -690,6 +688,7 @@ static void dib0700_rc_urb_completion(st + + if (purb->status < 0) { + deb_info("discontinuing polling\n"); ++ kfree(purb->transfer_buffer); + usb_free_urb(purb); + return; + } +@@ -784,8 +783,11 @@ int dib0700_rc_setup(struct dvb_usb_devi + dib0700_rc_urb_completion, d); + + ret = usb_submit_urb(purb, GFP_ATOMIC); +- if (ret) ++ if (ret) { + err("rc submit urb failed\n"); ++ kfree(purb->transfer_buffer); ++ usb_free_urb(purb); ++ } + + return ret; + } +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9015.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/af9015.c ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9015.c +@@ -1164,6 +1164,41 @@ static int af9015_af9013_sleep(struct dv + return ret; + } + ++/* override tuner callbacks for resource locking */ ++static int af9015_tuner_init(struct dvb_frontend *fe) ++{ ++ int ret; ++ struct dvb_usb_adapter *adap = fe->dvb->priv; ++ struct af9015_state *priv = adap->dev->priv; ++ ++ if (mutex_lock_interruptible(&adap->dev->usb_mutex)) ++ return -EAGAIN; ++ ++ ret = priv->tuner_init[adap->id](fe); ++ ++ mutex_unlock(&adap->dev->usb_mutex); ++ ++ return ret; ++} ++ ++/* override tuner callbacks for resource locking */ ++static int af9015_tuner_sleep(struct dvb_frontend *fe) ++{ ++ int ret; ++ struct dvb_usb_adapter *adap = fe->dvb->priv; ++ struct af9015_state *priv = adap->dev->priv; ++ ++ if (mutex_lock_interruptible(&adap->dev->usb_mutex)) ++ return -EAGAIN; ++ ++ ret = priv->tuner_sleep[adap->id](fe); ++ ++ mutex_unlock(&adap->dev->usb_mutex); ++ ++ return ret; ++} ++ ++ + static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) + { + int ret; +@@ -1283,6 +1318,7 @@ static struct mxl5007t_config af9015_mxl + static int af9015_tuner_attach(struct dvb_usb_adapter *adap) + { + int ret; ++ struct af9015_state *state = adap->dev->priv; + deb_info("%s:\n", __func__); + + switch (af9015_af9013_config[adap->id].tuner) { +@@ -1340,6 +1376,19 @@ static int af9015_tuner_attach(struct dv + err("Unknown tuner id:%d", + af9015_af9013_config[adap->id].tuner); + } ++ ++ if (adap->fe_adap[0].fe->ops.tuner_ops.init) { ++ state->tuner_init[adap->id] = ++ adap->fe_adap[0].fe->ops.tuner_ops.init; ++ adap->fe_adap[0].fe->ops.tuner_ops.init = af9015_tuner_init; ++ } ++ ++ if (adap->fe_adap[0].fe->ops.tuner_ops.sleep) { ++ state->tuner_sleep[adap->id] = ++ adap->fe_adap[0].fe->ops.tuner_ops.sleep; ++ adap->fe_adap[0].fe->ops.tuner_ops.sleep = af9015_tuner_sleep; ++ } ++ + return ret; + } + +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9015.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/af9015.h ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9015.h +@@ -108,6 +108,8 @@ struct af9015_state { + int (*read_status[2]) (struct dvb_frontend *fe, fe_status_t *status); + int (*init[2]) (struct dvb_frontend *fe); + int (*sleep[2]) (struct dvb_frontend *fe); ++ int (*tuner_init[2]) (struct dvb_frontend *fe); ++ int (*tuner_sleep[2]) (struct dvb_frontend *fe); + }; + + struct af9015_config { +Index: linux-3.3.x86_64/drivers/media/rc/rc-main.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/rc-main.c ++++ linux-3.3.x86_64/drivers/media/rc/rc-main.c +@@ -1029,6 +1029,7 @@ EXPORT_SYMBOL_GPL(rc_free_device); + + int rc_register_device(struct rc_dev *dev) + { ++ static bool raw_init = false; /* raw decoders loaded? */ + static atomic_t devno = ATOMIC_INIT(0); + struct rc_map *rc_map; + const char *path; +@@ -1103,6 +1104,12 @@ int rc_register_device(struct rc_dev *de + kfree(path); + + if (dev->driver_type == RC_DRIVER_IR_RAW) { ++ /* Load raw decoders, if they aren't already */ ++ if (!raw_init) { ++ IR_dprintk(1, "Loading raw decoders\n"); ++ ir_raw_init(); ++ raw_init = true; ++ } + rc = ir_raw_event_register(dev); + if (rc < 0) + goto out_input; +@@ -1176,8 +1183,6 @@ static int __init rc_core_init(void) + return rc; + } + +- /* Initialize/load the decoders/keymap code that will be used */ +- ir_raw_init(); + rc_map_register(&empty_map); + + return 0; +Index: linux-3.3.x86_64/drivers/media/video/soc_camera.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/soc_camera.c ++++ linux-3.3.x86_64/drivers/media/video/soc_camera.c +@@ -526,10 +526,6 @@ static int soc_camera_open(struct file * + }, + }; + +- ret = soc_camera_power_on(icd, icl); +- if (ret < 0) +- goto epower; +- + /* The camera could have been already on, try to reset */ + if (icl->reset) + icl->reset(icd->pdev); +@@ -540,6 +536,10 @@ static int soc_camera_open(struct file * + goto eiciadd; + } + ++ ret = soc_camera_power_on(icd, icl); ++ if (ret < 0) ++ goto epower; ++ + pm_runtime_enable(&icd->vdev->dev); + ret = pm_runtime_resume(&icd->vdev->dev); + if (ret < 0 && ret != -ENOSYS) +@@ -578,10 +578,10 @@ einitvb: + esfmt: + pm_runtime_disable(&icd->vdev->dev); + eresume: +- ici->ops->remove(icd); +-eiciadd: + soc_camera_power_off(icd, icl); + epower: ++ ici->ops->remove(icd); ++eiciadd: + icd->use_count--; + module_put(ici->ops->owner); + +@@ -1050,6 +1050,14 @@ static int soc_camera_probe(struct soc_c + if (ret < 0) + goto ereg; + ++ /* The camera could have been already on, try to reset */ ++ if (icl->reset) ++ icl->reset(icd->pdev); ++ ++ ret = ici->ops->add(icd); ++ if (ret < 0) ++ goto eadd; ++ + /* + * This will not yet call v4l2_subdev_core_ops::s_power(1), because the + * subdevice has not been initialised yet. We'll have to call it once +@@ -1060,14 +1068,6 @@ static int soc_camera_probe(struct soc_c + if (ret < 0) + goto epower; + +- /* The camera could have been already on, try to reset */ +- if (icl->reset) +- icl->reset(icd->pdev); +- +- ret = ici->ops->add(icd); +- if (ret < 0) +- goto eadd; +- + /* Must have icd->vdev before registering the device */ + ret = video_dev_create(icd); + if (ret < 0) +@@ -1165,10 +1165,10 @@ eadddev: + video_device_release(icd->vdev); + icd->vdev = NULL; + evdc: +- ici->ops->remove(icd); +-eadd: + soc_camera_power_off(icd, icl); + epower: ++ ici->ops->remove(icd); ++eadd: + regulator_bulk_free(icl->num_regulators, icl->regulators); + ereg: + v4l2_ctrl_handler_free(&icd->ctrl_handler); +Index: linux-3.3.x86_64/drivers/media/video/sh_mobile_ceu_camera.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/sh_mobile_ceu_camera.c ++++ linux-3.3.x86_64/drivers/media/video/sh_mobile_ceu_camera.c +@@ -112,6 +112,10 @@ struct sh_mobile_ceu_dev { + + u32 cflcr; + ++ /* static max sizes either from platform data or default */ ++ int max_width; ++ int max_height; ++ + enum v4l2_field field; + int sequence; + +@@ -1081,7 +1085,15 @@ static int sh_mobile_ceu_get_formats(str + if (ret < 0) + return ret; + +- while ((mf.width > 2560 || mf.height > 1920) && shift < 4) { ++ /* ++ * All currently existing CEU implementations support 2560x1920 ++ * or larger frames. If the sensor is proposing too big a frame, ++ * don't bother with possibly supportred by the CEU larger ++ * sizes, just try VGA multiples. If needed, this can be ++ * adjusted in the future. ++ */ ++ while ((mf.width > pcdev->max_width || ++ mf.height > pcdev->max_height) && shift < 4) { + /* Try 2560x1920, 1280x960, 640x480, 320x240 */ + mf.width = 2560 >> shift; + mf.height = 1920 >> shift; +@@ -1377,6 +1389,8 @@ static int client_s_crop(struct soc_came + static int client_s_fmt(struct soc_camera_device *icd, + struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) + { ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct sh_mobile_ceu_dev *pcdev = ici->priv; + struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->parent; +@@ -1410,8 +1424,8 @@ static int client_s_fmt(struct soc_camer + if (ret < 0) + return ret; + +- max_width = min(cap.bounds.width, 2560); +- max_height = min(cap.bounds.height, 1920); ++ max_width = min(cap.bounds.width, pcdev->max_width); ++ max_height = min(cap.bounds.height, pcdev->max_height); + + /* Camera set a format, but geometry is not precise, try to improve */ + tmp_w = mf->width; +@@ -1551,7 +1565,7 @@ static int sh_mobile_ceu_set_crop(struct + if (ret < 0) + return ret; + +- if (mf.width > 2560 || mf.height > 1920) ++ if (mf.width > pcdev->max_width || mf.height > pcdev->max_height) + return -EINVAL; + + /* 4. Calculate camera scales */ +@@ -1834,6 +1848,8 @@ static int sh_mobile_ceu_set_fmt(struct + static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) + { ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct sh_mobile_ceu_dev *pcdev = ici->priv; + const struct soc_camera_format_xlate *xlate; + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); +@@ -1854,8 +1870,8 @@ static int sh_mobile_ceu_try_fmt(struct + /* FIXME: calculate using depth and bus width */ + + /* CFSZR requires height and width to be 4-pixel aligned */ +- v4l_bound_align_image(&pix->width, 2, 2560, 2, +- &pix->height, 4, 1920, 2, 0); ++ v4l_bound_align_image(&pix->width, 2, pcdev->max_width, 2, ++ &pix->height, 4, pcdev->max_height, 2, 0); + + width = pix->width; + height = pix->height; +@@ -1890,8 +1906,8 @@ static int sh_mobile_ceu_try_fmt(struct + * requested a bigger rectangle, it will not return a + * smaller one. + */ +- mf.width = 2560; +- mf.height = 1920; ++ mf.width = pcdev->max_width; ++ mf.height = pcdev->max_height; + ret = v4l2_device_call_until_err(sd->v4l2_dev, + soc_camera_grp_id(icd), video, + try_mbus_fmt, &mf); +@@ -2082,6 +2098,9 @@ static int __devinit sh_mobile_ceu_probe + goto exit_kfree; + } + ++ pcdev->max_width = pcdev->pdata->max_width ? : 2560; ++ pcdev->max_height = pcdev->pdata->max_height ? : 1920; ++ + base = ioremap_nocache(res->start, resource_size(res)); + if (!base) { + err = -ENXIO; +Index: linux-3.3.x86_64/include/media/sh_mobile_ceu.h +=================================================================== +--- linux-3.3.x86_64.orig/include/media/sh_mobile_ceu.h ++++ linux-3.3.x86_64/include/media/sh_mobile_ceu.h +@@ -18,6 +18,8 @@ struct sh_mobile_ceu_companion { + + struct sh_mobile_ceu_info { + unsigned long flags; ++ int max_width; ++ int max_height; + struct sh_mobile_ceu_companion *csi2; + }; + +Index: linux-3.3.x86_64/drivers/media/video/pxa_camera.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/pxa_camera.c ++++ linux-3.3.x86_64/drivers/media/video/pxa_camera.c +@@ -921,12 +921,12 @@ static void pxa_camera_activate(struct p + /* "Safe default" - 13MHz */ + recalculate_fifo_timeout(pcdev, 13000000); + +- clk_enable(pcdev->clk); ++ clk_prepare_enable(pcdev->clk); + } + + static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) + { +- clk_disable(pcdev->clk); ++ clk_disable_unprepare(pcdev->clk); + } + + static irqreturn_t pxa_camera_irq(int irq, void *data) +Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-i2c.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx-i2c.c ++++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-i2c.c +@@ -41,14 +41,6 @@ static unsigned int i2c_debug; + module_param(i2c_debug, int, 0644); + MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); + +- +-#define dprintk1(lvl, fmt, args...) \ +-do { \ +- if (i2c_debug >= lvl) { \ +- printk(fmt, ##args); \ +- } \ +-} while (0) +- + #define dprintk2(lvl, fmt, args...) \ + do { \ + if (i2c_debug >= lvl) { \ +Index: linux-3.3.x86_64/drivers/media/video/marvell-ccic/mcam-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/marvell-ccic/mcam-core.c ++++ linux-3.3.x86_64/drivers/media/video/marvell-ccic/mcam-core.c +@@ -509,11 +509,17 @@ static void mcam_sg_next_buffer(struct m + + buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue); + list_del_init(&buf->queue); ++ /* ++ * Very Bad Not Good Things happen if you don't clear ++ * C1_DESC_ENA before making any descriptor changes. ++ */ ++ mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_ENA); + mcam_reg_write(cam, REG_DMA_DESC_Y, buf->dma_desc_pa); + mcam_reg_write(cam, REG_DESC_LEN_Y, + buf->dma_desc_nent*sizeof(struct mcam_dma_desc)); + mcam_reg_write(cam, REG_DESC_LEN_U, 0); + mcam_reg_write(cam, REG_DESC_LEN_V, 0); ++ mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); + cam->vb_bufs[0] = buf; + } + +@@ -533,7 +539,6 @@ static void mcam_ctlr_dma_sg(struct mcam + + mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_3WORD); + mcam_sg_next_buffer(cam); +- mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); + cam->nbufs = 3; + } + +@@ -556,17 +561,16 @@ static void mcam_dma_sg_done(struct mcam + struct mcam_vb_buffer *buf = cam->vb_bufs[0]; + + /* +- * Very Bad Not Good Things happen if you don't clear +- * C1_DESC_ENA before making any descriptor changes. ++ * If we're no longer supposed to be streaming, don't do anything. + */ +- mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_ENA); ++ if (cam->state != S_STREAMING) ++ return; + /* + * If we have another buffer available, put it in and + * restart the engine. + */ + if (!list_empty(&cam->buffers)) { + mcam_sg_next_buffer(cam); +- mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); + mcam_ctlr_start(cam); + /* + * Otherwise set CF_SG_RESTART and the controller will +@@ -737,7 +741,14 @@ static void mcam_ctlr_stop_dma(struct mc + mcam_ctlr_stop(cam); + cam->state = S_IDLE; + spin_unlock_irqrestore(&cam->dev_lock, flags); +- msleep(40); ++ /* ++ * This is a brutally long sleep, but experience shows that ++ * it can take the controller a while to get the message that ++ * it needs to stop grabbing frames. In particular, we can ++ * sometimes (on mmp) get a frame at the end WITHOUT the ++ * start-of-frame indication. ++ */ ++ msleep(150); + if (test_bit(CF_DMA_ACTIVE, &cam->flags)) + cam_err(cam, "Timeout waiting for DMA to end\n"); + /* This would be bad news - what now? */ +@@ -880,6 +891,7 @@ static int mcam_read_setup(struct mcam_c + * Turn it loose. + */ + spin_lock_irqsave(&cam->dev_lock, flags); ++ clear_bit(CF_DMA_ACTIVE, &cam->flags); + mcam_reset_buffers(cam); + mcam_ctlr_irq_enable(cam); + cam->state = S_STREAMING; +@@ -922,7 +934,7 @@ static void mcam_vb_buf_queue(struct vb2 + spin_lock_irqsave(&cam->dev_lock, flags); + start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers); + list_add(&mvb->queue, &cam->buffers); +- if (test_bit(CF_SG_RESTART, &cam->flags)) ++ if (cam->state == S_STREAMING && test_bit(CF_SG_RESTART, &cam->flags)) + mcam_sg_restart(cam); + spin_unlock_irqrestore(&cam->dev_lock, flags); + if (start) +@@ -1555,15 +1567,12 @@ static int mcam_v4l_release(struct file + { + struct mcam_camera *cam = filp->private_data; + +- cam_err(cam, "Release, %d frames, %d singles, %d delivered\n", frames, ++ cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n", frames, + singles, delivered); + mutex_lock(&cam->s_mutex); + (cam->users)--; +- if (filp == cam->owner) { +- mcam_ctlr_stop_dma(cam); +- cam->owner = NULL; +- } + if (cam->users == 0) { ++ mcam_ctlr_stop_dma(cam); + mcam_cleanup_vb2(cam); + mcam_ctlr_power_down(cam); + if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read) +@@ -1688,6 +1697,8 @@ int mccic_irq(struct mcam_camera *cam, u + if (irqs & (IRQ_EOF0 << frame)) { + mcam_frame_complete(cam, frame); + handled = 1; ++ if (cam->buffer_mode == B_DMA_sg) ++ break; + } + /* + * If a frame starts, note that we have DMA active. This +Index: linux-3.3.x86_64/drivers/media/video/marvell-ccic/mcam-core.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/marvell-ccic/mcam-core.h ++++ linux-3.3.x86_64/drivers/media/video/marvell-ccic/mcam-core.h +@@ -107,7 +107,6 @@ struct mcam_camera { + enum mcam_state state; + unsigned long flags; /* Buffer status, mainly (dev_lock) */ + int users; /* How many open FDs */ +- struct file *owner; /* Who has data access (v4l2) */ + + /* + * Subsystem structures. +Index: linux-3.3.x86_64/drivers/media/video/marvell-ccic/mmp-driver.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/marvell-ccic/mmp-driver.c ++++ linux-3.3.x86_64/drivers/media/video/marvell-ccic/mmp-driver.c +@@ -106,6 +106,13 @@ static struct mmp_camera *mmpcam_find_de + /* + * Power control. + */ ++static void mmpcam_power_up_ctlr(struct mmp_camera *cam) ++{ ++ iowrite32(0x3f, cam->power_regs + REG_CCIC_DCGCR); ++ iowrite32(0x3805b, cam->power_regs + REG_CCIC_CRCR); ++ mdelay(1); ++} ++ + static void mmpcam_power_up(struct mcam_camera *mcam) + { + struct mmp_camera *cam = mcam_to_cam(mcam); +@@ -113,9 +120,7 @@ static void mmpcam_power_up(struct mcam_ + /* + * Turn on power and clocks to the controller. + */ +- iowrite32(0x3f, cam->power_regs + REG_CCIC_DCGCR); +- iowrite32(0x3805b, cam->power_regs + REG_CCIC_CRCR); +- mdelay(1); ++ mmpcam_power_up_ctlr(cam); + /* + * Provide power to the sensor. + */ +@@ -335,7 +340,7 @@ static int mmpcam_resume(struct platform + * touch a register even if nothing was active before; trust + * me, it's better this way. + */ +- mmpcam_power_up(&cam->mcam); ++ mmpcam_power_up_ctlr(cam); + return mccic_resume(&cam->mcam); + } + +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/mxl111sf.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/mxl111sf.c ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/mxl111sf.c +@@ -340,7 +340,6 @@ static int mxl111sf_ep6_streaming_ctrl(s + struct mxl111sf_state *state = d->priv; + struct mxl111sf_adap_state *adap_state = adap->fe_adap[adap->active_fe].priv; + int ret = 0; +- u8 tmp; + + deb_info("%s(%d)\n", __func__, onoff); + +Index: linux-3.3.x86_64/drivers/media/video/gspca/ov534_9.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/gspca/ov534_9.c ++++ linux-3.3.x86_64/drivers/media/video/gspca/ov534_9.c +@@ -1107,16 +1107,34 @@ static void setbrightness(struct gspca_d + { + struct sd *sd = (struct sd *) gspca_dev; + u8 val; ++ s8 sval; + + if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS)) + return; +- val = sd->ctrls[BRIGHTNESS].val; +- if (val < 8) +- val = 15 - val; /* f .. 8 */ +- else +- val = val - 8; /* 0 .. 7 */ +- sccb_write(gspca_dev, 0x55, /* brtn - brightness adjustment */ +- 0x0f | (val << 4)); ++ if (sd->sensor == SENSOR_OV562x) { ++ sval = sd->ctrls[BRIGHTNESS].val; ++ val = 0x76; ++ val += sval; ++ sccb_write(gspca_dev, 0x24, val); ++ val = 0x6a; ++ val += sval; ++ sccb_write(gspca_dev, 0x25, val); ++ if (sval < -40) ++ val = 0x71; ++ else if (sval < 20) ++ val = 0x94; ++ else ++ val = 0xe6; ++ sccb_write(gspca_dev, 0x26, val); ++ } else { ++ val = sd->ctrls[BRIGHTNESS].val; ++ if (val < 8) ++ val = 15 - val; /* f .. 8 */ ++ else ++ val = val - 8; /* 0 .. 7 */ ++ sccb_write(gspca_dev, 0x55, /* brtn - brightness adjustment */ ++ 0x0f | (val << 4)); ++ } + } + + static void setcontrast(struct gspca_dev *gspca_dev) +@@ -1339,7 +1357,16 @@ static int sd_init(struct gspca_dev *gsp + reg_w(gspca_dev, 0x56, 0x17); + } else if ((sensor_id & 0xfff0) == 0x5620) { + sd->sensor = SENSOR_OV562x; +- ++ gspca_dev->ctrl_dis = (1 << CONTRAST) | ++ (1 << AUTOGAIN) | ++ (1 << EXPOSURE) | ++ (1 << SHARPNESS) | ++ (1 << SATUR) | ++ (1 << LIGHTFREQ); ++ ++ sd->ctrls[BRIGHTNESS].min = -90; ++ sd->ctrls[BRIGHTNESS].max = 90; ++ sd->ctrls[BRIGHTNESS].def = 0; + gspca_dev->cam.cam_mode = ov562x_mode; + gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode); + +@@ -1360,8 +1387,12 @@ static int sd_start(struct gspca_dev *gs + { + struct sd *sd = (struct sd *) gspca_dev; + +- if (sd->sensor == SENSOR_OV971x || sd->sensor == SENSOR_OV562x) ++ if (sd->sensor == SENSOR_OV971x) + return gspca_dev->usb_err; ++ else if (sd->sensor == SENSOR_OV562x) { ++ setbrightness(gspca_dev); ++ return gspca_dev->usb_err; ++ } + switch (gspca_dev->curr_mode) { + case QVGA_MODE: /* 320x240 */ + sccb_w_array(gspca_dev, ov965x_start_1_vga, +Index: linux-3.3.x86_64/drivers/media/video/gspca/sn9c20x.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/gspca/sn9c20x.c ++++ linux-3.3.x86_64/drivers/media/video/gspca/sn9c20x.c +@@ -1,5 +1,7 @@ + /* + * Sonix sn9c201 sn9c202 library ++ * ++ * Copyright (C) 2012 Jean-Francois Moine + * Copyright (C) 2008-2009 microdia project + * Copyright (C) 2009 Brian Johnson + * +@@ -33,8 +35,6 @@ MODULE_AUTHOR("Brian Johnson dev; + int result; ++ ++ if (gspca_dev->usb_err < 0) ++ return; + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + 0x00, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, +@@ -1125,17 +1103,19 @@ static int reg_r(struct gspca_dev *gspca + length, + 500); + if (unlikely(result < 0 || result != length)) { +- pr_err("Read register failed 0x%02X\n", reg); +- return -EIO; ++ pr_err("Read register %02x failed %d\n", reg, result); ++ gspca_dev->usb_err = result; + } +- return 0; + } + +-static int reg_w(struct gspca_dev *gspca_dev, u16 reg, ++static void reg_w(struct gspca_dev *gspca_dev, u16 reg, + const u8 *buffer, int length) + { + struct usb_device *dev = gspca_dev->dev; + int result; ++ ++ if (gspca_dev->usb_err < 0) ++ return; + memcpy(gspca_dev->usb_buf, buffer, length); + result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + 0x08, +@@ -1146,38 +1126,41 @@ static int reg_w(struct gspca_dev *gspca + length, + 500); + if (unlikely(result < 0 || result != length)) { +- pr_err("Write register failed index 0x%02X\n", reg); +- return -EIO; ++ pr_err("Write register %02x failed %d\n", reg, result); ++ gspca_dev->usb_err = result; + } +- return 0; + } + +-static int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value) ++static void reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value) + { +- u8 data[1] = {value}; +- return reg_w(gspca_dev, reg, data, 1); ++ reg_w(gspca_dev, reg, &value, 1); + } + +-static int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer) ++static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer) + { + int i; ++ + reg_w(gspca_dev, 0x10c0, buffer, 8); + for (i = 0; i < 5; i++) { + reg_r(gspca_dev, 0x10c0, 1); ++ if (gspca_dev->usb_err < 0) ++ return; + if (gspca_dev->usb_buf[0] & 0x04) { +- if (gspca_dev->usb_buf[0] & 0x08) +- return -EIO; +- return 0; ++ if (gspca_dev->usb_buf[0] & 0x08) { ++ pr_err("i2c_w error\n"); ++ gspca_dev->usb_err = -EIO; ++ } ++ return; + } +- msleep(1); ++ msleep(10); + } +- return -EIO; ++ pr_err("i2c_w reg %02x no response\n", buffer[2]); ++/* gspca_dev->usb_err = -EIO; fixme: may occur */ + } + +-static int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) ++static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) + { + struct sd *sd = (struct sd *) gspca_dev; +- + u8 row[8]; + + /* +@@ -1193,10 +1176,19 @@ static int i2c_w1(struct gspca_dev *gspc + row[6] = 0x00; + row[7] = 0x10; + +- return i2c_w(gspca_dev, row); ++ i2c_w(gspca_dev, row); ++} ++ ++static void i2c_w1_buf(struct gspca_dev *gspca_dev, ++ struct i2c_reg_u8 *buf, int sz) ++{ ++ while (--sz >= 0) { ++ i2c_w1(gspca_dev, buf->reg, buf->val); ++ buf++; ++ } + } + +-static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) ++static void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) + { + struct sd *sd = (struct sd *) gspca_dev; + u8 row[8]; +@@ -1208,16 +1200,25 @@ static int i2c_w2(struct gspca_dev *gspc + row[0] = 0x81 | (3 << 4); + row[1] = sd->i2c_addr; + row[2] = reg; +- row[3] = (val >> 8) & 0xff; +- row[4] = val & 0xff; ++ row[3] = val >> 8; ++ row[4] = val; + row[5] = 0x00; + row[6] = 0x00; + row[7] = 0x10; + +- return i2c_w(gspca_dev, row); ++ i2c_w(gspca_dev, row); + } + +-static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) ++static void i2c_w2_buf(struct gspca_dev *gspca_dev, ++ struct i2c_reg_u16 *buf, int sz) ++{ ++ while (--sz >= 0) { ++ i2c_w2(gspca_dev, buf->reg, buf->val); ++ buf++; ++ } ++} ++ ++static void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) + { + struct sd *sd = (struct sd *) gspca_dev; + u8 row[8]; +@@ -1230,19 +1231,15 @@ static int i2c_r1(struct gspca_dev *gspc + row[5] = 0; + row[6] = 0; + row[7] = 0x10; +- if (i2c_w(gspca_dev, row) < 0) +- return -EIO; ++ i2c_w(gspca_dev, row); + row[0] = 0x81 | (1 << 4) | 0x02; + row[2] = 0; +- if (i2c_w(gspca_dev, row) < 0) +- return -EIO; +- if (reg_r(gspca_dev, 0x10c2, 5) < 0) +- return -EIO; ++ i2c_w(gspca_dev, row); ++ reg_r(gspca_dev, 0x10c2, 5); + *val = gspca_dev->usb_buf[4]; +- return 0; + } + +-static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) ++static void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) + { + struct sd *sd = (struct sd *) gspca_dev; + u8 row[8]; +@@ -1255,233 +1252,204 @@ static int i2c_r2(struct gspca_dev *gspc + row[5] = 0; + row[6] = 0; + row[7] = 0x10; +- if (i2c_w(gspca_dev, row) < 0) +- return -EIO; ++ i2c_w(gspca_dev, row); + row[0] = 0x81 | (2 << 4) | 0x02; + row[2] = 0; +- if (i2c_w(gspca_dev, row) < 0) +- return -EIO; +- if (reg_r(gspca_dev, 0x10c2, 5) < 0) +- return -EIO; ++ i2c_w(gspca_dev, row); ++ reg_r(gspca_dev, 0x10c2, 5); + *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; +- return 0; + } + +-static int ov9650_init_sensor(struct gspca_dev *gspca_dev) ++static void ov9650_init_sensor(struct gspca_dev *gspca_dev) + { +- int i; + u16 id; + struct sd *sd = (struct sd *) gspca_dev; + +- if (i2c_r2(gspca_dev, 0x1c, &id) < 0) +- return -EINVAL; ++ i2c_r2(gspca_dev, 0x1c, &id); ++ if (gspca_dev->usb_err < 0) ++ return; + + if (id != 0x7fa2) { + pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id); +- return -ENODEV; ++ gspca_dev->usb_err = -ENODEV; ++ return; + } + +- for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) { +- if (i2c_w1(gspca_dev, ov9650_init[i].reg, +- ov9650_init[i].val) < 0) { +- pr_err("OV9650 sensor initialization failed\n"); +- return -ENODEV; +- } +- } ++ i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ ++ msleep(200); ++ i2c_w1_buf(gspca_dev, ov9650_init, ARRAY_SIZE(ov9650_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("OV9650 sensor initialization failed\n"); + sd->hstart = 1; + sd->vstart = 7; +- return 0; + } + +-static int ov9655_init_sensor(struct gspca_dev *gspca_dev) ++static void ov9655_init_sensor(struct gspca_dev *gspca_dev) + { +- int i; + struct sd *sd = (struct sd *) gspca_dev; + +- for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) { +- if (i2c_w1(gspca_dev, ov9655_init[i].reg, +- ov9655_init[i].val) < 0) { +- pr_err("OV9655 sensor initialization failed\n"); +- return -ENODEV; +- } +- } ++ i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ ++ msleep(200); ++ i2c_w1_buf(gspca_dev, ov9655_init, ARRAY_SIZE(ov9655_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("OV9655 sensor initialization failed\n"); ++ + /* disable hflip and vflip */ +- gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); ++ gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP); + sd->hstart = 1; + sd->vstart = 2; +- return 0; + } + +-static int soi968_init_sensor(struct gspca_dev *gspca_dev) ++static void soi968_init_sensor(struct gspca_dev *gspca_dev) + { +- int i; + struct sd *sd = (struct sd *) gspca_dev; + +- for (i = 0; i < ARRAY_SIZE(soi968_init); i++) { +- if (i2c_w1(gspca_dev, soi968_init[i].reg, +- soi968_init[i].val) < 0) { +- pr_err("SOI968 sensor initialization failed\n"); +- return -ENODEV; +- } +- } ++ i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ ++ msleep(200); ++ i2c_w1_buf(gspca_dev, soi968_init, ARRAY_SIZE(soi968_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("SOI968 sensor initialization failed\n"); ++ + /* disable hflip and vflip */ +- gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) +- | (1 << EXPOSURE_IDX); ++ gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP) ++ | (1 << EXPOSURE); + sd->hstart = 60; + sd->vstart = 11; +- return 0; + } + +-static int ov7660_init_sensor(struct gspca_dev *gspca_dev) ++static void ov7660_init_sensor(struct gspca_dev *gspca_dev) + { +- int i; + struct sd *sd = (struct sd *) gspca_dev; + +- for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) { +- if (i2c_w1(gspca_dev, ov7660_init[i].reg, +- ov7660_init[i].val) < 0) { +- pr_err("OV7660 sensor initialization failed\n"); +- return -ENODEV; +- } +- } ++ i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ ++ msleep(200); ++ i2c_w1_buf(gspca_dev, ov7660_init, ARRAY_SIZE(ov7660_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("OV7660 sensor initialization failed\n"); + sd->hstart = 3; + sd->vstart = 3; +- return 0; + } + +-static int ov7670_init_sensor(struct gspca_dev *gspca_dev) ++static void ov7670_init_sensor(struct gspca_dev *gspca_dev) + { +- int i; + struct sd *sd = (struct sd *) gspca_dev; + +- for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) { +- if (i2c_w1(gspca_dev, ov7670_init[i].reg, +- ov7670_init[i].val) < 0) { +- pr_err("OV7670 sensor initialization failed\n"); +- return -ENODEV; +- } +- } ++ i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ ++ msleep(200); ++ i2c_w1_buf(gspca_dev, ov7670_init, ARRAY_SIZE(ov7670_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("OV7670 sensor initialization failed\n"); ++ + /* disable hflip and vflip */ +- gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); ++ gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP); + sd->hstart = 0; + sd->vstart = 1; +- return 0; + } + +-static int mt9v_init_sensor(struct gspca_dev *gspca_dev) ++static void mt9v_init_sensor(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- int i; + u16 value; +- int ret; + + sd->i2c_addr = 0x5d; +- ret = i2c_r2(gspca_dev, 0xff, &value); +- if ((ret == 0) && (value == 0x8243)) { +- for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) { +- if (i2c_w2(gspca_dev, mt9v011_init[i].reg, +- mt9v011_init[i].val) < 0) { +- pr_err("MT9V011 sensor initialization failed\n"); +- return -ENODEV; +- } ++ i2c_r2(gspca_dev, 0xff, &value); ++ if (gspca_dev->usb_err >= 0 ++ && value == 0x8243) { ++ i2c_w2_buf(gspca_dev, mt9v011_init, ARRAY_SIZE(mt9v011_init)); ++ if (gspca_dev->usb_err < 0) { ++ pr_err("MT9V011 sensor initialization failed\n"); ++ return; + } + sd->hstart = 2; + sd->vstart = 2; + sd->sensor = SENSOR_MT9V011; + pr_info("MT9V011 sensor detected\n"); +- return 0; ++ return; + } + ++ gspca_dev->usb_err = 0; + sd->i2c_addr = 0x5c; + i2c_w2(gspca_dev, 0x01, 0x0004); +- ret = i2c_r2(gspca_dev, 0xff, &value); +- if ((ret == 0) && (value == 0x823a)) { +- for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) { +- if (i2c_w2(gspca_dev, mt9v111_init[i].reg, +- mt9v111_init[i].val) < 0) { +- pr_err("MT9V111 sensor initialization failed\n"); +- return -ENODEV; +- } ++ i2c_r2(gspca_dev, 0xff, &value); ++ if (gspca_dev->usb_err >= 0 ++ && value == 0x823a) { ++ i2c_w2_buf(gspca_dev, mt9v111_init, ARRAY_SIZE(mt9v111_init)); ++ if (gspca_dev->usb_err < 0) { ++ pr_err("MT9V111 sensor initialization failed\n"); ++ return; + } +- gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) +- | (1 << AUTOGAIN_IDX) +- | (1 << GAIN_IDX); ++ gspca_dev->ctrl_dis = (1 << EXPOSURE) ++ | (1 << AUTOGAIN) ++ | (1 << GAIN); + sd->hstart = 2; + sd->vstart = 2; + sd->sensor = SENSOR_MT9V111; + pr_info("MT9V111 sensor detected\n"); +- return 0; ++ return; + } + ++ gspca_dev->usb_err = 0; + sd->i2c_addr = 0x5d; +- ret = i2c_w2(gspca_dev, 0xf0, 0x0000); +- if (ret < 0) { ++ i2c_w2(gspca_dev, 0xf0, 0x0000); ++ if (gspca_dev->usb_err < 0) { ++ gspca_dev->usb_err = 0; + sd->i2c_addr = 0x48; + i2c_w2(gspca_dev, 0xf0, 0x0000); + } +- ret = i2c_r2(gspca_dev, 0x00, &value); +- if ((ret == 0) && (value == 0x1229)) { +- for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) { +- if (i2c_w2(gspca_dev, mt9v112_init[i].reg, +- mt9v112_init[i].val) < 0) { +- pr_err("MT9V112 sensor initialization failed\n"); +- return -ENODEV; +- } ++ i2c_r2(gspca_dev, 0x00, &value); ++ if (gspca_dev->usb_err >= 0 ++ && value == 0x1229) { ++ i2c_w2_buf(gspca_dev, mt9v112_init, ARRAY_SIZE(mt9v112_init)); ++ if (gspca_dev->usb_err < 0) { ++ pr_err("MT9V112 sensor initialization failed\n"); ++ return; + } + sd->hstart = 6; + sd->vstart = 2; + sd->sensor = SENSOR_MT9V112; + pr_info("MT9V112 sensor detected\n"); +- return 0; ++ return; + } + +- return -ENODEV; ++ gspca_dev->usb_err = -ENODEV; + } + +-static int mt9m112_init_sensor(struct gspca_dev *gspca_dev) ++static void mt9m112_init_sensor(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- int i; +- for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) { +- if (i2c_w2(gspca_dev, mt9m112_init[i].reg, +- mt9m112_init[i].val) < 0) { +- pr_err("MT9M112 sensor initialization failed\n"); +- return -ENODEV; +- } +- } +- gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) +- | (1 << GAIN_IDX); ++ ++ i2c_w2_buf(gspca_dev, mt9m112_init, ARRAY_SIZE(mt9m112_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("MT9M112 sensor initialization failed\n"); ++ ++ gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN) ++ | (1 << GAIN); + sd->hstart = 0; + sd->vstart = 2; +- return 0; + } + +-static int mt9m111_init_sensor(struct gspca_dev *gspca_dev) ++static void mt9m111_init_sensor(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- int i; +- for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) { +- if (i2c_w2(gspca_dev, mt9m111_init[i].reg, +- mt9m111_init[i].val) < 0) { +- pr_err("MT9M111 sensor initialization failed\n"); +- return -ENODEV; +- } +- } +- gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) +- | (1 << GAIN_IDX); ++ ++ i2c_w2_buf(gspca_dev, mt9m111_init, ARRAY_SIZE(mt9m111_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("MT9M111 sensor initialization failed\n"); ++ ++ gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN) ++ | (1 << GAIN); + sd->hstart = 0; + sd->vstart = 2; +- return 0; + } + +-static int mt9m001_init_sensor(struct gspca_dev *gspca_dev) ++static void mt9m001_init_sensor(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- int i; + u16 id; + +- if (i2c_r2(gspca_dev, 0x00, &id) < 0) +- return -EINVAL; ++ i2c_r2(gspca_dev, 0x00, &id); ++ if (gspca_dev->usb_err < 0) ++ return; + + /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ + switch (id) { +@@ -1494,85 +1462,78 @@ static int mt9m001_init_sensor(struct gs + break; + default: + pr_err("No MT9M001 chip detected, ID = %x\n\n", id); +- return -ENODEV; ++ gspca_dev->usb_err = -ENODEV; ++ return; + } + +- for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) { +- if (i2c_w2(gspca_dev, mt9m001_init[i].reg, +- mt9m001_init[i].val) < 0) { +- pr_err("MT9M001 sensor initialization failed\n"); +- return -ENODEV; +- } +- } ++ i2c_w2_buf(gspca_dev, mt9m001_init, ARRAY_SIZE(mt9m001_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("MT9M001 sensor initialization failed\n"); ++ + /* disable hflip and vflip */ +- gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); ++ gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP); + sd->hstart = 1; + sd->vstart = 1; +- return 0; + } + +-static int hv7131r_init_sensor(struct gspca_dev *gspca_dev) ++static void hv7131r_init_sensor(struct gspca_dev *gspca_dev) + { +- int i; + struct sd *sd = (struct sd *) gspca_dev; + +- for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) { +- if (i2c_w1(gspca_dev, hv7131r_init[i].reg, +- hv7131r_init[i].val) < 0) { +- pr_err("HV7131R Sensor initialization failed\n"); +- return -ENODEV; +- } +- } ++ i2c_w1_buf(gspca_dev, hv7131r_init, ARRAY_SIZE(hv7131r_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("HV7131R Sensor initialization failed\n"); ++ + sd->hstart = 0; + sd->vstart = 1; +- return 0; + } + +-static int set_cmatrix(struct gspca_dev *gspca_dev) ++static void set_cmatrix(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- s32 hue_coord, hue_index = 180 + sd->hue; ++ int satur; ++ s32 hue_coord, hue_index = 180 + sd->ctrls[HUE].val; + u8 cmatrix[21]; + + memset(cmatrix, 0, sizeof cmatrix); +- cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26; ++ cmatrix[2] = (sd->ctrls[CONTRAST].val * 0x25 / 0x100) + 0x26; + cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25; + cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25; +- cmatrix[18] = sd->brightness - 0x80; ++ cmatrix[18] = sd->ctrls[BRIGHTNESS].val - 0x80; + +- hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8; ++ satur = sd->ctrls[SATURATION].val; ++ hue_coord = (hsv_red_x[hue_index] * satur) >> 8; + cmatrix[6] = hue_coord; + cmatrix[7] = (hue_coord >> 8) & 0x0f; + +- hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8; ++ hue_coord = (hsv_red_y[hue_index] * satur) >> 8; + cmatrix[8] = hue_coord; + cmatrix[9] = (hue_coord >> 8) & 0x0f; + +- hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8; ++ hue_coord = (hsv_green_x[hue_index] * satur) >> 8; + cmatrix[10] = hue_coord; + cmatrix[11] = (hue_coord >> 8) & 0x0f; + +- hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8; ++ hue_coord = (hsv_green_y[hue_index] * satur) >> 8; + cmatrix[12] = hue_coord; + cmatrix[13] = (hue_coord >> 8) & 0x0f; + +- hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8; ++ hue_coord = (hsv_blue_x[hue_index] * satur) >> 8; + cmatrix[14] = hue_coord; + cmatrix[15] = (hue_coord >> 8) & 0x0f; + +- hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8; ++ hue_coord = (hsv_blue_y[hue_index] * satur) >> 8; + cmatrix[16] = hue_coord; + cmatrix[17] = (hue_coord >> 8) & 0x0f; + +- return reg_w(gspca_dev, 0x10e1, cmatrix, 21); ++ reg_w(gspca_dev, 0x10e1, cmatrix, 21); + } + +-static int set_gamma(struct gspca_dev *gspca_dev) ++static void set_gamma(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; + u8 gamma[17]; +- u8 gval = sd->gamma * 0xb8 / 0x100; +- ++ u8 gval = sd->ctrls[GAMMA].val * 0xb8 / 0x100; + + gamma[0] = 0x0a; + gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8); +@@ -1592,29 +1553,29 @@ static int set_gamma(struct gspca_dev *g + gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8); + gamma[16] = 0xf5; + +- return reg_w(gspca_dev, 0x1190, gamma, 17); ++ reg_w(gspca_dev, 0x1190, gamma, 17); + } + +-static int set_redblue(struct gspca_dev *gspca_dev) ++static void set_redblue(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- reg_w1(gspca_dev, 0x118c, sd->red); +- reg_w1(gspca_dev, 0x118f, sd->blue); +- return 0; ++ ++ reg_w1(gspca_dev, 0x118c, sd->ctrls[RED].val); ++ reg_w1(gspca_dev, 0x118f, sd->ctrls[BLUE].val); + } + +-static int set_hvflip(struct gspca_dev *gspca_dev) ++static void set_hvflip(struct gspca_dev *gspca_dev) + { + u8 value, tslb, hflip, vflip; + u16 value2; + struct sd *sd = (struct sd *) gspca_dev; + + if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) { +- hflip = !sd->hflip; +- vflip = !sd->vflip; ++ hflip = !sd->ctrls[HFLIP].val; ++ vflip = !sd->ctrls[VFLIP].val; + } else { +- hflip = sd->hflip; +- vflip = sd->vflip; ++ hflip = sd->ctrls[HFLIP].val; ++ vflip = sd->ctrls[VFLIP].val; + } + + switch (sd->sensor) { +@@ -1625,8 +1586,9 @@ static int set_hvflip(struct gspca_dev * + if (vflip) { + value |= 0x10; + sd->vstart = 2; +- } else ++ } else { + sd->vstart = 3; ++ } + reg_w1(gspca_dev, 0x1182, sd->vstart); + i2c_w1(gspca_dev, 0x1e, value); + break; +@@ -1674,13 +1636,15 @@ static int set_hvflip(struct gspca_dev * + i2c_w1(gspca_dev, 0x01, value); + break; + } +- return 0; + } + +-static int set_exposure(struct gspca_dev *gspca_dev) ++static void set_exposure(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; + u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e}; ++ int expo; ++ ++ expo = sd->ctrls[EXPOSURE].val; + switch (sd->sensor) { + case SENSOR_OV7660: + case SENSOR_OV7670: +@@ -1688,35 +1652,37 @@ static int set_exposure(struct gspca_dev + case SENSOR_OV9650: + exp[0] |= (3 << 4); + exp[2] = 0x2d; +- exp[3] = sd->exposure & 0xff; +- exp[4] = sd->exposure >> 8; ++ exp[3] = expo; ++ exp[4] = expo >> 8; + break; + case SENSOR_MT9M001: + case SENSOR_MT9V112: + case SENSOR_MT9V011: + exp[0] |= (3 << 4); + exp[2] = 0x09; +- exp[3] = sd->exposure >> 8; +- exp[4] = sd->exposure & 0xff; ++ exp[3] = expo >> 8; ++ exp[4] = expo; + break; + case SENSOR_HV7131R: + exp[0] |= (4 << 4); + exp[2] = 0x25; +- exp[3] = (sd->exposure >> 5) & 0xff; +- exp[4] = (sd->exposure << 3) & 0xff; ++ exp[3] = expo >> 5; ++ exp[4] = expo << 3; + exp[5] = 0; + break; + default: +- return 0; ++ return; + } + i2c_w(gspca_dev, exp); +- return 0; + } + +-static int set_gain(struct gspca_dev *gspca_dev) ++static void set_gain(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; + u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d}; ++ int g; ++ ++ g = sd->ctrls[GAIN].val; + switch (sd->sensor) { + case SENSOR_OV7660: + case SENSOR_OV7670: +@@ -1724,238 +1690,50 @@ static int set_gain(struct gspca_dev *gs + case SENSOR_OV9655: + case SENSOR_OV9650: + gain[0] |= (2 << 4); +- gain[3] = ov_gain[sd->gain]; ++ gain[3] = ov_gain[g]; + break; + case SENSOR_MT9V011: + gain[0] |= (3 << 4); + gain[2] = 0x35; +- gain[3] = micron1_gain[sd->gain] >> 8; +- gain[4] = micron1_gain[sd->gain] & 0xff; ++ gain[3] = micron1_gain[g] >> 8; ++ gain[4] = micron1_gain[g]; + break; + case SENSOR_MT9V112: + gain[0] |= (3 << 4); + gain[2] = 0x2f; +- gain[3] = micron1_gain[sd->gain] >> 8; +- gain[4] = micron1_gain[sd->gain] & 0xff; ++ gain[3] = micron1_gain[g] >> 8; ++ gain[4] = micron1_gain[g]; + break; + case SENSOR_MT9M001: + gain[0] |= (3 << 4); + gain[2] = 0x2f; +- gain[3] = micron2_gain[sd->gain] >> 8; +- gain[4] = micron2_gain[sd->gain] & 0xff; ++ gain[3] = micron2_gain[g] >> 8; ++ gain[4] = micron2_gain[g]; + break; + case SENSOR_HV7131R: + gain[0] |= (2 << 4); + gain[2] = 0x30; +- gain[3] = hv7131r_gain[sd->gain]; ++ gain[3] = hv7131r_gain[g]; + break; + default: +- return 0; ++ return; + } + i2c_w(gspca_dev, gain); +- return 0; +-} +- +-static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->brightness = val; +- if (gspca_dev->streaming) +- return set_cmatrix(gspca_dev); +- return 0; +-} +- +-static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->brightness; +- return 0; +-} +- +- +-static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->contrast = val; +- if (gspca_dev->streaming) +- return set_cmatrix(gspca_dev); +- return 0; +-} +- +-static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->contrast; +- return 0; +-} +- +-static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->saturation = val; +- if (gspca_dev->streaming) +- return set_cmatrix(gspca_dev); +- return 0; +-} +- +-static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->saturation; +- return 0; +-} +- +-static int sd_sethue(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->hue = val; +- if (gspca_dev->streaming) +- return set_cmatrix(gspca_dev); +- return 0; +-} +- +-static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->hue; +- return 0; +-} +- +-static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->gamma = val; +- if (gspca_dev->streaming) +- return set_gamma(gspca_dev); +- return 0; +-} +- +-static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->gamma; +- return 0; +-} +- +-static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->red = val; +- if (gspca_dev->streaming) +- return set_redblue(gspca_dev); +- return 0; +-} +- +-static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->red; +- return 0; +-} +- +-static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->blue = val; +- if (gspca_dev->streaming) +- return set_redblue(gspca_dev); +- return 0; +-} +- +-static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->blue; +- return 0; +-} +- +-static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->hflip = val; +- if (gspca_dev->streaming) +- return set_hvflip(gspca_dev); +- return 0; +-} +- +-static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->hflip; +- return 0; +-} +- +-static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->vflip = val; +- if (gspca_dev->streaming) +- return set_hvflip(gspca_dev); +- return 0; +-} +- +-static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->vflip; +- return 0; +-} +- +-static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->exposure = val; +- if (gspca_dev->streaming) +- return set_exposure(gspca_dev); +- return 0; +-} +- +-static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->exposure; +- return 0; +-} +- +-static int sd_setgain(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->gain = val; +- if (gspca_dev->streaming) +- return set_gain(gspca_dev); +- return 0; +-} +- +-static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->gain; +- return 0; + } + +-static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val) ++static void set_quality(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- sd->auto_exposure = val; +- return 0; +-} + +-static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->auto_exposure; +- return 0; ++ jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); ++ reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */ ++ reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */ ++ reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64); ++ reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64); ++ reg_w1(gspca_dev, 0x1061, 0x03); /* restart transfer */ ++ reg_w1(gspca_dev, 0x10e0, sd->fmt); ++ sd->fmt ^= 0x0c; /* invert QTAB use + write */ ++ reg_w1(gspca_dev, 0x10e0, sd->fmt); + } + + #ifdef CONFIG_VIDEO_ADV_DEBUG +@@ -1963,28 +1741,26 @@ static int sd_dbg_g_register(struct gspc + struct v4l2_dbg_register *reg) + { + struct sd *sd = (struct sd *) gspca_dev; ++ + switch (reg->match.type) { + case V4L2_CHIP_MATCH_HOST: + if (reg->match.addr != 0) + return -EINVAL; + if (reg->reg < 0x1000 || reg->reg > 0x11ff) + return -EINVAL; +- if (reg_r(gspca_dev, reg->reg, 1) < 0) +- return -EINVAL; ++ reg_r(gspca_dev, reg->reg, 1); + reg->val = gspca_dev->usb_buf[0]; +- return 0; ++ return gspca_dev->usb_err; + case V4L2_CHIP_MATCH_I2C_ADDR: + if (reg->match.addr != sd->i2c_addr) + return -EINVAL; + if (sd->sensor >= SENSOR_MT9V011 && + sd->sensor <= SENSOR_MT9M112) { +- if (i2c_r2(gspca_dev, reg->reg, (u16 *)®->val) < 0) +- return -EINVAL; ++ i2c_r2(gspca_dev, reg->reg, (u16 *) ®->val); + } else { +- if (i2c_r1(gspca_dev, reg->reg, (u8 *)®->val) < 0) +- return -EINVAL; ++ i2c_r1(gspca_dev, reg->reg, (u8 *) ®->val); + } +- return 0; ++ return gspca_dev->usb_err; + } + return -EINVAL; + } +@@ -1993,27 +1769,25 @@ static int sd_dbg_s_register(struct gspc + struct v4l2_dbg_register *reg) + { + struct sd *sd = (struct sd *) gspca_dev; ++ + switch (reg->match.type) { + case V4L2_CHIP_MATCH_HOST: + if (reg->match.addr != 0) + return -EINVAL; + if (reg->reg < 0x1000 || reg->reg > 0x11ff) + return -EINVAL; +- if (reg_w1(gspca_dev, reg->reg, reg->val) < 0) +- return -EINVAL; +- return 0; ++ reg_w1(gspca_dev, reg->reg, reg->val); ++ return gspca_dev->usb_err; + case V4L2_CHIP_MATCH_I2C_ADDR: + if (reg->match.addr != sd->i2c_addr) + return -EINVAL; + if (sd->sensor >= SENSOR_MT9V011 && + sd->sensor <= SENSOR_MT9M112) { +- if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0) +- return -EINVAL; ++ i2c_w2(gspca_dev, reg->reg, reg->val); + } else { +- if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0) +- return -EINVAL; ++ i2c_w1(gspca_dev, reg->reg, reg->val); + } +- return 0; ++ return gspca_dev->usb_err; + } + return -EINVAL; + } +@@ -2050,9 +1824,9 @@ static int sd_config(struct gspca_dev *g + cam = &gspca_dev->cam; + cam->needs_full_bandwidth = 1; + +- sd->sensor = (id->driver_info >> 8) & 0xff; +- sd->i2c_addr = id->driver_info & 0xff; +- sd->flags = (id->driver_info >> 16) & 0xff; ++ sd->sensor = id->driver_info >> 8; ++ sd->i2c_addr = id->driver_info; ++ sd->flags = id->driver_info >> 16; + + switch (sd->sensor) { + case SENSOR_MT9M112: +@@ -2076,21 +1850,9 @@ static int sd_config(struct gspca_dev *g + sd->older_step = 0; + sd->exposure_step = 16; + +- sd->brightness = BRIGHTNESS_DEFAULT; +- sd->contrast = CONTRAST_DEFAULT; +- sd->saturation = SATURATION_DEFAULT; +- sd->hue = HUE_DEFAULT; +- sd->gamma = GAMMA_DEFAULT; +- sd->red = RED_DEFAULT; +- sd->blue = BLUE_DEFAULT; +- +- sd->hflip = HFLIP_DEFAULT; +- sd->vflip = VFLIP_DEFAULT; +- sd->exposure = EXPOSURE_DEFAULT; +- sd->gain = GAIN_DEFAULT; +- sd->auto_exposure = AUTO_EXPOSURE_DEFAULT; ++ gspca_dev->cam.ctrls = sd->ctrls; + +- sd->quality = 95; ++ INIT_WORK(&sd->work, qual_upd); + + return 0; + } +@@ -2105,9 +1867,10 @@ static int sd_init(struct gspca_dev *gsp + + for (i = 0; i < ARRAY_SIZE(bridge_init); i++) { + value = bridge_init[i][1]; +- if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) { ++ reg_w(gspca_dev, bridge_init[i][0], &value, 1); ++ if (gspca_dev->usb_err < 0) { + pr_err("Device initialization failed\n"); +- return -ENODEV; ++ return gspca_dev->usb_err; + } + } + +@@ -2116,72 +1879,85 @@ static int sd_init(struct gspca_dev *gsp + else + reg_w1(gspca_dev, 0x1006, 0x20); + +- if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) { ++ reg_w(gspca_dev, 0x10c0, i2c_init, 9); ++ if (gspca_dev->usb_err < 0) { + pr_err("Device initialization failed\n"); +- return -ENODEV; ++ return gspca_dev->usb_err; + } + + switch (sd->sensor) { + case SENSOR_OV9650: +- if (ov9650_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ ov9650_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + pr_info("OV9650 sensor detected\n"); + break; + case SENSOR_OV9655: +- if (ov9655_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ ov9655_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + pr_info("OV9655 sensor detected\n"); + break; + case SENSOR_SOI968: +- if (soi968_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ soi968_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + pr_info("SOI968 sensor detected\n"); + break; + case SENSOR_OV7660: +- if (ov7660_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ ov7660_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + pr_info("OV7660 sensor detected\n"); + break; + case SENSOR_OV7670: +- if (ov7670_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ ov7670_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + pr_info("OV7670 sensor detected\n"); + break; + case SENSOR_MT9VPRB: +- if (mt9v_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ mt9v_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; ++ pr_info("MT9VPRB sensor detected\n"); + break; + case SENSOR_MT9M111: +- if (mt9m111_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ mt9m111_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + pr_info("MT9M111 sensor detected\n"); + break; + case SENSOR_MT9M112: +- if (mt9m112_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ mt9m112_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + pr_info("MT9M112 sensor detected\n"); + break; + case SENSOR_MT9M001: +- if (mt9m001_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ mt9m001_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + break; + case SENSOR_HV7131R: +- if (hv7131r_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ hv7131r_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + pr_info("HV7131R sensor detected\n"); + break; + default: +- pr_info("Unsupported Sensor\n"); +- return -ENODEV; ++ pr_err("Unsupported sensor\n"); ++ gspca_dev->usb_err = -ENODEV; + } + +- return 0; ++ return gspca_dev->usb_err; + } + + static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode) + { + struct sd *sd = (struct sd *) gspca_dev; + u8 value; ++ + switch (sd->sensor) { + case SENSOR_SOI968: + if (mode & MODE_SXGA) { +@@ -2264,6 +2040,7 @@ static int sd_isoc_init(struct gspca_dev + break; + default: /* >= 640x480 */ + gspca_dev->alt = 9; ++ break; + } + } + +@@ -2290,14 +2067,15 @@ static int sd_start(struct gspca_dev *gs + + jpeg_define(sd->jpeg_hdr, height, width, + 0x21); +- jpeg_set_qual(sd->jpeg_hdr, sd->quality); ++ jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); + + if (mode & MODE_RAW) + fmt = 0x2d; + else if (mode & MODE_JPEG) +- fmt = 0x2c; ++ fmt = 0x24; + else + fmt = 0x2f; /* YUV 420 */ ++ sd->fmt = fmt; + + switch (mode & SCALE_MASK) { + case SCALE_1280x1024: +@@ -2334,18 +2112,37 @@ static int sd_start(struct gspca_dev *gs + set_hvflip(gspca_dev); + + reg_w1(gspca_dev, 0x1007, 0x20); ++ reg_w1(gspca_dev, 0x1061, 0x03); + +- reg_r(gspca_dev, 0x1061, 1); +- reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02); +- return 0; ++ /* if JPEG, prepare the compression quality update */ ++ if (mode & MODE_JPEG) { ++ sd->pktsz = sd->npkt = 0; ++ sd->nchg = 0; ++ sd->work_thread = ++ create_singlethread_workqueue(KBUILD_MODNAME); ++ } ++ ++ return gspca_dev->usb_err; + } + + static void sd_stopN(struct gspca_dev *gspca_dev) + { + reg_w1(gspca_dev, 0x1007, 0x00); ++ reg_w1(gspca_dev, 0x1061, 0x01); ++} + +- reg_r(gspca_dev, 0x1061, 1); +- reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02); ++/* called on streamoff with alt==0 and on disconnect */ ++/* the usb_lock is held at entry - restore on exit */ ++static void sd_stop0(struct gspca_dev *gspca_dev) ++{ ++ struct sd *sd = (struct sd *) gspca_dev; ++ ++ if (sd->work_thread != NULL) { ++ mutex_unlock(&gspca_dev->usb_lock); ++ destroy_workqueue(sd->work_thread); ++ mutex_lock(&gspca_dev->usb_lock); ++ sd->work_thread = NULL; ++ } + } + + static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum) +@@ -2359,15 +2156,15 @@ static void do_autoexposure(struct gspca + * and exposure steps + */ + if (avg_lum < MIN_AVG_LUM) { +- if (sd->exposure > 0x1770) ++ if (sd->ctrls[EXPOSURE].val > 0x1770) + return; + +- new_exp = sd->exposure + sd->exposure_step; ++ new_exp = sd->ctrls[EXPOSURE].val + sd->exposure_step; + if (new_exp > 0x1770) + new_exp = 0x1770; + if (new_exp < 0x10) + new_exp = 0x10; +- sd->exposure = new_exp; ++ sd->ctrls[EXPOSURE].val = new_exp; + set_exposure(gspca_dev); + + sd->older_step = sd->old_step; +@@ -2379,14 +2176,14 @@ static void do_autoexposure(struct gspca + sd->exposure_step += 2; + } + if (avg_lum > MAX_AVG_LUM) { +- if (sd->exposure < 0x10) ++ if (sd->ctrls[EXPOSURE].val < 0x10) + return; +- new_exp = sd->exposure - sd->exposure_step; ++ new_exp = sd->ctrls[EXPOSURE].val - sd->exposure_step; + if (new_exp > 0x1700) + new_exp = 0x1770; + if (new_exp < 0x10) + new_exp = 0x10; +- sd->exposure = new_exp; ++ sd->ctrls[EXPOSURE].val = new_exp; + set_exposure(gspca_dev); + sd->older_step = sd->old_step; + sd->old_step = 0; +@@ -2403,14 +2200,14 @@ static void do_autogain(struct gspca_dev + struct sd *sd = (struct sd *) gspca_dev; + + if (avg_lum < MIN_AVG_LUM) { +- if (sd->gain + 1 <= 28) { +- sd->gain++; ++ if (sd->ctrls[GAIN].val + 1 <= 28) { ++ sd->ctrls[GAIN].val++; + set_gain(gspca_dev); + } + } + if (avg_lum > MAX_AVG_LUM) { +- if (sd->gain > 0) { +- sd->gain--; ++ if (sd->ctrls[GAIN].val > 0) { ++ sd->ctrls[GAIN].val--; + set_gain(gspca_dev); + } + } +@@ -2421,7 +2218,7 @@ static void sd_dqcallback(struct gspca_d + struct sd *sd = (struct sd *) gspca_dev; + int avg_lum; + +- if (!sd->auto_exposure) ++ if (!sd->ctrls[AUTOGAIN].val) + return; + + avg_lum = atomic_read(&sd->avg_lum); +@@ -2431,33 +2228,92 @@ static void sd_dqcallback(struct gspca_d + do_autoexposure(gspca_dev, avg_lum); + } + ++/* JPEG quality update */ ++/* This function is executed from a work queue. */ ++static void qual_upd(struct work_struct *work) ++{ ++ struct sd *sd = container_of(work, struct sd, work); ++ struct gspca_dev *gspca_dev = &sd->gspca_dev; ++ ++ mutex_lock(&gspca_dev->usb_lock); ++ PDEBUG(D_STREAM, "qual_upd %d%%", sd->ctrls[QUALITY].val); ++ set_quality(gspca_dev); ++ mutex_unlock(&gspca_dev->usb_lock); ++} ++ + #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, + u8 *data, /* interrupt packet */ + int len) /* interrupt packet length */ + { + struct sd *sd = (struct sd *) gspca_dev; +- int ret = -EINVAL; ++ + if (!(sd->flags & HAS_NO_BUTTON) && len == 1) { +- input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); +- input_sync(gspca_dev->input_dev); +- input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); +- input_sync(gspca_dev->input_dev); +- ret = 0; ++ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); ++ input_sync(gspca_dev->input_dev); ++ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); ++ input_sync(gspca_dev->input_dev); ++ return 0; + } +- return ret; ++ return -EINVAL; + } + #endif + ++/* check the JPEG compression */ ++static void transfer_check(struct gspca_dev *gspca_dev, ++ u8 *data) ++{ ++ struct sd *sd = (struct sd *) gspca_dev; ++ int new_qual, r; ++ ++ new_qual = 0; ++ ++ /* if USB error, discard the frame and decrease the quality */ ++ if (data[6] & 0x08) { /* USB FIFO full */ ++ gspca_dev->last_packet_type = DISCARD_PACKET; ++ new_qual = -5; ++ } else { ++ ++ /* else, compute the filling rate and a new JPEG quality */ ++ r = (sd->pktsz * 100) / ++ (sd->npkt * ++ gspca_dev->urb[0]->iso_frame_desc[0].length); ++ if (r >= 85) ++ new_qual = -3; ++ else if (r < 75) ++ new_qual = 2; ++ } ++ if (new_qual != 0) { ++ sd->nchg += new_qual; ++ if (sd->nchg < -6 || sd->nchg >= 12) { ++ sd->nchg = 0; ++ new_qual += sd->ctrls[QUALITY].val; ++ if (new_qual < QUALITY_MIN) ++ new_qual = QUALITY_MIN; ++ else if (new_qual > QUALITY_MAX) ++ new_qual = QUALITY_MAX; ++ if (new_qual != sd->ctrls[QUALITY].val) { ++ sd->ctrls[QUALITY].val = new_qual; ++ queue_work(sd->work_thread, &sd->work); ++ } ++ } ++ } else { ++ sd->nchg = 0; ++ } ++ sd->pktsz = sd->npkt = 0; ++} ++ + static void sd_pkt_scan(struct gspca_dev *gspca_dev, + u8 *data, /* isoc packet */ + int len) /* iso packet length */ + { + struct sd *sd = (struct sd *) gspca_dev; +- int avg_lum; ++ int avg_lum, is_jpeg; + static u8 frame_header[] = + {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; +- if (len == 64 && memcmp(data, frame_header, 6) == 0) { ++ ++ is_jpeg = (sd->fmt & 0x03) == 0; ++ if (len >= 64 && memcmp(data, frame_header, 6) == 0) { + avg_lum = ((data[35] >> 2) & 3) | + (data[20] << 2) | + (data[19] << 10); +@@ -2484,12 +2340,18 @@ static void sd_pkt_scan(struct gspca_dev + (data[33] << 10); + avg_lum >>= 9; + atomic_set(&sd->avg_lum, avg_lum); ++ ++ if (is_jpeg) ++ transfer_check(gspca_dev, data); ++ + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); +- return; ++ len -= 64; ++ if (len == 0) ++ return; ++ data += 64; + } + if (gspca_dev->last_packet_type == LAST_PACKET) { +- if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv +- & MODE_JPEG) { ++ if (is_jpeg) { + gspca_frame_add(gspca_dev, FIRST_PACKET, + sd->jpeg_hdr, JPEG_HDR_SZ); + gspca_frame_add(gspca_dev, INTER_PACKET, +@@ -2499,13 +2361,18 @@ static void sd_pkt_scan(struct gspca_dev + data, len); + } + } else { ++ /* if JPEG, count the packets and their size */ ++ if (is_jpeg) { ++ sd->npkt++; ++ sd->pktsz += len; ++ } + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); + } + } + + /* sub-driver description */ + static const struct sd_desc sd_desc = { +- .name = MODULE_NAME, ++ .name = KBUILD_MODNAME, + .ctrls = sd_ctrls, + .nctrls = ARRAY_SIZE(sd_ctrls), + .config = sd_config, +@@ -2513,6 +2380,7 @@ static const struct sd_desc sd_desc = { + .isoc_init = sd_isoc_init, + .start = sd_start, + .stopN = sd_stopN, ++ .stop0 = sd_stop0, + .pkt_scan = sd_pkt_scan, + #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + .int_pkt_scan = sd_int_pkt_scan, +@@ -2581,7 +2449,7 @@ static int sd_probe(struct usb_interface + } + + static struct usb_driver sd_driver = { +- .name = MODULE_NAME, ++ .name = KBUILD_MODNAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-udma.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-udma.c ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-udma.c +@@ -57,9 +57,9 @@ int ivtv_udma_fill_sg_list (struct ivtv_ + if (dma->bouncemap[map_offset] == NULL) + return -1; + local_irq_save(flags); +- src = kmap_atomic(dma->map[map_offset], KM_BOUNCE_READ) + offset; ++ src = kmap_atomic(dma->map[map_offset]) + offset; + memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len); +- kunmap_atomic(src, KM_BOUNCE_READ); ++ kunmap_atomic(src); + local_irq_restore(flags); + sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset], len, offset); + } +Index: linux-3.3.x86_64/drivers/media/video/videobuf2-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/videobuf2-core.c ++++ linux-3.3.x86_64/drivers/media/video/videobuf2-core.c +@@ -19,6 +19,9 @@ + #include + #include + ++#include ++#include ++#include + #include + + static int debug; +@@ -1642,32 +1645,46 @@ static int __vb2_cleanup_fileio(struct v + * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor + * will be reported as available for writing. + * ++ * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any ++ * pending events. ++ * + * The return values from this function are intended to be directly returned + * from poll handler in driver. + */ + unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) + { +- unsigned long flags; +- unsigned int ret; ++ struct video_device *vfd = video_devdata(file); ++ unsigned long req_events = poll_requested_events(wait); + struct vb2_buffer *vb = NULL; ++ unsigned int res = 0; ++ unsigned long flags; ++ ++ if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { ++ struct v4l2_fh *fh = file->private_data; ++ ++ if (v4l2_event_pending(fh)) ++ res = POLLPRI; ++ else if (req_events & POLLPRI) ++ poll_wait(file, &fh->wait, wait); ++ } + + /* + * Start file I/O emulator only if streaming API has not been used yet. + */ + if (q->num_buffers == 0 && q->fileio == NULL) { +- if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ)) { +- ret = __vb2_init_fileio(q, 1); +- if (ret) +- return POLLERR; ++ if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) && ++ (req_events & (POLLIN | POLLRDNORM))) { ++ if (__vb2_init_fileio(q, 1)) ++ return res | POLLERR; + } +- if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE)) { +- ret = __vb2_init_fileio(q, 0); +- if (ret) +- return POLLERR; ++ if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE) && ++ (req_events & (POLLOUT | POLLWRNORM))) { ++ if (__vb2_init_fileio(q, 0)) ++ return res | POLLERR; + /* + * Write to OUTPUT queue can be done immediately. + */ +- return POLLOUT | POLLWRNORM; ++ return res | POLLOUT | POLLWRNORM; + } + } + +@@ -1675,7 +1692,7 @@ unsigned int vb2_poll(struct vb2_queue * + * There is nothing to wait for if no buffers have already been queued. + */ + if (list_empty(&q->queued_list)) +- return POLLERR; ++ return res | POLLERR; + + poll_wait(file, &q->done_wq, wait); + +@@ -1690,10 +1707,11 @@ unsigned int vb2_poll(struct vb2_queue * + + if (vb && (vb->state == VB2_BUF_STATE_DONE + || vb->state == VB2_BUF_STATE_ERROR)) { +- return (V4L2_TYPE_IS_OUTPUT(q->type)) ? POLLOUT | POLLWRNORM : +- POLLIN | POLLRDNORM; ++ return (V4L2_TYPE_IS_OUTPUT(q->type)) ? ++ res | POLLOUT | POLLWRNORM : ++ res | POLLIN | POLLRDNORM; + } +- return 0; ++ return res; + } + EXPORT_SYMBOL_GPL(vb2_poll); + +Index: linux-3.3.x86_64/drivers/media/video/videobuf-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/videobuf-core.c ++++ linux-3.3.x86_64/drivers/media/video/videobuf-core.c +@@ -1129,6 +1129,7 @@ unsigned int videobuf_poll_stream(struct + struct videobuf_queue *q, + poll_table *wait) + { ++ unsigned long req_events = poll_requested_events(wait); + struct videobuf_buffer *buf = NULL; + unsigned int rc = 0; + +@@ -1137,7 +1138,7 @@ unsigned int videobuf_poll_stream(struct + if (!list_empty(&q->stream)) + buf = list_entry(q->stream.next, + struct videobuf_buffer, stream); +- } else { ++ } else if (req_events & (POLLIN | POLLRDNORM)) { + if (!q->reading) + __videobuf_read_start(q); + if (!q->reading) { +Index: linux-3.3.x86_64/drivers/media/video/pwc/pwc-if.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/pwc/pwc-if.c ++++ linux-3.3.x86_64/drivers/media/video/pwc/pwc-if.c +@@ -625,10 +625,19 @@ static ssize_t pwc_video_read(struct fil + static unsigned int pwc_video_poll(struct file *file, poll_table *wait) + { + struct pwc_device *pdev = video_drvdata(file); ++ unsigned long req_events = poll_requested_events(wait); + + if (!pdev->udev) + return POLL_ERR; + ++ if ((req_events & (POLLIN | POLLRDNORM)) && ++ pdev->vb_queue.num_buffers == 0 && ++ !pdev->iso_init) { ++ /* This poll will start a read stream, check capt_file */ ++ if (pwc_test_n_set_capt_file(pdev, file)) ++ return POLL_ERR; ++ } ++ + return vb2_poll(&pdev->vb_queue, file, wait); + } + +Index: linux-3.3.x86_64/drivers/media/common/tuners/Kconfig +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/common/tuners/Kconfig ++++ linux-3.3.x86_64/drivers/media/common/tuners/Kconfig +@@ -204,6 +204,13 @@ config MEDIA_TUNER_TDA18218 + help + NXP TDA18218 silicon tuner driver. + ++config MEDIA_TUNER_FC0011 ++ tristate "Fitipower FC0011 silicon tuner" ++ depends on VIDEO_MEDIA && I2C ++ default m if MEDIA_TUNER_CUSTOMISE ++ help ++ Fitipower FC0011 silicon tuner driver. ++ + config MEDIA_TUNER_TDA18212 + tristate "NXP TDA18212 silicon tuner" + depends on VIDEO_MEDIA && I2C +@@ -211,4 +218,10 @@ config MEDIA_TUNER_TDA18212 + help + NXP TDA18212 silicon tuner driver. + ++config MEDIA_TUNER_TUA9001 ++ tristate "Infineon TUA 9001 silicon tuner" ++ depends on VIDEO_MEDIA && I2C ++ default m if MEDIA_TUNER_CUSTOMISE ++ help ++ Infineon TUA 9001 silicon tuner driver. + endmenu +Index: linux-3.3.x86_64/drivers/media/common/tuners/tua9001.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/common/tuners/tua9001.c +@@ -0,0 +1,215 @@ ++/* ++ * Infineon TUA 9001 silicon tuner driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include "tua9001.h" ++#include "tua9001_priv.h" ++ ++/* write register */ ++static int tua9001_wr_reg(struct tua9001_priv *priv, u8 reg, u16 val) ++{ ++ int ret; ++ u8 buf[3] = { reg, (val >> 8) & 0xff, (val >> 0) & 0xff }; ++ struct i2c_msg msg[1] = { ++ { ++ .addr = priv->cfg->i2c_addr, ++ .flags = 0, ++ .len = sizeof(buf), ++ .buf = buf, ++ } ++ }; ++ ++ ret = i2c_transfer(priv->i2c, msg, 1); ++ if (ret == 1) { ++ ret = 0; ++ } else { ++ printk(KERN_WARNING "%s: I2C wr failed=%d reg=%02x\n", ++ __func__, ret, reg); ++ ret = -EREMOTEIO; ++ } ++ ++ return ret; ++} ++ ++static int tua9001_release(struct dvb_frontend *fe) ++{ ++ kfree(fe->tuner_priv); ++ fe->tuner_priv = NULL; ++ ++ return 0; ++} ++ ++static int tua9001_init(struct dvb_frontend *fe) ++{ ++ struct tua9001_priv *priv = fe->tuner_priv; ++ int ret = 0; ++ u8 i; ++ struct reg_val data[] = { ++ { 0x1e, 0x6512 }, ++ { 0x25, 0xb888 }, ++ { 0x39, 0x5460 }, ++ { 0x3b, 0x00c0 }, ++ { 0x3a, 0xf000 }, ++ { 0x08, 0x0000 }, ++ { 0x32, 0x0030 }, ++ { 0x41, 0x703a }, ++ { 0x40, 0x1c78 }, ++ { 0x2c, 0x1c00 }, ++ { 0x36, 0xc013 }, ++ { 0x37, 0x6f18 }, ++ { 0x27, 0x0008 }, ++ { 0x2a, 0x0001 }, ++ { 0x34, 0x0a40 }, ++ }; ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */ ++ ++ for (i = 0; i < ARRAY_SIZE(data); i++) { ++ ret = tua9001_wr_reg(priv, data[i].reg, data[i].val); ++ if (ret) ++ break; ++ } ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */ ++ ++ if (ret < 0) ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int tua9001_set_params(struct dvb_frontend *fe) ++{ ++ struct tua9001_priv *priv = fe->tuner_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret, i; ++ u16 val; ++ u32 frequency; ++ struct reg_val data[2]; ++ ++ pr_debug("%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n", ++ __func__, c->delivery_system, c->frequency, ++ c->bandwidth_hz); ++ ++ switch (c->delivery_system) { ++ case SYS_DVBT: ++ switch (c->bandwidth_hz) { ++ case 8000000: ++ val = 0x0000; ++ break; ++ case 7000000: ++ val = 0x1000; ++ break; ++ case 6000000: ++ val = 0x2000; ++ break; ++ case 5000000: ++ val = 0x3000; ++ break; ++ default: ++ ret = -EINVAL; ++ goto err; ++ } ++ break; ++ default: ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ data[0].reg = 0x04; ++ data[0].val = val; ++ ++ frequency = (c->frequency - 150000000); ++ frequency /= 100; ++ frequency *= 48; ++ frequency /= 10000; ++ ++ data[1].reg = 0x1f; ++ data[1].val = frequency; ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */ ++ ++ for (i = 0; i < ARRAY_SIZE(data); i++) { ++ ret = tua9001_wr_reg(priv, data[i].reg, data[i].val); ++ if (ret < 0) ++ break; ++ } ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */ ++ ++err: ++ if (ret < 0) ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) ++{ ++ *frequency = 0; /* Zero-IF */ ++ ++ return 0; ++} ++ ++static const struct dvb_tuner_ops tua9001_tuner_ops = { ++ .info = { ++ .name = "Infineon TUA 9001", ++ ++ .frequency_min = 170000000, ++ .frequency_max = 862000000, ++ .frequency_step = 0, ++ }, ++ ++ .release = tua9001_release, ++ ++ .init = tua9001_init, ++ .set_params = tua9001_set_params, ++ ++ .get_if_frequency = tua9001_get_if_frequency, ++}; ++ ++struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, struct tua9001_config *cfg) ++{ ++ struct tua9001_priv *priv = NULL; ++ ++ priv = kzalloc(sizeof(struct tua9001_priv), GFP_KERNEL); ++ if (priv == NULL) ++ return NULL; ++ ++ priv->cfg = cfg; ++ priv->i2c = i2c; ++ ++ printk(KERN_INFO "Infineon TUA 9001 successfully attached."); ++ ++ memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops, ++ sizeof(struct dvb_tuner_ops)); ++ ++ fe->tuner_priv = priv; ++ return fe; ++} ++EXPORT_SYMBOL(tua9001_attach); ++ ++MODULE_DESCRIPTION("Infineon TUA 9001 silicon tuner driver"); ++MODULE_AUTHOR("Antti Palosaari "); ++MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/common/tuners/tua9001.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/common/tuners/tua9001.h +@@ -0,0 +1,46 @@ ++/* ++ * Infineon TUA 9001 silicon tuner driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef TUA9001_H ++#define TUA9001_H ++ ++#include "dvb_frontend.h" ++ ++struct tua9001_config { ++ /* ++ * I2C address ++ */ ++ u8 i2c_addr; ++}; ++ ++#if defined(CONFIG_MEDIA_TUNER_TUA9001) || \ ++ (defined(CONFIG_MEDIA_TUNER_TUA9001_MODULE) && defined(MODULE)) ++extern struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, struct tua9001_config *cfg); ++#else ++static inline struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, struct tua9001_config *cfg) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif ++ ++#endif +Index: linux-3.3.x86_64/drivers/media/common/tuners/tua9001_priv.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/common/tuners/tua9001_priv.h +@@ -0,0 +1,34 @@ ++/* ++ * Infineon TUA 9001 silicon tuner driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef TUA9001_PRIV_H ++#define TUA9001_PRIV_H ++ ++struct reg_val { ++ u8 reg; ++ u16 val; ++}; ++ ++struct tua9001_priv { ++ struct tua9001_config *cfg; ++ struct i2c_adapter *i2c; ++}; ++ ++#endif +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/af9033.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/af9033.c +@@ -0,0 +1,919 @@ ++/* ++ * Afatech AF9033 demodulator driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * Copyright (C) 2012 Antti Palosaari ++ * ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include "af9033_priv.h" ++ ++struct af9033_state { ++ struct i2c_adapter *i2c; ++ struct dvb_frontend fe; ++ struct af9033_config cfg; ++ ++ u32 bandwidth_hz; ++ bool ts_mode_parallel; ++ bool ts_mode_serial; ++}; ++ ++/* write multiple registers */ ++static int af9033_wr_regs(struct af9033_state *state, u32 reg, const u8 *val, ++ int len) ++{ ++ int ret; ++ u8 buf[3 + len]; ++ struct i2c_msg msg[1] = { ++ { ++ .addr = state->cfg.i2c_addr, ++ .flags = 0, ++ .len = sizeof(buf), ++ .buf = buf, ++ } ++ }; ++ ++ buf[0] = (reg >> 16) & 0xff; ++ buf[1] = (reg >> 8) & 0xff; ++ buf[2] = (reg >> 0) & 0xff; ++ memcpy(&buf[3], val, len); ++ ++ ret = i2c_transfer(state->i2c, msg, 1); ++ if (ret == 1) { ++ ret = 0; ++ } else { ++ printk(KERN_WARNING "%s: i2c wr failed=%d reg=%06x len=%d\n", ++ __func__, ret, reg, len); ++ ret = -EREMOTEIO; ++ } ++ ++ return ret; ++} ++ ++/* read multiple registers */ ++static int af9033_rd_regs(struct af9033_state *state, u32 reg, u8 *val, int len) ++{ ++ int ret; ++ u8 buf[3] = { (reg >> 16) & 0xff, (reg >> 8) & 0xff, ++ (reg >> 0) & 0xff }; ++ struct i2c_msg msg[2] = { ++ { ++ .addr = state->cfg.i2c_addr, ++ .flags = 0, ++ .len = sizeof(buf), ++ .buf = buf ++ }, { ++ .addr = state->cfg.i2c_addr, ++ .flags = I2C_M_RD, ++ .len = len, ++ .buf = val ++ } ++ }; ++ ++ ret = i2c_transfer(state->i2c, msg, 2); ++ if (ret == 2) { ++ ret = 0; ++ } else { ++ printk(KERN_WARNING "%s: i2c rd failed=%d reg=%06x len=%d\n", ++ __func__, ret, reg, len); ++ ret = -EREMOTEIO; ++ } ++ ++ return ret; ++} ++ ++ ++/* write single register */ ++static int af9033_wr_reg(struct af9033_state *state, u32 reg, u8 val) ++{ ++ return af9033_wr_regs(state, reg, &val, 1); ++} ++ ++/* read single register */ ++static int af9033_rd_reg(struct af9033_state *state, u32 reg, u8 *val) ++{ ++ return af9033_rd_regs(state, reg, val, 1); ++} ++ ++/* write single register with mask */ ++static int af9033_wr_reg_mask(struct af9033_state *state, u32 reg, u8 val, ++ u8 mask) ++{ ++ int ret; ++ u8 tmp; ++ ++ /* no need for read if whole reg is written */ ++ if (mask != 0xff) { ++ ret = af9033_rd_regs(state, reg, &tmp, 1); ++ if (ret) ++ return ret; ++ ++ val &= mask; ++ tmp &= ~mask; ++ val |= tmp; ++ } ++ ++ return af9033_wr_regs(state, reg, &val, 1); ++} ++ ++/* read single register with mask */ ++static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val, ++ u8 mask) ++{ ++ int ret, i; ++ u8 tmp; ++ ++ ret = af9033_rd_regs(state, reg, &tmp, 1); ++ if (ret) ++ return ret; ++ ++ tmp &= mask; ++ ++ /* find position of the first bit */ ++ for (i = 0; i < 8; i++) { ++ if ((mask >> i) & 0x01) ++ break; ++ } ++ *val = tmp >> i; ++ ++ return 0; ++} ++ ++static u32 af9033_div(u32 a, u32 b, u32 x) ++{ ++ u32 r = 0, c = 0, i; ++ ++ pr_debug("%s: a=%d b=%d x=%d\n", __func__, a, b, x); ++ ++ if (a > b) { ++ c = a / b; ++ a = a - c * b; ++ } ++ ++ for (i = 0; i < x; i++) { ++ if (a >= b) { ++ r += 1; ++ a -= b; ++ } ++ a <<= 1; ++ r <<= 1; ++ } ++ r = (c << (u32)x) + r; ++ ++ pr_debug("%s: a=%d b=%d x=%d r=%d r=%x\n", __func__, a, b, x, r, r); ++ ++ return r; ++} ++ ++static void af9033_release(struct dvb_frontend *fe) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ ++ kfree(state); ++} ++ ++static int af9033_init(struct dvb_frontend *fe) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ int ret, i, len; ++ const struct reg_val *init; ++ u8 buf[4]; ++ u32 adc_cw, clock_cw; ++ struct reg_val_mask tab[] = { ++ { 0x80fb24, 0x00, 0x08 }, ++ { 0x80004c, 0x00, 0xff }, ++ { 0x00f641, state->cfg.tuner, 0xff }, ++ { 0x80f5ca, 0x01, 0x01 }, ++ { 0x80f715, 0x01, 0x01 }, ++ { 0x00f41f, 0x04, 0x04 }, ++ { 0x00f41a, 0x01, 0x01 }, ++ { 0x80f731, 0x00, 0x01 }, ++ { 0x00d91e, 0x00, 0x01 }, ++ { 0x00d919, 0x00, 0x01 }, ++ { 0x80f732, 0x00, 0x01 }, ++ { 0x00d91f, 0x00, 0x01 }, ++ { 0x00d91a, 0x00, 0x01 }, ++ { 0x80f730, 0x00, 0x01 }, ++ { 0x80f778, 0x00, 0xff }, ++ { 0x80f73c, 0x01, 0x01 }, ++ { 0x80f776, 0x00, 0x01 }, ++ { 0x00d8fd, 0x01, 0xff }, ++ { 0x00d830, 0x01, 0xff }, ++ { 0x00d831, 0x00, 0xff }, ++ { 0x00d832, 0x00, 0xff }, ++ { 0x80f985, state->ts_mode_serial, 0x01 }, ++ { 0x80f986, state->ts_mode_parallel, 0x01 }, ++ { 0x00d827, 0x00, 0xff }, ++ { 0x00d829, 0x00, 0xff }, ++ }; ++ ++ /* program clock control */ ++ clock_cw = af9033_div(state->cfg.clock, 1000000ul, 19ul); ++ buf[0] = (clock_cw >> 0) & 0xff; ++ buf[1] = (clock_cw >> 8) & 0xff; ++ buf[2] = (clock_cw >> 16) & 0xff; ++ buf[3] = (clock_cw >> 24) & 0xff; ++ ++ pr_debug("%s: clock=%d clock_cw=%08x\n", __func__, state->cfg.clock, ++ clock_cw); ++ ++ ret = af9033_wr_regs(state, 0x800025, buf, 4); ++ if (ret < 0) ++ goto err; ++ ++ /* program ADC control */ ++ for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { ++ if (clock_adc_lut[i].clock == state->cfg.clock) ++ break; ++ } ++ ++ adc_cw = af9033_div(clock_adc_lut[i].adc, 1000000ul, 19ul); ++ buf[0] = (adc_cw >> 0) & 0xff; ++ buf[1] = (adc_cw >> 8) & 0xff; ++ buf[2] = (adc_cw >> 16) & 0xff; ++ ++ pr_debug("%s: adc=%d adc_cw=%06x\n", __func__, clock_adc_lut[i].adc, ++ adc_cw); ++ ++ ret = af9033_wr_regs(state, 0x80f1cd, buf, 3); ++ if (ret < 0) ++ goto err; ++ ++ /* program register table */ ++ for (i = 0; i < ARRAY_SIZE(tab); i++) { ++ ret = af9033_wr_reg_mask(state, tab[i].reg, tab[i].val, ++ tab[i].mask); ++ if (ret < 0) ++ goto err; ++ } ++ ++ /* settings for TS interface */ ++ if (state->cfg.ts_mode == AF9033_TS_MODE_USB) { ++ ret = af9033_wr_reg_mask(state, 0x80f9a5, 0x00, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x01, 0x01); ++ if (ret < 0) ++ goto err; ++ } else { ++ ret = af9033_wr_reg_mask(state, 0x80f990, 0x00, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x00, 0x01); ++ if (ret < 0) ++ goto err; ++ } ++ ++ /* load OFSM settings */ ++ pr_debug("%s: load ofsm settings\n", __func__); ++ len = ARRAY_SIZE(ofsm_init); ++ init = ofsm_init; ++ for (i = 0; i < len; i++) { ++ ret = af9033_wr_reg(state, init[i].reg, init[i].val); ++ if (ret < 0) ++ goto err; ++ } ++ ++ /* load tuner specific settings */ ++ pr_debug("%s: load tuner specific settings\n", ++ __func__); ++ switch (state->cfg.tuner) { ++ case AF9033_TUNER_TUA9001: ++ len = ARRAY_SIZE(tuner_init_tua9001); ++ init = tuner_init_tua9001; ++ break; ++ case AF9033_TUNER_FC0011: ++ len = ARRAY_SIZE(tuner_init_fc0011); ++ init = tuner_init_fc0011; ++ break; ++ case AF9033_TUNER_MXL5007T: ++ len = ARRAY_SIZE(tuner_init_mxl5007t); ++ init = tuner_init_mxl5007t; ++ break; ++ case AF9033_TUNER_TDA18218: ++ len = ARRAY_SIZE(tuner_init_tda18218); ++ init = tuner_init_tda18218; ++ break; ++ default: ++ pr_debug("%s: unsupported tuner ID=%d\n", __func__, ++ state->cfg.tuner); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ for (i = 0; i < len; i++) { ++ ret = af9033_wr_reg(state, init[i].reg, init[i].val); ++ if (ret < 0) ++ goto err; ++ } ++ ++ state->bandwidth_hz = 0; /* force to program all parameters */ ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9033_sleep(struct dvb_frontend *fe) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ int ret, i; ++ u8 tmp; ++ ++ ret = af9033_wr_reg(state, 0x80004c, 1); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_wr_reg(state, 0x800000, 0); ++ if (ret < 0) ++ goto err; ++ ++ for (i = 100, tmp = 1; i && tmp; i--) { ++ ret = af9033_rd_reg(state, 0x80004c, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ usleep_range(200, 10000); ++ } ++ ++ pr_debug("%s: loop=%d\n", __func__, i); ++ ++ if (i == 0) { ++ ret = -ETIMEDOUT; ++ goto err; ++ } ++ ++ ret = af9033_wr_reg_mask(state, 0x80fb24, 0x08, 0x08); ++ if (ret < 0) ++ goto err; ++ ++ /* prevent current leak (?) */ ++ if (state->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { ++ /* enable parallel TS */ ++ ret = af9033_wr_reg_mask(state, 0x00d917, 0x00, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_wr_reg_mask(state, 0x00d916, 0x01, 0x01); ++ if (ret < 0) ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9033_get_tune_settings(struct dvb_frontend *fe, ++ struct dvb_frontend_tune_settings *fesettings) ++{ ++ fesettings->min_delay_ms = 800; ++ fesettings->step_size = 0; ++ fesettings->max_drift = 0; ++ ++ return 0; ++} ++ ++static int af9033_set_frontend(struct dvb_frontend *fe) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret, i, spec_inv; ++ u8 tmp, buf[3], bandwidth_reg_val; ++ u32 if_frequency, freq_cw, adc_freq; ++ ++ pr_debug("%s: frequency=%d bandwidth_hz=%d\n", __func__, c->frequency, ++ c->bandwidth_hz); ++ ++ /* check bandwidth */ ++ switch (c->bandwidth_hz) { ++ case 6000000: ++ bandwidth_reg_val = 0x00; ++ break; ++ case 7000000: ++ bandwidth_reg_val = 0x01; ++ break; ++ case 8000000: ++ bandwidth_reg_val = 0x02; ++ break; ++ default: ++ pr_debug("%s: invalid bandwidth_hz\n", __func__); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ /* program tuner */ ++ if (fe->ops.tuner_ops.set_params) ++ fe->ops.tuner_ops.set_params(fe); ++ ++ /* program CFOE coefficients */ ++ if (c->bandwidth_hz != state->bandwidth_hz) { ++ for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) { ++ if (coeff_lut[i].clock == state->cfg.clock && ++ coeff_lut[i].bandwidth_hz == c->bandwidth_hz) { ++ break; ++ } ++ } ++ ret = af9033_wr_regs(state, 0x800001, ++ coeff_lut[i].val, sizeof(coeff_lut[i].val)); ++ } ++ ++ /* program frequency control */ ++ if (c->bandwidth_hz != state->bandwidth_hz) { ++ spec_inv = state->cfg.spec_inv ? -1 : 1; ++ ++ for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { ++ if (clock_adc_lut[i].clock == state->cfg.clock) ++ break; ++ } ++ adc_freq = clock_adc_lut[i].adc; ++ ++ /* get used IF frequency */ ++ if (fe->ops.tuner_ops.get_if_frequency) ++ fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency); ++ else ++ if_frequency = 0; ++ ++ while (if_frequency > (adc_freq / 2)) ++ if_frequency -= adc_freq; ++ ++ if (if_frequency >= 0) ++ spec_inv *= -1; ++ else ++ if_frequency *= -1; ++ ++ freq_cw = af9033_div(if_frequency, adc_freq, 23ul); ++ ++ if (spec_inv == -1) ++ freq_cw *= -1; ++ ++ /* get adc multiplies */ ++ ret = af9033_rd_reg(state, 0x800045, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ if (tmp == 1) ++ freq_cw /= 2; ++ ++ buf[0] = (freq_cw >> 0) & 0xff; ++ buf[1] = (freq_cw >> 8) & 0xff; ++ buf[2] = (freq_cw >> 16) & 0x7f; ++ ret = af9033_wr_regs(state, 0x800029, buf, 3); ++ if (ret < 0) ++ goto err; ++ ++ state->bandwidth_hz = c->bandwidth_hz; ++ } ++ ++ ret = af9033_wr_reg_mask(state, 0x80f904, bandwidth_reg_val, 0x03); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_wr_reg(state, 0x800040, 0x00); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_wr_reg(state, 0x800047, 0x00); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_wr_reg_mask(state, 0x80f999, 0x00, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ if (c->frequency <= 230000000) ++ tmp = 0x00; /* VHF */ ++ else ++ tmp = 0x01; /* UHF */ ++ ++ ret = af9033_wr_reg(state, 0x80004b, tmp); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_wr_reg(state, 0x800000, 0x00); ++ if (ret < 0) ++ goto err; ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9033_get_frontend(struct dvb_frontend *fe) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret; ++ u8 buf[8]; ++ ++ pr_debug("%s\n", __func__); ++ ++ /* read all needed registers */ ++ ret = af9033_rd_regs(state, 0x80f900, buf, sizeof(buf)); ++ if (ret < 0) ++ goto err; ++ ++ switch ((buf[0] >> 0) & 3) { ++ case 0: ++ c->transmission_mode = TRANSMISSION_MODE_2K; ++ break; ++ case 1: ++ c->transmission_mode = TRANSMISSION_MODE_8K; ++ break; ++ } ++ ++ switch ((buf[1] >> 0) & 3) { ++ case 0: ++ c->guard_interval = GUARD_INTERVAL_1_32; ++ break; ++ case 1: ++ c->guard_interval = GUARD_INTERVAL_1_16; ++ break; ++ case 2: ++ c->guard_interval = GUARD_INTERVAL_1_8; ++ break; ++ case 3: ++ c->guard_interval = GUARD_INTERVAL_1_4; ++ break; ++ } ++ ++ switch ((buf[2] >> 0) & 7) { ++ case 0: ++ c->hierarchy = HIERARCHY_NONE; ++ break; ++ case 1: ++ c->hierarchy = HIERARCHY_1; ++ break; ++ case 2: ++ c->hierarchy = HIERARCHY_2; ++ break; ++ case 3: ++ c->hierarchy = HIERARCHY_4; ++ break; ++ } ++ ++ switch ((buf[3] >> 0) & 3) { ++ case 0: ++ c->modulation = QPSK; ++ break; ++ case 1: ++ c->modulation = QAM_16; ++ break; ++ case 2: ++ c->modulation = QAM_64; ++ break; ++ } ++ ++ switch ((buf[4] >> 0) & 3) { ++ case 0: ++ c->bandwidth_hz = 6000000; ++ break; ++ case 1: ++ c->bandwidth_hz = 7000000; ++ break; ++ case 2: ++ c->bandwidth_hz = 8000000; ++ break; ++ } ++ ++ switch ((buf[6] >> 0) & 7) { ++ case 0: ++ c->code_rate_HP = FEC_1_2; ++ break; ++ case 1: ++ c->code_rate_HP = FEC_2_3; ++ break; ++ case 2: ++ c->code_rate_HP = FEC_3_4; ++ break; ++ case 3: ++ c->code_rate_HP = FEC_5_6; ++ break; ++ case 4: ++ c->code_rate_HP = FEC_7_8; ++ break; ++ case 5: ++ c->code_rate_HP = FEC_NONE; ++ break; ++ } ++ ++ switch ((buf[7] >> 0) & 7) { ++ case 0: ++ c->code_rate_LP = FEC_1_2; ++ break; ++ case 1: ++ c->code_rate_LP = FEC_2_3; ++ break; ++ case 2: ++ c->code_rate_LP = FEC_3_4; ++ break; ++ case 3: ++ c->code_rate_LP = FEC_5_6; ++ break; ++ case 4: ++ c->code_rate_LP = FEC_7_8; ++ break; ++ case 5: ++ c->code_rate_LP = FEC_NONE; ++ break; ++ } ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ int ret; ++ u8 tmp; ++ ++ *status = 0; ++ ++ /* radio channel status, 0=no result, 1=has signal, 2=no signal */ ++ ret = af9033_rd_reg(state, 0x800047, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ /* has signal */ ++ if (tmp == 0x01) ++ *status |= FE_HAS_SIGNAL; ++ ++ if (tmp != 0x02) { ++ /* TPS lock */ ++ ret = af9033_rd_reg_mask(state, 0x80f5a9, &tmp, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ if (tmp) ++ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | ++ FE_HAS_VITERBI; ++ ++ /* full lock */ ++ ret = af9033_rd_reg_mask(state, 0x80f999, &tmp, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ if (tmp) ++ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | ++ FE_HAS_VITERBI | FE_HAS_SYNC | ++ FE_HAS_LOCK; ++ } ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9033_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ int ret, i, len; ++ u8 buf[3], tmp; ++ u32 snr_val; ++ const struct val_snr *uninitialized_var(snr_lut); ++ ++ /* read value */ ++ ret = af9033_rd_regs(state, 0x80002c, buf, 3); ++ if (ret < 0) ++ goto err; ++ ++ snr_val = (buf[2] << 16) | (buf[1] << 8) | buf[0]; ++ ++ /* read current modulation */ ++ ret = af9033_rd_reg(state, 0x80f903, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ switch ((tmp >> 0) & 3) { ++ case 0: ++ len = ARRAY_SIZE(qpsk_snr_lut); ++ snr_lut = qpsk_snr_lut; ++ break; ++ case 1: ++ len = ARRAY_SIZE(qam16_snr_lut); ++ snr_lut = qam16_snr_lut; ++ break; ++ case 2: ++ len = ARRAY_SIZE(qam64_snr_lut); ++ snr_lut = qam64_snr_lut; ++ break; ++ default: ++ goto err; ++ } ++ ++ for (i = 0; i < len; i++) { ++ tmp = snr_lut[i].snr; ++ ++ if (snr_val < snr_lut[i].val) ++ break; ++ } ++ ++ *snr = tmp * 10; /* dB/10 */ ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ int ret; ++ u8 strength2; ++ ++ /* read signal strength of 0-100 scale */ ++ ret = af9033_rd_reg(state, 0x800048, &strength2); ++ if (ret < 0) ++ goto err; ++ ++ /* scale value to 0x0000-0xffff */ ++ *strength = strength2 * 0xffff / 100; ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9033_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ *ber = 0; ++ ++ return 0; ++} ++ ++static int af9033_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ *ucblocks = 0; ++ ++ return 0; ++} ++ ++static int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ int ret; ++ ++ pr_debug("%s: enable=%d\n", __func__, enable); ++ ++ ret = af9033_wr_reg_mask(state, 0x00fa04, enable, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static struct dvb_frontend_ops af9033_ops; ++ ++struct dvb_frontend *af9033_attach(const struct af9033_config *config, ++ struct i2c_adapter *i2c) ++{ ++ int ret; ++ struct af9033_state *state; ++ u8 buf[8]; ++ ++ pr_debug("%s:\n", __func__); ++ ++ /* allocate memory for the internal state */ ++ state = kzalloc(sizeof(struct af9033_state), GFP_KERNEL); ++ if (state == NULL) ++ goto err; ++ ++ /* setup the state */ ++ state->i2c = i2c; ++ memcpy(&state->cfg, config, sizeof(struct af9033_config)); ++ ++ if (state->cfg.clock != 12000000) { ++ printk(KERN_INFO "af9033: unsupported clock=%d, only " \ ++ "12000000 Hz is supported currently\n", ++ state->cfg.clock); ++ goto err; ++ } ++ ++ /* firmware version */ ++ ret = af9033_rd_regs(state, 0x0083e9, &buf[0], 4); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_rd_regs(state, 0x804191, &buf[4], 4); ++ if (ret < 0) ++ goto err; ++ ++ printk(KERN_INFO "af9033: firmware version: LINK=%d.%d.%d.%d " \ ++ "OFDM=%d.%d.%d.%d\n", buf[0], buf[1], buf[2], buf[3], ++ buf[4], buf[5], buf[6], buf[7]); ++ ++ /* configure internal TS mode */ ++ switch (state->cfg.ts_mode) { ++ case AF9033_TS_MODE_PARALLEL: ++ state->ts_mode_parallel = true; ++ break; ++ case AF9033_TS_MODE_SERIAL: ++ state->ts_mode_serial = true; ++ break; ++ case AF9033_TS_MODE_USB: ++ /* usb mode for AF9035 */ ++ default: ++ break; ++ } ++ ++ /* create dvb_frontend */ ++ memcpy(&state->fe.ops, &af9033_ops, sizeof(struct dvb_frontend_ops)); ++ state->fe.demodulator_priv = state; ++ ++ return &state->fe; ++ ++err: ++ kfree(state); ++ return NULL; ++} ++EXPORT_SYMBOL(af9033_attach); ++ ++static struct dvb_frontend_ops af9033_ops = { ++ .delsys = { SYS_DVBT }, ++ .info = { ++ .name = "Afatech AF9033 (DVB-T)", ++ .frequency_min = 174000000, ++ .frequency_max = 862000000, ++ .frequency_stepsize = 250000, ++ .frequency_tolerance = 0, ++ .caps = FE_CAN_FEC_1_2 | ++ FE_CAN_FEC_2_3 | ++ FE_CAN_FEC_3_4 | ++ FE_CAN_FEC_5_6 | ++ FE_CAN_FEC_7_8 | ++ FE_CAN_FEC_AUTO | ++ FE_CAN_QPSK | ++ FE_CAN_QAM_16 | ++ FE_CAN_QAM_64 | ++ FE_CAN_QAM_AUTO | ++ FE_CAN_TRANSMISSION_MODE_AUTO | ++ FE_CAN_GUARD_INTERVAL_AUTO | ++ FE_CAN_HIERARCHY_AUTO | ++ FE_CAN_RECOVER | ++ FE_CAN_MUTE_TS ++ }, ++ ++ .release = af9033_release, ++ ++ .init = af9033_init, ++ .sleep = af9033_sleep, ++ ++ .get_tune_settings = af9033_get_tune_settings, ++ .set_frontend = af9033_set_frontend, ++ .get_frontend = af9033_get_frontend, ++ ++ .read_status = af9033_read_status, ++ .read_snr = af9033_read_snr, ++ .read_signal_strength = af9033_read_signal_strength, ++ .read_ber = af9033_read_ber, ++ .read_ucblocks = af9033_read_ucblocks, ++ ++ .i2c_gate_ctrl = af9033_i2c_gate_ctrl, ++}; ++ ++MODULE_AUTHOR("Antti Palosaari "); ++MODULE_DESCRIPTION("Afatech AF9033 DVB-T demodulator driver"); ++MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/af9033.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/af9033.h +@@ -0,0 +1,75 @@ ++/* ++ * Afatech AF9033 demodulator driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * Copyright (C) 2012 Antti Palosaari ++ * ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef AF9033_H ++#define AF9033_H ++ ++struct af9033_config { ++ /* ++ * I2C address ++ */ ++ u8 i2c_addr; ++ ++ /* ++ * clock Hz ++ * 12000000, 22000000, 24000000, 34000000, 32000000, 28000000, 26000000, ++ * 30000000, 36000000, 20480000, 16384000 ++ */ ++ u32 clock; ++ ++ /* ++ * tuner ++ */ ++#define AF9033_TUNER_TUA9001 0x27 /* Infineon TUA 9001 */ ++#define AF9033_TUNER_FC0011 0x28 /* Fitipower FC0011 */ ++#define AF9033_TUNER_MXL5007T 0xa0 /* MaxLinear MxL5007T */ ++#define AF9033_TUNER_TDA18218 0xa1 /* NXP TDA 18218HN */ ++ u8 tuner; ++ ++ /* ++ * TS settings ++ */ ++#define AF9033_TS_MODE_USB 0 ++#define AF9033_TS_MODE_PARALLEL 1 ++#define AF9033_TS_MODE_SERIAL 2 ++ u8 ts_mode:2; ++ ++ /* ++ * input spectrum inversion ++ */ ++ bool spec_inv; ++}; ++ ++ ++#if defined(CONFIG_DVB_AF9033) || \ ++ (defined(CONFIG_DVB_AF9033_MODULE) && defined(MODULE)) ++extern struct dvb_frontend *af9033_attach(const struct af9033_config *config, ++ struct i2c_adapter *i2c); ++#else ++static inline struct dvb_frontend *af9033_attach( ++ const struct af9033_config *config, struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif ++ ++#endif /* AF9033_H */ +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/af9033_priv.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/af9033_priv.h +@@ -0,0 +1,470 @@ ++/* ++ * Afatech AF9033 demodulator driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * Copyright (C) 2012 Antti Palosaari ++ * ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef AF9033_PRIV_H ++#define AF9033_PRIV_H ++ ++#include "dvb_frontend.h" ++#include "af9033.h" ++ ++struct reg_val { ++ u32 reg; ++ u8 val; ++}; ++ ++struct reg_val_mask { ++ u32 reg; ++ u8 val; ++ u8 mask; ++}; ++ ++struct coeff { ++ u32 clock; ++ u32 bandwidth_hz; ++ u8 val[36]; ++}; ++ ++struct clock_adc { ++ u32 clock; ++ u32 adc; ++}; ++ ++struct val_snr { ++ u32 val; ++ u8 snr; ++}; ++ ++/* Xtal clock vs. ADC clock lookup table */ ++static const struct clock_adc clock_adc_lut[] = { ++ { 16384000, 20480000 }, ++ { 20480000, 20480000 }, ++ { 36000000, 20250000 }, ++ { 30000000, 20156250 }, ++ { 26000000, 20583333 }, ++ { 28000000, 20416667 }, ++ { 32000000, 20500000 }, ++ { 34000000, 20187500 }, ++ { 24000000, 20500000 }, ++ { 22000000, 20625000 }, ++ { 12000000, 20250000 }, ++}; ++ ++/* pre-calculated coeff lookup table */ ++static const struct coeff coeff_lut[] = { ++ /* 12.000 MHz */ ++ { 12000000, 8000000, { ++ 0x01, 0xce, 0x55, 0xc9, 0x00, 0xe7, 0x2a, 0xe4, 0x00, 0x73, ++ 0x99, 0x0f, 0x00, 0x73, 0x95, 0x72, 0x00, 0x73, 0x91, 0xd5, ++ 0x00, 0x39, 0xca, 0xb9, 0x00, 0xe7, 0x2a, 0xe4, 0x00, 0x73, ++ 0x95, 0x72, 0x37, 0x02, 0xce, 0x01 } ++ }, ++ { 12000000, 7000000, { ++ 0x01, 0x94, 0x8b, 0x10, 0x00, 0xca, 0x45, 0x88, 0x00, 0x65, ++ 0x25, 0xed, 0x00, 0x65, 0x22, 0xc4, 0x00, 0x65, 0x1f, 0x9b, ++ 0x00, 0x32, 0x91, 0x62, 0x00, 0xca, 0x45, 0x88, 0x00, 0x65, ++ 0x22, 0xc4, 0x88, 0x02, 0x95, 0x01 } ++ }, ++ { 12000000, 6000000, { ++ 0x01, 0x5a, 0xc0, 0x56, 0x00, 0xad, 0x60, 0x2b, 0x00, 0x56, ++ 0xb2, 0xcb, 0x00, 0x56, 0xb0, 0x15, 0x00, 0x56, 0xad, 0x60, ++ 0x00, 0x2b, 0x58, 0x0b, 0x00, 0xad, 0x60, 0x2b, 0x00, 0x56, ++ 0xb0, 0x15, 0xf4, 0x02, 0x5b, 0x01 } ++ }, ++}; ++ ++/* QPSK SNR lookup table */ ++static const struct val_snr qpsk_snr_lut[] = { ++ { 0x0b4771, 0 }, ++ { 0x0c1aed, 1 }, ++ { 0x0d0d27, 2 }, ++ { 0x0e4d19, 3 }, ++ { 0x0e5da8, 4 }, ++ { 0x107097, 5 }, ++ { 0x116975, 6 }, ++ { 0x1252d9, 7 }, ++ { 0x131fa4, 8 }, ++ { 0x13d5e1, 9 }, ++ { 0x148e53, 10 }, ++ { 0x15358b, 11 }, ++ { 0x15dd29, 12 }, ++ { 0x168112, 13 }, ++ { 0x170b61, 14 }, ++ { 0x17a532, 15 }, ++ { 0x180f94, 16 }, ++ { 0x186ed2, 17 }, ++ { 0x18b271, 18 }, ++ { 0x18e118, 19 }, ++ { 0x18ff4b, 20 }, ++ { 0x190af1, 21 }, ++ { 0x191451, 22 }, ++ { 0xffffff, 23 }, ++}; ++ ++/* QAM16 SNR lookup table */ ++static const struct val_snr qam16_snr_lut[] = { ++ { 0x04f0d5, 0 }, ++ { 0x05387a, 1 }, ++ { 0x0573a4, 2 }, ++ { 0x05a99e, 3 }, ++ { 0x05cc80, 4 }, ++ { 0x05eb62, 5 }, ++ { 0x05fecf, 6 }, ++ { 0x060b80, 7 }, ++ { 0x062501, 8 }, ++ { 0x064865, 9 }, ++ { 0x069604, 10 }, ++ { 0x06f356, 11 }, ++ { 0x07706a, 12 }, ++ { 0x0804d3, 13 }, ++ { 0x089d1a, 14 }, ++ { 0x093e3d, 15 }, ++ { 0x09e35d, 16 }, ++ { 0x0a7c3c, 17 }, ++ { 0x0afaf8, 18 }, ++ { 0x0b719d, 19 }, ++ { 0x0bda6a, 20 }, ++ { 0x0c0c75, 21 }, ++ { 0x0c3f7d, 22 }, ++ { 0x0c5e62, 23 }, ++ { 0x0c6c31, 24 }, ++ { 0x0c7925, 25 }, ++ { 0xffffff, 26 }, ++}; ++ ++/* QAM64 SNR lookup table */ ++static const struct val_snr qam64_snr_lut[] = { ++ { 0x0256d0, 0 }, ++ { 0x027a65, 1 }, ++ { 0x029873, 2 }, ++ { 0x02b7fe, 3 }, ++ { 0x02cf1e, 4 }, ++ { 0x02e234, 5 }, ++ { 0x02f409, 6 }, ++ { 0x030046, 7 }, ++ { 0x030844, 8 }, ++ { 0x030a02, 9 }, ++ { 0x030cde, 10 }, ++ { 0x031031, 11 }, ++ { 0x03144c, 12 }, ++ { 0x0315dd, 13 }, ++ { 0x031920, 14 }, ++ { 0x0322d0, 15 }, ++ { 0x0339fc, 16 }, ++ { 0x0364a1, 17 }, ++ { 0x038bcc, 18 }, ++ { 0x03c7d3, 19 }, ++ { 0x0408cc, 20 }, ++ { 0x043bed, 21 }, ++ { 0x048061, 22 }, ++ { 0x04be95, 23 }, ++ { 0x04fa7d, 24 }, ++ { 0x052405, 25 }, ++ { 0x05570d, 26 }, ++ { 0x059feb, 27 }, ++ { 0x05bf38, 28 }, ++ { 0xffffff, 29 }, ++}; ++ ++static const struct reg_val ofsm_init[] = { ++ { 0x800051, 0x01 }, ++ { 0x800070, 0x0a }, ++ { 0x80007e, 0x04 }, ++ { 0x800081, 0x0a }, ++ { 0x80008a, 0x01 }, ++ { 0x80008e, 0x01 }, ++ { 0x800092, 0x06 }, ++ { 0x800099, 0x01 }, ++ { 0x80009f, 0xe1 }, ++ { 0x8000a0, 0xcf }, ++ { 0x8000a3, 0x01 }, ++ { 0x8000a5, 0x01 }, ++ { 0x8000a6, 0x01 }, ++ { 0x8000a9, 0x00 }, ++ { 0x8000aa, 0x01 }, ++ { 0x8000ab, 0x01 }, ++ { 0x8000b0, 0x01 }, ++ { 0x8000c0, 0x05 }, ++ { 0x8000c4, 0x19 }, ++ { 0x80f000, 0x0f }, ++ { 0x80f016, 0x10 }, ++ { 0x80f017, 0x04 }, ++ { 0x80f018, 0x05 }, ++ { 0x80f019, 0x04 }, ++ { 0x80f01a, 0x05 }, ++ { 0x80f021, 0x03 }, ++ { 0x80f022, 0x0a }, ++ { 0x80f023, 0x0a }, ++ { 0x80f02b, 0x00 }, ++ { 0x80f02c, 0x01 }, ++ { 0x80f064, 0x03 }, ++ { 0x80f065, 0xf9 }, ++ { 0x80f066, 0x03 }, ++ { 0x80f067, 0x01 }, ++ { 0x80f06f, 0xe0 }, ++ { 0x80f070, 0x03 }, ++ { 0x80f072, 0x0f }, ++ { 0x80f073, 0x03 }, ++ { 0x80f078, 0x00 }, ++ { 0x80f087, 0x00 }, ++ { 0x80f09b, 0x3f }, ++ { 0x80f09c, 0x00 }, ++ { 0x80f09d, 0x20 }, ++ { 0x80f09e, 0x00 }, ++ { 0x80f09f, 0x0c }, ++ { 0x80f0a0, 0x00 }, ++ { 0x80f130, 0x04 }, ++ { 0x80f132, 0x04 }, ++ { 0x80f144, 0x1a }, ++ { 0x80f146, 0x00 }, ++ { 0x80f14a, 0x01 }, ++ { 0x80f14c, 0x00 }, ++ { 0x80f14d, 0x00 }, ++ { 0x80f14f, 0x04 }, ++ { 0x80f158, 0x7f }, ++ { 0x80f15a, 0x00 }, ++ { 0x80f15b, 0x08 }, ++ { 0x80f15d, 0x03 }, ++ { 0x80f15e, 0x05 }, ++ { 0x80f163, 0x05 }, ++ { 0x80f166, 0x01 }, ++ { 0x80f167, 0x40 }, ++ { 0x80f168, 0x0f }, ++ { 0x80f17a, 0x00 }, ++ { 0x80f17b, 0x00 }, ++ { 0x80f183, 0x01 }, ++ { 0x80f19d, 0x40 }, ++ { 0x80f1bc, 0x36 }, ++ { 0x80f1bd, 0x00 }, ++ { 0x80f1cb, 0xa0 }, ++ { 0x80f1cc, 0x01 }, ++ { 0x80f204, 0x10 }, ++ { 0x80f214, 0x00 }, ++ { 0x80f40e, 0x0a }, ++ { 0x80f40f, 0x40 }, ++ { 0x80f410, 0x08 }, ++ { 0x80f55f, 0x0a }, ++ { 0x80f561, 0x15 }, ++ { 0x80f562, 0x20 }, ++ { 0x80f5df, 0xfb }, ++ { 0x80f5e0, 0x00 }, ++ { 0x80f5e3, 0x09 }, ++ { 0x80f5e4, 0x01 }, ++ { 0x80f5e5, 0x01 }, ++ { 0x80f5f8, 0x01 }, ++ { 0x80f5fd, 0x01 }, ++ { 0x80f600, 0x05 }, ++ { 0x80f601, 0x08 }, ++ { 0x80f602, 0x0b }, ++ { 0x80f603, 0x0e }, ++ { 0x80f604, 0x11 }, ++ { 0x80f605, 0x14 }, ++ { 0x80f606, 0x17 }, ++ { 0x80f607, 0x1f }, ++ { 0x80f60e, 0x00 }, ++ { 0x80f60f, 0x04 }, ++ { 0x80f610, 0x32 }, ++ { 0x80f611, 0x10 }, ++ { 0x80f707, 0xfc }, ++ { 0x80f708, 0x00 }, ++ { 0x80f709, 0x37 }, ++ { 0x80f70a, 0x00 }, ++ { 0x80f78b, 0x01 }, ++ { 0x80f80f, 0x40 }, ++ { 0x80f810, 0x54 }, ++ { 0x80f811, 0x5a }, ++ { 0x80f905, 0x01 }, ++ { 0x80fb06, 0x03 }, ++ { 0x80fd8b, 0x00 }, ++}; ++ ++/* Infineon TUA 9001 tuner init ++ AF9033_TUNER_TUA9001 = 0x27 */ ++static const struct reg_val tuner_init_tua9001[] = { ++ { 0x800046, 0x27 }, ++ { 0x800057, 0x00 }, ++ { 0x800058, 0x01 }, ++ { 0x80005f, 0x00 }, ++ { 0x800060, 0x00 }, ++ { 0x80006d, 0x00 }, ++ { 0x800071, 0x05 }, ++ { 0x800072, 0x02 }, ++ { 0x800074, 0x01 }, ++ { 0x800075, 0x03 }, ++ { 0x800076, 0x02 }, ++ { 0x800077, 0x00 }, ++ { 0x800078, 0x01 }, ++ { 0x800079, 0x00 }, ++ { 0x80007a, 0x7e }, ++ { 0x80007b, 0x3e }, ++ { 0x800093, 0x00 }, ++ { 0x800094, 0x01 }, ++ { 0x800095, 0x02 }, ++ { 0x800096, 0x01 }, ++ { 0x800098, 0x0a }, ++ { 0x80009b, 0x05 }, ++ { 0x80009c, 0x80 }, ++ { 0x8000b3, 0x00 }, ++ { 0x8000c1, 0x01 }, ++ { 0x8000c2, 0x00 }, ++ { 0x80f007, 0x00 }, ++ { 0x80f01f, 0x82 }, ++ { 0x80f020, 0x00 }, ++ { 0x80f029, 0x82 }, ++ { 0x80f02a, 0x00 }, ++ { 0x80f047, 0x00 }, ++ { 0x80f054, 0x00 }, ++ { 0x80f055, 0x00 }, ++ { 0x80f077, 0x01 }, ++ { 0x80f1e6, 0x00 }, ++}; ++ ++/* Fitipower fc0011 tuner init ++ AF9033_TUNER_FC0011 = 0x28 */ ++static const struct reg_val tuner_init_fc0011[] = { ++ { 0x800046, AF9033_TUNER_FC0011 }, ++ { 0x800057, 0x00 }, ++ { 0x800058, 0x01 }, ++ { 0x80005f, 0x00 }, ++ { 0x800060, 0x00 }, ++ { 0x800068, 0xa5 }, ++ { 0x80006e, 0x01 }, ++ { 0x800071, 0x0A }, ++ { 0x800072, 0x02 }, ++ { 0x800074, 0x01 }, ++ { 0x800079, 0x01 }, ++ { 0x800093, 0x00 }, ++ { 0x800094, 0x00 }, ++ { 0x800095, 0x00 }, ++ { 0x800096, 0x00 }, ++ { 0x80009b, 0x2D }, ++ { 0x80009c, 0x60 }, ++ { 0x80009d, 0x23 }, ++ { 0x8000a4, 0x50 }, ++ { 0x8000ad, 0x50 }, ++ { 0x8000b3, 0x01 }, ++ { 0x8000b7, 0x88 }, ++ { 0x8000b8, 0xa6 }, ++ { 0x8000c3, 0x01 }, ++ { 0x8000c4, 0x01 }, ++ { 0x8000c7, 0x69 }, ++ { 0x80F007, 0x00 }, ++ { 0x80F00A, 0x1B }, ++ { 0x80F00B, 0x1B }, ++ { 0x80F00C, 0x1B }, ++ { 0x80F00D, 0x1B }, ++ { 0x80F00E, 0xFF }, ++ { 0x80F00F, 0x01 }, ++ { 0x80F010, 0x00 }, ++ { 0x80F011, 0x02 }, ++ { 0x80F012, 0xFF }, ++ { 0x80F013, 0x01 }, ++ { 0x80F014, 0x00 }, ++ { 0x80F015, 0x02 }, ++ { 0x80F01B, 0xEF }, ++ { 0x80F01C, 0x01 }, ++ { 0x80F01D, 0x0f }, ++ { 0x80F01E, 0x02 }, ++ { 0x80F01F, 0x6E }, ++ { 0x80F020, 0x00 }, ++ { 0x80F025, 0xDE }, ++ { 0x80F026, 0x00 }, ++ { 0x80F027, 0x0A }, ++ { 0x80F028, 0x03 }, ++ { 0x80F029, 0x6E }, ++ { 0x80F02A, 0x00 }, ++ { 0x80F047, 0x00 }, ++ { 0x80F054, 0x00 }, ++ { 0x80F055, 0x00 }, ++ { 0x80F077, 0x01 }, ++ { 0x80F1E6, 0x00 }, ++}; ++ ++/* MaxLinear MxL5007T tuner init ++ AF9033_TUNER_MXL5007T = 0xa0 */ ++static const struct reg_val tuner_init_mxl5007t[] = { ++ { 0x800046, 0x1b }, ++ { 0x800057, 0x01 }, ++ { 0x800058, 0x01 }, ++ { 0x80005f, 0x00 }, ++ { 0x800060, 0x00 }, ++ { 0x800068, 0x96 }, ++ { 0x800071, 0x05 }, ++ { 0x800072, 0x02 }, ++ { 0x800074, 0x01 }, ++ { 0x800079, 0x01 }, ++ { 0x800093, 0x00 }, ++ { 0x800094, 0x00 }, ++ { 0x800095, 0x00 }, ++ { 0x800096, 0x00 }, ++ { 0x8000b3, 0x01 }, ++ { 0x8000c1, 0x01 }, ++ { 0x8000c2, 0x00 }, ++ { 0x80f007, 0x00 }, ++ { 0x80f00c, 0x19 }, ++ { 0x80f00d, 0x1a }, ++ { 0x80f012, 0xda }, ++ { 0x80f013, 0x00 }, ++ { 0x80f014, 0x00 }, ++ { 0x80f015, 0x02 }, ++ { 0x80f01f, 0x82 }, ++ { 0x80f020, 0x00 }, ++ { 0x80f029, 0x82 }, ++ { 0x80f02a, 0x00 }, ++ { 0x80f077, 0x02 }, ++ { 0x80f1e6, 0x00 }, ++}; ++ ++/* NXP TDA 18218HN tuner init ++ AF9033_TUNER_TDA18218 = 0xa1 */ ++static const struct reg_val tuner_init_tda18218[] = { ++ {0x800046, 0xa1}, ++ {0x800057, 0x01}, ++ {0x800058, 0x01}, ++ {0x80005f, 0x00}, ++ {0x800060, 0x00}, ++ {0x800071, 0x05}, ++ {0x800072, 0x02}, ++ {0x800074, 0x01}, ++ {0x800079, 0x01}, ++ {0x800093, 0x00}, ++ {0x800094, 0x00}, ++ {0x800095, 0x00}, ++ {0x800096, 0x00}, ++ {0x8000b3, 0x01}, ++ {0x8000c3, 0x01}, ++ {0x8000c4, 0x00}, ++ {0x80f007, 0x00}, ++ {0x80f00c, 0x19}, ++ {0x80f00d, 0x1a}, ++ {0x80f012, 0xda}, ++ {0x80f013, 0x00}, ++ {0x80f014, 0x00}, ++ {0x80f015, 0x02}, ++ {0x80f01f, 0x82}, ++ {0x80f020, 0x00}, ++ {0x80f029, 0x82}, ++ {0x80f02a, 0x00}, ++ {0x80f077, 0x02}, ++ {0x80f1e6, 0x00}, ++}; ++ ++#endif /* AF9033_PRIV_H */ ++ +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9035.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9035.c +@@ -0,0 +1,1164 @@ ++/* ++ * Afatech AF9035 DVB USB driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * Copyright (C) 2012 Antti Palosaari ++ * ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include "af9035.h" ++#include "af9033.h" ++#include "tua9001.h" ++#include "fc0011.h" ++#include "mxl5007t.h" ++#include "tda18218.h" ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++static DEFINE_MUTEX(af9035_usb_mutex); ++static struct config af9035_config; ++static struct dvb_usb_device_properties af9035_properties[2]; ++static int af9035_properties_count = ARRAY_SIZE(af9035_properties); ++static struct af9033_config af9035_af9033_config[] = { ++ { ++ .ts_mode = AF9033_TS_MODE_USB, ++ }, { ++ .ts_mode = AF9033_TS_MODE_SERIAL, ++ } ++}; ++ ++static u16 af9035_checksum(const u8 *buf, size_t len) ++{ ++ size_t i; ++ u16 checksum = 0; ++ ++ for (i = 1; i < len; i++) { ++ if (i % 2) ++ checksum += buf[i] << 8; ++ else ++ checksum += buf[i]; ++ } ++ checksum = ~checksum; ++ ++ return checksum; ++} ++ ++static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req) ++{ ++#define BUF_LEN 63 ++#define REQ_HDR_LEN 4 /* send header size */ ++#define ACK_HDR_LEN 3 /* rece header size */ ++#define CHECKSUM_LEN 2 ++#define USB_TIMEOUT 2000 ++ ++ int ret, act_len; ++ u8 buf[BUF_LEN]; ++ u32 msg_len; ++ static u8 seq; /* packet sequence number */ ++ u16 checksum, tmpsum; ++ ++ /* buffer overflow check */ ++ if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) || ++ req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) { ++ pr_debug("%s: too much data wlen=%d rlen=%d\n", __func__, ++ req->wlen, req->rlen); ++ return -EINVAL; ++ } ++ ++ if (mutex_lock_interruptible(&af9035_usb_mutex) < 0) ++ return -EAGAIN; ++ ++ buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1; ++ buf[1] = req->mbox; ++ buf[2] = req->cmd; ++ buf[3] = seq++; ++ if (req->wlen) ++ memcpy(&buf[4], req->wbuf, req->wlen); ++ ++ /* calc and add checksum */ ++ checksum = af9035_checksum(buf, buf[0] - 1); ++ buf[buf[0]-1] = (checksum >> 8); ++ buf[buf[0]-0] = (checksum & 0xff); ++ ++ msg_len = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN ; ++ ++ /* send req */ ++ ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len, ++ &act_len, USB_TIMEOUT); ++ if (ret < 0) ++ err("bulk message failed=%d (%d/%d)", ret, msg_len, act_len); ++ else ++ if (act_len != msg_len) ++ ret = -EIO; /* all data is not send */ ++ if (ret < 0) ++ goto err_mutex_unlock; ++ ++ /* no ack for those packets */ ++ if (req->cmd == CMD_FW_DL) ++ goto exit_mutex_unlock; ++ ++ /* receive ack and data if read req */ ++ msg_len = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN; ++ ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len, ++ &act_len, USB_TIMEOUT); ++ if (ret < 0) { ++ err("recv bulk message failed=%d", ret); ++ ret = -EIO; ++ goto err_mutex_unlock; ++ } ++ if (act_len != msg_len) { ++ err("recv bulk message truncated (%d != %u)\n", ++ act_len, (unsigned int)msg_len); ++ ret = -EIO; ++ goto err_mutex_unlock; ++ } ++ ++ /* verify checksum */ ++ checksum = af9035_checksum(buf, act_len - 2); ++ tmpsum = (buf[act_len - 2] << 8) | buf[act_len - 1]; ++ if (tmpsum != checksum) { ++ err("%s: command=%02X checksum mismatch (%04X != %04X)\n", ++ __func__, req->cmd, ++ (unsigned int)tmpsum, (unsigned int)checksum); ++ ret = -EIO; ++ goto err_mutex_unlock; ++ } ++ /* check status */ ++ if (buf[2]) { ++ pr_debug("%s: command=%02x failed fw error=%d\n", __func__, ++ req->cmd, buf[2]); ++ ret = -EIO; ++ goto err_mutex_unlock; ++ } ++ ++ /* read request, copy returned data to return buf */ ++ if (req->rlen) ++ memcpy(req->rbuf, &buf[ACK_HDR_LEN], req->rlen); ++ ++err_mutex_unlock: ++exit_mutex_unlock: ++ mutex_unlock(&af9035_usb_mutex); ++ ++ return ret; ++} ++ ++/* write multiple registers */ ++static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) ++{ ++ u8 wbuf[6 + len]; ++ u8 mbox = (reg >> 16) & 0xff; ++ struct usb_req req = { CMD_MEM_WR, mbox, sizeof(wbuf), wbuf, 0, NULL }; ++ ++ wbuf[0] = len; ++ wbuf[1] = 2; ++ wbuf[2] = 0; ++ wbuf[3] = 0; ++ wbuf[4] = (reg >> 8) & 0xff; ++ wbuf[5] = (reg >> 0) & 0xff; ++ memcpy(&wbuf[6], val, len); ++ ++ return af9035_ctrl_msg(d->udev, &req); ++} ++ ++/* read multiple registers */ ++static int af9035_rd_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) ++{ ++ u8 wbuf[] = { len, 2, 0, 0, (reg >> 8) & 0xff, reg & 0xff }; ++ u8 mbox = (reg >> 16) & 0xff; ++ struct usb_req req = { CMD_MEM_RD, mbox, sizeof(wbuf), wbuf, len, val }; ++ ++ return af9035_ctrl_msg(d->udev, &req); ++} ++ ++/* write single register */ ++static int af9035_wr_reg(struct dvb_usb_device *d, u32 reg, u8 val) ++{ ++ return af9035_wr_regs(d, reg, &val, 1); ++} ++ ++/* read single register */ ++static int af9035_rd_reg(struct dvb_usb_device *d, u32 reg, u8 *val) ++{ ++ return af9035_rd_regs(d, reg, val, 1); ++} ++ ++/* write single register with mask */ ++static int af9035_wr_reg_mask(struct dvb_usb_device *d, u32 reg, u8 val, ++ u8 mask) ++{ ++ int ret; ++ u8 tmp; ++ ++ /* no need for read if whole reg is written */ ++ if (mask != 0xff) { ++ ret = af9035_rd_regs(d, reg, &tmp, 1); ++ if (ret) ++ return ret; ++ ++ val &= mask; ++ tmp &= ~mask; ++ val |= tmp; ++ } ++ ++ return af9035_wr_regs(d, reg, &val, 1); ++} ++ ++static int af9035_i2c_master_xfer(struct i2c_adapter *adap, ++ struct i2c_msg msg[], int num) ++{ ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ int ret; ++ ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ /* ++ * I2C sub header is 5 bytes long. Meaning of those bytes are: ++ * 0: data len ++ * 1: I2C addr << 1 ++ * 2: reg addr len ++ * byte 3 and 4 can be used as reg addr ++ * 3: reg addr MSB ++ * used when reg addr len is set to 2 ++ * 4: reg addr LSB ++ * used when reg addr len is set to 1 or 2 ++ * ++ * For the simplify we do not use register addr at all. ++ * NOTE: As a firmware knows tuner type there is very small possibility ++ * there could be some tuner I2C hacks done by firmware and this may ++ * lead problems if firmware expects those bytes are used. ++ */ ++ if (num == 2 && !(msg[0].flags & I2C_M_RD) && ++ (msg[1].flags & I2C_M_RD)) { ++ if (msg[0].len > 40 || msg[1].len > 40) { ++ /* TODO: correct limits > 40 */ ++ ret = -EOPNOTSUPP; ++ } else if (msg[0].addr == af9035_af9033_config[0].i2c_addr) { ++ /* integrated demod */ ++ u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | ++ msg[0].buf[2]; ++ ret = af9035_rd_regs(d, reg, &msg[1].buf[0], ++ msg[1].len); ++ } else { ++ /* I2C */ ++ u8 buf[5 + msg[0].len]; ++ struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), ++ buf, msg[1].len, msg[1].buf }; ++ buf[0] = msg[1].len; ++ buf[1] = msg[0].addr << 1; ++ buf[2] = 0x00; /* reg addr len */ ++ buf[3] = 0x00; /* reg addr MSB */ ++ buf[4] = 0x00; /* reg addr LSB */ ++ memcpy(&buf[5], msg[0].buf, msg[0].len); ++ ret = af9035_ctrl_msg(d->udev, &req); ++ } ++ } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { ++ if (msg[0].len > 40) { ++ /* TODO: correct limits > 40 */ ++ ret = -EOPNOTSUPP; ++ } else if (msg[0].addr == af9035_af9033_config[0].i2c_addr) { ++ /* integrated demod */ ++ u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | ++ msg[0].buf[2]; ++ ret = af9035_wr_regs(d, reg, &msg[0].buf[3], ++ msg[0].len - 3); ++ } else { ++ /* I2C */ ++ u8 buf[5 + msg[0].len]; ++ struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf, ++ 0, NULL }; ++ buf[0] = msg[0].len; ++ buf[1] = msg[0].addr << 1; ++ buf[2] = 0x00; /* reg addr len */ ++ buf[3] = 0x00; /* reg addr MSB */ ++ buf[4] = 0x00; /* reg addr LSB */ ++ memcpy(&buf[5], msg[0].buf, msg[0].len); ++ ret = af9035_ctrl_msg(d->udev, &req); ++ } ++ } else { ++ /* ++ * We support only two kind of I2C transactions: ++ * 1) 1 x read + 1 x write ++ * 2) 1 x write ++ */ ++ ret = -EOPNOTSUPP; ++ } ++ ++ mutex_unlock(&d->i2c_mutex); ++ ++ if (ret < 0) ++ return ret; ++ else ++ return num; ++} ++ ++static u32 af9035_i2c_functionality(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static struct i2c_algorithm af9035_i2c_algo = { ++ .master_xfer = af9035_i2c_master_xfer, ++ .functionality = af9035_i2c_functionality, ++}; ++ ++static int af9035_init(struct dvb_usb_device *d) ++{ ++ int ret, i; ++ u16 frame_size = 87 * 188 / 4; ++ u8 packet_size = 512 / 4; ++ struct reg_val_mask tab[] = { ++ { 0x80f99d, 0x01, 0x01 }, ++ { 0x80f9a4, 0x01, 0x01 }, ++ { 0x00dd11, 0x00, 0x20 }, ++ { 0x00dd11, 0x00, 0x40 }, ++ { 0x00dd13, 0x00, 0x20 }, ++ { 0x00dd13, 0x00, 0x40 }, ++ { 0x00dd11, 0x20, 0x20 }, ++ { 0x00dd88, (frame_size >> 0) & 0xff, 0xff}, ++ { 0x00dd89, (frame_size >> 8) & 0xff, 0xff}, ++ { 0x00dd0c, packet_size, 0xff}, ++ { 0x00dd11, af9035_config.dual_mode << 6, 0x40 }, ++ { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff}, ++ { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff}, ++ { 0x00dd0d, packet_size, 0xff }, ++ { 0x80f9a3, 0x00, 0x01 }, ++ { 0x80f9cd, 0x00, 0x01 }, ++ { 0x80f99d, 0x00, 0x01 }, ++ { 0x80f9a4, 0x00, 0x01 }, ++ }; ++ ++ pr_debug("%s: USB speed=%d frame_size=%04x packet_size=%02x\n", ++ __func__, d->udev->speed, frame_size, packet_size); ++ ++ /* init endpoints */ ++ for (i = 0; i < ARRAY_SIZE(tab); i++) { ++ ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val, ++ tab[i].mask); ++ if (ret < 0) ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9035_identify_state(struct usb_device *udev, ++ struct dvb_usb_device_properties *props, ++ struct dvb_usb_device_description **desc, ++ int *cold) ++{ ++ int ret; ++ u8 wbuf[1] = { 1 }; ++ u8 rbuf[4]; ++ struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf, ++ sizeof(rbuf), rbuf }; ++ ++ ret = af9035_ctrl_msg(udev, &req); ++ if (ret < 0) ++ goto err; ++ ++ pr_debug("%s: reply=%02x %02x %02x %02x\n", __func__, ++ rbuf[0], rbuf[1], rbuf[2], rbuf[3]); ++ if (rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3]) ++ *cold = 0; ++ else ++ *cold = 1; ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9035_download_firmware(struct usb_device *udev, ++ const struct firmware *fw) ++{ ++ int ret, i, j, len; ++ u8 wbuf[1]; ++ u8 rbuf[4]; ++ struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; ++ struct usb_req req_fw_dl = { CMD_FW_DL, 0, 0, wbuf, 0, NULL }; ++ struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; ++ u8 hdr_core; ++ u16 hdr_addr, hdr_data_len, hdr_checksum; ++ #define MAX_DATA 57 ++ #define HDR_SIZE 7 ++ ++ /* ++ * Thanks to Daniel Glöckner about that info! ++ * ++ * byte 0: MCS 51 core ++ * There are two inside the AF9035 (1=Link and 2=OFDM) with separate ++ * address spaces ++ * byte 1-2: Big endian destination address ++ * byte 3-4: Big endian number of data bytes following the header ++ * byte 5-6: Big endian header checksum, apparently ignored by the chip ++ * Calculated as ~(h[0]*256+h[1]+h[2]*256+h[3]+h[4]*256) ++ */ ++ ++ for (i = fw->size; i > HDR_SIZE;) { ++ hdr_core = fw->data[fw->size - i + 0]; ++ hdr_addr = fw->data[fw->size - i + 1] << 8; ++ hdr_addr |= fw->data[fw->size - i + 2] << 0; ++ hdr_data_len = fw->data[fw->size - i + 3] << 8; ++ hdr_data_len |= fw->data[fw->size - i + 4] << 0; ++ hdr_checksum = fw->data[fw->size - i + 5] << 8; ++ hdr_checksum |= fw->data[fw->size - i + 6] << 0; ++ ++ pr_debug("%s: core=%d addr=%04x data_len=%d checksum=%04x\n", ++ __func__, hdr_core, hdr_addr, hdr_data_len, ++ hdr_checksum); ++ ++ if (((hdr_core != 1) && (hdr_core != 2)) || ++ (hdr_data_len > i)) { ++ pr_debug("%s: bad firmware\n", __func__); ++ break; ++ } ++ ++ /* download begin packet */ ++ req.cmd = CMD_FW_DL_BEGIN; ++ ret = af9035_ctrl_msg(udev, &req); ++ if (ret < 0) ++ goto err; ++ ++ /* download firmware packet(s) */ ++ for (j = HDR_SIZE + hdr_data_len; j > 0; j -= MAX_DATA) { ++ len = j; ++ if (len > MAX_DATA) ++ len = MAX_DATA; ++ req_fw_dl.wlen = len; ++ req_fw_dl.wbuf = (u8 *) &fw->data[fw->size - i + ++ HDR_SIZE + hdr_data_len - j]; ++ ret = af9035_ctrl_msg(udev, &req_fw_dl); ++ if (ret < 0) ++ goto err; ++ } ++ ++ /* download end packet */ ++ req.cmd = CMD_FW_DL_END; ++ ret = af9035_ctrl_msg(udev, &req); ++ if (ret < 0) ++ goto err; ++ ++ i -= hdr_data_len + HDR_SIZE; ++ ++ pr_debug("%s: data uploaded=%zu\n", __func__, fw->size - i); ++ } ++ ++ /* firmware loaded, request boot */ ++ req.cmd = CMD_FW_BOOT; ++ ret = af9035_ctrl_msg(udev, &req); ++ if (ret < 0) ++ goto err; ++ ++ /* ensure firmware starts */ ++ wbuf[0] = 1; ++ ret = af9035_ctrl_msg(udev, &req_fw_ver); ++ if (ret < 0) ++ goto err; ++ ++ if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { ++ info("firmware did not run"); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2], ++ rbuf[3]); ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9035_download_firmware_it9135(struct usb_device *udev, ++ const struct firmware *fw) ++{ ++ int ret, i, i_prev; ++ u8 wbuf[1]; ++ u8 rbuf[4]; ++ struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; ++ struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL }; ++ struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; ++ #define HDR_SIZE 7 ++ ++ /* ++ * There seems to be following firmware header. Meaning of bytes 0-3 ++ * is unknown. ++ * ++ * 0: 3 ++ * 1: 0, 1 ++ * 2: 0 ++ * 3: 1, 2, 3 ++ * 4: addr MSB ++ * 5: addr LSB ++ * 6: count of data bytes ? ++ */ ++ ++ for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) { ++ if (i == fw->size || ++ (fw->data[i + 0] == 0x03 && ++ (fw->data[i + 1] == 0x00 || ++ fw->data[i + 1] == 0x01) && ++ fw->data[i + 2] == 0x00)) { ++ req_fw_dl.wlen = i - i_prev; ++ req_fw_dl.wbuf = (u8 *) &fw->data[i_prev]; ++ i_prev = i; ++ ret = af9035_ctrl_msg(udev, &req_fw_dl); ++ if (ret < 0) ++ goto err; ++ ++ pr_debug("%s: data uploaded=%d\n", __func__, i); ++ } ++ } ++ ++ /* firmware loaded, request boot */ ++ req.cmd = CMD_FW_BOOT; ++ ret = af9035_ctrl_msg(udev, &req); ++ if (ret < 0) ++ goto err; ++ ++ /* ensure firmware starts */ ++ wbuf[0] = 1; ++ ret = af9035_ctrl_msg(udev, &req_fw_ver); ++ if (ret < 0) ++ goto err; ++ ++ if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { ++ info("firmware did not run"); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2], ++ rbuf[3]); ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++/* abuse that callback as there is no better one for reading eeprom */ ++static int af9035_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ int ret, i, eeprom_shift = 0; ++ u8 tmp; ++ u16 tmp16; ++ ++ /* check if there is dual tuners */ ++ ret = af9035_rd_reg(d, EEPROM_DUAL_MODE, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ af9035_config.dual_mode = tmp; ++ pr_debug("%s: dual mode=%d\n", __func__, af9035_config.dual_mode); ++ ++ for (i = 0; i < af9035_properties[0].num_adapters; i++) { ++ /* tuner */ ++ ret = af9035_rd_reg(d, EEPROM_1_TUNER_ID + eeprom_shift, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ af9035_af9033_config[i].tuner = tmp; ++ pr_debug("%s: [%d]tuner=%02x\n", __func__, i, tmp); ++ ++ switch (tmp) { ++ case AF9033_TUNER_TUA9001: ++ case AF9033_TUNER_FC0011: ++ case AF9033_TUNER_MXL5007T: ++ case AF9033_TUNER_TDA18218: ++ af9035_af9033_config[i].spec_inv = 1; ++ break; ++ default: ++ af9035_config.hw_not_supported = true; ++ warn("tuner ID=%02x not supported, please report!", ++ tmp); ++ }; ++ ++ /* tuner IF frequency */ ++ ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_L + eeprom_shift, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ tmp16 = tmp; ++ ++ ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_H + eeprom_shift, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ tmp16 |= tmp << 8; ++ ++ pr_debug("%s: [%d]IF=%d\n", __func__, i, tmp16); ++ ++ eeprom_shift = 0x10; /* shift for the 2nd tuner params */ ++ } ++ ++ /* get demod clock */ ++ ret = af9035_rd_reg(d, 0x00d800, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ tmp = (tmp >> 0) & 0x0f; ++ ++ for (i = 0; i < af9035_properties[0].num_adapters; i++) ++ af9035_af9033_config[i].clock = clock_lut[tmp]; ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++/* abuse that callback as there is no better one for reading eeprom */ ++static int af9035_read_mac_address_it9135(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ int ret, i; ++ u8 tmp; ++ ++ af9035_config.dual_mode = 0; ++ ++ /* get demod clock */ ++ ret = af9035_rd_reg(d, 0x00d800, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ tmp = (tmp >> 0) & 0x0f; ++ ++ for (i = 0; i < af9035_properties[0].num_adapters; i++) ++ af9035_af9033_config[i].clock = clock_lut_it9135[tmp]; ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d, ++ int cmd, int arg) ++{ ++ int ret; ++ ++ switch (cmd) { ++ case FC0011_FE_CALLBACK_POWER: ++ /* Tuner enable */ ++ ret = af9035_wr_reg_mask(d, 0xd8eb, 1, 1); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg_mask(d, 0xd8ec, 1, 1); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg_mask(d, 0xd8ed, 1, 1); ++ if (ret < 0) ++ goto err; ++ ++ /* LED */ ++ ret = af9035_wr_reg_mask(d, 0xd8d0, 1, 1); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg_mask(d, 0xd8d1, 1, 1); ++ if (ret < 0) ++ goto err; ++ ++ usleep_range(10000, 50000); ++ break; ++ case FC0011_FE_CALLBACK_RESET: ++ ret = af9035_wr_reg(d, 0xd8e9, 1); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg(d, 0xd8e8, 1); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg(d, 0xd8e7, 1); ++ if (ret < 0) ++ goto err; ++ ++ usleep_range(10000, 20000); ++ ++ ret = af9035_wr_reg(d, 0xd8e7, 0); ++ if (ret < 0) ++ goto err; ++ ++ usleep_range(10000, 20000); ++ break; ++ default: ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) ++{ ++ switch (af9035_af9033_config[0].tuner) { ++ case AF9033_TUNER_FC0011: ++ return af9035_fc0011_tuner_callback(d, cmd, arg); ++ default: ++ break; ++ } ++ ++ return -ENODEV; ++} ++ ++static int af9035_frontend_callback(void *adapter_priv, int component, ++ int cmd, int arg) ++{ ++ struct i2c_adapter *adap = adapter_priv; ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ ++ switch (component) { ++ case DVB_FRONTEND_COMPONENT_TUNER: ++ return af9035_tuner_callback(d, cmd, arg); ++ default: ++ break; ++ } ++ ++ return -EINVAL; ++} ++ ++static int af9035_frontend_attach(struct dvb_usb_adapter *adap) ++{ ++ int ret; ++ ++ if (af9035_config.hw_not_supported) { ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ if (adap->id == 0) { ++ ret = af9035_wr_reg(adap->dev, 0x00417f, ++ af9035_af9033_config[1].i2c_addr); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg(adap->dev, 0x00d81a, ++ af9035_config.dual_mode); ++ if (ret < 0) ++ goto err; ++ } ++ ++ /* attach demodulator */ ++ adap->fe_adap[0].fe = dvb_attach(af9033_attach, ++ &af9035_af9033_config[adap->id], &adap->dev->i2c_adap); ++ if (adap->fe_adap[0].fe == NULL) { ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ /* disable I2C-gate */ ++ adap->fe_adap[0].fe->ops.i2c_gate_ctrl = NULL; ++ adap->fe_adap[0].fe->callback = af9035_frontend_callback; ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static struct tua9001_config af9035_tua9001_config = { ++ .i2c_addr = 0x60, ++}; ++ ++static const struct fc0011_config af9035_fc0011_config = { ++ .i2c_address = 0x60, ++}; ++ ++static struct mxl5007t_config af9035_mxl5007t_config = { ++ .xtal_freq_hz = MxL_XTAL_24_MHZ, ++ .if_freq_hz = MxL_IF_4_57_MHZ, ++ .invert_if = 0, ++ .loop_thru_enable = 0, ++ .clk_out_enable = 0, ++ .clk_out_amp = MxL_CLKOUT_AMP_0_94V, ++}; ++ ++static struct tda18218_config af9035_tda18218_config = { ++ .i2c_address = 0x60, ++ .i2c_wr_max = 21, ++}; ++ ++static int af9035_tuner_attach(struct dvb_usb_adapter *adap) ++{ ++ int ret; ++ struct dvb_frontend *fe; ++ ++ switch (af9035_af9033_config[adap->id].tuner) { ++ case AF9033_TUNER_TUA9001: ++ /* AF9035 gpiot3 = TUA9001 RESETN ++ AF9035 gpiot2 = TUA9001 RXEN */ ++ ++ /* configure gpiot2 and gpiot2 as output */ ++ ret = af9035_wr_reg_mask(adap->dev, 0x00d8ec, 0x01, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg_mask(adap->dev, 0x00d8ed, 0x01, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg_mask(adap->dev, 0x00d8e8, 0x01, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg_mask(adap->dev, 0x00d8e9, 0x01, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ /* reset tuner */ ++ ret = af9035_wr_reg_mask(adap->dev, 0x00d8e7, 0x00, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ usleep_range(2000, 20000); ++ ++ ret = af9035_wr_reg_mask(adap->dev, 0x00d8e7, 0x01, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ /* activate tuner RX */ ++ /* TODO: use callback for TUA9001 RXEN */ ++ ret = af9035_wr_reg_mask(adap->dev, 0x00d8eb, 0x01, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ /* attach tuner */ ++ fe = dvb_attach(tua9001_attach, adap->fe_adap[0].fe, ++ &adap->dev->i2c_adap, &af9035_tua9001_config); ++ break; ++ case AF9033_TUNER_FC0011: ++ fe = dvb_attach(fc0011_attach, adap->fe_adap[0].fe, ++ &adap->dev->i2c_adap, &af9035_fc0011_config); ++ break; ++ case AF9033_TUNER_MXL5007T: ++ ret = af9035_wr_reg(adap->dev, 0x00d8e0, 1); ++ if (ret < 0) ++ goto err; ++ ret = af9035_wr_reg(adap->dev, 0x00d8e1, 1); ++ if (ret < 0) ++ goto err; ++ ret = af9035_wr_reg(adap->dev, 0x00d8df, 0); ++ if (ret < 0) ++ goto err; ++ ++ msleep(30); ++ ++ ret = af9035_wr_reg(adap->dev, 0x00d8df, 1); ++ if (ret < 0) ++ goto err; ++ ++ msleep(300); ++ ++ ret = af9035_wr_reg(adap->dev, 0x00d8c0, 1); ++ if (ret < 0) ++ goto err; ++ ret = af9035_wr_reg(adap->dev, 0x00d8c1, 1); ++ if (ret < 0) ++ goto err; ++ ret = af9035_wr_reg(adap->dev, 0x00d8bf, 0); ++ if (ret < 0) ++ goto err; ++ ret = af9035_wr_reg(adap->dev, 0x00d8b4, 1); ++ if (ret < 0) ++ goto err; ++ ret = af9035_wr_reg(adap->dev, 0x00d8b5, 1); ++ if (ret < 0) ++ goto err; ++ ret = af9035_wr_reg(adap->dev, 0x00d8b3, 1); ++ if (ret < 0) ++ goto err; ++ ++ /* attach tuner */ ++ fe = dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe, ++ &adap->dev->i2c_adap, 0x60, &af9035_mxl5007t_config); ++ break; ++ case AF9033_TUNER_TDA18218: ++ /* attach tuner */ ++ fe = dvb_attach(tda18218_attach, adap->fe_adap[0].fe, ++ &adap->dev->i2c_adap, &af9035_tda18218_config); ++ break; ++ default: ++ fe = NULL; ++ } ++ ++ if (fe == NULL) { ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++enum af9035_id_entry { ++ AF9035_15A4_9035, ++ AF9035_15A4_1001, ++ AF9035_0CCD_0093, ++ AF9035_07CA_A835, ++ AF9035_07CA_B835, ++ AF9035_07CA_1867, ++ AF9035_07CA_A867, ++ AF9035_07CA_0825, ++}; ++ ++static struct usb_device_id af9035_id[] = { ++ [AF9035_15A4_9035] = { ++ USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035)}, ++ [AF9035_15A4_1001] = { ++ USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_2)}, ++ [AF9035_0CCD_0093] = { ++ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK)}, ++ [AF9035_07CA_A835] = { ++ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835)}, ++ [AF9035_07CA_B835] = { ++ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835)}, ++ [AF9035_07CA_1867] = { ++ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867)}, ++ [AF9035_07CA_A867] = { ++ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867)}, ++ [AF9035_07CA_0825] = { ++ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR)}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(usb, af9035_id); ++ ++static struct dvb_usb_device_properties af9035_properties[] = { ++ { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .download_firmware = af9035_download_firmware, ++ .firmware = "dvb-usb-af9035-02.fw", ++ .no_reconnect = 1, ++ ++ .num_adapters = 1, ++ .adapter = { ++ { ++ .num_frontends = 1, ++ .fe = { ++ { ++ .frontend_attach = af9035_frontend_attach, ++ .tuner_attach = af9035_tuner_attach, ++ .stream = { ++ .type = USB_BULK, ++ .count = 6, ++ .endpoint = 0x84, ++ .u = { ++ .bulk = { ++ .buffersize = (87 * 188), ++ } ++ } ++ } ++ } ++ } ++ } ++ }, ++ ++ .identify_state = af9035_identify_state, ++ .read_mac_address = af9035_read_mac_address, ++ ++ .i2c_algo = &af9035_i2c_algo, ++ ++ .num_device_descs = 5, ++ .devices = { ++ { ++ .name = "Afatech AF9035 reference design", ++ .cold_ids = { ++ &af9035_id[AF9035_15A4_9035], ++ &af9035_id[AF9035_15A4_1001], ++ }, ++ }, { ++ .name = "TerraTec Cinergy T Stick", ++ .cold_ids = { ++ &af9035_id[AF9035_0CCD_0093], ++ }, ++ }, { ++ .name = "AVerMedia AVerTV Volar HD/PRO (A835)", ++ .cold_ids = { ++ &af9035_id[AF9035_07CA_A835], ++ &af9035_id[AF9035_07CA_B835], ++ }, ++ }, { ++ .name = "AVerMedia HD Volar (A867)", ++ .cold_ids = { ++ &af9035_id[AF9035_07CA_1867], ++ &af9035_id[AF9035_07CA_A867], ++ }, ++ }, { ++ .name = "AVerMedia Twinstar (A825)", ++ .cold_ids = { ++ &af9035_id[AF9035_07CA_0825], ++ }, ++ }, ++ } ++ }, ++ { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .download_firmware = af9035_download_firmware_it9135, ++ .firmware = "dvb-usb-it9135-01.fw", ++ .no_reconnect = 1, ++ ++ .num_adapters = 1, ++ .adapter = { ++ { ++ .num_frontends = 1, ++ .fe = { ++ { ++ .frontend_attach = af9035_frontend_attach, ++ .tuner_attach = af9035_tuner_attach, ++ .stream = { ++ .type = USB_BULK, ++ .count = 6, ++ .endpoint = 0x84, ++ .u = { ++ .bulk = { ++ .buffersize = (87 * 188), ++ } ++ } ++ } ++ } ++ } ++ } ++ }, ++ ++ .identify_state = af9035_identify_state, ++ .read_mac_address = af9035_read_mac_address_it9135, ++ ++ .i2c_algo = &af9035_i2c_algo, ++ ++ .num_device_descs = 0, /* disabled as no support for IT9135 */ ++ .devices = { ++ { ++ .name = "ITE Tech. IT9135 reference design", ++ }, ++ } ++ }, ++}; ++ ++static int af9035_usb_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ int ret, i; ++ struct dvb_usb_device *d = NULL; ++ struct usb_device *udev; ++ bool found; ++ ++ pr_debug("%s: interface=%d\n", __func__, ++ intf->cur_altsetting->desc.bInterfaceNumber); ++ ++ /* interface 0 is used by DVB-T receiver and ++ interface 1 is for remote controller (HID) */ ++ if (intf->cur_altsetting->desc.bInterfaceNumber != 0) ++ return 0; ++ ++ /* Dynamic USB ID support. Replaces first device ID with current one. */ ++ udev = interface_to_usbdev(intf); ++ ++ for (i = 0, found = false; i < ARRAY_SIZE(af9035_id) - 1; i++) { ++ if (af9035_id[i].idVendor == ++ le16_to_cpu(udev->descriptor.idVendor) && ++ af9035_id[i].idProduct == ++ le16_to_cpu(udev->descriptor.idProduct)) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) { ++ pr_debug("%s: using dynamic ID %04x:%04x\n", __func__, ++ le16_to_cpu(udev->descriptor.idVendor), ++ le16_to_cpu(udev->descriptor.idProduct)); ++ af9035_properties[0].devices[0].cold_ids[0]->idVendor = ++ le16_to_cpu(udev->descriptor.idVendor); ++ af9035_properties[0].devices[0].cold_ids[0]->idProduct = ++ le16_to_cpu(udev->descriptor.idProduct); ++ } ++ ++ ++ for (i = 0; i < af9035_properties_count; i++) { ++ ret = dvb_usb_device_init(intf, &af9035_properties[i], ++ THIS_MODULE, &d, adapter_nr); ++ ++ if (ret == -ENODEV) ++ continue; ++ else ++ break; ++ } ++ ++ if (ret < 0) ++ goto err; ++ ++ if (d) { ++ ret = af9035_init(d); ++ if (ret < 0) ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++/* usb specific object needed to register this driver with the usb subsystem */ ++static struct usb_driver af9035_usb_driver = { ++ .name = "dvb_usb_af9035", ++ .probe = af9035_usb_probe, ++ .disconnect = dvb_usb_device_exit, ++ .id_table = af9035_id, ++}; ++ ++module_usb_driver(af9035_usb_driver); ++ ++MODULE_AUTHOR("Antti Palosaari "); ++MODULE_DESCRIPTION("Afatech AF9035 driver"); ++MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9035.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9035.h +@@ -0,0 +1,120 @@ ++/* ++ * Afatech AF9035 DVB USB driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * Copyright (C) 2012 Antti Palosaari ++ * ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef AF9035_H ++#define AF9035_H ++ ++/* prefix for dvb-usb log writings */ ++#define DVB_USB_LOG_PREFIX "af9035" ++ ++#include "dvb-usb.h" ++ ++struct reg_val { ++ u32 reg; ++ u8 val; ++}; ++ ++struct reg_val_mask { ++ u32 reg; ++ u8 val; ++ u8 mask; ++}; ++ ++struct usb_req { ++ u8 cmd; ++ u8 mbox; ++ u8 wlen; ++ u8 *wbuf; ++ u8 rlen; ++ u8 *rbuf; ++}; ++ ++struct config { ++ bool dual_mode; ++ bool hw_not_supported; ++}; ++ ++struct fw_segment { ++#define SEGMENT_FW_DL 0 ++#define SEGMENT_ROM_COPY 1 ++#define SEGMENT_DIRECT_CMD 2 ++ u8 type; ++ u32 len; ++}; ++ ++struct fw_header { ++#define SEGMENT_MAX_COUNT 6 ++ u8 segment_count; ++ struct fw_segment segment[SEGMENT_MAX_COUNT]; ++}; ++ ++u32 clock_lut[] = { ++ 20480000, /* FPGA */ ++ 16384000, /* 16.38 MHz */ ++ 20480000, /* 20.48 MHz */ ++ 36000000, /* 36.00 MHz */ ++ 30000000, /* 30.00 MHz */ ++ 26000000, /* 26.00 MHz */ ++ 28000000, /* 28.00 MHz */ ++ 32000000, /* 32.00 MHz */ ++ 34000000, /* 34.00 MHz */ ++ 24000000, /* 24.00 MHz */ ++ 22000000, /* 22.00 MHz */ ++ 12000000, /* 12.00 MHz */ ++}; ++ ++u32 clock_lut_it9135[] = { ++ 12000000, /* 12.00 MHz */ ++ 20480000, /* 20.48 MHz */ ++ 36000000, /* 36.00 MHz */ ++ 30000000, /* 30.00 MHz */ ++ 26000000, /* 26.00 MHz */ ++ 28000000, /* 28.00 MHz */ ++ 32000000, /* 32.00 MHz */ ++ 34000000, /* 34.00 MHz */ ++ 24000000, /* 24.00 MHz */ ++ 22000000, /* 22.00 MHz */ ++}; ++ ++/* EEPROM locations */ ++#define EEPROM_IR_MODE 0x430d ++#define EEPROM_DUAL_MODE 0x4326 ++#define EEPROM_IR_TYPE 0x4329 ++#define EEPROM_1_IFFREQ_L 0x432d ++#define EEPROM_1_IFFREQ_H 0x432e ++#define EEPROM_1_TUNER_ID 0x4331 ++#define EEPROM_2_IFFREQ_L 0x433d ++#define EEPROM_2_IFFREQ_H 0x433e ++#define EEPROM_2_TUNER_ID 0x4341 ++ ++/* USB commands */ ++#define CMD_MEM_RD 0x00 ++#define CMD_MEM_WR 0x01 ++#define CMD_I2C_RD 0x02 ++#define CMD_I2C_WR 0x03 ++#define CMD_FW_DL 0x21 ++#define CMD_FW_QUERYINFO 0x22 ++#define CMD_FW_BOOT 0x23 ++#define CMD_FW_DL_BEGIN 0x24 ++#define CMD_FW_DL_END 0x25 ++#define CMD_FW_SCATTER_WR 0x29 ++ ++#endif +Index: linux-3.3.x86_64/MAINTAINERS +=================================================================== +--- linux-3.3.x86_64.orig/MAINTAINERS ++++ linux-3.3.x86_64/MAINTAINERS +@@ -2659,6 +2659,13 @@ S: Maintained + F: Documentation/hwmon/f71805f + F: drivers/hwmon/f71805f.c + ++FC0011 TUNER DRIVER ++M: Michael Buesch ++L: linux-media@vger.kernel.org ++S: Maintained ++F: drivers/media/common/tuners/fc0011.h ++F: drivers/media/common/tuners/fc0011.c ++ + FANOTIFY + M: Eric Paris + S: Maintained +Index: linux-3.3.x86_64/drivers/media/common/tuners/fc0011.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/common/tuners/fc0011.c +@@ -0,0 +1,524 @@ ++/* ++ * Fitipower FC0011 tuner driver ++ * ++ * Copyright (C) 2012 Michael Buesch ++ * ++ * Derived from FC0012 tuner driver: ++ * Copyright (C) 2012 Hans-Frieder Vogt ++ * ++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include "fc0011.h" ++ ++ ++/* Tuner registers */ ++enum { ++ FC11_REG_0, ++ FC11_REG_FA, /* FA */ ++ FC11_REG_FP, /* FP */ ++ FC11_REG_XINHI, /* XIN high 8 bit */ ++ FC11_REG_XINLO, /* XIN low 8 bit */ ++ FC11_REG_VCO, /* VCO */ ++ FC11_REG_VCOSEL, /* VCO select */ ++ FC11_REG_7, /* Unknown tuner reg 7 */ ++ FC11_REG_8, /* Unknown tuner reg 8 */ ++ FC11_REG_9, ++ FC11_REG_10, /* Unknown tuner reg 10 */ ++ FC11_REG_11, /* Unknown tuner reg 11 */ ++ FC11_REG_12, ++ FC11_REG_RCCAL, /* RC calibrate */ ++ FC11_REG_VCOCAL, /* VCO calibrate */ ++ FC11_REG_15, ++ FC11_REG_16, /* Unknown tuner reg 16 */ ++ FC11_REG_17, ++ ++ FC11_NR_REGS, /* Number of registers */ ++}; ++ ++enum FC11_REG_VCOSEL_bits { ++ FC11_VCOSEL_2 = 0x08, /* VCO select 2 */ ++ FC11_VCOSEL_1 = 0x10, /* VCO select 1 */ ++ FC11_VCOSEL_CLKOUT = 0x20, /* Fix clock out */ ++ FC11_VCOSEL_BW7M = 0x40, /* 7MHz bw */ ++ FC11_VCOSEL_BW6M = 0x80, /* 6MHz bw */ ++}; ++ ++enum FC11_REG_RCCAL_bits { ++ FC11_RCCAL_FORCE = 0x10, /* force */ ++}; ++ ++enum FC11_REG_VCOCAL_bits { ++ FC11_VCOCAL_RUN = 0, /* VCO calibration run */ ++ FC11_VCOCAL_VALUEMASK = 0x3F, /* VCO calibration value mask */ ++ FC11_VCOCAL_OK = 0x40, /* VCO calibration Ok */ ++ FC11_VCOCAL_RESET = 0x80, /* VCO calibration reset */ ++}; ++ ++ ++struct fc0011_priv { ++ struct i2c_adapter *i2c; ++ u8 addr; ++ ++ u32 frequency; ++ u32 bandwidth; ++}; ++ ++ ++static int fc0011_writereg(struct fc0011_priv *priv, u8 reg, u8 val) ++{ ++ u8 buf[2] = { reg, val }; ++ struct i2c_msg msg = { .addr = priv->addr, ++ .flags = 0, .buf = buf, .len = 2 }; ++ ++ if (i2c_transfer(priv->i2c, &msg, 1) != 1) { ++ dev_err(&priv->i2c->dev, ++ "I2C write reg failed, reg: %02x, val: %02x\n", ++ reg, val); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int fc0011_readreg(struct fc0011_priv *priv, u8 reg, u8 *val) ++{ ++ u8 dummy; ++ struct i2c_msg msg[2] = { ++ { .addr = priv->addr, ++ .flags = 0, .buf = ®, .len = 1 }, ++ { .addr = priv->addr, ++ .flags = I2C_M_RD, .buf = val ? : &dummy, .len = 1 }, ++ }; ++ ++ if (i2c_transfer(priv->i2c, msg, 2) != 2) { ++ dev_err(&priv->i2c->dev, ++ "I2C read failed, reg: %02x\n", reg); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int fc0011_release(struct dvb_frontend *fe) ++{ ++ kfree(fe->tuner_priv); ++ fe->tuner_priv = NULL; ++ ++ return 0; ++} ++ ++static int fc0011_init(struct dvb_frontend *fe) ++{ ++ struct fc0011_priv *priv = fe->tuner_priv; ++ int err; ++ ++ if (WARN_ON(!fe->callback)) ++ return -EINVAL; ++ ++ err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, ++ FC0011_FE_CALLBACK_POWER, priv->addr); ++ if (err) { ++ dev_err(&priv->i2c->dev, "Power-on callback failed\n"); ++ return err; ++ } ++ err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, ++ FC0011_FE_CALLBACK_RESET, priv->addr); ++ if (err) { ++ dev_err(&priv->i2c->dev, "Reset callback failed\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++/* Initiate VCO calibration */ ++static int fc0011_vcocal_trigger(struct fc0011_priv *priv) ++{ ++ int err; ++ ++ err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RESET); ++ if (err) ++ return err; ++ err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN); ++ if (err) ++ return err; ++ ++ return 0; ++} ++ ++/* Read VCO calibration value */ ++static int fc0011_vcocal_read(struct fc0011_priv *priv, u8 *value) ++{ ++ int err; ++ ++ err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN); ++ if (err) ++ return err; ++ usleep_range(10000, 20000); ++ err = fc0011_readreg(priv, FC11_REG_VCOCAL, value); ++ if (err) ++ return err; ++ ++ return 0; ++} ++ ++static int fc0011_set_params(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ struct fc0011_priv *priv = fe->tuner_priv; ++ int err; ++ unsigned int i, vco_retries; ++ u32 freq = p->frequency / 1000; ++ u32 bandwidth = p->bandwidth_hz / 1000; ++ u32 fvco, xin, xdiv, xdivr; ++ u16 frac; ++ u8 fa, fp, vco_sel, vco_cal; ++ u8 regs[FC11_NR_REGS] = { }; ++ ++ regs[FC11_REG_7] = 0x0F; ++ regs[FC11_REG_8] = 0x3E; ++ regs[FC11_REG_10] = 0xB8; ++ regs[FC11_REG_11] = 0x80; ++ regs[FC11_REG_RCCAL] = 0x04; ++ err = fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]); ++ err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]); ++ err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]); ++ err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]); ++ err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]); ++ if (err) ++ return -EIO; ++ ++ /* Set VCO freq and VCO div */ ++ if (freq < 54000) { ++ fvco = freq * 64; ++ regs[FC11_REG_VCO] = 0x82; ++ } else if (freq < 108000) { ++ fvco = freq * 32; ++ regs[FC11_REG_VCO] = 0x42; ++ } else if (freq < 216000) { ++ fvco = freq * 16; ++ regs[FC11_REG_VCO] = 0x22; ++ } else if (freq < 432000) { ++ fvco = freq * 8; ++ regs[FC11_REG_VCO] = 0x12; ++ } else { ++ fvco = freq * 4; ++ regs[FC11_REG_VCO] = 0x0A; ++ } ++ ++ /* Calc XIN. The PLL reference frequency is 18 MHz. */ ++ xdiv = fvco / 18000; ++ frac = fvco - xdiv * 18000; ++ frac = (frac << 15) / 18000; ++ if (frac >= 16384) ++ frac += 32786; ++ if (!frac) ++ xin = 0; ++ else if (frac < 511) ++ xin = 512; ++ else if (frac < 65026) ++ xin = frac; ++ else ++ xin = 65024; ++ regs[FC11_REG_XINHI] = xin >> 8; ++ regs[FC11_REG_XINLO] = xin; ++ ++ /* Calc FP and FA */ ++ xdivr = xdiv; ++ if (fvco - xdiv * 18000 >= 9000) ++ xdivr += 1; /* round */ ++ fp = xdivr / 8; ++ fa = xdivr - fp * 8; ++ if (fa < 2) { ++ fp -= 1; ++ fa += 8; ++ } ++ if (fp > 0x1F) { ++ fp &= 0x1F; ++ fa &= 0xF; ++ } ++ if (fa >= fp) { ++ dev_warn(&priv->i2c->dev, ++ "fa %02X >= fp %02X, but trying to continue\n", ++ (unsigned int)(u8)fa, (unsigned int)(u8)fp); ++ } ++ regs[FC11_REG_FA] = fa; ++ regs[FC11_REG_FP] = fp; ++ ++ /* Select bandwidth */ ++ switch (bandwidth) { ++ case 8000: ++ break; ++ case 7000: ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW7M; ++ break; ++ default: ++ dev_warn(&priv->i2c->dev, "Unsupported bandwidth %u kHz. " ++ "Using 6000 kHz.\n", ++ bandwidth); ++ bandwidth = 6000; ++ /* fallthrough */ ++ case 6000: ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW6M; ++ break; ++ } ++ ++ /* Pre VCO select */ ++ if (fvco < 2320000) { ++ vco_sel = 0; ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ } else if (fvco < 3080000) { ++ vco_sel = 1; ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1; ++ } else { ++ vco_sel = 2; ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2; ++ } ++ ++ /* Fix for low freqs */ ++ if (freq < 45000) { ++ regs[FC11_REG_FA] = 0x6; ++ regs[FC11_REG_FP] = 0x11; ++ } ++ ++ /* Clock out fix */ ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_CLKOUT; ++ ++ /* Write the cached registers */ ++ for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++) { ++ err = fc0011_writereg(priv, i, regs[i]); ++ if (err) ++ return err; ++ } ++ ++ /* VCO calibration */ ++ err = fc0011_vcocal_trigger(priv); ++ if (err) ++ return err; ++ err = fc0011_vcocal_read(priv, &vco_cal); ++ if (err) ++ return err; ++ vco_retries = 0; ++ while (!(vco_cal & FC11_VCOCAL_OK) && vco_retries < 3) { ++ /* Reset the tuner and try again */ ++ err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, ++ FC0011_FE_CALLBACK_RESET, priv->addr); ++ if (err) { ++ dev_err(&priv->i2c->dev, "Failed to reset tuner\n"); ++ return err; ++ } ++ /* Reinit tuner config */ ++ err = 0; ++ for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++) ++ err |= fc0011_writereg(priv, i, regs[i]); ++ err |= fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]); ++ err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]); ++ err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]); ++ err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]); ++ err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]); ++ if (err) ++ return -EIO; ++ /* VCO calibration */ ++ err = fc0011_vcocal_trigger(priv); ++ if (err) ++ return err; ++ err = fc0011_vcocal_read(priv, &vco_cal); ++ if (err) ++ return err; ++ vco_retries++; ++ } ++ if (!(vco_cal & FC11_VCOCAL_OK)) { ++ dev_err(&priv->i2c->dev, ++ "Failed to read VCO calibration value (got %02X)\n", ++ (unsigned int)vco_cal); ++ return -EIO; ++ } ++ vco_cal &= FC11_VCOCAL_VALUEMASK; ++ ++ switch (vco_sel) { ++ case 0: ++ if (vco_cal < 8) { ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1; ++ err = fc0011_writereg(priv, FC11_REG_VCOSEL, ++ regs[FC11_REG_VCOSEL]); ++ if (err) ++ return err; ++ err = fc0011_vcocal_trigger(priv); ++ if (err) ++ return err; ++ } else { ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ err = fc0011_writereg(priv, FC11_REG_VCOSEL, ++ regs[FC11_REG_VCOSEL]); ++ if (err) ++ return err; ++ } ++ break; ++ case 1: ++ if (vco_cal < 5) { ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2; ++ err = fc0011_writereg(priv, FC11_REG_VCOSEL, ++ regs[FC11_REG_VCOSEL]); ++ if (err) ++ return err; ++ err = fc0011_vcocal_trigger(priv); ++ if (err) ++ return err; ++ } else if (vco_cal <= 48) { ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1; ++ err = fc0011_writereg(priv, FC11_REG_VCOSEL, ++ regs[FC11_REG_VCOSEL]); ++ if (err) ++ return err; ++ } else { ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ err = fc0011_writereg(priv, FC11_REG_VCOSEL, ++ regs[FC11_REG_VCOSEL]); ++ if (err) ++ return err; ++ err = fc0011_vcocal_trigger(priv); ++ if (err) ++ return err; ++ } ++ break; ++ case 2: ++ if (vco_cal > 53) { ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1; ++ err = fc0011_writereg(priv, FC11_REG_VCOSEL, ++ regs[FC11_REG_VCOSEL]); ++ if (err) ++ return err; ++ err = fc0011_vcocal_trigger(priv); ++ if (err) ++ return err; ++ } else { ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2; ++ err = fc0011_writereg(priv, FC11_REG_VCOSEL, ++ regs[FC11_REG_VCOSEL]); ++ if (err) ++ return err; ++ } ++ break; ++ } ++ err = fc0011_vcocal_read(priv, NULL); ++ if (err) ++ return err; ++ usleep_range(10000, 50000); ++ ++ err = fc0011_readreg(priv, FC11_REG_RCCAL, ®s[FC11_REG_RCCAL]); ++ if (err) ++ return err; ++ regs[FC11_REG_RCCAL] |= FC11_RCCAL_FORCE; ++ err = fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]); ++ if (err) ++ return err; ++ err = fc0011_writereg(priv, FC11_REG_16, 0xB); ++ if (err) ++ return err; ++ ++ dev_dbg(&priv->i2c->dev, "Tuned to " ++ "fa=%02X fp=%02X xin=%02X%02X vco=%02X vcosel=%02X " ++ "vcocal=%02X(%u) bw=%u\n", ++ (unsigned int)regs[FC11_REG_FA], ++ (unsigned int)regs[FC11_REG_FP], ++ (unsigned int)regs[FC11_REG_XINHI], ++ (unsigned int)regs[FC11_REG_XINLO], ++ (unsigned int)regs[FC11_REG_VCO], ++ (unsigned int)regs[FC11_REG_VCOSEL], ++ (unsigned int)vco_cal, vco_retries, ++ (unsigned int)bandwidth); ++ ++ priv->frequency = p->frequency; ++ priv->bandwidth = p->bandwidth_hz; ++ ++ return 0; ++} ++ ++static int fc0011_get_frequency(struct dvb_frontend *fe, u32 *frequency) ++{ ++ struct fc0011_priv *priv = fe->tuner_priv; ++ ++ *frequency = priv->frequency; ++ ++ return 0; ++} ++ ++static int fc0011_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) ++{ ++ *frequency = 0; ++ ++ return 0; ++} ++ ++static int fc0011_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) ++{ ++ struct fc0011_priv *priv = fe->tuner_priv; ++ ++ *bandwidth = priv->bandwidth; ++ ++ return 0; ++} ++ ++static const struct dvb_tuner_ops fc0011_tuner_ops = { ++ .info = { ++ .name = "Fitipower FC0011", ++ ++ .frequency_min = 45000000, ++ .frequency_max = 1000000000, ++ }, ++ ++ .release = fc0011_release, ++ .init = fc0011_init, ++ ++ .set_params = fc0011_set_params, ++ ++ .get_frequency = fc0011_get_frequency, ++ .get_if_frequency = fc0011_get_if_frequency, ++ .get_bandwidth = fc0011_get_bandwidth, ++}; ++ ++struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, ++ const struct fc0011_config *config) ++{ ++ struct fc0011_priv *priv; ++ ++ priv = kzalloc(sizeof(struct fc0011_priv), GFP_KERNEL); ++ if (!priv) ++ return NULL; ++ ++ priv->i2c = i2c; ++ priv->addr = config->i2c_address; ++ ++ fe->tuner_priv = priv; ++ fe->ops.tuner_ops = fc0011_tuner_ops; ++ ++ dev_info(&priv->i2c->dev, "Fitipower FC0011 tuner attached\n"); ++ ++ return fe; ++} ++EXPORT_SYMBOL(fc0011_attach); ++ ++MODULE_DESCRIPTION("Fitipower FC0011 silicon tuner driver"); ++MODULE_AUTHOR("Michael Buesch "); ++MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/common/tuners/fc0011.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/common/tuners/fc0011.h +@@ -0,0 +1,41 @@ ++#ifndef LINUX_FC0011_H_ ++#define LINUX_FC0011_H_ ++ ++#include "dvb_frontend.h" ++ ++ ++/** struct fc0011_config - fc0011 hardware config ++ * ++ * @i2c_address: I2C bus address. ++ */ ++struct fc0011_config { ++ u8 i2c_address; ++}; ++ ++/** enum fc0011_fe_callback_commands - Frontend callbacks ++ * ++ * @FC0011_FE_CALLBACK_POWER: Power on tuner hardware. ++ * @FC0011_FE_CALLBACK_RESET: Request a tuner reset. ++ */ ++enum fc0011_fe_callback_commands { ++ FC0011_FE_CALLBACK_POWER, ++ FC0011_FE_CALLBACK_RESET, ++}; ++ ++#if defined(CONFIG_MEDIA_TUNER_FC0011) ||\ ++ defined(CONFIG_MEDIA_TUNER_FC0011_MODULE) ++struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, ++ const struct fc0011_config *config); ++#else ++static inline ++struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, ++ const struct fc0011_config *config) ++{ ++ dev_err(&i2c->dev, "fc0011 driver disabled in Kconfig\n"); ++ return NULL; ++} ++#endif ++ ++#endif /* LINUX_FC0011_H_ */ diff --git a/kernel.spec b/kernel.spec index 644b33d12..44111ec0e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -629,9 +629,8 @@ Patch1900: linux-2.6-intel-iommu-igfx.patch Patch2802: linux-2.6-silence-acpi-blacklist.patch # media patches -Patch2899: linux-2.6-v4l-dvb-fixes.patch -Patch2900: linux-2.6-v4l-dvb-update.patch -Patch2901: linux-2.6-v4l-dvb-experimental.patch +Patch2900: add-poll-requested-events.patch +Patch2901: drivers-media-update.patch # fs fixes @@ -1248,11 +1247,10 @@ ApplyPatch linux-2.6-intel-iommu-igfx.patch ApplyPatch linux-2.6-silence-acpi-blacklist.patch ApplyPatch quite-apm.patch -# V4L/DVB updates/fixes/experimental drivers +# Media (V4L/DVB/IR) updates/fixes/experimental drivers # apply if non-empty -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 add-poll-requested-events.patch +ApplyOptionalPatch drivers-media-update.patch # Patches headed upstream @@ -1971,6 +1969,9 @@ fi # and build. %changelog +* Tue Apr 10 2012 Mauro Carvalho Chehab 3.3.1-5 +- Backport dvb-core and a few driver fixes from media tree (rhbz808871) + * Tue Apr 10 2012 Josh Boyer - Apply upstream patch to add USB device 13d3:3375 (rhbz 811087) - Backport fixes for correct register constraints in cmpxchg.h (rhbz 809014) diff --git a/linux-2.6-v4l-dvb-experimental.patch b/linux-2.6-v4l-dvb-experimental.patch deleted file mode 100644 index e69de29bb..000000000 diff --git a/linux-2.6-v4l-dvb-fixes.patch b/linux-2.6-v4l-dvb-fixes.patch deleted file mode 100644 index e69de29bb..000000000 diff --git a/linux-2.6-v4l-dvb-update.patch b/linux-2.6-v4l-dvb-update.patch deleted file mode 100644 index e69de29bb..000000000 From af29089acc1c7e70e03cb919f84d3594c1e7f7ec Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 10 Apr 2012 20:10:54 -0400 Subject: [PATCH 360/397] Update hibernate watermark patch to latest tested version --- hibernate-watermark.patch | 147 +++++++++++++++++++++++++++++++------- 1 file changed, 123 insertions(+), 24 deletions(-) diff --git a/hibernate-watermark.patch b/hibernate-watermark.patch index 2cb75e6ef..7031e167f 100644 --- a/hibernate-watermark.patch +++ b/hibernate-watermark.patch @@ -1,7 +1,40 @@ +Hi Rafael, ---- a/kernel/power/swap.c -+++ a/kernel/power/swap.c -@@ -6,7 +6,7 @@ +One more version. Heeding Per's suggestion to optimise when +CONFIG_HIGHMEM is not configured. + +--------------------------------------- +Hibernation/thaw fixes/improvements: + +1. Calculate the number of required free pages based on non-high memory +pages only, because that is where the buffers will come from. + +2. Do not allocate memory for buffers from emergency pools, unless +absolutely required. Do not warn about and do not retry non-essential +failed allocations. + +3. Do not check the amount of free pages left on every single page +write, but wait until one map is completely populated and then check. + +4. Set maximum number of pages for read buffering consistently, instead +of inadvertently depending on the size of the sector type. + +5. Fix copyright line, which I missed when I submitted the hibernation +threading patch. + +6. Dispense with bit shifting arithmetic to improve readability. + +Signed-off-by: Bojan Smojver +Signed-off-by: Per Olofsson +--- + kernel/power/swap.c | 76 +++++++++++++++++++++++++++++++++++++++------------ + 1 files changed, 58 insertions(+), 18 deletions(-) + +diff --git a/kernel/power/swap.c b/kernel/power/swap.c +index 8742fd0..8a1c293 100644 +--- a/kernel/power/swap.c ++++ b/kernel/power/swap.c +@@ -6,7 +6,7 @@ * * Copyright (C) 1998,2001-2005 Pavel Machek * Copyright (C) 2006 Rafael J. Wysocki @@ -10,23 +43,44 @@ * * This file is released under the GPLv2. * -@@ -51,6 +51,15 @@ +@@ -51,6 +51,36 @@ #define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(sector_t) - 1) ++/* ++ * Number of free pages that are not high. ++ */ ++#ifdef CONFIG_HIGHMEM ++static unsigned long low_free_pages(void) ++{ ++ struct zone *zone; ++ unsigned long free = 0; ++ ++ for_each_populated_zone(zone) ++ if (!is_highmem(zone)) ++ free += zone_page_state(zone, NR_FREE_PAGES); ++ return free; ++} ++#else ++static inline unsigned long low_free_pages(void) ++{ ++ return nr_free_pages(); ++} ++#endif ++ +/* + * Number of pages required to be kept free while writing the image. Always -+ * three quarters of all available pages before the writing starts. ++ * half of all available low pages before the writing starts. + */ +static inline unsigned long reqd_free_pages(void) +{ -+ return (nr_free_pages() / 4) * 3; ++ return low_free_pages() / 2; +} + struct swap_map_page { sector_t entries[MAP_PAGE_ENTRIES]; sector_t next_swap; -@@ -72,7 +81,7 @@ struct swap_map_handle { +@@ -72,7 +102,7 @@ struct swap_map_handle { sector_t cur_swap; sector_t first_sector; unsigned int k; @@ -35,7 +89,27 @@ u32 crc32; }; -@@ -316,8 +325,7 @@ static int get_swap_writer(struct swap_map_handle *handle) +@@ -265,14 +295,17 @@ static int write_page(void *buf, sector_t offset, struct bio **bio_chain) + return -ENOSPC; + + if (bio_chain) { +- src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); ++ src = (void *)__get_free_page(__GFP_WAIT | __GFP_NOWARN | ++ __GFP_NORETRY); + if (src) { + copy_page(src, buf); + } else { + ret = hib_wait_on_bio_chain(bio_chain); /* Free pages */ + if (ret) + return ret; +- src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); ++ src = (void *)__get_free_page(__GFP_WAIT | ++ __GFP_NOWARN | ++ __GFP_NORETRY); + if (src) { + copy_page(src, buf); + } else { +@@ -316,8 +349,7 @@ static int get_swap_writer(struct swap_map_handle *handle) goto err_rel; } handle->k = 0; @@ -45,25 +119,31 @@ handle->first_sector = handle->cur_swap; return 0; err_rel: -@@ -352,11 +360,15 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, +@@ -351,12 +383,17 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, + clear_page(handle->cur); handle->cur_swap = offset; handle->k = 0; - } +- } - if (bio_chain && ++handle->written > handle->nr_free_pages) { -+ if (bio_chain && nr_free_pages() <= handle->reqd_free_pages) { - error = hib_wait_on_bio_chain(bio_chain); - if (error) - goto out; +- error = hib_wait_on_bio_chain(bio_chain); +- if (error) +- goto out; - handle->written = 0; -+ /* -+ * Recalculate the number of required free pages, to make sure -+ * we never take more than a quarter. -+ */ -+ handle->reqd_free_pages = reqd_free_pages(); ++ ++ if (bio_chain && low_free_pages() <= handle->reqd_free_pages) { ++ error = hib_wait_on_bio_chain(bio_chain); ++ if (error) ++ goto out; ++ /* ++ * Recalculate the number of required free pages, to ++ * make sure we never take more than half. ++ */ ++ handle->reqd_free_pages = reqd_free_pages(); ++ } } out: return error; -@@ -404,7 +416,7 @@ static int swap_writer_finish(struct swap_map_handle *handle, +@@ -404,7 +441,7 @@ static int swap_writer_finish(struct swap_map_handle *handle, #define LZO_THREADS 3 /* Maximum number of pages for read buffering. */ @@ -72,7 +152,7 @@ /** -@@ -615,10 +627,10 @@ static int save_image_lzo(struct swap_map_handle *handle, +@@ -615,10 +652,10 @@ static int save_image_lzo(struct swap_map_handle *handle, } /* @@ -86,14 +166,33 @@ /* * Start the CRC32 thread. -@@ -1129,8 +1141,9 @@ static int load_image_lzo(struct swap_map_handle *handle, +@@ -1129,14 +1166,17 @@ static int load_image_lzo(struct swap_map_handle *handle, /* * Adjust number of pages for read buffering, in case we are short. -+ * Never take more than a quarter of all available pages. ++ * Never take more than half of all available low pages. */ - read_pages = (nr_free_pages() - snapshot_get_image_size()) >> 1; -+ read_pages = (nr_free_pages() - snapshot_get_image_size()) / 4; ++ read_pages = (low_free_pages() - snapshot_get_image_size()) / 2; read_pages = clamp_val(read_pages, LZO_CMP_PAGES, LZO_READ_PAGES); for (i = 0; i < read_pages; i++) { + page[i] = (void *)__get_free_page(i < LZO_CMP_PAGES ? + __GFP_WAIT | __GFP_HIGH : +- __GFP_WAIT); ++ __GFP_WAIT | __GFP_NOWARN | ++ __GFP_NORETRY); ++ + if (!page[i]) { + if (i < LZO_CMP_PAGES) { + ring_size = i; +--------------------------------------- + +-- +Bojan + +-- +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/ \ No newline at end of file From 0b98ebd8f66e591861e6d46262e0c18c4a038da0 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Thu, 12 Apr 2012 10:49:35 -0500 Subject: [PATCH 361/397] KALLSYMS_EXTRA_PASS=1 is only able to be set via environment variables pass it in on the make line for arm only --- kernel.spec | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kernel.spec b/kernel.spec index 44111ec0e..2aedc02d1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1435,7 +1435,12 @@ BuildKernel() { echo USING ARCH=$Arch make -s ARCH=$Arch oldnoconfig >/dev/null +%ifarch %{arm} + # http://lists.infradead.org/pipermail/linux-arm-kernel/2012-March/091404.html + make -s ARCH=$Arch V=1 %{?_smp_mflags} $MakeTarget %{?sparse_mflags} KALLSYMS_EXTRA_PASS=1 +%else make -s ARCH=$Arch V=1 %{?_smp_mflags} $MakeTarget %{?sparse_mflags} +%endif make -s ARCH=$Arch V=1 %{?_smp_mflags} modules %{?sparse_mflags} || exit 1 # Start installing the results @@ -1969,6 +1974,9 @@ fi # and build. %changelog +* Thu Apr 12 2012 Dennis Gilmore +- KALLSYMS_EXTRA_PASS=1 has to be passed in on the command line so do so only for arm + * Tue Apr 10 2012 Mauro Carvalho Chehab 3.3.1-5 - Backport dvb-core and a few driver fixes from media tree (rhbz808871) From 16f6b7e04b9b763b8ff159fbc81a9689311e22ae Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 13 Apr 2012 13:21:06 -0400 Subject: [PATCH 362/397] 3.3.2 --- ...x-regression-in-FADT-revision-checks.patch | 58 ------- ...ensure-thermal-limits-match-cpu-freq.patch | 146 ------------------ iwlegacy-do-not-nulify-il-vif-on-reset.patch | 77 --------- kernel.spec | 35 +---- ...-tid_rx-reorder_timer-use-after-free.patch | 42 ----- ...er-copied-in-__nfs4_get_acl_uncached.patch | 32 ---- sources | 2 +- 7 files changed, 7 insertions(+), 385 deletions(-) delete mode 100644 ACPICA-Fix-regression-in-FADT-revision-checks.patch delete mode 100644 acpi-ensure-thermal-limits-match-cpu-freq.patch delete mode 100644 iwlegacy-do-not-nulify-il-vif-on-reset.patch delete mode 100644 mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch delete mode 100644 nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch diff --git a/ACPICA-Fix-regression-in-FADT-revision-checks.patch b/ACPICA-Fix-regression-in-FADT-revision-checks.patch deleted file mode 100644 index d6b590389..000000000 --- a/ACPICA-Fix-regression-in-FADT-revision-checks.patch +++ /dev/null @@ -1,58 +0,0 @@ - commit 64b3db22c04586997ab4be46dd5a5b99f8a2d390 (2.6.39), -"Remove use of unreliable FADT revision field" causes regression -for old P4 systems because now cst_control and other fields are -not reset to 0. - - The effect is that acpi_processor_power_init will notice -cst_control != 0 and a write to CST_CNT register is performed -that should not happen. As result, the system oopses after the -"No _CST, giving up" message, sometimes in acpi_ns_internalize_name, -sometimes in acpi_ns_get_type, usually at random places. May be -during migration to CPU 1 in acpi_processor_get_throttling. - - Every one of these settings help to avoid this problem: - - acpi=off - - processor.nocst=1 - - maxcpus=1 - - The fix is to update acpi_gbl_FADT.header.length after -the original value is used to check for old revisions. - -Signed-off-by: Julian Anastasov ---- - drivers/acpi/acpica/tbfadt.c | 8 ++++---- - 1 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c -index c5d8704..4c9c760 100644 ---- a/drivers/acpi/acpica/tbfadt.c -+++ b/drivers/acpi/acpica/tbfadt.c -@@ -363,10 +363,6 @@ static void acpi_tb_convert_fadt(void) - u32 address32; - u32 i; - -- /* Update the local FADT table header length */ -- -- acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); -- - /* - * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary. - * Later code will always use the X 64-bit field. Also, check for an -@@ -408,6 +404,10 @@ static void acpi_tb_convert_fadt(void) - acpi_gbl_FADT.boot_flags = 0; - } - -+ /* Update the local FADT table header length */ -+ -+ acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); -+ - /* - * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" - * generic address structures as necessary. Later code will always use --- -1.7.3.4 - --- -To unsubscribe from this list: send the line "unsubscribe linux-acpi" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/acpi-ensure-thermal-limits-match-cpu-freq.patch b/acpi-ensure-thermal-limits-match-cpu-freq.patch deleted file mode 100644 index 9d97b6024..000000000 --- a/acpi-ensure-thermal-limits-match-cpu-freq.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 9a056a5843ff83db987d6e18625f4a2ee64b5450 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Tue, 30 Aug 2011 10:07:24 -0400 -Subject: [PATCH] ACPI: Ensure thermal limits match CPU frequencies - -The ACPI thermal management code supports slowing down a CPU when it's -overheating. Right now that's done by choosing to run it at 100%, 75%, 50% -or 25% of full speed. However, most CPUs do not allow an arbitrary -frequency to be set and so will run at the first frequency below that value. -This doesn't match the intent of the specification, which is to drop the -frequency state by state until the temperature stabalises. Fix this up -so it uses actual frequencies rather than percentages. - -Reported by: Gene Snider -Signed-off-by: Matthew Garrett ---- - drivers/acpi/Kconfig | 1 + - drivers/acpi/processor_thermal.c | 45 +++++++++++++++++++++---------------- - 2 files changed, 26 insertions(+), 20 deletions(-) - -diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig -index de0e3df..7d1bdb5 100644 ---- a/drivers/acpi/Kconfig -+++ b/drivers/acpi/Kconfig -@@ -185,6 +185,7 @@ config ACPI_PROCESSOR - tristate "Processor" - select THERMAL - select CPU_IDLE -+ select CPU_FREQ_TABLE - default y - help - This driver installs ACPI as the idle handler for Linux and uses -diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c -index 870550d..1c4eb60 100644 ---- a/drivers/acpi/processor_thermal.c -+++ b/drivers/acpi/processor_thermal.c -@@ -52,10 +52,8 @@ ACPI_MODULE_NAME("processor_thermal"); - * _any_ cpufreq driver and not only the acpi-cpufreq driver. - */ - --#define CPUFREQ_THERMAL_MIN_STEP 0 --#define CPUFREQ_THERMAL_MAX_STEP 3 - --static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg); -+static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_limit_state); - static unsigned int acpi_thermal_cpufreq_is_init = 0; - - static int cpu_has_cpufreq(unsigned int cpu) -@@ -70,19 +68,19 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, - unsigned long event, void *data) - { - struct cpufreq_policy *policy = data; -- unsigned long max_freq = 0; -+ int state = per_cpu(cpufreq_thermal_limit_state, policy->cpu); -+ struct cpufreq_frequency_table *table; - - if (event != CPUFREQ_ADJUST) -- goto out; -+ return 0; -+ -+ table = cpufreq_frequency_get_table(policy->cpu); - -- max_freq = ( -- policy->cpuinfo.max_freq * -- (100 - per_cpu(cpufreq_thermal_reduction_pctg, policy->cpu) * 20) -- ) / 100; -+ if (!table) -+ return 0; - -- cpufreq_verify_within_limits(policy, 0, max_freq); -+ cpufreq_verify_within_limits(policy, 0, table[state].frequency); - -- out: - return 0; - } - -@@ -92,10 +90,21 @@ static struct notifier_block acpi_thermal_cpufreq_notifier_block = { - - static int cpufreq_get_max_state(unsigned int cpu) - { -+ int count = 0; -+ struct cpufreq_frequency_table *table; -+ - if (!cpu_has_cpufreq(cpu)) - return 0; - -- return CPUFREQ_THERMAL_MAX_STEP; -+ table = cpufreq_frequency_get_table(cpu); -+ -+ if (!table) -+ return 0; -+ -+ while (table[count].frequency != CPUFREQ_TABLE_END) -+ count++; -+ -+ return count; - } - - static int cpufreq_get_cur_state(unsigned int cpu) -@@ -103,7 +112,7 @@ static int cpufreq_get_cur_state(unsigned int cpu) - if (!cpu_has_cpufreq(cpu)) - return 0; - -- return per_cpu(cpufreq_thermal_reduction_pctg, cpu); -+ return per_cpu(cpufreq_thermal_limit_state, cpu); - } - - static int cpufreq_set_cur_state(unsigned int cpu, int state) -@@ -111,7 +120,7 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state) - if (!cpu_has_cpufreq(cpu)) - return 0; - -- per_cpu(cpufreq_thermal_reduction_pctg, cpu) = state; -+ per_cpu(cpufreq_thermal_limit_state, cpu) = state; - cpufreq_update_policy(cpu); - return 0; - } -@@ -122,7 +131,7 @@ void acpi_thermal_cpufreq_init(void) - - for (i = 0; i < nr_cpu_ids; i++) - if (cpu_present(i)) -- per_cpu(cpufreq_thermal_reduction_pctg, i) = 0; -+ per_cpu(cpufreq_thermal_limit_state, i) = 0; - - i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block, - CPUFREQ_POLICY_NOTIFIER); -@@ -170,15 +179,11 @@ int acpi_processor_get_limit_info(struct acpi_processor *pr) - return 0; - } - --/* thermal coolign device callbacks */ -+/* thermal cooling device callbacks */ - static int acpi_processor_max_state(struct acpi_processor *pr) - { - int max_state = 0; - -- /* -- * There exists four states according to -- * cpufreq_thermal_reduction_ptg. 0, 1, 2, 3 -- */ - max_state += cpufreq_get_max_state(pr->id); - if (pr->flags.throttling) - max_state += (pr->throttling.state_count -1); --- -1.7.6 - diff --git a/iwlegacy-do-not-nulify-il-vif-on-reset.patch b/iwlegacy-do-not-nulify-il-vif-on-reset.patch deleted file mode 100644 index d1913d708..000000000 --- a/iwlegacy-do-not-nulify-il-vif-on-reset.patch +++ /dev/null @@ -1,77 +0,0 @@ -This il->vif is dereferenced in different part of iwlegacy code, so do -not nullify it. This should fix random crashes observed in companion -with microcode errors i.e. crash in il3945_config_ap(). - -Additionally this should address also -WARNING: at drivers/net/wireless/iwlegacy/common.c:4656 il_mac_remove_interface -at least one of the possible reasons of that warning. - -Cc: stable@vger.kernel.org -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/iwlegacy/3945-mac.c | 2 -- - drivers/net/wireless/iwlegacy/4965-mac.c | 2 -- - drivers/net/wireless/iwlegacy/common.c | 15 ++++++++++++--- - 3 files changed, 12 insertions(+), 7 deletions(-) - ---- linux-3.3.noarch.orig/drivers/net/wireless/iwlegacy/3945-mac.c -+++ linux-3.3.noarch/drivers/net/wireless/iwlegacy/3945-mac.c -@@ -2684,7 +2684,6 @@ il3945_bg_restart(struct work_struct *da - - if (test_and_clear_bit(S_FW_ERROR, &il->status)) { - mutex_lock(&il->mutex); -- il->ctx.vif = NULL; - il->is_open = 0; - mutex_unlock(&il->mutex); - il3945_down(il); ---- linux-3.3.noarch.orig/drivers/net/wireless/iwlegacy/4965-mac.c -+++ linux-3.3.noarch/drivers/net/wireless/iwlegacy/4965-mac.c -@@ -5381,7 +5381,6 @@ il4965_bg_restart(struct work_struct *da - - if (test_and_clear_bit(S_FW_ERROR, &il->status)) { - mutex_lock(&il->mutex); -- il->ctx.vif = NULL; - il->is_open = 0; - - __il4965_down(il); ---- linux-3.3.noarch.orig/drivers/net/wireless/iwlegacy/common.c -+++ linux-3.3.noarch/drivers/net/wireless/iwlegacy/common.c -@@ -4575,6 +4575,7 @@ il_mac_add_interface(struct ieee80211_hw - struct il_priv *il = hw->priv; - struct il_vif_priv *vif_priv = (void *)vif->drv_priv; - int err; -+ bool reset; - u32 modes; - - D_MAC80211("enter: type %d, addr %pM\n", vif->type, vif->addr); -@@ -4594,6 +4595,16 @@ il_mac_add_interface(struct ieee80211_hw - goto out; - } - -+ /* -+ * We do not support multiple virtual interfaces, but on hardware reset -+ * we have to add the same interface again. -+ */ -+ reset = (il->ctx.vif == vif); -+ if (il->ctx.vif && !reset) { -+ err = -EOPNOTSUPP; -+ goto out; -+ } -+ - modes = il->ctx.interface_modes | il->ctx.exclusive_interface_modes; - if (!(modes & BIT(vif->type))) { - err = -EOPNOTSUPP; -@@ -4605,8 +4616,11 @@ il_mac_add_interface(struct ieee80211_hw - - err = il_setup_interface(il, &il->ctx); - if (err) { -- il->ctx.vif = NULL; -- il->iw_mode = NL80211_IFTYPE_STATION; -+ IL_WARN("Fail to set mode %d\n", vif->type); -+ if (!reset) { -+ il->ctx.vif = NULL; -+ il->iw_mode = NL80211_IFTYPE_STATION; -+ } - } - - out: diff --git a/kernel.spec b/kernel.spec index 2aedc02d1..d0a6fd50d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 # Set rpm version accordingly @@ -588,7 +588,6 @@ Patch383: linux-2.6-defaults-aspm.patch Patch390: linux-2.6-defaults-acpi-video.patch Patch391: linux-2.6-acpi-video-dos.patch Patch394: linux-2.6-acpi-debug-infinite-loop.patch -Patch395: acpi-ensure-thermal-limits-match-cpu-freq.patch Patch396: acpi-sony-nonvs-blacklist.patch Patch450: linux-2.6-input-kill-stupid-messages.patch @@ -678,25 +677,15 @@ Patch21232: rt2x00_fix_MCU_request_failures.patch #rhbz 789644 Patch21237: mcelog-rcu-splat.patch -#rhbz 727865 730007 -Patch21240: ACPICA-Fix-regression-in-FADT-revision-checks.patch - #rhbz 728478 Patch21242: sony-laptop-Enable-keyboard-backlight-by-default.patch Patch21300: unhandled-irqs-switch-to-polling.patch -#rhbz 804007 -Patch21305: mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch - #rhbz 804957 CVE-2012-1568 Patch21306: shlib_base_randomize.patch -#rhbz 806433 -Patch21360: uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch - #rhbz 770476 -Patch21370: iwlegacy-do-not-nulify-il-vif-on-reset.patch Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch #rhbz 808603 @@ -709,8 +698,6 @@ Patch21385: libata-disable-runtime-pm-for-hotpluggable-port.patch Patch21390: x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch Patch21391: x86-Use-correct-byte-sized-register-constraint-in-__add.patch -Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch - #rhbz 808207 CVE-2012-1601 Patch21520: KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch @@ -1176,7 +1163,6 @@ ApplyPatch NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch ApplyPatch linux-2.6-defaults-acpi-video.patch ApplyPatch linux-2.6-acpi-video-dos.patch ApplyPatch linux-2.6-acpi-debug-infinite-loop.patch -ApplyPatch acpi-ensure-thermal-limits-match-cpu-freq.patch ApplyPatch acpi-sony-nonvs-blacklist.patch # force UTSNAME to show version 2.6.4X @@ -1250,7 +1236,7 @@ ApplyPatch quite-apm.patch # Media (V4L/DVB/IR) updates/fixes/experimental drivers # apply if non-empty ApplyPatch add-poll-requested-events.patch -ApplyOptionalPatch drivers-media-update.patch +#ApplyOptionalPatch drivers-media-update.patch # Patches headed upstream @@ -1284,15 +1270,9 @@ ApplyPatch bcma-brcmsmac-compat.patch #rhbz 789644 ApplyPatch mcelog-rcu-splat.patch -#rhbz 727865 730007 -ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch - #rhbz 728478 ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch -#rhbz 804007 -ApplyPatch mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch - #rhbz 804957 CVE-2012-1568 ApplyPatch shlib_base_randomize.patch @@ -1300,18 +1280,12 @@ ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch -ApplyPatch nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch - #rhbz 808207 CVE-2012-1601 ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch #rhbz 770476 -ApplyPatch iwlegacy-do-not-nulify-il-vif-on-reset.patch ApplyPatch iwlwifi-do-not-nulify-ctx-vif-on-reset.patch -#rhbz 806433 -ApplyPatch uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch - #rhbz 808603 ApplyPatch wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch @@ -1974,10 +1948,13 @@ fi # and build. %changelog +* Fri Apr 13 2012 Dave Jones 2.6.43.1-5 +- Linux 3.3.2 + * Thu Apr 12 2012 Dennis Gilmore - KALLSYMS_EXTRA_PASS=1 has to be passed in on the command line so do so only for arm -* Tue Apr 10 2012 Mauro Carvalho Chehab 3.3.1-5 +* Tue Apr 10 2012 Mauro Carvalho Chehab - Backport dvb-core and a few driver fixes from media tree (rhbz808871) * Tue Apr 10 2012 Josh Boyer diff --git a/mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch b/mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch deleted file mode 100644 index accda8afc..000000000 --- a/mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch +++ /dev/null @@ -1,42 +0,0 @@ -Is possible that we will arm the tid_rx->reorder_timer after -del_timer_sync() in ___ieee80211_stop_rx_ba_session(). We need to stop -timer after RCU grace period finish, so move it to -ieee80211_free_tid_rx(). Timer will not be armed again, as -rcu_dereference(sta->ampdu_mlme.tid_rx[tid]) will return NULL. - -Debug object detected problem with the following warning: -ODEBUG: free active (active state 0) object type: timer_list hint: sta_rx_agg_reorder_timer_expired+0x0/0xf0 [mac80211] - -Bug report (with all warning messages): -https://bugzilla.redhat.com/show_bug.cgi?id=804007 - -Reported-by: "jan p. springer" -Cc: stable@vger.kernel.org -Signed-off-by: Stanislaw Gruszka ---- - net/mac80211/agg-rx.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c -index 1068f66..64d3ce5 100644 ---- a/net/mac80211/agg-rx.c -+++ b/net/mac80211/agg-rx.c -@@ -49,6 +49,8 @@ static void ieee80211_free_tid_rx(struct rcu_head *h) - container_of(h, struct tid_ampdu_rx, rcu_head); - int i; - -+ del_timer_sync(&tid_rx->reorder_timer); -+ - for (i = 0; i < tid_rx->buf_size; i++) - dev_kfree_skb(tid_rx->reorder_buf[i]); - kfree(tid_rx->reorder_buf); -@@ -91,7 +93,6 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, - tid, WLAN_BACK_RECIPIENT, reason); - - del_timer_sync(&tid_rx->session_timer); -- del_timer_sync(&tid_rx->reorder_timer); - - call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); - } --- -1.7.1 diff --git a/nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch b/nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch deleted file mode 100644 index 981f1f467..000000000 --- a/nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 20e0fa98b751facf9a1101edaefbc19c82616a68 Mon Sep 17 00:00:00 2001 -From: Sachin Prabhu -Date: Thu, 22 Mar 2012 16:46:28 +0000 -Subject: [PATCH] Fix length of buffer copied in __nfs4_get_acl_uncached - -_copy_from_pages() used to copy data from the temporary buffer to the -user passed buffer is passed the wrong size parameter when copying -data. res.acl_len contains both the bitmap and acl lenghts while -acl_len contains the acl length after adjusting for the bitmap size. - -Signed-off-by: Sachin Prabhu -Signed-off-by: Trond Myklebust ---- - fs/nfs/nfs4proc.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c -index e809d23..45df7d4 100644 ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -3712,7 +3712,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu - if (acl_len > buflen) - goto out_free; - _copy_from_pages(buf, pages, res.acl_data_offset, -- res.acl_len); -+ acl_len); - } - ret = acl_len; - out_free: --- -1.7.7.6 - diff --git a/sources b/sources index e8c9e05f6..413d6dc42 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz -10771d657c5bf342bcfe66ed06653ecb patch-3.3.1.xz +68907107b0f62a19608588bdb6b29e20 patch-3.3.2.xz From 549bc3181c12d5d3ee03548561dea022dd91ebe6 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 13 Apr 2012 13:22:21 -0400 Subject: [PATCH 363/397] fix version --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index d0a6fd50d..1e77192e8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 5 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -1948,7 +1948,7 @@ fi # and build. %changelog -* Fri Apr 13 2012 Dave Jones 2.6.43.1-5 +* Fri Apr 13 2012 Dave Jones 2.6.43.2-1 - Linux 3.3.2 * Thu Apr 12 2012 Dennis Gilmore From c44648089e3c415ab1798a5d2d48424fa80538a0 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 13 Apr 2012 13:24:09 -0400 Subject: [PATCH 364/397] remove uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch --- ...uced-crash-in-uvc_video_clock_update.patch | 113 ------------------ 1 file changed, 113 deletions(-) delete mode 100644 uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch diff --git a/uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch b/uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch deleted file mode 100644 index 5f2a1c006..000000000 --- a/uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch +++ /dev/null @@ -1,113 +0,0 @@ -@@ -, +, @@ - drivers/media/video/uvc/uvc_video.c | 50 ++++++++++++++++++++++------------ - 1 files changed, 32 insertions(+), 18 deletions(-) ---- a/drivers/media/video/uvc/uvc_video.c -+++ a/drivers/media/video/uvc/uvc_video.c -@@ -468,22 +468,30 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf, - spin_unlock_irqrestore(&stream->clock.lock, flags); - } - --static int uvc_video_clock_init(struct uvc_streaming *stream) -+static void uvc_video_clock_reset(struct uvc_streaming *stream) - { - struct uvc_clock *clock = &stream->clock; - -- spin_lock_init(&clock->lock); - clock->head = 0; - clock->count = 0; -- clock->size = 32; - clock->last_sof = -1; - clock->sof_offset = -1; -+} -+ -+static int uvc_video_clock_init(struct uvc_streaming *stream) -+{ -+ struct uvc_clock *clock = &stream->clock; -+ -+ spin_lock_init(&clock->lock); -+ clock->size = 32; - - clock->samples = kmalloc(clock->size * sizeof(*clock->samples), - GFP_KERNEL); - if (clock->samples == NULL) - return -ENOMEM; - -+ uvc_video_clock_reset(stream); -+ - return 0; - } - -@@ -1424,8 +1432,6 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) - - if (free_buffers) - uvc_free_urb_buffers(stream); -- -- uvc_video_clock_cleanup(stream); - } - - /* -@@ -1555,10 +1561,6 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) - - uvc_video_stats_start(stream); - -- ret = uvc_video_clock_init(stream); -- if (ret < 0) -- return ret; -- - if (intf->num_altsetting > 1) { - struct usb_host_endpoint *best_ep = NULL; - unsigned int best_psize = 3 * 1024; -@@ -1683,6 +1685,8 @@ int uvc_video_resume(struct uvc_streaming *stream, int reset) - - stream->frozen = 0; - -+ uvc_video_clock_reset(stream); -+ - ret = uvc_commit_video(stream, &stream->ctrl); - if (ret < 0) { - uvc_queue_enable(&stream->queue, 0); -@@ -1819,25 +1823,35 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable) - uvc_uninit_video(stream, 1); - usb_set_interface(stream->dev->udev, stream->intfnum, 0); - uvc_queue_enable(&stream->queue, 0); -+ uvc_video_clock_cleanup(stream); - return 0; - } - -- ret = uvc_queue_enable(&stream->queue, 1); -+ ret = uvc_video_clock_init(stream); - if (ret < 0) - return ret; - -+ ret = uvc_queue_enable(&stream->queue, 1); -+ if (ret < 0) -+ goto error_queue; -+ - /* Commit the streaming parameters. */ - ret = uvc_commit_video(stream, &stream->ctrl); -- if (ret < 0) { -- uvc_queue_enable(&stream->queue, 0); -- return ret; -- } -+ if (ret < 0) -+ goto error_commit; - - ret = uvc_init_video(stream, GFP_KERNEL); -- if (ret < 0) { -- usb_set_interface(stream->dev->udev, stream->intfnum, 0); -- uvc_queue_enable(&stream->queue, 0); -- } -+ if (ret < 0) -+ goto error_video; -+ -+ return 0; -+ -+error_video: -+ usb_set_interface(stream->dev->udev, stream->intfnum, 0); -+error_commit: -+ uvc_queue_enable(&stream->queue, 0); -+error_queue: -+ uvc_video_clock_cleanup(stream); - - return ret; - } From 51e2b3d120a39de0077c45398f288cbf752078e9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 13 Apr 2012 15:43:44 -0400 Subject: [PATCH 365/397] Reapply rebased drivers-media-update.patch --- drivers-media-update.patch | 42 +++----------------------------------- kernel.spec | 7 +++++-- 2 files changed, 8 insertions(+), 41 deletions(-) diff --git a/drivers-media-update.patch b/drivers-media-update.patch index 5d5612b72..f08a5d5cf 100644 --- a/drivers-media-update.patch +++ b/drivers-media-update.patch @@ -10439,51 +10439,15 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-core/dvb_frontend.c =================================================================== --- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-core/dvb_frontend.c +++ linux-3.3.x86_64/drivers/media/dvb/dvb-core/dvb_frontend.c -@@ -143,10 +143,12 @@ struct dvb_frontend_private { - static void dvb_frontend_wakeup(struct dvb_frontend *fe); - static int dtv_get_frontend(struct dvb_frontend *fe, - struct dvb_frontend_parameters *p_out); -+static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, -+ struct dvb_frontend_parameters *p); - +@@ -148,7 +148,7 @@ static int dtv_property_legacy_params_sy + static bool has_get_frontend(struct dvb_frontend *fe) { - return fe->ops.get_frontend; + return fe->ops.get_frontend != NULL; } - + /* -@@ -655,6 +657,8 @@ restart: - dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); - re_tune = true; - fepriv->state = FESTATE_TUNED; -+ } else { -+ re_tune = false; - } - - if (fe->ops.tune) -@@ -695,6 +699,7 @@ restart: - fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; - fepriv->delay = HZ / 2; - } -+ dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); - fe->ops.read_status(fe, &s); - if (s != fepriv->status) { - dvb_frontend_add_event(fe, s); /* update event list */ -@@ -1831,6 +1836,13 @@ static int dtv_set_frontend(struct dvb_f - return -EINVAL; - - /* -+ * Initialize output parameters to match the values given by -+ * the user. FE_SET_FRONTEND triggers an initial frontend event -+ * with status = 0, which copies output parameters to userspace. -+ */ -+ dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); -+ -+ /* - * Be sure that the bandwidth will be filled for all - * non-satellite systems, as tuners need to know what - * low pass/Nyquist half filter should be applied, in Index: linux-3.3.x86_64/drivers/media/common/tuners/xc5000.c =================================================================== --- linux-3.3.x86_64.orig/drivers/media/common/tuners/xc5000.c diff --git a/kernel.spec b/kernel.spec index 1e77192e8..d54750216 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -1236,7 +1236,7 @@ ApplyPatch quite-apm.patch # Media (V4L/DVB/IR) updates/fixes/experimental drivers # apply if non-empty ApplyPatch add-poll-requested-events.patch -#ApplyOptionalPatch drivers-media-update.patch +ApplyOptionalPatch drivers-media-update.patch # Patches headed upstream @@ -1948,6 +1948,9 @@ fi # and build. %changelog +* Fri Apr 13 2012 Josh Boyer +- Reapply rebased drivers-media-update.patch + * Fri Apr 13 2012 Dave Jones 2.6.43.2-1 - Linux 3.3.2 From b8614ae383e33bcd91547bf719124cd9cb184f24 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sat, 14 Apr 2012 09:23:39 -0400 Subject: [PATCH 366/397] Add ALSA quirk for MacPro 5,1 machines (rhbz 808559) --- ...k-Add-quirk-for-Mac-Pro-5-1-machines.patch | 37 +++++++++++++++++++ kernel.spec | 11 +++++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch diff --git a/ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch b/ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch new file mode 100644 index 000000000..28579d13b --- /dev/null +++ b/ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch @@ -0,0 +1,37 @@ +From a9e1e167d934aa74f48008393ade4f09fc587432 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Thu, 12 Apr 2012 13:55:36 -0400 +Subject: [PATCH] ALSA: hda/realtek - Add quirk for Mac Pro 5,1 machines + +A user reported that setting model=imac24 used to allow sound to work on their +Mac Pro 5,1 machine. Commit 5671087ffa "Move ALC885 macpro and imac24 models +to auto-parser" removed this model option. All Mac machines are now explicitly +handled with a quirk and the auto-parser. This adds a quirk for the device +found on the Mac Pro 5,1 machines. + +This (partially) fixes https://bugzilla.redhat.com/show_bug.cgi?id=808559 + +[sorted the new entry in the ID number order by tiwai] + +Reported-by: Gabriel Somlo +Signed-off-by: Josh Boyer +Signed-off-by: Takashi Iwai +--- + sound/pci/hda/patch_realtek.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 22c73b7..bd34b51 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -4659,6 +4659,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { + SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO), + SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD), + SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO), ++ SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO), + + SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), + SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index d54750216..92bd05035 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -701,6 +701,9 @@ Patch21391: x86-Use-correct-byte-sized-register-constraint-in-__add.patch #rhbz 808207 CVE-2012-1601 Patch21520: KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch +#rhbz 808559 +Patch21530: ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch + Patch22000: weird-root-dentry-name-debug.patch %endif @@ -1182,6 +1185,9 @@ ApplyPatch linux-2.6-defaults-aspm.patch # ALSA +#rhbz 808559 +ApplyPatch ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch + # Networking @@ -1948,6 +1954,9 @@ fi # and build. %changelog +* Sat Apr 14 2012 Josh Boyer +- Add ALSA quirk for MacPro 5,1 machines (rhbz 808559) + * Fri Apr 13 2012 Josh Boyer - Reapply rebased drivers-media-update.patch From 210099fb2c34b46bfda653480aea01f7e5565dc8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 17 Apr 2012 11:05:33 -0400 Subject: [PATCH 367/397] Fix oops on invalid AMD microcode load (rhbz 797559) --- kernel.spec | 10 ++ ...s-only-loaded-for-supported-AMD-CPUs.patch | 163 +++++++++++++++++ ...ng-module-unload-on-unsupported-CPUs.patch | 167 ++++++++++++++++++ 3 files changed, 340 insertions(+) create mode 100644 x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch create mode 100644 x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch diff --git a/kernel.spec b/kernel.spec index 92bd05035..57a731a05 100644 --- a/kernel.spec +++ b/kernel.spec @@ -704,6 +704,9 @@ Patch21520: KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch #rhbz 808559 Patch21530: ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch +Patch21700: x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch +Patch21701: x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch + Patch22000: weird-root-dentry-name-debug.patch %endif @@ -1302,6 +1305,10 @@ ApplyPatch libata-disable-runtime-pm-for-hotpluggable-port.patch ApplyPatch x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch ApplyPatch x86-Use-correct-byte-sized-register-constraint-in-__add.patch +#rhbz 797559 +ApplyPatch x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch +ApplyPatch x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch + # END OF PATCH APPLICATIONS %endif @@ -1954,6 +1961,9 @@ fi # and build. %changelog +* Tue Apr 17 2012 Josh Boyer +- Fix oops on invalid AMD microcode load (rhbz 797559) + * Sat Apr 14 2012 Josh Boyer - Add ALSA quirk for MacPro 5,1 machines (rhbz 808559) diff --git a/x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch b/x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch new file mode 100644 index 000000000..d69317316 --- /dev/null +++ b/x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch @@ -0,0 +1,163 @@ +Path: news.gmane.org!not-for-mail +From: Borislav Petkov +Newsgroups: gmane.linux.kernel +Subject: [PATCH 2/2] x86, microcode: Ensure that module is only loaded for +Date: Thu, 12 Apr 2012 18:34:22 +0200 +Lines: 80 +Approved: news@gmane.org +Message-ID: <20120412163422.GM24549@aftab> +References: <20120411163849.GE4794@alberich.amd.com> + <20120411200601.GC12288@kroah.com> + <20120411201053.GF18114@aftab> + <20120412162351.GJ24549@aftab> +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +X-Trace: dough.gmane.org 1334248500 15307 80.91.229.3 (12 Apr 2012 16:35:00 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Thu, 12 Apr 2012 16:35:00 +0000 (UTC) +Cc: Andreas Herrmann , + Kay Sievers , + Dave Jones , +To: Greg Kroah-Hartman +Original-X-From: linux-kernel-owner@vger.kernel.org Thu Apr 12 18:34:59 2012 +Return-path: +Envelope-to: glk-linux-kernel-3@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1SIMz4-0008MV-3g + for glk-linux-kernel-3@plane.gmane.org; Thu, 12 Apr 2012 18:34:58 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S965760Ab2DLQep (ORCPT ); + Thu, 12 Apr 2012 12:34:45 -0400 +Original-Received: from db3ehsobe002.messaging.microsoft.com ([213.199.154.140]:56919 + "EHLO db3outboundpool.messaging.microsoft.com" rhost-flags-OK-OK-OK-OK) + by vger.kernel.org with ESMTP id S965553Ab2DLQen (ORCPT + ); + Thu, 12 Apr 2012 12:34:43 -0400 +Original-Received: from mail2-db3-R.bigfish.com (10.3.81.239) by + DB3EHSOBE005.bigfish.com (10.3.84.25) with Microsoft SMTP Server id + 14.1.225.23; Thu, 12 Apr 2012 16:34:41 +0000 +Original-Received: from mail2-db3 (localhost [127.0.0.1]) by mail2-db3-R.bigfish.com + (Postfix) with ESMTP id E4EF14404B4; Thu, 12 Apr 2012 16:34:41 +0000 (UTC) +X-SpamScore: 0 +X-BigFish: VPS0(zzzz1202hzz8275bh8275dhz2dh668h839h944hd25hd2bh) +X-Forefront-Antispam-Report: CIP:163.181.249.108;KIP:(null);UIP:(null);IPV:NLI;H:ausb3twp01.amd.com;RD:none;EFVD:NLI +Original-Received: from mail2-db3 (localhost.localdomain [127.0.0.1]) by mail2-db3 + (MessageSwitch) id 1334248479906480_3860; Thu, 12 Apr 2012 16:34:39 +0000 + (UTC) +Original-Received: from DB3EHSMHS005.bigfish.com (unknown [10.3.81.241]) by + mail2-db3.bigfish.com (Postfix) with ESMTP id CEB76400A4; Thu, 12 Apr 2012 + 16:34:39 +0000 (UTC) +Original-Received: from ausb3twp01.amd.com (163.181.249.108) by + DB3EHSMHS005.bigfish.com (10.3.87.105) with Microsoft SMTP Server id + 14.1.225.23; Thu, 12 Apr 2012 16:34:38 +0000 +X-WSS-ID: 0M2DKPO-01-CNU-02 +X-M-MSG: +Original-Received: from sausexedgep02.amd.com (sausexedgep02-ext.amd.com + [163.181.249.73]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No + client certificate requested) by ausb3twp01.amd.com (Axway MailGate 3.8.1) + with ESMTP id 2C1D81028100; Thu, 12 Apr 2012 11:34:36 -0500 (CDT) +Original-Received: from SAUSEXDAG02.amd.com (163.181.55.2) by sausexedgep02.amd.com + (163.181.36.59) with Microsoft SMTP Server (TLS) id 8.3.192.1; Thu, 12 Apr + 2012 11:34:51 -0500 +Original-Received: from storexhtp01.amd.com (172.24.4.3) by sausexdag02.amd.com + (163.181.55.2) with Microsoft SMTP Server (TLS) id 14.1.323.3; Thu, 12 Apr + 2012 11:34:36 -0500 +Original-Received: from gwo.osrc.amd.com (165.204.16.204) by storexhtp01.amd.com + (172.24.4.3) with Microsoft SMTP Server id 8.3.213.0; Thu, 12 Apr 2012 + 12:34:35 -0400 +Original-Received: from aftab (aftab.osrc.amd.com [165.204.15.109]) by gwo.osrc.amd.com + (Postfix) with ESMTP id D8E4C49C58B; Thu, 12 Apr 2012 17:34:33 +0100 (BST) +Content-Disposition: inline +In-Reply-To: <20120412162351.GJ24549@aftab> +User-Agent: Mutt/1.5.21 (2010-09-15) +X-OriginatorOrg: amd.com +Original-Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel:1281050 +Archived-At: + +From: Andreas Herrmann +Date: Thu, 12 Apr 2012 16:51:57 +0200 +Subject: [PATCH 2/2] x86, microcode: Ensure that module is only loaded for supported AMD CPUs + +Exit early when there's no support for a particular CPU family. Also, +fixup the "no support for this CPU vendor" to be issued only when the +driver is attempted to be loaded on an unsupported vendor. + +Cc: stable@vger.kernel.org +Cc: Tigran Aivazian +Cc: Borislav Petkov +[Boris: added a commit msg because Andreas is lazy] +Signed-off-by: Andreas Herrmann +--- + arch/x86/kernel/microcode_amd.c | 12 +++++++----- + arch/x86/kernel/microcode_core.c | 6 +++--- + 2 files changed, 10 insertions(+), 8 deletions(-) + +diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c +index 73465aa..8a2ce8f 100644 +--- a/arch/x86/kernel/microcode_amd.c ++++ b/arch/x86/kernel/microcode_amd.c +@@ -82,11 +82,6 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) + { + struct cpuinfo_x86 *c = &cpu_data(cpu); + +- if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { +- pr_warning("CPU%d: family %d not supported\n", cpu, c->x86); +- return -1; +- } +- + csig->rev = c->microcode; + pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev); + +@@ -380,6 +375,13 @@ static struct microcode_ops microcode_amd_ops = { + + struct microcode_ops * __init init_amd_microcode(void) + { ++ struct cpuinfo_x86 *c = &cpu_data(0); ++ ++ if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { ++ pr_warning("AMD CPU family 0x%x not supported\n", c->x86); ++ return NULL; ++ } ++ + patch = (void *)get_zeroed_page(GFP_KERNEL); + if (!patch) + return NULL; +diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c +index d389e74..c9bda6d 100644 +--- a/arch/x86/kernel/microcode_core.c ++++ b/arch/x86/kernel/microcode_core.c +@@ -526,11 +526,11 @@ static int __init microcode_init(void) + microcode_ops = init_intel_microcode(); + else if (c->x86_vendor == X86_VENDOR_AMD) + microcode_ops = init_amd_microcode(); +- +- if (!microcode_ops) { ++ else + pr_err("no support for this CPU vendor\n"); ++ ++ if (!microcode_ops) + return -ENODEV; +- } + + microcode_pdev = platform_device_register_simple("microcode", -1, + NULL, 0); +-- +1.7.8.4 + +-- +Regards/Gruss, +Boris. + +Advanced Micro Devices GmbH +Einsteinring 24, 85609 Dornach +GM: Alberto Bozzo +Reg: Dornach, Landkreis Muenchen +HRB Nr. 43632 WEEE Registernr: 129 19551 + diff --git a/x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch b/x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch new file mode 100644 index 000000000..d1cafc162 --- /dev/null +++ b/x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch @@ -0,0 +1,167 @@ +Path: news.gmane.org!not-for-mail +From: Borislav Petkov +Newsgroups: gmane.linux.kernel +Subject: [PATCH 1/2] x86, microcode: Fix sysfs warning during module unload +Date: Thu, 12 Apr 2012 18:30:38 +0200 +Lines: 83 +Approved: news@gmane.org +Message-ID: <20120412163038.GL24549@aftab> +References: <20120411163849.GE4794@alberich.amd.com> + <20120411200601.GC12288@kroah.com> + <20120411201053.GF18114@aftab> + <20120412162351.GJ24549@aftab> +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +X-Trace: dough.gmane.org 1334248312 13759 80.91.229.3 (12 Apr 2012 16:31:52 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Thu, 12 Apr 2012 16:31:52 +0000 (UTC) +Cc: Andreas Herrmann , + Kay Sievers , + Dave Jones , +To: Greg Kroah-Hartman +Original-X-From: linux-kernel-owner@vger.kernel.org Thu Apr 12 18:31:50 2012 +Return-path: +Envelope-to: glk-linux-kernel-3@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1SIMw1-0005nm-KE + for glk-linux-kernel-3@plane.gmane.org; Thu, 12 Apr 2012 18:31:49 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S934534Ab2DLQbF (ORCPT ); + Thu, 12 Apr 2012 12:31:05 -0400 +Original-Received: from db3ehsobe004.messaging.microsoft.com ([213.199.154.142]:35401 + "EHLO db3outboundpool.messaging.microsoft.com" rhost-flags-OK-OK-OK-OK) + by vger.kernel.org with ESMTP id S934436Ab2DLQbD (ORCPT + ); + Thu, 12 Apr 2012 12:31:03 -0400 +Original-Received: from mail117-db3-R.bigfish.com (10.3.81.240) by + DB3EHSOBE002.bigfish.com (10.3.84.22) with Microsoft SMTP Server id + 14.1.225.23; Thu, 12 Apr 2012 16:31:00 +0000 +Original-Received: from mail117-db3 (localhost [127.0.0.1]) by + mail117-db3-R.bigfish.com (Postfix) with ESMTP id BAA93180481; Thu, 12 Apr + 2012 16:31:00 +0000 (UTC) +X-SpamScore: 1 +X-BigFish: VPS1(zzzz1202hzz8275eh8275bh8275dha1495iz2dh668h839h944hd25hd2bh) +X-Forefront-Antispam-Report: CIP:163.181.249.109;KIP:(null);UIP:(null);IPV:NLI;H:ausb3twp02.amd.com;RD:none;EFVD:NLI +Original-Received: from mail117-db3 (localhost.localdomain [127.0.0.1]) by mail117-db3 + (MessageSwitch) id 133424825930391_28243; Thu, 12 Apr 2012 16:30:59 +0000 + (UTC) +Original-Received: from DB3EHSMHS006.bigfish.com (unknown [10.3.81.226]) by + mail117-db3.bigfish.com (Postfix) with ESMTP id ED7022E004F; Thu, 12 Apr 2012 + 16:30:58 +0000 (UTC) +Original-Received: from ausb3twp02.amd.com (163.181.249.109) by + DB3EHSMHS006.bigfish.com (10.3.87.106) with Microsoft SMTP Server id + 14.1.225.23; Thu, 12 Apr 2012 16:30:57 +0000 +X-WSS-ID: 0M2DKJG-02-0NU-02 +X-M-MSG: +Original-Received: from sausexedgep01.amd.com (sausexedgep01-ext.amd.com + [163.181.249.72]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No + client certificate requested) by ausb3twp02.amd.com (Axway MailGate 3.8.1) + with ESMTP id 21D3FC814C; Thu, 12 Apr 2012 11:30:50 -0500 (CDT) +Original-Received: from SAUSEXDAG01.amd.com (163.181.55.1) by sausexedgep01.amd.com + (163.181.36.54) with Microsoft SMTP Server (TLS) id 8.3.192.1; Thu, 12 Apr + 2012 11:31:09 -0500 +Original-Received: from storexhtp02.amd.com (172.24.4.4) by sausexdag01.amd.com + (163.181.55.1) with Microsoft SMTP Server (TLS) id 14.1.323.3; Thu, 12 Apr + 2012 11:30:54 -0500 +Original-Received: from gwo.osrc.amd.com (165.204.16.204) by storexhtp02.amd.com + (172.24.4.4) with Microsoft SMTP Server id 8.3.213.0; Thu, 12 Apr 2012 + 12:30:51 -0400 +Original-Received: from aftab (aftab.osrc.amd.com [165.204.15.109]) by gwo.osrc.amd.com + (Postfix) with ESMTP id 0D00D49C58B; Thu, 12 Apr 2012 17:30:50 +0100 (BST) +Content-Disposition: inline +In-Reply-To: <20120412162351.GJ24549@aftab> +User-Agent: Mutt/1.5.21 (2010-09-15) +X-OriginatorOrg: amd.com +Original-Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel:1281049 +Archived-At: + +From: Andreas Herrmann +Date: Thu, 12 Apr 2012 16:48:01 +0200 +Subject: [PATCH 1/2] x86, microcode: Fix sysfs warning during module unload on unsupported CPUs + +Loading microcode driver on an unsupported CPU and subsequently +unloading the driver causes + + WARNING: at fs/sysfs/group.c:138 mc_device_remove+0x5f/0x70 [microcode]() + Hardware name: 01972NG + sysfs group ffffffffa00013d0 not found for kobject 'cpu0' + Modules linked in: snd_hda_codec_hdmi snd_hda_codec_conexant snd_hda_intel btusb snd_hda_codec bluetooth thinkpad_acpi rfkill microcode(-) [last unloaded: cfg80211] + Pid: 4560, comm: modprobe Not tainted 3.4.0-rc2-00002-g258f742 #5 + Call Trace: + [] ? warn_slowpath_common+0x7b/0xc0 + [] ? warn_slowpath_fmt+0x45/0x50 + [] ? sysfs_remove_group+0x34/0x120 + [] ? mc_device_remove+0x5f/0x70 [microcode] + [] ? subsys_interface_unregister+0x69/0xa0 + [] ? mutex_lock+0x16/0x40 + [] ? microcode_exit+0x50/0x92 [microcode] + [] ? sys_delete_module+0x16d/0x260 + [] ? wait_iff_congested+0x45/0x110 + [] ? page_fault+0x1f/0x30 + [] ? system_call_fastpath+0x16/0x1b + +on recent kernels. + +This is due to + + commit 8a25a2fd126c621f44f3aeaef80d51f00fc11639 + (cpu: convert 'cpu' and 'machinecheck' sysdev_class to a regular + subsystem) + +which renders + + commit 6c53cbfced048c421e4f72cb2183465f68fbc5e7 + (x86, microcode: Correct sysdev_add error path) + +useless. + +See http://marc.info/?l=linux-kernel&m=133416246406478 + +Avoid above warning by restoring the old driver behaviour before +commit 6c53cbfced048c421e4f72cb2183465f68fbc5e7 (x86, microcode: +Correct sysdev_add error path) + +Cc: stable@vger.kernel.org +Cc: Tigran Aivazian +Cc: Borislav Petkov +Signed-off-by: Andreas Herrmann +--- + arch/x86/kernel/microcode_core.c | 4 +--- + 1 files changed, 1 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c +index 87a0f86..d389e74 100644 +--- a/arch/x86/kernel/microcode_core.c ++++ b/arch/x86/kernel/microcode_core.c +@@ -419,10 +419,8 @@ static int mc_device_add(struct device *dev, struct subsys_interface *sif) + if (err) + return err; + +- if (microcode_init_cpu(cpu) == UCODE_ERROR) { +- sysfs_remove_group(&dev->kobj, &mc_attr_group); ++ if (microcode_init_cpu(cpu) == UCODE_ERROR) + return -EINVAL; +- } + + return err; + } +-- +1.7.8.4 + +-- +Regards/Gruss, +Boris. + +Advanced Micro Devices GmbH +Einsteinring 24, 85609 Dornach +GM: Alberto Bozzo +Reg: Dornach, Landkreis Muenchen +HRB Nr. 43632 WEEE Registernr: 129 19551 + From 0f21eed9f45988ca2416c02f4008c542b6afb7dd Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 17 Apr 2012 11:12:10 -0400 Subject: [PATCH 368/397] Add "# END OF PATCH DEFINITIONS" tag (rhbz 811777) --- kernel.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel.spec b/kernel.spec index 57a731a05..7652893e5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -709,6 +709,8 @@ Patch21701: x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CP Patch22000: weird-root-dentry-name-debug.patch +# END OF PATCH DEFINITIONS + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root From 58daa350240ff0f2ecc244104bdca61e0c7b8dbe Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 17 Apr 2012 12:43:28 -0400 Subject: [PATCH 369/397] Fix oops in nfs_have_delegation (rhbz 811138) --- ...nups-for-nfs4_handle_exception-and-n.patch | 51 +++++++++++++++++++ kernel.spec | 5 +- 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch diff --git a/NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch b/NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch new file mode 100644 index 000000000..105235126 --- /dev/null +++ b/NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch @@ -0,0 +1,51 @@ +From 14977489ffdb80d4caf5a184ba41b23b02fbacd9 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Tue, 27 Mar 2012 18:31:25 -0400 +Subject: [PATCH] NFSv4: Minor cleanups for nfs4_handle_exception and + nfs4_async_handle_error + +Signed-off-by: Trond Myklebust +--- + fs/nfs/nfs4proc.c | 10 +++++----- + 1 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index 1933e67..f82bde0 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -270,7 +270,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc + case 0: + return 0; + case -NFS4ERR_OPENMODE: +- if (nfs_have_delegation(inode, FMODE_READ)) { ++ if (inode && nfs_have_delegation(inode, FMODE_READ)) { + nfs_inode_return_delegation(inode); + exception->retry = 1; + return 0; +@@ -282,10 +282,9 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc + case -NFS4ERR_DELEG_REVOKED: + case -NFS4ERR_ADMIN_REVOKED: + case -NFS4ERR_BAD_STATEID: +- if (state != NULL) +- nfs_remove_bad_delegation(state->inode); + if (state == NULL) + break; ++ nfs_remove_bad_delegation(state->inode); + nfs4_schedule_stateid_recovery(server, state); + goto wait_on_recovery; + case -NFS4ERR_EXPIRED: +@@ -3825,8 +3824,9 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, + case -NFS4ERR_DELEG_REVOKED: + case -NFS4ERR_ADMIN_REVOKED: + case -NFS4ERR_BAD_STATEID: +- if (state != NULL) +- nfs_remove_bad_delegation(state->inode); ++ if (state == NULL) ++ break; ++ nfs_remove_bad_delegation(state->inode); + case -NFS4ERR_OPENMODE: + if (state == NULL) + break; +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index 7652893e5..7f7fb2f57 100644 --- a/kernel.spec +++ b/kernel.spec @@ -639,6 +639,7 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 Patch4000: NFSv4-Reduce-the-footprint-of-the-idmapper.patch Patch4001: NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch +Patch4107: NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch # patches headed upstream @@ -1162,7 +1163,8 @@ ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 ApplyPatch NFSv4-Reduce-the-footprint-of-the-idmapper.patch ApplyPatch NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch - +ApplyPatch NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch + # USB # WMI @@ -1964,6 +1966,7 @@ fi %changelog * Tue Apr 17 2012 Josh Boyer +- Fix oops in nfs_have_delegation (rhbz 811138) - Fix oops on invalid AMD microcode load (rhbz 797559) * Sat Apr 14 2012 Josh Boyer From e417ace608ad628741e22ad5e32aa58e8e497f69 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 18 Apr 2012 09:49:29 -0400 Subject: [PATCH 370/397] Disable CONFIG_HID_BATTERY_STRENGTH (rhbz 806295) --- disable-hid-battery.patch | 11 +++++++++++ kernel.spec | 11 ++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 disable-hid-battery.patch diff --git a/disable-hid-battery.patch b/disable-hid-battery.patch new file mode 100644 index 000000000..98fe2139e --- /dev/null +++ b/disable-hid-battery.patch @@ -0,0 +1,11 @@ +--- linux-2.6.43.noarch.orig/drivers/hid/Kconfig ++++ linux-2.6.43.noarch/drivers/hid/Kconfig +@@ -34,7 +34,7 @@ config HID + config HID_BATTERY_STRENGTH + bool + depends on HID && POWER_SUPPLY && HID = POWER_SUPPLY +- default y ++ default n + + config HIDRAW + bool "/dev/hidraw raw HID device support" diff --git a/kernel.spec b/kernel.spec index 7f7fb2f57..c6112c3b1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -708,6 +708,9 @@ Patch21530: ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch Patch21700: x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch Patch21701: x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch +#rhbz 806295 +Patch21710: disable-hid-battery.patch + Patch22000: weird-root-dentry-name-debug.patch # END OF PATCH DEFINITIONS @@ -1313,6 +1316,9 @@ ApplyPatch x86-Use-correct-byte-sized-register-constraint-in-__add.patch ApplyPatch x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch ApplyPatch x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch +#rhbz 806295 +ApplyPatch disable-hid-battery.patch + # END OF PATCH APPLICATIONS %endif @@ -1965,6 +1971,9 @@ fi # and build. %changelog +* Wed Apr 18 2012 Josh Boyer +- Disable CONFIG_HID_BATTERY_STRENGTH (rhbz 806295) + * Tue Apr 17 2012 Josh Boyer - Fix oops in nfs_have_delegation (rhbz 811138) - Fix oops on invalid AMD microcode load (rhbz 797559) From 735ab180711108a49c5c59fe9e1d98d2ecb7ea52 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 18 Apr 2012 13:54:46 -0400 Subject: [PATCH 371/397] Change patch to resolve libata hotplug (rhbz 807632) --- kernel.spec | 9 +- ...ble-runtime-pm-for-hotpluggable-port.patch | 180 ------------------ ...ta-forbid-port-runtime-pm-by-default.patch | 24 +++ 3 files changed, 29 insertions(+), 184 deletions(-) delete mode 100644 libata-disable-runtime-pm-for-hotpluggable-port.patch create mode 100644 libata-forbid-port-runtime-pm-by-default.patch diff --git a/kernel.spec b/kernel.spec index c6112c3b1..bb8d21ce9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -692,8 +692,8 @@ Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch #rhbz 808603 Patch21380: wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch -#rhbz 806676 807632 -Patch21385: libata-disable-runtime-pm-for-hotpluggable-port.patch +#rhbz 807632 +Patch21385: libata-forbid-port-runtime-pm-by-default.patch #rhbz 809014 Patch21390: x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch @@ -1305,8 +1305,8 @@ ApplyPatch iwlwifi-do-not-nulify-ctx-vif-on-reset.patch #rhbz 808603 ApplyPatch wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch -#rhbz 806676 807632 -ApplyPatch libata-disable-runtime-pm-for-hotpluggable-port.patch +#rhbz 807632 +ApplyPatch libata-forbid-port-runtime-pm-by-default.patch #rhbz 809014 ApplyPatch x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch @@ -1972,6 +1972,7 @@ fi %changelog * Wed Apr 18 2012 Josh Boyer +- Change patch to resolve libata hotplug (rhbz 807632) - Disable CONFIG_HID_BATTERY_STRENGTH (rhbz 806295) * Tue Apr 17 2012 Josh Boyer diff --git a/libata-disable-runtime-pm-for-hotpluggable-port.patch b/libata-disable-runtime-pm-for-hotpluggable-port.patch deleted file mode 100644 index 06020fdde..000000000 --- a/libata-disable-runtime-pm-for-hotpluggable-port.patch +++ /dev/null @@ -1,180 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Lin Ming -Newsgroups: gmane.linux.ide,gmane.linux.kernel -Subject: [PATCH v2] libata: disable runtime pm for hotpluggable port -Date: Tue, 13 Mar 2012 09:57:37 +0800 -Lines: 131 -Approved: news@gmane.org -Message-ID: <1331603857.3436.24.camel@minggr> -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset="UTF-8" -Content-Transfer-Encoding: 7bit -X-Trace: dough.gmane.org 1331603865 12388 80.91.229.3 (13 Mar 2012 01:57:45 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Tue, 13 Mar 2012 01:57:45 +0000 (UTC) -Cc: linux-ide@vger.kernel.org, lkml , - jslaby@suse.cz, cwillu@cwillu.com, jackdachef@gmail.com, - Sergei Shtylyov -To: Jeff Garzik -Original-X-From: linux-ide-owner@vger.kernel.org Tue Mar 13 02:57:43 2012 -Return-path: -Envelope-to: lnx-linux-ide@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1S7Gze-0005pE-Sg - for lnx-linux-ide@plane.gmane.org; Tue, 13 Mar 2012 02:57:43 +0100 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1754650Ab2CMB5l (ORCPT ); - Mon, 12 Mar 2012 21:57:41 -0400 -Original-Received: from mga14.intel.com ([143.182.124.37]:15186 "EHLO mga14.intel.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1754582Ab2CMB5k (ORCPT ); - Mon, 12 Mar 2012 21:57:40 -0400 -Original-Received: from azsmga002.ch.intel.com ([10.2.17.35]) - by azsmga102.ch.intel.com with ESMTP; 12 Mar 2012 18:57:39 -0700 -X-ExtLoop1: 1 -X-IronPort-AV: E=Sophos;i="4.71,315,1320652800"; - d="scan'208";a="76719701" -Original-Received: from minggr.sh.intel.com (HELO [10.239.36.45]) ([10.239.36.45]) - by AZSMGA002.ch.intel.com with ESMTP; 12 Mar 2012 18:57:38 -0700 -X-Mailer: Evolution 2.30.3 -Original-Sender: linux-ide-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-ide@vger.kernel.org -Xref: news.gmane.org gmane.linux.ide:51560 gmane.linux.kernel:1266262 -Archived-At: - -Currently, hotplug doesn't work if port is already runtime suspended. -For now, we simply disable runtime pm for hotpluggable port. -Later, we should add runtime pm support for hotpluggable port too. - -Bug report: -https://lkml.org/lkml/2012/2/19/70 - -v2: -- Use bit 2 and 3 for flags ATA_FLAG_EXTERNAL and ATA_FLAG_PLUGGABLE. - -TODO: add similar hotpluggable port check for controllers other than -AHCI. - -Reported-and-tested-by: Jiri Slaby -Reported-and-tested-by: cwillu@cwillu.com -Reported-and-tested-by: jackdachef@gmail.com -Signed-off-by: Lin Ming ---- - drivers/ata/ahci.c | 3 +++ - drivers/ata/ahci.h | 3 +++ - drivers/ata/libahci.c | 20 ++++++++++++++++++++ - drivers/ata/libata-transport.c | 6 ++++-- - include/linux/libata.h | 2 ++ - 5 files changed, 32 insertions(+), 2 deletions(-) - -diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c -index d07bf03..02e93ff 100644 ---- a/drivers/ata/ahci.c -+++ b/drivers/ata/ahci.c -@@ -1145,6 +1145,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) - if (hpriv->cap & HOST_CAP_PMP) - pi.flags |= ATA_FLAG_PMP; - -+ if (hpriv->cap & HOST_CAP_SXS) -+ pi.flags |= ATA_FLAG_EXTERNAL; -+ - ahci_set_em_messages(hpriv, &pi); - - if (ahci_broken_system_poweroff(pdev)) { -diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h -index b175000..92f7172 100644 ---- a/drivers/ata/ahci.h -+++ b/drivers/ata/ahci.h -@@ -172,6 +172,9 @@ enum { - PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */ - PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ - PORT_CMD_FBSCP = (1 << 22), /* FBS Capable Port */ -+ PORT_CMD_ESP = (1 << 21), /* External SATA Port */ -+ PORT_CMD_MPSP = (1 << 19), /* Mechanical Presence Switch Attached to Port */ -+ PORT_CMD_HPCP = (1 << 18), /* Hot Plug Capable Port */ - PORT_CMD_PMP = (1 << 17), /* PMP attached */ - PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ - PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ -diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c -index a72bfd0..7d72d3c 100644 ---- a/drivers/ata/libahci.c -+++ b/drivers/ata/libahci.c -@@ -1097,6 +1097,23 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap, - writel(1 << port_no, mmio + HOST_IRQ_STAT); - } - -+static bool ahci_port_pluggable(struct ata_port *ap) -+{ -+ void __iomem *port_mmio = ahci_port_base(ap); -+ u32 cmd; -+ -+ cmd = readl(port_mmio + PORT_CMD); -+ -+ if ((ap->flags & ATA_FLAG_EXTERNAL) && -+ (cmd & PORT_CMD_ESP)) -+ return true; -+ -+ if (cmd & (PORT_CMD_MPSP | PORT_CMD_HPCP)) -+ return true; -+ -+ return false; -+} -+ - void ahci_init_controller(struct ata_host *host) - { - struct ahci_host_priv *hpriv = host->private_data; -@@ -1112,6 +1129,9 @@ void ahci_init_controller(struct ata_host *host) - if (ata_port_is_dummy(ap)) - continue; - -+ if (ahci_port_pluggable(ap)) -+ ap->flags |= ATA_FLAG_PLUGGABLE; -+ - ahci_port_init(host->dev, ap, i, mmio, port_mmio); - } - -diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c -index 74aaee3..a7166b9 100644 ---- a/drivers/ata/libata-transport.c -+++ b/drivers/ata/libata-transport.c -@@ -292,8 +292,10 @@ int ata_tport_add(struct device *parent, - } - - device_enable_async_suspend(dev); -- pm_runtime_set_active(dev); -- pm_runtime_enable(dev); -+ if (!(ap->flags & ATA_FLAG_PLUGGABLE)) { -+ pm_runtime_set_active(dev); -+ pm_runtime_enable(dev); -+ } - - transport_add_device(dev); - transport_configure_device(dev); -diff --git a/include/linux/libata.h b/include/linux/libata.h -index cafc09a..f46961d 100644 ---- a/include/linux/libata.h -+++ b/include/linux/libata.h -@@ -187,6 +187,8 @@ enum { - ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ - /* (doesn't imply presence) */ - ATA_FLAG_SATA = (1 << 1), -+ ATA_FLAG_EXTERNAL = (1 << 2), /* Controller supports external SATA */ -+ ATA_FLAG_PLUGGABLE = (1 << 3), /* Port is hotpluggable */ - ATA_FLAG_NO_ATAPI = (1 << 6), /* No ATAPI support */ - ATA_FLAG_PIO_DMA = (1 << 7), /* PIO cmds via DMA */ - ATA_FLAG_PIO_LBA48 = (1 << 8), /* Host DMA engine is LBA28 only */ --- -1.7.2.5 - - - --- -To unsubscribe from this list: send the line "unsubscribe linux-ide" 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/libata-forbid-port-runtime-pm-by-default.patch b/libata-forbid-port-runtime-pm-by-default.patch new file mode 100644 index 000000000..0d93a19f5 --- /dev/null +++ b/libata-forbid-port-runtime-pm-by-default.patch @@ -0,0 +1,24 @@ +From: Lin Ming +Date: Wed, 18 Apr 2012 09:13:41 +0800 +Subject: [PATCH] libata: forbid port runtime pm by default + +Forbid port runtime pm by default because it has known hotplug issue. +User can allow it by, for example + +echo auto > /sys/devices/pci0000:00/0000:00:1f.2/ata2/power/control + +Signed-off-by: Lin Ming +--- + drivers/ata/libata-transport.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +--- linux-3.3.noarch.orig/drivers/ata/libata-transport.c ++++ linux-3.3.noarch/drivers/ata/libata-transport.c +@@ -294,6 +294,7 @@ int ata_tport_add(struct device *parent, + device_enable_async_suspend(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); ++ pm_runtime_forbid(dev); + + transport_add_device(dev); + transport_configure_device(dev); From 0f5390a921397662030bbe3d4b0578c6ec12be5f Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 19 Apr 2012 09:56:27 -0500 Subject: [PATCH 372/397] Fix KVM device assignment page leak --- ...rom-the-iommu-when-slots-are-removed.patch | 92 +++++++++++++++++++ kernel.spec | 9 ++ 2 files changed, 101 insertions(+) create mode 100644 KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch diff --git a/KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch b/KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch new file mode 100644 index 000000000..b98e392f7 --- /dev/null +++ b/KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch @@ -0,0 +1,92 @@ +commit 32f6daad4651a748a58a3ab6da0611862175722f +Author: Alex Williamson +Date: Wed Apr 11 09:51:49 2012 -0600 + + KVM: unmap pages from the iommu when slots are removed + + We've been adding new mappings, but not destroying old mappings. + This can lead to a page leak as pages are pinned using + get_user_pages, but only unpinned with put_page if they still + exist in the memslots list on vm shutdown. A memslot that is + destroyed while an iommu domain is enabled for the guest will + therefore result in an elevated page reference count that is + never cleared. + + Additionally, without this fix, the iommu is only programmed + with the first translation for a gpa. This can result in + peer-to-peer errors if a mapping is destroyed and replaced by a + new mapping at the same gpa as the iommu will still be pointing + to the original, pinned memory address. + + Signed-off-by: Alex Williamson + Signed-off-by: Marcelo Tosatti + +diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h +index 665a260..72cbf08 100644 +--- a/include/linux/kvm_host.h ++++ b/include/linux/kvm_host.h +@@ -596,6 +596,7 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id); + + #ifdef CONFIG_IOMMU_API + int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot); ++void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot); + int kvm_iommu_map_guest(struct kvm *kvm); + int kvm_iommu_unmap_guest(struct kvm *kvm); + int kvm_assign_device(struct kvm *kvm, +@@ -609,6 +610,11 @@ static inline int kvm_iommu_map_pages(struct kvm *kvm, + return 0; + } + ++static inline void kvm_iommu_unmap_pages(struct kvm *kvm, ++ struct kvm_memory_slot *slot) ++{ ++} ++ + static inline int kvm_iommu_map_guest(struct kvm *kvm) + { + return -ENODEV; +diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c +index a457d21..fec1723 100644 +--- a/virt/kvm/iommu.c ++++ b/virt/kvm/iommu.c +@@ -310,6 +310,11 @@ static void kvm_iommu_put_pages(struct kvm *kvm, + } + } + ++void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot) ++{ ++ kvm_iommu_put_pages(kvm, slot->base_gfn, slot->npages); ++} ++ + static int kvm_iommu_unmap_memslots(struct kvm *kvm) + { + int idx; +@@ -320,7 +325,7 @@ static int kvm_iommu_unmap_memslots(struct kvm *kvm) + slots = kvm_memslots(kvm); + + kvm_for_each_memslot(memslot, slots) +- kvm_iommu_put_pages(kvm, memslot->base_gfn, memslot->npages); ++ kvm_iommu_unmap_pages(kvm, memslot); + + srcu_read_unlock(&kvm->srcu, idx); + +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index 42b7393..9739b53 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -808,12 +808,13 @@ int __kvm_set_memory_region(struct kvm *kvm, + if (r) + goto out_free; + +- /* map the pages in iommu page table */ ++ /* map/unmap the pages in iommu page table */ + if (npages) { + r = kvm_iommu_map_pages(kvm, &new); + if (r) + goto out_free; +- } ++ } else ++ kvm_iommu_unmap_pages(kvm, &old); + + r = -ENOMEM; + slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots), diff --git a/kernel.spec b/kernel.spec index bb8d21ce9..f99aac745 100644 --- a/kernel.spec +++ b/kernel.spec @@ -713,6 +713,9 @@ Patch21710: disable-hid-battery.patch Patch22000: weird-root-dentry-name-debug.patch +#rhbz 814149 814155 +Patch22006: KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch + # END OF PATCH DEFINITIONS %endif @@ -1319,6 +1322,9 @@ ApplyPatch x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPU #rhbz 806295 ApplyPatch disable-hid-battery.patch +#rhbz 814149 814155 +ApplyPatch KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch + # END OF PATCH APPLICATIONS %endif @@ -1971,6 +1977,9 @@ fi # and build. %changelog +* Thu Apr 19 2012 Justin M. Forbes +- Fix KVM device assignment page leak (rhbz 814149 814155) + * Wed Apr 18 2012 Josh Boyer - Change patch to resolve libata hotplug (rhbz 807632) - Disable CONFIG_HID_BATTERY_STRENGTH (rhbz 806295) From c54adc8eef24dda29209d52a9f382b1680fba4a3 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 19 Apr 2012 16:27:40 -0500 Subject: [PATCH 373/397] CVE-2012-2119 macvtap: zerocopy: vector length is not validated before pinning user pages (rhbz 814278 814289) --- kernel.spec | 14 +++++++++-- macvtap-zerocopy-validate-vector-length.patch | 25 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 macvtap-zerocopy-validate-vector-length.patch diff --git a/kernel.spec b/kernel.spec index f99aac745..9b390bc5f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -713,9 +713,12 @@ Patch21710: disable-hid-battery.patch Patch22000: weird-root-dentry-name-debug.patch -#rhbz 814149 814155 +#rhbz 814149 814155 CVE-2012-2121 Patch22006: KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch +#rhbz 814278 814289 CVE-2012-2119 +Patch22007: macvtap-zerocopy-validate-vector-length.patch + # END OF PATCH DEFINITIONS %endif @@ -1322,9 +1325,12 @@ ApplyPatch x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPU #rhbz 806295 ApplyPatch disable-hid-battery.patch -#rhbz 814149 814155 +#rhbz 814149 814155 CVE-2012-2121 ApplyPatch KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch +#rhbz 814278 814289 CVE-2012-2119 +ApplyPatch macvtap-zerocopy-validate-vector-length.patch + # END OF PATCH APPLICATIONS %endif @@ -1977,6 +1983,10 @@ fi # and build. %changelog +* Thu Apr 19 2012 Justin M. Forbes 2.6.43.2-4 +- CVE-2012-2119 macvtap: zerocopy: vector length is not validated before + pinning user pages (rhbz 814278 814289) + * Thu Apr 19 2012 Justin M. Forbes - Fix KVM device assignment page leak (rhbz 814149 814155) diff --git a/macvtap-zerocopy-validate-vector-length.patch b/macvtap-zerocopy-validate-vector-length.patch new file mode 100644 index 000000000..3ac31e4b6 --- /dev/null +++ b/macvtap-zerocopy-validate-vector-length.patch @@ -0,0 +1,25 @@ +Currently we do not validate the vector length before calling +get_user_pages_fast(), host stack would be easily overflowed by +malicious guest driver who give us a descriptor with length greater +than MAX_SKB_FRAGS. Solve this problem by checking the free entries +before trying to pin user pages. + +Signed-off-by: Jason Wang +--- + drivers/net/macvtap.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c +index 7cb2684..d197a78 100644 +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -527,6 +527,8 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, + } + base = (unsigned long)from->iov_base + offset1; + size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT; ++ if (i + size >= MAX_SKB_FRAGS) ++ return -EFAULT; + num_pages = get_user_pages_fast(base, size, 0, &page[i]); + if ((num_pages != size) || + (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags)) + From d4c69c56b03ed56b81899a6587b710fb271d5d5f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 20 Apr 2012 08:28:25 -0400 Subject: [PATCH 374/397] CVE-2012-2123 fcaps: clear the same personality flags as suid when fcaps are used (rhbz 814523 806722) --- ...same-personality-flags-as-suid-when-.patch | 38 +++++++++++++++++++ kernel.spec | 14 ++++++- ...ity-fix-compile-error-in-commoncap.c.patch | 28 ++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 fcaps-clear-the-same-personality-flags-as-suid-when-.patch create mode 100644 security-fix-compile-error-in-commoncap.c.patch diff --git a/fcaps-clear-the-same-personality-flags-as-suid-when-.patch b/fcaps-clear-the-same-personality-flags-as-suid-when-.patch new file mode 100644 index 000000000..1cf2ac208 --- /dev/null +++ b/fcaps-clear-the-same-personality-flags-as-suid-when-.patch @@ -0,0 +1,38 @@ +From d52fc5dde171f030170a6cb78034d166b13c9445 Mon Sep 17 00:00:00 2001 +From: Eric Paris +Date: Tue, 17 Apr 2012 16:26:54 -0400 +Subject: [PATCH] fcaps: clear the same personality flags as suid when fcaps + are used + +If a process increases permissions using fcaps all of the dangerous +personality flags which are cleared for suid apps should also be cleared. +Thus programs given priviledge with fcaps will continue to have address space +randomization enabled even if the parent tried to disable it to make it +easier to attack. + +Signed-off-by: Eric Paris +Reviewed-by: Serge Hallyn +Signed-off-by: James Morris +--- + security/commoncap.c | 5 +++++ + 1 files changed, 5 insertions(+), 0 deletions(-) + +diff --git a/security/commoncap.c b/security/commoncap.c +index 0cf4b53..0ecf4ba 100644 +--- a/security/commoncap.c ++++ b/security/commoncap.c +@@ -505,6 +505,11 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) + } + skip: + ++ /* if we have fs caps, clear dangerous personality flags */ ++ if (!cap_issubset(new->cap_permitted, old->cap_permitted)) ++ bprm->per_clear |= PER_CLEAR_ON_SETID; ++ ++ + /* Don't let someone trace a set[ug]id/setpcap binary with the revised + * credentials unless they have the appropriate permit + */ +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index 9b390bc5f..8c9c8657b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -719,6 +719,10 @@ Patch22006: KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch #rhbz 814278 814289 CVE-2012-2119 Patch22007: macvtap-zerocopy-validate-vector-length.patch +#rhbz 814523 806722 CVE-2012-2123 +Patch22008: fcaps-clear-the-same-personality-flags-as-suid-when-.patch +Patch22009: security-fix-compile-error-in-commoncap.c.patch + # END OF PATCH DEFINITIONS %endif @@ -1331,6 +1335,10 @@ ApplyPatch KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch #rhbz 814278 814289 CVE-2012-2119 ApplyPatch macvtap-zerocopy-validate-vector-length.patch +#rhbz 814523 806722 CVE-2012-2123 +ApplyPatch fcaps-clear-the-same-personality-flags-as-suid-when-.patch +ApplyPatch security-fix-compile-error-in-commoncap.c.patch + # END OF PATCH APPLICATIONS %endif @@ -1983,6 +1991,10 @@ fi # and build. %changelog +* Fri Apr 20 2012 Josh Boyer +- CVE-2012-2123 fcaps: clear the same personality flags as suid when fcaps + are used (rhbz 814523 806722) + * Thu Apr 19 2012 Justin M. Forbes 2.6.43.2-4 - CVE-2012-2119 macvtap: zerocopy: vector length is not validated before pinning user pages (rhbz 814278 814289) diff --git a/security-fix-compile-error-in-commoncap.c.patch b/security-fix-compile-error-in-commoncap.c.patch new file mode 100644 index 000000000..de333e219 --- /dev/null +++ b/security-fix-compile-error-in-commoncap.c.patch @@ -0,0 +1,28 @@ +From 51b79bee627d526199b2f6a6bef8ee0c0739b6d1 Mon Sep 17 00:00:00 2001 +From: Jonghwan Choi +Date: Wed, 18 Apr 2012 17:23:04 -0400 +Subject: [PATCH] security: fix compile error in commoncap.c + +Add missing "personality.h" +security/commoncap.c: In function 'cap_bprm_set_creds': +security/commoncap.c:510: error: 'PER_CLEAR_ON_SETID' undeclared (first use in this function) +security/commoncap.c:510: error: (Each undeclared identifier is reported only once +security/commoncap.c:510: error: for each function it appears in.) + +Signed-off-by: Jonghwan Choi +Acked-by: Serge Hallyn +Signed-off-by: James Morris +--- + security/commoncap.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +--- linux-3.3.2-6.fc17.noarch.orig/security/commoncap.c ++++ linux-3.3.2-6.fc17.noarch/security/commoncap.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + /* + * If a non-root user executes a setuid-root binary in From ffb669c977646f7e36ab368da99c25da5bc1b43f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sat, 21 Apr 2012 08:07:10 -0400 Subject: [PATCH 375/397] Fix error check in memblock that prevented boot on various Dells (rhbz 811225) --- kernel.spec | 11 +++- ...k-should-be-able-to-handle-zero-leng.patch | 63 +++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 memblock-memblock-should-be-able-to-handle-zero-leng.patch diff --git a/kernel.spec b/kernel.spec index 8c9c8657b..115d721c9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 5 +%global baserelease 6 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -723,6 +723,9 @@ Patch22007: macvtap-zerocopy-validate-vector-length.patch Patch22008: fcaps-clear-the-same-personality-flags-as-suid-when-.patch Patch22009: security-fix-compile-error-in-commoncap.c.patch +#rhbz 811225 +Patch22010: memblock-memblock-should-be-able-to-handle-zero-leng.patch + # END OF PATCH DEFINITIONS %endif @@ -1339,6 +1342,9 @@ ApplyPatch macvtap-zerocopy-validate-vector-length.patch ApplyPatch fcaps-clear-the-same-personality-flags-as-suid-when-.patch ApplyPatch security-fix-compile-error-in-commoncap.c.patch +#rhbz 811225 +ApplyPatch memblock-memblock-should-be-able-to-handle-zero-leng.patch + # END OF PATCH APPLICATIONS %endif @@ -1991,6 +1997,9 @@ fi # and build. %changelog +* Sat Apr 21 2012 Josh Boyer - 2.6.43.2-6 +- Fix error check in memblock that prevented boot on various Dells (rhbz 811225) + * Fri Apr 20 2012 Josh Boyer - CVE-2012-2123 fcaps: clear the same personality flags as suid when fcaps are used (rhbz 814523 806722) diff --git a/memblock-memblock-should-be-able-to-handle-zero-leng.patch b/memblock-memblock-should-be-able-to-handle-zero-leng.patch new file mode 100644 index 000000000..08e364534 --- /dev/null +++ b/memblock-memblock-should-be-able-to-handle-zero-leng.patch @@ -0,0 +1,63 @@ +From b3dc627cabb33fc95f93da78457770c1b2a364d2 Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Fri, 20 Apr 2012 08:31:34 -0700 +Subject: [PATCH] memblock: memblock should be able to handle zero length + operations + +Commit 24aa07882b ("memblock, x86: Replace memblock_x86_reserve/ +free_range() with generic ones") replaced x86 specific memblock +operations with the generic ones; unfortunately, it lost zero length +operation handling in the process making the kernel panic if somebody +tries to reserve zero length area. + +There isn't much to be gained by being cranky to zero length operations +and panicking is almost the worst response. Drop the BUG_ON() in +memblock_reserve() and update memblock_add_region/isolate_range() so +that all zero length operations are handled as noops. + +Signed-off-by: Tejun Heo +Cc: stable@vger.kernel.org +Reported-by: Valere Monseur +Bisected-by: Joseph Freeman +Tested-by: Joseph Freeman +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=43098 +Signed-off-by: Linus Torvalds +--- + mm/memblock.c | 7 ++++++- + 1 files changed, 6 insertions(+), 1 deletions(-) + +diff --git a/mm/memblock.c b/mm/memblock.c +index 99f2855..a44eab3 100644 +--- a/mm/memblock.c ++++ b/mm/memblock.c +@@ -330,6 +330,9 @@ static int __init_memblock memblock_add_region(struct memblock_type *type, + phys_addr_t end = base + memblock_cap_size(base, &size); + int i, nr_new; + ++ if (!size) ++ return 0; ++ + /* special case for empty array */ + if (type->regions[0].size == 0) { + WARN_ON(type->cnt != 1 || type->total_size); +@@ -430,6 +433,9 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, + + *start_rgn = *end_rgn = 0; + ++ if (!size) ++ return 0; ++ + /* we'll create at most two more regions */ + while (type->cnt + 2 > type->max) + if (memblock_double_array(type) < 0) +@@ -514,7 +520,6 @@ int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size) + (unsigned long long)base, + (unsigned long long)base + size, + (void *)_RET_IP_); +- BUG_ON(0 == size); + + return memblock_add_region(_rgn, base, size, MAX_NUMNODES); + } +-- +1.7.7.6 + From 11834d2d28b4f620737e58bbcfc2cdc2d0910fe4 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 23 Apr 2012 16:50:35 +1000 Subject: [PATCH 376/397] Fix regression on clickpads --- ...gression-with-image-sensor-trackpads.patch | 38 +++++++++++++++++++ kernel.spec | 9 ++++- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 input-synaptics-fix-regression-with-image-sensor-trackpads.patch diff --git a/input-synaptics-fix-regression-with-image-sensor-trackpads.patch b/input-synaptics-fix-regression-with-image-sensor-trackpads.patch new file mode 100644 index 000000000..6c1542b7c --- /dev/null +++ b/input-synaptics-fix-regression-with-image-sensor-trackpads.patch @@ -0,0 +1,38 @@ +From 899c612d74d4a242158a4db20367388d6299c028 Mon Sep 17 00:00:00 2001 +From: Benjamin Herrenschmidt +Date: Fri, 20 Apr 2012 22:34:49 -0700 +Subject: [PATCH] Input: synaptics - fix regression with "image sensor" + trackpads + +commit 7968a5dd492ccc38345013e534ad4c8d6eb60ed1 +Input: synaptics - add support for Relative mode + +Accidentally broke support for advanced gestures (multitouch) +on some trackpads such as the one in my ThinkPad X220 by +incorretly changing the condition for enabling them. This +restores it. + +Signed-off-by: Benjamin Herrenschmidt +CC: stable@kernel.org [3.3] +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/synaptics.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c +index 8081a0a..a4b14a4 100644 +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -274,7 +274,8 @@ static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) + static unsigned char param = 0xc8; + struct synaptics_data *priv = psmouse->private; + +- if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) ++ if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || ++ SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c))) + return 0; + + if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL)) +-- +1.7.10 + diff --git a/kernel.spec b/kernel.spec index 115d721c9..4c130659d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 6 +%global baserelease 7 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -726,6 +726,8 @@ Patch22009: security-fix-compile-error-in-commoncap.c.patch #rhbz 811225 Patch22010: memblock-memblock-should-be-able-to-handle-zero-leng.patch +Patch22011: input-synaptics-fix-regression-with-image-sensor-trackpads.patch + # END OF PATCH DEFINITIONS %endif @@ -1345,6 +1347,8 @@ ApplyPatch security-fix-compile-error-in-commoncap.c.patch #rhbz 811225 ApplyPatch memblock-memblock-should-be-able-to-handle-zero-leng.patch +ApplyPatch input-synaptics-fix-regression-with-image-sensor-trackpads.patch + # END OF PATCH APPLICATIONS %endif @@ -1997,6 +2001,9 @@ fi # and build. %changelog +* Mon Apr 23 2012 Peter Hutterer +- Fix regression on clickpads + * Sat Apr 21 2012 Josh Boyer - 2.6.43.2-6 - Fix error check in memblock that prevented boot on various Dells (rhbz 811225) From 6b7781c7dda01815ff4d959df6a635f193e22f6c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 23 Apr 2012 10:51:58 -0400 Subject: [PATCH 377/397] Linux 3.3.3 --- ...-USB-device-13d3-3375-as-an-Atheros-.patch | 58 ------------------- ...same-personality-flags-as-suid-when-.patch | 38 ------------ kernel.spec | 25 ++------ ...ity-fix-compile-error-in-commoncap.c.patch | 28 --------- sources | 2 +- ...e-sized-register-constraint-in-__add.patch | 35 ----------- ...zed-register-constraint-in-__xchg_op.patch | 32 ---------- 7 files changed, 6 insertions(+), 212 deletions(-) delete mode 100644 Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch delete mode 100644 fcaps-clear-the-same-personality-flags-as-suid-when-.patch delete mode 100644 security-fix-compile-error-in-commoncap.c.patch delete mode 100644 x86-Use-correct-byte-sized-register-constraint-in-__add.patch delete mode 100644 x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch diff --git a/Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch b/Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch deleted file mode 100644 index f238d50da..000000000 --- a/Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 9498ba7a1d38d42eef4ef6d906ab1743c9f0fd6f Mon Sep 17 00:00:00 2001 -From: Eran -Date: Mon, 5 Dec 2011 22:15:29 +0000 -Subject: [PATCH] Bluetooth: Adding USB device 13d3:3375 as an Atheros AR3012. - -The bluetooth module in the Asus UX31/UX21 is based on Atheros AR3012 -and requires a firmware to be uploaded before it's usable. - -output of usb-devices for this module: -T: Bus=01 Lev=02 Prnt=02 Port=07 Cnt=03 Dev#= 6 Spd=12 MxCh= 0 -D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 -P: Vendor=13d3 ProdID=3375 Rev=00.02 -S: Manufacturer=Atheros Communications -S: Product=Bluetooth USB Host Controller -S: SerialNumber=Alaska Day 2006 -C: #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA -I: If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb -I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb - -Signed-off-by: Eran -Tested-by: Michal Labedzki -Signed-off-by: Gustavo F. Padovan - -diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c -index 4eca6e5..4844247 100644 ---- a/drivers/bluetooth/ath3k.c -+++ b/drivers/bluetooth/ath3k.c -@@ -72,6 +72,7 @@ static struct usb_device_id ath3k_table[] = { - - /* Atheros AR3012 with sflash firmware*/ - { USB_DEVICE(0x0CF3, 0x3004) }, -+ { USB_DEVICE(0x13d3, 0x3375) }, - - /* Atheros AR5BBU12 with sflash firmware */ - { USB_DEVICE(0x0489, 0xE02C) }, -@@ -88,6 +89,7 @@ static struct usb_device_id ath3k_blist_tbl[] = { - - /* Atheros AR3012 with sflash firmware*/ - { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, -+ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, - - { } /* Terminating entry */ - }; -diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c -index 22f695e..480cad9 100644 ---- a/drivers/bluetooth/btusb.c -+++ b/drivers/bluetooth/btusb.c -@@ -129,6 +129,7 @@ static struct usb_device_id blacklist_table[] = { - - /* Atheros 3012 with sflash firmware */ - { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, -+ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, - - /* Atheros AR5BBU12 with sflash firmware */ - { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, --- -1.7.7.6 - diff --git a/fcaps-clear-the-same-personality-flags-as-suid-when-.patch b/fcaps-clear-the-same-personality-flags-as-suid-when-.patch deleted file mode 100644 index 1cf2ac208..000000000 --- a/fcaps-clear-the-same-personality-flags-as-suid-when-.patch +++ /dev/null @@ -1,38 +0,0 @@ -From d52fc5dde171f030170a6cb78034d166b13c9445 Mon Sep 17 00:00:00 2001 -From: Eric Paris -Date: Tue, 17 Apr 2012 16:26:54 -0400 -Subject: [PATCH] fcaps: clear the same personality flags as suid when fcaps - are used - -If a process increases permissions using fcaps all of the dangerous -personality flags which are cleared for suid apps should also be cleared. -Thus programs given priviledge with fcaps will continue to have address space -randomization enabled even if the parent tried to disable it to make it -easier to attack. - -Signed-off-by: Eric Paris -Reviewed-by: Serge Hallyn -Signed-off-by: James Morris ---- - security/commoncap.c | 5 +++++ - 1 files changed, 5 insertions(+), 0 deletions(-) - -diff --git a/security/commoncap.c b/security/commoncap.c -index 0cf4b53..0ecf4ba 100644 ---- a/security/commoncap.c -+++ b/security/commoncap.c -@@ -505,6 +505,11 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) - } - skip: - -+ /* if we have fs caps, clear dangerous personality flags */ -+ if (!cap_issubset(new->cap_permitted, old->cap_permitted)) -+ bprm->per_clear |= PER_CLEAR_ON_SETID; -+ -+ - /* Don't let someone trace a set[ug]id/setpcap binary with the revised - * credentials unless they have the appropriate permit - */ --- -1.7.7.6 - diff --git a/kernel.spec b/kernel.spec index 4c130659d..97fbc4076 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 7 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 @@ -655,7 +655,6 @@ Patch14001: hibernate-watermark.patch Patch14010: lis3-improve-handling-of-null-rate.patch Patch15000: bluetooth-use-after-free.patch -Patch15001: Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch Patch20000: utrace.patch @@ -695,10 +694,6 @@ Patch21380: wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch #rhbz 807632 Patch21385: libata-forbid-port-runtime-pm-by-default.patch -#rhbz 809014 -Patch21390: x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch -Patch21391: x86-Use-correct-byte-sized-register-constraint-in-__add.patch - #rhbz 808207 CVE-2012-1601 Patch21520: KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch @@ -719,10 +714,6 @@ Patch22006: KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch #rhbz 814278 814289 CVE-2012-2119 Patch22007: macvtap-zerocopy-validate-vector-length.patch -#rhbz 814523 806722 CVE-2012-2123 -Patch22008: fcaps-clear-the-same-personality-flags-as-suid-when-.patch -Patch22009: security-fix-compile-error-in-commoncap.c.patch - #rhbz 811225 Patch22010: memblock-memblock-should-be-able-to-handle-zero-leng.patch @@ -1285,7 +1276,6 @@ ApplyPatch hibernate-watermark.patch ApplyPatch lis3-improve-handling-of-null-rate.patch ApplyPatch bluetooth-use-after-free.patch -ApplyPatch Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch # utrace. ApplyPatch utrace.patch @@ -1323,10 +1313,6 @@ ApplyPatch wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch #rhbz 807632 ApplyPatch libata-forbid-port-runtime-pm-by-default.patch -#rhbz 809014 -ApplyPatch x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch -ApplyPatch x86-Use-correct-byte-sized-register-constraint-in-__add.patch - #rhbz 797559 ApplyPatch x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch ApplyPatch x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch @@ -1340,10 +1326,6 @@ ApplyPatch KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch #rhbz 814278 814289 CVE-2012-2119 ApplyPatch macvtap-zerocopy-validate-vector-length.patch -#rhbz 814523 806722 CVE-2012-2123 -ApplyPatch fcaps-clear-the-same-personality-flags-as-suid-when-.patch -ApplyPatch security-fix-compile-error-in-commoncap.c.patch - #rhbz 811225 ApplyPatch memblock-memblock-should-be-able-to-handle-zero-leng.patch @@ -2001,6 +1983,9 @@ fi # and build. %changelog +* Mon Apr 23 2012 Josh Boyer +- Linux 3.3.3 + * Mon Apr 23 2012 Peter Hutterer - Fix regression on clickpads diff --git a/security-fix-compile-error-in-commoncap.c.patch b/security-fix-compile-error-in-commoncap.c.patch deleted file mode 100644 index de333e219..000000000 --- a/security-fix-compile-error-in-commoncap.c.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 51b79bee627d526199b2f6a6bef8ee0c0739b6d1 Mon Sep 17 00:00:00 2001 -From: Jonghwan Choi -Date: Wed, 18 Apr 2012 17:23:04 -0400 -Subject: [PATCH] security: fix compile error in commoncap.c - -Add missing "personality.h" -security/commoncap.c: In function 'cap_bprm_set_creds': -security/commoncap.c:510: error: 'PER_CLEAR_ON_SETID' undeclared (first use in this function) -security/commoncap.c:510: error: (Each undeclared identifier is reported only once -security/commoncap.c:510: error: for each function it appears in.) - -Signed-off-by: Jonghwan Choi -Acked-by: Serge Hallyn -Signed-off-by: James Morris ---- - security/commoncap.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - ---- linux-3.3.2-6.fc17.noarch.orig/security/commoncap.c -+++ linux-3.3.2-6.fc17.noarch/security/commoncap.c -@@ -28,6 +28,7 @@ - #include - #include - #include -+#include - - /* - * If a non-root user executes a setuid-root binary in diff --git a/sources b/sources index 413d6dc42..d1990b3af 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz -68907107b0f62a19608588bdb6b29e20 patch-3.3.2.xz +634a088d3789870885dc6ee1eb9627d4 patch-3.3.3.xz diff --git a/x86-Use-correct-byte-sized-register-constraint-in-__add.patch b/x86-Use-correct-byte-sized-register-constraint-in-__add.patch deleted file mode 100644 index 3ec765691..000000000 --- a/x86-Use-correct-byte-sized-register-constraint-in-__add.patch +++ /dev/null @@ -1,35 +0,0 @@ -From: H. Peter Anvin -Date: Fri, 6 Apr 2012 16:30:57 +0000 (-0700) -Subject: x86: Use correct byte-sized register constraint in __add() -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftip%2Ftip.git;a=commitdiff_plain;h=8c91c5325e107ec17e40a59a47c6517387d64eb7 - -x86: Use correct byte-sized register constraint in __add() - -Similar to: - - 2ca052a x86: Use correct byte-sized register constraint in __xchg_op() - -... the __add() macro also needs to use a "q" constraint in the -byte-sized case, lest we try to generate an illegal register. - -Link: http://lkml.kernel.org/r/4F7A3315.501@goop.org -Signed-off-by: H. Peter Anvin -Cc: Jeremy Fitzhardinge -Cc: Leigh Scott -Cc: Thomas Reitmayr -Cc: v3.3 ---- - -diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h -index bc18d0e..99480e5 100644 ---- a/arch/x86/include/asm/cmpxchg.h -+++ b/arch/x86/include/asm/cmpxchg.h -@@ -173,7 +173,7 @@ extern void __add_wrong_size(void) - switch (sizeof(*(ptr))) { \ - case __X86_CASE_B: \ - asm volatile (lock "addb %b1, %0\n" \ -- : "+m" (*(ptr)) : "ri" (inc) \ -+ : "+m" (*(ptr)) : "qi" (inc) \ - : "memory", "cc"); \ - break; \ - case __X86_CASE_W: \ diff --git a/x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch b/x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch deleted file mode 100644 index a33602f9f..000000000 --- a/x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Jeremy Fitzhardinge -Date: Mon, 2 Apr 2012 23:15:33 +0000 (-0700) -Subject: x86: Use correct byte-sized register constraint in __xchg_op() -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftip%2Ftip.git;a=commitdiff_plain;h=2ca052a3710fac208eee690faefdeb8bbd4586a1 - -x86: Use correct byte-sized register constraint in __xchg_op() - -x86-64 can access the low half of any register, but i386 can only do -it with a subset of registers. 'r' causes compilation failures on i386, -but 'q' expresses the constraint properly. - -Signed-off-by: Jeremy Fitzhardinge -Link: http://lkml.kernel.org/r/4F7A3315.501@goop.org -Reported-by: Leigh Scott -Tested-by: Thomas Reitmayr -Signed-off-by: H. Peter Anvin -Cc: v3.3 ---- - -diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h -index b3b7332..bc18d0e 100644 ---- a/arch/x86/include/asm/cmpxchg.h -+++ b/arch/x86/include/asm/cmpxchg.h -@@ -43,7 +43,7 @@ extern void __add_wrong_size(void) - switch (sizeof(*(ptr))) { \ - case __X86_CASE_B: \ - asm volatile (lock #op "b %b0, %1\n" \ -- : "+r" (__ret), "+m" (*(ptr)) \ -+ : "+q" (__ret), "+m" (*(ptr)) \ - : : "memory", "cc"); \ - break; \ - case __X86_CASE_W: \ From 0b9442a5b4b82051cae24a66581066ce11dca34c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 24 Apr 2012 08:47:28 -0400 Subject: [PATCH 378/397] Add patch to fix ipw2200 (rhbz 783708) --- ...n-the-command-completion-acknowledge.patch | 69 +++++++++++++++++++ kernel.spec | 11 ++- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch diff --git a/ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch b/ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch new file mode 100644 index 000000000..3b7451f9f --- /dev/null +++ b/ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch @@ -0,0 +1,69 @@ +Driver incorrectly validates command completion: instead of waiting +for a command to be acknowledged it continues execution. Most of the +time driver gets acknowledge of the command completion in a tasklet +before it executes the next one. But sometimes it sends the next +command before it gets acknowledge for the previous one. In such a +case one of the following error messages appear in the log: + +Failed to send SYSTEM_CONFIG: Already sending a command. +Failed to send ASSOCIATE: Already sending a command. +Failed to send TX_POWER: Already sending a command. + +After that you need to reload the driver to get it working again. + +This bug occurs during roammaping (reported by Sam Varshavchik) +https://bugzilla.redhat.com/show_bug.cgi?id=738508 +and machine booting (reported by Tom Gundersen and Mads Kiilerich) +https://bugs.archlinux.org/task/28097 +https://bugzilla.redhat.com/show_bug.cgi?id=802106 + +This patch doesn't fix the delay issue during firmware load. +But at least device now works as usual after boot. + +Cc: stable@kernel.org +Signed-off-by: Stanislav Yakovlev +--- + drivers/net/wireless/ipw2x00/ipw2200.c | 13 ++++++++++++- + 1 files changed, 12 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c +index 4130802..8cbafa5 100644 +--- a/drivers/net/wireless/ipw2x00/ipw2200.c ++++ b/drivers/net/wireless/ipw2x00/ipw2200.c +@@ -2192,6 +2192,7 @@ static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) + { + int rc = 0; + unsigned long flags; ++ unsigned long now, end; + + spin_lock_irqsave(&priv->lock, flags); + if (priv->status & STATUS_HCMD_ACTIVE) { +@@ -2233,10 +2234,20 @@ static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) + } + spin_unlock_irqrestore(&priv->lock, flags); + ++ now = jiffies; ++ end = now + HOST_COMPLETE_TIMEOUT; ++again: + rc = wait_event_interruptible_timeout(priv->wait_command_queue, + !(priv-> + status & STATUS_HCMD_ACTIVE), +- HOST_COMPLETE_TIMEOUT); ++ end - now); ++ if (rc < 0) { ++ now = jiffies; ++ if (time_before(now, end)) ++ goto again; ++ rc = 0; ++ } ++ + if (rc == 0) { + spin_lock_irqsave(&priv->lock, flags); + if (priv->status & STATUS_HCMD_ACTIVE) { +-- +1.7.2.5 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index 97fbc4076..4f9ea942e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -719,6 +719,9 @@ Patch22010: memblock-memblock-should-be-able-to-handle-zero-leng.patch Patch22011: input-synaptics-fix-regression-with-image-sensor-trackpads.patch +#rhbz 783708 +Patch22012: ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch + # END OF PATCH DEFINITIONS %endif @@ -1331,6 +1334,9 @@ ApplyPatch memblock-memblock-should-be-able-to-handle-zero-leng.patch ApplyPatch input-synaptics-fix-regression-with-image-sensor-trackpads.patch +#rhbz 783708 +ApplyPatch ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch + # END OF PATCH APPLICATIONS %endif @@ -1983,6 +1989,9 @@ fi # and build. %changelog +* Tue Apr 24 2012 Josh Boyer +- Add patch to fix ipw2200 (rhbz 783708) + * Mon Apr 23 2012 Josh Boyer - Linux 3.3.3 From 9583a846127bc91f41940b068fb5789099696ccc Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 24 Apr 2012 09:46:24 -0400 Subject: [PATCH 379/397] Add patch to fix perf build due to incorrect cherry-pick in 3.3.3 --- kernel.spec | 5 ++++ perf-fix-build-breakage.patch | 54 +++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 perf-fix-build-breakage.patch diff --git a/kernel.spec b/kernel.spec index 4f9ea942e..074577f28 100644 --- a/kernel.spec +++ b/kernel.spec @@ -722,6 +722,8 @@ Patch22011: input-synaptics-fix-regression-with-image-sensor-trackpads.patch #rhbz 783708 Patch22012: ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch +Patch22013: perf-fix-build-breakage.patch + # END OF PATCH DEFINITIONS %endif @@ -1337,6 +1339,8 @@ ApplyPatch input-synaptics-fix-regression-with-image-sensor-trackpads.patch #rhbz 783708 ApplyPatch ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch +ApplyPatch perf-fix-build-breakage.patch + # END OF PATCH APPLICATIONS %endif @@ -1990,6 +1994,7 @@ fi %changelog * Tue Apr 24 2012 Josh Boyer +- Add patch to fix perf build due to incorrect cherry-pick in 3.3.3 - Add patch to fix ipw2200 (rhbz 783708) * Mon Apr 23 2012 Josh Boyer diff --git a/perf-fix-build-breakage.patch b/perf-fix-build-breakage.patch new file mode 100644 index 000000000..d1385ddce --- /dev/null +++ b/perf-fix-build-breakage.patch @@ -0,0 +1,54 @@ +From zeev.tarantov@gmail.com Sun Apr 22 23:38:36 2012 +From: Zeev Tarantov +Date: Mon, 23 Apr 2012 09:37:04 +0300 +Subject: Perf: fix build breakage +To: "David S. Miller" , Arnaldo Carvalho de Melo , Greg Kroah-Hartman , Linux Kernel Mailing List +Message-ID: <20120423063704.GA3465@myhost> +Content-Disposition: inline + + +From: Zeev Tarantov + +[Patch not needed upstream as this is a backport build bugfix - gregkh + +gcc correctly complains: + +util/hist.c: In function ‘__hists__add_entry’: +util/hist.c:240:27: error: invalid type argument of ‘->’ (have ‘struct hist_entry’) +util/hist.c:241:23: error: invalid type argument of ‘->’ (have ‘struct hist_entry’) + +for this new code: + ++ if (he->ms.map != entry->ms.map) { ++ he->ms.map = entry->ms.map; ++ if (he->ms.map) ++ he->ms.map->referenced = true; ++ } + +because "entry" is a "struct hist_entry", not a pointer to a struct. + +In mainline, "entry" is a pointer to struct passed as argument to the function. +So this is broken during backporting. But obviously not compile tested. + +Signed-off-by: Zeev Tarantov +Cc: Signed-off-by: David S. Miller +Cc: Arnaldo Carvalho de Melo +Signed-off-by: Greg Kroah-Hartman + +--- + tools/perf/util/hist.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/tools/perf/util/hist.c ++++ b/tools/perf/util/hist.c +@@ -237,8 +237,8 @@ struct hist_entry *__hists__add_entry(st + * mis-adjust symbol addresses when computing + * the history counter to increment. + */ +- if (he->ms.map != entry->ms.map) { +- he->ms.map = entry->ms.map; ++ if (he->ms.map != entry.ms.map) { ++ he->ms.map = entry.ms.map; + if (he->ms.map) + he->ms.map->referenced = true; + } From 5b71df1e006666d03c5bb5ad34c3302fe7f60096 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 30 Apr 2012 11:17:03 -0500 Subject: [PATCH 380/397] Linux 3.3.4 --- ...rom-the-iommu-when-slots-are-removed.patch | 92 ------------------- kernel.spec | 29 +----- ...k-should-be-able-to-handle-zero-leng.patch | 63 ------------- perf-fix-build-breakage.patch | 54 ----------- sources | 2 +- ...vent-a-possible-kernel-bug-due-to-mi.patch | 34 ------- 6 files changed, 6 insertions(+), 268 deletions(-) delete mode 100644 KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch delete mode 100644 memblock-memblock-should-be-able-to-handle-zero-leng.patch delete mode 100644 perf-fix-build-breakage.patch delete mode 100644 wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch diff --git a/KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch b/KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch deleted file mode 100644 index b98e392f7..000000000 --- a/KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch +++ /dev/null @@ -1,92 +0,0 @@ -commit 32f6daad4651a748a58a3ab6da0611862175722f -Author: Alex Williamson -Date: Wed Apr 11 09:51:49 2012 -0600 - - KVM: unmap pages from the iommu when slots are removed - - We've been adding new mappings, but not destroying old mappings. - This can lead to a page leak as pages are pinned using - get_user_pages, but only unpinned with put_page if they still - exist in the memslots list on vm shutdown. A memslot that is - destroyed while an iommu domain is enabled for the guest will - therefore result in an elevated page reference count that is - never cleared. - - Additionally, without this fix, the iommu is only programmed - with the first translation for a gpa. This can result in - peer-to-peer errors if a mapping is destroyed and replaced by a - new mapping at the same gpa as the iommu will still be pointing - to the original, pinned memory address. - - Signed-off-by: Alex Williamson - Signed-off-by: Marcelo Tosatti - -diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h -index 665a260..72cbf08 100644 ---- a/include/linux/kvm_host.h -+++ b/include/linux/kvm_host.h -@@ -596,6 +596,7 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id); - - #ifdef CONFIG_IOMMU_API - int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot); -+void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot); - int kvm_iommu_map_guest(struct kvm *kvm); - int kvm_iommu_unmap_guest(struct kvm *kvm); - int kvm_assign_device(struct kvm *kvm, -@@ -609,6 +610,11 @@ static inline int kvm_iommu_map_pages(struct kvm *kvm, - return 0; - } - -+static inline void kvm_iommu_unmap_pages(struct kvm *kvm, -+ struct kvm_memory_slot *slot) -+{ -+} -+ - static inline int kvm_iommu_map_guest(struct kvm *kvm) - { - return -ENODEV; -diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c -index a457d21..fec1723 100644 ---- a/virt/kvm/iommu.c -+++ b/virt/kvm/iommu.c -@@ -310,6 +310,11 @@ static void kvm_iommu_put_pages(struct kvm *kvm, - } - } - -+void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot) -+{ -+ kvm_iommu_put_pages(kvm, slot->base_gfn, slot->npages); -+} -+ - static int kvm_iommu_unmap_memslots(struct kvm *kvm) - { - int idx; -@@ -320,7 +325,7 @@ static int kvm_iommu_unmap_memslots(struct kvm *kvm) - slots = kvm_memslots(kvm); - - kvm_for_each_memslot(memslot, slots) -- kvm_iommu_put_pages(kvm, memslot->base_gfn, memslot->npages); -+ kvm_iommu_unmap_pages(kvm, memslot); - - srcu_read_unlock(&kvm->srcu, idx); - -diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c -index 42b7393..9739b53 100644 ---- a/virt/kvm/kvm_main.c -+++ b/virt/kvm/kvm_main.c -@@ -808,12 +808,13 @@ int __kvm_set_memory_region(struct kvm *kvm, - if (r) - goto out_free; - -- /* map the pages in iommu page table */ -+ /* map/unmap the pages in iommu page table */ - if (npages) { - r = kvm_iommu_map_pages(kvm, &new); - if (r) - goto out_free; -- } -+ } else -+ kvm_iommu_unmap_pages(kvm, &old); - - r = -ENOMEM; - slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots), diff --git a/kernel.spec b/kernel.spec index 074577f28..e82e624c0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 @@ -688,9 +688,6 @@ Patch21306: shlib_base_randomize.patch #rhbz 770476 Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch -#rhbz 808603 -Patch21380: wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch - #rhbz 807632 Patch21385: libata-forbid-port-runtime-pm-by-default.patch @@ -708,22 +705,14 @@ Patch21710: disable-hid-battery.patch Patch22000: weird-root-dentry-name-debug.patch -#rhbz 814149 814155 CVE-2012-2121 -Patch22006: KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch - #rhbz 814278 814289 CVE-2012-2119 Patch22007: macvtap-zerocopy-validate-vector-length.patch -#rhbz 811225 -Patch22010: memblock-memblock-should-be-able-to-handle-zero-leng.patch - Patch22011: input-synaptics-fix-regression-with-image-sensor-trackpads.patch #rhbz 783708 Patch22012: ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch -Patch22013: perf-fix-build-breakage.patch - # END OF PATCH DEFINITIONS %endif @@ -1312,9 +1301,6 @@ ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch #rhbz 770476 ApplyPatch iwlwifi-do-not-nulify-ctx-vif-on-reset.patch -#rhbz 808603 -ApplyPatch wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch - #rhbz 807632 ApplyPatch libata-forbid-port-runtime-pm-by-default.patch @@ -1325,22 +1311,14 @@ ApplyPatch x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPU #rhbz 806295 ApplyPatch disable-hid-battery.patch -#rhbz 814149 814155 CVE-2012-2121 -ApplyPatch KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch - #rhbz 814278 814289 CVE-2012-2119 ApplyPatch macvtap-zerocopy-validate-vector-length.patch -#rhbz 811225 -ApplyPatch memblock-memblock-should-be-able-to-handle-zero-leng.patch - ApplyPatch input-synaptics-fix-regression-with-image-sensor-trackpads.patch #rhbz 783708 ApplyPatch ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch -ApplyPatch perf-fix-build-breakage.patch - # END OF PATCH APPLICATIONS %endif @@ -1993,6 +1971,9 @@ fi # and build. %changelog +* Mon Apr 30 2012 Justin M. Forbes 2.6.43.4-1 +- Linux 3.3.4 + * Tue Apr 24 2012 Josh Boyer - Add patch to fix perf build due to incorrect cherry-pick in 3.3.3 - Add patch to fix ipw2200 (rhbz 783708) diff --git a/memblock-memblock-should-be-able-to-handle-zero-leng.patch b/memblock-memblock-should-be-able-to-handle-zero-leng.patch deleted file mode 100644 index 08e364534..000000000 --- a/memblock-memblock-should-be-able-to-handle-zero-leng.patch +++ /dev/null @@ -1,63 +0,0 @@ -From b3dc627cabb33fc95f93da78457770c1b2a364d2 Mon Sep 17 00:00:00 2001 -From: Tejun Heo -Date: Fri, 20 Apr 2012 08:31:34 -0700 -Subject: [PATCH] memblock: memblock should be able to handle zero length - operations - -Commit 24aa07882b ("memblock, x86: Replace memblock_x86_reserve/ -free_range() with generic ones") replaced x86 specific memblock -operations with the generic ones; unfortunately, it lost zero length -operation handling in the process making the kernel panic if somebody -tries to reserve zero length area. - -There isn't much to be gained by being cranky to zero length operations -and panicking is almost the worst response. Drop the BUG_ON() in -memblock_reserve() and update memblock_add_region/isolate_range() so -that all zero length operations are handled as noops. - -Signed-off-by: Tejun Heo -Cc: stable@vger.kernel.org -Reported-by: Valere Monseur -Bisected-by: Joseph Freeman -Tested-by: Joseph Freeman -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=43098 -Signed-off-by: Linus Torvalds ---- - mm/memblock.c | 7 ++++++- - 1 files changed, 6 insertions(+), 1 deletions(-) - -diff --git a/mm/memblock.c b/mm/memblock.c -index 99f2855..a44eab3 100644 ---- a/mm/memblock.c -+++ b/mm/memblock.c -@@ -330,6 +330,9 @@ static int __init_memblock memblock_add_region(struct memblock_type *type, - phys_addr_t end = base + memblock_cap_size(base, &size); - int i, nr_new; - -+ if (!size) -+ return 0; -+ - /* special case for empty array */ - if (type->regions[0].size == 0) { - WARN_ON(type->cnt != 1 || type->total_size); -@@ -430,6 +433,9 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, - - *start_rgn = *end_rgn = 0; - -+ if (!size) -+ return 0; -+ - /* we'll create at most two more regions */ - while (type->cnt + 2 > type->max) - if (memblock_double_array(type) < 0) -@@ -514,7 +520,6 @@ int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size) - (unsigned long long)base, - (unsigned long long)base + size, - (void *)_RET_IP_); -- BUG_ON(0 == size); - - return memblock_add_region(_rgn, base, size, MAX_NUMNODES); - } --- -1.7.7.6 - diff --git a/perf-fix-build-breakage.patch b/perf-fix-build-breakage.patch deleted file mode 100644 index d1385ddce..000000000 --- a/perf-fix-build-breakage.patch +++ /dev/null @@ -1,54 +0,0 @@ -From zeev.tarantov@gmail.com Sun Apr 22 23:38:36 2012 -From: Zeev Tarantov -Date: Mon, 23 Apr 2012 09:37:04 +0300 -Subject: Perf: fix build breakage -To: "David S. Miller" , Arnaldo Carvalho de Melo , Greg Kroah-Hartman , Linux Kernel Mailing List -Message-ID: <20120423063704.GA3465@myhost> -Content-Disposition: inline - - -From: Zeev Tarantov - -[Patch not needed upstream as this is a backport build bugfix - gregkh - -gcc correctly complains: - -util/hist.c: In function ‘__hists__add_entry’: -util/hist.c:240:27: error: invalid type argument of ‘->’ (have ‘struct hist_entry’) -util/hist.c:241:23: error: invalid type argument of ‘->’ (have ‘struct hist_entry’) - -for this new code: - -+ if (he->ms.map != entry->ms.map) { -+ he->ms.map = entry->ms.map; -+ if (he->ms.map) -+ he->ms.map->referenced = true; -+ } - -because "entry" is a "struct hist_entry", not a pointer to a struct. - -In mainline, "entry" is a pointer to struct passed as argument to the function. -So this is broken during backporting. But obviously not compile tested. - -Signed-off-by: Zeev Tarantov -Cc: Signed-off-by: David S. Miller -Cc: Arnaldo Carvalho de Melo -Signed-off-by: Greg Kroah-Hartman - ---- - tools/perf/util/hist.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/tools/perf/util/hist.c -+++ b/tools/perf/util/hist.c -@@ -237,8 +237,8 @@ struct hist_entry *__hists__add_entry(st - * mis-adjust symbol addresses when computing - * the history counter to increment. - */ -- if (he->ms.map != entry->ms.map) { -- he->ms.map = entry->ms.map; -+ if (he->ms.map != entry.ms.map) { -+ he->ms.map = entry.ms.map; - if (he->ms.map) - he->ms.map->referenced = true; - } diff --git a/sources b/sources index d1990b3af..1918a7281 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz -634a088d3789870885dc6ee1eb9627d4 patch-3.3.3.xz +9c4cc16f10b645fbb90f6c05ad388883 patch-3.3.4.xz diff --git a/wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch b/wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch deleted file mode 100644 index 92b2e9970..000000000 --- a/wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 4eee6a3a04e8bb53fbe7de0f64d0524d3fbe3f80 Mon Sep 17 00:00:00 2001 -From: Phil Sutter -Date: Mon, 26 Mar 2012 09:01:30 +0000 -Subject: [PATCH] wimax: i2400m - prevent a possible kernel bug due to missing - fw_name string - -This happened on a machine with a custom hotplug script calling nameif, -probably due to slow firmware loading. At the time nameif uses ethtool -to gather interface information, i2400m->fw_name is zero and so a null -pointer dereference occurs from within i2400m_get_drvinfo(). - -Signed-off-by: Phil Sutter -Signed-off-by: David S. Miller ---- - drivers/net/wimax/i2400m/netdev.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c -index 63e4b70..1d76ae8 100644 ---- a/drivers/net/wimax/i2400m/netdev.c -+++ b/drivers/net/wimax/i2400m/netdev.c -@@ -597,7 +597,8 @@ static void i2400m_get_drvinfo(struct net_device *net_dev, - struct i2400m *i2400m = net_dev_to_i2400m(net_dev); - - strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver) - 1); -- strncpy(info->fw_version, i2400m->fw_name, sizeof(info->fw_version) - 1); -+ strncpy(info->fw_version, -+ i2400m->fw_name ? : "", sizeof(info->fw_version) - 1); - if (net_dev->dev.parent) - strncpy(info->bus_info, dev_name(net_dev->dev.parent), - sizeof(info->bus_info) - 1); --- -1.7.7.6 - From c4a5c01e74ee4f2da21cde82d9a10023a413977f Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 30 Apr 2012 12:29:54 -0400 Subject: [PATCH 381/397] Disable CONFIG_RCU_FAST_NO_HZ for now. (rhbz 806548) --- config-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 33fcbf07a..9d2c3341b 100644 --- a/config-generic +++ b/config-generic @@ -4522,7 +4522,7 @@ CONFIG_LSM_MMAP_MIN_ADDR=65536 CONFIG_STRIP_ASM_SYMS=y # CONFIG_RCU_FANOUT_EXACT is not set -CONFIG_RCU_FAST_NO_HZ=y +# CONFIG_RCU_FAST_NO_HZ is not set CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_TRACE is not set diff --git a/kernel.spec b/kernel.spec index e82e624c0..2eefe4706 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1971,6 +1971,9 @@ fi # and build. %changelog +* Mon Apr 30 2012 Dave Jones +- Disable CONFIG_RCU_FAST_NO_HZ for now. (rhbz 806548) + * Mon Apr 30 2012 Justin M. Forbes 2.6.43.4-1 - Linux 3.3.4 From de33fd2feac80350ea92fc6fa7c5f9eb10964f32 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 30 Apr 2012 15:23:12 -0400 Subject: [PATCH 382/397] Backport ipw2x00 nl80211 cipher suite reporting (rhbz 817298) --- ...ipher-suites-to-wiphy-initialization.patch | 155 ++++++++++++++++++ kernel.spec | 11 +- 2 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch diff --git a/ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch b/ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch new file mode 100644 index 000000000..705c5eff0 --- /dev/null +++ b/ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch @@ -0,0 +1,155 @@ +Path: news.gmane.org!not-for-mail +From: Stanislav Yakovlev +Newsgroups: gmane.linux.kernel.wireless.general +Subject: [PATCH] net/wireless: ipw2x00: add supported cipher suites to wiphy initialization +Date: Tue, 10 Apr 2012 21:44:47 -0400 +Lines: 97 +Approved: news@gmane.org +Message-ID: <1334108687-12954-1-git-send-email-stas.yakovlev@gmail.com> +NNTP-Posting-Host: plane.gmane.org +X-Trace: dough.gmane.org 1334108469 22291 80.91.229.3 (11 Apr 2012 01:41:09 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Wed, 11 Apr 2012 01:41:09 +0000 (UTC) +Cc: simar-hi6Y0CQ0nG0@public.gmane.org, linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, + Stanislav Yakovlev +To: linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org +Original-X-From: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Wed Apr 11 03:41:07 2012 +Return-path: +Envelope-to: glkwg-linux-wireless-wOFGN7rlS/M9smdsby/KFg@public.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1SHmYV-0004IK-CT + for glkwg-linux-wireless-wOFGN7rlS/M9smdsby/KFg@public.gmane.org; Wed, 11 Apr 2012 03:41:07 +0200 +Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand + id S1759898Ab2DKBlF (ORCPT + ); + Tue, 10 Apr 2012 21:41:05 -0400 +Original-Received: from mail-ob0-f174.google.com ([209.85.214.174]:60108 "EHLO + mail-ob0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1753779Ab2DKBlE (ORCPT + ); + Tue, 10 Apr 2012 21:41:04 -0400 +Original-Received: by obbtb18 with SMTP id tb18so567970obb.19 + for ; Tue, 10 Apr 2012 18:41:02 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20120113; + h=from:to:cc:subject:date:message-id:x-mailer; + bh=8+D+Uuo0bIOG6rz8vxd6TGAxmrbuAw2bjWhd058IjOQ=; + b=beOgy1Y9ZAV1Xw5XqsnPDJ1Oc0qOpOo+gCWlwmWbLdVHxUVG+ZVuRW9eCRQkh+5bZm + 5Ic+xOISztYUJp144Fr4flnbGPRKKp7jP8qQ/HvCOo34J6MCgBlnuWNYKbn4/NUvOYAh + SeHpk2D8yOHbiWAMV+JGTqGG+/N4jVvRL147Yg1IfNDAJd8Ahbl0wARLOVg8WGGTSPvn + MU3HNbmKFFBDhnukYr4keCnjixuDkqPYGMYuDrsmKdiAFHBRDI6qudnvaqi8F8gbtaWg + dfssdTbmNYM/R/PJenInoy7IbRps2iW9ZX+zFzydZWp2EyJ4EZkKrYKmnezQgNJzRVex + KHfg== +Original-Received: by 10.60.24.9 with SMTP id q9mr19071024oef.4.1334108462648; + Tue, 10 Apr 2012 18:41:02 -0700 (PDT) +Original-Received: from localhost.localdomain (50-0-191-227.dsl.static.sonic.net. [50.0.191.227]) + by mx.google.com with ESMTPS id tx2sm1309336obb.8.2012.04.10.18.40.54 + (version=TLSv1/SSLv3 cipher=OTHER); + Tue, 10 Apr 2012 18:41:01 -0700 (PDT) +X-Mailer: git-send-email 1.7.2.5 +Original-Sender: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Xref: news.gmane.org gmane.linux.kernel.wireless.general:88613 +Archived-At: + +Driver doesn't report its supported cipher suites through cfg80211 +interface. It still uses wext interface and probably will not work +through nl80211, but will at least correctly advertise supported +features. + +Bug was reported by Omar Siam. +https://bugzilla.kernel.org/show_bug.cgi?id=43049 + +Signed-off-by: Stanislav Yakovlev +--- + drivers/net/wireless/ipw2x00/ipw.h | 23 +++++++++++++++++++++++ + drivers/net/wireless/ipw2x00/ipw2100.c | 4 ++++ + drivers/net/wireless/ipw2x00/ipw2200.c | 4 ++++ + 3 files changed, 31 insertions(+), 0 deletions(-) + create mode 100644 drivers/net/wireless/ipw2x00/ipw.h + +diff --git a/drivers/net/wireless/ipw2x00/ipw.h b/drivers/net/wireless/ipw2x00/ipw.h +new file mode 100644 +index 0000000..4007bf5 +--- /dev/null ++++ b/drivers/net/wireless/ipw2x00/ipw.h +@@ -0,0 +1,23 @@ ++/* ++ * Intel Pro/Wireless 2100, 2200BG, 2915ABG network connection driver ++ * ++ * Copyright 2012 Stanislav Yakovlev ++ * ++ * 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. ++ */ ++ ++#ifndef __IPW_H__ ++#define __IPW_H__ ++ ++#include ++ ++static const u32 ipw_cipher_suites[] = { ++ WLAN_CIPHER_SUITE_WEP40, ++ WLAN_CIPHER_SUITE_WEP104, ++ WLAN_CIPHER_SUITE_TKIP, ++ WLAN_CIPHER_SUITE_CCMP, ++}; ++ ++#endif +diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c +index f0551f8..7c8e8b1 100644 +--- a/drivers/net/wireless/ipw2x00/ipw2100.c ++++ b/drivers/net/wireless/ipw2x00/ipw2100.c +@@ -166,6 +166,7 @@ that only one external action is invoked at a time. + #include + + #include "ipw2100.h" ++#include "ipw.h" + + #define IPW2100_VERSION "git-1.2.2" + +@@ -1946,6 +1947,9 @@ static int ipw2100_wdev_init(struct net_device *dev) + wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band; + } + ++ wdev->wiphy->cipher_suites = ipw_cipher_suites; ++ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites); ++ + set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); + if (wiphy_register(wdev->wiphy)) { + ipw2100_down(priv); +diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c +index 2b02257..bb4f42a 100644 +--- a/drivers/net/wireless/ipw2x00/ipw2200.c ++++ b/drivers/net/wireless/ipw2x00/ipw2200.c +@@ -34,6 +34,7 @@ + #include + #include + #include "ipw2200.h" ++#include "ipw.h" + + + #ifndef KBUILD_EXTMOD +@@ -11533,6 +11534,9 @@ static int ipw_wdev_init(struct net_device *dev) + wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = a_band; + } + ++ wdev->wiphy->cipher_suites = ipw_cipher_suites; ++ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites); ++ + set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); + + /* With that information in place, we can now register the wiphy... */ +-- +1.7.2.5 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + diff --git a/kernel.spec b/kernel.spec index 2eefe4706..ad80d226e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -713,6 +713,9 @@ Patch22011: input-synaptics-fix-regression-with-image-sensor-trackpads.patch #rhbz 783708 Patch22012: ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch +#rhbz 817298 +Patch22013: ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch + # END OF PATCH DEFINITIONS %endif @@ -1319,6 +1322,9 @@ ApplyPatch input-synaptics-fix-regression-with-image-sensor-trackpads.patch #rhbz 783708 ApplyPatch ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch +#rhbz 817298 +ApplyPatch ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch + # END OF PATCH APPLICATIONS %endif @@ -1971,6 +1977,9 @@ fi # and build. %changelog +* Mon Apr 30 2012 Josh Boyer +- Backport ipw2x00 nl80211 cipher suite reporting (rhbz 817298) + * Mon Apr 30 2012 Dave Jones - Disable CONFIG_RCU_FAST_NO_HZ for now. (rhbz 806548) From b4b239926d838b17a00283a908b37414034c69d1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 4 May 2012 07:16:28 -0400 Subject: [PATCH 383/397] unfiltered netdev rio_ioctl access by users (rhbz 818820) --- dl2k-Clean-up-rio_ioctl.patch | 120 ++++++++++++++++++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 dl2k-Clean-up-rio_ioctl.patch diff --git a/dl2k-Clean-up-rio_ioctl.patch b/dl2k-Clean-up-rio_ioctl.patch new file mode 100644 index 000000000..2ef4eed6d --- /dev/null +++ b/dl2k-Clean-up-rio_ioctl.patch @@ -0,0 +1,120 @@ +From 1bb57e940e1958e40d51f2078f50c3a96a9b2d75 Mon Sep 17 00:00:00 2001 +From: Jeff Mahoney +Date: Wed, 25 Apr 2012 14:32:09 +0000 +Subject: [PATCH] dl2k: Clean up rio_ioctl + +The dl2k driver's rio_ioctl call has a few issues: +- No permissions checking +- Implements SIOCGMIIREG and SIOCGMIIREG using the SIOCDEVPRIVATE numbers +- Has a few ioctls that may have been used for debugging at one point + but have no place in the kernel proper. + +This patch removes all but the MII ioctls, renumbers them to use the +standard ones, and adds the proper permission check for SIOCSMIIREG. + +We can also get rid of the dl2k-specific struct mii_data in favor of +the generic struct mii_ioctl_data. + +Since we have the phyid on hand, we can add the SIOCGMIIPHY ioctl too. + +Most of the MII code for the driver could probably be converted to use +the generic MII library but I don't have a device to test the results. + +Reported-by: Stephan Mueller +Signed-off-by: Jeff Mahoney +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/dlink/dl2k.c | 52 ++++++------------------------------ + drivers/net/ethernet/dlink/dl2k.h | 7 ----- + 2 files changed, 9 insertions(+), 50 deletions(-) + +diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c +index b2dc2c8..2e09edb 100644 +--- a/drivers/net/ethernet/dlink/dl2k.c ++++ b/drivers/net/ethernet/dlink/dl2k.c +@@ -1259,55 +1259,21 @@ rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) + { + int phy_addr; + struct netdev_private *np = netdev_priv(dev); +- struct mii_data *miidata = (struct mii_data *) &rq->ifr_ifru; +- +- struct netdev_desc *desc; +- int i; ++ struct mii_ioctl_data *miidata = if_mii(rq); + + phy_addr = np->phy_addr; + switch (cmd) { +- case SIOCDEVPRIVATE: +- break; +- +- case SIOCDEVPRIVATE + 1: +- miidata->out_value = mii_read (dev, phy_addr, miidata->reg_num); ++ case SIOCGMIIPHY: ++ miidata->phy_id = phy_addr; + break; +- case SIOCDEVPRIVATE + 2: +- mii_write (dev, phy_addr, miidata->reg_num, miidata->in_value); ++ case SIOCGMIIREG: ++ miidata->val_out = mii_read (dev, phy_addr, miidata->reg_num); + break; +- case SIOCDEVPRIVATE + 3: +- break; +- case SIOCDEVPRIVATE + 4: +- break; +- case SIOCDEVPRIVATE + 5: +- netif_stop_queue (dev); ++ case SIOCSMIIREG: ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ mii_write (dev, phy_addr, miidata->reg_num, miidata->val_in); + break; +- case SIOCDEVPRIVATE + 6: +- netif_wake_queue (dev); +- break; +- case SIOCDEVPRIVATE + 7: +- printk +- ("tx_full=%x cur_tx=%lx old_tx=%lx cur_rx=%lx old_rx=%lx\n", +- netif_queue_stopped(dev), np->cur_tx, np->old_tx, np->cur_rx, +- np->old_rx); +- break; +- case SIOCDEVPRIVATE + 8: +- printk("TX ring:\n"); +- for (i = 0; i < TX_RING_SIZE; i++) { +- desc = &np->tx_ring[i]; +- printk +- ("%02x:cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x", +- i, +- (u32) (np->tx_ring_dma + i * sizeof (*desc)), +- (u32)le64_to_cpu(desc->next_desc), +- (u32)le64_to_cpu(desc->status), +- (u32)(le64_to_cpu(desc->fraginfo) >> 32), +- (u32)le64_to_cpu(desc->fraginfo)); +- printk ("\n"); +- } +- printk ("\n"); +- break; +- + default: + return -EOPNOTSUPP; + } +diff --git a/drivers/net/ethernet/dlink/dl2k.h b/drivers/net/ethernet/dlink/dl2k.h +index ba0adca..30c2da3 100644 +--- a/drivers/net/ethernet/dlink/dl2k.h ++++ b/drivers/net/ethernet/dlink/dl2k.h +@@ -365,13 +365,6 @@ struct ioctl_data { + char *data; + }; + +-struct mii_data { +- __u16 reserved; +- __u16 reg_num; +- __u16 in_value; +- __u16 out_value; +-}; +- + /* The Rx and Tx buffer descriptors. */ + struct netdev_desc { + __le64 next_desc; +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index ad80d226e..1a7c28c0c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -716,6 +716,9 @@ Patch22012: ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.pat #rhbz 817298 Patch22013: ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch +#rhbz 818820 +Patch22016: dl2k-Clean-up-rio_ioctl.patch + # END OF PATCH DEFINITIONS %endif @@ -1325,6 +1328,9 @@ ApplyPatch ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patc #rhbz 817298 ApplyPatch ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch +#rhbz 818820 +ApplyPatch dl2k-Clean-up-rio_ioctl.patch + # END OF PATCH APPLICATIONS %endif @@ -1977,6 +1983,9 @@ fi # and build. %changelog +* Fri May 04 2012 Josh Boyer +- unfiltered netdev rio_ioctl access by users (rhbz 818820) + * Mon Apr 30 2012 Josh Boyer - Backport ipw2x00 nl80211 cipher suite reporting (rhbz 817298) From 851e38799ece771902a89a5ac432d8d844a188e0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 7 May 2012 13:41:07 -0400 Subject: [PATCH 384/397] Linux 3.3.5 - Add patch to rate limit NFSv4 message (rhbz 732748) --- ...-the-state-manager-for-lock-reclaim-.patch | 37 ++++ config-arm-generic | 5 + hibernate-watermark.patch | 198 ------------------ ...gression-with-image-sensor-trackpads.patch | 38 ---- ...n-the-command-completion-acknowledge.patch | 69 ------ iwlwifi-do-not-nulify-ctx-vif-on-reset.patch | 66 ------ kernel.spec | 40 +--- sources | 2 +- ...s-only-loaded-for-supported-AMD-CPUs.patch | 163 -------------- ...ng-module-unload-on-unsupported-CPUs.patch | 167 --------------- 10 files changed, 51 insertions(+), 734 deletions(-) create mode 100644 NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch delete mode 100644 hibernate-watermark.patch delete mode 100644 input-synaptics-fix-regression-with-image-sensor-trackpads.patch delete mode 100644 ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch delete mode 100644 iwlwifi-do-not-nulify-ctx-vif-on-reset.patch delete mode 100644 x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch delete mode 100644 x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch diff --git a/NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch b/NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch new file mode 100644 index 000000000..5b7f5e51d --- /dev/null +++ b/NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch @@ -0,0 +1,37 @@ +From 34d91cfbc163c6e2a136a27c96918fc35de06341 Mon Sep 17 00:00:00 2001 +From: William Dauchy +Date: Wed, 14 Mar 2012 12:32:04 +0100 +Subject: [PATCH] NFSv4: Rate limit the state manager for lock reclaim warning + messages + +Adding rate limit on `Lock reclaim failed` messages since it could fill +up system logs +Signed-off-by: William Dauchy +Signed-off-by: Trond Myklebust + +Conflicts: + + fs/nfs/nfs4state.c +--- + fs/nfs/nfs4state.c | 5 +++-- + 1 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c +index bacb271..3676b5c 100644 +--- a/fs/nfs/nfs4state.c ++++ b/fs/nfs/nfs4state.c +@@ -1247,8 +1247,9 @@ restart: + spin_lock(&state->state_lock); + list_for_each_entry(lock, &state->lock_states, ls_locks) { + if (!(lock->ls_flags & NFS_LOCK_INITIALIZED)) +- printk("%s: Lock reclaim failed!\n", +- __func__); ++ pr_warn_ratelimited("NFS: " ++ "%s: Lock reclaim " ++ "failed!\n", __func__); + } + spin_unlock(&state->state_lock); + nfs4_put_open_state(state); +-- +1.7.7.6 + diff --git a/config-arm-generic b/config-arm-generic index 2ad9ca63c..6cb515ddb 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -190,6 +190,11 @@ CONFIG_LSM_MMAP_MIN_ADDR=32768 # CONFIG_MACH_EUKREA_CPUIMX35SD is not set CONFIG_ARM_ERRATA_720789=y CONFIG_ARM_ERRATA_751472=y +<<<<<<< HEAD +======= +CONFIG_ARM_ERRATA_326103=y +CONFIG_OMAP4_ERRATA_I688=y +>>>>>>> 99667a9... Linux 3.3.5 # CONFIG_FB_MX3 is not set # CONFIG_MX3_IPU is not set # CONFIG_MX3_IPU_IRQS is not set diff --git a/hibernate-watermark.patch b/hibernate-watermark.patch deleted file mode 100644 index 7031e167f..000000000 --- a/hibernate-watermark.patch +++ /dev/null @@ -1,198 +0,0 @@ -Hi Rafael, - -One more version. Heeding Per's suggestion to optimise when -CONFIG_HIGHMEM is not configured. - ---------------------------------------- -Hibernation/thaw fixes/improvements: - -1. Calculate the number of required free pages based on non-high memory -pages only, because that is where the buffers will come from. - -2. Do not allocate memory for buffers from emergency pools, unless -absolutely required. Do not warn about and do not retry non-essential -failed allocations. - -3. Do not check the amount of free pages left on every single page -write, but wait until one map is completely populated and then check. - -4. Set maximum number of pages for read buffering consistently, instead -of inadvertently depending on the size of the sector type. - -5. Fix copyright line, which I missed when I submitted the hibernation -threading patch. - -6. Dispense with bit shifting arithmetic to improve readability. - -Signed-off-by: Bojan Smojver -Signed-off-by: Per Olofsson ---- - kernel/power/swap.c | 76 +++++++++++++++++++++++++++++++++++++++------------ - 1 files changed, 58 insertions(+), 18 deletions(-) - -diff --git a/kernel/power/swap.c b/kernel/power/swap.c -index 8742fd0..8a1c293 100644 ---- a/kernel/power/swap.c -+++ b/kernel/power/swap.c -@@ -6,7 +6,7 @@ - * - * Copyright (C) 1998,2001-2005 Pavel Machek - * Copyright (C) 2006 Rafael J. Wysocki -- * Copyright (C) 2010 Bojan Smojver -+ * Copyright (C) 2010-2012 Bojan Smojver - * - * This file is released under the GPLv2. - * -@@ -51,6 +51,36 @@ - - #define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(sector_t) - 1) - -+/* -+ * Number of free pages that are not high. -+ */ -+#ifdef CONFIG_HIGHMEM -+static unsigned long low_free_pages(void) -+{ -+ struct zone *zone; -+ unsigned long free = 0; -+ -+ for_each_populated_zone(zone) -+ if (!is_highmem(zone)) -+ free += zone_page_state(zone, NR_FREE_PAGES); -+ return free; -+} -+#else -+static inline unsigned long low_free_pages(void) -+{ -+ return nr_free_pages(); -+} -+#endif -+ -+/* -+ * Number of pages required to be kept free while writing the image. Always -+ * half of all available low pages before the writing starts. -+ */ -+static inline unsigned long reqd_free_pages(void) -+{ -+ return low_free_pages() / 2; -+} -+ - struct swap_map_page { - sector_t entries[MAP_PAGE_ENTRIES]; - sector_t next_swap; -@@ -72,7 +102,7 @@ struct swap_map_handle { - sector_t cur_swap; - sector_t first_sector; - unsigned int k; -- unsigned long nr_free_pages, written; -+ unsigned long reqd_free_pages; - u32 crc32; - }; - -@@ -265,14 +295,17 @@ static int write_page(void *buf, sector_t offset, struct bio **bio_chain) - return -ENOSPC; - - if (bio_chain) { -- src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); -+ src = (void *)__get_free_page(__GFP_WAIT | __GFP_NOWARN | -+ __GFP_NORETRY); - if (src) { - copy_page(src, buf); - } else { - ret = hib_wait_on_bio_chain(bio_chain); /* Free pages */ - if (ret) - return ret; -- src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); -+ src = (void *)__get_free_page(__GFP_WAIT | -+ __GFP_NOWARN | -+ __GFP_NORETRY); - if (src) { - copy_page(src, buf); - } else { -@@ -316,8 +349,7 @@ static int get_swap_writer(struct swap_map_handle *handle) - goto err_rel; - } - handle->k = 0; -- handle->nr_free_pages = nr_free_pages() >> 1; -- handle->written = 0; -+ handle->reqd_free_pages = reqd_free_pages(); - handle->first_sector = handle->cur_swap; - return 0; - err_rel: -@@ -351,12 +383,17 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, - clear_page(handle->cur); - handle->cur_swap = offset; - handle->k = 0; -- } -- if (bio_chain && ++handle->written > handle->nr_free_pages) { -- error = hib_wait_on_bio_chain(bio_chain); -- if (error) -- goto out; -- handle->written = 0; -+ -+ if (bio_chain && low_free_pages() <= handle->reqd_free_pages) { -+ error = hib_wait_on_bio_chain(bio_chain); -+ if (error) -+ goto out; -+ /* -+ * Recalculate the number of required free pages, to -+ * make sure we never take more than half. -+ */ -+ handle->reqd_free_pages = reqd_free_pages(); -+ } - } - out: - return error; -@@ -404,7 +441,7 @@ static int swap_writer_finish(struct swap_map_handle *handle, - #define LZO_THREADS 3 - - /* Maximum number of pages for read buffering. */ --#define LZO_READ_PAGES (MAP_PAGE_ENTRIES * 8) -+#define LZO_READ_PAGES 8192 - - - /** -@@ -615,10 +652,10 @@ static int save_image_lzo(struct swap_map_handle *handle, - } - - /* -- * Adjust number of free pages after all allocations have been done. -- * We don't want to run out of pages when writing. -+ * Adjust the number of required free pages after all allocations have -+ * been done. We don't want to run out of pages when writing. - */ -- handle->nr_free_pages = nr_free_pages() >> 1; -+ handle->reqd_free_pages = reqd_free_pages(); - - /* - * Start the CRC32 thread. -@@ -1129,14 +1166,17 @@ static int load_image_lzo(struct swap_map_handle *handle, - - /* - * Adjust number of pages for read buffering, in case we are short. -+ * Never take more than half of all available low pages. - */ -- read_pages = (nr_free_pages() - snapshot_get_image_size()) >> 1; -+ read_pages = (low_free_pages() - snapshot_get_image_size()) / 2; - read_pages = clamp_val(read_pages, LZO_CMP_PAGES, LZO_READ_PAGES); - - for (i = 0; i < read_pages; i++) { - page[i] = (void *)__get_free_page(i < LZO_CMP_PAGES ? - __GFP_WAIT | __GFP_HIGH : -- __GFP_WAIT); -+ __GFP_WAIT | __GFP_NOWARN | -+ __GFP_NORETRY); -+ - if (!page[i]) { - if (i < LZO_CMP_PAGES) { - ring_size = i; ---------------------------------------- - --- -Bojan - --- -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/ \ No newline at end of file diff --git a/input-synaptics-fix-regression-with-image-sensor-trackpads.patch b/input-synaptics-fix-regression-with-image-sensor-trackpads.patch deleted file mode 100644 index 6c1542b7c..000000000 --- a/input-synaptics-fix-regression-with-image-sensor-trackpads.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 899c612d74d4a242158a4db20367388d6299c028 Mon Sep 17 00:00:00 2001 -From: Benjamin Herrenschmidt -Date: Fri, 20 Apr 2012 22:34:49 -0700 -Subject: [PATCH] Input: synaptics - fix regression with "image sensor" - trackpads - -commit 7968a5dd492ccc38345013e534ad4c8d6eb60ed1 -Input: synaptics - add support for Relative mode - -Accidentally broke support for advanced gestures (multitouch) -on some trackpads such as the one in my ThinkPad X220 by -incorretly changing the condition for enabling them. This -restores it. - -Signed-off-by: Benjamin Herrenschmidt -CC: stable@kernel.org [3.3] -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/synaptics.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c -index 8081a0a..a4b14a4 100644 ---- a/drivers/input/mouse/synaptics.c -+++ b/drivers/input/mouse/synaptics.c -@@ -274,7 +274,8 @@ static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) - static unsigned char param = 0xc8; - struct synaptics_data *priv = psmouse->private; - -- if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) -+ if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || -+ SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c))) - return 0; - - if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL)) --- -1.7.10 - diff --git a/ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch b/ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch deleted file mode 100644 index 3b7451f9f..000000000 --- a/ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch +++ /dev/null @@ -1,69 +0,0 @@ -Driver incorrectly validates command completion: instead of waiting -for a command to be acknowledged it continues execution. Most of the -time driver gets acknowledge of the command completion in a tasklet -before it executes the next one. But sometimes it sends the next -command before it gets acknowledge for the previous one. In such a -case one of the following error messages appear in the log: - -Failed to send SYSTEM_CONFIG: Already sending a command. -Failed to send ASSOCIATE: Already sending a command. -Failed to send TX_POWER: Already sending a command. - -After that you need to reload the driver to get it working again. - -This bug occurs during roammaping (reported by Sam Varshavchik) -https://bugzilla.redhat.com/show_bug.cgi?id=738508 -and machine booting (reported by Tom Gundersen and Mads Kiilerich) -https://bugs.archlinux.org/task/28097 -https://bugzilla.redhat.com/show_bug.cgi?id=802106 - -This patch doesn't fix the delay issue during firmware load. -But at least device now works as usual after boot. - -Cc: stable@kernel.org -Signed-off-by: Stanislav Yakovlev ---- - drivers/net/wireless/ipw2x00/ipw2200.c | 13 ++++++++++++- - 1 files changed, 12 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c -index 4130802..8cbafa5 100644 ---- a/drivers/net/wireless/ipw2x00/ipw2200.c -+++ b/drivers/net/wireless/ipw2x00/ipw2200.c -@@ -2192,6 +2192,7 @@ static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) - { - int rc = 0; - unsigned long flags; -+ unsigned long now, end; - - spin_lock_irqsave(&priv->lock, flags); - if (priv->status & STATUS_HCMD_ACTIVE) { -@@ -2233,10 +2234,20 @@ static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) - } - spin_unlock_irqrestore(&priv->lock, flags); - -+ now = jiffies; -+ end = now + HOST_COMPLETE_TIMEOUT; -+again: - rc = wait_event_interruptible_timeout(priv->wait_command_queue, - !(priv-> - status & STATUS_HCMD_ACTIVE), -- HOST_COMPLETE_TIMEOUT); -+ end - now); -+ if (rc < 0) { -+ now = jiffies; -+ if (time_before(now, end)) -+ goto again; -+ rc = 0; -+ } -+ - if (rc == 0) { - spin_lock_irqsave(&priv->lock, flags); - if (priv->status & STATUS_HCMD_ACTIVE) { --- -1.7.2.5 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/iwlwifi-do-not-nulify-ctx-vif-on-reset.patch b/iwlwifi-do-not-nulify-ctx-vif-on-reset.patch deleted file mode 100644 index e03f2d304..000000000 --- a/iwlwifi-do-not-nulify-ctx-vif-on-reset.patch +++ /dev/null @@ -1,66 +0,0 @@ -ctx->vif is dereferenced in different part of iwlwifi code, so do not -nullify it. - -This should address at least one of the possible reasons of WARNING at -iwlagn_mac_remove_interface, and perhaps some random crashes when -firmware reset is performed. - -Cc: stable@vger.kernel.org -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/iwlwifi/iwl-agn.c | 3 --- - drivers/net/wireless/iwlwifi/iwl-mac80211.c | 10 +++++++++- - 2 files changed, 9 insertions(+), 4 deletions(-) - ---- linux-3.3.noarch.orig/drivers/net/wireless/iwlwifi/iwl-agn.c -+++ linux-3.3.noarch/drivers/net/wireless/iwlwifi/iwl-agn.c -@@ -1403,7 +1403,6 @@ static void iwl_bg_run_time_calib_work(s - - void iwlagn_prepare_restart(struct iwl_priv *priv) - { -- struct iwl_rxon_context *ctx; - bool bt_full_concurrent; - u8 bt_ci_compliance; - u8 bt_load; -@@ -1412,8 +1411,6 @@ void iwlagn_prepare_restart(struct iwl_p - - lockdep_assert_held(&priv->shrd->mutex); - -- for_each_context(priv, ctx) -- ctx->vif = NULL; - priv->is_open = 0; - - /* ---- linux-3.3.noarch.orig/drivers/net/wireless/iwlwifi/iwl-mac80211.c -+++ linux-3.3.noarch/drivers/net/wireless/iwlwifi/iwl-mac80211.c -@@ -1226,6 +1226,7 @@ static int iwlagn_mac_add_interface(stru - struct iwl_rxon_context *tmp, *ctx = NULL; - int err; - enum nl80211_iftype viftype = ieee80211_vif_type_p2p(vif); -+ bool reset = false; - - IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", - viftype, vif->addr); -@@ -1247,6 +1248,13 @@ static int iwlagn_mac_add_interface(stru - tmp->interface_modes | tmp->exclusive_interface_modes; - - if (tmp->vif) { -+ /* On reset we need to add the same interface again */ -+ if (tmp->vif == vif) { -+ reset = true; -+ ctx = tmp; -+ break; -+ } -+ - /* check if this busy context is exclusive */ - if (tmp->exclusive_interface_modes & - BIT(tmp->vif->type)) { -@@ -1273,7 +1281,7 @@ static int iwlagn_mac_add_interface(stru - ctx->vif = vif; - - err = iwl_setup_interface(priv, ctx); -- if (!err) -+ if (!err || reset) - goto out; - - ctx->vif = NULL; diff --git a/kernel.spec b/kernel.spec index 1a7c28c0c..676a9d85a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 # Set rpm version accordingly @@ -640,6 +640,7 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch Patch4000: NFSv4-Reduce-the-footprint-of-the-idmapper.patch Patch4001: NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch Patch4107: NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch +Patch4115: NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch # patches headed upstream @@ -649,9 +650,6 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch -Patch14000: hibernate-freeze-filesystems.patch -Patch14001: hibernate-watermark.patch - Patch14010: lis3-improve-handling-of-null-rate.patch Patch15000: bluetooth-use-after-free.patch @@ -685,9 +683,6 @@ Patch21300: unhandled-irqs-switch-to-polling.patch #rhbz 804957 CVE-2012-1568 Patch21306: shlib_base_randomize.patch -#rhbz 770476 -Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch - #rhbz 807632 Patch21385: libata-forbid-port-runtime-pm-by-default.patch @@ -697,9 +692,6 @@ Patch21520: KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch #rhbz 808559 Patch21530: ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch -Patch21700: x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch -Patch21701: x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch - #rhbz 806295 Patch21710: disable-hid-battery.patch @@ -708,11 +700,6 @@ Patch22000: weird-root-dentry-name-debug.patch #rhbz 814278 814289 CVE-2012-2119 Patch22007: macvtap-zerocopy-validate-vector-length.patch -Patch22011: input-synaptics-fix-regression-with-image-sensor-trackpads.patch - -#rhbz 783708 -Patch22012: ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch - #rhbz 817298 Patch22013: ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch @@ -1173,6 +1160,7 @@ ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch ApplyPatch NFSv4-Reduce-the-footprint-of-the-idmapper.patch ApplyPatch NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch ApplyPatch NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch +ApplyPatch NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch # USB @@ -1269,10 +1257,6 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch -# FIXME -#ApplyPatch hibernate-freeze-filesystems.patch -ApplyPatch hibernate-watermark.patch - ApplyPatch lis3-improve-handling-of-null-rate.patch ApplyPatch bluetooth-use-after-free.patch @@ -1304,27 +1288,15 @@ ApplyPatch weird-root-dentry-name-debug.patch #rhbz 808207 CVE-2012-1601 ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch -#rhbz 770476 -ApplyPatch iwlwifi-do-not-nulify-ctx-vif-on-reset.patch - #rhbz 807632 ApplyPatch libata-forbid-port-runtime-pm-by-default.patch -#rhbz 797559 -ApplyPatch x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch -ApplyPatch x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch - #rhbz 806295 ApplyPatch disable-hid-battery.patch #rhbz 814278 814289 CVE-2012-2119 ApplyPatch macvtap-zerocopy-validate-vector-length.patch -ApplyPatch input-synaptics-fix-regression-with-image-sensor-trackpads.patch - -#rhbz 783708 -ApplyPatch ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch - #rhbz 817298 ApplyPatch ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch @@ -1983,6 +1955,10 @@ fi # and build. %changelog +* Mon May 07 2012 Josh Boyer 2.6.43.5-1 +- Linux 3.3.5 +- Add patch to rate limit NFSv4 message (rhbz 732748) + * Fri May 04 2012 Josh Boyer - unfiltered netdev rio_ioctl access by users (rhbz 818820) diff --git a/sources b/sources index 1918a7281..ae9616785 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz -9c4cc16f10b645fbb90f6c05ad388883 patch-3.3.4.xz +d346edca5d3de7052f49996b01cef401 patch-3.3.5.xz diff --git a/x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch b/x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch deleted file mode 100644 index d69317316..000000000 --- a/x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch +++ /dev/null @@ -1,163 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Borislav Petkov -Newsgroups: gmane.linux.kernel -Subject: [PATCH 2/2] x86, microcode: Ensure that module is only loaded for -Date: Thu, 12 Apr 2012 18:34:22 +0200 -Lines: 80 -Approved: news@gmane.org -Message-ID: <20120412163422.GM24549@aftab> -References: <20120411163849.GE4794@alberich.amd.com> - <20120411200601.GC12288@kroah.com> - <20120411201053.GF18114@aftab> - <20120412162351.GJ24549@aftab> -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset="us-ascii" -X-Trace: dough.gmane.org 1334248500 15307 80.91.229.3 (12 Apr 2012 16:35:00 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Thu, 12 Apr 2012 16:35:00 +0000 (UTC) -Cc: Andreas Herrmann , - Kay Sievers , - Dave Jones , -To: Greg Kroah-Hartman -Original-X-From: linux-kernel-owner@vger.kernel.org Thu Apr 12 18:34:59 2012 -Return-path: -Envelope-to: glk-linux-kernel-3@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1SIMz4-0008MV-3g - for glk-linux-kernel-3@plane.gmane.org; Thu, 12 Apr 2012 18:34:58 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S965760Ab2DLQep (ORCPT ); - Thu, 12 Apr 2012 12:34:45 -0400 -Original-Received: from db3ehsobe002.messaging.microsoft.com ([213.199.154.140]:56919 - "EHLO db3outboundpool.messaging.microsoft.com" rhost-flags-OK-OK-OK-OK) - by vger.kernel.org with ESMTP id S965553Ab2DLQen (ORCPT - ); - Thu, 12 Apr 2012 12:34:43 -0400 -Original-Received: from mail2-db3-R.bigfish.com (10.3.81.239) by - DB3EHSOBE005.bigfish.com (10.3.84.25) with Microsoft SMTP Server id - 14.1.225.23; Thu, 12 Apr 2012 16:34:41 +0000 -Original-Received: from mail2-db3 (localhost [127.0.0.1]) by mail2-db3-R.bigfish.com - (Postfix) with ESMTP id E4EF14404B4; Thu, 12 Apr 2012 16:34:41 +0000 (UTC) -X-SpamScore: 0 -X-BigFish: VPS0(zzzz1202hzz8275bh8275dhz2dh668h839h944hd25hd2bh) -X-Forefront-Antispam-Report: CIP:163.181.249.108;KIP:(null);UIP:(null);IPV:NLI;H:ausb3twp01.amd.com;RD:none;EFVD:NLI -Original-Received: from mail2-db3 (localhost.localdomain [127.0.0.1]) by mail2-db3 - (MessageSwitch) id 1334248479906480_3860; Thu, 12 Apr 2012 16:34:39 +0000 - (UTC) -Original-Received: from DB3EHSMHS005.bigfish.com (unknown [10.3.81.241]) by - mail2-db3.bigfish.com (Postfix) with ESMTP id CEB76400A4; Thu, 12 Apr 2012 - 16:34:39 +0000 (UTC) -Original-Received: from ausb3twp01.amd.com (163.181.249.108) by - DB3EHSMHS005.bigfish.com (10.3.87.105) with Microsoft SMTP Server id - 14.1.225.23; Thu, 12 Apr 2012 16:34:38 +0000 -X-WSS-ID: 0M2DKPO-01-CNU-02 -X-M-MSG: -Original-Received: from sausexedgep02.amd.com (sausexedgep02-ext.amd.com - [163.181.249.73]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No - client certificate requested) by ausb3twp01.amd.com (Axway MailGate 3.8.1) - with ESMTP id 2C1D81028100; Thu, 12 Apr 2012 11:34:36 -0500 (CDT) -Original-Received: from SAUSEXDAG02.amd.com (163.181.55.2) by sausexedgep02.amd.com - (163.181.36.59) with Microsoft SMTP Server (TLS) id 8.3.192.1; Thu, 12 Apr - 2012 11:34:51 -0500 -Original-Received: from storexhtp01.amd.com (172.24.4.3) by sausexdag02.amd.com - (163.181.55.2) with Microsoft SMTP Server (TLS) id 14.1.323.3; Thu, 12 Apr - 2012 11:34:36 -0500 -Original-Received: from gwo.osrc.amd.com (165.204.16.204) by storexhtp01.amd.com - (172.24.4.3) with Microsoft SMTP Server id 8.3.213.0; Thu, 12 Apr 2012 - 12:34:35 -0400 -Original-Received: from aftab (aftab.osrc.amd.com [165.204.15.109]) by gwo.osrc.amd.com - (Postfix) with ESMTP id D8E4C49C58B; Thu, 12 Apr 2012 17:34:33 +0100 (BST) -Content-Disposition: inline -In-Reply-To: <20120412162351.GJ24549@aftab> -User-Agent: Mutt/1.5.21 (2010-09-15) -X-OriginatorOrg: amd.com -Original-Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel:1281050 -Archived-At: - -From: Andreas Herrmann -Date: Thu, 12 Apr 2012 16:51:57 +0200 -Subject: [PATCH 2/2] x86, microcode: Ensure that module is only loaded for supported AMD CPUs - -Exit early when there's no support for a particular CPU family. Also, -fixup the "no support for this CPU vendor" to be issued only when the -driver is attempted to be loaded on an unsupported vendor. - -Cc: stable@vger.kernel.org -Cc: Tigran Aivazian -Cc: Borislav Petkov -[Boris: added a commit msg because Andreas is lazy] -Signed-off-by: Andreas Herrmann ---- - arch/x86/kernel/microcode_amd.c | 12 +++++++----- - arch/x86/kernel/microcode_core.c | 6 +++--- - 2 files changed, 10 insertions(+), 8 deletions(-) - -diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c -index 73465aa..8a2ce8f 100644 ---- a/arch/x86/kernel/microcode_amd.c -+++ b/arch/x86/kernel/microcode_amd.c -@@ -82,11 +82,6 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) - { - struct cpuinfo_x86 *c = &cpu_data(cpu); - -- if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { -- pr_warning("CPU%d: family %d not supported\n", cpu, c->x86); -- return -1; -- } -- - csig->rev = c->microcode; - pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev); - -@@ -380,6 +375,13 @@ static struct microcode_ops microcode_amd_ops = { - - struct microcode_ops * __init init_amd_microcode(void) - { -+ struct cpuinfo_x86 *c = &cpu_data(0); -+ -+ if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { -+ pr_warning("AMD CPU family 0x%x not supported\n", c->x86); -+ return NULL; -+ } -+ - patch = (void *)get_zeroed_page(GFP_KERNEL); - if (!patch) - return NULL; -diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c -index d389e74..c9bda6d 100644 ---- a/arch/x86/kernel/microcode_core.c -+++ b/arch/x86/kernel/microcode_core.c -@@ -526,11 +526,11 @@ static int __init microcode_init(void) - microcode_ops = init_intel_microcode(); - else if (c->x86_vendor == X86_VENDOR_AMD) - microcode_ops = init_amd_microcode(); -- -- if (!microcode_ops) { -+ else - pr_err("no support for this CPU vendor\n"); -+ -+ if (!microcode_ops) - return -ENODEV; -- } - - microcode_pdev = platform_device_register_simple("microcode", -1, - NULL, 0); --- -1.7.8.4 - --- -Regards/Gruss, -Boris. - -Advanced Micro Devices GmbH -Einsteinring 24, 85609 Dornach -GM: Alberto Bozzo -Reg: Dornach, Landkreis Muenchen -HRB Nr. 43632 WEEE Registernr: 129 19551 - diff --git a/x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch b/x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch deleted file mode 100644 index d1cafc162..000000000 --- a/x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch +++ /dev/null @@ -1,167 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Borislav Petkov -Newsgroups: gmane.linux.kernel -Subject: [PATCH 1/2] x86, microcode: Fix sysfs warning during module unload -Date: Thu, 12 Apr 2012 18:30:38 +0200 -Lines: 83 -Approved: news@gmane.org -Message-ID: <20120412163038.GL24549@aftab> -References: <20120411163849.GE4794@alberich.amd.com> - <20120411200601.GC12288@kroah.com> - <20120411201053.GF18114@aftab> - <20120412162351.GJ24549@aftab> -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset="us-ascii" -X-Trace: dough.gmane.org 1334248312 13759 80.91.229.3 (12 Apr 2012 16:31:52 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Thu, 12 Apr 2012 16:31:52 +0000 (UTC) -Cc: Andreas Herrmann , - Kay Sievers , - Dave Jones , -To: Greg Kroah-Hartman -Original-X-From: linux-kernel-owner@vger.kernel.org Thu Apr 12 18:31:50 2012 -Return-path: -Envelope-to: glk-linux-kernel-3@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1SIMw1-0005nm-KE - for glk-linux-kernel-3@plane.gmane.org; Thu, 12 Apr 2012 18:31:49 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S934534Ab2DLQbF (ORCPT ); - Thu, 12 Apr 2012 12:31:05 -0400 -Original-Received: from db3ehsobe004.messaging.microsoft.com ([213.199.154.142]:35401 - "EHLO db3outboundpool.messaging.microsoft.com" rhost-flags-OK-OK-OK-OK) - by vger.kernel.org with ESMTP id S934436Ab2DLQbD (ORCPT - ); - Thu, 12 Apr 2012 12:31:03 -0400 -Original-Received: from mail117-db3-R.bigfish.com (10.3.81.240) by - DB3EHSOBE002.bigfish.com (10.3.84.22) with Microsoft SMTP Server id - 14.1.225.23; Thu, 12 Apr 2012 16:31:00 +0000 -Original-Received: from mail117-db3 (localhost [127.0.0.1]) by - mail117-db3-R.bigfish.com (Postfix) with ESMTP id BAA93180481; Thu, 12 Apr - 2012 16:31:00 +0000 (UTC) -X-SpamScore: 1 -X-BigFish: VPS1(zzzz1202hzz8275eh8275bh8275dha1495iz2dh668h839h944hd25hd2bh) -X-Forefront-Antispam-Report: CIP:163.181.249.109;KIP:(null);UIP:(null);IPV:NLI;H:ausb3twp02.amd.com;RD:none;EFVD:NLI -Original-Received: from mail117-db3 (localhost.localdomain [127.0.0.1]) by mail117-db3 - (MessageSwitch) id 133424825930391_28243; Thu, 12 Apr 2012 16:30:59 +0000 - (UTC) -Original-Received: from DB3EHSMHS006.bigfish.com (unknown [10.3.81.226]) by - mail117-db3.bigfish.com (Postfix) with ESMTP id ED7022E004F; Thu, 12 Apr 2012 - 16:30:58 +0000 (UTC) -Original-Received: from ausb3twp02.amd.com (163.181.249.109) by - DB3EHSMHS006.bigfish.com (10.3.87.106) with Microsoft SMTP Server id - 14.1.225.23; Thu, 12 Apr 2012 16:30:57 +0000 -X-WSS-ID: 0M2DKJG-02-0NU-02 -X-M-MSG: -Original-Received: from sausexedgep01.amd.com (sausexedgep01-ext.amd.com - [163.181.249.72]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No - client certificate requested) by ausb3twp02.amd.com (Axway MailGate 3.8.1) - with ESMTP id 21D3FC814C; Thu, 12 Apr 2012 11:30:50 -0500 (CDT) -Original-Received: from SAUSEXDAG01.amd.com (163.181.55.1) by sausexedgep01.amd.com - (163.181.36.54) with Microsoft SMTP Server (TLS) id 8.3.192.1; Thu, 12 Apr - 2012 11:31:09 -0500 -Original-Received: from storexhtp02.amd.com (172.24.4.4) by sausexdag01.amd.com - (163.181.55.1) with Microsoft SMTP Server (TLS) id 14.1.323.3; Thu, 12 Apr - 2012 11:30:54 -0500 -Original-Received: from gwo.osrc.amd.com (165.204.16.204) by storexhtp02.amd.com - (172.24.4.4) with Microsoft SMTP Server id 8.3.213.0; Thu, 12 Apr 2012 - 12:30:51 -0400 -Original-Received: from aftab (aftab.osrc.amd.com [165.204.15.109]) by gwo.osrc.amd.com - (Postfix) with ESMTP id 0D00D49C58B; Thu, 12 Apr 2012 17:30:50 +0100 (BST) -Content-Disposition: inline -In-Reply-To: <20120412162351.GJ24549@aftab> -User-Agent: Mutt/1.5.21 (2010-09-15) -X-OriginatorOrg: amd.com -Original-Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel:1281049 -Archived-At: - -From: Andreas Herrmann -Date: Thu, 12 Apr 2012 16:48:01 +0200 -Subject: [PATCH 1/2] x86, microcode: Fix sysfs warning during module unload on unsupported CPUs - -Loading microcode driver on an unsupported CPU and subsequently -unloading the driver causes - - WARNING: at fs/sysfs/group.c:138 mc_device_remove+0x5f/0x70 [microcode]() - Hardware name: 01972NG - sysfs group ffffffffa00013d0 not found for kobject 'cpu0' - Modules linked in: snd_hda_codec_hdmi snd_hda_codec_conexant snd_hda_intel btusb snd_hda_codec bluetooth thinkpad_acpi rfkill microcode(-) [last unloaded: cfg80211] - Pid: 4560, comm: modprobe Not tainted 3.4.0-rc2-00002-g258f742 #5 - Call Trace: - [] ? warn_slowpath_common+0x7b/0xc0 - [] ? warn_slowpath_fmt+0x45/0x50 - [] ? sysfs_remove_group+0x34/0x120 - [] ? mc_device_remove+0x5f/0x70 [microcode] - [] ? subsys_interface_unregister+0x69/0xa0 - [] ? mutex_lock+0x16/0x40 - [] ? microcode_exit+0x50/0x92 [microcode] - [] ? sys_delete_module+0x16d/0x260 - [] ? wait_iff_congested+0x45/0x110 - [] ? page_fault+0x1f/0x30 - [] ? system_call_fastpath+0x16/0x1b - -on recent kernels. - -This is due to - - commit 8a25a2fd126c621f44f3aeaef80d51f00fc11639 - (cpu: convert 'cpu' and 'machinecheck' sysdev_class to a regular - subsystem) - -which renders - - commit 6c53cbfced048c421e4f72cb2183465f68fbc5e7 - (x86, microcode: Correct sysdev_add error path) - -useless. - -See http://marc.info/?l=linux-kernel&m=133416246406478 - -Avoid above warning by restoring the old driver behaviour before -commit 6c53cbfced048c421e4f72cb2183465f68fbc5e7 (x86, microcode: -Correct sysdev_add error path) - -Cc: stable@vger.kernel.org -Cc: Tigran Aivazian -Cc: Borislav Petkov -Signed-off-by: Andreas Herrmann ---- - arch/x86/kernel/microcode_core.c | 4 +--- - 1 files changed, 1 insertions(+), 3 deletions(-) - -diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c -index 87a0f86..d389e74 100644 ---- a/arch/x86/kernel/microcode_core.c -+++ b/arch/x86/kernel/microcode_core.c -@@ -419,10 +419,8 @@ static int mc_device_add(struct device *dev, struct subsys_interface *sif) - if (err) - return err; - -- if (microcode_init_cpu(cpu) == UCODE_ERROR) { -- sysfs_remove_group(&dev->kobj, &mc_attr_group); -+ if (microcode_init_cpu(cpu) == UCODE_ERROR) - return -EINVAL; -- } - - return err; - } --- -1.7.8.4 - --- -Regards/Gruss, -Boris. - -Advanced Micro Devices GmbH -Einsteinring 24, 85609 Dornach -GM: Alberto Bozzo -Reg: Dornach, Landkreis Muenchen -HRB Nr. 43632 WEEE Registernr: 129 19551 - From 29201d8820533bb60021f9f1b323505d12f93383 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 7 May 2012 14:50:48 -0300 Subject: [PATCH 385/397] Fix DVB-S zig-zag logic This logic got broken by the dvb_frontend.c rewrite. Signed-off-by: Mauro Carvalho Chehab --- dvbs-fix-zigzag.patch | 15 +++++++++++++++ kernel.spec | 7 ++++++- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 dvbs-fix-zigzag.patch diff --git a/dvbs-fix-zigzag.patch b/dvbs-fix-zigzag.patch new file mode 100644 index 000000000..4bc9daaf4 --- /dev/null +++ b/dvbs-fix-zigzag.patch @@ -0,0 +1,15 @@ +diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c +index 39696c6..de7dc29 100644 +--- a/drivers/media/dvb/dvb-core/dvb_frontend.c ++++ b/drivers/media/dvb/dvb-core/dvb_frontend.c +@@ -1898,6 +1898,10 @@ static int dtv_set_frontend(struct dvb_frontend *fe) + } else { + /* default values */ + switch (c->delivery_system) { ++ case SYS_DVBS: ++ case SYS_DVBS2: ++ case SYS_ISDBS: ++ case SYS_TURBO: + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_C: + fepriv->min_delay = HZ / 20; diff --git a/kernel.spec b/kernel.spec index 676a9d85a..ef4412199 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -630,6 +630,7 @@ Patch2802: linux-2.6-silence-acpi-blacklist.patch # media patches Patch2900: add-poll-requested-events.patch Patch2901: drivers-media-update.patch +Patch2902: dvbs-fix-zigzag.patch # fs fixes @@ -1246,6 +1247,7 @@ ApplyPatch quite-apm.patch # Media (V4L/DVB/IR) updates/fixes/experimental drivers # apply if non-empty ApplyPatch add-poll-requested-events.patch +ApplyPatch dvbs-fix-zigzag.patch ApplyOptionalPatch drivers-media-update.patch # Patches headed upstream @@ -1955,6 +1957,9 @@ fi # and build. %changelog +* Mon May 07 2012 Mauro Carvalho Chehab 2.6.43.5-2 +- Add patch to fix DVB-S zigzag (rhbz 814404) + * Mon May 07 2012 Josh Boyer 2.6.43.5-1 - Linux 3.3.5 - Add patch to rate limit NFSv4 message (rhbz 732748) From 9520d51b59fa1182701c1766f0cf322e1d93d8c9 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 14 May 2012 13:39:52 -0500 Subject: [PATCH 386/397] Linux 3.3.6 --- ...cpus-are-consistent-with-in-kernel-i.patch | 106 ------------------ config-generic | 2 + kernel.spec | 19 +--- ...Enable-keyboard-backlight-by-default.patch | 44 -------- sources | 2 +- 5 files changed, 8 insertions(+), 165 deletions(-) delete mode 100644 KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch delete mode 100644 sony-laptop-Enable-keyboard-backlight-by-default.patch diff --git a/KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch b/KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch deleted file mode 100644 index 7e1664f41..000000000 --- a/KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 5b40572ed5f0344b9dbee486a17c589ce1abe1a3 Mon Sep 17 00:00:00 2001 -From: Avi Kivity -Date: Mon, 5 Mar 2012 14:23:29 +0200 -Subject: [PATCH] KVM: Ensure all vcpus are consistent with in-kernel irqchip - settings - -If some vcpus are created before KVM_CREATE_IRQCHIP, then -irqchip_in_kernel() and vcpu->arch.apic will be inconsistent, leading -to potential NULL pointer dereferences. - -Fix by: -- ensuring that no vcpus are installed when KVM_CREATE_IRQCHIP is called -- ensuring that a vcpu has an apic if it is installed after KVM_CREATE_IRQCHIP - -This is somewhat long winded because vcpu->arch.apic is created without -kvm->lock held. - -Based on earlier patch by Michael Ellerman. - -Signed-off-by: Michael Ellerman -Signed-off-by: Avi Kivity ---- - arch/ia64/kvm/kvm-ia64.c | 5 +++++ - arch/x86/kvm/x86.c | 8 ++++++++ - include/linux/kvm_host.h | 7 +++++++ - virt/kvm/kvm_main.c | 4 ++++ - 4 files changed, 24 insertions(+), 0 deletions(-) - -diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c -index d8ddbba..f5104b7 100644 ---- a/arch/ia64/kvm/kvm-ia64.c -+++ b/arch/ia64/kvm/kvm-ia64.c -@@ -1172,6 +1172,11 @@ out: - - #define PALE_RESET_ENTRY 0x80000000ffffffb0UL - -+bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) -+{ -+ return irqchip_in_kernel(vcpu->kcm) == (vcpu->arch.apic != NULL); -+} -+ - int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) - { - struct kvm_vcpu *v; -diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c -index 3ee008f..be9594a 100644 ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -3199,6 +3199,9 @@ long kvm_arch_vm_ioctl(struct file *filp, - r = -EEXIST; - if (kvm->arch.vpic) - goto create_irqchip_unlock; -+ r = -EINVAL; -+ if (atomic_read(&kvm->online_vcpus)) -+ goto create_irqchip_unlock; - r = -ENOMEM; - vpic = kvm_create_pic(kvm); - if (vpic) { -@@ -6107,6 +6110,11 @@ void kvm_arch_check_processor_compat(void *rtn) - kvm_x86_ops->check_processor_compatibility(rtn); - } - -+bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) -+{ -+ return irqchip_in_kernel(vcpu->kvm) == (vcpu->arch.apic != NULL); -+} -+ - int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) - { - struct page *page; -diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h -index 355e445..759fa26 100644 ---- a/include/linux/kvm_host.h -+++ b/include/linux/kvm_host.h -@@ -805,6 +805,13 @@ static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu) - { - return vcpu->kvm->bsp_vcpu_id == vcpu->vcpu_id; - } -+ -+bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu); -+ -+#else -+ -+static bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) { return true; } -+ - #endif - - #ifdef __KVM_HAVE_DEVICE_ASSIGNMENT -diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c -index e4431ad..94e148e 100644 ---- a/virt/kvm/kvm_main.c -+++ b/virt/kvm/kvm_main.c -@@ -1651,6 +1651,10 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id) - goto vcpu_destroy; - - mutex_lock(&kvm->lock); -+ if (!kvm_vcpu_compatible(vcpu)) { -+ r = -EINVAL; -+ goto unlock_vcpu_destroy; -+ } - if (atomic_read(&kvm->online_vcpus) == KVM_MAX_VCPUS) { - r = -EINVAL; - goto unlock_vcpu_destroy; --- -1.7.7.6 - diff --git a/config-generic b/config-generic index 9d2c3341b..072b025d6 100644 --- a/config-generic +++ b/config-generic @@ -352,6 +352,8 @@ CONFIG_BLK_DEV_FD=m # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set + CONFIG_BLK_CPQ_DA=m CONFIG_BLK_CPQ_CISS_DA=m CONFIG_CISS_SCSI_TAPE=y diff --git a/kernel.spec b/kernel.spec index ef4412199..bec326fc9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 # Set rpm version accordingly @@ -676,9 +676,6 @@ Patch21232: rt2x00_fix_MCU_request_failures.patch #rhbz 789644 Patch21237: mcelog-rcu-splat.patch -#rhbz 728478 -Patch21242: sony-laptop-Enable-keyboard-backlight-by-default.patch - Patch21300: unhandled-irqs-switch-to-polling.patch #rhbz 804957 CVE-2012-1568 @@ -687,9 +684,6 @@ Patch21306: shlib_base_randomize.patch #rhbz 807632 Patch21385: libata-forbid-port-runtime-pm-by-default.patch -#rhbz 808207 CVE-2012-1601 -Patch21520: KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch - #rhbz 808559 Patch21530: ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch @@ -1277,9 +1271,6 @@ ApplyPatch bcma-brcmsmac-compat.patch #rhbz 789644 ApplyPatch mcelog-rcu-splat.patch -#rhbz 728478 -ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch - #rhbz 804957 CVE-2012-1568 ApplyPatch shlib_base_randomize.patch @@ -1287,9 +1278,6 @@ ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch -#rhbz 808207 CVE-2012-1601 -ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch - #rhbz 807632 ApplyPatch libata-forbid-port-runtime-pm-by-default.patch @@ -1957,6 +1945,9 @@ fi # and build. %changelog +* Mon May 14 2012 Justin M. Forbes 2.6.43.6-1 +- Linux 3.3.6 + * Mon May 07 2012 Mauro Carvalho Chehab 2.6.43.5-2 - Add patch to fix DVB-S zigzag (rhbz 814404) diff --git a/sony-laptop-Enable-keyboard-backlight-by-default.patch b/sony-laptop-Enable-keyboard-backlight-by-default.patch deleted file mode 100644 index c993fd86d..000000000 --- a/sony-laptop-Enable-keyboard-backlight-by-default.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0dbc2bc96b1ec741bdd43451c286ccd45da3310b Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Wed, 2 Nov 2011 14:31:59 -0400 -Subject: [PATCH] sony-laptop: Enable keyboard backlight by default - -When the keyboard backlight support was originally added, the commit said -to default it to on with a 10 second timeout. That actually wasn't the -case, as the default value is commented out for the kbd_backlight parameter. -Because it is a static variable, it gets set to 0 by default without some -other form of initialization. - -However, it seems the function to set the value wasn't actually called -immediately, so whatever state the keyboard was in initially would remain. -Then commit df410d522410e67660 was introduced during the 2.6.39 timeframe to -immediately set whatever value was present (as well as attempt to -restore/reset the state on module removal or resume). That seems to have -now forced the light off immediately when the module is loaded unless -the option kbd_backlight=1 is specified. - -Let's enable it by default again (for the first time). This should solve -https://bugzilla.redhat.com/show_bug.cgi?id=728478 - -Acked-by: Mattia Dongili -Signed-off-by: Josh Boyer ---- - drivers/platform/x86/sony-laptop.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c -index c006dee..40c4705 100644 ---- a/drivers/platform/x86/sony-laptop.c -+++ b/drivers/platform/x86/sony-laptop.c -@@ -127,7 +127,7 @@ MODULE_PARM_DESC(minor, - "default is -1 (automatic)"); - #endif - --static int kbd_backlight; /* = 1 */ -+static int kbd_backlight = 1; - module_param(kbd_backlight, int, 0444); - MODULE_PARM_DESC(kbd_backlight, - "set this to 0 to disable keyboard backlight, " --- -1.7.7.6 - diff --git a/sources b/sources index ae9616785..755d90dc6 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz -d346edca5d3de7052f49996b01cef401 patch-3.3.5.xz +a7f67e9c491403906e4bb475de194631 patch-3.3.6.xz From 1b8756327bc7e89ce560d6e0e5f4908cbf9e55d1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 15 May 2012 07:57:12 -0400 Subject: [PATCH 387/397] Fixup atl1c register programming (rhbz 749276) --- atl1c_net_next_update-3.3.patch | 3633 +++++++++++++++++++++++++++++++ kernel.spec | 11 +- 2 files changed, 3643 insertions(+), 1 deletion(-) create mode 100644 atl1c_net_next_update-3.3.patch diff --git a/atl1c_net_next_update-3.3.patch b/atl1c_net_next_update-3.3.patch new file mode 100644 index 000000000..6c53ed607 --- /dev/null +++ b/atl1c_net_next_update-3.3.patch @@ -0,0 +1,3633 @@ +diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c.h b/drivers/net/ethernet/atheros/atl1c/atl1c.h +index ca70e16..b2bf324 100644 +--- a/drivers/net/ethernet/atheros/atl1c/atl1c.h ++++ b/drivers/net/ethernet/atheros/atl1c/atl1c.h +@@ -74,8 +74,6 @@ + + #define AT_RX_BUF_SIZE (ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN) + #define MAX_JUMBO_FRAME_SIZE (6*1024) +-#define MAX_TSO_FRAME_SIZE (7*1024) +-#define MAX_TX_OFFLOAD_THRESH (9*1024) + + #define AT_MAX_RECEIVE_QUEUE 4 + #define AT_DEF_RECEIVE_QUEUE 1 +@@ -100,7 +98,7 @@ + #define ATL1C_ASPM_L0s_ENABLE 0x0001 + #define ATL1C_ASPM_L1_ENABLE 0x0002 + +-#define AT_REGS_LEN (75 * sizeof(u32)) ++#define AT_REGS_LEN (74 * sizeof(u32)) + #define AT_EEPROM_LEN 512 + + #define ATL1C_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i])) +@@ -297,20 +295,6 @@ enum atl1c_dma_req_block { + atl1c_dma_req_4096 = 5 + }; + +-enum atl1c_rss_mode { +- atl1c_rss_mode_disable = 0, +- atl1c_rss_sig_que = 1, +- atl1c_rss_mul_que_sig_int = 2, +- atl1c_rss_mul_que_mul_int = 4, +-}; +- +-enum atl1c_rss_type { +- atl1c_rss_disable = 0, +- atl1c_rss_ipv4 = 1, +- atl1c_rss_ipv4_tcp = 2, +- atl1c_rss_ipv6 = 4, +- atl1c_rss_ipv6_tcp = 8 +-}; + + enum atl1c_nic_type { + athr_l1c = 0, +@@ -388,7 +372,6 @@ struct atl1c_hw { + enum atl1c_dma_order dma_order; + enum atl1c_dma_rcb rcb_value; + enum atl1c_dma_req_block dmar_block; +- enum atl1c_dma_req_block dmaw_block; + + u16 device_id; + u16 vendor_id; +@@ -399,8 +382,6 @@ struct atl1c_hw { + u16 phy_id2; + + u32 intr_mask; +- u8 dmaw_dly_cnt; +- u8 dmar_dly_cnt; + + u8 preamble_len; + u16 max_frame_size; +@@ -440,10 +421,6 @@ struct atl1c_hw { + #define ATL1C_FPGA_VERSION 0x8000 + u16 link_cap_flags; + #define ATL1C_LINK_CAP_1000M 0x0001 +- u16 cmb_tpd; +- u16 cmb_rrd; +- u16 cmb_rx_timer; /* 2us resolution */ +- u16 cmb_tx_timer; + u32 smb_timer; + + u16 rrd_thresh; /* Threshold of number of RRD produced to trigger +@@ -451,9 +428,6 @@ struct atl1c_hw { + u16 tpd_thresh; + u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. */ + u8 rfd_burst; +- enum atl1c_rss_type rss_type; +- enum atl1c_rss_mode rss_mode; +- u8 rss_hash_bits; + u32 base_cpu; + u32 indirect_tab; + u8 mac_addr[ETH_ALEN]; +@@ -462,12 +436,12 @@ struct atl1c_hw { + bool phy_configured; + bool re_autoneg; + bool emi_ca; ++ bool msi_lnkpatch; /* link patch for specific platforms */ + }; + + /* + * atl1c_ring_header represents a single, contiguous block of DMA space +- * mapped for the three descriptor rings (tpd, rfd, rrd) and the two +- * message blocks (cmb, smb) described below ++ * mapped for the three descriptor rings (tpd, rfd, rrd) described below + */ + struct atl1c_ring_header { + void *desc; /* virtual address */ +@@ -541,16 +515,6 @@ struct atl1c_rrd_ring { + u16 next_to_clean; + }; + +-struct atl1c_cmb { +- void *cmb; +- dma_addr_t dma; +-}; +- +-struct atl1c_smb { +- void *smb; +- dma_addr_t dma; +-}; +- + /* board specific private data structure */ + struct atl1c_adapter { + struct net_device *netdev; +@@ -586,11 +550,8 @@ struct atl1c_adapter { + /* All Descriptor memory */ + struct atl1c_ring_header ring_header; + struct atl1c_tpd_ring tpd_ring[AT_MAX_TRANSMIT_QUEUE]; +- struct atl1c_rfd_ring rfd_ring[AT_MAX_RECEIVE_QUEUE]; +- struct atl1c_rrd_ring rrd_ring[AT_MAX_RECEIVE_QUEUE]; +- struct atl1c_cmb cmb; +- struct atl1c_smb smb; +- int num_rx_queues; ++ struct atl1c_rfd_ring rfd_ring; ++ struct atl1c_rrd_ring rrd_ring; + u32 bd_number; /* board number;*/ + }; + +@@ -618,8 +579,14 @@ struct atl1c_adapter { + #define AT_WRITE_REGW(a, reg, value) (\ + writew((value), ((a)->hw_addr + reg))) + +-#define AT_READ_REGW(a, reg) (\ +- readw((a)->hw_addr + reg)) ++#define AT_READ_REGW(a, reg, pdata) do { \ ++ if (unlikely((a)->hibernate)) { \ ++ readw((a)->hw_addr + reg); \ ++ *(u16 *)pdata = readw((a)->hw_addr + reg); \ ++ } else { \ ++ *(u16 *)pdata = readw((a)->hw_addr + reg); \ ++ } \ ++ } while (0) + + #define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \ + writel((value), (((a)->hw_addr + reg) + ((offset) << 2)))) +diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c +index 0a9326a..859ea84 100644 +--- a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c ++++ b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c +@@ -141,8 +141,7 @@ static void atl1c_get_regs(struct net_device *netdev, + + memset(p, 0, AT_REGS_LEN); + +- regs->version = 0; +- AT_READ_REG(hw, REG_VPD_CAP, p++); ++ regs->version = 1; + AT_READ_REG(hw, REG_PM_CTRL, p++); + AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL, p++); + AT_READ_REG(hw, REG_TWSI_CTRL, p++); +@@ -154,7 +153,7 @@ static void atl1c_get_regs(struct net_device *netdev, + AT_READ_REG(hw, REG_LINK_CTRL, p++); + AT_READ_REG(hw, REG_IDLE_STATUS, p++); + AT_READ_REG(hw, REG_MDIO_CTRL, p++); +- AT_READ_REG(hw, REG_SERDES_LOCK, p++); ++ AT_READ_REG(hw, REG_SERDES, p++); + AT_READ_REG(hw, REG_MAC_CTRL, p++); + AT_READ_REG(hw, REG_MAC_IPG_IFG, p++); + AT_READ_REG(hw, REG_MAC_STA_ADDR, p++); +@@ -167,9 +166,9 @@ static void atl1c_get_regs(struct net_device *netdev, + AT_READ_REG(hw, REG_WOL_CTRL, p++); + + atl1c_read_phy_reg(hw, MII_BMCR, &phy_data); +- regs_buff[73] = (u32) phy_data; ++ regs_buff[AT_REGS_LEN/sizeof(u32) - 2] = (u32) phy_data; + atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); +- regs_buff[74] = (u32) phy_data; ++ regs_buff[AT_REGS_LEN/sizeof(u32) - 1] = (u32) phy_data; + } + + static int atl1c_get_eeprom_len(struct net_device *netdev) +diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c +index 23f2ab0..2ea6a21 100644 +--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c ++++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c +@@ -43,7 +43,7 @@ int atl1c_check_eeprom_exist(struct atl1c_hw *hw) + return 0; + } + +-void atl1c_hw_set_mac_addr(struct atl1c_hw *hw) ++void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr) + { + u32 value; + /* +@@ -51,35 +51,48 @@ void atl1c_hw_set_mac_addr(struct atl1c_hw *hw) + * 0: 6AF600DC 1: 000B + * low dword + */ +- value = (((u32)hw->mac_addr[2]) << 24) | +- (((u32)hw->mac_addr[3]) << 16) | +- (((u32)hw->mac_addr[4]) << 8) | +- (((u32)hw->mac_addr[5])) ; ++ value = mac_addr[2] << 24 | ++ mac_addr[3] << 16 | ++ mac_addr[4] << 8 | ++ mac_addr[5]; + AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value); + /* hight dword */ +- value = (((u32)hw->mac_addr[0]) << 8) | +- (((u32)hw->mac_addr[1])) ; ++ value = mac_addr[0] << 8 | ++ mac_addr[1]; + AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value); + } + ++/* read mac address from hardware register */ ++static bool atl1c_read_current_addr(struct atl1c_hw *hw, u8 *eth_addr) ++{ ++ u32 addr[2]; ++ ++ AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]); ++ AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]); ++ ++ *(u32 *) ð_addr[2] = htonl(addr[0]); ++ *(u16 *) ð_addr[0] = htons((u16)addr[1]); ++ ++ return is_valid_ether_addr(eth_addr); ++} ++ + /* + * atl1c_get_permanent_address + * return 0 if get valid mac address, + */ + static int atl1c_get_permanent_address(struct atl1c_hw *hw) + { +- u32 addr[2]; + u32 i; + u32 otp_ctrl_data; + u32 twsi_ctrl_data; +- u32 ltssm_ctrl_data; +- u32 wol_data; +- u8 eth_addr[ETH_ALEN]; + u16 phy_data; + bool raise_vol = false; + ++ /* MAC-address from BIOS is the 1st priority */ ++ if (atl1c_read_current_addr(hw, hw->perm_mac_addr)) ++ return 0; ++ + /* init */ +- addr[0] = addr[1] = 0; + AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data); + if (atl1c_check_eeprom_exist(hw)) { + if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) { +@@ -91,33 +104,17 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw) + msleep(1); + } + } +- +- if (hw->nic_type == athr_l2c_b || +- hw->nic_type == athr_l2c_b2 || +- hw->nic_type == athr_l1d) { +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00); +- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) +- goto out; +- phy_data &= 0xFF7F; +- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); +- +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B); +- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) +- goto out; +- phy_data |= 0x8; +- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); ++ /* raise voltage temporally for l2cb */ ++ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { ++ atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data); ++ phy_data &= ~ANACTRL_HB_EN; ++ atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data); ++ atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); ++ phy_data |= VOLT_CTRL_SWLOWEST; ++ atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); + udelay(20); + raise_vol = true; + } +- /* close open bit of ReadOnly*/ +- AT_READ_REG(hw, REG_LTSSM_ID_CTRL, <ssm_ctrl_data); +- ltssm_ctrl_data &= ~LTSSM_ID_EN_WRO; +- AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, ltssm_ctrl_data); +- +- /* clear any WOL settings */ +- AT_WRITE_REG(hw, REG_WOL_CTRL, 0); +- AT_READ_REG(hw, REG_WOL_CTRL, &wol_data); +- + + AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data); + twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART; +@@ -138,37 +135,18 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw) + msleep(1); + } + if (raise_vol) { +- if (hw->nic_type == athr_l2c_b || +- hw->nic_type == athr_l2c_b2 || +- hw->nic_type == athr_l1d || +- hw->nic_type == athr_l1d_2) { +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00); +- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) +- goto out; +- phy_data |= 0x80; +- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); +- +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B); +- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) +- goto out; +- phy_data &= 0xFFF7; +- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); +- udelay(20); +- } ++ atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data); ++ phy_data |= ANACTRL_HB_EN; ++ atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data); ++ atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); ++ phy_data &= ~VOLT_CTRL_SWLOWEST; ++ atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); ++ udelay(20); + } + +- /* maybe MAC-address is from BIOS */ +- AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]); +- AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]); +- *(u32 *) ð_addr[2] = swab32(addr[0]); +- *(u16 *) ð_addr[0] = swab16(*(u16 *)&addr[1]); +- +- if (is_valid_ether_addr(eth_addr)) { +- memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN); ++ if (atl1c_read_current_addr(hw, hw->perm_mac_addr)) + return 0; +- } + +-out: + return -1; + } + +@@ -278,33 +256,158 @@ void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value) + } + + /* +- * Reads the value from a PHY register +- * hw - Struct containing variables accessed by shared code +- * reg_addr - address of the PHY register to read ++ * wait mdio module be idle ++ * return true: idle ++ * false: still busy + */ +-int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) ++bool atl1c_wait_mdio_idle(struct atl1c_hw *hw) + { + u32 val; + int i; + +- val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT | +- MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | +- MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; ++ for (i = 0; i < MDIO_MAX_AC_TO; i++) { ++ AT_READ_REG(hw, REG_MDIO_CTRL, &val); ++ if (!(val & (MDIO_CTRL_BUSY | MDIO_CTRL_START))) ++ break; ++ udelay(10); ++ } ++ ++ return i != MDIO_MAX_AC_TO; ++} ++ ++void atl1c_stop_phy_polling(struct atl1c_hw *hw) ++{ ++ if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) ++ return; ++ ++ AT_WRITE_REG(hw, REG_MDIO_CTRL, 0); ++ atl1c_wait_mdio_idle(hw); ++} + ++void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel) ++{ ++ u32 val; ++ ++ if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) ++ return; ++ ++ val = MDIO_CTRL_SPRES_PRMBL | ++ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | ++ FIELDX(MDIO_CTRL_REG, 1) | ++ MDIO_CTRL_START | ++ MDIO_CTRL_OP_READ; ++ AT_WRITE_REG(hw, REG_MDIO_CTRL, val); ++ atl1c_wait_mdio_idle(hw); ++ val |= MDIO_CTRL_AP_EN; ++ val &= ~MDIO_CTRL_START; + AT_WRITE_REG(hw, REG_MDIO_CTRL, val); ++ udelay(30); ++} + +- for (i = 0; i < MDIO_WAIT_TIMES; i++) { +- udelay(2); +- AT_READ_REG(hw, REG_MDIO_CTRL, &val); +- if (!(val & (MDIO_START | MDIO_BUSY))) +- break; ++ ++/* ++ * atl1c_read_phy_core ++ * core funtion to read register in PHY via MDIO control regsiter. ++ * ext: extension register (see IEEE 802.3) ++ * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0) ++ * reg: reg to read ++ */ ++int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, ++ u16 reg, u16 *phy_data) ++{ ++ u32 val; ++ u16 clk_sel = MDIO_CTRL_CLK_25_4; ++ ++ atl1c_stop_phy_polling(hw); ++ ++ *phy_data = 0; ++ ++ /* only l2c_b2 & l1d_2 could use slow clock */ ++ if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) && ++ hw->hibernate) ++ clk_sel = MDIO_CTRL_CLK_25_128; ++ if (ext) { ++ val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg); ++ AT_WRITE_REG(hw, REG_MDIO_EXTN, val); ++ val = MDIO_CTRL_SPRES_PRMBL | ++ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | ++ MDIO_CTRL_START | ++ MDIO_CTRL_MODE_EXT | ++ MDIO_CTRL_OP_READ; ++ } else { ++ val = MDIO_CTRL_SPRES_PRMBL | ++ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | ++ FIELDX(MDIO_CTRL_REG, reg) | ++ MDIO_CTRL_START | ++ MDIO_CTRL_OP_READ; + } +- if (!(val & (MDIO_START | MDIO_BUSY))) { +- *phy_data = (u16)val; +- return 0; ++ AT_WRITE_REG(hw, REG_MDIO_CTRL, val); ++ ++ if (!atl1c_wait_mdio_idle(hw)) ++ return -1; ++ ++ AT_READ_REG(hw, REG_MDIO_CTRL, &val); ++ *phy_data = (u16)FIELD_GETX(val, MDIO_CTRL_DATA); ++ ++ atl1c_start_phy_polling(hw, clk_sel); ++ ++ return 0; ++} ++ ++/* ++ * atl1c_write_phy_core ++ * core funtion to write to register in PHY via MDIO control regsiter. ++ * ext: extension register (see IEEE 802.3) ++ * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0) ++ * reg: reg to write ++ */ ++int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, ++ u16 reg, u16 phy_data) ++{ ++ u32 val; ++ u16 clk_sel = MDIO_CTRL_CLK_25_4; ++ ++ atl1c_stop_phy_polling(hw); ++ ++ ++ /* only l2c_b2 & l1d_2 could use slow clock */ ++ if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) && ++ hw->hibernate) ++ clk_sel = MDIO_CTRL_CLK_25_128; ++ ++ if (ext) { ++ val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg); ++ AT_WRITE_REG(hw, REG_MDIO_EXTN, val); ++ val = MDIO_CTRL_SPRES_PRMBL | ++ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | ++ FIELDX(MDIO_CTRL_DATA, phy_data) | ++ MDIO_CTRL_START | ++ MDIO_CTRL_MODE_EXT; ++ } else { ++ val = MDIO_CTRL_SPRES_PRMBL | ++ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | ++ FIELDX(MDIO_CTRL_DATA, phy_data) | ++ FIELDX(MDIO_CTRL_REG, reg) | ++ MDIO_CTRL_START; + } ++ AT_WRITE_REG(hw, REG_MDIO_CTRL, val); + +- return -1; ++ if (!atl1c_wait_mdio_idle(hw)) ++ return -1; ++ ++ atl1c_start_phy_polling(hw, clk_sel); ++ ++ return 0; ++} ++ ++/* ++ * Reads the value from a PHY register ++ * hw - Struct containing variables accessed by shared code ++ * reg_addr - address of the PHY register to read ++ */ ++int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) ++{ ++ return atl1c_read_phy_core(hw, false, 0, reg_addr, phy_data); + } + + /* +@@ -315,27 +418,47 @@ int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) + */ + int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data) + { +- int i; +- u32 val; ++ return atl1c_write_phy_core(hw, false, 0, reg_addr, phy_data); ++} + +- val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT | +- (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT | +- MDIO_SUP_PREAMBLE | MDIO_START | +- MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; ++/* read from PHY extension register */ ++int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr, ++ u16 reg_addr, u16 *phy_data) ++{ ++ return atl1c_read_phy_core(hw, true, dev_addr, reg_addr, phy_data); ++} + +- AT_WRITE_REG(hw, REG_MDIO_CTRL, val); ++/* write to PHY extension register */ ++int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr, ++ u16 reg_addr, u16 phy_data) ++{ ++ return atl1c_write_phy_core(hw, true, dev_addr, reg_addr, phy_data); ++} + +- for (i = 0; i < MDIO_WAIT_TIMES; i++) { +- udelay(2); +- AT_READ_REG(hw, REG_MDIO_CTRL, &val); +- if (!(val & (MDIO_START | MDIO_BUSY))) +- break; +- } ++int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) ++{ ++ int err; + +- if (!(val & (MDIO_START | MDIO_BUSY))) +- return 0; ++ err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr); ++ if (unlikely(err)) ++ return err; ++ else ++ err = atl1c_read_phy_reg(hw, MII_DBG_DATA, phy_data); + +- return -1; ++ return err; ++} ++ ++int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data) ++{ ++ int err; ++ ++ err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr); ++ if (unlikely(err)) ++ return err; ++ else ++ err = atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); ++ ++ return err; + } + + /* +@@ -380,119 +503,100 @@ static int atl1c_phy_setup_adv(struct atl1c_hw *hw) + + void atl1c_phy_disable(struct atl1c_hw *hw) + { +- AT_WRITE_REGW(hw, REG_GPHY_CTRL, +- GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET); ++ atl1c_power_saving(hw, 0); + } + +-static void atl1c_phy_magic_data(struct atl1c_hw *hw) +-{ +- u16 data; +- +- data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE | +- ((1 & ANA_INTERVAL_SEL_TIMER_MASK) << +- ANA_INTERVAL_SEL_TIMER_SHIFT); +- +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_18); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); +- +- data = (2 & ANA_SERDES_CDR_BW_MASK) | ANA_MS_PAD_DBG | +- ANA_SERDES_EN_DEEM | ANA_SERDES_SEL_HSP | ANA_SERDES_EN_PLL | +- ANA_SERDES_EN_LCKDT; +- +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_5); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); +- +- data = (44 & ANA_LONG_CABLE_TH_100_MASK) | +- ((33 & ANA_SHORT_CABLE_TH_100_MASK) << +- ANA_SHORT_CABLE_TH_100_SHIFT) | ANA_BP_BAD_LINK_ACCUM | +- ANA_BP_SMALL_BW; +- +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_54); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); +- +- data = (11 & ANA_IECHO_ADJ_MASK) | ((11 & ANA_IECHO_ADJ_MASK) << +- ANA_IECHO_ADJ_2_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) << +- ANA_IECHO_ADJ_1_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) << +- ANA_IECHO_ADJ_0_SHIFT); +- +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_4); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); +- +- data = ANA_RESTART_CAL | ((7 & ANA_MANUL_SWICH_ON_MASK) << +- ANA_MANUL_SWICH_ON_SHIFT) | ANA_MAN_ENABLE | +- ANA_SEL_HSP | ANA_EN_HB | ANA_OEN_125M; +- +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_0); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); +- +- if (hw->ctrl_flags & ATL1C_HIB_DISABLE) { +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_41); +- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0) +- return; +- data &= ~ANA_TOP_PS_EN; +- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); +- +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_11); +- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0) +- return; +- data &= ~ANA_PS_HIB_EN; +- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); +- } +-} + + int atl1c_phy_reset(struct atl1c_hw *hw) + { + struct atl1c_adapter *adapter = hw->adapter; + struct pci_dev *pdev = adapter->pdev; + u16 phy_data; +- u32 phy_ctrl_data = GPHY_CTRL_DEFAULT; +- u32 mii_ier_data = IER_LINK_UP | IER_LINK_DOWN; ++ u32 phy_ctrl_data, lpi_ctrl; + int err; + +- if (hw->ctrl_flags & ATL1C_HIB_DISABLE) +- phy_ctrl_data &= ~GPHY_CTRL_HIB_EN; +- ++ /* reset PHY core */ ++ AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl_data); ++ phy_ctrl_data &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_PHY_IDDQ | ++ GPHY_CTRL_GATE_25M_EN | GPHY_CTRL_PWDOWN_HW | GPHY_CTRL_CLS); ++ phy_ctrl_data |= GPHY_CTRL_SEL_ANA_RST; ++ if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE)) ++ phy_ctrl_data |= (GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE); ++ else ++ phy_ctrl_data &= ~(GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE); + AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data); + AT_WRITE_FLUSH(hw); +- msleep(40); +- phy_ctrl_data |= GPHY_CTRL_EXT_RESET; +- AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data); ++ udelay(10); ++ AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data | GPHY_CTRL_EXT_RESET); + AT_WRITE_FLUSH(hw); +- msleep(10); ++ udelay(10 * GPHY_CTRL_EXT_RST_TO); /* delay 800us */ + ++ /* switch clock */ + if (hw->nic_type == athr_l2c_b) { +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x0A); +- atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xDFFF); ++ atl1c_read_phy_dbg(hw, MIIDBG_CFGLPSPD, &phy_data); ++ atl1c_write_phy_dbg(hw, MIIDBG_CFGLPSPD, ++ phy_data & ~CFGLPSPD_RSTCNT_CLK125SW); + } + +- if (hw->nic_type == athr_l2c_b || +- hw->nic_type == athr_l2c_b2 || +- hw->nic_type == athr_l1d || +- hw->nic_type == athr_l1d_2) { +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B); +- atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xFFF7); +- msleep(20); ++ /* tx-half amplitude issue fix */ ++ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { ++ atl1c_read_phy_dbg(hw, MIIDBG_CABLE1TH_DET, &phy_data); ++ phy_data |= CABLE1TH_DET_EN; ++ atl1c_write_phy_dbg(hw, MIIDBG_CABLE1TH_DET, phy_data); + } +- if (hw->nic_type == athr_l1d) { +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x929D); ++ ++ /* clear bit3 of dbgport 3B to lower voltage */ ++ if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE)) { ++ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { ++ atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); ++ phy_data &= ~VOLT_CTRL_SWLOWEST; ++ atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); ++ } ++ /* power saving config */ ++ phy_data = ++ hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 ? ++ L1D_LEGCYPS_DEF : L1C_LEGCYPS_DEF; ++ atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS, phy_data); ++ /* hib */ ++ atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, ++ SYSMODCTRL_IECHOADJ_DEF); ++ } else { ++ /* disable pws */ ++ atl1c_read_phy_dbg(hw, MIIDBG_LEGCYPS, &phy_data); ++ atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS, ++ phy_data & ~LEGCYPS_EN); ++ /* disable hibernate */ ++ atl1c_read_phy_dbg(hw, MIIDBG_HIBNEG, &phy_data); ++ atl1c_write_phy_dbg(hw, MIIDBG_HIBNEG, ++ phy_data & HIBNEG_PSHIB_EN); + } +- if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b2 +- || hw->nic_type == athr_l2c) { +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD); ++ /* disable AZ(EEE) by default */ ++ if (hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 || ++ hw->nic_type == athr_l2c_b2) { ++ AT_READ_REG(hw, REG_LPI_CTRL, &lpi_ctrl); ++ AT_WRITE_REG(hw, REG_LPI_CTRL, lpi_ctrl & ~LPI_CTRL_EN); ++ atl1c_write_phy_ext(hw, MIIEXT_ANEG, MIIEXT_LOCAL_EEEADV, 0); ++ atl1c_write_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL3, ++ L2CB_CLDCTRL3); + } +- err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data); ++ ++ /* other debug port to set */ ++ atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, ANACTRL_DEF); ++ atl1c_write_phy_dbg(hw, MIIDBG_SRDSYSMOD, SRDSYSMOD_DEF); ++ atl1c_write_phy_dbg(hw, MIIDBG_TST10BTCFG, TST10BTCFG_DEF); ++ /* UNH-IOL test issue, set bit7 */ ++ atl1c_write_phy_dbg(hw, MIIDBG_TST100BTCFG, ++ TST100BTCFG_DEF | TST100BTCFG_LITCH_EN); ++ ++ /* set phy interrupt mask */ ++ phy_data = IER_LINK_UP | IER_LINK_DOWN; ++ err = atl1c_write_phy_reg(hw, MII_IER, phy_data); + if (err) { + if (netif_msg_hw(adapter)) + dev_err(&pdev->dev, + "Error enable PHY linkChange Interrupt\n"); + return err; + } +- if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) +- atl1c_phy_magic_data(hw); + return 0; + } + +@@ -589,7 +693,8 @@ int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex) + return 0; + } + +-int atl1c_phy_power_saving(struct atl1c_hw *hw) ++/* select one link mode to get lower power consumption */ ++int atl1c_phy_to_ps_link(struct atl1c_hw *hw) + { + struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; + struct pci_dev *pdev = adapter->pdev; +@@ -660,3 +765,101 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw) + + return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data); + } ++ ++int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc) ++{ ++ struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; ++ struct pci_dev *pdev = adapter->pdev; ++ u32 master_ctrl, mac_ctrl, phy_ctrl; ++ u32 wol_ctrl, speed; ++ u16 phy_data; ++ ++ wol_ctrl = 0; ++ speed = adapter->link_speed == SPEED_1000 ? ++ MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100; ++ ++ AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl); ++ AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl); ++ AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl); ++ ++ master_ctrl &= ~MASTER_CTRL_CLK_SEL_DIS; ++ mac_ctrl = FIELD_SETX(mac_ctrl, MAC_CTRL_SPEED, speed); ++ mac_ctrl &= ~(MAC_CTRL_DUPLX | MAC_CTRL_RX_EN | MAC_CTRL_TX_EN); ++ if (adapter->link_duplex == FULL_DUPLEX) ++ mac_ctrl |= MAC_CTRL_DUPLX; ++ phy_ctrl &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS); ++ phy_ctrl |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE | ++ GPHY_CTRL_HIB_EN; ++ if (!wufc) { /* without WoL */ ++ master_ctrl |= MASTER_CTRL_CLK_SEL_DIS; ++ phy_ctrl |= GPHY_CTRL_PHY_IDDQ | GPHY_CTRL_PWDOWN_HW; ++ AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl); ++ AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl); ++ AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl); ++ AT_WRITE_REG(hw, REG_WOL_CTRL, 0); ++ hw->phy_configured = false; /* re-init PHY when resume */ ++ return 0; ++ } ++ phy_ctrl |= GPHY_CTRL_EXT_RESET; ++ if (wufc & AT_WUFC_MAG) { ++ mac_ctrl |= MAC_CTRL_RX_EN | MAC_CTRL_BC_EN; ++ wol_ctrl |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN; ++ if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V11) ++ wol_ctrl |= WOL_PATTERN_EN | WOL_PATTERN_PME_EN; ++ } ++ if (wufc & AT_WUFC_LNKC) { ++ wol_ctrl |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN; ++ if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) { ++ dev_dbg(&pdev->dev, "%s: write phy MII_IER faild.\n", ++ atl1c_driver_name); ++ } ++ } ++ /* clear PHY interrupt */ ++ atl1c_read_phy_reg(hw, MII_ISR, &phy_data); ++ ++ dev_dbg(&pdev->dev, "%s: suspend MAC=%x,MASTER=%x,PHY=0x%x,WOL=%x\n", ++ atl1c_driver_name, mac_ctrl, master_ctrl, phy_ctrl, wol_ctrl); ++ AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl); ++ AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl); ++ AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl); ++ AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl); ++ ++ return 0; ++} ++ ++ ++/* configure phy after Link change Event */ ++void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed) ++{ ++ u16 phy_val; ++ bool adj_thresh = false; ++ ++ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 || ++ hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2) ++ adj_thresh = true; ++ ++ if (link_speed != SPEED_0) { /* link up */ ++ /* az with brcm, half-amp */ ++ if (hw->nic_type == athr_l1d_2) { ++ atl1c_read_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL6, ++ &phy_val); ++ phy_val = FIELD_GETX(phy_val, CLDCTRL6_CAB_LEN); ++ phy_val = phy_val > CLDCTRL6_CAB_LEN_SHORT ? ++ AZ_ANADECT_LONG : AZ_ANADECT_DEF; ++ atl1c_write_phy_dbg(hw, MIIDBG_AZ_ANADECT, phy_val); ++ } ++ /* threshold adjust */ ++ if (adj_thresh && link_speed == SPEED_100 && hw->msi_lnkpatch) { ++ atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, L1D_MSE16DB_UP); ++ atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, ++ L1D_SYSMODCTRL_IECHOADJ_DEF); ++ } ++ } else { /* link down */ ++ if (adj_thresh && hw->msi_lnkpatch) { ++ atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, ++ SYSMODCTRL_IECHOADJ_DEF); ++ atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, ++ L1D_MSE16DB_DOWN); ++ } ++ } ++} +diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h +index 655fc6c..17d935b 100644 +--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h ++++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h +@@ -25,12 +25,18 @@ + #include + #include + ++#define FIELD_GETX(_x, _name) ((_x) >> (_name##_SHIFT) & (_name##_MASK)) ++#define FIELD_SETX(_x, _name, _v) \ ++(((_x) & ~((_name##_MASK) << (_name##_SHIFT))) |\ ++(((_v) & (_name##_MASK)) << (_name##_SHIFT))) ++#define FIELDX(_name, _v) (((_v) & (_name##_MASK)) << (_name##_SHIFT)) ++ + struct atl1c_adapter; + struct atl1c_hw; + + /* function prototype */ + void atl1c_phy_disable(struct atl1c_hw *hw); +-void atl1c_hw_set_mac_addr(struct atl1c_hw *hw); ++void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr); + int atl1c_phy_reset(struct atl1c_hw *hw); + int atl1c_read_mac_addr(struct atl1c_hw *hw); + int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex); +@@ -42,47 +48,45 @@ bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value); + int atl1c_phy_init(struct atl1c_hw *hw); + int atl1c_check_eeprom_exist(struct atl1c_hw *hw); + int atl1c_restart_autoneg(struct atl1c_hw *hw); +-int atl1c_phy_power_saving(struct atl1c_hw *hw); ++int atl1c_phy_to_ps_link(struct atl1c_hw *hw); ++int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc); ++bool atl1c_wait_mdio_idle(struct atl1c_hw *hw); ++void atl1c_stop_phy_polling(struct atl1c_hw *hw); ++void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel); ++int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, ++ u16 reg, u16 *phy_data); ++int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, ++ u16 reg, u16 phy_data); ++int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr, ++ u16 reg_addr, u16 *phy_data); ++int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr, ++ u16 reg_addr, u16 phy_data); ++int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data); ++int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data); ++void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed); ++ ++/* hw-ids */ ++#define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062 ++#define PCI_DEVICE_ID_ATTANSIC_L1C 0x1063 ++#define PCI_DEVICE_ID_ATHEROS_L2C_B 0x2060 /* AR8152 v1.1 Fast 10/100 */ ++#define PCI_DEVICE_ID_ATHEROS_L2C_B2 0x2062 /* AR8152 v2.0 Fast 10/100 */ ++#define PCI_DEVICE_ID_ATHEROS_L1D 0x1073 /* AR8151 v1.0 Gigabit 1000 */ ++#define PCI_DEVICE_ID_ATHEROS_L1D_2_0 0x1083 /* AR8151 v2.0 Gigabit 1000 */ ++#define L2CB_V10 0xc0 ++#define L2CB_V11 0xc1 ++ + /* register definition */ + #define REG_DEVICE_CAP 0x5C + #define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7 + #define DEVICE_CAP_MAX_PAYLOAD_SHIFT 0 + +-#define REG_DEVICE_CTRL 0x60 +-#define DEVICE_CTRL_MAX_PAYLOAD_MASK 0x7 +-#define DEVICE_CTRL_MAX_PAYLOAD_SHIFT 5 +-#define DEVICE_CTRL_MAX_RREQ_SZ_MASK 0x7 +-#define DEVICE_CTRL_MAX_RREQ_SZ_SHIFT 12 ++#define DEVICE_CTRL_MAXRRS_MIN 2 + + #define REG_LINK_CTRL 0x68 + #define LINK_CTRL_L0S_EN 0x01 + #define LINK_CTRL_L1_EN 0x02 + #define LINK_CTRL_EXT_SYNC 0x80 + +-#define REG_VPD_CAP 0x6C +-#define VPD_CAP_ID_MASK 0xff +-#define VPD_CAP_ID_SHIFT 0 +-#define VPD_CAP_NEXT_PTR_MASK 0xFF +-#define VPD_CAP_NEXT_PTR_SHIFT 8 +-#define VPD_CAP_VPD_ADDR_MASK 0x7FFF +-#define VPD_CAP_VPD_ADDR_SHIFT 16 +-#define VPD_CAP_VPD_FLAG 0x80000000 +- +-#define REG_VPD_DATA 0x70 +- +-#define REG_PCIE_UC_SEVERITY 0x10C +-#define PCIE_UC_SERVRITY_TRN 0x00000001 +-#define PCIE_UC_SERVRITY_DLP 0x00000010 +-#define PCIE_UC_SERVRITY_PSN_TLP 0x00001000 +-#define PCIE_UC_SERVRITY_FCP 0x00002000 +-#define PCIE_UC_SERVRITY_CPL_TO 0x00004000 +-#define PCIE_UC_SERVRITY_CA 0x00008000 +-#define PCIE_UC_SERVRITY_UC 0x00010000 +-#define PCIE_UC_SERVRITY_ROV 0x00020000 +-#define PCIE_UC_SERVRITY_MLFP 0x00040000 +-#define PCIE_UC_SERVRITY_ECRC 0x00080000 +-#define PCIE_UC_SERVRITY_UR 0x00100000 +- + #define REG_DEV_SERIALNUM_CTRL 0x200 + #define REG_DEV_MAC_SEL_MASK 0x0 /* 0:EUI; 1:MAC */ + #define REG_DEV_MAC_SEL_SHIFT 0 +@@ -90,25 +94,17 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define REG_DEV_SERIAL_NUM_EN_SHIFT 1 + + #define REG_TWSI_CTRL 0x218 ++#define TWSI_CTLR_FREQ_MASK 0x3UL ++#define TWSI_CTRL_FREQ_SHIFT 24 ++#define TWSI_CTRL_FREQ_100K 0 ++#define TWSI_CTRL_FREQ_200K 1 ++#define TWSI_CTRL_FREQ_300K 2 ++#define TWSI_CTRL_FREQ_400K 3 ++#define TWSI_CTRL_LD_EXIST BIT(23) ++#define TWSI_CTRL_HW_LDSTAT BIT(12) /* 0:finish,1:in progress */ ++#define TWSI_CTRL_SW_LDSTART BIT(11) + #define TWSI_CTRL_LD_OFFSET_MASK 0xFF + #define TWSI_CTRL_LD_OFFSET_SHIFT 0 +-#define TWSI_CTRL_LD_SLV_ADDR_MASK 0x7 +-#define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8 +-#define TWSI_CTRL_SW_LDSTART 0x800 +-#define TWSI_CTRL_HW_LDSTART 0x1000 +-#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x7F +-#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15 +-#define TWSI_CTRL_LD_EXIST 0x400000 +-#define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3 +-#define TWSI_CTRL_READ_FREQ_SEL_SHIFT 23 +-#define TWSI_CTRL_FREQ_SEL_100K 0 +-#define TWSI_CTRL_FREQ_SEL_200K 1 +-#define TWSI_CTRL_FREQ_SEL_300K 2 +-#define TWSI_CTRL_FREQ_SEL_400K 3 +-#define TWSI_CTRL_SMB_SLV_ADDR +-#define TWSI_CTRL_WRITE_FREQ_SEL_MASK 0x3 +-#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT 24 +- + + #define REG_PCIE_DEV_MISC_CTRL 0x21C + #define PCIE_DEV_MISC_EXT_PIPE 0x2 +@@ -118,16 +114,23 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define PCIE_DEV_MISC_SERDES_SEL_DIN 0x10 + + #define REG_PCIE_PHYMISC 0x1000 +-#define PCIE_PHYMISC_FORCE_RCV_DET 0x4 ++#define PCIE_PHYMISC_FORCE_RCV_DET BIT(2) ++#define PCIE_PHYMISC_NFTS_MASK 0xFFUL ++#define PCIE_PHYMISC_NFTS_SHIFT 16 + + #define REG_PCIE_PHYMISC2 0x1004 +-#define PCIE_PHYMISC2_SERDES_CDR_MASK 0x3 +-#define PCIE_PHYMISC2_SERDES_CDR_SHIFT 16 +-#define PCIE_PHYMISC2_SERDES_TH_MASK 0x3 +-#define PCIE_PHYMISC2_SERDES_TH_SHIFT 18 ++#define PCIE_PHYMISC2_L0S_TH_MASK 0x3UL ++#define PCIE_PHYMISC2_L0S_TH_SHIFT 18 ++#define L2CB1_PCIE_PHYMISC2_L0S_TH 3 ++#define PCIE_PHYMISC2_CDR_BW_MASK 0x3UL ++#define PCIE_PHYMISC2_CDR_BW_SHIFT 16 ++#define L2CB1_PCIE_PHYMISC2_CDR_BW 3 + + #define REG_TWSI_DEBUG 0x1108 +-#define TWSI_DEBUG_DEV_EXIST 0x20000000 ++#define TWSI_DEBUG_DEV_EXIST BIT(29) ++ ++#define REG_DMA_DBG 0x1114 ++#define DMA_DBG_VENDOR_MSG BIT(0) + + #define REG_EEPROM_CTRL 0x12C0 + #define EEPROM_CTRL_DATA_HI_MASK 0xFFFF +@@ -140,56 +143,81 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define REG_EEPROM_DATA_LO 0x12C4 + + #define REG_OTP_CTRL 0x12F0 +-#define OTP_CTRL_CLK_EN 0x0002 ++#define OTP_CTRL_CLK_EN BIT(1) + + #define REG_PM_CTRL 0x12F8 +-#define PM_CTRL_SDES_EN 0x00000001 +-#define PM_CTRL_RBER_EN 0x00000002 +-#define PM_CTRL_CLK_REQ_EN 0x00000004 +-#define PM_CTRL_ASPM_L1_EN 0x00000008 +-#define PM_CTRL_SERDES_L1_EN 0x00000010 +-#define PM_CTRL_SERDES_PLL_L1_EN 0x00000020 +-#define PM_CTRL_SERDES_PD_EX_L1 0x00000040 +-#define PM_CTRL_SERDES_BUDS_RX_L1_EN 0x00000080 +-#define PM_CTRL_L0S_ENTRY_TIMER_MASK 0xF +-#define PM_CTRL_L0S_ENTRY_TIMER_SHIFT 8 +-#define PM_CTRL_ASPM_L0S_EN 0x00001000 +-#define PM_CTRL_CLK_SWH_L1 0x00002000 +-#define PM_CTRL_CLK_PWM_VER1_1 0x00004000 +-#define PM_CTRL_RCVR_WT_TIMER 0x00008000 +-#define PM_CTRL_L1_ENTRY_TIMER_MASK 0xF +-#define PM_CTRL_L1_ENTRY_TIMER_SHIFT 16 +-#define PM_CTRL_PM_REQ_TIMER_MASK 0xF +-#define PM_CTRL_PM_REQ_TIMER_SHIFT 20 +-#define PM_CTRL_LCKDET_TIMER_MASK 0xF ++#define PM_CTRL_HOTRST BIT(31) ++#define PM_CTRL_MAC_ASPM_CHK BIT(30) /* L0s/L1 dis by MAC based on ++ * thrghput(setting in 15A0) */ ++#define PM_CTRL_SA_DLY_EN BIT(29) ++#define PM_CTRL_L0S_BUFSRX_EN BIT(28) ++#define PM_CTRL_LCKDET_TIMER_MASK 0xFUL + #define PM_CTRL_LCKDET_TIMER_SHIFT 24 +-#define PM_CTRL_EN_BUFS_RX_L0S 0x10000000 +-#define PM_CTRL_SA_DLY_EN 0x20000000 +-#define PM_CTRL_MAC_ASPM_CHK 0x40000000 +-#define PM_CTRL_HOTRST 0x80000000 ++#define PM_CTRL_LCKDET_TIMER_DEF 0xC ++#define PM_CTRL_PM_REQ_TIMER_MASK 0xFUL ++#define PM_CTRL_PM_REQ_TIMER_SHIFT 20 /* pm_request_l1 time > @ ++ * ->L0s not L1 */ ++#define PM_CTRL_PM_REQ_TO_DEF 0xF ++#define PMCTRL_TXL1_AFTER_L0S BIT(19) /* l1dv2.0+ */ ++#define L1D_PMCTRL_L1_ENTRY_TM_MASK 7UL /* l1dv2.0+, 3bits */ ++#define L1D_PMCTRL_L1_ENTRY_TM_SHIFT 16 ++#define L1D_PMCTRL_L1_ENTRY_TM_DIS 0 ++#define L1D_PMCTRL_L1_ENTRY_TM_2US 1 ++#define L1D_PMCTRL_L1_ENTRY_TM_4US 2 ++#define L1D_PMCTRL_L1_ENTRY_TM_8US 3 ++#define L1D_PMCTRL_L1_ENTRY_TM_16US 4 ++#define L1D_PMCTRL_L1_ENTRY_TM_24US 5 ++#define L1D_PMCTRL_L1_ENTRY_TM_32US 6 ++#define L1D_PMCTRL_L1_ENTRY_TM_63US 7 ++#define PM_CTRL_L1_ENTRY_TIMER_MASK 0xFUL /* l1C 4bits */ ++#define PM_CTRL_L1_ENTRY_TIMER_SHIFT 16 ++#define L2CB1_PM_CTRL_L1_ENTRY_TM 7 ++#define L1C_PM_CTRL_L1_ENTRY_TM 0xF ++#define PM_CTRL_RCVR_WT_TIMER BIT(15) /* 1:1us, 0:2ms */ ++#define PM_CTRL_CLK_PWM_VER1_1 BIT(14) /* 0:1.0a,1:1.1 */ ++#define PM_CTRL_CLK_SWH_L1 BIT(13) /* en pcie clk sw in L1 */ ++#define PM_CTRL_ASPM_L0S_EN BIT(12) ++#define PM_CTRL_RXL1_AFTER_L0S BIT(11) /* l1dv2.0+ */ ++#define L1D_PMCTRL_L0S_TIMER_MASK 7UL /* l1d2.0+, 3bits*/ ++#define L1D_PMCTRL_L0S_TIMER_SHIFT 8 ++#define PM_CTRL_L0S_ENTRY_TIMER_MASK 0xFUL /* l1c, 4bits */ ++#define PM_CTRL_L0S_ENTRY_TIMER_SHIFT 8 ++#define PM_CTRL_SERDES_BUFS_RX_L1_EN BIT(7) ++#define PM_CTRL_SERDES_PD_EX_L1 BIT(6) /* power down serdes rx */ ++#define PM_CTRL_SERDES_PLL_L1_EN BIT(5) ++#define PM_CTRL_SERDES_L1_EN BIT(4) ++#define PM_CTRL_ASPM_L1_EN BIT(3) ++#define PM_CTRL_CLK_REQ_EN BIT(2) ++#define PM_CTRL_RBER_EN BIT(1) ++#define PM_CTRL_SPRSDWER_EN BIT(0) + + #define REG_LTSSM_ID_CTRL 0x12FC + #define LTSSM_ID_EN_WRO 0x1000 ++ ++ + /* Selene Master Control Register */ + #define REG_MASTER_CTRL 0x1400 +-#define MASTER_CTRL_SOFT_RST 0x1 +-#define MASTER_CTRL_TEST_MODE_MASK 0x3 +-#define MASTER_CTRL_TEST_MODE_SHIFT 2 +-#define MASTER_CTRL_BERT_START 0x10 +-#define MASTER_CTRL_OOB_DIS_OFF 0x40 +-#define MASTER_CTRL_SA_TIMER_EN 0x80 +-#define MASTER_CTRL_MTIMER_EN 0x100 +-#define MASTER_CTRL_MANUAL_INT 0x200 +-#define MASTER_CTRL_TX_ITIMER_EN 0x400 +-#define MASTER_CTRL_RX_ITIMER_EN 0x800 +-#define MASTER_CTRL_CLK_SEL_DIS 0x1000 +-#define MASTER_CTRL_CLK_SWH_MODE 0x2000 +-#define MASTER_CTRL_INT_RDCLR 0x4000 +-#define MASTER_CTRL_REV_NUM_SHIFT 16 +-#define MASTER_CTRL_REV_NUM_MASK 0xff +-#define MASTER_CTRL_DEV_ID_SHIFT 24 +-#define MASTER_CTRL_DEV_ID_MASK 0x7f +-#define MASTER_CTRL_OTP_SEL 0x80000000 ++#define MASTER_CTRL_OTP_SEL BIT(31) ++#define MASTER_DEV_NUM_MASK 0x7FUL ++#define MASTER_DEV_NUM_SHIFT 24 ++#define MASTER_REV_NUM_MASK 0xFFUL ++#define MASTER_REV_NUM_SHIFT 16 ++#define MASTER_CTRL_INT_RDCLR BIT(14) ++#define MASTER_CTRL_CLK_SEL_DIS BIT(12) /* 1:alwys sel pclk from ++ * serdes, not sw to 25M */ ++#define MASTER_CTRL_RX_ITIMER_EN BIT(11) /* IRQ MODURATION FOR RX */ ++#define MASTER_CTRL_TX_ITIMER_EN BIT(10) /* MODURATION FOR TX/RX */ ++#define MASTER_CTRL_MANU_INT BIT(9) /* SOFT MANUAL INT */ ++#define MASTER_CTRL_MANUTIMER_EN BIT(8) ++#define MASTER_CTRL_SA_TIMER_EN BIT(7) /* SYS ALIVE TIMER EN */ ++#define MASTER_CTRL_OOB_DIS BIT(6) /* OUT OF BOX DIS */ ++#define MASTER_CTRL_WAKEN_25M BIT(5) /* WAKE WO. PCIE CLK */ ++#define MASTER_CTRL_BERT_START BIT(4) ++#define MASTER_PCIE_TSTMOD_MASK 3UL ++#define MASTER_PCIE_TSTMOD_SHIFT 2 ++#define MASTER_PCIE_RST BIT(1) ++#define MASTER_CTRL_SOFT_RST BIT(0) /* RST MAC & DMA */ ++#define DMA_MAC_RST_TO 50 + + /* Timer Initial Value Register */ + #define REG_MANUAL_TIMER_INIT 0x1404 +@@ -201,87 +229,85 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define IRQ_MODRT_RX_TIMER_SHIFT 16 + + #define REG_GPHY_CTRL 0x140C +-#define GPHY_CTRL_EXT_RESET 0x1 +-#define GPHY_CTRL_RTL_MODE 0x2 +-#define GPHY_CTRL_LED_MODE 0x4 +-#define GPHY_CTRL_ANEG_NOW 0x8 +-#define GPHY_CTRL_REV_ANEG 0x10 +-#define GPHY_CTRL_GATE_25M_EN 0x20 +-#define GPHY_CTRL_LPW_EXIT 0x40 +-#define GPHY_CTRL_PHY_IDDQ 0x80 +-#define GPHY_CTRL_PHY_IDDQ_DIS 0x100 +-#define GPHY_CTRL_GIGA_DIS 0x200 +-#define GPHY_CTRL_HIB_EN 0x400 +-#define GPHY_CTRL_HIB_PULSE 0x800 +-#define GPHY_CTRL_SEL_ANA_RST 0x1000 +-#define GPHY_CTRL_PHY_PLL_ON 0x2000 +-#define GPHY_CTRL_PWDOWN_HW 0x4000 +-#define GPHY_CTRL_PHY_PLL_BYPASS 0x8000 +- +-#define GPHY_CTRL_DEFAULT ( \ +- GPHY_CTRL_SEL_ANA_RST |\ +- GPHY_CTRL_HIB_PULSE |\ +- GPHY_CTRL_HIB_EN) +- +-#define GPHY_CTRL_PW_WOL_DIS ( \ +- GPHY_CTRL_SEL_ANA_RST |\ +- GPHY_CTRL_HIB_PULSE |\ +- GPHY_CTRL_HIB_EN |\ +- GPHY_CTRL_PWDOWN_HW |\ +- GPHY_CTRL_PHY_IDDQ) +- +-#define GPHY_CTRL_POWER_SAVING ( \ +- GPHY_CTRL_SEL_ANA_RST |\ +- GPHY_CTRL_HIB_EN |\ +- GPHY_CTRL_HIB_PULSE |\ +- GPHY_CTRL_PWDOWN_HW |\ +- GPHY_CTRL_PHY_IDDQ) ++#define GPHY_CTRL_ADDR_MASK 0x1FUL ++#define GPHY_CTRL_ADDR_SHIFT 19 ++#define GPHY_CTRL_BP_VLTGSW BIT(18) ++#define GPHY_CTRL_100AB_EN BIT(17) ++#define GPHY_CTRL_10AB_EN BIT(16) ++#define GPHY_CTRL_PHY_PLL_BYPASS BIT(15) ++#define GPHY_CTRL_PWDOWN_HW BIT(14) /* affect MAC&PHY, to low pw */ ++#define GPHY_CTRL_PHY_PLL_ON BIT(13) /* 1:pll always on, 0:can sw */ ++#define GPHY_CTRL_SEL_ANA_RST BIT(12) ++#define GPHY_CTRL_HIB_PULSE BIT(11) ++#define GPHY_CTRL_HIB_EN BIT(10) ++#define GPHY_CTRL_GIGA_DIS BIT(9) ++#define GPHY_CTRL_PHY_IDDQ_DIS BIT(8) /* pw on RST */ ++#define GPHY_CTRL_PHY_IDDQ BIT(7) /* bit8 affect bit7 while rb */ ++#define GPHY_CTRL_LPW_EXIT BIT(6) ++#define GPHY_CTRL_GATE_25M_EN BIT(5) ++#define GPHY_CTRL_REV_ANEG BIT(4) ++#define GPHY_CTRL_ANEG_NOW BIT(3) ++#define GPHY_CTRL_LED_MODE BIT(2) ++#define GPHY_CTRL_RTL_MODE BIT(1) ++#define GPHY_CTRL_EXT_RESET BIT(0) /* 1:out of DSP RST status */ ++#define GPHY_CTRL_EXT_RST_TO 80 /* 800us atmost */ ++#define GPHY_CTRL_CLS (\ ++ GPHY_CTRL_LED_MODE |\ ++ GPHY_CTRL_100AB_EN |\ ++ GPHY_CTRL_PHY_PLL_ON) ++ + /* Block IDLE Status Register */ +-#define REG_IDLE_STATUS 0x1410 +-#define IDLE_STATUS_MASK 0x00FF +-#define IDLE_STATUS_RXMAC_NO_IDLE 0x1 +-#define IDLE_STATUS_TXMAC_NO_IDLE 0x2 +-#define IDLE_STATUS_RXQ_NO_IDLE 0x4 +-#define IDLE_STATUS_TXQ_NO_IDLE 0x8 +-#define IDLE_STATUS_DMAR_NO_IDLE 0x10 +-#define IDLE_STATUS_DMAW_NO_IDLE 0x20 +-#define IDLE_STATUS_SMB_NO_IDLE 0x40 +-#define IDLE_STATUS_CMB_NO_IDLE 0x80 ++#define REG_IDLE_STATUS 0x1410 ++#define IDLE_STATUS_SFORCE_MASK 0xFUL ++#define IDLE_STATUS_SFORCE_SHIFT 14 ++#define IDLE_STATUS_CALIB_DONE BIT(13) ++#define IDLE_STATUS_CALIB_RES_MASK 0x1FUL ++#define IDLE_STATUS_CALIB_RES_SHIFT 8 ++#define IDLE_STATUS_CALIBERR_MASK 0xFUL ++#define IDLE_STATUS_CALIBERR_SHIFT 4 ++#define IDLE_STATUS_TXQ_BUSY BIT(3) ++#define IDLE_STATUS_RXQ_BUSY BIT(2) ++#define IDLE_STATUS_TXMAC_BUSY BIT(1) ++#define IDLE_STATUS_RXMAC_BUSY BIT(0) ++#define IDLE_STATUS_MASK (\ ++ IDLE_STATUS_TXQ_BUSY |\ ++ IDLE_STATUS_RXQ_BUSY |\ ++ IDLE_STATUS_TXMAC_BUSY |\ ++ IDLE_STATUS_RXMAC_BUSY) + + /* MDIO Control Register */ + #define REG_MDIO_CTRL 0x1414 +-#define MDIO_DATA_MASK 0xffff /* On MDIO write, the 16-bit +- * control data to write to PHY +- * MII management register */ +-#define MDIO_DATA_SHIFT 0 /* On MDIO read, the 16-bit +- * status data that was read +- * from the PHY MII management register */ +-#define MDIO_REG_ADDR_MASK 0x1f /* MDIO register address */ +-#define MDIO_REG_ADDR_SHIFT 16 +-#define MDIO_RW 0x200000 /* 1: read, 0: write */ +-#define MDIO_SUP_PREAMBLE 0x400000 /* Suppress preamble */ +-#define MDIO_START 0x800000 /* Write 1 to initiate the MDIO +- * master. And this bit is self +- * cleared after one cycle */ +-#define MDIO_CLK_SEL_SHIFT 24 +-#define MDIO_CLK_25_4 0 +-#define MDIO_CLK_25_6 2 +-#define MDIO_CLK_25_8 3 +-#define MDIO_CLK_25_10 4 +-#define MDIO_CLK_25_14 5 +-#define MDIO_CLK_25_20 6 +-#define MDIO_CLK_25_28 7 +-#define MDIO_BUSY 0x8000000 +-#define MDIO_AP_EN 0x10000000 +-#define MDIO_WAIT_TIMES 10 +- +-/* MII PHY Status Register */ +-#define REG_PHY_STATUS 0x1418 +-#define PHY_GENERAL_STATUS_MASK 0xFFFF +-#define PHY_STATUS_RECV_ENABLE 0x0001 +-#define PHY_OE_PWSP_STATUS_MASK 0x07FF +-#define PHY_OE_PWSP_STATUS_SHIFT 16 +-#define PHY_STATUS_LPW_STATE 0x80000000 ++#define MDIO_CTRL_MODE_EXT BIT(30) ++#define MDIO_CTRL_POST_READ BIT(29) ++#define MDIO_CTRL_AP_EN BIT(28) ++#define MDIO_CTRL_BUSY BIT(27) ++#define MDIO_CTRL_CLK_SEL_MASK 0x7UL ++#define MDIO_CTRL_CLK_SEL_SHIFT 24 ++#define MDIO_CTRL_CLK_25_4 0 /* 25MHz divide 4 */ ++#define MDIO_CTRL_CLK_25_6 2 ++#define MDIO_CTRL_CLK_25_8 3 ++#define MDIO_CTRL_CLK_25_10 4 ++#define MDIO_CTRL_CLK_25_32 5 ++#define MDIO_CTRL_CLK_25_64 6 ++#define MDIO_CTRL_CLK_25_128 7 ++#define MDIO_CTRL_START BIT(23) ++#define MDIO_CTRL_SPRES_PRMBL BIT(22) ++#define MDIO_CTRL_OP_READ BIT(21) /* 1:read, 0:write */ ++#define MDIO_CTRL_REG_MASK 0x1FUL ++#define MDIO_CTRL_REG_SHIFT 16 ++#define MDIO_CTRL_DATA_MASK 0xFFFFUL ++#define MDIO_CTRL_DATA_SHIFT 0 ++#define MDIO_MAX_AC_TO 120 /* 1.2ms timeout for slow clk */ ++ ++/* for extension reg access */ ++#define REG_MDIO_EXTN 0x1448 ++#define MDIO_EXTN_PORTAD_MASK 0x1FUL ++#define MDIO_EXTN_PORTAD_SHIFT 21 ++#define MDIO_EXTN_DEVAD_MASK 0x1FUL ++#define MDIO_EXTN_DEVAD_SHIFT 16 ++#define MDIO_EXTN_REG_MASK 0xFFFFUL ++#define MDIO_EXTN_REG_SHIFT 0 ++ + /* BIST Control and Status Register0 (for the Packet Memory) */ + #define REG_BIST0_CTRL 0x141c + #define BIST0_NOW 0x1 +@@ -299,50 +325,81 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define BIST1_FUSE_FLAG 0x4 + + /* SerDes Lock Detect Control and Status Register */ +-#define REG_SERDES_LOCK 0x1424 +-#define SERDES_LOCK_DETECT 0x1 /* SerDes lock detected. This signal +- * comes from Analog SerDes */ +-#define SERDES_LOCK_DETECT_EN 0x2 /* 1: Enable SerDes Lock detect function */ +-#define SERDES_LOCK_STS_SELFB_PLL_SHIFT 0xE +-#define SERDES_LOCK_STS_SELFB_PLL_MASK 0x3 +-#define SERDES_OVCLK_18_25 0x0 +-#define SERDES_OVCLK_12_18 0x1 +-#define SERDES_OVCLK_0_4 0x2 +-#define SERDES_OVCLK_4_12 0x3 +-#define SERDES_MAC_CLK_SLOWDOWN 0x20000 +-#define SERDES_PYH_CLK_SLOWDOWN 0x40000 ++#define REG_SERDES 0x1424 ++#define SERDES_PHY_CLK_SLOWDOWN BIT(18) ++#define SERDES_MAC_CLK_SLOWDOWN BIT(17) ++#define SERDES_SELFB_PLL_MASK 0x3UL ++#define SERDES_SELFB_PLL_SHIFT 14 ++#define SERDES_PHYCLK_SEL_GTX BIT(13) /* 1:gtx_clk, 0:25M */ ++#define SERDES_PCIECLK_SEL_SRDS BIT(12) /* 1:serdes,0:25M */ ++#define SERDES_BUFS_RX_EN BIT(11) ++#define SERDES_PD_RX BIT(10) ++#define SERDES_PLL_EN BIT(9) ++#define SERDES_EN BIT(8) ++#define SERDES_SELFB_PLL_SEL_CSR BIT(6) /* 0:state-machine,1:csr */ ++#define SERDES_SELFB_PLL_CSR_MASK 0x3UL ++#define SERDES_SELFB_PLL_CSR_SHIFT 4 ++#define SERDES_SELFB_PLL_CSR_4 3 /* 4-12% OV-CLK */ ++#define SERDES_SELFB_PLL_CSR_0 2 /* 0-4% OV-CLK */ ++#define SERDES_SELFB_PLL_CSR_12 1 /* 12-18% OV-CLK */ ++#define SERDES_SELFB_PLL_CSR_18 0 /* 18-25% OV-CLK */ ++#define SERDES_VCO_SLOW BIT(3) ++#define SERDES_VCO_FAST BIT(2) ++#define SERDES_LOCK_DETECT_EN BIT(1) ++#define SERDES_LOCK_DETECT BIT(0) ++ ++#define REG_LPI_DECISN_TIMER 0x143C ++#define L2CB_LPI_DESISN_TIMER 0x7D00 ++ ++#define REG_LPI_CTRL 0x1440 ++#define LPI_CTRL_CHK_DA BIT(31) ++#define LPI_CTRL_ENH_TO_MASK 0x1FFFUL ++#define LPI_CTRL_ENH_TO_SHIFT 12 ++#define LPI_CTRL_ENH_TH_MASK 0x1FUL ++#define LPI_CTRL_ENH_TH_SHIFT 6 ++#define LPI_CTRL_ENH_EN BIT(5) ++#define LPI_CTRL_CHK_RX BIT(4) ++#define LPI_CTRL_CHK_STATE BIT(3) ++#define LPI_CTRL_GMII BIT(2) ++#define LPI_CTRL_TO_PHY BIT(1) ++#define LPI_CTRL_EN BIT(0) ++ ++#define REG_LPI_WAIT 0x1444 ++#define LPI_WAIT_TIMER_MASK 0xFFFFUL ++#define LPI_WAIT_TIMER_SHIFT 0 + + /* MAC Control Register */ + #define REG_MAC_CTRL 0x1480 +-#define MAC_CTRL_TX_EN 0x1 +-#define MAC_CTRL_RX_EN 0x2 +-#define MAC_CTRL_TX_FLOW 0x4 +-#define MAC_CTRL_RX_FLOW 0x8 +-#define MAC_CTRL_LOOPBACK 0x10 +-#define MAC_CTRL_DUPLX 0x20 +-#define MAC_CTRL_ADD_CRC 0x40 +-#define MAC_CTRL_PAD 0x80 +-#define MAC_CTRL_LENCHK 0x100 +-#define MAC_CTRL_HUGE_EN 0x200 +-#define MAC_CTRL_PRMLEN_SHIFT 10 +-#define MAC_CTRL_PRMLEN_MASK 0xf +-#define MAC_CTRL_RMV_VLAN 0x4000 +-#define MAC_CTRL_PROMIS_EN 0x8000 +-#define MAC_CTRL_TX_PAUSE 0x10000 +-#define MAC_CTRL_SCNT 0x20000 +-#define MAC_CTRL_SRST_TX 0x40000 +-#define MAC_CTRL_TX_SIMURST 0x80000 +-#define MAC_CTRL_SPEED_SHIFT 20 +-#define MAC_CTRL_SPEED_MASK 0x3 +-#define MAC_CTRL_DBG_TX_BKPRESURE 0x400000 +-#define MAC_CTRL_TX_HUGE 0x800000 +-#define MAC_CTRL_RX_CHKSUM_EN 0x1000000 +-#define MAC_CTRL_MC_ALL_EN 0x2000000 +-#define MAC_CTRL_BC_EN 0x4000000 +-#define MAC_CTRL_DBG 0x8000000 +-#define MAC_CTRL_SINGLE_PAUSE_EN 0x10000000 +-#define MAC_CTRL_HASH_ALG_CRC32 0x20000000 +-#define MAC_CTRL_SPEED_MODE_SW 0x40000000 ++#define MAC_CTRL_SPEED_MODE_SW BIT(30) /* 0:phy,1:sw */ ++#define MAC_CTRL_HASH_ALG_CRC32 BIT(29) /* 1:legacy,0:lw_5b */ ++#define MAC_CTRL_SINGLE_PAUSE_EN BIT(28) ++#define MAC_CTRL_DBG BIT(27) ++#define MAC_CTRL_BC_EN BIT(26) ++#define MAC_CTRL_MC_ALL_EN BIT(25) ++#define MAC_CTRL_RX_CHKSUM_EN BIT(24) ++#define MAC_CTRL_TX_HUGE BIT(23) ++#define MAC_CTRL_DBG_TX_BKPRESURE BIT(22) ++#define MAC_CTRL_SPEED_MASK 3UL ++#define MAC_CTRL_SPEED_SHIFT 20 ++#define MAC_CTRL_SPEED_10_100 1 ++#define MAC_CTRL_SPEED_1000 2 ++#define MAC_CTRL_TX_SIMURST BIT(19) ++#define MAC_CTRL_SCNT BIT(17) ++#define MAC_CTRL_TX_PAUSE BIT(16) ++#define MAC_CTRL_PROMIS_EN BIT(15) ++#define MAC_CTRL_RMV_VLAN BIT(14) ++#define MAC_CTRL_PRMLEN_MASK 0xFUL ++#define MAC_CTRL_PRMLEN_SHIFT 10 ++#define MAC_CTRL_HUGE_EN BIT(9) ++#define MAC_CTRL_LENCHK BIT(8) ++#define MAC_CTRL_PAD BIT(7) ++#define MAC_CTRL_ADD_CRC BIT(6) ++#define MAC_CTRL_DUPLX BIT(5) ++#define MAC_CTRL_LOOPBACK BIT(4) ++#define MAC_CTRL_RX_FLOW BIT(3) ++#define MAC_CTRL_TX_FLOW BIT(2) ++#define MAC_CTRL_RX_EN BIT(1) ++#define MAC_CTRL_TX_EN BIT(0) + + /* MAC IPG/IFG Control Register */ + #define REG_MAC_IPG_IFG 0x1484 +@@ -386,34 +443,53 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + + /* Wake-On-Lan control register */ + #define REG_WOL_CTRL 0x14a0 +-#define WOL_PATTERN_EN 0x00000001 +-#define WOL_PATTERN_PME_EN 0x00000002 +-#define WOL_MAGIC_EN 0x00000004 +-#define WOL_MAGIC_PME_EN 0x00000008 +-#define WOL_LINK_CHG_EN 0x00000010 +-#define WOL_LINK_CHG_PME_EN 0x00000020 +-#define WOL_PATTERN_ST 0x00000100 +-#define WOL_MAGIC_ST 0x00000200 +-#define WOL_LINKCHG_ST 0x00000400 +-#define WOL_CLK_SWITCH_EN 0x00008000 +-#define WOL_PT0_EN 0x00010000 +-#define WOL_PT1_EN 0x00020000 +-#define WOL_PT2_EN 0x00040000 +-#define WOL_PT3_EN 0x00080000 +-#define WOL_PT4_EN 0x00100000 +-#define WOL_PT5_EN 0x00200000 +-#define WOL_PT6_EN 0x00400000 ++#define WOL_PT7_MATCH BIT(31) ++#define WOL_PT6_MATCH BIT(30) ++#define WOL_PT5_MATCH BIT(29) ++#define WOL_PT4_MATCH BIT(28) ++#define WOL_PT3_MATCH BIT(27) ++#define WOL_PT2_MATCH BIT(26) ++#define WOL_PT1_MATCH BIT(25) ++#define WOL_PT0_MATCH BIT(24) ++#define WOL_PT7_EN BIT(23) ++#define WOL_PT6_EN BIT(22) ++#define WOL_PT5_EN BIT(21) ++#define WOL_PT4_EN BIT(20) ++#define WOL_PT3_EN BIT(19) ++#define WOL_PT2_EN BIT(18) ++#define WOL_PT1_EN BIT(17) ++#define WOL_PT0_EN BIT(16) ++#define WOL_LNKCHG_ST BIT(10) ++#define WOL_MAGIC_ST BIT(9) ++#define WOL_PATTERN_ST BIT(8) ++#define WOL_OOB_EN BIT(6) ++#define WOL_LINK_CHG_PME_EN BIT(5) ++#define WOL_LINK_CHG_EN BIT(4) ++#define WOL_MAGIC_PME_EN BIT(3) ++#define WOL_MAGIC_EN BIT(2) ++#define WOL_PATTERN_PME_EN BIT(1) ++#define WOL_PATTERN_EN BIT(0) + + /* WOL Length ( 2 DWORD ) */ +-#define REG_WOL_PATTERN_LEN 0x14a4 +-#define WOL_PT_LEN_MASK 0x7f +-#define WOL_PT0_LEN_SHIFT 0 +-#define WOL_PT1_LEN_SHIFT 8 +-#define WOL_PT2_LEN_SHIFT 16 +-#define WOL_PT3_LEN_SHIFT 24 +-#define WOL_PT4_LEN_SHIFT 0 +-#define WOL_PT5_LEN_SHIFT 8 +-#define WOL_PT6_LEN_SHIFT 16 ++#define REG_WOL_PTLEN1 0x14A4 ++#define WOL_PTLEN1_3_MASK 0xFFUL ++#define WOL_PTLEN1_3_SHIFT 24 ++#define WOL_PTLEN1_2_MASK 0xFFUL ++#define WOL_PTLEN1_2_SHIFT 16 ++#define WOL_PTLEN1_1_MASK 0xFFUL ++#define WOL_PTLEN1_1_SHIFT 8 ++#define WOL_PTLEN1_0_MASK 0xFFUL ++#define WOL_PTLEN1_0_SHIFT 0 ++ ++#define REG_WOL_PTLEN2 0x14A8 ++#define WOL_PTLEN2_7_MASK 0xFFUL ++#define WOL_PTLEN2_7_SHIFT 24 ++#define WOL_PTLEN2_6_MASK 0xFFUL ++#define WOL_PTLEN2_6_SHIFT 16 ++#define WOL_PTLEN2_5_MASK 0xFFUL ++#define WOL_PTLEN2_5_SHIFT 8 ++#define WOL_PTLEN2_4_MASK 0xFFUL ++#define WOL_PTLEN2_4_SHIFT 0 + + /* Internal SRAM Partition Register */ + #define RFDX_HEAD_ADDR_MASK 0x03FF +@@ -458,66 +534,50 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + */ + #define REG_RX_BASE_ADDR_HI 0x1540 + #define REG_TX_BASE_ADDR_HI 0x1544 +-#define REG_SMB_BASE_ADDR_HI 0x1548 +-#define REG_SMB_BASE_ADDR_LO 0x154C + #define REG_RFD0_HEAD_ADDR_LO 0x1550 +-#define REG_RFD1_HEAD_ADDR_LO 0x1554 +-#define REG_RFD2_HEAD_ADDR_LO 0x1558 +-#define REG_RFD3_HEAD_ADDR_LO 0x155C + #define REG_RFD_RING_SIZE 0x1560 + #define RFD_RING_SIZE_MASK 0x0FFF + #define REG_RX_BUF_SIZE 0x1564 + #define RX_BUF_SIZE_MASK 0xFFFF + #define REG_RRD0_HEAD_ADDR_LO 0x1568 +-#define REG_RRD1_HEAD_ADDR_LO 0x156C +-#define REG_RRD2_HEAD_ADDR_LO 0x1570 +-#define REG_RRD3_HEAD_ADDR_LO 0x1574 + #define REG_RRD_RING_SIZE 0x1578 + #define RRD_RING_SIZE_MASK 0x0FFF +-#define REG_HTPD_HEAD_ADDR_LO 0x157C +-#define REG_NTPD_HEAD_ADDR_LO 0x1580 ++#define REG_TPD_PRI1_ADDR_LO 0x157C ++#define REG_TPD_PRI0_ADDR_LO 0x1580 + #define REG_TPD_RING_SIZE 0x1584 + #define TPD_RING_SIZE_MASK 0xFFFF +-#define REG_CMB_BASE_ADDR_LO 0x1588 +- +-/* RSS about */ +-#define REG_RSS_KEY0 0x14B0 +-#define REG_RSS_KEY1 0x14B4 +-#define REG_RSS_KEY2 0x14B8 +-#define REG_RSS_KEY3 0x14BC +-#define REG_RSS_KEY4 0x14C0 +-#define REG_RSS_KEY5 0x14C4 +-#define REG_RSS_KEY6 0x14C8 +-#define REG_RSS_KEY7 0x14CC +-#define REG_RSS_KEY8 0x14D0 +-#define REG_RSS_KEY9 0x14D4 +-#define REG_IDT_TABLE0 0x14E0 +-#define REG_IDT_TABLE1 0x14E4 +-#define REG_IDT_TABLE2 0x14E8 +-#define REG_IDT_TABLE3 0x14EC +-#define REG_IDT_TABLE4 0x14F0 +-#define REG_IDT_TABLE5 0x14F4 +-#define REG_IDT_TABLE6 0x14F8 +-#define REG_IDT_TABLE7 0x14FC +-#define REG_IDT_TABLE REG_IDT_TABLE0 +-#define REG_RSS_HASH_VALUE 0x15B0 +-#define REG_RSS_HASH_FLAG 0x15B4 +-#define REG_BASE_CPU_NUMBER 0x15B8 + + /* TXQ Control Register */ +-#define REG_TXQ_CTRL 0x1590 +-#define TXQ_NUM_TPD_BURST_MASK 0xF +-#define TXQ_NUM_TPD_BURST_SHIFT 0 +-#define TXQ_CTRL_IP_OPTION_EN 0x10 +-#define TXQ_CTRL_EN 0x20 +-#define TXQ_CTRL_ENH_MODE 0x40 +-#define TXQ_CTRL_LS_8023_EN 0x80 +-#define TXQ_TXF_BURST_NUM_SHIFT 16 +-#define TXQ_TXF_BURST_NUM_MASK 0xFFFF ++#define REG_TXQ_CTRL 0x1590 ++#define TXQ_TXF_BURST_NUM_MASK 0xFFFFUL ++#define TXQ_TXF_BURST_NUM_SHIFT 16 ++#define L1C_TXQ_TXF_BURST_PREF 0x200 ++#define L2CB_TXQ_TXF_BURST_PREF 0x40 ++#define TXQ_CTRL_PEDING_CLR BIT(8) ++#define TXQ_CTRL_LS_8023_EN BIT(7) ++#define TXQ_CTRL_ENH_MODE BIT(6) ++#define TXQ_CTRL_EN BIT(5) ++#define TXQ_CTRL_IP_OPTION_EN BIT(4) ++#define TXQ_NUM_TPD_BURST_MASK 0xFUL ++#define TXQ_NUM_TPD_BURST_SHIFT 0 ++#define TXQ_NUM_TPD_BURST_DEF 5 ++#define TXQ_CFGV (\ ++ FIELDX(TXQ_NUM_TPD_BURST, TXQ_NUM_TPD_BURST_DEF) |\ ++ TXQ_CTRL_ENH_MODE |\ ++ TXQ_CTRL_LS_8023_EN |\ ++ TXQ_CTRL_IP_OPTION_EN) ++#define L1C_TXQ_CFGV (\ ++ TXQ_CFGV |\ ++ FIELDX(TXQ_TXF_BURST_NUM, L1C_TXQ_TXF_BURST_PREF)) ++#define L2CB_TXQ_CFGV (\ ++ TXQ_CFGV |\ ++ FIELDX(TXQ_TXF_BURST_NUM, L2CB_TXQ_TXF_BURST_PREF)) ++ + + /* Jumbo packet Threshold for task offload */ + #define REG_TX_TSO_OFFLOAD_THRESH 0x1594 /* In 8-bytes */ + #define TX_TSO_OFFLOAD_THRESH_MASK 0x07FF ++#define MAX_TSO_FRAME_SIZE (7*1024) + + #define REG_TXF_WATER_MARK 0x1598 /* In 8-bytes */ + #define TXF_WATER_MARK_MASK 0x0FFF +@@ -537,26 +597,21 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define ASPM_THRUPUT_LIMIT_NO 0x00 + #define ASPM_THRUPUT_LIMIT_1M 0x01 + #define ASPM_THRUPUT_LIMIT_10M 0x02 +-#define ASPM_THRUPUT_LIMIT_100M 0x04 +-#define RXQ1_CTRL_EN 0x10 +-#define RXQ2_CTRL_EN 0x20 +-#define RXQ3_CTRL_EN 0x40 +-#define IPV6_CHKSUM_CTRL_EN 0x80 +-#define RSS_HASH_BITS_MASK 0x00FF +-#define RSS_HASH_BITS_SHIFT 8 +-#define RSS_HASH_IPV4 0x10000 +-#define RSS_HASH_IPV4_TCP 0x20000 +-#define RSS_HASH_IPV6 0x40000 +-#define RSS_HASH_IPV6_TCP 0x80000 ++#define ASPM_THRUPUT_LIMIT_100M 0x03 ++#define IPV6_CHKSUM_CTRL_EN BIT(7) + #define RXQ_RFD_BURST_NUM_MASK 0x003F + #define RXQ_RFD_BURST_NUM_SHIFT 20 +-#define RSS_MODE_MASK 0x0003 ++#define RXQ_NUM_RFD_PREF_DEF 8 ++#define RSS_MODE_MASK 3UL + #define RSS_MODE_SHIFT 26 +-#define RSS_NIP_QUEUE_SEL_MASK 0x1 +-#define RSS_NIP_QUEUE_SEL_SHIFT 28 +-#define RRS_HASH_CTRL_EN 0x20000000 +-#define RX_CUT_THRU_EN 0x40000000 +-#define RXQ_CTRL_EN 0x80000000 ++#define RSS_MODE_DIS 0 ++#define RSS_MODE_SQSI 1 ++#define RSS_MODE_MQSI 2 ++#define RSS_MODE_MQMI 3 ++#define RSS_NIP_QUEUE_SEL BIT(28) /* 0:q0, 1:table */ ++#define RRS_HASH_CTRL_EN BIT(29) ++#define RX_CUT_THRU_EN BIT(30) ++#define RXQ_CTRL_EN BIT(31) + + #define REG_RFD_FREE_THRESH 0x15A4 + #define RFD_FREE_THRESH_MASK 0x003F +@@ -577,57 +632,45 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define RXD_DMA_DOWN_TIMER_SHIFT 16 + + /* DMA Engine Control Register */ +-#define REG_DMA_CTRL 0x15C0 +-#define DMA_CTRL_DMAR_IN_ORDER 0x1 +-#define DMA_CTRL_DMAR_ENH_ORDER 0x2 +-#define DMA_CTRL_DMAR_OUT_ORDER 0x4 +-#define DMA_CTRL_RCB_VALUE 0x8 +-#define DMA_CTRL_DMAR_BURST_LEN_MASK 0x0007 +-#define DMA_CTRL_DMAR_BURST_LEN_SHIFT 4 +-#define DMA_CTRL_DMAW_BURST_LEN_MASK 0x0007 +-#define DMA_CTRL_DMAW_BURST_LEN_SHIFT 7 +-#define DMA_CTRL_DMAR_REQ_PRI 0x400 +-#define DMA_CTRL_DMAR_DLY_CNT_MASK 0x001F +-#define DMA_CTRL_DMAR_DLY_CNT_SHIFT 11 +-#define DMA_CTRL_DMAW_DLY_CNT_MASK 0x000F +-#define DMA_CTRL_DMAW_DLY_CNT_SHIFT 16 +-#define DMA_CTRL_CMB_EN 0x100000 +-#define DMA_CTRL_SMB_EN 0x200000 +-#define DMA_CTRL_CMB_NOW 0x400000 +-#define MAC_CTRL_SMB_DIS 0x1000000 +-#define DMA_CTRL_SMB_NOW 0x80000000 +- +-/* CMB/SMB Control Register */ ++#define REG_DMA_CTRL 0x15C0 ++#define DMA_CTRL_SMB_NOW BIT(31) ++#define DMA_CTRL_WPEND_CLR BIT(30) ++#define DMA_CTRL_RPEND_CLR BIT(29) ++#define DMA_CTRL_WDLY_CNT_MASK 0xFUL ++#define DMA_CTRL_WDLY_CNT_SHIFT 16 ++#define DMA_CTRL_WDLY_CNT_DEF 4 ++#define DMA_CTRL_RDLY_CNT_MASK 0x1FUL ++#define DMA_CTRL_RDLY_CNT_SHIFT 11 ++#define DMA_CTRL_RDLY_CNT_DEF 15 ++#define DMA_CTRL_RREQ_PRI_DATA BIT(10) /* 0:tpd, 1:data */ ++#define DMA_CTRL_WREQ_BLEN_MASK 7UL ++#define DMA_CTRL_WREQ_BLEN_SHIFT 7 ++#define DMA_CTRL_RREQ_BLEN_MASK 7UL ++#define DMA_CTRL_RREQ_BLEN_SHIFT 4 ++#define L1C_CTRL_DMA_RCB_LEN128 BIT(3) /* 0:64bytes,1:128bytes */ ++#define DMA_CTRL_RORDER_MODE_MASK 7UL ++#define DMA_CTRL_RORDER_MODE_SHIFT 0 ++#define DMA_CTRL_RORDER_MODE_OUT 4 ++#define DMA_CTRL_RORDER_MODE_ENHANCE 2 ++#define DMA_CTRL_RORDER_MODE_IN 1 ++ ++/* INT-triggle/SMB Control Register */ + #define REG_SMB_STAT_TIMER 0x15C4 /* 2us resolution */ + #define SMB_STAT_TIMER_MASK 0xFFFFFF +-#define REG_CMB_TPD_THRESH 0x15C8 +-#define CMB_TPD_THRESH_MASK 0xFFFF +-#define REG_CMB_TX_TIMER 0x15CC /* 2us resolution */ +-#define CMB_TX_TIMER_MASK 0xFFFF ++#define REG_TINT_TPD_THRESH 0x15C8 /* tpd th to trig intrrupt */ + + /* Mail box */ + #define MB_RFDX_PROD_IDX_MASK 0xFFFF + #define REG_MB_RFD0_PROD_IDX 0x15E0 +-#define REG_MB_RFD1_PROD_IDX 0x15E4 +-#define REG_MB_RFD2_PROD_IDX 0x15E8 +-#define REG_MB_RFD3_PROD_IDX 0x15EC + +-#define MB_PRIO_PROD_IDX_MASK 0xFFFF +-#define REG_MB_PRIO_PROD_IDX 0x15F0 +-#define MB_HTPD_PROD_IDX_SHIFT 0 +-#define MB_NTPD_PROD_IDX_SHIFT 16 +- +-#define MB_PRIO_CONS_IDX_MASK 0xFFFF +-#define REG_MB_PRIO_CONS_IDX 0x15F4 +-#define MB_HTPD_CONS_IDX_SHIFT 0 +-#define MB_NTPD_CONS_IDX_SHIFT 16 ++#define REG_TPD_PRI1_PIDX 0x15F0 /* 16bit,hi-tpd producer idx */ ++#define REG_TPD_PRI0_PIDX 0x15F2 /* 16bit,lo-tpd producer idx */ ++#define REG_TPD_PRI1_CIDX 0x15F4 /* 16bit,hi-tpd consumer idx */ ++#define REG_TPD_PRI0_CIDX 0x15F6 /* 16bit,lo-tpd consumer idx */ + + #define REG_MB_RFD01_CONS_IDX 0x15F8 + #define MB_RFD0_CONS_IDX_MASK 0x0000FFFF + #define MB_RFD1_CONS_IDX_MASK 0xFFFF0000 +-#define REG_MB_RFD23_CONS_IDX 0x15FC +-#define MB_RFD2_CONS_IDX_MASK 0x0000FFFF +-#define MB_RFD3_CONS_IDX_MASK 0xFFFF0000 + + /* Interrupt Status Register */ + #define REG_ISR 0x1600 +@@ -705,13 +748,6 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define REG_INT_RETRIG_TIMER 0x1608 + #define INT_RETRIG_TIMER_MASK 0xFFFF + +-#define REG_HDS_CTRL 0x160C +-#define HDS_CTRL_EN 0x0001 +-#define HDS_CTRL_BACKFILLSIZE_SHIFT 8 +-#define HDS_CTRL_BACKFILLSIZE_MASK 0x0FFF +-#define HDS_CTRL_MAX_HDRSIZE_SHIFT 20 +-#define HDS_CTRL_MAC_HDRSIZE_MASK 0x0FFF +- + #define REG_MAC_RX_STATUS_BIN 0x1700 + #define REG_MAC_RX_STATUS_END 0x175c + #define REG_MAC_TX_STATUS_BIN 0x1760 +@@ -796,73 +832,188 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define MII_DBG_ADDR 0x1D + #define MII_DBG_DATA 0x1E + +-#define MII_ANA_CTRL_0 0x0 +-#define ANA_RESTART_CAL 0x0001 +-#define ANA_MANUL_SWICH_ON_SHIFT 0x1 +-#define ANA_MANUL_SWICH_ON_MASK 0xF +-#define ANA_MAN_ENABLE 0x0020 +-#define ANA_SEL_HSP 0x0040 +-#define ANA_EN_HB 0x0080 +-#define ANA_EN_HBIAS 0x0100 +-#define ANA_OEN_125M 0x0200 +-#define ANA_EN_LCKDT 0x0400 +-#define ANA_LCKDT_PHY 0x0800 +-#define ANA_AFE_MODE 0x1000 +-#define ANA_VCO_SLOW 0x2000 +-#define ANA_VCO_FAST 0x4000 +-#define ANA_SEL_CLK125M_DSP 0x8000 +- +-#define MII_ANA_CTRL_4 0x4 +-#define ANA_IECHO_ADJ_MASK 0xF +-#define ANA_IECHO_ADJ_3_SHIFT 0 +-#define ANA_IECHO_ADJ_2_SHIFT 4 +-#define ANA_IECHO_ADJ_1_SHIFT 8 +-#define ANA_IECHO_ADJ_0_SHIFT 12 +- +-#define MII_ANA_CTRL_5 0x5 +-#define ANA_SERDES_CDR_BW_SHIFT 0 +-#define ANA_SERDES_CDR_BW_MASK 0x3 +-#define ANA_MS_PAD_DBG 0x0004 +-#define ANA_SPEEDUP_DBG 0x0008 +-#define ANA_SERDES_TH_LOS_SHIFT 4 +-#define ANA_SERDES_TH_LOS_MASK 0x3 +-#define ANA_SERDES_EN_DEEM 0x0040 +-#define ANA_SERDES_TXELECIDLE 0x0080 +-#define ANA_SERDES_BEACON 0x0100 +-#define ANA_SERDES_HALFTXDR 0x0200 +-#define ANA_SERDES_SEL_HSP 0x0400 +-#define ANA_SERDES_EN_PLL 0x0800 +-#define ANA_SERDES_EN 0x1000 +-#define ANA_SERDES_EN_LCKDT 0x2000 +- +-#define MII_ANA_CTRL_11 0xB +-#define ANA_PS_HIB_EN 0x8000 +- +-#define MII_ANA_CTRL_18 0x12 +-#define ANA_TEST_MODE_10BT_01SHIFT 0 +-#define ANA_TEST_MODE_10BT_01MASK 0x3 +-#define ANA_LOOP_SEL_10BT 0x0004 +-#define ANA_RGMII_MODE_SW 0x0008 +-#define ANA_EN_LONGECABLE 0x0010 +-#define ANA_TEST_MODE_10BT_2 0x0020 +-#define ANA_EN_10BT_IDLE 0x0400 +-#define ANA_EN_MASK_TB 0x0800 +-#define ANA_TRIGGER_SEL_TIMER_SHIFT 12 +-#define ANA_TRIGGER_SEL_TIMER_MASK 0x3 +-#define ANA_INTERVAL_SEL_TIMER_SHIFT 14 +-#define ANA_INTERVAL_SEL_TIMER_MASK 0x3 +- +-#define MII_ANA_CTRL_41 0x29 +-#define ANA_TOP_PS_EN 0x8000 +- +-#define MII_ANA_CTRL_54 0x36 +-#define ANA_LONG_CABLE_TH_100_SHIFT 0 +-#define ANA_LONG_CABLE_TH_100_MASK 0x3F +-#define ANA_DESERVED 0x0040 +-#define ANA_EN_LIT_CH 0x0080 +-#define ANA_SHORT_CABLE_TH_100_SHIFT 8 +-#define ANA_SHORT_CABLE_TH_100_MASK 0x3F +-#define ANA_BP_BAD_LINK_ACCUM 0x4000 +-#define ANA_BP_SMALL_BW 0x8000 ++/***************************** debug port *************************************/ ++ ++#define MIIDBG_ANACTRL 0x00 ++#define ANACTRL_CLK125M_DELAY_EN 0x8000 ++#define ANACTRL_VCO_FAST 0x4000 ++#define ANACTRL_VCO_SLOW 0x2000 ++#define ANACTRL_AFE_MODE_EN 0x1000 ++#define ANACTRL_LCKDET_PHY 0x800 ++#define ANACTRL_LCKDET_EN 0x400 ++#define ANACTRL_OEN_125M 0x200 ++#define ANACTRL_HBIAS_EN 0x100 ++#define ANACTRL_HB_EN 0x80 ++#define ANACTRL_SEL_HSP 0x40 ++#define ANACTRL_CLASSA_EN 0x20 ++#define ANACTRL_MANUSWON_SWR_MASK 3U ++#define ANACTRL_MANUSWON_SWR_SHIFT 2 ++#define ANACTRL_MANUSWON_SWR_2V 0 ++#define ANACTRL_MANUSWON_SWR_1P9V 1 ++#define ANACTRL_MANUSWON_SWR_1P8V 2 ++#define ANACTRL_MANUSWON_SWR_1P7V 3 ++#define ANACTRL_MANUSWON_BW3_4M 0x2 ++#define ANACTRL_RESTART_CAL 0x1 ++#define ANACTRL_DEF 0x02EF ++ ++#define MIIDBG_SYSMODCTRL 0x04 ++#define SYSMODCTRL_IECHOADJ_PFMH_PHY 0x8000 ++#define SYSMODCTRL_IECHOADJ_BIASGEN 0x4000 ++#define SYSMODCTRL_IECHOADJ_PFML_PHY 0x2000 ++#define SYSMODCTRL_IECHOADJ_PS_MASK 3U ++#define SYSMODCTRL_IECHOADJ_PS_SHIFT 10 ++#define SYSMODCTRL_IECHOADJ_PS_40 3 ++#define SYSMODCTRL_IECHOADJ_PS_20 2 ++#define SYSMODCTRL_IECHOADJ_PS_0 1 ++#define SYSMODCTRL_IECHOADJ_10BT_100MV 0x40 /* 1:100mv, 0:200mv */ ++#define SYSMODCTRL_IECHOADJ_HLFAP_MASK 3U ++#define SYSMODCTRL_IECHOADJ_HLFAP_SHIFT 4 ++#define SYSMODCTRL_IECHOADJ_VDFULBW 0x8 ++#define SYSMODCTRL_IECHOADJ_VDBIASHLF 0x4 ++#define SYSMODCTRL_IECHOADJ_VDAMPHLF 0x2 ++#define SYSMODCTRL_IECHOADJ_VDLANSW 0x1 ++#define SYSMODCTRL_IECHOADJ_DEF 0x88BB /* ???? */ ++ ++/* for l1d & l2cb */ ++#define SYSMODCTRL_IECHOADJ_CUR_ADD 0x8000 ++#define SYSMODCTRL_IECHOADJ_CUR_MASK 7U ++#define SYSMODCTRL_IECHOADJ_CUR_SHIFT 12 ++#define SYSMODCTRL_IECHOADJ_VOL_MASK 0xFU ++#define SYSMODCTRL_IECHOADJ_VOL_SHIFT 8 ++#define SYSMODCTRL_IECHOADJ_VOL_17ALL 3 ++#define SYSMODCTRL_IECHOADJ_VOL_100M15 1 ++#define SYSMODCTRL_IECHOADJ_VOL_10M17 0 ++#define SYSMODCTRL_IECHOADJ_BIAS1_MASK 0xFU ++#define SYSMODCTRL_IECHOADJ_BIAS1_SHIFT 4 ++#define SYSMODCTRL_IECHOADJ_BIAS2_MASK 0xFU ++#define SYSMODCTRL_IECHOADJ_BIAS2_SHIFT 0 ++#define L1D_SYSMODCTRL_IECHOADJ_DEF 0x4FBB ++ ++#define MIIDBG_SRDSYSMOD 0x05 ++#define SRDSYSMOD_LCKDET_EN 0x2000 ++#define SRDSYSMOD_PLL_EN 0x800 ++#define SRDSYSMOD_SEL_HSP 0x400 ++#define SRDSYSMOD_HLFTXDR 0x200 ++#define SRDSYSMOD_TXCLK_DELAY_EN 0x100 ++#define SRDSYSMOD_TXELECIDLE 0x80 ++#define SRDSYSMOD_DEEMP_EN 0x40 ++#define SRDSYSMOD_MS_PAD 0x4 ++#define SRDSYSMOD_CDR_ADC_VLTG 0x2 ++#define SRDSYSMOD_CDR_DAC_1MA 0x1 ++#define SRDSYSMOD_DEF 0x2C46 ++ ++#define MIIDBG_CFGLPSPD 0x0A ++#define CFGLPSPD_RSTCNT_MASK 3U ++#define CFGLPSPD_RSTCNT_SHIFT 14 ++#define CFGLPSPD_RSTCNT_CLK125SW 0x2000 ++ ++#define MIIDBG_HIBNEG 0x0B ++#define HIBNEG_PSHIB_EN 0x8000 ++#define HIBNEG_WAKE_BOTH 0x4000 ++#define HIBNEG_ONOFF_ANACHG_SUDEN 0x2000 ++#define HIBNEG_HIB_PULSE 0x1000 ++#define HIBNEG_GATE_25M_EN 0x800 ++#define HIBNEG_RST_80U 0x400 ++#define HIBNEG_RST_TIMER_MASK 3U ++#define HIBNEG_RST_TIMER_SHIFT 8 ++#define HIBNEG_GTX_CLK_DELAY_MASK 3U ++#define HIBNEG_GTX_CLK_DELAY_SHIFT 5 ++#define HIBNEG_BYPSS_BRKTIMER 0x10 ++#define HIBNEG_DEF 0xBC40 ++ ++#define MIIDBG_TST10BTCFG 0x12 ++#define TST10BTCFG_INTV_TIMER_MASK 3U ++#define TST10BTCFG_INTV_TIMER_SHIFT 14 ++#define TST10BTCFG_TRIGER_TIMER_MASK 3U ++#define TST10BTCFG_TRIGER_TIMER_SHIFT 12 ++#define TST10BTCFG_DIV_MAN_MLT3_EN 0x800 ++#define TST10BTCFG_OFF_DAC_IDLE 0x400 ++#define TST10BTCFG_LPBK_DEEP 0x4 /* 1:deep,0:shallow */ ++#define TST10BTCFG_DEF 0x4C04 ++ ++#define MIIDBG_AZ_ANADECT 0x15 ++#define AZ_ANADECT_10BTRX_TH 0x8000 ++#define AZ_ANADECT_BOTH_01CHNL 0x4000 ++#define AZ_ANADECT_INTV_MASK 0x3FU ++#define AZ_ANADECT_INTV_SHIFT 8 ++#define AZ_ANADECT_THRESH_MASK 0xFU ++#define AZ_ANADECT_THRESH_SHIFT 4 ++#define AZ_ANADECT_CHNL_MASK 0xFU ++#define AZ_ANADECT_CHNL_SHIFT 0 ++#define AZ_ANADECT_DEF 0x3220 ++#define AZ_ANADECT_LONG 0xb210 ++ ++#define MIIDBG_MSE16DB 0x18 /* l1d */ ++#define L1D_MSE16DB_UP 0x05EA ++#define L1D_MSE16DB_DOWN 0x02EA ++ ++#define MIIDBG_LEGCYPS 0x29 ++#define LEGCYPS_EN 0x8000 ++#define LEGCYPS_DAC_AMP1000_MASK 7U ++#define LEGCYPS_DAC_AMP1000_SHIFT 12 ++#define LEGCYPS_DAC_AMP100_MASK 7U ++#define LEGCYPS_DAC_AMP100_SHIFT 9 ++#define LEGCYPS_DAC_AMP10_MASK 7U ++#define LEGCYPS_DAC_AMP10_SHIFT 6 ++#define LEGCYPS_UNPLUG_TIMER_MASK 7U ++#define LEGCYPS_UNPLUG_TIMER_SHIFT 3 ++#define LEGCYPS_UNPLUG_DECT_EN 0x4 ++#define LEGCYPS_ECNC_PS_EN 0x1 ++#define L1D_LEGCYPS_DEF 0x129D ++#define L1C_LEGCYPS_DEF 0x36DD ++ ++#define MIIDBG_TST100BTCFG 0x36 ++#define TST100BTCFG_NORMAL_BW_EN 0x8000 ++#define TST100BTCFG_BADLNK_BYPASS 0x4000 ++#define TST100BTCFG_SHORTCABL_TH_MASK 0x3FU ++#define TST100BTCFG_SHORTCABL_TH_SHIFT 8 ++#define TST100BTCFG_LITCH_EN 0x80 ++#define TST100BTCFG_VLT_SW 0x40 ++#define TST100BTCFG_LONGCABL_TH_MASK 0x3FU ++#define TST100BTCFG_LONGCABL_TH_SHIFT 0 ++#define TST100BTCFG_DEF 0xE12C ++ ++#define MIIDBG_VOLT_CTRL 0x3B /* only for l2cb 1 & 2 */ ++#define VOLT_CTRL_CABLE1TH_MASK 0x1FFU ++#define VOLT_CTRL_CABLE1TH_SHIFT 7 ++#define VOLT_CTRL_AMPCTRL_MASK 3U ++#define VOLT_CTRL_AMPCTRL_SHIFT 5 ++#define VOLT_CTRL_SW_BYPASS 0x10 ++#define VOLT_CTRL_SWLOWEST 0x8 ++#define VOLT_CTRL_DACAMP10_MASK 7U ++#define VOLT_CTRL_DACAMP10_SHIFT 0 ++ ++#define MIIDBG_CABLE1TH_DET 0x3E ++#define CABLE1TH_DET_EN 0x8000 ++ ++ ++/******* dev 3 *********/ ++#define MIIEXT_PCS 3 ++ ++#define MIIEXT_CLDCTRL3 0x8003 ++#define CLDCTRL3_BP_CABLE1TH_DET_GT 0x8000 ++#define CLDCTRL3_AZ_DISAMP 0x1000 ++#define L2CB_CLDCTRL3 0x4D19 ++#define L1D_CLDCTRL3 0xDD19 ++ ++#define MIIEXT_CLDCTRL6 0x8006 ++#define CLDCTRL6_CAB_LEN_MASK 0x1FFU ++#define CLDCTRL6_CAB_LEN_SHIFT 0 ++#define CLDCTRL6_CAB_LEN_SHORT 0x50 ++ ++/********* dev 7 **********/ ++#define MIIEXT_ANEG 7 ++ ++#define MIIEXT_LOCAL_EEEADV 0x3C ++#define LOCAL_EEEADV_1000BT 0x4 ++#define LOCAL_EEEADV_100BT 0x2 ++ ++#define MIIEXT_REMOTE_EEEADV 0x3D ++#define REMOTE_EEEADV_1000BT 0x4 ++#define REMOTE_EEEADV_100BT 0x2 ++ ++#define MIIEXT_EEE_ANEG 0x8000 ++#define EEE_ANEG_1000M 0x4 ++#define EEE_ANEG_100M 0x2 + + #endif /*_ATL1C_HW_H_*/ +diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +index 47a9bb2..f6f3fe3 100644 +--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c ++++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +@@ -24,14 +24,6 @@ + #define ATL1C_DRV_VERSION "1.0.1.0-NAPI" + char atl1c_driver_name[] = "atl1c"; + char atl1c_driver_version[] = ATL1C_DRV_VERSION; +-#define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062 +-#define PCI_DEVICE_ID_ATTANSIC_L1C 0x1063 +-#define PCI_DEVICE_ID_ATHEROS_L2C_B 0x2060 /* AR8152 v1.1 Fast 10/100 */ +-#define PCI_DEVICE_ID_ATHEROS_L2C_B2 0x2062 /* AR8152 v2.0 Fast 10/100 */ +-#define PCI_DEVICE_ID_ATHEROS_L1D 0x1073 /* AR8151 v1.0 Gigabit 1000 */ +-#define PCI_DEVICE_ID_ATHEROS_L1D_2_0 0x1083 /* AR8151 v2.0 Gigabit 1000 */ +-#define L2CB_V10 0xc0 +-#define L2CB_V11 0xc1 + + /* + * atl1c_pci_tbl - PCI Device ID Table +@@ -54,70 +46,72 @@ static DEFINE_PCI_DEVICE_TABLE(atl1c_pci_tbl) = { + }; + MODULE_DEVICE_TABLE(pci, atl1c_pci_tbl); + +-MODULE_AUTHOR("Jie Yang "); +-MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver"); ++MODULE_AUTHOR("Jie Yang"); ++MODULE_AUTHOR("Qualcomm Atheros Inc., "); ++MODULE_DESCRIPTION("Qualcom Atheros 100/1000M Ethernet Network Driver"); + MODULE_LICENSE("GPL"); + MODULE_VERSION(ATL1C_DRV_VERSION); + + static int atl1c_stop_mac(struct atl1c_hw *hw); +-static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw); +-static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw); + static void atl1c_disable_l0s_l1(struct atl1c_hw *hw); +-static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup); +-static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter); +-static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que, ++static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed); ++static void atl1c_start_mac(struct atl1c_adapter *adapter); ++static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, + int *work_done, int work_to_do); + static int atl1c_up(struct atl1c_adapter *adapter); + static void atl1c_down(struct atl1c_adapter *adapter); ++static int atl1c_reset_mac(struct atl1c_hw *hw); ++static void atl1c_reset_dma_ring(struct atl1c_adapter *adapter); ++static int atl1c_configure(struct atl1c_adapter *adapter); ++static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter); + + static const u16 atl1c_pay_load_size[] = { + 128, 256, 512, 1024, 2048, 4096, + }; + +-static const u16 atl1c_rfd_prod_idx_regs[AT_MAX_RECEIVE_QUEUE] = +-{ +- REG_MB_RFD0_PROD_IDX, +- REG_MB_RFD1_PROD_IDX, +- REG_MB_RFD2_PROD_IDX, +- REG_MB_RFD3_PROD_IDX +-}; +- +-static const u16 atl1c_rfd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] = +-{ +- REG_RFD0_HEAD_ADDR_LO, +- REG_RFD1_HEAD_ADDR_LO, +- REG_RFD2_HEAD_ADDR_LO, +- REG_RFD3_HEAD_ADDR_LO +-}; +- +-static const u16 atl1c_rrd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] = +-{ +- REG_RRD0_HEAD_ADDR_LO, +- REG_RRD1_HEAD_ADDR_LO, +- REG_RRD2_HEAD_ADDR_LO, +- REG_RRD3_HEAD_ADDR_LO +-}; + + static const u32 atl1c_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | + NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP; + static void atl1c_pcie_patch(struct atl1c_hw *hw) + { +- u32 data; ++ u32 mst_data, data; + +- AT_READ_REG(hw, REG_PCIE_PHYMISC, &data); +- data |= PCIE_PHYMISC_FORCE_RCV_DET; +- AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data); ++ /* pclk sel could switch to 25M */ ++ AT_READ_REG(hw, REG_MASTER_CTRL, &mst_data); ++ mst_data &= ~MASTER_CTRL_CLK_SEL_DIS; ++ AT_WRITE_REG(hw, REG_MASTER_CTRL, mst_data); + ++ /* WoL/PCIE related settings */ ++ if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) { ++ AT_READ_REG(hw, REG_PCIE_PHYMISC, &data); ++ data |= PCIE_PHYMISC_FORCE_RCV_DET; ++ AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data); ++ } else { /* new dev set bit5 of MASTER */ ++ if (!(mst_data & MASTER_CTRL_WAKEN_25M)) ++ AT_WRITE_REG(hw, REG_MASTER_CTRL, ++ mst_data | MASTER_CTRL_WAKEN_25M); ++ } ++ /* aspm/PCIE setting only for l2cb 1.0 */ + if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) { + AT_READ_REG(hw, REG_PCIE_PHYMISC2, &data); +- +- data &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK << +- PCIE_PHYMISC2_SERDES_CDR_SHIFT); +- data |= 3 << PCIE_PHYMISC2_SERDES_CDR_SHIFT; +- data &= ~(PCIE_PHYMISC2_SERDES_TH_MASK << +- PCIE_PHYMISC2_SERDES_TH_SHIFT); +- data |= 3 << PCIE_PHYMISC2_SERDES_TH_SHIFT; ++ data = FIELD_SETX(data, PCIE_PHYMISC2_CDR_BW, ++ L2CB1_PCIE_PHYMISC2_CDR_BW); ++ data = FIELD_SETX(data, PCIE_PHYMISC2_L0S_TH, ++ L2CB1_PCIE_PHYMISC2_L0S_TH); + AT_WRITE_REG(hw, REG_PCIE_PHYMISC2, data); ++ /* extend L1 sync timer */ ++ AT_READ_REG(hw, REG_LINK_CTRL, &data); ++ data |= LINK_CTRL_EXT_SYNC; ++ AT_WRITE_REG(hw, REG_LINK_CTRL, data); ++ } ++ /* l2cb 1.x & l1d 1.x */ ++ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d) { ++ AT_READ_REG(hw, REG_PM_CTRL, &data); ++ data |= PM_CTRL_L0S_BUFSRX_EN; ++ AT_WRITE_REG(hw, REG_PM_CTRL, data); ++ /* clear vendor msg */ ++ AT_READ_REG(hw, REG_DMA_DBG, &data); ++ AT_WRITE_REG(hw, REG_DMA_DBG, data & ~DMA_DBG_VENDOR_MSG); + } + } + +@@ -130,6 +124,7 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag) + u32 data; + u32 pci_cmd; + struct pci_dev *pdev = hw->adapter->pdev; ++ int pos; + + AT_READ_REG(hw, PCI_COMMAND, &pci_cmd); + pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; +@@ -142,14 +137,23 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag) + */ + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); ++ /* wol sts read-clear */ ++ AT_READ_REG(hw, REG_WOL_CTRL, &data); ++ AT_WRITE_REG(hw, REG_WOL_CTRL, 0); + + /* + * Mask some pcie error bits + */ +- AT_READ_REG(hw, REG_PCIE_UC_SEVERITY, &data); +- data &= ~PCIE_UC_SERVRITY_DLP; +- data &= ~PCIE_UC_SERVRITY_FCP; +- AT_WRITE_REG(hw, REG_PCIE_UC_SEVERITY, data); ++ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); ++ pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data); ++ data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP); ++ pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data); ++ /* clear error status */ ++ pci_write_config_word(pdev, pci_pcie_cap(pdev) + PCI_EXP_DEVSTA, ++ PCI_EXP_DEVSTA_NFED | ++ PCI_EXP_DEVSTA_FED | ++ PCI_EXP_DEVSTA_CED | ++ PCI_EXP_DEVSTA_URD); + + AT_READ_REG(hw, REG_LTSSM_ID_CTRL, &data); + data &= ~LTSSM_ID_EN_WRO; +@@ -158,11 +162,6 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag) + atl1c_pcie_patch(hw); + if (flag & ATL1C_PCIE_L0S_L1_DISABLE) + atl1c_disable_l0s_l1(hw); +- if (flag & ATL1C_PCIE_PHY_RESET) +- AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT); +- else +- AT_WRITE_REG(hw, REG_GPHY_CTRL, +- GPHY_CTRL_DEFAULT | GPHY_CTRL_EXT_RESET); + + msleep(5); + } +@@ -207,14 +206,14 @@ static inline void atl1c_irq_reset(struct atl1c_adapter *adapter) + * atl1c_wait_until_idle - wait up to AT_HW_MAX_IDLE_DELAY reads + * of the idle status register until the device is actually idle + */ +-static u32 atl1c_wait_until_idle(struct atl1c_hw *hw) ++static u32 atl1c_wait_until_idle(struct atl1c_hw *hw, u32 modu_ctrl) + { + int timeout; + u32 data; + + for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { + AT_READ_REG(hw, REG_IDLE_STATUS, &data); +- if ((data & IDLE_STATUS_MASK) == 0) ++ if ((data & modu_ctrl) == 0) + return 0; + msleep(1); + } +@@ -261,15 +260,16 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) + + if ((phy_data & BMSR_LSTATUS) == 0) { + /* link down */ +- hw->hibernate = true; +- if (atl1c_stop_mac(hw) != 0) +- if (netif_msg_hw(adapter)) +- dev_warn(&pdev->dev, "stop mac failed\n"); +- atl1c_set_aspm(hw, false); + netif_carrier_off(netdev); + netif_stop_queue(netdev); +- atl1c_phy_reset(hw); +- atl1c_phy_init(&adapter->hw); ++ hw->hibernate = true; ++ if (atl1c_reset_mac(hw) != 0) ++ if (netif_msg_hw(adapter)) ++ dev_warn(&pdev->dev, "reset mac failed\n"); ++ atl1c_set_aspm(hw, SPEED_0); ++ atl1c_post_phy_linkchg(hw, SPEED_0); ++ atl1c_reset_dma_ring(adapter); ++ atl1c_configure(adapter); + } else { + /* Link Up */ + hw->hibernate = false; +@@ -283,10 +283,9 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) + adapter->link_duplex != duplex) { + adapter->link_speed = speed; + adapter->link_duplex = duplex; +- atl1c_set_aspm(hw, true); +- atl1c_enable_tx_ctrl(hw); +- atl1c_enable_rx_ctrl(hw); +- atl1c_setup_mac_ctrl(adapter); ++ atl1c_set_aspm(hw, speed); ++ atl1c_post_phy_linkchg(hw, speed); ++ atl1c_start_mac(adapter); + if (netif_msg_link(adapter)) + dev_info(&pdev->dev, + "%s: %s NIC Link is Up<%d Mbps %s>\n", +@@ -337,6 +336,9 @@ static void atl1c_common_task(struct work_struct *work) + adapter = container_of(work, struct atl1c_adapter, common_task); + netdev = adapter->netdev; + ++ if (test_bit(__AT_DOWN, &adapter->flags)) ++ return; ++ + if (test_and_clear_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event)) { + netif_device_detach(netdev); + atl1c_down(adapter); +@@ -345,8 +347,11 @@ static void atl1c_common_task(struct work_struct *work) + } + + if (test_and_clear_bit(ATL1C_WORK_EVENT_LINK_CHANGE, +- &adapter->work_event)) ++ &adapter->work_event)) { ++ atl1c_irq_disable(adapter); + atl1c_check_link_status(adapter); ++ atl1c_irq_enable(adapter); ++ } + } + + +@@ -469,7 +474,7 @@ static int atl1c_set_mac_addr(struct net_device *netdev, void *p) + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); + +- atl1c_hw_set_mac_addr(&adapter->hw); ++ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr); + + return 0; + } +@@ -522,11 +527,16 @@ static int atl1c_set_features(struct net_device *netdev, + static int atl1c_change_mtu(struct net_device *netdev, int new_mtu) + { + struct atl1c_adapter *adapter = netdev_priv(netdev); ++ struct atl1c_hw *hw = &adapter->hw; + int old_mtu = netdev->mtu; + int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; + +- if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || +- (max_frame > MAX_JUMBO_FRAME_SIZE)) { ++ /* Fast Ethernet controller doesn't support jumbo packet */ ++ if (((hw->nic_type == athr_l2c || ++ hw->nic_type == athr_l2c_b || ++ hw->nic_type == athr_l2c_b2) && new_mtu > ETH_DATA_LEN) || ++ max_frame < ETH_ZLEN + ETH_FCS_LEN || ++ max_frame > MAX_JUMBO_FRAME_SIZE) { + if (netif_msg_link(adapter)) + dev_warn(&adapter->pdev->dev, "invalid MTU setting\n"); + return -EINVAL; +@@ -542,14 +552,6 @@ static int atl1c_change_mtu(struct net_device *netdev, int new_mtu) + netdev_update_features(netdev); + atl1c_up(adapter); + clear_bit(__AT_RESETTING, &adapter->flags); +- if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) { +- u32 phy_data; +- +- AT_READ_REG(&adapter->hw, 0x1414, &phy_data); +- phy_data |= 0x10000000; +- AT_WRITE_REG(&adapter->hw, 0x1414, phy_data); +- } +- + } + return 0; + } +@@ -562,7 +564,7 @@ static int atl1c_mdio_read(struct net_device *netdev, int phy_id, int reg_num) + struct atl1c_adapter *adapter = netdev_priv(netdev); + u16 result; + +- atl1c_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result); ++ atl1c_read_phy_reg(&adapter->hw, reg_num, &result); + return result; + } + +@@ -571,7 +573,7 @@ static void atl1c_mdio_write(struct net_device *netdev, int phy_id, + { + struct atl1c_adapter *adapter = netdev_priv(netdev); + +- atl1c_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val); ++ atl1c_write_phy_reg(&adapter->hw, reg_num, val); + } + + /* +@@ -686,21 +688,15 @@ static void atl1c_set_mac_type(struct atl1c_hw *hw) + + static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) + { +- u32 phy_status_data; + u32 link_ctrl_data; + + atl1c_set_mac_type(hw); +- AT_READ_REG(hw, REG_PHY_STATUS, &phy_status_data); + AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data); + + hw->ctrl_flags = ATL1C_INTR_MODRT_ENABLE | + ATL1C_TXQ_MODE_ENHANCE; +- if (link_ctrl_data & LINK_CTRL_L0S_EN) +- hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT; +- if (link_ctrl_data & LINK_CTRL_L1_EN) +- hw->ctrl_flags |= ATL1C_ASPM_L1_SUPPORT; +- if (link_ctrl_data & LINK_CTRL_EXT_SYNC) +- hw->ctrl_flags |= ATL1C_LINK_EXT_SYNC; ++ hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT | ++ ATL1C_ASPM_L1_SUPPORT; + hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON; + + if (hw->nic_type == athr_l1c || +@@ -709,6 +705,55 @@ static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) + hw->link_cap_flags |= ATL1C_LINK_CAP_1000M; + return 0; + } ++ ++struct atl1c_platform_patch { ++ u16 pci_did; ++ u8 pci_revid; ++ u16 subsystem_vid; ++ u16 subsystem_did; ++ u32 patch_flag; ++#define ATL1C_LINK_PATCH 0x1 ++}; ++static const struct atl1c_platform_patch plats[] __devinitdata = { ++{0x2060, 0xC1, 0x1019, 0x8152, 0x1}, ++{0x2060, 0xC1, 0x1019, 0x2060, 0x1}, ++{0x2060, 0xC1, 0x1019, 0xE000, 0x1}, ++{0x2062, 0xC0, 0x1019, 0x8152, 0x1}, ++{0x2062, 0xC0, 0x1019, 0x2062, 0x1}, ++{0x2062, 0xC0, 0x1458, 0xE000, 0x1}, ++{0x2062, 0xC1, 0x1019, 0x8152, 0x1}, ++{0x2062, 0xC1, 0x1019, 0x2062, 0x1}, ++{0x2062, 0xC1, 0x1458, 0xE000, 0x1}, ++{0x2062, 0xC1, 0x1565, 0x2802, 0x1}, ++{0x2062, 0xC1, 0x1565, 0x2801, 0x1}, ++{0x1073, 0xC0, 0x1019, 0x8151, 0x1}, ++{0x1073, 0xC0, 0x1019, 0x1073, 0x1}, ++{0x1073, 0xC0, 0x1458, 0xE000, 0x1}, ++{0x1083, 0xC0, 0x1458, 0xE000, 0x1}, ++{0x1083, 0xC0, 0x1019, 0x8151, 0x1}, ++{0x1083, 0xC0, 0x1019, 0x1083, 0x1}, ++{0x1083, 0xC0, 0x1462, 0x7680, 0x1}, ++{0x1083, 0xC0, 0x1565, 0x2803, 0x1}, ++{0}, ++}; ++ ++static void __devinit atl1c_patch_assign(struct atl1c_hw *hw) ++{ ++ int i = 0; ++ ++ hw->msi_lnkpatch = false; ++ ++ while (plats[i].pci_did != 0) { ++ if (plats[i].pci_did == hw->device_id && ++ plats[i].pci_revid == hw->revision_id && ++ plats[i].subsystem_vid == hw->subsystem_vendor_id && ++ plats[i].subsystem_did == hw->subsystem_id) { ++ if (plats[i].patch_flag & ATL1C_LINK_PATCH) ++ hw->msi_lnkpatch = true; ++ } ++ i++; ++ } ++} + /* + * atl1c_sw_init - Initialize general software structures (struct atl1c_adapter) + * @adapter: board private structure to initialize +@@ -728,9 +773,8 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) + device_set_wakeup_enable(&pdev->dev, false); + adapter->link_speed = SPEED_0; + adapter->link_duplex = FULL_DUPLEX; +- adapter->num_rx_queues = AT_DEF_RECEIVE_QUEUE; + adapter->tpd_ring[0].count = 1024; +- adapter->rfd_ring[0].count = 512; ++ adapter->rfd_ring.count = 512; + + hw->vendor_id = pdev->vendor; + hw->device_id = pdev->device; +@@ -745,26 +789,18 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) + dev_err(&pdev->dev, "set mac function pointers failed\n"); + return -1; + } ++ atl1c_patch_assign(hw); ++ + hw->intr_mask = IMR_NORMAL_MASK; + hw->phy_configured = false; + hw->preamble_len = 7; + hw->max_frame_size = adapter->netdev->mtu; +- if (adapter->num_rx_queues < 2) { +- hw->rss_type = atl1c_rss_disable; +- hw->rss_mode = atl1c_rss_mode_disable; +- } else { +- hw->rss_type = atl1c_rss_ipv4; +- hw->rss_mode = atl1c_rss_mul_que_mul_int; +- hw->rss_hash_bits = 16; +- } + hw->autoneg_advertised = ADVERTISED_Autoneg; + hw->indirect_tab = 0xE4E4E4E4; + hw->base_cpu = 0; + + hw->ict = 50000; /* 100ms */ + hw->smb_timer = 200000; /* 400ms */ +- hw->cmb_tpd = 4; +- hw->cmb_tx_timer = 1; /* 2 us */ + hw->rx_imt = 200; + hw->tx_imt = 1000; + +@@ -772,9 +808,6 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) + hw->rfd_burst = 8; + hw->dma_order = atl1c_dma_ord_out; + hw->dmar_block = atl1c_dma_req_1024; +- hw->dmaw_block = atl1c_dma_req_1024; +- hw->dmar_dly_cnt = 15; +- hw->dmaw_dly_cnt = 4; + + if (atl1c_alloc_queues(adapter)) { + dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); +@@ -850,24 +883,22 @@ static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter, + */ + static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter) + { +- struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring; +- struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring; ++ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; ++ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1c_buffer *buffer_info; + struct pci_dev *pdev = adapter->pdev; +- int i, j; ++ int j; + +- for (i = 0; i < adapter->num_rx_queues; i++) { +- for (j = 0; j < rfd_ring[i].count; j++) { +- buffer_info = &rfd_ring[i].buffer_info[j]; +- atl1c_clean_buffer(pdev, buffer_info, 0); +- } +- /* zero out the descriptor ring */ +- memset(rfd_ring[i].desc, 0, rfd_ring[i].size); +- rfd_ring[i].next_to_clean = 0; +- rfd_ring[i].next_to_use = 0; +- rrd_ring[i].next_to_use = 0; +- rrd_ring[i].next_to_clean = 0; ++ for (j = 0; j < rfd_ring->count; j++) { ++ buffer_info = &rfd_ring->buffer_info[j]; ++ atl1c_clean_buffer(pdev, buffer_info, 0); + } ++ /* zero out the descriptor ring */ ++ memset(rfd_ring->desc, 0, rfd_ring->size); ++ rfd_ring->next_to_clean = 0; ++ rfd_ring->next_to_use = 0; ++ rrd_ring->next_to_use = 0; ++ rrd_ring->next_to_clean = 0; + } + + /* +@@ -876,8 +907,8 @@ static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter) + static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter) + { + struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; +- struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring; +- struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring; ++ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; ++ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1c_buffer *buffer_info; + int i, j; + +@@ -889,15 +920,13 @@ static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter) + ATL1C_SET_BUFFER_STATE(&buffer_info[i], + ATL1C_BUFFER_FREE); + } +- for (i = 0; i < adapter->num_rx_queues; i++) { +- rfd_ring[i].next_to_use = 0; +- rfd_ring[i].next_to_clean = 0; +- rrd_ring[i].next_to_use = 0; +- rrd_ring[i].next_to_clean = 0; +- for (j = 0; j < rfd_ring[i].count; j++) { +- buffer_info = &rfd_ring[i].buffer_info[j]; +- ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); +- } ++ rfd_ring->next_to_use = 0; ++ rfd_ring->next_to_clean = 0; ++ rrd_ring->next_to_use = 0; ++ rrd_ring->next_to_clean = 0; ++ for (j = 0; j < rfd_ring->count; j++) { ++ buffer_info = &rfd_ring->buffer_info[j]; ++ ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); + } + } + +@@ -934,27 +963,23 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) + { + struct pci_dev *pdev = adapter->pdev; + struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; +- struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring; +- struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring; ++ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; ++ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1c_ring_header *ring_header = &adapter->ring_header; +- int num_rx_queues = adapter->num_rx_queues; + int size; + int i; + int count = 0; + int rx_desc_count = 0; + u32 offset = 0; + +- rrd_ring[0].count = rfd_ring[0].count; ++ rrd_ring->count = rfd_ring->count; + for (i = 1; i < AT_MAX_TRANSMIT_QUEUE; i++) + tpd_ring[i].count = tpd_ring[0].count; + +- for (i = 1; i < adapter->num_rx_queues; i++) +- rfd_ring[i].count = rrd_ring[i].count = rfd_ring[0].count; +- + /* 2 tpd queue, one high priority queue, + * another normal priority queue */ + size = sizeof(struct atl1c_buffer) * (tpd_ring->count * 2 + +- rfd_ring->count * num_rx_queues); ++ rfd_ring->count); + tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL); + if (unlikely(!tpd_ring->buffer_info)) { + dev_err(&pdev->dev, "kzalloc failed, size = %d\n", +@@ -967,12 +992,11 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) + count += tpd_ring[i].count; + } + +- for (i = 0; i < num_rx_queues; i++) { +- rfd_ring[i].buffer_info = +- (struct atl1c_buffer *) (tpd_ring->buffer_info + count); +- count += rfd_ring[i].count; +- rx_desc_count += rfd_ring[i].count; +- } ++ rfd_ring->buffer_info = ++ (struct atl1c_buffer *) (tpd_ring->buffer_info + count); ++ count += rfd_ring->count; ++ rx_desc_count += rfd_ring->count; ++ + /* + * real ring DMA buffer + * each ring/block may need up to 8 bytes for alignment, hence the +@@ -982,8 +1006,7 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) + sizeof(struct atl1c_tpd_desc) * tpd_ring->count * 2 + + sizeof(struct atl1c_rx_free_desc) * rx_desc_count + + sizeof(struct atl1c_recv_ret_status) * rx_desc_count + +- sizeof(struct atl1c_hw_stats) + +- 8 * 4 + 8 * 2 * num_rx_queues; ++ 8 * 4; + + ring_header->desc = pci_alloc_consistent(pdev, ring_header->size, + &ring_header->dma); +@@ -1004,25 +1027,18 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) + offset += roundup(tpd_ring[i].size, 8); + } + /* init RFD ring */ +- for (i = 0; i < num_rx_queues; i++) { +- rfd_ring[i].dma = ring_header->dma + offset; +- rfd_ring[i].desc = (u8 *) ring_header->desc + offset; +- rfd_ring[i].size = sizeof(struct atl1c_rx_free_desc) * +- rfd_ring[i].count; +- offset += roundup(rfd_ring[i].size, 8); +- } ++ rfd_ring->dma = ring_header->dma + offset; ++ rfd_ring->desc = (u8 *) ring_header->desc + offset; ++ rfd_ring->size = sizeof(struct atl1c_rx_free_desc) * rfd_ring->count; ++ offset += roundup(rfd_ring->size, 8); + + /* init RRD ring */ +- for (i = 0; i < num_rx_queues; i++) { +- rrd_ring[i].dma = ring_header->dma + offset; +- rrd_ring[i].desc = (u8 *) ring_header->desc + offset; +- rrd_ring[i].size = sizeof(struct atl1c_recv_ret_status) * +- rrd_ring[i].count; +- offset += roundup(rrd_ring[i].size, 8); +- } ++ rrd_ring->dma = ring_header->dma + offset; ++ rrd_ring->desc = (u8 *) ring_header->desc + offset; ++ rrd_ring->size = sizeof(struct atl1c_recv_ret_status) * ++ rrd_ring->count; ++ offset += roundup(rrd_ring->size, 8); + +- adapter->smb.dma = ring_header->dma + offset; +- adapter->smb.smb = (u8 *)ring_header->desc + offset; + return 0; + + err_nomem: +@@ -1033,26 +1049,20 @@ err_nomem: + static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) + { + struct atl1c_hw *hw = &adapter->hw; +- struct atl1c_rfd_ring *rfd_ring = (struct atl1c_rfd_ring *) +- adapter->rfd_ring; +- struct atl1c_rrd_ring *rrd_ring = (struct atl1c_rrd_ring *) +- adapter->rrd_ring; ++ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; ++ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *) + adapter->tpd_ring; +- struct atl1c_cmb *cmb = (struct atl1c_cmb *) &adapter->cmb; +- struct atl1c_smb *smb = (struct atl1c_smb *) &adapter->smb; +- int i; +- u32 data; + + /* TPD */ + AT_WRITE_REG(hw, REG_TX_BASE_ADDR_HI, + (u32)((tpd_ring[atl1c_trans_normal].dma & + AT_DMA_HI_ADDR_MASK) >> 32)); + /* just enable normal priority TX queue */ +- AT_WRITE_REG(hw, REG_NTPD_HEAD_ADDR_LO, ++ AT_WRITE_REG(hw, REG_TPD_PRI0_ADDR_LO, + (u32)(tpd_ring[atl1c_trans_normal].dma & + AT_DMA_LO_ADDR_MASK)); +- AT_WRITE_REG(hw, REG_HTPD_HEAD_ADDR_LO, ++ AT_WRITE_REG(hw, REG_TPD_PRI1_ADDR_LO, + (u32)(tpd_ring[atl1c_trans_high].dma & + AT_DMA_LO_ADDR_MASK)); + AT_WRITE_REG(hw, REG_TPD_RING_SIZE, +@@ -1061,31 +1071,21 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) + + /* RFD */ + AT_WRITE_REG(hw, REG_RX_BASE_ADDR_HI, +- (u32)((rfd_ring[0].dma & AT_DMA_HI_ADDR_MASK) >> 32)); +- for (i = 0; i < adapter->num_rx_queues; i++) +- AT_WRITE_REG(hw, atl1c_rfd_addr_lo_regs[i], +- (u32)(rfd_ring[i].dma & AT_DMA_LO_ADDR_MASK)); ++ (u32)((rfd_ring->dma & AT_DMA_HI_ADDR_MASK) >> 32)); ++ AT_WRITE_REG(hw, REG_RFD0_HEAD_ADDR_LO, ++ (u32)(rfd_ring->dma & AT_DMA_LO_ADDR_MASK)); + + AT_WRITE_REG(hw, REG_RFD_RING_SIZE, +- rfd_ring[0].count & RFD_RING_SIZE_MASK); ++ rfd_ring->count & RFD_RING_SIZE_MASK); + AT_WRITE_REG(hw, REG_RX_BUF_SIZE, + adapter->rx_buffer_len & RX_BUF_SIZE_MASK); + + /* RRD */ +- for (i = 0; i < adapter->num_rx_queues; i++) +- AT_WRITE_REG(hw, atl1c_rrd_addr_lo_regs[i], +- (u32)(rrd_ring[i].dma & AT_DMA_LO_ADDR_MASK)); ++ AT_WRITE_REG(hw, REG_RRD0_HEAD_ADDR_LO, ++ (u32)(rrd_ring->dma & AT_DMA_LO_ADDR_MASK)); + AT_WRITE_REG(hw, REG_RRD_RING_SIZE, +- (rrd_ring[0].count & RRD_RING_SIZE_MASK)); ++ (rrd_ring->count & RRD_RING_SIZE_MASK)); + +- /* CMB */ +- AT_WRITE_REG(hw, REG_CMB_BASE_ADDR_LO, cmb->dma & AT_DMA_LO_ADDR_MASK); +- +- /* SMB */ +- AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_HI, +- (u32)((smb->dma & AT_DMA_HI_ADDR_MASK) >> 32)); +- AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_LO, +- (u32)(smb->dma & AT_DMA_LO_ADDR_MASK)); + if (hw->nic_type == athr_l2c_b) { + AT_WRITE_REG(hw, REG_SRAM_RXF_LEN, 0x02a0L); + AT_WRITE_REG(hw, REG_SRAM_TXF_LEN, 0x0100L); +@@ -1096,13 +1096,6 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) + AT_WRITE_REG(hw, REG_TXF_WATER_MARK, 0); /* TX watermark, to enter l1 state.*/ + AT_WRITE_REG(hw, REG_RXD_DMA_CTRL, 0); /* RXD threshold.*/ + } +- if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d_2) { +- /* Power Saving for L2c_B */ +- AT_READ_REG(hw, REG_SERDES_LOCK, &data); +- data |= SERDES_MAC_CLK_SLOWDOWN; +- data |= SERDES_PYH_CLK_SLOWDOWN; +- AT_WRITE_REG(hw, REG_SERDES_LOCK, data); +- } + /* Load all of base address above */ + AT_WRITE_REG(hw, REG_LOAD_PTR, 1); + } +@@ -1110,32 +1103,26 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) + static void atl1c_configure_tx(struct atl1c_adapter *adapter) + { + struct atl1c_hw *hw = &adapter->hw; +- u32 dev_ctrl_data; +- u32 max_pay_load; ++ int max_pay_load; + u16 tx_offload_thresh; + u32 txq_ctrl_data; +- u32 max_pay_load_data; + +- tx_offload_thresh = MAX_TX_OFFLOAD_THRESH; ++ tx_offload_thresh = MAX_TSO_FRAME_SIZE; + AT_WRITE_REG(hw, REG_TX_TSO_OFFLOAD_THRESH, + (tx_offload_thresh >> 3) & TX_TSO_OFFLOAD_THRESH_MASK); +- AT_READ_REG(hw, REG_DEVICE_CTRL, &dev_ctrl_data); +- max_pay_load = (dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT) & +- DEVICE_CTRL_MAX_PAYLOAD_MASK; +- hw->dmaw_block = min_t(u32, max_pay_load, hw->dmaw_block); +- max_pay_load = (dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT) & +- DEVICE_CTRL_MAX_RREQ_SZ_MASK; ++ max_pay_load = pcie_get_readrq(adapter->pdev) >> 8; + hw->dmar_block = min_t(u32, max_pay_load, hw->dmar_block); +- +- txq_ctrl_data = (hw->tpd_burst & TXQ_NUM_TPD_BURST_MASK) << +- TXQ_NUM_TPD_BURST_SHIFT; +- if (hw->ctrl_flags & ATL1C_TXQ_MODE_ENHANCE) +- txq_ctrl_data |= TXQ_CTRL_ENH_MODE; +- max_pay_load_data = (atl1c_pay_load_size[hw->dmar_block] & +- TXQ_TXF_BURST_NUM_MASK) << TXQ_TXF_BURST_NUM_SHIFT; +- if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) +- max_pay_load_data >>= 1; +- txq_ctrl_data |= max_pay_load_data; ++ /* ++ * if BIOS had changed the dam-read-max-length to an invalid value, ++ * restore it to default value ++ */ ++ if (hw->dmar_block < DEVICE_CTRL_MAXRRS_MIN) { ++ pcie_set_readrq(adapter->pdev, 128 << DEVICE_CTRL_MAXRRS_MIN); ++ hw->dmar_block = DEVICE_CTRL_MAXRRS_MIN; ++ } ++ txq_ctrl_data = ++ hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 ? ++ L2CB_TXQ_CFGV : L1C_TXQ_CFGV; + + AT_WRITE_REG(hw, REG_TXQ_CTRL, txq_ctrl_data); + } +@@ -1150,34 +1137,13 @@ static void atl1c_configure_rx(struct atl1c_adapter *adapter) + + if (hw->ctrl_flags & ATL1C_RX_IPV6_CHKSUM) + rxq_ctrl_data |= IPV6_CHKSUM_CTRL_EN; +- if (hw->rss_type == atl1c_rss_ipv4) +- rxq_ctrl_data |= RSS_HASH_IPV4; +- if (hw->rss_type == atl1c_rss_ipv4_tcp) +- rxq_ctrl_data |= RSS_HASH_IPV4_TCP; +- if (hw->rss_type == atl1c_rss_ipv6) +- rxq_ctrl_data |= RSS_HASH_IPV6; +- if (hw->rss_type == atl1c_rss_ipv6_tcp) +- rxq_ctrl_data |= RSS_HASH_IPV6_TCP; +- if (hw->rss_type != atl1c_rss_disable) +- rxq_ctrl_data |= RRS_HASH_CTRL_EN; +- +- rxq_ctrl_data |= (hw->rss_mode & RSS_MODE_MASK) << +- RSS_MODE_SHIFT; +- rxq_ctrl_data |= (hw->rss_hash_bits & RSS_HASH_BITS_MASK) << +- RSS_HASH_BITS_SHIFT; +- if (hw->ctrl_flags & ATL1C_ASPM_CTRL_MON) +- rxq_ctrl_data |= (ASPM_THRUPUT_LIMIT_1M & +- ASPM_THRUPUT_LIMIT_MASK) << ASPM_THRUPUT_LIMIT_SHIFT; + +- AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data); +-} +- +-static void atl1c_configure_rss(struct atl1c_adapter *adapter) +-{ +- struct atl1c_hw *hw = &adapter->hw; ++ /* aspm for gigabit */ ++ if (hw->nic_type != athr_l1d_2 && (hw->device_id & 1) != 0) ++ rxq_ctrl_data = FIELD_SETX(rxq_ctrl_data, ASPM_THRUPUT_LIMIT, ++ ASPM_THRUPUT_LIMIT_100M); + +- AT_WRITE_REG(hw, REG_IDT_TABLE, hw->indirect_tab); +- AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, hw->base_cpu); ++ AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data); + } + + static void atl1c_configure_dma(struct atl1c_adapter *adapter) +@@ -1185,36 +1151,11 @@ static void atl1c_configure_dma(struct atl1c_adapter *adapter) + struct atl1c_hw *hw = &adapter->hw; + u32 dma_ctrl_data; + +- dma_ctrl_data = DMA_CTRL_DMAR_REQ_PRI; +- if (hw->ctrl_flags & ATL1C_CMB_ENABLE) +- dma_ctrl_data |= DMA_CTRL_CMB_EN; +- if (hw->ctrl_flags & ATL1C_SMB_ENABLE) +- dma_ctrl_data |= DMA_CTRL_SMB_EN; +- else +- dma_ctrl_data |= MAC_CTRL_SMB_DIS; +- +- switch (hw->dma_order) { +- case atl1c_dma_ord_in: +- dma_ctrl_data |= DMA_CTRL_DMAR_IN_ORDER; +- break; +- case atl1c_dma_ord_enh: +- dma_ctrl_data |= DMA_CTRL_DMAR_ENH_ORDER; +- break; +- case atl1c_dma_ord_out: +- dma_ctrl_data |= DMA_CTRL_DMAR_OUT_ORDER; +- break; +- default: +- break; +- } +- +- dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK) +- << DMA_CTRL_DMAR_BURST_LEN_SHIFT; +- dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK) +- << DMA_CTRL_DMAW_BURST_LEN_SHIFT; +- dma_ctrl_data |= (((u32)hw->dmar_dly_cnt) & DMA_CTRL_DMAR_DLY_CNT_MASK) +- << DMA_CTRL_DMAR_DLY_CNT_SHIFT; +- dma_ctrl_data |= (((u32)hw->dmaw_dly_cnt) & DMA_CTRL_DMAW_DLY_CNT_MASK) +- << DMA_CTRL_DMAW_DLY_CNT_SHIFT; ++ dma_ctrl_data = FIELDX(DMA_CTRL_RORDER_MODE, DMA_CTRL_RORDER_MODE_OUT) | ++ DMA_CTRL_RREQ_PRI_DATA | ++ FIELDX(DMA_CTRL_RREQ_BLEN, hw->dmar_block) | ++ FIELDX(DMA_CTRL_WDLY_CNT, DMA_CTRL_WDLY_CNT_DEF) | ++ FIELDX(DMA_CTRL_RDLY_CNT, DMA_CTRL_RDLY_CNT_DEF); + + AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data); + } +@@ -1229,52 +1170,53 @@ static int atl1c_stop_mac(struct atl1c_hw *hw) + u32 data; + + AT_READ_REG(hw, REG_RXQ_CTRL, &data); +- data &= ~(RXQ1_CTRL_EN | RXQ2_CTRL_EN | +- RXQ3_CTRL_EN | RXQ_CTRL_EN); ++ data &= ~RXQ_CTRL_EN; + AT_WRITE_REG(hw, REG_RXQ_CTRL, data); + + AT_READ_REG(hw, REG_TXQ_CTRL, &data); + data &= ~TXQ_CTRL_EN; +- AT_WRITE_REG(hw, REG_TWSI_CTRL, data); ++ AT_WRITE_REG(hw, REG_TXQ_CTRL, data); + +- atl1c_wait_until_idle(hw); ++ atl1c_wait_until_idle(hw, IDLE_STATUS_RXQ_BUSY | IDLE_STATUS_TXQ_BUSY); + + AT_READ_REG(hw, REG_MAC_CTRL, &data); + data &= ~(MAC_CTRL_TX_EN | MAC_CTRL_RX_EN); + AT_WRITE_REG(hw, REG_MAC_CTRL, data); + +- return (int)atl1c_wait_until_idle(hw); ++ return (int)atl1c_wait_until_idle(hw, ++ IDLE_STATUS_TXMAC_BUSY | IDLE_STATUS_RXMAC_BUSY); + } + +-static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw) ++static void atl1c_start_mac(struct atl1c_adapter *adapter) + { +- u32 data; +- +- AT_READ_REG(hw, REG_RXQ_CTRL, &data); +- switch (hw->adapter->num_rx_queues) { +- case 4: +- data |= (RXQ3_CTRL_EN | RXQ2_CTRL_EN | RXQ1_CTRL_EN); +- break; +- case 3: +- data |= (RXQ2_CTRL_EN | RXQ1_CTRL_EN); +- break; +- case 2: +- data |= RXQ1_CTRL_EN; +- break; +- default: +- break; +- } +- data |= RXQ_CTRL_EN; +- AT_WRITE_REG(hw, REG_RXQ_CTRL, data); +-} +- +-static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw) +-{ +- u32 data; ++ struct atl1c_hw *hw = &adapter->hw; ++ u32 mac, txq, rxq; ++ ++ hw->mac_duplex = adapter->link_duplex == FULL_DUPLEX ? true : false; ++ hw->mac_speed = adapter->link_speed == SPEED_1000 ? ++ atl1c_mac_speed_1000 : atl1c_mac_speed_10_100; ++ ++ AT_READ_REG(hw, REG_TXQ_CTRL, &txq); ++ AT_READ_REG(hw, REG_RXQ_CTRL, &rxq); ++ AT_READ_REG(hw, REG_MAC_CTRL, &mac); ++ ++ txq |= TXQ_CTRL_EN; ++ rxq |= RXQ_CTRL_EN; ++ mac |= MAC_CTRL_TX_EN | MAC_CTRL_TX_FLOW | ++ MAC_CTRL_RX_EN | MAC_CTRL_RX_FLOW | ++ MAC_CTRL_ADD_CRC | MAC_CTRL_PAD | ++ MAC_CTRL_BC_EN | MAC_CTRL_SINGLE_PAUSE_EN | ++ MAC_CTRL_HASH_ALG_CRC32; ++ if (hw->mac_duplex) ++ mac |= MAC_CTRL_DUPLX; ++ else ++ mac &= ~MAC_CTRL_DUPLX; ++ mac = FIELD_SETX(mac, MAC_CTRL_SPEED, hw->mac_speed); ++ mac = FIELD_SETX(mac, MAC_CTRL_PRMLEN, hw->preamble_len); + +- AT_READ_REG(hw, REG_TXQ_CTRL, &data); +- data |= TXQ_CTRL_EN; +- AT_WRITE_REG(hw, REG_TXQ_CTRL, data); ++ AT_WRITE_REG(hw, REG_TXQ_CTRL, txq); ++ AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq); ++ AT_WRITE_REG(hw, REG_MAC_CTRL, mac); + } + + /* +@@ -1286,10 +1228,7 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) + { + struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; + struct pci_dev *pdev = adapter->pdev; +- u32 master_ctrl_data = 0; +- +- AT_WRITE_REG(hw, REG_IMR, 0); +- AT_WRITE_REG(hw, REG_ISR, ISR_DIS_INT); ++ u32 ctrl_data = 0; + + atl1c_stop_mac(hw); + /* +@@ -1298,194 +1237,148 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) + * the current PCI configuration. The global reset bit is self- + * clearing, and should clear within a microsecond. + */ +- AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); +- master_ctrl_data |= MASTER_CTRL_OOB_DIS_OFF; +- AT_WRITE_REGW(hw, REG_MASTER_CTRL, ((master_ctrl_data | MASTER_CTRL_SOFT_RST) +- & 0xFFFF)); ++ AT_READ_REG(hw, REG_MASTER_CTRL, &ctrl_data); ++ ctrl_data |= MASTER_CTRL_OOB_DIS; ++ AT_WRITE_REG(hw, REG_MASTER_CTRL, ctrl_data | MASTER_CTRL_SOFT_RST); + + AT_WRITE_FLUSH(hw); + msleep(10); + /* Wait at least 10ms for All module to be Idle */ + +- if (atl1c_wait_until_idle(hw)) { ++ if (atl1c_wait_until_idle(hw, IDLE_STATUS_MASK)) { + dev_err(&pdev->dev, + "MAC state machine can't be idle since" + " disabled for 10ms second\n"); + return -1; + } ++ AT_WRITE_REG(hw, REG_MASTER_CTRL, ctrl_data); ++ ++ /* driver control speed/duplex */ ++ AT_READ_REG(hw, REG_MAC_CTRL, &ctrl_data); ++ AT_WRITE_REG(hw, REG_MAC_CTRL, ctrl_data | MAC_CTRL_SPEED_MODE_SW); ++ ++ /* clk switch setting */ ++ AT_READ_REG(hw, REG_SERDES, &ctrl_data); ++ switch (hw->nic_type) { ++ case athr_l2c_b: ++ ctrl_data &= ~(SERDES_PHY_CLK_SLOWDOWN | ++ SERDES_MAC_CLK_SLOWDOWN); ++ AT_WRITE_REG(hw, REG_SERDES, ctrl_data); ++ break; ++ case athr_l2c_b2: ++ case athr_l1d_2: ++ ctrl_data |= SERDES_PHY_CLK_SLOWDOWN | SERDES_MAC_CLK_SLOWDOWN; ++ AT_WRITE_REG(hw, REG_SERDES, ctrl_data); ++ break; ++ default: ++ break; ++ } ++ + return 0; + } + + static void atl1c_disable_l0s_l1(struct atl1c_hw *hw) + { +- u32 pm_ctrl_data; ++ u16 ctrl_flags = hw->ctrl_flags; + +- AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data); +- pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << +- PM_CTRL_L1_ENTRY_TIMER_SHIFT); +- pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1; +- pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; +- pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; +- pm_ctrl_data &= ~PM_CTRL_MAC_ASPM_CHK; +- pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1; +- +- pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN; +- pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN; +- pm_ctrl_data |= PM_CTRL_SERDES_L1_EN; +- AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data); ++ hw->ctrl_flags &= ~(ATL1C_ASPM_L0S_SUPPORT | ATL1C_ASPM_L1_SUPPORT); ++ atl1c_set_aspm(hw, SPEED_0); ++ hw->ctrl_flags = ctrl_flags; + } + + /* + * Set ASPM state. + * Enable/disable L0s/L1 depend on link state. + */ +-static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup) ++static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed) + { + u32 pm_ctrl_data; +- u32 link_ctrl_data; +- u32 link_l1_timer = 0xF; ++ u32 link_l1_timer; + + AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data); +- AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data); ++ pm_ctrl_data &= ~(PM_CTRL_ASPM_L1_EN | ++ PM_CTRL_ASPM_L0S_EN | ++ PM_CTRL_MAC_ASPM_CHK); ++ /* L1 timer */ ++ if (hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { ++ pm_ctrl_data &= ~PMCTRL_TXL1_AFTER_L0S; ++ link_l1_timer = ++ link_speed == SPEED_1000 || link_speed == SPEED_100 ? ++ L1D_PMCTRL_L1_ENTRY_TM_16US : 1; ++ pm_ctrl_data = FIELD_SETX(pm_ctrl_data, ++ L1D_PMCTRL_L1_ENTRY_TM, link_l1_timer); ++ } else { ++ link_l1_timer = hw->nic_type == athr_l2c_b ? ++ L2CB1_PM_CTRL_L1_ENTRY_TM : L1C_PM_CTRL_L1_ENTRY_TM; ++ if (link_speed != SPEED_1000 && link_speed != SPEED_100) ++ link_l1_timer = 1; ++ pm_ctrl_data = FIELD_SETX(pm_ctrl_data, ++ PM_CTRL_L1_ENTRY_TIMER, link_l1_timer); ++ } + +- pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1; +- pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << +- PM_CTRL_L1_ENTRY_TIMER_SHIFT); +- pm_ctrl_data &= ~(PM_CTRL_LCKDET_TIMER_MASK << +- PM_CTRL_LCKDET_TIMER_SHIFT); +- pm_ctrl_data |= AT_LCKDET_TIMER << PM_CTRL_LCKDET_TIMER_SHIFT; ++ /* L0S/L1 enable */ ++ if ((hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT) && link_speed != SPEED_0) ++ pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN | PM_CTRL_MAC_ASPM_CHK; ++ if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) ++ pm_ctrl_data |= PM_CTRL_ASPM_L1_EN | PM_CTRL_MAC_ASPM_CHK; + ++ /* l2cb & l1d & l2cb2 & l1d2 */ + if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d || +- hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { +- link_ctrl_data &= ~LINK_CTRL_EXT_SYNC; +- if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) { +- if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) +- link_ctrl_data |= LINK_CTRL_EXT_SYNC; +- } +- +- AT_WRITE_REG(hw, REG_LINK_CTRL, link_ctrl_data); +- +- pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER; +- pm_ctrl_data &= ~(PM_CTRL_PM_REQ_TIMER_MASK << +- PM_CTRL_PM_REQ_TIMER_SHIFT); +- pm_ctrl_data |= AT_ASPM_L1_TIMER << +- PM_CTRL_PM_REQ_TIMER_SHIFT; +- pm_ctrl_data &= ~PM_CTRL_SA_DLY_EN; +- pm_ctrl_data &= ~PM_CTRL_HOTRST; +- pm_ctrl_data |= 1 << PM_CTRL_L1_ENTRY_TIMER_SHIFT; +- pm_ctrl_data |= PM_CTRL_SERDES_PD_EX_L1; +- } +- pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK; +- if (linkup) { +- pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; +- pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; +- if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) +- pm_ctrl_data |= PM_CTRL_ASPM_L1_EN; +- if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT) +- pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN; +- +- if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d || +- hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { +- if (hw->nic_type == athr_l2c_b) +- if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) +- pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; +- pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN; +- pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN; +- pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN; +- pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; +- if (hw->adapter->link_speed == SPEED_100 || +- hw->adapter->link_speed == SPEED_1000) { +- pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << +- PM_CTRL_L1_ENTRY_TIMER_SHIFT); +- if (hw->nic_type == athr_l2c_b) +- link_l1_timer = 7; +- else if (hw->nic_type == athr_l2c_b2 || +- hw->nic_type == athr_l1d_2) +- link_l1_timer = 4; +- pm_ctrl_data |= link_l1_timer << +- PM_CTRL_L1_ENTRY_TIMER_SHIFT; +- } +- } else { +- pm_ctrl_data |= PM_CTRL_SERDES_L1_EN; +- pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN; +- pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN; +- pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1; ++ hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { ++ pm_ctrl_data = FIELD_SETX(pm_ctrl_data, ++ PM_CTRL_PM_REQ_TIMER, PM_CTRL_PM_REQ_TO_DEF); ++ pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER | ++ PM_CTRL_SERDES_PD_EX_L1 | ++ PM_CTRL_CLK_SWH_L1; ++ pm_ctrl_data &= ~(PM_CTRL_SERDES_L1_EN | ++ PM_CTRL_SERDES_PLL_L1_EN | ++ PM_CTRL_SERDES_BUFS_RX_L1_EN | ++ PM_CTRL_SA_DLY_EN | ++ PM_CTRL_HOTRST); ++ /* disable l0s if link down or l2cb */ ++ if (link_speed == SPEED_0 || hw->nic_type == athr_l2c_b) + pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; +- pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; +- ++ } else { /* l1c */ ++ pm_ctrl_data = ++ FIELD_SETX(pm_ctrl_data, PM_CTRL_L1_ENTRY_TIMER, 0); ++ if (link_speed != SPEED_0) { ++ pm_ctrl_data |= PM_CTRL_SERDES_L1_EN | ++ PM_CTRL_SERDES_PLL_L1_EN | ++ PM_CTRL_SERDES_BUFS_RX_L1_EN; ++ pm_ctrl_data &= ~(PM_CTRL_SERDES_PD_EX_L1 | ++ PM_CTRL_CLK_SWH_L1 | ++ PM_CTRL_ASPM_L0S_EN | ++ PM_CTRL_ASPM_L1_EN); ++ } else { /* link down */ ++ pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; ++ pm_ctrl_data &= ~(PM_CTRL_SERDES_L1_EN | ++ PM_CTRL_SERDES_PLL_L1_EN | ++ PM_CTRL_SERDES_BUFS_RX_L1_EN | ++ PM_CTRL_ASPM_L0S_EN); + } +- } else { +- pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN; +- pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; +- pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN; +- pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; +- +- if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) +- pm_ctrl_data |= PM_CTRL_ASPM_L1_EN; +- else +- pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; + } + AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data); + + return; + } + +-static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter) +-{ +- struct atl1c_hw *hw = &adapter->hw; +- struct net_device *netdev = adapter->netdev; +- u32 mac_ctrl_data; +- +- mac_ctrl_data = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN; +- mac_ctrl_data |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW); +- +- if (adapter->link_duplex == FULL_DUPLEX) { +- hw->mac_duplex = true; +- mac_ctrl_data |= MAC_CTRL_DUPLX; +- } +- +- if (adapter->link_speed == SPEED_1000) +- hw->mac_speed = atl1c_mac_speed_1000; +- else +- hw->mac_speed = atl1c_mac_speed_10_100; +- +- mac_ctrl_data |= (hw->mac_speed & MAC_CTRL_SPEED_MASK) << +- MAC_CTRL_SPEED_SHIFT; +- +- mac_ctrl_data |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD); +- mac_ctrl_data |= ((hw->preamble_len & MAC_CTRL_PRMLEN_MASK) << +- MAC_CTRL_PRMLEN_SHIFT); +- +- __atl1c_vlan_mode(netdev->features, &mac_ctrl_data); +- +- mac_ctrl_data |= MAC_CTRL_BC_EN; +- if (netdev->flags & IFF_PROMISC) +- mac_ctrl_data |= MAC_CTRL_PROMIS_EN; +- if (netdev->flags & IFF_ALLMULTI) +- mac_ctrl_data |= MAC_CTRL_MC_ALL_EN; +- +- mac_ctrl_data |= MAC_CTRL_SINGLE_PAUSE_EN; +- if (hw->nic_type == athr_l1d || hw->nic_type == athr_l2c_b2 || +- hw->nic_type == athr_l1d_2) { +- mac_ctrl_data |= MAC_CTRL_SPEED_MODE_SW; +- mac_ctrl_data |= MAC_CTRL_HASH_ALG_CRC32; +- } +- AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); +-} +- + /* + * atl1c_configure - Configure Transmit&Receive Unit after Reset + * @adapter: board private structure + * + * Configure the Tx /Rx unit of the MAC after a reset. + */ +-static int atl1c_configure(struct atl1c_adapter *adapter) ++static int atl1c_configure_mac(struct atl1c_adapter *adapter) + { + struct atl1c_hw *hw = &adapter->hw; + u32 master_ctrl_data = 0; + u32 intr_modrt_data; + u32 data; + ++ AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); ++ master_ctrl_data &= ~(MASTER_CTRL_TX_ITIMER_EN | ++ MASTER_CTRL_RX_ITIMER_EN | ++ MASTER_CTRL_INT_RDCLR); + /* clear interrupt status */ + AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF); + /* Clear any WOL status */ +@@ -1524,30 +1417,39 @@ static int atl1c_configure(struct atl1c_adapter *adapter) + master_ctrl_data |= MASTER_CTRL_SA_TIMER_EN; + AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); + +- if (hw->ctrl_flags & ATL1C_CMB_ENABLE) { +- AT_WRITE_REG(hw, REG_CMB_TPD_THRESH, +- hw->cmb_tpd & CMB_TPD_THRESH_MASK); +- AT_WRITE_REG(hw, REG_CMB_TX_TIMER, +- hw->cmb_tx_timer & CMB_TX_TIMER_MASK); +- } ++ AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, ++ hw->smb_timer & SMB_STAT_TIMER_MASK); + +- if (hw->ctrl_flags & ATL1C_SMB_ENABLE) +- AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, +- hw->smb_timer & SMB_STAT_TIMER_MASK); + /* set MTU */ + AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN + + VLAN_HLEN + ETH_FCS_LEN); +- /* HDS, disable */ +- AT_WRITE_REG(hw, REG_HDS_CTRL, 0); + + atl1c_configure_tx(adapter); + atl1c_configure_rx(adapter); +- atl1c_configure_rss(adapter); + atl1c_configure_dma(adapter); + + return 0; + } + ++static int atl1c_configure(struct atl1c_adapter *adapter) ++{ ++ struct net_device *netdev = adapter->netdev; ++ int num; ++ ++ atl1c_init_ring_ptrs(adapter); ++ atl1c_set_multi(netdev); ++ atl1c_restore_vlan(adapter); ++ ++ num = atl1c_alloc_rx_buffer(adapter); ++ if (unlikely(num == 0)) ++ return -ENOMEM; ++ ++ if (atl1c_configure_mac(adapter)) ++ return -EIO; ++ ++ return 0; ++} ++ + static void atl1c_update_hw_stats(struct atl1c_adapter *adapter) + { + u16 hw_reg_addr = 0; +@@ -1634,16 +1536,11 @@ static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter, + struct pci_dev *pdev = adapter->pdev; + u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean); + u16 hw_next_to_clean; +- u16 shift; +- u32 data; ++ u16 reg; + +- if (type == atl1c_trans_high) +- shift = MB_HTPD_CONS_IDX_SHIFT; +- else +- shift = MB_NTPD_CONS_IDX_SHIFT; ++ reg = type == atl1c_trans_high ? REG_TPD_PRI1_CIDX : REG_TPD_PRI0_CIDX; + +- AT_READ_REG(&adapter->hw, REG_MB_PRIO_CONS_IDX, &data); +- hw_next_to_clean = (data >> shift) & MB_PRIO_PROD_IDX_MASK; ++ AT_READ_REGW(&adapter->hw, reg, &hw_next_to_clean); + + while (next_to_clean != hw_next_to_clean) { + buffer_info = &tpd_ring->buffer_info[next_to_clean]; +@@ -1745,9 +1642,9 @@ static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter, + skb_checksum_none_assert(skb); + } + +-static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid) ++static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter) + { +- struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[ringid]; ++ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; + struct pci_dev *pdev = adapter->pdev; + struct atl1c_buffer *buffer_info, *next_info; + struct sk_buff *skb; +@@ -1799,7 +1696,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid + /* TODO: update mailbox here */ + wmb(); + rfd_ring->next_to_use = rfd_next_to_use; +- AT_WRITE_REG(&adapter->hw, atl1c_rfd_prod_idx_regs[ringid], ++ AT_WRITE_REG(&adapter->hw, REG_MB_RFD0_PROD_IDX, + rfd_ring->next_to_use & MB_RFDX_PROD_IDX_MASK); + } + +@@ -1838,7 +1735,7 @@ static void atl1c_clean_rfd(struct atl1c_rfd_ring *rfd_ring, + rfd_ring->next_to_clean = rfd_index; + } + +-static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que, ++static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, + int *work_done, int work_to_do) + { + u16 rfd_num, rfd_index; +@@ -1846,8 +1743,8 @@ static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que, + u16 length; + struct pci_dev *pdev = adapter->pdev; + struct net_device *netdev = adapter->netdev; +- struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[que]; +- struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring[que]; ++ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; ++ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct sk_buff *skb; + struct atl1c_recv_ret_status *rrs; + struct atl1c_buffer *buffer_info; +@@ -1913,7 +1810,7 @@ rrs_checked: + count++; + } + if (count) +- atl1c_alloc_rx_buffer(adapter, que); ++ atl1c_alloc_rx_buffer(adapter); + } + + /* +@@ -1930,7 +1827,7 @@ static int atl1c_clean(struct napi_struct *napi, int budget) + if (!netif_carrier_ok(adapter->netdev)) + goto quit_polling; + /* just enable one RXQ */ +- atl1c_clean_rx_irq(adapter, 0, &work_done, budget); ++ atl1c_clean_rx_irq(adapter, &work_done, budget); + + if (work_done < budget) { + quit_polling: +@@ -2205,23 +2102,10 @@ static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb, + struct atl1c_tpd_desc *tpd, enum atl1c_trans_queue type) + { + struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; +- u32 prod_data; ++ u16 reg; + +- AT_READ_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, &prod_data); +- switch (type) { +- case atl1c_trans_high: +- prod_data &= 0xFFFF0000; +- prod_data |= tpd_ring->next_to_use & 0xFFFF; +- break; +- case atl1c_trans_normal: +- prod_data &= 0x0000FFFF; +- prod_data |= (tpd_ring->next_to_use & 0xFFFF) << 16; +- break; +- default: +- break; +- } +- wmb(); +- AT_WRITE_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, prod_data); ++ reg = type == atl1c_trans_high ? REG_TPD_PRI1_PIDX : REG_TPD_PRI0_PIDX; ++ AT_WRITE_REGW(&adapter->hw, reg, tpd_ring->next_to_use); + } + + static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb, +@@ -2327,44 +2211,38 @@ static int atl1c_request_irq(struct atl1c_adapter *adapter) + return err; + } + ++ ++static void atl1c_reset_dma_ring(struct atl1c_adapter *adapter) ++{ ++ /* release tx-pending skbs and reset tx/rx ring index */ ++ atl1c_clean_tx_ring(adapter, atl1c_trans_normal); ++ atl1c_clean_tx_ring(adapter, atl1c_trans_high); ++ atl1c_clean_rx_ring(adapter); ++} ++ + static int atl1c_up(struct atl1c_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; +- int num; + int err; +- int i; + + netif_carrier_off(netdev); +- atl1c_init_ring_ptrs(adapter); +- atl1c_set_multi(netdev); +- atl1c_restore_vlan(adapter); +- +- for (i = 0; i < adapter->num_rx_queues; i++) { +- num = atl1c_alloc_rx_buffer(adapter, i); +- if (unlikely(num == 0)) { +- err = -ENOMEM; +- goto err_alloc_rx; +- } +- } + +- if (atl1c_configure(adapter)) { +- err = -EIO; ++ err = atl1c_configure(adapter); ++ if (unlikely(err)) + goto err_up; +- } + + err = atl1c_request_irq(adapter); + if (unlikely(err)) + goto err_up; + ++ atl1c_check_link_status(adapter); + clear_bit(__AT_DOWN, &adapter->flags); + napi_enable(&adapter->napi); + atl1c_irq_enable(adapter); +- atl1c_check_link_status(adapter); + netif_start_queue(netdev); + return err; + + err_up: +-err_alloc_rx: + atl1c_clean_rx_ring(adapter); + return err; + } +@@ -2382,15 +2260,15 @@ static void atl1c_down(struct atl1c_adapter *adapter) + napi_disable(&adapter->napi); + atl1c_irq_disable(adapter); + atl1c_free_irq(adapter); ++ /* disable ASPM if device inactive */ ++ atl1c_disable_l0s_l1(&adapter->hw); + /* reset MAC to disable all RX/TX */ + atl1c_reset_mac(&adapter->hw); + msleep(1); + + adapter->link_speed = SPEED_0; + adapter->link_duplex = -1; +- atl1c_clean_tx_ring(adapter, atl1c_trans_normal); +- atl1c_clean_tx_ring(adapter, atl1c_trans_high); +- atl1c_clean_rx_ring(adapter); ++ atl1c_reset_dma_ring(adapter); + } + + /* +@@ -2423,13 +2301,6 @@ static int atl1c_open(struct net_device *netdev) + if (unlikely(err)) + goto err_up; + +- if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) { +- u32 phy_data; +- +- AT_READ_REG(&adapter->hw, REG_MDIO_CTRL, &phy_data); +- phy_data |= MDIO_AP_EN; +- AT_WRITE_REG(&adapter->hw, REG_MDIO_CTRL, phy_data); +- } + return 0; + + err_up: +@@ -2455,6 +2326,8 @@ static int atl1c_close(struct net_device *netdev) + struct atl1c_adapter *adapter = netdev_priv(netdev); + + WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); ++ set_bit(__AT_DOWN, &adapter->flags); ++ cancel_work_sync(&adapter->common_task); + atl1c_down(adapter); + atl1c_free_ring_resources(adapter); + return 0; +@@ -2466,10 +2339,6 @@ static int atl1c_suspend(struct device *dev) + struct net_device *netdev = pci_get_drvdata(pdev); + struct atl1c_adapter *adapter = netdev_priv(netdev); + struct atl1c_hw *hw = &adapter->hw; +- u32 mac_ctrl_data = 0; +- u32 master_ctrl_data = 0; +- u32 wol_ctrl_data = 0; +- u16 mii_intr_status_data = 0; + u32 wufc = adapter->wol; + + atl1c_disable_l0s_l1(hw); +@@ -2480,75 +2349,10 @@ static int atl1c_suspend(struct device *dev) + netif_device_detach(netdev); + + if (wufc) +- if (atl1c_phy_power_saving(hw) != 0) ++ if (atl1c_phy_to_ps_link(hw) != 0) + dev_dbg(&pdev->dev, "phy power saving failed"); + +- AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); +- AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data); +- +- master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS; +- mac_ctrl_data &= ~(MAC_CTRL_PRMLEN_MASK << MAC_CTRL_PRMLEN_SHIFT); +- mac_ctrl_data |= (((u32)adapter->hw.preamble_len & +- MAC_CTRL_PRMLEN_MASK) << +- MAC_CTRL_PRMLEN_SHIFT); +- mac_ctrl_data &= ~(MAC_CTRL_SPEED_MASK << MAC_CTRL_SPEED_SHIFT); +- mac_ctrl_data &= ~MAC_CTRL_DUPLX; +- +- if (wufc) { +- mac_ctrl_data |= MAC_CTRL_RX_EN; +- if (adapter->link_speed == SPEED_1000 || +- adapter->link_speed == SPEED_0) { +- mac_ctrl_data |= atl1c_mac_speed_1000 << +- MAC_CTRL_SPEED_SHIFT; +- mac_ctrl_data |= MAC_CTRL_DUPLX; +- } else +- mac_ctrl_data |= atl1c_mac_speed_10_100 << +- MAC_CTRL_SPEED_SHIFT; +- +- if (adapter->link_duplex == DUPLEX_FULL) +- mac_ctrl_data |= MAC_CTRL_DUPLX; +- +- /* turn on magic packet wol */ +- if (wufc & AT_WUFC_MAG) +- wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN; +- +- if (wufc & AT_WUFC_LNKC) { +- wol_ctrl_data |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN; +- /* only link up can wake up */ +- if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) { +- dev_dbg(&pdev->dev, "%s: read write phy " +- "register failed.\n", +- atl1c_driver_name); +- } +- } +- /* clear phy interrupt */ +- atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data); +- /* Config MAC Ctrl register */ +- __atl1c_vlan_mode(netdev->features, &mac_ctrl_data); +- +- /* magic packet maybe Broadcast&multicast&Unicast frame */ +- if (wufc & AT_WUFC_MAG) +- mac_ctrl_data |= MAC_CTRL_BC_EN; +- +- dev_dbg(&pdev->dev, +- "%s: suspend MAC=0x%x\n", +- atl1c_driver_name, mac_ctrl_data); +- AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); +- AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data); +- AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); +- +- AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT | +- GPHY_CTRL_EXT_RESET); +- } else { +- AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_POWER_SAVING); +- master_ctrl_data |= MASTER_CTRL_CLK_SEL_DIS; +- mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT; +- mac_ctrl_data |= MAC_CTRL_DUPLX; +- AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); +- AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); +- AT_WRITE_REG(hw, REG_WOL_CTRL, 0); +- hw->phy_configured = false; /* re-init PHY when resume */ +- } ++ atl1c_power_saving(hw, wufc); + + return 0; + } +@@ -2561,8 +2365,7 @@ static int atl1c_resume(struct device *dev) + struct atl1c_adapter *adapter = netdev_priv(netdev); + + AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); +- atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE | +- ATL1C_PCIE_PHY_RESET); ++ atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE); + + atl1c_phy_reset(&adapter->hw); + atl1c_reset_mac(&adapter->hw); +@@ -2713,7 +2516,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, + adapter->mii.mdio_read = atl1c_mdio_read; + adapter->mii.mdio_write = atl1c_mdio_write; + adapter->mii.phy_id_mask = 0x1f; +- adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK; ++ adapter->mii.reg_num_mask = MDIO_CTRL_REG_MASK; + netif_napi_add(netdev, &adapter->napi, atl1c_clean, 64); + setup_timer(&adapter->phy_config_timer, atl1c_phy_config, + (unsigned long)adapter); +@@ -2723,8 +2526,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, + dev_err(&pdev->dev, "net device private data init failed\n"); + goto err_sw_init; + } +- atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE | +- ATL1C_PCIE_PHY_RESET); ++ atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE); + + /* Init GPHY as early as possible due to power saving issue */ + atl1c_phy_reset(&adapter->hw); +@@ -2753,7 +2555,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, + dev_dbg(&pdev->dev, "mac address : %pM\n", + adapter->hw.mac_addr); + +- atl1c_hw_set_mac_addr(&adapter->hw); ++ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr); + INIT_WORK(&adapter->common_task, atl1c_common_task); + adapter->work_event = 0; + err = register_netdev(netdev); +@@ -2798,6 +2600,8 @@ static void __devexit atl1c_remove(struct pci_dev *pdev) + struct atl1c_adapter *adapter = netdev_priv(netdev); + + unregister_netdev(netdev); ++ /* restore permanent address */ ++ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.perm_mac_addr); + atl1c_phy_disable(&adapter->hw); + + iounmap(adapter->hw.hw_addr); diff --git a/kernel.spec b/kernel.spec index bec326fc9..20a076e9c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -701,6 +701,9 @@ Patch22013: ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch #rhbz 818820 Patch22016: dl2k-Clean-up-rio_ioctl.patch +#rhbz 749276 +Patch22018: atl1c_net_next_update-3.3.patch + # END OF PATCH DEFINITIONS %endif @@ -1293,6 +1296,9 @@ ApplyPatch ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch #rhbz 818820 ApplyPatch dl2k-Clean-up-rio_ioctl.patch +#rhbz 749276 +ApplyPatch atl1c_net_next_update-3.3.patch + # END OF PATCH APPLICATIONS %endif @@ -1945,6 +1951,9 @@ fi # and build. %changelog +* Tue May 15 2012 Josh Boyer +- Fixup atl1c register programming (rhbz 749276) + * Mon May 14 2012 Justin M. Forbes 2.6.43.6-1 - Linux 3.3.6 From 55023013356604136b357d3d522bc08d686ddf35 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 17 May 2012 08:07:44 -0500 Subject: [PATCH 388/397] rtl818x fix sleeping function called from invalid context (rhbz 795176) --- kernel.spec | 11 ++++- ...function-called-from-invalid-context.patch | 49 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 rtl818x-fix-sleeping-function-called-from-invalid-context.patch diff --git a/kernel.spec b/kernel.spec index 20a076e9c..c20f3b9ad 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -704,6 +704,9 @@ Patch22016: dl2k-Clean-up-rio_ioctl.patch #rhbz 749276 Patch22018: atl1c_net_next_update-3.3.patch +#rhbz 795176 +Patch22019: rtl818x-fix-sleeping-function-called-from-invalid-context.patch + # END OF PATCH DEFINITIONS %endif @@ -1299,6 +1302,9 @@ ApplyPatch dl2k-Clean-up-rio_ioctl.patch #rhbz 749276 ApplyPatch atl1c_net_next_update-3.3.patch +#rhbz 795176 +ApplyPatch rtl818x-fix-sleeping-function-called-from-invalid-context.patch + # END OF PATCH APPLICATIONS %endif @@ -1951,6 +1957,9 @@ fi # and build. %changelog +* Wed May 16 2012 Justin M. Forbes 2.6.43.6-3 +- fix rtl8187: ->brightness_set can not sleep (rhbz 795176) + * Tue May 15 2012 Josh Boyer - Fixup atl1c register programming (rhbz 749276) diff --git a/rtl818x-fix-sleeping-function-called-from-invalid-context.patch b/rtl818x-fix-sleeping-function-called-from-invalid-context.patch new file mode 100644 index 000000000..141fcd201 --- /dev/null +++ b/rtl818x-fix-sleeping-function-called-from-invalid-context.patch @@ -0,0 +1,49 @@ +Fix: + +BUG: sleeping function called from invalid context at kernel/workqueue.c:2547 +in_atomic(): 1, irqs_disabled(): 0, pid: 629, name: wpa_supplicant +2 locks held by wpa_supplicant/629: + #0: (rtnl_mutex){+.+.+.}, at: [] rtnl_lock+0x14/0x20 + #1: (&trigger->leddev_list_lock){.+.?..}, at: [] led_trigger_event+0x21/0x80 +Pid: 629, comm: wpa_supplicant Not tainted 3.3.0-0.rc3.git5.1.fc17.i686 +Call Trace: + [] __might_sleep+0x126/0x1d0 + [] wait_on_work+0x2c/0x1d0 + [] __cancel_work_timer+0x6a/0x120 + [] cancel_delayed_work_sync+0x10/0x20 + [] rtl8187_led_brightness_set+0x82/0xf0 [rtl8187] + [] led_trigger_event+0x5c/0x80 + [] ieee80211_led_radio+0x1d/0x40 [mac80211] + [] ieee80211_stop_device+0x13/0x230 [mac80211] + +Removing _sync is ok, because if led_on work is currently running +it will be finished before led_off work start to perform, since +they are always queued on the same mac80211 local->workqueue. + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=795176 + +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/rtl818x/rtl8187/leds.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/rtl818x/rtl8187/leds.c b/drivers/net/wireless/rtl818x/rtl8187/leds.c +index 2e0de2f..c2d5b49 100644 +--- a/drivers/net/wireless/rtl818x/rtl8187/leds.c ++++ b/drivers/net/wireless/rtl818x/rtl8187/leds.c +@@ -117,7 +117,7 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev, + radio_on = true; + } else if (radio_on) { + radio_on = false; +- cancel_delayed_work_sync(&priv->led_on); ++ cancel_delayed_work(&priv->led_on); + ieee80211_queue_delayed_work(hw, &priv->led_off, 0); + } + } else if (radio_on) { +-- +1.7.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file From ea6941cbff09b581c68234889a5f07a24da41f21 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 17 May 2012 10:30:44 -0400 Subject: [PATCH 389/397] Fix rtlwifi async firmware load race condition (rhbz 822120) --- kernel.spec | 11 ++- ...race-condition-when-firmware-is-cach.patch | 86 +++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch diff --git a/kernel.spec b/kernel.spec index c20f3b9ad..de56a9eb7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -707,6 +707,9 @@ Patch22018: atl1c_net_next_update-3.3.patch #rhbz 795176 Patch22019: rtl818x-fix-sleeping-function-called-from-invalid-context.patch +#rhbz 822120 +Patch22020: rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch + # END OF PATCH DEFINITIONS %endif @@ -1305,6 +1308,9 @@ ApplyPatch atl1c_net_next_update-3.3.patch #rhbz 795176 ApplyPatch rtl818x-fix-sleeping-function-called-from-invalid-context.patch +#rhbz 822120 +ApplyPatch rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch + # END OF PATCH APPLICATIONS %endif @@ -1957,6 +1963,9 @@ fi # and build. %changelog +* Thu May 17 2012 Josh Boyer +- Fix rtlwifi async firmware load race condition (rhbz 822120) + * Wed May 16 2012 Justin M. Forbes 2.6.43.6-3 - fix rtl8187: ->brightness_set can not sleep (rhbz 795176) diff --git a/rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch b/rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch new file mode 100644 index 000000000..431ec00b6 --- /dev/null +++ b/rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch @@ -0,0 +1,86 @@ +From 574e02abaf816b582685805f0c1150ca9f1f18ee Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Fri, 4 May 2012 08:27:43 -0500 +Subject: [PATCH] rtlwifi: fix for race condition when firmware is cached + +In commit b0302ab, the rtlwifi family of drivers was converted to use +asynchronous firmware loading. Unfortumately, the implementation was +racy, and the ieee80211 routines could be started before rtl_init_core() +was called to setup the data. + +This patch fixes the bug noted in https://bugzilla.kernel.org/show_bug.cgi?id=43187. + +Reported-by: Joshua Roys +Tested-by: Neptune Ning +Signed-off-by: Larry Finger +Cc: Stable [3.3] +Signed-off-by: John W. Linville +--- + drivers/net/wireless/rtlwifi/pci.c | 16 ++++++++-------- + drivers/net/wireless/rtlwifi/usb.c | 10 +++++----- + 2 files changed, 13 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c +index b588ca8..03c400e 100644 +--- a/drivers/net/wireless/rtlwifi/pci.c ++++ b/drivers/net/wireless/rtlwifi/pci.c +@@ -1865,14 +1865,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, + /*like read eeprom and so on */ + rtlpriv->cfg->ops->read_eeprom_info(hw); + +- if (rtlpriv->cfg->ops->init_sw_vars(hw)) { +- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +- ("Can't init_sw_vars.\n")); +- goto fail3; +- } +- +- rtlpriv->cfg->ops->init_sw_leds(hw); +- + /*aspm */ + rtl_pci_init_aspm(hw); + +@@ -1892,6 +1884,14 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, + goto fail3; + } + ++ if (rtlpriv->cfg->ops->init_sw_vars(hw)) { ++ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ++ ("Can't init_sw_vars.\n")); ++ goto fail3; ++ } ++ ++ rtlpriv->cfg->ops->init_sw_leds(hw); ++ + err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c +index 049e207..20b53ae 100644 +--- a/drivers/net/wireless/rtlwifi/usb.c ++++ b/drivers/net/wireless/rtlwifi/usb.c +@@ -970,12 +970,6 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, + rtlpriv->cfg->ops->read_chip_version(hw); + /*like read eeprom and so on */ + rtlpriv->cfg->ops->read_eeprom_info(hw); +- if (rtlpriv->cfg->ops->init_sw_vars(hw)) { +- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +- ("Can't init_sw_vars.\n")); +- goto error_out; +- } +- rtlpriv->cfg->ops->init_sw_leds(hw); + err = _rtl_usb_init(hw); + err = _rtl_usb_init_sw(hw); + /* Init mac80211 sw */ +@@ -985,6 +979,12 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, + ("Can't allocate sw for mac80211.\n")); + goto error_out; + } ++ if (rtlpriv->cfg->ops->init_sw_vars(hw)) { ++ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ++ ("Can't init_sw_vars.\n")); ++ goto error_out; ++ } ++ rtlpriv->cfg->ops->init_sw_leds(hw); + + return 0; + error_out: From af7453a80684762d22aaf50e34fffc61cc7d0294 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 18 May 2012 09:19:40 -0400 Subject: [PATCH 390/397] Additional fixes for CVE-2011-4131 (rhbz 822874 822869) --- kernel.spec | 12 +- ...beyond-bounds-copy-while-caching-ACL.patch | 85 +++++++++++++ ...ding-past-buffer-when-calling-GETACL.patch | 120 ++++++++++++++++++ 3 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch create mode 100644 nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch diff --git a/kernel.spec b/kernel.spec index de56a9eb7..938439fdc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -643,6 +643,10 @@ Patch4001: NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch Patch4107: NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch Patch4115: NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch +#rhbz 822874 +Patch4116: nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch +Patch4117: nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch + # patches headed upstream Patch12016: disable-i8042-check-on-apple-mac.patch @@ -1166,6 +1170,9 @@ ApplyPatch NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch ApplyPatch NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch ApplyPatch NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch +ApplyPatch nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch +ApplyPatch nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch + # USB # WMI @@ -1963,6 +1970,9 @@ fi # and build. %changelog +* Fri May 18 2012 Josh Boyer +- Additional fixes for CVE-2011-4131 (rhbz 822874 822869) + * Thu May 17 2012 Josh Boyer - Fix rtlwifi async firmware load race condition (rhbz 822120) diff --git a/nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch b/nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch new file mode 100644 index 000000000..2798b0d1d --- /dev/null +++ b/nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch @@ -0,0 +1,85 @@ +From 5794d21ef4639f0e33440927bb903f9598c21e92 Mon Sep 17 00:00:00 2001 +From: Sachin Prabhu +Date: Tue, 17 Apr 2012 14:36:40 +0100 +Subject: [PATCH] Avoid beyond bounds copy while caching ACL + +When attempting to cache ACLs returned from the server, if the bitmap +size + the ACL size is greater than a PAGE_SIZE but the ACL size itself +is smaller than a PAGE_SIZE, we can read past the buffer page boundary. + +Signed-off-by: Sachin Prabhu +Reported-by: Jian Li +Signed-off-by: Trond Myklebust +--- + fs/nfs/nfs4proc.c | 12 +++++------- + fs/nfs/nfs4xdr.c | 2 +- + 2 files changed, 6 insertions(+), 8 deletions(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index f5f125f..2ce0698 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -3628,16 +3628,16 @@ out: + return ret; + } + +-static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t acl_len) ++static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len) + { + struct nfs4_cached_acl *acl; + +- if (buf && acl_len <= PAGE_SIZE) { ++ if (pages && acl_len <= PAGE_SIZE) { + acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL); + if (acl == NULL) + goto out; + acl->cached = 1; +- memcpy(acl->data, buf, acl_len); ++ _copy_from_pages(acl->data, pages, pgbase, acl_len); + } else { + acl = kmalloc(sizeof(*acl), GFP_KERNEL); + if (acl == NULL) +@@ -3670,7 +3670,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu + struct nfs_getaclres res = { + .acl_len = buflen, + }; +- void *resp_buf; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL], + .rpc_argp = &args, +@@ -3705,7 +3704,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu + * the page we send as a guess */ + if (buf == NULL) + res.acl_flags |= NFS4_ACL_LEN_REQUEST; +- resp_buf = page_address(pages[0]); + + dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n", + __func__, buf, buflen, npages, args.acl_len); +@@ -3716,9 +3714,9 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu + + acl_len = res.acl_len - res.acl_data_offset; + if (acl_len > args.acl_len) +- nfs4_write_cached_acl(inode, NULL, acl_len); ++ nfs4_write_cached_acl(inode, NULL, 0, acl_len); + else +- nfs4_write_cached_acl(inode, resp_buf + res.acl_data_offset, ++ nfs4_write_cached_acl(inode, pages, res.acl_data_offset, + acl_len); + if (buf) { + ret = -ERANGE; +diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c +index 9312dd7..203c096 100644 +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -4940,7 +4940,7 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, + res->acl_len = attrlen; + goto out; + } +- dprintk("NFS: acl reply: attrlen %zu > page_len %u\n", ++ dprintk("NFS: acl reply: attrlen %u > page_len %zu\n", + attrlen, page_len); + return -EINVAL; + } +-- +1.7.7.6 + diff --git a/nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch b/nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch new file mode 100644 index 000000000..7122e3b9a --- /dev/null +++ b/nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch @@ -0,0 +1,120 @@ +From 5a00689930ab975fdd1b37b034475017e460cf2a Mon Sep 17 00:00:00 2001 +From: Sachin Prabhu +Date: Tue, 17 Apr 2012 14:35:39 +0100 +Subject: [PATCH] Avoid reading past buffer when calling GETACL + +Bug noticed in commit +bf118a342f10dafe44b14451a1392c3254629a1f + +When calling GETACL, if the size of the bitmap array, the length +attribute and the acl returned by the server is greater than the +allocated buffer(args.acl_len), we can Oops with a General Protection +fault at _copy_from_pages() when we attempt to read past the pages +allocated. + +This patch allocates an extra PAGE for the bitmap and checks to see that +the bitmap + attribute_length + ACLs don't exceed the buffer space +allocated to it. + +Signed-off-by: Sachin Prabhu +Reported-by: Jian Li +[Trond: Fixed a size_t vs unsigned int printk() warning] +Signed-off-by: Trond Myklebust +--- + fs/nfs/nfs4proc.c | 16 ++++++++++------ + fs/nfs/nfs4xdr.c | 18 +++++++++++------- + 2 files changed, 21 insertions(+), 13 deletions(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index 60d5f4c..f5f125f 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -3684,19 +3684,23 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu + if (npages == 0) + npages = 1; + ++ /* Add an extra page to handle the bitmap returned */ ++ npages++; ++ + for (i = 0; i < npages; i++) { + pages[i] = alloc_page(GFP_KERNEL); + if (!pages[i]) + goto out_free; + } +- if (npages > 1) { +- /* for decoding across pages */ +- res.acl_scratch = alloc_page(GFP_KERNEL); +- if (!res.acl_scratch) +- goto out_free; +- } ++ ++ /* for decoding across pages */ ++ res.acl_scratch = alloc_page(GFP_KERNEL); ++ if (!res.acl_scratch) ++ goto out_free; ++ + args.acl_len = npages * PAGE_SIZE; + args.acl_pgbase = 0; ++ + /* Let decode_getfacl know not to fail if the ACL data is larger than + * the page we send as a guess */ + if (buf == NULL) +diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c +index 77fc5f9..9312dd7 100644 +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -4902,11 +4902,19 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, + bitmap[3] = {0}; + struct kvec *iov = req->rq_rcv_buf.head; + int status; ++ size_t page_len = xdr->buf->page_len; + + res->acl_len = 0; + if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) + goto out; ++ + bm_p = xdr->p; ++ res->acl_data_offset = be32_to_cpup(bm_p) + 2; ++ res->acl_data_offset <<= 2; ++ /* Check if the acl data starts beyond the allocated buffer */ ++ if (res->acl_data_offset > page_len) ++ return -ERANGE; ++ + if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) + goto out; + if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) +@@ -4916,28 +4924,24 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, + return -EIO; + if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { + size_t hdrlen; +- u32 recvd; + + /* The bitmap (xdr len + bitmaps) and the attr xdr len words + * are stored with the acl data to handle the problem of + * variable length bitmaps.*/ + xdr->p = bm_p; +- res->acl_data_offset = be32_to_cpup(bm_p) + 2; +- res->acl_data_offset <<= 2; + + /* We ignore &savep and don't do consistency checks on + * the attr length. Let userspace figure it out.... */ + hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; + attrlen += res->acl_data_offset; +- recvd = req->rq_rcv_buf.len - hdrlen; +- if (attrlen > recvd) { ++ if (attrlen > page_len) { + if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { + /* getxattr interface called with a NULL buf */ + res->acl_len = attrlen; + goto out; + } +- dprintk("NFS: acl reply: attrlen %u > recvd %u\n", +- attrlen, recvd); ++ dprintk("NFS: acl reply: attrlen %zu > page_len %u\n", ++ attrlen, page_len); + return -EINVAL; + } + xdr_read_pages(xdr, attrlen); +-- +1.7.7.6 + From 763835f05493264551de10b2b95cf193b905dbd2 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 22 May 2012 08:49:46 -0500 Subject: [PATCH 391/397] Linux 3.3.7 --- dl2k-Clean-up-rio_ioctl.patch | 120 ------------------ dvbs-fix-zigzag.patch | 15 --- kernel.spec | 22 +--- ...beyond-bounds-copy-while-caching-ACL.patch | 85 ------------- ...ding-past-buffer-when-calling-GETACL.patch | 120 ------------------ sources | 2 +- 6 files changed, 6 insertions(+), 358 deletions(-) delete mode 100644 dl2k-Clean-up-rio_ioctl.patch delete mode 100644 dvbs-fix-zigzag.patch delete mode 100644 nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch delete mode 100644 nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch diff --git a/dl2k-Clean-up-rio_ioctl.patch b/dl2k-Clean-up-rio_ioctl.patch deleted file mode 100644 index 2ef4eed6d..000000000 --- a/dl2k-Clean-up-rio_ioctl.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 1bb57e940e1958e40d51f2078f50c3a96a9b2d75 Mon Sep 17 00:00:00 2001 -From: Jeff Mahoney -Date: Wed, 25 Apr 2012 14:32:09 +0000 -Subject: [PATCH] dl2k: Clean up rio_ioctl - -The dl2k driver's rio_ioctl call has a few issues: -- No permissions checking -- Implements SIOCGMIIREG and SIOCGMIIREG using the SIOCDEVPRIVATE numbers -- Has a few ioctls that may have been used for debugging at one point - but have no place in the kernel proper. - -This patch removes all but the MII ioctls, renumbers them to use the -standard ones, and adds the proper permission check for SIOCSMIIREG. - -We can also get rid of the dl2k-specific struct mii_data in favor of -the generic struct mii_ioctl_data. - -Since we have the phyid on hand, we can add the SIOCGMIIPHY ioctl too. - -Most of the MII code for the driver could probably be converted to use -the generic MII library but I don't have a device to test the results. - -Reported-by: Stephan Mueller -Signed-off-by: Jeff Mahoney -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/dlink/dl2k.c | 52 ++++++------------------------------ - drivers/net/ethernet/dlink/dl2k.h | 7 ----- - 2 files changed, 9 insertions(+), 50 deletions(-) - -diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c -index b2dc2c8..2e09edb 100644 ---- a/drivers/net/ethernet/dlink/dl2k.c -+++ b/drivers/net/ethernet/dlink/dl2k.c -@@ -1259,55 +1259,21 @@ rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) - { - int phy_addr; - struct netdev_private *np = netdev_priv(dev); -- struct mii_data *miidata = (struct mii_data *) &rq->ifr_ifru; -- -- struct netdev_desc *desc; -- int i; -+ struct mii_ioctl_data *miidata = if_mii(rq); - - phy_addr = np->phy_addr; - switch (cmd) { -- case SIOCDEVPRIVATE: -- break; -- -- case SIOCDEVPRIVATE + 1: -- miidata->out_value = mii_read (dev, phy_addr, miidata->reg_num); -+ case SIOCGMIIPHY: -+ miidata->phy_id = phy_addr; - break; -- case SIOCDEVPRIVATE + 2: -- mii_write (dev, phy_addr, miidata->reg_num, miidata->in_value); -+ case SIOCGMIIREG: -+ miidata->val_out = mii_read (dev, phy_addr, miidata->reg_num); - break; -- case SIOCDEVPRIVATE + 3: -- break; -- case SIOCDEVPRIVATE + 4: -- break; -- case SIOCDEVPRIVATE + 5: -- netif_stop_queue (dev); -+ case SIOCSMIIREG: -+ if (!capable(CAP_NET_ADMIN)) -+ return -EPERM; -+ mii_write (dev, phy_addr, miidata->reg_num, miidata->val_in); - break; -- case SIOCDEVPRIVATE + 6: -- netif_wake_queue (dev); -- break; -- case SIOCDEVPRIVATE + 7: -- printk -- ("tx_full=%x cur_tx=%lx old_tx=%lx cur_rx=%lx old_rx=%lx\n", -- netif_queue_stopped(dev), np->cur_tx, np->old_tx, np->cur_rx, -- np->old_rx); -- break; -- case SIOCDEVPRIVATE + 8: -- printk("TX ring:\n"); -- for (i = 0; i < TX_RING_SIZE; i++) { -- desc = &np->tx_ring[i]; -- printk -- ("%02x:cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x", -- i, -- (u32) (np->tx_ring_dma + i * sizeof (*desc)), -- (u32)le64_to_cpu(desc->next_desc), -- (u32)le64_to_cpu(desc->status), -- (u32)(le64_to_cpu(desc->fraginfo) >> 32), -- (u32)le64_to_cpu(desc->fraginfo)); -- printk ("\n"); -- } -- printk ("\n"); -- break; -- - default: - return -EOPNOTSUPP; - } -diff --git a/drivers/net/ethernet/dlink/dl2k.h b/drivers/net/ethernet/dlink/dl2k.h -index ba0adca..30c2da3 100644 ---- a/drivers/net/ethernet/dlink/dl2k.h -+++ b/drivers/net/ethernet/dlink/dl2k.h -@@ -365,13 +365,6 @@ struct ioctl_data { - char *data; - }; - --struct mii_data { -- __u16 reserved; -- __u16 reg_num; -- __u16 in_value; -- __u16 out_value; --}; -- - /* The Rx and Tx buffer descriptors. */ - struct netdev_desc { - __le64 next_desc; --- -1.7.7.6 - diff --git a/dvbs-fix-zigzag.patch b/dvbs-fix-zigzag.patch deleted file mode 100644 index 4bc9daaf4..000000000 --- a/dvbs-fix-zigzag.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c -index 39696c6..de7dc29 100644 ---- a/drivers/media/dvb/dvb-core/dvb_frontend.c -+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c -@@ -1898,6 +1898,10 @@ static int dtv_set_frontend(struct dvb_frontend *fe) - } else { - /* default values */ - switch (c->delivery_system) { -+ case SYS_DVBS: -+ case SYS_DVBS2: -+ case SYS_ISDBS: -+ case SYS_TURBO: - case SYS_DVBC_ANNEX_A: - case SYS_DVBC_ANNEX_C: - fepriv->min_delay = HZ / 20; diff --git a/kernel.spec b/kernel.spec index 938439fdc..c8701d3ac 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 5 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 # Set rpm version accordingly @@ -630,7 +630,6 @@ Patch2802: linux-2.6-silence-acpi-blacklist.patch # media patches Patch2900: add-poll-requested-events.patch Patch2901: drivers-media-update.patch -Patch2902: dvbs-fix-zigzag.patch # fs fixes @@ -643,10 +642,6 @@ Patch4001: NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch Patch4107: NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch Patch4115: NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch -#rhbz 822874 -Patch4116: nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch -Patch4117: nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch - # patches headed upstream Patch12016: disable-i8042-check-on-apple-mac.patch @@ -702,9 +697,6 @@ Patch22007: macvtap-zerocopy-validate-vector-length.patch #rhbz 817298 Patch22013: ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch -#rhbz 818820 -Patch22016: dl2k-Clean-up-rio_ioctl.patch - #rhbz 749276 Patch22018: atl1c_net_next_update-3.3.patch @@ -1170,9 +1162,6 @@ ApplyPatch NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch ApplyPatch NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch ApplyPatch NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch -ApplyPatch nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch -ApplyPatch nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch - # USB # WMI @@ -1257,7 +1246,6 @@ ApplyPatch quite-apm.patch # Media (V4L/DVB/IR) updates/fixes/experimental drivers # apply if non-empty ApplyPatch add-poll-requested-events.patch -ApplyPatch dvbs-fix-zigzag.patch ApplyOptionalPatch drivers-media-update.patch # Patches headed upstream @@ -1306,9 +1294,6 @@ ApplyPatch macvtap-zerocopy-validate-vector-length.patch #rhbz 817298 ApplyPatch ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch -#rhbz 818820 -ApplyPatch dl2k-Clean-up-rio_ioctl.patch - #rhbz 749276 ApplyPatch atl1c_net_next_update-3.3.patch @@ -1970,6 +1955,9 @@ fi # and build. %changelog +* Mon May 21 2012 Justin M. Forbes 3.3.7-1 +- Linux 3.3.7 + * Fri May 18 2012 Josh Boyer - Additional fixes for CVE-2011-4131 (rhbz 822874 822869) diff --git a/nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch b/nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch deleted file mode 100644 index 2798b0d1d..000000000 --- a/nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 5794d21ef4639f0e33440927bb903f9598c21e92 Mon Sep 17 00:00:00 2001 -From: Sachin Prabhu -Date: Tue, 17 Apr 2012 14:36:40 +0100 -Subject: [PATCH] Avoid beyond bounds copy while caching ACL - -When attempting to cache ACLs returned from the server, if the bitmap -size + the ACL size is greater than a PAGE_SIZE but the ACL size itself -is smaller than a PAGE_SIZE, we can read past the buffer page boundary. - -Signed-off-by: Sachin Prabhu -Reported-by: Jian Li -Signed-off-by: Trond Myklebust ---- - fs/nfs/nfs4proc.c | 12 +++++------- - fs/nfs/nfs4xdr.c | 2 +- - 2 files changed, 6 insertions(+), 8 deletions(-) - -diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c -index f5f125f..2ce0698 100644 ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -3628,16 +3628,16 @@ out: - return ret; - } - --static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t acl_len) -+static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len) - { - struct nfs4_cached_acl *acl; - -- if (buf && acl_len <= PAGE_SIZE) { -+ if (pages && acl_len <= PAGE_SIZE) { - acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL); - if (acl == NULL) - goto out; - acl->cached = 1; -- memcpy(acl->data, buf, acl_len); -+ _copy_from_pages(acl->data, pages, pgbase, acl_len); - } else { - acl = kmalloc(sizeof(*acl), GFP_KERNEL); - if (acl == NULL) -@@ -3670,7 +3670,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu - struct nfs_getaclres res = { - .acl_len = buflen, - }; -- void *resp_buf; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL], - .rpc_argp = &args, -@@ -3705,7 +3704,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu - * the page we send as a guess */ - if (buf == NULL) - res.acl_flags |= NFS4_ACL_LEN_REQUEST; -- resp_buf = page_address(pages[0]); - - dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n", - __func__, buf, buflen, npages, args.acl_len); -@@ -3716,9 +3714,9 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu - - acl_len = res.acl_len - res.acl_data_offset; - if (acl_len > args.acl_len) -- nfs4_write_cached_acl(inode, NULL, acl_len); -+ nfs4_write_cached_acl(inode, NULL, 0, acl_len); - else -- nfs4_write_cached_acl(inode, resp_buf + res.acl_data_offset, -+ nfs4_write_cached_acl(inode, pages, res.acl_data_offset, - acl_len); - if (buf) { - ret = -ERANGE; -diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c -index 9312dd7..203c096 100644 ---- a/fs/nfs/nfs4xdr.c -+++ b/fs/nfs/nfs4xdr.c -@@ -4940,7 +4940,7 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, - res->acl_len = attrlen; - goto out; - } -- dprintk("NFS: acl reply: attrlen %zu > page_len %u\n", -+ dprintk("NFS: acl reply: attrlen %u > page_len %zu\n", - attrlen, page_len); - return -EINVAL; - } --- -1.7.7.6 - diff --git a/nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch b/nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch deleted file mode 100644 index 7122e3b9a..000000000 --- a/nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 5a00689930ab975fdd1b37b034475017e460cf2a Mon Sep 17 00:00:00 2001 -From: Sachin Prabhu -Date: Tue, 17 Apr 2012 14:35:39 +0100 -Subject: [PATCH] Avoid reading past buffer when calling GETACL - -Bug noticed in commit -bf118a342f10dafe44b14451a1392c3254629a1f - -When calling GETACL, if the size of the bitmap array, the length -attribute and the acl returned by the server is greater than the -allocated buffer(args.acl_len), we can Oops with a General Protection -fault at _copy_from_pages() when we attempt to read past the pages -allocated. - -This patch allocates an extra PAGE for the bitmap and checks to see that -the bitmap + attribute_length + ACLs don't exceed the buffer space -allocated to it. - -Signed-off-by: Sachin Prabhu -Reported-by: Jian Li -[Trond: Fixed a size_t vs unsigned int printk() warning] -Signed-off-by: Trond Myklebust ---- - fs/nfs/nfs4proc.c | 16 ++++++++++------ - fs/nfs/nfs4xdr.c | 18 +++++++++++------- - 2 files changed, 21 insertions(+), 13 deletions(-) - -diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c -index 60d5f4c..f5f125f 100644 ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -3684,19 +3684,23 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu - if (npages == 0) - npages = 1; - -+ /* Add an extra page to handle the bitmap returned */ -+ npages++; -+ - for (i = 0; i < npages; i++) { - pages[i] = alloc_page(GFP_KERNEL); - if (!pages[i]) - goto out_free; - } -- if (npages > 1) { -- /* for decoding across pages */ -- res.acl_scratch = alloc_page(GFP_KERNEL); -- if (!res.acl_scratch) -- goto out_free; -- } -+ -+ /* for decoding across pages */ -+ res.acl_scratch = alloc_page(GFP_KERNEL); -+ if (!res.acl_scratch) -+ goto out_free; -+ - args.acl_len = npages * PAGE_SIZE; - args.acl_pgbase = 0; -+ - /* Let decode_getfacl know not to fail if the ACL data is larger than - * the page we send as a guess */ - if (buf == NULL) -diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c -index 77fc5f9..9312dd7 100644 ---- a/fs/nfs/nfs4xdr.c -+++ b/fs/nfs/nfs4xdr.c -@@ -4902,11 +4902,19 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, - bitmap[3] = {0}; - struct kvec *iov = req->rq_rcv_buf.head; - int status; -+ size_t page_len = xdr->buf->page_len; - - res->acl_len = 0; - if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) - goto out; -+ - bm_p = xdr->p; -+ res->acl_data_offset = be32_to_cpup(bm_p) + 2; -+ res->acl_data_offset <<= 2; -+ /* Check if the acl data starts beyond the allocated buffer */ -+ if (res->acl_data_offset > page_len) -+ return -ERANGE; -+ - if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) - goto out; - if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) -@@ -4916,28 +4924,24 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, - return -EIO; - if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { - size_t hdrlen; -- u32 recvd; - - /* The bitmap (xdr len + bitmaps) and the attr xdr len words - * are stored with the acl data to handle the problem of - * variable length bitmaps.*/ - xdr->p = bm_p; -- res->acl_data_offset = be32_to_cpup(bm_p) + 2; -- res->acl_data_offset <<= 2; - - /* We ignore &savep and don't do consistency checks on - * the attr length. Let userspace figure it out.... */ - hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; - attrlen += res->acl_data_offset; -- recvd = req->rq_rcv_buf.len - hdrlen; -- if (attrlen > recvd) { -+ if (attrlen > page_len) { - if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { - /* getxattr interface called with a NULL buf */ - res->acl_len = attrlen; - goto out; - } -- dprintk("NFS: acl reply: attrlen %u > recvd %u\n", -- attrlen, recvd); -+ dprintk("NFS: acl reply: attrlen %zu > page_len %u\n", -+ attrlen, page_len); - return -EINVAL; - } - xdr_read_pages(xdr, attrlen); --- -1.7.7.6 - diff --git a/sources b/sources index 755d90dc6..03cb562cf 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz -a7f67e9c491403906e4bb475de194631 patch-3.3.6.xz +622a3b43238559aeb778279969631260 patch-3.3.7.xz From 32cdc846dd9e350d30bbbe26b7fe3a0128395eb1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 24 May 2012 07:43:48 -0400 Subject: [PATCH 392/397] CVE-2012-2372 mm: 32bit PAE pmd walk vs populate SMP race (rhbz 822821 822825) --- kernel.spec | 12 +- ...k-vs-pmd_populate-SMP-race-condition.patch | 272 ++++++++++++++++++ 2 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch diff --git a/kernel.spec b/kernel.spec index c8701d3ac..362b58106 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -706,6 +706,10 @@ Patch22019: rtl818x-fix-sleeping-function-called-from-invalid-context.patch #rhbz 822120 Patch22020: rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch +#rhbz 822825 822821 CVE-2012-2372 +Patch22021: mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch + + # END OF PATCH DEFINITIONS %endif @@ -1303,6 +1307,9 @@ ApplyPatch rtl818x-fix-sleeping-function-called-from-invalid-context.patch #rhbz 822120 ApplyPatch rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch +#rhbz 822825 822821 CVE-2012-2372 +ApplyPatch mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch + # END OF PATCH APPLICATIONS %endif @@ -1955,6 +1962,9 @@ fi # and build. %changelog +* Thu May 24 2012 Josh Boyer +- CVE-2012-2372 mm: 32bit PAE pmd walk vs populate SMP race (rhbz 822821 822825) + * Mon May 21 2012 Justin M. Forbes 3.3.7-1 - Linux 3.3.7 diff --git a/mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch b/mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch new file mode 100644 index 000000000..49ff98a62 --- /dev/null +++ b/mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch @@ -0,0 +1,272 @@ +Path: news.gmane.org!not-for-mail +From: Andrea Arcangeli +Newsgroups: gmane.linux.kernel.mm +Subject: [PATCH] mm: pmd_read_atomic: fix 32bit PAE pmd walk vs pmd_populate SMP race condition +Date: Thu, 24 May 2012 01:39:01 +0200 +Lines: 208 +Approved: news@gmane.org +Message-ID: <1337816341-30743-1-git-send-email-aarcange@redhat.com> +References: <20120518230028.GF32479@redhat.com> +NNTP-Posting-Host: plane.gmane.org +X-Trace: dough.gmane.org 1337816354 18906 80.91.229.3 (23 May 2012 23:39:14 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Wed, 23 May 2012 23:39:14 +0000 (UTC) +Cc: Andrew Morton , Mel Gorman , + Hugh Dickins , Larry Woodman , + Petr Matousek , + Ulrich Obergfell , Rik van Riel +To: linux-mm@kvack.org +Original-X-From: owner-linux-mm@kvack.org Thu May 24 01:39:12 2012 +Return-path: +Envelope-to: glkm-linux-mm-2@m.gmane.org +Original-Received: from kanga.kvack.org ([205.233.56.17]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1SXL94-0002ub-3P + for glkm-linux-mm-2@m.gmane.org; Thu, 24 May 2012 01:39:10 +0200 +Original-Received: by kanga.kvack.org (Postfix) + id 1684A6B0083; Wed, 23 May 2012 19:39:09 -0400 (EDT) +Delivered-To: linux-mm-outgoing@kvack.org +Original-Received: by kanga.kvack.org (Postfix, from userid 40) + id 080DD6B0092; Wed, 23 May 2012 19:39:08 -0400 (EDT) +X-Original-To: int-list-linux-mm@kvack.org +Delivered-To: int-list-linux-mm@kvack.org +Original-Received: by kanga.kvack.org (Postfix, from userid 63042) + id C84046B00E7; Wed, 23 May 2012 19:39:08 -0400 (EDT) +X-Original-To: linux-mm@kvack.org +Delivered-To: linux-mm@kvack.org +Original-Received: from psmtp.com (na3sys010amx119.postini.com [74.125.245.119]) + by kanga.kvack.org (Postfix) with SMTP id 0B2DC6B0083 + for ; Wed, 23 May 2012 19:39:07 -0400 (EDT) +Original-Received: from mx1.redhat.com ([209.132.183.28]) (using TLSv1) by na3sys010amx119.postini.com ([74.125.244.10]) with SMTP; + Wed, 23 May 2012 18:39:08 CDT +Original-Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q4NNd3dP002492 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Wed, 23 May 2012 19:39:03 -0400 +Original-Received: from random.random (ovpn-113-72.phx2.redhat.com [10.3.113.72]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q4NNd1P7012233; + Wed, 23 May 2012 19:39:02 -0400 +In-Reply-To: <20120518230028.GF32479@redhat.com> +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-pstn-neptune: 0/0/0.00/0 +X-pstn-levels: (S:99.90000/99.90000 CV:99.9000 FC:95.5390 LC:95.5390 R:95.9108 P:95.9108 M:97.0282 C:98.6951 ) +X-pstn-dkim: 0 skipped:not-enabled +X-pstn-settings: 3 (1.0000:1.0000) s cv gt3 gt2 gt1 r p m c +X-pstn-addresses: from [db-null] +X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.2 +Original-Sender: owner-linux-mm@kvack.org +Precedence: bulk +X-Loop: owner-majordomo@kvack.org +List-ID: +Xref: news.gmane.org gmane.linux.kernel.mm:78936 +Archived-At: + +When holding the mmap_sem for reading, pmd_offset_map_lock should only +run on a pmd_t that has been read atomically from the pmdp +pointer, otherwise we may read only half of it leading to this crash. + +PID: 11679 TASK: f06e8000 CPU: 3 COMMAND: "do_race_2_panic" + #0 [f06a9dd8] crash_kexec at c049b5ec + #1 [f06a9e2c] oops_end at c083d1c2 + #2 [f06a9e40] no_context at c0433ded + #3 [f06a9e64] bad_area_nosemaphore at c043401a + #4 [f06a9e6c] __do_page_fault at c0434493 + #5 [f06a9eec] do_page_fault at c083eb45 + #6 [f06a9f04] error_code (via page_fault) at c083c5d5 + EAX: 01fb470c EBX: fff35000 ECX: 00000003 EDX: 00000100 EBP: + 00000000 + DS: 007b ESI: 9e201000 ES: 007b EDI: 01fb4700 GS: 00e0 + CS: 0060 EIP: c083bc14 ERR: ffffffff EFLAGS: 00010246 + #7 [f06a9f38] _spin_lock at c083bc14 + #8 [f06a9f44] sys_mincore at c0507b7d + #9 [f06a9fb0] system_call at c083becd + start len + EAX: ffffffda EBX: 9e200000 ECX: 00001000 EDX: 6228537f + DS: 007b ESI: 00000000 ES: 007b EDI: 003d0f00 + SS: 007b ESP: 62285354 EBP: 62285388 GS: 0033 + CS: 0073 EIP: 00291416 ERR: 000000da EFLAGS: 00000286 + +This should be a longstanding bug affecting x86 32bit PAE without +THP. Only archs with 64bit large pmd_t and 32bit unsigned long should +be affected. + +With THP enabled the barrier() in +pmd_none_or_trans_huge_or_clear_bad() would partly hide the bug when +the pmd transition from none to stable, by forcing a re-read of the +*pmd in pmd_offset_map_lock, but when THP is enabled a new set of +problem arises by the fact could then transition freely in any of the +none, pmd_trans_huge or pmd_trans_stable states. So making the barrier +in pmd_none_or_trans_huge_or_clear_bad() unconditional isn't good idea +and it would be a flakey solution. + +This should be fully fixed by introducing a pmd_read_atomic that reads +the pmd in order with THP disabled, or by reading the pmd atomically +with cmpxchg8b with THP enabled. + +Luckily this new race condition only triggers in the places that must +already be covered by pmd_none_or_trans_huge_or_clear_bad() so the fix +is localized there but this bug is not related to THP. + +NOTE: this can trigger on x86 32bit systems with PAE enabled with more +than 4G of ram, otherwise the high part of the pmd will never risk to +be truncated because it would be zero at all times, in turn so hiding +the SMP race. + +This bug was discovered and fully debugged by Ulrich, quote: + +---- +[..] +pmd_none_or_trans_huge_or_clear_bad() loads the content of edx and +eax. + + 496 static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t + *pmd) + 497 { + 498 /* depend on compiler for an atomic pmd read */ + 499 pmd_t pmdval = *pmd; + + // edi = pmd pointer +0xc0507a74 : mov 0x8(%esp),%edi +... + // edx = PTE page table high address +0xc0507a84 : mov 0x4(%edi),%edx +... + // eax = PTE page table low address +0xc0507a8e : mov (%edi),%eax + +[..] + +Please note that the PMD is not read atomically. These are two "mov" +instructions where the high order bits of the PMD entry are fetched +first. Hence, the above machine code is prone to the following race. + +- The PMD entry {high|low} is 0x0000000000000000. + The "mov" at 0xc0507a84 loads 0x00000000 into edx. + +- A page fault (on another CPU) sneaks in between the two "mov" + instructions and instantiates the PMD. + +- The PMD entry {high|low} is now 0x00000003fda38067. + The "mov" at 0xc0507a8e loads 0xfda38067 into eax. +---- + +Reported-by: Ulrich Obergfell +Signed-off-by: Andrea Arcangeli +--- + arch/x86/include/asm/pgtable-3level.h | 50 +++++++++++++++++++++++++++++++++ + include/asm-generic/pgtable.h | 22 +++++++++++++- + 2 files changed, 70 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h +index effff47..43876f1 100644 +--- a/arch/x86/include/asm/pgtable-3level.h ++++ b/arch/x86/include/asm/pgtable-3level.h +@@ -31,6 +31,56 @@ static inline void native_set_pte(pte_t *ptep, pte_t pte) + ptep->pte_low = pte.pte_low; + } + ++#define pmd_read_atomic pmd_read_atomic ++/* ++ * pte_offset_map_lock on 32bit PAE kernels was reading the pmd_t with ++ * a "*pmdp" dereference done by gcc. Problem is, in certain places ++ * where pte_offset_map_lock is called, concurrent page faults are ++ * allowed, if the mmap_sem is hold for reading. An example is mincore ++ * vs page faults vs MADV_DONTNEED. On the page fault side ++ * pmd_populate rightfully does a set_64bit, but if we're reading the ++ * pmd_t with a "*pmdp" on the mincore side, a SMP race can happen ++ * because gcc will not read the 64bit of the pmd atomically. To fix ++ * this all places running pmd_offset_map_lock() while holding the ++ * mmap_sem in read mode, shall read the pmdp pointer using this ++ * function to know if the pmd is null nor not, and in turn to know if ++ * they can run pmd_offset_map_lock or pmd_trans_huge or other pmd ++ * operations. ++ * ++ * Without THP if the mmap_sem is hold for reading, the ++ * pmd can only transition from null to not null while pmd_read_atomic runs. ++ * So there's no need of literally reading it atomically. ++ * ++ * With THP if the mmap_sem is hold for reading, the pmd can become ++ * THP or null or point to a pte (and in turn become "stable") at any ++ * time under pmd_read_atomic, so it's mandatory to read it atomically ++ * with cmpxchg8b. ++ */ ++#ifndef CONFIG_TRANSPARENT_HUGEPAGE ++static inline pmd_t pmd_read_atomic(pmd_t *pmdp) ++{ ++ pmdval_t ret; ++ u32 *tmp = (u32 *)pmdp; ++ ++ ret = (pmdval_t) (*tmp); ++ if (ret) { ++ /* ++ * If the low part is null, we must not read the high part ++ * or we can end up with a partial pmd. ++ */ ++ smp_rmb(); ++ ret |= ((pmdval_t)*(tmp + 1)) << 32; ++ } ++ ++ return (pmd_t) { ret }; ++} ++#else /* CONFIG_TRANSPARENT_HUGEPAGE */ ++static inline pmd_t pmd_read_atomic(pmd_t *pmdp) ++{ ++ return (pmd_t) { atomic64_read((atomic64_t *)pmdp) }; ++} ++#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ ++ + static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) + { + set_64bit((unsigned long long *)(ptep), native_pte_val(pte)); +diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h +index 125c54e..fa596d9 100644 +--- a/include/asm-generic/pgtable.h ++++ b/include/asm-generic/pgtable.h +@@ -446,6 +446,18 @@ static inline int pmd_write(pmd_t pmd) + #endif /* __HAVE_ARCH_PMD_WRITE */ + #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ + ++#ifndef pmd_read_atomic ++static inline pmd_t pmd_read_atomic(pmd_t *pmdp) ++{ ++ /* ++ * Depend on compiler for an atomic pmd read. NOTE: this is ++ * only going to work, if the pmdval_t isn't larger than ++ * an unsigned long. ++ */ ++ return *pmdp; ++} ++#endif ++ + /* + * This function is meant to be used by sites walking pagetables with + * the mmap_sem hold in read mode to protect against MADV_DONTNEED and +@@ -459,11 +471,17 @@ static inline int pmd_write(pmd_t pmd) + * undefined so behaving like if the pmd was none is safe (because it + * can return none anyway). The compiler level barrier() is critically + * important to compute the two checks atomically on the same pmdval. ++ * ++ * For 32bit kernels with a 64bit large pmd_t this automatically takes ++ * care of reading the pmd atomically to avoid SMP race conditions ++ * against pmd_populate() when the mmap_sem is hold for reading by the ++ * caller (a special atomic read not done by "gcc" as in the generic ++ * version above, is also needed when THP is disabled because the page ++ * fault can populate the pmd from under us). + */ + static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) + { +- /* depend on compiler for an atomic pmd read */ +- pmd_t pmdval = *pmd; ++ pmd_t pmdval = pmd_read_atomic(pmd); + /* + * The barrier will stabilize the pmdval in a register or on + * the stack so that it will stop changing under the code. + +-- +To unsubscribe, send a message with 'unsubscribe linux-mm' in +the body to majordomo@kvack.org. For more info on Linux MM, +see: http://www.linux-mm.org/ . +Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ +Don't email: email@kvack.org + From f9d1ef9da630b5ec125d1fcc3106006560a0cd11 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 30 May 2012 07:33:55 -0400 Subject: [PATCH 393/397] CVE-2012-2390 huge pages: memory leak on mmap failure (rhbz 824352 824345) --- hugetlb-fix-resv_map-leak-in-error-path.patch | 108 ++++++++++++++++++ kernel.spec | 10 +- 2 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 hugetlb-fix-resv_map-leak-in-error-path.patch diff --git a/hugetlb-fix-resv_map-leak-in-error-path.patch b/hugetlb-fix-resv_map-leak-in-error-path.patch new file mode 100644 index 000000000..0bfd38c22 --- /dev/null +++ b/hugetlb-fix-resv_map-leak-in-error-path.patch @@ -0,0 +1,108 @@ +From c50ac050811d6485616a193eb0f37bfbd191cc89 Mon Sep 17 00:00:00 2001 +From: Dave Hansen +Date: Tue, 29 May 2012 15:06:46 -0700 +Subject: [PATCH] hugetlb: fix resv_map leak in error path + +When called for anonymous (non-shared) mappings, hugetlb_reserve_pages() +does a resv_map_alloc(). It depends on code in hugetlbfs's +vm_ops->close() to release that allocation. + +However, in the mmap() failure path, we do a plain unmap_region() without +the remove_vma() which actually calls vm_ops->close(). + +This is a decent fix. This leak could get reintroduced if new code (say, +after hugetlb_reserve_pages() in hugetlbfs_file_mmap()) decides to return +an error. But, I think it would have to unroll the reservation anyway. + +Christoph's test case: + + http://marc.info/?l=linux-mm&m=133728900729735 + +This patch applies to 3.4 and later. A version for earlier kernels is at +https://lkml.org/lkml/2012/5/22/418. + +Signed-off-by: Dave Hansen +Acked-by: Mel Gorman +Acked-by: KOSAKI Motohiro +Reported-by: Christoph Lameter +Tested-by: Christoph Lameter +Cc: Andrea Arcangeli +Cc: [2.6.32+] +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + mm/hugetlb.c | 28 ++++++++++++++++++++++------ + 1 files changed, 22 insertions(+), 6 deletions(-) + +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 41a647d..285a81e 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -2157,6 +2157,15 @@ static void hugetlb_vm_op_open(struct vm_area_struct *vma) + kref_get(&reservations->refs); + } + ++static void resv_map_put(struct vm_area_struct *vma) ++{ ++ struct resv_map *reservations = vma_resv_map(vma); ++ ++ if (!reservations) ++ return; ++ kref_put(&reservations->refs, resv_map_release); ++} ++ + static void hugetlb_vm_op_close(struct vm_area_struct *vma) + { + struct hstate *h = hstate_vma(vma); +@@ -2173,7 +2182,7 @@ static void hugetlb_vm_op_close(struct vm_area_struct *vma) + reserve = (end - start) - + region_count(&reservations->regions, start, end); + +- kref_put(&reservations->refs, resv_map_release); ++ resv_map_put(vma); + + if (reserve) { + hugetlb_acct_memory(h, -reserve); +@@ -2991,12 +3000,16 @@ int hugetlb_reserve_pages(struct inode *inode, + set_vma_resv_flags(vma, HPAGE_RESV_OWNER); + } + +- if (chg < 0) +- return chg; ++ if (chg < 0) { ++ ret = chg; ++ goto out_err; ++ } + + /* There must be enough pages in the subpool for the mapping */ +- if (hugepage_subpool_get_pages(spool, chg)) +- return -ENOSPC; ++ if (hugepage_subpool_get_pages(spool, chg)) { ++ ret = -ENOSPC; ++ goto out_err; ++ } + + /* + * Check enough hugepages are available for the reservation. +@@ -3005,7 +3018,7 @@ int hugetlb_reserve_pages(struct inode *inode, + ret = hugetlb_acct_memory(h, chg); + if (ret < 0) { + hugepage_subpool_put_pages(spool, chg); +- return ret; ++ goto out_err; + } + + /* +@@ -3022,6 +3035,9 @@ int hugetlb_reserve_pages(struct inode *inode, + if (!vma || vma->vm_flags & VM_MAYSHARE) + region_add(&inode->i_mapping->private_list, from, to); + return 0; ++out_err: ++ resv_map_put(vma); ++ return ret; + } + + void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed) +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index 362b58106..ac9ac06e9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -709,6 +709,8 @@ Patch22020: rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch #rhbz 822825 822821 CVE-2012-2372 Patch22021: mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch +#rhbz 824352 824345 CVE-2012-2390 +Patch22022: hugetlb-fix-resv_map-leak-in-error-path.patch # END OF PATCH DEFINITIONS @@ -1310,6 +1312,9 @@ ApplyPatch rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch #rhbz 822825 822821 CVE-2012-2372 ApplyPatch mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch +#rhbz 824352 824345 CVE-2012-2390 +ApplyPatch hugetlb-fix-resv_map-leak-in-error-path.patch + # END OF PATCH APPLICATIONS %endif @@ -1962,6 +1967,9 @@ fi # and build. %changelog +* Wed May 30 2012 Josh Boyer +- CVE-2012-2390 huge pages: memory leak on mmap failure (rhbz 824352 824345) + * Thu May 24 2012 Josh Boyer - CVE-2012-2372 mm: 32bit PAE pmd walk vs populate SMP race (rhbz 822821 822825) From 1ab88d2f92b6f2882f8f2fd515027e84e96c5cd4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 30 May 2012 12:01:58 -0400 Subject: [PATCH 394/397] Include upstream commit 4523e145 for CVE-2012-2390 This fixes an oops that was trivially triggered after the original commit went in. Props to Dave J. --- hugetlb-fix-resv_map-leak-in-error-path.patch | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/hugetlb-fix-resv_map-leak-in-error-path.patch b/hugetlb-fix-resv_map-leak-in-error-path.patch index 0bfd38c22..888d5ce70 100644 --- a/hugetlb-fix-resv_map-leak-in-error-path.patch +++ b/hugetlb-fix-resv_map-leak-in-error-path.patch @@ -106,3 +106,71 @@ index 41a647d..285a81e 100644 -- 1.7.7.6 +From 4523e1458566a0e8ecfaff90f380dd23acc44d27 Mon Sep 17 00:00:00 2001 +From: Dave Hansen +Date: Wed, 30 May 2012 07:51:07 -0700 +Subject: [PATCH] mm: fix vma_resv_map() NULL pointer + +hugetlb_reserve_pages() can be used for either normal file-backed +hugetlbfs mappings, or MAP_HUGETLB. In the MAP_HUGETLB, semi-anonymous +mode, there is not a VMA around. The new call to resv_map_put() assumed +that there was, and resulted in a NULL pointer dereference: + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000030 + IP: vma_resv_map+0x9/0x30 + PGD 141453067 PUD 1421e1067 PMD 0 + Oops: 0000 [#1] PREEMPT SMP + ... + Pid: 14006, comm: trinity-child6 Not tainted 3.4.0+ #36 + RIP: vma_resv_map+0x9/0x30 + ... + Process trinity-child6 (pid: 14006, threadinfo ffff8801414e0000, task ffff8801414f26b0) + Call Trace: + resv_map_put+0xe/0x40 + hugetlb_reserve_pages+0xa6/0x1d0 + hugetlb_file_setup+0x102/0x2c0 + newseg+0x115/0x360 + ipcget+0x1ce/0x310 + sys_shmget+0x5a/0x60 + system_call_fastpath+0x16/0x1b + +This was reported by Dave Jones, but was reproducible with the +libhugetlbfs test cases, so shame on me for not running them in the +first place. + +With this, the oops is gone, and the output of libhugetlbfs's +run_tests.py is identical to plain 3.4 again. + +[ Marked for stable, since this was introduced by commit c50ac050811d + ("hugetlb: fix resv_map leak in error path") which was also marked for + stable ] + +Reported-by: Dave Jones +Cc: Mel Gorman +Cc: KOSAKI Motohiro +Cc: Christoph Lameter +Cc: Andrea Arcangeli +Cc: Andrew Morton +Cc: [2.6.32+] +Signed-off-by: Linus Torvalds +--- + mm/hugetlb.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 285a81e..e198831 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -3036,7 +3036,8 @@ int hugetlb_reserve_pages(struct inode *inode, + region_add(&inode->i_mapping->private_list, from, to); + return 0; + out_err: +- resv_map_put(vma); ++ if (vma) ++ resv_map_put(vma); + return ret; + } + +-- +1.7.7.6 + From 8cd38153da9cff9751ce7da1be426d6127641321 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 4 Jun 2012 11:55:32 -0400 Subject: [PATCH 395/397] disable 32bit nx, it seems to be broken --- kernel.spec | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/kernel.spec b/kernel.spec index ac9ac06e9..f201249ce 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1143,9 +1143,12 @@ ApplyPatch taint-vbox.patch # # NX Emulation # -ApplyPatch linux-2.6-32bit-mmap-exec-randomization.patch -ApplyPatch linux-2.6-i386-nx-emulation.patch -ApplyPatch nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch +#ApplyPatch linux-2.6-32bit-mmap-exec-randomization.patch +#ApplyPatch linux-2.6-i386-nx-emulation.patch +#ApplyPatch nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch +#rhbz 804957 CVE-2012-1568 +#ApplyPatch shlib_base_randomize.patch + # # bugfixes to drivers and filesystems @@ -1281,9 +1284,6 @@ ApplyPatch bcma-brcmsmac-compat.patch #rhbz 789644 ApplyPatch mcelog-rcu-splat.patch -#rhbz 804957 CVE-2012-1568 -ApplyPatch shlib_base_randomize.patch - ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch @@ -1967,6 +1967,9 @@ fi # and build. %changelog +* Mon Jun 04 2012 Dave Jones +- Disable 32bit NX emulation. + * Wed May 30 2012 Josh Boyer - CVE-2012-2390 huge pages: memory leak on mmap failure (rhbz 824352 824345) From c23f8db71c1b1fd09145d729185afb8ab4d9f3b6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 4 Jun 2012 15:58:21 -0400 Subject: [PATCH 396/397] Linux v3.3.8 --- kernel.spec | 19 ++-- ...ta-forbid-port-runtime-pm-by-default.patch | 24 ------ ...race-condition-when-firmware-is-cach.patch | 86 ------------------- sources | 2 +- 4 files changed, 6 insertions(+), 125 deletions(-) delete mode 100644 libata-forbid-port-runtime-pm-by-default.patch delete mode 100644 rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch diff --git a/kernel.spec b/kernel.spec index f201249ce..70b50f95f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # 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 @@ -680,9 +680,6 @@ Patch21300: unhandled-irqs-switch-to-polling.patch #rhbz 804957 CVE-2012-1568 Patch21306: shlib_base_randomize.patch -#rhbz 807632 -Patch21385: libata-forbid-port-runtime-pm-by-default.patch - #rhbz 808559 Patch21530: ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch @@ -703,9 +700,6 @@ Patch22018: atl1c_net_next_update-3.3.patch #rhbz 795176 Patch22019: rtl818x-fix-sleeping-function-called-from-invalid-context.patch -#rhbz 822120 -Patch22020: rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch - #rhbz 822825 822821 CVE-2012-2372 Patch22021: mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch @@ -1288,9 +1282,6 @@ ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch -#rhbz 807632 -ApplyPatch libata-forbid-port-runtime-pm-by-default.patch - #rhbz 806295 ApplyPatch disable-hid-battery.patch @@ -1306,9 +1297,6 @@ ApplyPatch atl1c_net_next_update-3.3.patch #rhbz 795176 ApplyPatch rtl818x-fix-sleeping-function-called-from-invalid-context.patch -#rhbz 822120 -ApplyPatch rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch - #rhbz 822825 822821 CVE-2012-2372 ApplyPatch mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch @@ -1967,6 +1955,9 @@ fi # and build. %changelog +* Mon Jun 04 2012 Josh Boyer 2.6.43.8-1 +- Linux v3.3.8 + * Mon Jun 04 2012 Dave Jones - Disable 32bit NX emulation. diff --git a/libata-forbid-port-runtime-pm-by-default.patch b/libata-forbid-port-runtime-pm-by-default.patch deleted file mode 100644 index 0d93a19f5..000000000 --- a/libata-forbid-port-runtime-pm-by-default.patch +++ /dev/null @@ -1,24 +0,0 @@ -From: Lin Ming -Date: Wed, 18 Apr 2012 09:13:41 +0800 -Subject: [PATCH] libata: forbid port runtime pm by default - -Forbid port runtime pm by default because it has known hotplug issue. -User can allow it by, for example - -echo auto > /sys/devices/pci0000:00/0000:00:1f.2/ata2/power/control - -Signed-off-by: Lin Ming ---- - drivers/ata/libata-transport.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - ---- linux-3.3.noarch.orig/drivers/ata/libata-transport.c -+++ linux-3.3.noarch/drivers/ata/libata-transport.c -@@ -294,6 +294,7 @@ int ata_tport_add(struct device *parent, - device_enable_async_suspend(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); -+ pm_runtime_forbid(dev); - - transport_add_device(dev); - transport_configure_device(dev); diff --git a/rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch b/rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch deleted file mode 100644 index 431ec00b6..000000000 --- a/rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 574e02abaf816b582685805f0c1150ca9f1f18ee Mon Sep 17 00:00:00 2001 -From: Larry Finger -Date: Fri, 4 May 2012 08:27:43 -0500 -Subject: [PATCH] rtlwifi: fix for race condition when firmware is cached - -In commit b0302ab, the rtlwifi family of drivers was converted to use -asynchronous firmware loading. Unfortumately, the implementation was -racy, and the ieee80211 routines could be started before rtl_init_core() -was called to setup the data. - -This patch fixes the bug noted in https://bugzilla.kernel.org/show_bug.cgi?id=43187. - -Reported-by: Joshua Roys -Tested-by: Neptune Ning -Signed-off-by: Larry Finger -Cc: Stable [3.3] -Signed-off-by: John W. Linville ---- - drivers/net/wireless/rtlwifi/pci.c | 16 ++++++++-------- - drivers/net/wireless/rtlwifi/usb.c | 10 +++++----- - 2 files changed, 13 insertions(+), 13 deletions(-) - -diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c -index b588ca8..03c400e 100644 ---- a/drivers/net/wireless/rtlwifi/pci.c -+++ b/drivers/net/wireless/rtlwifi/pci.c -@@ -1865,14 +1865,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, - /*like read eeprom and so on */ - rtlpriv->cfg->ops->read_eeprom_info(hw); - -- if (rtlpriv->cfg->ops->init_sw_vars(hw)) { -- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -- ("Can't init_sw_vars.\n")); -- goto fail3; -- } -- -- rtlpriv->cfg->ops->init_sw_leds(hw); -- - /*aspm */ - rtl_pci_init_aspm(hw); - -@@ -1892,6 +1884,14 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, - goto fail3; - } - -+ if (rtlpriv->cfg->ops->init_sw_vars(hw)) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Can't init_sw_vars.\n")); -+ goto fail3; -+ } -+ -+ rtlpriv->cfg->ops->init_sw_leds(hw); -+ - err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c -index 049e207..20b53ae 100644 ---- a/drivers/net/wireless/rtlwifi/usb.c -+++ b/drivers/net/wireless/rtlwifi/usb.c -@@ -970,12 +970,6 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, - rtlpriv->cfg->ops->read_chip_version(hw); - /*like read eeprom and so on */ - rtlpriv->cfg->ops->read_eeprom_info(hw); -- if (rtlpriv->cfg->ops->init_sw_vars(hw)) { -- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -- ("Can't init_sw_vars.\n")); -- goto error_out; -- } -- rtlpriv->cfg->ops->init_sw_leds(hw); - err = _rtl_usb_init(hw); - err = _rtl_usb_init_sw(hw); - /* Init mac80211 sw */ -@@ -985,6 +979,12 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, - ("Can't allocate sw for mac80211.\n")); - goto error_out; - } -+ if (rtlpriv->cfg->ops->init_sw_vars(hw)) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Can't init_sw_vars.\n")); -+ goto error_out; -+ } -+ rtlpriv->cfg->ops->init_sw_leds(hw); - - return 0; - error_out: diff --git a/sources b/sources index 03cb562cf..033ae54df 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz -622a3b43238559aeb778279969631260 patch-3.3.7.xz +e1714b5136a7f4dab1b5d2d7f98e2891 patch-3.3.8.xz From 9638c875dcd2f5a98828839e19defb1e7c6e36b9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 11 Jun 2012 08:39:18 -0400 Subject: [PATCH 397/397] Add patch to fix xen domU 32bit (rhbz 834671) --- kernel.spec | 11 +- ...ead-in-pmd_read_atomic-for-32bit-PAE.patch | 228 ++++++++++++++++++ 2 files changed, 237 insertions(+), 2 deletions(-) create mode 100644 thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch diff --git a/kernel.spec b/kernel.spec index 70b50f95f..c61d484d5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -703,8 +703,11 @@ Patch22019: rtl818x-fix-sleeping-function-called-from-invalid-context.patch #rhbz 822825 822821 CVE-2012-2372 Patch22021: mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch +#rhbz 829016 +Patch22022: thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch + #rhbz 824352 824345 CVE-2012-2390 -Patch22022: hugetlb-fix-resv_map-leak-in-error-path.patch +Patch22023: hugetlb-fix-resv_map-leak-in-error-path.patch # END OF PATCH DEFINITIONS @@ -1299,6 +1302,7 @@ ApplyPatch rtl818x-fix-sleeping-function-called-from-invalid-context.patch #rhbz 822825 822821 CVE-2012-2372 ApplyPatch mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch +ApplyPatch thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch #rhbz 824352 824345 CVE-2012-2390 ApplyPatch hugetlb-fix-resv_map-leak-in-error-path.patch @@ -1955,6 +1959,9 @@ fi # and build. %changelog +* Fri Jun 22 2012 Josh Boyer 2.6.43.8-2 +- Add patch to fix xen domU 32bit (rhbz 834671) + * Mon Jun 04 2012 Josh Boyer 2.6.43.8-1 - Linux v3.3.8 diff --git a/thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch b/thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch new file mode 100644 index 000000000..a91e9bbe4 --- /dev/null +++ b/thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch @@ -0,0 +1,228 @@ + +Delivered-To: jwboyer@gmail.com +Received: by 10.229.175.203 with SMTP id bb11csp66243qcb; + Fri, 8 Jun 2012 15:08:27 -0700 (PDT) +Received: by 10.68.222.133 with SMTP id qm5mr23412736pbc.113.1339193307132; + Fri, 08 Jun 2012 15:08:27 -0700 (PDT) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id ku9si12482578pbc.355.2012.06.08.15.08.24; + Fri, 08 Jun 2012 15:08:25 -0700 (PDT) +Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S964992Ab2FHWIW (ORCPT + 21 others); + Fri, 8 Jun 2012 18:08:22 -0400 +Received: from mail-bk0-f74.google.com ([209.85.214.74]:41783 "EHLO + mail-bk0-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S964922Ab2FHWIV (ORCPT + ); Fri, 8 Jun 2012 18:08:21 -0400 +Received: by bkty5 with SMTP id y5so128736bkt.1 + for ; Fri, 08 Jun 2012 15:08:20 -0700 (PDT) +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=google.com; s=20120113; + h=subject:to:cc:from:date:message-id:x-gm-message-state; + bh=RSdNZSZcXg/enKaYIM+JR4+Bd890ieO+blY9bsk9giI=; + b=NwTZEmRSdqDAiTV/EW91GXpM/yrRd7CNzfPif0JcF0iFgxGAo4lB7W1I05vmrnPcCQ + Va+P6xXLWle2rAVQLsPooKdtb3u2wnNRDEGvBPZl2alje+qzhKGlQcVgnI5+KCM6GaS+ + YWoE+2gv5UFmF6JlelThyecGTyZ0D93K5aVYewSxg0H7KZ6BgvMnB/qJKFdScatv1uDH + g39MFwJzmD+DmNMn149jeUWYOLLTeMZJkymtJCLgxS8eJzQxXA0nes2Wz/pXCBdxXF2z + mft6LyzKtoEUDeTtalgm9zxkT4XJ+6bsAMEXBFgkcyNq0Ic8P79AP0ynlET2L/Ql3ARP + C5Sg== +Received: by 10.14.101.2 with SMTP id a2mr2823176eeg.6.1339193299969; + Fri, 08 Jun 2012 15:08:19 -0700 (PDT) +Received: from hpza10.eem.corp.google.com ([74.125.121.33]) + by gmr-mx.google.com with ESMTPS id d52si7345113eei.1.2012.06.08.15.08.19 + (version=TLSv1/SSLv3 cipher=AES128-SHA); + Fri, 08 Jun 2012 15:08:19 -0700 (PDT) +Received: from akpm.mtv.corp.google.com (akpm.mtv.corp.google.com [172.18.96.75]) + by hpza10.eem.corp.google.com (Postfix) with ESMTP id 9D09620004E; + Fri, 8 Jun 2012 15:08:19 -0700 (PDT) +Received: from localhost.localdomain (localhost [127.0.0.1]) + by akpm.mtv.corp.google.com (Postfix) with ESMTP id D5FACA0329; + Fri, 8 Jun 2012 15:08:18 -0700 (PDT) +Subject: + thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae.patch added to -mm tree +To: mm-commits@vger.kernel.org +Cc: aarcange@redhat.com, hughd@google.com, jbeulich@suse.com, + jrnieder@gmail.com, kosaki.motohiro@gmail.com, lwoodman@redhat.com, + mgorman@suse.de, pmatouse@redhat.com, riel@redhat.com, + stable@vger.kernel.org, uobergfe@redhat.com +From: akpm@linux-foundation.org +Date: Fri, 08 Jun 2012 15:08:18 -0700 +Message-Id: <20120608220818.D5FACA0329@akpm.mtv.corp.google.com> +X-Gm-Message-State: ALoCoQnqC0C+2OVVfC5Yi43jUu5vH03b/RBncPoI4SpE4HFSgaRrM+gM2J8rR6MMoba3nM/OmDAU +Sender: stable-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: stable@vger.kernel.org + + +The patch titled + Subject: thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE +has been added to the -mm tree. Its filename is + thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae.patch + +Before you just go and hit "reply", please: + a) Consider who else should be cc'ed + b) Prefer to cc a suitable mailing list as well + c) Ideally: find the original patch on the mailing list and do a + reply-to-all to that, adding suitable additional cc's + +*** Remember to use Documentation/SubmitChecklist when testing your code *** + +The -mm tree is included into linux-next and is updated +there every 3-4 working days + +------------------------------------------------------ +From: Andrea Arcangeli +Subject: thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE + +In the x86 32bit PAE CONFIG_TRANSPARENT_HUGEPAGE=y case while holding the +mmap_sem for reading, cmpxchg8b cannot be used to read pmd contents under +Xen. + +So instead of dealing only with "consistent" pmdvals in +pmd_none_or_trans_huge_or_clear_bad() (which would be conceptually +simpler) we let pmd_none_or_trans_huge_or_clear_bad() deal with pmdvals +where the low 32bit and high 32bit could be inconsistent (to avoid having +to use cmpxchg8b). + +The only guarantee we get from pmd_read_atomic is that if the low part of +the pmd was found null, the high part will be null too (so the pmd will be +considered unstable). And if the low part of the pmd is found "stable" +later, then it means the whole pmd was read atomically (because after a +pmd is stable, neither MADV_DONTNEED nor page faults can alter it anymore, +and we read the high part after the low part). + +In the 32bit PAE x86 case, it is enough to read the low part of the pmdval +atomically to declare the pmd as "stable" and that's true for THP and no +THP, furthermore in the THP case we also have a barrier() that will +prevent any inconsistent pmdvals to be cached by a later re-read of the +*pmd. + +Signed-off-by: Andrea Arcangeli +Cc: Jonathan Nieder +Cc: Ulrich Obergfell +Cc: Mel Gorman +Cc: Hugh Dickins +Cc: Larry Woodman +Cc: Petr Matousek +Cc: Rik van Riel +Cc: Jan Beulich +Cc: KOSAKI Motohiro +Cc: +Signed-off-by: Andrew Morton +--- + + arch/x86/include/asm/pgtable-3level.h | 30 +++++++++++++----------- + include/asm-generic/pgtable.h | 10 ++++++++ + 2 files changed, 27 insertions(+), 13 deletions(-) + +diff -puN arch/x86/include/asm/pgtable-3level.h~thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae arch/x86/include/asm/pgtable-3level.h +--- a/arch/x86/include/asm/pgtable-3level.h~thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae ++++ a/arch/x86/include/asm/pgtable-3level.h +@@ -47,16 +47,26 @@ static inline void native_set_pte(pte_t + * they can run pmd_offset_map_lock or pmd_trans_huge or other pmd + * operations. + * +- * Without THP if the mmap_sem is hold for reading, the +- * pmd can only transition from null to not null while pmd_read_atomic runs. +- * So there's no need of literally reading it atomically. ++ * Without THP if the mmap_sem is hold for reading, the pmd can only ++ * transition from null to not null while pmd_read_atomic runs. So ++ * we can always return atomic pmd values with this function. + * + * With THP if the mmap_sem is hold for reading, the pmd can become +- * THP or null or point to a pte (and in turn become "stable") at any +- * time under pmd_read_atomic, so it's mandatory to read it atomically +- * with cmpxchg8b. ++ * trans_huge or none or point to a pte (and in turn become "stable") ++ * at any time under pmd_read_atomic. We could read it really ++ * atomically here with a atomic64_read for the THP enabled case (and ++ * it would be a whole lot simpler), but to avoid using cmpxchg8b we ++ * only return an atomic pmdval if the low part of the pmdval is later ++ * found stable (i.e. pointing to a pte). And we're returning a none ++ * pmdval if the low part of the pmd is none. In some cases the high ++ * and low part of the pmdval returned may not be consistent if THP is ++ * enabled (the low part may point to previously mapped hugepage, ++ * while the high part may point to a more recently mapped hugepage), ++ * but pmd_none_or_trans_huge_or_clear_bad() only needs the low part ++ * of the pmd to be read atomically to decide if the pmd is unstable ++ * or not, with the only exception of when the low part of the pmd is ++ * zero in which case we return a none pmd. + */ +-#ifndef CONFIG_TRANSPARENT_HUGEPAGE + static inline pmd_t pmd_read_atomic(pmd_t *pmdp) + { + pmdval_t ret; +@@ -74,12 +84,6 @@ static inline pmd_t pmd_read_atomic(pmd_ + + return (pmd_t) { ret }; + } +-#else /* CONFIG_TRANSPARENT_HUGEPAGE */ +-static inline pmd_t pmd_read_atomic(pmd_t *pmdp) +-{ +- return (pmd_t) { atomic64_read((atomic64_t *)pmdp) }; +-} +-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ + + static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) + { +diff -puN include/asm-generic/pgtable.h~thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae include/asm-generic/pgtable.h +--- a/include/asm-generic/pgtable.h~thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae ++++ a/include/asm-generic/pgtable.h +@@ -484,6 +484,16 @@ static inline int pmd_none_or_trans_huge + /* + * The barrier will stabilize the pmdval in a register or on + * the stack so that it will stop changing under the code. ++ * ++ * When CONFIG_TRANSPARENT_HUGEPAGE=y on x86 32bit PAE, ++ * pmd_read_atomic is allowed to return a not atomic pmdval ++ * (for example pointing to an hugepage that has never been ++ * mapped in the pmd). The below checks will only care about ++ * the low part of the pmd with 32bit PAE x86 anyway, with the ++ * exception of pmd_none(). So the important thing is that if ++ * the low part of the pmd is found null, the high part will ++ * be also null or the pmd_none() check below would be ++ * confused. + */ + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + barrier(); +_ +Subject: Subject: thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE + +Patches currently in -mm which might be from aarcange@redhat.com are + +origin.patch +linux-next.patch +mm-fix-slab-page-_count-corruption-when-using-slub.patch +thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae.patch +hugetlb-rename-max_hstate-to-hugetlb_max_hstate.patch +hugetlbfs-dont-use-err_ptr-with-vm_fault-values.patch +hugetlbfs-add-an-inline-helper-for-finding-hstate-index.patch +hugetlbfs-add-an-inline-helper-for-finding-hstate-index-fix.patch +hugetlb-use-mmu_gather-instead-of-a-temporary-linked-list-for-accumulating-pages.patch +hugetlb-use-mmu_gather-instead-of-a-temporary-linked-list-for-accumulating-pages-fix.patch +hugetlb-use-mmu_gather-instead-of-a-temporary-linked-list-for-accumulating-pages-fix-fix.patch +hugetlb-avoid-taking-i_mmap_mutex-in-unmap_single_vma-for-hugetlb.patch +hugetlb-simplify-migrate_huge_page.patch +hugetlb-simplify-migrate_huge_page-fix.patch +memcg-add-hugetlb-extension.patch +memcg-add-hugetlb-extension-fix.patch +memcg-add-hugetlb-extension-fix-fix.patch +hugetlb-add-charge-uncharge-calls-for-hugetlb-alloc-free.patch +memcg-track-resource-index-in-cftype-private.patch +hugetlbfs-add-memcg-control-files-for-hugetlbfs.patch +hugetlbfs-add-memcg-control-files-for-hugetlbfs-use-scnprintf-instead-of-sprintf.patch +hugetlbfs-add-memcg-control-files-for-hugetlbfs-use-scnprintf-instead-of-sprintf-fix.patch +hugetlbfs-add-a-list-for-tracking-in-use-hugetlb-pages.patch +memcg-move-hugetlb-resource-count-to-parent-cgroup-on-memcg-removal.patch +memcg-move-hugetlb-resource-count-to-parent-cgroup-on-memcg-removal-fix.patch +memcg-move-hugetlb-resource-count-to-parent-cgroup-on-memcg-removal-fix-fix.patch +hugetlb-migrate-memcg-info-from-oldpage-to-new-page-during-migration.patch +memcg-add-memory-controller-documentation-for-hugetlb-management.patch + +-- +To unsubscribe from this list: send the line "unsubscribe stable" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html